diff --git a/.travis.yml b/.travis.yml index 5c6309f817..165a1eff9a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,24 +1,25 @@ language: android jdk: oraclejdk8 +dist: trusty env: matrix: - - ANDROID_TARGET=android-23 ANDROID_ABI=x86 org.gradle.jvmargs=-XX:-OmitStackTraceInFastThrow + - ANDROID_TARGET=android-28 ANDROID_ABI=x86 org.gradle.jvmargs=-XX:-OmitStackTraceInFastThrow android: components: - platform-tools - tools - - build-tools-27.0.2 - - android-23 + - build-tools-28.0.3 + - android-28 - extra-google-m2repository - extra-android-m2repository - extra-google-google_play_services before_install: -- yes | sdkmanager "platforms;android-27" +#- yes | sdkmanager "platforms;android-28" script: # Unit Test - - ./gradlew -Pcoverage testFullDebugUnitTest jacocoTestFullDebugUnitTestReport + - ./gradlew -Pcoverage -PfirebaseDisable testFullDebugUnitTest jacocoTestFullDebugUnitTestReport after_success: - bash <(curl -s https://codecov.io/bash) @@ -31,4 +32,4 @@ cache: directories: - $HOME/.gradle/caches/ - $HOME/.gradle/wrapper/ - - $HOME/.android/build-cache \ No newline at end of file + - $HOME/.android/build-cache diff --git a/README.md b/README.md index d1e1e8a47c..32aef48cd9 100644 --- a/README.md +++ b/README.md @@ -11,4 +11,4 @@ dev: [![codecov](https://codecov.io/gh/MilosKozak/AndroidAPS/branch/dev/graph/badge.svg)](https://codecov.io/gh/MilosKozak/AndroidAPS) -[![Donate via PayPal](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=Y4LHGJJESAVB8) +[![Donate via PayPal](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=Y4LHGJJESAVB8) \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index bb01bf19d8..858fe354fc 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -6,30 +6,39 @@ buildscript { dependencies { classpath 'io.fabric.tools:gradle:1.+' - classpath 'com.dicedmelon.gradle:jacoco-android:0.1.2' + classpath 'com.dicedmelon.gradle:jacoco-android:0.1.4' + classpath 'de.undercouch:gradle-download-task:3.4.3' } } -apply plugin: "com.android.application" -apply plugin: "io.fabric" -apply plugin: "jacoco-android" -apply plugin: 'com.jakewharton.butterknife' +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' +apply plugin: 'com.google.gms.google-services' +apply plugin: 'io.fabric' +apply plugin: 'jacoco-android' +apply plugin: 'de.undercouch.download' + + +jacoco { + toolVersion = "0.8.3" +} ext { - supportLibraryVersion = "27.1.0" + supportLibraryVersion = "28.0.0" ormLiteVersion = "4.46" powermockVersion = "1.7.3" dexmakerVersion = "1.2" - butterknifeVersion = "8.8.1" } repositories { maven { url 'https://maven.fabric.io/public' } jcenter { url "https://jcenter.bintray.com/" } + mavenCentral() } def generateGitBuild = { -> - StringBuilder stringBuilder = new StringBuilder(); + StringBuilder stringBuilder = new StringBuilder() try { def stdout = new ByteArrayOutputStream() exec { @@ -44,40 +53,82 @@ def generateGitBuild = { -> return stringBuilder.toString() } +def generateGitRemote = { -> + StringBuilder stringBuilder = new StringBuilder() + try { + def stdout = new ByteArrayOutputStream() + exec { + commandLine 'git', 'remote', 'get-url', 'origin' + standardOutput = stdout + } + String commitObject = stdout.toString().trim() + stringBuilder.append(commitObject) + } catch (ignored) { + stringBuilder.append('NoGitSystemAvailable') + } + return stringBuilder.toString() +} + def generateDate = { -> - StringBuilder stringBuilder = new StringBuilder(); + StringBuilder stringBuilder = new StringBuilder() stringBuilder.append((new Date()).format('yyyy.MM.dd-HH:mm')) return stringBuilder.toString() } +def isMaster = { -> + return !version.contains('-') +} + +def allCommited = { -> + StringBuilder stringBuilder = new StringBuilder() + try { + def stdout = new ByteArrayOutputStream() + exec { + commandLine 'git', 'status', '-s' + standardOutput = stdout + } + String commitObject = stdout.toString().trim() + stringBuilder.append(commitObject) + } catch (ignored) { + return false // NoGitSystemAvailable + } + return stringBuilder.toString().isEmpty() + +} + tasks.matching { it instanceof Test }.all { testLogging.events = ["failed", "skipped", "started"] testLogging.exceptionFormat = "full" } android { - compileSdkVersion 27 + compileSdkVersion 28 defaultConfig { - minSdkVersion 21 - targetSdkVersion 25 + minSdkVersion 23 + targetSdkVersion 28 multiDexEnabled true versionCode 1500 - version "2.0" + version "2.6-dev" buildConfigField "String", "VERSION", '"' + version + '"' buildConfigField "String", "BUILDVERSION", '"' + generateGitBuild() + '-' + generateDate() + '"' + buildConfigField "String", "REMOTE", '"' + generateGitRemote() + '"' buildConfigField "String", "HEAD", '"' + generateGitBuild() + '"' - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + // if you change minSdkVersion to less than 11, you need to change executeTask for wear ndk { moduleName "BleCommandUtil" } } + kotlinOptions { + jvmTarget = '1.8' + } lintOptions { // TODO remove once wear dependency com.google.android.gms:play-services-wearable:7.3.0 // has been upgraded (requiring significant code changes), which currently fails release // build with a deprecation warning - abortOnError false + // abortOnError false // (disabled entirely to avoid reports on the error, which would still be displayed // and it's easy to overlook that it's ignored) checkReleaseBuilds false @@ -90,7 +141,10 @@ android { proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } debug { - testCoverageEnabled(project.hasProperty('coverage') ? true : false) + testCoverageEnabled(project.hasProperty('coverage')) + } + firebaseDisable { + System.setProperty("disableFirebase", "true") } } productFlavors { @@ -101,17 +155,17 @@ android { resValue "string", "app_name", "AndroidAPS" versionName version manifestPlaceholders = [ - appIcon: "@mipmap/ic_launcher", + appIcon : "@mipmap/ic_launcher", appIconRound: "@mipmap/ic_launcher_round" ] } pumpcontrol { - applicationId "info.nightscout.androidaps" + applicationId "info.nightscout.aapspumpcontrol" dimension "standard" - resValue "string", "app_name", "AndroidAPS" - versionName version + resValue "string", "app_name", "Pumpcontrol" + versionName version + "-pumpcontrol" manifestPlaceholders = [ - appIcon: "@mipmap/blueowl", + appIcon : "@mipmap/ic_pumpcontrol", appIconRound: "@null" ] } @@ -121,7 +175,7 @@ android { resValue "string", "app_name", "NSClient" versionName version + "-nsclient" manifestPlaceholders = [ - appIcon: "@mipmap/yellowowl", + appIcon : "@mipmap/ic_yellowowl", appIconRound: "@null" ] } @@ -131,7 +185,7 @@ android { resValue "string", "app_name", "NSClient2" versionName version + "-nsclient" manifestPlaceholders = [ - appIcon: "@mipmap/yellowowl", + appIcon : "@mipmap/ic_yellowowl", appIconRound: "@null" ] } @@ -142,11 +196,18 @@ android { } testOptions { - unitTests.returnDefaultValues = true - unitTests.includeAndroidResources = true + unitTests { + returnDefaultValues = true + includeAndroidResources = true + + all { + maxParallelForks = 10 + forkEvery = 20 + } + } } - useLibrary "org.apache.http.legacy" + useLibrary "org.apache.http.legacy" } allprojects { @@ -155,48 +216,45 @@ allprojects { flatDir { dirs 'libs' } + maven { url 'https://jitpack.io' } } } -configurations { - libs -} - dependencies { wearApp project(':wear') implementation fileTree(include: ['*.jar'], dir: 'libs') - implementation("com.crashlytics.sdk.android:crashlytics:2.6.7@aar") { + implementation 'com.google.android.gms:play-services-wearable:17.0.0' + implementation 'com.google.firebase:firebase-core:17.2.0' + implementation("com.crashlytics.sdk.android:crashlytics:2.9.9@aar") { transitive = true; } - implementation("com.crashlytics.sdk.android:answers:1.3.12@aar") { - transitive = true; - } - libs "MilosKozak:danars-support-lib:master@zip" - implementation "com.android.support:appcompat-v7:${supportLibraryVersion}" - implementation "com.android.support:support-v13:${supportLibraryVersion}" - implementation "com.android.support:support-v4:${supportLibraryVersion}" - implementation "com.android.support:cardview-v7:${supportLibraryVersion}" - implementation "com.android.support:recyclerview-v7:${supportLibraryVersion}" - implementation "com.android.support:gridlayout-v7:${supportLibraryVersion}" - implementation "com.android.support:design:${supportLibraryVersion}" - implementation "com.android.support:percent:${supportLibraryVersion}" + implementation 'androidx.appcompat:appcompat:1.1.0' + implementation 'androidx.legacy:legacy-support-v13:1.0.0' + implementation 'androidx.legacy:legacy-support-v4:1.0.0' + implementation 'androidx.cardview:cardview:1.0.0' + implementation 'androidx.recyclerview:recyclerview:1.0.0' + implementation 'androidx.gridlayout:gridlayout:1.0.0' + implementation 'com.google.android.material:material:1.0.0' + implementation 'androidx.percentlayout:percentlayout:1.0.0' implementation "com.wdullaer:materialdatetimepicker:2.3.0" - implementation 'com.android.support.constraint:constraint-layout:1.0.2' - implementation "com.squareup:otto:1.3.7" + + implementation "io.reactivex.rxjava2:rxandroid:2.1.1" + implementation "com.j256.ormlite:ormlite-core:${ormLiteVersion}" implementation "com.j256.ormlite:ormlite-android:${ormLiteVersion}" implementation("com.github.tony19:logback-android-classic:1.1.1-6") { exclude group: "com.google.android", module: "android" } - implementation "org.apache.commons:commons-lang3:3.6" - implementation "org.slf4j:slf4j-api:1.7.12" + implementation "org.apache.commons:commons-lang3:3.7" + implementation "org.slf4j:slf4j-api:1.7.21" + // Graphview cannot be upgraded implementation "com.jjoe64:graphview:4.0.1" implementation "com.joanzapata.iconify:android-iconify-fontawesome:2.1.1" - implementation "com.google.android.gms:play-services-wearable:7.5.0" + implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation(name: "android-edittext-validator-v1.3.4-mod", ext: "aar") - implementation(name: "sightparser-release", ext: "aar") + implementation 'com.madgag.spongycastle:core:1.58.0.0' implementation("com.google.android:flexbox:0.3.0") { exclude group: "com.android.support" @@ -205,44 +263,65 @@ dependencies { // excluding org.json which is provided by Android exclude group: "org.json", module: "json" } - implementation "com.google.code.gson:gson:2.7" - implementation "com.google.guava:guava:20.0" + implementation "com.google.code.gson:gson:2.8.5" + implementation "com.google.guava:guava:24.1-jre" implementation "net.danlew:android.joda:2.9.9.1" implementation "uk.com.robust-it:cloning:1.9.9" implementation 'org.mozilla:rhino:1.7.7.2' - implementation "com.jakewharton:butterknife:${butterknifeVersion}" - annotationProcessor "com.jakewharton:butterknife-compiler:${butterknifeVersion}" + implementation 'com.github.DavidProdinger:weekdays-selector:1.1.0' testImplementation "junit:junit:4.12" testImplementation "org.json:json:20140107" - testImplementation "org.mockito:mockito-core:2.7.22" + testImplementation "org.mockito:mockito-core:2.8.47" testImplementation "org.powermock:powermock-api-mockito2:${powermockVersion}" testImplementation "org.powermock:powermock-module-junit4-rule-agent:${powermockVersion}" testImplementation "org.powermock:powermock-module-junit4-rule:${powermockVersion}" testImplementation "org.powermock:powermock-module-junit4:${powermockVersion}" - testImplementation "joda-time:joda-time:2.9.4.2" - testImplementation "com.google.truth:truth:0.39" - testImplementation 'org.robolectric:robolectric:3.8' + testImplementation "joda-time:joda-time:2.9.9" + testImplementation("com.google.truth:truth:0.39") { + exclude group: "com.google.guava", module: "guava" + } testImplementation "org.skyscreamer:jsonassert:1.5.0" + testImplementation "org.hamcrest:hamcrest-all:1.3" +/* + testImplementation("uk.org.lidalia:slf4j-test:1.2.0") { + exclude group: "com.google.guava", module: "guava" + } +*/ - androidTestImplementation "org.mockito:mockito-core:2.7.22" + androidTestImplementation "org.mockito:mockito-core:2.8.47" androidTestImplementation "com.google.dexmaker:dexmaker:${dexmakerVersion}" androidTestImplementation "com.google.dexmaker:dexmaker-mockito:${dexmakerVersion}" + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" + + + // new for tidepool + implementation 'com.squareup.okhttp3:okhttp:3.10.0' + implementation 'com.squareup.okhttp3:logging-interceptor:3.10.0' + implementation "com.squareup.retrofit2:retrofit:2.4.0" + implementation "com.squareup.retrofit2:adapter-rxjava2:2.4.0" + implementation "com.squareup.retrofit2:converter-gson:2.4.0" + } -task unzip(type: Copy) { - def zipPath = configurations.libs.find { it.name.startsWith("danars") } - def zipFile = file(zipPath) - def outputDir = file("${buildDir}/unpacked/dist") - from zipTree(zipFile) +task downloadZipFile(type: Download) { + src 'https://github.com/MilosKozak/danars-support-lib/archive/master.zip' + dest new File(buildDir, 'danars.zip') +} + +task downloadAndUnzipFile(dependsOn: downloadZipFile, type: Copy) { + from zipTree(downloadZipFile.dest) + def outputDir = file("${buildDir}/unpacked/dist") into outputDir } -task copyLibs(dependsOn: unzip, type: Copy) { + +task copyLibs(dependsOn: downloadAndUnzipFile, type: Copy) { def src = file("${buildDir}/unpacked/dist/danars-support-lib-master") def target = file("src/main/jniLibs/") @@ -256,3 +335,12 @@ task full_clean(type: Delete) { clean.dependsOn full_clean preBuild.dependsOn copyLibs + +printf('--------------\n') +printf('isMaster: %s\n', isMaster().toString()) +printf('allCommited: %s\n', allCommited().toString()) +printf('--------------\n') +if (isMaster() && !allCommited()) { + throw new GradleException('There are uncommitted changes or git system is not available. Clone sources again as described in wiki and do not allow gradle update') +} + diff --git a/app/google-services.json b/app/google-services.json new file mode 100644 index 0000000000..42db6f4289 --- /dev/null +++ b/app/google-services.json @@ -0,0 +1,107 @@ +{ + "project_info": { + "project_number": "477603612366", + "firebase_url": "https://androidaps-c34f8.firebaseio.com", + "project_id": "androidaps-c34f8", + "storage_bucket": "androidaps-c34f8.appspot.com" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:477603612366:android:aef229914e3e5448", + "android_client_info": { + "package_name": "info.nightscout.aapspumpcontrol" + } + }, + "oauth_client": [], + "api_key": [ + { + "current_key": "AIzaSyDcZpDRMaGjdhihXp531cVYM6LkEL8KbgM" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "477603612366-a925drvlvs7qn7gt73r585erbqto8c79.apps.googleusercontent.com", + "client_type": 3 + } + ] + } + } + }, + { + "client_info": { + "mobilesdk_app_id": "1:477603612366:android:efc956f55b281623", + "android_client_info": { + "package_name": "info.nightscout.androidaps" + } + }, + "oauth_client": [], + "api_key": [ + { + "current_key": "AIzaSyDcZpDRMaGjdhihXp531cVYM6LkEL8KbgM" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "477603612366-a925drvlvs7qn7gt73r585erbqto8c79.apps.googleusercontent.com", + "client_type": 3 + } + ] + } + } + }, + { + "client_info": { + "mobilesdk_app_id": "1:477603612366:android:b38d6e7351f73cc0", + "android_client_info": { + "package_name": "info.nightscout.nsclient" + } + }, + "oauth_client": [], + "api_key": [ + { + "current_key": "AIzaSyDcZpDRMaGjdhihXp531cVYM6LkEL8KbgM" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "477603612366-a925drvlvs7qn7gt73r585erbqto8c79.apps.googleusercontent.com", + "client_type": 3 + } + ] + } + } + }, + { + "client_info": { + "mobilesdk_app_id": "1:477603612366:android:2dc8cf3acd3332e7", + "android_client_info": { + "package_name": "info.nightscout.nsclient2" + } + }, + "oauth_client": [], + "api_key": [ + { + "current_key": "AIzaSyDcZpDRMaGjdhihXp531cVYM6LkEL8KbgM" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "477603612366-a925drvlvs7qn7gt73r585erbqto8c79.apps.googleusercontent.com", + "client_type": 3 + } + ] + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file diff --git a/app/libs/sightparser-release.aar b/app/libs/sightparser-release.aar deleted file mode 100644 index 1f0c16ee34..0000000000 Binary files a/app/libs/sightparser-release.aar and /dev/null differ diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 163b6651ec..aeeb53475d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -17,10 +17,12 @@ + + - + @@ -31,73 +33,88 @@ android:name=".MainApp" android:allowBackup="true" android:icon="${appIcon}" - android:roundIcon="${appIconRound}" android:label="@string/app_name" + android:roundIcon="${appIconRound}" android:supportsRtl="true" - android:theme="@style/AppTheme.NoActionBar"> + android:theme="@style/AppTheme.Launcher" + android:fullBackupContent="true"> + + - - + + - + - + - + - + + + android:name=".receivers.DataReceiver" + android:enabled="true" + android:exported="true"> - - - - + - + - - - + + + - + + + + + + + + + + + @@ -106,16 +123,8 @@ - - - - - - @@ -132,7 +141,7 @@ @@ -146,30 +155,89 @@ android:name=".services.DataService" android:exported="false" /> + - + + + + + + + + + + + + + + + + + + - + + + + android:label="@string/title_activity_setup_wizard" + android:theme="@style/AppTheme.NoActionBar" /> - - + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + diff --git a/app/src/main/assets/OpenAPSAMA/loggerhelper.js b/app/src/main/assets/OpenAPSAMA/loggerhelper.js index e790f465c8..81c19b5a38 100644 --- a/app/src/main/assets/OpenAPSAMA/loggerhelper.js +++ b/app/src/main/assets/OpenAPSAMA/loggerhelper.js @@ -1,12 +1,33 @@ var console = { }; console.error = function error(){ + var s = ''; for (var i = 0, len = arguments.length; i < len; i++) { - console2.log(arguments[i]); + if (i > 0) s = s + ' '; + if (typeof arguments[i] === 'undefined') { + s = s + 'undefined'; + } else if (typeof arguments[i] === 'object') { + s = s + JSON.stringify(arguments[i]); + } else { + s = s + arguments[i].toString(); + } } + s = s + "\n"; + console2.log(s); }; console.log = function log(){ + var s = ''; for (var i = 0, len = arguments.length; i < len; i++) { - console2.log(arguments[i]); + if (i > 0) s = s + ' '; + if (typeof arguments[i] === 'undefined') { + s = s + 'undefined'; + } else if (typeof arguments[i] === 'object') { + s = s + JSON.stringify(arguments[i]); + } else { + s = s + arguments[i].toString(); + } + //console2.log(arguments[i]); } + s = s + "\n"; + console2.log(s); }; diff --git a/app/src/main/assets/revoked_certs.txt b/app/src/main/assets/revoked_certs.txt new file mode 100644 index 0000000000..59a55d9e42 --- /dev/null +++ b/app/src/main/assets/revoked_certs.txt @@ -0,0 +1,2 @@ +#Demo certificate +51:6D:12:67:4C:27:F4:9B:9F:E5:42:9B:01:B3:98:E4:66:2B:85:B7:A8:DD:70:32:B7:6A:D7:97:9A:0D:97:10 \ No newline at end of file diff --git a/app/src/main/java/com/squareup/otto/LoggingBus.java b/app/src/main/java/com/squareup/otto/LoggingBus.java deleted file mode 100644 index d9758a9a24..0000000000 --- a/app/src/main/java/com/squareup/otto/LoggingBus.java +++ /dev/null @@ -1,96 +0,0 @@ -package com.squareup.otto; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.ConcurrentModificationException; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -import info.nightscout.androidaps.events.Event; -import info.nightscout.androidaps.logging.L; - -/** - * Logs events has they're being posted to and dispatched from the event bus. - *

- * A summary of event-receiver calls that occurred so far is logged - * after 10s (after startup) and then again every 60s. - */ -public class LoggingBus extends Bus { - private static Logger log = LoggerFactory.getLogger(L.EVENTS); - - private static long everyMinute = System.currentTimeMillis() + 10 * 1000; - private Map> event2Receiver = new HashMap<>(); - - public LoggingBus(ThreadEnforcer enforcer) { - super(enforcer); - } - - @Override - public void post(Object event) { - if (event instanceof DeadEvent) { - log.debug("Event has no receiver: " + ((DeadEvent) event).event + ", source: " + ((DeadEvent) event).source); - return; - } - - if (!(event instanceof Event)) { - log.error("Posted event not an event class: " + event.getClass()); - } - - log.debug("<<< " + event); - try { - StackTraceElement caller = new Throwable().getStackTrace()[1]; - String className = caller.getClassName(); - className = className.substring(className.lastIndexOf(".") + 1); - log.debug(" source: " + className + "." + caller.getMethodName() + ":" + caller.getLineNumber()); - } catch (RuntimeException e) { - log.debug(" source: "); - } - - try { - super.post(event); - } catch (IllegalStateException ignored) { - } - } - - @Override - protected void dispatch(Object event, EventHandler wrapper) { - try { - log.debug(">>> " + event); - Field methodField = wrapper.getClass().getDeclaredField("method"); - methodField.setAccessible(true); - Method targetMethod = (Method) methodField.get(wrapper); - String className = targetMethod.getDeclaringClass().getSimpleName(); - String methodName = targetMethod.getName(); - String receiverMethod = className + "." + methodName; - log.debug(" receiver: " + receiverMethod); - - String key = event.getClass().getSimpleName(); - if (!event2Receiver.containsKey(key)) event2Receiver.put(key, new HashSet()); - event2Receiver.get(key).add(receiverMethod); - } catch (ReflectiveOperationException e) { - log.debug(" receiver: "); - } - - try { - if (everyMinute < System.currentTimeMillis()) { - log.debug("***************** Event -> receiver pairings seen so far ****************"); - for (Map.Entry> stringSetEntry : event2Receiver.entrySet()) { - log.debug(" " + stringSetEntry.getKey()); - for (String s : stringSetEntry.getValue()) { - log.debug(" -> " + s); - } - } - log.debug("*************************************************************************"); - everyMinute = System.currentTimeMillis() + 60 * 1000; - } - } catch (ConcurrentModificationException ignored) { - } - - super.dispatch(event, wrapper); - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/Config.java b/app/src/main/java/info/nightscout/androidaps/Config.java index ae0e14c9b6..bb967cdeb6 100644 --- a/app/src/main/java/info/nightscout/androidaps/Config.java +++ b/app/src/main/java/info/nightscout/androidaps/Config.java @@ -12,13 +12,4 @@ public class Config { public static final boolean PUMPCONTROL = BuildConfig.FLAVOR.equals("pumpcontrol"); public static final boolean PUMPDRIVERS = BuildConfig.FLAVOR.equals("full") || BuildConfig.FLAVOR.equals("pumpcontrol"); - - public static final boolean ACTION = !NSCLIENT; - public static final boolean MDI = !NSCLIENT; - public static final boolean OTHERPROFILES = !NSCLIENT; - public static final boolean SAFETY = !NSCLIENT; - - public static final boolean SMSCOMMUNICATORENABLED = !NSCLIENT; - - } diff --git a/app/src/main/java/info/nightscout/androidaps/Constants.java b/app/src/main/java/info/nightscout/androidaps/Constants.java index ffe227dc1b..21a89d8920 100644 --- a/app/src/main/java/info/nightscout/androidaps/Constants.java +++ b/app/src/main/java/info/nightscout/androidaps/Constants.java @@ -1,6 +1,6 @@ package info.nightscout.androidaps; -import info.nightscout.utils.T; +import info.nightscout.androidaps.utils.T; /** * Created by mike on 07.06.2016. @@ -31,11 +31,13 @@ public class Constants { public static final long remoteBolusMinDistance = 15 * 60 * 1000L; // Circadian Percentage Profile - public static final int CPP_MIN_PERCENTAGE = 50; + public static final int CPP_MIN_PERCENTAGE = 30; public static final int CPP_MAX_PERCENTAGE = 200; public static final int CPP_MIN_TIMESHIFT = -6; public static final int CPP_MAX_TIMESHIFT = 23; + public static final double MAX_PROFILE_SWITCH_DURATION = 7 * 24 * 60; // [min] ~ 7 days + //DanaR public static final double dailyLimitWarning = 0.95d; @@ -50,6 +52,11 @@ public class Constants { public static final double defaultHypoTTmgdl = 120d; public static final double defaultHypoTTmmol = 6.5d; + public static final double MIN_TT_MGDL = 72d; + public static final double MAX_TT_MGDL = 180d; + public static final double MIN_TT_MMOL = 4d; + public static final double MAX_TT_MMOL = 10d; + //NSClientInternal public static final int MAX_LOG_LINES = 100; @@ -68,4 +75,7 @@ public class Constants { //SMS Communicator public static final long SMS_CONFIRM_TIMEOUT = T.mins(5).msecs(); + //Storage [MB] + public static final long MINIMUM_FREE_SPACE = 200; + } diff --git a/app/src/main/java/info/nightscout/androidaps/MainActivity.java b/app/src/main/java/info/nightscout/androidaps/MainActivity.java index 844f218803..64c2656086 100644 --- a/app/src/main/java/info/nightscout/androidaps/MainActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/MainActivity.java @@ -6,17 +6,6 @@ import android.content.pm.PackageManager; import android.graphics.Rect; import android.os.Bundle; import android.os.PersistableBundle; -import android.os.PowerManager; -import android.support.annotation.Nullable; -import android.support.design.widget.NavigationView; -import android.support.design.widget.TabLayout; -import android.support.v4.app.ActivityCompat; -import android.support.v4.view.ViewPager; -import android.support.v4.widget.DrawerLayout; -import android.support.v7.app.ActionBarDrawerToggle; -import android.support.v7.app.AlertDialog; -import android.support.v7.app.AppCompatActivity; -import android.support.v7.widget.Toolbar; import android.text.SpannableString; import android.text.method.LinkMovementMethod; import android.text.util.Linkify; @@ -31,53 +20,65 @@ import android.widget.EditText; import android.widget.LinearLayout; import android.widget.TextView; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.ActionBarDrawerToggle; +import androidx.appcompat.app.AlertDialog; +import androidx.appcompat.widget.Toolbar; +import androidx.core.app.ActivityCompat; +import androidx.drawerlayout.widget.DrawerLayout; +import androidx.viewpager.widget.ViewPager; + +import com.google.android.material.navigation.NavigationView; +import com.google.android.material.tabs.TabLayout; import com.joanzapata.iconify.Iconify; import com.joanzapata.iconify.fonts.FontAwesomeModule; -import com.squareup.otto.Subscribe; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.activities.AgreementActivity; import info.nightscout.androidaps.activities.HistoryBrowseActivity; +import info.nightscout.androidaps.activities.NoSplashAppCompatActivity; import info.nightscout.androidaps.activities.PreferencesActivity; import info.nightscout.androidaps.activities.SingleFragmentActivity; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.events.EventAppExit; -import info.nightscout.androidaps.events.EventFeatureRunning; import info.nightscout.androidaps.events.EventPreferenceChange; -import info.nightscout.androidaps.events.EventRefreshGui; +import info.nightscout.androidaps.events.EventRebuildTabs; import info.nightscout.androidaps.interfaces.PluginBase; +import info.nightscout.androidaps.interfaces.PluginType; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSettingsStatus; +import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; +import info.nightscout.androidaps.plugins.constraints.versionChecker.VersionCheckerUtilsKt; +import info.nightscout.androidaps.plugins.general.nsclient.data.NSSettingsStatus; import info.nightscout.androidaps.setupwizard.SetupWizardActivity; import info.nightscout.androidaps.tabs.TabPageAdapter; -import info.nightscout.utils.AndroidPermission; -import info.nightscout.utils.LocaleHelper; -import info.nightscout.utils.OKDialog; -import info.nightscout.utils.PasswordProtection; -import info.nightscout.utils.SP; -import info.nightscout.utils.VersionChecker; +import info.nightscout.androidaps.utils.AndroidPermission; +import info.nightscout.androidaps.utils.FabricPrivacy; +import info.nightscout.androidaps.utils.LocaleHelper; +import info.nightscout.androidaps.utils.OKDialog; +import info.nightscout.androidaps.utils.PasswordProtection; +import info.nightscout.androidaps.utils.SP; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.CompositeDisposable; -public class MainActivity extends AppCompatActivity { +public class MainActivity extends NoSplashAppCompatActivity { private static Logger log = LoggerFactory.getLogger(L.CORE); - - protected PowerManager.WakeLock mWakeLock; + private CompositeDisposable disposable = new CompositeDisposable(); private ActionBarDrawerToggle actionBarDrawerToggle; private MenuItem pluginPreferencesMenuItem; @Override - protected void onCreate(Bundle savedInstanceState) { + public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - if (L.isEnabled(L.CORE)) - log.debug("onCreate"); - Iconify.with(new FontAwesomeModule()); - LocaleHelper.onCreate(this, "en"); + LocaleHelper.INSTANCE.update(getApplicationContext()); setContentView(R.layout.activity_main); setSupportActionBar(findViewById(R.id.toolbar)); @@ -91,14 +92,10 @@ public class MainActivity extends AppCompatActivity { actionBarDrawerToggle.syncState(); // initialize screen wake lock - onEventPreferenceChange(new EventPreferenceChange(R.string.key_keep_screen_on)); + processPreferenceChange(new EventPreferenceChange(R.string.key_keep_screen_on)); doMigrations(); - registerBus(); - setupTabs(); - setupViews(false); - final ViewPager viewPager = findViewById(R.id.pager); viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override @@ -114,7 +111,49 @@ public class MainActivity extends AppCompatActivity { public void onPageScrollStateChanged(int state) { } }); - VersionChecker.check(); + + //Check here if loop plugin is disabled. Else check via constraints + if (!LoopPlugin.getPlugin().isEnabled(PluginType.LOOP)) + VersionCheckerUtilsKt.triggerCheckVersion(); + + FabricPrivacy.setUserStats(); + + setupTabs(); + setupViews(); + + disposable.add(RxBus.INSTANCE + .toObservable(EventRebuildTabs.class) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(event -> { + LocaleHelper.INSTANCE.update(getApplicationContext()); + if (event.getRecreate()) { + recreate(); + } else { + setupTabs(); + setupViews(); + } + setWakeLock(); + }, FabricPrivacy::logException) + ); + disposable.add(RxBus.INSTANCE + .toObservable(EventPreferenceChange.class) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(this::processPreferenceChange, FabricPrivacy::logException) + ); + + if (!SP.getBoolean(R.string.key_setupwizard_processed, false)) { + Intent intent = new Intent(this, SetupWizardActivity.class); + startActivity(intent); + } else { + checkEula(); + } + + AndroidPermission.notifyForStoragePermission(this); + AndroidPermission.notifyForBatteryOptimizationPermission(this); + if (Config.PUMPDRIVERS) { + AndroidPermission.notifyForLocationPermissions(this); + AndroidPermission.notifyForSMSPermissions(this); + } } private void checkPluginPreferences(ViewPager viewPager) { @@ -130,86 +169,29 @@ public class MainActivity extends AppCompatActivity { actionBarDrawerToggle.syncState(); } - @Override - protected void onResume() { - super.onResume(); - - if (L.isEnabled(L.CORE)) - log.debug("onResume"); - - if (!SP.getBoolean(R.string.key_setupwizard_processed, false)) { - Intent intent = new Intent(this, SetupWizardActivity.class); - startActivity(intent); - } else { - checkEula(); - } - - AndroidPermission.notifyForStoragePermission(this); - AndroidPermission.notifyForBatteryOptimizationPermission(this); - if (Config.PUMPDRIVERS) { - AndroidPermission.notifyForLocationPermissions(this); - AndroidPermission.notifyForSMSPermissions(this); - } - - MainApp.bus().post(new EventFeatureRunning(EventFeatureRunning.Feature.MAIN)); - } - @Override public void onDestroy() { - if (L.isEnabled(L.CORE)) - log.debug("onDestroy"); - if (mWakeLock != null) - if (mWakeLock.isHeld()) - mWakeLock.release(); super.onDestroy(); + disposable.clear(); } - @Subscribe - public void onEventPreferenceChange(final EventPreferenceChange ev) { - if (ev.isChanged(R.string.key_keep_screen_on)) { - boolean keepScreenOn = SP.getBoolean(R.string.key_keep_screen_on, false); - final PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); - if (keepScreenOn) { - mWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "AAPS"); - if (!mWakeLock.isHeld()) - mWakeLock.acquire(); - } else { - if (mWakeLock != null && mWakeLock.isHeld()) - mWakeLock.release(); - } - } + private void setWakeLock() { + boolean keepScreenOn = SP.getBoolean(R.string.key_keep_screen_on, false); + if (keepScreenOn) + getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + else + getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); } - @Subscribe - public void onStatusEvent(final EventRefreshGui ev) { - String lang = SP.getString(R.string.key_language, "en"); - LocaleHelper.setLocale(getApplicationContext(), lang); - runOnUiThread(() -> { - if (ev.recreate) { - recreate(); - } else { - try { // activity may be destroyed - setupTabs(); - setupViews(true); - } catch (IllegalStateException e) { - log.error("Unhandled exception", e); - } - } - - boolean keepScreenOn = Config.NSCLIENT && SP.getBoolean(R.string.key_keep_screen_on, false); - if (keepScreenOn) - getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); - else - getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); - }); + public void processPreferenceChange(final EventPreferenceChange ev) { + if (ev.isChanged(R.string.key_keep_screen_on)) + setWakeLock(); } - private void setupViews(boolean switchToLast) { + private void setupViews() { TabPageAdapter pageAdapter = new TabPageAdapter(getSupportFragmentManager(), this); NavigationView navigationView = findViewById(R.id.navigation_view); - navigationView.setNavigationItemSelectedListener(menuItem -> { - return true; - }); + navigationView.setNavigationItemSelectedListener(menuItem -> true); Menu menu = navigationView.getMenu(); menu.clear(); for (PluginBase p : MainApp.getPluginsList()) { @@ -228,8 +210,8 @@ public class MainActivity extends AppCompatActivity { } ViewPager mPager = findViewById(R.id.pager); mPager.setAdapter(pageAdapter); - if (switchToLast) - mPager.setCurrentItem(pageAdapter.getCount() - 1, false); + //if (switchToLast) + // mPager.setCurrentItem(pageAdapter.getCount() - 1, false); checkPluginPreferences(mPager); } @@ -255,15 +237,6 @@ public class MainActivity extends AppCompatActivity { } } - private void registerBus() { - try { - MainApp.bus().unregister(this); - } catch (RuntimeException x) { - // Ignore - } - MainApp.bus().register(this); - } - private void checkEula() { //SP.removeBoolean(R.string.key_i_understand); boolean IUnderstand = SP.getBoolean(R.string.key_i_understand, false); @@ -280,10 +253,10 @@ public class MainActivity extends AppCompatActivity { // guarantee that the unreachable threshold is at least 30 and of type String // Added in 1.57 at 21.01.2018 - Integer unreachable_threshold = SP.getInt(R.string.key_pump_unreachable_threshold, 30); + int unreachable_threshold = SP.getInt(R.string.key_pump_unreachable_threshold, 30); SP.remove(R.string.key_pump_unreachable_threshold); if (unreachable_threshold < 30) unreachable_threshold = 30; - SP.putString(R.string.key_pump_unreachable_threshold, unreachable_threshold.toString()); + SP.putString(R.string.key_pump_unreachable_threshold, Integer.toString(unreachable_threshold)); } @@ -299,19 +272,16 @@ public class MainActivity extends AppCompatActivity { String message = "Target range is changed in current version.\n\nIt's not taken from preferences but from profile.\n\n!!! REVIEW YOUR SETTINGS !!!"; message += "\n\nOld settings: " + oldRange; message += "\nProfile settings: " + newRange; - OKDialog.show(this, "Target range change", message, new Runnable() { - @Override - public void run() { - SP.remove("openapsma_min_bg"); - SP.remove("openapsma_max_bg"); - SP.remove("openapsma_target_bg"); - } + OKDialog.show(this, "Target range change", message, () -> { + SP.remove("openapsma_min_bg"); + SP.remove("openapsma_max_bg"); + SP.remove("openapsma_target_bg"); }); } } @Override - public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (permissions.length != 0) { if (ActivityCompat.checkSelfPermission(this, permissions[0]) == PackageManager.PERMISSION_GRANTED) { @@ -326,7 +296,7 @@ public class MainActivity extends AppCompatActivity { case AndroidPermission.CASE_LOCATION: case AndroidPermission.CASE_SMS: case AndroidPermission.CASE_BATTERY: - case AndroidPermission.CASE_PHONESTATE: + case AndroidPermission.CASE_PHONE_STATE: break; } } @@ -378,10 +348,7 @@ public class MainActivity extends AppCompatActivity { case R.id.nav_about: AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle(MainApp.gs(R.string.app_name) + " " + BuildConfig.VERSION); - if (Config.NSCLIENT) - builder.setIcon(R.mipmap.yellowowl); - else - builder.setIcon(R.mipmap.blueowl); + builder.setIcon(MainApp.getIcon()); String message = "Build: " + BuildConfig.BUILDVERSION + "\n"; message += "Flavor: " + BuildConfig.FLAVOR + BuildConfig.BUILD_TYPE + "\n"; message += MainApp.gs(R.string.configbuilder_nightscoutversion_label) + " " + NSSettingsStatus.getInstance().nightscoutVersionName; @@ -399,7 +366,7 @@ public class MainActivity extends AppCompatActivity { case R.id.nav_exit: log.debug("Exiting"); MainApp.instance().stopKeepAliveService(); - MainApp.bus().post(new EventAppExit()); + RxBus.INSTANCE.send(new EventAppExit()); MainApp.closeDbHelper(); finish(); System.runFinalization(); diff --git a/app/src/main/java/info/nightscout/androidaps/MainApp.java b/app/src/main/java/info/nightscout/androidaps/MainApp.java index 327e451225..379afabddf 100644 --- a/app/src/main/java/info/nightscout/androidaps/MainApp.java +++ b/app/src/main/java/info/nightscout/androidaps/MainApp.java @@ -1,19 +1,17 @@ package info.nightscout.androidaps; import android.app.Application; +import android.content.BroadcastReceiver; import android.content.IntentFilter; import android.content.res.Resources; import android.os.SystemClock; -import android.support.annotation.Nullable; -import android.support.annotation.PluralsRes; -import android.support.v4.content.LocalBroadcastManager; + +import androidx.annotation.PluralsRes; +import androidx.localbroadcastmanager.content.LocalBroadcastManager; import com.crashlytics.android.Crashlytics; -import com.crashlytics.android.answers.Answers; +import com.google.firebase.analytics.FirebaseAnalytics; import com.j256.ormlite.android.apptools.OpenHelperManager; -import com.squareup.otto.Bus; -import com.squareup.otto.LoggingBus; -import com.squareup.otto.ThreadEnforcer; import net.danlew.android.joda.JodaTimeAndroid; @@ -29,69 +27,82 @@ import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginType; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.Actions.ActionsFragment; -import info.nightscout.androidaps.plugins.Careportal.CareportalPlugin; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.ConstraintsObjectives.ObjectivesPlugin; -import info.nightscout.androidaps.plugins.ConstraintsSafety.SafetyPlugin; -import info.nightscout.androidaps.plugins.Food.FoodPlugin; -import info.nightscout.androidaps.plugins.Insulin.InsulinOrefFreePeakPlugin; -import info.nightscout.androidaps.plugins.Insulin.InsulinOrefRapidActingPlugin; -import info.nightscout.androidaps.plugins.Insulin.InsulinOrefUltraRapidActingPlugin; -import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin; -import info.nightscout.androidaps.plugins.Maintenance.MaintenancePlugin; -import info.nightscout.androidaps.plugins.Loop.LoopPlugin; -import info.nightscout.androidaps.plugins.NSClientInternal.NSClientPlugin; -import info.nightscout.androidaps.plugins.NSClientInternal.NSUpload; -import info.nightscout.androidaps.plugins.NSClientInternal.receivers.AckAlarmReceiver; -import info.nightscout.androidaps.plugins.NSClientInternal.receivers.DBAccessReceiver; -import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin; -import info.nightscout.androidaps.plugins.OpenAPSMA.OpenAPSMAPlugin; -import info.nightscout.androidaps.plugins.OpenAPSSMB.OpenAPSSMBPlugin; -import info.nightscout.androidaps.plugins.Overview.OverviewPlugin; -import info.nightscout.androidaps.plugins.Persistentnotification.PersistentNotificationPlugin; -import info.nightscout.androidaps.plugins.ProfileLocal.LocalProfilePlugin; -import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin; -import info.nightscout.androidaps.plugins.ProfileSimple.SimpleProfilePlugin; -import info.nightscout.androidaps.plugins.PumpCombo.ComboPlugin; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; -import info.nightscout.androidaps.plugins.PumpDanaRS.DanaRSPlugin; -import info.nightscout.androidaps.plugins.PumpDanaRv2.DanaRv2Plugin; -import info.nightscout.androidaps.plugins.PumpInsight.InsightPlugin; -import info.nightscout.androidaps.plugins.PumpMDI.MDIPlugin; -import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin; -import info.nightscout.androidaps.plugins.Sensitivity.SensitivityAAPSPlugin; -import info.nightscout.androidaps.plugins.Sensitivity.SensitivityOref0Plugin; -import info.nightscout.androidaps.plugins.Sensitivity.SensitivityOref1Plugin; -import info.nightscout.androidaps.plugins.Sensitivity.SensitivityWeightedAveragePlugin; -import info.nightscout.androidaps.plugins.SmsCommunicator.SmsCommunicatorPlugin; -import info.nightscout.androidaps.plugins.Source.SourceDexcomG5Plugin; -import info.nightscout.androidaps.plugins.Source.SourceGlimpPlugin; -import info.nightscout.androidaps.plugins.Source.SourceMM640gPlugin; -import info.nightscout.androidaps.plugins.Source.SourceNSClientPlugin; -import info.nightscout.androidaps.plugins.Source.SourcePoctechPlugin; -import info.nightscout.androidaps.plugins.Source.SourceXdripPlugin; -import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; -import info.nightscout.androidaps.plugins.Wear.WearPlugin; -import info.nightscout.androidaps.plugins.XDripStatusline.StatuslinePlugin; +import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin; +import info.nightscout.androidaps.plugins.aps.openAPSAMA.OpenAPSAMAPlugin; +import info.nightscout.androidaps.plugins.aps.openAPSMA.OpenAPSMAPlugin; +import info.nightscout.androidaps.plugins.aps.openAPSSMB.OpenAPSSMBPlugin; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.constraints.dstHelper.DstHelperPlugin; +import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin; +import info.nightscout.androidaps.plugins.constraints.safety.SafetyPlugin; +import info.nightscout.androidaps.plugins.constraints.signatureVerifier.SignatureVerifierPlugin; +import info.nightscout.androidaps.plugins.constraints.storage.StorageConstraintPlugin; +import info.nightscout.androidaps.plugins.constraints.versionChecker.VersionCheckerPlugin; +import info.nightscout.androidaps.plugins.general.actions.ActionsPlugin; +import info.nightscout.androidaps.plugins.general.automation.AutomationPlugin; +import info.nightscout.androidaps.plugins.general.careportal.CareportalPlugin; +import info.nightscout.androidaps.plugins.general.food.FoodPlugin; +import info.nightscout.androidaps.plugins.general.maintenance.LoggerUtils; +import info.nightscout.androidaps.plugins.general.maintenance.MaintenancePlugin; +import info.nightscout.androidaps.plugins.general.nsclient.NSClientPlugin; +import info.nightscout.androidaps.plugins.general.nsclient.NSUpload; +import info.nightscout.androidaps.plugins.general.nsclient.receivers.AckAlarmReceiver; +import info.nightscout.androidaps.plugins.general.nsclient.receivers.DBAccessReceiver; +import info.nightscout.androidaps.plugins.general.overview.OverviewPlugin; +import info.nightscout.androidaps.plugins.general.persistentNotification.PersistentNotificationPlugin; +import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin; +import info.nightscout.androidaps.plugins.general.wear.WearPlugin; +import info.nightscout.androidaps.plugins.general.xdripStatusline.StatuslinePlugin; +import info.nightscout.androidaps.plugins.insulin.InsulinOrefFreePeakPlugin; +import info.nightscout.androidaps.plugins.insulin.InsulinOrefRapidActingPlugin; +import info.nightscout.androidaps.plugins.insulin.InsulinOrefUltraRapidActingPlugin; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin; +import info.nightscout.androidaps.plugins.profile.local.LocalProfilePlugin; +import info.nightscout.androidaps.plugins.profile.ns.NSProfilePlugin; +import info.nightscout.androidaps.plugins.profile.simple.SimpleProfilePlugin; +import info.nightscout.androidaps.plugins.pump.combo.ComboPlugin; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPlugin; +import info.nightscout.androidaps.plugins.pump.danaRKorean.DanaRKoreanPlugin; +import info.nightscout.androidaps.plugins.pump.danaRS.DanaRSPlugin; +import info.nightscout.androidaps.plugins.pump.danaRv2.DanaRv2Plugin; +import info.nightscout.androidaps.plugins.pump.insight.LocalInsightPlugin; +import info.nightscout.androidaps.plugins.pump.mdi.MDIPlugin; +import info.nightscout.androidaps.plugins.pump.medtronic.MedtronicPumpPlugin; +import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin; +import info.nightscout.androidaps.plugins.sensitivity.SensitivityAAPSPlugin; +import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref0Plugin; +import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin; +import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAveragePlugin; +import info.nightscout.androidaps.plugins.source.SourceDexcomPlugin; +import info.nightscout.androidaps.plugins.source.SourceEversensePlugin; +import info.nightscout.androidaps.plugins.source.SourceGlimpPlugin; +import info.nightscout.androidaps.plugins.source.SourceMM640gPlugin; +import info.nightscout.androidaps.plugins.source.SourceNSClientPlugin; +import info.nightscout.androidaps.plugins.source.SourcePoctechPlugin; +import info.nightscout.androidaps.plugins.source.SourceTomatoPlugin; +import info.nightscout.androidaps.plugins.source.SourceXdripPlugin; +import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; import info.nightscout.androidaps.receivers.DataReceiver; import info.nightscout.androidaps.receivers.KeepAliveReceiver; import info.nightscout.androidaps.receivers.NSAlarmReceiver; +import info.nightscout.androidaps.receivers.TimeDateOrTZChangeReceiver; import info.nightscout.androidaps.services.Intents; -import info.nightscout.utils.FabricPrivacy; -import info.nightscout.androidaps.plugins.Maintenance.LoggerUtils; +import info.nightscout.androidaps.utils.FabricPrivacy; +import info.nightscout.androidaps.utils.LocaleHelper; import io.fabric.sdk.android.Fabric; +import static info.nightscout.androidaps.plugins.constraints.versionChecker.VersionCheckerUtilsKt.triggerCheckVersion; + public class MainApp extends Application { private static Logger log = LoggerFactory.getLogger(L.CORE); private static KeepAliveReceiver keepAliveReceiver; - private static Bus sBus; private static MainApp sInstance; public static Resources sResources; + private static FirebaseAnalytics mFirebaseAnalytics; + private static DatabaseHelper sDatabaseHelper = null; private static ConstraintChecker sConstraintsChecker = null; @@ -102,6 +113,8 @@ public class MainApp extends Application { private static AckAlarmReceiver ackAlarmReciever = new AckAlarmReceiver(); private static DBAccessReceiver dbAccessReciever = new DBAccessReceiver(); private LocalBroadcastManager lbm; + BroadcastReceiver btReceiver; + TimeDateOrTZChangeReceiver timeDateOrTZChangeReceiver; public static boolean devBranch; public static boolean engineeringMode; @@ -112,40 +125,47 @@ public class MainApp extends Application { log.debug("onCreate"); sInstance = this; sResources = getResources(); - sConstraintsChecker = new ConstraintChecker(this); + LocaleHelper.INSTANCE.update(this); + sConstraintsChecker = new ConstraintChecker(); sDatabaseHelper = OpenHelperManager.getHelper(sInstance, DatabaseHelper.class); + Thread.setDefaultUncaughtExceptionHandler((thread, ex) -> log.error("Uncaught exception crashing app", ex)); + try { if (FabricPrivacy.fabricEnabled()) { Fabric.with(this, new Crashlytics()); - Fabric.with(this, new Answers()); - Crashlytics.setString("BUILDVERSION", BuildConfig.BUILDVERSION); } } catch (Exception e) { log.error("Error with Fabric init! " + e); } + mFirebaseAnalytics = FirebaseAnalytics.getInstance(this); + mFirebaseAnalytics.setAnalyticsCollectionEnabled(!Boolean.getBoolean("disableFirebase")); + JodaTimeAndroid.init(this); log.info("Version: " + BuildConfig.VERSION_NAME); log.info("BuildVersion: " + BuildConfig.BUILDVERSION); + log.info("Remote: " + BuildConfig.REMOTE); String extFilesDir = LoggerUtils.getLogDirectory(); File engineeringModeSemaphore = new File(extFilesDir, "engineering_mode"); engineeringMode = engineeringModeSemaphore.exists() && engineeringModeSemaphore.isFile(); - devBranch = BuildConfig.VERSION.contains("dev"); - - sBus = L.isEnabled(L.EVENTS) && devBranch ? new LoggingBus(ThreadEnforcer.ANY) : new Bus(ThreadEnforcer.ANY); + devBranch = BuildConfig.VERSION.contains("-") || BuildConfig.VERSION.matches(".*[a-zA-Z]+.*"); registerLocalBroadcastReceiver(); + //trigger here to see the new version on app start after an update + triggerCheckVersion(); + //setBTReceiver(); + if (pluginsList == null) { pluginsList = new ArrayList<>(); // Register all tabs in app here - pluginsList.add(OverviewPlugin.getPlugin()); + pluginsList.add(OverviewPlugin.INSTANCE); pluginsList.add(IobCobCalculatorPlugin.getPlugin()); - if (Config.ACTION) pluginsList.add(ActionsFragment.getPlugin()); + if (!Config.NSCLIENT) pluginsList.add(ActionsPlugin.INSTANCE); pluginsList.add(InsulinOrefRapidActingPlugin.getPlugin()); pluginsList.add(InsulinOrefUltraRapidActingPlugin.getPlugin()); pluginsList.add(InsulinOrefFreePeakPlugin.getPlugin()); @@ -157,39 +177,49 @@ public class MainApp extends Application { if (Config.PUMPDRIVERS) pluginsList.add(DanaRKoreanPlugin.getPlugin()); if (Config.PUMPDRIVERS) pluginsList.add(DanaRv2Plugin.getPlugin()); if (Config.PUMPDRIVERS) pluginsList.add(DanaRSPlugin.getPlugin()); - pluginsList.add(CareportalPlugin.getPlugin()); - if (Config.PUMPDRIVERS && engineeringMode) - pluginsList.add(InsightPlugin.getPlugin()); // <-- Enable Insight plugin here + if (Config.PUMPDRIVERS) pluginsList.add(LocalInsightPlugin.getPlugin()); if (Config.PUMPDRIVERS) pluginsList.add(ComboPlugin.getPlugin()); - if (Config.MDI) pluginsList.add(MDIPlugin.getPlugin()); + if (Config.PUMPDRIVERS) pluginsList.add(MedtronicPumpPlugin.getPlugin()); + if (!Config.NSCLIENT) pluginsList.add(MDIPlugin.getPlugin()); pluginsList.add(VirtualPumpPlugin.getPlugin()); + pluginsList.add(CareportalPlugin.getPlugin()); if (Config.APS) pluginsList.add(LoopPlugin.getPlugin()); if (Config.APS) pluginsList.add(OpenAPSMAPlugin.getPlugin()); if (Config.APS) pluginsList.add(OpenAPSAMAPlugin.getPlugin()); if (Config.APS) pluginsList.add(OpenAPSSMBPlugin.getPlugin()); pluginsList.add(NSProfilePlugin.getPlugin()); - if (Config.OTHERPROFILES) pluginsList.add(SimpleProfilePlugin.getPlugin()); - if (Config.OTHERPROFILES) pluginsList.add(LocalProfilePlugin.getPlugin()); + if (!Config.NSCLIENT) pluginsList.add(SimpleProfilePlugin.getPlugin()); + if (!Config.NSCLIENT) pluginsList.add(LocalProfilePlugin.getPlugin()); pluginsList.add(TreatmentsPlugin.getPlugin()); - if (Config.SAFETY) pluginsList.add(SafetyPlugin.getPlugin()); - if (Config.APS) pluginsList.add(ObjectivesPlugin.getPlugin()); + if (!Config.NSCLIENT) pluginsList.add(SafetyPlugin.getPlugin()); + if (!Config.NSCLIENT) pluginsList.add(VersionCheckerPlugin.INSTANCE); + if (Config.APS) pluginsList.add(StorageConstraintPlugin.getPlugin()); + if (Config.APS) pluginsList.add(SignatureVerifierPlugin.getPlugin()); + if (Config.APS) pluginsList.add(ObjectivesPlugin.INSTANCE); pluginsList.add(SourceXdripPlugin.getPlugin()); pluginsList.add(SourceNSClientPlugin.getPlugin()); pluginsList.add(SourceMM640gPlugin.getPlugin()); pluginsList.add(SourceGlimpPlugin.getPlugin()); - pluginsList.add(SourceDexcomG5Plugin.getPlugin()); + pluginsList.add(SourceDexcomPlugin.INSTANCE); pluginsList.add(SourcePoctechPlugin.getPlugin()); - if (Config.SMSCOMMUNICATORENABLED) pluginsList.add(SmsCommunicatorPlugin.getPlugin()); + pluginsList.add(SourceTomatoPlugin.getPlugin()); + pluginsList.add(SourceEversensePlugin.getPlugin()); + if (!Config.NSCLIENT) pluginsList.add(SmsCommunicatorPlugin.getPlugin()); pluginsList.add(FoodPlugin.getPlugin()); pluginsList.add(WearPlugin.initPlugin(this)); pluginsList.add(StatuslinePlugin.initPlugin(this)); pluginsList.add(PersistentNotificationPlugin.getPlugin()); pluginsList.add(NSClientPlugin.getPlugin()); +// if (engineeringMode) pluginsList.add(TidepoolPlugin.INSTANCE); pluginsList.add(MaintenancePlugin.initPlugin(this)); + pluginsList.add(AutomationPlugin.INSTANCE); pluginsList.add(ConfigBuilderPlugin.getPlugin()); + pluginsList.add(DstHelperPlugin.getPlugin()); + + ConfigBuilderPlugin.getPlugin().initialize(); } @@ -231,6 +261,10 @@ public class MainApp extends Application { //register dbaccess lbm.registerReceiver(dbAccessReciever, new IntentFilter(Intents.ACTION_DATABASE)); + + this.timeDateOrTZChangeReceiver = new TimeDateOrTZChangeReceiver(); + this.timeDateOrTZChangeReceiver.registerBroadcasts(this); + } private void startKeepAliveService() { @@ -245,26 +279,6 @@ public class MainApp extends Application { KeepAliveReceiver.cancelAlarm(this); } - public static void subscribe(Object subscriber) { - try { - bus().register(subscriber); - } catch (IllegalArgumentException e) { - // already registered - } - } - - public static void unsubscribe(Object subscriber) { - try { - bus().unregister(subscriber); - } catch (IllegalArgumentException e) { - // already unregistered - } - } - - public static Bus bus() { - return sBus; - } - public static String gs(int id) { return sResources.getString(id); } @@ -296,6 +310,10 @@ public class MainApp extends Application { } } + public static FirebaseAnalytics getFirebaseAnalytics() { + return mFirebaseAnalytics; + } + public static ConstraintChecker getConstraintChecker() { return sConstraintsChecker; } @@ -362,19 +380,6 @@ public class MainApp extends Application { return newList; } - @Nullable - public static T getSpecificPlugin(Class pluginClass) { - if (pluginsList != null) { - for (PluginBase p : pluginsList) { - if (pluginClass.isAssignableFrom(p.getClass())) - return (T) p; - } - } else { - log.error("pluginsList=null"); - } - return null; - } - public static boolean isEngineeringModeOrRelease() { if (!Config.APS) return true; @@ -385,6 +390,24 @@ public class MainApp extends Application { return devBranch; } + public static int getIcon() { + if (Config.NSCLIENT) + return R.mipmap.ic_yellowowl; + else if (Config.PUMPCONTROL) + return R.mipmap.ic_pumpcontrol; + else + return R.mipmap.ic_launcher; + } + + public static int getNotificationIcon() { + if (Config.NSCLIENT) + return R.drawable.ic_notif_nsclient; + else if (Config.PUMPCONTROL) + return R.drawable.ic_notif_pumpcontrol; + else + return R.drawable.ic_notif_aaps; + } + @Override public void onTerminate() { if (L.isEnabled(L.CORE)) @@ -394,5 +417,19 @@ public class MainApp extends Application { sDatabaseHelper.close(); sDatabaseHelper = null; } + + if (btReceiver != null) { + unregisterReceiver(btReceiver); + } + + if (timeDateOrTZChangeReceiver != null) { + unregisterReceiver(timeDateOrTZChangeReceiver); + } + + } + + public static int dpToPx(int dp) { + float scale = sResources.getDisplayMetrics().density; + return (int) (dp * scale + 0.5f); } } diff --git a/app/src/main/java/info/nightscout/androidaps/activities/AgreementActivity.java b/app/src/main/java/info/nightscout/androidaps/activities/AgreementActivity.java index 582b10d57d..d3792bbad5 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/AgreementActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/activities/AgreementActivity.java @@ -2,24 +2,22 @@ package info.nightscout.androidaps.activities; import android.app.Activity; import android.content.Intent; -import android.content.SharedPreferences; import android.os.Bundle; -import android.preference.PreferenceManager; import android.view.View; import android.widget.Button; import android.widget.CheckBox; import info.nightscout.androidaps.MainActivity; import info.nightscout.androidaps.R; -import info.nightscout.utils.SP; +import info.nightscout.androidaps.utils.SP; -public class AgreementActivity extends Activity { +public class AgreementActivity extends NoSplashActivity { boolean IUnderstand; CheckBox agreeCheckBox; Button saveButton; @Override - protected void onCreate(Bundle savedInstanceState) { + public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_agreement); IUnderstand = SP.getBoolean(R.string.key_i_understand, false); diff --git a/app/src/main/java/info/nightscout/androidaps/activities/HistoryBrowseActivity.java b/app/src/main/java/info/nightscout/androidaps/activities/HistoryBrowseActivity.java index 7303eb9d97..79f3fbf4d4 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/HistoryBrowseActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/activities/HistoryBrowseActivity.java @@ -2,9 +2,6 @@ package info.nightscout.androidaps.activities; import android.os.Bundle; import android.os.SystemClock; -import android.support.v4.content.res.ResourcesCompat; -import android.support.v7.app.AppCompatActivity; -import android.support.v7.widget.PopupMenu; import android.text.SpannableString; import android.text.style.ForegroundColorSpan; import android.view.Menu; @@ -15,8 +12,10 @@ import android.widget.ImageButton; import android.widget.SeekBar; import android.widget.TextView; +import androidx.appcompat.widget.PopupMenu; +import androidx.core.content.res.ResourcesCompat; + import com.jjoe64.graphview.GraphView; -import com.squareup.otto.Subscribe; import com.wdullaer.materialdatetimepicker.date.DatePickerDialog; import org.slf4j.Logger; @@ -25,49 +24,43 @@ import org.slf4j.LoggerFactory; import java.util.Calendar; import java.util.Date; -import butterknife.BindView; -import butterknife.ButterKnife; -import butterknife.OnClick; -import butterknife.OnLongClick; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.events.EventCustomCalculationFinished; import info.nightscout.androidaps.interfaces.PumpInterface; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions; -import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin; -import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventAutosensCalculationFinished; -import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventIobCalculationProgress; -import info.nightscout.androidaps.plugins.Overview.OverviewFragment; -import info.nightscout.androidaps.plugins.Overview.OverviewPlugin; -import info.nightscout.androidaps.plugins.Overview.graphData.GraphData; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.T; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; +import info.nightscout.androidaps.plugins.general.overview.OverviewFragment; +import info.nightscout.androidaps.plugins.general.overview.OverviewPlugin; +import info.nightscout.androidaps.plugins.general.overview.graphData.GraphData; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutosensCalculationFinished; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventIobCalculationProgress; +import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.FabricPrivacy; +import info.nightscout.androidaps.utils.SP; +import info.nightscout.androidaps.utils.T; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.CompositeDisposable; -public class HistoryBrowseActivity extends AppCompatActivity { +public class HistoryBrowseActivity extends NoSplashActivity { private static Logger log = LoggerFactory.getLogger(HistoryBrowseActivity.class); - + private CompositeDisposable disposable = new CompositeDisposable(); ImageButton chartButton; boolean showBasal = true; - boolean showIob, showCob, showDev, showRat, showDevslope; + boolean showIob, showCob, showDev, showRat, showActPrim, showActSec, showDevslope; - @BindView(R.id.historybrowse_date) Button buttonDate; - @BindView(R.id.historybrowse_zoom) Button buttonZoom; - @BindView(R.id.historyybrowse_bggraph) GraphView bgGraph; - @BindView(R.id.historybrowse_iobgraph) GraphView iobGraph; - @BindView(R.id.historybrowse_seekBar) SeekBar seekBar; - @BindView(R.id.historybrowse_noprofile) TextView noProfile; - @BindView(R.id.overview_iobcalculationprogess) TextView iobCalculationProgressView; private int rangeToDisplay = 24; // for graph @@ -82,11 +75,83 @@ public class HistoryBrowseActivity extends AppCompatActivity { } @Override - protected void onCreate(Bundle savedInstanceState) { + public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_historybrowse); - ButterKnife.bind(this); + buttonDate = findViewById(R.id.historybrowse_date); + buttonZoom = findViewById(R.id.historybrowse_zoom); + bgGraph = findViewById(R.id.historyybrowse_bggraph); + iobGraph = findViewById(R.id.historybrowse_iobgraph); + seekBar = findViewById(R.id.historybrowse_seekBar); + noProfile = findViewById(R.id.historybrowse_noprofile); + iobCalculationProgressView = findViewById(R.id.overview_iobcalculationprogess); + + findViewById(R.id.historybrowse_left).setOnClickListener(v -> { + start -= T.hours(rangeToDisplay).msecs(); + updateGUI("onClickLeft"); + runCalculation("onClickLeft"); + }); + + findViewById(R.id.historybrowse_right).setOnClickListener(v -> { + start += T.hours(rangeToDisplay).msecs(); + updateGUI("onClickRight"); + runCalculation("onClickRight"); + }); + + findViewById(R.id.historybrowse_end).setOnClickListener(v -> { + Calendar calendar = Calendar.getInstance(); + calendar.setTimeInMillis(System.currentTimeMillis()); + calendar.set(Calendar.MILLISECOND, 0); + calendar.set(Calendar.SECOND, 0); + calendar.set(Calendar.MINUTE, 0); + calendar.set(Calendar.HOUR_OF_DAY, 0); + start = calendar.getTimeInMillis(); + updateGUI("onClickEnd"); + runCalculation("onClickEnd"); + }); + + findViewById(R.id.historybrowse_zoom).setOnClickListener(v -> { + rangeToDisplay += 6; + rangeToDisplay = rangeToDisplay > 24 ? 6 : rangeToDisplay; + updateGUI("rangeChange"); + }); + + findViewById(R.id.historybrowse_zoom).setOnLongClickListener(v -> { + Calendar calendar = Calendar.getInstance(); + calendar.setTimeInMillis(start); + calendar.set(Calendar.MILLISECOND, 0); + calendar.set(Calendar.SECOND, 0); + calendar.set(Calendar.MINUTE, 0); + calendar.set(Calendar.HOUR_OF_DAY, 0); + start = calendar.getTimeInMillis(); + updateGUI("resetToMidnight"); + runCalculation("onLongClickZoom"); + return true; + }); + + findViewById(R.id.historybrowse_date).setOnClickListener(v -> { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(new Date(start)); + DatePickerDialog dpd = DatePickerDialog.newInstance( + (view, year, monthOfYear, dayOfMonth) -> { + Date date = new Date(0); + date.setYear(year - 1900); + date.setMonth(monthOfYear); + date.setDate(dayOfMonth); + date.setHours(0); + start = date.getTime(); + updateGUI("onClickDate"); + runCalculation("onClickDate"); + }, + calendar.get(Calendar.YEAR), + calendar.get(Calendar.MONTH), + calendar.get(Calendar.DAY_OF_MONTH) + ); + dpd.setThemeDark(true); + dpd.dismissOnPause(true); + dpd.show(getFragmentManager(), "Datepickerdialog"); + }); bgGraph.getGridLabelRenderer().setGridColor(MainApp.gc(R.color.graphgrid)); bgGraph.getGridLabelRenderer().reloadStyles(); @@ -103,14 +168,33 @@ public class HistoryBrowseActivity extends AppCompatActivity { @Override public void onPause() { super.onPause(); - MainApp.bus().unregister(this); + disposable.clear(); iobCobCalculatorPlugin.stopCalculation("onPause"); } @Override public void onResume() { super.onResume(); - MainApp.bus().register(this); + disposable.add(RxBus.INSTANCE + .toObservable(EventAutosensCalculationFinished.class) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(event -> { + if (event.getCause() == eventCustomCalculationFinished) { + log.debug("EventAutosensCalculationFinished"); + synchronized (HistoryBrowseActivity.this) { + updateGUI("EventAutosensCalculationFinished"); + } + } + }, FabricPrivacy::logException) + ); + disposable.add(RxBus.INSTANCE + .toObservable(EventIobCalculationProgress.class) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(event -> { + if (iobCalculationProgressView != null) + iobCalculationProgressView.setText(event.getProgress()); + }, FabricPrivacy::logException) + ); // set start of current day Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(System.currentTimeMillis()); @@ -124,78 +208,6 @@ public class HistoryBrowseActivity extends AppCompatActivity { updateGUI("onResume"); } - @OnClick(R.id.historybrowse_left) - void onClickLeft() { - start -= T.hours(rangeToDisplay).msecs(); - updateGUI("onClickLeft"); - runCalculation("onClickLeft"); - } - - @OnClick(R.id.historybrowse_right) - void onClickRight() { - start += T.hours(rangeToDisplay).msecs(); - updateGUI("onClickRight"); - runCalculation("onClickRight"); - } - - @OnClick(R.id.historybrowse_end) - void onClickEnd() { - Calendar calendar = Calendar.getInstance(); - calendar.setTimeInMillis(System.currentTimeMillis()); - calendar.set(Calendar.MILLISECOND, 0); - calendar.set(Calendar.SECOND, 0); - calendar.set(Calendar.MINUTE, 0); - calendar.set(Calendar.HOUR_OF_DAY, 0); - start = calendar.getTimeInMillis(); - updateGUI("onClickEnd"); - runCalculation("onClickEnd"); - } - - @OnClick(R.id.historybrowse_zoom) - void onClickZoom() { - rangeToDisplay += 6; - rangeToDisplay = rangeToDisplay > 24 ? 6 : rangeToDisplay; - updateGUI("rangeChange"); - } - - @OnLongClick(R.id.historybrowse_zoom) - boolean onLongClickZoom() { - Calendar calendar = Calendar.getInstance(); - calendar.setTimeInMillis(start); - calendar.set(Calendar.MILLISECOND, 0); - calendar.set(Calendar.SECOND, 0); - calendar.set(Calendar.MINUTE, 0); - calendar.set(Calendar.HOUR_OF_DAY, 0); - start = calendar.getTimeInMillis(); - updateGUI("resetToMidnight"); - runCalculation("onLongClickZoom"); - return true; - } - - @OnClick(R.id.historybrowse_date) - void onClickDate() { - Calendar calendar = Calendar.getInstance(); - calendar.setTime(new Date(start)); - DatePickerDialog dpd = DatePickerDialog.newInstance( - (view, year, monthOfYear, dayOfMonth) -> { - Date date = new Date(0); - date.setYear(year - 1900); - date.setMonth(monthOfYear); - date.setDate(dayOfMonth); - date.setHours(0); - start = date.getTime(); - updateGUI("onClickDate"); - runCalculation("onClickDate"); - }, - calendar.get(Calendar.YEAR), - calendar.get(Calendar.MONTH), - calendar.get(Calendar.DAY_OF_MONTH) - ); - dpd.setThemeDark(true); - dpd.dismissOnPause(true); - dpd.show(getFragmentManager(), "Datepickerdialog"); - } - private void runCalculation(String from) { long end = start + T.hours(rangeToDisplay).msecs(); iobCobCalculatorPlugin.stopCalculation(from); @@ -203,26 +215,6 @@ public class HistoryBrowseActivity extends AppCompatActivity { iobCobCalculatorPlugin.runCalculation(from, end, true, false, eventCustomCalculationFinished); } - @Subscribe - public void onStatusEvent(final EventAutosensCalculationFinished e) { - if (e.cause == eventCustomCalculationFinished) { - log.debug("EventAutosensCalculationFinished"); - runOnUiThread(() -> { - synchronized (HistoryBrowseActivity.this) { - updateGUI("EventAutosensCalculationFinished"); - } - }); - } - } - - @Subscribe - public void onStatusEvent(final EventIobCalculationProgress e) { - runOnUiThread(() -> { - if (iobCalculationProgressView != null) - iobCalculationProgressView.setText(e.progress); - }); - } - void updateGUI(String from) { log.debug("updateGUI from: " + from); @@ -240,14 +232,23 @@ public class HistoryBrowseActivity extends AppCompatActivity { } final String units = profile.getUnits(); - final double lowLine = OverviewPlugin.getPlugin().determineLowLine(units); - final double highLine = OverviewPlugin.getPlugin().determineHighLine(units); + final double lowLine = OverviewPlugin.INSTANCE.determineLowLine(units); + final double highLine = OverviewPlugin.INSTANCE.determineHighLine(units); buttonDate.setText(DateUtil.dateAndTimeString(start)); buttonZoom.setText(String.valueOf(rangeToDisplay)); final boolean showPrediction = false; + showBasal = SP.getBoolean("hist_showbasals", true); + showIob = SP.getBoolean("hist_showiob", true); + showCob = SP.getBoolean("hist_showcob", true); + showDev = SP.getBoolean("hist_showdeviations", false); + showRat = SP.getBoolean("hist_showratios", false); + showActPrim = SP.getBoolean("hist_showactivityprimary", false); + showActSec = SP.getBoolean("hist_showactivitysecondary", false); + showDevslope = SP.getBoolean("hist_showdevslope", false); + int hoursToFetch; final long toTime; final long fromTime; @@ -285,6 +286,10 @@ public class HistoryBrowseActivity extends AppCompatActivity { // set manual x bounds to have nice steps graphData.formatAxis(fromTime, toTime); + if (showActPrim) { + graphData.addActivity(fromTime, toTime, false, 1d); + } + // Treatments graphData.addTreatments(fromTime, toTime); @@ -305,6 +310,7 @@ public class HistoryBrowseActivity extends AppCompatActivity { boolean useCobForScale = false; boolean useDevForScale = false; boolean useRatioForScale = false; + boolean useIAForScale = false; boolean useDSForScale = false; if (showIob) { @@ -315,18 +321,22 @@ public class HistoryBrowseActivity extends AppCompatActivity { useDevForScale = true; } else if (showRat) { useRatioForScale = true; + } else if (showActSec) { + useIAForScale = true; } else if (showDevslope) { useDSForScale = true; } if (showIob) - secondGraphData.addIob(fromTime, toTime, useIobForScale, 1d); + secondGraphData.addIob(fromTime, toTime, useIobForScale, 1d, showPrediction); if (showCob) secondGraphData.addCob(fromTime, toTime, useCobForScale, useCobForScale ? 1d : 0.5d); if (showDev) secondGraphData.addDeviations(fromTime, toTime, useDevForScale, 1d); if (showRat) secondGraphData.addRatio(fromTime, toTime, useRatioForScale, 1d); + if (showActSec) + secondGraphData.addActivity(fromTime, toTime, useIAForScale, useIAForScale ? 2d : 1d); if (showDevslope) secondGraphData.addDeviationSlope(fromTime, toTime, useDSForScale, 1d); @@ -337,14 +347,14 @@ public class HistoryBrowseActivity extends AppCompatActivity { // do GUI update runOnUiThread(() -> { - if (showIob || showCob || showDev || showRat || showDevslope) { + if (showIob || showCob || showDev || showRat || showActSec || showDevslope) { iobGraph.setVisibility(View.VISIBLE); } else { iobGraph.setVisibility(View.GONE); } // finally enforce drawing of graphs graphData.performUpdate(); - if (showIob || showCob || showDev || showRat || showDevslope) + if (showIob || showCob || showDev || showRat || showActSec || showDevslope) secondGraphData.performUpdate(); }); }).start(); @@ -353,22 +363,37 @@ public class HistoryBrowseActivity extends AppCompatActivity { private void setupChartMenu() { chartButton = (ImageButton) findViewById(R.id.overview_chartMenuButton); chartButton.setOnClickListener(v -> { - MenuItem item; + MenuItem item, dividerItem; CharSequence title; + int titleMaxChars = 0; SpannableString s; PopupMenu popup = new PopupMenu(v.getContext(), v); item = popup.getMenu().add(Menu.NONE, OverviewFragment.CHARTTYPE.BAS.ordinal(), Menu.NONE, MainApp.gs(R.string.overview_show_basals)); title = item.getTitle(); + if (titleMaxChars < title.length()) titleMaxChars = title.length(); s = new SpannableString(title); s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.basal, null)), 0, s.length(), 0); item.setTitle(s); item.setCheckable(true); item.setChecked(showBasal); + item = popup.getMenu().add(Menu.NONE, OverviewFragment.CHARTTYPE.ACTPRIM.ordinal(), Menu.NONE, MainApp.gs(R.string.overview_show_activity)); + title = item.getTitle(); + if (titleMaxChars < title.length()) titleMaxChars = title.length(); + s = new SpannableString(title); + s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.activity, null)), 0, s.length(), 0); + item.setTitle(s); + item.setCheckable(true); + item.setChecked(showActPrim); + + dividerItem = popup.getMenu().add(""); + dividerItem.setEnabled(false); + item = popup.getMenu().add(Menu.NONE, OverviewFragment.CHARTTYPE.IOB.ordinal(), Menu.NONE, MainApp.gs(R.string.overview_show_iob)); title = item.getTitle(); + if (titleMaxChars < title.length()) titleMaxChars = title.length(); s = new SpannableString(title); s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.iob, null)), 0, s.length(), 0); item.setTitle(s); @@ -377,6 +402,7 @@ public class HistoryBrowseActivity extends AppCompatActivity { item = popup.getMenu().add(Menu.NONE, OverviewFragment.CHARTTYPE.COB.ordinal(), Menu.NONE, MainApp.gs(R.string.overview_show_cob)); title = item.getTitle(); + if (titleMaxChars < title.length()) titleMaxChars = title.length(); s = new SpannableString(title); s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.cob, null)), 0, s.length(), 0); item.setTitle(s); @@ -385,6 +411,7 @@ public class HistoryBrowseActivity extends AppCompatActivity { item = popup.getMenu().add(Menu.NONE, OverviewFragment.CHARTTYPE.DEV.ordinal(), Menu.NONE, MainApp.gs(R.string.overview_show_deviations)); title = item.getTitle(); + if (titleMaxChars < title.length()) titleMaxChars = title.length(); s = new SpannableString(title); s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.deviations, null)), 0, s.length(), 0); item.setTitle(s); @@ -393,15 +420,27 @@ public class HistoryBrowseActivity extends AppCompatActivity { item = popup.getMenu().add(Menu.NONE, OverviewFragment.CHARTTYPE.SEN.ordinal(), Menu.NONE, MainApp.gs(R.string.overview_show_sensitivity)); title = item.getTitle(); + if (titleMaxChars < title.length()) titleMaxChars = title.length(); s = new SpannableString(title); s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.ratio, null)), 0, s.length(), 0); item.setTitle(s); item.setCheckable(true); item.setChecked(showRat); + item = popup.getMenu().add(Menu.NONE, OverviewFragment.CHARTTYPE.ACTSEC.ordinal(), Menu.NONE, MainApp.gs(R.string.overview_show_activity)); + title = item.getTitle(); + if (titleMaxChars < title.length()) titleMaxChars = title.length(); + s = new SpannableString(title); + s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.activity, null)), 0, s.length(), 0); + item.setTitle(s); + item.setCheckable(true); + item.setChecked(showActSec); + + if (MainApp.devBranch) { item = popup.getMenu().add(Menu.NONE, OverviewFragment.CHARTTYPE.DEVSLOPE.ordinal(), Menu.NONE, "Deviation slope"); title = item.getTitle(); + if (titleMaxChars < title.length()) titleMaxChars = title.length(); s = new SpannableString(title); s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.devslopepos, null)), 0, s.length(), 0); item.setTitle(s); @@ -409,19 +448,27 @@ public class HistoryBrowseActivity extends AppCompatActivity { item.setChecked(showDevslope); } + // Fairly good guestimate for required divider text size... + title = new String(new char[titleMaxChars + 10]).replace("\0", "_"); + dividerItem.setTitle(title); + popup.setOnMenuItemClickListener(item1 -> { if (item1.getItemId() == OverviewFragment.CHARTTYPE.BAS.ordinal()) { - showBasal = !item1.isChecked(); + SP.putBoolean("hist_showbasals", !item1.isChecked()); } else if (item1.getItemId() == OverviewFragment.CHARTTYPE.IOB.ordinal()) { - showIob = !item1.isChecked(); + SP.putBoolean("hist_showiob", !item1.isChecked()); } else if (item1.getItemId() == OverviewFragment.CHARTTYPE.COB.ordinal()) { - showCob = !item1.isChecked(); + SP.putBoolean("hist_showcob", !item1.isChecked()); } else if (item1.getItemId() == OverviewFragment.CHARTTYPE.DEV.ordinal()) { - showDev = !item1.isChecked(); + SP.putBoolean("hist_showdeviations", !item1.isChecked()); } else if (item1.getItemId() == OverviewFragment.CHARTTYPE.SEN.ordinal()) { - showRat = !item1.isChecked(); + SP.putBoolean("hist_showratios", !item1.isChecked()); + } else if (item1.getItemId() == OverviewFragment.CHARTTYPE.ACTPRIM.ordinal()) { + SP.putBoolean("hist_showactivityprimary", !item1.isChecked()); + } else if (item1.getItemId() == OverviewFragment.CHARTTYPE.ACTSEC.ordinal()) { + SP.putBoolean("hist_showactivitysecondary", !item1.isChecked()); } else if (item1.getItemId() == OverviewFragment.CHARTTYPE.DEVSLOPE.ordinal()) { - showDevslope = !item1.isChecked(); + SP.putBoolean("hist_showdevslope", !item1.isChecked()); } updateGUI("onGraphCheckboxesCheckedChanged"); return true; diff --git a/app/src/main/java/info/nightscout/androidaps/activities/NoSplashActivity.kt b/app/src/main/java/info/nightscout/androidaps/activities/NoSplashActivity.kt new file mode 100644 index 0000000000..0b7af2bd1d --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/activities/NoSplashActivity.kt @@ -0,0 +1,13 @@ +package info.nightscout.androidaps.activities + +import android.app.Activity +import android.os.Bundle + +import info.nightscout.androidaps.R + +open class NoSplashActivity : Activity() { + public override fun onCreate(savedInstanceState: Bundle?) { + setTheme(R.style.AppTheme_NoActionBar) + super.onCreate(savedInstanceState) + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/activities/NoSplashAppCompatActivity.kt b/app/src/main/java/info/nightscout/androidaps/activities/NoSplashAppCompatActivity.kt new file mode 100644 index 0000000000..e4c8027cd5 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/activities/NoSplashAppCompatActivity.kt @@ -0,0 +1,12 @@ +package info.nightscout.androidaps.activities + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import info.nightscout.androidaps.R + +open class NoSplashAppCompatActivity : AppCompatActivity() { + public override fun onCreate(savedInstanceState: Bundle?) { + setTheme(R.style.AppTheme_NoActionBar) + super.onCreate(savedInstanceState) + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/activities/PreferencesActivity.java b/app/src/main/java/info/nightscout/androidaps/activities/PreferencesActivity.java index 10a9487da0..367429dbbf 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/PreferencesActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/activities/PreferencesActivity.java @@ -9,47 +9,54 @@ import android.preference.PreferenceActivity; import android.preference.PreferenceFragment; import android.preference.PreferenceGroup; import android.preference.PreferenceManager; +import android.preference.PreferenceScreen; import android.text.TextUtils; import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.plugins.bus.RxBus; import info.nightscout.androidaps.events.EventPreferenceChange; -import info.nightscout.androidaps.events.EventRefreshGui; +import info.nightscout.androidaps.events.EventRebuildTabs; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginType; -import info.nightscout.androidaps.plugins.Careportal.CareportalPlugin; -import info.nightscout.androidaps.plugins.ConstraintsSafety.SafetyPlugin; -import info.nightscout.androidaps.plugins.Insulin.InsulinOrefFreePeakPlugin; -import info.nightscout.androidaps.plugins.Loop.LoopPlugin; -import info.nightscout.androidaps.plugins.NSClientInternal.NSClientPlugin; -import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin; -import info.nightscout.androidaps.plugins.OpenAPSMA.OpenAPSMAPlugin; -import info.nightscout.androidaps.plugins.OpenAPSSMB.OpenAPSSMBPlugin; -import info.nightscout.androidaps.plugins.PumpCombo.ComboPlugin; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; -import info.nightscout.androidaps.plugins.PumpDanaRS.DanaRSPlugin; -import info.nightscout.androidaps.plugins.PumpDanaRv2.DanaRv2Plugin; -import info.nightscout.androidaps.plugins.PumpInsight.InsightPlugin; -import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin; -import info.nightscout.androidaps.plugins.Sensitivity.SensitivityAAPSPlugin; -import info.nightscout.androidaps.plugins.Sensitivity.SensitivityOref0Plugin; -import info.nightscout.androidaps.plugins.Sensitivity.SensitivityOref1Plugin; -import info.nightscout.androidaps.plugins.Sensitivity.SensitivityWeightedAveragePlugin; -import info.nightscout.androidaps.plugins.SmsCommunicator.SmsCommunicatorPlugin; -import info.nightscout.androidaps.plugins.Source.SourceDexcomG5Plugin; -import info.nightscout.androidaps.plugins.Wear.WearPlugin; -import info.nightscout.androidaps.plugins.XDripStatusline.StatuslinePlugin; -import info.nightscout.utils.LocaleHelper; -import info.nightscout.utils.OKDialog; -import info.nightscout.utils.SP; +import info.nightscout.androidaps.plugins.general.careportal.CareportalPlugin; +import info.nightscout.androidaps.plugins.constraints.safety.SafetyPlugin; +import info.nightscout.androidaps.plugins.general.tidepool.TidepoolPlugin; +import info.nightscout.androidaps.plugins.general.tidepool.comm.TidepoolUploader; +import info.nightscout.androidaps.plugins.insulin.InsulinOrefFreePeakPlugin; +import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin; +import info.nightscout.androidaps.plugins.general.nsclient.NSClientPlugin; +import info.nightscout.androidaps.plugins.aps.openAPSAMA.OpenAPSAMAPlugin; +import info.nightscout.androidaps.plugins.aps.openAPSMA.OpenAPSMAPlugin; +import info.nightscout.androidaps.plugins.aps.openAPSSMB.OpenAPSSMBPlugin; +import info.nightscout.androidaps.plugins.pump.combo.ComboPlugin; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPlugin; +import info.nightscout.androidaps.plugins.pump.danaRKorean.DanaRKoreanPlugin; +import info.nightscout.androidaps.plugins.pump.danaRS.DanaRSPlugin; +import info.nightscout.androidaps.plugins.pump.danaRv2.DanaRv2Plugin; +import info.nightscout.androidaps.plugins.pump.insight.LocalInsightPlugin; +import info.nightscout.androidaps.plugins.pump.medtronic.MedtronicPumpPlugin; +import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin; +import info.nightscout.androidaps.plugins.sensitivity.SensitivityAAPSPlugin; +import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref0Plugin; +import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin; +import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAveragePlugin; +import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin; +import info.nightscout.androidaps.plugins.general.wear.WearPlugin; +import info.nightscout.androidaps.plugins.general.xdripStatusline.StatuslinePlugin; +import info.nightscout.androidaps.plugins.source.SourceDexcomPlugin; +import info.nightscout.androidaps.utils.LocaleHelper; +import info.nightscout.androidaps.utils.OKDialog; +import info.nightscout.androidaps.utils.SP; +import info.nightscout.androidaps.plugins.general.automation.AutomationPlugin; public class PreferencesActivity extends PreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener { MyPreferenceFragment myPreferenceFragment; @Override protected void onCreate(Bundle savedInstanceState) { + setTheme(R.style.AppTheme_NoActionBar); super.onCreate(savedInstanceState); myPreferenceFragment = new MyPreferenceFragment(); Bundle args = new Bundle(); @@ -61,16 +68,14 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { - MainApp.bus().post(new EventPreferenceChange(key)); + RxBus.INSTANCE.send(new EventPreferenceChange(key)); if (key.equals("language")) { - String lang = sharedPreferences.getString("language", "en"); - LocaleHelper.setLocale(getApplicationContext(), lang); - MainApp.bus().post(new EventRefreshGui(true)); + RxBus.INSTANCE.send(new EventRebuildTabs(true)); //recreate() does not update language so better close settings finish(); } if (key.equals("short_tabtitles")) { - MainApp.bus().post(new EventRefreshGui()); + RxBus.INSTANCE.send(new EventRebuildTabs()); } if (key.equals(MainApp.gs(R.string.key_openapsama_useautosens)) && SP.getBoolean(R.string.key_openapsama_useautosens, false)) { OKDialog.show(this, MainApp.gs(R.string.configbuilder_sensitivity), MainApp.gs(R.string.sensitivity_warning), null); @@ -92,7 +97,7 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre } else if (editTextPref.getText() != null) { ((EditTextPreference) pref).setDialogMessage(editTextPref.getDialogMessage()); pref.setSummary(editTextPref.getText()); - } else if (pref.getKey().contains("smscommunicator_allowednumbers") && TextUtils.isEmpty(editTextPref.getText().trim())) { + } else if (pref.getKey().contains("smscommunicator_allowednumbers") && (editTextPref.getText() == null || TextUtils.isEmpty(editTextPref.getText().trim()))) { pref.setSummary(MainApp.gs(R.string.smscommunicator_allowednumbers_summary)); } } @@ -143,7 +148,7 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre addPreferencesFromResource(R.xml.pref_overview); - addPreferencesFromResourceIfEnabled(SourceDexcomG5Plugin.getPlugin(), PluginType.BGSOURCE); + addPreferencesFromResourceIfEnabled(SourceDexcomPlugin.INSTANCE, PluginType.BGSOURCE); addPreferencesFromResourceIfEnabled(CareportalPlugin.getPlugin(), PluginType.GENERAL); addPreferencesFromResourceIfEnabled(SafetyPlugin.getPlugin(), PluginType.CONSTRAINTS); if (Config.APS) { @@ -163,8 +168,9 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre addPreferencesFromResourceIfEnabled(DanaRKoreanPlugin.getPlugin(), PluginType.PUMP); addPreferencesFromResourceIfEnabled(DanaRv2Plugin.getPlugin(), PluginType.PUMP); addPreferencesFromResourceIfEnabled(DanaRSPlugin.getPlugin(), PluginType.PUMP); - addPreferencesFromResourceIfEnabled(InsightPlugin.getPlugin(), PluginType.PUMP); + addPreferencesFromResourceIfEnabled(LocalInsightPlugin.getPlugin(), PluginType.PUMP); addPreferencesFromResourceIfEnabled(ComboPlugin.getPlugin(), PluginType.PUMP); + addPreferencesFromResourceIfEnabled(MedtronicPumpPlugin.getPlugin(), PluginType.PUMP); if (DanaRPlugin.getPlugin().isEnabled(PluginType.PROFILE) || DanaRKoreanPlugin.getPlugin().isEnabled(PluginType.PROFILE) @@ -181,7 +187,9 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre addPreferencesFromResourceIfEnabled(InsulinOrefFreePeakPlugin.getPlugin(), PluginType.INSULIN); addPreferencesFromResourceIfEnabled(NSClientPlugin.getPlugin(), PluginType.GENERAL); + addPreferencesFromResourceIfEnabled(TidepoolPlugin.INSTANCE, PluginType.GENERAL); addPreferencesFromResourceIfEnabled(SmsCommunicatorPlugin.getPlugin(), PluginType.GENERAL); + addPreferencesFromResourceIfEnabled(AutomationPlugin.INSTANCE, PluginType.GENERAL); addPreferencesFromResource(R.xml.pref_others); addPreferencesFromResource(R.xml.pref_datachoices); @@ -190,7 +198,26 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre addPreferencesFromResourceIfEnabled(StatuslinePlugin.getPlugin(), PluginType.GENERAL); } + if (Config.NSCLIENT) { + PreferenceScreen scrnAdvancedSettings = (PreferenceScreen) findPreference(getString(R.string.key_advancedsettings)); + if (scrnAdvancedSettings != null) { + scrnAdvancedSettings.removePreference(getPreference(getString(R.string.key_statuslights_res_warning))); + scrnAdvancedSettings.removePreference(getPreference(getString(R.string.key_statuslights_res_critical))); + scrnAdvancedSettings.removePreference(getPreference(getString(R.string.key_statuslights_bat_warning))); + scrnAdvancedSettings.removePreference(getPreference(getString(R.string.key_statuslights_bat_critical))); + scrnAdvancedSettings.removePreference(getPreference(getString(R.string.key_show_statuslights))); + scrnAdvancedSettings.removePreference(getPreference(getString(R.string.key_show_statuslights_extended))); + } + } + initSummary(getPreferenceScreen()); + + final Preference tidepoolTestLogin = findPreference(MainApp.gs(R.string.key_tidepool_test_login)); + if (tidepoolTestLogin != null) + tidepoolTestLogin.setOnPreferenceClickListener(preference -> { + TidepoolUploader.INSTANCE.testLogin(getActivity()); + return false; + }); } @Override diff --git a/app/src/main/java/info/nightscout/androidaps/activities/RequestDexcomPermissionActivity.kt b/app/src/main/java/info/nightscout/androidaps/activities/RequestDexcomPermissionActivity.kt new file mode 100644 index 0000000000..96a399a299 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/activities/RequestDexcomPermissionActivity.kt @@ -0,0 +1,19 @@ +package info.nightscout.androidaps.activities + +import android.os.Bundle +import info.nightscout.androidaps.plugins.source.SourceDexcomPlugin + +class RequestDexcomPermissionActivity : NoSplashAppCompatActivity() { + + private val requestCode = "AndroidAPS <3".map { it.toInt() }.sum() + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + requestPermissions(arrayOf(SourceDexcomPlugin.PERMISSION), requestCode) + } + + override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { + finish() + } + +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/activities/SingleFragmentActivity.java b/app/src/main/java/info/nightscout/androidaps/activities/SingleFragmentActivity.java index 04fd7a6be7..688ba82c6a 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/SingleFragmentActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/activities/SingleFragmentActivity.java @@ -2,24 +2,24 @@ package info.nightscout.androidaps.activities; import android.content.Intent; import android.os.Bundle; -import android.support.annotation.Nullable; -import android.support.v4.app.Fragment; -import android.support.v7.app.AppCompatActivity; import android.view.Menu; import android.view.MenuItem; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; +import androidx.fragment.app.Fragment; + import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.activities.PreferencesActivity; import info.nightscout.androidaps.interfaces.PluginBase; -import info.nightscout.utils.PasswordProtection; +import info.nightscout.androidaps.utils.PasswordProtection; public class SingleFragmentActivity extends AppCompatActivity { private PluginBase plugin; @Override - protected void onCreate(@Nullable Bundle savedInstanceState) { + public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_single_fragment); diff --git a/app/src/main/java/info/nightscout/androidaps/activities/TDDStatsActivity.java b/app/src/main/java/info/nightscout/androidaps/activities/TDDStatsActivity.java index b46faec980..24cdceada6 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/TDDStatsActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/activities/TDDStatsActivity.java @@ -1,10 +1,8 @@ package info.nightscout.androidaps.activities; -import android.app.Activity; import android.graphics.Color; import android.graphics.Rect; import android.os.Bundle; -import android.support.v7.widget.LinearLayoutManager; import android.text.TextUtils; import android.view.KeyEvent; import android.view.MotionEvent; @@ -18,7 +16,7 @@ import android.widget.TableLayout; import android.widget.TableRow; import android.widget.TextView; -import com.squareup.otto.Subscribe; +import androidx.recyclerview.widget.LinearLayoutManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -39,21 +37,26 @@ import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.db.TDD; import info.nightscout.androidaps.events.EventPumpStatusChanged; import info.nightscout.androidaps.interfaces.PumpInterface; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; -import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRSyncStatus; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; -import info.nightscout.androidaps.plugins.PumpDanaRS.DanaRSPlugin; -import info.nightscout.androidaps.plugins.PumpDanaRv2.DanaRv2Plugin; -import info.nightscout.androidaps.plugins.PumpInsight.InsightPlugin; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPlugin; +import info.nightscout.androidaps.plugins.pump.danaR.events.EventDanaRSyncStatus; +import info.nightscout.androidaps.plugins.pump.danaRKorean.DanaRKoreanPlugin; +import info.nightscout.androidaps.plugins.pump.danaRS.DanaRSPlugin; +import info.nightscout.androidaps.plugins.pump.danaRv2.DanaRv2Plugin; +import info.nightscout.androidaps.plugins.pump.insight.LocalInsightPlugin; import info.nightscout.androidaps.queue.Callback; -import info.nightscout.utils.DecimalFormatter; -import info.nightscout.utils.SP; -import info.nightscout.utils.SafeParse; +import info.nightscout.androidaps.utils.DecimalFormatter; +import info.nightscout.androidaps.utils.FabricPrivacy; +import info.nightscout.androidaps.utils.SP; +import info.nightscout.androidaps.utils.SafeParse; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.CompositeDisposable; -public class TDDStatsActivity extends Activity { +public class TDDStatsActivity extends NoSplashActivity { private static Logger log = LoggerFactory.getLogger(TDDStatsActivity.class); + private CompositeDisposable disposable = new CompositeDisposable(); TextView statusView, statsMessage, totalBaseBasal2; EditText totalBaseBasal; @@ -74,13 +77,25 @@ public class TDDStatsActivity extends Activity { @Override protected void onResume() { super.onResume(); - MainApp.bus().register(this); + disposable.add(RxBus.INSTANCE + .toObservable(EventPumpStatusChanged.class) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(event -> statusView.setText(event.getStatus()), FabricPrivacy::logException) + ); + disposable.add(RxBus.INSTANCE + .toObservable(EventDanaRSyncStatus.class) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(event -> { + log.debug("EventDanaRSyncStatus: " + event.getMessage()); + statusView.setText(event.getMessage()); + }, FabricPrivacy::logException) + ); } @Override protected void onPause() { super.onPause(); - MainApp.bus().unregister(this); + disposable.clear(); } @Override @@ -99,7 +114,7 @@ public class TDDStatsActivity extends Activity { } @Override - protected void onCreate(Bundle savedInstanceState) { + public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.danar_statsactivity); getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN); @@ -239,7 +254,7 @@ public class TDDStatsActivity extends Activity { statsMessage.setText(MainApp.gs(R.string.danar_stats_warning_Message)); } }); - ConfigBuilderPlugin.getPlugin().getCommandQueue().loadTDDs( new Callback() { + ConfigBuilderPlugin.getPlugin().getCommandQueue().loadTDDs(new Callback() { @Override public void run() { loadDataFromDB(); @@ -399,7 +414,7 @@ public class TDDStatsActivity extends Activity { //cumulative TDDs for (TDD record : historyList) { - if(!historyList.isEmpty() && df.format(new Date(record.date)).equals(df.format(new Date()))) { + if (!historyList.isEmpty() && df.format(new Date(record.date)).equals(df.format(new Date()))) { //Today should not be included continue; } @@ -448,7 +463,7 @@ public class TDDStatsActivity extends Activity { tl.setBackgroundColor(Color.TRANSPARENT); } - if(!historyList.isEmpty() && df.format(new Date(historyList.get(0).date)).equals(df.format(new Date()))) { + if (!historyList.isEmpty() && df.format(new Date(historyList.get(0).date)).equals(df.format(new Date()))) { //Today should not be included historyList.remove(0); } @@ -519,42 +534,17 @@ public class TDDStatsActivity extends Activity { } } - @Subscribe - public void onStatusEvent(final EventDanaRSyncStatus s) { - log.debug("EventDanaRSyncStatus: " + s.message); - runOnUiThread( - new Runnable() { - @Override - public void run() { - statusView.setText(s.message); - } - }); - } - - @Subscribe - public void onStatusEvent(final EventPumpStatusChanged c) { - runOnUiThread( - new Runnable() { - @Override - public void run() { - statusView.setText(c.textStatus()); - } - } - ); - } - - public static boolean isOldData(List historyList) { Object activePump = ConfigBuilderPlugin.getPlugin().getActivePump(); - PumpInterface dana = MainApp.getSpecificPlugin(DanaRPlugin.class); - PumpInterface danaRS = MainApp.getSpecificPlugin(DanaRSPlugin.class); - PumpInterface danaV2 = MainApp.getSpecificPlugin(DanaRv2Plugin.class); - PumpInterface danaKorean = MainApp.getSpecificPlugin(DanaRKoreanPlugin.class); - PumpInterface insight = MainApp.getSpecificPlugin(InsightPlugin.class); + PumpInterface dana = DanaRPlugin.getPlugin(); + PumpInterface danaRS = DanaRSPlugin.getPlugin(); + PumpInterface danaV2 = DanaRv2Plugin.getPlugin(); + PumpInterface danaKorean = DanaRKoreanPlugin.getPlugin(); + PumpInterface insight = LocalInsightPlugin.getPlugin(); boolean startsYesterday = activePump == dana || activePump == danaRS || activePump == danaV2 || activePump == danaKorean || activePump == insight; DateFormat df = new SimpleDateFormat("dd.MM."); - return (historyList.size() < 3 || !(df.format(new Date(historyList.get(0).date)).equals(df.format(new Date(System.currentTimeMillis() - (startsYesterday?1000 * 60 * 60 * 24:0)))))); + return (historyList.size() < 3 || !(df.format(new Date(historyList.get(0).date)).equals(df.format(new Date(System.currentTimeMillis() - (startsYesterday ? 1000 * 60 * 60 * 24 : 0)))))); } } \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/data/ConstraintChecker.java b/app/src/main/java/info/nightscout/androidaps/data/ConstraintChecker.java index ceb85c6967..9d7a49493b 100644 --- a/app/src/main/java/info/nightscout/androidaps/data/ConstraintChecker.java +++ b/app/src/main/java/info/nightscout/androidaps/data/ConstraintChecker.java @@ -1,5 +1,7 @@ package info.nightscout.androidaps.data; +import androidx.annotation.NonNull; + import java.util.ArrayList; import info.nightscout.androidaps.Constants; @@ -15,13 +17,6 @@ import info.nightscout.androidaps.interfaces.PluginType; public class ConstraintChecker implements ConstraintsInterface { - private MainApp mainApp; - - public ConstraintChecker(MainApp mainApp) { - this.mainApp = mainApp; - } - - public Constraint isLoopInvokationAllowed() { return isLoopInvocationAllowed(new Constraint<>(true)); } @@ -50,6 +45,10 @@ public class ConstraintChecker implements ConstraintsInterface { return isAdvancedFilteringEnabled(new Constraint<>(true)); } + public Constraint isSuperBolusEnabled() { + return isSuperBolusEnabled(new Constraint<>(true)); + } + public Constraint getMaxBasalAllowed(Profile profile) { return applyBasalConstraints(new Constraint<>(Constants.REALLYHIGHBASALRATE), profile); } @@ -75,9 +74,9 @@ public class ConstraintChecker implements ConstraintsInterface { } @Override - public Constraint isLoopInvocationAllowed(Constraint value) { + public Constraint isLoopInvocationAllowed(@NonNull Constraint value) { - ArrayList constraintsPlugins = mainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class); + ArrayList constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class); for (PluginBase p : constraintsPlugins) { ConstraintsInterface constraint = (ConstraintsInterface) p; if (!p.isEnabled(PluginType.CONSTRAINTS)) continue; @@ -87,9 +86,9 @@ public class ConstraintChecker implements ConstraintsInterface { } @Override - public Constraint isClosedLoopAllowed(Constraint value) { + public Constraint isClosedLoopAllowed(@NonNull Constraint value) { - ArrayList constraintsPlugins = mainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class); + ArrayList constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class); for (PluginBase p : constraintsPlugins) { ConstraintsInterface constraint = (ConstraintsInterface) p; if (!p.isEnabled(PluginType.CONSTRAINTS)) continue; @@ -99,9 +98,9 @@ public class ConstraintChecker implements ConstraintsInterface { } @Override - public Constraint isAutosensModeEnabled(Constraint value) { + public Constraint isAutosensModeEnabled(@NonNull Constraint value) { - ArrayList constraintsPlugins = mainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class); + ArrayList constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class); for (PluginBase p : constraintsPlugins) { ConstraintsInterface constraint = (ConstraintsInterface) p; if (!p.isEnabled(PluginType.CONSTRAINTS)) continue; @@ -111,9 +110,9 @@ public class ConstraintChecker implements ConstraintsInterface { } @Override - public Constraint isAMAModeEnabled(Constraint value) { + public Constraint isAMAModeEnabled(@NonNull Constraint value) { - ArrayList constraintsPlugins = mainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class); + ArrayList constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class); for (PluginBase p : constraintsPlugins) { ConstraintsInterface constrain = (ConstraintsInterface) p; if (!p.isEnabled(PluginType.CONSTRAINTS)) continue; @@ -123,9 +122,9 @@ public class ConstraintChecker implements ConstraintsInterface { } @Override - public Constraint isSMBModeEnabled(Constraint value) { + public Constraint isSMBModeEnabled(@NonNull Constraint value) { - ArrayList constraintsPlugins = mainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class); + ArrayList constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class); for (PluginBase p : constraintsPlugins) { ConstraintsInterface constraint = (ConstraintsInterface) p; if (!p.isEnabled(PluginType.CONSTRAINTS)) continue; @@ -135,9 +134,9 @@ public class ConstraintChecker implements ConstraintsInterface { } @Override - public Constraint isUAMEnabled(Constraint value) { + public Constraint isUAMEnabled(@NonNull Constraint value) { - ArrayList constraintsPlugins = mainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class); + ArrayList constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class); for (PluginBase p : constraintsPlugins) { ConstraintsInterface constraint = (ConstraintsInterface) p; if (!p.isEnabled(PluginType.CONSTRAINTS)) continue; @@ -147,8 +146,8 @@ public class ConstraintChecker implements ConstraintsInterface { } @Override - public Constraint isAdvancedFilteringEnabled(Constraint value) { - ArrayList constraintsPlugins = mainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class); + public Constraint isAdvancedFilteringEnabled(@NonNull Constraint value) { + ArrayList constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class); for (PluginBase p : constraintsPlugins) { ConstraintsInterface constraint = (ConstraintsInterface) p; if (!p.isEnabled(PluginType.CONSTRAINTS)) continue; @@ -158,8 +157,19 @@ public class ConstraintChecker implements ConstraintsInterface { } @Override - public Constraint applyBasalConstraints(Constraint absoluteRate, Profile profile) { - ArrayList constraintsPlugins = mainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class); + public Constraint isSuperBolusEnabled(@NonNull Constraint value) { + ArrayList constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class); + for (PluginBase p : constraintsPlugins) { + ConstraintsInterface constraint = (ConstraintsInterface) p; + if (!p.isEnabled(PluginType.CONSTRAINTS)) continue; + constraint.isSuperBolusEnabled(value); + } + return value; + } + + @Override + public Constraint applyBasalConstraints(@NonNull Constraint absoluteRate, Profile profile) { + ArrayList constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class); for (PluginBase p : constraintsPlugins) { ConstraintsInterface constraint = (ConstraintsInterface) p; if (!p.isEnabled(PluginType.CONSTRAINTS)) continue; @@ -169,8 +179,8 @@ public class ConstraintChecker implements ConstraintsInterface { } @Override - public Constraint applyBasalPercentConstraints(Constraint percentRate, Profile profile) { - ArrayList constraintsPlugins = mainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class); + public Constraint applyBasalPercentConstraints(@NonNull Constraint percentRate, Profile profile) { + ArrayList constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class); for (PluginBase p : constraintsPlugins) { ConstraintsInterface constrain = (ConstraintsInterface) p; if (!p.isEnabled(PluginType.CONSTRAINTS)) continue; @@ -180,8 +190,8 @@ public class ConstraintChecker implements ConstraintsInterface { } @Override - public Constraint applyBolusConstraints(Constraint insulin) { - ArrayList constraintsPlugins = mainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class); + public Constraint applyBolusConstraints(@NonNull Constraint insulin) { + ArrayList constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class); for (PluginBase p : constraintsPlugins) { ConstraintsInterface constrain = (ConstraintsInterface) p; if (!p.isEnabled(PluginType.CONSTRAINTS)) continue; @@ -191,8 +201,8 @@ public class ConstraintChecker implements ConstraintsInterface { } @Override - public Constraint applyExtendedBolusConstraints(Constraint insulin) { - ArrayList constraintsPlugins = mainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class); + public Constraint applyExtendedBolusConstraints(@NonNull Constraint insulin) { + ArrayList constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class); for (PluginBase p : constraintsPlugins) { ConstraintsInterface constrain = (ConstraintsInterface) p; if (!p.isEnabled(PluginType.CONSTRAINTS)) continue; @@ -202,8 +212,8 @@ public class ConstraintChecker implements ConstraintsInterface { } @Override - public Constraint applyCarbsConstraints(Constraint carbs) { - ArrayList constraintsPlugins = mainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class); + public Constraint applyCarbsConstraints(@NonNull Constraint carbs) { + ArrayList constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class); for (PluginBase p : constraintsPlugins) { ConstraintsInterface constrain = (ConstraintsInterface) p; if (!p.isEnabled(PluginType.CONSTRAINTS)) continue; @@ -213,8 +223,8 @@ public class ConstraintChecker implements ConstraintsInterface { } @Override - public Constraint applyMaxIOBConstraints(Constraint maxIob) { - ArrayList constraintsPlugins = mainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class); + public Constraint applyMaxIOBConstraints(@NonNull Constraint maxIob) { + ArrayList constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class); for (PluginBase p : constraintsPlugins) { ConstraintsInterface constrain = (ConstraintsInterface) p; if (!p.isEnabled(PluginType.CONSTRAINTS)) continue; diff --git a/app/src/main/java/info/nightscout/androidaps/data/DetailedBolusInfo.java b/app/src/main/java/info/nightscout/androidaps/data/DetailedBolusInfo.java index 51a1e18685..ef5cd69782 100644 --- a/app/src/main/java/info/nightscout/androidaps/data/DetailedBolusInfo.java +++ b/app/src/main/java/info/nightscout/androidaps/data/DetailedBolusInfo.java @@ -2,15 +2,12 @@ package info.nightscout.androidaps.data; import android.content.Context; -import com.rits.cloning.Cloner; - import org.json.JSONObject; import java.util.Date; import info.nightscout.androidaps.db.CareportalEvent; import info.nightscout.androidaps.db.Source; -import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; /** * Created by mike on 29.05.2017. diff --git a/app/src/main/java/info/nightscout/androidaps/data/GlucoseStatus.java b/app/src/main/java/info/nightscout/androidaps/data/GlucoseStatus.java deleted file mode 100644 index d8ee55b73a..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/data/GlucoseStatus.java +++ /dev/null @@ -1,163 +0,0 @@ -package info.nightscout.androidaps.data; - -import android.content.SharedPreferences; -import android.preference.PreferenceManager; -import android.support.annotation.Nullable; -import android.text.Html; -import android.text.Spanned; - -import com.j256.ormlite.dao.Dao; -import com.j256.ormlite.stmt.PreparedQuery; -import com.j256.ormlite.stmt.QueryBuilder; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.db.BgReading; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.DecimalFormatter; -import info.nightscout.utils.Round; - -/** - * Created by mike on 04.01.2017. - */ - -public class GlucoseStatus { - private static Logger log = LoggerFactory.getLogger(GlucoseStatus.class); - public double glucose = 0d; - public double delta = 0d; - public double avgdelta = 0d; - public double short_avgdelta = 0d; - public double long_avgdelta = 0d; - public long date = 0L; - - - @Override - public String toString() { - return MainApp.gs(R.string.glucose) + " " + DecimalFormatter.to0Decimal(glucose) + " mg/dl\n" + - MainApp.gs(R.string.delta) + " " + DecimalFormatter.to0Decimal(delta) + " mg/dl\n" + - MainApp.gs(R.string.short_avgdelta) + " " + DecimalFormatter.to2Decimal(short_avgdelta) + " mg/dl\n" + - MainApp.gs(R.string.long_avgdelta) + " " + DecimalFormatter.to2Decimal(long_avgdelta) + " mg/dl"; - } - - public GlucoseStatus() { - } - - public GlucoseStatus round() { - this.glucose = Round.roundTo(this.glucose, 0.1); - this.delta = Round.roundTo(this.delta, 0.01); - this.avgdelta = Round.roundTo(this.avgdelta, 0.01); - this.short_avgdelta = Round.roundTo(this.short_avgdelta, 0.01); - this.long_avgdelta = Round.roundTo(this.long_avgdelta, 0.01); - return this; - } - - - - @Nullable - public static GlucoseStatus getGlucoseStatusData(){ - return getGlucoseStatusData(false); - } - - @Nullable - public static GlucoseStatus getGlucoseStatusData(boolean allowOldData) { - // load 45min - long fromtime = DateUtil.now() - 60 * 1000L * 45; - List data = MainApp.getDbHelper().getBgreadingsDataFromTime(fromtime, false); - - int sizeRecords = data.size(); - if (sizeRecords == 0) { - return null; - } - - if (data.get(0).date < DateUtil.now() - 7 * 60 * 1000L && !allowOldData) { - return null; - } - - BgReading now = data.get(0); - long now_date = now.date; - double change; - - if (sizeRecords == 1) { - GlucoseStatus status = new GlucoseStatus(); - status.glucose = now.value; - status.short_avgdelta = 0d; - status.delta = 0d; - status.long_avgdelta = 0d; - status.avgdelta = 0d; // for OpenAPS MA - status.date = now_date; - return status.round(); - } - - ArrayList last_deltas = new ArrayList(); - ArrayList short_deltas = new ArrayList(); - ArrayList long_deltas = new ArrayList(); - - for (int i = 1; i < data.size(); i++) { - if (data.get(i).value > 38) { - BgReading then = data.get(i); - long then_date = then.date; - double avgdelta = 0; - long minutesago; - - minutesago = Math.round((now_date - then_date) / (1000d * 60)); - // multiply by 5 to get the same units as delta, i.e. mg/dL/5m - change = now.value - then.value; - avgdelta = change / minutesago * 5; - - // use the average of all data points in the last 2.5m for all further "now" calculations - if (0 < minutesago && minutesago < 2.5) { - now.value = (now.value + then.value) / 2; - now_date = (now_date + then_date) / 2; - // short_deltas are calculated from everything ~5-15 minutes ago - } else if (2.5 < minutesago && minutesago < 17.5) { - //console.error(minutesago, avgdelta); - short_deltas.add(avgdelta); - // last_deltas are calculated from everything ~5 minutes ago - if (2.5 < minutesago && minutesago < 7.5) { - last_deltas.add(avgdelta); - } - // long_deltas are calculated from everything ~20-40 minutes ago - } else if (17.5 < minutesago && minutesago < 42.5) { - long_deltas.add(avgdelta); - } - } - } - - GlucoseStatus status = new GlucoseStatus(); - status.glucose = now.value; - status.date = now_date; - - status.short_avgdelta = average(short_deltas); - - if (last_deltas.isEmpty()) { - status.delta = status.short_avgdelta; - } else { - status.delta = average(last_deltas); - } - - status.long_avgdelta = average(long_deltas); - status.avgdelta = status.short_avgdelta; // for OpenAPS MA - - return status.round(); - } - - public static double average(ArrayList array) { - double sum = 0d; - - if (array.size() == 0) - return 0d; - - for (Double value : array) { - sum += value; - } - return sum / array.size(); - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/data/Intervals.java b/app/src/main/java/info/nightscout/androidaps/data/Intervals.java index 66d567d9bd..efb3b76aea 100644 --- a/app/src/main/java/info/nightscout/androidaps/data/Intervals.java +++ b/app/src/main/java/info/nightscout/androidaps/data/Intervals.java @@ -1,7 +1,7 @@ package info.nightscout.androidaps.data; -import android.support.annotation.Nullable; -import android.support.v4.util.LongSparseArray; +import androidx.annotation.Nullable; +import androidx.collection.LongSparseArray; import java.util.ArrayList; import java.util.List; @@ -22,7 +22,7 @@ public abstract class Intervals { rawData = new LongSparseArray(); } - public synchronized Intervals reset() { + public synchronized Intervals reset() { rawData = new LongSparseArray(); return this; } diff --git a/app/src/main/java/info/nightscout/androidaps/data/IobTotal.java b/app/src/main/java/info/nightscout/androidaps/data/IobTotal.java index a87b77be07..79885e297f 100644 --- a/app/src/main/java/info/nightscout/androidaps/data/IobTotal.java +++ b/app/src/main/java/info/nightscout/androidaps/data/IobTotal.java @@ -9,10 +9,12 @@ import org.slf4j.LoggerFactory; import java.util.Date; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.Round; +import info.nightscout.androidaps.plugins.general.overview.graphExtensions.DataPointWithLabelInterface; +import info.nightscout.androidaps.plugins.general.overview.graphExtensions.PointsWithLabelGraphSeries; +import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.Round; -public class IobTotal { +public class IobTotal implements DataPointWithLabelInterface { private static Logger log = LoggerFactory.getLogger(IobTotal.class); public double iob; @@ -133,4 +135,52 @@ public class IobTotal { return json; } + // DataPoint interface + + int color; + + @Override + public double getX() { + return time; + } + + @Override + public double getY() { + return iob; + } + + @Override + public void setY(double y) { + + } + + @Override + public String getLabel() { + return null; + } + + @Override + public long getDuration() { + return 0; + } + + @Override + public PointsWithLabelGraphSeries.Shape getShape() { + return PointsWithLabelGraphSeries.Shape.IOBPREDICTION; + } + + @Override + public float getSize() { + return 0.5f; + } + + @Override + public int getColor() { + return color; + } + + public IobTotal setColor(int color) { + this.color = color; + return this; + } } diff --git a/app/src/main/java/info/nightscout/androidaps/data/NonOverlappingIntervals.java b/app/src/main/java/info/nightscout/androidaps/data/NonOverlappingIntervals.java index 8e0c286e7e..c426aede40 100644 --- a/app/src/main/java/info/nightscout/androidaps/data/NonOverlappingIntervals.java +++ b/app/src/main/java/info/nightscout/androidaps/data/NonOverlappingIntervals.java @@ -1,10 +1,8 @@ package info.nightscout.androidaps.data; -import android.support.annotation.Nullable; -import android.support.v4.util.LongSparseArray; +import androidx.annotation.Nullable; -import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.interfaces.Interval; /** @@ -21,7 +19,7 @@ public class NonOverlappingIntervals extends Intervals { rawData = other.rawData.clone(); } - protected synchronized void merge() { + public synchronized void merge() { for (int index = 0; index < rawData.size() - 1; index++) { Interval i = rawData.valueAt(index); long startOfNewer = rawData.valueAt(index + 1).start(); diff --git a/app/src/main/java/info/nightscout/androidaps/data/OverlappingIntervals.java b/app/src/main/java/info/nightscout/androidaps/data/OverlappingIntervals.java index 76c2ff3615..5515ea15e1 100644 --- a/app/src/main/java/info/nightscout/androidaps/data/OverlappingIntervals.java +++ b/app/src/main/java/info/nightscout/androidaps/data/OverlappingIntervals.java @@ -1,7 +1,7 @@ package info.nightscout.androidaps.data; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import info.nightscout.androidaps.interfaces.Interval; diff --git a/app/src/main/java/info/nightscout/androidaps/data/Profile.java b/app/src/main/java/info/nightscout/androidaps/data/Profile.java index e6df495c40..6f18ba7af5 100644 --- a/app/src/main/java/info/nightscout/androidaps/data/Profile.java +++ b/app/src/main/java/info/nightscout/androidaps/data/Profile.java @@ -1,6 +1,6 @@ package info.nightscout.androidaps.data; -import android.support.v4.util.LongSparseArray; +import androidx.collection.LongSparseArray; import org.json.JSONArray; import org.json.JSONException; @@ -9,21 +9,22 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.text.DecimalFormat; -import java.util.Calendar; import java.util.TimeZone; +import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.interfaces.PumpInterface; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; -import info.nightscout.androidaps.plugins.Overview.notifications.Notification; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.DecimalFormatter; -import info.nightscout.utils.FabricPrivacy; -import info.nightscout.utils.MidnightTime; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; +import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.DecimalFormatter; +import info.nightscout.androidaps.utils.FabricPrivacy; +import info.nightscout.androidaps.utils.MidnightTime; public class Profile { private static Logger log = LoggerFactory.getLogger(Profile.class); @@ -166,17 +167,18 @@ public class Profile { final JSONObject o = array.getJSONObject(index); long tas = 0; try { - tas = getShitfTimeSecs((int) o.getLong("timeAsSeconds")); - } catch (JSONException e) { String time = o.getString("time"); tas = getShitfTimeSecs(DateUtil.toSeconds(time)); + } catch (JSONException e) { //log.debug(">>>>>>>>>>>> Used recalculated timeAsSecons: " + time + " " + tas); + tas = getShitfTimeSecs((int) o.getLong("timeAsSeconds")); } double value = o.getDouble("value") * multiplier; sparse.put(tas, value); - } catch (JSONException e) { + } catch (Exception e) { log.error("Unhandled exception", e); log.error(json.toString()); + FabricPrivacy.logException(e); } } @@ -227,8 +229,10 @@ public class Profile { for (int index = 0; index < basal_v.size(); index++) { long secondsFromMidnight = basal_v.keyAt(index); if (notify && secondsFromMidnight % 3600 != 0) { - Notification notification = new Notification(Notification.BASAL_PROFILE_NOT_ALIGNED_TO_HOURS, String.format(MainApp.gs(R.string.basalprofilenotaligned), from), Notification.NORMAL); - MainApp.bus().post(new EventNewNotification(notification)); + if (Config.APS) { + Notification notification = new Notification(Notification.BASAL_PROFILE_NOT_ALIGNED_TO_HOURS, String.format(MainApp.gs(R.string.basalprofilenotaligned), from), Notification.NORMAL); + RxBus.INSTANCE.send(new EventNewNotification(notification)); + } } } } @@ -259,11 +263,11 @@ public class Profile { } protected void sendBelowMinimumNotification(String from) { - MainApp.bus().post(new EventNewNotification(new Notification(Notification.MINIMAL_BASAL_VALUE_REPLACED, String.format(MainApp.gs(R.string.minimalbasalvaluereplaced), from), Notification.NORMAL))); + RxBus.INSTANCE.send(new EventNewNotification(new Notification(Notification.MINIMAL_BASAL_VALUE_REPLACED, String.format(MainApp.gs(R.string.minimalbasalvaluereplaced), from), Notification.NORMAL))); } protected void sendAboveMaximumNotification(String from) { - MainApp.bus().post(new EventNewNotification(new Notification(Notification.MAXIMUM_BASAL_VALUE_REPLACED, String.format(MainApp.gs(R.string.maximumbasalvaluereplaced), from), Notification.NORMAL))); + RxBus.INSTANCE.send(new EventNewNotification(new Notification(Notification.MAXIMUM_BASAL_VALUE_REPLACED, String.format(MainApp.gs(R.string.maximumbasalvaluereplaced), from), Notification.NORMAL))); } private void validate(LongSparseArray array) { @@ -401,6 +405,19 @@ public class Profile { return getValuesList(isf_v, null, new DecimalFormat("0.0"), getUnits() + MainApp.gs(R.string.profile_per_unit)); } + public ProfileValue[] getIsfs() { + if (isf_v == null) + isf_v = convertToSparseArray(ic); + ProfileValue[] ret = new ProfileValue[isf_v.size()]; + + for (Integer index = 0; index < isf_v.size(); index++) { + Integer tas = (int) isf_v.keyAt(index); + double value = isf_v.valueAt(index); + ret[index] = new ProfileValue(tas, value); + } + return ret; + } + public double getIc() { return getIcTimeFromMidnight(secondsFromMidnight()); } @@ -421,6 +438,19 @@ public class Profile { return getValuesList(ic_v, null, new DecimalFormat("0.0"), MainApp.gs(R.string.profile_carbs_per_unit)); } + public ProfileValue[] getIcs() { + if (ic_v == null) + ic_v = convertToSparseArray(ic); + ProfileValue[] ret = new ProfileValue[ic_v.size()]; + + for (Integer index = 0; index < ic_v.size(); index++) { + Integer tas = (int) ic_v.keyAt(index); + double value = ic_v.valueAt(index); + ret[index] = new ProfileValue(tas, value); + } + return ret; + } + public double getBasal() { return getBasalTimeFromMidnight(secondsFromMidnight()); } @@ -439,11 +469,11 @@ public class Profile { public String getBasalList() { if (basal_v == null) basal_v = convertToSparseArray(basal); - return getValuesList(basal_v, null, new DecimalFormat("0.00"), MainApp.gs(R.string.profile_ins_units_per_hout)); + return getValuesList(basal_v, null, new DecimalFormat("0.00"), MainApp.gs(R.string.profile_ins_units_per_hour)); } - public class BasalValue { - public BasalValue(int timeAsSeconds, double value) { + public class ProfileValue { + public ProfileValue(int timeAsSeconds, double value) { this.timeAsSeconds = timeAsSeconds; this.value = value; } @@ -452,15 +482,15 @@ public class Profile { public double value; } - public synchronized BasalValue[] getBasalValues() { + public synchronized ProfileValue[] getBasalValues() { if (basal_v == null) basal_v = convertToSparseArray(basal); - BasalValue[] ret = new BasalValue[basal_v.size()]; + ProfileValue[] ret = new ProfileValue[basal_v.size()]; for (Integer index = 0; index < basal_v.size(); index++) { Integer tas = (int) basal_v.keyAt(index); double value = basal_v.valueAt(index); - ret[index] = new BasalValue(tas, value); + ret[index] = new ProfileValue(tas, value); } return ret; } @@ -501,6 +531,49 @@ public class Profile { return getValueToTime(targetHigh_v, timeAsSeconds); } + public class TargetValue { + public TargetValue(int timeAsSeconds, double low, double high) { + this.timeAsSeconds = timeAsSeconds; + this.low = low; + this.high = high; + } + + public int timeAsSeconds; + public double low; + public double high; + } + + public TargetValue[] getTargets() { + if (targetLow_v == null) + targetLow_v = convertToSparseArray(targetLow); + if (targetHigh_v == null) + targetHigh_v = convertToSparseArray(targetHigh); + TargetValue[] ret = new TargetValue[targetLow_v.size()]; + + for (Integer index = 0; index < targetLow_v.size(); index++) { + Integer tas = (int) targetLow_v.keyAt(index); + double low = targetLow_v.valueAt(index); + double high = targetHigh_v.valueAt(index); + ret[index] = new TargetValue(tas, low, high); + } + return ret; + } + + public ProfileValue[] getSingleTargets() { + if (targetLow_v == null) + targetLow_v = convertToSparseArray(targetLow); + if (targetHigh_v == null) + targetHigh_v = convertToSparseArray(targetHigh); + ProfileValue[] ret = new ProfileValue[targetLow_v.size()]; + + for (Integer index = 0; index < targetLow_v.size(); index++) { + Integer tas = (int) targetLow_v.keyAt(index); + double target = (targetLow_v.valueAt(index) + targetHigh_v.valueAt(index)) / 2; + ret[index] = new ProfileValue(tas, target); + } + return ret; + } + public String getTargetList() { if (targetLow_v == null) targetLow_v = convertToSparseArray(targetLow); diff --git a/app/src/main/java/info/nightscout/androidaps/data/ProfileIntervals.java b/app/src/main/java/info/nightscout/androidaps/data/ProfileIntervals.java index 9343596eee..37be1dc6e9 100644 --- a/app/src/main/java/info/nightscout/androidaps/data/ProfileIntervals.java +++ b/app/src/main/java/info/nightscout/androidaps/data/ProfileIntervals.java @@ -1,7 +1,7 @@ package info.nightscout.androidaps.data; -import android.support.annotation.Nullable; -import android.support.v4.util.LongSparseArray; +import androidx.annotation.Nullable; +import androidx.collection.LongSparseArray; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -10,7 +10,6 @@ import java.util.ArrayList; import java.util.List; import info.nightscout.androidaps.interfaces.Interval; -import info.nightscout.utils.DateUtil; /** * Created by mike on 09.05.2017. @@ -32,7 +31,7 @@ public class ProfileIntervals { rawData = other.rawData.clone(); } - public synchronized ProfileIntervals reset() { + public synchronized ProfileIntervals reset() { rawData = new LongSparseArray<>(); return this; } diff --git a/app/src/main/java/info/nightscout/androidaps/data/ProfileStore.java b/app/src/main/java/info/nightscout/androidaps/data/ProfileStore.java index f97d8b5e02..a0b54ec0bb 100644 --- a/app/src/main/java/info/nightscout/androidaps/data/ProfileStore.java +++ b/app/src/main/java/info/nightscout/androidaps/data/ProfileStore.java @@ -1,7 +1,7 @@ package info.nightscout.androidaps.data; -import android.support.annotation.Nullable; -import android.support.v4.util.ArrayMap; +import androidx.annotation.Nullable; +import androidx.collection.ArrayMap; import org.json.JSONException; import org.json.JSONObject; diff --git a/app/src/main/java/info/nightscout/androidaps/data/PumpEnactResult.java b/app/src/main/java/info/nightscout/androidaps/data/PumpEnactResult.java index 404833b77c..461d8faa7b 100644 --- a/app/src/main/java/info/nightscout/androidaps/data/PumpEnactResult.java +++ b/app/src/main/java/info/nightscout/androidaps/data/PumpEnactResult.java @@ -1,8 +1,5 @@ package info.nightscout.androidaps.data; -import android.text.Html; -import android.text.Spanned; - import org.json.JSONException; import org.json.JSONObject; import org.slf4j.Logger; @@ -11,8 +8,8 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.logging.L; -import info.nightscout.utils.DecimalFormatter; -import info.nightscout.utils.Round; +import info.nightscout.androidaps.utils.DecimalFormatter; +import info.nightscout.androidaps.utils.Round; public class PumpEnactResult { private static Logger log = LoggerFactory.getLogger(L.APS); @@ -48,6 +45,11 @@ public class PumpEnactResult { return this; } + public PumpEnactResult comment(int comment) { + this.comment = MainApp.gs(comment); + return this; + } + public PumpEnactResult duration(int duration) { this.duration = duration; return this; diff --git a/app/src/main/java/info/nightscout/androidaps/data/QuickWizard.java b/app/src/main/java/info/nightscout/androidaps/data/QuickWizard.java deleted file mode 100644 index 25c768cdda..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/data/QuickWizard.java +++ /dev/null @@ -1,90 +0,0 @@ -package info.nightscout.androidaps.data; - -import android.content.SharedPreferences; -import android.preference.PreferenceManager; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import info.nightscout.androidaps.MainApp; -import info.nightscout.utils.SP; - -/** - * Created by mike on 12.10.2016. - */ - -public class QuickWizard { - private static Logger log = LoggerFactory.getLogger(QuickWizard.class); - - private JSONArray storage = new JSONArray(); - - public void setData(JSONArray newData) { - storage = newData; - } - - public void save() { - SP.putString("QuickWizard", storage.toString()); - } - - public int size() { - return storage.length(); - } - - public QuickWizardEntry get(int position) { - try { - return new QuickWizardEntry((JSONObject) storage.get(position), position); - } catch (JSONException e) { - log.error("Unhandled exception", e); - } - return null; - } - - public Boolean isActive() { - for (int i = 0; i < storage.length(); i++) { - try { - if (new QuickWizardEntry((JSONObject) storage.get(i), i).isActive()) return true; - } catch (JSONException e) { - log.error("Unhandled exception", e); - } - } - return false; - } - - public QuickWizardEntry getActive() { - for (int i = 0; i < storage.length(); i++) { - QuickWizardEntry entry; - try { - entry = new QuickWizardEntry((JSONObject) storage.get(i), i); - } catch (JSONException e) { - continue; - } - if (entry.isActive()) return entry; - } - return null; - } - - public QuickWizardEntry newEmptyItem() { - return new QuickWizardEntry(); - } - - public void addOrUpdate(QuickWizardEntry newItem) { - if (newItem.position == -1) - storage.put(newItem.storage); - else { - try { - storage.put(newItem.position, newItem.storage); - } catch (JSONException e) { - log.error("Unhandled exception", e); - } - } - save(); - } - - public void remove(int position) { - storage.remove(position); - save(); - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/data/QuickWizard.kt b/app/src/main/java/info/nightscout/androidaps/data/QuickWizard.kt new file mode 100644 index 0000000000..f8bca8c450 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/data/QuickWizard.kt @@ -0,0 +1,52 @@ +package info.nightscout.androidaps.data + +import info.nightscout.androidaps.utils.SP +import org.json.JSONArray +import org.json.JSONObject + +object QuickWizard { + private var storage = JSONArray() + + init { + setData(JSONArray(SP.getString("QuickWizard", "[]"))) + } + + fun getActive(): QuickWizardEntry? { + for (i in 0 until storage.length()) { + val entry = QuickWizardEntry(storage.get(i) as JSONObject, i) + if (entry.isActive) return entry + } + return null + } + + fun setData(newData: JSONArray) { + storage = newData + } + + fun save() { + SP.putString("QuickWizard", storage.toString()) + } + + fun size(): Int = storage.length() + + operator fun get(position: Int): QuickWizardEntry = + QuickWizardEntry(storage.get(position) as JSONObject, position) + + + fun newEmptyItem(): QuickWizardEntry { + return QuickWizardEntry() + } + + fun addOrUpdate(newItem: QuickWizardEntry) { + if (newItem.position == -1) + storage.put(newItem.storage) + else + storage.put(newItem.position, newItem.storage) + save() + } + + fun remove(position: Int) { + storage.remove(position) + save() + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/data/QuickWizardEntry.java b/app/src/main/java/info/nightscout/androidaps/data/QuickWizardEntry.java index 04f297d7a9..062f6ae391 100644 --- a/app/src/main/java/info/nightscout/androidaps/data/QuickWizardEntry.java +++ b/app/src/main/java/info/nightscout/androidaps/data/QuickWizardEntry.java @@ -11,13 +11,14 @@ import info.nightscout.androidaps.R; import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.db.TempTarget; import info.nightscout.androidaps.interfaces.TreatmentsInterface; -import info.nightscout.androidaps.plugins.IobCobCalculator.CobInfo; -import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin; -import info.nightscout.androidaps.plugins.Loop.LoopPlugin; -import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; -import info.nightscout.utils.BolusWizard; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.SP; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.CobInfo; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin; +import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin; +import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; +import info.nightscout.androidaps.utils.BolusWizard; +import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.SP; /** * Created by mike on 25.12.2017. @@ -49,7 +50,7 @@ public class QuickWizardEntry { useTemptarget: 0 } */ - public QuickWizardEntry() { + QuickWizardEntry() { String emptyData = "{\"buttonText\":\"\",\"carbs\":0,\"validFrom\":0,\"validTo\":86340}"; try { storage = new JSONObject(emptyData); @@ -59,18 +60,17 @@ public class QuickWizardEntry { position = -1; } - public QuickWizardEntry(JSONObject entry, int position) { + QuickWizardEntry(JSONObject entry, int position) { storage = entry; this.position = position; } - public Boolean isActive() { + Boolean isActive() { return Profile.secondsFromMidnight() >= validFrom() && Profile.secondsFromMidnight() <= validTo(); } - public BolusWizard doCalc(Profile profile, TempTarget tempTarget, BgReading lastBG, boolean _synchronized) { - BolusWizard wizard = new BolusWizard(); - + public BolusWizard doCalc(Profile profile, String profileName, BgReading lastBG, boolean _synchronized) { + final TempTarget tempTarget = TreatmentsPlugin.getPlugin().getTempTargetFromHistory(); //BG double bg = 0; if (lastBG != null && useBG() == YES) { @@ -85,11 +85,6 @@ public class QuickWizardEntry { cob = cobInfo.displayCob; } - // Temp target - if (useTempTarget() == NO) { - tempTarget = null; - } - // Bolus IOB boolean bolusIOB = false; if (useBolusIOB() == YES) { @@ -129,8 +124,7 @@ public class QuickWizardEntry { trend = true; } - wizard.doCalc(profile, tempTarget, carbs(), cob, bg, 0d, bolusIOB, basalIOB, superBolus, trend); - return wizard; + return new BolusWizard(profile, profileName, tempTarget, carbs(), cob, bg, 0d, 100, true, useCOB() == YES, bolusIOB, basalIOB, superBolus, useTempTarget() == YES, trend, "QuickWizard"); } public String buttonText() { diff --git a/app/src/main/java/info/nightscout/androidaps/db/BgReading.java b/app/src/main/java/info/nightscout/androidaps/db/BgReading.java index 3b5963b83b..8b206e2c78 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/BgReading.java +++ b/app/src/main/java/info/nightscout/androidaps/db/BgReading.java @@ -1,7 +1,5 @@ package info.nightscout.androidaps.db; -import android.content.res.Resources; - import com.j256.ormlite.field.DatabaseField; import com.j256.ormlite.table.DatabaseTable; @@ -14,15 +12,13 @@ import java.util.Objects; import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSgv; -import info.nightscout.androidaps.plugins.Overview.OverviewPlugin; -import info.nightscout.androidaps.plugins.Overview.graphExtensions.DataPointWithLabelInterface; -import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLabelGraphSeries; -import info.nightscout.utils.DecimalFormatter; -import info.nightscout.utils.SP; +import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; +import info.nightscout.androidaps.plugins.general.nsclient.data.NSSgv; +import info.nightscout.androidaps.plugins.general.overview.OverviewPlugin; +import info.nightscout.androidaps.plugins.general.overview.graphExtensions.DataPointWithLabelInterface; +import info.nightscout.androidaps.plugins.general.overview.graphExtensions.PointsWithLabelGraphSeries; +import info.nightscout.androidaps.utils.DecimalFormatter; @DatabaseTable(tableName = DatabaseHelper.DATABASE_BGREADINGS) public class BgReading implements DataPointWithLabelInterface { @@ -220,8 +216,8 @@ public class BgReading implements DataPointWithLabelInterface { @Override public int getColor() { String units = ProfileFunctions.getInstance().getProfileUnits(); - Double lowLine = OverviewPlugin.getPlugin().determineLowLine(units); - Double highLine = OverviewPlugin.getPlugin().determineHighLine(units); + Double lowLine = OverviewPlugin.INSTANCE.determineLowLine(units); + Double highLine = OverviewPlugin.INSTANCE.determineHighLine(units); int color = MainApp.gc(R.color.inrange); if (isPrediction()) return getPredectionColor(); diff --git a/app/src/main/java/info/nightscout/androidaps/db/CareportalEvent.java b/app/src/main/java/info/nightscout/androidaps/db/CareportalEvent.java index 60c7553cc3..40fadff684 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/CareportalEvent.java +++ b/app/src/main/java/info/nightscout/androidaps/db/CareportalEvent.java @@ -13,7 +13,6 @@ import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.Collections; -import java.util.Date; import java.util.EnumSet; import java.util.LinkedHashMap; import java.util.List; @@ -26,14 +25,14 @@ import info.nightscout.androidaps.R; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.interfaces.Interval; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSMbg; -import info.nightscout.androidaps.plugins.Overview.OverviewFragment; -import info.nightscout.androidaps.plugins.Overview.graphExtensions.DataPointWithLabelInterface; -import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLabelGraphSeries; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.T; -import info.nightscout.utils.Translator; +import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; +import info.nightscout.androidaps.plugins.general.nsclient.data.NSMbg; +import info.nightscout.androidaps.plugins.general.overview.OverviewFragment; +import info.nightscout.androidaps.plugins.general.overview.graphExtensions.DataPointWithLabelInterface; +import info.nightscout.androidaps.plugins.general.overview.graphExtensions.PointsWithLabelGraphSeries; +import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.T; +import info.nightscout.androidaps.utils.Translator; @DatabaseTable(tableName = DatabaseHelper.DATABASE_CAREPORTALEVENTS) public class CareportalEvent implements DataPointWithLabelInterface, Interval { @@ -90,16 +89,26 @@ public class CareportalEvent implements DataPointWithLabelInterface, Interval { return System.currentTimeMillis() - date; } - public long getHoursFromStart() { - return (System.currentTimeMillis() - date) / (60 * 60 * 1000); + public double getHoursFromStart() { + return (System.currentTimeMillis() - date) / (60 * 60 * 1000.0); + } + + public String age(boolean useShortText) { + Map diff = computeDiff(date, System.currentTimeMillis()); + + String days = " " + MainApp.gs(R.string.days) + " "; + String hours = " " + MainApp.gs(R.string.hours) + " "; + + if (useShortText) { + days = "d"; + hours = "h"; + } + + return diff.get(TimeUnit.DAYS) + days + diff.get(TimeUnit.HOURS) + hours; } public String age() { - Map diff = computeDiff(date, System.currentTimeMillis()); - if (OverviewFragment.shorttextmode) - return diff.get(TimeUnit.DAYS) + "d" + diff.get(TimeUnit.HOURS) + "h"; - else - return diff.get(TimeUnit.DAYS) + " " + MainApp.gs(R.string.days) + " " + diff.get(TimeUnit.HOURS) + " " + MainApp.gs(R.string.hours); + return age(OverviewFragment.shorttextmode); } public boolean isOlderThan(double hours) { diff --git a/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java b/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java index 56f5d3b432..d8926fc4c1 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java +++ b/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java @@ -3,7 +3,7 @@ package info.nightscout.androidaps.db; import android.content.Context; import android.database.DatabaseUtils; import android.database.sqlite.SQLiteDatabase; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper; import com.j256.ormlite.dao.CloseableIterator; @@ -21,6 +21,8 @@ import org.slf4j.LoggerFactory; import java.sql.SQLException; import java.util.ArrayList; +import java.util.Calendar; +import java.util.GregorianCalendar; import java.util.List; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; @@ -29,13 +31,14 @@ import java.util.concurrent.TimeUnit; import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.plugins.bus.RxBus; import info.nightscout.androidaps.data.OverlappingIntervals; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.ProfileStore; import info.nightscout.androidaps.events.EventCareportalEventChange; import info.nightscout.androidaps.events.EventExtendedBolusChange; import info.nightscout.androidaps.events.EventNewBG; -import info.nightscout.androidaps.events.EventProfileSwitchChange; +import info.nightscout.androidaps.events.EventProfileNeedsUpdate; import info.nightscout.androidaps.events.EventRefreshOverview; import info.nightscout.androidaps.events.EventReloadProfileSwitchData; import info.nightscout.androidaps.events.EventReloadTempBasalData; @@ -44,16 +47,19 @@ import info.nightscout.androidaps.events.EventTempBasalChange; import info.nightscout.androidaps.events.EventTempTargetChange; import info.nightscout.androidaps.interfaces.ProfileInterface; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions; -import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventNewHistoryData; -import info.nightscout.androidaps.plugins.NSClientInternal.NSUpload; -import info.nightscout.androidaps.plugins.PumpDanaR.activities.DanaRNSHistorySync; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes; -import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin; -import info.nightscout.utils.JsonHelper; -import info.nightscout.utils.PercentageSplitter; -import info.nightscout.utils.ToastUtils; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.general.nsclient.NSUpload; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventNewHistoryData; +import info.nightscout.androidaps.plugins.pump.danaR.activities.DanaRNSHistorySync; +import info.nightscout.androidaps.plugins.pump.danaR.comm.RecordTypes; +import info.nightscout.androidaps.plugins.pump.insight.database.InsightBolusID; +import info.nightscout.androidaps.plugins.pump.insight.database.InsightHistoryOffset; +import info.nightscout.androidaps.plugins.pump.insight.database.InsightPumpID; +import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin; +import info.nightscout.androidaps.utils.JsonHelper; +import info.nightscout.androidaps.utils.PercentageSplitter; +import info.nightscout.androidaps.utils.ToastUtils; /** * This Helper contains all resource to provide a central DB management functionality. Only methods handling @@ -76,8 +82,11 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { public static final String DATABASE_CAREPORTALEVENTS = "CareportalEvents"; public static final String DATABASE_PROFILESWITCHES = "ProfileSwitches"; public static final String DATABASE_TDDS = "TDDs"; + public static final String DATABASE_INSIGHT_HISTORY_OFFSETS = "InsightHistoryOffsets"; + public static final String DATABASE_INSIGHT_BOLUS_IDS = "InsightBolusIDs"; + public static final String DATABASE_INSIGHT_PUMP_IDS = "InsightPumpIDs"; - private static final int DATABASE_VERSION = 9; + private static final int DATABASE_VERSION = 11; public static Long earliestDataChange = null; @@ -122,6 +131,13 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { TableUtils.createTableIfNotExists(connectionSource, CareportalEvent.class); TableUtils.createTableIfNotExists(connectionSource, ProfileSwitch.class); TableUtils.createTableIfNotExists(connectionSource, TDD.class); + TableUtils.createTableIfNotExists(connectionSource, InsightHistoryOffset.class); + TableUtils.createTableIfNotExists(connectionSource, InsightBolusID.class); + TableUtils.createTableIfNotExists(connectionSource, InsightPumpID.class); + database.execSQL("INSERT INTO sqlite_sequence (name, seq) SELECT \"" + DATABASE_INSIGHT_BOLUS_IDS + "\", " + System.currentTimeMillis() + " " + + "WHERE NOT EXISTS (SELECT 1 FROM sqlite_sequence WHERE name = \"" + DATABASE_INSIGHT_BOLUS_IDS + "\")"); + database.execSQL("INSERT INTO sqlite_sequence (name, seq) SELECT \"" + DATABASE_INSIGHT_PUMP_IDS + "\", " + System.currentTimeMillis() + " " + + "WHERE NOT EXISTS (SELECT 1 FROM sqlite_sequence WHERE name = \"" + DATABASE_INSIGHT_PUMP_IDS + "\")"); } catch (SQLException e) { log.error("Can't create database", e); throw new RuntimeException(e); @@ -134,11 +150,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { this.oldVersion = oldVersion; this.newVersion = newVersion; - if (oldVersion == 7 && newVersion == 8) { - log.debug("Upgrading database from v7 to v8"); - } else if (oldVersion == 8 && newVersion == 9) { - log.debug("Upgrading database from v8 to v9"); - } else { + if (oldVersion < 7) { log.info(DatabaseHelper.class.getName(), "onUpgrade"); TableUtils.dropTable(connectionSource, TempTarget.class, true); TableUtils.dropTable(connectionSource, BgReading.class, true); @@ -149,6 +161,17 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { TableUtils.dropTable(connectionSource, CareportalEvent.class, true); TableUtils.dropTable(connectionSource, ProfileSwitch.class, true); onCreate(database, connectionSource); + } else if (oldVersion < 10) { + TableUtils.createTableIfNotExists(connectionSource, InsightHistoryOffset.class); + TableUtils.createTableIfNotExists(connectionSource, InsightBolusID.class); + TableUtils.createTableIfNotExists(connectionSource, InsightPumpID.class); + database.execSQL("INSERT INTO sqlite_sequence (name, seq) SELECT \"" + DATABASE_INSIGHT_BOLUS_IDS + "\", " + System.currentTimeMillis() + " " + + "WHERE NOT EXISTS (SELECT 1 FROM sqlite_sequence WHERE name = \"" + DATABASE_INSIGHT_BOLUS_IDS + "\")"); + database.execSQL("INSERT INTO sqlite_sequence (name, seq) SELECT \"" + DATABASE_INSIGHT_PUMP_IDS + "\", " + System.currentTimeMillis() + " " + + "WHERE NOT EXISTS (SELECT 1 FROM sqlite_sequence WHERE name = \"" + DATABASE_INSIGHT_PUMP_IDS + "\")"); + } else if (oldVersion < 11) { + database.execSQL("UPDATE sqlite_sequence SET seq = " + System.currentTimeMillis() + " WHERE name = \"" + DATABASE_INSIGHT_BOLUS_IDS + "\""); + database.execSQL("UPDATE sqlite_sequence SET seq = " + System.currentTimeMillis() + " WHERE name = \"" + DATABASE_INSIGHT_PUMP_IDS + "\""); } } catch (SQLException e) { log.error("Can't drop databases", e); @@ -220,7 +243,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { new java.util.TimerTask() { @Override public void run() { - MainApp.bus().post(new EventRefreshOverview("resetDatabases")); + RxBus.INSTANCE.send(new EventRefreshOverview("resetDatabases")); } }, 3000 @@ -327,6 +350,18 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { return getDao(ProfileSwitch.class); } + private Dao getDaoInsightPumpID() throws SQLException { + return getDao(InsightPumpID.class); + } + + private Dao getDaoInsightBolusID() throws SQLException { + return getDao(InsightBolusID.class); + } + + private Dao getDaoInsightHistoryOffset() throws SQLException { + return getDao(InsightHistoryOffset.class); + } + public static long roundDateToSec(long date) { long rounded = date - date % 1000; if (rounded != date) @@ -377,7 +412,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { public void run() { if (L.isEnabled(L.DATABASE)) log.debug("Firing EventNewBg"); - MainApp.bus().post(new EventNewBG(bgReading)); + RxBus.INSTANCE.send(new EventNewBG(bgReading)); scheduledBgPost = null; } } @@ -396,24 +431,15 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { */ @Nullable public static BgReading lastBg() { - List bgList = null; + List bgList = IobCobCalculatorPlugin.getPlugin().getBgReadings(); - try { - Dao daoBgReadings = MainApp.getDbHelper().getDaoBgReadings(); - QueryBuilder queryBuilder = daoBgReadings.queryBuilder(); - queryBuilder.orderBy("date", false); - queryBuilder.limit(1L); - queryBuilder.where().ge("value", 39).and().eq("isValid", true); - PreparedQuery preparedQuery = queryBuilder.prepare(); - bgList = daoBgReadings.query(preparedQuery); - - } catch (SQLException e) { - log.error("Unhandled exception", e); - } - if (bgList != null && bgList.size() > 0) - return bgList.get(0); - else + if (bgList == null) return null; + + for (int i = 0; i < bgList.size(); i++) + if (bgList.get(i).value >= 39) + return bgList.get(i); + return null; } /* @@ -448,7 +474,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { } catch (SQLException e) { log.error("Unhandled exception", e); } - return new ArrayList(); + return new ArrayList<>(); } public List getBgreadingsDataFromTime(long start, long end, boolean ascending) { @@ -465,7 +491,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { } catch (SQLException e) { log.error("Unhandled exception", e); } - return new ArrayList(); + return new ArrayList<>(); } public List getAllBgreadingsDataFromTime(long mills, boolean ascending) { @@ -511,6 +537,24 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { return tddList; } + public List getTDDsForLastXDays(int days) { + List tddList; + GregorianCalendar gc = new GregorianCalendar(); + gc.add(Calendar.DAY_OF_YEAR, (-1) * days); + + try { + QueryBuilder queryBuilder = getDaoTDD().queryBuilder(); + queryBuilder.orderBy("date", false); + Where where = queryBuilder.where(); + where.ge("date", gc.getTimeInMillis()); + PreparedQuery preparedQuery = queryBuilder.prepare(); + tddList = getDaoTDD().query(preparedQuery); + } catch (SQLException e) { + log.error("Unhandled exception", e); + tddList = new ArrayList<>(); + } + return tddList; + } // ------------- DbRequests handling ------------------- @@ -573,7 +617,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { } } - // -------------------- TREATMENT HANDLING ------------------- + // -------------------- TEMPTARGET HANDLING ------------------- public static void updateEarliestDataChange(long newDate) { if (earliestDataChange == null) { @@ -604,6 +648,23 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { return new ArrayList(); } + public List getTemptargetsDataFromTime(long from, long to, boolean ascending) { + try { + Dao daoTempTargets = getDaoTempTargets(); + List tempTargets; + QueryBuilder queryBuilder = daoTempTargets.queryBuilder(); + queryBuilder.orderBy("date", ascending); + Where where = queryBuilder.where(); + where.between("date", from, to); + PreparedQuery preparedQuery = queryBuilder.prepare(); + tempTargets = daoTempTargets.query(preparedQuery); + return tempTargets; + } catch (SQLException e) { + log.error("Unhandled exception", e); + } + return new ArrayList(); + } + public boolean createOrUpdate(TempTarget tempTarget) { try { TempTarget old; @@ -676,7 +737,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { public void run() { if (L.isEnabled(L.DATABASE)) log.debug("Firing EventTempTargetChange"); - MainApp.bus().post(new EventTempTargetChange()); + RxBus.INSTANCE.send(new EventTempTargetChange()); scheduledTemTargetPost = null; } } @@ -710,7 +771,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { String units = JsonHelper.safeGetString(trJson, "units", Constants.MGDL); TempTarget tempTarget = new TempTarget() .date(trJson.getLong("mills")) - .duration(trJson.getInt("duration")) + .duration(JsonHelper.safeGetInt(trJson, "duration")) .low(Profile.toMgdl(trJson.getDouble("targetBottom"), units)) .high(Profile.toMgdl(trJson.getDouble("targetTop"), units)) .reason(JsonHelper.safeGetString(trJson, "reason", "")) @@ -829,6 +890,31 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { log.debug("TEMPBASAL: Already exists from: " + Source.getString(tempBasal.source) + " " + tempBasal.toString()); return false; } + + // search by date (in case its standard record that has become pump record) + QueryBuilder queryBuilder2 = getDaoTemporaryBasal().queryBuilder(); + Where where2 = queryBuilder2.where(); + where2.eq("date", tempBasal.date); + PreparedQuery preparedQuery2 = queryBuilder2.prepare(); + List trList2 = getDaoTemporaryBasal().query(preparedQuery2); + + if (trList2.size() > 0) { + old = trList2.get(0); + + old.copyFromPump(tempBasal); + old.source = Source.PUMP; + + if (L.isEnabled(L.DATABASE)) + log.debug("TEMPBASAL: Updated record with Pump Data : " + Source.getString(tempBasal.source) + " " + tempBasal.toString()); + + getDaoTemporaryBasal().update(old); + + updateEarliestDataChange(tempBasal.date); + scheduleTemporaryBasalChange(); + + return false; + } + getDaoTemporaryBasal().create(tempBasal); if (L.isEnabled(L.DATABASE)) log.debug("TEMPBASAL: New record from: " + Source.getString(tempBasal.source) + " " + tempBasal.toString()); @@ -927,15 +1013,31 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { return new ArrayList(); } + public List getTemporaryBasalsDataFromTime(long from, long to, boolean ascending) { + try { + List tempbasals; + QueryBuilder queryBuilder = getDaoTemporaryBasal().queryBuilder(); + queryBuilder.orderBy("date", ascending); + Where where = queryBuilder.where(); + where.between("date", from, to); + PreparedQuery preparedQuery = queryBuilder.prepare(); + tempbasals = getDaoTemporaryBasal().query(preparedQuery); + return tempbasals; + } catch (SQLException e) { + log.error("Unhandled exception", e); + } + return new ArrayList(); + } + private static void scheduleTemporaryBasalChange() { class PostRunnable implements Runnable { public void run() { if (L.isEnabled(L.DATABASE)) log.debug("Firing EventTempBasalChange"); - MainApp.bus().post(new EventReloadTempBasalData()); - MainApp.bus().post(new EventTempBasalChange()); + RxBus.INSTANCE.send(new EventReloadTempBasalData()); + RxBus.INSTANCE.send(new EventTempBasalChange()); if (earliestDataChange != null) - MainApp.bus().post(new EventNewHistoryData(earliestDataChange)); + RxBus.INSTANCE.send(new EventNewHistoryData(earliestDataChange)); earliestDataChange = null; scheduledTemBasalsPost = null; } @@ -1053,6 +1155,29 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { return null; } + + public TemporaryBasal findTempBasalByPumpId(Long pumpId) { + try { + QueryBuilder queryBuilder = null; + queryBuilder = getDaoTemporaryBasal().queryBuilder(); + queryBuilder.orderBy("date", false); + Where where = queryBuilder.where(); + where.eq("pumpId", pumpId); + PreparedQuery preparedQuery = queryBuilder.prepare(); + List list = getDaoTemporaryBasal().query(preparedQuery); + + if (list.size() > 0) + return list.get(0); + else + return null; + + } catch (SQLException e) { + log.error("Unhandled exception", e); + } + return null; + } + + // ------------ ExtendedBolus handling --------------- public boolean createOrUpdate(ExtendedBolus extendedBolus) { @@ -1149,6 +1274,17 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { return false; } + public ExtendedBolus getExtendedBolusByPumpId(long pumpId) { + try { + return getDaoExtendedBolus().queryBuilder() + .where().eq("pumpId", pumpId) + .queryForFirst(); + } catch (SQLException e) { + log.error("Unhandled exception", e); + } + return null; + } + public void delete(ExtendedBolus extendedBolus) { try { getDaoExtendedBolus().delete(extendedBolus); @@ -1234,9 +1370,9 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { public void run() { if (L.isEnabled(L.DATABASE)) log.debug("Firing EventExtendedBolusChange"); - MainApp.bus().post(new EventReloadTreatmentData(new EventExtendedBolusChange())); + RxBus.INSTANCE.send(new EventReloadTreatmentData(new EventExtendedBolusChange())); if (earliestDataChange != null) - MainApp.bus().post(new EventNewHistoryData(earliestDataChange)); + RxBus.INSTANCE.send(new EventNewHistoryData(earliestDataChange)); earliestDataChange = null; scheduledExtendedBolusPost = null; } @@ -1320,6 +1456,23 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { return new ArrayList<>(); } + public List getCareportalEvents(long start, long end, boolean ascending) { + try { + List careportalEvents; + QueryBuilder queryBuilder = getDaoCareportalEvents().queryBuilder(); + queryBuilder.orderBy("date", ascending); + Where where = queryBuilder.where(); + where.between("date", start, end); + PreparedQuery preparedQuery = queryBuilder.prepare(); + careportalEvents = getDaoCareportalEvents().query(preparedQuery); + preprocessOpenAPSOfflineEvents(careportalEvents); + return careportalEvents; + } catch (SQLException e) { + log.error("Unhandled exception", e); + } + return new ArrayList<>(); + } + public void preprocessOpenAPSOfflineEvents(List list) { OverlappingIntervals offlineEvents = new OverlappingIntervals(); for (int i = 0; i < list.size(); i++) { @@ -1423,7 +1576,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { public void run() { if (L.isEnabled(L.DATABASE)) log.debug("Firing scheduleCareportalEventChange"); - MainApp.bus().post(new EventCareportalEventChange()); + RxBus.INSTANCE.send(new EventCareportalEventChange()); scheduledCareportalEventPost = null; } } @@ -1473,6 +1626,24 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { return new ArrayList<>(); } + public List getProfileSwitchEventsFromTime(long from, long to, boolean ascending) { + try { + Dao daoProfileSwitch = getDaoProfileSwitch(); + List profileSwitches; + QueryBuilder queryBuilder = daoProfileSwitch.queryBuilder(); + queryBuilder.orderBy("date", ascending); + queryBuilder.limit(100L); + Where where = queryBuilder.where(); + where.between("date", from, to); + PreparedQuery preparedQuery = queryBuilder.prepare(); + profileSwitches = daoProfileSwitch.query(preparedQuery); + return profileSwitches; + } catch (SQLException e) { + log.error("Unhandled exception", e); + } + return new ArrayList<>(); + } + public boolean createOrUpdate(ProfileSwitch profileSwitch) { try { ProfileSwitch old; @@ -1547,9 +1718,9 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { class PostRunnable implements Runnable { public void run() { if (L.isEnabled(L.DATABASE)) - log.debug("Firing EventProfileSwitchChange"); - MainApp.bus().post(new EventReloadProfileSwitchData()); - MainApp.bus().post(new EventProfileSwitchChange()); + log.debug("Firing EventProfileNeedsUpdate"); + RxBus.INSTANCE.send(new EventReloadProfileSwitchData()); + RxBus.INSTANCE.send(new EventProfileNeedsUpdate()); scheduledProfileSwitchEventPost = null; } } @@ -1656,5 +1827,67 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { return null; } + // ---------------- Insight history handling --------------- + + public void createOrUpdate(InsightHistoryOffset offset) { + try { + getDaoInsightHistoryOffset().createOrUpdate(offset); + } catch (SQLException e) { + log.error("Unhandled exception", e); + } + } + + public InsightHistoryOffset getInsightHistoryOffset(String pumpSerial) { + try { + return getDaoInsightHistoryOffset().queryForId(pumpSerial); + } catch (SQLException e) { + log.error("Unhandled exception", e); + } + return null; + } + + public void createOrUpdate(InsightBolusID bolusID) { + try { + getDaoInsightBolusID().createOrUpdate(bolusID); + } catch (SQLException e) { + log.error("Unhandled exception", e); + } + } + + public InsightBolusID getInsightBolusID(String pumpSerial, int bolusID, long timestamp) { + try { + return getDaoInsightBolusID().queryBuilder() + .where().eq("pumpSerial", pumpSerial) + .and().eq("bolusID", bolusID) + .and().between("timestamp", timestamp - 259200000, timestamp + 259200000) + .queryForFirst(); + } catch (SQLException e) { + log.error("Unhandled exception", e); + } + return null; + } + + public void createOrUpdate(InsightPumpID pumpID) { + try { + getDaoInsightPumpID().createOrUpdate(pumpID); + } catch (SQLException e) { + log.error("Unhandled exception", e); + } + } + + public InsightPumpID getPumpStoppedEvent(String pumpSerial, long before) { + try { + return getDaoInsightPumpID().queryBuilder() + .orderBy("timestamp", false) + .where().eq("pumpSerial", pumpSerial) + .and().in("eventType", "PumpStopped", "PumpPaused") + .and().lt("timestamp", before) + .queryForFirst(); + } catch (SQLException e) { + log.error("Unhandled exception", e); + } + return null; + } + // ---------------- Food handling --------------- } diff --git a/app/src/main/java/info/nightscout/androidaps/db/DbObjectBase.java b/app/src/main/java/info/nightscout/androidaps/db/DbObjectBase.java new file mode 100644 index 0000000000..a0c7f4bd7b --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/db/DbObjectBase.java @@ -0,0 +1,9 @@ +package info.nightscout.androidaps.db; + +public interface DbObjectBase { + + long getDate(); + + long getPumpId(); + +} diff --git a/app/src/main/java/info/nightscout/androidaps/db/ExtendedBolus.java b/app/src/main/java/info/nightscout/androidaps/db/ExtendedBolus.java index b4fda73ab6..25d2c308c1 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/ExtendedBolus.java +++ b/app/src/main/java/info/nightscout/androidaps/db/ExtendedBolus.java @@ -9,7 +9,6 @@ import android.graphics.Color; import com.j256.ormlite.field.DatabaseField; import com.j256.ormlite.table.DatabaseTable; -import org.json.JSONException; import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -19,17 +18,19 @@ import java.util.Objects; import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.data.Iob; import info.nightscout.androidaps.data.IobTotal; +import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.interfaces.InsulinInterface; import info.nightscout.androidaps.interfaces.Interval; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.Overview.graphExtensions.DataPointWithLabelInterface; -import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLabelGraphSeries; -import info.nightscout.androidaps.plugins.Treatments.Treatment; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.DecimalFormatter; -import info.nightscout.utils.JsonHelper; -import info.nightscout.utils.Round; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.general.overview.graphExtensions.DataPointWithLabelInterface; +import info.nightscout.androidaps.plugins.general.overview.graphExtensions.PointsWithLabelGraphSeries; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult; +import info.nightscout.androidaps.plugins.treatments.Treatment; +import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.DecimalFormatter; +import info.nightscout.androidaps.utils.JsonHelper; +import info.nightscout.androidaps.utils.Round; /** * Created by mike on 21.05.2017. @@ -220,7 +221,7 @@ public class ExtendedBolus implements Interval, DataPointWithLabelInterface { IobTotal result = new IobTotal(time); InsulinInterface insulinInterface = ConfigBuilderPlugin.getPlugin().getActiveInsulin(); - int realDuration = getDurationToTime(time); + double realDuration = getDurationToTime(time); if (realDuration > 0) { double dia_ago = time - dia * 60 * 60 * 1000; @@ -248,6 +249,56 @@ public class ExtendedBolus implements Interval, DataPointWithLabelInterface { return result; } + public IobTotal iobCalc(long time, Profile profile, AutosensResult lastAutosensResult, boolean exercise_mode, int half_basal_exercise_target, boolean isTempTarget) { + IobTotal result = new IobTotal(time); + InsulinInterface insulinInterface = ConfigBuilderPlugin.getPlugin().getActiveInsulin(); + + double realDuration = getDurationToTime(time); + double netBasalAmount = 0d; + + double sensitivityRatio = lastAutosensResult.ratio; + double normalTarget = 100; + + if (exercise_mode && isTempTarget && profile.getTarget() >= normalTarget + 5) { + // w/ target 100, temp target 110 = .89, 120 = 0.8, 140 = 0.67, 160 = .57, and 200 = .44 + // e.g.: Sensitivity ratio set to 0.8 based on temp target of 120; Adjusting basal from 1.65 to 1.35; ISF from 58.9 to 73.6 + double c = half_basal_exercise_target - normalTarget; + sensitivityRatio = c / (c + profile.getTarget() - normalTarget); + } + + if (realDuration > 0) { + double netBasalRate; + double dia_ago = time - dia * 60 * 60 * 1000; + int aboutFiveMinIntervals = (int) Math.ceil(realDuration / 5d); + double spacing = realDuration / aboutFiveMinIntervals; + + for (long j = 0L; j < aboutFiveMinIntervals; j++) { + // find middle of the interval + long calcdate = (long) (date + j * spacing * 60 * 1000 + 0.5d * spacing * 60 * 1000); + + double basalRate = profile.getBasal(calcdate); + double basalRateCorrection = basalRate * (sensitivityRatio - 1); + + + netBasalRate = absoluteRate() - basalRateCorrection; + + if (calcdate > dia_ago && calcdate <= time) { + double tempBolusSize = netBasalRate * spacing / 60d; + + Treatment tempBolusPart = new Treatment(); + tempBolusPart.insulin = tempBolusSize; + tempBolusPart.date = calcdate; + + Iob aIOB = insulinInterface.iobCalcForTreatment(tempBolusPart, time, dia); + result.iob += aIOB.iobContrib; + result.activity += aIOB.activityContrib; + result.extendedBolusInsulin += tempBolusPart.insulin; + } + } + } + return result; + } + public int getRealDuration() { return getDurationToTime(System.currentTimeMillis()); } diff --git a/app/src/main/java/info/nightscout/androidaps/db/ProfileSwitch.java b/app/src/main/java/info/nightscout/androidaps/db/ProfileSwitch.java index f7252e97df..62b963e9ef 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/ProfileSwitch.java +++ b/app/src/main/java/info/nightscout/androidaps/db/ProfileSwitch.java @@ -1,12 +1,13 @@ package info.nightscout.androidaps.db; import android.graphics.Color; -import android.support.annotation.Nullable; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import com.j256.ormlite.field.DatabaseField; import com.j256.ormlite.table.DatabaseTable; -import org.json.JSONException; import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -19,14 +20,16 @@ import info.nightscout.androidaps.R; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.interfaces.Interval; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; -import info.nightscout.androidaps.plugins.Overview.graphExtensions.DataPointWithLabelInterface; -import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLabelGraphSeries; -import info.nightscout.androidaps.plugins.Overview.notifications.Notification; -import info.nightscout.androidaps.plugins.ProfileLocal.LocalProfilePlugin; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.DecimalFormatter; -import info.nightscout.utils.T; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.general.overview.graphExtensions.DataPointWithLabelInterface; +import info.nightscout.androidaps.plugins.general.overview.graphExtensions.PointsWithLabelGraphSeries; +import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; +import info.nightscout.androidaps.plugins.profile.local.LocalProfilePlugin; +import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; +import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.DecimalFormatter; +import info.nightscout.androidaps.utils.T; @DatabaseTable(tableName = DatabaseHelper.DATABASE_PROFILESWITCHES) public class ProfileSwitch implements Interval, DataPointWithLabelInterface { @@ -79,12 +82,12 @@ public class ProfileSwitch implements Interval, DataPointWithLabelInterface { return this; } - public ProfileSwitch source(int source) { + public ProfileSwitch source(int source) { this.source = source; return this; } - public ProfileSwitch duration(int duration) { + public ProfileSwitch duration(int duration) { this.durationInMinutes = duration; return this; } @@ -104,11 +107,11 @@ public class ProfileSwitch implements Interval, DataPointWithLabelInterface { /** * Note: the name returned here is used as the PS name when uploading to NS. When such a PS is retrieved * again from NS, the added parts must be removed again, see - * {@link info.nightscout.utils.PercentageSplitter#pureName} + * {@link info.nightscout.androidaps.utils.PercentageSplitter#pureName} */ public String getCustomizedName() { String name = profileName; - if(LocalProfilePlugin.LOCAL_PROFILE.equals(name)){ + if (LocalProfilePlugin.LOCAL_PROFILE.equals(name)) { name = DecimalFormatter.to2Decimal(getProfileObject().percentageBasalSum()) + "U "; } if (isCPP) { @@ -157,7 +160,7 @@ public class ProfileSwitch implements Interval, DataPointWithLabelInterface { // -------- Interval interface --------- - Long cuttedEnd = null; + private Long cuttedEnd = null; public long durationInMsec() { return durationInMinutes * 60 * 1000L; @@ -213,16 +216,17 @@ public class ProfileSwitch implements Interval, DataPointWithLabelInterface { @Override public boolean isValid() { - boolean isValid = getProfileObject() != null && getProfileObject().isValid(DateUtil.dateAndTimeString(date)); - if (!isValid) + ProfileSwitch active = TreatmentsPlugin.getPlugin().getProfileSwitchFromHistory(DateUtil.now()); + long activeProfileSwitchDate = active != null ? active.date : -1L; + if (!isValid && date == activeProfileSwitchDate) createNotificationInvalidProfile(DateUtil.dateAndTimeString(date)); return isValid; } - public void createNotificationInvalidProfile(String detail) { + private void createNotificationInvalidProfile(String detail) { Notification notification = new Notification(Notification.ZERO_VALUE_IN_PROFILE, String.format(MainApp.gs(R.string.zerovalueinprofile), detail), Notification.LOW, 5); - MainApp.bus().post(new EventNewNotification(notification)); + RxBus.INSTANCE.send(new EventNewNotification(notification)); } public static boolean isEvent5minBack(List list, long time, boolean zeroDurationOnly) { @@ -291,6 +295,7 @@ public class ProfileSwitch implements Interval, DataPointWithLabelInterface { return Color.CYAN; } + @NonNull public String toString() { return "ProfileSwitch{" + "date=" + date + diff --git a/app/src/main/java/info/nightscout/androidaps/db/TDD.java b/app/src/main/java/info/nightscout/androidaps/db/TDD.java index 9ca849b7b6..93a228316c 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/TDD.java +++ b/app/src/main/java/info/nightscout/androidaps/db/TDD.java @@ -6,9 +6,8 @@ import com.j256.ormlite.table.DatabaseTable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.Objects; - import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil; /** * Created by mike on 20.09.2017. @@ -45,4 +44,16 @@ public class TDD { this.basal = basal; this.total = total; } + + + @Override + public String toString() { + return "TDD [" + + "date=" + date + + "date(str)=" + DateTimeUtil.toStringFromTimeInMillis(date) + + ", bolus=" + bolus + + ", basal=" + basal + + ", total=" + total + + ']'; + } } diff --git a/app/src/main/java/info/nightscout/androidaps/db/TempTarget.java b/app/src/main/java/info/nightscout/androidaps/db/TempTarget.java index 15692cbdfe..ef60d02911 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/TempTarget.java +++ b/app/src/main/java/info/nightscout/androidaps/db/TempTarget.java @@ -6,14 +6,16 @@ import com.j256.ormlite.table.DatabaseTable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.Date; import java.util.Objects; import info.nightscout.androidaps.Constants; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.interfaces.Interval; import info.nightscout.androidaps.logging.L; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.DecimalFormatter; +import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.DecimalFormatter; @DatabaseTable(tableName = DatabaseHelper.DATABASE_TEMPTARGETS) public class TempTarget implements Interval { @@ -192,4 +194,11 @@ public class TempTarget implements Interval { '}'; } + public String friendlyDescription(String units) { + return Profile.toTargetRangeString(low, high, Constants.MGDL, units) + + units + + "@" + MainApp.gs(R.string.mins, durationInMinutes) + + (reason != null && !reason.equals("") ? "(" + reason + ")" : ""); + } + } diff --git a/app/src/main/java/info/nightscout/androidaps/db/TemporaryBasal.java b/app/src/main/java/info/nightscout/androidaps/db/TemporaryBasal.java index eeaa8c0ee7..f2a10cf4a4 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/TemporaryBasal.java +++ b/app/src/main/java/info/nightscout/androidaps/db/TemporaryBasal.java @@ -8,7 +8,6 @@ import org.slf4j.LoggerFactory; import java.util.Objects; -import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.data.Iob; import info.nightscout.androidaps.data.IobTotal; @@ -16,19 +15,20 @@ import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.interfaces.InsulinInterface; import info.nightscout.androidaps.interfaces.Interval; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions; -import info.nightscout.androidaps.plugins.Treatments.Treatment; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.DecimalFormatter; -import info.nightscout.utils.SP; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult; +import info.nightscout.androidaps.plugins.treatments.Treatment; +import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.DecimalFormatter; +import info.nightscout.androidaps.utils.SP; /** * Created by mike on 21.05.2017. */ @DatabaseTable(tableName = DatabaseHelper.DATABASE_TEMPORARYBASALS) -public class TemporaryBasal implements Interval { +public class TemporaryBasal implements Interval, DbObjectBase { private static Logger log = LoggerFactory.getLogger(L.DATABASE); @DatabaseField(id = true) @@ -157,6 +157,14 @@ public class TemporaryBasal implements Interval { netExtendedRate = t.netExtendedRate; } + public void copyFromPump(TemporaryBasal t) { + durationInMinutes = t.durationInMinutes; + isAbsolute = t.isAbsolute; + percentRate = t.percentRate; + absoluteRate = t.absoluteRate; + pumpId = t.pumpId; + } + // -------- Interval interface --------- Long cuttedEnd = null; @@ -234,7 +242,7 @@ public class TemporaryBasal implements Interval { double netBasalAmount = 0d; if (realDuration > 0) { - double netBasalRate = 0d; + double netBasalRate; double dia = profile.getDia(); double dia_ago = time - dia * 60 * 60 * 1000; int aboutFiveMinIntervals = (int) Math.ceil(realDuration / 5d); @@ -244,10 +252,8 @@ public class TemporaryBasal implements Interval { // find middle of the interval long calcdate = (long) (date + j * tempBolusSpacing * 60 * 1000 + 0.5d * tempBolusSpacing * 60 * 1000); - Double basalRate = profile.getBasal(calcdate); + double basalRate = profile.getBasal(calcdate); - if (basalRate == null) - continue; if (isAbsolute) { netBasalRate = absoluteRate - basalRate; } else { @@ -277,6 +283,73 @@ public class TemporaryBasal implements Interval { return result; } + public IobTotal iobCalc(long time, Profile profile, AutosensResult lastAutosensResult, boolean exercise_mode, int half_basal_exercise_target, boolean isTempTarget) { + + if (isFakeExtended) { + log.error("iobCalc should only be called on Extended boluses separately"); + return new IobTotal(time); + } + + IobTotal result = new IobTotal(time); + InsulinInterface insulinInterface = ConfigBuilderPlugin.getPlugin().getActiveInsulin(); + + double realDuration = getDurationToTime(time); + double netBasalAmount = 0d; + + double sensitivityRatio = lastAutosensResult.ratio; + double normalTarget = 100; + + if (exercise_mode && isTempTarget && profile.getTarget() >= normalTarget + 5) { + // w/ target 100, temp target 110 = .89, 120 = 0.8, 140 = 0.67, 160 = .57, and 200 = .44 + // e.g.: Sensitivity ratio set to 0.8 based on temp target of 120; Adjusting basal from 1.65 to 1.35; ISF from 58.9 to 73.6 + double c = half_basal_exercise_target - normalTarget; + sensitivityRatio = c / (c + profile.getTarget() - normalTarget); + } + + if (realDuration > 0) { + double netBasalRate; + double dia = profile.getDia(); + double dia_ago = time - dia * 60 * 60 * 1000; + int aboutFiveMinIntervals = (int) Math.ceil(realDuration / 5d); + double tempBolusSpacing = realDuration / aboutFiveMinIntervals; + + for (long j = 0L; j < aboutFiveMinIntervals; j++) { + // find middle of the interval + long calcdate = (long) (date + j * tempBolusSpacing * 60 * 1000 + 0.5d * tempBolusSpacing * 60 * 1000); + + double basalRate = profile.getBasal(calcdate); + basalRate *= sensitivityRatio; + + if (isAbsolute) { + netBasalRate = absoluteRate - basalRate; + } else { + double abs = percentRate / 100d * profile.getBasal(calcdate); + netBasalRate = abs - basalRate; + } + + if (calcdate > dia_ago && calcdate <= time) { + double tempBolusSize = netBasalRate * tempBolusSpacing / 60d; + netBasalAmount += tempBolusSize; + + Treatment tempBolusPart = new Treatment(); + tempBolusPart.insulin = tempBolusSize; + tempBolusPart.date = calcdate; + + Iob aIOB = insulinInterface.iobCalcForTreatment(tempBolusPart, time, dia); + result.basaliob += aIOB.iobContrib; + result.activity += aIOB.activityContrib; + result.netbasalinsulin += tempBolusPart.insulin; + if (tempBolusPart.insulin > 0) { + result.hightempinsulin += tempBolusPart.insulin; + } + } + result.netRatio = netBasalRate; // ratio at the end of interval + } + } + result.netInsulin = netBasalAmount; + return result; + } + public int getRealDuration() { return getDurationToTime(System.currentTimeMillis()); } @@ -332,8 +405,10 @@ public class TemporaryBasal implements Interval { if (isFakeExtended) { Profile profile = ProfileFunctions.getInstance().getProfile(); + if (profile == null) + return "null"; Double currentBasalRate = profile.getBasal(); - double rate = (currentBasalRate == null) ? 0d : (currentBasalRate + netExtendedRate); + double rate = currentBasalRate + netExtendedRate; return getCalcuatedPercentageIfNeeded() + DecimalFormatter.to2Decimal(rate) + "U/h (" + DecimalFormatter.to2Decimal(netExtendedRate) + "E) @" + DateUtil.timeString(date) + " " + getRealDuration() + "/" + durationInMinutes + "'"; @@ -351,12 +426,14 @@ public class TemporaryBasal implements Interval { public String toStringShort() { if (isAbsolute || isFakeExtended) { - double rate = 0d; + double rate; if (isFakeExtended) { Profile profile = ProfileFunctions.getInstance().getProfile(); - Double currentBasalRate = profile.getBasal(); - rate = (currentBasalRate == null) ? 0d : (currentBasalRate + netExtendedRate); - } else if (isAbsolute) { + if (profile == null) + return "null"; + double currentBasalRate = profile.getBasal(); + rate = currentBasalRate + netExtendedRate; + } else { rate = absoluteRate; } @@ -376,24 +453,25 @@ public class TemporaryBasal implements Interval { } private String getCalcuatedPercentageIfNeeded() { + Profile profile = ProfileFunctions.getInstance().getProfile(); + + if (profile == null) + return "null"; + if (isAbsolute || isFakeExtended) { - double rate = 0d; + double rate; if (isFakeExtended) { - Profile profile = ProfileFunctions.getInstance().getProfile(); - Double currentBasalRate = profile.getBasal(); - rate = (currentBasalRate == null) ? 0d : (currentBasalRate + netExtendedRate); - } else if (isAbsolute) { + double currentBasalRate = profile.getBasal(); + rate = currentBasalRate + netExtendedRate; + } else { rate = absoluteRate; } if (SP.getBoolean(R.string.key_danar_visualizeextendedaspercentage, false) && SP.getBoolean(R.string.key_danar_useextended, false)) { - Profile profile = ProfileFunctions.getInstance().getProfile(); - if (profile != null) { - double basal = profile.getBasal(); - if (basal != 0) { - return Math.round(rate * 100d / basal) + "% "; - } + double basal = profile.getBasal(); + if (basal != 0) { + return Math.round(rate * 100d / basal) + "% "; } } } @@ -401,14 +479,18 @@ public class TemporaryBasal implements Interval { } public String toStringVeryShort() { + Profile profile = ProfileFunctions.getInstance().getProfile(); + + if (profile == null) + return "null"; + if (isAbsolute || isFakeExtended) { - double rate = 0d; + double rate; if (isFakeExtended) { - Profile profile = ProfileFunctions.getInstance().getProfile(); - Double currentBasalRate = profile.getBasal(); - rate = (currentBasalRate == null) ? 0d : (currentBasalRate + netExtendedRate); - } else if (isAbsolute) { + double currentBasalRate = profile.getBasal(); + rate = currentBasalRate + netExtendedRate; + } else { rate = absoluteRate; } return DecimalFormatter.to2Decimal(rate) + "U/h "; @@ -417,4 +499,13 @@ public class TemporaryBasal implements Interval { } } + @Override + public long getDate() { + return this.date; + } + + @Override + public long getPumpId() { + return this.pumpId; + } } diff --git a/app/src/main/java/info/nightscout/androidaps/events/Event.java b/app/src/main/java/info/nightscout/androidaps/events/Event.java deleted file mode 100644 index 864d55d6f7..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/events/Event.java +++ /dev/null @@ -1,16 +0,0 @@ -package info.nightscout.androidaps.events; - -import org.apache.commons.lang3.builder.ReflectionToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; - -/** Base class for all events posted on the event bus. */ -public abstract class Event { - static { - ReflectionToStringBuilder.setDefaultStyle(ToStringStyle.SHORT_PREFIX_STYLE); - } - - @Override - public String toString() { - return ReflectionToStringBuilder.toString(this); - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/events/Event.kt b/app/src/main/java/info/nightscout/androidaps/events/Event.kt new file mode 100644 index 0000000000..a44f65e836 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/events/Event.kt @@ -0,0 +1,18 @@ +package info.nightscout.androidaps.events + +import org.apache.commons.lang3.builder.ReflectionToStringBuilder +import org.apache.commons.lang3.builder.ToStringStyle + +/** Base class for all events posted on the event bus. */ +abstract class Event { + + override fun toString(): String { + return ReflectionToStringBuilder.toString(this) + } + + companion object { + init { + ReflectionToStringBuilder.setDefaultStyle(ToStringStyle.SHORT_PREFIX_STYLE) + } + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventAcceptOpenLoopChange.java b/app/src/main/java/info/nightscout/androidaps/events/EventAcceptOpenLoopChange.java deleted file mode 100644 index 2dfbf9ae35..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/events/EventAcceptOpenLoopChange.java +++ /dev/null @@ -1,5 +0,0 @@ -package info.nightscout.androidaps.events; - -/** Base class for events to update the UI, mostly a specific tab. */ -public class EventAcceptOpenLoopChange extends Event { -} diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventAcceptOpenLoopChange.kt b/app/src/main/java/info/nightscout/androidaps/events/EventAcceptOpenLoopChange.kt new file mode 100644 index 0000000000..552564edfc --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/events/EventAcceptOpenLoopChange.kt @@ -0,0 +1,3 @@ +package info.nightscout.androidaps.events + +class EventAcceptOpenLoopChange : Event() diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventAppExit.java b/app/src/main/java/info/nightscout/androidaps/events/EventAppExit.java deleted file mode 100644 index 9ce91a9a39..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/events/EventAppExit.java +++ /dev/null @@ -1,7 +0,0 @@ -package info.nightscout.androidaps.events; - -/** - * Created by mike on 07.07.2016. - */ -public class EventAppExit extends Event { -} diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventAppExit.kt b/app/src/main/java/info/nightscout/androidaps/events/EventAppExit.kt new file mode 100644 index 0000000000..640b586f5f --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/events/EventAppExit.kt @@ -0,0 +1,3 @@ +package info.nightscout.androidaps.events + +class EventAppExit : Event() \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventAppInitialized.java b/app/src/main/java/info/nightscout/androidaps/events/EventAppInitialized.java deleted file mode 100644 index 17262cfb85..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/events/EventAppInitialized.java +++ /dev/null @@ -1,8 +0,0 @@ -package info.nightscout.androidaps.events; - -/** - * Created by mike on 23.01.2018. - */ - -public class EventAppInitialized extends Event { -} diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventAppInitialized.kt b/app/src/main/java/info/nightscout/androidaps/events/EventAppInitialized.kt new file mode 100644 index 0000000000..293f9698f2 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/events/EventAppInitialized.kt @@ -0,0 +1,3 @@ +package info.nightscout.androidaps.events + +class EventAppInitialized : Event() \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventBolusRequested.java b/app/src/main/java/info/nightscout/androidaps/events/EventBolusRequested.java deleted file mode 100644 index cb727758bb..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/events/EventBolusRequested.java +++ /dev/null @@ -1,21 +0,0 @@ -package info.nightscout.androidaps.events; - -/** - * Created by adrian on 07/02/17. - */ - -public class EventBolusRequested extends Event { - private double amount; - - public EventBolusRequested (double amount){ - this.amount = amount; - } - - public double getAmount() { - return amount; - } - - public void setAmount(double amount) { - this.amount = amount; - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventBolusRequested.kt b/app/src/main/java/info/nightscout/androidaps/events/EventBolusRequested.kt new file mode 100644 index 0000000000..a528ef1656 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/events/EventBolusRequested.kt @@ -0,0 +1,3 @@ +package info.nightscout.androidaps.events + +class EventBolusRequested(var amount: Double) : Event() \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventCareportalEventChange.java b/app/src/main/java/info/nightscout/androidaps/events/EventCareportalEventChange.java deleted file mode 100644 index 9b47ed39cb..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/events/EventCareportalEventChange.java +++ /dev/null @@ -1,8 +0,0 @@ -package info.nightscout.androidaps.events; - -/** - * Created by mike on 25.05.2017. - */ - -public class EventCareportalEventChange extends Event { -} diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventCareportalEventChange.kt b/app/src/main/java/info/nightscout/androidaps/events/EventCareportalEventChange.kt new file mode 100644 index 0000000000..e7d52d86c0 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/events/EventCareportalEventChange.kt @@ -0,0 +1,3 @@ +package info.nightscout.androidaps.events + +class EventCareportalEventChange : Event() diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventChargingState.java b/app/src/main/java/info/nightscout/androidaps/events/EventChargingState.java deleted file mode 100644 index bcd9061133..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/events/EventChargingState.java +++ /dev/null @@ -1,13 +0,0 @@ -package info.nightscout.androidaps.events; - -public class EventChargingState { - - public boolean isCharging = false; - - public EventChargingState() {} - - public EventChargingState(boolean isCharging) { - this.isCharging = isCharging; - } - -} diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventChargingState.kt b/app/src/main/java/info/nightscout/androidaps/events/EventChargingState.kt new file mode 100644 index 0000000000..f9ff60a71d --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/events/EventChargingState.kt @@ -0,0 +1,3 @@ +package info.nightscout.androidaps.events + +class EventChargingState(val isCharging: Boolean) : Event() diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventConfigBuilderChange.java b/app/src/main/java/info/nightscout/androidaps/events/EventConfigBuilderChange.java deleted file mode 100644 index ad5f558fe8..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/events/EventConfigBuilderChange.java +++ /dev/null @@ -1,8 +0,0 @@ -package info.nightscout.androidaps.events; - -/** - * Created by mike on 17.02.2017. - */ - -public class EventConfigBuilderChange extends Event { -} diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventConfigBuilderChange.kt b/app/src/main/java/info/nightscout/androidaps/events/EventConfigBuilderChange.kt new file mode 100644 index 0000000000..b674374fad --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/events/EventConfigBuilderChange.kt @@ -0,0 +1,3 @@ +package info.nightscout.androidaps.events + +class EventConfigBuilderChange : Event() diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventCustomActionsChanged.kt b/app/src/main/java/info/nightscout/androidaps/events/EventCustomActionsChanged.kt new file mode 100644 index 0000000000..d75bf612ce --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/events/EventCustomActionsChanged.kt @@ -0,0 +1,3 @@ +package info.nightscout.androidaps.events + +class EventCustomActionsChanged : Event() diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventCustomCalculationFinished.java b/app/src/main/java/info/nightscout/androidaps/events/EventCustomCalculationFinished.java deleted file mode 100644 index e52761dc58..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/events/EventCustomCalculationFinished.java +++ /dev/null @@ -1,8 +0,0 @@ -package info.nightscout.androidaps.events; - -/** - * Created by mike on 13.02.2018. - */ - -public class EventCustomCalculationFinished extends Event { -} diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventCustomCalculationFinished.kt b/app/src/main/java/info/nightscout/androidaps/events/EventCustomCalculationFinished.kt new file mode 100644 index 0000000000..f6092b395d --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/events/EventCustomCalculationFinished.kt @@ -0,0 +1,3 @@ +package info.nightscout.androidaps.events + +class EventCustomCalculationFinished : Event() \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventExtendedBolusChange.java b/app/src/main/java/info/nightscout/androidaps/events/EventExtendedBolusChange.java deleted file mode 100644 index 8881b0ecc1..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/events/EventExtendedBolusChange.java +++ /dev/null @@ -1,8 +0,0 @@ -package info.nightscout.androidaps.events; - -/** - * Created by mike on 15.05.2017. - */ - -public class EventExtendedBolusChange extends Event { -} diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventExtendedBolusChange.kt b/app/src/main/java/info/nightscout/androidaps/events/EventExtendedBolusChange.kt new file mode 100644 index 0000000000..4ed0ca5ffe --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/events/EventExtendedBolusChange.kt @@ -0,0 +1,3 @@ +package info.nightscout.androidaps.events + +class EventExtendedBolusChange : EventLoop() diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventFeatureRunning.java b/app/src/main/java/info/nightscout/androidaps/events/EventFeatureRunning.java deleted file mode 100644 index 0d07cd6c61..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/events/EventFeatureRunning.java +++ /dev/null @@ -1,36 +0,0 @@ -package info.nightscout.androidaps.events; - -/** - * Created by jamorham on 07/02/2018. - * - * Event to indicate that an app feature is being used, for example bolus wizard being opened - * - * The purpose this has been created for is to enable opportunistic connection to the pump - * so that it is already connected before the user wishes to enact a pump function - * - */ - -public class EventFeatureRunning extends Event { - - private Feature feature = Feature.UNKNOWN; - - public EventFeatureRunning() { - } - - public EventFeatureRunning(Feature feature) { - this.feature = feature; - } - - public Feature getFeature() { - return feature; - } - - public enum Feature { - UNKNOWN, - MAIN, - WIZARD, - - JUST_ADD_MORE_HERE - } - -} diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventFoodDatabaseChanged.java b/app/src/main/java/info/nightscout/androidaps/events/EventFoodDatabaseChanged.java deleted file mode 100644 index 48e6be3a14..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/events/EventFoodDatabaseChanged.java +++ /dev/null @@ -1,8 +0,0 @@ -package info.nightscout.androidaps.events; - -/** - * Created by mike on 20.09.2017. - */ - -public class EventFoodDatabaseChanged extends Event { -} diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventFoodDatabaseChanged.kt b/app/src/main/java/info/nightscout/androidaps/events/EventFoodDatabaseChanged.kt new file mode 100644 index 0000000000..83402c3cb6 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/events/EventFoodDatabaseChanged.kt @@ -0,0 +1,3 @@ +package info.nightscout.androidaps.events + +class EventFoodDatabaseChanged : Event() \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventInitializationChanged.java b/app/src/main/java/info/nightscout/androidaps/events/EventInitializationChanged.java deleted file mode 100644 index f2bef1d3d0..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/events/EventInitializationChanged.java +++ /dev/null @@ -1,8 +0,0 @@ -package info.nightscout.androidaps.events; - -/** - * Created by mike on 13.12.2016. - */ - -public class EventInitializationChanged extends Event { -} diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventInitializationChanged.kt b/app/src/main/java/info/nightscout/androidaps/events/EventInitializationChanged.kt new file mode 100644 index 0000000000..33ab0062c5 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/events/EventInitializationChanged.kt @@ -0,0 +1,3 @@ +package info.nightscout.androidaps.events + +class EventInitializationChanged : Event() diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventLocationChange.kt b/app/src/main/java/info/nightscout/androidaps/events/EventLocationChange.kt new file mode 100644 index 0000000000..fee6c9f800 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/events/EventLocationChange.kt @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.events + +import android.location.Location + +class EventLocationChange(var location: Location) : Event() diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventLoop.java b/app/src/main/java/info/nightscout/androidaps/events/EventLoop.java deleted file mode 100644 index d694d52537..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/events/EventLoop.java +++ /dev/null @@ -1,5 +0,0 @@ -package info.nightscout.androidaps.events; - -/** Supeclass for all events concerned with input or output into or from the LoopPlugin. */ -public abstract class EventLoop extends Event { -} diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventLoop.kt b/app/src/main/java/info/nightscout/androidaps/events/EventLoop.kt new file mode 100644 index 0000000000..dd28e2323b --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/events/EventLoop.kt @@ -0,0 +1,4 @@ +package info.nightscout.androidaps.events + +/** Supeclass for all events concerned with input or output into or from the LoopPlugin. */ +abstract class EventLoop : Event() diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventNetworkChange.java b/app/src/main/java/info/nightscout/androidaps/events/EventNetworkChange.java deleted file mode 100644 index 57050bdcc9..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/events/EventNetworkChange.java +++ /dev/null @@ -1,17 +0,0 @@ -package info.nightscout.androidaps.events; - - -import info.nightscout.utils.StringUtils; - -public class EventNetworkChange extends Event { - - public boolean mobileConnected = false; - public boolean wifiConnected = false; - - public String ssid = ""; - public boolean roaming = false; - - public String getSsid() { - return StringUtils.removeSurroundingQuotes(ssid); - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventNetworkChange.kt b/app/src/main/java/info/nightscout/androidaps/events/EventNetworkChange.kt new file mode 100644 index 0000000000..62c8bdd13e --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/events/EventNetworkChange.kt @@ -0,0 +1,16 @@ +package info.nightscout.androidaps.events + +import info.nightscout.androidaps.utils.StringUtils + +class EventNetworkChange : Event() { + + var mobileConnected = false + var wifiConnected = false + + var ssid = "" + var roaming = false + + fun connectedSsid(): String { + return StringUtils.removeSurroundingQuotes(ssid) + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventNewBG.java b/app/src/main/java/info/nightscout/androidaps/events/EventNewBG.java deleted file mode 100644 index dc4d434e0a..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/events/EventNewBG.java +++ /dev/null @@ -1,17 +0,0 @@ -package info.nightscout.androidaps.events; - -import android.support.annotation.Nullable; - -import info.nightscout.androidaps.db.BgReading; - -/** - * Created by mike on 05.06.2016. - */ -public class EventNewBG extends EventLoop { - @Nullable - public final BgReading bgReading; - - public EventNewBG(BgReading bgReading) { - this.bgReading = bgReading; - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventNewBG.kt b/app/src/main/java/info/nightscout/androidaps/events/EventNewBG.kt new file mode 100644 index 0000000000..08c05407c9 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/events/EventNewBG.kt @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.events + +import info.nightscout.androidaps.db.BgReading + +class EventNewBG(val bgReading: BgReading?) : EventLoop() \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventNewBasalProfile.java b/app/src/main/java/info/nightscout/androidaps/events/EventNewBasalProfile.java deleted file mode 100644 index f26a310b6b..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/events/EventNewBasalProfile.java +++ /dev/null @@ -1,7 +0,0 @@ -package info.nightscout.androidaps.events; - -/** - * Created by mike on 04.06.2016. - */ -public class EventNewBasalProfile extends Event { -} diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventNewBasalProfile.kt b/app/src/main/java/info/nightscout/androidaps/events/EventNewBasalProfile.kt new file mode 100644 index 0000000000..2ffa5a9724 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/events/EventNewBasalProfile.kt @@ -0,0 +1,3 @@ +package info.nightscout.androidaps.events + +class EventNewBasalProfile : Event() \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventNsFood.java b/app/src/main/java/info/nightscout/androidaps/events/EventNsFood.java deleted file mode 100644 index 90b6f5681b..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/events/EventNsFood.java +++ /dev/null @@ -1,35 +0,0 @@ -package info.nightscout.androidaps.events; - -import android.os.Bundle; - -/** - * Event which is published with data fetched from NightScout specific for the - * Food-class. - * - * Payload is the from NS retrieved JSON-String which should be handled by all - * subscriber. - */ - -public class EventNsFood extends Event { - - public static final int ADD = 0; - public static final int UPDATE = 1; - public static final int REMOVE = 2; - - private final int mode; - - private final Bundle payload; - - public EventNsFood(int mode, Bundle payload) { - this.mode = mode; - this.payload = payload; - } - - public int getMode() { - return mode; - } - - public Bundle getPayload() { - return payload; - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventNsFood.kt b/app/src/main/java/info/nightscout/androidaps/events/EventNsFood.kt new file mode 100644 index 0000000000..2f34e76c85 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/events/EventNsFood.kt @@ -0,0 +1,19 @@ +package info.nightscout.androidaps.events + +import android.os.Bundle + +/** + * Event which is published with data fetched from NightScout specific for the + * Food-class. + * + * Payload is the from NS retrieved JSON-String which should be handled by all + * subscriber. + */ + +class EventNsFood(val mode: Int, val payload: Bundle) : Event() { + companion object { + val ADD = 0 + val UPDATE = 1 + val REMOVE = 2 + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventNsTreatment.java b/app/src/main/java/info/nightscout/androidaps/events/EventNsTreatment.java deleted file mode 100644 index 2c5ba6c9c0..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/events/EventNsTreatment.java +++ /dev/null @@ -1,36 +0,0 @@ -package info.nightscout.androidaps.events; - -import org.json.JSONObject; - - -/** - * Event which is published with data fetched from NightScout specific for the - * Treatment-class. - *

- * Payload is the from NS retrieved JSON-String which should be handled by all - * subscriber. - */ - -public class EventNsTreatment extends Event { - - public static final int ADD = 0; - public static final int UPDATE = 1; - public static final int REMOVE = 2; - - private final int mode; - - private final JSONObject payload; - - public EventNsTreatment(int mode, JSONObject payload) { - this.mode = mode; - this.payload = payload; - } - - public int getMode() { - return mode; - } - - public JSONObject getPayload() { - return payload; - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventNsTreatment.kt b/app/src/main/java/info/nightscout/androidaps/events/EventNsTreatment.kt new file mode 100644 index 0000000000..149894c221 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/events/EventNsTreatment.kt @@ -0,0 +1,21 @@ +package info.nightscout.androidaps.events + +import org.json.JSONObject + + +/** + * Event which is published with data fetched from NightScout specific for the + * Treatment-class. + * + * + * Payload is the from NS retrieved JSON-String which should be handled by all + * subscriber. + */ + +class EventNsTreatment(val mode: Int, val payload: JSONObject) : Event() { + companion object { + val ADD = 0 + val UPDATE = 1 + val REMOVE = 2 + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventPreferenceChange.java b/app/src/main/java/info/nightscout/androidaps/events/EventPreferenceChange.java deleted file mode 100644 index f23d4e802a..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/events/EventPreferenceChange.java +++ /dev/null @@ -1,25 +0,0 @@ -package info.nightscout.androidaps.events; - -import info.nightscout.androidaps.MainApp; - -/** - * Created by mike on 19.06.2016. - */ -public class EventPreferenceChange extends Event { - public String changedKey; - public EventPreferenceChange(String key) { - changedKey = key; - } - - public EventPreferenceChange(int resourceID) { - changedKey = MainApp.gs(resourceID); - } - - public boolean isChanged(int id) { - return changedKey.equals(MainApp.gs(id)); - } - - public boolean isChanged(String id) { - return changedKey.equals(id); - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventPreferenceChange.kt b/app/src/main/java/info/nightscout/androidaps/events/EventPreferenceChange.kt new file mode 100644 index 0000000000..d224d75df1 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/events/EventPreferenceChange.kt @@ -0,0 +1,19 @@ +package info.nightscout.androidaps.events + +import info.nightscout.androidaps.MainApp + +class EventPreferenceChange : Event { + private var changedKey: String? = null + + constructor(key: String) { + changedKey = key + } + + constructor(resourceID: Int) { + changedKey = MainApp.gs(resourceID) + } + + fun isChanged(id: Int): Boolean { + return changedKey == MainApp.gs(id) + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventProfileNeedsUpdate.kt b/app/src/main/java/info/nightscout/androidaps/events/EventProfileNeedsUpdate.kt new file mode 100644 index 0000000000..2baf1db945 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/events/EventProfileNeedsUpdate.kt @@ -0,0 +1,3 @@ +package info.nightscout.androidaps.events + +class EventProfileNeedsUpdate : Event() \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventProfileStoreChanged.java b/app/src/main/java/info/nightscout/androidaps/events/EventProfileStoreChanged.java deleted file mode 100644 index 0b2d933c12..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/events/EventProfileStoreChanged.java +++ /dev/null @@ -1,4 +0,0 @@ -package info.nightscout.androidaps.events; - -public class EventProfileStoreChanged extends Event { -} diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventProfileStoreChanged.kt b/app/src/main/java/info/nightscout/androidaps/events/EventProfileStoreChanged.kt new file mode 100644 index 0000000000..0e839ca2d3 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/events/EventProfileStoreChanged.kt @@ -0,0 +1,3 @@ +package info.nightscout.androidaps.events + +class EventProfileStoreChanged : Event() diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventProfileSwitchChange.java b/app/src/main/java/info/nightscout/androidaps/events/EventProfileSwitchChange.java deleted file mode 100644 index 7bab9d4518..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/events/EventProfileSwitchChange.java +++ /dev/null @@ -1,8 +0,0 @@ -package info.nightscout.androidaps.events; - -/** - * Created by mike on 02.06.2017. - */ - -public class EventProfileSwitchChange extends Event { -} diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventPumpStatusChanged.java b/app/src/main/java/info/nightscout/androidaps/events/EventPumpStatusChanged.java deleted file mode 100644 index 6729a4e703..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/events/EventPumpStatusChanged.java +++ /dev/null @@ -1,63 +0,0 @@ -package info.nightscout.androidaps.events; - -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.R; - -/** - * Created by mike on 19.02.2017. - */ - -public class EventPumpStatusChanged extends Event { - public static final int CONNECTING = 0; - public static final int CONNECTED = 1; - public static final int HANDSHAKING = 2; - public static final int PERFORMING = 3; - public static final int DISCONNECTING = 4; - public static final int DISCONNECTED = 5; - - public int sStatus = DISCONNECTED; - public int sSecondsElapsed = 0; - public String sPerfomingAction = ""; - - public static String error = ""; - - public EventPumpStatusChanged(int status) { - sStatus = status; - sSecondsElapsed = 0; - error = ""; - } - - public EventPumpStatusChanged(int status, int secondsElapsed) { - sStatus = status; - sSecondsElapsed = secondsElapsed; - error = ""; - } - - public EventPumpStatusChanged(int status, String error) { - sStatus = status; - sSecondsElapsed = 0; - this.error = error; - } - - public EventPumpStatusChanged(String action) { - sStatus = PERFORMING; - sSecondsElapsed = 0; - sPerfomingAction = action; - } - - public String textStatus() { - if (sStatus == CONNECTING) - return String.format(MainApp.gs(R.string.danar_history_connectingfor), sSecondsElapsed); - else if (sStatus == HANDSHAKING) - return MainApp.gs(R.string.handshaking); - else if (sStatus == CONNECTED) - return MainApp.gs(R.string.connected); - else if (sStatus == PERFORMING) - return sPerfomingAction; - else if (sStatus == DISCONNECTING) - return MainApp.gs(R.string.disconnecting); - else if (sStatus == DISCONNECTED) - return ""; - return ""; - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventPumpStatusChanged.kt b/app/src/main/java/info/nightscout/androidaps/events/EventPumpStatusChanged.kt new file mode 100644 index 0000000000..3d25bc1ca5 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/events/EventPumpStatusChanged.kt @@ -0,0 +1,62 @@ +package info.nightscout.androidaps.events + +import info.nightscout.androidaps.MainApp +import info.nightscout.androidaps.R + +class EventPumpStatusChanged : EventStatus { + + enum class Status { + CONNECTING, + CONNECTED, + HANDSHAKING, + PERFORMING, + DISCONNECTING, + DISCONNECTED + } + + var sStatus: Status = Status.DISCONNECTED + var sSecondsElapsed = 0 + var sPerfomingAction = "" + var error = "" + + constructor(status: Status) { + sStatus = status + sSecondsElapsed = 0 + error = "" + } + + constructor(status: Status, secondsElapsed: Int) { + sStatus = status + sSecondsElapsed = secondsElapsed + error = "" + } + + constructor(status: Status, error: String) { + sStatus = status + sSecondsElapsed = 0 + this.error = error + } + + constructor(action: String) { + sStatus = Status.PERFORMING + sSecondsElapsed = 0 + sPerfomingAction = action + } + + // status for startup wizard + override fun getStatus(): String { + if (sStatus == Status.CONNECTING) + return String.format(MainApp.gs(R.string.danar_history_connectingfor), sSecondsElapsed) + else if (sStatus == Status.HANDSHAKING) + return MainApp.gs(R.string.handshaking) + else if (sStatus == Status.CONNECTED) + return MainApp.gs(R.string.connected) + else if (sStatus == Status.PERFORMING) + return sPerfomingAction + else if (sStatus == Status.DISCONNECTING) + return MainApp.gs(R.string.disconnecting) + else if (sStatus == Status.DISCONNECTED) + return "" + return "" + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventRebuildTabs.kt b/app/src/main/java/info/nightscout/androidaps/events/EventRebuildTabs.kt new file mode 100644 index 0000000000..aa0db3467a --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/events/EventRebuildTabs.kt @@ -0,0 +1,3 @@ +package info.nightscout.androidaps.events + +class EventRebuildTabs @JvmOverloads constructor(var recreate: Boolean = false) : Event() diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventRefreshGui.java b/app/src/main/java/info/nightscout/androidaps/events/EventRefreshGui.java deleted file mode 100644 index 390ad8ea4f..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/events/EventRefreshGui.java +++ /dev/null @@ -1,14 +0,0 @@ -package info.nightscout.androidaps.events; - -/** - * Created by mike on 13.06.2016. - */ -public class EventRefreshGui extends Event { - public boolean recreate = false; - public EventRefreshGui(boolean recreate) { - this.recreate = recreate; - } - public EventRefreshGui(){ - this(false); - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventRefreshOverview.java b/app/src/main/java/info/nightscout/androidaps/events/EventRefreshOverview.java deleted file mode 100644 index 2ba78fa9ec..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/events/EventRefreshOverview.java +++ /dev/null @@ -1,13 +0,0 @@ -package info.nightscout.androidaps.events; - -/** - * Created by mike on 16.06.2017. - */ - -public class EventRefreshOverview extends Event { - public String from; - - public EventRefreshOverview(String from) { - this.from = from; - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventRefreshOverview.kt b/app/src/main/java/info/nightscout/androidaps/events/EventRefreshOverview.kt new file mode 100644 index 0000000000..533a25dd40 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/events/EventRefreshOverview.kt @@ -0,0 +1,3 @@ +package info.nightscout.androidaps.events + +class EventRefreshOverview(var from: String) : Event() diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventReloadProfileSwitchData.java b/app/src/main/java/info/nightscout/androidaps/events/EventReloadProfileSwitchData.java deleted file mode 100644 index 212e8856d9..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/events/EventReloadProfileSwitchData.java +++ /dev/null @@ -1,8 +0,0 @@ -package info.nightscout.androidaps.events; - -/** - * Created by mike on 12.06.2017. - */ - -public class EventReloadProfileSwitchData extends Event { -} diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventReloadProfileSwitchData.kt b/app/src/main/java/info/nightscout/androidaps/events/EventReloadProfileSwitchData.kt new file mode 100644 index 0000000000..6f6d848b5e --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/events/EventReloadProfileSwitchData.kt @@ -0,0 +1,3 @@ +package info.nightscout.androidaps.events + +class EventReloadProfileSwitchData : Event() diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventReloadTempBasalData.java b/app/src/main/java/info/nightscout/androidaps/events/EventReloadTempBasalData.java deleted file mode 100644 index 80125cbb4a..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/events/EventReloadTempBasalData.java +++ /dev/null @@ -1,8 +0,0 @@ -package info.nightscout.androidaps.events; - -/** - * Created by mike on 29.05.2017. - */ - -public class EventReloadTempBasalData extends Event { -} diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventReloadTempBasalData.kt b/app/src/main/java/info/nightscout/androidaps/events/EventReloadTempBasalData.kt new file mode 100644 index 0000000000..fa8f720896 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/events/EventReloadTempBasalData.kt @@ -0,0 +1,3 @@ +package info.nightscout.androidaps.events + +class EventReloadTempBasalData : Event() diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventReloadTreatmentData.java b/app/src/main/java/info/nightscout/androidaps/events/EventReloadTreatmentData.java deleted file mode 100644 index 0ba9b95ad7..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/events/EventReloadTreatmentData.java +++ /dev/null @@ -1,13 +0,0 @@ -package info.nightscout.androidaps.events; - -/** - * Created by mike on 29.05.2017. - */ - -public class EventReloadTreatmentData extends Event { - public Object next; - - public EventReloadTreatmentData(Object next) { - this.next = next; - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventReloadTreatmentData.kt b/app/src/main/java/info/nightscout/androidaps/events/EventReloadTreatmentData.kt new file mode 100644 index 0000000000..1f8b2938b9 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/events/EventReloadTreatmentData.kt @@ -0,0 +1,3 @@ +package info.nightscout.androidaps.events + +class EventReloadTreatmentData(var next: Event) : Event() diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventStatus.kt b/app/src/main/java/info/nightscout/androidaps/events/EventStatus.kt new file mode 100644 index 0000000000..193c3b1fdb --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/events/EventStatus.kt @@ -0,0 +1,6 @@ +package info.nightscout.androidaps.events + +// pass string to startup wizard +abstract class EventStatus :Event() { + abstract fun getStatus() : String +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventTempBasalChange.java b/app/src/main/java/info/nightscout/androidaps/events/EventTempBasalChange.java deleted file mode 100644 index 73660bb00e..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/events/EventTempBasalChange.java +++ /dev/null @@ -1,7 +0,0 @@ -package info.nightscout.androidaps.events; - -/** - * Created by mike on 05.06.2016. - */ -public class EventTempBasalChange extends EventLoop { -} diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventTempBasalChange.kt b/app/src/main/java/info/nightscout/androidaps/events/EventTempBasalChange.kt new file mode 100644 index 0000000000..3f3ecf732e --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/events/EventTempBasalChange.kt @@ -0,0 +1,3 @@ +package info.nightscout.androidaps.events + +class EventTempBasalChange : EventLoop() diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventTempTargetChange.java b/app/src/main/java/info/nightscout/androidaps/events/EventTempTargetChange.java deleted file mode 100644 index 4e3bf5c5f8..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/events/EventTempTargetChange.java +++ /dev/null @@ -1,8 +0,0 @@ -package info.nightscout.androidaps.events; - -/** - * Created by mike on 13.01.2017. - */ - -public class EventTempTargetChange extends Event { -} diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventTempTargetChange.kt b/app/src/main/java/info/nightscout/androidaps/events/EventTempTargetChange.kt new file mode 100644 index 0000000000..c108d6589c --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/events/EventTempTargetChange.kt @@ -0,0 +1,3 @@ +package info.nightscout.androidaps.events + +class EventTempTargetChange : Event() diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventTreatmentChange.java b/app/src/main/java/info/nightscout/androidaps/events/EventTreatmentChange.java deleted file mode 100644 index 989b24b7f9..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/events/EventTreatmentChange.java +++ /dev/null @@ -1,17 +0,0 @@ -package info.nightscout.androidaps.events; - -import android.support.annotation.Nullable; - -import info.nightscout.androidaps.plugins.Treatments.Treatment; - -/** - * Created by mike on 04.06.2016. - */ -public class EventTreatmentChange extends EventLoop { - @Nullable - public final Treatment treatment; - - public EventTreatmentChange(Treatment treatment) { - this.treatment = treatment; - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventTreatmentChange.kt b/app/src/main/java/info/nightscout/androidaps/events/EventTreatmentChange.kt new file mode 100644 index 0000000000..9cbc9d1563 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/events/EventTreatmentChange.kt @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.events + +import info.nightscout.androidaps.plugins.treatments.Treatment + +class EventTreatmentChange(val treatment: Treatment?) : EventLoop() diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventUpdateGui.java b/app/src/main/java/info/nightscout/androidaps/events/EventUpdateGui.java deleted file mode 100644 index 3471d2e851..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/events/EventUpdateGui.java +++ /dev/null @@ -1,5 +0,0 @@ -package info.nightscout.androidaps.events; - -/** Base class for events to update the UI, mostly a specific tab. */ -public abstract class EventUpdateGui extends Event { -} diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventUpdateGui.kt b/app/src/main/java/info/nightscout/androidaps/events/EventUpdateGui.kt new file mode 100644 index 0000000000..cc21e784b9 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/events/EventUpdateGui.kt @@ -0,0 +1,4 @@ +package info.nightscout.androidaps.events + +/** Base class for events to update the UI, mostly a specific tab. */ +abstract class EventUpdateGui : Event() diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/APSInterface.java b/app/src/main/java/info/nightscout/androidaps/interfaces/APSInterface.java index 2f37c47391..7d32e37ff0 100644 --- a/app/src/main/java/info/nightscout/androidaps/interfaces/APSInterface.java +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/APSInterface.java @@ -1,13 +1,14 @@ package info.nightscout.androidaps.interfaces; -import info.nightscout.androidaps.plugins.Loop.APSResult; +import info.nightscout.androidaps.plugins.aps.loop.APSResult; /** * Created by mike on 10.06.2016. */ public interface APSInterface { - public APSResult getLastAPSResult(); - public long getLastAPSRun(); + APSResult getLastAPSResult(); - public void invoke(String initiator, boolean tempBasalFallback); + long getLastAPSRun(); + + void invoke(String initiator, boolean tempBasalFallback); } diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/ConstraintsInterface.java b/app/src/main/java/info/nightscout/androidaps/interfaces/ConstraintsInterface.java index 5ac8cc83f7..14b2d549af 100644 --- a/app/src/main/java/info/nightscout/androidaps/interfaces/ConstraintsInterface.java +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/ConstraintsInterface.java @@ -35,6 +35,10 @@ public interface ConstraintsInterface { return value; } + default Constraint isSuperBolusEnabled(Constraint value) { + return value; + } + default Constraint applyBasalConstraints(Constraint absoluteRate, Profile profile) { return absoluteRate; } @@ -57,6 +61,6 @@ public interface ConstraintsInterface { default Constraint applyMaxIOBConstraints(Constraint maxIob) { return maxIob; - }; + } } diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/InsulinInterface.java b/app/src/main/java/info/nightscout/androidaps/interfaces/InsulinInterface.java index 34b14d9b5d..2ad36fb747 100644 --- a/app/src/main/java/info/nightscout/androidaps/interfaces/InsulinInterface.java +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/InsulinInterface.java @@ -1,7 +1,7 @@ package info.nightscout.androidaps.interfaces; import info.nightscout.androidaps.data.Iob; -import info.nightscout.androidaps.plugins.Treatments.Treatment; +import info.nightscout.androidaps.plugins.treatments.Treatment; /** * Created by mike on 17.04.2017. diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/PluginBase.java b/app/src/main/java/info/nightscout/androidaps/interfaces/PluginBase.java index a1a35b7413..f7c8e9ada4 100644 --- a/app/src/main/java/info/nightscout/androidaps/interfaces/PluginBase.java +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/PluginBase.java @@ -1,16 +1,23 @@ package info.nightscout.androidaps.interfaces; import android.os.SystemClock; -import android.support.v4.app.FragmentActivity; + +import androidx.appcompat.app.AlertDialog; +import androidx.fragment.app.FragmentActivity; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.events.EventConfigBuilderChange; +import info.nightscout.androidaps.events.EventRebuildTabs; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.configBuilder.EventConfigBuilderUpdateGui; import info.nightscout.androidaps.queue.CommandQueue; +import info.nightscout.androidaps.utils.SP; /** * Created by mike on 09.06.2016. @@ -38,17 +45,46 @@ public abstract class PluginBase { // Default always calls invoke // Plugins that have special constraints if they get switched to may override this method - public void switchAllowed(ConfigBuilderFragment.PluginViewHolder.PluginSwitcher pluginSwitcher, FragmentActivity activity) { - pluginSwitcher.invoke(); + public void switchAllowed(boolean newState, FragmentActivity activity, PluginType type) { + performPluginSwitch(newState, type); } -// public PluginType getType() { -// return mainType; -// } + protected void confirmPumpPluginActivation(boolean newState, FragmentActivity activity, PluginType type) { + if (type == PluginType.PUMP) { + boolean allowHardwarePump = SP.getBoolean("allow_hardware_pump", false); + if (allowHardwarePump || activity == null) { + performPluginSwitch(newState, type); + } else { + AlertDialog.Builder builder = new AlertDialog.Builder(activity); + builder.setMessage(R.string.allow_hardware_pump_text) + .setPositiveButton(R.string.yes, (dialog, id) -> { + performPluginSwitch(newState, type); + SP.putBoolean("allow_hardware_pump", true); + if (L.isEnabled(L.PUMP)) + log.debug("First time HW pump allowed!"); + }) + .setNegativeButton(R.string.cancel, (dialog, id) -> { + RxBus.INSTANCE.send(new EventConfigBuilderUpdateGui()); + if (L.isEnabled(L.PUMP)) + log.debug("User does not allow switching to HW pump!"); + }); + builder.create().show(); + } + } else { + performPluginSwitch(newState, type); + } + } -// public String getFragmentClass() { -// return fragmentClass; -// } + private void performPluginSwitch(boolean enabled, PluginType type) { + setPluginEnabled(type, enabled); + setFragmentVisible(type, enabled); + ConfigBuilderPlugin.getPlugin().processOnEnabledCategoryChanged(this, getType()); + ConfigBuilderPlugin.getPlugin().storeSettings("CheckedCheckboxEnabled"); + RxBus.INSTANCE.send(new EventRebuildTabs()); + RxBus.INSTANCE.send(new EventConfigBuilderChange()); + RxBus.INSTANCE.send(new EventConfigBuilderUpdateGui()); + ConfigBuilderPlugin.getPlugin().logPluginStatus(); + } public String getName() { if (pluginDescription.pluginName == -1) @@ -80,10 +116,6 @@ public abstract class PluginBase { return pluginDescription.preferencesId; } - public int getAdvancedPreferencesId() { - return pluginDescription.advancedPreferencesId; - } - public boolean isEnabled(PluginType type) { if (pluginDescription.alwaysEnabled && type == pluginDescription.mainType) return true; @@ -93,6 +125,8 @@ public abstract class PluginBase { return state == State.ENABLED && specialEnableCondition(); if (type == PluginType.CONSTRAINTS && pluginDescription.mainType == PluginType.PUMP && isEnabled(PluginType.PUMP)) return true; + if (type == PluginType.CONSTRAINTS && pluginDescription.mainType == PluginType.APS && isEnabled(PluginType.APS)) + return true; if (type == PluginType.PROFILE && pluginDescription.mainType == PluginType.PUMP) return isProfileInterfaceEnabled; return false; @@ -141,7 +175,7 @@ public abstract class PluginBase { } public boolean isFragmentVisible() { - if (pluginDescription.alwayVisible) + if (pluginDescription.alwaysVisible) return true; if (pluginDescription.neverVisible) return false; diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/PluginDescription.java b/app/src/main/java/info/nightscout/androidaps/interfaces/PluginDescription.java index 1634fc672d..5882c5870c 100644 --- a/app/src/main/java/info/nightscout/androidaps/interfaces/PluginDescription.java +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/PluginDescription.java @@ -3,7 +3,7 @@ package info.nightscout.androidaps.interfaces; public class PluginDescription { PluginType mainType = PluginType.GENERAL; String fragmentClass = null; - public boolean alwayVisible = false; + public boolean alwaysVisible = false; public boolean neverVisible = false; public boolean alwaysEnabled = false; boolean showInList = true; @@ -11,7 +11,6 @@ public class PluginDescription { int shortName = -1; int description = -1; int preferencesId = -1; - int advancedPreferencesId = -1; public boolean enableByDefault = false; public boolean visibleByDefault = false; @@ -30,8 +29,8 @@ public class PluginDescription { return this; } - public PluginDescription alwayVisible(boolean alwayVisible) { - this.alwayVisible = alwayVisible; + public PluginDescription alwaysVisible(boolean alwayVisible) { + this.alwaysVisible = alwayVisible; return this; } @@ -60,11 +59,6 @@ public class PluginDescription { return this; } - public PluginDescription advancedPreferencesId(int advancedPreferencesId) { - this.advancedPreferencesId = advancedPreferencesId; - return this; - } - public PluginDescription enableByDefault(boolean enableByDefault) { this.enableByDefault = enableByDefault; return this; diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/ProfileInterface.java b/app/src/main/java/info/nightscout/androidaps/interfaces/ProfileInterface.java index e3b368fe86..482278e437 100644 --- a/app/src/main/java/info/nightscout/androidaps/interfaces/ProfileInterface.java +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/ProfileInterface.java @@ -1,6 +1,6 @@ package info.nightscout.androidaps.interfaces; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import info.nightscout.androidaps.data.ProfileStore; diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/PumpDescription.java b/app/src/main/java/info/nightscout/androidaps/interfaces/PumpDescription.java index 34221b203f..e4a02883e8 100644 --- a/app/src/main/java/info/nightscout/androidaps/interfaces/PumpDescription.java +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/PumpDescription.java @@ -1,8 +1,8 @@ package info.nightscout.androidaps.interfaces; -import info.nightscout.androidaps.plugins.PumpCommon.defs.PumpCapability; -import info.nightscout.androidaps.plugins.PumpCommon.defs.PumpTempBasalType; -import info.nightscout.androidaps.plugins.PumpCommon.defs.PumpType; +import info.nightscout.androidaps.plugins.pump.common.defs.PumpCapability; +import info.nightscout.androidaps.plugins.pump.common.defs.PumpTempBasalType; +import info.nightscout.androidaps.plugins.pump.common.defs.PumpType; /** * Created by mike on 08.12.2016. diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/PumpInterface.java b/app/src/main/java/info/nightscout/androidaps/interfaces/PumpInterface.java index 614c6033d3..025f10076d 100644 --- a/app/src/main/java/info/nightscout/androidaps/interfaces/PumpInterface.java +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/PumpInterface.java @@ -2,9 +2,15 @@ package info.nightscout.androidaps.interfaces; import org.json.JSONObject; +import java.util.List; + import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.PumpEnactResult; +import info.nightscout.androidaps.plugins.common.ManufacturerType; +import info.nightscout.androidaps.plugins.general.actions.defs.CustomAction; +import info.nightscout.androidaps.plugins.general.actions.defs.CustomActionType; +import info.nightscout.androidaps.plugins.pump.common.defs.PumpType; /** * Created by mike on 04.06.2016. @@ -12,40 +18,64 @@ import info.nightscout.androidaps.data.PumpEnactResult; public interface PumpInterface { boolean isInitialized(); // true if pump status has been read and is ready to accept commands + boolean isSuspended(); // true if suspended (not delivering insulin) + boolean isBusy(); // if true pump is not ready to accept commands right now + boolean isConnected(); // true if BT connection is established + boolean isConnecting(); // true if BT connection is in progress + boolean isHandshakeInProgress(); // true if BT is connected but initial handshake is still in progress + void finishHandshaking(); // set initial handshake completed void connect(String reason); + void disconnect(String reason); + void stopConnecting(); void getPumpStatus(); // Upload to pump new basal profile PumpEnactResult setNewBasalProfile(Profile profile); + boolean isThisProfileSet(Profile profile); long lastDataTime(); double getBaseBasalRate(); // base basal rate, not temp basal + double getReservoirLevel(); + + int getBatteryLevel(); // in percent as integer + PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo); + void stopBolusDelivering(); + PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, Profile profile, boolean enforceNew); + PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, Profile profile, boolean enforceNew); + PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes); + //some pumps might set a very short temp close to 100% as cancelling a temp can be noisy //when the cancel request is requested by the user (forced), the pump should always do a real cancel PumpEnactResult cancelTempBasal(boolean enforceNew); + PumpEnactResult cancelExtendedBolus(); // Status to be passed to NS JSONObject getJSONStatus(Profile profile, String profileName); - String deviceID(); + + ManufacturerType manufacturer(); + + PumpType model(); + + String serialNumber(); // Pump capabilities PumpDescription getPumpDescription(); @@ -57,4 +87,16 @@ public interface PumpInterface { PumpEnactResult loadTDDs(); + boolean canHandleDST(); + + List getCustomActions(); + + void executeCustomAction(CustomActionType customActionType); + + /** + * This method will be called when time or Timezone changes, and pump driver can then do a specific action (for + * example update clock on pump). + */ + void timeDateOrTimeZoneChanged(); + } diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/SensitivityInterface.java b/app/src/main/java/info/nightscout/androidaps/interfaces/SensitivityInterface.java index f4514ad572..9d75382542 100644 --- a/app/src/main/java/info/nightscout/androidaps/interfaces/SensitivityInterface.java +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/SensitivityInterface.java @@ -1,7 +1,7 @@ package info.nightscout.androidaps.interfaces; -import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensResult; -import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin; /** * Created by mike on 24.06.2017. diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/TreatmentsInterface.java b/app/src/main/java/info/nightscout/androidaps/interfaces/TreatmentsInterface.java index dc437e04ab..43661b117a 100644 --- a/app/src/main/java/info/nightscout/androidaps/interfaces/TreatmentsInterface.java +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/TreatmentsInterface.java @@ -5,12 +5,13 @@ import java.util.List; import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.MealData; +import info.nightscout.androidaps.data.NonOverlappingIntervals; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.db.ExtendedBolus; import info.nightscout.androidaps.db.ProfileSwitch; import info.nightscout.androidaps.db.TempTarget; import info.nightscout.androidaps.db.TemporaryBasal; -import info.nightscout.androidaps.plugins.Treatments.Treatment; +import info.nightscout.androidaps.plugins.treatments.Treatment; import info.nightscout.androidaps.data.Intervals; import info.nightscout.androidaps.data.ProfileIntervals; @@ -25,12 +26,13 @@ public interface TreatmentsInterface { IobTotal getLastCalculationTreatments(); IobTotal getCalculationToTimeTreatments(long time); IobTotal getLastCalculationTempBasals(); - IobTotal getCalculationToTimeTempBasals(long time, Profile profile); + IobTotal getCalculationToTimeTempBasals(long time); MealData getMealData(); List getTreatmentsFromHistory(); List getTreatments5MinBackFromHistory(long time); + List getTreatmentsFromHistoryAfterTimestamp(long timestamp); long getLastBolusTime(); // real basals (not faked by extended bolus) @@ -42,7 +44,7 @@ public interface TreatmentsInterface { // basal that can be faked by extended boluses boolean isTempBasalInProgress(); TemporaryBasal getTempBasalFromHistory(long time); - Intervals getTemporaryBasalsFromHistory(); + NonOverlappingIntervals getTemporaryBasalsFromHistory(); boolean isInHistoryExtendedBoluslInProgress(); ExtendedBolus getExtendedBolusFromHistory(long time); @@ -63,4 +65,4 @@ public interface TreatmentsInterface { long oldestDataAvailable(); -} +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/logging/L.java b/app/src/main/java/info/nightscout/androidaps/logging/L.java index 0fde02f4ed..25b6750844 100644 --- a/app/src/main/java/info/nightscout/androidaps/logging/L.java +++ b/app/src/main/java/info/nightscout/androidaps/logging/L.java @@ -3,7 +3,7 @@ package info.nightscout.androidaps.logging; import java.util.ArrayList; import java.util.List; -import info.nightscout.utils.SP; +import info.nightscout.androidaps.utils.SP; public class L { @@ -77,7 +77,9 @@ public class L { public static final String CORE = "CORE"; public static final String AUTOSENS = "AUTOSENS"; + public static final String AUTOMATION = "AUTOMATION"; public static final String EVENTS = "EVENTS"; + public static final String GLUCOSE = "GLUCOSE"; public static final String BGSOURCE = "BGSOURCE"; public static final String OVERVIEW = "OVERVIEW"; public static final String NOTIFICATION = "NOTIFICATION"; @@ -86,6 +88,7 @@ public class L { public static final String DATAFOOD = "DATAFOOD"; public static final String DATATREATMENTS = "DATATREATMENTS"; public static final String NSCLIENT = "NSCLIENT"; + public static final String TIDEPOOL = "TIDEPOOL"; public static final String CONSTRAINTS = "CONSTRAINTS"; public static final String PUMP = "PUMP"; public static final String PUMPQUEUE = "PUMPQUEUE"; @@ -95,12 +98,16 @@ public class L { public static final String PROFILE = "PROFILE"; public static final String CONFIGBUILDER = "CONFIGBUILDER"; public static final String UI = "UI"; + public static final String LOCATION = "LOCATION"; + public static final String SMS = "SMS"; private static void initialize() { logElements = new ArrayList<>(); logElements.add(new LogElement(APS, true)); + logElements.add(new LogElement(AUTOMATION, true)); logElements.add(new LogElement(AUTOSENS, false)); logElements.add(new LogElement(BGSOURCE, true)); + logElements.add(new LogElement(GLUCOSE, false)); logElements.add(new LogElement(CONFIGBUILDER, false)); logElements.add(new LogElement(CONSTRAINTS, true)); logElements.add(new LogElement(CORE, true)); @@ -109,14 +116,17 @@ public class L { logElements.add(new LogElement(DATASERVICE, true)); logElements.add(new LogElement(DATATREATMENTS, true)); logElements.add(new LogElement(EVENTS, false, true)); + logElements.add(new LogElement(LOCATION, true)); logElements.add(new LogElement(NOTIFICATION, true)); logElements.add(new LogElement(NSCLIENT, true)); + logElements.add(new LogElement(TIDEPOOL, true)); logElements.add(new LogElement(OVERVIEW, true)); logElements.add(new LogElement(PROFILE, true)); logElements.add(new LogElement(PUMP, true)); logElements.add(new LogElement(PUMPBTCOMM, false)); logElements.add(new LogElement(PUMPCOMM, true)); logElements.add(new LogElement(PUMPQUEUE, true)); + logElements.add(new LogElement(SMS, true)); logElements.add(new LogElement(UI, true)); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Actions/ActionsFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Actions/ActionsFragment.java deleted file mode 100644 index a71b447d82..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Actions/ActionsFragment.java +++ /dev/null @@ -1,252 +0,0 @@ -package info.nightscout.androidaps.plugins.Actions; - - -import android.app.Activity; -import android.content.Intent; -import android.os.Bundle; -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentManager; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - -import com.crashlytics.android.answers.CustomEvent; -import com.squareup.otto.Subscribe; - -import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.activities.HistoryBrowseActivity; -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.activities.TDDStatsActivity; -import info.nightscout.androidaps.db.ExtendedBolus; -import info.nightscout.androidaps.db.TemporaryBasal; -import info.nightscout.androidaps.events.EventExtendedBolusChange; -import info.nightscout.androidaps.events.EventInitializationChanged; -import info.nightscout.androidaps.events.EventRefreshOverview; -import info.nightscout.androidaps.events.EventTempBasalChange; -import info.nightscout.androidaps.interfaces.PumpInterface; -import info.nightscout.androidaps.plugins.Actions.dialogs.FillDialog; -import info.nightscout.androidaps.plugins.Actions.dialogs.NewExtendedBolusDialog; -import info.nightscout.androidaps.plugins.Actions.dialogs.NewTempBasalDialog; -import info.nightscout.androidaps.plugins.Careportal.CareportalFragment; -import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog; -import info.nightscout.androidaps.plugins.Careportal.OptionsToShow; -import info.nightscout.androidaps.plugins.Common.SubscriberFragment; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions; -import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; -import info.nightscout.utils.FabricPrivacy; -import info.nightscout.utils.SingleClickButton; - -/** - * A simple {@link Fragment} subclass. - */ -public class ActionsFragment extends SubscriberFragment implements View.OnClickListener { - - static ActionsPlugin actionsPlugin = new ActionsPlugin(); - - static public ActionsPlugin getPlugin() { - return actionsPlugin; - } - - SingleClickButton profileSwitch; - SingleClickButton tempTarget; - SingleClickButton extendedBolus; - SingleClickButton extendedBolusCancel; - SingleClickButton tempBasal; - SingleClickButton tempBasalCancel; - SingleClickButton fill; - SingleClickButton tddStats; - SingleClickButton history; - - public ActionsFragment() { - super(); - } - - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - try { - View view = inflater.inflate(R.layout.actions_fragment, container, false); - - profileSwitch = (SingleClickButton) view.findViewById(R.id.actions_profileswitch); - tempTarget = (SingleClickButton) view.findViewById(R.id.actions_temptarget); - extendedBolus = (SingleClickButton) view.findViewById(R.id.actions_extendedbolus); - extendedBolusCancel = (SingleClickButton) view.findViewById(R.id.actions_extendedbolus_cancel); - tempBasal = (SingleClickButton) view.findViewById(R.id.actions_settempbasal); - tempBasalCancel = (SingleClickButton) view.findViewById(R.id.actions_canceltempbasal); - fill = (SingleClickButton) view.findViewById(R.id.actions_fill); - tddStats = view.findViewById(R.id.actions_tddstats); - history = view.findViewById(R.id.actions_historybrowser); - - profileSwitch.setOnClickListener(this); - tempTarget.setOnClickListener(this); - extendedBolus.setOnClickListener(this); - extendedBolusCancel.setOnClickListener(this); - tempBasal.setOnClickListener(this); - tempBasalCancel.setOnClickListener(this); - fill.setOnClickListener(this); - history.setOnClickListener(this); - tddStats.setOnClickListener(this); - - updateGUI(); - return view; - } catch (Exception e) { - FabricPrivacy.logException(e); - } - - return null; - } - - @Subscribe - public void onStatusEvent(final EventInitializationChanged ev) { - updateGUI(); - } - - @Subscribe - public void onStatusEvent(final EventRefreshOverview ev) { - updateGUI(); - } - - @Subscribe - public void onStatusEvent(final EventExtendedBolusChange ev) { - updateGUI(); - } - - @Subscribe - public void onStatusEvent(final EventTempBasalChange ev) { - updateGUI(); - } - - @Override - protected void updateGUI() { - Activity activity = getActivity(); - if (activity != null) - activity.runOnUiThread(new Runnable() { - @Override - public void run() { - if (ConfigBuilderPlugin.getPlugin().getActiveProfileInterface() != null && ConfigBuilderPlugin.getPlugin().getActiveProfileInterface().getProfile() != null) { - profileSwitch.setVisibility(View.VISIBLE); - } else { - profileSwitch.setVisibility(View.GONE); - } - - if (ProfileFunctions.getInstance().getProfile() == null) { - tempTarget.setVisibility(View.GONE); - extendedBolus.setVisibility(View.GONE); - extendedBolusCancel.setVisibility(View.GONE); - tempBasal.setVisibility(View.GONE); - tempBasalCancel.setVisibility(View.GONE); - fill.setVisibility(View.GONE); - return; - } - - final PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump(); - final boolean basalprofileEnabled = MainApp.isEngineeringModeOrRelease() - && pump.getPumpDescription().isSetBasalProfileCapable; - - if (!basalprofileEnabled || !pump.isInitialized() || pump.isSuspended()) - profileSwitch.setVisibility(View.GONE); - else - profileSwitch.setVisibility(View.VISIBLE); - - if (!pump.getPumpDescription().isExtendedBolusCapable || !pump.isInitialized() || pump.isSuspended() || pump.isFakingTempsByExtendedBoluses()) { - extendedBolus.setVisibility(View.GONE); - extendedBolusCancel.setVisibility(View.GONE); - } else { - ExtendedBolus activeExtendedBolus = TreatmentsPlugin.getPlugin().getExtendedBolusFromHistory(System.currentTimeMillis()); - if (activeExtendedBolus != null) { - extendedBolus.setVisibility(View.GONE); - extendedBolusCancel.setVisibility(View.VISIBLE); - extendedBolusCancel.setText(MainApp.gs(R.string.cancel) + " " + activeExtendedBolus.toString()); - } else { - extendedBolus.setVisibility(View.VISIBLE); - extendedBolusCancel.setVisibility(View.GONE); - } - } - - - if (!pump.getPumpDescription().isTempBasalCapable || !pump.isInitialized() || pump.isSuspended()) { - tempBasal.setVisibility(View.GONE); - tempBasalCancel.setVisibility(View.GONE); - } else { - final TemporaryBasal activeTemp = TreatmentsPlugin.getPlugin().getTempBasalFromHistory(System.currentTimeMillis()); - if (activeTemp != null) { - tempBasal.setVisibility(View.GONE); - tempBasalCancel.setVisibility(View.VISIBLE); - tempBasalCancel.setText(MainApp.gs(R.string.cancel) + " " + activeTemp.toStringShort()); - } else { - tempBasal.setVisibility(View.VISIBLE); - tempBasalCancel.setVisibility(View.GONE); - } - } - - if (!pump.getPumpDescription().isRefillingCapable || !pump.isInitialized() || pump.isSuspended()) - fill.setVisibility(View.GONE); - else - fill.setVisibility(View.VISIBLE); - - if (!Config.APS) - tempTarget.setVisibility(View.GONE); - else - tempTarget.setVisibility(View.VISIBLE); - - if (!ConfigBuilderPlugin.getPlugin().getActivePump().getPumpDescription().supportsTDDs) tddStats.setVisibility(View.GONE); - else tddStats.setVisibility(View.VISIBLE); - } - }); - } - - - @Override - public void onClick(View view) { - FragmentManager manager = getFragmentManager(); - switch (view.getId()) { - case R.id.actions_profileswitch: - NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog(); - final OptionsToShow profileswitch = CareportalFragment.PROFILESWITCH; - profileswitch.executeProfileSwitch = true; - newDialog.setOptions(profileswitch, R.string.careportal_profileswitch); - newDialog.show(manager, "NewNSTreatmentDialog"); - break; - case R.id.actions_temptarget: - NewNSTreatmentDialog newTTDialog = new NewNSTreatmentDialog(); - final OptionsToShow temptarget = CareportalFragment.TEMPTARGET; - temptarget.executeTempTarget = true; - newTTDialog.setOptions(temptarget, R.string.careportal_temporarytarget); - newTTDialog.show(manager, "NewNSTreatmentDialog"); - break; - case R.id.actions_extendedbolus: - NewExtendedBolusDialog newExtendedDialog = new NewExtendedBolusDialog(); - newExtendedDialog.show(manager, "NewExtendedDialog"); - break; - case R.id.actions_extendedbolus_cancel: - if (TreatmentsPlugin.getPlugin().isInHistoryExtendedBoluslInProgress()) { - ConfigBuilderPlugin.getPlugin().getCommandQueue().cancelExtended(null); - FabricPrivacy.getInstance().logCustom(new CustomEvent("CancelExtended")); - } - break; - case R.id.actions_canceltempbasal: - if (TreatmentsPlugin.getPlugin().isTempBasalInProgress()) { - ConfigBuilderPlugin.getPlugin().getCommandQueue().cancelTempBasal(true, null); - FabricPrivacy.getInstance().logCustom(new CustomEvent("CancelTemp")); - } - break; - case R.id.actions_settempbasal: - NewTempBasalDialog newTempDialog = new NewTempBasalDialog(); - newTempDialog.show(manager, "NewTempDialog"); - break; - case R.id.actions_fill: - FillDialog fillDialog = new FillDialog(); - fillDialog.show(manager, "FillDialog"); - break; - case R.id.actions_historybrowser: - startActivity(new Intent(getContext(), HistoryBrowseActivity.class)); - break; - case R.id.actions_tddstats: - startActivity(new Intent(getContext(), TDDStatsActivity.class)); - break; - } - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Actions/ActionsPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Actions/ActionsPlugin.java deleted file mode 100644 index ff6275c9c9..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Actions/ActionsPlugin.java +++ /dev/null @@ -1,23 +0,0 @@ -package info.nightscout.androidaps.plugins.Actions; - -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.interfaces.PluginBase; -import info.nightscout.androidaps.interfaces.PluginDescription; -import info.nightscout.androidaps.interfaces.PluginType; - -/** - * Created by mike on 05.11.2016. - */ - -public class ActionsPlugin extends PluginBase { - - public ActionsPlugin() { - super(new PluginDescription() - .mainType(PluginType.GENERAL) - .fragmentClass(ActionsFragment.class.getName()) - .pluginName(R.string.actions) - .shortName(R.string.actions_shortname) - .description(R.string.description_actions) - ); - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Common/SubscriberFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Common/SubscriberFragment.java deleted file mode 100644 index fabd83f0ea..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Common/SubscriberFragment.java +++ /dev/null @@ -1,32 +0,0 @@ -package info.nightscout.androidaps.plugins.Common; - -import android.support.v4.app.Fragment; - -import butterknife.Unbinder; -import info.nightscout.androidaps.MainApp; - -abstract public class SubscriberFragment extends Fragment { - protected Unbinder unbinder; - - @Override - public void onPause() { - super.onPause(); - MainApp.bus().unregister(this); - } - - @Override - public void onResume() { - super.onResume(); - MainApp.bus().register(this); - updateGUI(); - } - - @Override public synchronized void onDestroyView() { - super.onDestroyView(); - if (unbinder != null) - unbinder.unbind(); - } - - - protected abstract void updateGUI(); -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderFragment.java deleted file mode 100644 index 3df78c9a28..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderFragment.java +++ /dev/null @@ -1,286 +0,0 @@ -package info.nightscout.androidaps.plugins.ConfigBuilder; - - -import android.content.Intent; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.StringRes; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Button; -import android.widget.CheckBox; -import android.widget.ImageButton; -import android.widget.LinearLayout; -import android.widget.RadioButton; -import android.widget.ScrollView; -import android.widget.TextView; - -import com.crashlytics.android.answers.CustomEvent; - -import java.util.ArrayList; -import java.util.List; - -import butterknife.BindView; -import butterknife.ButterKnife; -import butterknife.OnClick; -import butterknife.Unbinder; -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.activities.PreferencesActivity; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.events.EventConfigBuilderChange; -import info.nightscout.androidaps.events.EventRefreshGui; -import info.nightscout.androidaps.interfaces.APSInterface; -import info.nightscout.androidaps.interfaces.BgSourceInterface; -import info.nightscout.androidaps.interfaces.ConstraintsInterface; -import info.nightscout.androidaps.interfaces.InsulinInterface; -import info.nightscout.androidaps.interfaces.PluginBase; -import info.nightscout.androidaps.interfaces.PluginType; -import info.nightscout.androidaps.interfaces.ProfileInterface; -import info.nightscout.androidaps.interfaces.PumpInterface; -import info.nightscout.androidaps.interfaces.SensitivityInterface; -import info.nightscout.androidaps.plugins.Common.SubscriberFragment; -import info.nightscout.androidaps.plugins.Insulin.InsulinOrefRapidActingPlugin; -import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin; -import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin; -import info.nightscout.androidaps.plugins.Sensitivity.SensitivityOref0Plugin; -import info.nightscout.utils.FabricPrivacy; -import info.nightscout.utils.PasswordProtection; - - -public class ConfigBuilderFragment extends SubscriberFragment { - - private List pluginViewHolders = new ArrayList<>(); - - @BindView(R.id.categories) - LinearLayout categories; - - @BindView(R.id.main_layout) - ScrollView mainLayout; - @BindView(R.id.unlock) - Button unlock; - - @Override - public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - try { - View view = inflater.inflate(R.layout.configbuilder_fragment, container, false); - unbinder = ButterKnife.bind(this, view); - - if (PasswordProtection.isLocked("settings_password")) - mainLayout.setVisibility(View.GONE); - else unlock.setVisibility(View.GONE); - - createViews(); - - return view; - } catch (Exception e) { - FabricPrivacy.logException(e); - } - - return null; - } - - @OnClick(R.id.unlock) - void onClickUnlock() { - PasswordProtection.QueryPassword(getContext(), R.string.settings_password, "settings_password", () -> { - mainLayout.setVisibility(View.VISIBLE); - unlock.setVisibility(View.GONE); - }, null); - } - - @Override - public void onDestroyView() { - super.onDestroyView(); - for (PluginViewHolder pluginViewHolder : pluginViewHolders) pluginViewHolder.unbind(); - pluginViewHolders.clear(); - } - - @Override - protected void updateGUI() { - for (PluginViewHolder pluginViewHolder : pluginViewHolders) pluginViewHolder.update(); - } - - private void createViews() { - createViewsForPlugins(R.string.configbuilder_profile, R.string.configbuilder_profile_description, PluginType.PROFILE, MainApp.getSpecificPluginsVisibleInListByInterface(ProfileInterface.class, PluginType.PROFILE)); - createViewsForPlugins(R.string.configbuilder_insulin, R.string.configbuilder_insulin_description, PluginType.INSULIN, MainApp.getSpecificPluginsVisibleInListByInterface(InsulinInterface.class, PluginType.INSULIN)); - createViewsForPlugins(R.string.configbuilder_bgsource, R.string.configbuilder_bgsource_description, PluginType.BGSOURCE, MainApp.getSpecificPluginsVisibleInListByInterface(BgSourceInterface.class, PluginType.BGSOURCE)); - createViewsForPlugins(R.string.configbuilder_pump, R.string.configbuilder_pump_description, PluginType.PUMP, MainApp.getSpecificPluginsVisibleInList(PluginType.PUMP)); - createViewsForPlugins(R.string.configbuilder_sensitivity, R.string.configbuilder_sensitivity_description, PluginType.SENSITIVITY, MainApp.getSpecificPluginsVisibleInListByInterface(SensitivityInterface.class, PluginType.SENSITIVITY)); - createViewsForPlugins(R.string.configbuilder_aps, R.string.configbuilder_aps_description, PluginType.APS, MainApp.getSpecificPluginsVisibleInList(PluginType.APS)); - createViewsForPlugins(R.string.configbuilder_loop, R.string.configbuilder_loop_description, PluginType.LOOP, MainApp.getSpecificPluginsVisibleInList(PluginType.LOOP)); - createViewsForPlugins(R.string.constraints, R.string.configbuilder_constraints_description, PluginType.CONSTRAINTS, MainApp.getSpecificPluginsVisibleInListByInterface(ConstraintsInterface.class, PluginType.CONSTRAINTS)); - createViewsForPlugins(R.string.configbuilder_treatments, R.string.configbuilder_treatments_description, PluginType.TREATMENT, MainApp.getSpecificPluginsVisibleInList(PluginType.TREATMENT)); - createViewsForPlugins(R.string.configbuilder_general, R.string.configbuilder_general_description, PluginType.GENERAL, MainApp.getSpecificPluginsVisibleInList(PluginType.GENERAL)); - } - - private void createViewsForPlugins(@StringRes int title, @StringRes int description, PluginType pluginType, List plugins) { - if (plugins.size() == 0) return; - LinearLayout parent = (LinearLayout) getLayoutInflater().inflate(R.layout.configbuilder_single_category, null); - ((TextView) parent.findViewById(R.id.category_title)).setText(MainApp.gs(title)); - ((TextView) parent.findViewById(R.id.category_description)).setText(MainApp.gs(description)); - LinearLayout pluginContainer = parent.findViewById(R.id.category_plugins); - for (PluginBase plugin: plugins) { - PluginViewHolder pluginViewHolder = new PluginViewHolder(pluginType, plugin); - pluginContainer.addView(pluginViewHolder.getBaseView()); - pluginViewHolders.add(pluginViewHolder); - } - categories.addView(parent); - } - - private boolean areMultipleSelectionsAllowed(PluginType type) { - return type == PluginType.GENERAL || type == PluginType.CONSTRAINTS ||type == PluginType.LOOP; - } - - public static void processOnEnabledCategoryChanged(PluginBase changedPlugin, PluginType type) { - ArrayList pluginsInCategory = null; - switch (type) { - // Multiple selection allowed - case GENERAL: - case CONSTRAINTS: - case LOOP: - break; - // Single selection allowed - case INSULIN: - pluginsInCategory = MainApp.getSpecificPluginsListByInterface(InsulinInterface.class); - break; - case SENSITIVITY: - pluginsInCategory = MainApp.getSpecificPluginsListByInterface(SensitivityInterface.class); - break; - case APS: - pluginsInCategory = MainApp.getSpecificPluginsListByInterface(APSInterface.class); - break; - case PROFILE: - pluginsInCategory = MainApp.getSpecificPluginsListByInterface(ProfileInterface.class); - break; - case BGSOURCE: - pluginsInCategory = MainApp.getSpecificPluginsListByInterface(BgSourceInterface.class); - break; - case TREATMENT: - case PUMP: - pluginsInCategory = MainApp.getSpecificPluginsListByInterface(PumpInterface.class); - break; - } - if (pluginsInCategory != null) { - boolean newSelection = changedPlugin.isEnabled(type); - if (newSelection) { // new plugin selected -> disable others - for (PluginBase p : pluginsInCategory) { - if (p.getName().equals(changedPlugin.getName())) { - // this is new selected - } else { - p.setPluginEnabled(type, false); - p.setFragmentVisible(type, false); - } - } - } else { // enable first plugin in list - if (type == PluginType.PUMP) - VirtualPumpPlugin.getPlugin().setPluginEnabled(type, true); - else if (type == PluginType.INSULIN) - InsulinOrefRapidActingPlugin.getPlugin().setPluginEnabled(type, true); - else if (type == PluginType.SENSITIVITY) - SensitivityOref0Plugin.getPlugin().setPluginEnabled(type, true); - else if (type == PluginType.PROFILE) - NSProfilePlugin.getPlugin().setPluginEnabled(type, true); - else - pluginsInCategory.get(0).setPluginEnabled(type, true); - } - } - } - - public class PluginViewHolder { - - private Unbinder unbinder; - private PluginType pluginType; - private PluginBase plugin; - - LinearLayout baseView; - @BindView(R.id.plugin_enabled_exclusive) - RadioButton enabledExclusive; - @BindView(R.id.plugin_enabled_inclusive) - CheckBox enabledInclusive; - @BindView(R.id.plugin_name) - TextView pluginName; - @BindView(R.id.plugin_description) - TextView pluginDescription; - @BindView(R.id.plugin_preferences) - ImageButton pluginPreferences; - @BindView(R.id.plugin_visibility) - CheckBox pluginVisibility; - - public PluginViewHolder(PluginType pluginType, PluginBase plugin) { - this.pluginType = pluginType; - this.plugin = plugin; - baseView = (LinearLayout) getLayoutInflater().inflate(R.layout.configbuilder_single_plugin, null); - unbinder = ButterKnife.bind(this, baseView); - update(); - } - - public LinearLayout getBaseView() { - return baseView; - } - - public void update() { - enabledExclusive.setVisibility(areMultipleSelectionsAllowed(pluginType) ? View.GONE : View.VISIBLE); - enabledInclusive.setVisibility(areMultipleSelectionsAllowed(pluginType) ? View.VISIBLE : View.GONE); - enabledExclusive.setChecked(plugin.isEnabled(pluginType)); - enabledInclusive.setChecked(plugin.isEnabled(pluginType)); - enabledInclusive.setEnabled(!plugin.pluginDescription.alwaysEnabled); - enabledExclusive.setEnabled(!plugin.pluginDescription.alwaysEnabled); - pluginName.setText(plugin.getName()); - if (plugin.getDescription() == null) pluginDescription.setVisibility(View.GONE); - else { - pluginDescription.setVisibility(View.VISIBLE); - pluginDescription.setText(plugin.getDescription()); - } - pluginPreferences.setVisibility(plugin.getPreferencesId() == -1 || !plugin.isEnabled(pluginType) ? View.INVISIBLE : View.VISIBLE); - pluginVisibility.setVisibility(plugin.hasFragment() ? View.VISIBLE : View.INVISIBLE); - pluginVisibility.setEnabled(!(plugin.pluginDescription.neverVisible || plugin.pluginDescription.alwayVisible) && plugin.isEnabled(pluginType)); - pluginVisibility.setChecked(plugin.isFragmentVisible()); - } - - @OnClick(R.id.plugin_visibility) - void onVisibilityChanged() { - plugin.setFragmentVisible(pluginType, pluginVisibility.isChecked()); - ConfigBuilderPlugin.getPlugin().storeSettings("CheckedCheckboxVisible"); - MainApp.bus().post(new EventRefreshGui()); - ConfigBuilderPlugin.getPlugin().logPluginStatus(); - } - - @OnClick({R.id.plugin_enabled_exclusive, R.id.plugin_enabled_inclusive}) - void onEnabledChanged() { - plugin.switchAllowed(new PluginSwitcher(), getActivity()); - } - - @OnClick(R.id.plugin_preferences) - void onPluginPreferencesClicked() { - PasswordProtection.QueryPassword(getContext(), R.string.settings_password, "settings_password", () -> { - Intent i = new Intent(getContext(), PreferencesActivity.class); - i.putExtra("id", plugin.getPreferencesId()); - startActivity(i); - }, null); - } - - public void unbind() { - unbinder.unbind(); - } - - public class PluginSwitcher { - public void invoke() { - boolean enabled = enabledExclusive.getVisibility() == View.VISIBLE ? enabledExclusive.isChecked() : enabledInclusive.isChecked(); - plugin.setPluginEnabled(pluginType, enabled); - plugin.setFragmentVisible(pluginType, enabled); - processOnEnabledCategoryChanged(plugin, pluginType); - updateGUI(); - ConfigBuilderPlugin.getPlugin().storeSettings("CheckedCheckboxEnabled"); - MainApp.bus().post(new EventRefreshGui()); - MainApp.bus().post(new EventConfigBuilderChange()); - ConfigBuilderPlugin.getPlugin().logPluginStatus(); - FabricPrivacy.getInstance().logCustom(new CustomEvent("ConfigurationChange")); - } - - public void cancel(){ - updateGUI(); - } - } - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/DetailedBolusInfoStorage.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/DetailedBolusInfoStorage.java deleted file mode 100644 index 9b4e1d0a28..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/DetailedBolusInfoStorage.java +++ /dev/null @@ -1,44 +0,0 @@ -package info.nightscout.androidaps.plugins.ConfigBuilder; - -import android.support.annotation.Nullable; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.List; - -import info.nightscout.androidaps.data.DetailedBolusInfo; -import info.nightscout.androidaps.logging.L; - -/** - * Created by mike on 08.08.2017. - */ - -public class DetailedBolusInfoStorage { - private static Logger log = LoggerFactory.getLogger(L.PUMP); - private static List store = new ArrayList<>(); - - public static synchronized void add(DetailedBolusInfo detailedBolusInfo) { - log.debug("Stored bolus info: " + detailedBolusInfo); - store.add(detailedBolusInfo); - } - - @Nullable - public static synchronized DetailedBolusInfo findDetailedBolusInfo(long bolustime) { - DetailedBolusInfo found = null; - for (int i = 0; i < store.size(); i++) { - long infoTime = store.get(i).date; - if (L.isEnabled(L.PUMP)) - log.debug("Existing bolus info: " + store.get(i)); - if (bolustime > infoTime - 60 * 1000 && bolustime < infoTime + 60 * 1000) { - found = store.get(i); - if (L.isEnabled(L.PUMP)) - log.debug("Using & removing bolus info: " + store.get(i)); - store.remove(i); - break; - } - } - return found; - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ProfileFunctions.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ProfileFunctions.java deleted file mode 100644 index 312c0cd9ae..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ProfileFunctions.java +++ /dev/null @@ -1,142 +0,0 @@ -package info.nightscout.androidaps.plugins.ConfigBuilder; - -import android.content.Intent; -import android.support.annotation.Nullable; - -import com.crashlytics.android.answers.CustomEvent; -import com.squareup.otto.Subscribe; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import info.nightscout.androidaps.BuildConfig; -import info.nightscout.androidaps.Constants; -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.data.Profile; -import info.nightscout.androidaps.data.ProfileStore; -import info.nightscout.androidaps.db.ProfileSwitch; -import info.nightscout.androidaps.events.EventNewBasalProfile; -import info.nightscout.androidaps.events.EventProfileSwitchChange; -import info.nightscout.androidaps.interfaces.ProfileInterface; -import info.nightscout.androidaps.interfaces.TreatmentsInterface; -import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.Overview.Dialogs.ErrorHelperActivity; -import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; -import info.nightscout.androidaps.queue.Callback; -import info.nightscout.utils.FabricPrivacy; - -public class ProfileFunctions { - private static Logger log = LoggerFactory.getLogger(L.PROFILE); - - private static ProfileFunctions profileFunctions = null; - - public static ProfileFunctions getInstance() { - if (profileFunctions == null) - profileFunctions = new ProfileFunctions(); - return profileFunctions; - } - - static { - ProfileFunctions.getInstance(); // register to bus at start - } - - ProfileFunctions() { - MainApp.bus().register(this); - } - - @Subscribe - public void onProfileSwitch(EventProfileSwitchChange ignored) { - if (L.isEnabled(L.PROFILE)) - log.debug("onProfileSwitch"); - ConfigBuilderPlugin.getPlugin().getCommandQueue().setProfile(getProfile(), new Callback() { - @Override - public void run() { - if (!result.success) { - Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class); - i.putExtra("soundid", R.raw.boluserror); - i.putExtra("status", result.comment); - i.putExtra("title", MainApp.gs(R.string.failedupdatebasalprofile)); - i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - MainApp.instance().startActivity(i); - } - MainApp.bus().post(new EventNewBasalProfile()); - } - }); - } - - public String getProfileName() { - return getProfileName(System.currentTimeMillis()); - } - - public String getProfileName(boolean customized) { - return getProfileName(System.currentTimeMillis(), customized); - } - - public String getProfileName(long time) { - return getProfileName(time, true); - } - - public String getProfileName(long time, boolean customized) { - TreatmentsInterface activeTreatments = TreatmentsPlugin.getPlugin(); - ProfileInterface activeProfile = ConfigBuilderPlugin.getPlugin().getActiveProfileInterface(); - - ProfileSwitch profileSwitch = activeTreatments.getProfileSwitchFromHistory(time); - if (profileSwitch != null) { - if (profileSwitch.profileJson != null) { - return customized ? profileSwitch.getCustomizedName() : profileSwitch.profileName; - } else { - ProfileStore profileStore = activeProfile.getProfile(); - if (profileStore != null) { - Profile profile = profileStore.getSpecificProfile(profileSwitch.profileName); - if (profile != null) - return profileSwitch.profileName; - } - } - } - return MainApp.gs(R.string.noprofileselected); - } - - public boolean isProfileValid(String from) { - return getProfile() != null && getProfile().isValid(from); - } - - @Nullable - public Profile getProfile() { - return getProfile(System.currentTimeMillis()); - } - - public String getProfileUnits() { - Profile profile = getProfile(); - return profile != null ? profile.getUnits() : Constants.MGDL; - } - - @Nullable - public Profile getProfile(long time) { - TreatmentsInterface activeTreatments = TreatmentsPlugin.getPlugin(); - ProfileInterface activeProfile = ConfigBuilderPlugin.getPlugin().getActiveProfileInterface(); - - //log.debug("Profile for: " + new Date(time).toLocaleString() + " : " + getProfileName(time)); - ProfileSwitch profileSwitch = activeTreatments.getProfileSwitchFromHistory(time); - if (profileSwitch != null) { - if (profileSwitch.profileJson != null) { - return profileSwitch.getProfileObject(); - } else if (activeProfile.getProfile() != null) { - Profile profile = activeProfile.getProfile().getSpecificProfile(profileSwitch.profileName); - if (profile != null) - return profile; - } - } - if (activeTreatments.getProfileSwitchesFromHistory().size() > 0) { - FabricPrivacy.getInstance().logCustom(new CustomEvent("CatchedError") - .putCustomAttribute("buildversion", BuildConfig.BUILDVERSION) - .putCustomAttribute("version", BuildConfig.VERSION) - .putCustomAttribute("time", time) - .putCustomAttribute("getProfileSwitchesFromHistory", activeTreatments.getProfileSwitchesFromHistory().toString()) - ); - } - log.error("getProfile at the end: returning null"); - return null; - } - -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesFragment.java deleted file mode 100644 index 3dcec0920f..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesFragment.java +++ /dev/null @@ -1,211 +0,0 @@ -package info.nightscout.androidaps.plugins.ConstraintsObjectives; - -import android.app.Activity; -import android.os.Bundle; -import android.os.Handler; -import android.os.Looper; -import android.support.annotation.NonNull; -import android.support.v7.widget.CardView; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.LinearSmoothScroller; -import android.support.v7.widget.RecyclerView; -import android.text.Html; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Button; -import android.widget.CheckBox; -import android.widget.LinearLayout; -import android.widget.TextView; - -import java.util.Date; - -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.plugins.Common.SubscriberFragment; -import info.nightscout.androidaps.plugins.ConstraintsObjectives.objectives.Objective; -import info.nightscout.utils.FabricPrivacy; - -public class ObjectivesFragment extends SubscriberFragment { - RecyclerView recyclerView; - CheckBox enableFake; - TextView reset; - ObjectivesAdapter objectivesAdapter = new ObjectivesAdapter(); - Handler handler = new Handler(Looper.getMainLooper()); - - private Runnable objectiveUpdater = new Runnable() { - @Override - public void run() { - handler.postDelayed(this, 60 * 1000); - updateGUI(); - } - }; - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - try { - View view = inflater.inflate(R.layout.objectives_fragment, container, false); - - recyclerView = view.findViewById(R.id.objectives_recyclerview); - recyclerView.setLayoutManager(new LinearLayoutManager(view.getContext())); - recyclerView.setAdapter(objectivesAdapter); - enableFake = view.findViewById(R.id.objectives_fake); - reset = view.findViewById(R.id.objectives_reset); - enableFake.setOnClickListener(v -> updateGUI()); - reset.setOnClickListener(v -> { - ObjectivesPlugin.getPlugin().reset(); - ObjectivesPlugin.getPlugin().saveProgress(); - recyclerView.getAdapter().notifyDataSetChanged(); - scrollToCurrentObjective(); - }); - scrollToCurrentObjective(); - startUpdateTimer(); - return view; - } catch (Exception e) { - FabricPrivacy.logException(e); - } - - return null; - } - - @Override - public synchronized void onDestroyView() { - super.onDestroyView(); - handler.removeCallbacks(objectiveUpdater); - } - - private void startUpdateTimer() { - handler.removeCallbacks(objectiveUpdater); - for (Objective objective : ObjectivesPlugin.getPlugin().getObjectives()) { - if (objective.isStarted() && !objective.isAccomplished()) { - long timeTillNextMinute = (System.currentTimeMillis() - objective.getStartedOn().getTime()) % (60 * 1000); - handler.postDelayed(objectiveUpdater, timeTillNextMinute); - break; - } - } - } - - private void scrollToCurrentObjective() { - for (int i = 0; i < ObjectivesPlugin.getPlugin().getObjectives().size(); i++) { - Objective objective = ObjectivesPlugin.getPlugin().getObjectives().get(i); - if (!objective.isStarted() || !objective.isAccomplished()) { - RecyclerView.SmoothScroller smoothScroller = new LinearSmoothScroller(getContext()) { - @Override - protected int getVerticalSnapPreference() { - return LinearSmoothScroller.SNAP_TO_START; - } - - @Override - protected int calculateTimeForScrolling(int dx) { - return super.calculateTimeForScrolling(dx) * 4; - } - }; - smoothScroller.setTargetPosition(i); - recyclerView.getLayoutManager().startSmoothScroll(smoothScroller); - break; - } - } - } - - private class ObjectivesAdapter extends RecyclerView.Adapter { - - @NonNull - @Override - public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.objectives_item, parent, false)); - } - - @Override - public void onBindViewHolder(@NonNull ViewHolder holder, int position) { - Objective objective = ObjectivesPlugin.getPlugin().getObjectives().get(position); - holder.title.setText(MainApp.gs(R.string.nth_objective, position + 1)); - if (objective.getObjective() != 0) { - holder.objective.setVisibility(View.VISIBLE); - holder.objective.setText(MainApp.gs(objective.getObjective())); - } else holder.objective.setVisibility(View.GONE); - if (objective.getGate() != 0) { - holder.gate.setVisibility(View.VISIBLE); - holder.gate.setText(MainApp.gs(objective.getGate())); - } else holder.gate.setVisibility(View.GONE); - if (!objective.isStarted()) { - holder.gate.setTextColor(0xFFFFFFFF); - holder.verify.setVisibility(View.GONE); - holder.progress.setVisibility(View.GONE); - if (position == 0 || ObjectivesPlugin.getPlugin().getObjectives().get(position - 1).isAccomplished()) - holder.start.setVisibility(View.VISIBLE); - else holder.start.setVisibility(View.GONE); - } else if (objective.isAccomplished()) { - holder.gate.setTextColor(0xFF4CAF50); - holder.verify.setVisibility(View.GONE); - holder.progress.setVisibility(View.GONE); - holder.start.setVisibility(View.GONE); - } else if (objective.isStarted()) { - holder.gate.setTextColor(0xFFFFFFFF); - holder.verify.setVisibility(View.VISIBLE); - holder.verify.setEnabled(objective.isCompleted() || enableFake.isChecked()); - holder.start.setVisibility(View.GONE); - holder.progress.setVisibility(View.VISIBLE); - holder.progress.removeAllViews(); - for (Objective.Task task : objective.getTasks()) { - if (task.shouldBeIgnored()) continue; - TextView textView = new TextView(holder.progress.getContext()); - textView.setTextColor(0xFFFFFFFF); - String basicHTML = "%2$s: %3$s"; - String formattedHTML = String.format(basicHTML, task.isCompleted() ? "#4CAF50" : "#FF9800", MainApp.gs(task.getTask()), task.getProgress()); - textView.setText(Html.fromHtml(formattedHTML)); - holder.progress.addView(textView, LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT); - } - } - holder.verify.setOnClickListener((view) -> { - objective.setAccomplishedOn(new Date()); - notifyDataSetChanged(); - scrollToCurrentObjective(); - startUpdateTimer(); - }); - holder.start.setOnClickListener((view) -> { - objective.setStartedOn(new Date()); - notifyDataSetChanged(); - scrollToCurrentObjective(); - startUpdateTimer(); - }); - } - - @Override - public int getItemCount() { - return ObjectivesPlugin.getPlugin().getObjectives().size(); - } - - public class ViewHolder extends RecyclerView.ViewHolder { - - public CardView cardView; - public TextView title; - public TextView objective; - public TextView gate; - public LinearLayout progress; - public Button verify; - public Button start; - - public ViewHolder(View itemView) { - super(itemView); - cardView = (CardView) itemView; - title = itemView.findViewById(R.id.objective_title); - objective = itemView.findViewById(R.id.objective_objective); - gate = itemView.findViewById(R.id.objective_gate); - progress = itemView.findViewById(R.id.objective_progress); - verify = itemView.findViewById(R.id.objective_verify); - start = itemView.findViewById(R.id.objective_start); - } - } - } - - @Override - public void updateGUI() { - Activity activity = getActivity(); - if (activity != null) - activity.runOnUiThread(() -> { - objectivesAdapter.notifyDataSetChanged(); - }); - } - -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesPlugin.java deleted file mode 100644 index cc50189346..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesPlugin.java +++ /dev/null @@ -1,164 +0,0 @@ -package info.nightscout.androidaps.plugins.ConstraintsObjectives; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.List; - -import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.interfaces.Constraint; -import info.nightscout.androidaps.interfaces.ConstraintsInterface; -import info.nightscout.androidaps.interfaces.PluginBase; -import info.nightscout.androidaps.interfaces.PluginDescription; -import info.nightscout.androidaps.interfaces.PluginType; -import info.nightscout.androidaps.interfaces.PumpInterface; -import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.ConstraintsObjectives.events.EventObjectivesSaved; -import info.nightscout.androidaps.plugins.ConstraintsObjectives.objectives.Objective; -import info.nightscout.androidaps.plugins.ConstraintsObjectives.objectives.Objective1; -import info.nightscout.androidaps.plugins.ConstraintsObjectives.objectives.Objective2; -import info.nightscout.androidaps.plugins.ConstraintsObjectives.objectives.Objective3; -import info.nightscout.androidaps.plugins.ConstraintsObjectives.objectives.Objective4; -import info.nightscout.androidaps.plugins.ConstraintsObjectives.objectives.Objective5; -import info.nightscout.androidaps.plugins.ConstraintsObjectives.objectives.Objective6; -import info.nightscout.androidaps.plugins.ConstraintsObjectives.objectives.Objective7; -import info.nightscout.androidaps.plugins.ConstraintsObjectives.objectives.Objective8; -import info.nightscout.utils.SP; - -/** - * Created by mike on 05.08.2016. - */ -public class ObjectivesPlugin extends PluginBase implements ConstraintsInterface { - private static Logger log = LoggerFactory.getLogger(L.CONSTRAINTS); - - private static ObjectivesPlugin objectivesPlugin; - - public List objectives = new ArrayList<>(); - public boolean bgIsAvailableInNS = false; - public boolean pumpStatusIsAvailableInNS = false; - public Integer manualEnacts = 0; - - public static ObjectivesPlugin getPlugin() { - if (objectivesPlugin == null) { - objectivesPlugin = new ObjectivesPlugin(); - } - return objectivesPlugin; - } - - private ObjectivesPlugin() { - super(new PluginDescription() - .mainType(PluginType.CONSTRAINTS) - .fragmentClass(ObjectivesFragment.class.getName()) - .alwaysEnabled(!Config.NSCLIENT) - .showInList(!Config.NSCLIENT) - .pluginName(R.string.objectives) - .shortName(R.string.objectives_shortname) - .description(R.string.description_objectives) - ); - setupObjectives(); - loadProgress(); - } - - @Override - public boolean specialEnableCondition() { - PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump(); - return pump == null || pump.getPumpDescription().isTempBasalCapable; - } - - private void setupObjectives() { - objectives.add(new Objective1()); - objectives.add(new Objective2()); - objectives.add(new Objective3()); - objectives.add(new Objective4()); - objectives.add(new Objective5()); - objectives.add(new Objective6()); - objectives.add(new Objective7()); - objectives.add(new Objective8()); - } - - public void reset() { - for (Objective objective : objectives) { - objective.setStartedOn(null); - objective.setAccomplishedOn(null); - } - bgIsAvailableInNS = false; - pumpStatusIsAvailableInNS = false; - manualEnacts = 0; - saveProgress(); - } - - public void saveProgress() { - SP.putBoolean("Objectives" + "bgIsAvailableInNS", bgIsAvailableInNS); - SP.putBoolean("Objectives" + "pumpStatusIsAvailableInNS", pumpStatusIsAvailableInNS); - SP.putString("Objectives" + "manualEnacts", Integer.toString(manualEnacts)); - if (L.isEnabled(L.CONSTRAINTS)) - log.debug("Objectives stored"); - MainApp.bus().post(new EventObjectivesSaved()); - } - - private void loadProgress() { - bgIsAvailableInNS = SP.getBoolean("Objectives" + "bgIsAvailableInNS", false); - pumpStatusIsAvailableInNS = SP.getBoolean("Objectives" + "pumpStatusIsAvailableInNS", false); - try { - manualEnacts = SP.getInt("Objectives" + "manualEnacts", 0); - } catch (Exception e) { - log.error("Unhandled exception", e); - } - if (L.isEnabled(L.CONSTRAINTS)) - log.debug("Objectives loaded"); - } - - public List getObjectives() { - return objectives; - } - - /** - * Constraints interface - **/ - @Override - public Constraint isLoopInvocationAllowed(Constraint value) { - if (!objectives.get(0).isStarted()) - value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), 1), this); - return value; - } - - @Override - public Constraint isClosedLoopAllowed(Constraint value) { - if (!objectives.get(3).isStarted()) - value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), 4), this); - return value; - } - - @Override - public Constraint isAutosensModeEnabled(Constraint value) { - if (!objectives.get(5).isStarted()) - value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), 6), this); - return value; - } - - @Override - public Constraint isAMAModeEnabled(Constraint value) { - if (!objectives.get(6).isStarted()) - value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), 7), this); - return value; - } - - @Override - public Constraint isSMBModeEnabled(Constraint value) { - if (!objectives.get(7).isStarted()) - value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), 8), this); - return value; - } - - @Override - public Constraint applyMaxIOBConstraints(Constraint maxIob) { - if (objectives.get(3).isStarted() && !objectives.get(3).isAccomplished()) - maxIob.set(0d, String.format(MainApp.gs(R.string.objectivenotfinished), 4), this); - return maxIob; - } - -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/events/EventObjectivesSaved.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/events/EventObjectivesSaved.java deleted file mode 100644 index 1822368cf9..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/events/EventObjectivesSaved.java +++ /dev/null @@ -1,6 +0,0 @@ -package info.nightscout.androidaps.plugins.ConstraintsObjectives.events; - -import info.nightscout.androidaps.events.Event; - -public class EventObjectivesSaved extends Event { -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective.java deleted file mode 100644 index 5127f64b34..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective.java +++ /dev/null @@ -1,141 +0,0 @@ -package info.nightscout.androidaps.plugins.ConstraintsObjectives.objectives; - -import android.support.annotation.StringRes; - -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.R; -import info.nightscout.utils.SP; -import info.nightscout.utils.T; - -public abstract class Objective { - - private int number; - @StringRes - private int objective; - @StringRes - private int gate; - private Date startedOn; - private Date accomplishedOn; - private List tasks = new ArrayList<>(); - - public Objective(int number, @StringRes int objective, @StringRes int gate) { - this.number = number; - this.objective = objective; - this.gate = gate; - startedOn = new Date(SP.getLong("Objectives" + number + "started", 0L)); - if (startedOn.getTime() == 0L) startedOn = null; - accomplishedOn = new Date(SP.getLong("Objectives" + number + "accomplished", 0L)); - if (accomplishedOn.getTime() == 0L) accomplishedOn = null; - setupTasks(tasks); - for (Task task : tasks) task.objective = this; - } - - public boolean isCompleted() { - for (Task task : tasks) { - if (!task.shouldBeIgnored() && !task.isCompleted()) - return false; - } - return true; - } - - public boolean isAccomplished() { - return accomplishedOn != null; - } - - public boolean isStarted() { - return startedOn != null; - } - - public Date getStartedOn() { - return startedOn; - } - - public int getObjective() { - return objective; - } - - public int getGate() { - return gate; - } - - public void setStartedOn(Date startedOn) { - this.startedOn = startedOn; - SP.putLong("Objectives" + number + "started", startedOn == null ? 0 : startedOn.getTime()); - } - - public void setAccomplishedOn(Date accomplishedOn) { - this.accomplishedOn = accomplishedOn; - SP.putLong("Objectives" + number + "accomplished", accomplishedOn == null ? 0 : accomplishedOn.getTime()); - } - - protected void setupTasks(List tasks) { - - } - - public List getTasks() { - return tasks; - } - - public abstract class Task { - @StringRes - private int task; - private Objective objective; - - public Task(@StringRes int task) { - this.task = task; - } - - public int getTask() { - return task; - } - - protected Objective getObjective() { - return objective; - } - - public abstract boolean isCompleted(); - - public String getProgress() { - return MainApp.gs(isCompleted() ? R.string.completed_well_done : R.string.not_completed_yet); - } - - public boolean shouldBeIgnored() { - return false; - } - } - - public class MinimumDurationTask extends Task { - - private long minimumDuration; - - public MinimumDurationTask(long minimumDuration) { - super(R.string.time_elapsed); - this.minimumDuration = minimumDuration; - } - - @Override - public boolean isCompleted() { - return getObjective().isStarted() && System.currentTimeMillis() - getObjective().getStartedOn().getTime() >= minimumDuration; - } - - @Override - public String getProgress() { - return getDurationText(System.currentTimeMillis() - getObjective().getStartedOn().getTime()) - + " / " + getDurationText(minimumDuration); - } - - private String getDurationText(long duration) { - int days = (int) Math.floor((double) duration / T.days(1).msecs()); - int hours = (int) Math.floor((double) duration / T.hours(1).msecs()); - int minutes = (int) Math.floor((double) duration / T.mins(1).msecs()); - if (days > 0) return MainApp.gq(R.plurals.objective_days, days, days); - else if (hours > 0) return MainApp.gq(R.plurals.objective_hours, hours, hours); - else return MainApp.gq(R.plurals.objective_minutes, minutes, minutes); - } - } - -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective2.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective2.java deleted file mode 100644 index ac5485f953..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective2.java +++ /dev/null @@ -1,36 +0,0 @@ -package info.nightscout.androidaps.plugins.ConstraintsObjectives.objectives; - -import java.util.List; - -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.plugins.ConstraintsObjectives.ObjectivesPlugin; -import info.nightscout.utils.T; - -public class Objective2 extends Objective { - - public final int MANUAL_ENACTS_NEEDED = 20; - - public Objective2() { - super(1, R.string.objectives_1_objective, R.string.objectives_1_gate); - } - - @Override - protected void setupTasks(List tasks) { - tasks.add(new MinimumDurationTask(T.days(7).msecs())); - tasks.add(new Task(R.string.objectives_manualenacts) { - @Override - public boolean isCompleted() { - return ObjectivesPlugin.getPlugin().manualEnacts >= MANUAL_ENACTS_NEEDED; - } - - @Override - public String getProgress() { - if (ObjectivesPlugin.getPlugin().manualEnacts >= MANUAL_ENACTS_NEEDED) - return MainApp.gs(R.string.completed_well_done); - else - return ObjectivesPlugin.getPlugin().manualEnacts + " / " + MANUAL_ENACTS_NEEDED; - } - }); - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective3.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective3.java deleted file mode 100644 index 8a84e3c83c..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective3.java +++ /dev/null @@ -1,10 +0,0 @@ -package info.nightscout.androidaps.plugins.ConstraintsObjectives.objectives; - -import info.nightscout.androidaps.R; - -public class Objective3 extends Objective { - - public Objective3() { - super(2, R.string.objectives_2_objective, R.string.objectives_2_gate); - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective6.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective6.java deleted file mode 100644 index 7867b28e70..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective6.java +++ /dev/null @@ -1,18 +0,0 @@ -package info.nightscout.androidaps.plugins.ConstraintsObjectives.objectives; - -import java.util.List; - -import info.nightscout.androidaps.R; -import info.nightscout.utils.T; - -public class Objective6 extends Objective { - - public Objective6() { - super(5, R.string.objectives_5_objective, R.string.objectives_5_gate); - } - - @Override - protected void setupTasks(List tasks) { - tasks.add(new MinimumDurationTask(T.days(7).msecs())); - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective7.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective7.java deleted file mode 100644 index 670cffe746..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective7.java +++ /dev/null @@ -1,18 +0,0 @@ -package info.nightscout.androidaps.plugins.ConstraintsObjectives.objectives; - -import java.util.List; - -import info.nightscout.androidaps.R; -import info.nightscout.utils.T; - -public class Objective7 extends Objective { - - public Objective7() { - super(6, R.string.objectives_6_objective, 0); - } - - @Override - protected void setupTasks(List tasks) { - tasks.add(new MinimumDurationTask(T.days(28).msecs())); - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/events/EventAutosensCalculationFinished.java b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/events/EventAutosensCalculationFinished.java deleted file mode 100644 index 2cb9b7ca4c..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/events/EventAutosensCalculationFinished.java +++ /dev/null @@ -1,16 +0,0 @@ -package info.nightscout.androidaps.plugins.IobCobCalculator.events; - -import info.nightscout.androidaps.events.Event; -import info.nightscout.androidaps.events.EventLoop; - -/** - * Created by mike on 30.04.2017. - */ - -public class EventAutosensCalculationFinished extends EventLoop { - public Event cause; - - public EventAutosensCalculationFinished(Event cause) { - this.cause = cause; - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/events/EventIobCalculationProgress.java b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/events/EventIobCalculationProgress.java deleted file mode 100644 index 08f2747e60..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/events/EventIobCalculationProgress.java +++ /dev/null @@ -1,11 +0,0 @@ -package info.nightscout.androidaps.plugins.IobCobCalculator.events; - -import info.nightscout.androidaps.events.Event; - -public class EventIobCalculationProgress extends Event { - public String progress; - - public EventIobCalculationProgress(String progress) { - this.progress = progress; - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/events/EventNewHistoryData.java b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/events/EventNewHistoryData.java deleted file mode 100644 index 8814741099..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/events/EventNewHistoryData.java +++ /dev/null @@ -1,15 +0,0 @@ -package info.nightscout.androidaps.plugins.IobCobCalculator.events; - -import info.nightscout.androidaps.events.Event; - -/** - * Created by mike on 26.04.2017. - */ - -public class EventNewHistoryData extends Event { - public long time = 0; - - public EventNewHistoryData(long time) { - this.time = time; - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopFragment.java deleted file mode 100644 index 0c0e31fb03..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopFragment.java +++ /dev/null @@ -1,146 +0,0 @@ -package info.nightscout.androidaps.plugins.Loop; - - -import android.app.Activity; -import android.os.Bundle; -import android.text.Html; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Button; -import android.widget.TextView; - -import com.crashlytics.android.answers.CustomEvent; -import com.squareup.otto.Subscribe; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import butterknife.BindView; -import butterknife.ButterKnife; -import butterknife.OnClick; -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.interfaces.Constraint; -import info.nightscout.androidaps.plugins.Common.SubscriberFragment; -import info.nightscout.androidaps.plugins.Loop.events.EventLoopSetLastRunGui; -import info.nightscout.androidaps.plugins.Loop.events.EventLoopUpdateGui; -import info.nightscout.utils.FabricPrivacy; - -public class LoopFragment extends SubscriberFragment { - @BindView(R.id.loop_run) - Button runNowButton; - @BindView(R.id.loop_lastrun) - TextView lastRunView; - @BindView(R.id.loop_lastenact) - TextView lastEnactView; - @BindView(R.id.loop_source) - TextView sourceView; - @BindView(R.id.loop_request) - TextView requestView; - @BindView(R.id.loop_constraintsprocessed) - TextView constraintsProcessedView; - @BindView(R.id.loop_constraints) - TextView constraintsView; - @BindView(R.id.loop_tbrsetbypump) - TextView tbrSetByPumpView; - @BindView(R.id.loop_smbsetbypump) - TextView smbSetByPumpView; - - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - try { - View view = inflater.inflate(R.layout.loop_fragment, container, false); - unbinder = ButterKnife.bind(this, view); - return view; - } catch (Exception e) { - FabricPrivacy.logException(e); - } - return null; - } - - @OnClick(R.id.loop_run) - void onRunClick() { - lastRunView.setText(MainApp.gs(R.string.executing)); - new Thread(() -> LoopPlugin.getPlugin().invoke("Loop button", true)).start(); - FabricPrivacy.getInstance().logCustom(new CustomEvent("Loop_Run")); - } - - @Subscribe - public void onStatusEvent(final EventLoopUpdateGui ev) { - updateGUI(); - } - - @Subscribe - public void onStatusEvent(final EventLoopSetLastRunGui ev) { - clearGUI(); - final Activity activity = getActivity(); - if (activity != null) - activity.runOnUiThread(() -> { synchronized (LoopFragment.this) { if (lastRunView != null) lastRunView.setText(ev.text); } }); - } - - - @Override - protected void updateGUI() { - Activity activity = getActivity(); - if (activity != null) - activity.runOnUiThread(() -> { - synchronized (LoopFragment.this) { - if (!isBound()) return; - LoopPlugin.LastRun lastRun = LoopPlugin.lastRun; - if (lastRun != null) { - requestView.setText(lastRun.request != null ? lastRun.request.toSpanned() : ""); - constraintsProcessedView.setText(lastRun.constraintsProcessed != null ? lastRun.constraintsProcessed.toSpanned() : ""); - sourceView.setText(lastRun.source != null ? lastRun.source : ""); - lastRunView.setText(lastRun.lastAPSRun != null && lastRun.lastAPSRun.getTime() != 0 ? lastRun.lastAPSRun.toLocaleString() : ""); - lastEnactView.setText(lastRun.lastEnact != null && lastRun.lastEnact.getTime() != 0 ? lastRun.lastEnact.toLocaleString() : ""); - tbrSetByPumpView.setText(lastRun.tbrSetByPump != null ? Html.fromHtml(lastRun.tbrSetByPump.toHtml()) : ""); - smbSetByPumpView.setText(lastRun.smbSetByPump != null ? Html.fromHtml(lastRun.smbSetByPump.toHtml()) : ""); - - String constraints = ""; - if (lastRun.constraintsProcessed != null) { - Constraint allConstraints = new Constraint<>(0d); - if (lastRun.constraintsProcessed.rateConstraint != null) - allConstraints.copyReasons(lastRun.constraintsProcessed.rateConstraint); - if (lastRun.constraintsProcessed.smbConstraint != null) - allConstraints.copyReasons(lastRun.constraintsProcessed.smbConstraint); - constraints = allConstraints.getMostLimitedReasons(); - } - constraintsView.setText(constraints); - } - } - }); - } - - void clearGUI() { - Activity activity = getActivity(); - if (activity != null) - activity.runOnUiThread(() -> { - synchronized (LoopFragment.this) { - if (isBound()) { - requestView.setText(""); - constraintsProcessedView.setText(""); - sourceView.setText(""); - lastRunView.setText(""); - lastEnactView.setText(""); - tbrSetByPumpView.setText(""); - smbSetByPumpView.setText(""); - } - } - }); - } - - boolean isBound() { - return requestView != null - && constraintsProcessedView != null - && sourceView != null - && lastRunView != null - && lastEnactView != null - && tbrSetByPumpView != null - && smbSetByPumpView != null - && constraintsView != null - && runNowButton != null; - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/events/EventLoopSetLastRunGui.java b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/events/EventLoopSetLastRunGui.java deleted file mode 100644 index 1ef5dc4c94..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/events/EventLoopSetLastRunGui.java +++ /dev/null @@ -1,14 +0,0 @@ -package info.nightscout.androidaps.plugins.Loop.events; - -import info.nightscout.androidaps.events.EventUpdateGui; - -/** - * Created by mike on 05.08.2016. - */ -public class EventLoopSetLastRunGui extends EventUpdateGui { - public String text = null; - - public EventLoopSetLastRunGui(String text) { - this.text = text; - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/events/EventLoopUpdateGui.java b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/events/EventLoopUpdateGui.java deleted file mode 100644 index d4417dbb12..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/events/EventLoopUpdateGui.java +++ /dev/null @@ -1,9 +0,0 @@ -package info.nightscout.androidaps.plugins.Loop.events; - -import info.nightscout.androidaps.events.EventUpdateGui; - -/** - * Created by mike on 05.08.2016. - */ -public class EventLoopUpdateGui extends EventUpdateGui { -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/events/EventNewOpenLoopNotification.java b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/events/EventNewOpenLoopNotification.java deleted file mode 100644 index 001d11661e..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/events/EventNewOpenLoopNotification.java +++ /dev/null @@ -1,9 +0,0 @@ -package info.nightscout.androidaps.plugins.Loop.events; - -import info.nightscout.androidaps.events.Event; - -/** - * Created by mike on 07.08.2016. - */ -public class EventNewOpenLoopNotification extends Event { -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Maintenance/activities/LogSettingActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/Maintenance/activities/LogSettingActivity.java deleted file mode 100644 index 7d21d561b9..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Maintenance/activities/LogSettingActivity.java +++ /dev/null @@ -1,80 +0,0 @@ -package info.nightscout.androidaps.plugins.Maintenance.activities; - -import android.os.Bundle; -import android.support.v7.app.AppCompatActivity; -import android.view.View; -import android.widget.CheckBox; -import android.widget.LinearLayout; -import android.widget.TextView; - -import java.util.List; - -import butterknife.BindView; -import butterknife.ButterKnife; -import butterknife.OnClick; -import butterknife.Unbinder; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.logging.L; - -public class LogSettingActivity extends AppCompatActivity { - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_logsetting); - ButterKnife.bind(this); - - createViewsForSettings(L.getLogElements()); - } - - private void createViewsForSettings(List elements) { - if (elements.size() == 0) return; - LinearLayout container = (LinearLayout) findViewById(R.id.logsettings_placeholder); - container.removeAllViews(); - for (L.LogElement element : elements) { - PluginViewHolder pluginViewHolder = new PluginViewHolder(element); - container.addView(pluginViewHolder.getBaseView()); - } - } - - @OnClick(R.id.logsettings_reset) - public void onResetClick() { - L.resetToDefaults(); - createViewsForSettings(L.getLogElements()); - } - - public class PluginViewHolder { - - private Unbinder unbinder; - private L.LogElement element; - - LinearLayout baseView; - @BindView(R.id.logsettings_description) - TextView description; - @BindView(R.id.logsettings_visibility) - CheckBox enabled; - - public PluginViewHolder(L.LogElement element) { - this.element = element; - baseView = (LinearLayout) getLayoutInflater().inflate(R.layout.logsettings_item, null); - unbinder = ButterKnife.bind(this, baseView); - - description.setText(element.name); - enabled.setChecked(element.enabled); - } - - public View getBaseView() { - return baseView; - } - - @OnClick(R.id.logsettings_visibility) - void onEnagledChanged() { - element.setEnabled(enabled.isChecked()); - } - - public void unbind() { - unbinder.unbind(); - } - } - -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/NSClientFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/NSClientFragment.java deleted file mode 100644 index 9eff2ca84c..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/NSClientFragment.java +++ /dev/null @@ -1,169 +0,0 @@ -package info.nightscout.androidaps.plugins.NSClientInternal; - - -import android.app.Activity; -import android.app.AlertDialog; -import android.content.Context; -import android.content.DialogInterface; -import android.graphics.Paint; -import android.os.Bundle; -import android.text.Html; -import android.text.Spanned; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.CheckBox; -import android.widget.CompoundButton; -import android.widget.ScrollView; -import android.widget.TextView; - -import com.crashlytics.android.answers.CustomEvent; -import com.squareup.otto.Subscribe; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.events.EventPreferenceChange; -import info.nightscout.androidaps.plugins.Common.SubscriberFragment; -import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientNewLog; -import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientRestart; -import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientUpdateGUI; -import info.nightscout.utils.FabricPrivacy; -import info.nightscout.utils.SP; - -public class NSClientFragment extends SubscriberFragment implements View.OnClickListener, CompoundButton.OnCheckedChangeListener { - private TextView logTextView; - private TextView queueTextView; - private TextView urlTextView; - private TextView statusTextView; - private TextView clearlog; - private TextView restart; - private TextView delivernow; - private TextView clearqueue; - private TextView showqueue; - private ScrollView logScrollview; - private CheckBox autoscrollCheckbox; - private CheckBox pausedCheckbox; - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - try { - View view = inflater.inflate(R.layout.nsclientinternal_fragment, container, false); - - logScrollview = (ScrollView) view.findViewById(R.id.nsclientinternal_logscrollview); - autoscrollCheckbox = (CheckBox) view.findViewById(R.id.nsclientinternal_autoscroll); - autoscrollCheckbox.setChecked(NSClientPlugin.getPlugin().autoscroll); - autoscrollCheckbox.setOnCheckedChangeListener(this); - pausedCheckbox = (CheckBox) view.findViewById(R.id.nsclientinternal_paused); - pausedCheckbox.setChecked(NSClientPlugin.getPlugin().paused); - pausedCheckbox.setOnCheckedChangeListener(this); - logTextView = (TextView) view.findViewById(R.id.nsclientinternal_log); - queueTextView = (TextView) view.findViewById(R.id.nsclientinternal_queue); - urlTextView = (TextView) view.findViewById(R.id.nsclientinternal_url); - statusTextView = (TextView) view.findViewById(R.id.nsclientinternal_status); - - clearlog = (TextView) view.findViewById(R.id.nsclientinternal_clearlog); - clearlog.setOnClickListener(this); - clearlog.setPaintFlags(clearlog.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG); - restart = (TextView) view.findViewById(R.id.nsclientinternal_restart); - restart.setOnClickListener(this); - restart.setPaintFlags(restart.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG); - delivernow = (TextView) view.findViewById(R.id.nsclientinternal_delivernow); - delivernow.setOnClickListener(this); - delivernow.setPaintFlags(delivernow.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG); - clearqueue = (TextView) view.findViewById(R.id.nsclientinternal_clearqueue); - clearqueue.setOnClickListener(this); - clearqueue.setPaintFlags(clearqueue.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG); - showqueue = (TextView) view.findViewById(R.id.nsclientinternal_showqueue); - showqueue.setOnClickListener(this); - showqueue.setPaintFlags(showqueue.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG); - - updateGUI(); - return view; - } catch (Exception e) { - FabricPrivacy.logException(e); - } - - return null; - } - - @Override - public void onClick(View view) { - switch (view.getId()) { - case R.id.nsclientinternal_restart: - MainApp.bus().post(new EventNSClientRestart()); - FabricPrivacy.getInstance().logCustom(new CustomEvent("NSClientRestart")); - break; - case R.id.nsclientinternal_delivernow: - NSClientPlugin.getPlugin().resend("GUI"); - FabricPrivacy.getInstance().logCustom(new CustomEvent("NSClientDeliverNow")); - break; - case R.id.nsclientinternal_clearlog: - NSClientPlugin.getPlugin().clearLog(); - break; - case R.id.nsclientinternal_clearqueue: - final Context context = getContext(); - AlertDialog.Builder builder = new AlertDialog.Builder(context); - - builder.setTitle(MainApp.gs(R.string.confirmation)); - builder.setMessage("Clear queue? All data in queue will be lost!"); - builder.setPositiveButton(MainApp.gs(R.string.ok), new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - UploadQueue.clearQueue(); - updateGUI(); - FabricPrivacy.getInstance().logCustom(new CustomEvent("NSClientClearQueue")); - } - }); - builder.setNegativeButton(MainApp.gs(R.string.cancel), null); - builder.show(); - break; - case R.id.nsclientinternal_showqueue: - MainApp.bus().post(new EventNSClientNewLog("QUEUE", NSClientPlugin.getPlugin().queue().textList())); - FabricPrivacy.getInstance().logCustom(new CustomEvent("NSClientShowQueue")); - break; - } - } - - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - switch (buttonView.getId()) { - case R.id.nsclientinternal_paused: - NSClientPlugin.getPlugin().pause(isChecked); - updateGUI(); - FabricPrivacy.getInstance().logCustom(new CustomEvent("NSClientPause")); - break; - case R.id.nsclientinternal_autoscroll: - SP.putBoolean(R.string.key_nsclientinternal_autoscroll, isChecked); - NSClientPlugin.getPlugin().autoscroll = isChecked; - updateGUI(); - break; - } - } - - @Subscribe - public void onStatusEvent(final EventNSClientUpdateGUI ev) { - updateGUI(); - } - - @Override - protected void updateGUI() { - Activity activity = getActivity(); - if (activity != null) - activity.runOnUiThread(() -> { - NSClientPlugin.getPlugin().updateLog(); - pausedCheckbox.setChecked(SP.getBoolean(R.string.key_nsclientinternal_paused, false)); - logTextView.setText(NSClientPlugin.getPlugin().textLog); - if (NSClientPlugin.getPlugin().autoscroll) { - logScrollview.fullScroll(ScrollView.FOCUS_DOWN); - } - urlTextView.setText(NSClientPlugin.getPlugin().url()); - Spanned queuetext = Html.fromHtml(MainApp.gs(R.string.queue) + " " + UploadQueue.size() + ""); - queueTextView.setText(queuetext); - statusTextView.setText(NSClientPlugin.getPlugin().status); - }); - } - -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/events/EventNSClientNewLog.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/events/EventNSClientNewLog.java deleted file mode 100644 index 82b11a812d..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/events/EventNSClientNewLog.java +++ /dev/null @@ -1,33 +0,0 @@ -package info.nightscout.androidaps.plugins.NSClientInternal.events; - -import java.text.SimpleDateFormat; -import java.util.Date; - -import info.nightscout.androidaps.events.Event; - -/** - * Created by mike on 15.02.2017. - */ - -public class EventNSClientNewLog extends Event { - public Date date = new Date(); - public String action; - public String logText; - public EventNSClientNewLog(String action, String logText) { - this.action = action; - this.logText = logText; - } - - SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss"); - - public StringBuilder toPreparedHtml() { - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append(timeFormat.format(date)); - stringBuilder.append(" "); - stringBuilder.append(action); - stringBuilder.append(" "); - stringBuilder.append(logText); - stringBuilder.append("
"); - return stringBuilder; - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/events/EventNSClientRestart.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/events/EventNSClientRestart.java deleted file mode 100644 index b968878da8..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/events/EventNSClientRestart.java +++ /dev/null @@ -1,10 +0,0 @@ -package info.nightscout.androidaps.plugins.NSClientInternal.events; - -import info.nightscout.androidaps.events.Event; - -/** - * Created by mike on 15.02.2017. - */ - -public class EventNSClientRestart extends Event { -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/events/EventNSClientStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/events/EventNSClientStatus.java deleted file mode 100644 index 977c0e31fc..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/events/EventNSClientStatus.java +++ /dev/null @@ -1,18 +0,0 @@ -package info.nightscout.androidaps.plugins.NSClientInternal.events; - -import info.nightscout.androidaps.events.Event; - -/** - * Created by mike on 02.01.2016. - */ -public class EventNSClientStatus extends Event { - public String status = ""; - - public EventNSClientStatus(String status) { - this.status = status; - } - - public EventNSClientStatus() { - } - -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/events/EventNSClientUpdateGUI.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/events/EventNSClientUpdateGUI.java deleted file mode 100644 index dd78d2cd28..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/events/EventNSClientUpdateGUI.java +++ /dev/null @@ -1,10 +0,0 @@ -package info.nightscout.androidaps.plugins.NSClientInternal.events; - -import info.nightscout.androidaps.events.EventUpdateGui; - -/** - * Created by mike on 17.02.2017. - */ - -public class EventNSClientUpdateGUI extends EventUpdateGui { -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/receivers/AutoStartReceiver.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/receivers/AutoStartReceiver.java deleted file mode 100644 index dd5d3330ab..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/receivers/AutoStartReceiver.java +++ /dev/null @@ -1,17 +0,0 @@ -package info.nightscout.androidaps.plugins.NSClientInternal.receivers; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; - -import info.nightscout.androidaps.plugins.NSClientInternal.services.NSClientService; - -public class AutoStartReceiver extends BroadcastReceiver { - public AutoStartReceiver() { - } - - @Override - public void onReceive(Context context, Intent intent) { - context.startService(new Intent(context, NSClientService.class)); - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/receivers/RestartReceiver.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/receivers/RestartReceiver.java deleted file mode 100644 index a38ca842f9..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/receivers/RestartReceiver.java +++ /dev/null @@ -1,25 +0,0 @@ -package info.nightscout.androidaps.plugins.NSClientInternal.receivers; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.support.v4.content.WakefulBroadcastReceiver; - -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientRestart; -import info.nightscout.androidaps.plugins.NSClientInternal.services.NSClientService; - -public class RestartReceiver extends WakefulBroadcastReceiver { - public RestartReceiver() { - } - - @Override - public void onReceive(Context context, Intent intent) { - startWakefulService(context, new Intent(context, NSClientService.class) - .setAction(intent.getAction()) - .putExtras(intent)); - - MainApp.bus().post(new EventNSClientRestart()); - completeWakefulIntent(intent); - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/OpenAPSAMAFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/OpenAPSAMAFragment.java deleted file mode 100644 index 1874816ddc..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/OpenAPSAMAFragment.java +++ /dev/null @@ -1,137 +0,0 @@ -package info.nightscout.androidaps.plugins.OpenAPSAMA; - -import android.app.Activity; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Button; -import android.widget.TextView; - -import com.crashlytics.android.answers.CustomEvent; -import com.squareup.otto.Subscribe; - -import org.json.JSONArray; -import org.json.JSONException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.Common.SubscriberFragment; -import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateGui; -import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateResultGui; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.FabricPrivacy; -import info.nightscout.utils.JSONFormatter; - -public class OpenAPSAMAFragment extends SubscriberFragment implements View.OnClickListener { - private static Logger log = LoggerFactory.getLogger(L.APS); - - Button run; - TextView lastRunView; - TextView glucoseStatusView; - TextView currentTempView; - TextView iobDataView; - TextView profileView; - TextView mealDataView; - TextView autosensDataView; - TextView resultView; - TextView scriptdebugView; - TextView requestView; - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.openapsama_fragment, container, false); - - run = (Button) view.findViewById(R.id.openapsma_run); - run.setOnClickListener(this); - lastRunView = (TextView) view.findViewById(R.id.openapsma_lastrun); - glucoseStatusView = (TextView) view.findViewById(R.id.openapsma_glucosestatus); - currentTempView = (TextView) view.findViewById(R.id.openapsma_currenttemp); - iobDataView = (TextView) view.findViewById(R.id.openapsma_iobdata); - profileView = (TextView) view.findViewById(R.id.openapsma_profile); - mealDataView = (TextView) view.findViewById(R.id.openapsma_mealdata); - autosensDataView = (TextView) view.findViewById(R.id.openapsma_autosensdata); - scriptdebugView = (TextView) view.findViewById(R.id.openapsma_scriptdebugdata); - resultView = (TextView) view.findViewById(R.id.openapsma_result); - requestView = (TextView) view.findViewById(R.id.openapsma_request); - - updateGUI(); - return view; - } - - @Override - public void onClick(View view) { - switch (view.getId()) { - case R.id.openapsma_run: - OpenAPSAMAPlugin.getPlugin().invoke("OpenAPSAMA button", false); - FabricPrivacy.getInstance().logCustom(new CustomEvent("OpenAPS_AMA_Run")); - break; - } - - } - - @Subscribe - public void onStatusEvent(final EventOpenAPSUpdateGui ev) { - updateGUI(); - } - - @Subscribe - public void onStatusEvent(final EventOpenAPSUpdateResultGui ev) { - updateResultGUI(ev.text); - } - - @Override - protected void updateGUI() { - Activity activity = getActivity(); - if (activity != null) - activity.runOnUiThread(() -> { - DetermineBasalResultAMA lastAPSResult = OpenAPSAMAPlugin.getPlugin().lastAPSResult; - if (lastAPSResult != null) { - resultView.setText(JSONFormatter.format(lastAPSResult.json)); - requestView.setText(lastAPSResult.toSpanned()); - } - DetermineBasalAdapterAMAJS determineBasalAdapterAMAJS = OpenAPSAMAPlugin.getPlugin().lastDetermineBasalAdapterAMAJS; - if (determineBasalAdapterAMAJS != null) { - glucoseStatusView.setText(JSONFormatter.format(determineBasalAdapterAMAJS.getGlucoseStatusParam())); - currentTempView.setText(JSONFormatter.format(determineBasalAdapterAMAJS.getCurrentTempParam())); - try { - JSONArray iobArray = new JSONArray(determineBasalAdapterAMAJS.getIobDataParam()); - iobDataView.setText(String.format(MainApp.gs(R.string.array_of_elements), iobArray.length()) + "\n" + JSONFormatter.format(iobArray.getString(0))); - } catch (JSONException e) { - log.error("Unhandled exception", e); - iobDataView.setText("JSONException"); - } - profileView.setText(JSONFormatter.format(determineBasalAdapterAMAJS.getProfileParam())); - mealDataView.setText(JSONFormatter.format(determineBasalAdapterAMAJS.getMealDataParam())); - scriptdebugView.setText(determineBasalAdapterAMAJS.getScriptDebug()); - } - if (OpenAPSAMAPlugin.getPlugin().lastAPSRun != 0) { - lastRunView.setText(DateUtil.dateAndTimeFullString(OpenAPSAMAPlugin.getPlugin().lastAPSRun)); - } - if (OpenAPSAMAPlugin.getPlugin().lastAutosensResult != null) { - autosensDataView.setText(JSONFormatter.format(OpenAPSAMAPlugin.getPlugin().lastAutosensResult.json())); - } - }); - } - - void updateResultGUI(final String text) { - Activity activity = getActivity(); - if (activity != null) - activity.runOnUiThread(() -> { - resultView.setText(text); - glucoseStatusView.setText(""); - currentTempView.setText(""); - iobDataView.setText(""); - profileView.setText(""); - mealDataView.setText(""); - autosensDataView.setText(""); - scriptdebugView.setText(""); - requestView.setText(""); - lastRunView.setText(""); - }); - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/OpenAPSMAFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/OpenAPSMAFragment.java deleted file mode 100644 index 12d7988a16..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/OpenAPSMAFragment.java +++ /dev/null @@ -1,118 +0,0 @@ -package info.nightscout.androidaps.plugins.OpenAPSMA; - -import android.app.Activity; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Button; -import android.widget.TextView; - -import com.crashlytics.android.answers.CustomEvent; -import com.squareup.otto.Subscribe; - -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.plugins.Common.SubscriberFragment; -import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateGui; -import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateResultGui; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.FabricPrivacy; -import info.nightscout.utils.JSONFormatter; - -public class OpenAPSMAFragment extends SubscriberFragment implements View.OnClickListener { - Button run; - TextView lastRunView; - TextView glucoseStatusView; - TextView currentTempView; - TextView iobDataView; - TextView profileView; - TextView mealDataView; - TextView resultView; - TextView requestView; - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - try { - View view = inflater.inflate(R.layout.openapsma_fragment, container, false); - - run = (Button) view.findViewById(R.id.openapsma_run); - run.setOnClickListener(this); - lastRunView = (TextView) view.findViewById(R.id.openapsma_lastrun); - glucoseStatusView = (TextView) view.findViewById(R.id.openapsma_glucosestatus); - currentTempView = (TextView) view.findViewById(R.id.openapsma_currenttemp); - iobDataView = (TextView) view.findViewById(R.id.openapsma_iobdata); - profileView = (TextView) view.findViewById(R.id.openapsma_profile); - mealDataView = (TextView) view.findViewById(R.id.openapsma_mealdata); - resultView = (TextView) view.findViewById(R.id.openapsma_result); - requestView = (TextView) view.findViewById(R.id.openapsma_request); - - updateGUI(); - return view; - } catch (Exception e) { - FabricPrivacy.logException(e); - } - - return null; - } - - @Override - public void onClick(View view) { - switch (view.getId()) { - case R.id.openapsma_run: - OpenAPSMAPlugin.getPlugin().invoke("OpenAPSMA button", false); - FabricPrivacy.getInstance().logCustom(new CustomEvent("OpenAPS_MA_Run")); - break; - } - - } - - @Subscribe - public void onStatusEvent(final EventOpenAPSUpdateGui ev) { - updateGUI(); - } - - @Subscribe - public void onStatusEvent(final EventOpenAPSUpdateResultGui ev) { - updateResultGUI(ev.text); - } - - @Override - protected void updateGUI() { - Activity activity = getActivity(); - if (activity != null) - activity.runOnUiThread(() -> { - DetermineBasalResultMA lastAPSResult = OpenAPSMAPlugin.getPlugin().lastAPSResult; - if (lastAPSResult != null) { - resultView.setText(JSONFormatter.format(lastAPSResult.json)); - requestView.setText(lastAPSResult.toSpanned()); - } - DetermineBasalAdapterMAJS determineBasalAdapterMAJS = OpenAPSMAPlugin.getPlugin().lastDetermineBasalAdapterMAJS; - if (determineBasalAdapterMAJS != null) { - glucoseStatusView.setText(JSONFormatter.format(determineBasalAdapterMAJS.getGlucoseStatusParam())); - currentTempView.setText(JSONFormatter.format(determineBasalAdapterMAJS.getCurrentTempParam())); - iobDataView.setText(JSONFormatter.format(determineBasalAdapterMAJS.getIobDataParam())); - profileView.setText(JSONFormatter.format(determineBasalAdapterMAJS.getProfileParam())); - mealDataView.setText(JSONFormatter.format(determineBasalAdapterMAJS.getMealDataParam())); - } - if (OpenAPSMAPlugin.getPlugin().lastAPSRun != 0) { - lastRunView.setText(DateUtil.dateAndTimeFullString(OpenAPSMAPlugin.getPlugin().lastAPSRun)); - } - }); - } - - private void updateResultGUI(final String text) { - Activity activity = getActivity(); - if (activity != null) - activity.runOnUiThread(() -> { - resultView.setText(text); - glucoseStatusView.setText(""); - currentTempView.setText(""); - iobDataView.setText(""); - profileView.setText(""); - mealDataView.setText(""); - requestView.setText(""); - lastRunView.setText(""); - }); - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/events/EventOpenAPSUpdateGui.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/events/EventOpenAPSUpdateGui.java deleted file mode 100644 index 40f3c31973..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/events/EventOpenAPSUpdateGui.java +++ /dev/null @@ -1,9 +0,0 @@ -package info.nightscout.androidaps.plugins.OpenAPSMA.events; - -import info.nightscout.androidaps.events.EventUpdateGui; - -/** - * Created by mike on 05.08.2016. - */ -public class EventOpenAPSUpdateGui extends EventUpdateGui { -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/events/EventOpenAPSUpdateResultGui.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/events/EventOpenAPSUpdateResultGui.java deleted file mode 100644 index 177133f155..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/events/EventOpenAPSUpdateResultGui.java +++ /dev/null @@ -1,14 +0,0 @@ -package info.nightscout.androidaps.plugins.OpenAPSMA.events; - -import info.nightscout.androidaps.events.EventUpdateGui; - -/** - * Created by mike on 05.08.2016. - */ -public class EventOpenAPSUpdateResultGui extends EventUpdateGui { - public String text; - - public EventOpenAPSUpdateResultGui(String text) { - this.text = text; - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/OpenAPSSMBFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/OpenAPSSMBFragment.java deleted file mode 100644 index d27f8b31d0..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/OpenAPSSMBFragment.java +++ /dev/null @@ -1,160 +0,0 @@ -package info.nightscout.androidaps.plugins.OpenAPSSMB; - -import android.app.Activity; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Button; -import android.widget.TextView; - -import com.crashlytics.android.answers.CustomEvent; -import com.squareup.otto.Subscribe; - -import org.json.JSONArray; -import org.json.JSONException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import butterknife.BindView; -import butterknife.ButterKnife; -import butterknife.OnClick; -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.Common.SubscriberFragment; -import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateGui; -import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateResultGui; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.FabricPrivacy; -import info.nightscout.utils.JSONFormatter; - -public class OpenAPSSMBFragment extends SubscriberFragment { - private static Logger log = LoggerFactory.getLogger(L.APS); - - @BindView(R.id.openapsma_run) - Button run; - @BindView(R.id.openapsma_lastrun) - TextView lastRunView; - @BindView(R.id.openapsma_constraints) - TextView constraintsView; - @BindView(R.id.openapsma_glucosestatus) - TextView glucoseStatusView; - @BindView(R.id.openapsma_currenttemp) - TextView currentTempView; - @BindView(R.id.openapsma_iobdata) - TextView iobDataView; - @BindView(R.id.openapsma_profile) - TextView profileView; - @BindView(R.id.openapsma_mealdata) - TextView mealDataView; - @BindView(R.id.openapsma_autosensdata) - TextView autosensDataView; - @BindView(R.id.openapsma_result) - TextView resultView; - @BindView(R.id.openapsma_scriptdebugdata) - TextView scriptdebugView; - @BindView(R.id.openapsma_request) - TextView requestView; - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.openapsama_fragment, container, false); - - unbinder = ButterKnife.bind(this, view); - return view; - } - - @OnClick(R.id.openapsma_run) - public void onRunClick() { - OpenAPSSMBPlugin.getPlugin().invoke("OpenAPSSMB button", false); - FabricPrivacy.getInstance().logCustom(new CustomEvent("OpenAPS_SMB_Run")); - } - - @Subscribe - public void onStatusEvent(final EventOpenAPSUpdateGui ev) { - updateGUI(); - } - - @Subscribe - public void onStatusEvent(final EventOpenAPSUpdateResultGui ev) { - updateResultGUI(ev.text); - } - - @Override - protected void updateGUI() { - Activity activity = getActivity(); - if (activity != null) - activity.runOnUiThread(() -> { - synchronized (OpenAPSSMBFragment.this) { - if (!isBound()) return; - OpenAPSSMBPlugin plugin = OpenAPSSMBPlugin.getPlugin(); - DetermineBasalResultSMB lastAPSResult = plugin.lastAPSResult; - if (lastAPSResult != null) { - resultView.setText(JSONFormatter.format(lastAPSResult.json)); - requestView.setText(lastAPSResult.toSpanned()); - } - DetermineBasalAdapterSMBJS determineBasalAdapterSMBJS = plugin.lastDetermineBasalAdapterSMBJS; - if (determineBasalAdapterSMBJS != null) { - glucoseStatusView.setText(JSONFormatter.format(determineBasalAdapterSMBJS.getGlucoseStatusParam()).toString().trim()); - currentTempView.setText(JSONFormatter.format(determineBasalAdapterSMBJS.getCurrentTempParam()).toString().trim()); - try { - JSONArray iobArray = new JSONArray(determineBasalAdapterSMBJS.getIobDataParam()); - iobDataView.setText((String.format(MainApp.gs(R.string.array_of_elements), iobArray.length()) + "\n" + JSONFormatter.format(iobArray.getString(0))).trim()); - } catch (JSONException e) { - log.error("Unhandled exception", e); - iobDataView.setText("JSONException see log for details"); - } - profileView.setText(JSONFormatter.format(determineBasalAdapterSMBJS.getProfileParam()).toString().trim()); - mealDataView.setText(JSONFormatter.format(determineBasalAdapterSMBJS.getMealDataParam()).toString().trim()); - scriptdebugView.setText(determineBasalAdapterSMBJS.getScriptDebug().trim()); - if (lastAPSResult != null && lastAPSResult.inputConstraints != null) - constraintsView.setText(lastAPSResult.inputConstraints.getReasons().trim()); - } - if (plugin.lastAPSRun != 0) { - lastRunView.setText(DateUtil.dateAndTimeFullString(plugin.lastAPSRun)); - } - if (plugin.lastAutosensResult != null) { - autosensDataView.setText(JSONFormatter.format(plugin.lastAutosensResult.json()).toString().trim()); - } - } - }); - } - - void updateResultGUI(final String text) { - Activity activity = getActivity(); - if (activity != null) - activity.runOnUiThread(() -> { - synchronized (OpenAPSSMBFragment.this) { - if (isBound()) { - resultView.setText(text); - glucoseStatusView.setText(""); - currentTempView.setText(""); - iobDataView.setText(""); - profileView.setText(""); - mealDataView.setText(""); - autosensDataView.setText(""); - scriptdebugView.setText(""); - requestView.setText(""); - lastRunView.setText(""); - } - } - }); - } - - private boolean isBound() { - return run != null - && lastRunView != null - && constraintsView != null - && glucoseStatusView != null - && currentTempView != null - && iobDataView != null - && profileView != null - && mealDataView != null - && autosensDataView != null - && resultView != null - && scriptdebugView != null - && requestView != null; - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/BolusProgressHelperActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/BolusProgressHelperActivity.java deleted file mode 100644 index 6fddc218ac..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/BolusProgressHelperActivity.java +++ /dev/null @@ -1,24 +0,0 @@ -package info.nightscout.androidaps.plugins.Overview.Dialogs; - -import android.os.Bundle; -import android.support.v7.app.AppCompatActivity; - -/** - * Created by adrian on 09/02/17. - */ - -public class BolusProgressHelperActivity extends AppCompatActivity { - public BolusProgressHelperActivity() { - super(); - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - this.getIntent().getDoubleExtra("insulin", 0d); - BolusProgressDialog bolusProgressDialog = new BolusProgressDialog(); - bolusProgressDialog.setHelperActivity(this); - bolusProgressDialog.setInsulin(this.getIntent().getDoubleExtra("insulin", 0d)); - bolusProgressDialog.show(this.getSupportFragmentManager(), "BolusProgress"); - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/EditQuickWizardDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/EditQuickWizardDialog.java deleted file mode 100644 index 50de25b656..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/EditQuickWizardDialog.java +++ /dev/null @@ -1,190 +0,0 @@ -package info.nightscout.androidaps.plugins.Overview.Dialogs; - - -import android.os.Bundle; -import android.support.v4.app.DialogFragment; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.view.Window; -import android.view.WindowManager; -import android.widget.ArrayAdapter; -import android.widget.EditText; -import android.widget.Spinner; - -import org.json.JSONException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; - -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.data.QuickWizard; -import info.nightscout.androidaps.data.QuickWizardEntry; -import info.nightscout.androidaps.plugins.Overview.OverviewPlugin; -import info.nightscout.androidaps.plugins.Overview.events.EventQuickWizardChange; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.SafeParse; - -public class EditQuickWizardDialog extends DialogFragment implements View.OnClickListener { - private static Logger log = LoggerFactory.getLogger(EditQuickWizardDialog.class); - - QuickWizardEntry entry = new QuickWizard().newEmptyItem(); - QuickWizard quickWizard = MainApp.getSpecificPlugin(OverviewPlugin.class).quickWizard; - - EditText buttonEdit; - EditText carbsEdit; - Spinner fromSpinner; - Spinner toSpinner; - Spinner useBGSpinner; - Spinner useCOBSpinner; - Spinner useBolusIOBSpinner; - Spinner useBasalIOBSpinner; - Spinner useTrendSpinner; - Spinner useSuperBolusSpinner; - Spinner useTempTargetSpinner; - - public EditQuickWizardDialog() { - } - - public void setData(QuickWizardEntry data) { - entry = data; - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE); - getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); - - View view = inflater.inflate(R.layout.overview_editquickwizard_dialog, container, false); - buttonEdit = (EditText) view.findViewById(R.id.overview_editquickwizard_button_edit); - carbsEdit = (EditText) view.findViewById(R.id.overview_editquickwizard_carbs_edit); - fromSpinner = (Spinner) view.findViewById(R.id.overview_editquickwizard_from_spinner); - toSpinner = (Spinner) view.findViewById(R.id.overview_editquickwizard_to_spinner); - useBGSpinner = (Spinner) view.findViewById(R.id.overview_editquickwizard_usebg_spinner); - useCOBSpinner = (Spinner) view.findViewById(R.id.overview_editquickwizard_usecob_spinner); - useBolusIOBSpinner = (Spinner) view.findViewById(R.id.overview_editquickwizard_usebolusiob_spinner); - useBasalIOBSpinner = (Spinner) view.findViewById(R.id.overview_editquickwizard_usebasaliob_spinner); - useTrendSpinner = (Spinner) view.findViewById(R.id.overview_editquickwizard_usetrend_spinner); - useSuperBolusSpinner = (Spinner) view.findViewById(R.id.overview_editquickwizard_usesuperbolus_spinner); - useTempTargetSpinner = (Spinner) view.findViewById(R.id.overview_editquickwizard_usetemptarget_spinner); - - view.findViewById(R.id.ok).setOnClickListener(this); - view.findViewById(R.id.cancel).setOnClickListener(this); - - int posFrom = 0; - int posTo = 95; - ArrayList timeList = new ArrayList<>(); - int pos = 0; - for (int t = 0; t < 24 * 60 * 60; t += 15 * 60) { - timeList.add(DateUtil.timeString(DateUtil.toDate(t))); - if (entry.validFrom() == t) posFrom = pos; - if (entry.validTo() == t) posTo = pos; - pos++; - } - timeList.add(DateUtil.timeString(DateUtil.toDate(24 * 60 * 60 - 60))); - - ArrayAdapter adapter = new ArrayAdapter(getContext(), - R.layout.spinner_centered, timeList); - fromSpinner.setAdapter(adapter); - toSpinner.setAdapter(adapter); - - buttonEdit.setText(entry.buttonText()); - carbsEdit.setText(entry.carbs().toString()); - fromSpinner.setSelection(posFrom); - toSpinner.setSelection(posTo); - - setSelection(useBGSpinner, entry.useBG()); - setSelection(useCOBSpinner, entry.useCOB()); - setSelection(useBolusIOBSpinner, entry.useBolusIOB()); - setSelection(useBasalIOBSpinner, entry.useBasalIOB()); - setSelection(useTrendSpinner, entry.useTrend()); - setSelection(useSuperBolusSpinner, entry.useSuperBolus()); - setSelection(useTempTargetSpinner, entry.useTempTarget()); - - return view; - } - - @Override - public void onResume() { - super.onResume(); - if (getDialog() != null) - getDialog().getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); - } - - @Override - public void onClick(View v) { - switch (v.getId()) { - case R.id.ok: - if (fromSpinner.getSelectedItem() == null) return; - if (toSpinner.getSelectedItem() == null) return; - try { - entry.storage.put("buttonText", buttonEdit.getText().toString()); - entry.storage.put("carbs", SafeParse.stringToInt(carbsEdit.getText().toString())); - int validFromInt = DateUtil.toSeconds(fromSpinner.getSelectedItem().toString()); - entry.storage.put("validFrom", validFromInt); - int validToInt = DateUtil.toSeconds(toSpinner.getSelectedItem().toString()); - entry.storage.put("validTo", validToInt); - entry.storage.put("useBG", getSelection(useBGSpinner)); - entry.storage.put("useCOB", getSelection(useCOBSpinner)); - entry.storage.put("useBolusIOB", getSelection(useBolusIOBSpinner)); - entry.storage.put("useBasalIOB", getSelection(useBasalIOBSpinner)); - entry.storage.put("useTrend", getSelection(useTrendSpinner)); - entry.storage.put("useSuperBolus", getSelection(useSuperBolusSpinner)); - entry.storage.put("useTempTarget", getSelection(useTempTargetSpinner)); - } catch (JSONException e) { - log.error("Unhandled exception", e); - } - quickWizard.addOrUpdate(entry); - dismiss(); - MainApp.bus().post(new EventQuickWizardChange()); - break; - case R.id.cancel: - dismiss(); - break; - } - } - - int getSelection(Spinner spinner) { - String value = spinner.getSelectedItem().toString(); - if (value.equals(MainApp.gs(R.string.yes))) - return QuickWizardEntry.YES; - if (value.equals(MainApp.gs(R.string.no))) - return QuickWizardEntry.NO; - if (value.equals(MainApp.gs(R.string.positiveonly))) - return QuickWizardEntry.POSITIVE_ONLY; - if (value.equals(MainApp.gs(R.string.negativeonly))) - return QuickWizardEntry.NEGATIVE_ONLY; - return QuickWizardEntry.NO; - } - - void setSelection(Spinner spinner, int value) { - String selection; - switch (value) { - case QuickWizardEntry.YES: - selection = MainApp.gs(R.string.yes); - break; - case QuickWizardEntry.NO: - selection = MainApp.gs(R.string.no); - break; - case QuickWizardEntry.POSITIVE_ONLY: - selection = MainApp.gs(R.string.positiveonly); - break; - case QuickWizardEntry.NEGATIVE_ONLY: - selection = MainApp.gs(R.string.negativeonly); - break; - default: - selection = MainApp.gs(R.string.no); - break; - } - - for (int i = 0; i < spinner.getCount(); i++) { - if (spinner.getItemAtPosition(i).toString().equalsIgnoreCase(selection)) { - spinner.setSelection(i); - break; - } - } - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/ErrorDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/ErrorDialog.java deleted file mode 100644 index dc4fa21aca..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/ErrorDialog.java +++ /dev/null @@ -1,108 +0,0 @@ -package info.nightscout.androidaps.plugins.Overview.Dialogs; - - -import android.content.Intent; -import android.os.Bundle; -import android.support.v4.app.DialogFragment; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Button; -import android.widget.TextView; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.services.AlarmSoundService; - -public class ErrorDialog extends DialogFragment implements View.OnClickListener { - private static Logger log = LoggerFactory.getLogger(ErrorDialog.class); - Button muteButton; - Button okButton; - TextView statusView; - ErrorHelperActivity helperActivity; - - static String status; - static String title; - static int soundId; - - public ErrorDialog() { - super(); - } - - public void setStatus(String status) { - this.status = status; - } - - public void setTitle(String title) { - this.title = title; - } - - public void setSound(int soundId) { - this.soundId = soundId; - } - - public void setHelperActivity(ErrorHelperActivity activity) { - this.helperActivity = activity; - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - getDialog().setTitle(title); - View view = inflater.inflate(R.layout.overview_error_dialog, container, false); - muteButton = (Button) view.findViewById(R.id.overview_error_mute); - okButton = (Button) view.findViewById(R.id.overview_error_ok); - statusView = (TextView) view.findViewById(R.id.overview_error_status); - muteButton.setOnClickListener(this); - okButton.setOnClickListener(this); - setCancelable(false); - - startAlarm(); - return view; - } - - @Override - public void onResume() { - super.onResume(); - if (getDialog() != null) - getDialog().getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); - statusView.setText(status); - } - - @Override - public void dismiss() { - super.dismissAllowingStateLoss(); - if (helperActivity != null) { - helperActivity.finish(); - } - stopAlarm(); - } - - @Override - public void onClick(View view) { - switch (view.getId()) { - case R.id.overview_error_mute: - log.debug("Error dialog mute button pressed"); - stopAlarm(); - break; - case R.id.overview_error_ok: - log.debug("Error dialog ok button pressed"); - dismiss(); - break; - } - } - - private void startAlarm() { - Intent alarm = new Intent(MainApp.instance().getApplicationContext(), AlarmSoundService.class); - alarm.putExtra("soundid", soundId); - MainApp.instance().startService(alarm); - } - - private void stopAlarm() { - Intent alarm = new Intent(MainApp.instance().getApplicationContext(), AlarmSoundService.class); - MainApp.instance().stopService(alarm); - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/ErrorHelperActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/ErrorHelperActivity.java deleted file mode 100644 index c556a6c844..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/ErrorHelperActivity.java +++ /dev/null @@ -1,29 +0,0 @@ -package info.nightscout.androidaps.plugins.Overview.Dialogs; - -import android.os.Bundle; -import android.support.v7.app.AppCompatActivity; - -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.plugins.NSClientInternal.NSUpload; -import info.nightscout.utils.SP; - -public class ErrorHelperActivity extends AppCompatActivity { - public ErrorHelperActivity() { - super(); - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - ErrorDialog errorDialog = new ErrorDialog(); - errorDialog.setHelperActivity(this); - errorDialog.setStatus(getIntent().getStringExtra("status")); - errorDialog.setSound(getIntent().getIntExtra("soundid", 0)); - errorDialog.setTitle(getIntent().getStringExtra("title")); - errorDialog.show(this.getSupportFragmentManager(), "Error"); - - if (SP.getBoolean(R.string.key_ns_create_announcements_from_errors, true)) { - NSUpload.uploadError(getIntent().getStringExtra("status")); - } - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialog.java deleted file mode 100644 index 1b6a4f2ff8..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialog.java +++ /dev/null @@ -1,613 +0,0 @@ -package info.nightscout.androidaps.plugins.Overview.Dialogs; - -import android.app.Activity; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.os.Bundle; -import android.support.v4.app.DialogFragment; -import android.support.v7.app.AlertDialog; -import android.text.Editable; -import android.text.Html; -import android.text.TextWatcher; -import android.view.LayoutInflater; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.ViewGroup; -import android.view.Window; -import android.view.WindowManager; -import android.widget.AdapterView; -import android.widget.ArrayAdapter; -import android.widget.Button; -import android.widget.CheckBox; -import android.widget.CompoundButton; -import android.widget.EditText; -import android.widget.LinearLayout; -import android.widget.Spinner; -import android.widget.TextView; - -import com.crashlytics.android.answers.CustomEvent; -import com.squareup.otto.Subscribe; - -import org.json.JSONException; -import org.json.JSONObject; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.text.DecimalFormat; -import java.util.ArrayList; -import java.util.Date; - -import info.nightscout.androidaps.Constants; -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.data.DetailedBolusInfo; -import info.nightscout.androidaps.data.IobTotal; -import info.nightscout.androidaps.data.Profile; -import info.nightscout.androidaps.data.ProfileStore; -import info.nightscout.androidaps.db.BgReading; -import info.nightscout.androidaps.db.CareportalEvent; -import info.nightscout.androidaps.db.DatabaseHelper; -import info.nightscout.androidaps.db.Source; -import info.nightscout.androidaps.db.TempTarget; -import info.nightscout.androidaps.events.EventFeatureRunning; -import info.nightscout.androidaps.events.EventNewBG; -import info.nightscout.androidaps.events.EventRefreshOverview; -import info.nightscout.androidaps.interfaces.Constraint; -import info.nightscout.androidaps.interfaces.PluginType; -import info.nightscout.androidaps.interfaces.PumpInterface; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions; -import info.nightscout.androidaps.plugins.IobCobCalculator.CobInfo; -import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin; -import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventAutosensCalculationFinished; -import info.nightscout.androidaps.plugins.Loop.LoopPlugin; -import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; -import info.nightscout.androidaps.queue.Callback; -import info.nightscout.utils.BolusWizard; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.DecimalFormatter; -import info.nightscout.utils.FabricPrivacy; -import info.nightscout.utils.NumberPicker; -import info.nightscout.utils.SP; -import info.nightscout.utils.SafeParse; -import info.nightscout.utils.ToastUtils; - -public class WizardDialog extends DialogFragment implements OnClickListener, CompoundButton.OnCheckedChangeListener, Spinner.OnItemSelectedListener { - private static Logger log = LoggerFactory.getLogger(WizardDialog.class); - - Button okButton; - TextView bg; - TextView bgInsulin; - TextView bgUnits; - CheckBox bgCheckbox; - CheckBox ttCheckbox; - TextView carbs; - TextView carbsInsulin; - TextView bolusIobInsulin; - TextView basalIobInsulin; - CheckBox bolusIobCheckbox; - CheckBox basalIobCheckbox; - TextView correctionInsulin; - TextView total; - Spinner profileSpinner; - CheckBox superbolusCheckbox; - TextView superbolus; - TextView superbolusInsulin; - CheckBox bgtrendCheckbox; - TextView bgTrend; - TextView bgTrendInsulin; - LinearLayout cobLayout; - CheckBox cobCheckbox; - TextView cob; - TextView cobInsulin; - - NumberPicker editBg; - NumberPicker editCarbs; - NumberPicker editCorr; - NumberPicker editCarbTime; - - LinearLayout notesLayout; - EditText notesEdit; - - Integer calculatedCarbs = 0; - Double calculatedTotalInsulin = 0d; - JSONObject boluscalcJSON; - - Context context; - - //one shot guards - private boolean accepted; - private boolean okClicked; - - public WizardDialog() { - super(); - } - - @Override - public void onAttach(Context context) { - super.onAttach(context); - this.context = context; - } - - @Override - public void onDetach() { - super.onDetach(); - this.context = null; - } - - @Override - public void onResume() { - super.onResume(); - MainApp.bus().register(this); - MainApp.bus().post(new EventFeatureRunning(EventFeatureRunning.Feature.WIZARD)); - } - - @Override - public void onPause() { - super.onPause(); - MainApp.bus().unregister(this); - } - - @Override - public void onSaveInstanceState(Bundle savedInstanceState) { - savedInstanceState.putBoolean("bgCheckbox", bgCheckbox.isChecked()); - savedInstanceState.putBoolean("ttCheckbox", ttCheckbox.isChecked()); - savedInstanceState.putBoolean("bolusIobCheckbox", bolusIobCheckbox.isChecked()); - savedInstanceState.putBoolean("basalIobCheckbox", basalIobCheckbox.isChecked()); - savedInstanceState.putBoolean("bgtrendCheckbox", bgtrendCheckbox.isChecked()); - savedInstanceState.putBoolean("cobCheckbox", cobCheckbox.isChecked()); - savedInstanceState.putDouble("editBg", editBg.getValue()); - savedInstanceState.putDouble("editCarbs", editCarbs.getValue()); - savedInstanceState.putDouble("editCorr", editCorr.getValue()); - savedInstanceState.putDouble("editCarbTime", editCarbTime.getValue()); - super.onSaveInstanceState(savedInstanceState); - } - - - @Subscribe - public void onStatusEvent(final EventNewBG e) { - Activity activity = getActivity(); - if (activity != null) - activity.runOnUiThread(new Runnable() { - @Override - public void run() { - calculateInsulin(); - } - }); - } - - @Subscribe - public void onStatusEvent(final EventAutosensCalculationFinished e) { - Activity activity = getActivity(); - if (activity != null) - activity.runOnUiThread(new Runnable() { - @Override - public void run() { - calculateInsulin(); - } - }); - } - - final private TextWatcher textWatcher = new TextWatcher() { - @Override - public void afterTextChanged(Editable s) { - } - - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - } - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - calculateInsulin(); - } - }; - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.overview_wizard_dialog, container, false); - - getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE); - getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); - - okButton = (Button) view.findViewById(R.id.ok); - okButton.setOnClickListener(this); - view.findViewById(R.id.cancel).setOnClickListener(this); - - bg = (TextView) view.findViewById(R.id.treatments_wizard_bg); - bgInsulin = (TextView) view.findViewById(R.id.treatments_wizard_bginsulin); - bgUnits = (TextView) view.findViewById(R.id.treatments_wizard_bgunits); - carbs = (TextView) view.findViewById(R.id.treatments_wizard_carbs); - carbsInsulin = (TextView) view.findViewById(R.id.treatments_wizard_carbsinsulin); - bolusIobInsulin = (TextView) view.findViewById(R.id.treatments_wizard_bolusiobinsulin); - basalIobInsulin = (TextView) view.findViewById(R.id.treatments_wizard_basaliobinsulin); - correctionInsulin = (TextView) view.findViewById(R.id.treatments_wizard_correctioninsulin); - total = (TextView) view.findViewById(R.id.treatments_wizard_total); - superbolus = (TextView) view.findViewById(R.id.treatments_wizard_sb); - superbolusInsulin = (TextView) view.findViewById(R.id.treatments_wizard_sbinsulin); - - notesLayout = view.findViewById(R.id.treatments_wizard_notes_layout); - notesLayout.setVisibility(SP.getBoolean(R.string.key_show_notes_entry_dialogs, false) ? View.VISIBLE : View.GONE); - notesEdit = (EditText) view.findViewById(R.id.treatment_wizard_notes); - - bgTrend = (TextView) view.findViewById(R.id.treatments_wizard_bgtrend); - bgTrendInsulin = (TextView) view.findViewById(R.id.treatments_wizard_bgtrendinsulin); - cobLayout = (LinearLayout) view.findViewById(R.id.treatments_wizard_cob_layout); - cob = (TextView) view.findViewById(R.id.treatments_wizard_cob); - cobInsulin = (TextView) view.findViewById(R.id.treatments_wizard_cobinsulin); - - bgCheckbox = (CheckBox) view.findViewById(R.id.treatments_wizard_bgcheckbox); - ttCheckbox = (CheckBox) view.findViewById(R.id.treatments_wizard_ttcheckbox); - bgtrendCheckbox = (CheckBox) view.findViewById(R.id.treatments_wizard_bgtrendcheckbox); - cobCheckbox = (CheckBox) view.findViewById(R.id.treatments_wizard_cobcheckbox); - bolusIobCheckbox = (CheckBox) view.findViewById(R.id.treatments_wizard_bolusiobcheckbox); - basalIobCheckbox = (CheckBox) view.findViewById(R.id.treatments_wizard_basaliobcheckbox); - superbolusCheckbox = (CheckBox) view.findViewById(R.id.treatments_wizard_sbcheckbox); - loadCheckedStates(); - - bgCheckbox.setOnCheckedChangeListener(this); - ttCheckbox.setOnCheckedChangeListener(this); - bgtrendCheckbox.setOnCheckedChangeListener(this); - cobCheckbox.setOnCheckedChangeListener(this); - basalIobCheckbox.setOnCheckedChangeListener(this); - bolusIobCheckbox.setOnCheckedChangeListener(this); - superbolusCheckbox.setOnCheckedChangeListener(this); - - profileSpinner = (Spinner) view.findViewById(R.id.treatments_wizard_profile); - profileSpinner.setOnItemSelectedListener(this); - - editCarbTime = (NumberPicker) view.findViewById(R.id.treatments_wizard_carbtimeinput); - editCorr = (NumberPicker) view.findViewById(R.id.treatments_wizard_correctioninput); - editCarbs = (NumberPicker) view.findViewById(R.id.treatments_wizard_carbsinput); - editBg = (NumberPicker) view.findViewById(R.id.treatments_wizard_bginput); - - superbolusCheckbox.setVisibility(SP.getBoolean(R.string.key_usesuperbolus, false) ? View.VISIBLE : View.GONE); - - Integer maxCarbs = MainApp.getConstraintChecker().getMaxCarbsAllowed().value(); - Double maxCorrection = MainApp.getConstraintChecker().getMaxBolusAllowed().value(); - - editBg.setParams(0d, 0d, 500d, 0.1d, new DecimalFormat("0.0"), false, textWatcher); - editCarbs.setParams(0d, 0d, (double) maxCarbs, 1d, new DecimalFormat("0"), false, textWatcher); - double bolusstep = ConfigBuilderPlugin.getPlugin().getActivePump().getPumpDescription().bolusStep; - editCorr.setParams(0d, -maxCorrection, maxCorrection, bolusstep, DecimalFormatter.pumpSupportedBolusFormat(), false, textWatcher); - editCarbTime.setParams(0d, -60d, 60d, 5d, new DecimalFormat("0"), false); - initDialog(); - - setCancelable(true); - getDialog().setCanceledOnTouchOutside(false); - //recovering state if there is something - if (savedInstanceState != null) { - editCarbs.setValue(savedInstanceState.getDouble("editCarbs")); - editBg.setValue(savedInstanceState.getDouble("editBg")); - editCarbTime.setValue(savedInstanceState.getDouble("editCarbTime")); - editCorr.setValue(savedInstanceState.getDouble("editCorr")); - } - return view; - } - - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - saveCheckedStates(); - ttCheckbox.setEnabled(bgCheckbox.isChecked() && TreatmentsPlugin.getPlugin().getTempTargetFromHistory() != null); - calculateInsulin(); - } - - private void saveCheckedStates() { - SP.putBoolean(MainApp.gs(R.string.key_wizard_include_cob), cobCheckbox.isChecked()); - SP.putBoolean(MainApp.gs(R.string.key_wizard_include_trend_bg), bgtrendCheckbox.isChecked()); - } - - private void loadCheckedStates() { - bgtrendCheckbox.setChecked(SP.getBoolean(MainApp.gs(R.string.key_wizard_include_trend_bg), false)); - cobCheckbox.setChecked(SP.getBoolean(MainApp.gs(R.string.key_wizard_include_cob), false)); - } - - @Override - public void onItemSelected(AdapterView parent, View view, int position, long id) { - calculateInsulin(); - okButton.setVisibility(View.VISIBLE); - } - - @Override - public void onNothingSelected(AdapterView parent) { - ToastUtils.showToastInUiThread(context, MainApp.gs(R.string.noprofileselected)); - okButton.setVisibility(View.GONE); - } - - @Override - public synchronized void onClick(View view) { - switch (view.getId()) { - case R.id.ok: - if (okClicked) { - log.debug("guarding: ok already clicked"); - dismiss(); - return; - } - okClicked = true; - final Profile profile = ProfileFunctions.getInstance().getProfile(); - final PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump(); - - if (pump != null && profile != null && (calculatedTotalInsulin > 0d || calculatedCarbs > 0d)) { - String confirmMessage = MainApp.gs(R.string.entertreatmentquestion); - - Double insulinAfterConstraints = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(calculatedTotalInsulin)).value(); - Integer carbsAfterConstraints = MainApp.getConstraintChecker().applyCarbsConstraints(new Constraint<>(calculatedCarbs)).value(); - - if (insulinAfterConstraints > 0) - confirmMessage += "
" + MainApp.gs(R.string.bolus) + ": " + "" + DecimalFormatter.toPumpSupportedBolus(insulinAfterConstraints) + "U" + ""; - if (carbsAfterConstraints > 0) - confirmMessage += "
" + MainApp.gs(R.string.carbs) + ": " + "" + carbsAfterConstraints + "g" + ""; - - if (Math.abs(insulinAfterConstraints - calculatedTotalInsulin) > pump.getPumpDescription().pumpType.determineCorrectBolusSize(insulinAfterConstraints) || !carbsAfterConstraints.equals(calculatedCarbs)) { - confirmMessage += "
" + MainApp.gs(R.string.bolusconstraintapplied) + ""; - } - - final Double finalInsulinAfterConstraints = insulinAfterConstraints; - final Integer finalCarbsAfterConstraints = carbsAfterConstraints; - final Double bg = SafeParse.stringToDouble(editBg.getText()); - final int carbTime = SafeParse.stringToInt(editCarbTime.getText()); - final boolean useSuperBolus = superbolusCheckbox.isChecked(); - final String finalNotes = notesEdit.getText().toString(); - - final AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setTitle(MainApp.gs(R.string.confirmation)); - builder.setMessage(Html.fromHtml(confirmMessage)); - builder.setPositiveButton(MainApp.gs(R.string.ok), new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - synchronized (builder) { - if (accepted) { - log.debug("guarding: already accepted"); - return; - } - accepted = true; - if (finalInsulinAfterConstraints > 0 || finalCarbsAfterConstraints > 0) { - if (useSuperBolus) { - final LoopPlugin loopPlugin = LoopPlugin.getPlugin(); - if (loopPlugin.isEnabled(PluginType.LOOP)) { - loopPlugin.superBolusTo(System.currentTimeMillis() + 2 * 60L * 60 * 1000); - MainApp.bus().post(new EventRefreshOverview("WizardDialog")); - } - ConfigBuilderPlugin.getPlugin().getCommandQueue().tempBasalPercent(0, 120, true, profile, new Callback() { - @Override - public void run() { - if (!result.success) { - Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class); - i.putExtra("soundid", R.raw.boluserror); - i.putExtra("status", result.comment); - i.putExtra("title", MainApp.gs(R.string.tempbasaldeliveryerror)); - i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - MainApp.instance().startActivity(i); - } - } - }); - } - DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); - detailedBolusInfo.eventType = CareportalEvent.BOLUSWIZARD; - detailedBolusInfo.insulin = finalInsulinAfterConstraints; - detailedBolusInfo.carbs = finalCarbsAfterConstraints; - detailedBolusInfo.context = context; - detailedBolusInfo.glucose = bg; - detailedBolusInfo.glucoseType = "Manual"; - detailedBolusInfo.carbTime = carbTime; - detailedBolusInfo.boluscalc = boluscalcJSON; - detailedBolusInfo.source = Source.USER; - detailedBolusInfo.notes = finalNotes; - if (detailedBolusInfo.insulin > 0 || ConfigBuilderPlugin.getPlugin().getActivePump().getPumpDescription().storesCarbInfo) { - ConfigBuilderPlugin.getPlugin().getCommandQueue().bolus(detailedBolusInfo, new Callback() { - @Override - public void run() { - if (!result.success) { - Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class); - i.putExtra("soundid", R.raw.boluserror); - i.putExtra("status", result.comment); - i.putExtra("title", MainApp.gs(R.string.treatmentdeliveryerror)); - i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - MainApp.instance().startActivity(i); - } - } - }); - } else { - TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, false); - } - FabricPrivacy.getInstance().logCustom(new CustomEvent("Wizard")); - } - } - } - }); - builder.setNegativeButton(MainApp.gs(R.string.cancel), null); - builder.show(); - dismiss(); - } - break; - case R.id.cancel: - dismiss(); - break; - } - } - - private void initDialog() { - Profile profile = ProfileFunctions.getInstance().getProfile(); - ProfileStore profileStore = ConfigBuilderPlugin.getPlugin().getActiveProfileInterface() != null ? ConfigBuilderPlugin.getPlugin().getActiveProfileInterface().getProfile() : null; - - if (profile == null || profileStore == null) { - ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.noprofile)); - dismiss(); - return; - } - - ArrayList profileList; - profileList = profileStore.getProfileList(); - profileList.add(0, MainApp.gs(R.string.active)); - ArrayAdapter adapter = new ArrayAdapter<>(getContext(), - R.layout.spinner_centered, profileList); - - profileSpinner.setAdapter(adapter); - - String units = profile.getUnits(); - bgUnits.setText(units); - if (units.equals(Constants.MGDL)) editBg.setStep(1d); - else editBg.setStep(0.1d); - - // Set BG if not old - BgReading lastBg = DatabaseHelper.actualBg(); - - if (lastBg != null) { - editBg.setValue(lastBg.valueToUnits(units)); - } else { - editBg.setValue(0d); - } - ttCheckbox.setEnabled(TreatmentsPlugin.getPlugin().getTempTargetFromHistory() != null); - - // IOB calculation - TreatmentsPlugin.getPlugin().updateTotalIOBTreatments(); - IobTotal bolusIob = TreatmentsPlugin.getPlugin().getLastCalculationTreatments().round(); - TreatmentsPlugin.getPlugin().updateTotalIOBTempBasals(); - IobTotal basalIob = TreatmentsPlugin.getPlugin().getLastCalculationTempBasals().round(); - - bolusIobInsulin.setText(DecimalFormatter.to2Decimal(-bolusIob.iob) + "U"); - basalIobInsulin.setText(DecimalFormatter.to2Decimal(-basalIob.basaliob) + "U"); - - calculateInsulin(); - } - - private void calculateInsulin() { - ProfileStore profileStore = ConfigBuilderPlugin.getPlugin().getActiveProfileInterface().getProfile(); - if (profileSpinner == null || profileSpinner.getSelectedItem() == null || profileStore == null) - return; // not initialized yet - String selectedAlternativeProfile = profileSpinner.getSelectedItem().toString(); - Profile specificProfile; - if (selectedAlternativeProfile.equals(MainApp.gs(R.string.active))) { - specificProfile = ProfileFunctions.getInstance().getProfile(); - selectedAlternativeProfile = ProfileFunctions.getInstance().getProfileName(); - } else - specificProfile = profileStore.getSpecificProfile(selectedAlternativeProfile); - - // Entered values - Double c_bg = SafeParse.stringToDouble(editBg.getText()); - Integer c_carbs = SafeParse.stringToInt(editCarbs.getText()); - Double c_correction = SafeParse.stringToDouble(editCorr.getText()); - Double corrAfterConstraint = c_correction; - if (c_correction > 0) - c_correction = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(c_correction)).value(); - if (Math.abs(c_correction - corrAfterConstraint) > 0.01d) { // c_correction != corrAfterConstraint doesn't work - editCorr.setValue(0d); - ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.bolusconstraintapplied)); - return; - } - Integer carbsAfterConstraint = MainApp.getConstraintChecker().applyCarbsConstraints(new Constraint<>(c_carbs)).value(); - if (Math.abs(c_carbs - carbsAfterConstraint) > 0.01d) { - editCarbs.setValue(0d); - ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.carbsconstraintapplied)); - return; - } - - c_bg = bgCheckbox.isChecked() ? c_bg : 0d; - TempTarget tempTarget = ttCheckbox.isChecked() ? TreatmentsPlugin.getPlugin().getTempTargetFromHistory() : null; - - // COB - Double c_cob = 0d; - if (cobCheckbox.isChecked()) { - CobInfo cobInfo = IobCobCalculatorPlugin.getPlugin().getCobInfo(false, "Wizard COB"); - if (cobInfo != null && cobInfo.displayCob != null) - c_cob = cobInfo.displayCob; - } - - BolusWizard wizard = new BolusWizard(); - wizard.doCalc(specificProfile, tempTarget, carbsAfterConstraint, c_cob, c_bg, corrAfterConstraint, bolusIobCheckbox.isChecked(), basalIobCheckbox.isChecked(), superbolusCheckbox.isChecked(), bgtrendCheckbox.isChecked()); - - bg.setText(c_bg + " ISF: " + DecimalFormatter.to1Decimal(wizard.sens)); - bgInsulin.setText(DecimalFormatter.to2Decimal(wizard.insulinFromBG) + "U"); - - carbs.setText(DecimalFormatter.to0Decimal(c_carbs) + "g IC: " + DecimalFormatter.to1Decimal(wizard.ic)); - carbsInsulin.setText(DecimalFormatter.to2Decimal(wizard.insulinFromCarbs) + "U"); - - bolusIobInsulin.setText(DecimalFormatter.to2Decimal(wizard.insulingFromBolusIOB) + "U"); - basalIobInsulin.setText(DecimalFormatter.to2Decimal(wizard.insulingFromBasalsIOB) + "U"); - - correctionInsulin.setText(DecimalFormatter.to2Decimal(wizard.insulinFromCorrection) + "U"); - calculatedTotalInsulin = wizard.calculatedTotalInsulin; - - calculatedCarbs = carbsAfterConstraint; - - // Superbolus - if (superbolusCheckbox.isChecked()) { - superbolus.setText("2h"); - } else { - superbolus.setText(""); - } - superbolusInsulin.setText(DecimalFormatter.to2Decimal(wizard.insulinFromSuperBolus) + "U"); - - // Trend - if (bgtrendCheckbox.isChecked()) { - if (wizard.glucoseStatus != null) { - bgTrend.setText((wizard.glucoseStatus.avgdelta > 0 ? "+" : "") + Profile.toUnitsString(wizard.glucoseStatus.avgdelta * 3, wizard.glucoseStatus.avgdelta * 3 / 18, specificProfile.getUnits()) + " " + specificProfile.getUnits()); - } else { - bgTrend.setText(""); - } - } else { - bgTrend.setText(""); - } - bgTrendInsulin.setText(DecimalFormatter.to2Decimal(wizard.insulinFromTrend) + "U"); - - // COB - if (cobCheckbox.isChecked()) { - cob.setText(DecimalFormatter.to2Decimal(c_cob) + "g IC: " + DecimalFormatter.to1Decimal(wizard.ic)); - cobInsulin.setText(DecimalFormatter.to2Decimal(wizard.insulinFromCOB) + "U"); - } else { - cob.setText(""); - cobInsulin.setText(""); - } - - if (calculatedTotalInsulin > 0d || calculatedCarbs > 0d) { - String insulinText = calculatedTotalInsulin > 0d ? (DecimalFormatter.toPumpSupportedBolus(calculatedTotalInsulin) + "U") : ""; - String carbsText = calculatedCarbs > 0d ? (DecimalFormatter.to0Decimal(calculatedCarbs) + "g") : ""; - total.setText(MainApp.gs(R.string.result) + ": " + insulinText + " " + carbsText); - okButton.setVisibility(View.VISIBLE); - } else { - // TODO this should also be run when loading the dialog as the OK button is initially visible - // but does nothing if neither carbs nor insulin is > 0 - total.setText(MainApp.gs(R.string.missing) + " " + DecimalFormatter.to0Decimal(wizard.carbsEquivalent) + "g"); - okButton.setVisibility(View.INVISIBLE); - } - - boluscalcJSON = new JSONObject(); - try { - boluscalcJSON.put("profile", selectedAlternativeProfile); - boluscalcJSON.put("notes", notesEdit.getText()); - boluscalcJSON.put("eventTime", DateUtil.toISOString(new Date())); - boluscalcJSON.put("targetBGLow", wizard.targetBGLow); - boluscalcJSON.put("targetBGHigh", wizard.targetBGHigh); - boluscalcJSON.put("isf", wizard.sens); - boluscalcJSON.put("ic", wizard.ic); - boluscalcJSON.put("iob", -(wizard.insulingFromBolusIOB + wizard.insulingFromBasalsIOB)); - boluscalcJSON.put("bolusiob", wizard.insulingFromBolusIOB); - boluscalcJSON.put("basaliob", wizard.insulingFromBasalsIOB); - boluscalcJSON.put("bolusiobused", bolusIobCheckbox.isChecked()); - boluscalcJSON.put("basaliobused", basalIobCheckbox.isChecked()); - boluscalcJSON.put("bg", c_bg); - boluscalcJSON.put("insulinbg", wizard.insulinFromBG); - boluscalcJSON.put("insulinbgused", bgCheckbox.isChecked()); - boluscalcJSON.put("bgdiff", wizard.bgDiff); - boluscalcJSON.put("insulincarbs", wizard.insulinFromCarbs); - boluscalcJSON.put("carbs", c_carbs); - boluscalcJSON.put("cob", c_cob); - boluscalcJSON.put("cobused", cobCheckbox.isChecked()); - boluscalcJSON.put("insulincob", wizard.insulinFromCOB); - boluscalcJSON.put("othercorrection", corrAfterConstraint); - boluscalcJSON.put("insulinsuperbolus", wizard.insulinFromSuperBolus); - boluscalcJSON.put("insulintrend", wizard.insulinFromTrend); - boluscalcJSON.put("insulin", calculatedTotalInsulin); - boluscalcJSON.put("superbolusused", superbolusCheckbox.isChecked()); - boluscalcJSON.put("insulinsuperbolus", wizard.insulinFromSuperBolus); - boluscalcJSON.put("trendused", bgtrendCheckbox.isChecked()); - boluscalcJSON.put("insulintrend", wizard.insulinFromTrend); - boluscalcJSON.put("trend", bgTrend.getText()); - boluscalcJSON.put("ttused", ttCheckbox.isChecked()); - } catch (JSONException e) { - log.error("Unhandled exception", e); - } - } - -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewPlugin.java deleted file mode 100644 index b184201908..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewPlugin.java +++ /dev/null @@ -1,110 +0,0 @@ -package info.nightscout.androidaps.plugins.Overview; - -import com.squareup.otto.Subscribe; - -import org.json.JSONArray; -import org.json.JSONException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.data.Profile; -import info.nightscout.androidaps.data.QuickWizard; -import info.nightscout.androidaps.events.EventRefreshOverview; -import info.nightscout.androidaps.interfaces.PluginBase; -import info.nightscout.androidaps.interfaces.PluginDescription; -import info.nightscout.androidaps.interfaces.PluginType; -import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions; -import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; -import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; -import info.nightscout.androidaps.plugins.Overview.notifications.NotificationStore; -import info.nightscout.utils.SP; - -/** - * Created by mike on 05.08.2016. - */ -public class OverviewPlugin extends PluginBase { - private static Logger log = LoggerFactory.getLogger(L.OVERVIEW); - - private static OverviewPlugin overviewPlugin = new OverviewPlugin(); - - public static OverviewPlugin getPlugin() { - if (overviewPlugin == null) - overviewPlugin = new OverviewPlugin(); - return overviewPlugin; - } - - public static double bgTargetLow = 80d; - public static double bgTargetHigh = 180d; - - public QuickWizard quickWizard = new QuickWizard(); - - public NotificationStore notificationStore = new NotificationStore(); - - public OverviewPlugin() { - super(new PluginDescription() - .mainType(PluginType.GENERAL) - .fragmentClass(OverviewFragment.class.getName()) - .alwayVisible(true) - .alwaysEnabled(true) - .pluginName(R.string.overview) - .shortName(R.string.overview_shortname) - .preferencesId(R.xml.pref_overview) - .description(R.string.description_overview) - ); - String storedData = SP.getString("QuickWizard", "[]"); - try { - quickWizard.setData(new JSONArray(storedData)); - } catch (JSONException e) { - log.error("Unhandled exception", e); - } - } - - @Override - protected void onStart() { - MainApp.bus().register(this); - super.onStart(); - } - - @Override - protected void onStop() { - MainApp.bus().unregister(this); - } - - @Subscribe - public void onStatusEvent(final EventNewNotification n) { - if (notificationStore.add(n.notification)) - MainApp.bus().post(new EventRefreshOverview("EventNewNotification")); - } - - @Subscribe - public void onStatusEvent(final EventDismissNotification n) { - if (notificationStore.remove(n.id)) - MainApp.bus().post(new EventRefreshOverview("EventDismissNotification")); - } - - public double determineHighLine(String units) { - double highLineSetting = SP.getDouble("high_mark", Profile.fromMgdlToUnits(OverviewPlugin.bgTargetHigh, units)); - if (highLineSetting < 1) - highLineSetting = Profile.fromMgdlToUnits(180d, units); - return highLineSetting; - } - - public double determineLowLine() { - Profile profile = ProfileFunctions.getInstance().getProfile(); - if (profile == null) { - return bgTargetLow; - } - return determineLowLine(profile.getUnits()); - } - - public double determineLowLine(String units) { - double lowLineSetting = SP.getDouble("low_mark", Profile.fromMgdlToUnits(OverviewPlugin.bgTargetLow, units)); - if (lowLineSetting < 1) - lowLineSetting = Profile.fromMgdlToUnits(76d, units); - return lowLineSetting; - } - -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/activities/QuickWizardListActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/activities/QuickWizardListActivity.java deleted file mode 100644 index 237575c328..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/activities/QuickWizardListActivity.java +++ /dev/null @@ -1,172 +0,0 @@ -package info.nightscout.androidaps.plugins.Overview.activities; - -import android.app.Activity; -import android.os.Bundle; -import android.support.v4.app.FragmentManager; -import android.support.v7.app.AppCompatActivity; -import android.support.v7.widget.CardView; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Button; -import android.widget.TextView; - -import com.squareup.otto.Subscribe; - -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.data.QuickWizard; -import info.nightscout.androidaps.plugins.Overview.Dialogs.EditQuickWizardDialog; -import info.nightscout.androidaps.plugins.Overview.OverviewPlugin; -import info.nightscout.androidaps.plugins.Overview.events.EventQuickWizardChange; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.DecimalFormatter; - -public class QuickWizardListActivity extends AppCompatActivity implements View.OnClickListener { - - RecyclerView recyclerView; - LinearLayoutManager llm; - - Button adButton; - - public static class RecyclerViewAdapter extends RecyclerView.Adapter { - - QuickWizard qvData; - FragmentManager fragmentManager; - - RecyclerViewAdapter(QuickWizard data, FragmentManager fragmentManager) { - this.qvData = data; - this.fragmentManager = fragmentManager; - } - - @Override - public QuickWizardEntryViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { - View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.overview_quickwizardlist_item, viewGroup, false); - QuickWizardEntryViewHolder quickWizardEntryViewHolder = new QuickWizardEntryViewHolder(v, fragmentManager, qvData); - return quickWizardEntryViewHolder; - } - - @Override - public void onBindViewHolder(QuickWizardEntryViewHolder holder, int position) { - holder.from.setText(DateUtil.timeString(qvData.get(position).validFromDate())); - holder.to.setText(DateUtil.timeString(qvData.get(position).validToDate())); - holder.buttonText.setText(qvData.get(position).buttonText()); - holder.carbs.setText(DecimalFormatter.to0Decimal(qvData.get(position).carbs()) + " g"); - } - - @Override - public int getItemCount() { - return qvData.size(); - } - - @Override - public void onAttachedToRecyclerView(RecyclerView recyclerView) { - super.onAttachedToRecyclerView(recyclerView); - } - - public static class QuickWizardEntryViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { - CardView cv; - TextView buttonText; - TextView carbs; - TextView from; - TextView to; - Button editButton; - Button removeButton; - FragmentManager fragmentManager; - QuickWizard qvData; - - QuickWizardEntryViewHolder(View itemView, FragmentManager fragmentManager, QuickWizard qvData) { - super(itemView); - cv = (CardView) itemView.findViewById(R.id.overview_quickwizard_cardview); - buttonText = (TextView) itemView.findViewById(R.id.overview_quickwizard_item_buttonText); - carbs = (TextView) itemView.findViewById(R.id.overview_quickwizard_item_carbs); - from = (TextView) itemView.findViewById(R.id.overview_quickwizard_item_from); - to = (TextView) itemView.findViewById(R.id.overview_quickwizard_item_to); - editButton = (Button) itemView.findViewById(R.id.overview_quickwizard_item_edit_button); - removeButton = (Button) itemView.findViewById(R.id.overview_quickwizard_item_remove_button); - editButton.setOnClickListener(this); - removeButton.setOnClickListener(this); - this.fragmentManager = fragmentManager; - this.qvData = qvData; - } - - @Override - public void onClick(View v) { - int position = getAdapterPosition(); - switch (v.getId()) { - case R.id.overview_quickwizard_item_edit_button: - FragmentManager manager = fragmentManager; - EditQuickWizardDialog editQuickWizardDialog = new EditQuickWizardDialog(); - editQuickWizardDialog.setData(qvData.get(position)); - editQuickWizardDialog.show(manager, "EditQuickWizardDialog"); - break; - case R.id.overview_quickwizard_item_remove_button: - qvData.remove(position); - MainApp.bus().post(new EventQuickWizardChange()); - break; - } - } - } - } - - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.overview_quickwizardlist_activity); - - recyclerView = (RecyclerView) findViewById(R.id.overview_quickwizardactivity_recyclerview); - recyclerView.setHasFixedSize(true); - llm = new LinearLayoutManager(this); - recyclerView.setLayoutManager(llm); - - RecyclerViewAdapter adapter = new RecyclerViewAdapter(MainApp.getSpecificPlugin(OverviewPlugin.class).quickWizard, getSupportFragmentManager()); - recyclerView.setAdapter(adapter); - - adButton = (Button) findViewById(R.id.overview_quickwizardactivity_add_button); - adButton.setOnClickListener(this); - } - - @Override - protected void onResume() { - super.onResume(); - MainApp.bus().register(this); - } - - @Override - protected void onPause() { - super.onPause(); - MainApp.bus().unregister(this); - } - - @Override - public void onClick(View v) { - switch (v.getId()) { - case R.id.overview_quickwizardactivity_add_button: - FragmentManager manager = getSupportFragmentManager(); - EditQuickWizardDialog editQuickWizardDialog = new EditQuickWizardDialog(); - editQuickWizardDialog.show(manager, "EditQuickWizardDialog"); - break; - } - } - - @Subscribe - public void onStatusEvent(final EventQuickWizardChange ev) { - updateGUI(); - } - - public void updateGUI() { - Activity activity = this; - if (activity != null && recyclerView != null) { - activity.runOnUiThread(new Runnable() { - @Override - public void run() { - RecyclerViewAdapter adapter = new RecyclerViewAdapter(MainApp.getSpecificPlugin(OverviewPlugin.class).quickWizard, getSupportFragmentManager()); - recyclerView.swapAdapter(adapter, false); - } - }); - } - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventDismissBolusprogressIfRunning.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventDismissBolusprogressIfRunning.java deleted file mode 100644 index af336cd74c..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventDismissBolusprogressIfRunning.java +++ /dev/null @@ -1,16 +0,0 @@ -package info.nightscout.androidaps.plugins.Overview.events; - -import info.nightscout.androidaps.data.PumpEnactResult; -import info.nightscout.androidaps.events.Event; - -/** - * Created by adrian on 20/02/17. - */ - -public class EventDismissBolusprogressIfRunning extends Event { - public final PumpEnactResult result; - - public EventDismissBolusprogressIfRunning(PumpEnactResult result) { - this.result = result; - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventDismissNotification.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventDismissNotification.java deleted file mode 100644 index 1fa71febbe..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventDismissNotification.java +++ /dev/null @@ -1,16 +0,0 @@ -package info.nightscout.androidaps.plugins.Overview.events; - -import info.nightscout.androidaps.events.Event; - -/** - * Created by mike on 03.12.2016. - */ - -public class EventDismissNotification extends Event { - public int id; - - public EventDismissNotification(int did) { - id = did; - } - -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventNewNotification.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventNewNotification.java deleted file mode 100644 index 2a669d26d2..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventNewNotification.java +++ /dev/null @@ -1,16 +0,0 @@ -package info.nightscout.androidaps.plugins.Overview.events; - -import info.nightscout.androidaps.events.Event; -import info.nightscout.androidaps.plugins.Overview.notifications.Notification; - -/** - * Created by mike on 03.12.2016. - */ - -public class EventNewNotification extends Event { - public Notification notification; - - public EventNewNotification(Notification n) { - notification = n; - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventOverviewBolusProgress.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventOverviewBolusProgress.java deleted file mode 100644 index 18e8ff91bc..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventOverviewBolusProgress.java +++ /dev/null @@ -1,30 +0,0 @@ -package info.nightscout.androidaps.plugins.Overview.events; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import info.nightscout.androidaps.plugins.Treatments.Treatment; -import info.nightscout.androidaps.events.Event; - -public class EventOverviewBolusProgress extends Event { - public String status = ""; - public Treatment t = null; - public int percent = 0; - public int bolusId; - private static EventOverviewBolusProgress eventOverviewBolusProgress = null; - - public EventOverviewBolusProgress() { - } - - public boolean isSMB(){ - return (t != null) && t.isSMB; - } - - public static EventOverviewBolusProgress getInstance() { - if(eventOverviewBolusProgress == null) { - eventOverviewBolusProgress = new EventOverviewBolusProgress(); - } - return eventOverviewBolusProgress; - } - -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventQuickWizardChange.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventQuickWizardChange.java deleted file mode 100644 index b72c2548e2..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventQuickWizardChange.java +++ /dev/null @@ -1,10 +0,0 @@ -package info.nightscout.androidaps.plugins.Overview.events; - -import info.nightscout.androidaps.events.Event; - -/** - * Created by mike on 20.10.2016. - */ - -public class EventQuickWizardChange extends Event { -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Persistentnotification/DummyService.java b/app/src/main/java/info/nightscout/androidaps/plugins/Persistentnotification/DummyService.java deleted file mode 100644 index 56b3a2cd09..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Persistentnotification/DummyService.java +++ /dev/null @@ -1,58 +0,0 @@ -package info.nightscout.androidaps.plugins.Persistentnotification; - -import android.app.Notification; -import android.app.Service; -import android.content.Intent; -import android.os.IBinder; -import android.support.annotation.Nullable; - -import com.squareup.otto.Subscribe; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.events.EventAppExit; -import info.nightscout.androidaps.logging.L; - -/** - * Keeps AndroidAPS in foreground state, so it won't be terminated by Android nor get restricted by the background execution limits - */ -public class DummyService extends Service { - private static Logger log = LoggerFactory.getLogger(L.CORE); - - @Nullable - @Override - public IBinder onBind(Intent intent) { - return null; - } - - @Override - public int onStartCommand(Intent intent, int flags, int startId) { - Notification notification = PersistentNotificationPlugin.getPlugin().updateNotification(); - if (notification != null) - startForeground(PersistentNotificationPlugin.ONGOING_NOTIFICATION_ID, notification); - return START_STICKY; - } - - @Subscribe - public void onStatusEvent(EventAppExit event) { - if (L.isEnabled(L.CORE)) - log.debug("EventAppExit received"); - - stopSelf(); - } - - @Override - public void onCreate() { - MainApp.bus().register(this); - } - - @Override - public void onDestroy() { - if (L.isEnabled(L.CORE)) - log.debug("onDestroy"); - MainApp.bus().unregister(this); - stopForeground(true); - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Persistentnotification/PersistentNotificationPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Persistentnotification/PersistentNotificationPlugin.java deleted file mode 100644 index 6b93b7a715..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Persistentnotification/PersistentNotificationPlugin.java +++ /dev/null @@ -1,319 +0,0 @@ -package info.nightscout.androidaps.plugins.Persistentnotification; - -import android.annotation.SuppressLint; -import android.app.Notification; -import android.app.NotificationChannel; -import android.app.NotificationManager; -import android.app.PendingIntent; -import android.content.Context; -import android.content.Intent; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.os.Build; -import android.support.v4.app.NotificationCompat; -import android.support.v4.app.TaskStackBuilder; - -// Android Auto -import android.support.v4.app.NotificationCompat; -import android.support.v4.app.NotificationManagerCompat; -import android.support.v4.app.RemoteInput; - - - - -import com.squareup.otto.Subscribe; - -import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.Constants; -import info.nightscout.androidaps.MainActivity; -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.data.GlucoseStatus; -import info.nightscout.androidaps.data.IobTotal; -import info.nightscout.androidaps.db.BgReading; -import info.nightscout.androidaps.db.DatabaseHelper; -import info.nightscout.androidaps.db.TemporaryBasal; -import info.nightscout.androidaps.events.EventExtendedBolusChange; -import info.nightscout.androidaps.events.EventInitializationChanged; -import info.nightscout.androidaps.events.EventNewBG; -import info.nightscout.androidaps.events.EventNewBasalProfile; -import info.nightscout.androidaps.events.EventPreferenceChange; -import info.nightscout.androidaps.events.EventRefreshOverview; -import info.nightscout.androidaps.events.EventTempBasalChange; -import info.nightscout.androidaps.events.EventTreatmentChange; -import info.nightscout.androidaps.interfaces.PluginBase; -import info.nightscout.androidaps.interfaces.PluginDescription; -import info.nightscout.androidaps.interfaces.PluginType; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions; -import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin; -import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; -import info.nightscout.utils.DecimalFormatter; - -/** - * Created by adrian on 23/12/16. - */ - -public class PersistentNotificationPlugin extends PluginBase { - - private static PersistentNotificationPlugin plugin; - - public static PersistentNotificationPlugin getPlugin() { - if (plugin == null) plugin = new PersistentNotificationPlugin(MainApp.instance()); - return plugin; - } - - public static final String CHANNEL_ID = "AndroidAPS-Ongoing"; - - public static final int ONGOING_NOTIFICATION_ID = 4711; - private final Context ctx; - - /// For Android Auto - /// Intents are not declared in manifest and not consumed, this is intentionally because actually we can't do anything with - private static final String PACKAGE = "info.nightscout"; - private static final String READ_ACTION = - "info.nightscout.androidaps.ACTION_MESSAGE_READ"; - private static final String REPLY_ACTION = - "info.nightscout.androidaps.ACTION_MESSAGE_REPLY"; - private static final String CONVERSATION_ID = "conversation_id"; - private static final String EXTRA_VOICE_REPLY = "extra_voice_reply"; - /// End Android Auto - - - public PersistentNotificationPlugin(Context ctx) { - super(new PluginDescription() - .mainType(PluginType.GENERAL) - .neverVisible(true) - .pluginName(R.string.ongoingnotificaction) - .enableByDefault(true) - .alwaysEnabled(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) - .description(R.string.description_persistent_notification) - ); - this.ctx = ctx; - } - - @Override - protected void onStart() { - MainApp.bus().register(this); - createNotificationChannel(); - triggerNotificationUpdate(); - super.onStart(); - } - - private void createNotificationChannel() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - - NotificationManager mNotificationManager = - (NotificationManager) ctx.getSystemService(Context.NOTIFICATION_SERVICE); - @SuppressLint("WrongConstant") NotificationChannel channel = new NotificationChannel(CHANNEL_ID, - CHANNEL_ID, - NotificationManager.IMPORTANCE_HIGH); - mNotificationManager.createNotificationChannel(channel); - } - } - - @Override - protected void onStop() { - MainApp.bus().unregister(this); - MainApp.instance().stopService(new Intent(MainApp.instance(), DummyService.class)); - } - - private void triggerNotificationUpdate() { - MainApp.instance().startService(new Intent(MainApp.instance(), DummyService.class)); - } - - Notification updateNotification() { - if (!isEnabled(PluginType.GENERAL)) { - return null; - } - - String line1; - String line1_aa; - - if (ConfigBuilderPlugin.getPlugin().getActiveProfileInterface() == null || !ProfileFunctions.getInstance().isProfileValid("Notificiation")) - return null; - String units = ProfileFunctions.getInstance().getProfileUnits(); - - - BgReading lastBG = DatabaseHelper.lastBg(); - GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData(); - - if (lastBG != null) { - line1 = line1_aa = lastBG.valueToUnitsToString(units); - if (glucoseStatus != null) { - line1 += " Δ" + deltastring(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units) - + " avgΔ" + deltastring(glucoseStatus.avgdelta, glucoseStatus.avgdelta * Constants.MGDL_TO_MMOLL, units); - line1_aa += " " + lastBG.directionToSymbol(); - } else { - line1 += " " + - MainApp.gs(R.string.old_data) + - " "; - line1_aa += line1 + "."; - } - } else { - line1 = line1_aa = MainApp.gs(R.string.missed_bg_readings); - } - - TemporaryBasal activeTemp = TreatmentsPlugin.getPlugin().getTempBasalFromHistory(System.currentTimeMillis()); - if (activeTemp != null) { - line1 += " " + activeTemp.toStringShort(); - line1_aa += " " + activeTemp.toStringShort() + "."; - } - - //IOB - TreatmentsPlugin.getPlugin().updateTotalIOBTreatments(); - TreatmentsPlugin.getPlugin().updateTotalIOBTempBasals(); - IobTotal bolusIob = TreatmentsPlugin.getPlugin().getLastCalculationTreatments().round(); - IobTotal basalIob = TreatmentsPlugin.getPlugin().getLastCalculationTempBasals().round(); - - - String line2 = MainApp.gs(R.string.treatments_iob_label_string) + " " + DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U " + MainApp.gs(R.string.cob)+": " + IobCobCalculatorPlugin.getPlugin().getCobInfo(false, "PersistentNotificationPlugin").generateCOBString(); - String line2_aa = MainApp.gs(R.string.treatments_iob_label_string) + " " + DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U. " + MainApp.gs(R.string.cob)+": " + IobCobCalculatorPlugin.getPlugin().getCobInfo(false, "PersistentNotificationPlugin").generateCOBString() + "."; - - - String line3 = DecimalFormatter.to2Decimal(ConfigBuilderPlugin.getPlugin().getActivePump().getBaseBasalRate()) + " U/h"; - String line3_aa = DecimalFormatter.to2Decimal(ConfigBuilderPlugin.getPlugin().getActivePump().getBaseBasalRate()) + " U/h."; - - - line3 += " - " + ProfileFunctions.getInstance().getProfileName(); - line3_aa += " - " + ProfileFunctions.getInstance().getProfileName() + "."; - - /// For Android Auto - Intent msgReadIntent = new Intent() - .addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES) - .setAction(READ_ACTION) - .putExtra(CONVERSATION_ID, ONGOING_NOTIFICATION_ID) - .setPackage(PACKAGE); - - PendingIntent msgReadPendingIntent = - PendingIntent.getBroadcast(ctx, - ONGOING_NOTIFICATION_ID, - msgReadIntent, - PendingIntent.FLAG_UPDATE_CURRENT); - - Intent msgReplyIntent = new Intent() - .addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES) - .setAction(REPLY_ACTION) - .putExtra(CONVERSATION_ID, ONGOING_NOTIFICATION_ID) - .setPackage(PACKAGE); - - PendingIntent msgReplyPendingIntent = PendingIntent.getBroadcast( - ctx, - ONGOING_NOTIFICATION_ID, - msgReplyIntent, - PendingIntent.FLAG_UPDATE_CURRENT); - - // Build a RemoteInput for receiving voice input from devices - RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY).build(); - - // Create the UnreadConversation - NotificationCompat.CarExtender.UnreadConversation.Builder unreadConversationBuilder = - new NotificationCompat.CarExtender.UnreadConversation.Builder(line1_aa + "\n" + line2_aa) - .setLatestTimestamp(System.currentTimeMillis()) - .setReadPendingIntent(msgReadPendingIntent) - .setReplyAction(msgReplyPendingIntent, remoteInput); - - /// Add dot to produce a "more natural sounding result" - unreadConversationBuilder.addMessage(line3_aa); - /// End Android Auto - - - NotificationCompat.Builder builder = new NotificationCompat.Builder(ctx, CHANNEL_ID); - builder.setOngoing(true); - builder.setOnlyAlertOnce(true); - builder.setCategory(NotificationCompat.CATEGORY_STATUS); - if (Config.NSCLIENT){ - builder.setSmallIcon(R.drawable.nsclient_smallicon); - Bitmap largeIcon = BitmapFactory.decodeResource(ctx.getResources(), R.mipmap.yellowowl); - builder.setLargeIcon(largeIcon); - } else { - builder.setSmallIcon(R.drawable.ic_notification); - Bitmap largeIcon = BitmapFactory.decodeResource(ctx.getResources(), R.mipmap.blueowl); - builder.setLargeIcon(largeIcon); - } - builder.setContentTitle(line1); - builder.setContentText(line2); - builder.setSubText(line3); - /// Android Auto - builder.extend(new NotificationCompat.CarExtender() - .setUnreadConversation(unreadConversationBuilder.build())); - /// End Android Auto - - - Intent resultIntent = new Intent(ctx, MainActivity.class); - - TaskStackBuilder stackBuilder = TaskStackBuilder.create(ctx); - stackBuilder.addParentStack(MainActivity.class); - stackBuilder.addNextIntent(resultIntent); - PendingIntent resultPendingIntent = - stackBuilder.getPendingIntent( - 0, - PendingIntent.FLAG_UPDATE_CURRENT - ); - builder.setContentIntent(resultPendingIntent); - NotificationManager mNotificationManager = - (NotificationManager) ctx.getSystemService(Context.NOTIFICATION_SERVICE); - - android.app.Notification notification = builder.build(); - mNotificationManager.notify(ONGOING_NOTIFICATION_ID, notification); - return notification; - } - - private String deltastring(double deltaMGDL, double deltaMMOL, String units) { - String deltastring = ""; - if (deltaMGDL >= 0) { - deltastring += "+"; - } else { - deltastring += "-"; - - } - if (units.equals(Constants.MGDL)) { - deltastring += DecimalFormatter.to1Decimal(Math.abs(deltaMGDL)); - } else { - deltastring += DecimalFormatter.to1Decimal(Math.abs(deltaMMOL)); - } - return deltastring; - } - - - @Subscribe - public void onStatusEvent(final EventPreferenceChange ev) { - triggerNotificationUpdate(); - } - - @Subscribe - public void onStatusEvent(final EventTreatmentChange ev) { - triggerNotificationUpdate(); - } - - @Subscribe - public void onStatusEvent(final EventTempBasalChange ev) { - triggerNotificationUpdate(); - } - - @Subscribe - public void onStatusEvent(final EventExtendedBolusChange ev) { - triggerNotificationUpdate(); - } - - @Subscribe - public void onStatusEvent(final EventNewBG ev) { - triggerNotificationUpdate(); - } - - @Subscribe - public void onStatusEvent(final EventNewBasalProfile ev) { - triggerNotificationUpdate(); - } - - @Subscribe - public void onStatusEvent(final EventInitializationChanged ev) { - triggerNotificationUpdate(); - } - - @Subscribe - public void onStatusEvent(final EventRefreshOverview ev) { - triggerNotificationUpdate(); - } - -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/NSProfileFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/NSProfileFragment.java deleted file mode 100644 index 4edaef1761..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/NSProfileFragment.java +++ /dev/null @@ -1,165 +0,0 @@ -package info.nightscout.androidaps.plugins.ProfileNS; - -import android.app.Activity; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ArrayAdapter; -import android.widget.Button; -import android.widget.Spinner; -import android.widget.TextView; - -import com.squareup.otto.Subscribe; - -import java.util.ArrayList; - -import butterknife.BindView; -import butterknife.ButterKnife; -import butterknife.OnClick; -import butterknife.OnItemSelected; -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.data.Profile; -import info.nightscout.androidaps.data.ProfileStore; -import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog; -import info.nightscout.androidaps.plugins.Common.SubscriberFragment; -import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions; -import info.nightscout.androidaps.plugins.ProfileNS.events.EventNSProfileUpdateGUI; -import info.nightscout.androidaps.plugins.Treatments.fragments.ProfileGraph; -import info.nightscout.utils.DecimalFormatter; -import info.nightscout.utils.OKDialog; - -import static butterknife.OnItemSelected.Callback.NOTHING_SELECTED; - - -public class NSProfileFragment extends SubscriberFragment { - @BindView(R.id.nsprofile_spinner) - Spinner profileSpinner; - @BindView(R.id.profileview_noprofile) - TextView noProfile; - @BindView(R.id.profileview_invalidprofile) - TextView invalidProfile; - @BindView(R.id.profileview_units) - TextView units; - @BindView(R.id.profileview_dia) - TextView dia; - @BindView(R.id.profileview_activeprofile) - TextView activeProfile; - @BindView(R.id.profileview_ic) - TextView ic; - @BindView(R.id.profileview_isf) - TextView isf; - @BindView(R.id.profileview_basal) - TextView basal; - @BindView(R.id.profileview_basaltotal) - TextView basaltotal; - @BindView(R.id.profileview_target) - TextView target; - @BindView(R.id.basal_graph) - ProfileGraph basalGraph; - @BindView(R.id.nsprofile_profileswitch) - Button activateButton; - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.nsprofile_fragment, container, false); - - unbinder = ButterKnife.bind(this, view); - updateGUI(); - return view; - } - - @Subscribe - public void onStatusEvent(final EventNSProfileUpdateGUI ev) { - Activity activity = getActivity(); - if (activity != null) - activity.runOnUiThread(() -> { - synchronized (NSProfileFragment.this) { - updateGUI(); - } - }); - } - - @Override - protected void updateGUI() { - if (noProfile == null || profileSpinner == null) - return; - - ProfileStore profileStore = NSProfilePlugin.getPlugin().getProfile(); - if (profileStore != null) { - ArrayList profileList = profileStore.getProfileList(); - ArrayAdapter adapter = new ArrayAdapter<>(getContext(), - R.layout.spinner_centered, profileList); - profileSpinner.setAdapter(adapter); - // set selected to actual profile - for (int p = 0; p < profileList.size(); p++) { - if (profileList.get(p).equals(ProfileFunctions.getInstance().getProfileName())) - profileSpinner.setSelection(p); - } - noProfile.setVisibility(View.GONE); - } else { - noProfile.setVisibility(View.VISIBLE); - } - } - - @OnItemSelected(R.id.nsprofile_spinner) - public void onItemSelected(Spinner spinner, int position) { - String name = spinner.getItemAtPosition(position).toString(); - - ProfileStore store = NSProfilePlugin.getPlugin().getProfile(); - if (store != null) { - Profile profile = store.getSpecificProfile(name); - if (profile != null) { - units.setText(profile.getUnits()); - dia.setText(DecimalFormatter.to2Decimal(profile.getDia()) + " h"); - activeProfile.setText(name); - ic.setText(profile.getIcList()); - isf.setText(profile.getIsfList()); - basal.setText(profile.getBasalList()); - basaltotal.setText(String.format(MainApp.gs(R.string.profile_total), DecimalFormatter.to2Decimal(profile.baseBasalSum()))); - target.setText(profile.getTargetList()); - basalGraph.show(profile); - } - if (profile.isValid("NSProfileFragment")) { - invalidProfile.setVisibility(View.GONE); - activateButton.setVisibility(View.VISIBLE); - } else { - invalidProfile.setVisibility(View.VISIBLE); - activateButton.setVisibility(View.GONE); - } - } else { - activateButton.setVisibility(View.GONE); - } - } - - @OnItemSelected(value = R.id.nsprofile_spinner, callback = NOTHING_SELECTED) - public void onNothingSelected() { - invalidProfile.setVisibility(View.VISIBLE); - noProfile.setVisibility(View.VISIBLE); - units.setText(""); - dia.setText(""); - activeProfile.setText(""); - ic.setText(""); - isf.setText(""); - basal.setText(""); - basaltotal.setText(""); - target.setText(""); - activateButton.setVisibility(View.GONE); - } - - @OnClick(R.id.nsprofile_profileswitch) - public void onClickProfileSwitch() { - String name = profileSpinner.getSelectedItem() != null ? profileSpinner.getSelectedItem().toString() : ""; - ProfileStore store = NSProfilePlugin.getPlugin().getProfile(); - if (store != null) { - Profile profile = store.getSpecificProfile(name); - if (profile != null) { - OKDialog.showConfirmation(getActivity(), MainApp.gs(R.string.activate_profile) + ": " + name + " ?", () -> - NewNSTreatmentDialog.doProfileSwitch(store, name, 0, 100, 0) - ); - } - } - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/events/EventNSProfileUpdateGUI.java b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/events/EventNSProfileUpdateGUI.java deleted file mode 100644 index d24c59e511..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/events/EventNSProfileUpdateGUI.java +++ /dev/null @@ -1,9 +0,0 @@ -package info.nightscout.androidaps.plugins.ProfileNS.events; - -import info.nightscout.androidaps.events.EventUpdateGui; - -/** - * Created by mike on 05.08.2016. - */ -public class EventNSProfileUpdateGUI extends EventUpdateGui { -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboFragment.java deleted file mode 100644 index e1ae0286de..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboFragment.java +++ /dev/null @@ -1,234 +0,0 @@ -package info.nightscout.androidaps.plugins.PumpCombo; - - -import android.app.Activity; -import android.app.AlertDialog; -import android.graphics.Color; -import android.graphics.Typeface; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Button; -import android.widget.TextView; - -import com.squareup.otto.Subscribe; - -import org.apache.commons.lang3.StringUtils; - -import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.PumpState; -import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.history.Bolus; -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.plugins.Common.SubscriberFragment; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.PumpCombo.events.EventComboPumpUpdateGUI; -import info.nightscout.androidaps.queue.Callback; -import info.nightscout.androidaps.queue.events.EventQueueChanged; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.SP; - -public class ComboFragment extends SubscriberFragment implements View.OnClickListener { - private TextView stateView; - private TextView activityView; - private TextView batteryView; - private TextView reservoirView; - private TextView lastConnectionView; - private TextView lastBolusView; - private TextView baseBasalRate; - private TextView tempBasalText; - private Button refreshButton; - private TextView bolusCount; - private TextView tbrCount; - - @Override - public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.combopump_fragment, container, false); - - stateView = view.findViewById(R.id.combo_state); - activityView = view.findViewById(R.id.combo_activity); - batteryView = view.findViewById(R.id.combo_pumpstate_battery); - reservoirView = view.findViewById(R.id.combo_insulinstate); - lastBolusView = view.findViewById(R.id.combo_last_bolus); - lastConnectionView = view.findViewById(R.id.combo_lastconnection); - baseBasalRate = view.findViewById(R.id.combo_base_basal_rate); - tempBasalText = view.findViewById(R.id.combo_temp_basal); - bolusCount = view.findViewById(R.id.combo_bolus_count); - tbrCount = view.findViewById(R.id.combo_tbr_count); - - refreshButton = view.findViewById(R.id.combo_refresh_button); - refreshButton.setOnClickListener(this); - - updateGUI(); - return view; - } - - private void runOnUiThread(Runnable action) { - Activity activity = getActivity(); - if (activity != null) { - activity.runOnUiThread(action); - } - } - - @Override - public void onClick(View view) { - switch (view.getId()) { - case R.id.combo_refresh_button: - refreshButton.setEnabled(false); - ConfigBuilderPlugin.getPlugin().getCommandQueue().readStatus("User request", new Callback() { - @Override - public void run() { - runOnUiThread(() -> refreshButton.setEnabled(true)); - } - }); - break; - } - } - - @Subscribe - public void onStatusEvent(final EventComboPumpUpdateGUI ignored) { - updateGUI(); - } - - @Subscribe - public void onStatusEvent(final EventQueueChanged ignored) { - updateGUI(); - } - - - public void updateGUI() { - runOnUiThread(() -> { - ComboPlugin plugin = ComboPlugin.getPlugin(); - - // state - stateView.setText(plugin.getStateSummary()); - PumpState ps = plugin.getPump().state; - if (ps.insulinState == PumpState.EMPTY || ps.batteryState == PumpState.EMPTY - || ps.activeAlert != null && ps.activeAlert.errorCode != null) { - stateView.setTextColor(Color.RED); - stateView.setTypeface(null, Typeface.BOLD); - } else if (plugin.getPump().state.suspended - || ps.activeAlert != null && ps.activeAlert.warningCode != null) { - stateView.setTextColor(Color.YELLOW); - stateView.setTypeface(null, Typeface.BOLD); - } else { - stateView.setTextColor(Color.WHITE); - stateView.setTypeface(null, Typeface.NORMAL); - } - - // activity - String activity = plugin.getPump().activity; - if (activity != null) { - activityView.setTextColor(Color.WHITE); - activityView.setTextSize(14); - activityView.setText(activity); - } else if (ConfigBuilderPlugin.getPlugin().getCommandQueue().size() > 0) { - activityView.setTextColor(Color.WHITE); - activityView.setTextSize(14); - activityView.setText(""); - } else if (plugin.isInitialized()){ - activityView.setTextColor(Color.WHITE); - activityView.setTextSize(20); - activityView.setText("{fa-bed}"); - } else { - activityView.setTextColor(Color.RED); - activityView.setTextSize(14); - activityView.setText(MainApp.gs(R.string.pump_unreachable)); - } - - if (plugin.isInitialized()) { - // battery - batteryView.setTextSize(20); - if (ps.batteryState == PumpState.EMPTY) { - batteryView.setText("{fa-battery-empty}"); - batteryView.setTextColor(Color.RED); - } else if (ps.batteryState == PumpState.LOW) { - batteryView.setText("{fa-battery-quarter}"); - batteryView.setTextColor(Color.YELLOW); - } else { - batteryView.setText("{fa-battery-full}"); - batteryView.setTextColor(Color.WHITE); - } - - // reservoir - int reservoirLevel = plugin.getPump().reservoirLevel; - if (reservoirLevel != -1) { - reservoirView.setText(reservoirLevel + " " + MainApp.gs(R.string.insulin_unit_shortname)); - } else if (ps.insulinState == PumpState.LOW) { - reservoirView.setText(MainApp.gs(R.string.combo_reservoir_low)); - } else if (ps.insulinState == PumpState.EMPTY) { - reservoirView.setText(MainApp.gs(R.string.combo_reservoir_empty)); - } else { - reservoirView.setText(MainApp.gs(R.string.combo_reservoir_normal)); - } - - if (ps.insulinState == PumpState.UNKNOWN) { - reservoirView.setTextColor(Color.WHITE); - reservoirView.setTypeface(null, Typeface.NORMAL); - } else if (ps.insulinState == PumpState.LOW) { - reservoirView.setTextColor(Color.YELLOW); - reservoirView.setTypeface(null, Typeface.BOLD); - } else if (ps.insulinState == PumpState.EMPTY) { - reservoirView.setTextColor(Color.RED); - reservoirView.setTypeface(null, Typeface.BOLD); - } else { - reservoirView.setTextColor(Color.WHITE); - reservoirView.setTypeface(null, Typeface.NORMAL); - } - - // last connection - String minAgo = DateUtil.minAgo(plugin.getPump().lastSuccessfulCmdTime); - long min = (System.currentTimeMillis() - plugin.getPump().lastSuccessfulCmdTime) / 1000 / 60; - if (plugin.getPump().lastSuccessfulCmdTime + 60 * 1000 > System.currentTimeMillis()) { - lastConnectionView.setText(R.string.combo_pump_connected_now); - lastConnectionView.setTextColor(Color.WHITE); - } else if (plugin.getPump().lastSuccessfulCmdTime + 30 * 60 * 1000 < System.currentTimeMillis()) { - lastConnectionView.setText(MainApp.gs(R.string.combo_no_pump_connection, min)); - lastConnectionView.setTextColor(Color.RED); - } else { - lastConnectionView.setText(minAgo); - lastConnectionView.setTextColor(Color.WHITE); - } - - // last bolus - Bolus bolus = plugin.getPump().lastBolus; - if (bolus != null) { - long agoMsc = System.currentTimeMillis() - bolus.timestamp; - double bolusMinAgo = agoMsc / 60d / 1000d; - String unit = MainApp.gs(R.string.insulin_unit_shortname); - String ago; - if ((agoMsc < 60 * 1000)) { - ago = MainApp.gs(R.string.combo_pump_connected_now); - } else if (bolusMinAgo < 60) { - ago = DateUtil.minAgo(bolus.timestamp); - } else { - ago = DateUtil.hourAgo(bolus.timestamp); - } - lastBolusView.setText(MainApp.gs(R.string.combo_last_bolus, bolus.amount, unit, ago)); - } else { - lastBolusView.setText(""); - } - - // base basal rate - baseBasalRate.setText(MainApp.gs(R.string.pump_basebasalrate, plugin.getBaseBasalRate())); - - // TBR - String tbrStr = ""; - if (ps.tbrPercent != -1 && ps.tbrPercent != 100) { - long minSinceRead = (System.currentTimeMillis() - plugin.getPump().state.timestamp) / 1000 / 60; - long remaining = ps.tbrRemainingDuration - minSinceRead; - if (remaining >= 0) { - tbrStr = MainApp.gs(R.string.combo_tbr_remaining, ps.tbrPercent, remaining); - } - } - tempBasalText.setText(tbrStr); - - // stats - bolusCount.setText(String.valueOf(SP.getLong(ComboPlugin.COMBO_BOLUSES_DELIVERED, 0L))); - tbrCount.setText(String.valueOf(SP.getLong(ComboPlugin.COMBO_TBRS_SET, 0L))); - } - }); - } -} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/events/EventComboPumpUpdateGUI.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/events/EventComboPumpUpdateGUI.java deleted file mode 100644 index e9bf3f8415..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/events/EventComboPumpUpdateGUI.java +++ /dev/null @@ -1,8 +0,0 @@ -package info.nightscout.androidaps.plugins.PumpCombo.events; - -/** - * Created by mike on 24.05.2017. - */ - -public class EventComboPumpUpdateGUI { -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRFragment.java deleted file mode 100644 index 33d371dca3..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRFragment.java +++ /dev/null @@ -1,304 +0,0 @@ -package info.nightscout.androidaps.plugins.PumpDanaR; - - -import android.app.Activity; -import android.content.Intent; -import android.os.Bundle; -import android.os.Handler; -import android.support.v4.app.FragmentManager; -import android.text.Spanned; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Button; -import android.widget.LinearLayout; -import android.widget.TextView; - -import com.squareup.otto.Subscribe; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import butterknife.BindView; -import butterknife.ButterKnife; -import butterknife.OnClick; -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.activities.TDDStatsActivity; -import info.nightscout.androidaps.db.ExtendedBolus; -import info.nightscout.androidaps.db.TemporaryBasal; -import info.nightscout.androidaps.events.EventExtendedBolusChange; -import info.nightscout.androidaps.events.EventPumpStatusChanged; -import info.nightscout.androidaps.events.EventTempBasalChange; -import info.nightscout.androidaps.interfaces.PluginType; -import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.Common.SubscriberFragment; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.PumpDanaR.Dialogs.ProfileViewDialog; -import info.nightscout.androidaps.plugins.PumpDanaR.activities.DanaRHistoryActivity; -import info.nightscout.androidaps.plugins.PumpDanaR.activities.DanaRUserOptionsActivity; -import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRNewStatus; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; -import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; -import info.nightscout.androidaps.queue.events.EventQueueChanged; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.DecimalFormatter; -import info.nightscout.utils.SetWarnColor; - -public class DanaRFragment extends SubscriberFragment { - private static Logger log = LoggerFactory.getLogger(L.PUMP); - - private Handler loopHandler = new Handler(); - private Runnable refreshLoop = new Runnable() { - @Override - public void run() { - updateGUI(); - loopHandler.postDelayed(refreshLoop, 60 * 1000L); - } - }; - - @BindView(R.id.danar_lastconnection) - TextView lastConnectionView; - @BindView(R.id.danar_btconnection) - TextView btConnectionView; - @BindView(R.id.danar_lastbolus) - TextView lastBolusView; - @BindView(R.id.danar_dailyunits) - TextView dailyUnitsView; - @BindView(R.id.danar_basabasalrate) - TextView basaBasalRateView; - @BindView(R.id.danar_tempbasal) - TextView tempBasalView; - @BindView(R.id.danar_extendedbolus) - TextView extendedBolusView; - @BindView(R.id.danar_battery) - TextView batteryView; - @BindView(R.id.danar_reservoir) - TextView reservoirView; - @BindView(R.id.danar_iob) - TextView iobView; - @BindView(R.id.danar_firmware) - TextView firmwareView; - @BindView(R.id.danar_basalstep) - TextView basalStepView; - @BindView(R.id.danar_bolusstep) - TextView bolusStepView; - @BindView(R.id.danar_serialnumber) - TextView serialNumberView; - @BindView(R.id.danar_queue) - TextView queueView; - - @BindView(R.id.overview_pumpstatuslayout) - LinearLayout pumpStatusLayout; - @BindView(R.id.overview_pumpstatus) - TextView pumpStatusView; - @BindView(R.id.danar_user_options) - Button danar_user_options; - - public DanaRFragment() { - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - loopHandler.postDelayed(refreshLoop, 60 * 1000L); - } - - @Override - public void onDestroy() { - super.onDestroy(); - loopHandler.removeCallbacks(refreshLoop); - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.danar_fragment, container, false); - unbinder = ButterKnife.bind(this, view); - - pumpStatusView.setBackgroundColor(MainApp.gc(R.color.colorInitializingBorder)); - - return view; - } - - @OnClick(R.id.danar_history) - void onHistoryClick() { - startActivity(new Intent(getContext(), DanaRHistoryActivity.class)); - } - - @OnClick(R.id.danar_viewprofile) - void onViewProfileClick() { - FragmentManager manager = getFragmentManager(); - ProfileViewDialog profileViewDialog = new ProfileViewDialog(); - profileViewDialog.show(manager, "ProfileViewDialog"); - } - - @OnClick(R.id.danar_stats) - void onStatsClick() { - startActivity(new Intent(getContext(), TDDStatsActivity.class)); - } - - @OnClick(R.id.danar_user_options) - void onUserOptionsClick() { - startActivity(new Intent(getContext(), DanaRUserOptionsActivity.class)); - } - - @OnClick(R.id.danar_btconnection) - void onBtConnectionClick() { - if (L.isEnabled(L.PUMP)) - log.debug("Clicked connect to pump"); - DanaRPump.getInstance().lastConnection = 0; - ConfigBuilderPlugin.getPlugin().getCommandQueue().readStatus("Clicked connect to pump", null); - } - - @Subscribe - public void onStatusEvent(final EventPumpStatusChanged c) { - Activity activity = getActivity(); - final String status = c.textStatus(); - if (activity != null) { - activity.runOnUiThread( - () -> { - synchronized (DanaRFragment.this) { - - if (btConnectionView == null || pumpStatusView == null || pumpStatusLayout == null) - return; - - if (c.sStatus == EventPumpStatusChanged.CONNECTING) - btConnectionView.setText("{fa-bluetooth-b spin} " + c.sSecondsElapsed + "s"); - else if (c.sStatus == EventPumpStatusChanged.CONNECTED) - btConnectionView.setText("{fa-bluetooth}"); - else if (c.sStatus == EventPumpStatusChanged.DISCONNECTED) - btConnectionView.setText("{fa-bluetooth-b}"); - - if (!status.equals("")) { - pumpStatusView.setText(status); - pumpStatusLayout.setVisibility(View.VISIBLE); - } else { - pumpStatusLayout.setVisibility(View.GONE); - } - } - } - ); - } - } - - @Subscribe - public void onStatusEvent(final EventDanaRNewStatus s) { - updateGUI(); - } - - @Subscribe - public void onStatusEvent(final EventTempBasalChange s) { - updateGUI(); - } - - @Subscribe - public void onStatusEvent(final EventExtendedBolusChange s) { - updateGUI(); - } - - @Subscribe - public void onStatusEvent(final EventQueueChanged s) { - updateGUI(); - } - - // GUI functions - @Override - protected void updateGUI() { - Activity activity = getActivity(); - if (activity != null && basaBasalRateView != null) - activity.runOnUiThread(() -> { - synchronized (DanaRFragment.this) { - if (!isBound()) return; - - DanaRPump pump = DanaRPump.getInstance(); - if (pump.lastConnection != 0) { - Long agoMsec = System.currentTimeMillis() - pump.lastConnection; - int agoMin = (int) (agoMsec / 60d / 1000d); - lastConnectionView.setText(DateUtil.timeString(pump.lastConnection) + " (" + String.format(MainApp.gs(R.string.minago), agoMin) + ")"); - SetWarnColor.setColor(lastConnectionView, agoMin, 16d, 31d); - } - if (pump.lastBolusTime != 0) { - Long agoMsec = System.currentTimeMillis() - pump.lastBolusTime; - double agoHours = agoMsec / 60d / 60d / 1000d; - if (agoHours < 6) // max 6h back - lastBolusView.setText(DateUtil.timeString(pump.lastBolusTime) + " " + DateUtil.sinceString(pump.lastBolusTime) + " " + DecimalFormatter.to2Decimal(DanaRPump.getInstance().lastBolusAmount) + " U"); - else lastBolusView.setText(""); - } - - dailyUnitsView.setText(DecimalFormatter.to0Decimal(pump.dailyTotalUnits) + " / " + pump.maxDailyTotalUnits + " U"); - SetWarnColor.setColor(dailyUnitsView, pump.dailyTotalUnits, pump.maxDailyTotalUnits * 0.75d, pump.maxDailyTotalUnits * 0.9d); - basaBasalRateView.setText("( " + (pump.activeProfile + 1) + " ) " + DecimalFormatter.to2Decimal(ConfigBuilderPlugin.getPlugin().getActivePump().getBaseBasalRate()) + " U/h"); - // DanaRPlugin, DanaRKoreanPlugin - if (ConfigBuilderPlugin.getPlugin().getActivePump().isFakingTempsByExtendedBoluses()) { - if (TreatmentsPlugin.getPlugin().isInHistoryRealTempBasalInProgress()) { - tempBasalView.setText(TreatmentsPlugin.getPlugin().getRealTempBasalFromHistory(System.currentTimeMillis()).toStringFull()); - } else { - tempBasalView.setText(""); - } - } else { - // v2 plugin - TemporaryBasal tb = TreatmentsPlugin.getPlugin().getTempBasalFromHistory(System.currentTimeMillis()); - if (tb != null) { - tempBasalView.setText(tb.toStringFull()); - } else { - tempBasalView.setText(""); - } - } - ExtendedBolus activeExtendedBolus = TreatmentsPlugin.getPlugin().getExtendedBolusFromHistory(System.currentTimeMillis()); - if (activeExtendedBolus != null) { - extendedBolusView.setText(activeExtendedBolus.toString()); - } else { - extendedBolusView.setText(""); - } - reservoirView.setText(DecimalFormatter.to0Decimal(pump.reservoirRemainingUnits) + " / 300 U"); - SetWarnColor.setColorInverse(reservoirView, pump.reservoirRemainingUnits, 50d, 20d); - batteryView.setText("{fa-battery-" + (pump.batteryRemaining / 25) + "}"); - SetWarnColor.setColorInverse(batteryView, pump.batteryRemaining, 51d, 26d); - iobView.setText(pump.iob + " U"); - if (pump.model != 0 || pump.protocol != 0 || pump.productCode != 0) { - firmwareView.setText(String.format(MainApp.gs(R.string.danar_model), pump.model, pump.protocol, pump.productCode)); - } else { - firmwareView.setText("OLD"); - } - basalStepView.setText("" + pump.basalStep); - bolusStepView.setText("" + pump.bolusStep); - serialNumberView.setText("" + pump.serialNumber); - if (queueView != null) { - Spanned status = ConfigBuilderPlugin.getPlugin().getCommandQueue().spannedStatus(); - if (status.toString().equals("")) { - queueView.setVisibility(View.GONE); - } else { - queueView.setVisibility(View.VISIBLE); - queueView.setText(status); - } - } - //hide user options button if not an RS pump or old firmware - // also excludes pump with model 03 because of untested error - boolean isKorean = DanaRKoreanPlugin.getPlugin().isEnabled(PluginType.PUMP); - if (isKorean || firmwareView.getText() == "OLD" || pump.model == 3) { - danar_user_options.setVisibility(View.GONE); - } - } - }); - } - - private boolean isBound() { - return lastConnectionView != null - && lastBolusView != null - && dailyUnitsView != null - && basaBasalRateView != null - && tempBasalView != null - && extendedBolusView != null - && reservoirView != null - && batteryView != null - && iobView != null - && firmwareView != null - && basalStepView != null - && bolusStepView != null - && serialNumberView != null - && danar_user_options != null - && queueView != null; - } - -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/Dialogs/ProfileViewDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/Dialogs/ProfileViewDialog.java deleted file mode 100644 index 06906aa0b4..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/Dialogs/ProfileViewDialog.java +++ /dev/null @@ -1,92 +0,0 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.Dialogs; - -import android.os.Bundle; -import android.support.v4.app.DialogFragment; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Button; -import android.widget.TextView; - -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.data.Profile; -import info.nightscout.androidaps.data.ProfileStore; -import info.nightscout.androidaps.interfaces.ProfileInterface; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.Treatments.fragments.ProfileGraph; -import info.nightscout.utils.DecimalFormatter; - -/** - * Created by mike on 10.07.2016. - */ -public class ProfileViewDialog extends DialogFragment { - private TextView noProfile; - private TextView units; - private TextView dia; - private TextView activeProfile; - private TextView ic; - private TextView isf; - private TextView basal; - private TextView target; - private ProfileGraph basalGraph; - - - private Button refreshButton; - - public ProfileViewDialog() { - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - View layout = inflater.inflate(R.layout.profileviewer_fragment, container, false); - - noProfile = (TextView) layout.findViewById(R.id.profileview_noprofile); - units = (TextView) layout.findViewById(R.id.profileview_units); - dia = (TextView) layout.findViewById(R.id.profileview_dia); - activeProfile = (TextView) layout.findViewById(R.id.profileview_activeprofile); - ic = (TextView) layout.findViewById(R.id.profileview_ic); - isf = (TextView) layout.findViewById(R.id.profileview_isf); - basal = (TextView) layout.findViewById(R.id.profileview_basal); - target = (TextView) layout.findViewById(R.id.profileview_target); - refreshButton = (Button) layout.findViewById(R.id.profileview_reload); - refreshButton.setVisibility(View.VISIBLE); - refreshButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - ConfigBuilderPlugin.getPlugin().getCommandQueue().readStatus("ProfileViewDialog", null); - dismiss(); - } - }); - basalGraph = (ProfileGraph) layout.findViewById(R.id.basal_graph); - setContent(); - return layout; - } - - @Override - public void onResume() { - super.onResume(); - getDialog().getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); - } - - private void setContent() { - ProfileStore store = ((ProfileInterface)ConfigBuilderPlugin.getPlugin().getActivePump()).getProfile(); - if (store != null) { - noProfile.setVisibility(View.GONE); - Profile profile = store.getDefaultProfile(); - units.setText(profile.getUnits()); - dia.setText(DecimalFormatter.to2Decimal(profile.getDia()) + " h"); - activeProfile.setText(((ProfileInterface) ConfigBuilderPlugin.getPlugin().getActivePump()).getProfileName()); - ic.setText(profile.getIcList()); - isf.setText(profile.getIsfList()); - basal.setText(profile.getBasalList()); - target.setText(profile.getTargetList()); - basalGraph.show(store.getDefaultProfile()); - } else { - noProfile.setVisibility(View.VISIBLE); - } - } - - -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MessageHashTable.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MessageHashTable.java deleted file mode 100644 index e7f1adca07..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MessageHashTable.java +++ /dev/null @@ -1,85 +0,0 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.HashMap; - -/** - * Created by mike on 28.05.2016. - */ -public class MessageHashTable { - public static HashMap messages = null; - - static { - if (messages == null) { - messages = new HashMap(); - put(new MsgBolusStop()); // 0x0101 CMD_MEALINS_STOP - put(new MsgBolusStart()); // 0x0102 CMD_MEALINS_START_DATA - put(new MsgBolusStartWithSpeed()); // 0x0104 CMD_MEALINS_START_DATA_SPEED - put(new MsgBolusProgress()); // 0x0202 CMD_PUMP_THIS_REMAINDER_MEAL_INS - put(new MsgStatusProfile()); // 0x0204 CMD_PUMP_CALCULATION_SETTING - put(new MsgStatusTempBasal()); // 0x0205 CMD_PUMP_EXERCISE_MODE - put(new MsgStatusBolusExtended()); // 0x0207 CMD_PUMP_EXPANS_INS_I - put(new MsgStatusBasic()); // 0x020A CMD_PUMP_INITVIEW_I - put(new MsgStatus()); // 0x020B CMD_PUMP_STATUS - put(new MsgInitConnStatusTime()); // 0x0301 CMD_PUMPINIT_TIME_INFO - put(new MsgInitConnStatusBolus()); // 0x0302 CMD_PUMPINIT_BOLUS_INFO - put(new MsgInitConnStatusBasic()); // 0x0303 CMD_PUMPINIT_INIT_INFO - put(new MsgInitConnStatusOption()); // 0x0304 CMD_PUMPINIT_OPTION - put(new MsgSetTempBasalStart()); // 0x0401 CMD_PUMPSET_EXERCISE_S - put(new MsgSetCarbsEntry()); // 0x0402 CMD_PUMPSET_HIS_S - put(new MsgSetTempBasalStop()); // 0x0403 CMD_PUMPSET_EXERCISE_STOP - put(new MsgSetExtendedBolusStop()); // 0x0406 CMD_PUMPSET_EXPANS_INS_STOP - put(new MsgSetExtendedBolusStart()); // 0x0407 CMD_PUMPSET_EXPANS_INS_S - put(new MsgError()); // 0x0601 CMD_PUMPOWAY_SYSTEM_STATUS - put(new MsgPCCommStart()); // 0x3001 CMD_CONNECT - put(new MsgPCCommStop()); // 0x3002 CMD_DISCONNECT - put(new MsgHistoryBolus()); // 0x3101 CMD_HISTORY_MEAL_INS - put(new MsgHistoryDailyInsulin()); // 0x3102 CMD_HISTORY_DAY_INS - put(new MsgHistoryGlucose()); // 0x3104 CMD_HISTORY_GLUCOSE - put(new MsgHistoryAlarm()); // 0x3105 CMD_HISTORY_ALARM - put(new MsgHistoryError()); // 0x3106 CMD_HISTORY_ERROR - put(new MsgHistoryCarbo()); // 0x3107 CMD_HISTORY_CARBOHY - put(new MsgHistoryRefill()); // 0x3108 CMD_HISTORY_REFILL - put(new MsgHistorySuspend()); // 0x3109 CMD_HISTORY_SUSPEND - put(new MsgHistoryBasalHour()); // 0x310A CMD_HISTORY_BASAL_HOUR - put(new MsgHistoryDone()); // 0x31F1 CMD_HISTORY_DONT_USED - put(new MsgSettingBasal()); // 0x3202 CMD_SETTING_V_BASAL_INS_I - put(new MsgSettingMeal()); // 0x3203 CMD_SETTING_V_MEAL_SETTING_I - put(new MsgSettingProfileRatios()); // 0x3204 CMD_SETTING_V_CCC_I - put(new MsgSettingMaxValues()); // 0x3205 CMD_SETTING_V_MAX_VALUE_I - put(new MsgSettingBasalProfileAll()); // 0x3206 CMD_SETTING_V_BASAL_PROFILE_ALL - put(new MsgSettingShippingInfo()); // 0x3207 CMD_SETTING_V_SHIPPING_I - put(new MsgSettingGlucose()); // 0x3209 CMD_SETTING_V_GLUCOSEandEASY - put(new MsgSettingPumpTime()); // 0x320A CMD_SETTING_V_TIME_I - put(new MsgSettingUserOptions()); // 0x320B CMD_SETTING_V_USER_OPTIONS - put(new MsgSettingActiveProfile()); // 0x320C CMD_SETTING_V_PROFILE_NUMBER - put(new MsgSettingProfileRatiosAll()); // 0x320D CMD_SETTING_V_CIR_CF_VALUE - put(new MsgSetSingleBasalProfile()); // 0x3302 CMD_SETTING_BASAL_INS_S - put(new MsgSetBasalProfile()); // 0x3306 CMD_SETTING_BASAL_PROFILE_S - put(new MsgSetUserOptions()); // 0x330B CMD_SETTING_USER_OPTIONS_S - put(new MsgSetActivateBasalProfile()); // 0x330C CMD_SETTING_PROFILE_NUMBER_S - put(new MsgHistoryAllDone()); // 0x41F1 CMD_HISTORY_ALL_DONE - put(new MsgHistoryAll()); // 0x41F2 CMD_HISTORY_ALL - put(new MsgHistoryNewDone()); // 0x42F1 CMD_HISTORY_NEW_DONE - put(new MsgHistoryNew()); // 0x42F2 CMD_HISTORY_NEW - put(new MsgCheckValue()); // 0xF0F1 CMD_PUMP_CHECK_VALUE - } - } - - public static void put(MessageBase message) { - int command = message.getCommand(); - //String name = MessageOriginalNames.getName(command); - messages.put(command, message); - //log.debug(String.format("%04x ", command) + " " + name); - } - - public static MessageBase findMessage(Integer command) { - if (messages.containsKey(command)) { - return messages.get(command); - } else { - return new MessageBase(); - } - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/events/EventDanaRNewStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/events/EventDanaRNewStatus.java deleted file mode 100644 index 55b0ab0998..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/events/EventDanaRNewStatus.java +++ /dev/null @@ -1,9 +0,0 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.events; - -import info.nightscout.androidaps.events.Event; - -/** - * Created by mike on 08.07.2016. - */ -public class EventDanaRNewStatus extends Event { -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/events/EventDanaRSyncStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/events/EventDanaRSyncStatus.java deleted file mode 100644 index f2a5dc7b2a..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/events/EventDanaRSyncStatus.java +++ /dev/null @@ -1,14 +0,0 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.events; - -import info.nightscout.androidaps.events.Event; - -/** - * Created by mike on 20.07.2016. - */ -public class EventDanaRSyncStatus extends Event { - public String message; - - public EventDanaRSyncStatus() { - } - - } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/SerialIOThread.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/SerialIOThread.java deleted file mode 100644 index ea12b2b9c4..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/SerialIOThread.java +++ /dev/null @@ -1,210 +0,0 @@ -package info.nightscout.androidaps.plugins.PumpDanaRKorean; - -import android.bluetooth.BluetoothSocket; -import android.os.SystemClock; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; -import info.nightscout.androidaps.plugins.PumpDanaR.services.AbstractSerialIOThread; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.comm.MessageHashTable_k; -import info.nightscout.utils.CRC; - -/** - * Created by mike on 17.07.2016. - */ -public class SerialIOThread extends AbstractSerialIOThread { - private static Logger log = LoggerFactory.getLogger(L.PUMPBTCOMM); - - private InputStream mInputStream = null; - private OutputStream mOutputStream = null; - private BluetoothSocket mRfCommSocket; - - private boolean mKeepRunning = true; - private byte[] mReadBuff = new byte[0]; - - private MessageBase processedMessage; - - public SerialIOThread(BluetoothSocket rfcommSocket) { - super(); - - mRfCommSocket = rfcommSocket; - try { - mOutputStream = mRfCommSocket.getOutputStream(); - mInputStream = mRfCommSocket.getInputStream(); - } catch (IOException e) { - log.error("Unhandled exception", e); - } - this.start(); - } - - @Override - public final void run() { - try { - while (mKeepRunning) { - int availableBytes = mInputStream.available(); - // Ask for 1024 byte (or more if available) - byte[] newData = new byte[Math.max(1024, availableBytes)]; - int gotBytes = mInputStream.read(newData); - // When we are here there is some new data available - appendToBuffer(newData, gotBytes); - - // process all messages we already got - while (mReadBuff.length > 3) { // 3rd byte is packet size. continue only if we an determine packet size - byte[] extractedBuff = cutMessageFromBuffer(); - if (extractedBuff == null) - break; // message is not complete in buffer (wrong packet calls disconnection) - - int command = (extractedBuff[5] & 0xFF) | ((extractedBuff[4] << 8) & 0xFF00); - - MessageBase message; - if (processedMessage != null && processedMessage.getCommand() == command) { - message = processedMessage; - } else { - // get it from hash table - message = MessageHashTable_k.findMessage(command); - } - - if (L.isEnabled(L.PUMPBTCOMM)) - log.debug("<<<<< " + message.getMessageName() + " " + message.toHexString(extractedBuff)); - - // process the message content - message.received = true; - message.handleMessage(extractedBuff); - synchronized (message) { - message.notify(); - } - } - } - } catch (Exception e) { - if (e.getMessage().indexOf("bt socket closed") < 0) - log.error("Thread exception: ", e); - mKeepRunning = false; - } - disconnect("EndOfLoop"); - } - - void appendToBuffer(byte[] newData, int gotBytes) { - // add newData to mReadBuff - byte[] newReadBuff = new byte[mReadBuff.length + gotBytes]; - System.arraycopy(mReadBuff, 0, newReadBuff, 0, mReadBuff.length); - System.arraycopy(newData, 0, newReadBuff, mReadBuff.length, gotBytes); - mReadBuff = newReadBuff; - } - - byte[] cutMessageFromBuffer() { - if (mReadBuff[0] == (byte) 0x7E && mReadBuff[1] == (byte) 0x7E) { - int length = (mReadBuff[2] & 0xFF) + 7; - // Check if we have enough data - if (mReadBuff.length < length) { - return null; - } - if (mReadBuff[length - 2] != (byte) 0x2E || mReadBuff[length - 1] != (byte) 0x2E) { - log.error("wrong packet lenght=" + length + " data " + MessageBase.toHexString(mReadBuff)); - disconnect("wrong packet"); - return null; - } - - short crc = CRC.getCrc16(mReadBuff, 3, length - 7); - byte crcByte0 = (byte) (crc >> 8 & 0xFF); - byte crcByte1 = (byte) (crc & 0xFF); - - byte crcByte0received = mReadBuff[length - 4]; - byte crcByte1received = mReadBuff[length - 3]; - - if (crcByte0 != crcByte0received || crcByte1 != crcByte1received) { - log.error("CRC Error" + String.format("%02x ", crcByte0) + String.format("%02x ", crcByte1) + String.format("%02x ", crcByte0received) + String.format("%02x ", crcByte1received)); - disconnect("crc error"); - return null; - } - // Packet is verified here. extract data - byte[] extractedBuff = new byte[length]; - System.arraycopy(mReadBuff, 0, extractedBuff, 0, length); - // remove extracted data from read buffer - byte[] unprocessedData = new byte[mReadBuff.length - length]; - System.arraycopy(mReadBuff, length, unprocessedData, 0, unprocessedData.length); - mReadBuff = unprocessedData; - return extractedBuff; - } else { - log.error("Wrong beginning of packet len=" + mReadBuff.length + " " + MessageBase.toHexString(mReadBuff)); - disconnect("Wrong beginning of packet"); - return null; - } - } - - @Override - public synchronized void sendMessage(MessageBase message) { - if (!mRfCommSocket.isConnected()) { - log.error("Socket not connected on sendMessage"); - return; - } - processedMessage = message; - - byte[] messageBytes = message.getRawMessageBytes(); - if (L.isEnabled(L.PUMPBTCOMM)) - log.debug(">>>>> " + message.getMessageName() + " " + message.toHexString(messageBytes)); - - try { - mOutputStream.write(messageBytes); - } catch (Exception e) { - log.error("sendMessage write exception: ", e); - } - - synchronized (message) { - try { - message.wait(5000); - } catch (InterruptedException e) { - log.error("sendMessage InterruptedException", e); - } - } - - SystemClock.sleep(200); - if (!message.received) { - if (L.isEnabled(L.PUMPBTCOMM)) - log.warn("Reply not received " + message.getMessageName()); - if (message.getCommand() == 0xF0F1) { - DanaRPump.getInstance().isNewPump = false; - log.error("Old firmware detected"); - } - } - } - - @Override - public void disconnect(String reason) { - mKeepRunning = false; - try { - mInputStream.close(); - } catch (Exception e) { - if (L.isEnabled(L.PUMPBTCOMM)) - log.debug(e.getMessage()); - } - try { - mOutputStream.close(); - } catch (Exception e) { - if (L.isEnabled(L.PUMPBTCOMM)) - log.debug(e.getMessage()); - } - try { - mRfCommSocket.close(); - } catch (Exception e) { - if (L.isEnabled(L.PUMPBTCOMM)) - log.debug(e.getMessage()); - } - try { - System.runFinalization(); - } catch (Exception e) { - if (L.isEnabled(L.PUMPBTCOMM)) - log.debug(e.getMessage()); - } - if (L.isEnabled(L.PUMPBTCOMM)) - log.debug("Disconnected: " + reason); - } - -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MessageHashTable_k.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MessageHashTable_k.java deleted file mode 100644 index 422391c127..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MessageHashTable_k.java +++ /dev/null @@ -1,76 +0,0 @@ -package info.nightscout.androidaps.plugins.PumpDanaRKorean.comm; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.HashMap; - -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.*; - -/** - * Created by mike on 28.05.2016. - */ -public class MessageHashTable_k { - private static Logger log = LoggerFactory.getLogger(MessageHashTable_k.class); - - public static HashMap messages = null; - - static { - if (messages == null) { - messages = new HashMap(); - put(new MsgBolusStop()); // 0x0101 CMD_MEALINS_STOP - put(new MsgBolusStart()); // 0x0102 CMD_MEALINS_START_DATA - put(new MsgBolusProgress()); // 0x0202 CMD_PUMP_THIS_REMAINDER_MEAL_INS - put(new MsgStatusProfile()); // 0x0204 CMD_PUMP_CALCULATION_SETTING - put(new MsgStatusTempBasal()); // 0x0205 CMD_PUMP_EXERCISE_MODE - put(new MsgStatusBolusExtended()); // 0x0207 CMD_PUMP_EXPANS_INS_I - put(new MsgStatusBasic_k()); // 0x020A CMD_PUMP_INITVIEW_I - put(new MsgStatus_k()); // 0x020B CMD_PUMP_STATUS - put(new MsgInitConnStatusTime_k()); // 0x0301 CMD_PUMPINIT_TIME_INFO - put(new MsgInitConnStatusBolus_k()); // 0x0302 CMD_PUMPINIT_BOLUS_INFO - put(new MsgInitConnStatusBasic_k()); // 0x0303 CMD_PUMPINIT_INIT_INFO - put(new MsgSetTempBasalStart()); // 0x0401 CMD_PUMPSET_EXERCISE_S - put(new MsgSetCarbsEntry()); // 0x0402 CMD_PUMPSET_HIS_S - put(new MsgSetTempBasalStop()); // 0x0403 CMD_PUMPSET_EXERCISE_STOP - put(new MsgSetExtendedBolusStop()); // 0x0406 CMD_PUMPSET_EXPANS_INS_STOP - put(new MsgSetExtendedBolusStart()); // 0x0407 CMD_PUMPSET_EXPANS_INS_S - put(new MsgError()); // 0x0601 CMD_PUMPOWAY_SYSTEM_STATUS - put(new MsgPCCommStart()); // 0x3001 CMD_CONNECT - put(new MsgPCCommStop()); // 0x3002 CMD_DISCONNECT - put(new MsgHistoryBolus()); // 0x3101 CMD_HISTORY_MEAL_INS - put(new MsgHistoryDailyInsulin()); // 0x3102 CMD_HISTORY_DAY_INS - put(new MsgHistoryGlucose()); // 0x3104 CMD_HISTORY_GLUCOSE - put(new MsgHistoryAlarm()); // 0x3105 CMD_HISTORY_ALARM - put(new MsgHistoryCarbo()); // 0x3107 CMD_HISTORY_CARBOHY - put(new MsgSettingBasal_k()); // 0x3202 CMD_SETTING_V_BASAL_INS_I - put(new MsgSettingMeal()); // 0x3203 CMD_SETTING_V_MEAL_SETTING_I - put(new MsgSettingProfileRatios()); // 0x3204 CMD_SETTING_V_CCC_I - put(new MsgSettingMaxValues()); // 0x3205 CMD_SETTING_V_MAX_VALUE_I - put(new MsgSettingBasalProfileAll_k()); // 0x3206 CMD_SETTING_V_BASAL_PROFILE_ALL - put(new MsgSettingShippingInfo()); // 0x3207 CMD_SETTING_V_SHIPPING_I - put(new MsgSettingGlucose()); // 0x3209 CMD_SETTING_V_GLUCOSEandEASY - put(new MsgSettingPumpTime()); // 0x320A CMD_SETTING_V_TIME_I - put(new MsgSetSingleBasalProfile()); // 0x3302 CMD_SETTING_BASAL_INS_S - put(new MsgHistoryAll()); // 0x41F2 CMD_HISTORY_ALL - put(new MsgHistoryNewDone()); // 0x42F1 CMD_HISTORY_NEW_DONE - put(new MsgHistoryNew()); // 0x42F2 CMD_HISTORY_NEW - put(new MsgCheckValue_k()); // 0xF0F1 CMD_PUMP_CHECK_VALUE - } - } - - public static void put(MessageBase message) { - int command = message.getCommand(); - //String name = MessageOriginalNames.getName(command); - messages.put(command, message); - //log.debug(String.format("%04x ", command) + " " + name); - } - - public static MessageBase findMessage(Integer command) { - if (messages.containsKey(command)) { - return messages.get(command); - } else { - return new MessageBase(); - } - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/events/EventDanaRSDeviceChange.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/events/EventDanaRSDeviceChange.java deleted file mode 100644 index dd9b86ebce..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/events/EventDanaRSDeviceChange.java +++ /dev/null @@ -1,10 +0,0 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.events; - -import info.nightscout.androidaps.events.Event; - -/** - * Created by mike on 05.09.2017. - */ - -public class EventDanaRSDeviceChange extends Event { -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/events/EventDanaRSPacket.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/events/EventDanaRSPacket.java deleted file mode 100644 index e42b6b1440..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/events/EventDanaRSPacket.java +++ /dev/null @@ -1,16 +0,0 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.events; - -import info.nightscout.androidaps.events.Event; -import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet; - -/** - * Created by mike on 01.09.2017. - */ - -public class EventDanaRSPacket extends Event{ - public EventDanaRSPacket(DanaRS_Packet data) { - this.data = data; - } - - public DanaRS_Packet data; -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/events/EventDanaRSPairingSuccess.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/events/EventDanaRSPairingSuccess.java deleted file mode 100644 index 433cdec9bf..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/events/EventDanaRSPairingSuccess.java +++ /dev/null @@ -1,10 +0,0 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.events; - -import info.nightscout.androidaps.events.Event; - -/** - * Created by mike on 01.09.2017. - */ - -public class EventDanaRSPairingSuccess extends Event{ -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/SerialIOThread.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/SerialIOThread.java deleted file mode 100644 index 61047a8d5a..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/SerialIOThread.java +++ /dev/null @@ -1,209 +0,0 @@ -package info.nightscout.androidaps.plugins.PumpDanaRv2; - -import android.bluetooth.BluetoothSocket; -import android.os.SystemClock; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; -import info.nightscout.androidaps.plugins.PumpDanaR.services.AbstractSerialIOThread; -import info.nightscout.androidaps.plugins.PumpDanaRv2.comm.MessageHashTable_v2; -import info.nightscout.utils.CRC; - -/** - * Created by mike on 17.07.2016. - */ -public class SerialIOThread extends AbstractSerialIOThread { - private static Logger log = LoggerFactory.getLogger(L.PUMPBTCOMM); - - private InputStream mInputStream = null; - private OutputStream mOutputStream = null; - private BluetoothSocket mRfCommSocket; - - private boolean mKeepRunning = true; - private byte[] mReadBuff = new byte[0]; - - private MessageBase processedMessage; - - public SerialIOThread(BluetoothSocket rfcommSocket) { - super(); - - mRfCommSocket = rfcommSocket; - try { - mOutputStream = mRfCommSocket.getOutputStream(); - mInputStream = mRfCommSocket.getInputStream(); - } catch (IOException e) { - log.error("Unhandled exception", e); - } - this.start(); - } - - @Override - public final void run() { - try { - while (mKeepRunning) { - int availableBytes = mInputStream.available(); - // Ask for 1024 byte (or more if available) - byte[] newData = new byte[Math.max(1024, availableBytes)]; - int gotBytes = mInputStream.read(newData); - // When we are here there is some new data available - appendToBuffer(newData, gotBytes); - - // process all messages we already got - while (mReadBuff.length > 3) { // 3rd byte is packet size. continue only if we an determine packet size - byte[] extractedBuff = cutMessageFromBuffer(); - if (extractedBuff == null) - break; // message is not complete in buffer (wrong packet calls disconnection) - - int command = (extractedBuff[5] & 0xFF) | ((extractedBuff[4] << 8) & 0xFF00); - - MessageBase message; - if (processedMessage != null && processedMessage.getCommand() == command) { - message = processedMessage; - } else { - // get it from hash table - message = MessageHashTable_v2.findMessage(command); - } - - if (L.isEnabled(L.PUMPBTCOMM)) - log.debug("<<<<< " + message.getMessageName() + " " + message.toHexString(extractedBuff)); - - // process the message content - message.received = true; - message.handleMessage(extractedBuff); - synchronized (message) { - message.notify(); - } - } - } - } catch (Exception e) { - if (e.getMessage().indexOf("bt socket closed") < 0) - log.error("Thread exception: ", e); - mKeepRunning = false; - } - disconnect("EndOfLoop"); - } - - void appendToBuffer(byte[] newData, int gotBytes) { - // add newData to mReadBuff - byte[] newReadBuff = new byte[mReadBuff.length + gotBytes]; - System.arraycopy(mReadBuff, 0, newReadBuff, 0, mReadBuff.length); - System.arraycopy(newData, 0, newReadBuff, mReadBuff.length, gotBytes); - mReadBuff = newReadBuff; - } - - byte[] cutMessageFromBuffer() { - if (mReadBuff[0] == (byte) 0x7E && mReadBuff[1] == (byte) 0x7E) { - int length = (mReadBuff[2] & 0xFF) + 7; - // Check if we have enough data - if (mReadBuff.length < length) { - return null; - } - if (mReadBuff[length - 2] != (byte) 0x2E || mReadBuff[length - 1] != (byte) 0x2E) { - log.error("wrong packet lenght=" + length + " data " + MessageBase.toHexString(mReadBuff)); - disconnect("wrong packet"); - return null; - } - - short crc = CRC.getCrc16(mReadBuff, 3, length - 7); - byte crcByte0 = (byte) (crc >> 8 & 0xFF); - byte crcByte1 = (byte) (crc & 0xFF); - - byte crcByte0received = mReadBuff[length - 4]; - byte crcByte1received = mReadBuff[length - 3]; - - if (crcByte0 != crcByte0received || crcByte1 != crcByte1received) { - log.error("CRC Error" + String.format("%02x ", crcByte0) + String.format("%02x ", crcByte1) + String.format("%02x ", crcByte0received) + String.format("%02x ", crcByte1received)); - disconnect("crc error"); - return null; - } - // Packet is verified here. extract data - byte[] extractedBuff = new byte[length]; - System.arraycopy(mReadBuff, 0, extractedBuff, 0, length); - // remove extracted data from read buffer - byte[] unprocessedData = new byte[mReadBuff.length - length]; - System.arraycopy(mReadBuff, length, unprocessedData, 0, unprocessedData.length); - mReadBuff = unprocessedData; - return extractedBuff; - } else { - log.error("Wrong beginning of packet len=" + mReadBuff.length + " " + MessageBase.toHexString(mReadBuff)); - disconnect("Wrong beginning of packet"); - return null; - } - } - - @Override - public synchronized void sendMessage(MessageBase message) { - if (!mRfCommSocket.isConnected()) { - log.error("Socket not connected on sendMessage"); - return; - } - processedMessage = message; - - byte[] messageBytes = message.getRawMessageBytes(); - if (L.isEnabled(L.PUMPBTCOMM)) - log.debug(">>>>> " + message.getMessageName() + " " + message.toHexString(messageBytes)); - - try { - mOutputStream.write(messageBytes); - } catch (Exception e) { - log.error("sendMessage write exception: ", e); - } - - synchronized (message) { - try { - message.wait(5000); - } catch (InterruptedException e) { - log.error("sendMessage InterruptedException", e); - } - } - - SystemClock.sleep(200); - if (!message.received) { - log.error("Reply not received " + message.getMessageName()); - if (message.getCommand() == 0xF0F1) { - DanaRPump.getInstance().isNewPump = false; - log.error("Old firmware detected"); - } - } - } - - @Override - public void disconnect(String reason) { - mKeepRunning = false; - try { - mInputStream.close(); - } catch (Exception e) { - if (L.isEnabled(L.PUMPBTCOMM)) - log.debug(e.getMessage()); - } - try { - mOutputStream.close(); - } catch (Exception e) { - if (L.isEnabled(L.PUMPBTCOMM)) - log.debug(e.getMessage()); - } - try { - mRfCommSocket.close(); - } catch (Exception e) { - if (L.isEnabled(L.PUMPBTCOMM)) - log.debug(e.getMessage()); - } - try { - System.runFinalization(); - } catch (Exception e) { - if (L.isEnabled(L.PUMPBTCOMM)) - log.debug(e.getMessage()); - } - if (L.isEnabled(L.PUMPBTCOMM)) - log.debug("Disconnected: " + reason); - } - -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MessageHashTable_v2.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MessageHashTable_v2.java deleted file mode 100644 index c95a800128..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MessageHashTable_v2.java +++ /dev/null @@ -1,92 +0,0 @@ -package info.nightscout.androidaps.plugins.PumpDanaRv2.comm; - -import java.util.HashMap; - -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.*; - - -/** - * Created by mike on 28.05.2016. - */ -public class MessageHashTable_v2 { - public static HashMap messages = null; - - static { - if (messages == null) { - messages = new HashMap(); - put(new MsgBolusStop()); // 0x0101 CMD_MEALINS_STOP - put(new MsgBolusStart()); // 0x0102 CMD_MEALINS_START_DATA - put(new MsgBolusStartWithSpeed()); // 0x0104 CMD_MEALINS_START_DATA_SPEED - put(new MsgBolusProgress()); // 0x0202 CMD_PUMP_THIS_REMAINDER_MEAL_INS - put(new MsgStatusProfile()); // 0x0204 CMD_PUMP_CALCULATION_SETTING - - put(new MsgStatusTempBasal_v2()); // 0x0205 CMD_PUMP_EXERCISE_MODE - put(new MsgStatusBolusExtended_v2()); // 0x0207 CMD_PUMP_EXPANS_INS_I - - put(new MsgStatusBasic()); // 0x020A CMD_PUMP_INITVIEW_I - put(new MsgStatus()); // 0x020B CMD_PUMP_STATUS - put(new MsgInitConnStatusTime()); // 0x0301 CMD_PUMPINIT_TIME_INFO - put(new MsgInitConnStatusBolus()); // 0x0302 CMD_PUMPINIT_BOLUS_INFO - put(new MsgInitConnStatusBasic()); // 0x0303 CMD_PUMPINIT_INIT_INFO - put(new MsgInitConnStatusOption()); // 0x0304 CMD_PUMPINIT_OPTION - put(new MsgSetTempBasalStart()); // 0x0401 CMD_PUMPSET_EXERCISE_S - put(new MsgSetCarbsEntry()); // 0x0402 CMD_PUMPSET_HIS_S - put(new MsgSetTempBasalStop()); // 0x0403 CMD_PUMPSET_EXERCISE_STOP - put(new MsgSetExtendedBolusStop()); // 0x0406 CMD_PUMPSET_EXPANS_INS_STOP - put(new MsgSetExtendedBolusStart()); // 0x0407 CMD_PUMPSET_EXPANS_INS_S - put(new MsgError()); // 0x0601 CMD_PUMPOWAY_SYSTEM_STATUS - put(new MsgPCCommStart()); // 0x3001 CMD_CONNECT - put(new MsgPCCommStop()); // 0x3002 CMD_DISCONNECT - put(new MsgHistoryBolus()); // 0x3101 CMD_HISTORY_MEAL_INS - put(new MsgHistoryDailyInsulin()); // 0x3102 CMD_HISTORY_DAY_INS - put(new MsgHistoryGlucose()); // 0x3104 CMD_HISTORY_GLUCOSE - put(new MsgHistoryAlarm()); // 0x3105 CMD_HISTORY_ALARM - put(new MsgHistoryError()); // 0x3106 CMD_HISTORY_ERROR - put(new MsgHistoryCarbo()); // 0x3107 CMD_HISTORY_CARBOHY - put(new MsgHistoryRefill()); // 0x3108 CMD_HISTORY_REFILL - put(new MsgHistorySuspend()); // 0x3109 CMD_HISTORY_SUSPEND - put(new MsgHistoryBasalHour()); // 0x310A CMD_HISTORY_BASAL_HOUR - put(new MsgHistoryDone()); // 0x31F1 CMD_HISTORY_DONT_USED - put(new MsgSettingBasal()); // 0x3202 CMD_SETTING_V_BASAL_INS_I - put(new MsgSettingMeal()); // 0x3203 CMD_SETTING_V_MEAL_SETTING_I - put(new MsgSettingProfileRatios()); // 0x3204 CMD_SETTING_V_CCC_I - put(new MsgSettingMaxValues()); // 0x3205 CMD_SETTING_V_MAX_VALUE_I - put(new MsgSettingBasalProfileAll()); // 0x3206 CMD_SETTING_V_BASAL_PROFILE_ALL - put(new MsgSettingShippingInfo()); // 0x3207 CMD_SETTING_V_SHIPPING_I - put(new MsgSettingGlucose()); // 0x3209 CMD_SETTING_V_GLUCOSEandEASY - put(new MsgSettingPumpTime()); // 0x320A CMD_SETTING_V_TIME_I - put(new MsgSettingUserOptions()); // 0x320B CMD_SETTING_V_USER_OPTIONS - put(new MsgSettingActiveProfile()); // 0x320C CMD_SETTING_V_PROFILE_NUMBER - put(new MsgSettingProfileRatiosAll()); // 0x320D CMD_SETTING_V_CIR_CF_VALUE - put(new MsgSetSingleBasalProfile()); // 0x3302 CMD_SETTING_BASAL_INS_S - put(new MsgSetBasalProfile()); // 0x3306 CMD_SETTING_BASAL_PROFILE_S - put(new MsgSetUserOptions()); // 0x330B CMD_SETTING_USER_OPTIONS_S - put(new MsgSetActivateBasalProfile()); // 0x330C CMD_SETTING_PROFILE_NUMBER_S - put(new MsgHistoryAllDone()); // 0x41F1 CMD_HISTORY_ALL_DONE - put(new MsgHistoryAll()); // 0x41F2 CMD_HISTORY_ALL - put(new MsgHistoryNewDone()); // 0x42F1 CMD_HISTORY_NEW_DONE - put(new MsgHistoryNew()); // 0x42F2 CMD_HISTORY_NEW - put(new MsgCheckValue_v2()); // 0xF0F1 CMD_PUMP_CHECK_VALUE - put(new MsgStatusAPS_v2()); // 0xE001 CMD_PUMPSTATUS_APS - put(new MsgSetAPSTempBasalStart_v2()); // 0xE002 CMD_PUMPSET_APSTEMP - put(new MsgHistoryEvents_v2()); // 0xE003 CMD_GET_HISTORY - put(new MsgSetHistoryEntry_v2()); // 0xE004 CMD_SET_HISTORY_ENTRY - } - } - - public static void put(MessageBase message) { - int command = message.getCommand(); - //String name = MessageOriginalNames.getName(command); - messages.put(command, message); - //log.debug(String.format("%04x ", command) + " " + name); - } - - public static MessageBase findMessage(Integer command) { - if (messages.containsKey(command)) { - return messages.get(command); - } else { - return new MessageBase(); - } - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/InsightFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/InsightFragment.java deleted file mode 100644 index 5d3c3850b3..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/InsightFragment.java +++ /dev/null @@ -1,114 +0,0 @@ -package info.nightscout.androidaps.plugins.PumpInsight; - -import android.app.Activity; -import android.os.Bundle; -import android.os.Handler; -import android.support.annotation.Nullable; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.LinearLayout; - -import com.squareup.otto.Subscribe; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.List; - -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.Common.SubscriberFragment; -import info.nightscout.androidaps.plugins.PumpInsight.events.EventInsightUpdateGui; -import info.nightscout.androidaps.plugins.PumpInsight.utils.StatusItem; -import info.nightscout.androidaps.plugins.PumpInsight.utils.ui.StatusItemViewAdapter; -import info.nightscout.utils.FabricPrivacy; - - -public class InsightFragment extends SubscriberFragment { - private static final Logger log = LoggerFactory.getLogger(L.PUMP); - private static final Handler sLoopHandler = new Handler(); - private static volatile boolean refresh = false; - private static volatile boolean pending = false; - StatusItemViewAdapter viewAdapter; - LinearLayout holder; - private final Runnable sRefreshLoop = new Runnable() { - @Override - public void run() { - pending = false; - updateGUI(); - if (refresh) { - scheduleRefresh(); - } - } - }; - - private synchronized void scheduleRefresh() { - if (!pending) { - pending = true; - sLoopHandler.postDelayed(sRefreshLoop, 30 * 1000L); - } - } - - @Override - public void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - try { - final View view = inflater.inflate(R.layout.insightpump_fragment, container, false); - holder = (LinearLayout) view.findViewById(R.id.insightholder); - viewAdapter = new StatusItemViewAdapter(getActivity(), holder); - - return view; - } catch (Exception e) { - FabricPrivacy.logException(e); - } - - return null; - } - - - @Override - public void setUserVisibleHint(boolean visible) { - super.setUserVisibleHint(visible); - if (visible) { - refresh = true; - pending = false; - updateGUI(); - scheduleRefresh(); - } else { - refresh = false; - //sLoopHandler.removeCallbacksAndMessages(null); - } - } - - - @Subscribe - public void onStatusEvent(final EventInsightUpdateGui ev) { - updateGUI(); - } - - @Override - protected void updateGUI() { - final Activity activity = getActivity(); - if (activity != null && holder != null) - activity.runOnUiThread(new Runnable() { - @Override - public void run() { - final InsightPlugin insightPlugin = InsightPlugin.getPlugin(); - final List l = insightPlugin.getStatusItems(refresh); - - holder.removeAllViews(); - - for (StatusItem row : l) { - viewAdapter.inflateStatus(row); - } - - } - }); - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/InsightPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/InsightPlugin.java deleted file mode 100644 index c72da31fdf..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/InsightPlugin.java +++ /dev/null @@ -1,935 +0,0 @@ -package info.nightscout.androidaps.plugins.PumpInsight; - -import android.content.DialogInterface; -import android.os.SystemClock; -import android.support.v4.app.FragmentActivity; -import android.support.v7.app.AlertDialog; - -import org.json.JSONException; -import org.json.JSONObject; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.text.DecimalFormat; -import java.util.ArrayList; -import java.util.List; - -import info.nightscout.androidaps.BuildConfig; -import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.data.DetailedBolusInfo; -import info.nightscout.androidaps.data.Profile; -import info.nightscout.androidaps.data.PumpEnactResult; -import info.nightscout.androidaps.db.ExtendedBolus; -import info.nightscout.androidaps.db.Source; -import info.nightscout.androidaps.db.TemporaryBasal; -import info.nightscout.androidaps.interfaces.Constraint; -import info.nightscout.androidaps.interfaces.ConstraintsInterface; -import info.nightscout.androidaps.interfaces.PluginBase; -import info.nightscout.androidaps.interfaces.PluginDescription; -import info.nightscout.androidaps.interfaces.PluginType; -import info.nightscout.androidaps.interfaces.PumpDescription; -import info.nightscout.androidaps.interfaces.PumpInterface; -import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment; -import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions; -import info.nightscout.androidaps.plugins.NSClientInternal.NSUpload; -import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; -import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; -import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress; -import info.nightscout.androidaps.plugins.Overview.notifications.Notification; -import info.nightscout.androidaps.plugins.PumpCommon.defs.PumpType; -import info.nightscout.androidaps.plugins.PumpInsight.connector.CancelBolusSilentlyTaskRunner; -import info.nightscout.androidaps.plugins.PumpInsight.connector.CancelTBRSilentlyTaskRunner; -import info.nightscout.androidaps.plugins.PumpInsight.connector.Connector; -import info.nightscout.androidaps.plugins.PumpInsight.connector.SetTBRTaskRunner; -import info.nightscout.androidaps.plugins.PumpInsight.connector.StatusTaskRunner; -import info.nightscout.androidaps.plugins.PumpInsight.connector.WriteBasalProfileTaskRunner; -import info.nightscout.androidaps.plugins.PumpInsight.events.EventInsightCallback; -import info.nightscout.androidaps.plugins.PumpInsight.events.EventInsightUpdateGui; -import info.nightscout.androidaps.plugins.PumpInsight.history.HistoryReceiver; -import info.nightscout.androidaps.plugins.PumpInsight.history.LiveHistory; -import info.nightscout.androidaps.plugins.PumpInsight.utils.Helpers; -import info.nightscout.androidaps.plugins.PumpInsight.utils.StatusItem; -import info.nightscout.androidaps.plugins.Treatments.Treatment; -import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.SP; -import sugar.free.sightparser.applayer.descriptors.ActiveBolus; -import sugar.free.sightparser.applayer.descriptors.ActiveBolusType; -import sugar.free.sightparser.applayer.descriptors.MessagePriority; -import sugar.free.sightparser.applayer.descriptors.PumpStatus; -import sugar.free.sightparser.applayer.descriptors.configuration_blocks.BRProfileBlock; -import sugar.free.sightparser.applayer.messages.AppLayerMessage; -import sugar.free.sightparser.applayer.messages.remote_control.BolusMessage; -import sugar.free.sightparser.applayer.messages.remote_control.CancelBolusMessage; -import sugar.free.sightparser.applayer.messages.remote_control.ExtendedBolusMessage; -import sugar.free.sightparser.applayer.messages.remote_control.StandardBolusMessage; -import sugar.free.sightparser.applayer.messages.status.ActiveBolusesMessage; -import sugar.free.sightparser.handling.SingleMessageTaskRunner; -import sugar.free.sightparser.handling.TaskRunner; -import sugar.free.sightparser.pipeline.Status; - -import static info.nightscout.androidaps.plugins.PumpInsight.history.PumpIdCache.getRecordUniqueID; - - -/** - * Created by jamorham on 23/01/2018. - *

- * Connects to SightRemote app service using SightParser library - *

- * SightRemote and SightParser created by Tebbe Ubben - *

- * Original proof of concept SightProxy by jamorham - */ - -@SuppressWarnings("AccessStaticViaInstance") -public class InsightPlugin extends PluginBase implements PumpInterface, ConstraintsInterface { - private Logger log = LoggerFactory.getLogger(L.PUMP); - - private static volatile InsightPlugin plugin; - - public static InsightPlugin getPlugin() { - if (plugin == null) { - plugin = new InsightPlugin(); - } - return plugin; - } - - private static final long BUSY_WAIT_TIME = 20000; - private static Integer batteryPercent = 0; - private static Integer reservoirInUnits = 0; - private static boolean initialized = false; - private static volatile boolean update_pending = false; - private StatusTaskRunner.Result statusResult; - private long statusResultTime = -1; - private long lastDataTime = 0; - private boolean fauxTBRcancel = true; - private PumpDescription pumpDescription = new PumpDescription(); - private double basalRate = 0; - private Connector connector; - private volatile boolean connector_enabled = false; - private List profileBlocks; - - private InsightPlugin() { - super(new PluginDescription() - .mainType(PluginType.PUMP) - .fragmentClass(InsightFragment.class.getName()) - .pluginName(R.string.insightpump) - .shortName(R.string.insightpump_shortname) - .preferencesId(R.xml.pref_insightpump) - .description(R.string.description_pump_insight) - ); - if (L.isEnabled(L.PUMP)) - log.debug("InsightPlugin instantiated"); - pumpDescription.setPumpDescription(PumpType.AccuChekInsight); - } - - - private static void updateGui() { - update_pending = false; - MainApp.bus().post(new EventInsightUpdateGui()); - } - - private static void pushCallbackEvent(EventInsightCallback e) { - MainApp.bus().post(e); - } - - @Override - protected void onStart() { - if (!connector_enabled) { - synchronized (this) { - if (!connector_enabled) { - if (L.isEnabled(L.PUMP)) - log.debug("Instantiating connector"); - connector_enabled = true; - this.connector = Connector.get(); - this.connector.init(); - } - } - } - super.onStart(); - } - - protected void onStop() { - if (connector_enabled) { - synchronized (this) { - if (connector_enabled) { - if (L.isEnabled(L.PUMP)) - log.debug("Shutting down connector"); - Connector.get().shutdown(); - connector_enabled = false; - } - } - } - } - - @Override - public boolean isFakingTempsByExtendedBoluses() { - return true; - } - - @Override - public PumpEnactResult loadTDDs() { - PumpEnactResult result = new PumpEnactResult(); - result.success = true; - return result; - } - - @Override - public void switchAllowed(ConfigBuilderFragment.PluginViewHolder.PluginSwitcher pluginSwitcher, FragmentActivity context) { - boolean allowHardwarePump = SP.getBoolean("allow_hardware_pump", false); - if (allowHardwarePump || context == null) { - pluginSwitcher.invoke(); - } else { - AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setMessage(R.string.allow_hardware_pump_text) - .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - pluginSwitcher.invoke(); - SP.putBoolean("allow_hardware_pump", true); - log.debug("First time HW pump allowed!"); - } - }) - .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - pluginSwitcher.cancel(); - log.debug("User does not allow switching to HW pump!"); - } - }); - builder.create().show(); - } - } - - @Override - public boolean isInitialized() { - return initialized; - } - - @Override - public boolean isSuspended() { - return !isPumpRunning(); - } - - @Override - public boolean isBusy() { - return false; - } - - @Override - public boolean isConnected() { - return Connector.get().isPumpConnected(); - } - - @Override - public boolean isConnecting() { - return Connector.get().isPumpConnecting(); - } - - @Override - public boolean isHandshakeInProgress() { - return false; - } - - @Override - public void finishHandshaking() { - } - - @Override - public void connect(String reason) { - if (L.isEnabled(L.PUMP)) - log.debug("InsightPlugin::connect()"); - try { - if (!connector.isPumpConnected()) { - if (Helpers.ratelimit("insight-connect-timer", 40)) { - if (L.isEnabled(L.PUMP)) - log.debug("Actually requesting a connect"); - connector.connectToPump(); - } - } else { - if (L.isEnabled(L.PUMP)) - log.debug("Already connected"); - } - } catch (NullPointerException e) { - log.error("Could not sconnect - null pointer: " + e); - } - - // TODO review - if (!Config.NSCLIENT) - NSUpload.uploadDeviceStatus(); - } - - @Override - public void disconnect(String reason) { - if (L.isEnabled(L.PUMP)) - log.debug("InsightPlugin::disconnect()"); - try { - if (!SP.getBoolean("insight_always_connected", false)) { - if (L.isEnabled(L.PUMP)) - log.debug("Requesting disconnect"); - connector.disconnectFromPump(); - } else { - if (L.isEnabled(L.PUMP)) - log.debug("Not disconnecting due to preference"); - } - } catch (NullPointerException e) { - log.error("Could not disconnect - null pointer: " + e); - } - } - - @Override - public void stopConnecting() { - if (L.isEnabled(L.PUMP)) - log.debug("InsightPlugin::stopConnecting()"); - try { - if (isConnecting()) { - if (!SP.getBoolean("insight_always_connected", false)) { - if (L.isEnabled(L.PUMP)) - log.debug("Requesting disconnect"); - connector.disconnectFromPump(); - } else { - if (L.isEnabled(L.PUMP)) - log.debug("Not disconnecting due to preference"); - } - } else { - if (L.isEnabled(L.PUMP)) - log.debug("Not currently trying to connect so not stopping connection"); - } - } catch (NullPointerException e) { - log.error("Could not stop connecting - null pointer: " + e); - } - } - - @Override - public void getPumpStatus() { - if (L.isEnabled(L.PUMP)) - log.debug("getPumpStatus"); - if (Connector.get().isPumpConnected()) { - if (L.isEnabled(L.PUMP)) - log.debug("is connected.. requesting status"); - try { - setStatusResult(fetchTaskRunner(new StatusTaskRunner(connector.getServiceConnector()), StatusTaskRunner.Result.class)); - if (L.isEnabled(L.PUMP)) - log.debug("GOT STATUS RESULT!!! PARTY WOOHOO!!!"); - statusResultTime = Helpers.tsl(); - processStatusResult(); - updateGui(); - connector.requestHistoryReSync(); - connector.requestHistorySync(); - } catch (Exception e) { - log.error("StatusTaskRunner wasn't successful."); - if (connector.getServiceConnector().isConnectedToService() && connector.getServiceConnector().getStatus() != Status.CONNECTED) { - if (Helpers.ratelimit("insight-reconnect", 2)) { - Connector.connectToPump(); - updateGui(); - } - } - } - } else { - if (L.isEnabled(L.PUMP)) - log.debug("not connected.. not requesting status"); - } - } - - public void setStatusResult(StatusTaskRunner.Result result) { - this.statusResult = result; - this.pumpDescription.basalMinimumRate = result.minimumBasalAmount; - this.pumpDescription.basalMaximumRate = result.maximumBasalAmount; - } - - @Override - public PumpEnactResult setNewBasalProfile(Profile profile) { - PumpEnactResult result = new PumpEnactResult(); - if (!isInitialized()) { - log.error("setNewBasalProfile not initialized"); - Notification notification = new Notification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED, MainApp.gs(R.string.pumpNotInitializedProfileNotSet), Notification.URGENT); - MainApp.bus().post(new EventNewNotification(notification)); - result.comment = MainApp.gs(R.string.pumpNotInitializedProfileNotSet); - return result; - } - MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED)); - List profileBlocks = new ArrayList<>(); - for (int i = 0; i < profile.getBasalValues().length; i++) { - Profile.BasalValue basalValue = profile.getBasalValues()[i]; - Profile.BasalValue nextValue = null; - if (profile.getBasalValues().length > i + 1) - nextValue = profile.getBasalValues()[i + 1]; - profileBlocks.add(new BRProfileBlock.ProfileBlock((((nextValue != null ? nextValue.timeAsSeconds : 24 * 60 * 60) - basalValue.timeAsSeconds) / 60), Helpers.roundDouble(basalValue.value, 2))); - if (L.isEnabled(L.PUMP)) - log.debug("setNewBasalProfile: " + basalValue.value + " for " + Integer.toString(((nextValue != null ? nextValue.timeAsSeconds : 24 * 60 * 60) - basalValue.timeAsSeconds) / 60)); - } - try { - fetchTaskRunner(new WriteBasalProfileTaskRunner(connector.getServiceConnector(), profileBlocks)); - MainApp.bus().post(new EventDismissNotification(Notification.FAILED_UDPATE_PROFILE)); - Notification notification = new Notification(Notification.PROFILE_SET_OK, MainApp.gs(R.string.profile_set_ok), Notification.INFO, 60); - MainApp.bus().post(new EventNewNotification(notification)); - result.success = true; - result.enacted = true; - result.comment = "OK"; - this.profileBlocks = profileBlocks; - } catch (Exception e) { - Notification notification = new Notification(Notification.FAILED_UDPATE_PROFILE, MainApp.gs(R.string.failedupdatebasalprofile), Notification.URGENT); - MainApp.bus().post(new EventNewNotification(notification)); - result.comment = MainApp.gs(R.string.failedupdatebasalprofile); - } - return result; - } - - @Override - public boolean isThisProfileSet(Profile profile) { - if (!isInitialized() || profileBlocks == null) return true; - if (profile.getBasalValues().length != profileBlocks.size()) return false; - for (int i = 0; i < profileBlocks.size(); i++) { - BRProfileBlock.ProfileBlock profileBlock = profileBlocks.get(i); - Profile.BasalValue basalValue = profile.getBasalValues()[i]; - Profile.BasalValue nextValue = null; - if (profile.getBasalValues().length > i + 1) - nextValue = profile.getBasalValues()[i + 1]; - if (L.isEnabled(L.PUMP)) - log.debug("isThisProfileSet - Comparing block: Pump: " + profileBlock.getAmount() + " for " + profileBlock.getDuration() - + " Profile: " + basalValue.value + " for " + Integer.toString(((nextValue != null ? nextValue.timeAsSeconds : 24 * 60 * 60) - basalValue.timeAsSeconds) / 60)); - if (profileBlock.getDuration() * 60 != (nextValue != null ? nextValue.timeAsSeconds : 24 * 60 * 60) - basalValue.timeAsSeconds) - return false; - //Allow a little imprecision due to rounding errors - if (Math.abs(profileBlock.getAmount() - Helpers.roundDouble(basalValue.value, 2)) >= 0.01D) - return false; - } - return true; - } - - @Override - public long lastDataTime() { - return lastDataTime; - } - - @Override - public double getBaseBasalRate() { - return basalRate; - } - - public String getBaseBasalRateString() { - final DecimalFormat df = new DecimalFormat("#.##"); - return df.format(basalRate); - } - - @Override - public PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo) { - final PumpEnactResult result = new PumpEnactResult(); - result.bolusDelivered = detailedBolusInfo.insulin; - result.carbsDelivered = detailedBolusInfo.carbs; - result.enacted = result.bolusDelivered > 0 || result.carbsDelivered > 0; - result.comment = MainApp.gs(R.string.virtualpump_resultok); - - result.percent = 100; - - int bolusId = 0; - - // is there an insulin component to the treatment? - if (detailedBolusInfo.insulin > 0) { - try { - bolusId = deliverBolus(detailedBolusInfo.insulin); - result.success = true; - detailedBolusInfo.pumpId = getRecordUniqueID(bolusId); - } catch (Exception e) { - return pumpEnactFailure(); - } - } else { - result.success = true; // always true with carb only treatments - } - - if (result.success) { - if (L.isEnabled(L.PUMP)) - log.debug("Success!"); - - Treatment t = new Treatment(); - t.isSMB = detailedBolusInfo.isSMB; - final EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance(); - bolusingEvent.t = t; - bolusingEvent.status = String.format(MainApp.gs(R.string.bolusdelivering), 0F); - bolusingEvent.bolusId = bolusId; - bolusingEvent.percent = 0; - MainApp.bus().post(bolusingEvent); - TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, true); - } else { - if (L.isEnabled(L.PUMP)) - log.debug("Failure to deliver treatment"); - } - - if (L.isEnabled(L.PUMP)) - log.debug("Delivering treatment insulin: " + detailedBolusInfo.insulin + "U carbs: " + detailedBolusInfo.carbs + "g " + result); - - updateGui(); - connector.tryToGetPumpStatusAgain(); - - if (result.success) while (true) { - try { - Thread.sleep(500); - final EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance(); - ActiveBolusesMessage activeBolusesMessage = fetchSingleMessage(new ActiveBolusesMessage(), ActiveBolusesMessage.class); - ActiveBolus activeBolus = null; - if (activeBolusesMessage.getBolus1() != null && activeBolusesMessage.getBolus1().getBolusID() == bolusingEvent.bolusId) - activeBolus = activeBolusesMessage.getBolus1(); - else if (activeBolusesMessage.getBolus2() != null && activeBolusesMessage.getBolus2().getBolusID() == bolusingEvent.bolusId) - activeBolus = activeBolusesMessage.getBolus2(); - else if (activeBolusesMessage.getBolus3() != null && activeBolusesMessage.getBolus3().getBolusID() == bolusingEvent.bolusId) - activeBolus = activeBolusesMessage.getBolus3(); - if (activeBolus == null) break; - else { - int percentBefore = bolusingEvent.percent; - bolusingEvent.percent = (int) (100D / activeBolus.getInitialAmount() * (activeBolus.getInitialAmount() - activeBolus.getLeftoverAmount())); - bolusingEvent.status = String.format(MainApp.gs(R.string.bolusdelivering), activeBolus.getInitialAmount() - activeBolus.getLeftoverAmount()); - if (percentBefore != bolusingEvent.percent) MainApp.bus().post(bolusingEvent); - } - } catch (Exception e) { - break; - } - } - - connector.requestHistorySync(2000); - return result; - } - - @Override - public void stopBolusDelivering() { - CancelBolusMessage cancelBolusMessage = new CancelBolusMessage(); - cancelBolusMessage.setMessagePriority(MessagePriority.HIGHEST); - cancelBolusMessage.setBolusId(EventOverviewBolusProgress.getInstance().bolusId); - try { - fetchSingleMessage(cancelBolusMessage); - } catch (Exception e) { - } - } - - // Temporary Basals - - @Override - public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, Profile profile, boolean enforceNew) { - if (L.isEnabled(L.PUMP)) - log.debug("Set TBR absolute: " + absoluteRate); - if (getBaseBasalRate() == 0) { - if (L.isEnabled(L.PUMP)) - log.debug("Base basal rate appears to be zero!"); - return pumpEnactFailure(); - } - double percent = 100D / getBaseBasalRate() * absoluteRate; - if (L.isEnabled(L.PUMP)) - log.debug("Calculated requested rate: " + absoluteRate + " base rate: " + getBaseBasalRate() + " percentage: " + percent + "%"); - try { - if (percent > 250) { - if (L.isEnabled(L.PUMP)) - log.debug("Calculated rate is above 250%, switching to emulation using extended boluses"); - cancelTempBasal(true); - if (!setExtendedBolus((absoluteRate - getBaseBasalRate()) / 60D * ((double) durationInMinutes), durationInMinutes).success) { - //Fallback to TBR if setting an extended bolus didn't work - if (L.isEnabled(L.PUMP)) - log.debug("Setting an extended bolus didn't work, falling back to normal TBR"); - return setTempBasalPercent((int) percent, durationInMinutes, profile, true); - } - return new PumpEnactResult().success(true).enacted(true).absolute(absoluteRate).duration(durationInMinutes); - } else { - if (L.isEnabled(L.PUMP)) - log.debug("Calculated rate is below or equal to 250%, using normal TBRs"); - cancelExtendedBolus(); - return setTempBasalPercent((int) percent, durationInMinutes, profile, true); - } - } catch (Exception e) { - return pumpEnactFailure(); - } - } - - - @Override - public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, Profile profile, boolean enforceNew) { - if (L.isEnabled(L.PUMP)) - log.debug("Set TBR %"); - - percent = (int) Math.round(((double) percent) / 10d) * 10; - if (percent == 100) { - // This would cause a cancel if a tbr is in progress so treat as a cancel - return cancelTempBasal(false); - } else if (percent > 250) percent = 250; - - try { - fetchTaskRunner(new SetTBRTaskRunner(connector.getServiceConnector(), percent, durationInMinutes)); - final TemporaryBasal tempBasal = new TemporaryBasal() - .date(System.currentTimeMillis()) - .percent(percent) - .duration(durationInMinutes) - .source(Source.USER); - TreatmentsPlugin.getPlugin().addToHistoryTempBasal(tempBasal); - updateGui(); - if (L.isEnabled(L.PUMP)) - log.debug("Set temp basal " + percent + "% for " + durationInMinutes + "m"); - connector.requestHistorySync(5000); - connector.tryToGetPumpStatusAgain(); - return new PumpEnactResult().success(true).enacted(true).percent(percent); - } catch (Exception e) { - return pumpEnactFailure(); - } - } - - - @Override - public PumpEnactResult cancelTempBasal(boolean enforceNew) { - if (L.isEnabled(L.PUMP)) - log.debug("Cancel TBR called"); - - try { - cancelExtendedBolus(); - SystemClock.sleep(1100); // to be sure db records are at least 1 sec off (for NS) - realTBRCancel(); - SystemClock.sleep(1100); // to be sure db records are at least 1 sec off (for NS) - updateGui(); - connector.requestHistorySync(5000); - connector.tryToGetPumpStatusAgain(); - return new PumpEnactResult().success(true).enacted(true).isTempCancel(true); - } catch (Exception e) { - return pumpEnactFailure(); - } - } - - private void realTBRCancel() throws Exception { - if (fetchTaskRunner(new CancelTBRSilentlyTaskRunner(connector.getServiceConnector()), Boolean.class) && TreatmentsPlugin.getPlugin().isTempBasalInProgress()) { - TemporaryBasal tempStop = new TemporaryBasal().date(System.currentTimeMillis()).source(Source.USER); - TreatmentsPlugin.getPlugin().addToHistoryTempBasal(tempStop); - } - } - - - // Extended Boluses - - @Override - public PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes) { - if (L.isEnabled(L.PUMP)) - log.debug("Set Extended bolus " + insulin + " " + durationInMinutes); - try { - ExtendedBolusMessage extendedBolusMessage = new ExtendedBolusMessage(); - extendedBolusMessage.setAmount(insulin); - extendedBolusMessage.setDuration(durationInMinutes); - BolusMessage bolusMessage = fetchSingleMessage(extendedBolusMessage, BolusMessage.class); - final ExtendedBolus extendedBolus = new ExtendedBolus() - .date(System.currentTimeMillis()) - .insulin(insulin) - .durationInMinutes(durationInMinutes) - .source(Source.USER) - .pumpId(getRecordUniqueID(bolusMessage.getBolusId())); - TreatmentsPlugin.getPlugin().addToHistoryExtendedBolus(extendedBolus); - updateGui(); - connector.requestHistorySync(30000); - connector.tryToGetPumpStatusAgain(); - return new PumpEnactResult().success(true).enacted(true).duration(durationInMinutes).bolusDelivered(insulin); - } catch (Exception e) { - return pumpEnactFailure(); - } - } - - @Override - public PumpEnactResult cancelExtendedBolus() { - if (L.isEnabled(L.PUMP)) - log.debug("Cancel Extended bolus called"); - - Integer bolusId = null; - - try { - bolusId = fetchTaskRunner(new CancelBolusSilentlyTaskRunner(connector.getServiceConnector(), ActiveBolusType.EXTENDED), Integer.class); - if (TreatmentsPlugin.getPlugin().isInHistoryExtendedBoluslInProgress()) { - ExtendedBolus exStop = new ExtendedBolus(System.currentTimeMillis()); - exStop.source = Source.USER; - TreatmentsPlugin.getPlugin().addToHistoryExtendedBolus(exStop); - } - if (bolusId != null) connector.requestHistorySync(5000); - connector.tryToGetPumpStatusAgain(); - updateGui(); - return new PumpEnactResult().success(true).enacted(bolusId != null); - } catch (Exception e) { - return pumpEnactFailure(); - } - } - - - private int deliverBolus(double bolusValue) throws Exception { - if (L.isEnabled(L.PUMP)) - log.debug("DeliverBolus: " + bolusValue); - - final StandardBolusMessage message = new StandardBolusMessage(); - message.setAmount(bolusValue); - - return fetchSingleMessage(message, BolusMessage.class).getBolusId(); - } - - @Override - public JSONObject getJSONStatus(Profile profile, String profileName) { - long now = System.currentTimeMillis(); - if (Helpers.msSince(connector.getLastContactTime()) > (60 * 60 * 1000)) { - if (L.isEnabled(L.PUMP)) - log.debug("getJSONStatus not returning as data likely stale"); - return null; - } - - final JSONObject pump = new JSONObject(); - final JSONObject battery = new JSONObject(); - final JSONObject status = new JSONObject(); - final JSONObject extended = new JSONObject(); - try { - battery.put("percent", batteryPercent); - status.put("status", isSuspended() ? "suspended" : "normal"); - status.put("timestamp", DateUtil.toISOString(connector.getLastContactTime())); - extended.put("Version", BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION); - try { - extended.put("ActiveProfile", ProfileFunctions.getInstance().getProfileName()); - } catch (Exception e) { - } - TemporaryBasal tb = TreatmentsPlugin.getPlugin().getTempBasalFromHistory(now); - if (tb != null) { - extended.put("TempBasalAbsoluteRate", tb.tempBasalConvertedToAbsolute(now, profile)); - extended.put("TempBasalStart", DateUtil.dateAndTimeString(tb.date)); - extended.put("TempBasalRemaining", tb.getPlannedRemainingMinutes()); - } - ExtendedBolus eb = TreatmentsPlugin.getPlugin().getExtendedBolusFromHistory(now); - if (eb != null) { - extended.put("ExtendedBolusAbsoluteRate", eb.absoluteRate()); - extended.put("ExtendedBolusStart", DateUtil.dateAndTimeString(eb.date)); - extended.put("ExtendedBolusRemaining", eb.getPlannedRemainingMinutes()); - } - extended.put("BaseBasalRate", getBaseBasalRate()); - status.put("timestamp", DateUtil.toISOString(now)); - - pump.put("battery", battery); - pump.put("status", status); - pump.put("extended", extended); - pump.put("reservoir", reservoirInUnits); - pump.put("clock", DateUtil.toISOString(now)); - } catch (JSONException e) { - log.error("Unhandled exception", e); - } - return pump; - } - - @Override - public String deviceID() { - return "InsightPump"; - } - - @Override - public PumpDescription getPumpDescription() { - return pumpDescription; - } - - @Override - public String shortStatus(boolean veryShort) { - String msg = gs(R.string.insightpump_shortname) + " Batt: " + batteryPercent + " Reserv: " + reservoirInUnits + " Basal: " + basalRate; - if (LiveHistory.getStatus().length() > 0) { - msg += LiveHistory.getStatus(); - } - return msg; - } - - private void processStatusResult() { - if (statusResult != null) { - batteryPercent = statusResult.battery; - reservoirInUnits = (int) statusResult.cartridge; - basalRate = statusResult.baseBasalRate; - profileBlocks = statusResult.basalProfile; - initialized = true; // basic communication test - } - } - - private String gs(int id) { - return MainApp.gs(id); - } - - private boolean isPumpRunning() { - if (statusResult == null) return true; // assume running if we have no information - return statusResult.pumpStatus == PumpStatus.STARTED; - } - - List getStatusItems(boolean refresh) { - final List l = new ArrayList<>(); - - // Todo last contact time - - l.add(new StatusItem(gs(R.string.status_no_colon), connector.getLastStatusMessage())); - l.add(new StatusItem(gs(R.string.changed), connector.getNiceLastStatusTime())); - - boolean pumpRunning; - // also check time since received - if (statusResult != null) { - - pumpRunning = isPumpRunning(); - if (pumpRunning) { - l.add(new StatusItem(gs(R.string.pump_basebasalrate_label), getBaseBasalRateString() + "U")); - } else { - l.add(new StatusItem(gs(R.string.combo_warning), gs(R.string.pump_stopped_uppercase), StatusItem.Highlight.CRITICAL)); - } - } - - final long offset_ms = Helpers.msSince(statusResultTime); - final long offset_minutes = offset_ms / 60000; - - if (statusResult != null) { - l.add(new StatusItem(gs(R.string.status_updated), Helpers.niceTimeScalar(Helpers.msSince(statusResultTime)) + " " + gs(R.string.ago))); - l.add(new StatusItem(gs(R.string.pump_battery_label), batteryPercent + "%", batteryPercent < 100 ? - (batteryPercent < 90 ? - (batteryPercent < 70 ? - (StatusItem.Highlight.BAD) : StatusItem.Highlight.NOTICE) : StatusItem.Highlight.NORMAL) : StatusItem.Highlight.GOOD)); - l.add(new StatusItem(gs(R.string.pump_reservoir_label), reservoirInUnits + "U")); - try { - if (statusResult.tbrAmount != 100) { - l.add(new StatusItem(gs(R.string.insight_active_tbr), statusResult.tbrAmount + "% " + gs(R.string.with) + " " - + Helpers.qs(statusResult.tbrLeftoverDuration - offset_minutes, 0) - + " " + gs(R.string.insight_min_left), StatusItem.Highlight.NOTICE)); - } - } catch (NullPointerException e) { - // currentTBRMessage may be null - } - - } - - if (TreatmentsPlugin.getPlugin().isTempBasalInProgress()) { - try { - l.add(new StatusItem(gs(R.string.pump_tempbasal_label), TreatmentsPlugin.getPlugin().getTempBasalFromHistory(System.currentTimeMillis()).toStringFull())); - } catch (NullPointerException e) { - // - } - } - - if (statusResult != null) { - try { - statusActiveBolus(statusResult.activeBolus1, offset_minutes, l); - statusActiveBolus(statusResult.activeBolus2, offset_minutes, l); - statusActiveBolus(statusResult.activeBolus3, offset_minutes, l); - } catch (NullPointerException e) { - // getActiveBolusesMessage() may be null - } - } - - if (TreatmentsPlugin.getPlugin().isInHistoryExtendedBoluslInProgress()) { - try { - - l.add(new StatusItem(gs(R.string.virtualpump_extendedbolus_label), TreatmentsPlugin.getPlugin().getExtendedBolusFromHistory(System.currentTimeMillis()).toString())); - } catch (NullPointerException e) { - // - } - } - - l.add(new StatusItem(gs(R.string.log_book), HistoryReceiver.getStatusString())); - - if (LiveHistory.getStatus().length() > 0) { - l.add(new StatusItem(gs(R.string.insight_last_completed_action), LiveHistory.getStatus())); - } - - final String keep_alive_status = Connector.getKeepAliveString(); - if (keep_alive_status != null) { - l.add(new StatusItem(gs(R.string.insight_keep_alive_status), keep_alive_status)); - } - - final List status_statistics = connector.getStatusStatistics(); - if (status_statistics.size() > 0) { - l.addAll(status_statistics); - } - - if (Helpers.ratelimit("insight-status-ui-refresh", 10)) { - connector.tryToGetPumpStatusAgain(); - } - connector.requestHistorySync(); - if (refresh) scheduleGUIUpdate(); - - return l; - } - - private synchronized void scheduleGUIUpdate() { - if (!update_pending && connector.uiFresh()) { - update_pending = true; - Helpers.runOnUiThreadDelayed(new Runnable() { - @Override - public void run() { - updateGui(); - } - }, 1000); - } - } - - private void statusActiveBolus(ActiveBolus activeBolus, long offset_mins, List l) { - if (activeBolus == null) return; - switch (activeBolus.getBolusType()) { - - case STANDARD: - l.add(new StatusItem(activeBolus.getBolusType() + " " + gs(R.string.bolus), activeBolus.getInitialAmount() + "U", StatusItem.Highlight.NOTICE)); - break; - case EXTENDED: - l.add(new StatusItem(activeBolus.getBolusType() + " " + gs(R.string.bolus), activeBolus.getInitialAmount() + "U " + gs(R.string.insight_total_with) + " " - + activeBolus.getLeftoverAmount() + "U " + gs(R.string.insight_remaining_over) + " " + (activeBolus.getDuration() - offset_mins) + " " + gs(R.string.insight_min), StatusItem.Highlight.NOTICE)); - break; - case MULTIWAVE: - l.add(new StatusItem(activeBolus.getBolusType() + " " + gs(R.string.bolus), activeBolus.getInitialAmount() + "U " + gs(R.string.insight_upfront_with) + " " - + activeBolus.getLeftoverAmount() + "U " + gs(R.string.insight_remaining_over) + " " + (activeBolus.getDuration() - offset_mins) + " " + gs(R.string.insight_min), StatusItem.Highlight.NOTICE)); - - break; - default: - log.error("ERROR: unknown bolus type! " + activeBolus.getBolusType()); - } - } - - private void fetchTaskRunner(TaskRunner taskRunner) throws Exception { - fetchTaskRunner(taskRunner, Object.class); - } - - private void fetchSingleMessage(AppLayerMessage message) throws Exception { - fetchSingleMessage(message, AppLayerMessage.class); - } - - private T fetchTaskRunner(TaskRunner taskRunner, Class resultType) throws Exception { - try { - T result = (T) taskRunner.fetchAndWaitUsingLatch(BUSY_WAIT_TIME); - lastDataTime = System.currentTimeMillis(); - return result; - } catch (Exception e) { - log.error("Error while fetching " + taskRunner.getClass().getSimpleName() + ": " + e.getClass().getSimpleName()); - throw e; - } - } - - private T fetchSingleMessage(AppLayerMessage message, Class resultType) throws Exception { - try { - T result = (T) new SingleMessageTaskRunner(connector.getServiceConnector(), message).fetchAndWaitUsingLatch(BUSY_WAIT_TIME); - lastDataTime = System.currentTimeMillis(); - return result; - } catch (Exception e) { - log.error("Error while fetching " + message.getClass().getSimpleName() + ": " + e.getClass().getSimpleName()); - throw e; - } - } - - - private PumpEnactResult pumpEnactFailure() { - return new PumpEnactResult().success(false).enacted(false); - } - - // Constraints - - @Override - public Constraint applyBasalPercentConstraints(Constraint percentRate, Profile profile) { - percentRate.setIfGreater(0, String.format(MainApp.gs(R.string.limitingpercentrate), 0, MainApp.gs(R.string.itmustbepositivevalue)), this); - percentRate.setIfSmaller(getPumpDescription().maxTempPercent, String.format(MainApp.gs(R.string.limitingpercentrate), getPumpDescription().maxTempPercent, MainApp.gs(R.string.pumplimit)), this); - - return percentRate; - } - - @Override - public Constraint applyBolusConstraints(Constraint insulin) { - if (statusResult != null) { - insulin.setIfSmaller(statusResult.maximumBolusAmount, String.format(MainApp.gs(R.string.limitingbolus), statusResult.maximumBolusAmount, MainApp.gs(R.string.pumplimit)), this); - if (insulin.value() < statusResult.minimumBolusAmount) { - - //TODO: Add function to Constraints or use different approach - // This only works if the interface of the InsightPlugin is called last. - // If not, another contraint could theoretically set the value between 0 and minimumBolusAmount - - insulin.set(0d, String.format(MainApp.gs(R.string.limitingbolus), statusResult.minimumBolusAmount, MainApp.gs(R.string.pumplimit)), this); - } - } - return insulin; - } - -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/connector/CancelBolusSilentlyTaskRunner.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/connector/CancelBolusSilentlyTaskRunner.java deleted file mode 100644 index 7b3108602e..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/connector/CancelBolusSilentlyTaskRunner.java +++ /dev/null @@ -1,66 +0,0 @@ -package info.nightscout.androidaps.plugins.PumpInsight.connector; - -import sugar.free.sightparser.applayer.descriptors.ActiveBolusType; -import sugar.free.sightparser.applayer.descriptors.MessagePriority; -import sugar.free.sightparser.applayer.descriptors.alerts.Warning38BolusCancelled; -import sugar.free.sightparser.applayer.messages.AppLayerMessage; -import sugar.free.sightparser.applayer.messages.remote_control.CancelBolusMessage; -import sugar.free.sightparser.applayer.messages.remote_control.DismissAlertMessage; -import sugar.free.sightparser.applayer.messages.status.ActiveAlertMessage; -import sugar.free.sightparser.applayer.messages.status.ActiveBolusesMessage; -import sugar.free.sightparser.handling.SightServiceConnector; -import sugar.free.sightparser.handling.TaskRunner; - -// by Tebbe Ubben - -public class CancelBolusSilentlyTaskRunner extends TaskRunner { - - private ActiveBolusType bolusType; - private long cancelledAt; - private int bolusId; - - public CancelBolusSilentlyTaskRunner(SightServiceConnector serviceConnector, ActiveBolusType bolusType) { - super(serviceConnector); - this.bolusType = bolusType; - } - - @Override - protected AppLayerMessage run(AppLayerMessage message) throws Exception { - if (message == null) return new ActiveBolusesMessage(); - else if (message instanceof ActiveBolusesMessage) { - ActiveBolusesMessage bolusesMessage = (ActiveBolusesMessage) message; - CancelBolusMessage cancelBolusMessage = new CancelBolusMessage(); - if (bolusesMessage.getBolus1().getBolusType() == bolusType) - bolusId = bolusesMessage.getBolus1().getBolusID(); - else if (bolusesMessage.getBolus2().getBolusType() == bolusType) - bolusId = bolusesMessage.getBolus2().getBolusID(); - else if (bolusesMessage.getBolus3().getBolusType() == bolusType) - bolusId = bolusesMessage.getBolus3().getBolusID(); - else finish(null); - cancelBolusMessage.setBolusId(bolusId); - return cancelBolusMessage; - } else if (message instanceof CancelBolusMessage) { - cancelledAt = System.currentTimeMillis(); - ActiveAlertMessage activeAlertMessage = new ActiveAlertMessage(); - activeAlertMessage.setMessagePriority(MessagePriority.HIGHER); - return activeAlertMessage; - } else if (message instanceof ActiveAlertMessage) { - ActiveAlertMessage activeAlertMessage = (ActiveAlertMessage) message; - if (activeAlertMessage.getAlert() == null) { - if (System.currentTimeMillis() - cancelledAt >= 10000) finish(bolusId); - else { - ActiveAlertMessage activeAlertMessage2 = new ActiveAlertMessage(); - activeAlertMessage2.setMessagePriority(MessagePriority.HIGHER); - return activeAlertMessage2; - } - } else if (!(activeAlertMessage.getAlert() instanceof Warning38BolusCancelled)) finish(bolusId); - else { - DismissAlertMessage dismissAlertMessage = new DismissAlertMessage(); - dismissAlertMessage.setAlertID(activeAlertMessage.getAlertID()); - dismissAlertMessage.setMessagePriority(MessagePriority.HIGHER); - return dismissAlertMessage; - } - } else if (message instanceof DismissAlertMessage) finish(bolusId); - return null; - } -} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/connector/CancelTBRSilentlyTaskRunner.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/connector/CancelTBRSilentlyTaskRunner.java deleted file mode 100644 index 9a3068aef9..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/connector/CancelTBRSilentlyTaskRunner.java +++ /dev/null @@ -1,50 +0,0 @@ -package info.nightscout.androidaps.plugins.PumpInsight.connector; - -import sugar.free.sightparser.applayer.descriptors.MessagePriority; -import sugar.free.sightparser.applayer.descriptors.alerts.Warning36TBRCancelled; -import sugar.free.sightparser.applayer.messages.AppLayerMessage; -import sugar.free.sightparser.applayer.messages.remote_control.CancelTBRMessage; -import sugar.free.sightparser.applayer.messages.remote_control.DismissAlertMessage; -import sugar.free.sightparser.applayer.messages.status.ActiveAlertMessage; -import sugar.free.sightparser.applayer.messages.status.CurrentTBRMessage; -import sugar.free.sightparser.handling.SightServiceConnector; -import sugar.free.sightparser.handling.TaskRunner; - -public class CancelTBRSilentlyTaskRunner extends TaskRunner { - - private long cancelledAt; - - public CancelTBRSilentlyTaskRunner(SightServiceConnector serviceConnector) { - super(serviceConnector); - } - - @Override - protected AppLayerMessage run(AppLayerMessage message) throws Exception { - if (message == null) return new CurrentTBRMessage(); - else if (message instanceof CurrentTBRMessage) { - if (((CurrentTBRMessage) message).getPercentage() == 100) finish(false); - else return new CancelTBRMessage(); - } else if (message instanceof CancelTBRMessage) { - ActiveAlertMessage activeAlertMessage = new ActiveAlertMessage(); - activeAlertMessage.setMessagePriority(MessagePriority.HIGHER); - return activeAlertMessage; - } else if (message instanceof ActiveAlertMessage) { - ActiveAlertMessage activeAlertMessage = (ActiveAlertMessage) message; - if (activeAlertMessage.getAlert() == null) { - if (System.currentTimeMillis() - cancelledAt >= 10000) finish(true); - else { - ActiveAlertMessage activeAlertMessage2 = new ActiveAlertMessage(); - activeAlertMessage2.setMessagePriority(MessagePriority.HIGHER); - return activeAlertMessage2; - } - } else if (!(activeAlertMessage.getAlert() instanceof Warning36TBRCancelled)) finish(true); - else { - DismissAlertMessage dismissAlertMessage = new DismissAlertMessage(); - dismissAlertMessage.setAlertID(activeAlertMessage.getAlertID()); - dismissAlertMessage.setMessagePriority(MessagePriority.HIGHER); - return dismissAlertMessage; - } - } else if (message instanceof DismissAlertMessage) finish(true); - return null; - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/connector/Connector.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/connector/Connector.java deleted file mode 100644 index fdc2aff0a6..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/connector/Connector.java +++ /dev/null @@ -1,574 +0,0 @@ -package info.nightscout.androidaps.plugins.PumpInsight.connector; - -import android.content.Intent; -import android.os.PowerManager; - -import com.squareup.otto.Subscribe; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.Formatter; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.events.EventFeatureRunning; -import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.PumpInsight.events.EventInsightUpdateGui; -import info.nightscout.androidaps.plugins.PumpInsight.history.HistoryReceiver; -import info.nightscout.androidaps.plugins.PumpInsight.history.LiveHistory; -import info.nightscout.androidaps.plugins.PumpInsight.utils.Helpers; -import info.nightscout.androidaps.plugins.PumpInsight.utils.StatusItem; -import info.nightscout.utils.SP; -import sugar.free.sightparser.handling.ServiceConnectionCallback; -import sugar.free.sightparser.handling.SightServiceConnector; -import sugar.free.sightparser.handling.StatusCallback; -import sugar.free.sightparser.pipeline.Status; - -import static sugar.free.sightparser.handling.HistoryBroadcast.ACTION_START_RESYNC; -import static sugar.free.sightparser.handling.HistoryBroadcast.ACTION_START_SYNC; -import static sugar.free.sightparser.handling.SightService.COMPATIBILITY_VERSION; - -/** - * Created by jamorham on 23/01/2018. - *

- * Connects to SightRemote app service using SightParser library - *

- * SightRemote and SightParser created by Tebbe Ubben - *

- * Original proof of concept SightProxy by jamorham - */ - -public class Connector { - private static Logger log = LoggerFactory.getLogger(L.PUMP); - - // TODO connection statistics - - private static final String TAG = "InsightConnector"; - private static final String COMPANION_APP_PACKAGE = "sugar.free.sightremote"; - private final static long FRESH_MS = 70000; - private static final Map statistics = new HashMap<>(); - private static volatile Connector instance; - private static volatile HistoryReceiver historyReceiver; - private static volatile long stayConnectedTill = -1; - private static volatile long stayConnectedTime = 0; - private static volatile boolean disconnect_thread_running = false; - private volatile SightServiceConnector serviceConnector; - private volatile Status lastStatus = null; - private String compatabilityMessage = null; - private volatile long lastStatusTime = -1; - private volatile long lastContactTime = -1; - private boolean companionAppInstalled = false; - private int serviceReconnects = 0; - private StatusCallback statusCallback = new StatusCallback() { - @Override - public synchronized void onStatusChange(Status status, long statusTime, long waitTime) { - - if ((status != lastStatus) || (Helpers.msSince(lastStatusTime) > 2000)) { - if (L.isEnabled(L.PUMP)) - log.debug("Status change: " + status); - - updateStatusStatistics(lastStatus, lastStatusTime); - lastStatus = status; - lastStatusTime = Helpers.tsl(); - - if (status == Status.CONNECTED) { - lastContactTime = lastStatusTime; - extendKeepAliveIfActive(); - } - - MainApp.bus().post(new EventInsightUpdateGui()); - } else { - if (L.isEnabled(L.PUMP)) - log.debug("Same status as before: " + status); - } - } - - }; - private ServiceConnectionCallback connectionCallback = new ServiceConnectionCallback() { - - @Override - public synchronized void onServiceConnected() { - if (L.isEnabled(L.PUMP)) - log.debug("On service connected"); - try { - final String remoteVersion = serviceConnector.getRemoteVersion(); - if (remoteVersion.equals(COMPATIBILITY_VERSION)) { - serviceConnector.connect(); - } else { - log.error("PROTOCOL VERSION MISMATCH! local: " + COMPATIBILITY_VERSION + " remote: " + remoteVersion); - statusCallback.onStatusChange(Status.INCOMPATIBLE, 0, 0); - compatabilityMessage = MainApp.gs(R.string.insight_incompatible_compantion_app_we_need_version) + " " + getLocalVersion(); - serviceConnector.disconnectFromService(); - - } - } catch (NullPointerException e) { - log.error("ERROR: null pointer when trying to connect to pump"); - } - statusCallback.onStatusChange(safeGetStatus(), 0, 0); - } - - @Override - public synchronized void onServiceDisconnected() { - if (L.isEnabled(L.PUMP)) - log.debug("Disconnected from service"); - if (Helpers.ratelimit("insight-automatic-reconnect", 30)) { - if (L.isEnabled(L.PUMP)) - log.debug("Scheduling automatic service reconnection"); - Helpers.runOnUiThreadDelayed(new Runnable() { - @Override - public void run() { - init(); - } - }, 20000); - } - } - }; - - private Connector() { - initializeHistoryReceiver(); - MainApp.bus().register(this); - } - - public static Connector get() { - if (instance == null) { - init_instance(); - } - return instance; - } - - private synchronized static void init_instance() { - if (instance == null) { - instance = new Connector(); - } - } - - private static boolean isCompanionAppInstalled() { - return Helpers.checkPackageExists(MainApp.instance(), TAG, COMPANION_APP_PACKAGE); - } - - public static void connectToPump() { - connectToPump(0); - } - - public synchronized static void connectToPump(long keep_alive) { - if (L.isEnabled(L.PUMP)) - log.debug("Attempting to connect to pump."); - if (keep_alive > 0 && Helpers.tsl() + keep_alive > stayConnectedTill) { - stayConnectedTime = keep_alive; - stayConnectedTill = Helpers.tsl() + keep_alive; - if (L.isEnabled(L.PUMP)) - log.debug("Staying connected till: " + Helpers.dateTimeText(stayConnectedTill)); - delayedDisconnectionThread(); - } - get().getServiceConnector().connect(); - } - - public static void disconnectFromPump() { - if (Helpers.tsl() >= stayConnectedTill) { - if (L.isEnabled(L.PUMP)) - log.debug("Requesting real pump disconnect"); - get().getServiceConnector().disconnect(); - } else { - if (L.isEnabled(L.PUMP)) - log.debug("Cannot disconnect as due to keep alive till: " + Helpers.dateTimeText(stayConnectedTill)); - // TODO set a disconnection timer? - } - } - - static String getLocalVersion() { - return COMPATIBILITY_VERSION; - } - - private static String statusToString(Status status) { - switch (status) { - - case EXCHANGING_KEYS: - return MainApp.gs(R.string.connecting).toUpperCase(); - case WAITING_FOR_CODE_CONFIRMATION: - return MainApp.gs(R.string.insight_waiting_for_code).toUpperCase(); - case CODE_REJECTED: - return MainApp.gs(R.string.insight_code_rejected).toUpperCase(); - case APP_BINDING: - return MainApp.gs(R.string.insight_app_binding).toUpperCase(); - case CONNECTING: - return MainApp.gs(R.string.connecting).toUpperCase(); - case CONNECTED: - return MainApp.gs(R.string.connected).toUpperCase(); - case DISCONNECTED: - return MainApp.gs(R.string.disconnected).toUpperCase(); - case NOT_AUTHORIZED: - return MainApp.gs(R.string.insight_not_authorized).toUpperCase(); - case INCOMPATIBLE: - return MainApp.gs(R.string.insight_incompatible).toUpperCase(); - - default: - return status.toString(); - } - } - - private static synchronized void extendKeepAliveIfActive() { - if (keepAliveActive()) { - if (Helpers.ratelimit("extend-insight-keepalive", 10)) { - stayConnectedTill = Helpers.tsl() + stayConnectedTime; - if (L.isEnabled(L.PUMP)) - log.debug("Keep-alive extended until: " + Helpers.dateTimeText(stayConnectedTill)); - } - } - } - - private static boolean keepAliveActive() { - return Helpers.tsl() <= stayConnectedTill; - } - - public static String getKeepAliveString() { - if (keepAliveActive()) { - return MainApp.gs(R.string.insight_keepalive_format_string, - stayConnectedTime / 1000, Helpers.hourMinuteSecondString(stayConnectedTill)); - - } else { - return null; - } - } - - private static synchronized void delayedDisconnectionThread() { - if (keepAliveActive()) { - if (!disconnect_thread_running) { - disconnect_thread_running = true; - new Thread(new Runnable() { - @Override - public void run() { - final PowerManager.WakeLock wl = Helpers.getWakeLock("insight-disconnection-timer", 600000); - try { - while (disconnect_thread_running && keepAliveActive()) { - if (Helpers.ratelimit("insight-expiry-notice", 5)) { - if (L.isEnabled(L.PUMP)) - log.debug("Staying connected thread expires: " + Helpers.dateTimeText(stayConnectedTill)); - } - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - // - } - } - - if (disconnect_thread_running) { - if (L.isEnabled(L.PUMP)) - log.debug("Sending the real delayed disconnect"); - get().getServiceConnector().disconnect(); - } else { - if (L.isEnabled(L.PUMP)) - log.debug("Disconnect thread already terminating"); - } - } finally { - Helpers.releaseWakeLock(wl); - disconnect_thread_running = false; - } - } - }).start(); - } else { - if (L.isEnabled(L.PUMP)) - log.debug("Disconnect thread already running"); - } - } - } - - private static long percentage(long t, long total) { - return (long) (Helpers.roundDouble(((double) t * 100) / total, 0)); - } - - public synchronized void shutdown() { - if (instance != null) { - if (L.isEnabled(L.PUMP)) - log.debug("Attempting to shut down connector"); - try { - disconnect_thread_running = false; - try { - instance.serviceConnector.setConnectionCallback(null); - } catch (Exception e) { - // - } - try { - instance.serviceConnector.removeStatusCallback(statusCallback); - } catch (Exception e) { - // - } - try { - instance.serviceConnector.disconnect(); - } catch (Exception e) { - log.error("Exception disconnecting: " + e); - } - try { - instance.serviceConnector.disconnectFromService(); - } catch (Exception e) { - log.error("Excpetion disconnecting service: " + e); - } - instance.serviceConnector = null; - instance = null; - } catch (Exception e) { - log.error("Exception shutting down: " + e); - } - } - } - - @SuppressWarnings("AccessStaticViaInstance") - private synchronized void initializeHistoryReceiver() { - if (historyReceiver == null) { - historyReceiver = new HistoryReceiver(); - } - historyReceiver.registerHistoryReceiver(); - } - - public synchronized void init() { - if (L.isEnabled(L.PUMP)) - log.debug("Connector::init()"); - if (serviceConnector == null) { - companionAppInstalled = isCompanionAppInstalled(); - if (companionAppInstalled) { - serviceConnector = new SightServiceConnector(MainApp.instance()); - serviceConnector.removeStatusCallback(statusCallback); - serviceConnector.addStatusCallback(statusCallback); - serviceConnector.setConnectionCallback(connectionCallback); - serviceConnector.connectToService(); - if (L.isEnabled(L.PUMP)) - log.debug("Trying to connect"); - } else { - if (L.isEnabled(L.PUMP)) - log.debug("Not trying init due to missing companion app"); - } - } else { - if (!serviceConnector.isConnectedToService()) { - if (serviceReconnects > 0) { - serviceConnector = null; - init(); - } else { - if (L.isEnabled(L.PUMP)) - log.debug("Trying to reconnect to service (" + serviceReconnects + ")"); - serviceConnector.connectToService(); - serviceReconnects++; - } - } else { - serviceReconnects = 0; // everything ok - } - } - } - - public SightServiceConnector getServiceConnector() { - init(); - return serviceConnector; - } - - public String getCurrent() { - init(); - return safeGetStatus().toString(); - } - - public Status safeGetStatus() { - try { - if (isConnected()) return serviceConnector.getStatus(); - return Status.DISCONNECTED; - } catch (IllegalArgumentException e) { - return Status.INCOMPATIBLE; - } - } - - public Status getLastStatus() { - return lastStatus; - } - - public boolean isConnected() { - return serviceConnector != null && serviceConnector.isConnectedToService(); - } - - public boolean isPumpConnected() { - return isConnected() && getLastStatus() == Status.CONNECTED; - } - - public boolean isPumpConnecting() { - return isConnected() && getLastStatus() == Status.CONNECTING; - } - - public long getLastContactTime() { - return lastContactTime; - } - - public String getLastStatusMessage() { - - if (!companionAppInstalled) { - return MainApp.gs(R.string.insight_companion_app_not_installed); - } - - if (!isConnected()) { - if (L.isEnabled(L.PUMP)) - log.debug("Not connected to companion"); - if (Helpers.ratelimit("insight-app-not-connected", 5)) { - init(); - } - - if ((lastStatus == null) || (lastStatus != Status.INCOMPATIBLE)) { - if (compatabilityMessage != null) { - // if disconnected but previous state was incompatible - return compatabilityMessage; - } else { - return MainApp.gs(R.string.insight_not_connected_to_companion_app); - } - } - } - - if (lastStatus == null) { - return MainApp.gs(R.string.insight_unknown); - } - - switch (lastStatus) { - case CONNECTED: - if (Helpers.msSince(lastStatusTime) > (60 * 10 * 1000)) { - tryToGetPumpStatusAgain(); - } - break; - case INCOMPATIBLE: - return statusToString(lastStatus) + " " + MainApp.gs(R.string.insight_needs) + " " + getLocalVersion(); - } - return statusToString(lastStatus); - } - - public String getNiceLastStatusTime() { - if (lastStatusTime < 1) { - return MainApp.gs(R.string.insight_startup_uppercase); - } else { - return Helpers.niceTimeScalar(Helpers.msSince(lastStatusTime)) + " " + MainApp.gs(R.string.ago); - } - } - - public boolean uiFresh() { - // todo check other changes - - if (Helpers.msSince(lastStatusTime) < FRESH_MS) { - return true; - } - if (Helpers.msSince(LiveHistory.getStatusTime()) < FRESH_MS) { - return true; - } - return false; - } - - @SuppressWarnings("AccessStaticViaInstance") - public void tryToGetPumpStatusAgain() { - if (Helpers.ratelimit("insight-retry-status-request", 5)) { - try { - ConfigBuilderPlugin.getPlugin().getCommandQueue().readStatus("Insight. Status missing", null); - } catch (NullPointerException e) { - // - } - } - } - - public void requestHistorySync() { - requestHistorySync(0); - } - - public void requestHistoryReSync() { - requestHistoryReSync(0); - } - - public void requestHistorySync(long delay) { - if (Helpers.ratelimit("insight-history-sync-request", 10)) { - final Intent intent = new Intent(ACTION_START_SYNC); - sendBroadcastToCompanion(intent, delay); - } - } - - public void requestHistoryReSync(long delay) { - if (Helpers.ratelimit("insight-history-resync-request", 300)) { - final Intent intent = new Intent(ACTION_START_RESYNC); - sendBroadcastToCompanion(intent, delay); - } - } - - private void sendBroadcastToCompanion(final Intent intent, final long delay) { - new Thread(new Runnable() { - @Override - public void run() { - final PowerManager.WakeLock wl = Helpers.getWakeLock("insight-companion-delay", 60000); - intent.setPackage(COMPANION_APP_PACKAGE); - intent.setFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); - try { - if (delay > 0) { - - Thread.sleep(delay); - } - } catch (InterruptedException e) { - // - } finally { - Helpers.releaseWakeLock(wl); - } - MainApp.instance().sendBroadcast(intent); - } - }).start(); - } - - public boolean lastStatusRecent() { - return true; // TODO evaluate whether current - } - - private void updateStatusStatistics(Status last, long since) { - if ((last != null) && (since > 0)) { - Long total = statistics.get(last); - if (total == null) total = 0L; - statistics.put(last, total + Helpers.msSince(since)); - if (L.isEnabled(L.PUMP)) - log.debug("Updated statistics for: " + last + " total: " + Helpers.niceTimeScalar(statistics.get(last))); - // TODO persist data - } - } - - public List getStatusStatistics() { - final List l = new ArrayList<>(); - long total = 0; - for (Map.Entry entry : statistics.entrySet()) { - total += getEntryTime(entry); - } - for (Map.Entry entry : statistics.entrySet()) { - if ((long) entry.getValue() > 1000) { - l.add(new StatusItem(MainApp.gs(R.string.statistics) + " " + Helpers.capitalize(entry.getKey().toString()), - new Formatter().format("%4s %12s", - percentage(getEntryTime(entry), total) + "%", - Helpers.niceTimeScalar(getEntryTime(entry))).toString())); - } - } - return l; - } - - private long getEntryTime(Map.Entry entry) { - return (long) entry.getValue() + (entry.getKey().equals(lastStatus) ? Helpers.msSince(lastStatusTime) : 0); - } - - @Subscribe - public void onStatusEvent(final EventFeatureRunning ev) { - new Thread(new Runnable() { - @Override - public void run() { - if (isConnected()) { - if (SP.getBoolean("insight_preemptive_connect", true)) { - switch (ev.getFeature()) { - case WIZARD: - if (L.isEnabled(L.PUMP)) - log.debug("Wizard feature detected, preconnecting to pump"); - connectToPump(120 * 1000); - break; - case MAIN: - if (L.isEnabled(L.PUMP)) - log.debug("Main feature detected, preconnecting to pump"); - connectToPump(30 * 1000); - break; - } - } - } - } - }).start(); - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/connector/SetTBRTaskRunner.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/connector/SetTBRTaskRunner.java deleted file mode 100644 index f18bb0d487..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/connector/SetTBRTaskRunner.java +++ /dev/null @@ -1,41 +0,0 @@ -package info.nightscout.androidaps.plugins.PumpInsight.connector; - -import sugar.free.sightparser.applayer.messages.AppLayerMessage; -import sugar.free.sightparser.applayer.messages.remote_control.ChangeTBRMessage; -import sugar.free.sightparser.applayer.messages.remote_control.SetTBRMessage; -import sugar.free.sightparser.applayer.messages.status.CurrentTBRMessage; -import sugar.free.sightparser.handling.SightServiceConnector; -import sugar.free.sightparser.handling.TaskRunner; - -// from Tebbe - note this uses 1 minute duration to silently cancel existing TBR - -public class SetTBRTaskRunner extends TaskRunner { - - private int amount; - private int duration; - - public SetTBRTaskRunner(SightServiceConnector serviceConnector, int amount, int duration) { - super(serviceConnector); - this.amount = amount; - this.duration = duration; - } - - @Override - protected AppLayerMessage run(AppLayerMessage message) throws Exception { - if (message == null) return new CurrentTBRMessage(); - else if (message instanceof CurrentTBRMessage) { - if (((CurrentTBRMessage) message).getPercentage() == 100) { - SetTBRMessage setTBRMessage = new SetTBRMessage(); - setTBRMessage.setDuration(duration); - setTBRMessage.setAmount(amount); - return setTBRMessage; - } else { - ChangeTBRMessage changeTBRMessage = new ChangeTBRMessage(); - changeTBRMessage.setDuration(duration); - changeTBRMessage.setAmount(amount); - return changeTBRMessage; - } - } else if (message instanceof SetTBRMessage) finish(amount); - return null; - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/connector/StatusTaskRunner.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/connector/StatusTaskRunner.java deleted file mode 100644 index 1df56be468..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/connector/StatusTaskRunner.java +++ /dev/null @@ -1,140 +0,0 @@ -package info.nightscout.androidaps.plugins.PumpInsight.connector; - -import java.util.List; - -import sugar.free.sightparser.applayer.descriptors.ActiveBolus; -import sugar.free.sightparser.applayer.descriptors.PumpStatus; -import sugar.free.sightparser.applayer.descriptors.configuration_blocks.ActiveProfileBlock; -import sugar.free.sightparser.applayer.descriptors.configuration_blocks.BRProfile1Block; -import sugar.free.sightparser.applayer.descriptors.configuration_blocks.BRProfile2Block; -import sugar.free.sightparser.applayer.descriptors.configuration_blocks.BRProfile3Block; -import sugar.free.sightparser.applayer.descriptors.configuration_blocks.BRProfile4Block; -import sugar.free.sightparser.applayer.descriptors.configuration_blocks.BRProfile5Block; -import sugar.free.sightparser.applayer.descriptors.configuration_blocks.BRProfileBlock; -import sugar.free.sightparser.applayer.descriptors.configuration_blocks.ConfigurationBlock; -import sugar.free.sightparser.applayer.descriptors.configuration_blocks.FactoryMinBRAmountBlock; -import sugar.free.sightparser.applayer.descriptors.configuration_blocks.FactoryMinBolusAmountBlock; -import sugar.free.sightparser.applayer.descriptors.configuration_blocks.MaxBRAmountBlock; -import sugar.free.sightparser.applayer.descriptors.configuration_blocks.MaxBolusAmountBlock; -import sugar.free.sightparser.applayer.messages.AppLayerMessage; -import sugar.free.sightparser.applayer.messages.configuration.ReadConfigurationBlockMessage; -import sugar.free.sightparser.applayer.messages.status.ActiveBolusesMessage; -import sugar.free.sightparser.applayer.messages.status.BatteryAmountMessage; -import sugar.free.sightparser.applayer.messages.status.CartridgeAmountMessage; -import sugar.free.sightparser.applayer.messages.status.CurrentBasalMessage; -import sugar.free.sightparser.applayer.messages.status.CurrentTBRMessage; -import sugar.free.sightparser.applayer.messages.status.PumpStatusMessage; -import sugar.free.sightparser.handling.SightServiceConnector; -import sugar.free.sightparser.handling.TaskRunner; - -/** - * Created by Tebbe Ubben on 12.03.2018. - */ - -public class StatusTaskRunner extends TaskRunner { - - private Result result = new Result(); - - public StatusTaskRunner(SightServiceConnector serviceConnector) { - super(serviceConnector); - } - - @Override - protected AppLayerMessage run(AppLayerMessage message) throws Exception { - if (message == null) return new PumpStatusMessage(); - else if (message instanceof PumpStatusMessage) { - result.pumpStatus = ((PumpStatusMessage) message).getPumpStatus(); - if (result.pumpStatus == PumpStatus.STOPPED) return new BatteryAmountMessage(); - else return new CurrentTBRMessage(); - } else if (message instanceof CurrentTBRMessage) { - CurrentTBRMessage currentTBRMessage = (CurrentTBRMessage) message; - result.tbrAmount = currentTBRMessage.getPercentage(); - result.tbrInitialDuration = currentTBRMessage.getInitialTime(); - result.tbrLeftoverDuration = currentTBRMessage.getLeftoverTime(); - return new ActiveBolusesMessage(); - } else if (message instanceof ActiveBolusesMessage) { - ActiveBolusesMessage activeBolusesMessage = (ActiveBolusesMessage) message; - result.activeBolus1 = activeBolusesMessage.getBolus1(); - result.activeBolus2 = activeBolusesMessage.getBolus2(); - result.activeBolus3 = activeBolusesMessage.getBolus3(); - return new CurrentBasalMessage(); - } else if (message instanceof CurrentBasalMessage) { - result.baseBasalRate = ((CurrentBasalMessage) message).getCurrentBasalAmount(); - return new BatteryAmountMessage(); - } else if (message instanceof BatteryAmountMessage) { - result.battery = ((BatteryAmountMessage) message).getBatteryAmount(); - return new CartridgeAmountMessage(); - } else if (message instanceof CartridgeAmountMessage) { - result.cartridge = ((CartridgeAmountMessage) message).getCartridgeAmount(); - ReadConfigurationBlockMessage readMessage = new ReadConfigurationBlockMessage(); - readMessage.setConfigurationBlockID(ActiveProfileBlock.ID); - return readMessage; - } else if (message instanceof ReadConfigurationBlockMessage) { - ConfigurationBlock configurationBlock = ((ReadConfigurationBlockMessage) message).getConfigurationBlock(); - if (configurationBlock instanceof ActiveProfileBlock) { - ActiveProfileBlock activeProfileBlock = (ActiveProfileBlock) configurationBlock; - ReadConfigurationBlockMessage readMessage = new ReadConfigurationBlockMessage(); - switch (activeProfileBlock.getActiveProfile()) { - case BR_PROFILE_1: - readMessage.setConfigurationBlockID(BRProfile1Block.ID); - break; - case BR_PROFILE_2: - readMessage.setConfigurationBlockID(BRProfile2Block.ID); - break; - case BR_PROFILE_3: - readMessage.setConfigurationBlockID(BRProfile3Block.ID); - break; - case BR_PROFILE_4: - readMessage.setConfigurationBlockID(BRProfile4Block.ID); - break; - case BR_PROFILE_5: - readMessage.setConfigurationBlockID(BRProfile5Block.ID); - break; - } - return readMessage; - } else if (configurationBlock instanceof BRProfileBlock) { - result.basalProfile = ((BRProfileBlock) configurationBlock).getProfileBlocks(); - ReadConfigurationBlockMessage readMessage = new ReadConfigurationBlockMessage(); - readMessage.setConfigurationBlockID(MaxBolusAmountBlock.ID); - return readMessage; - } else if (configurationBlock instanceof MaxBolusAmountBlock) { - result.maximumBolusAmount = ((MaxBolusAmountBlock) configurationBlock).getMaximumAmount(); - ReadConfigurationBlockMessage readMessage = new ReadConfigurationBlockMessage(); - readMessage.setConfigurationBlockID(MaxBRAmountBlock.ID); - return readMessage; - } else if (configurationBlock instanceof MaxBRAmountBlock) { - result.maximumBasalAmount = ((MaxBRAmountBlock) configurationBlock).getMaximumAmount(); - ReadConfigurationBlockMessage readMessage = new ReadConfigurationBlockMessage(); - readMessage.setConfigurationBlockID(FactoryMinBRAmountBlock.ID); - return readMessage; - } else if (configurationBlock instanceof FactoryMinBRAmountBlock) { - result.minimumBasalAmount = ((FactoryMinBRAmountBlock) configurationBlock).getMinimumAmount(); - ReadConfigurationBlockMessage readMessage = new ReadConfigurationBlockMessage(); - readMessage.setConfigurationBlockID(FactoryMinBolusAmountBlock.ID); - return readMessage; - } else if (configurationBlock instanceof FactoryMinBolusAmountBlock) { - result.minimumBolusAmount = ((FactoryMinBolusAmountBlock) configurationBlock).getMinimumAmount(); - finish(result); - } - } - return null; - } - - public static class Result { - public PumpStatus pumpStatus; - public double baseBasalRate; - public int battery; - public double cartridge ; - public int tbrAmount = 100; - public int tbrInitialDuration = 0; - public int tbrLeftoverDuration = 0; - public ActiveBolus activeBolus1; - public ActiveBolus activeBolus2; - public ActiveBolus activeBolus3; - public List basalProfile; - public double maximumBolusAmount; - public double maximumBasalAmount; - public double minimumBolusAmount; - public double minimumBasalAmount; - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/connector/WriteBasalProfileTaskRunner.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/connector/WriteBasalProfileTaskRunner.java deleted file mode 100644 index 7012d200e7..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/connector/WriteBasalProfileTaskRunner.java +++ /dev/null @@ -1,72 +0,0 @@ -package info.nightscout.androidaps.plugins.PumpInsight.connector; - -import java.util.List; - -import sugar.free.sightparser.applayer.descriptors.configuration_blocks.ActiveProfileBlock; -import sugar.free.sightparser.applayer.descriptors.configuration_blocks.BRProfile1Block; -import sugar.free.sightparser.applayer.descriptors.configuration_blocks.BRProfile2Block; -import sugar.free.sightparser.applayer.descriptors.configuration_blocks.BRProfile3Block; -import sugar.free.sightparser.applayer.descriptors.configuration_blocks.BRProfile4Block; -import sugar.free.sightparser.applayer.descriptors.configuration_blocks.BRProfile5Block; -import sugar.free.sightparser.applayer.descriptors.configuration_blocks.BRProfileBlock; -import sugar.free.sightparser.applayer.descriptors.configuration_blocks.ConfigurationBlock; -import sugar.free.sightparser.applayer.messages.AppLayerMessage; -import sugar.free.sightparser.applayer.messages.configuration.CloseWriteSessionMessage; -import sugar.free.sightparser.applayer.messages.configuration.OpenWriteSessionMessage; -import sugar.free.sightparser.applayer.messages.configuration.ReadConfigurationBlockMessage; -import sugar.free.sightparser.applayer.messages.configuration.WriteConfigurationBlockMessage; -import sugar.free.sightparser.handling.SightServiceConnector; -import sugar.free.sightparser.handling.TaskRunner; - -/** - * Created by Tebbe Ubben on 10.03.2018. - */ - -public class WriteBasalProfileTaskRunner extends TaskRunner { - - private List profileBlocks; - private BRProfileBlock profileBlock; - - public WriteBasalProfileTaskRunner(SightServiceConnector serviceConnector, List profileBlocks) { - super(serviceConnector); - this.profileBlocks = profileBlocks; - } - - @Override - protected AppLayerMessage run(AppLayerMessage message) throws Exception { - if (message == null) { - ReadConfigurationBlockMessage readMessage = new ReadConfigurationBlockMessage(); - readMessage.setConfigurationBlockID(ActiveProfileBlock.ID); - return readMessage; - } else if (message instanceof ReadConfigurationBlockMessage) { - ConfigurationBlock configurationBlock = ((ReadConfigurationBlockMessage) message).getConfigurationBlock(); - ActiveProfileBlock activeProfileBlock = (ActiveProfileBlock) configurationBlock; - switch (activeProfileBlock.getActiveProfile()) { - case BR_PROFILE_1: - profileBlock = new BRProfile1Block(); - break; - case BR_PROFILE_2: - profileBlock = new BRProfile2Block(); - break; - case BR_PROFILE_3: - profileBlock = new BRProfile3Block(); - break; - case BR_PROFILE_4: - profileBlock = new BRProfile4Block(); - break; - case BR_PROFILE_5: - profileBlock = new BRProfile5Block(); - break; - } - profileBlock.setProfileBlocks(profileBlocks); - return new OpenWriteSessionMessage(); - } else if (message instanceof OpenWriteSessionMessage) { - WriteConfigurationBlockMessage writeMessage = new WriteConfigurationBlockMessage(); - writeMessage.setConfigurationBlock(profileBlock); - return writeMessage; - } else if (message instanceof WriteConfigurationBlockMessage) { - return new CloseWriteSessionMessage(); - } else if (message instanceof CloseWriteSessionMessage) finish(null); - return null; - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/events/EventInsightCallback.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/events/EventInsightCallback.java deleted file mode 100644 index 753ac7f0e6..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/events/EventInsightCallback.java +++ /dev/null @@ -1,26 +0,0 @@ -package info.nightscout.androidaps.plugins.PumpInsight.events; - -import java.util.UUID; - -import info.nightscout.androidaps.events.Event; - -/** - * Created by jamorham on 23/01/2018. - */ -public class EventInsightCallback extends Event { - - public UUID request_uuid; - public boolean success = false; - public String message = null; - public Object response_object = null; - - public EventInsightCallback() { - request_uuid = UUID.randomUUID(); - } - - @Override - public String toString() { - return "Event: " + request_uuid + " success: " + success + " msg: " + message + " Object: " + response_object; - } - -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/events/EventInsightUpdateGui.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/events/EventInsightUpdateGui.java deleted file mode 100644 index 3741c607c4..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/events/EventInsightUpdateGui.java +++ /dev/null @@ -1,9 +0,0 @@ -package info.nightscout.androidaps.plugins.PumpInsight.events; - -import info.nightscout.androidaps.events.EventUpdateGui; - -/** - * Created by jamorham on 23/01/2018. - */ -public class EventInsightUpdateGui extends EventUpdateGui { -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/history/HistoryIntentAdapter.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/history/HistoryIntentAdapter.java deleted file mode 100644 index 49836e9f3b..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/history/HistoryIntentAdapter.java +++ /dev/null @@ -1,243 +0,0 @@ -package info.nightscout.androidaps.plugins.PumpInsight.history; - -import android.content.Intent; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.db.CareportalEvent; -import info.nightscout.androidaps.db.TDD; -import info.nightscout.androidaps.logging.L; -import info.nightscout.utils.DateUtil; -import info.nightscout.androidaps.plugins.NSClientInternal.NSUpload; -import info.nightscout.utils.SP; - -import org.json.JSONException; -import org.json.JSONObject; - -import sugar.free.sightparser.handling.HistoryBroadcast; - -import java.util.Date; - -import static info.nightscout.androidaps.plugins.PumpInsight.history.PumpIdCache.updatePumpSerialNumber; - -/** - * Created by jamorham on 27/01/2018. - *

- * Parse inbound logbook intents - */ - -class HistoryIntentAdapter { - private Logger log = LoggerFactory.getLogger(L.PUMP); - - private HistoryLogAdapter logAdapter = new HistoryLogAdapter(); - - private static long getDateExtra(Intent intent, String name) { - return ((Date) intent.getSerializableExtra(name)).getTime(); - } - - static long getRecordUniqueID(long pump_serial_number, long pump_record_id) { - updatePumpSerialNumber(pump_serial_number); - return (pump_serial_number * 10000000) + pump_record_id; - } - - void processTBRIntent(Intent intent) { - - final int pump_tbr_duration = intent.getIntExtra(HistoryBroadcast.EXTRA_DURATION, -1); - final int pump_tbr_percent = intent.getIntExtra(HistoryBroadcast.EXTRA_TBR_AMOUNT, -1); - long pump_record_id = intent.getLongExtra(HistoryBroadcast.EXTRA_EVENT_NUMBER, -1); - if (pump_record_id == -1) { - pump_record_id = intent.getIntExtra(HistoryBroadcast.EXTRA_EVENT_NUMBER, -1); - } - final long pump_serial_number = Long.parseLong(intent.getStringExtra(HistoryBroadcast.EXTRA_PUMP_SERIAL_NUMBER)); - final long start_time = getDateExtra(intent, HistoryBroadcast.EXTRA_START_TIME); - - if ((pump_tbr_duration == -1) || (pump_tbr_percent == -1) || (pump_record_id == -1)) { - log.error("Invalid TBR record!!!"); - return; - } - - final long record_unique_id = getRecordUniqueID(pump_serial_number, pump_record_id); - - if (L.isEnabled(L.PUMP)) - log.debug("Creating TBR record: " + pump_tbr_percent + "% " + pump_tbr_duration + "m" + " id:" + record_unique_id); - logAdapter.createTBRrecord(start_time, pump_tbr_percent, pump_tbr_duration, record_unique_id); - } - - void processDeliveredBolusIntent(Intent intent) { - - final String bolus_type = intent.getStringExtra(HistoryBroadcast.EXTRA_BOLUS_TYPE); - final int bolus_id = intent.getIntExtra(HistoryBroadcast.EXTRA_BOLUS_ID, -1); - long pump_record_id = intent.getLongExtra(HistoryBroadcast.EXTRA_EVENT_NUMBER, -1); - if (pump_record_id == -1) { - pump_record_id = intent.getIntExtra(HistoryBroadcast.EXTRA_EVENT_NUMBER, -1); - } - final long pump_serial_number = Long.parseLong(intent.getStringExtra(HistoryBroadcast.EXTRA_PUMP_SERIAL_NUMBER)); - final long event_time = getDateExtra(intent, HistoryBroadcast.EXTRA_EVENT_TIME); - final long start_time = getDateExtra(intent, HistoryBroadcast.EXTRA_START_TIME); - final double immediate_amount = intent.getDoubleExtra(HistoryBroadcast.EXTRA_IMMEDIATE_AMOUNT, -1); - final double extended_insulin = intent.getDoubleExtra(HistoryBroadcast.EXTRA_EXTENDED_AMOUNT, -1); - final int extended_minutes = intent.getIntExtra(HistoryBroadcast.EXTRA_DURATION, -1); - - final long record_unique_id = getRecordUniqueID(pump_serial_number, bolus_id > -1 ? bolus_id : pump_record_id); - - switch (bolus_type) { - case "STANDARD": - if (immediate_amount == -1) { - log.error("ERROR Standard bolus fails sanity check"); - return; - } - LiveHistory.setStatus(bolus_type + " BOLUS\n" + immediate_amount + "U ", event_time); - logAdapter.createStandardBolusRecord(start_time, immediate_amount, record_unique_id); - break; - - case "EXTENDED": - if ((extended_insulin == -1) || (extended_minutes == -1)) { - log.error("ERROR: Extended bolus fails sanity check"); - return; - } - LiveHistory.setStatus(bolus_type + " BOLUS\n" + extended_insulin + "U over " + extended_minutes + " min, ", event_time); - logAdapter.createExtendedBolusRecord(start_time, extended_insulin, extended_minutes, record_unique_id); - break; - - case "MULTIWAVE": - if ((immediate_amount == -1) || (extended_insulin == -1) || (extended_minutes == -1)) { - log.error("ERROR: Multiwave bolus fails sanity check"); - return; - } - LiveHistory.setStatus(bolus_type + " BOLUS\n" + immediate_amount + "U + " + extended_insulin + "U over " + extended_minutes + " min, ", event_time); - logAdapter.createStandardBolusRecord(start_time, immediate_amount, pump_serial_number + pump_record_id); - logAdapter.createExtendedBolusRecord(start_time, extended_insulin, extended_minutes, record_unique_id); - break; - default: - log.error("ERROR, UNKNWON BOLUS TYPE: " + bolus_type); - } - } - - void processDailyTotalIntent(Intent intent) { - long date = getDateExtra(intent, HistoryBroadcast.EXTRA_TOTAL_DATE); - double basal = intent.getDoubleExtra(HistoryBroadcast.EXTRA_BASAL_TOTAL, 0D); - double bolus = intent.getDoubleExtra(HistoryBroadcast.EXTRA_BOLUS_TOTAL, 0D); - TDD tdd = new TDD(date, bolus, basal, bolus + basal); - MainApp.getDbHelper().createOrUpdateTDD(tdd); - } - - void processCannulaFilledIntent(Intent intent) { - long date = getDateExtra(intent, HistoryBroadcast.EXTRA_EVENT_TIME); - uploadCareportalEvent(date, CareportalEvent.SITECHANGE); - } - - void processCartridgeInsertedIntent(Intent intent) { - long date = getDateExtra(intent, HistoryBroadcast.EXTRA_EVENT_TIME); - uploadCareportalEvent(date, CareportalEvent.INSULINCHANGE); - } - - void processBatteryInsertedIntent(Intent intent) { - long date = getDateExtra(intent, HistoryBroadcast.EXTRA_EVENT_TIME); - uploadCareportalEvent(date, CareportalEvent.PUMPBATTERYCHANGE); - } - - private void uploadCareportalEvent(long date, String event) { - if (SP.getBoolean("insight_automatic_careportal_events", false)) { - if (MainApp.getDbHelper().getCareportalEventFromTimestamp(date) != null) - return; - try { - JSONObject data = new JSONObject(); - String enteredBy = SP.getString("careportal_enteredby", ""); - if (!enteredBy.equals("")) data.put("enteredBy", enteredBy); - data.put("created_at", DateUtil.toISOString(date)); - data.put("eventType", event); - NSUpload.uploadCareportalEntryToNS(data); - } catch (JSONException e) { - e.printStackTrace(); - } - } - } - - void processOccurenceOfAlertIntent(Intent intent) { - if (SP.getBoolean("insight_automatic_careportal_events", false)) { - long date = getDateExtra(intent, HistoryBroadcast.EXTRA_EVENT_TIME); - String alertType = intent.getStringExtra(HistoryBroadcast.EXTRA_ALERT_TYPE); - int alertText = getAlertText(alertType); - if (alertText == 0) return; - if (MainApp.getDbHelper().getCareportalEventFromTimestamp(date) != null) - return; - logNote(date, MainApp.gs(alertText)); - } - } - - void processPumpStatusChangedIntent(Intent intent) { - long newStatusTime = getDateExtra(intent, HistoryBroadcast.EXTRA_EVENT_TIME); - if (SP.getBoolean("insight_automatic_careportal_events", false)) { - String newStatus = intent.getStringExtra(HistoryBroadcast.EXTRA_NEW_STATUS); - switch (newStatus) { - case "STARTED": - logNote(newStatusTime, MainApp.gs(R.string.pump_started)); - break; - case "STOPPED": - logNote(newStatusTime, MainApp.gs(R.string.pump_stopped)); - break; - case "PAUSED": - logNote(newStatusTime, MainApp.gs(R.string.pump_paused)); - break; - } - } - if (intent.hasExtra(HistoryBroadcast.EXTRA_OLD_STATUS_TIME)) { - String oldStatus = intent.getStringExtra(HistoryBroadcast.EXTRA_OLD_STATUS); - if (oldStatus.equals("STOPPED")) { - long oldStatusTime = getDateExtra(intent, HistoryBroadcast.EXTRA_OLD_STATUS_TIME); - int duration = (int) ((newStatusTime - oldStatusTime) / 60000); - - long serialNumber = Long.parseLong(intent.getStringExtra(HistoryBroadcast.EXTRA_PUMP_SERIAL_NUMBER)); - long recordId = intent.getLongExtra(HistoryBroadcast.EXTRA_EVENT_NUMBER, -1); - long uniqueRecordId = getRecordUniqueID(serialNumber, recordId); - - logAdapter.createTBRrecord(oldStatusTime, 0, duration, uniqueRecordId); - } - } - } - - private void logNote(long date, String note) { - try { - if (MainApp.getDbHelper().getCareportalEventFromTimestamp(date) != null) - return; - JSONObject data = new JSONObject(); - String enteredBy = SP.getString("careportal_enteredby", ""); - if (!enteredBy.equals("")) data.put("enteredBy", enteredBy); - data.put("created_at", DateUtil.toISOString(date)); - data.put("eventType", CareportalEvent.NOTE); - data.put("notes", note); - NSUpload.uploadCareportalEntryToNS(data); - } catch (JSONException e) { - e.printStackTrace(); - } - } - - private int getAlertText(String type) { - if (type.equals("Error6MechanicalError")) return R.string.alert_e6; - if (type.equals("Error7ElectronicError")) return R.string.alert_e7; - if (type.equals("Error10RewindError")) return R.string.alert_e10; - if (type.equals("Error13LanguageError")) return R.string.alert_e13; - if (type.equals("Maintenance20CartridgeNotInserted")) return R.string.alert_m20; - if (type.equals("Maintenance21CartridgeEmpty")) return R.string.alert_m21; - if (type.equals("Maintenance22BatteryEmpty")) return R.string.alert_m22; - if (type.equals("Maintenance23AutomaticOff")) return R.string.alert_m23; - if (type.equals("Maintenance24Occlusion")) return R.string.alert_m24; - if (type.equals("Maintenance25LoantimeOver")) return R.string.alert_m25; - if (type.equals("Maintenance26CartridgeChangeNotCompleted")) return R.string.alert_m26; - if (type.equals("Maintenance27DataDownloadFailed")) return R.string.alert_m27; - if (type.equals("Maintenance28PauseModeTimeout")) return R.string.alert_m28; - if (type.equals("Maintenance29BatteryTypeNotSet")) return R.string.alert_m29; - if (type.equals("Maintenance30CartridgeTypeNotSet")) return R.string.alert_m30; - if (type.equals("Warning31CartridgeLow")) return R.string.alert_w31; - if (type.equals("Warning32BatteryLow")) return R.string.alert_w32; - if (type.equals("Warning33InvalidDateTime")) return R.string.alert_w33; - if (type.equals("Warning34EndOfWarranty")) return R.string.alert_w34; - if (type.equals("Warning36TBRCancelled")) return 0; - if (type.equals("Warning38BolusCancelled")) return 0; - if (type.equals("Warning39LoantimeWarning")) return R.string.alert_w39; - return 0; - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/history/HistoryLogAdapter.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/history/HistoryLogAdapter.java deleted file mode 100644 index fc44f25418..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/history/HistoryLogAdapter.java +++ /dev/null @@ -1,136 +0,0 @@ -package info.nightscout.androidaps.plugins.PumpInsight.history; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.data.DetailedBolusInfo; -import info.nightscout.androidaps.db.ExtendedBolus; -import info.nightscout.androidaps.db.Source; -import info.nightscout.androidaps.db.TemporaryBasal; -import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions; -import info.nightscout.androidaps.plugins.NSClientInternal.NSUpload; -import info.nightscout.androidaps.plugins.NSClientInternal.UploadQueue; -import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.T; - -/** - * Created by jamorham on 27/01/2018. - *

- * Write to the History Log - */ - -class HistoryLogAdapter { - private Logger log = LoggerFactory.getLogger(L.PUMP); - - private static final long MAX_TIME_DIFFERENCE = T.secs(61).msecs(); - - void createTBRrecord(long eventDate, int percent, int duration, long record_id) { - - TemporaryBasal temporaryBasal = new TemporaryBasal().date(eventDate); - - final TemporaryBasal temporaryBasalFromHistory = TreatmentsPlugin.getPlugin().getTempBasalFromHistory(eventDate); - - if (temporaryBasalFromHistory == null) { - if (L.isEnabled(L.PUMP)) - log.debug("Create new TBR: " + eventDate + " " + percent + " " + duration); - } else { - if (L.isEnabled(L.PUMP)) - log.debug("Loaded existing TBR record: " + temporaryBasalFromHistory.toString()); - if (Math.abs(eventDate - temporaryBasalFromHistory.date) < MAX_TIME_DIFFERENCE) { - if (temporaryBasalFromHistory.source != Source.PUMP) { - if (temporaryBasalFromHistory.percentRate == percent) { - if (L.isEnabled(L.PUMP)) - log.debug("Things seem to match: %" + percent); - temporaryBasal = temporaryBasalFromHistory; - String _id = temporaryBasal._id; - if (NSUpload.isIdValid(_id)) { - NSUpload.removeCareportalEntryFromNS(_id); - } else { - UploadQueue.removeID("dbAdd", _id); - } - MainApp.getDbHelper().delete(temporaryBasalFromHistory); - } else { - if (L.isEnabled(L.PUMP)) - log.debug("This record has different percent rates: " + temporaryBasalFromHistory.percentRate + " vs us: " + percent); - } - } else { - if (L.isEnabled(L.PUMP)) - log.debug("This record is already a pump record!"); - } - } else { - if (L.isEnabled(L.PUMP)) - log.debug("Time difference too big! : " + (eventDate - temporaryBasalFromHistory.date)); - } - } - - temporaryBasal.source(Source.PUMP) - .pumpId(record_id) - .percent(percent) - .duration(duration); - - TreatmentsPlugin.getPlugin().addToHistoryTempBasal(temporaryBasal); - } - - void createExtendedBolusRecord(long eventDate, double insulin, int durationInMinutes, long record_id) { - - final ExtendedBolus extendedBolusFromHistory = TreatmentsPlugin.getPlugin().getExtendedBolusFromHistory(eventDate); - - if (extendedBolusFromHistory == null) { - if (L.isEnabled(L.PUMP)) - log.debug("Create new EB: " + eventDate + " " + insulin + " " + durationInMinutes); - } else { - if (L.isEnabled(L.PUMP)) - log.debug("Loaded existing EB record: " + extendedBolusFromHistory.log()); - if (Math.abs(eventDate - extendedBolusFromHistory.date) < MAX_TIME_DIFFERENCE) { - if (extendedBolusFromHistory.source != Source.PUMP) { - if (L.isEnabled(L.PUMP)) - log.debug("Date seem to match: " + DateUtil.dateAndTimeFullString(eventDate)); - String _id = extendedBolusFromHistory._id; - if (NSUpload.isIdValid(_id)) { - NSUpload.removeCareportalEntryFromNS(_id); - } else { - UploadQueue.removeID("dbAdd", _id); - } - MainApp.getDbHelper().delete(extendedBolusFromHistory); - } else { - if (L.isEnabled(L.PUMP)) - log.debug("This record is already a pump record!"); - } - } else { - if (L.isEnabled(L.PUMP)) - log.debug("Time difference too big! : " + (eventDate - extendedBolusFromHistory.date)); - } - } - - // TODO trap items below minimum period - - // TODO (mike) find and remove ending record with Source.USER - - ExtendedBolus extendedBolus = new ExtendedBolus() - .date(eventDate) - .insulin(insulin) - .durationInMinutes(durationInMinutes) - .source(Source.PUMP) - .pumpId(record_id); - - if (ProfileFunctions.getInstance().getProfile(extendedBolus.date) != null) // actual basal rate is needed for absolute rate calculation - TreatmentsPlugin.getPlugin().addToHistoryExtendedBolus(extendedBolus); - } - - void createStandardBolusRecord(long eventDate, double insulin, long record_id) { - - //DetailedBolusInfo detailedBolusInfo = DetailedBolusInfoStorage.findDetailedBolusInfo(eventDate.getTime()); - - // TODO do we need to do the same delete + insert that we are doing for temporary basals here too? - - final DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); - detailedBolusInfo.date = eventDate; - detailedBolusInfo.source = Source.PUMP; - detailedBolusInfo.pumpId = record_id; - detailedBolusInfo.insulin = insulin; - TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, true); - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/history/HistoryReceiver.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/history/HistoryReceiver.java deleted file mode 100644 index a66378ba54..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/history/HistoryReceiver.java +++ /dev/null @@ -1,134 +0,0 @@ -package info.nightscout.androidaps.plugins.PumpInsight.history; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; - -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.R; - -import static info.nightscout.androidaps.plugins.PumpInsight.history.HistoryReceiver.Status.BUSY; -import static info.nightscout.androidaps.plugins.PumpInsight.history.HistoryReceiver.Status.SYNCED; -import static info.nightscout.androidaps.plugins.PumpInsight.history.HistoryReceiver.Status.SYNCING; -import static sugar.free.sightparser.handling.HistoryBroadcast.*; - -/** - * Created by jamorham on 27/01/2018. - */ - -public class HistoryReceiver { - - private static BroadcastReceiver historyReceiver; - private volatile static Status status = Status.IDLE; - private volatile HistoryIntentAdapter intentAdapter; - - public HistoryReceiver() { - initializeHistoryReceiver(); - } - - public static synchronized void registerHistoryReceiver() { - try { - MainApp.instance().unregisterReceiver(historyReceiver); - } catch (Exception e) { - // - } - - final IntentFilter filter = new IntentFilter(); - filter.addAction(ACTION_PUMP_STATUS_CHANGED); - filter.addAction(ACTION_BOLUS_PROGRAMMED); - filter.addAction(ACTION_BOLUS_DELIVERED); - filter.addAction(ACTION_END_OF_TBR); - filter.addAction(ACTION_DAILY_TOTAL); - filter.addAction(ACTION_SYNC_STARTED); - filter.addAction(ACTION_STILL_SYNCING); - filter.addAction(ACTION_SYNC_FINISHED); - filter.addAction(ACTION_CANNULA_FILLED); - filter.addAction(ACTION_CARTRIDGE_INSERTED); - filter.addAction(ACTION_BATTERY_INSERTED); - filter.addAction(ACTION_OCCURENCE_OF_ALERT); - filter.addAction(ACTION_PUMP_STATUS_CHANGED); - - MainApp.instance().registerReceiver(historyReceiver, filter); - } - - // History - - public static String getStatusString() { - return status.toString(); - } - - private synchronized void initializeHistoryReceiver() { - historyReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, final Intent intent) { - - final String action = intent.getAction(); - if (action == null) return; - - if (intentAdapter == null) { - synchronized (this) { - if (intentAdapter == null) { - intentAdapter = new HistoryIntentAdapter(); - } - } - } - - switch (action) { - case ACTION_SYNC_STARTED: - status = SYNCING; - break; - case ACTION_STILL_SYNCING: - status = BUSY; - break; - case ACTION_SYNC_FINISHED: - status = SYNCED; - break; - case ACTION_BOLUS_DELIVERED: - intentAdapter.processDeliveredBolusIntent(intent); - break; - case ACTION_END_OF_TBR: - intentAdapter.processTBRIntent(intent); - break; - case ACTION_DAILY_TOTAL: - intentAdapter.processDailyTotalIntent(intent); - break; - case ACTION_CANNULA_FILLED: - intentAdapter.processCannulaFilledIntent(intent); - break; - case ACTION_CARTRIDGE_INSERTED: - intentAdapter.processCartridgeInsertedIntent(intent); - break; - case ACTION_BATTERY_INSERTED: - intentAdapter.processBatteryInsertedIntent(intent); - break; - case ACTION_OCCURENCE_OF_ALERT: - intentAdapter.processOccurenceOfAlertIntent(intent); - break; - case ACTION_PUMP_STATUS_CHANGED: - intentAdapter.processPumpStatusChangedIntent(intent); - break; - } - } - }; - } - - enum Status { - IDLE(R.string.insight_history_idle), - SYNCING(R.string.insight_history_syncing), - BUSY(R.string.insight_history_busy), - SYNCED(R.string.insight_history_synced); - - private final int string_id; - - Status(int string_id) { - this.string_id = string_id; - } - - @Override - public String toString() { - return MainApp.gs(string_id); - } - } - -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/history/LiveHistory.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/history/LiveHistory.java deleted file mode 100644 index 46af6bda98..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/history/LiveHistory.java +++ /dev/null @@ -1,33 +0,0 @@ -package info.nightscout.androidaps.plugins.PumpInsight.history; - -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.plugins.PumpInsight.utils.Helpers; - -/** - * Created by jamorham on 27/01/2018. - * - * In memory status storage class - */ - -public class LiveHistory { - - private static String status = ""; - private static long status_time = -1; - - public static String getStatus() { - if (status.equals("")) return status; - return status + " " + Helpers.niceTimeScalar(Helpers.msSince(status_time)) + " " + MainApp.gs(R.string.ago); - } - - public static long getStatusTime() { - return status_time; - } - - static void setStatus(String mystatus, long eventtime) { - if (eventtime > status_time) { - status_time = eventtime; - status = mystatus; - } - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/history/PumpIdCache.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/history/PumpIdCache.java deleted file mode 100644 index 9a2bcfeff5..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/history/PumpIdCache.java +++ /dev/null @@ -1,35 +0,0 @@ -package info.nightscout.androidaps.plugins.PumpInsight.history; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import info.nightscout.androidaps.logging.L; -import info.nightscout.utils.SP; - -/** - * Created by jamorham on 01/02/2018. - */ - -public class PumpIdCache { - private static Logger log = LoggerFactory.getLogger(L.PUMP); - - private static final String INSIGHT_PUMP_ID_PREF = "insight-pump-id"; - private static long cachedPumpSerialNumber = -1; - - static void updatePumpSerialNumber(long pump_serial_number) { - if (pump_serial_number != cachedPumpSerialNumber) { - cachedPumpSerialNumber = pump_serial_number; - if (L.isEnabled(L.PUMP)) - log.debug("Updating pump serial number: " + pump_serial_number); - SP.putLong(INSIGHT_PUMP_ID_PREF, cachedPumpSerialNumber); - } - } - - public static long getRecordUniqueID(long record_id) { - if (cachedPumpSerialNumber == -1) { - cachedPumpSerialNumber = SP.getLong(INSIGHT_PUMP_ID_PREF, 0L); - } - return HistoryIntentAdapter.getRecordUniqueID(cachedPumpSerialNumber, record_id); - } - -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/utils/Helpers.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/utils/Helpers.java deleted file mode 100644 index bfdca16588..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/utils/Helpers.java +++ /dev/null @@ -1,197 +0,0 @@ -package info.nightscout.androidaps.plugins.PumpInsight.utils; - -import android.content.Context; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.os.Handler; -import android.os.PowerManager; -import android.util.Log; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.math.BigDecimal; -import java.math.RoundingMode; -import java.text.DecimalFormat; -import java.text.DecimalFormatSymbols; -import java.util.HashMap; -import java.util.Map; - -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.logging.L; - -/** - * Created by jamorham on 24/01/2018. - *

- * Useful utility methods from xDrip+ - */ - -public class Helpers { - private static Logger log = LoggerFactory.getLogger(L.PUMP); - - - private static final Map rateLimits = new HashMap<>(); - // singletons to avoid repeated allocation - private static DecimalFormatSymbols dfs; - private static DecimalFormat df; - - // return true if below rate limit - public static synchronized boolean ratelimit(String name, int seconds) { - // check if over limit - if ((rateLimits.containsKey(name)) && (tsl() - rateLimits.get(name) < (seconds * 1000))) { - if (L.isEnabled(L.PUMP)) - log.debug(name + " rate limited: " + seconds + " seconds"); - return false; - } - // not over limit - rateLimits.put(name, tsl()); - return true; - } - - public static long tsl() { - return System.currentTimeMillis(); - } - - public static long msSince(long when) { - return (tsl() - when); - } - - public static long msTill(long when) { - return (when - tsl()); - } - - public static boolean checkPackageExists(Context context, String TAG, String packageName) { - try { - final PackageManager pm = context.getPackageManager(); - final PackageInfo pi = pm.getPackageInfo(packageName, 0); - return pi.packageName.equals(packageName); - } catch (PackageManager.NameNotFoundException e) { - return false; - } catch (Exception e) { - log.error("Exception trying to determine packages! " + e); - return false; - } - } - - public static boolean runOnUiThreadDelayed(Runnable theRunnable, long delay) { - return new Handler(MainApp.instance().getMainLooper()).postDelayed(theRunnable, delay); - } - - public static PowerManager.WakeLock getWakeLock(final String name, int millis) { - final PowerManager pm = (PowerManager) MainApp.instance().getSystemService(Context.POWER_SERVICE); - if (pm == null) return null; - final PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, name); - wl.acquire(millis); - return wl; - } - - public static void releaseWakeLock(PowerManager.WakeLock wl) { - if (wl == null) return; - if (wl.isHeld()) wl.release(); - } - - public static String niceTimeSince(long t) { - return niceTimeScalar(msSince(t)); - } - - public static String niceTimeTill(long t) { - return niceTimeScalar(-msSince(t)); - } - - public static String niceTimeScalar(long t) { - String unit = MainApp.gs(R.string.second); - t = t / 1000; - if (t > 59) { - unit = MainApp.gs(R.string.minute); - t = t / 60; - if (t > 59) { - unit = MainApp.gs(R.string.hour); - t = t / 60; - if (t > 24) { - unit = MainApp.gs(R.string.day); - t = t / 24; - if (t > 28) { - unit = MainApp.gs(R.string.week); - t = t / 7; - } - } - } - } - if (t != 1) unit = unit + MainApp.gs(R.string.time_plural); - return qs((double) t, 0) + " " + unit; - } - - public static String qs(double x, int digits) { - - if (digits == -1) { - digits = 0; - if (((int) x != x)) { - digits++; - if ((((int) x * 10) / 10 != x)) { - digits++; - if ((((int) x * 100) / 100 != x)) digits++; - } - } - } - - if (dfs == null) { - final DecimalFormatSymbols local_dfs = new DecimalFormatSymbols(); - local_dfs.setDecimalSeparator('.'); - dfs = local_dfs; // avoid race condition - } - - final DecimalFormat this_df; - // use singleton if on ui thread otherwise allocate new as DecimalFormat is not thread safe - if (Thread.currentThread().getId() == 1) { - if (df == null) { - final DecimalFormat local_df = new DecimalFormat("#", dfs); - local_df.setMinimumIntegerDigits(1); - df = local_df; // avoid race condition - } - this_df = df; - } else { - this_df = new DecimalFormat("#", dfs); - } - - this_df.setMaximumFractionDigits(digits); - return this_df.format(x); - } - - public static String niceTimeScalarRedux(long t) { - return niceTimeScalar(t).replaceFirst("^1 ", ""); - } - - public static String niceTimeScalarBrief(long t) { - // TODO i18n wont work for non-latin characterset - return niceTimeScalar(t).replaceFirst("([a-z])[a-z]*", "$1").replace(" ", ""); - } - - public static String hourMinuteString(long timestamp) { - return android.text.format.DateFormat.format("kk:mm", timestamp).toString(); - } - - public static String hourMinuteSecondString(long timestamp) { - return android.text.format.DateFormat.format("kk:mm:ss", timestamp).toString(); - } - - public static String dateTimeText(long timestamp) { - return android.text.format.DateFormat.format("yyyy-MM-dd kk:mm:ss", timestamp).toString(); - } - - public static String dateText(long timestamp) { - return android.text.format.DateFormat.format("yyyy-MM-dd", timestamp).toString(); - } - - public static String capitalize(String text) { - return text.substring(0, 1).toUpperCase() + text.substring(1).toLowerCase(); - } - - public static double roundDouble(double value, int places) { - if (places < 0) throw new IllegalArgumentException("Invalid decimal places"); - BigDecimal bd = new BigDecimal(value); - bd = bd.setScale(places, RoundingMode.HALF_UP); - return bd.doubleValue(); - } - -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/utils/StatusItem.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/utils/StatusItem.java deleted file mode 100644 index 395dd51084..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/utils/StatusItem.java +++ /dev/null @@ -1,64 +0,0 @@ -package info.nightscout.androidaps.plugins.PumpInsight.utils; - -/** - * Created by jamorham on 26/01/2018. - * - * For representing row status items - */ - -public class StatusItem { - - public enum Highlight { - NORMAL, - GOOD, - BAD, - NOTICE, - CRITICAL - } - - public String name; - public String value; - public Highlight highlight; - public String button_name; - public Runnable runnable; - - - public StatusItem(String name, String value) { - this(name, value, Highlight.NORMAL); - } - - public StatusItem() { - this("line-break", "", Highlight.NORMAL); - } - - public StatusItem(String name, Highlight highlight) { - this("heading-break", name, highlight); - } - - public StatusItem(String name, Runnable runnable) { - this("button-break", "", Highlight.NORMAL, name, runnable); - } - - public StatusItem(String name, String value, Highlight highlight) { - this(name, value, highlight, null, null); - } - - public StatusItem(String name, String value, Highlight highlight, String button_name, Runnable runnable) { - this.name = name; - this.value = value; - this.highlight = highlight; - this.button_name = button_name; - this.runnable = runnable; - } - - public StatusItem(String name, Integer value) { - this(name, value, Highlight.NORMAL); - } - - public StatusItem(String name, Integer value, Highlight highlight) { - this.name = name; - this.value = Integer.toString(value); - this.highlight = highlight; - } - -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/utils/ui/StatusItemViewAdapter.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/utils/ui/StatusItemViewAdapter.java deleted file mode 100644 index 87c40c19de..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/utils/ui/StatusItemViewAdapter.java +++ /dev/null @@ -1,85 +0,0 @@ -package info.nightscout.androidaps.plugins.PumpInsight.utils.ui; - -import android.app.Activity; -import android.graphics.Color; -import android.view.Gravity; -import android.view.View; -import android.view.ViewGroup; -import android.widget.LinearLayout; -import android.widget.TextView; - -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.plugins.PumpInsight.utils.StatusItem; - -/** - * Created by jamorham on 26/01/2018. - * - * Convert StatusItem to View - */ - -public class StatusItemViewAdapter { - - private final Activity activity; - private final ViewGroup holder; - - public StatusItemViewAdapter(Activity activity, ViewGroup holder) { - this.activity = activity; - this.holder = holder; - } - - public View inflateStatus(StatusItem statusItem) { - if (activity == null) return null; - final View child = activity.getLayoutInflater().inflate(R.layout.insightpump_statuselements, null); - final TextView name = (TextView) child.findViewById(R.id.insightstatuslabel); - final TextView value = (TextView)child.findViewById(R.id.insightstatusvalue); - final TextView spacer = (TextView)child.findViewById(R.id.insightstatusspacer); - final LinearLayout layout = (LinearLayout)child.findViewById(R.id.insightstatuslayout); - - if (statusItem.name.equals("line-break")) { - spacer.setVisibility(View.GONE); - name.setVisibility(View.GONE); - value.setVisibility(View.GONE); - layout.setPadding(10, 10, 10, 10); - } else if (statusItem.name.equals("heading-break")) { - value.setVisibility(View.GONE); - spacer.setVisibility(View.GONE); - name.setText(statusItem.value); - name.setGravity(Gravity.CENTER_HORIZONTAL); - name.setTextColor(Color.parseColor("#fff9c4")); - } else { - name.setText(statusItem.name); - value.setText(statusItem.value); - } - - final int this_color = getHighlightColor(statusItem); - name.setBackgroundColor(this_color); - value.setBackgroundColor(this_color); - spacer.setBackgroundColor(this_color); - - if (this_color != Color.TRANSPARENT) { - name.setTextColor(Color.WHITE); - spacer.setTextColor(Color.WHITE); - } - - if (holder != null) { - holder.addView(child); - } - return child; - } - - private static int getHighlightColor(StatusItem row) { - switch (row.highlight) { - case BAD: - return Color.parseColor("#480000"); - case NOTICE: - return Color.parseColor("#403000"); - case GOOD: - return Color.parseColor("#003000"); - case CRITICAL: - return Color.parseColor("#770000"); - default: - return Color.TRANSPARENT; - } - } - -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/VirtualPumpFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/VirtualPumpFragment.java deleted file mode 100644 index ef4c85e0a7..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/VirtualPumpFragment.java +++ /dev/null @@ -1,122 +0,0 @@ -package info.nightscout.androidaps.plugins.PumpVirtual; - - -import android.app.Activity; -import android.os.Bundle; -import android.os.Handler; -import android.support.annotation.Nullable; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; - -import com.squareup.otto.Subscribe; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.db.ExtendedBolus; -import info.nightscout.androidaps.db.TemporaryBasal; -import info.nightscout.androidaps.plugins.Common.SubscriberFragment; -import info.nightscout.androidaps.plugins.PumpCommon.defs.PumpType; -import info.nightscout.androidaps.plugins.PumpVirtual.events.EventVirtualPumpUpdateGui; -import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; -import info.nightscout.utils.FabricPrivacy; - -public class VirtualPumpFragment extends SubscriberFragment { - private static Logger log = LoggerFactory.getLogger(VirtualPumpFragment.class); - - TextView basaBasalRateView; - TextView tempBasalView; - TextView extendedBolusView; - TextView batteryView; - TextView reservoirView; - TextView pumpTypeView; - TextView pumpSettingsView; - - - private static Handler sLoopHandler = new Handler(); - private static Runnable sRefreshLoop = null; - - @Override - public void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - if (sRefreshLoop == null) { - sRefreshLoop = new Runnable() { - @Override - public void run() { - updateGUI(); - sLoopHandler.postDelayed(sRefreshLoop, 60 * 1000L); - } - }; - sLoopHandler.postDelayed(sRefreshLoop, 60 * 1000L); - } - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - try { - View view = inflater.inflate(R.layout.virtualpump_fragment, container, false); - basaBasalRateView = (TextView) view.findViewById(R.id.virtualpump_basabasalrate); - tempBasalView = (TextView) view.findViewById(R.id.virtualpump_tempbasal); - extendedBolusView = (TextView) view.findViewById(R.id.virtualpump_extendedbolus); - batteryView = (TextView) view.findViewById(R.id.virtualpump_battery); - reservoirView = (TextView) view.findViewById(R.id.virtualpump_reservoir); - pumpTypeView = (TextView) view.findViewById(R.id.virtualpump_type); - pumpSettingsView = (TextView) view.findViewById(R.id.virtualpump_type_def); - - return view; - } catch (Exception e) { - FabricPrivacy.logException(e); - } - - return null; - } - - @Subscribe - public void onStatusEvent(final EventVirtualPumpUpdateGui ev) { - updateGUI(); - } - - @Override - protected void updateGUI() { - Activity activity = getActivity(); - if (activity != null && basaBasalRateView != null) - activity.runOnUiThread(new Runnable() { - @Override - public void run() { - VirtualPumpPlugin virtualPump = VirtualPumpPlugin.getPlugin(); - basaBasalRateView.setText(virtualPump.getBaseBasalRate() + "U"); - TemporaryBasal activeTemp = TreatmentsPlugin.getPlugin().getTempBasalFromHistory(System.currentTimeMillis()); - if (activeTemp != null) { - tempBasalView.setText(activeTemp.toStringFull()); - } else { - tempBasalView.setText(""); - } - ExtendedBolus activeExtendedBolus = TreatmentsPlugin.getPlugin().getExtendedBolusFromHistory(System.currentTimeMillis()); - if (activeExtendedBolus != null) { - extendedBolusView.setText(activeExtendedBolus.toString()); - } else { - extendedBolusView.setText(""); - } - batteryView.setText(virtualPump.batteryPercent + "%"); - reservoirView.setText(virtualPump.reservoirInUnits + "U"); - - virtualPump.refreshConfiguration(); - - PumpType pumpType = virtualPump.getPumpType(); - - pumpTypeView.setText(pumpType.getDescription()); - - String template = MainApp.gs(R.string.virtualpump_pump_def); - - - pumpSettingsView.setText(pumpType.getFullDescription(template, pumpType.hasExtendedBasals())); - - } - }); - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/events/EventVirtualPumpUpdateGui.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/events/EventVirtualPumpUpdateGui.java deleted file mode 100644 index e035ea3aba..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/events/EventVirtualPumpUpdateGui.java +++ /dev/null @@ -1,9 +0,0 @@ -package info.nightscout.androidaps.plugins.PumpVirtual.events; - -import info.nightscout.androidaps.events.EventUpdateGui; - -/** - * Created by mike on 05.08.2016. - */ -public class EventVirtualPumpUpdateGui extends EventUpdateGui { -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/SmsCommunicatorFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/SmsCommunicatorFragment.java deleted file mode 100644 index 3f218063ef..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/SmsCommunicatorFragment.java +++ /dev/null @@ -1,92 +0,0 @@ -package info.nightscout.androidaps.plugins.SmsCommunicator; - - -import android.app.Activity; -import android.os.Bundle; -import android.support.v4.app.Fragment; -import android.text.Html; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; - -import com.squareup.otto.Subscribe; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Collections; -import java.util.Comparator; - -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.plugins.Common.SubscriberFragment; -import info.nightscout.androidaps.plugins.SmsCommunicator.events.EventSmsCommunicatorUpdateGui; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.FabricPrivacy; - -/** - * A simple {@link Fragment} subclass. - */ -public class SmsCommunicatorFragment extends SubscriberFragment { - private static Logger log = LoggerFactory.getLogger(SmsCommunicatorFragment.class); - - TextView logView; - - public SmsCommunicatorFragment() { - super(); - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - try { - View view = inflater.inflate(R.layout.smscommunicator_fragment, container, false); - - logView = (TextView) view.findViewById(R.id.smscommunicator_log); - - updateGUI(); - return view; - } catch (Exception e) { - FabricPrivacy.logException(e); - } - - return null; - } - - @Subscribe - public void onStatusEvent(final EventSmsCommunicatorUpdateGui ev) { - updateGUI(); - } - - - @Override - protected void updateGUI() { - Activity activity = getActivity(); - if (activity != null) - activity.runOnUiThread(new Runnable() { - @Override - public void run() { - class CustomComparator implements Comparator { - public int compare(SmsCommunicatorPlugin.Sms object1, SmsCommunicatorPlugin.Sms object2) { - return (int) (object1.date - object2.date); - } - } - Collections.sort(SmsCommunicatorPlugin.getPlugin().messages, new CustomComparator()); - int messagesToShow = 40; - - int start = Math.max(0, SmsCommunicatorPlugin.getPlugin().messages.size() - messagesToShow); - - String logText = ""; - for (int x = start; x < SmsCommunicatorPlugin.getPlugin().messages.size(); x++) { - SmsCommunicatorPlugin.Sms sms = SmsCommunicatorPlugin.getPlugin().messages.get(x); - if (sms.received) { - logText += DateUtil.timeString(sms.date) + " <<< " + (sms.processed ? "● " : "○ ") + sms.phoneNumber + " " + sms.text + "
"; - } else if (sms.sent) { - logText += DateUtil.timeString(sms.date) + " >>> " + (sms.processed ? "● " : "○ ") + sms.phoneNumber + " " + sms.text + "
"; - } - } - logView.setText(Html.fromHtml(logText)); - } - }); - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/SmsCommunicatorPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/SmsCommunicatorPlugin.java deleted file mode 100644 index b3800cbe82..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/SmsCommunicatorPlugin.java +++ /dev/null @@ -1,605 +0,0 @@ -package info.nightscout.androidaps.plugins.SmsCommunicator; - -import android.content.Intent; -import android.content.pm.ResolveInfo; -import android.os.Bundle; -import android.os.SystemClock; -import android.telephony.SmsManager; -import android.telephony.SmsMessage; - -import com.crashlytics.android.answers.CustomEvent; -import com.squareup.otto.Subscribe; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.text.Normalizer; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - -import info.nightscout.androidaps.Constants; -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions; -import info.nightscout.androidaps.services.Intents; -import info.nightscout.androidaps.data.DetailedBolusInfo; -import info.nightscout.androidaps.data.GlucoseStatus; -import info.nightscout.androidaps.data.IobTotal; -import info.nightscout.androidaps.data.Profile; -import info.nightscout.androidaps.db.BgReading; -import info.nightscout.androidaps.db.DatabaseHelper; -import info.nightscout.androidaps.db.Source; -import info.nightscout.androidaps.events.EventPreferenceChange; -import info.nightscout.androidaps.events.EventRefreshOverview; -import info.nightscout.androidaps.interfaces.Constraint; -import info.nightscout.androidaps.interfaces.PluginBase; -import info.nightscout.androidaps.interfaces.PluginDescription; -import info.nightscout.androidaps.interfaces.PluginType; -import info.nightscout.androidaps.interfaces.PumpInterface; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.Loop.LoopPlugin; -import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; -import info.nightscout.androidaps.plugins.Overview.notifications.Notification; -import info.nightscout.androidaps.plugins.SmsCommunicator.events.EventSmsCommunicatorUpdateGui; -import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; -import info.nightscout.androidaps.queue.Callback; -import info.nightscout.utils.DecimalFormatter; -import info.nightscout.utils.FabricPrivacy; -import info.nightscout.androidaps.plugins.NSClientInternal.NSUpload; -import info.nightscout.utils.SP; -import info.nightscout.utils.SafeParse; -import info.nightscout.utils.T; -import info.nightscout.utils.XdripCalibrations; - -/** - * Created by mike on 05.08.2016. - */ -public class SmsCommunicatorPlugin extends PluginBase { - private static Logger log = LoggerFactory.getLogger(SmsCommunicatorPlugin.class); - - private static SmsCommunicatorPlugin smsCommunicatorPlugin; - - public static SmsCommunicatorPlugin getPlugin() { - - if (smsCommunicatorPlugin == null) { - smsCommunicatorPlugin = new SmsCommunicatorPlugin(); - } - return smsCommunicatorPlugin; - } - - private List allowedNumbers = new ArrayList<>(); - - class Sms { - String phoneNumber; - String text; - long date; - boolean received = false; - boolean sent = false; - boolean processed = false; - - String confirmCode; - double bolusRequested = 0d; - double tempBasal = 0d; - double calibrationRequested = 0d; - int duration = 0; - - Sms(SmsMessage message) { - phoneNumber = message.getOriginatingAddress(); - text = message.getMessageBody(); - date = message.getTimestampMillis(); - received = true; - } - - Sms(String phoneNumber, String text, long date) { - this.phoneNumber = phoneNumber; - this.text = text; - this.date = date; - sent = true; - } - - Sms(String phoneNumber, String text, long date, String confirmCode) { - this.phoneNumber = phoneNumber; - this.text = text; - this.date = date; - this.confirmCode = confirmCode; - sent = true; - } - - public String toString() { - return "SMS from " + phoneNumber + ": " + text; - } - } - - private Sms cancelTempBasalWaitingForConfirmation = null; - private Sms tempBasalWaitingForConfirmation = null; - private Sms bolusWaitingForConfirmation = null; - private Sms calibrationWaitingForConfirmation = null; - private Sms suspendWaitingForConfirmation = null; - private Date lastRemoteBolusTime = new Date(0); - - ArrayList messages = new ArrayList<>(); - - private SmsCommunicatorPlugin() { - super(new PluginDescription() - .mainType(PluginType.GENERAL) - .fragmentClass(SmsCommunicatorFragment.class.getName()) - .pluginName(R.string.smscommunicator) - .shortName(R.string.smscommunicator_shortname) - .preferencesId(R.xml.pref_smscommunicator) - .description(R.string.description_sms_communicator) - ); - processSettings(null); - } - - @Override - protected void onStart() { - MainApp.bus().register(this); - super.onStart(); - } - - @Override - protected void onStop() { - MainApp.bus().unregister(this); - } - - @Subscribe - public void processSettings(final EventPreferenceChange ev) { - if (ev == null || ev.isChanged(R.string.key_smscommunicator_allowednumbers)) { - String settings = SP.getString(R.string.key_smscommunicator_allowednumbers, ""); - - String pattern = ";"; - - String[] substrings = settings.split(pattern); - for (String number : substrings) { - String cleaned = number.replaceAll("\\s+", ""); - allowedNumbers.add(cleaned); - log.debug("Found allowed number: " + cleaned); - } - } - } - - private boolean isAllowedNumber(String number) { - for (String num : allowedNumbers) { - if (num.equals(number)) return true; - } - return false; - } - - public void handleNewData(Intent intent) { - Bundle bundle = intent.getExtras(); - if (bundle == null) return; - - Object[] pdus = (Object[]) bundle.get("pdus"); - if (pdus != null) { - // For every SMS message received - for (Object pdu : pdus) { - SmsMessage message = SmsMessage.createFromPdu((byte[]) pdu); - processSms(new Sms(message)); - } - } - } - - private void processSms(final Sms receivedSms) { - if (!isEnabled(PluginType.GENERAL)) { - log.debug("Ignoring SMS. Plugin disabled."); - return; - } - if (!isAllowedNumber(receivedSms.phoneNumber)) { - log.debug("Ignoring SMS from: " + receivedSms.phoneNumber + ". Sender not allowed"); - return; - } - - String reply = ""; - - messages.add(receivedSms); - log.debug(receivedSms.toString()); - - String[] splited = receivedSms.text.split("\\s+"); - Double amount; - Double tempBasal; - int duration = 0; - String passCode; - boolean remoteCommandsAllowed = SP.getBoolean(R.string.key_smscommunicator_remotecommandsallowed, false); - - if (splited.length > 0) { - switch (splited[0].toUpperCase()) { - case "BG": - BgReading actualBG = DatabaseHelper.actualBg(); - BgReading lastBG = DatabaseHelper.lastBg(); - - String units = ProfileFunctions.getInstance().getProfileUnits(); - - if (actualBG != null) { - reply = MainApp.gs(R.string.sms_actualbg) + " " + actualBG.valueToUnitsToString(units) + ", "; - } else if (lastBG != null) { - Long agoMsec = System.currentTimeMillis() - lastBG.date; - int agoMin = (int) (agoMsec / 60d / 1000d); - reply = MainApp.gs(R.string.sms_lastbg) + " " + lastBG.valueToUnitsToString(units) + " " + String.format(MainApp.gs(R.string.sms_minago), agoMin) + ", "; - } - GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData(); - if (glucoseStatus != null) - reply += MainApp.gs(R.string.sms_delta) + " " + Profile.toUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units) + " " + units + ", "; - - TreatmentsPlugin.getPlugin().updateTotalIOBTreatments(); - IobTotal bolusIob = TreatmentsPlugin.getPlugin().getLastCalculationTreatments().round(); - TreatmentsPlugin.getPlugin().updateTotalIOBTempBasals(); - IobTotal basalIob = TreatmentsPlugin.getPlugin().getLastCalculationTempBasals().round(); - - reply += MainApp.gs(R.string.sms_iob) + " " + DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U (" - + MainApp.gs(R.string.sms_bolus) + " " + DecimalFormatter.to2Decimal(bolusIob.iob) + "U " - + MainApp.gs(R.string.sms_basal) + " " + DecimalFormatter.to2Decimal(basalIob.basaliob) + "U)"; - - sendSMS(new Sms(receivedSms.phoneNumber, reply, System.currentTimeMillis())); - receivedSms.processed = true; - FabricPrivacy.getInstance().logCustom(new CustomEvent("SMS_Bg")); - break; - case "LOOP": - if (splited.length > 1) - switch (splited[1].toUpperCase()) { - case "DISABLE": - case "STOP": - LoopPlugin loopPlugin = MainApp.getSpecificPlugin(LoopPlugin.class); - if (loopPlugin != null && loopPlugin.isEnabled(PluginType.LOOP)) { - loopPlugin.setPluginEnabled(PluginType.LOOP, false); - ConfigBuilderPlugin.getPlugin().getCommandQueue().cancelTempBasal(true, new Callback() { - @Override - public void run() { - MainApp.bus().post(new EventRefreshOverview("SMS_LOOP_STOP")); - String reply = MainApp.gs(R.string.smscommunicator_loophasbeendisabled) + " " + - MainApp.gs(result.success ? R.string.smscommunicator_tempbasalcanceled : R.string.smscommunicator_tempbasalcancelfailed); - sendSMS(new Sms(receivedSms.phoneNumber, reply, System.currentTimeMillis())); - } - }); - } - receivedSms.processed = true; - FabricPrivacy.getInstance().logCustom(new CustomEvent("SMS_Loop_Stop")); - break; - case "ENABLE": - case "START": - loopPlugin = MainApp.getSpecificPlugin(LoopPlugin.class); - if (loopPlugin != null && !loopPlugin.isEnabled(PluginType.LOOP)) { - loopPlugin.setPluginEnabled(PluginType.LOOP, true); - reply = MainApp.gs(R.string.smscommunicator_loophasbeenenabled); - sendSMS(new Sms(receivedSms.phoneNumber, reply, System.currentTimeMillis())); - MainApp.bus().post(new EventRefreshOverview("SMS_LOOP_START")); - } - receivedSms.processed = true; - FabricPrivacy.getInstance().logCustom(new CustomEvent("SMS_Loop_Start")); - break; - case "STATUS": - loopPlugin = MainApp.getSpecificPlugin(LoopPlugin.class); - if (loopPlugin != null) { - if (loopPlugin.isEnabled(PluginType.LOOP)) { - if (loopPlugin.isSuspended()) - reply = String.format(MainApp.gs(R.string.loopsuspendedfor), loopPlugin.minutesToEndOfSuspend()); - else - reply = MainApp.gs(R.string.smscommunicator_loopisenabled); - } else { - reply = MainApp.gs(R.string.smscommunicator_loopisdisabled); - } - sendSMS(new Sms(receivedSms.phoneNumber, reply, System.currentTimeMillis())); - } - receivedSms.processed = true; - FabricPrivacy.getInstance().logCustom(new CustomEvent("SMS_Loop_Status")); - break; - case "RESUME": - LoopPlugin.getPlugin().suspendTo(0); - MainApp.bus().post(new EventRefreshOverview("SMS_LOOP_RESUME")); - NSUpload.uploadOpenAPSOffline(0); - reply = MainApp.gs(R.string.smscommunicator_loopresumed); - sendSMSToAllNumbers(new Sms(receivedSms.phoneNumber, reply, System.currentTimeMillis())); - FabricPrivacy.getInstance().logCustom(new CustomEvent("SMS_Loop_Resume")); - break; - case "SUSPEND": - if (splited.length >= 3) - duration = SafeParse.stringToInt(splited[2]); - duration = Math.max(0, duration); - duration = Math.min(180, duration); - if (duration == 0) { - reply = MainApp.gs(R.string.smscommunicator_wrongduration); - sendSMS(new Sms(receivedSms.phoneNumber, reply, System.currentTimeMillis())); - } else if (remoteCommandsAllowed) { - passCode = generatePasscode(); - reply = String.format(MainApp.gs(R.string.smscommunicator_suspendreplywithcode), duration, passCode); - receivedSms.processed = true; - resetWaitingMessages(); - sendSMS(suspendWaitingForConfirmation = new Sms(receivedSms.phoneNumber, reply, System.currentTimeMillis(), passCode)); - suspendWaitingForConfirmation.duration = duration; - FabricPrivacy.getInstance().logCustom(new CustomEvent("SMS_Loop_Suspend")); - } else { - reply = MainApp.gs(R.string.smscommunicator_remotecommandnotallowed); - sendSMS(new Sms(receivedSms.phoneNumber, reply, System.currentTimeMillis())); - } - break; - } - break; - case "TREATMENTS": - if (splited.length > 1) - switch (splited[1].toUpperCase()) { - case "REFRESH": - Intent restartNSClient = new Intent(Intents.ACTION_RESTART); - TreatmentsPlugin.getPlugin().getService().resetTreatments(); - MainApp.instance().getApplicationContext().sendBroadcast(restartNSClient); - List q = MainApp.instance().getApplicationContext().getPackageManager().queryBroadcastReceivers(restartNSClient, 0); - reply = "TERATMENTS REFRESH " + q.size() + " receivers"; - sendSMS(new Sms(receivedSms.phoneNumber, reply, System.currentTimeMillis())); - receivedSms.processed = true; - FabricPrivacy.getInstance().logCustom(new CustomEvent("SMS_Treatments_Refresh")); - break; - } - break; - case "NSCLIENT": - if (splited.length > 1) - switch (splited[1].toUpperCase()) { - case "RESTART": - Intent restartNSClient = new Intent(Intents.ACTION_RESTART); - MainApp.instance().getApplicationContext().sendBroadcast(restartNSClient); - List q = MainApp.instance().getApplicationContext().getPackageManager().queryBroadcastReceivers(restartNSClient, 0); - reply = "NSCLIENT RESTART " + q.size() + " receivers"; - sendSMS(new Sms(receivedSms.phoneNumber, reply, System.currentTimeMillis())); - receivedSms.processed = true; - FabricPrivacy.getInstance().logCustom(new CustomEvent("SMS_Nsclient_Restart")); - break; - } - break; - case "PUMP": - case "DANAR": - ConfigBuilderPlugin.getPlugin().getCommandQueue().readStatus("SMS", new Callback() { - @Override - public void run() { - PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump(); - if (result.success) { - if (pump != null) { - String reply = pump.shortStatus(true); - sendSMSToAllNumbers(new Sms(receivedSms.phoneNumber, reply, System.currentTimeMillis())); - } - } else { - String reply = MainApp.gs(R.string.readstatusfailed); - sendSMS(new Sms(receivedSms.phoneNumber, reply, System.currentTimeMillis())); - } - } - }); - receivedSms.processed = true; - FabricPrivacy.getInstance().logCustom(new CustomEvent("SMS_Pump")); - break; - case "BASAL": - if (splited.length > 1) { - if (splited[1].toUpperCase().equals("CANCEL") || splited[1].toUpperCase().equals("STOP")) { - if (remoteCommandsAllowed) { - passCode = generatePasscode(); - reply = String.format(MainApp.gs(R.string.smscommunicator_basalstopreplywithcode), passCode); - receivedSms.processed = true; - resetWaitingMessages(); - sendSMS(cancelTempBasalWaitingForConfirmation = new Sms(receivedSms.phoneNumber, reply, System.currentTimeMillis(), passCode)); - FabricPrivacy.getInstance().logCustom(new CustomEvent("SMS_Basal")); - } else { - reply = MainApp.gs(R.string.smscommunicator_remotebasalnotallowed); - sendSMS(new Sms(receivedSms.phoneNumber, reply, System.currentTimeMillis())); - } - } else { - tempBasal = SafeParse.stringToDouble(splited[1]); - Profile profile = ProfileFunctions.getInstance().getProfile(); - if (profile == null) { - reply = MainApp.gs(R.string.noprofile); - sendSMS(new Sms(receivedSms.phoneNumber, reply, System.currentTimeMillis())); - } else { - tempBasal = MainApp.getConstraintChecker().applyBasalConstraints(new Constraint<>(tempBasal), profile).value(); - if (remoteCommandsAllowed) { - passCode = generatePasscode(); - reply = String.format(MainApp.gs(R.string.smscommunicator_basalreplywithcode), tempBasal, passCode); - receivedSms.processed = true; - resetWaitingMessages(); - sendSMS(tempBasalWaitingForConfirmation = new Sms(receivedSms.phoneNumber, reply, System.currentTimeMillis(), passCode)); - tempBasalWaitingForConfirmation.tempBasal = tempBasal; - FabricPrivacy.getInstance().logCustom(new CustomEvent("SMS_Basal")); - } else { - reply = MainApp.gs(R.string.smscommunicator_remotebasalnotallowed); - sendSMS(new Sms(receivedSms.phoneNumber, reply, System.currentTimeMillis())); - } - } - } - } - break; - case "BOLUS": - if (System.currentTimeMillis() - lastRemoteBolusTime.getTime() < Constants.remoteBolusMinDistance) { - reply = MainApp.gs(R.string.smscommunicator_remotebolusnotallowed); - sendSMS(new Sms(receivedSms.phoneNumber, reply, System.currentTimeMillis())); - } else if (ConfigBuilderPlugin.getPlugin().getActivePump().isSuspended()) { - reply = MainApp.gs(R.string.pumpsuspended); - sendSMS(new Sms(receivedSms.phoneNumber, reply, System.currentTimeMillis())); - } else if (splited.length > 1) { - amount = SafeParse.stringToDouble(splited[1]); - amount = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(amount)).value(); - if (amount > 0d && remoteCommandsAllowed) { - passCode = generatePasscode(); - reply = String.format(MainApp.gs(R.string.smscommunicator_bolusreplywithcode), amount, passCode); - receivedSms.processed = true; - resetWaitingMessages(); - sendSMS(bolusWaitingForConfirmation = new Sms(receivedSms.phoneNumber, reply, System.currentTimeMillis(), passCode)); - bolusWaitingForConfirmation.bolusRequested = amount; - FabricPrivacy.getInstance().logCustom(new CustomEvent("SMS_Bolus")); - } else { - reply = MainApp.gs(R.string.smscommunicator_remotebolusnotallowed); - sendSMS(new Sms(receivedSms.phoneNumber, reply, System.currentTimeMillis())); - } - } - break; - case "CAL": - if (splited.length > 1) { - amount = SafeParse.stringToDouble(splited[1]); - if (amount > 0d && remoteCommandsAllowed) { - passCode = generatePasscode(); - reply = String.format(MainApp.gs(R.string.smscommunicator_calibrationreplywithcode), amount, passCode); - receivedSms.processed = true; - resetWaitingMessages(); - sendSMS(calibrationWaitingForConfirmation = new Sms(receivedSms.phoneNumber, reply, System.currentTimeMillis(), passCode)); - calibrationWaitingForConfirmation.calibrationRequested = amount; - FabricPrivacy.getInstance().logCustom(new CustomEvent("SMS_Cal")); - } else { - reply = MainApp.gs(R.string.smscommunicator_remotecalibrationnotallowed); - sendSMS(new Sms(receivedSms.phoneNumber, reply, System.currentTimeMillis())); - } - } - break; - default: // expect passCode here - if (bolusWaitingForConfirmation != null && !bolusWaitingForConfirmation.processed && - bolusWaitingForConfirmation.confirmCode.equals(splited[0]) && System.currentTimeMillis() - bolusWaitingForConfirmation.date < Constants.SMS_CONFIRM_TIMEOUT) { - bolusWaitingForConfirmation.processed = true; - DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); - detailedBolusInfo.insulin = bolusWaitingForConfirmation.bolusRequested; - detailedBolusInfo.source = Source.USER; - ConfigBuilderPlugin.getPlugin().getCommandQueue().bolus(detailedBolusInfo, new Callback() { - @Override - public void run() { - PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump(); - if (result.success) { - SystemClock.sleep(T.secs(15).msecs()); // wait some time to get history - String reply = String.format(MainApp.gs(R.string.smscommunicator_bolusdelivered), result.bolusDelivered); - if (pump != null) - reply += "\n" + pump.shortStatus(true); - lastRemoteBolusTime = new Date(); - sendSMSToAllNumbers(new Sms(receivedSms.phoneNumber, reply, System.currentTimeMillis())); - } else { - SystemClock.sleep(T.secs(60).msecs()); // wait some time to get history - String reply = MainApp.gs(R.string.smscommunicator_bolusfailed); - if (pump != null) - reply += "\n" + pump.shortStatus(true); - sendSMS(new Sms(receivedSms.phoneNumber, reply, System.currentTimeMillis())); - } - } - }); - } else if (tempBasalWaitingForConfirmation != null && !tempBasalWaitingForConfirmation.processed && - tempBasalWaitingForConfirmation.confirmCode.equals(splited[0]) && System.currentTimeMillis() - tempBasalWaitingForConfirmation.date < Constants.SMS_CONFIRM_TIMEOUT) { - tempBasalWaitingForConfirmation.processed = true; - Profile profile = ProfileFunctions.getInstance().getProfile(); - if (profile != null) - ConfigBuilderPlugin.getPlugin().getCommandQueue().tempBasalAbsolute(tempBasalWaitingForConfirmation.tempBasal, 30, true, profile, new Callback() { - @Override - public void run() { - if (result.success) { - String reply = String.format(MainApp.gs(R.string.smscommunicator_tempbasalset), result.absolute, result.duration); - reply += "\n" + ConfigBuilderPlugin.getPlugin().getActivePump().shortStatus(true); - sendSMSToAllNumbers(new Sms(receivedSms.phoneNumber, reply, System.currentTimeMillis())); - } else { - String reply = MainApp.gs(R.string.smscommunicator_tempbasalfailed); - reply += "\n" + ConfigBuilderPlugin.getPlugin().getActivePump().shortStatus(true); - sendSMS(new Sms(receivedSms.phoneNumber, reply, System.currentTimeMillis())); - } - } - }); - } else if (cancelTempBasalWaitingForConfirmation != null && !cancelTempBasalWaitingForConfirmation.processed && - cancelTempBasalWaitingForConfirmation.confirmCode.equals(splited[0]) && System.currentTimeMillis() - cancelTempBasalWaitingForConfirmation.date < Constants.SMS_CONFIRM_TIMEOUT) { - cancelTempBasalWaitingForConfirmation.processed = true; - ConfigBuilderPlugin.getPlugin().getCommandQueue().cancelTempBasal(true, new Callback() { - @Override - public void run() { - if (result.success) { - String reply = MainApp.gs(R.string.smscommunicator_tempbasalcanceled); - reply += "\n" + ConfigBuilderPlugin.getPlugin().getActivePump().shortStatus(true); - sendSMSToAllNumbers(new Sms(receivedSms.phoneNumber, reply, System.currentTimeMillis())); - } else { - String reply = MainApp.gs(R.string.smscommunicator_tempbasalcancelfailed); - reply += "\n" + ConfigBuilderPlugin.getPlugin().getActivePump().shortStatus(true); - sendSMS(new Sms(receivedSms.phoneNumber, reply, System.currentTimeMillis())); - } - } - }); - } else if (calibrationWaitingForConfirmation != null && !calibrationWaitingForConfirmation.processed && - calibrationWaitingForConfirmation.confirmCode.equals(splited[0]) && System.currentTimeMillis() - calibrationWaitingForConfirmation.date < Constants.SMS_CONFIRM_TIMEOUT) { - calibrationWaitingForConfirmation.processed = true; - boolean result = XdripCalibrations.sendIntent(calibrationWaitingForConfirmation.calibrationRequested); - if (result) { - reply = MainApp.gs(R.string.smscommunicator_calibrationsent); - sendSMSToAllNumbers(new Sms(receivedSms.phoneNumber, reply, System.currentTimeMillis())); - } else { - reply = MainApp.gs(R.string.smscommunicator_calibrationfailed); - sendSMS(new Sms(receivedSms.phoneNumber, reply, System.currentTimeMillis())); - } - } else if (suspendWaitingForConfirmation != null && !suspendWaitingForConfirmation.processed && - suspendWaitingForConfirmation.confirmCode.equals(splited[0]) && System.currentTimeMillis() - suspendWaitingForConfirmation.date < Constants.SMS_CONFIRM_TIMEOUT) { - suspendWaitingForConfirmation.processed = true; - final int dur = suspendWaitingForConfirmation.duration; - ConfigBuilderPlugin.getPlugin().getCommandQueue().cancelTempBasal(true, new Callback() { - @Override - public void run() { - if (result.success) { - LoopPlugin.getPlugin().suspendTo(System.currentTimeMillis() + dur * 60L * 1000); - NSUpload.uploadOpenAPSOffline(dur * 60); - MainApp.bus().post(new EventRefreshOverview("SMS_LOOP_SUSPENDED")); - String reply = MainApp.gs(R.string.smscommunicator_loopsuspended) + " " + - MainApp.gs(result.success ? R.string.smscommunicator_tempbasalcanceled : R.string.smscommunicator_tempbasalcancelfailed); - sendSMSToAllNumbers(new Sms(receivedSms.phoneNumber, reply, System.currentTimeMillis())); - } else { - String reply = MainApp.gs(R.string.smscommunicator_tempbasalcancelfailed); - reply += "\n" + ConfigBuilderPlugin.getPlugin().getActivePump().shortStatus(true); - sendSMS(new Sms(receivedSms.phoneNumber, reply, System.currentTimeMillis())); - } - } - }); - } else { - sendSMS(new Sms(receivedSms.phoneNumber, MainApp.gs(R.string.smscommunicator_unknowncommand), System.currentTimeMillis())); - } - resetWaitingMessages(); - break; - } - } - - MainApp.bus().post(new EventSmsCommunicatorUpdateGui()); - } - - public void sendNotificationToAllNumbers(String text) { - for (int i = 0; i < allowedNumbers.size(); i++) { - Sms sms = new Sms(allowedNumbers.get(i), text, System.currentTimeMillis()); - sendSMS(sms); - } - } - - private void sendSMSToAllNumbers(Sms sms) { - for (String number : allowedNumbers) { - sms.phoneNumber = number; - sendSMS(sms); - } - } - - private void sendSMS(Sms sms) { - SmsManager smsManager = SmsManager.getDefault(); - sms.text = stripAccents(sms.text); - if (sms.text.length() > 140) sms.text = sms.text.substring(0, 139); - try { - log.debug("Sending SMS to " + sms.phoneNumber + ": " + sms.text); - smsManager.sendTextMessage(sms.phoneNumber, null, sms.text, null, null); - messages.add(sms); - } catch (IllegalArgumentException e) { - Notification notification = new Notification(Notification.INVALID_PHONE_NUMBER, MainApp.gs(R.string.smscommunicator_invalidphonennumber), Notification.NORMAL); - MainApp.bus().post(new EventNewNotification(notification)); - } catch (java.lang.SecurityException e) { - Notification notification = new Notification(Notification.MISSING_SMS_PERMISSION, MainApp.gs(R.string.smscommunicator_missingsmspermission), Notification.NORMAL); - MainApp.bus().post(new EventNewNotification(notification)); - } - } - - private String generatePasscode() { - int startChar1 = 'A'; // on iphone 1st char is uppercase :) - String passCode = Character.toString((char) (startChar1 + Math.random() * ('z' - 'a' + 1))); - int startChar2 = Math.random() > 0.5 ? 'a' : 'A'; - passCode += Character.toString((char) (startChar2 + Math.random() * ('z' - 'a' + 1))); - int startChar3 = Math.random() > 0.5 ? 'a' : 'A'; - passCode += Character.toString((char) (startChar3 + Math.random() * ('z' - 'a' + 1))); - return passCode; - } - - private void resetWaitingMessages() { - tempBasalWaitingForConfirmation = null; - cancelTempBasalWaitingForConfirmation = null; - bolusWaitingForConfirmation = null; - calibrationWaitingForConfirmation = null; - suspendWaitingForConfirmation = null; - } - - private static String stripAccents(String s) { - s = Normalizer.normalize(s, Normalizer.Form.NFD); - s = s.replaceAll("[\\p{InCombiningDiacriticalMarks}]", ""); - return s; - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/events/EventSmsCommunicatorUpdateGui.java b/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/events/EventSmsCommunicatorUpdateGui.java deleted file mode 100644 index 02956a5d67..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/events/EventSmsCommunicatorUpdateGui.java +++ /dev/null @@ -1,9 +0,0 @@ -package info.nightscout.androidaps.plugins.SmsCommunicator.events; - -import info.nightscout.androidaps.events.EventUpdateGui; - -/** - * Created by mike on 05.08.2016. - */ -public class EventSmsCommunicatorUpdateGui extends EventUpdateGui { -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Source/SourceDexcomG5Plugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Source/SourceDexcomG5Plugin.java deleted file mode 100644 index 460e550b8e..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Source/SourceDexcomG5Plugin.java +++ /dev/null @@ -1,95 +0,0 @@ -package info.nightscout.androidaps.plugins.Source; - -import android.content.Intent; -import android.os.Bundle; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.db.BgReading; -import info.nightscout.androidaps.interfaces.BgSourceInterface; -import info.nightscout.androidaps.interfaces.PluginBase; -import info.nightscout.androidaps.interfaces.PluginDescription; -import info.nightscout.androidaps.interfaces.PluginType; -import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.NSClientInternal.NSUpload; -import info.nightscout.utils.SP; - -/** - * Created by mike on 28.11.2017. - */ - -public class SourceDexcomG5Plugin extends PluginBase implements BgSourceInterface { - private static Logger log = LoggerFactory.getLogger(L.BGSOURCE); - - private static SourceDexcomG5Plugin plugin = null; - - public static SourceDexcomG5Plugin getPlugin() { - if (plugin == null) - plugin = new SourceDexcomG5Plugin(); - return plugin; - } - - private SourceDexcomG5Plugin() { - super(new PluginDescription() - .mainType(PluginType.BGSOURCE) - .fragmentClass(BGSourceFragment.class.getName()) - .pluginName(R.string.DexcomG5) - .shortName(R.string.dexcomG5_shortname) - .preferencesId(R.xml.pref_dexcomg5) - .description(R.string.description_source_dexcom_g5) - ); - } - - @Override - public boolean advancedFilteringSupported() { - return true; - } - - @Override - public void handleNewData(Intent intent) { - // onHandleIntent Bundle{ data => [{"m_time":1511939180,"m_trend":"NotComputable","m_value":335}]; android.support.content.wakelockid => 95; }Bundle - - if (!isEnabled(PluginType.BGSOURCE)) return; - - Bundle bundle = intent.getExtras(); - if (bundle == null) return; - - BgReading bgReading = new BgReading(); - - String data = bundle.getString("data"); - if (L.isEnabled(L.BGSOURCE)) - log.debug("Received Dexcom Data", data); - - if (data == null) return; - - try { - JSONArray jsonArray = new JSONArray(data); - if (L.isEnabled(L.BGSOURCE)) - log.debug("Received Dexcom Data size:" + jsonArray.length()); - for (int i = 0; i < jsonArray.length(); i++) { - JSONObject json = jsonArray.getJSONObject(i); - bgReading.value = json.getInt("m_value"); - bgReading.direction = json.getString("m_trend"); - bgReading.date = json.getLong("m_time") * 1000L; - bgReading.raw = 0; - boolean isNew = MainApp.getDbHelper().createIfNotExists(bgReading, "DexcomG5"); - if (isNew && SP.getBoolean(R.string.key_dexcomg5_nsupload, false)) { - NSUpload.uploadBg(bgReading); - } - if (isNew && SP.getBoolean(R.string.key_dexcomg5_xdripupload, false)) { - NSUpload.sendToXdrip(bgReading); - } - } - - } catch (JSONException e) { - log.error("Exception: ", e); - } - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/dialogs/WizardInfoDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/dialogs/WizardInfoDialog.java deleted file mode 100644 index 25ffc946a2..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/dialogs/WizardInfoDialog.java +++ /dev/null @@ -1,88 +0,0 @@ -package info.nightscout.androidaps.plugins.Treatments.dialogs; - -import android.os.Bundle; -import android.support.v4.app.DialogFragment; -import android.view.LayoutInflater; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.ViewGroup; -import android.view.Window; -import android.view.WindowManager; -import android.widget.CheckBox; -import android.widget.TextView; - -import org.json.JSONObject; - -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.R; -import info.nightscout.utils.DecimalFormatter; -import info.nightscout.utils.JsonHelper; - -public class WizardInfoDialog extends DialogFragment implements OnClickListener { - JSONObject json; - - public WizardInfoDialog() { - super(); - } - - public void setData(JSONObject json) { - this.json = json; - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.treatments_wizardinfo_dialog, container, false); - - getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); - - view.findViewById(R.id.ok).setOnClickListener(this); - - // BG - ((TextView) view.findViewById(R.id.treatments_wizard_bg)).setText(DecimalFormatter.to1Decimal(JsonHelper.safeGetDouble(json, "bg")) + " ISF: " + DecimalFormatter.to1Decimal(JsonHelper.safeGetDouble(json, "isf"))); - ((TextView) view.findViewById(R.id.treatments_wizard_bginsulin)).setText(DecimalFormatter.to2Decimal(JsonHelper.safeGetDouble(json, "insulinbg")) + "U"); - ((CheckBox) view.findViewById(R.id.treatments_wizard_bgcheckbox)).setChecked(JsonHelper.safeGetBoolean(json, "insulinbgused")); - ((CheckBox) view.findViewById(R.id.treatments_wizard_ttcheckbox)).setChecked(JsonHelper.safeGetBoolean(json, "ttused")); - // Trend - ((TextView) view.findViewById(R.id.treatments_wizard_bgtrend)).setText(JsonHelper.safeGetString(json, "trend")); - ((TextView) view.findViewById(R.id.treatments_wizard_bgtrendinsulin)).setText(DecimalFormatter.to2Decimal(JsonHelper.safeGetDouble(json, "insulintrend")) + "U"); - ((CheckBox) view.findViewById(R.id.treatments_wizard_bgtrendcheckbox)).setChecked(JsonHelper.safeGetBoolean(json, "trendused")); - // COB - ((TextView) view.findViewById(R.id.treatments_wizard_cob)).setText(DecimalFormatter.to0Decimal(JsonHelper.safeGetDouble(json, "cob")) + "g IC: " + DecimalFormatter.to1Decimal(JsonHelper.safeGetDouble(json, "ic"))); - ((TextView) view.findViewById(R.id.treatments_wizard_cobinsulin)).setText(DecimalFormatter.to2Decimal(JsonHelper.safeGetDouble(json, "insulincob")) + "U"); - ((CheckBox) view.findViewById(R.id.treatments_wizard_cobcheckbox)).setChecked(JsonHelper.safeGetBoolean(json, "cobused")); - // Bolus IOB - ((TextView) view.findViewById(R.id.treatments_wizard_bolusiobinsulin)).setText(DecimalFormatter.to2Decimal(JsonHelper.safeGetDouble(json, "bolusiob")) + "U"); - ((CheckBox) view.findViewById(R.id.treatments_wizard_bolusiobcheckbox)).setChecked(JsonHelper.safeGetBoolean(json, "bolusiobused")); - // Basal IOB - ((TextView) view.findViewById(R.id.treatments_wizard_basaliobinsulin)).setText(DecimalFormatter.to2Decimal(JsonHelper.safeGetDouble(json, "basaliob")) + "U"); - ((CheckBox) view.findViewById(R.id.treatments_wizard_basaliobcheckbox)).setChecked(JsonHelper.safeGetBoolean(json, "basaliobused")); - // Superbolus - ((TextView) view.findViewById(R.id.treatments_wizard_sbinsulin)).setText(DecimalFormatter.to2Decimal(JsonHelper.safeGetDouble(json, "insulinsuperbolus")) + "U"); - ((CheckBox) view.findViewById(R.id.treatments_wizard_sbcheckbox)).setChecked(JsonHelper.safeGetBoolean(json, "superbolusused")); - // Carbs - ((TextView) view.findViewById(R.id.treatments_wizard_carbs)).setText(DecimalFormatter.to0Decimal(JsonHelper.safeGetDouble(json, "carbs")) + "g IC: " + DecimalFormatter.to1Decimal(JsonHelper.safeGetDouble(json, "ic"))); - ((TextView) view.findViewById(R.id.treatments_wizard_carbsinsulin)).setText(DecimalFormatter.to2Decimal(JsonHelper.safeGetDouble(json, "insulincarbs")) + "U"); - // Correction - ((TextView) view.findViewById(R.id.treatments_wizard_correctioninsulin)).setText(DecimalFormatter.to2Decimal(JsonHelper.safeGetDouble(json, "othercorrection")) + "U"); - // Profile - ((TextView) view.findViewById(R.id.treatments_wizard_profile)).setText(JsonHelper.safeGetString(json, "profile")); - // Notes - ((TextView) view.findViewById(R.id.treatments_wizard_notes)).setText(JsonHelper.safeGetString(json, "notes")); - // Total - ((TextView) view.findViewById(R.id.treatments_wizard_totalinsulin)).setText(DecimalFormatter.to2Decimal(JsonHelper.safeGetDouble(json, "insulin")) + "U"); - - setCancelable(true); - return view; - } - - @Override - public synchronized void onClick(View view) { - switch (view.getId()) { - case R.id.ok: - dismiss(); - break; - } - } - -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/ProfileViewerDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/ProfileViewerDialog.java deleted file mode 100644 index c2263d81b5..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/ProfileViewerDialog.java +++ /dev/null @@ -1,139 +0,0 @@ -package info.nightscout.androidaps.plugins.Treatments.fragments; - -import android.os.Bundle; -import android.support.v4.app.DialogFragment; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Button; -import android.widget.LinearLayout; -import android.widget.TextView; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import butterknife.BindView; -import butterknife.ButterKnife; -import butterknife.Unbinder; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.data.Profile; -import info.nightscout.androidaps.db.ProfileSwitch; -import info.nightscout.androidaps.plugins.PumpDanaR.Dialogs.ProfileViewDialog; -import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.DecimalFormatter; - -/** - * Created by adrian on 17/08/17. - */ - -public class ProfileViewerDialog extends DialogFragment { - - private long time; - - @BindView(R.id.profileview_noprofile) - TextView noProfile; - @BindView(R.id.profileview_invalidprofile) - TextView invalidProfile; - @BindView(R.id.profileview_units) - TextView units; - @BindView(R.id.profileview_dia) - TextView dia; - @BindView(R.id.profileview_activeprofile) - TextView activeProfile; - @BindView(R.id.profileview_ic) - TextView ic; - @BindView(R.id.profileview_isf) - TextView isf; - @BindView(R.id.profileview_basal) - TextView basal; - @BindView(R.id.profileview_target) - TextView target; - @BindView(R.id.profileview_datedelimiter) - View dateDelimiter; - @BindView(R.id.profileview_datelayout) - LinearLayout dateLayout; - @BindView(R.id.profileview_date) - TextView dateTextView; - @BindView(R.id.profileview_reload) - Button refreshButton; - @BindView(R.id.basal_graph) - ProfileGraph basalGraph; - - private Unbinder unbinder; - - public static ProfileViewerDialog newInstance(long time) { - ProfileViewerDialog dialog = new ProfileViewerDialog(); - - Bundle args = new Bundle(); - args.putLong("time", time); - dialog.setArguments(args); - - return dialog; - } - - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - time = getArguments().getLong("time"); - } - - @Override - public void onDestroyView() { - super.onDestroyView(); - if (unbinder != null) - unbinder.unbind(); - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.profileviewer_fragment, container, false); - - unbinder = ButterKnife.bind(this, view); - - refreshButton.setVisibility(View.GONE); - dateDelimiter.setVisibility(View.VISIBLE); - dateLayout.setVisibility(View.VISIBLE); - - setContent(); - return view; - } - - @Override - public void onResume() { - ViewGroup.LayoutParams params = getDialog().getWindow().getAttributes(); - params.width = ViewGroup.LayoutParams.MATCH_PARENT; - params.height = ViewGroup.LayoutParams.MATCH_PARENT; - getDialog().getWindow().setAttributes((android.view.WindowManager.LayoutParams) params); - super.onResume(); - } - - private void setContent() { - Profile profile = null; - ProfileSwitch profileSwitch = TreatmentsPlugin.getPlugin().getProfileSwitchFromHistory(time); - if (profileSwitch != null && profileSwitch.profileJson != null) { - profile = profileSwitch.getProfileObject(); - } - if (profile != null) { - noProfile.setVisibility(View.GONE); - units.setText(profile.getUnits()); - dia.setText(DecimalFormatter.to2Decimal(profile.getDia()) + " h"); - activeProfile.setText(profileSwitch.getCustomizedName()); - dateTextView.setText(DateUtil.dateAndTimeString(profileSwitch.date)); - ic.setText(profile.getIcList()); - isf.setText(profile.getIsfList()); - basal.setText(profile.getBasalList()); - target.setText(profile.getTargetList()); - basalGraph.show(profile); - - if (profile.isValid("ProfileViewDialog")) - invalidProfile.setVisibility(View.GONE); - else - invalidProfile.setVisibility(View.VISIBLE); - } else { - noProfile.setVisibility(View.VISIBLE); - } - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Wear/WearPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Wear/WearPlugin.java deleted file mode 100644 index 72b2397213..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Wear/WearPlugin.java +++ /dev/null @@ -1,217 +0,0 @@ -package info.nightscout.androidaps.plugins.Wear; - -import android.content.Context; -import android.content.Intent; - -import com.squareup.otto.Subscribe; - -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.events.EventBolusRequested; -import info.nightscout.androidaps.events.EventExtendedBolusChange; -import info.nightscout.androidaps.events.EventNewBG; -import info.nightscout.androidaps.events.EventNewBasalProfile; -import info.nightscout.androidaps.events.EventPreferenceChange; -import info.nightscout.androidaps.events.EventRefreshOverview; -import info.nightscout.androidaps.events.EventTempBasalChange; -import info.nightscout.androidaps.events.EventTreatmentChange; -import info.nightscout.androidaps.interfaces.PluginBase; -import info.nightscout.androidaps.interfaces.PluginDescription; -import info.nightscout.androidaps.interfaces.PluginType; -import info.nightscout.androidaps.plugins.Loop.LoopPlugin; -import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateGui; -import info.nightscout.androidaps.plugins.Overview.events.EventDismissBolusprogressIfRunning; -import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress; -import info.nightscout.androidaps.plugins.Wear.wearintegration.WatchUpdaterService; -import info.nightscout.utils.SP; - -/** - * Created by adrian on 17/11/16. - */ - -public class WearPlugin extends PluginBase { - - private static WatchUpdaterService watchUS; - private final Context ctx; - - private static WearPlugin wearPlugin; - - public static WearPlugin getPlugin() { - return wearPlugin; - } - - public static WearPlugin initPlugin(Context ctx) { - - if (wearPlugin == null) { - wearPlugin = new WearPlugin(ctx); - } - - return wearPlugin; - } - - WearPlugin(Context ctx) { - super(new PluginDescription() - .mainType(PluginType.GENERAL) - .fragmentClass(WearFragment.class.getName()) - .pluginName(R.string.wear) - .shortName(R.string.wear_shortname) - .preferencesId(R.xml.pref_wear) - .description(R.string.description_wear) - ); - this.ctx = ctx; - } - - @Override - protected void onStart() { - MainApp.bus().register(this); - if (watchUS != null) { - watchUS.setSettings(); - } - super.onStart(); - } - - @Override - protected void onStop() { - MainApp.bus().unregister(this); - } - - private void sendDataToWatch(boolean status, boolean basals, boolean bgValue) { - if (isEnabled(getType())) { //only start service when this plugin is enabled - - if (bgValue) { - ctx.startService(new Intent(ctx, WatchUpdaterService.class)); - } - - if (basals) { - ctx.startService(new Intent(ctx, WatchUpdaterService.class).setAction(WatchUpdaterService.ACTION_SEND_BASALS)); - } - - if (status) { - ctx.startService(new Intent(ctx, WatchUpdaterService.class).setAction(WatchUpdaterService.ACTION_SEND_STATUS)); - } - } - } - - void resendDataToWatch() { - ctx.startService(new Intent(ctx, WatchUpdaterService.class).setAction(WatchUpdaterService.ACTION_RESEND)); - } - - void openSettings() { - ctx.startService(new Intent(ctx, WatchUpdaterService.class).setAction(WatchUpdaterService.ACTION_OPEN_SETTINGS)); - } - - void requestNotificationCancel(String actionstring) { - Intent intent = new Intent(ctx, WatchUpdaterService.class).setAction(WatchUpdaterService.ACTION_CANCEL_NOTIFICATION); - intent.putExtra("actionstring", actionstring); - ctx.startService(intent); - } - - - @Subscribe - public void onStatusEvent(final EventPreferenceChange ev) { - // possibly new high or low mark - resendDataToWatch(); - // status may be formated differently - sendDataToWatch(true, false, false); - } - - @Subscribe - public void onStatusEvent(final EventTreatmentChange ev) { - sendDataToWatch(true, true, false); - } - - @Subscribe - public void onStatusEvent(final EventTempBasalChange ev) { - sendDataToWatch(true, true, false); - } - - @Subscribe - public void onStatusEvent(final EventOpenAPSUpdateGui ev) { - sendDataToWatch(true, true, false); - } - - @Subscribe - public void onStatusEvent(final EventExtendedBolusChange ev) { - sendDataToWatch(true, true, false); - } - - @Subscribe - public void onStatusEvent(final EventNewBG ev) { - sendDataToWatch(true, true, true); - } - - @Subscribe - public void onStatusEvent(final EventNewBasalProfile ev) { - sendDataToWatch(false, true, false); - } - - @Subscribe - public void onStatusEvent(final EventRefreshOverview ev) { - if (WatchUpdaterService.shouldReportLoopStatus(LoopPlugin.getPlugin().isEnabled(PluginType.LOOP))) { - sendDataToWatch(true, false, false); - } - } - - - @Subscribe - public void onStatusEvent(final EventOverviewBolusProgress ev) { - if (!ev.isSMB() || SP.getBoolean("wear_notifySMB", true)) { - Intent intent = new Intent(ctx, WatchUpdaterService.class).setAction(WatchUpdaterService.ACTION_SEND_BOLUSPROGRESS); - intent.putExtra("progresspercent", ev.percent); - intent.putExtra("progressstatus", ev.status); - ctx.startService(intent); - } - } - - @Subscribe - public void onStatusEvent(final EventBolusRequested ev) { - String status = String.format(MainApp.gs(R.string.bolusrequested), ev.getAmount()); - Intent intent = new Intent(ctx, WatchUpdaterService.class).setAction(WatchUpdaterService.ACTION_SEND_BOLUSPROGRESS); - intent.putExtra("progresspercent", 0); - intent.putExtra("progressstatus", status); - ctx.startService(intent); - - } - - @Subscribe - public void onStatusEvent(final EventDismissBolusprogressIfRunning ev) { - if (ev.result == null) return; - - String status; - if (ev.result.success) { - status = MainApp.gs(R.string.success); - } else { - status = MainApp.gs(R.string.nosuccess); - } - Intent intent = new Intent(ctx, WatchUpdaterService.class).setAction(WatchUpdaterService.ACTION_SEND_BOLUSPROGRESS); - intent.putExtra("progresspercent", 100); - intent.putExtra("progressstatus", status); - ctx.startService(intent); - } - - public void requestActionConfirmation(String title, String message, String actionstring) { - - Intent intent = new Intent(ctx, WatchUpdaterService.class).setAction(WatchUpdaterService.ACTION_SEND_ACTIONCONFIRMATIONREQUEST); - intent.putExtra("title", title); - intent.putExtra("message", message); - intent.putExtra("actionstring", actionstring); - ctx.startService(intent); - } - - public void requestChangeConfirmation(String title, String message, String actionstring) { - - Intent intent = new Intent(ctx, WatchUpdaterService.class).setAction(WatchUpdaterService.ACTION_SEND_CHANGECONFIRMATIONREQUEST); - intent.putExtra("title", title); - intent.putExtra("message", message); - intent.putExtra("actionstring", actionstring); - ctx.startService(intent); - } - - public static void registerWatchUpdaterService(WatchUpdaterService wus) { - watchUS = wus; - } - - public static void unRegisterWatchUpdaterService() { - watchUS = null; - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Wear/wearintegration/SendToDataLayerThread.java b/app/src/main/java/info/nightscout/androidaps/plugins/Wear/wearintegration/SendToDataLayerThread.java deleted file mode 100644 index 02c74defca..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Wear/wearintegration/SendToDataLayerThread.java +++ /dev/null @@ -1,52 +0,0 @@ -package info.nightscout.androidaps.plugins.Wear.wearintegration; - -import android.os.AsyncTask; -import android.util.Log; - -import com.google.android.gms.common.api.GoogleApiClient; -import com.google.android.gms.wearable.DataApi; -import com.google.android.gms.wearable.DataMap; -import com.google.android.gms.wearable.Node; -import com.google.android.gms.wearable.NodeApi; -import com.google.android.gms.wearable.PutDataMapRequest; -import com.google.android.gms.wearable.PutDataRequest; -import com.google.android.gms.wearable.Wearable; - -import java.util.concurrent.TimeUnit; - -/** - * Created by emmablack on 12/26/14. - */ -class SendToDataLayerThread extends AsyncTask { - private GoogleApiClient googleApiClient; - private static final String TAG = "SendDataThread"; - String path; - - SendToDataLayerThread(String path, GoogleApiClient pGoogleApiClient) { - this.path = path; - googleApiClient = pGoogleApiClient; - } - - @Override - protected Void doInBackground(DataMap... params) { - try { - final NodeApi.GetConnectedNodesResult nodes = Wearable.NodeApi.getConnectedNodes(googleApiClient).await(15, TimeUnit.SECONDS); - for (Node node : nodes.getNodes()) { - for (DataMap dataMap : params) { - PutDataMapRequest putDMR = PutDataMapRequest.create(path); - putDMR.getDataMap().putAll(dataMap); - PutDataRequest request = putDMR.asPutDataRequest(); - DataApi.DataItemResult result = Wearable.DataApi.putDataItem(googleApiClient, request).await(15, TimeUnit.SECONDS); - if (result.getStatus().isSuccess()) { - Log.d(TAG, "DataMap: " + dataMap + " sent to: " + node.getDisplayName()); - } else { - Log.d(TAG, "ERROR: failed to send DataMap"); - } - } - } - } catch (Exception e) { - Log.e(TAG, "Got exception sending data to wear: " + e.toString()); - } - return null; - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/APSResult.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/APSResult.java similarity index 97% rename from app/src/main/java/info/nightscout/androidaps/plugins/Loop/APSResult.java rename to app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/APSResult.java index 3678617c96..b3b0c091d5 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/APSResult.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/APSResult.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.Loop; +package info.nightscout.androidaps.plugins.aps.loop; import android.text.Html; import android.text.Spanned; @@ -22,11 +22,11 @@ import info.nightscout.androidaps.interfaces.Constraint; import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions; -import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; -import info.nightscout.utils.DecimalFormatter; -import info.nightscout.utils.SP; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; +import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; +import info.nightscout.androidaps.utils.DecimalFormatter; +import info.nightscout.androidaps.utils.SP; /** * Created by mike on 09.06.2016. diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/DeviceStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/DeviceStatus.java similarity index 99% rename from app/src/main/java/info/nightscout/androidaps/plugins/Loop/DeviceStatus.java rename to app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/DeviceStatus.java index 2c2bb1a2ee..69afe3d8e7 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/DeviceStatus.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/DeviceStatus.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.Loop; +package info.nightscout.androidaps.plugins.aps.loop; import org.json.JSONException; import org.json.JSONObject; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopFragment.kt new file mode 100644 index 0000000000..b7549fcfed --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopFragment.kt @@ -0,0 +1,109 @@ +package info.nightscout.androidaps.plugins.aps.loop + + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import info.nightscout.androidaps.MainApp +import info.nightscout.androidaps.R +import info.nightscout.androidaps.interfaces.Constraint +import info.nightscout.androidaps.plugins.aps.loop.events.EventLoopSetLastRunGui +import info.nightscout.androidaps.plugins.aps.loop.events.EventLoopUpdateGui +import info.nightscout.androidaps.plugins.bus.RxBus +import info.nightscout.androidaps.utils.* +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.disposables.CompositeDisposable +import kotlinx.android.synthetic.main.loop_fragment.* + +class LoopFragment : Fragment() { + + private var disposable: CompositeDisposable = CompositeDisposable() + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle?): View? { + return inflater.inflate(R.layout.loop_fragment, container, false) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + loop_run.setOnClickListener { + loop_lastrun.text = MainApp.gs(R.string.executing) + Thread { LoopPlugin.getPlugin().invoke("Loop button", true) }.start() + } + } + + @Synchronized + override fun onResume() { + super.onResume() + disposable += RxBus + .toObservable(EventLoopUpdateGui::class.java) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe({ + updateGUI() + }, { + FabricPrivacy.logException(it) + }) + + disposable += RxBus + .toObservable(EventLoopSetLastRunGui::class.java) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe({ + clearGUI() + loop_lastrun.text = it.text + }, { + FabricPrivacy.logException(it) + }) + + updateGUI() + SP.putBoolean(R.string.key_objectiveuseloop, true) + } + + @Synchronized + override fun onPause() { + super.onPause() + disposable.clear() + } + + @Synchronized + fun updateGUI() { + if (loop_request == null) return + LoopPlugin.lastRun?.let { + loop_request.text = it.request?.toSpanned() ?: "" + loop_constraintsprocessed.text = it.constraintsProcessed?.toSpanned() ?: "" + loop_source.text = it.source ?: "" + loop_lastrun.text = it.lastAPSRun?.let { lastRun -> DateUtil.dateAndTimeString(lastRun.time) } + ?: "" + loop_lastenact.text = it.lastAPSRun?.let { lastEnact -> DateUtil.dateAndTimeString(lastEnact.time) } + ?: "" + loop_tbrsetbypump.text = it.tbrSetByPump?.let { tbrSetByPump -> HtmlHelper.fromHtml(tbrSetByPump.toHtml()) } + ?: "" + loop_smbsetbypump.text = it.smbSetByPump?.let { smbSetByPump -> HtmlHelper.fromHtml(smbSetByPump.toHtml()) } + ?: "" + + val constraints = + it.constraintsProcessed?.let { constraintsProcessed -> + val allConstraints = Constraint(0.0) + constraintsProcessed.rateConstraint?.let { rateConstraint -> allConstraints.copyReasons(rateConstraint) } + constraintsProcessed.smbConstraint?.let { smbConstraint -> allConstraints.copyReasons(smbConstraint) } + allConstraints.mostLimitedReasons + } ?: "" + loop_constraints.text = constraints + } + } + + @Synchronized + private fun clearGUI() { + if (loop_request == null) return + loop_request.text = "" + loop_constraints.text = "" + loop_constraintsprocessed.text = "" + loop_source.text = "" + loop_lastrun.text = "" + loop_lastenact.text = "" + loop_tbrsetbypump.text = "" + loop_smbsetbypump.text = "" + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.java similarity index 79% rename from app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopPlugin.java rename to app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.java index 0b20ddf582..f339bd3771 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.Loop; +package info.nightscout.androidaps.plugins.aps.loop; import android.annotation.SuppressLint; import android.app.Notification; @@ -10,11 +10,9 @@ import android.content.Context; import android.content.Intent; import android.os.Build; import android.os.SystemClock; -import android.support.annotation.NonNull; -import android.support.v4.app.NotificationCompat; -import com.crashlytics.android.answers.CustomEvent; -import com.squareup.otto.Subscribe; +import androidx.annotation.NonNull; +import androidx.core.app.NotificationCompat; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -33,7 +31,9 @@ import info.nightscout.androidaps.db.CareportalEvent; import info.nightscout.androidaps.db.DatabaseHelper; import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.TemporaryBasal; +import info.nightscout.androidaps.events.EventAcceptOpenLoopChange; import info.nightscout.androidaps.events.EventNewBG; +import info.nightscout.androidaps.events.EventTempTargetChange; import info.nightscout.androidaps.interfaces.APSInterface; import info.nightscout.androidaps.interfaces.Constraint; import info.nightscout.androidaps.interfaces.PluginBase; @@ -43,30 +43,33 @@ import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.interfaces.TreatmentsInterface; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.ConstraintsObjectives.ObjectivesPlugin; -import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions; -import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventAutosensCalculationFinished; -import info.nightscout.androidaps.plugins.Loop.events.EventLoopSetLastRunGui; -import info.nightscout.androidaps.plugins.Loop.events.EventLoopUpdateGui; -import info.nightscout.androidaps.plugins.Loop.events.EventNewOpenLoopNotification; -import info.nightscout.androidaps.plugins.NSClientInternal.NSUpload; -import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin; -import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; -import info.nightscout.androidaps.plugins.Wear.ActionStringHandler; -import info.nightscout.androidaps.events.EventAcceptOpenLoopChange; +import info.nightscout.androidaps.plugins.aps.loop.events.EventLoopSetLastRunGui; +import info.nightscout.androidaps.plugins.aps.loop.events.EventLoopUpdateGui; +import info.nightscout.androidaps.plugins.aps.loop.events.EventNewOpenLoopNotification; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; +import info.nightscout.androidaps.plugins.general.nsclient.NSUpload; +import info.nightscout.androidaps.plugins.general.overview.dialogs.ErrorHelperActivity; +import info.nightscout.androidaps.plugins.general.wear.ActionStringHandler; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutosensCalculationFinished; +import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin; +import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; import info.nightscout.androidaps.queue.Callback; import info.nightscout.androidaps.queue.commands.Command; -import info.nightscout.utils.FabricPrivacy; -import info.nightscout.utils.SP; -import info.nightscout.utils.T; -import info.nightscout.utils.ToastUtils; +import info.nightscout.androidaps.utils.FabricPrivacy; +import info.nightscout.androidaps.utils.SP; +import info.nightscout.androidaps.utils.T; +import info.nightscout.androidaps.utils.ToastUtils; +import io.reactivex.disposables.CompositeDisposable; +import io.reactivex.schedulers.Schedulers; /** * Created by mike on 05.08.2016. */ public class LoopPlugin extends PluginBase { private static Logger log = LoggerFactory.getLogger(L.APS); + private CompositeDisposable disposable = new CompositeDisposable(); private static final String CHANNEL_ID = "AndroidAPS-Openloop"; @@ -115,9 +118,39 @@ public class LoopPlugin extends PluginBase { @Override protected void onStart() { - MainApp.bus().register(this); createNotificationChannel(); super.onStart(); + disposable.add(RxBus.INSTANCE + .toObservable(EventTempTargetChange.class) + .observeOn(Schedulers.io()) + .subscribe(event -> { + invoke("EventTempTargetChange", true); + }, FabricPrivacy::logException) + ); + /** + * This method is triggered once autosens calculation has completed, so the LoopPlugin + * has current data to work with. However, autosens calculation can be triggered by multiple + * sources and currently only a new BG should trigger a loop run. Hence we return early if + * the event causing the calculation is not EventNewBg. + *

+ */ + disposable.add(RxBus.INSTANCE + .toObservable(EventAutosensCalculationFinished.class) + .observeOn(Schedulers.io()) + .subscribe(event -> { + // Autosens calculation not triggered by a new BG + if (!(event.getCause() instanceof EventNewBG)) return; + + BgReading bgReading = DatabaseHelper.actualBg(); + // BG outdated + if (bgReading == null) return; + // already looped with that value + if (bgReading.date <= lastBgTriggeredRun) return; + + lastBgTriggeredRun = bgReading.date; + invoke("AutosenseCalculation for " + bgReading, true); + }, FabricPrivacy::logException) + ); } private void createNotificationChannel() { @@ -134,8 +167,8 @@ public class LoopPlugin extends PluginBase { @Override protected void onStop() { + disposable.clear(); super.onStop(); - MainApp.bus().unregister(this); } @Override @@ -144,33 +177,6 @@ public class LoopPlugin extends PluginBase { return pump == null || pump.getPumpDescription().isTempBasalCapable; } - /** - * This method is triggered once autosens calculation has completed, so the LoopPlugin - * has current data to work with. However, autosens calculation can be triggered by multiple - * sources and currently only a new BG should trigger a loop run. Hence we return early if - * the event causing the calculation is not EventNewBg. - *

- */ - @Subscribe - public void onStatusEvent(final EventAutosensCalculationFinished ev) { - if (!(ev.cause instanceof EventNewBG)) { - // Autosens calculation not triggered by a new BG - return; - } - BgReading bgReading = DatabaseHelper.actualBg(); - if (bgReading == null) { - // BG outdated - return; - } - if (bgReading.date <= lastBgTriggeredRun) { - // already looped with that value - return; - } - - lastBgTriggeredRun = bgReading.date; - invoke("AutosenseCalculation for " + bgReading, true); - } - public long suspendedTo() { return loopSuspendedTill; } @@ -272,7 +278,7 @@ public class LoopPlugin extends PluginBase { String message = MainApp.gs(R.string.loopdisabled) + "\n" + loopEnabled.getReasons(); if (L.isEnabled(L.APS)) log.debug(message); - MainApp.bus().post(new EventLoopSetLastRunGui(message)); + RxBus.INSTANCE.send(new EventLoopSetLastRunGui(message)); return; } final PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump(); @@ -283,10 +289,10 @@ public class LoopPlugin extends PluginBase { Profile profile = ProfileFunctions.getInstance().getProfile(); - if (!ProfileFunctions.getInstance().isProfileValid("Loop")) { + if (profile == null || !ProfileFunctions.getInstance().isProfileValid("Loop")) { if (L.isEnabled(L.APS)) log.debug(MainApp.gs(R.string.noprofileselected)); - MainApp.bus().post(new EventLoopSetLastRunGui(MainApp.gs(R.string.noprofileselected))); + RxBus.INSTANCE.send(new EventLoopSetLastRunGui(MainApp.gs(R.string.noprofileselected))); return; } @@ -301,7 +307,7 @@ public class LoopPlugin extends PluginBase { // Check if we have any result if (result == null) { - MainApp.bus().post(new EventLoopSetLastRunGui(MainApp.gs(R.string.noapsselected))); + RxBus.INSTANCE.send(new EventLoopSetLastRunGui(MainApp.gs(R.string.noapsselected))); return; } @@ -343,14 +349,14 @@ public class LoopPlugin extends PluginBase { if (isSuspended()) { if (L.isEnabled(L.APS)) log.debug(MainApp.gs(R.string.loopsuspended)); - MainApp.bus().post(new EventLoopSetLastRunGui(MainApp.gs(R.string.loopsuspended))); + RxBus.INSTANCE.send(new EventLoopSetLastRunGui(MainApp.gs(R.string.loopsuspended))); return; } if (pump.isSuspended()) { if (L.isEnabled(L.APS)) log.debug(MainApp.gs(R.string.pumpsuspended)); - MainApp.bus().post(new EventLoopSetLastRunGui(MainApp.gs(R.string.pumpsuspended))); + RxBus.INSTANCE.send(new EventLoopSetLastRunGui(MainApp.gs(R.string.pumpsuspended))); return; } @@ -366,8 +372,8 @@ public class LoopPlugin extends PluginBase { lastRun.tbrSetByPump = waiting; if (resultAfterConstraints.bolusRequested) lastRun.smbSetByPump = waiting; - MainApp.bus().post(new EventLoopUpdateGui()); - FabricPrivacy.getInstance().logCustom(new CustomEvent("APSRequest")); + RxBus.INSTANCE.send(new EventLoopUpdateGui()); + FabricPrivacy.getInstance().logCustom("APSRequest"); applyTBRRequest(resultAfterConstraints, profile, new Callback() { @Override public void run() { @@ -386,13 +392,12 @@ public class LoopPlugin extends PluginBase { SystemClock.sleep(1000); LoopPlugin.getPlugin().invoke("tempBasalFallback", allowNotification, true); }).start(); - FabricPrivacy.getInstance().logCustom(new CustomEvent("Loop_Run_TempBasalFallback")); } - MainApp.bus().post(new EventLoopUpdateGui()); + RxBus.INSTANCE.send(new EventLoopUpdateGui()); } }); } - MainApp.bus().post(new EventLoopUpdateGui()); + RxBus.INSTANCE.send(new EventLoopUpdateGui()); } }); } else { @@ -409,7 +414,7 @@ public class LoopPlugin extends PluginBase { .setAutoCancel(true) .setPriority(Notification.PRIORITY_HIGH) .setCategory(Notification.CATEGORY_ALARM) - .setVisibility(Notification.VISIBILITY_PUBLIC); + .setVisibility(NotificationCompat.VISIBILITY_PUBLIC); if (SP.getBoolean("wearcontrol", false)) { builder.setLocalOnly(true); } @@ -433,7 +438,7 @@ public class LoopPlugin extends PluginBase { (NotificationManager) MainApp.instance().getSystemService(Context.NOTIFICATION_SERVICE); // mId allows you to update the notification later on. mNotificationManager.notify(Constants.notificationID, builder.build()); - MainApp.bus().post(new EventNewOpenLoopNotification()); + RxBus.INSTANCE.send(new EventNewOpenLoopNotification()); // Send to Wear ActionStringHandler.handleInitiate("changeRequest"); @@ -446,7 +451,7 @@ public class LoopPlugin extends PluginBase { } } - MainApp.bus().post(new EventLoopUpdateGui()); + RxBus.INSTANCE.send(new EventLoopUpdateGui()); } finally { if (L.isEnabled(L.APS)) log.debug("invoke end"); @@ -464,16 +469,12 @@ public class LoopPlugin extends PluginBase { lastRun.lastEnact = new Date(); lastRun.lastOpenModeAccept = new Date(); NSUpload.uploadDeviceStatus(); - ObjectivesPlugin objectivesPlugin = MainApp.getSpecificPlugin(ObjectivesPlugin.class); - if (objectivesPlugin != null) { - ObjectivesPlugin.getPlugin().manualEnacts++; - ObjectivesPlugin.getPlugin().saveProgress(); - } + SP.incInt(R.string.key_ObjectivesmanualEnacts); } - MainApp.bus().post(new EventAcceptOpenLoopChange()); + RxBus.INSTANCE.send(new EventAcceptOpenLoopChange()); } }); - FabricPrivacy.getInstance().logCustom(new CustomEvent("AcceptTemp")); + FabricPrivacy.getInstance().logCustom("AcceptTemp"); } /** @@ -639,20 +640,48 @@ public class LoopPlugin extends PluginBase { TreatmentsInterface activeTreatments = TreatmentsPlugin.getPlugin(); LoopPlugin.getPlugin().disconnectTo(System.currentTimeMillis() + durationInMinutes * 60 * 1000L); - ConfigBuilderPlugin.getPlugin().getCommandQueue().tempBasalPercent(0, durationInMinutes, true, profile, new Callback() { - @Override - public void run() { - if (!result.success) { - ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.tempbasaldeliveryerror)); + + if (pump.getPumpDescription().tempBasalStyle == PumpDescription.ABSOLUTE) { + ConfigBuilderPlugin.getPlugin().getCommandQueue().tempBasalAbsolute(0, durationInMinutes, true, profile, new Callback() { + @Override + public void run() { + if (!result.success) { + Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class); + i.putExtra("soundid", R.raw.boluserror); + i.putExtra("status", result.comment); + i.putExtra("title", MainApp.gs(R.string.tempbasaldeliveryerror)); + i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + MainApp.instance().startActivity(i); + } } - } - }); + }); + } else { + ConfigBuilderPlugin.getPlugin().getCommandQueue().tempBasalPercent(0, durationInMinutes, true, profile, new Callback() { + @Override + public void run() { + if (!result.success) { + Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class); + i.putExtra("soundid", R.raw.boluserror); + i.putExtra("status", result.comment); + i.putExtra("title", MainApp.gs(R.string.tempbasaldeliveryerror)); + i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + MainApp.instance().startActivity(i); + } + } + }); + } + if (pump.getPumpDescription().isExtendedBolusCapable && activeTreatments.isInHistoryExtendedBoluslInProgress()) { ConfigBuilderPlugin.getPlugin().getCommandQueue().cancelExtended(new Callback() { @Override public void run() { if (!result.success) { - ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.extendedbolusdeliveryerror)); + Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class); + i.putExtra("soundid", R.raw.boluserror); + i.putExtra("status", result.comment); + i.putExtra("title", MainApp.gs(R.string.extendedbolusdeliveryerror)); + i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + MainApp.instance().startActivity(i); } } }); @@ -666,7 +695,12 @@ public class LoopPlugin extends PluginBase { @Override public void run() { if (!result.success) { - ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.tempbasaldeliveryerror)); + Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class); + i.putExtra("soundid", R.raw.boluserror); + i.putExtra("status", result.comment); + i.putExtra("title", MainApp.gs(R.string.tempbasaldeliveryerror)); + i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + MainApp.instance().startActivity(i); } } }); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/ScriptReader.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/ScriptReader.java similarity index 94% rename from app/src/main/java/info/nightscout/androidaps/plugins/Loop/ScriptReader.java rename to app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/ScriptReader.java index 988d08fb84..e3a64dbece 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/ScriptReader.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/ScriptReader.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.Loop; +package info.nightscout.androidaps.plugins.aps.loop; import android.content.Context; import android.content.res.AssetManager; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/events/EventLoopSetLastRunGui.kt b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/events/EventLoopSetLastRunGui.kt new file mode 100644 index 0000000000..19c7e92c5c --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/events/EventLoopSetLastRunGui.kt @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.aps.loop.events + +import info.nightscout.androidaps.events.EventUpdateGui + +/** + * Created by mike on 05.08.2016. + */ +class EventLoopSetLastRunGui(val text: String) : EventUpdateGui() diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/events/EventLoopUpdateGui.kt b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/events/EventLoopUpdateGui.kt new file mode 100644 index 0000000000..89507d85f8 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/events/EventLoopUpdateGui.kt @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.aps.loop.events + +import info.nightscout.androidaps.events.EventUpdateGui + +/** + * Created by mike on 05.08.2016. + */ +class EventLoopUpdateGui : EventUpdateGui() diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/events/EventNewOpenLoopNotification.kt b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/events/EventNewOpenLoopNotification.kt new file mode 100644 index 0000000000..2933318dd6 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/events/EventNewOpenLoopNotification.kt @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.aps.loop.events + +import info.nightscout.androidaps.events.Event + +class EventNewOpenLoopNotification : Event() \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/DetermineBasalAdapterAMAJS.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/DetermineBasalAdapterAMAJS.java similarity index 94% rename from app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/DetermineBasalAdapterAMAJS.java rename to app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/DetermineBasalAdapterAMAJS.java index 50e79d1e37..703dc4255b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/DetermineBasalAdapterAMAJS.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/DetermineBasalAdapterAMAJS.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.OpenAPSAMA; +package info.nightscout.androidaps.plugins.aps.openAPSAMA; import org.json.JSONArray; import org.json.JSONException; @@ -16,22 +16,25 @@ import org.slf4j.LoggerFactory; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.nio.charset.StandardCharsets; + +import javax.annotation.Nullable; import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.data.GlucoseStatus; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus; import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.MealData; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin; -import info.nightscout.androidaps.plugins.Loop.ScriptReader; -import info.nightscout.androidaps.plugins.OpenAPSMA.LoggerCallback; -import info.nightscout.androidaps.plugins.OpenAPSSMB.SMBDefaults; -import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; -import info.nightscout.utils.SP; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin; +import info.nightscout.androidaps.plugins.aps.loop.ScriptReader; +import info.nightscout.androidaps.plugins.aps.openAPSMA.LoggerCallback; +import info.nightscout.androidaps.plugins.aps.openAPSSMB.SMBDefaults; +import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; +import info.nightscout.androidaps.utils.SP; public class DetermineBasalAdapterAMAJS { private static Logger log = LoggerFactory.getLogger(L.APS); @@ -59,6 +62,7 @@ public class DetermineBasalAdapterAMAJS { mScriptReader = scriptReader; } + @Nullable public DetermineBasalResultAMA invoke() { if (L.isEnabled(L.APS)) { @@ -277,7 +281,7 @@ public class DetermineBasalAdapterAMAJS { private String readFile(String filename) throws IOException { byte[] bytes = mScriptReader.readFile(filename); - String string = new String(bytes, "UTF-8"); + String string = new String(bytes, StandardCharsets.UTF_8); if (string.startsWith("#!/usr/bin/env node")) { string = string.substring(20); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/DetermineBasalResultAMA.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/DetermineBasalResultAMA.java similarity index 92% rename from app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/DetermineBasalResultAMA.java rename to app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/DetermineBasalResultAMA.java index 77c8d8a860..46f1057e27 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/DetermineBasalResultAMA.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/DetermineBasalResultAMA.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.OpenAPSAMA; +package info.nightscout.androidaps.plugins.aps.openAPSAMA; import org.json.JSONException; import org.json.JSONObject; @@ -7,8 +7,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.Loop.APSResult; -import info.nightscout.utils.DateUtil; +import info.nightscout.androidaps.plugins.aps.loop.APSResult; +import info.nightscout.androidaps.utils.DateUtil; public class DetermineBasalResultAMA extends APSResult { private static Logger log = LoggerFactory.getLogger(L.APS); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/OpenAPSAMAFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/OpenAPSAMAFragment.kt new file mode 100644 index 0000000000..94747a4597 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/OpenAPSAMAFragment.kt @@ -0,0 +1,115 @@ +package info.nightscout.androidaps.plugins.aps.openAPSAMA + +import android.os.Bundle +import android.text.TextUtils +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import info.nightscout.androidaps.MainApp +import info.nightscout.androidaps.R +import info.nightscout.androidaps.logging.L +import info.nightscout.androidaps.plugins.aps.openAPSMA.events.EventOpenAPSUpdateGui +import info.nightscout.androidaps.plugins.aps.openAPSMA.events.EventOpenAPSUpdateResultGui +import info.nightscout.androidaps.plugins.bus.RxBus +import info.nightscout.androidaps.utils.DateUtil +import info.nightscout.androidaps.utils.FabricPrivacy +import info.nightscout.androidaps.utils.JSONFormatter +import info.nightscout.androidaps.utils.plusAssign +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.disposables.CompositeDisposable +import kotlinx.android.synthetic.main.openapsama_fragment.* +import org.json.JSONArray +import org.json.JSONException +import org.slf4j.LoggerFactory + +class OpenAPSAMAFragment : Fragment() { + private val log = LoggerFactory.getLogger(L.APS) + private var disposable: CompositeDisposable = CompositeDisposable() + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle?): View? { + return inflater.inflate(R.layout.openapsama_fragment, container, false) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + openapsma_run.setOnClickListener { + OpenAPSAMAPlugin.getPlugin().invoke("OpenAPSAMA button", false) + } + } + + @Synchronized + override fun onResume() { + super.onResume() + + disposable += RxBus + .toObservable(EventOpenAPSUpdateGui::class.java) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe({ + updateGUI() + }, { + FabricPrivacy.logException(it) + }) + disposable += RxBus + .toObservable(EventOpenAPSUpdateResultGui::class.java) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe({ + updateResultGUI(it.text) + }, { + FabricPrivacy.logException(it) + }) + + updateGUI() + } + + @Synchronized + override fun onPause() { + super.onPause() + disposable.clear() + } + + @Synchronized + private fun updateGUI() { + if (openapsma_result == null) return + OpenAPSAMAPlugin.getPlugin().lastAPSResult?.let { lastAPSResult -> + openapsma_result.text = JSONFormatter.format(lastAPSResult.json) + openapsma_request.text = lastAPSResult.toSpanned() + } + OpenAPSAMAPlugin.getPlugin().lastDetermineBasalAdapterAMAJS?.let { determineBasalAdapterAMAJS -> + openapsma_glucosestatus.text = JSONFormatter.format(determineBasalAdapterAMAJS.glucoseStatusParam) + openapsma_currenttemp.text = JSONFormatter.format(determineBasalAdapterAMAJS.currentTempParam) + try { + val iobArray = JSONArray(determineBasalAdapterAMAJS.iobDataParam) + openapsma_iobdata.text = TextUtils.concat(String.format(MainApp.gs(R.string.array_of_elements), iobArray.length()) + "\n", JSONFormatter.format(iobArray.getString(0))) + } catch (e: JSONException) { + log.error("Unhandled exception", e) + openapsma_iobdata.text = "JSONException see log for details" + } + + openapsma_profile.text = JSONFormatter.format(determineBasalAdapterAMAJS.profileParam) + openapsma_mealdata.text = JSONFormatter.format(determineBasalAdapterAMAJS.mealDataParam) + openapsma_scriptdebugdata.text = determineBasalAdapterAMAJS.scriptDebug + } + if (OpenAPSAMAPlugin.getPlugin().lastAPSRun != 0L) { + openapsma_lastrun.text = DateUtil.dateAndTimeFullString(OpenAPSAMAPlugin.getPlugin().lastAPSRun) + } + OpenAPSAMAPlugin.getPlugin().lastAutosensResult?.let { + openapsma_autosensdata.text = JSONFormatter.format(it.json()) + } + } + + private fun updateResultGUI(text: String) { + openapsma_result.text = text + openapsma_glucosestatus.text = "" + openapsma_currenttemp.text = "" + openapsma_iobdata.text = "" + openapsma_profile.text = "" + openapsma_mealdata.text = "" + openapsma_autosensdata.text = "" + openapsma_scriptdebugdata.text = "" + openapsma_request.text = "" + openapsma_lastrun.text = "" + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/OpenAPSAMAPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/OpenAPSAMAPlugin.java similarity index 74% rename from app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/OpenAPSAMAPlugin.java rename to app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/OpenAPSAMAPlugin.java index 3bf1301416..ef31ad599e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/OpenAPSAMAPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/OpenAPSAMAPlugin.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.OpenAPSAMA; +package info.nightscout.androidaps.plugins.aps.openAPSAMA; import org.json.JSONException; import org.slf4j.Logger; @@ -6,32 +6,33 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.data.GlucoseStatus; import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.MealData; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.db.TempTarget; -import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.interfaces.APSInterface; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginDescription; import info.nightscout.androidaps.interfaces.PluginType; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions; -import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData; -import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensResult; -import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin; -import info.nightscout.androidaps.plugins.Loop.APSResult; -import info.nightscout.androidaps.plugins.Loop.ScriptReader; -import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateGui; -import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateResultGui; -import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.HardLimits; -import info.nightscout.utils.Profiler; -import info.nightscout.utils.Round; +import info.nightscout.androidaps.plugins.aps.loop.APSResult; +import info.nightscout.androidaps.plugins.aps.loop.ScriptReader; +import info.nightscout.androidaps.plugins.aps.openAPSMA.events.EventOpenAPSUpdateGui; +import info.nightscout.androidaps.plugins.aps.openAPSMA.events.EventOpenAPSUpdateResultGui; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensData; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin; +import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; +import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.FabricPrivacy; +import info.nightscout.androidaps.utils.HardLimits; +import info.nightscout.androidaps.utils.Profiler; +import info.nightscout.androidaps.utils.Round; /** * Created by mike on 05.08.2016. @@ -100,21 +101,21 @@ public class OpenAPSAMAPlugin extends PluginBase implements APSInterface { PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump(); if (profile == null) { - MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.gs(R.string.noprofileselected))); + RxBus.INSTANCE.send(new EventOpenAPSUpdateResultGui(MainApp.gs(R.string.noprofileselected))); if (L.isEnabled(L.APS)) log.debug(MainApp.gs(R.string.noprofileselected)); return; } if (!isEnabled(PluginType.APS)) { - MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.gs(R.string.openapsma_disabled))); + RxBus.INSTANCE.send(new EventOpenAPSUpdateResultGui(MainApp.gs(R.string.openapsma_disabled))); if (L.isEnabled(L.APS)) log.debug(MainApp.gs(R.string.openapsma_disabled)); return; } if (glucoseStatus == null) { - MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.gs(R.string.openapsma_noglucosedata))); + RxBus.INSTANCE.send(new EventOpenAPSUpdateResultGui(MainApp.gs(R.string.openapsma_noglucosedata))); if (L.isEnabled(L.APS)) log.debug(MainApp.gs(R.string.openapsma_noglucosedata)); return; @@ -172,7 +173,7 @@ public class OpenAPSAMAPlugin extends PluginBase implements APSInterface { if (MainApp.getConstraintChecker().isAutosensModeEnabled().value()) { AutosensData autosensData = IobCobCalculatorPlugin.getPlugin().getLastAutosensDataSynchronized("OpenAPSPlugin"); if (autosensData == null) { - MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.gs(R.string.openaps_noasdata))); + RxBus.INSTANCE.send(new EventOpenAPSUpdateResultGui(MainApp.gs(R.string.openaps_noasdata))); return; } lastAutosensResult = autosensData.autosensResult; @@ -193,7 +194,8 @@ public class OpenAPSAMAPlugin extends PluginBase implements APSInterface { isTempTarget ); } catch (JSONException e) { - log.error("Unable to set data: " + e.toString()); + FabricPrivacy.logException(e); + return; } @@ -201,23 +203,31 @@ public class OpenAPSAMAPlugin extends PluginBase implements APSInterface { if (L.isEnabled(L.APS)) Profiler.log(log, "AMA calculation", start); // Fix bug determine basal - if (determineBasalResultAMA.rate == 0d && determineBasalResultAMA.duration == 0 && !TreatmentsPlugin.getPlugin().isTempBasalInProgress()) - determineBasalResultAMA.tempBasalRequested = false; + if (determineBasalResultAMA == null) { + if (L.isEnabled(L.APS)) + log.error("SMB calculation returned null"); + lastDetermineBasalAdapterAMAJS = null; + lastAPSResult = null; + lastAPSRun = 0; + } else { + if (determineBasalResultAMA.rate == 0d && determineBasalResultAMA.duration == 0 && !TreatmentsPlugin.getPlugin().isTempBasalInProgress()) + determineBasalResultAMA.tempBasalRequested = false; - determineBasalResultAMA.iob = iobArray[0]; + determineBasalResultAMA.iob = iobArray[0]; - long now = System.currentTimeMillis(); + long now = System.currentTimeMillis(); - try { - determineBasalResultAMA.json.put("timestamp", DateUtil.toISOString(now)); - } catch (JSONException e) { - log.error("Unhandled exception", e); + try { + determineBasalResultAMA.json.put("timestamp", DateUtil.toISOString(now)); + } catch (JSONException e) { + log.error("Unhandled exception", e); + } + + lastDetermineBasalAdapterAMAJS = determineBasalAdapterAMAJS; + lastAPSResult = determineBasalResultAMA; + lastAPSRun = now; } - - lastDetermineBasalAdapterAMAJS = determineBasalAdapterAMAJS; - lastAPSResult = determineBasalResultAMA; - lastAPSRun = now; - MainApp.bus().post(new EventOpenAPSUpdateGui()); + RxBus.INSTANCE.send(new EventOpenAPSUpdateGui()); //deviceStatus.suggested = determineBasalResultAMA.json; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/DetermineBasalAdapterMAJS.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/DetermineBasalAdapterMAJS.java similarity index 94% rename from app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/DetermineBasalAdapterMAJS.java rename to app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/DetermineBasalAdapterMAJS.java index 1574665dc4..1ded34b7cb 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/DetermineBasalAdapterMAJS.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/DetermineBasalAdapterMAJS.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.OpenAPSMA; +package info.nightscout.androidaps.plugins.aps.openAPSMA; import org.json.JSONException; import org.json.JSONObject; @@ -14,18 +14,21 @@ import org.slf4j.LoggerFactory; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.nio.charset.StandardCharsets; + +import javax.annotation.Nullable; import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.data.GlucoseStatus; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus; import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.MealData; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.Loop.ScriptReader; -import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; -import info.nightscout.utils.SP; +import info.nightscout.androidaps.plugins.aps.loop.ScriptReader; +import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; +import info.nightscout.androidaps.utils.SP; public class DetermineBasalAdapterMAJS { private static Logger log = LoggerFactory.getLogger(L.APS); @@ -47,6 +50,7 @@ public class DetermineBasalAdapterMAJS { mScriptReader = scriptReader; } + @Nullable public DetermineBasalResultMA invoke() { DetermineBasalResultMA determineBasalResultMA = null; @@ -207,7 +211,7 @@ public class DetermineBasalAdapterMAJS { private String readFile(String filename) throws IOException { byte[] bytes = mScriptReader.readFile(filename); - String string = new String(bytes, "UTF-8"); + String string = new String(bytes, StandardCharsets.UTF_8); if (string.startsWith("#!/usr/bin/env node")) { string = string.substring(20); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/DetermineBasalResultMA.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/DetermineBasalResultMA.java similarity index 94% rename from app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/DetermineBasalResultMA.java rename to app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/DetermineBasalResultMA.java index d3e1869f87..bbbcf7f893 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/DetermineBasalResultMA.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/DetermineBasalResultMA.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.OpenAPSMA; +package info.nightscout.androidaps.plugins.aps.openAPSMA; import org.json.JSONException; import org.json.JSONObject; @@ -7,7 +7,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.Loop.APSResult; +import info.nightscout.androidaps.plugins.aps.loop.APSResult; public class DetermineBasalResultMA extends APSResult { private static Logger log = LoggerFactory.getLogger(L.APS); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/LoggerCallback.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/LoggerCallback.java similarity index 87% rename from app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/LoggerCallback.java rename to app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/LoggerCallback.java index 8907166951..a2596d9174 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/LoggerCallback.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/LoggerCallback.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.OpenAPSMA; +package info.nightscout.androidaps.plugins.aps.openAPSMA; import org.mozilla.javascript.ScriptableObject; import org.slf4j.Logger; @@ -36,16 +36,14 @@ public class LoggerCallback extends ScriptableObject { public void jsFunction_log(Object obj1) { if (L.isEnabled(L.APS)) - log.debug(obj1.toString()); + log.debug(obj1.toString().trim()); logBuffer.append(obj1.toString()); - logBuffer.append(' '); } public void jsFunction_error(Object obj1) { if (L.isEnabled(L.APS)) - log.error(obj1.toString()); + log.error(obj1.toString().trim()); errorBuffer.append(obj1.toString()); - errorBuffer.append(' '); } @@ -60,4 +58,4 @@ public class LoggerCallback extends ScriptableObject { } return ret; } -} \ No newline at end of file +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/OpenAPSMAFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/OpenAPSMAFragment.kt new file mode 100644 index 0000000000..1b72f57365 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/OpenAPSMAFragment.kt @@ -0,0 +1,100 @@ +package info.nightscout.androidaps.plugins.aps.openAPSMA + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import info.nightscout.androidaps.R +import info.nightscout.androidaps.logging.L +import info.nightscout.androidaps.plugins.aps.openAPSMA.events.EventOpenAPSUpdateGui +import info.nightscout.androidaps.plugins.aps.openAPSMA.events.EventOpenAPSUpdateResultGui +import info.nightscout.androidaps.plugins.bus.RxBus +import info.nightscout.androidaps.utils.DateUtil +import info.nightscout.androidaps.utils.FabricPrivacy +import info.nightscout.androidaps.utils.JSONFormatter +import info.nightscout.androidaps.utils.plusAssign +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.disposables.CompositeDisposable +import kotlinx.android.synthetic.main.openapsama_fragment.* +import org.slf4j.LoggerFactory + +class OpenAPSMAFragment : Fragment() { + private val log = LoggerFactory.getLogger(L.APS) + private var disposable: CompositeDisposable = CompositeDisposable() + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle?): View? { + return inflater.inflate(R.layout.openapsma_fragment, container, false) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + openapsma_run.setOnClickListener { + OpenAPSMAPlugin.getPlugin().invoke("OpenAPSMA button", false) + } + + } + + @Synchronized + override fun onResume() { + super.onResume() + + disposable += RxBus + .toObservable(EventOpenAPSUpdateGui::class.java) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe({ + updateGUI() + }, { + FabricPrivacy.logException(it) + }) + disposable += RxBus + .toObservable(EventOpenAPSUpdateResultGui::class.java) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe({ + updateResultGUI(it.text) + }, { + FabricPrivacy.logException(it) + }) + updateGUI() + } + + @Synchronized + override fun onPause() { + super.onPause() + disposable.clear() + } + + @Synchronized + private fun updateGUI() { + if (openapsma_result == null) return + OpenAPSMAPlugin.getPlugin().lastAPSResult?.let { lastAPSResult -> + openapsma_result.text = JSONFormatter.format(lastAPSResult.json) + openapsma_request.text = lastAPSResult.toSpanned() + } + OpenAPSMAPlugin.getPlugin().lastDetermineBasalAdapterMAJS?.let { determineBasalAdapterMAJS -> + openapsma_glucosestatus.text = JSONFormatter.format(determineBasalAdapterMAJS.glucoseStatusParam) + openapsma_currenttemp.text = JSONFormatter.format(determineBasalAdapterMAJS.currentTempParam) + openapsma_iobdata.text = JSONFormatter.format(determineBasalAdapterMAJS.iobDataParam) + openapsma_profile.text = JSONFormatter.format(determineBasalAdapterMAJS.profileParam) + openapsma_mealdata.text = JSONFormatter.format(determineBasalAdapterMAJS.mealDataParam) + } + if (OpenAPSMAPlugin.getPlugin().lastAPSRun != 0L) { + openapsma_lastrun.text = DateUtil.dateAndTimeString(OpenAPSMAPlugin.getPlugin().lastAPSRun) + } + } + + @Synchronized + private fun updateResultGUI(text: String) { + if (openapsma_result == null) return + openapsma_result.text = text + openapsma_glucosestatus.text = "" + openapsma_currenttemp.text = "" + openapsma_iobdata.text = "" + openapsma_profile.text = "" + openapsma_mealdata.text = "" + openapsma_request.text = "" + openapsma_lastrun.text = "" + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/OpenAPSMAPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/OpenAPSMAPlugin.java similarity index 73% rename from app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/OpenAPSMAPlugin.java rename to app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/OpenAPSMAPlugin.java index 5b59252ea1..899c0151d8 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/OpenAPSMAPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/OpenAPSMAPlugin.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.OpenAPSMA; +package info.nightscout.androidaps.plugins.aps.openAPSMA; import org.json.JSONException; import org.slf4j.Logger; @@ -6,32 +6,33 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.data.GlucoseStatus; import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.MealData; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.db.TempTarget; -import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.interfaces.APSInterface; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginDescription; import info.nightscout.androidaps.interfaces.PluginType; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions; -import info.nightscout.androidaps.plugins.Loop.APSResult; -import info.nightscout.androidaps.plugins.Loop.ScriptReader; -import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateGui; -import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateResultGui; -import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.HardLimits; -import info.nightscout.utils.Profiler; -import info.nightscout.utils.Round; +import info.nightscout.androidaps.plugins.aps.loop.APSResult; +import info.nightscout.androidaps.plugins.aps.loop.ScriptReader; +import info.nightscout.androidaps.plugins.aps.openAPSMA.events.EventOpenAPSUpdateGui; +import info.nightscout.androidaps.plugins.aps.openAPSMA.events.EventOpenAPSUpdateResultGui; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus; +import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; +import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.FabricPrivacy; +import info.nightscout.androidaps.utils.HardLimits; +import info.nightscout.androidaps.utils.Profiler; +import info.nightscout.androidaps.utils.Round; -import static info.nightscout.utils.HardLimits.checkOnlyHardLimits; -import static info.nightscout.utils.HardLimits.verifyHardLimits; +import static info.nightscout.androidaps.utils.HardLimits.checkOnlyHardLimits; +import static info.nightscout.androidaps.utils.HardLimits.verifyHardLimits; /** * Created by mike on 05.08.2016. @@ -99,21 +100,21 @@ public class OpenAPSMAPlugin extends PluginBase implements APSInterface { PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump(); if (profile == null) { - MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.gs(R.string.noprofileselected))); + RxBus.INSTANCE.send(new EventOpenAPSUpdateResultGui(MainApp.gs(R.string.noprofileselected))); if (L.isEnabled(L.APS)) log.debug(MainApp.gs(R.string.noprofileselected)); return; } if (!isEnabled(PluginType.APS)) { - MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.gs(R.string.openapsma_disabled))); + RxBus.INSTANCE.send(new EventOpenAPSUpdateResultGui(MainApp.gs(R.string.openapsma_disabled))); if (L.isEnabled(L.APS)) log.debug(MainApp.gs(R.string.openapsma_disabled)); return; } if (glucoseStatus == null) { - MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.gs(R.string.openapsma_noglucosedata))); + RxBus.INSTANCE.send(new EventOpenAPSUpdateResultGui(MainApp.gs(R.string.openapsma_noglucosedata))); if (L.isEnabled(L.APS)) log.debug(MainApp.gs(R.string.openapsma_noglucosedata)); return; @@ -170,7 +171,8 @@ public class OpenAPSMAPlugin extends PluginBase implements APSInterface { try { determineBasalAdapterMAJS.setData(profile, maxIob, maxBasal, minBg, maxBg, targetBg, ConfigBuilderPlugin.getPlugin().getActivePump().getBaseBasalRate(), iobTotal, glucoseStatus, mealData); } catch (JSONException e) { - log.error("Unhandled exception", e); + FabricPrivacy.logException(e); + return; } if (L.isEnabled(L.APS)) Profiler.log(log, "MA calculation", start); @@ -179,22 +181,30 @@ public class OpenAPSMAPlugin extends PluginBase implements APSInterface { long now = System.currentTimeMillis(); DetermineBasalResultMA determineBasalResultMA = determineBasalAdapterMAJS.invoke(); - // Fix bug determinef basal - if (determineBasalResultMA.rate == 0d && determineBasalResultMA.duration == 0 && !TreatmentsPlugin.getPlugin().isTempBasalInProgress()) - determineBasalResultMA.tempBasalRequested = false; + if (determineBasalResultMA == null) { + if (L.isEnabled(L.APS)) + log.error("MA calculation returned null"); + lastDetermineBasalAdapterMAJS = null; + lastAPSResult = null; + lastAPSRun = 0; + } else { + // Fix bug determinef basal + if (determineBasalResultMA.rate == 0d && determineBasalResultMA.duration == 0 && !TreatmentsPlugin.getPlugin().isTempBasalInProgress()) + determineBasalResultMA.tempBasalRequested = false; - determineBasalResultMA.iob = iobTotal; + determineBasalResultMA.iob = iobTotal; - try { - determineBasalResultMA.json.put("timestamp", DateUtil.toISOString(now)); - } catch (JSONException e) { - log.error("Unhandled exception", e); + try { + determineBasalResultMA.json.put("timestamp", DateUtil.toISOString(now)); + } catch (JSONException e) { + log.error("Unhandled exception", e); + } + + lastDetermineBasalAdapterMAJS = determineBasalAdapterMAJS; + lastAPSResult = determineBasalResultMA; + lastAPSRun = now; } - - lastDetermineBasalAdapterMAJS = determineBasalAdapterMAJS; - lastAPSResult = determineBasalResultMA; - lastAPSRun = now; - MainApp.bus().post(new EventOpenAPSUpdateGui()); + RxBus.INSTANCE.send(new EventOpenAPSUpdateGui()); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/events/EventOpenAPSUpdateGui.kt b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/events/EventOpenAPSUpdateGui.kt new file mode 100644 index 0000000000..2b642c6880 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/events/EventOpenAPSUpdateGui.kt @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.aps.openAPSMA.events + +import info.nightscout.androidaps.events.EventUpdateGui + +class EventOpenAPSUpdateGui : EventUpdateGui() diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/events/EventOpenAPSUpdateResultGui.kt b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/events/EventOpenAPSUpdateResultGui.kt new file mode 100644 index 0000000000..4ba02b8755 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/events/EventOpenAPSUpdateResultGui.kt @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.aps.openAPSMA.events + +import info.nightscout.androidaps.events.EventUpdateGui + +class EventOpenAPSUpdateResultGui(val text: String) : EventUpdateGui() diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/DetermineBasalAdapterSMBJS.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/DetermineBasalAdapterSMBJS.java similarity index 87% rename from app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/DetermineBasalAdapterSMBJS.java rename to app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/DetermineBasalAdapterSMBJS.java index bdd06372d9..b7b6d82e5e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/DetermineBasalAdapterSMBJS.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/DetermineBasalAdapterSMBJS.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.OpenAPSSMB; +package info.nightscout.androidaps.plugins.aps.openAPSSMB; import org.json.JSONArray; import org.json.JSONException; @@ -16,22 +16,25 @@ import org.slf4j.LoggerFactory; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.nio.charset.StandardCharsets; + +import javax.annotation.Nullable; import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.data.GlucoseStatus; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus; import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.MealData; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin; -import info.nightscout.androidaps.plugins.Loop.ScriptReader; -import info.nightscout.androidaps.plugins.OpenAPSMA.LoggerCallback; -import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; -import info.nightscout.utils.SP; -import info.nightscout.utils.SafeParse; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin; +import info.nightscout.androidaps.plugins.aps.loop.ScriptReader; +import info.nightscout.androidaps.plugins.aps.openAPSMA.LoggerCallback; +import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; +import info.nightscout.androidaps.utils.SP; +import info.nightscout.androidaps.utils.SafeParse; public class DetermineBasalAdapterSMBJS { private static Logger log = LoggerFactory.getLogger(L.APS); @@ -68,6 +71,7 @@ public class DetermineBasalAdapterSMBJS { } + @Nullable public DetermineBasalResultSMB invoke() { @@ -232,8 +236,13 @@ public class DetermineBasalAdapterSMBJS { mProfile.put("max_daily_safety_multiplier", SP.getInt(R.string.key_openapsama_max_daily_safety_multiplier, 3)); mProfile.put("current_basal_safety_multiplier", SP.getDouble(R.string.key_openapsama_current_basal_safety_multiplier, 4d)); - mProfile.put("high_temptarget_raises_sensitivity", SP.getBoolean(R.string.key_high_temptarget_raises_sensitivity, SMBDefaults.high_temptarget_raises_sensitivity)); - mProfile.put("low_temptarget_lowers_sensitivity", SP.getBoolean(R.string.key_low_temptarget_lowers_sensitivity, SMBDefaults.low_temptarget_lowers_sensitivity)); + // TODO AS-FIX + // mProfile.put("high_temptarget_raises_sensitivity", SP.getBoolean(R.string.key_high_temptarget_raises_sensitivity, SMBDefaults.high_temptarget_raises_sensitivity)); + mProfile.put("high_temptarget_raises_sensitivity", false); + //mProfile.put("low_temptarget_lowers_sensitivity", SP.getBoolean(R.string.key_low_temptarget_lowers_sensitivity, SMBDefaults.low_temptarget_lowers_sensitivity)); + mProfile.put("low_temptarget_lowers_sensitivity", false); + + mProfile.put("sensitivity_raises_target", SMBDefaults.sensitivity_raises_target); mProfile.put("resistance_lowers_target", SMBDefaults.resistance_lowers_target); mProfile.put("adv_target_adjustments", SMBDefaults.adv_target_adjustments); @@ -250,12 +259,14 @@ public class DetermineBasalAdapterSMBJS { mProfile.put("remainingCarbsCap", SMBDefaults.remainingCarbsCap); mProfile.put("enableUAM", uamAllowed); mProfile.put("A52_risk_enable", SMBDefaults.A52_risk_enable); - mProfile.put("enableSMB_with_COB", SP.getBoolean(R.string.key_enableSMB_with_COB, false)); - mProfile.put("enableSMB_with_temptarget", SP.getBoolean(R.string.key_enableSMB_with_temptarget, false)); - mProfile.put("allowSMB_with_high_temptarget", SP.getBoolean(R.string.key_allowSMB_with_high_temptarget, false)); - mProfile.put("enableSMB_always", SP.getBoolean(R.string.key_enableSMB_always, false) && advancedFiltering); - mProfile.put("enableSMB_after_carbs", SP.getBoolean(R.string.key_enableSMB_after_carbs, false) && advancedFiltering); - mProfile.put("maxSMBBasalMinutes", SP.getInt("key_smbmaxminutes", SMBDefaults.maxSMBBasalMinutes)); + + boolean smbEnabled = SP.getBoolean(MainApp.gs(R.string.key_use_smb), false); + mProfile.put("enableSMB_with_COB", smbEnabled && SP.getBoolean(R.string.key_enableSMB_with_COB, false)); + mProfile.put("enableSMB_with_temptarget", smbEnabled && SP.getBoolean(R.string.key_enableSMB_with_temptarget, false)); + mProfile.put("allowSMB_with_high_temptarget", smbEnabled && SP.getBoolean(R.string.key_allowSMB_with_high_temptarget, false)); + mProfile.put("enableSMB_always", smbEnabled && SP.getBoolean(R.string.key_enableSMB_always, false) && advancedFiltering); + mProfile.put("enableSMB_after_carbs", smbEnabled && SP.getBoolean(R.string.key_enableSMB_after_carbs, false) && advancedFiltering); + mProfile.put("maxSMBBasalMinutes", SP.getInt(R.string.key_smbmaxminutes, SMBDefaults.maxSMBBasalMinutes)); mProfile.put("carbsReqThreshold", SMBDefaults.carbsReqThreshold); mProfile.put("current_basal", basalrate); @@ -333,7 +344,7 @@ public class DetermineBasalAdapterSMBJS { private String readFile(String filename) throws IOException { byte[] bytes = mScriptReader.readFile(filename); - String string = new String(bytes, "UTF-8"); + String string = new String(bytes, StandardCharsets.UTF_8); if (string.startsWith("#!/usr/bin/env node")) { string = string.substring(20); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/DetermineBasalResultSMB.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/DetermineBasalResultSMB.java similarity index 93% rename from app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/DetermineBasalResultSMB.java rename to app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/DetermineBasalResultSMB.java index 364731bea5..9d0bd22557 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/DetermineBasalResultSMB.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/DetermineBasalResultSMB.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.OpenAPSSMB; +package info.nightscout.androidaps.plugins.aps.openAPSSMB; import org.json.JSONException; import org.json.JSONObject; @@ -6,8 +6,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.Loop.APSResult; -import info.nightscout.utils.DateUtil; +import info.nightscout.androidaps.plugins.aps.loop.APSResult; +import info.nightscout.androidaps.utils.DateUtil; public class DetermineBasalResultSMB extends APSResult { private static final Logger log = LoggerFactory.getLogger(L.APS); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/OpenAPSSMBFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/OpenAPSSMBFragment.kt new file mode 100644 index 0000000000..06ad0d01fd --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/OpenAPSSMBFragment.kt @@ -0,0 +1,122 @@ +package info.nightscout.androidaps.plugins.aps.openAPSSMB + +import android.annotation.SuppressLint +import android.os.Bundle +import android.text.TextUtils +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import info.nightscout.androidaps.MainApp +import info.nightscout.androidaps.R +import info.nightscout.androidaps.logging.L +import info.nightscout.androidaps.plugins.aps.openAPSMA.events.EventOpenAPSUpdateGui +import info.nightscout.androidaps.plugins.aps.openAPSMA.events.EventOpenAPSUpdateResultGui +import info.nightscout.androidaps.plugins.bus.RxBus +import info.nightscout.androidaps.utils.DateUtil +import info.nightscout.androidaps.utils.FabricPrivacy +import info.nightscout.androidaps.utils.JSONFormatter +import info.nightscout.androidaps.utils.plusAssign +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.disposables.CompositeDisposable +import kotlinx.android.synthetic.main.openapsama_fragment.* +import org.json.JSONArray +import org.json.JSONException +import org.slf4j.LoggerFactory + +class OpenAPSSMBFragment : Fragment() { + private val log = LoggerFactory.getLogger(L.APS) + private var disposable: CompositeDisposable = CompositeDisposable() + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle?): View? { + return inflater.inflate(R.layout.openapsama_fragment, container, false) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + openapsma_run.setOnClickListener { + OpenAPSSMBPlugin.getPlugin().invoke("OpenAPSSMB button", false) + } + } + + @Synchronized + override fun onResume() { + super.onResume() + disposable += RxBus + .toObservable(EventOpenAPSUpdateGui::class.java) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe({ + updateGUI() + }, { + FabricPrivacy.logException(it) + }) + disposable += RxBus + .toObservable(EventOpenAPSUpdateResultGui::class.java) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe({ + updateResultGUI(it.text) + }, { + FabricPrivacy.logException(it) + }) + + updateGUI() + } + + @Synchronized + override fun onPause() { + super.onPause() + disposable.clear() + } + + @Synchronized + fun updateGUI() { + if (openapsma_result == null) return + val plugin = OpenAPSSMBPlugin.getPlugin() + plugin.lastAPSResult?.let { lastAPSResult -> + openapsma_result.text = JSONFormatter.format(lastAPSResult.json) + openapsma_request.text = lastAPSResult.toSpanned() + } + plugin.lastDetermineBasalAdapterSMBJS?.let { determineBasalAdapterSMBJS -> + openapsma_glucosestatus.text = JSONFormatter.format(determineBasalAdapterSMBJS.glucoseStatusParam) + openapsma_currenttemp.text = JSONFormatter.format(determineBasalAdapterSMBJS.currentTempParam) + try { + val iobArray = JSONArray(determineBasalAdapterSMBJS.iobDataParam) + openapsma_iobdata.text = TextUtils.concat(String.format(MainApp.gs(R.string.array_of_elements), iobArray.length()) + "\n", JSONFormatter.format(iobArray.getString(0))) + } catch (e: JSONException) { + log.error("Unhandled exception", e) + @SuppressLint("SetTextl18n") + openapsma_iobdata.text = "JSONException see log for details" + } + + openapsma_profile.text = JSONFormatter.format(determineBasalAdapterSMBJS.profileParam) + openapsma_mealdata.text = JSONFormatter.format(determineBasalAdapterSMBJS.mealDataParam) + openapsma_scriptdebugdata.text = determineBasalAdapterSMBJS.scriptDebug + plugin.lastAPSResult?.inputConstraints?.let { + openapsma_constraints.text = it.reasons + } + } + if (plugin.lastAPSRun != 0L) { + openapsma_lastrun.text = DateUtil.dateAndTimeFullString(plugin.lastAPSRun) + } + plugin.lastAutosensResult?.let { + openapsma_autosensdata.text = JSONFormatter.format(it.json()) + } + } + + @Synchronized + private fun updateResultGUI(text: String) { + if (openapsma_result == null) return + openapsma_result.text = text + openapsma_glucosestatus.text = "" + openapsma_currenttemp.text = "" + openapsma_iobdata.text = "" + openapsma_profile.text = "" + openapsma_mealdata.text = "" + openapsma_autosensdata.text = "" + openapsma_scriptdebugdata.text = "" + openapsma_request.text = "" + openapsma_lastrun.text = "" + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/OpenAPSSMBPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/OpenAPSSMBPlugin.java similarity index 73% rename from app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/OpenAPSSMBPlugin.java rename to app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/OpenAPSSMBPlugin.java index 1d6b558c74..d410eba291 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/OpenAPSSMBPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/OpenAPSSMBPlugin.java @@ -1,47 +1,47 @@ -package info.nightscout.androidaps.plugins.OpenAPSSMB; +package info.nightscout.androidaps.plugins.aps.openAPSSMB; import org.json.JSONException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.Date; - import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.data.GlucoseStatus; import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.MealData; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.db.TempTarget; -import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.interfaces.APSInterface; import info.nightscout.androidaps.interfaces.Constraint; +import info.nightscout.androidaps.interfaces.ConstraintsInterface; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginDescription; import info.nightscout.androidaps.interfaces.PluginType; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions; -import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData; -import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensResult; -import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin; -import info.nightscout.androidaps.plugins.Loop.APSResult; -import info.nightscout.androidaps.plugins.Loop.ScriptReader; -import info.nightscout.androidaps.plugins.NSClientInternal.NSUpload; -import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateGui; -import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateResultGui; -import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.HardLimits; -import info.nightscout.utils.Profiler; -import info.nightscout.utils.Round; -import info.nightscout.utils.ToastUtils; +import info.nightscout.androidaps.plugins.aps.loop.APSResult; +import info.nightscout.androidaps.plugins.aps.loop.ScriptReader; +import info.nightscout.androidaps.plugins.aps.openAPSMA.events.EventOpenAPSUpdateGui; +import info.nightscout.androidaps.plugins.aps.openAPSMA.events.EventOpenAPSUpdateResultGui; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; +import info.nightscout.androidaps.plugins.general.nsclient.NSUpload; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensData; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin; +import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; +import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.FabricPrivacy; +import info.nightscout.androidaps.utils.HardLimits; +import info.nightscout.androidaps.utils.Profiler; +import info.nightscout.androidaps.utils.Round; +import info.nightscout.androidaps.utils.ToastUtils; /** * Created by mike on 05.08.2016. */ -public class OpenAPSSMBPlugin extends PluginBase implements APSInterface { +public class OpenAPSSMBPlugin extends PluginBase implements APSInterface, ConstraintsInterface { private static Logger log = LoggerFactory.getLogger(L.APS); private static OpenAPSSMBPlugin openAPSSMBPlugin; @@ -105,21 +105,21 @@ public class OpenAPSSMBPlugin extends PluginBase implements APSInterface { PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump(); if (profile == null) { - MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.gs(R.string.noprofileselected))); + RxBus.INSTANCE.send(new EventOpenAPSUpdateResultGui(MainApp.gs(R.string.noprofileselected))); if (L.isEnabled(L.APS)) log.debug(MainApp.gs(R.string.noprofileselected)); return; } if (!isEnabled(PluginType.APS)) { - MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.gs(R.string.openapsma_disabled))); + RxBus.INSTANCE.send(new EventOpenAPSUpdateResultGui(MainApp.gs(R.string.openapsma_disabled))); if (L.isEnabled(L.APS)) log.debug(MainApp.gs(R.string.openapsma_disabled)); return; } if (glucoseStatus == null) { - MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.gs(R.string.openapsma_noglucosedata))); + RxBus.INSTANCE.send(new EventOpenAPSUpdateResultGui(MainApp.gs(R.string.openapsma_noglucosedata))); if (L.isEnabled(L.APS)) log.debug(MainApp.gs(R.string.openapsma_noglucosedata)); return; @@ -141,16 +141,14 @@ public class OpenAPSSMBPlugin extends PluginBase implements APSInterface { long start = System.currentTimeMillis(); long startPart = System.currentTimeMillis(); - IobTotal[] iobArray = IobCobCalculatorPlugin.getPlugin().calculateIobArrayForSMB(profile); - if (L.isEnabled(L.APS)) - Profiler.log(log, "calculateIobArrayInDia()", startPart); - startPart = System.currentTimeMillis(); MealData mealData = TreatmentsPlugin.getPlugin().getMealData(); if (L.isEnabled(L.APS)) Profiler.log(log, "getMealData()", startPart); - double maxIob = MainApp.getConstraintChecker().getMaxIOBAllowed().value(); + Constraint maxIOBAllowedConstraint = MainApp.getConstraintChecker().getMaxIOBAllowed(); + inputConstraints.copyReasons(maxIOBAllowedConstraint); + double maxIob = maxIOBAllowedConstraint.value(); minBg = verifyHardLimits(minBg, "minBg", HardLimits.VERY_HARD_LIMIT_MIN_BG[0], HardLimits.VERY_HARD_LIMIT_MIN_BG[1]); maxBg = verifyHardLimits(maxBg, "maxBg", HardLimits.VERY_HARD_LIMIT_MAX_BG[0], HardLimits.VERY_HARD_LIMIT_MAX_BG[1]); @@ -181,7 +179,7 @@ public class OpenAPSSMBPlugin extends PluginBase implements APSInterface { if (MainApp.getConstraintChecker().isAutosensModeEnabled().value()) { AutosensData autosensData = IobCobCalculatorPlugin.getPlugin().getLastAutosensDataSynchronized("OpenAPSPlugin"); if (autosensData == null) { - MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.gs(R.string.openaps_noasdata))); + RxBus.INSTANCE.send(new EventOpenAPSUpdateResultGui(MainApp.gs(R.string.openaps_noasdata))); return; } lastAutosensResult = autosensData.autosensResult; @@ -190,6 +188,11 @@ public class OpenAPSSMBPlugin extends PluginBase implements APSInterface { lastAutosensResult.sensResult = "autosens disabled"; } + IobTotal[] iobArray = IobCobCalculatorPlugin.getPlugin().calculateIobArrayForSMB(lastAutosensResult, SMBDefaults.exercise_mode, SMBDefaults.half_basal_exercise_target, isTempTarget); + if (L.isEnabled(L.APS)) + Profiler.log(log, "calculateIobArrayInDia()", startPart); + + startPart = System.currentTimeMillis(); Constraint smbAllowed = new Constraint<>(!tempBasalFallback); MainApp.getConstraintChecker().isSMBModeEnabled(smbAllowed); inputConstraints.copyReasons(smbAllowed); @@ -217,7 +220,7 @@ public class OpenAPSSMBPlugin extends PluginBase implements APSInterface { advancedFiltering.value() ); } catch (JSONException e) { - log.error(e.getMessage()); + FabricPrivacy.logException(e); return; } @@ -226,25 +229,33 @@ public class OpenAPSSMBPlugin extends PluginBase implements APSInterface { DetermineBasalResultSMB determineBasalResultSMB = determineBasalAdapterSMBJS.invoke(); if (L.isEnabled(L.APS)) Profiler.log(log, "SMB calculation", start); - // TODO still needed with oref1? - // Fix bug determine basal - if (determineBasalResultSMB.rate == 0d && determineBasalResultSMB.duration == 0 && !TreatmentsPlugin.getPlugin().isTempBasalInProgress()) - determineBasalResultSMB.tempBasalRequested = false; + if (determineBasalResultSMB == null) { + if (L.isEnabled(L.APS)) + log.error("SMB calculation returned null"); + lastDetermineBasalAdapterSMBJS = null; + lastAPSResult = null; + lastAPSRun = 0; + } else { + // TODO still needed with oref1? + // Fix bug determine basal + if (determineBasalResultSMB.rate == 0d && determineBasalResultSMB.duration == 0 && !TreatmentsPlugin.getPlugin().isTempBasalInProgress()) + determineBasalResultSMB.tempBasalRequested = false; - determineBasalResultSMB.iob = iobArray[0]; + determineBasalResultSMB.iob = iobArray[0]; - try { - determineBasalResultSMB.json.put("timestamp", DateUtil.toISOString(now)); - } catch (JSONException e) { - log.error("Unhandled exception", e); + try { + determineBasalResultSMB.json.put("timestamp", DateUtil.toISOString(now)); + } catch (JSONException e) { + log.error("Unhandled exception", e); + } + + determineBasalResultSMB.inputConstraints = inputConstraints; + + lastDetermineBasalAdapterSMBJS = determineBasalAdapterSMBJS; + lastAPSResult = determineBasalResultSMB; + lastAPSRun = now; } - - determineBasalResultSMB.inputConstraints = inputConstraints; - - lastDetermineBasalAdapterSMBJS = determineBasalAdapterSMBJS; - lastAPSResult = determineBasalResultSMB; - lastAPSRun = now; - MainApp.bus().post(new EventOpenAPSUpdateGui()); + RxBus.INSTANCE.send(new EventOpenAPSUpdateGui()); //deviceStatus.suggested = determineBasalResultAMA.json; } @@ -269,4 +280,9 @@ public class OpenAPSSMBPlugin extends PluginBase implements APSInterface { return newvalue; } + public Constraint isSuperBolusEnabled(Constraint value) { + value.set(false); + return value; + } + } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/SMBDefaults.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/SMBDefaults.java similarity index 98% rename from app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/SMBDefaults.java rename to app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/SMBDefaults.java index 0ce8d2bb94..f6b8f20233 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/SMBDefaults.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/SMBDefaults.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.OpenAPSSMB; +package info.nightscout.androidaps.plugins.aps.openAPSSMB; /** * Created by mike on 10.12.2017. diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/bus/RxBus.kt b/app/src/main/java/info/nightscout/androidaps/plugins/bus/RxBus.kt new file mode 100644 index 0000000000..1774df1471 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/bus/RxBus.kt @@ -0,0 +1,23 @@ +package info.nightscout.androidaps.plugins.bus + +import info.nightscout.androidaps.events.Event +import io.reactivex.Observable +import io.reactivex.schedulers.Schedulers +import io.reactivex.subjects.PublishSubject + +// Use object so we have a singleton instance +object RxBus { + + private val publisher = PublishSubject.create() + + fun send(event: Event) { + publisher.onNext(event) + } + + // Listen should return an Observable and not the publisher + // Using ofType we filter only events that match that class type + fun toObservable(eventType: Class): Observable = + publisher + .subscribeOn(Schedulers.io()) + .ofType(eventType) +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/common/ManufacturerType.java b/app/src/main/java/info/nightscout/androidaps/plugins/common/ManufacturerType.java new file mode 100644 index 0000000000..0f61dd3320 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/common/ManufacturerType.java @@ -0,0 +1,27 @@ +package info.nightscout.androidaps.plugins.common; + +public enum ManufacturerType { + + AndroidAPS("AndroidAPS"), + Medtronic("Medtronic"), + Sooil("SOOIL"), + + Tandem("Tandem"), + Insulet("Insulet"), + Animas("Animas"), Cellnovo("Cellnovo"), Roche("Roche"); + + + + private String description; + + ManufacturerType(String description) { + + this.description = description; + } + + public String getDescription() { + return description; + } + + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/ConfigBuilderFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/ConfigBuilderFragment.kt new file mode 100644 index 0000000000..059bec1444 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/ConfigBuilderFragment.kt @@ -0,0 +1,98 @@ +package info.nightscout.androidaps.plugins.configBuilder + + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.LinearLayout +import android.widget.TextView +import androidx.annotation.StringRes +import androidx.fragment.app.Fragment +import info.nightscout.androidaps.MainApp +import info.nightscout.androidaps.R +import info.nightscout.androidaps.interfaces.* +import info.nightscout.androidaps.plugins.bus.RxBus +import info.nightscout.androidaps.utils.FabricPrivacy +import info.nightscout.androidaps.utils.PasswordProtection +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.disposables.CompositeDisposable +import kotlinx.android.synthetic.main.configbuilder_fragment.* +import java.util.* + +class ConfigBuilderFragment : Fragment() { + + private var disposable: CompositeDisposable = CompositeDisposable() + private val pluginViewHolders = ArrayList() + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle?): View? { + return inflater.inflate(R.layout.configbuilder_fragment, container, false) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + if (PasswordProtection.isLocked("settings_password")) + configbuilder_main_layout.visibility = View.GONE + else + unlock.visibility = View.GONE + + unlock.setOnClickListener { + PasswordProtection.QueryPassword(context, R.string.settings_password, "settings_password", { + configbuilder_main_layout.visibility = View.VISIBLE + unlock.visibility = View.GONE + }, null) + } + } + + @Synchronized + override fun onResume() { + super.onResume() + disposable.add(RxBus + .toObservable(EventConfigBuilderUpdateGui::class.java) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe({ + for (pluginViewHolder in pluginViewHolders) pluginViewHolder.update() + }, { + FabricPrivacy.logException(it) + })) + updateGUI() + } + + @Synchronized + override fun onPause() { + super.onPause() + disposable.clear() + } + + @Synchronized + private fun updateGUI() { + configbuilder_categories.removeAllViews() + createViewsForPlugins(R.string.configbuilder_profile, R.string.configbuilder_profile_description, PluginType.PROFILE, MainApp.getSpecificPluginsVisibleInListByInterface(ProfileInterface::class.java, PluginType.PROFILE)) + createViewsForPlugins(R.string.configbuilder_insulin, R.string.configbuilder_insulin_description, PluginType.INSULIN, MainApp.getSpecificPluginsVisibleInListByInterface(InsulinInterface::class.java, PluginType.INSULIN)) + createViewsForPlugins(R.string.configbuilder_bgsource, R.string.configbuilder_bgsource_description, PluginType.BGSOURCE, MainApp.getSpecificPluginsVisibleInListByInterface(BgSourceInterface::class.java, PluginType.BGSOURCE)) + createViewsForPlugins(R.string.configbuilder_pump, R.string.configbuilder_pump_description, PluginType.PUMP, MainApp.getSpecificPluginsVisibleInList(PluginType.PUMP)) + createViewsForPlugins(R.string.configbuilder_sensitivity, R.string.configbuilder_sensitivity_description, PluginType.SENSITIVITY, MainApp.getSpecificPluginsVisibleInListByInterface(SensitivityInterface::class.java, PluginType.SENSITIVITY)) + createViewsForPlugins(R.string.configbuilder_aps, R.string.configbuilder_aps_description, PluginType.APS, MainApp.getSpecificPluginsVisibleInList(PluginType.APS)) + createViewsForPlugins(R.string.configbuilder_loop, R.string.configbuilder_loop_description, PluginType.LOOP, MainApp.getSpecificPluginsVisibleInList(PluginType.LOOP)) + createViewsForPlugins(R.string.constraints, R.string.configbuilder_constraints_description, PluginType.CONSTRAINTS, MainApp.getSpecificPluginsVisibleInListByInterface(ConstraintsInterface::class.java, PluginType.CONSTRAINTS)) + createViewsForPlugins(R.string.configbuilder_treatments, R.string.configbuilder_treatments_description, PluginType.TREATMENT, MainApp.getSpecificPluginsVisibleInList(PluginType.TREATMENT)) + createViewsForPlugins(R.string.configbuilder_general, R.string.configbuilder_general_description, PluginType.GENERAL, MainApp.getSpecificPluginsVisibleInList(PluginType.GENERAL)) + } + + private fun createViewsForPlugins(@StringRes title: Int, @StringRes description: Int, pluginType: PluginType, plugins: List) { + if (plugins.size == 0) return + val parent = layoutInflater.inflate(R.layout.configbuilder_single_category, null) as LinearLayout + (parent.findViewById(R.id.category_title) as TextView).text = MainApp.gs(title) + (parent.findViewById(R.id.category_description) as TextView).text = MainApp.gs(description) + val pluginContainer = parent.findViewById(R.id.category_plugins) + for (plugin in plugins) { + val pluginViewHolder = PluginViewHolder(this, pluginType, plugin) + pluginContainer.addView(pluginViewHolder.baseView) + pluginViewHolders.add(pluginViewHolder) + } + configbuilder_categories.addView(parent) + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/ConfigBuilderPlugin.java similarity index 82% rename from app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderPlugin.java rename to app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/ConfigBuilderPlugin.java index 588ba2ac93..f43513fbf5 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/ConfigBuilderPlugin.java @@ -1,6 +1,6 @@ -package info.nightscout.androidaps.plugins.ConfigBuilder; +package info.nightscout.androidaps.plugins.configBuilder; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -20,11 +20,13 @@ import info.nightscout.androidaps.interfaces.ProfileInterface; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.interfaces.SensitivityInterface; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.Insulin.InsulinOrefRapidActingPlugin; -import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin; -import info.nightscout.androidaps.plugins.Sensitivity.SensitivityOref0Plugin; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.insulin.InsulinOrefRapidActingPlugin; +import info.nightscout.androidaps.plugins.profile.ns.NSProfilePlugin; +import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin; +import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref0Plugin; import info.nightscout.androidaps.queue.CommandQueue; -import info.nightscout.utils.SP; +import info.nightscout.androidaps.utils.SP; /** * Created by mike on 05.08.2016. @@ -57,7 +59,7 @@ public class ConfigBuilderPlugin extends PluginBase { .fragmentClass(ConfigBuilderFragment.class.getName()) .showInList(true) .alwaysEnabled(true) - .alwayVisible(false) + .alwaysVisible(false) .pluginName(R.string.configbuilder) .shortName(R.string.configbuilder_shortname) .description(R.string.description_config_builder) @@ -66,14 +68,12 @@ public class ConfigBuilderPlugin extends PluginBase { @Override protected void onStart() { - MainApp.bus().register(this); super.onStart(); } @Override protected void onStop() { super.onStop(); - MainApp.bus().unregister(this); } @@ -82,7 +82,7 @@ public class ConfigBuilderPlugin extends PluginBase { upgradeSettings(); loadSettings(); setAlwaysEnabledPluginsEnabled(); - MainApp.bus().post(new EventAppInitialized()); + RxBus.INSTANCE.send(new EventAppInitialized()); } private void setAlwaysEnabledPluginsEnabled() { @@ -102,7 +102,7 @@ public class ConfigBuilderPlugin extends PluginBase { for (PluginBase p : pluginList) { PluginType type = p.getType(); - if (p.pluginDescription.alwaysEnabled && p.pluginDescription.alwayVisible) + if (p.pluginDescription.alwaysEnabled && p.pluginDescription.alwaysVisible) continue; if (p.pluginDescription.alwaysEnabled && p.pluginDescription.neverVisible) continue; @@ -232,31 +232,37 @@ public class ConfigBuilderPlugin extends PluginBase { return commandQueue; } + @Nullable public BgSourceInterface getActiveBgSource() { return activeBgSource; } + @Nullable public ProfileInterface getActiveProfileInterface() { return activeProfile; } + @Nullable public InsulinInterface getActiveInsulin() { return activeInsulin; } + @Nullable public APSInterface getActiveAPS() { return activeAPS; } + @Nullable public PumpInterface getActivePump() { return activePump; } + @Nullable public SensitivityInterface getActiveSensitivity() { return activeSensitivity; } - void logPluginStatus() { + public void logPluginStatus() { if (L.isEnabled(L.CONFIGBUILDER)) for (PluginBase p : pluginList) { log.debug(p.getName() + ":" + @@ -399,4 +405,58 @@ public class ConfigBuilderPlugin extends PluginBase { return found; } + public void processOnEnabledCategoryChanged(PluginBase changedPlugin, PluginType type) { + ArrayList pluginsInCategory = null; + switch (type) { + // Multiple selection allowed + case GENERAL: + case CONSTRAINTS: + case LOOP: + break; + // Single selection allowed + case INSULIN: + pluginsInCategory = MainApp.getSpecificPluginsListByInterface(InsulinInterface.class); + break; + case SENSITIVITY: + pluginsInCategory = MainApp.getSpecificPluginsListByInterface(SensitivityInterface.class); + break; + case APS: + pluginsInCategory = MainApp.getSpecificPluginsListByInterface(APSInterface.class); + break; + case PROFILE: + pluginsInCategory = MainApp.getSpecificPluginsListByInterface(ProfileInterface.class); + break; + case BGSOURCE: + pluginsInCategory = MainApp.getSpecificPluginsListByInterface(BgSourceInterface.class); + break; + case TREATMENT: + case PUMP: + pluginsInCategory = MainApp.getSpecificPluginsListByInterface(PumpInterface.class); + break; + } + if (pluginsInCategory != null) { + boolean newSelection = changedPlugin.isEnabled(type); + if (newSelection) { // new plugin selected -> disable others + for (PluginBase p : pluginsInCategory) { + if (p.getName().equals(changedPlugin.getName())) { + // this is new selected + } else { + p.setPluginEnabled(type, false); + p.setFragmentVisible(type, false); + } + } + } else { // enable first plugin in list + if (type == PluginType.PUMP) + VirtualPumpPlugin.getPlugin().setPluginEnabled(type, true); + else if (type == PluginType.INSULIN) + InsulinOrefRapidActingPlugin.getPlugin().setPluginEnabled(type, true); + else if (type == PluginType.SENSITIVITY) + SensitivityOref0Plugin.getPlugin().setPluginEnabled(type, true); + else if (type == PluginType.PROFILE) + NSProfilePlugin.getPlugin().setPluginEnabled(type, true); + else + pluginsInCategory.get(0).setPluginEnabled(type, true); + } + } + } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/EventConfigBuilderUpdateGui.kt b/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/EventConfigBuilderUpdateGui.kt new file mode 100644 index 0000000000..e57fd79983 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/EventConfigBuilderUpdateGui.kt @@ -0,0 +1,6 @@ +package info.nightscout.androidaps.plugins.configBuilder + +import info.nightscout.androidaps.events.EventUpdateGui + +class EventConfigBuilderUpdateGui : EventUpdateGui() { +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/PluginViewHolder.kt b/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/PluginViewHolder.kt new file mode 100644 index 0000000000..86e0f39437 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/PluginViewHolder.kt @@ -0,0 +1,82 @@ +package info.nightscout.androidaps.plugins.configBuilder + +import android.content.Intent +import android.view.View +import android.widget.* +import info.nightscout.androidaps.R +import info.nightscout.androidaps.activities.PreferencesActivity +import info.nightscout.androidaps.events.EventRebuildTabs +import info.nightscout.androidaps.interfaces.PluginBase +import info.nightscout.androidaps.interfaces.PluginType +import info.nightscout.androidaps.plugins.bus.RxBus +import info.nightscout.androidaps.utils.PasswordProtection + +class PluginViewHolder internal constructor(private val fragment: ConfigBuilderFragment, + private val pluginType: PluginType, + private val plugin: PluginBase) { + + val baseView: LinearLayout = fragment.layoutInflater.inflate(R.layout.configbuilder_single_plugin, null) as LinearLayout + private val enabledExclusive: RadioButton + private val enabledInclusive: CheckBox + private val pluginName: TextView + private val pluginDescription: TextView + private val pluginPreferences: ImageButton + private val pluginVisibility: CheckBox + + init { + enabledExclusive = baseView.findViewById(R.id.plugin_enabled_exclusive) + enabledInclusive = baseView.findViewById(R.id.plugin_enabled_inclusive) + pluginName = baseView.findViewById(R.id.plugin_name) + pluginDescription = baseView.findViewById(R.id.plugin_description) + pluginPreferences = baseView.findViewById(R.id.plugin_preferences) + pluginVisibility = baseView.findViewById(R.id.plugin_visibility) + + pluginVisibility.setOnClickListener { + plugin.setFragmentVisible(pluginType, pluginVisibility.isChecked) + ConfigBuilderPlugin.getPlugin().storeSettings("CheckedCheckboxVisible") + RxBus.send(EventRebuildTabs()) + ConfigBuilderPlugin.getPlugin().logPluginStatus() + } + + enabledExclusive.setOnClickListener { + plugin.switchAllowed(if (enabledExclusive.visibility == View.VISIBLE) enabledExclusive.isChecked else enabledInclusive.isChecked, fragment.activity, pluginType) + } + enabledInclusive.setOnClickListener { + plugin.switchAllowed(if (enabledExclusive.visibility == View.VISIBLE) enabledExclusive.isChecked else enabledInclusive.isChecked, fragment.activity, pluginType) + } + + pluginPreferences.setOnClickListener { + PasswordProtection.QueryPassword(fragment.context, R.string.settings_password, "settings_password", { + val i = Intent(fragment.context, PreferencesActivity::class.java) + i.putExtra("id", plugin.preferencesId) + fragment.startActivity(i) + }, null) + } + update() + } + + fun update() { + enabledExclusive.visibility = if (areMultipleSelectionsAllowed(pluginType)) View.GONE else View.VISIBLE + enabledInclusive.visibility = if (areMultipleSelectionsAllowed(pluginType)) View.VISIBLE else View.GONE + enabledExclusive.isChecked = plugin.isEnabled(pluginType) + enabledInclusive.isChecked = plugin.isEnabled(pluginType) + enabledInclusive.isEnabled = !plugin.pluginDescription.alwaysEnabled + enabledExclusive.isEnabled = !plugin.pluginDescription.alwaysEnabled + pluginName.text = plugin.name + if (plugin.description == null) + pluginDescription.visibility = View.GONE + else { + pluginDescription.visibility = View.VISIBLE + pluginDescription.text = plugin.description + } + pluginPreferences.visibility = if (plugin.preferencesId == -1 || !plugin.isEnabled(pluginType)) View.INVISIBLE else View.VISIBLE + pluginVisibility.visibility = if (plugin.hasFragment()) View.VISIBLE else View.INVISIBLE + pluginVisibility.isEnabled = !(plugin.pluginDescription.neverVisible || plugin.pluginDescription.alwaysVisible) && plugin.isEnabled(pluginType) + pluginVisibility.isChecked = plugin.isFragmentVisible + } + + private fun areMultipleSelectionsAllowed(type: PluginType): Boolean { + return type == PluginType.GENERAL || type == PluginType.CONSTRAINTS || type == PluginType.LOOP + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/ProfileFunctions.java b/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/ProfileFunctions.java new file mode 100644 index 0000000000..025d8dac1e --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/ProfileFunctions.java @@ -0,0 +1,192 @@ +package info.nightscout.androidaps.plugins.configBuilder; + +import android.content.Intent; +import android.os.Bundle; + +import androidx.annotation.Nullable; + +import com.google.firebase.analytics.FirebaseAnalytics; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import info.nightscout.androidaps.BuildConfig; +import info.nightscout.androidaps.Constants; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.data.ProfileStore; +import info.nightscout.androidaps.db.ProfileSwitch; +import info.nightscout.androidaps.db.Source; +import info.nightscout.androidaps.events.EventNewBasalProfile; +import info.nightscout.androidaps.events.EventProfileNeedsUpdate; +import info.nightscout.androidaps.interfaces.ProfileInterface; +import info.nightscout.androidaps.interfaces.TreatmentsInterface; +import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.general.overview.dialogs.ErrorHelperActivity; +import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; +import info.nightscout.androidaps.queue.Callback; +import info.nightscout.androidaps.utils.FabricPrivacy; +import info.nightscout.androidaps.utils.SP; +import io.reactivex.disposables.CompositeDisposable; +import io.reactivex.schedulers.Schedulers; + +public class ProfileFunctions { + private static Logger log = LoggerFactory.getLogger(L.PROFILE); + private CompositeDisposable disposable = new CompositeDisposable(); + + private static ProfileFunctions profileFunctions = null; + + public static ProfileFunctions getInstance() { + if (profileFunctions == null) + profileFunctions = new ProfileFunctions(); + return profileFunctions; + } + + static { + ProfileFunctions.getInstance(); // register to bus at start + } + + private ProfileFunctions() { + disposable.add(RxBus.INSTANCE + .toObservable(EventProfileNeedsUpdate.class) + .observeOn(Schedulers.io()) + .subscribe(event -> { + if (L.isEnabled(L.PROFILE)) + log.debug("onProfileSwitch"); + ConfigBuilderPlugin.getPlugin().getCommandQueue().setProfile(getProfile(), new Callback() { + @Override + public void run() { + if (!result.success) { + Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class); + i.putExtra("soundid", R.raw.boluserror); + i.putExtra("status", result.comment); + i.putExtra("title", MainApp.gs(R.string.failedupdatebasalprofile)); + i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + MainApp.instance().startActivity(i); + } + if (result.enacted) + RxBus.INSTANCE.send(new EventNewBasalProfile()); + } + }); + }, FabricPrivacy::logException) + ); + } + + public String getProfileName() { + return getProfileName(System.currentTimeMillis()); + } + + public String getProfileName(boolean customized) { + return getProfileName(System.currentTimeMillis(), customized); + } + + public String getProfileName(long time) { + return getProfileName(time, true); + } + + public String getProfileName(long time, boolean customized) { + TreatmentsInterface activeTreatments = TreatmentsPlugin.getPlugin(); + ProfileInterface activeProfile = ConfigBuilderPlugin.getPlugin().getActiveProfileInterface(); + + ProfileSwitch profileSwitch = activeTreatments.getProfileSwitchFromHistory(time); + if (profileSwitch != null) { + if (profileSwitch.profileJson != null) { + return customized ? profileSwitch.getCustomizedName() : profileSwitch.profileName; + } else { + ProfileStore profileStore = activeProfile.getProfile(); + if (profileStore != null) { + Profile profile = profileStore.getSpecificProfile(profileSwitch.profileName); + if (profile != null) + return profileSwitch.profileName; + } + } + } + return MainApp.gs(R.string.noprofileselected); + } + + public boolean isProfileValid(String from) { + Profile profile = getProfile(); + return profile != null && profile.isValid(from); + } + + @Nullable + public Profile getProfile() { + return getProfile(System.currentTimeMillis()); + } + + public String getProfileUnits() { + Profile profile = getProfile(); + return profile != null ? profile.getUnits() : Constants.MGDL; + } + + @Nullable + public Profile getProfile(long time) { + TreatmentsInterface activeTreatments = TreatmentsPlugin.getPlugin(); + ProfileInterface activeProfile = ConfigBuilderPlugin.getPlugin().getActiveProfileInterface(); + + //log.debug("Profile for: " + new Date(time).toLocaleString() + " : " + getProfileName(time)); + ProfileSwitch profileSwitch = activeTreatments.getProfileSwitchFromHistory(time); + if (profileSwitch != null) { + if (profileSwitch.profileJson != null) { + return profileSwitch.getProfileObject(); + } else if (activeProfile.getProfile() != null) { + Profile profile = activeProfile.getProfile().getSpecificProfile(profileSwitch.profileName); + if (profile != null) + return profile; + } + } + if (activeTreatments.getProfileSwitchesFromHistory().size() > 0) { + Bundle bundle = new Bundle(); + bundle.putString(FirebaseAnalytics.Param.ITEM_ID, "CatchedError"); + bundle.putString(FirebaseAnalytics.Param.ITEM_CATEGORY, BuildConfig.BUILDVERSION); + bundle.putString(FirebaseAnalytics.Param.START_DATE, String.valueOf(time)); + bundle.putString(FirebaseAnalytics.Param.VALUE, activeTreatments.getProfileSwitchesFromHistory().toString()); + FabricPrivacy.getInstance().logCustom(bundle); + } + log.error("getProfile at the end: returning null"); + return null; + } + + public static ProfileSwitch prepareProfileSwitch(final ProfileStore profileStore, final String profileName, final int duration, final int percentage, final int timeshift, long date) { + ProfileSwitch profileSwitch = new ProfileSwitch(); + profileSwitch.date = date; + profileSwitch.source = Source.USER; + profileSwitch.profileName = profileName; + profileSwitch.profileJson = profileStore.getSpecificProfile(profileName).getData().toString(); + profileSwitch.profilePlugin = ConfigBuilderPlugin.getPlugin().getActiveProfileInterface().getClass().getName(); + profileSwitch.durationInMinutes = duration; + profileSwitch.isCPP = percentage != 100 || timeshift != 0; + profileSwitch.timeshift = timeshift; + profileSwitch.percentage = percentage; + return profileSwitch; + } + + public static void doProfileSwitch(final ProfileStore profileStore, final String profileName, final int duration, final int percentage, final int timeshift) { + ProfileSwitch profileSwitch = prepareProfileSwitch(profileStore, profileName, duration, percentage, timeshift, System.currentTimeMillis()); + TreatmentsPlugin.getPlugin().addToHistoryProfileSwitch(profileSwitch); + if (percentage == 90 && duration == 10) + SP.putBoolean(R.string.key_objectiveuseprofileswitch, true); + } + + public static void doProfileSwitch(final int duration, final int percentage, final int timeshift) { + ProfileSwitch profileSwitch = TreatmentsPlugin.getPlugin().getProfileSwitchFromHistory(System.currentTimeMillis()); + if (profileSwitch != null) { + profileSwitch = new ProfileSwitch(); + profileSwitch.date = System.currentTimeMillis(); + profileSwitch.source = Source.USER; + profileSwitch.profileName = getInstance().getProfileName(System.currentTimeMillis(), false); + profileSwitch.profileJson = getInstance().getProfile().getData().toString(); + profileSwitch.profilePlugin = ConfigBuilderPlugin.getPlugin().getActiveProfileInterface().getClass().getName(); + profileSwitch.durationInMinutes = duration; + profileSwitch.isCPP = percentage != 100 || timeshift != 0; + profileSwitch.timeshift = timeshift; + profileSwitch.percentage = percentage; + TreatmentsPlugin.getPlugin().addToHistoryProfileSwitch(profileSwitch); + } else { + log.error("No profile switch existing"); + } + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/dstHelper/DstHelperPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/dstHelper/DstHelperPlugin.java new file mode 100644 index 0000000000..e026d6589d --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/dstHelper/DstHelperPlugin.java @@ -0,0 +1,95 @@ +package info.nightscout.androidaps.plugins.constraints.dstHelper; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Calendar; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.interfaces.Constraint; +import info.nightscout.androidaps.interfaces.ConstraintsInterface; +import info.nightscout.androidaps.interfaces.PluginBase; +import info.nightscout.androidaps.interfaces.PluginDescription; +import info.nightscout.androidaps.interfaces.PluginType; +import info.nightscout.androidaps.interfaces.PumpInterface; +import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; + +public class DstHelperPlugin extends PluginBase implements ConstraintsInterface { + public static final int DISABLE_TIMEFRAME_HOURS = -3; + public static final int WARN_PRIOR_TIMEFRAME_HOURS = 24; + private static Logger log = LoggerFactory.getLogger(L.CONSTRAINTS); + + static DstHelperPlugin plugin = null; + + public static DstHelperPlugin getPlugin() { + if (plugin == null) + plugin = new DstHelperPlugin(); + return plugin; + } + + public DstHelperPlugin() { + super(new PluginDescription() + .mainType(PluginType.CONSTRAINTS) + .neverVisible(true) + .alwaysEnabled(true) + .showInList(false) + .pluginName(R.string.dst_plugin_name) + ); + } + + public static boolean wasDST(Calendar now) { + Calendar ago = (Calendar) now.clone(); + ago.add(Calendar.HOUR, DISABLE_TIMEFRAME_HOURS); + return now.get(Calendar.DST_OFFSET) != ago.get(Calendar.DST_OFFSET); + } + + public static boolean willBeDST(Calendar now) { + Calendar ago = (Calendar) now.clone(); + ago.add(Calendar.HOUR, WARN_PRIOR_TIMEFRAME_HOURS); + return now.get(Calendar.DST_OFFSET) != ago.get(Calendar.DST_OFFSET); + } + + //Return false if time to DST change happened in the last 3 hours. + @Override + public Constraint isLoopInvocationAllowed(Constraint value) { + + PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump(); + if (pump == null || pump.canHandleDST()) { + log.debug("Pump can handle DST"); + return value; + } + + Calendar cal = Calendar.getInstance(); + + if (willBeDST(cal)) { + warnUser(Notification.DST_IN_24H, MainApp.gs(R.string.dst_in_24h_warning)); + } + + if (!value.value()) { + log.debug("Already not allowed - don't check further"); + return value; + } + + if (wasDST(cal)) { + LoopPlugin loopPlugin = LoopPlugin.getPlugin(); + if (!loopPlugin.isSuspended()) { + warnUser(Notification.DST_LOOP_DISABLED, MainApp.gs(R.string.dst_loop_disabled_warning)); + } else { + log.debug("Loop already suspended"); + } + value.set(false, "DST in last 3 hours.", this); + } + return value; + } + + private void warnUser(int id, String warningText) { + Notification notification = new Notification(id, warningText, Notification.LOW); + RxBus.INSTANCE.send(new EventNewNotification(notification)); + } +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/ObjectivesFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/ObjectivesFragment.kt new file mode 100644 index 0000000000..aafd877672 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/ObjectivesFragment.kt @@ -0,0 +1,321 @@ +package info.nightscout.androidaps.plugins.constraints.objectives + +import android.graphics.Color +import android.os.Bundle +import android.os.Handler +import android.os.Looper +import android.view.Gravity +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.Button +import android.widget.EditText +import android.widget.LinearLayout +import android.widget.TextView +import androidx.fragment.app.Fragment +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.LinearSmoothScroller +import androidx.recyclerview.widget.RecyclerView +import info.nightscout.androidaps.MainApp +import info.nightscout.androidaps.R +import info.nightscout.androidaps.logging.L +import info.nightscout.androidaps.plugins.bus.RxBus +import info.nightscout.androidaps.plugins.constraints.objectives.activities.ObjectivesExamDialog +import info.nightscout.androidaps.plugins.constraints.objectives.events.EventObjectivesUpdateGui +import info.nightscout.androidaps.plugins.constraints.objectives.objectives.Objective.ExamTask +import info.nightscout.androidaps.receivers.NetworkChangeReceiver +import info.nightscout.androidaps.utils.* +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.disposables.CompositeDisposable +import kotlinx.android.synthetic.main.objectives_fragment.* +import org.slf4j.LoggerFactory + +class ObjectivesFragment : Fragment() { + private val log = LoggerFactory.getLogger(L.CONSTRAINTS) + private val objectivesAdapter = ObjectivesAdapter() + private val handler = Handler(Looper.getMainLooper()) + + private var disposable: CompositeDisposable = CompositeDisposable() + + private val objectiveUpdater = object : Runnable { + override fun run() { + handler.postDelayed(this, (60 * 1000).toLong()) + updateGUI() + } + } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle?): View? { + return inflater.inflate(R.layout.objectives_fragment, container, false) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + objectives_recyclerview.layoutManager = LinearLayoutManager(view.context) + objectives_recyclerview.adapter = objectivesAdapter + objectives_fake.setOnClickListener { updateGUI() } + objectives_reset.setOnClickListener { + ObjectivesPlugin.reset() + objectives_recyclerview.adapter?.notifyDataSetChanged() + scrollToCurrentObjective() + } + scrollToCurrentObjective() + startUpdateTimer() + } + + @Synchronized + override fun onResume() { + super.onResume() + disposable.add(RxBus + .toObservable(EventObjectivesUpdateGui::class.java) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe({ + objectives_recyclerview.adapter?.notifyDataSetChanged() + }, { + FabricPrivacy.logException(it) + }) + ) + } + + @Synchronized + override fun onPause() { + super.onPause() + disposable.clear() + } + + @Synchronized + override fun onDestroyView() { + super.onDestroyView() + handler.removeCallbacks(objectiveUpdater) + } + + private fun startUpdateTimer() { + handler.removeCallbacks(objectiveUpdater) + for (objective in ObjectivesPlugin.objectives) { + if (objective.isStarted && !objective.isAccomplished) { + val timeTillNextMinute = (System.currentTimeMillis() - objective.startedOn) % (60 * 1000) + handler.postDelayed(objectiveUpdater, timeTillNextMinute) + break + } + } + } + + private fun scrollToCurrentObjective() { + for (i in 0 until ObjectivesPlugin.objectives.size) { + val objective = ObjectivesPlugin.objectives[i] + if (!objective.isStarted || !objective.isAccomplished) { + context?.let { + val smoothScroller = object : LinearSmoothScroller(it) { + override fun getVerticalSnapPreference(): Int = SNAP_TO_START + override fun calculateTimeForScrolling(dx: Int): Int = super.calculateTimeForScrolling(dx) * 4 + } + smoothScroller.targetPosition = i + objectives_recyclerview.layoutManager?.startSmoothScroll(smoothScroller) + } + break + } + } + } + + private inner class ObjectivesAdapter : RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + return ViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.objectives_item, parent, false)) + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + val objective = ObjectivesPlugin.objectives[position] + holder.title.text = MainApp.gs(R.string.nth_objective, position + 1) + holder.revert.visibility = View.GONE + if (objective.objective != 0) { + holder.objective.visibility = View.VISIBLE + holder.objective.text = MainApp.gs(objective.objective) + } else + holder.objective.visibility = View.GONE + if (objective.gate != 0) { + holder.gate.visibility = View.VISIBLE + holder.gate.text = MainApp.gs(objective.gate) + } else + holder.gate.visibility = View.GONE + if (!objective.isStarted) { + holder.gate.setTextColor(-0x1) + holder.verify.visibility = View.GONE + holder.progress.visibility = View.GONE + holder.accomplished.visibility = View.GONE + if (position == 0 || ObjectivesPlugin.objectives[position - 1].isAccomplished) + holder.start.visibility = View.VISIBLE + else + holder.start.visibility = View.GONE + } else if (objective.isAccomplished) { + holder.gate.setTextColor(-0xb350b0) + holder.verify.visibility = View.GONE + holder.progress.visibility = View.GONE + holder.start.visibility = View.GONE + holder.accomplished.visibility = View.VISIBLE + } else if (objective.isStarted) { + holder.gate.setTextColor(-0x1) + holder.verify.visibility = View.VISIBLE + holder.verify.isEnabled = objective.isCompleted || objectives_fake.isChecked + holder.start.visibility = View.GONE + holder.accomplished.visibility = View.GONE + if (objective.isRevertable) { + holder.revert.visibility = View.VISIBLE + } + holder.progress.visibility = View.VISIBLE + holder.progress.removeAllViews() + for (task in objective.tasks) { + if (task.shouldBeIgnored()) continue + // name + val name = TextView(holder.progress.context) + name.text = MainApp.gs(task.task) + ":" + name.setTextColor(-0x1) + holder.progress.addView(name, LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT) + // hint + task.hints.forEach { h -> + if (!task.isCompleted) + holder.progress.addView(h.generate(context)) + } + // state + val state = TextView(holder.progress.context) + state.setTextColor(-0x1) + val basicHTML = "%2\$s" + val formattedHTML = String.format(basicHTML, if (task.isCompleted) "#4CAF50" else "#FF9800", task.progress) + state.text = HtmlHelper.fromHtml(formattedHTML) + state.gravity = Gravity.END + holder.progress.addView(state, LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT) + if (task is ExamTask) { + state.setOnClickListener { + val dialog = ObjectivesExamDialog() + val bundle = Bundle() + val taskPosition = objective.tasks.indexOf(task) + bundle.putInt("currentTask", taskPosition) + dialog.arguments = bundle + ObjectivesExamDialog.objective = objective + fragmentManager?.let { dialog.show(it, "ObjectivesFragment") } + } + } + // horizontal line + val separator = View(holder.progress.context) + separator.setBackgroundColor(Color.DKGRAY) + holder.progress.addView(separator, LinearLayout.LayoutParams.MATCH_PARENT, 2) + } + } + holder.accomplished.text = MainApp.gs(R.string.accomplished, DateUtil.dateAndTimeString(objective.accomplishedOn)) + holder.accomplished.setTextColor(-0x3e3e3f) + holder.verify.setOnClickListener { + holder.verify.visibility = View.INVISIBLE + NetworkChangeReceiver.fetch() + if (objectives_fake.isChecked) { + objective.accomplishedOn = DateUtil.now() + scrollToCurrentObjective() + startUpdateTimer() + RxBus.send(EventObjectivesUpdateGui()) + } else + SntpClient.ntpTime(object : SntpClient.Callback() { + override fun run() { + activity?.runOnUiThread { + holder.verify.visibility = View.VISIBLE + log.debug("NTP time: $time System time: ${DateUtil.now()}") + if (!networkConnected) { + ToastUtils.showToastInUiThread(context, R.string.notconnected) + } else if (success) { + if (objective.isCompleted(time)) { + objective.accomplishedOn = time + scrollToCurrentObjective() + startUpdateTimer() + RxBus.send(EventObjectivesUpdateGui()) + } else { + ToastUtils.showToastInUiThread(context, R.string.requirementnotmet) + } + } else { + ToastUtils.showToastInUiThread(context, R.string.failedretrievetime) + } + } + } + }, NetworkChangeReceiver.isConnected()) + } + holder.start.setOnClickListener { + holder.start.visibility = View.INVISIBLE + NetworkChangeReceiver.fetch() + if (objectives_fake.isChecked) { + objective.startedOn = DateUtil.now() + scrollToCurrentObjective() + startUpdateTimer() + RxBus.send(EventObjectivesUpdateGui()) + } else + SntpClient.ntpTime(object : SntpClient.Callback() { + override fun run() { + activity?.runOnUiThread { + holder.start.visibility = View.VISIBLE + log.debug("NTP time: $time System time: ${DateUtil.now()}") + if (!networkConnected) { + ToastUtils.showToastInUiThread(context, R.string.notconnected) + } else if (success) { + objective.startedOn = time + scrollToCurrentObjective() + startUpdateTimer() + RxBus.send(EventObjectivesUpdateGui()) + } else { + ToastUtils.showToastInUiThread(context, R.string.failedretrievetime) + } + } + } + }, NetworkChangeReceiver.isConnected()) + } + holder.revert.setOnClickListener { + objective.accomplishedOn = 0 + objective.startedOn = 0 + if (position > 0) { + val prevObj = ObjectivesPlugin.objectives[position - 1] + prevObj.accomplishedOn = 0 + } + scrollToCurrentObjective() + RxBus.send(EventObjectivesUpdateGui()) + } + if (objective.hasSpecialInput && !objective.isAccomplished && objective.isStarted) { + // generate random request code if none exists + val request = SP.getString(R.string.key_objectives_request_code, String.format("%1$05d", (Math.random() * 99999).toInt())) + SP.putString(R.string.key_objectives_request_code, request) + holder.requestCode.text = MainApp.gs(R.string.requestcode, request) + holder.requestCode.visibility = View.VISIBLE + holder.enterButton.visibility = View.VISIBLE + holder.input.visibility = View.VISIBLE + holder.inputHint.visibility = View.VISIBLE + holder.enterButton.setOnClickListener { + val input = holder.input.text.toString() + objective.specialAction(activity, input) + RxBus.send(EventObjectivesUpdateGui()) + } + } else { + holder.enterButton.visibility = View.GONE + holder.input.visibility = View.GONE + holder.inputHint.visibility = View.GONE + holder.requestCode.visibility = View.GONE + } + } + + + override fun getItemCount(): Int { + return ObjectivesPlugin.objectives.size + } + + inner class ViewHolder internal constructor(itemView: View) : RecyclerView.ViewHolder(itemView) { + val title: TextView = itemView.findViewById(R.id.objective_title) + val objective: TextView = itemView.findViewById(R.id.objective_objective) + val gate: TextView = itemView.findViewById(R.id.objective_gate) + val accomplished: TextView = itemView.findViewById(R.id.objective_accomplished) + val progress: LinearLayout = itemView.findViewById(R.id.objective_progress) + val verify: Button = itemView.findViewById(R.id.objective_verify) + val start: Button = itemView.findViewById(R.id.objective_start) + val revert: Button = itemView.findViewById(R.id.objective_back) + val inputHint: TextView = itemView.findViewById(R.id.objective_inputhint) + val input: EditText = itemView.findViewById(R.id.objective_input) + val enterButton: Button = itemView.findViewById(R.id.objective_enterbutton) + val requestCode: TextView = itemView.findViewById(R.id.objective_requestcode) + } + } + + fun updateGUI() { + activity?.runOnUiThread { objectivesAdapter.notifyDataSetChanged() } + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/ObjectivesPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/ObjectivesPlugin.kt new file mode 100644 index 0000000000..ca3e1d3126 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/ObjectivesPlugin.kt @@ -0,0 +1,170 @@ +package info.nightscout.androidaps.plugins.constraints.objectives + +import android.app.Activity +import com.google.common.base.Charsets +import com.google.common.hash.Hashing +import info.nightscout.androidaps.BuildConfig +import info.nightscout.androidaps.Config +import info.nightscout.androidaps.MainApp +import info.nightscout.androidaps.R +import info.nightscout.androidaps.interfaces.* +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin +import info.nightscout.androidaps.plugins.constraints.objectives.objectives.* +import info.nightscout.androidaps.utils.DateUtil +import info.nightscout.androidaps.utils.OKDialog +import info.nightscout.androidaps.utils.SP +import java.util.* + +/** + * Created by mike on 05.08.2016. + */ +object ObjectivesPlugin : PluginBase(PluginDescription() + .mainType(PluginType.CONSTRAINTS) + .fragmentClass(ObjectivesFragment::class.qualifiedName) + .alwaysEnabled(Config.APS) + .showInList(Config.APS) + .pluginName(R.string.objectives) + .shortName(R.string.objectives_shortname) + .description(R.string.description_objectives)), ConstraintsInterface { + + var objectives: MutableList = ArrayList() + + val FIRST_OBJECTIVE = 0 + val USAGE_OBJECTIVE = 1 + val EXAM_OBJECTIVE = 2 + val OPENLOOP_OBJECTIVE = 3 + val MAXBASAL_OBJECTIVE = 4 + val MAXIOB_ZERO_CL_OBJECTIVE = 5 + val MAXIOB_OBJECTIVE = 6 + val AUTOSENS_OBJECTIVE = 7 + val AMA_OBJECTIVE = 8 + val SMB_OBJECTIVE = 9 + + init { + convertSP() + setupObjectives() + } + + override fun specialEnableCondition(): Boolean { + val pump = ConfigBuilderPlugin.getPlugin().activePump + return pump == null || pump.pumpDescription.isTempBasalCapable + } + + // convert 2.3 SP version + private fun convertSP() { + doConvertSP(0, "config") + doConvertSP(1, "openloop") + doConvertSP(2, "maxbasal") + doConvertSP(3, "maxiobzero") + doConvertSP(4, "maxiob") + doConvertSP(5, "autosens") + doConvertSP(6, "ama") + doConvertSP(7, "smb") + } + + private fun doConvertSP(number: Int, name: String) { + if (!SP.contains("Objectives_" + name + "_started")) { + SP.putLong("Objectives_" + name + "_started", SP.getLong("Objectives" + number + "started", 0L)) + SP.putLong("Objectives_" + name + "_accomplished", SP.getLong("Objectives" + number + "accomplished", 0L)) + } + // TODO: we can remove Objectives1accomplished sometimes later + } + + private fun setupObjectives() { + objectives.clear() + objectives.add(Objective0()) + objectives.add(Objective1()) + objectives.add(Objective2()) + objectives.add(Objective3()) + objectives.add(Objective4()) + objectives.add(Objective5()) + objectives.add(Objective6()) + objectives.add(Objective7()) + objectives.add(Objective8()) + objectives.add(Objective9()) + } + + fun reset() { + for (objective in objectives) { + objective.startedOn = 0 + objective.accomplishedOn = 0 + } + SP.putBoolean(R.string.key_ObjectivesbgIsAvailableInNS, false) + SP.putBoolean(R.string.key_ObjectivespumpStatusIsAvailableInNS, false) + SP.putInt(R.string.key_ObjectivesmanualEnacts, 0) + SP.putBoolean(R.string.key_objectiveuseprofileswitch, false) + SP.putBoolean(R.string.key_objectiveusedisconnect, false) + SP.putBoolean(R.string.key_objectiveusereconnect, false) + SP.putBoolean(R.string.key_objectiveusetemptarget, false) + SP.putBoolean(R.string.key_objectiveuseactions, false) + SP.putBoolean(R.string.key_objectiveuseloop, false) + SP.putBoolean(R.string.key_objectiveusescale, false) + } + + fun completeObjectives(activity: Activity, request: String) { + val requestCode = SP.getString(R.string.key_objectives_request_code, "") + var url = SP.getString(R.string.key_nsclientinternal_url, "").toLowerCase() + if (!url.endsWith("\"")) url = "$url/" + val hashNS = Hashing.sha1().hashString(url + BuildConfig.APPLICATION_ID + "/" + requestCode, Charsets.UTF_8).toString() + if (request.equals(hashNS.substring(0, 10), ignoreCase = true)) { + SP.putLong("Objectives_" + "openloop" + "_started", DateUtil.now()) + SP.putLong("Objectives_" + "openloop" + "_accomplished", DateUtil.now()) + SP.putLong("Objectives_" + "maxbasal" + "_started", DateUtil.now()) + SP.putLong("Objectives_" + "maxbasal" + "_accomplished", DateUtil.now()) + SP.putLong("Objectives_" + "maxiobzero" + "_started", DateUtil.now()) + SP.putLong("Objectives_" + "maxiobzero" + "_accomplished", DateUtil.now()) + SP.putLong("Objectives_" + "maxiob" + "_started", DateUtil.now()) + SP.putLong("Objectives_" + "maxiob" + "_accomplished", DateUtil.now()) + SP.putLong("Objectives_" + "autosens" + "_started", DateUtil.now()) + SP.putLong("Objectives_" + "autosens" + "_accomplished", DateUtil.now()) + SP.putLong("Objectives_" + "ama" + "_started", DateUtil.now()) + SP.putLong("Objectives_" + "ama" + "_accomplished", DateUtil.now()) + SP.putLong("Objectives_" + "smb" + "_started", DateUtil.now()) + SP.putLong("Objectives_" + "smb" + "_accomplished", DateUtil.now()) + setupObjectives() + OKDialog.show(activity, "", MainApp.gs(R.string.codeaccepted), null) + } else { + OKDialog.show(activity, "", MainApp.gs(R.string.codeinvalid), null) + } + } + + /** + * Constraints interface + */ + override fun isLoopInvocationAllowed(value: Constraint): Constraint { + if (!objectives[FIRST_OBJECTIVE].isStarted) + value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), FIRST_OBJECTIVE + 1), this) + return value + } + + override fun isClosedLoopAllowed(value: Constraint): Constraint { + if (!objectives[MAXIOB_ZERO_CL_OBJECTIVE].isStarted) + value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), MAXIOB_ZERO_CL_OBJECTIVE + 1), this) + return value + } + + override fun isAutosensModeEnabled(value: Constraint): Constraint { + if (!objectives[AUTOSENS_OBJECTIVE].isStarted) + value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), AUTOSENS_OBJECTIVE + 1), this) + return value + } + + override fun isAMAModeEnabled(value: Constraint): Constraint { + if (!objectives[AMA_OBJECTIVE].isStarted) + value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), AMA_OBJECTIVE + 1), this) + return value + } + + override fun isSMBModeEnabled(value: Constraint): Constraint { + if (!objectives[SMB_OBJECTIVE].isStarted) + value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), SMB_OBJECTIVE + 1), this) + return value + } + + override fun applyMaxIOBConstraints(maxIob: Constraint): Constraint { + if (objectives[MAXIOB_ZERO_CL_OBJECTIVE].isStarted && !objectives[MAXIOB_ZERO_CL_OBJECTIVE].isAccomplished) + maxIob.set(0.0, String.format(MainApp.gs(R.string.objectivenotfinished), MAXIOB_ZERO_CL_OBJECTIVE + 1), this) + return maxIob + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/activities/ObjectivesExamDialog.kt b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/activities/ObjectivesExamDialog.kt new file mode 100644 index 0000000000..1428652be5 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/activities/ObjectivesExamDialog.kt @@ -0,0 +1,130 @@ +package info.nightscout.androidaps.plugins.constraints.objectives.activities + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.DialogFragment +import info.nightscout.androidaps.MainApp +import info.nightscout.androidaps.R +import info.nightscout.androidaps.plugins.bus.RxBus +import info.nightscout.androidaps.plugins.constraints.objectives.events.EventObjectivesUpdateGui +import info.nightscout.androidaps.plugins.constraints.objectives.objectives.Objective +import info.nightscout.androidaps.plugins.constraints.objectives.objectives.Objective.* +import info.nightscout.androidaps.utils.DateUtil +import info.nightscout.androidaps.utils.OKDialog +import info.nightscout.androidaps.utils.T +import info.nightscout.androidaps.utils.ToastUtils +import kotlinx.android.synthetic.main.objectives_exam_fragment.* + +class ObjectivesExamDialog : DialogFragment() { + companion object { + var objective: Objective? = null + } + + var currentTask = 0 + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle?): View? { + // load data from bundle + (savedInstanceState ?: arguments)?.let { bundle -> + currentTask = bundle.getInt("currentTask", 0) + } + + return inflater.inflate(R.layout.objectives_exam_fragment, container, false) + } + + override fun onStart() { + super.onStart() + dialog?.setCanceledOnTouchOutside(false) + dialog?.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); + } + + override fun onResume() { + super.onResume() + updateGui() + } + + override fun onSaveInstanceState(bundle: Bundle) { + super.onSaveInstanceState(bundle) + bundle.putInt("currentTask", currentTask) + } + + fun updateGui() { + objective?.let { objective -> + val task: ExamTask = objective.tasks[currentTask] as ExamTask + objectives_exam_name.setText(task.task) + objectives_exam_question.setText(task.question) + // Options + objectives_exam_options.removeAllViews() + task.options.forEach { + val cb = it.generate(context) + if (task.answered) { + cb.isEnabled = false + if (it.isCorrect) + cb.isChecked = true + } + objectives_exam_options.addView(cb) + } + // Hints + objectives_exam_hints.removeAllViews() + for (h in task.hints) { + objectives_exam_hints.addView(h.generate(context)) + } + // Disabled to + objectives_exam_disabledto.text = MainApp.gs(R.string.answerdisabledto, DateUtil.timeString(task.disabledTo)) + objectives_exam_disabledto.visibility = if (task.isEnabledAnswer) View.GONE else View.VISIBLE + // Buttons + objectives_exam_verify.isEnabled = !task.answered && task.isEnabledAnswer + objectives_exam_verify.setOnClickListener { + var result = true + for (o in task.options) { + val option: Option = o as Option; + result = result && option.evaluate() + } + task.setAnswered(result); + if (!result) { + task.disabledTo = DateUtil.now() + T.hours(1).msecs() + ToastUtils.showToastInUiThread(context, R.string.wronganswer) + } else task.disabledTo = 0 + updateGui() + RxBus.send(EventObjectivesUpdateGui()) + } + close.setOnClickListener { dismiss() } + objectives_exam_reset.setOnClickListener { + task.answered = false + //task.disabledTo = 0 + updateGui() + RxBus.send(EventObjectivesUpdateGui()) + } + objectives_back_button.isEnabled = currentTask != 0 + objectives_back_button.setOnClickListener { + currentTask-- + updateGui() + } + objectives_next_button.isEnabled = currentTask != objective.tasks.size - 1 + objectives_next_button.setOnClickListener { + currentTask++ + updateGui() + } + + objectives_next_unanswered_button.isEnabled = !objective.isCompleted + objectives_next_unanswered_button.setOnClickListener { + for (i in (currentTask + 1)..(objective.tasks.size - 1)) { + if (!objective.tasks[i].isCompleted) { + currentTask = i + updateGui() + return@setOnClickListener + } + } + for (i in 0..currentTask) { + if (!objective.tasks[i].isCompleted) { + currentTask = i + updateGui() + return@setOnClickListener + } + } + } + } + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/events/EventObjectivesUpdateGui.kt b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/events/EventObjectivesUpdateGui.kt new file mode 100644 index 0000000000..fd59db7d9f --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/events/EventObjectivesUpdateGui.kt @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.constraints.objectives.events + +import info.nightscout.androidaps.events.EventUpdateGui + +class EventObjectivesUpdateGui : EventUpdateGui() \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective.java new file mode 100644 index 0000000000..c882a921f5 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective.java @@ -0,0 +1,289 @@ +package info.nightscout.androidaps.plugins.constraints.objectives.objectives; + +import android.app.Activity; +import android.content.Context; +import android.graphics.Color; +import android.text.util.Linkify; +import android.view.View; +import android.widget.CheckBox; +import android.widget.TextView; + +import androidx.annotation.StringRes; + +import java.util.ArrayList; +import java.util.List; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.SP; +import info.nightscout.androidaps.utils.T; + +public abstract class Objective { + + private String spName; + @StringRes + private int objective; + @StringRes + private int gate; + private long startedOn; + private long accomplishedOn; + List tasks = new ArrayList<>(); + public boolean hasSpecialInput = false; + + public Objective(String spName, @StringRes int objective, @StringRes int gate) { + this.spName = spName; + this.objective = objective; + this.gate = gate; + startedOn = SP.getLong("Objectives_" + spName + "_started", 0L); + accomplishedOn = SP.getLong("Objectives_" + spName + "_accomplished", 0L); + if ((accomplishedOn - DateUtil.now()) > T.hours(3).msecs() || (startedOn - DateUtil.now()) > T.hours(3).msecs()) { // more than 3 hours in the future + startedOn = 0; + accomplishedOn = 0; + } + setupTasks(tasks); + for (Task task : tasks) task.objective = this; + } + + public boolean isCompleted() { + for (Task task : tasks) { + if (!task.shouldBeIgnored() && !task.isCompleted()) + return false; + } + return true; + } + + public boolean isCompleted(long trueTime) { + for (Task task : tasks) { + if (!task.shouldBeIgnored() && !task.isCompleted(trueTime)) + return false; + } + return true; + } + + public boolean isRevertable() { + return false; + } + + public boolean isAccomplished() { + return accomplishedOn != 0 && accomplishedOn < DateUtil.now(); + } + + public boolean isStarted() { + return startedOn != 0; + } + + public long getStartedOn() { + return startedOn; + } + + public int getObjective() { + return objective; + } + + public int getGate() { + return gate; + } + + public void setStartedOn(long startedOn) { + this.startedOn = startedOn; + SP.putLong("Objectives_" + spName + "_started", startedOn); + } + + public void setAccomplishedOn(long accomplishedOn) { + this.accomplishedOn = accomplishedOn; + SP.putLong("Objectives_" + spName + "_accomplished", accomplishedOn); + } + + public long getAccomplishedOn() { + return accomplishedOn; + } + + protected void setupTasks(List tasks) { + + } + + public List getTasks() { + return tasks; + } + + public void specialAction(Activity activity, String input) {} + + public abstract class Task { + @StringRes + private int task; + private Objective objective; + ArrayList hints = new ArrayList<>(); + + public Task(@StringRes int task) { + this.task = task; + } + + public @StringRes int getTask() { + return task; + } + + protected Objective getObjective() { + return objective; + } + + public abstract boolean isCompleted(); + public boolean isCompleted(long trueTime) { return isCompleted(); }; + + public String getProgress() { + return MainApp.gs(isCompleted() ? R.string.completed_well_done : R.string.not_completed_yet); + } + + Task hint(Hint hint) { + hints.add(hint); + return this; + } + + public ArrayList getHints() { + return hints; + } + + public boolean shouldBeIgnored() { + return false; + } + } + + public class MinimumDurationTask extends Task { + + private long minimumDuration; + + MinimumDurationTask(long minimumDuration) { + super(R.string.time_elapsed); + this.minimumDuration = minimumDuration; + } + + @Override + public boolean isCompleted() { + return getObjective().isStarted() && System.currentTimeMillis() - getObjective().getStartedOn() >= minimumDuration; + } + + @Override + public boolean isCompleted(long trueTime) { + return getObjective().isStarted() && trueTime - getObjective().getStartedOn() >= minimumDuration; + } + + @Override + public String getProgress() { + return getDurationText(System.currentTimeMillis() - getObjective().getStartedOn()) + + " / " + getDurationText(minimumDuration); + } + + private String getDurationText(long duration) { + int days = (int) Math.floor((double) duration / T.days(1).msecs()); + int hours = (int) Math.floor((double) duration / T.hours(1).msecs()); + int minutes = (int) Math.floor((double) duration / T.mins(1).msecs()); + if (days > 0) return MainApp.gq(R.plurals.objective_days, days, days); + else if (hours > 0) return MainApp.gq(R.plurals.objective_hours, hours, hours); + else return MainApp.gq(R.plurals.objective_minutes, minutes, minutes); + } + } + + public class ExamTask extends Task { + @StringRes + int question; + ArrayList

* Most of this defintions is intended for VirtualPump only, but they can be used by other plugins. */ public enum PumpType { - GenericAAPS("Generic AAPS", 0.1d, null, // - new DoseSettings(0.05d, 30, 8*60, 0.05d), // + GenericAAPS("Generic AAPS", ManufacturerType.AndroidAPS, "VirutalPump", 0.1d, null, // + new DoseSettings(0.05d, 30, 8 * 60, 0.05d), // PumpTempBasalType.Percent, // - new DoseSettings(10,30, 24*60, 0d, 500d), PumpCapability.BasalRate_Duration15and30minAllowed, // + new DoseSettings(10, 30, 24 * 60, 0d, 500d), PumpCapability.BasalRate_Duration15and30minAllowed, // 0.01d, 0.01d, null, PumpCapability.VirtualPumpCapabilities), // // Cellnovo - Cellnovo1("Cellnovo", 0.05d, null, // - new DoseSettings(0.05d, 30, 24*60, 1d, null), + Cellnovo1("Cellnovo", ManufacturerType.Cellnovo, "Cellnovo", 0.05d, null, // + new DoseSettings(0.05d, 30, 24 * 60, 1d, null), PumpTempBasalType.Percent, - new DoseSettings(5,30, 24*60, 0d, 200d), PumpCapability.BasalRate_Duration30minAllowed, // + new DoseSettings(5, 30, 24 * 60, 0d, 200d), PumpCapability.BasalRate_Duration30minAllowed, // 0.05d, 0.05d, null, PumpCapability.VirtualPumpCapabilities), // // Accu-Chek - AccuChekCombo("Accu-Chek Combo", 0.1d, null, // - new DoseSettings(0.1d, 15, 12*60, 0.1d), // + AccuChekCombo("Accu-Chek Combo", ManufacturerType.Roche, "Combo", 0.1d, null, // + new DoseSettings(0.1d, 15, 12 * 60, 0.1d), // PumpTempBasalType.Percent, - new DoseSettings(10, 15, 12*60,0d, 500d), PumpCapability.BasalRate_Duration15and30minAllowed, // + new DoseSettings(10, 15, 12 * 60, 0d, 500d), PumpCapability.BasalRate_Duration15and30minAllowed, // 0.01d, 0.01d, DoseStepSize.ComboBasal, PumpCapability.ComboCapabilities), // - AccuChekSpirit("Accu-Chek Spirit", 0.1d, null, // - new DoseSettings(0.1d, 15, 12*60, 0.1d), // + AccuChekSpirit("Accu-Chek Spirit", ManufacturerType.Roche, "Spirit", 0.1d, null, // + new DoseSettings(0.1d, 15, 12 * 60, 0.1d), // PumpTempBasalType.Percent, - new DoseSettings(10, 15, 12*60,0d, 500d), PumpCapability.BasalRate_Duration15and30minAllowed, // + new DoseSettings(10, 15, 12 * 60, 0d, 500d), PumpCapability.BasalRate_Duration15and30minAllowed, // 0.01d, 0.1d, null, PumpCapability.VirtualPumpCapabilities), // - AccuChekInsight("Accu-Chek Insight", 0.05d, DoseStepSize.InsightBolus, // - new DoseSettings(0.05d, 15, 24*60, 0.05d), // + AccuChekInsight("Accu-Chek Insight", ManufacturerType.Roche, "Insight", 0.05d, DoseStepSize.InsightBolus, // + new DoseSettings(0.05d, 15, 24 * 60, 0.05d), // PumpTempBasalType.Percent, - new DoseSettings(10, 15, 12*60,0d, 250d), PumpCapability.BasalRate_Duration15and30minAllowed, // + new DoseSettings(10, 15, 24 * 60, 0d, 250d), PumpCapability.BasalRate_Duration15and30minAllowed, // 0.02d, 0.01d, null, PumpCapability.InsightCapabilities), // + AccuChekInsightBluetooth("Accu-Chek Insight", ManufacturerType.Roche, "Insight", 0.01d, null, // + new DoseSettings(0.01d, 15, 24 * 60, 0.05d), // + PumpTempBasalType.Percent, + new DoseSettings(10, 15, 24 * 60, 0d, 250d), PumpCapability.BasalRate_Duration15and30minAllowed, // + 0.02d, 0.01d, DoseStepSize.InsightBolus, PumpCapability.InsightCapabilities), // + // Animas - AnimasVibe("Animas Vibe", 0.05d, null, // AnimasBolus? - new DoseSettings(0.05d, 30, 12*60, 0.05d), // + AnimasVibe("Animas Vibe", ManufacturerType.Animas, "Vibe", 0.05d, null, // AnimasBolus? + new DoseSettings(0.05d, 30, 12 * 60, 0.05d), // PumpTempBasalType.Percent, // - new DoseSettings(10, 30, 24*60, 0d, 300d), PumpCapability.BasalRate_Duration30minAllowed, // + new DoseSettings(10, 30, 24 * 60, 0d, 300d), PumpCapability.BasalRate_Duration30minAllowed, // 0.025d, 5d, 0d, null, PumpCapability.VirtualPumpCapabilities), // - AnimasPing("Animas Ping", AnimasVibe), + AnimasPing("Animas Ping", "Ping", AnimasVibe), // Dana - DanaR("DanaR", 0.05d, null, // - new DoseSettings(0.05d, 30, 8*60, 0.05d), // + DanaR("DanaR", ManufacturerType.Sooil, "DanaR", 0.05d, null, // + new DoseSettings(0.05d, 30, 8 * 60, 0.05d), // PumpTempBasalType.Percent, // - new DoseSettings(10d, 60, 24*60, 0d, 200d), PumpCapability.BasalRate_Duration15and30minNotAllowed, // + new DoseSettings(10d, 60, 24 * 60, 0d, 200d), PumpCapability.BasalRate_Duration15and30minNotAllowed, // 0.04d, 0.01d, null, PumpCapability.DanaCapabilities), - DanaRKorean("DanaR Korean", 0.05d, null, // - new DoseSettings(0.05d, 30, 8*60, 0.05d), // + DanaRKorean("DanaR Korean", ManufacturerType.Sooil, "DanaRKorean", 0.05d, null, // + new DoseSettings(0.05d, 30, 8 * 60, 0.05d), // PumpTempBasalType.Percent, // - new DoseSettings(10d, 60, 24*60, 0d, 200d), PumpCapability.BasalRate_Duration15and30minNotAllowed, // + new DoseSettings(10d, 60, 24 * 60, 0d, 200d), PumpCapability.BasalRate_Duration15and30minNotAllowed, // 0.1d, 0.01d, null, PumpCapability.DanaCapabilities), - DanaRS("DanaRS", 0.05d, null, // - new DoseSettings(0.05d, 30, 8*60, 0.05d), // + DanaRS("DanaRS", ManufacturerType.Sooil, "DanaRS", 0.05d, null, // + new DoseSettings(0.05d, 30, 8 * 60, 0.05d), // PumpTempBasalType.Percent, // - new DoseSettings(10d, 60, 24*60, 0d, 200d), PumpCapability.BasalRate_Duration15and30minAllowed, // + new DoseSettings(10d, 60, 24 * 60, 0d, 200d), PumpCapability.BasalRate_Duration15and30minAllowed, // 0.04d, 0.01d, null, PumpCapability.DanaWithHistoryCapabilities), - DanaRv2("DanaRv2", DanaRS), + DanaRv2("DanaRv2", "DanaRv2", DanaRS), // Insulet - Insulet_Omnipod("Insulet Omnipod", 0.05d, null, // - new DoseSettings(0.05d, 30, 8*60, 0.05d), // + Insulet_Omnipod("Insulet Omnipod", ManufacturerType.Insulet, "Omnipod", 0.05d, null, // + new DoseSettings(0.05d, 30, 8 * 60, 0.05d), // PumpTempBasalType.Absolute, // - new DoseSettings(0.05d, 30, 12*60, 0d, 30.0d), PumpCapability.BasalRate_Duration30minAllowed, // cannot exceed max basal rate 30u/hr + new DoseSettings(0.05d, 30, 12 * 60, 0d, 30.0d), PumpCapability.BasalRate_Duration30minAllowed, // cannot exceed max basal rate 30u/hr 0.05d, 0.05d, null, PumpCapability.VirtualPumpCapabilities), // Medtronic - Medtronic_512_712("Medtronic 512/712", 0.05d, null, // - new DoseSettings(0.05d, 30, 8*60, 0.05d), // + Medtronic_512_712("Medtronic 512/712", ManufacturerType.Medtronic, "512/712", 0.1d, null, // + new DoseSettings(0.05d, 30, 8 * 60, 0.05d), // PumpTempBasalType.Absolute, // - new DoseSettings(0.05d, 30, 24*60, 0d, 35d), PumpCapability.BasalRate_Duration30minAllowed, // - 0.05d, 0.05d, null, PumpCapability.VirtualPumpCapabilities), // TODO + new DoseSettings(0.05d, 30, 24 * 60, 0d, 35d), PumpCapability.BasalRate_Duration30minAllowed, // + 0.05d, 0.05d, null, PumpCapability.MedtronicCapabilities), // - Medtronic_515_715("Medtronic 515/715", Medtronic_512_712), - Medtronic_522_722("Medtronic 522/722", Medtronic_512_712), + Medtronic_515_715("Medtronic 515/715", "515/715", Medtronic_512_712), + Medtronic_522_722("Medtronic 522/722", "522/722", Medtronic_512_712), - Medtronic_523_723_Revel("Medtronic 523/723 (Revel)", 0.05d, null, // - new DoseSettings(0.05d, 30, 8*60, 0.05d), // + Medtronic_523_723_Revel("Medtronic 523/723 (Revel)", ManufacturerType.Medtronic, "523/723 (Revel)", 0.05d, null, // + new DoseSettings(0.05d, 30, 8 * 60, 0.05d), // PumpTempBasalType.Absolute, // - new DoseSettings(0.05d, 30, 24*60, 0d, 35d), PumpCapability.BasalRate_Duration30minAllowed, // - 0.025d, 0.025d, DoseStepSize.MedtronicVeoBasal, PumpCapability.VirtualPumpCapabilities), // + new DoseSettings(0.05d, 30, 24 * 60, 0d, 35d), PumpCapability.BasalRate_Duration30minAllowed, // + 0.025d, 0.025d, DoseStepSize.MedtronicVeoBasal, PumpCapability.MedtronicCapabilities), // - Medtronic_554_754_Veo("Medtronic 554/754 (Veo)", Medtronic_523_723_Revel), // TODO + Medtronic_554_754_Veo("Medtronic 554/754 (Veo)", "554/754 (Veo)", Medtronic_523_723_Revel), // TODO - Medtronic_640G("Medtronic 640G", 0.025d, null, // - new DoseSettings(0.05d, 30, 8*60, 0.05d), // + Medtronic_640G("Medtronic 640G", ManufacturerType.Medtronic, "640G", 0.025d, null, // + new DoseSettings(0.05d, 30, 8 * 60, 0.05d), // PumpTempBasalType.Absolute, // - new DoseSettings(0.05d, 30, 24*60, 0d, 35d), PumpCapability.BasalRate_Duration30minAllowed, // + new DoseSettings(0.05d, 30, 24 * 60, 0d, 35d), PumpCapability.BasalRate_Duration30minAllowed, // 0.025d, 0.025d, DoseStepSize.MedtronicVeoBasal, PumpCapability.VirtualPumpCapabilities), // // Tandem - TandemTSlim("Tandem t:slim", 0.01d, null, // - new DoseSettings(0.01d,15, 8*60, 0.4d), + TandemTSlim("Tandem t:slim", ManufacturerType.Tandem, "t:slim", 0.01d, null, // + new DoseSettings(0.01d, 15, 8 * 60, 0.4d), PumpTempBasalType.Percent, - new DoseSettings(1,15, 8*60, 0d, 250d), PumpCapability.BasalRate_Duration15and30minAllowed, // + new DoseSettings(1, 15, 8 * 60, 0d, 250d), PumpCapability.BasalRate_Duration15and30minAllowed, // 0.1d, 0.001d, null, PumpCapability.VirtualPumpCapabilities), - TandemTFlex("Tandem t:flex", TandemTSlim), // - TandemTSlimG4("Tandem t:slim G4", TandemTSlim), // - TandemTSlimX2("Tandem t:slim X2", TandemTSlim), // - ; + TandemTFlex("Tandem t:flex", "t:flex", TandemTSlim), // + TandemTSlimG4("Tandem t:slim G4", "t:slim G4", TandemTSlim), // + TandemTSlimX2("Tandem t:slim X2", "t:slim X2", TandemTSlim), // + + // MDI + MDI("MDI", ManufacturerType.AndroidAPS, "MDI"); + private String description; + private ManufacturerType manufacturer; + private String model; private double bolusSize; private DoseStepSize specialBolusSize; private DoseSettings extendedBolusSettings; @@ -140,10 +152,9 @@ public enum PumpType { private PumpCapability pumpCapability; private PumpType parent; - private static Map mapByDescription; + private static Map mapByDescription; - static - { + static { mapByDescription = new HashMap<>(); for (PumpType pumpType : values()) { @@ -152,33 +163,41 @@ public enum PumpType { } - PumpType(String description, PumpType parent) - { + PumpType(String description, String model, PumpType parent) { this.description = description; this.parent = parent; + this.model = model; } - PumpType(String description, PumpType parent, PumpCapability pumpCapability) - { + + PumpType(String description, ManufacturerType manufacturer, String model) { + this.description = description; + this.manufacturer = manufacturer; + this.model = model; + } + + + PumpType(String description, String model, PumpType parent, PumpCapability pumpCapability) { this.description = description; this.parent = parent; this.pumpCapability = pumpCapability; + parent.model = model; } - PumpType(String description, double bolusSize, DoseStepSize specialBolusSize, // - DoseSettings extendedBolusSettings, // - PumpTempBasalType pumpTempBasalType, DoseSettings tbrSettings, PumpCapability specialBasalDurations, // - double baseBasalMinValue, double baseBasalStep, DoseStepSize baseBasalSpecialSteps, PumpCapability pumpCapability) - { - this(description, bolusSize, specialBolusSize, extendedBolusSettings, pumpTempBasalType, tbrSettings, specialBasalDurations, baseBasalMinValue, null, baseBasalStep, baseBasalSpecialSteps, pumpCapability); - } - - PumpType(String description, double bolusSize, DoseStepSize specialBolusSize, // + PumpType(String description, ManufacturerType manufacturer, String model, double bolusSize, DoseStepSize specialBolusSize, // DoseSettings extendedBolusSettings, // PumpTempBasalType pumpTempBasalType, DoseSettings tbrSettings, PumpCapability specialBasalDurations, // - double baseBasalMinValue, Double baseBasalMaxValue, double baseBasalStep, DoseStepSize baseBasalSpecialSteps, PumpCapability pumpCapability) - { + double baseBasalMinValue, double baseBasalStep, DoseStepSize baseBasalSpecialSteps, PumpCapability pumpCapability) { + this(description, manufacturer, model, bolusSize, specialBolusSize, extendedBolusSettings, pumpTempBasalType, tbrSettings, specialBasalDurations, baseBasalMinValue, null, baseBasalStep, baseBasalSpecialSteps, pumpCapability); + } + + PumpType(String description, ManufacturerType manufacturer, String model, double bolusSize, DoseStepSize specialBolusSize, // + DoseSettings extendedBolusSettings, // + PumpTempBasalType pumpTempBasalType, DoseSettings tbrSettings, PumpCapability specialBasalDurations, // + double baseBasalMinValue, Double baseBasalMaxValue, double baseBasalStep, DoseStepSize baseBasalSpecialSteps, PumpCapability pumpCapability) { this.description = description; + this.manufacturer = manufacturer; + this.model = model; this.bolusSize = bolusSize; this.specialBolusSize = specialBolusSize; this.extendedBolusSettings = extendedBolusSettings; @@ -197,6 +216,14 @@ public enum PumpType { return description; } + public ManufacturerType getManufacturer() { + return isParentSet() ? parent.manufacturer : manufacturer; + } + + public String getModel() { + return isParentSet() ? parent.model : model; + } + public PumpCapability getPumpCapability() { if (isParentSet()) @@ -255,20 +282,15 @@ public enum PumpType { } - private boolean isParentSet() - { - return this.parent!=null; + private boolean isParentSet() { + return this.parent != null; } - public static PumpType getByDescription(String desc) - { - if (mapByDescription.containsKey(desc)) - { + public static PumpType getByDescription(String desc) { + if (mapByDescription.containsKey(desc)) { return mapByDescription.get(desc); - } - else - { + } else { return PumpType.GenericAAPS; } } @@ -276,7 +298,7 @@ public enum PumpType { public String getFullDescription(String i18nTemplate, boolean hasExtendedBasals) { - String unit = getPumpTempBasalType()==PumpTempBasalType.Percent ? "%" : ""; + String unit = getPumpTempBasalType() == PumpTempBasalType.Percent ? "%" : ""; DoseSettings eb = getExtendedBolusSettings(); DoseSettings tbr = getTbrSettings(); @@ -285,24 +307,22 @@ public enum PumpType { return String.format(i18nTemplate, // getStep("" + getBolusSize(), getSpecialBolusSize()), // - eb.getStep(), eb.getDurationStep(), eb.getMaxDuration()/60, // + eb.getStep(), eb.getDurationStep(), eb.getMaxDuration() / 60, // getStep(getBaseBasalRange(), getBaseBasalSpecialSteps()), // tbr.getMinDose() + unit + "-" + tbr.getMaxDose() + unit, tbr.getStep() + unit, - tbr.getDurationStep(), tbr.getMaxDuration()/60, extendedNote); + tbr.getDurationStep(), tbr.getMaxDuration() / 60, extendedNote); } - private String getBaseBasalRange() - { + private String getBaseBasalRange() { Double maxValue = getBaseBasalMaxValue(); - return maxValue==null ? "" + getBaseBasalMinValue() : getBaseBasalMinValue() + "-" + maxValue; + return maxValue == null ? "" + getBaseBasalMinValue() : getBaseBasalMinValue() + "-" + maxValue; } - private String getStep(String step, DoseStepSize stepSize) - { - if (stepSize!=null) + private String getStep(String step, DoseStepSize stepSize) { + if (stepSize != null) return step + " [" + stepSize.getDescription() + "] *"; else return "" + step; @@ -310,18 +330,15 @@ public enum PumpType { public boolean hasExtendedBasals() { - return ((getBaseBasalSpecialSteps() !=null) || (getSpecialBolusSize() != null)); + return ((getBaseBasalSpecialSteps() != null) || (getSpecialBolusSize() != null)); } public PumpCapability getSpecialBasalDurations() { - if (isParentSet()) - { + if (isParentSet()) { return parent.getSpecialBasalDurations(); - } - else - { + } else { return specialBasalDurations == null ? // PumpCapability.BasalRate_Duration15and30minNotAllowed : specialBasalDurations; } @@ -332,20 +349,24 @@ public enum PumpType { return bolusAmount; } - double bolusStepSize; + double bolusStepSize = getBolusSize(); - if (getSpecialBolusSize() == null) { - bolusStepSize = getBolusSize(); - } else { + if (getSpecialBolusSize() != null) { DoseStepSize specialBolusSize = getSpecialBolusSize(); - - bolusStepSize = specialBolusSize.getStepSizeForAmount((double)bolusAmount); + bolusStepSize = specialBolusSize.getStepSizeForAmount(bolusAmount); } - return Math.round(bolusAmount / bolusStepSize) * bolusStepSize; + return Round.roundTo(bolusAmount, bolusStepSize); } + public double determineCorrectBolusStepSize(double bolusAmount) { + DoseStepSize specialBolusSize = getSpecialBolusSize(); + if (specialBolusSize != null) + return specialBolusSize.getStepSizeForAmount(bolusAmount); + return getBolusSize(); + } + public double determineCorrectExtendedBolusSize(double bolusAmount) { if (bolusAmount == 0.0d) { return bolusAmount; @@ -365,7 +386,7 @@ public enum PumpType { bolusAmount = extendedBolusSettings.getMaxDose(); } - return Math.round(bolusAmount / bolusStepSize) * bolusStepSize; + return Round.roundTo(bolusAmount, bolusStepSize); } @@ -387,7 +408,7 @@ public enum PumpType { if (basalAmount > getTbrSettings().getMaxDose()) basalAmount = getTbrSettings().getMaxDose().doubleValue(); - return Math.round(basalAmount / basalStepSize) * basalStepSize; + return Round.roundTo(basalAmount, basalStepSize); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/dialog/RefreshableInterface.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/dialog/RefreshableInterface.java new file mode 100644 index 0000000000..df84750152 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/dialog/RefreshableInterface.java @@ -0,0 +1,11 @@ +package info.nightscout.androidaps.plugins.pump.common.dialog; + +/** + * Created by andy on 5/19/18. + */ + +public interface RefreshableInterface { + + void refreshData(); + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/dialog/RileyLinkBLEScanActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/dialog/RileyLinkBLEScanActivity.java new file mode 100644 index 0000000000..ae0a0d34f7 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/dialog/RileyLinkBLEScanActivity.java @@ -0,0 +1,419 @@ +package info.nightscout.androidaps.plugins.pump.common.dialog; + +import android.Manifest; +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothDevice; +import android.bluetooth.le.BluetoothLeScanner; +import android.bluetooth.le.ScanCallback; +import android.bluetooth.le.ScanFilter; +import android.bluetooth.le.ScanResult; +import android.bluetooth.le.ScanSettings; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.os.Bundle; +import android.os.Handler; +import android.os.ParcelUuid; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.ListView; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.widget.Toolbar; +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.activities.NoSplashAppCompatActivity; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkConst; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.GattAttributes; +import info.nightscout.androidaps.plugins.pump.common.utils.LocationHelper; +import info.nightscout.androidaps.plugins.pump.medtronic.driver.MedtronicPumpStatus; +import info.nightscout.androidaps.plugins.pump.medtronic.events.EventMedtronicPumpConfigurationChanged; +import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil; +import info.nightscout.androidaps.utils.SP; + +// IMPORTANT: This activity needs to be called from RileyLinkSelectPreference (see pref_medtronic.xml as example) +public class RileyLinkBLEScanActivity extends NoSplashAppCompatActivity { + + private static final Logger LOG = LoggerFactory.getLogger(RileyLinkBLEScanActivity.class); + + private static final int PERMISSION_REQUEST_COARSE_LOCATION = 30241; // arbitrary. + private static final int REQUEST_ENABLE_BT = 30242; // arbitrary + + private static String TAG = "RileyLinkBLEScanActivity"; + + // Stops scanning after 30 seconds. + private static final long SCAN_PERIOD = 30000; + public boolean mScanning; + public ScanSettings settings; + public List filters; + public ListView listBTScan; + public Toolbar toolbarBTScan; + public Context mContext = this; + private BluetoothAdapter mBluetoothAdapter; + private BluetoothLeScanner mLEScanner; + private LeDeviceListAdapter mLeDeviceListAdapter; + private Handler mHandler; + + private String actionTitleStart, actionTitleStop; + private MenuItem menuItem; + + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.rileylink_scan_activity); + + // Initializes Bluetooth adapter. + mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); + mHandler = new Handler(); + + mLeDeviceListAdapter = new LeDeviceListAdapter(); + listBTScan = (ListView) findViewById(R.id.rileylink_listBTScan); + listBTScan.setAdapter(mLeDeviceListAdapter); + listBTScan.setOnItemClickListener((parent, view, position, id) -> { + + // stop scanning if still active + if (mScanning) { + mScanning = false; + mLEScanner.stopScan(mScanCallback2); + } + + TextView textview = (TextView) view.findViewById(R.id.rileylink_device_address); + String bleAddress = textview.getText().toString(); + + SP.putString(RileyLinkConst.Prefs.RileyLinkAddress, bleAddress); + + RileyLinkUtil.getRileyLinkSelectPreference().setSummary(bleAddress); + + MedtronicPumpStatus pumpStatus = MedtronicUtil.getPumpStatus(); + pumpStatus.verifyConfiguration(); // force reloading of address + + RxBus.INSTANCE.send(new EventMedtronicPumpConfigurationChanged()); + + finish(); + }); + + toolbarBTScan = (Toolbar) findViewById(R.id.rileylink_toolbarBTScan); + toolbarBTScan.setTitle(R.string.rileylink_scanner_title); + setSupportActionBar(toolbarBTScan); + + prepareForScanning(); + } + + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.menu_rileylink_ble_scan, menu); + + actionTitleStart = MainApp.gs(R.string.rileylink_scanner_scan_scan); + actionTitleStop = MainApp.gs(R.string.rileylink_scanner_scan_stop); + + menuItem = menu.getItem(0); + + menuItem.setTitle(actionTitleStart); + + return true; + } + + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.rileylink_miScan: { + scanLeDevice(menuItem.getTitle().equals(actionTitleStart)); + return true; + } + + default: + return super.onOptionsItemSelected(item); + } + } + + + public void prepareForScanning() { + // https://developer.android.com/training/permissions/requesting.html + // http://developer.radiusnetworks.com/2015/09/29/is-your-beacon-app-ready-for-android-6.html + if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) { + Toast.makeText(this, R.string.rileylink_scanner_ble_not_supported, Toast.LENGTH_SHORT).show(); + } else { + // Use this check to determine whether BLE is supported on the device. Then + // you can selectively disable BLE-related features. + if (ContextCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { + // your code that requires permission + ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, + PERMISSION_REQUEST_COARSE_LOCATION); + } + + // Ensures Bluetooth is available on the device and it is enabled. If not, + // displays a dialog requesting user permission to enable Bluetooth. + if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) { + Toast.makeText(this, R.string.rileylink_scanner_ble_not_enabled, Toast.LENGTH_SHORT).show(); + } else { + + // Will request that GPS be enabled for devices running Marshmallow or newer. + if (!LocationHelper.isLocationEnabled(this)) { + LocationHelper.requestLocationForBluetooth(this); + } + + mLEScanner = mBluetoothAdapter.getBluetoothLeScanner(); + settings = new ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build(); + filters = Arrays.asList(new ScanFilter.Builder().setServiceUuid( + ParcelUuid.fromString(GattAttributes.SERVICE_RADIO)).build()); + + } + } + + // disable currently selected RL, so that we can discover it + RileyLinkUtil.sendBroadcastMessage(RileyLinkConst.Intents.RileyLinkDisconnect); + } + + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == REQUEST_ENABLE_BT) { + if (resultCode == RESULT_OK) { + // User allowed Bluetooth to turn on + } else if (resultCode == RESULT_CANCELED) { + // Error, or user said "NO" + finish(); + } + } + } + + private ScanCallback mScanCallback2 = new ScanCallback() { + + @Override + public void onScanResult(int callbackType, final ScanResult scanRecord) { + + Log.d(TAG, scanRecord.toString()); + + runOnUiThread(() -> { + if (addDevice(scanRecord)) + mLeDeviceListAdapter.notifyDataSetChanged(); + }); + } + + + @Override + public void onBatchScanResults(final List results) { + + runOnUiThread(() -> { + + boolean added = false; + + for (ScanResult result : results) { + if (addDevice(result)) + added = true; + } + + if (added) + mLeDeviceListAdapter.notifyDataSetChanged(); + }); + } + + + private boolean addDevice(ScanResult result) { + + BluetoothDevice device = result.getDevice(); + + List serviceUuids = result.getScanRecord().getServiceUuids(); + + if (serviceUuids == null || serviceUuids.size() == 0) { + Log.v(TAG, "Device " + device.getAddress() + " has no serviceUuids (Not RileyLink)."); + } else if (serviceUuids.size() > 1) { + Log.v(TAG, "Device " + device.getAddress() + " has too many serviceUuids (Not RileyLink)."); + } else { + + String uuid = serviceUuids.get(0).getUuid().toString().toLowerCase(); + + if (uuid.equals(GattAttributes.SERVICE_RADIO)) { + Log.i(TAG, "Found RileyLink with address: " + device.getAddress()); + mLeDeviceListAdapter.addDevice(result); + return true; + } else { + Log.v(TAG, "Device " + device.getAddress() + " has incorrect uuid (Not RileyLink)."); + } + } + + return false; + } + + + private String getDeviceDebug(BluetoothDevice device) { + return "BluetoothDevice [name=" + device.getName() + ", address=" + device.getAddress() + // + ", type=" + device.getType(); // + ", alias=" + device.getAlias(); + } + + + @Override + public void onScanFailed(int errorCode) { + Log.e("Scan Failed", "Error Code: " + errorCode); + Toast.makeText(mContext, MainApp.gs(R.string.rileylink_scanner_scanning_error, errorCode), + Toast.LENGTH_LONG).show(); + } + + }; + + + private void scanLeDevice(final boolean enable) { + + if (mLEScanner == null) + return; + + if (enable) { + + mLeDeviceListAdapter.clear(); + mLeDeviceListAdapter.notifyDataSetChanged(); + + // Stops scanning after a pre-defined scan period. + mHandler.postDelayed(() -> { + + if (mScanning) { + mScanning = false; + mLEScanner.stopScan(mScanCallback2); + LOG.debug("scanLeDevice: Scanning Stop"); + Toast.makeText(mContext, R.string.rileylink_scanner_scanning_finished, Toast.LENGTH_SHORT).show(); + menuItem.setTitle(actionTitleStart); + } + }, SCAN_PERIOD); + + mScanning = true; + mLEScanner.startScan(filters, settings, mScanCallback2); + LOG.debug("scanLeDevice: Scanning Start"); + Toast.makeText(this, R.string.rileylink_scanner_scanning, Toast.LENGTH_SHORT).show(); + + menuItem.setTitle(actionTitleStop); + + } else { + if (mScanning) { + mScanning = false; + mLEScanner.stopScan(mScanCallback2); + + LOG.debug("scanLeDevice: Scanning Stop"); + Toast.makeText(this, R.string.rileylink_scanner_scanning_finished, Toast.LENGTH_SHORT).show(); + + menuItem.setTitle(actionTitleStart); + } + } + } + + private class LeDeviceListAdapter extends BaseAdapter { + + private ArrayList mLeDevices; + private Map rileyLinkDevices; + private LayoutInflater mInflator; + String currentlySelectedAddress; + + + public LeDeviceListAdapter() { + super(); + mLeDevices = new ArrayList<>(); + rileyLinkDevices = new HashMap<>(); + mInflator = RileyLinkBLEScanActivity.this.getLayoutInflater(); + currentlySelectedAddress = SP.getString(RileyLinkConst.Prefs.RileyLinkAddress, ""); + } + + + public void addDevice(ScanResult result) { + + if (!mLeDevices.contains(result.getDevice())) { + mLeDevices.add(result.getDevice()); + } + rileyLinkDevices.put(result.getDevice(), result.getRssi()); + notifyDataSetChanged(); + } + + + public void clear() { + mLeDevices.clear(); + rileyLinkDevices.clear(); + notifyDataSetChanged(); + } + + + @Override + public int getCount() { + return mLeDevices.size(); + } + + + @Override + public Object getItem(int i) { + return mLeDevices.get(i); + } + + + @Override + public long getItemId(int i) { + return i; + } + + + @Override + public View getView(int i, View view, ViewGroup viewGroup) { + + ViewHolder viewHolder; + // General ListView optimization code. + if (view == null) { + view = mInflator.inflate(R.layout.rileylink_scan_item, null); + viewHolder = new ViewHolder(); + viewHolder.deviceAddress = (TextView) view.findViewById(R.id.rileylink_device_address); + viewHolder.deviceName = (TextView) view.findViewById(R.id.rileylink_device_name); + view.setTag(viewHolder); + } else { + viewHolder = (ViewHolder) view.getTag(); + } + + BluetoothDevice device = mLeDevices.get(i); + String deviceName = device.getName(); + + if (StringUtils.isBlank(deviceName)) { + deviceName = "RileyLink"; + } + + deviceName += " [" + rileyLinkDevices.get(device).intValue() + "]"; + + if (currentlySelectedAddress.equals(device.getAddress())) { + // viewHolder.deviceName.setTextColor(getColor(R.color.secondary_text_light)); + // viewHolder.deviceAddress.setTextColor(getColor(R.color.secondary_text_light)); + deviceName += " (" + getResources().getString(R.string.rileylink_scanner_selected_device) + ")"; + } + + viewHolder.deviceName.setText(deviceName); + viewHolder.deviceAddress.setText(device.getAddress()); + + return view; + } + + } + + static class ViewHolder { + + TextView deviceName; + TextView deviceAddress; + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/RileyLinkCommunicationManager.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/RileyLinkCommunicationManager.java new file mode 100644 index 0000000000..69837afd7c --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/RileyLinkCommunicationManager.java @@ -0,0 +1,439 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import android.content.Context; + +import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.pump.common.data.PumpStatus; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.RFSpy; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.RileyLinkCommunicationException; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.FrequencyScanResults; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.FrequencyTrial; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.RFSpyResponse; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.RLMessage; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.RadioPacket; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.RadioResponse; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RLMessageType; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RileyLinkBLEError; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.RileyLinkServiceData; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.ServiceTaskExecutor; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.WakeAndTuneTask; +import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; +import info.nightscout.androidaps.plugins.pump.medtronic.defs.PumpDeviceState; +import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil; +import info.nightscout.androidaps.utils.SP; + +/** + * This is abstract class for RileyLink Communication, this one needs to be extended by specific "Pump" class. + *

+ * Created by andy on 5/10/18. + */ +public abstract class RileyLinkCommunicationManager { + + private static final Logger LOG = LoggerFactory.getLogger(L.PUMPCOMM); + + private static final int SCAN_TIMEOUT = 1500; + private static final int ALLOWED_PUMP_UNREACHABLE = 10 * 60 * 1000; // 10 minutes + + protected final RFSpy rfspy; + protected final Context context; + protected int receiverDeviceAwakeForMinutes = 1; // override this in constructor of specific implementation + protected String receiverDeviceID; // String representation of receiver device (ex. Pump (xxxxxx) or Pod (yyyyyy)) + protected long lastGoodReceiverCommunicationTime = 0; + protected PumpStatus pumpStatus; + protected RileyLinkServiceData rileyLinkServiceData; + private long nextWakeUpRequired = 0L; + + // internal flag + private boolean showPumpMessages = true; + private int timeoutCount = 0; + + + public RileyLinkCommunicationManager(Context context, RFSpy rfspy) { + this.context = context; + this.rfspy = rfspy; + this.rileyLinkServiceData = RileyLinkUtil.getRileyLinkServiceData(); + RileyLinkUtil.setRileyLinkCommunicationManager(this); + + configurePumpSpecificSettings(); + } + + + protected abstract void configurePumpSpecificSettings(); + + + // All pump communications go through this function. + protected E sendAndListen(RLMessage msg, int timeout_ms, Class clazz) + throws RileyLinkCommunicationException { + + if (showPumpMessages) { + if (isLogEnabled()) + LOG.info("Sent:" + ByteUtil.shortHexString(msg.getTxData())); + } + + RFSpyResponse rfSpyResponse = rfspy.transmitThenReceive(new RadioPacket(msg.getTxData()), timeout_ms); + + RadioResponse radioResponse = rfSpyResponse.getRadioResponse(); + + E response = createResponseMessage(rfSpyResponse.getRadioResponse().getPayload(), clazz); + + if (response.isValid()) { + // Mark this as the last time we heard from the pump. + rememberLastGoodDeviceCommunicationTime(); + } else { + LOG.warn("isDeviceReachable. Response is invalid ! [interrupted={}, timeout={}, unknownCommand={}, invalidParam={}]", rfSpyResponse.wasInterrupted(), + rfSpyResponse.wasTimeout(), rfSpyResponse.isUnknownCommand(), rfSpyResponse.isInvalidParam()); + + if (rfSpyResponse.wasTimeout()) { + timeoutCount++; + + long diff = System.currentTimeMillis() - pumpStatus.lastConnection; + + if (diff > ALLOWED_PUMP_UNREACHABLE) { + LOG.warn("We reached max time that Pump can be unreachable. Starting Tuning."); + ServiceTaskExecutor.startTask(new WakeAndTuneTask()); + timeoutCount = 0; + } + + throw new RileyLinkCommunicationException(RileyLinkBLEError.Timeout); + } else if (rfSpyResponse.wasInterrupted()) { + throw new RileyLinkCommunicationException(RileyLinkBLEError.Interrupted); + } + } + + if (showPumpMessages) { + if (isLogEnabled()) + LOG.info("Received:" + ByteUtil.shortHexString(rfSpyResponse.getRadioResponse().getPayload())); + } + + return response; + } + + + public abstract E createResponseMessage(byte[] payload, Class clazz); + + + public void wakeUp(boolean force) { + wakeUp(receiverDeviceAwakeForMinutes, force); + } + + + public int getNotConnectedCount() { + return rfspy != null ? rfspy.notConnectedCount : 0; + } + + + + // FIXME change wakeup + // TODO we might need to fix this. Maybe make pump awake for shorter time (battery factor for pump) - Andy + public void wakeUp(int duration_minutes, boolean force) { + // If it has been longer than n minutes, do wakeup. Otherwise assume pump is still awake. + // **** FIXME: this wakeup doesn't seem to work well... must revisit + // receiverDeviceAwakeForMinutes = duration_minutes; + + MedtronicUtil.setPumpDeviceState(PumpDeviceState.WakingUp); + + if (force) + nextWakeUpRequired = 0L; + + if (System.currentTimeMillis() > nextWakeUpRequired) { + if (isLogEnabled()) + LOG.info("Waking pump..."); + + byte[] pumpMsgContent = createPumpMessageContent(RLMessageType.ReadSimpleData); // simple + RFSpyResponse resp = rfspy.transmitThenReceive(new RadioPacket(pumpMsgContent), (byte)0, (byte)200, + (byte)0, (byte)0, 25000, (byte)0); + if (isLogEnabled()) + LOG.info("wakeup: raw response is " + ByteUtil.shortHexString(resp.getRaw())); + + // FIXME wakeUp successful !!!!!!!!!!!!!!!!!! + + nextWakeUpRequired = System.currentTimeMillis() + (receiverDeviceAwakeForMinutes * 60 * 1000); + } else { + if (isLogEnabled()) + LOG.trace("Last pump communication was recent, not waking pump."); + } + + // long lastGoodPlus = getLastGoodReceiverCommunicationTime() + (receiverDeviceAwakeForMinutes * 60 * 1000); + // + // if (System.currentTimeMillis() > lastGoodPlus || force) { + // LOG.info("Waking pump..."); + // + // byte[] pumpMsgContent = createPumpMessageContent(RLMessageType.PowerOn); + // RFSpyResponse resp = rfspy.transmitThenReceive(new RadioPacket(pumpMsgContent), (byte) 0, (byte) 200, (byte) + // 0, (byte) 0, 15000, (byte) 0); + // LOG.info("wakeup: raw response is " + ByteUtil.shortHexString(resp.getRaw())); + // } else { + // LOG.trace("Last pump communication was recent, not waking pump."); + // } + } + + + public void setRadioFrequencyForPump(double freqMHz) { + rfspy.setBaseFrequency(freqMHz); + } + + + public double tuneForDevice() { + return scanForDevice(RileyLinkUtil.getRileyLinkTargetFrequency().getScanFrequencies()); + } + + + /** + * If user changes pump and one pump is running in US freq, and other in WW, then previously set frequency would be + * invalid, + * so we would need to retune. This checks that saved frequency is correct range. + * + * @param frequency + * @return + */ + public boolean isValidFrequency(double frequency) { + + double[] scanFrequencies = RileyLinkUtil.getRileyLinkTargetFrequency().getScanFrequencies(); + + if (scanFrequencies.length == 1) { + return RileyLinkUtil.isSame(scanFrequencies[0], frequency); + } else { + return (scanFrequencies[0] <= frequency && scanFrequencies[scanFrequencies.length - 1] >= frequency); + } + } + + + /** + * Do device connection, with wakeup + * + * @return + */ + public abstract boolean tryToConnectToDevice(); + + + public double scanForDevice(double[] frequencies) { + if (isLogEnabled()) + LOG.info("Scanning for receiver ({})", receiverDeviceID); + wakeUp(receiverDeviceAwakeForMinutes, false); + FrequencyScanResults results = new FrequencyScanResults(); + + for (int i = 0; i < frequencies.length; i++) { + int tries = 3; + FrequencyTrial trial = new FrequencyTrial(); + trial.frequencyMHz = frequencies[i]; + rfspy.setBaseFrequency(frequencies[i]); + + int sumRSSI = 0; + for (int j = 0; j < tries; j++) { + + byte[] pumpMsgContent = createPumpMessageContent(RLMessageType.ReadSimpleData); + RFSpyResponse resp = rfspy.transmitThenReceive(new RadioPacket(pumpMsgContent), (byte)0, (byte)0, + (byte)0, (byte)0, 1250, (byte)0); + if (resp.wasTimeout()) { + LOG.error("scanForPump: Failed to find pump at frequency {}", frequencies[i]); + } else if (resp.looksLikeRadioPacket()) { + RadioResponse radioResponse = new RadioResponse(); + + try { + + radioResponse.init(resp.getRaw()); + + if (radioResponse.isValid()) { + int rssi = calculateRssi(radioResponse.rssi); + sumRSSI += rssi; + trial.rssiList.add(rssi); + trial.successes++; + } else { + LOG.warn("Failed to parse radio response: " + ByteUtil.shortHexString(resp.getRaw())); + trial.rssiList.add(-99); + } + + } catch (RileyLinkCommunicationException rle) { + LOG.warn("Failed to decode radio response: " + ByteUtil.shortHexString(resp.getRaw())); + trial.rssiList.add(-99); + } + + } else { + LOG.error("scanForPump: raw response is " + ByteUtil.shortHexString(resp.getRaw())); + trial.rssiList.add(-99); + } + trial.tries++; + } + sumRSSI += -99.0 * (trial.tries - trial.successes); + trial.averageRSSI2 = (double)(sumRSSI) / (double)(trial.tries); + + trial.calculateAverage(); + + results.trials.add(trial); + } + + results.dateTime = System.currentTimeMillis(); + + StringBuilder stringBuilder = new StringBuilder("Scan results:\n"); + + for (int k = 0; k < results.trials.size(); k++) { + FrequencyTrial one = results.trials.get(k); + + stringBuilder.append(String.format("Scan Result[%s]: Freq=%s, avg RSSI = %s\n", "" + k, "" + + one.frequencyMHz, "" + one.averageRSSI + ", RSSIs =" + one.rssiList)); + } + + LOG.info(stringBuilder.toString()); + + results.sort(); // sorts in ascending order + + FrequencyTrial bestTrial = results.trials.get(results.trials.size() - 1); + results.bestFrequencyMHz = bestTrial.frequencyMHz; + if (bestTrial.successes > 0) { + rfspy.setBaseFrequency(results.bestFrequencyMHz); + if (isLogEnabled()) + LOG.debug("Best frequency found: " + results.bestFrequencyMHz); + return results.bestFrequencyMHz; + } else { + LOG.error("No pump response during scan."); + return 0.0; + } + } + + + private int calculateRssi(int rssiIn) { + int rssiOffset = 73; + int outRssi = 0; + if (rssiIn >= 128) { + outRssi = ((rssiIn - 256) / 2) - rssiOffset; + } else { + outRssi = (rssiIn / 2) - rssiOffset; + } + + return outRssi; + } + + + public abstract byte[] createPumpMessageContent(RLMessageType type); + + + private int tune_tryFrequency(double freqMHz) { + rfspy.setBaseFrequency(freqMHz); + // RLMessage msg = makeRLMessage(RLMessageType.ReadSimpleData); + byte[] pumpMsgContent = createPumpMessageContent(RLMessageType.ReadSimpleData); + RadioPacket pkt = new RadioPacket(pumpMsgContent); + RFSpyResponse resp = rfspy.transmitThenReceive(pkt, (byte)0, (byte)0, (byte)0, (byte)0, SCAN_TIMEOUT, (byte)0); + if (resp.wasTimeout()) { + LOG.warn("tune_tryFrequency: no pump response at frequency {}", freqMHz); + } else if (resp.looksLikeRadioPacket()) { + RadioResponse radioResponse = new RadioResponse(); + try { + radioResponse.init(resp.getRaw()); + + if (radioResponse.isValid()) { + LOG.warn("tune_tryFrequency: saw response level {} at frequency {}", radioResponse.rssi, freqMHz); + return calculateRssi(radioResponse.rssi); + } else { + LOG.warn("tune_tryFrequency: invalid radio response:" + + ByteUtil.shortHexString(radioResponse.getPayload())); + } + + } catch (RileyLinkCommunicationException e) { + LOG.warn("Failed to decode radio response: " + ByteUtil.shortHexString(resp.getRaw())); + } + } + + return 0; + } + + + public double quickTuneForPump(double startFrequencyMHz) { + double betterFrequency = startFrequencyMHz; + double stepsize = 0.05; + for (int tries = 0; tries < 4; tries++) { + double evenBetterFrequency = quickTunePumpStep(betterFrequency, stepsize); + if (evenBetterFrequency == 0.0) { + // could not see the pump at all. + // Try again at larger step size + stepsize += 0.05; + } else { + if ((int)(evenBetterFrequency * 100) == (int)(betterFrequency * 100)) { + // value did not change, so we're done. + break; + } + betterFrequency = evenBetterFrequency; // and go again. + } + } + if (betterFrequency == 0.0) { + // we've failed... caller should try a full scan for pump + if (isLogEnabled()) + LOG.error("quickTuneForPump: failed to find pump"); + } else { + rfspy.setBaseFrequency(betterFrequency); + if (betterFrequency != startFrequencyMHz) { + if (isLogEnabled()) + LOG.info("quickTuneForPump: new frequency is {}MHz", betterFrequency); + } else { + if (isLogEnabled()) + LOG.info("quickTuneForPump: pump frequency is the same: {}MHz", startFrequencyMHz); + } + } + return betterFrequency; + } + + + private double quickTunePumpStep(double startFrequencyMHz, double stepSizeMHz) { + if (isLogEnabled()) + LOG.info("Doing quick radio tune for receiver ({})", receiverDeviceID); + wakeUp(false); + int startRssi = tune_tryFrequency(startFrequencyMHz); + double lowerFrequency = startFrequencyMHz - stepSizeMHz; + int lowerRssi = tune_tryFrequency(lowerFrequency); + double higherFrequency = startFrequencyMHz + stepSizeMHz; + int higherRssi = tune_tryFrequency(higherFrequency); + + if ((higherRssi == 0.0) && (lowerRssi == 0.0) && (startRssi == 0.0)) { + // we can't see the pump at all... + return 0.0; + } + if (higherRssi > startRssi) { + // need to move higher + return higherFrequency; + } else if (lowerRssi > startRssi) { + // need to move lower. + return lowerFrequency; + } + return startFrequencyMHz; + } + + + protected void rememberLastGoodDeviceCommunicationTime() { + lastGoodReceiverCommunicationTime = System.currentTimeMillis(); + + SP.putLong(RileyLinkConst.Prefs.LastGoodDeviceCommunicationTime, lastGoodReceiverCommunicationTime); + pumpStatus.setLastCommunicationToNow(); + } + + + private long getLastGoodReceiverCommunicationTime() { + // If we have a value of zero, we need to load from prefs. + if (lastGoodReceiverCommunicationTime == 0L) { + lastGoodReceiverCommunicationTime = SP.getLong(RileyLinkConst.Prefs.LastGoodDeviceCommunicationTime, 0L); + // Might still be zero, but that's fine. + } + double minutesAgo = (System.currentTimeMillis() - lastGoodReceiverCommunicationTime) / (1000.0 * 60.0); + if (isLogEnabled()) + LOG.trace("Last good pump communication was " + minutesAgo + " minutes ago."); + return lastGoodReceiverCommunicationTime; + } + + + public PumpStatus getPumpStatus() { + return pumpStatus; + } + + + public void clearNotConnectedCount() { + if (rfspy != null) { + rfspy.notConnectedCount = 0; + } + } + + private boolean isLogEnabled() { + return L.isEnabled(L.PUMPCOMM); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/RileyLinkConst.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/RileyLinkConst.java new file mode 100644 index 0000000000..bff2a39240 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/RileyLinkConst.java @@ -0,0 +1,50 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink; + +import info.nightscout.androidaps.R; + +/** + * Created by andy on 16/05/2018. + */ + +public class RileyLinkConst { + + static final String Prefix = "AAPS.RileyLink."; + + public class Intents { + + public static final String RileyLinkReady = Prefix + "RileyLink_Ready"; + public static final String RileyLinkGattFailed = Prefix + "RileyLink_Gatt_Failed"; + + public static final String BluetoothConnected = Prefix + "Bluetooth_Connected"; + public static final String BluetoothReconnected = Prefix + "Bluetooth_Reconnected"; + public static final String BluetoothDisconnected = Prefix + "Bluetooth_Disconnected"; + public static final String RileyLinkDisconnected = Prefix + "RileyLink_Disconnected"; + + public static final String RileyLinkNewAddressSet = Prefix + "NewAddressSet"; + + public static final String INTENT_NEW_rileylinkAddressKey = Prefix + "INTENT_NEW_rileylinkAddressKey"; + public static final String INTENT_NEW_pumpIDKey = Prefix + "INTENT_NEW_pumpIDKey"; + public static final String RileyLinkDisconnect = Prefix + "RileyLink_Disconnect"; + } + + public class Prefs { + + //public static final String PrefPrefix = "pref_rileylink_"; + //public static final String RileyLinkAddress = PrefPrefix + "mac_address"; // pref_rileylink_mac_address + public static final int RileyLinkAddress = R.string.key_rileylink_mac_address; + public static final String LastGoodDeviceCommunicationTime = Prefix + "lastGoodDeviceCommunicationTime"; + public static final String LastGoodDeviceFrequency = Prefix + "LastGoodDeviceFrequency"; + } + + public class IPC { + + // needs to br renamed (and maybe removed) + public static final String MSG_PUMP_quickTune = Prefix + "MSG_PUMP_quickTune"; + public static final String MSG_PUMP_tunePump = Prefix + "MSG_PUMP_tunePump"; + public static final String MSG_PUMP_fetchHistory = Prefix + "MSG_PUMP_fetchHistory"; + public static final String MSG_PUMP_fetchSavedHistory = Prefix + "MSG_PUMP_fetchSavedHistory"; + + public static final String MSG_ServiceCommand = Prefix + "MSG_ServiceCommand"; + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/RileyLinkUtil.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/RileyLinkUtil.java new file mode 100644 index 0000000000..3c7ba730a7 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/RileyLinkUtil.java @@ -0,0 +1,328 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink; + +import android.content.Context; +import android.content.Intent; + +import androidx.localbroadcastmanager.content.LocalBroadcastManager; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.RileyLinkBLE; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.encoding.Encoding4b6b; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.encoding.Encoding4b6bGeoff; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RileyLinkEncodingType; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RileyLinkFirmwareVersion; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RileyLinkTargetFrequency; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.data.BleAdvertisedData; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.data.RLHistoryItem; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkError; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkServiceState; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkTargetDevice; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.RileyLinkService; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.RileyLinkServiceData; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.data.ServiceNotification; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.data.ServiceResult; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.data.ServiceTransport; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.ServiceTask; +import info.nightscout.androidaps.plugins.pump.common.ui.RileyLinkSelectPreference; +import info.nightscout.androidaps.plugins.pump.medtronic.events.EventMedtronicDeviceStatusChange; + +/** + * Created by andy on 17/05/2018. + */ + +public class RileyLinkUtil { + + private static final Logger LOG = LoggerFactory.getLogger(L.PUMP); + protected static List historyRileyLink = new ArrayList<>(); + protected static RileyLinkCommunicationManager rileyLinkCommunicationManager; + static ServiceTask currentTask; + private static Context context; + private static RileyLinkBLE rileyLinkBLE; + private static RileyLinkServiceData rileyLinkServiceData; + private static RileyLinkService rileyLinkService; + private static RileyLinkTargetFrequency rileyLinkTargetFrequency; + + private static RileyLinkTargetDevice targetDevice; + private static RileyLinkEncodingType encoding; + private static RileyLinkSelectPreference rileyLinkSelectPreference; + private static Encoding4b6b encoding4b6b; + private static RileyLinkFirmwareVersion firmwareVersion; + + + public static void setContext(Context contextIn) { + RileyLinkUtil.context = contextIn; + } + + + public static RileyLinkEncodingType getEncoding() { + return encoding; + } + + + public static void setEncoding(RileyLinkEncodingType encoding) { + RileyLinkUtil.encoding = encoding; + + if (encoding == RileyLinkEncodingType.FourByteSixByteLocal) { + RileyLinkUtil.encoding4b6b = new Encoding4b6bGeoff(); + } + } + + + public static void sendBroadcastMessage(String message) { + if (context != null) { + Intent intent = new Intent(message); + LocalBroadcastManager.getInstance(RileyLinkUtil.context).sendBroadcast(intent); + } + } + + + public static void setServiceState(RileyLinkServiceState newState) { + setServiceState(newState, null); + } + + + public static RileyLinkError getError() { + if (RileyLinkUtil.rileyLinkServiceData != null) + return RileyLinkUtil.rileyLinkServiceData.errorCode; + else + return null; + } + + + public static RileyLinkServiceState getServiceState() { + return workWithServiceState(null, null, false); + } + + + public static void setServiceState(RileyLinkServiceState newState, RileyLinkError errorCode) { + workWithServiceState(newState, errorCode, true); + } + + + private static synchronized RileyLinkServiceState workWithServiceState(RileyLinkServiceState newState, + RileyLinkError errorCode, boolean set) { + + if (set) { + + RileyLinkUtil.rileyLinkServiceData.serviceState = newState; + RileyLinkUtil.rileyLinkServiceData.errorCode = errorCode; + + if (L.isEnabled(L.PUMP)) + LOG.info("RileyLink State Changed: {} {}", newState, errorCode == null ? "" : " - Error State: " + + errorCode.name()); + + RileyLinkUtil.historyRileyLink.add(new RLHistoryItem(RileyLinkUtil.rileyLinkServiceData.serviceState, + RileyLinkUtil.rileyLinkServiceData.errorCode, targetDevice)); + RxBus.INSTANCE.send(new EventMedtronicDeviceStatusChange(newState, errorCode)); + return null; + + } else { + return (RileyLinkUtil.rileyLinkServiceData == null || RileyLinkUtil.rileyLinkServiceData.serviceState == null) ? // + RileyLinkServiceState.NotStarted + : RileyLinkUtil.rileyLinkServiceData.serviceState; + } + + } + + + public static RileyLinkBLE getRileyLinkBLE() { + return RileyLinkUtil.rileyLinkBLE; + } + + + public static void setRileyLinkBLE(RileyLinkBLE rileyLinkBLEIn) { + RileyLinkUtil.rileyLinkBLE = rileyLinkBLEIn; + } + + + public static RileyLinkServiceData getRileyLinkServiceData() { + return RileyLinkUtil.rileyLinkServiceData; + } + + + public static void setRileyLinkServiceData(RileyLinkServiceData rileyLinkServiceData) { + RileyLinkUtil.rileyLinkServiceData = rileyLinkServiceData; + } + + + public static boolean hasPumpBeenTunned() { + return RileyLinkUtil.rileyLinkServiceData.tuneUpDone; + } + + + public static RileyLinkService getRileyLinkService() { + return RileyLinkUtil.rileyLinkService; + } + + + public static void setRileyLinkService(RileyLinkService rileyLinkService) { + RileyLinkUtil.rileyLinkService = rileyLinkService; + } + + + public static RileyLinkCommunicationManager getRileyLinkCommunicationManager() { + return RileyLinkUtil.rileyLinkCommunicationManager; + } + + + public static void setRileyLinkCommunicationManager(RileyLinkCommunicationManager rileyLinkCommunicationManager) { + RileyLinkUtil.rileyLinkCommunicationManager = rileyLinkCommunicationManager; + } + + + public static boolean sendNotification(ServiceNotification notification, Integer clientHashcode) { + return false; + } + + + // FIXME remove ? + public static void setCurrentTask(ServiceTask task) { + if (currentTask == null) { + currentTask = task; + } else { + //LOG.error("setCurrentTask: Cannot replace current task"); + } + } + + + public static void finishCurrentTask(ServiceTask task) { + if (task != currentTask) { + //LOG.error("finishCurrentTask: task does not match"); + } + // hack to force deep copy of transport contents + ServiceTransport transport = task.getServiceTransport().clone(); + + if (transport.hasServiceResult()) { + sendServiceTransportResponse(transport, transport.getServiceResult()); + } + currentTask = null; + } + + + public static void sendServiceTransportResponse(ServiceTransport transport, ServiceResult serviceResult) { + // get the key (hashcode) of the client who requested this + Integer clientHashcode = transport.getSenderHashcode(); + // make a new bundle to send as the message data + transport.setServiceResult(serviceResult); + // FIXME + // transport.setTransportType(RT2Const.IPC.MSG_ServiceResult); + // rileyLinkIPCConnection.sendTransport(transport, clientHashcode); + } + + + public static RileyLinkTargetFrequency getRileyLinkTargetFrequency() { + return RileyLinkUtil.rileyLinkTargetFrequency; + } + + + public static void setRileyLinkTargetFrequency(RileyLinkTargetFrequency rileyLinkTargetFrequency) { + RileyLinkUtil.rileyLinkTargetFrequency = rileyLinkTargetFrequency; + } + + + public static boolean isSame(Double d1, Double d2) { + double diff = d1 - d2; + + return (Math.abs(diff) <= 0.000001); + } + + + @Deprecated + public static BleAdvertisedData parseAdertisedData(byte[] advertisedData) { + List uuids = new ArrayList(); + String name = null; + if (advertisedData == null) { + return new BleAdvertisedData(uuids, name); + } + + ByteBuffer buffer = ByteBuffer.wrap(advertisedData).order(ByteOrder.LITTLE_ENDIAN); + while (buffer.remaining() > 2) { + byte length = buffer.get(); + if (length == 0) + break; + + byte type = buffer.get(); + switch (type) { + case 0x02: // Partial list of 16-bit UUIDs + case 0x03: // Complete list of 16-bit UUIDs + while (length >= 2) { + uuids + .add(UUID.fromString(String.format("%08x-0000-1000-8000-00805f9b34fb", buffer.getShort()))); + length -= 2; + } + break; + case 0x06: // Partial list of 128-bit UUIDs + case 0x07: // Complete list of 128-bit UUIDs + while (length >= 16) { + long lsb = buffer.getLong(); + long msb = buffer.getLong(); + uuids.add(new UUID(msb, lsb)); + length -= 16; + } + break; + case 0x09: + byte[] nameBytes = new byte[length - 1]; + buffer.get(nameBytes); + name = new String(nameBytes, StandardCharsets.UTF_8); + break; + default: + buffer.position(buffer.position() + length - 1); + break; + } + } + return new BleAdvertisedData(uuids, name); + } + + + public static List getRileyLinkHistory() { + return historyRileyLink; + } + + + public static RileyLinkTargetDevice getTargetDevice() { + return targetDevice; + } + + + public static void setTargetDevice(RileyLinkTargetDevice targetDevice) { + RileyLinkUtil.targetDevice = targetDevice; + } + + + public static void setRileyLinkSelectPreference(RileyLinkSelectPreference rileyLinkSelectPreference) { + + RileyLinkUtil.rileyLinkSelectPreference = rileyLinkSelectPreference; + } + + + public static RileyLinkSelectPreference getRileyLinkSelectPreference() { + + return rileyLinkSelectPreference; + } + + + public static Encoding4b6b getEncoding4b6b() { + return RileyLinkUtil.encoding4b6b; + } + + + public static void setFirmwareVersion(RileyLinkFirmwareVersion firmwareVersion) { + RileyLinkUtil.firmwareVersion = firmwareVersion; + } + + + public static RileyLinkFirmwareVersion getFirmwareVersion() { + return firmwareVersion; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/RFSpy.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/RFSpy.java new file mode 100644 index 0000000000..1fb24821e1 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/RFSpy.java @@ -0,0 +1,438 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble; + +import android.os.SystemClock; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.UUID; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.command.Reset; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.command.RileyLinkCommand; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.command.SendAndListen; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.command.SetHardwareEncoding; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.command.SetPreamble; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.command.UpdateRegister; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.GattAttributes; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.RFSpyResponse; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.RadioPacket; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.CC111XRegister; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RXFilterMode; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RileyLinkCommandType; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RileyLinkEncodingType; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RileyLinkFirmwareVersion; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RileyLinkTargetFrequency; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.operations.BLECommOperationResult; +import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; +import info.nightscout.androidaps.plugins.pump.common.utils.StringUtil; +import info.nightscout.androidaps.plugins.pump.common.utils.ThreadUtil; +import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicConst; +import info.nightscout.androidaps.utils.SP; + +/** + * Created by geoff on 5/26/16. + */ +public class RFSpy { + + public static final long RILEYLINK_FREQ_XTAL = 24000000; + public static final int EXPECTED_MAX_BLUETOOTH_LATENCY_MS = 7500; // 1500 + private static final Logger LOG = LoggerFactory.getLogger(L.PUMPBTCOMM); + public int notConnectedCount = 0; + private RileyLinkBLE rileyLinkBle; + private RFSpyReader reader; + private RileyLinkTargetFrequency selectedTargetFrequency; + private UUID radioServiceUUID = UUID.fromString(GattAttributes.SERVICE_RADIO); + private UUID radioDataUUID = UUID.fromString(GattAttributes.CHARA_RADIO_DATA); + private UUID radioVersionUUID = UUID.fromString(GattAttributes.CHARA_RADIO_VERSION); + private UUID responseCountUUID = UUID.fromString(GattAttributes.CHARA_RADIO_RESPONSE_COUNT); + private RileyLinkFirmwareVersion firmwareVersion; + private String bleVersion; // We don't use it so no need of sofisticated logic + Double currentFrequencyMHz; + + + public RFSpy(RileyLinkBLE rileyLinkBle) { + this.rileyLinkBle = rileyLinkBle; + reader = new RFSpyReader(rileyLinkBle); + } + + + public RileyLinkFirmwareVersion getRLVersionCached() { + return firmwareVersion; + } + + + public String getBLEVersionCached() { + return bleVersion; + } + + + // Call this after the RL services are discovered. + // Starts an async task to read when data is available + public void startReader() { + rileyLinkBle.registerRadioResponseCountNotification(new Runnable() { + + @Override + public void run() { + newDataIsAvailable(); + } + }); + reader.start(); + } + + + // Here should go generic RL initialisation + protocol adjustments depending on + // firmware version + public void initializeRileyLink() { + bleVersion = getVersion(); + firmwareVersion = getFirmwareVersion(); + RileyLinkUtil.setFirmwareVersion(firmwareVersion); + } + + + // Call this from the "response count" notification handler. + public void newDataIsAvailable() { + // pass the message to the reader (which should be internal to RFSpy) + reader.newDataIsAvailable(); + } + + + // This gets the version from the BLE113, not from the CC1110. + // I.e., this gets the version from the BLE interface, not from the radio. + public String getVersion() { + BLECommOperationResult result = rileyLinkBle.readCharacteristic_blocking(radioServiceUUID, radioVersionUUID); + if (result.resultCode == BLECommOperationResult.RESULT_SUCCESS) { + String version = StringUtil.fromBytes(result.value); + if (isLogEnabled()) + LOG.debug("BLE Version: " + version); + return version; + } else { + LOG.error("getVersion failed with code: " + result.resultCode); + return "(null)"; + } + } + + + public RileyLinkFirmwareVersion getFirmwareVersion() { + + if (isLogEnabled()) + LOG.debug("Firmware Version. Get Version - Start"); + + for (int i = 0; i < 5; i++) { + // We have to call raw version of communication to get firmware version + // So that we can adjust other commands accordingly afterwords + + byte[] getVersionRaw = getByteArray(RileyLinkCommandType.GetVersion.code); + byte[] response = writeToDataRaw(getVersionRaw, 5000); + + if (isLogEnabled()) + LOG.debug("Firmware Version. GetVersion [response={}]", ByteUtil.shortHexString(response)); + + if (response != null) { // && response[0] == (byte) 0xDD) { + + String versionString = StringUtil.fromBytes(response); + + RileyLinkFirmwareVersion version = RileyLinkFirmwareVersion.getByVersionString(StringUtil + .fromBytes(response)); + + if (isLogEnabled()) + LOG.trace("Firmware Version string: {}, resolved to {}.", versionString, version); + + if (version != RileyLinkFirmwareVersion.UnknownVersion) + return version; + + SystemClock.sleep(1000); + } + } + + LOG.error("Firmware Version can't be determined. Checking with BLE Version [{}].", bleVersion); + + if (bleVersion.contains(" 2.")) { + return RileyLinkFirmwareVersion.Version_2_0; + } + + return RileyLinkFirmwareVersion.UnknownVersion; + } + + + private byte[] writeToDataRaw(byte[] bytes, int responseTimeout_ms) { + SystemClock.sleep(100); + // FIXME drain read queue? + byte[] junkInBuffer = reader.poll(0); + + while (junkInBuffer != null) { + LOG.warn(ThreadUtil.sig() + "writeToData: draining read queue, found this: " + + ByteUtil.shortHexString(junkInBuffer)); + junkInBuffer = reader.poll(0); + } + + // prepend length, and send it. + byte[] prepended = ByteUtil.concat(new byte[]{(byte) (bytes.length)}, bytes); + + LOG.debug("writeToData (raw={})", ByteUtil.shortHexString(prepended)); + + BLECommOperationResult writeCheck = rileyLinkBle.writeCharacteristic_blocking(radioServiceUUID, radioDataUUID, + prepended); + if (writeCheck.resultCode != BLECommOperationResult.RESULT_SUCCESS) { + LOG.error("BLE Write operation failed, code=" + writeCheck.resultCode); + return null; // will be a null (invalid) response + } + SystemClock.sleep(100); + // Log.i(TAG,ThreadUtil.sig()+String.format(" writeToData:(timeout %d) %s",(responseTimeout_ms),ByteUtil.shortHexString(prepended))); + byte[] rawResponse = reader.poll(responseTimeout_ms); + return rawResponse; + + } + + + // The caller has to know how long the RFSpy will be busy with what was sent to it. + private RFSpyResponse writeToData(RileyLinkCommand command, int responseTimeout_ms) { + + byte[] bytes = command.getRaw(); + byte[] rawResponse = writeToDataRaw(bytes, responseTimeout_ms); + + RFSpyResponse resp = new RFSpyResponse(command, rawResponse); + if (rawResponse == null) { + LOG.error("writeToData: No response from RileyLink"); + notConnectedCount++; + } else { + if (resp.wasInterrupted()) { + LOG.error("writeToData: RileyLink was interrupted"); + } else if (resp.wasTimeout()) { + LOG.error("writeToData: RileyLink reports timeout"); + notConnectedCount++; + } else if (resp.isOK()) { + LOG.warn("writeToData: RileyLink reports OK"); + resetNotConnectedCount(); + } else { + if (resp.looksLikeRadioPacket()) { + // RadioResponse radioResp = resp.getRadioResponse(); + // byte[] responsePayload = radioResp.getPayload(); + if (isLogEnabled()) + LOG.trace("writeToData: received radio response. Will decode at upper level"); + resetNotConnectedCount(); + } + // Log.i(TAG, "writeToData: raw response is " + ByteUtil.shortHexString(rawResponse)); + } + } + return resp; + } + + + private void resetNotConnectedCount() { + this.notConnectedCount = 0; + } + + + private byte[] getByteArray(byte... input) { + return input; + } + + + private byte[] getCommandArray(RileyLinkCommandType command, byte[] body) { + int bodyLength = body == null ? 0 : body.length; + + byte[] output = new byte[bodyLength + 1]; + + output[0] = command.code; + + if (body != null) { + for (int i = 0; i < body.length; i++) { + output[i + 1] = body[i]; + } + } + + return output; + } + + + public RFSpyResponse transmitThenReceive(RadioPacket pkt, byte sendChannel, byte repeatCount, byte delay_ms, + byte listenChannel, int timeout_ms, byte retryCount) { + return transmitThenReceive(pkt, sendChannel, repeatCount, delay_ms, listenChannel, timeout_ms, retryCount, null); + } + + + public RFSpyResponse transmitThenReceive(RadioPacket pkt, int timeout_ms) { + return transmitThenReceive(pkt, (byte) 0, (byte) 0, (byte) 0, (byte) 0, timeout_ms, (byte) 0); + } + + + public RFSpyResponse transmitThenReceive(RadioPacket pkt, byte sendChannel, byte repeatCount, byte delay_ms, + byte listenChannel, int timeout_ms, byte retryCount, Integer extendPreamble_ms) { + + int sendDelay = repeatCount * delay_ms; + int receiveDelay = timeout_ms * (retryCount + 1); + + SendAndListen command = new SendAndListen(sendChannel, repeatCount, delay_ms, listenChannel, timeout_ms, + retryCount, extendPreamble_ms, pkt); + + return writeToData(command, sendDelay + receiveDelay + EXPECTED_MAX_BLUETOOTH_LATENCY_MS); + } + + + public RFSpyResponse updateRegister(CC111XRegister reg, int val) { + RFSpyResponse resp = writeToData(new UpdateRegister(reg, (byte) val), EXPECTED_MAX_BLUETOOTH_LATENCY_MS); + return resp; + } + + + public void setBaseFrequency(double freqMHz) { + int value = (int) (freqMHz * 1000000 / ((double) (RILEYLINK_FREQ_XTAL) / Math.pow(2.0, 16.0))); + updateRegister(CC111XRegister.freq0, (byte) (value & 0xff)); + updateRegister(CC111XRegister.freq1, (byte) ((value >> 8) & 0xff)); + updateRegister(CC111XRegister.freq2, (byte) ((value >> 16) & 0xff)); + LOG.info("Set frequency to {} MHz", freqMHz); + + this.currentFrequencyMHz = freqMHz; + + configureRadioForRegion(RileyLinkUtil.getRileyLinkTargetFrequency()); + } + + + private void configureRadioForRegion(RileyLinkTargetFrequency frequency) { + + // we update registers only on first run, or if region changed + + switch (frequency) { + case Medtronic_WorldWide: { + // updateRegister(CC111X_MDMCFG4, (byte) 0x59); + setRXFilterMode(RXFilterMode.Wide); + // updateRegister(CC111X_MDMCFG3, (byte) 0x66); + // updateRegister(CC111X_MDMCFG2, (byte) 0x33); + updateRegister(CC111XRegister.mdmcfg1, 0x62); + updateRegister(CC111XRegister.mdmcfg0, 0x1A); + updateRegister(CC111XRegister.deviatn, 0x13); + setMedtronicEncoding(); + } + break; + + case Medtronic_US: { + // updateRegister(CC111X_MDMCFG4, (byte) 0x99); + setRXFilterMode(RXFilterMode.Narrow); + // updateRegister(CC111X_MDMCFG3, (byte) 0x66); + // updateRegister(CC111X_MDMCFG2, (byte) 0x33); + updateRegister(CC111XRegister.mdmcfg1, 0x61); + updateRegister(CC111XRegister.mdmcfg0, 0x7E); + updateRegister(CC111XRegister.deviatn, 0x15); + setMedtronicEncoding(); + } + break; + + case Omnipod: { + RFSpyResponse r = null; + // RL initialization for Omnipod is a copy/paste from OmniKit implementation. + // Last commit from original repository: 5c3beb4144 + // so if something is terribly wrong, please check git diff PodCommsSession.swift since that commit + r = updateRegister(CC111XRegister.pktctrl1, 0x20); + r = updateRegister(CC111XRegister.agcctrl0, 0x00); + r = updateRegister(CC111XRegister.fsctrl1, 0x06); + r = updateRegister(CC111XRegister.mdmcfg4, 0xCA); + r = updateRegister(CC111XRegister.mdmcfg3, 0xBC); + r = updateRegister(CC111XRegister.mdmcfg2, 0x06); + r = updateRegister(CC111XRegister.mdmcfg1, 0x70); + r = updateRegister(CC111XRegister.mdmcfg0, 0x11); + r = updateRegister(CC111XRegister.deviatn, 0x44); + r = updateRegister(CC111XRegister.mcsm0, 0x18); + r = updateRegister(CC111XRegister.foccfg, 0x17); + r = updateRegister(CC111XRegister.fscal3, 0xE9); + r = updateRegister(CC111XRegister.fscal2, 0x2A); + r = updateRegister(CC111XRegister.fscal1, 0x00); + r = updateRegister(CC111XRegister.fscal0, 0x1F); + + r = updateRegister(CC111XRegister.test1, 0x31); + r = updateRegister(CC111XRegister.test0, 0x09); + r = updateRegister(CC111XRegister.paTable0, 0x84); + r = updateRegister(CC111XRegister.sync1, 0xA5); + r = updateRegister(CC111XRegister.sync0, 0x5A); + + r = setRileyLinkEncoding(RileyLinkEncodingType.Manchester); + r = setPreamble(0x6665); + + } + break; + default: + LOG.warn("No region configuration for RfSpy and {}", frequency.name()); + break; + + } + + this.selectedTargetFrequency = frequency; + } + + + private void setMedtronicEncoding() { + RileyLinkEncodingType encoding = RileyLinkEncodingType.FourByteSixByteLocal; + + if (RileyLinkFirmwareVersion.isSameVersion(this.firmwareVersion, RileyLinkFirmwareVersion.Version2AndHigher)) { + if (SP.getString(MedtronicConst.Prefs.Encoding, "None").equals(MainApp.gs(R.string.key_medtronic_pump_encoding_4b6b_rileylink))) { + encoding = RileyLinkEncodingType.FourByteSixByteRileyLink; + } + } + + setRileyLinkEncoding(encoding); + + if (isLogEnabled()) + LOG.debug("Set Encoding for Medtronic: " + encoding.name()); + } + + + private RFSpyResponse setPreamble(int preamble) { + RFSpyResponse resp = null; + try { + resp = writeToData(new SetPreamble(preamble), EXPECTED_MAX_BLUETOOTH_LATENCY_MS); + } catch (Exception e) { + e.toString(); + } + return resp; + } + + + public RFSpyResponse setRileyLinkEncoding(RileyLinkEncodingType encoding) { + RFSpyResponse resp = writeToData(new SetHardwareEncoding(encoding), EXPECTED_MAX_BLUETOOTH_LATENCY_MS); + + if (resp.isOK()) { + reader.setRileyLinkEncodingType(encoding); + RileyLinkUtil.setEncoding(encoding); + } + + return resp; + } + + + private void setRXFilterMode(RXFilterMode mode) { + + byte drate_e = (byte) 0x9; // exponent of symbol rate (16kbps) + byte chanbw = mode.value; + + updateRegister(CC111XRegister.mdmcfg4, (byte) (chanbw | drate_e)); + } + + /** + * Reset RileyLink Configuration (set all updateRegisters) + */ + public void resetRileyLinkConfiguration() { + if (this.currentFrequencyMHz != null) + this.setBaseFrequency(this.currentFrequencyMHz); + } + + + public RFSpyResponse resetRileyLink() { + RFSpyResponse resp = null; + try { + resp = writeToData(new Reset(), EXPECTED_MAX_BLUETOOTH_LATENCY_MS); + if (isLogEnabled()) + LOG.debug("Reset command send, response: {}", resp); + } catch (Exception e) { + e.toString(); + } + return resp; + } + + + private boolean isLogEnabled() { + return L.isEnabled(L.PUMPBTCOMM); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/RFSpyReader.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/RFSpyReader.java new file mode 100644 index 0000000000..063cdb877b --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/RFSpyReader.java @@ -0,0 +1,150 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble; + +import java.util.UUID; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import android.os.AsyncTask; +import android.os.SystemClock; + +import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.GattAttributes; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RileyLinkEncodingType; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.operations.BLECommOperationResult; +import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; +import info.nightscout.androidaps.plugins.pump.common.utils.ThreadUtil; + +/** + * Created by geoff on 5/26/16. + */ +public class RFSpyReader { + + private static final Logger LOG = LoggerFactory.getLogger(L.PUMPBTCOMM); + private static AsyncTask readerTask; + private RileyLinkBLE rileyLinkBle; + private Semaphore waitForRadioData = new Semaphore(0, true); + private LinkedBlockingQueue mDataQueue = new LinkedBlockingQueue<>(); + private int acquireCount = 0; + private int releaseCount = 0; + private boolean stopAtNull = true; + + + public RFSpyReader(RileyLinkBLE rileyLinkBle) { + this.rileyLinkBle = rileyLinkBle; + } + + + public void init(RileyLinkBLE rileyLinkBLE) { + this.rileyLinkBle = rileyLinkBLE; + } + + + public void setRileyLinkBle(RileyLinkBLE rileyLinkBle) { + if (readerTask != null) { + readerTask.cancel(true); + } + this.rileyLinkBle = rileyLinkBle; + } + + public void setRileyLinkEncodingType(RileyLinkEncodingType encodingType) { + stopAtNull = !(encodingType == RileyLinkEncodingType.Manchester || // + encodingType == RileyLinkEncodingType.FourByteSixByteRileyLink); + } + + + // This timeout must be coordinated with the length of the RFSpy radio operation or Bad Things Happen. + public byte[] poll(int timeout_ms) { + if (isLogEnabled()) + LOG.trace(ThreadUtil.sig() + "Entering poll at t==" + SystemClock.uptimeMillis() + ", timeout is " + timeout_ms + + " mDataQueue size is " + mDataQueue.size()); + + if (mDataQueue.isEmpty()) + try { + // block until timeout or data available. + // returns null if timeout. + byte[] dataFromQueue = mDataQueue.poll(timeout_ms, TimeUnit.MILLISECONDS); + if (dataFromQueue != null) { + if (isLogEnabled()) + LOG.debug("Got data [" + ByteUtil.shortHexString(dataFromQueue) + "] at t==" + + SystemClock.uptimeMillis()); + } else { + if (isLogEnabled()) + LOG.debug("Got data [null] at t==" + SystemClock.uptimeMillis()); + } + return dataFromQueue; + } catch (InterruptedException e) { + LOG.error("poll: Interrupted waiting for data"); + } + return null; + } + + + // Call this from the "response count" notification handler. + public void newDataIsAvailable() { + releaseCount++; + + if (isLogEnabled()) + LOG.trace(ThreadUtil.sig() + "waitForRadioData released(count=" + releaseCount + ") at t=" + + SystemClock.uptimeMillis()); + waitForRadioData.release(); + } + + + public void start() { + readerTask = new AsyncTask() { + + @Override + protected Void doInBackground(Void... voids) { + UUID serviceUUID = UUID.fromString(GattAttributes.SERVICE_RADIO); + UUID radioDataUUID = UUID.fromString(GattAttributes.CHARA_RADIO_DATA); + BLECommOperationResult result; + while (true) { + try { + acquireCount++; + waitForRadioData.acquire(); + if (isLogEnabled()) + LOG.trace(ThreadUtil.sig() + "waitForRadioData acquired (count=" + acquireCount + ") at t=" + + SystemClock.uptimeMillis()); + SystemClock.sleep(100); + SystemClock.sleep(1); + result = rileyLinkBle.readCharacteristic_blocking(serviceUUID, radioDataUUID); + SystemClock.sleep(100); + + if (result.resultCode == BLECommOperationResult.RESULT_SUCCESS) { + if (stopAtNull) { + // only data up to the first null is valid + for (int i = 0; i < result.value.length; i++) { + if (result.value[i] == 0) { + result.value = ByteUtil.substring(result.value, 0, i); + break; + } + } + } + mDataQueue.add(result.value); + } else if (result.resultCode == BLECommOperationResult.RESULT_INTERRUPTED) { + LOG.error("Read operation was interrupted"); + } else if (result.resultCode == BLECommOperationResult.RESULT_TIMEOUT) { + LOG.error("Read operation on Radio Data timed out"); + } else if (result.resultCode == BLECommOperationResult.RESULT_BUSY) { + LOG.error("FAIL: RileyLinkBLE reports operation already in progress"); + } else if (result.resultCode == BLECommOperationResult.RESULT_NONE) { + LOG.error("FAIL: got invalid result code: " + result.resultCode); + } + } catch (InterruptedException e) { + LOG.error("Interrupted while waiting for data"); + } + } + } + }.execute(); + } + + private boolean isLogEnabled() { + return L.isEnabled(L.PUMPBTCOMM); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/RileyLinkBLE.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/RileyLinkBLE.java new file mode 100644 index 0000000000..aab5e35142 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/RileyLinkBLE.java @@ -0,0 +1,589 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble; + +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothGatt; +import android.bluetooth.BluetoothGattCallback; +import android.bluetooth.BluetoothGattCharacteristic; +import android.bluetooth.BluetoothGattDescriptor; +import android.bluetooth.BluetoothGattService; +import android.bluetooth.BluetoothProfile; +import android.content.Context; +import android.os.SystemClock; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; +import java.util.UUID; +import java.util.concurrent.Semaphore; + +import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkConst; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.GattAttributes; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.operations.BLECommOperation; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.operations.BLECommOperationResult; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.operations.CharacteristicReadOperation; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.operations.CharacteristicWriteOperation; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.operations.DescriptorWriteOperation; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkError; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkServiceState; +import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; +import info.nightscout.androidaps.plugins.pump.common.utils.ThreadUtil; + +/** + * Created by geoff on 5/26/16. + * Added: State handling, configuration of RF for different configuration ranges, connection handling + */ +public class RileyLinkBLE { + + private static final Logger LOG = LoggerFactory.getLogger(L.PUMPBTCOMM); + + private final Context context; + public boolean gattDebugEnabled = true; + boolean manualDisconnect = false; + private BluetoothAdapter bluetoothAdapter; + private BluetoothGattCallback bluetoothGattCallback; + private BluetoothDevice rileyLinkDevice; + private BluetoothGatt bluetoothConnectionGatt = null; + private BLECommOperation mCurrentOperation; + private Semaphore gattOperationSema = new Semaphore(1, true); + private Runnable radioResponseCountNotified; + private boolean mIsConnected = false; + + + public RileyLinkBLE(final Context context) { + this.context = context; + this.bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); + + if (isLogEnabled()) + LOG.debug("BT Adapter: " + this.bluetoothAdapter); + bluetoothGattCallback = new BluetoothGattCallback() { + + @Override + public void onCharacteristicChanged(final BluetoothGatt gatt, + final BluetoothGattCharacteristic characteristic) { + super.onCharacteristicChanged(gatt, characteristic); + if (gattDebugEnabled && isLogEnabled()) { + LOG.trace(ThreadUtil.sig() + "onCharacteristicChanged " + + GattAttributes.lookup(characteristic.getUuid()) + " " + + ByteUtil.getHex(characteristic.getValue())); + if (characteristic.getUuid().equals(UUID.fromString(GattAttributes.CHARA_RADIO_RESPONSE_COUNT))) { + LOG.debug("Response Count is " + ByteUtil.shortHexString(characteristic.getValue())); + } + } + if (radioResponseCountNotified != null) { + radioResponseCountNotified.run(); + } + } + + + @Override + public void onCharacteristicRead(final BluetoothGatt gatt, + final BluetoothGattCharacteristic characteristic, int status) { + super.onCharacteristicRead(gatt, characteristic, status); + + final String statusMessage = getGattStatusMessage(status); + if (gattDebugEnabled && isLogEnabled()) { + LOG.trace(ThreadUtil.sig() + "onCharacteristicRead (" + + GattAttributes.lookup(characteristic.getUuid()) + ") " + statusMessage + ":" + + ByteUtil.getHex(characteristic.getValue())); + } + mCurrentOperation.gattOperationCompletionCallback(characteristic.getUuid(), characteristic.getValue()); + } + + + @Override + public void onCharacteristicWrite(final BluetoothGatt gatt, + final BluetoothGattCharacteristic characteristic, int status) { + super.onCharacteristicWrite(gatt, characteristic, status); + + final String uuidString = GattAttributes.lookup(characteristic.getUuid()); + if (gattDebugEnabled && isLogEnabled()) { + LOG.trace(ThreadUtil.sig() + "onCharacteristicWrite " + getGattStatusMessage(status) + " " + + uuidString + " " + ByteUtil.shortHexString(characteristic.getValue())); + } + mCurrentOperation.gattOperationCompletionCallback(characteristic.getUuid(), characteristic.getValue()); + } + + + @Override + public void onConnectionStateChange(final BluetoothGatt gatt, final int status, final int newState) { + super.onConnectionStateChange(gatt, status, newState); + + // https://github.com/NordicSemiconductor/puck-central-android/blob/master/PuckCentral/app/src/main/java/no/nordicsemi/puckcentral/bluetooth/gatt/GattManager.java#L117 + if (status == 133) { + LOG.error("Got the status 133 bug, closing gatt"); + disconnect(); + SystemClock.sleep(500); + return; + } + + if (gattDebugEnabled) { + final String stateMessage; + if (newState == BluetoothProfile.STATE_CONNECTED) { + stateMessage = "CONNECTED"; + } else if (newState == BluetoothProfile.STATE_CONNECTING) { + stateMessage = "CONNECTING"; + } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { + stateMessage = "DISCONNECTED"; + } else if (newState == BluetoothProfile.STATE_DISCONNECTING) { + stateMessage = "DISCONNECTING"; + } else { + stateMessage = "UNKNOWN newState (" + newState + ")"; + } + + if (isLogEnabled()) + LOG.warn("onConnectionStateChange " + getGattStatusMessage(status) + " " + stateMessage); + } + + if (newState == BluetoothProfile.STATE_CONNECTED) { + if (status == BluetoothGatt.GATT_SUCCESS) { + RileyLinkUtil.sendBroadcastMessage(RileyLinkConst.Intents.BluetoothConnected); + } else { + if (isLogEnabled()) + LOG.debug("BT State connected, GATT status {} ({})", status, getGattStatusMessage(status)); + } + + } else if ((newState == BluetoothProfile.STATE_CONNECTING) || // + (newState == BluetoothProfile.STATE_DISCONNECTING)) { + // LOG.debug("We are in {} state.", status == BluetoothProfile.STATE_CONNECTING ? "Connecting" : + // "Disconnecting"); + } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { + RileyLinkUtil.sendBroadcastMessage(RileyLinkConst.Intents.RileyLinkDisconnected); + if (manualDisconnect) + close(); + LOG.warn("RileyLink Disconnected."); + } else { + LOG.warn("Some other state: (status={},newState={})", status, newState); + } + } + + + @Override + public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { + super.onDescriptorWrite(gatt, descriptor, status); + if (gattDebugEnabled && isLogEnabled()) { + LOG.warn("onDescriptorWrite " + GattAttributes.lookup(descriptor.getUuid()) + " " + + getGattStatusMessage(status) + " written: " + ByteUtil.getHex(descriptor.getValue())); + } + mCurrentOperation.gattOperationCompletionCallback(descriptor.getUuid(), descriptor.getValue()); + } + + + @Override + public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { + super.onDescriptorRead(gatt, descriptor, status); + mCurrentOperation.gattOperationCompletionCallback(descriptor.getUuid(), descriptor.getValue()); + if (gattDebugEnabled && isLogEnabled()) { + LOG.warn("onDescriptorRead " + getGattStatusMessage(status) + " status " + descriptor); + } + } + + + @Override + public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) { + super.onMtuChanged(gatt, mtu, status); + if (gattDebugEnabled && isLogEnabled()) { + LOG.warn("onMtuChanged " + mtu + " status " + status); + } + } + + + @Override + public void onReadRemoteRssi(final BluetoothGatt gatt, int rssi, int status) { + super.onReadRemoteRssi(gatt, rssi, status); + if (gattDebugEnabled && isLogEnabled()) { + LOG.warn("onReadRemoteRssi " + getGattStatusMessage(status) + ": " + rssi); + } + } + + + @Override + public void onReliableWriteCompleted(BluetoothGatt gatt, int status) { + super.onReliableWriteCompleted(gatt, status); + if (gattDebugEnabled && isLogEnabled()) { + LOG.warn("onReliableWriteCompleted status " + status); + } + } + + + @Override + public void onServicesDiscovered(final BluetoothGatt gatt, int status) { + super.onServicesDiscovered(gatt, status); + + if (status == BluetoothGatt.GATT_SUCCESS) { + final List services = gatt.getServices(); + + boolean rileyLinkFound = false; + + for (BluetoothGattService service : services) { + final UUID uuidService = service.getUuid(); + + if (isAnyRileyLinkServiceFound(service)) { + rileyLinkFound = true; + } + + if (gattDebugEnabled) { + debugService(service, 0); + } + } + + if (gattDebugEnabled && isLogEnabled()) { + LOG.warn("onServicesDiscovered " + getGattStatusMessage(status)); + } + + LOG.info("Gatt device is RileyLink device: " + rileyLinkFound); + + if (rileyLinkFound) { + mIsConnected = true; + RileyLinkUtil.sendBroadcastMessage(RileyLinkConst.Intents.RileyLinkReady); + // RileyLinkUtil.sendNotification(new + // ServiceNotification(RileyLinkConst.Intents.RileyLinkReady), null); + } else { + mIsConnected = false; + RileyLinkUtil.setServiceState(RileyLinkServiceState.RileyLinkError, + RileyLinkError.DeviceIsNotRileyLink); + } + + } else { + if (isLogEnabled()) + LOG.debug("onServicesDiscovered " + getGattStatusMessage(status)); + RileyLinkUtil.sendBroadcastMessage(RileyLinkConst.Intents.RileyLinkGattFailed); + } + } + }; + } + + + private boolean isAnyRileyLinkServiceFound(BluetoothGattService service) { + + boolean found = false; + + found = GattAttributes.isRileyLink(service.getUuid()); + + if (found) { + return true; + } else { + List includedServices = service.getIncludedServices(); + + for (BluetoothGattService serviceI : includedServices) { + if (isAnyRileyLinkServiceFound(serviceI)) { + return true; + } + + } + } + + return false; + } + + + public BluetoothDevice getRileyLinkDevice() { + return this.rileyLinkDevice; + } + + + public void debugService(BluetoothGattService service, int indentCount) { + + String indentString = StringUtils.repeat(' ', indentCount); + + final UUID uuidService = service.getUuid(); + + if (gattDebugEnabled) { + final String uuidServiceString = uuidService.toString(); + + StringBuilder stringBuilder = new StringBuilder(); + + stringBuilder.append(indentString); + stringBuilder.append(GattAttributes.lookup(uuidServiceString, "Unknown service")); + stringBuilder.append(" (" + uuidServiceString + ")"); + + for (BluetoothGattCharacteristic character : service.getCharacteristics()) { + final String uuidCharacteristicString = character.getUuid().toString(); + + stringBuilder.append("\n "); + stringBuilder.append(indentString); + stringBuilder.append(" - " + GattAttributes.lookup(uuidCharacteristicString, "Unknown Characteristic")); + stringBuilder.append(" (" + uuidCharacteristicString + ")"); + } + + stringBuilder.append("\n\n"); + + LOG.warn(stringBuilder.toString()); + + List includedServices = service.getIncludedServices(); + + for (BluetoothGattService serviceI : includedServices) { + debugService(serviceI, indentCount + 4); + } + } + } + + + public void registerRadioResponseCountNotification(Runnable notifier) { + radioResponseCountNotified = notifier; + } + + + public boolean isConnected() { + return mIsConnected; + } + + + public boolean discoverServices() { + + if (bluetoothConnectionGatt == null) { + // shouldn't happen, but if it does we exit + return false; + } + + if (bluetoothConnectionGatt.discoverServices()) { + if (isLogEnabled()) + LOG.warn("Starting to discover GATT Services."); + return true; + } else { + LOG.error("Cannot discover GATT Services."); + return false; + } + } + + + public boolean enableNotifications() { + BLECommOperationResult result = setNotification_blocking(UUID.fromString(GattAttributes.SERVICE_RADIO), // + UUID.fromString(GattAttributes.CHARA_RADIO_RESPONSE_COUNT)); + if (result.resultCode != BLECommOperationResult.RESULT_SUCCESS) { + LOG.error("Error setting response count notification"); + return false; + } + return true; + } + + + public void findRileyLink(String RileyLinkAddress) { + if (isLogEnabled()) + LOG.debug("RileyLink address: " + RileyLinkAddress); + // Must verify that this is a valid MAC, or crash. + + rileyLinkDevice = bluetoothAdapter.getRemoteDevice(RileyLinkAddress); + // if this succeeds, we get a connection state change callback? + + if (rileyLinkDevice!=null) { + connectGatt(); + } else { + LOG.error("RileyLink device not found with address: " + RileyLinkAddress); + } + } + + + // This function must be run on UI thread. + public void connectGatt() { + if (this.rileyLinkDevice==null) { + LOG.error("RileyLink device is null, can't do connectGatt."); + return; + } + + bluetoothConnectionGatt = rileyLinkDevice.connectGatt(context, true, bluetoothGattCallback); + // , BluetoothDevice.TRANSPORT_LE + if (bluetoothConnectionGatt == null) { + LOG.error("Failed to connect to Bluetooth Low Energy device at " + bluetoothAdapter.getAddress()); + } else { + if (gattDebugEnabled) { + if (isLogEnabled()) + LOG.debug("Gatt Connected."); + } + } + } + + + public void disconnect() { + mIsConnected = false; + if (isLogEnabled()) + LOG.warn("Closing GATT connection"); + // Close old conenction + if (bluetoothConnectionGatt != null) { + // Not sure if to disconnect or to close first.. + bluetoothConnectionGatt.disconnect(); + manualDisconnect = true; + } + } + + + public void close() { + if (bluetoothConnectionGatt != null) { + bluetoothConnectionGatt.close(); + bluetoothConnectionGatt = null; + } + } + + + public BLECommOperationResult setNotification_blocking(UUID serviceUUID, UUID charaUUID) { + BLECommOperationResult rval = new BLECommOperationResult(); + if (bluetoothConnectionGatt != null) { + + try { + gattOperationSema.acquire(); + SystemClock.sleep(1); // attempting to yield thread, to make sequence of events easier to follow + } catch (InterruptedException e) { + LOG.error("setNotification_blocking: interrupted waiting for gattOperationSema"); + return rval; + } + if (mCurrentOperation != null) { + rval.resultCode = BLECommOperationResult.RESULT_BUSY; + } else { + if (bluetoothConnectionGatt.getService(serviceUUID) == null) { + // Catch if the service is not supported by the BLE device + rval.resultCode = BLECommOperationResult.RESULT_NONE; + LOG.error("BT Device not supported"); + // TODO: 11/07/2016 UI update for user + } else { + BluetoothGattCharacteristic chara = bluetoothConnectionGatt.getService(serviceUUID) + .getCharacteristic(charaUUID); + // Tell Android that we want the notifications + bluetoothConnectionGatt.setCharacteristicNotification(chara, true); + List list = chara.getDescriptors(); + if (gattDebugEnabled) { + for (int i = 0; i < list.size(); i++) { + if (isLogEnabled()) + LOG.debug("Found descriptor: " + list.get(i).toString()); + } + } + BluetoothGattDescriptor descr = list.get(0); + // Tell the remote device to send the notifications + mCurrentOperation = new DescriptorWriteOperation(bluetoothConnectionGatt, descr, + BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE); + mCurrentOperation.execute(this); + if (mCurrentOperation.timedOut) { + rval.resultCode = BLECommOperationResult.RESULT_TIMEOUT; + } else if (mCurrentOperation.interrupted) { + rval.resultCode = BLECommOperationResult.RESULT_INTERRUPTED; + } else { + rval.resultCode = BLECommOperationResult.RESULT_SUCCESS; + } + } + mCurrentOperation = null; + gattOperationSema.release(); + } + } else { + LOG.error("setNotification_blocking: not configured!"); + rval.resultCode = BLECommOperationResult.RESULT_NOT_CONFIGURED; + } + return rval; + } + + + // call from main + public BLECommOperationResult writeCharacteristic_blocking(UUID serviceUUID, UUID charaUUID, byte[] value) { + BLECommOperationResult rval = new BLECommOperationResult(); + if (bluetoothConnectionGatt != null) { + rval.value = value; + try { + gattOperationSema.acquire(); + SystemClock.sleep(1); // attempting to yield thread, to make sequence of events easier to follow + } catch (InterruptedException e) { + LOG.error("writeCharacteristic_blocking: interrupted waiting for gattOperationSema"); + return rval; + } + + if (mCurrentOperation != null) { + rval.resultCode = BLECommOperationResult.RESULT_BUSY; + } else { + if (bluetoothConnectionGatt.getService(serviceUUID) == null) { + // Catch if the service is not supported by the BLE device + // GGW: Tue Jul 12 01:14:01 UTC 2016: This can also happen if the + // app that created the bluetoothConnectionGatt has been destroyed/created, + // e.g. when the user switches from portrait to landscape. + rval.resultCode = BLECommOperationResult.RESULT_NONE; + LOG.error("BT Device not supported"); + // TODO: 11/07/2016 UI update for user + } else { + BluetoothGattCharacteristic chara = bluetoothConnectionGatt.getService(serviceUUID) + .getCharacteristic(charaUUID); + mCurrentOperation = new CharacteristicWriteOperation(bluetoothConnectionGatt, chara, value); + mCurrentOperation.execute(this); + if (mCurrentOperation.timedOut) { + rval.resultCode = BLECommOperationResult.RESULT_TIMEOUT; + } else if (mCurrentOperation.interrupted) { + rval.resultCode = BLECommOperationResult.RESULT_INTERRUPTED; + } else { + rval.resultCode = BLECommOperationResult.RESULT_SUCCESS; + } + } + mCurrentOperation = null; + gattOperationSema.release(); + } + } else { + LOG.error("writeCharacteristic_blocking: not configured!"); + rval.resultCode = BLECommOperationResult.RESULT_NOT_CONFIGURED; + } + return rval; + } + + + public BLECommOperationResult readCharacteristic_blocking(UUID serviceUUID, UUID charaUUID) { + BLECommOperationResult rval = new BLECommOperationResult(); + if (bluetoothConnectionGatt != null) { + try { + gattOperationSema.acquire(); + SystemClock.sleep(1); // attempting to yield thread, to make sequence of events easier to follow + } catch (InterruptedException e) { + LOG.error("readCharacteristic_blocking: Interrupted waiting for gattOperationSema"); + return rval; + } + if (mCurrentOperation != null) { + rval.resultCode = BLECommOperationResult.RESULT_BUSY; + } else { + if (bluetoothConnectionGatt.getService(serviceUUID) == null) { + // Catch if the service is not supported by the BLE device + rval.resultCode = BLECommOperationResult.RESULT_NONE; + LOG.error("BT Device not supported"); + // TODO: 11/07/2016 UI update for user + } else { + BluetoothGattCharacteristic chara = bluetoothConnectionGatt.getService(serviceUUID).getCharacteristic( + charaUUID); + mCurrentOperation = new CharacteristicReadOperation(bluetoothConnectionGatt, chara); + mCurrentOperation.execute(this); + if (mCurrentOperation.timedOut) { + rval.resultCode = BLECommOperationResult.RESULT_TIMEOUT; + } else if (mCurrentOperation.interrupted) { + rval.resultCode = BLECommOperationResult.RESULT_INTERRUPTED; + } else { + rval.resultCode = BLECommOperationResult.RESULT_SUCCESS; + rval.value = mCurrentOperation.getValue(); + } + } + } + mCurrentOperation = null; + gattOperationSema.release(); + } else { + LOG.error("readCharacteristic_blocking: not configured!"); + rval.resultCode = BLECommOperationResult.RESULT_NOT_CONFIGURED; + } + return rval; + } + + + private String getGattStatusMessage(final int status) { + final String statusMessage; + if (status == BluetoothGatt.GATT_SUCCESS) { + statusMessage = "SUCCESS"; + } else if (status == BluetoothGatt.GATT_FAILURE) { + statusMessage = "FAILED"; + } else if (status == BluetoothGatt.GATT_WRITE_NOT_PERMITTED) { + statusMessage = "NOT PERMITTED"; + } else if (status == 133) { + statusMessage = "Found the strange 133 bug"; + } else { + statusMessage = "UNKNOWN (" + status + ")"; + } + + return statusMessage; + } + + private boolean isLogEnabled() { + return L.isEnabled(L.PUMPBTCOMM); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/RileyLinkCommunicationException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/RileyLinkCommunicationException.java new file mode 100644 index 0000000000..e694609571 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/RileyLinkCommunicationException.java @@ -0,0 +1,30 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble; + +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RileyLinkBLEError; + +/** + * Created by andy on 11/23/18. + */ + +public class RileyLinkCommunicationException extends Exception { + + String extendedErrorText; + private RileyLinkBLEError errorCode; + + + public RileyLinkCommunicationException(RileyLinkBLEError errorCode, String extendedErrorText) { + super(errorCode.getDescription()); + + this.errorCode = errorCode; + this.extendedErrorText = extendedErrorText; + } + + + public RileyLinkCommunicationException(RileyLinkBLEError errorCode) { + super(errorCode.getDescription()); + + this.errorCode = errorCode; + // this.extendedErrorText = extendedErrorText; + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/command/GetVersion.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/command/GetVersion.java new file mode 100644 index 0000000000..757be66aac --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/command/GetVersion.java @@ -0,0 +1,22 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.command; + +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RileyLinkCommandType; + +public class GetVersion extends RileyLinkCommand { + + public GetVersion() { + super(); + } + + + @Override + public RileyLinkCommandType getCommandType() { + return RileyLinkCommandType.GetVersion; + } + + + @Override + public byte[] getRaw() { + return super.getRawSimple(); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/command/Reset.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/command/Reset.java new file mode 100644 index 0000000000..bd556d6695 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/command/Reset.java @@ -0,0 +1,22 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.command; + +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RileyLinkCommandType; + +public class Reset extends RileyLinkCommand { + + public Reset() { + super(); + } + + + @Override + public RileyLinkCommandType getCommandType() { + return RileyLinkCommandType.Reset; + } + + + @Override + public byte[] getRaw() { + return super.getRawSimple(); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/command/ResetRadioConfig.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/command/ResetRadioConfig.java new file mode 100644 index 0000000000..c37d4da35c --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/command/ResetRadioConfig.java @@ -0,0 +1,22 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.command; + +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RileyLinkCommandType; + +public class ResetRadioConfig extends RileyLinkCommand { + + public ResetRadioConfig() { + super(); + } + + + @Override + public RileyLinkCommandType getCommandType() { + return RileyLinkCommandType.ResetRadioConfig; + } + + + @Override + public byte[] getRaw() { + return super.getRawSimple(); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/command/RileyLinkCommand.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/command/RileyLinkCommand.java new file mode 100644 index 0000000000..4eeffc6439 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/command/RileyLinkCommand.java @@ -0,0 +1,27 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.command; + +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RileyLinkCommandType; + +public abstract class RileyLinkCommand { + + public RileyLinkCommand() { + } + + + public abstract RileyLinkCommandType getCommandType(); + + + public abstract byte[] getRaw(); + + + protected byte[] getRawSimple() { + return getByteArray(getCommandType().code); + + } + + + protected byte[] getByteArray(byte... input) { + return input; + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/command/SendAndListen.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/command/SendAndListen.java new file mode 100644 index 0000000000..900275a05f --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/command/SendAndListen.java @@ -0,0 +1,96 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.command; + +import java.nio.ByteBuffer; +import java.util.ArrayList; + +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.RadioPacket; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RileyLinkCommandType; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RileyLinkFirmwareVersion; +import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; + +public class SendAndListen extends RileyLinkCommand { + + private byte sendChannel; + private byte repeatCount; + private int delayBetweenPackets_ms; + private byte listenChannel; + private int timeout_ms; + private byte retryCount; + private Integer preambleExtension_ms; + private RadioPacket packetToSend; + + + public SendAndListen(byte sendChannel, byte repeatCount, byte delayBetweenPackets_ms, byte listenChannel, + int timeout_ms, byte retryCount, RadioPacket packetToSend + + ) { + this(sendChannel, repeatCount, delayBetweenPackets_ms, listenChannel, timeout_ms, retryCount, null, + packetToSend); + } + + + public SendAndListen(byte sendChannel, byte repeatCount, int delayBetweenPackets_ms, byte listenChannel, + int timeout_ms, byte retryCount, Integer preambleExtension_ms, RadioPacket packetToSend + + ) { + super(); + this.sendChannel = sendChannel; + this.repeatCount = repeatCount; + this.delayBetweenPackets_ms = delayBetweenPackets_ms; + this.listenChannel = listenChannel; + this.timeout_ms = timeout_ms; + this.retryCount = retryCount; + this.preambleExtension_ms = preambleExtension_ms == null ? 0 : preambleExtension_ms; + this.packetToSend = packetToSend; + } + + + @Override + public RileyLinkCommandType getCommandType() { + return RileyLinkCommandType.SendAndListen; + } + + + @Override + public byte[] getRaw() { + + // If firmware version is not set (error reading version from device, shouldn't happen), + // we will default to version 2 + boolean isPacketV2 = RileyLinkUtil.getFirmwareVersion() != null ? RileyLinkUtil.getFirmwareVersion() + .isSameVersion(RileyLinkFirmwareVersion.Version2AndHigher) : true; + + ArrayList bytes = new ArrayList(); + bytes.add(this.getCommandType().code); + bytes.add(this.sendChannel); + bytes.add(this.repeatCount); + + if (isPacketV2) { // delay is unsigned 16-bit integer + byte[] delayBuff = ByteBuffer.allocate(4).putInt(delayBetweenPackets_ms).array(); + bytes.add(delayBuff[2]); + bytes.add(delayBuff[3]); + } else { + bytes.add((byte)delayBetweenPackets_ms); + } + + bytes.add(this.listenChannel); + + byte[] timeoutBuff = ByteBuffer.allocate(4).putInt(timeout_ms).array(); + + bytes.add(timeoutBuff[0]); + bytes.add(timeoutBuff[1]); + bytes.add(timeoutBuff[2]); + bytes.add(timeoutBuff[3]); + + bytes.add(retryCount); + + if (isPacketV2) { // 2.x (and probably higher versions) support preamble extension + byte[] preambleBuf = ByteBuffer.allocate(4).putInt(preambleExtension_ms).array(); + bytes.add(preambleBuf[2]); + bytes.add(preambleBuf[3]); + } + + return ByteUtil.concat(ByteUtil.getByteArrayFromList(bytes), packetToSend.getEncoded()); + + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/command/SetHardwareEncoding.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/command/SetHardwareEncoding.java new file mode 100644 index 0000000000..8019563ee9 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/command/SetHardwareEncoding.java @@ -0,0 +1,27 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.command; + +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RileyLinkCommandType; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RileyLinkEncodingType; + +public class SetHardwareEncoding extends RileyLinkCommand { + + private final RileyLinkEncodingType encoding; + + + public SetHardwareEncoding(RileyLinkEncodingType encoding) { + super(); + this.encoding = encoding; + } + + + @Override + public RileyLinkCommandType getCommandType() { + return RileyLinkCommandType.SetHardwareEncoding; + } + + + @Override + public byte[] getRaw() { + return getByteArray(getCommandType().code, encoding.value); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/command/SetPreamble.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/command/SetPreamble.java new file mode 100644 index 0000000000..7333459f2b --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/command/SetPreamble.java @@ -0,0 +1,42 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.command; + +import java.nio.ByteBuffer; + +import org.apache.commons.lang3.NotImplementedException; + +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RileyLinkCommandType; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RileyLinkFirmwareVersion; + +public class SetPreamble extends RileyLinkCommand { + + private int preamble; + + + public SetPreamble(int preamble) throws Exception { + super(); + + // this command was not supported before 2.0 + if (!RileyLinkUtil.getFirmwareVersion().isSameVersion(RileyLinkFirmwareVersion.Version2AndHigher)) { + throw new NotImplementedException("Old firmware does not support SetPreamble command"); + } + + if (preamble < 0 || preamble > 0xFFFF) { + throw new Exception("preamble value is out of range"); + } + this.preamble = preamble; + } + + + @Override + public RileyLinkCommandType getCommandType() { + return RileyLinkCommandType.SetPreamble; + } + + + @Override + public byte[] getRaw() { + byte[] bytes = ByteBuffer.allocate(4).putInt(preamble).array(); + return getByteArray(this.getCommandType().code, bytes[2], bytes[3]); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/command/UpdateRegister.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/command/UpdateRegister.java new file mode 100644 index 0000000000..71ae922ba8 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/command/UpdateRegister.java @@ -0,0 +1,29 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.command; + +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.CC111XRegister; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RileyLinkCommandType; + +public class UpdateRegister extends RileyLinkCommand { + + CC111XRegister register; + byte registerValue; + + + public UpdateRegister(CC111XRegister register, byte registerValue) { + super(); + this.register = register; + this.registerValue = registerValue; + } + + + @Override + public RileyLinkCommandType getCommandType() { + return RileyLinkCommandType.UpdateRegister; + } + + + @Override + public byte[] getRaw() { + return getByteArray(getCommandType().code, register.value, registerValue); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/data/FrequencyScanResults.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/data/FrequencyScanResults.java new file mode 100644 index 0000000000..88850e315e --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/data/FrequencyScanResults.java @@ -0,0 +1,30 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * Created by geoff on 5/30/16. + * changed by Andy 10/20/18 + */ +public class FrequencyScanResults { + + public List trials = new ArrayList<>(); + public double bestFrequencyMHz = 0.0; + public long dateTime; + + + public void sort() { + Collections.sort(trials, (trial1, trial2) -> { + int res = trial1.averageRSSI.compareTo(trial2.averageRSSI); + + if (res == 0) { + return (int)(trial1.frequencyMHz - trial2.frequencyMHz); + } else + return res; + + }); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/data/FrequencyTrial.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/data/FrequencyTrial.java new file mode 100644 index 0000000000..af7dce6a98 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/data/FrequencyTrial.java @@ -0,0 +1,35 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by geoff on 5/30/16. + * changed by Andy 10/20/18 + */ +public class FrequencyTrial { + + public int tries = 0; + public int successes = 0; + public Double averageRSSI = 0.0; + public double frequencyMHz = 0.0; + public List rssiList = new ArrayList<>(); + public double averageRSSI2; + + + public void calculateAverage() { + int sum = 0; + int count = 0; + for (Integer rssi : rssiList) { + sum += Math.abs(rssi); + count++; + } + + double avg = (sum / (count * 1.0d)); + + if (count != 0) + this.averageRSSI = avg * (-1); + else + this.averageRSSI = -99.0d; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/data/GattAttributes.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/data/GattAttributes.java new file mode 100644 index 0000000000..4a76d25d1c --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/data/GattAttributes.java @@ -0,0 +1,87 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +/** + * Created by geoff on 5/21/16. + */ +public class GattAttributes { + + // NOTE: these uuid strings must be lower case! + + public static String PREFIX = "0000"; + public static String SUFFIX = "-0000-1000-8000-00805f9b34fb"; + public static String SERVICE_GAP = PREFIX + "1800" + SUFFIX; + public static String CHARA_GAP_NAME = PREFIX + "2a00" + SUFFIX; // RileyLink RFSpy + public static String CHARA_GAP_NUM = PREFIX + "2a01" + SUFFIX; // 0000 + public static String CHARA_GAP_UNK = PREFIX + "2a01" + SUFFIX; // a + + public static String SERVICE_BATTERY = PREFIX + "180f" + SUFFIX; // Battery + public static String CHARA_BATTERY_UNK = PREFIX + "2a19" + SUFFIX; + + // RileyLink Radio Service + public static String SERVICE_RADIO = "0235733b-99c5-4197-b856-69219c2a3845"; + public static String CHARA_RADIO_DATA = "c842e849-5028-42e2-867c-016adada9155"; + public static String CHARA_RADIO_RESPONSE_COUNT = "6e6c7910-b89e-43a5-a0fe-50c5e2b81f4a"; + public static String CHARA_RADIO_TIMER_TICK = "6e6c7910-b89e-43a5-78af-50c5e2b86f7e"; + public static String CHARA_RADIO_CUSTOM_NAME = "d93b2af0-1e28-11e4-8c21-0800200c9a66"; + public static String CHARA_RADIO_VERSION = "30d99dc9-7c91-4295-a051-0a104d238cf2"; + public static String CHARA_RADIO_LED_MODE = "c6d84241-f1a7-4f9c-a25f-fce16732f14e"; + + private static Map attributes; + private static Map attributesRileyLinkSpecific; + + // table of names for uuids + static { + attributes = new HashMap<>(); + + attributes.put(SERVICE_GAP, "Device Information Service"); + attributes.put(CHARA_GAP_NAME, "Name"); // + attributes.put(CHARA_GAP_NUM, "Number"); // + + attributes.put(SERVICE_BATTERY, "Battery Service"); + + attributes.put(SERVICE_RADIO, "Radio Interface"); // a + attributes.put(CHARA_RADIO_CUSTOM_NAME, "Custom Name"); + attributes.put(CHARA_RADIO_DATA, "Data"); + attributes.put(CHARA_RADIO_RESPONSE_COUNT, "Response Count"); + attributes.put(CHARA_RADIO_TIMER_TICK, "Timer Tick"); + attributes.put(CHARA_RADIO_VERSION, "Version"); // firmwareVersion + attributes.put(CHARA_RADIO_LED_MODE, "Led Mode"); + + attributesRileyLinkSpecific = new HashMap<>(); + + attributesRileyLinkSpecific.put(SERVICE_RADIO, "Radio Interface"); // a + attributesRileyLinkSpecific.put(CHARA_RADIO_CUSTOM_NAME, "Custom Name"); + attributesRileyLinkSpecific.put(CHARA_RADIO_DATA, "Data"); + attributesRileyLinkSpecific.put(CHARA_RADIO_RESPONSE_COUNT, "Response Count"); + attributesRileyLinkSpecific.put(CHARA_RADIO_TIMER_TICK, "Timer Tick"); + attributesRileyLinkSpecific.put(CHARA_RADIO_VERSION, "Version"); // firmwareVersion + attributesRileyLinkSpecific.put(CHARA_RADIO_LED_MODE, "Led Mode"); + } + + + public static String lookup(UUID uuid) { + return lookup(uuid.toString()); + } + + + public static String lookup(String uuid) { + return lookup(uuid, uuid); + } + + + public static String lookup(String uuid, String defaultName) { + String name = attributes.get(uuid); + return name == null ? defaultName : name; + } + + + // we check for specific UUID (Radio ones, because thoose seem to be unique + public static boolean isRileyLink(UUID uuid) { + return attributesRileyLinkSpecific.containsKey(uuid.toString()); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/data/RFSpyResponse.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/data/RFSpyResponse.java new file mode 100644 index 0000000000..cf5362427c --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/data/RFSpyResponse.java @@ -0,0 +1,134 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data; + +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.RileyLinkCommunicationException; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.command.RileyLinkCommand; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RFSpyRLResponse; + +/** + * Created by geoff on 5/26/16. + */ +public class RFSpyResponse { + + // 0xaa == timeout + // 0xbb == interrupted + // 0xcc == zero-data + // 0xdd == success + // 0x11 == invalidParam + // 0x22 == unknownCommand + + protected byte[] raw; + protected RadioResponse radioResponse; + private RileyLinkCommand command; + + + public RFSpyResponse() { + init(new byte[0]); + } + + + public RFSpyResponse(byte[] bytes) { + init(bytes); + } + + + public RFSpyResponse(RileyLinkCommand command, byte[] rawResponse) { + + this.command = command; + init(rawResponse); + } + + + public void init(byte[] bytes) { + if (bytes == null) { + raw = new byte[0]; + } else { + raw = bytes; + } + + } + + + public RadioResponse getRadioResponse() throws RileyLinkCommunicationException { + if (looksLikeRadioPacket()) { + radioResponse = new RadioResponse(command); + radioResponse.init(raw); + } else { + radioResponse = new RadioResponse(); + } + return radioResponse; + } + + + public boolean wasTimeout() { + if ((raw.length == 1) || (raw.length == 2)) { + if (raw[0] == (byte)0xaa) { + return true; + } + } + return false; + } + + + public boolean wasInterrupted() { + if ((raw.length == 1) || (raw.length == 2)) { + if (raw[0] == (byte)0xbb) { + return true; + } + } + return false; + } + + + public boolean isInvalidParam() { + if ((raw.length == 1) || (raw.length == 2)) { + if (raw[0] == (byte)0x11) { + return true; + } + } + return false; + } + + + public boolean isUnknownCommand() { + if ((raw.length == 1) || (raw.length == 2)) { + if (raw[0] == (byte)0x22) { + return true; + } + } + return false; + } + + + public boolean isOK() { + if ((raw.length == 1) || (raw.length == 2)) { + if (raw[0] == (byte)0x01 || raw[0] == (byte)0xDD) { + return true; + } + } + return false; + } + + + public boolean looksLikeRadioPacket() { + if (raw.length > 2) { + return true; + } + return false; + } + + + @Override + public String toString() { + if (raw.length > 2) { + return "Radio packet"; + } else { + RFSpyRLResponse r = RFSpyRLResponse.fromByte(raw[0]); + return r.toString(); + } + } + + + public byte[] getRaw() { + return raw; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/data/RLMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/data/RLMessage.java new file mode 100644 index 0000000000..b52c3eb264 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/data/RLMessage.java @@ -0,0 +1,13 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data; + +/** + * Created by andy on 5/6/18. + */ +public interface RLMessage { + + byte[] getTxData(); + + + boolean isValid(); + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/data/RLMessageType.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/data/RLMessageType.java new file mode 100644 index 0000000000..4fbc3144bd --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/data/RLMessageType.java @@ -0,0 +1,11 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data; + +/** + * Created by andy on 5/6/18. + */ + +public enum RLMessageType { + PowerOn, // for powering on the pump (wakeup) + ReadSimpleData, // for checking if pump is readable (for Medtronic we can use GetModel) + ; +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/data/RadioPacket.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/data/RadioPacket.java new file mode 100644 index 0000000000..a48e3de208 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/data/RadioPacket.java @@ -0,0 +1,57 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data; + +import org.apache.commons.lang3.NotImplementedException; + +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil; +import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; +import info.nightscout.androidaps.plugins.pump.common.utils.CRC; + +/** + * Created by geoff on 5/22/16. + */ + +public class RadioPacket { + + protected byte[] pkt; + + + public RadioPacket(byte[] pkt) { + this.pkt = pkt; + } + + + public byte[] getRaw() { + return pkt; + } + + + public byte[] getWithCRC() { + byte[] withCRC = ByteUtil.concat(pkt, CRC.crc8(pkt)); + return withCRC; + } + + + public byte[] getEncoded() { + + switch (RileyLinkUtil.getEncoding()) { + case Manchester: { // We have this encoding in RL firmware + return pkt; + } + + case FourByteSixByteLocal: { + byte[] withCRC = getWithCRC(); + + byte[] encoded = RileyLinkUtil.getEncoding4b6b().encode4b6b(withCRC); + return ByteUtil.concat(encoded, (byte)0); + } + + case FourByteSixByteRileyLink: { + return getWithCRC(); + } + + default: + throw new NotImplementedException(("Encoding not supported: " + RileyLinkUtil.getEncoding().toString())); + } + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/data/RadioResponse.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/data/RadioResponse.java new file mode 100644 index 0000000000..646d7aac9a --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/data/RadioResponse.java @@ -0,0 +1,142 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data; + +import org.apache.commons.lang3.NotImplementedException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.RileyLinkCommunicationException; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.command.RileyLinkCommand; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RileyLinkBLEError; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RileyLinkCommandType; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RileyLinkFirmwareVersion; +import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; +import info.nightscout.androidaps.plugins.pump.common.utils.CRC; + +/** + * Created by geoff on 5/30/16. + */ +public class RadioResponse { + + private static final Logger LOG = LoggerFactory.getLogger(L.PUMPBTCOMM); + + public boolean decodedOK = false; + public int rssi; + public int responseNumber; + public byte[] decodedPayload = new byte[0]; + public byte receivedCRC; + private RileyLinkCommand command; + + + public RadioResponse() { + + } + + + // public RadioResponse(byte[] rxData) { + // init(rxData); + // } + + public RadioResponse(RileyLinkCommand command /* , byte[] raw */) { + this.command = command; + // init(raw); + } + + + public boolean isValid() { + + // We should check for all listening commands, but only one is actually used + if (command != null && command.getCommandType() != RileyLinkCommandType.SendAndListen) { + return true; + } + + if (!decodedOK) { + return false; + } + if (decodedPayload != null) { + if (receivedCRC == CRC.crc8(decodedPayload)) { + return true; + } + } + return false; + } + + + public void init(byte[] rxData) throws RileyLinkCommunicationException { + + if (rxData == null) { + return; + } + if (rxData.length < 3) { + // This does not look like something valid heard from a RileyLink device + return; + } + byte[] encodedPayload; + + if (RileyLinkFirmwareVersion.isSameVersion(RileyLinkUtil.getRileyLinkServiceData().versionCC110, + RileyLinkFirmwareVersion.Version2)) { + encodedPayload = ByteUtil.substring(rxData, 3, rxData.length - 3); + rssi = rxData[1]; + responseNumber = rxData[2]; + } else { + encodedPayload = ByteUtil.substring(rxData, 2, rxData.length - 2); + rssi = rxData[0]; + responseNumber = rxData[1]; + } + + try { + + // for non-radio commands we just return the raw response + // well, for non-radio commands we shouldn't even reach this point + // but getVersion is kind of exception + if (command != null && // + command.getCommandType() != RileyLinkCommandType.SendAndListen) { + decodedOK = true; + decodedPayload = encodedPayload; + return; + } + + switch (RileyLinkUtil.getEncoding()) { + + case Manchester: + case FourByteSixByteRileyLink: { + decodedOK = true; + decodedPayload = encodedPayload; + } + break; + + case FourByteSixByteLocal: { + byte[] decodeThis = RileyLinkUtil.getEncoding4b6b().decode4b6b(encodedPayload); + + if (decodeThis != null && decodeThis.length > 2) { + decodedOK = true; + + decodedPayload = ByteUtil.substring(decodeThis, 0, decodeThis.length - 1); + receivedCRC = decodeThis[decodeThis.length - 1]; + byte calculatedCRC = CRC.crc8(decodedPayload); + if (receivedCRC != calculatedCRC) { + LOG.error(String.format("RadioResponse: CRC mismatch, calculated 0x%02x, received 0x%02x", + calculatedCRC, receivedCRC)); + } + } else { + throw new RileyLinkCommunicationException(RileyLinkBLEError.TooShortOrNullResponse); + } + } + break; + + default: + throw new NotImplementedException("this {" + RileyLinkUtil.getEncoding().toString() + + "} encoding is not supported"); + } + } catch (NumberFormatException e) { + decodedOK = false; + LOG.error("Failed to decode radio data: " + ByteUtil.shortHexString(encodedPayload)); + } + } + + + public byte[] getPayload() { + return decodedPayload; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/data/encoding/Encoding4b6b.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/data/encoding/Encoding4b6b.java new file mode 100644 index 0000000000..a05a0be401 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/data/encoding/Encoding4b6b.java @@ -0,0 +1,16 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.encoding; + +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.RileyLinkCommunicationException; + +/** + * Created by andy on 11/24/18. + */ + +public interface Encoding4b6b { + + byte[] encode4b6b(byte[] data); + + + byte[] decode4b6b(byte[] data) throws RileyLinkCommunicationException; + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/data/encoding/Encoding4b6bAbstract.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/data/encoding/Encoding4b6bAbstract.java new file mode 100644 index 0000000000..3bab1a6d05 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/data/encoding/Encoding4b6bAbstract.java @@ -0,0 +1,69 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.encoding; + +import org.slf4j.Logger; + +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.RileyLinkCommunicationException; +import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; + + +/** + * Created by andy on 11/24/18. + */ + +public abstract class Encoding4b6bAbstract implements Encoding4b6b { + + /** + * encode4b6bMap is an ordered list of translations 6bits -> 4 bits, in order from 0x0 to 0xF + * The 6 bit codes are what is used on the RF side of the RileyLink to communicate + * with a Medtronic pump. + */ + public static final byte[] encode4b6bList = new byte[] { + 0x15, 0x31, 0x32, 0x23, 0x34, 0x25, 0x26, 0x16, 0x1a, 0x19, 0x2a, 0x0b, 0x2c, 0x0d, 0x0e, 0x1c }; + + + // 21, 49, 50, 35, 52, 37, 38, 22, 26, 25, 42, 11, 44, 13, 14, 28 + + public abstract byte[] encode4b6b(byte[] data); + + + public abstract byte[] decode4b6b(byte[] data) throws RileyLinkCommunicationException; + + + protected short convertUnsigned(byte x) { + short ss = x; + + if (ss < 0) { + ss += 256; + } + + return ss; + } + + + /* O(n) lookup. Run on an O(n) translation of a byte-stream, gives O(n**2) performance. Sigh. */ + public static int encode4b6bListIndex(byte b) { + for (int i = 0; i < encode4b6bList.length; i++) { + if (b == encode4b6bList[i]) { + return i; + } + } + return -1; + } + + + public void writeError(Logger LOG, byte[] raw, String errorData) { + + LOG.error("\n=============================================================================\n" + // + " Decoded payload length is zero.\n" + + " encodedPayload: {}\n" + + " errors: {}\n" + + "=============================================================================", // + ByteUtil.getHex(raw), errorData); + + //FabricUtil.createEvent("MedtronicDecode4b6bError", null); + + return; + + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/data/encoding/Encoding4b6bGeoff.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/data/encoding/Encoding4b6bGeoff.java new file mode 100644 index 0000000000..40f24cf135 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/data/encoding/Encoding4b6bGeoff.java @@ -0,0 +1,249 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.encoding; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; + +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.RileyLinkCommunicationException; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RileyLinkBLEError; +import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; + +/** + * Created by andy on 11/24/18. + */ + +public class Encoding4b6bGeoff extends Encoding4b6bAbstract { + + public static final Logger LOG = LoggerFactory.getLogger(Encoding4b6bGeoff.class); + + + public byte[] encode4b6b(byte[] data) { + // if ((data.length % 2) != 0) { + // LOG.error("Warning: data is odd number of bytes"); + // } + // use arraylists because byte[] is annoying. + List inData = ByteUtil.getListFromByteArray(data); + List outData = new ArrayList<>(); + + int acc = 0; + int bitcount = 0; + int i; + for (i = 0; i < inData.size(); i++) { + acc <<= 6; + acc |= encode4b6bList[(inData.get(i) >> 4) & 0x0f]; + bitcount += 6; + + acc <<= 6; + acc |= encode4b6bList[inData.get(i) & 0x0f]; + bitcount += 6; + + while (bitcount >= 8) { + byte outByte = (byte) (acc >> (bitcount - 8) & 0xff); + outData.add(outByte); + bitcount -= 8; + acc &= (0xffff >> (16 - bitcount)); + } + } + if (bitcount > 0) { + acc <<= 6; + acc |= 0x14; // marks uneven packet boundary. + bitcount += 6; + if (bitcount >= 8) { + byte outByte = (byte) ((acc >> (bitcount - 8)) & 0xff); + outData.add(outByte); + bitcount -= 8; + // acc &= (0xffff >> (16 - bitcount)); + } + while (bitcount >= 8) { + outData.add((byte) 0); + bitcount -= 8; + } + } + + // convert back to byte[] + byte[] rval = ByteUtil.getByteArrayFromList(outData); + + return rval; + + } + + + /** + * Decode by Geoff + * + * @param raw + * @return + * @throws NumberFormatException + */ + public byte[] decode4b6b(byte[] raw) throws RileyLinkCommunicationException { + + StringBuilder errorMessageBuilder = new StringBuilder(); + + errorMessageBuilder.append("Input data: " + ByteUtil.shortHexString(raw) + "\n"); + + if ((raw.length % 2) != 0) { + errorMessageBuilder.append("Warn: odd number of bytes.\n"); + } + + byte[] rval = new byte[]{}; + int availableBits = 0; + int codingErrors = 0; + int x = 0; + // Log.w(TAG,"decode4b6b: untested code"); + // Log.w(TAG,String.format("Decoding %d bytes: %s",raw.length,ByteUtil.shortHexString(raw))); + for (int i = 0; i < raw.length; i++) { + int unsignedValue = raw[i]; + if (unsignedValue < 0) { + unsignedValue += 256; + } + x = (x << 8) + unsignedValue; + availableBits += 8; + if (availableBits >= 12) { + // take top six + int highcode = (x >> (availableBits - 6)) & 0x3F; + int highIndex = encode4b6bListIndex((byte) (highcode)); + // take bottom six + int lowcode = (x >> (availableBits - 12)) & 0x3F; + int lowIndex = encode4b6bListIndex((byte) (lowcode)); + // special case at end of transmission on uneven boundaries: + if ((highIndex >= 0) && (lowIndex >= 0)) { + byte decoded = (byte) ((highIndex << 4) + lowIndex); + rval = ByteUtil.concat(rval, decoded); + /* + * LOG.debug(String.format( + * "i=%d,x=0x%08X,0x%02X->0x%02X, 0x%02X->0x%02X, result: 0x%02X, %d bits remaining, errors %d, bytes remaining: %s" + * , + * i,x,highcode,highIndex, lowcode, + * lowIndex,decoded,availableBits,codingErrors,ByteUtil.shortHexString + * (ByteUtil.substring(raw,i+1,raw.length-i-1)))); + */ + } else { + // LOG.debug(String.format("i=%d,x=%08X, coding error: highcode=0x%02X, lowcode=0x%02X, %d bits remaining",i,x,highcode,lowcode,availableBits)); + errorMessageBuilder.append(String.format( + "decode4b6b: i=%d,x=%08X, coding error: highcode=0x%02X, lowcode=0x%02X, %d bits remaining.\n", + i, x, highcode, lowcode, availableBits)); + codingErrors++; + } + + availableBits -= 12; + x = x & (0x0000ffff >> (16 - availableBits)); + } + } + + if (availableBits != 0) { + if ((availableBits == 4) && (x == 0x05)) { + // normal end + } else { + // LOG.error("decode4b6b: failed clean decode -- extra bits available (not marker)(" + availableBits + + // ")"); + errorMessageBuilder.append("decode4b6b: failed clean decode -- extra bits available (not marker)(" + + availableBits + ")\n"); + codingErrors++; + } + } else { + // also normal end. + } + + if (codingErrors > 0) { + // LOG.error("decode4b6b: " + codingErrors + " coding errors encountered."); + errorMessageBuilder.append("decode4b6b: " + codingErrors + " coding errors encountered."); + writeError(LOG, raw, errorMessageBuilder.toString()); + throw new RileyLinkCommunicationException(RileyLinkBLEError.CodingErrors, errorMessageBuilder.toString()); + } + return rval; + } + + // public static RFTools.DecodeResponseDto decode4b6bWithoutException(byte[] raw) { + // /* + // * if ((raw.length % 2) != 0) { + // * LOG.error("Warning: data is odd number of bytes"); + // * } + // */ + // + // RFTools.DecodeResponseDto response = new RFTools.DecodeResponseDto(); + // + // StringBuilder errorMessageBuilder = new StringBuilder(); + // + // errorMessageBuilder.append("Input data: " + ByteUtil.getHex(raw) + "\n"); + // + // if ((raw.length % 2) != 0) { + // errorMessageBuilder.append("Warn: odd number of bytes."); + // } + // + // byte[] rval = new byte[] {}; + // int availableBits = 0; + // int codingErrors = 0; + // int x = 0; + // // Log.w(TAG,"decode4b6b: untested code"); + // // Log.w(TAG,String.format("Decoding %d bytes: %s",raw.length,ByteUtil.shortHexString(raw))); + // for (int i = 0; i < raw.length; i++) { + // int unsignedValue = raw[i]; + // if (unsignedValue < 0) { + // unsignedValue += 256; + // } + // x = (x << 8) + unsignedValue; + // availableBits += 8; + // if (availableBits >= 12) { + // // take top six + // int highcode = (x >> (availableBits - 6)) & 0x3F; + // int highIndex = encode4b6bListIndex((byte)(highcode)); + // // take bottom six + // int lowcode = (x >> (availableBits - 12)) & 0x3F; + // int lowIndex = encode4b6bListIndex((byte)(lowcode)); + // // special case at end of transmission on uneven boundaries: + // if ((highIndex >= 0) && (lowIndex >= 0)) { + // byte decoded = (byte)((highIndex << 4) + lowIndex); + // rval = ByteUtil.concat(rval, decoded); + // /* + // * LOG.debug(String.format( + // * + // "i=%d,x=0x%08X,0x%02X->0x%02X, 0x%02X->0x%02X, result: 0x%02X, %d bits remaining, errors %d, bytes remaining: %s" + // * , + // * i,x,highcode,highIndex, lowcode, + // * lowIndex,decoded,availableBits,codingErrors,ByteUtil.shortHexString + // * (ByteUtil.substring(raw,i+1,raw.length-i-1)))); + // */ + // } else { + // // + // LOG.debug(String.format("i=%d,x=%08X, coding error: highcode=0x%02X, lowcode=0x%02X, %d bits remaining",i,x,highcode,lowcode,availableBits)); + // errorMessageBuilder.append(String.format( + // "decode4b6b: i=%d,x=%08X, coding error: highcode=0x%02X, lowcode=0x%02X, %d bits remaining.\n", + // i, x, highcode, lowcode, availableBits)); + // codingErrors++; + // } + // + // availableBits -= 12; + // x = x & (0x0000ffff >> (16 - availableBits)); + // } else { + // // LOG.debug(String.format("i=%d, skip: x=0x%08X, available bits %d",i,x,availableBits)); + // } + // } + // + // if (availableBits != 0) { + // if ((availableBits == 4) && (x == 0x05)) { + // // normal end + // } else { + // LOG.error("decode4b6b: failed clean decode -- extra bits available (not marker)(" + availableBits + ")"); + // errorMessageBuilder.append("decode4b6b: failed clean decode -- extra bits available (not marker)(" + // + availableBits + ")\n"); + // codingErrors++; + // } + // } else { + // // also normal end. + // } + // + // if (codingErrors > 0) { + // LOG.error("decode4b6b: " + codingErrors + " coding errors encountered."); + // errorMessageBuilder.append("decode4b6b: " + codingErrors + " coding errors encountered."); + // + // response.errorData = errorMessageBuilder.toString(); + // } else { + // response.data = rval; + // } + // + // return response; + // } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/data/encoding/Encoding4b6bGo.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/data/encoding/Encoding4b6bGo.java new file mode 100644 index 0000000000..6609138011 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/data/encoding/Encoding4b6bGo.java @@ -0,0 +1,163 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.encoding; + +import java.util.HashMap; +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.RileyLinkCommunicationException; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RileyLinkBLEError; +import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; + +/** + * Created by andy on 11/24/18. + */ + +public class Encoding4b6bGo extends Encoding4b6bAbstract { + + public static final Logger LOG = LoggerFactory.getLogger(Encoding4b6bGo.class); + private static Map decodeGoMap; + + + public byte[] encode4b6b(byte[] src) { + // 2 input bytes produce 3 output bytes. + // Odd final input byte, if any, produces 2 output bytes. + int n = src.length; + byte[] dst = new byte[3 * (n / 2) + 2 * (n % 2)]; + int j = 0; + + for (int i = 0; i < n; i += 2, j = j + 3) { + short x = convertUnsigned(src[i]); + short a = encode4b6bList[hi(4, x)]; + short b = encode4b6bList[lo(4, x)]; + dst[j] = (byte)(a << 2 | hi(4, b)); + if (i + 1 < n) { + short y = convertUnsigned(src[i + 1]); + short c = encode4b6bList[hi(4, y)]; + short d = encode4b6bList[lo(4, y)]; + dst[j + 1] = (byte)(lo(4, b) << 4 | hi(6, c)); + dst[j + 2] = (byte)(lo(2, c) << 6 | d); + } else { + // Fill final nibble with 5 to match pump behavior. + dst[j + 1] = (byte)(lo(4, b) << 4 | 0x5); + } + + } + return dst; + } + + + /** + * Decode from Go code by ecc1. NOT WORKING + * + * @param src + * @return + */ + public byte[] decode4b6b(byte[] src) throws RileyLinkCommunicationException { + int n = src.length; + + if (decodeGoMap == null) + initDecodeGo(); + + StringBuilder errorMessageBuilder = new StringBuilder(); + + errorMessageBuilder.append("Input data: " + ByteUtil.getHex(src) + "\n"); + int codingErrors = 0; + + // Check for valid packet length. + if (n % 3 == 1) { + errorMessageBuilder.append("Invalid package length " + n); + codingErrors++; + // return nil, ErrDecoding + } + // 3 input bytes produce 2 output bytes. + // Final 2 input bytes, if any, produce 1 output byte. + byte[] dst = new byte[2 * (n / 3) + (n % 3) / 2]; + + int j = 0; + for (int i = 0; i < n; i = i + 3, j = j + 2) { + if (i + 1 >= n) { + errorMessageBuilder.append("Overflow in i (" + i + ")"); + } + short x = convertUnsigned(src[i]); + short y = convertUnsigned(src[i + 1]); + short a = decode6b_goMap(hi(6, x)); + short b = decode6b_goMap(lo(2, x) << 4 | hi(4, y)); + if (a == 0xFF || b == 0xFF) { + errorMessageBuilder.append("Error decoding "); + codingErrors++; + } + dst[j] = (byte)(a << 4 | b); + if (i + 2 < n) { + short z = convertUnsigned(src[i + 2]); + short c = decode6b_goMap(lo(4, y) << 2 | hi(2, z)); + short d = decode6b_goMap(lo(6, z)); + if (c == 0xFF || d == 0xFF) { + errorMessageBuilder.append("Error decoding "); + codingErrors++; + } + dst[j + 1] = (byte)(c << 4 | d); + } + } + + if (codingErrors > 0) { + errorMessageBuilder.append("decode4b6b: " + codingErrors + " coding errors encountered."); + writeError(LOG, dst, errorMessageBuilder.toString()); + throw new RileyLinkCommunicationException(RileyLinkBLEError.CodingErrors, errorMessageBuilder.toString()); + } + + return dst; + } + + + static short hi(int n, short x) { + // x = convertUnsigned(x); + return (short)(x >> (8 - n)); + } + + + static short lo(int n, short x) { + // byte b = (byte)x; + return (short)(x & ((1 << n) - 1)); + } + + + public static void initDecodeGo() { + + decodeGoMap = new HashMap<>(); + + putToMap(0x0B, 0x0B); + putToMap(0x0D, 0x0D); + putToMap(0x0E, 0x0E); + putToMap(0x15, 0x00); + putToMap(0x16, 0x07); + putToMap(0x19, 0x09); + putToMap(0x1A, 0x08); + putToMap(0x1C, 0x0F); + putToMap(0x23, 0x03); + putToMap(0x25, 0x05); + putToMap(0x26, 0x06); + putToMap(0x2A, 0x0A); + putToMap(0x2C, 0x0C); + putToMap(0x31, 0x01); + putToMap(0x32, 0x02); + putToMap(0x34, 0x04); + + } + + + private static short decode6b_goMap(int value) { + short val = (short)value; + if (decodeGoMap.containsKey(val)) + return decodeGoMap.get(val); + else + return (short)0xff; + } + + + private static void putToMap(int val1, int val2) { + decodeGoMap.put((short)val1, (short)val2); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/data/encoding/Encoding4b6bLoop.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/data/encoding/Encoding4b6bLoop.java new file mode 100644 index 0000000000..3e551b6ccf --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/data/encoding/Encoding4b6bLoop.java @@ -0,0 +1,136 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.encoding; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.RileyLinkCommunicationException; +import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; + +/** + * Created by andy on 11/24/18. + */ + +public class Encoding4b6bLoop extends Encoding4b6bAbstract { + + public static final Logger LOG = LoggerFactory.getLogger(Encoding4b6bLoop.class); + public Map codesRev = null; + + + public Encoding4b6bLoop() { + createCodeRev(); + } + + + /** + * This method is almost 1:1 with same method from Loop, only change is unsigning of element and |05 added for + * last byte. It should work better than original one, which is really different than this one. + * + * @param data + * @return + */ + public byte[] encode4b6b(byte[] data) { + + List buffer = new ArrayList(); + int bitAccumulator = 0x0; + int bitcount = 0; + + for (byte element : data) { + + short element2 = element; + + if (element2 < 0) { + element2 += 256; + } + + bitAccumulator <<= 6; + bitAccumulator |= encode4b6bList[element2 >> 4]; + bitcount += 6; + + bitAccumulator <<= 6; + bitAccumulator |= encode4b6bList[element2 & 0x0f]; + bitcount += 6; + + while (bitcount >= 8) { + buffer.add((byte)((bitAccumulator >> (bitcount - 8)) & 0xff)); + bitcount -= 8; + bitAccumulator &= (0xffff >> (16 - bitcount)); + } + } + + if (bitcount > 0) { + bitAccumulator <<= (8 - bitcount); + buffer.add((byte)((bitAccumulator | 0x5) & 0xff)); + } + + return ByteUtil.getByteArrayFromList(buffer); + } + + + /** + * DOESN'T WORK YET + * + * @param data + * @return + * @throws RileyLinkCommunicationException + */ + public byte[] decode4b6b(byte[] data) throws RileyLinkCommunicationException { + List buffer = new ArrayList(); + int availBits = 0; + int bitAccumulator = 0; + + for (byte element2 : data) { + + short element = convertUnsigned(element2); + + // if (element < 0) { + // element += 255; + // } + + if (element == 0) { + break; + } + + bitAccumulator = (bitAccumulator << 8) + element; + availBits += 8; + + if (availBits >= 12) { + + int hiNibble; + int loNibble; + + try { + int index = (bitAccumulator >> (availBits - 6)); + int index2 = ((bitAccumulator >> (availBits - 12)) & 0b111111); + hiNibble = codesRev.get((bitAccumulator >> (availBits - 6))); + loNibble = codesRev.get(((bitAccumulator >> (availBits - 12)) & 0b111111)); + } catch (Exception ex) { + System.out.println("Exception: " + ex.getMessage()); + ex.printStackTrace(); + return null; + } + + int decoded = ((hiNibble << 4) + loNibble); + buffer.add((byte)decoded); + availBits -= 12; + bitAccumulator = bitAccumulator & (0xffff >> (16 - availBits)); + } + } + + return ByteUtil.getByteArrayFromList(buffer); + } + + + private void createCodeRev() { + codesRev = new HashMap<>(); + + for (int i = 0; i < encode4b6bList.length; i++) { + codesRev.put(i, encode4b6bList[i]); + } + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/defs/CC111XRegister.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/defs/CC111XRegister.java new file mode 100644 index 0000000000..02694979d9 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/defs/CC111XRegister.java @@ -0,0 +1,48 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs; + +/** + * Created by andy on 21/05/2018. + */ + +public enum CC111XRegister { + + sync1(0x00), // + sync0(0x01), // + pktlen(0x02), // + pktctrl1(0x03), // + pktctrl0(0x04), // + fsctrl1(0x07), // + freq2(0x09), // + freq1(0x0a), // + freq0(0x0b), // + mdmcfg4(0x0c), // + mdmcfg3(0x0d), // + mdmcfg2(0x0e), // + mdmcfg1(0x0f), // + mdmcfg0(0x10), // + deviatn(0x11), // + mcsm0(0x14), // + foccfg(0x15), // + agcctrl2(0x17), // + agcctrl1(0x18), // + agcctrl0(0x19), // + frend1(0x1a), // + frend0(0x1b), // + fscal3(0x1c), // + fscal2(0x1d), // + fscal1(0x1e), // + fscal0(0x1f), // + test1(0x24), // + test0(0x25), // + paTable0(0x2e), // + + ; + + public byte value; + + + CC111XRegister(int value) { + this.value = (byte)value; + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/defs/RFSpyCommand.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/defs/RFSpyCommand.java new file mode 100644 index 0000000000..b2bbe81e9a --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/defs/RFSpyCommand.java @@ -0,0 +1,42 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs; + +/** + * Created by andy on 22/05/2018. + */ + +public enum RFSpyCommand { + + GetState(1), // + GetVersion(2, false), // + GetPacket(3), // aka Listen, receive + Send(4), // + SendAndListen(5), // + UpdateRegister(6), // + Reset(7), // + + ; + + public byte code; + private boolean encoded = true; + + + RFSpyCommand(int code) { + this.code = (byte)code; + } + + + RFSpyCommand(int code, boolean encoded) { + this.code = (byte)code; + this.encoded = encoded; + } + + + public boolean isEncoded() { + return encoded; + } + + + public void setEncoded(boolean encoded) { + this.encoded = encoded; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/defs/RFSpyRLResponse.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/defs/RFSpyRLResponse.java new file mode 100644 index 0000000000..d1435d470d --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/defs/RFSpyRLResponse.java @@ -0,0 +1,37 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs; + +public enum RFSpyRLResponse { + // 0xaa == timeout + // 0xbb == interrupted + // 0xcc == zero-data + // 0xdd == success + // 0x11 == invalidParam + // 0x22 == unknownCommand + + Invalid(0), // default, just fail + Timeout(0xAA), + Interrupted(0xBB), + ZeroData(0xCC), + Success(0xDD), + OldSuccess(0x01), + InvalidParam(0x11), + UnknownCommand(0x22), ; + + byte value; + + + RFSpyRLResponse(int value) { + this.value = (byte)value; + } + + + public static RFSpyRLResponse fromByte(byte input) { + for (RFSpyRLResponse type : values()) { + if (type.value == input) { + return type; + } + } + return null; + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/defs/RLMessageType.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/defs/RLMessageType.java new file mode 100644 index 0000000000..a55fa1db19 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/defs/RLMessageType.java @@ -0,0 +1,11 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs; + +/** + * Created by andy on 5/6/18. + */ + +public enum RLMessageType { + PowerOn, // for powering on the pump (wakeup) + ReadSimpleData, // for checking if pump is readable (for Medtronic we can use GetModel) + ; +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/defs/RXFilterMode.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/defs/RXFilterMode.java new file mode 100644 index 0000000000..e50929ebfe --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/defs/RXFilterMode.java @@ -0,0 +1,19 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs; + +/** + * Created by andy on 21/05/2018. + */ + +public enum RXFilterMode { + + Wide(0x50), // + Narrow(0x90) // + ; + + public byte value; + + + RXFilterMode(int value) { + this.value = (byte)value; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/defs/RileyLinkBLEError.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/defs/RileyLinkBLEError.java new file mode 100644 index 0000000000..8d32445718 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/defs/RileyLinkBLEError.java @@ -0,0 +1,25 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs; + +/** + * Created by andy on 11/24/18. + */ + +public enum RileyLinkBLEError { + CodingErrors("Coding Errors encountered during decode of RileyLink packet."), // + Timeout("Timeout"), // + Interrupted("Interrupted"), + TooShortOrNullResponse("Too short or null decoded response."); + + private String description; + + + RileyLinkBLEError(String description) { + + this.description = description; + } + + + public String getDescription() { + return description; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/defs/RileyLinkCommandType.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/defs/RileyLinkCommandType.java new file mode 100644 index 0000000000..e241f0a83a --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/defs/RileyLinkCommandType.java @@ -0,0 +1,30 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs; + +/** + * Created by andy on 22/05/2018. + */ + +public enum RileyLinkCommandType { + + GetState(1), // + GetVersion(2), // + GetPacket(3), // aka Listen, receive + Send(4), // + SendAndListen(5), // + UpdateRegister(6), // + Reset(7), // + Led(8), + ReadRegister(9), + SetModeRegisters(10), + SetHardwareEncoding(11), + SetPreamble(12), + ResetRadioConfig(13), + GetStatistics(14), ; + + public byte code; + + + RileyLinkCommandType(int code) { + this.code = (byte)code; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/defs/RileyLinkEncodingType.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/defs/RileyLinkEncodingType.java new file mode 100644 index 0000000000..5482e224e3 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/defs/RileyLinkEncodingType.java @@ -0,0 +1,52 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs; + +import java.util.HashMap; +import java.util.Map; + +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.MainApp; + +public enum RileyLinkEncodingType { + + None(0x00, null), // No encoding on RL + Manchester(0x01, null), // Manchester encoding on RL (for Omnipod) + FourByteSixByteRileyLink(0x02, R.string.key_medtronic_pump_encoding_4b6b_rileylink), // 4b6b encoding on RL (for Medtronic) + FourByteSixByteLocal(0x00, R.string.key_medtronic_pump_encoding_4b6b_local), // No encoding on RL, but 4b6b encoding in code + ; + + public byte value; + public Integer resourceId; + public String description; + + private static Map encodingTypeMap; + + static { + encodingTypeMap = new HashMap<>(); + + for (RileyLinkEncodingType encType : values()) { + if (encType.resourceId!=null) { + encodingTypeMap.put(MainApp.gs(encType.resourceId), encType); + } + } + } + + + RileyLinkEncodingType(int value) { + this.value = (byte)value; + } + + + RileyLinkEncodingType(int value, Integer resourceId) { + this.value = (byte)value; + this.resourceId = resourceId; + } + + public static RileyLinkEncodingType getByDescription(String description) { + if (encodingTypeMap.containsKey(description)) { + return encodingTypeMap.get(description); + } + + return RileyLinkEncodingType.FourByteSixByteLocal; + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/defs/RileyLinkFirmwareVersion.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/defs/RileyLinkFirmwareVersion.java new file mode 100644 index 0000000000..b6d0eab3cd --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/defs/RileyLinkFirmwareVersion.java @@ -0,0 +1,104 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs; + +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public enum RileyLinkFirmwareVersion { + + Version_0_0(0, 0, "0.0"), // just for defaulting + Version_0_9(0, 9, "0.9"), // + Version_1_0(1, 0, "1.0"), // + Version_2_0(2, 0, "2.0"), // + Version_2_2(2, 2, "2.2"), // + Version_3_0(3, 0, "3.0"), // + UnknownVersion(0, 0, "???"), // + Version1(Version_0_0, Version_0_9, Version_1_0), // + Version2(Version_2_0, Version_2_2), // + Version2AndHigher(Version_2_0, Version_2_2, Version_3_0), // + ; + + private static final String FIRMWARE_IDENTIFICATION_PREFIX = "subg_rfspy "; + private static final Pattern _version_pattern = Pattern.compile(FIRMWARE_IDENTIFICATION_PREFIX + + "([0-9]+)\\.([0-9]+)"); + static Map mapByVersion; + + static { + mapByVersion = new HashMap<>(); + for (RileyLinkFirmwareVersion version : values()) { + if (version.familyMembers == null) { + mapByVersion.put(version.versionKey, version); + } + } + } + + protected RileyLinkFirmwareVersion[] familyMembers; + private int major; + private int minor; + private String versionKey = ""; + + + RileyLinkFirmwareVersion(int major, int minor, String versionKey) { + this.major = major; + this.minor = minor; + this.versionKey = versionKey; + } + + + RileyLinkFirmwareVersion(RileyLinkFirmwareVersion... familyMembers) { + this.familyMembers = familyMembers; + } + + + public static boolean isSameVersion(RileyLinkFirmwareVersion versionWeCheck, RileyLinkFirmwareVersion versionSources) { + if (versionSources.familyMembers != null) { + for (RileyLinkFirmwareVersion vrs : versionSources.familyMembers) { + if (vrs == versionWeCheck) + return true; + } + } else { + return (versionWeCheck == versionSources); + } + return false; + } + + + public static RileyLinkFirmwareVersion getByVersionString(String versionString) { + if (versionString != null) { + Matcher m = _version_pattern.matcher(versionString); + if (m.find()) { + int major = Integer.parseInt(m.group(1)); + int minor = Integer.parseInt(m.group(2)); + String versionKey = major + "." + minor; + if (mapByVersion.containsKey(versionKey)) { + return mapByVersion.get(versionKey); + } else { + return defaultToLowestMajorVersion(major); // just in case there is new release that we don't cover + // example: 2.3 etc + } + } + } + + return RileyLinkFirmwareVersion.UnknownVersion; + } + + + private static RileyLinkFirmwareVersion defaultToLowestMajorVersion(int major) { + if (mapByVersion.containsKey(major + ".0")) { + return mapByVersion.get(major + ".0"); + } + return UnknownVersion; + } + + + public boolean isSameVersion(RileyLinkFirmwareVersion versionSources) { + return isSameVersion(this, versionSources); + } + + + @Override + public String toString() { + return FIRMWARE_IDENTIFICATION_PREFIX + versionKey; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/defs/RileyLinkTargetFrequency.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/defs/RileyLinkTargetFrequency.java new file mode 100644 index 0000000000..0d7f341584 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/defs/RileyLinkTargetFrequency.java @@ -0,0 +1,25 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs; + +/** + * Created by andy on 6/7/18. + */ + +public enum RileyLinkTargetFrequency { + + Medtronic_WorldWide(868.25, 868.3, 868.35, 868.4, 868.45, 868.5, 868.55, 868.6, 868.65), // + Medtronic_US(916.45, 916.5, 916.55, 916.6, 916.65, 916.7, 916.75, 916.8), // + Omnipod(433.91), // + ; + + double[] frequencies; + + + RileyLinkTargetFrequency(double... frequencies) { + this.frequencies = frequencies; + } + + + public double[] getScanFrequencies() { + return frequencies; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/operations/BLECommOperation.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/operations/BLECommOperation.java new file mode 100644 index 0000000000..81fe52f890 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/operations/BLECommOperation.java @@ -0,0 +1,38 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.operations; + +import java.util.UUID; +import java.util.concurrent.Semaphore; + +import android.bluetooth.BluetoothGatt; + +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.RileyLinkBLE; + +/** + * Created by geoff on 5/26/16. + */ +public abstract class BLECommOperation { + + public boolean timedOut = false; + public boolean interrupted = false; + protected byte[] value; + protected BluetoothGatt gatt; + protected Semaphore operationComplete = new Semaphore(0, true); + + + // This is to be run on the main thread + public abstract void execute(RileyLinkBLE comm); + + + public void gattOperationCompletionCallback(UUID uuid, byte[] value) { + } + + + public int getGattOperationTimeout_ms() { + return 22000; + } + + + public byte[] getValue() { + return value; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/operations/BLECommOperationResult.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/operations/BLECommOperationResult.java new file mode 100644 index 0000000000..06f1e4e94e --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/operations/BLECommOperationResult.java @@ -0,0 +1,16 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.operations; + +/** + * Created by geoff on 5/26/16. + */ +public class BLECommOperationResult { + + public static final int RESULT_NONE = 0; + public static final int RESULT_SUCCESS = 1; + public static final int RESULT_TIMEOUT = 2; + public static final int RESULT_BUSY = 3; + public static final int RESULT_INTERRUPTED = 4; + public static final int RESULT_NOT_CONFIGURED = 5; + public byte[] value; + public int resultCode; +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/operations/CharacteristicReadOperation.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/operations/CharacteristicReadOperation.java new file mode 100644 index 0000000000..6c12a8ef77 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/operations/CharacteristicReadOperation.java @@ -0,0 +1,71 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.operations; + +import java.util.UUID; +import java.util.concurrent.TimeUnit; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import android.bluetooth.BluetoothGatt; +import android.bluetooth.BluetoothGattCharacteristic; +import android.os.SystemClock; + +import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.RileyLinkBLE; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.GattAttributes; + +/** + * Created by geoff on 5/26/16. + */ +public class CharacteristicReadOperation extends BLECommOperation { + + private static final Logger LOG = LoggerFactory.getLogger(L.PUMPBTCOMM); + + private BluetoothGattCharacteristic characteristic; + + + public CharacteristicReadOperation(BluetoothGatt gatt, BluetoothGattCharacteristic chara) { + this.gatt = gatt; + this.characteristic = chara; + } + + + @Override + public void execute(RileyLinkBLE comm) { + gatt.readCharacteristic(characteristic); + // wait here for callback to notify us that value was read. + try { + boolean didAcquire = operationComplete.tryAcquire(getGattOperationTimeout_ms(), TimeUnit.MILLISECONDS); + if (didAcquire) { + SystemClock.sleep(1); // This is to allow the IBinder thread to exit before we continue, allowing easier + // understanding of the sequence of events. + // success + } else { + LOG.error("Timeout waiting for gatt write operation to complete"); + timedOut = true; + } + } catch (InterruptedException e) { + if (isLogEnabled()) + LOG.error("Interrupted while waiting for gatt write operation to complete"); + interrupted = true; + } + value = characteristic.getValue(); + } + + + @Override + public void gattOperationCompletionCallback(UUID uuid, byte[] value) { + super.gattOperationCompletionCallback(uuid, value); + if (!characteristic.getUuid().equals(uuid)) { + LOG.error(String.format( + "Completion callback: UUID does not match! out of sequence? Found: %s, should be %s", + GattAttributes.lookup(characteristic.getUuid()), GattAttributes.lookup(uuid))); + } + operationComplete.release(); + } + + private boolean isLogEnabled() { + return L.isEnabled(L.PUMPBTCOMM); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/operations/CharacteristicWriteOperation.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/operations/CharacteristicWriteOperation.java new file mode 100644 index 0000000000..488b03af27 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/operations/CharacteristicWriteOperation.java @@ -0,0 +1,74 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.operations; + +import java.util.UUID; +import java.util.concurrent.TimeUnit; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import android.bluetooth.BluetoothGatt; +import android.bluetooth.BluetoothGattCharacteristic; +import android.os.SystemClock; + +import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.RileyLinkBLE; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.GattAttributes; + +/** + * Created by geoff on 5/26/16. + */ +public class CharacteristicWriteOperation extends BLECommOperation { + + private static final Logger LOG = LoggerFactory.getLogger(L.PUMPBTCOMM); + + private BluetoothGattCharacteristic characteristic; + + + public CharacteristicWriteOperation(BluetoothGatt gatt, BluetoothGattCharacteristic chara, byte[] value) { + this.gatt = gatt; + this.characteristic = chara; + this.value = value; + } + + + @Override + public void execute(RileyLinkBLE comm) { + + characteristic.setValue(value); + gatt.writeCharacteristic(characteristic); + // wait here for callback to notify us that value was written. + try { + boolean didAcquire = operationComplete.tryAcquire(getGattOperationTimeout_ms(), TimeUnit.MILLISECONDS); + if (didAcquire) { + SystemClock.sleep(1); // This is to allow the IBinder thread to exit before we continue, allowing easier + // understanding of the sequence of events. + // success + } else { + LOG.error("Timeout waiting for gatt write operation to complete"); + timedOut = true; + } + } catch (InterruptedException e) { + LOG.error("Interrupted while waiting for gatt write operation to complete"); + interrupted = true; + } + + } + + + // This will be run on the IBinder thread + @Override + public void gattOperationCompletionCallback(UUID uuid, byte[] value) { + if (!characteristic.getUuid().equals(uuid)) { + LOG.error(String.format( + "Completion callback: UUID does not match! out of sequence? Found: %s, should be %s", + GattAttributes.lookup(characteristic.getUuid()), GattAttributes.lookup(uuid))); + } + operationComplete.release(); + } + + + private boolean isLogEnabled() { + return L.isEnabled(L.PUMPBTCOMM); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/operations/DescriptorWriteOperation.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/operations/DescriptorWriteOperation.java new file mode 100644 index 0000000000..9e631c1c7c --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/operations/DescriptorWriteOperation.java @@ -0,0 +1,59 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.operations; + +import java.util.UUID; +import java.util.concurrent.TimeUnit; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import android.bluetooth.BluetoothGatt; +import android.bluetooth.BluetoothGattDescriptor; +import android.os.SystemClock; + +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.RileyLinkBLE; + +/** + * Created by geoff on 5/26/16. + */ +public class DescriptorWriteOperation extends BLECommOperation { + + private static final Logger LOG = LoggerFactory.getLogger(DescriptorWriteOperation.class); + + private BluetoothGattDescriptor descr; + + + public DescriptorWriteOperation(BluetoothGatt gatt, BluetoothGattDescriptor descr, byte[] value) { + this.gatt = gatt; + this.descr = descr; + this.value = value; + } + + + @Override + public void gattOperationCompletionCallback(UUID uuid, byte[] value) { + super.gattOperationCompletionCallback(uuid, value); + operationComplete.release(); + } + + + @Override + public void execute(RileyLinkBLE comm) { + descr.setValue(value); + gatt.writeDescriptor(descr); + // wait here for callback to notify us that value was read. + try { + boolean didAcquire = operationComplete.tryAcquire(getGattOperationTimeout_ms(), TimeUnit.MILLISECONDS); + if (didAcquire) { + SystemClock.sleep(1); // This is to allow the IBinder thread to exit before we continue, allowing easier + // understanding of the sequence of events. + // success + } else { + LOG.error("Timeout waiting for descriptor write operation to complete"); + timedOut = true; + } + } catch (InterruptedException e) { + LOG.error("Interrupted while waiting for descriptor write operation to complete"); + interrupted = true; + } + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/data/BleAdvertisedData.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/data/BleAdvertisedData.java new file mode 100644 index 0000000000..8a2bbdfec7 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/data/BleAdvertisedData.java @@ -0,0 +1,35 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.data; + +import java.util.List; +import java.util.UUID; + +/** + * Created by andy on 9/10/18. + */ + +public class BleAdvertisedData { + + private List mUuids; + private String mName; + + + public BleAdvertisedData(List uuids, String name) { + mUuids = uuids; + mName = name; + } + + + public List getUuids() { + return mUuids; + } + + + public String getName() { + return mName; + } + + + public String toString() { + return "BleAdvertisedData [name=" + mName + ", UUIDs=" + mUuids + "]"; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/data/CommandValueDefinition.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/data/CommandValueDefinition.java new file mode 100644 index 0000000000..fceb0609aa --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/data/CommandValueDefinition.java @@ -0,0 +1,14 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.data; + +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.CommandValueDefinitionType; + +/** + * Created by andy on 4/5/19. + */ + +public class CommandValueDefinition { + + public CommandValueDefinitionType definitionType; + public String value; + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/data/RLHistoryItem.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/data/RLHistoryItem.java new file mode 100644 index 0000000000..a887fede5c --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/data/RLHistoryItem.java @@ -0,0 +1,115 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.data; + +import org.joda.time.LocalDateTime; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkError; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkServiceState; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkTargetDevice; +import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicCommandType; +import info.nightscout.androidaps.plugins.pump.medtronic.defs.PumpDeviceState; + +/** + * Created by andy on 5/19/18. + */ + +public class RLHistoryItem { + + private MedtronicCommandType medtronicCommandType; + private LocalDateTime dateTime; + private RLHistoryItemSource source; + private RileyLinkServiceState serviceState; + private RileyLinkError errorCode; + + private RileyLinkTargetDevice targetDevice; + private PumpDeviceState pumpDeviceState; + + + public RLHistoryItem(RileyLinkServiceState serviceState, RileyLinkError errorCode, + RileyLinkTargetDevice targetDevice) { + this.targetDevice = targetDevice; + this.dateTime = new LocalDateTime(); + this.serviceState = serviceState; + this.errorCode = errorCode; + this.source = RLHistoryItemSource.RileyLink; + } + + + public RLHistoryItem(PumpDeviceState pumpDeviceState, RileyLinkTargetDevice targetDevice) { + this.pumpDeviceState = pumpDeviceState; + this.dateTime = new LocalDateTime(); + this.targetDevice = targetDevice; + this.source = RLHistoryItemSource.MedtronicPump; + } + + + public RLHistoryItem(MedtronicCommandType medtronicCommandType) { + this.dateTime = new LocalDateTime(); + this.medtronicCommandType = medtronicCommandType; + source = RLHistoryItemSource.MedtronicCommand; + } + + + public LocalDateTime getDateTime() { + return dateTime; + } + + + public RileyLinkServiceState getServiceState() { + return serviceState; + } + + + public RileyLinkError getErrorCode() { + return errorCode; + } + + + public String getDescription() { + + // TODO extend when we have Omnipod + switch (this.source) { + case RileyLink: + return "State: " + MainApp.gs(serviceState.getResourceId(targetDevice)) + + (this.errorCode == null ? "" : ", Error Code: " + errorCode); + + case MedtronicPump: + return MainApp.gs(pumpDeviceState.getResourceId()); + + case MedtronicCommand: + return medtronicCommandType.name(); + + default: + return "Unknown Description"; + } + } + + + public RLHistoryItemSource getSource() { + return source; + } + + + public PumpDeviceState getPumpDeviceState() { + return pumpDeviceState; + } + + public enum RLHistoryItemSource { + RileyLink("RileyLink"), // + MedtronicPump("Medtronic"), // + MedtronicCommand("Medtronic"); + + private String desc; + + + RLHistoryItemSource(String desc) { + this.desc = desc; + } + + + public String getDesc() { + return desc; + } + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/defs/CommandValueDefinitionRLType.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/defs/CommandValueDefinitionRLType.java new file mode 100644 index 0000000000..5be3087b49 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/defs/CommandValueDefinitionRLType.java @@ -0,0 +1,32 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs; + +/** + * Created by andy on 4/5/19. + */ + +public enum CommandValueDefinitionRLType implements CommandValueDefinitionType { + Name, // + Firmware, // + SignalStrength, // + ConnectionState, // + Frequency, // + ; + + @Override + public String getName() { + return this.name(); + } + + + @Override + public String getDescription() { + return null; + } + + + @Override + public String commandAction() { + return null; + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/defs/CommandValueDefinitionType.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/defs/CommandValueDefinitionType.java new file mode 100644 index 0000000000..db5c5b2b91 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/defs/CommandValueDefinitionType.java @@ -0,0 +1,17 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs; + +/** + * Created by andy on 4/5/19. + */ + +public interface CommandValueDefinitionType { + + String getName(); + + + String getDescription(); + + + String commandAction(); + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/defs/RileyLinkError.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/defs/RileyLinkError.java new file mode 100644 index 0000000000..07867a781a --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/defs/RileyLinkError.java @@ -0,0 +1,52 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs; + +import info.nightscout.androidaps.R; + +/** + * Created by andy on 14/05/2018. + */ + +public enum RileyLinkError { + + // Configuration + + // BT + NoBluetoothAdapter(R.string.rileylink_error_no_bt_adapter), // + BluetoothDisabled(R.string.rileylink_error_bt_disabled), // + + // RileyLink + RileyLinkUnreachable(R.string.rileylink_error_unreachable), // + DeviceIsNotRileyLink(R.string.rileylink_error_not_rl), // + + // Device + TuneUpOfDeviceFailed(R.string.rileylink_error_tuneup_failed), // + NoContactWithDevice(R.string.rileylink_error_pump_unreachable, R.string.rileylink_error_pod_unreachable), // + ; + + int resourceId; + Integer resourceIdPod; + + + RileyLinkError(int resourceId) { + this.resourceId = resourceId; + } + + + RileyLinkError(int resourceId, int resourceIdPod) { + this.resourceId = resourceId; + this.resourceIdPod = resourceIdPod; + } + + + public int getResourceId(RileyLinkTargetDevice targetDevice) { + if (this.resourceIdPod != null) { + + return targetDevice == RileyLinkTargetDevice.MedtronicPump ? // + this.resourceId + : this.resourceIdPod; + } else { + return this.resourceId; + } + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/defs/RileyLinkServiceState.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/defs/RileyLinkServiceState.java new file mode 100644 index 0000000000..2ae66b53c9 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/defs/RileyLinkServiceState.java @@ -0,0 +1,95 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs; + +import info.nightscout.androidaps.R; + +/** + * Created by andy on 14/05/2018. + */ + +public enum RileyLinkServiceState { + + NotStarted(R.string.rileylink_state_not_started), // + + // Bluetooth + BluetoothInitializing(R.string.rileylink_state_bt_init), // (S) init BT (if error no BT interface -> Disabled, BT + // not enabled -> BluetoothError) + // BluetoothNotAvailable, // (E) BT not available, would happen only if device has no BT + BluetoothError(R.string.rileylink_state_bt_error), // (E) if BT gets disabled ( -> EnableBluetooth) + BluetoothReady(R.string.rileylink_state_bt_ready), // (OK) + + // RileyLink + RileyLinkInitializing(R.string.rileylink_state_rl_init), // (S) start Gatt discovery (OK -> RileyLinkReady, Error -> + // BluetoothEnabled) ?? + RileyLinkError(R.string.rileylink_state_rl_error), // (E) + RileyLinkReady(R.string.rileylink_state_connected), // (OK) if tunning was already done we go to PumpConnectorReady + + // Tunning + TuneUpDevice(R.string.rileylink_state_pc_tune_up), // (S) + PumpConnectorError(R.string.rileylink_state_pc_error), // either TuneUp Error or pump couldn't not be contacted + // error + PumpConnectorReady(R.string.rileylink_state_connected), // (OK) RileyLink Ready for Pump Communication + + // Initializing, // get all parameters required for connection (if not possible -> Disabled, if sucessful -> + // EnableBluetooth) + + // EnableBlueTooth, // enable BT (if error no BT interface -> Disabled, BT not enabled -> BluetoothError) + // BlueToothEnabled, // -> InitializeRileyLink + // RileyLinkInitialized, // + + // RileyLinkConnected, // -> TuneUpPump (on 1st), else PumpConnectorReady + + // PumpConnected, // + + ; + + int resourceId; + Integer resourceIdPod; + + + RileyLinkServiceState(int resourceId) { + this.resourceId = resourceId; + } + + + RileyLinkServiceState(int resourceId, int resourceIdPod) { + this.resourceId = resourceId; + this.resourceIdPod = resourceIdPod; + } + + + public static boolean isReady(RileyLinkServiceState serviceState) { + return (/* serviceState == RileyLinkReady || */serviceState == PumpConnectorReady); + } + + + public int getResourceId(RileyLinkTargetDevice targetDevice) { + if (this.resourceIdPod != null) { + + return (targetDevice == null || targetDevice == RileyLinkTargetDevice.MedtronicPump) ? // + this.resourceId + : this.resourceIdPod; + } else { + return this.resourceId; + } + } + + + public boolean isConnecting() { + + return (this == RileyLinkServiceState.BluetoothInitializing || // + // this == RileyLinkServiceState.BluetoothError || // + this == RileyLinkServiceState.BluetoothReady || // + this == RileyLinkServiceState.RileyLinkInitializing || // + this == RileyLinkReady + // this == RileyLinkServiceState.RileyLinkBLEError + ); + } + + + public boolean isError() { + + return (this == RileyLinkServiceState.BluetoothError || // + // this == RileyLinkServiceState.PumpConnectorError || // + this == RileyLinkServiceState.RileyLinkError); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/defs/RileyLinkTargetDevice.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/defs/RileyLinkTargetDevice.java new file mode 100644 index 0000000000..2d0dea69f7 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/defs/RileyLinkTargetDevice.java @@ -0,0 +1,32 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs; + +import info.nightscout.androidaps.R; + +/** + * Created by andy on 5/19/18. + */ + +public enum RileyLinkTargetDevice { + MedtronicPump(R.string.rileylink_target_device_medtronic, true), // + Omnipod(R.string.rileylink_target_device_omnipod, false), // + ; + + private int resourceId; + private boolean tuneUpEnabled; + + + RileyLinkTargetDevice(int resourceId, boolean tuneUpEnabled) { + this.resourceId = resourceId; + this.tuneUpEnabled = tuneUpEnabled; + } + + + public boolean isTuneUpEnabled() { + return tuneUpEnabled; + } + + + public int getResourceId() { + return resourceId; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/dialog/RileyLinkStatusActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/dialog/RileyLinkStatusActivity.java new file mode 100644 index 0000000000..37a6656a6e --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/dialog/RileyLinkStatusActivity.java @@ -0,0 +1,161 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.dialog; + +import android.os.Bundle; +import android.widget.TextView; + +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentPagerAdapter; +import androidx.viewpager.widget.ViewPager; + +import com.google.android.material.floatingactionbutton.FloatingActionButton; +import com.google.android.material.tabs.TabLayout; + +import java.util.ArrayList; +import java.util.List; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.activities.NoSplashAppCompatActivity; +import info.nightscout.androidaps.plugins.pump.common.dialog.RefreshableInterface; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.RileyLinkServiceData; + +public class RileyLinkStatusActivity extends NoSplashAppCompatActivity { + + TextView connectionStatus; + TextView configuredAddress; + TextView connectedDevice; + TextView connectionError; + RileyLinkServiceData rileyLinkServiceData; + + private SectionsPagerAdapter mSectionsPagerAdapter; + private FloatingActionButton floatingActionButton; + private TabLayout tabLayout; + /** + * The {@link ViewPager} that will host the section contents. + */ + private ViewPager mViewPager; + + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.rileylink_status); + + // Create the adapter that will return a fragment for each of the three + // primary sections of the activity. + + // Set up the ViewPager with the sections adapter. + mViewPager = (ViewPager) findViewById(R.id.rileylink_settings_container); + // mViewPager.setAdapter(mSectionsPagerAdapter); + setupViewPager(mViewPager); + + tabLayout = (TabLayout) findViewById(R.id.rileylink_settings_tabs); + tabLayout.setupWithViewPager(mViewPager); + + floatingActionButton = (FloatingActionButton) findViewById(R.id.rileylink_settings_fab); + floatingActionButton.setOnClickListener(v -> { + + RefreshableInterface selectableInterface = (RefreshableInterface) mSectionsPagerAdapter + .getItem(tabLayout.getSelectedTabPosition()); + selectableInterface.refreshData(); + + // refreshData(tabLayout.getSelectedTabPosition()); + + // Toast.makeText(getApplicationContext(), "Test pos: " + tabLayout.getSelectedTabPosition(), + // Toast.LENGTH_LONG); + }); + + this.connectionStatus = findViewById(R.id.rls_t1_connection_status); + this.configuredAddress = findViewById(R.id.rls_t1_configured_address); + this.connectedDevice = findViewById(R.id.rls_t1_connected_device); + this.connectionError = findViewById(R.id.rls_t1_connection_error); + + rileyLinkServiceData = RileyLinkUtil.getRileyLinkServiceData(); + + // // 7-12 + // int[] ids = {R.id.rls_t1_tv02, R.id.rls_t1_tv03, R.id.rls_t1_tv04, R.id.rls_t1_tv05, R.id.rls_t1_tv07, // + // R.id.rls_t1_tv08, R.id.rls_t1_tv09, R.id.rls_t1_tv10, R.id.rls_t1_tv11, R.id.rls_t1_tv12}; + // + // for (int id : ids) { + // + // TextView tv = (TextView) findViewById(id); + // tv.setText(tv.getText() + ":"); + // } + + // refreshData(0); + // refreshData(1); + + } + + + public void refreshData(int position) { + if (position == 0) { + // FIXME i18n + this.connectionStatus.setText(rileyLinkServiceData.serviceState.name()); + this.configuredAddress.setText(rileyLinkServiceData.rileylinkAddress); + // FIXME + this.connectedDevice.setText("???"); + // FIXME i18n + this.connectionError.setText(rileyLinkServiceData.errorCode.name()); + } else { + + } + + } + + + public void setupViewPager(ViewPager pager) { + + mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager()); + + mSectionsPagerAdapter.addFragment(new RileyLinkStatusGeneral(), MainApp.gs(R.string.rileylink_settings_tab1)); + mSectionsPagerAdapter.addFragment(new RileyLinkStatusHistory(), MainApp.gs(R.string.rileylink_settings_tab2)); + //mSectionsPagerAdapter.addFragment(new RileyLinkStatusDevice(), "Medtronic"); + + mViewPager.setAdapter(mSectionsPagerAdapter); + } + + /** + * A {@link FragmentPagerAdapter} that returns a fragment corresponding to + * one of the sections/tabs/pages. + */ + public class SectionsPagerAdapter extends FragmentPagerAdapter { + + List fragmentList = new ArrayList<>(); + List fragmentTitle = new ArrayList<>(); + int lastSelectedPosition = 0; + + + public SectionsPagerAdapter(FragmentManager fm) { + super(fm); + } + + + @Override + public Fragment getItem(int position) { + this.lastSelectedPosition = position; + return fragmentList.get(position); + } + + + @Override + public int getCount() { + // Show 3 total pages. + return fragmentList.size(); + } + + + public void addFragment(Fragment fragment, String title) { + this.fragmentList.add(fragment); + this.fragmentTitle.add(title); + } + + + @Override + public CharSequence getPageTitle(int position) { + return fragmentTitle.get(position); + } + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/dialog/RileyLinkStatusDevice.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/dialog/RileyLinkStatusDevice.java new file mode 100644 index 0000000000..226d7fc622 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/dialog/RileyLinkStatusDevice.java @@ -0,0 +1,154 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.dialog; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import android.os.Bundle; +import androidx.fragment.app.Fragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.Button; +import android.widget.ListView; +import android.widget.TextView; + +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.plugins.pump.common.dialog.RefreshableInterface; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.data.CommandValueDefinition; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.CommandValueDefinitionType; +//import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.data.CommandValueDefinition; +//import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.data.RLHistoryItem; +//import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.CommandValueDefinitionType; +//import info.nightscout.androidaps.plugins.pump.common.utils.StringUtil; + +/** + * Created by andy on 5/19/18. + */ + +// FIXME needs to be implemented + +public class RileyLinkStatusDevice extends Fragment implements RefreshableInterface { + + ListView listView; + + RileyLinkCommandListAdapter adapter; + + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View rootView = inflater.inflate(R.layout.rileylink_status_device, container, false); + + adapter = new RileyLinkCommandListAdapter(); + + return rootView; + } + + + @Override + public void onStart() { + super.onStart(); + + this.listView = (ListView)getActivity().findViewById(R.id.rileyLinkDeviceList); + + listView.setAdapter(adapter); + + setElements(); + } + + + private void setElements() { + + } + + + @Override + public void refreshData() { + // adapter.addItemsAndClean(RileyLinkUtil.getRileyLinkHistory()); + } + + static class ViewHolder { + + TextView itemDescription; + Button itemValue; + } + + private class RileyLinkCommandListAdapter extends BaseAdapter { + + private List commandValueList; + private Map commandValueMap; + private LayoutInflater mInflator; + + + public RileyLinkCommandListAdapter() { + super(); + commandValueList = new ArrayList<>(); + mInflator = RileyLinkStatusDevice.this.getLayoutInflater(); + } + + + public void addItems(List list) { + commandValueList.addAll(list); + + for (CommandValueDefinition commandValueDefinition : list) { + commandValueMap.put(commandValueDefinition.definitionType, commandValueDefinition); + } + + notifyDataSetChanged(); + } + + + public CommandValueDefinition getCommandValueItem(int position) { + return commandValueList.get(position); + } + + + public void clear() { + commandValueList.clear(); + notifyDataSetChanged(); + } + + + @Override + public int getCount() { + return commandValueList.size(); + } + + + @Override + public Object getItem(int i) { + return commandValueList.get(i); + } + + + @Override + public long getItemId(int i) { + return i; + } + + + @Override + public View getView(int i, View view, ViewGroup viewGroup) { + RileyLinkStatusDevice.ViewHolder viewHolder; + // General ListView optimization code. + if (view == null) { + view = mInflator.inflate(R.layout.rileylink_status_device_item, null); + viewHolder = new RileyLinkStatusDevice.ViewHolder(); + viewHolder.itemDescription = (TextView)view.findViewById(R.id.rileylink_device_label); + viewHolder.itemValue = (Button)view.findViewById(R.id.rileylink_device_action); + view.setTag(viewHolder); + } else { + viewHolder = (RileyLinkStatusDevice.ViewHolder)view.getTag(); + } + // Z + // RLHistoryItem item = historyItemList.get(i); + // viewHolder.itemTime.setText(StringUtil.toDateTimeString(item.getDateTime())); + // viewHolder.itemSource.setText("Riley Link"); // for now + // viewHolder.itemDescription.setText(item.getDescription()); + + return view; + } + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/dialog/RileyLinkStatusGeneral.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/dialog/RileyLinkStatusGeneral.java new file mode 100644 index 0000000000..021d1ee068 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/dialog/RileyLinkStatusGeneral.java @@ -0,0 +1,150 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.dialog; + +import android.os.Bundle; +import androidx.fragment.app.Fragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import org.joda.time.LocalDateTime; + +import java.util.Locale; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.plugins.pump.common.dialog.RefreshableInterface; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RileyLinkFirmwareVersion; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkServiceState; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkTargetDevice; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.RileyLinkServiceData; +import info.nightscout.androidaps.plugins.pump.common.utils.StringUtil; +import info.nightscout.androidaps.plugins.pump.medtronic.driver.MedtronicPumpStatus; +import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil; + +/** + * Created by andy on 5/19/18. + */ + +public class RileyLinkStatusGeneral extends Fragment implements RefreshableInterface { + + TextView connectionStatus; + TextView configuredAddress; + TextView connectedDevice; + TextView connectionError; + TextView deviceType; + TextView deviceModel; + TextView serialNumber; + TextView pumpFrequency; + TextView lastUsedFrequency; + TextView lastDeviceContact; + TextView firmwareVersion; + + RileyLinkServiceData rileyLinkServiceData; + + MedtronicPumpStatus medtronicPumpStatus; + boolean first = false; + + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View rootView = inflater.inflate(R.layout.rileylink_status_general, container, false); + + return rootView; + } + + + @Override + public void onStart() { + super.onStart(); + rileyLinkServiceData = RileyLinkUtil.getRileyLinkServiceData(); + + this.connectionStatus = getActivity().findViewById(R.id.rls_t1_connection_status); + this.configuredAddress = getActivity().findViewById(R.id.rls_t1_configured_address); + this.connectedDevice = getActivity().findViewById(R.id.rls_t1_connected_device); + this.connectionError = getActivity().findViewById(R.id.rls_t1_connection_error); + this.deviceType = getActivity().findViewById(R.id.rls_t1_device_type); + this.deviceModel = getActivity().findViewById(R.id.rls_t1_device_model); + this.serialNumber = getActivity().findViewById(R.id.rls_t1_serial_number); + this.pumpFrequency = getActivity().findViewById(R.id.rls_t1_pump_frequency); + this.lastUsedFrequency = getActivity().findViewById(R.id.rls_t1_last_used_frequency); + this.lastDeviceContact = getActivity().findViewById(R.id.rls_t1_last_device_contact); + this.firmwareVersion = getActivity().findViewById(R.id.rls_t1_firmware_version); + + if (!first) { + + // 7-12 + int[] ids = {R.id.rls_t1_tv02, R.id.rls_t1_tv03, R.id.rls_t1_tv04, R.id.rls_t1_tv05, R.id.rls_t1_tv07, // + R.id.rls_t1_tv08, R.id.rls_t1_tv09, R.id.rls_t1_tv10, R.id.rls_t1_tv11, R.id.rls_t1_tv12, R.id.rls_t1_tv13}; + + for (int id : ids) { + + TextView tv = (TextView) getActivity().findViewById(id); + tv.setText(tv.getText() + ":"); + } + + first = true; + } + + refreshData(); + } + + + public void refreshData() { + + RileyLinkTargetDevice targetDevice = RileyLinkUtil.getTargetDevice(); + + if (RileyLinkUtil.getServiceState()==null) + this.connectionStatus.setText(MainApp.gs(RileyLinkServiceState.NotStarted.getResourceId(targetDevice))); + else + this.connectionStatus.setText(MainApp.gs(RileyLinkUtil.getServiceState().getResourceId(targetDevice))); + + if (rileyLinkServiceData != null) { + this.configuredAddress.setText(rileyLinkServiceData.rileylinkAddress); + this.connectionError.setText(rileyLinkServiceData.errorCode == null ? // + "-" + : MainApp.gs(rileyLinkServiceData.errorCode.getResourceId(targetDevice))); + + + RileyLinkFirmwareVersion firmwareVersion = rileyLinkServiceData.versionCC110; + + if (firmwareVersion==null) { + this.firmwareVersion.setText("BLE113: -\nCC110: -"); + } else { + this.firmwareVersion.setText("BLE113: " + rileyLinkServiceData.versionBLE113 + // + "\nCC110: " + firmwareVersion.toString()); + } + + } + + // TODO add handling for Omnipod pump status + this.medtronicPumpStatus = MedtronicUtil.getPumpStatus(); + + if (medtronicPumpStatus != null) { + this.deviceType.setText(MainApp.gs(RileyLinkTargetDevice.MedtronicPump.getResourceId())); + this.deviceModel.setText(medtronicPumpStatus.pumpType.getDescription()); + this.serialNumber.setText(medtronicPumpStatus.serialNumber); + this.pumpFrequency.setText(MainApp.gs(medtronicPumpStatus.pumpFrequency.equals("medtronic_pump_frequency_us_ca") ? R.string.medtronic_pump_frequency_us_ca : R.string.medtronic_pump_frequency_worldwide)); + + // TODO extend when Omnipod used + + if (MedtronicUtil.getMedtronicPumpModel() != null) + this.connectedDevice.setText("Medtronic " + MedtronicUtil.getMedtronicPumpModel().getPumpModel()); + else + this.connectedDevice.setText("???"); + + if (rileyLinkServiceData.lastGoodFrequency != null) + this.lastUsedFrequency.setText(String.format(Locale.ENGLISH, "%.2f MHz", + rileyLinkServiceData.lastGoodFrequency)); + + if (medtronicPumpStatus.lastConnection != 0) + this.lastDeviceContact.setText(StringUtil.toDateTimeString(new LocalDateTime( + medtronicPumpStatus.lastDataTime))); + else + this.lastDeviceContact.setText("Never"); + } + + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/dialog/RileyLinkStatusHistory.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/dialog/RileyLinkStatusHistory.java new file mode 100644 index 0000000000..d6af799550 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/dialog/RileyLinkStatusHistory.java @@ -0,0 +1,161 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.dialog; + +import java.util.ArrayList; +import java.util.List; + +import android.os.Bundle; +import androidx.fragment.app.Fragment; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.plugins.pump.common.dialog.RefreshableInterface; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.data.RLHistoryItem; +import info.nightscout.androidaps.plugins.pump.common.utils.StringUtil; +import info.nightscout.androidaps.plugins.pump.medtronic.defs.PumpDeviceState; + +/** + * Created by andy on 5/19/18. + */ + +public class RileyLinkStatusHistory extends Fragment implements RefreshableInterface { + + RecyclerView recyclerView; + RecyclerViewAdapter recyclerViewAdapter; + + LinearLayoutManager llm; + List filteredHistoryList = new ArrayList<>(); + + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View rootView = inflater.inflate(R.layout.rileylink_status_history, container, false); + + recyclerView = (RecyclerView)rootView.findViewById(R.id.rileylink_history_list); + + recyclerView.setHasFixedSize(true); + llm = new LinearLayoutManager(getActivity().getApplicationContext()); + recyclerView.setLayoutManager(llm); + + recyclerViewAdapter = new RecyclerViewAdapter(filteredHistoryList); + recyclerView.setAdapter(recyclerViewAdapter); + + return rootView; + } + + + @Override + public void onStart() { + super.onStart(); + + refreshData(); + } + + + @Override + public void refreshData() { + if (RileyLinkUtil.getRileyLinkHistory()!=null) { + recyclerViewAdapter.addItemsAndClean(RileyLinkUtil.getRileyLinkHistory()); + } + } + + + public static class RecyclerViewAdapter extends RecyclerView.Adapter { + + List historyList; + + + RecyclerViewAdapter(List historyList) { + this.historyList = historyList; + } + + + public void setHistoryList(List historyList) { + this.historyList = historyList; + } + + + public void addItemsAndClean(List items) { + this.historyList.clear(); + + for (RLHistoryItem item : items) { + + if (!historyList.contains(item) && isValidItem(item)) { + historyList.add(item); + } + } + + notifyDataSetChanged(); + } + + + private boolean isValidItem(RLHistoryItem item) { + + PumpDeviceState pumpState = item.getPumpDeviceState(); + + if ((pumpState != null) && // + (pumpState == PumpDeviceState.Sleeping || // + pumpState == PumpDeviceState.Active || // + pumpState == PumpDeviceState.WakingUp // + )) + return false; + + return true; + + } + + + @Override + public RecyclerViewAdapter.HistoryViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { + View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.rileylink_status_history_item, // + viewGroup, false); + return new RecyclerViewAdapter.HistoryViewHolder(v); + } + + + @Override + public void onBindViewHolder(RecyclerViewAdapter.HistoryViewHolder holder, int position) { + RLHistoryItem item = historyList.get(position); + + if (item != null) { + holder.timeView.setText(StringUtil.toDateTimeString(item.getDateTime())); + holder.typeView.setText(item.getSource().getDesc()); + holder.valueView.setText(item.getDescription()); + } + } + + + @Override + public int getItemCount() { + return historyList.size(); + } + + + @Override + public void onAttachedToRecyclerView(RecyclerView recyclerView) { + super.onAttachedToRecyclerView(recyclerView); + } + + static class HistoryViewHolder extends RecyclerView.ViewHolder { + + TextView timeView; + TextView typeView; + TextView valueView; + + + HistoryViewHolder(View itemView) { + super(itemView); + + timeView = (TextView)itemView.findViewById(R.id.rileylink_history_time); + typeView = (TextView)itemView.findViewById(R.id.rileylink_history_source); + valueView = (TextView)itemView.findViewById(R.id.rileylink_history_description); + } + } + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/RileyLinkBluetoothStateReceiver.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/RileyLinkBluetoothStateReceiver.java new file mode 100644 index 0000000000..78b7def1af --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/RileyLinkBluetoothStateReceiver.java @@ -0,0 +1,58 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service; + +import android.bluetooth.BluetoothAdapter; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.interfaces.PumpInterface; +import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkConst; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil; + +public class RileyLinkBluetoothStateReceiver extends BroadcastReceiver { + + private static Logger LOG = LoggerFactory.getLogger(L.PUMP); + + @Override + public void onReceive(Context context, Intent intent) { + final String action = intent.getAction(); + + PumpInterface activePump = ConfigBuilderPlugin.getPlugin().getActivePump(); + + if (action != null && activePump != null) { + + final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR); + switch (state) { + case BluetoothAdapter.STATE_OFF: + case BluetoothAdapter.STATE_TURNING_OFF: + case BluetoothAdapter.STATE_TURNING_ON: + break; + + case BluetoothAdapter.STATE_ON: { + LOG.debug("RileyLinkBluetoothStateReceiver: Bluetooth back on. Sending broadcast to RileyLink Framework"); + RileyLinkUtil.sendBroadcastMessage(RileyLinkConst.Intents.BluetoothReconnected); + } + break; + } + } + } + + + public void unregisterBroadcasts() { + MainApp.instance().unregisterReceiver(this); + } + + + public void registerBroadcasts() { + IntentFilter filter = new IntentFilter(); + filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); + MainApp.instance().registerReceiver(this, filter); + } +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/RileyLinkBroadcastReceiver.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/RileyLinkBroadcastReceiver.java new file mode 100644 index 0000000000..d8a897955e --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/RileyLinkBroadcastReceiver.java @@ -0,0 +1,260 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service; + +/** + * Created by andy on 10/23/18. + */ + +import android.bluetooth.BluetoothAdapter; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import androidx.localbroadcastmanager.content.LocalBroadcastManager; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkConst; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RileyLinkFirmwareVersion; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkError; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkServiceState; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.DiscoverGattServicesTask; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.InitializePumpManagerTask; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.ServiceTask; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.ServiceTaskExecutor; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.WakeAndTuneTask; +import info.nightscout.androidaps.utils.SP; + +/** + * I added this class outside of RileyLinkService, because for now it's very important part of RL framework and + * where we get a lot of problems. Especially merging between AAPS and RileyLinkAAPS. I might put it back at + * later time + */ +public class RileyLinkBroadcastReceiver extends BroadcastReceiver { + + private static final Logger LOG = LoggerFactory.getLogger(L.PUMPCOMM); + + RileyLinkService serviceInstance; + protected Map> broadcastIdentifiers = null; + String deviceSpecificPrefix; + Context context; + + + public RileyLinkBroadcastReceiver(RileyLinkService serviceInstance, Context context) { + this.serviceInstance = serviceInstance; + this.context = context; + + createBroadcastIdentifiers(); + } + + + private void createBroadcastIdentifiers() { + + this.broadcastIdentifiers = new HashMap<>(); + + // Bluetooth + this.broadcastIdentifiers.put("Bluetooth", Arrays.asList( // + RileyLinkConst.Intents.BluetoothConnected, // + RileyLinkConst.Intents.BluetoothReconnected)); + + // TuneUp + this.broadcastIdentifiers.put("TuneUp", Arrays.asList( // + RileyLinkConst.IPC.MSG_PUMP_tunePump, // + RileyLinkConst.IPC.MSG_PUMP_quickTune)); + + // RileyLink + this.broadcastIdentifiers.put("RileyLink", Arrays.asList( // + RileyLinkConst.Intents.RileyLinkDisconnected, // + RileyLinkConst.Intents.RileyLinkReady, // + RileyLinkConst.Intents.RileyLinkDisconnected, // + RileyLinkConst.Intents.RileyLinkNewAddressSet, // + RileyLinkConst.Intents.RileyLinkDisconnect)); + + // Device Specific + deviceSpecificPrefix = serviceInstance.getDeviceSpecificBroadcastsIdentifierPrefix(); + + // Application specific + + } + + + @Override + public void onReceive(Context context, Intent intent) { + + if (intent == null) { + LOG.error("onReceive: received null intent"); + } else { + String action = intent.getAction(); + if (action == null) { + LOG.error("onReceive: null action"); + } else { + if (isLoggingEnabled()) + LOG.debug("Received Broadcast: " + action); + + if (!processBluetoothBroadcasts(action) && // + !processRileyLinkBroadcasts(action) && // + !processTuneUpBroadcasts(action) && // + !processDeviceSpecificBroadcasts(action, intent) && // + !processApplicationSpecificBroadcasts(action, intent) // + ) { + LOG.error("Unhandled broadcast: action=" + action); + } + } + } + } + + + public void registerBroadcasts() { + + IntentFilter intentFilter = new IntentFilter(); + + for (Map.Entry> stringListEntry : broadcastIdentifiers.entrySet()) { + + for (String intentKey : stringListEntry.getValue()) { + intentFilter.addAction(intentKey); + } + } + + if (deviceSpecificPrefix != null) { + serviceInstance.registerDeviceSpecificBroadcasts(intentFilter); + } + + LocalBroadcastManager.getInstance(context).registerReceiver(this, intentFilter); + } + + + private boolean processRileyLinkBroadcasts(String action) { + + if (action.equals(RileyLinkConst.Intents.RileyLinkDisconnected)) { + if (BluetoothAdapter.getDefaultAdapter().isEnabled()) { + RileyLinkUtil + .setServiceState(RileyLinkServiceState.BluetoothError, RileyLinkError.RileyLinkUnreachable); + } else { + RileyLinkUtil.setServiceState(RileyLinkServiceState.BluetoothError, RileyLinkError.BluetoothDisabled); + } + + return true; + } else if (action.equals(RileyLinkConst.Intents.RileyLinkReady)) { + + if (isLoggingEnabled()) + LOG.warn("MedtronicConst.Intents.RileyLinkReady"); + // sendIPCNotification(RT2Const.IPC.MSG_note_WakingPump); + + if (this.serviceInstance.rileyLinkBLE == null) + return false; + + this.serviceInstance.rileyLinkBLE.enableNotifications(); + this.serviceInstance.rfspy.startReader(); // call startReader from outside? + + this.serviceInstance.rfspy.initializeRileyLink(); + String bleVersion = this.serviceInstance.rfspy.getBLEVersionCached(); + RileyLinkFirmwareVersion rlVersion = this.serviceInstance.rfspy.getRLVersionCached(); + +// if (isLoggingEnabled()) + LOG.debug("RfSpy version (BLE113): " + bleVersion); + this.serviceInstance.rileyLinkServiceData.versionBLE113 = bleVersion; + +// if (isLoggingEnabled()) + LOG.debug("RfSpy Radio version (CC110): " + rlVersion.name()); + this.serviceInstance.rileyLinkServiceData.versionCC110 = rlVersion; + + ServiceTask task = new InitializePumpManagerTask(RileyLinkUtil.getTargetDevice()); + ServiceTaskExecutor.startTask(task); + if (isLoggingEnabled()) + LOG.info("Announcing RileyLink open For business"); + + return true; + } else if (action.equals(RileyLinkConst.Intents.RileyLinkNewAddressSet)) { + String RileylinkBLEAddress = SP.getString(RileyLinkConst.Prefs.RileyLinkAddress, ""); + if (RileylinkBLEAddress.equals("")) { + LOG.error("No Rileylink BLE Address saved in app"); + } else { + // showBusy("Configuring Service", 50); + // rileyLinkBLE.findRileyLink(RileylinkBLEAddress); + this.serviceInstance.reconfigureRileyLink(RileylinkBLEAddress); + // MainApp.getServiceClientConnection().setThisRileylink(RileylinkBLEAddress); + } + + return true; + } else if (action.equals(RileyLinkConst.Intents.RileyLinkDisconnect)) { + this.serviceInstance.disconnectRileyLink(); + + return true; + } else { + return false; + } + + } + + + public boolean processBluetoothBroadcasts(String action) { + + if (action.equals(RileyLinkConst.Intents.BluetoothConnected)) { + if (isLoggingEnabled()) + LOG.debug("Bluetooth - Connected"); + ServiceTaskExecutor.startTask(new DiscoverGattServicesTask()); + + return true; + + } else if (action.equals(RileyLinkConst.Intents.BluetoothReconnected)) { + if (isLoggingEnabled()) + LOG.debug("Bluetooth - Reconnecting"); + + serviceInstance.bluetoothInit(); + ServiceTaskExecutor.startTask(new DiscoverGattServicesTask(true)); + + return true; + } else { + + return false; + } + + } + + + private boolean processTuneUpBroadcasts(String action) { + + if (this.broadcastIdentifiers.get("TuneUp").contains(action)) { + if (serviceInstance.getRileyLinkTargetDevice().isTuneUpEnabled()) { + ServiceTaskExecutor.startTask(new WakeAndTuneTask()); + } + return true; + } else { + return false; + } + } + + + public boolean processDeviceSpecificBroadcasts(String action, Intent intent) { + + if (this.deviceSpecificPrefix == null) { + return false; + } + + if (action.startsWith(this.deviceSpecificPrefix)) { + return this.serviceInstance.handleDeviceSpecificBroadcasts(intent); + } else + return false; + } + + + public boolean processApplicationSpecificBroadcasts(String action, Intent intent) { + return false; + } + + + public boolean isLoggingEnabled() { + return (L.isEnabled(L.PUMPCOMM)); + } + + public void unregisterBroadcasts() { + LocalBroadcastManager.getInstance(context).unregisterReceiver(this); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/RileyLinkService.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/RileyLinkService.java new file mode 100644 index 0000000000..29781d191b --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/RileyLinkService.java @@ -0,0 +1,289 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service; + +import static info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil.getRileyLinkCommunicationManager; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import android.app.Service; +import android.bluetooth.BluetoothAdapter; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; + +import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkCommunicationManager; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkConst; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.RFSpy; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.RileyLinkBLE; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RileyLinkEncodingType; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkError; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkServiceState; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkTargetDevice; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.data.ServiceResult; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.data.ServiceTransport; +import info.nightscout.androidaps.plugins.pump.medtronic.defs.PumpDeviceState; +import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil; +import info.nightscout.androidaps.utils.SP; + +/** + * Created by andy on 5/6/18. + * Split from original file and renamed. + */ +public abstract class RileyLinkService extends Service { + + private static final Logger LOG = LoggerFactory.getLogger(L.PUMPCOMM); + + public RileyLinkBLE rileyLinkBLE; // android-bluetooth management + protected BluetoothAdapter bluetoothAdapter; + protected RFSpy rfspy; // interface for RL xxx Mhz radio. + protected Context context; + protected RileyLinkBroadcastReceiver mBroadcastReceiver; + protected RileyLinkServiceData rileyLinkServiceData; + protected RileyLinkBluetoothStateReceiver bluetoothStateReceiver; + + public RileyLinkService(Context context) { + super(); + this.context = context; + RileyLinkUtil.setContext(this.context); + RileyLinkUtil.setRileyLinkService(this); + RileyLinkUtil.setEncoding(getEncoding()); + initRileyLinkServiceData(); + } + + + /** + * Get Encoding for RileyLink communication + */ + public abstract RileyLinkEncodingType getEncoding(); + + + /** + * If you have customized RileyLinkServiceData you need to override this + */ + public abstract void initRileyLinkServiceData(); + + + @Override + public boolean onUnbind(Intent intent) { + //LOG.warn("onUnbind"); + return super.onUnbind(intent); + } + + + @Override + public void onRebind(Intent intent) { + //LOG.warn("onRebind"); + super.onRebind(intent); + } + + + @Override + public void onDestroy() { + super.onDestroy(); + //LOG.error("I die! I die!"); + + if (rileyLinkBLE != null) { + rileyLinkBLE.disconnect(); // dispose of Gatt (disconnect and close) + rileyLinkBLE = null; + } + + if (mBroadcastReceiver!=null) { + mBroadcastReceiver.unregisterBroadcasts(); + } + + if (bluetoothStateReceiver!=null) { + bluetoothStateReceiver.unregisterBroadcasts(); + } + + } + + + @Override + public void onCreate() { + super.onCreate(); + //LOG.debug("onCreate"); + + mBroadcastReceiver = new RileyLinkBroadcastReceiver(this, this.context); + mBroadcastReceiver.registerBroadcasts(); + + + bluetoothStateReceiver = new RileyLinkBluetoothStateReceiver(); + bluetoothStateReceiver.registerBroadcasts(); + + //LOG.debug("onCreate(): It's ALIVE!"); + } + + + /** + * Prefix for Device specific broadcast identifier prefix (for example MSG_PUMP_ for pump or + * MSG_POD_ for Omnipod) + * + * @return + */ + public abstract String getDeviceSpecificBroadcastsIdentifierPrefix(); + + + public abstract boolean handleDeviceSpecificBroadcasts(Intent intent); + + + public abstract void registerDeviceSpecificBroadcasts(IntentFilter intentFilter); + + + public abstract RileyLinkCommunicationManager getDeviceCommunicationManager(); + + + // Here is where the wake-lock begins: + // We've received a service startCommand, we grab the lock. + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + RileyLinkUtil.setContext(getApplicationContext()); + return (START_STICKY); + } + + + public boolean bluetoothInit() { + if (isLogEnabled()) + LOG.debug("bluetoothInit: attempting to get an adapter"); + RileyLinkUtil.setServiceState(RileyLinkServiceState.BluetoothInitializing); + + bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); + + if (bluetoothAdapter == null) { + LOG.error("Unable to obtain a BluetoothAdapter."); + RileyLinkUtil.setServiceState(RileyLinkServiceState.BluetoothError, RileyLinkError.NoBluetoothAdapter); + } else { + + if (!bluetoothAdapter.isEnabled()) { + LOG.error("Bluetooth is not enabled."); + RileyLinkUtil.setServiceState(RileyLinkServiceState.BluetoothError, RileyLinkError.BluetoothDisabled); + } else { + RileyLinkUtil.setServiceState(RileyLinkServiceState.BluetoothReady); + return true; + } + } + + return false; + } + + + // returns true if our Rileylink configuration changed + public boolean reconfigureRileyLink(String deviceAddress) { + + if (rileyLinkBLE == null) { + RileyLinkUtil.setServiceState(RileyLinkServiceState.BluetoothInitializing); + return false; + } + + RileyLinkUtil.setServiceState(RileyLinkServiceState.RileyLinkInitializing); + + if (rileyLinkBLE.isConnected()) { + if (deviceAddress.equals(rileyLinkServiceData.rileylinkAddress)) { + if (isLogEnabled()) + LOG.info("No change to RL address. Not reconnecting."); + return false; + } else { + if (isLogEnabled()) + LOG.warn("Disconnecting from old RL (" + rileyLinkServiceData.rileylinkAddress + + "), reconnecting to new: " + deviceAddress); + + rileyLinkBLE.disconnect(); + // prolly need to shut down listening thread too? + // SP.putString(MedtronicConst.Prefs.RileyLinkAddress, deviceAddress); + + rileyLinkServiceData.rileylinkAddress = deviceAddress; + rileyLinkBLE.findRileyLink(rileyLinkServiceData.rileylinkAddress); + return true; + } + } else { + if (isLogEnabled()) + LOG.debug("Using RL " + deviceAddress); + + if (RileyLinkUtil.getServiceState() == RileyLinkServiceState.NotStarted) { + if (!bluetoothInit()) { + LOG.error("RileyLink can't get activated, Bluetooth is not functioning correctly. {}", + RileyLinkUtil.getError() != null ? RileyLinkUtil.getError().name() : "Unknown error (null)"); + return false; + } + } + + rileyLinkBLE.findRileyLink(deviceAddress); + + return true; + } + } + + + public void sendServiceTransportResponse(ServiceTransport transport, ServiceResult serviceResult) { + } + + + // FIXME: This needs to be run in a session so that is interruptable, has a separate thread, etc. + public void doTuneUpDevice() { + + RileyLinkUtil.setServiceState(RileyLinkServiceState.TuneUpDevice); + MedtronicUtil.setPumpDeviceState(PumpDeviceState.Sleeping); + + double lastGoodFrequency = 0.0d; + + if (rileyLinkServiceData.lastGoodFrequency == null) { + lastGoodFrequency = SP.getDouble(RileyLinkConst.Prefs.LastGoodDeviceFrequency, 0.0d); + } else { + lastGoodFrequency = rileyLinkServiceData.lastGoodFrequency; + } + + double newFrequency; + + newFrequency = getDeviceCommunicationManager().tuneForDevice(); + + if ((newFrequency != 0.0) && (newFrequency != lastGoodFrequency)) { + if (isLogEnabled()) + LOG.info("Saving new pump frequency of {} MHz", newFrequency); + SP.putDouble(RileyLinkConst.Prefs.LastGoodDeviceFrequency, newFrequency); + rileyLinkServiceData.lastGoodFrequency = newFrequency; + rileyLinkServiceData.tuneUpDone = true; + rileyLinkServiceData.lastTuneUpTime = System.currentTimeMillis(); + } + + if (newFrequency == 0.0d) { + // error tuning pump, pump not present ?? + RileyLinkUtil + .setServiceState(RileyLinkServiceState.PumpConnectorError, RileyLinkError.TuneUpOfDeviceFailed); + } else { + getRileyLinkCommunicationManager().clearNotConnectedCount(); + RileyLinkUtil.setServiceState(RileyLinkServiceState.PumpConnectorReady); + } + } + + + public void disconnectRileyLink() { + + if (this.rileyLinkBLE != null && this.rileyLinkBLE.isConnected()) { + this.rileyLinkBLE.disconnect(); + rileyLinkServiceData.rileylinkAddress = null; + } + + RileyLinkUtil.setServiceState(RileyLinkServiceState.BluetoothReady); + } + + + /** + * Get Target Device for Service + */ + public RileyLinkTargetDevice getRileyLinkTargetDevice() { + return this.rileyLinkServiceData.targetDevice; + } + + + private boolean isLogEnabled() { + return L.isEnabled(L.PUMPCOMM); + } + + + public void changeRileyLinkEncoding(RileyLinkEncodingType encodingType) { + if (rfspy != null) { + rfspy.setRileyLinkEncoding(encodingType); + } + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/RileyLinkServiceData.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/RileyLinkServiceData.java new file mode 100644 index 0000000000..dd66255da4 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/RileyLinkServiceData.java @@ -0,0 +1,43 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service; + +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RileyLinkFirmwareVersion; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkError; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkServiceState; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkTargetDevice; + +/** + * Created by andy on 16/05/2018. + */ + +public class RileyLinkServiceData { + + public boolean tuneUpDone = false; + public RileyLinkError errorCode; + public RileyLinkServiceState serviceState = RileyLinkServiceState.NotStarted; + public String rileylinkAddress; + public long lastTuneUpTime = 0L; + public Double lastGoodFrequency; + + // bt version + public String versionBLE113; + // radio version + public RileyLinkFirmwareVersion versionCC110; + + public RileyLinkTargetDevice targetDevice; + + // Medtronic Pump + public String pumpID; + public byte[] pumpIDBytes; + + + public RileyLinkServiceData(RileyLinkTargetDevice targetDevice) { + this.targetDevice = targetDevice; + } + + + public void setPumpID(String pumpId, byte[] pumpIdBytes) { + this.pumpID = pumpId; + this.pumpIDBytes = pumpIdBytes; + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/data/ServiceCommand.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/data/ServiceCommand.java new file mode 100644 index 0000000000..4f43013328 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/data/ServiceCommand.java @@ -0,0 +1,67 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.data; + +import android.os.Bundle; + +/** + * Created by geoff on 6/25/16. + */ +public class ServiceCommand extends ServiceMessage { + + public ServiceCommand() { + map = new Bundle(); + } + + + // commandID is a string that the client can set on the message. + // The service does not use this value, but passes it back with the result + // so that the client can identify it. + public ServiceCommand(String commandName, String commandID) { + init(); + map.putString("command", commandName); + map.putString("commandID", commandID); + } + + + public ServiceCommand(Bundle commandBundle) { + if (commandBundle != null) { + map = commandBundle; + } else { + map = new Bundle(); + init(); + map.putString("command", "(null)"); + map.putString("commandID", "(null"); + } + } + + + @Override + public void init() { + map.putString("ServiceMessageType", "ServiceCommand"); + } + + + public String getCommandID() { + return map.getString("commandID"); + } + + + public String getCommandName() { + return map.getString("command"); + } + + + public boolean isPumpCommand() { + switch (getCommandName()) { + case "FetchPumpHistory": + case "ReadPumpClock": + case "RetrieveHistoryPage": + case "ReadISFProfile": + case "ReadBolusWizardCarbProfile": + case "UpdatePumpStatus": + case "WakeAndTune": + return true; + default: + return false; + } + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/data/ServiceMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/data/ServiceMessage.java new file mode 100644 index 0000000000..83e2f57ade --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/data/ServiceMessage.java @@ -0,0 +1,40 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.data; + +import android.os.Bundle; + +/** + * Created by geoff on 7/4/16. + *

+ * Base class for all messages passed between service and client + */ +public class ServiceMessage { + + protected Bundle map = new Bundle(); + + + public ServiceMessage() { + init(); + } + + + public void init() { + map.putString("ServiceMessageClass", this.getClass().getCanonicalName()); + map.putString("ServiceMessageType", this.getClass().getSimpleName()); + } + + + public Bundle getMap() { + return map; + } + + + public void setMap(Bundle map) { + this.map = map; + } + + + public String getServiceMessageType() { + return map.getString("ServiceMessageType"); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/data/ServiceNotification.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/data/ServiceNotification.java new file mode 100644 index 0000000000..aad45093f1 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/data/ServiceNotification.java @@ -0,0 +1,48 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.data; + +import android.os.Bundle; + +/** + * Created by geoff on 7/6/16. + *

+ * These are "one liner" messages between client and service. Must still be contained within ServiceTransports + */ +public class ServiceNotification extends ServiceMessage { + + public ServiceNotification() { + } + + + public ServiceNotification(Bundle b) { + if (b != null) { + if ("ServiceNotification".equals(b.getString("ServiceMessageType"))) { + setMap(b); + } else { + throw new IllegalArgumentException(); + } + } + } + + + public ServiceNotification(String notificationType) { + setNotificationType(notificationType); + } + + + @Override + public void init() { + super.init(); + map.putString("ServiceMessageType", "ServiceNotification"); + } + + + public String getNotificationType() { + return map.getString("NotificationType", ""); + } + + + public void setNotificationType(String notificationType) { + map.putString("NotificationType", notificationType); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/data/ServiceResult.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/data/ServiceResult.java new file mode 100644 index 0000000000..ecf7d54f99 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/data/ServiceResult.java @@ -0,0 +1,96 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.data; + +import android.os.Bundle; + +/** + * Created by geoff on 6/25/16. + */ +public class ServiceResult extends ServiceMessage { + + public static final int ERROR_MALFORMED_PUMP_RESPONSE = 1; + public static final int ERROR_NULL_PUMP_RESPONSE = 2; + public static final int ERROR_INVALID_PUMP_RESPONSE = 3; + public static final int ERROR_PUMP_BUSY = 4; + + + public ServiceResult() { + init(); + } + + + public ServiceResult(Bundle resultBundle) { + if (resultBundle != null) { + setMap(resultBundle); + } else { + init(); + } + } + + + public static final String getErrorDescription(int errorCode) { + switch (errorCode) { + case ERROR_MALFORMED_PUMP_RESPONSE: + return "Malformed Pump Response"; + case ERROR_NULL_PUMP_RESPONSE: + return "Null pump response"; + case ERROR_INVALID_PUMP_RESPONSE: + return "Invalid pump response"; + case ERROR_PUMP_BUSY: + return "A pump command session is already in progress"; + default: + return "Unknown error code (" + errorCode + ")"; + } + } + + + @Override + public void init() { + super.init(); + map.putString("ServiceMessageType", "ServiceResult"); + setServiceResultType(this.getClass().getSimpleName()); + setResultError(0, "Uninitialized ServiceResult"); + } + + + public String getServiceResultType() { + return map.getString("ServiceResultType", "ServiceResult"); + } + + + public void setServiceResultType(String serviceResultType) { + map.putString("ServiceResultType", serviceResultType); + } + + + public void setResultOK() { + map.putString("result", "OK"); + } + + + public void setResultError(int errorCode) { + setResultError(errorCode, getErrorDescription(errorCode)); + } + + + public void setResultError(int errorCode, String errorDescription) { + map.putString("result", "error"); + map.putInt("errorCode", errorCode); + map.putString("errorDescription", errorDescription); + } + + + public boolean resultIsOK() { + return ("OK".equals(map.getString("result", ""))); + } + + + public String getErrorDescription() { + return map.getString("errorDescription", ""); + } + + + public String getResult() { + return map.getString("result", ""); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/data/ServiceTransport.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/data/ServiceTransport.java new file mode 100644 index 0000000000..c2043708fe --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/data/ServiceTransport.java @@ -0,0 +1,150 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.data; + +import android.os.Bundle; +import android.os.Parcel; + +/** + * Created by geoff on 7/6/16. + *

+ * This class exists to hold a ServiceCommand along with transport variables such as time sent, time received, sender. + * May also contain result, if the command is completed. + */ +public class ServiceTransport extends ServiceMessage { + + private ServiceTransportType serviceTransportType = ServiceTransportType.Undefined; + + + public ServiceTransport() { + } + + + public ServiceTransport(Bundle b) { + if (b != null) { + if ("ServiceTransport".equals(b.getString("ServiceMessageType"))) { + setMap(b); + } else { + throw new IllegalArgumentException(); + } + } + } + + + @Override + public void init() { + super.init(); + map.putString("ServiceMessageType", "ServiceTransport"); + setTransportType("unknown"); + setSenderHashcode(0); + } + + + public Integer getSenderHashcode() { + return map.getInt("senderHashCode", 0); + } + + + public void setSenderHashcode(Integer senderHashcode) { + map.putInt("senderHashcode", senderHashcode); + } + + + public ServiceCommand getServiceCommand() { + return new ServiceCommand(map.getBundle("ServiceCommand")); + } + + + public void setServiceCommand(ServiceCommand serviceCommand) { + map.putBundle("ServiceCommand", serviceCommand.getMap()); + this.serviceTransportType = ServiceTransportType.ServiceCommand; + } + + + public boolean hasServiceCommand() { + return (getMap().containsKey("ServiceCommand")); + } + + + public String getTransportType() { + return map.getString("transportType", "unknown"); + } + + + // On remote end, this will be converted to the "action" of a local Intent, + // so can be used for separating types of messages to different internal handlers. + public void setTransportType(String transportType) { + map.putString("transportType", transportType); + } + + + public ServiceResult getServiceResult() { + return new ServiceResult(map.getBundle("ServiceResult")); + } + + + public void setServiceResult(ServiceResult serviceResult) { + map.putBundle("ServiceResult", serviceResult.getMap()); + this.serviceTransportType = ServiceTransportType.ServiceResult; + } + + + public boolean hasServiceResult() { + return (getMap().containsKey("ServiceResult")); + } + + + public ServiceNotification getServiceNotification() { + return new ServiceNotification(map.getBundle("ServiceNotification")); + } + + + public void setServiceNotification(ServiceNotification notification) { + map.putBundle("ServiceNotification", notification.getMap()); + this.serviceTransportType = ServiceTransportType.ServiceNotification; + } + + + public boolean hasServiceNotification() { + return (map.containsKey("ServiceNotification")); + } + + + public boolean commandDidCompleteOK() { + return getServiceResult().resultIsOK(); + } + + + public String getOriginalCommandName() { + return getServiceCommand().getCommandName(); + } + + + public String describeContentsShort() { + String rval = ""; + rval += getTransportType(); + + if (this.serviceTransportType == ServiceTransportType.ServiceNotification) { + rval += "note: " + getServiceNotification().getNotificationType(); + } else if (this.serviceTransportType == ServiceTransportType.ServiceCommand) { + rval += ", cmd=" + getOriginalCommandName(); + } else if (this.serviceTransportType == ServiceTransportType.ServiceResult) { + rval += ", cmd=" + getOriginalCommandName(); + rval += ", rslt=" + getServiceResult().getResult(); + rval += ", err=" + getServiceResult().getErrorDescription(); + } + return rval; + } + + + public ServiceTransport clone() { + Parcel p = Parcel.obtain(); + Parcel p2 = Parcel.obtain(); + getMap().writeToParcel(p, 0); + byte[] bytes = p.marshall(); + p2.unmarshall(bytes, 0, bytes.length); + p2.setDataPosition(0); + Bundle b = p2.readBundle(); + ServiceTransport rval = new ServiceTransport(); + rval.setMap(b); + return rval; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/data/ServiceTransportType.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/data/ServiceTransportType.java new file mode 100644 index 0000000000..135c217996 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/data/ServiceTransportType.java @@ -0,0 +1,15 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.data; + +/** + * Created by andy on 31/05/18. + */ + +public enum ServiceTransportType { + + Undefined, // + ServiceNotification, // + + ServiceCommand, // + ServiceResult + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/tasks/DiscoverGattServicesTask.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/tasks/DiscoverGattServicesTask.java new file mode 100644 index 0000000000..5f807c3e89 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/tasks/DiscoverGattServicesTask.java @@ -0,0 +1,30 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks; + +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil; + +/** + * Created by geoff on 7/9/16. + */ +public class DiscoverGattServicesTask extends ServiceTask { + + public boolean needToConnect = false; + + + public DiscoverGattServicesTask() { + } + + + public DiscoverGattServicesTask(boolean needToConnect) { + this.needToConnect = needToConnect; + } + + + @Override + public void run() { + + if (needToConnect) + RileyLinkUtil.getRileyLinkBLE().connectGatt(); + + RileyLinkUtil.getRileyLinkBLE().discoverServices(); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/tasks/InitializePumpManagerTask.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/tasks/InitializePumpManagerTask.java new file mode 100644 index 0000000000..9856b21b66 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/tasks/InitializePumpManagerTask.java @@ -0,0 +1,83 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks; + +import android.util.Log; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkConst; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkError; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkServiceState; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkTargetDevice; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.data.ServiceTransport; +import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicConst; +import info.nightscout.androidaps.utils.SP; + +/** + * Created by geoff on 7/9/16. + *

+ * This class is intended to be run by the Service, for the Service. Not intended for clients to run. + */ +public class InitializePumpManagerTask extends ServiceTask { + + private static final String TAG = "InitPumpManagerTask"; + private RileyLinkTargetDevice targetDevice; + private static final Logger LOG = LoggerFactory.getLogger(L.PUMPCOMM); + + public InitializePumpManagerTask(RileyLinkTargetDevice targetDevice) { + super(); + this.targetDevice = targetDevice; + } + + + public InitializePumpManagerTask(ServiceTransport transport) { + super(transport); + } + + + @Override + public void run() { + + double lastGoodFrequency = 0.0d; + + if (RileyLinkUtil.getRileyLinkServiceData().lastGoodFrequency==null) { + + lastGoodFrequency = SP.getDouble(RileyLinkConst.Prefs.LastGoodDeviceFrequency, 0.0d); + lastGoodFrequency = Math.round(lastGoodFrequency * 1000d) / 1000d; + + RileyLinkUtil.getRileyLinkServiceData().lastGoodFrequency = lastGoodFrequency; + +// if (RileyLinkUtil.getRileyLinkTargetFrequency() == null) { +// String pumpFrequency = SP.getString(MedtronicConst.Prefs.PumpFrequency, null); +// } + } else { + lastGoodFrequency = RileyLinkUtil.getRileyLinkServiceData().lastGoodFrequency; + } + + if ((lastGoodFrequency > 0.0d) + && RileyLinkUtil.getRileyLinkCommunicationManager().isValidFrequency(lastGoodFrequency)) { + + RileyLinkUtil.setServiceState(RileyLinkServiceState.RileyLinkReady); + + if (L.isEnabled(L.PUMPCOMM)) + LOG.info("Setting radio frequency to {} MHz", lastGoodFrequency); + + RileyLinkUtil.getRileyLinkCommunicationManager().setRadioFrequencyForPump(lastGoodFrequency); + + boolean foundThePump = RileyLinkUtil.getRileyLinkCommunicationManager().tryToConnectToDevice(); + + if (foundThePump) { + RileyLinkUtil.setServiceState(RileyLinkServiceState.PumpConnectorReady); + } else { + RileyLinkUtil.setServiceState(RileyLinkServiceState.PumpConnectorError, + RileyLinkError.NoContactWithDevice); + RileyLinkUtil.sendBroadcastMessage(RileyLinkConst.IPC.MSG_PUMP_tunePump); + } + + } else { + RileyLinkUtil.sendBroadcastMessage(RileyLinkConst.IPC.MSG_PUMP_tunePump); + } + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/tasks/PumpTask.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/tasks/PumpTask.java new file mode 100644 index 0000000000..c307a43590 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/tasks/PumpTask.java @@ -0,0 +1,18 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks; + +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.data.ServiceTransport; + +/** + * Created by geoff on 7/10/16. + */ +public class PumpTask extends ServiceTask { + + public PumpTask() { + super(); + } + + + public PumpTask(ServiceTransport transport) { + super(transport); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/tasks/ResetRileyLinkConfigurationTask.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/tasks/ResetRileyLinkConfigurationTask.java new file mode 100644 index 0000000000..cce127ffdf --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/tasks/ResetRileyLinkConfigurationTask.java @@ -0,0 +1,35 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks; + +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.data.ServiceTransport; +import info.nightscout.androidaps.plugins.pump.medtronic.MedtronicPumpPlugin; +import info.nightscout.androidaps.plugins.pump.medtronic.events.EventRefreshButtonState; +import info.nightscout.androidaps.plugins.pump.medtronic.service.RileyLinkMedtronicService; + +/** + * Created by geoff on 7/16/16. + */ +public class ResetRileyLinkConfigurationTask extends PumpTask { + + private static final String TAG = "ResetRileyLinkTask"; + + + public ResetRileyLinkConfigurationTask() { + } + + + public ResetRileyLinkConfigurationTask(ServiceTransport transport) { + super(transport); + } + + + @Override + public void run() { + RxBus.INSTANCE.send(new EventRefreshButtonState(false)); + MedtronicPumpPlugin.isBusy = true; + RileyLinkMedtronicService.getInstance().resetRileyLinkConfiguration(); + MedtronicPumpPlugin.isBusy = false; + RxBus.INSTANCE.send(new EventRefreshButtonState(true)); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/tasks/ServiceTask.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/tasks/ServiceTask.java new file mode 100644 index 0000000000..e287b63e17 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/tasks/ServiceTask.java @@ -0,0 +1,54 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks; + +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.data.ServiceTransport; + +/** + * Created by geoff on 7/9/16. + */ +public class ServiceTask implements Runnable { + + private static final String TAG = "ServiceTask(base)"; + public boolean completed = false; + protected ServiceTransport mTransport; + + + public ServiceTask() { + init(new ServiceTransport()); + } + + + public ServiceTask(ServiceTransport transport) { + init(transport); + } + + + public void init(ServiceTransport transport) { + mTransport = transport; + } + + + @Override + public void run() { + } + + + public void preOp() { + // This function is called by UI thread before running asynch thread. + } + + + public void postOp() { + // This function is called by UI thread after running asynch thread. + } + + + public ServiceTransport getServiceTransport() { + return mTransport; + } + + /* + * protected void sendResponse(ServiceResult result) { + * RoundtripService.getInstance().sendServiceTransportResponse(mTransport,result); + * } + */ +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/tasks/ServiceTaskExecutor.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/tasks/ServiceTaskExecutor.java new file mode 100644 index 0000000000..1c6f33b071 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/tasks/ServiceTaskExecutor.java @@ -0,0 +1,59 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks; + +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +import android.util.Log; + +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil; + +/** + * Created by geoff on 7/9/16. + */ +public class ServiceTaskExecutor extends ThreadPoolExecutor { + + private static final String TAG = "ServiceTaskExecutor"; + private static ServiceTaskExecutor instance; + private static LinkedBlockingQueue taskQueue = new LinkedBlockingQueue<>(); + + static { + instance = new ServiceTaskExecutor(); + } + + + private ServiceTaskExecutor() { + super(1, 1, 10000, TimeUnit.MILLISECONDS, taskQueue); + } + + + public static ServiceTaskExecutor getInstance() { + return instance; + } + + + public static ServiceTask startTask(ServiceTask task) { + instance.execute(task); // task will be run on async thread from pool. + return task; + } + + + // FIXME + protected void beforeExecute(Thread t, Runnable r) { + // This is run on either caller UI thread or Service UI thread. + ServiceTask task = (ServiceTask)r; + Log.v(TAG, "About to run task " + task.getClass().getSimpleName()); + RileyLinkUtil.setCurrentTask(task); + task.preOp(); + } + + + // FIXME + protected void afterExecute(Runnable r, Throwable t) { + // This is run on either caller UI thread or Service UI thread. + ServiceTask task = (ServiceTask)r; + task.postOp(); + Log.v(TAG, "Finishing task " + task.getClass().getSimpleName()); + RileyLinkUtil.finishCurrentTask(task); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/tasks/WakeAndTuneTask.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/tasks/WakeAndTuneTask.java new file mode 100644 index 0000000000..5feb5ab405 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/tasks/WakeAndTuneTask.java @@ -0,0 +1,34 @@ +package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks; + +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.data.ServiceTransport; +import info.nightscout.androidaps.plugins.pump.medtronic.MedtronicPumpPlugin; +import info.nightscout.androidaps.plugins.pump.medtronic.events.EventRefreshButtonState; +import info.nightscout.androidaps.plugins.pump.medtronic.service.RileyLinkMedtronicService; + +/** + * Created by geoff on 7/16/16. + */ +public class WakeAndTuneTask extends PumpTask { + + private static final String TAG = "WakeAndTuneTask"; + + + public WakeAndTuneTask() { + } + + + public WakeAndTuneTask(ServiceTransport transport) { + super(transport); + } + + + @Override + public void run() { + RxBus.INSTANCE.send(new EventRefreshButtonState(false)); + MedtronicPumpPlugin.isBusy = true; + RileyLinkMedtronicService.getInstance().doTuneUpDevice(); + MedtronicPumpPlugin.isBusy = false; + RxBus.INSTANCE.send(new EventRefreshButtonState(true)); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/ui/RileyLinkSelectPreference.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/ui/RileyLinkSelectPreference.java new file mode 100644 index 0000000000..de9d28d46b --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/ui/RileyLinkSelectPreference.java @@ -0,0 +1,40 @@ +package info.nightscout.androidaps.plugins.pump.common.ui; + +import android.content.Context; +import android.preference.Preference; +import android.util.AttributeSet; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil; +import info.nightscout.androidaps.utils.SP; + +/** + * Created by andy on 10/18/18. + */ + +public class RileyLinkSelectPreference extends Preference { + + public RileyLinkSelectPreference(Context context) { + super(context); + setInitialSummaryValue(); + + MedtronicUtil.setRileyLinkSelectPreference(this); + } + + + public RileyLinkSelectPreference(Context context, AttributeSet attrs) { + super(context, attrs); + setInitialSummaryValue(); + + MedtronicUtil.setRileyLinkSelectPreference(this); + } + + + private void setInitialSummaryValue() { + String value = SP.getString("pref_rileylink_mac_address", null); + + setSummary(value == null ? MainApp.gs(R.string.rileylink_error_address_not_set_short) : value); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/ByteUtil.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/ByteUtil.java new file mode 100644 index 0000000000..5451689ebe --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/ByteUtil.java @@ -0,0 +1,450 @@ +package info.nightscout.androidaps.plugins.pump.common.utils; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by geoff on 4/28/15. + */ +public class ByteUtil { + + private final static char[] HEX_DIGITS = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; + + private final static String HEX_DIGITS_STR = "0123456789ABCDEF"; + + + public static byte highByte(short s) { + return (byte) (s / 256); + } + + + public static byte lowByte(short s) { + return (byte) (s % 256); + } + + + public static int asUINT8(byte b) { + return (b < 0) ? b + 256 : b; + } + + + /* For Reference: static void System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length) */ + + public static byte[] concat(byte[] a, byte[] b) { + + if (b == null) { + return a; + } + + int aLen = a.length; + int bLen = b.length; + byte[] c = new byte[aLen + bLen]; + System.arraycopy(a, 0, c, 0, aLen); + System.arraycopy(b, 0, c, aLen, bLen); + return c; + } + + + public static byte[] concat(byte[] a, byte b) { + int aLen = a.length; + byte[] c = new byte[aLen + 1]; + System.arraycopy(a, 0, c, 0, aLen); + c[aLen] = b; + return c; + } + + + public static byte[] concat(byte a, byte[] b) { + int aLen = b.length; + byte[] c = new byte[aLen + 1]; + c[0] = a; + System.arraycopy(b, 0, c, 1, aLen); + + return c; + } + + + public static byte[] substring(byte[] a, int start, int len) { + byte[] rval = new byte[len]; + System.arraycopy(a, start, rval, 0, len); + return rval; + } + + public static byte[] substring(List a, int start, int len) { + byte[] rval = new byte[len]; + + for (int i = start, j = 0; i < start + len; i++, j++) { + rval[j] = a.get(i); + } + return rval; + } + + + public static byte[] substring(byte[] a, int start) { + int len = a.length - start; + byte[] rval = new byte[len]; + System.arraycopy(a, start, rval, 0, len); + return rval; + } + + + public static String shortHexString(byte[] ra) { + String rval = ""; + if (ra == null) { + return rval; + } + if (ra.length == 0) { + return rval; + } + for (int i = 0; i < ra.length; i++) { + rval = rval + HEX_DIGITS[(ra[i] & 0xF0) >> 4]; + rval = rval + HEX_DIGITS[(ra[i] & 0x0F)]; + if (i < ra.length - 1) { + rval = rval + " "; + } + } + return rval; + } + + public static String shortHexString(List list) { + + byte[] abyte0 = getByteArrayFromList(list); + + return shortHexString(abyte0); + } + + + public static String shortHexString(byte val) { + return getHexCompact(val); + } + + + public static String showPrintable(byte[] ra) { + String s = new String(); + for (int i = 0; i < ra.length; i++) { + char c = (char) ra[i]; + if (((c >= '0') && (c <= '9')) || ((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z'))) { + s = s + c; + } else { + s = s + '.'; + } + } + return s; + } + + + public static byte[] fromHexString(String src) { + String s = src.toUpperCase(); + byte[] rval = new byte[]{}; + if ((s.length() % 2) != 0) { + // invalid hex string! + return null; + } + for (int i = 0; i < s.length(); i += 2) { + int highNibbleOrd = HEX_DIGITS_STR.indexOf(s.charAt(i)); + if (highNibbleOrd < 0) { + // Not a hex digit. + return null; + } + int lowNibbleOrd = HEX_DIGITS_STR.indexOf(s.charAt(i + 1)); + if (lowNibbleOrd < 0) { + // Not a hex digit + return null; + } + rval = concat(rval, (byte) (highNibbleOrd * 16 + lowNibbleOrd)); + } + return rval; + } + + + // public static byte[] fromByteList(List byteArray) { + // byte[] rval = new byte[byteArray.size()]; + // for (int i = 0; i < byteArray.size(); i++) { + // rval[i] = byteArray.get(i); + // } + // return rval; + // } + + // public static List toByteList(byte[] data) { + // ArrayList rval = new ArrayList<>(data.length); + // for (int i = 0; i < data.length; i++) { + // rval.add(i, new Byte(data[i])); + // } + // return rval; + // } + + public static List getListFromByteArray(byte[] array) { + List listOut = new ArrayList(); + + for (byte val : array) { + listOut.add(val); + } + + return listOut; + } + + + public static byte[] getByteArrayFromList(List list) { + byte[] out = new byte[list.size()]; + + for (int i = 0; i < list.size(); i++) { + out[i] = list.get(i); + } + + return out; + } + + + // compares byte strings like strcmp + public static int compare(byte[] s1, byte[] s2) { + int i; + int len1 = s1.length; + int len2 = s2.length; + if (len1 > len2) { + return 1; + } + if (len2 > len1) { + return -1; + } + int acc = 0; + for (i = 0; i < len1; i++) { + acc += s1[i]; + acc -= s2[i]; + if (acc != 0) { + return acc; + } + } + return 0; + } + + + /** + * Converts 4 (or less) ints into int. (Shorts are objects, so you can send null if you have less parameters) + * + * @param b1 short 1 + * @param b2 short 2 + * @param b3 short 3 + * @param b4 short 4 + * @param flag Conversion Flag (Big Endian, Little endian) + * @return int value + */ + public static int toInt(Integer b1, Integer b2, Integer b3, Integer b4, BitConversion flag) { + switch (flag) { + case LITTLE_ENDIAN: { + if (b4 != null) { + return (b4 & 0xff) << 24 | (b3 & 0xff) << 16 | (b2 & 0xff) << 8 | b1 & 0xff; + } else if (b3 != null) { + return (b3 & 0xff) << 16 | (b2 & 0xff) << 8 | b1 & 0xff; + } else if (b2 != null) { + return (b2 & 0xff) << 8 | b1 & 0xff; + } else { + return b1 & 0xff; + } + } + + default: + case BIG_ENDIAN: { + if (b4 != null) { + return (b1 & 0xff) << 24 | (b2 & 0xff) << 16 | (b3 & 0xff) << 8 | b4 & 0xff; + } else if (b3 != null) { + return (b1 & 0xff) << 16 | (b2 & 0xff) << 8 | b3 & 0xff; + } else if (b2 != null) { + return (b1 & 0xff) << 8 | b2 & 0xff; + } else { + return b1 & 0xff; + } + } + } + } + + + public static int toInt(int b1, int b2) { + return toInt(b1, b2, null, null, BitConversion.BIG_ENDIAN); + } + + + public static int toInt(int b1, int b2, int b3) { + return toInt(b1, b2, b3, null, BitConversion.BIG_ENDIAN); + } + + + public static int toInt(int b1, int b2, BitConversion flag) { + return toInt(b1, b2, null, null, flag); + } + + + public static int makeUnsignedShort(int i, int j) { + int k = (i & 0xff) << 8 | j & 0xff; + return k; + } + + + /** + * Gets the correct hex value. + * + * @param inp the inp + * @return the correct hex value + */ + public static String getCorrectHexValue(int inp) { + String hx = Integer.toHexString((char) inp); + + if (hx.length() == 0) + return "00"; + else if (hx.length() == 1) + return "0" + hx; + else if (hx.length() == 2) + return hx; + else if (hx.length() == 4) + return hx.substring(2); + else { + System.out.println("Hex Error: " + inp); + } + + return null; + } + + + public static String getHex(byte[] abyte0) { + return abyte0 != null ? getHex(abyte0, abyte0.length) : null; + } + + + public static String getString(short[] abyte0) { + StringBuilder sb = new StringBuilder(); + + for (short i : abyte0) { + sb.append(i); + sb.append(" "); + } + + return sb.toString(); + } + + + public static String getHex(List list) { + + byte[] abyte0 = getByteArrayFromList(list); + + return abyte0 != null ? getHex(abyte0, abyte0.length) : null; + } + + + public static String getHex(byte[] abyte0, int i) { + StringBuffer stringbuffer = new StringBuffer(); + if (abyte0 != null) { + i = Math.min(i, abyte0.length); + for (int j = 0; j < i; j++) { + stringbuffer.append(shortHexString(abyte0[j])); + if (j < i - 1) { + stringbuffer.append(" "); + } + } + + } + return new String(stringbuffer); + } + + + public static String getHex(byte byte0) { + String s = byte0 != -1 ? "0x" : ""; + return s + getHexCompact(byte0); + } + + + public static String getHexCompact(byte byte0) { + int i = byte0 != -1 ? convertUnsignedByteToInt(byte0) : (int) byte0; + return getHexCompact(i); + } + + + public static int convertUnsignedByteToInt(byte data) { + return data & 0xff; + } + + + // public String getHexCompact(int i) { + // long l = i != -1 ? convertUnsignedIntToLong(i) : i; + // return getHexCompact(l); + // } + + public static String getHexCompact(int l) { + String s = Long.toHexString(l).toUpperCase(); + String s1 = isOdd(s.length()) ? "0" : ""; + return l != -1L ? s1 + s : "-1"; + } + + + public static boolean isEven(int i) { + return i % 2 == 0; + } + + + public static boolean isOdd(int i) { + return !isEven(i); + } + + public enum BitConversion { + LITTLE_ENDIAN, // 20 0 0 0 = reverse + BIG_ENDIAN // 0 0 0 20 = normal - java + } + + + public static String getCompactString(byte[] data) { + if (data == null) + return "null"; + + String vval2 = ByteUtil.getHex(data); + vval2 = vval2.replace(" 0x", ""); + vval2 = vval2.replace("0x", ""); + return vval2; + } + + + // 000300050100C800A0 + public static byte[] createByteArrayFromCompactString(String dataFull) { + return createByteArrayFromCompactString(dataFull, 0, dataFull.length()); + } + + + // 00 03 00 05 01 00 C8 00 A0 + public static byte[] createByteArrayFromString(String dataFull) { + + String data = dataFull.replace(" ", ""); + + return createByteArrayFromCompactString(data, 0, data.length()); + } + + + public static byte[] createByteArrayFromHexString(String dataFull) { + + String data = dataFull.replace(" 0x", ""); + data = data.replace("0x", ""); + + return createByteArrayFromCompactString(data, 0, data.length()); + } + + + public static byte[] createByteArrayFromCompactString(String dataFull, int startIndex) { + return createByteArrayFromCompactString(dataFull, startIndex, dataFull.length()); + } + + + public static byte[] createByteArrayFromCompactString(String dataFull, int startIndex, int length) { + + String data = dataFull.substring(startIndex); + + data = data.substring(0, length); + + int len = data.length(); + byte[] outArray = new byte[len / 2]; + for (int i = 0; i < len; i += 2) { + outArray[i / 2] = (byte) ((Character.digit(data.charAt(i), 16) << 4) + Character.digit(data.charAt(i + 1), + 16)); + } + + return outArray; + } + + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/CRC.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/CRC.java new file mode 100644 index 0000000000..ac90d1edb8 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/CRC.java @@ -0,0 +1,153 @@ +package info.nightscout.androidaps.plugins.pump.common.utils; + +/** + * Created by geoff on 4/27/15. + */ +public class CRC { + + static final int[] crc8lookup = new int[] { + 0, 155, 173, 54, 193, 90, 108, 247, 25, + 130, + 180, + 47, + 216, + 67, + 117, + 238, + 50, + 169, // + 159, 4, 243, 104, 94, 197, 43, 176, 134, 29, 234, 113, 71, 220, 100, 255, 201, + 82, + 165, + 62, + 8, + 147, + 125, + 230, + 208, + 75, // + 188, 39, 17, 138, 86, 205, 251, 96, 151, 12, 58, 161, 79, 212, 226, 121, 142, 21, + 35, + 184, + 200, + 83, + 101, + 254, + 9, + 146, // + 164, 63, 209, 74, 124, 231, 16, 139, 189, 38, 250, 97, 87, 204, 59, 160, 150, 13, 227, + 120, + 78, + 213, + 34, + 185, + 143, + 20, // + 172, 55, 1, 154, 109, 246, 192, 91, 181, 46, 24, 131, 116, 239, 217, 66, 158, 5, 51, 168, 95, + 196, + 242, + 105, + 135, + 28, + 42, // + 177, 70, 221, 235, 112, 11, 144, 166, 61, 202, 81, 103, 252, 18, 137, 191, 36, 211, 72, 126, 229, + 57, + 162, + 148, + 15, + 248, // + 99, 85, 206, 32, 187, 141, 22, 225, 122, 76, 215, 111, 244, 194, 89, 174, 53, 3, 152, 118, 237, 219, 64, + 183, + 44, + 26, + 129, // + 93, 198, 240, 107, 156, 7, 49, 170, 68, 223, 233, 114, 133, 30, 40, 179, 195, 88, 110, 245, 2, 153, 175, 52, + 218, + 65, + 119, // + 236, 27, 128, 182, 45, 241, 106, 92, 199, 48, 171, 157, 6, 232, 115, 69, 222, 41, 178, 132, 31, 167, 60, 10, + 145, 102, + 253, // + 203, 80, 190, 37, 19, 136, 127, 228, 210, 73, 149, 14, 56, 163, 84, 207, 249, 98, 140, 23, 33, 186, 77, 214, + 224, 123 }; + + static final int[] crc16lookup = new int[] { + 0x0000, 0x8005, 0x800f, 0x000a, 0x801b, 0x001e, 0x0014, 0x8011, 0x8033, 0x0036, 0x003c, 0x8039, 0x0028, 0x802d, + 0x8027, 0x0022, 0x8063, 0x0066, 0x006c, 0x8069, 0x0078, 0x807d, 0x8077, 0x0072, 0x0050, 0x8055, 0x805f, 0x005a, + 0x804b, 0x004e, 0x0044, 0x8041, 0x80c3, 0x00c6, 0x00cc, 0x80c9, 0x00d8, 0x80dd, 0x80d7, 0x00d2, 0x00f0, 0x80f5, + 0x80ff, 0x00fa, 0x80eb, 0x00ee, 0x00e4, 0x80e1, 0x00a0, 0x80a5, 0x80af, 0x00aa, 0x80bb, 0x00be, 0x00b4, 0x80b1, + 0x8093, 0x0096, 0x009c, 0x8099, 0x0088, 0x808d, 0x8087, 0x0082, 0x8183, 0x0186, 0x018c, 0x8189, 0x0198, 0x819d, + 0x8197, 0x0192, 0x01b0, 0x81b5, 0x81bf, 0x01ba, 0x81ab, 0x01ae, 0x01a4, 0x81a1, 0x01e0, 0x81e5, 0x81ef, 0x01ea, + 0x81fb, 0x01fe, 0x01f4, 0x81f1, 0x81d3, 0x01d6, 0x01dc, 0x81d9, 0x01c8, 0x81cd, 0x81c7, 0x01c2, 0x0140, 0x8145, + 0x814f, 0x014a, 0x815b, 0x015e, 0x0154, 0x8151, 0x8173, 0x0176, 0x017c, 0x8179, 0x0168, 0x816d, 0x8167, 0x0162, + 0x8123, 0x0126, 0x012c, 0x8129, 0x0138, 0x813d, 0x8137, 0x0132, 0x0110, 0x8115, 0x811f, 0x011a, 0x810b, 0x010e, + 0x0104, 0x8101, 0x8303, 0x0306, 0x030c, 0x8309, 0x0318, 0x831d, 0x8317, 0x0312, 0x0330, 0x8335, 0x833f, 0x033a, + 0x832b, 0x032e, 0x0324, 0x8321, 0x0360, 0x8365, 0x836f, 0x036a, 0x837b, 0x037e, 0x0374, 0x8371, 0x8353, 0x0356, + 0x035c, 0x8359, 0x0348, 0x834d, 0x8347, 0x0342, 0x03c0, 0x83c5, 0x83cf, 0x03ca, 0x83db, 0x03de, 0x03d4, 0x83d1, + 0x83f3, 0x03f6, 0x03fc, 0x83f9, 0x03e8, 0x83ed, 0x83e7, 0x03e2, 0x83a3, 0x03a6, 0x03ac, 0x83a9, 0x03b8, 0x83bd, + 0x83b7, 0x03b2, 0x0390, 0x8395, 0x839f, 0x039a, 0x838b, 0x038e, 0x0384, 0x8381, 0x0280, 0x8285, 0x828f, 0x028a, + 0x829b, 0x029e, 0x0294, 0x8291, 0x82b3, 0x02b6, 0x02bc, 0x82b9, 0x02a8, 0x82ad, 0x82a7, 0x02a2, 0x82e3, 0x02e6, + 0x02ec, 0x82e9, 0x02f8, 0x82fd, 0x82f7, 0x02f2, 0x02d0, 0x82d5, 0x82df, 0x02da, 0x82cb, 0x02ce, 0x02c4, 0x82c1, + 0x8243, 0x0246, 0x024c, 0x8249, 0x0258, 0x825d, 0x8257, 0x0252, 0x0270, 0x8275, 0x827f, 0x027a, 0x826b, 0x026e, + 0x0264, 0x8261, 0x0220, 0x8225, 0x822f, 0x022a, 0x823b, 0x023e, 0x0234, 0x8231, 0x8213, 0x0216, 0x021c, 0x8219, + 0x0208, 0x820d, 0x8207, 0x0202 }; + + + public static byte crc8(byte[] data, int len) { + byte result = 0; + if (data == null) { + return 0; + } + if (len > data.length) { + len = data.length; + } + for (int i = 0; i < len; i++) { + int tmp = result; + int tmp2 = tmp ^ data[i]; + int tmp3 = tmp2 & 0xFF; + int idx = tmp3; + result = (byte)crc8lookup[idx]; + // log(String.format("iter=%d,tmp=0x%02x, tmp2=0x%02x, tmp3=0x%02x, lookup=0x%02x",i,tmp,tmp2,tmp3,result)); + } + // orig python: + // result = klass.lookup[ ( result ^ block[ i ] & 0xFF ) ] + return result; + + } + + + public static byte crc8(byte[] data) { + return crc8(data, data.length); + } + + + public static byte[] calculate16CCITT(byte[] data) { + int crc = 0xFFFF; + int polynomial = 0x1021; + if (data != null) { + if (data.length > 0) { + for (int j = 0; j < data.length; j++) { + byte b = data[j]; + for (int i = 0; i < 8; i++) { + boolean bit = ((b >> (7 - i) & 1) == 1); + boolean c15 = ((crc >> 15 & 1) == 1); + crc <<= 1; + if (c15 ^ bit) + crc ^= polynomial; + } + } + } + } + crc &= 0xffff; + return new byte[] { (byte)((crc & 0xFF00) >> 8), (byte)(crc & 0xFF) }; + } + + + public static int crc16(byte[] bytes) { + int crc = 0x0000; + for (byte b : bytes) { + crc = (crc >>> 8) ^ crc16lookup[(crc ^ b) & 0xff]; + } + return crc; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/DateTimeUtil.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/DateTimeUtil.java new file mode 100644 index 0000000000..783553f431 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/DateTimeUtil.java @@ -0,0 +1,278 @@ +package info.nightscout.androidaps.plugins.pump.common.utils; + +/** + * Created by andy on 10/25/18. + */ + +import org.joda.time.LocalDateTime; +import org.joda.time.Minutes; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Calendar; +import java.util.GregorianCalendar; + +import info.nightscout.androidaps.logging.L; + +/** + * This is simple version of ATechDate, limited only to one format (yyyymmddHHMIss) + */ +public class DateTimeUtil { + + private static final Logger LOG = LoggerFactory.getLogger(L.PUMPCOMM); + + /** + * DateTime is packed as long: yyyymmddHHMMss + * + * @param atechDateTime + * @return + */ + public static LocalDateTime toLocalDateTime(long atechDateTime) { + int year = (int) (atechDateTime / 10000000000L); + atechDateTime -= year * 10000000000L; + + int month = (int) (atechDateTime / 100000000L); + atechDateTime -= month * 100000000L; + + int dayOfMonth = (int) (atechDateTime / 1000000L); + atechDateTime -= dayOfMonth * 1000000L; + + int hourOfDay = (int) (atechDateTime / 10000L); + atechDateTime -= hourOfDay * 10000L; + + int minute = (int) (atechDateTime / 100L); + atechDateTime -= minute * 100L; + + int second = (int) atechDateTime; + + try { + return new LocalDateTime(year, month, dayOfMonth, hourOfDay, minute, second); + } catch (Exception ex) { + if (L.isEnabled(L.PUMPCOMM)) + LOG.error("Error creating LocalDateTime from values [atechDateTime={}, year={}, month={}, day={}, hour={}, minute={}, second={}]. Exception: {}", atechDateTime, year, month, dayOfMonth, hourOfDay, minute, second, ex.getMessage()); + //return null; + throw ex; + } + } + + + /** + * DateTime is packed as long: yyyymmddHHMMss + * + * @param atechDateTime + * @return + */ + public static GregorianCalendar toGregorianCalendar(long atechDateTime) { + int year = (int) (atechDateTime / 10000000000L); + atechDateTime -= year * 10000000000L; + + int month = (int) (atechDateTime / 100000000L); + atechDateTime -= month * 100000000L; + + int dayOfMonth = (int) (atechDateTime / 1000000L); + atechDateTime -= dayOfMonth * 1000000L; + + int hourOfDay = (int) (atechDateTime / 10000L); + atechDateTime -= hourOfDay * 10000L; + + int minute = (int) (atechDateTime / 100L); + atechDateTime -= minute * 100L; + + int second = (int) atechDateTime; + + try { + return new GregorianCalendar(year, month - 1, dayOfMonth, hourOfDay, minute, second); + } catch (Exception ex) { + if (L.isEnabled(L.PUMPCOMM)) + LOG.error("DateTimeUtil", String.format("Error creating GregorianCalendar from values [atechDateTime=%d, year=%d, month=%d, day=%d, hour=%d, minute=%d, second=%d]", atechDateTime, year, month, dayOfMonth, hourOfDay, minute, second)); + //return null; + throw ex; + } + } + + + public static long toATechDate(LocalDateTime ldt) { + long atechDateTime = 0L; + + atechDateTime += ldt.getYear() * 10000000000L; + atechDateTime += ldt.getMonthOfYear() * 100000000L; + atechDateTime += ldt.getDayOfMonth() * 1000000L; + atechDateTime += ldt.getHourOfDay() * 10000L; + atechDateTime += ldt.getMinuteOfHour() * 100L; + atechDateTime += ldt.getSecondOfMinute(); + + return atechDateTime; + } + + + public static long toATechDate(GregorianCalendar gc) { + long atechDateTime = 0L; + + atechDateTime += gc.get(Calendar.YEAR) * 10000000000L; + atechDateTime += (gc.get(Calendar.MONTH) + 1) * 100000000L; + atechDateTime += gc.get(Calendar.DAY_OF_MONTH) * 1000000L; + atechDateTime += gc.get(Calendar.HOUR_OF_DAY) * 10000L; + atechDateTime += gc.get(Calendar.MINUTE) * 100L; + atechDateTime += gc.get(Calendar.SECOND); + + return atechDateTime; + } + + + public static boolean isSameDay(LocalDateTime ldt1, LocalDateTime ldt2) { + + return (ldt1.getYear() == ldt2.getYear() && // + ldt1.getMonthOfYear() == ldt2.getMonthOfYear() && // + ldt1.getDayOfMonth() == ldt2.getDayOfMonth()); + + } + + + public static boolean isSameDay(long ldt1, long ldt2) { + + long day1 = ldt1 / 10000L; + long day2 = ldt2 / 10000L; + + return day1 == day2; + } + + + public static long toATechDate(int year, int month, int dayOfMonth, int hour, int minutes, int seconds) { + + long atechDateTime = 0L; + + atechDateTime += year * 10000000000L; + atechDateTime += month * 100000000L; + atechDateTime += dayOfMonth * 1000000L; + atechDateTime += hour * 10000L; + atechDateTime += minutes * 100L; + atechDateTime += seconds; + + return atechDateTime; + } + + +// public static long toATechDate(Date date) { +// +// long atechDateTime = 0L; +// +// atechDateTime += (date.getYear() + 1900) * 10000000000L; +// atechDateTime += (date.getMonth() + 1) * 100000000L; +// atechDateTime += date.getDate() * 1000000L; +// atechDateTime += date.getHours() * 10000L; +// atechDateTime += date.getMinutes() * 100L; +// atechDateTime += date.getSeconds(); +// +// return atechDateTime; +// } + + + public static String toString(long atechDateTime) { + int year = (int) (atechDateTime / 10000000000L); + atechDateTime -= year * 10000000000L; + + int month = (int) (atechDateTime / 100000000L); + atechDateTime -= month * 100000000L; + + int dayOfMonth = (int) (atechDateTime / 1000000L); + atechDateTime -= dayOfMonth * 1000000L; + + int hourOfDay = (int) (atechDateTime / 10000L); + atechDateTime -= hourOfDay * 10000L; + + int minute = (int) (atechDateTime / 100L); + atechDateTime -= minute * 100L; + + int second = (int) atechDateTime; + + return getZeroPrefixed(dayOfMonth) + "." + getZeroPrefixed(month) + "." + year + " " + // + getZeroPrefixed(hourOfDay) + ":" + getZeroPrefixed(minute) + ":" + getZeroPrefixed(second); + } + + + public static String toString(GregorianCalendar gc) { + + return getZeroPrefixed(gc.get(Calendar.DAY_OF_MONTH)) + "." + getZeroPrefixed(gc.get(Calendar.MONTH) + 1) + "." + + gc.get(Calendar.YEAR) + " " + + // + getZeroPrefixed(gc.get(Calendar.HOUR_OF_DAY)) + ":" + getZeroPrefixed(gc.get(Calendar.MINUTE)) + ":" + + getZeroPrefixed(gc.get(Calendar.SECOND)); + } + + + public static String toStringFromTimeInMillis(long timeInMillis) { + + GregorianCalendar gc = new GregorianCalendar(); + gc.setTimeInMillis(timeInMillis); + + return toString(gc); + } + + + private static String getZeroPrefixed(int number) { + return (number < 10) ? "0" + number : "" + number; + } + + + public static int getYear(Long atechDateTime) { + + if (atechDateTime == null || atechDateTime == 0) { + return 2000; + } + + int year = (int) (atechDateTime / 10000000000L); + return year; + } + + + public static boolean isSameDayATDAndMillis(long atechDateTime, long timeInMillis) { + + GregorianCalendar dt = new GregorianCalendar(); + dt.setTimeInMillis(timeInMillis); + + long entryDate = toATechDate(dt); + + return (isSameDay(atechDateTime, entryDate)); + } + + + public static long toMillisFromATD(long atechDateTime) { + + GregorianCalendar gc = toGregorianCalendar(atechDateTime); + + return gc.getTimeInMillis(); + } + + + public static int getATechDateDiferenceAsMinutes(Long date1, Long date2) { + + Minutes minutes = Minutes.minutesBetween(toLocalDateTime(date1), toLocalDateTime(date2)); + + return minutes.getMinutes(); + } + + + public static long getMillisFromATDWithAddedMinutes(long atd, int minutesDiff) { + GregorianCalendar oldestEntryTime = DateTimeUtil.toGregorianCalendar(atd); + oldestEntryTime.add(Calendar.MINUTE, minutesDiff); + + return oldestEntryTime.getTimeInMillis(); + } + + + public static long getATDWithAddedMinutes(long atd, int minutesDiff) { + GregorianCalendar oldestEntryTime = DateTimeUtil.toGregorianCalendar(atd); + oldestEntryTime.add(Calendar.MINUTE, minutesDiff); + + return oldestEntryTime.getTimeInMillis(); + } + + + public static long getATDWithAddedMinutes(GregorianCalendar oldestEntryTime, int minutesDiff) { + oldestEntryTime.add(Calendar.MINUTE, minutesDiff); + + return toATechDate(oldestEntryTime); + } + + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/LocationHelper.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/LocationHelper.java new file mode 100644 index 0000000000..98682679a7 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/LocationHelper.java @@ -0,0 +1,80 @@ +package info.nightscout.androidaps.plugins.pump.common.utils; + +import android.app.Activity; +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.location.LocationManager; +import android.os.Build; + +import info.nightscout.androidaps.R; + +/** + * Helper for checking if location services are enabled on the device. + */ +public class LocationHelper { + + /** + * Determine if GPS is currently enabled. + *

+ * On Android 6 (Marshmallow), location needs to be enabled for Bluetooth discovery to work. + * + * @param context The current app context. + * @return true if location is enabled, false otherwise. + */ + public static boolean isLocationEnabled(Context context) { + LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); + + return (locationManager != null && // + (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) || // + locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER))); + + // return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER); + } + + + /** + * Prompt the user to enable GPS location if it isn't already on. + * + * @param parent The currently visible activity. + */ + public static void requestLocation(final Activity parent) { + if (LocationHelper.isLocationEnabled(parent)) { + return; + } + + // Shamelessly borrowed from http://stackoverflow.com/a/10311877/868533 + + AlertDialog.Builder builder = new AlertDialog.Builder(parent); + builder.setTitle(R.string.location_not_found_title); + builder.setMessage(R.string.location_not_found_message); + builder.setPositiveButton(R.string.location_yes, new DialogInterface.OnClickListener() { + + public void onClick(DialogInterface dialogInterface, int i) { + parent.startActivity(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS)); + } + }); + builder.setNegativeButton(R.string.location_no, null); + builder.create().show(); + } + + + /** + * Prompt the user to enable GPS location on devices that need it for Bluetooth discovery. + *

+ * Android 6 (Marshmallow) needs GPS enabled for Bluetooth discovery to work. + * + * @param activity The currently visible activity. + */ + public static void requestLocationForBluetooth(Activity activity) { + // Location needs to be enabled for Bluetooth discovery on Marshmallow. + LocationHelper.requestLocation(activity); + } + + // public static Boolean locationPermission(ActivityWithMenu act) { + // return ActivityCompat.checkSelfPermission(act, Manifest.permission.ACCESS_FINE_LOCATION) == + // PackageManager.PERMISSION_GRANTED; + // } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/StringUtil.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/StringUtil.java new file mode 100644 index 0000000000..ed7e4e2634 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/StringUtil.java @@ -0,0 +1,121 @@ +package info.nightscout.androidaps.plugins.pump.common.utils; + +import org.joda.time.LocalDateTime; + +import java.nio.charset.Charset; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.List; + +/** + * Created by geoff on 4/28/15. + * modified by Andy + */ +public class StringUtil { + + public static DecimalFormat[] DecimalFormaters = { + new DecimalFormat("#0"), new DecimalFormat("#0.0"), new DecimalFormat("#0.00"), new DecimalFormat("#0.000")}; + + + public static String fromBytes(byte[] ra) { + if (ra == null) + return "null array"; + else + return new String(ra, Charset.forName("UTF-8")); + } + + + // these should go in some project-wide string utils package + public static String join(ArrayList ra, String joiner) { + int sz = ra.size(); + String rval = ""; + int n; + for (n = 0; n < sz; n++) { + rval = rval + ra.get(n); + if (n < sz - 1) { + rval = rval + joiner; + } + } + return rval; + } + + + public static String testJoin() { + ArrayList ra = new ArrayList(); + ra.add("one"); + ra.add("two"); + ra.add("three"); + return join(ra, "+"); + } + + + /** + * Append To StringBuilder + * + * @param stringBuilder + * @param stringToAdd + * @param delimiter + * @return + */ + public static void appendToStringBuilder(StringBuilder stringBuilder, String stringToAdd, String delimiter) { + if (stringBuilder.length() > 0) { + stringBuilder.append(delimiter + stringToAdd); + } else { + stringBuilder.append(stringToAdd); + } + } + + + public static String getFormatedValueUS(Number value, int decimals) { + return DecimalFormaters[decimals].format(value).replace(",", "."); + } + + + public static String getLeadingZero(int number, int places) { + String nn = "" + number; + + while (nn.length() < places) { + nn = "0" + nn; + } + + return nn; + } + + + public static String toDateTimeString(LocalDateTime localDateTime) { + return localDateTime.toString("dd.MM.yyyy HH:mm:ss"); + } + + + public static String getStringInLength(String value, int length) { + StringBuilder val = new StringBuilder(value); + + if (val.length() > length) { + return val.substring(0, length); + } + + for (int i = val.length(); i < length; i++) { + val.append(" "); + } + + return val.toString(); + } + + + public static List splitString(String s, int characters) { + + List outString = new ArrayList<>(); + + do { + if (s.length() > characters) { + String token = s.substring(0, characters); + outString.add(token); + s = s.substring(characters); + } + } while (s.length() > characters); + + outString.add(s); + + return outString; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/ThreadUtil.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/ThreadUtil.java new file mode 100644 index 0000000000..d1781da72a --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/ThreadUtil.java @@ -0,0 +1,22 @@ +package info.nightscout.androidaps.plugins.pump.common.utils; + +/** + * Created by geoff on 5/27/16. + */ +public class ThreadUtil { + + public static long getThreadId() { + return Thread.currentThread().getId(); + } + + + public static String getThreadName() { + return Thread.currentThread().getName(); + } + + + public static String sig() { + Thread t = Thread.currentThread(); + return t.getName() + "[" + t.getId() + "]"; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/AbstractDanaRPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/AbstractDanaRPlugin.java similarity index 86% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/AbstractDanaRPlugin.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/AbstractDanaRPlugin.java index c50e635eb8..1a40e449e5 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/AbstractDanaRPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/AbstractDanaRPlugin.java @@ -1,6 +1,7 @@ -package info.nightscout.androidaps.plugins.PumpDanaR; +package info.nightscout.androidaps.plugins.pump.danaR; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; +import androidx.fragment.app.FragmentActivity; import org.json.JSONException; import org.json.JSONObject; @@ -8,6 +9,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Date; +import java.util.List; import info.nightscout.androidaps.BuildConfig; import info.nightscout.androidaps.MainApp; @@ -27,17 +29,21 @@ import info.nightscout.androidaps.interfaces.ProfileInterface; import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; -import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; -import info.nightscout.androidaps.plugins.Overview.notifications.Notification; -import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes; -import info.nightscout.androidaps.plugins.PumpDanaR.services.AbstractDanaRExecutionService; -import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.DecimalFormatter; -import info.nightscout.utils.Round; -import info.nightscout.utils.SP; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.common.ManufacturerType; +import info.nightscout.androidaps.plugins.general.actions.defs.CustomAction; +import info.nightscout.androidaps.plugins.general.actions.defs.CustomActionType; +import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification; +import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; +import info.nightscout.androidaps.plugins.profile.ns.NSProfilePlugin; +import info.nightscout.androidaps.plugins.pump.danaR.comm.RecordTypes; +import info.nightscout.androidaps.plugins.pump.danaR.services.AbstractDanaRExecutionService; +import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; +import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.DecimalFormatter; +import info.nightscout.androidaps.utils.Round; +import info.nightscout.androidaps.utils.SP; /** * Created by mike on 28.01.2018. @@ -73,6 +79,11 @@ public abstract class AbstractDanaRPlugin extends PluginBase implements PumpInte } } + @Override + public void switchAllowed(boolean newState, FragmentActivity activity, PluginType type) { + confirmPumpPluginActivation(newState, activity, type); + } + @Override public boolean isSuspended() { return DanaRPump.getInstance().pumpSuspended; @@ -97,22 +108,22 @@ public abstract class AbstractDanaRPlugin extends PluginBase implements PumpInte if (!isInitialized()) { log.error("setNewBasalProfile not initialized"); Notification notification = new Notification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED, MainApp.gs(R.string.pumpNotInitializedProfileNotSet), Notification.URGENT); - MainApp.bus().post(new EventNewNotification(notification)); + RxBus.INSTANCE.send(new EventNewNotification(notification)); result.comment = MainApp.gs(R.string.pumpNotInitializedProfileNotSet); return result; } else { - MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED)); + RxBus.INSTANCE.send(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED)); } if (!sExecutionService.updateBasalsInPump(profile)) { Notification notification = new Notification(Notification.FAILED_UDPATE_PROFILE, MainApp.gs(R.string.failedupdatebasalprofile), Notification.URGENT); - MainApp.bus().post(new EventNewNotification(notification)); + RxBus.INSTANCE.send(new EventNewNotification(notification)); result.comment = MainApp.gs(R.string.failedupdatebasalprofile); return result; } else { - MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED)); - MainApp.bus().post(new EventDismissNotification(Notification.FAILED_UDPATE_PROFILE)); + RxBus.INSTANCE.send(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED)); + RxBus.INSTANCE.send(new EventDismissNotification(Notification.FAILED_UDPATE_PROFILE)); Notification notification = new Notification(Notification.PROFILE_SET_OK, MainApp.gs(R.string.profile_set_ok), Notification.INFO, 60); - MainApp.bus().post(new EventNewNotification(notification)); + RxBus.INSTANCE.send(new EventNewNotification(notification)); result.success = true; result.enacted = true; result.comment = "OK"; @@ -152,6 +163,12 @@ public abstract class AbstractDanaRPlugin extends PluginBase implements PumpInte return DanaRPump.getInstance().currentBasal; } + @Override + public double getReservoirLevel() { return DanaRPump.getInstance().reservoirRemainingUnits; } + + @Override + public int getBatteryLevel() { return DanaRPump.getInstance().batteryRemaining; } + @Override public void stopBolusDelivering() { if (sExecutionService == null) { @@ -177,8 +194,8 @@ public abstract class AbstractDanaRPlugin extends PluginBase implements PumpInte if (percent > getPumpDescription().maxTempPercent) percent = getPumpDescription().maxTempPercent; long now = System.currentTimeMillis(); - TemporaryBasal runningTB = TreatmentsPlugin.getPlugin().getRealTempBasalFromHistory(now); - if (runningTB != null && runningTB.percentRate == percent && !enforceNew) { + TemporaryBasal activeTemp = TreatmentsPlugin.getPlugin().getRealTempBasalFromHistory(now); + if (activeTemp != null && activeTemp.percentRate == percent && activeTemp.getPlannedRemainingMinutes() > 4 && !enforceNew) { result.enacted = false; result.success = true; result.isTempCancel = false; @@ -367,7 +384,12 @@ public abstract class AbstractDanaRPlugin extends PluginBase implements PumpInte } @Override - public String deviceID() { + public ManufacturerType manufacturer() { + return ManufacturerType.Sooil; + } + + @Override + public String serialNumber() { return DanaRPump.getInstance().serialNumber; } @@ -460,11 +482,33 @@ public abstract class AbstractDanaRPlugin extends PluginBase implements PumpInte if (!veryShort) { ret += "TDD: " + DecimalFormatter.to0Decimal(pump.dailyTotalUnits) + " / " + pump.maxDailyTotalUnits + " U\n"; } - ret += "IOB: " + pump.iob + "U\n"; ret += "Reserv: " + DecimalFormatter.to0Decimal(pump.reservoirRemainingUnits) + "U\n"; ret += "Batt: " + pump.batteryRemaining + "\n"; return ret; } // TODO: daily total constraint + + @Override + public List getCustomActions() { + return null; + } + + + @Override + public void executeCustomAction(CustomActionType customActionType) { + + } + + @Override + public boolean canHandleDST() { + return false; + } + + @Override + public void timeDateOrTimeZoneChanged() { + + } + + } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/BluetoothDevicePreference.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/BluetoothDevicePreference.java similarity index 94% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/BluetoothDevicePreference.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/BluetoothDevicePreference.java index e39fdcfdaa..d02bf4690a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/BluetoothDevicePreference.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/BluetoothDevicePreference.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaR; +package info.nightscout.androidaps.plugins.pump.danaR; import android.bluetooth.*; import android.content.Context; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/DanaRFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/DanaRFragment.kt new file mode 100644 index 0000000000..3f58acf4d2 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/DanaRFragment.kt @@ -0,0 +1,189 @@ +package info.nightscout.androidaps.plugins.pump.danaR + + +import android.content.Intent +import android.os.Bundle +import android.os.Handler +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import info.nightscout.androidaps.MainApp +import info.nightscout.androidaps.R +import info.nightscout.androidaps.activities.TDDStatsActivity +import info.nightscout.androidaps.events.EventExtendedBolusChange +import info.nightscout.androidaps.events.EventPumpStatusChanged +import info.nightscout.androidaps.events.EventTempBasalChange +import info.nightscout.androidaps.interfaces.PluginType +import info.nightscout.androidaps.interfaces.PumpInterface +import info.nightscout.androidaps.logging.L +import info.nightscout.androidaps.plugins.bus.RxBus +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin +import info.nightscout.androidaps.plugins.pump.danaR.activities.DanaRHistoryActivity +import info.nightscout.androidaps.plugins.pump.danaR.activities.DanaRUserOptionsActivity +import info.nightscout.androidaps.plugins.pump.danaR.events.EventDanaRNewStatus +import info.nightscout.androidaps.plugins.pump.danaRKorean.DanaRKoreanPlugin +import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin +import info.nightscout.androidaps.plugins.treatments.fragments.ProfileViewerDialog +import info.nightscout.androidaps.queue.events.EventQueueChanged +import info.nightscout.androidaps.utils.* +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.disposables.CompositeDisposable +import kotlinx.android.synthetic.main.danar_fragment.* +import org.slf4j.LoggerFactory + +class DanaRFragment : Fragment() { + private val log = LoggerFactory.getLogger(L.PUMP) + private var disposable: CompositeDisposable = CompositeDisposable() + + private val loopHandler = Handler() + private lateinit var refreshLoop: Runnable + + init { + refreshLoop = Runnable { + activity?.runOnUiThread { updateGUI() } + loopHandler.postDelayed(refreshLoop, T.mins(1).msecs()) + } + } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle?): View? { + return inflater.inflate(R.layout.danar_fragment, container, false) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + dana_pumpstatus.setBackgroundColor(MainApp.gc(R.color.colorInitializingBorder)) + + danar_history.setOnClickListener { startActivity(Intent(context, DanaRHistoryActivity::class.java)) } + danar_viewprofile.setOnClickListener { + fragmentManager?.let { fragmentManager -> + val args = Bundle() + args.putLong("time", DateUtil.now()) + args.putInt("mode", ProfileViewerDialog.Mode.PUMP_PROFILE.ordinal) + val pvd = ProfileViewerDialog() + pvd.arguments = args + pvd.show(fragmentManager, "ProfileViewDialog") + } + } + danar_stats.setOnClickListener { startActivity(Intent(context, TDDStatsActivity::class.java)) } + danar_user_options.setOnClickListener { startActivity(Intent(context, DanaRUserOptionsActivity::class.java)) } + danar_btconnection.setOnClickListener { + if (L.isEnabled(L.PUMP)) + log.debug("Clicked connect to pump") + DanaRPump.getInstance().lastConnection = 0 + ConfigBuilderPlugin.getPlugin().commandQueue.readStatus("Clicked connect to pump", null) + } + } + + @Synchronized + override fun onResume() { + super.onResume() + loopHandler.postDelayed(refreshLoop, T.mins(1).msecs()) + disposable += RxBus + .toObservable(EventDanaRNewStatus::class.java) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe({ updateGUI() }, { FabricPrivacy.logException(it) }) + disposable += RxBus + .toObservable(EventExtendedBolusChange::class.java) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe({ updateGUI() }, { FabricPrivacy.logException(it) }) + disposable += RxBus + .toObservable(EventTempBasalChange::class.java) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe({ updateGUI() }, { FabricPrivacy.logException(it) }) + disposable += RxBus + .toObservable(EventQueueChanged::class.java) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe({ updateGUI() }, { FabricPrivacy.logException(it) }) + disposable += RxBus + .toObservable(EventPumpStatusChanged::class.java) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe({ + when { + it.sStatus == EventPumpStatusChanged.Status.CONNECTING -> danar_btconnection?.text = "{fa-bluetooth-b spin} " + it.sSecondsElapsed + "s" + it.sStatus == EventPumpStatusChanged.Status.CONNECTED -> danar_btconnection?.text = "{fa-bluetooth}" + it.sStatus == EventPumpStatusChanged.Status.DISCONNECTED -> danar_btconnection?.text = "{fa-bluetooth-b}" + } + if (it.getStatus() != "") { + dana_pumpstatus?.text = it.getStatus() + dana_pumpstatuslayout?.visibility = View.VISIBLE + } else { + dana_pumpstatuslayout?.visibility = View.GONE + } + }, { FabricPrivacy.logException(it) }) + updateGUI() + } + + @Synchronized + override fun onPause() { + super.onPause() + disposable.clear() + loopHandler.removeCallbacks(refreshLoop) + } + + // GUI functions + @Synchronized + internal fun updateGUI() { + if (danar_dailyunits == null) return + val pump = DanaRPump.getInstance() + val plugin: PumpInterface = ConfigBuilderPlugin.getPlugin().activePump ?: return + if (pump.lastConnection != 0L) { + val agoMsec = System.currentTimeMillis() - pump.lastConnection + val agoMin = (agoMsec.toDouble() / 60.0 / 1000.0).toInt() + danar_lastconnection.text = DateUtil.timeString(pump.lastConnection) + " (" + String.format(MainApp.gs(R.string.minago), agoMin) + ")" + SetWarnColor.setColor(danar_lastconnection, agoMin.toDouble(), 16.0, 31.0) + } + if (pump.lastBolusTime != 0L) { + val agoMsec = System.currentTimeMillis() - pump.lastBolusTime + val agoHours = agoMsec.toDouble() / 60.0 / 60.0 / 1000.0 + if (agoHours < 6) + // max 6h back + danar_lastbolus.text = DateUtil.timeString(pump.lastBolusTime) + " " + DateUtil.sinceString(pump.lastBolusTime) + " " + MainApp.gs(R.string.formatinsulinunits, pump.lastBolusAmount) + else + danar_lastbolus.text = "" + } + + danar_dailyunits.text = MainApp.gs(R.string.reservoirvalue, pump.dailyTotalUnits, pump.maxDailyTotalUnits) + SetWarnColor.setColor(danar_dailyunits, pump.dailyTotalUnits, pump.maxDailyTotalUnits * 0.75, pump.maxDailyTotalUnits * 0.9) + danar_basabasalrate.text = "( " + (pump.activeProfile + 1) + " ) " + MainApp.gs(R.string.pump_basebasalrate, plugin.baseBasalRate) + // DanaRPlugin, DanaRKoreanPlugin + if (ConfigBuilderPlugin.getPlugin().activePump!!.isFakingTempsByExtendedBoluses) { + danar_tempbasal.text = TreatmentsPlugin.getPlugin() + .getRealTempBasalFromHistory(System.currentTimeMillis())?.toStringFull() ?: "" + } else { + // v2 plugin + danar_tempbasal.text = TreatmentsPlugin.getPlugin() + .getTempBasalFromHistory(System.currentTimeMillis())?.toStringFull() ?: "" + } + danar_extendedbolus.text = TreatmentsPlugin.getPlugin() + .getExtendedBolusFromHistory(System.currentTimeMillis())?.toString() ?: "" + danar_reservoir.text = MainApp.gs(R.string.reservoirvalue, pump.reservoirRemainingUnits, 300) + SetWarnColor.setColorInverse(danar_reservoir, pump.reservoirRemainingUnits, 50.0, 20.0) + danar_battery.text = "{fa-battery-" + pump.batteryRemaining / 25 + "}" + SetWarnColor.setColorInverse(danar_battery, pump.batteryRemaining.toDouble(), 51.0, 26.0) + danar_iob.text = MainApp.gs(R.string.formatinsulinunits, pump.iob) + if (pump.model != 0 || pump.protocol != 0 || pump.productCode != 0) { + danar_firmware.text = String.format(MainApp.gs(R.string.danar_model), pump.model, pump.protocol, pump.productCode) + } else { + danar_firmware.text = "OLD" + } + danar_basalstep.text = pump.basalStep.toString() + danar_bolusstep.text = pump.bolusStep.toString() + danar_serialnumber.text = pump.serialNumber + val status = ConfigBuilderPlugin.getPlugin().commandQueue.spannedStatus() + if (status.toString() == "") { + danar_queue.visibility = View.GONE + } else { + danar_queue.visibility = View.VISIBLE + danar_queue.text = status + } + //hide user options button if not an RS pump or old firmware + // also excludes pump with model 03 because of untested error + val isKorean = DanaRKoreanPlugin.getPlugin().isEnabled(PluginType.PUMP) + if (isKorean || danar_firmware.text === "OLD" || pump.model == 3) { + danar_user_options.visibility = View.GONE + } + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/DanaRPlugin.java similarity index 85% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPlugin.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/DanaRPlugin.java index dfdca746cb..e9293b39a6 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/DanaRPlugin.java @@ -1,14 +1,10 @@ -package info.nightscout.androidaps.plugins.PumpDanaR; +package info.nightscout.androidaps.plugins.pump.danaR; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.IBinder; -import android.support.v4.app.FragmentActivity; -import android.support.v7.app.AlertDialog; - -import com.squareup.otto.Subscribe; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; @@ -22,19 +18,23 @@ import info.nightscout.androidaps.events.EventPreferenceChange; import info.nightscout.androidaps.interfaces.Constraint; import info.nightscout.androidaps.interfaces.PluginType; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment; -import info.nightscout.androidaps.plugins.PumpCommon.defs.PumpType; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusStartWithSpeed; -import info.nightscout.androidaps.plugins.PumpDanaR.services.DanaRExecutionService; -import info.nightscout.androidaps.plugins.Treatments.Treatment; -import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; -import info.nightscout.utils.Round; -import info.nightscout.utils.SP; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.pump.common.defs.PumpType; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgBolusStartWithSpeed; +import info.nightscout.androidaps.plugins.pump.danaR.services.DanaRExecutionService; +import info.nightscout.androidaps.plugins.treatments.Treatment; +import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; +import info.nightscout.androidaps.utils.FabricPrivacy; +import info.nightscout.androidaps.utils.Round; +import info.nightscout.androidaps.utils.SP; +import io.reactivex.disposables.CompositeDisposable; +import io.reactivex.schedulers.Schedulers; /** * Created by mike on 05.08.2016. */ public class DanaRPlugin extends AbstractDanaRPlugin { + private CompositeDisposable disposable = new CompositeDisposable(); private static DanaRPlugin plugin = null; @@ -50,35 +50,32 @@ public class DanaRPlugin extends AbstractDanaRPlugin { pumpDescription.setPumpDescription(PumpType.DanaR); } - @Override - public void switchAllowed(ConfigBuilderFragment.PluginViewHolder.PluginSwitcher pluginSwitcher, FragmentActivity context) { - boolean allowHardwarePump = SP.getBoolean("allow_hardware_pump", false); - if (allowHardwarePump || context == null) { - pluginSwitcher.invoke(); - } else { - AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setMessage(R.string.allow_hardware_pump_text) - .setPositiveButton(R.string.yes, (dialog, id) -> { - pluginSwitcher.invoke(); - SP.putBoolean("allow_hardware_pump", true); - if (L.isEnabled(L.PUMP)) - log.debug("First time HW pump allowed!"); - }) - .setNegativeButton(R.string.cancel, (dialog, id) -> { - pluginSwitcher.cancel(); - if (L.isEnabled(L.PUMP)) - log.debug("User does not allow switching to HW pump!"); - }); - builder.create().show(); - } - } - @Override protected void onStart() { Context context = MainApp.instance().getApplicationContext(); Intent intent = new Intent(context, DanaRExecutionService.class); context.bindService(intent, mConnection, Context.BIND_AUTO_CREATE); - MainApp.bus().register(this); + disposable.add(RxBus.INSTANCE + .toObservable(EventPreferenceChange.class) + .observeOn(Schedulers.io()) + .subscribe(event -> { + if (isEnabled(PluginType.PUMP)) { + boolean previousValue = useExtendedBoluses; + useExtendedBoluses = SP.getBoolean(R.string.key_danar_useextended, false); + + if (useExtendedBoluses != previousValue && TreatmentsPlugin.getPlugin().isInHistoryExtendedBoluslInProgress()) { + sExecutionService.extendedBolusStop(); + } + } + }, FabricPrivacy::logException) + ); + disposable.add(RxBus.INSTANCE + .toObservable(EventAppExit.class) + .observeOn(Schedulers.io()) + .subscribe(event -> { + MainApp.instance().getApplicationContext().unbindService(mConnection); + }, FabricPrivacy::logException) + ); super.onStart(); } @@ -87,7 +84,8 @@ public class DanaRPlugin extends AbstractDanaRPlugin { Context context = MainApp.instance().getApplicationContext(); context.unbindService(mConnection); - MainApp.bus().unregister(this); + disposable.clear(); + super.onStop(); } private ServiceConnection mConnection = new ServiceConnection() { @@ -106,24 +104,6 @@ public class DanaRPlugin extends AbstractDanaRPlugin { } }; - @SuppressWarnings("UnusedParameters") - @Subscribe - public void onStatusEvent(final EventAppExit e) { - MainApp.instance().getApplicationContext().unbindService(mConnection); - } - - @Subscribe - public void onStatusEvent(final EventPreferenceChange s) { - if (isEnabled(PluginType.PUMP)) { - boolean previousValue = useExtendedBoluses; - useExtendedBoluses = SP.getBoolean(R.string.key_danar_useextended, false); - - if (useExtendedBoluses != previousValue && TreatmentsPlugin.getPlugin().isInHistoryExtendedBoluslInProgress()) { - sExecutionService.extendedBolusStop(); - } - } - } - // Plugin base interface @Override public String getName() { @@ -262,7 +242,7 @@ public class DanaRPlugin extends AbstractDanaRPlugin { // Correct basal already set ? if (L.isEnabled(L.PUMP)) log.debug("setTempBasalAbsolute: currently running: " + activeTemp.toString()); - if (activeTemp.percentRate == percentRate) { + if (activeTemp.percentRate == percentRate && activeTemp.getPlannedRemainingMinutes() > 4) { if (enforceNew) { cancelTempBasal(true); } else { @@ -360,6 +340,11 @@ public class DanaRPlugin extends AbstractDanaRPlugin { return result; } + @Override + public PumpType model() { + return PumpType.DanaR; + } + private PumpEnactResult cancelRealTempBasal() { PumpEnactResult result = new PumpEnactResult(); TemporaryBasal runningTB = TreatmentsPlugin.getPlugin().getTempBasalFromHistory(System.currentTimeMillis()); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPump.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/DanaRPump.java similarity index 98% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPump.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/DanaRPump.java index df9b48f795..baa636ea81 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPump.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/DanaRPump.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaR; +package info.nightscout.androidaps.plugins.pump.danaR; import org.json.JSONArray; import org.json.JSONException; @@ -7,14 +7,13 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.text.DecimalFormat; -import java.util.Date; import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.R; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.ProfileStore; import info.nightscout.androidaps.logging.L; -import info.nightscout.utils.SP; +import info.nightscout.androidaps.utils.SP; /** * Created by mike on 04.07.2016. diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/SerialIOThread.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/SerialIOThread.java similarity index 87% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/SerialIOThread.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/SerialIOThread.java index a319353d63..782ec42eed 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/SerialIOThread.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/SerialIOThread.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaR; +package info.nightscout.androidaps.plugins.pump.danaR; import android.bluetooth.BluetoothSocket; import android.os.SystemClock; @@ -11,10 +11,10 @@ import java.io.InputStream; import java.io.OutputStream; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageHashTable; -import info.nightscout.androidaps.plugins.PumpDanaR.services.AbstractSerialIOThread; -import info.nightscout.utils.CRC; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MessageBase; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MessageHashTableBase; +import info.nightscout.androidaps.plugins.pump.danaR.services.AbstractSerialIOThread; +import info.nightscout.androidaps.utils.CRC; /** * Created by mike on 17.07.2016. @@ -30,9 +30,11 @@ public class SerialIOThread extends AbstractSerialIOThread { private byte[] mReadBuff = new byte[0]; private MessageBase processedMessage; + private MessageHashTableBase hashTable; - public SerialIOThread(BluetoothSocket rfcommSocket) { + public SerialIOThread(BluetoothSocket rfcommSocket, MessageHashTableBase hashTable) { super(); + this.hashTable = hashTable; mRfCommSocket = rfcommSocket; try { @@ -68,11 +70,11 @@ public class SerialIOThread extends AbstractSerialIOThread { message = processedMessage; } else { // get it from hash table - message = MessageHashTable.findMessage(command); + message = hashTable.findMessage(command); } if (L.isEnabled(L.PUMPBTCOMM)) - log.debug("<<<<< " + message.getMessageName() + " " + message.toHexString(extractedBuff)); + log.debug("<<<<< " + message.getMessageName() + " " + MessageBase.toHexString(extractedBuff)); // process the message content message.received = true; @@ -83,14 +85,14 @@ public class SerialIOThread extends AbstractSerialIOThread { } } } catch (Exception e) { - if (e.getMessage().indexOf("bt socket closed") < 0) + if (!e.getMessage().contains("bt socket closed")) log.error("Thread exception: ", e); mKeepRunning = false; } disconnect("EndOfLoop"); } - void appendToBuffer(byte[] newData, int gotBytes) { + private void appendToBuffer(byte[] newData, int gotBytes) { // add newData to mReadBuff byte[] newReadBuff = new byte[mReadBuff.length + gotBytes]; System.arraycopy(mReadBuff, 0, newReadBuff, 0, mReadBuff.length); @@ -98,7 +100,7 @@ public class SerialIOThread extends AbstractSerialIOThread { mReadBuff = newReadBuff; } - byte[] cutMessageFromBuffer() { + private byte[] cutMessageFromBuffer() { if (mReadBuff[0] == (byte) 0x7E && mReadBuff[1] == (byte) 0x7E) { int length = (mReadBuff[2] & 0xFF) + 7; // Check if we have enough data @@ -148,7 +150,7 @@ public class SerialIOThread extends AbstractSerialIOThread { byte[] messageBytes = message.getRawMessageBytes(); if (L.isEnabled(L.PUMPBTCOMM)) - log.debug(">>>>> " + message.getMessageName() + " " + message.toHexString(messageBytes)); + log.debug(">>>>> " + message.getMessageName() + " " + MessageBase.toHexString(messageBytes)); try { mOutputStream.write(messageBytes); @@ -165,8 +167,10 @@ public class SerialIOThread extends AbstractSerialIOThread { } SystemClock.sleep(200); - if (!message.received) { - log.warn("Reply not received " + message.getMessageName()); + if (!message.isReceived()) { + message.handleMessageNotReceived(); + if (L.isEnabled(L.PUMPBTCOMM)) + log.error("Reply not received " + message.getMessageName()); if (message.getCommand() == 0xF0F1) { DanaRPump.getInstance().isNewPump = false; if (L.isEnabled(L.PUMPCOMM)) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/activities/DanaRHistoryActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/activities/DanaRHistoryActivity.java similarity index 72% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/activities/DanaRHistoryActivity.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/activities/DanaRHistoryActivity.java index 5a3e127b9a..f20a74b024 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/activities/DanaRHistoryActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/activities/DanaRHistoryActivity.java @@ -1,12 +1,6 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.activities; +package info.nightscout.androidaps.plugins.pump.danaR.activities; -import android.app.Activity; import android.os.Bundle; -import android.os.Handler; -import android.os.HandlerThread; -import android.support.v7.widget.CardView; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -16,7 +10,10 @@ import android.widget.Button; import android.widget.Spinner; import android.widget.TextView; -import com.squareup.otto.Subscribe; +import androidx.annotation.NonNull; +import androidx.cardview.widget.CardView; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -27,33 +24,36 @@ import java.util.List; import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.activities.NoSplashActivity; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.db.DanaRHistoryRecord; import info.nightscout.androidaps.events.EventPumpStatusChanged; import info.nightscout.androidaps.interfaces.PluginType; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes; -import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRSyncStatus; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; -import info.nightscout.androidaps.plugins.PumpDanaRS.DanaRSPlugin; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; +import info.nightscout.androidaps.plugins.pump.danaR.comm.RecordTypes; +import info.nightscout.androidaps.plugins.pump.danaR.events.EventDanaRSyncStatus; +import info.nightscout.androidaps.plugins.pump.danaRKorean.DanaRKoreanPlugin; +import info.nightscout.androidaps.plugins.pump.danaRS.DanaRSPlugin; import info.nightscout.androidaps.queue.Callback; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.DecimalFormatter; -import info.nightscout.utils.ToastUtils; +import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.DecimalFormatter; +import info.nightscout.androidaps.utils.FabricPrivacy; +import info.nightscout.androidaps.utils.ToastUtils; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.CompositeDisposable; -public class DanaRHistoryActivity extends Activity { +public class DanaRHistoryActivity extends NoSplashActivity { private static Logger log = LoggerFactory.getLogger(L.PUMP); - - private Handler mHandler; + private CompositeDisposable disposable = new CompositeDisposable(); static Profile profile = null; Spinner historyTypeSpinner; TextView statusView; Button reloadButton; - Button syncButton; RecyclerView recyclerView; LinearLayoutManager llm; @@ -69,6 +69,7 @@ public class DanaRHistoryActivity extends Activity { this.name = name; } + @NonNull @Override public String toString() { return name; @@ -77,34 +78,43 @@ public class DanaRHistoryActivity extends Activity { public DanaRHistoryActivity() { super(); - HandlerThread mHandlerThread = new HandlerThread(DanaRHistoryActivity.class.getSimpleName()); - mHandlerThread.start(); - this.mHandler = new Handler(mHandlerThread.getLooper()); } @Override protected void onResume() { super.onResume(); - MainApp.bus().register(this); + disposable.add(RxBus.INSTANCE + .toObservable(EventPumpStatusChanged.class) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(event -> statusView.setText(event.getStatus()), FabricPrivacy::logException) + ); + disposable.add(RxBus.INSTANCE + .toObservable(EventDanaRSyncStatus.class) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(event -> { + if (L.isEnabled(L.PUMP)) + log.debug("EventDanaRSyncStatus: " + event.getMessage()); + statusView.setText(event.getMessage()); + }, FabricPrivacy::logException) + ); } @Override protected void onPause() { super.onPause(); - MainApp.bus().unregister(this); + disposable.clear(); } @Override - protected void onCreate(Bundle savedInstanceState) { + public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.danar_historyactivity); - historyTypeSpinner = (Spinner) findViewById(R.id.danar_historytype); - statusView = (TextView) findViewById(R.id.danar_historystatus); - reloadButton = (Button) findViewById(R.id.danar_historyreload); - syncButton = (Button) findViewById(R.id.danar_historysync); - recyclerView = (RecyclerView) findViewById(R.id.danar_history_recyclerview); + historyTypeSpinner = findViewById(R.id.danar_historytype); + statusView = findViewById(R.id.danar_historystatus); + reloadButton = findViewById(R.id.danar_historyreload); + recyclerView = findViewById(R.id.danar_history_recyclerview); recyclerView.setHasFixedSize(true); llm = new LinearLayoutManager(this); @@ -144,7 +154,6 @@ public class DanaRHistoryActivity extends Activity { final TypeList selected = (TypeList) historyTypeSpinner.getSelectedItem(); runOnUiThread(() -> { reloadButton.setVisibility(View.GONE); - syncButton.setVisibility(View.GONE); statusView.setVisibility(View.VISIBLE); }); clearCardView(); @@ -154,37 +163,12 @@ public class DanaRHistoryActivity extends Activity { loadDataFromDB(selected.type); runOnUiThread(() -> { reloadButton.setVisibility(View.VISIBLE); - syncButton.setVisibility(View.VISIBLE); statusView.setVisibility(View.GONE); }); } }); }); - syncButton.setOnClickListener(v -> mHandler.post(new Runnable() { - @Override - public void run() { - runOnUiThread(new Runnable() { - @Override - public void run() { - reloadButton.setVisibility(View.GONE); - syncButton.setVisibility(View.GONE); - statusView.setVisibility(View.VISIBLE); - } - }); - DanaRNSHistorySync sync = new DanaRNSHistorySync(historyList); - sync.sync(DanaRNSHistorySync.SYNC_ALL); - runOnUiThread(new Runnable() { - @Override - public void run() { - reloadButton.setVisibility(View.VISIBLE); - syncButton.setVisibility(View.VISIBLE); - statusView.setVisibility(View.GONE); - } - }); - } - })); - historyTypeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView parent, View view, int position, long id) { @@ -213,14 +197,15 @@ public class DanaRHistoryActivity extends Activity { this.historyList = historyList; } + @NonNull @Override - public HistoryViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { + public HistoryViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) { View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.danar_history_item, viewGroup, false); return new HistoryViewHolder(v); } @Override - public void onBindViewHolder(HistoryViewHolder holder, int position) { + public void onBindViewHolder(@NonNull HistoryViewHolder holder, int position) { DanaRHistoryRecord record = historyList.get(position); holder.time.setText(DateUtil.dateAndTimeString(record.recordDate)); holder.value.setText(DecimalFormatter.to2Decimal(record.recordValue)); @@ -305,7 +290,7 @@ public class DanaRHistoryActivity extends Activity { } @Override - public void onAttachedToRecyclerView(RecyclerView recyclerView) { + public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) { super.onAttachedToRecyclerView(recyclerView); } @@ -323,16 +308,16 @@ public class DanaRHistoryActivity extends Activity { HistoryViewHolder(View itemView) { super(itemView); - cv = (CardView) itemView.findViewById(R.id.danar_history_cardview); - time = (TextView) itemView.findViewById(R.id.danar_history_time); - value = (TextView) itemView.findViewById(R.id.danar_history_value); - bolustype = (TextView) itemView.findViewById(R.id.danar_history_bolustype); - stringvalue = (TextView) itemView.findViewById(R.id.danar_history_stringvalue); - duration = (TextView) itemView.findViewById(R.id.danar_history_duration); - dailybasal = (TextView) itemView.findViewById(R.id.danar_history_dailybasal); - dailybolus = (TextView) itemView.findViewById(R.id.danar_history_dailybolus); - dailytotal = (TextView) itemView.findViewById(R.id.danar_history_dailytotal); - alarm = (TextView) itemView.findViewById(R.id.danar_history_alarm); + cv = itemView.findViewById(R.id.danar_history_cardview); + time = itemView.findViewById(R.id.danar_history_time); + value = itemView.findViewById(R.id.danar_history_value); + bolustype = itemView.findViewById(R.id.danar_history_bolustype); + stringvalue = itemView.findViewById(R.id.danar_history_stringvalue); + duration = itemView.findViewById(R.id.danar_history_duration); + dailybasal = itemView.findViewById(R.id.danar_history_dailybasal); + dailybolus = itemView.findViewById(R.id.danar_history_dailybolus); + dailytotal = itemView.findViewById(R.id.danar_history_dailytotal); + alarm = itemView.findViewById(R.id.danar_history_alarm); } } } @@ -347,21 +332,4 @@ public class DanaRHistoryActivity extends Activity { historyList = new ArrayList<>(); runOnUiThread(() -> recyclerView.swapAdapter(new RecyclerViewAdapter(historyList), false)); } - - @Subscribe - public void onStatusEvent(final EventDanaRSyncStatus s) { - if (L.isEnabled(L.PUMP)) - log.debug("EventDanaRSyncStatus: " + s.message); - runOnUiThread( - () -> statusView.setText(s.message)); - } - - @Subscribe - public void onStatusEvent(final EventPumpStatusChanged s) { - runOnUiThread( - () -> statusView.setText(s.textStatus()) - ); - } - - } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/activities/DanaRNSHistorySync.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/activities/DanaRNSHistorySync.java similarity index 85% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/activities/DanaRNSHistorySync.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/activities/DanaRNSHistorySync.java index eab9e8bc6e..dcb182a0d6 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/activities/DanaRNSHistorySync.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/activities/DanaRNSHistorySync.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.activities; +package info.nightscout.androidaps.plugins.pump.danaR.activities; import org.json.JSONException; import org.json.JSONObject; @@ -14,11 +14,12 @@ import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.db.CareportalEvent; import info.nightscout.androidaps.db.DanaRHistoryRecord; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes; -import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRSyncStatus; -import info.nightscout.utils.DateUtil; -import info.nightscout.androidaps.plugins.NSClientInternal.NSUpload; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; +import info.nightscout.androidaps.plugins.pump.danaR.comm.RecordTypes; +import info.nightscout.androidaps.plugins.pump.danaR.events.EventDanaRSyncStatus; +import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.plugins.general.nsclient.NSUpload; /** * Created by mike on 20.07.2016. @@ -28,13 +29,13 @@ public class DanaRNSHistorySync { private static Logger log = LoggerFactory.getLogger(L.PUMP); private List historyRecords; - public final static int SYNC_BOLUS = 0b00000001; - public final static int SYNC_ERROR = 0b00000010; - public final static int SYNC_REFILL = 0b00000100; - public final static int SYNC_GLUCOSE = 0b00001000; - public final static int SYNC_CARBO = 0b00010000; - public final static int SYNC_ALARM = 0b00100000; - public final static int SYNC_BASALHOURS = 0b01000000; + private final static int SYNC_BOLUS = 0b00000001; + private final static int SYNC_ERROR = 0b00000010; + private final static int SYNC_REFILL = 0b00000100; + private final static int SYNC_GLUCOSE = 0b00001000; + private final static int SYNC_CARBO = 0b00010000; + private final static int SYNC_ALARM = 0b00100000; + private final static int SYNC_BASALHOURS = 0b01000000; public final static int SYNC_ALL = 0b11111111; public final static String DANARSIGNATURE = "DANARMESSAGE"; @@ -52,13 +53,13 @@ public class DanaRNSHistorySync { long uploaded = 0; if (L.isEnabled(L.PUMP)) log.debug("Database contains " + records + " records"); - EventDanaRSyncStatus ev = new EventDanaRSyncStatus(); + EventDanaRSyncStatus ev = new EventDanaRSyncStatus(""); for (DanaRHistoryRecord record : historyRecords) { processing++; if (record._id != null) continue; //log.debug(record.bytes); JSONObject nsrec = new JSONObject(); - ev.message = MainApp.gs(R.string.uploading) + " " + processing + "/" + records + " "; // TODO: translations + ev.setMessage(MainApp.gs(R.string.uploading) + " " + processing + "/" + records + " "); // TODO: translations switch (record.recordCode) { case RecordTypes.RECORD_TYPE_BOLUS: if ((what & SYNC_BOLUS) == 0) break; @@ -73,7 +74,7 @@ public class DanaRNSHistorySync { nsrec.put("enteredBy", "openaps://" + MainApp.gs(R.string.app_name)); NSUpload.uploadCareportalEntryToNS(nsrec); uploaded++; - ev.message += MainApp.gs(R.string.danar_sbolus); + ev.setMessage(ev.getMessage() + MainApp.gs(R.string.danar_sbolus)); break; case "E": if (record.recordDuration > 0) { @@ -92,7 +93,7 @@ public class DanaRNSHistorySync { nsrec.put("enteredBy", "openaps://" + MainApp.gs(R.string.app_name)); NSUpload.uploadCareportalEntryToNS(nsrec); uploaded++; - ev.message += MainApp.gs(R.string.danar_ebolus); + ev.setMessage(ev.getMessage() + MainApp.gs(R.string.danar_ebolus)); } else { if (L.isEnabled(L.PUMP)) log.debug("NOT Syncing extended bolus record " + record.recordValue + "U " + DateUtil.toISOString(record.recordDate) + " zero duration"); @@ -110,7 +111,7 @@ public class DanaRNSHistorySync { nsrec.put("enteredBy", "openaps://" + MainApp.gs(R.string.app_name)); NSUpload.uploadCareportalEntryToNS(nsrec); uploaded++; - ev.message += MainApp.gs(R.string.danar_dsbolus); + ev.setMessage(ev.getMessage() + MainApp.gs(R.string.danar_dsbolus)); break; case "DE": if (L.isEnabled(L.PUMP)) @@ -127,7 +128,7 @@ public class DanaRNSHistorySync { nsrec.put("enteredBy", "openaps://" + MainApp.gs(R.string.app_name)); NSUpload.uploadCareportalEntryToNS(nsrec); uploaded++; - ev.message += MainApp.gs(R.string.danar_debolus); + ev.setMessage(ev.getMessage() + MainApp.gs(R.string.danar_debolus)); break; default: log.error("Unknown bolus record"); @@ -145,7 +146,7 @@ public class DanaRNSHistorySync { nsrec.put("enteredBy", "openaps://" + MainApp.gs(R.string.app_name)); NSUpload.uploadCareportalEntryToNS(nsrec); uploaded++; - ev.message += MainApp.gs(R.string.danar_error); + ev.setMessage(ev.getMessage() + MainApp.gs(R.string.danar_error)); break; case RecordTypes.RECORD_TYPE_REFILL: if ((what & SYNC_REFILL) == 0) break; @@ -158,7 +159,7 @@ public class DanaRNSHistorySync { nsrec.put("enteredBy", "openaps://" + MainApp.gs(R.string.app_name)); NSUpload.uploadCareportalEntryToNS(nsrec); uploaded++; - ev.message += MainApp.gs(R.string.danar_refill); + ev.setMessage(ev.getMessage() + MainApp.gs(R.string.danar_refill)); break; case RecordTypes.RECORD_TYPE_BASALHOUR: if ((what & SYNC_BASALHOURS) == 0) break; @@ -172,7 +173,7 @@ public class DanaRNSHistorySync { nsrec.put("enteredBy", "openaps://" + MainApp.gs(R.string.app_name)); NSUpload.uploadCareportalEntryToNS(nsrec); uploaded++; - ev.message += MainApp.gs(R.string.danar_basalhour); + ev.setMessage(ev.getMessage() + MainApp.gs(R.string.danar_basalhour)); break; case RecordTypes.RECORD_TYPE_TB: //log.debug("Ignoring TB record " + record.bytes + " " + DateUtil.toISOString(record.recordDate)); @@ -189,7 +190,7 @@ public class DanaRNSHistorySync { nsrec.put("enteredBy", "openaps://" + MainApp.gs(R.string.app_name)); NSUpload.uploadCareportalEntryToNS(nsrec); uploaded++; - ev.message += MainApp.gs(R.string.danar_glucose); + ev.setMessage(ev.getMessage() + MainApp.gs(R.string.danar_glucose)); break; case RecordTypes.RECORD_TYPE_CARBO: if ((what & SYNC_CARBO) == 0) break; @@ -202,7 +203,7 @@ public class DanaRNSHistorySync { nsrec.put("enteredBy", "openaps://" + MainApp.gs(R.string.app_name)); NSUpload.uploadCareportalEntryToNS(nsrec); uploaded++; - ev.message += MainApp.gs(R.string.danar_carbohydrate); + ev.setMessage(ev.getMessage() + MainApp.gs(R.string.danar_carbohydrate)); break; case RecordTypes.RECORD_TYPE_ALARM: if ((what & SYNC_ALARM) == 0) break; @@ -215,7 +216,7 @@ public class DanaRNSHistorySync { nsrec.put("enteredBy", "openaps://" + MainApp.gs(R.string.app_name)); NSUpload.uploadCareportalEntryToNS(nsrec); uploaded++; - ev.message += MainApp.gs(R.string.danar_alarm); + ev.setMessage(ev.getMessage() + MainApp.gs(R.string.danar_alarm)); break; case RecordTypes.RECORD_TYPE_SUSPEND: // TODO: this too case RecordTypes.RECORD_TYPE_DAILY: @@ -226,10 +227,10 @@ public class DanaRNSHistorySync { log.error("Unknown record type"); break; } - MainApp.bus().post(ev); + RxBus.INSTANCE.send(ev); } - ev.message = String.format(MainApp.gs(R.string.danar_totaluploaded), uploaded); - MainApp.bus().post(ev); + ev.setMessage(String.format(MainApp.gs(R.string.danar_totaluploaded), uploaded)); + RxBus.INSTANCE.send(ev); } catch (JSONException e) { log.error("Unhandled exception", e); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/activities/DanaRUserOptionsActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/activities/DanaRUserOptionsActivity.java similarity index 80% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/activities/DanaRUserOptionsActivity.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/activities/DanaRUserOptionsActivity.java index d2d08a5d0b..f1181bb7cb 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/activities/DanaRUserOptionsActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/activities/DanaRUserOptionsActivity.java @@ -1,14 +1,11 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.activities; +package info.nightscout.androidaps.plugins.pump.danaR.activities; -import android.app.Activity; import android.os.Bundle; import android.widget.Button; import android.widget.RadioButton; import android.widget.RadioGroup; import android.widget.Switch; -import com.squareup.otto.Subscribe; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -17,22 +14,28 @@ import java.text.DecimalFormat; import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.activities.NoSplashActivity; import info.nightscout.androidaps.events.EventInitializationChanged; import info.nightscout.androidaps.interfaces.PluginType; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; -import info.nightscout.androidaps.plugins.PumpDanaRS.DanaRSPlugin; -import info.nightscout.androidaps.plugins.PumpDanaRv2.DanaRv2Plugin; -import info.nightscout.utils.NumberPicker; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPlugin; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaRS.DanaRSPlugin; +import info.nightscout.androidaps.plugins.pump.danaRv2.DanaRv2Plugin; +import info.nightscout.androidaps.utils.FabricPrivacy; +import info.nightscout.androidaps.utils.NumberPicker; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.CompositeDisposable; /** * Created by Rumen Georgiev on 5/31/2018. */ -public class DanaRUserOptionsActivity extends Activity { +public class DanaRUserOptionsActivity extends NoSplashActivity { private static Logger log = LoggerFactory.getLogger(L.PUMP); + private CompositeDisposable disposable = new CompositeDisposable(); Switch timeFormat; Switch buttonScroll; @@ -48,24 +51,28 @@ public class DanaRUserOptionsActivity extends Activity { NumberPicker lowReservoir; Button saveToPumpButton; // This is for Dana pumps only - boolean isRS = MainApp.getSpecificPlugin(DanaRSPlugin.class) != null && MainApp.getSpecificPlugin(DanaRSPlugin.class).isEnabled(PluginType.PUMP); - boolean isDanaR = MainApp.getSpecificPlugin(DanaRPlugin.class) != null && MainApp.getSpecificPlugin(DanaRPlugin.class).isEnabled(PluginType.PUMP); - boolean isDanaRv2 = MainApp.getSpecificPlugin(DanaRv2Plugin.class) != null && MainApp.getSpecificPlugin(DanaRv2Plugin.class).isEnabled(PluginType.PUMP); + boolean isRS = DanaRSPlugin.getPlugin().isEnabled(PluginType.PUMP); + boolean isDanaR = DanaRPlugin.getPlugin().isEnabled(PluginType.PUMP); + boolean isDanaRv2 = DanaRv2Plugin.getPlugin().isEnabled(PluginType.PUMP); @Override - protected void onResume() { + protected synchronized void onResume() { super.onResume(); - MainApp.bus().register(this); + disposable.add(RxBus.INSTANCE + .toObservable(EventInitializationChanged.class) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(event -> setData(), FabricPrivacy::logException) + ); } @Override - protected void onPause() { + protected synchronized void onPause() { + disposable.clear(); super.onPause(); - MainApp.bus().unregister(this); } @Override - protected void onCreate(Bundle savedInstanceState) { + public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.danar_user_options); @@ -97,10 +104,10 @@ public class DanaRUserOptionsActivity extends Activity { + "\npumpUnits:" + pump.units + "\nlowReservoir:" + pump.lowReservoirRate); - screenTimeout.setParams((double) pump.lcdOnTimeSec, 5d, 240d, 5d, new DecimalFormat("1"), false); - backlightTimeout.setParams((double) pump.backlightOnTimeSec, 1d, 60d, 1d, new DecimalFormat("1"), false); - shutdown.setParams((double) pump.shutdownHour, 0d, 24d, 1d, new DecimalFormat("1"), true); - lowReservoir.setParams((double) pump.lowReservoirRate, 10d, 60d, 10d, new DecimalFormat("10"), false); + screenTimeout.setParams((double) pump.lcdOnTimeSec, 5d, 240d, 5d, new DecimalFormat("1"), false, findViewById(R.id.ok)); + backlightTimeout.setParams((double) pump.backlightOnTimeSec, 1d, 60d, 1d, new DecimalFormat("1"), false, findViewById(R.id.ok)); + shutdown.setParams((double) pump.shutdownHour, 0d, 24d, 1d, new DecimalFormat("1"), true, findViewById(R.id.ok)); + lowReservoir.setParams((double) pump.lowReservoirRate, 10d, 60d, 10d, new DecimalFormat("10"), false, findViewById(R.id.ok)); switch (pump.beepAndAlarm) { case 0x01: pumpAlarmSound.setChecked(true); @@ -143,11 +150,6 @@ public class DanaRUserOptionsActivity extends Activity { lowReservoir.setValue((double) pump.lowReservoirRate); } - @Subscribe - public void onEventInitializationChanged(EventInitializationChanged ignored) { - runOnUiThread(this::setData); - } - public void onSaveClick() { if (!isRS && !isDanaR && !isDanaRv2) { //exit if pump is not DanaRS, Dana!, or DanaR with upgraded firmware diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MessageBase.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MessageBase.java similarity index 96% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MessageBase.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MessageBase.java index 0fd444412f..bf2ca4b83b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MessageBase.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MessageBase.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; import android.annotation.TargetApi; import android.os.Build; @@ -13,7 +13,7 @@ import java.util.Date; import java.util.GregorianCalendar; import info.nightscout.androidaps.logging.L; -import info.nightscout.utils.CRC; +import info.nightscout.androidaps.utils.CRC; /* * 00 01 02 03 04 05 06 @@ -105,6 +105,9 @@ public class MessageBase { } } + public void handleMessageNotReceived() { + } + public int getCommand() { int command = byteFromRawBuff(buffer, 5) | (byteFromRawBuff(buffer, 4) << 8); return command; @@ -189,4 +192,8 @@ public class MessageBase { return sb.toString(); } + + public boolean isReceived() { + return received; + } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MessageHashTableBase.kt b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MessageHashTableBase.kt new file mode 100644 index 0000000000..9c524e02a6 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MessageHashTableBase.kt @@ -0,0 +1,6 @@ +package info.nightscout.androidaps.plugins.pump.danaR.comm + +interface MessageHashTableBase { + fun put(message: MessageBase) + fun findMessage(command: Int): MessageBase +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MessageHashTableR.kt b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MessageHashTableR.kt new file mode 100644 index 0000000000..6d3129f5ba --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MessageHashTableR.kt @@ -0,0 +1,69 @@ +package info.nightscout.androidaps.plugins.pump.danaR.comm + +import java.util.* + +object MessageHashTableR : MessageHashTableBase { + var messages: HashMap = HashMap() + + init { + put(MsgBolusStop()) // 0x0101 CMD_MEALINS_STOP + put(MsgBolusStart()) // 0x0102 CMD_MEALINS_START_DATA + put(MsgBolusStartWithSpeed()) // 0x0104 CMD_MEALINS_START_DATA_SPEED + put(MsgBolusProgress()) // 0x0202 CMD_PUMP_THIS_REMAINDER_MEAL_INS + put(MsgStatusProfile()) // 0x0204 CMD_PUMP_CALCULATION_SETTING + put(MsgStatusTempBasal()) // 0x0205 CMD_PUMP_EXERCISE_MODE + put(MsgStatusBolusExtended()) // 0x0207 CMD_PUMP_EXPANS_INS_I + put(MsgStatusBasic()) // 0x020A CMD_PUMP_INITVIEW_I + put(MsgStatus()) // 0x020B CMD_PUMP_STATUS + put(MsgInitConnStatusTime()) // 0x0301 CMD_PUMPINIT_TIME_INFO + put(MsgInitConnStatusBolus()) // 0x0302 CMD_PUMPINIT_BOLUS_INFO + put(MsgInitConnStatusBasic()) // 0x0303 CMD_PUMPINIT_INIT_INFO + put(MsgInitConnStatusOption()) // 0x0304 CMD_PUMPINIT_OPTION + put(MsgSetTempBasalStart()) // 0x0401 CMD_PUMPSET_EXERCISE_S + put(MsgSetCarbsEntry()) // 0x0402 CMD_PUMPSET_HIS_S + put(MsgSetTempBasalStop()) // 0x0403 CMD_PUMPSET_EXERCISE_STOP + put(MsgSetExtendedBolusStop()) // 0x0406 CMD_PUMPSET_EXPANS_INS_STOP + put(MsgSetExtendedBolusStart()) // 0x0407 CMD_PUMPSET_EXPANS_INS_S + put(MsgError()) // 0x0601 CMD_PUMPOWAY_SYSTEM_STATUS + put(MsgPCCommStart()) // 0x3001 CMD_CONNECT + put(MsgPCCommStop()) // 0x3002 CMD_DISCONNECT + put(MsgHistoryBolus()) // 0x3101 CMD_HISTORY_MEAL_INS + put(MsgHistoryDailyInsulin()) // 0x3102 CMD_HISTORY_DAY_INS + put(MsgHistoryGlucose()) // 0x3104 CMD_HISTORY_GLUCOSE + put(MsgHistoryAlarm()) // 0x3105 CMD_HISTORY_ALARM + put(MsgHistoryError()) // 0x3106 CMD_HISTORY_ERROR + put(MsgHistoryCarbo()) // 0x3107 CMD_HISTORY_CARBOHY + put(MsgHistoryRefill()) // 0x3108 CMD_HISTORY_REFILL + put(MsgHistorySuspend()) // 0x3109 CMD_HISTORY_SUSPEND + put(MsgHistoryBasalHour()) // 0x310A CMD_HISTORY_BASAL_HOUR + put(MsgHistoryDone()) // 0x31F1 CMD_HISTORY_DONT_USED + put(MsgSettingBasal()) // 0x3202 CMD_SETTING_V_BASAL_INS_I + put(MsgSettingMeal()) // 0x3203 CMD_SETTING_V_MEAL_SETTING_I + put(MsgSettingProfileRatios()) // 0x3204 CMD_SETTING_V_CCC_I + put(MsgSettingMaxValues()) // 0x3205 CMD_SETTING_V_MAX_VALUE_I + put(MsgSettingBasalProfileAll()) // 0x3206 CMD_SETTING_V_BASAL_PROFILE_ALL + put(MsgSettingShippingInfo()) // 0x3207 CMD_SETTING_V_SHIPPING_I + put(MsgSettingGlucose()) // 0x3209 CMD_SETTING_V_GLUCOSEandEASY + put(MsgSettingPumpTime()) // 0x320A CMD_SETTING_V_TIME_I + put(MsgSettingUserOptions()) // 0x320B CMD_SETTING_V_USER_OPTIONS + put(MsgSettingActiveProfile()) // 0x320C CMD_SETTING_V_PROFILE_NUMBER + put(MsgSettingProfileRatiosAll()) // 0x320D CMD_SETTING_V_CIR_CF_VALUE + put(MsgSetSingleBasalProfile()) // 0x3302 CMD_SETTING_BASAL_INS_S + put(MsgSetBasalProfile()) // 0x3306 CMD_SETTING_BASAL_PROFILE_S + put(MsgSetUserOptions()) // 0x330B CMD_SETTING_USER_OPTIONS_S + put(MsgSetActivateBasalProfile()) // 0x330C CMD_SETTING_PROFILE_NUMBER_S + put(MsgHistoryAllDone()) // 0x41F1 CMD_HISTORY_ALL_DONE + put(MsgHistoryAll()) // 0x41F2 CMD_HISTORY_ALL + put(MsgHistoryNewDone()) // 0x42F1 CMD_HISTORY_NEW_DONE + put(MsgHistoryNew()) // 0x42F2 CMD_HISTORY_NEW + put(MsgCheckValue()) // 0xF0F1 CMD_PUMP_CHECK_VALUE + } + + override fun put(message: MessageBase) { + messages[message.command] = message + } + + override fun findMessage(command: Int): MessageBase { + return messages[command] ?: MessageBase() + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MessageOriginalNames.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MessageOriginalNames.java similarity index 99% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MessageOriginalNames.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MessageOriginalNames.java index a285ce5120..2cba96f838 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MessageOriginalNames.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MessageOriginalNames.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusProgress.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgBolusProgress.java similarity index 69% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusProgress.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgBolusProgress.java index 873824f966..362b72c929 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusProgress.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgBolusProgress.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -6,8 +6,9 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress; -import info.nightscout.androidaps.plugins.Treatments.Treatment; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress; +import info.nightscout.androidaps.plugins.treatments.Treatment; public class MsgBolusProgress extends MessageBase { private static Logger log = LoggerFactory.getLogger(L.PUMPCOMM); @@ -37,15 +38,15 @@ public class MsgBolusProgress extends MessageBase { lastReceive = System.currentTimeMillis(); Double done = (amount * 100 - progress) / 100d; t.insulin = done; - EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance(); - bolusingEvent.status = String.format(MainApp.gs(R.string.bolusdelivering), done); - bolusingEvent.t = t; - bolusingEvent.percent = Math.min((int) (done / amount * 100), 100); + EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.INSTANCE; + bolusingEvent.setStatus(String.format(MainApp.gs(R.string.bolusdelivering), done)); + bolusingEvent.setT(t); + bolusingEvent.setPercent(Math.min((int) (done / amount * 100), 100)); if (L.isEnabled(L.PUMPCOMM)) { log.debug("Bolus remaining: " + progress + " delivered: " + done); } - MainApp.bus().post(bolusingEvent); + RxBus.INSTANCE.send(bolusingEvent); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusStart.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgBolusStart.java similarity index 95% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusStart.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgBolusStart.java index 06200d1f0c..4b7cd2ff41 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusStart.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgBolusStart.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusStartWithSpeed.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgBolusStartWithSpeed.java similarity index 95% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusStartWithSpeed.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgBolusStartWithSpeed.java index a3160ff887..0c174807b3 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusStartWithSpeed.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgBolusStartWithSpeed.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusStop.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgBolusStop.java similarity index 66% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusStop.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgBolusStop.java index fe5d47c131..2ea50297fb 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusStop.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgBolusStop.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -6,8 +6,9 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress; -import info.nightscout.androidaps.plugins.Treatments.Treatment; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress; +import info.nightscout.androidaps.plugins.treatments.Treatment; public class MsgBolusStop extends MessageBase { private static Logger log = LoggerFactory.getLogger(L.PUMPCOMM); @@ -35,15 +36,15 @@ public class MsgBolusStop extends MessageBase { public void handleMessage(byte[] bytes) { if (L.isEnabled(L.PUMPCOMM)) log.debug("Messsage received"); - EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance(); + EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.INSTANCE; stopped = true; if (!forced) { t.insulin = amount; - bolusingEvent.status = MainApp.gs(R.string.overview_bolusprogress_delivered); - bolusingEvent.percent = 100; + bolusingEvent.setStatus(MainApp.gs(R.string.overview_bolusprogress_delivered)); + bolusingEvent.setPercent(100); } else { - bolusingEvent.status = MainApp.gs(R.string.overview_bolusprogress_stoped); + bolusingEvent.setStatus(MainApp.gs(R.string.overview_bolusprogress_stoped)); } - MainApp.bus().post(bolusingEvent); + RxBus.INSTANCE.send(bolusingEvent); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgCheckValue.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgCheckValue.java similarity index 81% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgCheckValue.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgCheckValue.java index e04d9243e7..317fe9db81 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgCheckValue.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgCheckValue.java @@ -1,12 +1,12 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPlugin; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; /** * Created by mike on 30.06.2016. @@ -32,7 +32,7 @@ public class MsgCheckValue extends MessageBase { pump.protocol = intFromBuff(bytes, 1, 1); pump.productCode = intFromBuff(bytes, 2, 1); if (pump.model != DanaRPump.EXPORT_MODEL) { - MainApp.getSpecificPlugin(DanaRPlugin.class).disconnect("Wrong Model"); + DanaRPlugin.getPlugin().disconnect("Wrong Model"); log.debug("Wrong model selected"); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgError.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgError.java similarity index 80% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgError.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgError.java index a8e67a98a0..a6fdaa8d0d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgError.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgError.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -6,8 +6,9 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress; -import info.nightscout.androidaps.plugins.NSClientInternal.NSUpload; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress; +import info.nightscout.androidaps.plugins.general.nsclient.NSUpload; public class MsgError extends MessageBase { private static Logger log = LoggerFactory.getLogger(L.PUMPCOMM); @@ -44,10 +45,10 @@ public class MsgError extends MessageBase { } if (errorCode < 8) { // bolus delivering stopped - EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance(); + EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.INSTANCE; MsgBolusStop.stopped = true; - bolusingEvent.status = errorString; - MainApp.bus().post(bolusingEvent); + bolusingEvent.setStatus(errorString); + RxBus.INSTANCE.send(bolusingEvent); failed=true; } if (L.isEnabled(L.PUMPCOMM)) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryAlarm.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgHistoryAlarm.java similarity index 88% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryAlarm.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgHistoryAlarm.java index 7adb335e93..8abbf55c31 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryAlarm.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgHistoryAlarm.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryAll.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgHistoryAll.java similarity index 93% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryAll.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgHistoryAll.java index 0fe64a20f5..955d7fc090 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryAll.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgHistoryAll.java @@ -1,15 +1,14 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.Date; - import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.db.DanaRHistoryRecord; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRSyncStatus; -import info.nightscout.utils.DateUtil; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.pump.danaR.events.EventDanaRSyncStatus; +import info.nightscout.androidaps.utils.DateUtil; public class MsgHistoryAll extends MessageBase { private static Logger log = LoggerFactory.getLogger(L.PUMPCOMM); @@ -35,8 +34,6 @@ public class MsgHistoryAll extends MessageBase { byte paramByte8 = (byte) intFromBuff(bytes, 7, 1); double value = (double) intFromBuff(bytes, 8, 2); - EventDanaRSyncStatus ev = new EventDanaRSyncStatus(); - DanaRHistoryRecord danaRHistoryRecord = new DanaRHistoryRecord(); danaRHistoryRecord.recordCode = recordCode; @@ -147,11 +144,6 @@ public class MsgHistoryAll extends MessageBase { } MainApp.getDbHelper().createOrUpdate(danaRHistoryRecord); - - ev.message = DateUtil.dateAndTimeString(danaRHistoryRecord.recordDate); - ev.message += " " + messageType; - MainApp.bus().post(ev); - - return; + RxBus.INSTANCE.send(new EventDanaRSyncStatus(DateUtil.dateAndTimeString(danaRHistoryRecord.recordDate) + " " + messageType)); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryAllDone.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgHistoryAllDone.java similarity index 91% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryAllDone.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgHistoryAllDone.java index e78771f99d..7b110dd45f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryAllDone.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgHistoryAllDone.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryBasalHour.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgHistoryBasalHour.java similarity index 88% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryBasalHour.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgHistoryBasalHour.java index f56e2af273..2599cc7434 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryBasalHour.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgHistoryBasalHour.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryBolus.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgHistoryBolus.java similarity index 88% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryBolus.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgHistoryBolus.java index d675ddc488..88978be98c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryBolus.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgHistoryBolus.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryCarbo.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgHistoryCarbo.java similarity index 88% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryCarbo.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgHistoryCarbo.java index 6755800bba..5682c3c85f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryCarbo.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgHistoryCarbo.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryDailyInsulin.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgHistoryDailyInsulin.java similarity index 88% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryDailyInsulin.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgHistoryDailyInsulin.java index 68d46f0d20..2bed9419dd 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryDailyInsulin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgHistoryDailyInsulin.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryDone.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgHistoryDone.java similarity index 91% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryDone.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgHistoryDone.java index 63e51e24ba..eeaffd33a2 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryDone.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgHistoryDone.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryError.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgHistoryError.java similarity index 88% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryError.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgHistoryError.java index 8d6d0615d4..0666e8915a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryError.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgHistoryError.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryGlucose.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgHistoryGlucose.java similarity index 88% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryGlucose.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgHistoryGlucose.java index 10fd68e3ab..114d392f40 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryGlucose.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgHistoryGlucose.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryNew.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgHistoryNew.java similarity index 88% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryNew.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgHistoryNew.java index 01f7197434..e93c440fac 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryNew.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgHistoryNew.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryNewDone.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgHistoryNewDone.java similarity index 91% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryNewDone.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgHistoryNewDone.java index fb9118e629..c58f55f2cf 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryNewDone.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgHistoryNewDone.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryRefill.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgHistoryRefill.java similarity index 88% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryRefill.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgHistoryRefill.java index 238a606cfb..1ccae856af 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryRefill.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgHistoryRefill.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistorySuspend.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgHistorySuspend.java similarity index 88% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistorySuspend.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgHistorySuspend.java index 7182722f97..1dac016f4d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistorySuspend.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgHistorySuspend.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusBasic.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgInitConnStatusBasic.java similarity index 96% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusBasic.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgInitConnStatusBasic.java index 61150079cd..9b7d7feaed 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusBasic.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgInitConnStatusBasic.java @@ -1,10 +1,10 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; public class MsgInitConnStatusBasic extends MessageBase { private static Logger log = LoggerFactory.getLogger(L.PUMPCOMM); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusBolus.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgInitConnStatusBolus.java similarity index 70% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusBolus.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgInitConnStatusBolus.java index df9447cc45..79fac775a5 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusBolus.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgInitConnStatusBolus.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -6,10 +6,11 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; -import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; -import info.nightscout.androidaps.plugins.Overview.notifications.Notification; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification; +import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; /** * Created by mike on 28.05.2016. @@ -45,9 +46,9 @@ public class MsgInitConnStatusBolus extends MessageBase { if (!pump.isExtendedBolusEnabled) { Notification notification = new Notification(Notification.EXTENDED_BOLUS_DISABLED, MainApp.gs(R.string.danar_enableextendedbolus), Notification.URGENT); - MainApp.bus().post(new EventNewNotification(notification)); + RxBus.INSTANCE.send(new EventNewNotification(notification)); } else { - MainApp.bus().post(new EventDismissNotification(Notification.EXTENDED_BOLUS_DISABLED)); + RxBus.INSTANCE.send(new EventDismissNotification(Notification.EXTENDED_BOLUS_DISABLED)); } } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusOption.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgInitConnStatusOption.java similarity index 72% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusOption.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgInitConnStatusOption.java index f8f82e16d0..f615b4d559 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusOption.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgInitConnStatusOption.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -6,11 +6,12 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; -import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; -import info.nightscout.androidaps.plugins.Overview.notifications.Notification; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification; +import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; /** * Created by mike on 28.05.2016. @@ -45,13 +46,13 @@ public class MsgInitConnStatusOption extends MessageBase { if (!DanaRPump.getInstance().isPasswordOK()) { Notification notification = new Notification(Notification.WRONG_PUMP_PASSWORD, MainApp.gs(R.string.wrongpumppassword), Notification.URGENT); - MainApp.bus().post(new EventNewNotification(notification)); + RxBus.INSTANCE.send(new EventNewNotification(notification)); } else { - MainApp.bus().post(new EventDismissNotification(Notification.WRONG_PUMP_PASSWORD)); + RxBus.INSTANCE.send(new EventDismissNotification(Notification.WRONG_PUMP_PASSWORD)); } // This is last message of initial sequence - if (ConfigBuilderPlugin.getPlugin().getActivePump() != null ) + if (ConfigBuilderPlugin.getPlugin().getActivePump() != null) ConfigBuilderPlugin.getPlugin().getActivePump().finishHandshaking(); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusTime.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgInitConnStatusTime.java similarity index 50% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusTime.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgInitConnStatusTime.java index 5404c58837..974e63fe80 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusTime.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgInitConnStatusTime.java @@ -1,22 +1,21 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.Date; - import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.events.EventRefreshGui; +import info.nightscout.androidaps.events.EventRebuildTabs; import info.nightscout.androidaps.interfaces.PluginType; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; -import info.nightscout.androidaps.plugins.Overview.notifications.Notification; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; -import info.nightscout.utils.DateUtil; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPlugin; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaRKorean.DanaRKoreanPlugin; +import info.nightscout.androidaps.utils.DateUtil; public class MsgInitConnStatusTime extends MessageBase { private static Logger log = LoggerFactory.getLogger(L.PUMPCOMM); @@ -31,24 +30,24 @@ public class MsgInitConnStatusTime extends MessageBase { public void handleMessage(byte[] bytes) { if (bytes.length - 10 > 7) { Notification notification = new Notification(Notification.WRONG_DRIVER, MainApp.gs(R.string.pumpdrivercorrected), Notification.NORMAL); - MainApp.bus().post(new EventNewNotification(notification)); - MainApp.getSpecificPlugin(DanaRPlugin.class).disconnect("Wrong Model"); + RxBus.INSTANCE.send(new EventNewNotification(notification)); + DanaRPlugin.getPlugin().disconnect("Wrong Model"); log.error("Wrong model selected. Switching to Korean DanaR"); - MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).setPluginEnabled(PluginType.PUMP, true); - MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).setFragmentVisible(PluginType.PUMP, true); - MainApp.getSpecificPlugin(DanaRPlugin.class).setPluginEnabled(PluginType.PUMP, false); - MainApp.getSpecificPlugin(DanaRPlugin.class).setFragmentVisible(PluginType.PUMP, false); + DanaRKoreanPlugin.getPlugin().setPluginEnabled(PluginType.PUMP, true); + DanaRKoreanPlugin.getPlugin().setFragmentVisible(PluginType.PUMP, true); + DanaRPlugin.getPlugin().setPluginEnabled(PluginType.PUMP, false); + DanaRPlugin.getPlugin().setFragmentVisible(PluginType.PUMP, false); DanaRPump.reset(); // mark not initialized //If profile coming from pump, switch it as well - if (MainApp.getSpecificPlugin(DanaRPlugin.class).isEnabled(PluginType.PROFILE)) { - (MainApp.getSpecificPlugin(DanaRPlugin.class)).setPluginEnabled(PluginType.PROFILE, false); - (MainApp.getSpecificPlugin(DanaRKoreanPlugin.class)).setPluginEnabled(PluginType.PROFILE, true); + if (DanaRPlugin.getPlugin().isEnabled(PluginType.PROFILE)) { + (DanaRPlugin.getPlugin()).setPluginEnabled(PluginType.PROFILE, false); + (DanaRKoreanPlugin.getPlugin()).setPluginEnabled(PluginType.PROFILE, true); } ConfigBuilderPlugin.getPlugin().storeSettings("ChangingDanaDriver"); - MainApp.bus().post(new EventRefreshGui()); + RxBus.INSTANCE.send(new EventRebuildTabs()); ConfigBuilderPlugin.getPlugin().getCommandQueue().readStatus("PumpDriverChange", null); // force new connection failed = false; return; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgPCCommStart.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgPCCommStart.java similarity index 89% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgPCCommStart.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgPCCommStart.java index 6f92c3241c..3d2084371c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgPCCommStart.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgPCCommStart.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgPCCommStop.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgPCCommStop.java similarity index 89% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgPCCommStop.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgPCCommStop.java index 255bb17532..e942f6b6e8 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgPCCommStop.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgPCCommStop.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetActivateBasalProfile.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSetActivateBasalProfile.java similarity index 94% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetActivateBasalProfile.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSetActivateBasalProfile.java index 2d222f9601..22f962713b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetActivateBasalProfile.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSetActivateBasalProfile.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetBasalProfile.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSetBasalProfile.java similarity index 77% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetBasalProfile.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSetBasalProfile.java index 3e87e4bf41..89cd1c95f4 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetBasalProfile.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSetBasalProfile.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -6,8 +6,9 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; -import info.nightscout.androidaps.plugins.Overview.notifications.Notification; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; public class MsgSetBasalProfile extends MessageBase { private static Logger log = LoggerFactory.getLogger(L.PUMPCOMM); @@ -37,12 +38,12 @@ public class MsgSetBasalProfile extends MessageBase { if (L.isEnabled(L.PUMPCOMM)) log.debug("Set basal profile result: " + result + " FAILED!!!"); Notification reportFail = new Notification(Notification.PROFILE_SET_FAILED, MainApp.gs(R.string.profile_set_failed), Notification.URGENT); - MainApp.bus().post(new EventNewNotification(reportFail)); + RxBus.INSTANCE.send(new EventNewNotification(reportFail)); } else { if (L.isEnabled(L.PUMPCOMM)) log.debug("Set basal profile result: " + result); Notification reportOK = new Notification(Notification.PROFILE_SET_OK, MainApp.gs(R.string.profile_set_ok), Notification.INFO, 60); - MainApp.bus().post(new EventNewNotification(reportOK)); + RxBus.INSTANCE.send(new EventNewNotification(reportOK)); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetCarbsEntry.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSetCarbsEntry.java similarity index 96% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetCarbsEntry.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSetCarbsEntry.java index 59cbcdafa0..a00b5bfd72 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetCarbsEntry.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSetCarbsEntry.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetExtendedBolusStart.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSetExtendedBolusStart.java similarity index 96% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetExtendedBolusStart.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSetExtendedBolusStart.java index 2577435e11..dad437ac72 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetExtendedBolusStart.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSetExtendedBolusStart.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetExtendedBolusStop.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSetExtendedBolusStop.java similarity index 93% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetExtendedBolusStop.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSetExtendedBolusStop.java index 504db719ea..a19efe7488 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetExtendedBolusStop.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSetExtendedBolusStop.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetSingleBasalProfile.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSetSingleBasalProfile.java similarity index 76% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetSingleBasalProfile.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSetSingleBasalProfile.java index eabf383b94..8888f17b1c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetSingleBasalProfile.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSetSingleBasalProfile.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -6,8 +6,9 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.Overview.notifications.Notification; -import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; +import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification; public class MsgSetSingleBasalProfile extends MessageBase { private static Logger log = LoggerFactory.getLogger(L.PUMPCOMM); @@ -34,12 +35,12 @@ public class MsgSetSingleBasalProfile extends MessageBase { if (L.isEnabled(L.PUMPCOMM)) log.debug("Set basal profile result: " + result + " FAILED!!!"); Notification reportFail = new Notification(Notification.PROFILE_SET_FAILED, MainApp.gs(R.string.profile_set_failed), Notification.URGENT); - MainApp.bus().post(new EventNewNotification(reportFail)); + RxBus.INSTANCE.send(new EventNewNotification(reportFail)); } else { if (L.isEnabled(L.PUMPCOMM)) log.debug("Set basal profile result: " + result); Notification reportOK = new Notification(Notification.PROFILE_SET_OK, MainApp.gs(R.string.profile_set_ok), Notification.INFO, 60); - MainApp.bus().post(new EventNewNotification(reportOK)); + RxBus.INSTANCE.send(new EventNewNotification(reportOK)); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetTempBasalStart.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSetTempBasalStart.java similarity index 95% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetTempBasalStart.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSetTempBasalStart.java index c756af3491..adc6a0b4da 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetTempBasalStart.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSetTempBasalStart.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetTempBasalStop.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSetTempBasalStop.java similarity index 92% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetTempBasalStop.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSetTempBasalStop.java index 7b14e8e3e3..19427ee965 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetTempBasalStop.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSetTempBasalStop.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetTime.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSetTime.java similarity index 88% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetTime.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSetTime.java index 6842344959..2840ff3faa 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetTime.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSetTime.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -6,7 +6,7 @@ import org.slf4j.LoggerFactory; import java.util.Date; import info.nightscout.androidaps.logging.L; -import info.nightscout.utils.DateUtil; +import info.nightscout.androidaps.utils.DateUtil; /** * Created by mike on 09.12.2016. diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetUserOptions.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSetUserOptions.java similarity index 93% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetUserOptions.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSetUserOptions.java index 7484966dba..07e4ff669d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetUserOptions.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSetUserOptions.java @@ -1,10 +1,10 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; /** * Created by mike on 05.07.2016. diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingActiveProfile.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSettingActiveProfile.java similarity index 84% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingActiveProfile.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSettingActiveProfile.java index 57ab6367b0..1776c48a20 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingActiveProfile.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSettingActiveProfile.java @@ -1,10 +1,10 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; /** * Created by mike on 05.07.2016. diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingBasal.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSettingBasal.java similarity index 74% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingBasal.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSettingBasal.java index 899a5a08f0..68dcf089c0 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingBasal.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSettingBasal.java @@ -1,11 +1,13 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.Locale; + import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPlugin; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; /** * Created by mike on 05.07.2016. @@ -31,7 +33,7 @@ public class MsgSettingBasal extends MessageBase { if (L.isEnabled(L.PUMPCOMM)) for (int index = 0; index < 24; index++) { - log.debug("Basal " + String.format("%02d", index) + "h: " + pump.pumpProfiles[pump.activeProfile][index]); + log.debug("Basal " + String.format(Locale.ENGLISH, "%02d", index) + "h: " + pump.pumpProfiles[pump.activeProfile][index]); } } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingBasalProfileAll.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSettingBasalProfileAll.java similarity index 86% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingBasalProfileAll.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSettingBasalProfileAll.java index f231412e06..9c471a3a00 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingBasalProfileAll.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSettingBasalProfileAll.java @@ -1,10 +1,12 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.Locale; + import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; /** @@ -55,7 +57,7 @@ public class MsgSettingBasalProfileAll extends MessageBase { for (int profile = 0; profile < 4; profile++) { for (int index = 0; index < 48; index++) { try { - log.debug("Basal profile " + profile + ": " + String.format("%02d", index) + "h: " + pump.pumpProfiles[profile][index]); + log.debug("Basal profile " + profile + ": " + String.format(Locale.ENGLISH, "%02d", index) + "h: " + pump.pumpProfiles[profile][index]); } catch (Exception e){ log.error("Unhandled exception" , e); } @@ -67,8 +69,8 @@ public class MsgSettingBasalProfileAll extends MessageBase { //this is absurd pump.pumpProfiles[profile][index] returns nullPointerException try { log.debug("Basal profile " + profile + ": " + - String.format("%02d", (index / 2)) + - ":" + String.format("%02d", (index % 2) * 30) + " : " + + String.format(Locale.ENGLISH, "%02d", (index / 2)) + + ":" + String.format(Locale.ENGLISH, "%02d", (index % 2) * 30) + " : " + pump.pumpProfiles[profile][index]); } catch (Exception e){ log.error("Unhandled exception" , e); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingGlucose.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSettingGlucose.java similarity index 87% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingGlucose.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSettingGlucose.java index ded78c6272..70964a98b2 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingGlucose.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSettingGlucose.java @@ -1,10 +1,10 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; /** * Created by mike on 05.07.2016. diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingMaxValues.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSettingMaxValues.java similarity index 88% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingMaxValues.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSettingMaxValues.java index 3c640e1870..1eb3defb90 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingMaxValues.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSettingMaxValues.java @@ -1,10 +1,10 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; /** diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingMeal.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSettingMeal.java similarity index 70% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingMeal.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSettingMeal.java index 558b8953c0..6756d9d504 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingMeal.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSettingMeal.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -7,11 +7,12 @@ import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.interfaces.PluginType; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; -import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; -import info.nightscout.androidaps.plugins.Overview.notifications.Notification; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification; +import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaRKorean.DanaRKoreanPlugin; /** * Created by mike on 13.12.2016. @@ -51,16 +52,16 @@ public class MsgSettingMeal extends MessageBase { if (pump.basalStep != 0.01d) { Notification notification = new Notification(Notification.WRONGBASALSTEP, MainApp.gs(R.string.danar_setbasalstep001), Notification.URGENT); - MainApp.bus().post(new EventNewNotification(notification)); + RxBus.INSTANCE.send(new EventNewNotification(notification)); } else { - MainApp.bus().post(new EventDismissNotification(Notification.WRONGBASALSTEP)); + RxBus.INSTANCE.send(new EventDismissNotification(Notification.WRONGBASALSTEP)); } if (pump.isConfigUD) { Notification notification = new Notification(Notification.UD_MODE_ENABLED, MainApp.gs(R.string.danar_switchtouhmode), Notification.URGENT); - MainApp.bus().post(new EventNewNotification(notification)); + RxBus.INSTANCE.send(new EventNewNotification(notification)); } else { - MainApp.bus().post(new EventDismissNotification(Notification.UD_MODE_ENABLED)); + RxBus.INSTANCE.send(new EventDismissNotification(Notification.UD_MODE_ENABLED)); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingProfileRatios.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSettingProfileRatios.java similarity index 93% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingProfileRatios.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSettingProfileRatios.java index 5b6ea9b6cf..17f18cb160 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingProfileRatios.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSettingProfileRatios.java @@ -1,10 +1,10 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; /** * Created by mike on 05.07.2016. diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingProfileRatiosAll.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSettingProfileRatiosAll.java similarity index 94% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingProfileRatiosAll.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSettingProfileRatiosAll.java index 10d424657b..becdf5a745 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingProfileRatiosAll.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSettingProfileRatiosAll.java @@ -1,10 +1,10 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; /** * Created by mike on 05.07.2016. diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingPumpTime.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSettingPumpTime.java similarity index 78% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingPumpTime.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSettingPumpTime.java index 0e57c6c2f8..23a6ba6f75 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingPumpTime.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSettingPumpTime.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -6,8 +6,8 @@ import org.slf4j.LoggerFactory; import java.util.Date; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; -import info.nightscout.utils.DateUtil; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; +import info.nightscout.androidaps.utils.DateUtil; public class MsgSettingPumpTime extends MessageBase { private static Logger log = LoggerFactory.getLogger(L.PUMPCOMM); @@ -34,4 +34,10 @@ public class MsgSettingPumpTime extends MessageBase { DanaRPump.getInstance().pumpTime = time; } + + @Override + public void handleMessageNotReceived() { + DanaRPump.getInstance().pumpTime = 0; + } + } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingShippingInfo.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSettingShippingInfo.java similarity index 88% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingShippingInfo.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSettingShippingInfo.java index b700b0baa0..7362ecfdb1 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingShippingInfo.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSettingShippingInfo.java @@ -1,10 +1,10 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; /** * Created by mike on 05.07.2016. diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingUserOptions.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSettingUserOptions.java similarity index 95% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingUserOptions.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSettingUserOptions.java index e45e2050db..2dce2a6e1f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingUserOptions.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSettingUserOptions.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -6,7 +6,7 @@ import org.slf4j.LoggerFactory; import java.util.Arrays; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; /** * Created by Rumen Georgiev on 6/11/2018. diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgStatus.java similarity index 92% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatus.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgStatus.java index 474c29daa1..70c0d3b944 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatus.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgStatus.java @@ -1,10 +1,10 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; public class MsgStatus extends MessageBase { private static Logger log = LoggerFactory.getLogger(L.PUMPCOMM); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatusBasic.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgStatusBasic.java similarity index 94% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatusBasic.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgStatusBasic.java index 8f81220885..6a0635c378 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatusBasic.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgStatusBasic.java @@ -1,10 +1,10 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; public class MsgStatusBasic extends MessageBase { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatusBolusExtended.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgStatusBolusExtended.java similarity index 92% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatusBolusExtended.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgStatusBolusExtended.java index 30e41e2704..aa272b546d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatusBolusExtended.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgStatusBolusExtended.java @@ -1,19 +1,17 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; -import android.support.annotation.NonNull; +import androidx.annotation.NonNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.db.ExtendedBolus; import info.nightscout.androidaps.db.Source; -import info.nightscout.androidaps.interfaces.PluginType; import info.nightscout.androidaps.interfaces.TreatmentsInterface; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; -import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; -import info.nightscout.utils.DateUtil; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; +import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; +import info.nightscout.androidaps.utils.DateUtil; public class MsgStatusBolusExtended extends MessageBase { private static Logger log = LoggerFactory.getLogger(L.PUMPCOMM); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatusProfile.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgStatusProfile.java similarity index 92% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatusProfile.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgStatusProfile.java index 079357c6ee..f4ee2be0a6 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatusProfile.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgStatusProfile.java @@ -1,10 +1,10 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; /** * Created by mike on 05.07.2016. diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatusTempBasal.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgStatusTempBasal.java similarity index 95% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatusTempBasal.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgStatusTempBasal.java index db6080f74a..00b3bf5f69 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatusTempBasal.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgStatusTempBasal.java @@ -1,6 +1,6 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; -import android.support.annotation.NonNull; +import androidx.annotation.NonNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -8,8 +8,8 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; -import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; +import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; public class MsgStatusTempBasal extends MessageBase { private static Logger log = LoggerFactory.getLogger(L.PUMPCOMM); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/RecordTypes.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/RecordTypes.java similarity index 93% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/RecordTypes.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/RecordTypes.java index f0de05810a..36f3402cc7 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/RecordTypes.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/RecordTypes.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.comm; +package info.nightscout.androidaps.plugins.pump.danaR.comm; /** * Created by mike on 28.05.2016. diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/events/EventDanaRNewStatus.kt b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/events/EventDanaRNewStatus.kt new file mode 100644 index 0000000000..67b12d954c --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/events/EventDanaRNewStatus.kt @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.pump.danaR.events + +import info.nightscout.androidaps.events.Event + +class EventDanaRNewStatus : Event() diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/events/EventDanaRSyncStatus.kt b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/events/EventDanaRSyncStatus.kt new file mode 100644 index 0000000000..59ad7e2d83 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/events/EventDanaRSyncStatus.kt @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.pump.danaR.events + +import info.nightscout.androidaps.events.Event + +class EventDanaRSyncStatus(var message: String) : Event() \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/AbstractDanaRExecutionService.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/services/AbstractDanaRExecutionService.java similarity index 80% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/AbstractDanaRExecutionService.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/services/AbstractDanaRExecutionService.java index ae09281c91..839debe9be 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/AbstractDanaRExecutionService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/services/AbstractDanaRExecutionService.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.services; +package info.nightscout.androidaps.plugins.pump.danaR.services; import android.app.Service; import android.bluetooth.BluetoothAdapter; @@ -23,26 +23,26 @@ import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.events.EventPumpStatusChanged; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusStop; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryAlarm; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryBasalHour; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryBolus; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryCarbo; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryDailyInsulin; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryDone; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryError; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryGlucose; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryRefill; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistorySuspend; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgPCCommStart; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgPCCommStop; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes; -import info.nightscout.androidaps.plugins.Treatments.Treatment; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.SP; -import info.nightscout.utils.ToastUtils; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MessageBase; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgBolusStop; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgHistoryAlarm; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgHistoryBasalHour; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgHistoryBolus; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgHistoryCarbo; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgHistoryDailyInsulin; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgHistoryDone; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgHistoryError; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgHistoryGlucose; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgHistoryRefill; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgHistorySuspend; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgPCCommStart; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgPCCommStop; +import info.nightscout.androidaps.plugins.pump.danaR.comm.RecordTypes; +import info.nightscout.androidaps.plugins.treatments.Treatment; +import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.SP; +import info.nightscout.androidaps.utils.ToastUtils; /** * Created by mike on 28.01.2018. @@ -106,7 +106,7 @@ public abstract class AbstractDanaRExecutionService extends Service { if (mSerialIOThread != null) { mSerialIOThread.disconnect("BT disconnection broadcast"); } - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTED)); + RxBus.INSTANCE.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTED)); } } } @@ -136,7 +136,7 @@ public abstract class AbstractDanaRExecutionService extends Service { public void finishHandshaking() { mHandshakeInProgress = false; - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.CONNECTED, 0)); + RxBus.INSTANCE.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.CONNECTED, 0)); } public void disconnect(String from) { @@ -244,7 +244,7 @@ public abstract class AbstractDanaRExecutionService extends Service { long timeToWholeMinute = (60000 - time % 60000); if (timeToWholeMinute > 59800 || timeToWholeMinute < 3000) break; - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.waitingfortimesynchronization, (int) (timeToWholeMinute / 1000)))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.waitingfortimesynchronization, (int) (timeToWholeMinute / 1000)))); SystemClock.sleep(Math.min(timeToWholeMinute, 100)); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/AbstractSerialIOThread.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/services/AbstractSerialIOThread.java similarity index 62% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/AbstractSerialIOThread.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/services/AbstractSerialIOThread.java index 1cca0b2512..6d2cba9741 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/AbstractSerialIOThread.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/services/AbstractSerialIOThread.java @@ -1,6 +1,6 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.services; +package info.nightscout.androidaps.plugins.pump.danaR.services; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MessageBase; /** * Created by mike on 28.01.2018. diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/DanaRExecutionService.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/services/DanaRExecutionService.java similarity index 63% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/DanaRExecutionService.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/services/DanaRExecutionService.java index 268d5378c1..0801d8a173 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/DanaRExecutionService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/services/DanaRExecutionService.java @@ -1,12 +1,10 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.services; +package info.nightscout.androidaps.plugins.pump.danaR.services; import android.bluetooth.BluetoothDevice; import android.content.IntentFilter; import android.os.Binder; import android.os.SystemClock; -import com.squareup.otto.Subscribe; - import java.io.IOException; import java.util.Date; @@ -18,62 +16,99 @@ import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.events.EventAppExit; import info.nightscout.androidaps.events.EventInitializationChanged; import info.nightscout.androidaps.events.EventPreferenceChange; -import info.nightscout.androidaps.events.EventProfileSwitchChange; +import info.nightscout.androidaps.events.EventProfileNeedsUpdate; import info.nightscout.androidaps.events.EventPumpStatusChanged; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions; -import info.nightscout.androidaps.plugins.NSClientInternal.NSUpload; -import info.nightscout.androidaps.plugins.Overview.Dialogs.BolusProgressDialog; -import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; -import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress; -import info.nightscout.androidaps.plugins.Overview.notifications.Notification; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; -import info.nightscout.androidaps.plugins.PumpDanaR.SerialIOThread; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusProgress; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusStart; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusStartWithSpeed; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusStop; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgCheckValue; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetActivateBasalProfile; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetBasalProfile; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetCarbsEntry; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetExtendedBolusStart; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetExtendedBolusStop; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetTempBasalStart; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetTempBasalStop; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetTime; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetUserOptions; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingActiveProfile; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingBasal; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingGlucose; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingMaxValues; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingMeal; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingProfileRatios; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingProfileRatiosAll; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingPumpTime; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingShippingInfo; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingUserOptions; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgStatus; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgStatusBasic; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgStatusBolusExtended; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgStatusTempBasal; -import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRNewStatus; -import info.nightscout.androidaps.plugins.Treatments.Treatment; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; +import info.nightscout.androidaps.plugins.general.nsclient.NSUpload; +import info.nightscout.androidaps.plugins.general.overview.dialogs.BolusProgressDialog; +import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress; +import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaR.SerialIOThread; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MessageBase; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MessageHashTableR; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgBolusProgress; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgBolusStart; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgBolusStartWithSpeed; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgBolusStop; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgCheckValue; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgSetActivateBasalProfile; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgSetBasalProfile; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgSetCarbsEntry; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgSetExtendedBolusStart; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgSetExtendedBolusStop; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgSetTempBasalStart; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgSetTempBasalStop; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgSetTime; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgSetUserOptions; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgSettingActiveProfile; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgSettingBasal; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgSettingGlucose; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgSettingMaxValues; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgSettingMeal; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgSettingProfileRatios; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgSettingProfileRatiosAll; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgSettingPumpTime; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgSettingShippingInfo; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgSettingUserOptions; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgStatus; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgStatusBasic; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgStatusBolusExtended; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgStatusTempBasal; +import info.nightscout.androidaps.plugins.pump.danaR.events.EventDanaRNewStatus; +import info.nightscout.androidaps.plugins.treatments.Treatment; import info.nightscout.androidaps.queue.Callback; import info.nightscout.androidaps.queue.commands.Command; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.SP; +import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.FabricPrivacy; +import info.nightscout.androidaps.utils.SP; +import io.reactivex.disposables.CompositeDisposable; +import io.reactivex.schedulers.Schedulers; public class DanaRExecutionService extends AbstractDanaRExecutionService { + private CompositeDisposable disposable = new CompositeDisposable(); public DanaRExecutionService() { mBinder = new LocalBinder(); - registerBus(); MainApp.instance().getApplicationContext().registerReceiver(receiver, new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED)); + } + + @Override + public void onCreate() { + super.onCreate(); + disposable.add(RxBus.INSTANCE + .toObservable(EventPreferenceChange.class) + .observeOn(Schedulers.io()) + .subscribe(event -> { + if (mSerialIOThread != null) + mSerialIOThread.disconnect("EventPreferenceChange"); + }, FabricPrivacy::logException) + ); + disposable.add(RxBus.INSTANCE + .toObservable(EventAppExit.class) + .observeOn(Schedulers.io()) + .subscribe(event -> { + if (L.isEnabled(L.PUMP)) + log.debug("EventAppExit received"); + + if (mSerialIOThread != null) + mSerialIOThread.disconnect("Application exit"); + MainApp.instance().getApplicationContext().unregisterReceiver(receiver); + stopSelf(); + }, FabricPrivacy::logException) + ); + } + + @Override + public void onDestroy() { + disposable.clear(); + super.onDestroy(); } public class LocalBinder extends Binder { @@ -82,21 +117,6 @@ public class DanaRExecutionService extends AbstractDanaRExecutionService { } } - private void registerBus() { - try { - MainApp.bus().unregister(this); - } catch (RuntimeException x) { - // Ignore - } - MainApp.bus().register(this); - } - - @Subscribe - public void onStatusEvent(final EventPreferenceChange pch) { - if (mSerialIOThread != null) - mSerialIOThread.disconnect("EventPreferenceChange"); - } - public void connect() { if (mConnectionInProgress) return; @@ -123,9 +143,9 @@ public class DanaRExecutionService extends AbstractDanaRExecutionService { if (mSerialIOThread != null) { mSerialIOThread.disconnect("Recreate SerialIOThread"); } - mSerialIOThread = new SerialIOThread(mRfcommSocket); + mSerialIOThread = new SerialIOThread(mRfcommSocket, MessageHashTableR.INSTANCE); mHandshakeInProgress = true; - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.HANDSHAKING, 0)); + RxBus.INSTANCE.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.HANDSHAKING, 0)); } mConnectionInProgress = false; @@ -135,7 +155,7 @@ public class DanaRExecutionService extends AbstractDanaRExecutionService { public void getPumpStatus() { DanaRPump danaRPump = DanaRPump.getInstance(); try { - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumpstatus))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumpstatus))); MsgStatus statusMsg = new MsgStatus(); MsgStatusBasic statusBasicMsg = new MsgStatusBasic(); MsgStatusTempBasal tempStatusMsg = new MsgStatusTempBasal(); @@ -151,11 +171,11 @@ public class DanaRExecutionService extends AbstractDanaRExecutionService { mSerialIOThread.sendMessage(statusMsg); mSerialIOThread.sendMessage(statusBasicMsg); - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingtempbasalstatus))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.gettingtempbasalstatus))); mSerialIOThread.sendMessage(tempStatusMsg); - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingextendedbolusstatus))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.gettingextendedbolusstatus))); mSerialIOThread.sendMessage(exStatusMsg); - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingbolusstatus))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.gettingbolusstatus))); long now = System.currentTimeMillis(); danaRPump.lastConnection = now; @@ -163,15 +183,15 @@ public class DanaRExecutionService extends AbstractDanaRExecutionService { Profile profile = ProfileFunctions.getInstance().getProfile(); PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump(); if (profile != null && Math.abs(danaRPump.currentBasal - profile.getBasal()) >= pump.getPumpDescription().basalStep) { - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumpsettings))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumpsettings))); mSerialIOThread.sendMessage(new MsgSettingBasal()); if (!pump.isThisProfileSet(profile) && !ConfigBuilderPlugin.getPlugin().getCommandQueue().isRunning(Command.CommandType.BASALPROFILE)) { - MainApp.bus().post(new EventProfileSwitchChange()); + RxBus.INSTANCE.send(new EventProfileNeedsUpdate()); } } if (danaRPump.lastSettingsRead + 60 * 60 * 1000L < now || !pump.isInitialized()) { - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumpsettings))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumpsettings))); mSerialIOThread.sendMessage(new MsgSettingShippingInfo()); mSerialIOThread.sendMessage(new MsgSettingActiveProfile()); mSerialIOThread.sendMessage(new MsgSettingMeal()); @@ -183,8 +203,17 @@ public class DanaRExecutionService extends AbstractDanaRExecutionService { mSerialIOThread.sendMessage(new MsgSettingProfileRatios()); mSerialIOThread.sendMessage(new MsgSettingProfileRatiosAll()); mSerialIOThread.sendMessage(new MsgSettingUserOptions()); - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumptime))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumptime))); mSerialIOThread.sendMessage(new MsgSettingPumpTime()); + if (danaRPump.pumpTime == 0) { + // initial handshake was not successfull + // deinitialize pump + danaRPump.lastConnection = 0; + danaRPump.lastSettingsRead = 0; + RxBus.INSTANCE.send(new EventDanaRNewStatus()); + RxBus.INSTANCE.send(new EventInitializationChanged()); + return; + } long timeDiff = (danaRPump.pumpTime - System.currentTimeMillis()) / 1000L; if (L.isEnabled(L.PUMP)) log.debug("Pump time difference: " + timeDiff + " seconds"); @@ -198,15 +227,15 @@ public class DanaRExecutionService extends AbstractDanaRExecutionService { danaRPump.lastSettingsRead = now; } - MainApp.bus().post(new EventDanaRNewStatus()); - MainApp.bus().post(new EventInitializationChanged()); + RxBus.INSTANCE.send(new EventDanaRNewStatus()); + RxBus.INSTANCE.send(new EventInitializationChanged()); NSUpload.uploadDeviceStatus(); if (danaRPump.dailyTotalUnits > danaRPump.maxDailyTotalUnits * Constants.dailyLimitWarning) { if (L.isEnabled(L.PUMP)) log.debug("Approaching daily limit: " + danaRPump.dailyTotalUnits + "/" + danaRPump.maxDailyTotalUnits); if (System.currentTimeMillis() > lastApproachingDailyLimit + 30 * 60 * 1000) { Notification reportFail = new Notification(Notification.APPROACHING_DAILY_LIMIT, MainApp.gs(R.string.approachingdailylimit), Notification.URGENT); - MainApp.bus().post(new EventNewNotification(reportFail)); + RxBus.INSTANCE.send(new EventNewNotification(reportFail)); NSUpload.uploadError(MainApp.gs(R.string.approachingdailylimit) + ": " + danaRPump.dailyTotalUnits + "/" + danaRPump.maxDailyTotalUnits + "U"); lastApproachingDailyLimit = System.currentTimeMillis(); } @@ -220,41 +249,41 @@ public class DanaRExecutionService extends AbstractDanaRExecutionService { DanaRPump danaRPump = DanaRPump.getInstance(); if (!isConnected()) return false; if (danaRPump.isTempBasalInProgress) { - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.stoppingtempbasal))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.stoppingtempbasal))); mSerialIOThread.sendMessage(new MsgSetTempBasalStop()); SystemClock.sleep(500); } - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.settingtempbasal))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.settingtempbasal))); mSerialIOThread.sendMessage(new MsgSetTempBasalStart(percent, durationInHours)); mSerialIOThread.sendMessage(new MsgStatusTempBasal()); - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING)); + RxBus.INSTANCE.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING)); return true; } public boolean tempBasalStop() { if (!isConnected()) return false; - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.stoppingtempbasal))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.stoppingtempbasal))); mSerialIOThread.sendMessage(new MsgSetTempBasalStop()); mSerialIOThread.sendMessage(new MsgStatusTempBasal()); - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING)); + RxBus.INSTANCE.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING)); return true; } public boolean extendedBolus(double insulin, int durationInHalfHours) { if (!isConnected()) return false; - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.settingextendedbolus))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.settingextendedbolus))); mSerialIOThread.sendMessage(new MsgSetExtendedBolusStart(insulin, (byte) (durationInHalfHours & 0xFF))); mSerialIOThread.sendMessage(new MsgStatusBolusExtended()); - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING)); + RxBus.INSTANCE.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING)); return true; } public boolean extendedBolusStop() { if (!isConnected()) return false; - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.stoppingextendedbolus))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.stoppingextendedbolus))); mSerialIOThread.sendMessage(new MsgSetExtendedBolusStop()); mSerialIOThread.sendMessage(new MsgStatusBolusExtended()); - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING)); + RxBus.INSTANCE.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING)); return true; } @@ -302,9 +331,9 @@ public class DanaRExecutionService extends AbstractDanaRExecutionService { } SystemClock.sleep(300); - EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance(); - bolusingEvent.t = t; - bolusingEvent.percent = 99; + EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.INSTANCE; + bolusingEvent.setT(t); + bolusingEvent.setPercent(99); mBolusingTreatment = null; @@ -328,8 +357,8 @@ public class DanaRExecutionService extends AbstractDanaRExecutionService { while (System.currentTimeMillis() < expectedEnd) { long waitTime = expectedEnd - System.currentTimeMillis(); - bolusingEvent.status = String.format(MainApp.gs(R.string.waitingforestimatedbolusend), waitTime / 1000); - MainApp.bus().post(bolusingEvent); + bolusingEvent.setStatus(String.format(MainApp.gs(R.string.waitingforestimatedbolusend), waitTime / 1000)); + RxBus.INSTANCE.send(bolusingEvent); SystemClock.sleep(1000); } @@ -384,7 +413,7 @@ public class DanaRExecutionService extends AbstractDanaRExecutionService { public boolean updateBasalsInPump(final Profile profile) { DanaRPump danaRPump = DanaRPump.getInstance(); if (!isConnected()) return false; - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.updatingbasalrates))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.updatingbasalrates))); double[] basal = DanaRPump.getInstance().buildDanaRProfileRecord(profile); MsgSetBasalProfile msgSet = new MsgSetBasalProfile((byte) 0, basal); mSerialIOThread.sendMessage(msgSet); @@ -392,23 +421,10 @@ public class DanaRExecutionService extends AbstractDanaRExecutionService { mSerialIOThread.sendMessage(msgActivate); danaRPump.lastSettingsRead = 0; // force read full settings getPumpStatus(); - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING)); + RxBus.INSTANCE.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING)); return true; } - @Subscribe - public void onStatusEvent(EventAppExit event) { - if (L.isEnabled(L.PUMP)) - log.debug("EventAppExit received"); - - if (mSerialIOThread != null) - mSerialIOThread.disconnect("Application exit"); - - MainApp.instance().getApplicationContext().unregisterReceiver(receiver); - - stopSelf(); - } - public PumpEnactResult setUserOptions() { if (!isConnected()) return new PumpEnactResult().success(false); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/DanaRKoreanPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRKorean/DanaRKoreanPlugin.java similarity index 84% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/DanaRKoreanPlugin.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRKorean/DanaRKoreanPlugin.java index 54f0beb89b..2645e25ade 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/DanaRKoreanPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRKorean/DanaRKoreanPlugin.java @@ -1,14 +1,10 @@ -package info.nightscout.androidaps.plugins.PumpDanaRKorean; +package info.nightscout.androidaps.plugins.pump.danaRKorean; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.IBinder; -import android.support.v4.app.FragmentActivity; -import android.support.v7.app.AlertDialog; - -import com.squareup.otto.Subscribe; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; @@ -22,21 +18,25 @@ import info.nightscout.androidaps.events.EventPreferenceChange; import info.nightscout.androidaps.interfaces.Constraint; import info.nightscout.androidaps.interfaces.PluginType; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment; -import info.nightscout.androidaps.plugins.PumpCommon.defs.PumpType; -import info.nightscout.androidaps.plugins.PumpDanaR.AbstractDanaRPlugin; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusStart; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.services.DanaRKoreanExecutionService; -import info.nightscout.androidaps.plugins.Treatments.Treatment; -import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; -import info.nightscout.utils.Round; -import info.nightscout.utils.SP; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.pump.common.defs.PumpType; +import info.nightscout.androidaps.plugins.pump.danaR.AbstractDanaRPlugin; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgBolusStart; +import info.nightscout.androidaps.plugins.pump.danaRKorean.services.DanaRKoreanExecutionService; +import info.nightscout.androidaps.plugins.treatments.Treatment; +import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; +import info.nightscout.androidaps.utils.FabricPrivacy; +import info.nightscout.androidaps.utils.Round; +import info.nightscout.androidaps.utils.SP; +import io.reactivex.disposables.CompositeDisposable; +import io.reactivex.schedulers.Schedulers; /** * Created by mike on 05.08.2016. */ public class DanaRKoreanPlugin extends AbstractDanaRPlugin { + private CompositeDisposable disposable = new CompositeDisposable(); private static DanaRKoreanPlugin plugin = null; @@ -53,36 +53,32 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin { pumpDescription.setPumpDescription(PumpType.DanaRKorean); } - @Override - public void switchAllowed(ConfigBuilderFragment.PluginViewHolder.PluginSwitcher pluginSwitcher, FragmentActivity context) { - boolean allowHardwarePump = SP.getBoolean("allow_hardware_pump", false); - if (allowHardwarePump || context == null) { - pluginSwitcher.invoke(); - } else { - AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setMessage(R.string.allow_hardware_pump_text) - .setPositiveButton(R.string.yes, (dialog, id) -> { - pluginSwitcher.invoke(); - SP.putBoolean("allow_hardware_pump", true); - if (L.isEnabled(L.PUMP)) - log.debug("First time HW pump allowed!"); - }) - .setNegativeButton(R.string.cancel, (dialog, id) -> { - pluginSwitcher.cancel(); - if (L.isEnabled(L.PUMP)) - log.debug("User does not allow switching to HW pump!"); - }); - builder.create().show(); - } - } - - @Override protected void onStart() { Context context = MainApp.instance().getApplicationContext(); Intent intent = new Intent(context, DanaRKoreanExecutionService.class); context.bindService(intent, mConnection, Context.BIND_AUTO_CREATE); - MainApp.bus().register(this); + disposable.add(RxBus.INSTANCE + .toObservable(EventPreferenceChange.class) + .observeOn(Schedulers.io()) + .subscribe(event -> { + if (isEnabled(PluginType.PUMP)) { + boolean previousValue = useExtendedBoluses; + useExtendedBoluses = SP.getBoolean(R.string.key_danar_useextended, false); + + if (useExtendedBoluses != previousValue && TreatmentsPlugin.getPlugin().isInHistoryExtendedBoluslInProgress()) { + sExecutionService.extendedBolusStop(); + } + } + }, FabricPrivacy::logException) + ); + disposable.add(RxBus.INSTANCE + .toObservable(EventAppExit.class) + .observeOn(Schedulers.io()) + .subscribe(event -> { + MainApp.instance().getApplicationContext().unbindService(mConnection); + }, FabricPrivacy::logException) + ); super.onStart(); } @@ -91,7 +87,8 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin { Context context = MainApp.instance().getApplicationContext(); context.unbindService(mConnection); - MainApp.bus().unregister(this); + disposable.clear(); + super.onStop(); } private ServiceConnection mConnection = new ServiceConnection() { @@ -110,24 +107,6 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin { } }; - @SuppressWarnings("UnusedParameters") - @Subscribe - public void onStatusEvent(final EventAppExit e) { - MainApp.instance().getApplicationContext().unbindService(mConnection); - } - - @Subscribe - public void onStatusEvent(final EventPreferenceChange s) { - if (isEnabled(PluginType.PUMP)) { - boolean previousValue = useExtendedBoluses; - useExtendedBoluses = SP.getBoolean(R.string.key_danar_useextended, false); - - if (useExtendedBoluses != previousValue && TreatmentsPlugin.getPlugin().isInHistoryExtendedBoluslInProgress()) { - sExecutionService.extendedBolusStop(); - } - } - } - // Plugin base interface @Override public String getName() { @@ -266,7 +245,7 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin { // Correct basal already set ? if (L.isEnabled(L.PUMP)) log.debug("setTempBasalAbsolute: currently running: " + activeTemp.toString()); - if (activeTemp.percentRate == percentRate) { + if (activeTemp.percentRate == percentRate && activeTemp.getPlannedRemainingMinutes() > 4) { if (enforceNew) { cancelTempBasal(true); } else { @@ -364,6 +343,11 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin { return result; } + @Override + public PumpType model() { + return PumpType.DanaRKorean; + } + private PumpEnactResult cancelRealTempBasal() { PumpEnactResult result = new PumpEnactResult(); TemporaryBasal runningTB = TreatmentsPlugin.getPlugin().getTempBasalFromHistory(System.currentTimeMillis()); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRKorean/comm/MessageHashTableRkorean.kt b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRKorean/comm/MessageHashTableRkorean.kt new file mode 100644 index 0000000000..ffdf9d14c5 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRKorean/comm/MessageHashTableRkorean.kt @@ -0,0 +1,56 @@ +package info.nightscout.androidaps.plugins.pump.danaRKorean.comm + +import info.nightscout.androidaps.plugins.pump.danaR.comm.* +import java.util.* + +object MessageHashTableRkorean : MessageHashTableBase { + var messages: HashMap = HashMap() + + init { + put(MsgBolusStop()) // 0x0101 CMD_MEALINS_STOP + put(MsgBolusStart()) // 0x0102 CMD_MEALINS_START_DATA + put(MsgBolusProgress()) // 0x0202 CMD_PUMP_THIS_REMAINDER_MEAL_INS + put(MsgStatusProfile()) // 0x0204 CMD_PUMP_CALCULATION_SETTING + put(MsgStatusTempBasal()) // 0x0205 CMD_PUMP_EXERCISE_MODE + put(MsgStatusBolusExtended()) // 0x0207 CMD_PUMP_EXPANS_INS_I + put(MsgStatusBasic_k()) // 0x020A CMD_PUMP_INITVIEW_I + put(MsgStatus_k()) // 0x020B CMD_PUMP_STATUS + put(MsgInitConnStatusTime_k()) // 0x0301 CMD_PUMPINIT_TIME_INFO + put(MsgInitConnStatusBolus_k()) // 0x0302 CMD_PUMPINIT_BOLUS_INFO + put(MsgInitConnStatusBasic_k()) // 0x0303 CMD_PUMPINIT_INIT_INFO + put(MsgSetTempBasalStart()) // 0x0401 CMD_PUMPSET_EXERCISE_S + put(MsgSetCarbsEntry()) // 0x0402 CMD_PUMPSET_HIS_S + put(MsgSetTempBasalStop()) // 0x0403 CMD_PUMPSET_EXERCISE_STOP + put(MsgSetExtendedBolusStop()) // 0x0406 CMD_PUMPSET_EXPANS_INS_STOP + put(MsgSetExtendedBolusStart()) // 0x0407 CMD_PUMPSET_EXPANS_INS_S + put(MsgError()) // 0x0601 CMD_PUMPOWAY_SYSTEM_STATUS + put(MsgPCCommStart()) // 0x3001 CMD_CONNECT + put(MsgPCCommStop()) // 0x3002 CMD_DISCONNECT + put(MsgHistoryBolus()) // 0x3101 CMD_HISTORY_MEAL_INS + put(MsgHistoryDailyInsulin()) // 0x3102 CMD_HISTORY_DAY_INS + put(MsgHistoryGlucose()) // 0x3104 CMD_HISTORY_GLUCOSE + put(MsgHistoryAlarm()) // 0x3105 CMD_HISTORY_ALARM + put(MsgHistoryCarbo()) // 0x3107 CMD_HISTORY_CARBOHY + put(MsgSettingBasal_k()) // 0x3202 CMD_SETTING_V_BASAL_INS_I + put(MsgSettingMeal()) // 0x3203 CMD_SETTING_V_MEAL_SETTING_I + put(MsgSettingProfileRatios()) // 0x3204 CMD_SETTING_V_CCC_I + put(MsgSettingMaxValues()) // 0x3205 CMD_SETTING_V_MAX_VALUE_I + put(MsgSettingBasalProfileAll_k()) // 0x3206 CMD_SETTING_V_BASAL_PROFILE_ALL + put(MsgSettingShippingInfo()) // 0x3207 CMD_SETTING_V_SHIPPING_I + put(MsgSettingGlucose()) // 0x3209 CMD_SETTING_V_GLUCOSEandEASY + put(MsgSettingPumpTime()) // 0x320A CMD_SETTING_V_TIME_I + put(MsgSetSingleBasalProfile()) // 0x3302 CMD_SETTING_BASAL_INS_S + put(MsgHistoryAll()) // 0x41F2 CMD_HISTORY_ALL + put(MsgHistoryNewDone()) // 0x42F1 CMD_HISTORY_NEW_DONE + put(MsgHistoryNew()) // 0x42F2 CMD_HISTORY_NEW + put(MsgCheckValue_k()) // 0xF0F1 CMD_PUMP_CHECK_VALUE + } + + override fun put(message: MessageBase) { + messages[message.command] = message + } + + override fun findMessage(command: Int): MessageBase { + return messages[command] ?: MessageBase() + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgCheckValue_k.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRKorean/comm/MsgCheckValue_k.java similarity index 81% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgCheckValue_k.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRKorean/comm/MsgCheckValue_k.java index 7bde73d5a1..731c25d4d1 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgCheckValue_k.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRKorean/comm/MsgCheckValue_k.java @@ -1,12 +1,12 @@ -package info.nightscout.androidaps.plugins.PumpDanaRKorean.comm; +package info.nightscout.androidaps.plugins.pump.danaRKorean.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MessageBase; +import info.nightscout.androidaps.plugins.pump.danaRKorean.DanaRKoreanPlugin; /** * Created by mike on 30.06.2016. diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusBasic_k.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRKorean/comm/MsgInitConnStatusBasic_k.java similarity index 67% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusBasic_k.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRKorean/comm/MsgInitConnStatusBasic_k.java index 32253b0007..8f62ccd58f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusBasic_k.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRKorean/comm/MsgInitConnStatusBasic_k.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRKorean.comm; +package info.nightscout.androidaps.plugins.pump.danaRKorean.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -6,11 +6,12 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; -import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; -import info.nightscout.androidaps.plugins.Overview.notifications.Notification; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification; +import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MessageBase; public class MsgInitConnStatusBasic_k extends MessageBase { private static Logger log = LoggerFactory.getLogger(L.PUMPCOMM); @@ -42,16 +43,16 @@ public class MsgInitConnStatusBasic_k extends MessageBase { if (pump.isEasyModeEnabled) { Notification notification = new Notification(Notification.EASYMODE_ENABLED, MainApp.gs(R.string.danar_disableeasymode), Notification.URGENT); - MainApp.bus().post(new EventNewNotification(notification)); + RxBus.INSTANCE.send(new EventNewNotification(notification)); } else { - MainApp.bus().post(new EventDismissNotification(Notification.EASYMODE_ENABLED)); + RxBus.INSTANCE.send(new EventDismissNotification(Notification.EASYMODE_ENABLED)); } if (!DanaRPump.getInstance().isPasswordOK()) { Notification notification = new Notification(Notification.WRONG_PUMP_PASSWORD, MainApp.gs(R.string.wrongpumppassword), Notification.URGENT); - MainApp.bus().post(new EventNewNotification(notification)); + RxBus.INSTANCE.send(new EventNewNotification(notification)); } else { - MainApp.bus().post(new EventDismissNotification(Notification.WRONG_PUMP_PASSWORD)); + RxBus.INSTANCE.send(new EventDismissNotification(Notification.WRONG_PUMP_PASSWORD)); } } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusBolus_k.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRKorean/comm/MsgInitConnStatusBolus_k.java similarity index 70% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusBolus_k.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRKorean/comm/MsgInitConnStatusBolus_k.java index b8bdfd053c..0df308369f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusBolus_k.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRKorean/comm/MsgInitConnStatusBolus_k.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRKorean.comm; +package info.nightscout.androidaps.plugins.pump.danaRKorean.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -6,12 +6,13 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; -import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; -import info.nightscout.androidaps.plugins.Overview.notifications.Notification; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification; +import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MessageBase; /** * Created by mike on 28.05.2016. @@ -48,9 +49,9 @@ public class MsgInitConnStatusBolus_k extends MessageBase { if (!pump.isExtendedBolusEnabled) { Notification notification = new Notification(Notification.EXTENDED_BOLUS_DISABLED, MainApp.gs(R.string.danar_enableextendedbolus), Notification.URGENT); - MainApp.bus().post(new EventNewNotification(notification)); + RxBus.INSTANCE.send(new EventNewNotification(notification)); } else { - MainApp.bus().post(new EventDismissNotification(Notification.EXTENDED_BOLUS_DISABLED)); + RxBus.INSTANCE.send(new EventDismissNotification(Notification.EXTENDED_BOLUS_DISABLED)); } // This is last message of initial sequence diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusTime_k.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRKorean/comm/MsgInitConnStatusTime_k.java similarity index 55% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusTime_k.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRKorean/comm/MsgInitConnStatusTime_k.java index d713bb5a6c..8a642a89f8 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusTime_k.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRKorean/comm/MsgInitConnStatusTime_k.java @@ -1,21 +1,22 @@ -package info.nightscout.androidaps.plugins.PumpDanaRKorean.comm; +package info.nightscout.androidaps.plugins.pump.danaRKorean.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.events.EventRefreshGui; +import info.nightscout.androidaps.events.EventRebuildTabs; import info.nightscout.androidaps.interfaces.PluginType; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; -import info.nightscout.androidaps.plugins.Overview.notifications.Notification; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; -import info.nightscout.utils.DateUtil; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPlugin; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MessageBase; +import info.nightscout.androidaps.plugins.pump.danaRKorean.DanaRKoreanPlugin; +import info.nightscout.androidaps.utils.DateUtil; public class MsgInitConnStatusTime_k extends MessageBase { private static Logger log = LoggerFactory.getLogger(L.PUMPCOMM); @@ -31,24 +32,24 @@ public class MsgInitConnStatusTime_k extends MessageBase { if (bytes.length - 10 < 10) { Notification notification = new Notification(Notification.WRONG_DRIVER, MainApp.gs(R.string.pumpdrivercorrected), Notification.NORMAL); - MainApp.bus().post(new EventNewNotification(notification)); + RxBus.INSTANCE.send(new EventNewNotification(notification)); DanaRKoreanPlugin.getPlugin().disconnect("Wrong Model"); log.error("Wrong model selected. Switching to export DanaR"); - MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).setPluginEnabled(PluginType.PUMP, false); - MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).setFragmentVisible(PluginType.PUMP, false); - MainApp.getSpecificPlugin(DanaRPlugin.class).setPluginEnabled(PluginType.PUMP, true); - MainApp.getSpecificPlugin(DanaRPlugin.class).setFragmentVisible(PluginType.PUMP, true); + DanaRKoreanPlugin.getPlugin().setPluginEnabled(PluginType.PUMP, false); + DanaRKoreanPlugin.getPlugin().setFragmentVisible(PluginType.PUMP, false); + DanaRPlugin.getPlugin().setPluginEnabled(PluginType.PUMP, true); + DanaRPlugin.getPlugin().setFragmentVisible(PluginType.PUMP, true); DanaRPump.reset(); // mark not initialized //If profile coming from pump, switch it as well - if (MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).isEnabled(PluginType.PROFILE)) { - (MainApp.getSpecificPlugin(DanaRKoreanPlugin.class)).setPluginEnabled(PluginType.PROFILE, false); - (MainApp.getSpecificPlugin(DanaRPlugin.class)).setPluginEnabled(PluginType.PROFILE, true); + if (DanaRKoreanPlugin.getPlugin().isEnabled(PluginType.PROFILE)) { + (DanaRKoreanPlugin.getPlugin()).setPluginEnabled(PluginType.PROFILE, false); + (DanaRPlugin.getPlugin()).setPluginEnabled(PluginType.PROFILE, true); } ConfigBuilderPlugin.getPlugin().storeSettings("ChangingKoreanDanaDriver"); - MainApp.bus().post(new EventRefreshGui()); + RxBus.INSTANCE.send(new EventRebuildTabs()); ConfigBuilderPlugin.getPlugin().getCommandQueue().readStatus("PumpDriverChange", null); // force new connection return; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgSettingBasalProfileAll_k.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRKorean/comm/MsgSettingBasalProfileAll_k.java similarity index 83% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgSettingBasalProfileAll_k.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRKorean/comm/MsgSettingBasalProfileAll_k.java index 2455f59e14..85591d4655 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgSettingBasalProfileAll_k.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRKorean/comm/MsgSettingBasalProfileAll_k.java @@ -1,11 +1,13 @@ -package info.nightscout.androidaps.plugins.PumpDanaRKorean.comm; +package info.nightscout.androidaps.plugins.pump.danaRKorean.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.Locale; + import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MessageBase; /** @@ -55,15 +57,15 @@ public class MsgSettingBasalProfileAll_k extends MessageBase { if (pump.basal48Enable) { for (int profile = 0; profile < 4; profile++) { for (int index = 0; index < 24; index++) { - log.debug("Basal profile " + profile + ": " + String.format("%02d", index) + "h: " + pump.pumpProfiles[profile][index]); + log.debug("Basal profile " + profile + ": " + String.format(Locale.ENGLISH, "%02d", index) + "h: " + pump.pumpProfiles[profile][index]); } } } else { for (int profile = 0; profile < 4; profile++) { for (int index = 0; index < 48; index++) { log.debug("Basal profile " + profile + ": " + - String.format("%02d", (index / 2)) + - ":" + String.format("%02d", (index % 2) * 30) + " : " + + String.format(Locale.ENGLISH, "%02d", (index / 2)) + + ":" + String.format(Locale.ENGLISH, "%02d", (index % 2) * 30) + " : " + pump.pumpProfiles[profile][index]); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgSettingBasal_k.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRKorean/comm/MsgSettingBasal_k.java similarity index 70% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgSettingBasal_k.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRKorean/comm/MsgSettingBasal_k.java index b149ceb2ad..b3ba918a4a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgSettingBasal_k.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRKorean/comm/MsgSettingBasal_k.java @@ -1,12 +1,14 @@ -package info.nightscout.androidaps.plugins.PumpDanaRKorean.comm; +package info.nightscout.androidaps.plugins.pump.danaRKorean.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.Locale; + import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MessageBase; +import info.nightscout.androidaps.plugins.pump.danaRKorean.DanaRKoreanPlugin; /** * Created by mike on 05.07.2016. @@ -32,7 +34,7 @@ public class MsgSettingBasal_k extends MessageBase { if (L.isEnabled(L.PUMPCOMM)) for (int index = 0; index < 24; index++) { - log.debug("Basal " + String.format("%02d", index) + "h: " + pump.pumpProfiles[pump.activeProfile][index]); + log.debug("Basal " + String.format(Locale.ENGLISH, "%02d", index) + "h: " + pump.pumpProfiles[pump.activeProfile][index]); } } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgStatusBasic_k.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRKorean/comm/MsgStatusBasic_k.java similarity index 87% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgStatusBasic_k.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRKorean/comm/MsgStatusBasic_k.java index d22c6e376a..e7752cfb8f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgStatusBasic_k.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRKorean/comm/MsgStatusBasic_k.java @@ -1,11 +1,11 @@ -package info.nightscout.androidaps.plugins.PumpDanaRKorean.comm; +package info.nightscout.androidaps.plugins.pump.danaRKorean.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MessageBase; public class MsgStatusBasic_k extends MessageBase { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgStatus_k.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRKorean/comm/MsgStatus_k.java similarity index 88% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgStatus_k.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRKorean/comm/MsgStatus_k.java index 4d8b012244..4ef29247b2 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgStatus_k.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRKorean/comm/MsgStatus_k.java @@ -1,11 +1,11 @@ -package info.nightscout.androidaps.plugins.PumpDanaRKorean.comm; +package info.nightscout.androidaps.plugins.pump.danaRKorean.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MessageBase; public class MsgStatus_k extends MessageBase { private static Logger log = LoggerFactory.getLogger(L.PUMPCOMM); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/services/DanaRKoreanExecutionService.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRKorean/services/DanaRKoreanExecutionService.java similarity index 59% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/services/DanaRKoreanExecutionService.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRKorean/services/DanaRKoreanExecutionService.java index f3588c4efa..bb1f226730 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/services/DanaRKoreanExecutionService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRKorean/services/DanaRKoreanExecutionService.java @@ -1,12 +1,10 @@ -package info.nightscout.androidaps.plugins.PumpDanaRKorean.services; +package info.nightscout.androidaps.plugins.pump.danaRKorean.services; import android.bluetooth.BluetoothDevice; import android.content.IntentFilter; import android.os.Binder; import android.os.SystemClock; -import com.squareup.otto.Subscribe; - import java.io.IOException; import java.util.Date; @@ -18,90 +16,99 @@ import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.events.EventAppExit; import info.nightscout.androidaps.events.EventInitializationChanged; import info.nightscout.androidaps.events.EventPreferenceChange; -import info.nightscout.androidaps.events.EventProfileSwitchChange; +import info.nightscout.androidaps.events.EventProfileNeedsUpdate; import info.nightscout.androidaps.events.EventPumpStatusChanged; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions; -import info.nightscout.androidaps.plugins.NSClientInternal.NSUpload; -import info.nightscout.androidaps.plugins.Overview.Dialogs.BolusProgressDialog; -import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; -import info.nightscout.androidaps.plugins.Overview.notifications.Notification; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusProgress; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusStart; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusStop; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetCarbsEntry; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetExtendedBolusStart; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetExtendedBolusStop; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetSingleBasalProfile; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetTempBasalStart; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetTempBasalStop; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetTime; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingBasal; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingGlucose; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingMaxValues; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingMeal; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingProfileRatios; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingPumpTime; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingShippingInfo; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgStatusBolusExtended; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgStatusTempBasal; -import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRNewStatus; -import info.nightscout.androidaps.plugins.PumpDanaR.services.AbstractDanaRExecutionService; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.SerialIOThread; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.comm.MsgCheckValue_k; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.comm.MsgSettingBasal_k; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.comm.MsgStatusBasic_k; -import info.nightscout.androidaps.plugins.Treatments.Treatment; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; +import info.nightscout.androidaps.plugins.general.nsclient.NSUpload; +import info.nightscout.androidaps.plugins.general.overview.dialogs.BolusProgressDialog; +import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaR.SerialIOThread; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgBolusProgress; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgBolusStart; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgBolusStop; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgSetCarbsEntry; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgSetExtendedBolusStart; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgSetExtendedBolusStop; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgSetSingleBasalProfile; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgSetTempBasalStart; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgSetTempBasalStop; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgSetTime; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgSettingBasal; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgSettingGlucose; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgSettingMaxValues; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgSettingMeal; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgSettingProfileRatios; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgSettingPumpTime; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgSettingShippingInfo; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgStatusBolusExtended; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgStatusTempBasal; +import info.nightscout.androidaps.plugins.pump.danaR.events.EventDanaRNewStatus; +import info.nightscout.androidaps.plugins.pump.danaR.services.AbstractDanaRExecutionService; +import info.nightscout.androidaps.plugins.pump.danaRKorean.comm.MessageHashTableRkorean; +import info.nightscout.androidaps.plugins.pump.danaRKorean.comm.MsgCheckValue_k; +import info.nightscout.androidaps.plugins.pump.danaRKorean.comm.MsgSettingBasal_k; +import info.nightscout.androidaps.plugins.pump.danaRKorean.comm.MsgStatusBasic_k; +import info.nightscout.androidaps.plugins.treatments.Treatment; import info.nightscout.androidaps.queue.commands.Command; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.T; +import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.FabricPrivacy; +import info.nightscout.androidaps.utils.T; +import io.reactivex.disposables.CompositeDisposable; +import io.reactivex.schedulers.Schedulers; public class DanaRKoreanExecutionService extends AbstractDanaRExecutionService { + private CompositeDisposable disposable = new CompositeDisposable(); public DanaRKoreanExecutionService() { mBinder = new LocalBinder(); - registerBus(); MainApp.instance().getApplicationContext().registerReceiver(receiver, new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED)); } + @Override + public void onCreate() { + super.onCreate(); + disposable.add(RxBus.INSTANCE + .toObservable(EventPreferenceChange.class) + .observeOn(Schedulers.io()) + .subscribe(event -> { + if (mSerialIOThread != null) + mSerialIOThread.disconnect("EventPreferenceChange"); + }, FabricPrivacy::logException) + ); + disposable.add(RxBus.INSTANCE + .toObservable(EventAppExit.class) + .observeOn(Schedulers.io()) + .subscribe(event -> { + if (L.isEnabled(L.PUMP)) + log.debug("EventAppExit received"); + + if (mSerialIOThread != null) + mSerialIOThread.disconnect("Application exit"); + MainApp.instance().getApplicationContext().unregisterReceiver(receiver); + stopSelf(); + }, FabricPrivacy::logException) + ); + } + + @Override + public void onDestroy() { + disposable.clear(); + super.onDestroy(); + } + public class LocalBinder extends Binder { public DanaRKoreanExecutionService getServiceInstance() { return DanaRKoreanExecutionService.this; } } - private void registerBus() { - try { - MainApp.bus().unregister(this); - } catch (RuntimeException x) { - // Ignore - } - MainApp.bus().register(this); - } - - @Subscribe - public void onStatusEvent(EventAppExit event) { - if (L.isEnabled(L.PUMP)) - log.debug("EventAppExit received"); - - if (mSerialIOThread != null) - mSerialIOThread.disconnect("Application exit"); - - MainApp.instance().getApplicationContext().unregisterReceiver(receiver); - - stopSelf(); - } - - @Subscribe - public void onStatusEvent(final EventPreferenceChange pch) { - if (mSerialIOThread != null) - mSerialIOThread.disconnect("EventPreferenceChange"); - } - public void connect() { if (mConnectionInProgress) return; @@ -128,9 +135,9 @@ public class DanaRKoreanExecutionService extends AbstractDanaRExecutionService { if (mSerialIOThread != null) { mSerialIOThread.disconnect("Recreate SerialIOThread"); } - mSerialIOThread = new SerialIOThread(mRfcommSocket); + mSerialIOThread = new SerialIOThread(mRfcommSocket, MessageHashTableRkorean.INSTANCE); mHandshakeInProgress = true; - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.HANDSHAKING, 0)); + RxBus.INSTANCE.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.HANDSHAKING, 0)); } mConnectionInProgress = false; @@ -140,7 +147,7 @@ public class DanaRKoreanExecutionService extends AbstractDanaRExecutionService { public void getPumpStatus() { DanaRPump danaRPump = DanaRPump.getInstance(); try { - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumpstatus))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumpstatus))); //MsgStatus_k statusMsg = new MsgStatus_k(); MsgStatusBasic_k statusBasicMsg = new MsgStatusBasic_k(); MsgStatusTempBasal tempStatusMsg = new MsgStatusTempBasal(); @@ -156,11 +163,11 @@ public class DanaRKoreanExecutionService extends AbstractDanaRExecutionService { //mSerialIOThread.sendMessage(statusMsg); mSerialIOThread.sendMessage(statusBasicMsg); - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingtempbasalstatus))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.gettingtempbasalstatus))); mSerialIOThread.sendMessage(tempStatusMsg); - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingextendedbolusstatus))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.gettingextendedbolusstatus))); mSerialIOThread.sendMessage(exStatusMsg); - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingbolusstatus))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.gettingbolusstatus))); long now = System.currentTimeMillis(); danaRPump.lastConnection = now; @@ -168,15 +175,15 @@ public class DanaRKoreanExecutionService extends AbstractDanaRExecutionService { Profile profile = ProfileFunctions.getInstance().getProfile(); PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump(); if (profile != null && Math.abs(danaRPump.currentBasal - profile.getBasal()) >= pump.getPumpDescription().basalStep) { - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumpsettings))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumpsettings))); mSerialIOThread.sendMessage(new MsgSettingBasal()); if (!pump.isThisProfileSet(profile) && !ConfigBuilderPlugin.getPlugin().getCommandQueue().isRunning(Command.CommandType.BASALPROFILE)) { - MainApp.bus().post(new EventProfileSwitchChange()); + RxBus.INSTANCE.send(new EventProfileNeedsUpdate()); } } if (danaRPump.lastSettingsRead + 60 * 60 * 1000L < now || !pump.isInitialized()) { - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumpsettings))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumpsettings))); mSerialIOThread.sendMessage(new MsgSettingShippingInfo()); mSerialIOThread.sendMessage(new MsgSettingMeal()); mSerialIOThread.sendMessage(new MsgSettingBasal_k()); @@ -184,8 +191,17 @@ public class DanaRKoreanExecutionService extends AbstractDanaRExecutionService { mSerialIOThread.sendMessage(new MsgSettingMaxValues()); mSerialIOThread.sendMessage(new MsgSettingGlucose()); mSerialIOThread.sendMessage(new MsgSettingProfileRatios()); - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumptime))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumptime))); mSerialIOThread.sendMessage(new MsgSettingPumpTime()); + if (danaRPump.pumpTime == 0) { + // initial handshake was not successfull + // deinitialize pump + danaRPump.lastConnection = 0; + danaRPump.lastSettingsRead = 0; + RxBus.INSTANCE.send(new EventDanaRNewStatus()); + RxBus.INSTANCE.send(new EventInitializationChanged()); + return; + } long timeDiff = (danaRPump.pumpTime - System.currentTimeMillis()) / 1000L; if (L.isEnabled(L.PUMP)) log.debug("Pump time difference: " + timeDiff + " seconds"); @@ -201,15 +217,15 @@ public class DanaRKoreanExecutionService extends AbstractDanaRExecutionService { danaRPump.lastSettingsRead = now; } - MainApp.bus().post(new EventDanaRNewStatus()); - MainApp.bus().post(new EventInitializationChanged()); + RxBus.INSTANCE.send(new EventDanaRNewStatus()); + RxBus.INSTANCE.send(new EventInitializationChanged()); NSUpload.uploadDeviceStatus(); if (danaRPump.dailyTotalUnits > danaRPump.maxDailyTotalUnits * Constants.dailyLimitWarning) { if (L.isEnabled(L.PUMP)) log.debug("Approaching daily limit: " + danaRPump.dailyTotalUnits + "/" + danaRPump.maxDailyTotalUnits); if (System.currentTimeMillis() > lastApproachingDailyLimit + 30 * 60 * 1000) { Notification reportFail = new Notification(Notification.APPROACHING_DAILY_LIMIT, MainApp.gs(R.string.approachingdailylimit), Notification.URGENT); - MainApp.bus().post(new EventNewNotification(reportFail)); + RxBus.INSTANCE.send(new EventNewNotification(reportFail)); NSUpload.uploadError(MainApp.gs(R.string.approachingdailylimit) + ": " + danaRPump.dailyTotalUnits + "/" + danaRPump.maxDailyTotalUnits + "U"); lastApproachingDailyLimit = System.currentTimeMillis(); } @@ -223,41 +239,41 @@ public class DanaRKoreanExecutionService extends AbstractDanaRExecutionService { DanaRPump danaRPump = DanaRPump.getInstance(); if (!isConnected()) return false; if (danaRPump.isTempBasalInProgress) { - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.stoppingtempbasal))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.stoppingtempbasal))); mSerialIOThread.sendMessage(new MsgSetTempBasalStop()); SystemClock.sleep(500); } - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.settingtempbasal))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.settingtempbasal))); mSerialIOThread.sendMessage(new MsgSetTempBasalStart(percent, durationInHours)); mSerialIOThread.sendMessage(new MsgStatusTempBasal()); - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING)); + RxBus.INSTANCE.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING)); return true; } public boolean tempBasalStop() { if (!isConnected()) return false; - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.stoppingtempbasal))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.stoppingtempbasal))); mSerialIOThread.sendMessage(new MsgSetTempBasalStop()); mSerialIOThread.sendMessage(new MsgStatusTempBasal()); - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING)); + RxBus.INSTANCE.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING)); return true; } public boolean extendedBolus(double insulin, int durationInHalfHours) { if (!isConnected()) return false; - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.settingextendedbolus))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.settingextendedbolus))); mSerialIOThread.sendMessage(new MsgSetExtendedBolusStart(insulin, (byte) (durationInHalfHours & 0xFF))); mSerialIOThread.sendMessage(new MsgStatusBolusExtended()); - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING)); + RxBus.INSTANCE.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING)); return true; } public boolean extendedBolusStop() { if (!isConnected()) return false; - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.stoppingextendedbolus))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.stoppingextendedbolus))); mSerialIOThread.sendMessage(new MsgSetExtendedBolusStop()); mSerialIOThread.sendMessage(new MsgStatusBolusExtended()); - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING)); + RxBus.INSTANCE.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING)); return true; } @@ -325,13 +341,13 @@ public class DanaRKoreanExecutionService extends AbstractDanaRExecutionService { public boolean updateBasalsInPump(final Profile profile) { DanaRPump danaRPump = DanaRPump.getInstance(); if (!isConnected()) return false; - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.updatingbasalrates))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.updatingbasalrates))); double[] basal = DanaRPump.getInstance().buildDanaRProfileRecord(profile); MsgSetSingleBasalProfile msgSet = new MsgSetSingleBasalProfile(basal); mSerialIOThread.sendMessage(msgSet); danaRPump.lastSettingsRead = 0; // force read full settings getPumpStatus(); - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING)); + RxBus.INSTANCE.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING)); return true; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/DanaRSPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/DanaRSPlugin.java similarity index 86% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/DanaRSPlugin.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/DanaRSPlugin.java index d6a4dd015b..7b2668d45c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/DanaRSPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/DanaRSPlugin.java @@ -1,21 +1,21 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS; +package info.nightscout.androidaps.plugins.pump.danaRS; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.IBinder; -import android.support.annotation.Nullable; -import android.support.v4.app.FragmentActivity; -import android.support.v7.app.AlertDialog; -import com.squareup.otto.Subscribe; +import androidx.annotation.Nullable; +import androidx.fragment.app.FragmentActivity; import org.json.JSONException; import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.List; + import info.nightscout.androidaps.BuildConfig; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; @@ -36,27 +36,33 @@ import info.nightscout.androidaps.interfaces.ProfileInterface; import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment; -import info.nightscout.androidaps.plugins.ConfigBuilder.DetailedBolusInfoStorage; -import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions; -import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; -import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; -import info.nightscout.androidaps.plugins.Overview.notifications.Notification; -import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin; -import info.nightscout.androidaps.plugins.PumpCommon.defs.PumpType; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRFragment; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes; -import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Bolus_Set_Step_Bolus_Start; -import info.nightscout.androidaps.plugins.PumpDanaRS.events.EventDanaRSDeviceChange; -import info.nightscout.androidaps.plugins.PumpDanaRS.services.DanaRSService; -import info.nightscout.androidaps.plugins.Treatments.Treatment; -import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.DecimalFormatter; -import info.nightscout.utils.Round; -import info.nightscout.utils.SP; -import info.nightscout.utils.T; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.common.ManufacturerType; +import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; +import info.nightscout.androidaps.plugins.general.actions.defs.CustomAction; +import info.nightscout.androidaps.plugins.general.actions.defs.CustomActionType; +import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification; +import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; +import info.nightscout.androidaps.plugins.profile.ns.NSProfilePlugin; +import info.nightscout.androidaps.plugins.pump.common.bolusInfo.DetailedBolusInfoStorage; +import info.nightscout.androidaps.plugins.pump.common.defs.PumpType; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRFragment; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaR.comm.RecordTypes; +import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_Bolus_Set_Step_Bolus_Start; +import info.nightscout.androidaps.plugins.pump.danaRS.events.EventDanaRSDeviceChange; +import info.nightscout.androidaps.plugins.pump.danaRS.services.DanaRSService; +import info.nightscout.androidaps.plugins.treatments.Treatment; +import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; +import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.DecimalFormatter; +import info.nightscout.androidaps.utils.FabricPrivacy; +import info.nightscout.androidaps.utils.Round; +import info.nightscout.androidaps.utils.SP; +import info.nightscout.androidaps.utils.T; +import io.reactivex.disposables.CompositeDisposable; +import io.reactivex.schedulers.Schedulers; /** * Created by mike on 03.09.2017. @@ -64,6 +70,8 @@ import info.nightscout.utils.T; public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInterface, ConstraintsInterface, ProfileInterface { private Logger log = LoggerFactory.getLogger(L.PUMP); + private CompositeDisposable disposable = new CompositeDisposable(); + private static DanaRSPlugin plugin = null; public static DanaRSPlugin getPlugin() { @@ -108,8 +116,21 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte Intent intent = new Intent(context, DanaRSService.class); context.bindService(intent, mConnection, Context.BIND_AUTO_CREATE); - MainApp.bus().register(this); - onStatusEvent(new EventDanaRSDeviceChange()); // load device name + disposable.add(RxBus.INSTANCE + .toObservable(EventAppExit.class) + .observeOn(Schedulers.io()) + .subscribe(event -> { + MainApp.instance().getApplicationContext().unbindService(mConnection); + }, FabricPrivacy::logException) + ); + disposable.add(RxBus.INSTANCE + .toObservable(EventDanaRSDeviceChange.class) + .observeOn(Schedulers.io()) + .subscribe(event -> { + loadAddress(); + }, FabricPrivacy::logException) + ); + loadAddress(); // load device name super.onStart(); } @@ -118,30 +139,13 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte Context context = MainApp.instance().getApplicationContext(); context.unbindService(mConnection); - MainApp.bus().unregister(this); + disposable.clear(); + super.onStop(); } @Override - public void switchAllowed(ConfigBuilderFragment.PluginViewHolder.PluginSwitcher pluginSwitcher, FragmentActivity context) { - boolean allowHardwarePump = SP.getBoolean("allow_hardware_pump", false); - if (allowHardwarePump || context == null) { - pluginSwitcher.invoke(); - } else { - AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setMessage(R.string.allow_hardware_pump_text) - .setPositiveButton(R.string.yes, (dialog, id) -> { - pluginSwitcher.invoke(); - SP.putBoolean("allow_hardware_pump", true); - if (L.isEnabled(L.PUMP)) - log.debug("First time HW pump allowed!"); - }) - .setNegativeButton(R.string.cancel, (dialog, id) -> { - pluginSwitcher.cancel(); - if (L.isEnabled(L.PUMP)) - log.debug("User does not allow switching to HW pump!"); - }); - builder.create().show(); - } + public void switchAllowed(boolean newState, FragmentActivity activity, PluginType type) { + confirmPumpPluginActivation(newState, activity, type); } private ServiceConnection mConnection = new ServiceConnection() { @@ -160,14 +164,7 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte } }; - @SuppressWarnings("UnusedParameters") - @Subscribe - public void onStatusEvent(final EventAppExit e) { - MainApp.instance().getApplicationContext().unbindService(mConnection); - } - - @Subscribe - public void onStatusEvent(final EventDanaRSDeviceChange e) { + private void loadAddress() { mDeviceAddress = SP.getString(R.string.key_danars_address, ""); mDeviceName = SP.getString(R.string.key_danars_name, ""); } @@ -318,22 +315,22 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte if (!isInitialized()) { log.error("setNewBasalProfile not initialized"); Notification notification = new Notification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED, MainApp.gs(R.string.pumpNotInitializedProfileNotSet), Notification.URGENT); - MainApp.bus().post(new EventNewNotification(notification)); + RxBus.INSTANCE.send(new EventNewNotification(notification)); result.comment = MainApp.gs(R.string.pumpNotInitializedProfileNotSet); return result; } else { - MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED)); + RxBus.INSTANCE.send(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED)); } if (!danaRSService.updateBasalsInPump(profile)) { Notification notification = new Notification(Notification.FAILED_UDPATE_PROFILE, MainApp.gs(R.string.failedupdatebasalprofile), Notification.URGENT); - MainApp.bus().post(new EventNewNotification(notification)); + RxBus.INSTANCE.send(new EventNewNotification(notification)); result.comment = MainApp.gs(R.string.failedupdatebasalprofile); return result; } else { - MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED)); - MainApp.bus().post(new EventDismissNotification(Notification.FAILED_UDPATE_PROFILE)); + RxBus.INSTANCE.send(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED)); + RxBus.INSTANCE.send(new EventDismissNotification(Notification.FAILED_UDPATE_PROFILE)); Notification notification = new Notification(Notification.PROFILE_SET_OK, MainApp.gs(R.string.profile_set_ok), Notification.INFO, 60); - MainApp.bus().post(new EventNewNotification(notification)); + RxBus.INSTANCE.send(new EventNewNotification(notification)); result.success = true; result.enacted = true; result.comment = "OK"; @@ -373,6 +370,16 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte return DanaRPump.getInstance().currentBasal; } + @Override + public double getReservoirLevel() { + return DanaRPump.getInstance().reservoirRemainingUnits; + } + + @Override + public int getBatteryLevel() { + return DanaRPump.getInstance().batteryRemaining; + } + @Override public synchronized PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo) { detailedBolusInfo.insulin = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(detailedBolusInfo.insulin)).value(); @@ -401,7 +408,7 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte if (carbTime == 0) carbTime--; // better set 1 min back to prevents clash with insulin detailedBolusInfo.carbTime = 0; - DetailedBolusInfoStorage.add(detailedBolusInfo); // will be picked up on reading history + DetailedBolusInfoStorage.INSTANCE.add(detailedBolusInfo); // will be picked up on reading history Treatment t = new Treatment(); t.isSMB = detailedBolusInfo.isSMB; @@ -502,7 +509,7 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte if (L.isEnabled(L.PUMP)) log.debug("setTempBasalAbsolute: currently running: " + activeTemp.toString()); // Correct basal already set ? - if (activeTemp.percentRate == percentRate) { + if (activeTemp.percentRate == percentRate && activeTemp.getPlannedRemainingMinutes() > 4) { if (!enforceNew) { result.success = true; result.percent = percentRate; @@ -520,7 +527,7 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte if (L.isEnabled(L.PUMP)) log.debug("setTempBasalAbsolute: Setting temp basal " + percentRate + "% for " + durationInMinutes + " mins (doLowTemp || doHighTemp)"); if (percentRate == 0 && durationInMinutes > 30) { - result = setTempBasalPercent(percentRate, durationInMinutes, profile, false); + result = setTempBasalPercent(percentRate, durationInMinutes, profile, enforceNew); } else { // use special APS temp basal call ... 100+/15min .... 100-/30min result = setHighTempBasalPercent(percentRate); @@ -556,8 +563,8 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte if (percent > getPumpDescription().maxTempPercent) percent = getPumpDescription().maxTempPercent; long now = System.currentTimeMillis(); - TemporaryBasal runningTB = TreatmentsPlugin.getPlugin().getTempBasalFromHistory(now); - if (runningTB != null && runningTB.percentRate == percent && !enforceNew) { + TemporaryBasal activeTemp = TreatmentsPlugin.getPlugin().getTempBasalFromHistory(now); + if (activeTemp != null && activeTemp.percentRate == percent && activeTemp.getPlannedRemainingMinutes() > 4 && !enforceNew) { result.enacted = false; result.success = true; result.isTempCancel = false; @@ -759,7 +766,17 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte } @Override - public String deviceID() { + public ManufacturerType manufacturer() { + return ManufacturerType.Sooil; + } + + @Override + public PumpType model() { + return PumpType.DanaRS; + } + + @Override + public String serialNumber() { return DanaRPump.getInstance().serialNumber; } @@ -791,7 +808,6 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte if (!veryShort) { ret += "TDD: " + DecimalFormatter.to0Decimal(pump.dailyTotalUnits) + " / " + pump.maxDailyTotalUnits + " U\n"; } - ret += "IOB: " + pump.iob + "U\n"; ret += "Reserv: " + DecimalFormatter.to0Decimal(pump.reservoirRemainingUnits) + "U\n"; ret += "Batt: " + pump.batteryRemaining + "\n"; return ret; @@ -807,4 +823,24 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte return loadHistory(RecordTypes.RECORD_TYPE_DAILY); } + @Override + public List getCustomActions() { + return null; + } + + @Override + public void executeCustomAction(CustomActionType customActionType) { + + } + + @Override + public boolean canHandleDST() { + return false; + } + + @Override + public void timeDateOrTimeZoneChanged() { + + } + } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/activities/BLEScanActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/activities/BLEScanActivity.java similarity index 90% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/activities/BLEScanActivity.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/activities/BLEScanActivity.java index 7594e917c5..42e910f291 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/activities/BLEScanActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/activities/BLEScanActivity.java @@ -1,47 +1,39 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.activities; +package info.nightscout.androidaps.plugins.pump.danaRS.activities; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothManager; import android.bluetooth.le.BluetoothLeScanner; import android.bluetooth.le.ScanCallback; import android.bluetooth.le.ScanResult; -import android.content.Context; -import android.content.DialogInterface; import android.os.Bundle; import android.os.Handler; -import android.support.v7.app.AlertDialog; -import android.support.v7.app.AppCompatActivity; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ListView; import android.widget.TextView; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.util.ArrayList; import java.util.regex.Matcher; import java.util.regex.Pattern; -import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.plugins.PumpDanaRS.events.EventDanaRSDeviceChange; -import info.nightscout.utils.SP; +import info.nightscout.androidaps.activities.NoSplashAppCompatActivity; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.pump.danaRS.events.EventDanaRSDeviceChange; +import info.nightscout.androidaps.utils.SP; -public class BLEScanActivity extends AppCompatActivity { +public class BLEScanActivity extends NoSplashAppCompatActivity { private ListView listView = null; private ListAdapter mListAdapter = null; private ArrayList mDevices = new ArrayList<>(); - ; private BluetoothAdapter mBluetoothAdapter = null; private BluetoothLeScanner mBluetoothLeScanner = null; @Override - protected void onCreate(Bundle savedInstanceState) { + public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.danars_blescanner_activity); @@ -164,7 +156,7 @@ public class BLEScanActivity extends AppCompatActivity { SP.putString(R.string.key_danars_address, item.device.getAddress()); SP.putString(R.string.key_danars_name, mName.getText().toString()); item.device.createBond(); - MainApp.bus().post(new EventDanaRSDeviceChange()); + RxBus.INSTANCE.send(new EventDanaRSDeviceChange()); finish(); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/activities/PairingHelperActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/activities/PairingHelperActivity.java similarity index 54% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/activities/PairingHelperActivity.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/activities/PairingHelperActivity.java index c67534ac75..5be6d7fbd1 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/activities/PairingHelperActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/activities/PairingHelperActivity.java @@ -1,12 +1,13 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.activities; +package info.nightscout.androidaps.plugins.pump.danaRS.activities; -import android.support.v7.app.AppCompatActivity; import android.os.Bundle; -public class PairingHelperActivity extends AppCompatActivity { +import info.nightscout.androidaps.activities.NoSplashAppCompatActivity; + +public class PairingHelperActivity extends NoSplashAppCompatActivity { @Override - protected void onCreate(Bundle savedInstanceState) { + public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); PairingProgressDialog bolusProgressDialog = new PairingProgressDialog(); bolusProgressDialog.setHelperActivity(this); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/activities/PairingProgressDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/activities/PairingProgressDialog.java similarity index 84% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/activities/PairingProgressDialog.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/activities/PairingProgressDialog.java index 08c0ce0372..afb5e86387 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/activities/PairingProgressDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/activities/PairingProgressDialog.java @@ -1,11 +1,10 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.activities; +package info.nightscout.androidaps.plugins.pump.danaRS.activities; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; -import android.support.v4.app.DialogFragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -13,14 +12,19 @@ import android.widget.Button; import android.widget.ProgressBar; import android.widget.TextView; -import com.squareup.otto.Subscribe; +import androidx.fragment.app.DialogFragment; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.plugins.PumpDanaRS.events.EventDanaRSPairingSuccess; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.pump.danaRS.events.EventDanaRSPairingSuccess; +import info.nightscout.androidaps.utils.FabricPrivacy; +import io.reactivex.disposables.CompositeDisposable; +import io.reactivex.schedulers.Schedulers; public class PairingProgressDialog extends DialogFragment implements View.OnClickListener { + private CompositeDisposable disposable = new CompositeDisposable(); TextView statusView; ProgressBar progressBar; @@ -101,7 +105,11 @@ public class PairingProgressDialog extends DialogFragment implements View.OnClic @Override public void onResume() { super.onResume(); - MainApp.bus().register(this); + disposable.add(RxBus.INSTANCE + .toObservable(EventDanaRSPairingSuccess.class) + .observeOn(Schedulers.io()) + .subscribe(event -> pairingEnded = true, FabricPrivacy::logException) + ); running = true; if (pairingEnded) dismiss(); } @@ -117,15 +125,10 @@ public class PairingProgressDialog extends DialogFragment implements View.OnClic @Override public void onPause() { super.onPause(); - MainApp.bus().unregister(this); + disposable.clear(); running = false; } - @Subscribe - public void onStatusEvent(final EventDanaRSPairingSuccess ev) { - pairingEnded = true; - } - public void setHelperActivity(PairingHelperActivity activity) { this.helperActivity = activity; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRSMessageHashTable.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRSMessageHashTable.java similarity index 97% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRSMessageHashTable.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRSMessageHashTable.java index bda5d42207..a81aa3c9bc 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRSMessageHashTable.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRSMessageHashTable.java @@ -1,9 +1,7 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import java.util.HashMap; -import info.nightscout.androidaps.logging.L; - /** * Created by mike on 28.05.2016. */ diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet.java similarity index 98% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet.java index d913f50b94..3d59b34e16 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import android.annotation.TargetApi; import android.os.Build; @@ -47,8 +47,6 @@ public class DanaRS_Packet { return null; } - ; - // STATIC FUNCTIONS public static int getCommand(byte[] data) { @@ -60,6 +58,9 @@ public class DanaRS_Packet { public void handleMessage(byte[] data) { } + public void handleMessageNotReceived() { + } + public String getFriendlyName() { return "UNKNOWN_PACKET"; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_APS_Basal_Set_Temporary_Basal.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_APS_Basal_Set_Temporary_Basal.java similarity index 98% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_APS_Basal_Set_Temporary_Basal.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_APS_Basal_Set_Temporary_Basal.java index c33cd7b405..c850eace0a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_APS_Basal_Set_Temporary_Basal.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_APS_Basal_Set_Temporary_Basal.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_APS_History_Events.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_APS_History_Events.java similarity index 94% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_APS_History_Events.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_APS_History_Events.java index 98e08a7ee3..fde34c58e0 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_APS_History_Events.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_APS_History_Events.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; @@ -17,10 +17,11 @@ import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.events.EventPumpStatusChanged; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.DetailedBolusInfoStorage; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; -import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; -import info.nightscout.utils.DateUtil; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.pump.common.bolusInfo.DetailedBolusInfoStorage; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; +import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; +import info.nightscout.androidaps.utils.DateUtil; public class DanaRS_Packet_APS_History_Events extends DanaRS_Packet { private Logger log = LoggerFactory.getLogger(L.PUMPCOMM); @@ -129,7 +130,7 @@ public class DanaRS_Packet_APS_History_Events extends DanaRS_Packet { status = "EXTENDEDSTOP " + DateUtil.timeString(datetime); break; case DanaRPump.BOLUS: - DetailedBolusInfo detailedBolusInfo = DetailedBolusInfoStorage.findDetailedBolusInfo(datetime); + DetailedBolusInfo detailedBolusInfo = DetailedBolusInfoStorage.INSTANCE.findDetailedBolusInfo(datetime, param1 / 100d); if (detailedBolusInfo == null) { detailedBolusInfo = new DetailedBolusInfo(); } @@ -144,7 +145,7 @@ public class DanaRS_Packet_APS_History_Events extends DanaRS_Packet { status = "BOLUS " + DateUtil.timeString(datetime); break; case DanaRPump.DUALBOLUS: - detailedBolusInfo = DetailedBolusInfoStorage.findDetailedBolusInfo(datetime); + detailedBolusInfo = DetailedBolusInfoStorage.INSTANCE.findDetailedBolusInfo(datetime, param1 / 100d); if (detailedBolusInfo == null) { detailedBolusInfo = new DetailedBolusInfo(); } @@ -223,7 +224,7 @@ public class DanaRS_Packet_APS_History_Events extends DanaRS_Packet { if (datetime > lastEventTimeLoaded) lastEventTimeLoaded = datetime; - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.processinghistory) + ": " + status)); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.processinghistory) + ": " + status)); } @Override diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_APS_Set_Event_History.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_APS_Set_Event_History.java similarity index 93% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_APS_Set_Event_History.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_APS_Set_Event_History.java index f31bdf66e2..fda5f33959 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_APS_Set_Event_History.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_APS_Set_Event_History.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; @@ -9,8 +9,8 @@ import java.util.Calendar; import java.util.GregorianCalendar; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; -import info.nightscout.utils.DateUtil; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; +import info.nightscout.androidaps.utils.DateUtil; public class DanaRS_Packet_APS_Set_Event_History extends DanaRS_Packet { private Logger log = LoggerFactory.getLogger(L.PUMPCOMM); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Get_Basal_Rate.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Basal_Get_Basal_Rate.java similarity index 70% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Get_Basal_Rate.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Basal_Get_Basal_Rate.java index 3cb5523dfc..830aca2d02 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Get_Basal_Rate.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Basal_Get_Basal_Rate.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; @@ -6,13 +6,16 @@ import com.cozmo.danar.util.BleCommandUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.Locale; + import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; -import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; -import info.nightscout.androidaps.plugins.Overview.notifications.Notification; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification; +import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; public class DanaRS_Packet_Basal_Get_Basal_Rate extends DanaRS_Packet { private Logger log = LoggerFactory.getLogger(L.PUMPCOMM); @@ -49,15 +52,15 @@ public class DanaRS_Packet_Basal_Get_Basal_Rate extends DanaRS_Packet { log.debug("Max basal: " + pump.maxBasal + " U"); log.debug("Basal step: " + pump.basalStep + " U"); for (int index = 0; index < 24; index++) - log.debug("Basal " + String.format("%02d", index) + "h: " + pump.pumpProfiles[pump.activeProfile][index]); + log.debug("Basal " + String.format(Locale.ENGLISH, "%02d", index) + "h: " + pump.pumpProfiles[pump.activeProfile][index]); } if (pump.basalStep != 0.01d) { failed = true; Notification notification = new Notification(Notification.WRONGBASALSTEP, MainApp.gs(R.string.danar_setbasalstep001), Notification.URGENT); - MainApp.bus().post(new EventNewNotification(notification)); + RxBus.INSTANCE.send(new EventNewNotification(notification)); } else { - MainApp.bus().post(new EventDismissNotification(Notification.WRONGBASALSTEP)); + RxBus.INSTANCE.send(new EventDismissNotification(Notification.WRONGBASALSTEP)); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Get_Profile_Basal_Rate.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Basal_Get_Profile_Basal_Rate.java similarity index 85% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Get_Profile_Basal_Rate.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Basal_Get_Profile_Basal_Rate.java index 60b9f6da51..778b794b2a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Get_Profile_Basal_Rate.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Basal_Get_Profile_Basal_Rate.java @@ -1,12 +1,14 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.Locale; + import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; public class DanaRS_Packet_Basal_Get_Profile_Basal_Rate extends DanaRS_Packet { private Logger log = LoggerFactory.getLogger(L.PUMPCOMM); @@ -51,7 +53,7 @@ public class DanaRS_Packet_Basal_Get_Profile_Basal_Rate extends DanaRS_Packet { } if (L.isEnabled(L.PUMPCOMM)) { for (int index = 0; index < 24; index++) - log.debug("Basal " + String.format("%02d", index) + "h: " + pump.pumpProfiles[profileNumber][index]); + log.debug("Basal " + String.format(Locale.ENGLISH, "%02d", index) + "h: " + pump.pumpProfiles[profileNumber][index]); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Get_Profile_Number.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Basal_Get_Profile_Number.java similarity index 89% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Get_Profile_Number.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Basal_Get_Profile_Number.java index 1beadfd705..6da58c7a43 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Get_Profile_Number.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Basal_Get_Profile_Number.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; @@ -6,7 +6,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; public class DanaRS_Packet_Basal_Get_Profile_Number extends DanaRS_Packet { private Logger log = LoggerFactory.getLogger(L.PUMPCOMM); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Get_Temporary_Basal_State.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Basal_Get_Temporary_Basal_State.java similarity index 93% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Get_Temporary_Basal_State.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Basal_Get_Temporary_Basal_State.java index 748d88f242..117baf23ff 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Get_Temporary_Basal_State.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Basal_Get_Temporary_Basal_State.java @@ -1,6 +1,6 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; -import android.support.annotation.NonNull; +import androidx.annotation.NonNull; import com.cozmo.danar.util.BleCommandUtil; @@ -8,8 +8,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; -import info.nightscout.utils.DateUtil; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; +import info.nightscout.androidaps.utils.DateUtil; public class DanaRS_Packet_Basal_Get_Temporary_Basal_State extends DanaRS_Packet { private Logger log = LoggerFactory.getLogger(L.PUMPCOMM); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Basal_Rate.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Basal_Set_Basal_Rate.java similarity index 96% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Basal_Rate.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Basal_Set_Basal_Rate.java index 188c1df093..cef7c8ab92 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Basal_Rate.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Basal_Set_Basal_Rate.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Cancel_Temporary_Basal.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Basal_Set_Cancel_Temporary_Basal.java similarity index 94% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Cancel_Temporary_Basal.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Basal_Set_Cancel_Temporary_Basal.java index f0f2691315..0020e3ffa1 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Cancel_Temporary_Basal.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Basal_Set_Cancel_Temporary_Basal.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Profile_Basal_Rate.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Basal_Set_Profile_Basal_Rate.java similarity index 96% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Profile_Basal_Rate.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Basal_Set_Profile_Basal_Rate.java index a42176cc59..d6ae1c94a7 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Profile_Basal_Rate.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Basal_Set_Profile_Basal_Rate.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Profile_Number.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Basal_Set_Profile_Number.java similarity index 95% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Profile_Number.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Basal_Set_Profile_Number.java index 4f39fcfd2f..ab6f4174da 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Profile_Number.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Basal_Set_Profile_Number.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Suspend_Off.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Basal_Set_Suspend_Off.java similarity index 94% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Suspend_Off.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Basal_Set_Suspend_Off.java index 65ef6ae1b1..5fbda1d902 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Suspend_Off.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Basal_Set_Suspend_Off.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Suspend_On.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Basal_Set_Suspend_On.java similarity index 94% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Suspend_On.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Basal_Set_Suspend_On.java index bde3b622db..82c282adad 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Suspend_On.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Basal_Set_Suspend_On.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Temporary_Basal.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Basal_Set_Temporary_Basal.java similarity index 96% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Temporary_Basal.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Basal_Set_Temporary_Basal.java index 1f6106ab83..f2abcbc164 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Temporary_Basal.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Basal_Set_Temporary_Basal.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Bolus_Option.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Get_Bolus_Option.java similarity index 89% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Bolus_Option.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Get_Bolus_Option.java index 0e5a3d79c4..c656de11cf 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Bolus_Option.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Get_Bolus_Option.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; @@ -8,10 +8,11 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; -import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; -import info.nightscout.androidaps.plugins.Overview.notifications.Notification; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification; +import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; public class DanaRS_Packet_Bolus_Get_Bolus_Option extends DanaRS_Packet { private Logger log = LoggerFactory.getLogger(L.PUMPCOMM); @@ -105,10 +106,10 @@ public class DanaRS_Packet_Bolus_Get_Bolus_Option extends DanaRS_Packet { if (!pump.isExtendedBolusEnabled) { Notification notification = new Notification(Notification.EXTENDED_BOLUS_DISABLED, MainApp.gs(R.string.danar_enableextendedbolus), Notification.URGENT); - MainApp.bus().post(new EventNewNotification(notification)); + RxBus.INSTANCE.send(new EventNewNotification(notification)); failed = true; } else { - MainApp.bus().post(new EventDismissNotification(Notification.EXTENDED_BOLUS_DISABLED)); + RxBus.INSTANCE.send(new EventDismissNotification(Notification.EXTENDED_BOLUS_DISABLED)); } if (L.isEnabled(L.PUMPCOMM)) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_CIR_CF_Array.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Get_CIR_CF_Array.java similarity index 97% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_CIR_CF_Array.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Get_CIR_CF_Array.java index 9b5636eaaf..5dca32bdd3 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_CIR_CF_Array.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Get_CIR_CF_Array.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; @@ -7,7 +7,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; public class DanaRS_Packet_Bolus_Get_CIR_CF_Array extends DanaRS_Packet { private Logger log = LoggerFactory.getLogger(L.PUMPCOMM); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Calculation_Information.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Get_Calculation_Information.java similarity index 95% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Calculation_Information.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Get_Calculation_Information.java index 194edd5d55..b024dd056c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Calculation_Information.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Get_Calculation_Information.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; @@ -6,7 +6,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; public class DanaRS_Packet_Bolus_Get_Calculation_Information extends DanaRS_Packet { private Logger log = LoggerFactory.getLogger(L.PUMPCOMM); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Carbohydrate_Calculation_Information.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Get_Carbohydrate_Calculation_Information.java similarity index 92% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Carbohydrate_Calculation_Information.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Get_Carbohydrate_Calculation_Information.java index 476ae7167f..60da3683ac 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Carbohydrate_Calculation_Information.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Get_Carbohydrate_Calculation_Information.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; @@ -6,7 +6,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; public class DanaRS_Packet_Bolus_Get_Carbohydrate_Calculation_Information extends DanaRS_Packet { private Logger log = LoggerFactory.getLogger(L.PUMPCOMM); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Dual_Bolus.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Get_Dual_Bolus.java similarity index 93% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Dual_Bolus.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Get_Dual_Bolus.java index 7d561bd679..5f1bbc5a39 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Dual_Bolus.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Get_Dual_Bolus.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; @@ -6,7 +6,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; public class DanaRS_Packet_Bolus_Get_Dual_Bolus extends DanaRS_Packet { private Logger log = LoggerFactory.getLogger(L.PUMPCOMM); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Extended_Bolus.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Get_Extended_Bolus.java similarity index 93% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Extended_Bolus.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Get_Extended_Bolus.java index 785d8d3fbe..2b857e3fc8 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Extended_Bolus.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Get_Extended_Bolus.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; @@ -6,7 +6,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; public class DanaRS_Packet_Bolus_Get_Extended_Bolus extends DanaRS_Packet { private Logger log = LoggerFactory.getLogger(L.PUMPCOMM); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Extended_Bolus_State.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Get_Extended_Bolus_State.java similarity index 94% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Extended_Bolus_State.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Get_Extended_Bolus_State.java index a07652218f..15d2678451 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Extended_Bolus_State.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Get_Extended_Bolus_State.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; @@ -6,7 +6,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; public class DanaRS_Packet_Bolus_Get_Extended_Bolus_State extends DanaRS_Packet { private Logger log = LoggerFactory.getLogger(L.PUMPCOMM); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Extended_Menu_Option_State.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Get_Extended_Menu_Option_State.java similarity index 91% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Extended_Menu_Option_State.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Get_Extended_Menu_Option_State.java index fda8778d08..9e66d9458b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Extended_Menu_Option_State.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Get_Extended_Menu_Option_State.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; @@ -6,7 +6,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; public class DanaRS_Packet_Bolus_Get_Extended_Menu_Option_State extends DanaRS_Packet { private Logger log = LoggerFactory.getLogger(L.PUMPCOMM); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Initial_Bolus.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Get_Initial_Bolus.java similarity index 96% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Initial_Bolus.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Get_Initial_Bolus.java index 15ad57d83a..37c9d9138e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Initial_Bolus.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Get_Initial_Bolus.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Step_Bolus_Information.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Get_Step_Bolus_Information.java similarity index 93% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Step_Bolus_Information.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Get_Step_Bolus_Information.java index a9968eb7eb..755fff3829 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Step_Bolus_Information.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Get_Step_Bolus_Information.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; @@ -8,8 +8,8 @@ import org.slf4j.LoggerFactory; import java.util.Date; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; -import info.nightscout.utils.DateUtil; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; +import info.nightscout.androidaps.utils.DateUtil; public class DanaRS_Packet_Bolus_Get_Step_Bolus_Information extends DanaRS_Packet { private Logger log = LoggerFactory.getLogger(L.PUMPCOMM); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Bolus_Option.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Set_Bolus_Option.java similarity index 98% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Bolus_Option.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Set_Bolus_Option.java index cc4a26f24f..2013bd74eb 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Bolus_Option.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Set_Bolus_Option.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_CIR_CF_Array.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Set_CIR_CF_Array.java similarity index 98% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_CIR_CF_Array.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Set_CIR_CF_Array.java index 15bde78a76..50a6871bd4 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_CIR_CF_Array.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Set_CIR_CF_Array.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Dual_Bolus.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Set_Dual_Bolus.java similarity index 97% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Dual_Bolus.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Set_Dual_Bolus.java index 023458e5dc..da11d172fc 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Dual_Bolus.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Set_Dual_Bolus.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Extended_Bolus.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Set_Extended_Bolus.java similarity index 96% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Extended_Bolus.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Set_Extended_Bolus.java index 504b21bbc9..4337663d6d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Extended_Bolus.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Set_Extended_Bolus.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Extended_Bolus_Cancel.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Set_Extended_Bolus_Cancel.java similarity index 94% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Extended_Bolus_Cancel.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Set_Extended_Bolus_Cancel.java index 587e87df9d..e8d9df360c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Extended_Bolus_Cancel.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Set_Extended_Bolus_Cancel.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Initial_Bolus.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Set_Initial_Bolus.java similarity index 97% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Initial_Bolus.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Set_Initial_Bolus.java index 2e7b9be1ff..206a61b6f5 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Initial_Bolus.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Set_Initial_Bolus.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Step_Bolus_Start.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Set_Step_Bolus_Start.java similarity index 94% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Step_Bolus_Start.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Set_Step_Bolus_Start.java index e50fbd70b5..7ff91fa9ef 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Step_Bolus_Start.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Set_Step_Bolus_Start.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; @@ -6,7 +6,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.data.ConstraintChecker; import info.nightscout.androidaps.interfaces.Constraint; import info.nightscout.androidaps.logging.L; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Step_Bolus_Stop.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Set_Step_Bolus_Stop.java similarity index 74% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Step_Bolus_Stop.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Set_Step_Bolus_Stop.java index e12b3db7f1..7cb0a11f9b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Step_Bolus_Stop.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Bolus_Set_Step_Bolus_Stop.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -9,8 +9,9 @@ import info.nightscout.androidaps.R; import com.cozmo.danar.util.BleCommandUtil; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.Treatments.Treatment; -import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.treatments.Treatment; +import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress; public class DanaRS_Packet_Bolus_Set_Step_Bolus_Stop extends DanaRS_Packet { private Logger log = LoggerFactory.getLogger(L.PUMPCOMM); @@ -47,16 +48,16 @@ public class DanaRS_Packet_Bolus_Set_Step_Bolus_Stop extends DanaRS_Packet { } } - EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance(); + EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.INSTANCE; stopped = true; if (!forced) { t.insulin = amount; - bolusingEvent.status = MainApp.gs(R.string.overview_bolusprogress_delivered); - bolusingEvent.percent = 100; + bolusingEvent.setStatus(MainApp.gs(R.string.overview_bolusprogress_delivered)); + bolusingEvent.setPercent(100); } else { - bolusingEvent.status = MainApp.gs(R.string.overview_bolusprogress_stoped); + bolusingEvent.setStatus(MainApp.gs(R.string.overview_bolusprogress_stoped)); } - MainApp.bus().post(bolusingEvent); + RxBus.INSTANCE.send(bolusingEvent); } @Override diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Etc_Keep_Connection.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Etc_Keep_Connection.java similarity index 93% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Etc_Keep_Connection.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Etc_Keep_Connection.java index 8adf46f742..306787d4ee 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Etc_Keep_Connection.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Etc_Keep_Connection.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Etc_Set_History_Save.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Etc_Set_History_Save.java similarity index 97% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Etc_Set_History_Save.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Etc_Set_History_Save.java index 1c9af359e2..7c0b652979 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Etc_Set_History_Save.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Etc_Set_History_Save.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Delivery_Status.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_General_Delivery_Status.java similarity index 94% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Delivery_Status.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_General_Delivery_Status.java index c64680379f..0f5e4a8e02 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Delivery_Status.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_General_Delivery_Status.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Get_More_Information.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_General_Get_More_Information.java similarity index 95% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Get_More_Information.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_General_Get_More_Information.java index b1553a2c05..f14197ac41 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Get_More_Information.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_General_Get_More_Information.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; @@ -8,7 +8,7 @@ import org.slf4j.LoggerFactory; import java.util.Date; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; public class DanaRS_Packet_General_Get_More_Information extends DanaRS_Packet { private Logger log = LoggerFactory.getLogger(L.PUMPCOMM); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Get_Password.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_General_Get_Password.java similarity index 90% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Get_Password.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_General_Get_Password.java index dc5cbc59f0..0a4d15d456 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Get_Password.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_General_Get_Password.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; @@ -6,7 +6,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; public class DanaRS_Packet_General_Get_Password extends DanaRS_Packet { private Logger log = LoggerFactory.getLogger(L.PUMPCOMM); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Get_Pump_Check.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_General_Get_Pump_Check.java similarity index 74% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Get_Pump_Check.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_General_Get_Pump_Check.java index 5c26e2ce74..f9bda3dfe5 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Get_Pump_Check.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_General_Get_Pump_Check.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; @@ -8,9 +8,10 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; -import info.nightscout.androidaps.plugins.Overview.notifications.Notification; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; public class DanaRS_Packet_General_Get_Pump_Check extends DanaRS_Packet { private Logger log = LoggerFactory.getLogger(L.PUMPCOMM); @@ -24,7 +25,7 @@ public class DanaRS_Packet_General_Get_Pump_Check extends DanaRS_Packet { @Override public void handleMessage(byte[] data) { - if (data.length <5){ + if (data.length < 5) { failed = true; return; } @@ -49,7 +50,7 @@ public class DanaRS_Packet_General_Get_Pump_Check extends DanaRS_Packet { } if (pump.productCode < 2) { - MainApp.bus().post(new EventNewNotification(new Notification(Notification.UNSUPPORTED_FIRMWARE, MainApp.gs(R.string.unsupportedfirmware), Notification.URGENT))); + RxBus.INSTANCE.send(new EventNewNotification(new Notification(Notification.UNSUPPORTED_FIRMWARE, MainApp.gs(R.string.unsupportedfirmware), Notification.URGENT))); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Get_Shipping_Information.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_General_Get_Shipping_Information.java similarity index 89% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Get_Shipping_Information.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_General_Get_Shipping_Information.java index f2cb14cf73..e1efa91296 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Get_Shipping_Information.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_General_Get_Shipping_Information.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; @@ -6,8 +6,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; -import info.nightscout.utils.DateUtil; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; +import info.nightscout.androidaps.utils.DateUtil; public class DanaRS_Packet_General_Get_Shipping_Information extends DanaRS_Packet { private Logger log = LoggerFactory.getLogger(L.PUMPCOMM); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Get_Today_Delivery_Total.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_General_Get_Today_Delivery_Total.java similarity index 92% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Get_Today_Delivery_Total.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_General_Get_Today_Delivery_Total.java index 2a3b136279..c154ac3476 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Get_Today_Delivery_Total.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_General_Get_Today_Delivery_Total.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; @@ -6,7 +6,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; public class DanaRS_Packet_General_Get_Today_Delivery_Total extends DanaRS_Packet { private Logger log = LoggerFactory.getLogger(L.PUMPCOMM); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Get_User_Time_Change_Flag.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_General_Get_User_Time_Change_Flag.java similarity index 94% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Get_User_Time_Change_Flag.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_General_Get_User_Time_Change_Flag.java index 0d07ecc33d..65bf066023 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Get_User_Time_Change_Flag.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_General_Get_User_Time_Change_Flag.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Initial_Screen_Information.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_General_Initial_Screen_Information.java similarity index 96% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Initial_Screen_Information.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_General_Initial_Screen_Information.java index d8e5b95c14..75b969b1bc 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Initial_Screen_Information.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_General_Initial_Screen_Information.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; @@ -6,7 +6,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; public class DanaRS_Packet_General_Initial_Screen_Information extends DanaRS_Packet { private Logger log = LoggerFactory.getLogger(L.PUMPCOMM); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Set_History_Upload_Mode.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_General_Set_History_Upload_Mode.java similarity index 95% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Set_History_Upload_Mode.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_General_Set_History_Upload_Mode.java index f66c3c4afe..21a15b1dbd 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Set_History_Upload_Mode.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_General_Set_History_Upload_Mode.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Set_User_Time_Change_Flag_Clear.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_General_Set_User_Time_Change_Flag_Clear.java similarity index 94% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Set_User_Time_Change_Flag_Clear.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_General_Set_User_Time_Change_Flag_Clear.java index 9f7570d4ce..b8771c1939 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Set_User_Time_Change_Flag_Clear.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_General_Set_User_Time_Change_Flag_Clear.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_History_.java similarity index 95% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_History_.java index aab933e787..07893346d7 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_History_.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -10,9 +10,10 @@ import java.util.GregorianCalendar; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.db.DanaRHistoryRecord; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes; -import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRSyncStatus; -import info.nightscout.utils.DateUtil; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.pump.danaR.comm.RecordTypes; +import info.nightscout.androidaps.plugins.pump.danaR.events.EventDanaRSyncStatus; +import info.nightscout.androidaps.utils.DateUtil; public abstract class DanaRS_Packet_History_ extends DanaRS_Packet { private Logger log = LoggerFactory.getLogger(L.PUMPCOMM); @@ -109,7 +110,6 @@ public abstract class DanaRS_Packet_History_ extends DanaRS_Packet { log.debug("History packet: " + recordCode + " Date: " + datetimewihtsec.toLocaleString() + " Code: " + historyCode + " Value: " + value); - EventDanaRSyncStatus ev = new EventDanaRSyncStatus(); DanaRHistoryRecord danaRHistoryRecord = new DanaRHistoryRecord(); danaRHistoryRecord.setBytes(data); @@ -224,9 +224,7 @@ public abstract class DanaRS_Packet_History_ extends DanaRS_Packet { MainApp.getDbHelper().createOrUpdate(danaRHistoryRecord); - ev.message = DateUtil.dateAndTimeString(danaRHistoryRecord.recordDate); - ev.message += " " + messageType; - MainApp.bus().post(ev); + RxBus.INSTANCE.send(new EventDanaRSyncStatus(DateUtil.dateAndTimeString(danaRHistoryRecord.recordDate) + " " + messageType)); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Alarm.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_History_Alarm.java similarity index 89% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Alarm.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_History_Alarm.java index e586166783..437804b102 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Alarm.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_History_Alarm.java @@ -1,12 +1,10 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.Date; - import info.nightscout.androidaps.logging.L; public class DanaRS_Packet_History_Alarm extends DanaRS_Packet_History_ { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_All_History.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_History_All_History.java similarity index 92% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_All_History.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_History_All_History.java index f6411dca5f..68940dd4c5 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_All_History.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_History_All_History.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Basal.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_History_Basal.java similarity index 92% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Basal.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_History_Basal.java index 76d485695c..0a94f16a40 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Basal.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_History_Basal.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Blood_Glucose.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_History_Blood_Glucose.java similarity index 92% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Blood_Glucose.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_History_Blood_Glucose.java index e66db9bb78..dc0e00d844 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Blood_Glucose.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_History_Blood_Glucose.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Bolus.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_History_Bolus.java similarity index 92% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Bolus.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_History_Bolus.java index 41a2bd0995..64fb26dd09 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Bolus.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_History_Bolus.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Carbohydrate.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_History_Carbohydrate.java similarity index 92% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Carbohydrate.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_History_Carbohydrate.java index 58d9fac3dc..9cd931718d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Carbohydrate.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_History_Carbohydrate.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Daily.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_History_Daily.java similarity index 92% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Daily.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_History_Daily.java index b480f76258..35a154f5e6 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Daily.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_History_Daily.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Prime.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_History_Prime.java similarity index 92% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Prime.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_History_Prime.java index 28ea4c30f0..7ec05fc0e0 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Prime.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_History_Prime.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Refill.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_History_Refill.java similarity index 92% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Refill.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_History_Refill.java index 685c8e519e..e031ee1460 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Refill.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_History_Refill.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Suspend.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_History_Suspend.java similarity index 92% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Suspend.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_History_Suspend.java index ef787746ce..20f4de5098 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Suspend.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_History_Suspend.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Temporary.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_History_Temporary.java similarity index 92% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Temporary.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_History_Temporary.java index 68526b5fb2..65f86c5b7f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Temporary.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_History_Temporary.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Notify_Alarm.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Notify_Alarm.java similarity index 95% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Notify_Alarm.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Notify_Alarm.java index 799b3c248c..4fc28e4cc9 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Notify_Alarm.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Notify_Alarm.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; @@ -8,7 +8,7 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.NSClientInternal.NSUpload; +import info.nightscout.androidaps.plugins.general.nsclient.NSUpload; public class DanaRS_Packet_Notify_Alarm extends DanaRS_Packet { private Logger log = LoggerFactory.getLogger(L.PUMPCOMM); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Notify_Delivery_Complete.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Notify_Delivery_Complete.java similarity index 72% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Notify_Delivery_Complete.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Notify_Delivery_Complete.java index 836a52cb65..00b6483fbb 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Notify_Delivery_Complete.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Notify_Delivery_Complete.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; @@ -8,8 +8,9 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress; -import info.nightscout.androidaps.plugins.Treatments.Treatment; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress; +import info.nightscout.androidaps.plugins.treatments.Treatment; public class DanaRS_Packet_Notify_Delivery_Complete extends DanaRS_Packet { private Logger log = LoggerFactory.getLogger(L.PUMPCOMM); @@ -39,12 +40,12 @@ public class DanaRS_Packet_Notify_Delivery_Complete extends DanaRS_Packet { if (t != null) { t.insulin = deliveredInsulin; - EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance(); - bolusingEvent.status = String.format(MainApp.gs(R.string.bolusdelivering), deliveredInsulin); - bolusingEvent.t = t; - bolusingEvent.percent = Math.min((int) (deliveredInsulin / amount * 100), 100); + EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.INSTANCE; + bolusingEvent.setStatus(String.format(MainApp.gs(R.string.bolusdelivering), deliveredInsulin)); + bolusingEvent.setT(t); + bolusingEvent.setPercent(Math.min((int) (deliveredInsulin / amount * 100), 100)); done = true; - MainApp.bus().post(bolusingEvent); + RxBus.INSTANCE.send(bolusingEvent); } if (L.isEnabled(L.PUMPCOMM)) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Notify_Delivery_Rate_Display.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Notify_Delivery_Rate_Display.java similarity index 71% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Notify_Delivery_Rate_Display.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Notify_Delivery_Rate_Display.java index c2eb232dac..1d650cb779 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Notify_Delivery_Rate_Display.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Notify_Delivery_Rate_Display.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; @@ -8,8 +8,9 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress; -import info.nightscout.androidaps.plugins.Treatments.Treatment; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress; +import info.nightscout.androidaps.plugins.treatments.Treatment; public class DanaRS_Packet_Notify_Delivery_Rate_Display extends DanaRS_Packet { private Logger log = LoggerFactory.getLogger(L.PUMPCOMM); @@ -40,12 +41,12 @@ public class DanaRS_Packet_Notify_Delivery_Rate_Display extends DanaRS_Packet { if (t != null) { lastReceive = System.currentTimeMillis(); t.insulin = deliveredInsulin; - EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance(); - bolusingEvent.status = String.format(MainApp.gs(R.string.bolusdelivering), deliveredInsulin); - bolusingEvent.t = t; - bolusingEvent.percent = Math.min((int) (deliveredInsulin / amount * 100), 100); - failed = bolusingEvent.percent < 100? true: false; - MainApp.bus().post(bolusingEvent); + EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.INSTANCE; + bolusingEvent.setStatus(String.format(MainApp.gs(R.string.bolusdelivering), deliveredInsulin)); + bolusingEvent.setT(t); + bolusingEvent.setPercent(Math.min((int) (deliveredInsulin / amount * 100), 100)); + failed = bolusingEvent.getPercent() < 100? true: false; + RxBus.INSTANCE.send(bolusingEvent); } if (L.isEnabled(L.PUMPCOMM)) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Notify_Missed_Bolus_Alarm.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Notify_Missed_Bolus_Alarm.java similarity index 96% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Notify_Missed_Bolus_Alarm.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Notify_Missed_Bolus_Alarm.java index 8239bb34b7..0d7d9af2c5 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Notify_Missed_Bolus_Alarm.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Notify_Missed_Bolus_Alarm.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Option_Get_Pump_Time.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Option_Get_Pump_Time.java similarity index 88% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Option_Get_Pump_Time.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Option_Get_Pump_Time.java index b4bcbaef98..500c1707b6 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Option_Get_Pump_Time.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Option_Get_Pump_Time.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; @@ -8,7 +8,7 @@ import org.slf4j.LoggerFactory; import java.util.Date; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; public class DanaRS_Packet_Option_Get_Pump_Time extends DanaRS_Packet { private Logger log = LoggerFactory.getLogger(L.PUMPCOMM); @@ -58,6 +58,11 @@ public class DanaRS_Packet_Option_Get_Pump_Time extends DanaRS_Packet { } } + @Override + public void handleMessageNotReceived() { + DanaRPump.getInstance().pumpTime = 0; + } + @Override public String getFriendlyName() { return "OPTION__GET_PUMP_TIME"; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Option_Get_User_Option.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Option_Get_User_Option.java similarity index 97% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Option_Get_User_Option.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Option_Get_User_Option.java index 6c6d7d7185..457b7ab2b8 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Option_Get_User_Option.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Option_Get_User_Option.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; @@ -6,7 +6,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; public class DanaRS_Packet_Option_Get_User_Option extends DanaRS_Packet { private Logger log = LoggerFactory.getLogger(L.PUMPCOMM); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Option_Set_Pump_Time.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Option_Set_Pump_Time.java similarity index 96% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Option_Set_Pump_Time.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Option_Set_Pump_Time.java index f43f82fb15..58bf00e6a6 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Option_Set_Pump_Time.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Option_Set_Pump_Time.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Option_Set_User_Option.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Option_Set_User_Option.java similarity index 95% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Option_Set_User_Option.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Option_Set_User_Option.java index a64e1e5142..30fc07cfd0 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Option_Set_User_Option.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Option_Set_User_Option.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; @@ -6,7 +6,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; public class DanaRS_Packet_Option_Set_User_Option extends DanaRS_Packet { private Logger log = LoggerFactory.getLogger(L.PUMPCOMM); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Review_Bolus_Avg.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Review_Bolus_Avg.java similarity index 97% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Review_Bolus_Avg.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Review_Bolus_Avg.java index 7a2421c310..50edd71bd6 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Review_Bolus_Avg.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Review_Bolus_Avg.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.comm; +package info.nightscout.androidaps.plugins.pump.danaRS.comm; import com.cozmo.danar.util.BleCommandUtil; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/events/EventDanaRSDeviceChange.kt b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/events/EventDanaRSDeviceChange.kt new file mode 100644 index 0000000000..8b87d59ec1 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/events/EventDanaRSDeviceChange.kt @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.pump.danaRS.events + +import info.nightscout.androidaps.events.Event + +class EventDanaRSDeviceChange : Event() \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/events/EventDanaRSPairingSuccess.kt b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/events/EventDanaRSPairingSuccess.kt new file mode 100644 index 0000000000..6e0379a4d3 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/events/EventDanaRSPairingSuccess.kt @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.pump.danaRS.events + +import info.nightscout.androidaps.events.Event + +class EventDanaRSPairingSuccess : Event() diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/BLEComm.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/services/BLEComm.java similarity index 93% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/BLEComm.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/services/BLEComm.java index 48bb311385..8a43d6e35a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/BLEComm.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/services/BLEComm.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.services; +package info.nightscout.androidaps.plugins.pump.danaRS.services; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; @@ -26,17 +26,17 @@ import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.events.EventPumpStatusChanged; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; -import info.nightscout.androidaps.plugins.Overview.notifications.Notification; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; -import info.nightscout.androidaps.plugins.PumpDanaRS.DanaRSPlugin; -import info.nightscout.androidaps.plugins.PumpDanaRS.activities.PairingHelperActivity; -import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRSMessageHashTable; -import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet; -import info.nightscout.androidaps.plugins.PumpDanaRS.events.EventDanaRSPacket; -import info.nightscout.androidaps.plugins.PumpDanaRS.events.EventDanaRSPairingSuccess; -import info.nightscout.androidaps.plugins.NSClientInternal.NSUpload; -import info.nightscout.utils.SP; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.general.nsclient.NSUpload; +import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaRS.DanaRSPlugin; +import info.nightscout.androidaps.plugins.pump.danaRS.activities.PairingHelperActivity; +import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRSMessageHashTable; +import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet; +import info.nightscout.androidaps.plugins.pump.danaRS.events.EventDanaRSPairingSuccess; +import info.nightscout.androidaps.utils.SP; /** * Created by mike on 23.09.2017. @@ -338,7 +338,7 @@ public class BLEComm { close(); isConnected = false; isConnecting = false; - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTED)); + RxBus.INSTANCE.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTED)); if (L.isEnabled(L.PUMPBTCOMM)) log.debug("Device was disconnected " + gatt.getDevice().getName());//Device was disconnected } @@ -451,24 +451,24 @@ public class BLEComm { if (L.isEnabled(L.PUMPBTCOMM)) log.debug("<<<<< " + "ENCRYPTION__PUMP_CHECK (PUMP)" + " " + DanaRS_Packet.toHexString(inputBuffer)); mSendQueue.clear(); - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTED, MainApp.gs(R.string.pumperror))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTED, MainApp.gs(R.string.pumperror))); NSUpload.uploadError(MainApp.gs(R.string.pumperror)); Notification n = new Notification(Notification.PUMPERROR, MainApp.gs(R.string.pumperror), Notification.URGENT); - MainApp.bus().post(new EventNewNotification(n)); + RxBus.INSTANCE.send(new EventNewNotification(n)); } else if (inputBuffer.length == 6 && inputBuffer[2] == 'B' && inputBuffer[3] == 'U' && inputBuffer[4] == 'S' && inputBuffer[5] == 'Y') { if (L.isEnabled(L.PUMPBTCOMM)) log.debug("<<<<< " + "ENCRYPTION__PUMP_CHECK (BUSY)" + " " + DanaRS_Packet.toHexString(inputBuffer)); mSendQueue.clear(); - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTED, MainApp.gs(R.string.pumpbusy))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTED, MainApp.gs(R.string.pumpbusy))); } else { // ERROR in response, wrong serial number if (L.isEnabled(L.PUMPBTCOMM)) log.debug("<<<<< " + "ENCRYPTION__PUMP_CHECK (ERROR)" + " " + DanaRS_Packet.toHexString(inputBuffer)); mSendQueue.clear(); - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTED, MainApp.gs(R.string.connectionerror))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTED, MainApp.gs(R.string.connectionerror))); SP.remove(MainApp.gs(R.string.key_danars_pairingkey) + DanaRSPlugin.mDeviceName); Notification n = new Notification(Notification.WRONGSERIALNUMBER, MainApp.gs(R.string.wrongpassword), Notification.URGENT); - MainApp.bus().post(new EventNewNotification(n)); + RxBus.INSTANCE.send(new EventNewNotification(n)); } break; // 2nd packet, pairing key @@ -495,7 +495,7 @@ public class BLEComm { if (L.isEnabled(L.PUMPBTCOMM)) log.debug("<<<<< " + "ENCRYPTION__PASSKEY_RETURN " + DanaRS_Packet.toHexString(inputBuffer)); // Paring is successfull, sending time info - MainApp.bus().post(new EventDanaRSPairingSuccess()); + RxBus.INSTANCE.send(new EventDanaRSPairingSuccess()); SendTimeInfo(); byte[] pairingKey = {inputBuffer[2], inputBuffer[3]}; // store pairing key to preferences @@ -514,7 +514,7 @@ public class BLEComm { if (L.isEnabled(L.PUMPBTCOMM)) log.debug("Pump user password: " + Integer.toHexString(pass)); - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.CONNECTED)); + RxBus.INSTANCE.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.CONNECTED)); isConnected = true; isConnecting = false; if (L.isEnabled(L.PUMPBTCOMM)) @@ -545,7 +545,6 @@ public class BLEComm { // notify to sendMessage message.notify(); } - MainApp.bus().post(new EventDanaRSPacket(message)); } else { log.error("Unknown message received " + DanaRS_Packet.toHexString(inputBuffer)); } @@ -643,6 +642,7 @@ public class BLEComm { //SystemClock.sleep(200); if (!message.isReceived()) { log.warn("Reply not received " + message.getFriendlyName()); + message.handleMessageNotReceived(); } } @@ -663,9 +663,9 @@ public class BLEComm { private void SendPumpCheck() { // 1st message sent to pump after connect String devicename = getConnectDeviceName(); - if(devicename == null || devicename.equals("")){ + if (devicename == null || devicename.equals("")) { Notification n = new Notification(Notification.DEVICENOTPAIRED, MainApp.gs(R.string.pairfirst), Notification.URGENT); - MainApp.bus().post(new EventNewNotification(n)); + RxBus.INSTANCE.send(new EventNewNotification(n)); return; } byte[] bytes = BleCommandUtil.getInstance().getEncryptedPacket(BleCommandUtil.DANAR_PACKET__OPCODE_ENCRYPTION__PUMP_CHECK, null, devicename); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/DanaRSService.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/services/DanaRSService.java similarity index 64% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/DanaRSService.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/services/DanaRSService.java index cb823a3c88..2850f08c8d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/DanaRSService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/services/DanaRSService.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS.services; +package info.nightscout.androidaps.plugins.pump.danaRS.services; import android.app.Service; import android.content.Intent; @@ -6,8 +6,6 @@ import android.os.Binder; import android.os.IBinder; import android.os.SystemClock; -import com.squareup.otto.Subscribe; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -20,71 +18,76 @@ import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.events.EventAppExit; import info.nightscout.androidaps.events.EventInitializationChanged; -import info.nightscout.androidaps.events.EventProfileSwitchChange; +import info.nightscout.androidaps.events.EventProfileNeedsUpdate; import info.nightscout.androidaps.events.EventPumpStatusChanged; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions; -import info.nightscout.androidaps.plugins.Overview.Dialogs.BolusProgressDialog; -import info.nightscout.androidaps.plugins.Overview.Dialogs.ErrorHelperActivity; -import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; -import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress; -import info.nightscout.androidaps.plugins.Overview.notifications.Notification; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes; -import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRNewStatus; -import info.nightscout.androidaps.plugins.PumpDanaRS.DanaRSPlugin; -import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet; -import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_APS_Basal_Set_Temporary_Basal; -import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_APS_History_Events; -import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_APS_Set_Event_History; -import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Basal_Get_Basal_Rate; -import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Basal_Get_Profile_Number; -import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Basal_Get_Temporary_Basal_State; -import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Basal_Set_Cancel_Temporary_Basal; -import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Basal_Set_Profile_Basal_Rate; -import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Basal_Set_Profile_Number; -import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Basal_Set_Temporary_Basal; -import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Bolus_Get_Bolus_Option; -import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Bolus_Get_CIR_CF_Array; -import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Bolus_Get_Calculation_Information; -import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Bolus_Get_Extended_Bolus_State; -import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Bolus_Get_Step_Bolus_Information; -import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Bolus_Set_Extended_Bolus; -import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Bolus_Set_Extended_Bolus_Cancel; -import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Bolus_Set_Step_Bolus_Start; -import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Bolus_Set_Step_Bolus_Stop; -import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_General_Get_Pump_Check; -import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_General_Get_Shipping_Information; -import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_General_Initial_Screen_Information; -import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_General_Set_History_Upload_Mode; -import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_History_; -import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_History_Alarm; -import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_History_Basal; -import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_History_Blood_Glucose; -import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_History_Bolus; -import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_History_Carbohydrate; -import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_History_Daily; -import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_History_Prime; -import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_History_Refill; -import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_History_Suspend; -import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Notify_Delivery_Complete; -import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Notify_Delivery_Rate_Display; -import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Option_Get_Pump_Time; -import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Option_Get_User_Option; -import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Option_Set_Pump_Time; -import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Option_Set_User_Option; -import info.nightscout.androidaps.plugins.Treatments.Treatment; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; +import info.nightscout.androidaps.plugins.general.nsclient.NSUpload; +import info.nightscout.androidaps.plugins.general.overview.dialogs.BolusProgressDialog; +import info.nightscout.androidaps.plugins.general.overview.dialogs.ErrorHelperActivity; +import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress; +import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaR.comm.RecordTypes; +import info.nightscout.androidaps.plugins.pump.danaR.events.EventDanaRNewStatus; +import info.nightscout.androidaps.plugins.pump.danaRS.DanaRSPlugin; +import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet; +import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_APS_Basal_Set_Temporary_Basal; +import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_APS_History_Events; +import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_APS_Set_Event_History; +import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_Basal_Get_Basal_Rate; +import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_Basal_Get_Profile_Number; +import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_Basal_Get_Temporary_Basal_State; +import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_Basal_Set_Cancel_Temporary_Basal; +import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_Basal_Set_Profile_Basal_Rate; +import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_Basal_Set_Profile_Number; +import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_Basal_Set_Temporary_Basal; +import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_Bolus_Get_Bolus_Option; +import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_Bolus_Get_CIR_CF_Array; +import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_Bolus_Get_Calculation_Information; +import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_Bolus_Get_Extended_Bolus_State; +import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_Bolus_Get_Step_Bolus_Information; +import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_Bolus_Set_Extended_Bolus; +import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_Bolus_Set_Extended_Bolus_Cancel; +import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_Bolus_Set_Step_Bolus_Start; +import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_Bolus_Set_Step_Bolus_Stop; +import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_General_Get_Pump_Check; +import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_General_Get_Shipping_Information; +import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_General_Initial_Screen_Information; +import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_General_Set_History_Upload_Mode; +import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_History_; +import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_History_Alarm; +import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_History_Basal; +import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_History_Blood_Glucose; +import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_History_Bolus; +import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_History_Carbohydrate; +import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_History_Daily; +import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_History_Prime; +import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_History_Refill; +import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_History_Suspend; +import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_Notify_Delivery_Complete; +import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_Notify_Delivery_Rate_Display; +import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_Option_Get_Pump_Time; +import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_Option_Get_User_Option; +import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_Option_Set_Pump_Time; +import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_Option_Set_User_Option; +import info.nightscout.androidaps.plugins.treatments.Treatment; import info.nightscout.androidaps.queue.Callback; import info.nightscout.androidaps.queue.commands.Command; -import info.nightscout.utils.DateUtil; -import info.nightscout.androidaps.plugins.NSClientInternal.NSUpload; -import info.nightscout.utils.SP; -import info.nightscout.utils.T; +import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.FabricPrivacy; +import info.nightscout.androidaps.utils.SP; +import info.nightscout.androidaps.utils.T; +import io.reactivex.disposables.CompositeDisposable; +import io.reactivex.schedulers.Schedulers; public class DanaRSService extends Service { private Logger log = LoggerFactory.getLogger(L.PUMPCOMM); + private CompositeDisposable disposable = new CompositeDisposable(); private BLEComm bleComm = BLEComm.getInstance(this); @@ -96,12 +99,25 @@ public class DanaRSService extends Service { private long lastApproachingDailyLimit = 0; public DanaRSService() { - try { - MainApp.bus().unregister(this); - } catch (RuntimeException x) { - // Ignore - } - MainApp.bus().register(this); + } + + @Override + public void onCreate() { + super.onCreate(); + disposable.add(RxBus.INSTANCE + .toObservable(EventAppExit.class) + .observeOn(Schedulers.io()) + .subscribe(event -> { + if (L.isEnabled(L.PUMP)) log.debug("EventAppExit received"); + stopSelf(); + }, FabricPrivacy::logException) + ); + } + + @Override + public void onDestroy() { + disposable.clear(); + super.onDestroy(); } public boolean isConnected() { @@ -131,14 +147,14 @@ public class DanaRSService extends Service { public void getPumpStatus() { DanaRPump danaRPump = DanaRPump.getInstance(); try { - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumpstatus))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumpstatus))); bleComm.sendMessage(new DanaRS_Packet_General_Initial_Screen_Information()); - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingextendedbolusstatus))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.gettingextendedbolusstatus))); bleComm.sendMessage(new DanaRS_Packet_Bolus_Get_Extended_Bolus_State()); - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingbolusstatus))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.gettingbolusstatus))); bleComm.sendMessage(new DanaRS_Packet_Bolus_Get_Step_Bolus_Information()); // last bolus, bolusStep, maxBolus - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingtempbasalstatus))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.gettingtempbasalstatus))); bleComm.sendMessage(new DanaRS_Packet_Basal_Get_Temporary_Basal_State()); danaRPump.lastConnection = System.currentTimeMillis(); @@ -146,17 +162,25 @@ public class DanaRSService extends Service { Profile profile = ProfileFunctions.getInstance().getProfile(); PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump(); if (profile != null && Math.abs(danaRPump.currentBasal - profile.getBasal()) >= pump.getPumpDescription().basalStep) { - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumpsettings))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumpsettings))); bleComm.sendMessage(new DanaRS_Packet_Basal_Get_Basal_Rate()); // basal profile, basalStep, maxBasal if (!pump.isThisProfileSet(profile) && !ConfigBuilderPlugin.getPlugin().getCommandQueue().isRunning(Command.CommandType.BASALPROFILE)) { - MainApp.bus().post(new EventProfileSwitchChange()); + RxBus.INSTANCE.send(new EventProfileNeedsUpdate()); } } - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumptime))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumptime))); bleComm.sendMessage(new DanaRS_Packet_Option_Get_Pump_Time()); long timeDiff = (danaRPump.pumpTime - System.currentTimeMillis()) / 1000L; + if (danaRPump.pumpTime == 0) { + // initial handshake was not successfull + // deinitialize pump + danaRPump.lastConnection = 0; + RxBus.INSTANCE.send(new EventDanaRNewStatus()); + RxBus.INSTANCE.send(new EventInitializationChanged()); + return; + } if (L.isEnabled(L.PUMPCOMM)) log.debug("Pump time difference: " + timeDiff + " seconds"); if (Math.abs(timeDiff) > 3) { @@ -173,8 +197,8 @@ public class DanaRSService extends Service { //deinitialize pump danaRPump.lastConnection = 0; - MainApp.bus().post(new EventDanaRNewStatus()); - MainApp.bus().post(new EventInitializationChanged()); + RxBus.INSTANCE.send(new EventDanaRNewStatus()); + RxBus.INSTANCE.send(new EventInitializationChanged()); return; } else { waitForWholeMinute(); // Dana can set only whole minute @@ -189,7 +213,7 @@ public class DanaRSService extends Service { long now = System.currentTimeMillis(); if (danaRPump.lastSettingsRead + 60 * 60 * 1000L < now || !pump.isInitialized()) { - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumpsettings))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumpsettings))); bleComm.sendMessage(new DanaRS_Packet_General_Get_Shipping_Information()); // serial no bleComm.sendMessage(new DanaRS_Packet_General_Get_Pump_Check()); // firmware bleComm.sendMessage(new DanaRS_Packet_Basal_Get_Profile_Number()); @@ -203,15 +227,15 @@ public class DanaRSService extends Service { loadEvents(); - MainApp.bus().post(new EventDanaRNewStatus()); - MainApp.bus().post(new EventInitializationChanged()); + RxBus.INSTANCE.send(new EventDanaRNewStatus()); + RxBus.INSTANCE.send(new EventInitializationChanged()); NSUpload.uploadDeviceStatus(); if (danaRPump.dailyTotalUnits > danaRPump.maxDailyTotalUnits * Constants.dailyLimitWarning) { if (L.isEnabled(L.PUMPCOMM)) log.debug("Approaching daily limit: " + danaRPump.dailyTotalUnits + "/" + danaRPump.maxDailyTotalUnits); if (System.currentTimeMillis() > lastApproachingDailyLimit + 30 * 60 * 1000) { Notification reportFail = new Notification(Notification.APPROACHING_DAILY_LIMIT, MainApp.gs(R.string.approachingdailylimit), Notification.URGENT); - MainApp.bus().post(new EventNewNotification(reportFail)); + RxBus.INSTANCE.send(new EventNewNotification(reportFail)); NSUpload.uploadError(MainApp.gs(R.string.approachingdailylimit) + ": " + danaRPump.dailyTotalUnits + "/" + danaRPump.maxDailyTotalUnits + "U"); lastApproachingDailyLimit = System.currentTimeMillis(); } @@ -225,7 +249,7 @@ public class DanaRSService extends Service { public PumpEnactResult loadEvents() { - if (!MainApp.getSpecificPlugin(DanaRSPlugin.class).isInitialized()) { + if (!DanaRSPlugin.getPlugin().isInitialized()) { PumpEnactResult result = new PumpEnactResult().success(false); result.comment = "pump not initialized"; return result; @@ -241,7 +265,7 @@ public class DanaRSService extends Service { } else { msg = new DanaRS_Packet_APS_History_Events(lastHistoryFetched); if (L.isEnabled(L.PUMPCOMM)) - log.debug("Loading event history from: " +DateUtil.dateAndTimeFullString(lastHistoryFetched)); + log.debug("Loading event history from: " + DateUtil.dateAndTimeFullString(lastHistoryFetched)); } bleComm.sendMessage(msg); while (!msg.done && bleComm.isConnected()) { @@ -269,7 +293,7 @@ public class DanaRSService extends Service { if (!isConnected()) return false; if (BolusProgressDialog.stopPressed) return false; - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.startingbolus))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.startingbolus))); bolusingTreatment = t; final int preferencesSpeed = SP.getInt(R.string.key_danars_bolusspeed, 0); DanaRS_Packet_Bolus_Set_Step_Bolus_Start start = new DanaRS_Packet_Bolus_Set_Step_Bolus_Start(insulin, preferencesSpeed); @@ -305,9 +329,9 @@ public class DanaRSService extends Service { } } - final EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance(); - bolusingEvent.t = t; - bolusingEvent.percent = 99; + final EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.INSTANCE; + bolusingEvent.setT(t); + bolusingEvent.setPercent(99); bolusingTreatment = null; int speed = 12; @@ -326,8 +350,8 @@ public class DanaRSService extends Service { long expectedEnd = bolusStart + bolusDurationInMSec + 2000; while (System.currentTimeMillis() < expectedEnd) { long waitTime = expectedEnd - System.currentTimeMillis(); - bolusingEvent.status = String.format(MainApp.gs(R.string.waitingforestimatedbolusend), waitTime / 1000); - MainApp.bus().post(bolusingEvent); + bolusingEvent.setStatus(String.format(MainApp.gs(R.string.waitingforestimatedbolusend), waitTime / 1000)); + RxBus.INSTANCE.send(bolusingEvent); SystemClock.sleep(1000); } // do not call loadEvents() directly, reconnection may be needed @@ -335,10 +359,10 @@ public class DanaRSService extends Service { @Override public void run() { // reread bolus status - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingbolusstatus))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.gettingbolusstatus))); bleComm.sendMessage(new DanaRS_Packet_Bolus_Get_Step_Bolus_Information()); // last bolus - bolusingEvent.percent = 100; - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.disconnecting))); + bolusingEvent.setPercent(100); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.disconnecting))); } }); return !start.failed; @@ -363,30 +387,30 @@ public class DanaRSService extends Service { public boolean tempBasal(Integer percent, int durationInHours) { if (!isConnected()) return false; if (DanaRPump.getInstance().isTempBasalInProgress) { - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.stoppingtempbasal))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.stoppingtempbasal))); bleComm.sendMessage(new DanaRS_Packet_Basal_Set_Cancel_Temporary_Basal()); SystemClock.sleep(500); } - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.settingtempbasal))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.settingtempbasal))); bleComm.sendMessage(new DanaRS_Packet_Basal_Set_Temporary_Basal(percent, durationInHours)); SystemClock.sleep(200); bleComm.sendMessage(new DanaRS_Packet_Basal_Get_Temporary_Basal_State()); loadEvents(); - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING)); + RxBus.INSTANCE.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING)); return true; } public boolean highTempBasal(Integer percent) { if (DanaRPump.getInstance().isTempBasalInProgress) { - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.stoppingtempbasal))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.stoppingtempbasal))); bleComm.sendMessage(new DanaRS_Packet_Basal_Set_Cancel_Temporary_Basal()); SystemClock.sleep(500); } - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.settingtempbasal))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.settingtempbasal))); bleComm.sendMessage(new DanaRS_Packet_APS_Basal_Set_Temporary_Basal(percent)); bleComm.sendMessage(new DanaRS_Packet_Basal_Get_Temporary_Basal_State()); loadEvents(); - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING)); + RxBus.INSTANCE.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING)); return true; } @@ -397,52 +421,52 @@ public class DanaRSService extends Service { } if (DanaRPump.getInstance().isTempBasalInProgress) { - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.stoppingtempbasal))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.stoppingtempbasal))); bleComm.sendMessage(new DanaRS_Packet_Basal_Set_Cancel_Temporary_Basal()); SystemClock.sleep(500); } - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.settingtempbasal))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.settingtempbasal))); bleComm.sendMessage(new DanaRS_Packet_APS_Basal_Set_Temporary_Basal(percent, durationInMinutes == 15, durationInMinutes == 30)); bleComm.sendMessage(new DanaRS_Packet_Basal_Get_Temporary_Basal_State()); loadEvents(); - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING)); + RxBus.INSTANCE.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING)); return true; } public boolean tempBasalStop() { if (!isConnected()) return false; - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.stoppingtempbasal))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.stoppingtempbasal))); bleComm.sendMessage(new DanaRS_Packet_Basal_Set_Cancel_Temporary_Basal()); bleComm.sendMessage(new DanaRS_Packet_Basal_Get_Temporary_Basal_State()); loadEvents(); - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING)); + RxBus.INSTANCE.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING)); return true; } public boolean extendedBolus(Double insulin, int durationInHalfHours) { if (!isConnected()) return false; - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.settingextendedbolus))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.settingextendedbolus))); bleComm.sendMessage(new DanaRS_Packet_Bolus_Set_Extended_Bolus(insulin, durationInHalfHours)); SystemClock.sleep(200); bleComm.sendMessage(new DanaRS_Packet_Bolus_Get_Extended_Bolus_State()); loadEvents(); - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING)); + RxBus.INSTANCE.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING)); return true; } public boolean extendedBolusStop() { if (!isConnected()) return false; - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.stoppingextendedbolus))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.stoppingextendedbolus))); bleComm.sendMessage(new DanaRS_Packet_Bolus_Set_Extended_Bolus_Cancel()); bleComm.sendMessage(new DanaRS_Packet_Bolus_Get_Extended_Bolus_State()); loadEvents(); - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING)); + RxBus.INSTANCE.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING)); return true; } public boolean updateBasalsInPump(Profile profile) { if (!isConnected()) return false; - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.updatingbasalrates))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.updatingbasalrates))); double[] basal = DanaRPump.getInstance().buildDanaRProfileRecord(profile); DanaRS_Packet_Basal_Set_Profile_Basal_Rate msgSet = new DanaRS_Packet_Basal_Set_Profile_Basal_Rate(0, basal); bleComm.sendMessage(msgSet); @@ -450,7 +474,7 @@ public class DanaRSService extends Service { bleComm.sendMessage(msgActivate); DanaRPump.getInstance().lastSettingsRead = 0; // force read full settings getPumpStatus(); - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING)); + RxBus.INSTANCE.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING)); return true; } @@ -520,21 +544,13 @@ public class DanaRSService extends Service { return START_STICKY; } - @Subscribe - public void onStatusEvent(EventAppExit event) { - if (L.isEnabled(L.PUMP)) - log.debug("EventAppExit received"); - - stopSelf(); - } - void waitForWholeMinute() { while (true) { long time = DateUtil.now(); long timeToWholeMinute = (60000 - time % 60000); if (timeToWholeMinute > 59800 || timeToWholeMinute < 300) break; - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.waitingfortimesynchronization, (int) (timeToWholeMinute / 1000)))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.waitingfortimesynchronization, (int) (timeToWholeMinute / 1000)))); SystemClock.sleep(Math.min(timeToWholeMinute, 100)); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/DanaRv2Plugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/DanaRv2Plugin.java similarity index 84% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/DanaRv2Plugin.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/DanaRv2Plugin.java index 86c07b89ff..3437d37656 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/DanaRv2Plugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/DanaRv2Plugin.java @@ -1,14 +1,10 @@ -package info.nightscout.androidaps.plugins.PumpDanaRv2; +package info.nightscout.androidaps.plugins.pump.danaRv2; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.IBinder; -import android.support.v4.app.FragmentActivity; -import android.support.v7.app.AlertDialog; - -import com.squareup.otto.Subscribe; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; @@ -19,24 +15,28 @@ import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.events.EventAppExit; import info.nightscout.androidaps.interfaces.Constraint; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment; -import info.nightscout.androidaps.plugins.ConfigBuilder.DetailedBolusInfoStorage; -import info.nightscout.androidaps.plugins.PumpCommon.defs.PumpType; -import info.nightscout.androidaps.plugins.PumpDanaR.AbstractDanaRPlugin; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusStartWithSpeed; -import info.nightscout.androidaps.plugins.PumpDanaRv2.services.DanaRv2ExecutionService; -import info.nightscout.androidaps.plugins.Treatments.Treatment; -import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.Round; -import info.nightscout.utils.SP; -import info.nightscout.utils.T; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.pump.common.bolusInfo.DetailedBolusInfoStorage; +import info.nightscout.androidaps.plugins.pump.common.defs.PumpType; +import info.nightscout.androidaps.plugins.pump.danaR.AbstractDanaRPlugin; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgBolusStartWithSpeed; +import info.nightscout.androidaps.plugins.pump.danaRv2.services.DanaRv2ExecutionService; +import info.nightscout.androidaps.plugins.treatments.Treatment; +import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; +import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.FabricPrivacy; +import info.nightscout.androidaps.utils.Round; +import info.nightscout.androidaps.utils.SP; +import info.nightscout.androidaps.utils.T; +import io.reactivex.disposables.CompositeDisposable; +import io.reactivex.schedulers.Schedulers; /** * Created by mike on 05.08.2016. */ public class DanaRv2Plugin extends AbstractDanaRPlugin { + private CompositeDisposable disposable = new CompositeDisposable(); private static DanaRv2Plugin plugin = null; @@ -59,7 +59,13 @@ public class DanaRv2Plugin extends AbstractDanaRPlugin { Intent intent = new Intent(context, DanaRv2ExecutionService.class); context.bindService(intent, mConnection, Context.BIND_AUTO_CREATE); - MainApp.bus().register(this); + disposable.add(RxBus.INSTANCE + .toObservable(EventAppExit.class) + .observeOn(Schedulers.io()) + .subscribe(event -> { + MainApp.instance().getApplicationContext().unbindService(mConnection); + }, FabricPrivacy::logException) + ); super.onStart(); } @@ -68,7 +74,8 @@ public class DanaRv2Plugin extends AbstractDanaRPlugin { Context context = MainApp.instance().getApplicationContext(); context.unbindService(mConnection); - MainApp.bus().unregister(this); + disposable.clear(); + super.onStop(); } private ServiceConnection mConnection = new ServiceConnection() { @@ -87,12 +94,6 @@ public class DanaRv2Plugin extends AbstractDanaRPlugin { } }; - @SuppressWarnings("UnusedParameters") - @Subscribe - public void onStatusEvent(final EventAppExit e) { - MainApp.instance().getApplicationContext().unbindService(mConnection); - } - // Plugin base interface @Override public String getName() { @@ -124,29 +125,6 @@ public class DanaRv2Plugin extends AbstractDanaRPlugin { sExecutionService.finishHandshaking(); } - @Override - public void switchAllowed(ConfigBuilderFragment.PluginViewHolder.PluginSwitcher pluginSwitcher, FragmentActivity context) { - boolean allowHardwarePump = SP.getBoolean("allow_hardware_pump", false); - if (allowHardwarePump || context == null) { - pluginSwitcher.invoke(); - } else { - AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setMessage(R.string.allow_hardware_pump_text) - .setPositiveButton(R.string.yes, (dialog, id) -> { - pluginSwitcher.invoke(); - SP.putBoolean("allow_hardware_pump", true); - if (L.isEnabled(L.PUMP)) - log.debug("First time HW pump allowed!"); - }) - .setNegativeButton(R.string.cancel, (dialog, id) -> { - pluginSwitcher.cancel(); - if (L.isEnabled(L.PUMP)) - log.debug("User does not allow switching to HW pump!"); - }); - builder.create().show(); - } - } - // Pump interface @Override public PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo) { @@ -176,7 +154,7 @@ public class DanaRv2Plugin extends AbstractDanaRPlugin { if (carbTime == 0) carbTime--; // better set 1 man back to prevent clash with insulin detailedBolusInfo.carbTime = 0; - DetailedBolusInfoStorage.add(detailedBolusInfo); // will be picked up on reading history + DetailedBolusInfoStorage.INSTANCE.add(detailedBolusInfo); // will be picked up on reading history Treatment t = new Treatment(); t.isSMB = detailedBolusInfo.isSMB; @@ -259,7 +237,7 @@ public class DanaRv2Plugin extends AbstractDanaRPlugin { TemporaryBasal activeTemp = TreatmentsPlugin.getPlugin().getTempBasalFromHistory(System.currentTimeMillis()); if (activeTemp != null) { // Correct basal already set ? - if (activeTemp.percentRate == percentRate) { + if (activeTemp.percentRate == percentRate && activeTemp.getPlannedRemainingMinutes() > 4) { if (!enforceNew) { result.success = true; result.percent = percentRate; @@ -277,7 +255,7 @@ public class DanaRv2Plugin extends AbstractDanaRPlugin { if (L.isEnabled(L.PUMP)) log.debug("setTempBasalAbsolute: Setting temp basal " + percentRate + "% for " + durationInMinutes + " mins (doLowTemp || doHighTemp)"); if (percentRate == 0 && durationInMinutes > 30) { - result = setTempBasalPercent(percentRate, durationInMinutes, profile, false); + result = setTempBasalPercent(percentRate, durationInMinutes, profile, enforceNew); } else { // use special APS temp basal call ... 100+/15min .... 100-/30min result = setHighTempBasalPercent(percentRate); @@ -313,8 +291,8 @@ public class DanaRv2Plugin extends AbstractDanaRPlugin { if (percent > getPumpDescription().maxTempPercent) percent = getPumpDescription().maxTempPercent; long now = System.currentTimeMillis(); - TemporaryBasal runningTB = TreatmentsPlugin.getPlugin().getRealTempBasalFromHistory(now); - if (runningTB != null && runningTB.percentRate == percent && !enforceNew) { + TemporaryBasal activeTemp = TreatmentsPlugin.getPlugin().getRealTempBasalFromHistory(now); + if (activeTemp != null && activeTemp.percentRate == percent && activeTemp.getPlannedRemainingMinutes() > 4 && !enforceNew) { result.enacted = false; result.success = true; result.isTempCancel = false; @@ -400,6 +378,11 @@ public class DanaRv2Plugin extends AbstractDanaRPlugin { } } + @Override + public PumpType model() { + return PumpType.DanaRv2; + } + @Override public PumpEnactResult loadEvents() { return sExecutionService.loadEvents(); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/comm/MessageHashTableRv2.kt b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/comm/MessageHashTableRv2.kt new file mode 100644 index 0000000000..f22a3cf3fa --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/comm/MessageHashTableRv2.kt @@ -0,0 +1,77 @@ +package info.nightscout.androidaps.plugins.pump.danaRv2.comm + +import info.nightscout.androidaps.plugins.pump.danaR.comm.* +import java.util.* + + +object MessageHashTableRv2 : MessageHashTableBase { + var messages: HashMap = HashMap() + + init { + put(MsgBolusStop()) // 0x0101 CMD_MEALINS_STOP + put(MsgBolusStart()) // 0x0102 CMD_MEALINS_START_DATA + put(MsgBolusStartWithSpeed()) // 0x0104 CMD_MEALINS_START_DATA_SPEED + put(MsgBolusProgress()) // 0x0202 CMD_PUMP_THIS_REMAINDER_MEAL_INS + put(MsgStatusProfile()) // 0x0204 CMD_PUMP_CALCULATION_SETTING + + put(MsgStatusTempBasal_v2()) // 0x0205 CMD_PUMP_EXERCISE_MODE + put(MsgStatusBolusExtended_v2()) // 0x0207 CMD_PUMP_EXPANS_INS_I + + put(MsgStatusBasic()) // 0x020A CMD_PUMP_INITVIEW_I + put(MsgStatus()) // 0x020B CMD_PUMP_STATUS + put(MsgInitConnStatusTime()) // 0x0301 CMD_PUMPINIT_TIME_INFO + put(MsgInitConnStatusBolus()) // 0x0302 CMD_PUMPINIT_BOLUS_INFO + put(MsgInitConnStatusBasic()) // 0x0303 CMD_PUMPINIT_INIT_INFO + put(MsgInitConnStatusOption()) // 0x0304 CMD_PUMPINIT_OPTION + put(MsgSetTempBasalStart()) // 0x0401 CMD_PUMPSET_EXERCISE_S + put(MsgSetCarbsEntry()) // 0x0402 CMD_PUMPSET_HIS_S + put(MsgSetTempBasalStop()) // 0x0403 CMD_PUMPSET_EXERCISE_STOP + put(MsgSetExtendedBolusStop()) // 0x0406 CMD_PUMPSET_EXPANS_INS_STOP + put(MsgSetExtendedBolusStart()) // 0x0407 CMD_PUMPSET_EXPANS_INS_S + put(MsgError()) // 0x0601 CMD_PUMPOWAY_SYSTEM_STATUS + put(MsgPCCommStart()) // 0x3001 CMD_CONNECT + put(MsgPCCommStop()) // 0x3002 CMD_DISCONNECT + put(MsgHistoryBolus()) // 0x3101 CMD_HISTORY_MEAL_INS + put(MsgHistoryDailyInsulin()) // 0x3102 CMD_HISTORY_DAY_INS + put(MsgHistoryGlucose()) // 0x3104 CMD_HISTORY_GLUCOSE + put(MsgHistoryAlarm()) // 0x3105 CMD_HISTORY_ALARM + put(MsgHistoryError()) // 0x3106 CMD_HISTORY_ERROR + put(MsgHistoryCarbo()) // 0x3107 CMD_HISTORY_CARBOHY + put(MsgHistoryRefill()) // 0x3108 CMD_HISTORY_REFILL + put(MsgHistorySuspend()) // 0x3109 CMD_HISTORY_SUSPEND + put(MsgHistoryBasalHour()) // 0x310A CMD_HISTORY_BASAL_HOUR + put(MsgHistoryDone()) // 0x31F1 CMD_HISTORY_DONT_USED + put(MsgSettingBasal()) // 0x3202 CMD_SETTING_V_BASAL_INS_I + put(MsgSettingMeal()) // 0x3203 CMD_SETTING_V_MEAL_SETTING_I + put(MsgSettingProfileRatios()) // 0x3204 CMD_SETTING_V_CCC_I + put(MsgSettingMaxValues()) // 0x3205 CMD_SETTING_V_MAX_VALUE_I + put(MsgSettingBasalProfileAll()) // 0x3206 CMD_SETTING_V_BASAL_PROFILE_ALL + put(MsgSettingShippingInfo()) // 0x3207 CMD_SETTING_V_SHIPPING_I + put(MsgSettingGlucose()) // 0x3209 CMD_SETTING_V_GLUCOSEandEASY + put(MsgSettingPumpTime()) // 0x320A CMD_SETTING_V_TIME_I + put(MsgSettingUserOptions()) // 0x320B CMD_SETTING_V_USER_OPTIONS + put(MsgSettingActiveProfile()) // 0x320C CMD_SETTING_V_PROFILE_NUMBER + put(MsgSettingProfileRatiosAll()) // 0x320D CMD_SETTING_V_CIR_CF_VALUE + put(MsgSetSingleBasalProfile()) // 0x3302 CMD_SETTING_BASAL_INS_S + put(MsgSetBasalProfile()) // 0x3306 CMD_SETTING_BASAL_PROFILE_S + put(MsgSetUserOptions()) // 0x330B CMD_SETTING_USER_OPTIONS_S + put(MsgSetActivateBasalProfile()) // 0x330C CMD_SETTING_PROFILE_NUMBER_S + put(MsgHistoryAllDone()) // 0x41F1 CMD_HISTORY_ALL_DONE + put(MsgHistoryAll()) // 0x41F2 CMD_HISTORY_ALL + put(MsgHistoryNewDone()) // 0x42F1 CMD_HISTORY_NEW_DONE + put(MsgHistoryNew()) // 0x42F2 CMD_HISTORY_NEW + put(MsgCheckValue_v2()) // 0xF0F1 CMD_PUMP_CHECK_VALUE + put(MsgStatusAPS_v2()) // 0xE001 CMD_PUMPSTATUS_APS + put(MsgSetAPSTempBasalStart_v2()) // 0xE002 CMD_PUMPSET_APSTEMP + put(MsgHistoryEvents_v2()) // 0xE003 CMD_GET_HISTORY + put(MsgSetHistoryEntry_v2()) // 0xE004 CMD_SET_HISTORY_ENTRY + } + + override fun put(message: MessageBase) { + messages[message.command] = message + } + + override fun findMessage(command: Int): MessageBase { + return messages[command] ?: MessageBase() + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgCheckValue_v2.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/comm/MsgCheckValue_v2.java similarity index 51% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgCheckValue_v2.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/comm/MsgCheckValue_v2.java index 034c7648a0..3070c52b64 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgCheckValue_v2.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/comm/MsgCheckValue_v2.java @@ -1,21 +1,22 @@ -package info.nightscout.androidaps.plugins.PumpDanaRv2.comm; +package info.nightscout.androidaps.plugins.pump.danaRv2.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.events.EventRefreshGui; +import info.nightscout.androidaps.events.EventRebuildTabs; import info.nightscout.androidaps.interfaces.PluginType; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; -import info.nightscout.androidaps.plugins.Overview.notifications.Notification; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; -import info.nightscout.androidaps.plugins.PumpDanaRv2.DanaRv2Plugin; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPlugin; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MessageBase; +import info.nightscout.androidaps.plugins.pump.danaRKorean.DanaRKoreanPlugin; +import info.nightscout.androidaps.plugins.pump.danaRv2.DanaRv2Plugin; /** * Created by mike on 30.06.2016. @@ -43,24 +44,24 @@ public class MsgCheckValue_v2 extends MessageBase { if (pump.model != DanaRPump.EXPORT_MODEL) { pump.lastConnection = 0; Notification notification = new Notification(Notification.WRONG_DRIVER, MainApp.gs(R.string.pumpdrivercorrected), Notification.NORMAL); - MainApp.bus().post(new EventNewNotification(notification)); - MainApp.getSpecificPlugin(DanaRPlugin.class).disconnect("Wrong Model"); + RxBus.INSTANCE.send(new EventNewNotification(notification)); + DanaRPlugin.getPlugin().disconnect("Wrong Model"); log.error("Wrong model selected. Switching to Korean DanaR"); - MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).setPluginEnabled(PluginType.PUMP, true); - MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).setFragmentVisible(PluginType.PUMP, true); - MainApp.getSpecificPlugin(DanaRPlugin.class).setPluginEnabled(PluginType.PUMP, false); - MainApp.getSpecificPlugin(DanaRPlugin.class).setFragmentVisible(PluginType.PUMP, false); + DanaRKoreanPlugin.getPlugin().setPluginEnabled(PluginType.PUMP, true); + DanaRKoreanPlugin.getPlugin().setFragmentVisible(PluginType.PUMP, true); + DanaRPlugin.getPlugin().setPluginEnabled(PluginType.PUMP, false); + DanaRPlugin.getPlugin().setFragmentVisible(PluginType.PUMP, false); DanaRPump.reset(); // mark not initialized //If profile coming from pump, switch it as well - if (MainApp.getSpecificPlugin(DanaRPlugin.class).isEnabled(PluginType.PROFILE)) { - (MainApp.getSpecificPlugin(DanaRPlugin.class)).setPluginEnabled(PluginType.PROFILE, false); - (MainApp.getSpecificPlugin(DanaRKoreanPlugin.class)).setPluginEnabled(PluginType.PROFILE, true); + if (DanaRPlugin.getPlugin().isEnabled(PluginType.PROFILE)) { + (DanaRPlugin.getPlugin()).setPluginEnabled(PluginType.PROFILE, false); + (DanaRKoreanPlugin.getPlugin()).setPluginEnabled(PluginType.PROFILE, true); } ConfigBuilderPlugin.getPlugin().storeSettings("ChangingDanaRv2Driver"); - MainApp.bus().post(new EventRefreshGui()); + RxBus.INSTANCE.send(new EventRebuildTabs()); ConfigBuilderPlugin.getPlugin().getCommandQueue().readStatus("PumpDriverChange", null); // force new connection return; } @@ -68,22 +69,22 @@ public class MsgCheckValue_v2 extends MessageBase { if (pump.protocol != 2) { pump.lastConnection = 0; Notification notification = new Notification(Notification.WRONG_DRIVER, MainApp.gs(R.string.pumpdrivercorrected), Notification.NORMAL); - MainApp.bus().post(new EventNewNotification(notification)); + RxBus.INSTANCE.send(new EventNewNotification(notification)); DanaRKoreanPlugin.getPlugin().disconnect("Wrong Model"); log.error("Wrong model selected. Switching to non APS DanaR"); - (MainApp.getSpecificPlugin(DanaRv2Plugin.class)).setPluginEnabled(PluginType.PUMP, false); - (MainApp.getSpecificPlugin(DanaRv2Plugin.class)).setFragmentVisible(PluginType.PUMP, false); - (MainApp.getSpecificPlugin(DanaRPlugin.class)).setPluginEnabled(PluginType.PUMP, true); - (MainApp.getSpecificPlugin(DanaRPlugin.class)).setFragmentVisible(PluginType.PUMP, true); + (DanaRv2Plugin.getPlugin()).setPluginEnabled(PluginType.PUMP, false); + (DanaRv2Plugin.getPlugin()).setFragmentVisible(PluginType.PUMP, false); + (DanaRPlugin.getPlugin()).setPluginEnabled(PluginType.PUMP, true); + (DanaRPlugin.getPlugin()).setFragmentVisible(PluginType.PUMP, true); //If profile coming from pump, switch it as well - if (MainApp.getSpecificPlugin(DanaRv2Plugin.class).isEnabled(PluginType.PROFILE)) { - (MainApp.getSpecificPlugin(DanaRv2Plugin.class)).setPluginEnabled(PluginType.PROFILE, false); - (MainApp.getSpecificPlugin(DanaRPlugin.class)).setPluginEnabled(PluginType.PROFILE, true); + if (DanaRv2Plugin.getPlugin().isEnabled(PluginType.PROFILE)) { + (DanaRv2Plugin.getPlugin()).setPluginEnabled(PluginType.PROFILE, false); + (DanaRPlugin.getPlugin()).setPluginEnabled(PluginType.PROFILE, true); } ConfigBuilderPlugin.getPlugin().storeSettings("ChangingDanaRv2Driver"); - MainApp.bus().post(new EventRefreshGui()); + RxBus.INSTANCE.send(new EventRebuildTabs()); ConfigBuilderPlugin.getPlugin().getCommandQueue().readStatus("PumpDriverChange", null); // force new connection return; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgHistoryEvents_v2.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/comm/MsgHistoryEvents_v2.java similarity index 92% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgHistoryEvents_v2.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/comm/MsgHistoryEvents_v2.java index 32ac8862ee..3ef43cad86 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgHistoryEvents_v2.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/comm/MsgHistoryEvents_v2.java @@ -1,9 +1,8 @@ -package info.nightscout.androidaps.plugins.PumpDanaRv2.comm; +package info.nightscout.androidaps.plugins.pump.danaRv2.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.Date; import java.util.GregorianCalendar; import info.nightscout.androidaps.MainApp; @@ -14,11 +13,12 @@ import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.events.EventPumpStatusChanged; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.DetailedBolusInfoStorage; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; -import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; -import info.nightscout.utils.DateUtil; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.pump.common.bolusInfo.DetailedBolusInfoStorage; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MessageBase; +import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; +import info.nightscout.androidaps.utils.DateUtil; public class MsgHistoryEvents_v2 extends MessageBase { private Logger log = LoggerFactory.getLogger(L.PUMPCOMM); @@ -111,7 +111,7 @@ public class MsgHistoryEvents_v2 extends MessageBase { status = "EXTENDEDSTOP " + DateUtil.timeString(datetime); break; case DanaRPump.BOLUS: - DetailedBolusInfo detailedBolusInfo = DetailedBolusInfoStorage.findDetailedBolusInfo(datetime); + DetailedBolusInfo detailedBolusInfo = DetailedBolusInfoStorage.INSTANCE.findDetailedBolusInfo(datetime, param1 / 100d); if (detailedBolusInfo == null) { detailedBolusInfo = new DetailedBolusInfo(); } @@ -126,7 +126,7 @@ public class MsgHistoryEvents_v2 extends MessageBase { status = "BOLUS " + DateUtil.timeString(datetime); break; case DanaRPump.DUALBOLUS: - detailedBolusInfo = DetailedBolusInfoStorage.findDetailedBolusInfo(datetime); + detailedBolusInfo = DetailedBolusInfoStorage.INSTANCE.findDetailedBolusInfo(datetime, param1 / 100d); if (detailedBolusInfo == null) { detailedBolusInfo = new DetailedBolusInfo(); } @@ -200,6 +200,6 @@ public class MsgHistoryEvents_v2 extends MessageBase { if (datetime > lastEventTimeLoaded) lastEventTimeLoaded = datetime; - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.processinghistory) + ": " + status)); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.processinghistory) + ": " + status)); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgSetAPSTempBasalStart_v2.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/comm/MsgSetAPSTempBasalStart_v2.java similarity index 95% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgSetAPSTempBasalStart_v2.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/comm/MsgSetAPSTempBasalStart_v2.java index 42964a64c6..875cd4ac64 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgSetAPSTempBasalStart_v2.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/comm/MsgSetAPSTempBasalStart_v2.java @@ -1,10 +1,10 @@ -package info.nightscout.androidaps.plugins.PumpDanaRv2.comm; +package info.nightscout.androidaps.plugins.pump.danaRv2.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MessageBase; public class MsgSetAPSTempBasalStart_v2 extends MessageBase { private Logger log = LoggerFactory.getLogger(L.PUMPCOMM); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgSetHistoryEntry_v2.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/comm/MsgSetHistoryEntry_v2.java similarity index 90% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgSetHistoryEntry_v2.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/comm/MsgSetHistoryEntry_v2.java index 0c55b29a3f..b817495ba3 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgSetHistoryEntry_v2.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/comm/MsgSetHistoryEntry_v2.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRv2.comm; +package info.nightscout.androidaps.plugins.pump.danaRv2.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -7,7 +7,7 @@ import java.util.Date; import java.util.GregorianCalendar; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MessageBase; public class MsgSetHistoryEntry_v2 extends MessageBase { private Logger log = LoggerFactory.getLogger(L.PUMPCOMM); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgStatusAPS_v2.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/comm/MsgStatusAPS_v2.java similarity index 79% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgStatusAPS_v2.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/comm/MsgStatusAPS_v2.java index 5d0238f2f7..601a5d4933 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgStatusAPS_v2.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/comm/MsgStatusAPS_v2.java @@ -1,11 +1,11 @@ -package info.nightscout.androidaps.plugins.PumpDanaRv2.comm; +package info.nightscout.androidaps.plugins.pump.danaRv2.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MessageBase; public class MsgStatusAPS_v2 extends MessageBase { private Logger log = LoggerFactory.getLogger(L.PUMPCOMM); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgStatusBolusExtended_v2.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/comm/MsgStatusBolusExtended_v2.java similarity index 91% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgStatusBolusExtended_v2.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/comm/MsgStatusBolusExtended_v2.java index 5a442e39c1..a829b3afcb 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgStatusBolusExtended_v2.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/comm/MsgStatusBolusExtended_v2.java @@ -1,13 +1,13 @@ -package info.nightscout.androidaps.plugins.PumpDanaRv2.comm; +package info.nightscout.androidaps.plugins.pump.danaRv2.comm; -import android.support.annotation.NonNull; +import androidx.annotation.NonNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MessageBase; public class MsgStatusBolusExtended_v2 extends MessageBase { private Logger log = LoggerFactory.getLogger(L.PUMPCOMM); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgStatusTempBasal_v2.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/comm/MsgStatusTempBasal_v2.java similarity index 89% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgStatusTempBasal_v2.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/comm/MsgStatusTempBasal_v2.java index fb26d2c0de..19a0a2b6ce 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgStatusTempBasal_v2.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/comm/MsgStatusTempBasal_v2.java @@ -1,14 +1,14 @@ -package info.nightscout.androidaps.plugins.PumpDanaRv2.comm; +package info.nightscout.androidaps.plugins.pump.danaRv2.comm; -import android.support.annotation.NonNull; +import androidx.annotation.NonNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; -import info.nightscout.utils.DateUtil; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MessageBase; +import info.nightscout.androidaps.utils.DateUtil; public class MsgStatusTempBasal_v2 extends MessageBase { private Logger log = LoggerFactory.getLogger(L.PUMPCOMM); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/services/DanaRv2ExecutionService.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/services/DanaRv2ExecutionService.java similarity index 63% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/services/DanaRv2ExecutionService.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/services/DanaRv2ExecutionService.java index f51f846978..e528a67fae 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/services/DanaRv2ExecutionService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/services/DanaRv2ExecutionService.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRv2.services; +package info.nightscout.androidaps.plugins.pump.danaRv2.services; import android.bluetooth.BluetoothDevice; import android.content.Intent; @@ -6,8 +6,6 @@ import android.content.IntentFilter; import android.os.Binder; import android.os.SystemClock; -import com.squareup.otto.Subscribe; - import java.io.IOException; import java.util.Date; @@ -19,70 +17,75 @@ import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.events.EventAppExit; import info.nightscout.androidaps.events.EventInitializationChanged; import info.nightscout.androidaps.events.EventPreferenceChange; -import info.nightscout.androidaps.events.EventProfileSwitchChange; +import info.nightscout.androidaps.events.EventProfileNeedsUpdate; import info.nightscout.androidaps.events.EventPumpStatusChanged; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions; -import info.nightscout.androidaps.plugins.NSClientInternal.NSUpload; -import info.nightscout.androidaps.plugins.Overview.Dialogs.BolusProgressDialog; -import info.nightscout.androidaps.plugins.Overview.Dialogs.ErrorHelperActivity; -import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; -import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress; -import info.nightscout.androidaps.plugins.Overview.notifications.Notification; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusProgress; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusStart; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusStartWithSpeed; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusStop; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetActivateBasalProfile; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetBasalProfile; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetCarbsEntry; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetExtendedBolusStart; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetExtendedBolusStop; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetTempBasalStart; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetTempBasalStop; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetTime; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetUserOptions; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingActiveProfile; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingBasal; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingGlucose; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingMaxValues; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingMeal; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingProfileRatios; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingProfileRatiosAll; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingPumpTime; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingShippingInfo; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingUserOptions; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgStatus; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgStatusBasic; -import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRNewStatus; -import info.nightscout.androidaps.plugins.PumpDanaR.services.AbstractDanaRExecutionService; -import info.nightscout.androidaps.plugins.PumpDanaRv2.DanaRv2Plugin; -import info.nightscout.androidaps.plugins.PumpDanaRv2.SerialIOThread; -import info.nightscout.androidaps.plugins.PumpDanaRv2.comm.MsgCheckValue_v2; -import info.nightscout.androidaps.plugins.PumpDanaRv2.comm.MsgHistoryEvents_v2; -import info.nightscout.androidaps.plugins.PumpDanaRv2.comm.MsgSetAPSTempBasalStart_v2; -import info.nightscout.androidaps.plugins.PumpDanaRv2.comm.MsgSetHistoryEntry_v2; -import info.nightscout.androidaps.plugins.PumpDanaRv2.comm.MsgStatusBolusExtended_v2; -import info.nightscout.androidaps.plugins.PumpDanaRv2.comm.MsgStatusTempBasal_v2; -import info.nightscout.androidaps.plugins.Treatments.Treatment; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; +import info.nightscout.androidaps.plugins.general.nsclient.NSUpload; +import info.nightscout.androidaps.plugins.general.overview.dialogs.BolusProgressDialog; +import info.nightscout.androidaps.plugins.general.overview.dialogs.ErrorHelperActivity; +import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress; +import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaR.SerialIOThread; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MessageBase; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgBolusProgress; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgBolusStart; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgBolusStartWithSpeed; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgBolusStop; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgSetActivateBasalProfile; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgSetBasalProfile; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgSetCarbsEntry; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgSetExtendedBolusStart; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgSetExtendedBolusStop; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgSetTempBasalStart; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgSetTempBasalStop; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgSetTime; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgSetUserOptions; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgSettingActiveProfile; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgSettingBasal; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgSettingGlucose; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgSettingMaxValues; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgSettingMeal; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgSettingProfileRatios; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgSettingProfileRatiosAll; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgSettingPumpTime; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgSettingShippingInfo; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgSettingUserOptions; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgStatus; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgStatusBasic; +import info.nightscout.androidaps.plugins.pump.danaR.events.EventDanaRNewStatus; +import info.nightscout.androidaps.plugins.pump.danaR.services.AbstractDanaRExecutionService; +import info.nightscout.androidaps.plugins.pump.danaRv2.DanaRv2Plugin; +import info.nightscout.androidaps.plugins.pump.danaRv2.comm.MessageHashTableRv2; +import info.nightscout.androidaps.plugins.pump.danaRv2.comm.MsgCheckValue_v2; +import info.nightscout.androidaps.plugins.pump.danaRv2.comm.MsgHistoryEvents_v2; +import info.nightscout.androidaps.plugins.pump.danaRv2.comm.MsgSetAPSTempBasalStart_v2; +import info.nightscout.androidaps.plugins.pump.danaRv2.comm.MsgSetHistoryEntry_v2; +import info.nightscout.androidaps.plugins.pump.danaRv2.comm.MsgStatusBolusExtended_v2; +import info.nightscout.androidaps.plugins.pump.danaRv2.comm.MsgStatusTempBasal_v2; +import info.nightscout.androidaps.plugins.treatments.Treatment; import info.nightscout.androidaps.queue.Callback; import info.nightscout.androidaps.queue.commands.Command; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.SP; -import info.nightscout.utils.T; +import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.FabricPrivacy; +import info.nightscout.androidaps.utils.SP; +import info.nightscout.androidaps.utils.T; +import io.reactivex.disposables.CompositeDisposable; +import io.reactivex.schedulers.Schedulers; public class DanaRv2ExecutionService extends AbstractDanaRExecutionService { + private CompositeDisposable disposable = new CompositeDisposable(); private long lastHistoryFetched = 0; public DanaRv2ExecutionService() { mBinder = new LocalBinder(); - registerBus(); MainApp.instance().getApplicationContext().registerReceiver(receiver, new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED)); } @@ -92,32 +95,36 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService { } } - private void registerBus() { - try { - MainApp.bus().unregister(this); - } catch (RuntimeException x) { - // Ignore - } - MainApp.bus().register(this); + @Override + public void onCreate() { + super.onCreate(); + disposable.add(RxBus.INSTANCE + .toObservable(EventPreferenceChange.class) + .observeOn(Schedulers.io()) + .subscribe(event -> { + if (mSerialIOThread != null) + mSerialIOThread.disconnect("EventPreferenceChange"); + }, FabricPrivacy::logException) + ); + disposable.add(RxBus.INSTANCE + .toObservable(EventAppExit.class) + .observeOn(Schedulers.io()) + .subscribe(event -> { + if (L.isEnabled(L.PUMP)) + log.debug("EventAppExit received"); + + if (mSerialIOThread != null) + mSerialIOThread.disconnect("Application exit"); + MainApp.instance().getApplicationContext().unregisterReceiver(receiver); + stopSelf(); + }, FabricPrivacy::logException) + ); } - @Subscribe - public void onStatusEvent(EventAppExit event) { - if (L.isEnabled(L.PUMP)) - log.debug("EventAppExit received"); - - if (mSerialIOThread != null) - mSerialIOThread.disconnect("Application exit"); - - MainApp.instance().getApplicationContext().unregisterReceiver(receiver); - - stopSelf(); - } - - @Subscribe - public void onStatusEvent(final EventPreferenceChange pch) { - if (mSerialIOThread != null) - mSerialIOThread.disconnect("EventPreferenceChange"); + @Override + public void onDestroy() { + disposable.clear(); + super.onDestroy(); } public void connect() { @@ -146,9 +153,9 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService { if (mSerialIOThread != null) { mSerialIOThread.disconnect("Recreate SerialIOThread"); } - mSerialIOThread = new SerialIOThread(mRfcommSocket); + mSerialIOThread = new SerialIOThread(mRfcommSocket, MessageHashTableRv2.INSTANCE); mHandshakeInProgress = true; - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.HANDSHAKING, 0)); + RxBus.INSTANCE.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.HANDSHAKING, 0)); } mConnectionInProgress = false; @@ -158,7 +165,7 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService { public void getPumpStatus() { DanaRPump danaRPump = DanaRPump.getInstance(); try { - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumpstatus))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumpstatus))); MsgStatus statusMsg = new MsgStatus(); MsgStatusBasic statusBasicMsg = new MsgStatusBasic(); MsgStatusTempBasal_v2 tempStatusMsg = new MsgStatusTempBasal_v2(); @@ -172,12 +179,12 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService { } } - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingbolusstatus))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.gettingbolusstatus))); mSerialIOThread.sendMessage(statusMsg); mSerialIOThread.sendMessage(statusBasicMsg); - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingtempbasalstatus))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.gettingtempbasalstatus))); mSerialIOThread.sendMessage(tempStatusMsg); - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingextendedbolusstatus))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.gettingextendedbolusstatus))); mSerialIOThread.sendMessage(exStatusMsg); danaRPump.lastConnection = System.currentTimeMillis(); @@ -185,15 +192,24 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService { Profile profile = ProfileFunctions.getInstance().getProfile(); PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump(); if (profile != null && Math.abs(danaRPump.currentBasal - profile.getBasal()) >= pump.getPumpDescription().basalStep) { - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumpsettings))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumpsettings))); mSerialIOThread.sendMessage(new MsgSettingBasal()); if (!pump.isThisProfileSet(profile) && !ConfigBuilderPlugin.getPlugin().getCommandQueue().isRunning(Command.CommandType.BASALPROFILE)) { - MainApp.bus().post(new EventProfileSwitchChange()); + RxBus.INSTANCE.send(new EventProfileNeedsUpdate()); } } - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumptime))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumptime))); mSerialIOThread.sendMessage(new MsgSettingPumpTime()); + if (danaRPump.pumpTime == 0) { + // initial handshake was not successfull + // deinitialize pump + danaRPump.lastConnection = 0; + danaRPump.lastSettingsRead = 0; + RxBus.INSTANCE.send(new EventDanaRNewStatus()); + RxBus.INSTANCE.send(new EventInitializationChanged()); + return; + } long timeDiff = (danaRPump.pumpTime - System.currentTimeMillis()) / 1000L; if (L.isEnabled(L.PUMP)) log.debug("Pump time difference: " + timeDiff + " seconds"); @@ -211,8 +227,8 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService { //deinitialize pump danaRPump.lastConnection = 0; - MainApp.bus().post(new EventDanaRNewStatus()); - MainApp.bus().post(new EventInitializationChanged()); + RxBus.INSTANCE.send(new EventDanaRNewStatus()); + RxBus.INSTANCE.send(new EventInitializationChanged()); return; } else { waitForWholeMinute(); // Dana can set only whole minute @@ -227,7 +243,7 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService { long now = System.currentTimeMillis(); if (danaRPump.lastSettingsRead + 60 * 60 * 1000L < now || !pump.isInitialized()) { - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumpsettings))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumpsettings))); mSerialIOThread.sendMessage(new MsgSettingShippingInfo()); mSerialIOThread.sendMessage(new MsgSettingActiveProfile()); mSerialIOThread.sendMessage(new MsgSettingMeal()); @@ -244,15 +260,15 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService { loadEvents(); - MainApp.bus().post(new EventDanaRNewStatus()); - MainApp.bus().post(new EventInitializationChanged()); + RxBus.INSTANCE.send(new EventDanaRNewStatus()); + RxBus.INSTANCE.send(new EventInitializationChanged()); NSUpload.uploadDeviceStatus(); if (danaRPump.dailyTotalUnits > danaRPump.maxDailyTotalUnits * Constants.dailyLimitWarning) { if (L.isEnabled(L.PUMP)) log.debug("Approaching daily limit: " + danaRPump.dailyTotalUnits + "/" + danaRPump.maxDailyTotalUnits); if (System.currentTimeMillis() > lastApproachingDailyLimit + 30 * 60 * 1000) { Notification reportFail = new Notification(Notification.APPROACHING_DAILY_LIMIT, MainApp.gs(R.string.approachingdailylimit), Notification.URGENT); - MainApp.bus().post(new EventNewNotification(reportFail)); + RxBus.INSTANCE.send(new EventNewNotification(reportFail)); NSUpload.uploadError(MainApp.gs(R.string.approachingdailylimit) + ": " + danaRPump.dailyTotalUnits + "/" + danaRPump.maxDailyTotalUnits + "U"); lastApproachingDailyLimit = System.currentTimeMillis(); } @@ -266,15 +282,15 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService { DanaRPump danaRPump = DanaRPump.getInstance(); if (!isConnected()) return false; if (danaRPump.isTempBasalInProgress) { - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.stoppingtempbasal))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.stoppingtempbasal))); mSerialIOThread.sendMessage(new MsgSetTempBasalStop()); SystemClock.sleep(500); } - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.settingtempbasal))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.settingtempbasal))); mSerialIOThread.sendMessage(new MsgSetTempBasalStart(percent, durationInHours)); mSerialIOThread.sendMessage(new MsgStatusTempBasal_v2()); loadEvents(); - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING)); + RxBus.INSTANCE.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING)); return true; } @@ -282,15 +298,15 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService { DanaRPump danaRPump = DanaRPump.getInstance(); if (!isConnected()) return false; if (danaRPump.isTempBasalInProgress) { - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.stoppingtempbasal))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.stoppingtempbasal))); mSerialIOThread.sendMessage(new MsgSetTempBasalStop()); SystemClock.sleep(500); } - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.settingtempbasal))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.settingtempbasal))); mSerialIOThread.sendMessage(new MsgSetAPSTempBasalStart_v2(percent)); mSerialIOThread.sendMessage(new MsgStatusTempBasal_v2()); loadEvents(); - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING)); + RxBus.INSTANCE.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING)); return true; } @@ -303,45 +319,45 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService { if (!isConnected()) return false; if (danaRPump.isTempBasalInProgress) { - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.stoppingtempbasal))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.stoppingtempbasal))); mSerialIOThread.sendMessage(new MsgSetTempBasalStop()); SystemClock.sleep(500); } - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.settingtempbasal))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.settingtempbasal))); mSerialIOThread.sendMessage(new MsgSetAPSTempBasalStart_v2(percent, durationInMinutes == 15, durationInMinutes == 30)); mSerialIOThread.sendMessage(new MsgStatusTempBasal_v2()); loadEvents(); - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING)); + RxBus.INSTANCE.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING)); return true; } public boolean tempBasalStop() { if (!isConnected()) return false; - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.stoppingtempbasal))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.stoppingtempbasal))); mSerialIOThread.sendMessage(new MsgSetTempBasalStop()); mSerialIOThread.sendMessage(new MsgStatusTempBasal_v2()); loadEvents(); - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING)); + RxBus.INSTANCE.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING)); return true; } public boolean extendedBolus(double insulin, int durationInHalfHours) { if (!isConnected()) return false; - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.settingextendedbolus))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.settingextendedbolus))); mSerialIOThread.sendMessage(new MsgSetExtendedBolusStart(insulin, (byte) (durationInHalfHours & 0xFF))); mSerialIOThread.sendMessage(new MsgStatusBolusExtended_v2()); loadEvents(); - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING)); + RxBus.INSTANCE.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING)); return true; } public boolean extendedBolusStop() { if (!isConnected()) return false; - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.stoppingextendedbolus))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.stoppingextendedbolus))); mSerialIOThread.sendMessage(new MsgSetExtendedBolusStop()); mSerialIOThread.sendMessage(new MsgStatusBolusExtended_v2()); loadEvents(); - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING)); + RxBus.INSTANCE.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING)); return true; } @@ -349,7 +365,7 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService { if (!isConnected()) return false; if (BolusProgressDialog.stopPressed) return false; - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.startingbolus))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.startingbolus))); mBolusingTreatment = t; final int preferencesSpeed = SP.getInt(R.string.key_danars_bolusspeed, 0); MessageBase start; @@ -387,9 +403,9 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService { } } - final EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance(); - bolusingEvent.t = t; - bolusingEvent.percent = 99; + final EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.INSTANCE; + bolusingEvent.setT(t); + bolusingEvent.setPercent(99); mBolusingTreatment = null; int speed = 12; @@ -408,8 +424,8 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService { long expectedEnd = bolusStart + bolusDurationInMSec + 2000; while (System.currentTimeMillis() < expectedEnd) { long waitTime = expectedEnd - System.currentTimeMillis(); - bolusingEvent.status = String.format(MainApp.gs(R.string.waitingforestimatedbolusend), waitTime / 1000); - MainApp.bus().post(bolusingEvent); + bolusingEvent.setStatus(String.format(MainApp.gs(R.string.waitingforestimatedbolusend), waitTime / 1000)); + RxBus.INSTANCE.send(bolusingEvent); SystemClock.sleep(1000); } // do not call loadEvents() directly, reconnection may be needed @@ -417,10 +433,10 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService { @Override public void run() { // load last bolus status - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingbolusstatus))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.gettingbolusstatus))); mSerialIOThread.sendMessage(new MsgStatus()); - bolusingEvent.percent = 100; - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.disconnecting))); + bolusingEvent.setPercent(100); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.disconnecting))); } }); return !start.failed; @@ -455,7 +471,7 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService { public PumpEnactResult loadEvents() { DanaRPump danaRPump = DanaRPump.getInstance(); - if (!MainApp.getSpecificPlugin(DanaRv2Plugin.class).isInitialized()) { + if (!DanaRv2Plugin.getPlugin().isInitialized()) { PumpEnactResult result = new PumpEnactResult().success(false); result.comment = "pump not initialized"; return result; @@ -485,7 +501,7 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService { public boolean updateBasalsInPump(final Profile profile) { DanaRPump danaRPump = DanaRPump.getInstance(); if (!isConnected()) return false; - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.updatingbasalrates))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.updatingbasalrates))); double[] basal = DanaRPump.getInstance().buildDanaRProfileRecord(profile); MsgSetBasalProfile msgSet = new MsgSetBasalProfile((byte) 0, basal); mSerialIOThread.sendMessage(msgSet); @@ -493,7 +509,7 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService { mSerialIOThread.sendMessage(msgActivate); danaRPump.lastSettingsRead = 0; // force read full settings getPumpStatus(); - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING)); + RxBus.INSTANCE.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING)); return true; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/InsightAlertService.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/InsightAlertService.java new file mode 100644 index 0000000000..26555898c0 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/InsightAlertService.java @@ -0,0 +1,260 @@ +package info.nightscout.androidaps.plugins.pump.insight; + +import android.app.Service; +import android.content.ComponentName; +import android.content.Intent; +import android.content.ServiceConnection; +import android.media.AudioAttributes; +import android.media.AudioManager; +import android.media.Ringtone; +import android.media.RingtoneManager; +import android.net.Uri; +import android.os.Binder; +import android.os.Build; +import android.os.Handler; +import android.os.IBinder; +import android.os.Looper; +import android.os.Vibrator; +import androidx.annotation.Nullable; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.pump.insight.activities.InsightAlertActivity; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.remote_control.ConfirmAlertMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.remote_control.SnoozeAlertMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.status.GetActiveAlertMessage; +import info.nightscout.androidaps.plugins.pump.insight.connection_service.InsightConnectionService; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.Alert; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.AlertStatus; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.AlertType; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.InsightState; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.InsightException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.AppLayerErrorException; +import info.nightscout.androidaps.plugins.pump.insight.utils.ExceptionTranslator; + +public class InsightAlertService extends Service implements InsightConnectionService.StateCallback { + + private static Logger log = LoggerFactory.getLogger(L.PUMPCOMM); + + private LocalBinder localBinder = new LocalBinder(); + private boolean connectionRequested; + private final Object $alertLock = new Object[0]; + private Alert alert; + private Thread thread; + private InsightAlertActivity alertActivity; + private Ringtone ringtone; + private Vibrator vibrator; + private boolean vibrating; + private InsightConnectionService connectionService; + private long ignoreTimestamp; + private AlertType ignoreType; + + private ServiceConnection serviceConnection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName name, IBinder binder) { + connectionService = ((InsightConnectionService.LocalBinder) binder).getService(); + connectionService.registerStateCallback(InsightAlertService.this); + onStateChanged(connectionService.getState()); + } + + @Override + public void onServiceDisconnected(ComponentName name) { + connectionService = null; + } + }; + + private void retrieveRingtone() { + Uri uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE); + ringtone = RingtoneManager.getRingtone(this, uri); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + ringtone.setAudioAttributes(new AudioAttributes.Builder() + .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE) + .setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN) + .setLegacyStreamType(AudioManager.STREAM_RING).build()); + } else ringtone.setStreamType(AudioManager.STREAM_RING); + } + + public Alert getAlert() { + synchronized ($alertLock) { + return alert; + } + } + + public void setAlertActivity(InsightAlertActivity alertActivity) { + this.alertActivity = alertActivity; + } + + public void ignore(AlertType alertType) { + synchronized ($alertLock) { + if (alertType == null) { + ignoreTimestamp = 0; + ignoreType = null; + } else { + ignoreTimestamp = System.currentTimeMillis(); + ignoreType = alertType; + } + } + } + + @Nullable + @Override + public IBinder onBind(Intent intent) { + return localBinder; + } + + @Override + public void onCreate() { + vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE); + bindService(new Intent(this, InsightConnectionService.class), serviceConnection, BIND_AUTO_CREATE); + } + + @Override + public void onDestroy() { + if (thread != null) thread.interrupt(); + unbindService(serviceConnection); + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + return START_STICKY; + } + + @Override + public void onStateChanged(InsightState state) { + if (state == InsightState.CONNECTED) { + thread = new Thread(this::queryActiveAlert); + thread.start(); + + } else if (thread != null) thread.interrupt(); + } + + private void queryActiveAlert() { + while (!Thread.currentThread().isInterrupted()) { + try { + Alert alert = connectionService.requestMessage(new GetActiveAlertMessage()).await().getAlert(); + if (Thread.currentThread().isInterrupted()) { + connectionService.withdrawConnectionRequest(thread); + break; + } + synchronized ($alertLock) { + if ((this.alert == null && alert != null) + || (this.alert != null && alert == null) + || (this.alert != null && alert != null && !this.alert.equals(alert))) { + if (this.alert != null && (alert == null || this.alert.getAlertId() != alert.getAlertId())) stopAlerting(); + this.alert = alert; + if (alertActivity != null && alert != null) + new Handler(Looper.getMainLooper()).post(() -> alertActivity.update(alert)); + } + if (alert == null) { + stopAlerting(); + if (connectionRequested) { + connectionService.withdrawConnectionRequest(this); + connectionRequested = false; + } + if (alertActivity != null) + new Handler(Looper.getMainLooper()).post(() -> alertActivity.finish()); + } else if (!(alert.getAlertType() == ignoreType && System.currentTimeMillis() - ignoreTimestamp < 10000)) { + if (alert.getAlertStatus() == AlertStatus.ACTIVE) alert(); + else stopAlerting(); + if (!connectionRequested) { + connectionService.requestConnection(this); + connectionRequested = true; + } + if (alertActivity == null) { + Intent intent = new Intent(InsightAlertService.this, InsightAlertActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); + new Handler(Looper.getMainLooper()).post(() -> startActivity(intent)); + } + } + } + } catch (InterruptedException ignored) { + connectionService.withdrawConnectionRequest(thread); + break; + } catch (AppLayerErrorException e) { + log.info("Exception while fetching alert: " + e.getClass().getCanonicalName() + " (" + e.getErrorCode() + ")"); + } catch (InsightException e) { + log.info("Exception while fetching alert: " + e.getClass().getSimpleName()); + } catch (Exception e) { + log.error("Exception while fetching alert", e); + } + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + break; + } + } + if (connectionRequested) { + connectionService.withdrawConnectionRequest(thread); + connectionRequested = false; + } + if (alertActivity != null) + new Handler(Looper.getMainLooper()).post(() -> alertActivity.finish()); + stopAlerting(); + thread = null; + } + + private void alert() { + if (!vibrating) { + vibrator.vibrate(new long[] {0, 1000, 1000}, 0); + vibrating = true; + } + if (ringtone == null || !ringtone.isPlaying()) { + retrieveRingtone(); + ringtone.play(); + } + } + + private void stopAlerting() { + if (vibrating) { + vibrator.cancel(); + vibrating = false; + } + if (ringtone != null && ringtone.isPlaying()) ringtone.stop(); + } + + public void mute() { + new Thread(() -> { + try { + SnoozeAlertMessage snoozeAlertMessage = new SnoozeAlertMessage(); + snoozeAlertMessage.setAlertID(alert.getAlertId()); + connectionService.requestMessage(snoozeAlertMessage).await(); + } catch (AppLayerErrorException e) { + log.info("Exception while muting alert: " + e.getClass().getCanonicalName() + " (" + e.getErrorCode() + ")"); + ExceptionTranslator.makeToast(InsightAlertService.this, e); + } catch (InsightException e) { + log.info("Exception while muting alert: " + e.getClass().getSimpleName()); + ExceptionTranslator.makeToast(InsightAlertService.this, e); + } catch (Exception e) { + log.error("Exception while muting alert", e); + ExceptionTranslator.makeToast(InsightAlertService.this, e); + } + }).start(); + } + + public void confirm() { + new Thread(() -> { + try { + ConfirmAlertMessage confirmAlertMessage = new ConfirmAlertMessage(); + confirmAlertMessage.setAlertID(alert.getAlertId()); + connectionService.requestMessage(confirmAlertMessage).await(); + } catch (AppLayerErrorException e) { + log.info("Exception while confirming alert: " + e.getClass().getCanonicalName() + " (" + e.getErrorCode() + ")"); + ExceptionTranslator.makeToast(InsightAlertService.this, e); + } catch (InsightException e) { + log.info("Exception while confirming alert: " + e.getClass().getSimpleName()); + ExceptionTranslator.makeToast(InsightAlertService.this, e); + } catch (Exception e) { + log.error("Exception while confirming alert", e); + ExceptionTranslator.makeToast(InsightAlertService.this, e); + } + }).start(); + } + + public class LocalBinder extends Binder { + public InsightAlertService getService() { + return InsightAlertService.this; + } + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/LocalInsightFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/LocalInsightFragment.java new file mode 100644 index 0000000000..3464a1803a --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/LocalInsightFragment.java @@ -0,0 +1,317 @@ +package info.nightscout.androidaps.plugins.pump.insight; + +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; + +import java.util.ArrayList; +import java.util.List; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks.TBROverNotificationBlock; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.ActiveBasalRate; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.ActiveBolus; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.ActiveTBR; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.CartridgeStatus; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.InsightState; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.TotalDailyDose; +import info.nightscout.androidaps.plugins.pump.insight.events.EventLocalInsightUpdateGUI; +import info.nightscout.androidaps.queue.Callback; +import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.DecimalFormatter; +import info.nightscout.androidaps.utils.FabricPrivacy; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.CompositeDisposable; + +public class LocalInsightFragment extends Fragment implements View.OnClickListener { + private CompositeDisposable disposable = new CompositeDisposable(); + + private static final boolean ENABLE_OPERATING_MODE_BUTTON = false; + + private boolean viewsCreated; + private Button operatingMode; + private Button tbrOverNotification; + private Button refresh; + private LinearLayout statusItemContainer = null; + + private Callback operatingModeCallback; + private Callback tbrOverNotificationCallback; + private Callback refreshCallback; + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.local_insight_fragment, container, false); + statusItemContainer = view.findViewById(R.id.status_item_container); + tbrOverNotification = view.findViewById(R.id.tbr_over_notification); + tbrOverNotification.setOnClickListener(this); + operatingMode = view.findViewById(R.id.operating_mode); + operatingMode.setOnClickListener(this); + refresh = view.findViewById(R.id.refresh); + refresh.setOnClickListener(this); + viewsCreated = true; + return view; + } + + @Override + public synchronized void onResume() { + super.onResume(); + disposable.add(RxBus.INSTANCE + .toObservable(EventLocalInsightUpdateGUI.class) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(event -> updateGUI(), FabricPrivacy::logException) + ); + updateGUI(); + } + + @Override + public synchronized void onPause() { + super.onPause(); + disposable.clear(); + } + + @Override + public synchronized void onDestroyView() { + super.onDestroyView(); + viewsCreated = false; + } + + @Override + public void onClick(View v) { + if (v == operatingMode) { + if (LocalInsightPlugin.getPlugin().getOperatingMode() != null) { + operatingMode.setEnabled(false); + operatingModeCallback = new Callback() { + @Override + public void run() { + new Handler(Looper.getMainLooper()).post(() -> { + operatingModeCallback = null; + updateGUI(); + }); + } + }; + switch (LocalInsightPlugin.getPlugin().getOperatingMode()) { + case PAUSED: + case STOPPED: + ConfigBuilderPlugin.getPlugin().getCommandQueue().startPump(operatingModeCallback); + break; + case STARTED: + ConfigBuilderPlugin.getPlugin().getCommandQueue().stopPump(operatingModeCallback); + } + } + } else if (v == tbrOverNotification) { + TBROverNotificationBlock notificationBlock = LocalInsightPlugin.getPlugin().getTBROverNotificationBlock(); + if (notificationBlock != null) { + tbrOverNotification.setEnabled(false); + tbrOverNotificationCallback = new Callback() { + @Override + public void run() { + new Handler(Looper.getMainLooper()).post(() -> { + tbrOverNotificationCallback = null; + updateGUI(); + }); + } + }; + ConfigBuilderPlugin.getPlugin().getCommandQueue() + .setTBROverNotification(tbrOverNotificationCallback, !notificationBlock.isEnabled()); + } + } else if (v == refresh) { + refresh.setEnabled(false); + refreshCallback = new Callback() { + @Override + public void run() { + new Handler(Looper.getMainLooper()).post(() -> { + refreshCallback = null; + updateGUI(); + }); + } + }; + ConfigBuilderPlugin.getPlugin().getCommandQueue().readStatus("InsightRefreshButton", refreshCallback); + } + } + + protected void updateGUI() { + if (!viewsCreated) return; + statusItemContainer.removeAllViews(); + if (!LocalInsightPlugin.getPlugin().isInitialized()) { + operatingMode.setVisibility(View.GONE); + tbrOverNotification.setVisibility(View.GONE); + refresh.setVisibility(View.GONE); + return; + } + refresh.setVisibility(View.VISIBLE); + refresh.setEnabled(refreshCallback == null); + TBROverNotificationBlock notificationBlock = LocalInsightPlugin.getPlugin().getTBROverNotificationBlock(); + tbrOverNotification.setVisibility(notificationBlock == null ? View.GONE : View.VISIBLE); + if (notificationBlock != null) + tbrOverNotification.setText(notificationBlock.isEnabled() ? R.string.disable_tbr_over_notification : R.string.enable_tbr_over_notification); + tbrOverNotification.setEnabled(tbrOverNotificationCallback == null); + List statusItems = new ArrayList<>(); + getConnectionStatusItem(statusItems); + getLastConnectedItem(statusItems); + getOperatingModeItem(statusItems); + getBatteryStatusItem(statusItems); + getCartridgeStatusItem(statusItems); + getTDDItems(statusItems); + getBaseBasalRateItem(statusItems); + getTBRItem(statusItems); + getBolusItems(statusItems); + for (int i = 0; i < statusItems.size(); i++) { + statusItemContainer.addView(statusItems.get(i)); + if (i != statusItems.size() - 1) + getLayoutInflater().inflate(R.layout.local_insight_status_delimitter, statusItemContainer); + } + } + + private View getStatusItem(String label, String value) { + View statusItem = getLayoutInflater().inflate(R.layout.local_insight_status_item, null); + ((TextView) statusItem.findViewById(R.id.label)).setText(label); + ((TextView) statusItem.findViewById(R.id.value)).setText(value); + return statusItem; + } + + private void getConnectionStatusItem(List statusItems) { + int string = 0; + InsightState state = LocalInsightPlugin.getPlugin().getConnectionService().getState(); + switch (state) { + case NOT_PAIRED: + string = R.string.not_paired; + break; + case DISCONNECTED: + string = R.string.disconnected; + break; + case CONNECTING: + case SATL_CONNECTION_REQUEST: + case SATL_KEY_REQUEST: + case SATL_SYN_REQUEST: + case SATL_VERIFY_CONFIRM_REQUEST: + case SATL_VERIFY_DISPLAY_REQUEST: + case APP_ACTIVATE_PARAMETER_SERVICE: + case APP_ACTIVATE_STATUS_SERVICE: + case APP_BIND_MESSAGE: + case APP_CONNECT_MESSAGE: + case APP_FIRMWARE_VERSIONS: + case APP_SYSTEM_IDENTIFICATION: + case AWAITING_CODE_CONFIRMATION: + string = R.string.connecting; + break; + case CONNECTED: + string = R.string.connected; + break; + case RECOVERING: + string = R.string.recovering; + break; + } + statusItems.add(getStatusItem(MainApp.gs(R.string.insight_status), MainApp.gs(string))); + if (state == InsightState.RECOVERING) { + statusItems.add(getStatusItem(MainApp.gs(R.string.recovery_duration), LocalInsightPlugin.getPlugin().getConnectionService().getRecoveryDuration() / 1000 + "s")); + } + } + + private void getLastConnectedItem(List statusItems) { + switch (LocalInsightPlugin.getPlugin().getConnectionService().getState()) { + case CONNECTED: + case NOT_PAIRED: + return; + default: + long lastConnection = LocalInsightPlugin.getPlugin().getConnectionService().getLastConnected(); + if (lastConnection == 0) return; + int min = (int) ((System.currentTimeMillis() - lastConnection) / 60000); + statusItems.add(getStatusItem(MainApp.gs(R.string.last_connected), DateUtil.timeString(lastConnection))); + } + } + + private void getOperatingModeItem(List statusItems) { + if (LocalInsightPlugin.getPlugin().getOperatingMode() == null) { + operatingMode.setVisibility(View.GONE); + return; + } + int string = 0; + if (ENABLE_OPERATING_MODE_BUTTON) operatingMode.setVisibility(View.VISIBLE); + operatingMode.setEnabled(operatingModeCallback == null); + switch (LocalInsightPlugin.getPlugin().getOperatingMode()) { + case STARTED: + operatingMode.setText(R.string.stop_pump); + string = R.string.started; + break; + case STOPPED: + operatingMode.setText(R.string.start_pump); + string = R.string.stopped; + break; + case PAUSED: + operatingMode.setText(R.string.start_pump); + string = R.string.paused; + break; + } + statusItems.add(getStatusItem(MainApp.gs(R.string.operating_mode), MainApp.gs(string))); + } + + private void getBatteryStatusItem(List statusItems) { + if (LocalInsightPlugin.getPlugin().getBatteryStatus() == null) return; + statusItems.add(getStatusItem(MainApp.gs(R.string.pump_battery_label), + LocalInsightPlugin.getPlugin().getBatteryStatus().getBatteryAmount() + "%")); + } + + private void getCartridgeStatusItem(List statusItems) { + CartridgeStatus cartridgeStatus = LocalInsightPlugin.getPlugin().getCartridgeStatus(); + if (cartridgeStatus == null) return; + String status; + if (cartridgeStatus.isInserted()) + status = DecimalFormatter.to2Decimal(LocalInsightPlugin.getPlugin().getCartridgeStatus().getRemainingAmount()) + "U"; + else status = MainApp.gs(R.string.not_inserted); + statusItems.add(getStatusItem(MainApp.gs(R.string.pump_reservoir_label), status)); + } + + private void getTDDItems(List statusItems) { + if (LocalInsightPlugin.getPlugin().getTotalDailyDose() == null) return; + TotalDailyDose tdd = LocalInsightPlugin.getPlugin().getTotalDailyDose(); + statusItems.add(getStatusItem(MainApp.gs(R.string.tdd_bolus), DecimalFormatter.to2Decimal(tdd.getBolus()))); + statusItems.add(getStatusItem(MainApp.gs(R.string.tdd_basal), DecimalFormatter.to2Decimal(tdd.getBasal()))); + statusItems.add(getStatusItem(MainApp.gs(R.string.tdd_total), DecimalFormatter.to2Decimal(tdd.getBolusAndBasal()))); + } + + private void getBaseBasalRateItem(List statusItems) { + if (LocalInsightPlugin.getPlugin().getActiveBasalRate() == null) return; + ActiveBasalRate activeBasalRate = LocalInsightPlugin.getPlugin().getActiveBasalRate(); + statusItems.add(getStatusItem(MainApp.gs(R.string.pump_basebasalrate_label), + DecimalFormatter.to2Decimal(activeBasalRate.getActiveBasalRate()) + " U/h (" + activeBasalRate.getActiveBasalProfileName() + ")")); + } + + private void getTBRItem(List statusItems) { + if (LocalInsightPlugin.getPlugin().getActiveTBR() == null) return; + ActiveTBR activeTBR = LocalInsightPlugin.getPlugin().getActiveTBR(); + statusItems.add(getStatusItem(MainApp.gs(R.string.pump_tempbasal_label), + MainApp.gs(R.string.tbr_formatter, activeTBR.getPercentage(), activeTBR.getInitialDuration() - activeTBR.getRemainingDuration(), activeTBR.getInitialDuration()))); + } + + private void getBolusItems(List statusItems) { + if (LocalInsightPlugin.getPlugin().getActiveBoluses() == null) return; + for (ActiveBolus activeBolus : LocalInsightPlugin.getPlugin().getActiveBoluses()) { + String label; + switch (activeBolus.getBolusType()) { + case MULTIWAVE: + label = MainApp.gs(R.string.multiwave_bolus); + break; + case EXTENDED: + label = MainApp.gs(R.string.extended_bolus); + break; + default: + continue; + } + statusItems.add(getStatusItem(label, MainApp.gs(R.string.eb_formatter, activeBolus.getRemainingAmount(), activeBolus.getInitialAmount(), activeBolus.getRemainingDuration()))); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/LocalInsightPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/LocalInsightPlugin.java new file mode 100644 index 0000000000..7baf9458c9 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/LocalInsightPlugin.java @@ -0,0 +1,1631 @@ +package info.nightscout.androidaps.plugins.pump.insight; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.Handler; +import android.os.IBinder; +import android.os.Looper; + +import androidx.fragment.app.FragmentActivity; + +import org.json.JSONException; +import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Collections; +import java.util.Date; +import java.util.List; +import java.util.TimeZone; + +import info.nightscout.androidaps.BuildConfig; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.data.DetailedBolusInfo; +import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.data.PumpEnactResult; +import info.nightscout.androidaps.db.CareportalEvent; +import info.nightscout.androidaps.db.ExtendedBolus; +import info.nightscout.androidaps.db.Source; +import info.nightscout.androidaps.db.TDD; +import info.nightscout.androidaps.db.TemporaryBasal; +import info.nightscout.androidaps.events.EventInitializationChanged; +import info.nightscout.androidaps.events.EventRefreshOverview; +import info.nightscout.androidaps.interfaces.Constraint; +import info.nightscout.androidaps.interfaces.ConstraintsInterface; +import info.nightscout.androidaps.interfaces.PluginBase; +import info.nightscout.androidaps.interfaces.PluginDescription; +import info.nightscout.androidaps.interfaces.PluginType; +import info.nightscout.androidaps.interfaces.PumpDescription; +import info.nightscout.androidaps.interfaces.PumpInterface; +import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.common.ManufacturerType; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; +import info.nightscout.androidaps.plugins.general.actions.defs.CustomAction; +import info.nightscout.androidaps.plugins.general.actions.defs.CustomActionType; +import info.nightscout.androidaps.plugins.general.nsclient.NSUpload; +import info.nightscout.androidaps.plugins.general.nsclient.UploadQueue; +import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification; +import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress; +import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; +import info.nightscout.androidaps.plugins.pump.common.defs.PumpType; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.Service; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.history.HistoryReadingDirection; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.history.ReadHistoryEventsMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.history.StartReadingHistoryMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.history.StopReadingHistoryMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events.BolusDeliveredEvent; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events.BolusProgrammedEvent; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events.CannulaFilledEvent; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events.DateTimeChangedEvent; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events.DefaultDateTimeSetEvent; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events.EndOfTBREvent; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events.HistoryEvent; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events.OccurrenceOfAlertEvent; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events.OperatingModeChangedEvent; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events.PowerUpEvent; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events.SniffingDoneEvent; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events.StartOfTBREvent; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events.TotalDailyDoseEvent; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events.TubeFilledEvent; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks.ActiveBRProfileBlock; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks.BRProfile1Block; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks.BRProfileBlock; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks.FactoryMinBasalAmountBlock; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks.FactoryMinBolusAmountBlock; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks.MaxBasalAmountBlock; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks.MaxBolusAmountBlock; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks.TBROverNotificationBlock; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.remote_control.CancelBolusMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.remote_control.CancelTBRMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.remote_control.ChangeTBRMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.remote_control.ConfirmAlertMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.remote_control.DeliverBolusMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.remote_control.SetDateTimeMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.remote_control.SetOperatingModeMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.remote_control.SetTBRMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.status.GetActiveAlertMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.status.GetActiveBasalRateMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.status.GetActiveBolusesMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.status.GetActiveTBRMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.status.GetBatteryStatusMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.status.GetCartridgeStatusMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.status.GetDateTimeMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.status.GetOperatingModeMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.status.GetPumpStatusRegisterMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.status.GetTotalDailyDoseMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.status.ResetPumpStatusRegisterMessage; +import info.nightscout.androidaps.plugins.pump.insight.connection_service.InsightConnectionService; +import info.nightscout.androidaps.plugins.pump.insight.database.InsightBolusID; +import info.nightscout.androidaps.plugins.pump.insight.database.InsightHistoryOffset; +import info.nightscout.androidaps.plugins.pump.insight.database.InsightPumpID; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.ActiveBasalRate; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.ActiveBolus; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.ActiveTBR; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.AlertType; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.BasalProfile; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.BasalProfileBlock; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.BatteryStatus; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.BolusType; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.CartridgeStatus; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.InsightState; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.OperatingMode; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.PumpTime; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.TotalDailyDose; +import info.nightscout.androidaps.plugins.pump.insight.events.EventLocalInsightUpdateGUI; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.InsightException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.AppLayerErrorException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.NoActiveTBRToCanceLException; +import info.nightscout.androidaps.plugins.pump.insight.utils.ExceptionTranslator; +import info.nightscout.androidaps.plugins.pump.insight.utils.ParameterBlockUtil; +import info.nightscout.androidaps.plugins.treatments.Treatment; +import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; +import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.SP; + +public class LocalInsightPlugin extends PluginBase implements PumpInterface, ConstraintsInterface, InsightConnectionService.StateCallback { + + private static LocalInsightPlugin instance = null; + + private Logger log = LoggerFactory.getLogger(L.PUMP); + + private PumpDescription pumpDescription; + private InsightAlertService alertService; + private InsightConnectionService connectionService; + private long timeOffset; + private ServiceConnection serviceConnection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName name, IBinder binder) { + if (binder instanceof InsightConnectionService.LocalBinder) { + connectionService = ((InsightConnectionService.LocalBinder) binder).getService(); + connectionService.registerStateCallback(LocalInsightPlugin.this); + } else if (binder instanceof InsightAlertService.LocalBinder) { + alertService = ((InsightAlertService.LocalBinder) binder).getService(); + } + if (connectionService != null && alertService != null) { + RxBus.INSTANCE.send(new EventInitializationChanged()); + } + } + + @Override + public void onServiceDisconnected(ComponentName name) { + connectionService = null; + } + }; + + private final Object $bolusLock = new Object[0]; + private int bolusID; + private boolean bolusCancelled; + private BasalProfile activeBasalProfile; + private List profileBlocks; + private boolean limitsFetched; + private double maximumBolusAmount; + private double maximumBasalAmount; + private double minimumBolusAmount; + private double minimumBasalAmount; + private long lastUpdated = -1; + private OperatingMode operatingMode; + private BatteryStatus batteryStatus; + private CartridgeStatus cartridgeStatus; + private TotalDailyDose totalDailyDose; + private ActiveBasalRate activeBasalRate; + private ActiveTBR activeTBR; + private List activeBoluses; + private boolean statusLoaded; + private TBROverNotificationBlock tbrOverNotificationBlock; + + public static LocalInsightPlugin getPlugin() { + if (instance == null) instance = new LocalInsightPlugin(); + return instance; + } + + public LocalInsightPlugin() { + super(new PluginDescription() + .pluginName(R.string.insight_local) + .shortName(R.string.insightpump_shortname) + .mainType(PluginType.PUMP) + .description(R.string.description_pump_insight_local) + .fragmentClass(LocalInsightFragment.class.getName()) + .preferencesId(MainApp.instance().getPackageName().equals("info.nightscout.androidaps") + ? R.xml.pref_insight_local_full : R.xml.pref_insight_local_pumpcontrol)); + + pumpDescription = new PumpDescription(); + pumpDescription.setPumpDescription(PumpType.AccuChekInsightBluetooth); + } + + public TBROverNotificationBlock getTBROverNotificationBlock() { + return tbrOverNotificationBlock; + } + + public long getLastUpdated() { + return lastUpdated; + } + + public InsightConnectionService getConnectionService() { + return connectionService; + } + + public OperatingMode getOperatingMode() { + return operatingMode; + } + + public BatteryStatus getBatteryStatus() { + return batteryStatus; + } + + public CartridgeStatus getCartridgeStatus() { + return cartridgeStatus; + } + + public TotalDailyDose getTotalDailyDose() { + return totalDailyDose; + } + + public ActiveBasalRate getActiveBasalRate() { + return activeBasalRate; + } + + public ActiveTBR getActiveTBR() { + return activeTBR; + } + + public List getActiveBoluses() { + return activeBoluses; + } + + @Override + protected void onStart() { + super.onStart(); + MainApp.instance().bindService(new Intent(MainApp.instance(), InsightConnectionService.class), serviceConnection, Context.BIND_AUTO_CREATE); + MainApp.instance().bindService(new Intent(MainApp.instance(), InsightAlertService.class), serviceConnection, Context.BIND_AUTO_CREATE); + } + + @Override + protected void onStop() { + super.onStop(); + MainApp.instance().unbindService(serviceConnection); + } + + @Override + public void switchAllowed(boolean newState, FragmentActivity activity, PluginType type) { + confirmPumpPluginActivation(newState, activity, type); + } + + @Override + public boolean isInitialized() { + return connectionService != null && alertService != null && connectionService.isPaired(); + } + + @Override + public boolean isSuspended() { + return operatingMode != null && operatingMode != OperatingMode.STARTED; + } + + @Override + public boolean isBusy() { + return false; + } + + @Override + public boolean isConnected() { + return connectionService != null + && alertService != null + && connectionService.hasRequestedConnection(this) + && connectionService.getState() == InsightState.CONNECTED; + } + + @Override + public boolean isConnecting() { + if (connectionService == null || alertService == null || !connectionService.hasRequestedConnection(this)) + return false; + InsightState state = connectionService.getState(); + return state == InsightState.CONNECTING + || state == InsightState.APP_CONNECT_MESSAGE + || state == InsightState.RECOVERING; + } + + @Override + public boolean isHandshakeInProgress() { + return false; + } + + @Override + public void finishHandshaking() { + + } + + @Override + public void connect(String reason) { + if (connectionService != null && alertService != null) + connectionService.requestConnection(this); + } + + @Override + public void disconnect(String reason) { + if (connectionService != null && alertService != null) + connectionService.withdrawConnectionRequest(this); + } + + @Override + public void stopConnecting() { + if (connectionService != null && alertService != null) + connectionService.withdrawConnectionRequest(this); + } + + @Override + public void getPumpStatus() { + try { + tbrOverNotificationBlock = ParameterBlockUtil.readParameterBlock(connectionService, Service.CONFIGURATION, TBROverNotificationBlock.class); + readHistory(); + fetchBasalProfile(); + fetchLimitations(); + updatePumpTimeIfNeeded(); + fetchStatus(); + } catch (AppLayerErrorException e) { + log.info("Exception while fetching status: " + e.getClass().getCanonicalName() + " (" + e.getErrorCode() + ")"); + } catch (InsightException e) { + log.info("Exception while fetching status: " + e.getClass().getCanonicalName()); + } catch (Exception e) { + log.error("Exception while fetching status", e); + } + } + + private void updatePumpTimeIfNeeded() throws Exception { + PumpTime pumpTime = connectionService.requestMessage(new GetDateTimeMessage()).await().getPumpTime(); + Calendar calendar = Calendar.getInstance(); + calendar.set(Calendar.YEAR, pumpTime.getYear()); + calendar.set(Calendar.MONTH, pumpTime.getMonth() - 1); + calendar.set(Calendar.DAY_OF_MONTH, pumpTime.getDay()); + calendar.set(Calendar.HOUR_OF_DAY, pumpTime.getHour()); + calendar.set(Calendar.MINUTE, pumpTime.getMinute()); + calendar.set(Calendar.SECOND, pumpTime.getSecond()); + if (calendar.get(Calendar.HOUR_OF_DAY) != pumpTime.getHour() || Math.abs(calendar.getTimeInMillis() - System.currentTimeMillis()) > 10000) { + calendar.setTime(new Date()); + pumpTime.setYear(calendar.get(Calendar.YEAR)); + pumpTime.setMonth(calendar.get(Calendar.MONTH) + 1); + pumpTime.setDay(calendar.get(Calendar.DAY_OF_MONTH)); + pumpTime.setHour(calendar.get(Calendar.HOUR_OF_DAY)); + pumpTime.setMinute(calendar.get(Calendar.MINUTE)); + pumpTime.setSecond(calendar.get(Calendar.SECOND)); + SetDateTimeMessage setDateTimeMessage = new SetDateTimeMessage(); + setDateTimeMessage.setPumpTime(pumpTime); + connectionService.requestMessage(setDateTimeMessage).await(); + Notification notification = new Notification(Notification.INSIGHT_DATE_TIME_UPDATED, MainApp.gs(R.string.pump_time_updated), Notification.INFO, 60); + RxBus.INSTANCE.send(new EventNewNotification(notification)); + } + } + + private void fetchBasalProfile() throws Exception { + activeBasalProfile = ParameterBlockUtil.readParameterBlock(connectionService, Service.CONFIGURATION, ActiveBRProfileBlock.class).getActiveBasalProfile(); + profileBlocks = ParameterBlockUtil.readParameterBlock(connectionService, Service.CONFIGURATION, BRProfile1Block.class).getProfileBlocks(); + } + + private void fetchStatus() throws Exception { + if (statusLoaded) { + GetPumpStatusRegisterMessage registerMessage = connectionService.requestMessage(new GetPumpStatusRegisterMessage()).await(); + ResetPumpStatusRegisterMessage resetMessage = new ResetPumpStatusRegisterMessage(); + resetMessage.setOperatingModeChanged(registerMessage.isOperatingModeChanged()); + resetMessage.setBatteryStatusChanged(registerMessage.isBatteryStatusChanged()); + resetMessage.setCartridgeStatusChanged(registerMessage.isCartridgeStatusChanged()); + resetMessage.setTotalDailyDoseChanged(registerMessage.isTotalDailyDoseChanged()); + resetMessage.setActiveTBRChanged(registerMessage.isActiveTBRChanged()); + resetMessage.setActiveBolusesChanged(registerMessage.isActiveBolusesChanged()); + connectionService.requestMessage(resetMessage).await(); + if (registerMessage.isOperatingModeChanged()) + operatingMode = connectionService.requestMessage(new GetOperatingModeMessage()).await().getOperatingMode(); + if (registerMessage.isBatteryStatusChanged()) + batteryStatus = connectionService.requestMessage(new GetBatteryStatusMessage()).await().getBatteryStatus(); + if (registerMessage.isCartridgeStatusChanged()) + cartridgeStatus = connectionService.requestMessage(new GetCartridgeStatusMessage()).await().getCartridgeStatus(); + if (registerMessage.isTotalDailyDoseChanged()) + totalDailyDose = connectionService.requestMessage(new GetTotalDailyDoseMessage()).await().getTDD(); + if (operatingMode == OperatingMode.STARTED) { + if (registerMessage.isActiveBasalRateChanged()) + activeBasalRate = connectionService.requestMessage(new GetActiveBasalRateMessage()).await().getActiveBasalRate(); + if (registerMessage.isActiveTBRChanged()) + activeTBR = connectionService.requestMessage(new GetActiveTBRMessage()).await().getActiveTBR(); + if (registerMessage.isActiveBolusesChanged()) + activeBoluses = connectionService.requestMessage(new GetActiveBolusesMessage()).await().getActiveBoluses(); + } else { + activeBasalRate = null; + activeTBR = null; + activeBoluses = null; + } + + } else { + ResetPumpStatusRegisterMessage resetMessage = new ResetPumpStatusRegisterMessage(); + resetMessage.setOperatingModeChanged(true); + resetMessage.setBatteryStatusChanged(true); + resetMessage.setCartridgeStatusChanged(true); + resetMessage.setTotalDailyDoseChanged(true); + resetMessage.setActiveBasalRateChanged(true); + resetMessage.setActiveTBRChanged(true); + resetMessage.setActiveBolusesChanged(true); + connectionService.requestMessage(resetMessage).await(); + operatingMode = connectionService.requestMessage(new GetOperatingModeMessage()).await().getOperatingMode(); + batteryStatus = connectionService.requestMessage(new GetBatteryStatusMessage()).await().getBatteryStatus(); + cartridgeStatus = connectionService.requestMessage(new GetCartridgeStatusMessage()).await().getCartridgeStatus(); + totalDailyDose = connectionService.requestMessage(new GetTotalDailyDoseMessage()).await().getTDD(); + if (operatingMode == OperatingMode.STARTED) { + activeBasalRate = connectionService.requestMessage(new GetActiveBasalRateMessage()).await().getActiveBasalRate(); + activeTBR = connectionService.requestMessage(new GetActiveTBRMessage()).await().getActiveTBR(); + activeBoluses = connectionService.requestMessage(new GetActiveBolusesMessage()).await().getActiveBoluses(); + } else { + activeBasalRate = null; + activeTBR = null; + activeBoluses = null; + } + statusLoaded = true; + } + lastUpdated = System.currentTimeMillis(); + new Handler(Looper.getMainLooper()).post(() -> { + RxBus.INSTANCE.send(new EventLocalInsightUpdateGUI()); + RxBus.INSTANCE.send(new EventRefreshOverview("LocalInsightPlugin::fetchStatus")); + }); + } + + private void fetchLimitations() throws Exception { + maximumBolusAmount = ParameterBlockUtil.readParameterBlock(connectionService, Service.CONFIGURATION, MaxBolusAmountBlock.class).getAmountLimitation(); + maximumBasalAmount = ParameterBlockUtil.readParameterBlock(connectionService, Service.CONFIGURATION, MaxBasalAmountBlock.class).getAmountLimitation(); + minimumBolusAmount = ParameterBlockUtil.readParameterBlock(connectionService, Service.CONFIGURATION, FactoryMinBolusAmountBlock.class).getAmountLimitation(); + minimumBasalAmount = ParameterBlockUtil.readParameterBlock(connectionService, Service.CONFIGURATION, FactoryMinBasalAmountBlock.class).getAmountLimitation(); + this.pumpDescription.basalMaximumRate = maximumBasalAmount; + this.pumpDescription.basalMinimumRate = minimumBasalAmount; + limitsFetched = true; + } + + @Override + public PumpEnactResult setNewBasalProfile(Profile profile) { + PumpEnactResult result = new PumpEnactResult(); + RxBus.INSTANCE.send(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED)); + List profileBlocks = new ArrayList<>(); + for (int i = 0; i < profile.getBasalValues().length; i++) { + Profile.ProfileValue basalValue = profile.getBasalValues()[i]; + Profile.ProfileValue nextValue = null; + if (profile.getBasalValues().length > i + 1) + nextValue = profile.getBasalValues()[i + 1]; + BasalProfileBlock profileBlock = new BasalProfileBlock(); + profileBlock.setBasalAmount(basalValue.value > 5 ? Math.round(basalValue.value / 0.1) * 0.1 : Math.round(basalValue.value / 0.01) * 0.01); + profileBlock.setDuration((((nextValue != null ? nextValue.timeAsSeconds : 24 * 60 * 60) - basalValue.timeAsSeconds) / 60)); + profileBlocks.add(profileBlock); + } + try { + ActiveBRProfileBlock activeBRProfileBlock = new ActiveBRProfileBlock(); + activeBRProfileBlock.setActiveBasalProfile(BasalProfile.PROFILE_1); + ParameterBlockUtil.writeConfigurationBlock(connectionService, activeBRProfileBlock); + activeBasalProfile = BasalProfile.PROFILE_1; + BRProfileBlock profileBlock = new BRProfile1Block(); + profileBlock.setProfileBlocks(profileBlocks); + ParameterBlockUtil.writeConfigurationBlock(connectionService, profileBlock); + RxBus.INSTANCE.send(new EventDismissNotification(Notification.FAILED_UDPATE_PROFILE)); + Notification notification = new Notification(Notification.PROFILE_SET_OK, MainApp.gs(R.string.profile_set_ok), Notification.INFO, 60); + RxBus.INSTANCE.send(new EventNewNotification(notification)); + result.success = true; + result.enacted = true; + result.comment = MainApp.gs(R.string.virtualpump_resultok); + this.profileBlocks = profileBlocks; + try { + fetchStatus(); + } catch (Exception ignored) { + } + } catch (AppLayerErrorException e) { + log.info("Exception while setting profile: " + e.getClass().getCanonicalName() + " (" + e.getErrorCode() + ")"); + Notification notification = new Notification(Notification.FAILED_UDPATE_PROFILE, MainApp.gs(R.string.failedupdatebasalprofile), Notification.URGENT); + RxBus.INSTANCE.send(new EventNewNotification(notification)); + result.comment = ExceptionTranslator.getString(e); + } catch (InsightException e) { + log.info("Exception while setting profile: " + e.getClass().getCanonicalName()); + Notification notification = new Notification(Notification.FAILED_UDPATE_PROFILE, MainApp.gs(R.string.failedupdatebasalprofile), Notification.URGENT); + RxBus.INSTANCE.send(new EventNewNotification(notification)); + result.comment = ExceptionTranslator.getString(e); + } catch (Exception e) { + log.error("Exception while setting profile", e); + Notification notification = new Notification(Notification.FAILED_UDPATE_PROFILE, MainApp.gs(R.string.failedupdatebasalprofile), Notification.URGENT); + RxBus.INSTANCE.send(new EventNewNotification(notification)); + result.comment = ExceptionTranslator.getString(e); + } + return result; + } + + @Override + public boolean isThisProfileSet(Profile profile) { + if (!isInitialized() || profileBlocks == null) return true; + if (profile.getBasalValues().length != profileBlocks.size()) return false; + if (activeBasalProfile != BasalProfile.PROFILE_1) return false; + for (int i = 0; i < profileBlocks.size(); i++) { + BasalProfileBlock profileBlock = profileBlocks.get(i); + Profile.ProfileValue basalValue = profile.getBasalValues()[i]; + Profile.ProfileValue nextValue = null; + if (profile.getBasalValues().length > i + 1) + nextValue = profile.getBasalValues()[i + 1]; + if (profileBlock.getDuration() * 60 != (nextValue != null ? nextValue.timeAsSeconds : 24 * 60 * 60) - basalValue.timeAsSeconds) + return false; + if (Math.abs(profileBlock.getBasalAmount() - basalValue.value) > (basalValue.value > 5 ? 0.05 : 0.005)) + return false; + } + return true; + } + + @Override + public long lastDataTime() { + if (connectionService == null || alertService == null) return System.currentTimeMillis(); + return connectionService.getLastDataTime(); + } + + @Override + public double getBaseBasalRate() { + if (connectionService == null || alertService == null) return 0; + if (activeBasalRate != null) return activeBasalRate.getActiveBasalRate(); + else return 0; + } + + @Override + public double getReservoirLevel() { + if (cartridgeStatus == null) return 0; + return cartridgeStatus.getRemainingAmount(); + } + + @Override + public int getBatteryLevel() { + if (batteryStatus == null) return 0; + return batteryStatus.getBatteryAmount(); + } + + @Override + public PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo) { + PumpEnactResult result = new PumpEnactResult(); + double insulin = Math.round(detailedBolusInfo.insulin / 0.01) * 0.01; + if (insulin > 0) { + try { + synchronized ($bolusLock) { + DeliverBolusMessage bolusMessage = new DeliverBolusMessage(); + bolusMessage.setBolusType(BolusType.STANDARD); + bolusMessage.setDuration(0); + bolusMessage.setExtendedAmount(0); + bolusMessage.setImmediateAmount(insulin); + bolusID = connectionService.requestMessage(bolusMessage).await().getBolusId(); + bolusCancelled = false; + } + result.success = true; + result.enacted = true; + Treatment t = new Treatment(); + t.isSMB = detailedBolusInfo.isSMB; + final EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.INSTANCE; + bolusingEvent.setT(t); + bolusingEvent.setStatus(MainApp.gs(R.string.insight_delivered, 0d, insulin)); + bolusingEvent.setPercent(0); + RxBus.INSTANCE.send(bolusingEvent); + int trials = 0; + InsightBolusID insightBolusID = new InsightBolusID(); + insightBolusID.bolusID = bolusID; + insightBolusID.timestamp = System.currentTimeMillis(); + insightBolusID.pumpSerial = connectionService.getPumpSystemIdentification().getSerialNumber(); + MainApp.getDbHelper().createOrUpdate(insightBolusID); + detailedBolusInfo.date = insightBolusID.timestamp; + detailedBolusInfo.source = Source.PUMP; + detailedBolusInfo.pumpId = insightBolusID.id; + TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, true); + while (true) { + synchronized ($bolusLock) { + if (bolusCancelled) break; + } + OperatingMode operatingMode = connectionService.requestMessage(new GetOperatingModeMessage()).await().getOperatingMode(); + if (operatingMode != OperatingMode.STARTED) break; + List activeBoluses = connectionService.requestMessage(new GetActiveBolusesMessage()).await().getActiveBoluses(); + ActiveBolus activeBolus = null; + for (ActiveBolus bolus : activeBoluses) { + if (bolus.getBolusID() == bolusID) { + activeBolus = bolus; + break; + } + } + if (activeBolus != null) { + trials = -1; + int percentBefore = bolusingEvent.getPercent(); + bolusingEvent.setPercent((int) (100D / activeBolus.getInitialAmount() * (activeBolus.getInitialAmount() - activeBolus.getRemainingAmount()))); + bolusingEvent.setStatus(MainApp.gs(R.string.insight_delivered, activeBolus.getInitialAmount() - activeBolus.getRemainingAmount(), activeBolus.getInitialAmount())); + if (percentBefore != bolusingEvent.getPercent()) + RxBus.INSTANCE.send(bolusingEvent); + } else { + synchronized ($bolusLock) { + if (bolusCancelled || trials == -1 || trials++ >= 5) { + if (!bolusCancelled) { + bolusingEvent.setStatus(MainApp.gs(R.string.insight_delivered, insulin, insulin)); + bolusingEvent.setPercent(100); + RxBus.INSTANCE.send(bolusingEvent); + } + break; + } + } + } + Thread.sleep(200); + } + readHistory(); + fetchStatus(); + } catch (AppLayerErrorException e) { + log.info("Exception while delivering bolus: " + e.getClass().getCanonicalName() + " (" + e.getErrorCode() + ")"); + result.comment = ExceptionTranslator.getString(e); + } catch (InsightException e) { + log.info("Exception while delivering bolus: " + e.getClass().getCanonicalName()); + result.comment = ExceptionTranslator.getString(e); + } catch (Exception e) { + log.error("Exception while delivering bolus", e); + result.comment = ExceptionTranslator.getString(e); + } + } else if (detailedBolusInfo.carbs > 0) { + result.success = true; + result.enacted = true; + } + result.carbsDelivered = detailedBolusInfo.carbs; + result.bolusDelivered = insulin; + return result; + } + + @Override + public void stopBolusDelivering() { + new Thread(() -> { + try { + synchronized ($bolusLock) { + alertService.ignore(AlertType.WARNING_38); + CancelBolusMessage cancelBolusMessage = new CancelBolusMessage(); + cancelBolusMessage.setBolusID(bolusID); + connectionService.requestMessage(cancelBolusMessage).await(); + bolusCancelled = true; + } + confirmAlert(AlertType.WARNING_38); + } catch (AppLayerErrorException e) { + log.info("Exception while canceling bolus: " + e.getClass().getCanonicalName() + " (" + e.getErrorCode() + ")"); + } catch (InsightException e) { + log.info("Exception while canceling bolus: " + e.getClass().getCanonicalName()); + } catch (Exception e) { + log.error("Exception while canceling bolus", e); + } + }).start(); + } + + @Override + public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, Profile profile, boolean enforceNew) { + PumpEnactResult result = new PumpEnactResult(); + if (activeBasalRate == null) return result; + if (activeBasalRate.getActiveBasalRate() == 0) return result; + double percent = 100D / activeBasalRate.getActiveBasalRate() * absoluteRate; + if (isFakingTempsByExtendedBoluses()) { + PumpEnactResult cancelEBResult = cancelExtendedBolusOnly(); + if (cancelEBResult.success) { + if (percent > 250) { + PumpEnactResult cancelTBRResult = cancelTempBasalOnly(); + if (cancelTBRResult.success) { + PumpEnactResult ebResult = setExtendedBolusOnly((absoluteRate - getBaseBasalRate()) / 60D + * ((double) durationInMinutes), durationInMinutes); + if (ebResult.success) { + result.success = true; + result.enacted = true; + result.isPercent = false; + result.absolute = absoluteRate; + result.duration = durationInMinutes; + result.comment = MainApp.gs(R.string.virtualpump_resultok); + } else { + result.comment = ebResult.comment; + } + } else { + result.comment = cancelTBRResult.comment; + } + } else { + return setTempBasalPercent((int) Math.round(percent), durationInMinutes, profile, enforceNew); + } + } else { + result.comment = cancelEBResult.comment; + } + } else { + return setTempBasalPercent((int) Math.round(percent), durationInMinutes, profile, enforceNew); + } + try { + fetchStatus(); + readHistory(); + } catch (AppLayerErrorException e) { + log.info("Exception after setting TBR: " + e.getClass().getCanonicalName() + " (" + e.getErrorCode() + ")"); + } catch (InsightException e) { + log.info("Exception after setting TBR: " + e.getClass().getCanonicalName()); + } catch (Exception e) { + log.error("Exception after setting TBR", e); + } + return result; + } + + @Override + public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, Profile profile, boolean enforceNew) { + PumpEnactResult result = new PumpEnactResult(); + percent = (int) Math.round(((double) percent) / 10d) * 10; + if (percent == 100) return cancelTempBasal(true); + else if (percent > 250) percent = 250; + try { + if (activeTBR != null) { + ChangeTBRMessage message = new ChangeTBRMessage(); + message.setDuration(durationInMinutes); + message.setPercentage(percent); + connectionService.requestMessage(message); + } else { + SetTBRMessage message = new SetTBRMessage(); + message.setDuration(durationInMinutes); + message.setPercentage(percent); + connectionService.requestMessage(message); + } + result.isPercent = true; + result.percent = percent; + result.duration = durationInMinutes; + result.success = true; + result.enacted = true; + result.comment = MainApp.gs(R.string.virtualpump_resultok); + readHistory(); + fetchStatus(); + } catch (AppLayerErrorException e) { + log.info("Exception while setting TBR: " + e.getClass().getCanonicalName() + " (" + e.getErrorCode() + ")"); + result.comment = ExceptionTranslator.getString(e); + } catch (InsightException e) { + log.info("Exception while setting TBR: " + e.getClass().getCanonicalName()); + result.comment = ExceptionTranslator.getString(e); + } catch (Exception e) { + log.error("Exception while setting TBR", e); + result.comment = ExceptionTranslator.getString(e); + } + return result; + } + + @Override + public PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes) { + PumpEnactResult result = cancelExtendedBolusOnly(); + if (result.success) result = setExtendedBolusOnly(insulin, durationInMinutes); + try { + fetchStatus(); + readHistory(); + } catch (AppLayerErrorException e) { + log.info("Exception after delivering extended bolus: " + e.getClass().getCanonicalName() + " (" + e.getErrorCode() + ")"); + } catch (InsightException e) { + log.info("Exception after delivering extended bolus: " + e.getClass().getCanonicalName()); + } catch (Exception e) { + log.error("Exception after delivering extended bolus", e); + } + return result; + } + + public PumpEnactResult setExtendedBolusOnly(Double insulin, Integer durationInMinutes) { + PumpEnactResult result = new PumpEnactResult(); + try { + DeliverBolusMessage bolusMessage = new DeliverBolusMessage(); + bolusMessage.setBolusType(BolusType.EXTENDED); + bolusMessage.setDuration(durationInMinutes); + bolusMessage.setExtendedAmount(insulin); + bolusMessage.setImmediateAmount(0); + int bolusID = connectionService.requestMessage(bolusMessage).await().getBolusId(); + InsightBolusID insightBolusID = new InsightBolusID(); + insightBolusID.bolusID = bolusID; + insightBolusID.timestamp = System.currentTimeMillis(); + insightBolusID.pumpSerial = connectionService.getPumpSystemIdentification().getSerialNumber(); + MainApp.getDbHelper().createOrUpdate(insightBolusID); + ExtendedBolus extendedBolus = new ExtendedBolus(); + extendedBolus.date = insightBolusID.timestamp; + extendedBolus.source = Source.PUMP; + extendedBolus.durationInMinutes = durationInMinutes; + extendedBolus.insulin = insulin; + extendedBolus.pumpId = insightBolusID.id; + TreatmentsPlugin.getPlugin().addToHistoryExtendedBolus(extendedBolus); + result.success = true; + result.enacted = true; + result.comment = MainApp.gs(R.string.virtualpump_resultok); + } catch (AppLayerErrorException e) { + log.info("Exception while delivering extended bolus: " + e.getClass().getCanonicalName() + " (" + e.getErrorCode() + ")"); + result.comment = ExceptionTranslator.getString(e); + } catch (InsightException e) { + log.info("Exception while delivering extended bolus: " + e.getClass().getCanonicalName()); + result.comment = ExceptionTranslator.getString(e); + } catch (Exception e) { + log.error("Exception while delivering extended bolus", e); + result.comment = ExceptionTranslator.getString(e); + } + return result; + } + + @Override + public PumpEnactResult cancelTempBasal(boolean enforceNew) { + PumpEnactResult result = new PumpEnactResult(); + PumpEnactResult cancelEBResult = null; + if (isFakingTempsByExtendedBoluses()) cancelEBResult = cancelExtendedBolusOnly(); + PumpEnactResult cancelTBRResult = cancelTempBasalOnly(); + result.success = (cancelEBResult != null && cancelEBResult.success) && cancelTBRResult.success; + result.enacted = (cancelEBResult != null && cancelEBResult.enacted) || cancelTBRResult.enacted; + result.comment = cancelEBResult != null ? cancelEBResult.comment : cancelTBRResult.comment; + try { + fetchStatus(); + readHistory(); + } catch (AppLayerErrorException e) { + log.info("Exception after canceling TBR: " + e.getClass().getCanonicalName() + " (" + e.getErrorCode() + ")"); + } catch (InsightException e) { + log.info("Exception after canceling TBR: " + e.getClass().getCanonicalName()); + } catch (Exception e) { + log.error("Exception after canceling TBR", e); + } + return result; + } + + private PumpEnactResult cancelTempBasalOnly() { + PumpEnactResult result = new PumpEnactResult(); + try { + alertService.ignore(AlertType.WARNING_36); + connectionService.requestMessage(new CancelTBRMessage()).await(); + result.success = true; + result.enacted = true; + result.isTempCancel = true; + confirmAlert(AlertType.WARNING_36); + alertService.ignore(null); + result.comment = MainApp.gs(R.string.virtualpump_resultok); + } catch (NoActiveTBRToCanceLException e) { + result.success = true; + result.comment = MainApp.gs(R.string.virtualpump_resultok); + } catch (AppLayerErrorException e) { + log.info("Exception while canceling TBR: " + e.getClass().getCanonicalName() + " (" + e.getErrorCode() + ")"); + result.comment = ExceptionTranslator.getString(e); + } catch (InsightException e) { + log.info("Exception while canceling TBR: " + e.getClass().getCanonicalName()); + result.comment = ExceptionTranslator.getString(e); + } catch (Exception e) { + log.error("Exception while canceling TBR", e); + result.comment = ExceptionTranslator.getString(e); + } + return result; + } + + @Override + public PumpEnactResult cancelExtendedBolus() { + PumpEnactResult result = cancelExtendedBolusOnly(); + try { + fetchStatus(); + readHistory(); + } catch (AppLayerErrorException e) { + log.info("Exception after canceling extended bolus: " + e.getClass().getCanonicalName() + " (" + e.getErrorCode() + ")"); + } catch (InsightException e) { + log.info("Exception after canceling extended bolus: " + e.getClass().getCanonicalName()); + } catch (Exception e) { + log.error("Exception after canceling extended bolus", e); + } + return result; + } + + private PumpEnactResult cancelExtendedBolusOnly() { + PumpEnactResult result = new PumpEnactResult(); + try { + for (ActiveBolus activeBolus : activeBoluses) { + if (activeBolus.getBolusType() == BolusType.EXTENDED || activeBolus.getBolusType() == BolusType.MULTIWAVE) { + alertService.ignore(AlertType.WARNING_38); + CancelBolusMessage cancelBolusMessage = new CancelBolusMessage(); + cancelBolusMessage.setBolusID(activeBolus.getBolusID()); + connectionService.requestMessage(cancelBolusMessage).await(); + confirmAlert(AlertType.WARNING_38); + alertService.ignore(null); + InsightBolusID insightBolusID = MainApp.getDbHelper().getInsightBolusID(connectionService.getPumpSystemIdentification().getSerialNumber(), + activeBolus.getBolusID(), System.currentTimeMillis()); + if (insightBolusID != null) { + ExtendedBolus extendedBolus = MainApp.getDbHelper().getExtendedBolusByPumpId(insightBolusID.id); + if (extendedBolus != null) { + extendedBolus.durationInMinutes = (int) ((System.currentTimeMillis() - extendedBolus.date) / 60000); + if (extendedBolus.durationInMinutes <= 0) { + final String _id = extendedBolus._id; + if (NSUpload.isIdValid(_id)) + NSUpload.removeCareportalEntryFromNS(_id); + else UploadQueue.removeID("dbAdd", _id); + MainApp.getDbHelper().delete(extendedBolus); + } else + TreatmentsPlugin.getPlugin().addToHistoryExtendedBolus(extendedBolus); + } + result.enacted = true; + result.success = true; + } + } + } + result.success = true; + result.comment = MainApp.gs(R.string.virtualpump_resultok); + } catch (AppLayerErrorException e) { + log.info("Exception while canceling extended bolus: " + e.getClass().getCanonicalName() + " (" + e.getErrorCode() + ")"); + result.comment = ExceptionTranslator.getString(e); + } catch (InsightException e) { + log.info("Exception while canceling extended bolus: " + e.getClass().getCanonicalName()); + result.comment = ExceptionTranslator.getString(e); + } catch (Exception e) { + log.error("Exception while canceling extended bolus", e); + result.comment = ExceptionTranslator.getString(e); + } + return result; + } + + private void confirmAlert(AlertType alertType) { + try { + long started = System.currentTimeMillis(); + while (System.currentTimeMillis() - started < 10000) { + GetActiveAlertMessage activeAlertMessage = connectionService.requestMessage(new GetActiveAlertMessage()).await(); + if (activeAlertMessage.getAlert() != null) { + if (activeAlertMessage.getAlert().getAlertType() == alertType) { + ConfirmAlertMessage confirmMessage = new ConfirmAlertMessage(); + confirmMessage.setAlertID(activeAlertMessage.getAlert().getAlertId()); + connectionService.requestMessage(confirmMessage).await(); + } else break; + } + } + } catch (AppLayerErrorException e) { + log.info("Exception while confirming alert: " + e.getClass().getCanonicalName() + " (" + e.getErrorCode() + ")"); + } catch (InsightException e) { + log.info("Exception while confirming alert: " + e.getClass().getCanonicalName()); + } catch (Exception e) { + log.error("Exception while confirming alert", e); + } + } + + @Override + public JSONObject getJSONStatus(Profile profile, String profileName) { + long now = System.currentTimeMillis(); + if (System.currentTimeMillis() - connectionService.getLastConnected() > (60 * 60 * 1000)) { + return null; + } + + final JSONObject pump = new JSONObject(); + final JSONObject battery = new JSONObject(); + final JSONObject status = new JSONObject(); + final JSONObject extended = new JSONObject(); + try { + status.put("timestamp", DateUtil.toISOString(connectionService.getLastConnected())); + extended.put("Version", BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION); + try { + extended.put("ActiveProfile", ProfileFunctions.getInstance().getProfileName()); + } catch (Exception e) { + } + TemporaryBasal tb = TreatmentsPlugin.getPlugin().getTempBasalFromHistory(now); + if (tb != null) { + extended.put("TempBasalAbsoluteRate", tb.tempBasalConvertedToAbsolute(now, profile)); + extended.put("TempBasalStart", DateUtil.dateAndTimeString(tb.date)); + extended.put("TempBasalRemaining", tb.getPlannedRemainingMinutes()); + } + ExtendedBolus eb = TreatmentsPlugin.getPlugin().getExtendedBolusFromHistory(now); + if (eb != null) { + extended.put("ExtendedBolusAbsoluteRate", eb.absoluteRate()); + extended.put("ExtendedBolusStart", DateUtil.dateAndTimeString(eb.date)); + extended.put("ExtendedBolusRemaining", eb.getPlannedRemainingMinutes()); + } + extended.put("BaseBasalRate", getBaseBasalRate()); + status.put("timestamp", DateUtil.toISOString(now)); + + pump.put("extended", extended); + if (statusLoaded) { + status.put("status", operatingMode != OperatingMode.STARTED ? "suspended" : "normal"); + pump.put("status", status); + battery.put("percent", batteryStatus.getBatteryAmount()); + pump.put("battery", battery); + pump.put("reservoir", cartridgeStatus.getRemainingAmount()); + } + pump.put("clock", DateUtil.toISOString(now)); + } catch (JSONException e) { + log.error("Unhandled exception", e); + } + return pump; + } + + @Override + public ManufacturerType manufacturer() { + return ManufacturerType.Roche; + } + + @Override + public PumpType model() { + return PumpType.AccuChekInsightBluetooth; + } + + @Override + public String serialNumber() { + if (connectionService == null || alertService == null) return "Unknown"; + return connectionService.getPumpSystemIdentification().getSerialNumber(); + } + + public PumpEnactResult stopPump() { + PumpEnactResult result = new PumpEnactResult(); + try { + SetOperatingModeMessage operatingModeMessage = new SetOperatingModeMessage(); + operatingModeMessage.setOperatingMode(OperatingMode.STOPPED); + connectionService.requestMessage(operatingModeMessage).await(); + result.success = true; + result.enacted = true; + fetchStatus(); + readHistory(); + } catch (AppLayerErrorException e) { + log.info("Exception while stopping pump: " + e.getClass().getCanonicalName() + " (" + e.getErrorCode() + ")"); + result.comment = ExceptionTranslator.getString(e); + } catch (InsightException e) { + log.info("Exception while stopping pump: " + e.getClass().getCanonicalName()); + result.comment = ExceptionTranslator.getString(e); + } catch (Exception e) { + log.error("Exception while stopping pump", e); + result.comment = ExceptionTranslator.getString(e); + } + return result; + } + + public PumpEnactResult startPump() { + PumpEnactResult result = new PumpEnactResult(); + try { + SetOperatingModeMessage operatingModeMessage = new SetOperatingModeMessage(); + operatingModeMessage.setOperatingMode(OperatingMode.STARTED); + connectionService.requestMessage(operatingModeMessage).await(); + result.success = true; + result.enacted = true; + fetchStatus(); + readHistory(); + } catch (AppLayerErrorException e) { + log.info("Exception while starting pump: " + e.getClass().getCanonicalName() + " (" + e.getErrorCode() + ")"); + result.comment = ExceptionTranslator.getString(e); + } catch (InsightException e) { + log.info("Exception while starting pump: " + e.getClass().getCanonicalName()); + result.comment = ExceptionTranslator.getString(e); + } catch (Exception e) { + log.error("Exception while starting pump", e); + result.comment = ExceptionTranslator.getString(e); + } + return result; + } + + public PumpEnactResult setTBROverNotification(boolean enabled) { + PumpEnactResult result = new PumpEnactResult(); + boolean valueBefore = tbrOverNotificationBlock.isEnabled(); + tbrOverNotificationBlock.setEnabled(enabled); + try { + ParameterBlockUtil.writeConfigurationBlock(connectionService, tbrOverNotificationBlock); + result.success = true; + result.enacted = true; + } catch (AppLayerErrorException e) { + tbrOverNotificationBlock.setEnabled(valueBefore); + log.info("Exception while updating TBR notification block: " + e.getClass().getCanonicalName() + " (" + e.getErrorCode() + ")"); + result.comment = ExceptionTranslator.getString(e); + } catch (InsightException e) { + tbrOverNotificationBlock.setEnabled(valueBefore); + log.info("Exception while updating TBR notification block: " + e.getClass().getSimpleName()); + result.comment = ExceptionTranslator.getString(e); + } catch (Exception e) { + tbrOverNotificationBlock.setEnabled(valueBefore); + log.error("Exception while updating TBR notification block", e); + result.comment = ExceptionTranslator.getString(e); + } + return result; + } + + @Override + public PumpDescription getPumpDescription() { + return pumpDescription; + } + + @Override + public String shortStatus(boolean veryShort) { + StringBuilder ret = new StringBuilder(); + if (connectionService.getLastConnected() != 0) { + Long agoMsec = System.currentTimeMillis() - connectionService.getLastConnected(); + int agoMin = (int) (agoMsec / 60d / 1000d); + ret.append(MainApp.gs(R.string.short_status_last_connected, agoMin) + "\n"); + } + if (activeTBR != null) { + ret.append(MainApp.gs(R.string.short_status_tbr, activeTBR.getPercentage(), + activeTBR.getInitialDuration() - activeTBR.getRemainingDuration(), activeTBR.getInitialDuration()) + "\n"); + } + if (activeBoluses != null) for (ActiveBolus activeBolus : activeBoluses) { + if (activeBolus.getBolusType() == BolusType.STANDARD) continue; + ret.append(MainApp.gs(activeBolus.getBolusType() == BolusType.MULTIWAVE ? R.string.short_status_multiwave : R.string.short_status_extended, + activeBolus.getRemainingAmount(), activeBolus.getInitialAmount(), activeBolus.getRemainingDuration()) + "\n"); + } + if (!veryShort && totalDailyDose != null) { + ret.append(MainApp.gs(R.string.short_status_tdd, totalDailyDose.getBolusAndBasal()) + "\n"); + } + if (cartridgeStatus != null) { + ret.append(MainApp.gs(R.string.short_status_reservoir, cartridgeStatus.getRemainingAmount()) + "\n"); + } + if (batteryStatus != null) { + ret.append(MainApp.gs(R.string.short_status_battery, batteryStatus.getBatteryAmount()) + "\n"); + } + return ret.toString(); + } + + @Override + public boolean isFakingTempsByExtendedBoluses() { + return SP.getBoolean("insight_enable_tbr_emulation", false); + } + + @Override + public PumpEnactResult loadTDDs() { + return new PumpEnactResult().success(true); + } + + @Override + public List getCustomActions() { + return null; + } + + @Override + public void executeCustomAction(CustomActionType customActionType) { + + } + + private void readHistory() { + try { + PumpTime pumpTime = connectionService.requestMessage(new GetDateTimeMessage()).await().getPumpTime(); + String pumpSerial = connectionService.getPumpSystemIdentification().getSerialNumber(); + timeOffset = Calendar.getInstance(TimeZone.getTimeZone("UTC")).getTimeInMillis() - parseDate(pumpTime.getYear(), + pumpTime.getMonth(), pumpTime.getDay(), pumpTime.getHour(), pumpTime.getMinute(), pumpTime.getSecond()); + InsightHistoryOffset historyOffset = MainApp.getDbHelper().getInsightHistoryOffset(pumpSerial); + try { + List historyEvents = new ArrayList<>(); + if (historyOffset == null) { + StartReadingHistoryMessage startMessage = new StartReadingHistoryMessage(); + startMessage.setDirection(HistoryReadingDirection.BACKWARD); + startMessage.setOffset(0xFFFFFFFF); + connectionService.requestMessage(startMessage).await(); + historyEvents = connectionService.requestMessage(new ReadHistoryEventsMessage()).await().getHistoryEvents(); + } else { + StartReadingHistoryMessage startMessage = new StartReadingHistoryMessage(); + startMessage.setDirection(HistoryReadingDirection.FORWARD); + startMessage.setOffset(historyOffset.offset + 1); + connectionService.requestMessage(startMessage).await(); + while (true) { + List newEvents = connectionService.requestMessage(new ReadHistoryEventsMessage()).await().getHistoryEvents(); + if (newEvents.size() == 0) break; + historyEvents.addAll(newEvents); + } + } + Collections.sort(historyEvents); + Collections.reverse(historyEvents); + if (historyOffset != null) processHistoryEvents(pumpSerial, historyEvents); + if (historyEvents.size() > 0) { + historyOffset = new InsightHistoryOffset(); + historyOffset.pumpSerial = pumpSerial; + historyOffset.offset = historyEvents.get(0).getEventPosition(); + MainApp.getDbHelper().createOrUpdate(historyOffset); + } + } catch (AppLayerErrorException e) { + log.info("Exception while reading history: " + e.getClass().getCanonicalName() + " (" + e.getErrorCode() + ")"); + } catch (InsightException e) { + log.info("Exception while reading history: " + e.getClass().getSimpleName()); + } catch (Exception e) { + log.error("Exception while reading history", e); + } finally { + try { + connectionService.requestMessage(new StopReadingHistoryMessage()).await(); + } catch (Exception ignored) { + } + } + } catch (AppLayerErrorException e) { + log.info("Exception while reading history: " + e.getClass().getCanonicalName() + " (" + e.getErrorCode() + ")"); + } catch (InsightException e) { + log.info("Exception while reading history: " + e.getClass().getSimpleName()); + } catch (Exception e) { + log.error("Exception while reading history", e); + } + new Handler(Looper.getMainLooper()).post(() -> RxBus.INSTANCE.send(new EventRefreshOverview("LocalInsightPlugin::readHistory"))); + } + + private void processHistoryEvents(String serial, List historyEvents) { + List temporaryBasals = new ArrayList<>(); + List pumpStartedEvents = new ArrayList<>(); + for (HistoryEvent historyEvent : historyEvents) + if (!processHistoryEvent(serial, temporaryBasals, pumpStartedEvents, historyEvent)) + break; + Collections.reverse(temporaryBasals); + for (InsightPumpID pumpID : pumpStartedEvents) { + InsightPumpID stoppedEvent = MainApp.getDbHelper().getPumpStoppedEvent(pumpID.pumpSerial, pumpID.timestamp); + if (stoppedEvent == null || stoppedEvent.eventType.equals("PumpPaused")) continue; + long tbrStart = stoppedEvent.timestamp + 10000; + TemporaryBasal temporaryBasal = new TemporaryBasal(); + temporaryBasal.durationInMinutes = (int) ((pumpID.timestamp - tbrStart) / 60000); + temporaryBasal.date = tbrStart; + temporaryBasal.source = Source.PUMP; + temporaryBasal.pumpId = pumpID.id; + temporaryBasal.percentRate = 0; + temporaryBasal.isAbsolute = false; + temporaryBasals.add(temporaryBasal); + } + Collections.sort(temporaryBasals, (o1, o2) -> (int) (o1.date - o2.date)); + for (TemporaryBasal temporaryBasal : temporaryBasals) + TreatmentsPlugin.getPlugin().addToHistoryTempBasal(temporaryBasal); + } + + private boolean processHistoryEvent(String serial, List temporaryBasals, List pumpStartedEvents, HistoryEvent event) { + if (event instanceof DefaultDateTimeSetEvent) return false; + else if (event instanceof DateTimeChangedEvent) + processDateTimeChangedEvent((DateTimeChangedEvent) event); + else if (event instanceof CannulaFilledEvent) + processCannulaFilledEvent((CannulaFilledEvent) event); + else if (event instanceof TotalDailyDoseEvent) + processTotalDailyDoseEvent((TotalDailyDoseEvent) event); + else if (event instanceof TubeFilledEvent) processTubeFilledEvent((TubeFilledEvent) event); + else if (event instanceof SniffingDoneEvent) + processSniffingDoneEvent((SniffingDoneEvent) event); + else if (event instanceof PowerUpEvent) processPowerUpEvent((PowerUpEvent) event); + else if (event instanceof OperatingModeChangedEvent) + processOperatingModeChangedEvent(serial, pumpStartedEvents, (OperatingModeChangedEvent) event); + else if (event instanceof StartOfTBREvent) + processStartOfTBREvent(serial, temporaryBasals, (StartOfTBREvent) event); + else if (event instanceof EndOfTBREvent) + processEndOfTBREvent(serial, temporaryBasals, (EndOfTBREvent) event); + else if (event instanceof BolusProgrammedEvent) + processBolusProgrammedEvent(serial, (BolusProgrammedEvent) event); + else if (event instanceof BolusDeliveredEvent) + processBolusDeliveredEvent(serial, (BolusDeliveredEvent) event); + else if (event instanceof OccurrenceOfAlertEvent) + processOccurrenceOfAlertEvent((OccurrenceOfAlertEvent) event); + return true; + } + + private void processDateTimeChangedEvent(DateTimeChangedEvent event) { + long timeAfter = parseDate(event.getEventYear(), event.getEventMonth(), event.getEventDay(), event.getEventHour(), event.getEventMinute(), event.getEventSecond()); + long timeBefore = parseDate(event.getBeforeYear(), event.getBeforeMonth(), event.getBeforeDay(), event.getBeforeHour(), event.getBeforeMinute(), event.getBeforeSecond()); + timeOffset -= timeAfter - timeBefore; + } + + private void processCannulaFilledEvent(CannulaFilledEvent event) { + if (!SP.getBoolean("insight_log_site_changes", false)) return; + long timestamp = parseDate(event.getEventYear(), event.getEventMonth(), event.getEventDay(), + event.getEventHour(), event.getEventMinute(), event.getEventSecond()) + timeOffset; + uploadCareportalEvent(timestamp, CareportalEvent.SITECHANGE); + } + + private void processTotalDailyDoseEvent(TotalDailyDoseEvent event) { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(new Date(0)); + calendar.set(Calendar.YEAR, event.getTotalYear()); + calendar.set(Calendar.MONTH, event.getTotalMonth() - 1); + calendar.set(Calendar.DAY_OF_MONTH, event.getTotalDay()); + TDD tdd = new TDD(); + tdd.basal = event.getBasalTotal(); + tdd.bolus = event.getBolusTotal(); + tdd.total = tdd.basal + tdd.bolus; + tdd.date = calendar.getTimeInMillis(); + MainApp.getDbHelper().createOrUpdateTDD(tdd); + } + + private void processTubeFilledEvent(TubeFilledEvent event) { + if (!SP.getBoolean("insight_log_tube_changes", false)) return; + long timestamp = parseDate(event.getEventYear(), event.getEventMonth(), event.getEventDay(), + event.getEventHour(), event.getEventMinute(), event.getEventSecond()) + timeOffset; + logNote(timestamp, MainApp.gs(R.string.tube_changed)); + } + + private void processSniffingDoneEvent(SniffingDoneEvent event) { + if (!SP.getBoolean("insight_log_reservoir_changes", false)) return; + long timestamp = parseDate(event.getEventYear(), event.getEventMonth(), event.getEventDay(), + event.getEventHour(), event.getEventMinute(), event.getEventSecond()) + timeOffset; + uploadCareportalEvent(timestamp, CareportalEvent.INSULINCHANGE); + } + + private void processPowerUpEvent(PowerUpEvent event) { + if (!SP.getBoolean("insight_log_battery_changes", false)) return; + long timestamp = parseDate(event.getEventYear(), event.getEventMonth(), event.getEventDay(), + event.getEventHour(), event.getEventMinute(), event.getEventSecond()) + timeOffset; + uploadCareportalEvent(timestamp, CareportalEvent.PUMPBATTERYCHANGE); + } + + private void processOperatingModeChangedEvent(String serial, List pumpStartedEvents, OperatingModeChangedEvent event) { + long timestamp = parseDate(event.getEventYear(), event.getEventMonth(), event.getEventDay(), + event.getEventHour(), event.getEventMinute(), event.getEventSecond()) + timeOffset; + InsightPumpID pumpID = new InsightPumpID(); + pumpID.eventID = event.getEventPosition(); + pumpID.pumpSerial = serial; + pumpID.timestamp = timestamp; + switch (event.getNewValue()) { + case STARTED: + pumpID.eventType = "PumpStarted"; + pumpStartedEvents.add(pumpID); + if (SP.getBoolean("insight_log_operating_mode_changes", false)) + logNote(timestamp, MainApp.gs(R.string.pump_started)); + break; + case STOPPED: + pumpID.eventType = "PumpStopped"; + if (SP.getBoolean("insight_log_operating_mode_changes", false)) + logNote(timestamp, MainApp.gs(R.string.pump_stopped)); + break; + case PAUSED: + pumpID.eventType = "PumpPaused"; + if (SP.getBoolean("insight_log_operating_mode_changes", false)) + logNote(timestamp, MainApp.gs(R.string.pump_paused)); + break; + } + MainApp.getDbHelper().createOrUpdate(pumpID); + } + + private void processStartOfTBREvent(String serial, List temporaryBasals, StartOfTBREvent event) { + long timestamp = parseDate(event.getEventYear(), event.getEventMonth(), event.getEventDay(), + event.getEventHour(), event.getEventMinute(), event.getEventSecond()) + timeOffset; + InsightPumpID pumpID = new InsightPumpID(); + pumpID.eventID = event.getEventPosition(); + pumpID.pumpSerial = serial; + pumpID.timestamp = timestamp; + pumpID.eventType = "StartOfTBR"; + MainApp.getDbHelper().createOrUpdate(pumpID); + TemporaryBasal temporaryBasal = new TemporaryBasal(); + temporaryBasal.durationInMinutes = event.getDuration(); + temporaryBasal.source = Source.PUMP; + temporaryBasal.pumpId = pumpID.id; + temporaryBasal.percentRate = event.getAmount(); + temporaryBasal.isAbsolute = false; + temporaryBasal.date = timestamp; + temporaryBasals.add(temporaryBasal); + } + + private void processEndOfTBREvent(String serial, List temporaryBasals, EndOfTBREvent event) { + long timestamp = parseDate(event.getEventYear(), event.getEventMonth(), event.getEventDay(), + event.getEventHour(), event.getEventMinute(), event.getEventSecond()) + timeOffset; + InsightPumpID pumpID = new InsightPumpID(); + pumpID.eventID = event.getEventPosition(); + pumpID.pumpSerial = serial; + pumpID.eventType = "EndOfTBR"; + pumpID.timestamp = timestamp; + MainApp.getDbHelper().createOrUpdate(pumpID); + TemporaryBasal temporaryBasal = new TemporaryBasal(); + temporaryBasal.durationInMinutes = 0; + temporaryBasal.source = Source.PUMP; + temporaryBasal.pumpId = pumpID.id; + temporaryBasal.date = timestamp; + temporaryBasals.add(temporaryBasal); + } + + private void processBolusProgrammedEvent(String serial, BolusProgrammedEvent event) { + long timestamp = parseDate(event.getEventYear(), event.getEventMonth(), event.getEventDay(), + event.getEventHour(), event.getEventMinute(), event.getEventSecond()) + timeOffset; + InsightBolusID bolusID = MainApp.getDbHelper().getInsightBolusID(serial, event.getBolusID(), timestamp); + if (bolusID != null && bolusID.endID != null) { + bolusID.startID = event.getEventPosition(); + MainApp.getDbHelper().createOrUpdate(bolusID); + return; + } + if (bolusID == null || bolusID.startID != null) { + bolusID = new InsightBolusID(); + bolusID.timestamp = timestamp; + bolusID.bolusID = event.getBolusID(); + bolusID.pumpSerial = serial; + } + bolusID.startID = event.getEventPosition(); + MainApp.getDbHelper().createOrUpdate(bolusID); + if (event.getBolusType() == BolusType.STANDARD || event.getBolusType() == BolusType.MULTIWAVE) { + DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); + detailedBolusInfo.date = bolusID.timestamp; + detailedBolusInfo.source = Source.PUMP; + detailedBolusInfo.pumpId = bolusID.id; + detailedBolusInfo.insulin = event.getImmediateAmount(); + TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, true); + } + if ((event.getBolusType() == BolusType.EXTENDED || event.getBolusType() == BolusType.MULTIWAVE)) { + ExtendedBolus extendedBolus = new ExtendedBolus(); + extendedBolus.date = bolusID.timestamp; + extendedBolus.source = Source.PUMP; + extendedBolus.durationInMinutes = event.getDuration(); + extendedBolus.insulin = event.getExtendedAmount(); + extendedBolus.pumpId = bolusID.id; + if (ProfileFunctions.getInstance().getProfile(extendedBolus.date) != null) + TreatmentsPlugin.getPlugin().addToHistoryExtendedBolus(extendedBolus); + } + } + + private void processBolusDeliveredEvent(String serial, BolusDeliveredEvent event) { + long timestamp = parseDate(event.getEventYear(), event.getEventMonth(), event.getEventDay(), + event.getEventHour(), event.getEventMinute(), event.getEventSecond()) + timeOffset; + long startTimestamp = parseRelativeDate(event.getEventYear(), event.getEventMonth(), event.getEventDay(), event.getEventHour(), + event.getEventMinute(), event.getEventSecond(), event.getStartHour(), event.getStartMinute(), event.getStartSecond()) + timeOffset; + InsightBolusID bolusID = MainApp.getDbHelper().getInsightBolusID(serial, event.getBolusID(), timestamp); + if (bolusID == null || bolusID.endID != null) { + bolusID = new InsightBolusID(); + bolusID.timestamp = startTimestamp; + bolusID.bolusID = event.getBolusID(); + bolusID.pumpSerial = serial; + } + bolusID.endID = event.getEventPosition(); + MainApp.getDbHelper().createOrUpdate(bolusID); + if (event.getBolusType() == BolusType.STANDARD || event.getBolusType() == BolusType.MULTIWAVE) { + DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); + detailedBolusInfo.date = bolusID.timestamp; + detailedBolusInfo.source = Source.PUMP; + detailedBolusInfo.pumpId = bolusID.id; + detailedBolusInfo.insulin = event.getImmediateAmount(); + TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, true); + } + if (event.getBolusType() == BolusType.EXTENDED || event.getBolusType() == BolusType.MULTIWAVE) { + if (event.getDuration() == 0) { + ExtendedBolus extendedBolus = MainApp.getDbHelper().getExtendedBolusByPumpId(bolusID.id); + if (extendedBolus != null) { + final String _id = extendedBolus._id; + if (NSUpload.isIdValid(_id)) NSUpload.removeCareportalEntryFromNS(_id); + else UploadQueue.removeID("dbAdd", _id); + MainApp.getDbHelper().delete(extendedBolus); + } + } else { + ExtendedBolus extendedBolus = new ExtendedBolus(); + extendedBolus.date = bolusID.timestamp; + extendedBolus.source = Source.PUMP; + extendedBolus.durationInMinutes = event.getDuration(); + extendedBolus.insulin = event.getExtendedAmount(); + extendedBolus.pumpId = bolusID.id; + if (ProfileFunctions.getInstance().getProfile(extendedBolus.date) != null) + TreatmentsPlugin.getPlugin().addToHistoryExtendedBolus(extendedBolus); + } + } + } + + private void processOccurrenceOfAlertEvent(OccurrenceOfAlertEvent event) { + if (!SP.getBoolean("insight_log_alerts", false)) return; + long timestamp = parseDate(event.getEventYear(), event.getEventMonth(), event.getEventDay(), + event.getEventHour(), event.getEventMinute(), event.getEventSecond()) + timeOffset; + Integer code = null; + Integer title = null; + switch (event.getAlertType()) { + case ERROR_6: + code = R.string.alert_e6_code; + title = R.string.alert_e6_title; + break; + case ERROR_10: + code = R.string.alert_e10_code; + title = R.string.alert_e10_title; + break; + case ERROR_13: + code = R.string.alert_e13_code; + title = R.string.alert_e13_title; + break; + case MAINTENANCE_20: + code = R.string.alert_m20_code; + title = R.string.alert_m20_title; + break; + case MAINTENANCE_21: + code = R.string.alert_m21_code; + title = R.string.alert_m21_title; + break; + case MAINTENANCE_22: + code = R.string.alert_m22_code; + title = R.string.alert_m22_title; + break; + case MAINTENANCE_23: + code = R.string.alert_m23_code; + title = R.string.alert_m23_title; + break; + case MAINTENANCE_24: + code = R.string.alert_m24_code; + title = R.string.alert_m24_title; + break; + case MAINTENANCE_25: + code = R.string.alert_m25_code; + title = R.string.alert_m25_title; + break; + case MAINTENANCE_26: + code = R.string.alert_m26_code; + title = R.string.alert_m26_title; + break; + case MAINTENANCE_27: + code = R.string.alert_m27_code; + title = R.string.alert_m27_title; + break; + case MAINTENANCE_28: + code = R.string.alert_m28_code; + title = R.string.alert_m28_title; + break; + case MAINTENANCE_29: + code = R.string.alert_m29_code; + title = R.string.alert_m29_title; + break; + case MAINTENANCE_30: + code = R.string.alert_m30_code; + title = R.string.alert_m30_title; + break; + case WARNING_31: + code = R.string.alert_w31_code; + title = R.string.alert_w31_title; + break; + case WARNING_32: + code = R.string.alert_w32_code; + title = R.string.alert_w32_title; + break; + case WARNING_33: + code = R.string.alert_w33_code; + title = R.string.alert_w33_title; + break; + case WARNING_34: + code = R.string.alert_w34_code; + title = R.string.alert_w34_title; + break; + case WARNING_39: + code = R.string.alert_w39_code; + title = R.string.alert_w39_title; + break; + } + if (code != null) + logNote(timestamp, MainApp.gs(R.string.insight_alert_formatter, MainApp.gs(code), MainApp.gs(title))); + } + + private long parseDate(int year, int month, int day, int hour, int minute, int second) { + Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC")); + calendar.set(Calendar.YEAR, year); + calendar.set(Calendar.MONTH, month - 1); + calendar.set(Calendar.DAY_OF_MONTH, day); + calendar.set(Calendar.HOUR_OF_DAY, hour); + calendar.set(Calendar.MINUTE, minute); + calendar.set(Calendar.SECOND, second); + return calendar.getTimeInMillis(); + } + + private void logNote(long date, String note) { + try { + if (MainApp.getDbHelper().getCareportalEventFromTimestamp(date) != null) + return; + JSONObject data = new JSONObject(); + String enteredBy = SP.getString("careportal_enteredby", ""); + if (!enteredBy.equals("")) data.put("enteredBy", enteredBy); + data.put("created_at", DateUtil.toISOString(date)); + data.put("eventType", CareportalEvent.NOTE); + data.put("notes", note); + NSUpload.uploadCareportalEntryToNS(data); + } catch (JSONException e) { + e.printStackTrace(); + } + } + + private long parseRelativeDate(int year, int month, int day, int hour, int minute, int second, int relativeHour, int relativeMinute, int relativeSecond) { + if (relativeHour * 60 * 60 + relativeMinute * 60 + relativeSecond >= hour * 60 * 60 * minute * 60 + second) + day--; + Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC")); + calendar.set(Calendar.YEAR, year); + calendar.set(Calendar.MONTH, month - 1); + calendar.set(Calendar.DAY_OF_MONTH, day); + calendar.set(Calendar.HOUR_OF_DAY, relativeHour); + calendar.set(Calendar.MINUTE, relativeMinute); + calendar.set(Calendar.SECOND, relativeSecond); + return calendar.getTimeInMillis(); + } + + private void uploadCareportalEvent(long date, String event) { + if (MainApp.getDbHelper().getCareportalEventFromTimestamp(date) != null) + return; + try { + JSONObject data = new JSONObject(); + String enteredBy = SP.getString("careportal_enteredby", ""); + if (!enteredBy.equals("")) data.put("enteredBy", enteredBy); + data.put("created_at", DateUtil.toISOString(date)); + data.put("eventType", event); + NSUpload.uploadCareportalEntryToNS(data); + } catch (JSONException e) { + e.printStackTrace(); + } + } + + @Override + public Constraint applyBasalPercentConstraints(Constraint percentRate, Profile profile) { + percentRate.setIfGreater(0, String.format(MainApp.gs(R.string.limitingpercentrate), 0, MainApp.gs(R.string.itmustbepositivevalue)), this); + percentRate.setIfSmaller(getPumpDescription().maxTempPercent, String.format(MainApp.gs(R.string.limitingpercentrate), getPumpDescription().maxTempPercent, MainApp.gs(R.string.pumplimit)), this); + return percentRate; + } + + @Override + public Constraint applyBolusConstraints(Constraint insulin) { + if (!limitsFetched) return insulin; + insulin.setIfSmaller(maximumBolusAmount, String.format(MainApp.gs(R.string.limitingbolus), maximumBolusAmount, MainApp.gs(R.string.pumplimit)), this); + if (insulin.value() < minimumBolusAmount) { + + //TODO: Add function to Constraints or use different approach + // This only works if the interface of the InsightPlugin is called last. + // If not, another constraint could theoretically set the value between 0 and minimumBolusAmount + + insulin.set(0d, String.format(MainApp.gs(R.string.limitingbolus), minimumBolusAmount, MainApp.gs(R.string.pumplimit)), this); + } + return insulin; + } + + @Override + public Constraint applyExtendedBolusConstraints(Constraint insulin) { + return applyBolusConstraints(insulin); + } + + @Override + public void onStateChanged(InsightState state) { + if (state == InsightState.CONNECTED) { + statusLoaded = false; + new Handler(Looper.getMainLooper()).post(() -> RxBus.INSTANCE.send(new EventDismissNotification(Notification.INSIGHT_TIMEOUT_DURING_HANDSHAKE))); + } else if (state == InsightState.NOT_PAIRED) { + connectionService.withdrawConnectionRequest(this); + statusLoaded = false; + profileBlocks = null; + operatingMode = null; + batteryStatus = null; + cartridgeStatus = null; + totalDailyDose = null; + activeBasalRate = null; + activeTBR = null; + activeBoluses = null; + tbrOverNotificationBlock = null; + new Handler(Looper.getMainLooper()).post(() -> RxBus.INSTANCE.send(new EventRefreshOverview("LocalInsightPlugin::onStateChanged"))); + } + new Handler(Looper.getMainLooper()).post(() -> RxBus.INSTANCE.send(new EventLocalInsightUpdateGUI())); + } + + @Override + public void onPumpPaired() { + ConfigBuilderPlugin.getPlugin().getCommandQueue().readStatus("Pump paired", null); + } + + @Override + public void onTimeoutDuringHandshake() { + Notification notification = new Notification(Notification.INSIGHT_TIMEOUT_DURING_HANDSHAKE, MainApp.gs(R.string.timeout_during_handshake), Notification.URGENT); + new Handler(Looper.getMainLooper()).post(() -> RxBus.INSTANCE.send(new EventNewNotification(notification))); + } + + @Override + public boolean canHandleDST() { + return true; + } + + @Override + public void timeDateOrTimeZoneChanged() { + + } + +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/activities/InsightAlertActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/activities/InsightAlertActivity.java new file mode 100644 index 0000000000..77be3ab03a --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/activities/InsightAlertActivity.java @@ -0,0 +1,258 @@ +package info.nightscout.androidaps.plugins.pump.insight.activities; + +import android.content.ComponentName; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.Bundle; +import android.os.IBinder; +import android.text.Html; +import android.view.View; +import android.view.WindowManager; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.core.content.ContextCompat; + +import java.text.DecimalFormat; + +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.activities.NoSplashAppCompatActivity; +import info.nightscout.androidaps.plugins.pump.insight.InsightAlertService; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.Alert; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.AlertStatus; + +public class InsightAlertActivity extends NoSplashAppCompatActivity { + + private Alert alert; + private InsightAlertService alertService; + + private ImageView icon; + private TextView errorCode; + private TextView errorTitle; + private TextView errorDescription; + private Button mute; + private Button confirm; + + private ServiceConnection serviceConnection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName name, IBinder binder) { + alertService = ((InsightAlertService.LocalBinder) binder).getService(); + alertService.setAlertActivity(InsightAlertActivity.this); + alert = alertService.getAlert(); + if (alert == null) finish(); + else update(alert); + } + + @Override + public void onServiceDisconnected(ComponentName name) { + alertService = null; + } + }; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_insight_alert); + + bindService(new Intent(this, InsightAlertService.class), serviceConnection, BIND_AUTO_CREATE); + + icon = findViewById(R.id.icon); + errorCode = findViewById(R.id.error_code); + errorTitle = findViewById(R.id.error_title); + errorDescription = findViewById(R.id.error_description); + mute = findViewById(R.id.mute); + confirm = findViewById(R.id.confirm); + + setFinishOnTouchOutside(false); + + getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON + | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD + | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED + | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON); + WindowManager.LayoutParams layoutParams = getWindow().getAttributes(); + layoutParams.screenBrightness = 1.0F; + getWindow().setAttributes(layoutParams); + } + + @Override + protected void onDestroy() { + alertService.setAlertActivity(null); + unbindService(serviceConnection); + super.onDestroy(); + } + + public void update(Alert alert) { + this.alert = alert; + mute.setEnabled(true); + mute.setVisibility(alert.getAlertStatus() == AlertStatus.SNOOZED ? View.GONE : View.VISIBLE); + confirm.setEnabled(true); + int icon = 0; + int code = 0; + int title = 0; + String description = null; + switch (alert.getAlertCategory()) { + case ERROR: + icon = R.drawable.ic_error; + break; + case MAINTENANCE: + icon = R.drawable.ic_maintenance; + break; + case WARNING: + icon = R.drawable.ic_warning; + break; + case REMINDER: + icon = R.drawable.ic_reminder; + break; + } + DecimalFormat decimalFormat = new DecimalFormat("##0.00"); + int hours = alert.getTBRDuration() / 60; + int minutes = alert.getTBRDuration() - hours * 60; + switch (alert.getAlertType()) { + case REMINDER_01: + code = R.string.alert_r1_code; + title = R.string.alert_r1_title; + break; + case REMINDER_02: + code = R.string.alert_r2_code; + title = R.string.alert_r2_title; + break; + case REMINDER_03: + code = R.string.alert_r3_code; + title = R.string.alert_r3_title; + break; + case REMINDER_04: + code = R.string.alert_r4_code; + title = R.string.alert_r4_title; + break; + case REMINDER_07: + code = R.string.alert_r7_code; + title = R.string.alert_r7_title; + description = getString(R.string.alert_r7_description, alert.getTBRAmount(), new DecimalFormat("#0").format(hours) + ":" + new DecimalFormat("00").format(minutes)); + break; + case WARNING_31: + code = R.string.alert_w31_code; + title = R.string.alert_w31_title; + description = getString(R.string.alert_w31_description, decimalFormat.format(alert.getCartridgeAmount())); + break; + case WARNING_32: + code = R.string.alert_w32_code; + title = R.string.alert_w32_title; + description = getString(R.string.alert_w32_description); + break; + case WARNING_33: + code = R.string.alert_w33_code; + title = R.string.alert_w33_title; + description = getString(R.string.alert_w33_description); + break; + case WARNING_34: + code = R.string.alert_w34_code; + title = R.string.alert_w34_title; + description = getString(R.string.alert_w34_description); + break; + case WARNING_36: + code = R.string.alert_w36_code; + title = R.string.alert_w36_title; + description = getString(R.string.alert_w36_description, alert.getTBRAmount(), new DecimalFormat("#0").format(hours) + ":" + new DecimalFormat("00").format(minutes)); + break; + case WARNING_38: + code = R.string.alert_w38_code; + title = R.string.alert_w38_title; + description = getString(R.string.alert_w38_description, decimalFormat.format(alert.getProgrammedBolusAmount()), decimalFormat.format(alert.getDeliveredBolusAmount())); + break; + case WARNING_39: + code = R.string.alert_w39_code; + title = R.string.alert_w39_title; + break; + case MAINTENANCE_20: + code = R.string.alert_m20_code; + title = R.string.alert_m20_title; + description = getString(R.string.alert_m20_description); + break; + case MAINTENANCE_21: + code = R.string.alert_m21_code; + title = R.string.alert_m21_title; + description = getString(R.string.alert_m21_description); + break; + case MAINTENANCE_22: + code = R.string.alert_m22_code; + title = R.string.alert_m22_title; + description = getString(R.string.alert_m22_description); + break; + case MAINTENANCE_23: + code = R.string.alert_m23_code; + title = R.string.alert_m23_title; + description = getString(R.string.alert_m23_description); + break; + case MAINTENANCE_24: + code = R.string.alert_m24_code; + title = R.string.alert_m24_title; + description = getString(R.string.alert_m24_description); + break; + case MAINTENANCE_25: + code = R.string.alert_m25_code; + title = R.string.alert_m25_title; + description = getString(R.string.alert_m25_description); + break; + case MAINTENANCE_26: + code = R.string.alert_m26_code; + title = R.string.alert_m26_title; + description = getString(R.string.alert_m26_description); + break; + case MAINTENANCE_27: + code = R.string.alert_m27_code; + title = R.string.alert_m27_title; + description = getString(R.string.alert_m27_description); + break; + case MAINTENANCE_28: + code = R.string.alert_m28_code; + title = R.string.alert_m28_title; + description = getString(R.string.alert_m28_description); + break; + case MAINTENANCE_29: + code = R.string.alert_m29_code; + title = R.string.alert_m29_title; + description = getString(R.string.alert_m29_description); + break; + case MAINTENANCE_30: + code = R.string.alert_m30_code; + title = R.string.alert_m30_title; + description = getString(R.string.alert_m30_description); + break; + case ERROR_6: + code = R.string.alert_e6_code; + title = R.string.alert_e6_title; + description = getString(R.string.alert_e6_description); + break; + case ERROR_10: + code = R.string.alert_e10_code; + title = R.string.alert_e10_title; + description = getString(R.string.alert_e10_description); + break; + case ERROR_13: + code = R.string.alert_e13_code; + title = R.string.alert_e13_title; + description = getString(R.string.alert_e13_description); + break; + } + this.icon.setImageDrawable(ContextCompat.getDrawable(this, icon)); + this.errorCode.setText(code); + this.errorTitle.setText(title); + if (description == null) this.errorDescription.setVisibility(View.GONE); + else { + this.errorDescription.setVisibility(View.VISIBLE); + this.errorDescription.setText(Html.fromHtml(description)); + } + } + + public void muteClicked(View view) { + mute.setEnabled(false); + alertService.mute(); + } + + public void confirmClicked(View view) { + mute.setEnabled(false); + confirm.setEnabled(false); + alertService.confirm(); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/activities/InsightPairingActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/activities/InsightPairingActivity.java new file mode 100644 index 0000000000..71450aaa0c --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/activities/InsightPairingActivity.java @@ -0,0 +1,260 @@ +package info.nightscout.androidaps.plugins.pump.insight.activities; + +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothDevice; +import android.content.BroadcastReceiver; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.ServiceConnection; +import android.os.Bundle; +import android.os.IBinder; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import java.util.ArrayList; +import java.util.List; + +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.activities.NoSplashAppCompatActivity; +import info.nightscout.androidaps.plugins.pump.insight.connection_service.InsightConnectionService; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.InsightState; +import info.nightscout.androidaps.plugins.pump.insight.utils.ExceptionTranslator; + +public class InsightPairingActivity extends NoSplashAppCompatActivity implements InsightConnectionService.StateCallback, View.OnClickListener, InsightConnectionService.ExceptionCallback { + + private boolean scanning; + private LinearLayout deviceSearchSection; + private TextView pleaseWaitSection; + private LinearLayout codeCompareSection; + private LinearLayout pairingCompletedSection; + private Button yes; + private Button no; + private TextView code; + private Button exit; + private RecyclerView deviceList; + private DeviceAdapter deviceAdapter = new DeviceAdapter(); + + private InsightConnectionService service; + + private ServiceConnection serviceConnection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName name, IBinder binder) { + service = ((InsightConnectionService.LocalBinder) binder).getService(); + if (service.isPaired()) return; + else { + service.requestConnection(InsightPairingActivity.this); + service.registerStateCallback(InsightPairingActivity.this); + service.registerExceptionCallback(InsightPairingActivity.this); + onStateChanged(service.getState()); + } + } + + @Override + public void onServiceDisconnected(ComponentName name) { + + } + }; + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_insight_pairing); + + deviceSearchSection = findViewById(R.id.device_search_section); + pleaseWaitSection = findViewById(R.id.please_wait_section); + codeCompareSection = findViewById(R.id.code_compare_section); + pairingCompletedSection = findViewById(R.id.pairing_completed_section); + yes = findViewById(R.id.yes); + no = findViewById(R.id.no); + code = findViewById(R.id.code); + exit = findViewById(R.id.exit); + deviceList = findViewById(R.id.device_list); + + yes.setOnClickListener(this); + no.setOnClickListener(this); + exit.setOnClickListener(this); + + deviceList.setLayoutManager(new LinearLayoutManager(this)); + deviceList.setAdapter(deviceAdapter); + + + bindService(new Intent(this, InsightConnectionService.class), serviceConnection, BIND_AUTO_CREATE); +} + + @Override + protected void onDestroy() { + if (service != null) { + service.withdrawConnectionRequest(InsightPairingActivity.this); + service.unregisterStateCallback(InsightPairingActivity.this); + service.unregisterExceptionCallback(InsightPairingActivity.this); + } + unbindService(serviceConnection); + super.onDestroy(); + } + + @Override + protected void onStart() { + super.onStart(); + if (service != null && service.getState() == InsightState.NOT_PAIRED) startBLScan(); + } + + @Override + protected void onStop() { + stopBLScan(); + super.onStop(); + } + + @Override + public void onStateChanged(InsightState state) { + runOnUiThread(() -> { + switch (state) { + case NOT_PAIRED: + startBLScan(); + deviceSearchSection.setVisibility(View.VISIBLE); + pleaseWaitSection.setVisibility(View.GONE); + codeCompareSection.setVisibility(View.GONE); + pairingCompletedSection.setVisibility(View.GONE); + break; + case CONNECTING: + case SATL_CONNECTION_REQUEST: + case SATL_KEY_REQUEST: + case SATL_VERIFY_DISPLAY_REQUEST: + case SATL_VERIFY_CONFIRM_REQUEST: + case APP_BIND_MESSAGE: + stopBLScan(); + deviceSearchSection.setVisibility(View.GONE); + pleaseWaitSection.setVisibility(View.VISIBLE); + codeCompareSection.setVisibility(View.GONE); + pairingCompletedSection.setVisibility(View.GONE); + break; + case AWAITING_CODE_CONFIRMATION: + stopBLScan(); + deviceSearchSection.setVisibility(View.GONE); + pleaseWaitSection.setVisibility(View.GONE); + codeCompareSection.setVisibility(View.VISIBLE); + pairingCompletedSection.setVisibility(View.GONE); + code.setText(service.getVerificationString()); + break; + case DISCONNECTED: + case CONNECTED: + stopBLScan(); + deviceSearchSection.setVisibility(View.GONE); + pleaseWaitSection.setVisibility(View.GONE); + codeCompareSection.setVisibility(View.GONE); + pairingCompletedSection.setVisibility(View.VISIBLE); + break; + } + }); + } + + private void startBLScan() { + if (!scanning) { + BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); + if (bluetoothAdapter != null) { + if (!bluetoothAdapter.isEnabled()) bluetoothAdapter.enable(); + IntentFilter intentFilter = new IntentFilter(); + intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); + intentFilter.addAction(BluetoothDevice.ACTION_FOUND); + registerReceiver(broadcastReceiver, intentFilter); + bluetoothAdapter.startDiscovery(); + scanning = true; + } + } + } + + private void stopBLScan() { + if (scanning) { + unregisterReceiver(broadcastReceiver); + BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); + if (bluetoothAdapter != null) { + bluetoothAdapter.cancelDiscovery(); + } + scanning = false; + } + } + @Override + public void onClick(View v) { + if (v == exit) finish(); + else if (v == yes) service.confirmVerificationString(); + else if (v == no) service.rejectVerificationString(); + } + + @Override + public void onExceptionOccur(Exception e) { + ExceptionTranslator.makeToast(this, e); + } + + private void deviceSelected(BluetoothDevice device) { + service.pair(device.getAddress()); + } + + private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + if (action.equals(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)) + BluetoothAdapter.getDefaultAdapter().startDiscovery(); + else if (action.equals(BluetoothDevice.ACTION_FOUND)) { + BluetoothDevice bluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); + deviceAdapter.addDevice(bluetoothDevice); + } + } + }; + + private class DeviceAdapter extends RecyclerView.Adapter { + + private List bluetoothDevices = new ArrayList<>(); + + public void addDevice(BluetoothDevice bluetoothDevice) { + if (!bluetoothDevices.contains(bluetoothDevice)) { + bluetoothDevices.add(bluetoothDevice); + notifyDataSetChanged(); + } + } + + public void clear() { + bluetoothDevices.clear(); + notifyDataSetChanged(); + } + + @NonNull + @Override + public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.bluetooth_device, parent, false)); + } + + @Override + public void onBindViewHolder(@NonNull ViewHolder holder, int position) { + BluetoothDevice bluetoothDevice = bluetoothDevices.get(position); + holder.deviceName.setText(bluetoothDevice.getName() == null ? bluetoothDevice.getAddress() : bluetoothDevice.getName()); + holder.deviceName.setOnClickListener((v) -> deviceSelected(bluetoothDevice)); + } + + @Override + public int getItemCount() { + return bluetoothDevices.size(); + } + + public class ViewHolder extends RecyclerView.ViewHolder { + + private TextView deviceName; + + public ViewHolder(View itemView) { + super(itemView); + deviceName = (TextView) itemView; + } + } + + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/activities/InsightPairingInformationActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/activities/InsightPairingInformationActivity.java new file mode 100644 index 0000000000..e20fb2c94f --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/activities/InsightPairingInformationActivity.java @@ -0,0 +1,89 @@ +package info.nightscout.androidaps.plugins.pump.insight.activities; + +import android.content.ComponentName; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.Bundle; +import android.os.IBinder; +import android.view.View; +import android.widget.TextView; + +import androidx.annotation.Nullable; + +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.activities.NoSplashAppCompatActivity; +import info.nightscout.androidaps.plugins.pump.insight.connection_service.InsightConnectionService; + +public class InsightPairingInformationActivity extends NoSplashAppCompatActivity { + + private InsightConnectionService connectionService; + + private TextView serialNumber; + private TextView releaseSWVersion; + private TextView uiProcSWVersion; + private TextView pcProcSWVersion; + private TextView mdTelSWVersion; + private TextView safetyProcSWVersion; + private TextView btInfoPageVersion; + private TextView bluetoothAddress; + private TextView systemIdAppendix; + private TextView manufacturingDate; + + private ServiceConnection serviceConnection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName name, IBinder binder) { + connectionService = ((InsightConnectionService.LocalBinder) binder).getService(); + if (!connectionService.isPaired()) { + overridePendingTransition(0, 0); + finish(); + startActivity(new Intent(InsightPairingInformationActivity.this, InsightPairingActivity.class)); + } else { + serialNumber.setText(connectionService.getPumpSystemIdentification().getSerialNumber()); + manufacturingDate.setText(connectionService.getPumpSystemIdentification().getManufacturingDate()); + systemIdAppendix.setText(connectionService.getPumpSystemIdentification().getSystemIdAppendix() + ""); + releaseSWVersion.setText(connectionService.getPumpFirmwareVersions().getReleaseSWVersion()); + uiProcSWVersion.setText(connectionService.getPumpFirmwareVersions().getUiProcSWVersion()); + pcProcSWVersion.setText(connectionService.getPumpFirmwareVersions().getPcProcSWVersion()); + mdTelSWVersion.setText(connectionService.getPumpFirmwareVersions().getMdTelProcSWVersion()); + safetyProcSWVersion.setText(connectionService.getPumpFirmwareVersions().getSafetyProcSWVersion()); + btInfoPageVersion.setText(connectionService.getPumpFirmwareVersions().getBtInfoPageVersion()); + bluetoothAddress.setText(connectionService.getBluetoothAddress()); + } + } + + @Override + public void onServiceDisconnected(ComponentName name) { + connectionService = null; + } + }; + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_insight_pairing_information); + serialNumber = findViewById(R.id.serial_number); + releaseSWVersion = findViewById(R.id.release_sw_version); + uiProcSWVersion = findViewById(R.id.ui_proc_sw_version); + pcProcSWVersion = findViewById(R.id.pc_proc_sw_version); + mdTelSWVersion = findViewById(R.id.md_tel_sw_version); + safetyProcSWVersion = findViewById(R.id.safety_proc_sw_version); + btInfoPageVersion = findViewById(R.id.bt_info_page_version); + bluetoothAddress = findViewById(R.id.bluetooth_address); + systemIdAppendix = findViewById(R.id.system_id_appendix); + manufacturingDate = findViewById(R.id.manufacturing_date); + bindService(new Intent(this, InsightConnectionService.class), serviceConnection, BIND_AUTO_CREATE); + } + + @Override + protected void onDestroy() { + unbindService(serviceConnection); + super.onDestroy(); + } + + public void deletePairing(View view) { + if (connectionService != null) { + connectionService.reset(); + finish(); + } + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/AppLayerMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/AppLayerMessage.java new file mode 100644 index 0000000000..7783abe063 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/AppLayerMessage.java @@ -0,0 +1,91 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer; + +import info.nightscout.androidaps.plugins.pump.insight.descriptors.MessagePriority; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.IncompatibleAppVersionException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.InvalidAppCRCException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.UnknownAppCommandException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.UnknownServiceException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.AppLayerErrorException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.UnknownAppLayerErrorCodeException; +import info.nightscout.androidaps.plugins.pump.insight.ids.AppCommandIDs; +import info.nightscout.androidaps.plugins.pump.insight.ids.AppErrorIDs; +import info.nightscout.androidaps.plugins.pump.insight.ids.ServiceIDs; +import info.nightscout.androidaps.plugins.pump.insight.satl.DataMessage; +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; +import info.nightscout.androidaps.plugins.pump.insight.utils.crypto.Cryptograph; + +public class AppLayerMessage implements Comparable { + + private static final byte VERSION = 0x20; + + private final MessagePriority messagePriority; + private final boolean inCRC; + private final boolean outCRC; + private final Service service; + + public AppLayerMessage(MessagePriority messagePriority, boolean inCRC, boolean outCRC, Service service) { + this.messagePriority = messagePriority; + this.inCRC = inCRC; + this.outCRC = outCRC; + this.service = service; + } + + protected ByteBuf getData() { + return new ByteBuf(0); + } + + protected void parse(ByteBuf byteBuf) throws Exception { + + } + + public ByteBuf serialize(Class clazz) { + byte[] data = getData().getBytes(); + ByteBuf byteBuf = new ByteBuf(4 + data.length + (outCRC ? 2 : 0)); + byteBuf.putByte(VERSION); + byteBuf.putByte(ServiceIDs.IDS.getID(getService())); + byteBuf.putUInt16LE(AppCommandIDs.IDS.getID(clazz)); + byteBuf.putBytes(data); + if (outCRC) byteBuf.putUInt16LE(Cryptograph.calculateCRC(data)); + return byteBuf; + } + + public static AppLayerMessage deserialize(ByteBuf byteBuf) throws Exception { + byte version = byteBuf.readByte(); + byte service = byteBuf.readByte(); + int command = byteBuf.readUInt16LE(); + int error = byteBuf.readUInt16LE(); + Class clazz = AppCommandIDs.IDS.getType(command); + if (clazz == null) throw new UnknownAppCommandException(); + if (version != VERSION) throw new IncompatibleAppVersionException(); + AppLayerMessage message = clazz.newInstance(); + if (ServiceIDs.IDS.getType(service) == null) throw new UnknownServiceException(); + if (error != 0) { + Class exceptionClass = AppErrorIDs.IDS.getType(error); + if (exceptionClass == null) throw new UnknownAppLayerErrorCodeException(error); + else throw exceptionClass.getConstructor(int.class).newInstance(error); + } + byte[] data = byteBuf.readBytes(byteBuf.getSize() - (message.inCRC ? 2 : 0)); + if (message.inCRC && Cryptograph.calculateCRC(data) != byteBuf.readUInt16LE()) throw new InvalidAppCRCException(); + message.parse(ByteBuf.from(data)); + return message; + } + + public static DataMessage wrap(AppLayerMessage message) { + DataMessage dataMessage = new DataMessage(); + dataMessage.setData(message.serialize(message.getClass())); + return dataMessage; + } + + public static AppLayerMessage unwrap(DataMessage dataMessage) throws Exception { + return deserialize(dataMessage.getData()); + } + + @Override + public int compareTo(AppLayerMessage o) { + return messagePriority.compareTo(o.messagePriority); + } + + public Service getService() { + return this.service; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/ReadParameterBlockMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/ReadParameterBlockMessage.java new file mode 100644 index 0000000000..221cf80462 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/ReadParameterBlockMessage.java @@ -0,0 +1,48 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer; + +import info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks.ParameterBlock; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.MessagePriority; +import info.nightscout.androidaps.plugins.pump.insight.ids.ParameterBlockIDs; +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public class ReadParameterBlockMessage extends AppLayerMessage { + + private Class parameterBlockId; + private ParameterBlock parameterBlock; + private Service service; + + public ReadParameterBlockMessage() { + super(MessagePriority.NORMAL, true, false, null); + } + + @Override + public Service getService() { + return service; + } + + public void setService(Service service) { + this.service = service; + } + + @Override + protected ByteBuf getData() { + ByteBuf byteBuf = new ByteBuf(2); + byteBuf.putUInt16LE(ParameterBlockIDs.IDS.getID(parameterBlockId)); + return byteBuf; + } + + @Override + protected void parse(ByteBuf byteBuf) throws Exception { + parameterBlock = ParameterBlockIDs.IDS.getType(byteBuf.readUInt16LE()).newInstance(); + byteBuf.shift(2); //Restriction level + parameterBlock.parse(byteBuf); + } + + public ParameterBlock getParameterBlock() { + return this.parameterBlock; + } + + public void setParameterBlockId(Class configurationBlockId) { + this.parameterBlockId = configurationBlockId; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/Service.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/Service.java new file mode 100644 index 0000000000..aeec3150d3 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/Service.java @@ -0,0 +1,31 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer; + +public enum Service { + + CONNECTION((short) 0x0000, null), + STATUS((short) 0x0100, null), + HISTORY((short) 0x0200, null), + CONFIGURATION((short) 0x0200, "u+5Fhz6Gw4j1Kkas"), + PARAMETER((short) 0x0200, null), + REMOTE_CONTROL((short) 0x0100, "MAbcV2X6PVjxuz+R"); + + private short version; + private String servicePassword; + + Service(short version, String servicePassword) { + this.version = version; + this.servicePassword = servicePassword; + } + + public short getVersion() { + return this.version; + } + + public String getServicePassword() { + return this.servicePassword; + } + + public void setServicePassword(String servicePassword) { + this.servicePassword = servicePassword; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/configuration/CloseConfigurationWriteSessionMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/configuration/CloseConfigurationWriteSessionMessage.java new file mode 100644 index 0000000000..2e6133b79e --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/configuration/CloseConfigurationWriteSessionMessage.java @@ -0,0 +1,12 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.configuration; + +import info.nightscout.androidaps.plugins.pump.insight.app_layer.AppLayerMessage; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.MessagePriority; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.Service; + +public class CloseConfigurationWriteSessionMessage extends AppLayerMessage { + + public CloseConfigurationWriteSessionMessage() { + super(MessagePriority.NORMAL, false, false, Service.CONFIGURATION); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/configuration/OpenConfigurationWriteSessionMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/configuration/OpenConfigurationWriteSessionMessage.java new file mode 100644 index 0000000000..0706742559 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/configuration/OpenConfigurationWriteSessionMessage.java @@ -0,0 +1,12 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.configuration; + +import info.nightscout.androidaps.plugins.pump.insight.app_layer.AppLayerMessage; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.MessagePriority; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.Service; + +public class OpenConfigurationWriteSessionMessage extends AppLayerMessage { + + public OpenConfigurationWriteSessionMessage() { + super(MessagePriority.NORMAL, false, false, Service.CONFIGURATION); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/configuration/WriteConfigurationBlockMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/configuration/WriteConfigurationBlockMessage.java new file mode 100644 index 0000000000..a33530d48e --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/configuration/WriteConfigurationBlockMessage.java @@ -0,0 +1,41 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.configuration; + +import info.nightscout.androidaps.plugins.pump.insight.app_layer.AppLayerMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.Service; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks.ParameterBlock; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.MessagePriority; +import info.nightscout.androidaps.plugins.pump.insight.ids.ParameterBlockIDs; +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public class WriteConfigurationBlockMessage extends AppLayerMessage { + + private ParameterBlock parameterBlock; + private Class configurationBlockId; + + public WriteConfigurationBlockMessage() { + super(MessagePriority.NORMAL, false, true, Service.CONFIGURATION); + } + + @Override + protected ByteBuf getData() { + ByteBuf configBlockData = parameterBlock.getData(); + ByteBuf data = new ByteBuf(4 + configBlockData.getSize()); + data.putUInt16LE(ParameterBlockIDs.IDS.getID(parameterBlock.getClass())); + data.putUInt16LE(31); + data.putByteBuf(configBlockData); + return data; + } + + @Override + protected void parse(ByteBuf byteBuf) throws Exception { + configurationBlockId = ParameterBlockIDs.IDS.getType(byteBuf.readUInt16LE()); + } + + public Class getConfigurationBlockId() { + return this.configurationBlockId; + } + + public void setParameterBlock(ParameterBlock parameterBlock) { + this.parameterBlock = parameterBlock; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/connection/ActivateServiceMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/connection/ActivateServiceMessage.java new file mode 100644 index 0000000000..322864bffe --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/connection/ActivateServiceMessage.java @@ -0,0 +1,51 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.connection; + +import info.nightscout.androidaps.plugins.pump.insight.app_layer.AppLayerMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.Service; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.MessagePriority; +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public class ActivateServiceMessage extends AppLayerMessage { + + private byte serviceID; + private short version; + private byte[] servicePassword; + + public ActivateServiceMessage() { + super(MessagePriority.NORMAL, false, false, Service.CONNECTION); + } + + protected void parse(ByteBuf byteBuf) { + serviceID = byteBuf.readByte(); + version = byteBuf.readShort(); + } + + @Override + protected ByteBuf getData() { + ByteBuf byteBuf = new ByteBuf(19); + byteBuf.putByte(serviceID); + byteBuf.putShort(version); + byteBuf.putBytes(servicePassword); + return byteBuf; + } + + public byte getServiceID() { + return this.serviceID; + } + + public short getVersion() { + return this.version; + } + + public void setServiceID(byte serviceID) { + this.serviceID = serviceID; + } + + public void setVersion(short version) { + this.version = version; + } + + public void setServicePassword(byte[] servicePassword) { + this.servicePassword = servicePassword; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/connection/BindMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/connection/BindMessage.java new file mode 100644 index 0000000000..b636797464 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/connection/BindMessage.java @@ -0,0 +1,20 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.connection; + +import org.spongycastle.util.encoders.Hex; + +import info.nightscout.androidaps.plugins.pump.insight.app_layer.AppLayerMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.Service; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.MessagePriority; +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public class BindMessage extends AppLayerMessage { + + public BindMessage() { + super(MessagePriority.NORMAL, false, false, Service.CONNECTION); + } + + @Override + protected ByteBuf getData() { + return ByteBuf.from(Hex.decode("3438310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/connection/ConnectMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/connection/ConnectMessage.java new file mode 100644 index 0000000000..c56864209c --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/connection/ConnectMessage.java @@ -0,0 +1,20 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.connection; + +import org.spongycastle.util.encoders.Hex; + +import info.nightscout.androidaps.plugins.pump.insight.app_layer.AppLayerMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.Service; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.MessagePriority; +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public class ConnectMessage extends AppLayerMessage { + + public ConnectMessage() { + super(MessagePriority.NORMAL, false, false, Service.CONNECTION); + } + + @Override + protected ByteBuf getData() { + return ByteBuf.from(Hex.decode("0000080100196000")); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/connection/DisconnectMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/connection/DisconnectMessage.java new file mode 100644 index 0000000000..22ddbc7608 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/connection/DisconnectMessage.java @@ -0,0 +1,20 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.connection; + +import org.spongycastle.util.encoders.Hex; + +import info.nightscout.androidaps.plugins.pump.insight.app_layer.AppLayerMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.Service; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.MessagePriority; +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public class DisconnectMessage extends AppLayerMessage { + + public DisconnectMessage() { + super(MessagePriority.NORMAL, false, false, Service.CONNECTION); + } + + @Override + protected ByteBuf getData() { + return ByteBuf.from(Hex.decode("0360")); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/connection/ServiceChallengeMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/connection/ServiceChallengeMessage.java new file mode 100644 index 0000000000..07be4dd469 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/connection/ServiceChallengeMessage.java @@ -0,0 +1,42 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.connection; + +import info.nightscout.androidaps.plugins.pump.insight.app_layer.AppLayerMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.Service; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.MessagePriority; +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public class ServiceChallengeMessage extends AppLayerMessage { + + private byte serviceID; + private byte[] randomData; + private short version; + + public ServiceChallengeMessage() { + super(MessagePriority.NORMAL, false, false, Service.CONNECTION); + } + + @Override + protected void parse(ByteBuf byteBuf) { + randomData = byteBuf.getBytes(16); + } + + @Override + protected ByteBuf getData() { + ByteBuf byteBuf = new ByteBuf(3); + byteBuf.putByte(serviceID); + byteBuf.putShort(version); + return byteBuf; + } + + public byte[] getRandomData() { + return this.randomData; + } + + public void setServiceID(byte serviceID) { + this.serviceID = serviceID; + } + + public void setVersion(short version) { + this.version = version; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/HistoryReadingDirection.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/HistoryReadingDirection.java new file mode 100644 index 0000000000..1bf9a2d165 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/HistoryReadingDirection.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.history; + +public enum HistoryReadingDirection { + + FORWARD, + BACKWARD + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/ReadHistoryEventsMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/ReadHistoryEventsMessage.java new file mode 100644 index 0000000000..f4c8cb4557 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/ReadHistoryEventsMessage.java @@ -0,0 +1,34 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.history; + +import java.util.ArrayList; +import java.util.List; + +import info.nightscout.androidaps.plugins.pump.insight.app_layer.AppLayerMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.Service; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events.HistoryEvent; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.MessagePriority; +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public class ReadHistoryEventsMessage extends AppLayerMessage { + + private List historyEvents; + + public ReadHistoryEventsMessage() { + super(MessagePriority.NORMAL, true, false, Service.HISTORY); + } + + @Override + protected void parse(ByteBuf byteBuf) throws Exception { + historyEvents = new ArrayList<>(); + byteBuf.shift(2); + int frameCount = byteBuf.readUInt16LE(); + for (int i = 0; i < frameCount; i++) { + int length = byteBuf.readUInt16LE(); + historyEvents.add(HistoryEvent.deserialize(ByteBuf.from(byteBuf.readBytes(length)))); + } + } + + public List getHistoryEvents() { + return historyEvents; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/StartReadingHistoryMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/StartReadingHistoryMessage.java new file mode 100644 index 0000000000..9b8c2c6b16 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/StartReadingHistoryMessage.java @@ -0,0 +1,34 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.history; + +import info.nightscout.androidaps.plugins.pump.insight.app_layer.AppLayerMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.Service; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.MessagePriority; +import info.nightscout.androidaps.plugins.pump.insight.ids.HistoryReadingDirectionIDs; +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public class StartReadingHistoryMessage extends AppLayerMessage { + + private long offset; + private HistoryReadingDirection direction; + + public StartReadingHistoryMessage() { + super(MessagePriority.NORMAL, false, true, Service.HISTORY); + } + + @Override + protected ByteBuf getData() { + ByteBuf byteBuf = new ByteBuf(8); + byteBuf.putUInt16LE(31); + byteBuf.putUInt16LE(HistoryReadingDirectionIDs.IDS.getID(direction)); + byteBuf.putUInt32LE(offset); + return byteBuf; + } + + public void setOffset(long offset) { + this.offset = offset; + } + + public void setDirection(HistoryReadingDirection direction) { + this.direction = direction; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/StopReadingHistoryMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/StopReadingHistoryMessage.java new file mode 100644 index 0000000000..56749fcffe --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/StopReadingHistoryMessage.java @@ -0,0 +1,12 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.history; + +import info.nightscout.androidaps.plugins.pump.insight.app_layer.AppLayerMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.Service; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.MessagePriority; + +public class StopReadingHistoryMessage extends AppLayerMessage { + + public StopReadingHistoryMessage() { + super(MessagePriority.NORMAL, false, false, Service.HISTORY); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/BasalDeliveryChangedEvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/BasalDeliveryChangedEvent.java new file mode 100644 index 0000000000..1eb62c6c42 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/BasalDeliveryChangedEvent.java @@ -0,0 +1,23 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events; + +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public class BasalDeliveryChangedEvent extends HistoryEvent { + + private double oldBasalRate; + private double newBasalRate; + + @Override + public void parse(ByteBuf byteBuf) { + oldBasalRate = byteBuf.readUInt32Decimal1000(); + newBasalRate = byteBuf.readUInt32Decimal1000(); + } + + public double getOldBasalRate() { + return oldBasalRate; + } + + public double getNewBasalRate() { + return newBasalRate; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/BolusDeliveredEvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/BolusDeliveredEvent.java new file mode 100644 index 0000000000..05ba09ccf3 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/BolusDeliveredEvent.java @@ -0,0 +1,64 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events; + +import info.nightscout.androidaps.plugins.pump.insight.descriptors.BolusType; +import info.nightscout.androidaps.plugins.pump.insight.ids.BolusTypeIDs; +import info.nightscout.androidaps.plugins.pump.insight.utils.BOCUtil; +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public class BolusDeliveredEvent extends HistoryEvent { + + private BolusType bolusType; + private int startHour; + private int startMinute; + private int startSecond; + private double immediateAmount; + private double extendedAmount; + private int duration; + private int bolusID; + + @Override + public void parse(ByteBuf byteBuf) { + bolusType = BolusTypeIDs.IDS.getType(byteBuf.readUInt16LE()); + byteBuf.shift(1); + startHour = BOCUtil.parseBOC(byteBuf.readByte()); + startMinute = BOCUtil.parseBOC(byteBuf.readByte()); + startSecond = BOCUtil.parseBOC(byteBuf.readByte()); + immediateAmount = byteBuf.readUInt16Decimal(); + extendedAmount = byteBuf.readUInt16Decimal(); + duration = byteBuf.readUInt16LE(); + byteBuf.shift(2); + bolusID = byteBuf.readUInt16LE(); + } + + public BolusType getBolusType() { + return bolusType; + } + + public int getStartHour() { + return startHour; + } + + public int getStartMinute() { + return startMinute; + } + + public int getStartSecond() { + return startSecond; + } + + public double getImmediateAmount() { + return immediateAmount; + } + + public double getExtendedAmount() { + return extendedAmount; + } + + public int getDuration() { + return duration; + } + + public int getBolusID() { + return bolusID; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/BolusProgrammedEvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/BolusProgrammedEvent.java new file mode 100644 index 0000000000..0a456406d0 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/BolusProgrammedEvent.java @@ -0,0 +1,45 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events; + +import info.nightscout.androidaps.plugins.pump.insight.descriptors.BolusType; +import info.nightscout.androidaps.plugins.pump.insight.ids.BolusTypeIDs; +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public class BolusProgrammedEvent extends HistoryEvent { + + private BolusType bolusType; + private double immediateAmount; + private double extendedAmount; + private int duration; + private int bolusID; + + @Override + public void parse(ByteBuf byteBuf) { + bolusType = BolusTypeIDs.IDS.getType(byteBuf.readUInt16LE()); + immediateAmount = byteBuf.readUInt16Decimal(); + extendedAmount = byteBuf.readUInt16Decimal(); + duration = byteBuf.readUInt16LE(); + byteBuf.shift(4); + bolusID = byteBuf.readUInt16LE(); + } + + + public BolusType getBolusType() { + return bolusType; + } + + public double getImmediateAmount() { + return immediateAmount; + } + + public double getExtendedAmount() { + return extendedAmount; + } + + public int getDuration() { + return duration; + } + + public int getBolusID() { + return bolusID; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/CannulaFilledEvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/CannulaFilledEvent.java new file mode 100644 index 0000000000..4ee16e35e1 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/CannulaFilledEvent.java @@ -0,0 +1,17 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events; + +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public class CannulaFilledEvent extends HistoryEvent { + + private double amount; + + @Override + public void parse(ByteBuf byteBuf) { + amount = byteBuf.readUInt16Decimal(); + } + + public double getAmount() { + return amount; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/CartridgeInsertedEvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/CartridgeInsertedEvent.java new file mode 100644 index 0000000000..94ebcc442e --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/CartridgeInsertedEvent.java @@ -0,0 +1,4 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events; + +public class CartridgeInsertedEvent extends HistoryEvent { +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/CartridgeRemovedEvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/CartridgeRemovedEvent.java new file mode 100644 index 0000000000..f65d85b06e --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/CartridgeRemovedEvent.java @@ -0,0 +1,4 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events; + +public class CartridgeRemovedEvent extends HistoryEvent { +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/DateTimeChangedEvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/DateTimeChangedEvent.java new file mode 100644 index 0000000000..1397bb2529 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/DateTimeChangedEvent.java @@ -0,0 +1,49 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events; + +import info.nightscout.androidaps.plugins.pump.insight.utils.BOCUtil; +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public class DateTimeChangedEvent extends HistoryEvent { + + private int beforeYear; + private int beforeMonth; + private int beforeDay; + private int beforeHour; + private int beforeMinute; + private int beforeSecond; + + @Override + public void parse(ByteBuf byteBuf) { + beforeYear = BOCUtil.parseBOC(byteBuf.readByte()) * 100 + BOCUtil.parseBOC(byteBuf.readByte()); + beforeMonth = BOCUtil.parseBOC(byteBuf.readByte()); + beforeDay = BOCUtil.parseBOC(byteBuf.readByte()); + byteBuf.shift(1); + beforeHour = BOCUtil.parseBOC(byteBuf.readByte()); + beforeMinute = BOCUtil.parseBOC(byteBuf.readByte()); + beforeSecond = BOCUtil.parseBOC(byteBuf.readByte()); + } + + public int getBeforeYear() { + return beforeYear; + } + + public int getBeforeMonth() { + return beforeMonth; + } + + public int getBeforeDay() { + return beforeDay; + } + + public int getBeforeHour() { + return beforeHour; + } + + public int getBeforeMinute() { + return beforeMinute; + } + + public int getBeforeSecond() { + return beforeSecond; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/DefaultDateTimeSetEvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/DefaultDateTimeSetEvent.java new file mode 100644 index 0000000000..b3b468f09a --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/DefaultDateTimeSetEvent.java @@ -0,0 +1,4 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events; + +public class DefaultDateTimeSetEvent extends HistoryEvent { +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/EndOfTBREvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/EndOfTBREvent.java new file mode 100644 index 0000000000..2edbec2dd4 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/EndOfTBREvent.java @@ -0,0 +1,43 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events; + +import info.nightscout.androidaps.plugins.pump.insight.utils.BOCUtil; +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public class EndOfTBREvent extends HistoryEvent { + + private int startHour; + private int startMinute; + private int startSecond; + private int amount; + private int duration; + + @Override + public void parse(ByteBuf byteBuf) { + byteBuf.shift(1); + startHour = BOCUtil.parseBOC(byteBuf.readByte()); + startMinute = BOCUtil.parseBOC(byteBuf.readByte()); + startSecond = BOCUtil.parseBOC(byteBuf.readByte()); + amount = byteBuf.readUInt16LE(); + duration = byteBuf.readUInt16LE(); + } + + public int getStartHour() { + return startHour; + } + + public int getStartMinute() { + return startMinute; + } + + public int getStartSecond() { + return startSecond; + } + + public int getAmount() { + return amount; + } + + public int getDuration() { + return duration; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/HistoryEvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/HistoryEvent.java new file mode 100644 index 0000000000..874c908ca5 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/HistoryEvent.java @@ -0,0 +1,83 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events; + +import info.nightscout.androidaps.plugins.pump.insight.ids.HistoryEventIDs; +import info.nightscout.androidaps.plugins.pump.insight.utils.BOCUtil; +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public class HistoryEvent implements Comparable { + + private int eventYear; + private int eventMonth; + private int eventDay; + private int eventHour; + private int eventMinute; + private int eventSecond; + private long eventPosition; + + public static HistoryEvent deserialize(ByteBuf byteBuf) { + int eventID = byteBuf.readUInt16LE(); + Class eventClass = HistoryEventIDs.IDS.getType(eventID); + HistoryEvent event = null; + if (eventClass == null) event = new HistoryEvent(); + else { + try { + event = eventClass.newInstance(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (InstantiationException e) { + e.printStackTrace(); + } + } + event.parseHeader(byteBuf); + event.parse(byteBuf); + return event; + } + + public final void parseHeader(ByteBuf byteBuf) { + eventYear = BOCUtil.parseBOC(byteBuf.readByte()) * 100 + BOCUtil.parseBOC(byteBuf.readByte()); + eventMonth = BOCUtil.parseBOC(byteBuf.readByte()); + eventDay = BOCUtil.parseBOC(byteBuf.readByte()); + byteBuf.shift(1); + eventHour = BOCUtil.parseBOC(byteBuf.readByte()); + eventMinute = BOCUtil.parseBOC(byteBuf.readByte()); + eventSecond = BOCUtil.parseBOC(byteBuf.readByte()); + eventPosition = byteBuf.readUInt32LE(); + } + + public void parse(ByteBuf byteBuf) { + + } + + public int getEventYear() { + return eventYear; + } + + public int getEventMonth() { + return eventMonth; + } + + public int getEventDay() { + return eventDay; + } + + public int getEventHour() { + return eventHour; + } + + public int getEventMinute() { + return eventMinute; + } + + public int getEventSecond() { + return eventSecond; + } + + public long getEventPosition() { + return eventPosition; + } + + @Override + public int compareTo(HistoryEvent historyEvent) { + return (int) (eventPosition - historyEvent.eventPosition); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/OccurrenceOfAlertEvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/OccurrenceOfAlertEvent.java new file mode 100644 index 0000000000..e6edc8c95c --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/OccurrenceOfAlertEvent.java @@ -0,0 +1,25 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events; + +import info.nightscout.androidaps.plugins.pump.insight.descriptors.AlertType; +import info.nightscout.androidaps.plugins.pump.insight.ids.AlertTypeIncrementalIDs; +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public abstract class OccurrenceOfAlertEvent extends HistoryEvent { + + private AlertType alertType; + private int alertID; + + @Override + public void parse(ByteBuf byteBuf) { + alertType = AlertTypeIncrementalIDs.IDS.getType(byteBuf.readUInt16LE()); + alertID = byteBuf.readUInt16LE(); + } + + public AlertType getAlertType() { + return alertType; + } + + public int getAlertID() { + return alertID; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/OccurrenceOfErrorEvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/OccurrenceOfErrorEvent.java new file mode 100644 index 0000000000..7d6c61e9c2 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/OccurrenceOfErrorEvent.java @@ -0,0 +1,4 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events; + +public class OccurrenceOfErrorEvent extends OccurrenceOfAlertEvent { +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/OccurrenceOfMaintenanceEvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/OccurrenceOfMaintenanceEvent.java new file mode 100644 index 0000000000..6884797250 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/OccurrenceOfMaintenanceEvent.java @@ -0,0 +1,4 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events; + +public class OccurrenceOfMaintenanceEvent extends OccurrenceOfAlertEvent { +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/OccurrenceOfWarningEvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/OccurrenceOfWarningEvent.java new file mode 100644 index 0000000000..b504e4e09a --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/OccurrenceOfWarningEvent.java @@ -0,0 +1,4 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events; + +public class OccurrenceOfWarningEvent extends OccurrenceOfAlertEvent { +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/OperatingModeChangedEvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/OperatingModeChangedEvent.java new file mode 100644 index 0000000000..067b46e51f --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/OperatingModeChangedEvent.java @@ -0,0 +1,26 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events; + +import info.nightscout.androidaps.plugins.pump.insight.descriptors.OperatingMode; +import info.nightscout.androidaps.plugins.pump.insight.ids.OperatingModeIDs; +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public class OperatingModeChangedEvent extends HistoryEvent { + + private OperatingMode oldValue; + private OperatingMode newValue; + + @Override + public void parse(ByteBuf byteBuf) { + oldValue = OperatingModeIDs.IDS.getType(byteBuf.readUInt16LE()); + newValue = OperatingModeIDs.IDS.getType(byteBuf.readUInt16LE()); + } + + + public OperatingMode getOldValue() { + return oldValue; + } + + public OperatingMode getNewValue() { + return newValue; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/PowerDownEvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/PowerDownEvent.java new file mode 100644 index 0000000000..ff73ce0383 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/PowerDownEvent.java @@ -0,0 +1,4 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events; + +public class PowerDownEvent extends HistoryEvent { +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/PowerUpEvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/PowerUpEvent.java new file mode 100644 index 0000000000..d31690e9e9 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/PowerUpEvent.java @@ -0,0 +1,4 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events; + +public class PowerUpEvent extends HistoryEvent { +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/SniffingDoneEvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/SniffingDoneEvent.java new file mode 100644 index 0000000000..4afe3c72ba --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/SniffingDoneEvent.java @@ -0,0 +1,18 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events; + + +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public class SniffingDoneEvent extends HistoryEvent { + + private double amount; + + @Override + public void parse(ByteBuf byteBuf) { + amount = byteBuf.readUInt16Decimal(); + } + + public double getAmount() { + return amount; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/StartOfTBREvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/StartOfTBREvent.java new file mode 100644 index 0000000000..99795ed12c --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/StartOfTBREvent.java @@ -0,0 +1,23 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events; + +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public class StartOfTBREvent extends HistoryEvent { + + private int amount; + private int duration; + + @Override + public void parse(ByteBuf byteBuf) { + amount = byteBuf.readUInt16LE(); + duration = byteBuf.readUInt16LE(); + } + + public int getAmount() { + return amount; + } + + public int getDuration() { + return duration; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/TotalDailyDoseEvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/TotalDailyDoseEvent.java new file mode 100644 index 0000000000..c7f52ce1ef --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/TotalDailyDoseEvent.java @@ -0,0 +1,42 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events; + +import info.nightscout.androidaps.plugins.pump.insight.utils.BOCUtil; +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public class TotalDailyDoseEvent extends HistoryEvent { + + private double basalTotal; + private double bolusTotal; + private int totalYear; + private int totalMonth; + private int totalDay; + + @Override + public void parse(ByteBuf byteBuf) { + basalTotal = byteBuf.readUInt32Decimal100(); + bolusTotal = byteBuf.readUInt32Decimal100(); + totalYear = BOCUtil.parseBOC(byteBuf.readByte()) * 100 + BOCUtil.parseBOC(byteBuf.readByte()); + totalMonth = BOCUtil.parseBOC(byteBuf.readByte()); + totalDay = BOCUtil.parseBOC(byteBuf.readByte()); + } + + public double getBasalTotal() { + return basalTotal; + } + + public double getBolusTotal() { + return bolusTotal; + } + + public int getTotalYear() { + return totalYear; + } + + public int getTotalMonth() { + return totalMonth; + } + + public int getTotalDay() { + return totalDay; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/TubeFilledEvent.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/TubeFilledEvent.java new file mode 100644 index 0000000000..58a1851936 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/history/history_events/TubeFilledEvent.java @@ -0,0 +1,17 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events; + +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public class TubeFilledEvent extends HistoryEvent { + + private double amount; + + @Override + public void parse(ByteBuf byteBuf) { + amount = byteBuf.readUInt16Decimal(); + } + + public double getAmount() { + return amount; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/ActiveBRProfileBlock.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/ActiveBRProfileBlock.java new file mode 100644 index 0000000000..1d5630ea94 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/ActiveBRProfileBlock.java @@ -0,0 +1,30 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks; + +import info.nightscout.androidaps.plugins.pump.insight.descriptors.BasalProfile; +import info.nightscout.androidaps.plugins.pump.insight.ids.ActiveBasalProfileIDs; +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public class ActiveBRProfileBlock extends ParameterBlock { + + private BasalProfile activeBasalProfile; + + @Override + public void parse(ByteBuf byteBuf) { + activeBasalProfile = ActiveBasalProfileIDs.IDS.getType(byteBuf.readUInt16LE()); + } + + @Override + public ByteBuf getData() { + ByteBuf byteBuf = new ByteBuf(2); + byteBuf.putUInt16LE(ActiveBasalProfileIDs.IDS.getID(activeBasalProfile)); + return byteBuf; + } + + public BasalProfile getActiveBasalProfile() { + return activeBasalProfile; + } + + public void setActiveBasalProfile(BasalProfile activeBasalProfile) { + this.activeBasalProfile = activeBasalProfile; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/BRProfile1Block.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/BRProfile1Block.java new file mode 100644 index 0000000000..5f6be32181 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/BRProfile1Block.java @@ -0,0 +1,4 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks; + +public class BRProfile1Block extends BRProfileBlock { +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/BRProfile1NameBlock.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/BRProfile1NameBlock.java new file mode 100644 index 0000000000..1135eac5ac --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/BRProfile1NameBlock.java @@ -0,0 +1,4 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks; + +public class BRProfile1NameBlock extends NameBlock { +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/BRProfile2Block.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/BRProfile2Block.java new file mode 100644 index 0000000000..0b961458f2 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/BRProfile2Block.java @@ -0,0 +1,4 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks; + +public class BRProfile2Block extends BRProfileBlock { +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/BRProfile2NameBlock.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/BRProfile2NameBlock.java new file mode 100644 index 0000000000..591dd4d08c --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/BRProfile2NameBlock.java @@ -0,0 +1,4 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks; + +public class BRProfile2NameBlock extends NameBlock { +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/BRProfile3Block.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/BRProfile3Block.java new file mode 100644 index 0000000000..31e0ac0409 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/BRProfile3Block.java @@ -0,0 +1,4 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks; + +public class BRProfile3Block extends BRProfileBlock { +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/BRProfile3NameBlock.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/BRProfile3NameBlock.java new file mode 100644 index 0000000000..390e3be0dc --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/BRProfile3NameBlock.java @@ -0,0 +1,4 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks; + +public class BRProfile3NameBlock extends NameBlock { +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/BRProfile4Block.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/BRProfile4Block.java new file mode 100644 index 0000000000..06eaeb943c --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/BRProfile4Block.java @@ -0,0 +1,4 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks; + +public class BRProfile4Block extends BRProfileBlock { +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/BRProfile4NameBlock.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/BRProfile4NameBlock.java new file mode 100644 index 0000000000..5e2a5eb811 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/BRProfile4NameBlock.java @@ -0,0 +1,4 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks; + +public class BRProfile4NameBlock extends NameBlock { +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/BRProfile5Block.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/BRProfile5Block.java new file mode 100644 index 0000000000..738ea270f1 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/BRProfile5Block.java @@ -0,0 +1,4 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks; + +public class BRProfile5Block extends BRProfileBlock { +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/BRProfile5NameBlock.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/BRProfile5NameBlock.java new file mode 100644 index 0000000000..1ff159aeb2 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/BRProfile5NameBlock.java @@ -0,0 +1,4 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks; + +public class BRProfile5NameBlock extends NameBlock { +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/BRProfileBlock.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/BRProfileBlock.java new file mode 100644 index 0000000000..c6b4a515a1 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/BRProfileBlock.java @@ -0,0 +1,50 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import info.nightscout.androidaps.plugins.pump.insight.descriptors.BasalProfileBlock; +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public abstract class BRProfileBlock extends ParameterBlock { + + private List profileBlocks; + + @Override + public void parse(ByteBuf byteBuf) { + profileBlocks = new ArrayList<>(); + for (int i = 0; i < 24; i++) { + BasalProfileBlock basalProfileBlock = new BasalProfileBlock(); + basalProfileBlock.setDuration(byteBuf.readUInt16LE()); + profileBlocks.add(basalProfileBlock); + } + for (int i = 0; i < 24; i++) profileBlocks.get(i).setBasalAmount(byteBuf.readUInt16Decimal()); + Iterator iterator = profileBlocks.iterator(); + while (iterator.hasNext()) + if (iterator.next().getDuration() == 0) + iterator.remove(); + } + + @Override + public ByteBuf getData() { + ByteBuf byteBuf = new ByteBuf(96); + for (int i = 0; i < 24; i++) { + if (profileBlocks.size() > i) byteBuf.putUInt16LE(profileBlocks.get(i).getDuration()); + else byteBuf.putUInt16LE(0); + } + for (int i = 0; i < 24; i++) { + if (profileBlocks.size() > i) byteBuf.putUInt16Decimal(profileBlocks.get(i).getBasalAmount()); + else byteBuf.putUInt16Decimal(0); + } + return byteBuf; + } + + public List getProfileBlocks() { + return profileBlocks; + } + + public void setProfileBlocks(List profileBlocks) { + this.profileBlocks = profileBlocks; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/FactoryMaxBasalAmountBlock.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/FactoryMaxBasalAmountBlock.java new file mode 100644 index 0000000000..9db116edaf --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/FactoryMaxBasalAmountBlock.java @@ -0,0 +1,4 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks; + +public class FactoryMaxBasalAmountBlock extends InsulinAmountLimitationBlock { +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/FactoryMaxBolusAmountBlock.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/FactoryMaxBolusAmountBlock.java new file mode 100644 index 0000000000..9df9cf4dff --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/FactoryMaxBolusAmountBlock.java @@ -0,0 +1,4 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks; + +public class FactoryMaxBolusAmountBlock extends InsulinAmountLimitationBlock { +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/FactoryMinBasalAmountBlock.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/FactoryMinBasalAmountBlock.java new file mode 100644 index 0000000000..70cd39c07b --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/FactoryMinBasalAmountBlock.java @@ -0,0 +1,4 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks; + +public class FactoryMinBasalAmountBlock extends InsulinAmountLimitationBlock { +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/FactoryMinBolusAmountBlock.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/FactoryMinBolusAmountBlock.java new file mode 100644 index 0000000000..46ae394834 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/FactoryMinBolusAmountBlock.java @@ -0,0 +1,4 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks; + +public class FactoryMinBolusAmountBlock extends InsulinAmountLimitationBlock { +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/InsulinAmountLimitationBlock.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/InsulinAmountLimitationBlock.java new file mode 100644 index 0000000000..a753a62567 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/InsulinAmountLimitationBlock.java @@ -0,0 +1,28 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks; + +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public abstract class InsulinAmountLimitationBlock extends ParameterBlock { + + private double amountLimitation; + + @Override + public void parse(ByteBuf byteBuf) { + amountLimitation = byteBuf.readUInt16Decimal(); + } + + @Override + public ByteBuf getData() { + ByteBuf byteBuf = new ByteBuf(2); + byteBuf.putUInt16Decimal(amountLimitation); + return byteBuf; + } + + public double getAmountLimitation() { + return this.amountLimitation; + } + + public void setAmountLimitation(double amountLimitation) { + this.amountLimitation = amountLimitation; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/MaxBasalAmountBlock.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/MaxBasalAmountBlock.java new file mode 100644 index 0000000000..d09b4681c0 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/MaxBasalAmountBlock.java @@ -0,0 +1,4 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks; + +public class MaxBasalAmountBlock extends InsulinAmountLimitationBlock { +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/MaxBolusAmountBlock.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/MaxBolusAmountBlock.java new file mode 100644 index 0000000000..d53fe5e742 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/MaxBolusAmountBlock.java @@ -0,0 +1,4 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks; + +public class MaxBolusAmountBlock extends InsulinAmountLimitationBlock { +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/NameBlock.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/NameBlock.java new file mode 100644 index 0000000000..d4cf2060cb --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/NameBlock.java @@ -0,0 +1,28 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks; + +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public abstract class NameBlock extends ParameterBlock { + + private String name; + + @Override + public void parse(ByteBuf byteBuf) { + name = byteBuf.readUTF16(40); + } + + @Override + public ByteBuf getData() { + ByteBuf byteBuf = new ByteBuf(42); + byteBuf.putUTF16(name, 40); + return byteBuf; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/ParameterBlock.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/ParameterBlock.java new file mode 100644 index 0000000000..6ed2ca15c1 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/ParameterBlock.java @@ -0,0 +1,10 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks; + +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public abstract class ParameterBlock { + + public abstract void parse(ByteBuf byteBuf); + public abstract ByteBuf getData(); + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/SystemIdentificationBlock.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/SystemIdentificationBlock.java new file mode 100644 index 0000000000..e4e5d10c70 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/SystemIdentificationBlock.java @@ -0,0 +1,26 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks; + +import info.nightscout.androidaps.plugins.pump.insight.descriptors.SystemIdentification; +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public class SystemIdentificationBlock extends ParameterBlock { + + private SystemIdentification systemIdentification; + + @Override + public void parse(ByteBuf byteBuf) { + systemIdentification = new SystemIdentification(); + systemIdentification.setSerialNumber(byteBuf.readUTF16(18)); + systemIdentification.setSystemIdAppendix(byteBuf.readUInt32LE()); + systemIdentification.setManufacturingDate(byteBuf.readUTF16(22)); + } + + @Override + public ByteBuf getData() { + return null; + } + + public SystemIdentification getSystemIdentification() { + return systemIdentification; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/TBROverNotificationBlock.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/TBROverNotificationBlock.java new file mode 100644 index 0000000000..aec41ded44 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/parameter_blocks/TBROverNotificationBlock.java @@ -0,0 +1,31 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks; + +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public class TBROverNotificationBlock extends ParameterBlock { + + private boolean enabled; + private int melody; + + @Override + public void parse(ByteBuf byteBuf) { + enabled = byteBuf.readBoolean(); + melody = byteBuf.readUInt16LE(); + } + + @Override + public ByteBuf getData() { + ByteBuf byteBuf = new ByteBuf(4); + byteBuf.putBoolean(enabled); + byteBuf.putUInt16LE(melody); + return byteBuf; + } + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/remote_control/CancelBolusMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/remote_control/CancelBolusMessage.java new file mode 100644 index 0000000000..559d5dfcbd --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/remote_control/CancelBolusMessage.java @@ -0,0 +1,26 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.remote_control; + +import info.nightscout.androidaps.plugins.pump.insight.app_layer.AppLayerMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.Service; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.MessagePriority; +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public class CancelBolusMessage extends AppLayerMessage { + + private int bolusID; + + public CancelBolusMessage() { + super(MessagePriority.HIGHEST, false, true, Service.REMOTE_CONTROL); + } + + @Override + protected ByteBuf getData() { + ByteBuf byteBuf = new ByteBuf(2); + byteBuf.putUInt16LE(bolusID); + return byteBuf; + } + + public void setBolusID(int bolusID) { + this.bolusID = bolusID; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/remote_control/CancelTBRMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/remote_control/CancelTBRMessage.java new file mode 100644 index 0000000000..09b1762d2f --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/remote_control/CancelTBRMessage.java @@ -0,0 +1,11 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.remote_control; + +import info.nightscout.androidaps.plugins.pump.insight.app_layer.AppLayerMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.Service; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.MessagePriority; + +public class CancelTBRMessage extends AppLayerMessage { + public CancelTBRMessage() { + super(MessagePriority.HIGHER, false, false, Service.REMOTE_CONTROL); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/remote_control/ChangeTBRMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/remote_control/ChangeTBRMessage.java new file mode 100644 index 0000000000..f9ea0b9d2f --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/remote_control/ChangeTBRMessage.java @@ -0,0 +1,33 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.remote_control; + +import info.nightscout.androidaps.plugins.pump.insight.app_layer.AppLayerMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.Service; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.MessagePriority; +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public class ChangeTBRMessage extends AppLayerMessage { + + private int percentage; + private int duration; + + public ChangeTBRMessage() { + super(MessagePriority.NORMAL, false, true, Service.REMOTE_CONTROL); + } + + @Override + protected ByteBuf getData() { + ByteBuf byteBuf = new ByteBuf(6); + byteBuf.putUInt16LE(percentage); + byteBuf.putUInt16LE(duration); + byteBuf.putUInt16LE(31); + return byteBuf; + } + + public void setPercentage(int percentage) { + this.percentage = percentage; + } + + public void setDuration(int duration) { + this.duration = duration; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/remote_control/ConfirmAlertMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/remote_control/ConfirmAlertMessage.java new file mode 100644 index 0000000000..1d8e905c1c --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/remote_control/ConfirmAlertMessage.java @@ -0,0 +1,26 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.remote_control; + +import info.nightscout.androidaps.plugins.pump.insight.app_layer.AppLayerMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.Service; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.MessagePriority; +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public class ConfirmAlertMessage extends AppLayerMessage { + + private int alertID; + + public ConfirmAlertMessage() { + super(MessagePriority.NORMAL, false, true, Service.REMOTE_CONTROL); + } + + @Override + protected ByteBuf getData() { + ByteBuf byteBuf = new ByteBuf(2); + byteBuf.putUInt16LE(alertID); + return byteBuf; + } + + public void setAlertID(int alertID) { + this.alertID = alertID; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/remote_control/DeliverBolusMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/remote_control/DeliverBolusMessage.java new file mode 100644 index 0000000000..f1b4c3f6de --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/remote_control/DeliverBolusMessage.java @@ -0,0 +1,63 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.remote_control; + +import info.nightscout.androidaps.plugins.pump.insight.app_layer.AppLayerMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.Service; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.BolusType; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.MessagePriority; +import info.nightscout.androidaps.plugins.pump.insight.ids.BolusTypeIDs; +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public class DeliverBolusMessage extends AppLayerMessage { + + private BolusType bolusType; + private double immediateAmount; + private double extendedAmount; + private int duration; + private int bolusId; + + public DeliverBolusMessage() { + super(MessagePriority.NORMAL, true, true, Service.REMOTE_CONTROL); + } + + @Override + protected ByteBuf getData() { + ByteBuf byteBuf = new ByteBuf(22); + byteBuf.putUInt16LE(805); + byteBuf.putUInt16LE(BolusTypeIDs.IDS.getID(bolusType)); + byteBuf.putUInt16LE(31); + byteBuf.putUInt16LE(0); + byteBuf.putUInt16Decimal(immediateAmount); + byteBuf.putUInt16Decimal(extendedAmount); + byteBuf.putUInt16LE(duration); + byteBuf.putUInt16LE(0); + byteBuf.putUInt16Decimal(immediateAmount); + byteBuf.putUInt16Decimal(extendedAmount); + byteBuf.putUInt16LE(duration); + return byteBuf; + } + + @Override + protected void parse(ByteBuf byteBuf) throws Exception { + bolusId = byteBuf.readUInt16LE(); + } + + public void setBolusType(BolusType bolusType) { + this.bolusType = bolusType; + } + + public void setImmediateAmount(double immediateAmount) { + this.immediateAmount = immediateAmount; + } + + public void setExtendedAmount(double extendedAmount) { + this.extendedAmount = extendedAmount; + } + + public void setDuration(int duration) { + this.duration = duration; + } + + public int getBolusId() { + return bolusId; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/remote_control/GetAvailableBolusTypesMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/remote_control/GetAvailableBolusTypesMessage.java new file mode 100644 index 0000000000..965d0bd3fd --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/remote_control/GetAvailableBolusTypesMessage.java @@ -0,0 +1,28 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.remote_control; + +import info.nightscout.androidaps.plugins.pump.insight.app_layer.AppLayerMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.Service; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.AvailableBolusTypes; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.MessagePriority; +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public class GetAvailableBolusTypesMessage extends AppLayerMessage { + + private AvailableBolusTypes availableBolusTypes; + + public GetAvailableBolusTypesMessage() { + super(MessagePriority.NORMAL, false, false, Service.REMOTE_CONTROL); + } + + @Override + protected void parse(ByteBuf byteBuf) throws Exception { + availableBolusTypes = new AvailableBolusTypes(); + availableBolusTypes.setStandardAvailable(byteBuf.readBoolean()); + availableBolusTypes.setExtendedAvailable(byteBuf.readBoolean()); + availableBolusTypes.setMultiwaveAvailable(byteBuf.readBoolean()); + } + + public AvailableBolusTypes getAvailableBolusTypes() { + return this.availableBolusTypes; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/remote_control/SetDateTimeMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/remote_control/SetDateTimeMessage.java new file mode 100644 index 0000000000..5fe99f2bdf --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/remote_control/SetDateTimeMessage.java @@ -0,0 +1,32 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.remote_control; + +import info.nightscout.androidaps.plugins.pump.insight.app_layer.AppLayerMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.Service; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.MessagePriority; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.PumpTime; +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public class SetDateTimeMessage extends AppLayerMessage { + + private PumpTime pumpTime; + + public SetDateTimeMessage() { + super(MessagePriority.NORMAL, false, true, Service.CONFIGURATION); + } + + @Override + protected ByteBuf getData() { + ByteBuf byteBuf = new ByteBuf(7); + byteBuf.putUInt16LE(pumpTime.getYear()); + byteBuf.putUInt8((short) pumpTime.getMonth()); + byteBuf.putUInt8((short) pumpTime.getDay()); + byteBuf.putUInt8((short) pumpTime.getHour()); + byteBuf.putUInt8((short) pumpTime.getMinute()); + byteBuf.putUInt8((short) pumpTime.getSecond()); + return byteBuf; + } + + public void setPumpTime(PumpTime pumpTime) { + this.pumpTime = pumpTime; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/remote_control/SetOperatingModeMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/remote_control/SetOperatingModeMessage.java new file mode 100644 index 0000000000..41dff43ed4 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/remote_control/SetOperatingModeMessage.java @@ -0,0 +1,28 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.remote_control; + +import info.nightscout.androidaps.plugins.pump.insight.app_layer.AppLayerMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.Service; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.MessagePriority; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.OperatingMode; +import info.nightscout.androidaps.plugins.pump.insight.ids.OperatingModeIDs; +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public class SetOperatingModeMessage extends AppLayerMessage { + + private OperatingMode operatingMode; + + public SetOperatingModeMessage() { + super(MessagePriority.HIGHEST, false, true, Service.REMOTE_CONTROL); + } + + @Override + protected ByteBuf getData() { + ByteBuf byteBuf = new ByteBuf(2); + byteBuf.putUInt16LE(OperatingModeIDs.IDS.getID(operatingMode)); + return byteBuf; + } + + public void setOperatingMode(OperatingMode operatingMode) { + this.operatingMode = operatingMode; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/remote_control/SetTBRMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/remote_control/SetTBRMessage.java new file mode 100644 index 0000000000..0bdff3295d --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/remote_control/SetTBRMessage.java @@ -0,0 +1,33 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.remote_control; + +import info.nightscout.androidaps.plugins.pump.insight.app_layer.AppLayerMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.Service; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.MessagePriority; +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public class SetTBRMessage extends AppLayerMessage { + + private int percentage; + private int duration; + + public SetTBRMessage() { + super(MessagePriority.NORMAL, false, true, Service.REMOTE_CONTROL); + } + + @Override + protected ByteBuf getData() { + ByteBuf byteBuf = new ByteBuf(6); + byteBuf.putUInt16LE(percentage); + byteBuf.putUInt16LE(duration); + byteBuf.putUInt16LE(31); + return byteBuf; + } + + public void setPercentage(int percentage) { + this.percentage = percentage; + } + + public void setDuration(int duration) { + this.duration = duration; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/remote_control/SnoozeAlertMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/remote_control/SnoozeAlertMessage.java new file mode 100644 index 0000000000..139ea7e82b --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/remote_control/SnoozeAlertMessage.java @@ -0,0 +1,26 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.remote_control; + +import info.nightscout.androidaps.plugins.pump.insight.app_layer.AppLayerMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.Service; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.MessagePriority; +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public class SnoozeAlertMessage extends AppLayerMessage { + + private int alertID; + + public SnoozeAlertMessage() { + super(MessagePriority.NORMAL, false, true, Service.REMOTE_CONTROL); + } + + @Override + protected ByteBuf getData() { + ByteBuf byteBuf = new ByteBuf(2); + byteBuf.putUInt16LE(alertID); + return byteBuf; + } + + public void setAlertID(int alertID) { + this.alertID = alertID; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/status/GetActiveAlertMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/status/GetActiveAlertMessage.java new file mode 100644 index 0000000000..899ba182e8 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/status/GetActiveAlertMessage.java @@ -0,0 +1,54 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.status; + +import info.nightscout.androidaps.plugins.pump.insight.app_layer.AppLayerMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.Service; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.Alert; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.MessagePriority; +import info.nightscout.androidaps.plugins.pump.insight.ids.AlertCategoryIDs; +import info.nightscout.androidaps.plugins.pump.insight.ids.AlertStatusIDs; +import info.nightscout.androidaps.plugins.pump.insight.ids.AlertTypeIDs; +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public class GetActiveAlertMessage extends AppLayerMessage { + + private Alert alert; + + public GetActiveAlertMessage() { + super(MessagePriority.NORMAL, true, false, Service.STATUS); + } + + @Override + protected void parse(ByteBuf byteBuf) { + Alert alert = new Alert(); + alert.setAlertId(byteBuf.readUInt16LE()); + alert.setAlertCategory(AlertCategoryIDs.IDS.getType(byteBuf.readUInt16LE())); + alert.setAlertType(AlertTypeIDs.IDS.getType(byteBuf.readUInt16LE())); + alert.setAlertStatus(AlertStatusIDs.IDS.getType(byteBuf.readUInt16LE())); + if (alert.getAlertType() != null) { + switch (alert.getAlertType()) { + case WARNING_38: + byteBuf.shift(4); + alert.setProgrammedBolusAmount(byteBuf.readUInt16Decimal()); + alert.setDeliveredBolusAmount(byteBuf.readUInt16Decimal()); + break; + case REMINDER_07: + case WARNING_36: + byteBuf.shift(2); + alert.setTBRAmount(byteBuf.readUInt16LE()); + alert.setTBRDuration(byteBuf.readUInt16LE()); + break; + case WARNING_31: + alert.setCartridgeAmount(byteBuf.readUInt16Decimal()); + break; + } + } + if (alert.getAlertCategory() != null + && alert.getAlertType() != null + && alert.getAlertStatus() != null) + this.alert = alert; + } + + public Alert getAlert() { + return this.alert; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/status/GetActiveBasalRateMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/status/GetActiveBasalRateMessage.java new file mode 100644 index 0000000000..4b68739583 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/status/GetActiveBasalRateMessage.java @@ -0,0 +1,30 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.status; + +import info.nightscout.androidaps.plugins.pump.insight.app_layer.AppLayerMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.Service; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.ActiveBasalRate; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.MessagePriority; +import info.nightscout.androidaps.plugins.pump.insight.ids.ActiveBasalProfileIDs; +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public class GetActiveBasalRateMessage extends AppLayerMessage { + + private ActiveBasalRate activeBasalRate; + + public GetActiveBasalRateMessage() { + super(MessagePriority.NORMAL, true, false, Service.STATUS); + } + + @Override + protected void parse(ByteBuf byteBuf) { + ActiveBasalRate activeBasalRate = new ActiveBasalRate(); + activeBasalRate.setActiveBasalProfile(ActiveBasalProfileIDs.IDS.getType(byteBuf.readUInt16LE())); + activeBasalRate.setActiveBasalProfileName(byteBuf.readUTF16(30)); + activeBasalRate.setActiveBasalRate(byteBuf.readUInt16Decimal()); + if (activeBasalRate.getActiveBasalProfile() != null) this.activeBasalRate = activeBasalRate; + } + + public ActiveBasalRate getActiveBasalRate() { + return this.activeBasalRate; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/status/GetActiveBolusesMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/status/GetActiveBolusesMessage.java new file mode 100644 index 0000000000..4bcb988afd --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/status/GetActiveBolusesMessage.java @@ -0,0 +1,40 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.status; + +import java.util.ArrayList; +import java.util.List; + +import info.nightscout.androidaps.plugins.pump.insight.app_layer.AppLayerMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.Service; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.ActiveBolus; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.MessagePriority; +import info.nightscout.androidaps.plugins.pump.insight.ids.ActiveBolusTypeIDs; +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public class GetActiveBolusesMessage extends AppLayerMessage { + + private List activeBoluses; + + public GetActiveBolusesMessage() { + super(MessagePriority.NORMAL, true, false, Service.STATUS); + } + + @Override + protected void parse(ByteBuf byteBuf) { + activeBoluses = new ArrayList<>(); + for (int i = 0; i < 3; i++) { + ActiveBolus activeBolus = new ActiveBolus(); + activeBolus.setBolusID(byteBuf.readUInt16LE()); + activeBolus.setBolusType(ActiveBolusTypeIDs.IDS.getType(byteBuf.readUInt16LE())); + byteBuf.shift(2); + byteBuf.shift(2); + activeBolus.setInitialAmount(byteBuf.readUInt16Decimal()); + activeBolus.setRemainingAmount(byteBuf.readUInt16Decimal()); + activeBolus.setRemainingDuration(byteBuf.readUInt16LE()); + if (activeBolus.getBolusType() != null) activeBoluses.add(activeBolus); + } + } + + public List getActiveBoluses() { + return this.activeBoluses; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/status/GetActiveTBRMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/status/GetActiveTBRMessage.java new file mode 100644 index 0000000000..b685c65304 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/status/GetActiveTBRMessage.java @@ -0,0 +1,29 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.status; + +import info.nightscout.androidaps.plugins.pump.insight.app_layer.AppLayerMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.Service; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.ActiveTBR; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.MessagePriority; +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public class GetActiveTBRMessage extends AppLayerMessage { + + private ActiveTBR activeTBR; + + public GetActiveTBRMessage() { + super(MessagePriority.NORMAL, true, false, Service.STATUS); + } + + @Override + protected void parse(ByteBuf byteBuf) { + ActiveTBR activeTBR = new ActiveTBR(); + activeTBR.setPercentage(byteBuf.readUInt16LE()); + activeTBR.setRemainingDuration(byteBuf.readUInt16LE()); + activeTBR.setInitialDuration(byteBuf.readUInt16LE()); + if (activeTBR.getPercentage() != 100) this.activeTBR = activeTBR; + } + + public ActiveTBR getActiveTBR() { + return this.activeTBR; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/status/GetBatteryStatusMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/status/GetBatteryStatusMessage.java new file mode 100644 index 0000000000..af4b7dc17a --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/status/GetBatteryStatusMessage.java @@ -0,0 +1,30 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.status; + +import info.nightscout.androidaps.plugins.pump.insight.app_layer.AppLayerMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.Service; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.BatteryStatus; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.MessagePriority; +import info.nightscout.androidaps.plugins.pump.insight.ids.BatteryTypeIDs; +import info.nightscout.androidaps.plugins.pump.insight.ids.SymbolStatusIDs; +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public class GetBatteryStatusMessage extends AppLayerMessage { + + private BatteryStatus batteryStatus; + + public GetBatteryStatusMessage() { + super(MessagePriority.NORMAL, false, false, Service.STATUS); + } + + @Override + protected void parse(ByteBuf byteBuf) { + batteryStatus = new BatteryStatus(); + batteryStatus.setBatteryType(BatteryTypeIDs.IDS.getType(byteBuf.readUInt16LE())); + batteryStatus.setBatteryAmount(byteBuf.readUInt16LE()); + batteryStatus.setSymbolStatus(SymbolStatusIDs.IDS.getType(byteBuf.readUInt16LE())); + } + + public BatteryStatus getBatteryStatus() { + return this.batteryStatus; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/status/GetCartridgeStatusMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/status/GetCartridgeStatusMessage.java new file mode 100644 index 0000000000..33740c5ce1 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/status/GetCartridgeStatusMessage.java @@ -0,0 +1,31 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.status; + +import info.nightscout.androidaps.plugins.pump.insight.app_layer.AppLayerMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.Service; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.CartridgeStatus; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.MessagePriority; +import info.nightscout.androidaps.plugins.pump.insight.ids.CartridgeTypeIDs; +import info.nightscout.androidaps.plugins.pump.insight.ids.SymbolStatusIDs; +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public class GetCartridgeStatusMessage extends AppLayerMessage { + + private CartridgeStatus cartridgeStatus; + + public GetCartridgeStatusMessage() { + super(MessagePriority.NORMAL, false, false, Service.STATUS); + } + + @Override + protected void parse(ByteBuf byteBuf) { + cartridgeStatus = new CartridgeStatus(); + cartridgeStatus.setInserted(byteBuf.readBoolean()); + cartridgeStatus.setCartridgeType(CartridgeTypeIDs.IDS.getType(byteBuf.readUInt16LE())); + cartridgeStatus.setSymbolStatus(SymbolStatusIDs.IDS.getType(byteBuf.readUInt16LE())); + cartridgeStatus.setRemainingAmount(byteBuf.readUInt16Decimal()); + } + + public CartridgeStatus getCartridgeStatus() { + return this.cartridgeStatus; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/status/GetDateTimeMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/status/GetDateTimeMessage.java new file mode 100644 index 0000000000..e29bc5eaa2 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/status/GetDateTimeMessage.java @@ -0,0 +1,31 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.status; + +import info.nightscout.androidaps.plugins.pump.insight.app_layer.AppLayerMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.Service; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.MessagePriority; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.PumpTime; +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public class GetDateTimeMessage extends AppLayerMessage { + + private PumpTime pumpTime; + + public GetDateTimeMessage() { + super(MessagePriority.NORMAL, true, false, Service.STATUS); + } + + @Override + protected void parse(ByteBuf byteBuf) { + pumpTime = new PumpTime(); + pumpTime.setYear(byteBuf.readUInt16LE()); + pumpTime.setMonth(byteBuf.readUInt8()); + pumpTime.setDay(byteBuf.readUInt8()); + pumpTime.setHour(byteBuf.readUInt8()); + pumpTime.setMinute(byteBuf.readUInt8()); + pumpTime.setSecond(byteBuf.readUInt8()); + } + + public PumpTime getPumpTime() { + return this.pumpTime; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/status/GetFirmwareVersionsMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/status/GetFirmwareVersionsMessage.java new file mode 100644 index 0000000000..705a5e228c --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/status/GetFirmwareVersionsMessage.java @@ -0,0 +1,35 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.status; + +import info.nightscout.androidaps.plugins.pump.insight.app_layer.AppLayerMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.Service; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.FirmwareVersions; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.MessagePriority; +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public class GetFirmwareVersionsMessage extends AppLayerMessage { + + private FirmwareVersions firmwareVersions; + + public GetFirmwareVersionsMessage() { + super(MessagePriority.NORMAL, false, false, Service.STATUS); + } + + @Override + protected void parse(ByteBuf byteBuf) { + firmwareVersions = new FirmwareVersions(); + firmwareVersions.setReleaseSWVersion(byteBuf.readASCII(13)); + firmwareVersions.setUiProcSWVersion(byteBuf.readASCII(11)); + firmwareVersions.setPcProcSWVersion(byteBuf.readASCII(11)); + firmwareVersions.setMdTelProcSWVersion(byteBuf.readASCII(11)); + firmwareVersions.setBtInfoPageVersion(byteBuf.readASCII(11)); + firmwareVersions.setSafetyProcSWVersion(byteBuf.readASCII(11)); + firmwareVersions.setConfigIndex(byteBuf.readUInt16LE()); + firmwareVersions.setHistoryIndex(byteBuf.readUInt16LE()); + firmwareVersions.setStateIndex(byteBuf.readUInt16LE()); + firmwareVersions.setVocabularyIndex(byteBuf.readUInt16LE()); + } + + public FirmwareVersions getFirmwareVersions() { + return this.firmwareVersions; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/status/GetOperatingModeMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/status/GetOperatingModeMessage.java new file mode 100644 index 0000000000..27053a2a6a --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/status/GetOperatingModeMessage.java @@ -0,0 +1,26 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.status; + +import info.nightscout.androidaps.plugins.pump.insight.app_layer.AppLayerMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.Service; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.MessagePriority; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.OperatingMode; +import info.nightscout.androidaps.plugins.pump.insight.ids.OperatingModeIDs; +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public class GetOperatingModeMessage extends AppLayerMessage { + + private OperatingMode operatingMode; + + public GetOperatingModeMessage() { + super(MessagePriority.NORMAL, true, false, Service.STATUS); + } + + @Override + protected void parse(ByteBuf byteBuf) { + this.operatingMode = OperatingModeIDs.IDS.getType(byteBuf.readUInt16LE()); + } + + public OperatingMode getOperatingMode() { + return this.operatingMode; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/status/GetPumpStatusRegisterMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/status/GetPumpStatusRegisterMessage.java new file mode 100644 index 0000000000..11d777c197 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/status/GetPumpStatusRegisterMessage.java @@ -0,0 +1,60 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.status; + +import info.nightscout.androidaps.plugins.pump.insight.app_layer.AppLayerMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.Service; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.MessagePriority; +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public class GetPumpStatusRegisterMessage extends AppLayerMessage { + + private boolean operatingModeChanged; + private boolean batteryStatusChanged; + private boolean cartridgeStatusChanged; + private boolean totalDailyDoseChanged; + private boolean activeBasalRateChanged; + private boolean activeTBRChanged; + private boolean activeBolusesChanged; + + public GetPumpStatusRegisterMessage() { + super(MessagePriority.NORMAL, false, false, Service.STATUS); + } + + @Override + protected void parse(ByteBuf byteBuf) { + operatingModeChanged = byteBuf.readBoolean(); + batteryStatusChanged = byteBuf.readBoolean(); + cartridgeStatusChanged = byteBuf.readBoolean(); + totalDailyDoseChanged = byteBuf.readBoolean(); + activeBasalRateChanged = byteBuf.readBoolean(); + activeTBRChanged = byteBuf.readBoolean(); + activeBolusesChanged = byteBuf.readBoolean(); + } + + public boolean isOperatingModeChanged() { + return this.operatingModeChanged; + } + + public boolean isBatteryStatusChanged() { + return this.batteryStatusChanged; + } + + public boolean isCartridgeStatusChanged() { + return this.cartridgeStatusChanged; + } + + public boolean isTotalDailyDoseChanged() { + return this.totalDailyDoseChanged; + } + + public boolean isActiveBasalRateChanged() { + return this.activeBasalRateChanged; + } + + public boolean isActiveTBRChanged() { + return this.activeTBRChanged; + } + + public boolean isActiveBolusesChanged() { + return this.activeBolusesChanged; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/status/GetTotalDailyDoseMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/status/GetTotalDailyDoseMessage.java new file mode 100644 index 0000000000..e622614eea --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/status/GetTotalDailyDoseMessage.java @@ -0,0 +1,28 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.status; + +import info.nightscout.androidaps.plugins.pump.insight.app_layer.AppLayerMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.Service; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.MessagePriority; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.TotalDailyDose; +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public class GetTotalDailyDoseMessage extends AppLayerMessage { + + private TotalDailyDose tdd; + + public GetTotalDailyDoseMessage() { + super(MessagePriority.NORMAL, true, false, Service.STATUS); + } + + @Override + protected void parse(ByteBuf byteBuf) { + tdd = new TotalDailyDose(); + tdd.setBolus(byteBuf.readUInt32Decimal100()); + tdd.setBasal(byteBuf.readUInt32Decimal100()); + tdd.setBolusAndBasal(byteBuf.readUInt32Decimal100()); + } + + public TotalDailyDose getTDD() { + return this.tdd; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/status/ResetPumpStatusRegisterMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/status/ResetPumpStatusRegisterMessage.java new file mode 100644 index 0000000000..eacdf14769 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/app_layer/status/ResetPumpStatusRegisterMessage.java @@ -0,0 +1,63 @@ +package info.nightscout.androidaps.plugins.pump.insight.app_layer.status; + +import info.nightscout.androidaps.plugins.pump.insight.app_layer.AppLayerMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.Service; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.MessagePriority; +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public class ResetPumpStatusRegisterMessage extends AppLayerMessage { + + private boolean operatingModeChanged; + private boolean batteryStatusChanged; + private boolean cartridgeStatusChanged; + private boolean totalDailyDoseChanged; + private boolean activeBasalRateChanged; + private boolean activeTBRChanged; + private boolean activeBolusesChanged; + + public ResetPumpStatusRegisterMessage() { + super(MessagePriority.NORMAL, false, false, Service.STATUS); + } + + @Override + protected ByteBuf getData() { + ByteBuf byteBuf = new ByteBuf(28); + byteBuf.putBoolean(operatingModeChanged); + byteBuf.putBoolean(batteryStatusChanged); + byteBuf.putBoolean(cartridgeStatusChanged); + byteBuf.putBoolean(totalDailyDoseChanged); + byteBuf.putBoolean(activeBasalRateChanged); + byteBuf.putBoolean(activeTBRChanged); + byteBuf.putBoolean(activeBolusesChanged); + for (int i = 0; i < 7; i++) byteBuf.putBoolean(false); + return byteBuf; + } + + public void setOperatingModeChanged(boolean operatingModeChanged) { + this.operatingModeChanged = operatingModeChanged; + } + + public void setBatteryStatusChanged(boolean batteryStatusChanged) { + this.batteryStatusChanged = batteryStatusChanged; + } + + public void setCartridgeStatusChanged(boolean cartridgeStatusChanged) { + this.cartridgeStatusChanged = cartridgeStatusChanged; + } + + public void setTotalDailyDoseChanged(boolean totalDailyDoseChanged) { + this.totalDailyDoseChanged = totalDailyDoseChanged; + } + + public void setActiveBasalRateChanged(boolean activeBasalRateChanged) { + this.activeBasalRateChanged = activeBasalRateChanged; + } + + public void setActiveTBRChanged(boolean activeTBRChanged) { + this.activeTBRChanged = activeTBRChanged; + } + + public void setActiveBolusesChanged(boolean activeBolusesChanged) { + this.activeBolusesChanged = activeBolusesChanged; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/connection_service/ConfigurationMessageRequest.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/connection_service/ConfigurationMessageRequest.java new file mode 100644 index 0000000000..44812eb48b --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/connection_service/ConfigurationMessageRequest.java @@ -0,0 +1,33 @@ +package info.nightscout.androidaps.plugins.pump.insight.connection_service; + +import info.nightscout.androidaps.plugins.pump.insight.app_layer.AppLayerMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.configuration.CloseConfigurationWriteSessionMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.configuration.OpenConfigurationWriteSessionMessage; + +public class ConfigurationMessageRequest extends MessageRequest { + + private MessageRequest openRequest; + private MessageRequest closeRequest; + + public ConfigurationMessageRequest(T request, MessageRequest openRequest, MessageRequest closeRequest) { + super(request); + this.openRequest = openRequest; + this.closeRequest = closeRequest; + } + + @Override + public T await() throws Exception { + openRequest.await(); + T response = super.await(); + closeRequest.await(); + return response; + } + + @Override + public T await(long timeout) throws Exception { + openRequest.await(timeout); + T response = super.await(timeout); + closeRequest.await(timeout); + return response; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/connection_service/InsightConnectionService.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/connection_service/InsightConnectionService.java new file mode 100644 index 0000000000..cecb631776 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/connection_service/InsightConnectionService.java @@ -0,0 +1,827 @@ +package info.nightscout.androidaps.plugins.pump.insight.connection_service; + +import android.app.Service; +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothSocket; +import android.content.Intent; +import android.os.Binder; +import android.os.IBinder; +import android.os.PowerManager; +import androidx.annotation.Nullable; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.spongycastle.crypto.InvalidCipherTextException; + +import java.io.IOException; +import java.security.SecureRandom; +import java.util.ArrayList; +import java.util.List; + +import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.AppLayerMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.ReadParameterBlockMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.configuration.CloseConfigurationWriteSessionMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.configuration.OpenConfigurationWriteSessionMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.configuration.WriteConfigurationBlockMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.connection.ActivateServiceMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.connection.BindMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.connection.ConnectMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.connection.DisconnectMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.connection.ServiceChallengeMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks.SystemIdentificationBlock; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.status.GetFirmwareVersionsMessage; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.FirmwareVersions; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.InsightState; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.SystemIdentification; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.ConnectionFailedException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.ConnectionLostException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.DisconnectedException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.InsightException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.InvalidNonceException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.InvalidSatlCommandException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.ReceivedPacketInInvalidStateException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.TimeoutException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.TooChattyPumpException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.satl_errors.SatlCompatibleStateErrorException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.satl_errors.SatlDecryptVerifyFailedErrorException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.satl_errors.SatlIncompatibleVersionErrorException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.satl_errors.SatlInvalidCRCErrorException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.satl_errors.SatlInvalidCommIdErrorException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.satl_errors.SatlInvalidMacErrorException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.satl_errors.SatlInvalidMessageTypeErrorException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.satl_errors.SatlInvalidNonceErrorException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.satl_errors.SatlInvalidPacketErrorException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.satl_errors.SatlInvalidPayloadLengthErrorException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.satl_errors.SatlNoneErrorException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.satl_errors.SatlPairingRejectedException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.satl_errors.SatlUndefinedErrorException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.satl_errors.SatlWrongStateException; +import info.nightscout.androidaps.plugins.pump.insight.ids.ServiceIDs; +import info.nightscout.androidaps.plugins.pump.insight.satl.ConnectionRequest; +import info.nightscout.androidaps.plugins.pump.insight.satl.ConnectionResponse; +import info.nightscout.androidaps.plugins.pump.insight.satl.DataMessage; +import info.nightscout.androidaps.plugins.pump.insight.satl.ErrorMessage; +import info.nightscout.androidaps.plugins.pump.insight.satl.KeyRequest; +import info.nightscout.androidaps.plugins.pump.insight.satl.KeyResponse; +import info.nightscout.androidaps.plugins.pump.insight.satl.SatlMessage; +import info.nightscout.androidaps.plugins.pump.insight.satl.SynAckResponse; +import info.nightscout.androidaps.plugins.pump.insight.satl.SynRequest; +import info.nightscout.androidaps.plugins.pump.insight.satl.VerifyConfirmRequest; +import info.nightscout.androidaps.plugins.pump.insight.satl.VerifyConfirmResponse; +import info.nightscout.androidaps.plugins.pump.insight.satl.VerifyDisplayRequest; +import info.nightscout.androidaps.plugins.pump.insight.satl.VerifyDisplayResponse; +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; +import info.nightscout.androidaps.plugins.pump.insight.utils.ConnectionEstablisher; +import info.nightscout.androidaps.plugins.pump.insight.utils.DelayedActionThread; +import info.nightscout.androidaps.plugins.pump.insight.utils.InputStreamReader; +import info.nightscout.androidaps.plugins.pump.insight.utils.Nonce; +import info.nightscout.androidaps.plugins.pump.insight.utils.OutputStreamWriter; +import info.nightscout.androidaps.plugins.pump.insight.utils.PairingDataStorage; +import info.nightscout.androidaps.plugins.pump.insight.utils.crypto.Cryptograph; +import info.nightscout.androidaps.plugins.pump.insight.utils.crypto.DerivedKeys; +import info.nightscout.androidaps.plugins.pump.insight.utils.crypto.KeyPair; +import info.nightscout.androidaps.utils.SP; + +public class InsightConnectionService extends Service implements ConnectionEstablisher.Callback, InputStreamReader.Callback, OutputStreamWriter.Callback { + + private static Logger log = LoggerFactory.getLogger(L.PUMPCOMM); + + private static final int BUFFER_SIZE = 1024; + private static final int TIMEOUT_DURING_HANDSHAKE_NOTIFICATION_THRESHOLD = 3; + private static final long RESPONSE_TIMEOUT = 6000; + + private List stateCallbacks = new ArrayList<>(); + private final List connectionRequests = new ArrayList<>(); + private List exceptionCallbacks = new ArrayList<>(); + private LocalBinder localBinder = new LocalBinder(); + private PairingDataStorage pairingDataStorage; + private InsightState state; + private PowerManager.WakeLock wakeLock; + private DelayedActionThread disconnectTimer; + private DelayedActionThread recoveryTimer; + private DelayedActionThread timeoutTimer; + private BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); + private BluetoothDevice bluetoothDevice; + private BluetoothSocket bluetoothSocket; + private ConnectionEstablisher connectionEstablisher; + private InputStreamReader inputStreamReader; + private OutputStreamWriter outputStreamWriter; + private KeyRequest keyRequest; + private ByteBuf buffer = new ByteBuf(BUFFER_SIZE); + private String verificationString; + private KeyPair keyPair; + private byte[] randomBytes; + private MessageQueue messageQueue = new MessageQueue(); + private List activatedServices = new ArrayList<>(); + private long lastDataTime; + private long lastConnected; + private long recoveryDuration = 0; + private int timeoutDuringHandshakeCounter; + + KeyPair getKeyPair() { + if (keyPair == null) keyPair = Cryptograph.generateRSAKey(); + return keyPair; + } + + byte[] getRandomBytes() { + if (randomBytes == null) { + randomBytes = new byte[28]; + new SecureRandom().nextBytes(randomBytes); + } + return randomBytes; + } + + public synchronized long getRecoveryDuration() { + return recoveryDuration; + } + + private void increaseRecoveryDuration() { + long maxRecoveryDuration = SP.getInt("insight_max_recovery_duration", 20); + maxRecoveryDuration = Math.min(maxRecoveryDuration, 20); + maxRecoveryDuration = Math.max(maxRecoveryDuration, 0); + long minRecoveryDuration = SP.getInt("insight_min_recovery_duration", 5); + minRecoveryDuration = Math.min(minRecoveryDuration, 20); + minRecoveryDuration = Math.max(minRecoveryDuration, 0); + recoveryDuration += 1000; + recoveryDuration = Math.max(recoveryDuration, minRecoveryDuration * 1000); + recoveryDuration = Math.min(recoveryDuration, maxRecoveryDuration * 1000); + } + + public long getLastConnected() { + return lastConnected; + } + + public long getLastDataTime() { + return lastDataTime; + } + + public FirmwareVersions getPumpFirmwareVersions() { + return pairingDataStorage.getFirmwareVersions(); + } + + public SystemIdentification getPumpSystemIdentification() { + return pairingDataStorage.getSystemIdentification(); + } + + public String getBluetoothAddress() { + return pairingDataStorage.getMacAddress(); + } + + public synchronized String getVerificationString() { + return verificationString; + } + + public synchronized void registerStateCallback(StateCallback stateCallback) { + stateCallbacks.add(stateCallback); + } + + public synchronized void unregisterStateCallback(StateCallback stateCallback) { + stateCallbacks.remove(stateCallback); + } + + public synchronized void registerExceptionCallback(ExceptionCallback exceptionCallback) { + exceptionCallbacks.add(exceptionCallback); + } + + public synchronized void unregisterExceptionCallback(ExceptionCallback exceptionCallback) { + exceptionCallbacks.remove(exceptionCallback); + } + + public synchronized void confirmVerificationString() { + setState(InsightState.SATL_VERIFY_CONFIRM_REQUEST); + sendSatlMessage(new VerifyConfirmRequest()); + } + + public synchronized void rejectVerificationString() { + handleException(new SatlPairingRejectedException()); + } + + public synchronized boolean isPaired() { + return pairingDataStorage.isPaired(); + } + + public synchronized MessageRequest requestMessage(T message) { + MessageRequest messageRequest; + if (getState() != InsightState.CONNECTED) { + messageRequest = new MessageRequest<>(message); + messageRequest.exception = new DisconnectedException(); + return messageRequest; + } + if (message instanceof WriteConfigurationBlockMessage) { + MessageRequest openRequest = new MessageRequest<>(new OpenConfigurationWriteSessionMessage()); + MessageRequest closeRequest = new MessageRequest<>(new CloseConfigurationWriteSessionMessage()); + messageRequest = new ConfigurationMessageRequest<>(message, openRequest, closeRequest); + messageQueue.enqueueRequest(openRequest); + messageQueue.enqueueRequest(messageRequest); + messageQueue.enqueueRequest(closeRequest); + } else { + messageRequest = new MessageRequest<>(message); + messageQueue.enqueueRequest(messageRequest); + } + requestNextMessage(); + return messageRequest; + } + + private void requestNextMessage() { + while (messageQueue.getActiveRequest() == null && messageQueue.hasPendingMessages()) { + messageQueue.nextRequest(); + info.nightscout.androidaps.plugins.pump.insight.app_layer.Service service = messageQueue.getActiveRequest().request.getService(); + if (service != info.nightscout.androidaps.plugins.pump.insight.app_layer.Service.CONNECTION && !activatedServices.contains(service)) { + if (service.getServicePassword() == null) { + ActivateServiceMessage activateServiceMessage = new ActivateServiceMessage(); + activateServiceMessage.setServiceID(ServiceIDs.IDS.getID(service)); + activateServiceMessage.setVersion(service.getVersion()); + activateServiceMessage.setServicePassword(new byte[16]); + sendAppLayerMessage(activateServiceMessage); + } else { + ServiceChallengeMessage serviceChallengeMessage = new ServiceChallengeMessage(); + serviceChallengeMessage.setServiceID(ServiceIDs.IDS.getID(service)); + serviceChallengeMessage.setVersion(service.getVersion()); + sendAppLayerMessage(serviceChallengeMessage); + } + } else sendAppLayerMessage(messageQueue.getActiveRequest().request); + } + } + + public synchronized InsightState getState() { + return state; + } + + @Override + public synchronized void onCreate() { + pairingDataStorage = new PairingDataStorage(this); + state = pairingDataStorage.isPaired() ? InsightState.DISCONNECTED : InsightState.NOT_PAIRED; + wakeLock = ((PowerManager) getSystemService(POWER_SERVICE)).newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "AndroidAPS:InsightConnectionService"); + } + + private void setState(InsightState state) { + if (this.state == state) return; + if (this.state == InsightState.CONNECTED) lastConnected = System.currentTimeMillis(); + if ((state == InsightState.DISCONNECTED || state == InsightState.NOT_PAIRED) && wakeLock.isHeld()) + wakeLock.release(); + else if (!wakeLock.isHeld()) wakeLock.acquire(); + this.state = state; + for (StateCallback stateCallback : stateCallbacks) stateCallback.onStateChanged(state); + log.info("Insight state changed: " + state.name()); + } + + public synchronized void requestConnection(Object lock) { + if (connectionRequests.contains(lock)) return; + connectionRequests.add(lock); + if (disconnectTimer != null) { + disconnectTimer.interrupt(); + disconnectTimer = null; + } + if (state == InsightState.DISCONNECTED && pairingDataStorage.isPaired()) { + recoveryDuration = 0; + timeoutDuringHandshakeCounter = 0; + connect(); + } + } + + public synchronized void withdrawConnectionRequest(Object lock) { + if (!connectionRequests.contains(lock)) return; + connectionRequests.remove(lock); + if (connectionRequests.size() == 0) { + if (state == InsightState.RECOVERING) { + recoveryTimer.interrupt(); + recoveryTimer = null; + setState(InsightState.DISCONNECTED); + cleanup(true); + } else if (state != InsightState.DISCONNECTED) { + long disconnectTimeout = SP.getInt("insight_disconnect_delay", 5); + disconnectTimeout = Math.min(disconnectTimeout, 15); + disconnectTimeout = Math.max(disconnectTimeout, 0); + log.info("Last connection lock released, will disconnect in " + disconnectTimeout + " seconds"); + disconnectTimer = DelayedActionThread.runDelayed("Disconnect Timer", disconnectTimeout * 1000, this::disconnect); + } + } + } + + public synchronized boolean hasRequestedConnection(Object lock) { + return connectionRequests.contains(lock); + } + + private void cleanup(boolean closeSocket) { + messageQueue.completeActiveRequest(new ConnectionLostException()); + messageQueue.completePendingRequests(new ConnectionLostException()); + if (recoveryTimer != null) { + recoveryTimer.interrupt(); + recoveryTimer = null; + } + if (disconnectTimer != null) { + disconnectTimer.interrupt(); + disconnectTimer = null; + } + if (inputStreamReader != null) { + inputStreamReader.close(); + inputStreamReader = null; + } + if (outputStreamWriter != null) { + outputStreamWriter.close(); + outputStreamWriter = null; + } + if (connectionEstablisher != null) { + if (closeSocket) { + connectionEstablisher.close(closeSocket); + bluetoothSocket = null; + } + connectionEstablisher = null; + } + if (timeoutTimer != null) { + timeoutTimer.interrupt(); + timeoutTimer = null; + } + buffer.clear(); + verificationString = null; + keyPair = null; + randomBytes = null; + activatedServices.clear(); + if (!pairingDataStorage.isPaired()) { + bluetoothSocket = null; + bluetoothDevice = null; + pairingDataStorage.reset(); + } + } + + private synchronized void handleException(Exception e) { + switch (state) { + case NOT_PAIRED: + case DISCONNECTED: + case RECOVERING: + return; + } + log.info("Exception occurred: " + e.getClass().getSimpleName()); + if (pairingDataStorage.isPaired()) { + if (e instanceof TimeoutException && (state == InsightState.SATL_SYN_REQUEST || state == InsightState.APP_CONNECT_MESSAGE)) { + if (++timeoutDuringHandshakeCounter == TIMEOUT_DURING_HANDSHAKE_NOTIFICATION_THRESHOLD) { + for (StateCallback stateCallback : stateCallbacks) { + stateCallback.onTimeoutDuringHandshake(); + } + } + } + setState(connectionRequests.size() != 0 ? InsightState.RECOVERING : InsightState.DISCONNECTED); + if (e instanceof ConnectionFailedException) { + cleanup(((ConnectionFailedException) e).getDurationOfConnectionAttempt() <= 1000); + } else cleanup(true); + messageQueue.completeActiveRequest(e); + messageQueue.completePendingRequests(e); + if (connectionRequests.size() != 0) { + if (!(e instanceof ConnectionFailedException)) { + connect(); + } else { + increaseRecoveryDuration(); + if (recoveryDuration == 0) connect(); + else { + recoveryTimer = DelayedActionThread.runDelayed("RecoveryTimer", recoveryDuration, () -> { + recoveryTimer = null; + synchronized (InsightConnectionService.this) { + if (!Thread.currentThread().isInterrupted()) connect(); + } + }); + } + } + } + } else { + setState(InsightState.NOT_PAIRED); + cleanup(true); + } + for (ExceptionCallback exceptionCallback : exceptionCallbacks) + exceptionCallback.onExceptionOccur(e); + } + + private synchronized void disconnect() { + if (state == InsightState.CONNECTED) { + sendAppLayerMessage(new DisconnectMessage()); + sendSatlMessageAndWait(new info.nightscout.androidaps.plugins.pump.insight.satl.DisconnectMessage()); + } + cleanup(true); + setState(pairingDataStorage.isPaired() ? InsightState.DISCONNECTED : InsightState.NOT_PAIRED); + } + + public synchronized void reset() { + pairingDataStorage.reset(); + disconnect(); + } + + public synchronized void pair(String macAddress) { + if (pairingDataStorage.isPaired()) + throw new IllegalStateException("Pump must be unbonded first."); + if (connectionRequests.size() == 0) + throw new IllegalStateException("A connection lock must be hold for pairing"); + log.info("Pairing initiated"); + cleanup(true); + pairingDataStorage.setMacAddress(macAddress); + connect(); + } + + private synchronized void connect() { + if (bluetoothDevice == null) + bluetoothDevice = bluetoothAdapter.getRemoteDevice(pairingDataStorage.getMacAddress()); + setState(InsightState.CONNECTING); + connectionEstablisher = new ConnectionEstablisher(this, !pairingDataStorage.isPaired(), bluetoothAdapter, bluetoothDevice, bluetoothSocket); + connectionEstablisher.start(); + } + + @Override + public synchronized void onSocketCreated(BluetoothSocket bluetoothSocket) { + this.bluetoothSocket = bluetoothSocket; + } + + @Override + public synchronized void onConnectionSucceed() { + try { + recoveryDuration = 0; + inputStreamReader = new InputStreamReader(bluetoothSocket.getInputStream(), this); + outputStreamWriter = new OutputStreamWriter(bluetoothSocket.getOutputStream(), this); + inputStreamReader.start(); + outputStreamWriter.start(); + if (pairingDataStorage.isPaired()) { + setState(InsightState.SATL_SYN_REQUEST); + sendSatlMessage(new SynRequest()); + } else { + setState(InsightState.SATL_CONNECTION_REQUEST); + sendSatlMessage(new ConnectionRequest()); + } + } catch (IOException e) { + handleException(e); + } + } + + @Override + public synchronized void onReceiveBytes(byte[] buffer, int bytesRead) { + this.buffer.putBytes(buffer, bytesRead); + try { + while (SatlMessage.hasCompletePacket(this.buffer)) { + SatlMessage satlMessage = SatlMessage.deserialize(this.buffer, pairingDataStorage.getLastNonceReceived(), pairingDataStorage.getIncomingKey()); + if (pairingDataStorage.getIncomingKey() != null + && pairingDataStorage.getLastNonceReceived() != null + && !pairingDataStorage.getLastNonceReceived().isSmallerThan(satlMessage.getNonce())) { + throw new InvalidNonceException(); + } else processSatlMessage(satlMessage); + } + } catch (InsightException e) { + handleException(e); + } + } + + private byte[] prepareSatlMessage(SatlMessage satlMessage) { + satlMessage.setCommID(pairingDataStorage.getCommId()); + Nonce nonce = pairingDataStorage.getLastNonceSent(); + if (nonce != null) { + nonce.increment(); + pairingDataStorage.setLastNonceSent(nonce); + satlMessage.setNonce(nonce); + } + ByteBuf serialized = satlMessage.serialize(satlMessage.getClass(), pairingDataStorage.getOutgoingKey()); + if (timeoutTimer != null) timeoutTimer.interrupt(); + timeoutTimer = DelayedActionThread.runDelayed("TimeoutTimer", RESPONSE_TIMEOUT, () -> { + timeoutTimer = null; + handleException(new TimeoutException()); + }); + return serialized.getBytes(); + } + + private void sendSatlMessage(SatlMessage satlMessage) { + if (outputStreamWriter == null) return; + outputStreamWriter.write(prepareSatlMessage(satlMessage)); + } + + private void sendSatlMessageAndWait(SatlMessage satlMessage) { + if (outputStreamWriter == null) return; + outputStreamWriter.writeAndWait(prepareSatlMessage(satlMessage)); + } + + private void processSatlMessage(SatlMessage satlMessage) { + if (timeoutTimer != null) { + timeoutTimer.interrupt(); + timeoutTimer = null; + } + pairingDataStorage.setLastNonceReceived(satlMessage.getNonce()); + if (satlMessage instanceof ConnectionResponse) processConnectionResponse(); + else if (satlMessage instanceof KeyResponse) processKeyResponse((KeyResponse) satlMessage); + else if (satlMessage instanceof VerifyDisplayResponse) processVerifyDisplayResponse(); + else if (satlMessage instanceof VerifyConfirmResponse) + processVerifyConfirmResponse((VerifyConfirmResponse) satlMessage); + else if (satlMessage instanceof DataMessage) processDataMessage((DataMessage) satlMessage); + else if (satlMessage instanceof SynAckResponse) processSynAckResponse(); + else if (satlMessage instanceof ErrorMessage) + processErrorMessage((ErrorMessage) satlMessage); + else handleException(new InvalidSatlCommandException()); + } + + private void processConnectionResponse() { + if (state != InsightState.SATL_CONNECTION_REQUEST) { + handleException(new ReceivedPacketInInvalidStateException()); + return; + } + keyRequest = new KeyRequest(); + keyRequest.setPreMasterKey(getKeyPair().getPublicKeyBytes()); + keyRequest.setRandomBytes(getRandomBytes()); + setState(InsightState.SATL_KEY_REQUEST); + sendSatlMessage(keyRequest); + } + + private void processKeyResponse(KeyResponse keyResponse) { + if (state != InsightState.SATL_KEY_REQUEST) { + handleException(new ReceivedPacketInInvalidStateException()); + return; + } + try { + DerivedKeys derivedKeys = Cryptograph.deriveKeys(Cryptograph.combine(keyRequest.getSatlContent(), keyResponse.getSatlContent()), + Cryptograph.decryptRSA(getKeyPair().getPrivateKey(), keyResponse.getPreMasterSecret()), + getRandomBytes(), + keyResponse.getRandomData()); + pairingDataStorage.setCommId(keyResponse.getCommID()); + keyRequest = null; + randomBytes = null; + keyPair = null; + verificationString = derivedKeys.getVerificationString(); + pairingDataStorage.setOutgoingKey(derivedKeys.getOutgoingKey()); + pairingDataStorage.setIncomingKey(derivedKeys.getIncomingKey()); + pairingDataStorage.setLastNonceSent(new Nonce()); + setState(InsightState.SATL_VERIFY_DISPLAY_REQUEST); + sendSatlMessage(new VerifyDisplayRequest()); + } catch (InvalidCipherTextException e) { + handleException(e); + } + } + + private void processVerifyDisplayResponse() { + if (state != InsightState.SATL_VERIFY_DISPLAY_REQUEST) { + handleException(new ReceivedPacketInInvalidStateException()); + return; + } + setState(InsightState.AWAITING_CODE_CONFIRMATION); + } + + private void processVerifyConfirmResponse(VerifyConfirmResponse verifyConfirmResponse) { + if (state != InsightState.SATL_VERIFY_CONFIRM_REQUEST) { + handleException(new ReceivedPacketInInvalidStateException()); + return; + } + switch (verifyConfirmResponse.getPairingStatus()) { + case CONFIRMED: + verificationString = null; + setState(InsightState.APP_BIND_MESSAGE); + sendAppLayerMessage(new BindMessage()); + break; + case PENDING: + try { + Thread.sleep(200); + sendSatlMessage(new VerifyConfirmRequest()); + } catch (InterruptedException e) { + //Redirect interrupt flag + Thread.currentThread().interrupt(); + } + break; + case REJECTED: + handleException(new SatlPairingRejectedException()); + break; + } + } + + private void processSynAckResponse() { + if (state != InsightState.SATL_SYN_REQUEST) { + handleException(new ReceivedPacketInInvalidStateException()); + return; + } + setState(InsightState.APP_CONNECT_MESSAGE); + sendAppLayerMessage(new ConnectMessage()); + } + + private void processErrorMessage(ErrorMessage errorMessage) { + switch (errorMessage.getError()) { + case INVALID_NONCE: + handleException(new SatlInvalidNonceErrorException()); + break; + case INVALID_CRC: + handleException(new SatlInvalidCRCErrorException()); + break; + case INVALID_MAC_TRAILER: + handleException(new SatlInvalidMacErrorException()); + break; + case DECRYPT_VERIFY_FAILED: + handleException(new SatlDecryptVerifyFailedErrorException()); + break; + case INVALID_PAYLOAD_LENGTH: + handleException(new SatlInvalidPayloadLengthErrorException()); + break; + case INVALID_MESSAGE_TYPE: + handleException(new SatlInvalidMessageTypeErrorException()); + break; + case INCOMPATIBLE_VERSION: + handleException(new SatlIncompatibleVersionErrorException()); + break; + case COMPATIBLE_STATE: + handleException(new SatlCompatibleStateErrorException()); + break; + case INVALID_COMM_ID: + handleException(new SatlInvalidCommIdErrorException()); + break; + case INVALID_PACKET: + handleException(new SatlInvalidPacketErrorException()); + break; + case WRONG_STATE: + handleException(new SatlWrongStateException()); + break; + case UNDEFINED: + handleException(new SatlUndefinedErrorException()); + break; + case NONE: + handleException(new SatlNoneErrorException()); + break; + } + } + + private void processDataMessage(DataMessage dataMessage) { + switch (state) { + case CONNECTED: + case APP_BIND_MESSAGE: + case APP_CONNECT_MESSAGE: + case APP_ACTIVATE_PARAMETER_SERVICE: + case APP_ACTIVATE_STATUS_SERVICE: + case APP_FIRMWARE_VERSIONS: + case APP_SYSTEM_IDENTIFICATION: + break; + default: + handleException(new ReceivedPacketInInvalidStateException()); + } + try { + AppLayerMessage appLayerMessage = AppLayerMessage.unwrap(dataMessage); + if (appLayerMessage instanceof BindMessage) processBindMessage(); + else if (appLayerMessage instanceof ConnectMessage) processConnectMessage(); + else if (appLayerMessage instanceof ActivateServiceMessage) + processActivateServiceMessage(); + else if (appLayerMessage instanceof DisconnectMessage) ; + else if (appLayerMessage instanceof ServiceChallengeMessage) + processServiceChallengeMessage((ServiceChallengeMessage) appLayerMessage); + else if (appLayerMessage instanceof GetFirmwareVersionsMessage) + processFirmwareVersionsMessage((GetFirmwareVersionsMessage) appLayerMessage); + else if (appLayerMessage instanceof ReadParameterBlockMessage) + processReadParameterBlockMessage((ReadParameterBlockMessage) appLayerMessage); + else processGenericAppLayerMessage(appLayerMessage); + } catch (Exception e) { + if (state != InsightState.CONNECTED) { + handleException(e); + } else { + if (messageQueue.getActiveRequest() == null) { + handleException(new TooChattyPumpException()); + } else { + messageQueue.completeActiveRequest(e); + requestNextMessage(); + } + } + } + } + + private void processBindMessage() { + if (state != InsightState.APP_BIND_MESSAGE) { + handleException(new ReceivedPacketInInvalidStateException()); + return; + } + setState(InsightState.APP_ACTIVATE_STATUS_SERVICE); + ActivateServiceMessage activateServiceMessage = new ActivateServiceMessage(); + activateServiceMessage.setServiceID(ServiceIDs.IDS.getID(info.nightscout.androidaps.plugins.pump.insight.app_layer.Service.STATUS)); + activateServiceMessage.setServicePassword(new byte[16]); + activateServiceMessage.setVersion(info.nightscout.androidaps.plugins.pump.insight.app_layer.Service.STATUS.getVersion()); + sendAppLayerMessage(activateServiceMessage); + } + + private void processFirmwareVersionsMessage(GetFirmwareVersionsMessage message) { + if (state != InsightState.APP_FIRMWARE_VERSIONS) { + handleException(new ReceivedPacketInInvalidStateException()); + return; + } + pairingDataStorage.setFirmwareVersions(message.getFirmwareVersions()); + setState(InsightState.APP_ACTIVATE_PARAMETER_SERVICE); + ActivateServiceMessage activateServiceMessage = new ActivateServiceMessage(); + activateServiceMessage.setServiceID(ServiceIDs.IDS.getID(info.nightscout.androidaps.plugins.pump.insight.app_layer.Service.PARAMETER)); + activateServiceMessage.setServicePassword(new byte[16]); + activateServiceMessage.setVersion(info.nightscout.androidaps.plugins.pump.insight.app_layer.Service.PARAMETER.getVersion()); + sendAppLayerMessage(activateServiceMessage); + } + + private void processConnectMessage() { + if (state != InsightState.APP_CONNECT_MESSAGE) { + handleException(new ReceivedPacketInInvalidStateException()); + return; + } + setState(InsightState.CONNECTED); + } + + private void processActivateServiceMessage() { + if (state == InsightState.APP_ACTIVATE_PARAMETER_SERVICE) { + activatedServices.add(info.nightscout.androidaps.plugins.pump.insight.app_layer.Service.PARAMETER); + setState(InsightState.APP_SYSTEM_IDENTIFICATION); + ReadParameterBlockMessage message = new ReadParameterBlockMessage(); + message.setParameterBlockId(SystemIdentificationBlock.class); + message.setService(info.nightscout.androidaps.plugins.pump.insight.app_layer.Service.PARAMETER); + sendAppLayerMessage(message); + } else if (state == InsightState.APP_ACTIVATE_STATUS_SERVICE) { + activatedServices.add(info.nightscout.androidaps.plugins.pump.insight.app_layer.Service.STATUS); + setState(InsightState.APP_FIRMWARE_VERSIONS); + sendAppLayerMessage(new GetFirmwareVersionsMessage()); + } else { + if (messageQueue.getActiveRequest() == null) { + handleException(new TooChattyPumpException()); + } else { + activatedServices.add(messageQueue.getActiveRequest().request.getService()); + sendAppLayerMessage(messageQueue.getActiveRequest().request); + } + } + } + + private void processReadParameterBlockMessage(ReadParameterBlockMessage message) { + if (state == InsightState.APP_SYSTEM_IDENTIFICATION) { + if (!(message.getParameterBlock() instanceof SystemIdentificationBlock)) + handleException(new TooChattyPumpException()); + else { + SystemIdentification systemIdentification = ((SystemIdentificationBlock) message.getParameterBlock()).getSystemIdentification(); + pairingDataStorage.setSystemIdentification(systemIdentification); + pairingDataStorage.setPaired(true); + log.info("Pairing completed YEE-HAW ♪ ┏(・o・)┛ ♪ ┗( ・o・)┓ ♪"); + setState(InsightState.CONNECTED); + for (StateCallback stateCallback : stateCallbacks) stateCallback.onPumpPaired(); + } + } else processGenericAppLayerMessage(message); + } + + private void processServiceChallengeMessage(ServiceChallengeMessage serviceChallengeMessage) { + if (messageQueue.getActiveRequest() == null) { + handleException(new TooChattyPumpException()); + } else { + info.nightscout.androidaps.plugins.pump.insight.app_layer.Service service = messageQueue.getActiveRequest().request.getService(); + ActivateServiceMessage activateServiceMessage = new ActivateServiceMessage(); + activateServiceMessage.setServiceID(ServiceIDs.IDS.getID(service)); + activateServiceMessage.setVersion(service.getVersion()); + activateServiceMessage.setServicePassword(Cryptograph.getServicePasswordHash(service.getServicePassword(), serviceChallengeMessage.getRandomData())); + sendAppLayerMessage(activateServiceMessage); + } + } + + private void processGenericAppLayerMessage(AppLayerMessage appLayerMessage) { + if (messageQueue.getActiveRequest() == null) handleException(new TooChattyPumpException()); + else { + try { + messageQueue.completeActiveRequest(appLayerMessage); + lastDataTime = System.currentTimeMillis(); + } catch (Exception e) { + messageQueue.completeActiveRequest(e); + } + requestNextMessage(); + } + } + + void sendAppLayerMessage(AppLayerMessage appLayerMessage) { + sendSatlMessage(AppLayerMessage.wrap(appLayerMessage)); + } + + @Override + public synchronized void onConnectionFail(Exception e, long duration) { + handleException(new ConnectionFailedException(duration)); + } + + @Override + public synchronized void onErrorWhileReading(Exception e) { + handleException(new ConnectionLostException()); + } + + @Override + public synchronized void onErrorWhileWriting(Exception e) { + handleException(new ConnectionLostException()); + } + + @Override + public void onDestroy() { + disconnect(); + } + + @Nullable + @Override + public IBinder onBind(Intent intent) { + return localBinder; + } + + public class LocalBinder extends Binder { + public InsightConnectionService getService() { + return InsightConnectionService.this; + } + } + + public interface StateCallback { + void onStateChanged(InsightState state); + + default void onPumpPaired() { + } + + default void onTimeoutDuringHandshake() { + } + } + + public interface ExceptionCallback { + void onExceptionOccur(Exception e); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/connection_service/MessageQueue.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/connection_service/MessageQueue.java new file mode 100644 index 0000000000..f54f437564 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/connection_service/MessageQueue.java @@ -0,0 +1,66 @@ +package info.nightscout.androidaps.plugins.pump.insight.connection_service; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import info.nightscout.androidaps.plugins.pump.insight.app_layer.AppLayerMessage; + +public class MessageQueue { + + MessageRequest activeRequest; + final List messageRequests = new ArrayList<>(); + + public MessageRequest getActiveRequest() { + return activeRequest; + } + + public void completeActiveRequest(AppLayerMessage response) { + if (activeRequest == null) return; + synchronized (activeRequest) { + activeRequest.response = response; + activeRequest.notifyAll(); + } + activeRequest = null; + } + + public void completeActiveRequest(Exception exception) { + if (activeRequest == null) return; + synchronized (activeRequest) { + activeRequest.exception = exception; + activeRequest.notifyAll(); + } + activeRequest = null; + } + + public void completePendingRequests(Exception exception) { + for (MessageRequest messageRequest : messageRequests) { + synchronized (messageRequest) { + messageRequest.exception = exception; + messageRequest.notifyAll(); + } + } + messageRequests.clear(); + } + + public void enqueueRequest(MessageRequest messageRequest) { + messageRequests.add(messageRequest); + Collections.sort(messageRequests); + } + + public void nextRequest() { + if (messageRequests.size() != 0) { + activeRequest = messageRequests.get(0); + messageRequests.remove(0); + } + } + + public boolean hasPendingMessages() { + return messageRequests.size() != 0; + } + + public void reset() { + activeRequest = null; + messageRequests.clear(); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/connection_service/MessageRequest.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/connection_service/MessageRequest.java new file mode 100644 index 0000000000..70fdf63649 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/connection_service/MessageRequest.java @@ -0,0 +1,47 @@ +package info.nightscout.androidaps.plugins.pump.insight.connection_service; + +import info.nightscout.androidaps.plugins.pump.insight.app_layer.AppLayerMessage; + +public class MessageRequest implements Comparable { + + T request; + T response; + Exception exception; + + MessageRequest(T request) { + this.request = request; + } + + public T await() throws Exception { + synchronized (this) { + while (exception == null && response == null) wait(); + if (exception != null) throw exception; + return response; + } + } + + public T await(long timeout) throws Exception { + synchronized (this) { + while (exception == null && response == null) wait(timeout); + if (exception != null) throw exception; + return response; + } + } + + @Override + public int compareTo(MessageRequest messageRequest) { + return request.compareTo(messageRequest.request); + } + + public T getRequest() { + return this.request; + } + + public T getResponse() { + return this.response; + } + + public Exception getException() { + return this.exception; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/database/InsightBolusID.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/database/InsightBolusID.java new file mode 100644 index 0000000000..16fa232a40 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/database/InsightBolusID.java @@ -0,0 +1,29 @@ +package info.nightscout.androidaps.plugins.pump.insight.database; + +import com.j256.ormlite.field.DatabaseField; +import com.j256.ormlite.table.DatabaseTable; + +import info.nightscout.androidaps.db.DatabaseHelper; + +@DatabaseTable(tableName = DatabaseHelper.DATABASE_INSIGHT_BOLUS_IDS) +public class InsightBolusID { + + @DatabaseField(generatedId = true) + public Long id; + + @DatabaseField + public String pumpSerial; + + @DatabaseField + public Long timestamp; + + @DatabaseField + public Integer bolusID; + + @DatabaseField + public Long startID; + + @DatabaseField + public Long endID; + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/database/InsightHistoryOffset.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/database/InsightHistoryOffset.java new file mode 100644 index 0000000000..05f9d2d5e3 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/database/InsightHistoryOffset.java @@ -0,0 +1,16 @@ +package info.nightscout.androidaps.plugins.pump.insight.database; + +import com.j256.ormlite.field.DatabaseField; +import com.j256.ormlite.table.DatabaseTable; + +import info.nightscout.androidaps.db.DatabaseHelper; + +@DatabaseTable(tableName = DatabaseHelper.DATABASE_INSIGHT_HISTORY_OFFSETS) +public class InsightHistoryOffset { + + @DatabaseField(id = true, canBeNull = false) + public String pumpSerial; + + @DatabaseField + public long offset; +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/database/InsightPumpID.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/database/InsightPumpID.java new file mode 100644 index 0000000000..7bd70b9185 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/database/InsightPumpID.java @@ -0,0 +1,26 @@ +package info.nightscout.androidaps.plugins.pump.insight.database; + +import com.j256.ormlite.field.DatabaseField; +import com.j256.ormlite.table.DatabaseTable; + +import info.nightscout.androidaps.db.DatabaseHelper; + +@DatabaseTable(tableName = DatabaseHelper.DATABASE_INSIGHT_PUMP_IDS) +public class InsightPumpID { + + @DatabaseField(generatedId = true) + public Long id; + + @DatabaseField + public long timestamp; + + @DatabaseField + public String eventType; + + @DatabaseField + public String pumpSerial; + + @DatabaseField + public long eventID; + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/ActiveBasalRate.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/ActiveBasalRate.java new file mode 100644 index 0000000000..2fb078794b --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/ActiveBasalRate.java @@ -0,0 +1,32 @@ +package info.nightscout.androidaps.plugins.pump.insight.descriptors; + +public class ActiveBasalRate { + + private BasalProfile activeBasalProfile; + private String activeBasalProfileName; + private double activeBasalRate; + + public BasalProfile getActiveBasalProfile() { + return this.activeBasalProfile; + } + + public String getActiveBasalProfileName() { + return this.activeBasalProfileName; + } + + public double getActiveBasalRate() { + return this.activeBasalRate; + } + + public void setActiveBasalProfile(BasalProfile activeBasalProfile) { + this.activeBasalProfile = activeBasalProfile; + } + + public void setActiveBasalProfileName(String activeBasalProfileName) { + this.activeBasalProfileName = activeBasalProfileName; + } + + public void setActiveBasalRate(double activeBasalRate) { + this.activeBasalRate = activeBasalRate; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/ActiveBolus.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/ActiveBolus.java new file mode 100644 index 0000000000..f36e1d7de4 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/ActiveBolus.java @@ -0,0 +1,50 @@ +package info.nightscout.androidaps.plugins.pump.insight.descriptors; + +public class ActiveBolus { + + private int bolusID; + private BolusType bolusType; + private double initialAmount; + private double remainingAmount; + private int remainingDuration; + + public int getBolusID() { + return this.bolusID; + } + + public BolusType getBolusType() { + return this.bolusType; + } + + public double getInitialAmount() { + return this.initialAmount; + } + + public double getRemainingAmount() { + return this.remainingAmount; + } + + public int getRemainingDuration() { + return this.remainingDuration; + } + + public void setBolusID(int bolusID) { + this.bolusID = bolusID; + } + + public void setBolusType(BolusType bolusType) { + this.bolusType = bolusType; + } + + public void setInitialAmount(double initialAmount) { + this.initialAmount = initialAmount; + } + + public void setRemainingAmount(double remainingAmount) { + this.remainingAmount = remainingAmount; + } + + public void setRemainingDuration(int remainingDuration) { + this.remainingDuration = remainingDuration; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/ActiveTBR.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/ActiveTBR.java new file mode 100644 index 0000000000..406dd8c8fc --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/ActiveTBR.java @@ -0,0 +1,32 @@ +package info.nightscout.androidaps.plugins.pump.insight.descriptors; + +public class ActiveTBR { + + private int percentage; + private int remainingDuration; + private int initialDuration; + + public int getPercentage() { + return this.percentage; + } + + public int getRemainingDuration() { + return this.remainingDuration; + } + + public int getInitialDuration() { + return this.initialDuration; + } + + public void setPercentage(int percentage) { + this.percentage = percentage; + } + + public void setRemainingDuration(int remainingDuration) { + this.remainingDuration = remainingDuration; + } + + public void setInitialDuration(int initialDuration) { + this.initialDuration = initialDuration; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/Alert.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/Alert.java new file mode 100644 index 0000000000..8f6668c1ca --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/Alert.java @@ -0,0 +1,86 @@ +package info.nightscout.androidaps.plugins.pump.insight.descriptors; + +public class Alert { + + private int alertId; + private AlertCategory alertCategory; + private AlertType alertType; + private AlertStatus alertStatus; + private int tbrAmount; + private int tbrDuration; + private double programmedBolusAmount; + private double deliveredBolusAmount; + private double cartridgeAmount; + + public int getAlertId() { + return this.alertId; + } + + public AlertCategory getAlertCategory() { + return this.alertCategory; + } + + public AlertType getAlertType() { + return this.alertType; + } + + public AlertStatus getAlertStatus() { + return this.alertStatus; + } + + public void setAlertId(int alertId) { + this.alertId = alertId; + } + + public void setAlertCategory(AlertCategory alertCategory) { + this.alertCategory = alertCategory; + } + + public void setAlertType(AlertType alertType) { + this.alertType = alertType; + } + + public void setAlertStatus(AlertStatus alertStatus) { + this.alertStatus = alertStatus; + } + + public int getTBRAmount() { + return tbrAmount; + } + + public void setTBRAmount(int tbrAmount) { + this.tbrAmount = tbrAmount; + } + + public int getTBRDuration() { + return tbrDuration; + } + + public void setTBRDuration(int tbrDuration) { + this.tbrDuration = tbrDuration; + } + + public double getProgrammedBolusAmount() { + return programmedBolusAmount; + } + + public void setProgrammedBolusAmount(double programmedBolusAmount) { + this.programmedBolusAmount = programmedBolusAmount; + } + + public double getDeliveredBolusAmount() { + return deliveredBolusAmount; + } + + public void setDeliveredBolusAmount(double deliveredBolusAmount) { + this.deliveredBolusAmount = deliveredBolusAmount; + } + + public void setCartridgeAmount(double cartridgeAmount) { + this.cartridgeAmount = cartridgeAmount; + } + + public double getCartridgeAmount() { + return cartridgeAmount; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/AlertCategory.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/AlertCategory.java new file mode 100644 index 0000000000..95c39b77a2 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/AlertCategory.java @@ -0,0 +1,9 @@ +package info.nightscout.androidaps.plugins.pump.insight.descriptors; + +public enum AlertCategory { + + REMINDER, + MAINTENANCE, + WARNING, + ERROR +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/AlertStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/AlertStatus.java new file mode 100644 index 0000000000..3b85528462 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/AlertStatus.java @@ -0,0 +1,7 @@ +package info.nightscout.androidaps.plugins.pump.insight.descriptors; + +public enum AlertStatus { + + ACTIVE, + SNOOZED +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/AlertType.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/AlertType.java new file mode 100644 index 0000000000..92a59bd7fc --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/AlertType.java @@ -0,0 +1,31 @@ +package info.nightscout.androidaps.plugins.pump.insight.descriptors; + +public enum AlertType { + + REMINDER_01, + REMINDER_02, + REMINDER_03, + REMINDER_04, + REMINDER_07, + WARNING_31, + WARNING_32, + WARNING_33, + WARNING_34, + WARNING_36, + WARNING_38, + WARNING_39, + MAINTENANCE_20, + MAINTENANCE_21, + MAINTENANCE_22, + MAINTENANCE_23, + MAINTENANCE_24, + MAINTENANCE_25, + MAINTENANCE_26, + MAINTENANCE_27, + MAINTENANCE_28, + MAINTENANCE_29, + MAINTENANCE_30, + ERROR_6, + ERROR_10, + ERROR_13 +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/AvailableBolusTypes.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/AvailableBolusTypes.java new file mode 100644 index 0000000000..cbe6646212 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/AvailableBolusTypes.java @@ -0,0 +1,45 @@ +package info.nightscout.androidaps.plugins.pump.insight.descriptors; + +public class AvailableBolusTypes { + + private boolean standardAvailable; + private boolean extendedAvailable; + private boolean multiwaveAvailable; + + public boolean isStandardAvailable() { + return this.standardAvailable; + } + + public void setStandardAvailable(boolean standardAvailable) { + this.standardAvailable = standardAvailable; + } + + public boolean isExtendedAvailable() { + return this.extendedAvailable; + } + + public void setExtendedAvailable(boolean extendedAvailable) { + this.extendedAvailable = extendedAvailable; + } + + public boolean isMultiwaveAvailable() { + return this.multiwaveAvailable; + } + + public void setMultiwaveAvailable(boolean multiwaveAvailable) { + this.multiwaveAvailable = multiwaveAvailable; + } + + public boolean isBolusTypeAvailable(BolusType bolusType) { + switch (bolusType) { + case STANDARD: + return standardAvailable; + case EXTENDED: + return extendedAvailable; + case MULTIWAVE: + return multiwaveAvailable; + default: + return false; + } + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/BasalProfile.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/BasalProfile.java new file mode 100644 index 0000000000..298c2957dc --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/BasalProfile.java @@ -0,0 +1,10 @@ +package info.nightscout.androidaps.plugins.pump.insight.descriptors; + +public enum BasalProfile { + + PROFILE_1, + PROFILE_2, + PROFILE_3, + PROFILE_4, + PROFILE_5 +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/BasalProfileBlock.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/BasalProfileBlock.java new file mode 100644 index 0000000000..bc70691d59 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/BasalProfileBlock.java @@ -0,0 +1,23 @@ +package info.nightscout.androidaps.plugins.pump.insight.descriptors; + +public class BasalProfileBlock { + + private int duration; + private double basalAmount; + + public int getDuration() { + return this.duration; + } + + public double getBasalAmount() { + return this.basalAmount; + } + + public void setDuration(int duration) { + this.duration = duration; + } + + public void setBasalAmount(double basalAmount) { + this.basalAmount = basalAmount; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/BatteryStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/BatteryStatus.java new file mode 100644 index 0000000000..f8b33d287d --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/BatteryStatus.java @@ -0,0 +1,32 @@ +package info.nightscout.androidaps.plugins.pump.insight.descriptors; + +public class BatteryStatus { + + private BatteryType batteryType; + private int batteryAmount; + private SymbolStatus symbolStatus; + + public BatteryType getBatteryType() { + return this.batteryType; + } + + public int getBatteryAmount() { + return this.batteryAmount; + } + + public SymbolStatus getSymbolStatus() { + return this.symbolStatus; + } + + public void setBatteryType(BatteryType batteryType) { + this.batteryType = batteryType; + } + + public void setBatteryAmount(int batteryAmount) { + this.batteryAmount = batteryAmount; + } + + public void setSymbolStatus(SymbolStatus symbolStatus) { + this.symbolStatus = symbolStatus; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/BatteryType.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/BatteryType.java new file mode 100644 index 0000000000..e0e1e2b69f --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/BatteryType.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.descriptors; + +public enum BatteryType { + + ALKALI, + LITHIUM, + NI_MH +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/BolusType.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/BolusType.java new file mode 100644 index 0000000000..0625e5d5e7 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/BolusType.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.descriptors; + +public enum BolusType { + + STANDARD, + EXTENDED, + MULTIWAVE +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/CartridgeStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/CartridgeStatus.java new file mode 100644 index 0000000000..5c1edb031d --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/CartridgeStatus.java @@ -0,0 +1,41 @@ +package info.nightscout.androidaps.plugins.pump.insight.descriptors; + +public class CartridgeStatus { + + private boolean inserted; + private CartridgeType cartridgeType; + private SymbolStatus symbolStatus; + private double remainingAmount; + + public boolean isInserted() { + return this.inserted; + } + + public CartridgeType getCartridgeType() { + return this.cartridgeType; + } + + public SymbolStatus getSymbolStatus() { + return this.symbolStatus; + } + + public double getRemainingAmount() { + return this.remainingAmount; + } + + public void setInserted(boolean inserted) { + this.inserted = inserted; + } + + public void setCartridgeType(CartridgeType cartridgeType) { + this.cartridgeType = cartridgeType; + } + + public void setSymbolStatus(SymbolStatus symbolStatus) { + this.symbolStatus = symbolStatus; + } + + public void setRemainingAmount(double remainingAmount) { + this.remainingAmount = remainingAmount; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/CartridgeType.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/CartridgeType.java new file mode 100644 index 0000000000..480e4d2a54 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/CartridgeType.java @@ -0,0 +1,7 @@ +package info.nightscout.androidaps.plugins.pump.insight.descriptors; + +public enum CartridgeType { + + PREFILLED, + SELF_FILLED +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/FirmwareVersions.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/FirmwareVersions.java new file mode 100644 index 0000000000..8930e47a4c --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/FirmwareVersions.java @@ -0,0 +1,95 @@ +package info.nightscout.androidaps.plugins.pump.insight.descriptors; + +public class FirmwareVersions { + + private String releaseSWVersion; + private String uiProcSWVersion; + private String pcProcSWVersion; + private String mdTelProcSWVersion; + private String btInfoPageVersion; + private String safetyProcSWVersion; + private int configIndex; + private int historyIndex; + private int stateIndex; + private int vocabularyIndex; + + public String getReleaseSWVersion() { + return this.releaseSWVersion; + } + + public String getUiProcSWVersion() { + return this.uiProcSWVersion; + } + + public String getPcProcSWVersion() { + return this.pcProcSWVersion; + } + + public String getMdTelProcSWVersion() { + return this.mdTelProcSWVersion; + } + + public String getBtInfoPageVersion() { + return this.btInfoPageVersion; + } + + public String getSafetyProcSWVersion() { + return this.safetyProcSWVersion; + } + + public int getConfigIndex() { + return this.configIndex; + } + + public int getHistoryIndex() { + return this.historyIndex; + } + + public int getStateIndex() { + return this.stateIndex; + } + + public int getVocabularyIndex() { + return this.vocabularyIndex; + } + + public void setReleaseSWVersion(String releaseSWVersion) { + this.releaseSWVersion = releaseSWVersion; + } + + public void setUiProcSWVersion(String uiProcSWVersion) { + this.uiProcSWVersion = uiProcSWVersion; + } + + public void setPcProcSWVersion(String pcProcSWVersion) { + this.pcProcSWVersion = pcProcSWVersion; + } + + public void setMdTelProcSWVersion(String mdTelProcSWVersion) { + this.mdTelProcSWVersion = mdTelProcSWVersion; + } + + public void setBtInfoPageVersion(String btInfoPageVersion) { + this.btInfoPageVersion = btInfoPageVersion; + } + + public void setSafetyProcSWVersion(String safetyProcSWVersion) { + this.safetyProcSWVersion = safetyProcSWVersion; + } + + public void setConfigIndex(int configIndex) { + this.configIndex = configIndex; + } + + public void setHistoryIndex(int historyIndex) { + this.historyIndex = historyIndex; + } + + public void setStateIndex(int stateIndex) { + this.stateIndex = stateIndex; + } + + public void setVocabularyIndex(int vocabularyIndex) { + this.vocabularyIndex = vocabularyIndex; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/InsightState.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/InsightState.java new file mode 100644 index 0000000000..2fe256663b --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/InsightState.java @@ -0,0 +1,22 @@ +package info.nightscout.androidaps.plugins.pump.insight.descriptors; + +public enum InsightState { + + NOT_PAIRED, + DISCONNECTED, + RECOVERING, + CONNECTING, + SATL_CONNECTION_REQUEST, + SATL_KEY_REQUEST, + SATL_VERIFY_DISPLAY_REQUEST, + AWAITING_CODE_CONFIRMATION, + SATL_VERIFY_CONFIRM_REQUEST, + SATL_SYN_REQUEST, + APP_CONNECT_MESSAGE, + APP_BIND_MESSAGE, + APP_ACTIVATE_STATUS_SERVICE, + APP_FIRMWARE_VERSIONS, + APP_ACTIVATE_PARAMETER_SERVICE, + APP_SYSTEM_IDENTIFICATION, + CONNECTED, +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/MessagePriority.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/MessagePriority.java new file mode 100644 index 0000000000..f24846f514 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/MessagePriority.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.descriptors; + +public enum MessagePriority { + + NORMAL, + HIGHER, + HIGHEST +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/OperatingMode.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/OperatingMode.java new file mode 100644 index 0000000000..85500f50df --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/OperatingMode.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.descriptors; + +public enum OperatingMode { + + STARTED, + STOPPED, + PAUSED +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/PumpTime.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/PumpTime.java new file mode 100644 index 0000000000..9188e0d3c8 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/PumpTime.java @@ -0,0 +1,59 @@ +package info.nightscout.androidaps.plugins.pump.insight.descriptors; + +public class PumpTime { + + private int year; + private int month; + private int day; + private int hour; + private int minute; + private int second; + + public int getYear() { + return this.year; + } + + public int getMonth() { + return this.month; + } + + public int getDay() { + return this.day; + } + + public int getHour() { + return this.hour; + } + + public int getMinute() { + return this.minute; + } + + public int getSecond() { + return this.second; + } + + public void setYear(int year) { + this.year = year; + } + + public void setMonth(int month) { + this.month = month; + } + + public void setDay(int day) { + this.day = day; + } + + public void setHour(int hour) { + this.hour = hour; + } + + public void setMinute(int minute) { + this.minute = minute; + } + + public void setSecond(int second) { + this.second = second; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/SymbolStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/SymbolStatus.java new file mode 100644 index 0000000000..b68362692b --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/SymbolStatus.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.descriptors; + +public enum SymbolStatus { + + FULL, + LOW, + EMPTY +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/SystemIdentification.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/SystemIdentification.java new file mode 100644 index 0000000000..540052c0d5 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/SystemIdentification.java @@ -0,0 +1,32 @@ +package info.nightscout.androidaps.plugins.pump.insight.descriptors; + +public class SystemIdentification { + + private String serialNumber; + private long systemIdAppendix; + private String manufacturingDate; + + public String getSerialNumber() { + return this.serialNumber; + } + + public long getSystemIdAppendix() { + return this.systemIdAppendix; + } + + public String getManufacturingDate() { + return this.manufacturingDate; + } + + public void setSerialNumber(String serialNumber) { + this.serialNumber = serialNumber; + } + + public void setSystemIdAppendix(long systemIdAppendix) { + this.systemIdAppendix = systemIdAppendix; + } + + public void setManufacturingDate(String manufacturingDate) { + this.manufacturingDate = manufacturingDate; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/TotalDailyDose.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/TotalDailyDose.java new file mode 100644 index 0000000000..7f197c8cb3 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/descriptors/TotalDailyDose.java @@ -0,0 +1,32 @@ +package info.nightscout.androidaps.plugins.pump.insight.descriptors; + +public class TotalDailyDose { + + private double bolus; + private double basal; + private double bolusAndBasal; + + public double getBolus() { + return this.bolus; + } + + public double getBasal() { + return this.basal; + } + + public double getBolusAndBasal() { + return this.bolusAndBasal; + } + + public void setBolus(double bolus) { + this.bolus = bolus; + } + + public void setBasal(double basal) { + this.basal = basal; + } + + public void setBolusAndBasal(double bolusAndBasal) { + this.bolusAndBasal = bolusAndBasal; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/events/EventLocalInsightUpdateGUI.kt b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/events/EventLocalInsightUpdateGUI.kt new file mode 100644 index 0000000000..d89515fe56 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/events/EventLocalInsightUpdateGUI.kt @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.pump.insight.events + +import info.nightscout.androidaps.events.EventUpdateGui + +class EventLocalInsightUpdateGUI : EventUpdateGui() diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/AppLayerException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/AppLayerException.java new file mode 100644 index 0000000000..aaf9dc695a --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/AppLayerException.java @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions; + +public abstract class AppLayerException extends InsightException { + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/CommandNotSupportedException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/CommandNotSupportedException.java new file mode 100644 index 0000000000..fe950c8bac --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/CommandNotSupportedException.java @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions; + +public class CommandNotSupportedException extends InsightException { + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/ConnectionFailedException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/ConnectionFailedException.java new file mode 100644 index 0000000000..524953f613 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/ConnectionFailedException.java @@ -0,0 +1,14 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions; + +public class ConnectionFailedException extends InsightException { + + private long durationOfConnectionAttempt; + + public ConnectionFailedException(long durationOfConnectionAttempt) { + this.durationOfConnectionAttempt = durationOfConnectionAttempt; + } + + public long getDurationOfConnectionAttempt() { + return durationOfConnectionAttempt; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/ConnectionLostException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/ConnectionLostException.java new file mode 100644 index 0000000000..fc7b517d80 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/ConnectionLostException.java @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions; + +public class ConnectionLostException extends InsightException { + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/DisconnectedException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/DisconnectedException.java new file mode 100644 index 0000000000..fe2fd75d81 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/DisconnectedException.java @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions; + +public class DisconnectedException extends InsightException { + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/IncompatibleAppVersionException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/IncompatibleAppVersionException.java new file mode 100644 index 0000000000..ce6b6edccb --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/IncompatibleAppVersionException.java @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions; + +public class IncompatibleAppVersionException extends AppLayerException { + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/IncompatibleSatlVersionException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/IncompatibleSatlVersionException.java new file mode 100644 index 0000000000..0a28aadb80 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/IncompatibleSatlVersionException.java @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions; + +public class IncompatibleSatlVersionException extends SatlException { + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/InsightException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/InsightException.java new file mode 100644 index 0000000000..4dc4161546 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/InsightException.java @@ -0,0 +1,4 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions; + +public abstract class InsightException extends Exception { +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/InvalidAppCRCException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/InvalidAppCRCException.java new file mode 100644 index 0000000000..643e9589f2 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/InvalidAppCRCException.java @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions; + +public class InvalidAppCRCException extends AppLayerException { + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/InvalidMacTrailerException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/InvalidMacTrailerException.java new file mode 100644 index 0000000000..a3eda3700f --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/InvalidMacTrailerException.java @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions; + +public class InvalidMacTrailerException extends SatlException { + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/InvalidNonceException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/InvalidNonceException.java new file mode 100644 index 0000000000..aedc99df1a --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/InvalidNonceException.java @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions; + +public class InvalidNonceException extends SatlException { + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/InvalidPacketLengthsException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/InvalidPacketLengthsException.java new file mode 100644 index 0000000000..5a4373efbb --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/InvalidPacketLengthsException.java @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions; + +public class InvalidPacketLengthsException extends SatlException { + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/InvalidPreambleException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/InvalidPreambleException.java new file mode 100644 index 0000000000..7a5b4a1dd4 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/InvalidPreambleException.java @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions; + +public class InvalidPreambleException extends SatlException { + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/InvalidSatlCRCException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/InvalidSatlCRCException.java new file mode 100644 index 0000000000..ed6aa30d07 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/InvalidSatlCRCException.java @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions; + +public class InvalidSatlCRCException extends SatlException { + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/InvalidSatlCommandException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/InvalidSatlCommandException.java new file mode 100644 index 0000000000..ccaca09b29 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/InvalidSatlCommandException.java @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions; + +public class InvalidSatlCommandException extends SatlException { + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/ReceivedPacketInInvalidStateException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/ReceivedPacketInInvalidStateException.java new file mode 100644 index 0000000000..63b8c9019e --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/ReceivedPacketInInvalidStateException.java @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions; + +public class ReceivedPacketInInvalidStateException extends InsightException { + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/SatlException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/SatlException.java new file mode 100644 index 0000000000..736e4c1b22 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/SatlException.java @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions; + +public abstract class SatlException extends InsightException { + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/SecondChannelFailedException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/SecondChannelFailedException.java new file mode 100644 index 0000000000..f4eaa259f8 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/SecondChannelFailedException.java @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions; + +public class SecondChannelFailedException extends AppLayerException { + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/SocketCreationFailedException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/SocketCreationFailedException.java new file mode 100644 index 0000000000..589a546a84 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/SocketCreationFailedException.java @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions; + +public class SocketCreationFailedException extends InsightException { + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/TimeoutException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/TimeoutException.java new file mode 100644 index 0000000000..f819bcdacb --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/TimeoutException.java @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions; + +public class TimeoutException extends InsightException { + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/TooChattyPumpException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/TooChattyPumpException.java new file mode 100644 index 0000000000..181d3112d1 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/TooChattyPumpException.java @@ -0,0 +1,4 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions; + +public class TooChattyPumpException extends InsightException { +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/UnknownAppCommandException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/UnknownAppCommandException.java new file mode 100644 index 0000000000..dbe39b56d2 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/UnknownAppCommandException.java @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions; + +public class UnknownAppCommandException extends AppLayerException { + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/UnknownServiceException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/UnknownServiceException.java new file mode 100644 index 0000000000..b119e7b9ca --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/UnknownServiceException.java @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions; + +public class UnknownServiceException extends AppLayerException { + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/AlreadyConnectedException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/AlreadyConnectedException.java new file mode 100644 index 0000000000..65631f3154 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/AlreadyConnectedException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class AlreadyConnectedException extends AppLayerErrorException { + + public AlreadyConnectedException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/AppLayerErrorException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/AppLayerErrorException.java new file mode 100644 index 0000000000..10d5bfea2c --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/AppLayerErrorException.java @@ -0,0 +1,21 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +import info.nightscout.androidaps.plugins.pump.insight.exceptions.AppLayerException; + +public abstract class AppLayerErrorException extends AppLayerException { + + private int errorCode; + + public AppLayerErrorException(int errorCode) { + this.errorCode = errorCode; + } + + @Override + public String getMessage() { + return "Error code: " + errorCode; + } + + public int getErrorCode() { + return errorCode; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/BolusAmountNotInRangeException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/BolusAmountNotInRangeException.java new file mode 100644 index 0000000000..b87989d5f2 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/BolusAmountNotInRangeException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class BolusAmountNotInRangeException extends AppLayerErrorException { + + public BolusAmountNotInRangeException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/BolusDurationNotInRangeException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/BolusDurationNotInRangeException.java new file mode 100644 index 0000000000..4b9eb1ebb1 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/BolusDurationNotInRangeException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class BolusDurationNotInRangeException extends AppLayerErrorException { + + public BolusDurationNotInRangeException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/BolusLagTimeFeatureDisabledException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/BolusLagTimeFeatureDisabledException.java new file mode 100644 index 0000000000..a7050d7c83 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/BolusLagTimeFeatureDisabledException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class BolusLagTimeFeatureDisabledException extends AppLayerErrorException { + + public BolusLagTimeFeatureDisabledException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/BolusTypeAndParameterMismatchException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/BolusTypeAndParameterMismatchException.java new file mode 100644 index 0000000000..8dbc6465b3 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/BolusTypeAndParameterMismatchException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class BolusTypeAndParameterMismatchException extends AppLayerErrorException { + + public BolusTypeAndParameterMismatchException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/CommandExecutionFailedException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/CommandExecutionFailedException.java new file mode 100644 index 0000000000..b7efb4998e --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/CommandExecutionFailedException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class CommandExecutionFailedException extends AppLayerErrorException { + + public CommandExecutionFailedException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/ConfigMemoryAccessException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/ConfigMemoryAccessException.java new file mode 100644 index 0000000000..b822fb0da4 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/ConfigMemoryAccessException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class ConfigMemoryAccessException extends AppLayerErrorException { + + public ConfigMemoryAccessException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/CustomBolusNotConfiguredException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/CustomBolusNotConfiguredException.java new file mode 100644 index 0000000000..8aee22cb66 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/CustomBolusNotConfiguredException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class CustomBolusNotConfiguredException extends AppLayerErrorException { + + public CustomBolusNotConfiguredException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/ImplausiblePortionLengthValueException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/ImplausiblePortionLengthValueException.java new file mode 100644 index 0000000000..1d87fada0f --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/ImplausiblePortionLengthValueException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class ImplausiblePortionLengthValueException extends AppLayerErrorException { + + public ImplausiblePortionLengthValueException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/IncompatibleVersionException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/IncompatibleVersionException.java new file mode 100644 index 0000000000..0d596fc825 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/IncompatibleVersionException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class IncompatibleVersionException extends AppLayerErrorException { + + public IncompatibleVersionException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/InvalidAlertInstanceIdException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/InvalidAlertInstanceIdException.java new file mode 100644 index 0000000000..f35566eb54 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/InvalidAlertInstanceIdException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class InvalidAlertInstanceIdException extends AppLayerErrorException { + + public InvalidAlertInstanceIdException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/InvalidConfigBlockCRCException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/InvalidConfigBlockCRCException.java new file mode 100644 index 0000000000..07834a34bd --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/InvalidConfigBlockCRCException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class InvalidConfigBlockCRCException extends AppLayerErrorException { + + public InvalidConfigBlockCRCException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/InvalidConfigBlockIdException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/InvalidConfigBlockIdException.java new file mode 100644 index 0000000000..e6a3aff909 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/InvalidConfigBlockIdException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class InvalidConfigBlockIdException extends AppLayerErrorException { + + public InvalidConfigBlockIdException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/InvalidConfigBlockLengthException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/InvalidConfigBlockLengthException.java new file mode 100644 index 0000000000..90eb6556c5 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/InvalidConfigBlockLengthException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class InvalidConfigBlockLengthException extends AppLayerErrorException { + + public InvalidConfigBlockLengthException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/InvalidDateParameterException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/InvalidDateParameterException.java new file mode 100644 index 0000000000..a7770859e4 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/InvalidDateParameterException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class InvalidDateParameterException extends AppLayerErrorException { + + public InvalidDateParameterException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/InvalidDurationPresetException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/InvalidDurationPresetException.java new file mode 100644 index 0000000000..0bc787ec58 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/InvalidDurationPresetException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class InvalidDurationPresetException extends AppLayerErrorException { + + public InvalidDurationPresetException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/InvalidLagTimeException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/InvalidLagTimeException.java new file mode 100644 index 0000000000..2f14b1156d --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/InvalidLagTimeException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class InvalidLagTimeException extends AppLayerErrorException { + + public InvalidLagTimeException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/InvalidParameterTypeException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/InvalidParameterTypeException.java new file mode 100644 index 0000000000..37bd17c41a --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/InvalidParameterTypeException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class InvalidParameterTypeException extends AppLayerErrorException { + + public InvalidParameterTypeException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/InvalidPayloadCRCException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/InvalidPayloadCRCException.java new file mode 100644 index 0000000000..5e06eca9d5 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/InvalidPayloadCRCException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class InvalidPayloadCRCException extends AppLayerErrorException { + + public InvalidPayloadCRCException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/InvalidPayloadException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/InvalidPayloadException.java new file mode 100644 index 0000000000..ebb942dc73 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/InvalidPayloadException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class InvalidPayloadException extends AppLayerErrorException { + + public InvalidPayloadException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/InvalidPayloadLengthException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/InvalidPayloadLengthException.java new file mode 100644 index 0000000000..89b519c472 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/InvalidPayloadLengthException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class InvalidPayloadLengthException extends AppLayerErrorException { + + public InvalidPayloadLengthException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/InvalidServicePasswordException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/InvalidServicePasswordException.java new file mode 100644 index 0000000000..be8b41a188 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/InvalidServicePasswordException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class InvalidServicePasswordException extends AppLayerErrorException { + + public InvalidServicePasswordException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/InvalidTBRDurationException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/InvalidTBRDurationException.java new file mode 100644 index 0000000000..d5fa35e4fb --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/InvalidTBRDurationException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class InvalidTBRDurationException extends AppLayerErrorException { + + public InvalidTBRDurationException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/InvalidTBRFactorException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/InvalidTBRFactorException.java new file mode 100644 index 0000000000..d27b0172b9 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/InvalidTBRFactorException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class InvalidTBRFactorException extends AppLayerErrorException { + + public InvalidTBRFactorException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/InvalidTBRTemplateException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/InvalidTBRTemplateException.java new file mode 100644 index 0000000000..d8f5c6f8d4 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/InvalidTBRTemplateException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class InvalidTBRTemplateException extends AppLayerErrorException { + + public InvalidTBRTemplateException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/InvalidTimeParameterException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/InvalidTimeParameterException.java new file mode 100644 index 0000000000..2170adc8af --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/InvalidTimeParameterException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class InvalidTimeParameterException extends AppLayerErrorException { + + public InvalidTimeParameterException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/InvalidValuesOfTwoChannelTransmission.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/InvalidValuesOfTwoChannelTransmission.java new file mode 100644 index 0000000000..8b51c6bf6e --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/InvalidValuesOfTwoChannelTransmission.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class InvalidValuesOfTwoChannelTransmission extends AppLayerErrorException { + + public InvalidValuesOfTwoChannelTransmission(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/MaximumNumberOfBolusTypeAlreadyRunningException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/MaximumNumberOfBolusTypeAlreadyRunningException.java new file mode 100644 index 0000000000..917b715a05 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/MaximumNumberOfBolusTypeAlreadyRunningException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class MaximumNumberOfBolusTypeAlreadyRunningException extends AppLayerErrorException { + + public MaximumNumberOfBolusTypeAlreadyRunningException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/NoActiveTBRToCanceLException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/NoActiveTBRToCanceLException.java new file mode 100644 index 0000000000..178a551896 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/NoActiveTBRToCanceLException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class NoActiveTBRToCanceLException extends AppLayerErrorException { + + public NoActiveTBRToCanceLException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/NoActiveTBRToChangeException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/NoActiveTBRToChangeException.java new file mode 100644 index 0000000000..63811f59e2 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/NoActiveTBRToChangeException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class NoActiveTBRToChangeException extends AppLayerErrorException { + + public NoActiveTBRToChangeException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/NoConfigBlockDataException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/NoConfigBlockDataException.java new file mode 100644 index 0000000000..1a3b1dfc3b --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/NoConfigBlockDataException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class NoConfigBlockDataException extends AppLayerErrorException { + + public NoConfigBlockDataException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/NoServicePasswordNeededException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/NoServicePasswordNeededException.java new file mode 100644 index 0000000000..72f4d4bd89 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/NoServicePasswordNeededException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class NoServicePasswordNeededException extends AppLayerErrorException { + + public NoServicePasswordNeededException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/NoSuchBolusToCancelException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/NoSuchBolusToCancelException.java new file mode 100644 index 0000000000..d3532d0dde --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/NoSuchBolusToCancelException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class NoSuchBolusToCancelException extends AppLayerErrorException { + + public NoSuchBolusToCancelException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/NotAllowedToAccessPositionZeroException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/NotAllowedToAccessPositionZeroException.java new file mode 100644 index 0000000000..758d80d216 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/NotAllowedToAccessPositionZeroException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class NotAllowedToAccessPositionZeroException extends AppLayerErrorException { + + public NotAllowedToAccessPositionZeroException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/NotConnectedException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/NotConnectedException.java new file mode 100644 index 0000000000..a0b47aa4da --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/NotConnectedException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class NotConnectedException extends AppLayerErrorException { + + public NotConnectedException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/NotReferencedException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/NotReferencedException.java new file mode 100644 index 0000000000..f2469d1ffe --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/NotReferencedException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class NotReferencedException extends AppLayerErrorException { + + public NotReferencedException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/PauseModeNotAllowedException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/PauseModeNotAllowedException.java new file mode 100644 index 0000000000..6da528ac27 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/PauseModeNotAllowedException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class PauseModeNotAllowedException extends AppLayerErrorException { + + public PauseModeNotAllowedException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/PositionProtectedException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/PositionProtectedException.java new file mode 100644 index 0000000000..7670eb6fb8 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/PositionProtectedException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class PositionProtectedException extends AppLayerErrorException { + + public PositionProtectedException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/PumpAlreadyInThatStateException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/PumpAlreadyInThatStateException.java new file mode 100644 index 0000000000..574efb065b --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/PumpAlreadyInThatStateException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class PumpAlreadyInThatStateException extends AppLayerErrorException { + + public PumpAlreadyInThatStateException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/PumpBusyException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/PumpBusyException.java new file mode 100644 index 0000000000..4d7fe90b43 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/PumpBusyException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class PumpBusyException extends AppLayerErrorException { + + public PumpBusyException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/PumpStoppedException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/PumpStoppedException.java new file mode 100644 index 0000000000..31aae38bb0 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/PumpStoppedException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class PumpStoppedException extends AppLayerErrorException { + + public PumpStoppedException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/ReadingHistoryAlreadyStartedException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/ReadingHistoryAlreadyStartedException.java new file mode 100644 index 0000000000..9091c8b999 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/ReadingHistoryAlreadyStartedException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class ReadingHistoryAlreadyStartedException extends AppLayerErrorException { + + public ReadingHistoryAlreadyStartedException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/ReadingHistoryNotStartedException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/ReadingHistoryNotStartedException.java new file mode 100644 index 0000000000..2a37f62b39 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/ReadingHistoryNotStartedException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class ReadingHistoryNotStartedException extends AppLayerErrorException { + + public ReadingHistoryNotStartedException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/RunModeNotAllowedException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/RunModeNotAllowedException.java new file mode 100644 index 0000000000..262e41ae21 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/RunModeNotAllowedException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class RunModeNotAllowedException extends AppLayerErrorException { + + public RunModeNotAllowedException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/ServiceAlreadyActivatedException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/ServiceAlreadyActivatedException.java new file mode 100644 index 0000000000..4865697483 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/ServiceAlreadyActivatedException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class ServiceAlreadyActivatedException extends AppLayerErrorException { + + public ServiceAlreadyActivatedException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/ServiceCommandNotAvailableException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/ServiceCommandNotAvailableException.java new file mode 100644 index 0000000000..7341cc67a9 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/ServiceCommandNotAvailableException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class ServiceCommandNotAvailableException extends AppLayerErrorException { + + public ServiceCommandNotAvailableException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/ServiceIncompatibleException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/ServiceIncompatibleException.java new file mode 100644 index 0000000000..4c3fc8b1dc --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/ServiceIncompatibleException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class ServiceIncompatibleException extends AppLayerErrorException { + + public ServiceIncompatibleException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/ServiceNotActivatedException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/ServiceNotActivatedException.java new file mode 100644 index 0000000000..55329a2a5b --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/ServiceNotActivatedException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class ServiceNotActivatedException extends AppLayerErrorException { + + public ServiceNotActivatedException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/StepCountOutOfRangeException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/StepCountOutOfRangeException.java new file mode 100644 index 0000000000..cb1a04fe74 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/StepCountOutOfRangeException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class StepCountOutOfRangeException extends AppLayerErrorException { + + public StepCountOutOfRangeException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/UnknownAppLayerErrorCodeException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/UnknownAppLayerErrorCodeException.java new file mode 100644 index 0000000000..4c08240102 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/UnknownAppLayerErrorCodeException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class UnknownAppLayerErrorCodeException extends AppLayerErrorException { + + public UnknownAppLayerErrorCodeException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/UnknownCommandException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/UnknownCommandException.java new file mode 100644 index 0000000000..edf06628dd --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/UnknownCommandException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class UnknownCommandException extends AppLayerErrorException { + + public UnknownCommandException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/UnknownServiceException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/UnknownServiceException.java new file mode 100644 index 0000000000..2992372e18 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/UnknownServiceException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class UnknownServiceException extends AppLayerErrorException { + + public UnknownServiceException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/WriteSessionAlreadyOpenException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/WriteSessionAlreadyOpenException.java new file mode 100644 index 0000000000..b4001d2f06 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/WriteSessionAlreadyOpenException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class WriteSessionAlreadyOpenException extends AppLayerErrorException { + + public WriteSessionAlreadyOpenException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/WriteSessionClosedException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/WriteSessionClosedException.java new file mode 100644 index 0000000000..966afecb68 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/WriteSessionClosedException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class WriteSessionClosedException extends AppLayerErrorException { + + public WriteSessionClosedException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/WrongStateException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/WrongStateException.java new file mode 100644 index 0000000000..b4cc3af99e --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/app_layer_errors/WrongStateException.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors; + +public class WrongStateException extends AppLayerErrorException { + + public WrongStateException(int errorCode) { + super(errorCode); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/satl_errors/SatlCompatibleStateErrorException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/satl_errors/SatlCompatibleStateErrorException.java new file mode 100644 index 0000000000..fde27a8f5f --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/satl_errors/SatlCompatibleStateErrorException.java @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.satl_errors; + +public class SatlCompatibleStateErrorException extends SatlErrorException { + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/satl_errors/SatlDecryptVerifyFailedErrorException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/satl_errors/SatlDecryptVerifyFailedErrorException.java new file mode 100644 index 0000000000..74a68dc2ce --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/satl_errors/SatlDecryptVerifyFailedErrorException.java @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.satl_errors; + +public class SatlDecryptVerifyFailedErrorException extends SatlErrorException { + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/satl_errors/SatlErrorException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/satl_errors/SatlErrorException.java new file mode 100644 index 0000000000..26dc0e2719 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/satl_errors/SatlErrorException.java @@ -0,0 +1,7 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.satl_errors; + +import info.nightscout.androidaps.plugins.pump.insight.exceptions.InsightException; + +public abstract class SatlErrorException extends InsightException { + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/satl_errors/SatlIncompatibleVersionErrorException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/satl_errors/SatlIncompatibleVersionErrorException.java new file mode 100644 index 0000000000..df152adf83 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/satl_errors/SatlIncompatibleVersionErrorException.java @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.satl_errors; + +public class SatlIncompatibleVersionErrorException extends SatlErrorException { + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/satl_errors/SatlInvalidCRCErrorException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/satl_errors/SatlInvalidCRCErrorException.java new file mode 100644 index 0000000000..2156bc48a0 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/satl_errors/SatlInvalidCRCErrorException.java @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.satl_errors; + +public class SatlInvalidCRCErrorException extends SatlErrorException { + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/satl_errors/SatlInvalidCommIdErrorException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/satl_errors/SatlInvalidCommIdErrorException.java new file mode 100644 index 0000000000..12e9ca7bb4 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/satl_errors/SatlInvalidCommIdErrorException.java @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.satl_errors; + +public class SatlInvalidCommIdErrorException extends SatlErrorException { + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/satl_errors/SatlInvalidMacErrorException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/satl_errors/SatlInvalidMacErrorException.java new file mode 100644 index 0000000000..75f547ef15 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/satl_errors/SatlInvalidMacErrorException.java @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.satl_errors; + +public class SatlInvalidMacErrorException extends SatlErrorException { + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/satl_errors/SatlInvalidMessageTypeErrorException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/satl_errors/SatlInvalidMessageTypeErrorException.java new file mode 100644 index 0000000000..6551a28c8f --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/satl_errors/SatlInvalidMessageTypeErrorException.java @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.satl_errors; + +public class SatlInvalidMessageTypeErrorException extends SatlErrorException { + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/satl_errors/SatlInvalidNonceErrorException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/satl_errors/SatlInvalidNonceErrorException.java new file mode 100644 index 0000000000..8f9304c3c0 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/satl_errors/SatlInvalidNonceErrorException.java @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.satl_errors; + +public class SatlInvalidNonceErrorException extends SatlErrorException { + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/satl_errors/SatlInvalidPacketErrorException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/satl_errors/SatlInvalidPacketErrorException.java new file mode 100644 index 0000000000..ed3f50e98b --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/satl_errors/SatlInvalidPacketErrorException.java @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.satl_errors; + +public class SatlInvalidPacketErrorException extends SatlErrorException { + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/satl_errors/SatlInvalidPayloadLengthErrorException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/satl_errors/SatlInvalidPayloadLengthErrorException.java new file mode 100644 index 0000000000..69646f265c --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/satl_errors/SatlInvalidPayloadLengthErrorException.java @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.satl_errors; + +public class SatlInvalidPayloadLengthErrorException extends SatlErrorException { + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/satl_errors/SatlNoneErrorException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/satl_errors/SatlNoneErrorException.java new file mode 100644 index 0000000000..febe6a8ced --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/satl_errors/SatlNoneErrorException.java @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.satl_errors; + +public class SatlNoneErrorException extends SatlErrorException { + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/satl_errors/SatlPairingRejectedException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/satl_errors/SatlPairingRejectedException.java new file mode 100644 index 0000000000..479efd150d --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/satl_errors/SatlPairingRejectedException.java @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.satl_errors; + +public class SatlPairingRejectedException extends SatlErrorException { + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/satl_errors/SatlUndefinedErrorException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/satl_errors/SatlUndefinedErrorException.java new file mode 100644 index 0000000000..f655c8668d --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/satl_errors/SatlUndefinedErrorException.java @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.satl_errors; + +public class SatlUndefinedErrorException extends SatlErrorException { + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/satl_errors/SatlWrongStateException.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/satl_errors/SatlWrongStateException.java new file mode 100644 index 0000000000..aa50c46ec9 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/exceptions/satl_errors/SatlWrongStateException.java @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.pump.insight.exceptions.satl_errors; + +public class SatlWrongStateException extends SatlErrorException { + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/ActiveBasalProfileIDs.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/ActiveBasalProfileIDs.java new file mode 100644 index 0000000000..9d5a6e1f85 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/ActiveBasalProfileIDs.java @@ -0,0 +1,18 @@ +package info.nightscout.androidaps.plugins.pump.insight.ids; + +import info.nightscout.androidaps.plugins.pump.insight.descriptors.BasalProfile; +import info.nightscout.androidaps.plugins.pump.insight.utils.IDStorage; + +public class ActiveBasalProfileIDs { + + public static final IDStorage IDS = new IDStorage<>(); + + static { + IDS.put(BasalProfile.PROFILE_1, 31); + IDS.put(BasalProfile.PROFILE_2, 227); + IDS.put(BasalProfile.PROFILE_3, 252); + IDS.put(BasalProfile.PROFILE_4, 805); + IDS.put(BasalProfile.PROFILE_5, 826); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/ActiveBolusTypeIDs.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/ActiveBolusTypeIDs.java new file mode 100644 index 0000000000..f04e7ddbbc --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/ActiveBolusTypeIDs.java @@ -0,0 +1,16 @@ +package info.nightscout.androidaps.plugins.pump.insight.ids; + +import info.nightscout.androidaps.plugins.pump.insight.descriptors.BolusType; +import info.nightscout.androidaps.plugins.pump.insight.utils.IDStorage; + +public class ActiveBolusTypeIDs { + + public static final IDStorage IDS = new IDStorage<>(); + + static { + IDS.put(BolusType.STANDARD, 227); + IDS.put(BolusType.EXTENDED, 252); + IDS.put(BolusType.MULTIWAVE, 805); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/AlertCategoryIDs.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/AlertCategoryIDs.java new file mode 100644 index 0000000000..59a02b36d3 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/AlertCategoryIDs.java @@ -0,0 +1,17 @@ +package info.nightscout.androidaps.plugins.pump.insight.ids; + +import info.nightscout.androidaps.plugins.pump.insight.descriptors.AlertCategory; +import info.nightscout.androidaps.plugins.pump.insight.utils.IDStorage; + +public class AlertCategoryIDs { + + public static final IDStorage IDS = new IDStorage<>(); + + static { + IDS.put(AlertCategory.REMINDER, 227); + IDS.put(AlertCategory.MAINTENANCE, 252); + IDS.put(AlertCategory.WARNING, 805); + IDS.put(AlertCategory.ERROR, 826); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/AlertStatusIDs.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/AlertStatusIDs.java new file mode 100644 index 0000000000..b249dfded2 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/AlertStatusIDs.java @@ -0,0 +1,15 @@ +package info.nightscout.androidaps.plugins.pump.insight.ids; + +import info.nightscout.androidaps.plugins.pump.insight.descriptors.AlertStatus; +import info.nightscout.androidaps.plugins.pump.insight.utils.IDStorage; + +public class AlertStatusIDs { + + public static final IDStorage IDS = new IDStorage<>(); + + static { + IDS.put(AlertStatus.ACTIVE, 31); + IDS.put(AlertStatus.SNOOZED, 227); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/AlertTypeIDs.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/AlertTypeIDs.java new file mode 100644 index 0000000000..0688fb6cf2 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/AlertTypeIDs.java @@ -0,0 +1,39 @@ +package info.nightscout.androidaps.plugins.pump.insight.ids; + +import info.nightscout.androidaps.plugins.pump.insight.descriptors.AlertType; +import info.nightscout.androidaps.plugins.pump.insight.utils.IDStorage; + +public class AlertTypeIDs { + + public static final IDStorage IDS = new IDStorage<>(); + + static { + IDS.put(AlertType.REMINDER_01, 31); + IDS.put(AlertType.REMINDER_02, 227); + IDS.put(AlertType.REMINDER_03, 252); + IDS.put(AlertType.REMINDER_04, 805); + IDS.put(AlertType.REMINDER_07, 826); + IDS.put(AlertType.WARNING_31, 966); + IDS.put(AlertType.WARNING_32, 985); + IDS.put(AlertType.WARNING_33, 1354); + IDS.put(AlertType.WARNING_34, 1365); + IDS.put(AlertType.WARNING_36, 1449); + IDS.put(AlertType.WARNING_38, 1462); + IDS.put(AlertType.WARNING_39, 1647); + IDS.put(AlertType.MAINTENANCE_20, 1648); + IDS.put(AlertType.MAINTENANCE_21, 1676); + IDS.put(AlertType.MAINTENANCE_22, 1683); + IDS.put(AlertType.MAINTENANCE_23, 6182); + IDS.put(AlertType.MAINTENANCE_24, 6201); + IDS.put(AlertType.MAINTENANCE_25, 6341); + IDS.put(AlertType.MAINTENANCE_26, 6362); + IDS.put(AlertType.MAINTENANCE_27, 6915); + IDS.put(AlertType.MAINTENANCE_28, 6940); + IDS.put(AlertType.MAINTENANCE_29, 7136); + IDS.put(AlertType.MAINTENANCE_30, 7167); + IDS.put(AlertType.ERROR_6, 7532); + IDS.put(AlertType.ERROR_10, 7539); + IDS.put(AlertType.ERROR_13, 7567); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/AlertTypeIncrementalIDs.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/AlertTypeIncrementalIDs.java new file mode 100644 index 0000000000..340648b8c7 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/AlertTypeIncrementalIDs.java @@ -0,0 +1,39 @@ +package info.nightscout.androidaps.plugins.pump.insight.ids; + +import info.nightscout.androidaps.plugins.pump.insight.descriptors.AlertType; +import info.nightscout.androidaps.plugins.pump.insight.utils.IDStorage; + +public class AlertTypeIncrementalIDs { + + public static final IDStorage IDS = new IDStorage<>(); + + static { + IDS.put(AlertType.REMINDER_01, 1); + IDS.put(AlertType.REMINDER_02, 2); + IDS.put(AlertType.REMINDER_03, 3); + IDS.put(AlertType.REMINDER_04, 4); + IDS.put(AlertType.REMINDER_07, 7); + IDS.put(AlertType.WARNING_31, 31); + IDS.put(AlertType.WARNING_32, 32); + IDS.put(AlertType.WARNING_33, 33); + IDS.put(AlertType.WARNING_34, 34); + IDS.put(AlertType.WARNING_36, 36); + IDS.put(AlertType.WARNING_38, 38); + IDS.put(AlertType.WARNING_39, 39); + IDS.put(AlertType.MAINTENANCE_20, 20); + IDS.put(AlertType.MAINTENANCE_21, 21); + IDS.put(AlertType.MAINTENANCE_22, 22); + IDS.put(AlertType.MAINTENANCE_23, 23); + IDS.put(AlertType.MAINTENANCE_24, 24); + IDS.put(AlertType.MAINTENANCE_25, 25); + IDS.put(AlertType.MAINTENANCE_26, 26); + IDS.put(AlertType.MAINTENANCE_27, 27); + IDS.put(AlertType.MAINTENANCE_28, 28); + IDS.put(AlertType.MAINTENANCE_29, 29); + IDS.put(AlertType.MAINTENANCE_30, 30); + IDS.put(AlertType.ERROR_6, 6); + IDS.put(AlertType.ERROR_10, 10); + IDS.put(AlertType.ERROR_13, 13); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/AppCommandIDs.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/AppCommandIDs.java new file mode 100644 index 0000000000..da52987a1f --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/AppCommandIDs.java @@ -0,0 +1,81 @@ +package info.nightscout.androidaps.plugins.pump.insight.ids; + +import info.nightscout.androidaps.plugins.pump.insight.app_layer.AppLayerMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.remote_control.SetDateTimeMessage; +import info.nightscout.androidaps.plugins.pump.insight.utils.IDStorage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.ReadParameterBlockMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.configuration.CloseConfigurationWriteSessionMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.configuration.OpenConfigurationWriteSessionMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.configuration.WriteConfigurationBlockMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.connection.ActivateServiceMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.connection.BindMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.connection.ConnectMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.connection.DisconnectMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.connection.ServiceChallengeMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.history.ReadHistoryEventsMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.history.StartReadingHistoryMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.history.StopReadingHistoryMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.remote_control.CancelBolusMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.remote_control.CancelTBRMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.remote_control.ChangeTBRMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.remote_control.ConfirmAlertMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.remote_control.DeliverBolusMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.remote_control.GetAvailableBolusTypesMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.remote_control.SetOperatingModeMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.remote_control.SetTBRMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.remote_control.SnoozeAlertMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.status.GetActiveAlertMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.status.GetActiveBasalRateMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.status.GetActiveBolusesMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.status.GetActiveTBRMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.status.GetBatteryStatusMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.status.GetCartridgeStatusMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.status.GetDateTimeMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.status.GetFirmwareVersionsMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.status.GetOperatingModeMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.status.GetPumpStatusRegisterMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.status.GetTotalDailyDoseMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.status.ResetPumpStatusRegisterMessage; + +public class AppCommandIDs { + + public static final IDStorage, Integer> IDS = new IDStorage<>(); + + static { + IDS.put(ConnectMessage.class, 61451); + IDS.put(BindMessage.class, 62413); + IDS.put(DisconnectMessage.class, 61460); + IDS.put(ActivateServiceMessage.class, 61687); + IDS.put(ServiceChallengeMessage.class, 62418); + IDS.put(GetActiveAlertMessage.class, 985); + IDS.put(GetActiveBolusesMessage.class, 1647); + IDS.put(GetActiveTBRMessage.class, 1462); + IDS.put(GetAvailableBolusTypesMessage.class, 6362); + IDS.put(GetBatteryStatusMessage.class, 805); + IDS.put(GetCartridgeStatusMessage.class, 826); + IDS.put(GetDateTimeMessage.class, 227); + IDS.put(GetFirmwareVersionsMessage.class, 11992); + IDS.put(GetOperatingModeMessage.class, 252); + IDS.put(GetPumpStatusRegisterMessage.class, 31); + IDS.put(ResetPumpStatusRegisterMessage.class, 35476); + IDS.put(GetActiveBasalRateMessage.class, 1449); + IDS.put(GetTotalDailyDoseMessage.class, 966); + IDS.put(CancelTBRMessage.class, 6201); + IDS.put(CancelBolusMessage.class, 7136); + IDS.put(SetOperatingModeMessage.class, 6182); + IDS.put(ReadParameterBlockMessage.class, 7766); + IDS.put(WriteConfigurationBlockMessage.class, 7850); + IDS.put(CloseConfigurationWriteSessionMessage.class, 7861); + IDS.put(OpenConfigurationWriteSessionMessage.class, 7753); + IDS.put(DeliverBolusMessage.class, 6915); + IDS.put(SetTBRMessage.class, 6341); + IDS.put(ChangeTBRMessage.class, 42067); + IDS.put(ReadHistoryEventsMessage.class, 10408); + IDS.put(StartReadingHistoryMessage.class, 10324); + IDS.put(StopReadingHistoryMessage.class, 38887); + IDS.put(ConfirmAlertMessage.class, 1683); + IDS.put(SnoozeAlertMessage.class, 1676); + IDS.put(SetDateTimeMessage.class, 7167); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/AppErrorIDs.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/AppErrorIDs.java new file mode 100644 index 0000000000..a06a18c56d --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/AppErrorIDs.java @@ -0,0 +1,121 @@ +package info.nightscout.androidaps.plugins.pump.insight.ids; + +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.AlreadyConnectedException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.AppLayerErrorException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.BolusAmountNotInRangeException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.BolusDurationNotInRangeException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.BolusLagTimeFeatureDisabledException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.BolusTypeAndParameterMismatchException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.CommandExecutionFailedException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.ConfigMemoryAccessException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.CustomBolusNotConfiguredException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.ImplausiblePortionLengthValueException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.IncompatibleVersionException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.InvalidAlertInstanceIdException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.InvalidConfigBlockCRCException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.InvalidConfigBlockIdException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.InvalidConfigBlockLengthException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.InvalidDateParameterException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.InvalidDurationPresetException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.InvalidLagTimeException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.InvalidParameterTypeException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.InvalidPayloadCRCException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.InvalidPayloadException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.InvalidPayloadLengthException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.InvalidServicePasswordException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.InvalidTBRDurationException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.InvalidTBRFactorException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.InvalidTBRTemplateException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.InvalidTimeParameterException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.InvalidValuesOfTwoChannelTransmission; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.MaximumNumberOfBolusTypeAlreadyRunningException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.NoActiveTBRToCanceLException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.NoActiveTBRToChangeException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.NoConfigBlockDataException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.NoServicePasswordNeededException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.NoSuchBolusToCancelException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.NotAllowedToAccessPositionZeroException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.NotConnectedException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.NotReferencedException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.PauseModeNotAllowedException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.PositionProtectedException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.PumpAlreadyInThatStateException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.PumpBusyException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.PumpStoppedException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.ReadingHistoryAlreadyStartedException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.ReadingHistoryNotStartedException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.RunModeNotAllowedException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.ServiceAlreadyActivatedException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.ServiceCommandNotAvailableException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.ServiceIncompatibleException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.ServiceNotActivatedException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.StepCountOutOfRangeException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.UnknownCommandException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.UnknownServiceException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.WriteSessionAlreadyOpenException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.WriteSessionClosedException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.WrongStateException; +import info.nightscout.androidaps.plugins.pump.insight.utils.IDStorage; + +public class AppErrorIDs { + + public static final IDStorage, Integer> IDS = new IDStorage<>(); + + static { + IDS.put(PumpStoppedException.class, 3178); + IDS.put(BolusAmountNotInRangeException.class, 6017); + IDS.put(PumpAlreadyInThatStateException.class, 3324); + IDS.put(InvalidServicePasswordException.class, 61593); + IDS.put(UnknownCommandException.class, 61455); + IDS.put(AlreadyConnectedException.class, 61530); + IDS.put(WrongStateException.class, 61680); + IDS.put(ServiceIncompatibleException.class, 61542); + IDS.put(UnknownServiceException.class, 61545); + IDS.put(NoServicePasswordNeededException.class, 61695); + IDS.put(ServiceAlreadyActivatedException.class, 61644); + IDS.put(IncompatibleVersionException.class, 61491); + IDS.put(InvalidPayloadLengthException.class, 61500); + IDS.put(NotConnectedException.class, 61525); + IDS.put(ServiceCommandNotAvailableException.class, 61605); + IDS.put(ServiceNotActivatedException.class, 61610); + IDS.put(PumpBusyException.class, 61635); + IDS.put(NotReferencedException.class, 5335); + IDS.put(StepCountOutOfRangeException.class, 5348); + IDS.put(InvalidPayloadCRCException.class, 2805); + IDS.put(InvalidParameterTypeException.class, 2810); + IDS.put(CommandExecutionFailedException.class, 22796); + IDS.put(InvalidAlertInstanceIdException.class, 3238); + IDS.put(InvalidTBRFactorException.class, 3241); + IDS.put(InvalidTBRDurationException.class, 3264); + IDS.put(InvalidTBRTemplateException.class, 6363); + IDS.put(PauseModeNotAllowedException.class, 3315); + IDS.put(RunModeNotAllowedException.class, 3279); + IDS.put(NoActiveTBRToCanceLException.class, 3840); + IDS.put(BolusTypeAndParameterMismatchException.class, 3925); + IDS.put(InvalidDurationPresetException.class, 5924); + IDS.put(BolusLagTimeFeatureDisabledException.class, 90); + IDS.put(BolusDurationNotInRangeException.class, 6014); + IDS.put(InvalidValuesOfTwoChannelTransmission.class, 0x0F96); + IDS.put(NoSuchBolusToCancelException.class, 4005); + IDS.put(MaximumNumberOfBolusTypeAlreadyRunningException.class, 4010); + IDS.put(CustomBolusNotConfiguredException.class, 6270); + IDS.put(InvalidDateParameterException.class, 4044); + IDS.put(InvalidTimeParameterException.class, 4080); + IDS.put(NoConfigBlockDataException.class, 4471); + IDS.put(InvalidConfigBlockIdException.class, 4472); + IDS.put(InvalidConfigBlockCRCException.class, 4487); + IDS.put(InvalidConfigBlockLengthException.class, 6286); + IDS.put(WriteSessionAlreadyOpenException.class, 4539); + IDS.put(WriteSessionClosedException.class, 4562); + IDS.put(ConfigMemoryAccessException.class, 4573); + IDS.put(ReadingHistoryAlreadyStartedException.class, 11794); + IDS.put(ReadingHistoryNotStartedException.class, 4680); + IDS.put(InvalidPayloadException.class, 6210); + IDS.put(ImplausiblePortionLengthValueException.class, 4824); + IDS.put(NotAllowedToAccessPositionZeroException.class, 4830); + IDS.put(PositionProtectedException.class, 4845); + IDS.put(InvalidLagTimeException.class, 3891); + IDS.put(NoActiveTBRToChangeException.class, 6322); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/BatteryTypeIDs.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/BatteryTypeIDs.java new file mode 100644 index 0000000000..9485da4a55 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/BatteryTypeIDs.java @@ -0,0 +1,16 @@ +package info.nightscout.androidaps.plugins.pump.insight.ids; + +import info.nightscout.androidaps.plugins.pump.insight.descriptors.BatteryType; +import info.nightscout.androidaps.plugins.pump.insight.utils.IDStorage; + +public class BatteryTypeIDs { + + public static final IDStorage IDS = new IDStorage<>(); + + static { + IDS.put(BatteryType.ALKALI, 31); + IDS.put(BatteryType.LITHIUM, 227); + IDS.put(BatteryType.NI_MH, 252); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/BolusTypeIDs.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/BolusTypeIDs.java new file mode 100644 index 0000000000..6917f82e9f --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/BolusTypeIDs.java @@ -0,0 +1,16 @@ +package info.nightscout.androidaps.plugins.pump.insight.ids; + +import info.nightscout.androidaps.plugins.pump.insight.descriptors.BolusType; +import info.nightscout.androidaps.plugins.pump.insight.utils.IDStorage; + +public class BolusTypeIDs { + + public static final IDStorage IDS = new IDStorage<>(); + + static { + IDS.put(BolusType.STANDARD, 31); + IDS.put(BolusType.EXTENDED, 227); + IDS.put(BolusType.MULTIWAVE, 252); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/CartridgeTypeIDs.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/CartridgeTypeIDs.java new file mode 100644 index 0000000000..9d48d8cdb2 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/CartridgeTypeIDs.java @@ -0,0 +1,15 @@ +package info.nightscout.androidaps.plugins.pump.insight.ids; + +import info.nightscout.androidaps.plugins.pump.insight.descriptors.CartridgeType; +import info.nightscout.androidaps.plugins.pump.insight.utils.IDStorage; + +public class CartridgeTypeIDs { + + public static final IDStorage IDS = new IDStorage<>(); + + static { + IDS.put(CartridgeType.PREFILLED, 31); + IDS.put(CartridgeType.SELF_FILLED, 227); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/HistoryEventIDs.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/HistoryEventIDs.java new file mode 100644 index 0000000000..407f132aa1 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/HistoryEventIDs.java @@ -0,0 +1,51 @@ +package info.nightscout.androidaps.plugins.pump.insight.ids; + +import info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events.BasalDeliveryChangedEvent; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events.BolusDeliveredEvent; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events.BolusProgrammedEvent; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events.CannulaFilledEvent; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events.CartridgeInsertedEvent; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events.CartridgeRemovedEvent; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events.DateTimeChangedEvent; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events.DefaultDateTimeSetEvent; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events.EndOfTBREvent; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events.HistoryEvent; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events.OccurrenceOfErrorEvent; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events.OccurrenceOfMaintenanceEvent; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events.OccurrenceOfWarningEvent; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events.OperatingModeChangedEvent; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events.PowerDownEvent; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events.PowerUpEvent; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events.SniffingDoneEvent; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events.StartOfTBREvent; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events.TotalDailyDoseEvent; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.history.history_events.TubeFilledEvent; +import info.nightscout.androidaps.plugins.pump.insight.utils.IDStorage; + +public class HistoryEventIDs { + + public static final IDStorage, Integer> IDS = new IDStorage<>(); + + static { + IDS.put(BolusDeliveredEvent.class, 917); + IDS.put(BolusProgrammedEvent.class, 874); + IDS.put(CannulaFilledEvent.class, 3264); + IDS.put(DateTimeChangedEvent.class, 165); + IDS.put(DefaultDateTimeSetEvent.class, 170); + IDS.put(EndOfTBREvent.class, 771); + IDS.put(OccurrenceOfErrorEvent.class, 1011); + IDS.put(OccurrenceOfMaintenanceEvent.class, 1290); + IDS.put(OccurrenceOfWarningEvent.class, 1360); + IDS.put(OperatingModeChangedEvent.class, 195); + IDS.put(PowerUpEvent.class, 15); + IDS.put(PowerDownEvent.class, 51); + IDS.put(SniffingDoneEvent.class, 102); + IDS.put(StartOfTBREvent.class, 240); + IDS.put(TotalDailyDoseEvent.class, 960); + IDS.put(TubeFilledEvent.class, 105); + IDS.put(CartridgeInsertedEvent.class, 60); + IDS.put(CartridgeRemovedEvent.class, 85); + IDS.put(BasalDeliveryChangedEvent.class, 204); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/HistoryReadingDirectionIDs.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/HistoryReadingDirectionIDs.java new file mode 100644 index 0000000000..f8b068d9af --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/HistoryReadingDirectionIDs.java @@ -0,0 +1,15 @@ +package info.nightscout.androidaps.plugins.pump.insight.ids; + +import info.nightscout.androidaps.plugins.pump.insight.app_layer.history.HistoryReadingDirection; +import info.nightscout.androidaps.plugins.pump.insight.utils.IDStorage; + +public class HistoryReadingDirectionIDs { + + public static final IDStorage IDS = new IDStorage<>(); + + static { + IDS.put(HistoryReadingDirection.FORWARD, 31); + IDS.put(HistoryReadingDirection.BACKWARD, 227); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/OperatingModeIDs.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/OperatingModeIDs.java new file mode 100644 index 0000000000..faf86d80d9 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/OperatingModeIDs.java @@ -0,0 +1,16 @@ +package info.nightscout.androidaps.plugins.pump.insight.ids; + +import info.nightscout.androidaps.plugins.pump.insight.descriptors.OperatingMode; +import info.nightscout.androidaps.plugins.pump.insight.utils.IDStorage; + +public class OperatingModeIDs { + + public static final IDStorage IDS = new IDStorage<>(); + + static { + IDS.put(OperatingMode.STOPPED, 31); + IDS.put(OperatingMode.STARTED, 227); + IDS.put(OperatingMode.PAUSED, 252); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/PairingStatusIDs.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/PairingStatusIDs.java new file mode 100644 index 0000000000..8325446e7d --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/PairingStatusIDs.java @@ -0,0 +1,16 @@ +package info.nightscout.androidaps.plugins.pump.insight.ids; + +import info.nightscout.androidaps.plugins.pump.insight.satl.PairingStatus; +import info.nightscout.androidaps.plugins.pump.insight.utils.IDStorage; + +public class PairingStatusIDs { + + public static final IDStorage IDS = new IDStorage<>(); + + static { + IDS.put(PairingStatus.PENDING, 1683); + IDS.put(PairingStatus.REJECTED, 7850); + IDS.put(PairingStatus.CONFIRMED, 11835); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/ParameterBlockIDs.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/ParameterBlockIDs.java new file mode 100644 index 0000000000..36813756f9 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/ParameterBlockIDs.java @@ -0,0 +1,51 @@ +package info.nightscout.androidaps.plugins.pump.insight.ids; + +import info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks.FactoryMaxBasalAmountBlock; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks.FactoryMinBasalAmountBlock; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks.MaxBasalAmountBlock; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks.ParameterBlock; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks.TBROverNotificationBlock; +import info.nightscout.androidaps.plugins.pump.insight.utils.IDStorage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks.ActiveBRProfileBlock; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks.BRProfile1Block; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks.BRProfile1NameBlock; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks.BRProfile2Block; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks.BRProfile2NameBlock; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks.BRProfile3Block; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks.BRProfile3NameBlock; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks.BRProfile4Block; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks.BRProfile4NameBlock; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks.BRProfile5Block; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks.BRProfile5NameBlock; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks.FactoryMaxBolusAmountBlock; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks.FactoryMinBolusAmountBlock; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks.MaxBolusAmountBlock; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks.SystemIdentificationBlock; + +public class ParameterBlockIDs { + + public static final IDStorage, Integer> IDS = new IDStorage<>(); + + static { + IDS.put(FactoryMaxBolusAmountBlock.class, 41222); + IDS.put(MaxBolusAmountBlock.class, 31); + IDS.put(FactoryMinBolusAmountBlock.class, 60183); + IDS.put(SystemIdentificationBlock.class, 35476); + IDS.put(BRProfile1Block.class, 7136); + IDS.put(BRProfile2Block.class, 7167); + IDS.put(BRProfile3Block.class, 7532); + IDS.put(BRProfile4Block.class, 7539); + IDS.put(BRProfile5Block.class, 7567); + IDS.put(BRProfile1NameBlock.class, 48265); + IDS.put(BRProfile2NameBlock.class, 48278); + IDS.put(BRProfile3NameBlock.class, 48975); + IDS.put(BRProfile4NameBlock.class, 48976); + IDS.put(BRProfile5NameBlock.class, 49068); + IDS.put(ActiveBRProfileBlock.class, 7568); + IDS.put(MaxBasalAmountBlock.class, 6940); + IDS.put(FactoryMinBasalAmountBlock.class, 60395); + IDS.put(FactoryMaxBasalAmountBlock.class, 41241); + IDS.put(TBROverNotificationBlock.class, 25814); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/SatlCommandIDs.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/SatlCommandIDs.java new file mode 100644 index 0000000000..2423118507 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/SatlCommandIDs.java @@ -0,0 +1,39 @@ +package info.nightscout.androidaps.plugins.pump.insight.ids; + +import info.nightscout.androidaps.plugins.pump.insight.satl.SatlMessage; +import info.nightscout.androidaps.plugins.pump.insight.utils.IDStorage; +import info.nightscout.androidaps.plugins.pump.insight.satl.ConnectionRequest; +import info.nightscout.androidaps.plugins.pump.insight.satl.ConnectionResponse; +import info.nightscout.androidaps.plugins.pump.insight.satl.DataMessage; +import info.nightscout.androidaps.plugins.pump.insight.satl.DisconnectMessage; +import info.nightscout.androidaps.plugins.pump.insight.satl.ErrorMessage; +import info.nightscout.androidaps.plugins.pump.insight.satl.KeyRequest; +import info.nightscout.androidaps.plugins.pump.insight.satl.KeyResponse; +import info.nightscout.androidaps.plugins.pump.insight.satl.SynAckResponse; +import info.nightscout.androidaps.plugins.pump.insight.satl.SynRequest; +import info.nightscout.androidaps.plugins.pump.insight.satl.VerifyConfirmRequest; +import info.nightscout.androidaps.plugins.pump.insight.satl.VerifyConfirmResponse; +import info.nightscout.androidaps.plugins.pump.insight.satl.VerifyDisplayRequest; +import info.nightscout.androidaps.plugins.pump.insight.satl.VerifyDisplayResponse; + +public class SatlCommandIDs { + + public static final IDStorage, Byte> IDS = new IDStorage<>(); + + static { + IDS.put(DataMessage.class, (byte) 3); + IDS.put(ErrorMessage.class, (byte) 6); + IDS.put(ConnectionRequest.class, (byte) 9); + IDS.put(ConnectionResponse.class, (byte) 10); + IDS.put(KeyRequest.class, (byte) 12); + IDS.put(VerifyConfirmRequest.class, (byte) 14); + IDS.put(KeyResponse.class, (byte) 17); + IDS.put(VerifyDisplayRequest.class, (byte) 18); + IDS.put(VerifyDisplayResponse.class, (byte) 20); + IDS.put(SynRequest.class, (byte) 23); + IDS.put(SynAckResponse.class, (byte) 24); + IDS.put(DisconnectMessage.class, (byte) 27); + IDS.put(VerifyConfirmResponse.class, (byte) 30); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/SatlErrorIDs.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/SatlErrorIDs.java new file mode 100644 index 0000000000..fe18afbff0 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/SatlErrorIDs.java @@ -0,0 +1,26 @@ +package info.nightscout.androidaps.plugins.pump.insight.ids; + +import info.nightscout.androidaps.plugins.pump.insight.satl.SatlError; +import info.nightscout.androidaps.plugins.pump.insight.utils.IDStorage; + +public class SatlErrorIDs { + + public static final IDStorage IDS = new IDStorage<>(); + + static { + IDS.put(SatlError.UNDEFINED, (byte) 0); + IDS.put(SatlError.INCOMPATIBLE_VERSION, (byte) 1); + IDS.put(SatlError.INVALID_COMM_ID, (byte) 2); + IDS.put(SatlError.INVALID_MAC_TRAILER, (byte) 3); + IDS.put(SatlError.INVALID_CRC, (byte) 4); + IDS.put(SatlError.INVALID_PACKET, (byte) 5); + IDS.put(SatlError.INVALID_NONCE, (byte) 6); + IDS.put(SatlError.DECRYPT_VERIFY_FAILED, (byte) 7); + IDS.put(SatlError.COMPATIBLE_STATE, (byte) 8); + IDS.put(SatlError.WRONG_STATE, (byte) 0x0F); + IDS.put(SatlError.INVALID_MESSAGE_TYPE, (byte) 51); + IDS.put(SatlError.INVALID_PAYLOAD_LENGTH, (byte) 60); + IDS.put(SatlError.NONE, (byte) 255); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/ServiceIDs.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/ServiceIDs.java new file mode 100644 index 0000000000..f9a59bdda5 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/ServiceIDs.java @@ -0,0 +1,18 @@ +package info.nightscout.androidaps.plugins.pump.insight.ids; + +import info.nightscout.androidaps.plugins.pump.insight.app_layer.Service; +import info.nightscout.androidaps.plugins.pump.insight.utils.IDStorage; + +public class ServiceIDs { + + public static final IDStorage IDS = new IDStorage<>(); + + static { + IDS.put(Service.CONNECTION, (byte) 0); + IDS.put(Service.STATUS, (byte) 15); + IDS.put(Service.HISTORY, (byte) 60); + IDS.put(Service.CONFIGURATION, (byte) 85); + IDS.put(Service.REMOTE_CONTROL, (byte) 102); + IDS.put(Service.PARAMETER, (byte) 51); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/SymbolStatusIDs.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/SymbolStatusIDs.java new file mode 100644 index 0000000000..84aee7f092 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/ids/SymbolStatusIDs.java @@ -0,0 +1,16 @@ +package info.nightscout.androidaps.plugins.pump.insight.ids; + +import info.nightscout.androidaps.plugins.pump.insight.descriptors.SymbolStatus; +import info.nightscout.androidaps.plugins.pump.insight.utils.IDStorage; + +public class SymbolStatusIDs { + + public static final IDStorage IDS = new IDStorage<>(); + + static { + IDS.put(SymbolStatus.FULL, 31); + IDS.put(SymbolStatus.LOW, 227); + IDS.put(SymbolStatus.EMPTY, 252); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/satl/ConnectionRequest.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/satl/ConnectionRequest.java new file mode 100644 index 0000000000..9a6bf6ee15 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/satl/ConnectionRequest.java @@ -0,0 +1,4 @@ +package info.nightscout.androidaps.plugins.pump.insight.satl; + +public class ConnectionRequest extends SatlMessage { +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/satl/ConnectionResponse.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/satl/ConnectionResponse.java new file mode 100644 index 0000000000..46bd0fd787 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/satl/ConnectionResponse.java @@ -0,0 +1,4 @@ +package info.nightscout.androidaps.plugins.pump.insight.satl; + +public class ConnectionResponse extends SatlMessage { +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/satl/DataMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/satl/DataMessage.java new file mode 100644 index 0000000000..d41059f208 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/satl/DataMessage.java @@ -0,0 +1,21 @@ +package info.nightscout.androidaps.plugins.pump.insight.satl; + +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public class DataMessage extends SatlMessage { + + private ByteBuf data; + + @Override + protected void parse(ByteBuf byteBuf) { + data = byteBuf; + } + + public ByteBuf getData() { + return this.data; + } + + public void setData(ByteBuf data) { + this.data = data; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/satl/DisconnectMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/satl/DisconnectMessage.java new file mode 100644 index 0000000000..d1e9eb0c56 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/satl/DisconnectMessage.java @@ -0,0 +1,4 @@ +package info.nightscout.androidaps.plugins.pump.insight.satl; + +public class DisconnectMessage extends SatlMessage { +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/satl/ErrorMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/satl/ErrorMessage.java new file mode 100644 index 0000000000..3acab320b4 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/satl/ErrorMessage.java @@ -0,0 +1,18 @@ +package info.nightscout.androidaps.plugins.pump.insight.satl; + +import info.nightscout.androidaps.plugins.pump.insight.ids.SatlErrorIDs; +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public class ErrorMessage extends SatlMessage { + + private SatlError error; + + @Override + protected void parse(ByteBuf byteBuf) { + error = SatlErrorIDs.IDS.getType(byteBuf.readByte()); + } + + public SatlError getError() { + return this.error; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/satl/KeyRequest.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/satl/KeyRequest.java new file mode 100644 index 0000000000..a4a8a57438 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/satl/KeyRequest.java @@ -0,0 +1,39 @@ +package info.nightscout.androidaps.plugins.pump.insight.satl; + +import java.util.Calendar; + +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public class KeyRequest extends SatlMessage { + + private byte[] randomBytes; + private byte[] preMasterKey; + + @Override + protected ByteBuf getData() { + ByteBuf byteBuf = new ByteBuf(288); + byteBuf.putBytes(randomBytes); + byteBuf.putUInt32LE(translateDate()); + byteBuf.putBytes(preMasterKey); + return byteBuf; + } + + private static int translateDate() { + Calendar calendar = Calendar.getInstance(); + int second = calendar.get(Calendar.SECOND); + int minute = calendar.get(Calendar.MINUTE); + int hour = calendar.get(Calendar.HOUR_OF_DAY); + int day = calendar.get(Calendar.DAY_OF_MONTH); + int month = calendar.get(Calendar.MONTH); + int year = calendar.get(Calendar.YEAR); + return (year % 100 & 0x3f) << 26 | (month & 0x0f) << 22 | (day & 0x1f) << 17 | (hour & 0x1f) << 12 | (minute & 0x3f) << 6 | (second & 0x3f); + } + + public void setRandomBytes(byte[] randomBytes) { + this.randomBytes = randomBytes; + } + + public void setPreMasterKey(byte[] preMasterKey) { + this.preMasterKey = preMasterKey; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/satl/KeyResponse.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/satl/KeyResponse.java new file mode 100644 index 0000000000..1affbab763 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/satl/KeyResponse.java @@ -0,0 +1,24 @@ +package info.nightscout.androidaps.plugins.pump.insight.satl; + +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public class KeyResponse extends SatlMessage { + + private byte[] randomData; + private byte[] preMasterSecret; + + @Override + protected void parse(ByteBuf byteBuf) { + randomData = byteBuf.readBytes(28); + byteBuf.shift(4); + preMasterSecret = byteBuf.getBytes(256); + } + + public byte[] getRandomData() { + return this.randomData; + } + + public byte[] getPreMasterSecret() { + return this.preMasterSecret; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/satl/PairingStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/satl/PairingStatus.java new file mode 100644 index 0000000000..899425f279 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/satl/PairingStatus.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.satl; + +public enum PairingStatus { + + CONFIRMED, + REJECTED, + PENDING +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/satl/SatlError.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/satl/SatlError.java new file mode 100644 index 0000000000..ac0b4ebebe --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/satl/SatlError.java @@ -0,0 +1,18 @@ +package info.nightscout.androidaps.plugins.pump.insight.satl; + +public enum SatlError { + + UNDEFINED, + INCOMPATIBLE_VERSION, + INVALID_COMM_ID, + INVALID_MAC_TRAILER, + INVALID_CRC, + INVALID_PACKET, + INVALID_NONCE, + DECRYPT_VERIFY_FAILED, + COMPATIBLE_STATE, + WRONG_STATE, + INVALID_MESSAGE_TYPE, + INVALID_PAYLOAD_LENGTH, + NONE +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/satl/SatlMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/satl/SatlMessage.java new file mode 100644 index 0000000000..09d5d1626a --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/satl/SatlMessage.java @@ -0,0 +1,178 @@ +package info.nightscout.androidaps.plugins.pump.insight.satl; + +import java.util.Arrays; + +import info.nightscout.androidaps.plugins.pump.insight.exceptions.IncompatibleSatlVersionException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.InvalidMacTrailerException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.InvalidNonceException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.InvalidPacketLengthsException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.InvalidPreambleException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.InvalidSatlCRCException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.InvalidSatlCommandException; +import info.nightscout.androidaps.plugins.pump.insight.ids.SatlCommandIDs; +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; +import info.nightscout.androidaps.plugins.pump.insight.utils.Nonce; +import info.nightscout.androidaps.plugins.pump.insight.utils.crypto.Cryptograph; + +public abstract class SatlMessage { + + private static final long PREAMBLE = 4293840008L; + private static final byte VERSION = 0x20; + + private Nonce nonce; + private long commID = 0; + private byte[] satlContent; + + protected ByteBuf getData() { + return new ByteBuf(0); + } + + protected void parse(ByteBuf byteBuf) { + + } + + public ByteBuf serialize(Class clazz, byte[] key) { + ByteBuf byteBuf; + if (nonce == null || key == null) byteBuf = serializeCRC(clazz); + else byteBuf = serializeCTR(nonce.getProductionalBytes(), key, SatlCommandIDs.IDS.getID(clazz)); + satlContent = byteBuf.getBytes(8, byteBuf.getSize() - 16); + return byteBuf; + } + + private ByteBuf serializeCRC(Class clazz) { + ByteBuf data = getData(); + int length = data.getSize() + 31; + ByteBuf byteBuf = new ByteBuf(length + 8); + byteBuf.putUInt32LE(PREAMBLE); + byteBuf.putUInt16LE(length); + byteBuf.putUInt16LE(~length); + byteBuf.putByte(VERSION); + byteBuf.putByte(SatlCommandIDs.IDS.getID(clazz)); + byteBuf.putUInt16LE(data.getSize() + 2); + byteBuf.putUInt32LE(clazz == KeyRequest.class ? 1 : commID); + byteBuf.putBytes((byte) 0x00, 13); + byteBuf.putByteBuf(data); + byteBuf.putUInt16LE(Cryptograph.calculateCRC(byteBuf.getBytes(8, length - 10))); + byteBuf.putBytes((byte) 0x00, 8); + return byteBuf; + } + + private ByteBuf serializeCTR(ByteBuf nonce, byte[] key, byte commandId) { + ByteBuf data = getData(); + ByteBuf encryptedData = ByteBuf.from(Cryptograph.encryptDataCTR(data.getBytes(), key, nonce.getBytes())); + int length = 29 + encryptedData.getSize(); + ByteBuf byteBuf = new ByteBuf(length + 8); + byteBuf.putUInt32LE(PREAMBLE); + byteBuf.putUInt16LE(length); + byteBuf.putUInt16LE(~length); + byteBuf.putByte(VERSION); + byteBuf.putByte(commandId); + byteBuf.putUInt16LE(encryptedData.getSize()); + byteBuf.putUInt32LE(commID); + byteBuf.putByteBuf(nonce); + byteBuf.putByteBuf(encryptedData); + byteBuf.putBytes(Cryptograph.produceCCMTag(byteBuf.getBytes(16, 13), data.getBytes(), byteBuf.getBytes(8, 21), key)); + return byteBuf; + } + + public static SatlMessage deserialize(ByteBuf data, Nonce lastNonce, byte[] key) throws InvalidMacTrailerException, InvalidSatlCRCException, InvalidNonceException, InvalidPreambleException, InvalidPacketLengthsException, IncompatibleSatlVersionException, InvalidSatlCommandException { + SatlMessage satlMessage; + byte[] satlContent = data.getBytes(8, data.getSize() - 16); + if (key == null) satlMessage = deserializeCRC(data); + else satlMessage = deserializeCTR(data, lastNonce, key); + satlMessage.setSatlContent(satlContent); + return satlMessage; + } + + private static SatlMessage deserializeCTR(ByteBuf data, Nonce lastNonce, byte[] key) throws InvalidMacTrailerException, InvalidNonceException, InvalidPreambleException, InvalidPacketLengthsException, IncompatibleSatlVersionException, InvalidSatlCommandException { + long preamble = data.readUInt32LE(); + int packetLength = data.readUInt16LE(); + int packetLengthXOR = data.readUInt16LE() ^ 65535; + byte[] header = data.getBytes(21); + byte version = data.readByte(); + byte commandId = data.readByte(); + Class clazz = SatlCommandIDs.IDS.getType(commandId); + int dataLength = data.readUInt16LE(); + long commId = data.readUInt32LE(); + byte[] nonce = data.readBytes(13); + byte[] payload = data.readBytes(dataLength); + byte[] trailer = data.readBytes(8); + Nonce parsedNonce = Nonce.fromProductionalBytes(nonce); + payload = Cryptograph.encryptDataCTR(payload, key, nonce); + if (!Arrays.equals(trailer, Cryptograph.produceCCMTag(nonce, payload, header, key))) throw new InvalidMacTrailerException(); + if (!lastNonce.isSmallerThan(parsedNonce)) throw new InvalidNonceException(); + if (preamble != PREAMBLE) throw new InvalidPreambleException(); + if (packetLength != packetLengthXOR) throw new InvalidPacketLengthsException(); + if (version != VERSION) throw new IncompatibleSatlVersionException(); + if (clazz == null) throw new InvalidSatlCommandException(); + SatlMessage message = null; + try { + message = clazz.newInstance(); + } catch (Exception ignored) { + } + message.parse(ByteBuf.from(payload)); + message.setNonce(parsedNonce); + message.setCommID(commId); + return message; + } + + private static SatlMessage deserializeCRC(ByteBuf data) throws InvalidSatlCRCException, InvalidPreambleException, InvalidPacketLengthsException, IncompatibleSatlVersionException, InvalidSatlCommandException { + long preamble = data.readUInt32LE(); + int packetLength = data.readUInt16LE(); + int packetLengthXOR = data.readUInt16LE() ^ 65535; + byte[] crcContent = data.getBytes(packetLength - 10); + byte version = data.readByte(); + byte commandId = data.readByte(); + Class clazz = SatlCommandIDs.IDS.getType(commandId); + int dataLength = data.readUInt16LE(); + long commId = data.readUInt32LE(); + byte[] nonce = data.readBytes(13); + byte[] payload = data.readBytes(dataLength - 2); + int crc = data.readUInt16LE(); + data.shift(8); + if (crc != Cryptograph.calculateCRC(crcContent)) throw new InvalidSatlCRCException(); + if (preamble != PREAMBLE) throw new InvalidPreambleException(); + if (packetLength != packetLengthXOR) throw new InvalidPacketLengthsException(); + if (version != VERSION) throw new IncompatibleSatlVersionException(); + if (clazz == null) throw new InvalidSatlCommandException(); + SatlMessage message = null; + try { + message = clazz.newInstance(); + } catch (Exception ignored) { + } + message.parse(ByteBuf.from(payload)); + message.setNonce(Nonce.fromProductionalBytes(nonce)); + message.setCommID(commId); + return message; + } + + public static boolean hasCompletePacket(ByteBuf byteBuf) { + if (byteBuf.getSize() < 37) return false; + if (byteBuf.getSize() < byteBuf.getUInt16LE(4) + 8) return false; + return true; + } + + public Nonce getNonce() { + return this.nonce; + } + + public long getCommID() { + return this.commID; + } + + public byte[] getSatlContent() { + return this.satlContent; + } + + public void setNonce(Nonce nonce) { + this.nonce = nonce; + } + + public void setCommID(long commID) { + this.commID = commID; + } + + public void setSatlContent(byte[] satlContent) { + this.satlContent = satlContent; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/satl/SynAckResponse.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/satl/SynAckResponse.java new file mode 100644 index 0000000000..261d2fa01c --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/satl/SynAckResponse.java @@ -0,0 +1,4 @@ +package info.nightscout.androidaps.plugins.pump.insight.satl; + +public class SynAckResponse extends SatlMessage { +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/satl/SynRequest.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/satl/SynRequest.java new file mode 100644 index 0000000000..9b47376495 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/satl/SynRequest.java @@ -0,0 +1,4 @@ +package info.nightscout.androidaps.plugins.pump.insight.satl; + +public class SynRequest extends SatlMessage { +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/satl/VerifyConfirmRequest.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/satl/VerifyConfirmRequest.java new file mode 100644 index 0000000000..dcca03a8f9 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/satl/VerifyConfirmRequest.java @@ -0,0 +1,14 @@ +package info.nightscout.androidaps.plugins.pump.insight.satl; + +import info.nightscout.androidaps.plugins.pump.insight.ids.PairingStatusIDs; +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public class VerifyConfirmRequest extends SatlMessage { + + @Override + protected ByteBuf getData() { + ByteBuf byteBuf = new ByteBuf(2); + byteBuf.putUInt16LE(PairingStatusIDs.IDS.getID(PairingStatus.CONFIRMED)); + return byteBuf; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/satl/VerifyConfirmResponse.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/satl/VerifyConfirmResponse.java new file mode 100644 index 0000000000..ed839f81a5 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/satl/VerifyConfirmResponse.java @@ -0,0 +1,18 @@ +package info.nightscout.androidaps.plugins.pump.insight.satl; + +import info.nightscout.androidaps.plugins.pump.insight.ids.PairingStatusIDs; +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public class VerifyConfirmResponse extends SatlMessage { + + private PairingStatus pairingStatus; + + @Override + protected void parse(ByteBuf byteBuf) { + pairingStatus = PairingStatusIDs.IDS.getType(byteBuf.readUInt16LE()); + } + + public PairingStatus getPairingStatus() { + return this.pairingStatus; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/satl/VerifyDisplayRequest.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/satl/VerifyDisplayRequest.java new file mode 100644 index 0000000000..4ed85b620c --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/satl/VerifyDisplayRequest.java @@ -0,0 +1,4 @@ +package info.nightscout.androidaps.plugins.pump.insight.satl; + +public class VerifyDisplayRequest extends SatlMessage { +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/satl/VerifyDisplayResponse.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/satl/VerifyDisplayResponse.java new file mode 100644 index 0000000000..0d3dc52f3e --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/satl/VerifyDisplayResponse.java @@ -0,0 +1,4 @@ +package info.nightscout.androidaps.plugins.pump.insight.satl; + +public class VerifyDisplayResponse extends SatlMessage { +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/utils/BOCUtil.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/utils/BOCUtil.java new file mode 100644 index 0000000000..6d0d93920f --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/utils/BOCUtil.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.pump.insight.utils; + +public final class BOCUtil { + + public static int parseBOC(byte b) { + return ((b & 0xF0) >> 4) * 10 + (b & 0x0F); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/utils/ByteBuf.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/utils/ByteBuf.java new file mode 100644 index 0000000000..0e5f275949 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/utils/ByteBuf.java @@ -0,0 +1,352 @@ +package info.nightscout.androidaps.plugins.pump.insight.utils; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.nio.charset.StandardCharsets; + +public class ByteBuf { + + private byte[] bytes; + private int size = 0; + + public ByteBuf(int length) { + bytes = new byte[length]; + } + + + public byte[] getBytes() { + byte[] bytes = new byte[size]; + System.arraycopy(this.bytes, 0, bytes, 0, size); + return bytes; + } + + public void shift(int offset) { + System.arraycopy(bytes, offset, bytes, 0, bytes.length - offset); + size -= offset; + } + + public byte getByte(int position) { + return bytes[position]; + } + + public byte getByte() { + return bytes[0]; + } + + public byte readByte() { + byte b = getByte(); + shift(1); + return b; + } + + public void putByte(byte b) { + bytes[size] = b; + size += 1; + } + + + public void putBytes(byte b, int count) { + for (int i = 0; i < count; i++) bytes[size++] = b; + } + + + public byte[] getBytes(int position, int length) { + byte[] copy = new byte[length]; + System.arraycopy(bytes, position, copy, 0, length); + return copy; + } + + public byte[] getBytes(int length) { + return getBytes(0, length); + } + + public byte[] readBytes(int length) { + byte[] copy = getBytes(length); + shift(length); + return copy; + } + + byte[] readBytes() { + return readBytes(size); + } + + public void putBytes(byte[] bytes, int length) { + System.arraycopy(bytes, 0, this.bytes, size, length); + size += length; + } + + public void putBytes(byte[] bytes) { + putBytes(bytes, bytes.length); + } + + + private byte[] getBytesLE(int position, int length) { + byte[] copy = new byte[length]; + for (int i = 0; i < length; i++) + copy[i] = bytes[length - 1 - i + position]; + return copy; + } + + private byte[] getBytesLE(int length) { + return getBytesLE(0, length); + } + + public byte[] readBytesLE(int length) { + byte[] copy = getBytesLE(length); + shift(length); + return copy; + } + + private void putBytesLE(byte[] bytes, int length) { + for (int i = 0; i < length; i++) + this.bytes[size + length - 1 - i] = bytes[i]; + size += length; + } + + void putBytesLE(byte[] bytes) { + putBytesLE(bytes, bytes.length); + } + + + public void putByteBuf(ByteBuf byteBuf) { + putBytes(byteBuf.getBytes(), byteBuf.getSize()); + } + + + private short getUInt8(int position) { + return (short) (bytes[position] & 0xFF); + } + + private short getUInt8() { + return getUInt8(0); + } + + public short readUInt8() { + short value = getUInt8(); + shift(1); + return value; + } + + public void putUInt8(short value) { + putByte((byte) (value & 0xFF)); + } + + + public int getUInt16LE(int position) { + return (bytes[position++] & 0xFF | + (bytes[position] & 0xFF) << 8); + } + + private int getUInt16LE() { + return getUInt16LE(0); + } + + public int readUInt16LE() { + int i = getUInt16LE(); + shift(2); + return i; + } + + public void putUInt16LE(int i) { + putByte((byte) (i & 0xFF)); + putByte((byte) ((i >> 8) & 0xFF)); + } + + + private double getUInt16Decimal(int position) { + return new BigDecimal(getUInt16LE(position)) + .divide(new BigDecimal(100), 2, RoundingMode.HALF_UP) + .doubleValue(); + } + + private double getUInt16Decimal() { + return getUInt16Decimal(0); + } + + public double readUInt16Decimal() { + double d = getUInt16Decimal(); + shift(2); + return d; + } + + public void putUInt16Decimal(double d) { + putUInt16LE(new BigDecimal(d) + .multiply(new BigDecimal(100)) + .setScale(0, RoundingMode.HALF_UP) + .intValue()); + } + + + private double getUInt32Decimal100(int position) { + return new BigDecimal(getUInt32LE(position)) + .divide(new BigDecimal(100), 2, RoundingMode.HALF_UP) + .doubleValue(); + } + + private double getUInt32Decimal100() { + return getUInt32Decimal100(0); + } + + public double readUInt32Decimal100() { + double d = getUInt32Decimal100(); + shift(4); + return d; + } + + public void putUInt32Decimal100(double d) { + putUInt32LE(new BigDecimal(d) + .multiply(new BigDecimal(100)) + .setScale(0, RoundingMode.HALF_UP) + .longValue()); + } + + + private double getUInt32Decimal1000(int position) { + return new BigDecimal(getUInt32LE(position)) + .divide(new BigDecimal(1000), 3, RoundingMode.HALF_UP) + .doubleValue(); + } + + private double getUInt32Decimal1000() { + return getUInt32Decimal1000(0); + } + + public double readUInt32Decimal1000() { + double d = getUInt32Decimal1000(); + shift(4); + return d; + } + + public void putUInt32Decimal1000(double d) { + putUInt32LE(new BigDecimal(d) + .multiply(new BigDecimal(1000)) + .setScale(0, RoundingMode.HALF_UP) + .longValue()); + } + + + private short getShort(int position) { + return (short) (bytes[position++] << 8 | + bytes[position] & 0xFF); + } + + public short getShort() { + return getShort(0); + } + + public short readShort() { + short s = getShort(); + shift(2); + return s; + } + + public void putShort(short s) { + putByte((byte) (s >> 8)); + putByte((byte) s); + } + + + private long getUInt32LE(int position) { + return ((long) bytes[position++] & 0xFF) | + ((long) bytes[position++] & 0xFF) << 8 | + ((long) bytes[position++] & 0xFF) << 16 | + ((long) bytes[position] & 0xFF) << 24; + } + + private long getUInt32LE() { + return getUInt32LE(0); + } + + public long readUInt32LE() { + long l = getUInt32LE(); + shift(4); + return l; + } + + public void putUInt32LE(long l) { + putByte((byte) (l & 0xFF)); + putByte((byte) ((l >> 8) & 0xFF)); + putByte((byte) ((l >> 16) & 0xFF)); + putByte((byte) ((l >> 24) & 0xFF)); + } + + + private String getUTF16(int position, int stringLength) { + String string = new String(getBytes(position, stringLength * 2 + 2), StandardCharsets.UTF_16LE); + return string.substring(0, string.indexOf(new String(new char[]{0, 0}))); + } + + private String getUTF16(int stringLength) { + return getUTF16(0, stringLength); + } + + public String readUTF16(int stringLength) { + String string = getUTF16(stringLength); + shift(stringLength * 2 + 2); + return string; + } + + public void putUTF16(String string, int stringLength) { + putBytes(string.getBytes(StandardCharsets.UTF_16LE), stringLength * 2); + putBytes((byte) 0, 2); + } + + + private String getASCII(int position, int stringLength) { + String string = new String(getBytes(position, stringLength + 1), StandardCharsets.US_ASCII); + return string.substring(0, string.indexOf(0)); + } + + private String getASCII(int stringLength) { + return getASCII(0, stringLength); + } + + public String readASCII(int stringLength) { + String string = getASCII(stringLength); + shift(stringLength + 1); + return string; + } + + public void putASCII(String string, int stringLength) { + putBytes(string.getBytes(StandardCharsets.UTF_16LE), stringLength * 2); + putBytes((byte) 0, 1); + } + + + public boolean getBoolean(int position) { + return getUInt16LE(position) == 75; + } + + public boolean getBoolean() { + return getBoolean(0); + } + + public boolean readBoolean() { + boolean bool = getBoolean(); + shift(2); + return bool; + } + + public void putBoolean(boolean bool) { + putUInt16LE(bool ? 75 : 180); + } + + + public static ByteBuf from(byte[] bytes, int length) { + ByteBuf byteBuf = new ByteBuf(length); + byteBuf.putBytes(bytes, length); + return byteBuf; + } + + public static ByteBuf from(byte[] bytes) { + return from(bytes, bytes.length); + } + + public int getSize() { + return this.size; + } + + public void clear() { + shift(size); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/utils/ConnectionEstablisher.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/utils/ConnectionEstablisher.java new file mode 100644 index 0000000000..ce6a299521 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/utils/ConnectionEstablisher.java @@ -0,0 +1,79 @@ +package info.nightscout.androidaps.plugins.pump.insight.utils; + +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothSocket; + +import java.io.IOException; +import java.lang.reflect.Method; +import java.util.UUID; + +public class ConnectionEstablisher extends Thread { + + private Callback callback; + private boolean forPairing; + private BluetoothAdapter bluetoothAdapter; + private BluetoothDevice bluetoothDevice; + private BluetoothSocket socket; + + public ConnectionEstablisher(Callback callback, boolean forPairing, BluetoothAdapter bluetoothAdapter, BluetoothDevice bluetoothDevice, BluetoothSocket socket) { + this.callback = callback; + this.forPairing = forPairing; + this.bluetoothAdapter = bluetoothAdapter; + this.bluetoothDevice = bluetoothDevice; + this.socket = socket; + } + + @Override + public void run() { + try { + if (!bluetoothAdapter.isEnabled()) { + bluetoothAdapter.enable(); + Thread.sleep(2000); + } + } catch (InterruptedException ignored) { + return; + } + if (forPairing && bluetoothDevice.getBondState() != BluetoothDevice.BOND_NONE) { + try { + Method removeBond = bluetoothDevice.getClass().getMethod("removeBond", (Class[]) null); + removeBond.invoke(bluetoothDevice, (Object[]) null); + } catch (ReflectiveOperationException e) { + if (!isInterrupted()) callback.onConnectionFail(e, 0); + return; + } + } + try { + if (socket == null) { + socket = bluetoothDevice.createInsecureRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805f9b34fb")); + callback.onSocketCreated(socket); + } + } catch (IOException e) { + if (!isInterrupted()) callback.onConnectionFail(e, 0); + return; + } + long connectionStart = System.currentTimeMillis(); + try { + socket.connect(); + if (!isInterrupted()) callback.onConnectionSucceed(); + } catch (IOException e) { + if (!isInterrupted()) callback.onConnectionFail(e, System.currentTimeMillis() - connectionStart); + } + } + + public void close(boolean closeSocket) { + try { + interrupt(); + if (closeSocket && socket != null && socket.isConnected()) socket.close(); + } catch (IOException ignored) { + } + } + + public interface Callback { + void onSocketCreated(BluetoothSocket bluetoothSocket); + + void onConnectionSucceed(); + + void onConnectionFail(Exception e, long duration); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/utils/DelayedActionThread.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/utils/DelayedActionThread.java new file mode 100644 index 0000000000..c801a1b2d3 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/utils/DelayedActionThread.java @@ -0,0 +1,28 @@ +package info.nightscout.androidaps.plugins.pump.insight.utils; + +public class DelayedActionThread extends Thread { + + private long duration; + private Runnable runnable; + + private DelayedActionThread(String name, long duration, Runnable runnable) { + setName(name); + this.duration = duration; + this.runnable = runnable; + } + + @Override + public void run() { + try { + Thread.sleep(duration); + runnable.run(); + } catch (InterruptedException e) { + } + } + + public static DelayedActionThread runDelayed(String name, long duration, Runnable runnable) { + DelayedActionThread delayedActionThread = new DelayedActionThread(name, duration, runnable); + delayedActionThread.start(); + return delayedActionThread; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/utils/ExceptionTranslator.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/utils/ExceptionTranslator.java new file mode 100644 index 0000000000..7eda84d01b --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/utils/ExceptionTranslator.java @@ -0,0 +1,55 @@ +package info.nightscout.androidaps.plugins.pump.insight.utils; + +import android.content.Context; +import android.os.Handler; +import android.os.Looper; +import android.widget.Toast; + +import java.util.HashMap; +import java.util.Map; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.ConnectionFailedException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.ConnectionLostException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.DisconnectedException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.SocketCreationFailedException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.TimeoutException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.MaximumNumberOfBolusTypeAlreadyRunningException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.NoActiveTBRToCanceLException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.NoActiveTBRToChangeException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.NoSuchBolusToCancelException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.PumpAlreadyInThatStateException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.PumpStoppedException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.app_layer_errors.RunModeNotAllowedException; +import info.nightscout.androidaps.plugins.pump.insight.exceptions.satl_errors.SatlPairingRejectedException; + +public class ExceptionTranslator { + + private static final Map, Integer> TABLE = new HashMap<>(); + + static { + TABLE.put(ConnectionFailedException.class, R.string.connection_failed); + TABLE.put(ConnectionLostException.class, R.string.connection_lost); + TABLE.put(DisconnectedException.class, R.string.disconnected); + TABLE.put(SatlPairingRejectedException.class, R.string.pairing_rejected); + TABLE.put(SocketCreationFailedException.class, R.string.socket_creation_failed); + TABLE.put(TimeoutException.class, R.string.timeout); + TABLE.put(MaximumNumberOfBolusTypeAlreadyRunningException.class, R.string.maximum_number_of_bolus_type_already_running); + TABLE.put(NoActiveTBRToCanceLException.class, R.string.no_active_tbr_to_cancel); + TABLE.put(NoActiveTBRToChangeException.class, R.string.no_active_tbr_to_change); + TABLE.put(NoSuchBolusToCancelException.class, R.string.no_such_bolus_to_cancel); + TABLE.put(PumpAlreadyInThatStateException.class, R.string.pump_already_in_that_state_exception); + TABLE.put(PumpStoppedException.class, R.string.pump_stopped); + TABLE.put(RunModeNotAllowedException.class, R.string.run_mode_not_allowed); + } + + public static String getString(Exception exception) { + Integer res = TABLE.get(exception.getClass()); + return res == null ? exception.getClass().getSimpleName() : MainApp.gs(res); + } + + public static void makeToast(Context context, Exception exception) { + new Handler(Looper.getMainLooper()).post(() -> Toast.makeText(context, getString(exception), Toast.LENGTH_LONG).show()); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/utils/IDStorage.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/utils/IDStorage.java new file mode 100644 index 0000000000..05d3290eb2 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/utils/IDStorage.java @@ -0,0 +1,24 @@ +package info.nightscout.androidaps.plugins.pump.insight.utils; + +import java.util.HashMap; +import java.util.Map; + +public class IDStorage { + + private Map types = new HashMap<>(); + private Map ids = new HashMap<>(); + + public void put(T type, I id) { + types.put(type, id); + ids.put(id, type); + } + + public T getType(I type) { + return ids.get(type); + } + + public I getID(T id) { + return types.get(id); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/utils/InputStreamReader.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/utils/InputStreamReader.java new file mode 100644 index 0000000000..7641aba369 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/utils/InputStreamReader.java @@ -0,0 +1,51 @@ +package info.nightscout.androidaps.plugins.pump.insight.utils; + +import java.io.IOException; +import java.io.InputStream; + +public class InputStreamReader extends Thread { + + private static final int BUFFER_SIZE = 1024; + + private InputStream inputStream; + private Callback callback; + + public InputStreamReader(InputStream inputStream, Callback callback) { + setName(getClass().getSimpleName()); + this.inputStream = inputStream; + this.callback = callback; + } + + @Override + public void run() { + byte[] buffer = new byte[BUFFER_SIZE]; + int bytesRead; + try { + while (!isInterrupted()) { + bytesRead = inputStream.read(buffer); + if (bytesRead == -1) callback.onErrorWhileReading(new IOException("Stream closed")); + else callback.onReceiveBytes(buffer, bytesRead); + } + } catch (IOException e) { + if (!isInterrupted()) callback.onErrorWhileReading(e); + } finally { + try { + inputStream.close(); + } catch (IOException e) { + } + } + } + + public void close() { + interrupt(); + try { + inputStream.close(); + } catch (IOException e) { + } + } + + public interface Callback { + void onReceiveBytes(byte[] buffer, int bytesRead); + void onErrorWhileReading(Exception e); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/utils/Nonce.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/utils/Nonce.java new file mode 100644 index 0000000000..60dddc60bf --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/utils/Nonce.java @@ -0,0 +1,47 @@ +package info.nightscout.androidaps.plugins.pump.insight.utils; + +import java.math.BigInteger; + +public class Nonce { + + private BigInteger bigInteger; + + public Nonce() { + bigInteger = BigInteger.ZERO; + } + + public Nonce(byte[] storageValue) { + bigInteger = new BigInteger(storageValue); + } + + public byte[] getStorageValue() { + return bigInteger.toByteArray(); + } + + public ByteBuf getProductionalBytes() { + ByteBuf byteBuf = new ByteBuf(13); + byteBuf.putBytesLE(bigInteger.toByteArray()); + byteBuf.putBytes((byte) 0x00, 13 - byteBuf.getSize()); + return byteBuf; + } + + public static Nonce fromProductionalBytes(byte[] bytes) { + ByteBuf byteBuf = new ByteBuf(14); + byteBuf.putByte((byte) 0x00); + byteBuf.putBytesLE(bytes); + return new Nonce(byteBuf.getBytes()); + } + + public void increment() { + bigInteger = bigInteger.add(BigInteger.ONE); + } + + public void increment(int count) { + bigInteger = bigInteger.add(BigInteger.valueOf(count)); + } + + public boolean isSmallerThan(Nonce greater) { + return bigInteger.compareTo(greater.bigInteger) < 0; + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/utils/OutputStreamWriter.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/utils/OutputStreamWriter.java new file mode 100644 index 0000000000..fa03cf7824 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/utils/OutputStreamWriter.java @@ -0,0 +1,74 @@ +package info.nightscout.androidaps.plugins.pump.insight.utils; + +import java.io.IOException; +import java.io.OutputStream; + +public class OutputStreamWriter extends Thread { + + private static final int BUFFER_SIZE = 1024; + + private OutputStream outputStream; + private Callback callback; + private final ByteBuf buffer = new ByteBuf(BUFFER_SIZE); + + public OutputStreamWriter(OutputStream outputStream, Callback callback) { + setName(getClass().getSimpleName()); + this.outputStream = outputStream; + this.callback = callback; + } + + @Override + public void run() { + try { + while (!isInterrupted()) { + synchronized (buffer) { + if (buffer.getSize() != 0) { + outputStream.write(buffer.readBytes()); + outputStream.flush(); + buffer.notifyAll(); + } + buffer.wait(); + } + } + } catch (IOException e) { + if (!isInterrupted()) callback.onErrorWhileWriting(e); + } catch (InterruptedException ignored) { + } finally { + try { + outputStream.close(); + } catch (IOException e) { + } + } + } + + public void write(byte[] bytes) { + synchronized (buffer) { + buffer.putBytes(bytes); + buffer.notifyAll(); + } + } + + public void writeAndWait(byte[] bytes) { + synchronized (buffer) { + buffer.putBytes(bytes); + buffer.notifyAll(); + try { + buffer.wait(); + } catch (InterruptedException e) { + } + } + } + + public void close() { + interrupt(); + try { + outputStream.close(); + } catch (IOException e) { + } + } + + public interface Callback { + void onErrorWhileWriting(Exception e); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/utils/PairingDataStorage.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/utils/PairingDataStorage.java new file mode 100644 index 0000000000..57234698ff --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/utils/PairingDataStorage.java @@ -0,0 +1,210 @@ +package info.nightscout.androidaps.plugins.pump.insight.utils; + +import android.content.Context; +import android.content.SharedPreferences; + +import org.spongycastle.util.encoders.Hex; + +import info.nightscout.androidaps.plugins.pump.insight.descriptors.FirmwareVersions; +import info.nightscout.androidaps.plugins.pump.insight.descriptors.SystemIdentification; + +public class PairingDataStorage { + + private SharedPreferences preferences; + + private boolean paired; + private String macAddress; + private Nonce lastNonceSent; + private Nonce lastNonceReceived; + private long commId; + private byte[] incomingKey; + private byte[] outgoingKey; + private FirmwareVersions firmwareVersions; + private SystemIdentification systemIdentification; + + public PairingDataStorage(Context context) { + this.preferences = context.getSharedPreferences(context.getPackageName() + ".PAIRING_DATA_STORAGE", Context.MODE_PRIVATE); + paired = preferences.getBoolean("paired", false); + macAddress = preferences.getString("macAddress", null); + String lastNonceSentHex = preferences.getString("lastNonceSent", null); + if (lastNonceSentHex != null) lastNonceSent = new Nonce(Hex.decode(lastNonceSentHex)); + String lastNonceReceivedHex = preferences.getString("lastNonceReceived", null); + if (lastNonceReceivedHex != null) lastNonceReceived = new Nonce(Hex.decode(lastNonceReceivedHex)); + commId = preferences.getLong("commId", 0); + String incomingKeyHex = preferences.getString("incomingKey", null); + incomingKey = incomingKeyHex == null ? null : Hex.decode(incomingKeyHex); + String outgoingKeyHex = preferences.getString("outgoingKey", null); + outgoingKey = outgoingKeyHex == null ? null : Hex.decode(outgoingKeyHex); + + String pumpSerial = preferences.getString("pumpSerial", null); + String manufacturingDate = preferences.getString("manufacturingDate", null); + long systemIdAppendix = preferences.getLong("systemIdAppendix", 0); + + if (pumpSerial != null) { + systemIdentification = new SystemIdentification(); + systemIdentification.setSerialNumber(pumpSerial); + systemIdentification.setManufacturingDate(manufacturingDate); + systemIdentification.setSystemIdAppendix(systemIdAppendix); + } + + String releaseSWVersion = preferences.getString("releaseSWVersion", null); + String uiProcSWVersion = preferences.getString("uiProcSWVersion", null); + String pcProcSWVersion = preferences.getString("pcProcSWVersion", null); + String mdTelProcSWVersion = preferences.getString("mdTelProcSWVersion", null); + String btInfoPageVersion = preferences.getString("btInfoPageVersion", null); + String safetyProcSWVersion = preferences.getString("safetyProcSWVersion", null); + int configIndex = preferences.getInt("configIndex", 0); + int historyIndex = preferences.getInt("historyIndex", 0); + int stateIndex = preferences.getInt("stateIndex", 0); + int vocabularyIndex = preferences.getInt("vocabularyIndex", 0); + if (releaseSWVersion != null) { + firmwareVersions = new FirmwareVersions(); + firmwareVersions.setReleaseSWVersion(releaseSWVersion); + firmwareVersions.setUiProcSWVersion(uiProcSWVersion); + firmwareVersions.setPcProcSWVersion(pcProcSWVersion); + firmwareVersions.setMdTelProcSWVersion(mdTelProcSWVersion); + firmwareVersions.setBtInfoPageVersion(btInfoPageVersion); + firmwareVersions.setSafetyProcSWVersion(safetyProcSWVersion); + firmwareVersions.setConfigIndex(configIndex); + firmwareVersions.setHistoryIndex(historyIndex); + firmwareVersions.setStateIndex(stateIndex); + firmwareVersions.setVocabularyIndex(vocabularyIndex); + } + } + + public void setPaired(boolean paired) { + this.paired = paired; + preferences.edit().putBoolean("paired", paired).apply(); + } + + public void setMacAddress(String macAddress) { + this.macAddress = macAddress; + preferences.edit().putString("macAddress", macAddress).apply(); + } + + public void setLastNonceSent(Nonce lastNonceSent) { + this.lastNonceSent = lastNonceSent; + preferences.edit().putString("lastNonceSent", lastNonceSent == null ? null : Hex.toHexString(lastNonceSent.getStorageValue())).apply(); + } + + public void setLastNonceReceived(Nonce lastNonceReceived) { + this.lastNonceReceived = lastNonceReceived; + preferences.edit().putString("lastNonceReceived", lastNonceReceived == null ? null : Hex.toHexString(lastNonceReceived.getStorageValue())).apply(); + } + + public void setCommId(long commId) { + this.commId = commId; + preferences.edit().putLong("commId", commId).apply(); + } + + public void setIncomingKey(byte[] incomingKey) { + this.incomingKey = incomingKey; + preferences.edit().putString("incomingKey", incomingKey == null ? null : Hex.toHexString(incomingKey)).apply(); + } + + public void setOutgoingKey(byte[] outgoingKey) { + this.outgoingKey = outgoingKey; + preferences.edit().putString("outgoingKey", outgoingKey == null ? null : Hex.toHexString(outgoingKey)).apply(); + } + + public SharedPreferences getPreferences() { + return this.preferences; + } + + public boolean isPaired() { + return this.paired; + } + + public String getMacAddress() { + return this.macAddress; + } + + public Nonce getLastNonceSent() { + return this.lastNonceSent; + } + + public Nonce getLastNonceReceived() { + return this.lastNonceReceived; + } + + public long getCommId() { + return this.commId; + } + + public byte[] getIncomingKey() { + return this.incomingKey; + } + + public byte[] getOutgoingKey() { + return this.outgoingKey; + } + + public FirmwareVersions getFirmwareVersions() { + return firmwareVersions; + } + + public void setFirmwareVersions(FirmwareVersions firmwareVersions) { + this.firmwareVersions = firmwareVersions; + if (firmwareVersions == null) { + preferences.edit() + .putString("releaseSWVersion", null) + .putString("uiProcSWVersion", null) + .putString("pcProcSWVersion", null) + .putString("mdTelProcSWVersion", null) + .putString("btInfoPageVersion", null) + .putString("safetyProcSWVersion", null) + .putInt("configIndex", 0) + .putInt("historyIndex", 0) + .putInt("stateIndex", 0) + .putInt("vocabularyIndex", 0) + .apply(); + } else { + preferences.edit() + .putString("releaseSWVersion", firmwareVersions.getReleaseSWVersion()) + .putString("uiProcSWVersion", firmwareVersions.getUiProcSWVersion()) + .putString("pcProcSWVersion", firmwareVersions.getPcProcSWVersion()) + .putString("mdTelProcSWVersion", firmwareVersions.getMdTelProcSWVersion()) + .putString("btInfoPageVersion", firmwareVersions.getBtInfoPageVersion()) + .putString("safetyProcSWVersion", firmwareVersions.getSafetyProcSWVersion()) + .putInt("configIndex", firmwareVersions.getConfigIndex()) + .putInt("historyIndex", firmwareVersions.getHistoryIndex()) + .putInt("stateIndex", firmwareVersions.getStateIndex()) + .putInt("vocabularyIndex", firmwareVersions.getVocabularyIndex()) + .apply(); + } + } + + public SystemIdentification getSystemIdentification() { + return systemIdentification; + } + + public void setSystemIdentification(SystemIdentification systemIdentification) { + this.systemIdentification = systemIdentification; + if (systemIdentification == null) { + preferences.edit() + .putString("pumpSerial", null) + .putString("manufacturingDate", null) + .putLong("systemIdAppendix", 0) + .apply(); + } else { + preferences.edit() + .putString("pumpSerial", systemIdentification.getSerialNumber()) + .putString("manufacturingDate", systemIdentification.getManufacturingDate()) + .putLong("systemIdAppendix", systemIdentification.getSystemIdAppendix()) + .apply(); + } + } + + public void reset() { + setPaired(false); + setMacAddress(null); + setCommId(0); + setIncomingKey(null); + setOutgoingKey(null); + setLastNonceReceived(null); + setLastNonceSent(null); + setFirmwareVersions(null); + setSystemIdentification(null); + setMacAddress(null); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/utils/ParameterBlockUtil.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/utils/ParameterBlockUtil.java new file mode 100644 index 0000000000..4cd75f26e7 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/utils/ParameterBlockUtil.java @@ -0,0 +1,24 @@ +package info.nightscout.androidaps.plugins.pump.insight.utils; + +import info.nightscout.androidaps.plugins.pump.insight.app_layer.ReadParameterBlockMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.Service; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.configuration.WriteConfigurationBlockMessage; +import info.nightscout.androidaps.plugins.pump.insight.app_layer.parameter_blocks.ParameterBlock; +import info.nightscout.androidaps.plugins.pump.insight.connection_service.InsightConnectionService; + +public class ParameterBlockUtil { + + public static T readParameterBlock(InsightConnectionService connectionService, Service service, Class parameterBlock) throws Exception { + ReadParameterBlockMessage readMessage = new ReadParameterBlockMessage(); + readMessage.setService(service); + readMessage.setParameterBlockId(parameterBlock); + return (T) connectionService.requestMessage(readMessage).await().getParameterBlock(); + } + + public static void writeConfigurationBlock(InsightConnectionService connectionService, ParameterBlock parameterBlock) throws Exception { + WriteConfigurationBlockMessage writeMessage = new WriteConfigurationBlockMessage(); + writeMessage.setParameterBlock(parameterBlock); + connectionService.requestMessage(writeMessage).await(); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/utils/crypto/CRC.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/utils/crypto/CRC.java new file mode 100644 index 0000000000..16fe253c1d --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/utils/crypto/CRC.java @@ -0,0 +1,44 @@ +package info.nightscout.androidaps.plugins.pump.insight.utils.crypto; + +/* + * Based on: http://introcs.cs.princeton.edu/java/61data/CRC16.java + * Table generated using: http://pycrc.org/ + * Command used: python pycrc.py --width 16 --poly 0x1021 --reflect-in True --reflect-out True --xor-in 0xffff --xor-out=0x0000 --generate TABLE + */ +class CRC { + + protected static final int[] TABLE = { + 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, + 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, + 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, + 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, + 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, + 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, + 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, + 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, + 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, + 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, + 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, + 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, + 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, + 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, + 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, + 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, + 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, + 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, + 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, + 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, + 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, + 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, + 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, + 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, + 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, + 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, + 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, + 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, + 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, + 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, + 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, + 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 + }; +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/utils/crypto/Cryptograph.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/utils/crypto/Cryptograph.java new file mode 100644 index 0000000000..bf34832b56 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/utils/crypto/Cryptograph.java @@ -0,0 +1,215 @@ +package info.nightscout.androidaps.plugins.pump.insight.utils.crypto; + +import org.spongycastle.crypto.AsymmetricCipherKeyPair; +import org.spongycastle.crypto.Digest; +import org.spongycastle.crypto.InvalidCipherTextException; +import org.spongycastle.crypto.digests.MD5Digest; +import org.spongycastle.crypto.digests.SHA1Digest; +import org.spongycastle.crypto.encodings.OAEPEncoding; +import org.spongycastle.crypto.engines.RSAEngine; +import org.spongycastle.crypto.engines.TwofishEngine; +import org.spongycastle.crypto.generators.RSAKeyPairGenerator; +import org.spongycastle.crypto.macs.HMac; +import org.spongycastle.crypto.modes.CBCBlockCipher; +import org.spongycastle.crypto.params.AsymmetricKeyParameter; +import org.spongycastle.crypto.params.KeyParameter; +import org.spongycastle.crypto.params.ParametersWithIV; +import org.spongycastle.crypto.params.RSAKeyGenerationParameters; +import org.spongycastle.crypto.params.RSAKeyParameters; +import org.spongycastle.crypto.params.RSAPrivateCrtKeyParameters; + +import java.math.BigInteger; +import java.security.SecureRandom; + +import info.nightscout.androidaps.plugins.pump.insight.utils.ByteBuf; + +public class Cryptograph { + + private static final String keySeed = "master secret"; + private static final String verificationSeed = "finished"; + + private static byte[] getHmac(byte[] secret, byte[] data, Digest algorithm) { + HMac hmac = new HMac(algorithm); + hmac.init(new KeyParameter(secret)); + byte[] result = new byte[hmac.getMacSize()]; + hmac.update(data, 0, data.length); + hmac.doFinal(result, 0); + return result; + } + + private static byte[] getMultiHmac(byte[] secret, byte[] data, int bytes, Digest algorithm) { + byte[] nuData = data; + byte[] output = new byte[bytes]; + int size = 0; + while (size < bytes) { + nuData = getHmac(secret, nuData, algorithm); + byte[] preOutput = getHmac(secret, combine(nuData, data), algorithm); + System.arraycopy(preOutput, 0, output, size, Math.min(bytes - size, preOutput.length)); + size += preOutput.length; + } + return output; + } + + private static byte[] sha1MultiHmac(byte[] secret, byte[] data, int bytes) { + return getMultiHmac(secret, data, bytes, new SHA1Digest()); + } + + private static byte[] md5MultiHmac(byte[] secret, byte[] data, int bytes) { + return getMultiHmac(secret, data, bytes, new MD5Digest()); + } + + public static byte[] getServicePasswordHash(String servicePassword, byte[] salt) { + return multiHashXOR(servicePassword.getBytes(), combine("service pwd".getBytes(), salt), 16); + } + + private static byte[] byteArrayXOR(byte[] array1, byte[] array2) { + int length = Math.min(array1.length, array2.length); + byte[] xor = new byte[length]; + for (int i = 0; i < length; i++) { + xor[i] = (byte) (array1[i] ^ array2[i]); + } + return xor; + } + + private static byte[] multiHashXOR(byte[] secret, byte[] seed, int bytes) { + byte[] array1 = new byte[secret.length / 2]; + byte[] array2 = new byte[array1.length]; + System.arraycopy(secret, 0, array1, 0, array1.length); + System.arraycopy(secret, array1.length, array2, 0, array2.length); + byte[] md5 = md5MultiHmac(array1, seed, bytes); + byte[] sha1 = sha1MultiHmac(array2, seed, bytes); + return byteArrayXOR(md5, sha1); + } + + public static DerivedKeys deriveKeys(byte[] verificationSeed, byte[] secret, byte[] random, byte[] peerRandom) { + byte[] result = multiHashXOR(secret, combine(combine(keySeed.getBytes(), random), peerRandom), 32); + DerivedKeys derivedKeys = new DerivedKeys(); + derivedKeys.incomingKey = new byte[result.length / 2]; + derivedKeys.outgoingKey = new byte[derivedKeys.incomingKey.length]; + System.arraycopy(result, 0, derivedKeys.incomingKey, 0, derivedKeys.incomingKey.length); + System.arraycopy(result, derivedKeys.incomingKey.length, derivedKeys.outgoingKey, 0, derivedKeys.outgoingKey.length); + derivedKeys.verificationString = calculateVerificationString(verificationSeed, result); + return derivedKeys; + } + + private static String calculateVerificationString(byte[] verificationSeed, byte[] key) { + byte[] verificationData = multiHashXOR(key, combine(Cryptograph.verificationSeed.getBytes(), verificationSeed), 8); + long value = 0; + for (int i = 7; i >= 0; i--) { + long byteValue = verificationData[i]; + if (byteValue < 0) byteValue += 256; + value |= byteValue << (i * 8); + } + StringBuilder stringBuilder = new StringBuilder(); + for (int index = 0; index < 10; index++) { + if (index == 3 || index == 6) stringBuilder.append(" "); + stringBuilder.append(VerificationString.TABLE[((int) value) & 63]); + value >>= 6; + } + return stringBuilder.toString(); + } + + private static byte[] processRSA(AsymmetricKeyParameter key, byte[] data, boolean encrypt) throws InvalidCipherTextException { + OAEPEncoding cipher = new OAEPEncoding(new RSAEngine()); + cipher.init(encrypt, key); + return cipher.processBlock(data, 0, data.length); + } + + public static byte[] decryptRSA(RSAPrivateCrtKeyParameters key, byte[] data) throws InvalidCipherTextException { + return processRSA(key, data, false); + } + + public static KeyPair generateRSAKey() { + RSAKeyPairGenerator generator = new RSAKeyPairGenerator(); + generator.init(new RSAKeyGenerationParameters(BigInteger.valueOf(65537), new SecureRandom(), 2048, 8)); + AsymmetricCipherKeyPair ackp = generator.generateKeyPair(); + KeyPair keyPair = new KeyPair(); + keyPair.privateKey = (RSAPrivateCrtKeyParameters) ackp.getPrivate(); + keyPair.publicKey = (RSAKeyParameters) ackp.getPublic(); + return keyPair; + } + + public static byte[] combine(byte[] array1, byte[] array2) { + byte[] combined = new byte[array1.length + array2.length]; + System.arraycopy(array1, 0, combined, 0, array1.length); + System.arraycopy(array2, 0, combined, array1.length, array2.length); + return combined; + } + + private static byte[] produceCCMPrimitive(byte headerByte, byte[] nonce, short number) { + ByteBuf byteBuf = new ByteBuf(16); + byteBuf.putByte(headerByte); + byteBuf.putBytes(nonce); + byteBuf.putShort(number); + return byteBuf.getBytes(); + } + + private static byte[] produceIV(byte[] nonce, short payloadSize) { + return produceCCMPrimitive((byte) 0x59, nonce, payloadSize); + } + + private static byte[] produceCTRBlock(byte[] nonce, short counter) { + return produceCCMPrimitive((byte) 0x01, nonce, counter); + } + + private static byte[] blockCipherZeroPad(byte[] input) { + int modulus = input.length % 16; + if (modulus == 0) return input; + byte[] append = new byte[16 - modulus]; + for (int i = 0; i < 16 - modulus; i++) { + append[i] = 0x00; + } + return combine(input, append); + } + + public static byte[] encryptDataCTR(byte[] data, byte[] key, byte[] nonce) { + byte[] padded = blockCipherZeroPad(data); + int length = padded.length >> 4; + byte[] result = new byte[length * 16]; + TwofishEngine engine = new TwofishEngine(); + engine.init(true, new KeyParameter(key)); + for (int i = 0; i < length; i++) { + engine.processBlock(produceCTRBlock(nonce, (short) (i + 1)), 0, result, i * 16); + } + byte[] xor = byteArrayXOR(padded, result); + byte[] copy = new byte[Math.min(data.length, xor.length)]; + System.arraycopy(xor, 0, copy, 0, copy.length); + return copy; + } + + private static byte[] processHeader(byte[] header) { + ByteBuf byteBuf; + byteBuf = new ByteBuf(2 + header.length); + byteBuf.putShort((short) header.length); + byteBuf.putBytes(header); + return byteBuf.getBytes(); + } + + public static byte[] produceCCMTag(byte[] nonce, byte[] payload, byte[] header, byte[] key) { + TwofishEngine engine = new TwofishEngine(); + engine.init(true, new KeyParameter(key)); + byte[] initializationVector = new byte[engine.getBlockSize()]; + engine.processBlock(produceIV(nonce, (short) payload.length), 0, initializationVector, 0); + CBCBlockCipher cbc = new CBCBlockCipher(new TwofishEngine()); + cbc.init(true, new ParametersWithIV(new KeyParameter(key), initializationVector)); + byte[] processedHeader = blockCipherZeroPad(processHeader(header)); + byte[] processedPayload = blockCipherZeroPad(payload); + byte[] combine = combine(processedHeader, blockCipherZeroPad(processedPayload)); + byte[] result = new byte[combine.length]; + for (int i = 0; i < combine.length / 16; i++) + cbc.processBlock(combine, i * 16, result, i * 16); + byte[] result2 = new byte[8]; + System.arraycopy(result, result.length - 16, result2, 0, 8); + byte[] ctr = new byte[engine.getBlockSize()]; + engine.processBlock(produceCTRBlock(nonce, (short) 0), 0, ctr, 0); + return byteArrayXOR(result2, ctr); + } + + public static int calculateCRC(byte[] bytes) { + int crc = 0xffff; + for (byte b : bytes) { + crc = (crc >>> 8) ^ CRC.TABLE[(crc ^ b) & 0xff]; + } + return crc; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/utils/crypto/DerivedKeys.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/utils/crypto/DerivedKeys.java new file mode 100644 index 0000000000..0e35ceeb31 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/utils/crypto/DerivedKeys.java @@ -0,0 +1,32 @@ +package info.nightscout.androidaps.plugins.pump.insight.utils.crypto; + +public class DerivedKeys { + + byte[] incomingKey; + byte[] outgoingKey; + String verificationString; + + public byte[] getIncomingKey() { + return this.incomingKey; + } + + public byte[] getOutgoingKey() { + return this.outgoingKey; + } + + public String getVerificationString() { + return this.verificationString; + } + + public void setIncomingKey(byte[] incomingKey) { + this.incomingKey = incomingKey; + } + + public void setOutgoingKey(byte[] outgoingKey) { + this.outgoingKey = outgoingKey; + } + + public void setVerificationString(String verificationString) { + this.verificationString = verificationString; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/utils/crypto/KeyPair.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/utils/crypto/KeyPair.java new file mode 100644 index 0000000000..44025fcccc --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/utils/crypto/KeyPair.java @@ -0,0 +1,28 @@ +package info.nightscout.androidaps.plugins.pump.insight.utils.crypto; + +import org.spongycastle.crypto.params.RSAKeyParameters; +import org.spongycastle.crypto.params.RSAPrivateCrtKeyParameters; + +public class KeyPair { + + protected KeyPair() { + } + + RSAPrivateCrtKeyParameters privateKey; + RSAKeyParameters publicKey; + + public byte[] getPublicKeyBytes() { + byte[] modulus = publicKey.getModulus().toByteArray(); + byte[] bytes = new byte[256]; + System.arraycopy(modulus, 1, bytes, 0, 256); + return bytes; + } + + public RSAPrivateCrtKeyParameters getPrivateKey() { + return this.privateKey; + } + + public RSAKeyParameters getPublicKey() { + return this.publicKey; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/utils/crypto/VerificationString.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/utils/crypto/VerificationString.java new file mode 100644 index 0000000000..c40e96910f --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/insight/utils/crypto/VerificationString.java @@ -0,0 +1,15 @@ +package info.nightscout.androidaps.plugins.pump.insight.utils.crypto; + +class VerificationString { + + static char[] TABLE = new char[] { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', + 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', + 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', + 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', + 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', + 'w', 'x', 'y', 'z', '0', '1', '2', '3', + '4', '5', '6', '7', '8', '9', '+', '/' + }; +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMDI/MDIPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/mdi/MDIPlugin.java similarity index 83% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpMDI/MDIPlugin.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/mdi/MDIPlugin.java index 7caca31891..21cac73d5d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMDI/MDIPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/mdi/MDIPlugin.java @@ -1,10 +1,12 @@ -package info.nightscout.androidaps.plugins.PumpMDI; +package info.nightscout.androidaps.plugins.pump.mdi; import org.json.JSONException; import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.List; + import info.nightscout.androidaps.BuildConfig; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; @@ -17,8 +19,14 @@ import info.nightscout.androidaps.interfaces.PluginType; import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; -import info.nightscout.utils.DateUtil; +import info.nightscout.androidaps.plugins.common.ManufacturerType; +import info.nightscout.androidaps.plugins.general.actions.defs.CustomAction; +import info.nightscout.androidaps.plugins.general.actions.defs.CustomActionType; +import info.nightscout.androidaps.plugins.pump.common.defs.PumpType; +import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; +import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.InstanceId; + /** * Created by mike on 05.08.2016. @@ -136,6 +144,12 @@ public class MDIPlugin extends PluginBase implements PumpInterface { return 0d; } + @Override + public double getReservoirLevel() { return -1; } + + @Override + public int getBatteryLevel() { return -1; } + @Override public PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo) { PumpEnactResult result = new PumpEnactResult(); @@ -225,8 +239,18 @@ public class MDIPlugin extends PluginBase implements PumpInterface { } @Override - public String deviceID() { - return "MDI"; + public ManufacturerType manufacturer() { + return ManufacturerType.AndroidAPS; + } + + @Override + public PumpType model() { + return PumpType.MDI; + } + + @Override + public String serialNumber() { + return InstanceId.INSTANCE.instanceId(); } @Override @@ -236,7 +260,28 @@ public class MDIPlugin extends PluginBase implements PumpInterface { @Override public String shortStatus(boolean veryShort) { - return deviceID(); + return model().getModel(); } + @Override + public List getCustomActions() { + return null; + } + + @Override + public void executeCustomAction(CustomActionType customActionType) { + + } + + @Override + public boolean canHandleDST() { + return true; + } + + @Override + public void timeDateOrTimeZoneChanged() { + + } + + } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicFragment.kt new file mode 100644 index 0000000000..69e0e0bbe8 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicFragment.kt @@ -0,0 +1,317 @@ +package info.nightscout.androidaps.plugins.pump.medtronic + +import android.content.Intent +import android.graphics.Color +import android.os.Bundle +import android.os.Handler +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import info.nightscout.androidaps.MainApp +import info.nightscout.androidaps.R +import info.nightscout.androidaps.events.EventExtendedBolusChange +import info.nightscout.androidaps.events.EventPumpStatusChanged +import info.nightscout.androidaps.events.EventTempBasalChange +import info.nightscout.androidaps.logging.L +import info.nightscout.androidaps.plugins.bus.RxBus +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkError +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkServiceState +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkTargetDevice +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.dialog.RileyLinkStatusActivity +import info.nightscout.androidaps.plugins.pump.medtronic.defs.BatteryType +import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicCommandType +import info.nightscout.androidaps.plugins.pump.medtronic.defs.PumpDeviceState +import info.nightscout.androidaps.plugins.pump.medtronic.dialog.MedtronicHistoryActivity +import info.nightscout.androidaps.plugins.pump.medtronic.driver.MedtronicPumpStatus +import info.nightscout.androidaps.plugins.pump.medtronic.events.EventMedtronicDeviceStatusChange +import info.nightscout.androidaps.plugins.pump.medtronic.events.EventMedtronicPumpConfigurationChanged +import info.nightscout.androidaps.plugins.pump.medtronic.events.EventMedtronicPumpValuesChanged +import info.nightscout.androidaps.plugins.pump.medtronic.events.EventRefreshButtonState +import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil +import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin +import info.nightscout.androidaps.queue.Callback +import info.nightscout.androidaps.queue.events.EventQueueChanged +import info.nightscout.androidaps.utils.* +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.disposables.CompositeDisposable +import kotlinx.android.synthetic.main.medtronic_fragment.* +import org.slf4j.LoggerFactory + + +class MedtronicFragment : Fragment() { + private val log = LoggerFactory.getLogger(L.PUMP) + private var disposable: CompositeDisposable = CompositeDisposable() + + private val loopHandler = Handler() + private lateinit var refreshLoop: Runnable + + init { + refreshLoop = Runnable { + activity?.runOnUiThread { updateGUI() } + loopHandler.postDelayed(refreshLoop, T.mins(1).msecs()) + } + } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + return inflater.inflate(R.layout.medtronic_fragment, container, false) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + medtronic_pumpstatus.setBackgroundColor(MainApp.gc(R.color.colorInitializingBorder)) + + medtronic_rl_status.text = MainApp.gs(RileyLinkServiceState.NotStarted.getResourceId(RileyLinkTargetDevice.MedtronicPump)) + + medtronic_pump_status.setTextColor(Color.WHITE) + medtronic_pump_status.text = "{fa-bed}" + + medtronic_history.setOnClickListener { + if (MedtronicUtil.getPumpStatus().verifyConfiguration()) { + startActivity(Intent(context, MedtronicHistoryActivity::class.java)) + } else { + MedtronicUtil.displayNotConfiguredDialog(context) + } + } + + medtronic_refresh.setOnClickListener { + if (!MedtronicUtil.getPumpStatus().verifyConfiguration()) { + MedtronicUtil.displayNotConfiguredDialog(context) + } else { + medtronic_refresh.isEnabled = false + MedtronicPumpPlugin.getPlugin().resetStatusState() + ConfigBuilderPlugin.getPlugin().commandQueue.readStatus("Clicked refresh", object : Callback() { + override fun run() { + activity?.runOnUiThread { medtronic_refresh?.isEnabled = true } + } + }) + } + } + + medtronic_stats.setOnClickListener { + if (MedtronicUtil.getPumpStatus().verifyConfiguration()) { + startActivity(Intent(context, RileyLinkStatusActivity::class.java)) + } else { + MedtronicUtil.displayNotConfiguredDialog(context) + } + } + } + + @Synchronized + override fun onResume() { + super.onResume() + loopHandler.postDelayed(refreshLoop, T.mins(1).msecs()) + disposable += RxBus + .toObservable(EventRefreshButtonState::class.java) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe({ medtronic_refresh.isEnabled = it.newState }, { FabricPrivacy.logException(it) }) + disposable += RxBus + .toObservable(EventMedtronicDeviceStatusChange::class.java) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe({ + if (L.isEnabled(L.PUMP)) + log.info("onStatusEvent(EventMedtronicDeviceStatusChange): {}", it) + setDeviceStatus() + }, { FabricPrivacy.logException(it) }) + disposable += RxBus + .toObservable(EventMedtronicPumpValuesChanged::class.java) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe({ updateGUI() }, { FabricPrivacy.logException(it) }) + disposable += RxBus + .toObservable(EventExtendedBolusChange::class.java) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe({ updateGUI() }, { FabricPrivacy.logException(it) }) + disposable += RxBus + .toObservable(EventTempBasalChange::class.java) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe({ updateGUI() }, { FabricPrivacy.logException(it) }) + disposable += RxBus + .toObservable(EventMedtronicPumpConfigurationChanged::class.java) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe({ + if (L.isEnabled(L.PUMP)) + log.debug("EventMedtronicPumpConfigurationChanged triggered") + MedtronicUtil.getPumpStatus().verifyConfiguration() + updateGUI() + }, { FabricPrivacy.logException(it) }) + disposable += RxBus + .toObservable(EventPumpStatusChanged::class.java) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe({ updateGUI() }, { FabricPrivacy.logException(it) }) + disposable += RxBus + .toObservable(EventQueueChanged::class.java) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe({ updateGUI() }, { FabricPrivacy.logException(it) }) + + updateGUI() + } + + @Synchronized + override fun onPause() { + super.onPause() + disposable.clear() + loopHandler.removeCallbacks(refreshLoop) + } + + @Synchronized + private fun setDeviceStatus() { + val pumpStatus: MedtronicPumpStatus = MedtronicUtil.getPumpStatus() + pumpStatus.rileyLinkServiceState = checkStatusSet(pumpStatus.rileyLinkServiceState, + RileyLinkUtil.getServiceState()) as RileyLinkServiceState? + + val resourceId = pumpStatus.rileyLinkServiceState.getResourceId(RileyLinkTargetDevice.MedtronicPump) + val rileyLinkError = RileyLinkUtil.getError() + medtronic_rl_status.text = + when { + pumpStatus.rileyLinkServiceState == RileyLinkServiceState.NotStarted -> MainApp.gs(resourceId) + pumpStatus.rileyLinkServiceState.isConnecting -> "{fa-bluetooth-b spin} " + MainApp.gs(resourceId) + pumpStatus.rileyLinkServiceState.isError && rileyLinkError == null -> "{fa-bluetooth-b} " + MainApp.gs(resourceId) + pumpStatus.rileyLinkServiceState.isError && rileyLinkError != null -> "{fa-bluetooth-b} " + MainApp.gs(rileyLinkError.getResourceId(RileyLinkTargetDevice.MedtronicPump)) + else -> "{fa-bluetooth-b} " + MainApp.gs(resourceId) + } + medtronic_rl_status.setTextColor(if (rileyLinkError != null) Color.RED else Color.WHITE) + + pumpStatus.rileyLinkError = checkStatusSet(pumpStatus.rileyLinkError, RileyLinkUtil.getError()) as RileyLinkError? + + medtronic_errors.text = + pumpStatus.rileyLinkError?.let { + MainApp.gs(it.getResourceId(RileyLinkTargetDevice.MedtronicPump)) + } ?: "-" + + pumpStatus.pumpDeviceState = checkStatusSet(pumpStatus.pumpDeviceState, + MedtronicUtil.getPumpDeviceState()) as PumpDeviceState? + + when (pumpStatus.pumpDeviceState) { + null, + PumpDeviceState.Sleeping -> medtronic_pump_status.text = "{fa-bed} " // + pumpStatus.pumpDeviceState.name()); + PumpDeviceState.NeverContacted, + PumpDeviceState.WakingUp, + PumpDeviceState.PumpUnreachable, + PumpDeviceState.ErrorWhenCommunicating, + PumpDeviceState.TimeoutWhenCommunicating, + PumpDeviceState.InvalidConfiguration -> medtronic_pump_status.text = " " + MainApp.gs(pumpStatus.pumpDeviceState.resourceId) + PumpDeviceState.Active -> { + val cmd = MedtronicUtil.getCurrentCommand() + if (cmd == null) + medtronic_pump_status.text = " " + MainApp.gs(pumpStatus.pumpDeviceState.resourceId) + else { + log.debug("Command: " + cmd) + val cmdResourceId = cmd.resourceId + if (cmd == MedtronicCommandType.GetHistoryData) { + medtronic_pump_status.text = MedtronicUtil.frameNumber?.let { + MainApp.gs(cmdResourceId, MedtronicUtil.pageNumber, MedtronicUtil.frameNumber) + } + ?: MainApp.gs(R.string.medtronic_cmd_desc_get_history_request, MedtronicUtil.pageNumber) + } else { + medtronic_pump_status.text = " " + (cmdResourceId?.let { MainApp.gs(it) } + ?: cmd.getCommandDescription()) + } + } + } + else -> log.warn("Unknown pump state: " + pumpStatus.pumpDeviceState) + } + + val status = ConfigBuilderPlugin.getPlugin().commandQueue.spannedStatus() + if (status.toString() == "") { + medtronic_queue.visibility = View.GONE + } else { + medtronic_queue.visibility = View.VISIBLE + medtronic_queue.text = status + } + } + + + private fun checkStatusSet(object1: Any?, object2: Any?): Any? { + return if (object1 == null) { + object2 + } else { + if (object1 != object2) { + object2 + } else + object1 + } + } + + // GUI functions + @Synchronized + fun updateGUI() { + if (medtronic_rl_status == null) return + val plugin = MedtronicPumpPlugin.getPlugin() + val pumpStatus = MedtronicUtil.getPumpStatus() + + setDeviceStatus() + + // last connection + if (pumpStatus.lastConnection != 0L) { + val minAgo = DateUtil.minAgo(pumpStatus.lastConnection) + val min = (System.currentTimeMillis() - pumpStatus.lastConnection) / 1000 / 60 + if (pumpStatus.lastConnection + 60 * 1000 > System.currentTimeMillis()) { + medtronic_lastconnection.setText(R.string.combo_pump_connected_now) + medtronic_lastconnection.setTextColor(Color.WHITE) + } else if (pumpStatus.lastConnection + 30 * 60 * 1000 < System.currentTimeMillis()) { + + if (min < 60) { + medtronic_lastconnection.text = MainApp.gs(R.string.minago, min) + } else if (min < 1440) { + val h = (min / 60).toInt() + medtronic_lastconnection.text = (MainApp.gq(R.plurals.objective_hours, h, h) + " " + + MainApp.gs(R.string.ago)) + } else { + val h = (min / 60).toInt() + val d = h / 24 + // h = h - (d * 24); + medtronic_lastconnection.text = (MainApp.gq(R.plurals.objective_days, d, d) + " " + + MainApp.gs(R.string.ago)) + } + medtronic_lastconnection.setTextColor(Color.RED) + } else { + medtronic_lastconnection.text = minAgo + medtronic_lastconnection.setTextColor(Color.WHITE) + } + } + + // last bolus + val bolus = pumpStatus.lastBolusAmount + val bolusTime = pumpStatus.lastBolusTime + if (bolus != null && bolusTime != null) { + val agoMsc = System.currentTimeMillis() - pumpStatus.lastBolusTime.time + val bolusMinAgo = agoMsc.toDouble() / 60.0 / 1000.0 + val unit = MainApp.gs(R.string.insulin_unit_shortname) + val ago: String + if (agoMsc < 60 * 1000) { + ago = MainApp.gs(R.string.combo_pump_connected_now) + } else if (bolusMinAgo < 60) { + ago = DateUtil.minAgo(pumpStatus.lastBolusTime.time) + } else { + ago = DateUtil.hourAgo(pumpStatus.lastBolusTime.time) + } + medtronic_lastbolus.text = MainApp.gs(R.string.combo_last_bolus, bolus, unit, ago) + } else { + medtronic_lastbolus.text = "" + } + + // base basal rate + medtronic_basabasalrate.text = ("(" + pumpStatus.activeProfileName + ") " + + MainApp.gs(R.string.pump_basebasalrate, plugin.baseBasalRate)) + + medtronic_tempbasal.text = TreatmentsPlugin.getPlugin() + .getTempBasalFromHistory(System.currentTimeMillis())?.toStringFull() ?: "" + + // battery + if (MedtronicUtil.getBatteryType() == BatteryType.None || pumpStatus.batteryVoltage == null) { + medtronic_pumpstate_battery.text = "{fa-battery-" + pumpStatus.batteryRemaining / 25 + "} " + } else { + medtronic_pumpstate_battery.text = "{fa-battery-" + pumpStatus.batteryRemaining / 25 + "} " + pumpStatus.batteryRemaining + "%" + String.format(" (%.2f V)", pumpStatus.batteryVoltage) + } + SetWarnColor.setColorInverse(medtronic_pumpstate_battery, pumpStatus.batteryRemaining.toDouble(), 25.0, 10.0) + + // reservoir + medtronic_reservoir.text = MainApp.gs(R.string.reservoirvalue, pumpStatus.reservoirRemainingUnits, pumpStatus.reservoirFullUnits) + SetWarnColor.setColorInverse(medtronic_reservoir, pumpStatus.reservoirRemainingUnits, 50.0, 20.0) + + medtronic_errors.text = pumpStatus.errorInfo + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.java new file mode 100644 index 0000000000..ae6d754493 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.java @@ -0,0 +1,1622 @@ +package info.nightscout.androidaps.plugins.pump.medtronic; + +import android.content.ComponentName; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.Bundle; +import android.os.IBinder; +import android.os.SystemClock; + +import androidx.annotation.NonNull; + +import org.joda.time.LocalDateTime; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +import info.nightscout.androidaps.BuildConfig; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.data.DetailedBolusInfo; +import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.data.PumpEnactResult; +import info.nightscout.androidaps.db.Source; +import info.nightscout.androidaps.db.TemporaryBasal; +import info.nightscout.androidaps.events.EventCustomActionsChanged; +import info.nightscout.androidaps.events.EventRefreshOverview; +import info.nightscout.androidaps.interfaces.PluginDescription; +import info.nightscout.androidaps.interfaces.PluginType; +import info.nightscout.androidaps.interfaces.PumpInterface; +import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.common.ManufacturerType; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.general.actions.defs.CustomAction; +import info.nightscout.androidaps.plugins.general.actions.defs.CustomActionType; +import info.nightscout.androidaps.plugins.general.overview.dialogs.ErrorHelperActivity; +import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; +import info.nightscout.androidaps.plugins.pump.common.PumpPluginAbstract; +import info.nightscout.androidaps.plugins.pump.common.defs.PumpDriverState; +import info.nightscout.androidaps.plugins.pump.common.defs.PumpType; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkConst; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkServiceState; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.ResetRileyLinkConfigurationTask; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.ServiceTaskExecutor; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.WakeAndTuneTask; +import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil; +import info.nightscout.androidaps.plugins.pump.medtronic.comm.MedtronicCommunicationManager; +import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryEntry; +import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryResult; +import info.nightscout.androidaps.plugins.pump.medtronic.comm.ui.MedtronicUIComm; +import info.nightscout.androidaps.plugins.pump.medtronic.comm.ui.MedtronicUITask; +import info.nightscout.androidaps.plugins.pump.medtronic.data.MedtronicHistoryData; +import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.BasalProfile; +import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.BasalProfileEntry; +import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.ClockDTO; +import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.TempBasalPair; +import info.nightscout.androidaps.plugins.pump.medtronic.defs.BasalProfileStatus; +import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicCommandType; +import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicCustomActionType; +import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicNotificationType; +import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicStatusRefreshType; +import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicUIResponseType; +import info.nightscout.androidaps.plugins.pump.medtronic.driver.MedtronicPumpStatus; +import info.nightscout.androidaps.plugins.pump.medtronic.events.EventMedtronicPumpValuesChanged; +import info.nightscout.androidaps.plugins.pump.medtronic.events.EventRefreshButtonState; +import info.nightscout.androidaps.plugins.pump.medtronic.service.RileyLinkMedtronicService; +import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicConst; +import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil; +import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; +import info.nightscout.androidaps.utils.SP; + +import static info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil.sendNotification; + +/** + * Created by andy on 23.04.18. + * + * @author Andy Rozman (andy.rozman@gmail.com) + */ +public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInterface { + + private static final Logger LOG = LoggerFactory.getLogger(L.PUMP); + + protected static MedtronicPumpPlugin plugin = null; + private RileyLinkMedtronicService medtronicService; + private MedtronicPumpStatus pumpStatusLocal = null; + private MedtronicUIComm medtronicUIComm = new MedtronicUIComm(); + + // variables for handling statuses and history + private boolean firstRun = true; + private boolean isRefresh = false; + private boolean isBasalProfileInvalid = false; + private boolean basalProfileChanged = false; + private Map statusRefreshMap = new HashMap<>(); + private boolean isInitialized = false; + private MedtronicHistoryData medtronicHistoryData; + private MedtronicCommunicationManager medtronicCommunicationManager; + private PumpHistoryEntry lastPumpHistoryEntry; + + public static boolean isBusy = false; + private List busyTimestamps = new ArrayList<>(); + private boolean sentIdToFirebase = false; + private boolean hasTimeDateOrTimeZoneChanged = false; + + + private MedtronicPumpPlugin() { + + super(new PluginDescription() // + .mainType(PluginType.PUMP) // + .fragmentClass(MedtronicFragment.class.getName()) // + .pluginName(R.string.medtronic_name) // + .shortName(R.string.medtronic_name_short) // + .preferencesId(R.xml.pref_medtronic).description(R.string.description_pump_medtronic), // + PumpType.Medtronic_522_722 // we default to most basic model, correct model from config is loaded later + ); + + displayConnectionMessages = false; + + medtronicHistoryData = new MedtronicHistoryData(); + + serviceConnection = new ServiceConnection() { + + public void onServiceDisconnected(ComponentName name) { + if (isLoggingEnabled()) + LOG.debug("RileyLinkMedtronicService is disconnected"); + medtronicService = null; + } + + public void onServiceConnected(ComponentName name, IBinder service) { + if (isLoggingEnabled()) + LOG.debug("RileyLinkMedtronicService is connected"); + RileyLinkMedtronicService.LocalBinder mLocalBinder = (RileyLinkMedtronicService.LocalBinder) service; + medtronicService = mLocalBinder.getServiceInstance(); + + new Thread(() -> { + + for (int i = 0; i < 20; i++) { + SystemClock.sleep(5000); + + if (MedtronicUtil.getPumpStatus() != null) { + if (isLoggingEnabled()) + LOG.debug("Starting Medtronic-RileyLink service"); + if (MedtronicUtil.getPumpStatus().setNotInPreInit()) { + break; + } + } + } + }).start(); + } + }; + } + + + public static MedtronicPumpPlugin getPlugin() { + if (plugin == null) + plugin = new MedtronicPumpPlugin(); + return plugin; + } + + + private String getLogPrefix() { + return "MedtronicPumpPlugin::"; + } + + + public MedtronicHistoryData getMedtronicHistoryData() { + return this.medtronicHistoryData; + } + + + @Override + public void initPumpStatusData() { + + this.pumpStatusLocal = new MedtronicPumpStatus(pumpDescription); + MedtronicUtil.setPumpStatus(pumpStatusLocal); + + pumpStatusLocal.lastConnection = SP.getLong(RileyLinkConst.Prefs.LastGoodDeviceCommunicationTime, 0L); + pumpStatusLocal.lastDataTime = new LocalDateTime(pumpStatusLocal.lastConnection); + pumpStatusLocal.previousConnection = pumpStatusLocal.lastConnection; + + pumpStatusLocal.refreshConfiguration(); + + if (isLoggingEnabled()) + LOG.debug("initPumpStatusData: {}", this.pumpStatusLocal); + + this.pumpStatus = pumpStatusLocal; + + // this is only thing that can change, by being configured + pumpDescription.maxTempAbsolute = (pumpStatusLocal.maxBasal != null) ? pumpStatusLocal.maxBasal : 35.0d; + + // set first Medtronic Pump Start + if (!SP.contains(MedtronicConst.Statistics.FirstPumpStart)) { + SP.putLong(MedtronicConst.Statistics.FirstPumpStart, System.currentTimeMillis()); + } + + migrateSettings(); + + } + + + private void migrateSettings() { + + if ("US (916 MHz)".equals(SP.getString(MedtronicConst.Prefs.PumpFrequency, null))) { + SP.putString(MedtronicConst.Prefs.PumpFrequency, MainApp.gs(R.string.key_medtronic_pump_frequency_us_ca)); + } + + String encoding = SP.getString(MedtronicConst.Prefs.Encoding, null); + + if ("RileyLink 4b6b Encoding".equals(encoding)) { + SP.putString(MedtronicConst.Prefs.Encoding, MainApp.gs(R.string.key_medtronic_pump_encoding_4b6b_rileylink)); + } + + if ("Local 4b6b Encoding".equals(encoding)) { + SP.putString(MedtronicConst.Prefs.Encoding, MainApp.gs(R.string.key_medtronic_pump_encoding_4b6b_local)); + } + } + + + public void onStartCustomActions() { + + // check status every minute (if any status needs refresh we send readStatus command) + new Thread(() -> { + + do { + SystemClock.sleep(60000); + + if (this.isInitialized) { + + Map statusRefresh = workWithStatusRefresh( + StatusRefreshAction.GetData, null, null); + + if (doWeHaveAnyStatusNeededRefereshing(statusRefresh)) { + if (!ConfigBuilderPlugin.getPlugin().getCommandQueue().statusInQueue()) { + ConfigBuilderPlugin.getPlugin().getCommandQueue() + .readStatus("Scheduled Status Refresh", null); + } + } + + clearBusyQueue(); + } + + } while (serviceRunning); + + }).start(); + } + + + public Class getServiceClass() { + return RileyLinkMedtronicService.class; + } + + + @Override + public String deviceID() { + return "Medtronic"; + } + + + @Override + public boolean isFakingTempsByExtendedBoluses() { + return false; + } + + + @Override + public boolean canHandleDST() { + return false; + } + + + // Pump Plugin + + private boolean isServiceSet() { + return medtronicService != null; + } + + + @Override + public boolean isInitialized() { + if (isLoggingEnabled() && displayConnectionMessages) + LOG.debug("MedtronicPumpPlugin::isInitialized"); + return isServiceSet() && isInitialized; + } + + + @Override + public boolean isBusy() { + if (isLoggingEnabled() && displayConnectionMessages) + LOG.debug("MedtronicPumpPlugin::isBusy"); + + if (isServiceSet()) { + + if (isBusy) + return true; + + if (busyTimestamps.size() > 0) { + + clearBusyQueue(); + + if (busyTimestamps.size() > 0) { + return true; + } + } + } + + return false; + } + + + private synchronized void clearBusyQueue() { + + if (busyTimestamps.size() == 0) { + return; + } + + Set deleteFromQueue = new HashSet<>(); + + for (Long busyTimestamp : busyTimestamps) { + + if (System.currentTimeMillis() > busyTimestamp) { + deleteFromQueue.add(busyTimestamp); + } + } + + if (deleteFromQueue.size() == busyTimestamps.size()) { + busyTimestamps.clear(); + setEnableCustomAction(MedtronicCustomActionType.ClearBolusBlock, false); + } + + if (deleteFromQueue.size() > 0) { + busyTimestamps.removeAll(deleteFromQueue); + } + + } + + + @Override + public boolean isConnected() { + if (isLoggingEnabled() && displayConnectionMessages) + LOG.debug("MedtronicPumpPlugin::isConnected"); + return isServiceSet() && medtronicService.isInitialized(); + } + + + @Override + public boolean isConnecting() { + if (isLoggingEnabled() && displayConnectionMessages) + LOG.debug("MedtronicPumpPlugin::isConnecting"); + return !isServiceSet() || !medtronicService.isInitialized(); + } + + + @Override + public void getPumpStatus() { + + getMDTPumpStatus(); + + if (firstRun) { + initializePump(!isRefresh); + } else { + refreshAnyStatusThatNeedsToBeRefreshed(); + } + + RxBus.INSTANCE.send(new EventMedtronicPumpValuesChanged()); + } + + + void resetStatusState() { + firstRun = true; + isRefresh = true; + } + + + private boolean isPumpNotReachable() { + + RileyLinkServiceState rileyLinkServiceState = MedtronicUtil.getServiceState(); + + if (rileyLinkServiceState==null) { + LOG.error("RileyLink unreachable. RileyLinkServiceState is null."); + return false; + } + + if (rileyLinkServiceState != RileyLinkServiceState.PumpConnectorReady // + && rileyLinkServiceState != RileyLinkServiceState.RileyLinkReady // + && rileyLinkServiceState != RileyLinkServiceState.TuneUpDevice) { + LOG.error("RileyLink unreachable."); + return false; + } + + return (!medtronicCommunicationManager.isDeviceReachable()); + } + + + private void refreshAnyStatusThatNeedsToBeRefreshed() { + + Map statusRefresh = workWithStatusRefresh(StatusRefreshAction.GetData, null, + null); + + if (!doWeHaveAnyStatusNeededRefereshing(statusRefresh)) { + return; + } + + boolean resetTime = false; + + if (isPumpNotReachable()) { + if (isLoggingEnabled()) + LOG.error("Pump unreachable."); + MedtronicUtil.sendNotification(MedtronicNotificationType.PumpUnreachable); + + return; + } + + MedtronicUtil.dismissNotification(MedtronicNotificationType.PumpUnreachable); + + + if (hasTimeDateOrTimeZoneChanged) { + + checkTimeAndOptionallySetTime(); + + // read time if changed, set new time + hasTimeDateOrTimeZoneChanged = false; + } + + + // execute + Set refreshTypesNeededToReschedule = new HashSet<>(); + + for (Map.Entry refreshType : statusRefresh.entrySet()) { + + if (refreshType.getValue() > 0 && System.currentTimeMillis() > refreshType.getValue()) { + + switch (refreshType.getKey()) { + case PumpHistory: { + readPumpHistory(); + } + break; + + case PumpTime: { + checkTimeAndOptionallySetTime(); + refreshTypesNeededToReschedule.add(refreshType.getKey()); + resetTime = true; + } + break; + + case BatteryStatus: + case RemainingInsulin: { + medtronicUIComm.executeCommand(refreshType.getKey().getCommandType()); + refreshTypesNeededToReschedule.add(refreshType.getKey()); + resetTime = true; + } + break; + + case Configuration: { + medtronicUIComm.executeCommand(refreshType.getKey().getCommandType()); + resetTime = true; + } + break; + } + } + + // reschedule + for (MedtronicStatusRefreshType refreshType2 : refreshTypesNeededToReschedule) { + scheduleNextRefresh(refreshType2); + } + + } + + if (resetTime) + pumpStatusLocal.setLastCommunicationToNow(); + + } + + + private boolean doWeHaveAnyStatusNeededRefereshing(Map statusRefresh) { + + for (Map.Entry refreshType : statusRefresh.entrySet()) { + + if (refreshType.getValue() > 0 && System.currentTimeMillis() > refreshType.getValue()) { + return true; + } + } + + return hasTimeDateOrTimeZoneChanged; + } + + + private void setRefreshButtonEnabled(boolean enabled) { + RxBus.INSTANCE.send(new EventRefreshButtonState(enabled)); + } + + + private void initializePump(boolean realInit) { + + if (isLoggingEnabled()) + LOG.info(getLogPrefix() + "initializePump - start"); + + if (medtronicCommunicationManager == null) { + medtronicCommunicationManager = MedtronicCommunicationManager.getInstance(); + medtronicCommunicationManager.setDoWakeUpBeforeCommand(false); + } + + setRefreshButtonEnabled(false); + + getMDTPumpStatus(); + + if (isRefresh) { + if (isPumpNotReachable()) { + if (isLoggingEnabled()) + LOG.error(getLogPrefix() + "initializePump::Pump unreachable."); + MedtronicUtil.sendNotification(MedtronicNotificationType.PumpUnreachable); + + setRefreshButtonEnabled(true); + + return; + } + + MedtronicUtil.dismissNotification(MedtronicNotificationType.PumpUnreachable); + } + + // model (once) + if (MedtronicUtil.getMedtronicPumpModel() == null) { + medtronicUIComm.executeCommand(MedtronicCommandType.PumpModel); + } else { + if (pumpStatusLocal.medtronicDeviceType != MedtronicUtil.getMedtronicPumpModel()) { + if (isLoggingEnabled()) + LOG.warn(getLogPrefix() + "Configured pump is not the same as one detected."); + MedtronicUtil.sendNotification(MedtronicNotificationType.PumpTypeNotSame); + } + } + + this.pumpState = PumpDriverState.Connected; + + // time (1h) + checkTimeAndOptionallySetTime(); + + readPumpHistory(); + + // remaining insulin (>50 = 4h; 50-20 = 1h; 15m) + medtronicUIComm.executeCommand(MedtronicCommandType.GetRemainingInsulin); + scheduleNextRefresh(MedtronicStatusRefreshType.RemainingInsulin, 10); + + // remaining power (1h) + medtronicUIComm.executeCommand(MedtronicCommandType.GetBatteryStatus); + scheduleNextRefresh(MedtronicStatusRefreshType.BatteryStatus, 20); + + // configuration (once and then if history shows config changes) + medtronicUIComm.executeCommand(MedtronicCommandType.getSettings(MedtronicUtil.getMedtronicPumpModel())); + + // read profile (once, later its controlled by isThisProfileSet method) + getBasalProfiles(); + + int errorCount = medtronicUIComm.getInvalidResponsesCount(); + + if (errorCount >= 5) { + if (isLoggingEnabled()) + LOG.error("Number of error counts was 5 or more. Starting tunning."); + setRefreshButtonEnabled(true); + ServiceTaskExecutor.startTask(new WakeAndTuneTask()); + return; + } + + pumpStatusLocal.setLastCommunicationToNow(); + setRefreshButtonEnabled(true); + + if (!isRefresh) { + pumpState = PumpDriverState.Initialized; + } + + if (!sentIdToFirebase) { + Bundle params = new Bundle(); + params.putString("version", BuildConfig.VERSION); + MainApp.getFirebaseAnalytics().logEvent("MedtronicPumpInit", params); + + sentIdToFirebase = true; + } + + isInitialized = true; + // this.pumpState = PumpDriverState.Initialized; + + this.firstRun = false; + } + + private void getBasalProfiles() { + + MedtronicUITask medtronicUITask = medtronicUIComm.executeCommand(MedtronicCommandType.GetBasalProfileSTD); + + if (medtronicUITask.getResponseType() == MedtronicUIResponseType.Error) { + medtronicUIComm.executeCommand(MedtronicCommandType.GetBasalProfileSTD); + } + } + + + @Override + public boolean isThisProfileSet(Profile profile) { + MedtronicPumpStatus mdtPumpStatus = getMDTPumpStatus(); + LOG.debug("isThisProfileSet: basalInitalized={}", mdtPumpStatus.basalProfileStatus); + + if (!isInitialized) + return true; + + if (mdtPumpStatus.basalProfileStatus == BasalProfileStatus.NotInitialized) { + // this shouldn't happen, but if there was problem we try again + getBasalProfiles(); + return isProfileSame(profile); + } else if (mdtPumpStatus.basalProfileStatus == BasalProfileStatus.ProfileChanged) { + return false; + } else { + + } + + + return (getMDTPumpStatus().basalProfileStatus != BasalProfileStatus.ProfileOK) || isProfileSame(profile); + } + + + private boolean isProfileSame(Profile profile) { + + boolean invalid = false; + Double[] basalsByHour = getMDTPumpStatus().basalsByHour; + PumpType pumpType = getMDTPumpStatus().getPumpType(); + + if (isLoggingEnabled()) + LOG.debug("Current Basals (h): " + + (basalsByHour == null ? "null" : BasalProfile.getProfilesByHourToString(basalsByHour))); + + // int index = 0; + + if (basalsByHour == null) + return true; // we don't want to set profile again, unless we are sure + + StringBuilder stringBuilder = new StringBuilder("Requested Basals (h): "); + + for (Profile.ProfileValue basalValue : profile.getBasalValues()) { + + double basalValueValue = pumpType.determineCorrectBasalSize(basalValue.value); + + int hour = basalValue.timeAsSeconds / (60 * 60); + + if (!MedtronicUtil.isSame(basalsByHour[hour], basalValueValue)) { + invalid = true; + } + + stringBuilder.append(String.format(Locale.ENGLISH, "%.3f", basalValueValue)); + stringBuilder.append(" "); + } + + if (isLoggingEnabled()) { + LOG.debug(stringBuilder.toString()); + + if (!invalid) { + LOG.debug("Basal profile is same as AAPS one."); + } else { + LOG.debug("Basal profile on Pump is different than the AAPS one."); + } + } + + return (!invalid); + } + + + @Override + public long lastDataTime() { + getMDTPumpStatus(); + + if (pumpStatusLocal.lastConnection != 0) { + return pumpStatusLocal.lastConnection; + } + + return System.currentTimeMillis(); + } + + + @Override + public double getBaseBasalRate() { + return getMDTPumpStatus().getBasalProfileForHour(); + } + + + @Override + public double getReservoirLevel() { + return getMDTPumpStatus().reservoirRemainingUnits; + } + + + @Override + public int getBatteryLevel() { + return getMDTPumpStatus().batteryRemaining; + } + + + private MedtronicPumpStatus getMDTPumpStatus() { + if (pumpStatusLocal == null) { + // FIXME I don't know why this happens + if (isLoggingEnabled()) + LOG.warn("!!!! Reset Pump Status Local"); + pumpStatusLocal = MedtronicUtil.getPumpStatus(); + } + + return pumpStatusLocal; + } + + + protected void triggerUIChange() { + RxBus.INSTANCE.send(new EventMedtronicPumpValuesChanged()); + } + + private BolusDeliveryType bolusDeliveryType = BolusDeliveryType.Idle; + + private enum BolusDeliveryType { + Idle, // + DeliveryPrepared, // + Delivering, // + CancelDelivery + } + + + private void checkTimeAndOptionallySetTime() { + + if (isLoggingEnabled()) + LOG.info("MedtronicPumpPlugin::checkTimeAndOptionallySetTime - Start"); + + setRefreshButtonEnabled(false); + + if (isPumpNotReachable()) { + LOG.debug("MedtronicPumpPlugin::checkTimeAndOptionallySetTime - Pump Unreachable."); + setRefreshButtonEnabled(true); + return; + } + + MedtronicUtil.dismissNotification(MedtronicNotificationType.PumpUnreachable); + + medtronicUIComm.executeCommand(MedtronicCommandType.GetRealTimeClock); + + ClockDTO clock = MedtronicUtil.getPumpTime(); + + if (clock==null) { // retry + medtronicUIComm.executeCommand(MedtronicCommandType.GetRealTimeClock); + + clock = MedtronicUtil.getPumpTime(); + } + + if (clock==null) + return; + + int timeDiff = Math.abs(clock.timeDifference); + + if (timeDiff > 20) { + + if ((clock.localDeviceTime.getYear() <= 2015) || (timeDiff <= 24 * 60 * 60)) { + + if (isLoggingEnabled()) + LOG.info("MedtronicPumpPlugin::checkTimeAndOptionallySetTime - Time difference is {} s. Set time on pump.", timeDiff); + + medtronicUIComm.executeCommand(MedtronicCommandType.SetRealTimeClock); + + if (clock.timeDifference == 0) { + Notification notification = new Notification(Notification.INSIGHT_DATE_TIME_UPDATED, MainApp.gs(R.string.pump_time_updated), Notification.INFO, 60); + RxBus.INSTANCE.send(new EventNewNotification(notification)); + } + } else { + if ((clock.localDeviceTime.getYear() > 2015)) { + LOG.error("MedtronicPumpPlugin::checkTimeAndOptionallySetTime - Time difference over 24h requested [diff={}]. Doing nothing.", timeDiff); + sendNotification(MedtronicNotificationType.TimeChangeOver24h); + } + } + + } else { + if (isLoggingEnabled()) + LOG.info("MedtronicPumpPlugin::checkTimeAndOptionallySetTime - Time difference is {} s. Do nothing.", timeDiff); + } + + scheduleNextRefresh(MedtronicStatusRefreshType.PumpTime, 0); + } + + + @NonNull + protected PumpEnactResult deliverBolus(final DetailedBolusInfo detailedBolusInfo) { + + LOG.info("MedtronicPumpPlugin::deliverBolus - {}", BolusDeliveryType.DeliveryPrepared); + + setRefreshButtonEnabled(false); + + MedtronicPumpStatus mdtPumpStatus = getMDTPumpStatus(); + + if (detailedBolusInfo.insulin > mdtPumpStatus.reservoirRemainingUnits) { + return new PumpEnactResult() // + .success(false) // + .enacted(false) // + .comment(MainApp.gs(R.string.medtronic_cmd_bolus_could_not_be_delivered_no_insulin, + mdtPumpStatus.reservoirRemainingUnits, + detailedBolusInfo.insulin)); + } + + bolusDeliveryType = BolusDeliveryType.DeliveryPrepared; + + if (isPumpNotReachable()) { + LOG.debug("MedtronicPumpPlugin::deliverBolus - Pump Unreachable."); + return setNotReachable(true, false); + } + + MedtronicUtil.dismissNotification(MedtronicNotificationType.PumpUnreachable); + + if (bolusDeliveryType == BolusDeliveryType.CancelDelivery) { + // LOG.debug("MedtronicPumpPlugin::deliverBolus - Delivery Canceled."); + return setNotReachable(true, true); + } + + // LOG.debug("MedtronicPumpPlugin::deliverBolus - Starting wait period."); + + int sleepTime = SP.getInt(MedtronicConst.Prefs.BolusDelay, 10) * 1000; + + SystemClock.sleep(sleepTime); + + if (bolusDeliveryType == BolusDeliveryType.CancelDelivery) { + // LOG.debug("MedtronicPumpPlugin::deliverBolus - Delivery Canceled, before wait period."); + return setNotReachable(true, true); + } + + // LOG.debug("MedtronicPumpPlugin::deliverBolus - End wait period. Start delivery"); + + try { + + bolusDeliveryType = BolusDeliveryType.Delivering; + + // LOG.debug("MedtronicPumpPlugin::deliverBolus - Start delivery"); + + MedtronicUITask responseTask = medtronicUIComm.executeCommand(MedtronicCommandType.SetBolus, + detailedBolusInfo.insulin); + + Boolean response = (Boolean) responseTask.returnData; + + setRefreshButtonEnabled(true); + + // LOG.debug("MedtronicPumpPlugin::deliverBolus - Response: {}", response); + + if (response) { + + if (bolusDeliveryType == BolusDeliveryType.CancelDelivery) { + // LOG.debug("MedtronicPumpPlugin::deliverBolus - Delivery Canceled after Bolus started."); + + new Thread(() -> { + // Looper.prepare(); + // LOG.debug("MedtronicPumpPlugin::deliverBolus - Show dialog - before"); + SystemClock.sleep(2000); + // LOG.debug("MedtronicPumpPlugin::deliverBolus - Show dialog. Context: " + // + MainApp.instance().getApplicationContext()); + + Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class); + i.putExtra("soundid", R.raw.boluserror); + i.putExtra("status", MainApp.gs(R.string.medtronic_cmd_cancel_bolus_not_supported)); + i.putExtra("title", MainApp.gs(R.string.combo_warning)); + i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + MainApp.instance().startActivity(i); + + }).start(); + } + + TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, true); + + // we subtract insulin, exact amount will be visible with next remainingInsulin update. + getMDTPumpStatus().reservoirRemainingUnits -= detailedBolusInfo.insulin; + + incrementStatistics(detailedBolusInfo.isSMB ? MedtronicConst.Statistics.SMBBoluses + : MedtronicConst.Statistics.StandardBoluses); + + + // calculate time for bolus and set driver to busy for that time + int bolusTime = (int) (detailedBolusInfo.insulin * 42.0d); + long time = System.currentTimeMillis() + (bolusTime * 1000); + + this.busyTimestamps.add(time); + setEnableCustomAction(MedtronicCustomActionType.ClearBolusBlock, true); + + return new PumpEnactResult().success(true) // + .enacted(true) // + .bolusDelivered(detailedBolusInfo.insulin) // + .carbsDelivered(detailedBolusInfo.carbs); + + } else { + return new PumpEnactResult() // + .success(bolusDeliveryType == BolusDeliveryType.CancelDelivery) // + .enacted(false) // + .comment(MainApp.gs(R.string.medtronic_cmd_bolus_could_not_be_delivered)); + } + + } finally { + finishAction("Bolus"); + this.bolusDeliveryType = BolusDeliveryType.Idle; + } + } + + + private PumpEnactResult setNotReachable(boolean isBolus, boolean success) { + setRefreshButtonEnabled(true); + + if (isBolus) { + bolusDeliveryType = BolusDeliveryType.Idle; + } + + if (success) { + return new PumpEnactResult() // + .success(true) // + .enacted(false); + } else { + return new PumpEnactResult() // + .success(false) // + .enacted(false) // + .comment(MainApp.gs(R.string.medtronic_pump_status_pump_unreachable)); + } + } + + + public void stopBolusDelivering() { + + this.bolusDeliveryType = BolusDeliveryType.CancelDelivery; + + // if (isLoggingEnabled()) + // LOG.warn("MedtronicPumpPlugin::deliverBolus - Stop Bolus Delivery."); + } + + + private void incrementStatistics(String statsKey) { + long currentCount = SP.getLong(statsKey, 0L); + currentCount++; + SP.putLong(statsKey, currentCount); + } + + + // if enforceNew===true current temp basal is canceled and new TBR set (duration is prolonged), + // if false and the same rate is requested enacted=false and success=true is returned and TBR is not changed + @Override + public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, Profile profile, + boolean enforceNew) { + + setRefreshButtonEnabled(false); + + if (isPumpNotReachable()) { + + setRefreshButtonEnabled(true); + + return new PumpEnactResult() // + .success(false) // + .enacted(false) // + .comment(MainApp.gs(R.string.medtronic_pump_status_pump_unreachable)); + } + + MedtronicUtil.dismissNotification(MedtronicNotificationType.PumpUnreachable); + + getMDTPumpStatus(); + + if (isLoggingEnabled()) + LOG.info(getLogPrefix() + "setTempBasalAbsolute: rate: {}, duration={}", absoluteRate, durationInMinutes); + + // read current TBR + TempBasalPair tbrCurrent = readTBR(); + + if (tbrCurrent == null) { + if (isLoggingEnabled()) + LOG.warn(getLogPrefix() + "setTempBasalAbsolute - Could not read current TBR, canceling operation."); + finishAction("TBR"); + return new PumpEnactResult().success(false).enacted(false) + .comment(MainApp.gs(R.string.medtronic_cmd_cant_read_tbr)); + } else { + if (isLoggingEnabled()) + LOG.info(getLogPrefix() + "setTempBasalAbsolute: Current Basal: duration: {} min, rate={}", + tbrCurrent.getDurationMinutes(), tbrCurrent.getInsulinRate()); + } + + if (!enforceNew) { + + if (MedtronicUtil.isSame(tbrCurrent.getInsulinRate(), absoluteRate)) { + + boolean sameRate = true; + if (MedtronicUtil.isSame(0.0d, absoluteRate) && durationInMinutes > 0) { + // if rate is 0.0 and duration>0 then the rate is not the same + sameRate = false; + } + + if (sameRate) { + if (isLoggingEnabled()) + LOG.info(getLogPrefix() + "setTempBasalAbsolute - No enforceNew and same rate. Exiting."); + finishAction("TBR"); + return new PumpEnactResult().success(true).enacted(false); + } + } + // if not the same rate, we cancel and start new + } + + // if TBR is running we will cancel it. + if (tbrCurrent.getInsulinRate() != 0.0f && tbrCurrent.getDurationMinutes() > 0) { + if (isLoggingEnabled()) + LOG.info(getLogPrefix() + "setTempBasalAbsolute - TBR running - so canceling it."); + + // CANCEL + + MedtronicUITask responseTask2 = medtronicUIComm.executeCommand(MedtronicCommandType.CancelTBR); + + Boolean response = (Boolean) responseTask2.returnData; + + if (response) { + if (isLoggingEnabled()) + LOG.info(getLogPrefix() + "setTempBasalAbsolute - Current TBR cancelled."); + } else { + if (isLoggingEnabled()) + LOG.error(getLogPrefix() + "setTempBasalAbsolute - Cancel TBR failed."); + + finishAction("TBR"); + + return new PumpEnactResult().success(false).enacted(false) + .comment(MainApp.gs(R.string.medtronic_cmd_cant_cancel_tbr_stop_op)); + } + } + + // now start new TBR + MedtronicUITask responseTask = medtronicUIComm.executeCommand(MedtronicCommandType.SetTemporaryBasal, + absoluteRate, durationInMinutes); + + Boolean response = (Boolean) responseTask.returnData; + + if (isLoggingEnabled()) + LOG.info(getLogPrefix() + "setTempBasalAbsolute - setTBR. Response: " + response); + + if (response) { + // FIXME put this into UIPostProcessor + pumpStatusLocal.tempBasalStart = new Date(); + pumpStatusLocal.tempBasalAmount = absoluteRate; + pumpStatusLocal.tempBasalLength = durationInMinutes; + + TemporaryBasal tempStart = new TemporaryBasal() // + .date(System.currentTimeMillis()) // + .duration(durationInMinutes) // + .absolute(absoluteRate) // + .source(Source.USER); + + TreatmentsPlugin.getPlugin().addToHistoryTempBasal(tempStart); + + incrementStatistics(MedtronicConst.Statistics.TBRsSet); + + finishAction("TBR"); + + return new PumpEnactResult().success(true).enacted(true) // + .absolute(absoluteRate).duration(durationInMinutes); + + } else { + finishAction("TBR"); + + return new PumpEnactResult().success(false).enacted(false) // + .comment(MainApp.gs(R.string.medtronic_cmd_tbr_could_not_be_delivered)); + } + + } + + + @Override + public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, Profile profile, + boolean enforceNew) { + if (percent==0) { + return setTempBasalAbsolute(0.0d, durationInMinutes, profile, enforceNew); + } else { + double absoluteValue = profile.getBasal() * (percent /100.0d); + getMDTPumpStatus(); + absoluteValue = pumpStatusLocal.pumpType.determineCorrectBasalSize(absoluteValue); + LOG.warn("setTempBasalPercent [MedtronicPumpPlugin] - You are trying to use setTempBasalPercent with percent other then 0% (%d). This will start setTempBasalAbsolute, with calculated value (%.3f). Result might not be 100% correct.", percent, absoluteValue); + return setTempBasalAbsolute(absoluteValue, durationInMinutes, profile, enforceNew); + } + } + + + private void finishAction(String overviewKey) { + + if (overviewKey != null) + RxBus.INSTANCE.send(new EventRefreshOverview(overviewKey)); + + triggerUIChange(); + + setRefreshButtonEnabled(true); + } + + + private void readPumpHistory() { + +// if (isLoggingEnabled()) +// LOG.error(getLogPrefix() + "readPumpHistory WIP."); + + readPumpHistoryLogic(); + + scheduleNextRefresh(MedtronicStatusRefreshType.PumpHistory); + + if (medtronicHistoryData.hasRelevantConfigurationChanged()) { + scheduleNextRefresh(MedtronicStatusRefreshType.Configuration, -1); + } + + if (medtronicHistoryData.hasPumpTimeChanged()) { + scheduleNextRefresh(MedtronicStatusRefreshType.PumpTime, -1); + } + + if (this.getMDTPumpStatus().basalProfileStatus != BasalProfileStatus.NotInitialized + && medtronicHistoryData.hasBasalProfileChanged()) { + medtronicHistoryData.processLastBasalProfileChange(getMDTPumpStatus()); + } + + PumpDriverState previousState = this.pumpState; + + if (medtronicHistoryData.isPumpSuspended()) { + this.pumpState = PumpDriverState.Suspended; + if (isLoggingEnabled()) + LOG.debug(getLogPrefix() + "isPumpSuspended: true"); + } else { + if (previousState == PumpDriverState.Suspended) { + this.pumpState = PumpDriverState.Ready; + } + if (isLoggingEnabled()) + LOG.debug(getLogPrefix() + "isPumpSuspended: false"); + } + + medtronicHistoryData.processNewHistoryData(); + + this.medtronicHistoryData.finalizeNewHistoryRecords(); + // this.medtronicHistoryData.setLastHistoryRecordTime(this.lastPumpHistoryEntry.atechDateTime); + + } + + + private void readPumpHistoryLogic() { + + LocalDateTime targetDate = null; + + if (lastPumpHistoryEntry == null) { + + if (isLoggingEnabled()) + LOG.debug(getLogPrefix() + "readPumpHistoryLogic(): lastPumpHistoryEntry: null"); + + Long lastPumpHistoryEntryTime = getLastPumpEntryTime(); + + LocalDateTime timeMinus36h = new LocalDateTime(); + timeMinus36h = timeMinus36h.minusHours(36); + medtronicHistoryData.setIsInInit(true); + + if (lastPumpHistoryEntryTime == 0L) { + if (isLoggingEnabled()) + LOG.debug(getLogPrefix() + "readPumpHistoryLogic(): lastPumpHistoryEntryTime: 0L - targetDate: " + + targetDate); + targetDate = timeMinus36h; + } else { + // LocalDateTime lastHistoryRecordTime = DateTimeUtil.toLocalDateTime(lastPumpHistoryEntryTime); + + if (isLoggingEnabled()) + LOG.debug(getLogPrefix() + "readPumpHistoryLogic(): lastPumpHistoryEntryTime: {} - targetDate: {}", + lastPumpHistoryEntryTime, targetDate); + + medtronicHistoryData.setLastHistoryRecordTime(lastPumpHistoryEntryTime); + + LocalDateTime lastHistoryRecordTime = DateTimeUtil.toLocalDateTime(lastPumpHistoryEntryTime); + + lastHistoryRecordTime = lastHistoryRecordTime.minusHours(12); // we get last 12 hours of history to + // determine pump state + // (we don't process that data), we process only + + if (timeMinus36h.isAfter(lastHistoryRecordTime)) { + targetDate = timeMinus36h; + } + + targetDate = (timeMinus36h.isAfter(lastHistoryRecordTime) ? timeMinus36h : lastHistoryRecordTime); + + if (isLoggingEnabled()) + LOG.debug(getLogPrefix() + "readPumpHistoryLogic(): targetDate: " + targetDate); + } + } else { + if (isLoggingEnabled()) + LOG.debug(getLogPrefix() + "readPumpHistoryLogic(): lastPumpHistoryEntry: not null - {}", + MedtronicUtil.gsonInstance.toJson(lastPumpHistoryEntry)); + medtronicHistoryData.setIsInInit(false); + // medtronicHistoryData.setLastHistoryRecordTime(lastPumpHistoryEntry.atechDateTime); + + // targetDate = lastPumpHistoryEntry.atechDateTime; + } + + LOG.debug("HST: Target Date: {}", targetDate); + + MedtronicUITask responseTask2 = medtronicUIComm.executeCommand(MedtronicCommandType.GetHistoryData, + lastPumpHistoryEntry, targetDate); + + LOG.debug("HST: After task"); + + PumpHistoryResult historyResult = (PumpHistoryResult) responseTask2.returnData; + + LOG.debug("HST: History Result: {}", historyResult.toString()); + + PumpHistoryEntry latestEntry = historyResult.getLatestEntry(); + + if (isLoggingEnabled()) + LOG.debug(getLogPrefix() + "Last entry: " + latestEntry); + + if (latestEntry == null) // no new history to read + return; + + this.lastPumpHistoryEntry = latestEntry; + SP.putLong(MedtronicConst.Statistics.LastPumpHistoryEntry, latestEntry.atechDateTime); + + LOG.debug("HST: History: valid={}, unprocessed={}", historyResult.validEntries.size(), + historyResult.unprocessedEntries.size()); + + this.medtronicHistoryData.addNewHistory(historyResult); + this.medtronicHistoryData.filterNewEntries(); + + // determine if first run, if yes detrmine how much of update do we need + // first run: + // get last hiostory entry, if not there download 1.5 days of data + // - there: check if last entry is older than 1.5 days + // - yes: download 1.5 days + // - no: download with last entry + // - not there: download 1.5 days + // + // upload all new entries to NightScout (TBR, Bolus) + // determine pump status + // + // save last entry + // + // not first run: + // update to last entry + // - save + // - determine pump status + + // + + } + + private Long getLastPumpEntryTime() { + Long lastPumpEntryTime = SP.getLong(MedtronicConst.Statistics.LastPumpHistoryEntry, 0L); + + try { + LocalDateTime localDateTime = DateTimeUtil.toLocalDateTime(lastPumpEntryTime); + + if (localDateTime.getYear() != (new GregorianCalendar().get(Calendar.YEAR))) { + LOG.warn("Saved LastPumpHistoryEntry was invalid. Year was not the same."); + return 0L; + } + + return lastPumpEntryTime; + + } catch (Exception ex) { + LOG.warn("Saved LastPumpHistoryEntry was invalid."); + return 0L; + } + + } + + + private void scheduleNextRefresh(MedtronicStatusRefreshType refreshType) { + scheduleNextRefresh(refreshType, 0); + } + + + private void scheduleNextRefresh(MedtronicStatusRefreshType refreshType, int additionalTimeInMinutes) { + switch (refreshType) { + + case RemainingInsulin: { + double remaining = pumpStatusLocal.reservoirRemainingUnits; + int min; + if (remaining > 50) + min = 4 * 60; + else if (remaining > 20) + min = 60; + else + min = 15; + + workWithStatusRefresh(StatusRefreshAction.Add, refreshType, getTimeInFutureFromMinutes(min)); + } + break; + + case PumpTime: + case Configuration: + case BatteryStatus: + case PumpHistory: { + workWithStatusRefresh(StatusRefreshAction.Add, refreshType, + getTimeInFutureFromMinutes(refreshType.getRefreshTime() + additionalTimeInMinutes)); + } + break; + } + } + + private enum StatusRefreshAction { + Add, // + GetData + } + + + private synchronized Map workWithStatusRefresh(StatusRefreshAction action, // + MedtronicStatusRefreshType statusRefreshType, // + Long time) { + + switch (action) { + + case Add: { + statusRefreshMap.put(statusRefreshType, time); + return null; + } + + case GetData: { + return new HashMap<>(statusRefreshMap); + } + + default: + return null; + + } + + } + + + private long getTimeInFutureFromMinutes(int minutes) { + return System.currentTimeMillis() + getTimeInMs(minutes); + } + + + private long getTimeInMs(int minutes) { + return minutes * 60 * 1000L; + } + + + private TempBasalPair readTBR() { + MedtronicUITask responseTask = medtronicUIComm.executeCommand(MedtronicCommandType.ReadTemporaryBasal); + + if (responseTask.hasData()) { + TempBasalPair tbr = (TempBasalPair) responseTask.returnData; + + // we sometimes get rate returned even if TBR is no longer running + if (tbr.getDurationMinutes() == 0) { + tbr.setInsulinRate(0.0d); + } + + return tbr; + } else { + return null; + } + } + + + @Override + public PumpEnactResult cancelTempBasal(boolean enforceNew) { + + if (isLoggingEnabled()) + LOG.info(getLogPrefix() + "cancelTempBasal - started"); + + if (isPumpNotReachable()) { + + setRefreshButtonEnabled(true); + + return new PumpEnactResult() // + .success(false) // + .enacted(false) // + .comment(MainApp.gs(R.string.medtronic_pump_status_pump_unreachable)); + } + + MedtronicUtil.dismissNotification(MedtronicNotificationType.PumpUnreachable); + setRefreshButtonEnabled(false); + + TempBasalPair tbrCurrent = readTBR(); + + if (tbrCurrent != null) { + if (tbrCurrent.getInsulinRate() == 0.0f && tbrCurrent.getDurationMinutes() == 0) { + if (isLoggingEnabled()) + LOG.info(getLogPrefix() + "cancelTempBasal - TBR already canceled."); + finishAction("TBR"); + return new PumpEnactResult().success(true).enacted(false); + } + } else { + if (isLoggingEnabled()) + LOG.warn(getLogPrefix() + "cancelTempBasal - Could not read currect TBR, canceling operation."); + finishAction("TBR"); + return new PumpEnactResult().success(false).enacted(false) + .comment(MainApp.gs(R.string.medtronic_cmd_cant_read_tbr)); + } + + MedtronicUITask responseTask2 = medtronicUIComm.executeCommand(MedtronicCommandType.CancelTBR); + + Boolean response = (Boolean) responseTask2.returnData; + + finishAction("TBR"); + + if (response) { + if (isLoggingEnabled()) + LOG.info(getLogPrefix() + "cancelTempBasal - Cancel TBR successful."); + + TemporaryBasal tempBasal = new TemporaryBasal() // + .date(System.currentTimeMillis()) // + .duration(0) // + .source(Source.USER); + + TreatmentsPlugin.getPlugin().addToHistoryTempBasal(tempBasal); + + return new PumpEnactResult().success(true).enacted(true) // + .isTempCancel(true); + } else { + if (isLoggingEnabled()) + LOG.info(getLogPrefix() + "cancelTempBasal - Cancel TBR failed."); + + return new PumpEnactResult().success(response).enacted(response) // + .comment(MainApp.gs(R.string.medtronic_cmd_cant_cancel_tbr)); + } + } + + @Override + public ManufacturerType manufacturer() { + return getMDTPumpStatus().pumpType.getManufacturer(); + } + + @Override + public PumpType model() { + return getMDTPumpStatus().pumpType; + } + + @Override + public String serialNumber() { + return getMDTPumpStatus().serialNumber; + } + + @Override + public PumpEnactResult setNewBasalProfile(Profile profile) { + if (isLoggingEnabled()) + LOG.info(getLogPrefix() + "setNewBasalProfile"); + + // this shouldn't be needed, but let's do check if profile setting we are setting is same as current one + if (isProfileSame(profile)) { + return new PumpEnactResult() // + .success(true) // + .enacted(false) // + .comment(MainApp.gs(R.string.medtronic_cmd_basal_profile_not_set_is_same)); + } + + setRefreshButtonEnabled(false); + + if (isPumpNotReachable()) { + + setRefreshButtonEnabled(true); + + return new PumpEnactResult() // + .success(false) // + .enacted(false) // + .comment(MainApp.gs(R.string.medtronic_pump_status_pump_unreachable)); + } + + MedtronicUtil.dismissNotification(MedtronicNotificationType.PumpUnreachable); + + BasalProfile basalProfile = convertProfileToMedtronicProfile(profile); + + String profileInvalid = isProfileValid(basalProfile); + + if (profileInvalid != null) { + return new PumpEnactResult() // + .success(false) // + .enacted(false) // + .comment(MainApp.gs(R.string.medtronic_cmd_set_profile_pattern_overflow, profileInvalid)); + } + + MedtronicUITask responseTask = medtronicUIComm.executeCommand(MedtronicCommandType.SetBasalProfileSTD, + basalProfile); + + Boolean response = (Boolean) responseTask.returnData; + + if (isLoggingEnabled()) + LOG.info(getLogPrefix() + "Basal Profile was set: " + response); + + if (response) { + return new PumpEnactResult().success(true).enacted(true); + } else { + return new PumpEnactResult().success(response).enacted(response) // + .comment(MainApp.gs(R.string.medtronic_cmd_basal_profile_could_not_be_set)); + } + } + + + private String isProfileValid(BasalProfile basalProfile) { + + StringBuilder stringBuilder = new StringBuilder(); + + MedtronicPumpStatus pumpStatus = getMDTPumpStatus(); + + if (pumpStatus.maxBasal == null) + return null; + + for (BasalProfileEntry profileEntry : basalProfile.getEntries()) { + + if (profileEntry.rate > pumpStatus.maxBasal) { + stringBuilder.append(profileEntry.startTime.toString("HH:mm")); + stringBuilder.append("="); + stringBuilder.append(profileEntry.rate); + } + } + + return stringBuilder.length() == 0 ? null : stringBuilder.toString(); + } + + + @NonNull + private BasalProfile convertProfileToMedtronicProfile(Profile profile) { + + MedtronicPumpStatus pumpStatus = getMDTPumpStatus(); + + PumpType pumpType = pumpStatus.pumpType; + + BasalProfile basalProfile = new BasalProfile(); + + for (int i = 0; i < 24; i++) { + double rate = profile.getBasalTimeFromMidnight(i * 60 * 60); + + double v = pumpType.determineCorrectBasalSize(rate); + + BasalProfileEntry basalEntry = new BasalProfileEntry(v, i, 0); + basalProfile.addEntry(basalEntry); + + } + + basalProfile.generateRawDataFromEntries(); + + return basalProfile; + } + + // OPERATIONS not supported by Pump or Plugin + + private List customActions = null; + + private CustomAction customActionWakeUpAndTune = new CustomAction(R.string.medtronic_custom_action_wake_and_tune, + MedtronicCustomActionType.WakeUpAndTune); + + private CustomAction customActionClearBolusBlock = new CustomAction( + R.string.medtronic_custom_action_clear_bolus_block, MedtronicCustomActionType.ClearBolusBlock, false); + + private CustomAction customActionResetRLConfig = new CustomAction( + R.string.medtronic_custom_action_reset_rileylink, MedtronicCustomActionType.ResetRileyLinkConfiguration, true); + + + @Override + public List getCustomActions() { + + if (customActions == null) { + this.customActions = Arrays.asList(customActionWakeUpAndTune, // + customActionClearBolusBlock, // + customActionResetRLConfig); + } + + return this.customActions; + } + + + @Override + public void executeCustomAction(CustomActionType customActionType) { + + MedtronicCustomActionType mcat = (MedtronicCustomActionType) customActionType; + + switch (mcat) { + + case WakeUpAndTune: { + if (MedtronicUtil.getPumpStatus().verifyConfiguration()) { + ServiceTaskExecutor.startTask(new WakeAndTuneTask()); + } else { + Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class); + i.putExtra("soundid", R.raw.boluserror); + i.putExtra("status", MainApp.gs(R.string.medtronic_error_operation_not_possible_no_configuration)); + i.putExtra("title", MainApp.gs(R.string.combo_warning)); + i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + MainApp.instance().startActivity(i); + } + } + break; + + case ClearBolusBlock: { + this.busyTimestamps.clear(); + this.customActionClearBolusBlock.setEnabled(false); + refreshCustomActionsList(); + } + break; + + case ResetRileyLinkConfiguration: { + ServiceTaskExecutor.startTask(new ResetRileyLinkConfigurationTask()); + } + break; + + default: + break; + } + + } + + @Override + public void timeDateOrTimeZoneChanged() { + + if (isLoggingEnabled()) + LOG.warn(getLogPrefix() + "Time, Date and/or TimeZone changed. "); + + this.hasTimeDateOrTimeZoneChanged = true; + } + + private void refreshCustomActionsList() { + RxBus.INSTANCE.send(new EventCustomActionsChanged()); + } + + + public void setEnableCustomAction(MedtronicCustomActionType customAction, boolean isEnabled) { + + if (customAction == MedtronicCustomActionType.ClearBolusBlock) { + this.customActionClearBolusBlock.setEnabled(isEnabled); + } else if (customAction == MedtronicCustomActionType.ResetRileyLinkConfiguration) { + this.customActionResetRLConfig.setEnabled(isEnabled); + } + + refreshCustomActionsList(); + } + + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.java new file mode 100644 index 0000000000..e054539e8f --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.java @@ -0,0 +1,966 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.comm; + +import android.content.Context; +import android.os.SystemClock; + +import org.joda.time.LocalDateTime; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Calendar; +import java.util.GregorianCalendar; +import java.util.List; +import java.util.Map; + +import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkCommunicationManager; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkConst; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.RFSpy; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.RileyLinkCommunicationException; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.RFSpyResponse; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.RLMessage; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.RadioPacket; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.RadioResponse; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RLMessageType; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.ServiceTaskExecutor; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.WakeAndTuneTask; +import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; +import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil; +import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.RawHistoryPage; +import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.MedtronicPumpHistoryDecoder; +import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryEntry; +import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryResult; +import info.nightscout.androidaps.plugins.pump.medtronic.comm.message.CarelinkLongMessageBody; +import info.nightscout.androidaps.plugins.pump.medtronic.comm.message.CarelinkShortMessageBody; +import info.nightscout.androidaps.plugins.pump.medtronic.comm.message.GetHistoryPageCarelinkMessageBody; +import info.nightscout.androidaps.plugins.pump.medtronic.comm.message.MessageBody; +import info.nightscout.androidaps.plugins.pump.medtronic.comm.message.PacketType; +import info.nightscout.androidaps.plugins.pump.medtronic.comm.message.PumpAckMessageBody; +import info.nightscout.androidaps.plugins.pump.medtronic.comm.message.PumpMessage; +import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.BasalProfile; +import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.BatteryStatusDTO; +import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.ClockDTO; +import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.PumpSettingDTO; +import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.TempBasalPair; +import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicCommandType; +import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicDeviceType; +import info.nightscout.androidaps.plugins.pump.medtronic.defs.PumpDeviceState; +import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil; +import info.nightscout.androidaps.utils.SP; + +/** + * Original file created by geoff on 5/30/16. + *

+ * Split into 2 implementations, so that we can split it by target device. - Andy + * This was mostly rewritten from Original version, and lots of commands and + * functionality added. + */ +public class MedtronicCommunicationManager extends RileyLinkCommunicationManager { + + private static final Logger LOG = LoggerFactory.getLogger(L.PUMPCOMM); + private static final int MAX_COMMAND_TRIES = 3; + private static final int DEFAULT_TIMEOUT = 2000; + private static final long RILEYLINK_TIMEOUT = 15 * 60 * 1000; // 15 min + + static MedtronicCommunicationManager medtronicCommunicationManager; + String errorMessage; + private MedtronicConverter medtronicConverter; + private boolean debugSetCommands = false; + + private MedtronicPumpHistoryDecoder pumpHistoryDecoder; + private boolean doWakeUpBeforeCommand = true; + + + public MedtronicCommunicationManager(Context context, RFSpy rfspy) { + super(context, rfspy); + medtronicCommunicationManager = this; + this.medtronicConverter = new MedtronicConverter(); + this.pumpHistoryDecoder = new MedtronicPumpHistoryDecoder(); + MedtronicUtil.getPumpStatus().previousConnection = SP.getLong( + RileyLinkConst.Prefs.LastGoodDeviceCommunicationTime, 0L); + } + + + public static MedtronicCommunicationManager getInstance() { + return medtronicCommunicationManager; + } + + + @Override + protected void configurePumpSpecificSettings() { + pumpStatus = MedtronicUtil.getPumpStatus(); + } + + + @Override + public E createResponseMessage(byte[] payload, Class clazz) { + PumpMessage pumpMessage = new PumpMessage(payload); + return (E) pumpMessage; + } + + + public void setDoWakeUpBeforeCommand(boolean doWakeUp) { + this.doWakeUpBeforeCommand = doWakeUp; + } + + + public boolean isDeviceReachable() { + return isDeviceReachable(false); + } + + + /** + * We do actual wakeUp and compare PumpModel with currently selected one. If returned model is + * not Unknown, pump is reachable. + * + * @return + */ + public boolean isDeviceReachable(boolean canPreventTuneUp) { + + PumpDeviceState state = MedtronicUtil.getPumpDeviceState(); + + if (state != PumpDeviceState.PumpUnreachable) + MedtronicUtil.setPumpDeviceState(PumpDeviceState.WakingUp); + + for (int retry = 0; retry < 5; retry++) { + + if (isLogEnabled()) + LOG.debug("isDeviceReachable. Waking pump... " + (retry != 0 ? " (retry " + retry + ")" : "")); + + boolean connected = connectToDevice(); + + if (connected) + return true; + + SystemClock.sleep(1000); + + } + + if (state != PumpDeviceState.PumpUnreachable) + MedtronicUtil.setPumpDeviceState(PumpDeviceState.PumpUnreachable); + + if (!canPreventTuneUp) { + + long diff = System.currentTimeMillis() - MedtronicUtil.getPumpStatus().lastConnection; + + if (diff > RILEYLINK_TIMEOUT) { + ServiceTaskExecutor.startTask(new WakeAndTuneTask()); + } + } + + return false; + } + + + private boolean connectToDevice() { + + PumpDeviceState state = MedtronicUtil.getPumpDeviceState(); + + byte[] pumpMsgContent = createPumpMessageContent(RLMessageType.ReadSimpleData); // simple + RFSpyResponse rfSpyResponse = rfspy.transmitThenReceive(new RadioPacket(pumpMsgContent), (byte) 0, (byte) 200, + (byte) 0, (byte) 0, 25000, (byte) 0); + if (isLogEnabled()) + LOG.info("wakeup: raw response is " + ByteUtil.shortHexString(rfSpyResponse.getRaw())); + + if (rfSpyResponse.wasTimeout()) { + LOG.error("isDeviceReachable. Failed to find pump (timeout)."); + } else if (rfSpyResponse.looksLikeRadioPacket()) { + RadioResponse radioResponse = new RadioResponse(); + + try { + + radioResponse.init(rfSpyResponse.getRaw()); + + if (radioResponse.isValid()) { + + PumpMessage pumpResponse = createResponseMessage(radioResponse.getPayload(), PumpMessage.class); + + if (!pumpResponse.isValid()) { + LOG.warn("Response is invalid ! [interrupted={}, timeout={}]", rfSpyResponse.wasInterrupted(), + rfSpyResponse.wasTimeout()); + } else { + + // radioResponse.rssi; + Object dataResponse = medtronicConverter.convertResponse(MedtronicCommandType.PumpModel, + pumpResponse.getRawContent()); + + MedtronicDeviceType pumpModel = (MedtronicDeviceType) dataResponse; + boolean valid = (pumpModel != MedtronicDeviceType.Unknown_Device); + + if (MedtronicUtil.getMedtronicPumpModel() == null && valid) { + MedtronicUtil.setMedtronicPumpModel(pumpModel); + } + + if (isLogEnabled()) + LOG.debug("isDeviceReachable. PumpModel is {} - Valid: {} (rssi={})", pumpModel.name(), valid, + radioResponse.rssi); + + if (valid) { + if (state == PumpDeviceState.PumpUnreachable) + MedtronicUtil.setPumpDeviceState(PumpDeviceState.WakingUp); + else + MedtronicUtil.setPumpDeviceState(PumpDeviceState.Sleeping); + + rememberLastGoodDeviceCommunicationTime(); + + return true; + + } else { + if (state != PumpDeviceState.PumpUnreachable) + MedtronicUtil.setPumpDeviceState(PumpDeviceState.PumpUnreachable); + } + + } + + } else { + LOG.warn("isDeviceReachable. Failed to parse radio response: " + + ByteUtil.shortHexString(rfSpyResponse.getRaw())); + } + + } catch (RileyLinkCommunicationException e) { + LOG.warn("isDeviceReachable. Failed to decode radio response: " + + ByteUtil.shortHexString(rfSpyResponse.getRaw())); + } + + } else { + LOG.warn("isDeviceReachable. Unknown response: " + ByteUtil.shortHexString(rfSpyResponse.getRaw())); + } + + return false; + } + + + @Override + public boolean tryToConnectToDevice() { + return isDeviceReachable(true); + } + + + private PumpMessage runCommandWithArgs(PumpMessage msg) throws RileyLinkCommunicationException { + + if (debugSetCommands) + LOG.debug("Run command with Args: "); + + PumpMessage rval; + PumpMessage shortMessage = makePumpMessage(msg.commandType, new CarelinkShortMessageBody(new byte[]{0})); + // look for ack from short message + PumpMessage shortResponse = sendAndListen(shortMessage); + if (shortResponse.commandType == MedtronicCommandType.CommandACK) { + if (debugSetCommands) + LOG.debug("Run command with Args: Got ACK response"); + + rval = sendAndListen(msg); + if (debugSetCommands) + LOG.debug("2nd Response: {}", rval); + + return rval; + } else { + if (isLogEnabled()) + LOG.error("runCommandWithArgs: Pump did not ack Attention packet"); + return new PumpMessage("No ACK after Attention packet."); + } + } + + + private PumpMessage runCommandWithFrames(MedtronicCommandType commandType, List> frames) + throws RileyLinkCommunicationException { + + if (isLogEnabled()) + LOG.debug("Run command with Frames: {}", commandType.name()); + + PumpMessage rval = null; + PumpMessage shortMessage = makePumpMessage(commandType, new CarelinkShortMessageBody(new byte[]{0})); + // look for ack from short message + PumpMessage shortResponse = sendAndListen(shortMessage); + + if (shortResponse.commandType != MedtronicCommandType.CommandACK) { + if (isLogEnabled()) + LOG.error("runCommandWithFrames: Pump did not ack Attention packet"); + + return new PumpMessage("No ACK after start message."); + } else { + if (isLogEnabled()) + LOG.debug("Run command with Frames: Got ACK response for Attention packet"); + } + + int frameNr = 1; + + for (List frame : frames) { + + byte[] frameData = MedtronicUtil.createByteArray(frame); + + // LOG.debug("Frame {} data:\n{}", frameNr, ByteUtil.getCompactString(frameData)); + + PumpMessage msg = makePumpMessage(commandType, new CarelinkLongMessageBody(frameData)); + + rval = sendAndListen(msg); + + // LOG.debug("PumpResponse: " + rval); + + if (rval.commandType != MedtronicCommandType.CommandACK) { + LOG.error("runCommandWithFrames: Pump did not ACK frame #{}", frameNr); + + LOG.error("Run command with Frames FAILED (command={}, response={})", commandType.name(), + rval.toString()); + + return new PumpMessage("No ACK after frame #" + frameNr); + } else { + if (isLogEnabled()) + LOG.debug("Run command with Frames: Got ACK response for frame #{}", (frameNr)); + } + + frameNr++; + } + + return rval; + + } + + + public PumpHistoryResult getPumpHistory(PumpHistoryEntry lastEntry, LocalDateTime targetDate) { + + PumpHistoryResult pumpTotalResult = new PumpHistoryResult(lastEntry, targetDate == null ? null + : DateTimeUtil.toATechDate(targetDate)); + + if (doWakeUpBeforeCommand) + wakeUp(receiverDeviceAwakeForMinutes, false); + + if (isLogEnabled()) + LOG.debug("Current command: " + MedtronicUtil.getCurrentCommand()); + + MedtronicUtil.setPumpDeviceState(PumpDeviceState.Active); + boolean doneWithError = false; + + for (int pageNumber = 0; pageNumber < 5; pageNumber++) { + + RawHistoryPage rawHistoryPage = new RawHistoryPage(); + // wakeUp(receiverDeviceAwakeForMinutes, false); + PumpMessage getHistoryMsg = makePumpMessage(MedtronicCommandType.GetHistoryData, + new GetHistoryPageCarelinkMessageBody(pageNumber)); + + if (isLogEnabled()) + LOG.info("getPumpHistory: Page {}", pageNumber); + // LOG.info("getPumpHistoryPage("+pageNumber+"): "+ByteUtil.shortHexString(getHistoryMsg.getTxData())); + // Ask the pump to transfer history (we get first frame?) + + PumpMessage firstResponse = null; + boolean failed = false; + + MedtronicUtil.setCurrentCommand(MedtronicCommandType.GetHistoryData, pageNumber, null); + + for (int retries = 0; retries < MAX_COMMAND_TRIES; retries++) { + + try { + firstResponse = runCommandWithArgs(getHistoryMsg); + failed = false; + break; + } catch (RileyLinkCommunicationException e) { + if (isLogEnabled()) + LOG.error("First call for PumpHistory failed (retry={})", retries); + failed = true; + } + } + + if (failed) { + MedtronicUtil.setPumpDeviceState(PumpDeviceState.Sleeping); + return pumpTotalResult; + } + + // LOG.info("getPumpHistoryPage("+pageNumber+"): " + ByteUtil.shortHexString(firstResponse.getContents())); + + PumpMessage ackMsg = makePumpMessage(MedtronicCommandType.CommandACK, new PumpAckMessageBody()); + GetHistoryPageCarelinkMessageBody currentResponse = new GetHistoryPageCarelinkMessageBody(firstResponse + .getMessageBody().getTxData()); + int expectedFrameNum = 1; + boolean done = false; + // while (expectedFrameNum == currentResponse.getFrameNumber()) { + + int failures = 0; + while (!done) { + // examine current response for problems. + byte[] frameData = currentResponse.getFrameData(); + if ((frameData != null) && (frameData.length > 0) + && currentResponse.getFrameNumber() == expectedFrameNum) { + // success! got a frame. + if (frameData.length != 64) { + if (isLogEnabled()) + LOG.warn("Expected frame of length 64, got frame of length " + frameData.length); + // but append it anyway? + } + // handle successful frame data + rawHistoryPage.appendData(currentResponse.getFrameData()); + // RileyLinkMedtronicService.getInstance().announceProgress(((100 / 16) * + // currentResponse.getFrameNumber() + 1)); + MedtronicUtil.setCurrentCommand(MedtronicCommandType.GetHistoryData, pageNumber, + currentResponse.getFrameNumber()); + + if (isLogEnabled()) + LOG.info("getPumpHistory: Got frame {} of Page {}", currentResponse.getFrameNumber(), pageNumber); + // Do we need to ask for the next frame? + if (expectedFrameNum < 16) { // This number may not be correct for pumps other than 522/722 + expectedFrameNum++; + } else { + done = true; // successful completion + } + } else { + if (frameData == null) { + if (isLogEnabled()) + LOG.error("null frame data, retrying"); + } else if (currentResponse.getFrameNumber() != expectedFrameNum) { + if (isLogEnabled()) + LOG.warn("Expected frame number {}, received {} (retrying)", expectedFrameNum, + currentResponse.getFrameNumber()); + } else if (frameData.length == 0) { + if (isLogEnabled()) + LOG.warn("Frame has zero length, retrying"); + } + failures++; + if (failures == 6) { + if (isLogEnabled()) + LOG.error( + "getPumpHistory: 6 failures in attempting to download frame {} of page {}, giving up.", + expectedFrameNum, pageNumber); + done = true; // failure completion. + doneWithError = true; + } + } + + if (!done) { + // ask for next frame + PumpMessage nextMsg = null; + + for (int retries = 0; retries < MAX_COMMAND_TRIES; retries++) { + + try { + nextMsg = sendAndListen(ackMsg); + break; + } catch (RileyLinkCommunicationException e) { + if (isLogEnabled()) + LOG.error("Problem acknowledging frame response. (retry={})", retries); + } + } + + if (nextMsg != null) + currentResponse = new GetHistoryPageCarelinkMessageBody(nextMsg.getMessageBody().getTxData()); + else { + if (isLogEnabled()) + LOG.error("We couldn't acknowledge frame from pump, aborting operation."); + } + } + } + + if (rawHistoryPage.getLength() != 1024) { + if (isLogEnabled()) + LOG.warn("getPumpHistory: short page. Expected length of 1024, found length of " + + rawHistoryPage.getLength()); + doneWithError = true; + } + + if (!rawHistoryPage.isChecksumOK()) { + if (isLogEnabled()) + LOG.error("getPumpHistory: checksum is wrong"); + doneWithError = true; + } + + if (doneWithError) { + MedtronicUtil.setPumpDeviceState(PumpDeviceState.Sleeping); + return pumpTotalResult; + } + + rawHistoryPage.dumpToDebug(); + + List medtronicHistoryEntries = pumpHistoryDecoder + .processPageAndCreateRecords(rawHistoryPage); + + if (isLogEnabled()) + LOG.debug("getPumpHistory: Found {} history entries.", medtronicHistoryEntries.size()); + + pumpTotalResult.addHistoryEntries(medtronicHistoryEntries, pageNumber); + + if (isLogEnabled()) + LOG.debug("getPumpHistory: Search status: Search finished: {}", pumpTotalResult.isSearchFinished()); + + if (pumpTotalResult.isSearchFinished()) { + MedtronicUtil.setPumpDeviceState(PumpDeviceState.Sleeping); + + return pumpTotalResult; + } + } + + MedtronicUtil.setPumpDeviceState(PumpDeviceState.Sleeping); + + return pumpTotalResult; + + } + + + public String getErrorResponse() { + return this.errorMessage; + } + + + @Override + public byte[] createPumpMessageContent(RLMessageType type) { + switch (type) { + case PowerOn: + return MedtronicUtil.buildCommandPayload(MedtronicCommandType.RFPowerOn, // + new byte[]{2, 1, (byte) receiverDeviceAwakeForMinutes}); // maybe this is better FIXME + + case ReadSimpleData: + return MedtronicUtil.buildCommandPayload(MedtronicCommandType.PumpModel, null); + } + return new byte[0]; + } + + + private PumpMessage makePumpMessage(MedtronicCommandType messageType, byte[] body) { + return makePumpMessage(messageType, body == null ? new CarelinkShortMessageBody() + : new CarelinkShortMessageBody(body)); + } + + + private PumpMessage makePumpMessage(MedtronicCommandType messageType) { + return makePumpMessage(messageType, (byte[]) null); + } + + + private PumpMessage makePumpMessage(MedtronicCommandType messageType, MessageBody messageBody) { + PumpMessage msg = new PumpMessage(); + msg.init(PacketType.Carelink, rileyLinkServiceData.pumpIDBytes, messageType, messageBody); + return msg; + } + + + private PumpMessage sendAndGetResponse(MedtronicCommandType commandType) throws RileyLinkCommunicationException { + + return sendAndGetResponse(commandType, null, DEFAULT_TIMEOUT); + } + + + /** + * Main wrapper method for sending data - (for getting responses) + * + * @param commandType + * @param bodyData + * @param timeoutMs + * @return + */ + private PumpMessage sendAndGetResponse(MedtronicCommandType commandType, byte[] bodyData, int timeoutMs) + throws RileyLinkCommunicationException { + // wakeUp + if (doWakeUpBeforeCommand) + wakeUp(receiverDeviceAwakeForMinutes, false); + + MedtronicUtil.setPumpDeviceState(PumpDeviceState.Active); + + // create message + PumpMessage msg; + + if (bodyData == null) + msg = makePumpMessage(commandType); + else + msg = makePumpMessage(commandType, bodyData); + + // send and wait for response + PumpMessage response = sendAndListen(msg, timeoutMs); + + MedtronicUtil.setPumpDeviceState(PumpDeviceState.Sleeping); + + return response; + } + + + private PumpMessage sendAndListen(RLMessage msg) throws RileyLinkCommunicationException { + return sendAndListen(msg, 4000); // 2000 + } + + + // All pump communications go through this function. + private PumpMessage sendAndListen(RLMessage msg, int timeout_ms) throws RileyLinkCommunicationException { + return sendAndListen(msg, timeout_ms, PumpMessage.class); + } + + + private Object sendAndGetResponseWithCheck(MedtronicCommandType commandType) { + + return sendAndGetResponseWithCheck(commandType, null); + } + + + private Object sendAndGetResponseWithCheck(MedtronicCommandType commandType, byte[] bodyData) { + + if (isLogEnabled()) + LOG.debug("getDataFromPump: {}", commandType); + + for (int retries = 0; retries < MAX_COMMAND_TRIES; retries++) { + + try { + PumpMessage response = null; + + response = sendAndGetResponse(commandType, bodyData, DEFAULT_TIMEOUT + (DEFAULT_TIMEOUT * retries)); + + String check = checkResponseContent(response, commandType.commandDescription, + commandType.expectedLength); + + if (check == null) { + + Object dataResponse = medtronicConverter.convertResponse(commandType, response.getRawContent()); + + if (dataResponse != null) { + this.errorMessage = null; + if (isLogEnabled()) + LOG.debug("Converted response for {} is {}.", commandType.name(), dataResponse); + + return dataResponse; + } else { + this.errorMessage = "Error decoding response."; + } + } else { + this.errorMessage = check; + // return null; + } + + } catch (RileyLinkCommunicationException e) { + if (isLogEnabled()) + LOG.warn("Error getting response from RileyLink (error={}, retry={})", e.getMessage(), retries + 1); + } + + } + + return null; + } + + + private String checkResponseContent(PumpMessage response, String method, int expectedLength) { + + if (!response.isValid()) { + String responseData = String.format("%s: Invalid response.", method); + if (isLogEnabled()) + LOG.warn(responseData); + return responseData; + } + + byte[] contents = response.getRawContent(); + + if (contents != null) { + if (contents.length >= expectedLength) { + LOG.trace("{}: Content: {}", method, ByteUtil.shortHexString(contents)); + return null; + + } else { + String responseData = String.format( + "%s: Cannot return data. Data is too short [expected=%s, received=%s].", method, "" + + expectedLength, "" + contents.length); + + if (isLogEnabled()) + LOG.warn(responseData); + return responseData; + } + } else { + String responseData = String.format("%s: Cannot return data. Null response.", method); + LOG.warn(responseData); + return responseData; + } + } + + + // PUMP SPECIFIC COMMANDS + + public Float getRemainingInsulin() { + + Object responseObject = sendAndGetResponseWithCheck(MedtronicCommandType.GetRemainingInsulin); + + return responseObject == null ? null : (Float) responseObject; + } + + + public MedtronicDeviceType getPumpModel() { + + Object responseObject = sendAndGetResponseWithCheck(MedtronicCommandType.PumpModel); + + return responseObject == null ? null : (MedtronicDeviceType) responseObject; + } + + + public BasalProfile getBasalProfile() { + + // wakeUp + if (doWakeUpBeforeCommand) + wakeUp(receiverDeviceAwakeForMinutes, false); + + MedtronicCommandType commandType = MedtronicCommandType.GetBasalProfileSTD; + + if (isLogEnabled()) + LOG.debug("getDataFromPump: {}", commandType); + + MedtronicUtil.setCurrentCommand(commandType); + + MedtronicUtil.setPumpDeviceState(PumpDeviceState.Active); + + for (int retries = 0; retries <= MAX_COMMAND_TRIES; retries++) { + + try { + // create message + PumpMessage msg; + + msg = makePumpMessage(commandType); + + // send and wait for response + PumpMessage response = null; + + response = sendAndListen(msg, DEFAULT_TIMEOUT + (DEFAULT_TIMEOUT * retries)); + +// LOG.debug("1st Response: " + HexDump.toHexStringDisplayable(response.getRawContent())); +// LOG.debug("1st Response: " + HexDump.toHexStringDisplayable(response.getMessageBody().getTxData())); + + String check = checkResponseContent(response, commandType.commandDescription, 1); + + byte[] data = null; + + if (check == null) { + + data = response.getRawContentOfFrame(); + + PumpMessage ackMsg = makePumpMessage(MedtronicCommandType.CommandACK, new PumpAckMessageBody()); + + while (checkIfWeHaveMoreData(commandType, response, data)) { + + response = sendAndListen(ackMsg, DEFAULT_TIMEOUT + (DEFAULT_TIMEOUT * retries)); + +// LOG.debug("{} Response: {}", runs, HexDump.toHexStringDisplayable(response2.getRawContent())); +// LOG.debug("{} Response: {}", runs, +// HexDump.toHexStringDisplayable(response2.getMessageBody().getTxData())); + + String check2 = checkResponseContent(response, commandType.commandDescription, 1); + + if (check2 == null) { + + data = ByteUtil.concat(data, response.getRawContentOfFrame()); + + } else { + this.errorMessage = check2; + LOG.error("Error with response got GetProfile: " + check2); + } + } + + } else { + errorMessage = check; + } + + BasalProfile basalProfile = (BasalProfile) medtronicConverter.convertResponse(commandType, data); + + if (basalProfile != null) { + if (isLogEnabled()) + LOG.debug("Converted response for {} is {}.", commandType.name(), basalProfile); + + MedtronicUtil.setCurrentCommand(null); + MedtronicUtil.setPumpDeviceState(PumpDeviceState.Sleeping); + + return basalProfile; + } + + } catch (RileyLinkCommunicationException e) { + LOG.error("Error getting response from RileyLink (error={}, retry={})", e.getMessage(), retries + 1); + } + } + + LOG.warn("Error reading profile in max retries."); + MedtronicUtil.setCurrentCommand(null); + MedtronicUtil.setPumpDeviceState(PumpDeviceState.Sleeping); + + return null; + + } + + + private boolean checkIfWeHaveMoreData(MedtronicCommandType commandType, PumpMessage response, byte[] data) { + + if (commandType == MedtronicCommandType.GetBasalProfileSTD || // + commandType == MedtronicCommandType.GetBasalProfileA || // + commandType == MedtronicCommandType.GetBasalProfileB) { + byte[] responseRaw = response.getRawContentOfFrame(); + + int last = responseRaw.length - 1; + + LOG.debug("Length: " + data.length); + + if (data.length >= BasalProfile.MAX_RAW_DATA_SIZE) { + return false; + } + + if (responseRaw.length < 2) { + return false; + } + + return !(responseRaw[last] == 0x00 && responseRaw[last - 1] == 0x00 && responseRaw[last - 2] == 0x00); + } + + return false; + } + + + public ClockDTO getPumpTime() { + + ClockDTO clockDTO = new ClockDTO(); + clockDTO.localDeviceTime = new LocalDateTime(); + + Object responseObject = sendAndGetResponseWithCheck(MedtronicCommandType.GetRealTimeClock); + + if (responseObject != null) { + clockDTO.pumpTime = (LocalDateTime) responseObject; + return clockDTO; + } + + return null; + } + + + public TempBasalPair getTemporaryBasal() { + + Object responseObject = sendAndGetResponseWithCheck(MedtronicCommandType.ReadTemporaryBasal); + + return responseObject == null ? null : (TempBasalPair) responseObject; + } + + + public Map getPumpSettings() { + + Object responseObject = sendAndGetResponseWithCheck(MedtronicCommandType.getSettings(MedtronicUtil + .getMedtronicPumpModel())); + + return responseObject == null ? null : (Map) responseObject; + } + + + public Boolean setBolus(double units) { + + if (isLogEnabled()) + LOG.info("setBolus: " + units); + + return setCommand(MedtronicCommandType.SetBolus, MedtronicUtil.getBolusStrokes(units)); + + } + + + public boolean setTBR(TempBasalPair tbr) { + + if (isLogEnabled()) + LOG.info("setTBR: " + tbr.getDescription()); + + return setCommand(MedtronicCommandType.SetTemporaryBasal, tbr.getAsRawData()); + } + + + public Boolean setPumpTime() { + + GregorianCalendar gc = new GregorianCalendar(); + gc.add(Calendar.SECOND, 5); + + if (isLogEnabled()) + LOG.info("setPumpTime: " + DateTimeUtil.toString(gc)); + + int i = 1; + byte[] data = new byte[8]; + data[0] = 7; + data[i] = (byte) gc.get(Calendar.HOUR_OF_DAY); + data[i + 1] = (byte) gc.get(Calendar.MINUTE); + data[i + 2] = (byte) gc.get(Calendar.SECOND); + + byte[] yearByte = MedtronicUtil.getByteArrayFromUnsignedShort(gc.get(Calendar.YEAR), true); + + data[i + 3] = yearByte[0]; + data[i + 4] = yearByte[1]; + + data[i + 5] = (byte) (gc.get(Calendar.MONTH) + 1); + data[i + 6] = (byte) gc.get(Calendar.DAY_OF_MONTH); + + //LOG.info("setPumpTime: Body: " + ByteUtil.getHex(data)); + + return setCommand(MedtronicCommandType.SetRealTimeClock, data); + + } + + + private boolean setCommand(MedtronicCommandType commandType, byte[] body) { + + for (int retries = 0; retries <= MAX_COMMAND_TRIES; retries++) { + + try { + if (this.doWakeUpBeforeCommand) + wakeUp(false); + + if (debugSetCommands) + LOG.debug("{}: Body - {}", commandType.getCommandDescription(), + ByteUtil.getHex(body)); + + PumpMessage msg = makePumpMessage(commandType, new CarelinkLongMessageBody(body)); + + PumpMessage pumpMessage = runCommandWithArgs(msg); + + if (debugSetCommands) + LOG.debug("{}: {}", commandType.getCommandDescription(), pumpMessage.getResponseContent()); + + if (pumpMessage.commandType == MedtronicCommandType.CommandACK) { + return true; + } else { + LOG.warn("We received non-ACK response from pump: {}", pumpMessage.getResponseContent()); + } + + } catch (RileyLinkCommunicationException e) { + if (isLogEnabled()) + LOG.warn("Error getting response from RileyLink (error={}, retry={})", e.getMessage(), retries + 1); + } + } + + return false; + } + + + public boolean cancelTBR() { + return setTBR(new TempBasalPair(0.0d, false, 0)); + } + + + public BatteryStatusDTO getRemainingBattery() { + + Object responseObject = sendAndGetResponseWithCheck(MedtronicCommandType.GetBatteryStatus); + + return responseObject == null ? null : (BatteryStatusDTO) responseObject; + } + + + public Boolean setBasalProfile(BasalProfile basalProfile) { + + List> basalProfileFrames = MedtronicUtil.getBasalProfileFrames(basalProfile.getRawData()); + + for (int retries = 0; retries <= MAX_COMMAND_TRIES; retries++) { + + PumpMessage responseMessage = null; + try { + responseMessage = runCommandWithFrames(MedtronicCommandType.SetBasalProfileSTD, + basalProfileFrames); + + if (responseMessage.commandType == MedtronicCommandType.CommandACK) + return true; + + } catch (RileyLinkCommunicationException e) { + LOG.warn("Error getting response from RileyLink (error={}, retry={})", e.getMessage(), retries + 1); + } + + if (responseMessage != null) + LOG.warn("Set Basal Profile: Invalid response: commandType={},rawData={}", responseMessage.commandType, ByteUtil.shortHexString(responseMessage.getRawContent())); + else + LOG.warn("Set Basal Profile: Null response."); + } + + return false; + + } + + + private boolean isLogEnabled() { + return L.isEnabled(L.PUMPCOMM); + } + + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicConverter.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicConverter.java new file mode 100644 index 0000000000..dc0a35f2e8 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicConverter.java @@ -0,0 +1,430 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.comm; + +import org.joda.time.IllegalFieldValueException; +import org.joda.time.LocalDateTime; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashMap; +import java.util.Map; + +import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; +import info.nightscout.androidaps.plugins.pump.common.utils.StringUtil; +import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.BasalProfile; +import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.BatteryStatusDTO; +import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.PumpSettingDTO; +import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.TempBasalPair; +import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicCommandType; +import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicDeviceType; +import info.nightscout.androidaps.plugins.pump.medtronic.defs.PumpConfigurationGroup; +import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil; + +/** + * Created by andy on 5/9/18. + * High level decoder for data returned through MedtroniUIComm + */ + +public class MedtronicConverter { + + private static final Logger LOG = LoggerFactory.getLogger(L.PUMPCOMM); + + MedtronicDeviceType pumpModel; + + + public Object convertResponse(MedtronicCommandType commandType, byte[] rawContent) { + + if ((rawContent == null || rawContent.length < 1) && commandType != MedtronicCommandType.PumpModel) { + LOG.warn("Content is empty or too short, no data to convert (type={},isNull={},length={})", + commandType.name(), rawContent == null, rawContent == null ? "-" : rawContent.length); + return null; + } + + if (isLogEnabled()) + LOG.debug("Raw response before convert: " + ByteUtil.shortHexString(rawContent)); + + this.pumpModel = MedtronicUtil.getMedtronicPumpModel(); + + switch (commandType) { + + case PumpModel: { + return decodeModel(rawContent); + } + + case GetRealTimeClock: { + return decodeTime(rawContent); + } + + case GetRemainingInsulin: { + return decodeRemainingInsulin(rawContent); + } + + case GetBatteryStatus: { + return decodeBatteryStatus(rawContent); // 1 + } + + case GetBasalProfileSTD: + case GetBasalProfileA: + case GetBasalProfileB: { + return decodeBasalProfile(rawContent); + + } + + case ReadTemporaryBasal: { + return new TempBasalPair(rawContent); // 5 + } + + case Settings_512: { + return decodeSettingsLoop(rawContent); + } + + case Settings: { + return decodeSettingsLoop(rawContent); + } + + case SetBolus: { + return rawContent; // 1 + } + + default: { + throw new RuntimeException("Unsupported command Type: " + commandType); + } + + } + + } + + + private BasalProfile decodeBasalProfile(byte[] rawContent) { + + BasalProfile basalProfile = new BasalProfile(rawContent); + + return basalProfile.verify() ? basalProfile : null; + } + + + private MedtronicDeviceType decodeModel(byte[] rawContent) { + + if ((rawContent == null || rawContent.length < 4)) { + LOG.warn("Error reading PumpModel, returning Unknown_Device"); + return MedtronicDeviceType.Unknown_Device; + } + + String rawModel = StringUtil.fromBytes(ByteUtil.substring(rawContent, 1, 3)); + MedtronicDeviceType pumpModel = MedtronicDeviceType.getByDescription(rawModel); + if (isLogEnabled()) + LOG.debug("PumpModel: [raw={}, resolved={}]", rawModel, pumpModel.name()); + + if (pumpModel != MedtronicDeviceType.Unknown_Device) { + if (!MedtronicUtil.isModelSet()) { + MedtronicUtil.setMedtronicPumpModel(pumpModel); + } + } + + return pumpModel; + } + + + private BatteryStatusDTO decodeBatteryStatus(byte[] rawData) { + // 00 7C 00 00 + + BatteryStatusDTO batteryStatus = new BatteryStatusDTO(); + + int status = rawData[0]; + + if (status == 0) { + batteryStatus.batteryStatusType = BatteryStatusDTO.BatteryStatusType.Normal; + } else if (status == 1) { + batteryStatus.batteryStatusType = BatteryStatusDTO.BatteryStatusType.Low; + } else if (status == 2) { + batteryStatus.batteryStatusType = BatteryStatusDTO.BatteryStatusType.Unknown; + } + + if (rawData.length > 1) { + + // if response in 3 bytes then we add additional information + double d = (ByteUtil.toInt(rawData[1], rawData[2]) * 1.0d) / 100.0d; + + batteryStatus.voltage = d; + batteryStatus.extendedDataReceived = true; + } + + return batteryStatus; + } + + + protected Float decodeRemainingInsulin(byte[] rawData) { + int startIdx = 0; + + this.pumpModel = MedtronicUtil.getMedtronicPumpModel(); + + int strokes = pumpModel == null ? 10 : pumpModel.getBolusStrokes(); + + if (strokes == 40) { + startIdx = 2; + } + + float value = ByteUtil.toInt(rawData[startIdx], rawData[startIdx + 1]) / (1.0f * strokes); + + if (isLogEnabled()) + LOG.debug("Remaining insulin: " + value); + return value; + } + + + private LocalDateTime decodeTime(byte[] rawContent) { + + int hours = ByteUtil.asUINT8(rawContent[0]); + int minutes = ByteUtil.asUINT8(rawContent[1]); + int seconds = ByteUtil.asUINT8(rawContent[2]); + int year = (ByteUtil.asUINT8(rawContent[4]) & 0x3f) + 1984; + int month = ByteUtil.asUINT8(rawContent[5]); + int day = ByteUtil.asUINT8(rawContent[6]); + try { + LocalDateTime pumpTime = new LocalDateTime(year, month, day, hours, minutes, seconds); + return pumpTime; + } catch (IllegalFieldValueException e) { + LOG.error( + "decodeTime: Failed to parse pump time value: year=%d, month=%d, hours=%d, minutes=%d, seconds=%d", + year, month, day, hours, minutes, seconds); + return null; + } + + } + + + public Map decodeSettingsLoop(byte[] rd) { + + Map map = new HashMap<>(); + + addSettingToMap("PCFG_MAX_BOLUS", "" + decodeMaxBolus(rd), PumpConfigurationGroup.Bolus, map); + addSettingToMap( + "PCFG_MAX_BASAL", + "" + + decodeBasalInsulin(ByteUtil.makeUnsignedShort(rd[getSettingIndexMaxBasal()], + rd[getSettingIndexMaxBasal() + 1])), PumpConfigurationGroup.Basal, map); + addSettingToMap("CFG_BASE_CLOCK_MODE", rd[getSettingIndexTimeDisplayFormat()] == 0 ? "12h" : "24h", + PumpConfigurationGroup.General, map); + + addSettingToMap("PCFG_BASAL_PROFILES_ENABLED", parseResultEnable(rd[10]), PumpConfigurationGroup.Basal, map); + + if (rd[10] == 1) { + String patt; + switch (rd[11]) { + case 0: + patt = "STD"; + break; + + case 1: + patt = "A"; + break; + + case 2: + patt = "B"; + break; + + default: + patt = "???"; + break; + } + + addSettingToMap("PCFG_ACTIVE_BASAL_PROFILE", patt, PumpConfigurationGroup.Basal, map); + + } else { + addSettingToMap("PCFG_ACTIVE_BASAL_PROFILE", "STD", PumpConfigurationGroup.Basal, map); + } + + addSettingToMap("PCFG_TEMP_BASAL_TYPE", rd[14] != 0 ? "Percent" : "Units", PumpConfigurationGroup.Basal, map); + + return map; + } + + + private Map decodeSettings512(byte[] rd) { + + Map map = new HashMap<>(); + + addSettingToMap("PCFG_AUTOOFF_TIMEOUT", "" + rd[0], PumpConfigurationGroup.General, map); + + if (rd[1] == 4) { + addSettingToMap("PCFG_ALARM_MODE", "Silent", PumpConfigurationGroup.Sound, map); + } else { + addSettingToMap("PCFG_ALARM_MODE", "Normal", PumpConfigurationGroup.Sound, map); + addSettingToMap("PCFG_ALARM_BEEP_VOLUME", "" + rd[1], PumpConfigurationGroup.Sound, map); + } + + addSettingToMap("PCFG_AUDIO_BOLUS_ENABLED", parseResultEnable(rd[2]), PumpConfigurationGroup.Bolus, map); + + if (rd[2] == 1) { + addSettingToMap("PCFG_AUDIO_BOLUS_STEP_SIZE", "" + decodeBolusInsulin(ByteUtil.asUINT8(rd[3])), + PumpConfigurationGroup.Bolus, map); + } + + addSettingToMap("PCFG_VARIABLE_BOLUS_ENABLED", parseResultEnable(rd[4]), PumpConfigurationGroup.Bolus, map); + addSettingToMap("PCFG_MAX_BOLUS", "" + decodeMaxBolus(rd), PumpConfigurationGroup.Bolus, map); + addSettingToMap( + "PCFG_MAX_BASAL", + "" + + decodeBasalInsulin(ByteUtil.makeUnsignedShort(rd[getSettingIndexMaxBasal()], + rd[getSettingIndexMaxBasal() + 1])), PumpConfigurationGroup.Basal, map); + addSettingToMap("CFG_BASE_CLOCK_MODE", rd[getSettingIndexTimeDisplayFormat()] == 0 ? "12h" : "24h", + PumpConfigurationGroup.General, map); + + if (MedtronicDeviceType.isSameDevice(pumpModel, MedtronicDeviceType.Medtronic_523andHigher)) { + addSettingToMap("PCFG_INSULIN_CONCENTRATION", "" + (rd[9] == 0 ? 50 : 100), PumpConfigurationGroup.Insulin, + map); +// LOG.debug("Insulin concentration: " + rd[9]); + } else { + addSettingToMap("PCFG_INSULIN_CONCENTRATION", "" + (rd[9] != 0 ? 50 : 100), PumpConfigurationGroup.Insulin, + map); +// LOG.debug("Insulin concentration: " + rd[9]); + } + addSettingToMap("PCFG_BASAL_PROFILES_ENABLED", parseResultEnable(rd[10]), PumpConfigurationGroup.Basal, map); + + if (rd[10] == 1) { + String patt; + switch (rd[11]) { + case 0: + patt = "STD"; + break; + + case 1: + patt = "A"; + break; + + case 2: + patt = "B"; + break; + + default: + patt = "???"; + break; + } + + addSettingToMap("PCFG_ACTIVE_BASAL_PROFILE", patt, PumpConfigurationGroup.Basal, map); + + } + + addSettingToMap("CFG_MM_RF_ENABLED", parseResultEnable(rd[12]), PumpConfigurationGroup.General, map); + addSettingToMap("CFG_MM_BLOCK_ENABLED", parseResultEnable(rd[13]), PumpConfigurationGroup.General, map); + + addSettingToMap("PCFG_TEMP_BASAL_TYPE", rd[14] != 0 ? "Percent" : "Units", PumpConfigurationGroup.Basal, map); + + if (rd[14] == 1) { + addSettingToMap("PCFG_TEMP_BASAL_PERCENT", "" + rd[15], PumpConfigurationGroup.Basal, map); + } + + addSettingToMap("CFG_PARADIGM_LINK_ENABLE", parseResultEnable(rd[16]), PumpConfigurationGroup.General, map); + + decodeInsulinActionSetting(rd, map); + + return map; + } + + + public void addSettingToMap(String key, String value, PumpConfigurationGroup group, Map map) { + map.put(key, new PumpSettingDTO(key, value, group)); + } + + + public Map decodeSettings(byte[] rd) { + Map map = decodeSettings512(rd); + + addSettingToMap("PCFG_MM_RESERVOIR_WARNING_TYPE_TIME", rd[18] != 0 ? "PCFG_MM_RESERVOIR_WARNING_TYPE_TIME" + : "PCFG_MM_RESERVOIR_WARNING_TYPE_UNITS", PumpConfigurationGroup.Other, map); + + addSettingToMap("PCFG_MM_SRESERVOIR_WARNING_POINT", "" + ByteUtil.asUINT8(rd[19]), + PumpConfigurationGroup.Other, map); + + addSettingToMap("CFG_MM_KEYPAD_LOCKED", parseResultEnable(rd[20]), PumpConfigurationGroup.Other, map); + + if (MedtronicDeviceType.isSameDevice(pumpModel, MedtronicDeviceType.Medtronic_523andHigher)) { + + addSettingToMap("PCFG_BOLUS_SCROLL_STEP_SIZE", "" + rd[21], PumpConfigurationGroup.Bolus, map); + addSettingToMap("PCFG_CAPTURE_EVENT_ENABLE", parseResultEnable(rd[22]), PumpConfigurationGroup.Other, map); + addSettingToMap("PCFG_OTHER_DEVICE_ENABLE", parseResultEnable(rd[23]), PumpConfigurationGroup.Other, map); + addSettingToMap("PCFG_OTHER_DEVICE_PAIRED_STATE", parseResultEnable(rd[24]), PumpConfigurationGroup.Other, + map); + } + + return map; + } + + + protected String parseResultEnable(int i) { + switch (i) { + case 0: + return "No"; + case 1: + return "Yes"; + default: + return "???"; + } + } + + + public float getStrokesPerUnit(boolean isBasal) { + return isBasal ? 40.0f : 10; // pumpModel.getBolusStrokes(); + } + + + // 512 + public void decodeInsulinActionSetting(byte[] ai, Map map) { + if (MedtronicDeviceType.isSameDevice(pumpModel, MedtronicDeviceType.Medtronic_512_712)) { + addSettingToMap("PCFG_INSULIN_ACTION_TYPE", (ai[17] != 0 ? "Regular" : "Fast"), + PumpConfigurationGroup.Insulin, map); + } else { + int i = ai[17]; + String s = ""; + + if ((i == 0) || (i == 1)) { + s = ai[17] != 0 ? "Regular" : "Fast"; + } else { + if (i == 15) + s = "Unset"; + else + s = "Curve: " + i; + } + + addSettingToMap("PCFG_INSULIN_ACTION_TYPE", s, PumpConfigurationGroup.Insulin, map); + } + } + + + public double decodeBasalInsulin(int i) { + return (double) i / (double) getStrokesPerUnit(true); + } + + + public double decodeBolusInsulin(int i) { + + return (double) i / (double) getStrokesPerUnit(false); + } + + + private int getSettingIndexMaxBasal() { + return is523orHigher() ? 7 : 6; + } + + + private int getSettingIndexTimeDisplayFormat() { + return is523orHigher() ? 9 : 8; + } + + + public double decodeMaxBolus(byte[] ai) { + return is523orHigher() ? decodeBolusInsulin(ByteUtil.toInt(ai[5], ai[6])) : decodeBolusInsulin(ByteUtil + .asUINT8(ai[5])); + } + + + private boolean is523orHigher() { + return (MedtronicDeviceType.isSameDevice(pumpModel, MedtronicDeviceType.Medtronic_523andHigher)); + } + + + private boolean isLogEnabled() { + return L.isEnabled(L.PUMPCOMM); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoder.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoder.java new file mode 100644 index 0000000000..fa0e58a15a --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoder.java @@ -0,0 +1,191 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.comm.history; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; +import info.nightscout.androidaps.plugins.pump.common.utils.StringUtil; +import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicDeviceType; +import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil; + + +/** + * This file was taken from GGC - GNU Gluco Control (ggc.sourceforge.net), application for diabetes + * management and modified/extended for AAPS. + * + * Author: Andy {andy.rozman@gmail.com} + */ + +public abstract class MedtronicHistoryDecoder implements MedtronicHistoryDecoderInterface { + + private static final Logger LOG = LoggerFactory.getLogger(L.PUMPCOMM); + + protected ByteUtil bitUtils; + + // STATISTICS (remove at later time or not) + protected boolean statisticsEnabled = true; + protected Map unknownOpCodes; + protected Map> mapStatistics; + protected MedtronicDeviceType deviceType; + + + public MedtronicHistoryDecoder() { + } + + + // public abstract Class getHistoryEntryClass(); + + // public abstract RecordDecodeStatus decodeRecord(T record); + + public abstract void postProcess(); + + + protected abstract void runPostDecodeTasks(); + + + // TODO_ extend this to also use bigger pages (for now we support only 1024 pages) + private List checkPage(RawHistoryPage page, boolean partial) throws RuntimeException { + List byteList = new ArrayList(); + + // if (!partial && page.getData().length != 1024 /* page.commandType.getRecordLength() */) { + // LOG.error("Page size is not correct. Size should be {}, but it was {} instead.", 1024, + // page.getData().length); + // // throw exception perhaps + // return byteList; + // } + + if (MedtronicUtil.getMedtronicPumpModel() == null) { + LOG.error("Device Type is not defined."); + return byteList; + } + + if (page.getData().length != 1024) { + return ByteUtil.getListFromByteArray(page.getData()); + } else if (page.isChecksumOK()) { + return ByteUtil.getListFromByteArray(page.getOnlyData()); + } else { + return null; + } + } + + + public List processPageAndCreateRecords(RawHistoryPage rawHistoryPage) { + return processPageAndCreateRecords(rawHistoryPage, false); + } + + + protected void prepareStatistics() { + if (!statisticsEnabled) + return; + + unknownOpCodes = new HashMap(); + mapStatistics = new HashMap>(); + + for (RecordDecodeStatus stat : RecordDecodeStatus.values()) { + mapStatistics.put(stat, new HashMap()); + } + } + + + protected void addToStatistics(MedtronicHistoryEntryInterface pumpHistoryEntry, RecordDecodeStatus status, + Integer opCode) { + if (!statisticsEnabled) + return; + + if (opCode != null) { + if (!unknownOpCodes.containsKey(opCode)) { + unknownOpCodes.put(opCode, opCode); + } + return; + } + + if (!mapStatistics.get(status).containsKey(pumpHistoryEntry.getEntryTypeName())) { + mapStatistics.get(status).put(pumpHistoryEntry.getEntryTypeName(), ""); + } + } + + + protected void showStatistics() { + StringBuilder sb = new StringBuilder(); + + for (Map.Entry unknownEntry : unknownOpCodes.entrySet()) { + StringUtil.appendToStringBuilder(sb, "" + unknownEntry.getKey(), ", "); + } + + if (isLogEnabled()) + LOG.debug("STATISTICS OF PUMP DECODE"); + + if (unknownOpCodes.size() > 0) { + LOG.warn("Unknown Op Codes: {}", sb.toString()); + } + + for (Map.Entry> entry : mapStatistics.entrySet()) { + sb = new StringBuilder(); + + if (entry.getKey() != RecordDecodeStatus.OK) { + if (entry.getValue().size() == 0) + continue; + + for (Map.Entry entrysub : entry.getValue().entrySet()) { + StringUtil.appendToStringBuilder(sb, entrysub.getKey(), ", "); + } + + String spaces = StringUtils.repeat(" ", 14 - entry.getKey().name().length()); + + if (isLogEnabled()) + LOG.debug(" {}{} - {}. Elements: {}", entry.getKey().name(), spaces, entry.getValue().size(), + sb.toString()); + } else { + if (isLogEnabled()) + LOG.debug(" {} - {}", entry.getKey().name(), entry.getValue().size()); + } + } + } + + + private int getUnsignedByte(byte value) { + if (value < 0) + return value + 256; + else + return value; + } + + + protected int getUnsignedInt(int value) { + if (value < 0) + return value + 256; + else + return value; + } + + + public String getFormattedFloat(float value, int decimals) { + return StringUtil.getFormatedValueUS(value, decimals); + } + + + private List processPageAndCreateRecords(RawHistoryPage rawHistoryPage, boolean partial) { + List dataClear = checkPage(rawHistoryPage, partial); + List records = createRecords(dataClear); + + for (T record : records) { + decodeRecord(record); + } + + runPostDecodeTasks(); + + return records; + } + + protected boolean isLogEnabled() { + return L.isEnabled(L.PUMPCOMM); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoderInterface.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoderInterface.java new file mode 100644 index 0000000000..b98b2d7d33 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoderInterface.java @@ -0,0 +1,15 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.comm.history; + +import java.util.List; + +/** + * Created by andy on 3/10/19. + */ + +public interface MedtronicHistoryDecoderInterface { + + RecordDecodeStatus decodeRecord(T record); + + List createRecords(List dataClear); + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntry.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntry.java new file mode 100644 index 0000000000..3b9dfbb48d --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntry.java @@ -0,0 +1,316 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.comm.history; + +import com.google.gson.annotations.Expose; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; +import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil; +import info.nightscout.androidaps.plugins.pump.common.utils.StringUtil; + +/** + * This file was taken from GGC - GNU Gluco Control (ggc.sourceforge.net), application for diabetes + * management and modified/extended for AAPS. + *

+ * Author: Andy {andy.rozman@gmail.com} + */ + +public abstract class MedtronicHistoryEntry implements MedtronicHistoryEntryInterface { + + protected List rawData; + + public static final Logger LOG = LoggerFactory.getLogger(MedtronicHistoryEntry.class); + + protected int[] sizes = new int[3]; + + protected byte[] head; + protected byte[] datetime; + protected byte[] body; + + // protected LocalDateTime dateTime; + + public long id; + + @Expose + public String DT; + + @Expose + public Long atechDateTime; + + @Expose + protected Map decodedData; + + public long phoneDateTime; // time on phone + + /** + * Pump id that will be used with AAPS object (time * 1000 + historyType (max is FF = 255) + */ + protected Long pumpId; + + /** + * if history object is already linked to AAPS object (either Treatment, TempBasal or TDD (tdd's + * are not actually + * linked)) + */ + public boolean linked = false; + + /** + * Linked object, see linked + */ + public Object linkedObject = null; + + + public void setLinkedObject(Object linkedObject) { + this.linked = true; + this.linkedObject = linkedObject; + } + + + public void setData(List listRawData, boolean doNotProcess) { + this.rawData = listRawData; + + // System.out.println("Head: " + sizes[0] + ", dates: " + sizes[1] + + // ", body=" + sizes[2]); + + if (doNotProcess) + return; + + head = new byte[getHeadLength() - 1]; + for (int i = 1; i < (getHeadLength()); i++) { + head[i - 1] = listRawData.get(i); + } + + if (getDateTimeLength() > 0) { + datetime = new byte[getDateTimeLength()]; + + for (int i = getHeadLength(), j = 0; j < getDateTimeLength(); i++, j++) { + datetime[j] = listRawData.get(i); + } + } + + if (getBodyLength() > 0) { + body = new byte[getBodyLength()]; + + for (int i = (getHeadLength() + getDateTimeLength()), j = 0; j < getBodyLength(); i++, j++) { + body[j] = listRawData.get(i); + } + + } + + } + + + public String getDateTimeString() { + return this.DT == null ? "Unknown" : this.DT; + } + + + public String getDecodedDataAsString() { + if (decodedData == null) + if (isNoDataEntry()) + return "No data"; + else + return ""; + else + return decodedData.toString(); + } + + + public boolean hasData() { + return (decodedData != null) || (isNoDataEntry()) || getEntryTypeName().equals("UnabsorbedInsulin"); + } + + + public boolean isNoDataEntry() { + return (sizes[0] == 2 && sizes[1] == 5 && sizes[2] == 0); + } + + + public Map getDecodedData() { + return this.decodedData; + } + + + public Object getDecodedDataEntry(String key) { + return this.decodedData != null ? this.decodedData.get(key) : null; + } + + + public boolean hasDecodedDataEntry(String key) { + return this.decodedData.containsKey(key); + } + + + public boolean showRaw() { + return getEntryTypeName().equals("EndResultTotals"); + } + + + public int getHeadLength() { + return sizes[0]; + } + + + public int getDateTimeLength() { + return sizes[1]; + } + + + public int getBodyLength() { + return sizes[2]; + } + + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + + if (this.DT == null) { + LOG.error("DT is null. RawData={}", ByteUtil.getHex(this.rawData)); + } + + sb.append(getToStringStart()); + sb.append(", DT: " + (this.DT == null ? "null" : StringUtil.getStringInLength(this.DT, 19))); + sb.append(", length="); + sb.append(getHeadLength()); + sb.append(","); + sb.append(getDateTimeLength()); + sb.append(","); + sb.append(getBodyLength()); + sb.append("("); + sb.append((getHeadLength() + getDateTimeLength() + getBodyLength())); + sb.append(")"); + + boolean hasData = hasData(); + + if (hasData) { + sb.append(", data=" + getDecodedDataAsString()); + } + + if (hasData && !showRaw()) { + sb.append("]"); + return sb.toString(); + } + + if (head != null) { + sb.append(", head="); + sb.append(ByteUtil.shortHexString(this.head)); + } + + if (datetime != null) { + sb.append(", datetime="); + sb.append(ByteUtil.shortHexString(this.datetime)); + } + + if (body != null) { + sb.append(", body="); + sb.append(ByteUtil.shortHexString(this.body)); + } + + sb.append(", rawData="); + sb.append(ByteUtil.shortHexString(this.rawData)); + sb.append("]"); + + // sb.append(" DT: "); + // sb.append(this.dateTime == null ? " - " : this.dateTime.toString("dd.MM.yyyy HH:mm:ss")); + + // sb.append(" Ext: "); + + return sb.toString(); + } + + + public abstract int getOpCode(); + + + public abstract String getToStringStart(); + + + public List getRawData() { + return rawData; + } + + + public byte getRawDataByIndex(int index) { + return rawData.get(index); + } + + + public int getUnsignedRawDataByIndex(int index) { + return ByteUtil.convertUnsignedByteToInt(rawData.get(index)); + } + + + public void setRawData(List rawData) { + this.rawData = rawData; + } + + + public byte[] getHead() { + return head; + } + + + public void setHead(byte[] head) { + this.head = head; + } + + + public byte[] getDatetime() { + return datetime; + } + + + public void setDatetime(byte[] datetime) { + this.datetime = datetime; + } + + + public byte[] getBody() { + return body; + } + + + public void setBody(byte[] body) { + this.body = body; + } + + + public void setAtechDateTime(long dt) { + this.atechDateTime = dt; + this.DT = DateTimeUtil.toString(this.atechDateTime); + } + + + public void addDecodedData(String key, Object value) { + if (decodedData == null) + decodedData = new HashMap<>(); + + decodedData.put(key, value); + } + + + public String toShortString() { + if (head == null) { + return "Unidentified record. "; + } else { + return "HistoryRecord: head=[" + ByteUtil.shortHexString(this.head) + "]"; + } + } + + public boolean containsDecodedData(String key) { + if (decodedData == null) + return false; + + return decodedData.containsKey(key); + } + + // if we extend to CGMS this need to be changed back + // public abstract PumpHistoryEntryType getEntryType(); + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntryInterface.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntryInterface.java new file mode 100644 index 0000000000..38b7e1dbeb --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntryInterface.java @@ -0,0 +1,16 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.comm.history; + +import java.util.List; + +/** + * Created by andy on 7/24/18. + */ +public interface MedtronicHistoryEntryInterface { + + String getEntryTypeName(); + + void setData(List listRawData, boolean doNotProcess); + + int getDateLength(); + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/RawHistoryPage.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/RawHistoryPage.java new file mode 100644 index 0000000000..77ae298235 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/RawHistoryPage.java @@ -0,0 +1,88 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.comm.history; + +import java.util.Arrays; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; +import info.nightscout.androidaps.plugins.pump.common.utils.CRC; +import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil; + +/** + * Created by geoff on 6/4/16. + */ +public class RawHistoryPage { + + private static final Logger LOG = LoggerFactory.getLogger(L.PUMPBTCOMM); + + private byte[] data = new byte[0]; + + + public RawHistoryPage() { + } + + + public void appendData(byte[] newdata) { + data = ByteUtil.concat(data, newdata); + } + + + public byte[] getData() { + return data; + } + + + public byte[] getOnlyData() { + return Arrays.copyOfRange(data, 0, 1022); + } + + + public int getLength() { + return data.length; + } + + + public boolean isChecksumOK() { + if (getLength() != 1024) { + return false; + } + byte[] computedCRC = CRC.calculate16CCITT(ByteUtil.substring(data, 0, 1022)); + + int crcCalculated = ByteUtil.toInt(computedCRC[0], computedCRC[1]); + int crcStored = ByteUtil.toInt(data[1022], data[1023]); + + if (crcCalculated != crcStored) { + LOG.error("Stored CRC ({}) is different than calculated ({}), but ignored for now.", crcStored, + crcCalculated); + } else { + if (MedtronicUtil.isLowLevelDebug()) + LOG.debug("CRC ok."); + } + + return crcCalculated == crcStored; + } + + + public void dumpToDebug() { + int linesize = 80; + int offset = 0; + + StringBuffer sb = new StringBuffer(); + + while (offset < data.length) { + int bytesToLog = linesize; + if (offset + linesize > data.length) { + bytesToLog = data.length - offset; + } + sb.append(ByteUtil.shortHexString(ByteUtil.substring(data, offset, bytesToLog)) + " "); + // sb.append("\n"); + + offset += linesize; + } + + LOG.debug("History Page Data:\n{}", sb.toString()); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/RecordDecodeStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/RecordDecodeStatus.java new file mode 100644 index 0000000000..18cb02cfad --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/RecordDecodeStatus.java @@ -0,0 +1,30 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.comm.history; + +/** + * This file was taken from GGC - GNU Gluco Control (ggc.sourceforge.net), application for diabetes + * management and modified/extended for AAPS. + * + * Author: Andy {andy.rozman@gmail.com} + */ + +public enum RecordDecodeStatus { + OK("OK "), // + Ignored("IGNORE "), // + NotSupported("N/A YET"), // + Error("ERROR "), // + WIP("WIP "), // + Unknown("UNK "); + + String description; + + + RecordDecodeStatus(String description) { + this.description = description; + + } + + + public String getDescription() { + return description; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/CGMSHistoryEntry.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/CGMSHistoryEntry.java new file mode 100644 index 0000000000..4d35426fb8 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/CGMSHistoryEntry.java @@ -0,0 +1,92 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.comm.history.cgms; + +import org.apache.commons.lang3.StringUtils; +import org.joda.time.LocalDateTime; + +import java.util.List; + +import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; +import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil; +import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.MedtronicHistoryEntry; + +/** + * This file was taken from GGC - GNU Gluco Control (ggc.sourceforge.net), application for diabetes + * management and modified/extended for AAPS. + * + * Author: Andy {andy.rozman@gmail.com} + */ + +public class CGMSHistoryEntry extends MedtronicHistoryEntry { + + private CGMSHistoryEntryType entryType; + private Integer opCode; // this is set only when we have unknown entry... + + + public CGMSHistoryEntryType getEntryType() { + return entryType; + } + + + public void setEntryType(CGMSHistoryEntryType entryType) { + this.entryType = entryType; + + this.sizes[0] = entryType.getHeadLength(); + this.sizes[1] = entryType.getDateLength(); + this.sizes[2] = entryType.getBodyLength(); + } + + + @Override + public String getEntryTypeName() { + return this.entryType.name(); + } + + + public void setData(List listRawData, boolean doNotProcess) { + if (this.entryType.schemaSet) { + super.setData(listRawData, doNotProcess); + } else { + this.rawData = listRawData; + } + } + + + @Override + public int getDateLength() { + return this.entryType.getDateLength(); + } + + + @Override + public int getOpCode() { + if (opCode == null) + return entryType.getOpCode(); + else + return opCode; + } + + + public void setOpCode(Integer opCode) { + this.opCode = opCode; + } + + + public boolean hasTimeStamp() { + return (this.entryType.hasDate()); + } + + + @Override + public String getToStringStart() { + + return "CGMSHistoryEntry [type=" + StringUtils.rightPad(entryType.name(), 18) + " [" + + StringUtils.leftPad("" + getOpCode(), 3) + ", 0x" + ByteUtil.getCorrectHexValue(getOpCode()) + "]"; + } + + + public void setDateTime(LocalDateTime timeStamp, int getIndex) { + + setAtechDateTime(DateTimeUtil.toATechDate(timeStamp.plusMinutes(getIndex * 5))); + + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/CGMSHistoryEntryType.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/CGMSHistoryEntryType.java new file mode 100644 index 0000000000..ef24ef136d --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/CGMSHistoryEntryType.java @@ -0,0 +1,135 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.comm.history.cgms; + +import java.util.HashMap; +import java.util.Map; + +/** + * This file was taken from GGC - GNU Gluco Control (ggc.sourceforge.net), application for diabetes + * management and modified/extended for AAPS. + * + * Author: Andy {andy.rozman@gmail.com} + */ + +public enum CGMSHistoryEntryType { + + None(0, "None", 1, 0, 0, DateType.None), // + + DataEnd(0x01, "DataEnd", 1, 0, 0, DateType.PreviousTimeStamp), // + SensorWeakSignal(0x02, "SensorWeakSignal", 1, 0, 0, DateType.PreviousTimeStamp), // + SensorCal(0x03, "SensorCal", 1, 0, 1, DateType.PreviousTimeStamp), // + SensorPacket(0x04, "SensorPacket", 1, 0, 1, DateType.PreviousTimeStamp), + SensorError(0x05, "SensorError", 1, 0, 1, DateType.PreviousTimeStamp), + SensorDataLow(0x06, "SensorDataLow", 1, 0, 1, DateType.PreviousTimeStamp), + SensorDataHigh(0x07, "SensorDataHigh", 1, 0, 1, DateType.PreviousTimeStamp), + SensorTimestamp(0x08, "SensorTimestamp", 1, 4, 0, DateType.MinuteSpecific), // + BatteryChange(0x0a, "BatteryChange", 1, 4, 0, DateType.MinuteSpecific), // + SensorStatus(0x0b, "SensorStatus", 1, 4, 0, DateType.MinuteSpecific), // + DateTimeChange(0x0c, "DateTimeChange", 1, 4, 0, DateType.SecondSpecific), // + SensorSync(0x0d, "SensorSync',packet_size=4", 1, 4, 0, DateType.MinuteSpecific), // + CalBGForGH(0x0e, "CalBGForGH',packet_size=5", 1, 4, 1, DateType.MinuteSpecific), // + SensorCalFactor(0x0f, "SensorCalFactor", 1, 4, 2, DateType.MinuteSpecific), // + Something10(0x10, "10-Something", 1, 4, 0, DateType.MinuteSpecific), // + Something19(0x13, "19-Something", 1, 0, 0, DateType.PreviousTimeStamp), + GlucoseSensorData(0xFF, "GlucoseSensorData", 1, 0, 0, DateType.PreviousTimeStamp); + + private static Map opCodeMap = new HashMap<>(); + + static { + for (CGMSHistoryEntryType type : values()) { + opCodeMap.put(type.opCode, type); + } + } + + public boolean schemaSet; + private int opCode; + private String description; + private int headLength; + private int dateLength; + private int bodyLength; + private int totalLength; + private DateType dateType; + + + CGMSHistoryEntryType(int opCode, String name, int head, int date, int body, DateType dateType) { + this.opCode = opCode; + this.description = name; + this.headLength = head; + this.dateLength = date; + this.bodyLength = body; + this.totalLength = (head + date + body); + this.schemaSet = true; + this.dateType = dateType; + } + + + // private CGMSHistoryEntryType(int opCode, String name, int length) + // { + // this.opCode = opCode; + // this.description = name; + // this.headLength = 0; + // this.dateLength = 0; + // this.bodyLength = 0; + // this.totalLength = length + 1; // opCode + // } + + public static CGMSHistoryEntryType getByCode(int opCode) { + if (opCodeMap.containsKey(opCode)) { + return opCodeMap.get(opCode); + } else + return CGMSHistoryEntryType.None; + } + + + public int getCode() { + return this.opCode; + } + + + public int getTotalLength() { + return totalLength; + } + + + public int getOpCode() { + return opCode; + } + + + public String getDescription() { + return description; + } + + + public int getHeadLength() { + return headLength; + } + + + public int getDateLength() { + return dateLength; + } + + + public int getBodyLength() { + return bodyLength; + } + + + public DateType getDateType() { + return dateType; + } + + + public boolean hasDate() { + return (this.dateType == DateType.MinuteSpecific) || (this.dateType == DateType.SecondSpecific); + } + + public enum DateType { + None, // + MinuteSpecific, // + SecondSpecific, // + PreviousTimeStamp // + + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/MedtronicCGMSHistoryDecoder.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/MedtronicCGMSHistoryDecoder.java new file mode 100644 index 0000000000..5a0f1e7983 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/MedtronicCGMSHistoryDecoder.java @@ -0,0 +1,470 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.comm.history.cgms; + +import org.joda.time.LocalDateTime; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil; +import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.MedtronicHistoryDecoder; +import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.RecordDecodeStatus; + +/** + * This file was taken from GGC - GNU Gluco Control (ggc.sourceforge.net), application for diabetes + * management and modified/extended for AAPS. + * + * Author: Andy {andy.rozman@gmail.com} + */ + +public class MedtronicCGMSHistoryDecoder extends MedtronicHistoryDecoder { + + private static final Logger LOG = LoggerFactory.getLogger(L.PUMPCOMM); + + + // CGMSValuesWriter cgmsValuesWriter = null; + + public MedtronicCGMSHistoryDecoder() { + } + + + public RecordDecodeStatus decodeRecord(CGMSHistoryEntry record) { + try { + return decodeRecord(record, false); + } catch (Exception ex) { + LOG.error(" Error decoding: type={}, ex={}", record.getEntryType().name(), ex.getMessage(), ex); + return RecordDecodeStatus.Error; + } + } + + + public RecordDecodeStatus decodeRecord(CGMSHistoryEntry entry, boolean x) { + + if (entry.getDateTimeLength() > 0) { + parseDate(entry); + } + + switch (entry.getEntryType()) { + + case SensorPacket: + decodeSensorPacket(entry); + break; + + case SensorError: + decodeSensorError(entry); + break; + + case SensorDataLow: + decodeDataHighLow(entry, 40); + break; + + case SensorDataHigh: + decodeDataHighLow(entry, 400); + break; + + case SensorTimestamp: + decodeSensorTimestamp(entry); + break; + + case SensorCal: + decodeSensorCal(entry); + break; + + case SensorCalFactor: + decodeSensorCalFactor(entry); + break; + + case SensorSync: + decodeSensorSync(entry); + break; + + case SensorStatus: + decodeSensorStatus(entry); + break; + + case CalBGForGH: + decodeCalBGForGH(entry); + break; + + case GlucoseSensorData: + decodeGlucoseSensorData(entry); + break; + + // just timestamp + case BatteryChange: + case Something10: + case DateTimeChange: + break; + + // just relative timestamp + case Something19: + case DataEnd: + case SensorWeakSignal: + break; + + case None: + break; + + } + + return RecordDecodeStatus.NotSupported; + } + + + @Override + public void postProcess() { + + } + + + public List createRecords(List dataClearInput) { + + List dataClear = reverseList(dataClearInput, Byte.class); + + prepareStatistics(); + + int counter = 0; + + List outList = new ArrayList(); + + // create CGMS entries (without dates) + do { + int opCode = getUnsignedInt(dataClear.get(counter)); + counter++; + + CGMSHistoryEntryType entryType; + + if (opCode == 0) { + // continue; + } else if ((opCode > 0) && (opCode < 20)) { + entryType = CGMSHistoryEntryType.getByCode(opCode); + + if (entryType == CGMSHistoryEntryType.None) { + this.unknownOpCodes.put(opCode, opCode); + LOG.warn("GlucoseHistoryEntry with unknown code: " + opCode); + + CGMSHistoryEntry pe = new CGMSHistoryEntry(); + pe.setEntryType(CGMSHistoryEntryType.None); + pe.setOpCode(opCode); + + pe.setData(Arrays.asList((byte) opCode), false); + + outList.add(pe); + } else { + // System.out.println("OpCode: " + opCode); + + List listRawData = new ArrayList(); + listRawData.add((byte) opCode); + + for (int j = 0; j < (entryType.getTotalLength() - 1); j++) { + listRawData.add(dataClear.get(counter)); + counter++; + } + + CGMSHistoryEntry pe = new CGMSHistoryEntry(); + pe.setEntryType(entryType); + + pe.setOpCode(opCode); + pe.setData(listRawData, false); + + // System.out.println("Record: " + pe); + + outList.add(pe); + } + } else { + CGMSHistoryEntry pe = new CGMSHistoryEntry(); + pe.setEntryType(CGMSHistoryEntryType.GlucoseSensorData); + + pe.setData(Arrays.asList((byte) opCode), false); + + outList.add(pe); + } + + } while (counter < dataClear.size()); + + List reversedOutList = reverseList(outList, CGMSHistoryEntry.class); + + Long timeStamp = null; + LocalDateTime dateTime = null; + int getIndex = 0; + + for (CGMSHistoryEntry entry : reversedOutList) { + + decodeRecord(entry); + + if (entry.hasTimeStamp()) { + timeStamp = entry.atechDateTime; + dateTime = DateTimeUtil.toLocalDateTime(timeStamp); + getIndex = 0; + } else if (entry.getEntryType() == CGMSHistoryEntryType.GlucoseSensorData) { + getIndex++; + if (dateTime != null) + entry.setDateTime(dateTime, getIndex); + } else { + if (dateTime != null) + entry.setDateTime(dateTime, getIndex); + } + + if (isLogEnabled()) + LOG.debug("Record: {}", entry); + } + + return reversedOutList; + + } + + + private List reverseList(List dataClearInput, Class clazz) { + + List outList = new ArrayList(); + + for (int i = dataClearInput.size() - 1; i > 0; i--) { + outList.add(dataClearInput.get(i)); + } + + return outList; + } + + + private int parseMinutes(int one) { + return (one & Integer.parseInt("0111111", 2)); + } + + + private int parseHours(int one) { + return (one & 0x1F); + } + + + private int parseDay(int one) { + return one & 0x1F; + } + + + private int parseMonths(int first_byte, int second_byte) { + + int first_two_bits = first_byte >> 6; + int second_two_bits = second_byte >> 6; + + return (first_two_bits << 2) + second_two_bits; + } + + + private int parseYear(int year) { + return (year & 0x0F) + 2000; + } + + + private Long parseDate(CGMSHistoryEntry entry) { + + if (!entry.getEntryType().hasDate()) + return null; + + byte[] data = entry.getDatetime(); + + if (entry.getEntryType().getDateType() == CGMSHistoryEntryType.DateType.MinuteSpecific) { + + Long atechDateTime = DateTimeUtil.toATechDate(parseYear(data[3]), parseMonths(data[0], data[1]), + parseDay(data[2]), parseHours(data[0]), parseMinutes(data[1]), 0); + + entry.setAtechDateTime(atechDateTime); + + return atechDateTime; + + } else if (entry.getEntryType().getDateType() == CGMSHistoryEntryType.DateType.SecondSpecific) { + LOG.warn("parseDate for SecondSpecific type is not implemented."); + throw new RuntimeException(); + // return null; + } else + return null; + + } + + + private void decodeGlucoseSensorData(CGMSHistoryEntry entry) { + int sgv = entry.getUnsignedRawDataByIndex(0) * 2; + entry.addDecodedData("sgv", sgv); + } + + + private void decodeCalBGForGH(CGMSHistoryEntry entry) { + + int amount = ((entry.getRawDataByIndex(3) & 0b00100000) << 3) | entry.getRawDataByIndex(5); + // + String originType; + + switch (entry.getRawDataByIndex(3) >> 5 & 0b00000011) { + case 0x00: + originType = "rf"; + break; + + default: + originType = "unknown"; + + } + + entry.addDecodedData("amount", amount); + entry.addDecodedData("originType", originType); + + } + + + private void decodeSensorSync(CGMSHistoryEntry entry) { + + String syncType; + + switch (entry.getRawDataByIndex(3) >> 5 & 0b00000011) { + case 0x01: + syncType = "new"; + break; + + case 0x02: + syncType = "old"; + break; + + default: + syncType = "find"; + break; + + } + + entry.addDecodedData("syncType", syncType); + } + + + private void decodeSensorStatus(CGMSHistoryEntry entry) { + + String statusType; + + switch (entry.getRawDataByIndex(3) >> 5 & 0b00000011) { + case 0x00: + statusType = "off"; + break; + + case 0x01: + statusType = "on"; + break; + + case 0x02: + statusType = "lost"; + break; + + default: + statusType = "unknown"; + } + + entry.addDecodedData("statusType", statusType); + + } + + + private void decodeSensorCalFactor(CGMSHistoryEntry entry) { + + double factor = (entry.getRawDataByIndex(5) << 8 | entry.getRawDataByIndex(6)) / 1000.0d; + + entry.addDecodedData("factor", factor); + } + + + private void decodeSensorCal(CGMSHistoryEntry entry) { + + String calibrationType; + + switch (entry.getRawDataByIndex(1)) { + case 0x00: + calibrationType = "meter_bg_now"; + break; + + case 0x01: + calibrationType = "waiting"; + break; + + case 0x02: + calibrationType = "cal_error"; + break; + + default: + calibrationType = "unknown"; + } + + entry.addDecodedData("calibrationType", calibrationType); + + } + + + private void decodeSensorTimestamp(CGMSHistoryEntry entry) { + + String sensorTimestampType; + + switch (entry.getRawDataByIndex(3) >> 5 & 0b00000011) { + + case 0x00: + sensorTimestampType = "LastRf"; + break; + + case 0x01: + sensorTimestampType = "PageEnd"; + break; + + case 0x02: + sensorTimestampType = "Gap"; + break; + + default: + sensorTimestampType = "Unknown"; + break; + + } + + entry.addDecodedData("sensorTimestampType", sensorTimestampType); + } + + + private void decodeSensorPacket(CGMSHistoryEntry entry) { + + String packetType; + + switch (entry.getRawDataByIndex(1)) { + case 0x02: + packetType = "init"; + break; + + default: + packetType = "unknown"; + } + + entry.addDecodedData("packetType", packetType); + } + + + private void decodeSensorError(CGMSHistoryEntry entry) { + + String errorType; + + switch (entry.getRawDataByIndex(1)) { + case 0x01: + errorType = "end"; + break; + + default: + errorType = "unknown"; + } + + entry.addDecodedData("errorType", errorType); + } + + + private void decodeDataHighLow(CGMSHistoryEntry entry, int sgv) { + entry.addDecodedData("sgv", sgv); + } + + + @Override + protected void runPostDecodeTasks() { + this.showStatistics(); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoder.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoder.java new file mode 100644 index 0000000000..32ca320de2 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoder.java @@ -0,0 +1,720 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump; + +import android.util.Log; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; +import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil; +import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.MedtronicHistoryDecoder; +import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.RecordDecodeStatus; +import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.BasalProfile; +import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.BolusDTO; +import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.BolusWizardDTO; +import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.DailyTotalsDTO; +import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.TempBasalPair; +import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicDeviceType; +import info.nightscout.androidaps.plugins.pump.medtronic.defs.PumpBolusType; +import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil; + +/** + * This file was taken from GGC - GNU Gluco Control (ggc.sourceforge.net), application for diabetes + * management and modified/extended for AAPS. + * + * Author: Andy {andy.rozman@gmail.com} + */ + +public class MedtronicPumpHistoryDecoder extends MedtronicHistoryDecoder { + + private static final Logger LOG = LoggerFactory.getLogger(L.PUMPCOMM); + + private PumpHistoryEntry tbrPreviousRecord; + private PumpHistoryEntry changeTimeRecord; + private MedtronicDeviceType deviceType; + private static final String TAG = "MdtPumpHistoryDecoder"; + + + public MedtronicPumpHistoryDecoder() { + } + + + public List createRecords(List dataClear) { + prepareStatistics(); + + int counter = 0; + int record = 0; + boolean incompletePacket = false; + deviceType = MedtronicUtil.getMedtronicPumpModel(); + + List outList = new ArrayList(); + String skipped = null; + int elementStart = 0; + + if (dataClear.size() == 0) { + Log.e(TAG, "Empty page."); + return outList; + } + + do { + int opCode = dataClear.get(counter); + boolean special = false; + incompletePacket = false; + + if (opCode == 0) { + counter++; + if (skipped == null) + skipped = "0x00"; + else + skipped += " 0x00"; + continue; + } else { + if (skipped != null) { + Log.w(TAG, " ... Skipped " + skipped); + skipped = null; + } + } + + PumpHistoryEntryType entryType = PumpHistoryEntryType.getByCode(opCode); + + PumpHistoryEntry pe = new PumpHistoryEntry(); + pe.setEntryType(entryType); + pe.setOffset(counter); + + counter++; + + if (counter >= 1022) { + break; + } + + List listRawData = new ArrayList(); + listRawData.add((byte) opCode); + + if (entryType == PumpHistoryEntryType.UnabsorbedInsulin + || entryType == PumpHistoryEntryType.UnabsorbedInsulin512) { + int elements = dataClear.get(counter); + listRawData.add((byte) elements); + counter++; + + int els = getUnsignedInt(elements); + + for (int k = 0; k < (els - 2); k++) { + listRawData.add((byte) dataClear.get(counter)); + counter++; + } + + special = true; + } else { + + for (int j = 0; j < (entryType.getTotalLength() - 1); j++) { + + try { + listRawData.add(dataClear.get(counter)); + counter++; + } catch (Exception ex) { + LOG.error("OpCode: " + ByteUtil.shortHexString((byte) opCode) + ", Invalid package: " + + ByteUtil.getHex(listRawData)); + // throw ex; + incompletePacket = true; + break; + } + + } + + if (incompletePacket) + break; + + } + + if (entryType == PumpHistoryEntryType.None) { + LOG.error("Error in code. We should have not come into this branch."); + } else { + + if (pe.getEntryType() == PumpHistoryEntryType.UnknownBasePacket) { + pe.setOpCode(opCode); + } + + if (entryType.getHeadLength() == 0) + special = true; + + pe.setData(listRawData, special); + + RecordDecodeStatus decoded = decodeRecord(pe); + + if ((decoded == RecordDecodeStatus.OK) || (decoded == RecordDecodeStatus.Ignored)) { + //Log.i(TAG, "#" + record + " " + decoded.getDescription() + " " + pe); + } else { + Log.w(TAG, "#" + record + " " + decoded.getDescription() + " " + pe); + } + + addToStatistics(pe, decoded, null); + + record++; + + if (decoded == RecordDecodeStatus.OK) // we add only OK records, all others are ignored + { + outList.add(pe); + } + } + + } while (counter < dataClear.size()); + + return outList; + } + + + public RecordDecodeStatus decodeRecord(PumpHistoryEntry record) { + try { + return decodeRecord(record, false); + } catch (Exception ex) { + LOG.error(" Error decoding: type={}, ex={}", record.getEntryType().name(), ex.getMessage(), ex); + return RecordDecodeStatus.Error; + } + } + + + public RecordDecodeStatus decodeRecord(PumpHistoryEntry entry, boolean x) { + + if (entry.getDateTimeLength() > 0) { + decodeDateTime(entry); + } + + switch (entry.getEntryType()) { + + // Valid entries, but not processed + case ChangeBasalPattern: + case CalBGForPH: + case ChangeRemoteId: + case ClearAlarm: + case ChangeAlarmNotifyMode: // ChangeUtility: + case EnableDisableRemote: + case BGReceived: // Ian3F: CGMS + case SensorAlert: // Ian08 CGMS + case ChangeTimeFormat: + case ChangeReservoirWarningTime: + case ChangeBolusReminderEnable: + case ChangeBolusReminderTime: + case ChangeChildBlockEnable: + case BolusWizardEnabled: + case ChangeBGReminderOffset: + case ChangeAlarmClockTime: + case ChangeMeterId: + case ChangeParadigmID: + case JournalEntryMealMarker: + case JournalEntryExerciseMarker: + case DeleteBolusReminderTime: + case SetAutoOff: + case SelfTest: + case JournalEntryInsulinMarker: + case JournalEntryOtherMarker: + case ChangeBolusWizardSetup512: + case ChangeSensorSetup2: + case ChangeSensorAlarmSilenceConfig: + case ChangeSensorRateOfChangeAlertSetup: + case ChangeBolusScrollStepSize: + case ChangeBolusWizardSetup: + case ChangeVariableBolus: + case ChangeAudioBolus: + case ChangeBGReminderEnable: + case ChangeAlarmClockEnable: + case BolusReminder: + case DeleteAlarmClockTime: + case ChangeCarbUnits: + case ChangeWatchdogEnable: + case ChangeOtherDeviceID: + case ReadOtherDevicesIDs: + case BGReceived512: + case SensorStatus: + case ReadCaptureEventEnabled: + case ChangeCaptureEventEnable: + case ReadOtherDevicesStatus: + return RecordDecodeStatus.OK; + + case Sensor_0x54: + case Sensor_0x55: + case Sensor_0x51: + case Sensor_0x52: + case EventUnknown_MM522_0x45: + case EventUnknown_MM522_0x46: + case EventUnknown_MM522_0x47: + case EventUnknown_MM522_0x48: + case EventUnknown_MM522_0x49: + case EventUnknown_MM522_0x4a: + case EventUnknown_MM522_0x4b: + case EventUnknown_MM522_0x4c: + case EventUnknown_MM512_0x10: + case EventUnknown_MM512_0x2e: + case EventUnknown_MM512_0x37: + case EventUnknown_MM512_0x38: + case EventUnknown_MM512_0x4e: + case EventUnknown_MM522_0x70: + case EventUnknown_MM512_0x88: + case EventUnknown_MM512_0x94: + case EventUnknown_MM522_0xE8: + case EventUnknown_0x4d: + case EventUnknown_MM522_0x25: + case EventUnknown_MM522_0x05: + LOG.debug(" -- ignored Unknown Pump Entry: " + entry); + return RecordDecodeStatus.Ignored; + + case UnabsorbedInsulin: + case UnabsorbedInsulin512: + return RecordDecodeStatus.Ignored; + + // **** Implemented records **** + + case DailyTotals522: + case DailyTotals523: + case DailyTotals515: + case EndResultTotals: + return decodeDailyTotals(entry); + + case ChangeBasalProfile_OldProfile: + case ChangeBasalProfile_NewProfile: + return decodeBasalProfile(entry); + + case BasalProfileStart: + return decodeBasalProfileStart(entry); + + case ChangeTime: + changeTimeRecord = entry; + return RecordDecodeStatus.OK; + + case NewTimeSet: + decodeChangeTime(entry); + return RecordDecodeStatus.OK; + + case TempBasalDuration: + // decodeTempBasal(entry); + return RecordDecodeStatus.OK; + + case TempBasalRate: + // decodeTempBasal(entry); + return RecordDecodeStatus.OK; + + case Bolus: + decodeBolus(entry); + return RecordDecodeStatus.OK; + + case BatteryChange: + decodeBatteryActivity(entry); + return RecordDecodeStatus.OK; + + case LowReservoir: + decodeLowReservoir(entry); + return RecordDecodeStatus.OK; + + case LowBattery: + case Suspend: + case Resume: + case Rewind: + case NoDeliveryAlarm: + case ChangeTempBasalType: + case ChangeMaxBolus: + case ChangeMaxBasal: + case ClearSettings: + case SaveSettings: + return RecordDecodeStatus.OK; + + case BolusWizard: + return decodeBolusWizard(entry); + + case BolusWizard512: + return decodeBolusWizard512(entry); + + case Prime: + decodePrime(entry); + return RecordDecodeStatus.OK; + + case TempBasalCombined: + return RecordDecodeStatus.Ignored; + + case None: + case UnknownBasePacket: + return RecordDecodeStatus.Error; + + default: { + LOG.debug("Not supported: " + entry.getEntryType()); + return RecordDecodeStatus.NotSupported; + } + + } + + // return RecordDecodeStatus.Error; + + } + + + private RecordDecodeStatus decodeDailyTotals(PumpHistoryEntry entry) { + + entry.addDecodedData("Raw Data", ByteUtil.getHex(entry.getRawData())); + + DailyTotalsDTO totals = new DailyTotalsDTO(entry); + + entry.addDecodedData("Object", totals); + + return RecordDecodeStatus.OK; + } + + + private RecordDecodeStatus decodeBasalProfile(PumpHistoryEntry entry) { + + // LOG.debug("decodeBasalProfile: {}", entry); + + BasalProfile basalProfile = new BasalProfile(); + basalProfile.setRawDataFromHistory(entry.getBody()); + + // LOG.debug("decodeBasalProfile BasalProfile: {}", basalProfile); + + entry.addDecodedData("Object", basalProfile); + + return RecordDecodeStatus.OK; + } + + + private void decodeChangeTime(PumpHistoryEntry entry) { + if (changeTimeRecord == null) + return; + + entry.setDisplayableValue(entry.getDateTimeString()); + + this.changeTimeRecord = null; + } + + + private void decodeBatteryActivity(PumpHistoryEntry entry) { + // this.writeData(PumpBaseType.Event, entry.getHead()[0] == 0 ? PumpEventType.BatteryRemoved : + // PumpEventType.BatteryReplaced, entry.getATechDate()); + + entry.setDisplayableValue(entry.getHead()[0] == 0 ? "Battery Removed" : "Battery Replaced"); + } + + + public static String getFormattedValue(float value, int decimals) { + return String.format(Locale.ENGLISH, "%." + decimals + "f", value); + } + + + private RecordDecodeStatus decodeBasalProfileStart(PumpHistoryEntry entry) { + byte[] body = entry.getBody(); + // int bodyOffset = headerSize + timestampSize; + int offset = body[0] * 1000 * 30 * 60; + Float rate = null; + int index = entry.getHead()[0]; + + if (MedtronicDeviceType.isSameDevice(MedtronicUtil.getMedtronicPumpModel(), + MedtronicDeviceType.Medtronic_523andHigher)) { + rate = body[1] * 0.025f; + } + + LOG.info("Basal Profile Start: offset={}, rate={}, index={}, body_raw={}", offset, rate, index, + body); + + if (rate == null) { + LOG.warn("Basal Profile Start (ERROR): offset={}, rate={}, index={}, body_raw={}", offset, rate, index, + body); + return RecordDecodeStatus.Error; + } else { + // writeData(PumpBaseType.Basal, PumpBasalType.ValueChange, getFormattedFloat(rate, 3), + // entry.getATechDate()); + entry.addDecodedData("Value", getFormattedFloat(rate, 3)); + entry.setDisplayableValue(getFormattedFloat(rate, 3)); + return RecordDecodeStatus.OK; + } + +// profileIndex = asUINT8(data[1]); +// offset = asUINT8(data[7]) * 30 * 1000 * 60; +// rate = (double)(asUINT8(data[8])) / 40.0; + + } + + + private RecordDecodeStatus decodeBolusWizard(PumpHistoryEntry entry) { + byte[] body = entry.getBody(); + + BolusWizardDTO dto = new BolusWizardDTO(); + + float bolusStrokes = 10.0f; + + if (MedtronicDeviceType.isSameDevice(MedtronicUtil.getMedtronicPumpModel(), + MedtronicDeviceType.Medtronic_523andHigher)) { + // https://github.com/ps2/minimed_rf/blob/master/lib/minimed_rf/log_entries/bolus_wizard.rb#L102 + bolusStrokes = 40.0f; + + dto.carbs = ((body[1] & 0x0c) << 6) + body[0]; + + dto.bloodGlucose = ((body[1] & 0x03) << 8) + entry.getHead()[0]; + dto.carbRatio = body[1] / 10.0f; + // carb_ratio (?) = (((self.body[2] & 0x07) << 8) + self.body[3]) / + // 10.0s + dto.insulinSensitivity = new Float(body[4]); + dto.bgTargetLow = (int)body[5]; + dto.bgTargetHigh = (int)body[14]; + dto.correctionEstimate = (((body[9] & 0x38) << 5) + body[6]) / bolusStrokes; + dto.foodEstimate = ((body[7] << 8) + body[8]) / bolusStrokes; + dto.unabsorbedInsulin = ((body[10] << 8) + body[11]) / bolusStrokes; + dto.bolusTotal = ((body[12] << 8) + body[13]) / bolusStrokes; + } else { + dto.bloodGlucose = (((body[1] & 0x0F) << 8) | entry.getHead()[0]); + dto.carbs = (int)body[0]; + dto.carbRatio = Float.valueOf(body[2]); + dto.insulinSensitivity = new Float(body[3]); + dto.bgTargetLow = (int)body[4]; + dto.bgTargetHigh = (int)body[12]; + dto.bolusTotal = body[11] / bolusStrokes; + dto.foodEstimate = body[6] / bolusStrokes; + dto.unabsorbedInsulin = body[9] / bolusStrokes; + dto.bolusTotal = body[11] / bolusStrokes; + dto.correctionEstimate = (body[7] + (body[5] & 0x0F)) / bolusStrokes; + } + + if (dto.bloodGlucose != null && dto.bloodGlucose < 0) { + dto.bloodGlucose = ByteUtil.convertUnsignedByteToInt(dto.bloodGlucose.byteValue()); + } + + dto.atechDateTime = entry.atechDateTime; + entry.addDecodedData("Object", dto); + entry.setDisplayableValue(dto.getDisplayableValue()); + + return RecordDecodeStatus.OK; + } + + + private RecordDecodeStatus decodeBolusWizard512(PumpHistoryEntry entry) { + byte[] body = entry.getBody(); + + BolusWizardDTO dto = new BolusWizardDTO(); + + float bolusStrokes = 10.0f; + + dto.bloodGlucose = ((body[1] & 0x03 << 8) | entry.getHead()[0]); + dto.carbs = (body[1] & 0xC) << 6 | body[0]; // (int)body[0]; + dto.carbRatio = Float.valueOf(body[2]); + dto.insulinSensitivity = new Float(body[3]); + dto.bgTargetLow = (int)body[4]; + dto.foodEstimate = body[6] / 10.0f; + dto.correctionEstimate = (body[7] + (body[5] & 0x0F)) / bolusStrokes; + dto.unabsorbedInsulin = body[9] / bolusStrokes; + dto.bolusTotal = body[11] / bolusStrokes; + dto.bgTargetHigh = dto.bgTargetLow; + + if (dto.bloodGlucose != null && dto.bloodGlucose < 0) { + dto.bloodGlucose = ByteUtil.convertUnsignedByteToInt(dto.bloodGlucose.byteValue()); + } + + dto.atechDateTime = entry.atechDateTime; + entry.addDecodedData("Object", dto); + entry.setDisplayableValue(dto.getDisplayableValue()); + + return RecordDecodeStatus.OK; + } + + + private void decodeLowReservoir(PumpHistoryEntry entry) { + float amount = (getUnsignedInt(entry.getHead()[0]) * 1.0f / 10.0f) * 2; + + entry.setDisplayableValue(getFormattedValue(amount, 1)); + } + + + private void decodePrime(PumpHistoryEntry entry) { + float amount = bitUtils.toInt(entry.getHead()[2], entry.getHead()[3]) / 10.0f; + float fixed = bitUtils.toInt(entry.getHead()[0], entry.getHead()[1]) / 10.0f; + +// amount = (double)(asUINT8(data[4]) << 2) / 40.0; +// programmedAmount = (double)(asUINT8(data[2]) << 2) / 40.0; +// primeType = programmedAmount == 0 ? "manual" : "fixed"; + + entry.addDecodedData("Amount", amount); + entry.addDecodedData("FixedAmount", fixed); + + entry.setDisplayableValue("Amount=" + getFormattedValue(amount, 2) + ", Fixed Amount=" + + getFormattedValue(fixed, 2)); + } + + + private void decodeChangeTempBasalType(PumpHistoryEntry entry) { + entry.addDecodedData("isPercent", ByteUtil.asUINT8(entry.getRawDataByIndex(0)) == 1); // index moved from 1 -> 0 + } + + + private void decodeBgReceived(PumpHistoryEntry entry) { + entry.addDecodedData("amount", (ByteUtil.asUINT8(entry.getRawDataByIndex(0)) << 3) + (ByteUtil.asUINT8(entry.getRawDataByIndex(3)) >> 5)); + entry.addDecodedData("meter", ByteUtil.substring(entry.getRawData(), 6, 3)); // index moved from 1 -> 0 + } + + + private void decodeCalBGForPH(PumpHistoryEntry entry) { + entry.addDecodedData("amount", ((ByteUtil.asUINT8(entry.getRawDataByIndex(5)) & 0x80) << 1) + ByteUtil.asUINT8(entry.getRawDataByIndex(0))); // index moved from 1 -> 0 + } + + + private void decodeNoDeliveryAlarm(PumpHistoryEntry entry) { + //rawtype = asUINT8(data[1]); + // not sure if this is actually NoDelivery Alarm? + } + + + @Override + public void postProcess() { + } + + + @Override + protected void runPostDecodeTasks() { + this.showStatistics(); + } + + + private void decodeBolus(PumpHistoryEntry entry) { + BolusDTO bolus = new BolusDTO(); + + byte[] data = entry.getHead(); + + if (MedtronicDeviceType.isSameDevice(MedtronicUtil.getMedtronicPumpModel(), + MedtronicDeviceType.Medtronic_523andHigher)) { + bolus.setRequestedAmount(ByteUtil.toInt(data[0], data[1]) / 40.0d); + bolus.setDeliveredAmount(ByteUtil.toInt(data[2], data[3]) / 40.0d); + bolus.setInsulinOnBoard(ByteUtil.toInt(data[4], data[5]) / 40.0d); + bolus.setDuration(data[6] * 30); + } else { + bolus.setRequestedAmount(ByteUtil.asUINT8(data[0]) / 10.0d); + bolus.setDeliveredAmount(ByteUtil.asUINT8(data[1]) / 10.0d); + bolus.setDuration(ByteUtil.asUINT8(data[2]) * 30); + } + + bolus.setBolusType((bolus.getDuration() != null && (bolus.getDuration() > 0)) ? PumpBolusType.Extended + : PumpBolusType.Normal); + bolus.setAtechDateTime(entry.atechDateTime); + + entry.addDecodedData("Object", bolus); + entry.setDisplayableValue(bolus.getDisplayableValue()); + + } + + + private void decodeTempBasal(PumpHistoryEntry entry) { + + if (this.tbrPreviousRecord == null) { + // LOG.debug(this.tbrPreviousRecord.toString()); + this.tbrPreviousRecord = entry; + return; + } + + decodeTempBasal(this.tbrPreviousRecord, entry); + + tbrPreviousRecord = null; + } + + + public static void decodeTempBasal(PumpHistoryEntry tbrPreviousRecord, PumpHistoryEntry entry) { + + PumpHistoryEntry tbrRate = null, tbrDuration = null; + + if (entry.getEntryType() == PumpHistoryEntryType.TempBasalRate) { + tbrRate = entry; + } else { + tbrDuration = entry; + } + + if (tbrRate != null) { + tbrDuration = tbrPreviousRecord; + } else { + tbrRate = tbrPreviousRecord; + } + + TempBasalPair tbr = new TempBasalPair(tbrRate.getHead()[0], tbrDuration.getHead()[0], (ByteUtil.asUINT8(tbrRate + .getDatetime()[4]) >> 3) == 0); + + // System.out.println("TBR: amount=" + tbr.getInsulinRate() + ", duration=" + tbr.getDurationMinutes() + // // + " min. Packed: " + tbr.getValue() + // ); + + entry.addDecodedData("Object", tbr); + entry.setDisplayableValue(tbr.getDescription()); + + } + + + private void decodeDateTime(PumpHistoryEntry entry) { + byte[] dt = entry.getDatetime(); + + if (dt == null) { + LOG.warn("DateTime not set."); + } + + if (entry.getDateTimeLength() == 5) { + + int seconds = dt[0] & 0x3F; + int minutes = dt[1] & 0x3F; + int hour = dt[2] & 0x1F; + + int month = ((dt[0] >> 4) & 0x0c) + ((dt[1] >> 6) & 0x03); + // ((dt[0] & 0xC0) >> 6) | ((dt[1] & 0xC0) >> 4); + + int dayOfMonth = dt[3] & 0x1F; + int year = fix2DigitYear(dt[4] & 0x3F); // Assuming this is correct, need to verify. Otherwise this will be + // a problem in 2016. + + entry.setAtechDateTime(DateTimeUtil.toATechDate(year, month, dayOfMonth, hour, minutes, seconds)); + + } else if (entry.getDateTimeLength() == 2) { + int low = ByteUtil.asUINT8(dt[0]) & 0x1F; + int mhigh = (ByteUtil.asUINT8(dt[0]) & 0xE0) >> 4; + int mlow = (ByteUtil.asUINT8(dt[1]) & 0x80) >> 7; + int month = mhigh + mlow; + // int dayOfMonth = low + 1; + int dayOfMonth = dt[0] & 0x1F; + int year = 2000 + (ByteUtil.asUINT8(dt[1]) & 0x7F); + + int hour = 0; + int minutes = 0; + int seconds = 0; + + //LOG.debug("DT: {} {} {}", year, month, dayOfMonth); + + if (dayOfMonth == 32) { + LOG.warn("Entry: Day 32 {} = [{}] {}", entry.getEntryType().name(), + ByteUtil.getHex(entry.getRawData()), entry); + } + + if (isEndResults(entry.getEntryType())) { + hour = 23; + minutes = 59; + seconds = 59; + } + + entry.setAtechDateTime(DateTimeUtil.toATechDate(year, month, dayOfMonth, hour, minutes, seconds)); + + } else { + LOG.warn("Unknown datetime format: " + entry.getDateTimeLength()); + } + + } + + + private boolean isEndResults(PumpHistoryEntryType entryType) { + + return (entryType == PumpHistoryEntryType.EndResultTotals || + entryType == PumpHistoryEntryType.DailyTotals515 || + entryType == PumpHistoryEntryType.DailyTotals522 || + entryType == PumpHistoryEntryType.DailyTotals523); + } + + + private int fix2DigitYear(int year) { + if (year > 90) { + year += 1900; + } else { + year += 2000; + } + + return year; + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntry.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntry.java new file mode 100644 index 0000000000..5a290c6a02 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntry.java @@ -0,0 +1,177 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump; + +import com.google.gson.annotations.Expose; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Objects; + +import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; +import info.nightscout.androidaps.plugins.pump.common.utils.StringUtil; +import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.MedtronicHistoryEntry; + +/** + * This file was taken from GGC - GNU Gluco Control (ggc.sourceforge.net), application for diabetes + * management and modified/extended for AAPS. + *

+ * Author: Andy {andy.rozman@gmail.com} + */ + +public class PumpHistoryEntry extends MedtronicHistoryEntry { + + private static Logger LOG = LoggerFactory.getLogger(PumpHistoryEntry.class); + + @Expose + private PumpHistoryEntryType entryType; + private Integer opCode; // this is set only when we have unknown entry... + private int offset; + private String displayableValue = ""; + + + public PumpHistoryEntryType getEntryType() { + return entryType; + } + + + public void setEntryType(PumpHistoryEntryType entryType) { + this.entryType = entryType; + + this.sizes[0] = entryType.getHeadLength(); + this.sizes[1] = entryType.getDateLength(); + this.sizes[2] = entryType.getBodyLength(); + + if (this.entryType != null && this.atechDateTime != null) + setPumpId(); + } + + + private void setPumpId() { + this.pumpId = this.entryType.getCode() + (this.atechDateTime * 1000L); + } + + + @Override + public int getOpCode() { + if (opCode == null) + return entryType.getOpCode(); + else + return opCode; + } + + + public void setOpCode(Integer opCode) { + this.opCode = opCode; + } + + + @Override + public String getToStringStart() { + return "PumpHistoryEntry [type=" + StringUtil.getStringInLength(entryType.name(), 20) + " [" + + StringUtil.getStringInLength("" + getOpCode(), 3) + ", 0x" + + ByteUtil.shortHexString((byte) getOpCode()) + "]"; + } + + + public String toString() { + Object object = this.getDecodedDataEntry("Object"); + + if (object == null) { + return super.toString(); + } else { + return "PumpHistoryEntry [DT: " + DT + ", Object=" + object.toString() + "]"; + } + } + + + public int getOffset() { + return offset; + } + + + public void setOffset(int offset) { + this.offset = offset; + } + + + @Override + public String getEntryTypeName() { + return this.entryType.name(); + } + + + @Override + public int getDateLength() { + return this.entryType.getDateLength(); + } + + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + + if (!(o instanceof PumpHistoryEntry)) + return false; + + PumpHistoryEntry that = (PumpHistoryEntry) o; + + return entryType == that.entryType && // + this.atechDateTime == that.atechDateTime; // && // + // Objects.equals(this.decodedData, that.decodedData); + } + + + @Override + public int hashCode() { + return Objects.hash(entryType, opCode, offset); + } + + + // public boolean isAfter(LocalDateTime dateTimeIn) { + // // LOG.debug("Entry: " + this.dateTime); + // // LOG.debug("Datetime: " + dateTimeIn); + // // LOG.debug("Item after: " + this.dateTime.isAfter(dateTimeIn)); + // return this.dateTime.isAfter(dateTimeIn); + // } + + public boolean isAfter(long atechDateTime) { + if (this.atechDateTime == null) { + LOG.error("Date is null. Show object: " + toString()); + return false; // FIXME shouldn't happen + } + + return atechDateTime < this.atechDateTime; + } + + + public void setDisplayableValue(String displayableValue) { + this.displayableValue = displayableValue; + } + + + public String getDisplayableValue() { + return displayableValue; + } + + public static class Comparator implements java.util.Comparator { + + @Override + public int compare(PumpHistoryEntry o1, PumpHistoryEntry o2) { + int data = (int) (o2.atechDateTime - o1.atechDateTime); + + if (data != 0) + return data; + + return o2.getEntryType().getCode() - o1.getEntryType().getCode(); + } + } + + + public Long getPumpId() { + setPumpId(); + + return pumpId; + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntryGroup.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntryGroup.java new file mode 100644 index 0000000000..33a7c89870 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntryGroup.java @@ -0,0 +1,73 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump; + +import java.util.ArrayList; +import java.util.List; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; + +/** + * This file was taken from GGC - GNU Gluco Control (ggc.sourceforge.net), application for diabetes + * management and modified/extended for AAPS. + * + * Author: Andy {andy.rozman@gmail.com} + */ + +public enum PumpHistoryEntryGroup { + + All(R.string.medtronic_history_group_all), // + Bolus(R.string.danar_history_bolus), // + Basal(R.string.medtronic_history_group_basal), // + Prime(R.string.danar_history_prime), // + Configuration(R.string.medtronic_history_group_configuration), // + Alarm(R.string.danar_history_alarm), // + Glucose(R.string.danar_history_glucose), // + Notification(R.string.medtronic_history_group_notification), // + Statistic(R.string.medtronic_history_group_statistic), + Unknown(R.string.medtronic_history_group_unknown), // + ; + + private int resourceId; + private String translated; + + public static boolean doNotTranslate = false; + + private static List list; + + static { + list = new ArrayList<>(); + + for (PumpHistoryEntryGroup pumpHistoryEntryGroup : values()) { + //if (doNotTranslate) { + pumpHistoryEntryGroup.translated = MainApp.gs(pumpHistoryEntryGroup.resourceId); + //} + list.add(pumpHistoryEntryGroup); + } + } + + + PumpHistoryEntryGroup(int resourceId) { + this.resourceId = resourceId; + // this.translated = MainApp.gs(resourceId); + } + + + public static List getList() { + return list; + } + + + public int getResourceId() { + return resourceId; + } + + + public String getTranslated() { + return translated; + } + + + public String toString() { + return this.translated; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntryType.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntryType.java new file mode 100644 index 0000000000..dec0cb80f6 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntryType.java @@ -0,0 +1,432 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicDeviceType; +import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil; + +/** + * This file was taken from GGC - GNU Gluco Control (ggc.sourceforge.net), application for diabetes + * management and modified/extended for AAPS. + * + * Author: Andy {andy.rozman@gmail.com} + */ + +public enum PumpHistoryEntryType // implements CodeEnum +{ + + None(0, "None", PumpHistoryEntryGroup.Unknown, 1, 0, 0), + + Bolus(0x01, "Bolus", PumpHistoryEntryGroup.Bolus, 4, 5, 0), // 523+[H=8] 9/13 + + Prime(0x03, "Prime", PumpHistoryEntryGroup.Prime, 5, 5, 0), // + + /**/EventUnknown_MM522_0x05((byte) 0x05, "Unknown Event 0x05", PumpHistoryEntryGroup.Unknown, 2, 5, 28), // + NoDeliveryAlarm(0x06, "No Delivery", PumpHistoryEntryGroup.Alarm, 4, 5, 0), // + EndResultTotals(0x07, "End Result Totals", PumpHistoryEntryGroup.Statistic, 5, 2, 0), + ChangeBasalProfile_OldProfile(0x08, "Change Basal Profile (Old)", PumpHistoryEntryGroup.Basal, 2, 5, 145), + ChangeBasalProfile_NewProfile(0x09, "Change Basal Profile (New)", PumpHistoryEntryGroup.Basal, 2, 5, 145), // + /**/EventUnknown_MM512_0x10(0x10, "Unknown Event 0x10", PumpHistoryEntryGroup.Unknown), // 29, 5, 0 + CalBGForPH(0x0a, "BG Capture", PumpHistoryEntryGroup.Glucose), // + SensorAlert(0x0b, "Sensor Alert", PumpHistoryEntryGroup.Alarm, 3, 5, 0), // Ian08 + ClearAlarm(0x0c, "Clear Alarm", PumpHistoryEntryGroup.Alarm, 2, 5, 0), // 2,5,4 + + // Andy0d(0x0d, "Unknown", 2, 5, 0), + + ChangeBasalPattern(0x14, "Change Basal Pattern", PumpHistoryEntryGroup.Basal), // + TempBasalDuration(0x16, "TBR Duration", PumpHistoryEntryGroup.Basal), // + ChangeTime(0x17, "Change Time", PumpHistoryEntryGroup.Configuration), // + NewTimeSet(0x18, "New Time Set", PumpHistoryEntryGroup.Notification), // + LowBattery(0x19, "LowBattery", PumpHistoryEntryGroup.Notification), // + BatteryChange(0x1a, "Battery Change", PumpHistoryEntryGroup.Notification), // + SetAutoOff(0x1b, "Set Auto Off", PumpHistoryEntryGroup.Configuration), // + Suspend(0x1e, "Suspend", PumpHistoryEntryGroup.Basal), // + Resume(0x1f, "Resume", PumpHistoryEntryGroup.Basal), // + SelfTest(0x20, "Self Test", PumpHistoryEntryGroup.Statistic), // + Rewind(0x21, "Rewind", PumpHistoryEntryGroup.Prime), // + ClearSettings(0x22, "Clear Settings", PumpHistoryEntryGroup.Configuration), // + ChangeChildBlockEnable(0x23, "Change Child Block Enable", PumpHistoryEntryGroup.Configuration), // + ChangeMaxBolus(0x24, "Change Max Bolus", PumpHistoryEntryGroup.Configuration), // + /**/EventUnknown_MM522_0x25(0x25, "Unknown Event 0x25", PumpHistoryEntryGroup.Unknown), // 8? + EnableDisableRemote(0x26, "Enable/Disable Remote", PumpHistoryEntryGroup.Configuration, 2, 5, 14), // 2, 5, 14 V6:2,5,14 + ChangeRemoteId(0x27, "Change Remote ID", PumpHistoryEntryGroup.Configuration), // ?? + + ChangeMaxBasal(0x2c, "Change Max Basal", PumpHistoryEntryGroup.Configuration), // + BolusWizardEnabled(0x2d, "Bolus Wizard Enabled", PumpHistoryEntryGroup.Configuration), // V3 ? + /**/EventUnknown_MM512_0x2e(0x2e, "Unknown Event 0x2e", PumpHistoryEntryGroup.Unknown), // + BolusWizard512(0x2f, "Bolus Wizard (512)", PumpHistoryEntryGroup.Bolus, 2, 5, 12), // + UnabsorbedInsulin512(0x30, "Unabsorbed Insulin (512)", PumpHistoryEntryGroup.Statistic, 5, 0, 0), // FIXME + ChangeBGReminderOffset(0x31, "Change BG Reminder Offset", PumpHistoryEntryGroup.Configuration), // + ChangeAlarmClockTime(0x32, "Change Alarm Clock Time", PumpHistoryEntryGroup.Configuration), // + TempBasalRate(0x33, "TBR Rate", PumpHistoryEntryGroup.Basal, 2, 5, 1), // + LowReservoir(0x34, "Low Reservoir", PumpHistoryEntryGroup.Notification), // + ChangeAlarmClock(0x35, "Change Alarm Clock", PumpHistoryEntryGroup.Configuration), // + ChangeMeterId(0x36, "Change Meter ID", PumpHistoryEntryGroup.Configuration), // + /**/EventUnknown_MM512_0x37(0x37, "Unknown Event 0x37", PumpHistoryEntryGroup.Unknown), // V:MM512 + /**/EventUnknown_MM512_0x38(0x38, "Unknown Event 0x38", PumpHistoryEntryGroup.Unknown), // + BGReceived512(0x39, "BG Received (512)", PumpHistoryEntryGroup.Glucose), // + /**/EventUnknown_MM512_0x3a(0x3a, "Unknown Event 0x3a", PumpHistoryEntryGroup.Unknown), // + SensorStatus(0x3b, "Sensor Status", PumpHistoryEntryGroup.Glucose), // + ChangeParadigmID(0x3c, "Change Paradigm ID", PumpHistoryEntryGroup.Configuration, 2, 5, 14), // V3 ? V6: 2,5,14 ?? is it this length or just 7 + EventUnknown_MM512_0x3D(0x3d, "Unknown Event 0x3D", PumpHistoryEntryGroup.Unknown), // + EventUnknown_MM512_0x3E(0x3e, "Unknown Event 0x3E", PumpHistoryEntryGroup.Unknown), // + BGReceived(0x3f, "BG Received", PumpHistoryEntryGroup.Glucose, 2, 5, 3), // Ian3F + JournalEntryMealMarker(0x40, "Meal Marker", PumpHistoryEntryGroup.Bolus, 2, 5, 2), // is size just 7??? V6 + JournalEntryExerciseMarker(0x41, "Exercise Marker", PumpHistoryEntryGroup.Bolus, 2, 5, 1), // ?? + JournalEntryInsulinMarker(0x42, "Insulin Marker", PumpHistoryEntryGroup.Bolus, 2, 5, 0), // V6 = body(0)/was=1 + JournalEntryOtherMarker(0x43, "Other Marker", PumpHistoryEntryGroup.Bolus, 2, 5, 1), // V6 = body(1)/was=0 + EnableSensorAutoCal(0x44, "Enable Sensor AutoCal", PumpHistoryEntryGroup.Glucose), // + /**/EventUnknown_MM522_0x45(0x45, "Unknown Event 0x45", PumpHistoryEntryGroup.Unknown, 2, 5, 1), // + /**/EventUnknown_MM522_0x46(0x46, "Unknown Event 0x46", PumpHistoryEntryGroup.Unknown, 2, 5, 1), // + /**/EventUnknown_MM522_0x47(0x47, "Unknown Event 0x47", PumpHistoryEntryGroup.Unknown, 2, 5, 1), // + /**/EventUnknown_MM522_0x48(0x48, "Unknown Event 0x48", PumpHistoryEntryGroup.Unknown, 2, 5, 1), // + /**/EventUnknown_MM522_0x49(0x49, "Unknown Event 0x49", PumpHistoryEntryGroup.Unknown, 2, 5, 1), // + /**/EventUnknown_MM522_0x4a(0x4a, "Unknown Event 0x4a", PumpHistoryEntryGroup.Unknown, 2, 5, 1), // + /**/EventUnknown_MM522_0x4b(0x4b, "Unknown Event 0x4b", PumpHistoryEntryGroup.Unknown, 2, 5, 1), // + /**/EventUnknown_MM522_0x4c(0x4c, "Unknown Event 0x4c", PumpHistoryEntryGroup.Unknown, 2, 5, 1), // + /**/EventUnknown_0x4d(0x4d, "Unknown Event 0x4d", PumpHistoryEntryGroup.Unknown), // V5: 512: 7, 522: 8 ????NS + /**/EventUnknown_MM512_0x4e(0x4e, "Unknown Event 0x4e", PumpHistoryEntryGroup.Unknown), // /**/ + ChangeBolusWizardSetup512(0x4f, "Bolus Wizard Setup (512)", PumpHistoryEntryGroup.Configuration, 2, 5, 32), // + ChangeSensorSetup2(0x50, "Sensor Setup2", PumpHistoryEntryGroup.Configuration, 2, 5, 30), // Ian50 + /**/Sensor_0x51(0x51, "Unknown Event 0x51", PumpHistoryEntryGroup.Unknown), // + /**/Sensor_0x52(0x52, "Unknown Event 0x52", PumpHistoryEntryGroup.Unknown), // + ChangeSensorAlarmSilenceConfig(0x53, "Sensor Alarm Silence Config", PumpHistoryEntryGroup.Configuration, 2, 5, 1), // 8 + + /**/Sensor_0x54(0x54, "Unknown Event 0x54", PumpHistoryEntryGroup.Unknown), // Ian54 + /**/Sensor_0x55(0x55, "Unknown Event 0x55", PumpHistoryEntryGroup.Unknown), // + ChangeSensorRateOfChangeAlertSetup(0x56, "Sensor Rate Of Change Alert Setup", PumpHistoryEntryGroup.Configuration, 2, 5, 5), // 12 + ChangeBolusScrollStepSize(0x57, "Change Bolus Scroll Step Size", PumpHistoryEntryGroup.Configuration), // + + // V4 + // Andy58(0x58, "Unknown", 13, 5, 0), // TO DO is this one really there ??? + + ChangeBolusWizardSetup(0x5a, "Bolus Wizard Setup (512)", PumpHistoryEntryGroup.Configuration, 2, 5, 137), // V2: 522+[B=143] // V6 124 -> 144 + BolusWizard(0x5b, "Bolus Wizard Estimate", PumpHistoryEntryGroup.Configuration, 2, 5, 13), // 15 // + UnabsorbedInsulin(0x5c, "Unabsorbed Insulin", PumpHistoryEntryGroup.Statistic, 5, 0, 0), // head[1] -> body + SaveSettings(0x5d, "Save Settings", PumpHistoryEntryGroup.Configuration), // + ChangeVariableBolus(0x5e, "Change Variable Bolus", PumpHistoryEntryGroup.Configuration), // + ChangeAudioBolus(0x5f, "Easy Bolus Enabled", PumpHistoryEntryGroup.Configuration), // V3 ? + ChangeBGReminderEnable(0x60, "BG Reminder Enable", PumpHistoryEntryGroup.Configuration), // questionable60 + ChangeAlarmClockEnable(0x61, "Alarm Clock Enable", PumpHistoryEntryGroup.Configuration), // + ChangeTempBasalType((byte) 0x62, "Change Basal Type", PumpHistoryEntryGroup.Configuration), // ChangeTempBasalTypePumpEvent + ChangeAlarmNotifyMode(0x63, "Change Alarm Notify Mode", PumpHistoryEntryGroup.Configuration), // + ChangeTimeFormat(0x64, "Change Time Format", PumpHistoryEntryGroup.Configuration), // + ChangeReservoirWarningTime((byte) 0x65, "Change Reservoir Warning Time", PumpHistoryEntryGroup.Configuration), // + ChangeBolusReminderEnable(0x66, "Change Bolus Reminder Enable", PumpHistoryEntryGroup.Configuration, 2, 5, 2), // 9 + ChangeBolusReminderTime((byte) 0x67, "Change Bolus Reminder Time", PumpHistoryEntryGroup.Configuration, 2, 5, 2), // 9 + DeleteBolusReminderTime((byte) 0x68, "Delete Bolus Reminder Time", PumpHistoryEntryGroup.Configuration, 2, 5, 2), // 9 + BolusReminder(0x69, "Bolus Reminder", PumpHistoryEntryGroup.Configuration, 2, 5, 0), // Ian69 + DeleteAlarmClockTime(0x6a, "Delete Alarm Clock Time", PumpHistoryEntryGroup.Configuration, 2, 5, 7), // 14 + + DailyTotals515(0x6c, "Daily Totals (515)", PumpHistoryEntryGroup.Statistic, 1, 2, 35), // v4: 0,0,36. v5: 1,2,33 + DailyTotals522(0x6d, "Daily Totals (522)", PumpHistoryEntryGroup.Statistic, 1, 2, 41), // + DailyTotals523(0x6e, "Daily Totals (523)", PumpHistoryEntryGroup.Statistic, 1, 2, 49), // 1102014-03-17T00:00:00 + ChangeCarbUnits((byte) 0x6f, "Change Carb Units", PumpHistoryEntryGroup.Configuration), // + /**/EventUnknown_MM522_0x70((byte) 0x70, "Unknown Event 0x70", PumpHistoryEntryGroup.Unknown, 2, 5, 1), // + + BasalProfileStart(0x7b, "Basal Profile Start", PumpHistoryEntryGroup.Basal, 2, 5, 3), // // 722 + ChangeWatchdogEnable((byte) 0x7c, "Change Watchdog Enable", PumpHistoryEntryGroup.Configuration), // + ChangeOtherDeviceID((byte) 0x7d, "Change Other Device ID", PumpHistoryEntryGroup.Configuration, 2, 5, 30), // + + ChangeWatchdogMarriageProfile(0x81, "Change Watchdog Marriage Profile", PumpHistoryEntryGroup.Configuration, 2, 5, 5), // 12 + DeleteOtherDeviceID(0x82, "Delete Other Device ID", PumpHistoryEntryGroup.Configuration, 2, 5, 5), // + ChangeCaptureEventEnable(0x83, "Change Capture Event Enable", PumpHistoryEntryGroup.Configuration), // + + /**/EventUnknown_MM512_0x88(0x88, "Unknown Event 0x88", PumpHistoryEntryGroup.Unknown), // + + /**/EventUnknown_MM512_0x94(0x94, "Unknown Event 0x94", PumpHistoryEntryGroup.Unknown), // + // IanA8(0xA8, "xx", 10, 5, 0), // + + // Andy90(0x90, "Unknown", 7, 5, 0), + + // AndyB4(0xb4, "Unknown", 7, 5, 0), + // Andy4A(0x4a, "Unknown", 5, 5, 0), + + // head[1], + // body[49] op[0x6e] + + /**/EventUnknown_MM522_0xE8(0xe8, "Unknown Event 0xE8", PumpHistoryEntryGroup.Unknown, 2, 5, 25), // + + ReadOtherDevicesIDs(0xf0, "Read Other Devices IDs", PumpHistoryEntryGroup.Configuration), // ? + ReadCaptureEventEnabled(0xf1, "Read Capture Event Enabled", PumpHistoryEntryGroup.Configuration), // ? + ChangeCaptureEventEnable2(0xf2, "Change Capture Event Enable2", PumpHistoryEntryGroup.Configuration), // ? + ReadOtherDevicesStatus(0xf3, "Read Other Devices Status", PumpHistoryEntryGroup.Configuration), // ? + + TempBasalCombined(0xfe, "TBR", PumpHistoryEntryGroup.Basal), // + UnknownBasePacket(0xff, "Unknown Base Packet", PumpHistoryEntryGroup.Unknown); + + private static Map opCodeMap = new HashMap(); + private static PumpHistoryEntryType tddType; + + static { + for (PumpHistoryEntryType type : values()) { + opCodeMap.put(type.opCode, type); + } + + setSpecialRulesForEntryTypes(); + } + + private int opCode; + private String description; + private int headLength = 0; + private int dateLength; + // private MinimedDeviceType deviceType; + private int bodyLength; + private int totalLength; + // special rules need to be put in list from highest to lowest (e.g.: + // 523andHigher=12, 515andHigher=10 and default (set in cnstr) would be 8) + private List specialRulesHead; + private List specialRulesBody; + private boolean hasSpecialRules = false; + private PumpHistoryEntryGroup group = PumpHistoryEntryGroup.Unknown; + private static Object TDDType; + + + PumpHistoryEntryType(int opCode, String name, PumpHistoryEntryGroup group) { + this(opCode, name, group, 2, 5, 0); + } + + + PumpHistoryEntryType(int opCode, PumpHistoryEntryGroup group) { + this(opCode, null, group, 2, 5, 0); + } + + + PumpHistoryEntryType(int opCode, PumpHistoryEntryGroup group, int head, int date, int body) { + this(opCode, null, group, head, date, body); + } + + + PumpHistoryEntryType(int opCode, String name, PumpHistoryEntryGroup group, int head, int date, int body) { + this.opCode = (byte) opCode; + this.description = name; + this.headLength = head; + this.dateLength = date; + this.bodyLength = body; + this.totalLength = (head + date + body); + this.group = group; + } + + + static void setSpecialRulesForEntryTypes() { + EndResultTotals.addSpecialRuleBody(new SpecialRule(MedtronicDeviceType.Medtronic_523andHigher, 3)); + Bolus.addSpecialRuleHead(new SpecialRule(MedtronicDeviceType.Medtronic_523andHigher, 8)); + // BolusWizardChange.addSpecialRuleBody(new SpecialRule(MedtronicDeviceType.Medtronic_522andHigher, 143)); + //ChangeBolusWizardSetup.addSpecialRuleBody(new SpecialRule(MedtronicDeviceType.Medtronic_523andHigher, 137)); // V5: + // 522 + // has + // old + // form + BolusWizard.addSpecialRuleBody(new SpecialRule(MedtronicDeviceType.Medtronic_523andHigher, 15)); + BolusReminder.addSpecialRuleBody(new SpecialRule(MedtronicDeviceType.Medtronic_523andHigher, 2)); + } + + + public static PumpHistoryEntryType getByCode(int opCode) { + if (opCodeMap.containsKey(opCode)) { + return opCodeMap.get(opCode); + } else { + return PumpHistoryEntryType.UnknownBasePacket; + } + } + + + // + // private PumpHistoryEntryType(int opCode, String name, int head, int date, + // int body) + // { + // this.opCode = (byte) opCode; + // this.description = name; + // this.headLength = head; + // this.dateLength = date; + // this.bodyLength = body; + // this.totalLength = (head + date + body); + // } + // + + public static boolean isAAPSRelevantEntry(PumpHistoryEntryType entryType) { + return (entryType == PumpHistoryEntryType.Bolus || // Treatments + entryType == PumpHistoryEntryType.TempBasalRate || // + entryType == PumpHistoryEntryType.TempBasalDuration || // + + entryType == PumpHistoryEntryType.Prime || // Pump Status Change + entryType == PumpHistoryEntryType.Suspend || // + entryType == PumpHistoryEntryType.Resume || // + entryType == PumpHistoryEntryType.Rewind || // + entryType == PumpHistoryEntryType.NoDeliveryAlarm || // no delivery + entryType == PumpHistoryEntryType.BasalProfileStart || // + + entryType == PumpHistoryEntryType.ChangeTime || // Time Change + entryType == PumpHistoryEntryType.NewTimeSet || // + + entryType == PumpHistoryEntryType.ChangeBasalPattern || // Configuration + entryType == PumpHistoryEntryType.ClearSettings || // + entryType == PumpHistoryEntryType.SaveSettings || // + entryType == PumpHistoryEntryType.ChangeMaxBolus || // + entryType == PumpHistoryEntryType.ChangeMaxBasal || // + entryType == PumpHistoryEntryType.ChangeTempBasalType || // + + entryType == PumpHistoryEntryType.ChangeBasalProfile_NewProfile || // Basal profile + + entryType == PumpHistoryEntryType.DailyTotals515 || // Daily Totals + entryType == PumpHistoryEntryType.DailyTotals522 || // + entryType == PumpHistoryEntryType.DailyTotals523 || // + entryType == PumpHistoryEntryType.EndResultTotals); + } + + + public static boolean isRelevantEntry() { + return true; + } + + + public int getCode() { + return this.opCode; + } + + + public int getTotalLength() { + if (hasSpecialRules()) { + return getHeadLength() + getBodyLength() + getDateLength(); + } else { + return totalLength; + } + } + + + private boolean hasSpecialRules() { + return hasSpecialRules; + } + + + void addSpecialRuleHead(SpecialRule rule) { + if (isEmpty(specialRulesHead)) { + specialRulesHead = new ArrayList(); + } + + specialRulesHead.add(rule); + hasSpecialRules = true; + } + + + void addSpecialRuleBody(SpecialRule rule) { + if (isEmpty(specialRulesBody)) { + specialRulesBody = new ArrayList(); + } + + specialRulesBody.add(rule); + hasSpecialRules = true; + } + + + public int getOpCode() { + return opCode; + } + + + public String getDescription() { + return this.description == null ? name() : this.description; + } + + + public int getHeadLength() { + if (hasSpecialRules) { + if (isNotEmpty(specialRulesHead)) { + return determineSizeByRule(headLength, specialRulesHead); + } else { + return headLength; + } + } else { + return headLength; + } + } + + + public int getDateLength() { + return dateLength; + } + + + public int getBodyLength() { + if (hasSpecialRules) { + if (isNotEmpty(specialRulesBody)) { + return determineSizeByRule(bodyLength, specialRulesBody); + } else { + return bodyLength; + } + } else { + return bodyLength; + } + } + + + private boolean isNotEmpty(List list) { + return list != null && !list.isEmpty(); + } + + + private boolean isEmpty(List list) { + return list == null || list.isEmpty(); + } + + + // byte[] dh = { 2, 3 }; + + private int determineSizeByRule(int defaultValue, List rules) { + int size = defaultValue; + + for (SpecialRule rule : rules) { + if (MedtronicDeviceType.isSameDevice(MedtronicUtil.getMedtronicPumpModel(), rule.deviceType)) { + size = rule.size; + break; + } + } + + return size; + } + + + public PumpHistoryEntryGroup getGroup() { + + return group; + } + + enum DateFormat { + None(0), // + LongDate(5), // + ShortDate(2); + + private int length; + + + DateFormat(int length) { + this.length = length; + } + + + public int getLength() { + return length; + } + + + public void setLength(int length) { + this.length = length; + } + } + + public static class SpecialRule { + + MedtronicDeviceType deviceType; + int size; + + + public SpecialRule(MedtronicDeviceType deviceType, int size) { + this.deviceType = deviceType; + this.size = size; + } + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryResult.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryResult.java new file mode 100644 index 0000000000..5017d50059 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryResult.java @@ -0,0 +1,200 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil; + +/** + * Created by andy on 9/23/18. + */ + +/** + * History page contains data, sorted from newest to oldest (0=newest..n=oldest) + */ +public class PumpHistoryResult { + + private static final Logger LOG = LoggerFactory.getLogger(L.PUMPCOMM); + + private boolean searchFinished = false; + private PumpHistoryEntry searchEntry = null; + private Long searchDate = null; + private SearchType searchType = SearchType.None; + public List unprocessedEntries; + public List validEntries; + + + // private Object validValues; + + public PumpHistoryResult(PumpHistoryEntry searchEntry, Long targetDate) { + if (searchEntry != null) { + /* + * this.searchEntry = searchEntry; + * this.searchType = SearchType.LastEntry; + * LOG.debug("PumpHistoryResult. Search parameters: Last Entry: " + searchEntry.atechDateTime + " type=" + * + searchEntry.getEntryType().name()); + */ + this.searchDate = searchEntry.atechDateTime; + this.searchType = SearchType.Date; + if (isLogEnabled()) + LOG.debug("PumpHistoryResult. Search parameters: Date(with searchEntry): " + targetDate); + } else if (targetDate != null) { + this.searchDate = targetDate; + this.searchType = SearchType.Date; + if (isLogEnabled()) + LOG.debug("PumpHistoryResult. Search parameters: Date: " + targetDate); + } + + // this.unprocessedEntries = new ArrayList<>(); + this.validEntries = new ArrayList<>(); + } + + + public void addHistoryEntries(List entries, int page) { + this.unprocessedEntries = entries; + //LOG.debug("PumpHistoryResult. Unprocessed entries: {}", MedtronicUtil.getGsonInstance().toJson(entries)); + processEntries(); + } + + // TODO Bug #145 need to check if we had timeChange that went -1, that situation needs to be evaluated separately + public void processEntries() { + int olderEntries = 0; + + Collections.reverse(this.unprocessedEntries); + + switch (searchType) { + case None: + //LOG.debug("PE. None search"); + this.validEntries.addAll(this.unprocessedEntries); + break; + + case LastEntry: { + LOG.debug("PE. Last entry search"); + + //Collections.sort(this.unprocessedEntries, new PumpHistoryEntry.Comparator()); + + LOG.debug("PE. PumpHistoryResult. Search entry date: " + searchEntry.atechDateTime); + + Long date = searchEntry.atechDateTime; + + for (PumpHistoryEntry unprocessedEntry : unprocessedEntries) { + + if (unprocessedEntry.equals(searchEntry)) { + //LOG.debug("PE. Item found {}.", unprocessedEntry); + searchFinished = true; + break; + } + + //LOG.debug("PE. Entry {} added.", unprocessedEntry); + this.validEntries.add(unprocessedEntry); + } + } + break; + case Date: { + LOG.debug("PE. Date search: Search date: {}", this.searchDate); + + + for (PumpHistoryEntry unprocessedEntry : unprocessedEntries) { + + if (unprocessedEntry.atechDateTime == null || unprocessedEntry.atechDateTime == 0) { + LOG.debug("PE. PumpHistoryResult. Search entry date: Entry with no date: {}", unprocessedEntry); + continue; + } + + if (unprocessedEntry.isAfter(this.searchDate)) { + this.validEntries.add(unprocessedEntry); + } else { + LOG.debug("PE. PumpHistoryResult. Not after.. Unprocessed Entry [year={},entry={}]", + DateTimeUtil.getYear(unprocessedEntry.atechDateTime), unprocessedEntry); + + if (DateTimeUtil.getYear(unprocessedEntry.atechDateTime) > 2015) + olderEntries++; + } + } + + if (olderEntries > 0) { + //Collections.sort(this.validEntries, new PumpHistoryEntry.Comparator()); + + searchFinished = true; + } + } + break; + + } // switch + + //LOG.debug("PE. Valid Entries: {}", validEntries); + } + + + private void clearOrPrepareList() { + if (this.validEntries == null) + this.validEntries = new ArrayList<>(); + else + this.validEntries.clear(); + } + + + public String toString() { + return "PumpHistoryResult [unprocessed=" + (unprocessedEntries != null ? "" + unprocessedEntries.size() : "0") + // + ", valid=" + (validEntries != null ? "" + validEntries.size() : "0") + // + ", searchEntry=" + searchEntry + // + ", searchDate=" + searchDate + // + ", searchType=" + searchType + // + ", searchFinished=" + searchFinished + // + "]"; + + } + + + /** + * Return latest entry (entry with highest date time) + * + * @return + */ + public PumpHistoryEntry getLatestEntry() { + if (this.validEntries == null || this.validEntries.size() == 0) + return null; + else { + return this.validEntries.get(0); + // PumpHistoryEntry pumpHistoryEntry = this.validEntries.get(0); + // + // if (pumpHistoryEntry.getEntryType() == PumpHistoryEntryType.EndResultTotals) + // return pumpHistoryEntry; + // else + // return this.validEntries.get(1); + } + } + + + public boolean isSearchRequired() { + return searchType != SearchType.None; + } + + + public boolean isSearchFinished() { + return searchFinished; + } + + + public List getValidEntries() { + return validEntries; + } + + enum SearchType { + None, // + LastEntry, // + Date + } + + + private boolean isLogEnabled() { + return L.isEnabled(L.PUMPCOMM); + } + + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/CarelinkLongMessageBody.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/CarelinkLongMessageBody.java new file mode 100644 index 0000000000..67b773999e --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/CarelinkLongMessageBody.java @@ -0,0 +1,59 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.comm.message; + +import java.util.List; + +import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil; + +/** + * Created by geoff on 6/2/16. + */ +public class CarelinkLongMessageBody extends MessageBody { + + public static final int LONG_MESSAGE_BODY_LENGTH = 65; + protected byte[] data; + + + public CarelinkLongMessageBody() { + init(new byte[0]); + } + + + public CarelinkLongMessageBody(byte[] payload) { + init(payload); + } + + + public CarelinkLongMessageBody(List payload) { + init(MedtronicUtil.createByteArray(payload)); + } + + + @Override + public void init(byte[] rxData) { + + if (rxData != null && rxData.length == LONG_MESSAGE_BODY_LENGTH) { + data = rxData; + } else { + data = new byte[LONG_MESSAGE_BODY_LENGTH]; + if (rxData != null) { + int size = rxData.length < LONG_MESSAGE_BODY_LENGTH ? rxData.length : LONG_MESSAGE_BODY_LENGTH; + for (int i = 0; i < size; i++) { + data[i] = rxData[i]; + } + } + } + } + + + @Override + public int getLength() { + return LONG_MESSAGE_BODY_LENGTH; + } + + + @Override + public byte[] getTxData() { + return data; + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/CarelinkShortMessageBody.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/CarelinkShortMessageBody.java new file mode 100644 index 0000000000..e2ebbff085 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/CarelinkShortMessageBody.java @@ -0,0 +1,53 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.comm.message; + +/** + * Created by geoff on 5/29/16. + */ +// Andy: See comments in message body +public class CarelinkShortMessageBody extends MessageBody { + + byte[] body; + + + public CarelinkShortMessageBody() { + init(new byte[] { 0 }); + } + + + public CarelinkShortMessageBody(byte[] data) { + init(data); + } + + + @Override + public int getLength() { + return body.length; + } + + + @Override + public void init(byte[] rxData) { + body = rxData; + } + + + public byte[] getRxData() { + return body; + } + + + public void setRxData(byte[] rxData) { + init(rxData); + } + + + @Override + public byte[] getTxData() { + return body; + } + + + public void setTxData(byte[] txData) { + init(txData); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/GetHistoryPageCarelinkMessageBody.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/GetHistoryPageCarelinkMessageBody.java new file mode 100644 index 0000000000..25e8aa087c --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/GetHistoryPageCarelinkMessageBody.java @@ -0,0 +1,59 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.comm.message; + +import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; + +/** + * Created by geoff on 6/2/16. + */ +public class GetHistoryPageCarelinkMessageBody extends CarelinkLongMessageBody { + + // public boolean wasLastFrame = false; + // public int frameNumber = 0; + // public byte[] frame = new byte[] {}; + + public GetHistoryPageCarelinkMessageBody(byte[] frameData) { + init(frameData); + } + + + public GetHistoryPageCarelinkMessageBody(int pageNum) { + init(pageNum); + } + + + @Override + public int getLength() { + return data.length; + } + + + @Override + public void init(byte[] rxData) { + super.init(rxData); + } + + + public void init(int pageNum) { + byte numArgs = 1; + super.init(new byte[] { numArgs, (byte)pageNum }); + } + + + public int getFrameNumber() { + if (data.length > 0) { + return data[0] & 0x7f; + } + return 255; + } + + + public boolean wasLastFrame() { + return (data[0] & 0x80) != 0; + } + + + public byte[] getFrameData() { + return ByteUtil.substring(data, 1, data.length - 1); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/MessageBody.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/MessageBody.java new file mode 100644 index 0000000000..fa4a3817be --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/MessageBody.java @@ -0,0 +1,34 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.comm.message; + +import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; + +/** + * Created by geoff on 5/29/16. + */ +public class MessageBody { + + public int getLength() { + return 0; + } + + + public void init(byte[] rxData) { + } + + + public byte[] getTxData() { + return new byte[]{}; + } + + + public String toString() { + StringBuilder sb = new StringBuilder(getClass().getSimpleName()); + + sb.append(" [txData="); + sb.append(ByteUtil.shortHexString(getTxData())); + sb.append("]"); + + return sb.toString(); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/PacketType.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/PacketType.java new file mode 100644 index 0000000000..8d02063d66 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/PacketType.java @@ -0,0 +1,47 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.comm.message; + +import java.util.HashMap; +import java.util.Map; + +/** + * Created by geoff on 5/29/16. + * refactored into enum + */ +public enum PacketType { + Invalid(0x00), // + MySentry(0xa2), // + Meter(0xa5), // + Carelink(0xa7), // + Sensor(0xa8) // + ; + + public static Map mapByValue; + + static { + mapByValue = new HashMap<>(); + + for (PacketType packetType : values()) { + mapByValue.put(packetType.value, packetType); + } + } + + private byte value = 0; + + + PacketType(int value) { + this.value = (byte)value; + } + + + public static PacketType getByValue(short value) { + if (mapByValue.containsKey(value)) + return mapByValue.get(value); + else + return PacketType.Invalid; + } + + + public byte getValue() { + return value; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/PumpAckMessageBody.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/PumpAckMessageBody.java new file mode 100644 index 0000000000..4cfda08975 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/PumpAckMessageBody.java @@ -0,0 +1,16 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.comm.message; + +/** + * Created by geoff on 5/29/16. + */ +public class PumpAckMessageBody extends CarelinkShortMessageBody { + + public PumpAckMessageBody() { + init(new byte[] { 0 }); + } + + + public PumpAckMessageBody(byte[] bodyData) { + init(bodyData); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/PumpMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/PumpMessage.java new file mode 100644 index 0000000000..4d81d81bfe --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/PumpMessage.java @@ -0,0 +1,219 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.comm.message; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.RLMessage; +import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; +import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicCommandType; + +/** + * Created by geoff on 5/29/16. + */ +public class PumpMessage implements RLMessage { + + private static final Logger LOG = LoggerFactory.getLogger(L.PUMPCOMM); + + public PacketType packetType = PacketType.Carelink; + public byte[] address = new byte[]{0, 0, 0}; + public MedtronicCommandType commandType; + public Byte invalidCommandType; + public MessageBody messageBody = new MessageBody(); + public String error = null; + + public static final int FRAME_DATA_LENGTH = 64; + + + public PumpMessage(String error) { + this.error = error; + } + + + public PumpMessage(byte[] rxData) { + init(rxData); + } + + + public PumpMessage() { + + } + + + public boolean isErrorResponse() { + return (this.error != null); + } + + + public void init(PacketType packetType, byte[] address, MedtronicCommandType commandType, MessageBody messageBody) { + this.packetType = packetType; + this.address = address; + this.commandType = commandType; + this.messageBody = messageBody; + } + + + public void init(byte[] rxData) { + if (rxData == null) { + return; + } + if (rxData.length > 0) { + this.packetType = PacketType.getByValue(rxData[0]); + } + if (rxData.length > 3) { + this.address = ByteUtil.substring(rxData, 1, 3); + } + if (rxData.length > 4) { + this.commandType = MedtronicCommandType.getByCode(rxData[4]); + if (this.commandType == MedtronicCommandType.InvalidCommand) { + if (isLogEnabled()) + LOG.error("PumpMessage - Unknown commandType " + rxData[4]); + } + } + if (rxData.length > 5) { + this.messageBody = MedtronicCommandType.constructMessageBody(commandType, + ByteUtil.substring(rxData, 5, rxData.length - 5)); + } + } + + + @Override + public byte[] getTxData() { + byte[] rval = ByteUtil.concat(new byte[]{(byte) packetType.getValue()}, address); + rval = ByteUtil.concat(rval, commandType.getCommandCode()); + rval = ByteUtil.concat(rval, messageBody.getTxData()); + return rval; + } + + + public byte[] getContents() { + return ByteUtil.concat(new byte[]{commandType.getCommandCode()}, messageBody.getTxData()); + } + + + // rawContent = just response without code (contents-2, messageBody.txData-1); + public byte[] getRawContent() { + + if ((messageBody == null) || (messageBody.getTxData() == null) || (messageBody.getTxData().length == 0)) + return null; + + byte[] data = messageBody.getTxData(); + + int length = ByteUtil.asUINT8(data[0]); // length is not always correct so, we check whole array if we have + // data, after length + int originalLength = length; + + // check if displayed length is invalid + if (length > data.length - 1) { + return data; + } + + // check Old Way + boolean oldWay = false; + for (int i = (length + 1); i < data.length; i++) { + if (data[i] != 0x00) { + oldWay = true; + } + } + + if (oldWay) { + length = data.length - 1; + } + + byte[] arrayOut = new byte[length]; + + System.arraycopy(messageBody.getTxData(), 1, arrayOut, 0, length); + +// if (isLogEnabled()) +// LOG.debug("PumpMessage - Length: " + length + ", Original Length: " + originalLength + ", CommandType: " +// + commandType); + + return arrayOut; + } + + + public byte[] getRawContentOfFrame() { + byte[] raw = messageBody.getTxData(); + return ByteUtil.substring(raw, 1, Math.min(FRAME_DATA_LENGTH, raw.length - 1)); + } + + + public boolean isValid() { + if (packetType == null) + return false; + if (address == null) + return false; + if (commandType == null) + return false; + if (messageBody == null) + return false; + return true; + } + + + public MessageBody getMessageBody() { + return messageBody; + } + + + public String getResponseContent() { + StringBuilder sb = new StringBuilder("PumpMessage [response="); + boolean showData = true; + + if (commandType != null) { + if (commandType == MedtronicCommandType.CommandACK) { + sb.append("Acknowledged"); + showData = false; + } else if (commandType == MedtronicCommandType.CommandNAK) { + sb.append("NOT Acknowledged"); + showData = false; + } else { + sb.append(commandType.name()); + } + } else { + sb.append("Unknown_Type"); + sb.append(" (" + invalidCommandType + ")"); + } + + if (showData) { + sb.append(", rawResponse="); + sb.append(ByteUtil.shortHexString(getRawContent())); + } + + sb.append("]"); + + return sb.toString(); + } + + + public String toString() { + StringBuilder sb = new StringBuilder("PumpMessage ["); + + sb.append("packetType="); + sb.append(packetType == null ? "null" : packetType.name()); + + sb.append(", address=("); + sb.append(ByteUtil.shortHexString(this.address)); + + sb.append("), commandType="); + sb.append(commandType == null ? "null" : commandType.name()); + + if (invalidCommandType != null) { + sb.append(", invalidCommandType="); + sb.append(invalidCommandType); + } + + sb.append(", messageBody=("); + sb.append(this.messageBody == null ? "null" : this.messageBody); + + sb.append(")]"); + + return sb.toString(); + } + + + private boolean isLogEnabled() { + return L.isEnabled(L.PUMPCOMM); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/UnknownMessageBody.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/UnknownMessageBody.java new file mode 100644 index 0000000000..675a794bd8 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/UnknownMessageBody.java @@ -0,0 +1,46 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.comm.message; + +/** + * Created by geoff on 5/29/16. + */ +public class UnknownMessageBody extends MessageBody { + + public byte[] rxData; + + + public UnknownMessageBody(byte[] data) { + this.rxData = data; + } + + + @Override + public int getLength() { + return 0; + } + + + @Override + public void init(byte[] rxData) { + } + + + public byte[] getRxData() { + return rxData; + } + + + public void setRxData(byte[] rxData) { + this.rxData = rxData; + } + + + @Override + public byte[] getTxData() { + return rxData; + } + + + public void setTxData(byte[] txData) { + this.rxData = txData; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIComm.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIComm.java new file mode 100644 index 0000000000..35fa184147 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIComm.java @@ -0,0 +1,109 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.comm.ui; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkConst; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil; +import info.nightscout.androidaps.plugins.pump.medtronic.comm.MedtronicCommunicationManager; +import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicCommandType; +import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil; + +/** + * Created by andy on 6/14/18. + */ +public class MedtronicUIComm { + + private static final Logger LOG = LoggerFactory.getLogger(L.PUMP); + + MedtronicCommunicationManager mcmInstance = null; + MedtronicUIPostprocessor uiPostprocessor = new MedtronicUIPostprocessor(); + + + private MedtronicCommunicationManager getCommunicationManager() { + if (mcmInstance == null) { + mcmInstance = MedtronicCommunicationManager.getInstance(); + } + + return mcmInstance; + } + + + public synchronized MedtronicUITask executeCommand(MedtronicCommandType commandType, Object... parameters) { + + if (isLogEnabled()) + LOG.warn("Execute Command: " + commandType.name()); + + MedtronicUITask task = new MedtronicUITask(commandType, parameters); + + MedtronicUtil.setCurrentCommand(commandType); + + // new Thread(() -> { + // LOG.warn("@@@ Start Thread"); + // + // task.execute(getCommunicationManager()); + // + // LOG.warn("@@@ End Thread"); + // }); + + task.execute(getCommunicationManager()); + + // for (int i = 0; i < getMaxWaitTime(commandType); i++) { + // synchronized (task) { + // // try { + // // + // // //task.wait(1000); + // // } catch (InterruptedException e) { + // // LOG.error("executeCommand InterruptedException", e); + // // } + // + // + // SystemClock.sleep(1000); + // } + // + // if (task.isReceived()) { + // break; + // } + // } + + if (!task.isReceived() && isLogEnabled()) { + LOG.warn("Reply not received for " + commandType); + } + + task.postProcess(uiPostprocessor); + + return task; + + } + + + /** + * We return 25s as waitTime (17 for wakeUp, and addtional 8 for data retrieval) for normal commands and + * 120s for History. Real time for returning data would be arround 5s, but lets be sure. + * + * @param commandType + * @return + */ + private int getMaxWaitTime(MedtronicCommandType commandType) { + if (commandType == MedtronicCommandType.GetHistoryData) + return 120; + else + return 25; + } + + + public int getInvalidResponsesCount() { + return getCommunicationManager().getNotConnectedCount(); + } + + + public void startTunning() { + RileyLinkUtil.sendBroadcastMessage(RileyLinkConst.IPC.MSG_PUMP_tunePump); + } + + private boolean isLogEnabled() { + return L.isEnabled(L.PUMP); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIPostprocessor.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIPostprocessor.java new file mode 100644 index 0000000000..e79531d4fc --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIPostprocessor.java @@ -0,0 +1,253 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.comm.ui; + +import org.joda.time.DateTimeZone; +import org.joda.time.Duration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Date; +import java.util.Map; + +import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.BasalProfile; +import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.BatteryStatusDTO; +import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.ClockDTO; +import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.PumpSettingDTO; +import info.nightscout.androidaps.plugins.pump.medtronic.defs.BasalProfileStatus; +import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicNotificationType; +import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicUIResponseType; +import info.nightscout.androidaps.plugins.pump.medtronic.driver.MedtronicPumpStatus; +import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil; + +import static info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil.sendNotification; + +/** + * Created by andy on 6/15/18. + */ + +public class MedtronicUIPostprocessor { + + private static final Logger LOG = LoggerFactory.getLogger(L.PUMP); + + MedtronicPumpStatus pumpStatus; + + + public MedtronicUIPostprocessor() { + pumpStatus = MedtronicUtil.getPumpStatus(); + } + + + // this is mostly intended for command that return certain statuses (Remaining Insulin, ...), and + // where responses won't be directly used + public void postProcessData(MedtronicUITask uiTask) { + + switch (uiTask.commandType) { + + case SetBasalProfileSTD: { + Boolean response = (Boolean) uiTask.returnData; + + if (response) { + BasalProfile basalProfile = (BasalProfile) uiTask.getParameter(0); + + pumpStatus.basalsByHour = basalProfile.getProfilesByHour(); + } + } + break; + + case GetBasalProfileSTD: { + BasalProfile basalProfile = (BasalProfile) uiTask.returnData; + + try { + Double[] profilesByHour = basalProfile.getProfilesByHour(); + + if (profilesByHour != null) { + pumpStatus.basalsByHour = profilesByHour; + pumpStatus.basalProfileStatus = BasalProfileStatus.ProfileOK; + } else { + uiTask.responseType = MedtronicUIResponseType.Error; + uiTask.errorDescription = "No profile found."; + LOG.error("Basal Profile was NOT valid. [{}]", basalProfile.basalProfileToStringError()); + } + } catch (Exception ex) { + LOG.error("Basal Profile was returned, but was invalid. [{}]", basalProfile.basalProfileToStringError()); + uiTask.responseType = MedtronicUIResponseType.Error; + uiTask.errorDescription = "No profile found."; + } + } + break; + + case SetBolus: { + pumpStatus.lastBolusAmount = uiTask.getDoubleFromParameters(0); + pumpStatus.lastBolusTime = new Date(); + } + break; + + case GetRemainingInsulin: { + pumpStatus.reservoirRemainingUnits = (Float) uiTask.returnData; + } + break; + + case CancelTBR: { + pumpStatus.tempBasalStart = null; + pumpStatus.tempBasalAmount = null; + pumpStatus.tempBasalLength = null; + } + break; + + case GetRealTimeClock: { + processTime(uiTask); + } + break; + + case SetRealTimeClock: { + boolean response = (Boolean) uiTask.returnData; + + if (isLogEnabled()) + LOG.debug("New time was {} set.", response ? "" : "NOT"); + + if (response) { + MedtronicUtil.getPumpTime().timeDifference = 0; + } + } + break; + + + case GetBatteryStatus: { + BatteryStatusDTO batteryStatusDTO = (BatteryStatusDTO) uiTask.returnData; + + pumpStatus.batteryRemaining = batteryStatusDTO.getCalculatedPercent(pumpStatus.batteryType); + + if (batteryStatusDTO.voltage != null) { + pumpStatus.batteryVoltage = batteryStatusDTO.voltage; + } + + if (isLogEnabled()) + LOG.info("BatteryStatus: {}", batteryStatusDTO.toString()); + + } + break; + + case PumpModel: { + if (pumpStatus.medtronicDeviceType != MedtronicUtil.getMedtronicPumpModel()) { + if (isLogEnabled()) + LOG.warn("Configured pump is different then pump detected !"); + sendNotification(MedtronicNotificationType.PumpTypeNotSame); + } + } + break; + + case Settings_512: + case Settings: { + postProcessSettings(uiTask); + } + break; + + // no postprocessing + + default: + if (isLogEnabled()) + LOG.trace("Post-processing not implemented for {}.", uiTask.commandType.name()); + + } + + } + + + private void processTime(MedtronicUITask uiTask) { + + ClockDTO clockDTO = (ClockDTO) uiTask.returnData; + + Duration dur = new Duration(clockDTO.pumpTime.toDateTime(DateTimeZone.UTC), + clockDTO.localDeviceTime.toDateTime(DateTimeZone.UTC)); + + clockDTO.timeDifference = (int) dur.getStandardSeconds(); + + MedtronicUtil.setPumpTime(clockDTO); + + if (isLogEnabled()) + LOG.debug("Pump Time: " + clockDTO.localDeviceTime + ", DeviceTime=" + clockDTO.pumpTime + // + ", diff: " + dur.getStandardSeconds() + " s"); + +// if (dur.getStandardMinutes() >= 10) { +// if (isLogEnabled()) +// LOG.warn("Pump clock needs update, pump time: " + clockDTO.pumpTime.toString("HH:mm:ss") + " (difference: " +// + dur.getStandardSeconds() + " s)"); +// sendNotification(MedtronicNotificationType.PumpWrongTimeUrgent); +// } else if (dur.getStandardMinutes() >= 4) { +// if (isLogEnabled()) +// LOG.warn("Pump clock needs update, pump time: " + clockDTO.pumpTime.toString("HH:mm:ss") + " (difference: " +// + dur.getStandardSeconds() + " s)"); +// sendNotification(MedtronicNotificationType.PumpWrongTimeNormal); +// } + + } + + + private void postProcessSettings(MedtronicUITask uiTask) { + + Map settings = (Map) uiTask.returnData; + + MedtronicUtil.setSettings(settings); + + PumpSettingDTO checkValue = null; + + if (pumpStatus == null) { + if (isLogEnabled()) + LOG.debug("Pump Status: was null"); + pumpStatus = MedtronicUtil.getPumpStatus(); + if (isLogEnabled()) + LOG.debug("Pump Status: " + this.pumpStatus); + } + + this.pumpStatus.verifyConfiguration(); + + // check profile + if (!"Yes".equals(settings.get("PCFG_BASAL_PROFILES_ENABLED").value)) { + if (isLogEnabled()) + LOG.error("Basal profiles are not enabled on pump."); + sendNotification(MedtronicNotificationType.PumpBasalProfilesNotEnabled); + + } else { + checkValue = settings.get("PCFG_ACTIVE_BASAL_PROFILE"); + + if (!"STD".equals(checkValue.value)) { + if (isLogEnabled()) + LOG.error("Basal profile set on pump is incorrect (must be STD)."); + sendNotification(MedtronicNotificationType.PumpIncorrectBasalProfileSelected); + } + } + + // TBR + + checkValue = settings.get("PCFG_TEMP_BASAL_TYPE"); + + if (!"Units".equals(checkValue.value)) { + if (isLogEnabled()) + LOG.error("Wrong TBR type set on pump (must be Absolute)."); + sendNotification(MedtronicNotificationType.PumpWrongTBRTypeSet); + } + + // MAXes + + checkValue = settings.get("PCFG_MAX_BOLUS"); + + if (!MedtronicUtil.isSame(Double.parseDouble(checkValue.value), pumpStatus.maxBolus)) { + LOG.error("Wrong Max Bolus set on Pump (current={}, required={}).", checkValue.value, pumpStatus.maxBolus); + sendNotification(MedtronicNotificationType.PumpWrongMaxBolusSet, pumpStatus.maxBolus); + } + + checkValue = settings.get("PCFG_MAX_BASAL"); + + if (!MedtronicUtil.isSame(Double.parseDouble(checkValue.value), pumpStatus.maxBasal)) { + if (isLogEnabled()) + LOG.error("Wrong Max Basal set on Pump (current={}, required={}).", checkValue.value, pumpStatus.maxBasal); + sendNotification(MedtronicNotificationType.PumpWrongMaxBasalSet, pumpStatus.maxBasal); + } + + } + + private boolean isLogEnabled() { + return L.isEnabled(L.PUMP); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUITask.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUITask.java new file mode 100644 index 0000000000..d6df56bb57 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUITask.java @@ -0,0 +1,228 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.comm.ui; + +import org.joda.time.LocalDateTime; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.pump.medtronic.comm.MedtronicCommunicationManager; +import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryEntry; +import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.BasalProfile; +import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.TempBasalPair; +import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicCommandType; +import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicUIResponseType; +import info.nightscout.androidaps.plugins.pump.medtronic.defs.PumpDeviceState; +import info.nightscout.androidaps.plugins.pump.medtronic.events.EventMedtronicDeviceStatusChange; +import info.nightscout.androidaps.plugins.pump.medtronic.events.EventMedtronicPumpValuesChanged; +import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil; + +/** + * Created by andy on 6/14/18. + */ + +public class MedtronicUITask { + + private static final Logger LOG = LoggerFactory.getLogger(L.PUMP); + + public MedtronicCommandType commandType; + public Object returnData; + String errorDescription; + // boolean invalid = false; + private Object[] parameters; + // private boolean received; + MedtronicUIResponseType responseType; + + + public MedtronicUITask(MedtronicCommandType commandType) { + this.commandType = commandType; + } + + + public MedtronicUITask(MedtronicCommandType commandType, Object... parameters) { + this.commandType = commandType; + this.parameters = parameters; + } + + + public void execute(MedtronicCommunicationManager communicationManager) { + + if (isLogEnabled()) + LOG.debug("MedtronicUITask: @@@ In execute. {}", commandType); + + switch (commandType) { + case PumpModel: { + returnData = communicationManager.getPumpModel(); + } + break; + + case GetBasalProfileSTD: { + returnData = communicationManager.getBasalProfile(); + } + break; + + case GetRemainingInsulin: { + returnData = communicationManager.getRemainingInsulin(); + } + break; + + case GetRealTimeClock: { + returnData = communicationManager.getPumpTime(); + MedtronicUtil.setPumpTime(null); + } + break; + + case SetRealTimeClock: { + returnData = communicationManager.setPumpTime(); + } + break; + + case GetBatteryStatus: { + returnData = communicationManager.getRemainingBattery(); + } + break; + + case SetTemporaryBasal: { + TempBasalPair tbr = getTBRSettings(); + if (tbr != null) { + returnData = communicationManager.setTBR(tbr); + } + } + break; + + case ReadTemporaryBasal: { + returnData = communicationManager.getTemporaryBasal(); + } + break; + + + case Settings: + case Settings_512: { + returnData = communicationManager.getPumpSettings(); + } + break; + + case SetBolus: { + Double amount = getDoubleFromParameters(0); + + if (amount != null) + returnData = communicationManager.setBolus(amount); + } + break; + + case CancelTBR: { + returnData = communicationManager.cancelTBR(); + } + break; + + case SetBasalProfileSTD: + case SetBasalProfileA: { + BasalProfile profile = (BasalProfile) parameters[0]; + + returnData = communicationManager.setBasalProfile(profile); + } + break; + + case GetHistoryData: { + returnData = communicationManager.getPumpHistory((PumpHistoryEntry) parameters[0], + (LocalDateTime) parameters[1]); + } + break; + + default: { + LOG.warn("This commandType is not supported (yet) - {}.", commandType); + // invalid = true; + responseType = MedtronicUIResponseType.Invalid; + } + + } + + if (responseType == null) { + if (returnData == null) { + errorDescription = communicationManager.getErrorResponse(); + this.responseType = MedtronicUIResponseType.Error; + } else { + this.responseType = MedtronicUIResponseType.Data; + } + } + + } + + + private TempBasalPair getTBRSettings() { + return new TempBasalPair(getDoubleFromParameters(0), // + false, // + getIntegerFromParameters(1)); + } + + + private Float getFloatFromParameters(int index) { + return (Float) parameters[index]; + } + + + public Double getDoubleFromParameters(int index) { + return (Double) parameters[index]; + } + + + public Integer getIntegerFromParameters(int index) { + return (Integer) parameters[index]; + } + + + public Object getResult() { + return returnData; + } + + + public boolean isReceived() { + return (returnData != null || errorDescription != null); + } + + + void postProcess(MedtronicUIPostprocessor postprocessor) { + + if (isLogEnabled()) + LOG.debug("MedtronicUITask: @@@ In execute. {}", commandType); + + if (responseType == MedtronicUIResponseType.Data) { + postprocessor.postProcessData(this); + } + + if (responseType == MedtronicUIResponseType.Invalid) { + RxBus.INSTANCE.send(new EventMedtronicDeviceStatusChange(PumpDeviceState.ErrorWhenCommunicating, + "Unsupported command in MedtronicUITask")); + } else if (responseType == MedtronicUIResponseType.Error) { + RxBus.INSTANCE.send(new EventMedtronicDeviceStatusChange(PumpDeviceState.ErrorWhenCommunicating, + errorDescription)); + } else { + RxBus.INSTANCE.send(new EventMedtronicPumpValuesChanged()); + MedtronicUtil.getPumpStatus().setLastCommunicationToNow(); + } + + MedtronicUtil.setCurrentCommand(null); + } + + + public boolean hasData() { + return (responseType == MedtronicUIResponseType.Data); + } + + + public Object getParameter(int index) { + return parameters[index]; + } + + + private boolean isLogEnabled() { + return L.isEnabled(L.PUMP); + } + + + public MedtronicUIResponseType getResponseType() { + return this.responseType; + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.java new file mode 100644 index 0000000000..1eed440cdc --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.java @@ -0,0 +1,1543 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.data; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +import org.apache.commons.lang3.StringUtils; +import org.joda.time.LocalDateTime; +import org.joda.time.Minutes; +import org.json.JSONException; +import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Collections; +import java.util.GregorianCalendar; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.data.DetailedBolusInfo; +import info.nightscout.androidaps.db.CareportalEvent; +import info.nightscout.androidaps.db.DatabaseHelper; +import info.nightscout.androidaps.db.DbObjectBase; +import info.nightscout.androidaps.db.ExtendedBolus; +import info.nightscout.androidaps.db.Source; +import info.nightscout.androidaps.db.TDD; +import info.nightscout.androidaps.db.TemporaryBasal; +import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.general.nsclient.NSUpload; +import info.nightscout.androidaps.plugins.pump.common.bolusInfo.DetailedBolusInfoStorage; +import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil; +import info.nightscout.androidaps.plugins.pump.common.utils.StringUtil; +import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.MedtronicPumpHistoryDecoder; +import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryEntry; +import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryEntryType; +import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryResult; +import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.BasalProfile; +import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.BolusDTO; +import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.BolusWizardDTO; +import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.ClockDTO; +import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.DailyTotalsDTO; +import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.TempBasalPair; +import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.TempBasalProcessDTO; +import info.nightscout.androidaps.plugins.pump.medtronic.driver.MedtronicPumpStatus; +import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicConst; +import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil; +import info.nightscout.androidaps.plugins.treatments.Treatment; +import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; +import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.SP; + + +/** + * Created by andy on 10/12/18. + */ + +// TODO: After release we need to refactor how data is retrieved from pump, each entry in history needs to be marked, and sorting +// needs to happen according those markings, not on time stamp (since AAPS can change time anytime it drifts away). This +// needs to include not returning any records if TZ goes into -x area. To fully support this AAPS would need to take note of +// all times that time changed (TZ, DST, etc.). Data needs to be returned in batches (time_changed batches, so that we can +// handle it. It would help to assign sort_ids to items (from oldest (1) to newest (x) + +// All things marked with "TODO: Fix db code" needs to be updated in new 2.5 database code + +public class MedtronicHistoryData { + + private static final Logger LOG = LoggerFactory.getLogger(L.PUMP); + + private List allHistory = null; + private List newHistory = null; + + private Long lastHistoryRecordTime; + private boolean isInit = false; + + private Gson gson; + + private DatabaseHelper databaseHelper = MainApp.getDbHelper(); + private ClockDTO pumpTime; + + private long lastIdUsed = 0; + + /** + * Double bolus debug. We seem to have small problem with double Boluses (or sometimes also missing boluses + * from history. This flag turns on debugging for that (default is off=false)... Debuging is pretty detailed, + * so log files will get bigger. + */ + public static boolean doubleBolusDebug = false; + + + public MedtronicHistoryData() { + this.allHistory = new ArrayList<>(); + this.gson = MedtronicUtil.gsonInstance; + + if (this.gson == null) { + this.gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create(); + } + } + + + /** + * Add New History entries + * + * @param result PumpHistoryResult instance + */ + public void addNewHistory(PumpHistoryResult result) { + + List validEntries = result.getValidEntries(); + + List newEntries = new ArrayList<>(); + + for (PumpHistoryEntry validEntry : validEntries) { + + if (!this.allHistory.contains(validEntry)) { + newEntries.add(validEntry); + } + } + + this.newHistory = newEntries; + + showLogs("List of history (before filtering): [" + this.newHistory.size() + "]", gson.toJson(this.newHistory)); + } + + + private static void showLogs(String header, String data) { + + if (!isLogEnabled()) + return; + + if (header != null) { + LOG.debug(header); + } + + if (StringUtils.isNotBlank(data)) { + for (final String token : StringUtil.splitString(data, 3500)) { + LOG.debug("{}", token); + } + } else { + LOG.debug("No data."); + } + } + + + public List getAllHistory() { + return this.allHistory; + } + + + public void filterNewEntries() { + + List newHistory2 = new ArrayList<>(); + List TBRs = new ArrayList<>(); + List bolusEstimates = new ArrayList<>(); + long atechDate = DateTimeUtil.toATechDate(new GregorianCalendar()); + + //LOG.debug("Filter new entries: Before {}", newHistory); + + if (!isCollectionEmpty(newHistory)) { + + for (PumpHistoryEntry pumpHistoryEntry : newHistory) { + + if (!this.allHistory.contains(pumpHistoryEntry)) { + + PumpHistoryEntryType type = pumpHistoryEntry.getEntryType(); + + if (type == PumpHistoryEntryType.TempBasalRate || type == PumpHistoryEntryType.TempBasalDuration) { + TBRs.add(pumpHistoryEntry); + } else if (type == PumpHistoryEntryType.BolusWizard || type == PumpHistoryEntryType.BolusWizard512) { + bolusEstimates.add(pumpHistoryEntry); + newHistory2.add(pumpHistoryEntry); + } else { + + if (type == PumpHistoryEntryType.EndResultTotals) { + if (!DateTimeUtil.isSameDay(atechDate, pumpHistoryEntry.atechDateTime)) { + newHistory2.add(pumpHistoryEntry); + } + } else { + newHistory2.add(pumpHistoryEntry); + } + } + } + } + + TBRs = preProcessTBRs(TBRs); + + if (bolusEstimates.size() > 0) { + extendBolusRecords(bolusEstimates, newHistory2); + } + + newHistory2.addAll(TBRs); + + this.newHistory = newHistory2; + + sort(this.newHistory); + } + + if (isLogEnabled()) + LOG.debug("New History entries found: {}", this.newHistory.size()); + + showLogs("List of history (after filtering): [" + this.newHistory.size() + "]", gson.toJson(this.newHistory)); + + } + + private void extendBolusRecords(List bolusEstimates, List newHistory2) { + + List boluses = getFilteredItems(newHistory2, PumpHistoryEntryType.Bolus); + + for (PumpHistoryEntry bolusEstimate : bolusEstimates) { + for (PumpHistoryEntry bolus : boluses) { + if (bolusEstimate.atechDateTime.equals(bolus.atechDateTime)) { + bolus.addDecodedData("Estimate", bolusEstimate.getDecodedData().get("Object")); + } + } + } + } + + + public void finalizeNewHistoryRecords() { + + if ((newHistory == null) || (newHistory.size() == 0)) + return; + + PumpHistoryEntry pheLast = newHistory.get(0); + + // find last entry + for (PumpHistoryEntry pumpHistoryEntry : newHistory) { + if (pumpHistoryEntry.atechDateTime != null && pumpHistoryEntry.isAfter(pheLast.atechDateTime)) { + pheLast = pumpHistoryEntry; + } + } + + // add new entries + Collections.reverse(newHistory); + + for (PumpHistoryEntry pumpHistoryEntry : newHistory) { + + if (!this.allHistory.contains(pumpHistoryEntry)) { + lastIdUsed++; + pumpHistoryEntry.id = lastIdUsed; + this.allHistory.add(pumpHistoryEntry); + } + + } + + + if (pheLast == null) // if we don't have any valid record we don't do the filtering and setting + return; + + this.setLastHistoryRecordTime(pheLast.atechDateTime); + SP.putLong(MedtronicConst.Statistics.LastPumpHistoryEntry, pheLast.atechDateTime); + + LocalDateTime dt = null; + + try { + dt = DateTimeUtil.toLocalDateTime(pheLast.atechDateTime); + } catch (Exception ex) { + LOG.error("Problem decoding date from last record: {}" + pheLast); + } + + if (dt != null) { + + dt = dt.minusDays(1); // we keep 24 hours + + long dtRemove = DateTimeUtil.toATechDate(dt); + + List removeList = new ArrayList<>(); + + for (PumpHistoryEntry pumpHistoryEntry : allHistory) { + + if (!pumpHistoryEntry.isAfter(dtRemove)) { + removeList.add(pumpHistoryEntry); + } + } + + this.allHistory.removeAll(removeList); + + this.sort(this.allHistory); + + if (isLogEnabled()) + LOG.debug("All History records [afterFilterCount={}, removedItemsCount={}, newItemsCount={}]", + allHistory.size(), removeList.size(), newHistory.size()); + } else { + LOG.error("Since we couldn't determine date, we don't clean full history. This is just workaround."); + } + + this.newHistory.clear(); + } + + + public boolean hasRelevantConfigurationChanged() { + return getStateFromFilteredList( // + PumpHistoryEntryType.ChangeBasalPattern, // + PumpHistoryEntryType.ClearSettings, // + PumpHistoryEntryType.SaveSettings, // + PumpHistoryEntryType.ChangeMaxBolus, // + PumpHistoryEntryType.ChangeMaxBasal, // + PumpHistoryEntryType.ChangeTempBasalType); + } + + + private boolean isCollectionEmpty(List col) { + return (col == null || col.isEmpty()); + } + + private boolean isCollectionNotEmpty(List col) { + return (col != null && !col.isEmpty()); + } + + + public boolean isPumpSuspended() { + + List items = getDataForPumpSuspends(); + + showLogs("isPumpSuspended: ", MedtronicUtil.gsonInstance.toJson(items)); + + if (isCollectionNotEmpty(items)) { + + PumpHistoryEntryType pumpHistoryEntryType = items.get(0).getEntryType(); + + boolean isSuspended = !(pumpHistoryEntryType == PumpHistoryEntryType.TempBasalCombined || // + pumpHistoryEntryType == PumpHistoryEntryType.BasalProfileStart || // + pumpHistoryEntryType == PumpHistoryEntryType.Bolus || // + pumpHistoryEntryType == PumpHistoryEntryType.Resume || // + pumpHistoryEntryType == PumpHistoryEntryType.BatteryChange || // + pumpHistoryEntryType == PumpHistoryEntryType.Prime); + + if (isLogEnabled()) + LOG.debug("isPumpSuspended. Last entry type={}, isSuspended={}", pumpHistoryEntryType, isSuspended); + + return isSuspended; + } else + return false; + + } + + + private List getDataForPumpSuspends() { + + List newAndAll = new ArrayList<>(); + + if (isCollectionNotEmpty(this.allHistory)) { + newAndAll.addAll(this.allHistory); + } + + if (isCollectionNotEmpty(this.newHistory)) { + + for (PumpHistoryEntry pumpHistoryEntry : newHistory) { + if (!newAndAll.contains(pumpHistoryEntry)) { + newAndAll.add(pumpHistoryEntry); + } + } + } + + if (newAndAll.isEmpty()) + return newAndAll; + + this.sort(newAndAll); + + List newAndAll2 = getFilteredItems(newAndAll, // + PumpHistoryEntryType.Bolus, // + PumpHistoryEntryType.TempBasalCombined, // + PumpHistoryEntryType.Prime, // + PumpHistoryEntryType.Suspend, // + PumpHistoryEntryType.Resume, // + PumpHistoryEntryType.Rewind, // + PumpHistoryEntryType.NoDeliveryAlarm, // + PumpHistoryEntryType.BatteryChange, // + PumpHistoryEntryType.BasalProfileStart); + + newAndAll2 = filterPumpSuspend(newAndAll2, 10); + + return newAndAll2; + } + + + private List filterPumpSuspend(List newAndAll, int filterCount) { + + if (newAndAll.size() <= filterCount) { + return newAndAll; + } + + List newAndAllOut = new ArrayList<>(); + + for (int i = 0; i < filterCount; i++) { + newAndAllOut.add(newAndAll.get(i)); + } + + return newAndAllOut; + } + + + /** + * Process History Data: Boluses(Treatments), TDD, TBRs, Suspend-Resume (or other pump stops: battery, prime) + */ + public void processNewHistoryData() { + + // TODO: Fix db code + // Prime (for reseting autosense) + List primeRecords = getFilteredItems(PumpHistoryEntryType.Prime); + + if (isLogEnabled()) + LOG.debug("ProcessHistoryData: Prime [count={}, items={}]", primeRecords.size(), gson.toJson(primeRecords)); + + if (isCollectionNotEmpty(primeRecords)) { + try { + processPrime(primeRecords); + } catch (Exception ex) { + LOG.error("ProcessHistoryData: Error processing Prime entries: " + ex.getMessage(), ex); + throw ex; + } + } + + // TDD + List tdds = getFilteredItems(PumpHistoryEntryType.EndResultTotals, getTDDType()); + + if (isLogEnabled()) + LOG.debug("ProcessHistoryData: TDD [count={}, items={}]", tdds.size(), gson.toJson(tdds)); + + if (isCollectionNotEmpty(tdds)) { + try { + processTDDs(tdds); + } catch (Exception ex) { + LOG.error("ProcessHistoryData: Error processing TDD entries: " + ex.getMessage(), ex); + throw ex; + } + } + + pumpTime = MedtronicUtil.getPumpTime(); + + // Bolus + List treatments = getFilteredItems(PumpHistoryEntryType.Bolus); + + if (isLogEnabled()) + LOG.debug("ProcessHistoryData: Bolus [count={}, items={}]", treatments.size(), gson.toJson(treatments)); + + if (treatments.size() > 0) { + try { + processBolusEntries(treatments); + } catch (Exception ex) { + LOG.error("ProcessHistoryData: Error processing Bolus entries: " + ex.getMessage(), ex); + throw ex; + } + } + + // TBR + List tbrs = getFilteredItems(PumpHistoryEntryType.TempBasalCombined); + + if (isLogEnabled()) + LOG.debug("ProcessHistoryData: TBRs Processed [count={}, items={}]", tbrs.size(), gson.toJson(tbrs)); + + if (tbrs.size() > 0) { + try { + processTBREntries(tbrs); + } catch (Exception ex) { + LOG.error("ProcessHistoryData: Error processing TBR entries: " + ex.getMessage(), ex); + throw ex; + } + } + + // 'Delivery Suspend' + List suspends = null; + + try { + suspends = getSuspends(); + } catch (Exception ex) { + LOG.error("ProcessHistoryData: Error getting Suspend entries: " + ex.getMessage(), ex); + throw ex; + } + + if (isLogEnabled()) + LOG.debug("ProcessHistoryData: 'Delivery Suspend' Processed [count={}, items={}]", suspends.size(), + gson.toJson(suspends)); + + if (isCollectionNotEmpty(suspends)) { + try { + processSuspends(suspends); + } catch (Exception ex) { + LOG.error("ProcessHistoryData: Error processing Suspends entries: " + ex.getMessage(), ex); + throw ex; + } + } + } + + + private void processPrime(List primeRecords) { + + long maxAllowedTimeInPast = DateTimeUtil.getATDWithAddedMinutes(new GregorianCalendar(), -30); + + long lastPrimeRecord = 0L; + + for (PumpHistoryEntry primeRecord : primeRecords) { + + if (primeRecord.atechDateTime > maxAllowedTimeInPast) { + if (lastPrimeRecord < primeRecord.atechDateTime) { + lastPrimeRecord = primeRecord.atechDateTime; + } + } + } + + if (lastPrimeRecord != 0L) { + long lastPrimeFromAAPS = SP.getLong(MedtronicConst.Statistics.LastPrime, 0L); + + if (lastPrimeRecord != lastPrimeFromAAPS) { + uploadCareportalEvent(DateTimeUtil.toMillisFromATD(lastPrimeRecord), CareportalEvent.SITECHANGE); + + SP.putLong(MedtronicConst.Statistics.LastPrime, lastPrimeRecord); + } + } + } + + + private void uploadCareportalEvent(long date, String event) { + if (MainApp.getDbHelper().getCareportalEventFromTimestamp(date) != null) + return; + try { + JSONObject data = new JSONObject(); + String enteredBy = SP.getString("careportal_enteredby", ""); + if (!enteredBy.equals("")) data.put("enteredBy", enteredBy); + data.put("created_at", DateUtil.toISOString(date)); + data.put("eventType", event); + NSUpload.uploadCareportalEntryToNS(data); + } catch (JSONException e) { + e.printStackTrace(); + } + } + + + private void processTDDs(List tddsIn) { + + List tdds = filterTDDs(tddsIn); + + if (isLogEnabled()) + LOG.debug(getLogPrefix() + "TDDs found: {}.\n{}", tdds.size(), gson.toJson(tdds)); + + List tddsDb = databaseHelper.getTDDsForLastXDays(3); + + for (PumpHistoryEntry tdd : tdds) { + + TDD tddDbEntry = findTDD(tdd.atechDateTime, tddsDb); + + DailyTotalsDTO totalsDTO = (DailyTotalsDTO) tdd.getDecodedData().get("Object"); + + //LOG.debug("DailyTotals: {}", totalsDTO); + + if (tddDbEntry == null) { + TDD tddNew = new TDD(); + totalsDTO.setTDD(tddNew); + + if (isLogEnabled()) + LOG.debug("TDD Add: {}", tddNew); + + databaseHelper.createOrUpdateTDD(tddNew); + + } else { + + if (!totalsDTO.doesEqual(tddDbEntry)) { + totalsDTO.setTDD(tddDbEntry); + + if (isLogEnabled()) + LOG.debug("TDD Edit: {}", tddDbEntry); + + databaseHelper.createOrUpdateTDD(tddDbEntry); + } + } + } + } + + + private enum ProcessHistoryRecord { + Bolus("Bolus"), + TBR("TBR"), + Suspend("Suspend"); + + private String description; + + ProcessHistoryRecord(String desc) { + this.description = desc; + } + + public String getDescription() { + return this.description; + } + + } + + + private void processBolusEntries(List entryList) { + + long oldestTimestamp = getOldestTimestamp(entryList); + + Gson gson = MedtronicUtil.getGsonInstance(); + + List entriesFromHistory = getDatabaseEntriesByLastTimestamp(oldestTimestamp, ProcessHistoryRecord.Bolus); + + if (doubleBolusDebug) + LOG.debug("DoubleBolusDebug: List (before filter): {}, FromDb={}", gson.toJson(entryList), + gson.toJson(entriesFromHistory)); + + filterOutAlreadyAddedEntries(entryList, entriesFromHistory); + + if (entryList.isEmpty()) { + if (doubleBolusDebug) + LOG.debug("DoubleBolusDebug: EntryList was filtered out."); + return; + } + + if (doubleBolusDebug) + LOG.debug("DoubleBolusDebug: List (after filter): {}, FromDb={}", gson.toJson(entryList), + gson.toJson(entriesFromHistory)); + + if (isCollectionEmpty(entriesFromHistory)) { + for (PumpHistoryEntry treatment : entryList) { + if (isLogEnabled()) + LOG.debug("Add Bolus (no db entry): " + treatment); + if (doubleBolusDebug) + LOG.debug("DoubleBolusDebug: Add Bolus: FromDb=null, Treatment={}", treatment); + + addBolus(treatment, null); + } + } else { + for (PumpHistoryEntry treatment : entryList) { + DbObjectBase treatmentDb = findDbEntry(treatment, entriesFromHistory); + if (isLogEnabled()) + LOG.debug("Add Bolus {} - (entryFromDb={}) ", treatment, treatmentDb); + if (doubleBolusDebug) + LOG.debug("DoubleBolusDebug: Add Bolus: FromDb={}, Treatment={}", treatmentDb, treatment); + + addBolus(treatment, (Treatment) treatmentDb); + } + } + } + + + private void processTBREntries(List entryList) { + + Collections.reverse(entryList); + + TempBasalPair tbr = (TempBasalPair) entryList.get(0).getDecodedDataEntry("Object"); + + boolean readOldItem = false; + + if (tbr.isCancelTBR()) { + PumpHistoryEntry oneMoreEntryFromHistory = getOneMoreEntryFromHistory(PumpHistoryEntryType.TempBasalCombined); + + if (oneMoreEntryFromHistory != null) { + entryList.add(0, oneMoreEntryFromHistory); + readOldItem = true; + } else { + entryList.remove(0); + } + } + + long oldestTimestamp = getOldestTimestamp(entryList); + + List entriesFromHistory = getDatabaseEntriesByLastTimestamp(oldestTimestamp, ProcessHistoryRecord.TBR); + + if (isLogEnabled()) + LOG.debug(ProcessHistoryRecord.TBR.getDescription() + " List (before filter): {}, FromDb={}", gson.toJson(entryList), + gson.toJson(entriesFromHistory)); + + + TempBasalProcessDTO processDTO = null; + List processList = new ArrayList<>(); + + for (PumpHistoryEntry treatment : entryList) { + + TempBasalPair tbr2 = (TempBasalPair) treatment.getDecodedDataEntry("Object"); + + if (tbr2.isCancelTBR()) { + + if (processDTO != null) { + processDTO.itemTwo = treatment; + + if (readOldItem) { + processDTO.processOperation = TempBasalProcessDTO.Operation.Edit; + readOldItem = false; + } + } else { + LOG.error("processDTO was null - shouldn't happen. ItemTwo={}", treatment); + } + } else { + if (processDTO != null) { + processList.add(processDTO); + } + + processDTO = new TempBasalProcessDTO(); + processDTO.itemOne = treatment; + processDTO.processOperation = TempBasalProcessDTO.Operation.Add; + } + } + + if (processDTO != null) { + processList.add(processDTO); + } + + + if (isCollectionNotEmpty(processList)) { + + for (TempBasalProcessDTO tempBasalProcessDTO : processList) { + + if (tempBasalProcessDTO.processOperation == TempBasalProcessDTO.Operation.Edit) { + // edit + TemporaryBasal tempBasal = findTempBasalWithPumpId(tempBasalProcessDTO.itemOne.getPumpId(), entriesFromHistory); + + if (tempBasal != null) { + + tempBasal.durationInMinutes = tempBasalProcessDTO.getDuration(); + + databaseHelper.createOrUpdate(tempBasal); + + if (isLogEnabled()) + LOG.debug("Edit " + ProcessHistoryRecord.TBR.getDescription() + " - (entryFromDb={}) ", tempBasal); + } else { + LOG.error("TempBasal not found. Item: {}", tempBasalProcessDTO.itemOne); + } + + } else { + // add + + PumpHistoryEntry treatment = tempBasalProcessDTO.itemOne; + + TempBasalPair tbr2 = (TempBasalPair) treatment.getDecodedData().get("Object"); + tbr2.setDurationMinutes(tempBasalProcessDTO.getDuration()); + + TemporaryBasal tempBasal = findTempBasalWithPumpId(tempBasalProcessDTO.itemOne.getPumpId(), entriesFromHistory); + + if (tempBasal == null) { + DbObjectBase treatmentDb = findDbEntry(treatment, entriesFromHistory); + + if (isLogEnabled()) + LOG.debug("Add " + ProcessHistoryRecord.TBR.getDescription() + " {} - (entryFromDb={}) ", treatment, treatmentDb); + + addTBR(treatment, (TemporaryBasal) treatmentDb); + } else { + // this shouldn't happen + if (tempBasal.durationInMinutes != tempBasalProcessDTO.getDuration()) { + LOG.debug("Found entry with wrong duration (shouldn't happen)... updating"); + tempBasal.durationInMinutes = tempBasalProcessDTO.getDuration(); + } + + } + } // if + } // for + + } // collection + } + + + private TemporaryBasal findTempBasalWithPumpId(long pumpId, List entriesFromHistory) { + + for (DbObjectBase dbObjectBase : entriesFromHistory) { + TemporaryBasal tbr = (TemporaryBasal) dbObjectBase; + + if (tbr.pumpId == pumpId) { + return tbr; + } + } + + TemporaryBasal tempBasal = databaseHelper.findTempBasalByPumpId(pumpId); + return tempBasal; + } + + + /** + * findDbEntry - finds Db entries in database, while theoretically this should have same dateTime they + * don't. Entry on pump is few seconds before treatment in AAPS, and on manual boluses on pump there + * is no treatment at all. For now we look fro tratment that was from 0s - 1m59s within pump entry. + * + * @param treatment Pump Entry + * @param entriesFromHistory entries from history + * @return DbObject from AAPS (if found) + */ + private DbObjectBase findDbEntry(PumpHistoryEntry treatment, List entriesFromHistory) { + + long proposedTime = DateTimeUtil.toMillisFromATD(treatment.atechDateTime); + + //proposedTime += (this.pumpTime.timeDifference * 1000); + + if (doubleBolusDebug) + LOG.debug("DoubleBolusDebug: findDbEntry Treatment={}, FromDb={}", treatment, gson.toJson(entriesFromHistory)); + + if (entriesFromHistory.size() == 0) { + if (doubleBolusDebug) + LOG.debug("DoubleBolusDebug: findDbEntry Treatment={}, FromDb=null", treatment); + return null; + } else if (entriesFromHistory.size() == 1) { + if (doubleBolusDebug) + LOG.debug("DoubleBolusDebug: findDbEntry Treatment={}, FromDb={}. Type=SingleEntry", treatment, entriesFromHistory.get(0)); + + // TODO: Fix db code + // if difference is bigger than 2 minutes we discard entry + long maxMillisAllowed = DateTimeUtil.getMillisFromATDWithAddedMinutes(treatment.atechDateTime, 2); + + if (doubleBolusDebug) + LOG.debug("DoubleBolusDebug: findDbEntry maxMillisAllowed={}, AtechDateTime={} (add 2 minutes). ", maxMillisAllowed, treatment.atechDateTime); + + if (entriesFromHistory.get(0).getDate() > maxMillisAllowed) { + if (doubleBolusDebug) + LOG.debug("DoubleBolusDebug: findDbEntry entry filtered out, returning null. "); + return null; + } + + return entriesFromHistory.get(0); + } + + for (int min = 0; min < 2; min += 1) { + + for (int sec = 0; sec <= 50; sec += 10) { + + if (min == 1 && sec == 50) { + sec = 59; + } + + int diff = (sec * 1000); + + List outList = new ArrayList<>(); + + for (DbObjectBase treatment1 : entriesFromHistory) { + + if ((treatment1.getDate() > proposedTime - diff) && (treatment1.getDate() < proposedTime + diff)) { + outList.add(treatment1); + } + } + + if (outList.size() == 1) { + if (doubleBolusDebug) + LOG.debug("DoubleBolusDebug: findDbEntry Treatment={}, FromDb={}. Type=EntrySelected, AtTimeMin={}, AtTimeSec={}", treatment, entriesFromHistory.get(0), min, sec); + + return outList.get(0); + } + + if (min == 0 && sec == 10 && outList.size() > 1) { + if (isLogEnabled()) + LOG.error("Too many entries (with too small diff): (timeDiff=[min={},sec={}],count={},list={})", + min, sec, outList.size(), gson.toJson(outList)); + if (doubleBolusDebug) + LOG.debug("DoubleBolusDebug: findDbEntry Error - Too many entries (with too small diff): (timeDiff=[min={},sec={}],count={},list={})", + min, sec, outList.size(), gson.toJson(outList)); + } + } + } + + return null; + } + + + private List getDatabaseEntriesByLastTimestamp(long startTimestamp, ProcessHistoryRecord processHistoryRecord) { + if (processHistoryRecord == ProcessHistoryRecord.Bolus) { + return TreatmentsPlugin.getPlugin().getTreatmentsFromHistoryAfterTimestamp(startTimestamp); + } else { + return databaseHelper.getTemporaryBasalsDataFromTime(startTimestamp, true); + } + } + + + private void filterOutAlreadyAddedEntries(List entryList, List treatmentsFromHistory) { + + if (isCollectionEmpty(treatmentsFromHistory)) + return; + + List removeTreatmentsFromHistory = new ArrayList<>(); + + for (DbObjectBase treatment : treatmentsFromHistory) { + + if (treatment.getPumpId() != 0) { + + PumpHistoryEntry selectedBolus = null; + + for (PumpHistoryEntry bolus : entryList) { + if (bolus.getPumpId() == treatment.getPumpId()) { + selectedBolus = bolus; + break; + } + } + + if (selectedBolus != null) { + entryList.remove(selectedBolus); + + removeTreatmentsFromHistory.add(treatment); + } + } + } + + treatmentsFromHistory.removeAll(removeTreatmentsFromHistory); + } + + + private void addBolus(PumpHistoryEntry bolus, Treatment treatment) { + + BolusDTO bolusDTO = (BolusDTO) bolus.getDecodedData().get("Object"); + + if (treatment == null) { + if (doubleBolusDebug) + LOG.debug("DoubleBolusDebug: addBolus(tretament==null): Bolus={}", bolusDTO); + + switch (bolusDTO.getBolusType()) { + case Normal: { + DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); + + detailedBolusInfo.date = tryToGetByLocalTime(bolus.atechDateTime); + detailedBolusInfo.source = Source.PUMP; + detailedBolusInfo.pumpId = bolus.getPumpId(); + detailedBolusInfo.insulin = bolusDTO.getDeliveredAmount(); + + addCarbsFromEstimate(detailedBolusInfo, bolus); + + if (doubleBolusDebug) + LOG.debug("DoubleBolusDebug: addBolus(tretament==null): DetailedBolusInfo={}", detailedBolusInfo); + + boolean newRecord = TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, false); + + bolus.setLinkedObject(detailedBolusInfo); + + if (isLogEnabled()) + LOG.debug("addBolus - [date={},pumpId={}, insulin={}, newRecord={}]", detailedBolusInfo.date, + detailedBolusInfo.pumpId, detailedBolusInfo.insulin, newRecord); + } + break; + + case Audio: + case Extended: { + ExtendedBolus extendedBolus = new ExtendedBolus(); + extendedBolus.date = tryToGetByLocalTime(bolus.atechDateTime); + extendedBolus.source = Source.PUMP; + extendedBolus.insulin = bolusDTO.getDeliveredAmount(); + extendedBolus.pumpId = bolus.getPumpId(); + extendedBolus.isValid = true; + extendedBolus.durationInMinutes = bolusDTO.getDuration(); + + bolus.setLinkedObject(extendedBolus); + + if (doubleBolusDebug) + LOG.debug("DoubleBolusDebug: addBolus(tretament==null): ExtendedBolus={}", extendedBolus); + + TreatmentsPlugin.getPlugin().addToHistoryExtendedBolus(extendedBolus); + + if (isLogEnabled()) + LOG.debug("addBolus - Extended [date={},pumpId={}, insulin={}, duration={}]", extendedBolus.date, + extendedBolus.pumpId, extendedBolus.insulin, extendedBolus.durationInMinutes); + + } + break; + } + + } else { + + DetailedBolusInfo detailedBolusInfo = DetailedBolusInfoStorage.INSTANCE.findDetailedBolusInfo(treatment.date, bolusDTO.getDeliveredAmount()); + + if (doubleBolusDebug) + LOG.debug("DoubleBolusDebug: addBolus(tretament={}): Bolus={}, DetailedBolusInfo={}", treatment, bolusDTO, detailedBolusInfo); + + if (detailedBolusInfo == null) { + detailedBolusInfo = new DetailedBolusInfo(); + + if (doubleBolusDebug) + LOG.debug("DoubleBolusDebug: detailedBolusInfoCouldNotBeRetrived !"); + } + + detailedBolusInfo.date = treatment.date; + detailedBolusInfo.source = Source.PUMP; + detailedBolusInfo.pumpId = bolus.getPumpId(); + detailedBolusInfo.insulin = bolusDTO.getDeliveredAmount(); + detailedBolusInfo.carbs = treatment.carbs; + + addCarbsFromEstimate(detailedBolusInfo, bolus); + + if (doubleBolusDebug) + LOG.debug("DoubleBolusDebug: addBolus(tretament!=null): DetailedBolusInfo(New)={}", detailedBolusInfo); + + boolean newRecord = TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, false); + + bolus.setLinkedObject(detailedBolusInfo); + + if (isLogEnabled()) + LOG.debug("editBolus - [date={},pumpId={}, insulin={}, newRecord={}]", detailedBolusInfo.date, + detailedBolusInfo.pumpId, detailedBolusInfo.insulin, newRecord); + + } + } + + + private void addCarbsFromEstimate(DetailedBolusInfo detailedBolusInfo, PumpHistoryEntry bolus) { + + if (bolus.containsDecodedData("Estimate")) { + + BolusWizardDTO bolusWizard = (BolusWizardDTO) bolus.getDecodedData().get("Estimate"); + + if (doubleBolusDebug) + LOG.debug("DoubleBolusDebug: addCarbsFromEstimate: Bolus={}, BolusWizardDTO={}", bolus, bolusWizard); + + detailedBolusInfo.carbs = bolusWizard.carbs; + } + } + + + private void addTBR(PumpHistoryEntry treatment, TemporaryBasal temporaryBasalDbInput) { + + TempBasalPair tbr = (TempBasalPair) treatment.getDecodedData().get("Object"); + + TemporaryBasal temporaryBasalDb = temporaryBasalDbInput; + String operation = "editTBR"; + + if (temporaryBasalDb == null) { + temporaryBasalDb = new TemporaryBasal(); + temporaryBasalDb.date = tryToGetByLocalTime(treatment.atechDateTime); + + operation = "addTBR"; + } + + temporaryBasalDb.source = Source.PUMP; + temporaryBasalDb.pumpId = treatment.getPumpId(); + temporaryBasalDb.durationInMinutes = tbr.getDurationMinutes(); + temporaryBasalDb.absoluteRate = tbr.getInsulinRate(); + temporaryBasalDb.isAbsolute = !tbr.isPercent(); + + treatment.setLinkedObject(temporaryBasalDb); + + databaseHelper.createOrUpdate(temporaryBasalDb); + + if (isLogEnabled()) + LOG.debug(operation + " - [date={},pumpId={}, rate={} {}, duration={}]", // + temporaryBasalDb.date, // + temporaryBasalDb.pumpId, // + temporaryBasalDb.isAbsolute ? String.format(Locale.ENGLISH, "%.2f", temporaryBasalDb.absoluteRate) : + String.format(Locale.ENGLISH, "%d", temporaryBasalDb.percentRate), // + temporaryBasalDb.isAbsolute ? "U/h" : "%", // + temporaryBasalDb.durationInMinutes); + } + + + private void processSuspends(List tempBasalProcessList) { + + for (TempBasalProcessDTO tempBasalProcess : tempBasalProcessList) { + + TemporaryBasal tempBasal = databaseHelper.findTempBasalByPumpId(tempBasalProcess.itemOne.getPumpId()); + + if (tempBasal == null) { + // add + tempBasal = new TemporaryBasal(); + tempBasal.date = tryToGetByLocalTime(tempBasalProcess.itemOne.atechDateTime); + + tempBasal.source = Source.PUMP; + tempBasal.pumpId = tempBasalProcess.itemOne.getPumpId(); + tempBasal.durationInMinutes = tempBasalProcess.getDuration(); + tempBasal.absoluteRate = 0.0d; + tempBasal.isAbsolute = true; + + tempBasalProcess.itemOne.setLinkedObject(tempBasal); + tempBasalProcess.itemTwo.setLinkedObject(tempBasal); + + databaseHelper.createOrUpdate(tempBasal); + + } + } + + } + + + private List getSuspends() { + + List outList = new ArrayList<>(); + + // suspend/resume + outList.addAll(getSuspendResumeRecords()); + // no_delivery/prime & rewind/prime + outList.addAll(getNoDeliveryRewindPrimeRecords()); + + return outList; + } + + private List getSuspendResumeRecords() { + List filteredItems = getFilteredItems(this.newHistory, // + PumpHistoryEntryType.Suspend, // + PumpHistoryEntryType.Resume); + + List outList = new ArrayList<>(); + + if (filteredItems.size() > 0) { + + List filtered2Items = new ArrayList<>(); + + if ((filteredItems.size() % 2 == 0) && (filteredItems.get(0).getEntryType() == PumpHistoryEntryType.Resume)) { + // full resume suspends (S R S R) + filtered2Items.addAll(filteredItems); + } else if ((filteredItems.size() % 2 == 0) && (filteredItems.get(0).getEntryType() == PumpHistoryEntryType.Suspend)) { + // not full suspends, need to retrive one more record and discard first one (R S R S) -> ([S] R S R [xS]) + filteredItems.remove(0); + + PumpHistoryEntry oneMoreEntryFromHistory = getOneMoreEntryFromHistory(PumpHistoryEntryType.Suspend); + if (oneMoreEntryFromHistory != null) { + filteredItems.add(oneMoreEntryFromHistory); + } else { + filteredItems.remove(filteredItems.size() - 1); // remove last (unpaired R) + } + + filtered2Items.addAll(filteredItems); + } else { + if (filteredItems.get(0).getEntryType() == PumpHistoryEntryType.Resume) { + // get one more from history (R S R) -> ([S] R S R) + + PumpHistoryEntry oneMoreEntryFromHistory = getOneMoreEntryFromHistory(PumpHistoryEntryType.Suspend); + if (oneMoreEntryFromHistory != null) { + filteredItems.add(oneMoreEntryFromHistory); + } else { + filteredItems.remove(filteredItems.size() - 1); // remove last (unpaired R) + } + + filtered2Items.addAll(filteredItems); + } else { + // remove last and have paired items + filteredItems.remove(0); + filtered2Items.addAll(filteredItems); + } + } + + if (filtered2Items.size() > 0) { + sort(filtered2Items); + Collections.reverse(filtered2Items); + + for (int i = 0; i < filtered2Items.size(); i += 2) { + TempBasalProcessDTO dto = new TempBasalProcessDTO(); + + dto.itemOne = filtered2Items.get(i); + dto.itemTwo = filtered2Items.get(i + 1); + + dto.processOperation = TempBasalProcessDTO.Operation.Add; + + outList.add(dto); + } + } + } + + return outList; + } + + + private List getNoDeliveryRewindPrimeRecords() { + List primeItems = getFilteredItems(this.newHistory, // + PumpHistoryEntryType.Prime); + + List outList = new ArrayList<>(); + + if (primeItems.size() == 0) + return outList; + + List filteredItems = getFilteredItems(this.newHistory, // + PumpHistoryEntryType.Prime, + PumpHistoryEntryType.Rewind, + PumpHistoryEntryType.NoDeliveryAlarm, + PumpHistoryEntryType.Bolus, + PumpHistoryEntryType.TempBasalCombined + ); + + List tempData = new ArrayList<>(); + boolean startedItems = false; + boolean finishedItems = false; + + for (PumpHistoryEntry filteredItem : filteredItems) { + if (filteredItem.getEntryType() == PumpHistoryEntryType.Prime) { + startedItems = true; + } + + if (startedItems) { + if (filteredItem.getEntryType() == PumpHistoryEntryType.Bolus || + filteredItem.getEntryType() == PumpHistoryEntryType.TempBasalCombined) { + finishedItems = true; + break; + } + + tempData.add(filteredItem); + } + } + + + if (!finishedItems) { + + List filteredItemsOld = getFilteredItems(this.allHistory, // + PumpHistoryEntryType.Rewind, + PumpHistoryEntryType.NoDeliveryAlarm, + PumpHistoryEntryType.Bolus, + PumpHistoryEntryType.TempBasalCombined + ); + + for (PumpHistoryEntry filteredItem : filteredItemsOld) { + + if (filteredItem.getEntryType() == PumpHistoryEntryType.Bolus || + filteredItem.getEntryType() == PumpHistoryEntryType.TempBasalCombined) { + finishedItems = true; + break; + } + + tempData.add(filteredItem); + } + } + + + if (!finishedItems) { + showLogs("NoDeliveryRewindPrimeRecords: Not finished Items: ", gson.toJson(tempData)); + return outList; + } + + showLogs("NoDeliveryRewindPrimeRecords: Records to evaluate: ", gson.toJson(tempData)); + + List items = getFilteredItems(tempData, // + PumpHistoryEntryType.Prime + ); + + + TempBasalProcessDTO processDTO = new TempBasalProcessDTO(); + + processDTO.itemTwo = items.get(0); + + items = getFilteredItems(tempData, // + PumpHistoryEntryType.NoDeliveryAlarm + ); + + if (items.size() > 0) { + + processDTO.itemOne = items.get(items.size() - 1); + processDTO.processOperation = TempBasalProcessDTO.Operation.Add; + + outList.add(processDTO); + return outList; + } + + + items = getFilteredItems(tempData, // + PumpHistoryEntryType.Rewind + ); + + if (items.size() > 0) { + + processDTO.itemOne = items.get(0); + processDTO.processOperation = TempBasalProcessDTO.Operation.Add; + + outList.add(processDTO); + return outList; + } + + return outList; + } + + + private PumpHistoryEntry getOneMoreEntryFromHistory(PumpHistoryEntryType entryType) { + List filteredItems = getFilteredItems(this.allHistory, entryType); + + return filteredItems.size() == 0 ? null : filteredItems.get(0); + } + + + private List filterTDDs(List tdds) { + List tddsOut = new ArrayList<>(); + + for (PumpHistoryEntry tdd : tdds) { + if (tdd.getEntryType() != PumpHistoryEntryType.EndResultTotals) { + tddsOut.add(tdd); + } + } + + return tddsOut.size() == 0 ? tdds : tddsOut; + } + + + private TDD findTDD(long atechDateTime, List tddsDb) { + + for (TDD tdd : tddsDb) { + + if (DateTimeUtil.isSameDayATDAndMillis(atechDateTime, tdd.date)) { + return tdd; + } + } + + return null; + } + + private long tryToGetByLocalTime(long atechDateTime) { + return DateTimeUtil.toMillisFromATD(atechDateTime); + } + + + private int getOldestDateDifference(List treatments) { + + long dt = Long.MAX_VALUE; + PumpHistoryEntry currentTreatment = null; + + if (isCollectionEmpty(treatments)) { + return 8; // default return of 6 (5 for diif on history reading + 2 for max allowed difference) minutes + } + + for (PumpHistoryEntry treatment : treatments) { + + if (treatment.atechDateTime < dt) { + dt = treatment.atechDateTime; + currentTreatment = treatment; + } + } + + LocalDateTime oldestEntryTime = null; + + try { + + oldestEntryTime = DateTimeUtil.toLocalDateTime(dt); + oldestEntryTime = oldestEntryTime.minusMinutes(3); + +// if (this.pumpTime.timeDifference < 0) { +// oldestEntryTime = oldestEntryTime.plusSeconds(this.pumpTime.timeDifference); +// } + } catch (Exception ex) { + LOG.error("Problem decoding date from last record: {}" + currentTreatment); + return 8; // default return of 6 minutes + } + + LocalDateTime now = new LocalDateTime(); + + Minutes minutes = Minutes.minutesBetween(oldestEntryTime, now); + + // returns oldest time in history, with calculated time difference between pump and phone, minus 5 minutes + if (isLogEnabled()) + LOG.debug("Oldest entry: {}, pumpTimeDifference={}, newDt={}, currentTime={}, differenceMin={}", dt, + this.pumpTime.timeDifference, oldestEntryTime, now, minutes.getMinutes()); + + return minutes.getMinutes(); + } + + + private long getOldestTimestamp(List treatments) { + + long dt = Long.MAX_VALUE; + PumpHistoryEntry currentTreatment = null; + + for (PumpHistoryEntry treatment : treatments) { + + if (treatment.atechDateTime < dt) { + dt = treatment.atechDateTime; + currentTreatment = treatment; + } + } + + if (doubleBolusDebug) + LOG.debug("DoubleBolusDebug: getOldestTimestamp. Oldest entry found: time={}, object={}", dt, currentTreatment); + + try { + + GregorianCalendar oldestEntryTime = DateTimeUtil.toGregorianCalendar(dt); + if (doubleBolusDebug) + LOG.debug("DoubleBolusDebug: getOldestTimestamp. oldestEntryTime: {}", DateTimeUtil.toString(oldestEntryTime)); + oldestEntryTime.add(Calendar.MINUTE, -2); + + if (doubleBolusDebug) + LOG.debug("DoubleBolusDebug: getOldestTimestamp. oldestEntryTime (-2m): {}, timeInMillis={}", DateTimeUtil.toString(oldestEntryTime), oldestEntryTime.getTimeInMillis()); + + return oldestEntryTime.getTimeInMillis(); + + } catch (Exception ex) { + LOG.error("Problem decoding date from last record: {}", currentTreatment); + return 8; // default return of 6 minutes + } + + } + + + private PumpHistoryEntryType getTDDType() { + + if (MedtronicUtil.getMedtronicPumpModel() == null) { + return PumpHistoryEntryType.EndResultTotals; + } + + switch (MedtronicUtil.getMedtronicPumpModel()) { + + case Medtronic_515: + case Medtronic_715: + return PumpHistoryEntryType.DailyTotals515; + + case Medtronic_522: + case Medtronic_722: + return PumpHistoryEntryType.DailyTotals522; + + case Medtronic_523_Revel: + case Medtronic_723_Revel: + case Medtronic_554_Veo: + case Medtronic_754_Veo: + return PumpHistoryEntryType.DailyTotals523; + + default: { + return PumpHistoryEntryType.EndResultTotals; + } + } + } + + + public boolean hasBasalProfileChanged() { + + List filteredItems = getFilteredItems(PumpHistoryEntryType.ChangeBasalProfile_NewProfile); + + if (isLogEnabled()) + LOG.debug("hasBasalProfileChanged. Items: " + gson.toJson(filteredItems)); + + return (filteredItems.size() > 0); + } + + + public void processLastBasalProfileChange(MedtronicPumpStatus mdtPumpStatus) { + + List filteredItems = getFilteredItems(PumpHistoryEntryType.ChangeBasalProfile_NewProfile); + + if (isLogEnabled()) + LOG.debug("processLastBasalProfileChange. Items: " + filteredItems); + + PumpHistoryEntry newProfile = null; + Long lastDate = null; + + if (filteredItems.size() == 1) { + newProfile = filteredItems.get(0); + } else if (filteredItems.size() > 1) { + + for (PumpHistoryEntry filteredItem : filteredItems) { + + if (lastDate == null || lastDate < filteredItem.atechDateTime) { + newProfile = filteredItem; + lastDate = newProfile.atechDateTime; + } + } + } + + if (newProfile != null) { + if (isLogEnabled()) + LOG.debug("processLastBasalProfileChange. item found, setting new basalProfileLocally: " + newProfile); + BasalProfile basalProfile = (BasalProfile) newProfile.getDecodedData().get("Object"); + + mdtPumpStatus.basalsByHour = basalProfile.getProfilesByHour(); + } + } + + + public boolean hasPumpTimeChanged() { + return getStateFromFilteredList(PumpHistoryEntryType.NewTimeSet, // + PumpHistoryEntryType.ChangeTime); + } + + + public void setLastHistoryRecordTime(Long lastHistoryRecordTime) { + + // this.previousLastHistoryRecordTime = this.lastHistoryRecordTime; + this.lastHistoryRecordTime = lastHistoryRecordTime; + } + + + public void setIsInInit(boolean init) { + this.isInit = init; + } + + + // HELPER METHODS + + private void sort(List list) { + Collections.sort(list, new PumpHistoryEntry.Comparator()); + } + + + private List preProcessTBRs(List TBRs_Input) { + List TBRs = new ArrayList<>(); + + Map map = new HashMap<>(); + + for (PumpHistoryEntry pumpHistoryEntry : TBRs_Input) { + if (map.containsKey(pumpHistoryEntry.DT)) { + MedtronicPumpHistoryDecoder.decodeTempBasal(map.get(pumpHistoryEntry.DT), pumpHistoryEntry); + pumpHistoryEntry.setEntryType(PumpHistoryEntryType.TempBasalCombined); + TBRs.add(pumpHistoryEntry); + map.remove(pumpHistoryEntry.DT); + } else { + map.put(pumpHistoryEntry.DT, pumpHistoryEntry); + } + } + + return TBRs; + } + + + private List getFilteredItems(PumpHistoryEntryType... entryTypes) { + return getFilteredItems(this.newHistory, entryTypes); + } + + + private boolean getStateFromFilteredList(PumpHistoryEntryType... entryTypes) { + if (isInit) { + return false; + } else { + List filteredItems = getFilteredItems(entryTypes); + + if (isLogEnabled()) + LOG.debug("Items: " + filteredItems); + + return filteredItems.size() > 0; + } + } + + + private List getFilteredItems(List inList, PumpHistoryEntryType... entryTypes) { + + // LOG.debug("InList: " + inList.size()); + List outList = new ArrayList<>(); + + if (inList != null && inList.size() > 0) { + for (PumpHistoryEntry pumpHistoryEntry : inList) { + + if (!isEmpty(entryTypes)) { + for (PumpHistoryEntryType pumpHistoryEntryType : entryTypes) { + + if (pumpHistoryEntry.getEntryType() == pumpHistoryEntryType) { + outList.add(pumpHistoryEntry); + break; + } + } + } else { + outList.add(pumpHistoryEntry); + } + } + } + + // LOG.debug("OutList: " + outList.size()); + + return outList; + } + + + private boolean isEmpty(PumpHistoryEntryType... entryTypes) { + return (entryTypes == null || (entryTypes.length == 1 && entryTypes[0] == null)); + } + + + private String getLogPrefix() { + return "MedtronicHistoryData::"; + } + + private static boolean isLogEnabled() { + return (L.isEnabled(L.PUMP)); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfile.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfile.java new file mode 100644 index 0000000000..25facaf9e6 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfile.java @@ -0,0 +1,387 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.data.dto; + +import com.google.gson.annotations.Expose; + +import org.joda.time.Instant; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; + +import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.pump.common.defs.PumpType; +import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; +import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil; + +/** + * Created by geoff on 6/1/15. + *

+ * There are three basal profiles stored on the pump. (722 only?) They are all parsed the same, the user just has 3 to + * choose from: Standard, A, and B + *

+ * The byte array is 48 times three byte entries long, plus a zero? If the profile is completely empty, it should have + * one entry: [0,0,0x3F]. The first entry of [0,0,0] marks the end of the used entries. + *

+ * Each entry is assumed to span from the specified start time to the start time of the next entry, or to midnight if + * there are no more entries. + *

+ * Individual entries are of the form [r,z,m] where r is the rate (in 0.025 U increments) z is zero (?) m is the start + * time-of-day for the basal rate period (in 30 minute increments) + */ +public class BasalProfile { + + private static final Logger LOG = LoggerFactory.getLogger(L.PUMPCOMM); + + public static final int MAX_RAW_DATA_SIZE = (48 * 3) + 1; + private static final boolean DEBUG_BASALPROFILE = false; + @Expose + private byte[] mRawData; // store as byte array to make transport (via parcel) easier + private List listEntries; + + + public BasalProfile() { + init(); + } + + + public BasalProfile(byte[] data) { + setRawData(data); + } + + + // this asUINT8 should be combined with Record.asUINT8, and placed in a new util class. + protected static int readUnsignedByte(byte b) { + return (b < 0) ? b + 256 : b; + } + + + public void init() { + mRawData = new byte[MAX_RAW_DATA_SIZE]; + mRawData[0] = 0; + mRawData[1] = 0; + mRawData[2] = 0x3f; + } + + + public boolean setRawData(byte[] data) { + if (data == null) { + LOG.error("setRawData: buffer is null!"); + return false; + } + + // if we have just one entry through all day it looks like just length 1 + if (data.length == 1) { + data = MedtronicUtil.createByteArray(data[0], (byte) 0, (byte) 0); + } + + if (data.length == MAX_RAW_DATA_SIZE) { + mRawData = data; + } else { + int len = Math.min(MAX_RAW_DATA_SIZE, data.length); + mRawData = new byte[MAX_RAW_DATA_SIZE]; + System.arraycopy(data, 0, mRawData, 0, len); + } + + return true; + } + + + public boolean setRawDataFromHistory(byte[] data) { + if (data == null) { + LOG.error("setRawData: buffer is null!"); + return false; + } + + mRawData = new byte[MAX_RAW_DATA_SIZE]; + int item = 0; + + for (int i = 0; i < data.length - 2; i += 3) { + + if ((data[i] == 0) && (data[i + 1] == 0) && (data[i + 2] == 0)) { + mRawData[i] = 0; + mRawData[i + 1] = 0; + mRawData[i + 2] = 0; + } + + mRawData[i] = data[i + 1]; + mRawData[i + 1] = data[i + 2]; + mRawData[i + 2] = data[i]; + } + + return true; + } + + + public void dumpBasalProfile() { + LOG.debug("Basal Profile entries:"); + List entries = getEntries(); + for (int i = 0; i < entries.size(); i++) { + BasalProfileEntry entry = entries.get(i); + String startString = entry.startTime.toString("HH:mm"); + // this doesn't work + LOG.debug(String.format("Entry %d, rate=%.3f (0x%02X), start=%s (0x%02X)", i + 1, entry.rate, + entry.rate_raw, startString, entry.startTime_raw)); + + } + } + + + public String getBasalProfileAsString() { + StringBuffer sb = new StringBuffer("Basal Profile entries:\n"); + List entries = getEntries(); + for (int i = 0; i < entries.size(); i++) { + BasalProfileEntry entry = entries.get(i); + String startString = entry.startTime.toString("HH:mm"); + + sb.append(String.format("Entry %d, rate=%.3f, start=%s\n", i + 1, entry.rate, startString)); + } + + return sb.toString(); + } + + public String basalProfileToStringError() { + return "Basal Profile [rawData=" + ByteUtil.shortHexString(this.getRawData()) + "]"; + } + + + public String basalProfileToString() { + StringBuffer sb = new StringBuffer("Basal Profile ["); + List entries = getEntries(); + for (int i = 0; i < entries.size(); i++) { + BasalProfileEntry entry = entries.get(i); + String startString = entry.startTime.toString("HH:mm"); + + sb.append(String.format("%s=%.3f, ", startString, entry.rate)); + } + + sb.append("]"); + + return sb.toString(); + } + + + // TODO: this function must be expanded to include changes in which profile is in use. + // and changes to the profiles themselves. + public BasalProfileEntry getEntryForTime(Instant when) { + BasalProfileEntry rval = new BasalProfileEntry(); + List entries = getEntries(); + if (entries.size() == 0) { + LOG.warn(String.format("getEntryForTime(%s): table is empty", + when.toDateTime().toLocalTime().toString("HH:mm"))); + return rval; + } + // Log.w(TAG,"Assuming first entry"); + rval = entries.get(0); + if (entries.size() == 1) { + LOG.debug("getEntryForTime: Only one entry in profile"); + return rval; + } + + int localMillis = when.toDateTime().toLocalTime().getMillisOfDay(); + boolean done = false; + int i = 1; + while (!done) { + BasalProfileEntry entry = entries.get(i); + if (DEBUG_BASALPROFILE) { + LOG.debug(String.format("Comparing 'now'=%s to entry 'start time'=%s", when.toDateTime().toLocalTime() + .toString("HH:mm"), entry.startTime.toString("HH:mm"))); + } + if (localMillis >= entry.startTime.getMillisOfDay()) { + rval = entry; + if (DEBUG_BASALPROFILE) + LOG.debug("Accepted Entry"); + } else { + // entry at i has later start time, keep older entry + if (DEBUG_BASALPROFILE) + LOG.debug("Rejected Entry"); + done = true; + } + i++; + if (i >= entries.size()) { + done = true; + } + } + if (DEBUG_BASALPROFILE) { + LOG.debug(String.format("getEntryForTime(%s): Returning entry: rate=%.3f (%d), start=%s (%d)", when + .toDateTime().toLocalTime().toString("HH:mm"), rval.rate, rval.rate_raw, + rval.startTime.toString("HH:mm"), rval.startTime_raw)); + } + return rval; + } + + + public List getEntries() { + List entries = new ArrayList<>(); + + if (mRawData == null || mRawData[2] == 0x3f) { + LOG.warn("Raw Data is empty."); + return entries; // an empty list + } + boolean done = false; + int r, st; + + for (int i = 0; i < mRawData.length - 2; i += 3) { + + if ((mRawData[i] == 0) && (mRawData[i + 1] == 0) && (mRawData[i + 2] == 0)) + break; + + if ((mRawData[i] == 0) && (mRawData[i + 1] == 0) && (mRawData[i + 2] == 0x3f)) + break; + + r = MedtronicUtil.makeUnsignedShort(mRawData[i + 1], mRawData[i]); // readUnsignedByte(mRawData[i]); + st = readUnsignedByte(mRawData[i + 2]); + + try { + entries.add(new BasalProfileEntry(r, st)); + } catch (Exception ex) { + LOG.error("Error decoding basal profile from bytes: {}", ByteUtil.shortHexString(mRawData)); + throw ex; + } + + } + + return entries; + } + + + /** + * This is used to prepare new profile + * + * @param entry + */ + public void addEntry(BasalProfileEntry entry) { + if (listEntries == null) + listEntries = new ArrayList<>(); + + listEntries.add(entry); + } + + + public void generateRawDataFromEntries() { + + List outData = new ArrayList<>(); + + for (BasalProfileEntry profileEntry : listEntries) { + + byte[] strokes = MedtronicUtil.getBasalStrokes(profileEntry.rate, true); + + outData.add(profileEntry.rate_raw[0]); + outData.add(profileEntry.rate_raw[1]); + outData.add(profileEntry.startTime_raw); + } + + this.setRawData(MedtronicUtil.createByteArray(outData)); + + // return this.mRawData; + } + + + public Double[] getProfilesByHour() { + + List entries = null; + + try { + entries = getEntries(); + } catch (Exception ex) { + LOG.error("============================================================================="); + LOG.error(" Error generating entries. Ex.: " + ex, ex); + LOG.error(" rawBasalValues: " + ByteUtil.shortHexString(this.getRawData())); + LOG.error("============================================================================="); + + //FabricUtil.createEvent("MedtronicBasalProfileGetByHourError", null); + } + + if (entries == null || entries.size() == 0) { + Double[] basalByHour = new Double[24]; + + for (int i = 0; i < 24; i++) { + basalByHour[i] = 0.0d; + } + + return basalByHour; + } + + Double[] basalByHour = new Double[24]; + + PumpType pumpType = MedtronicUtil.getPumpStatus().pumpType; + + for (int i = 0; i < entries.size(); i++) { + BasalProfileEntry current = entries.get(i); + + int currentTime = (current.startTime_raw % 2 == 0) ? current.startTime_raw : current.startTime_raw - 1; + + currentTime = (currentTime * 30) / 60; + + int lastHour = 0; + if ((i + 1) == entries.size()) { + lastHour = 24; + } else { + BasalProfileEntry basalProfileEntry = entries.get(i + 1); + + int rawTime = (basalProfileEntry.startTime_raw % 2 == 0) ? basalProfileEntry.startTime_raw + : basalProfileEntry.startTime_raw - 1; + + lastHour = (rawTime * 30) / 60; + } + + // System.out.println("Current time: " + currentTime + " Next Time: " + lastHour); + + for (int j = currentTime; j < lastHour; j++) { + if (pumpType == null) + basalByHour[j] = current.rate; + else + basalByHour[j] = pumpType.determineCorrectBasalSize(current.rate); + } + } + + return basalByHour; + } + + + public static String getProfilesByHourToString(Double[] data) { + + StringBuilder stringBuilder = new StringBuilder(); + + for (Double value : data) { + stringBuilder.append(String.format("%.3f", value)); + stringBuilder.append(" "); + } + + return stringBuilder.toString(); + + } + + + public byte[] getRawData() { + return this.mRawData; + } + + + public String toString() { + return basalProfileToString(); + } + + + private boolean isLogEnabled() { + return L.isEnabled(L.PUMPCOMM); + } + + public boolean verify() { + + try { + getEntries(); + } catch (Exception ex) { + return false; + } + + Double[] profilesByHour = getProfilesByHour(); + + for (Double aDouble : profilesByHour) { + if (aDouble > 35.0d) + return false; + } + + return true; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfileEntry.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfileEntry.java new file mode 100644 index 0000000000..9768ad2fc8 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfileEntry.java @@ -0,0 +1,89 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.data.dto; + +import org.joda.time.LocalTime; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil; + +/** + * Created by geoff on 6/1/15. + * This is a helper class for BasalProfile, only used for interpreting the contents of BasalProfile + * - fixed rate is not one bit but two + */ +public class BasalProfileEntry { + + private static final Logger LOG = LoggerFactory.getLogger(L.PUMPCOMM); + + public byte[] rate_raw; + public double rate; + public byte startTime_raw; + public LocalTime startTime; // Just a "time of day" + + + public BasalProfileEntry() { + rate = -9.999E6; + rate_raw = MedtronicUtil.getByteArrayFromUnsignedShort(0xFF, true); + startTime = new LocalTime(0); + startTime_raw = (byte)0xFF; + } + + + public BasalProfileEntry(double rate, int hour, int minutes) { + byte[] data = MedtronicUtil.getBasalStrokes(rate, true); + + rate_raw = new byte[2]; + rate_raw[0] = data[1]; + rate_raw[1] = data[0]; + + int interval = hour * 2; + + if (minutes == 30) { + interval++; + } + + startTime_raw = (byte)interval; + startTime = new LocalTime(hour, minutes == 30 ? 30 : 0); + } + + + public BasalProfileEntry(int rateStrokes, int startTimeInterval) { + // rateByte is insulin delivery rate, U/hr, in 0.025 U increments + // startTimeByte is time-of-day, in 30 minute increments + rate_raw = MedtronicUtil.getByteArrayFromUnsignedShort(rateStrokes, true); + rate = rateStrokes * 0.025; + startTime_raw = (byte)startTimeInterval; + + try { + startTime = new LocalTime(startTimeInterval / 2, (startTimeInterval % 2) * 30); + } catch (Exception ex) { + LOG.error( + "Error creating BasalProfileEntry: startTimeInterval={}, startTime_raw={}, hours={}, rateStrokes={}", + startTimeInterval, startTime_raw, startTimeInterval / 2, rateStrokes); + throw ex; + } + + } + + + public BasalProfileEntry(byte rateByte, int startTimeByte) { + // rateByte is insulin delivery rate, U/hr, in 0.025 U increments + // startTimeByte is time-of-day, in 30 minute increments + rate_raw = MedtronicUtil.getByteArrayFromUnsignedShort(rateByte, true); + rate = rateByte * 0.025; + startTime_raw = (byte)startTimeByte; + startTime = new LocalTime(startTimeByte / 2, (startTimeByte % 2) * 30); + } + + + public void setStartTime(LocalTime localTime) { + this.startTime = localTime; + } + + + public void setRate(double rate) { + this.rate = rate; + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BatteryStatusDTO.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BatteryStatusDTO.java new file mode 100644 index 0000000000..93b5eb10cb --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BatteryStatusDTO.java @@ -0,0 +1,57 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.data.dto; + +import com.google.gson.annotations.Expose; + +import java.util.Locale; + +import info.nightscout.androidaps.plugins.pump.medtronic.defs.BatteryType; + +/** + * Created by andy on 6/14/18. + */ + +public class BatteryStatusDTO { + + @Expose + public BatteryStatusType batteryStatusType; + @Expose + public Double voltage; + + public boolean extendedDataReceived = false; + + + public int getCalculatedPercent(BatteryType batteryType) { + if (voltage == null || batteryType == BatteryType.None) { + return (batteryStatusType == BatteryStatusType.Low || batteryStatusType == BatteryStatusType.Unknown) ? 18 : 70; + } + + double percent = (voltage - batteryType.lowVoltage) / (batteryType.highVoltage - batteryType.lowVoltage); + + int percentInt = (int) (percent * 100.0d); + + if (percentInt<0) + percentInt = 1; + + if (percentInt > 100) + percentInt = 100; + + return percentInt; + } + + + public String toString() { + return String.format(Locale.ENGLISH, "BatteryStatusDTO [voltage=%.2f, alkaline=%d, lithium=%d, niZn={}]", + voltage == null ? 0.0f : voltage, + getCalculatedPercent(BatteryType.Alkaline), + getCalculatedPercent(BatteryType.Lithium), + getCalculatedPercent(BatteryType.NiZn)); + } + + + public enum BatteryStatusType { + Normal, + Low, + Unknown + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BolusDTO.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BolusDTO.java new file mode 100644 index 0000000000..8574bd831a --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BolusDTO.java @@ -0,0 +1,160 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.data.dto; + +import com.google.gson.annotations.Expose; + +import info.nightscout.androidaps.plugins.pump.common.utils.StringUtil; +import info.nightscout.androidaps.plugins.pump.medtronic.defs.PumpBolusType; + +/** + * Application: GGC - GNU Gluco Control + * Plug-in: Pump Tool (support for Pump devices) + *

+ * See AUTHORS for copyright information. + *

+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later + * version. + *

+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + *

+ * You should have received a copy of the GNU General Public License along with this program; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + *

+ * Filename: BolusDTO Description: Bolus DTO + *

+ * Author: Andy {andy@atech-software.com} + */ + +public class BolusDTO extends PumpTimeStampedRecord { + + @Expose + private Double requestedAmount; + @Expose + private Double deliveredAmount; + @Expose + private Double immediateAmount; // when Multiwave this is used + @Expose + private Integer duration; + @Expose + private PumpBolusType bolusType; + private Double insulinOnBoard; + + + public BolusDTO() { + // this.decimalPrecission = 2; + } + + + public Double getRequestedAmount() { + return requestedAmount; + } + + + public void setRequestedAmount(Double requestedAmount) { + this.requestedAmount = requestedAmount; + } + + + public Double getDeliveredAmount() { + return deliveredAmount; + } + + + public void setDeliveredAmount(Double deliveredAmount) { + this.deliveredAmount = deliveredAmount; + } + + + public Integer getDuration() { + return duration; + } + + + public void setDuration(Integer duration) { + this.duration = duration; + } + + + public PumpBolusType getBolusType() { + return bolusType; + } + + + public void setBolusType(PumpBolusType bolusType) { + this.bolusType = bolusType; + } + + + public Double getInsulinOnBoard() { + return insulinOnBoard; + } + + + public void setInsulinOnBoard(Double insulinOnBoard) { + this.insulinOnBoard = insulinOnBoard; + } + + + private String getDurationString() { + int minutes = this.duration; + + int h = minutes / 60; + + minutes -= (h * 60); + + return StringUtil.getLeadingZero(h, 2) + ":" + StringUtil.getLeadingZero(minutes, 2); + } + + + public String getValue() { + if ((bolusType == PumpBolusType.Normal) || (bolusType == PumpBolusType.Audio)) { + return getFormattedDecimal(this.deliveredAmount); + } else if (bolusType == PumpBolusType.Extended) { + return String.format("AMOUNT_SQUARE=%s;DURATION=%s", getFormattedDecimal(this.deliveredAmount), + getDurationString()); + } else { + return String.format("AMOUNT=%s;AMOUNT_SQUARE=%s;DURATION=%s", getFormattedDecimal(this.immediateAmount), + getFormattedDecimal(this.deliveredAmount), getDurationString()); + } + } + + + public String getDisplayableValue() { + String value = getValue(); + + value = value.replace("AMOUNT_SQUARE=", "Amount Square: "); + value = value.replace("AMOUNT=", "Amount: "); + value = value.replace("DURATION=", "Duration: "); + + return value; + } + + + public Double getImmediateAmount() { + return immediateAmount; + } + + + public void setImmediateAmount(Double immediateAmount) { + this.immediateAmount = immediateAmount; + } + + + public String getFormattedDecimal(double value) { + return StringUtil.getFormatedValueUS(value, 2); + } + + + public String getBolusKey() { + return "Bolus_" + this.bolusType.name(); + + } + + + @Override + public String toString() { + return "BolusDTO [type=" + bolusType.name() + ", " + getValue() + "]"; + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BolusWizardDTO.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BolusWizardDTO.java new file mode 100644 index 0000000000..5d9710a5c5 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BolusWizardDTO.java @@ -0,0 +1,48 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.data.dto; + +import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil; + +/** + * Created by andy on 18.05.15. + */ +public class BolusWizardDTO extends PumpTimeStampedRecord { + + // bloodGlucose and bgTarets are in mg/dL + public Integer bloodGlucose = 0; // mg/dL + public Integer carbs = 0; + public String chUnit = "g"; + + public Float carbRatio = 0.0f; + public Float insulinSensitivity = 0.0f; + public Integer bgTargetLow = 0; + public Integer bgTargetHigh = 0; + public Float bolusTotal = 0.0f; + public Float correctionEstimate = 0.0f; + public Float foodEstimate = 0.0f; + public Float unabsorbedInsulin = 0.0f; + + + // public LocalDateTime localDateTime; + // public long atechDateTime; + + public String getValue() { + return String.format("BG=%d;CH=%d;CH_UNIT=%s;CH_INS_RATIO=%5.3f;BG_INS_RATIO=%5.3f;" + + "BG_TARGET_LOW=%d;BG_TARGET_HIGH=%d;BOLUS_TOTAL=%5.3f;" + + "BOLUS_CORRECTION=%5.3f;BOLUS_FOOD=%5.3f;UNABSORBED_INSULIN=%5.3f", // + bloodGlucose, carbs, chUnit, carbRatio, insulinSensitivity, bgTargetLow, // + bgTargetHigh, bolusTotal, correctionEstimate, foodEstimate, unabsorbedInsulin); + } + + public String getDisplayableValue() { + return String.format("Bg=%d, CH=%d %s, Ch/Ins Ratio=%5.3f, Bg/Ins Ratio=%5.3f;" + + "Bg Target(L/H)=%d/%d, Bolus: Total=%5.3f, " + + "Correction=%5.3f, Food=%5.3f, IOB=%5.3f", // + bloodGlucose, carbs, chUnit, carbRatio, insulinSensitivity, bgTargetLow, // + bgTargetHigh, bolusTotal, correctionEstimate, foodEstimate, unabsorbedInsulin); + } + + + public String toString() { + return "BolusWizardDTO [dateTime=" + DateTimeUtil.toString(atechDateTime) + ", " + getValue() + "]"; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/ClockDTO.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/ClockDTO.java new file mode 100644 index 0000000000..1623e03ff5 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/ClockDTO.java @@ -0,0 +1,16 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.data.dto; + +import org.joda.time.LocalDateTime; + +/** + * Created by andy on 2/27/19. + */ + +public class ClockDTO { + + public LocalDateTime localDeviceTime; + + public LocalDateTime pumpTime; + + public int timeDifference; // s (pump -> local) +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/DailyTotalsDTO.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/DailyTotalsDTO.java new file mode 100644 index 0000000000..495bce8a31 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/DailyTotalsDTO.java @@ -0,0 +1,257 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.data.dto; + +import com.google.common.base.MoreObjects; +import com.google.gson.annotations.Expose; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import info.nightscout.androidaps.db.TDD; +import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; +import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil; +import info.nightscout.androidaps.plugins.pump.common.utils.StringUtil; +import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryEntry; + +/** + * Created by andy on 11/3/18. + */ + +/** + * NOTE: Decoding is only done for insulin part, everything else is pretty must left undecoded. + */ + +public class DailyTotalsDTO { + + private static final Logger LOG = LoggerFactory.getLogger(L.PUMPCOMM); + + // bg avg, bg low hi, number Bgs, + // Sen Avg, Sen Lo/Hi, Sens Cal/Data = 0/0, + // Insulin=19.8[8,9], Basal[10,11], Bolus[13,14], Carbs, + // Bolus=1.7, Fodd, Corr, Manual=1.7, + // Num bOlus=1, food/corr, Food+corr, manual bolus=1 + private Double bgAvg; + private Double bgLow; + private Double bgHigh; + private Integer bgCount; + + private Double sensorAvg; + private Double sensorMin; + private Double sensorMax; + private Integer sensorCalcCount; + private Integer sensorDataCount; + + @Expose + private Double insulinTotal = 0.0d; + @Expose + private Double insulinBasal = 0.0d; + @Expose + private Double insulinBolus = 0.0d; + private Double insulinCarbs; + + private Double bolusTotal; + private Double bolusFood; + private Double bolusFoodAndCorr; + private Double bolusCorrection; + private Double bolusManual; + + private Integer bolusCount; + private Integer bolusCountFoodOrCorr; + // Integer bolusCountCorr; + Integer bolusCountFoodAndCorr; + Integer bolusCountManual; + private Integer bolusCountFood; + private Integer bolusCountCorr; + + PumpHistoryEntry entry; + + + public DailyTotalsDTO(PumpHistoryEntry entry) { + this.entry = entry; + + switch (entry.getEntryType()) { + case EndResultTotals: + decodeEndResultsTotals(entry); + break; + + case DailyTotals515: + decodeDailyTotals515(entry.getBody()); + break; + + case DailyTotals522: + decodeDailyTotals522(entry.getBody()); + break; + + case DailyTotals523: + decodeDailyTotals523(entry.getBody()); + break; + + default: + break; + } + + setDisplayable(); + } + + + private void setDisplayable() { + + if (this.insulinBasal == null) { + this.entry.setDisplayableValue("Total Insulin: " + StringUtil.getFormatedValueUS(this.insulinTotal, 2)); + } else { + this.entry.setDisplayableValue("Basal Insulin: " + StringUtil.getFormatedValueUS(this.insulinBasal, 2) + + ", Total Insulin: " + StringUtil.getFormatedValueUS(this.insulinTotal, 2)); + } + + } + + + private void decodeEndResultsTotals(PumpHistoryEntry entry) { + double totals = ByteUtil.toInt((int) entry.getHead()[0], (int) entry.getHead()[1], (int) entry.getHead()[2], + (int) entry.getHead()[3], ByteUtil.BitConversion.BIG_ENDIAN) * 0.025d; + + this.insulinTotal = totals; + + entry.addDecodedData("Totals", totals); + } + + + private void testDecode(byte[] data) { + + // Daily + + byte[] body = data; // entry.getBody(); + //System.out.println("Totals 522"); + + for (int i = 0; i < body.length - 2; i++) { + + int j = ByteUtil.toInt(body[i], body[i + 1]); + int k = ByteUtil.toInt(body[i], body[i + 1], body[i + 2]); + + int j1 = ByteUtil.toInt(body[i + 1], body[i]); + int k1 = ByteUtil.toInt(body[i + 2], body[i + 1], body[i]); + + System.out.println(String.format( + "index: %d, number=%d, del/40=%.3f, del/10=%.3f, singular=%d, sing_hex=%s", i, j, j / 40.0d, j / 10.0d, + body[i], ByteUtil.shortHexString(body[i]))); + + System.out.println(String.format(" number[k,j1,k1]=%d / %d /%d, del/40=%.3f, del/40=%.3f, del/40=%.3f", + k, j1, k1, k / 40.0d, j1 / 40.0d, k1 / 40.0d)); + + } + } + + + private void decodeDailyTotals515(byte[] data) { + // LOG.debug("Can't decode DailyTotals515: Body={}", ByteUtil.getHex(data)); + + this.insulinTotal = ByteUtil.toInt(data[8], data[9]) / 40.0d; + this.insulinBasal = ByteUtil.toInt(data[10], data[11]) / 40.0d; + this.insulinBolus = ByteUtil.toInt(data[13], data[14]) / 40.0d; + + // Delivery Stats: BG AVG: Bg Low/Hi=none,Number BGs=0 + // Delivery Stats: INSULIN: Basal 22.30, Bolus=4.20, Catbs = 0g (26.5) + // Delivery Stats: BOLUS: Food=0.00, Corr=0.00, Manual=4.20 + // Delivery Stats: NUM BOLUS: Food/Corr=0,Food+Corr=0, Manual=3 + + //LOG.debug("515: {}", toString()); + } + + + private void decodeDailyTotals522(byte[] data) { + + this.insulinTotal = ByteUtil.toInt(data[8], data[9]) / 40.0d; + this.insulinBasal = ByteUtil.toInt(data[10], data[11]) / 40.0d; + this.insulinBolus = ByteUtil.toInt(data[13], data[14]) / 40.0d; + + this.bolusTotal = ByteUtil.toInt(data[17], data[18], data[19]) / 40.0d; + this.bolusFood = ByteUtil.toInt(data[21], data[22]) / 40.0d; + this.bolusCorrection = ByteUtil.toInt(data[23], data[24], data[25]) / 40.0d; + this.bolusManual = ByteUtil.toInt(data[26], data[27], data[28]) / 40.0d; + + bolusCount = ByteUtil.asUINT8(data[30]); + bolusCountFoodOrCorr = ByteUtil.asUINT8(data[31]); + bolusCountFoodAndCorr = ByteUtil.asUINT8(data[32]); + bolusCountManual = ByteUtil.asUINT8(data[33]); + + // bg avg, bg low hi, number Bgs, + // Sen Avg, Sen Lo/Hi, Sens Cal/Data = 0/0, + // Insulin=19.8[8,9], Basal[10,11], Bolus[13,14], Carbs, + // Bolus=1.7[18,19], Fodd, Corr, Manual=1.7[27,28], + // Num bOlus=1, food/corr, Food+corr, manual bolus=1 + + //LOG.debug("522: {}", toString()); + } + + + private void decodeDailyTotals523(byte[] data) { + + this.insulinTotal = ByteUtil.toInt(data[8], data[9]) / 40.0d; + this.insulinBasal = ByteUtil.toInt(data[10], data[11]) / 40.0d; + this.insulinBolus = ByteUtil.toInt(data[13], data[14]) / 40.0d; + this.insulinCarbs = ByteUtil.toInt(data[16], data[17]) * 1.0d; + + this.bolusFood = ByteUtil.toInt(data[18], data[19]) / 40.0d; + this.bolusCorrection = ByteUtil.toInt(data[20], data[21]) / 40.0d; + this.bolusFoodAndCorr = ByteUtil.toInt(data[22], data[23]) / 40.0d; + this.bolusManual = ByteUtil.toInt(data[24], data[25]) / 40.0d; + + this.bolusCountFood = ByteUtil.asUINT8(data[26]); + this.bolusCountCorr = ByteUtil.asUINT8(data[27]); + this.bolusCountFoodAndCorr = ByteUtil.asUINT8(data[28]); + this.bolusCountManual = ByteUtil.asUINT8(data[29]); // + + + // Delivery Stats: Carbs=11, Total Insulin=3.850, Basal=2.000 + // Delivery Stats: Basal 52,Bolus 1.850, Bolus=48%o + // Delivery Stats: Food only=0.9, Food only#=1, Corr only = 0.0 + // Delivery Stats: #Corr_only=0,Food+Corr=0.000, #Food+Corr=0 + // Delivery Stats: Manual = 0.95, #Manual=5 + + //LOG.debug("523: {}", toString()); + } + + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) // + .add("bgAvg", bgAvg) // + .add("bgLow", bgLow) // + .add("bgHigh", bgHigh) // + .add("bgCount", bgCount) // + .add("sensorAvg", sensorAvg) // + .add("sensorMin", sensorMin) // + .add("sensorMax", sensorMax) // + .add("sensorCalcCount", sensorCalcCount) // + .add("sensorDataCount", sensorDataCount) // + .add("insulinTotal", insulinTotal) // + .add("insulinBasal", insulinBasal) // + .add("insulinBolus", insulinBolus) // + .add("insulinCarbs", insulinCarbs) // + .add("bolusTotal", bolusTotal) // + .add("bolusFood", bolusFood) // + .add("bolusCorrection", bolusCorrection) // + .add("bolusManual", bolusManual) // + .add("bolusCount", bolusCount) // + .add("bolusCountFoodOrCorr", bolusCountFoodOrCorr) // + .add("bolusCountFoodAndCorr", bolusCountFoodAndCorr) // + .add("bolusCountFood", bolusCountFood) // + .add("bolusCountCorr", bolusCountCorr) // + .add("bolusCountManual", bolusCountManual) // + .omitNullValues() // + .toString(); + } + + + public void setTDD(TDD tdd) { + tdd.date = DateTimeUtil.toMillisFromATD(this.entry.atechDateTime); + tdd.basal = insulinBasal; + tdd.bolus = insulinBolus; + tdd.total = insulinTotal; + } + + + public boolean doesEqual(TDD tdd) { + return tdd.total == this.insulinTotal && tdd.bolus == this.insulinBolus && tdd.basal == this.insulinBasal; + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/PumpSettingDTO.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/PumpSettingDTO.java new file mode 100644 index 0000000000..1868064d8b --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/PumpSettingDTO.java @@ -0,0 +1,29 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.data.dto; + +import info.nightscout.androidaps.plugins.pump.medtronic.defs.PumpConfigurationGroup; + +/** + * Created by andy on 6/6/18. + */ + +public class PumpSettingDTO { + + public String key; + public String value; + + PumpConfigurationGroup configurationGroup; + + + public PumpSettingDTO(String key, String value, PumpConfigurationGroup configurationGroup) { + this.key = key; + this.value = value; + this.configurationGroup = configurationGroup; + } + + + @Override + public String toString() { + return "PumpSettingDTO [key=" + key + ",value=" + value + ",group=" + configurationGroup.name() + "]"; + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/PumpTimeStampedRecord.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/PumpTimeStampedRecord.java new file mode 100644 index 0000000000..84ad0914b3 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/PumpTimeStampedRecord.java @@ -0,0 +1,28 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.data.dto; + +import info.nightscout.androidaps.plugins.pump.common.utils.StringUtil; + +/** + * Created by andy on 6/2/18. + */ +public class PumpTimeStampedRecord { + + protected int decimalPrecission = 2; + public long atechDateTime; + + + public long getAtechDateTime() { + return this.atechDateTime; + } + + + public void setAtechDateTime(long atechDateTime) { + this.atechDateTime = atechDateTime; + } + + + public String getFormattedDecimal(double value) { + return StringUtil.getFormatedValueUS(value, this.decimalPrecission); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/TempBasalPair.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/TempBasalPair.java new file mode 100644 index 0000000000..7a17767243 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/TempBasalPair.java @@ -0,0 +1,175 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.data.dto; + +import com.google.gson.annotations.Expose; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; +import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil; + +/** + * Created by geoff on 5/29/15. + *

+ * Just need a class to keep the pair together, for parcel transport. + */ +public class TempBasalPair { + + private static final Logger LOG = LoggerFactory.getLogger(L.PUMPCOMM); + + @Expose + private double insulinRate = 0.0d; + @Expose + private int durationMinutes = 0; + @Expose + private boolean isPercent = false; + + + public TempBasalPair() { + } + + + /** + * This constructor is for use with PumpHistoryDecoder + * + * @param rateByte + * @param startTimeByte + * @param isPercent + */ + public TempBasalPair(byte rateByte, int startTimeByte, boolean isPercent) { + int rateInt = ByteUtil.asUINT8(rateByte); + + if (isPercent) + this.insulinRate = rateByte; + else + this.insulinRate = rateInt * 0.025; + this.durationMinutes = startTimeByte * 30; + this.isPercent = isPercent; + } + + + public TempBasalPair(double insulinRate, boolean isPercent, int durationMinutes) { + this.insulinRate = insulinRate; + this.isPercent = isPercent; + this.durationMinutes = durationMinutes; + } + + + public TempBasalPair(byte[] response) { + + if (L.isEnabled(L.PUMPCOMM)) + LOG.debug("Received TempBasal response: " + ByteUtil.getHex(response)); + + isPercent = response[0] == 1; + + if (isPercent) { + insulinRate = response[1]; + } else { + int strokes = MedtronicUtil.makeUnsignedShort(response[2], response[3]); + + insulinRate = strokes / 40.0d; + } + + if (response.length<6) { + durationMinutes = ByteUtil.asUINT8(response[4]); + } else { + durationMinutes = MedtronicUtil.makeUnsignedShort(response[4], response[5]); + } + + LOG.warn("TempBasalPair (with {} byte response): {}", response.length, toString()); + + } + + + public double getInsulinRate() { + return insulinRate; + } + + + public void setInsulinRate(double insulinRate) { + this.insulinRate = insulinRate; + } + + + public int getDurationMinutes() { + return durationMinutes; + } + + + public void setDurationMinutes(int durationMinutes) { + this.durationMinutes = durationMinutes; + } + + + public boolean isPercent() { + return isPercent; + } + + + public void setIsPercent(boolean yesIsPercent) { + this.isPercent = yesIsPercent; + } + + + public byte[] getAsRawData() { + + List list = new ArrayList(); + + list.add((byte) 5); + + byte[] insulinRate = MedtronicUtil.getBasalStrokes(this.insulinRate, true); + byte timeMin = (byte) MedtronicUtil.getIntervalFromMinutes(durationMinutes); + + // list.add((byte) 0); // ? + + // list.add((byte) 0); // is_absolute + + if (insulinRate.length == 1) + list.add((byte) 0x00); + else + list.add(insulinRate[0]); + + list.add(insulinRate[1]); + // list.add((byte) 0); // percent amount + + list.add(timeMin); // 3 (time) - OK + + if (insulinRate.length == 1) + list.add((byte) 0x00); + else + list.add(insulinRate[0]); + + list.add(insulinRate[1]); + + return MedtronicUtil.createByteArray(list); + } + + public boolean isCancelTBR() { + return (MedtronicUtil.isSame(insulinRate, 0.0d) && durationMinutes == 0); + } + + + public String getDescription() { + if (isCancelTBR()) { + return "Cancel TBR"; + } + + if (isPercent) { + return String.format(Locale.ENGLISH, "Rate: %.0f%%, Duration: %d min", insulinRate, durationMinutes); + } else { + return String.format(Locale.ENGLISH, "Rate: %.3f U, Duration: %d min", insulinRate, durationMinutes); + } + } + + + @Override + public String toString() { + return "TempBasalPair [" + "Rate=" + insulinRate + ", DurationMinutes=" + durationMinutes + ", IsPercent=" + + isPercent + "]"; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/TempBasalProcessDTO.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/TempBasalProcessDTO.java new file mode 100644 index 0000000000..86cba28184 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/TempBasalProcessDTO.java @@ -0,0 +1,31 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.data.dto; + +import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil; +import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryEntry; + +public class TempBasalProcessDTO { + + public PumpHistoryEntry itemOne; + public PumpHistoryEntry itemTwo; + + public Operation processOperation = Operation.None; + + public int getDuration() { + if (itemTwo == null) { + TempBasalPair tbr = (TempBasalPair) itemOne.getDecodedDataEntry("Object"); + return tbr.getDurationMinutes(); + } else { + int difference = DateTimeUtil.getATechDateDiferenceAsMinutes(itemOne.atechDateTime, itemTwo.atechDateTime); + return difference; + } + } + + + public enum Operation { + None, + Add, + Edit + } + + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/BasalProfileStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/BasalProfileStatus.java new file mode 100644 index 0000000000..0710e6ca4c --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/BasalProfileStatus.java @@ -0,0 +1,14 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.defs; + +/** + * Created by andy on 1/20/19. + */ + +public enum BasalProfileStatus { + + NotInitialized, // + ProfileOK, // + ProfileChanged, // + ; + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/BatteryType.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/BatteryType.java new file mode 100644 index 0000000000..5c7bf245a2 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/BatteryType.java @@ -0,0 +1,47 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.defs; + +import java.util.HashMap; +import java.util.Map; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; + +/** + * Created by andy on 6/4/18. + */ + +public enum BatteryType { + + None(R.string.key_medtronic_pump_battery_no, 0, 0), + Alkaline(R.string.key_medtronic_pump_battery_alkaline, 1.20d, 1.47d), // + Lithium(R.string.key_medtronic_pump_battery_lithium, 1.22d, 1.64d), // + NiZn(R.string.key_medtronic_pump_battery_nizn, 1.40d, 1.70d) // + ; + + private final String description; + public double lowVoltage; + public double highVoltage; + + static Map mapByDescription; + + static { + mapByDescription = new HashMap<>(); + + for (BatteryType value : values()) { + mapByDescription.put(value.description, value); + } + } + + BatteryType(int resId, double lowVoltage, double highVoltage) { + this.description = MainApp.gs(resId); + this.lowVoltage = lowVoltage; + this.highVoltage = highVoltage; + } + + public static BatteryType getByDescription(String batteryTypeStr) { + if (mapByDescription.containsKey(batteryTypeStr)) { + return mapByDescription.get(batteryTypeStr); + } + return BatteryType.None; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/CommandValueDefinitionMDTType.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/CommandValueDefinitionMDTType.java new file mode 100644 index 0000000000..f061b860cf --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/CommandValueDefinitionMDTType.java @@ -0,0 +1,33 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.defs; + +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.CommandValueDefinitionType; + +/** + * Created by andy on 4/5/19. + */ + +public enum CommandValueDefinitionMDTType implements CommandValueDefinitionType { + GetModel, // + TuneUp, // + GetProfile, // + GetTBR, // + ; + + @Override + public String getName() { + return this.name(); + } + + + @Override + public String getDescription() { + return null; + } + + + @Override + public String commandAction() { + return null; + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCommandType.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCommandType.java new file mode 100755 index 0000000000..516085269a --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCommandType.java @@ -0,0 +1,453 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.defs; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.plugins.pump.medtronic.comm.message.MessageBody; +import info.nightscout.androidaps.plugins.pump.medtronic.comm.message.PumpAckMessageBody; +import info.nightscout.androidaps.plugins.pump.medtronic.comm.message.UnknownMessageBody; + +/** + * Taken from GNU Gluco Control diabetes management software (ggc.sourceforge.net) + *

+ * Description: Medtronic Commands (Pump and CGMS) for all 512 and later models (just 5xx) + *

+ * Link to original/unmodified file: + * https://sourceforge.net/p/ggc/code/HEAD/tree/trunk/ggc-plugins/ggc-plugins-base/src/ + * main/java/ggc/plugin/device/impl/minimed/enums/MinimedCommandType.java + *

+ * A lot of stuff has been removed because it is not needed anymore (historical stuff from CareLink + * and Carelink USB communication. + *

+ * Author: Andy {andy@atech-software.com} + */ +public enum MedtronicCommandType implements Serializable // , MinimedCommandTypeInterface +{ + InvalidCommand(0, "Invalid Command", null, null), // + + // Pump Responses (9) + CommandACK(0x06, "ACK - Acknowledge", MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters), // + CommandNAK(0x15, "NAK - Not Acknowledged", MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters), // + + // All (8) + PushAck(91, "Push ACK", MedtronicDeviceType.All, MinimedCommandParameterType.FixedParameters, getByteArray(2)), // + + PushEsc(91, "Push Esc", MedtronicDeviceType.All, MinimedCommandParameterType.FixedParameters, getByteArray(1)), // + + PushButton(0x5b, "Push Button", MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters), // 91 + + RFPowerOn(93, "RF Power On", MedtronicDeviceType.All, MinimedCommandParameterType.FixedParameters, getByteArray( + 1, 10)), // + + RFPowerOff(93, "RF Power Off", MedtronicDeviceType.All, MinimedCommandParameterType.FixedParameters, getByteArray( + 0, 0)), // + + // SetSuspend(77, "Set Suspend", MinimedTargetType.InitCommand, MedtronicDeviceType.All, + // MinimedCommandParameterType.FixedParameters, getByteArray(1)), // + + // CancelSuspend(77, "Cancel Suspend", MinimedTargetType.InitCommand, MedtronicDeviceType.All, + // MinimedCommandParameterType.FixedParameters, getByteArray(0)), // + + PumpState(131, "Pump State", MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters), // + + ReadPumpErrorStatus(117, "Pump Error Status", MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters), // + + // 511 (InitCommand = 2, Config 7, Data = 1(+3) +// DetectBolus(75, "Detect Bolus", MedtronicDeviceType.Medtronic_511, MinimedCommandParameterType.FixedParameters, getByteArray( +// 0, 0, 0)), // + + // RemoteControlIds(118, "Remote Control Ids", MinimedTargetType.PumpConfiguration_NA, MedtronicDeviceType.All, + // MinimedCommandParameterType.NoParameters), // + + // FirmwareVersion(116, "Firmware Version", MinimedTargetType.InitCommand, MedtronicDeviceType.All, + // MinimedCommandParameterType.NoParameters), // + + // PumpId(113, "Pump Id", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.All, + // MinimedCommandParameterType.NoParameters), // init + + SetRealTimeClock(0x40, "Set Pump Time", MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters, // + 0), // + + GetRealTimeClock(112, "Get Pump Time", MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters, // + 7, R.string.medtronic_cmd_desc_get_time), // 0x70 + + GetBatteryStatus(0x72, "Get Battery Status", MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters), // + // GetBattery((byte) 0x72), // + + GetRemainingInsulin(0x73, "Read Remaining Insulin", MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters, 2), // 115 + + SetBolus(0x42, "Set Bolus", MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters, // + 0, R.string.medtronic_cmd_desc_set_bolus), // 66 + + // 512 + ReadTemporaryBasal(0x98, "Read Temporary Basal", MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters, // + 5, R.string.medtronic_cmd_desc_get_tbr), // 152 + + SetTemporaryBasal(76, "Set Temporay Basal", MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters, // + 0, R.string.medtronic_cmd_desc_set_tbr), + + // 512 Config + PumpModel(141, "Pump Model", MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters, // + 5, R.string.medtronic_cmd_desc_get_model), // 0x8D + + // BGTargets_512(140, "BG Targets", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.Medtronic_512_712, + // MinimedCommandParameterType.NoParameters), // + + // BGUnits(137, "BG Units", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.Medtronic_512andHigher, + // MinimedCommandParameterType.NoParameters), // + + // Language(134, "Language", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.Medtronic_512andHigher, + // MinimedCommandParameterType.NoParameters), // + + Settings_512(145, "Configuration", MedtronicDeviceType.Medtronic_512_712, MinimedCommandParameterType.NoParameters, // + 64, 1, 18, R.string.medtronic_cmd_desc_get_settings), // + + // BGAlarmClocks(142, "BG Alarm Clocks", MinimedTargetType.PumpConfiguration, + // MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters), // + + // BGAlarmEnable(151, "BG Alarm Enable", MinimedTargetType.PumpConfiguration, + // MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters), // + + // BGReminderEnable(144, "BG Reminder Enable", MinimedTargetType.PumpConfiguration, + // MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters), // + + // ReadInsulinSensitivities(0x8b, "Read Insulin Sensitivities", MinimedTargetType.PumpConfiguration, + // MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters), // 139 + + // 512 Data + GetHistoryData(128, "Get History", MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.SubCommands, // + 1024, 16, 1024, R.string.medtronic_cmd_desc_get_history), // 0x80 + + GetBasalProfileSTD(146, "Get Profile Standard", MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters, // + 64, 3, 192, R.string.medtronic_cmd_desc_get_basal_profile), // 146 + + GetBasalProfileA(147, "Get Profile A", MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters, // + 64, 3, 192, R.string.medtronic_cmd_desc_get_basal_profile), + + GetBasalProfileB(148, "Get Profile B", MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters, // + 64, 3, 192, R.string.medtronic_cmd_desc_get_basal_profile), // 148 + + SetBasalProfileSTD(0x6f, "Set Profile Standard", MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters, // + 64, 3, 192, R.string.medtronic_cmd_desc_set_basal_profile), // 111 + + SetBasalProfileA(0x30, "Set Profile A", MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters, // + 64, 3, 192, R.string.medtronic_cmd_desc_set_basal_profile), // 48 + + SetBasalProfileB(0x31, "Set Profile B", MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters, // + 64, 3, 192, R.string.medtronic_cmd_desc_set_basal_profile), // 49 + + // 515 + PumpStatus(206, "Pump Status", MedtronicDeviceType.Medtronic_515andHigher, MinimedCommandParameterType.NoParameters), // PumpConfiguration + + Settings(192, "Configuration", MedtronicDeviceType.Medtronic_515andHigher, MinimedCommandParameterType.NoParameters, // + 64, 1, 21, R.string.medtronic_cmd_desc_get_settings), // + + // 522 + SensorSettings_522(153, "Sensor Configuration", MedtronicDeviceType.Medtronic_522andHigher, MinimedCommandParameterType.NoParameters), // + + GlucoseHistory(154, "Glucose History", MedtronicDeviceType.Medtronic_522andHigher, MinimedCommandParameterType.SubCommands, 1024, 32, 0, null), // + + // 523 + SensorSettings(207, "Sensor Configuration", MedtronicDeviceType.Medtronic_523andHigher, MinimedCommandParameterType.NoParameters), // + + // 553 + // 554 + + // var MESSAGES = { + // READ_TIME : 0x70, + // READ_BATTERY_STATUS: 0x72, + // READ_HISTORY : 0x80, + // READ_CARB_RATIOS : 0x8A, + // READ_INSULIN_SENSITIVITIES: 0x8B, + // READ_MODEL : 0x8D, + // READ_PROFILE_STD : 0x92, + // READ_PROFILE_A : 0x93, + // READ_PROFILE_B : 0x94, + // READ_CBG_HISTORY: 0x9A, + // READ_ISIG_HISTORY: 0x9B, + // READ_CURRENT_PAGE : 0x9D, + // READ_BG_TARGETS : 0x9F, + // READ_SETTINGS : 0xC0, 192 + // READ_CURRENT_CBG_PAGE : 0xCD + // }; + + // Fake Commands + + CancelTBR(), + ; + + static Map mapByCode; + + static { + MedtronicCommandType.RFPowerOn.maxAllowedTime = 17000; + MedtronicCommandType.RFPowerOn.allowedRetries = 0; + MedtronicCommandType.RFPowerOn.recordLength = 0; + MedtronicCommandType.RFPowerOn.minimalBufferSizeToStartReading = 1; + + mapByCode = new HashMap<>(); + + for (MedtronicCommandType medtronicCommandType : values()) { + mapByCode.put(medtronicCommandType.getCommandCode(), medtronicCommandType); + } + } + + public byte commandCode = 0; + public String commandDescription = ""; + public byte[] commandParameters = null; + public int commandParametersCount = 0; + public int maxRecords = 1; + private Integer resourceId; + public int command_type = 0; + public int allowedRetries = 2; + public int maxAllowedTime = 2000; + public MinimedCommandParameterType parameterType; + public int minimalBufferSizeToStartReading = 14; + public int expectedLength = 0; + //MinimedTargetType targetType; + MedtronicDeviceType devices; + private int recordLength = 64; + + + MedtronicCommandType() { + // this is for "fake" commands needed by AAPS MedtronicUITask + } + + + // MedtronicCommandType(int code, String description, MedtronicDeviceType devices, +// MinimedCommandParameterType parameterType) { +// this(code, description, devices, parameterType, 64, 1, 0, 0, 0, 0); +// } +// +// +// MedtronicCommandType(int code, String description, MedtronicDeviceType devices, +// MinimedCommandParameterType parameterType, int expectedLength) { +// this(code, description, devices, parameterType, 64, 1, 0, 0, 0, expectedLength); +// } +// +// +// MedtronicCommandType(int code, String description, MedtronicDeviceType devices, +// MinimedCommandParameterType parameterType, int recordLength, int maxRecords, int commandType) { +// this(code, description, devices, parameterType, recordLength, maxRecords, 0, 0, commandType, 0); +// } +// +// +// MedtronicCommandType(int code, String description, MedtronicDeviceType devices, +// MinimedCommandParameterType parameterType, int recordLength, int maxRecords, int commandType, +// int expectedLength) { +// this(code, description, devices, parameterType, recordLength, maxRecords, 0, 0, commandType, +// expectedLength); +// } +// +// + MedtronicCommandType(int code, String description, MedtronicDeviceType devices, + MinimedCommandParameterType parameterType, byte[] cmd_params) { + this(code, description, devices, parameterType, 0, 1, 0, 0, 11, 0); + + this.commandParameters = cmd_params; + this.commandParametersCount = cmd_params.length; + } + + + MedtronicCommandType(int code, String description, MedtronicDeviceType devices, // + MinimedCommandParameterType parameterType) { + + this(code, description, devices, parameterType, 64, 1, 0, null); + } + + + // NEW + MedtronicCommandType(int code, String description, MedtronicDeviceType devices, + MinimedCommandParameterType parameterType, int recordLength, int maxRecords, int commandType) { + this(code, description, devices, parameterType, recordLength, maxRecords, 0, null); + } + + + // NEW + MedtronicCommandType(int code, String description, MedtronicDeviceType devices, // + MinimedCommandParameterType parameterType, int expectedLength) { + this(code, description, devices, parameterType, 64, 1, expectedLength, null); + } + + + // NEW + MedtronicCommandType(int code, String description, MedtronicDeviceType devices, // + MinimedCommandParameterType parameterType, int expectedLength, int resourceId) { + this(code, description, devices, parameterType, 64, 1, expectedLength, resourceId); + } + + + // NEW + MedtronicCommandType(int code, String description, + MedtronicDeviceType devices, // + MinimedCommandParameterType parameterType, int recordLength, int max_recs, int expectedLength, + Integer resourceId) { + this.commandCode = (byte) code; + this.commandDescription = description; + this.devices = devices; + this.recordLength = recordLength; + this.maxRecords = max_recs; + this.resourceId = resourceId; + + this.commandParametersCount = 0; + this.allowedRetries = 2; + this.parameterType = parameterType; + this.expectedLength = expectedLength; + + if (this.parameterType == MinimedCommandParameterType.SubCommands) { + this.minimalBufferSizeToStartReading = 200; + } + } + + + @Deprecated + MedtronicCommandType(int code, String description, MedtronicDeviceType devices, // + MinimedCommandParameterType parameterType, int recordLength, int max_recs, int addy, // + int addy_len, int cmd_type, int expectedLength) { + this.commandCode = (byte) code; + this.commandDescription = description; + //this.targetType = targetType; + this.devices = devices; + this.recordLength = recordLength; + this.maxRecords = max_recs; + + this.command_type = cmd_type; + this.commandParametersCount = 0; + this.allowedRetries = 2; + this.parameterType = parameterType; + this.expectedLength = expectedLength; + + if (this.parameterType == MinimedCommandParameterType.SubCommands) { + this.minimalBufferSizeToStartReading = 200; + } + + } + + + private static HashMap getDeviceTypesArray(MedtronicDeviceType... types) { + HashMap hashMap = new HashMap(); + + for (MedtronicDeviceType type : types) { + hashMap.put(type, null); + } + + return hashMap; + } + + + private static byte[] getByteArray(int... data) { + byte[] array = new byte[data.length]; + + for (int i = 0; i < data.length; i++) { + array[i] = (byte) data[i]; + } + + return array; + } + + + private static int[] getIntArray(int... data) { + return data; + } + + + public static MedtronicCommandType getByCode(byte code) { + if (mapByCode.containsKey(code)) { + return mapByCode.get(code); + } else { + return MedtronicCommandType.InvalidCommand; + } + } + + + public static MessageBody constructMessageBody(MedtronicCommandType messageType, byte[] bodyData) { + switch (messageType) { + case CommandACK: + return new PumpAckMessageBody(bodyData); + default: + return new UnknownMessageBody(bodyData); + } + } + + + public static MedtronicCommandType getSettings(MedtronicDeviceType medtronicPumpModel) { + if (MedtronicDeviceType.isSameDevice(medtronicPumpModel, MedtronicDeviceType.Medtronic_512_712)) + return MedtronicCommandType.Settings_512; + else + return MedtronicCommandType.Settings; + } + + + /** + * Get Full Command Description + * + * @return command description + */ + public String getFullCommandDescription() { + return "Command [name=" + this.name() + ", id=" + this.commandCode + ",description=" + this.commandDescription + + "] "; + } + + + public boolean canReturnData() { + System.out.println("CanReturnData: ]id=" + this.name() + "max=" + this.maxRecords + "recLen=" + recordLength); + return (this.maxRecords * this.recordLength) > 0; + } + + + public int getRecordLength() { + return recordLength; + } + + + public int getMaxRecords() { + return maxRecords; + } + + + public byte getCommandCode() { + return commandCode; + } + + + public int getCommandParametersCount() { + if (this.commandParameters == null) { + return 0; + } else { + return this.commandParameters.length; + } + } + + + public byte[] getCommandParameters() { + return commandParameters; + } + + + public boolean hasCommandParameters() { + return (getCommandParametersCount() > 0); + } + + + public String toString() { + return name(); + } + + + public String getCommandDescription() { + return this.commandDescription; + } + + + public Integer getResourceId() { + return resourceId; + } + + public enum MinimedCommandParameterType { + NoParameters, // + FixedParameters, // + SubCommands // + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCustomActionType.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCustomActionType.java new file mode 100644 index 0000000000..af0be33cfa --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCustomActionType.java @@ -0,0 +1,20 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.defs; + +import info.nightscout.androidaps.plugins.general.actions.defs.CustomActionType; + +/** + * Created by andy on 11/3/18. + */ + +public enum MedtronicCustomActionType implements CustomActionType { + + WakeUpAndTune(), // + ClearBolusBlock(), // + ResetRileyLinkConfiguration(), // + ; + + @Override + public String getKey() { + return this.name(); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicDeviceType.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicDeviceType.java new file mode 100644 index 0000000000..f13974999b --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicDeviceType.java @@ -0,0 +1,140 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.defs; + +import java.util.HashMap; +import java.util.Map; + +/** + * Taken from GNU Gluco Control diabetes management software (ggc.sourceforge.net) + *

+ * Author: Andy {andy@atech-software.com} + */ + +public enum MedtronicDeviceType { + Unknown_Device, // + + // Pump + Medtronic_511("511"), // + + Medtronic_512("512"), // + Medtronic_712("712"), // + Medtronic_512_712(Medtronic_512, Medtronic_712), // + + Medtronic_515("515"), // + Medtronic_715("715"), // + Medtronic_515_715(Medtronic_515, Medtronic_715), // + + Medtronic_522("522"), // + Medtronic_722("722"), // + Medtronic_522_722(Medtronic_522, Medtronic_722), // + + Medtronic_523_Revel("523"), // + Medtronic_723_Revel("723"), // + + Medtronic_554_Veo("554"), // + Medtronic_754_Veo("754"), // + + Medtronic_512andHigher(Medtronic_512, Medtronic_712, Medtronic_515, Medtronic_715, Medtronic_522, Medtronic_722, // + Medtronic_523_Revel, Medtronic_723_Revel, Medtronic_554_Veo, Medtronic_754_Veo), // + + Medtronic_515andHigher(Medtronic_515, Medtronic_715, Medtronic_522, Medtronic_722, Medtronic_523_Revel, Medtronic_723_Revel, // + Medtronic_554_Veo, Medtronic_754_Veo), // + Medtronic_522andHigher(Medtronic_522, Medtronic_722, Medtronic_523_Revel, Medtronic_723_Revel, // + Medtronic_554_Veo, Medtronic_754_Veo), // + Medtronic_523andHigher(Medtronic_523_Revel, Medtronic_723_Revel, Medtronic_554_Veo, // + Medtronic_754_Veo), // + + Medtronic_554andHigher(Medtronic_554_Veo, Medtronic_754_Veo), // + + + // + All; + + static Map mapByDescription; + + static { + + mapByDescription = new HashMap<>(); + + for (MedtronicDeviceType minimedDeviceType : values()) { + + if (!minimedDeviceType.isFamily) { + mapByDescription.put(minimedDeviceType.pumpModel, minimedDeviceType); + } + } + + } + + private String pumpModel; + + private boolean isFamily; + private MedtronicDeviceType[] familyMembers = null; + + + MedtronicDeviceType(String pumpModel) { + this.isFamily = false; + this.pumpModel = pumpModel; + } + + + MedtronicDeviceType(MedtronicDeviceType... familyMembers) { + this.familyMembers = familyMembers; + this.isFamily = true; + } + + + public static boolean isSameDevice(MedtronicDeviceType deviceWeCheck, MedtronicDeviceType deviceSources) { + if (deviceSources.isFamily) { + for (MedtronicDeviceType mdt : deviceSources.familyMembers) { + if (mdt == deviceWeCheck) + return true; + } + } else { + return (deviceWeCheck == deviceSources); + } + + return false; + } + + + public static MedtronicDeviceType getByDescription(String desc) { + if (mapByDescription.containsKey(desc)) { + return mapByDescription.get(desc); + } else { + return MedtronicDeviceType.Unknown_Device; + } + } + + +// public static boolean isLargerFormat(MedtronicDeviceType model) { +// return isSameDevice(model, Medtronic_523andHigher); +// } + + + public boolean isFamily() { + return isFamily; + } + + + public MedtronicDeviceType[] getFamilyMembers() { + return familyMembers; + } + + +// public boolean isLargerFormat() { +// return isSameDevice(this, Medtronic_523andHigher); +// } + + public boolean isMedtronic_523orHigher() { + return isSameDevice(this, Medtronic_523andHigher); + } + + + public int getBolusStrokes() { + return (isMedtronic_523orHigher()) ? 40 : 10; + } + + + public String getPumpModel() { + return pumpModel; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicNotificationType.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicNotificationType.java new file mode 100644 index 0000000000..d11d6ad64c --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicNotificationType.java @@ -0,0 +1,65 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.defs; + +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; + +/** + * Created by andy on 10/15/18. + */ + +public enum MedtronicNotificationType { + + PumpUnreachable(Notification.RILEYLINK_CONNECTION, R.string.medtronic_pump_status_pump_unreachable, Notification.NORMAL), // + PumpTypeNotSame(R.string.medtronic_error_pump_type_set_differs_from_detected, Notification.NORMAL), // + PumpBasalProfilesNotEnabled(R.string.medtronic_error_pump_basal_profiles_not_enabled, Notification.URGENT), // + PumpIncorrectBasalProfileSelected(R.string.medtronic_error_pump_incorrect_basal_profile_selected, Notification.URGENT), // + PumpWrongTBRTypeSet(R.string.medtronic_error_pump_wrong_tbr_type_set, Notification.URGENT), // + PumpWrongMaxBolusSet(R.string.medtronic_error_pump_wrong_max_bolus_set, Notification.NORMAL), // + PumpWrongMaxBasalSet(R.string.medtronic_error_pump_wrong_max_basal_set, Notification.NORMAL), // + PumpWrongTimeUrgent(R.string.combo_notification_check_time_date, Notification.URGENT), + PumpWrongTimeNormal(R.string.combo_notification_check_time_date, Notification.NORMAL), + TimeChangeOver24h(Notification.OVER_24H_TIME_CHANGE_REQUESTED, R.string.medtronic_error_pump_24h_time_change_requested, Notification.URGENT), + // + ; + + private int notificationType; + private int resourceId; + private int notificationUrgency; + + + MedtronicNotificationType(int resourceId, int notificationUrgency) { + this(Notification.MEDTRONIC_PUMP_ALARM, resourceId, notificationUrgency); + } + + + MedtronicNotificationType(int notificationType, int resourceId, int notificationUrgency) { + this.notificationType = notificationType; + this.resourceId = resourceId; + this.notificationUrgency = notificationUrgency; + } + + + public int getNotificationType() { + return notificationType; + } + + + public void setNotificationType(int notificationType) { + this.notificationType = notificationType; + } + + + public int getResourceId() { + + return resourceId; + } + + + public int getNotificationUrgency() { + + return notificationUrgency; + } + + // Notification.MEDTRONIC_PUMP_ALARM R.string.medtronic_pump_status_pump_unreachable, Notification.NORMAL + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicStatusRefreshType.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicStatusRefreshType.java new file mode 100644 index 0000000000..55dc9b1a49 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicStatusRefreshType.java @@ -0,0 +1,39 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.defs; + +import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil; + +/** + * Created by andy on 6/28/18. + */ + +public enum MedtronicStatusRefreshType { + + PumpHistory(5, null), // + Configuration(0, null), // + RemainingInsulin(-1, MedtronicCommandType.GetRemainingInsulin), // + BatteryStatus(55, MedtronicCommandType.GetBatteryStatus), // + PumpTime(60, MedtronicCommandType.GetRealTimeClock) // + ; + + private int refreshTime; + private MedtronicCommandType commandType; + + + MedtronicStatusRefreshType(int refreshTime, MedtronicCommandType commandType) { + this.refreshTime = refreshTime; + this.commandType = commandType; + } + + + public int getRefreshTime() { + return refreshTime; + } + + + public MedtronicCommandType getCommandType() { + if (this == Configuration) { + return MedtronicCommandType.getSettings(MedtronicUtil.getMedtronicPumpModel()); + } else + return commandType; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicUIResponseType.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicUIResponseType.java new file mode 100644 index 0000000000..8ab1fc0871 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicUIResponseType.java @@ -0,0 +1,13 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.defs; + +/** + * Created by andy on 10/18/18. + */ + +public enum MedtronicUIResponseType { + + Data, + Error, + Invalid + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/PumpBolusType.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/PumpBolusType.java new file mode 100644 index 0000000000..820bff8a5b --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/PumpBolusType.java @@ -0,0 +1,129 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.defs; + +import java.util.HashMap; + +/** + * Application: GGC - GNU Gluco Control + * Plug-in: Pump Tool (support for Pump devices) + *

+ * See AUTHORS for copyright information. + *

+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later + * version. + *

+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + *

+ * You should have received a copy of the GNU General Public License along with this program; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + *

+ * Filename: PumpBolusType Description: Pump Bolus Types + *

+ * Author: Andy {andy@atech-software.com} + */ + +public enum PumpBolusType // implements CodeEnumWithTranslation +{ + None(0, "NONE"), // + Normal(1, "BOLUS_STANDARD"), // + Audio(2, "BOLUS_AUDIO"), // + Extended(3, "BOLUS_SQUARE", "AMOUNT_SQUARE=%s;DURATION=%s"), // + Multiwave(4, "BOLUS_MULTIWAVE", "AMOUNT=%s;AMOUNT_SQUARE=%s;DURATION=%s"); + + static String[] descriptions; + // static HashMap translationMapping = new HashMap(); + static HashMap codeMapping = new HashMap(); + private static boolean translated; + + static { + for (PumpBolusType pbt : values()) { + codeMapping.put(pbt.code, pbt); + } + } + + // public static void translateKeywords(I18nControlAbstract ic) + // { + // if (translated) + // return; + // + // for (PumpBolusType pbt : values()) + // { + // pbt.setTranslation(ic.getMessage(pbt.i18nKey)); + // translationMapping.put(pbt.getTranslation(), pbt); + // } + // + // String[] bolusDescriptions = { ic.getMessage("SELECT_BOLUS_TYPE"), // + // ic.getMessage("BOLUS_STANDARD"), // + // ic.getMessage("BOLUS_AUDIO"), // + // ic.getMessage("BOLUS_SQUARE"), // + // ic.getMessage("BOLUS_MULTIWAVE"), }; + // + // descriptions = bolusDescriptions; + // + // translated = true; + // } + + int code; + String i18nKey; + String translation; + String valueTemplate; + + + PumpBolusType(int code, String i18nKey) { + this.code = code; + this.i18nKey = i18nKey; + } + + + PumpBolusType(int code, String i18nKey, String valueTemplate) { + this.code = code; + this.i18nKey = i18nKey; + this.valueTemplate = valueTemplate; + } + + + public static PumpBolusType getByCode(int code) { + if (codeMapping.containsKey(code)) { + return codeMapping.get(code); + } else { + return PumpBolusType.None; + } + } + + + /** + * Get Descriptions (array) + * + * @return array of strings with description + */ + public static String[] getDescriptions() { + return descriptions; + } + + + public String getTranslation() { + return translation; + } + + + public void setTranslation(String translation) { + this.translation = translation; + } + + + public int getCode() { + return code; + } + + + public String getI18nKey() { + return i18nKey; + } + + + public String getName() { + return this.name(); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/PumpConfigurationGroup.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/PumpConfigurationGroup.java new file mode 100644 index 0000000000..1c69641c98 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/PumpConfigurationGroup.java @@ -0,0 +1,58 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.defs; + +/** + * Created by andy on 27.02.15. + */ +public enum PumpConfigurationGroup { + General(1, "GROUP_GENERAL"), // + Device(2, "GROUP_DEVICE"), // + + Insulin(3, "GROUP_INSULIN"), // + + Basal(4, "GROUP_BASAL"), // + Bolus(5, "GROUP_BOLUS"), // + Sound(6, "GROUP_SOUND"), // + + Other(20, "GROUP_OTHER"), // + + UnknownGroup(21, "GROUP_UNKNOWN"), // + + ; // + + static boolean translated; + int code; + String i18nKey; + String translation; + + + PumpConfigurationGroup(int code, String i18nKey) { + this.code = code; + this.i18nKey = i18nKey; + } + + + public String getTranslation() { + return translation; + } + + + public void setTranslation(String translation) { + this.translation = translation; + } + + + public int getCode() { + return code; + } + + + public String getI18nKey() { + return i18nKey; + } + + + public String getName() { + return this.name(); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/PumpDeviceState.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/PumpDeviceState.java new file mode 100644 index 0000000000..ba86963869 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/PumpDeviceState.java @@ -0,0 +1,30 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.defs; + +import info.nightscout.androidaps.R; + +/** + * Created by andy on 6/11/18. + */ + +public enum PumpDeviceState { + + NeverContacted(R.string.medtronic_pump_status_never_contacted), // + Sleeping(R.string.medtronic_pump_status_sleeping), // + WakingUp(R.string.medtronic_pump_status_waking_up), // + Active(R.string.medtronic_pump_status_active), // + ErrorWhenCommunicating(R.string.medtronic_pump_status_error_comm), // + TimeoutWhenCommunicating(R.string.medtronic_pump_status_timeout_comm), // + // ProblemContacting(R.string.medtronic_pump_status_problem_contacting), // + PumpUnreachable(R.string.medtronic_pump_status_pump_unreachable), // + InvalidConfiguration(R.string.medtronic_pump_status_invalid_config); + + Integer resourceId; + + PumpDeviceState(int resourceId) { + this.resourceId = resourceId; + } + + public Integer getResourceId() { + return resourceId; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/MedtronicHistoryActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/MedtronicHistoryActivity.java new file mode 100644 index 0000000000..2d1a3a871e --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/MedtronicHistoryActivity.java @@ -0,0 +1,254 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.dialog; + +import android.os.Bundle; +import android.os.SystemClock; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.Spinner; +import android.widget.TextView; + +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; + +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.activities.NoSplashActivity; +import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.pump.medtronic.MedtronicPumpPlugin; +import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryEntry; +import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryEntryGroup; + +public class MedtronicHistoryActivity extends NoSplashActivity { + + private static Logger LOG = LoggerFactory.getLogger(L.PUMP); + + Spinner historyTypeSpinner; + TextView statusView; + RecyclerView recyclerView; + LinearLayoutManager llm; + + static TypeList showingType = null; + static PumpHistoryEntryGroup selectedGroup = PumpHistoryEntryGroup.All; + List filteredHistoryList = new ArrayList<>(); + + RecyclerViewAdapter recyclerViewAdapter; + boolean manualChange = false; + + List typeListFull; + + + public MedtronicHistoryActivity() { + super(); + } + + + private void filterHistory(PumpHistoryEntryGroup group) { + + this.filteredHistoryList.clear(); + + List list = new ArrayList<>(); + list.addAll(MedtronicPumpPlugin.getPlugin().getMedtronicHistoryData().getAllHistory()); + + //LOG.debug("Items on full list: {}", list.size()); + + if (group == PumpHistoryEntryGroup.All) { + this.filteredHistoryList.addAll(list); + } else { + for (PumpHistoryEntry pumpHistoryEntry : list) { + if (pumpHistoryEntry.getEntryType().getGroup() == group) { + this.filteredHistoryList.add(pumpHistoryEntry); + } + } + } + + if (this.recyclerViewAdapter != null) { + this.recyclerViewAdapter.setHistoryList(this.filteredHistoryList); + this.recyclerViewAdapter.notifyDataSetChanged(); + } + + //LOG.debug("Items on filtered list: {}", filteredHistoryList.size()); + } + + + @Override + protected void onResume() { + super.onResume(); + filterHistory(selectedGroup); + setHistoryTypeSpinner(); + } + + + private void setHistoryTypeSpinner() { + this.manualChange = true; + + for (int i = 0; i < typeListFull.size(); i++) { + if (typeListFull.get(i).entryGroup == selectedGroup) { + historyTypeSpinner.setSelection(i); + break; + } + } + + SystemClock.sleep(200); + this.manualChange = false; + } + + + @Override + protected void onPause() { + super.onPause(); + } + + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.medtronic_history_activity); + + historyTypeSpinner = (Spinner) findViewById(R.id.medtronic_historytype); + statusView = (TextView) findViewById(R.id.medtronic_historystatus); + recyclerView = (RecyclerView) findViewById(R.id.medtronic_history_recyclerview); + + recyclerView.setHasFixedSize(true); + llm = new LinearLayoutManager(this); + recyclerView.setLayoutManager(llm); + + recyclerViewAdapter = new RecyclerViewAdapter(filteredHistoryList); + recyclerView.setAdapter(recyclerViewAdapter); + + statusView.setVisibility(View.GONE); + + typeListFull = getTypeList(PumpHistoryEntryGroup.getList()); + + ArrayAdapter spinnerAdapter = new ArrayAdapter<>(this, R.layout.spinner_centered, typeListFull); + historyTypeSpinner.setAdapter(spinnerAdapter); + + historyTypeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + + @Override + public void onItemSelected(AdapterView parent, View view, int position, long id) { + if (manualChange) + return; + TypeList selected = (TypeList) historyTypeSpinner.getSelectedItem(); + showingType = selected; + selectedGroup = selected.entryGroup; + filterHistory(selectedGroup); + } + + + @Override + public void onNothingSelected(AdapterView parent) { + if (manualChange) + return; + filterHistory(PumpHistoryEntryGroup.All); + } + }); + + } + + + private List getTypeList(List list) { + + ArrayList typeList = new ArrayList<>(); + + for (PumpHistoryEntryGroup pumpHistoryEntryGroup : list) { + typeList.add(new TypeList(pumpHistoryEntryGroup)); + } + + return typeList; + } + + public static class TypeList { + + PumpHistoryEntryGroup entryGroup; + String name; + + + TypeList(PumpHistoryEntryGroup entryGroup) { + this.entryGroup = entryGroup; + this.name = entryGroup.getTranslated(); + } + + + @Override + public String toString() { + return name; + } + } + + public static class RecyclerViewAdapter extends RecyclerView.Adapter { + + List historyList; + + + RecyclerViewAdapter(List historyList) { + this.historyList = historyList; + } + + + public void setHistoryList(List historyList) { + // this.historyList.clear(); + // this.historyList.addAll(historyList); + + this.historyList = historyList; + + // this.notifyDataSetChanged(); + } + + + @Override + public HistoryViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { + View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.medtronic_history_item, // + viewGroup, false); + return new HistoryViewHolder(v); + } + + + @Override + public void onBindViewHolder(HistoryViewHolder holder, int position) { + PumpHistoryEntry record = historyList.get(position); + + if (record != null) { + holder.timeView.setText(record.getDateTimeString()); + holder.typeView.setText(record.getEntryType().getDescription()); + holder.valueView.setText(record.getDisplayableValue()); + } + } + + + @Override + public int getItemCount() { + return historyList.size(); + } + + + @Override + public void onAttachedToRecyclerView(RecyclerView recyclerView) { + super.onAttachedToRecyclerView(recyclerView); + } + + static class HistoryViewHolder extends RecyclerView.ViewHolder { + + TextView timeView; + TextView typeView; + TextView valueView; + + + HistoryViewHolder(View itemView) { + super(itemView); + // cv = (CardView)itemView.findViewById(R.id.rileylink_history_item); + timeView = (TextView) itemView.findViewById(R.id.medtronic_history_time); + typeView = (TextView) itemView.findViewById(R.id.medtronic_history_source); + valueView = (TextView) itemView.findViewById(R.id.medtronic_history_description); + } + } + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/RileyLinkStatusDeviceMedtronic.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/RileyLinkStatusDeviceMedtronic.java new file mode 100644 index 0000000000..2d7252cb7c --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/RileyLinkStatusDeviceMedtronic.java @@ -0,0 +1,159 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.dialog; + +import android.os.Bundle; +import androidx.fragment.app.Fragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.ListView; +import android.widget.TextView; + +import java.util.ArrayList; +import java.util.List; + +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.plugins.pump.common.dialog.RefreshableInterface; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.data.RLHistoryItem; +import info.nightscout.androidaps.plugins.pump.common.utils.StringUtil; + +/** + * Created by andy on 5/19/18. + *

+ * This is for 3rd tab, called Medtronic (in RileyLink stats), that should work similarly as the one in Loop. + *

+ * Showing currently selected RL, speed of RL, ability to issue simple commands (getModel, tuneUp, gerProfile) + */ + +// TODO needs to be implemented +public class RileyLinkStatusDeviceMedtronic extends Fragment implements RefreshableInterface { + + // @BindView(R.id.rileylink_history_list) + ListView listView; + + RileyLinkCommandListAdapter adapter; + + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View rootView = inflater.inflate(R.layout.rileylink_status_device, container, false); + + adapter = new RileyLinkCommandListAdapter(); + + return rootView; + } + + + @Override + public void onStart() { + super.onStart(); + + this.listView = (ListView) getActivity().findViewById(R.id.rileylink_history_list); + + listView.setAdapter(adapter); + + refreshData(); + } + + + @Override + public void refreshData() { + // adapter.addItemsAndClean(RileyLinkUtil.getRileyLinkHistory()); + } + + static class ViewHolder { + + TextView itemTime; + TextView itemSource; + TextView itemDescription; + } + + private class RileyLinkCommandListAdapter extends BaseAdapter { + + private List historyItemList; + private LayoutInflater mInflator; + + + public RileyLinkCommandListAdapter() { + super(); + historyItemList = new ArrayList<>(); + mInflator = RileyLinkStatusDeviceMedtronic.this.getLayoutInflater(); + } + + + public void addItem(RLHistoryItem item) { + if (!historyItemList.contains(item)) { + historyItemList.add(item); + notifyDataSetChanged(); + } + } + + + public RLHistoryItem getHistoryItem(int position) { + return historyItemList.get(position); + } + + + public void addItemsAndClean(List items) { + this.historyItemList.clear(); + + for (RLHistoryItem item : items) { + + if (!historyItemList.contains(item)) { + historyItemList.add(item); + } + } + + notifyDataSetChanged(); + } + + + public void clear() { + historyItemList.clear(); + notifyDataSetChanged(); + } + + + @Override + public int getCount() { + return historyItemList.size(); + } + + + @Override + public Object getItem(int i) { + return historyItemList.get(i); + } + + + @Override + public long getItemId(int i) { + return i; + } + + + @Override + public View getView(int i, View view, ViewGroup viewGroup) { + RileyLinkStatusDeviceMedtronic.ViewHolder viewHolder; + // General ListView optimization code. + if (view == null) { + view = mInflator.inflate(R.layout.rileylink_status_device_item, null); + viewHolder = new RileyLinkStatusDeviceMedtronic.ViewHolder(); + viewHolder.itemTime = (TextView) view.findViewById(R.id.rileylink_history_time); + viewHolder.itemSource = (TextView) view.findViewById(R.id.rileylink_history_source); + viewHolder.itemDescription = (TextView) view.findViewById(R.id.rileylink_history_description); + view.setTag(viewHolder); + } else { + viewHolder = (RileyLinkStatusDeviceMedtronic.ViewHolder) view.getTag(); + } + + RLHistoryItem item = historyItemList.get(i); + viewHolder.itemTime.setText(StringUtil.toDateTimeString(item.getDateTime())); + viewHolder.itemSource.setText("Riley Link"); // for now + viewHolder.itemDescription.setText(item.getDescription()); + + return view; + } + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/driver/MedtronicPumpStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/driver/MedtronicPumpStatus.java new file mode 100644 index 0000000000..fc1208a340 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/driver/MedtronicPumpStatus.java @@ -0,0 +1,390 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.driver; + +import org.joda.time.LocalDateTime; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.HashMap; +import java.util.Map; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.interfaces.PumpDescription; +import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.pump.common.data.PumpStatus; +import info.nightscout.androidaps.plugins.pump.common.defs.PumpType; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkConst; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RileyLinkEncodingType; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RileyLinkTargetFrequency; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkError; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkServiceState; +import info.nightscout.androidaps.plugins.pump.medtronic.data.MedtronicHistoryData; +import info.nightscout.androidaps.plugins.pump.medtronic.defs.BasalProfileStatus; +import info.nightscout.androidaps.plugins.pump.medtronic.defs.BatteryType; +import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicDeviceType; +import info.nightscout.androidaps.plugins.pump.medtronic.defs.PumpDeviceState; +import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicConst; +import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil; +import info.nightscout.androidaps.utils.SP; + +/** + * Created by andy on 4/28/18. + */ + +public class MedtronicPumpStatus extends PumpStatus { + + private static Logger LOG = LoggerFactory.getLogger(L.PUMP); + + public String errorDescription = null; + public String serialNumber; + public String pumpFrequency = null; + public String rileyLinkAddress = null; + public Double maxBolus; + public Double maxBasal; + public boolean inPreInit = true; + + // statuses + public RileyLinkServiceState rileyLinkServiceState = RileyLinkServiceState.NotStarted; + public RileyLinkError rileyLinkError; + public PumpDeviceState pumpDeviceState = PumpDeviceState.NeverContacted; + public MedtronicDeviceType medtronicDeviceType = null; + public double currentBasal = 0; + public int tempBasalInProgress = 0; + public int tempBasalRatio = 0; + public int tempBasalRemainMin = 0; + public Date tempBasalStart; + public Double tempBasalAmount = 0.0d; + + // fixme + public Integer tempBasalLength = 0; + + private String regexMac = "([\\da-fA-F]{1,2}(?:\\:|$)){6}"; + private String regexSN = "[0-9]{6}"; + + private boolean serialChanged = false; + private boolean rileyLinkAddressChanged = false; + private boolean encodingChanged = false; + private boolean targetFrequencyChanged = false; + + private RileyLinkEncodingType encodingType; + private String[] frequencies; + private boolean isFrequencyUS = false; + private Map medtronicPumpMap = null; + private Map medtronicDeviceTypeMap = null; + private RileyLinkTargetFrequency targetFrequency; + public BasalProfileStatus basalProfileStatus = BasalProfileStatus.NotInitialized; + public BatteryType batteryType = BatteryType.None; + + + public MedtronicPumpStatus(PumpDescription pumpDescription) { + super(pumpDescription); + } + + + @Override + public void initSettings() { + + this.activeProfileName = "STD"; + this.reservoirRemainingUnits = 75d; + this.batteryRemaining = 75; + + if (this.medtronicPumpMap == null) + createMedtronicPumpMap(); + + if (this.medtronicDeviceTypeMap == null) + createMedtronicDeviceTypeMap(); + + this.lastConnection = SP.getLong(MedtronicConst.Statistics.LastGoodPumpCommunicationTime, 0L); + this.lastDataTime = new LocalDateTime(this.lastConnection); + } + + + private void createMedtronicDeviceTypeMap() { + medtronicDeviceTypeMap = new HashMap<>(); + medtronicDeviceTypeMap.put("512", MedtronicDeviceType.Medtronic_512); + medtronicDeviceTypeMap.put("712", MedtronicDeviceType.Medtronic_712); + medtronicDeviceTypeMap.put("515", MedtronicDeviceType.Medtronic_515); + medtronicDeviceTypeMap.put("715", MedtronicDeviceType.Medtronic_715); + + medtronicDeviceTypeMap.put("522", MedtronicDeviceType.Medtronic_522); + medtronicDeviceTypeMap.put("722", MedtronicDeviceType.Medtronic_722); + medtronicDeviceTypeMap.put("523", MedtronicDeviceType.Medtronic_523_Revel); + medtronicDeviceTypeMap.put("723", MedtronicDeviceType.Medtronic_723_Revel); + medtronicDeviceTypeMap.put("554", MedtronicDeviceType.Medtronic_554_Veo); + medtronicDeviceTypeMap.put("754", MedtronicDeviceType.Medtronic_754_Veo); + } + + + private void createMedtronicPumpMap() { + + medtronicPumpMap = new HashMap<>(); + medtronicPumpMap.put("512", PumpType.Medtronic_512_712); + medtronicPumpMap.put("712", PumpType.Medtronic_512_712); + medtronicPumpMap.put("515", PumpType.Medtronic_515_715); + medtronicPumpMap.put("715", PumpType.Medtronic_515_715); + + medtronicPumpMap.put("522", PumpType.Medtronic_522_722); + medtronicPumpMap.put("722", PumpType.Medtronic_522_722); + medtronicPumpMap.put("523", PumpType.Medtronic_523_723_Revel); + medtronicPumpMap.put("723", PumpType.Medtronic_523_723_Revel); + medtronicPumpMap.put("554", PumpType.Medtronic_554_754_Veo); + medtronicPumpMap.put("754", PumpType.Medtronic_554_754_Veo); + + frequencies = new String[2]; + frequencies[0] = MainApp.gs(R.string.key_medtronic_pump_frequency_us_ca); + frequencies[1] = MainApp.gs(R.string.key_medtronic_pump_frequency_worldwide); + } + + + public boolean verifyConfiguration() { + try { + + // FIXME don't reload information several times + if (this.medtronicPumpMap == null) + createMedtronicPumpMap(); + + if (this.medtronicDeviceTypeMap == null) + createMedtronicDeviceTypeMap(); + + this.errorDescription = "-"; + + String serialNr = SP.getString(MedtronicConst.Prefs.PumpSerial, null); + + if (serialNr == null) { + this.errorDescription = MainApp.gs(R.string.medtronic_error_serial_not_set); + return false; + } else { + if (!serialNr.matches(regexSN)) { + this.errorDescription = MainApp.gs(R.string.medtronic_error_serial_invalid); + return false; + } else { + if (!serialNr.equals(this.serialNumber)) { + this.serialNumber = serialNr; + serialChanged = true; + } + } + } + + String pumpType = SP.getString(MedtronicConst.Prefs.PumpType, null); + + if (pumpType == null) { + this.errorDescription = MainApp.gs(R.string.medtronic_error_pump_type_not_set); + return false; + } else { + String pumpTypePart = pumpType.substring(0, 3); + + if (!pumpTypePart.matches("[0-9]{3}")) { + this.errorDescription = MainApp.gs(R.string.medtronic_error_pump_type_invalid); + return false; + } else { + this.pumpType = medtronicPumpMap.get(pumpTypePart); + this.medtronicDeviceType = medtronicDeviceTypeMap.get(pumpTypePart); + this.pumpDescription.setPumpDescription(this.pumpType); + + if (pumpTypePart.startsWith("7")) + this.reservoirFullUnits = 300; + else + this.reservoirFullUnits = 176; + } + } + + String pumpFrequency = SP.getString(MedtronicConst.Prefs.PumpFrequency, null); + + if (pumpFrequency == null) { + this.errorDescription = MainApp.gs(R.string.medtronic_error_pump_frequency_not_set); + return false; + } else { + if (!pumpFrequency.equals(frequencies[0]) && !pumpFrequency.equals(frequencies[1])) { + this.errorDescription = MainApp.gs(R.string.medtronic_error_pump_frequency_invalid); + return false; + } else { + this.pumpFrequency = pumpFrequency; + this.isFrequencyUS = pumpFrequency.equals(frequencies[0]); + + RileyLinkTargetFrequency newTargetFrequency = this.isFrequencyUS ? // + RileyLinkTargetFrequency.Medtronic_US + : RileyLinkTargetFrequency.Medtronic_WorldWide; + + if (targetFrequency != newTargetFrequency) { + RileyLinkUtil.setRileyLinkTargetFrequency(newTargetFrequency); + targetFrequency = newTargetFrequency; + targetFrequencyChanged = true; + } + + } + } + + String rileyLinkAddress = SP.getString(RileyLinkConst.Prefs.RileyLinkAddress, null); + + if (rileyLinkAddress == null) { + if (isLogEnabled()) + LOG.debug("RileyLink address invalid: null"); + this.errorDescription = MainApp.gs(R.string.medtronic_error_rileylink_address_invalid); + return false; + } else { + if (!rileyLinkAddress.matches(regexMac)) { + this.errorDescription = MainApp.gs(R.string.medtronic_error_rileylink_address_invalid); + if (isLogEnabled()) + LOG.debug("RileyLink address invalid: {}", rileyLinkAddress); + } else { + if (!rileyLinkAddress.equals(this.rileyLinkAddress)) { + this.rileyLinkAddress = rileyLinkAddress; + rileyLinkAddressChanged = true; + } + } + } + + double maxBolusLcl = checkParameterValue(MedtronicConst.Prefs.MaxBolus, "25.0", 25.0d); + + if (maxBolus == null || !maxBolus.equals(maxBolusLcl)) { + maxBolus = maxBolusLcl; + + //LOG.debug("Max Bolus from AAPS settings is " + maxBolus); + } + + double maxBasalLcl = checkParameterValue(MedtronicConst.Prefs.MaxBasal, "35.0", 35.0d); + + if (maxBasal == null || !maxBasal.equals(maxBasalLcl)) { + maxBasal = maxBasalLcl; + + //LOG.debug("Max Basal from AAPS settings is " + maxBasal); + } + + + String encodingTypeStr = SP.getString(MedtronicConst.Prefs.Encoding, null); + + if (encodingTypeStr == null) { + return false; + } + + RileyLinkEncodingType newEncodingType = RileyLinkEncodingType.getByDescription(encodingTypeStr); + + if (this.encodingType == null) { + this.encodingType = newEncodingType; + } else if (this.encodingType != newEncodingType) { + this.encodingType = newEncodingType; + this.encodingChanged = true; + } + + String batteryTypeStr = SP.getString(MedtronicConst.Prefs.BatteryType, null); + + if (batteryTypeStr == null) + return false; + + BatteryType batteryType = BatteryType.getByDescription(batteryTypeStr); + + if (this.batteryType != batteryType) { + this.batteryType = batteryType; + MedtronicUtil.setBatteryType(this.batteryType); + } + + String bolusDebugEnabled = SP.getString(MedtronicConst.Prefs.BolusDebugEnabled, null); + + boolean bolusDebug = bolusDebugEnabled != null && bolusDebugEnabled.equals(MainApp.gs(R.string.common_on)); + + MedtronicHistoryData.doubleBolusDebug = bolusDebug; + + reconfigureService(); + + return true; + + } catch (Exception ex) { + this.errorDescription = ex.getMessage(); + LOG.error("Error on Verification: " + ex.getMessage(), ex); + return false; + } + } + + + private boolean reconfigureService() { + + if (!inPreInit && MedtronicUtil.getMedtronicService() != null) { + + if (serialChanged) { + MedtronicUtil.getMedtronicService().setPumpIDString(this.serialNumber); // short operation + serialChanged = false; + } + + if (rileyLinkAddressChanged) { + MedtronicUtil.sendBroadcastMessage(RileyLinkConst.Intents.RileyLinkNewAddressSet); + rileyLinkAddressChanged = false; + } + + if (encodingChanged) { + RileyLinkUtil.getRileyLinkService().changeRileyLinkEncoding(encodingType); + encodingChanged = false; + } + } + + + // if (targetFrequencyChanged && !inPreInit && MedtronicUtil.getMedtronicService() != null) { + // RileyLinkUtil.setRileyLinkTargetFrequency(targetFrequency); + // // RileyLinkUtil.getRileyLinkCommunicationManager().refreshRileyLinkTargetFrequency(); + // targetFrequencyChanged = false; + // } + + return (!rileyLinkAddressChanged && !serialChanged && !encodingChanged); // && !targetFrequencyChanged); + } + + + private double checkParameterValue(int key, String defaultValue, double defaultValueDouble) { + double val = 0.0d; + + String value = SP.getString(key, defaultValue); + + try { + val = Double.parseDouble(value); + } catch (Exception ex) { + LOG.error("Error parsing setting: {}, value found {}", key, value); + val = defaultValueDouble; + } + + if (val > defaultValueDouble) { + SP.putString(key, defaultValue); + val = defaultValueDouble; + } + + return val; + } + + + public String getErrorInfo() { + verifyConfiguration(); + + return (this.errorDescription == null) ? "-" : this.errorDescription; + } + + + @Override + public void refreshConfiguration() { + verifyConfiguration(); + } + + + public boolean setNotInPreInit() { + this.inPreInit = false; + + return reconfigureService(); + } + + + public double getBasalProfileForHour() { + if (basalsByHour != null) { + GregorianCalendar c = new GregorianCalendar(); + int hour = c.get(Calendar.HOUR_OF_DAY); + + return basalsByHour[hour]; + } + + return 0; + } + + private boolean isLogEnabled() { + return L.isEnabled(L.PUMP); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/events/EventMedtronicDeviceStatusChange.kt b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/events/EventMedtronicDeviceStatusChange.kt new file mode 100644 index 0000000000..37e6649252 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/events/EventMedtronicDeviceStatusChange.kt @@ -0,0 +1,30 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.events + +import info.nightscout.androidaps.events.Event +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkError +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkServiceState +import info.nightscout.androidaps.plugins.pump.medtronic.defs.PumpDeviceState + +class EventMedtronicDeviceStatusChange : Event { + + private var rileyLinkServiceState: RileyLinkServiceState? = null + private var rileyLinkError: RileyLinkError? = null + + private var pumpDeviceState: PumpDeviceState? = null + private var errorDescription: String? = null + + + constructor(rileyLinkServiceState: RileyLinkServiceState?, rileyLinkError: RileyLinkError?) { + this.rileyLinkServiceState = rileyLinkServiceState + this.rileyLinkError = rileyLinkError + } + + constructor(pumpDeviceState: PumpDeviceState?) { + this.pumpDeviceState = pumpDeviceState + } + + constructor(pumpDeviceState: PumpDeviceState?, errorDescription: String?) { + this.pumpDeviceState = pumpDeviceState + this.errorDescription = errorDescription + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/events/EventMedtronicPumpConfigurationChanged.kt b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/events/EventMedtronicPumpConfigurationChanged.kt new file mode 100644 index 0000000000..458c055454 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/events/EventMedtronicPumpConfigurationChanged.kt @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.events + +import info.nightscout.androidaps.events.Event + +class EventMedtronicPumpConfigurationChanged : Event() diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/events/EventMedtronicPumpValuesChanged.kt b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/events/EventMedtronicPumpValuesChanged.kt new file mode 100644 index 0000000000..b314b9db19 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/events/EventMedtronicPumpValuesChanged.kt @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.events + +import info.nightscout.androidaps.events.Event + +class EventMedtronicPumpValuesChanged : Event() diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/events/EventRefreshButtonState.kt b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/events/EventRefreshButtonState.kt new file mode 100644 index 0000000000..81b9af4ff3 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/events/EventRefreshButtonState.kt @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.events + +import info.nightscout.androidaps.events.Event + +class EventRefreshButtonState (val newState : Boolean): Event() \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/service/RileyLinkMedtronicService.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/service/RileyLinkMedtronicService.java new file mode 100644 index 0000000000..cba33353f1 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/service/RileyLinkMedtronicService.java @@ -0,0 +1,205 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.service; + +import android.content.Intent; +import android.content.IntentFilter; +import android.content.res.Configuration; +import android.os.Binder; +import android.os.IBinder; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkCommunicationManager; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkConst; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.RFSpy; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.RileyLinkBLE; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RileyLinkEncodingType; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkServiceState; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkTargetDevice; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.RileyLinkService; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.RileyLinkServiceData; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.ServiceTask; +import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; +import info.nightscout.androidaps.plugins.pump.medtronic.MedtronicPumpPlugin; +import info.nightscout.androidaps.plugins.pump.medtronic.comm.MedtronicCommunicationManager; +import info.nightscout.androidaps.plugins.pump.medtronic.defs.PumpDeviceState; +import info.nightscout.androidaps.plugins.pump.medtronic.driver.MedtronicPumpStatus; +import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicConst; +import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil; +import info.nightscout.androidaps.utils.SP; + +/** + * RileyLinkMedtronicService is intended to stay running when the gui-app is closed. + */ +public class RileyLinkMedtronicService extends RileyLinkService { + + private static final Logger LOG = LoggerFactory.getLogger(L.PUMPCOMM); + + private static RileyLinkMedtronicService instance; + private static ServiceTask currentTask = null; + + // cache of most recently received set of pump history pages. Probably shouldn't be here. + public MedtronicCommunicationManager medtronicCommunicationManager; + MedtronicPumpStatus pumpStatus = null; + private IBinder mBinder = new LocalBinder(); + + + public RileyLinkMedtronicService() { + super(MainApp.instance().getApplicationContext()); + instance = this; + if (isLogEnabled()) + LOG.debug("RileyLinkMedtronicService newly constructed"); + MedtronicUtil.setMedtronicService(this); + pumpStatus = (MedtronicPumpStatus) MedtronicPumpPlugin.getPlugin().getPumpStatusData(); + } + + + public static RileyLinkMedtronicService getInstance() { + return instance; + } + + + public static MedtronicCommunicationManager getCommunicationManager() { + return instance.medtronicCommunicationManager; + } + + + @Override + public void onConfigurationChanged(Configuration newConfig) { + if (isLogEnabled()) + LOG.warn("onConfigurationChanged"); + super.onConfigurationChanged(newConfig); + } + + + @Override + public IBinder onBind(Intent intent) { + return mBinder; + } + + + @Override + public RileyLinkEncodingType getEncoding() { + return RileyLinkEncodingType.FourByteSixByteLocal; + } + + + /** + * If you have customized RileyLinkServiceData you need to override this + */ + public void initRileyLinkServiceData() { + + rileyLinkServiceData = new RileyLinkServiceData(RileyLinkTargetDevice.MedtronicPump); + + RileyLinkUtil.setRileyLinkServiceData(rileyLinkServiceData); + RileyLinkUtil.setTargetDevice(RileyLinkTargetDevice.MedtronicPump); + + setPumpIDString(SP.getString(MedtronicConst.Prefs.PumpSerial, "000000")); + + // get most recently used RileyLink address + rileyLinkServiceData.rileylinkAddress = SP.getString(RileyLinkConst.Prefs.RileyLinkAddress, ""); + + rileyLinkBLE = new RileyLinkBLE(this.context); // or this + rfspy = new RFSpy(rileyLinkBLE); + rfspy.startReader(); + + RileyLinkUtil.setRileyLinkBLE(rileyLinkBLE); + + // init rileyLinkCommunicationManager + medtronicCommunicationManager = new MedtronicCommunicationManager(context, rfspy); + } + + + public void resetRileyLinkConfiguration() { + rfspy.resetRileyLinkConfiguration(); + } + + + @Override + public RileyLinkCommunicationManager getDeviceCommunicationManager() { + return this.medtronicCommunicationManager; + } + + + public void setPumpIDString(String pumpID) { + if (pumpID.length() != 6) { + LOG.error("setPumpIDString: invalid pump id string: " + pumpID); + return; + } + + byte[] pumpIDBytes = ByteUtil.fromHexString(pumpID); + + if (pumpIDBytes == null) { + LOG.error("Invalid pump ID? - PumpID is null."); + + rileyLinkServiceData.setPumpID("000000", new byte[]{0, 0, 0}); + + } else if (pumpIDBytes.length != 3) { + LOG.error("Invalid pump ID? " + ByteUtil.shortHexString(pumpIDBytes)); + + rileyLinkServiceData.setPumpID("000000", new byte[]{0, 0, 0}); + + } else if (pumpID.equals("000000")) { + LOG.error("Using pump ID " + pumpID); + + rileyLinkServiceData.setPumpID(pumpID, new byte[]{0, 0, 0}); + + } else { + LOG.info("Using pump ID " + pumpID); + + String oldId = rileyLinkServiceData.pumpID; + + rileyLinkServiceData.setPumpID(pumpID, pumpIDBytes); + + if (oldId != null && !oldId.equals(pumpID)) { + MedtronicUtil.setMedtronicPumpModel(null); // if we change pumpId, model probably changed too + } + + return; + } + + MedtronicUtil.setPumpDeviceState(PumpDeviceState.InvalidConfiguration); + + // LOG.info("setPumpIDString: saved pumpID " + idString); + } + + public class LocalBinder extends Binder { + + public RileyLinkMedtronicService getServiceInstance() { + return RileyLinkMedtronicService.this; + } + } + + + /* private functions */ + + // PumpInterface - REMOVE + + public boolean isInitialized() { + return RileyLinkServiceState.isReady(RileyLinkUtil.getRileyLinkServiceData().serviceState); + } + + + @Override + public String getDeviceSpecificBroadcastsIdentifierPrefix() { + return null; + } + + + public boolean handleDeviceSpecificBroadcasts(Intent intent) { + return false; + } + + + @Override + public void registerDeviceSpecificBroadcasts(IntentFilter intentFilter) { + } + + + private boolean isLogEnabled() { + return L.isEnabled(L.PUMPCOMM); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/util/MedtronicConst.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/util/MedtronicConst.java new file mode 100644 index 0000000000..fef95087de --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/util/MedtronicConst.java @@ -0,0 +1,38 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.util; + +import info.nightscout.androidaps.R; + +/** + * Created by andy on 5/12/18. + */ + +public class MedtronicConst { + + static final String Prefix = "AAPS.Medtronic."; + + public class Prefs { + public static final int PumpSerial = R.string.key_medtronic_serial; + public static final int PumpType = R.string.key_medtronic_pump_type; + public static final int PumpFrequency = R.string.key_medtronic_frequency; + public static final int MaxBolus = R.string.key_medtronic_max_bolus; + public static final int MaxBasal = R.string.key_medtronic_max_basal; + public static final int BolusDelay = R.string.key_medtronic_bolus_delay; + public static final int Encoding = R.string.key_medtronic_encoding; + public static final int BatteryType = R.string.key_medtronic_battery_type; + public static final int BolusDebugEnabled = R.string.key_medtronic_bolus_debug; + } + + public class Statistics { + + public static final String StatsPrefix = "medtronic_"; + public static final String FirstPumpStart = Prefix + "first_pump_use"; + public static final String LastGoodPumpCommunicationTime = Prefix + "lastGoodPumpCommunicationTime"; + public static final String LastGoodPumpFrequency = Prefix + "LastGoodPumpFrequency"; + public static final String TBRsSet = StatsPrefix + "tbrs_set"; + public static final String StandardBoluses = StatsPrefix + "std_boluses_delivered"; + public static final String SMBBoluses = StatsPrefix + "smb_boluses_delivered"; + public static final String LastPumpHistoryEntry = StatsPrefix + "pump_history_entry"; + public static final String LastPrime = StatsPrefix + "last_sent_prime"; + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/util/MedtronicUtil.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/util/MedtronicUtil.java new file mode 100644 index 0000000000..96bf0a5d44 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/util/MedtronicUtil.java @@ -0,0 +1,537 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.util; + +import android.content.Context; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +import org.joda.time.LocalTime; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.interfaces.PluginType; +import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification; +import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.data.RLHistoryItem; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkTargetDevice; +import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; +import info.nightscout.androidaps.plugins.pump.medtronic.MedtronicPumpPlugin; +import info.nightscout.androidaps.plugins.pump.medtronic.comm.MedtronicCommunicationManager; +import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.ClockDTO; +import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.PumpSettingDTO; +import info.nightscout.androidaps.plugins.pump.medtronic.defs.BatteryType; +import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicCommandType; +import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicDeviceType; +import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicNotificationType; +import info.nightscout.androidaps.plugins.pump.medtronic.defs.PumpDeviceState; +import info.nightscout.androidaps.plugins.pump.medtronic.driver.MedtronicPumpStatus; +import info.nightscout.androidaps.plugins.pump.medtronic.events.EventMedtronicDeviceStatusChange; +import info.nightscout.androidaps.plugins.pump.medtronic.service.RileyLinkMedtronicService; +import info.nightscout.androidaps.utils.OKDialog; + +/** + * Created by andy on 5/9/18. + */ + +public class MedtronicUtil extends RileyLinkUtil { + + private static final Logger LOG = LoggerFactory.getLogger(L.PUMPCOMM); + static int ENVELOPE_SIZE = 4; // 0xA7 S1 S2 S3 CMD PARAM_COUNT [PARAMS] + static int CRC_SIZE = 1; + private static boolean lowLevelDebug = true; + private static PumpDeviceState pumpDeviceState; + private static MedtronicDeviceType medtronicPumpModel; + private static RileyLinkMedtronicService medtronicService; + private static MedtronicPumpStatus medtronicPumpStatus; + private static MedtronicCommandType currentCommand; + private static Map settings; + private static int BIG_FRAME_LENGTH = 65; + private static int doneBit = 1 << 7; + private static ClockDTO pumpTime; + public static Gson gsonInstance = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create(); + public static Gson gsonInstancePretty = new GsonBuilder().excludeFieldsWithoutExposeAnnotation() + .setPrettyPrinting().create(); + private static BatteryType batteryType = BatteryType.None; + + + public static Gson getGsonInstance() { + return gsonInstance; + } + + public static Gson getGsonInstancePretty() { + return gsonInstancePretty; + } + + + public static LocalTime getTimeFrom30MinInterval(int interval) { + if (interval % 2 == 0) { + return new LocalTime(interval / 2, 0); + } else { + return new LocalTime((interval - 1) / 2, 30); + } + } + + + public static int getIntervalFromMinutes(int minutes) { + return minutes / 30; + } + + + public static int makeUnsignedShort(int b2, int b1) { + int k = (b2 & 0xff) << 8 | b1 & 0xff; + return k; + } + + public static boolean isMedtronicPump() { + return MedtronicPumpPlugin.getPlugin().isEnabled(PluginType.PUMP); + //return ConfigBuilderPlugin.getPlugin().getActivePump().deviceID().equals("Medtronic"); + } + + + public static byte[] getByteArrayFromUnsignedShort(int shortValue, boolean returnFixedSize) { + byte highByte = (byte) (shortValue >> 8 & 0xFF); + byte lowByte = (byte) (shortValue & 0xFF); + + if (highByte > 0) { + return createByteArray(highByte, lowByte); + } else { + return returnFixedSize ? createByteArray(highByte, lowByte) : createByteArray(lowByte); + } + + } + + + public static byte[] createByteArray(byte... data) { + return data; + } + + + public static byte[] createByteArray(List data) { + + byte[] array = new byte[data.size()]; + + for (int i = 0; i < data.size(); i++) { + array[i] = data.get(i); + } + + return array; + } + + + public static double decodeBasalInsulin(int i, int j) { + return decodeBasalInsulin(makeUnsignedShort(i, j)); + } + + + public static double decodeBasalInsulin(int i) { + return (double) i / 40.0d; + } + + + public static byte[] getBasalStrokes(double amount) { + return getBasalStrokes(amount, false); + } + + + public static byte[] getBasalStrokes(double amount, boolean returnFixedSize) { + return getStrokes(amount, 40, returnFixedSize); + } + + + public static int getBasalStrokesInt(double amount) { + return getStrokesInt(amount, 40); + } + + + public static byte[] getBolusStrokes(double amount) { + + int strokesPerUnit = medtronicPumpModel.getBolusStrokes(); + + int length; + int scrollRate; + + if (strokesPerUnit >= 40) { + length = 2; + + // 40-stroke pumps scroll faster for higher unit values + + if (amount > 10) + scrollRate = 4; + else if (amount > 1) + scrollRate = 2; + else + scrollRate = 1; + + } else { + length = 1; + scrollRate = 1; + } + + int strokes = (int) (amount * ((strokesPerUnit * 1.0d) / (scrollRate * 1.0d))) * scrollRate; + + byte[] body = ByteUtil.fromHexString(String.format("%02x%0" + (2 * length) + "x", length, strokes)); + + return body; + } + + + public static byte[] createCommandBody(byte[] input) { + + return ByteUtil.concat((byte) input.length, input); + } + + + public static byte[] getStrokes(double amount, int strokesPerUnit, boolean returnFixedSize) { + + int strokes = getStrokesInt(amount, strokesPerUnit); + + return getByteArrayFromUnsignedShort(strokes, returnFixedSize); + + } + + + public static int getStrokesInt(double amount, int strokesPerUnit) { + + int length = 1; + int scrollRate = 1; + + if (strokesPerUnit >= 40) { + length = 2; + + // 40-stroke pumps scroll faster for higher unit values + if (amount > 10) + scrollRate = 4; + else if (amount > 1) + scrollRate = 2; + } + + int strokes = (int) (amount * (strokesPerUnit / (scrollRate * 1.0d))); + + strokes *= scrollRate; + + return strokes; + + } + + + public static void sendNotification(MedtronicNotificationType notificationType) { + Notification notification = new Notification( // + notificationType.getNotificationType(), // + MainApp.gs(notificationType.getResourceId()), // + notificationType.getNotificationUrgency()); + RxBus.INSTANCE.send(new EventNewNotification(notification)); + } + + + public static void sendNotification(MedtronicNotificationType notificationType, Object... parameters) { + Notification notification = new Notification( // + notificationType.getNotificationType(), // + MainApp.gs(notificationType.getResourceId(), parameters), // + notificationType.getNotificationUrgency()); + RxBus.INSTANCE.send(new EventNewNotification(notification)); + } + + + public static void dismissNotification(MedtronicNotificationType notificationType) { + RxBus.INSTANCE.send(new EventDismissNotification(notificationType.getNotificationType())); + } + + +// public static byte[] buildCommandPayload(MessageType commandType, byte[] parameters) { +// return buildCommandPayload(commandType.getValue(), parameters); +// } + + + public static byte[] buildCommandPayload(MedtronicCommandType commandType, byte[] parameters) { + return buildCommandPayload((byte) commandType.commandCode, parameters); + } + + + public static byte[] buildCommandPayload(byte commandType, byte[] parameters) { + // A7 31 65 51 C0 00 52 + + byte commandLength = (byte) (parameters == null ? 2 : 2 + parameters.length); + + ByteBuffer sendPayloadBuffer = ByteBuffer.allocate(ENVELOPE_SIZE + commandLength); // + CRC_SIZE + sendPayloadBuffer.order(ByteOrder.BIG_ENDIAN); + + byte[] serialNumberBCD = RileyLinkUtil.getRileyLinkServiceData().pumpIDBytes; + + sendPayloadBuffer.put((byte) 0xA7); + sendPayloadBuffer.put(serialNumberBCD[0]); + sendPayloadBuffer.put(serialNumberBCD[1]); + sendPayloadBuffer.put(serialNumberBCD[2]); + + sendPayloadBuffer.put(commandType); + + if (parameters == null) { + sendPayloadBuffer.put((byte) 0x00); + } else { + sendPayloadBuffer.put((byte) parameters.length); // size + + for (byte val : parameters) { + sendPayloadBuffer.put(val); + } + } + + byte[] payload = sendPayloadBuffer.array(); + + if (L.isEnabled(L.PUMPCOMM)) + LOG.debug("buildCommandPayload [{}]", ByteUtil.shortHexString(payload)); + + // int crc = computeCRC8WithPolynomial(payload, 0, payload.length - 1); + + // LOG.info("crc: " + crc); + + // sendPayloadBuffer.put((byte) crc); + + return sendPayloadBuffer.array(); + } + + + // Note: at the moment supported only for 24 items, if you will use it for more than + // that you will need to add + public static List> getBasalProfileFrames(byte[] data) { + + boolean done = false; + int start = 0; + int frame = 1; + + List> frames = new ArrayList<>(); + boolean lastFrame = false; + + do { + int frameLength = BIG_FRAME_LENGTH - 1; + + if (start + frameLength > data.length) { + frameLength = data.length - start; + } + + // System.out.println("Framelength: " + frameLength); + + byte[] substring = ByteUtil.substring(data, start, frameLength); + + // System.out.println("Subarray: " + ByteUtil.getCompactString(substring)); + // System.out.println("Subarray Lenths: " + substring.length); + + List frameData = ByteUtil.getListFromByteArray(substring); + + if (isEmptyFrame(frameData)) { + byte b = (byte) frame; + // b |= 0x80; + b |= 0b1000_0000; + // b |= doneBit; + + frameData.add(0, b); + + checkAndAppenLastFrame(frameData); + + lastFrame = true; + + done = true; + } else { + frameData.add(0, (byte) frame); + } + + // System.out.println("Subarray: " + ByteUtil.getCompactString(substring)); + + frames.add(frameData); + + frame++; + start += (BIG_FRAME_LENGTH - 1); + + if (start == data.length) { + done = true; + } + + } while (!done); + + if (!lastFrame) { + List frameData = new ArrayList<>(); + + byte b = (byte) frame; + b |= 0b1000_0000; + // b |= doneBit; + + frameData.add(b); + + checkAndAppenLastFrame(frameData); + } + + return frames; + + } + + + private static void checkAndAppenLastFrame(List frameData) { + + if (frameData.size() == BIG_FRAME_LENGTH) + return; + + int missing = BIG_FRAME_LENGTH - frameData.size(); + + for (int i = 0; i < missing; i++) { + frameData.add((byte) 0x00); + } + } + + + private static boolean isEmptyFrame(List frameData) { + + for (Byte frameDateEntry : frameData) { + if (frameDateEntry != 0x00) { + return false; + } + } + + return true; + } + + + public static boolean isLowLevelDebug() { + return lowLevelDebug; + } + + + public static void setLowLevelDebug(boolean lowLevelDebug) { + MedtronicUtil.lowLevelDebug = lowLevelDebug; + } + + + public static PumpDeviceState getPumpDeviceState() { + return pumpDeviceState; + } + + + public static void setPumpDeviceState(PumpDeviceState pumpDeviceState) { + MedtronicUtil.pumpDeviceState = pumpDeviceState; + + historyRileyLink.add(new RLHistoryItem(pumpDeviceState, RileyLinkTargetDevice.MedtronicPump)); + + RxBus.INSTANCE.send(new EventMedtronicDeviceStatusChange(pumpDeviceState)); + } + + + public static boolean isModelSet() { + return MedtronicUtil.medtronicPumpModel != null; + } + + + public static MedtronicDeviceType getMedtronicPumpModel() { + return MedtronicUtil.medtronicPumpModel; + } + + + public static void setMedtronicPumpModel(MedtronicDeviceType medtronicPumpModel) { + MedtronicUtil.medtronicPumpModel = medtronicPumpModel; + } + + + public static MedtronicCommunicationManager getMedtronicCommunicationManager() { + return (MedtronicCommunicationManager) RileyLinkUtil.rileyLinkCommunicationManager; + } + + + public static RileyLinkMedtronicService getMedtronicService() { + return MedtronicUtil.medtronicService; + } + + + public static void setMedtronicService(RileyLinkMedtronicService medtronicService) { + MedtronicUtil.medtronicService = medtronicService; + } + + + public static MedtronicPumpStatus getPumpStatus() { + return MedtronicUtil.medtronicPumpStatus; + } + + + public static void setPumpStatus(MedtronicPumpStatus medtronicPumpStatus) { + MedtronicUtil.medtronicPumpStatus = medtronicPumpStatus; + } + + + public static MedtronicCommandType getCurrentCommand() { + return MedtronicUtil.currentCommand; + } + + + public static void setCurrentCommand(MedtronicCommandType currentCommand) { + MedtronicUtil.currentCommand = currentCommand; + + if (currentCommand != null) + historyRileyLink.add(new RLHistoryItem(currentCommand)); + + } + + public static int pageNumber; + public static Integer frameNumber; + + + public static void setCurrentCommand(MedtronicCommandType currentCommand, int pageNumber_, Integer frameNumber_) { + pageNumber = pageNumber_; + frameNumber = frameNumber_; + + if (MedtronicUtil.currentCommand != currentCommand) { + setCurrentCommand(currentCommand); + } + + RxBus.INSTANCE.send(new EventMedtronicDeviceStatusChange(pumpDeviceState)); + } + + + public static boolean isSame(Double d1, Double d2) { + double diff = d1 - d2; + + return (Math.abs(diff) <= 0.000001); + } + + + public static Map getSettings() { + return settings; + } + + + public static void setSettings(Map settings) { + MedtronicUtil.settings = settings; + } + + + public static void setPumpTime(ClockDTO pumpTime) { + MedtronicUtil.pumpTime = pumpTime; + } + + + public static ClockDTO getPumpTime() { + return MedtronicUtil.pumpTime; + } + + public static void setBatteryType(BatteryType batteryType) { + MedtronicUtil.batteryType = batteryType; + } + + + public static BatteryType getBatteryType() { + return MedtronicUtil.batteryType; + } + + + public static void displayNotConfiguredDialog(Context context) { + OKDialog.show(context, MainApp.gs(R.string.combo_warning), + MainApp.gs(R.string.medtronic_error_operation_not_possible_no_configuration), null); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/virtual/VirtualPumpFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/pump/virtual/VirtualPumpFragment.kt new file mode 100644 index 0000000000..08402520c2 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/virtual/VirtualPumpFragment.kt @@ -0,0 +1,85 @@ +package info.nightscout.androidaps.plugins.pump.virtual + +import android.os.Bundle +import android.os.Handler +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import info.nightscout.androidaps.MainApp +import info.nightscout.androidaps.R +import info.nightscout.androidaps.events.EventExtendedBolusChange +import info.nightscout.androidaps.events.EventTempBasalChange +import info.nightscout.androidaps.plugins.bus.RxBus +import info.nightscout.androidaps.plugins.pump.virtual.events.EventVirtualPumpUpdateGui +import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin +import info.nightscout.androidaps.utils.FabricPrivacy +import info.nightscout.androidaps.utils.T +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.disposables.CompositeDisposable +import kotlinx.android.synthetic.main.virtualpump_fragment.* +import org.slf4j.LoggerFactory + +class VirtualPumpFragment : Fragment() { + private val disposable = CompositeDisposable() + + private val loopHandler = Handler() + private lateinit var refreshLoop: Runnable + + init { + refreshLoop = Runnable { + activity?.runOnUiThread { updateGui() } + loopHandler.postDelayed(refreshLoop, T.mins(1).msecs()) + } + } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + return inflater.inflate(R.layout.virtualpump_fragment, container, false) + } + + @Synchronized + override fun onResume() { + super.onResume() + disposable.add(RxBus + .toObservable(EventVirtualPumpUpdateGui::class.java) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe({ updateGui() }, { FabricPrivacy.logException(it) }) + ) + disposable.add(RxBus + .toObservable(EventTempBasalChange::class.java) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe({ updateGui() }, { FabricPrivacy.logException(it) }) + ) + disposable.add(RxBus + .toObservable(EventExtendedBolusChange::class.java) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe({ updateGui() }, { FabricPrivacy.logException(it) }) + ) + loopHandler.postDelayed(refreshLoop, T.mins(1).msecs()) + updateGui() + } + + @Synchronized + override fun onPause() { + super.onPause() + disposable.clear() + loopHandler.removeCallbacks(refreshLoop) + } + + @Synchronized + private fun updateGui() { + val virtualPump = VirtualPumpPlugin.getPlugin() + virtualpump_basabasalrate?.text = MainApp.gs(R.string.pump_basebasalrate, virtualPump.baseBasalRate) + virtualpump_tempbasal?.text = TreatmentsPlugin.getPlugin().getTempBasalFromHistory(System.currentTimeMillis())?.toStringFull() + ?: "" + virtualpump_extendedbolus?.text = TreatmentsPlugin.getPlugin().getExtendedBolusFromHistory(System.currentTimeMillis())?.toString() ?: "" + virtualpump_battery?.text = MainApp.gs(R.string.format_percent, virtualPump.batteryPercent) + virtualpump_reservoir?.text = MainApp.gs(R.string.formatinsulinunits, virtualPump.reservoirInUnits.toDouble()) + + virtualPump.refreshConfiguration() + val pumpType = virtualPump.pumpType + + virtualpump_type?.text = pumpType.description + virtualpump_type_def?.text = pumpType.getFullDescription(MainApp.gs(R.string.virtualpump_pump_def), pumpType.hasExtendedBasals()) + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/VirtualPumpPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/virtual/VirtualPumpPlugin.java similarity index 80% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/VirtualPumpPlugin.java rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/virtual/VirtualPumpPlugin.java index 3207791b88..447367c510 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/VirtualPumpPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/virtual/VirtualPumpPlugin.java @@ -1,14 +1,14 @@ -package info.nightscout.androidaps.plugins.PumpVirtual; +package info.nightscout.androidaps.plugins.pump.virtual; import android.os.SystemClock; -import com.squareup.otto.Subscribe; - import org.json.JSONException; import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.List; + import info.nightscout.androidaps.BuildConfig; import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; @@ -26,22 +26,32 @@ import info.nightscout.androidaps.interfaces.PluginType; import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions; -import info.nightscout.androidaps.plugins.NSClientInternal.NSUpload; -import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; -import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress; -import info.nightscout.androidaps.plugins.Overview.notifications.Notification; -import info.nightscout.androidaps.plugins.PumpCommon.defs.PumpType; -import info.nightscout.androidaps.plugins.PumpVirtual.events.EventVirtualPumpUpdateGui; -import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.SP; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.common.ManufacturerType; +import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; +import info.nightscout.androidaps.plugins.general.actions.defs.CustomAction; +import info.nightscout.androidaps.plugins.general.actions.defs.CustomActionType; +import info.nightscout.androidaps.plugins.general.nsclient.NSUpload; +import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress; +import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; +import info.nightscout.androidaps.plugins.pump.common.defs.PumpType; +import info.nightscout.androidaps.plugins.pump.virtual.events.EventVirtualPumpUpdateGui; +import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; +import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.FabricPrivacy; +import info.nightscout.androidaps.utils.InstanceId; +import info.nightscout.androidaps.utils.SP; +import io.reactivex.disposables.CompositeDisposable; +import io.reactivex.schedulers.Schedulers; + /** * Created by mike on 05.08.2016. */ public class VirtualPumpPlugin extends PluginBase implements PumpInterface { private Logger log = LoggerFactory.getLogger(L.PUMP); + private CompositeDisposable disposable = new CompositeDisposable(); Integer batteryPercent = 50; Integer reservoirInUnits = 50; @@ -114,19 +124,21 @@ public class VirtualPumpPlugin extends PluginBase implements PumpInterface { @Override protected void onStart() { super.onStart(); - MainApp.bus().register(this); + disposable.add(RxBus.INSTANCE + .toObservable(EventPreferenceChange.class) + .observeOn(Schedulers.io()) + .subscribe(event -> { + if (event.isChanged(R.string.key_virtualpump_type)) + refreshConfiguration(); + }, FabricPrivacy::logException) + ); refreshConfiguration(); } @Override protected void onStop() { - MainApp.bus().unregister(this); - } - - @Subscribe - public void onStatusEvent(final EventPreferenceChange s) { - if (s.isChanged(R.string.key_virtualpump_type)) - refreshConfiguration(); + disposable.clear(); + super.onStop(); } @Override @@ -140,6 +152,16 @@ public class VirtualPumpPlugin extends PluginBase implements PumpInterface { return new PumpEnactResult(); } + @Override + public List getCustomActions() { + return null; + } + + @Override + public void executeCustomAction(CustomActionType customActionType) { + + } + @Override public boolean isInitialized() { return true; @@ -201,7 +223,7 @@ public class VirtualPumpPlugin extends PluginBase implements PumpInterface { PumpEnactResult result = new PumpEnactResult(); result.success = true; Notification notification = new Notification(Notification.PROFILE_SET_OK, MainApp.gs(R.string.profile_set_ok), Notification.INFO, 60); - MainApp.bus().post(new EventNewNotification(notification)); + RxBus.INSTANCE.send(new EventNewNotification(notification)); return result; } @@ -225,6 +247,16 @@ public class VirtualPumpPlugin extends PluginBase implements PumpInterface { } + @Override + public double getReservoirLevel() { + return reservoirInUnits; + } + + @Override + public int getBatteryLevel() { + return batteryPercent; + } + @Override public PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo) { @@ -239,21 +271,21 @@ public class VirtualPumpPlugin extends PluginBase implements PumpInterface { while (delivering < detailedBolusInfo.insulin) { SystemClock.sleep(200); - EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance(); - bolusingEvent.status = String.format(MainApp.gs(R.string.bolusdelivering), delivering); - bolusingEvent.percent = Math.min((int) (delivering / detailedBolusInfo.insulin * 100), 100); - MainApp.bus().post(bolusingEvent); + EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.INSTANCE; + bolusingEvent.setStatus(String.format(MainApp.gs(R.string.bolusdelivering), delivering)); + bolusingEvent.setPercent(Math.min((int) (delivering / detailedBolusInfo.insulin * 100), 100)); + RxBus.INSTANCE.send(bolusingEvent); delivering += 0.1d; } SystemClock.sleep(200); - EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance(); - bolusingEvent.status = String.format(MainApp.gs(R.string.bolusdelivered), detailedBolusInfo.insulin); - bolusingEvent.percent = 100; - MainApp.bus().post(bolusingEvent); + EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.INSTANCE; + bolusingEvent.setStatus(String.format(MainApp.gs(R.string.bolusdelivered), detailedBolusInfo.insulin)); + bolusingEvent.setPercent(100); + RxBus.INSTANCE.send(bolusingEvent); SystemClock.sleep(1000); if (L.isEnabled(L.PUMPCOMM)) log.debug("Delivering treatment insulin: " + detailedBolusInfo.insulin + "U carbs: " + detailedBolusInfo.carbs + "g " + result); - MainApp.bus().post(new EventVirtualPumpUpdateGui()); + RxBus.INSTANCE.send(new EventVirtualPumpUpdateGui()); lastDataTime = System.currentTimeMillis(); TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, false); return result; @@ -281,7 +313,7 @@ public class VirtualPumpPlugin extends PluginBase implements PumpInterface { TreatmentsPlugin.getPlugin().addToHistoryTempBasal(tempBasal); if (L.isEnabled(L.PUMPCOMM)) log.debug("Setting temp basal absolute: " + result); - MainApp.bus().post(new EventVirtualPumpUpdateGui()); + RxBus.INSTANCE.send(new EventVirtualPumpUpdateGui()); lastDataTime = System.currentTimeMillis(); return result; } @@ -304,7 +336,7 @@ public class VirtualPumpPlugin extends PluginBase implements PumpInterface { TreatmentsPlugin.getPlugin().addToHistoryTempBasal(tempBasal); if (L.isEnabled(L.PUMPCOMM)) log.debug("Settings temp basal percent: " + result); - MainApp.bus().post(new EventVirtualPumpUpdateGui()); + RxBus.INSTANCE.send(new EventVirtualPumpUpdateGui()); lastDataTime = System.currentTimeMillis(); return result; } @@ -329,7 +361,7 @@ public class VirtualPumpPlugin extends PluginBase implements PumpInterface { TreatmentsPlugin.getPlugin().addToHistoryExtendedBolus(extendedBolus); if (L.isEnabled(L.PUMPCOMM)) log.debug("Setting extended bolus: " + result); - MainApp.bus().post(new EventVirtualPumpUpdateGui()); + RxBus.INSTANCE.send(new EventVirtualPumpUpdateGui()); lastDataTime = System.currentTimeMillis(); return result; } @@ -347,7 +379,7 @@ public class VirtualPumpPlugin extends PluginBase implements PumpInterface { //tempBasal = null; if (L.isEnabled(L.PUMPCOMM)) log.debug("Canceling temp basal: " + result); - MainApp.bus().post(new EventVirtualPumpUpdateGui()); + RxBus.INSTANCE.send(new EventVirtualPumpUpdateGui()); } lastDataTime = System.currentTimeMillis(); return result; @@ -367,7 +399,7 @@ public class VirtualPumpPlugin extends PluginBase implements PumpInterface { result.comment = MainApp.gs(R.string.virtualpump_resultok); if (L.isEnabled(L.PUMPCOMM)) log.debug("Canceling extended bolus: " + result); - MainApp.bus().post(new EventVirtualPumpUpdateGui()); + RxBus.INSTANCE.send(new EventVirtualPumpUpdateGui()); lastDataTime = System.currentTimeMillis(); return result; } @@ -416,8 +448,18 @@ public class VirtualPumpPlugin extends PluginBase implements PumpInterface { } @Override - public String deviceID() { - return "VirtualPump"; + public ManufacturerType manufacturer() { + return pumpDescription.pumpType.getManufacturer(); + } + + @Override + public PumpType model() { + return pumpDescription.pumpType; + } + + @Override + public String serialNumber() { + return InstanceId.INSTANCE.instanceId(); } @Override @@ -434,6 +476,11 @@ public class VirtualPumpPlugin extends PluginBase implements PumpInterface { return pumpType; } + @Override + public boolean canHandleDST() { + return true; + } + public void refreshConfiguration() { String pumptype = SP.getString(R.string.key_virtualpump_type, "Generic AAPS"); @@ -455,4 +502,11 @@ public class VirtualPumpPlugin extends PluginBase implements PumpInterface { } -} + + @Override + public void timeDateOrTimeZoneChanged() { + + } + + +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/virtual/events/EventVirtualPumpUpdateGui.kt b/app/src/main/java/info/nightscout/androidaps/plugins/pump/virtual/events/EventVirtualPumpUpdateGui.kt new file mode 100644 index 0000000000..a0498aa14d --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/virtual/events/EventVirtualPumpUpdateGui.kt @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.pump.virtual.events + +import info.nightscout.androidaps.events.EventUpdateGui + +class EventVirtualPumpUpdateGui : EventUpdateGui() \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Sensitivity/AbstractSensitivityPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/sensitivity/AbstractSensitivityPlugin.java similarity index 88% rename from app/src/main/java/info/nightscout/androidaps/plugins/Sensitivity/AbstractSensitivityPlugin.java rename to app/src/main/java/info/nightscout/androidaps/plugins/sensitivity/AbstractSensitivityPlugin.java index 9f72f1b119..6c8a9e8ba5 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Sensitivity/AbstractSensitivityPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/sensitivity/AbstractSensitivityPlugin.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.Sensitivity; +package info.nightscout.androidaps.plugins.sensitivity; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -8,11 +8,11 @@ import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginDescription; import info.nightscout.androidaps.interfaces.SensitivityInterface; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensResult; -import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin; -import info.nightscout.utils.Round; -import info.nightscout.utils.SP; -import info.nightscout.utils.SafeParse; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin; +import info.nightscout.androidaps.utils.Round; +import info.nightscout.androidaps.utils.SP; +import info.nightscout.androidaps.utils.SafeParse; public abstract class AbstractSensitivityPlugin extends PluginBase implements SensitivityInterface { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Sensitivity/SensitivityAAPSPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/sensitivity/SensitivityAAPSPlugin.java similarity index 92% rename from app/src/main/java/info/nightscout/androidaps/plugins/Sensitivity/SensitivityAAPSPlugin.java rename to app/src/main/java/info/nightscout/androidaps/plugins/sensitivity/SensitivityAAPSPlugin.java index 432420df85..dfc4bed25d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Sensitivity/SensitivityAAPSPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/sensitivity/SensitivityAAPSPlugin.java @@ -1,6 +1,6 @@ -package info.nightscout.androidaps.plugins.Sensitivity; +package info.nightscout.androidaps.plugins.sensitivity; -import android.support.v4.util.LongSparseArray; +import androidx.collection.LongSparseArray; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -18,12 +18,12 @@ import info.nightscout.androidaps.db.ProfileSwitch; import info.nightscout.androidaps.interfaces.PluginDescription; import info.nightscout.androidaps.interfaces.PluginType; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions; -import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData; -import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensResult; -import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.SP; +import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensData; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin; +import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.SP; /** * Created by mike on 24.06.2017. diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Sensitivity/SensitivityOref0Plugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/sensitivity/SensitivityOref0Plugin.java similarity index 93% rename from app/src/main/java/info/nightscout/androidaps/plugins/Sensitivity/SensitivityOref0Plugin.java rename to app/src/main/java/info/nightscout/androidaps/plugins/sensitivity/SensitivityOref0Plugin.java index 53a8be8661..cfcaf0eb22 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Sensitivity/SensitivityOref0Plugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/sensitivity/SensitivityOref0Plugin.java @@ -1,6 +1,6 @@ -package info.nightscout.androidaps.plugins.Sensitivity; +package info.nightscout.androidaps.plugins.sensitivity; -import android.support.v4.util.LongSparseArray; +import androidx.collection.LongSparseArray; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -18,11 +18,11 @@ import info.nightscout.androidaps.db.ProfileSwitch; import info.nightscout.androidaps.interfaces.PluginDescription; import info.nightscout.androidaps.interfaces.PluginType; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions; -import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData; -import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensResult; -import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin; -import info.nightscout.utils.DateUtil; +import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensData; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin; +import info.nightscout.androidaps.utils.DateUtil; /** * Created by mike on 24.06.2017. diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Sensitivity/SensitivityOref1Plugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/sensitivity/SensitivityOref1Plugin.java similarity index 92% rename from app/src/main/java/info/nightscout/androidaps/plugins/Sensitivity/SensitivityOref1Plugin.java rename to app/src/main/java/info/nightscout/androidaps/plugins/sensitivity/SensitivityOref1Plugin.java index 7d91c7fc4a..5e0f5d3d85 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Sensitivity/SensitivityOref1Plugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/sensitivity/SensitivityOref1Plugin.java @@ -1,6 +1,6 @@ -package info.nightscout.androidaps.plugins.Sensitivity; +package info.nightscout.androidaps.plugins.sensitivity; -import android.support.v4.util.LongSparseArray; +import androidx.collection.LongSparseArray; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -18,11 +18,11 @@ import info.nightscout.androidaps.db.ProfileSwitch; import info.nightscout.androidaps.interfaces.PluginDescription; import info.nightscout.androidaps.interfaces.PluginType; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions; -import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData; -import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensResult; -import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin; -import info.nightscout.utils.DateUtil; +import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensData; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin; +import info.nightscout.androidaps.utils.DateUtil; /** * Created by mike on 19.06.2018. @@ -134,7 +134,7 @@ public class SensitivityOref1Plugin extends AbstractSensitivityPlugin { if (L.isEnabled(L.AUTOSENS)) log.debug("Using most recent " + deviationsArray.size() + " deviations"); if (deviationsArray.size() < 96) { - int pad = Math.round((1 - deviationsArray.size() / 96) * 18); + int pad = (int) Math.round((1 - (double) deviationsArray.size() / 96) * 18); if (L.isEnabled(L.AUTOSENS)) log.debug("Adding " + pad + " more zero deviations"); for (int d = 0; d < pad; d++) { @@ -156,7 +156,7 @@ public class SensitivityOref1Plugin extends AbstractSensitivityPlugin { log.debug("Records: " + index + " " + pastSensitivity); Arrays.sort(deviations); - + /* Not used in calculation for (double i = 0.9; i > 0.1; i = i - 0.01) { if (IobCobCalculatorPlugin.percentile(deviations, (i + 0.01)) >= 0 && IobCobCalculatorPlugin.percentile(deviations, i) < 0) { if (L.isEnabled(L.AUTOSENS)) @@ -164,9 +164,10 @@ public class SensitivityOref1Plugin extends AbstractSensitivityPlugin { } if (IobCobCalculatorPlugin.percentile(deviations, (i + 0.01)) > 0 && IobCobCalculatorPlugin.percentile(deviations, i) <= 0) { if (L.isEnabled(L.AUTOSENS)) - log.debug(Math.round(100 * i) + "% of non-meal deviations negative (>50% = resistance)"); + log.debug(Math.round(100 * i) + "% of non-meal deviations positive (>50% = resistance)"); } } + */ double pSensitive = IobCobCalculatorPlugin.percentile(deviations, 0.50); double pResistant = IobCobCalculatorPlugin.percentile(deviations, 0.50); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Sensitivity/SensitivityWeightedAveragePlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/sensitivity/SensitivityWeightedAveragePlugin.java similarity index 93% rename from app/src/main/java/info/nightscout/androidaps/plugins/Sensitivity/SensitivityWeightedAveragePlugin.java rename to app/src/main/java/info/nightscout/androidaps/plugins/sensitivity/SensitivityWeightedAveragePlugin.java index 2aeb26bd1a..91b69162bb 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Sensitivity/SensitivityWeightedAveragePlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/sensitivity/SensitivityWeightedAveragePlugin.java @@ -1,6 +1,6 @@ -package info.nightscout.androidaps.plugins.Sensitivity; +package info.nightscout.androidaps.plugins.sensitivity; -import android.support.v4.util.LongSparseArray; +import androidx.collection.LongSparseArray; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -16,12 +16,12 @@ import info.nightscout.androidaps.db.ProfileSwitch; import info.nightscout.androidaps.interfaces.PluginDescription; import info.nightscout.androidaps.interfaces.PluginType; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions; -import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData; -import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensResult; -import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.SP; +import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensData; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin; +import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.SP; /** * Created by mike on 24.06.2017. diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Source/BGSourceFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/source/BGSourceFragment.java similarity index 78% rename from app/src/main/java/info/nightscout/androidaps/plugins/Source/BGSourceFragment.java rename to app/src/main/java/info/nightscout/androidaps/plugins/source/BGSourceFragment.java index 5c084eac29..6023d70d12 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Source/BGSourceFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/BGSourceFragment.java @@ -1,19 +1,18 @@ -package info.nightscout.androidaps.plugins.Source; +package info.nightscout.androidaps.plugins.source; -import android.app.Activity; import android.content.DialogInterface; import android.graphics.Paint; import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.v7.app.AlertDialog; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; -import com.squareup.otto.Subscribe; +import androidx.annotation.NonNull; +import androidx.appcompat.app.AlertDialog; +import androidx.fragment.app.Fragment; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; import java.util.List; @@ -21,19 +20,22 @@ import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.db.BgReading; -import info.nightscout.androidaps.events.EventNewBG; -import info.nightscout.androidaps.plugins.Common.SubscriberFragment; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.NSClientInternal.NSUpload; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.FabricPrivacy; -import info.nightscout.utils.T; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.general.nsclient.NSUpload; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutosensCalculationFinished; +import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.FabricPrivacy; +import info.nightscout.androidaps.utils.T; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.CompositeDisposable; /** * Created by mike on 16.10.2017. */ -public class BGSourceFragment extends SubscriberFragment { +public class BGSourceFragment extends Fragment { + private CompositeDisposable disposable = new CompositeDisposable(); RecyclerView recyclerView; String units = Constants.MGDL; @@ -66,19 +68,25 @@ public class BGSourceFragment extends SubscriberFragment { return null; } - @Subscribe - public void onStatusEvent(final EventNewBG unused) { - updateGUI(); + @Override + public synchronized void onResume() { + super.onResume(); + disposable.add(RxBus.INSTANCE + .toObservable(EventAutosensCalculationFinished.class) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(event -> updateGUI(), FabricPrivacy::logException) + ); } @Override + public synchronized void onPause() { + disposable.clear(); + super.onPause(); + } + protected void updateGUI() { - Activity activity = getActivity(); - if (activity != null) - activity.runOnUiThread(() -> { - long now = System.currentTimeMillis(); - recyclerView.swapAdapter(new RecyclerViewAdapter(MainApp.getDbHelper().getAllBgreadingsDataFromTime(now - MILLS_TO_THE_PAST, false)), true); - }); + long now = System.currentTimeMillis(); + recyclerView.swapAdapter(new RecyclerViewAdapter(MainApp.getDbHelper().getAllBgreadingsDataFromTime(now - MILLS_TO_THE_PAST, false)), true); } public class RecyclerViewAdapter extends RecyclerView.Adapter { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/SourceDexcomPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/SourceDexcomPlugin.kt new file mode 100644 index 0000000000..dfbe2fff39 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/SourceDexcomPlugin.kt @@ -0,0 +1,110 @@ +package info.nightscout.androidaps.plugins.source + +import android.content.Intent +import android.content.pm.PackageManager +import androidx.core.content.ContextCompat +import info.nightscout.androidaps.Constants +import info.nightscout.androidaps.MainApp +import info.nightscout.androidaps.R +import info.nightscout.androidaps.activities.RequestDexcomPermissionActivity +import info.nightscout.androidaps.db.BgReading +import info.nightscout.androidaps.db.CareportalEvent +import info.nightscout.androidaps.interfaces.BgSourceInterface +import info.nightscout.androidaps.interfaces.PluginBase +import info.nightscout.androidaps.interfaces.PluginDescription +import info.nightscout.androidaps.interfaces.PluginType +import info.nightscout.androidaps.logging.L +import info.nightscout.androidaps.plugins.general.nsclient.NSUpload +import info.nightscout.androidaps.utils.DateUtil +import info.nightscout.androidaps.utils.SP +import org.json.JSONObject +import org.slf4j.LoggerFactory + +object SourceDexcomPlugin : PluginBase(PluginDescription() + .mainType(PluginType.BGSOURCE) + .fragmentClass(BGSourceFragment::class.java.name) + .pluginName(R.string.dexcom_app_patched) + .shortName(R.string.dexcom_short) + .preferencesId(R.xml.pref_bgsource) + .description(R.string.description_source_dexcom)), BgSourceInterface { + + private val log = LoggerFactory.getLogger(L.BGSOURCE) + + private val PACKAGE_NAMES = arrayOf("com.dexcom.cgm.region1.mgdl", "com.dexcom.cgm.region1.mmol", + "com.dexcom.cgm.region2.mgdl", "com.dexcom.cgm.region2.mmol", + "com.dexcom.g6.region1.mmol", "com.dexcom.g6.region2.mgdl", + "com.dexcom.g6.region3.mgdl", "com.dexcom.g6.region3.mmol") + + const val PERMISSION = "com.dexcom.cgm.EXTERNAL_PERMISSION" + + override fun advancedFilteringSupported(): Boolean { + return true + } + + override fun onStart() { + super.onStart() + if (ContextCompat.checkSelfPermission(MainApp.instance(), PERMISSION) != PackageManager.PERMISSION_GRANTED) { + val intent = Intent(MainApp.instance(), RequestDexcomPermissionActivity::class.java) + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + MainApp.instance().startActivity(intent) + } + } + + fun findDexcomPackageName(): String? { + val packageManager = MainApp.instance().packageManager; + for (packageInfo in packageManager.getInstalledPackages(0)) { + if (PACKAGE_NAMES.contains(packageInfo.packageName)) return packageInfo.packageName + } + return null + } + + override fun handleNewData(intent: Intent) { + if (!isEnabled(PluginType.BGSOURCE)) return + try { + val sensorType = intent.getStringExtra("sensorType") ?: "" + val glucoseValues = intent.getBundleExtra("glucoseValues") + for (i in 0 until glucoseValues.size()) { + val glucoseValue = glucoseValues.getBundle(i.toString()) + val bgReading = BgReading() + bgReading.value = glucoseValue!!.getInt("glucoseValue").toDouble() + bgReading.direction = glucoseValue.getString("trendArrow") + bgReading.date = glucoseValue.getLong("timestamp") * 1000 + bgReading.raw = 0.0 + if (MainApp.getDbHelper().createIfNotExists(bgReading, "Dexcom$sensorType")) { + if (SP.getBoolean(R.string.key_dexcomg5_nsupload, false)) { + NSUpload.uploadBg(bgReading, "AndroidAPS-Dexcom$sensorType") + } + if (SP.getBoolean(R.string.key_dexcomg5_xdripupload, false)) { + NSUpload.sendToXdrip(bgReading) + } + } + } + val meters = intent.getBundleExtra("meters") + for (i in 0 until meters.size()) { + val meter = meters.getBundle(i.toString()) + val timestamp = meter!!.getLong("timestamp") * 1000 + if (MainApp.getDbHelper().getCareportalEventFromTimestamp(timestamp) != null) continue + val jsonObject = JSONObject() + jsonObject.put("enteredBy", "AndroidAPS-Dexcom$sensorType") + jsonObject.put("created_at", DateUtil.toISOString(timestamp)) + jsonObject.put("eventType", CareportalEvent.BGCHECK) + jsonObject.put("glucoseType", "Finger") + jsonObject.put("glucose", meter.getInt("meterValue")) + jsonObject.put("units", Constants.MGDL) + NSUpload.uploadCareportalEntryToNS(jsonObject) + } + if (SP.getBoolean(R.string.key_dexcom_lognssensorchange, false) && intent.hasExtra("sensorInsertionTime")) { + val sensorInsertionTime = intent.extras!!.getLong("sensorInsertionTime") * 1000 + if (MainApp.getDbHelper().getCareportalEventFromTimestamp(sensorInsertionTime) == null) { + val jsonObject = JSONObject() + jsonObject.put("enteredBy", "AndroidAPS-Dexcom$sensorType") + jsonObject.put("created_at", DateUtil.toISOString(sensorInsertionTime)) + jsonObject.put("eventType", CareportalEvent.SENSORCHANGE) + NSUpload.uploadCareportalEntryToNS(jsonObject) + } + } + } catch (e: Exception) { + log.error("Error while processing intent from Dexcom App", e) + } + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/SourceEversensePlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/source/SourceEversensePlugin.java new file mode 100644 index 0000000000..6f39e3d762 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/SourceEversensePlugin.java @@ -0,0 +1,154 @@ +package info.nightscout.androidaps.plugins.source; + +import android.content.Intent; +import android.os.Bundle; + +import org.json.JSONException; +import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Arrays; + +import info.nightscout.androidaps.Constants; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.db.BgReading; +import info.nightscout.androidaps.db.CareportalEvent; +import info.nightscout.androidaps.interfaces.BgSourceInterface; +import info.nightscout.androidaps.interfaces.PluginBase; +import info.nightscout.androidaps.interfaces.PluginDescription; +import info.nightscout.androidaps.interfaces.PluginType; +import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.general.nsclient.NSUpload; +import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.SP; + +/** + * Created by mike on 28.11.2017. + */ + +public class SourceEversensePlugin extends PluginBase implements BgSourceInterface { + private static Logger log = LoggerFactory.getLogger(L.BGSOURCE); + + private static SourceEversensePlugin plugin = null; + + public static SourceEversensePlugin getPlugin() { + if (plugin == null) + plugin = new SourceEversensePlugin(); + return plugin; + } + + private SourceEversensePlugin() { + super(new PluginDescription() + .mainType(PluginType.BGSOURCE) + .fragmentClass(BGSourceFragment.class.getName()) + .pluginName(R.string.eversense) + .shortName(R.string.eversense_shortname) + .preferencesId(R.xml.pref_poctech) + .description(R.string.description_source_eversense) + ); + } + + @Override + public boolean advancedFilteringSupported() { + return false; + } + + @Override + public void handleNewData(Intent intent) { + + if (!isEnabled(PluginType.BGSOURCE)) return; + + Bundle bundle = intent.getExtras(); + if (bundle == null) return; + + if (L.isEnabled(L.BGSOURCE)) { + if (bundle.containsKey("currentCalibrationPhase")) + log.debug("currentCalibrationPhase: " + bundle.getString("currentCalibrationPhase")); + if (bundle.containsKey("placementModeInProgress")) + log.debug("placementModeInProgress: " + bundle.getBoolean("placementModeInProgress")); + if (bundle.containsKey("glucoseLevel")) + log.debug("glucoseLevel: " + bundle.getInt("glucoseLevel")); + if (bundle.containsKey("glucoseTrendDirection")) + log.debug("glucoseTrendDirection: " + bundle.getString("glucoseTrendDirection")); + if (bundle.containsKey("glucoseTimestamp")) + log.debug("glucoseTimestamp: " + DateUtil.dateAndTimeFullString(bundle.getLong("glucoseTimestamp"))); + if (bundle.containsKey("batteryLevel")) + log.debug("batteryLevel: " + bundle.getString("batteryLevel")); + if (bundle.containsKey("signalStrength")) + log.debug("signalStrength: " + bundle.getString("signalStrength")); + if (bundle.containsKey("transmitterVersionNumber")) + log.debug("transmitterVersionNumber: " + bundle.getString("transmitterVersionNumber")); + if (bundle.containsKey("isXLVersion")) + log.debug("isXLVersion: " + bundle.getBoolean("isXLVersion")); + if (bundle.containsKey("transmitterModelNumber")) + log.debug("transmitterModelNumber: " + bundle.getString("transmitterModelNumber")); + if (bundle.containsKey("transmitterSerialNumber")) + log.debug("transmitterSerialNumber: " + bundle.getString("transmitterSerialNumber")); + if (bundle.containsKey("transmitterAddress")) + log.debug("transmitterAddress: " + bundle.getString("transmitterAddress")); + if (bundle.containsKey("sensorInsertionTimestamp")) + log.debug("sensorInsertionTimestamp: " + DateUtil.dateAndTimeFullString(bundle.getLong("sensorInsertionTimestamp"))); + if (bundle.containsKey("transmitterVersionNumber")) + log.debug("transmitterVersionNumber: " + bundle.getString("transmitterVersionNumber")); + if (bundle.containsKey("transmitterConnectionState")) + log.debug("transmitterConnectionState: " + bundle.getString("transmitterConnectionState")); + } + + if (bundle.containsKey("glucoseLevels")) { + int[] glucoseLevels = bundle.getIntArray("glucoseLevels"); + int[] glucoseRecordNumbers = bundle.getIntArray("glucoseRecordNumbers"); + long[] glucoseTimestamps = bundle.getLongArray("glucoseTimestamps"); + + if (L.isEnabled(L.BGSOURCE)) { + log.debug("glucoseLevels", Arrays.toString(glucoseLevels)); + log.debug("glucoseRecordNumbers", Arrays.toString(glucoseRecordNumbers)); + log.debug("glucoseTimestamps", Arrays.toString(glucoseTimestamps)); + } + + for (int i = 0; i < glucoseLevels.length; i++) { + BgReading bgReading = new BgReading(); + bgReading.value = glucoseLevels[i]; + bgReading.date = glucoseTimestamps[i]; + bgReading.raw = 0; + boolean isNew = MainApp.getDbHelper().createIfNotExists(bgReading, "Eversense"); + if (isNew && SP.getBoolean(R.string.key_dexcomg5_nsupload, false)) { + NSUpload.uploadBg(bgReading, "AndroidAPS-Eversense"); + } + if (isNew && SP.getBoolean(R.string.key_dexcomg5_xdripupload, false)) { + NSUpload.sendToXdrip(bgReading); + } + } + } + + if (bundle.containsKey("calibrationGlucoseLevels")) { + int[] calibrationGlucoseLevels = bundle.getIntArray("calibrationGlucoseLevels"); + long[] calibrationTimestamps = bundle.getLongArray("calibrationTimestamps"); + long[] calibrationRecordNumbers = bundle.getLongArray("calibrationRecordNumbers"); + + if (L.isEnabled(L.BGSOURCE)) { + log.debug("calibrationGlucoseLevels", Arrays.toString(calibrationGlucoseLevels)); + log.debug("calibrationTimestamps", Arrays.toString(calibrationTimestamps)); + log.debug("calibrationRecordNumbers", Arrays.toString(calibrationRecordNumbers)); + } + + for (int i = 0; i < calibrationGlucoseLevels.length; i++) { + try { + if (MainApp.getDbHelper().getCareportalEventFromTimestamp(calibrationTimestamps[i]) == null) { + JSONObject data = new JSONObject(); + data.put("enteredBy", "AndroidAPS-Eversense"); + data.put("created_at", DateUtil.toISOString(calibrationTimestamps[i])); + data.put("eventType", CareportalEvent.BGCHECK); + data.put("glucoseType", "Finger"); + data.put("glucose", calibrationGlucoseLevels[i]); + data.put("units", Constants.MGDL); + NSUpload.uploadCareportalEntryToNS(data); + } + } catch (JSONException e) { + log.error("Unhandled exception", e); + } + } + } + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Source/SourceGlimpPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/source/SourceGlimpPlugin.java similarity index 97% rename from app/src/main/java/info/nightscout/androidaps/plugins/Source/SourceGlimpPlugin.java rename to app/src/main/java/info/nightscout/androidaps/plugins/source/SourceGlimpPlugin.java index 07fdba51ee..243fe60070 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Source/SourceGlimpPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/SourceGlimpPlugin.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.Source; +package info.nightscout.androidaps.plugins.source; import android.content.Intent; import android.os.Bundle; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Source/SourceMM640gPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/source/SourceMM640gPlugin.java similarity index 98% rename from app/src/main/java/info/nightscout/androidaps/plugins/Source/SourceMM640gPlugin.java rename to app/src/main/java/info/nightscout/androidaps/plugins/source/SourceMM640gPlugin.java index 8bc6811ef4..daccbcedd7 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Source/SourceMM640gPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/SourceMM640gPlugin.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.Source; +package info.nightscout.androidaps.plugins.source; import android.content.Intent; import android.os.Bundle; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Source/SourceNSClientPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/source/SourceNSClientPlugin.java similarity index 87% rename from app/src/main/java/info/nightscout/androidaps/plugins/Source/SourceNSClientPlugin.java rename to app/src/main/java/info/nightscout/androidaps/plugins/source/SourceNSClientPlugin.java index de110edd4e..dd0a2c5e88 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Source/SourceNSClientPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/SourceNSClientPlugin.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.Source; +package info.nightscout.androidaps.plugins.source; import android.content.Intent; import android.os.Bundle; @@ -8,7 +8,6 @@ import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.db.BgReading; @@ -17,10 +16,9 @@ import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginDescription; import info.nightscout.androidaps.interfaces.PluginType; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConstraintsObjectives.ObjectivesPlugin; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSgv; -import info.nightscout.utils.JsonHelper; -import info.nightscout.utils.SP; +import info.nightscout.androidaps.plugins.general.nsclient.data.NSSgv; +import info.nightscout.androidaps.utils.JsonHelper; +import info.nightscout.androidaps.utils.SP; /** * Created by mike on 05.08.2016. @@ -86,8 +84,7 @@ public class SourceNSClientPlugin extends PluginBase implements BgSourceInterfac } // Objectives 0 - ObjectivesPlugin.getPlugin().bgIsAvailableInNS = true; - ObjectivesPlugin.getPlugin().saveProgress(); + SP.putBoolean(R.string.key_ObjectivesbgIsAvailableInNS, true); } private void storeSgv(JSONObject sgvJson) { @@ -99,7 +96,7 @@ public class SourceNSClientPlugin extends PluginBase implements BgSourceInterfac public void detectSource(String source, long timeStamp) { if (timeStamp > lastBGTimeStamp) { - if (source.contains("G5 Native") || source.contains("G6 Native") || source.contains("AndroidAPS-DexcomG5")) + if (source.contains("G5 Native") || source.contains("G6 Native") || source.contains("AndroidAPS-DexcomG5") || source.contains("AndroidAPS-DexcomG6")) isAdvancedFilteringEnabled = true; else isAdvancedFilteringEnabled = false; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Source/SourcePoctechPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/source/SourcePoctechPlugin.java similarity index 91% rename from app/src/main/java/info/nightscout/androidaps/plugins/Source/SourcePoctechPlugin.java rename to app/src/main/java/info/nightscout/androidaps/plugins/source/SourcePoctechPlugin.java index df390522d3..ceecfb844f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Source/SourcePoctechPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/SourcePoctechPlugin.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.Source; +package info.nightscout.androidaps.plugins.source; import android.content.Intent; import android.os.Bundle; @@ -9,7 +9,6 @@ import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; @@ -19,9 +18,9 @@ import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginDescription; import info.nightscout.androidaps.interfaces.PluginType; import info.nightscout.androidaps.logging.L; -import info.nightscout.utils.JsonHelper; -import info.nightscout.androidaps.plugins.NSClientInternal.NSUpload; -import info.nightscout.utils.SP; +import info.nightscout.androidaps.utils.JsonHelper; +import info.nightscout.androidaps.plugins.general.nsclient.NSUpload; +import info.nightscout.androidaps.utils.SP; /** * Created by mike on 05.08.2016. @@ -80,7 +79,7 @@ public class SourcePoctechPlugin extends PluginBase implements BgSourceInterface bgReading.value = bgReading.value * Constants.MMOLL_TO_MGDL; boolean isNew = MainApp.getDbHelper().createIfNotExists(bgReading, "Poctech"); if (isNew && SP.getBoolean(R.string.key_dexcomg5_nsupload, false)) { - NSUpload.uploadBg(bgReading); + NSUpload.uploadBg(bgReading, "AndroidAPS-Poctech"); } if (isNew && SP.getBoolean(R.string.key_dexcomg5_xdripupload, false)) { NSUpload.sendToXdrip(bgReading); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/SourceTomatoPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/source/SourceTomatoPlugin.java new file mode 100644 index 0000000000..211ec9a5a2 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/SourceTomatoPlugin.java @@ -0,0 +1,74 @@ +package info.nightscout.androidaps.plugins.source; + +import android.content.Intent; +import android.os.Bundle; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.db.BgReading; +import info.nightscout.androidaps.interfaces.BgSourceInterface; +import info.nightscout.androidaps.interfaces.PluginBase; +import info.nightscout.androidaps.interfaces.PluginDescription; +import info.nightscout.androidaps.interfaces.PluginType; +import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.general.nsclient.NSUpload; +import info.nightscout.androidaps.utils.SP; + +/** + * Created by mike on 05.08.2016. + */ +public class SourceTomatoPlugin extends PluginBase implements BgSourceInterface { + private static Logger log = LoggerFactory.getLogger(L.BGSOURCE); + + private static SourceTomatoPlugin plugin = null; + + public static SourceTomatoPlugin getPlugin() { + if (plugin == null) + plugin = new SourceTomatoPlugin(); + return plugin; + } + + private SourceTomatoPlugin() { + super(new PluginDescription() + .mainType(PluginType.BGSOURCE) + .fragmentClass(BGSourceFragment.class.getName()) + .pluginName(R.string.tomato) + .preferencesId(R.xml.pref_poctech) + .shortName(R.string.tomato_short) + .description(R.string.description_source_tomato) + ); + } + + @Override + public boolean advancedFilteringSupported() { + return false; + } + + @Override + public void handleNewData(Intent intent) { + + if (!isEnabled(PluginType.BGSOURCE)) return; + + Bundle bundle = intent.getExtras(); + if (bundle == null) return; + + BgReading bgReading = new BgReading(); + + if (L.isEnabled(L.BGSOURCE)) + log.debug("Received Tomato Data"); + + bgReading.value = bundle.getDouble("com.fanqies.tomatofn.Extras.BgEstimate"); + bgReading.date = bundle.getLong("com.fanqies.tomatofn.Extras.Time"); + boolean isNew = MainApp.getDbHelper().createIfNotExists(bgReading, "Tomato"); + if (isNew && SP.getBoolean(R.string.key_dexcomg5_nsupload, false)) { + NSUpload.uploadBg(bgReading, "AndroidAPS-Tomato"); + } + if (isNew && SP.getBoolean(R.string.key_dexcomg5_xdripupload, false)) { + NSUpload.sendToXdrip(bgReading); + } + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Source/SourceXdripPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/source/SourceXdripPlugin.java similarity index 98% rename from app/src/main/java/info/nightscout/androidaps/plugins/Source/SourceXdripPlugin.java rename to app/src/main/java/info/nightscout/androidaps/plugins/source/SourceXdripPlugin.java index a81bad41f4..1acefa724e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Source/SourceXdripPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/SourceXdripPlugin.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.Source; +package info.nightscout.androidaps.plugins.source; import android.content.Intent; import android.os.Bundle; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/CarbsGenerator.java b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/CarbsGenerator.java similarity index 88% rename from app/src/main/java/info/nightscout/androidaps/plugins/Treatments/CarbsGenerator.java rename to app/src/main/java/info/nightscout/androidaps/plugins/treatments/CarbsGenerator.java index 9eae9b9d07..0e7215b368 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/CarbsGenerator.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/CarbsGenerator.java @@ -1,19 +1,19 @@ -package info.nightscout.androidaps.plugins.Treatments; +package info.nightscout.androidaps.plugins.treatments; import android.content.Intent; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.db.CareportalEvent; import info.nightscout.androidaps.db.Source; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.Overview.Dialogs.ErrorHelperActivity; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.general.overview.dialogs.ErrorHelperActivity; import info.nightscout.androidaps.queue.Callback; -import info.nightscout.utils.T; +import info.nightscout.androidaps.utils.T; -import static info.nightscout.utils.DateUtil.now; +import static info.nightscout.androidaps.utils.DateUtil.now; public class CarbsGenerator { public static void generateCarbs(int amount, long startTime, int duration, @Nullable String notes) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/Treatment.java b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/Treatment.java similarity index 73% rename from app/src/main/java/info/nightscout/androidaps/plugins/Treatments/Treatment.java rename to app/src/main/java/info/nightscout/androidaps/plugins/treatments/Treatment.java index bd3526c043..19b41a0944 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/Treatment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/Treatment.java @@ -1,15 +1,13 @@ -package info.nightscout.androidaps.plugins.Treatments; +package info.nightscout.androidaps.plugins.treatments; import android.graphics.Color; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.j256.ormlite.field.DatabaseField; import com.j256.ormlite.table.DatabaseTable; import org.json.JSONException; import org.json.JSONObject; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import java.util.Date; import java.util.Objects; @@ -18,19 +16,21 @@ import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.data.Iob; -import info.nightscout.androidaps.db.DatabaseHelper; +import info.nightscout.androidaps.db.DbObjectBase; +import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.interfaces.InsulinInterface; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.Overview.OverviewPlugin; -import info.nightscout.androidaps.plugins.Overview.graphExtensions.DataPointWithLabelInterface; -import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLabelGraphSeries; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.DecimalFormatter; -import info.nightscout.utils.JsonHelper; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; +import info.nightscout.androidaps.plugins.general.overview.OverviewPlugin; +import info.nightscout.androidaps.plugins.general.overview.graphExtensions.DataPointWithLabelInterface; +import info.nightscout.androidaps.plugins.general.overview.graphExtensions.PointsWithLabelGraphSeries; +import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.DecimalFormatter; +import info.nightscout.androidaps.utils.JsonHelper; @DatabaseTable(tableName = Treatment.TABLE_TREATMENTS) -public class Treatment implements DataPointWithLabelInterface { +public class Treatment implements DataPointWithLabelInterface, DbObjectBase { public static final String TABLE_TREATMENTS = "Treatments"; @DatabaseField(id = true) @@ -104,15 +104,16 @@ public class Treatment implements DataPointWithLabelInterface { ", insulin= " + insulin + ", carbs= " + carbs + ", mealBolus= " + mealBolus + + ", source= " + source + "}"; } public boolean isDataChanging(Treatment other) { if (date != other.date) return true; - if (insulin != other.insulin) + if (!isSame(insulin, other.insulin)) return true; - if (carbs != other.carbs) + if (!isSame(carbs, other.carbs)) return true; return false; } @@ -120,9 +121,9 @@ public class Treatment implements DataPointWithLabelInterface { public boolean isEqual(Treatment other) { if (date != other.date) return false; - if (insulin != other.insulin) + if (!isSame(insulin, other.insulin)) return false; - if (carbs != other.carbs) + if (!isSame(carbs, other.carbs)) return false; if (mealBolus != other.mealBolus) return false; @@ -135,16 +136,47 @@ public class Treatment implements DataPointWithLabelInterface { return true; } + public boolean isEqualWithoutPumpId(Treatment other) { + if (date != other.date) + return false; + if (!isSame(insulin, other.insulin)) + return false; + if (!isSame(carbs, other.carbs)) + return false; + if (mealBolus != other.mealBolus) + return false; + if (isSMB != other.isSMB) + return false; + if (!Objects.equals(_id, other._id)) + return false; + return true; + } + + public boolean isSame(Double d1, Double d2) { + double diff = d1 - d2; + + return (Math.abs(diff) <= 0.000001); + } + @Nullable public JSONObject getBoluscalc() { try { if (boluscalc != null) - return new JSONObject(boluscalc); + return new JSONObject(boluscalc); } catch (JSONException ignored) { } return null; } + public double getIc() { + JSONObject bw = getBoluscalc(); + if (bw == null || !bw.has("ic")) { + Profile profile = ProfileFunctions.getInstance().getProfile(date); + return profile.getIc(date); + } + return JsonHelper.safeGetDouble(bw, "ic"); + } + /* * mealBolus, _id and isSMB cannot be known coming from pump. Only compare rest * TODO: remove debug toasts @@ -153,12 +185,13 @@ public class Treatment implements DataPointWithLabelInterface { if (date != other.date) { return false; } - if (insulin != other.insulin) { + + if (!isSame(insulin, other.insulin)) return false; - } - if (carbs != other.carbs) { + + if (!isSame(carbs, other.carbs)) return false; - } + return true; } @@ -191,7 +224,7 @@ public class Treatment implements DataPointWithLabelInterface { @Override public double getY() { - return isSMB ? OverviewPlugin.getPlugin().determineLowLine() : yValue; + return isSMB ? OverviewPlugin.INSTANCE.determineLowLine() : yValue; } @Override @@ -245,4 +278,14 @@ public class Treatment implements DataPointWithLabelInterface { InsulinInterface insulinInterface = ConfigBuilderPlugin.getPlugin().getActiveInsulin(); return insulinInterface.iobCalcForTreatment(this, time, dia); } -} + + @Override + public long getDate() { + return this.date; + } + + @Override + public long getPumpId() { + return this.pumpId; + } +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentService.java b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/TreatmentService.java similarity index 68% rename from app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentService.java rename to app/src/main/java/info/nightscout/androidaps/plugins/treatments/TreatmentService.java index 8c01db13fd..7123b6c96b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/TreatmentService.java @@ -1,8 +1,9 @@ -package info.nightscout.androidaps.plugins.Treatments; +package info.nightscout.androidaps.plugins.treatments; import android.content.Intent; import android.os.IBinder; -import android.support.annotation.Nullable; + +import androidx.annotation.Nullable; import com.j256.ormlite.android.apptools.OpenHelperManager; import com.j256.ormlite.android.apptools.OrmLiteBaseService; @@ -13,9 +14,8 @@ import com.j256.ormlite.stmt.QueryBuilder; import com.j256.ormlite.stmt.Where; import com.j256.ormlite.support.ConnectionSource; import com.j256.ormlite.table.TableUtils; -import com.squareup.otto.Subscribe; -import org.json.JSONArray; +import org.apache.commons.lang3.StringUtils; import org.json.JSONException; import org.json.JSONObject; import org.slf4j.Logger; @@ -29,7 +29,6 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; -import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.db.DatabaseHelper; import info.nightscout.androidaps.db.ICallback; import info.nightscout.androidaps.db.Source; @@ -38,8 +37,14 @@ import info.nightscout.androidaps.events.EventNsTreatment; import info.nightscout.androidaps.events.EventReloadTreatmentData; import info.nightscout.androidaps.events.EventTreatmentChange; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventNewHistoryData; -import info.nightscout.utils.JsonHelper; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventNewHistoryData; +import info.nightscout.androidaps.plugins.pump.medtronic.data.MedtronicHistoryData; +import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil; +import info.nightscout.androidaps.utils.FabricPrivacy; +import info.nightscout.androidaps.utils.JsonHelper; +import io.reactivex.disposables.CompositeDisposable; +import io.reactivex.schedulers.Schedulers; /** @@ -48,6 +53,7 @@ import info.nightscout.utils.JsonHelper; public class TreatmentService extends OrmLiteBaseService { private static Logger log = LoggerFactory.getLogger(L.DATATREATMENTS); + private CompositeDisposable disposable = new CompositeDisposable(); private static final ScheduledExecutorService treatmentEventWorker = Executors.newSingleThreadScheduledExecutor(); private static ScheduledFuture scheduledTreatmentEventPost = null; @@ -55,7 +61,20 @@ public class TreatmentService extends OrmLiteBaseService { public TreatmentService() { onCreate(); dbInitialize(); - MainApp.bus().register(this); + disposable.add(RxBus.INSTANCE + .toObservable(EventNsTreatment.class) + .observeOn(Schedulers.io()) + .subscribe(event -> { + int mode = event.getMode(); + JSONObject payload = event.getPayload(); + + if (mode == EventNsTreatment.Companion.getADD() || mode == EventNsTreatment.Companion.getUPDATE()) { + this.createTreatmentFromJsonIfNotExists(payload); + } else { // EventNsTreatment.REMOVE + this.deleteNS(payload); + } + }, FabricPrivacy::logException) + ); } /** @@ -86,19 +105,6 @@ public class TreatmentService extends OrmLiteBaseService { return null; } - @Subscribe - @SuppressWarnings("unused") - public void handleNsEvent(EventNsTreatment event) { - int mode = event.getMode(); - JSONObject payload = event.getPayload(); - - if (mode == EventNsTreatment.ADD || mode == EventNsTreatment.UPDATE) { - this.createTreatmentFromJsonIfNotExists(payload); - } else { // EventNsTreatment.REMOVE - this.deleteNS(payload); - } - } - @Override public void onCreate() { super.onCreate(); @@ -179,11 +185,11 @@ public class TreatmentService extends OrmLiteBaseService { public void run() { if (L.isEnabled(L.DATATREATMENTS)) log.debug("Firing EventReloadTreatmentData"); - MainApp.bus().post(event); + RxBus.INSTANCE.send(event); if (DatabaseHelper.earliestDataChange != null) { if (L.isEnabled(L.DATATREATMENTS)) log.debug("Firing EventNewHistoryData"); - MainApp.bus().post(new EventNewHistoryData(DatabaseHelper.earliestDataChange)); + RxBus.INSTANCE.send(new EventNewHistoryData(DatabaseHelper.earliestDataChange)); } DatabaseHelper.earliestDataChange = null; callback.setPost(null); @@ -191,8 +197,9 @@ public class TreatmentService extends OrmLiteBaseService { } // prepare task for execution in 1 sec // cancel waiting task to prevent sending multiple posts - if (callback.getPost() != null) - callback.getPost().cancel(false); + ScheduledFuture scheduledFuture = callback.getPost(); + if (scheduledFuture != null) + scheduledFuture.cancel(false); Runnable task = new PostRunnable(); final int sec = 1; callback.setPost(eventWorker.schedule(task, sec, TimeUnit.SECONDS)); @@ -242,15 +249,23 @@ public class TreatmentService extends OrmLiteBaseService { public void createTreatmentFromJsonIfNotExists(JSONObject json) { try { Treatment treatment = Treatment.createFromJson(json); - if (treatment != null) - createOrUpdate(treatment); - else + if (treatment != null) { + + if (MedtronicHistoryData.doubleBolusDebug) + log.debug("DoubleBolusDebug: createTreatmentFromJsonIfNotExists:: medtronicPump={}", MedtronicUtil.isMedtronicPump()); + + if (!MedtronicUtil.isMedtronicPump()) + createOrUpdate(treatment); + else + createOrUpdateMedtronic(treatment, true); + } else log.error("Date is null: " + treatment.toString()); } catch (JSONException e) { log.error("Unhandled exception", e); } } + // return true if new record is created public UpdateReturn createOrUpdate(Treatment treatment) { try { @@ -380,6 +395,196 @@ public class TreatmentService extends OrmLiteBaseService { return new UpdateReturn(false, false); } + + public UpdateReturn createOrUpdateMedtronic(Treatment treatment, boolean fromNightScout) { + + if (MedtronicHistoryData.doubleBolusDebug) + log.debug("DoubleBolusDebug: createOrUpdateMedtronic:: originalTreatment={}, fromNightScout={}", treatment, fromNightScout); + + try { + treatment.date = DatabaseHelper.roundDateToSec(treatment.date); + + Treatment existingTreatment = getRecord(treatment.pumpId, treatment.date); + + if (MedtronicHistoryData.doubleBolusDebug) + log.debug("DoubleBolusDebug: createOrUpdateMedtronic:: existingTreatment={}", treatment); + + if (existingTreatment == null) { + getDao().create(treatment); + if (L.isEnabled(L.DATATREATMENTS)) + log.debug("New record from: " + Source.getString(treatment.source) + " " + treatment.toString()); + DatabaseHelper.updateEarliestDataChange(treatment.date); + scheduleTreatmentChange(treatment); + return new UpdateReturn(true, true); + } else { + + if (existingTreatment.date == treatment.date) { + if (MedtronicHistoryData.doubleBolusDebug) + log.debug("DoubleBolusDebug: createOrUpdateMedtronic::(existingTreatment.date==treatment.date)"); + + // we will do update only, if entry changed + if (!optionalTreatmentCopy(existingTreatment, treatment, fromNightScout)) { + return new UpdateReturn(true, false); + } + getDao().update(existingTreatment); + DatabaseHelper.updateEarliestDataChange(existingTreatment.date); + scheduleTreatmentChange(treatment); + return new UpdateReturn(true, false); + } else { + if (MedtronicHistoryData.doubleBolusDebug) + log.debug("DoubleBolusDebug: createOrUpdateMedtronic::(existingTreatment.date != treatment.date)"); + + // date is different, we need to remove entry + getDao().delete(existingTreatment); + optionalTreatmentCopy(existingTreatment, treatment, fromNightScout); + getDao().create(existingTreatment); + DatabaseHelper.updateEarliestDataChange(existingTreatment.date); + scheduleTreatmentChange(treatment); + return new UpdateReturn(true, false); //updating a pump treatment with another one from the pump is not counted as clash + } + } + + } catch (SQLException e) { + log.error("Unhandled SQL exception: {}", e.getMessage(), e); + } + return new UpdateReturn(false, false); + } + + + private boolean optionalTreatmentCopy(Treatment oldTreatment, Treatment newTreatment, boolean fromNightScout) { + + log.debug("optionalTreatmentCopy [old={}, new={}]", oldTreatment.toString(), newTreatment.toString()); + + boolean changed = false; + + if (oldTreatment.date != newTreatment.date) { + oldTreatment.date = newTreatment.date; + changed = true; + } + + if (oldTreatment.isSMB != newTreatment.isSMB) { + if (!oldTreatment.isSMB) { + oldTreatment.isSMB = newTreatment.isSMB; + changed = true; + } + } + + if (!isSame(oldTreatment.carbs, newTreatment.carbs)) { + if (isSame(oldTreatment.carbs, 0.0d)) { + oldTreatment.carbs = newTreatment.carbs; + changed = true; + } + } + + if (oldTreatment.mealBolus != (oldTreatment.carbs > 0)) { + oldTreatment.mealBolus = (oldTreatment.carbs > 0); + changed = true; + } + + if (!isSame(oldTreatment.insulin, newTreatment.insulin)) { + if (!fromNightScout) { + oldTreatment.insulin = newTreatment.insulin; + changed = true; + } + } + + if (!StringUtils.equals(oldTreatment._id, newTreatment._id)) { + if (StringUtils.isBlank(oldTreatment._id)) { + oldTreatment._id = newTreatment._id; + changed = true; + } + } + + int source = Source.NONE; + + if (oldTreatment.pumpId == 0) { + if (newTreatment.pumpId > 0) { + oldTreatment.pumpId = newTreatment.pumpId; + source = Source.PUMP; + changed = true; + } + } + + if (source == Source.NONE) { + + if (oldTreatment.source == newTreatment.source) { + source = oldTreatment.source; + } else { + source = (oldTreatment.source == Source.NIGHTSCOUT || newTreatment.source == Source.NIGHTSCOUT) ? Source.NIGHTSCOUT : Source.USER; + } + } + + if (oldTreatment.source != source) { + oldTreatment.source = source; + changed = true; + } + + log.debug("optionalTreatmentCopy [changed={}, newAfterChange={}]", changed, oldTreatment.toString()); + return changed; + } + + + public static boolean isSame(Double d1, Double d2) { + double diff = d1 - d2; + + return (Math.abs(diff) <= 0.00001); + } + + @Deprecated + private void treatmentCopy(Treatment oldTreatment, Treatment newTreatment, boolean fromNightScout) { + + log.debug("treatmentCopy [old={}, new={}]", oldTreatment.toString(), newTreatment.toString()); + + + if (fromNightScout) { + long pumpId_old = oldTreatment.pumpId; + boolean isSMB = (oldTreatment.isSMB || newTreatment.isSMB); + + oldTreatment.copyFrom(newTreatment); + + if (pumpId_old != 0) { + oldTreatment.pumpId = pumpId_old; + } + + if (oldTreatment.pumpId != 0 && oldTreatment.source != Source.PUMP) { + oldTreatment.source = Source.PUMP; + } + + oldTreatment.isSMB = isSMB; + + } else { + oldTreatment.copyFrom(newTreatment); + } + + log.debug("treatmentCopy [newAfterChange={}]", oldTreatment.toString()); + + } + + + public Treatment getRecord(long pumpId, long date) { + + Treatment record = null; + + if (pumpId > 0) { + + record = getPumpRecordById(pumpId); + + if (record != null) { + return record; + } + } + + try { + record = getDao().queryForId(date); + } catch (SQLException ex) { + log.error("Error getting entry by id ({}", date); + } + + return record; + + } + + /** * Returns the record for the given id, null if none, throws RuntimeException * if multiple records with the same pump id exist. @@ -500,6 +705,23 @@ public class TreatmentService extends OrmLiteBaseService { return new ArrayList<>(); } + public List getTreatmentDataFromTime(long from, long to, boolean ascending) { + try { + Dao daoTreatments = getDao(); + List treatments; + QueryBuilder queryBuilder = daoTreatments.queryBuilder(); + queryBuilder.orderBy("date", ascending); + Where where = queryBuilder.where(); + where.between("date", from, to); + PreparedQuery preparedQuery = queryBuilder.prepare(); + treatments = daoTreatments.query(preparedQuery); + return treatments; + } catch (SQLException e) { + log.error("Unhandled exception", e); + } + return new ArrayList<>(); + } + @Nullable @Override public IBinder onBind(Intent intent) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/TreatmentsFragment.java similarity index 58% rename from app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsFragment.java rename to app/src/main/java/info/nightscout/androidaps/plugins/treatments/TreatmentsFragment.java index 32feb9fe7f..731042c237 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/TreatmentsFragment.java @@ -1,32 +1,32 @@ -package info.nightscout.androidaps.plugins.Treatments; +package info.nightscout.androidaps.plugins.treatments; import android.os.Bundle; -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentTransaction; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; -import com.squareup.otto.Subscribe; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentTransaction; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.events.EventExtendedBolusChange; -import info.nightscout.androidaps.plugins.Common.SubscriberFragment; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.Treatments.fragments.TreatmentsBolusFragment; -import info.nightscout.androidaps.plugins.Treatments.fragments.TreatmentsCareportalFragment; -import info.nightscout.androidaps.plugins.Treatments.fragments.TreatmentsExtendedBolusesFragment; -import info.nightscout.androidaps.plugins.Treatments.fragments.TreatmentsProfileSwitchFragment; -import info.nightscout.androidaps.plugins.Treatments.fragments.TreatmentsTempTargetFragment; -import info.nightscout.androidaps.plugins.Treatments.fragments.TreatmentsTemporaryBasalsFragment; -import info.nightscout.utils.FabricPrivacy; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.treatments.fragments.TreatmentsBolusFragment; +import info.nightscout.androidaps.plugins.treatments.fragments.TreatmentsCareportalFragment; +import info.nightscout.androidaps.plugins.treatments.fragments.TreatmentsExtendedBolusesFragment; +import info.nightscout.androidaps.plugins.treatments.fragments.TreatmentsProfileSwitchFragment; +import info.nightscout.androidaps.plugins.treatments.fragments.TreatmentsTempTargetFragment; +import info.nightscout.androidaps.plugins.treatments.fragments.TreatmentsTemporaryBasalsFragment; +import info.nightscout.androidaps.utils.FabricPrivacy; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.CompositeDisposable; + +public class TreatmentsFragment extends Fragment implements View.OnClickListener { + private CompositeDisposable disposable = new CompositeDisposable(); -public class TreatmentsFragment extends SubscriberFragment implements View.OnClickListener { TextView treatmentsTab; TextView extendedBolusesTab; TextView tempBasalsTab; @@ -37,32 +37,42 @@ public class TreatmentsFragment extends SubscriberFragment implements View.OnCli @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - try { - View view = inflater.inflate(R.layout.treatments_fragment, container, false); + View view = inflater.inflate(R.layout.treatments_fragment, container, false); - treatmentsTab = (TextView) view.findViewById(R.id.treatments_treatments); - extendedBolusesTab = (TextView) view.findViewById(R.id.treatments_extendedboluses); - tempBasalsTab = (TextView) view.findViewById(R.id.treatments_tempbasals); - tempTargetTab = (TextView) view.findViewById(R.id.treatments_temptargets); - profileSwitchTab = (TextView) view.findViewById(R.id.treatments_profileswitches); - careportalTab = (TextView) view.findViewById(R.id.treatments_careportal); - treatmentsTab.setOnClickListener(this); - extendedBolusesTab.setOnClickListener(this); - tempBasalsTab.setOnClickListener(this); - tempTargetTab.setOnClickListener(this); - profileSwitchTab.setOnClickListener(this); - careportalTab.setOnClickListener(this); + treatmentsTab = (TextView) view.findViewById(R.id.treatments_treatments); + extendedBolusesTab = (TextView) view.findViewById(R.id.treatments_extendedboluses); + tempBasalsTab = (TextView) view.findViewById(R.id.treatments_tempbasals); + tempTargetTab = (TextView) view.findViewById(R.id.treatments_temptargets); + profileSwitchTab = (TextView) view.findViewById(R.id.treatments_profileswitches); + careportalTab = (TextView) view.findViewById(R.id.treatments_careportal); + treatmentsTab.setOnClickListener(this); + extendedBolusesTab.setOnClickListener(this); + tempBasalsTab.setOnClickListener(this); + tempTargetTab.setOnClickListener(this); + profileSwitchTab.setOnClickListener(this); + careportalTab.setOnClickListener(this); - setFragment(new TreatmentsBolusFragment()); - setBackgroundColorOnSelected(treatmentsTab); + setFragment(new TreatmentsBolusFragment()); + setBackgroundColorOnSelected(treatmentsTab); - return view; - } catch (Exception e) { - FabricPrivacy.logException(e); - } + return view; + } - return null; + @Override + public synchronized void onResume() { + super.onResume(); + disposable.add(RxBus.INSTANCE + .toObservable(EventExtendedBolusChange.class) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(event -> updateGui(), FabricPrivacy::logException) + ); + updateGui(); + } + @Override + public synchronized void onPause() { + super.onPause(); + disposable.clear(); } @Override @@ -114,13 +124,7 @@ public class TreatmentsFragment extends SubscriberFragment implements View.OnCli selected.setBackgroundColor(MainApp.gc(R.color.tabBgColorSelected)); } - @Subscribe - public void onStatusEvent(final EventExtendedBolusChange ev) { - updateGUI(); - } - - @Override - protected void updateGUI() { + private void updateGui() { if (ConfigBuilderPlugin.getPlugin().getActivePump().getPumpDescription().isExtendedBolusCapable || TreatmentsPlugin.getPlugin().getExtendedBolusesFromHistory().size() > 0) { extendedBolusesTab.setVisibility(View.VISIBLE); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/TreatmentsPlugin.java similarity index 67% rename from app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsPlugin.java rename to app/src/main/java/info/nightscout/androidaps/plugins/treatments/TreatmentsPlugin.java index aeacddb89c..28181da190 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/TreatmentsPlugin.java @@ -1,10 +1,11 @@ -package info.nightscout.androidaps.plugins.Treatments; +package info.nightscout.androidaps.plugins.treatments; import android.content.Intent; -import android.support.annotation.Nullable; +import android.os.Bundle; -import com.crashlytics.android.answers.CustomEvent; -import com.squareup.otto.Subscribe; +import androidx.annotation.Nullable; + +import com.google.firebase.analytics.FirebaseAnalytics; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -37,22 +38,29 @@ import info.nightscout.androidaps.interfaces.InsulinInterface; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginDescription; import info.nightscout.androidaps.interfaces.PluginType; +import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.interfaces.TreatmentsInterface; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions; -import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData; -import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin; -import info.nightscout.androidaps.plugins.Overview.Dialogs.ErrorHelperActivity; -import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; -import info.nightscout.androidaps.plugins.Overview.notifications.Notification; -import info.nightscout.androidaps.plugins.Sensitivity.SensitivityAAPSPlugin; -import info.nightscout.androidaps.plugins.Sensitivity.SensitivityWeightedAveragePlugin; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.FabricPrivacy; -import info.nightscout.androidaps.plugins.NSClientInternal.NSUpload; -import info.nightscout.utils.SP; -import info.nightscout.utils.T; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; +import info.nightscout.androidaps.plugins.general.nsclient.NSUpload; +import info.nightscout.androidaps.plugins.general.overview.dialogs.ErrorHelperActivity; +import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification; +import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensData; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin; +import info.nightscout.androidaps.plugins.pump.medtronic.data.MedtronicHistoryData; +import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil; +import info.nightscout.androidaps.plugins.sensitivity.SensitivityAAPSPlugin; +import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAveragePlugin; +import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.FabricPrivacy; +import info.nightscout.androidaps.utils.SP; +import info.nightscout.androidaps.utils.T; +import io.reactivex.disposables.CompositeDisposable; +import io.reactivex.schedulers.Schedulers; /** * Created by mike on 05.08.2016. @@ -60,6 +68,8 @@ import info.nightscout.utils.T; public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface { private Logger log = LoggerFactory.getLogger(L.DATATREATMENTS); + private CompositeDisposable disposable = new CompositeDisposable(); + private static TreatmentsPlugin treatmentsPlugin; public static TreatmentsPlugin getPlugin() { @@ -93,18 +103,54 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface @Override protected void onStart() { - MainApp.bus().register(this); initializeTempBasalData(); initializeTreatmentData(); initializeExtendedBolusData(); initializeTempTargetData(); initializeProfileSwitchData(); super.onStart(); + disposable.add(RxBus.INSTANCE + .toObservable(EventReloadTreatmentData.class) + .observeOn(Schedulers.io()) + .subscribe(event -> { + if (L.isEnabled(L.DATATREATMENTS)) + log.debug("EventReloadTreatmentData"); + initializeTreatmentData(); + initializeExtendedBolusData(); + updateTotalIOBTreatments(); + RxBus.INSTANCE.send(event.getNext()); + }, + FabricPrivacy::logException + )); + disposable.add(RxBus.INSTANCE + .toObservable(EventReloadProfileSwitchData.class) + .observeOn(Schedulers.io()) + .subscribe(event -> initializeProfileSwitchData(), + FabricPrivacy::logException + )); + disposable.add(RxBus.INSTANCE + .toObservable(EventTempTargetChange.class) + .observeOn(Schedulers.io()) + .subscribe(event -> initializeTempTargetData(), + FabricPrivacy::logException + )); + disposable.add(RxBus.INSTANCE + .toObservable(EventReloadTempBasalData.class) + .observeOn(Schedulers.io()) + .subscribe(event -> { + if (L.isEnabled(L.DATATREATMENTS)) + log.debug("EventReloadTempBasalData"); + initializeTempBasalData(); + updateTotalIOBTempBasals(); + }, + FabricPrivacy::logException + )); } @Override protected void onStop() { - MainApp.bus().register(this); + disposable.clear(); + super.onStop(); } public TreatmentService getService() { @@ -184,7 +230,11 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface InsulinInterface insulinInterface = ConfigBuilderPlugin.getPlugin().getActiveInsulin(); if (insulinInterface == null) - return total; + return total; + + PumpInterface pumpInterface = ConfigBuilderPlugin.getPlugin().getActivePump(); + if (pumpInterface == null) + return total; double dia = profile.getDia(); @@ -209,7 +259,7 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface } } - if (!ConfigBuilderPlugin.getPlugin().getActivePump().isFakingTempsByExtendedBoluses()) + if (!pumpInterface.isFakingTempsByExtendedBoluses()) synchronized (extendedBoluses) { for (Integer pos = 0; pos < extendedBoluses.size(); pos++) { ExtendedBolus e = extendedBoluses.get(pos); @@ -259,7 +309,7 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface if (t > absorptionTime_ago && t <= now) { if (treatment.carbs >= 1) { result.carbs += treatment.carbs; - if(t > result.lastCarbTime) + if (t > result.lastCarbTime) result.lastCarbTime = t; } } @@ -284,6 +334,36 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface } } + + /** + * Returns all Treatments after specified timestamp. Also returns invalid entries (required to + * map "Fill Canulla" entries to history (and not to add double bolus for it) + * + * @param fromTimestamp + * @return + */ + @Override + public List getTreatmentsFromHistoryAfterTimestamp(long fromTimestamp) { + List in5minback = new ArrayList<>(); + + long time = System.currentTimeMillis(); + synchronized (treatments) { + if (MedtronicHistoryData.doubleBolusDebug) + log.debug("DoubleBolusDebug: AllTreatmentsInDb: {}", MedtronicUtil.getGsonInstance().toJson(treatments)); + + for (Treatment t : treatments) { + if (t.date <= time && t.date >= fromTimestamp) + in5minback.add(t); + } + + if (MedtronicHistoryData.doubleBolusDebug) + log.debug("DoubleBolusDebug: FilteredTreatments: AfterTime={}, Items={}", fromTimestamp, MedtronicUtil.getGsonInstance().toJson(in5minback)); + + return in5minback; + } + } + + @Override public List getTreatments5MinBackFromHistory(long time) { List in5minback = new ArrayList<>(); @@ -312,7 +392,23 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface } } if (L.isEnabled(L.DATATREATMENTS)) - log.debug("Last bolus time: " + new Date(last).toLocaleString()); + log.debug("Last bolus time: " + new Date(last).toLocaleString()); + return last; + } + + public long getLastBolusTime(boolean isSMB) { + long now = System.currentTimeMillis(); + long last = 0; + synchronized (treatments) { + for (Treatment t : treatments) { + if (!t.isValid) + continue; + if (t.date > last && t.insulin > 0 && t.isValid && t.date <= now && isSMB == t.isSMB) + last = t.date; + } + } + if (L.isEnabled(L.DATATREATMENTS)) + log.debug("Last manual bolus time: " + new Date(last).toLocaleString()); return last; } @@ -338,48 +434,31 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface return getExtendedBolusFromHistory(System.currentTimeMillis()) != null; //TODO: crosscheck here } - @Subscribe - public void onStatusEvent(final EventReloadTreatmentData ev) { - if (L.isEnabled(L.DATATREATMENTS)) - log.debug("EventReloadTreatmentData"); - initializeTreatmentData(); - initializeExtendedBolusData(); - updateTotalIOBTreatments(); - MainApp.bus().post(ev.next); - } - - @Subscribe - @SuppressWarnings("unused") - public void onStatusEvent(final EventReloadTempBasalData ev) { - if (L.isEnabled(L.DATATREATMENTS)) - log.debug("EventReloadTempBasalData"); - initializeTempBasalData(); - updateTotalIOBTempBasals(); - } - @Override public IobTotal getLastCalculationTempBasals() { return lastTempBasalsCalculation; } @Override - public IobTotal getCalculationToTimeTempBasals(long time, Profile profile) { - return getCalculationToTimeTempBasals(time, profile, false, 0); + public IobTotal getCalculationToTimeTempBasals(long time) { + return getCalculationToTimeTempBasals(time, false, 0); } - public IobTotal getCalculationToTimeTempBasals(long time, Profile profile, boolean truncate, long truncateTime) { + public IobTotal getCalculationToTimeTempBasals(long time, boolean truncate, long truncateTime) { IobTotal total = new IobTotal(time); InsulinInterface insulinInterface = ConfigBuilderPlugin.getPlugin().getActiveInsulin(); if (insulinInterface == null) - return total; + return total; synchronized (tempBasals) { for (Integer pos = 0; pos < tempBasals.size(); pos++) { TemporaryBasal t = tempBasals.get(pos); if (t.date > time) continue; IobTotal calc; - if(truncate && t.end() > truncateTime){ + Profile profile = ProfileFunctions.getInstance().getProfile(t.date); + if (profile == null) continue; + if (truncate && t.end() > truncateTime) { TemporaryBasal dummyTemp = new TemporaryBasal(); dummyTemp.copyFrom(t); dummyTemp.cutEndTo(truncateTime); @@ -398,7 +477,9 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface ExtendedBolus e = extendedBoluses.get(pos); if (e.date > time) continue; IobTotal calc; - if(truncate && e.end() > truncateTime){ + Profile profile = ProfileFunctions.getInstance().getProfile(e.date); + if (profile == null) continue; + if (truncate && e.end() > truncateTime) { ExtendedBolus dummyExt = new ExtendedBolus(); dummyExt.copyFrom(e); dummyExt.cutEndTo(truncateTime); @@ -419,11 +500,65 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface return total; } + public IobTotal getCalculationToTimeTempBasals(long time, long truncateTime, AutosensResult lastAutosensResult, boolean exercise_mode, int half_basal_exercise_target, boolean isTempTarget) { + IobTotal total = new IobTotal(time); + + InsulinInterface insulinInterface = ConfigBuilderPlugin.getPlugin().getActiveInsulin(); + if (insulinInterface == null) + return total; + + synchronized (tempBasals) { + for (int pos = 0; pos < tempBasals.size(); pos++) { + TemporaryBasal t = tempBasals.get(pos); + if (t.date > time) continue; + IobTotal calc; + Profile profile = ProfileFunctions.getInstance().getProfile(t.date); + if (profile == null) continue; + if (t.end() > truncateTime) { + TemporaryBasal dummyTemp = new TemporaryBasal(); + dummyTemp.copyFrom(t); + dummyTemp.cutEndTo(truncateTime); + calc = dummyTemp.iobCalc(time, profile, lastAutosensResult, exercise_mode, half_basal_exercise_target, isTempTarget); + } else { + calc = t.iobCalc(time, profile, lastAutosensResult, exercise_mode, half_basal_exercise_target, isTempTarget); + } + //log.debug("BasalIOB " + new Date(time) + " >>> " + calc.basaliob); + total.plus(calc); + } + } + if (ConfigBuilderPlugin.getPlugin().getActivePump().isFakingTempsByExtendedBoluses()) { + IobTotal totalExt = new IobTotal(time); + synchronized (extendedBoluses) { + for (int pos = 0; pos < extendedBoluses.size(); pos++) { + ExtendedBolus e = extendedBoluses.get(pos); + if (e.date > time) continue; + IobTotal calc; + Profile profile = ProfileFunctions.getInstance().getProfile(e.date); + if (profile == null) continue; + if (e.end() > truncateTime) { + ExtendedBolus dummyExt = new ExtendedBolus(); + dummyExt.copyFrom(e); + dummyExt.cutEndTo(truncateTime); + calc = dummyExt.iobCalc(time, profile, lastAutosensResult, exercise_mode, half_basal_exercise_target, isTempTarget); + } else { + calc = e.iobCalc(time, profile, lastAutosensResult, exercise_mode, half_basal_exercise_target, isTempTarget); + } + totalExt.plus(calc); + } + } + // Convert to basal iob + totalExt.basaliob = totalExt.iob; + totalExt.iob = 0d; + totalExt.netbasalinsulin = totalExt.extendedBolusInsulin; + totalExt.hightempinsulin = totalExt.extendedBolusInsulin; + total.plus(totalExt); + } + return total; + } + @Override public void updateTotalIOBTempBasals() { - Profile profile = ProfileFunctions.getInstance().getProfile(); - if (profile != null) - lastTempBasalsCalculation = getCalculationToTimeTempBasals(DateUtil.now(), profile); + lastTempBasalsCalculation = getCalculationToTimeTempBasals(DateUtil.now()); } @Nullable @@ -471,7 +606,7 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface } @Override - public Intervals getTemporaryBasalsFromHistory() { + public NonOverlappingIntervals getTemporaryBasalsFromHistory() { synchronized (tempBasals) { return new NonOverlappingIntervals<>(tempBasals); } @@ -495,6 +630,11 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface // return true if new record is created @Override public boolean addToHistoryTreatment(DetailedBolusInfo detailedBolusInfo, boolean allowUpdate) { + boolean medtronicPump = MedtronicUtil.isMedtronicPump(); + + if (MedtronicHistoryData.doubleBolusDebug) + log.debug("DoubleBolusDebug: addToHistoryTreatment::isMedtronicPump={}", medtronicPump); + Treatment treatment = new Treatment(); treatment.date = detailedBolusInfo.date; treatment.source = detailedBolusInfo.source; @@ -507,17 +647,34 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface treatment.source = detailedBolusInfo.source; treatment.mealBolus = treatment.carbs > 0; treatment.boluscalc = detailedBolusInfo.boluscalc != null ? detailedBolusInfo.boluscalc.toString() : null; - TreatmentService.UpdateReturn creatOrUpdateResult = getService().createOrUpdate(treatment); + TreatmentService.UpdateReturn creatOrUpdateResult; + + if (medtronicPump && MedtronicHistoryData.doubleBolusDebug) + log.debug("DoubleBolusDebug: addToHistoryTreatment::treatment={}", treatment); + + if (!medtronicPump) + creatOrUpdateResult = getService().createOrUpdate(treatment); + else + creatOrUpdateResult = getService().createOrUpdateMedtronic(treatment, false); + boolean newRecordCreated = creatOrUpdateResult.newRecord; //log.debug("Adding new Treatment record" + treatment.toString()); if (detailedBolusInfo.carbTime != 0) { + Treatment carbsTreatment = new Treatment(); carbsTreatment.source = detailedBolusInfo.source; carbsTreatment.pumpId = detailedBolusInfo.pumpId; // but this should never happen carbsTreatment.date = detailedBolusInfo.date + detailedBolusInfo.carbTime * 60 * 1000L + 1000L; // add 1 sec to make them different records carbsTreatment.carbs = detailedBolusInfo.carbs; carbsTreatment.source = detailedBolusInfo.source; - getService().createOrUpdate(carbsTreatment); + + if (medtronicPump && MedtronicHistoryData.doubleBolusDebug) + log.debug("DoubleBolusDebug: carbTime!=0, creating second treatment. CarbsTreatment={}", carbsTreatment); + + if (!medtronicPump) + getService().createOrUpdate(carbsTreatment); + else + getService().createOrUpdateMedtronic(carbsTreatment, false); //log.debug("Adding new Treatment record" + carbsTreatment); } if (newRecordCreated && detailedBolusInfo.isValid) @@ -535,9 +692,10 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); MainApp.instance().startActivity(i); - CustomEvent customEvent = new CustomEvent("TreatmentClash"); - customEvent.putCustomAttribute("status", status); - FabricPrivacy.getInstance().logCustom(customEvent); + Bundle bundle = new Bundle(); + bundle.putString(FirebaseAnalytics.Param.ITEM_ID, "TreatmentClash"); + bundle.putString(FirebaseAnalytics.Param.VALUE, status); + FabricPrivacy.getInstance().logCustom(bundle); } return newRecordCreated; @@ -562,13 +720,6 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface return oldestTime; } - // TempTargets - @Subscribe - @SuppressWarnings("unused") - public void onStatusEvent(final EventTempTargetChange ev) { - initializeTempTargetData(); - } - @Nullable @Override public TempTarget getTempTargetFromHistory() { @@ -599,14 +750,8 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface NSUpload.uploadTempTarget(tempTarget); } - // Profile Switch - @Subscribe - @SuppressWarnings("unused") - public void onStatusEvent(final EventReloadProfileSwitchData ev) { - initializeProfileSwitchData(); - } - @Override + @Nullable public ProfileSwitch getProfileSwitchFromHistory(long time) { synchronized (profiles) { return (ProfileSwitch) profiles.getValueToTime(time); @@ -623,7 +768,7 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface @Override public void addToHistoryProfileSwitch(ProfileSwitch profileSwitch) { //log.debug("Adding new TemporaryBasal record" + profileSwitch.log()); - MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_SWITCH_MISSING)); + RxBus.INSTANCE.send(new EventDismissNotification(Notification.PROFILE_SWITCH_MISSING)); MainApp.getDbHelper().createOrUpdate(profileSwitch); NSUpload.uploadProfileSwitch(profileSwitch); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/treatments/dialogs/WizardInfoDialog.kt b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/dialogs/WizardInfoDialog.kt new file mode 100644 index 0000000000..c65c75c00e --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/dialogs/WizardInfoDialog.kt @@ -0,0 +1,70 @@ +package info.nightscout.androidaps.plugins.treatments.dialogs + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import androidx.fragment.app.DialogFragment +import info.nightscout.androidaps.R +import info.nightscout.androidaps.utils.DecimalFormatter +import info.nightscout.androidaps.utils.JsonHelper +import kotlinx.android.synthetic.main.treatments_wizardinfo_dialog.* +import org.json.JSONObject + +class WizardInfoDialog : DialogFragment() { + private var json: JSONObject? = null + + fun setData(json: JSONObject) { + this.json = json + } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle?): View? { + dialog?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN) + isCancelable = true + return inflater.inflate(R.layout.treatments_wizardinfo_dialog, container, false) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + close.setOnClickListener { dismiss() } + + // BG + treatments_wizard_bg.text = DecimalFormatter.to1Decimal(JsonHelper.safeGetDouble(json, "bg")) + " ISF: " + DecimalFormatter.to1Decimal(JsonHelper.safeGetDouble(json, "isf")) + treatments_wizard_bginsulin.text = DecimalFormatter.to2Decimal(JsonHelper.safeGetDouble(json, "insulinbg")) + "U" + treatments_wizard_bgcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "insulinbgused") + treatments_wizard_ttcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "ttused") + // Trend + treatments_wizard_bgtrend.text = JsonHelper.safeGetString(json, "trend") + treatments_wizard_bgtrendinsulin.text = DecimalFormatter.to2Decimal(JsonHelper.safeGetDouble(json, "insulintrend")) + "U" + treatments_wizard_bgtrendcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "trendused") + // COB + treatments_wizard_cob.text = DecimalFormatter.to0Decimal(JsonHelper.safeGetDouble(json, "cob")) + "g IC: " + DecimalFormatter.to1Decimal(JsonHelper.safeGetDouble(json, "ic")) + treatments_wizard_cobinsulin.text = DecimalFormatter.to2Decimal(JsonHelper.safeGetDouble(json, "insulincob")) + "U" + treatments_wizard_cobcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "cobused") + // Bolus IOB + treatments_wizard_bolusiobinsulin.text = DecimalFormatter.to2Decimal(JsonHelper.safeGetDouble(json, "bolusiob")) + "U" + treatments_wizard_bolusiobcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "bolusiobused") + // Basal IOB + treatments_wizard_basaliobinsulin.text = DecimalFormatter.to2Decimal(JsonHelper.safeGetDouble(json, "basaliob")) + "U" + treatments_wizard_basaliobcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "basaliobused") + // Superbolus + treatments_wizard_sbinsulin.text = DecimalFormatter.to2Decimal(JsonHelper.safeGetDouble(json, "insulinsuperbolus")) + "U" + treatments_wizard_sbcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "superbolusused") + // Carbs + treatments_wizard_carbs.text = DecimalFormatter.to0Decimal(JsonHelper.safeGetDouble(json, "carbs")) + "g IC: " + DecimalFormatter.to1Decimal(JsonHelper.safeGetDouble(json, "ic")) + treatments_wizard_carbsinsulin.text = DecimalFormatter.to2Decimal(JsonHelper.safeGetDouble(json, "insulincarbs")) + "U" + // Correction + treatments_wizard_correctioninsulin.text = DecimalFormatter.to2Decimal(JsonHelper.safeGetDouble(json, "othercorrection")) + "U" + // Profile + treatments_wizard_profile.text = JsonHelper.safeGetString(json, "profile") + // Notes + treatments_wizard_notes.text = JsonHelper.safeGetString(json, "notes") + // Percentage + treatments_wizard_percent_used.text = DecimalFormatter.to0Decimal(JsonHelper.safeGetDouble(json, "percentageCorrection", 100.0)) + "%" + // Total + treatments_wizard_totalinsulin.text = DecimalFormatter.to2Decimal(JsonHelper.safeGetDouble(json, "insulin")) + "U" + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/ProfileGraph.java b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/ProfileGraph.java similarity index 94% rename from app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/ProfileGraph.java rename to app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/ProfileGraph.java index 99019e5fd7..dd9e820907 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/ProfileGraph.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/ProfileGraph.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.Treatments.fragments; +package info.nightscout.androidaps.plugins.treatments.fragments; import android.content.Context; import android.util.AttributeSet; @@ -11,7 +11,7 @@ import java.util.ArrayList; import java.util.List; import info.nightscout.androidaps.data.Profile; -import info.nightscout.utils.Round; +import info.nightscout.androidaps.utils.Round; /** * Created by Adrian on 15.04.2018. diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/ProfileViewerDialog.kt b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/ProfileViewerDialog.kt new file mode 100644 index 0000000000..a27ebfb656 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/ProfileViewerDialog.kt @@ -0,0 +1,97 @@ +package info.nightscout.androidaps.plugins.treatments.fragments + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.DialogFragment +import info.nightscout.androidaps.MainApp +import info.nightscout.androidaps.R +import info.nightscout.androidaps.data.Profile +import info.nightscout.androidaps.interfaces.ProfileInterface +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin +import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin +import info.nightscout.androidaps.utils.DateUtil +import kotlinx.android.synthetic.main.close.* +import kotlinx.android.synthetic.main.profileviewer_fragment.* + +class ProfileViewerDialog : DialogFragment() { + private var time: Long = 0 + + enum class Mode(val i: Int) { + RUNNING_PROFILE(1), + PUMP_PROFILE(2) + } + + private var mode: Mode = Mode.RUNNING_PROFILE; + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle?): View? { + // load data from bundle + (savedInstanceState ?: arguments)?.let { bundle -> + time = bundle.getLong("time", 0) + mode = Mode.values()[bundle.getInt("mode", Mode.RUNNING_PROFILE.ordinal)] + } + + return inflater.inflate(R.layout.profileviewer_fragment, container, false) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + close.setOnClickListener { dismiss() } + profileview_reload.setOnClickListener { + ConfigBuilderPlugin.getPlugin().commandQueue.readStatus("ProfileViewDialog", null) + dismiss() + } + + val profile: Profile? + val profileName: String? + val date: String? + when (mode) { + Mode.RUNNING_PROFILE -> { + profile = TreatmentsPlugin.getPlugin().getProfileSwitchFromHistory(time)?.profileObject + profileName = TreatmentsPlugin.getPlugin().getProfileSwitchFromHistory(time)?.customizedName + date = DateUtil.dateAndTimeString(TreatmentsPlugin.getPlugin().getProfileSwitchFromHistory(time)?.date + ?: 0) + profileview_reload.visibility = View.GONE + profileview_datelayout.visibility = View.VISIBLE + } + Mode.PUMP_PROFILE -> { + profile = (ConfigBuilderPlugin.getPlugin().activePump as ProfileInterface?)?.profile?.defaultProfile + profileName = (ConfigBuilderPlugin.getPlugin().activePump as ProfileInterface?)?.profileName + date = "" + profileview_reload.visibility = View.VISIBLE + profileview_datelayout.visibility = View.GONE + } + } + profileview_noprofile.visibility = View.VISIBLE + + profile?.let { + profileview_units.text = it.units + profileview_dia.text = MainApp.gs(R.string.format_hours, it.dia) + profileview_activeprofile.text = profileName + profileview_date.text = date + profileview_ic.text = it.icList + profileview_isf.text = it.isfList + profileview_basal.text = it.basalList + profileview_target.text = it.targetList + basal_graph.show(it) + + profileview_noprofile.visibility = View.GONE + profileview_invalidprofile.visibility = if (it.isValid("ProfileViewDialog")) View.GONE else View.VISIBLE + } + } + + override fun onResume() { + dialog?.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) + super.onResume() + } + + override fun onSaveInstanceState(bundle: Bundle) { + super.onSaveInstanceState(bundle) + bundle.putLong("time", time) + bundle.putInt("mode", mode.ordinal) + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsBolusFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsBolusFragment.java similarity index 77% rename from app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsBolusFragment.java rename to app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsBolusFragment.java index b99ad97685..ee78c6748b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsBolusFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsBolusFragment.java @@ -1,27 +1,22 @@ -package info.nightscout.androidaps.plugins.Treatments.fragments; +package info.nightscout.androidaps.plugins.treatments.fragments; -import android.app.Activity; import android.content.Context; import android.content.DialogInterface; -import android.content.Intent; import android.graphics.Paint; import android.os.Bundle; -import android.support.v4.app.FragmentManager; -import android.support.v4.content.ContextCompat; -import android.support.v7.app.AlertDialog; -import android.support.v7.widget.CardView; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.TextView; -import com.crashlytics.android.answers.CustomEvent; -import com.squareup.otto.Subscribe; - -import org.json.JSONObject; +import androidx.appcompat.app.AlertDialog; +import androidx.cardview.widget.CardView; +import androidx.core.content.ContextCompat; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; import java.util.List; @@ -30,24 +25,28 @@ import info.nightscout.androidaps.R; import info.nightscout.androidaps.data.Iob; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.db.Source; -import info.nightscout.androidaps.events.EventNewBG; import info.nightscout.androidaps.events.EventTreatmentChange; -import info.nightscout.androidaps.plugins.Common.SubscriberFragment; -import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions; -import info.nightscout.androidaps.plugins.NSClientInternal.NSUpload; -import info.nightscout.androidaps.plugins.NSClientInternal.UploadQueue; -import info.nightscout.androidaps.plugins.Treatments.Treatment; -import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; -import info.nightscout.androidaps.plugins.Treatments.dialogs.WizardInfoDialog; -import info.nightscout.androidaps.services.Intents; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.DecimalFormatter; -import info.nightscout.utils.FabricPrivacy; -import info.nightscout.utils.SP; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; +import info.nightscout.androidaps.plugins.general.nsclient.NSUpload; +import info.nightscout.androidaps.plugins.general.nsclient.UploadQueue; +import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutosensCalculationFinished; +import info.nightscout.androidaps.plugins.treatments.Treatment; +import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; +import info.nightscout.androidaps.plugins.treatments.dialogs.WizardInfoDialog; +import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.DecimalFormatter; +import info.nightscout.androidaps.utils.FabricPrivacy; +import info.nightscout.androidaps.utils.SP; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.CompositeDisposable; -import static info.nightscout.utils.DateUtil.now; +import static info.nightscout.androidaps.utils.DateUtil.now; + +public class TreatmentsBolusFragment extends Fragment implements View.OnClickListener { + private CompositeDisposable disposable = new CompositeDisposable(); -public class TreatmentsBolusFragment extends SubscriberFragment implements View.OnClickListener { RecyclerView recyclerView; LinearLayoutManager llm; @@ -166,8 +165,7 @@ public class TreatmentsBolusFragment extends SubscriberFragment implements View. } TreatmentsPlugin.getPlugin().getService().delete(treatment); } - updateGUI(); - FabricPrivacy.getInstance().logCustom(new CustomEvent("RemoveTreatment")); + updateGui(); } }); builder.setNegativeButton(MainApp.gs(R.string.cancel), null); @@ -218,7 +216,6 @@ public class TreatmentsBolusFragment extends SubscriberFragment implements View. context = getContext(); - updateGUI(); return view; } @@ -232,8 +229,7 @@ public class TreatmentsBolusFragment extends SubscriberFragment implements View. builder.setMessage(MainApp.gs(R.string.refresheventsfromnightscout) + "?"); builder.setPositiveButton(MainApp.gs(R.string.ok), (dialog, id) -> { TreatmentsPlugin.getPlugin().getService().resetTreatments(); - Intent restartNSClient = new Intent(Intents.ACTION_RESTART); - MainApp.instance().getApplicationContext().sendBroadcast(restartNSClient); + RxBus.INSTANCE.send(new EventNSClientRestart()); }); builder.setNegativeButton(MainApp.gs(R.string.cancel), null); builder.show(); @@ -254,7 +250,7 @@ public class TreatmentsBolusFragment extends SubscriberFragment implements View. } TreatmentsPlugin.getPlugin().getService().delete(treatment); } - updateGUI(); + updateGui(); }); builder.setNegativeButton(MainApp.gs(R.string.cancel), null); builder.show(); @@ -262,32 +258,39 @@ public class TreatmentsBolusFragment extends SubscriberFragment implements View. } } - @Subscribe - public void onStatusEvent(final EventTreatmentChange ev) { - updateGUI(); - } - - @Subscribe - public void onStatusEvent(final EventNewBG ev) { - updateGUI(); + @Override + public synchronized void onResume() { + super.onResume(); + disposable.add(RxBus.INSTANCE + .toObservable(EventTreatmentChange.class) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(event -> updateGui(), FabricPrivacy::logException) + ); + disposable.add(RxBus.INSTANCE + .toObservable(EventAutosensCalculationFinished.class) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(event -> updateGui(), FabricPrivacy::logException) + ); + updateGui(); } @Override - protected void updateGUI() { - Activity activity = getActivity(); - if (activity != null) - activity.runOnUiThread(() -> { - recyclerView.swapAdapter(new RecyclerViewAdapter(TreatmentsPlugin.getPlugin().getTreatmentsFromHistory()), false); - if (TreatmentsPlugin.getPlugin().getLastCalculationTreatments() != null) { - iobTotal.setText(DecimalFormatter.to2Decimal(TreatmentsPlugin.getPlugin().getLastCalculationTreatments().iob) + " " + MainApp.gs(R.string.insulin_unit_shortname)); - activityTotal.setText(DecimalFormatter.to3Decimal(TreatmentsPlugin.getPlugin().getLastCalculationTreatments().activity) + " " + MainApp.gs(R.string.insulin_unit_shortname)); - } - if (!TreatmentsPlugin.getPlugin().getService().getTreatmentDataFromTime(now() + 1000, true).isEmpty()) { - deleteFutureTreatments.setVisibility(View.VISIBLE); - } else { - deleteFutureTreatments.setVisibility(View.GONE); - } - }); + public synchronized void onPause() { + super.onPause(); + disposable.clear(); + } + + private void updateGui() { + recyclerView.swapAdapter(new RecyclerViewAdapter(TreatmentsPlugin.getPlugin().getTreatmentsFromHistory()), false); + if (TreatmentsPlugin.getPlugin().getLastCalculationTreatments() != null) { + iobTotal.setText(DecimalFormatter.to2Decimal(TreatmentsPlugin.getPlugin().getLastCalculationTreatments().iob) + " " + MainApp.gs(R.string.insulin_unit_shortname)); + activityTotal.setText(DecimalFormatter.to3Decimal(TreatmentsPlugin.getPlugin().getLastCalculationTreatments().activity) + " " + MainApp.gs(R.string.insulin_unit_shortname)); + } + if (!TreatmentsPlugin.getPlugin().getService().getTreatmentDataFromTime(now() + 1000, true).isEmpty()) { + deleteFutureTreatments.setVisibility(View.VISIBLE); + } else { + deleteFutureTreatments.setVisibility(View.GONE); + } } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsCareportalFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsCareportalFragment.java similarity index 81% rename from app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsCareportalFragment.java rename to app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsCareportalFragment.java index 56709963f7..4810a1ed8c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsCareportalFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsCareportalFragment.java @@ -1,42 +1,44 @@ -package info.nightscout.androidaps.plugins.Treatments.fragments; +package info.nightscout.androidaps.plugins.treatments.fragments; -import android.app.Activity; import android.content.Context; import android.content.DialogInterface; -import android.content.Intent; import android.graphics.Paint; import android.os.Bundle; -import android.support.v7.app.AlertDialog; -import android.support.v7.widget.CardView; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.TextView; -import com.squareup.otto.Subscribe; +import androidx.appcompat.app.AlertDialog; +import androidx.cardview.widget.CardView; +import androidx.fragment.app.Fragment; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; import java.util.List; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.services.Intents; import info.nightscout.androidaps.db.CareportalEvent; import info.nightscout.androidaps.events.EventCareportalEventChange; -import info.nightscout.androidaps.plugins.Common.SubscriberFragment; -import info.nightscout.androidaps.plugins.NSClientInternal.UploadQueue; -import info.nightscout.utils.DateUtil; -import info.nightscout.androidaps.plugins.NSClientInternal.NSUpload; -import info.nightscout.utils.SP; -import info.nightscout.utils.Translator; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.general.nsclient.NSUpload; +import info.nightscout.androidaps.plugins.general.nsclient.UploadQueue; +import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart; +import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.FabricPrivacy; +import info.nightscout.androidaps.utils.SP; +import info.nightscout.androidaps.utils.Translator; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.CompositeDisposable; /** * Created by mike on 13/01/17. */ -public class TreatmentsCareportalFragment extends SubscriberFragment implements View.OnClickListener { +public class TreatmentsCareportalFragment extends Fragment implements View.OnClickListener { + private CompositeDisposable disposable = new CompositeDisposable(); RecyclerView recyclerView; LinearLayoutManager llm; @@ -148,10 +150,26 @@ public class TreatmentsCareportalFragment extends SubscriberFragment implements if (nsUploadOnly) refreshFromNS.setVisibility(View.GONE); - updateGUI(); return view; } + @Override + public synchronized void onResume() { + super.onResume(); + disposable.add(RxBus.INSTANCE + .toObservable(EventCareportalEventChange.class) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(event -> updateGui(), FabricPrivacy::logException) + ); + updateGui(); + } + + @Override + public synchronized void onPause() { + super.onPause(); + disposable.clear(); + } + @Override public void onClick(View view) { switch (view.getId()) { @@ -162,8 +180,7 @@ public class TreatmentsCareportalFragment extends SubscriberFragment implements builder.setPositiveButton(MainApp.gs(R.string.ok), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { MainApp.getDbHelper().resetCareportalEvents(); - Intent restartNSClient = new Intent(Intents.ACTION_RESTART); - MainApp.instance().getApplicationContext().sendBroadcast(restartNSClient); + RxBus.INSTANCE.send(new EventNSClientRestart()); } }); builder.setNegativeButton(MainApp.gs(R.string.cancel), null); @@ -183,21 +200,8 @@ public class TreatmentsCareportalFragment extends SubscriberFragment implements } - @Subscribe - public void onStatusEvent(final EventCareportalEventChange ev) { - updateGUI(); - } - - @Override - protected void updateGUI() { - Activity activity = getActivity(); - if (activity != null) - activity.runOnUiThread(new Runnable() { - @Override - public void run() { - recyclerView.swapAdapter(new RecyclerViewAdapter(MainApp.getDbHelper().getCareportalEvents(false)), false); - } - }); + private void updateGui() { + recyclerView.swapAdapter(new RecyclerViewAdapter(MainApp.getDbHelper().getCareportalEvents(false)), false); } private void removeAndroidAPSStatedEvents() { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsExtendedBolusesFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsExtendedBolusesFragment.java similarity index 80% rename from app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsExtendedBolusesFragment.java rename to app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsExtendedBolusesFragment.java index 037a1a0023..5ce7b57564 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsExtendedBolusesFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsExtendedBolusesFragment.java @@ -1,22 +1,20 @@ -package info.nightscout.androidaps.plugins.Treatments.fragments; +package info.nightscout.androidaps.plugins.treatments.fragments; -import android.app.Activity; import android.content.Context; import android.content.DialogInterface; import android.graphics.Paint; import android.os.Bundle; -import android.support.v4.content.ContextCompat; -import android.support.v7.app.AlertDialog; -import android.support.v7.widget.CardView; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; -import com.crashlytics.android.answers.CustomEvent; -import com.squareup.otto.Subscribe; +import androidx.appcompat.app.AlertDialog; +import androidx.cardview.widget.CardView; +import androidx.core.content.ContextCompat; +import androidx.fragment.app.Fragment; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; @@ -25,17 +23,21 @@ import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.db.ExtendedBolus; import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.events.EventExtendedBolusChange; -import info.nightscout.androidaps.events.EventNewBG; -import info.nightscout.androidaps.plugins.Common.SubscriberFragment; -import info.nightscout.androidaps.plugins.NSClientInternal.UploadQueue; -import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.DecimalFormatter; -import info.nightscout.utils.FabricPrivacy; -import info.nightscout.androidaps.plugins.NSClientInternal.NSUpload; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.general.nsclient.NSUpload; +import info.nightscout.androidaps.plugins.general.nsclient.UploadQueue; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutosensCalculationFinished; +import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; +import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.DecimalFormatter; +import info.nightscout.androidaps.utils.FabricPrivacy; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.CompositeDisposable; -public class TreatmentsExtendedBolusesFragment extends SubscriberFragment { +public class TreatmentsExtendedBolusesFragment extends Fragment { + private CompositeDisposable disposable = new CompositeDisposable(); + RecyclerView recyclerView; LinearLayoutManager llm; @@ -150,7 +152,6 @@ public class TreatmentsExtendedBolusesFragment extends SubscriberFragment { UploadQueue.removeID("dbAdd", _id); } MainApp.getDbHelper().delete(extendedBolus); - FabricPrivacy.getInstance().logCustom(new CustomEvent("RemoveExtendedBolus")); } }); builder.setNegativeButton(MainApp.gs(R.string.cancel), null); @@ -176,30 +177,33 @@ public class TreatmentsExtendedBolusesFragment extends SubscriberFragment { context = getContext(); - updateGUI(); return view; } - @Subscribe - public void onStatusEvent(final EventExtendedBolusChange ev) { - updateGUI(); - } - - @Subscribe - public void onStatusEvent(final EventNewBG ev) { - updateGUI(); + @Override + public synchronized void onResume() { + super.onResume(); + disposable.add(RxBus.INSTANCE + .toObservable(EventExtendedBolusChange.class) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(event -> updateGui(), FabricPrivacy::logException) + ); + disposable.add(RxBus.INSTANCE + .toObservable(EventAutosensCalculationFinished.class) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(event -> updateGui(), FabricPrivacy::logException) + ); + updateGui(); } @Override - protected void updateGUI() { - Activity activity = getActivity(); - if (activity != null && recyclerView != null) - activity.runOnUiThread(new Runnable() { - @Override - public void run() { - recyclerView.swapAdapter(new RecyclerViewAdapter(TreatmentsPlugin.getPlugin().getExtendedBolusesFromHistory()), false); - } - }); + public synchronized void onPause() { + super.onPause(); + disposable.clear(); + } + + private void updateGui() { + recyclerView.swapAdapter(new RecyclerViewAdapter(TreatmentsPlugin.getPlugin().getExtendedBolusesFromHistory()), false); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsProfileSwitchFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsProfileSwitchFragment.java similarity index 77% rename from app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsProfileSwitchFragment.java rename to app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsProfileSwitchFragment.java index 0edc704eb6..2d06b2824f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsProfileSwitchFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsProfileSwitchFragment.java @@ -1,24 +1,22 @@ -package info.nightscout.androidaps.plugins.Treatments.fragments; +package info.nightscout.androidaps.plugins.treatments.fragments; -import android.app.Activity; import android.content.Context; import android.content.DialogInterface; -import android.content.Intent; import android.graphics.Paint; import android.os.Bundle; -import android.support.v4.app.FragmentManager; -import android.support.v4.content.ContextCompat; -import android.support.v7.app.AlertDialog; -import android.support.v7.widget.CardView; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.TextView; -import com.squareup.otto.Subscribe; +import androidx.appcompat.app.AlertDialog; +import androidx.cardview.widget.CardView; +import androidx.core.content.ContextCompat; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -27,26 +25,30 @@ import java.util.List; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions; -import info.nightscout.androidaps.services.Intents; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.db.ProfileSwitch; import info.nightscout.androidaps.db.Source; -import info.nightscout.androidaps.events.EventProfileSwitchChange; -import info.nightscout.androidaps.plugins.Common.SubscriberFragment; -import info.nightscout.androidaps.plugins.NSClientInternal.UploadQueue; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.DecimalFormatter; -import info.nightscout.androidaps.plugins.NSClientInternal.NSUpload; -import info.nightscout.utils.SP; +import info.nightscout.androidaps.events.EventProfileNeedsUpdate; +import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; +import info.nightscout.androidaps.plugins.general.nsclient.NSUpload; +import info.nightscout.androidaps.plugins.general.nsclient.UploadQueue; +import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart; +import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.DecimalFormatter; +import info.nightscout.androidaps.utils.FabricPrivacy; +import info.nightscout.androidaps.utils.SP; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.CompositeDisposable; /** * Created by mike on 13/01/17. */ -public class TreatmentsProfileSwitchFragment extends SubscriberFragment implements View.OnClickListener { +public class TreatmentsProfileSwitchFragment extends Fragment implements View.OnClickListener { private Logger log = LoggerFactory.getLogger(L.UI); + private CompositeDisposable disposable = new CompositeDisposable(); RecyclerView recyclerView; LinearLayoutManager llm; @@ -159,10 +161,14 @@ public class TreatmentsProfileSwitchFragment extends SubscriberFragment implemen break; case R.id.profileswitch_date: case R.id.profileswitch_name: - long time = ((ProfileSwitch) v.getTag()).date; - ProfileViewerDialog pvd = ProfileViewerDialog.newInstance(time); + Bundle args = new Bundle(); + args.putLong("time", ((ProfileSwitch) v.getTag()).date); + args.putLong("mode", ProfileViewerDialog.Mode.RUNNING_PROFILE.ordinal()); + ProfileViewerDialog pvd = new ProfileViewerDialog(); + pvd.setArguments(args); FragmentManager manager = getFragmentManager(); - pvd.show(manager, "ProfileViewDialog"); + if (manager != null) + pvd.show(manager, "ProfileViewDialog"); break; } } @@ -191,10 +197,26 @@ public class TreatmentsProfileSwitchFragment extends SubscriberFragment implemen if (nsUploadOnly) refreshFromNS.setVisibility(View.GONE); - updateGUI(); return view; } + @Override + public synchronized void onResume() { + super.onResume(); + disposable.add(RxBus.INSTANCE + .toObservable(EventProfileNeedsUpdate.class) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(event -> updateGUI(), FabricPrivacy::logException) + ); + updateGUI(); + } + + @Override + public synchronized void onPause() { + super.onPause(); + disposable.clear(); + } + @Override public void onClick(View view) { switch (view.getId()) { @@ -205,8 +227,7 @@ public class TreatmentsProfileSwitchFragment extends SubscriberFragment implemen builder.setPositiveButton(MainApp.gs(R.string.ok), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { MainApp.getDbHelper().resetProfileSwitch(); - Intent restartNSClient = new Intent(Intents.ACTION_RESTART); - MainApp.instance().getApplicationContext().sendBroadcast(restartNSClient); + RxBus.INSTANCE.send(new EventNSClientRestart()); } }); builder.setNegativeButton(MainApp.gs(R.string.cancel), null); @@ -215,20 +236,7 @@ public class TreatmentsProfileSwitchFragment extends SubscriberFragment implemen } } - @Subscribe - public void onStatusEvent(final EventProfileSwitchChange ev) { - updateGUI(); - } - - @Override protected void updateGUI() { - Activity activity = getActivity(); - if (activity != null) - activity.runOnUiThread(new Runnable() { - @Override - public void run() { - recyclerView.swapAdapter(new RecyclerViewAdapter(MainApp.getDbHelper().getProfileSwitchData(false)), false); - } - }); + recyclerView.swapAdapter(new RecyclerViewAdapter(MainApp.getDbHelper().getProfileSwitchData(false)), false); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsTempTargetFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsTempTargetFragment.java similarity index 82% rename from app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsTempTargetFragment.java rename to app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsTempTargetFragment.java index d60dfc9e4c..ccd1b327c9 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsTempTargetFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsTempTargetFragment.java @@ -1,45 +1,48 @@ -package info.nightscout.androidaps.plugins.Treatments.fragments; +package info.nightscout.androidaps.plugins.treatments.fragments; import android.app.Activity; import android.content.Context; import android.content.DialogInterface; -import android.content.Intent; import android.graphics.Paint; import android.os.Bundle; -import android.support.v4.content.ContextCompat; -import android.support.v7.app.AlertDialog; -import android.support.v7.widget.CardView; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.TextView; -import com.squareup.otto.Subscribe; +import androidx.appcompat.app.AlertDialog; +import androidx.cardview.widget.CardView; +import androidx.core.content.ContextCompat; +import androidx.fragment.app.Fragment; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions; -import info.nightscout.androidaps.services.Intents; import info.nightscout.androidaps.data.Intervals; import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.TempTarget; import info.nightscout.androidaps.events.EventTempTargetChange; -import info.nightscout.androidaps.plugins.Common.SubscriberFragment; -import info.nightscout.androidaps.plugins.NSClientInternal.UploadQueue; -import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.DecimalFormatter; -import info.nightscout.androidaps.plugins.NSClientInternal.NSUpload; -import info.nightscout.utils.SP; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; +import info.nightscout.androidaps.plugins.general.nsclient.NSUpload; +import info.nightscout.androidaps.plugins.general.nsclient.UploadQueue; +import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart; +import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; +import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.DecimalFormatter; +import info.nightscout.androidaps.utils.FabricPrivacy; +import info.nightscout.androidaps.utils.SP; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.CompositeDisposable; /** * Created by mike on 13/01/17. */ -public class TreatmentsTempTargetFragment extends SubscriberFragment implements View.OnClickListener { +public class TreatmentsTempTargetFragment extends Fragment implements View.OnClickListener { + private CompositeDisposable disposable = new CompositeDisposable(); RecyclerView recyclerView; LinearLayoutManager llm; @@ -184,10 +187,26 @@ public class TreatmentsTempTargetFragment extends SubscriberFragment implements if (nsUploadOnly) refreshFromNS.setVisibility(View.GONE); - updateGUI(); return view; } + @Override + public synchronized void onResume() { + super.onResume(); + disposable.add(RxBus.INSTANCE + .toObservable(EventTempTargetChange.class) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(event -> updateGui(), FabricPrivacy::logException) + ); + updateGui(); + } + + @Override + public synchronized void onPause() { + super.onPause(); + disposable.clear(); + } + @Override public void onClick(View view) { switch (view.getId()) { @@ -198,8 +217,7 @@ public class TreatmentsTempTargetFragment extends SubscriberFragment implements builder.setPositiveButton(MainApp.gs(R.string.ok), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { MainApp.getDbHelper().resetTempTargets(); - Intent restartNSClient = new Intent(Intents.ACTION_RESTART); - MainApp.instance().getApplicationContext().sendBroadcast(restartNSClient); + RxBus.INSTANCE.send(new EventNSClientRestart()); } }); builder.setNegativeButton(MainApp.gs(R.string.cancel), null); @@ -209,20 +227,7 @@ public class TreatmentsTempTargetFragment extends SubscriberFragment implements } - @Subscribe - public void onStatusEvent(final EventTempTargetChange ev) { - updateGUI(); - } - - @Override - protected void updateGUI() { - Activity activity = getActivity(); - if (activity != null) - activity.runOnUiThread(new Runnable() { - @Override - public void run() { - recyclerView.swapAdapter(new RecyclerViewAdapter(TreatmentsPlugin.getPlugin().getTempTargetsFromHistory()), false); - } - }); + private void updateGui() { + recyclerView.swapAdapter(new RecyclerViewAdapter(TreatmentsPlugin.getPlugin().getTempTargetsFromHistory()), false); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsTemporaryBasalsFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsTemporaryBasalsFragment.java similarity index 78% rename from app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsTemporaryBasalsFragment.java rename to app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsTemporaryBasalsFragment.java index 3185bd81ac..45f930410e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsTemporaryBasalsFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsTemporaryBasalsFragment.java @@ -1,22 +1,20 @@ -package info.nightscout.androidaps.plugins.Treatments.fragments; +package info.nightscout.androidaps.plugins.treatments.fragments; -import android.app.Activity; import android.content.Context; import android.graphics.Paint; import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.v4.content.ContextCompat; -import android.support.v7.app.AlertDialog; -import android.support.v7.widget.CardView; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; -import com.crashlytics.android.answers.CustomEvent; -import com.squareup.otto.Subscribe; +import androidx.annotation.NonNull; +import androidx.appcompat.app.AlertDialog; +import androidx.cardview.widget.CardView; +import androidx.core.content.ContextCompat; +import androidx.fragment.app.Fragment; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; @@ -25,19 +23,23 @@ import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.TemporaryBasal; -import info.nightscout.androidaps.events.EventNewBG; import info.nightscout.androidaps.events.EventTempBasalChange; -import info.nightscout.androidaps.plugins.Common.SubscriberFragment; -import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions; -import info.nightscout.androidaps.plugins.NSClientInternal.UploadQueue; -import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.DecimalFormatter; -import info.nightscout.utils.FabricPrivacy; -import info.nightscout.androidaps.plugins.NSClientInternal.NSUpload; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; +import info.nightscout.androidaps.plugins.general.nsclient.NSUpload; +import info.nightscout.androidaps.plugins.general.nsclient.UploadQueue; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutosensCalculationFinished; +import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; +import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.DecimalFormatter; +import info.nightscout.androidaps.utils.FabricPrivacy; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.CompositeDisposable; -public class TreatmentsTemporaryBasalsFragment extends SubscriberFragment { +public class TreatmentsTemporaryBasalsFragment extends Fragment { + private CompositeDisposable disposable = new CompositeDisposable(); + RecyclerView recyclerView; LinearLayoutManager llm; @@ -87,7 +89,7 @@ public class TreatmentsTemporaryBasalsFragment extends SubscriberFragment { if (tempBasal.isAbsolute) { Profile profile = ProfileFunctions.getInstance().getProfile(tempBasal.date); if (profile != null) { - holder.absolute.setText(DecimalFormatter.to0Decimal(tempBasal.tempBasalConvertedToAbsolute(tempBasal.date, profile), " U/h")); + holder.absolute.setText(DecimalFormatter.to2Decimal(tempBasal.tempBasalConvertedToAbsolute(tempBasal.date, profile), " U/h")); holder.percent.setText(""); } else { holder.absolute.setText(MainApp.gs(R.string.noprofile)); @@ -175,7 +177,6 @@ public class TreatmentsTemporaryBasalsFragment extends SubscriberFragment { UploadQueue.removeID("dbAdd", _id); } MainApp.getDbHelper().delete(tempBasal); - FabricPrivacy.getInstance().logCustom(new CustomEvent("RemoveTempBasal")); }); builder.setNegativeButton(MainApp.gs(R.string.cancel), null); builder.show(); @@ -202,30 +203,36 @@ public class TreatmentsTemporaryBasalsFragment extends SubscriberFragment { context = getContext(); - updateGUI(); return view; } - @Subscribe - public void onStatusEvent(final EventTempBasalChange ignored) { - updateGUI(); - } - - @Subscribe - public void onStatusEvent(final EventNewBG ignored) { - updateGUI(); + @Override + public synchronized void onResume() { + super.onResume(); + disposable.add(RxBus.INSTANCE + .toObservable(EventTempBasalChange.class) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(event -> updateGui(), FabricPrivacy::logException) + ); + disposable.add(RxBus.INSTANCE + .toObservable(EventAutosensCalculationFinished.class) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(event -> updateGui(), FabricPrivacy::logException) + ); + updateGui(); } @Override - protected void updateGUI() { - Activity activity = getActivity(); - if (activity != null) - activity.runOnUiThread(() -> { - recyclerView.swapAdapter(new RecyclerViewAdapter(TreatmentsPlugin.getPlugin().getTemporaryBasalsFromHistory()), false); - IobTotal tempBasalsCalculation = TreatmentsPlugin.getPlugin().getLastCalculationTempBasals(); - if (tempBasalsCalculation != null) - tempBasalTotalView.setText(DecimalFormatter.to2Decimal(tempBasalsCalculation.basaliob, " U")); - }); + public synchronized void onPause() { + super.onPause(); + disposable.clear(); + } + + private void updateGui() { + recyclerView.swapAdapter(new RecyclerViewAdapter(TreatmentsPlugin.getPlugin().getTemporaryBasalsFromHistory()), false); + IobTotal tempBasalsCalculation = TreatmentsPlugin.getPlugin().getLastCalculationTempBasals(); + if (tempBasalsCalculation != null) + tempBasalTotalView.setText(DecimalFormatter.to2Decimal(tempBasalsCalculation.basaliob, " U")); } } diff --git a/app/src/main/java/info/nightscout/androidaps/queue/CommandQueue.java b/app/src/main/java/info/nightscout/androidaps/queue/CommandQueue.java index 69979508fe..f24b02171f 100644 --- a/app/src/main/java/info/nightscout/androidaps/queue/CommandQueue.java +++ b/app/src/main/java/info/nightscout/androidaps/queue/CommandQueue.java @@ -3,10 +3,11 @@ package info.nightscout.androidaps.queue; import android.content.Context; import android.content.Intent; import android.os.SystemClock; -import android.support.v7.app.AppCompatActivity; import android.text.Html; import android.text.Spanned; +import androidx.appcompat.app.AppCompatActivity; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -21,20 +22,22 @@ import info.nightscout.androidaps.events.EventBolusRequested; import info.nightscout.androidaps.interfaces.Constraint; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions; -import info.nightscout.androidaps.plugins.Overview.Dialogs.BolusProgressDialog; -import info.nightscout.androidaps.plugins.Overview.Dialogs.BolusProgressHelperActivity; -import info.nightscout.androidaps.plugins.Overview.events.EventDismissBolusprogressIfRunning; -import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; -import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; -import info.nightscout.androidaps.plugins.Overview.notifications.Notification; -import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; +import info.nightscout.androidaps.plugins.general.overview.dialogs.BolusProgressDialog; +import info.nightscout.androidaps.plugins.general.overview.dialogs.BolusProgressHelperActivity; +import info.nightscout.androidaps.plugins.general.overview.events.EventDismissBolusProgressIfRunning; +import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification; +import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; +import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; import info.nightscout.androidaps.queue.commands.Command; import info.nightscout.androidaps.queue.commands.CommandBolus; import info.nightscout.androidaps.queue.commands.CommandCancelExtendedBolus; import info.nightscout.androidaps.queue.commands.CommandCancelTempBasal; import info.nightscout.androidaps.queue.commands.CommandExtendedBolus; +import info.nightscout.androidaps.queue.commands.CommandInsightSetTBROverNotification; import info.nightscout.androidaps.queue.commands.CommandLoadEvents; import info.nightscout.androidaps.queue.commands.CommandLoadHistory; import info.nightscout.androidaps.queue.commands.CommandLoadTDDs; @@ -42,6 +45,8 @@ import info.nightscout.androidaps.queue.commands.CommandReadStatus; import info.nightscout.androidaps.queue.commands.CommandSMBBolus; import info.nightscout.androidaps.queue.commands.CommandSetProfile; import info.nightscout.androidaps.queue.commands.CommandSetUserSettings; +import info.nightscout.androidaps.queue.commands.CommandStartPump; +import info.nightscout.androidaps.queue.commands.CommandStopPump; import info.nightscout.androidaps.queue.commands.CommandTempBasalAbsolute; import info.nightscout.androidaps.queue.commands.CommandTempBasalPercent; @@ -96,16 +101,20 @@ public class CommandQueue { } private synchronized void removeAll(Command.CommandType type) { - for (int i = queue.size() - 1; i >= 0; i--) { - if (queue.get(i).commandType == type) { - queue.remove(i); + synchronized (queue) { + for (int i = queue.size() - 1; i >= 0; i--) { + if (queue.get(i).commandType == type) { + queue.remove(i); + } } } } private synchronized boolean isLastScheduled(Command.CommandType type) { - if (queue.size() > 0 && queue.get(queue.size() - 1).commandType == type) { - return true; + synchronized (queue) { + if (queue.size() > 0 && queue.get(queue.size() - 1).commandType == type) { + return true; + } } return false; } @@ -114,37 +123,44 @@ public class CommandQueue { // inject as a first command if (L.isEnabled(L.PUMPQUEUE)) log.debug("Adding as first: " + command.getClass().getSimpleName() + " - " + command.status()); - queue.addFirst(command); + synchronized (queue) { + queue.addFirst(command); + } } private synchronized void add(Command command) { if (L.isEnabled(L.PUMPQUEUE)) log.debug("Adding: " + command.getClass().getSimpleName() + " - " + command.status()); - queue.add(command); + synchronized (queue) { + queue.add(command); + } } synchronized void pickup() { - performing = queue.poll(); + synchronized (queue) { + performing = queue.poll(); + } } synchronized void clear() { performing = null; - for (int i = 0; i < queue.size(); i++) { - queue.get(i).cancel(); + synchronized (queue) { + for (int i = 0; i < queue.size(); i++) { + queue.get(i).cancel(); + } + queue.clear(); } - - queue.clear(); } public int size() { return queue.size(); } - public Command performing() { + Command performing() { return performing; } - public void resetPerforming() { + void resetPerforming() { performing = null; } @@ -176,9 +192,11 @@ public class CommandQueue { public synchronized boolean bolusInQueue() { if (isRunning(Command.CommandType.BOLUS)) return true; - for (int i = 0; i < queue.size(); i++) { - if (queue.get(i).commandType == Command.CommandType.BOLUS) { - return true; + synchronized (queue) { + for (int i = 0; i < queue.size(); i++) { + if (queue.get(i).commandType == Command.CommandType.BOLUS) { + return true; + } } } return false; @@ -189,7 +207,7 @@ public class CommandQueue { Command.CommandType type = detailedBolusInfo.isSMB ? Command.CommandType.SMB_BOLUS : Command.CommandType.BOLUS; if (type == Command.CommandType.SMB_BOLUS) { - if (isRunning(Command.CommandType.BOLUS) || bolusInQueue()) { + if (isRunning(Command.CommandType.BOLUS) || isRunning(Command.CommandType.SMB_BOLUS) || bolusInQueue()) { if (L.isEnabled(L.PUMPQUEUE)) log.debug("Rejecting SMB since a bolus is queue/running"); return false; @@ -199,6 +217,7 @@ public class CommandQueue { log.debug("Rejecting bolus, another bolus was issued since request time"); return false; } + removeAll(Command.CommandType.SMB_BOLUS); } @@ -230,7 +249,7 @@ public class CommandQueue { // not when the Bolus command is starting. The command closes the dialog upon completion). showBolusProgressDialog(detailedBolusInfo.insulin, detailedBolusInfo.context); // Notify Wear about upcoming bolus - MainApp.bus().post(new EventBolusRequested(detailedBolusInfo.insulin)); + RxBus.INSTANCE.send(new EventBolusRequested(detailedBolusInfo.insulin)); } } @@ -239,9 +258,24 @@ public class CommandQueue { return true; } + public void stopPump(Callback callback) { + add(new CommandStopPump(callback)); + notifyAboutNewCommand(); + } + + public void startPump(Callback callback) { + add(new CommandStartPump(callback)); + notifyAboutNewCommand(); + } + + public void setTBROverNotification(Callback callback, boolean enable) { + add(new CommandInsightSetTBROverNotification(callback, enable)); + notifyAboutNewCommand(); + } + public synchronized void cancelAllBoluses() { if (!isRunning(Command.CommandType.BOLUS)) { - MainApp.bus().post(new EventDismissBolusprogressIfRunning(new PumpEnactResult().success(true).enacted(false))); + RxBus.INSTANCE.send(new EventDismissBolusProgressIfRunning(new PumpEnactResult().success(true).enacted(false))); } removeAll(Command.CommandType.BOLUS); removeAll(Command.CommandType.SMB_BOLUS); @@ -361,27 +395,27 @@ public class CommandQueue { if (!MainApp.isEngineeringModeOrRelease()) { Notification notification = new Notification(Notification.NOT_ENG_MODE_OR_RELEASE, MainApp.gs(R.string.not_eng_mode_or_release), Notification.URGENT); - MainApp.bus().post(new EventNewNotification(notification)); + RxBus.INSTANCE.send(new EventNewNotification(notification)); if (callback != null) - callback.result(new PumpEnactResult().success(false).comment(MainApp.gs(R.string.not_eng_mode_or_release))).run(); + callback.result(new PumpEnactResult().success(false).enacted(false).comment(MainApp.gs(R.string.not_eng_mode_or_release))).run(); return false; } // Compare with pump limits - Profile.BasalValue[] basalValues = profile.getBasalValues(); + Profile.ProfileValue[] basalValues = profile.getBasalValues(); PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump(); - for (Profile.BasalValue basalValue : basalValues) { + for (Profile.ProfileValue basalValue : basalValues) { if (basalValue.value < pump.getPumpDescription().basalMinimumRate) { Notification notification = new Notification(Notification.BASAL_VALUE_BELOW_MINIMUM, MainApp.gs(R.string.basalvaluebelowminimum), Notification.URGENT); - MainApp.bus().post(new EventNewNotification(notification)); + RxBus.INSTANCE.send(new EventNewNotification(notification)); if (callback != null) - callback.result(new PumpEnactResult().success(false).comment(MainApp.gs(R.string.basalvaluebelowminimum))).run(); + callback.result(new PumpEnactResult().success(false).enacted(false).comment(MainApp.gs(R.string.basalvaluebelowminimum))).run(); return false; } } - MainApp.bus().post(new EventDismissNotification(Notification.BASAL_VALUE_BELOW_MINIMUM)); + RxBus.INSTANCE.send(new EventDismissNotification(Notification.BASAL_VALUE_BELOW_MINIMUM)); // remove all unfinished removeAll(Command.CommandType.BASALPROFILE); @@ -415,6 +449,21 @@ public class CommandQueue { return true; } + + public synchronized boolean statusInQueue() { + if (isRunning(Command.CommandType.READSTATUS)) + return true; + synchronized (queue) { + for (int i = 0; i < queue.size(); i++) { + if (queue.get(i).commandType == Command.CommandType.READSTATUS) { + return true; + } + } + } + return false; + } + + // returns true if command is queued public boolean loadHistory(byte type, Callback callback) { if (isRunning(Command.CommandType.LOADHISTORY)) { @@ -494,15 +543,18 @@ public class CommandQueue { public Spanned spannedStatus() { String s = ""; int line = 0; - if (performing != null) { - s += "" + performing.status() + ""; + Command perf = performing; + if (perf != null) { + s += "" + perf.status() + ""; line++; } - for (int i = 0; i < queue.size(); i++) { - if (line != 0) - s += "
"; - s += queue.get(i).status(); - line++; + synchronized (queue) { + for (int i = 0; i < queue.size(); i++) { + if (line != 0) + s += "
"; + s += queue.get(i).status(); + line++; + } } return Html.fromHtml(s); } diff --git a/app/src/main/java/info/nightscout/androidaps/queue/QueueThread.java b/app/src/main/java/info/nightscout/androidaps/queue/QueueThread.java index 7c95498db4..85823c2c30 100644 --- a/app/src/main/java/info/nightscout/androidaps/queue/QueueThread.java +++ b/app/src/main/java/info/nightscout/androidaps/queue/QueueThread.java @@ -2,7 +2,6 @@ package info.nightscout.androidaps.queue; import android.bluetooth.BluetoothAdapter; import android.content.Context; -import android.content.ContextWrapper; import android.os.PowerManager; import android.os.SystemClock; @@ -15,10 +14,12 @@ import info.nightscout.androidaps.R; import info.nightscout.androidaps.events.EventPumpStatusChanged; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.Overview.events.EventDismissBolusprogressIfRunning; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.general.overview.events.EventDismissBolusProgressIfRunning; import info.nightscout.androidaps.queue.events.EventQueueChanged; -import info.nightscout.utils.SP; +import info.nightscout.androidaps.utils.SP; +import info.nightscout.androidaps.utils.T; /** * Created by mike on 09.11.2017. @@ -29,9 +30,8 @@ public class QueueThread extends Thread { private CommandQueue queue; - private long lastCommandTime = 0; private boolean connectLogged = false; - public boolean waitingForDisconnect = false; + boolean waitingForDisconnect = false; private PowerManager.WakeLock mWakeLock; @@ -42,14 +42,17 @@ public class QueueThread extends Thread { Context context = MainApp.instance().getApplicationContext(); if (context != null) { PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); - mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "QueueThread"); + if (powerManager != null) + mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "AndroidAPS:QueueThread"); } } @Override public final void run() { - mWakeLock.acquire(); - MainApp.bus().post(new EventQueueChanged()); + if (mWakeLock != null) + mWakeLock.acquire(T.mins(10).msecs()); + RxBus.INSTANCE.send(new EventQueueChanged()); + long lastCommandTime; long connectionStartTime = lastCommandTime = System.currentTimeMillis(); try { @@ -58,22 +61,22 @@ public class QueueThread extends Thread { if (pump == null) { if (L.isEnabled(L.PUMPQUEUE)) log.debug("pump == null"); - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.pumpNotInitialized))); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.pumpNotInitialized))); SystemClock.sleep(1000); continue; } long secondsElapsed = (System.currentTimeMillis() - connectionStartTime) / 1000; if (!pump.isConnected() && secondsElapsed > Constants.PUMP_MAX_CONNECTION_TIME_IN_SECONDS) { - MainApp.bus().post(new EventDismissBolusprogressIfRunning(null)); - MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.connectiontimedout))); + RxBus.INSTANCE.send(new EventDismissBolusProgressIfRunning(null)); + RxBus.INSTANCE.send(new EventPumpStatusChanged(MainApp.gs(R.string.connectiontimedout))); if (L.isEnabled(L.PUMPQUEUE)) log.debug("timed out"); pump.stopConnecting(); //BLUETOOTH-WATCHDOG boolean watchdog = SP.getBoolean(R.string.key_btwatchdog, false); - long last_watchdog = SP.getLong(R.string.key_btwatchdog_lastbark, 0l); + long last_watchdog = SP.getLong(R.string.key_btwatchdog_lastbark, 0L); watchdog = watchdog && System.currentTimeMillis() - last_watchdog > (Constants.MIN_WATCHDOG_INTERVAL_IN_SECONDS * 1000); if (watchdog) { if (L.isEnabled(L.PUMPQUEUE)) @@ -91,16 +94,16 @@ public class QueueThread extends Thread { SystemClock.sleep(1000); //start over again once after watchdog barked //Notification notification = new Notification(Notification.OLD_NSCLIENT, "Watchdog", Notification.URGENT); - //MainApp.bus().post(new EventNewNotification(notification)); + //RxBus.INSTANCE.send(new EventNewNotification(notification)); connectionStartTime = lastCommandTime = System.currentTimeMillis(); pump.connect("watchdog"); } else { queue.clear(); if (L.isEnabled(L.PUMPQUEUE)) log.debug("no connection possible"); - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING)); + RxBus.INSTANCE.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING)); pump.disconnect("Queue empty"); - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTED)); + RxBus.INSTANCE.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTED)); return; } } @@ -108,7 +111,7 @@ public class QueueThread extends Thread { if (pump.isHandshakeInProgress()) { if (L.isEnabled(L.PUMPQUEUE)) log.debug("handshaking " + secondsElapsed); - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.HANDSHAKING, (int) secondsElapsed)); + RxBus.INSTANCE.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.HANDSHAKING, (int) secondsElapsed)); SystemClock.sleep(100); continue; } @@ -116,7 +119,7 @@ public class QueueThread extends Thread { if (pump.isConnecting()) { if (L.isEnabled(L.PUMPQUEUE)) log.debug("connecting " + secondsElapsed); - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.CONNECTING, (int) secondsElapsed)); + RxBus.INSTANCE.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.CONNECTING, (int) secondsElapsed)); SystemClock.sleep(1000); continue; } @@ -124,7 +127,7 @@ public class QueueThread extends Thread { if (!pump.isConnected()) { if (L.isEnabled(L.PUMPQUEUE)) log.debug("connect"); - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.CONNECTING, (int) secondsElapsed)); + RxBus.INSTANCE.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.CONNECTING, (int) secondsElapsed)); pump.connect("Connection needed"); SystemClock.sleep(1000); continue; @@ -139,15 +142,17 @@ public class QueueThread extends Thread { // Pickup 1st command and set performing variable if (queue.size() > 0) { queue.pickup(); - if (L.isEnabled(L.PUMPQUEUE)) - log.debug("performing " + queue.performing().status()); - MainApp.bus().post(new EventQueueChanged()); - queue.performing().execute(); - queue.resetPerforming(); - MainApp.bus().post(new EventQueueChanged()); - lastCommandTime = System.currentTimeMillis(); - SystemClock.sleep(100); - continue; + if (queue.performing() != null) { + if (L.isEnabled(L.PUMPQUEUE)) + log.debug("performing " + queue.performing().status()); + RxBus.INSTANCE.send(new EventQueueChanged()); + queue.performing().execute(); + queue.resetPerforming(); + RxBus.INSTANCE.send(new EventQueueChanged()); + lastCommandTime = System.currentTimeMillis(); + SystemClock.sleep(100); + continue; + } } } @@ -157,9 +162,9 @@ public class QueueThread extends Thread { waitingForDisconnect = true; if (L.isEnabled(L.PUMPQUEUE)) log.debug("queue empty. disconnect"); - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING)); + RxBus.INSTANCE.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING)); pump.disconnect("Queue empty"); - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTED)); + RxBus.INSTANCE.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTED)); if (L.isEnabled(L.PUMPQUEUE)) log.debug("disconnected"); return; @@ -171,7 +176,8 @@ public class QueueThread extends Thread { } } } finally { - mWakeLock.release(); + if (mWakeLock != null && mWakeLock.isHeld()) + mWakeLock.release(); if (L.isEnabled(L.PUMPQUEUE)) log.debug("thread end"); } diff --git a/app/src/main/java/info/nightscout/androidaps/queue/commands/Command.java b/app/src/main/java/info/nightscout/androidaps/queue/commands/Command.java index 7207f5b8d1..97a7e68521 100644 --- a/app/src/main/java/info/nightscout/androidaps/queue/commands/Command.java +++ b/app/src/main/java/info/nightscout/androidaps/queue/commands/Command.java @@ -25,7 +25,10 @@ public abstract class Command { READSTATUS, LOADHISTORY, // TDDs and so far only Dana specific LOADEVENTS, // so far only Dana specific - SETUSERSETTINGS // so far only Dana specific + SETUSERSETTINGS, // so far only Dana specific, + START_PUMP, + STOP_PUMP, + INSIGHT_SET_TBR_OVER_ALARM } public CommandType commandType; diff --git a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandBolus.java b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandBolus.java index c239502187..6348ea31b9 100644 --- a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandBolus.java +++ b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandBolus.java @@ -3,15 +3,15 @@ package info.nightscout.androidaps.queue.commands; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.Overview.Dialogs.BolusProgressDialog; -import info.nightscout.androidaps.plugins.Overview.events.EventDismissBolusprogressIfRunning; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.general.overview.dialogs.BolusProgressDialog; +import info.nightscout.androidaps.plugins.general.overview.events.EventDismissBolusProgressIfRunning; import info.nightscout.androidaps.queue.Callback; -import info.nightscout.utils.DecimalFormatter; +import info.nightscout.androidaps.utils.DecimalFormatter; /** * Created by mike on 09.11.2017. @@ -33,7 +33,7 @@ public class CommandBolus extends Command { PumpEnactResult r = ConfigBuilderPlugin.getPlugin().getActivePump().deliverTreatment(detailedBolusInfo); BolusProgressDialog.bolusEnded = true; - MainApp.bus().post(new EventDismissBolusprogressIfRunning(r)); + RxBus.INSTANCE.send(new EventDismissBolusProgressIfRunning(r)); if (L.isEnabled(L.PUMPQUEUE)) log.debug("Result success: " + r.success + " enacted: " + r.enacted); diff --git a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandCancelExtendedBolus.java b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandCancelExtendedBolus.java index 8dca488890..84ff1942a5 100644 --- a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandCancelExtendedBolus.java +++ b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandCancelExtendedBolus.java @@ -5,7 +5,7 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.queue.Callback; /** diff --git a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandCancelTempBasal.java b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandCancelTempBasal.java index 241ae015fb..d6ef30ed36 100644 --- a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandCancelTempBasal.java +++ b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandCancelTempBasal.java @@ -5,7 +5,7 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.queue.Callback; /** diff --git a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandExtendedBolus.java b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandExtendedBolus.java index ea513bbb6c..7609973cf0 100644 --- a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandExtendedBolus.java +++ b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandExtendedBolus.java @@ -5,7 +5,7 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.queue.Callback; /** diff --git a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandInsightSetTBROverNotification.java b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandInsightSetTBROverNotification.java new file mode 100644 index 0000000000..e65aa31a29 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandInsightSetTBROverNotification.java @@ -0,0 +1,32 @@ +package info.nightscout.androidaps.queue.commands; + +import info.nightscout.androidaps.data.PumpEnactResult; +import info.nightscout.androidaps.interfaces.PumpInterface; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.pump.insight.LocalInsightPlugin; +import info.nightscout.androidaps.queue.Callback; + +public class CommandInsightSetTBROverNotification extends Command { + + private boolean enabled; + + public CommandInsightSetTBROverNotification(Callback callback, boolean enabled) { + commandType = CommandType.INSIGHT_SET_TBR_OVER_ALARM; + this.callback = callback; + this.enabled = enabled; + } + + @Override + public void execute() { + PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump(); + if (pump instanceof LocalInsightPlugin) { + PumpEnactResult result = ((LocalInsightPlugin) pump).setTBROverNotification(enabled); + if (callback != null) callback.result(result).run(); + } + } + + @Override + public String status() { + return "INSIGHTSETTBROVERNOTIFICATION"; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandLoadEvents.java b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandLoadEvents.java index 0742075035..30791a1831 100644 --- a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandLoadEvents.java +++ b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandLoadEvents.java @@ -7,7 +7,7 @@ import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.interfaces.DanaRInterface; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.queue.Callback; /** diff --git a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandLoadHistory.java b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandLoadHistory.java index 01ec6e1f16..fc6fd49d8f 100644 --- a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandLoadHistory.java +++ b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandLoadHistory.java @@ -7,7 +7,7 @@ import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.interfaces.DanaRInterface; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.queue.Callback; /** diff --git a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandLoadTDDs.java b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandLoadTDDs.java index c072766310..e70b5f2261 100644 --- a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandLoadTDDs.java +++ b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandLoadTDDs.java @@ -6,7 +6,7 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.queue.Callback; /** diff --git a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandReadStatus.java b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandReadStatus.java index 7e5bded5ee..070aec809e 100644 --- a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandReadStatus.java +++ b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandReadStatus.java @@ -6,10 +6,10 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.queue.Callback; -import info.nightscout.utils.LocalAlertUtils; -import info.nightscout.utils.T; +import info.nightscout.androidaps.utils.LocalAlertUtils; +import info.nightscout.androidaps.utils.T; /** * Created by mike on 09.11.2017. diff --git a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandSMBBolus.java b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandSMBBolus.java index 1bd958866e..4586389dc1 100644 --- a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandSMBBolus.java +++ b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandSMBBolus.java @@ -6,12 +6,12 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; import info.nightscout.androidaps.queue.Callback; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.DecimalFormatter; -import info.nightscout.utils.T; +import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.DecimalFormatter; +import info.nightscout.androidaps.utils.T; /** * Created by mike on 09.11.2017. diff --git a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandSetProfile.java b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandSetProfile.java index a9bf7258e3..62e14285eb 100644 --- a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandSetProfile.java +++ b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandSetProfile.java @@ -11,9 +11,9 @@ import info.nightscout.androidaps.db.ProfileSwitch; import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.interfaces.PluginType; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.SmsCommunicator.SmsCommunicatorPlugin; -import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin; +import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; import info.nightscout.androidaps.queue.Callback; /** @@ -50,8 +50,8 @@ public class CommandSetProfile extends Command { // Send SMS notification if ProfileSwitch is comming from NS ProfileSwitch profileSwitch = TreatmentsPlugin.getPlugin().getProfileSwitchFromHistory(System.currentTimeMillis()); if (profileSwitch != null && r.enacted && profileSwitch.source == Source.NIGHTSCOUT) { - SmsCommunicatorPlugin smsCommunicatorPlugin = MainApp.getSpecificPlugin(SmsCommunicatorPlugin.class); - if (smsCommunicatorPlugin != null && smsCommunicatorPlugin.isEnabled(PluginType.GENERAL)) { + SmsCommunicatorPlugin smsCommunicatorPlugin = SmsCommunicatorPlugin.getPlugin(); + if (smsCommunicatorPlugin.isEnabled(PluginType.GENERAL)) { smsCommunicatorPlugin.sendNotificationToAllNumbers(MainApp.gs(R.string.profile_set_ok)); } } diff --git a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandSetUserSettings.java b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandSetUserSettings.java index c1bf69ce01..643dbed3ab 100644 --- a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandSetUserSettings.java +++ b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandSetUserSettings.java @@ -7,7 +7,7 @@ import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.interfaces.DanaRInterface; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.queue.Callback; /** diff --git a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandStartPump.java b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandStartPump.java new file mode 100644 index 0000000000..24694a1778 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandStartPump.java @@ -0,0 +1,29 @@ +package info.nightscout.androidaps.queue.commands; + +import info.nightscout.androidaps.data.PumpEnactResult; +import info.nightscout.androidaps.interfaces.PumpInterface; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.pump.insight.LocalInsightPlugin; +import info.nightscout.androidaps.queue.Callback; + +public class CommandStartPump extends Command { + + public CommandStartPump(Callback callback) { + commandType = CommandType.START_PUMP; + this.callback = callback; + } + + @Override + public void execute() { + PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump(); + if (pump instanceof LocalInsightPlugin) { + PumpEnactResult result = ((LocalInsightPlugin) pump).startPump(); + if (callback != null) callback.result(result).run(); + } + } + + @Override + public String status() { + return "STARTPUMP"; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandStopPump.java b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandStopPump.java new file mode 100644 index 0000000000..6f1cd8ec77 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandStopPump.java @@ -0,0 +1,29 @@ +package info.nightscout.androidaps.queue.commands; + +import info.nightscout.androidaps.data.PumpEnactResult; +import info.nightscout.androidaps.interfaces.PumpInterface; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.pump.insight.LocalInsightPlugin; +import info.nightscout.androidaps.queue.Callback; + +public class CommandStopPump extends Command { + + public CommandStopPump(Callback callback) { + commandType = CommandType.STOP_PUMP; + this.callback = callback; + } + + @Override + public void execute() { + PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump(); + if (pump instanceof LocalInsightPlugin) { + PumpEnactResult result = ((LocalInsightPlugin) pump).stopPump(); + if (callback != null) callback.result(result).run(); + } + } + + @Override + public String status() { + return "STOPPUMP"; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandTempBasalAbsolute.java b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandTempBasalAbsolute.java index 9e75fd0713..1e36a1ab04 100644 --- a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandTempBasalAbsolute.java +++ b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandTempBasalAbsolute.java @@ -6,7 +6,7 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.queue.Callback; /** diff --git a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandTempBasalPercent.java b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandTempBasalPercent.java index 2bc44e269e..68da3b9865 100644 --- a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandTempBasalPercent.java +++ b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandTempBasalPercent.java @@ -6,7 +6,7 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.queue.Callback; /** diff --git a/app/src/main/java/info/nightscout/androidaps/queue/events/EventQueueChanged.java b/app/src/main/java/info/nightscout/androidaps/queue/events/EventQueueChanged.java deleted file mode 100644 index b0a53afd13..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/queue/events/EventQueueChanged.java +++ /dev/null @@ -1,8 +0,0 @@ -package info.nightscout.androidaps.queue.events; - -/** - * Created by mike on 11.11.2017. - */ - -public class EventQueueChanged { -} diff --git a/app/src/main/java/info/nightscout/androidaps/queue/events/EventQueueChanged.kt b/app/src/main/java/info/nightscout/androidaps/queue/events/EventQueueChanged.kt new file mode 100644 index 0000000000..297d443976 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/queue/events/EventQueueChanged.kt @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.queue.events + +import info.nightscout.androidaps.events.Event + +class EventQueueChanged : Event() diff --git a/app/src/main/java/info/nightscout/androidaps/receivers/ChargingStateReceiver.java b/app/src/main/java/info/nightscout/androidaps/receivers/ChargingStateReceiver.java index b10c2e99e5..9af15e9ddc 100644 --- a/app/src/main/java/info/nightscout/androidaps/receivers/ChargingStateReceiver.java +++ b/app/src/main/java/info/nightscout/androidaps/receivers/ChargingStateReceiver.java @@ -5,17 +5,20 @@ import android.content.Context; import android.content.Intent; import android.os.BatteryManager; -import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.events.EventChargingState; +import info.nightscout.androidaps.plugins.bus.RxBus; public class ChargingStateReceiver extends BroadcastReceiver { + private static EventChargingState lastEvent; + @Override public void onReceive(Context context, Intent intent) { EventChargingState event = grabChargingState(context); if (event != null) - MainApp.bus().post(event); + RxBus.INSTANCE.send(event); + lastEvent = event; } public EventChargingState grabChargingState(Context context) { @@ -32,4 +35,11 @@ public class ChargingStateReceiver extends BroadcastReceiver { return event; } + static public boolean isCharging() { + return lastEvent != null && lastEvent.isCharging(); + } + + static public EventChargingState getLastEvent() { + return lastEvent; + } } \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/receivers/DataReceiver.java b/app/src/main/java/info/nightscout/androidaps/receivers/DataReceiver.java index 087cd3a5f5..6c2e7c6920 100644 --- a/app/src/main/java/info/nightscout/androidaps/receivers/DataReceiver.java +++ b/app/src/main/java/info/nightscout/androidaps/receivers/DataReceiver.java @@ -2,7 +2,7 @@ package info.nightscout.androidaps.receivers; import android.content.Context; import android.content.Intent; -import android.support.v4.content.WakefulBroadcastReceiver; +import androidx.legacy.content.WakefulBroadcastReceiver; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/receivers/KeepAliveReceiver.java b/app/src/main/java/info/nightscout/androidaps/receivers/KeepAliveReceiver.java index cc36f21a59..4c8a3f660e 100644 --- a/app/src/main/java/info/nightscout/androidaps/receivers/KeepAliveReceiver.java +++ b/app/src/main/java/info/nightscout/androidaps/receivers/KeepAliveReceiver.java @@ -7,24 +7,23 @@ import android.content.Context; import android.content.Intent; import android.os.PowerManager; -import com.crashlytics.android.answers.CustomEvent; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.data.Profile; -import info.nightscout.androidaps.events.EventProfileSwitchChange; +import info.nightscout.androidaps.events.EventProfileNeedsUpdate; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; import info.nightscout.androidaps.queue.commands.Command; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.FabricPrivacy; -import info.nightscout.utils.LocalAlertUtils; -import info.nightscout.utils.T; +import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.FabricPrivacy; +import info.nightscout.androidaps.utils.LocalAlertUtils; +import info.nightscout.androidaps.utils.T; /** @@ -46,13 +45,12 @@ public class KeepAliveReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent rIntent) { PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); - PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, ""); + PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "AndroidAPS:KeepAliveReciever"); wl.acquire(); LocalAlertUtils.shortenSnoozeInterval(); LocalAlertUtils.checkStaleBGAlert(); checkPump(); - FabricPrivacy.uploadDailyStats(); if (L.isEnabled(L.CORE)) log.debug("KeepAlive received"); @@ -76,7 +74,7 @@ public class KeepAliveReceiver extends BroadcastReceiver { } if (!pump.isThisProfileSet(profile) && !ConfigBuilderPlugin.getPlugin().getCommandQueue().isRunning(Command.CommandType.BASALPROFILE)) { - MainApp.bus().post(new EventProfileSwitchChange()); + RxBus.INSTANCE.send(new EventProfileNeedsUpdate()); } else if (isStatusOutdated && !pump.isBusy()) { lastReadStatus = System.currentTimeMillis(); ConfigBuilderPlugin.getPlugin().getCommandQueue().readStatus("KeepAlive. Status outdated.", null); @@ -87,7 +85,7 @@ public class KeepAliveReceiver extends BroadcastReceiver { } if (lastRun != 0 && System.currentTimeMillis() - lastRun > T.mins(10).msecs()) { log.error("KeepAlive fail"); - FabricPrivacy.getInstance().logCustom(new CustomEvent("KeepAliveFail")); + FabricPrivacy.getInstance().logCustom("KeepAliveFail"); } lastRun = System.currentTimeMillis(); } diff --git a/app/src/main/java/info/nightscout/androidaps/receivers/NSAlarmReceiver.java b/app/src/main/java/info/nightscout/androidaps/receivers/NSAlarmReceiver.java index d167bb9510..3449bf2943 100644 --- a/app/src/main/java/info/nightscout/androidaps/receivers/NSAlarmReceiver.java +++ b/app/src/main/java/info/nightscout/androidaps/receivers/NSAlarmReceiver.java @@ -10,12 +10,12 @@ import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSAlarm; -import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; -import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; -import info.nightscout.androidaps.plugins.Overview.notifications.Notification; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.general.nsclient.data.NSAlarm; +import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification; +import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; import info.nightscout.androidaps.services.Intents; public class NSAlarmReceiver extends BroadcastReceiver { @@ -41,11 +41,11 @@ public class NSAlarmReceiver extends BroadcastReceiver { case Intents.ACTION_URGENT_ALARM: Notification notification = new Notification(nsAlarm); if (notification.isEnabled()) - MainApp.bus().post(new EventNewNotification(notification)); + RxBus.INSTANCE.send(new EventNewNotification(notification)); break; case Intents.ACTION_CLEAR_ALARM: - MainApp.bus().post(new EventDismissNotification(Notification.NSALARM)); - MainApp.bus().post(new EventDismissNotification(Notification.NSURGENTALARM)); + RxBus.INSTANCE.send(new EventDismissNotification(Notification.NSALARM)); + RxBus.INSTANCE.send(new EventDismissNotification(Notification.NSURGENTALARM)); break; } } diff --git a/app/src/main/java/info/nightscout/androidaps/receivers/NetworkChangeReceiver.java b/app/src/main/java/info/nightscout/androidaps/receivers/NetworkChangeReceiver.java index 9a3108e98c..3f12d75fce 100644 --- a/app/src/main/java/info/nightscout/androidaps/receivers/NetworkChangeReceiver.java +++ b/app/src/main/java/info/nightscout/androidaps/receivers/NetworkChangeReceiver.java @@ -8,7 +8,7 @@ import android.net.NetworkInfo; import android.net.wifi.SupplicantState; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -16,16 +16,26 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.events.EventNetworkChange; import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.bus.RxBus; public class NetworkChangeReceiver extends BroadcastReceiver { private static Logger log = LoggerFactory.getLogger(L.CORE); + private static EventNetworkChange lastEvent = null; + + public static final NetworkChangeReceiver instance = new NetworkChangeReceiver(); + + // TODO: Split NSClient into network state component that can be used by several plugins and logic for plugin + public static void fetch() { + new NetworkChangeReceiver().grabNetworkStatus(MainApp.instance().getApplicationContext()); + } + @Override public void onReceive(final Context context, final Intent intent) { EventNetworkChange event = grabNetworkStatus(context); if (event != null) - MainApp.bus().post(event); + RxBus.INSTANCE.send(event); } @Nullable @@ -38,29 +48,42 @@ public class NetworkChangeReceiver extends BroadcastReceiver { if (activeNetwork != null) { if (activeNetwork.getType() == ConnectivityManager.TYPE_WIFI && activeNetwork.isConnected()) { - event.wifiConnected = true; + event.setWifiConnected(true); WifiManager wifiManager = (WifiManager) MainApp.instance().getApplicationContext().getSystemService(Context.WIFI_SERVICE); if (wifiManager != null) { WifiInfo wifiInfo = wifiManager.getConnectionInfo(); if (wifiInfo.getSupplicantState() == SupplicantState.COMPLETED) { - event.ssid = wifiInfo.getSSID(); + event.setSsid(wifiInfo.getSSID()); } if (L.isEnabled(L.CORE)) - log.debug("NETCHANGE: Wifi connected. SSID: " + event.ssid); + log.debug("NETCHANGE: Wifi connected. SSID: " + event.connectedSsid()); } } if (activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE) { - event.mobileConnected = true; - event.roaming = activeNetwork.isRoaming(); + event.setMobileConnected(true); + event.setRoaming(activeNetwork.isRoaming()); if (L.isEnabled(L.CORE)) - log.debug("NETCHANGE: Mobile connected. Roaming: " + event.roaming); + log.debug("NETCHANGE: Mobile connected. Roaming: " + event.getRoaming()); } } else { if (L.isEnabled(L.CORE)) log.debug("NETCHANGE: Disconnected."); } + lastEvent = event; return event; } -} \ No newline at end of file + + public static boolean isWifiConnected() { + return lastEvent != null && lastEvent.getWifiConnected(); + } + + public static boolean isConnected() { + return lastEvent != null && (lastEvent.getWifiConnected() || lastEvent.getMobileConnected()); + } + + public static EventNetworkChange getLastEvent() { + return lastEvent; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/receivers/SmsReceiver.java b/app/src/main/java/info/nightscout/androidaps/receivers/SmsReceiver.java new file mode 100644 index 0000000000..f527375349 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/receivers/SmsReceiver.java @@ -0,0 +1,7 @@ +package info.nightscout.androidaps.receivers; + +/** + * Forward received SMS intents. This is a separate class, because unlike local broadcasts handled by DataReceiver, + * receiving SMS requires a special permission in the manifest, which necessitates a separate receiver. + */ +public class SmsReceiver extends DataReceiver {} diff --git a/app/src/main/java/info/nightscout/androidaps/receivers/TimeDateOrTZChangeReceiver.java b/app/src/main/java/info/nightscout/androidaps/receivers/TimeDateOrTZChangeReceiver.java new file mode 100644 index 0000000000..e74dfec20d --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/receivers/TimeDateOrTZChangeReceiver.java @@ -0,0 +1,45 @@ +package info.nightscout.androidaps.receivers; + +import android.bluetooth.BluetoothAdapter; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.interfaces.PumpInterface; +import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; + +public class TimeDateOrTZChangeReceiver extends BroadcastReceiver { + + private static Logger LOG = LoggerFactory.getLogger(L.PUMP); + + @Override + public void onReceive(Context context, Intent intent) { + final String action = intent.getAction(); + + PumpInterface activePump = ConfigBuilderPlugin.getPlugin().getActivePump(); + + LOG.debug("Date, Time and/or TimeZone changed."); + + if (action != null && activePump != null) { + LOG.debug("Date, Time and/or TimeZone changed. Notifying pump driver."); + activePump.timeDateOrTimeZoneChanged(); + } + } + + + public void registerBroadcasts(MainApp mainApp) { + IntentFilter filter = new IntentFilter(); + filter.addAction(Intent.ACTION_TIME_CHANGED); + filter.addAction(Intent.ACTION_DATE_CHANGED); + filter.addAction(Intent.ACTION_TIMEZONE_CHANGED); + mainApp.registerReceiver(this, filter); + } + + +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/services/AlarmSoundService.java b/app/src/main/java/info/nightscout/androidaps/services/AlarmSoundService.java index e95cd7c479..2e9130f7db 100644 --- a/app/src/main/java/info/nightscout/androidaps/services/AlarmSoundService.java +++ b/app/src/main/java/info/nightscout/androidaps/services/AlarmSoundService.java @@ -1,5 +1,6 @@ package info.nightscout.androidaps.services; +import android.app.Notification; import android.app.Service; import android.content.Context; import android.content.Intent; @@ -16,6 +17,7 @@ import java.io.IOException; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.general.persistentNotification.PersistentNotificationPlugin; public class AlarmSoundService extends Service { private static Logger log = LoggerFactory.getLogger(L.CORE); @@ -28,8 +30,7 @@ public class AlarmSoundService extends Service { @Override public IBinder onBind(Intent intent) { - // TODO: Return the communication channel to the service. - throw new UnsupportedOperationException("Not yet implemented"); + return null; } @Override @@ -37,9 +38,13 @@ public class AlarmSoundService extends Service { super.onCreate(); if (L.isEnabled(L.CORE)) log.debug("onCreate"); + Notification notification = PersistentNotificationPlugin.getPlugin().getLastNotification(); + startForeground(PersistentNotificationPlugin.ONGOING_NOTIFICATION_ID, notification); } public int onStartCommand(Intent intent, int flags, int startId) { + Notification notification = PersistentNotificationPlugin.getPlugin().getLastNotification(); + startForeground(PersistentNotificationPlugin.ONGOING_NOTIFICATION_ID, notification); if (player != null && player.isPlaying()) player.stop(); if (L.isEnabled(L.CORE)) @@ -48,35 +53,32 @@ public class AlarmSoundService extends Service { resourceId = intent.getIntExtra("soundid", R.raw.error); player = new MediaPlayer(); - AssetFileDescriptor afd = MainApp.sResources.openRawResourceFd(resourceId); - if (afd == null) - return START_STICKY; try { + AssetFileDescriptor afd = MainApp.sResources.openRawResourceFd(resourceId); + if (afd == null) + return START_STICKY; player.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength()); afd.close(); - } catch (IOException e) { - log.error("Unhandled exception", e); - } - player.setLooping(true); // Set looping - AudioManager manager = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE); - if (manager == null || !manager.isMusicActive()) { - player.setVolume(100, 100); - } - - try { + player.setLooping(true); // Set looping + AudioManager manager = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE); + if (manager == null || !manager.isMusicActive()) { + player.setVolume(100, 100); + } player.prepare(); player.start(); - } catch (IOException e) { + } catch (Exception e) { log.error("Unhandled exception", e); } - return START_STICKY; } @Override public void onDestroy() { - player.stop(); - player.release(); + if (player != null) { + player.stop(); + player.release(); + } + if (L.isEnabled(L.CORE)) log.debug("onDestroy"); } diff --git a/app/src/main/java/info/nightscout/androidaps/services/DataService.java b/app/src/main/java/info/nightscout/androidaps/services/DataService.java index cfc564770d..80a42e145a 100644 --- a/app/src/main/java/info/nightscout/androidaps/services/DataService.java +++ b/app/src/main/java/info/nightscout/androidaps/services/DataService.java @@ -16,25 +16,28 @@ import info.nightscout.androidaps.R; import info.nightscout.androidaps.db.CareportalEvent; import info.nightscout.androidaps.events.EventNsFood; import info.nightscout.androidaps.events.EventNsTreatment; -import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSDeviceStatus; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSMbg; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSettingsStatus; -import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; -import info.nightscout.androidaps.plugins.Overview.notifications.Notification; -import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin; -import info.nightscout.androidaps.plugins.PumpDanaR.activities.DanaRNSHistorySync; -import info.nightscout.androidaps.plugins.SmsCommunicator.SmsCommunicatorPlugin; -import info.nightscout.androidaps.plugins.Source.SourceDexcomG5Plugin; -import info.nightscout.androidaps.plugins.Source.SourceGlimpPlugin; -import info.nightscout.androidaps.plugins.Source.SourceMM640gPlugin; -import info.nightscout.androidaps.plugins.Source.SourceNSClientPlugin; -import info.nightscout.androidaps.plugins.Source.SourcePoctechPlugin; -import info.nightscout.androidaps.plugins.Source.SourceXdripPlugin; -import info.nightscout.androidaps.receivers.DataReceiver; import info.nightscout.androidaps.logging.BundleLogger; -import info.nightscout.utils.JsonHelper; -import info.nightscout.utils.SP; +import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.general.nsclient.data.NSDeviceStatus; +import info.nightscout.androidaps.plugins.general.nsclient.data.NSMbg; +import info.nightscout.androidaps.plugins.general.nsclient.data.NSSettingsStatus; +import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; +import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin; +import info.nightscout.androidaps.plugins.profile.ns.NSProfilePlugin; +import info.nightscout.androidaps.plugins.pump.danaR.activities.DanaRNSHistorySync; +import info.nightscout.androidaps.plugins.source.SourceDexcomPlugin; +import info.nightscout.androidaps.plugins.source.SourceEversensePlugin; +import info.nightscout.androidaps.plugins.source.SourceGlimpPlugin; +import info.nightscout.androidaps.plugins.source.SourceMM640gPlugin; +import info.nightscout.androidaps.plugins.source.SourceNSClientPlugin; +import info.nightscout.androidaps.plugins.source.SourcePoctechPlugin; +import info.nightscout.androidaps.plugins.source.SourceTomatoPlugin; +import info.nightscout.androidaps.plugins.source.SourceXdripPlugin; +import info.nightscout.androidaps.receivers.DataReceiver; +import info.nightscout.androidaps.utils.JsonHelper; +import info.nightscout.androidaps.utils.SP; public class DataService extends IntentService { @@ -42,7 +45,6 @@ public class DataService extends IntentService { public DataService() { super("DataService"); - registerBus(); } @Override @@ -66,10 +68,14 @@ public class DataService extends IntentService { SourceMM640gPlugin.getPlugin().handleNewData(intent); } else if (Intents.GLIMP_BG.equals(action)) { SourceGlimpPlugin.getPlugin().handleNewData(intent); - } else if (Intents.DEXCOMG5_BG.equals(action)) { - SourceDexcomG5Plugin.getPlugin().handleNewData(intent); + } else if (Intents.DEXCOM_BG.equals(action)) { + SourceDexcomPlugin.INSTANCE.handleNewData(intent); } else if (Intents.POCTECH_BG.equals(action)) { SourcePoctechPlugin.getPlugin().handleNewData(intent); + } else if (Intents.TOMATO_BG.equals(action)) { + SourceTomatoPlugin.getPlugin().handleNewData(intent); + } else if (Intents.EVERSENSE_BG.equals(action)) { + SourceEversensePlugin.getPlugin().handleNewData(intent); } else if (Intents.ACTION_NEW_SGV.equals(action)) { SourceNSClientPlugin.getPlugin().handleNewData(intent); } else if (Intents.ACTION_NEW_PROFILE.equals(action)) { @@ -80,21 +86,21 @@ public class DataService extends IntentService { } else if (Intents.ACTION_NEW_STATUS.equals(action)) { NSSettingsStatus.getInstance().handleNewData(intent); } else if (Intents.ACTION_NEW_FOOD.equals(action)) { - EventNsFood evt = new EventNsFood(EventNsFood.ADD, bundles); - MainApp.bus().post(evt); + EventNsFood evt = new EventNsFood(EventNsFood.Companion.getADD(), bundles); + RxBus.INSTANCE.send(evt); } else if (Intents.ACTION_CHANGED_FOOD.equals(action)) { - EventNsFood evt = new EventNsFood(EventNsFood.UPDATE, bundles); - MainApp.bus().post(evt); + EventNsFood evt = new EventNsFood(EventNsFood.Companion.getUPDATE(), bundles); + RxBus.INSTANCE.send(evt); } else if (Intents.ACTION_REMOVED_FOOD.equals(action)) { - EventNsFood evt = new EventNsFood(EventNsFood.REMOVE, bundles); - MainApp.bus().post(evt); + EventNsFood evt = new EventNsFood(EventNsFood.Companion.getREMOVE(), bundles); + RxBus.INSTANCE.send(evt); } else if (acceptNSData && (Intents.ACTION_NEW_TREATMENT.equals(action) || Intents.ACTION_CHANGED_TREATMENT.equals(action) || Intents.ACTION_REMOVED_TREATMENT.equals(action) || Intents.ACTION_NEW_CAL.equals(action) || Intents.ACTION_NEW_MBG.equals(action)) - ) { + ) { handleNewDataFromNSClient(intent); } else if (Telephony.Sms.Intents.SMS_RECEIVED_ACTION.equals(action)) { SmsCommunicatorPlugin.getPlugin().handleNewData(intent); @@ -108,16 +114,6 @@ public class DataService extends IntentService { @Override public void onDestroy() { super.onDestroy(); - MainApp.bus().unregister(this); - } - - private void registerBus() { - try { - MainApp.bus().unregister(this); - } catch (RuntimeException x) { - // Ignore - } - MainApp.bus().register(this); } private void handleNewDataFromNSClient(Intent intent) { @@ -191,8 +187,8 @@ public class DataService extends IntentService { private void handleRemovedTreatmentFromNS(JSONObject json) { // new DB model - EventNsTreatment evtTreatment = new EventNsTreatment(EventNsTreatment.REMOVE, json); - MainApp.bus().post(evtTreatment); + EventNsTreatment evtTreatment = new EventNsTreatment(EventNsTreatment.Companion.getREMOVE(), json); + RxBus.INSTANCE.send(evtTreatment); // old DB model String _id = JsonHelper.safeGetString(json, "_id"); MainApp.getDbHelper().deleteTempTargetById(_id); @@ -204,7 +200,7 @@ public class DataService extends IntentService { private void handleTreatmentFromNS(JSONObject json, Intent intent) { // new DB model - int mode = Intents.ACTION_NEW_TREATMENT.equals(intent.getAction()) ? EventNsTreatment.ADD : EventNsTreatment.UPDATE; + int mode = Intents.ACTION_NEW_TREATMENT.equals(intent.getAction()) ? EventNsTreatment.Companion.getADD() : EventNsTreatment.Companion.getUPDATE(); double insulin = JsonHelper.safeGetDouble(json, "insulin"); double carbs = JsonHelper.safeGetDouble(json, "carbs"); String eventType = JsonHelper.safeGetString(json, "eventType"); @@ -214,7 +210,7 @@ public class DataService extends IntentService { } if (insulin > 0 || carbs > 0) { EventNsTreatment evtTreatment = new EventNsTreatment(mode, json); - MainApp.bus().post(evtTreatment); + RxBus.INSTANCE.send(evtTreatment); } else if (json.has(DanaRNSHistorySync.DANARSIGNATURE)) { // old DB model MainApp.getDbHelper().updateDanaRHistoryRecordId(json); @@ -248,7 +244,7 @@ public class DataService extends IntentService { if (date > now - 15 * 60 * 1000L && !notes.isEmpty() && !enteredBy.equals(SP.getString("careportal_enteredby", "AndroidAPS"))) { Notification announcement = new Notification(Notification.NSANNOUNCEMENT, notes, Notification.ANNOUNCEMENT, 60); - MainApp.bus().post(new EventNewNotification(announcement)); + RxBus.INSTANCE.send(new EventNewNotification(announcement)); } } } diff --git a/app/src/main/java/info/nightscout/androidaps/services/Intents.java b/app/src/main/java/info/nightscout/androidaps/services/Intents.java index 6d3daf1ea9..98c2355a4f 100644 --- a/app/src/main/java/info/nightscout/androidaps/services/Intents.java +++ b/app/src/main/java/info/nightscout/androidaps/services/Intents.java @@ -23,8 +23,6 @@ public interface Intents { // App -> NSClient String ACTION_DATABASE = "info.nightscout.client.DBACCESS"; - String ACTION_RESTART = "info.nightscout.client.RESTART"; - String ACTION_RESEND = "info.nightscout.client.RESEND"; String ACTION_ACK_ALARM = "info.nightscout.client.ACK_ALARM"; // xDrip -> App @@ -48,7 +46,9 @@ public interface Intents { String GLIMP_BG = "it.ct.glicemia.ACTION_GLUCOSE_MEASURED"; - String DEXCOMG5_BG = "com.dexcom.cgm.DATA"; + String DEXCOM_BG = "com.dexcom.cgm.EXTERNAL_BROADCAST"; + String EVERSENSE_BG = "com.senseonics.AndroidAPSEventSubscriber.BROADCAST"; String POCTECH_BG = "com.china.poctech.data"; + String TOMATO_BG = "com.fanqies.tomatofn.BgEstimate"; } diff --git a/app/src/main/java/info/nightscout/androidaps/services/LocationService.java b/app/src/main/java/info/nightscout/androidaps/services/LocationService.java new file mode 100644 index 0000000000..9600515d6f --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/services/LocationService.java @@ -0,0 +1,168 @@ +package info.nightscout.androidaps.services; + +import android.app.Service; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.location.Location; +import android.location.LocationManager; +import android.os.Bundle; +import android.os.IBinder; + +import androidx.core.app.ActivityCompat; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.events.EventAppExit; +import info.nightscout.androidaps.events.EventLocationChange; +import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.general.persistentNotification.PersistentNotificationPlugin; +import info.nightscout.androidaps.utils.FabricPrivacy; +import info.nightscout.androidaps.utils.SP; +import info.nightscout.androidaps.utils.T; +import io.reactivex.disposables.CompositeDisposable; +import io.reactivex.schedulers.Schedulers; + +public class LocationService extends Service { + private static Logger log = LoggerFactory.getLogger(L.LOCATION); + private CompositeDisposable disposable = new CompositeDisposable(); + + private LocationManager mLocationManager = null; + private static final float LOCATION_DISTANCE = 10f; + + private static final long LOCATION_INTERVAL_ACTIVE = T.mins(5).msecs(); + private static final long LOCATION_INTERVAL_PASSIVE = T.mins(1).msecs(); // this doesn't cost more power + + private static Location mLastLocation; + + private class LocationListener implements android.location.LocationListener { + + LocationListener(String provider) { + if (L.isEnabled(L.LOCATION)) + log.debug("LocationListener " + provider); + mLastLocation = new Location(provider); + } + + @Override + public void onLocationChanged(Location location) { + if (L.isEnabled(L.LOCATION)) + log.debug("onLocationChanged: " + location); + mLastLocation.set(location); + RxBus.INSTANCE.send(new EventLocationChange(location)); + } + + @Override + public void onProviderDisabled(String provider) { + if (L.isEnabled(L.LOCATION)) + log.debug("onProviderDisabled: " + provider); + } + + @Override + public void onProviderEnabled(String provider) { + if (L.isEnabled(L.LOCATION)) + log.debug("onProviderEnabled: " + provider); + } + + @Override + public void onStatusChanged(String provider, int status, Bundle extras) { + if (L.isEnabled(L.LOCATION)) + log.debug("onStatusChanged: " + provider); + } + } + + LocationListener mLocationListener; + + @Override + public IBinder onBind(Intent arg0) { + return null; + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + super.onStartCommand(intent, flags, startId); + if (L.isEnabled(L.LOCATION)) + log.debug("onStartCommand"); + startForeground(PersistentNotificationPlugin.ONGOING_NOTIFICATION_ID, PersistentNotificationPlugin.getPlugin().getLastNotification()); + return START_STICKY; + } + + @Override + public void onCreate() { + super.onCreate(); + startForeground(PersistentNotificationPlugin.ONGOING_NOTIFICATION_ID, PersistentNotificationPlugin.getPlugin().getLastNotification()); + + if (L.isEnabled(L.LOCATION)) + log.debug("onCreate"); + + initializeLocationManager(); + + try { + if (SP.getString(R.string.key_location, "NONE").equals("NETWORK")) + mLocationManager.requestLocationUpdates( + LocationManager.NETWORK_PROVIDER, + LOCATION_INTERVAL_ACTIVE, + LOCATION_DISTANCE, + mLocationListener = new LocationListener(LocationManager.NETWORK_PROVIDER) + ); + if (SP.getString(R.string.key_location, "NONE").equals("GPS")) + mLocationManager.requestLocationUpdates( + LocationManager.GPS_PROVIDER, + LOCATION_INTERVAL_ACTIVE, + LOCATION_DISTANCE, + mLocationListener = new LocationListener(LocationManager.GPS_PROVIDER) + ); + if (SP.getString(R.string.key_location, "NONE").equals("PASSIVE")) + mLocationManager.requestLocationUpdates( + LocationManager.PASSIVE_PROVIDER, + LOCATION_INTERVAL_PASSIVE, + LOCATION_DISTANCE, + mLocationListener = new LocationListener(LocationManager.PASSIVE_PROVIDER) + ); + } catch (java.lang.SecurityException ex) { + log.error("fail to request location update, ignore", ex); + } catch (IllegalArgumentException ex) { + log.error("network provider does not exist, " + ex.getMessage()); + } + disposable.add(RxBus.INSTANCE + .toObservable(EventAppExit.class) + .observeOn(Schedulers.io()) + .subscribe(event -> { + if (L.isEnabled(L.CORE)) log.debug("EventAppExit received"); + stopSelf(); + }, FabricPrivacy::logException) + ); + } + + @Override + public void onDestroy() { + if (L.isEnabled(L.LOCATION)) + log.debug("onDestroy"); + super.onDestroy(); + if (mLocationManager != null) { + try { + if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { + return; + } + mLocationManager.removeUpdates(mLocationListener); + } catch (Exception ex) { + log.error("fail to remove location listener, ignore", ex); + } + } + disposable.clear(); + } + + private void initializeLocationManager() { + if (L.isEnabled(L.LOCATION)) + log.debug("initializeLocationManager - Provider: " + SP.getString(R.string.key_location, "NONE")); + if (mLocationManager == null) { + mLocationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE); + } + } + + public static Location getLastLocation() { + return mLastLocation; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/SWDefinition.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/SWDefinition.java index c1421d7f0c..2c9e1ea51b 100644 --- a/app/src/main/java/info/nightscout/androidaps/setupwizard/SWDefinition.java +++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/SWDefinition.java @@ -2,13 +2,8 @@ package info.nightscout.androidaps.setupwizard; import android.Manifest; import android.content.Intent; -import android.os.Build; -import android.support.v7.app.AppCompatActivity; -import com.squareup.otto.Subscribe; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import androidx.appcompat.app.AppCompatActivity; import java.util.ArrayList; import java.util.List; @@ -21,24 +16,25 @@ import info.nightscout.androidaps.events.EventConfigBuilderChange; import info.nightscout.androidaps.events.EventPumpStatusChanged; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginType; -import info.nightscout.androidaps.plugins.Careportal.CareportalFragment; -import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog; -import info.nightscout.androidaps.plugins.Careportal.OptionsToShow; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions; -import info.nightscout.androidaps.plugins.ConstraintsObjectives.ObjectivesFragment; -import info.nightscout.androidaps.plugins.ConstraintsObjectives.ObjectivesPlugin; -import info.nightscout.androidaps.plugins.Loop.LoopPlugin; -import info.nightscout.androidaps.plugins.Maintenance.ImportExportPrefs; -import info.nightscout.androidaps.plugins.NSClientInternal.NSClientPlugin; -import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientStatus; -import info.nightscout.androidaps.plugins.ProfileLocal.LocalProfileFragment; -import info.nightscout.androidaps.plugins.ProfileLocal.LocalProfilePlugin; -import info.nightscout.androidaps.plugins.ProfileNS.NSProfileFragment; -import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin; -import info.nightscout.androidaps.plugins.ProfileSimple.SimpleProfileFragment; -import info.nightscout.androidaps.plugins.ProfileSimple.SimpleProfilePlugin; +import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; +import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesFragment; +import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin; +import info.nightscout.androidaps.plugins.general.careportal.CareportalFragment; +import info.nightscout.androidaps.plugins.general.careportal.Dialogs.NewNSTreatmentDialog; +import info.nightscout.androidaps.plugins.general.careportal.OptionsToShow; +import info.nightscout.androidaps.plugins.general.maintenance.ImportExportPrefs; +import info.nightscout.androidaps.plugins.general.nsclient.NSClientPlugin; +import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientStatus; +import info.nightscout.androidaps.plugins.general.nsclient.services.NSClientService; +import info.nightscout.androidaps.plugins.profile.local.LocalProfileFragment; +import info.nightscout.androidaps.plugins.profile.local.LocalProfilePlugin; +import info.nightscout.androidaps.plugins.profile.ns.NSProfileFragment; +import info.nightscout.androidaps.plugins.profile.ns.NSProfilePlugin; +import info.nightscout.androidaps.plugins.profile.simple.SimpleProfileFragment; +import info.nightscout.androidaps.plugins.profile.simple.SimpleProfilePlugin; import info.nightscout.androidaps.setupwizard.elements.SWBreak; import info.nightscout.androidaps.setupwizard.elements.SWButton; import info.nightscout.androidaps.setupwizard.elements.SWEditString; @@ -48,16 +44,13 @@ import info.nightscout.androidaps.setupwizard.elements.SWHtmlLink; import info.nightscout.androidaps.setupwizard.elements.SWInfotext; import info.nightscout.androidaps.setupwizard.elements.SWPlugin; import info.nightscout.androidaps.setupwizard.elements.SWRadioButton; -import info.nightscout.androidaps.setupwizard.events.EventSWLabel; import info.nightscout.androidaps.setupwizard.events.EventSWUpdate; -import info.nightscout.utils.AndroidPermission; -import info.nightscout.utils.LocaleHelper; -import info.nightscout.utils.PasswordProtection; -import info.nightscout.utils.SP; +import info.nightscout.androidaps.utils.AndroidPermission; +import info.nightscout.androidaps.utils.LocaleHelper; +import info.nightscout.androidaps.utils.PasswordProtection; +import info.nightscout.androidaps.utils.SP; public class SWDefinition { - private static Logger log = LoggerFactory.getLogger(SWDefinition.class); - private AppCompatActivity activity; private List screens = new ArrayList<>(); @@ -69,569 +62,419 @@ public class SWDefinition { return activity; } - public List getScreens() { + List getScreens() { return screens; } - SWDefinition add(SWScreen newScreen) { + private SWDefinition add(SWScreen newScreen) { screens.add(newScreen); return this; } SWDefinition() { - if (Config.APS || Config.PUMPCONTROL) + if (Config.APS) SWDefinitionFull(); + else if (Config.PUMPCONTROL) + SWDefinitionPumpControl(); else if (Config.NSCLIENT) SWDefinitionNSClient(); } + private SWScreen screenSetupWizard = new SWScreen(R.string.nav_setupwizard) + .add(new SWInfotext() + .label(R.string.welcometosetupwizard)); + + private SWScreen screenLanguage = new SWScreen(R.string.language) + .skippable(false) + .add(new SWRadioButton() + .option(R.array.languagesArray, R.array.languagesValues) + .preferenceId(R.string.key_language).label(R.string.language) + .comment(R.string.setupwizard_language_prompt)) + .validator(() -> { + LocaleHelper.INSTANCE.update(MainApp.instance().getApplicationContext()); + return SP.contains(R.string.key_language); + }); + + private SWScreen screenEula = new SWScreen(R.string.end_user_license_agreement) + .skippable(false) + .add(new SWInfotext() + .label(R.string.end_user_license_agreement_text)) + .add(new SWBreak()) + .add(new SWButton() + .text(R.string.end_user_license_agreement_i_understand) + .visibility(() -> !SP.getBoolean(R.string.key_i_understand, false)) + .action(() -> { + SP.putBoolean(R.string.key_i_understand, true); + RxBus.INSTANCE.send(new EventSWUpdate(false)); + })) + .visibility(() -> !SP.getBoolean(R.string.key_i_understand, false)) + .validator(() -> SP.getBoolean(R.string.key_i_understand, false)); + + private SWScreen screenPermissionBattery = new SWScreen(R.string.permission) + .skippable(false) + .add(new SWInfotext() + .label(String.format(MainApp.gs(R.string.needwhitelisting), MainApp.gs(R.string.app_name)))) + .add(new SWBreak()) + .add(new SWButton() + .text(R.string.askforpermission) + .visibility(() -> AndroidPermission.permissionNotGranted(getActivity(), Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)) + .action(() -> AndroidPermission.askForPermission(getActivity(), Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS, AndroidPermission.CASE_BATTERY))) + .visibility(() -> AndroidPermission.permissionNotGranted(getActivity(), Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)) + .validator(() -> !(AndroidPermission.permissionNotGranted(getActivity(), Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS))); + + private SWScreen screenPermissionBt = new SWScreen(R.string.permission) + .skippable(false) + .add(new SWInfotext() + .label(MainApp.gs(R.string.needlocationpermission))) + .add(new SWBreak()) + .add(new SWButton() + .text(R.string.askforpermission) + .visibility(() -> AndroidPermission.permissionNotGranted(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION)) + .action(() -> AndroidPermission.askForPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION, AndroidPermission.CASE_LOCATION))) + .visibility(() -> AndroidPermission.permissionNotGranted(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION)) + .validator(() -> !(AndroidPermission.permissionNotGranted(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION))); + + private SWScreen screenPermissionStore = new SWScreen(R.string.permission) + .skippable(false) + .add(new SWInfotext() + .label(MainApp.gs(R.string.needstoragepermission))) + .add(new SWBreak()) + .add(new SWButton() + .text(R.string.askforpermission) + .visibility(() -> AndroidPermission.permissionNotGranted(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE)) + .action(() -> AndroidPermission.askForPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE, AndroidPermission.CASE_STORAGE))) + .visibility(() -> AndroidPermission.permissionNotGranted(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE)) + .validator(() -> !(AndroidPermission.permissionNotGranted(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE))); + + private SWScreen screenImport = new SWScreen(R.string.nav_import) + .add(new SWInfotext() + .label(R.string.storedsettingsfound)) + .add(new SWBreak()) + .add(new SWButton() + .text(R.string.nav_import) + .action(() -> ImportExportPrefs.importSharedPreferences(getActivity()))) + .visibility(() -> ImportExportPrefs.file.exists() && !(AndroidPermission.permissionNotGranted(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE))); + + private SWScreen screenNsClient = new SWScreen(R.string.nsclientinternal_title) + .skippable(true) + .add(new SWInfotext() + .label(R.string.nsclientinfotext)) + .add(new SWBreak()) + .add(new SWButton() + .text(R.string.enable_nsclient) + .action(() -> { + NSClientPlugin.getPlugin().setPluginEnabled(PluginType.GENERAL, true); + NSClientPlugin.getPlugin().setFragmentVisible(PluginType.GENERAL, true); + ConfigBuilderPlugin.getPlugin().processOnEnabledCategoryChanged(NSClientPlugin.getPlugin(), PluginType.GENERAL); + ConfigBuilderPlugin.getPlugin().storeSettings("SetupWizard"); + RxBus.INSTANCE.send(new EventConfigBuilderChange()); + RxBus.INSTANCE.send(new EventSWUpdate(true)); + }) + .visibility(() -> !NSClientPlugin.getPlugin().isEnabled(PluginType.GENERAL))) + .add(new SWEditUrl() + .preferenceId(R.string.key_nsclientinternal_url) + .updateDelay(5) + .label(R.string.nsclientinternal_url_title) + .comment(R.string.nsclientinternal_url_dialogmessage)) + .add(new SWEditString() + .validator(text -> text.length() >= 12) + .preferenceId(R.string.key_nsclientinternal_api_secret) + .updateDelay(5) + .label(R.string.nsclientinternal_secret_dialogtitle) + .comment(R.string.nsclientinternal_secret_dialogmessage)) + .add(new SWBreak()) + .add(new SWEventListener(this, EventNSClientStatus.class) + .label(R.string.status) + .initialStatus(NSClientPlugin.getPlugin().status) + ) + .add(new SWBreak()) + .validator(() -> NSClientPlugin.getPlugin().nsClientService != null && NSClientService.isConnected && NSClientService.hasWriteAuth) + .visibility(() -> !(NSClientPlugin.getPlugin().nsClientService != null && NSClientService.isConnected && NSClientService.hasWriteAuth)); + + private SWScreen screenAge = new SWScreen(R.string.patientage) + .skippable(false) + .add(new SWBreak()) + .add(new SWRadioButton() + .option(R.array.ageArray, R.array.ageValues) + .preferenceId(R.string.key_age) + .label(R.string.patientage) + .comment(R.string.patientage_summary)) + .validator(() -> SP.contains(R.string.key_age)); + + private SWScreen screenInsulin = new SWScreen(R.string.configbuilder_insulin) + .skippable(false) + .add(new SWPlugin() + .option(PluginType.INSULIN, R.string.configbuilder_insulin_description) + .makeVisible(false) + .label(R.string.configbuilder_insulin)) + .add(new SWBreak()) + .add(new SWInfotext() + .label(R.string.diawarning)) + .add(new SWBreak()) + .add(new SWButton() + .text(R.string.insulinsourcesetup) + .action(() -> { + final PluginBase plugin = (PluginBase) ConfigBuilderPlugin.getPlugin().getActiveInsulin(); + if (plugin != null) { + PasswordProtection.QueryPassword(activity, R.string.settings_password, "settings_password", () -> { + Intent i = new Intent(activity, PreferencesActivity.class); + i.putExtra("id", plugin.getPreferencesId()); + activity.startActivity(i); + }, null); + } + }) + .visibility(() -> ConfigBuilderPlugin.getPlugin().getActiveInsulin() != null && ((PluginBase) ConfigBuilderPlugin.getPlugin().getActiveInsulin()).getPreferencesId() > 0)) + .validator(() -> ConfigBuilderPlugin.getPlugin().getActiveInsulin() != null); + + private SWScreen screenBgSource = new SWScreen(R.string.configbuilder_bgsource) + .skippable(false) + .add(new SWPlugin() + .option(PluginType.BGSOURCE, R.string.configbuilder_bgsource_description) + .label(R.string.configbuilder_bgsource)) + .add(new SWBreak()) + .add(new SWButton() + .text(R.string.bgsourcesetup) + .action(() -> { + final PluginBase plugin = (PluginBase) ConfigBuilderPlugin.getPlugin().getActiveBgSource(); + if (plugin != null) { + PasswordProtection.QueryPassword(activity, R.string.settings_password, "settings_password", () -> { + Intent i = new Intent(activity, PreferencesActivity.class); + i.putExtra("id", plugin.getPreferencesId()); + activity.startActivity(i); + }, null); + } + }) + .visibility(() -> ConfigBuilderPlugin.getPlugin().getActiveBgSource() != null && ((PluginBase) ConfigBuilderPlugin.getPlugin().getActiveBgSource()).getPreferencesId() > 0)) + .validator(() -> ConfigBuilderPlugin.getPlugin().getActiveBgSource() != null); + + private SWScreen screenProfile = new SWScreen(R.string.configbuilder_profile) + .skippable(false) + .add(new SWInfotext() + .label(R.string.setupwizard_profile_description)) + .add(new SWBreak()) + .add(new SWPlugin() + .option(PluginType.PROFILE, R.string.configbuilder_profile_description) + .label(R.string.configbuilder_profile)) + .validator(() -> ConfigBuilderPlugin.getPlugin().getActiveProfileInterface() != null); + + private SWScreen screenNsProfile = new SWScreen(R.string.nsprofile) + .skippable(false) + .add(new SWInfotext() + .label(R.string.adjustprofileinns)) + .add(new SWFragment(this) + .add(new NSProfileFragment())) + .validator(() -> NSProfilePlugin.getPlugin().getProfile() != null && NSProfilePlugin.getPlugin().getProfile().getDefaultProfile() != null && NSProfilePlugin.getPlugin().getProfile().getDefaultProfile().isValid("StartupWizard")) + .visibility(() -> NSProfilePlugin.getPlugin().isEnabled(PluginType.PROFILE)); + + private SWScreen screenLocalProfile = new SWScreen(R.string.localprofile) + .skippable(false) + .add(new SWFragment(this) + .add(new LocalProfileFragment())) + .validator(() -> LocalProfilePlugin.getPlugin().getProfile() != null && LocalProfilePlugin.getPlugin().getProfile().getDefaultProfile() != null && LocalProfilePlugin.getPlugin().getProfile().getDefaultProfile().isValid("StartupWizard")) + .visibility(() -> LocalProfilePlugin.getPlugin().isEnabled(PluginType.PROFILE)); + + private SWScreen screenSimpleProfile = new SWScreen(R.string.simpleprofile) + .skippable(false) + .add(new SWFragment(this) + .add(new SimpleProfileFragment())) + .validator(() -> SimpleProfilePlugin.getPlugin().getProfile() != null && SimpleProfilePlugin.getPlugin().getProfile().getDefaultProfile() != null && SimpleProfilePlugin.getPlugin().getProfile().getDefaultProfile().isValid("StartupWizard")) + .visibility(() -> SimpleProfilePlugin.getPlugin().isEnabled(PluginType.PROFILE)); + + private SWScreen screenProfileSwitch = new SWScreen(R.string.profileswitch) + .skippable(false) + .add(new SWInfotext() + .label(R.string.profileswitch_ismissing)) + .add(new SWButton() + .text(R.string.profileswitch) + .action(() -> { + NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog(); + final OptionsToShow profileSwitch = CareportalFragment.PROFILESWITCHDIRECT; + profileSwitch.executeProfileSwitch = true; + newDialog.setOptions(profileSwitch, R.string.careportal_profileswitch); + newDialog.show(getActivity().getSupportFragmentManager(), "NewNSTreatmentDialog"); + })) + .validator(() -> ProfileFunctions.getInstance().getProfile() != null) + .visibility(() -> ProfileFunctions.getInstance().getProfile() == null); + + private SWScreen screenPump = new SWScreen(R.string.configbuilder_pump) + .skippable(false) + .add(new SWPlugin() + .option(PluginType.PUMP, R.string.configbuilder_pump_description) + .label(R.string.configbuilder_pump)) + .add(new SWBreak()) + .add(new SWButton() + .text(R.string.pumpsetup) + .action(() -> { + final PluginBase plugin = (PluginBase) ConfigBuilderPlugin.getPlugin().getActivePump(); + if (plugin != null) { + PasswordProtection.QueryPassword(activity, R.string.settings_password, "settings_password", () -> { + Intent i = new Intent(activity, PreferencesActivity.class); + i.putExtra("id", plugin.getPreferencesId()); + activity.startActivity(i); + }, null); + } + }) + .visibility(() -> (ConfigBuilderPlugin.getPlugin().getActivePump() != null && ((PluginBase) ConfigBuilderPlugin.getPlugin().getActivePump()).getPreferencesId() > 0))) + .add(new SWButton() + .text(R.string.readstatus) + .action(() -> ConfigBuilderPlugin.getPlugin().getCommandQueue().readStatus("Clicked connect to pump", null)) + .visibility(() -> ConfigBuilderPlugin.getPlugin().getActivePump() != null)) + .add(new SWEventListener(this, EventPumpStatusChanged.class)) + .validator(() -> ConfigBuilderPlugin.getPlugin().getActivePump() != null && ConfigBuilderPlugin.getPlugin().getActivePump().isInitialized()); + + private SWScreen screenAps = new SWScreen(R.string.configbuilder_aps) + .skippable(false) + .add(new SWInfotext() + .label(R.string.setupwizard_aps_description)) + .add(new SWBreak()) + .add(new SWHtmlLink() + .label("https://openaps.readthedocs.io/en/latest/")) + .add(new SWBreak()) + .add(new SWPlugin() + .option(PluginType.APS, R.string.configbuilder_aps_description) + .label(R.string.configbuilder_aps)) + .add(new SWButton() + .text(R.string.apssetup) + .action(() -> { + final PluginBase plugin = (PluginBase) ConfigBuilderPlugin.getPlugin().getActiveAPS(); + if (plugin != null) { + PasswordProtection.QueryPassword(activity, R.string.settings_password, "settings_password", () -> { + Intent i = new Intent(activity, PreferencesActivity.class); + i.putExtra("id", plugin.getPreferencesId()); + activity.startActivity(i); + }, null); + } + }) + .visibility(() -> ConfigBuilderPlugin.getPlugin().getActiveAPS() != null && ((PluginBase) ConfigBuilderPlugin.getPlugin().getActiveAPS()).getPreferencesId() > 0)) + .validator(() -> ConfigBuilderPlugin.getPlugin().getActiveAPS() != null) + .visibility(() -> Config.APS); + + private SWScreen screenApsMode = new SWScreen(R.string.apsmode_title) + .skippable(false) + .add(new SWRadioButton() + .option(R.array.aps_modeArray, R.array.aps_modeValues) + .preferenceId(R.string.key_aps_mode).label(R.string.apsmode_title) + .comment(R.string.setupwizard_preferred_aps_mode)) + .validator(() -> SP.contains(R.string.key_aps_mode)); + + private SWScreen screenLoop = new SWScreen(R.string.configbuilder_loop) + .skippable(false) + .add(new SWInfotext() + .label(R.string.setupwizard_loop_description)) + .add(new SWBreak()) + .add(new SWButton() + .text(R.string.enableloop) + .action(() -> { + LoopPlugin.getPlugin().setPluginEnabled(PluginType.LOOP, true); + LoopPlugin.getPlugin().setFragmentVisible(PluginType.LOOP, true); + ConfigBuilderPlugin.getPlugin().processOnEnabledCategoryChanged(LoopPlugin.getPlugin(), PluginType.LOOP); + ConfigBuilderPlugin.getPlugin().storeSettings("SetupWizard"); + RxBus.INSTANCE.send(new EventConfigBuilderChange()); + RxBus.INSTANCE.send(new EventSWUpdate(true)); + }) + .visibility(() -> !LoopPlugin.getPlugin().isEnabled(PluginType.LOOP))) + .validator(() -> LoopPlugin.getPlugin().isEnabled(PluginType.LOOP)) + .visibility(() -> !LoopPlugin.getPlugin().isEnabled(PluginType.LOOP) && Config.APS); + + private SWScreen screenSensitivity = new SWScreen(R.string.configbuilder_sensitivity) + .skippable(false) + .add(new SWInfotext() + .label(R.string.setupwizard_sensitivity_description)) + .add(new SWHtmlLink() + .label(R.string.setupwizard_sensitivity_url)) + .add(new SWBreak()) + .add(new SWPlugin() + .option(PluginType.SENSITIVITY, R.string.configbuilder_sensitivity_description) + .label(R.string.configbuilder_sensitivity)) + .add(new SWBreak()) + .add(new SWButton() + .text(R.string.sensitivitysetup) + .action(() -> { + final PluginBase plugin = (PluginBase) ConfigBuilderPlugin.getPlugin().getActiveSensitivity(); + if (plugin != null) { + PasswordProtection.QueryPassword(activity, R.string.settings_password, "settings_password", () -> { + Intent i = new Intent(activity, PreferencesActivity.class); + i.putExtra("id", plugin.getPreferencesId()); + activity.startActivity(i); + }, null); + } + }) + .visibility(() -> ConfigBuilderPlugin.getPlugin().getActiveSensitivity() != null && ((PluginBase) ConfigBuilderPlugin.getPlugin().getActiveSensitivity()).getPreferencesId() > 0)) + .validator(() -> ConfigBuilderPlugin.getPlugin().getActiveSensitivity() != null); + + private SWScreen getScreenObjectives = new SWScreen(R.string.objectives) + .skippable(false) + .add(new SWInfotext() + .label(R.string.startobjective)) + .add(new SWBreak()) + .add(new SWFragment(this) + .add(new ObjectivesFragment())) + .validator(() -> ObjectivesPlugin.INSTANCE.getObjectives().get(ObjectivesPlugin.INSTANCE.getFIRST_OBJECTIVE()).isStarted()) + .visibility(() -> !ObjectivesPlugin.INSTANCE.getObjectives().get(ObjectivesPlugin.INSTANCE.getFIRST_OBJECTIVE()).isStarted() && Config.APS); + private void SWDefinitionFull() { // List all the screens here - add(new SWScreen(R.string.nav_setupwizard) - .add(new SWInfotext() - .label(R.string.welcometosetupwizard)) - ) - .add(new SWScreen(R.string.language) - .skippable(false) - .add(new SWRadioButton() - .option(R.array.languagesArray, R.array.languagesValues) - .preferenceId(R.string.key_language).label(R.string.language) - .comment(R.string.setupwizard_language_prompt)) - .validator(() -> { - String lang = SP.getString("language", "en"); - LocaleHelper.setLocale(MainApp.instance().getApplicationContext(), lang); - return SP.contains(R.string.key_language); - }) - ) - .add(new SWScreen(R.string.end_user_license_agreement) - .skippable(false) - .add(new SWInfotext() - .label(R.string.end_user_license_agreement_text)) - .add(new SWBreak()) - .add(new SWButton() - .text(R.string.end_user_license_agreement_i_understand) - .visibility(() -> !SP.getBoolean(R.string.key_i_understand, false)) - .action(() -> { - SP.putBoolean(R.string.key_i_understand, true); - MainApp.bus().post(new EventSWUpdate(false)); - })) - .visibility(() -> !SP.getBoolean(R.string.key_i_understand, false)) - .validator(() -> SP.getBoolean(R.string.key_i_understand, false)) - ) - .add(new SWScreen(R.string.permission) - .skippable(false) - .add(new SWInfotext() - .label(String.format(MainApp.gs(R.string.needwhitelisting), MainApp.gs(R.string.app_name)))) - .add(new SWBreak()) - .add(new SWButton() - .text(R.string.askforpermission) - .visibility(() -> Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)) - .action(() -> AndroidPermission.askForPermission(getActivity(), Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS, AndroidPermission.CASE_BATTERY))) - .visibility(() -> Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)) - .validator(() -> !(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS))) - ) - .add(new SWScreen(R.string.permission) - .skippable(false) - .add(new SWInfotext() - .label(MainApp.gs(R.string.needlocationpermission))) - .add(new SWBreak()) - .add(new SWButton() - .text(R.string.askforpermission) - .visibility(() -> Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION)) - .action(() -> AndroidPermission.askForPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION, AndroidPermission.CASE_LOCATION))) - .visibility(() -> Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION)) - .validator(() -> !(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION))) - ) - .add(new SWScreen(R.string.permission) - .skippable(false) - .add(new SWInfotext() - .label(MainApp.gs(R.string.needstoragepermission))) - .add(new SWBreak()) - .add(new SWButton() - .text(R.string.askforpermission) - .visibility(() -> Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE)) - .action(() -> AndroidPermission.askForPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE, AndroidPermission.CASE_STORAGE))) - .visibility(() -> Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE)) - .validator(() -> !(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE))) - ) - .add(new SWScreen(R.string.nav_import) - .add(new SWInfotext() - .label(R.string.storedsettingsfound)) - .add(new SWBreak()) - .add(new SWButton() - .text(R.string.nav_import) - .action(() -> ImportExportPrefs.importSharedPreferences(getActivity()))) - .visibility(() -> ImportExportPrefs.file.exists() && !(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE))) - ) - .add(new SWScreen(R.string.nsclientinternal_title) - .skippable(true) - .add(new SWInfotext() - .label(R.string.nsclientinfotext)) - .add(new SWBreak()) - .add(new SWButton() - .text(R.string.enable_nsclient) - .action(() -> { - NSClientPlugin.getPlugin().setPluginEnabled(PluginType.GENERAL, true); - NSClientPlugin.getPlugin().setFragmentVisible(PluginType.GENERAL, true); - ConfigBuilderFragment.processOnEnabledCategoryChanged(NSClientPlugin.getPlugin(), PluginType.GENERAL); - ConfigBuilderPlugin.getPlugin().storeSettings("SetupWizard"); - MainApp.bus().post(new EventConfigBuilderChange()); - MainApp.bus().post(new EventSWUpdate(true)); - }) - .visibility(() -> !NSClientPlugin.getPlugin().isEnabled(PluginType.GENERAL))) - .add(new SWEditUrl() - .preferenceId(R.string.key_nsclientinternal_url) - .updateDelay(5) - .label(R.string.nsclientinternal_url_title) - .comment(R.string.nsclientinternal_url_dialogmessage)) - .add(new SWEditString() - .validator(text -> text.length() >= 12) - .preferenceId(R.string.key_nsclientinternal_api_secret) - .updateDelay(5) - .label(R.string.nsclientinternal_secret_dialogtitle) - .comment(R.string.nsclientinternal_secret_dialogmessage)) - .add(new SWBreak()) - .add(new SWEventListener(this) - .label(R.string.status) - .initialStatus(NSClientPlugin.getPlugin().status) - .listener(new Object() { - @Subscribe - public void onEventNSClientStatus(EventNSClientStatus event) { - MainApp.bus().post(new EventSWLabel(event.status)); - } - }) - ) - .add(new SWBreak()) - .validator(() -> NSClientPlugin.getPlugin().nsClientService != null && NSClientPlugin.getPlugin().nsClientService.isConnected && NSClientPlugin.getPlugin().nsClientService.hasWriteAuth) - .visibility(() -> !(NSClientPlugin.getPlugin().nsClientService != null && NSClientPlugin.getPlugin().nsClientService.isConnected && NSClientPlugin.getPlugin().nsClientService.hasWriteAuth)) - ) - .add(new SWScreen(R.string.patientage) - .skippable(false) - .add(new SWInfotext() - .label(R.string.patientage_summary)) - .add(new SWBreak()) - .add(new SWRadioButton() - .option(R.array.ageArray, R.array.ageValues) - .preferenceId(R.string.key_age) - .label(R.string.patientage) - .comment(R.string.patientage_summary)) - .validator(() -> SP.contains(R.string.key_age)) - ) - .add(new SWScreen(R.string.configbuilder_insulin) - .skippable(false) - .add(new SWPlugin() - .option(PluginType.INSULIN, R.string.configbuilder_insulin_description) - .makeVisible(false) - .label(R.string.configbuilder_insulin)) - .add(new SWBreak()) - .add(new SWInfotext() - .label(R.string.diawarning)) - .add(new SWBreak()) - .add(new SWButton() - .text(R.string.insulinsourcesetup) - .action(() -> { - final PluginBase plugin = (PluginBase) ConfigBuilderPlugin.getPlugin().getActiveInsulin(); - PasswordProtection.QueryPassword(activity, R.string.settings_password, "settings_password", () -> { - Intent i = new Intent(activity, PreferencesActivity.class); - i.putExtra("id", plugin.getPreferencesId()); - activity.startActivity(i); - }, null); - }) - .visibility(() -> ConfigBuilderPlugin.getPlugin().getActiveInsulin()!= null && ((PluginBase) ConfigBuilderPlugin.getPlugin().getActiveInsulin()).getPreferencesId() > 0)) - .validator(() -> ConfigBuilderPlugin.getPlugin().getActiveInsulin() != null) - ) - .add(new SWScreen(R.string.configbuilder_bgsource) - .skippable(false) - .add(new SWPlugin() - .option(PluginType.BGSOURCE, R.string.configbuilder_bgsource_description) - .label(R.string.configbuilder_bgsource)) - .add(new SWBreak()) - .add(new SWButton() - .text(R.string.bgsourcesetup) - .action(() -> { - final PluginBase plugin = (PluginBase) ConfigBuilderPlugin.getPlugin().getActiveBgSource(); - PasswordProtection.QueryPassword(activity, R.string.settings_password, "settings_password", () -> { - Intent i = new Intent(activity, PreferencesActivity.class); - i.putExtra("id", plugin.getPreferencesId()); - activity.startActivity(i); - }, null); - }) - .visibility(() -> ConfigBuilderPlugin.getPlugin().getActiveBgSource()!= null && ((PluginBase) ConfigBuilderPlugin.getPlugin().getActiveBgSource()).getPreferencesId() > 0)) - .validator(() -> ConfigBuilderPlugin.getPlugin().getActiveBgSource() != null) - ) - .add(new SWScreen(R.string.configbuilder_profile) - .skippable(false) - .add(new SWInfotext() - .label(R.string.setupwizard_profile_description)) - .add(new SWBreak()) - .add(new SWPlugin() - .option(PluginType.PROFILE, R.string.configbuilder_profile_description) - .label(R.string.configbuilder_profile)) - .validator(() -> ConfigBuilderPlugin.getPlugin().getActiveProfileInterface() != null) - ) - .add(new SWScreen(R.string.nsprofile) - .skippable(false) - .add(new SWInfotext() - .label(R.string.adjustprofileinns)) - .add(new SWFragment(this) - .add(new NSProfileFragment())) - .validator(() -> NSProfilePlugin.getPlugin().getProfile() != null && NSProfilePlugin.getPlugin().getProfile().getDefaultProfile().isValid("StartupWizard")) - .visibility(() -> NSProfilePlugin.getPlugin().isEnabled(PluginType.PROFILE)) - ) - .add(new SWScreen(R.string.localprofile) - .skippable(false) - .add(new SWFragment(this) - .add(new LocalProfileFragment())) - .validator(() -> LocalProfilePlugin.getPlugin().getProfile() != null && LocalProfilePlugin.getPlugin().getProfile().getDefaultProfile().isValid("StartupWizard")) - .visibility(() -> LocalProfilePlugin.getPlugin().isEnabled(PluginType.PROFILE)) - ) - .add(new SWScreen(R.string.simpleprofile) - .skippable(false) - .add(new SWFragment(this) - .add(new SimpleProfileFragment())) - .validator(() -> SimpleProfilePlugin.getPlugin().getProfile() != null && SimpleProfilePlugin.getPlugin().getProfile().getDefaultProfile().isValid("StartupWizard")) - .visibility(() -> SimpleProfilePlugin.getPlugin().isEnabled(PluginType.PROFILE)) - ) - .add(new SWScreen(R.string.profileswitch) - .skippable(false) - .add(new SWInfotext() - .label(R.string.profileswitch_ismissing)) - .add(new SWButton() - .text(R.string.profileswitch) - .action(() -> { - NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog(); - final OptionsToShow profileswitch = CareportalFragment.PROFILESWITCHDIRECT; - profileswitch.executeProfileSwitch = true; - newDialog.setOptions(profileswitch, R.string.careportal_profileswitch); - newDialog.show(getActivity().getSupportFragmentManager(), "NewNSTreatmentDialog"); - })) - .validator(() -> ProfileFunctions.getInstance().getProfile() != null) - .visibility(() -> ProfileFunctions.getInstance().getProfile() == null) - ) - .add(new SWScreen(R.string.configbuilder_pump) - .skippable(false) - .add(new SWPlugin() - .option(PluginType.PUMP, R.string.configbuilder_pump_description) - .label(R.string.configbuilder_pump)) - .add(new SWBreak()) - .add(new SWButton() - .text(R.string.pumpsetup) - .action(() -> { - final PluginBase plugin = (PluginBase) ConfigBuilderPlugin.getPlugin().getActivePump(); - PasswordProtection.QueryPassword(activity, R.string.settings_password, "settings_password", () -> { - Intent i = new Intent(activity, PreferencesActivity.class); - i.putExtra("id", plugin.getPreferencesId()); - activity.startActivity(i); - }, null); - }) - .visibility(() -> ((PluginBase) ConfigBuilderPlugin.getPlugin().getActivePump()).getPreferencesId() > 0)) - .add(new SWButton() - .text(R.string.readstatus) - .action(() -> ConfigBuilderPlugin.getPlugin().getCommandQueue().readStatus("Clicked connect to pump", null)) - .visibility(() -> ConfigBuilderPlugin.getPlugin().getActivePump() != null)) - .add(new SWEventListener(this) - .listener(new Object() { - @Subscribe - public void onEventPumpStatusChanged(EventPumpStatusChanged event) { - MainApp.bus().post(new EventSWLabel(event.textStatus())); - } - }) - ) - .validator(() -> ConfigBuilderPlugin.getPlugin().getActivePump() != null && ConfigBuilderPlugin.getPlugin().getActivePump().isInitialized()) - ) - .add(new SWScreen(R.string.configbuilder_aps) - .skippable(false) - .add(new SWInfotext() - .label(R.string.setupwizard_aps_description)) - .add(new SWBreak()) - .add(new SWHtmlLink() - .label("https://openaps.readthedocs.io/en/latest/")) - .add(new SWBreak()) - .add(new SWPlugin() - .option(PluginType.APS, R.string.configbuilder_aps_description) - .label(R.string.configbuilder_aps)) - .add(new SWButton() - .text(R.string.apssetup) - .action(() -> { - final PluginBase plugin = (PluginBase) ConfigBuilderPlugin.getPlugin().getActiveAPS(); - PasswordProtection.QueryPassword(activity, R.string.settings_password, "settings_password", () -> { - Intent i = new Intent(activity, PreferencesActivity.class); - i.putExtra("id", plugin.getPreferencesId()); - activity.startActivity(i); - }, null); - }) - .visibility(() -> ConfigBuilderPlugin.getPlugin().getActiveAPS() != null && ((PluginBase) ConfigBuilderPlugin.getPlugin().getActiveAPS()).getPreferencesId() > 0)) - .validator(() -> ConfigBuilderPlugin.getPlugin().getActiveAPS() != null) - .visibility(() -> Config.APS) - ) - .add(new SWScreen(R.string.apsmode_title) - .skippable(false) - .add(new SWRadioButton() - .option(R.array.aps_modeArray, R.array.aps_modeValues) - .preferenceId(R.string.key_aps_mode).label(R.string.apsmode_title) - .comment(R.string.setupwizard_preferred_aps_mode)) - .validator(() -> SP.contains(R.string.key_aps_mode)) - ) - .add(new SWScreen(R.string.configbuilder_loop) - .skippable(false) - .add(new SWInfotext() - .label(R.string.setupwizard_loop_description)) - .add(new SWBreak()) - .add(new SWButton() - .text(R.string.enableloop) - .action(() -> { - LoopPlugin.getPlugin().setPluginEnabled(PluginType.LOOP, true); - LoopPlugin.getPlugin().setFragmentVisible(PluginType.LOOP, true); - ConfigBuilderFragment.processOnEnabledCategoryChanged(LoopPlugin.getPlugin(), PluginType.LOOP); - ConfigBuilderPlugin.getPlugin().storeSettings("SetupWizard"); - MainApp.bus().post(new EventConfigBuilderChange()); - MainApp.bus().post(new EventSWUpdate(true)); - }) - .visibility(() -> !LoopPlugin.getPlugin().isEnabled(PluginType.LOOP))) - .validator(() -> LoopPlugin.getPlugin().isEnabled(PluginType.LOOP)) - .visibility(() -> !LoopPlugin.getPlugin().isEnabled(PluginType.LOOP) && Config.APS) - ) - .add(new SWScreen(R.string.configbuilder_sensitivity) - .skippable(false) - .add(new SWInfotext() - .label(R.string.setupwizard_sensitivity_description)) - .add(new SWHtmlLink() - .label(R.string.setupwizard_sensitivity_url)) - .add(new SWBreak()) - .add(new SWPlugin() - .option(PluginType.SENSITIVITY, R.string.configbuilder_sensitivity_description) - .label(R.string.configbuilder_sensitivity)) - .add(new SWBreak()) - .add(new SWButton() - .text(R.string.sensitivitysetup) - .action(() -> { - final PluginBase plugin = (PluginBase) ConfigBuilderPlugin.getPlugin().getActiveSensitivity(); - PasswordProtection.QueryPassword(activity, R.string.settings_password, "settings_password", () -> { - Intent i = new Intent(activity, PreferencesActivity.class); - i.putExtra("id", plugin.getPreferencesId()); - activity.startActivity(i); - }, null); - }) - .visibility(() -> ConfigBuilderPlugin.getPlugin().getActiveSensitivity() != null && ((PluginBase) ConfigBuilderPlugin.getPlugin().getActiveSensitivity()).getPreferencesId() > 0)) - .validator(() -> ConfigBuilderPlugin.getPlugin().getActiveSensitivity() != null) - ) - .add(new SWScreen(R.string.objectives) - .skippable(false) - .add(new SWInfotext() - .label(R.string.setupwizard_objectives_description)) - .add(new SWButton() - .text(R.string.enableobjectives) - .action(() -> { - ObjectivesPlugin.getPlugin().setPluginEnabled(PluginType.CONSTRAINTS, true); - ObjectivesPlugin.getPlugin().setFragmentVisible(PluginType.CONSTRAINTS, true); - ConfigBuilderFragment.processOnEnabledCategoryChanged(ObjectivesPlugin.getPlugin(), PluginType.CONSTRAINTS); - ConfigBuilderPlugin.getPlugin().storeSettings("SetupWizard"); - MainApp.bus().post(new EventConfigBuilderChange()); - MainApp.bus().post(new EventSWUpdate(true)); - }) - .visibility(() -> !ObjectivesPlugin.getPlugin().isFragmentVisible())) - .validator(() -> ObjectivesPlugin.getPlugin().isEnabled(PluginType.CONSTRAINTS)) - .visibility(() -> !ObjectivesPlugin.getPlugin().isFragmentVisible() && Config.APS) - ) - .add(new SWScreen(R.string.objectives) - .skippable(false) - .add(new SWInfotext() - .label(R.string.startobjective)) - .add(new SWBreak()) - .add(new SWFragment(this) - .add(new ObjectivesFragment())) - .validator(() -> ObjectivesPlugin.getPlugin().objectives.get(0).isStarted()) - .visibility(() -> !ObjectivesPlugin.getPlugin().objectives.get(0).isStarted() && Config.APS) - ) + add(screenSetupWizard) + .add(screenLanguage) + .add(screenEula) + .add(screenPermissionBattery) + .add(screenPermissionBt) + .add(screenPermissionStore) + .add(screenImport) + .add(screenNsClient) + .add(screenAge) + .add(screenInsulin) + .add(screenBgSource) + .add(screenProfile) + .add(screenNsProfile) + .add(screenLocalProfile) + .add(screenSimpleProfile) + .add(screenProfileSwitch) + .add(screenPump) + .add(screenAps) + .add(screenApsMode) + .add(screenLoop) + .add(screenSensitivity) + .add(getScreenObjectives) + ; + } + + private void SWDefinitionPumpControl() { + // List all the screens here + add(screenSetupWizard) + .add(screenLanguage) + .add(screenEula) + .add(screenPermissionBattery) + .add(screenPermissionBt) + .add(screenPermissionStore) + .add(screenImport) + .add(screenNsClient) + .add(screenAge) + .add(screenInsulin) + .add(screenBgSource) + .add(screenProfile) + .add(screenNsProfile) + .add(screenLocalProfile) + .add(screenSimpleProfile) + .add(screenProfileSwitch) + .add(screenPump) + .add(screenSensitivity) ; } private void SWDefinitionNSClient() { // List all the screens here - add(new SWScreen(R.string.nav_setupwizard) - .add(new SWInfotext() - .label(R.string.welcometosetupwizard)) - ) - .add(new SWScreen(R.string.language) - .skippable(false) - .add(new SWRadioButton() - .option(R.array.languagesArray, R.array.languagesValues) - .preferenceId(R.string.key_language).label(R.string.language) - .comment(R.string.setupwizard_language_prompt)) - .validator(() -> { - String lang = SP.getString("language", "en"); - LocaleHelper.setLocale(MainApp.instance().getApplicationContext(), lang); - return SP.contains(R.string.key_language); - }) - ) - .add(new SWScreen(R.string.end_user_license_agreement) - .skippable(false) - .add(new SWInfotext() - .label(R.string.end_user_license_agreement_text)) - .add(new SWBreak()) - .add(new SWButton() - .text(R.string.end_user_license_agreement_i_understand) - .visibility(() -> !SP.getBoolean(R.string.key_i_understand, false)) - .action(() -> { - SP.putBoolean(R.string.key_i_understand, true); - MainApp.bus().post(new EventSWUpdate(false)); - })) - .visibility(() -> !SP.getBoolean(R.string.key_i_understand, false)) - .validator(() -> SP.getBoolean(R.string.key_i_understand, false)) - ) - .add(new SWScreen(R.string.permission) - .skippable(false) - .add(new SWInfotext() - .label(String.format(MainApp.gs(R.string.needwhitelisting), MainApp.gs(R.string.app_name)))) - .add(new SWBreak()) - .add(new SWButton() - .text(R.string.askforpermission) - .visibility(() -> Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)) - .action(() -> AndroidPermission.askForPermission(getActivity(), Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS, AndroidPermission.CASE_BATTERY))) - .visibility(() -> Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)) - .validator(() -> !(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS))) - ) - .add(new SWScreen(R.string.permission) - .skippable(false) - .add(new SWInfotext() - .label(MainApp.gs(R.string.needstoragepermission))) - .add(new SWBreak()) - .add(new SWButton() - .text(R.string.askforpermission) - .visibility(() -> Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE)) - .action(() -> AndroidPermission.askForPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE, AndroidPermission.CASE_STORAGE))) - .visibility(() -> Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE)) - .validator(() -> !(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE))) - ) - .add(new SWScreen(R.string.nav_import) - .add(new SWInfotext() - .label(R.string.storedsettingsfound)) - .add(new SWBreak()) - .add(new SWButton() - .text(R.string.nav_import) - .action(() -> ImportExportPrefs.importSharedPreferences(getActivity()))) - .visibility(() -> ImportExportPrefs.file.exists() && !(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE))) - ) - .add(new SWScreen(R.string.nsclientinternal_title) - .skippable(true) - .add(new SWInfotext() - .label(R.string.nsclientinfotext)) - .add(new SWBreak()) - .add(new SWButton() - .text(R.string.enable_nsclient) - .action(() -> { - NSClientPlugin.getPlugin().setPluginEnabled(PluginType.GENERAL, true); - NSClientPlugin.getPlugin().setFragmentVisible(PluginType.GENERAL, true); - ConfigBuilderFragment.processOnEnabledCategoryChanged(NSClientPlugin.getPlugin(), PluginType.GENERAL); - ConfigBuilderPlugin.getPlugin().storeSettings("SetupWizard"); - MainApp.bus().post(new EventConfigBuilderChange()); - MainApp.bus().post(new EventSWUpdate(true)); - }) - .visibility(() -> !NSClientPlugin.getPlugin().isEnabled(PluginType.GENERAL))) - .add(new SWEditUrl() - .preferenceId(R.string.key_nsclientinternal_url) - .updateDelay(5) - .label(R.string.nsclientinternal_url_title) - .comment(R.string.nsclientinternal_url_dialogmessage)) - .add(new SWEditString() - .validator(text -> text.length() >= 12) - .updateDelay(5) - .preferenceId(R.string.key_nsclientinternal_api_secret) - .label(R.string.nsclientinternal_secret_dialogtitle) - .comment(R.string.nsclientinternal_secret_dialogmessage)) - .add(new SWBreak()) - .add(new SWEventListener(this) - .label(R.string.status) - .initialStatus(NSClientPlugin.getPlugin().status) - .listener(new Object() { - @Subscribe - public void onEventNSClientStatus(EventNSClientStatus event) { - MainApp.bus().post(new EventSWLabel(event.status)); - } - }) - ) - .add(new SWBreak()) - .validator(() -> NSClientPlugin.getPlugin().nsClientService != null && NSClientPlugin.getPlugin().nsClientService.isConnected && NSClientPlugin.getPlugin().nsClientService.hasWriteAuth) - .visibility(() -> !(NSClientPlugin.getPlugin().nsClientService != null && NSClientPlugin.getPlugin().nsClientService.isConnected && NSClientPlugin.getPlugin().nsClientService.hasWriteAuth)) - ) - .add(new SWScreen(R.string.configbuilder_bgsource) - .skippable(false) - .add(new SWPlugin() - .option(PluginType.BGSOURCE, R.string.configbuilder_bgsource_description) - .label(R.string.configbuilder_bgsource)) - .add(new SWBreak()) - .add(new SWButton() - .text(R.string.bgsourcesetup) - .action(() -> { - final PluginBase plugin = (PluginBase) ConfigBuilderPlugin.getPlugin().getActiveBgSource(); - PasswordProtection.QueryPassword(activity, R.string.settings_password, "settings_password", () -> { - Intent i = new Intent(activity, PreferencesActivity.class); - i.putExtra("id", plugin.getPreferencesId()); - activity.startActivity(i); - }, null); - }) - .visibility(() -> ConfigBuilderPlugin.getPlugin().getActiveBgSource()!= null && ((PluginBase) ConfigBuilderPlugin.getPlugin().getActiveBgSource()).getPreferencesId() > 0)) - .validator(() -> ConfigBuilderPlugin.getPlugin().getActiveBgSource() != null) - ) - .add(new SWScreen(R.string.patientage) - .skippable(false) - .add(new SWInfotext() - .label(R.string.patientage_summary)) - .add(new SWBreak()) - .add(new SWRadioButton() - .option(R.array.ageArray, R.array.ageValues) - .preferenceId(R.string.key_age) - .label(R.string.patientage) - .comment(R.string.patientage_summary)) - .validator(() -> SP.contains(R.string.key_age)) - ) - .add(new SWScreen(R.string.configbuilder_insulin) - .skippable(false) - .add(new SWPlugin() - .option(PluginType.INSULIN, R.string.configbuilder_insulin_description) - .makeVisible(false) - .label(R.string.configbuilder_insulin)) - .add(new SWBreak()) - .add(new SWInfotext() - .label(R.string.diawarning)) - .add(new SWBreak()) - .add(new SWButton() - .text(R.string.insulinsourcesetup) - .action(() -> { - final PluginBase plugin = (PluginBase) ConfigBuilderPlugin.getPlugin().getActiveInsulin(); - PasswordProtection.QueryPassword(activity, R.string.settings_password, "settings_password", () -> { - Intent i = new Intent(activity, PreferencesActivity.class); - i.putExtra("id", plugin.getPreferencesId()); - activity.startActivity(i); - }, null); - }) - .visibility(() -> ConfigBuilderPlugin.getPlugin().getActiveInsulin()!= null && ((PluginBase) ConfigBuilderPlugin.getPlugin().getActiveInsulin()).getPreferencesId() > 0)) - .validator(() -> ConfigBuilderPlugin.getPlugin().getActiveInsulin() != null) - ) - .add(new SWScreen(R.string.configbuilder_sensitivity) - .skippable(false) - .add(new SWInfotext() - .label(R.string.setupwizard_sensitivity_description)) - .add(new SWHtmlLink() - .label(R.string.setupwizard_sensitivity_url)) - .add(new SWBreak()) - .add(new SWPlugin() - .option(PluginType.SENSITIVITY, R.string.configbuilder_sensitivity_description) - .label(R.string.configbuilder_sensitivity)) - .add(new SWBreak()) - .add(new SWButton() - .text(R.string.sensitivitysetup) - .action(() -> { - final PluginBase plugin = (PluginBase) ConfigBuilderPlugin.getPlugin().getActiveSensitivity(); - PasswordProtection.QueryPassword(activity, R.string.settings_password, "settings_password", () -> { - Intent i = new Intent(activity, PreferencesActivity.class); - i.putExtra("id", plugin.getPreferencesId()); - activity.startActivity(i); - }, null); - }) - .visibility(() -> ConfigBuilderPlugin.getPlugin().getActiveSensitivity() != null && ((PluginBase) ConfigBuilderPlugin.getPlugin().getActiveSensitivity()).getPreferencesId() > 0)) - .validator(() -> ConfigBuilderPlugin.getPlugin().getActiveSensitivity() != null) - ) + add(screenSetupWizard) + .add(screenLanguage) + .add(screenEula) + .add(screenPermissionBattery) + .add(screenPermissionStore) + .add(screenImport) + .add(screenNsClient) + .add(screenBgSource) + .add(screenAge) + .add(screenInsulin) + .add(screenSensitivity) ; } diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/SWEventListener.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/SWEventListener.java index 487a80d91c..26944effbf 100644 --- a/app/src/main/java/info/nightscout/androidaps/setupwizard/SWEventListener.java +++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/SWEventListener.java @@ -1,33 +1,42 @@ package info.nightscout.androidaps.setupwizard; import android.content.Context; -import android.view.View; import android.widget.LinearLayout; import android.widget.TextView; -import com.squareup.otto.Subscribe; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.events.EventStatus; +import info.nightscout.androidaps.plugins.bus.RxBus; import info.nightscout.androidaps.setupwizard.elements.SWItem; -import info.nightscout.androidaps.setupwizard.events.EventSWLabel; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.CompositeDisposable; public class SWEventListener extends SWItem { private static Logger log = LoggerFactory.getLogger(SWEventListener.class); + private CompositeDisposable disposable = new CompositeDisposable(); private int textLabel = 0; private String status = ""; TextView textView; - Object listener; SWDefinition definition; - SWEventListener(SWDefinition definition) { + SWEventListener(SWDefinition definition, Class clazz) { super(Type.LISTENER); this.definition = definition; - MainApp.bus().register(this); + disposable.add(RxBus.INSTANCE + .toObservable(clazz) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(event -> { + status = ((EventStatus) event).getStatus(); + if (textView != null) + textView.setText((textLabel != 0 ? MainApp.gs(textLabel) : "") + " " + status); + }) + ); + } public SWEventListener label(int newLabel) { @@ -35,16 +44,11 @@ public class SWEventListener extends SWItem { return this; } - public SWEventListener initialStatus(String status) { + SWEventListener initialStatus(String status) { this.status = status; return this; } - public SWEventListener listener(Object listener) { - this.listener = listener; - return this; - } - @Override public void generateDialog(LinearLayout layout) { Context context = layout.getContext(); @@ -53,20 +57,5 @@ public class SWEventListener extends SWItem { textView.setId(layout.generateViewId()); textView.setText((textLabel != 0 ? MainApp.gs(textLabel) : "") + " " + status); layout.addView(textView); - if (listener != null) - try { - MainApp.bus().register(listener); - } catch (Exception ignored) {} } - - @Subscribe - public void onEventSWLabel(final EventSWLabel l) { - status = l.label; - if (definition != null && definition.getActivity() != null) - definition.getActivity().runOnUiThread(() -> { - if (textView != null) - textView.setText((textLabel != 0 ? MainApp.gs(textLabel) : "") + " " + status); - }); - } - } diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/SetupWizardActivity.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/SetupWizardActivity.java index 5102e36ac6..e6a4831693 100644 --- a/app/src/main/java/info/nightscout/androidaps/setupwizard/SetupWizardActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/SetupWizardActivity.java @@ -3,15 +3,14 @@ package info.nightscout.androidaps.setupwizard; import android.content.Intent; import android.content.pm.PackageManager; import android.os.Bundle; -import android.support.v4.app.ActivityCompat; -import android.support.v7.app.AlertDialog; -import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.LinearLayout; import android.widget.ScrollView; import android.widget.TextView; -import com.squareup.otto.Subscribe; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AlertDialog; +import androidx.core.app.ActivityCompat; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -21,21 +20,26 @@ import java.util.List; import info.nightscout.androidaps.MainActivity; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.activities.NoSplashAppCompatActivity; +import info.nightscout.androidaps.events.EventProfileNeedsUpdate; import info.nightscout.androidaps.events.EventProfileStoreChanged; -import info.nightscout.androidaps.events.EventProfileSwitchChange; import info.nightscout.androidaps.events.EventPumpStatusChanged; -import info.nightscout.androidaps.plugins.ConstraintsObjectives.events.EventObjectivesSaved; -import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientStatus; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientStatus; import info.nightscout.androidaps.setupwizard.elements.SWItem; import info.nightscout.androidaps.setupwizard.events.EventSWUpdate; -import info.nightscout.utils.AndroidPermission; -import info.nightscout.utils.LocaleHelper; -import info.nightscout.utils.OKDialog; -import info.nightscout.utils.SP; +import info.nightscout.androidaps.utils.AndroidPermission; +import info.nightscout.androidaps.utils.FabricPrivacy; +import info.nightscout.androidaps.utils.LocaleHelper; +import info.nightscout.androidaps.utils.OKDialog; +import info.nightscout.androidaps.utils.SP; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.CompositeDisposable; -public class SetupWizardActivity extends AppCompatActivity { +public class SetupWizardActivity extends NoSplashAppCompatActivity { //logging private static Logger log = LoggerFactory.getLogger(SetupWizardActivity.class); + private CompositeDisposable disposable = new CompositeDisposable(); ScrollView scrollView; @@ -45,9 +49,9 @@ public class SetupWizardActivity extends AppCompatActivity { public static final String INTENT_MESSAGE = "WIZZARDPAGE"; @Override - protected void onCreate(Bundle savedInstanceState) { + public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - LocaleHelper.onCreate(this, "en"); + LocaleHelper.INSTANCE.update(getApplicationContext()); setContentView(R.layout.activity_setupwizard); scrollView = (ScrollView) findViewById(R.id.sw_scrollview); @@ -70,7 +74,8 @@ public class SetupWizardActivity extends AppCompatActivity { @Override public void onBackPressed() { - if (currentWizardPage == 0) OKDialog.showConfirmation(this, MainApp.gs(R.string.exitwizard), this::finish); + if (currentWizardPage == 0) + OKDialog.showConfirmation(this, MainApp.gs(R.string.exitwizard), this::finish); else showPreviousPage(null); } @@ -82,46 +87,41 @@ public class SetupWizardActivity extends AppCompatActivity { @Override public void onPause() { super.onPause(); - MainApp.bus().unregister(this); + disposable.clear(); } @Override protected void onResume() { super.onResume(); - MainApp.bus().register(this); swDefinition.setActivity(this); - } - - @Subscribe - public void onContentUpdate(EventSWUpdate ev) { - if (ev.redraw) - generateLayout(); - updateButtons(); - } - - @Subscribe - public void onEventNSClientStatus(EventNSClientStatus ignored) { - updateButtons(); - } - - @Subscribe - public void onEventPumpStatusChanged(EventPumpStatusChanged ignored) { - updateButtons(); - } - - @Subscribe - public void onEventProfileStoreChanged(EventProfileStoreChanged ignored) { - updateButtons(); - } - - @Subscribe - public void onEventProfileSwitchChange(EventProfileSwitchChange ignored) { - updateButtons(); - } - - @Subscribe - public void onEventObjectivesSaved(EventObjectivesSaved ignored) { - updateButtons(); + disposable.add(RxBus.INSTANCE + .toObservable(EventPumpStatusChanged.class) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(event -> updateButtons(), FabricPrivacy::logException) + ); + disposable.add(RxBus.INSTANCE + .toObservable(EventNSClientStatus.class) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(event -> updateButtons(), FabricPrivacy::logException) + ); + disposable.add(RxBus.INSTANCE + .toObservable(EventProfileNeedsUpdate.class) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(event -> updateButtons(), FabricPrivacy::logException) + ); + disposable.add(RxBus.INSTANCE + .toObservable(EventProfileStoreChanged.class) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(event -> updateButtons(), FabricPrivacy::logException) + ); + disposable.add(RxBus.INSTANCE + .toObservable(EventSWUpdate.class) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(event -> { + if (event.getRedraw()) generateLayout(); + updateButtons(); + }, FabricPrivacy::logException) + ); } private void generateLayout() { @@ -131,7 +131,7 @@ public class SetupWizardActivity extends AppCompatActivity { SWItem currentItem = currentScreen.items.get(i); currentItem.generateDialog(layout); } - scrollView.smoothScrollTo(0,0); + scrollView.smoothScrollTo(0, 0); } private void updateButtons() { @@ -223,4 +223,10 @@ public class SetupWizardActivity extends AppCompatActivity { updateButtons(); } + @Override + protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == AndroidPermission.CASE_BATTERY) + updateButtons(); + } } diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWCheckbox.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWCheckbox.java index ed96b37944..d8194cbfc0 100644 --- a/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWCheckbox.java +++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWCheckbox.java @@ -14,7 +14,7 @@ import java.util.ArrayList; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginType; -import info.nightscout.utils.SP; +import info.nightscout.androidaps.utils.SP; /** * Created by Rumen Georgiev on 5/9/2018. diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWEditString.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWEditString.java index 1f32e6622d..50e851ed6b 100644 --- a/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWEditString.java +++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWEditString.java @@ -5,7 +5,6 @@ import android.graphics.Typeface; import android.text.Editable; import android.text.InputType; import android.text.TextWatcher; -import android.view.View; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.TextView; @@ -14,7 +13,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.setupwizard.SWTextValidator; -import info.nightscout.utils.SP; +import info.nightscout.androidaps.utils.SP; public class SWEditString extends SWItem { diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWEditUrl.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWEditUrl.java index 254723e4e1..f35decbf53 100644 --- a/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWEditUrl.java +++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWEditUrl.java @@ -16,8 +16,9 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.plugins.bus.RxBus; import info.nightscout.androidaps.setupwizard.events.EventSWLabel; -import info.nightscout.utils.SP; +import info.nightscout.androidaps.utils.SP; public class SWEditUrl extends SWItem { private static Logger log = LoggerFactory.getLogger(SWEditUrl.class); @@ -62,7 +63,7 @@ public class SWEditUrl extends SWItem { if (Patterns.WEB_URL.matcher(s).matches()) save(s.toString(), updateDelay); else - MainApp.bus().post(new EventSWLabel(MainApp.gs(R.string.error_url_not_valid))); + RxBus.INSTANCE.send(new EventSWLabel(MainApp.gs(R.string.error_url_not_valid))); } @Override diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWFragment.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWFragment.java index a061f57eb6..29149e5b81 100644 --- a/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWFragment.java @@ -1,7 +1,7 @@ package info.nightscout.androidaps.setupwizard.elements; -import android.support.v4.app.Fragment; -import android.view.View; +import androidx.fragment.app.Fragment; + import android.widget.LinearLayout; import org.slf4j.Logger; diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWItem.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWItem.java index 0cad26c553..6931344acf 100644 --- a/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWItem.java +++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWItem.java @@ -14,8 +14,9 @@ import java.util.concurrent.TimeUnit; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.events.EventPreferenceChange; import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.bus.RxBus; import info.nightscout.androidaps.setupwizard.events.EventSWUpdate; -import info.nightscout.utils.SP; +import info.nightscout.androidaps.utils.SP; public class SWItem { private static Logger log = LoggerFactory.getLogger(SWItem.class); @@ -97,8 +98,8 @@ public class SWItem { public void run() { if (L.isEnabled(L.CORE)) log.debug("Firing EventPreferenceChange"); - MainApp.bus().post(new EventPreferenceChange(preferenceId)); - MainApp.bus().post(new EventSWUpdate()); + RxBus.INSTANCE.send(new EventPreferenceChange(preferenceId)); + RxBus.INSTANCE.send(new EventSWUpdate(false)); scheduledEventPost = null; } } diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWPlugin.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWPlugin.java index 80f60eb678..e5dde501bc 100644 --- a/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWPlugin.java @@ -17,8 +17,8 @@ import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.events.EventConfigBuilderChange; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginType; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.setupwizard.events.EventSWUpdate; public class SWPlugin extends SWItem { @@ -86,10 +86,10 @@ public class SWPlugin extends SWItem { PluginBase plugin = (PluginBase) rb.getTag(); plugin.setPluginEnabled(pType, rb.isChecked()); plugin.setFragmentVisible(pType, rb.isChecked() && makeVisible); - ConfigBuilderFragment.processOnEnabledCategoryChanged(plugin, pType); + ConfigBuilderPlugin.getPlugin().processOnEnabledCategoryChanged(plugin, pType); ConfigBuilderPlugin.getPlugin().storeSettings("SetupWizard"); - MainApp.bus().post(new EventConfigBuilderChange()); - MainApp.bus().post(new EventSWUpdate()); + RxBus.INSTANCE.send(new EventConfigBuilderChange()); + RxBus.INSTANCE.send(new EventSWUpdate(false)); }); layout.addView(radioGroup); super.generateDialog(layout); diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWRadioButton.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWRadioButton.java index cf7dbd55fe..67ef9c19ae 100644 --- a/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWRadioButton.java +++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWRadioButton.java @@ -12,7 +12,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.MainApp; -import info.nightscout.utils.SP; +import info.nightscout.androidaps.utils.SP; public class SWRadioButton extends SWItem { private static Logger log = LoggerFactory.getLogger(SWRadioButton.class); diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/events/EventSWUpdate.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/events/EventSWUpdate.java deleted file mode 100644 index 181960ac40..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/setupwizard/events/EventSWUpdate.java +++ /dev/null @@ -1,14 +0,0 @@ -package info.nightscout.androidaps.setupwizard.events; - -import info.nightscout.androidaps.events.Event; - -public class EventSWUpdate extends Event { - public boolean redraw = false; - - public EventSWUpdate() { - } - - public EventSWUpdate(boolean redraw) { - this.redraw = redraw; - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/events/EventSWUpdate.kt b/app/src/main/java/info/nightscout/androidaps/setupwizard/events/EventSWUpdate.kt new file mode 100644 index 0000000000..3c700cda41 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/events/EventSWUpdate.kt @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.setupwizard.events + +import info.nightscout.androidaps.events.Event + +class EventSWUpdate(var redraw: Boolean) : Event() \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/tabs/TabPageAdapter.java b/app/src/main/java/info/nightscout/androidaps/tabs/TabPageAdapter.java index 88f7d48d32..c567df7b49 100644 --- a/app/src/main/java/info/nightscout/androidaps/tabs/TabPageAdapter.java +++ b/app/src/main/java/info/nightscout/androidaps/tabs/TabPageAdapter.java @@ -1,10 +1,10 @@ package info.nightscout.androidaps.tabs; import android.content.Context; -import android.support.annotation.Nullable; -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentManager; -import android.support.v4.app.FragmentPagerAdapter; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentPagerAdapter; import android.view.ViewGroup; import org.slf4j.Logger; @@ -15,7 +15,7 @@ import java.util.ArrayList; import info.nightscout.androidaps.R; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.logging.L; -import info.nightscout.utils.SP; +import info.nightscout.androidaps.utils.SP; /** * Created by mike on 30.05.2016. diff --git a/app/src/main/java/info/nightscout/androidaps/utils/AndroidPermission.java b/app/src/main/java/info/nightscout/androidaps/utils/AndroidPermission.java new file mode 100644 index 0000000000..9f7986cb97 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/utils/AndroidPermission.java @@ -0,0 +1,131 @@ +package info.nightscout.androidaps.utils; + +import android.Manifest; +import android.annotation.SuppressLint; +import android.app.Activity; +import android.content.ActivityNotFoundException; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.net.Uri; +import android.os.Build; +import android.os.PowerManager; +import android.provider.Settings; + +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification; +import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; +import info.nightscout.androidaps.plugins.general.overview.notifications.NotificationWithAction; + +public class AndroidPermission { + + public static final int CASE_STORAGE = 0x1; + public static final int CASE_SMS = 0x2; + public static final int CASE_LOCATION = 0x3; + public static final int CASE_BATTERY = 0x4; + public static final int CASE_PHONE_STATE = 0x5; + + private static boolean permission_battery_optimization_failed = false; + + @SuppressLint("BatteryLife") + private static void askForPermission(Activity activity, String[] permission, Integer requestCode) { + boolean test = false; + boolean testBattery = false; + for (String s : permission) { + test = test || (ContextCompat.checkSelfPermission(activity, s) != PackageManager.PERMISSION_GRANTED); + if (s.equals(Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)) { + PowerManager powerManager = (PowerManager) activity.getSystemService(Context.POWER_SERVICE); + String packageName = activity.getPackageName(); + testBattery = testBattery || !powerManager.isIgnoringBatteryOptimizations(packageName); + } + } + if (test) { + ActivityCompat.requestPermissions(activity, permission, requestCode); + } + if (testBattery) { + try { + Intent i = new Intent(); + i.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS); + i.setData(Uri.parse("package:" + activity.getPackageName())); + activity.startActivityForResult(i, CASE_BATTERY); + } catch (ActivityNotFoundException e) { + permission_battery_optimization_failed = true; + OKDialog.show(activity, MainApp.gs(R.string.permission), MainApp.gs(R.string.alert_dialog_permission_battery_optimization_failed), activity::recreate); + } + } + } + + public static void askForPermission(Activity activity, String permission, Integer requestCode) { + String[] permissions = {permission}; + askForPermission(activity, permissions, requestCode); + } + + public static boolean permissionNotGranted(Context context, String permission) { + boolean selfCheck = ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED; + if (permission.equals(Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)) { + if (!permission_battery_optimization_failed) { + PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); + String packageName = context.getPackageName(); + selfCheck = selfCheck && powerManager.isIgnoringBatteryOptimizations(packageName); + } + } + return !selfCheck; + } + + public static synchronized void notifyForSMSPermissions(Activity activity) { + if (SP.getBoolean(R.string.key_smscommunicator_remotecommandsallowed, false)) { + if (permissionNotGranted(activity, Manifest.permission.RECEIVE_SMS)) { + NotificationWithAction notification = new NotificationWithAction(Notification.PERMISSION_SMS, MainApp.gs(R.string.smscommunicator_missingsmspermission), Notification.URGENT); + notification.action(R.string.request, () -> AndroidPermission.askForPermission(activity, new String[]{Manifest.permission.RECEIVE_SMS, + Manifest.permission.SEND_SMS, + Manifest.permission.RECEIVE_MMS}, AndroidPermission.CASE_SMS)); + RxBus.INSTANCE.send(new EventNewNotification(notification)); + } else + RxBus.INSTANCE.send(new EventDismissNotification(Notification.PERMISSION_SMS)); + // Following is a bug in Android 8 + if (Build.VERSION.SDK_INT == Build.VERSION_CODES.O) { + if (permissionNotGranted(activity, Manifest.permission.READ_PHONE_STATE)) { + NotificationWithAction notification = new NotificationWithAction(Notification.PERMISSION_PHONESTATE, MainApp.gs(R.string.smscommunicator_missingphonestatepermission), Notification.URGENT); + notification.action(R.string.request, () -> + AndroidPermission.askForPermission(activity, new String[]{Manifest.permission.READ_PHONE_STATE}, AndroidPermission.CASE_PHONE_STATE)); + RxBus.INSTANCE.send(new EventNewNotification(notification)); + } else + RxBus.INSTANCE.send(new EventDismissNotification(Notification.PERMISSION_PHONESTATE)); + } + } + } + + public static synchronized void notifyForBatteryOptimizationPermission(Activity activity) { + if (permissionNotGranted(activity, Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)) { + NotificationWithAction notification = new NotificationWithAction(Notification.PERMISSION_BATTERY, String.format(MainApp.gs(R.string.needwhitelisting), MainApp.gs(R.string.app_name)), Notification.URGENT); + notification.action(R.string.request, () -> AndroidPermission.askForPermission(activity, new String[]{Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS}, AndroidPermission.CASE_BATTERY)); + RxBus.INSTANCE.send(new EventNewNotification(notification)); + } else + RxBus.INSTANCE.send(new EventDismissNotification(Notification.PERMISSION_BATTERY)); + } + + public static synchronized void notifyForStoragePermission(Activity activity) { + if (permissionNotGranted(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE)) { + NotificationWithAction notification = new NotificationWithAction(Notification.PERMISSION_STORAGE, MainApp.gs(R.string.needstoragepermission), Notification.URGENT); + notification.action(R.string.request, () -> AndroidPermission.askForPermission(activity, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, + Manifest.permission.WRITE_EXTERNAL_STORAGE}, AndroidPermission.CASE_STORAGE)); + RxBus.INSTANCE.send(new EventNewNotification(notification)); + } else + RxBus.INSTANCE.send(new EventDismissNotification(Notification.PERMISSION_STORAGE)); + } + + public static synchronized void notifyForLocationPermissions(Activity activity) { + if (permissionNotGranted(activity, Manifest.permission.ACCESS_FINE_LOCATION)) { + NotificationWithAction notification = new NotificationWithAction(Notification.PERMISSION_LOCATION, MainApp.gs(R.string.needlocationpermission), Notification.URGENT); + notification.action(R.string.request, () -> AndroidPermission.askForPermission(activity, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, AndroidPermission.CASE_LOCATION)); + RxBus.INSTANCE.send(new EventNewNotification(notification)); + } else + RxBus.INSTANCE.send(new EventDismissNotification(Notification.PERMISSION_LOCATION)); + } +} diff --git a/app/src/main/java/info/nightscout/utils/BatteryLevel.java b/app/src/main/java/info/nightscout/androidaps/utils/BatteryLevel.java similarity index 96% rename from app/src/main/java/info/nightscout/utils/BatteryLevel.java rename to app/src/main/java/info/nightscout/androidaps/utils/BatteryLevel.java index ea55dd9e69..bc000a95b9 100644 --- a/app/src/main/java/info/nightscout/utils/BatteryLevel.java +++ b/app/src/main/java/info/nightscout/androidaps/utils/BatteryLevel.java @@ -1,4 +1,4 @@ -package info.nightscout.utils; +package info.nightscout.androidaps.utils; import android.content.Intent; import android.content.IntentFilter; diff --git a/app/src/main/java/info/nightscout/androidaps/utils/BolusWizard.kt b/app/src/main/java/info/nightscout/androidaps/utils/BolusWizard.kt new file mode 100644 index 0000000000..ef4cae3f83 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/utils/BolusWizard.kt @@ -0,0 +1,356 @@ +package info.nightscout.androidaps.utils + +import android.content.Context +import android.content.Intent +import androidx.appcompat.app.AlertDialog +import info.nightscout.androidaps.MainApp +import info.nightscout.androidaps.R +import info.nightscout.androidaps.data.DetailedBolusInfo +import info.nightscout.androidaps.data.Profile +import info.nightscout.androidaps.db.CareportalEvent +import info.nightscout.androidaps.db.Source +import info.nightscout.androidaps.db.TempTarget +import info.nightscout.androidaps.events.EventRefreshOverview +import info.nightscout.androidaps.interfaces.Constraint +import info.nightscout.androidaps.interfaces.PluginType +import info.nightscout.androidaps.interfaces.PumpDescription +import info.nightscout.androidaps.interfaces.PumpInterface +import info.nightscout.androidaps.logging.L +import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin +import info.nightscout.androidaps.plugins.bus.RxBus +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin +import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions +import info.nightscout.androidaps.plugins.general.overview.dialogs.ErrorHelperActivity +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin +import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin +import info.nightscout.androidaps.queue.Callback +import org.json.JSONException +import org.json.JSONObject +import org.slf4j.LoggerFactory +import java.util.* +import kotlin.math.abs + +class BolusWizard @JvmOverloads constructor(val profile: Profile, + val profileName: String, + val tempTarget: TempTarget?, + val carbs: Int, + val cob: Double, + val bg: Double, + val correction: Double, + private val percentageCorrection: Double = 100.0, + private val useBg: Boolean, + private val useCob: Boolean, + private val includeBolusIOB: Boolean, + private val includeBasalIOB: Boolean, + private val useSuperBolus: Boolean, + private val useTT: Boolean, + private val useTrend: Boolean, + val notes: String = "", + private val carbTime: Int = 0 +) { + + private val log = LoggerFactory.getLogger(L.CORE) + + // Intermediate + var sens = 0.0 + private set + + var ic = 0.0 + private set + + var glucoseStatus: GlucoseStatus? = null + private set + + private var targetBGLow = 0.0 + + private var targetBGHigh = 0.0 + + private var bgDiff = 0.0 + + var insulinFromBG = 0.0 + private set + + var insulinFromCarbs = 0.0 + private set + + var insulinFromBolusIOB = 0.0 + private set + + var insulinFromBasalsIOB = 0.0 + private set + + var insulinFromCorrection = 0.0 + private set + + var insulinFromSuperBolus = 0.0 + private set + + var insulinFromCOB = 0.0 + private set + + var insulinFromTrend = 0.0 + private set + + var trend = 0.0 + private set + + private var accepted = false + + // Result + var calculatedTotalInsulin: Double = 0.0 + private set + + var totalBeforePercentageAdjustment: Double = 0.0 + private set + + var carbsEquivalent: Double = 0.0 + private set + + var insulinAfterConstraints: Double = 0.0 + private set + + init { + doCalc() + } + + private fun doCalc() { + + // Insulin from BG + sens = profile.isf + targetBGLow = profile.targetLow + targetBGHigh = profile.targetHigh + if (useTT && tempTarget != null) { + targetBGLow = Profile.fromMgdlToUnits(tempTarget.low, profile.units) + targetBGHigh = Profile.fromMgdlToUnits(tempTarget.high, profile.units) + } + if (useBg && bg > 0) { + bgDiff = when { + bg in targetBGLow..targetBGHigh -> 0.0 + bg <= targetBGLow -> bg - targetBGLow + else -> bg - targetBGHigh + } + insulinFromBG = bgDiff / sens + } + + // Insulin from 15 min trend + glucoseStatus = GlucoseStatus.getGlucoseStatusData() + glucoseStatus?.let { + if (useTrend) { + trend = it.short_avgdelta + insulinFromTrend = Profile.fromMgdlToUnits(trend, profile.units) * 3 / sens + } + } + + + // Insulin from carbs + ic = profile.ic + insulinFromCarbs = carbs / ic + insulinFromCOB = if (useCob) (cob / ic) else 0.0 + + // Insulin from IOB + // IOB calculation + val treatments = TreatmentsPlugin.getPlugin() + treatments.updateTotalIOBTreatments() + val bolusIob = treatments.lastCalculationTreatments.round() + treatments.updateTotalIOBTempBasals() + val basalIob = treatments.lastCalculationTempBasals.round() + + insulinFromBolusIOB = if (includeBolusIOB) -bolusIob.iob else 0.0 + insulinFromBasalsIOB = if (includeBasalIOB) -basalIob.basaliob else 0.0 + + // Insulin from correction + insulinFromCorrection = correction + + // Insulin from superbolus for 2h. Get basal rate now and after 1h + if (useSuperBolus) { + insulinFromSuperBolus = profile.basal + var timeAfter1h = System.currentTimeMillis() + timeAfter1h += T.hours(1).msecs() + insulinFromSuperBolus += profile.getBasal(timeAfter1h) + } + + // Total + calculatedTotalInsulin = insulinFromBG + insulinFromTrend + insulinFromCarbs + insulinFromBolusIOB + insulinFromBasalsIOB + insulinFromCorrection + insulinFromSuperBolus + insulinFromCOB + + // Percentage adjustment + totalBeforePercentageAdjustment = calculatedTotalInsulin + if (calculatedTotalInsulin > 0) { + calculatedTotalInsulin = calculatedTotalInsulin * percentageCorrection / 100.0 + } + + if (calculatedTotalInsulin < 0) { + carbsEquivalent = (-calculatedTotalInsulin) * ic + calculatedTotalInsulin = 0.0 + } + + val bolusStep = ConfigBuilderPlugin.getPlugin().activePump?.pumpDescription?.bolusStep + ?: 0.1 + calculatedTotalInsulin = Round.roundTo(calculatedTotalInsulin, bolusStep) + + insulinAfterConstraints = MainApp.getConstraintChecker().applyBolusConstraints(Constraint(calculatedTotalInsulin)).value() + + log.debug(this.toString()) + } + + private fun nsJSON(): JSONObject { + val boluscalcJSON = JSONObject() + try { + boluscalcJSON.put("profile", profileName) + boluscalcJSON.put("notes", notes) + boluscalcJSON.put("eventTime", DateUtil.toISOString(Date())) + boluscalcJSON.put("targetBGLow", targetBGLow) + boluscalcJSON.put("targetBGHigh", targetBGHigh) + boluscalcJSON.put("isf", sens) + boluscalcJSON.put("ic", ic) + boluscalcJSON.put("iob", -(insulinFromBolusIOB + insulinFromBasalsIOB)) + boluscalcJSON.put("bolusiob", insulinFromBolusIOB) + boluscalcJSON.put("basaliob", insulinFromBasalsIOB) + boluscalcJSON.put("bolusiobused", includeBolusIOB) + boluscalcJSON.put("basaliobused", includeBasalIOB) + boluscalcJSON.put("bg", bg) + boluscalcJSON.put("insulinbg", insulinFromBG) + boluscalcJSON.put("insulinbgused", useBg) + boluscalcJSON.put("bgdiff", bgDiff) + boluscalcJSON.put("insulincarbs", insulinFromCarbs) + boluscalcJSON.put("carbs", carbs) + boluscalcJSON.put("cob", cob) + boluscalcJSON.put("cobused", useCob) + boluscalcJSON.put("insulincob", insulinFromCOB) + boluscalcJSON.put("othercorrection", correction) + boluscalcJSON.put("insulinsuperbolus", insulinFromSuperBolus) + boluscalcJSON.put("insulintrend", insulinFromTrend) + boluscalcJSON.put("insulin", calculatedTotalInsulin) + boluscalcJSON.put("superbolusused", useSuperBolus) + boluscalcJSON.put("insulinsuperbolus", insulinFromSuperBolus) + boluscalcJSON.put("trendused", useTrend) + boluscalcJSON.put("insulintrend", insulinFromTrend) + boluscalcJSON.put("trend", trend) + boluscalcJSON.put("ttused", useTT) + boluscalcJSON.put("percentageCorrection", percentageCorrection) + } catch (e: JSONException) { + log.error("Unhandled exception", e) + } + return boluscalcJSON + } + + private fun confirmMessageAfterConstraints(pump: PumpInterface): String { + + var confirmMessage = MainApp.gs(R.string.entertreatmentquestion) + if (insulinAfterConstraints > 0) { + val pct = if (percentageCorrection != 100.0) " (" + percentageCorrection.toInt() + "%)" else "" + confirmMessage += "
" + MainApp.gs(R.string.bolus) + ": " + "" + DecimalFormatter.toPumpSupportedBolus(insulinAfterConstraints) + "U" + pct + "" + } + if (carbs > 0) { + var timeShift = "" + if (carbTime > 0) { + timeShift += " ( +" + MainApp.gs(R.string.mins, carbTime) + " )" + } else if (carbTime < 0) { + timeShift += " ( -" + MainApp.gs(R.string.mins, carbTime) + " )" + } + confirmMessage += "
" + MainApp.gs(R.string.carbs) + ": " + "" + carbs + "g" + timeShift + "" + } + if (insulinFromCOB > 0) { + confirmMessage += "
" + MainApp.gs(R.string.insulinFromCob, MainApp.gc(R.color.cobAlert), insulinFromBolusIOB + insulinFromBasalsIOB + insulinFromCOB + insulinFromBG) + val absorptionRate = IobCobCalculatorPlugin.getPlugin().slowAbsorptionPercentage(60) + if (absorptionRate > .25) + confirmMessage += "
" + MainApp.gs(R.string.slowabsorptiondetected, MainApp.gc(R.color.cobAlert), (absorptionRate * 100).toInt()) + } + if (abs(insulinAfterConstraints - calculatedTotalInsulin) > pump.pumpDescription.pumpType.determineCorrectBolusStepSize(insulinAfterConstraints)) { + confirmMessage += "
" + MainApp.gs(R.string.bolusconstraintappliedwarning, MainApp.gc(R.color.warning), calculatedTotalInsulin, insulinAfterConstraints) + } + + return confirmMessage + } + + fun confirmAndExecute(context: Context) { + val profile = ProfileFunctions.getInstance().profile ?: return + val pump = ConfigBuilderPlugin.getPlugin().activePump ?: return + + if (calculatedTotalInsulin > 0.0 || carbs > 0.0) { + val confirmMessage = confirmMessageAfterConstraints(pump) + + val builder = AlertDialog.Builder(context) + builder.setTitle(MainApp.gs(R.string.confirmation)) + builder.setMessage(HtmlHelper.fromHtml(confirmMessage)) + builder.setPositiveButton(MainApp.gs(R.string.ok)) { _, _ -> + synchronized(builder) { + if (accepted) { + log.debug("guarding: already accepted") + return@setPositiveButton + } + accepted = true + if (insulinAfterConstraints > 0 || carbs > 0) { + if (useSuperBolus) { + val loopPlugin = LoopPlugin.getPlugin() + if (loopPlugin.isEnabled(PluginType.LOOP)) { + loopPlugin.superBolusTo(System.currentTimeMillis() + 2 * 60L * 60 * 1000) + RxBus.send(EventRefreshOverview("WizardDialog")) + } + + val pump1 = ConfigBuilderPlugin.getPlugin().activePump + + if (pump1?.pumpDescription?.tempBasalStyle == PumpDescription.ABSOLUTE) { + ConfigBuilderPlugin.getPlugin().commandQueue.tempBasalAbsolute(0.0, 120, true, profile, object : Callback() { + override fun run() { + if (!result.success) { + val i = Intent(MainApp.instance(), ErrorHelperActivity::class.java) + i.putExtra("soundid", R.raw.boluserror) + i.putExtra("status", result.comment) + i.putExtra("title", MainApp.gs(R.string.tempbasaldeliveryerror)) + i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + MainApp.instance().startActivity(i) + } + } + }) + } else { + + ConfigBuilderPlugin.getPlugin().commandQueue.tempBasalPercent(0, 120, true, profile, object : Callback() { + override fun run() { + if (!result.success) { + val i = Intent(MainApp.instance(), ErrorHelperActivity::class.java) + i.putExtra("soundid", R.raw.boluserror) + i.putExtra("status", result.comment) + i.putExtra("title", MainApp.gs(R.string.tempbasaldeliveryerror)) + i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + MainApp.instance().startActivity(i) + } + } + }) + } + } + val detailedBolusInfo = DetailedBolusInfo() + detailedBolusInfo.eventType = CareportalEvent.BOLUSWIZARD + detailedBolusInfo.insulin = insulinAfterConstraints + detailedBolusInfo.carbs = carbs.toDouble() + detailedBolusInfo.context = context + detailedBolusInfo.glucose = bg + detailedBolusInfo.glucoseType = "Manual" + detailedBolusInfo.carbTime = carbTime + detailedBolusInfo.boluscalc = nsJSON() + detailedBolusInfo.source = Source.USER + detailedBolusInfo.notes = notes + if (detailedBolusInfo.insulin > 0 || ConfigBuilderPlugin.getPlugin().activePump?.pumpDescription?.storesCarbInfo == true) { + ConfigBuilderPlugin.getPlugin().commandQueue.bolus(detailedBolusInfo, object : Callback() { + override fun run() { + if (!result.success) { + val i = Intent(MainApp.instance(), ErrorHelperActivity::class.java) + i.putExtra("soundid", R.raw.boluserror) + i.putExtra("status", result.comment) + i.putExtra("title", MainApp.gs(R.string.treatmentdeliveryerror)) + i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + MainApp.instance().startActivity(i) + } + } + }) + } else { + TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, false) + } + } + } + } + builder.setNegativeButton(MainApp.gs(R.string.cancel), null) + builder.show() + } + } +} diff --git a/app/src/main/java/info/nightscout/utils/CRC.java b/app/src/main/java/info/nightscout/androidaps/utils/CRC.java similarity index 98% rename from app/src/main/java/info/nightscout/utils/CRC.java rename to app/src/main/java/info/nightscout/androidaps/utils/CRC.java index bc59d7e2ae..4c7086de85 100644 --- a/app/src/main/java/info/nightscout/utils/CRC.java +++ b/app/src/main/java/info/nightscout/androidaps/utils/CRC.java @@ -1,4 +1,4 @@ -package info.nightscout.utils; +package info.nightscout.androidaps.utils; public final class CRC { diff --git a/app/src/main/java/info/nightscout/androidaps/utils/CompositeDisposablePlusAssign.kt b/app/src/main/java/info/nightscout/androidaps/utils/CompositeDisposablePlusAssign.kt new file mode 100644 index 0000000000..1f2fb892e5 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/utils/CompositeDisposablePlusAssign.kt @@ -0,0 +1,9 @@ +package info.nightscout.androidaps.utils + +import io.reactivex.disposables.CompositeDisposable +import io.reactivex.disposables.Disposable + +operator fun CompositeDisposable.plusAssign(disposable: Disposable) { + add(disposable) +} + diff --git a/app/src/main/java/info/nightscout/utils/DateUtil.java b/app/src/main/java/info/nightscout/androidaps/utils/DateUtil.java similarity index 57% rename from app/src/main/java/info/nightscout/utils/DateUtil.java rename to app/src/main/java/info/nightscout/androidaps/utils/DateUtil.java index c5d5eed51c..d592347d1b 100644 --- a/app/src/main/java/info/nightscout/utils/DateUtil.java +++ b/app/src/main/java/info/nightscout/androidaps/utils/DateUtil.java @@ -1,7 +1,6 @@ -package info.nightscout.utils; +package info.nightscout.androidaps.utils; -import android.support.v4.util.LongSparseArray; -import android.text.format.DateUtils; +import androidx.collection.LongSparseArray; import org.joda.time.DateTime; import org.joda.time.format.DateTimeFormat; @@ -9,6 +8,8 @@ import org.joda.time.format.DateTimeFormatter; import org.joda.time.format.ISODateTimeFormat; import java.text.DateFormat; +import java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; @@ -38,10 +39,8 @@ public class DateUtil { * * @param isoDateString the iso date string * @return the date - * @throws Exception the exception */ - public static Date fromISODateString(String isoDateString) - throws Exception { + public static Date fromISODateString(String isoDateString) { DateTimeFormatter parser = ISODateTimeFormat.dateTimeParser(); DateTime dateTime = DateTime.parse(isoDateString, parser); @@ -72,6 +71,18 @@ public class DateUtil { return toISOString(new Date(date), FORMAT_DATE_ISO_OUT, TimeZone.getTimeZone("UTC")); } + public static String toISOAsUTC(final long timestamp) { + final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'0000Z'", Locale.US); + format.setTimeZone(TimeZone.getTimeZone("UTC")); + return format.format(timestamp); + } + + public static String toISONoZone(final long timestamp) { + final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.US); + format.setTimeZone(TimeZone.getDefault()); + return format.format(timestamp); + } + public static Date toDate(Integer seconds) { Calendar calendar = new GregorianCalendar(); calendar.set(Calendar.MONTH, 0); // Set january to be sure we miss DST changing @@ -107,11 +118,19 @@ public class DateUtil { } public static String timeString(Date date) { - return new DateTime(date).toString(DateTimeFormat.shortTime()); + String format = "hh:mma"; + if (android.text.format.DateFormat.is24HourFormat(MainApp.instance())) { + format = "HH:mm"; + } + return new DateTime(date).toString(DateTimeFormat.forPattern(format)); } public static String timeString(long mills) { - return new DateTime(mills).toString(DateTimeFormat.shortTime()); + String format = "hh:mma"; + if (android.text.format.DateFormat.is24HourFormat(MainApp.instance())) { + format = "HH:mm"; + } + return new DateTime(mills).toString(DateTimeFormat.forPattern(format)); } public static String timeFullString(long mills) { @@ -127,6 +146,7 @@ public class DateUtil { } public static String dateAndTimeString(long mills) { + if (mills == 0) return ""; return dateString(mills) + " " + timeString(mills); } @@ -183,4 +203,89 @@ public class DateUtil { public static long roundDateToSec(long date) { return date - date % 1000; } + + public static boolean isCloseToNow(long date) { + long diff = Math.abs(date - now()); + return diff < T.mins(2).msecs(); + } + + public static GregorianCalendar gregorianCalendar() { + return new GregorianCalendar(); + } + + public static long getTimeZoneOffsetMs() { + return new GregorianCalendar().getTimeZone().getRawOffset(); + } + + public static int getTimeZoneOffsetMinutes(final long timestamp) { + return TimeZone.getDefault().getOffset(timestamp) / 60000; + } + + public static String niceTimeScalar(long t) { + String unit = MainApp.gs(R.string.unit_second); + t = t / 1000; + if (t != 1) unit = MainApp.gs(R.string.unit_seconds); + if (t > 59) { + unit = MainApp.gs(R.string.unit_minute); + t = t / 60; + if (t != 1) unit = MainApp.gs(R.string.unit_minutes); + if (t > 59) { + unit = MainApp.gs(R.string.unit_hour); + t = t / 60; + if (t != 1) unit = MainApp.gs(R.string.unit_hours); + if (t > 24) { + unit = MainApp.gs(R.string.unit_day) + "\""; + t = t / 24; + if (t != 1) unit = MainApp.gs(R.string.unit_days) + "\""; + if (t > 28) { + unit = MainApp.gs(R.string.unit_week) + "\""; + t = t / 7; + if (t != 1) unit = MainApp.gs(R.string.unit_weeks) + "\""; + } + } + } + } + //if (t != 1) unit = unit + "s"; //implemented plurality in every step, because in other languages plurality of time is not every time adding the same character + return qs((double) t, 0) + " " + unit; + } + + // singletons to avoid repeated allocation + private static DecimalFormatSymbols dfs; + private static DecimalFormat df; + public static String qs(double x, int digits) { + + if (digits == -1) { + digits = 0; + if (((int) x != x)) { + digits++; + if ((((int) x * 10) / 10 != x)) { + digits++; + if ((((int) x * 100) / 100 != x)) digits++; + } + } + } + + if (dfs == null) { + final DecimalFormatSymbols local_dfs = new DecimalFormatSymbols(); + local_dfs.setDecimalSeparator('.'); + dfs = local_dfs; // avoid race condition + } + + final DecimalFormat this_df; + // use singleton if on ui thread otherwise allocate new as DecimalFormat is not thread safe + if (Thread.currentThread().getId() == 1) { + if (df == null) { + final DecimalFormat local_df = new DecimalFormat("#", dfs); + local_df.setMinimumIntegerDigits(1); + df = local_df; // avoid race condition + } + this_df = df; + } else { + this_df = new DecimalFormat("#", dfs); + } + + this_df.setMaximumFractionDigits(digits); + return this_df.format(x); + } + } diff --git a/app/src/main/java/info/nightscout/utils/DecimalFormatter.java b/app/src/main/java/info/nightscout/androidaps/utils/DecimalFormatter.java similarity index 94% rename from app/src/main/java/info/nightscout/utils/DecimalFormatter.java rename to app/src/main/java/info/nightscout/androidaps/utils/DecimalFormatter.java index 620e636843..66464ed1c5 100644 --- a/app/src/main/java/info/nightscout/utils/DecimalFormatter.java +++ b/app/src/main/java/info/nightscout/androidaps/utils/DecimalFormatter.java @@ -1,8 +1,8 @@ -package info.nightscout.utils; +package info.nightscout.androidaps.utils; import java.text.DecimalFormat; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; /** * Created by mike on 11.07.2016. diff --git a/app/src/main/java/info/nightscout/utils/DefaultValueHelper.java b/app/src/main/java/info/nightscout/androidaps/utils/DefaultValueHelper.java similarity index 98% rename from app/src/main/java/info/nightscout/utils/DefaultValueHelper.java rename to app/src/main/java/info/nightscout/androidaps/utils/DefaultValueHelper.java index ba1aba90b8..40448d2680 100644 --- a/app/src/main/java/info/nightscout/utils/DefaultValueHelper.java +++ b/app/src/main/java/info/nightscout/androidaps/utils/DefaultValueHelper.java @@ -1,4 +1,4 @@ -package info.nightscout.utils; +package info.nightscout.androidaps.utils; import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.R; diff --git a/app/src/main/java/info/nightscout/androidaps/utils/DigitsKeyListenerWithComma.java b/app/src/main/java/info/nightscout/androidaps/utils/DigitsKeyListenerWithComma.java new file mode 100644 index 0000000000..a84ccd61a2 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/utils/DigitsKeyListenerWithComma.java @@ -0,0 +1,199 @@ +package info.nightscout.androidaps.utils; + +import android.text.InputType; +import android.text.SpannableStringBuilder; +import android.text.Spanned; +import android.text.method.NumberKeyListener; +import android.view.KeyEvent; + +class DigitsKeyListenerWithComma extends NumberKeyListener { + + /** + * The characters that are used. + * + * @see KeyEvent#getMatch + * @see #getAcceptedChars + */ + private static final char[][] CHARACTERS = new char[][]{ + new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}, + new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-'}, + new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', ','}, + new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '.', ','}, + }; + + private char[] mAccepted; + private boolean mSign; + private boolean mDecimal; + + private static final int SIGN = 1; + private static final int DECIMAL = 2; + + private static DigitsKeyListenerWithComma[] sInstance = new DigitsKeyListenerWithComma[4]; + + @Override + protected char[] getAcceptedChars() { + return mAccepted; + } + + /** + * Allocates a DigitsKeyListener that accepts the digits 0 through 9. + */ + public DigitsKeyListenerWithComma() { + this(false, false); + } + + /** + * Allocates a DigitsKeyListener that accepts the digits 0 through 9, + * plus the minus sign (only at the beginning) and/or decimal point + * (only one per field) if specified. + */ + public DigitsKeyListenerWithComma(boolean sign, boolean decimal) { + mSign = sign; + mDecimal = decimal; + + int kind = (sign ? SIGN : 0) | (decimal ? DECIMAL : 0); + mAccepted = CHARACTERS[kind]; + } + + /** + * Returns a DigitsKeyListener that accepts the digits 0 through 9. + */ + public static DigitsKeyListenerWithComma getInstance() { + return getInstance(false, false); + } + + /** + * Returns a DigitsKeyListener that accepts the digits 0 through 9, + * plus the minus sign (only at the beginning) and/or decimal point + * (only one per field) if specified. + */ + public static DigitsKeyListenerWithComma getInstance(boolean sign, boolean decimal) { + int kind = (sign ? SIGN : 0) | (decimal ? DECIMAL : 0); + + if (sInstance[kind] != null) + return sInstance[kind]; + + sInstance[kind] = new DigitsKeyListenerWithComma(sign, decimal); + return sInstance[kind]; + } + + /** + * Returns a DigitsKeyListener that accepts only the characters + * that appear in the specified String. Note that not all characters + * may be available on every keyboard. + */ + public static DigitsKeyListenerWithComma getInstance(String accepted) { + // TODO: do we need a cache of these to avoid allocating? + + DigitsKeyListenerWithComma dim = new DigitsKeyListenerWithComma(); + + dim.mAccepted = new char[accepted.length()]; + accepted.getChars(0, accepted.length(), dim.mAccepted, 0); + + return dim; + } + + public int getInputType() { + int contentType = InputType.TYPE_CLASS_NUMBER; + if (mSign) { + contentType |= InputType.TYPE_NUMBER_FLAG_SIGNED; + } + if (mDecimal) { + contentType |= InputType.TYPE_NUMBER_FLAG_DECIMAL; + } + return contentType; + } + + @Override + public CharSequence filter(CharSequence source, int start, int end, + Spanned dest, int dstart, int dend) { + CharSequence out = super.filter(source, start, end, dest, dstart, dend); + + if (mSign == false && mDecimal == false) { + return out; + } + + if (out != null) { + source = out; + start = 0; + end = out.length(); + } + + int sign = -1; + int decimal = -1; + int dlen = dest.length(); + + /* + * Find out if the existing text has '-' or '.' characters. + */ + + for (int i = 0; i < dstart; i++) { + char c = dest.charAt(i); + + if (c == '-') { + sign = i; + } else if (c == '.' || c == ',') { + decimal = i; + } + } + for (int i = dend; i < dlen; i++) { + char c = dest.charAt(i); + + if (c == '-') { + return ""; // Nothing can be inserted in front of a '-'. + } else if (c == '.' || c == ',') { + decimal = i; + } + } + + /* + * If it does, we must strip them out from the source. + * In addition, '-' must be the very first character, + * and nothing can be inserted before an existing '-'. + * Go in reverse order so the offsets are stable. + */ + + SpannableStringBuilder stripped = null; + + for (int i = end - 1; i >= start; i--) { + char c = source.charAt(i); + boolean strip = false; + + if (c == '-') { + if (i != start || dstart != 0) { + strip = true; + } else if (sign >= 0) { + strip = true; + } else { + sign = i; + } + } else if (c == '.' || c == ',') { + if (decimal >= 0) { + strip = true; + } else { + decimal = i; + } + } + + if (strip) { + if (end == start + 1) { + return ""; // Only one character, and it was stripped. + } + + if (stripped == null) { + stripped = new SpannableStringBuilder(source, start, end); + } + + stripped.delete(i - start, i + 1 - start); + } + } + + if (stripped != null) { + return stripped; + } else if (out != null) { + return out; + } else { + return null; + } + } +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/utils/FabricPrivacy.java b/app/src/main/java/info/nightscout/androidaps/utils/FabricPrivacy.java new file mode 100644 index 0000000000..355623f38d --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/utils/FabricPrivacy.java @@ -0,0 +1,149 @@ +package info.nightscout.androidaps.utils; + +import android.os.Bundle; + +import com.crashlytics.android.Crashlytics; +import com.google.firebase.analytics.FirebaseAnalytics; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +import info.nightscout.androidaps.BuildConfig; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.constraints.signatureVerifier.SignatureVerifierPlugin; + +/** + * Created by jamorham on 21/02/2018. + *

+ * Some users do not wish to be tracked, Fabric Answers and Crashlytics do not provide an easy way + * to disable them and make calls from a potentially invalid singleton reference. This wrapper + * emulates the methods but ignores the request if the instance is null or invalid. + */ + +public class FabricPrivacy { + private static Logger log = LoggerFactory.getLogger(L.CORE); + + private static volatile FabricPrivacy instance; + + + public static FabricPrivacy getInstance() { + if (instance == null) { + initSelf(); + } + return instance; + } + + private static synchronized void initSelf() { + if (instance == null) { + instance = new FabricPrivacy(); + } + } + + // Crashlytics logException + public static void logException(Throwable throwable) { + try { + final Crashlytics crashlytics = Crashlytics.getInstance(); + crashlytics.core.logException(throwable); + } catch (NullPointerException | IllegalStateException e) { + if (L.isEnabled(L.CORE)) + log.debug("Ignoring opted out non-initialized log: " + throwable); + } + } + + // Crashlytics log + public static void log(String msg) { + try { + final Crashlytics crashlytics = Crashlytics.getInstance(); + crashlytics.core.log(msg); + } catch (NullPointerException | IllegalStateException e) { + if (L.isEnabled(L.CORE)) + log.debug("Ignoring opted out non-initialized log: " + msg); + } + } + + // Crashlytics log + public static void log(int priority, String tag, String msg) { + try { + final Crashlytics crashlytics = Crashlytics.getInstance(); + crashlytics.core.log(priority, tag, msg); + } catch (NullPointerException | IllegalStateException e) { + if (L.isEnabled(L.CORE)) + log.debug("Ignoring opted out non-initialized log: " + msg); + } + } + + public static boolean fabricEnabled() { + return SP.getBoolean("enable_fabric", true); + } + + // Analytics logCustom + public void logCustom(Bundle event) { + try { + if (fabricEnabled()) { + MainApp.getFirebaseAnalytics().logEvent(FirebaseAnalytics.Event.SELECT_CONTENT, event); + } else { + if (L.isEnabled(L.CORE)) + log.debug("Ignoring recently opted-out event: " + event.toString()); + } + } catch (NullPointerException | IllegalStateException e) { + if (L.isEnabled(L.CORE)) + log.debug("Ignoring opted-out non-initialized event: " + event.toString()); + } + } + + // Analytics logCustom + public void logCustom(String event) { + try { + if (fabricEnabled()) { + MainApp.getFirebaseAnalytics().logEvent(event, new Bundle()); + } else { + if (L.isEnabled(L.CORE)) + log.debug("Ignoring recently opted-out event: " + event); + } + } catch (NullPointerException | IllegalStateException e) { + if (L.isEnabled(L.CORE)) + log.debug("Ignoring opted-out non-initialized event: " + event); + } + } + + public static void setUserStats() { + if (!fabricEnabled()) return; + + String closedLoopEnabled = MainApp.getConstraintChecker().isClosedLoopAllowed().value() ? "CLOSED_LOOP_ENABLED" : "CLOSED_LOOP_DISABLED"; + // Size is limited to 36 chars + String remote = BuildConfig.REMOTE.toLowerCase() + .replace("https://", "") + .replace("http://", "") + .replace(".git", "") + .replace(".com/", ":") + .replace(".org/", ":") + .replace(".net/", ":"); + + MainApp.getFirebaseAnalytics().setUserProperty("Mode", BuildConfig.APPLICATION_ID + "-" + closedLoopEnabled); + MainApp.getFirebaseAnalytics().setUserProperty("Language", LocaleHelper.INSTANCE.currentLanguage()); + MainApp.getFirebaseAnalytics().setUserProperty("Version", BuildConfig.VERSION); + MainApp.getFirebaseAnalytics().setUserProperty("HEAD", BuildConfig.HEAD); + MainApp.getFirebaseAnalytics().setUserProperty("Remote", remote); + List hashes = SignatureVerifierPlugin.getPlugin().shortHashes(); + if (hashes.size() >= 1) + MainApp.getFirebaseAnalytics().setUserProperty("Hash", hashes.get(0)); + + if (ConfigBuilderPlugin.getPlugin().getActivePump() != null) + MainApp.getFirebaseAnalytics().setUserProperty("Pump", ConfigBuilderPlugin.getPlugin().getActivePump().getClass().getSimpleName()); + if (ConfigBuilderPlugin.getPlugin().getActiveAPS() != null) + MainApp.getFirebaseAnalytics().setUserProperty("Aps", ConfigBuilderPlugin.getPlugin().getActiveAPS().getClass().getSimpleName()); + if (ConfigBuilderPlugin.getPlugin().getActiveBgSource() != null) + MainApp.getFirebaseAnalytics().setUserProperty("BgSource", ConfigBuilderPlugin.getPlugin().getActiveBgSource().getClass().getSimpleName()); + if (ConfigBuilderPlugin.getPlugin().getActiveProfileInterface() != null) + MainApp.getFirebaseAnalytics().setUserProperty("Profile", ConfigBuilderPlugin.getPlugin().getActiveProfileInterface().getClass().getSimpleName()); + if (ConfigBuilderPlugin.getPlugin().getActiveSensitivity() != null) + MainApp.getFirebaseAnalytics().setUserProperty("Sensitivity", ConfigBuilderPlugin.getPlugin().getActiveSensitivity().getClass().getSimpleName()); + if (ConfigBuilderPlugin.getPlugin().getActiveInsulin() != null) + MainApp.getFirebaseAnalytics().setUserProperty("Insulin", ConfigBuilderPlugin.getPlugin().getActiveInsulin().getClass().getSimpleName()); + } + +} diff --git a/app/src/main/java/info/nightscout/utils/HardLimits.java b/app/src/main/java/info/nightscout/androidaps/utils/HardLimits.java similarity index 96% rename from app/src/main/java/info/nightscout/utils/HardLimits.java rename to app/src/main/java/info/nightscout/androidaps/utils/HardLimits.java index 1a36561b62..8b80c4c6fc 100644 --- a/app/src/main/java/info/nightscout/utils/HardLimits.java +++ b/app/src/main/java/info/nightscout/androidaps/utils/HardLimits.java @@ -1,11 +1,11 @@ -package info.nightscout.utils; +package info.nightscout.androidaps.utils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.plugins.NSClientInternal.NSUpload; +import info.nightscout.androidaps.plugins.general.nsclient.NSUpload; /** * Created by mike on 22.02.2017. diff --git a/app/src/main/java/info/nightscout/androidaps/utils/HtmlHelper.kt b/app/src/main/java/info/nightscout/androidaps/utils/HtmlHelper.kt new file mode 100644 index 0000000000..b79fe884b4 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/utils/HtmlHelper.kt @@ -0,0 +1,16 @@ +package info.nightscout.androidaps.utils + +import android.os.Build +import android.text.Html +import android.text.Spanned + +object HtmlHelper { + fun fromHtml(source: String): Spanned { + // API level 24 to replace call + @Suppress("DEPRECATION") + return when { + Build.VERSION.SDK_INT >= Build.VERSION_CODES.N -> Html.fromHtml(source, Html.FROM_HTML_MODE_LEGACY) + else -> Html.fromHtml(source) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/utils/InstanceId.kt b/app/src/main/java/info/nightscout/androidaps/utils/InstanceId.kt new file mode 100644 index 0000000000..64c84fcaa9 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/utils/InstanceId.kt @@ -0,0 +1,10 @@ +package info.nightscout.androidaps.utils + +import com.google.firebase.iid.FirebaseInstanceId + +object InstanceId { + fun instanceId(): String { + var id = FirebaseInstanceId.getInstance().id + return id + } +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/utils/JSONFormatter.java b/app/src/main/java/info/nightscout/androidaps/utils/JSONFormatter.java similarity index 73% rename from app/src/main/java/info/nightscout/utils/JSONFormatter.java rename to app/src/main/java/info/nightscout/androidaps/utils/JSONFormatter.java index 499ba01652..6205beee21 100644 --- a/app/src/main/java/info/nightscout/utils/JSONFormatter.java +++ b/app/src/main/java/info/nightscout/androidaps/utils/JSONFormatter.java @@ -1,5 +1,6 @@ -package info.nightscout.utils; +package info.nightscout.androidaps.utils; +import android.os.Build; import android.text.Html; import android.text.Spanned; @@ -18,14 +19,23 @@ public class JSONFormatter { private static Logger log = LoggerFactory.getLogger(JSONFormatter.class); public static Spanned format(final String jsonString) { - final JsonVisitor visitor = new JsonVisitor(4, ' '); + final JsonVisitor visitor = new JsonVisitor(1, '\t'); try { if (jsonString.equals("undefined")) return Html.fromHtml("undefined"); else if (jsonString.getBytes()[0] == '[') - return Html.fromHtml(visitor.visit(new JSONArray(jsonString), 0)); - else - return Html.fromHtml(visitor.visit(new JSONObject(jsonString), 0)); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + return Html.fromHtml(visitor.visit(new JSONArray(jsonString), 0), Html.FROM_HTML_MODE_COMPACT); + } else { + return Html.fromHtml(visitor.visit(new JSONArray(jsonString), 0)); + } + else { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + return Html.fromHtml(visitor.visit(new JSONObject(jsonString), 0), Html.FROM_HTML_MODE_COMPACT); + } else { + return Html.fromHtml(visitor.visit(new JSONObject(jsonString), 0)); + } + } } catch (JSONException e) { log.error("Unhandled exception", e); return Html.fromHtml(""); @@ -33,7 +43,7 @@ public class JSONFormatter { } public static Spanned format(final JSONObject object) { - final JsonVisitor visitor = new JsonVisitor(4, ' '); + final JsonVisitor visitor = new JsonVisitor(1, '\t'); try { return Html.fromHtml(visitor.visit(object, 0)); } catch (JSONException e) { @@ -58,7 +68,7 @@ public class JSONFormatter { } else { ret += write("[", indent); for (int i = 0; i < length; i++) { - ret += visit(array.get(i), indent + 1); + ret += visit(array.get(i), indent); } ret += write("]", indent); } @@ -73,8 +83,8 @@ public class JSONFormatter { final Iterator keys = obj.keys(); while (keys.hasNext()) { final String key = keys.next(); - ret += write("" + key + ": ", indent + 1); - ret += visit(obj.get(key), 0); + ret += write("" + key + ": ", indent); + ret += visit(obj.get(key), indent + 1); ret += "
"; } } @@ -86,7 +96,7 @@ public class JSONFormatter { if (object instanceof JSONArray) { ret += visit((JSONArray) object, indent); } else if (object instanceof JSONObject) { - ret += visit((JSONObject) object, indent); + ret += "
" + visit((JSONObject) object, indent); } else { if (object instanceof String) { ret += write("\"" + ((String) object).replace("<", "<").replace(">", ">") + "\"", indent); diff --git a/app/src/main/java/info/nightscout/utils/JsonHelper.java b/app/src/main/java/info/nightscout/androidaps/utils/JsonHelper.java similarity index 85% rename from app/src/main/java/info/nightscout/utils/JsonHelper.java rename to app/src/main/java/info/nightscout/androidaps/utils/JsonHelper.java index e082ed99f7..5308c62420 100644 --- a/app/src/main/java/info/nightscout/utils/JsonHelper.java +++ b/app/src/main/java/info/nightscout/androidaps/utils/JsonHelper.java @@ -1,6 +1,6 @@ -package info.nightscout.utils; +package info.nightscout.androidaps.utils; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import org.json.JSONException; import org.json.JSONObject; @@ -17,7 +17,7 @@ public class JsonHelper { private static final Logger log = LoggerFactory.getLogger(JsonHelper.class); - private JsonHelper() {}; + private JsonHelper() {} public static Object safeGetObject(JSONObject json, String fieldName, Object defaultValue) { Object result = defaultValue; @@ -72,6 +72,19 @@ public class JsonHelper { return result; } + public static double safeGetDouble(JSONObject json, String fieldName, double defaultValue) { + double result = defaultValue; + + if (json != null && json.has(fieldName)) { + try { + result = json.getDouble(fieldName); + } catch (JSONException ignored) { + } + } + + return result; + } + public static int safeGetInt(JSONObject json, String fieldName) { int result = 0; diff --git a/app/src/main/java/info/nightscout/utils/LocalAlertUtils.java b/app/src/main/java/info/nightscout/androidaps/utils/LocalAlertUtils.java similarity index 85% rename from app/src/main/java/info/nightscout/utils/LocalAlertUtils.java rename to app/src/main/java/info/nightscout/androidaps/utils/LocalAlertUtils.java index 89c422ec53..282ad1aa55 100644 --- a/app/src/main/java/info/nightscout/utils/LocalAlertUtils.java +++ b/app/src/main/java/info/nightscout/androidaps/utils/LocalAlertUtils.java @@ -1,4 +1,4 @@ -package info.nightscout.utils; +package info.nightscout.androidaps.utils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -10,13 +10,14 @@ import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.db.DatabaseHelper; import info.nightscout.androidaps.interfaces.PumpInterface; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions; -import info.nightscout.androidaps.plugins.Loop.LoopPlugin; -import info.nightscout.androidaps.plugins.NSClientInternal.NSUpload; -import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; -import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; -import info.nightscout.androidaps.plugins.Overview.notifications.Notification; +import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; +import info.nightscout.androidaps.plugins.general.nsclient.NSUpload; +import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification; +import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; /** * Created by adrian on 17/12/17. @@ -43,13 +44,13 @@ public class LocalAlertUtils { Notification n = new Notification(Notification.PUMP_UNREACHABLE, MainApp.gs(R.string.pump_unreachable), Notification.URGENT); n.soundId = R.raw.alarm; SP.putLong("nextPumpDisconnectedAlarm", System.currentTimeMillis() + pumpUnreachableThreshold()); - MainApp.bus().post(new EventNewNotification(n)); + RxBus.INSTANCE.send(new EventNewNotification(n)); if (SP.getBoolean(R.string.key_ns_create_announcements_from_errors, true)) { NSUpload.uploadError(n.text); } } if (!isStatusOutdated && !alarmTimeoutExpired) - MainApp.bus().post(new EventDismissNotification(Notification.PUMP_UNREACHABLE)); + RxBus.INSTANCE.send(new EventDismissNotification(Notification.PUMP_UNREACHABLE)); } /*Presnoozes the alarms with 5 minutes if no snooze exists. @@ -97,7 +98,7 @@ public class LocalAlertUtils { Notification n = new Notification(Notification.BG_READINGS_MISSED, MainApp.gs(R.string.missed_bg_readings), Notification.URGENT); n.soundId = R.raw.alarm; SP.putLong("nextMissedReadingsAlarm", System.currentTimeMillis() + missedReadingsThreshold()); - MainApp.bus().post(new EventNewNotification(n)); + RxBus.INSTANCE.send(new EventNewNotification(n)); if (SP.getBoolean(R.string.key_ns_create_announcements_from_errors, true)) { NSUpload.uploadError(n.text); } diff --git a/app/src/main/java/info/nightscout/androidaps/utils/LocaleHelper.kt b/app/src/main/java/info/nightscout/androidaps/utils/LocaleHelper.kt new file mode 100644 index 0000000000..6052c5699a --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/utils/LocaleHelper.kt @@ -0,0 +1,32 @@ +package info.nightscout.androidaps.utils + +import android.content.Context +import info.nightscout.androidaps.R +import java.util.* + +object LocaleHelper { + fun update(context: Context) = + updateResources(context, currentLanguage()) + + fun currentLanguage(): String = + SP.getString(R.string.key_language, Locale.getDefault().language) + + fun currentLocale(): Locale = + Locale(SP.getString(R.string.key_language, Locale.getDefault().language)) + + @Suppress("DEPRECATION") + private fun updateResources(context: Context, language: String) { + var locale = Locale(language) + if (language.contains("_")) { + // language with country like pt_BR defined in arrays.xml + val lang = language.substring(0, 2) + val country = language.substring(3, 5) + locale = Locale(lang, country) + } + + Locale.setDefault(locale) + val resources = context.resources + resources.configuration.setLocale(locale) + resources.updateConfiguration(resources.configuration, resources.displayMetrics) + } +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/utils/MidnightTime.java b/app/src/main/java/info/nightscout/androidaps/utils/MidnightTime.java new file mode 100644 index 0000000000..235bb9c6e9 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/utils/MidnightTime.java @@ -0,0 +1,55 @@ +package info.nightscout.androidaps.utils; + +import android.util.LongSparseArray; + +import java.util.Calendar; + +public class MidnightTime { + static final LongSparseArray times = new LongSparseArray<>(); + + private static long hits = 0; + private static long misses = 0; + + private static final int THRESHOLD = 100000; + + public static long calc() { + Calendar c = Calendar.getInstance(); + c.set(Calendar.HOUR_OF_DAY, 0); + c.set(Calendar.MINUTE, 0); + c.set(Calendar.SECOND, 0); + c.set(Calendar.MILLISECOND, 0); + return c.getTimeInMillis(); + } + + public static long calc(long time) { + Long m; + synchronized (times) { + m = times.get(time); + if (m != null) { + ++hits; + return m; + } + Calendar c = Calendar.getInstance(); + c.setTimeInMillis(time); + c.set(Calendar.HOUR_OF_DAY, 0); + c.set(Calendar.MINUTE, 0); + c.set(Calendar.SECOND, 0); + c.set(Calendar.MILLISECOND, 0); + m = c.getTimeInMillis(); + times.append(time, m); + ++misses; + if (times.size() > THRESHOLD) resetCache(); + } + return m; + } + + static void resetCache() { + hits = 0; + misses = 0; + times.clear(); + } + + public static String log() { + return "Hits: " + hits + " misses: " + misses + " stored: " + times.size(); + } +} diff --git a/app/src/main/java/info/nightscout/utils/NumberPicker.java b/app/src/main/java/info/nightscout/androidaps/utils/NumberPicker.java similarity index 72% rename from app/src/main/java/info/nightscout/utils/NumberPicker.java rename to app/src/main/java/info/nightscout/androidaps/utils/NumberPicker.java index 102abedc7d..e2a7489fc2 100644 --- a/app/src/main/java/info/nightscout/utils/NumberPicker.java +++ b/app/src/main/java/info/nightscout/androidaps/utils/NumberPicker.java @@ -1,4 +1,4 @@ -package info.nightscout.utils; +package info.nightscout.androidaps.utils; import android.content.Context; import android.os.Handler; @@ -14,7 +14,6 @@ import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.LinearLayout; -import android.widget.TextView; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -34,7 +33,11 @@ public class NumberPicker extends LinearLayout implements View.OnKeyListener, View.OnTouchListener, View.OnClickListener { private static Logger log = LoggerFactory.getLogger(NumberPicker.class); - TextView editText; + public interface OnValueChangedListener { + void onValueChanged(double value); + } + + EditText editText; Button minusButton; Button plusButton; @@ -46,8 +49,11 @@ public class NumberPicker extends LinearLayout implements View.OnKeyListener, boolean allowZero = false; TextWatcher textWatcher = null; + Button okButton = null; + private Handler mHandler; private ScheduledExecutorService mUpdater; + private OnValueChangedListener mOnValueChangedListener; private class UpdateCounterTask implements Runnable { private boolean mInc; @@ -56,7 +62,7 @@ public class NumberPicker extends LinearLayout implements View.OnKeyListener, private final int doubleLimit = 5; - public UpdateCounterTask(boolean inc) { + UpdateCounterTask(boolean inc) { mInc = inc; } @@ -85,39 +91,32 @@ public class NumberPicker extends LinearLayout implements View.OnKeyListener, public NumberPicker(Context context, AttributeSet attrs) { super(context, attrs); - this.initialize(context, attrs); + this.initialize(context); } - public NumberPicker(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - } - - private void initialize(Context context, AttributeSet attrs) { + private void initialize(Context context) { // set layout view LayoutInflater.from(context).inflate(R.layout.number_picker_layout, this, true); // init ui components - minusButton = (Button) findViewById(R.id.decrement); + minusButton = findViewById(R.id.decrement); minusButton.setId(View.generateViewId()); - plusButton = (Button) findViewById(R.id.increment); + plusButton = findViewById(R.id.increment); plusButton.setId(View.generateViewId()); - editText = (EditText) findViewById(R.id.display); + editText = findViewById(R.id.display); editText.setId(View.generateViewId()); - mHandler = new Handler() { - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case MSG_INC: - inc(msg.arg1); - return; - case MSG_DEC: - dec(msg.arg1); - return; - } - super.handleMessage(msg); + mHandler = new Handler(msg -> { + switch (msg.what) { + case MSG_INC: + inc(msg.arg1); + return true; + case MSG_DEC: + dec(msg.arg1); + return true; } - }; + return false; + }); minusButton.setOnTouchListener(this); minusButton.setOnKeyListener(this); @@ -139,33 +138,66 @@ public class NumberPicker extends LinearLayout implements View.OnKeyListener, @Override public void afterTextChanged(Editable s) { value = SafeParse.stringToDouble(editText.getText().toString()); + callValueChangedListener(); + if (okButton != null) { + if (value > maxValue || value < minValue) + okButton.setVisibility(INVISIBLE); + else + okButton.setVisibility(VISIBLE); + } } }); } + public void setOnValueChangedListener(OnValueChangedListener onValueChangedListener) { + mOnValueChangedListener = onValueChangedListener; + } + public void setTextWatcher(TextWatcher textWatcher) { this.textWatcher = textWatcher; editText.addTextChangedListener(textWatcher); + editText.setOnFocusChangeListener((v, hasFocus) -> { + if (!hasFocus) { + value = SafeParse.stringToDouble(editText.getText().toString()); + if (value > maxValue) { + value = maxValue; + ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.youareonallowedlimit)); + updateEditText(); + if (okButton != null) + okButton.setVisibility(VISIBLE); + } + if (value < minValue) { + value = minValue; + ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.youareonallowedlimit)); + updateEditText(); + if (okButton != null) + okButton.setVisibility(VISIBLE); + } + } + }); } - public void setParams(Double initValue, Double minValue, Double maxValue, Double step, NumberFormat formater, boolean allowZero, TextWatcher textWatcher) { + public void setParams(Double initValue, Double minValue, Double maxValue, Double step, NumberFormat formater, boolean allowZero, Button okButton, TextWatcher textWatcher) { if (this.textWatcher != null) { editText.removeTextChangedListener(this.textWatcher); } - setParams(initValue, minValue, maxValue, step, formater, allowZero); + setParams(initValue, minValue, maxValue, step, formater, allowZero, okButton); this.textWatcher = textWatcher; - editText.addTextChangedListener(textWatcher); + if (textWatcher != null) + editText.addTextChangedListener(textWatcher); } - public void setParams(Double initValue, Double minValue, Double maxValue, Double step, NumberFormat formater, boolean allowZero) { + public void setParams(Double initValue, Double minValue, Double maxValue, Double step, NumberFormat formater, boolean allowZero, Button okButton) { this.value = initValue; this.minValue = minValue; this.maxValue = maxValue; this.step = step; this.formater = formater; this.allowZero = allowZero; + callValueChangedListener(); + this.okButton = okButton; - editText.setKeyListener(DigitsKeyListener.getInstance(minValue < 0, step != Math.rint(step))); + editText.setKeyListener(DigitsKeyListenerWithComma.getInstance(minValue < 0, step != Math.rint(step))); if (textWatcher != null) editText.removeTextChangedListener(textWatcher); @@ -178,6 +210,7 @@ public class NumberPicker extends LinearLayout implements View.OnKeyListener, if (textWatcher != null) editText.removeTextChangedListener(textWatcher); this.value = value; + callValueChangedListener(); updateEditText(); if (textWatcher != null) editText.addTextChangedListener(textWatcher); @@ -199,6 +232,7 @@ public class NumberPicker extends LinearLayout implements View.OnKeyListener, value += step * multiplier; if (value > maxValue) { value = maxValue; + callValueChangedListener(); ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.youareonallowedlimit)); stopUpdating(); } @@ -209,6 +243,7 @@ public class NumberPicker extends LinearLayout implements View.OnKeyListener, value -= step * multiplier; if (value < minValue) { value = minValue; + callValueChangedListener(); ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.youareonallowedlimit)); stopUpdating(); } @@ -222,6 +257,11 @@ public class NumberPicker extends LinearLayout implements View.OnKeyListener, editText.setText(formater.format(value)); } + private void callValueChangedListener() { + if (mOnValueChangedListener != null) + mOnValueChangedListener.onValueChanged(value); + } + private void startUpdating(boolean inc) { if (mUpdater != null) { log.debug("Another executor is still active"); diff --git a/app/src/main/java/info/nightscout/utils/OKDialog.java b/app/src/main/java/info/nightscout/androidaps/utils/OKDialog.java similarity index 94% rename from app/src/main/java/info/nightscout/utils/OKDialog.java rename to app/src/main/java/info/nightscout/androidaps/utils/OKDialog.java index 0e9d95a22c..a45d329d63 100644 --- a/app/src/main/java/info/nightscout/utils/OKDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/utils/OKDialog.java @@ -1,12 +1,12 @@ -package info.nightscout.utils; +package info.nightscout.androidaps.utils; import android.app.Activity; import android.content.Context; import android.content.DialogInterface; import android.os.Handler; import android.os.SystemClock; -import android.support.v7.app.AlertDialog; -import android.support.v7.view.ContextThemeWrapper; +import androidx.appcompat.app.AlertDialog; +import androidx.appcompat.view.ContextThemeWrapper; import android.text.Spanned; import org.slf4j.Logger; @@ -39,7 +39,7 @@ public class OKDialog { builder.create().show(); } catch (Exception e) { - log.debug("show_dialog exception: " + e); + log.debug("show_dialog exception: ", e); } } diff --git a/app/src/main/java/info/nightscout/utils/PasswordProtection.java b/app/src/main/java/info/nightscout/androidaps/utils/PasswordProtection.java similarity index 98% rename from app/src/main/java/info/nightscout/utils/PasswordProtection.java rename to app/src/main/java/info/nightscout/androidaps/utils/PasswordProtection.java index 2a15dc7311..230be97e22 100644 --- a/app/src/main/java/info/nightscout/utils/PasswordProtection.java +++ b/app/src/main/java/info/nightscout/androidaps/utils/PasswordProtection.java @@ -1,4 +1,4 @@ -package info.nightscout.utils; +package info.nightscout.androidaps.utils; import android.app.AlertDialog; import android.content.Context; diff --git a/app/src/main/java/info/nightscout/utils/PercentageSplitter.java b/app/src/main/java/info/nightscout/androidaps/utils/PercentageSplitter.java similarity index 95% rename from app/src/main/java/info/nightscout/utils/PercentageSplitter.java rename to app/src/main/java/info/nightscout/androidaps/utils/PercentageSplitter.java index d590426b28..b3f8156cfe 100644 --- a/app/src/main/java/info/nightscout/utils/PercentageSplitter.java +++ b/app/src/main/java/info/nightscout/androidaps/utils/PercentageSplitter.java @@ -1,4 +1,4 @@ -package info.nightscout.utils; +package info.nightscout.androidaps.utils; import java.util.regex.Matcher; import java.util.regex.Pattern; diff --git a/app/src/main/java/info/nightscout/utils/Profiler.java b/app/src/main/java/info/nightscout/androidaps/utils/Profiler.java similarity index 88% rename from app/src/main/java/info/nightscout/utils/Profiler.java rename to app/src/main/java/info/nightscout/androidaps/utils/Profiler.java index 140adc6366..05eed9e97d 100644 --- a/app/src/main/java/info/nightscout/utils/Profiler.java +++ b/app/src/main/java/info/nightscout/androidaps/utils/Profiler.java @@ -1,4 +1,4 @@ -package info.nightscout.utils; +package info.nightscout.androidaps.utils; import org.slf4j.Logger; diff --git a/app/src/main/java/info/nightscout/utils/Round.java b/app/src/main/java/info/nightscout/androidaps/utils/Round.java similarity index 92% rename from app/src/main/java/info/nightscout/utils/Round.java rename to app/src/main/java/info/nightscout/androidaps/utils/Round.java index 26a4d5abce..ba7f7e3f86 100644 --- a/app/src/main/java/info/nightscout/utils/Round.java +++ b/app/src/main/java/info/nightscout/androidaps/utils/Round.java @@ -1,4 +1,4 @@ -package info.nightscout.utils; +package info.nightscout.androidaps.utils; /** * Created by mike on 20.06.2016. diff --git a/app/src/main/java/info/nightscout/utils/SP.java b/app/src/main/java/info/nightscout/androidaps/utils/SP.java similarity index 90% rename from app/src/main/java/info/nightscout/utils/SP.java rename to app/src/main/java/info/nightscout/androidaps/utils/SP.java index d5a40e19f5..1b46642751 100644 --- a/app/src/main/java/info/nightscout/utils/SP.java +++ b/app/src/main/java/info/nightscout/androidaps/utils/SP.java @@ -1,4 +1,4 @@ -package info.nightscout.utils; +package info.nightscout.androidaps.utils; import android.content.SharedPreferences; import android.preference.PreferenceManager; @@ -96,6 +96,12 @@ public class SP { editor.apply(); } + static public void putDouble(String key, double value) { + SharedPreferences.Editor editor = sharedPreferences.edit(); + editor.putString(key, Double.toString(value)); + editor.apply(); + } + static public void putLong(String key, long value) { SharedPreferences.Editor editor = sharedPreferences.edit(); editor.putLong(key, value); @@ -120,6 +126,13 @@ public class SP { editor.apply(); } + static public void incInt(int resourceID) { + SharedPreferences.Editor editor = sharedPreferences.edit(); + int value = SP.getInt(resourceID, 0) + 1; + editor.putInt(MainApp.gs(resourceID), value); + editor.apply(); + } + static public void putString(int resourceID, String value) { SharedPreferences.Editor editor = sharedPreferences.edit(); editor.putString(MainApp.gs(resourceID), value); diff --git a/app/src/main/java/info/nightscout/utils/SafeParse.java b/app/src/main/java/info/nightscout/androidaps/utils/SafeParse.java similarity index 97% rename from app/src/main/java/info/nightscout/utils/SafeParse.java rename to app/src/main/java/info/nightscout/androidaps/utils/SafeParse.java index 7d6d890b0e..5ee2a66177 100644 --- a/app/src/main/java/info/nightscout/utils/SafeParse.java +++ b/app/src/main/java/info/nightscout/androidaps/utils/SafeParse.java @@ -1,4 +1,4 @@ -package info.nightscout.utils; +package info.nightscout.androidaps.utils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/utils/SetWarnColor.java b/app/src/main/java/info/nightscout/androidaps/utils/SetWarnColor.java similarity index 95% rename from app/src/main/java/info/nightscout/utils/SetWarnColor.java rename to app/src/main/java/info/nightscout/androidaps/utils/SetWarnColor.java index a3a23695c7..e22197d83f 100644 --- a/app/src/main/java/info/nightscout/utils/SetWarnColor.java +++ b/app/src/main/java/info/nightscout/androidaps/utils/SetWarnColor.java @@ -1,4 +1,4 @@ -package info.nightscout.utils; +package info.nightscout.androidaps.utils; import android.graphics.Color; import android.widget.TextView; diff --git a/app/src/main/java/info/nightscout/utils/SingleClickButton.java b/app/src/main/java/info/nightscout/androidaps/utils/SingleClickButton.java similarity index 92% rename from app/src/main/java/info/nightscout/utils/SingleClickButton.java rename to app/src/main/java/info/nightscout/androidaps/utils/SingleClickButton.java index ef0d4d3aec..74500ebdbc 100644 --- a/app/src/main/java/info/nightscout/utils/SingleClickButton.java +++ b/app/src/main/java/info/nightscout/androidaps/utils/SingleClickButton.java @@ -1,9 +1,9 @@ -package info.nightscout.utils; +package info.nightscout.androidaps.utils; import android.app.Activity; import android.content.Context; import android.os.SystemClock; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import android.util.AttributeSet; import android.view.View; @@ -14,7 +14,7 @@ import org.slf4j.LoggerFactory; * Created by mike on 22.12.2017. */ -public class SingleClickButton extends android.support.v7.widget.AppCompatButton implements View.OnClickListener { +public class SingleClickButton extends androidx.appcompat.widget.AppCompatButton implements View.OnClickListener { private static Logger log = LoggerFactory.getLogger(SingleClickButton.class); Context context; diff --git a/app/src/main/java/info/nightscout/androidaps/utils/SntpClient.java b/app/src/main/java/info/nightscout/androidaps/utils/SntpClient.java new file mode 100644 index 0000000000..fcee3638b9 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/utils/SntpClient.java @@ -0,0 +1,227 @@ +package info.nightscout.androidaps.utils; +/* + * Copyright (C) 2008 The Android Open Source Project + * + * 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. + */ + +import android.os.SystemClock; +import android.util.Log; + +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetAddress; + +/** + * {@hide} + *

+ * Simple SNTP client class for retrieving network time. + *

+ * Sample usage: + *

SntpClient client = new SntpClient();
+ * if (client.requestTime("time.foo.com")) {
+ *     long now = client.getNtpTime() + SystemClock.elapsedRealtime() - client.getNtpTimeReference();
+ * }
+ * 
+ */ +public class SntpClient { + private static final String TAG = "SntpClient"; + + //private static final int REFERENCE_TIME_OFFSET = 16; + private static final int ORIGINATE_TIME_OFFSET = 24; + private static final int RECEIVE_TIME_OFFSET = 32; + private static final int TRANSMIT_TIME_OFFSET = 40; + private static final int NTP_PACKET_SIZE = 48; + + private static final int NTP_PORT = 123; + private static final int NTP_MODE_CLIENT = 3; + private static final int NTP_VERSION = 3; + + // Number of seconds between Jan 1, 1900 and Jan 1, 1970 + // 70 years plus 17 leap days + private static final long OFFSET_1900_TO_1970 = ((365L * 70L) + 17L) * 24L * 60L * 60L; + + // system time computed from NTP server response + private static long mNtpTime; + + // value of SystemClock.elapsedRealtime() corresponding to mNtpTime + private static long mNtpTimeReference; + + // round trip time in milliseconds + private static long mRoundTripTime; + + public static abstract class Callback implements Runnable { + public boolean networkConnected = false; + public boolean success = false; + public long time = 0; + } + + public static synchronized void ntpTime(final Callback callback, boolean isConnected) { + callback.networkConnected = isConnected; + if (callback.networkConnected) { + new Thread(() -> doNtpTime(callback)).start(); + } else { + callback.run(); + } + } + + static void doNtpTime(final Callback callback) { + callback.success = requestTime("time.google.com", 5000); + callback.time = getNtpTime() + SystemClock.elapsedRealtime() - getNtpTimeReference(); + callback.run(); + } + + /** + * Sends an SNTP request to the given host and processes the response. + * + * @param host host name of the server. + * @param timeout network timeout in milliseconds. + * @return true if the transaction was successful. + */ + private static synchronized boolean requestTime(String host, int timeout) { + try { + DatagramSocket socket = new DatagramSocket(); + socket.setSoTimeout(timeout); + InetAddress address = InetAddress.getByName(host); + byte[] buffer = new byte[NTP_PACKET_SIZE]; + DatagramPacket request = new DatagramPacket(buffer, buffer.length, address, NTP_PORT); + + // set mode = 3 (client) and version = 3 + // mode is in low 3 bits of first byte + // version is in bits 3-5 of first byte + buffer[0] = NTP_MODE_CLIENT | (NTP_VERSION << 3); + + // get current time and write it to the request packet + long requestTime = System.currentTimeMillis(); + long requestTicks = SystemClock.elapsedRealtime(); + writeTimeStamp(buffer, TRANSMIT_TIME_OFFSET, requestTime); + + socket.send(request); + + // read the response + DatagramPacket response = new DatagramPacket(buffer, buffer.length); + socket.receive(response); + long responseTicks = SystemClock.elapsedRealtime(); + long responseTime = requestTime + (responseTicks - requestTicks); + socket.close(); + + // extract the results + long originateTime = readTimeStamp(buffer, ORIGINATE_TIME_OFFSET); + long receiveTime = readTimeStamp(buffer, RECEIVE_TIME_OFFSET); + long transmitTime = readTimeStamp(buffer, TRANSMIT_TIME_OFFSET); + long roundTripTime = responseTicks - requestTicks - (transmitTime - receiveTime); + // receiveTime = originateTime + transit + skew + // responseTime = transmitTime + transit - skew + // clockOffset = ((receiveTime - originateTime) + (transmitTime - responseTime))/2 + // = ((originateTime + transit + skew - originateTime) + + // (transmitTime - (transmitTime + transit - skew)))/2 + // = ((transit + skew) + (transmitTime - transmitTime - transit + skew))/2 + // = (transit + skew - transit + skew)/2 + // = (2 * skew)/2 = skew + long clockOffset = ((receiveTime - originateTime) + (transmitTime - responseTime)) / 2; + // if (Config.LOGD) Log.d(TAG, "round trip: " + roundTripTime + " ms"); + // if (Config.LOGD) Log.d(TAG, "clock offset: " + clockOffset + " ms"); + + // save our results - use the times on this side of the network latency + // (response rather than request time) + mNtpTime = responseTime + clockOffset; + mNtpTimeReference = responseTicks; + mRoundTripTime = roundTripTime; + } catch (Exception e) { + Log.d(TAG, "request time failed: " + e); + return false; + } + + return true; + } + + /** + * Returns the time computed from the NTP transaction. + * + * @return time value computed from NTP server response. + */ + private static long getNtpTime() { + return mNtpTime; + } + + /** + * Returns the reference clock value (value of SystemClock.elapsedRealtime()) + * corresponding to the NTP time. + * + * @return reference clock corresponding to the NTP time. + */ + private static long getNtpTimeReference() { + return mNtpTimeReference; + } + + /** + * Returns the round trip time of the NTP transaction + * + * @return round trip time in milliseconds. + */ + public long getRoundTripTime() { + return mRoundTripTime; + } + + /** + * Reads an unsigned 32 bit big endian number from the given offset in the buffer. + */ + private static long read32(byte[] buffer, int offset) { + byte b0 = buffer[offset]; + byte b1 = buffer[offset + 1]; + byte b2 = buffer[offset + 2]; + byte b3 = buffer[offset + 3]; + + // convert signed bytes to unsigned values + int i0 = ((b0 & 0x80) == 0x80 ? (b0 & 0x7F) + 0x80 : b0); + int i1 = ((b1 & 0x80) == 0x80 ? (b1 & 0x7F) + 0x80 : b1); + int i2 = ((b2 & 0x80) == 0x80 ? (b2 & 0x7F) + 0x80 : b2); + int i3 = ((b3 & 0x80) == 0x80 ? (b3 & 0x7F) + 0x80 : b3); + + return ((long) i0 << 24) + ((long) i1 << 16) + ((long) i2 << 8) + (long) i3; + } + + /** + * Reads the NTP time stamp at the given offset in the buffer and returns + * it as a system time (milliseconds since January 1, 1970). + */ + private static long readTimeStamp(byte[] buffer, int offset) { + long seconds = read32(buffer, offset); + long fraction = read32(buffer, offset + 4); + return ((seconds - OFFSET_1900_TO_1970) * 1000) + ((fraction * 1000L) / 0x100000000L); + } + + /** + * Writes system time (milliseconds since January 1, 1970) as an NTP time stamp + * at the given offset in the buffer. + */ + private static void writeTimeStamp(byte[] buffer, int offset, long time) { + long seconds = time / 1000L; + long milliseconds = time - seconds * 1000L; + seconds += OFFSET_1900_TO_1970; + + // write seconds in big endian format + buffer[offset++] = (byte) (seconds >> 24); + buffer[offset++] = (byte) (seconds >> 16); + buffer[offset++] = (byte) (seconds >> 8); + buffer[offset++] = (byte) (seconds >> 0); + + long fraction = milliseconds * 0x100000000L / 1000L; + // write fraction in big endian format + buffer[offset++] = (byte) (fraction >> 24); + buffer[offset++] = (byte) (fraction >> 16); + buffer[offset++] = (byte) (fraction >> 8); + // low order bits should be random data + buffer[offset++] = (byte) (Math.random() * 255.0); + } +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/utils/SpinnerHelper.java b/app/src/main/java/info/nightscout/androidaps/utils/SpinnerHelper.java similarity index 99% rename from app/src/main/java/info/nightscout/utils/SpinnerHelper.java rename to app/src/main/java/info/nightscout/androidaps/utils/SpinnerHelper.java index 84315825f5..a45fcd5a57 100644 --- a/app/src/main/java/info/nightscout/utils/SpinnerHelper.java +++ b/app/src/main/java/info/nightscout/androidaps/utils/SpinnerHelper.java @@ -1,4 +1,4 @@ -package info.nightscout.utils; +package info.nightscout.androidaps.utils; import android.view.MotionEvent; import android.view.View; diff --git a/app/src/main/java/info/nightscout/utils/StringUtils.java b/app/src/main/java/info/nightscout/androidaps/utils/StringUtils.java similarity index 56% rename from app/src/main/java/info/nightscout/utils/StringUtils.java rename to app/src/main/java/info/nightscout/androidaps/utils/StringUtils.java index de16f7964e..74e8da7c9d 100644 --- a/app/src/main/java/info/nightscout/utils/StringUtils.java +++ b/app/src/main/java/info/nightscout/androidaps/utils/StringUtils.java @@ -1,4 +1,7 @@ -package info.nightscout.utils; +package info.nightscout.androidaps.utils; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; /** * class contains useful String functions @@ -17,4 +20,12 @@ public class StringUtils { return string; } + + public static boolean emptyString(final String str) { + return str == null || str.length() == 0; + } + + public static String formatInsulin(double insulin) { + return String.format(MainApp.gs(R.string.formatinsulinunits), insulin); + } } diff --git a/app/src/main/java/info/nightscout/utils/T.java b/app/src/main/java/info/nightscout/androidaps/utils/T.java similarity index 87% rename from app/src/main/java/info/nightscout/utils/T.java rename to app/src/main/java/info/nightscout/androidaps/utils/T.java index 99f4e573c3..5671f0725c 100644 --- a/app/src/main/java/info/nightscout/utils/T.java +++ b/app/src/main/java/info/nightscout/androidaps/utils/T.java @@ -1,4 +1,4 @@ -package info.nightscout.utils; +package info.nightscout.androidaps.utils; /** * Created by mike on 26.03.2018. @@ -43,6 +43,12 @@ public class T { return t; } + public static T months(long month) { + T t = new T(); + t.time = month * 31 * 24 * 60 * 60 * 1000L; + return t; + } + public long msecs() { return time; } diff --git a/app/src/main/java/info/nightscout/utils/TimeListEdit.java b/app/src/main/java/info/nightscout/androidaps/utils/TimeListEdit.java similarity index 69% rename from app/src/main/java/info/nightscout/utils/TimeListEdit.java rename to app/src/main/java/info/nightscout/androidaps/utils/TimeListEdit.java index ec03734b18..be8b89dff4 100644 --- a/app/src/main/java/info/nightscout/utils/TimeListEdit.java +++ b/app/src/main/java/info/nightscout/androidaps/utils/TimeListEdit.java @@ -1,9 +1,6 @@ -package info.nightscout.utils; +package info.nightscout.androidaps.utils; import android.content.Context; -import android.os.Handler; -import android.support.v4.content.ContextCompat; -import android.support.v4.widget.TextViewCompat; import android.text.Editable; import android.text.TextWatcher; import android.view.Gravity; @@ -15,6 +12,10 @@ import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; +import androidx.annotation.NonNull; +import androidx.core.content.ContextCompat; +import androidx.core.widget.TextViewCompat; + import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -24,6 +25,7 @@ import org.slf4j.LoggerFactory; import java.text.DecimalFormat; import java.text.NumberFormat; import java.util.ArrayList; +import java.util.List; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; @@ -77,8 +79,8 @@ public class TimeListEdit { } private void buildView() { - layout = (LinearLayout) view.findViewById(resLayoutId); - layout.removeAllViews(); + layout = view.findViewById(resLayoutId); + layout.removeAllViewsInLayout(); textlabel = new TextView(context); textlabel.setText(label); @@ -96,72 +98,63 @@ public class TimeListEdit { } // last "plus" to append new interval + float factor = layout.getContext().getResources().getDisplayMetrics().density; finalAdd = new ImageView(context); finalAdd.setImageResource(R.drawable.add); - LinearLayout.LayoutParams illp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT); + LinearLayout.LayoutParams illp = new LinearLayout.LayoutParams((int) (35d * factor), (int) (35 * factor)); illp.setMargins(0, 25, 0, 25); // llp.setMargins(left, top, right, bottom); illp.gravity = Gravity.CENTER; layout.addView(finalAdd); finalAdd.setLayoutParams(illp); - finalAdd.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - addItem(itemsCount(), itemsCount() > 0 ? secondFromMidnight(itemsCount() - 1) + ONEHOURINSECONDS : 0, 0, 0); - callSave(); - log(); - fillView(); - } + finalAdd.setOnClickListener(view -> { + addItem(itemsCount(), itemsCount() > 0 ? secondFromMidnight(itemsCount() - 1) + ONEHOURINSECONDS : 0, 0, 0); + callSave(); + log(); + fillView(); }); fillView(); } - private void inflateRow(int i) { + private void inflateRow(final int position) { LayoutInflater inflater = LayoutInflater.from(context); - View childview = intervals[i] = inflater.inflate(R.layout.timelistedit_element, layout, false); - spinners[i] = new SpinnerHelper(childview.findViewById(R.id.timelistedit_time)); - numberPickers1[i] = (NumberPicker) childview.findViewById(R.id.timelistedit_edit1); - numberPickers2[i] = (NumberPicker) childview.findViewById(R.id.timelistedit_edit2); - addButtons[i] = (ImageView) childview.findViewById(R.id.timelistedit_add); - removeButtons[i] = (ImageView) childview.findViewById(R.id.timelistedit_remove); + View childView = intervals[position] = inflater.inflate(R.layout.timelistedit_element, layout, false); + spinners[position] = new SpinnerHelper(childView.findViewById(R.id.timelistedit_time)); + numberPickers1[position] = childView.findViewById(R.id.timelistedit_edit1); + numberPickers2[position] = childView.findViewById(R.id.timelistedit_edit2); + addButtons[position] = childView.findViewById(R.id.timelistedit_add); + removeButtons[position] = childView.findViewById(R.id.timelistedit_remove); - final int fixedPos = i; - addButtons[i].setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - int seconds = secondFromMidnight(fixedPos); - addItem(fixedPos, seconds, 0, 0); - // for here for the rest of values - for (int i = fixedPos + 1; i < itemsCount(); i++) { - if (secondFromMidnight(i - 1) >= secondFromMidnight(i)) { - editItem(i, secondFromMidnight(i - 1) + ONEHOURINSECONDS, value1(i), value2(i)); - } + addButtons[position].setOnClickListener(view -> { + int seconds = secondFromMidnight(position); + addItem(position, seconds, 0, 0); + // for here for the rest of values + for (int i = position + 1; i < itemsCount(); i++) { + if (secondFromMidnight(i - 1) >= secondFromMidnight(i)) { + editItem(i, secondFromMidnight(i - 1) + ONEHOURINSECONDS, value1(i), value2(i)); } - while (itemsCount() > 24 || secondFromMidnight(itemsCount() - 1) > 23 * ONEHOURINSECONDS) - removeItem(itemsCount() - 1); - callSave(); - log(); - fillView(); } + while (itemsCount() > 24 || secondFromMidnight(itemsCount() - 1) > 23 * ONEHOURINSECONDS) + removeItem(itemsCount() - 1); + callSave(); + log(); + fillView(); }); - removeButtons[i].setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - removeItem(fixedPos); - callSave(); - log(); - fillView(); - } + removeButtons[position].setOnClickListener(view -> { + removeItem(position); + callSave(); + log(); + fillView(); }); - spinners[i].setOnItemSelectedListener( + spinners[position].setOnItemSelectedListener( new AdapterView.OnItemSelectedListener() { @Override - public void onItemSelected(AdapterView parent, View view, int position, long id) { - int seconds = DateUtil.toSeconds(spinners[fixedPos].getSelectedItem().toString()); - editItem(fixedPos, seconds, value1(fixedPos), value2(fixedPos)); + public void onItemSelected(AdapterView parent, View view, int selected, long id) { + int seconds = ((SpinnerAdapter) spinners[position].getAdapter()).valueForPosition(selected); + editItem(position, seconds, value1(position), value2(position)); log(); callSave(); fillView(); @@ -173,30 +166,10 @@ public class TimeListEdit { } ); - numberPickers1[i].setTextWatcher(new TextWatcher() { - @Override - public void afterTextChanged(Editable s) { - editItem(fixedPos, secondFromMidnight(fixedPos), SafeParse.stringToDouble(numberPickers1[fixedPos].getText()), value2(fixedPos)); - callSave(); - log(); - } - - @Override - public void beforeTextChanged(CharSequence s, int start, - int count, int after) { - } - - @Override - public void onTextChanged(CharSequence s, int start, - int before, int count) { - } - }); - - - numberPickers2[i].setTextWatcher(new TextWatcher() { + numberPickers1[position].setTextWatcher(new TextWatcher() { @Override public void afterTextChanged(Editable s) { - editItem(fixedPos, secondFromMidnight(fixedPos), value1(fixedPos), SafeParse.stringToDouble(numberPickers2[fixedPos].getText())); + editItem(position, secondFromMidnight(position), SafeParse.stringToDouble(numberPickers1[position].getText()), value2(position)); callSave(); log(); } @@ -212,7 +185,27 @@ public class TimeListEdit { } }); - layout.addView(childview); + + numberPickers2[position].setTextWatcher(new TextWatcher() { + @Override + public void afterTextChanged(Editable s) { + editItem(position, secondFromMidnight(position), value1(position), SafeParse.stringToDouble(numberPickers2[position].getText())); + callSave(); + log(); + } + + @Override + public void beforeTextChanged(CharSequence s, int start, + int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, + int before, int count) { + } + }); + + layout.addView(childView); } private void fillView() { @@ -220,7 +213,7 @@ public class TimeListEdit { if (i < itemsCount()) { intervals[i].setVisibility(View.VISIBLE); buildInterval(i); - } else if (i <= inflatedUntil){ + } else if (i <= inflatedUntil) { intervals[i].setVisibility(View.GONE); } } @@ -232,9 +225,8 @@ public class TimeListEdit { } } - private View buildInterval(int i) { + private void buildInterval(int i) { SpinnerHelper timeSpinner = spinners[i]; - View childview = intervals[i]; final NumberPicker editText1 = numberPickers1[i]; final NumberPicker editText2 = numberPickers2[i]; @@ -244,8 +236,8 @@ public class TimeListEdit { if (i == 0) next = ONEHOURINSECONDS; fillSpinner(timeSpinner, secondFromMidnight(i), previous, next); - editText1.setParams(value1(i), min, max, step, formatter, false); - editText2.setParams(value2(i), min, max, step, formatter, false); + editText1.setParams(value1(i), min, max, step, formatter, false,null); + editText2.setParams(value2(i), min, max, step, formatter, false, null); if (data2 == null) { editText2.setVisibility(View.GONE); @@ -263,29 +255,38 @@ public class TimeListEdit { addButtons[i].setVisibility(View.VISIBLE); } - return childview; + } + + class SpinnerAdapter extends ArrayAdapter { + List values; + + SpinnerAdapter(@NonNull Context context, int resource, final @NonNull List objects, final @NonNull List values) { + super(context, resource, objects); + this.values = values; + } + + int valueForPosition(int position) { + return values.get(position); + } } private void fillSpinner(final SpinnerHelper spinner, int secondsFromMidnight, int previous, int next) { int posInList = 0; ArrayList timeList = new ArrayList<>(); + ArrayList timeListValues = new ArrayList<>(); int pos = 0; for (int t = previous + ONEHOURINSECONDS; t < next; t += ONEHOURINSECONDS) { timeList.add(DateUtil.timeStringFromSeconds(t)); + timeListValues.add(t); if (secondsFromMidnight == t) posInList = pos; pos++; } - final ArrayAdapter adapter = new ArrayAdapter<>(context, - R.layout.spinner_centered, timeList); + final SpinnerAdapter adapter = new SpinnerAdapter(context, + R.layout.spinner_centered, timeList, timeListValues); spinner.setAdapter(adapter); - final int finalPosInList = posInList; - new Handler().postDelayed(new Runnable() { - public void run() { - spinner.setSelection(finalPosInList, false); - adapter.notifyDataSetChanged(); - } - }, 100); + spinner.setSelection(posInList, false); + adapter.notifyDataSetChanged(); } private int itemsCount() { @@ -350,7 +351,7 @@ public class TimeListEdit { data1.put(index, newObject1); if (data2 != null) { JSONObject newObject2 = new JSONObject(); - newObject1.put("time", time); + newObject2.put("time", time); newObject2.put("timeAsSeconds", timeAsSeconds); newObject2.put("value", value2); data2.put(index, newObject2); @@ -362,7 +363,7 @@ public class TimeListEdit { } private void addItem(int index, int timeAsSeconds, double value1, double value2) { - if(itemsCount()>inflatedUntil) { + if (itemsCount() > inflatedUntil) { layout.removeView(finalAdd); inflateRow(++inflatedUntil); layout.addView(finalAdd); @@ -389,10 +390,8 @@ public class TimeListEdit { } private void log() { - if (log.isDebugEnabled()) { - for (int i = 0; i < data1.length(); i++) { - log.debug(i + ": @" + DateUtil.timeStringFromSeconds(secondFromMidnight(i)) + " " + value1(i) + (data2 != null ? " " + value2(i) : "")); - } + for (int i = 0; i < data1.length(); i++) { + log.debug(i + ": @" + DateUtil.timeStringFromSeconds(secondFromMidnight(i)) + " " + value1(i) + (data2 != null ? " " + value2(i) : "")); } } @@ -400,9 +399,9 @@ public class TimeListEdit { if (save != null) save.run(); } - public void updateLabel(String txt){ + public void updateLabel(String txt) { this.label = txt; - if(textlabel!=null) + if (textlabel != null) textlabel.setText(txt); } } diff --git a/app/src/main/java/info/nightscout/androidaps/utils/ToastUtils.java b/app/src/main/java/info/nightscout/androidaps/utils/ToastUtils.java new file mode 100644 index 0000000000..fe596d8f08 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/utils/ToastUtils.java @@ -0,0 +1,39 @@ +package info.nightscout.androidaps.utils; + +import android.content.Context; +import android.media.MediaPlayer; +import android.os.Handler; +import android.os.Looper; +import android.widget.Toast; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; + + +public class ToastUtils { + public static void showToastInUiThread(final Context ctx, final int stringId) { + showToastInUiThread(ctx, MainApp.gs(stringId)); + } + + public static void showToastInUiThread(final Context ctx, final String string) { + Handler mainThread = new Handler(Looper.getMainLooper()); + mainThread.post(() -> Toast.makeText(ctx, string, Toast.LENGTH_SHORT).show()); + } + + public static void showToastInUiThread(final Context ctx, + final String string, int soundID) { + + showToastInUiThread(ctx, string); + playSound(ctx, soundID); + Notification notification = new Notification(Notification.TOAST_ALARM, string, Notification.URGENT); + RxBus.INSTANCE.send(new EventNewNotification(notification)); + } + + private static void playSound(final Context ctx, final int soundID) { + final MediaPlayer soundMP = MediaPlayer.create(ctx, soundID); + soundMP.start(); + soundMP.setOnCompletionListener(MediaPlayer::release); + } +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/utils/Translator.java b/app/src/main/java/info/nightscout/androidaps/utils/Translator.java similarity index 94% rename from app/src/main/java/info/nightscout/utils/Translator.java rename to app/src/main/java/info/nightscout/androidaps/utils/Translator.java index 98fdd32779..e25c083a7b 100644 --- a/app/src/main/java/info/nightscout/utils/Translator.java +++ b/app/src/main/java/info/nightscout/androidaps/utils/Translator.java @@ -1,4 +1,4 @@ -package info.nightscout.utils; +package info.nightscout.androidaps.utils; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; @@ -33,6 +33,8 @@ public class Translator { return MainApp.gs(R.string.careportal_exercise); case "Site Change": return MainApp.gs(R.string.careportal_pumpsitechange); + case "Pump Battery Change": + return MainApp.gs(R.string.careportal_pumpbatterychange); case "Sensor Start": return MainApp.gs(R.string.careportal_cgmsensorstart); case "Sensor Change": diff --git a/app/src/main/java/info/nightscout/utils/XdripCalibrations.java b/app/src/main/java/info/nightscout/androidaps/utils/XdripCalibrations.java similarity index 94% rename from app/src/main/java/info/nightscout/utils/XdripCalibrations.java rename to app/src/main/java/info/nightscout/androidaps/utils/XdripCalibrations.java index 18c066b1da..f7b8761823 100644 --- a/app/src/main/java/info/nightscout/utils/XdripCalibrations.java +++ b/app/src/main/java/info/nightscout/androidaps/utils/XdripCalibrations.java @@ -1,11 +1,11 @@ -package info.nightscout.utils; +package info.nightscout.androidaps.utils; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.ResolveInfo; import android.os.Bundle; -import android.support.v7.app.AlertDialog; +import androidx.appcompat.app.AlertDialog; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -15,7 +15,7 @@ import java.util.List; import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions; +import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; import info.nightscout.androidaps.services.Intents; /** diff --git a/app/src/main/java/info/nightscout/utils/AndroidPermission.java b/app/src/main/java/info/nightscout/utils/AndroidPermission.java deleted file mode 100644 index c2a572ff4f..0000000000 --- a/app/src/main/java/info/nightscout/utils/AndroidPermission.java +++ /dev/null @@ -1,105 +0,0 @@ -package info.nightscout.utils; - -import android.Manifest; -import android.app.Activity; -import android.content.Context; -import android.content.pm.PackageManager; -import android.os.Build; -import android.support.v4.app.ActivityCompat; -import android.support.v4.content.ContextCompat; - -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; -import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; -import info.nightscout.androidaps.plugins.Overview.notifications.Notification; -import info.nightscout.androidaps.plugins.Overview.notifications.NotificationWithAction; - -public class AndroidPermission { - - public static final int CASE_STORAGE = 0x1; - public static final int CASE_SMS = 0x2; - public static final int CASE_LOCATION = 0x3; - public static final int CASE_BATTERY = 0x4; - public static final int CASE_PHONESTATE = 0x5; - - public static void askForPermission(Activity activity, String[] permission, Integer requestCode) { - boolean test = false; - for (int i = 0; i < permission.length; i++) { - test = test || (ContextCompat.checkSelfPermission(activity, permission[i]) != PackageManager.PERMISSION_GRANTED); - } - if (test) { - ActivityCompat.requestPermissions(activity, permission, requestCode); - } - } - - public static void askForPermission(Activity activity, String permission, Integer requestCode) { - String[] permissions = {permission}; - - if (ContextCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) - ActivityCompat.requestPermissions(activity, permissions, requestCode); - } - - public static boolean checkForPermission(Context context, String permission) { - return ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED; - } - - public static synchronized void notifyForSMSPermissions(Activity activity) { - if (SP.getBoolean(R.string.key_smscommunicator_remotecommandsallowed, false)) { - if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) { - if (!checkForPermission(activity, Manifest.permission.RECEIVE_SMS)) { - NotificationWithAction notification = new NotificationWithAction(Notification.PERMISSION_SMS, MainApp.gs(R.string.smscommunicator_missingsmspermission), Notification.URGENT); - notification.action(MainApp.gs(R.string.request), () -> AndroidPermission.askForPermission(activity, new String[]{Manifest.permission.RECEIVE_SMS, - Manifest.permission.SEND_SMS, - Manifest.permission.RECEIVE_MMS}, AndroidPermission.CASE_SMS)); - MainApp.bus().post(new EventNewNotification(notification)); - } else - MainApp.bus().post(new EventDismissNotification(Notification.PERMISSION_SMS)); - } - // Following is a bug in Android 8 - if (Build.VERSION.SDK_INT == Build.VERSION_CODES.O) { - if (!checkForPermission(activity, Manifest.permission.READ_PHONE_STATE)) { - NotificationWithAction notification = new NotificationWithAction(Notification.PERMISSION_PHONESTATE, MainApp.gs(R.string.smscommunicator_missingphonestatepermission), Notification.URGENT); - notification.action(MainApp.gs(R.string.request), () -> - AndroidPermission.askForPermission(activity, new String[]{Manifest.permission.READ_PHONE_STATE}, AndroidPermission.CASE_PHONESTATE)); - MainApp.bus().post(new EventNewNotification(notification)); - } else - MainApp.bus().post(new EventDismissNotification(Notification.PERMISSION_PHONESTATE)); - } - } - } - - public static synchronized void notifyForBatteryOptimizationPermission(Activity activity) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - if (!checkForPermission(activity, Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)) { - NotificationWithAction notification = new NotificationWithAction(Notification.PERMISSION_BATTERY, String.format(MainApp.gs(R.string.needwhitelisting), MainApp.gs(R.string.app_name)), Notification.URGENT); - notification.action(MainApp.gs(R.string.request), () -> AndroidPermission.askForPermission(activity, new String[]{Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS}, AndroidPermission.CASE_BATTERY)); - MainApp.bus().post(new EventNewNotification(notification)); - } else - MainApp.bus().post(new EventDismissNotification(Notification.PERMISSION_BATTERY)); - } - } - - public static synchronized void notifyForStoragePermission(Activity activity) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - if (!checkForPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE)) { - NotificationWithAction notification = new NotificationWithAction(Notification.PERMISSION_STORAGE, MainApp.gs(R.string.needstoragepermission), Notification.URGENT); - notification.action(MainApp.gs(R.string.request), () -> AndroidPermission.askForPermission(activity, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, - Manifest.permission.WRITE_EXTERNAL_STORAGE}, AndroidPermission.CASE_STORAGE)); - MainApp.bus().post(new EventNewNotification(notification)); - } else - MainApp.bus().post(new EventDismissNotification(Notification.PERMISSION_STORAGE)); - } - } - - public static synchronized void notifyForLocationPermissions(Activity activity) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - if (!checkForPermission(activity, Manifest.permission.ACCESS_FINE_LOCATION)) { - NotificationWithAction notification = new NotificationWithAction(Notification.PERMISSION_LOCATION, MainApp.gs(R.string.needlocationpermission), Notification.URGENT); - notification.action(MainApp.gs(R.string.request), () -> AndroidPermission.askForPermission(activity, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, AndroidPermission.CASE_LOCATION)); - MainApp.bus().post(new EventNewNotification(notification)); - } else - MainApp.bus().post(new EventDismissNotification(Notification.PERMISSION_LOCATION)); - } - } -} diff --git a/app/src/main/java/info/nightscout/utils/BolusWizard.java b/app/src/main/java/info/nightscout/utils/BolusWizard.java deleted file mode 100644 index d20827ce9e..0000000000 --- a/app/src/main/java/info/nightscout/utils/BolusWizard.java +++ /dev/null @@ -1,183 +0,0 @@ -package info.nightscout.utils; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import info.nightscout.androidaps.data.GlucoseStatus; -import info.nightscout.androidaps.data.IobTotal; -import info.nightscout.androidaps.data.Profile; -import info.nightscout.androidaps.db.TempTarget; -import info.nightscout.androidaps.interfaces.TreatmentsInterface; -import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; - -/** - * Created by mike on 11.10.2016. - */ - -public class BolusWizard { - private Logger log = LoggerFactory.getLogger(L.CORE); - // Inputs - private Profile specificProfile = null; - private TempTarget tempTarget; - public Integer carbs = 0; - private Double bg = 0d; - private Double cob = 0d; - private Double correction; - private Double percentageCorrection; - private Boolean includeBolusIOB = true; - private Boolean includeBasalIOB = true; - public Boolean superBolus = false; - private Boolean trend = false; - - // Intermediate - public double sens = 0d; - public double ic = 0d; - - public GlucoseStatus glucoseStatus; - - public double targetBGLow = 0d; - public double targetBGHigh = 0d; - public double bgDiff = 0d; - - public double insulinFromBG = 0d; - public double insulinFromCarbs = 0d; - public double insulingFromBolusIOB = 0d; - public double insulingFromBasalsIOB = 0d; - public double insulinFromCorrection = 0d; - public double insulinFromSuperBolus = 0d; - public double insulinFromCOB = 0d; - public double insulinFromTrend = 0d; - - // Result - public Double calculatedTotalInsulin = 0d; - public Double totalBeforePercentageAdjustment = 0d; - public Double carbsEquivalent = 0d; - - public Double doCalc(Profile specificProfile, TempTarget tempTarget, Integer carbs, Double cob, Double bg, Double correction, Boolean includeBolusIOB, Boolean includeBasalIOB, Boolean superBolus, Boolean trend) { - return doCalc(specificProfile, tempTarget, carbs, cob, bg, correction, 100d, includeBolusIOB, includeBasalIOB, superBolus, trend); - } - - public Double doCalc(Profile specificProfile, TempTarget tempTarget, Integer carbs, Double cob, Double bg, Double correction, double percentageCorrection, Boolean includeBolusIOB, Boolean includeBasalIOB, Boolean superBolus, Boolean trend) { - this.specificProfile = specificProfile; - this.tempTarget = tempTarget; - this.carbs = carbs; - this.bg = bg; - this.cob = cob; - this.correction = correction; - this.percentageCorrection = percentageCorrection; - this.includeBolusIOB = includeBolusIOB; - this.includeBasalIOB = includeBasalIOB; - this.superBolus = superBolus; - this.trend = trend; - - // Insulin from BG - sens = specificProfile.getIsf(); - targetBGLow = specificProfile.getTargetLow(); - targetBGHigh = specificProfile.getTargetHigh(); - if (tempTarget != null) { - targetBGLow = Profile.fromMgdlToUnits(tempTarget.low, specificProfile.getUnits()); - targetBGHigh = Profile.fromMgdlToUnits(tempTarget.high, specificProfile.getUnits()); - } - if (bg >= targetBGLow && bg <= targetBGHigh) { - bgDiff = 0d; - } else if (bg <= targetBGLow) { - bgDiff = bg - targetBGLow; - } else { - bgDiff = bg - targetBGHigh; - } - insulinFromBG = bg != 0d ? bgDiff / sens : 0d; - - // Insulin from 15 min trend - glucoseStatus = GlucoseStatus.getGlucoseStatusData(); - if (glucoseStatus != null && trend) { - insulinFromTrend = (Profile.fromMgdlToUnits(glucoseStatus.short_avgdelta, specificProfile.getUnits()) * 3) / sens; - } - - // Insuling from carbs - ic = specificProfile.getIc(); - insulinFromCarbs = carbs / ic; - insulinFromCOB = cob / ic; - - // Insulin from IOB - // IOB calculation - TreatmentsInterface treatments = TreatmentsPlugin.getPlugin(); - treatments.updateTotalIOBTreatments(); - IobTotal bolusIob = treatments.getLastCalculationTreatments().round(); - treatments.updateTotalIOBTempBasals(); - IobTotal basalIob = treatments.getLastCalculationTempBasals().round(); - - insulingFromBolusIOB = includeBolusIOB ? -bolusIob.iob : 0d; - insulingFromBasalsIOB = includeBasalIOB ? -basalIob.basaliob : 0d; - - // Insulin from correction - insulinFromCorrection = correction; - - // Insulin from superbolus for 2h. Get basal rate now and after 1h - if (superBolus) { - insulinFromSuperBolus = specificProfile.getBasal(); - long timeAfter1h = System.currentTimeMillis(); - timeAfter1h += T.hours(1).msecs(); - insulinFromSuperBolus += specificProfile.getBasal(timeAfter1h); - } - - // Total - calculatedTotalInsulin = insulinFromBG + insulinFromTrend + insulinFromCarbs + insulingFromBolusIOB + insulingFromBasalsIOB + insulinFromCorrection + insulinFromSuperBolus + insulinFromCOB; - - // Percentage adjustment - totalBeforePercentageAdjustment = calculatedTotalInsulin; - if (calculatedTotalInsulin > 0) { - calculatedTotalInsulin = calculatedTotalInsulin * percentageCorrection / 100d; - } - - if (calculatedTotalInsulin < 0) { - carbsEquivalent = -calculatedTotalInsulin * ic; - calculatedTotalInsulin = 0d; - } - - double bolusStep = ConfigBuilderPlugin.getPlugin().getActivePump().getPumpDescription().bolusStep; - calculatedTotalInsulin = Round.roundTo(calculatedTotalInsulin, bolusStep); - - log.debug(log()); - - return calculatedTotalInsulin; - } - - public String log() { - StringBuilder sb = new StringBuilder(); - - sb.append("TempTarget=").append(tempTarget != null ? tempTarget.toString() : "null").append("; "); - sb.append("Carbs=").append(carbs != null ? carbs : null).append("; "); - sb.append("Bg=").append(bg).append("; "); - sb.append("Cob=").append(cob).append("; "); - sb.append("Correction=").append(correction).append("; "); - sb.append("PercentageCorrection=").append(percentageCorrection).append("; "); - sb.append("IncludeBolusIOB=").append(includeBolusIOB).append("; "); - sb.append("IncludeBasalIOB=").append(includeBasalIOB).append("; "); - sb.append("Superbolus=").append(superBolus).append("; "); - sb.append("Trend=").append(trend).append("; "); - sb.append("Profile=").append(specificProfile != null && specificProfile.getData() != null ? specificProfile.getData().toString() : "null").append("; "); - sb.append("\n"); - - sb.append("targetBGLow=").append(targetBGLow).append("; "); - sb.append("targetBGHigh=").append(targetBGHigh).append("; "); - sb.append("bgDiff=").append(bgDiff).append("; "); - sb.append("insulinFromBG=").append(insulinFromBG).append("; "); - sb.append("insulinFromCarbs=").append(insulinFromCarbs).append("; "); - sb.append("insulingFromBolusIOB=").append(insulingFromBolusIOB).append("; "); - sb.append("insulingFromBasalsIOB=").append(insulingFromBasalsIOB).append("; "); - sb.append("insulinFromCorrection=").append(insulinFromCorrection).append("; "); - sb.append("insulinFromSuperBolus=").append(insulinFromSuperBolus).append("; "); - sb.append("insulinFromCOB=").append(insulinFromCOB).append("; "); - sb.append("insulinFromTrend=").append(insulinFromTrend).append("; "); - sb.append("\n"); - - - sb.append("calculatedTotalInsulin=").append(calculatedTotalInsulin).append("; "); - sb.append("totalBeforePercentageAdjustment=").append(totalBeforePercentageAdjustment).append("; "); - sb.append("carbsEquivalent=").append(carbsEquivalent).append("; "); - - return sb.toString(); - } -} diff --git a/app/src/main/java/info/nightscout/utils/FabricPrivacy.java b/app/src/main/java/info/nightscout/utils/FabricPrivacy.java deleted file mode 100644 index 572cd4dab4..0000000000 --- a/app/src/main/java/info/nightscout/utils/FabricPrivacy.java +++ /dev/null @@ -1,140 +0,0 @@ -package info.nightscout.utils; - -import com.crashlytics.android.Crashlytics; -import com.crashlytics.android.answers.Answers; -import com.crashlytics.android.answers.CustomEvent; - -import info.nightscout.androidaps.BuildConfig; -import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.interfaces.PluginBase; - -import java.util.Date; - -/** - * Created by jamorham on 21/02/2018. - *

- * Some users do not wish to be tracked, Fabric Answers and Crashlytics do not provide an easy way - * to disable them and make calls from a potentially invalid singleton reference. This wrapper - * emulates the methods but ignores the request if the instance is null or invalid. - */ - -public class FabricPrivacy { - - private static final String TAG = "FabricPrivacy"; - private static volatile FabricPrivacy instance; - - - public static FabricPrivacy getInstance() { - if (instance == null) { - initSelf(); - } - return instance; - } - - private static synchronized void initSelf() { - if (instance == null) { - instance = new FabricPrivacy(); - } - } - - // Crashlytics logException - public static void logException(Throwable throwable) { - try { - final Crashlytics crashlytics = Crashlytics.getInstance(); - crashlytics.core.logException(throwable); - } catch (NullPointerException | IllegalStateException e) { - android.util.Log.d(TAG, "Ignoring opted out non-initialized log: " + throwable); - } - } - - // Crashlytics log - public static void log(String msg) { - try { - final Crashlytics crashlytics = Crashlytics.getInstance(); - crashlytics.core.log(msg); - } catch (NullPointerException | IllegalStateException e) { - android.util.Log.d(TAG, "Ignoring opted out non-initialized log: " + msg); - } - } - - // Crashlytics log - public static void log(int priority, String tag, String msg) { - try { - final Crashlytics crashlytics = Crashlytics.getInstance(); - crashlytics.core.log(priority, tag, msg); - } catch (NullPointerException | IllegalStateException e) { - android.util.Log.d(TAG, "Ignoring opted out non-initialized log: " + msg); - } - } - - public static boolean fabricEnabled() { - return SP.getBoolean("enable_fabric", true); - } - - // Answers logCustom - public void logCustom(CustomEvent event) { - try { - final Answers answers = Answers.getInstance(); - if (fabricEnabled()) { - answers.logCustom(event); - } else { - android.util.Log.d(TAG, "Ignoring recently opted-out event: " + event.toString()); - } - } catch (NullPointerException | IllegalStateException e) { - android.util.Log.d(TAG, "Ignoring opted-out non-initialized event: " + event.toString()); - } - } - - public static void uploadDailyStats() { - if (!fabricEnabled()) return; - - long lastUploadDay = SP.getLong(MainApp.gs(R.string.key_plugin_stats_report_timestamp), 0L); - - Date date = new Date(); - date.setHours(0); - date.setMinutes(0); - date.setSeconds(0); - long today = date.getTime() - date.getTime() % 1000; - - if (today > lastUploadDay) { - uploadAppUsageType(); - uploadPluginStats(); - - SP.putLong(MainApp.gs(R.string.key_plugin_stats_report_timestamp), today); - } - } - - private static void uploadPluginStats() { - CustomEvent pluginStats = new CustomEvent("PluginStats"); - pluginStats.putCustomAttribute("version", BuildConfig.VERSION); - pluginStats.putCustomAttribute("HEAD", BuildConfig.HEAD); - pluginStats.putCustomAttribute("language", SP.getString(R.string.key_language,"default")); - for (PluginBase plugin : MainApp.getPluginsList()) { - if (plugin.isEnabled(plugin.getType()) && !plugin.pluginDescription.alwaysEnabled) { - // Fabric allows no more than 20 attributes attached to an event. By reporting disabled plugins as - // well, we would exceed that threshold, so only report what is enabled - // TODO >2.0: consider reworking this to upload an event per enabled plugin instead. - pluginStats.putCustomAttribute(plugin.getClass().getSimpleName(), "enabled"); - } - } - - getInstance().logCustom(pluginStats); - } - - private static void uploadAppUsageType() { - CustomEvent type = new CustomEvent("AppUsageType"); - if (Config.NSCLIENT) - type.putCustomAttribute("type", "NSClient"); - else if (Config.PUMPCONTROL) - type.putCustomAttribute("type", "PumpControl"); - else if (MainApp.getConstraintChecker().isClosedLoopAllowed().value()) - type.putCustomAttribute("type", "ClosedLoop"); - else - type.putCustomAttribute("type", "OpenLoop"); - - getInstance().logCustom(type); - } - -} diff --git a/app/src/main/java/info/nightscout/utils/LocaleHelper.java b/app/src/main/java/info/nightscout/utils/LocaleHelper.java deleted file mode 100644 index c8faa83b9d..0000000000 --- a/app/src/main/java/info/nightscout/utils/LocaleHelper.java +++ /dev/null @@ -1,65 +0,0 @@ -package info.nightscout.utils; - -import android.content.Context; -import android.content.SharedPreferences; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.preference.PreferenceManager; - -import java.util.Locale; - -/** - * This class is used to change your application locale and persist this change for the next time - * that your app is going to be used. - *

- * You can also change the locale of your application on the fly by using the setLocale method. - *

- * Created by gunhansancar on 07/10/15. - */ -public class LocaleHelper { - - private static final String SELECTED_LANGUAGE = "Locale.Helper.Selected.Language"; - - public static void onCreate(Context context) { - String lang = getPersistedData(context, Locale.getDefault().getLanguage()); - setLocale(context, lang); - } - - public static void onCreate(Context context, String defaultLanguage) { - String lang = getPersistedData(context, defaultLanguage); - setLocale(context, lang); - } - - public static String getLanguage(Context context) { - return getPersistedData(context, Locale.getDefault().getLanguage()); - } - - public static void setLocale(Context context, String language) { - persist(context, language); - updateResources(context, language); - } - - private static String getPersistedData(Context context, String defaultLanguage) { - return SP.getString(SELECTED_LANGUAGE, defaultLanguage); - } - - private static void persist(Context context, String language) { - SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); - SharedPreferences.Editor editor = preferences.edit(); - - editor.putString(SELECTED_LANGUAGE, language); - editor.apply(); - } - - private static void updateResources(Context context, String language) { - Locale locale = new Locale(language); - Locale.setDefault(locale); - - Resources resources = context.getResources(); - - Configuration configuration = resources.getConfiguration(); - configuration.locale = locale; - - resources.updateConfiguration(configuration, resources.getDisplayMetrics()); - } -} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/utils/MidnightTime.java b/app/src/main/java/info/nightscout/utils/MidnightTime.java deleted file mode 100644 index 523fe13826..0000000000 --- a/app/src/main/java/info/nightscout/utils/MidnightTime.java +++ /dev/null @@ -1,43 +0,0 @@ -package info.nightscout.utils; - -import android.util.LongSparseArray; - -import java.util.Calendar; - -public class MidnightTime { - private static LongSparseArray times = new LongSparseArray(); - - private static long hits = 0; - private static long misses = 0; - - public static long calc() { - Calendar c = Calendar.getInstance(); - c.set(Calendar.HOUR_OF_DAY, 0); - c.set(Calendar.MINUTE, 0); - c.set(Calendar.SECOND, 0); - c.set(Calendar.MILLISECOND, 0); - return c.getTimeInMillis(); - } - - public static long calc(long time) { - Long m = (Long) times.get(time); - if (m != null) { - ++hits; - return m; - } - Calendar c = Calendar.getInstance(); - c.setTimeInMillis(time); - c.set(Calendar.HOUR_OF_DAY, 0); - c.set(Calendar.MINUTE, 0); - c.set(Calendar.SECOND, 0); - c.set(Calendar.MILLISECOND, 0); - m = c.getTimeInMillis(); - times.append(time, m); - ++misses; - return m; - } - - public static String log() { - return "Hits: " + hits + " misses: " + misses + " stored: " + times.size(); - } -} diff --git a/app/src/main/java/info/nightscout/utils/ToastUtils.java b/app/src/main/java/info/nightscout/utils/ToastUtils.java deleted file mode 100644 index 4ad07a4885..0000000000 --- a/app/src/main/java/info/nightscout/utils/ToastUtils.java +++ /dev/null @@ -1,51 +0,0 @@ -package info.nightscout.utils; - -import android.content.Context; -import android.media.MediaPlayer; -import android.os.Handler; -import android.os.Looper; -import android.widget.Toast; - -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.plugins.Overview.notifications.Notification; -import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; - - -public class ToastUtils { - public static void showToastInUiThread(final Context ctx, - final String string) { - - Handler mainThread = new Handler(Looper.getMainLooper()); - mainThread.post(new Runnable() { - @Override - public void run() { - Toast.makeText(ctx, string, Toast.LENGTH_SHORT).show(); - } - }); - } - - public static void showToastInUiThread(final Context ctx, - final String string, int soundID) { - - showToastInUiThread(ctx, string); - playSound(ctx, soundID); - new Thread(new Runnable() { - @Override - public void run() { - Notification notification = new Notification(Notification.TOAST_ALARM, string, Notification.URGENT); - MainApp.bus().post(new EventNewNotification(notification)); - } - }).start(); - } - - private static void playSound(final Context ctx, final int soundID) { - final MediaPlayer soundMP = MediaPlayer.create(ctx, soundID); - soundMP.start(); - soundMP.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { - @Override - public void onCompletion(MediaPlayer mp) { - mp.release(); - } - }); - } -} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/utils/VersionChecker.java b/app/src/main/java/info/nightscout/utils/VersionChecker.java deleted file mode 100644 index 00bfc50395..0000000000 --- a/app/src/main/java/info/nightscout/utils/VersionChecker.java +++ /dev/null @@ -1,101 +0,0 @@ -package info.nightscout.utils; - -import android.net.ConnectivityManager; -import android.net.NetworkInfo; - -import org.apache.http.HttpResponse; -import org.apache.http.client.HttpClient; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.impl.client.DefaultHttpClient; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import info.nightscout.androidaps.BuildConfig; -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; -import info.nightscout.androidaps.plugins.Overview.notifications.Notification; - -import static android.content.Context.CONNECTIVITY_SERVICE; - -public class VersionChecker { - private static Logger log = LoggerFactory.getLogger(L.CORE); - - public static void check() { - if (isConnected()) - new Thread(() -> { - HttpClient client = new DefaultHttpClient(); - HttpGet request = new HttpGet("https://raw.githubusercontent.com/MilosKozak/AndroidAPS/master/app/build.gradle"); - HttpResponse response; - - try { - response = client.execute(request); - InputStream inputStream = response.getEntity().getContent(); - - if (inputStream != null) { - String result = findLine(inputStream); - if (result != null) { - result = result.replace("version", "").replace("\"", "").replace("\\s+", "").trim(); - int compare = result.compareTo(BuildConfig.VERSION_NAME.replace("\"", "")); - if (compare == 0) { - log.debug("Version equal to master"); - return; - } else if (compare > 0) { - log.debug("Version outdated. Found " + result); - Notification notification = new Notification(Notification.NEWVERSIONDETECTED, String.format(MainApp.gs(R.string.versionavailable), result), Notification.LOW); - MainApp.bus().post(new EventNewNotification(notification)); - return; - } else { - log.debug("Version newer than master. Are you developer?"); - return; - } - } - } - - log.debug("Github master version not found"); - - } catch (IOException e) { - e.printStackTrace(); - log.debug("Github master version check error"); - } - }).start(); - else - log.debug("Github master version no checked. No connectivity"); - } - - // convert inputstream to String - private static String findLine(InputStream inputStream) throws IOException { - BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); - String line; - String regex = "(.*)version(.*)\"(\\d+)\\.(\\d+)\"(.*)"; - Pattern p = Pattern.compile(regex); - - while ((line = bufferedReader.readLine()) != null) { - Matcher m = p.matcher(line); - if (m.matches()) { - log.debug("+++ " + line); - return line; - } else { - log.debug("--- " + line); - } - } - inputStream.close(); - return null; - } - - // check network connection - public static boolean isConnected() { - ConnectivityManager connMgr = (ConnectivityManager) MainApp.instance().getApplicationContext().getSystemService(CONNECTIVITY_SERVICE); - NetworkInfo networkInfo = connMgr.getActiveNetworkInfo(); - return networkInfo != null && networkInfo.isConnected(); - } - -} diff --git a/app/src/main/java/org/monkey/d/ruffy/ruffy/driver/display/menu/MenuDate.java b/app/src/main/java/org/monkey/d/ruffy/ruffy/driver/display/menu/MenuDate.java index 05cc741413..6e3d54f3bb 100644 --- a/app/src/main/java/org/monkey/d/ruffy/ruffy/driver/display/menu/MenuDate.java +++ b/app/src/main/java/org/monkey/d/ruffy/ruffy/driver/display/menu/MenuDate.java @@ -1,5 +1,7 @@ package org.monkey.d.ruffy.ruffy.driver.display.menu; +import java.util.Locale; + /** * Created by fishermen21 on 24.05.17. */ @@ -30,6 +32,6 @@ public class MenuDate { @Override public String toString() { - return day+"."+String.format("%02d",month)+"."; + return day+"."+String.format(Locale.ENGLISH, "%02d",month)+"."; } } diff --git a/app/src/main/java/org/monkey/d/ruffy/ruffy/driver/display/menu/MenuTime.java b/app/src/main/java/org/monkey/d/ruffy/ruffy/driver/display/menu/MenuTime.java index 147aafc8eb..356f9e5ddf 100644 --- a/app/src/main/java/org/monkey/d/ruffy/ruffy/driver/display/menu/MenuTime.java +++ b/app/src/main/java/org/monkey/d/ruffy/ruffy/driver/display/menu/MenuTime.java @@ -1,5 +1,7 @@ package org.monkey.d.ruffy.ruffy.driver.display.menu; +import java.util.Locale; + /** * Created by fishermen21 on 22.05.17. */ @@ -31,6 +33,6 @@ public class MenuTime { @Override public String toString() { - return hour+":"+String.format("%02d",minute); + return hour+":"+String.format(Locale.ENGLISH, "%02d",minute); } } diff --git a/app/src/main/res/drawable-anydpi/ic_keyboard_capslock.xml b/app/src/main/res/drawable-anydpi/ic_keyboard_capslock.xml new file mode 100644 index 0000000000..db4409f2b8 --- /dev/null +++ b/app/src/main/res/drawable-anydpi/ic_keyboard_capslock.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable-anydpi/ic_keyboard_tab.xml b/app/src/main/res/drawable-anydpi/ic_keyboard_tab.xml new file mode 100644 index 0000000000..03ec6ed69f --- /dev/null +++ b/app/src/main/res/drawable-anydpi/ic_keyboard_tab.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable-anydpi/ic_location_on.xml b/app/src/main/res/drawable-anydpi/ic_location_on.xml new file mode 100644 index 0000000000..1017cbc8d2 --- /dev/null +++ b/app/src/main/res/drawable-anydpi/ic_location_on.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable-anydpi/ic_network_wifi.xml b/app/src/main/res/drawable-anydpi/ic_network_wifi.xml new file mode 100644 index 0000000000..c5ae21ec89 --- /dev/null +++ b/app/src/main/res/drawable-anydpi/ic_network_wifi.xml @@ -0,0 +1,13 @@ + + + + diff --git a/app/src/main/res/drawable-anydpi/ic_notifications.xml b/app/src/main/res/drawable-anydpi/ic_notifications.xml new file mode 100644 index 0000000000..b655d741e6 --- /dev/null +++ b/app/src/main/res/drawable-anydpi/ic_notifications.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable-hdpi/ic_error.png b/app/src/main/res/drawable-hdpi/ic_error.png new file mode 100644 index 0000000000..5b57c7458f Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_error.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_maintenance.png b/app/src/main/res/drawable-hdpi/ic_maintenance.png new file mode 100644 index 0000000000..60f34eb201 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_maintenance.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_notification.png b/app/src/main/res/drawable-hdpi/ic_notif_aaps.png similarity index 100% rename from app/src/main/res/drawable-hdpi/ic_notification.png rename to app/src/main/res/drawable-hdpi/ic_notif_aaps.png diff --git a/app/src/main/res/drawable-hdpi/nsclient_smallicon.png b/app/src/main/res/drawable-hdpi/ic_notif_nsclient.png similarity index 100% rename from app/src/main/res/drawable-hdpi/nsclient_smallicon.png rename to app/src/main/res/drawable-hdpi/ic_notif_nsclient.png diff --git a/app/src/main/res/drawable-hdpi/ic_notif_pumpcontrol.png b/app/src/main/res/drawable-hdpi/ic_notif_pumpcontrol.png new file mode 100644 index 0000000000..5562fef378 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_notif_pumpcontrol.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_reminder.png b/app/src/main/res/drawable-hdpi/ic_reminder.png new file mode 100644 index 0000000000..b45924d4eb Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_reminder.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_warning.png b/app/src/main/res/drawable-hdpi/ic_warning.png new file mode 100644 index 0000000000..d7aa344bca Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_warning.png differ diff --git a/app/src/main/res/drawable-mdpi-v11/refresh.xml b/app/src/main/res/drawable-mdpi-v11/refresh.xml new file mode 100644 index 0000000000..677809a8c2 --- /dev/null +++ b/app/src/main/res/drawable-mdpi-v11/refresh.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-mdpi/ic_error.png b/app/src/main/res/drawable-mdpi/ic_error.png new file mode 100644 index 0000000000..68a4b0e48c Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_error.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_maintenance.png b/app/src/main/res/drawable-mdpi/ic_maintenance.png new file mode 100644 index 0000000000..728313d9e7 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_maintenance.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_notification.png b/app/src/main/res/drawable-mdpi/ic_notif_aaps.png similarity index 100% rename from app/src/main/res/drawable-mdpi/ic_notification.png rename to app/src/main/res/drawable-mdpi/ic_notif_aaps.png diff --git a/app/src/main/res/drawable-mdpi/nsclient_smallicon.png b/app/src/main/res/drawable-mdpi/ic_notif_nsclient.png similarity index 100% rename from app/src/main/res/drawable-mdpi/nsclient_smallicon.png rename to app/src/main/res/drawable-mdpi/ic_notif_nsclient.png diff --git a/app/src/main/res/drawable-mdpi/ic_notif_pumpcontrol.png b/app/src/main/res/drawable-mdpi/ic_notif_pumpcontrol.png new file mode 100644 index 0000000000..3feb5d6248 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_notif_pumpcontrol.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_reminder.png b/app/src/main/res/drawable-mdpi/ic_reminder.png new file mode 100644 index 0000000000..2c269d5530 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_reminder.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_warning.png b/app/src/main/res/drawable-mdpi/ic_warning.png new file mode 100644 index 0000000000..1ff44a152a Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_warning.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_error.png b/app/src/main/res/drawable-xhdpi/ic_error.png new file mode 100644 index 0000000000..dee2d5af82 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_error.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_maintenance.png b/app/src/main/res/drawable-xhdpi/ic_maintenance.png new file mode 100644 index 0000000000..303e1780f9 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_maintenance.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_notification.png b/app/src/main/res/drawable-xhdpi/ic_notif_aaps.png similarity index 100% rename from app/src/main/res/drawable-xhdpi/ic_notification.png rename to app/src/main/res/drawable-xhdpi/ic_notif_aaps.png diff --git a/app/src/main/res/drawable-xhdpi/nsclient_smallicon.png b/app/src/main/res/drawable-xhdpi/ic_notif_nsclient.png similarity index 100% rename from app/src/main/res/drawable-xhdpi/nsclient_smallicon.png rename to app/src/main/res/drawable-xhdpi/ic_notif_nsclient.png diff --git a/app/src/main/res/drawable-xhdpi/ic_notif_pumpcontrol.png b/app/src/main/res/drawable-xhdpi/ic_notif_pumpcontrol.png new file mode 100644 index 0000000000..e5eb24b9da Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_notif_pumpcontrol.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_reminder.png b/app/src/main/res/drawable-xhdpi/ic_reminder.png new file mode 100644 index 0000000000..904a608285 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_reminder.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_warning.png b/app/src/main/res/drawable-xhdpi/ic_warning.png new file mode 100644 index 0000000000..652a1bb1d9 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_warning.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_error.png b/app/src/main/res/drawable-xxhdpi/ic_error.png new file mode 100644 index 0000000000..cf389b5d96 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_error.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_maintenance.png b/app/src/main/res/drawable-xxhdpi/ic_maintenance.png new file mode 100644 index 0000000000..952e7b9ef3 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_maintenance.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_notification.png b/app/src/main/res/drawable-xxhdpi/ic_notif_aaps.png similarity index 100% rename from app/src/main/res/drawable-xxhdpi/ic_notification.png rename to app/src/main/res/drawable-xxhdpi/ic_notif_aaps.png diff --git a/app/src/main/res/drawable-xxhdpi/nsclient_smallicon.png b/app/src/main/res/drawable-xxhdpi/ic_notif_nsclient.png similarity index 100% rename from app/src/main/res/drawable-xxhdpi/nsclient_smallicon.png rename to app/src/main/res/drawable-xxhdpi/ic_notif_nsclient.png diff --git a/app/src/main/res/drawable-xxhdpi/ic_notif_pumpcontrol.png b/app/src/main/res/drawable-xxhdpi/ic_notif_pumpcontrol.png new file mode 100644 index 0000000000..12bf9fd364 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_notif_pumpcontrol.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_reminder.png b/app/src/main/res/drawable-xxhdpi/ic_reminder.png new file mode 100644 index 0000000000..e918305ba0 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_reminder.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_warning.png b/app/src/main/res/drawable-xxhdpi/ic_warning.png new file mode 100644 index 0000000000..7ab70f77c2 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_warning.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_error.png b/app/src/main/res/drawable-xxxhdpi/ic_error.png new file mode 100644 index 0000000000..b8743474f7 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_error.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_maintenance.png b/app/src/main/res/drawable-xxxhdpi/ic_maintenance.png new file mode 100644 index 0000000000..1046459dc3 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_maintenance.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_reminder.png b/app/src/main/res/drawable-xxxhdpi/ic_reminder.png new file mode 100644 index 0000000000..6aa4e934d0 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_reminder.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_warning.png b/app/src/main/res/drawable-xxxhdpi/ic_warning.png new file mode 100644 index 0000000000..607e14b7d2 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_warning.png differ diff --git a/app/src/main/res/drawable/as.png b/app/src/main/res/drawable/as.png new file mode 100644 index 0000000000..a37e4c3465 Binary files /dev/null and b/app/src/main/res/drawable/as.png differ diff --git a/app/src/main/res/drawable/border_automation_unit.xml b/app/src/main/res/drawable/border_automation_unit.xml new file mode 100644 index 0000000000..eb85656295 --- /dev/null +++ b/app/src/main/res/drawable/border_automation_unit.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_access_alarm_24dp.xml b/app/src/main/res/drawable/ic_access_alarm_24dp.xml new file mode 100644 index 0000000000..3e1d84e037 --- /dev/null +++ b/app/src/main/res/drawable/ic_access_alarm_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_add_black_24dp.xml b/app/src/main/res/drawable/ic_add_black_24dp.xml new file mode 100644 index 0000000000..0258249cc4 --- /dev/null +++ b/app/src/main/res/drawable/ic_add_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_arrow_forward_white_24dp.xml b/app/src/main/res/drawable/ic_arrow_forward_white_24dp.xml new file mode 100644 index 0000000000..5304b93e18 --- /dev/null +++ b/app/src/main/res/drawable/ic_arrow_forward_white_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_notification.png b/app/src/main/res/drawable/ic_notif_aaps.png similarity index 100% rename from app/src/main/res/drawable/ic_notification.png rename to app/src/main/res/drawable/ic_notif_aaps.png diff --git a/app/src/main/res/drawable/ic_notif_pumpcontrol.png b/app/src/main/res/drawable/ic_notif_pumpcontrol.png new file mode 100644 index 0000000000..5562fef378 Binary files /dev/null and b/app/src/main/res/drawable/ic_notif_pumpcontrol.png differ diff --git a/app/src/main/res/drawable/ic_pause_circle_outline_24dp.xml b/app/src/main/res/drawable/ic_pause_circle_outline_24dp.xml new file mode 100644 index 0000000000..4a469646bd --- /dev/null +++ b/app/src/main/res/drawable/ic_pause_circle_outline_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_play_circle_outline_24dp.xml b/app/src/main/res/drawable/ic_play_circle_outline_24dp.xml new file mode 100644 index 0000000000..9997bf2034 --- /dev/null +++ b/app/src/main/res/drawable/ic_play_circle_outline_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_refresh.xml b/app/src/main/res/drawable/ic_refresh.xml new file mode 100644 index 0000000000..8229a9a64c --- /dev/null +++ b/app/src/main/res/drawable/ic_refresh.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_replay_24dp.xml b/app/src/main/res/drawable/ic_replay_24dp.xml new file mode 100644 index 0000000000..32942990ac --- /dev/null +++ b/app/src/main/res/drawable/ic_replay_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_stop_24dp.xml b/app/src/main/res/drawable/ic_stop_24dp.xml new file mode 100644 index 0000000000..88299804a8 --- /dev/null +++ b/app/src/main/res/drawable/ic_stop_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_trash_outline.xml b/app/src/main/res/drawable/ic_trash_outline.xml new file mode 100644 index 0000000000..a411c394e0 --- /dev/null +++ b/app/src/main/res/drawable/ic_trash_outline.xml @@ -0,0 +1,7 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/icon_auto_delta.png b/app/src/main/res/drawable/icon_auto_delta.png new file mode 100644 index 0000000000..ddb0930b0b Binary files /dev/null and b/app/src/main/res/drawable/icon_auto_delta.png differ diff --git a/app/src/main/res/drawable/launch_screen.xml b/app/src/main/res/drawable/launch_screen.xml new file mode 100644 index 0000000000..543fd89929 --- /dev/null +++ b/app/src/main/res/drawable/launch_screen.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/splash_icon.png b/app/src/main/res/drawable/splash_icon.png new file mode 100644 index 0000000000..2c0ee32c1b Binary files /dev/null and b/app/src/main/res/drawable/splash_icon.png differ diff --git a/app/src/main/res/layout/actions_fill_dialog.xml b/app/src/main/res/layout/actions_fill_dialog.xml index 21fb5d3c66..27fdb02ee7 100644 --- a/app/src/main/res/layout/actions_fill_dialog.xml +++ b/app/src/main/res/layout/actions_fill_dialog.xml @@ -75,7 +75,7 @@ android:textStyle="bold" android:text="@string/overview_insulin_label" /> - + tools:context=".plugins.general.actions.ActionsFragment"> - - - - - - - - - + android:layout_height="fill_parent"> - - - - @@ -129,4 +128,4 @@ - + diff --git a/app/src/main/res/layout/activity_insight_alert.xml b/app/src/main/res/layout/activity_insight_alert.xml new file mode 100644 index 0000000000..6bc3dc1565 --- /dev/null +++ b/app/src/main/res/layout/activity_insight_alert.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + +