diff --git a/.travis.yml b/.travis.yml index 5c6309f817..ec1632958e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,19 +2,19 @@ language: android jdk: oraclejdk8 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 diff --git a/app/build.gradle b/app/build.gradle index 46a2ee19dd..57e315c811 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -6,27 +6,37 @@ buildscript { dependencies { classpath 'io.fabric.tools:gradle:1.+' - classpath 'com.dicedmelon.gradle:jacoco-android:0.1.3' + 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: '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: 'io.fabric' +apply plugin: 'jacoco-android' apply plugin: 'com.jakewharton.butterknife' +apply plugin: 'de.undercouch.download' + + +jacoco { + toolVersion = "0.8.3" +} ext { - supportLibraryVersion = "27.1.1" + supportLibraryVersion = "28.0.0" ormLiteVersion = "4.46" powermockVersion = "1.7.3" dexmakerVersion = "1.2" - butterknifeVersion = "8.8.1" + butterknifeVersion = "10.1.0" } repositories { maven { url 'https://maven.fabric.io/public' } jcenter { url "https://jcenter.bintray.com/" } + mavenCentral() } def generateGitBuild = { -> @@ -67,31 +77,55 @@ def generateDate = { -> 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.2.3-dev" + version "2.4-dev" buildConfigField "String", "VERSION", '"' + version + '"' buildConfigField "String", "BUILDVERSION", '"' + generateGitBuild() + '-' + generateDate() + '"' - buildConfigField "String", "REMOTE", '"' + generateGitRemote()+ '"' + 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 @@ -120,7 +154,7 @@ android { resValue "string", "app_name", "AndroidAPS" versionName version manifestPlaceholders = [ - appIcon: "@mipmap/ic_launcher", + appIcon : "@mipmap/ic_launcher", appIconRound: "@mipmap/ic_launcher_round" ] } @@ -130,7 +164,7 @@ android { resValue "string", "app_name", "Pumpcontrol" versionName version + "-pumpcontrol" manifestPlaceholders = [ - appIcon: "@mipmap/ic_pumpcontrol", + appIcon : "@mipmap/ic_pumpcontrol", appIconRound: "@null" ] } @@ -140,7 +174,7 @@ android { resValue "string", "app_name", "NSClient" versionName version + "-nsclient" manifestPlaceholders = [ - appIcon: "@mipmap/ic_yellowowl", + appIcon : "@mipmap/ic_yellowowl", appIconRound: "@null" ] } @@ -150,7 +184,7 @@ android { resValue "string", "app_name", "NSClient2" versionName version + "-nsclient" manifestPlaceholders = [ - appIcon: "@mipmap/ic_yellowowl", + appIcon : "@mipmap/ic_yellowowl", appIconRound: "@null" ] } @@ -161,11 +195,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 { @@ -177,31 +218,30 @@ allprojects { } } -configurations { - libs -} - dependencies { wearApp project(':wear') implementation fileTree(include: ['*.jar'], dir: 'libs') - implementation 'com.google.android.gms:play-services-wearable:16.0.1' - implementation 'com.google.firebase:firebase-core:16.0.8' + implementation 'com.google.android.gms:play-services-wearable:17.0.0' + implementation 'com.google.firebase:firebase-core:17.0.1' implementation("com.crashlytics.sdk.android:crashlytics:2.9.9@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.0.2' + 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" + + // Otto bus will be replaced by rx 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") { @@ -212,7 +252,7 @@ dependencies { // Graphview cannot be upgraded implementation "com.jjoe64:graphview:4.0.1" implementation "com.joanzapata.iconify:android-iconify-fontawesome:2.1.1" - implementation 'com.android.support.constraint:constraint-layout:1.1.3' + implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation(name: "android-edittext-validator-v1.3.4-mod", ext: "aar") implementation 'com.madgag.spongycastle:core:1.58.0.0' @@ -223,7 +263,7 @@ dependencies { // excluding org.json which is provided by Android exclude group: "org.json", module: "json" } - implementation "com.google.code.gson:gson:2.8.2" + 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" @@ -243,24 +283,39 @@ dependencies { testImplementation "org.powermock:powermock-module-junit4:${powermockVersion}" testImplementation "joda-time:joda-time:2.9.9" testImplementation "com.google.truth:truth:0.39" - testImplementation 'org.robolectric:robolectric:3.8' + testImplementation 'org.robolectric:robolectric:4.2.1' testImplementation "org.skyscreamer:jsonassert:1.5.0" 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/") @@ -274,3 +329,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/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 3eaa81ba45..3424b84be1 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -17,10 +17,11 @@ + - + @@ -34,13 +35,15 @@ android:label="@string/app_name" android:roundIcon="${appIconRound}" android:supportsRtl="true" - android:theme="@style/AppTheme.NoActionBar"> + android:theme="@style/AppTheme.NoActionBar" + android:fullBackupContent="true"> + @@ -85,10 +88,8 @@ - - - - + + @@ -147,7 +148,7 @@ @@ -281,6 +282,10 @@ android:name=".plugins.pump.insight.activities.InsightPairingInformationActivity" android:label="@string/pairing_information" android:theme="@style/AppTheme" /> + + + + diff --git a/app/src/main/java/info/nightscout/androidaps/MainActivity.java b/app/src/main/java/info/nightscout/androidaps/MainActivity.java index f441a8b243..b9622daf1b 100644 --- a/app/src/main/java/info/nightscout/androidaps/MainActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/MainActivity.java @@ -7,16 +7,16 @@ 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 androidx.annotation.Nullable; +import com.google.android.material.navigation.NavigationView; +import com.google.android.material.tabs.TabLayout; +import androidx.core.app.ActivityCompat; +import androidx.viewpager.widget.ViewPager; +import androidx.drawerlayout.widget.DrawerLayout; +import androidx.appcompat.app.ActionBarDrawerToggle; +import androidx.appcompat.app.AlertDialog; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.widget.Toolbar; import android.text.SpannableString; import android.text.method.LinkMovementMethod; import android.text.util.Linkify; @@ -48,9 +48,12 @@ import info.nightscout.androidaps.events.EventFeatureRunning; import info.nightscout.androidaps.events.EventPreferenceChange; import info.nightscout.androidaps.events.EventRefreshGui; import info.nightscout.androidaps.interfaces.PluginBase; +import info.nightscout.androidaps.interfaces.PluginType; import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin; import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; import info.nightscout.androidaps.plugins.general.nsclient.data.NSSettingsStatus; +import info.nightscout.androidaps.plugins.general.versionChecker.VersionCheckerUtilsKt; import info.nightscout.androidaps.setupwizard.SetupWizardActivity; import info.nightscout.androidaps.tabs.TabPageAdapter; import info.nightscout.androidaps.utils.AndroidPermission; @@ -59,7 +62,6 @@ 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 info.nightscout.androidaps.utils.VersionChecker; public class MainActivity extends AppCompatActivity { private static Logger log = LoggerFactory.getLogger(L.CORE); @@ -115,7 +117,11 @@ 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(); } diff --git a/app/src/main/java/info/nightscout/androidaps/MainApp.java b/app/src/main/java/info/nightscout/androidaps/MainApp.java index a00f23fc10..b64e5673a6 100644 --- a/app/src/main/java/info/nightscout/androidaps/MainApp.java +++ b/app/src/main/java/info/nightscout/androidaps/MainApp.java @@ -4,9 +4,10 @@ import android.app.Application; 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.Nullable; +import androidx.annotation.PluralsRes; +import androidx.localbroadcastmanager.content.LocalBroadcastManager; import com.crashlytics.android.Crashlytics; import com.google.firebase.analytics.FirebaseAnalytics; @@ -50,6 +51,8 @@ import info.nightscout.androidaps.plugins.general.nsclient.receivers.DBAccessRec 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.tidepool.TidepoolPlugin; +import info.nightscout.androidaps.plugins.general.versionChecker.VersionCheckerPlugin; import info.nightscout.androidaps.plugins.general.wear.WearPlugin; import info.nightscout.androidaps.plugins.general.xdripStatusline.StatuslinePlugin; import info.nightscout.androidaps.plugins.insulin.InsulinOrefFreePeakPlugin; @@ -71,8 +74,7 @@ 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.SourceDexcomG5Plugin; -import info.nightscout.androidaps.plugins.source.SourceDexcomG6Plugin; +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; @@ -88,6 +90,8 @@ import info.nightscout.androidaps.services.Intents; import info.nightscout.androidaps.utils.FabricPrivacy; import io.fabric.sdk.android.Fabric; +import static info.nightscout.androidaps.plugins.general.versionChecker.VersionCheckerUtilsKt.triggerCheckVersion; + public class MainApp extends Application { private static Logger log = LoggerFactory.getLogger(L.CORE); @@ -119,7 +123,7 @@ public class MainApp extends Application { log.debug("onCreate"); sInstance = this; sResources = getResources(); - sConstraintsChecker = new ConstraintChecker(this); + sConstraintsChecker = new ConstraintChecker(); sDatabaseHelper = OpenHelperManager.getHelper(sInstance, DatabaseHelper.class); try { @@ -142,12 +146,15 @@ public class MainApp extends Application { File engineeringModeSemaphore = new File(extFilesDir, "engineering_mode"); engineeringMode = engineeringModeSemaphore.exists() && engineeringModeSemaphore.isFile(); - devBranch = BuildConfig.VERSION.contains("dev"); + devBranch = BuildConfig.VERSION.contains("-") || BuildConfig.VERSION.matches(".*[a-zA-Z]+.*"); sBus = L.isEnabled(L.EVENTS) && devBranch ? new LoggingBus(ThreadEnforcer.ANY) : new Bus(ThreadEnforcer.ANY); registerLocalBroadcastReceiver(); + //trigger here to see the new version on app start after an update + triggerCheckVersion(); + if (pluginsList == null) { pluginsList = new ArrayList<>(); // Register all tabs in app here @@ -179,14 +186,14 @@ public class MainApp extends Application { if (Config.OTHERPROFILES) pluginsList.add(LocalProfilePlugin.getPlugin()); pluginsList.add(TreatmentsPlugin.getPlugin()); if (Config.SAFETY) pluginsList.add(SafetyPlugin.getPlugin()); + if (Config.SAFETY) pluginsList.add(VersionCheckerPlugin.INSTANCE); if (Config.SAFETY) pluginsList.add(StorageConstraintPlugin.getPlugin()); if (Config.APS) pluginsList.add(ObjectivesPlugin.getPlugin()); pluginsList.add(SourceXdripPlugin.getPlugin()); pluginsList.add(SourceNSClientPlugin.getPlugin()); pluginsList.add(SourceMM640gPlugin.getPlugin()); pluginsList.add(SourceGlimpPlugin.getPlugin()); - pluginsList.add(SourceDexcomG5Plugin.getPlugin()); - pluginsList.add(SourceDexcomG6Plugin.getPlugin()); + pluginsList.add(SourceDexcomPlugin.INSTANCE); pluginsList.add(SourcePoctechPlugin.getPlugin()); pluginsList.add(SourceTomatoPlugin.getPlugin()); pluginsList.add(SourceEversensePlugin.getPlugin()); @@ -197,6 +204,8 @@ public class MainApp extends Application { 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(ConfigBuilderPlugin.getPlugin()); 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 c007d1fced..bf61df4564 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,9 @@ 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 androidx.core.content.res.ResourcesCompat; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.widget.PopupMenu; import android.text.SpannableString; import android.text.style.ForegroundColorSpan; import android.view.Menu; @@ -52,7 +52,7 @@ public class HistoryBrowseActivity extends AppCompatActivity { ImageButton chartButton; boolean showBasal = true; - boolean showIob, showCob, showDev, showRat, showDevslope; + boolean showIob, showCob, showDev, showRat, showActPrim, showActSec, showDevslope; @BindView(R.id.historybrowse_date) @@ -285,6 +285,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 +309,7 @@ public class HistoryBrowseActivity extends AppCompatActivity { boolean useCobForScale = false; boolean useDevForScale = false; boolean useRatioForScale = false; + boolean useIAForScale = false; boolean useDSForScale = false; if (showIob) { @@ -315,6 +320,8 @@ public class HistoryBrowseActivity extends AppCompatActivity { useDevForScale = true; } else if (showRat) { useRatioForScale = true; + } else if (showActSec) { + useIAForScale = true; } else if (showDevslope) { useDSForScale = true; } @@ -327,6 +334,8 @@ public class HistoryBrowseActivity extends AppCompatActivity { 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 +346,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 +362,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 +401,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 +410,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 +419,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,6 +447,10 @@ 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(); @@ -420,6 +462,10 @@ public class HistoryBrowseActivity extends AppCompatActivity { showDev = !item1.isChecked(); } else if (item1.getItemId() == OverviewFragment.CHARTTYPE.SEN.ordinal()) { showRat = !item1.isChecked(); + } else if (item1.getItemId() == OverviewFragment.CHARTTYPE.ACTPRIM.ordinal()) { + showActPrim = !item1.isChecked(); + } else if (item1.getItemId() == OverviewFragment.CHARTTYPE.ACTSEC.ordinal()) { + showActSec = !item1.isChecked(); } else if (item1.getItemId() == OverviewFragment.CHARTTYPE.DEVSLOPE.ordinal()) { showDevslope = !item1.isChecked(); } 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 aea7bcfca6..863e7f231d 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/PreferencesActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/activities/PreferencesActivity.java @@ -15,12 +15,15 @@ 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.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginType; 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; @@ -39,9 +42,9 @@ 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.source.SourceDexcomG5Plugin; 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; @@ -63,6 +66,7 @@ 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); @@ -93,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)); } } @@ -144,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) { @@ -182,6 +186,7 @@ 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); addPreferencesFromResource(R.xml.pref_others); @@ -192,7 +197,7 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre } if (Config.NSCLIENT) { - PreferenceScreen scrnAdvancedSettings = (PreferenceScreen)findPreference(getString(R.string.key_advancedsettings)); + 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))); @@ -203,6 +208,13 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre } 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..321c7d07ea --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/activities/RequestDexcomPermissionActivity.kt @@ -0,0 +1,25 @@ +package info.nightscout.androidaps.activities + +import android.os.Build +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import info.nightscout.androidaps.plugins.source.SourceDexcomPlugin + +class RequestDexcomPermissionActivity : AppCompatActivity() { + + private val requestCode = "AndroidAPS <3".map { it.toInt() }.sum() + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + requestPermissions(arrayOf(SourceDexcomPlugin.PERMISSION), requestCode) + } else { + finish() + } + } + + 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 2a381cd0a8..2c899784bd 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/SingleFragmentActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/activities/SingleFragmentActivity.java @@ -2,9 +2,9 @@ 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 androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.appcompat.app.AppCompatActivity; import android.view.Menu; import android.view.MenuItem; 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 e42d31d7c0..832ca2ad85 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/TDDStatsActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/activities/TDDStatsActivity.java @@ -4,7 +4,7 @@ import android.app.Activity; import android.graphics.Color; import android.graphics.Rect; import android.os.Bundle; -import android.support.v7.widget.LinearLayoutManager; +import androidx.recyclerview.widget.LinearLayoutManager; import android.text.TextUtils; import android.view.KeyEvent; import android.view.MotionEvent; 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 68664033d0..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)); } @@ -79,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; @@ -91,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; @@ -103,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; @@ -115,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; @@ -127,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; @@ -139,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; @@ -151,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; @@ -162,8 +157,8 @@ public class ConstraintChecker implements ConstraintsInterface { } @Override - public Constraint isSuperBolusEnabled(Constraint value) { - 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; @@ -173,8 +168,8 @@ public class ConstraintChecker implements ConstraintsInterface { } @Override - public Constraint applyBasalConstraints(Constraint absoluteRate, Profile profile) { - ArrayList constraintsPlugins = mainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class); + 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; @@ -184,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; @@ -195,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; @@ -206,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; @@ -217,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; @@ -228,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/GlucoseStatus.java b/app/src/main/java/info/nightscout/androidaps/data/GlucoseStatus.java deleted file mode 100644 index be3e981fb4..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/data/GlucoseStatus.java +++ /dev/null @@ -1,178 +0,0 @@ -package info.nightscout.androidaps.data; - -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.db.BgReading; -import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin; -import info.nightscout.androidaps.utils.DateUtil; -import info.nightscout.androidaps.utils.DecimalFormatter; -import info.nightscout.androidaps.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; - - - public String log() { - return "Glucose: " + DecimalFormatter.to0Decimal(glucose) + " mg/dl " + - "Delta: " + DecimalFormatter.to0Decimal(delta) + " mg/dl" + - "Short avg. delta: " + " " + DecimalFormatter.to2Decimal(short_avgdelta) + " mg/dl " + - "Long avg. delta: " + 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); - - List data = IobCobCalculatorPlugin.getPlugin().getBgReadings(); - - if (data == null) { - if (L.isEnabled(L.GLUCOSE)) - log.debug("data=null"); - return null; - } - - int sizeRecords = data.size(); - if (sizeRecords == 0) { - if (L.isEnabled(L.GLUCOSE)) - log.debug("sizeRecords==0"); - return null; - } - - if (data.get(0).date < DateUtil.now() - 7 * 60 * 1000L && !allowOldData) { - if (L.isEnabled(L.GLUCOSE)) - log.debug("olddata"); - 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; - if (L.isEnabled(L.GLUCOSE)) - log.debug("sizeRecords==1"); - return status.round(); - } - - ArrayList now_value_list = new ArrayList<>(); - ArrayList last_deltas = new ArrayList<>(); - ArrayList short_deltas = new ArrayList<>(); - ArrayList long_deltas = new ArrayList<>(); - - // Use the latest sgv value in the now calculations - now_value_list.add(now.value); - - for (int i = 1; i < sizeRecords; i++) { - if (data.get(i).value > 38) { - BgReading then = data.get(i); - long then_date = then.date; - double avgdelta; - 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; - - if (L.isEnabled(L.GLUCOSE)) - log.debug(then.toString() + " minutesago=" + minutesago + " avgdelta=" + avgdelta); - - // use the average of all data points in the last 2.5m for all further "now" calculations - if (0 < minutesago && minutesago < 2.5) { - // Keep and average all values within the last 2.5 minutes - now_value_list.add(then.value); - now.value = average(now_value_list); - // 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); - } else { - // Do not process any more records after >= 42.5 minutes - break; - } - } - } - - 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 - - if (L.isEnabled(L.GLUCOSE)) - log.debug(status.log()); - 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 d5c1c563c7..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; 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 23a7e62426..8524246d02 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; @@ -400,6 +400,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()); } @@ -420,6 +433,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()); } @@ -441,8 +467,8 @@ public class Profile { return getValuesList(basal_v, null, new DecimalFormat("0.00"), MainApp.gs(R.string.profile_ins_units_per_hout)); } - public class BasalValue { - public BasalValue(int timeAsSeconds, double value) { + public class ProfileValue { + public ProfileValue(int timeAsSeconds, double value) { this.timeAsSeconds = timeAsSeconds; this.value = value; } @@ -451,15 +477,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; } @@ -500,6 +526,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 2cb604a819..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; 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/QuickWizardEntry.java b/app/src/main/java/info/nightscout/androidaps/data/QuickWizardEntry.java index 4262fe2133..062f6ae391 100644 --- a/app/src/main/java/info/nightscout/androidaps/data/QuickWizardEntry.java +++ b/app/src/main/java/info/nightscout/androidaps/data/QuickWizardEntry.java @@ -12,6 +12,7 @@ import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.db.TempTarget; import info.nightscout.androidaps.interfaces.TreatmentsInterface; 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; @@ -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/DatabaseHelper.java b/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java index a41939b326..94c4f3376e 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; @@ -29,6 +29,7 @@ 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; @@ -45,9 +46,9 @@ 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.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.general.nsclient.NSUpload; 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; @@ -83,7 +84,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { public static final String DATABASE_INSIGHT_BOLUS_IDS = "InsightBolusIDs"; public static final String DATABASE_INSIGHT_PUMP_IDS = "InsightPumpIDs"; - private static final int DATABASE_VERSION = 10; + private static final int DATABASE_VERSION = 11; public static Long earliestDataChange = null; @@ -131,6 +132,10 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { 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); @@ -143,15 +148,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 == 9 && newVersion == 10) { - TableUtils.createTableIfNotExists(connectionSource, InsightHistoryOffset.class); - TableUtils.createTableIfNotExists(connectionSource, InsightBolusID.class); - TableUtils.createTableIfNotExists(connectionSource, InsightPumpID.class); - } else { + if (oldVersion < 7) { log.info(DatabaseHelper.class.getName(), "onUpgrade"); TableUtils.dropTable(connectionSource, TempTarget.class, true); TableUtils.dropTable(connectionSource, BgReading.class, true); @@ -162,6 +159,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); @@ -403,6 +411,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { if (L.isEnabled(L.DATABASE)) log.debug("Firing EventNewBg"); MainApp.bus().post(new EventNewBG(bgReading)); + RxBus.INSTANCE.send(new EventNewBG(bgReading)); scheduledBgPost = null; } } @@ -427,7 +436,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { return null; for (int i = 0; i < bgList.size(); i++) - if (bgList.get(i).value > 39) + if (bgList.get(i).value >= 39) return bgList.get(i); return null; } @@ -589,7 +598,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { } } - // -------------------- TREATMENT HANDLING ------------------- + // -------------------- TEMPTARGET HANDLING ------------------- public static void updateEarliestDataChange(long newDate) { if (earliestDataChange == null) { @@ -620,6 +629,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; @@ -943,6 +969,22 @@ 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() { @@ -1347,6 +1389,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++) { @@ -1500,6 +1559,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; 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 0e589f0595..5f37c3d96b 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/ProfileSwitch.java +++ b/app/src/main/java/info/nightscout/androidaps/db/ProfileSwitch.java @@ -1,7 +1,7 @@ package info.nightscout.androidaps.db; 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; diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventNewBG.java b/app/src/main/java/info/nightscout/androidaps/events/EventNewBG.java index dc4d434e0a..db3498bed7 100644 --- a/app/src/main/java/info/nightscout/androidaps/events/EventNewBG.java +++ b/app/src/main/java/info/nightscout/androidaps/events/EventNewBG.java @@ -1,6 +1,6 @@ package info.nightscout.androidaps.events; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import info.nightscout.androidaps.db.BgReading; diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventTreatmentChange.java b/app/src/main/java/info/nightscout/androidaps/events/EventTreatmentChange.java index 990f28a388..e1d9d527e1 100644 --- a/app/src/main/java/info/nightscout/androidaps/events/EventTreatmentChange.java +++ b/app/src/main/java/info/nightscout/androidaps/events/EventTreatmentChange.java @@ -1,6 +1,6 @@ package info.nightscout.androidaps.events; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import info.nightscout.androidaps.plugins.treatments.Treatment; 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 01be296539..2032c89b14 100644 --- a/app/src/main/java/info/nightscout/androidaps/interfaces/PluginBase.java +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/PluginBase.java @@ -1,7 +1,7 @@ package info.nightscout.androidaps.interfaces; import android.os.SystemClock; -import android.support.v4.app.FragmentActivity; +import androidx.fragment.app.FragmentActivity; import org.slf4j.Logger; import org.slf4j.LoggerFactory; 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/PumpInterface.java b/app/src/main/java/info/nightscout/androidaps/interfaces/PumpInterface.java index 3690312cf8..a5c9773012 100644 --- a/app/src/main/java/info/nightscout/androidaps/interfaces/PumpInterface.java +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/PumpInterface.java @@ -53,7 +53,9 @@ public interface PumpInterface { // Status to be passed to NS JSONObject getJSONStatus(Profile profile, String profileName); - String deviceID(); + String manufacter(); + String model(); + String serialNumber(); // Pump capabilities PumpDescription getPumpDescription(); 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 af44294cbb..4ea8be34a3 100644 --- a/app/src/main/java/info/nightscout/androidaps/interfaces/TreatmentsInterface.java +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/TreatmentsInterface.java @@ -5,6 +5,7 @@ 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; @@ -42,7 +43,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); 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 f685bbd424..362e03a0c7 100644 --- a/app/src/main/java/info/nightscout/androidaps/logging/L.java +++ b/app/src/main/java/info/nightscout/androidaps/logging/L.java @@ -87,6 +87,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"; @@ -114,6 +115,7 @@ public class L { logElements.add(new LogElement(EVENTS, false, 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)); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.java index 92378a1d6b..8569341ccd 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.java @@ -10,8 +10,8 @@ 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 androidx.annotation.NonNull; +import androidx.core.app.NotificationCompat; import com.squareup.otto.Subscribe; @@ -644,14 +644,27 @@ 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) { + ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.tempbasaldeliveryerror)); + } } - } - }); + }); + } else { + 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().isExtendedBolusCapable && activeTreatments.isInHistoryExtendedBoluslInProgress()) { ConfigBuilderPlugin.getPlugin().getCommandQueue().cancelExtended(new Callback() { @Override diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/DetermineBasalAdapterAMAJS.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/DetermineBasalAdapterAMAJS.java index 7eb9a2d81d..5b5c8cb63d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/DetermineBasalAdapterAMAJS.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/DetermineBasalAdapterAMAJS.java @@ -20,7 +20,7 @@ import java.lang.reflect.InvocationTargetException; 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; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/OpenAPSAMAPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/OpenAPSAMAPlugin.java index 3447c7c4f4..1f7deebea4 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/OpenAPSAMAPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/OpenAPSAMAPlugin.java @@ -6,7 +6,7 @@ import org.slf4j.LoggerFactory; 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; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/DetermineBasalAdapterMAJS.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/DetermineBasalAdapterMAJS.java index 4baabf22ab..ae1f390ded 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/DetermineBasalAdapterMAJS.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/DetermineBasalAdapterMAJS.java @@ -17,7 +17,7 @@ import java.lang.reflect.InvocationTargetException; 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; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/OpenAPSMAPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/OpenAPSMAPlugin.java index 24b4cb7929..2dd78bdb82 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/OpenAPSMAPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/OpenAPSMAPlugin.java @@ -6,7 +6,7 @@ import org.slf4j.LoggerFactory; 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; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/DetermineBasalAdapterSMBJS.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/DetermineBasalAdapterSMBJS.java index edaddd62c9..bfb75503c1 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/DetermineBasalAdapterSMBJS.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/DetermineBasalAdapterSMBJS.java @@ -20,7 +20,7 @@ import java.lang.reflect.InvocationTargetException; 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; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/OpenAPSSMBPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/OpenAPSSMBPlugin.java index ae1e634bbf..c0508e141a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/OpenAPSSMBPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/OpenAPSSMBPlugin.java @@ -6,7 +6,7 @@ import org.slf4j.LoggerFactory; 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; 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/SubscriberFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/common/SubscriberFragment.java index 3ac877b42d..1cf6a35f7d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/common/SubscriberFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/common/SubscriberFragment.java @@ -1,6 +1,6 @@ package info.nightscout.androidaps.plugins.common; -import android.support.v4.app.Fragment; +import androidx.fragment.app.Fragment; import butterknife.Unbinder; import info.nightscout.androidaps.MainApp; 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 index 47b5d49357..3b2fa590bf 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/ConfigBuilderFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/ConfigBuilderFragment.java @@ -3,8 +3,8 @@ 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 androidx.annotation.NonNull; +import androidx.annotation.StringRes; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; 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 index 3c3531da86..a29b893ef4 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; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -232,26 +232,32 @@ 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; } 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 index b19948fc5e..b81ae37983 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/DetailedBolusInfoStorage.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/DetailedBolusInfoStorage.java @@ -1,6 +1,6 @@ package info.nightscout.androidaps.plugins.configBuilder; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; 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 index 0360ba4a68..7c92cd98b3 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/ProfileFunctions.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/ProfileFunctions.java @@ -2,7 +2,7 @@ package info.nightscout.androidaps.plugins.configBuilder; import android.content.Intent; import android.os.Bundle; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.firebase.analytics.FirebaseAnalytics; import com.squareup.otto.Subscribe; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/ObjectivesFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/ObjectivesFragment.java index b943571089..7600c017c2 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/ObjectivesFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/ObjectivesFragment.java @@ -4,11 +4,11 @@ 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 androidx.annotation.NonNull; +import androidx.cardview.widget.CardView; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.LinearSmoothScroller; +import androidx.recyclerview.widget.RecyclerView; import android.text.Html; import android.view.LayoutInflater; import android.view.View; 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 index 83abe15688..55aba1b49f 100644 --- 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 @@ -1,6 +1,6 @@ package info.nightscout.androidaps.plugins.constraints.objectives.objectives; -import android.support.annotation.StringRes; +import androidx.annotation.StringRes; import java.util.ArrayList; import java.util.Date; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/safety/SafetyPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/safety/SafetyPlugin.java index 65dc119c6a..127752d8dc 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/safety/SafetyPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/safety/SafetyPlugin.java @@ -13,10 +13,10 @@ 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.plugins.configBuilder.ConfigBuilderPlugin; 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.general.overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin; @@ -196,7 +196,7 @@ public class SafetyPlugin extends PluginBase implements ConstraintsInterface { PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump(); if (pump != null) { - double rounded = Round.roundTo(insulin.value(), pump.getPumpDescription().pumpType.determineCorrectBolusSize(insulin.value())); + double rounded = pump.getPumpDescription().pumpType.determineCorrectBolusSize(insulin.value()); insulin.setIfDifferent(rounded, MainApp.gs(R.string.pumplimit), this); } return insulin; @@ -213,7 +213,7 @@ public class SafetyPlugin extends PluginBase implements ConstraintsInterface { PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump(); if (pump != null) { - double rounded = Round.roundTo(insulin.value(), pump.getPumpDescription().pumpType.determineCorrectExtendedBolusSize(insulin.value())); + double rounded = pump.getPumpDescription().pumpType.determineCorrectExtendedBolusSize(insulin.value()); insulin.setIfDifferent(rounded, MainApp.gs(R.string.pumplimit), this); } return insulin; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsFragment.java index ff99978fed..11428ce204 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsFragment.java @@ -5,8 +5,8 @@ import android.app.Activity; import android.content.Intent; import android.graphics.drawable.Drawable; import android.os.Bundle; -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentManager; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/dialogs/FillDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/dialogs/FillDialog.java index 94d548a444..e5ba4b9a13 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/dialogs/FillDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/dialogs/FillDialog.java @@ -3,8 +3,8 @@ package info.nightscout.androidaps.plugins.general.actions.dialogs; import android.content.Context; import android.content.Intent; import android.os.Bundle; -import android.support.v4.app.DialogFragment; -import android.support.v7.app.AlertDialog; +import androidx.fragment.app.DialogFragment; +import androidx.appcompat.app.AlertDialog; import android.text.Editable; import android.text.Html; import android.text.TextWatcher; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/dialogs/NewExtendedBolusDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/dialogs/NewExtendedBolusDialog.java index 579e9e2f06..9b5b7af515 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/dialogs/NewExtendedBolusDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/dialogs/NewExtendedBolusDialog.java @@ -4,8 +4,8 @@ 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 androidx.fragment.app.DialogFragment; +import androidx.appcompat.app.AlertDialog; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/dialogs/NewTempBasalDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/dialogs/NewTempBasalDialog.java index 80969b51b0..30b6e60dbd 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/dialogs/NewTempBasalDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/dialogs/NewTempBasalDialog.java @@ -3,8 +3,8 @@ package info.nightscout.androidaps.plugins.general.actions.dialogs; 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 androidx.fragment.app.DialogFragment; +import androidx.appcompat.app.AlertDialog; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/careportal/CareportalFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/careportal/CareportalFragment.java index 991fc962ee..ab98682fb4 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/careportal/CareportalFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/careportal/CareportalFragment.java @@ -4,7 +4,7 @@ package info.nightscout.androidaps.plugins.general.careportal; import android.app.Activity; import android.graphics.Color; import android.os.Bundle; -import android.support.v4.app.FragmentManager; +import androidx.fragment.app.FragmentManager; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/careportal/Dialogs/NewNSTreatmentDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/careportal/Dialogs/NewNSTreatmentDialog.java index e94cc658ca..078b3fc1ce 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/careportal/Dialogs/NewNSTreatmentDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/careportal/Dialogs/NewNSTreatmentDialog.java @@ -3,8 +3,8 @@ package info.nightscout.androidaps.plugins.general.careportal.Dialogs; import android.app.Activity; import android.os.Bundle; -import android.support.v4.app.DialogFragment; -import android.support.v7.app.AlertDialog; +import androidx.fragment.app.DialogFragment; +import androidx.appcompat.app.AlertDialog; import android.text.Editable; import android.text.TextWatcher; import android.text.format.DateFormat; @@ -39,7 +39,7 @@ import java.util.List; 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.Profile; import info.nightscout.androidaps.data.ProfileStore; import info.nightscout.androidaps.db.BgReading; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/food/FoodFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/food/FoodFragment.java index 6eb55db266..66727f0f7f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/food/FoodFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/food/FoodFragment.java @@ -4,9 +4,9 @@ import android.app.Activity; import android.content.DialogInterface; import android.graphics.Paint; import android.os.Bundle; -import android.support.v7.app.AlertDialog; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; +import androidx.appcompat.app.AlertDialog; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; import android.text.Editable; import android.text.TextWatcher; import android.view.LayoutInflater; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/food/FoodService.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/food/FoodService.java index 2d8d5f847b..3856ecfc22 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/food/FoodService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/food/FoodService.java @@ -3,7 +3,7 @@ package info.nightscout.androidaps.plugins.general.food; import android.content.Intent; import android.os.Bundle; 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; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/ImportExportPrefs.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/ImportExportPrefs.java index 67bf604f41..ea56115347 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/ImportExportPrefs.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/ImportExportPrefs.java @@ -8,9 +8,9 @@ import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.os.Environment; import android.preference.PreferenceManager; -import android.support.v4.app.ActivityCompat; -import android.support.v4.app.Fragment; -import android.support.v4.content.ContextCompat; +import androidx.core.app.ActivityCompat; +import androidx.fragment.app.Fragment; +import androidx.core.content.ContextCompat; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/MaintenanceFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/MaintenanceFragment.java index e0e9b58253..6b8863242a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/MaintenanceFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/MaintenanceFragment.java @@ -2,8 +2,8 @@ package info.nightscout.androidaps.plugins.general.maintenance; import android.content.Intent; import android.os.Bundle; -import android.support.v4.app.Fragment; -import android.support.v7.app.AlertDialog; +import androidx.fragment.app.Fragment; +import androidx.appcompat.app.AlertDialog; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/MaintenancePlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/MaintenancePlugin.java index 35bd9f9d06..1bad189aba 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/MaintenancePlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/MaintenancePlugin.java @@ -3,7 +3,7 @@ package info.nightscout.androidaps.plugins.general.maintenance; import android.content.Context; import android.content.Intent; import android.net.Uri; -import android.support.v4.content.FileProvider; +import androidx.core.content.FileProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/activities/LogSettingActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/activities/LogSettingActivity.java index 9d7681ae38..852554ed06 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/activities/LogSettingActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/activities/LogSettingActivity.java @@ -1,7 +1,7 @@ package info.nightscout.androidaps.plugins.general.maintenance.activities; import android.os.Bundle; -import android.support.v7.app.AppCompatActivity; +import androidx.appcompat.app.AppCompatActivity; import android.view.View; import android.widget.CheckBox; import android.widget.LinearLayout; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientPlugin.java index 1947c5911d..b5ff92ee0e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientPlugin.java @@ -22,6 +22,7 @@ import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.plugins.bus.RxBus; import info.nightscout.androidaps.events.EventAppExit; import info.nightscout.androidaps.events.EventChargingState; import info.nightscout.androidaps.events.EventNetworkChange; @@ -213,6 +214,7 @@ public class NSClientPlugin extends PluginBase { SP.putBoolean(R.string.key_nsclientinternal_paused, newState); paused = newState; MainApp.bus().post(new EventPreferenceChange(R.string.key_nsclientinternal_paused)); + RxBus.INSTANCE.send(new EventPreferenceChange(R.string.key_nsclientinternal_paused)); } public UploadQueue queue() { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSUpload.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSUpload.java index 40a411694b..881593b32a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSUpload.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSUpload.java @@ -7,8 +7,8 @@ import android.content.pm.ResolveInfo; import android.os.Build; import android.os.Bundle; import android.preference.PreferenceManager; -import android.support.annotation.Nullable; -import android.support.v4.content.LocalBroadcastManager; +import androidx.annotation.Nullable; +import androidx.localbroadcastmanager.content.LocalBroadcastManager; import org.apache.commons.lang3.StringUtils; import org.json.JSONArray; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NsClientReceiverDelegate.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NsClientReceiverDelegate.java index 8eeee8c43c..00d8d933ec 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NsClientReceiverDelegate.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NsClientReceiverDelegate.java @@ -10,6 +10,7 @@ import com.squareup.otto.Bus; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.plugins.bus.RxBus; import info.nightscout.androidaps.events.EventChargingState; import info.nightscout.androidaps.events.EventNetworkChange; import info.nightscout.androidaps.events.EventPreferenceChange; @@ -99,6 +100,7 @@ class NsClientReceiverDelegate { if (newAllowedState != allowed) { allowed = newAllowedState; bus.post(new EventPreferenceChange(R.string.key_nsclientinternal_paused)); + RxBus.INSTANCE.send(new EventPreferenceChange(R.string.key_nsclientinternal_paused)); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastAckAlarm.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastAckAlarm.java index 6873b59515..7179231068 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastAckAlarm.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastAckAlarm.java @@ -3,7 +3,7 @@ package info.nightscout.androidaps.plugins.general.nsclient.broadcasts; import android.content.Context; import android.content.Intent; import android.os.Bundle; -import android.support.v4.content.LocalBroadcastManager; +import androidx.localbroadcastmanager.content.LocalBroadcastManager; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastAlarm.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastAlarm.java index 9c1e3e7ae2..ce1de70900 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastAlarm.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastAlarm.java @@ -3,7 +3,7 @@ package info.nightscout.androidaps.plugins.general.nsclient.broadcasts; import android.content.Context; import android.content.Intent; import android.os.Bundle; -import android.support.v4.content.LocalBroadcastManager; +import androidx.localbroadcastmanager.content.LocalBroadcastManager; import org.json.JSONObject; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastAnnouncement.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastAnnouncement.java index b26c055851..f97f750287 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastAnnouncement.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastAnnouncement.java @@ -3,7 +3,7 @@ package info.nightscout.androidaps.plugins.general.nsclient.broadcasts; import android.content.Context; import android.content.Intent; import android.os.Bundle; -import android.support.v4.content.LocalBroadcastManager; +import androidx.localbroadcastmanager.content.LocalBroadcastManager; import org.json.JSONObject; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastCals.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastCals.java index 7d5dcddadc..83f3c0a0e4 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastCals.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastCals.java @@ -3,7 +3,7 @@ package info.nightscout.androidaps.plugins.general.nsclient.broadcasts; import android.content.Context; import android.content.Intent; import android.os.Bundle; -import android.support.v4.content.LocalBroadcastManager; +import androidx.localbroadcastmanager.content.LocalBroadcastManager; import org.json.JSONArray; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastClearAlarm.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastClearAlarm.java index fe9a194ca2..3f0586e65e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastClearAlarm.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastClearAlarm.java @@ -3,7 +3,7 @@ package info.nightscout.androidaps.plugins.general.nsclient.broadcasts; import android.content.Context; import android.content.Intent; import android.os.Bundle; -import android.support.v4.content.LocalBroadcastManager; +import androidx.localbroadcastmanager.content.LocalBroadcastManager; import org.json.JSONObject; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastDeviceStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastDeviceStatus.java index 412c321817..4631834d9b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastDeviceStatus.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastDeviceStatus.java @@ -3,7 +3,7 @@ package info.nightscout.androidaps.plugins.general.nsclient.broadcasts; import android.content.Context; import android.content.Intent; import android.os.Bundle; -import android.support.v4.content.LocalBroadcastManager; +import androidx.localbroadcastmanager.content.LocalBroadcastManager; import org.json.JSONArray; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastFood.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastFood.java index 0a8c21251b..35a2315ff2 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastFood.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastFood.java @@ -3,7 +3,7 @@ package info.nightscout.androidaps.plugins.general.nsclient.broadcasts; import android.content.Context; import android.content.Intent; import android.os.Bundle; -import android.support.v4.content.LocalBroadcastManager; +import androidx.localbroadcastmanager.content.LocalBroadcastManager; import org.json.JSONArray; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastMbgs.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastMbgs.java index 9c059ae8a2..248e5d627f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastMbgs.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastMbgs.java @@ -3,7 +3,7 @@ package info.nightscout.androidaps.plugins.general.nsclient.broadcasts; import android.content.Context; import android.content.Intent; import android.os.Bundle; -import android.support.v4.content.LocalBroadcastManager; +import androidx.localbroadcastmanager.content.LocalBroadcastManager; import org.json.JSONArray; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastProfile.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastProfile.java index 9411ed6e9e..d6d051e327 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastProfile.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastProfile.java @@ -3,7 +3,7 @@ package info.nightscout.androidaps.plugins.general.nsclient.broadcasts; import android.content.Context; import android.content.Intent; import android.os.Bundle; -import android.support.v4.content.LocalBroadcastManager; +import androidx.localbroadcastmanager.content.LocalBroadcastManager; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastSgvs.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastSgvs.java index 04e957811d..06fd3c0a35 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastSgvs.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastSgvs.java @@ -3,7 +3,7 @@ package info.nightscout.androidaps.plugins.general.nsclient.broadcasts; import android.content.Context; import android.content.Intent; import android.os.Bundle; -import android.support.v4.content.LocalBroadcastManager; +import androidx.localbroadcastmanager.content.LocalBroadcastManager; import org.json.JSONArray; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastStatus.java index c037acc9bb..81de2248e4 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastStatus.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastStatus.java @@ -4,7 +4,7 @@ import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.os.Bundle; -import android.support.v4.content.LocalBroadcastManager; +import androidx.localbroadcastmanager.content.LocalBroadcastManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastTreatment.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastTreatment.java index e4ca7b577f..a364d0d4ae 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastTreatment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastTreatment.java @@ -2,7 +2,7 @@ package info.nightscout.androidaps.plugins.general.nsclient.broadcasts; import android.content.Intent; import android.os.Bundle; -import android.support.v4.content.LocalBroadcastManager; +import androidx.localbroadcastmanager.content.LocalBroadcastManager; import org.json.JSONArray; import org.json.JSONException; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastUrgentAlarm.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastUrgentAlarm.java index 676dbe909d..b6b1c4f8d9 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastUrgentAlarm.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/broadcasts/BroadcastUrgentAlarm.java @@ -3,7 +3,7 @@ package info.nightscout.androidaps.plugins.general.nsclient.broadcasts; import android.content.Context; import android.content.Intent; import android.os.Bundle; -import android.support.v4.content.LocalBroadcastManager; +import androidx.localbroadcastmanager.content.LocalBroadcastManager; import org.json.JSONObject; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/data/NSSettingsStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/data/NSSettingsStatus.java index 8511247e42..93cf70dd12 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/data/NSSettingsStatus.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/data/NSSettingsStatus.java @@ -3,7 +3,7 @@ package info.nightscout.androidaps.plugins.general.nsclient.data; import android.content.Intent; import android.content.pm.PackageManager; import android.os.Bundle; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import org.json.JSONException; import org.json.JSONObject; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/receivers/RestartReceiver.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/receivers/RestartReceiver.java index 0b221ee456..5024801827 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/receivers/RestartReceiver.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/receivers/RestartReceiver.java @@ -2,7 +2,7 @@ package info.nightscout.androidaps.plugins.general.nsclient.receivers; import android.content.Context; import android.content.Intent; -import android.support.v4.content.WakefulBroadcastReceiver; +import androidx.legacy.content.WakefulBroadcastReceiver; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.java index c4d8655ca8..31df9c233e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.java @@ -3,7 +3,7 @@ package info.nightscout.androidaps.plugins.general.overview; import android.annotation.SuppressLint; import android.app.Activity; import android.app.NotificationManager; -import android.arch.core.util.Function; +import androidx.arch.core.util.Function; import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; @@ -12,14 +12,14 @@ import android.graphics.Color; import android.graphics.Paint; import android.os.Bundle; import android.os.Handler; -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentActivity; -import android.support.v4.app.FragmentManager; -import android.support.v4.content.res.ResourcesCompat; -import android.support.v7.app.AlertDialog; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.PopupMenu; -import android.support.v7.widget.RecyclerView; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentActivity; +import androidx.fragment.app.FragmentManager; +import androidx.core.content.res.ResourcesCompat; +import androidx.appcompat.app.AlertDialog; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.appcompat.widget.PopupMenu; +import androidx.recyclerview.widget.RecyclerView; import android.text.SpannableString; import android.text.style.ForegroundColorSpan; import android.util.DisplayMetrics; @@ -37,12 +37,9 @@ import android.widget.TextView; import com.jjoe64.graphview.GraphView; 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.Calendar; import java.util.Date; import java.util.Locale; @@ -55,8 +52,6 @@ import info.nightscout.androidaps.Config; 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.GlucoseStatus; import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.QuickWizardEntry; @@ -94,24 +89,21 @@ import info.nightscout.androidaps.plugins.general.careportal.OptionsToShow; import info.nightscout.androidaps.plugins.general.nsclient.NSUpload; import info.nightscout.androidaps.plugins.general.nsclient.data.NSDeviceStatus; import info.nightscout.androidaps.plugins.general.nsclient.data.NSSettingsStatus; +import info.nightscout.androidaps.plugins.general.overview.activities.QuickWizardListActivity; import info.nightscout.androidaps.plugins.general.overview.dialogs.CalibrationDialog; -import info.nightscout.androidaps.plugins.general.overview.dialogs.ErrorHelperActivity; import info.nightscout.androidaps.plugins.general.overview.dialogs.NewCarbsDialog; import info.nightscout.androidaps.plugins.general.overview.dialogs.NewInsulinDialog; import info.nightscout.androidaps.plugins.general.overview.dialogs.NewTreatmentDialog; import info.nightscout.androidaps.plugins.general.overview.dialogs.WizardDialog; -import info.nightscout.androidaps.plugins.general.overview.activities.QuickWizardListActivity; import info.nightscout.androidaps.plugins.general.overview.graphData.GraphData; -import info.nightscout.androidaps.plugins.general.overview.notifications.NotificationRecyclerViewAdapter; -import info.nightscout.androidaps.plugins.general.overview.notifications.NotificationStore; import info.nightscout.androidaps.plugins.general.wear.ActionStringHandler; import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensData; 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.iob.iobCobCalculator.events.EventAutosensCalculationFinished; import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventIobCalculationProgress; -import info.nightscout.androidaps.plugins.source.SourceDexcomG5Plugin; -import info.nightscout.androidaps.plugins.source.SourceDexcomG6Plugin; +import info.nightscout.androidaps.plugins.source.SourceDexcomPlugin; import info.nightscout.androidaps.plugins.source.SourceXdripPlugin; import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; import info.nightscout.androidaps.plugins.treatments.fragments.ProfileViewerDialog; @@ -197,7 +189,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, Handler sLoopHandler = new Handler(); Runnable sRefreshLoop = null; - public enum CHARTTYPE {PRE, BAS, IOB, COB, DEV, SEN, DEVSLOPE} + public enum CHARTTYPE {PRE, BAS, IOB, COB, DEV, SEN, ACTPRIM, ACTSEC, DEVSLOPE} private static final ScheduledExecutorService worker = Executors.newSingleThreadScheduledExecutor(); private static ScheduledFuture scheduledUpdate = null; @@ -358,14 +350,15 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, else predictionsAvailable = false; - MenuItem item; + MenuItem item,dividerItem; CharSequence title; + int titleMaxChars = 0; SpannableString s; PopupMenu popup = new PopupMenu(v.getContext(), v); - if (predictionsAvailable) { item = popup.getMenu().add(Menu.NONE, CHARTTYPE.PRE.ordinal(), Menu.NONE, "Predictions"); title = item.getTitle(); + if (titleMaxChars < title.length()) titleMaxChars = title.length(); s = new SpannableString(title); s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.prediction, null)), 0, s.length(), 0); item.setTitle(s); @@ -375,14 +368,28 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, item = popup.getMenu().add(Menu.NONE, 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(SP.getBoolean("showbasals", true)); + item = popup.getMenu().add(Menu.NONE, 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(SP.getBoolean("showactivityprimary", true)); + + dividerItem = popup.getMenu().add(""); + dividerItem.setEnabled(false); + item = popup.getMenu().add(Menu.NONE, 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); @@ -391,6 +398,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, item = popup.getMenu().add(Menu.NONE, 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); @@ -399,6 +407,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, item = popup.getMenu().add(Menu.NONE, 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); @@ -407,15 +416,26 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, item = popup.getMenu().add(Menu.NONE, 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(SP.getBoolean("showratios", false)); + item = popup.getMenu().add(Menu.NONE, 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(SP.getBoolean("showactivitysecondary", true)); + if (MainApp.devBranch) { item = popup.getMenu().add(Menu.NONE, 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); @@ -423,6 +443,10 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, item.setChecked(SP.getBoolean("showdevslope", false)); } + // Fairly good guestimate for required divider text size... + title = new String(new char[titleMaxChars+10]).replace("\0", "_"); + dividerItem.setTitle(title); + popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { @@ -438,6 +462,10 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, SP.putBoolean("showdeviations", !item.isChecked()); } else if (item.getItemId() == CHARTTYPE.SEN.ordinal()) { SP.putBoolean("showratios", !item.isChecked()); + } else if (item.getItemId() == CHARTTYPE.ACTPRIM.ordinal()) { + SP.putBoolean("showactivityprimary", !item.isChecked()); + } else if (item.getItemId() == CHARTTYPE.ACTSEC.ordinal()) { + SP.putBoolean("showactivitysecondary", !item.isChecked()); } else if (item.getItemId() == CHARTTYPE.DEVSLOPE.ordinal()) { SP.putBoolean("showdevslope", !item.isChecked()); } @@ -663,8 +691,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, @Override public void onClick(View v) { boolean xdrip = SourceXdripPlugin.getPlugin().isEnabled(PluginType.BGSOURCE); - boolean g5 = SourceDexcomG5Plugin.getPlugin().isEnabled(PluginType.BGSOURCE); - boolean g6 = SourceDexcomG6Plugin.getPlugin().isEnabled(PluginType.BGSOURCE); + boolean dexcom = SourceDexcomPlugin.INSTANCE.isEnabled(PluginType.BGSOURCE); String units = ProfileFunctions.getInstance().getProfileUnits(); FragmentManager manager = getFragmentManager(); @@ -687,10 +714,16 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, if (xdrip) { CalibrationDialog calibrationDialog = new CalibrationDialog(); calibrationDialog.show(manager, "CalibrationDialog"); - } else if (g5 || g6) { + } else if (dexcom) { try { - Intent i = new Intent("com.dexcom.cgm.activities.MeterEntryActivity"); - startActivity(i); + String packageName = SourceDexcomPlugin.INSTANCE.findDexcomPackageName(); + if (packageName != null) { + Intent i = new Intent("com.dexcom.cgm.activities.MeterEntryActivity"); + i.setPackage(packageName); + startActivity(i); + } else { + ToastUtils.showToastInUiThread(getActivity(), MainApp.gs(R.string.dexcom_app_not_installed)); + } } catch (ActivityNotFoundException e) { ToastUtils.showToastInUiThread(getActivity(), MainApp.gs(R.string.g5appnotdetected)); } @@ -699,14 +732,14 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, case R.id.overview_cgmbutton: if (xdrip) openCgmApp("com.eveningoutpost.dexdrip"); - else if (g5 && units.equals(Constants.MGDL)) - openCgmApp("com.dexcom.cgm.region5.mgdl"); - else if (g5 && units.equals(Constants.MMOL)) - openCgmApp("com.dexcom.cgm.region5.mmol"); - else if (g6 && units.equals(Constants.MGDL)) - openCgmApp("com.dexcom.g6.region3.mgdl"); - else if (g6 && units.equals(Constants.MMOL)) - openCgmApp("com.dexcom.g6.region3.mmol"); + else if (dexcom) { + String packageName = SourceDexcomPlugin.INSTANCE.findDexcomPackageName(); + if (packageName != null) { + openCgmApp(packageName); + } else { + ToastUtils.showToastInUiThread(getActivity(), MainApp.gs(R.string.dexcom_app_not_installed)); + } + } break; case R.id.overview_treatmentbutton: NewTreatmentDialog treatmentDialogFragment = new NewTreatmentDialog(); @@ -783,122 +816,25 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, void onClickQuickwizard() { final BgReading actualBg = DatabaseHelper.actualBg(); final Profile profile = ProfileFunctions.getInstance().getProfile(); - final TempTarget tempTarget = TreatmentsPlugin.getPlugin().getTempTargetFromHistory(); + final String profileName = ProfileFunctions.getInstance().getProfileName(); + final PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump(); final QuickWizardEntry quickWizardEntry = OverviewPlugin.getPlugin().quickWizard.getActive(); - if (quickWizardEntry != null && actualBg != null && profile != null) { + if (quickWizardEntry != null && actualBg != null && profile != null && pump != null) { quickWizardButton.setVisibility(View.VISIBLE); - final BolusWizard wizard = quickWizardEntry.doCalc(profile, tempTarget, actualBg, true); + final BolusWizard wizard = quickWizardEntry.doCalc(profile, profileName, actualBg, true); - final JSONObject boluscalcJSON = new JSONObject(); - try { - 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("bolusiobused", true); - boluscalcJSON.put("basaliobused", true); - boluscalcJSON.put("bg", actualBg.valueToUnits(profile.getUnits())); - boluscalcJSON.put("insulinbg", wizard.insulinFromBG); - boluscalcJSON.put("insulinbgused", true); - boluscalcJSON.put("bgdiff", wizard.bgDiff); - boluscalcJSON.put("insulincarbs", wizard.insulinFromCarbs); - boluscalcJSON.put("carbs", quickWizardEntry.carbs()); - boluscalcJSON.put("othercorrection", 0d); - boluscalcJSON.put("insulintrend", wizard.insulinFromTrend); - boluscalcJSON.put("insulin", wizard.calculatedTotalInsulin); - } catch (JSONException e) { - log.error("Unhandled exception", e); - } - if (wizard.calculatedTotalInsulin > 0d && quickWizardEntry.carbs() > 0d) { - DecimalFormat formatNumber2decimalplaces = new DecimalFormat("0.00"); - String confirmMessage = MainApp.gs(R.string.entertreatmentquestion); - - Double insulinAfterConstraints = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(wizard.calculatedTotalInsulin)).value(); + if (wizard.getCalculatedTotalInsulin() > 0d && quickWizardEntry.carbs() > 0d) { Integer carbsAfterConstraints = MainApp.getConstraintChecker().applyCarbsConstraints(new Constraint<>(quickWizardEntry.carbs())).value(); - confirmMessage += "\n" + MainApp.gs(R.string.bolus) + ": " + formatNumber2decimalplaces.format(insulinAfterConstraints) + "U"; - confirmMessage += "\n" + MainApp.gs(R.string.carbs) + ": " + carbsAfterConstraints + "g"; - - if (Math.abs(insulinAfterConstraints - wizard.calculatedTotalInsulin) >= 0.01 || !carbsAfterConstraints.equals(quickWizardEntry.carbs())) { - AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); - builder.setTitle(MainApp.gs(R.string.treatmentdeliveryerror)); - builder.setMessage(MainApp.gs(R.string.constraints_violation) + "\n" + MainApp.gs(R.string.changeyourinput)); - builder.setPositiveButton(MainApp.gs(R.string.ok), null); - builder.show(); + if (Math.abs(wizard.getInsulinAfterConstraints() - wizard.getCalculatedTotalInsulin()) >= pump.getPumpDescription().pumpType.determineCorrectBolusStepSize(wizard.getInsulinAfterConstraints()) || !carbsAfterConstraints.equals(quickWizardEntry.carbs())) { + OKDialog.show(getContext(), MainApp.gs(R.string.treatmentdeliveryerror), MainApp.gs(R.string.constraints_violation) + "\n" + MainApp.gs(R.string.changeyourinput), null); return; } - final Double finalInsulinAfterConstraints = insulinAfterConstraints; - final Integer finalCarbsAfterConstraints = carbsAfterConstraints; - final Context context = getContext(); - final AlertDialog.Builder builder = new AlertDialog.Builder(context); - accepted = false; - builder.setTitle(MainApp.gs(R.string.confirmation)); - builder.setMessage(confirmMessage); - builder.setPositiveButton(MainApp.gs(R.string.ok), (dialog, id) -> { - synchronized (builder) { - if (accepted) { - if (L.isEnabled(L.OVERVIEW)) - log.debug("guarding: already accepted"); - return; - } - accepted = true; - if (Math.abs(insulinAfterConstraints - wizard.calculatedTotalInsulin) >= 0.01 || finalCarbsAfterConstraints > 0) { - if (wizard.superBolus) { - final LoopPlugin loopPlugin = LoopPlugin.getPlugin(); - if (loopPlugin.isEnabled(PluginType.LOOP)) { - loopPlugin.superBolusTo(System.currentTimeMillis() + T.hours(2).msecs()); - 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.boluscalc = boluscalcJSON; - detailedBolusInfo.source = Source.USER; - if (finalInsulinAfterConstraints > 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); - } - } - } - }); - builder.setNegativeButton(MainApp.gs(R.string.cancel), null); - builder.show(); + wizard.confirmAndExecute(getContext()); } } - } @Override @@ -1064,7 +1000,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, timeView.setText(DateUtil.timeString(new Date())); } - updateNotifications(); + OverviewPlugin.getPlugin().notificationStore.updateNotifications(notificationsView); pumpStatusLayout.setVisibility(View.GONE); loopStatusLayout.setVisibility(View.GONE); @@ -1083,6 +1019,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, final PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump(); final Profile profile = ProfileFunctions.getInstance().getProfile(); + final String profileName = ProfileFunctions.getInstance().getProfileName(); final String units = profile.getUnits(); final double lowLine = OverviewPlugin.getPlugin().determineLowLine(units); @@ -1190,10 +1127,10 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, // **** Calibration & CGM buttons **** boolean xDripIsBgSource = MainApp.getSpecificPlugin(SourceXdripPlugin.class) != null && MainApp.getSpecificPlugin(SourceXdripPlugin.class).isEnabled(PluginType.BGSOURCE); - boolean g5IsBgSource = MainApp.getSpecificPlugin(SourceDexcomG5Plugin.class) != null && MainApp.getSpecificPlugin(SourceDexcomG5Plugin.class).isEnabled(PluginType.BGSOURCE); + boolean dexcomIsSource = SourceDexcomPlugin.INSTANCE.isEnabled(PluginType.BGSOURCE); boolean bgAvailable = DatabaseHelper.actualBg() != null; if (calibrationButton != null) { - if ((xDripIsBgSource || g5IsBgSource) && bgAvailable && SP.getBoolean(R.string.key_show_calibration_button, true)) { + if ((xDripIsBgSource || dexcomIsSource) && bgAvailable && SP.getBoolean(R.string.key_show_calibration_button, true)) { calibrationButton.setVisibility(View.VISIBLE); } else { calibrationButton.setVisibility(View.GONE); @@ -1202,7 +1139,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, if (cgmButton != null) { if (xDripIsBgSource && SP.getBoolean(R.string.key_show_cgm_button, false)) { cgmButton.setVisibility(View.VISIBLE); - } else if (g5IsBgSource && SP.getBoolean(R.string.key_show_cgm_button, false)) { + } else if (dexcomIsSource && SP.getBoolean(R.string.key_show_cgm_button, false)) { cgmButton.setVisibility(View.VISIBLE); } else { cgmButton.setVisibility(View.GONE); @@ -1280,10 +1217,10 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, if (quickWizardEntry != null && lastBG != null && pump.isInitialized() && !pump.isSuspended()) { quickWizardButton.setVisibility(View.VISIBLE); String text = quickWizardEntry.buttonText() + "\n" + DecimalFormatter.to0Decimal(quickWizardEntry.carbs()) + "g"; - BolusWizard wizard = quickWizardEntry.doCalc(profile, tempTarget, lastBG, false); - text += " " + DecimalFormatter.toPumpSupportedBolus(wizard.calculatedTotalInsulin) + "U"; + BolusWizard wizard = quickWizardEntry.doCalc(profile, profileName, lastBG, false); + text += " " + DecimalFormatter.toPumpSupportedBolus(wizard.getCalculatedTotalInsulin()) + "U"; quickWizardButton.setText(text); - if (wizard.calculatedTotalInsulin <= 0) + if (wizard.getCalculatedTotalInsulin() <= 0) quickWizardButton.setVisibility(View.GONE); } else quickWizardButton.setVisibility(View.GONE); @@ -1523,6 +1460,10 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, // set manual x bounds to have nice steps graphData.formatAxis(fromTime, endTime); + if(SP.getBoolean("showactivityprimary", true)) { + graphData.addActivity(fromTime, endTime, false,1d); + } + // Treatments graphData.addTreatments(fromTime, endTime); @@ -1548,6 +1489,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, boolean useDevForScale = false; boolean useRatioForScale = false; boolean useDSForScale = false; + boolean useIAForScale = false; if (SP.getBoolean("showiob", true)) { useIobForScale = true; @@ -1557,6 +1499,8 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, useDevForScale = true; } else if (SP.getBoolean("showratios", false)) { useRatioForScale = true; + } else if (SP.getBoolean("showactivitysecondary", false)) { + useIAForScale = true; } else if (SP.getBoolean("showdevslope", false)) { useDSForScale = true; } @@ -1569,6 +1513,8 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, secondGraphData.addDeviations(fromTime, now, useDevForScale, 1d); if (SP.getBoolean("showratios", false)) secondGraphData.addRatio(fromTime, now, useRatioForScale, 1d); + if(SP.getBoolean("showactivitysecondary", true)) + secondGraphData.addActivity(fromTime, endTime, useIAForScale,useIAForScale ? 2d: 1d); if (SP.getBoolean("showdevslope", false) && MainApp.devBranch) secondGraphData.addDeviationSlope(fromTime, now, useDSForScale, 1d); @@ -1585,6 +1531,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, || SP.getBoolean("showcob", true) || SP.getBoolean("showdeviations", false) || SP.getBoolean("showratios", false) + || SP.getBoolean("showactivitysecondary", false) || SP.getBoolean("showdevslope", false)) { iobGraph.setVisibility(View.VISIBLE); } else { @@ -1603,21 +1550,6 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, Profiler.log(log, from, updateGUIStart); } - //Notifications - - void updateNotifications() { - NotificationStore nstore = OverviewPlugin.getPlugin().notificationStore; - nstore.removeExpired(); - nstore.unSnooze(); - if (nstore.store.size() > 0) { - NotificationRecyclerViewAdapter adapter = new NotificationRecyclerViewAdapter(nstore.store); - notificationsView.setAdapter(adapter); - notificationsView.setVisibility(View.VISIBLE); - } else { - notificationsView.setVisibility(View.GONE); - } - } - public static void applyStatuslight(TextView view, String text, double value, double warnThreshold, double urgentThreshold, double invalid, boolean checkAscending) { Function check = checkAscending ? (Double threshold) -> value >= threshold : (Double threshold) -> value <= threshold; if (value != invalid) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/activities/QuickWizardListActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/activities/QuickWizardListActivity.java index d7eb9c86dd..85adbf7e80 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/activities/QuickWizardListActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/activities/QuickWizardListActivity.java @@ -2,11 +2,11 @@ package info.nightscout.androidaps.plugins.general.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 androidx.fragment.app.FragmentManager; +import androidx.appcompat.app.AppCompatActivity; +import androidx.cardview.widget.CardView; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/BolusProgressDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/BolusProgressDialog.java index 4189fcdcdb..1b41ea0c44 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/BolusProgressDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/BolusProgressDialog.java @@ -4,7 +4,7 @@ package info.nightscout.androidaps.plugins.general.overview.dialogs; import android.app.Activity; import android.os.Bundle; import android.os.SystemClock; -import android.support.v4.app.DialogFragment; +import androidx.fragment.app.DialogFragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/BolusProgressHelperActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/BolusProgressHelperActivity.java index fd1de6ce8c..7ca19d0334 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/BolusProgressHelperActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/BolusProgressHelperActivity.java @@ -1,7 +1,7 @@ package info.nightscout.androidaps.plugins.general.overview.dialogs; import android.os.Bundle; -import android.support.v7.app.AppCompatActivity; +import androidx.appcompat.app.AppCompatActivity; /** * Created by adrian on 09/02/17. diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/CalibrationDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/CalibrationDialog.java index 53c571aad7..7ec20254f2 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/CalibrationDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/CalibrationDialog.java @@ -3,7 +3,7 @@ package info.nightscout.androidaps.plugins.general.overview.dialogs; import android.content.Context; import android.os.Bundle; -import android.support.v4.app.DialogFragment; +import androidx.fragment.app.DialogFragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -18,7 +18,7 @@ import java.text.DecimalFormat; 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.Profile; import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; import info.nightscout.androidaps.utils.NumberPicker; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/EditQuickWizardDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/EditQuickWizardDialog.java index 9cd1277961..248ab30d7c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/EditQuickWizardDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/EditQuickWizardDialog.java @@ -2,7 +2,7 @@ package info.nightscout.androidaps.plugins.general.overview.dialogs; import android.os.Bundle; -import android.support.v4.app.DialogFragment; +import androidx.fragment.app.DialogFragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/ErrorDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/ErrorDialog.java index 209a585384..ea8dd8e4bb 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/ErrorDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/ErrorDialog.java @@ -2,8 +2,9 @@ package info.nightscout.androidaps.plugins.general.overview.dialogs; import android.content.Intent; +import android.os.Build; import android.os.Bundle; -import android.support.v4.app.DialogFragment; +import androidx.fragment.app.DialogFragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -98,7 +99,10 @@ public class ErrorDialog extends DialogFragment implements View.OnClickListener private void startAlarm() { Intent alarm = new Intent(MainApp.instance().getApplicationContext(), AlarmSoundService.class); alarm.putExtra("soundid", soundId); - MainApp.instance().startService(alarm); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) + MainApp.instance().startForegroundService(alarm); + else + MainApp.instance().startService(alarm); } private void stopAlarm() { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/ErrorHelperActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/ErrorHelperActivity.java index 667cadf2b1..86e7ac5461 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/ErrorHelperActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/ErrorHelperActivity.java @@ -1,7 +1,7 @@ package info.nightscout.androidaps.plugins.general.overview.dialogs; import android.os.Bundle; -import android.support.v7.app.AppCompatActivity; +import androidx.appcompat.app.AppCompatActivity; import info.nightscout.androidaps.R; import info.nightscout.androidaps.plugins.general.nsclient.NSUpload; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/NewCarbsDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/NewCarbsDialog.java index 789ced1df3..2a79a17bbd 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/NewCarbsDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/NewCarbsDialog.java @@ -2,8 +2,8 @@ package info.nightscout.androidaps.plugins.general.overview.dialogs; import android.os.Bundle; import android.os.HandlerThread; -import android.support.v4.app.DialogFragment; -import android.support.v7.app.AlertDialog; +import androidx.fragment.app.DialogFragment; +import androidx.appcompat.app.AlertDialog; import android.text.Editable; import android.text.Html; import android.text.TextWatcher; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/NewInsulinDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/NewInsulinDialog.java index 27e2e33ba7..ab43e0b6f0 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/NewInsulinDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/NewInsulinDialog.java @@ -4,8 +4,8 @@ import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.os.HandlerThread; -import android.support.v4.app.DialogFragment; -import android.support.v7.app.AlertDialog; +import androidx.fragment.app.DialogFragment; +import androidx.appcompat.app.AlertDialog; import android.text.Editable; import android.text.Html; import android.text.TextWatcher; @@ -225,7 +225,7 @@ public class NewInsulinDialog extends DialogFragment implements OnClickListener } } - if (Math.abs(insulinAfterConstraints - insulin) > pump.getPumpDescription().pumpType.determineCorrectBolusSize(insulinAfterConstraints)) + if (Math.abs(insulinAfterConstraints - insulin) > pump.getPumpDescription().pumpType.determineCorrectBolusStepSize(insulinAfterConstraints)) actions.add("" + MainApp.gs(R.string.bolusconstraintapplied) + ""); int eatingSoonTTDuration = SP.getInt(R.string.key_eatingsoon_duration, Constants.defaultEatingSoonTTDuration); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/NewTreatmentDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/NewTreatmentDialog.java index 837d206fb3..c3a9d76fb5 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/NewTreatmentDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/NewTreatmentDialog.java @@ -4,8 +4,8 @@ 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 androidx.fragment.app.DialogFragment; +import androidx.appcompat.app.AlertDialog; import android.text.Editable; import android.text.Html; import android.text.TextWatcher; @@ -141,7 +141,7 @@ public class NewTreatmentDialog extends DialogFragment implements OnClickListene if (recordOnlyCheckbox.isChecked()) { confirmMessage += "
" + MainApp.gs(R.string.bolusrecordedonly) + ""; } - if (Math.abs(insulinAfterConstraints - insulin) > pump.getPumpDescription().pumpType.determineCorrectBolusSize(insulinAfterConstraints) || !Objects.equals(carbsAfterConstraints, carbs)) + if (Math.abs(insulinAfterConstraints - insulin) > pump.getPumpDescription().pumpType.determineCorrectBolusStepSize(insulinAfterConstraints) || !Objects.equals(carbsAfterConstraints, carbs)) confirmMessage += "
" + MainApp.gs(R.string.bolusconstraintapplied) + ""; } if (carbsAfterConstraints > 0) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/WizardDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/WizardDialog.java index b4a3de4271..9638f3ef9b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/WizardDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/WizardDialog.java @@ -2,13 +2,10 @@ package info.nightscout.androidaps.plugins.general.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 androidx.fragment.app.DialogFragment; +import androidx.appcompat.app.AlertDialog; import android.text.Editable; -import android.text.Html; import android.text.TextWatcher; import android.view.LayoutInflater; import android.view.View; @@ -28,46 +25,35 @@ import android.widget.TextView; 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.EventRefreshOverview; import info.nightscout.androidaps.interfaces.Constraint; -import info.nightscout.androidaps.interfaces.PluginType; -import info.nightscout.androidaps.interfaces.PumpInterface; -import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin; import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; import info.nightscout.androidaps.plugins.iob.iobCobCalculator.CobInfo; import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin; import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutosensCalculationFinished; import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; -import info.nightscout.androidaps.queue.Callback; import info.nightscout.androidaps.utils.BolusWizard; -import info.nightscout.androidaps.utils.DateUtil; import info.nightscout.androidaps.utils.DecimalFormatter; import info.nightscout.androidaps.utils.NumberPicker; import info.nightscout.androidaps.utils.SP; import info.nightscout.androidaps.utils.SafeParse; +import info.nightscout.androidaps.utils.StringUtils; import info.nightscout.androidaps.utils.ToastUtils; public class WizardDialog extends DialogFragment implements OnClickListener, CompoundButton.OnCheckedChangeListener, Spinner.OnItemSelectedListener { @@ -108,8 +94,7 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com EditText notesEdit; Integer calculatedCarbs = 0; - Double calculatedTotalInsulin = 0d; - JSONObject boluscalcJSON; + BolusWizard wizard; Context context; @@ -311,99 +296,8 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com 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); - } - } - } - } - }); - builder.setNegativeButton(MainApp.gs(R.string.cancel), null); - builder.show(); - dismiss(); - } + wizard.confirmAndExecute(context); + dismiss(); break; case R.id.cancel: dismiss(); @@ -450,8 +344,8 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com TreatmentsPlugin.getPlugin().updateTotalIOBTempBasals(); IobTotal basalIob = TreatmentsPlugin.getPlugin().getLastCalculationTempBasals().round(); - bolusIobInsulin.setText(DecimalFormatter.to2Decimal(-bolusIob.iob) + "U"); - basalIobInsulin.setText(DecimalFormatter.to2Decimal(-basalIob.basaliob) + "U"); + bolusIobInsulin.setText(StringUtils.formatInsulin(-bolusIob.iob)); + basalIobInsulin.setText(StringUtils.formatInsulin(-basalIob.basaliob)); calculateInsulin(); } @@ -460,13 +354,13 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com ProfileStore profileStore = ConfigBuilderPlugin.getPlugin().getActiveProfileInterface().getProfile(); if (profileSpinner == null || profileSpinner.getSelectedItem() == null || profileStore == null) return; // not initialized yet - String selectedAlternativeProfile = profileSpinner.getSelectedItem().toString(); + String profileName = profileSpinner.getSelectedItem().toString(); Profile specificProfile; - if (selectedAlternativeProfile.equals(MainApp.gs(R.string.active))) { + if (profileName.equals(MainApp.gs(R.string.active))) { specificProfile = ProfileFunctions.getInstance().getProfile(); - selectedAlternativeProfile = ProfileFunctions.getInstance().getProfileName(); + profileName = ProfileFunctions.getInstance().getProfileName(); } else - specificProfile = profileStore.getSpecificProfile(selectedAlternativeProfile); + specificProfile = profileStore.getSpecificProfile(profileName); // Entered values Double c_bg = SafeParse.stringToDouble(editBg.getText()); @@ -494,104 +388,61 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com Double c_cob = 0d; if (cobCheckbox.isChecked()) { CobInfo cobInfo = IobCobCalculatorPlugin.getPlugin().getCobInfo(false, "Wizard COB"); - if (cobInfo != null && cobInfo.displayCob != null) + if (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()); + wizard = new BolusWizard(specificProfile, profileName, tempTarget, carbsAfterConstraint, c_cob, c_bg, corrAfterConstraint, 100d, bgCheckbox.isChecked(), cobCheckbox.isChecked(), bolusIobCheckbox.isChecked(), basalIobCheckbox.isChecked(), superbolusCheckbox.isChecked(), ttCheckbox.isChecked(), bgtrendCheckbox.isChecked(), notesEdit.getText().toString(), SafeParse.stringToInt(editCarbTime.getText())); - bg.setText(c_bg + " ISF: " + DecimalFormatter.to1Decimal(wizard.sens)); - bgInsulin.setText(DecimalFormatter.to2Decimal(wizard.insulinFromBG) + "U"); + bg.setText(c_bg + " ISF: " + DecimalFormatter.to1Decimal(wizard.getSens())); + bgInsulin.setText(StringUtils.formatInsulin(wizard.getInsulinFromBG())); - carbs.setText(DecimalFormatter.to0Decimal(c_carbs) + "g IC: " + DecimalFormatter.to1Decimal(wizard.ic)); - carbsInsulin.setText(DecimalFormatter.to2Decimal(wizard.insulinFromCarbs) + "U"); + carbs.setText(DecimalFormatter.to0Decimal(c_carbs) + "g IC: " + DecimalFormatter.to1Decimal(wizard.getIc())); + carbsInsulin.setText(StringUtils.formatInsulin(wizard.getInsulinFromCarbs())); - bolusIobInsulin.setText(DecimalFormatter.to2Decimal(wizard.insulingFromBolusIOB) + "U"); - basalIobInsulin.setText(DecimalFormatter.to2Decimal(wizard.insulingFromBasalsIOB) + "U"); + bolusIobInsulin.setText(StringUtils.formatInsulin(wizard.getInsulinFromBolusIOB())); + basalIobInsulin.setText(StringUtils.formatInsulin(wizard.getInsulinFromBasalsIOB())); - correctionInsulin.setText(DecimalFormatter.to2Decimal(wizard.insulinFromCorrection) + "U"); - calculatedTotalInsulin = wizard.calculatedTotalInsulin; + correctionInsulin.setText(StringUtils.formatInsulin(wizard.getInsulinFromCorrection())); calculatedCarbs = carbsAfterConstraint; // Superbolus - if (superbolusCheckbox.isChecked()) { - superbolus.setText("2h"); - } else { - superbolus.setText(""); - } - superbolusInsulin.setText(DecimalFormatter.to2Decimal(wizard.insulinFromSuperBolus) + "U"); + superbolus.setText(superbolusCheckbox.isChecked() ? MainApp.gs(R.string.twohours) : ""); + superbolusInsulin.setText(StringUtils.formatInsulin(wizard.getInsulinFromSuperBolus())); // 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(""); - } + if (bgtrendCheckbox.isChecked() && wizard.getGlucoseStatus() != null) { + bgTrend.setText( + (wizard.getTrend() > 0 ? "+" : "") + + Profile.toUnitsString(wizard.getTrend() * 3, wizard.getTrend() * 3 / Constants.MMOLL_TO_MGDL, specificProfile.getUnits()) + + " " + specificProfile.getUnits()); } else { bgTrend.setText(""); } - bgTrendInsulin.setText(DecimalFormatter.to2Decimal(wizard.insulinFromTrend) + "U"); + bgTrendInsulin.setText(StringUtils.formatInsulin(wizard.getInsulinFromTrend())); // COB if (cobCheckbox.isChecked()) { - cob.setText(DecimalFormatter.to2Decimal(c_cob) + "g IC: " + DecimalFormatter.to1Decimal(wizard.ic)); - cobInsulin.setText(DecimalFormatter.to2Decimal(wizard.insulinFromCOB) + "U"); + cob.setText(DecimalFormatter.to2Decimal(c_cob) + "g IC: " + DecimalFormatter.to1Decimal(wizard.getIc())); + cobInsulin.setText(StringUtils.formatInsulin(wizard.getInsulinFromCOB())); } else { cob.setText(""); cobInsulin.setText(""); } - if (calculatedTotalInsulin > 0d || calculatedCarbs > 0d) { - String insulinText = calculatedTotalInsulin > 0d ? (DecimalFormatter.toPumpSupportedBolus(calculatedTotalInsulin) + "U") : ""; + if (wizard.getCalculatedTotalInsulin() > 0d || calculatedCarbs > 0d) { + String insulinText = wizard.getCalculatedTotalInsulin() > 0d ? (DecimalFormatter.toPumpSupportedBolus(wizard.getCalculatedTotalInsulin()) + "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"); + total.setText(MainApp.gs(R.string.missing) + " " + DecimalFormatter.to0Decimal(wizard.getCarbsEquivalent()) + "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/general/overview/graphData/GraphData.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/graphData/GraphData.java index fae69f4d72..8c0f7f6326 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/graphData/GraphData.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/graphData/GraphData.java @@ -50,6 +50,7 @@ import info.nightscout.androidaps.plugins.treatments.Treatment; import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; import info.nightscout.androidaps.utils.DecimalFormatter; import info.nightscout.androidaps.utils.Round; +import info.nightscout.androidaps.utils.SP; /** * Created by mike on 18.10.2017. @@ -348,6 +349,59 @@ public class GraphData { ? Profile.fromMgdlToUnits(bgReadingsArray.get(0).value, units) : Profile.fromMgdlToUnits(100, units); } + public void addActivity(long fromTime, long toTime, boolean useForScale, double scale) { + FixedLineGraphSeries actSeriesHist; + List actArrayHist = new ArrayList<>(); + FixedLineGraphSeries actSeriesPred; + List actArrayPred = new ArrayList<>(); + + double now = System.currentTimeMillis(); + Scale actScale = new Scale(); + IobTotal total = null; + + for (long time = fromTime; time <= toTime; time += 5 * 60 * 1000L) { + Profile profile = ProfileFunctions.getInstance().getProfile(time); + double act = 0d; + if (profile == null) continue; + total = iobCobCalculatorPlugin.calculateFromTreatmentsAndTempsSynchronized(time, profile); + act = total.activity; + + if(time<=now) + actArrayHist.add(new ScaledDataPoint(time, act, actScale)); + else + actArrayPred.add(new ScaledDataPoint(time, act, actScale)); + } + + ScaledDataPoint[] actData = new ScaledDataPoint[actArrayHist.size()]; + actData = actArrayHist.toArray(actData); + actSeriesHist = new FixedLineGraphSeries<>(actData); + actSeriesHist.setDrawBackground(false); + actSeriesHist.setColor(MainApp.gc(R.color.activity)); + actSeriesHist.setThickness(3); + + addSeries(actSeriesHist); + + actData = new ScaledDataPoint[actArrayPred.size()]; + actData = actArrayPred.toArray(actData); + actSeriesPred = new FixedLineGraphSeries<>(actData); + + Paint paint = new Paint(); + paint.setStyle(Paint.Style.STROKE); + paint.setStrokeWidth(3); + paint.setPathEffect(new DashPathEffect(new float[]{4, 4}, 0)); + paint.setColor(MainApp.gc(R.color.activity)); + actSeriesPred.setCustomPaint(paint); + + double maxIAValue = SP.getDouble(R.string.key_scale_insulin_activity, 0.05); + if (useForScale) { + maxY = maxIAValue; + minY = -maxIAValue; + } + actScale.setMultiplier(maxY * scale / maxIAValue); + + addSeries(actSeriesPred); + } + // scale in % of vertical size (like 0.3) public void addIob(long fromTime, long toTime, boolean useForScale, double scale) { FixedLineGraphSeries iobSeries; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/notifications/DismissNotificationService.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/notifications/DismissNotificationService.java index a8d6fca1ba..475aa02332 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/notifications/DismissNotificationService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/notifications/DismissNotificationService.java @@ -3,7 +3,7 @@ package info.nightscout.androidaps.plugins.general.overview.notifications; import android.app.IntentService; import android.app.PendingIntent; import android.content.Intent; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/notifications/Notification.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/notifications/Notification.java index 3b6bcf615d..f7a4c32360 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/notifications/Notification.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/notifications/Notification.java @@ -74,6 +74,7 @@ public class Notification { public static final int DST_LOOP_DISABLED = 49; public static final int DST_IN_24H = 50; public static final int DISKFULL = 51; + public static final int OLDVERSION = 52; public int id; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/notifications/NotificationRecyclerViewAdapter.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/notifications/NotificationRecyclerViewAdapter.java index de35e4bc8c..6cb5c2fdf4 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/notifications/NotificationRecyclerViewAdapter.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/notifications/NotificationRecyclerViewAdapter.java @@ -1,8 +1,8 @@ package info.nightscout.androidaps.plugins.general.overview.notifications; -import android.support.v4.content.ContextCompat; -import android.support.v7.widget.CardView; -import android.support.v7.widget.RecyclerView; +import androidx.core.content.ContextCompat; +import androidx.cardview.widget.CardView; +import androidx.recyclerview.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/notifications/NotificationStore.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/notifications/NotificationStore.java index 8d327bf29f..2a94d2c859 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/notifications/NotificationStore.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/notifications/NotificationStore.java @@ -11,7 +11,9 @@ import android.media.AudioAttributes; import android.media.RingtoneManager; import android.net.Uri; import android.os.Build; -import android.support.v4.app.NotificationCompat; +import androidx.core.app.NotificationCompat; +import androidx.recyclerview.widget.RecyclerView; +import android.view.View; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -21,7 +23,6 @@ import java.util.Collections; import java.util.Comparator; import java.util.List; -import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.logging.L; @@ -68,14 +69,20 @@ public class NotificationStore { if (usesChannels && n.soundId != null) { Intent alarm = new Intent(MainApp.instance().getApplicationContext(), AlarmSoundService.class); alarm.putExtra("soundid", n.soundId); - MainApp.instance().startService(alarm); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) + MainApp.instance().startForegroundService(alarm); + else + MainApp.instance().startService(alarm); } } else { if (n.soundId != null) { Intent alarm = new Intent(MainApp.instance().getApplicationContext(), AlarmSoundService.class); alarm.putExtra("soundid", n.soundId); - MainApp.instance().startService(alarm); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) + MainApp.instance().startForegroundService(alarm); + else + MainApp.instance().startService(alarm); } } @@ -97,7 +104,7 @@ public class NotificationStore { return false; } - public synchronized void removeExpired() { + private synchronized void removeExpired() { for (int i = 0; i < store.size(); i++) { Notification n = store.get(i); if (n.validTo.getTime() != 0 && n.validTo.getTime() < System.currentTimeMillis()) { @@ -107,13 +114,13 @@ public class NotificationStore { } } - public void snoozeTo(long timeToSnooze) { + void snoozeTo(long timeToSnooze) { if (L.isEnabled(L.NOTIFICATION)) log.debug("Snoozing alarm until: " + timeToSnooze); SP.putLong("snoozedTo", timeToSnooze); } - public void unSnooze() { + private void unSnooze() { if (Notification.isAlarmForStaleData()) { Notification notification = new Notification(Notification.NSALARM, MainApp.gs(R.string.nsalarm_staledata), Notification.URGENT); SP.putLong("snoozedTo", System.currentTimeMillis()); @@ -160,4 +167,16 @@ public class NotificationStore { } } + public synchronized void updateNotifications(RecyclerView notificationsView) { + removeExpired(); + unSnooze(); + if (store.size() > 0) { + NotificationRecyclerViewAdapter adapter = new NotificationRecyclerViewAdapter(store); + notificationsView.setAdapter(adapter); + notificationsView.setVisibility(View.VISIBLE); + } else { + notificationsView.setVisibility(View.GONE); + } + } + } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/persistentNotification/DummyService.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/persistentNotification/DummyService.java index 863046c0c4..1400185afa 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/persistentNotification/DummyService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/persistentNotification/DummyService.java @@ -4,7 +4,8 @@ import android.app.Notification; import android.app.Service; import android.content.Intent; import android.os.IBinder; -import android.support.annotation.Nullable; + +import androidx.annotation.Nullable; import com.squareup.otto.Subscribe; @@ -29,9 +30,8 @@ public class DummyService extends Service { @Override public int onStartCommand(Intent intent, int flags, int startId) { - Notification notification = PersistentNotificationPlugin.getPlugin().updateNotification(); - if (notification != null) - startForeground(PersistentNotificationPlugin.ONGOING_NOTIFICATION_ID, notification); + super.onStartCommand(intent, flags, startId); + startForeground(PersistentNotificationPlugin.ONGOING_NOTIFICATION_ID, PersistentNotificationPlugin.getPlugin().updateNotification()); return START_STICKY; } @@ -45,6 +45,11 @@ public class DummyService extends Service { @Override public void onCreate() { + super.onCreate(); + // TODO: I guess this was moved here in order to adhere to the 5 seconds rule to call "startForeground" after a Service was called as Foreground service? + // As onCreate() is not called every time a service is started, copied to onStartCommand(). + Notification notification = PersistentNotificationPlugin.getPlugin().updateNotification(); + startForeground(PersistentNotificationPlugin.ONGOING_NOTIFICATION_ID, notification); MainApp.bus().register(this); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/persistentNotification/PersistentNotificationPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/persistentNotification/PersistentNotificationPlugin.java index 0287c21260..9dcb800033 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/persistentNotification/PersistentNotificationPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/persistentNotification/PersistentNotificationPlugin.java @@ -10,17 +10,19 @@ 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.RemoteInput; -import android.support.v4.app.TaskStackBuilder; + +import androidx.core.app.NotificationCompat; +import androidx.core.app.RemoteInput; +import androidx.core.app.TaskStackBuilder; import com.squareup.otto.Subscribe; +import javax.annotation.Nonnull; + 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; @@ -37,6 +39,7 @@ 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.iob.iobCobCalculator.GlucoseStatus; import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin; import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutosensCalculationFinished; import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; @@ -49,6 +52,7 @@ import info.nightscout.androidaps.utils.DecimalFormatter; public class PersistentNotificationPlugin extends PluginBase { private static PersistentNotificationPlugin plugin; + private Notification notification; public static PersistentNotificationPlugin getPlugin() { if (plugin == null) plugin = new PersistentNotificationPlugin(MainApp.instance()); @@ -72,13 +76,14 @@ public class PersistentNotificationPlugin extends PluginBase { /// End Android Auto - public PersistentNotificationPlugin(Context ctx) { + private 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) + .alwaysEnabled(true) + .showInList(false) .description(R.string.description_persistent_notification) ); this.ctx = ctx; @@ -86,8 +91,8 @@ public class PersistentNotificationPlugin extends PluginBase { @Override protected void onStart() { + createNotificationChannel(); // make sure channels exist before triggering updates through the bus MainApp.bus().register(this); - createNotificationChannel(); triggerNotificationUpdate(); super.onStart(); } @@ -111,105 +116,107 @@ public class PersistentNotificationPlugin extends PluginBase { } private void triggerNotificationUpdate() { - MainApp.instance().startService(new Intent(MainApp.instance(), DummyService.class)); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) + MainApp.instance().startForegroundService(new Intent(MainApp.instance(), DummyService.class)); + else + MainApp.instance().startService(new Intent(MainApp.instance(), DummyService.class)); } + @Nonnull Notification updateNotification() { - if (!isEnabled(PluginType.GENERAL)) { - return null; - } + String line1 = null; + String line2 = null; + String line3 = null; + NotificationCompat.CarExtender.UnreadConversation.Builder unreadConversationBuilder = null; - String line1; - String line1_aa; - - if (ConfigBuilderPlugin.getPlugin().getActiveProfileInterface() == null || !ProfileFunctions.getInstance().isProfileValid("Notificiation")) - return null; - String units = ProfileFunctions.getInstance().getProfileUnits(); + if (ConfigBuilderPlugin.getPlugin().getActiveProfileInterface() != null && ProfileFunctions.getInstance().isProfileValid("Notification")) { + String line1_aa; + String units = ProfileFunctions.getInstance().getProfileUnits(); - BgReading lastBG = DatabaseHelper.lastBg(); - GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData(); + 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(); + 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 += " " + - MainApp.gs(R.string.old_data) + - " "; - line1_aa += line1 + "."; + line1 = line1_aa = MainApp.gs(R.string.missed_bg_readings); } - } 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(); + + + 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() + "."; + + + 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 + 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 } - 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); @@ -217,12 +224,14 @@ public class PersistentNotificationPlugin extends PluginBase { builder.setSmallIcon(MainApp.getNotificationIcon()); Bitmap largeIcon = BitmapFactory.decodeResource(ctx.getResources(), MainApp.getIcon()); builder.setLargeIcon(largeIcon); - builder.setContentTitle(line1); - builder.setContentText(line2); - builder.setSubText(line3); + builder.setContentTitle(line1 != null ? line1 : MainApp.gs(R.string.noprofileset)); + builder.setContentText(line2 != null ? line2 : MainApp.gs(R.string.noprofileset)); + builder.setSubText(line3 != null ? line3 : MainApp.gs(R.string.noprofileset)); /// Android Auto - builder.extend(new NotificationCompat.CarExtender() - .setUnreadConversation(unreadConversationBuilder.build())); + if (unreadConversationBuilder != null) { + builder.extend(new NotificationCompat.CarExtender() + .setUnreadConversation(unreadConversationBuilder.build())); + } /// End Android Auto @@ -242,6 +251,7 @@ public class PersistentNotificationPlugin extends PluginBase { android.app.Notification notification = builder.build(); mNotificationManager.notify(ONGOING_NOTIFICATION_ID, notification); + this.notification = notification; return notification; } @@ -261,6 +271,17 @@ public class PersistentNotificationPlugin extends PluginBase { return deltastring; } + /*** + * returns the current ongoing notification. + * + * If it does not exist, return a dummy notification. This should only happen if onStart() wasn't called. + */ + + public Notification getLastNotification() { + if (notification != null) return notification; + else return new Notification(); + } + @Subscribe public void onStatusEvent(final EventPreferenceChange ev) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPlugin.java index 7703561aa9..181bdd86d2 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPlugin.java @@ -20,7 +20,7 @@ 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.GlucoseStatus; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus; import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.ProfileStore; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/TidepoolFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/TidepoolFragment.kt new file mode 100644 index 0000000000..7fc21ca510 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/TidepoolFragment.kt @@ -0,0 +1,57 @@ +package info.nightscout.androidaps.plugins.general.tidepool + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ScrollView +import androidx.fragment.app.Fragment +import info.nightscout.androidaps.R +import info.nightscout.androidaps.plugins.bus.RxBus +import info.nightscout.androidaps.plugins.general.tidepool.comm.TidepoolUploader +import info.nightscout.androidaps.plugins.general.tidepool.events.EventTidepoolDoUpload +import info.nightscout.androidaps.plugins.general.tidepool.events.EventTidepoolResetData +import info.nightscout.androidaps.plugins.general.tidepool.events.EventTidepoolUpdateGUI +import info.nightscout.androidaps.utils.SP +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.disposables.CompositeDisposable +import io.reactivex.disposables.Disposable +import kotlinx.android.synthetic.main.tidepool_fragment.* + +class TidepoolFragment : Fragment() { + + private var disposable: CompositeDisposable = CompositeDisposable() + + operator fun CompositeDisposable.plusAssign(disposable: Disposable) { + add(disposable) + } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + return inflater.inflate(R.layout.tidepool_fragment, container, false) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + tidepool_login.setOnClickListener { TidepoolUploader.doLogin(false) } + tidepool_uploadnow.setOnClickListener { RxBus.send(EventTidepoolDoUpload()) } + tidepool_removeall.setOnClickListener { RxBus.send(EventTidepoolResetData()) } + tidepool_resertstart.setOnClickListener { SP.putLong(R.string.key_tidepool_last_end, 0) } + + disposable.add(RxBus + .toObservable(EventTidepoolUpdateGUI::class.java) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe({ + TidepoolPlugin.updateLog() + tidepool_log.text = TidepoolPlugin.textLog + tidepool_status.text = TidepoolUploader.connectionStatus.name + tidepool_log.text = TidepoolPlugin.textLog + tidepool_logscrollview.fullScroll(ScrollView.FOCUS_DOWN) + }, {}) + ) + } + + override fun onStop() { + super.onStop() + disposable.clear() + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/TidepoolPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/TidepoolPlugin.kt new file mode 100644 index 0000000000..90f60d0542 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/TidepoolPlugin.kt @@ -0,0 +1,147 @@ +package info.nightscout.androidaps.plugins.general.tidepool + +import android.text.Html +import android.text.Spanned +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.EventNetworkChange +import info.nightscout.androidaps.events.EventNewBG +import info.nightscout.androidaps.events.EventPreferenceChange +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.bus.RxBus +import info.nightscout.androidaps.plugins.general.tidepool.comm.TidepoolUploader +import info.nightscout.androidaps.plugins.general.tidepool.events.EventTidepoolDoUpload +import info.nightscout.androidaps.plugins.general.tidepool.events.EventTidepoolResetData +import info.nightscout.androidaps.plugins.general.tidepool.events.EventTidepoolStatus +import info.nightscout.androidaps.plugins.general.tidepool.events.EventTidepoolUpdateGUI +import info.nightscout.androidaps.plugins.general.tidepool.utils.RateLimit +import info.nightscout.androidaps.receivers.ChargingStateReceiver +import info.nightscout.androidaps.receivers.NetworkChangeReceiver +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.disposables.Disposable +import io.reactivex.schedulers.Schedulers +import org.slf4j.LoggerFactory +import java.util.* + +object TidepoolPlugin : PluginBase(PluginDescription() + .mainType(PluginType.GENERAL) + .pluginName(R.string.tidepool) + .shortName(R.string.tidepool_shortname) + .fragmentClass(TidepoolFragment::class.qualifiedName) + .preferencesId(R.xml.pref_tidepool) + .description(R.string.description_tidepool) +) { + + private val log = LoggerFactory.getLogger(L.TIDEPOOL) + private var disposable: CompositeDisposable = CompositeDisposable() + + private val listLog = ArrayList() + @Suppress("DEPRECATION") // API level 24 to replace call + var textLog: Spanned = Html.fromHtml("") + + operator fun CompositeDisposable.plusAssign(disposable: Disposable) { + add(disposable) + } + + override fun onStart() { + super.onStart() + disposable += RxBus + .toObservable(EventTidepoolDoUpload::class.java) + .observeOn(Schedulers.io()) + .subscribe({ doUpload() }, {}) + disposable += RxBus + .toObservable(EventTidepoolResetData::class.java) + .observeOn(Schedulers.io()) + .subscribe({ + if (TidepoolUploader.connectionStatus != TidepoolUploader.ConnectionStatus.CONNECTED) { + log.debug("Not connected for delete Dataset") + } else { + TidepoolUploader.deleteDataSet() + SP.putLong(R.string.key_tidepool_last_end, 0) + TidepoolUploader.doLogin() + } + }, {}) + disposable += RxBus + .toObservable(EventTidepoolStatus::class.java) + .observeOn(Schedulers.io()) + .subscribe({ event -> addToLog(event) }, {}) + disposable += RxBus + .toObservable(EventNewBG::class.java) + .observeOn(Schedulers.io()) + .filter { it.bgReading != null } // better would be optional in API level >24 + .map { it.bgReading } + .subscribe { bgReading -> + if (bgReading!!.date < TidepoolUploader.getLastEnd()) + TidepoolUploader.setLastEnd(bgReading.date) + if (isEnabled(PluginType.GENERAL) + && (!SP.getBoolean(R.string.key_tidepool_only_while_charging, false) || ChargingStateReceiver.isCharging()) + && (!SP.getBoolean(R.string.key_tidepool_only_while_unmetered, false) || NetworkChangeReceiver.isWifiConnected()) + && RateLimit.rateLimit("tidepool-new-data-upload", T.mins(4).secs().toInt())) + doUpload() + } + disposable += RxBus + .toObservable(EventPreferenceChange::class.java) + .observeOn(Schedulers.io()) + .subscribe({ event -> + if (event.isChanged(R.string.key_tidepool_dev_servers) + || event.isChanged(R.string.key_tidepool_username) + || event.isChanged(R.string.key_tidepool_password) + ) + TidepoolUploader.resetInstance() + }, {}) + disposable += RxBus + .toObservable(EventNetworkChange::class.java) + .observeOn(Schedulers.io()) + .subscribe({}, {}) // TODO start upload on wifi connect + + } + + override fun onStop() { + disposable.clear() + super.onStop() + } + + private fun doUpload() { + if (TidepoolUploader.connectionStatus == TidepoolUploader.ConnectionStatus.DISCONNECTED) + TidepoolUploader.doLogin(true) + else + TidepoolUploader.doUpload() + } + + @Synchronized + private fun addToLog(ev: EventTidepoolStatus) { + synchronized(listLog) { + listLog.add(ev) + // remove the first line if log is too large + if (listLog.size >= Constants.MAX_LOG_LINES) { + listLog.removeAt(0) + } + } + RxBus.send(EventTidepoolUpdateGUI()) + } + + @Synchronized + fun updateLog() { + try { + val newTextLog = StringBuilder() + synchronized(listLog) { + for (log in listLog) { + newTextLog.append(log.toPreparedHtml()) + } + } + @Suppress("DEPRECATION") // API level 24 to replace call + textLog = Html.fromHtml(newTextLog.toString()) + } catch (e: OutOfMemoryError) { + ToastUtils.showToastInUiThread(MainApp.instance().applicationContext, "Out of memory!\nStop using this phone !!!", R.raw.error) + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/comm/InfoInterceptor.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/comm/InfoInterceptor.kt new file mode 100644 index 0000000000..ca3c3e0483 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/comm/InfoInterceptor.kt @@ -0,0 +1,32 @@ +package info.nightscout.androidaps.plugins.general.tidepool.comm + +import info.nightscout.androidaps.logging.L +import okhttp3.Interceptor +import okhttp3.Response +import okio.Buffer +import org.slf4j.LoggerFactory +import java.io.IOException + +class InfoInterceptor(tag: String) : Interceptor { + + private val log = LoggerFactory.getLogger(L.TIDEPOOL) + private var tag = "interceptor" + + init { + this.tag = tag + } + + @Throws(IOException::class) + override fun intercept(chain: Interceptor.Chain): Response { + val request = chain.request() + request?.body()?.let { + if (L.isEnabled(L.TIDEPOOL)) { + log.debug("Interceptor Body size: " + it.contentLength()) + val requestBuffer = Buffer() + it.writeTo(requestBuffer) + log.debug("Interceptor Body: " + requestBuffer.readUtf8()) + } + } + return chain.proceed(request) + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/comm/Session.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/comm/Session.kt new file mode 100644 index 0000000000..7067ddd073 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/comm/Session.kt @@ -0,0 +1,42 @@ +package info.nightscout.androidaps.plugins.general.tidepool.comm + +import info.nightscout.androidaps.plugins.general.tidepool.messages.AuthReplyMessage +import info.nightscout.androidaps.plugins.general.tidepool.messages.DatasetReplyMessage +import okhttp3.Headers + +class Session(val authHeader: String?, + private val sessionTokenHeader: String, + val service: TidepoolApiService?) { + + internal var token: String? = null + internal var authReply: AuthReplyMessage? = null + internal var datasetReply: DatasetReplyMessage? = null + internal var start: Long = 0 + internal var end: Long = 0 + @Volatile + internal var iterations: Int = 0 + + + fun populateHeaders(headers: Headers) { + if (this.token == null) { + this.token = headers.get(sessionTokenHeader) + } + } + + fun populateBody(obj: Any?) { + if (obj == null) return + if (obj is AuthReplyMessage) { + authReply = obj + } else if (obj is List<*>) { + val list = obj as? List<*>? + + list?.getOrNull(0)?.let { + if (it is DatasetReplyMessage) { + datasetReply = it + } + } + } else if (obj is DatasetReplyMessage) { + datasetReply = obj + } + } +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/comm/TidepoolApiService.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/comm/TidepoolApiService.kt new file mode 100644 index 0000000000..52adf539c5 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/comm/TidepoolApiService.kt @@ -0,0 +1,48 @@ +package info.nightscout.androidaps.plugins.general.tidepool.comm + +import info.nightscout.androidaps.BuildConfig +import info.nightscout.androidaps.plugins.general.tidepool.messages.AuthReplyMessage +import info.nightscout.androidaps.plugins.general.tidepool.messages.DatasetReplyMessage +import info.nightscout.androidaps.plugins.general.tidepool.messages.UploadReplyMessage +import okhttp3.RequestBody +import retrofit2.Call +import retrofit2.http.* + +const val SESSION_TOKEN_HEADER: String = "x-tidepool-session-token" + +interface TidepoolApiService { + + @Headers( + "User-Agent: AAPS- " + BuildConfig.VERSION_NAME, + "X-Tidepool-Client-Name: info.nightscout.androidaps" + BuildConfig.APPLICATION_ID, + "X-Tidepool-Client-Version: 0.1.0" + ) + + @POST("/auth/login") + fun getLogin(@Header("Authorization") secret: String): Call + + @DELETE("/v1/users/{userId}/data") + fun deleteAllData(@Header(SESSION_TOKEN_HEADER) token: String, @Path("userId") id: String): Call + + @DELETE("/v1/datasets/{dataSetId}") + fun deleteDataSet(@Header(SESSION_TOKEN_HEADER) token: String, @Path("dataSetId") id: String): Call + + @GET("/v1/users/{userId}/data_sets") + fun getOpenDataSets(@Header(SESSION_TOKEN_HEADER) token: String, + @Path("userId") id: String, + @Query("client.name") clientName: String, + @Query("size") size: Int): Call> + + @GET("/v1/datasets/{dataSetId}") + fun getDataSet(@Header(SESSION_TOKEN_HEADER) token: String, @Path("dataSetId") id: String): Call + + @POST("/v1/users/{userId}/data_sets") + fun openDataSet(@Header(SESSION_TOKEN_HEADER) token: String, @Path("userId") id: String, @Body body: RequestBody): Call + + @POST("/v1/datasets/{sessionId}/data") + fun doUpload(@Header(SESSION_TOKEN_HEADER) token: String, @Path("sessionId") id: String, @Body body: RequestBody): Call + + @PUT("/v1/datasets/{sessionId}") + fun closeDataSet(@Header(SESSION_TOKEN_HEADER) token: String, @Path("sessionId") id: String, @Body body: RequestBody): Call + +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/comm/TidepoolCallback.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/comm/TidepoolCallback.kt new file mode 100644 index 0000000000..58ba913e91 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/comm/TidepoolCallback.kt @@ -0,0 +1,35 @@ +package info.nightscout.androidaps.plugins.general.tidepool.comm + +import info.nightscout.androidaps.plugins.bus.RxBus +import info.nightscout.androidaps.logging.L +import info.nightscout.androidaps.plugins.general.tidepool.events.EventTidepoolStatus +import org.slf4j.LoggerFactory +import retrofit2.Call +import retrofit2.Callback +import retrofit2.Response + +internal class TidepoolCallback(private val session: Session, val name: String, val onSuccess: () -> Unit, val onFail: () -> Unit) : Callback { + private val log = LoggerFactory.getLogger(L.TIDEPOOL) + + override fun onResponse(call: Call, response: Response) { + if (response.isSuccessful && response.body() != null) { + if (L.isEnabled(L.TIDEPOOL)) log.debug("$name success") + session.populateBody(response.body()) + session.populateHeaders(response.headers()) + onSuccess() + } else { + val msg = name + " was not successful: " + response.code() + " " + response.message() + if (L.isEnabled(L.TIDEPOOL)) log.debug(msg) + RxBus.send(EventTidepoolStatus(msg)) + onFail() + } + } + + override fun onFailure(call: Call, t: Throwable) { + val msg = "$name Failed: $t" + if (L.isEnabled(L.TIDEPOOL)) log.debug(msg) + RxBus.send(EventTidepoolStatus(msg)) + onFail() + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/comm/TidepoolUploader.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/comm/TidepoolUploader.kt new file mode 100644 index 0000000000..5f6d5cc5d1 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/comm/TidepoolUploader.kt @@ -0,0 +1,314 @@ +package info.nightscout.androidaps.plugins.general.tidepool.comm + +import android.content.Context +import android.os.PowerManager +import android.os.SystemClock +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.bus.RxBus +import info.nightscout.androidaps.plugins.general.tidepool.events.EventTidepoolStatus +import info.nightscout.androidaps.plugins.general.tidepool.messages.* +import info.nightscout.androidaps.utils.DateUtil +import info.nightscout.androidaps.utils.OKDialog +import info.nightscout.androidaps.utils.SP +import info.nightscout.androidaps.utils.T +import okhttp3.MediaType +import okhttp3.OkHttpClient +import okhttp3.RequestBody +import okhttp3.logging.HttpLoggingInterceptor +import org.slf4j.LoggerFactory +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory + +object TidepoolUploader { + + private val log = LoggerFactory.getLogger(L.TIDEPOOL) + + private var wl: PowerManager.WakeLock? = null + + private const val INTEGRATION_BASE_URL = "https://int-api.tidepool.org" + private const val PRODUCTION_BASE_URL = "https://api.tidepool.org" + + internal const val VERSION = "0.0.1" + + private var retrofit: Retrofit? = null + + private var session: Session? = null + + enum class ConnectionStatus { + DISCONNECTED, CONNECTING, CONNECTED, FAILED + } + + val PUMPTYPE = "Tandem" + + var connectionStatus: ConnectionStatus = TidepoolUploader.ConnectionStatus.DISCONNECTED + + fun getRetrofitInstance(): Retrofit? { + if (retrofit == null) { + + val httpLoggingInterceptor = HttpLoggingInterceptor() + httpLoggingInterceptor.level = HttpLoggingInterceptor.Level.BODY + + val client = OkHttpClient.Builder() + .addInterceptor(httpLoggingInterceptor) + .addInterceptor(InfoInterceptor(TidepoolUploader::class.java.name)) + .build() + + retrofit = Retrofit.Builder() + .baseUrl(if (SP.getBoolean(R.string.key_tidepool_dev_servers, false)) INTEGRATION_BASE_URL else PRODUCTION_BASE_URL) + .client(client) + .addConverterFactory(GsonConverterFactory.create()) + .build() + } + return retrofit + } + + fun createSession(): Session { + val service = getRetrofitInstance()?.create(TidepoolApiService::class.java) + return Session(AuthRequestMessage.getAuthRequestHeader(), SESSION_TOKEN_HEADER, service) + } + + // TODO: call on preference change + fun resetInstance() { + retrofit = null + if (L.isEnabled(L.TIDEPOOL)) + log.debug("Instance reset") + connectionStatus = TidepoolUploader.ConnectionStatus.DISCONNECTED + } + + @Synchronized + fun doLogin(doUpload: Boolean = false) { + if (connectionStatus == TidepoolUploader.ConnectionStatus.CONNECTED || connectionStatus == TidepoolUploader.ConnectionStatus.CONNECTING) { + if (L.isEnabled(L.TIDEPOOL)) + log.debug("Already connected") + return + } + // TODO failure backoff + extendWakeLock(30000) + session = createSession() + val authHeader = session?.authHeader + if (authHeader != null) { + connectionStatus = TidepoolUploader.ConnectionStatus.CONNECTING + RxBus.send(EventTidepoolStatus(("Connecting"))) + val call = session?.service?.getLogin(authHeader) + + call?.enqueue(TidepoolCallback(session!!, "Login", { + startSession(session!!, doUpload) + }, { + connectionStatus = TidepoolUploader.ConnectionStatus.FAILED + loginFailed() + })) + return + } else { + if (L.isEnabled(L.TIDEPOOL)) log.debug("Cannot do login as user credentials have not been set correctly") + connectionStatus = TidepoolUploader.ConnectionStatus.FAILED + RxBus.send(EventTidepoolStatus(("Invalid credentials"))) + releaseWakeLock() + return + } + } + + fun testLogin(rootContext: Context) { + val session = createSession() + session.authHeader?.let { + val call = session.service?.getLogin(it) + + call?.enqueue(TidepoolCallback(session, "Login", { + OKDialog.show(rootContext, MainApp.gs(R.string.tidepool), "Successfully logged into Tidepool.", null) + }, { + OKDialog.show(rootContext, MainApp.gs(R.string.tidepool), "Failed to log into Tidepool.\nCheck that your user name and password are correct.", null) + })) + + } + ?: OKDialog.show(rootContext, MainApp.gs(R.string.tidepool), "Cannot do login as user credentials have not been set correctly", null) + + } + + private fun loginFailed() { + releaseWakeLock() + } + + private fun startSession(session: Session, doUpload: Boolean = false) { + extendWakeLock(30000) + if (session.authReply?.userid != null) { + // See if we already have an open data set to write to + val datasetCall = session.service!!.getOpenDataSets(session.token!!, + session.authReply!!.userid!!, BuildConfig.APPLICATION_ID, 1) + + datasetCall.enqueue(TidepoolCallback>(session, "Get Open Datasets", { + if (session.datasetReply == null) { + RxBus.send(EventTidepoolStatus(("Creating new dataset"))) + val call = session.service.openDataSet(session.token!!, session.authReply!!.userid!!, OpenDatasetRequestMessage().getBody()) + call.enqueue(TidepoolCallback(session, "Open New Dataset", { + connectionStatus = TidepoolUploader.ConnectionStatus.CONNECTED + RxBus.send(EventTidepoolStatus(("New dataset OK"))) + if (doUpload) doUpload() + else + releaseWakeLock() + }, { + RxBus.send(EventTidepoolStatus(("New dataset FAILED"))) + connectionStatus = TidepoolUploader.ConnectionStatus.FAILED + releaseWakeLock() + })) + } else { + if (L.isEnabled(L.TIDEPOOL)) + log.debug("Existing Dataset: " + session.datasetReply!!.getUploadId()) + // TODO: Wouldn't need to do this if we could block on the above `call.enqueue`. + // ie, do the openDataSet conditionally, and then do `doUpload` either way. + connectionStatus = TidepoolUploader.ConnectionStatus.CONNECTED + RxBus.send(EventTidepoolStatus(("Appending to existing dataset"))) + if (doUpload) doUpload() + else + releaseWakeLock() + } + }, { + connectionStatus = TidepoolUploader.ConnectionStatus.FAILED + RxBus.send(EventTidepoolStatus(("Open dataset FAILED"))) + releaseWakeLock() + })) + } else { + log.error("Got login response but cannot determine userId - cannot proceed") + connectionStatus = TidepoolUploader.ConnectionStatus.FAILED + RxBus.send(EventTidepoolStatus(("Error userId"))) + releaseWakeLock() + } + } + + @Synchronized + fun doUpload() { + session.let { session -> + if (session == null) { + log.error("Session is null, cannot proceed") + releaseWakeLock() + return + } + extendWakeLock(60000) + session.iterations++ + val chunk = UploadChunk.getNext(session) + when { + chunk == null -> { + log.error("Upload chunk is null, cannot proceed") + releaseWakeLock() + } + + chunk.length == 2 -> { + if (L.isEnabled(L.TIDEPOOL)) log.debug("Empty dataset - marking as succeeded") + RxBus.send(EventTidepoolStatus(("No data to upload"))) + releaseWakeLock() + unploadNext() + } + + else -> { + val body = RequestBody.create(MediaType.parse("application/json"), chunk) + + RxBus.send(EventTidepoolStatus(("Uploading"))) + val call = session.service!!.doUpload(session.token!!, session.datasetReply!!.getUploadId()!!, body) + call.enqueue(TidepoolCallback(session, "Data Upload", { + setLastEnd(session.end) + RxBus.send(EventTidepoolStatus(("Upload completed OK"))) + releaseWakeLock() + unploadNext() + }, { + RxBus.send(EventTidepoolStatus(("Upload FAILED"))) + releaseWakeLock() + })) + } + } + } + } + + private fun unploadNext() { + if (getLastEnd() < DateUtil.now() - T.mins(1).msecs()) { + SystemClock.sleep(3000) + if (L.isEnabled(L.TIDEPOOL)) + log.debug("Restarting doUpload. Last: " + DateUtil.dateAndTimeString(getLastEnd())) + doUpload() + } + } + + fun deleteDataSet() { + if (session?.datasetReply?.id != null) { + extendWakeLock(60000) + val call = session!!.service?.deleteDataSet(session!!.token!!, session!!.datasetReply!!.id!!) + call?.enqueue(TidepoolCallback(session!!, "Delete Dataset", { + connectionStatus = TidepoolUploader.ConnectionStatus.DISCONNECTED + RxBus.send(EventTidepoolStatus(("Dataset removed OK"))) + releaseWakeLock() + }, { + connectionStatus = TidepoolUploader.ConnectionStatus.DISCONNECTED + RxBus.send(EventTidepoolStatus(("Dataset remove FAILED"))) + releaseWakeLock() + })) + } else { + log.error("Got login response but cannot determine datasetId - cannot proceed") + } + } + + fun deleteAllData() { + val session = this.session + val token = session?.token + val userid = session?.authReply?.userid + try { + requireNotNull(session) + requireNotNull(token) + requireNotNull(userid) + extendWakeLock(60000) + val call = session.service?.deleteAllData(token, userid) + call?.enqueue(TidepoolCallback(session, "Delete all data", { + connectionStatus = TidepoolUploader.ConnectionStatus.DISCONNECTED + RxBus.send(EventTidepoolStatus(("All data removed OK"))) + releaseWakeLock() + }, { + connectionStatus = TidepoolUploader.ConnectionStatus.DISCONNECTED + RxBus.send(EventTidepoolStatus(("All data remove FAILED"))) + releaseWakeLock() + })) + } catch (e: IllegalArgumentException) { + log.error("Got login response but cannot determine userId - cannot proceed") + } + } + + fun getLastEnd(): Long { + val result = SP.getLong(R.string.key_tidepool_last_end, 0) + return Math.max(result, DateUtil.now() - T.months(2).msecs()) + } + + fun setLastEnd(time: Long) { + if (time > getLastEnd()) { + SP.putLong(R.string.key_tidepool_last_end, time) + val friendlyEnd = DateUtil.dateAndTimeString(time) + RxBus.send(EventTidepoolStatus(("Marking uploaded data up to $friendlyEnd"))) + if (L.isEnabled(L.TIDEPOOL)) log.debug("Updating last end to: " + DateUtil.dateAndTimeString(time)) + } else { + if (L.isEnabled(L.TIDEPOOL)) log.debug("Cannot set last end to: " + DateUtil.dateAndTimeString(time) + " vs " + DateUtil.dateAndTimeString(getLastEnd())) + } + } + + @Synchronized + private fun extendWakeLock(ms: Long) { + if (wl == null) { + val pm = MainApp.instance().getSystemService(Context.POWER_SERVICE) as PowerManager + wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "AndroidAPS:TidepoolUploader") + wl?.acquire(ms) + } else { + releaseWakeLock() // lets not get too messy + wl?.acquire(ms) + } + } + + @Synchronized + private fun releaseWakeLock() { + wl?.let { + if (it.isHeld) { + try { + it.release() + } catch (e: Exception) { + log.error("Error releasing wakelock: $e") + } + } + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/comm/UploadChunk.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/comm/UploadChunk.kt new file mode 100644 index 0000000000..40cab06f4c --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/comm/UploadChunk.kt @@ -0,0 +1,130 @@ +package info.nightscout.androidaps.plugins.general.tidepool.comm + +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.general.tidepool.elements.* +import info.nightscout.androidaps.plugins.general.tidepool.events.EventTidepoolStatus +import info.nightscout.androidaps.plugins.general.tidepool.utils.GsonInstance +import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin +import info.nightscout.androidaps.utils.DateUtil +import info.nightscout.androidaps.utils.SP +import info.nightscout.androidaps.utils.T +import org.slf4j.LoggerFactory +import java.util.* + +object UploadChunk { + + private val MAX_UPLOAD_SIZE = T.days(7).msecs() // don't change this + + private val log = LoggerFactory.getLogger(L.TIDEPOOL) + + fun getNext(session: Session?): String? { + if (session == null) + return null + + session.start = TidepoolUploader.getLastEnd() + session.end = Math.min(session.start + MAX_UPLOAD_SIZE, DateUtil.now()) + + val result = get(session.start, session.end) + if (result.length < 3) { + if (L.isEnabled(L.TIDEPOOL)) log.debug("No records in this time period, setting start to best end time") + TidepoolUploader.setLastEnd(Math.max(session.end, getOldestRecordTimeStamp())) + } + return result + } + + operator fun get(start: Long, end: Long): String { + + if (L.isEnabled(L.TIDEPOOL)) log.debug("Syncing data between: " + DateUtil.dateAndTimeString(start) + " -> " + DateUtil.dateAndTimeString(end)) + if (end <= start) { + if (L.isEnabled(L.TIDEPOOL)) log.debug("End is <= start: " + DateUtil.dateAndTimeString(start) + " " + DateUtil.dateAndTimeString(end)) + return "" + } + if (end - start > MAX_UPLOAD_SIZE) { + if (L.isEnabled(L.TIDEPOOL)) log.debug("More than max range - rejecting") + return "" + } + + val records = LinkedList() + + if (SP.getBoolean(R.string.key_tidepool_upload_bolus, true)) + records.addAll(getTreatments(start, end)) + if (SP.getBoolean(R.string.key_tidepool_upload_bg, true)) + records.addAll(getBloodTests(start, end)) + if (SP.getBoolean(R.string.key_tidepool_upload_tbr, true)) + records.addAll(getBasals(start, end)) + if (SP.getBoolean(R.string.key_tidepool_upload_cgm, true)) + records.addAll(getBgReadings(start, end)) + if (SP.getBoolean(R.string.key_tidepool_upload_profile, true)) + records.addAll(getProfiles(start, end)) + + return GsonInstance.defaultGsonInstance().toJson(records) + } + + // numeric limits must match max time windows + + private fun getOldestRecordTimeStamp(): Long { + // TODO we could make sure we include records older than the first bg record for completeness + + val start: Long = 0 + val end = DateUtil.now() + + val bgReadingList = MainApp.getDbHelper().getBgreadingsDataFromTime(start, end, true) + return if (bgReadingList.size > 0) + bgReadingList[0].date + else -1 + } + + private fun getTreatments(start: Long, end: Long): List { + val result = LinkedList() + val treatments = TreatmentsPlugin.getPlugin().service.getTreatmentDataFromTime(start, end, true) + for (treatment in treatments) { + if (treatment.carbs > 0) { + result.add(WizardElement(treatment)) + } else if (treatment.insulin > 0) { + result.add(BolusElement(treatment)) + } + } + return result + } + + private fun getBloodTests(start: Long, end: Long): List { + val readings = MainApp.getDbHelper().getCareportalEvents(start, end, true) + val selection = BloodGlucoseElement.fromCareportalEvents(readings) + if (selection.isNotEmpty()) + RxBus.send(EventTidepoolStatus("${selection.size} BGs selected for upload")) + return selection + + } + + internal fun getBgReadings(start: Long, end: Long): List { + val readings = MainApp.getDbHelper().getBgreadingsDataFromTime(start, end, true) + val selection = SensorGlucoseElement.fromBgReadings(readings) + if (selection.isNotEmpty()) + RxBus.send(EventTidepoolStatus("${selection.size} CGMs selected for upload")) + return selection + } + + private fun getBasals(start: Long, end: Long): List { + val tbrs = TreatmentsPlugin.getPlugin().temporaryBasalsFromHistory + tbrs.merge() + val selection = BasalElement.fromTemporaryBasals(tbrs, start, end) // TODO do not upload running TBR + if (selection.isNotEmpty()) + RxBus.send(EventTidepoolStatus("${selection.size} TBRs selected for upload")) + return selection + } + + private fun getProfiles(start: Long, end: Long): List { + val pss = MainApp.getDbHelper().getProfileSwitchEventsFromTime(start, end, true) + val selection = LinkedList() + for (ps in pss) { + ProfileElement.newInstanceOrNull(ps)?.let { selection.add(it) } + } + if (selection.size > 0) + RxBus.send(EventTidepoolStatus("${selection.size} ProfileSwitches selected for upload")) + return selection + } + +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/elements/BasalElement.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/elements/BasalElement.kt new file mode 100644 index 0000000000..11478afa66 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/elements/BasalElement.kt @@ -0,0 +1,44 @@ +package info.nightscout.androidaps.plugins.general.tidepool.elements + +import com.google.gson.annotations.Expose +import info.nightscout.androidaps.data.Intervals +import info.nightscout.androidaps.db.TemporaryBasal +import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions +import java.util.* + +class BasalElement(tbr: TemporaryBasal) + : BaseElement(tbr.date, UUID.nameUUIDFromBytes(("AAPS-basal" + tbr.date).toByteArray()).toString()) { + + internal var timestamp: Long = 0 // not exposed + + @Expose + internal var deliveryType = "automated" + @Expose + internal var duration: Long = 0 + @Expose + internal var rate = -1.0 + @Expose + internal var scheduleName = "AAPS" + @Expose + internal var clockDriftOffset: Long = 0 + @Expose + internal var conversionOffset: Long = 0 + + init { + type = "basal" + timestamp = tbr.date + rate = tbr.tempBasalConvertedToAbsolute(tbr.date, ProfileFunctions.getInstance().getProfile(tbr.date)) + duration = tbr.end() - tbr.start() + } + + companion object { + internal fun fromTemporaryBasals(tbrList: Intervals, start: Long, end: Long): List { + val results = LinkedList() + for (tbr in tbrList.list) { + if (tbr.date >= start && tbr.date <= end && tbr.durationInMinutes != 0) + results.add(BasalElement(tbr)) + } + return results + } + } +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/elements/BaseElement.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/elements/BaseElement.kt new file mode 100644 index 0000000000..96900e62d6 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/elements/BaseElement.kt @@ -0,0 +1,27 @@ +package info.nightscout.androidaps.plugins.general.tidepool.elements + +import com.google.gson.annotations.Expose +import info.nightscout.androidaps.utils.DateUtil + +open class BaseElement(timestamp: Long, uuid: String) { + @Expose + var deviceTime: String = "" + @Expose + var time: String = "" + @Expose + var timezoneOffset: Int = 0 + @Expose + var type: String? = null + @Expose + var origin: Origin? = null + + init { + deviceTime = DateUtil.toISONoZone(timestamp) + time = DateUtil.toISOAsUTC(timestamp) + timezoneOffset = DateUtil.getTimeZoneOffsetMinutes(timestamp) // TODO + origin = Origin(uuid) + } + + inner class Origin internal constructor(@field:Expose + internal var id: String) +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/elements/BloodGlucoseElement.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/elements/BloodGlucoseElement.kt new file mode 100644 index 0000000000..548df0388d --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/elements/BloodGlucoseElement.kt @@ -0,0 +1,42 @@ +package info.nightscout.androidaps.plugins.general.tidepool.elements + +import com.google.gson.annotations.Expose +import info.nightscout.androidaps.Constants +import info.nightscout.androidaps.data.Profile +import info.nightscout.androidaps.db.CareportalEvent +import info.nightscout.androidaps.utils.JsonHelper +import org.json.JSONObject +import java.util.* + +class BloodGlucoseElement(careportalEvent: CareportalEvent) + : BaseElement(careportalEvent.date, UUID.nameUUIDFromBytes(("AAPS-bg" + careportalEvent.date).toByteArray()).toString()) { + + @Expose + var subType: String = "manual" + @Expose + var units: String = "mg/dL" + @Expose + var value: Int = 0 + + init { + type = "cbg" + subType = "manual" // TODO + val json = if (careportalEvent.json != null) JSONObject(careportalEvent.json) else JSONObject() + value = Profile.toMgdl(JsonHelper.safeGetDouble(json, "glucose"), JsonHelper.safeGetString(json, "units", Constants.MGDL)).toInt() + } + + companion object { + + fun fromCareportalEvents(careportalList: List): List { + val results = LinkedList() + for (bt in careportalList) { + if (bt.eventType == CareportalEvent.MBG || bt.eventType == CareportalEvent.BGCHECK) { + val bge = BloodGlucoseElement(bt) + if (bge.value > 0) + results.add(BloodGlucoseElement(bt)) + } + } + return results + } + } +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/elements/BolusElement.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/elements/BolusElement.kt new file mode 100644 index 0000000000..3d8dcbe964 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/elements/BolusElement.kt @@ -0,0 +1,22 @@ +package info.nightscout.androidaps.plugins.general.tidepool.elements + +import com.google.gson.annotations.Expose +import info.nightscout.androidaps.plugins.treatments.Treatment +import java.util.* + +class BolusElement(treatment: Treatment) + : BaseElement(treatment.date, UUID.nameUUIDFromBytes(("AAPS-bolus" + treatment.date).toByteArray()).toString()) { + + @Expose + var subType = "normal" + @Expose + var normal: Double = 0.0 + @Expose + var expectedNormal: Double = 0.0 + + init { + type = "bolus" + normal = treatment.insulin + expectedNormal = treatment.insulin + } +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/elements/ProfileElement.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/elements/ProfileElement.kt new file mode 100644 index 0000000000..93009ea7e1 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/elements/ProfileElement.kt @@ -0,0 +1,111 @@ +package info.nightscout.androidaps.plugins.general.tidepool.elements + +import com.google.gson.annotations.Expose +import info.nightscout.androidaps.data.Profile +import info.nightscout.androidaps.db.ProfileSwitch +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin +import info.nightscout.androidaps.plugins.general.tidepool.comm.TidepoolUploader +import info.nightscout.androidaps.utils.InstanceId +import java.util.* +import kotlin.collections.ArrayList + +class ProfileElement private constructor(ps: ProfileSwitch) + : BaseElement(ps.date, UUID.nameUUIDFromBytes(("AAPS-profile" + ps.date).toByteArray()).toString()) { + + @Expose + internal var activeSchedule = "Normal" + @Expose + internal var basalSchedules: BasalProfile = BasalProfile() + @Expose + internal var units: Units = Units() + @Expose + internal var bgTargets: TargetProfile = TargetProfile() + @Expose + internal var carbRatios: IcProfile = IcProfile() + @Expose + internal var insulinSensitivities: IsfProfile = IsfProfile() + @Expose + internal var deviceId: String = TidepoolUploader.PUMPTYPE + ":" + (ConfigBuilderPlugin.getPlugin().activePump?.serialNumber() + ?: InstanceId.instanceId()) + @Expose + internal var deviceSerialNumber: String = ConfigBuilderPlugin.getPlugin().activePump?.serialNumber() + ?: InstanceId.instanceId() + @Expose + internal var clockDriftOffset: Long = 0 + @Expose + internal var conversionOffset: Long = 0 + + init { + type = "pumpSettings" + val profile: Profile? = ps.profileObject + checkNotNull(profile) + for (br in profile.basalValues) + basalSchedules.Normal.add(BasalRate(br.timeAsSeconds * 1000, br.value)) + for (target in profile.singleTargets) + bgTargets.Normal.add(Target(target.timeAsSeconds * 1000, Profile.toMgdl(target.value, profile.units))) + for (ic in profile.ics) + carbRatios.Normal.add(Ratio(ic.timeAsSeconds * 1000, ic.value)) + for (isf in profile.isfs) + insulinSensitivities.Normal.add(Ratio(isf.timeAsSeconds * 1000, Profile.toMgdl(isf.value, profile.units))) + } + + inner class BasalProfile internal constructor( + @field:Expose + internal var Normal: ArrayList = ArrayList() // must be the same var name as activeSchedule + ) + + inner class BasalRate internal constructor( + @field:Expose + internal var start: Int, + @field:Expose + internal var rate: Double + ) + + inner class Units internal constructor( + @field:Expose + internal var carb: String = "grams", + @field:Expose + internal var bg: String = "mg/dL" + ) + + inner class TargetProfile internal constructor( + @field:Expose + internal var Normal: ArrayList = ArrayList() // must be the same var name as activeSchedule + ) + + inner class Target internal constructor( + @field:Expose + internal var start: Int, + @field:Expose + internal var target: Double + ) + + inner class IcProfile internal constructor( + @field:Expose + internal var Normal: ArrayList = ArrayList() // must be the same var name as activeSchedule + ) + + inner class IsfProfile internal constructor( + @field:Expose + internal var Normal: ArrayList = ArrayList() // must be the same var name as activeSchedule + ) + + inner class Ratio internal constructor( + @field:Expose + internal var start: Int, + @field:Expose + internal var amount: Double + ) + + companion object { + @JvmStatic + fun newInstanceOrNull(ps: ProfileSwitch): ProfileElement? = try { + ProfileElement(ps) + } catch (e: Throwable) { + null + } + } + +} + + diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/elements/SensorGlucoseElement.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/elements/SensorGlucoseElement.kt new file mode 100644 index 0000000000..ca2aceca1c --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/elements/SensorGlucoseElement.kt @@ -0,0 +1,29 @@ +package info.nightscout.androidaps.plugins.general.tidepool.elements + +import com.google.gson.annotations.Expose +import info.nightscout.androidaps.db.BgReading +import java.util.* + +class SensorGlucoseElement(bgReading: BgReading) + : BaseElement(bgReading.date, UUID.nameUUIDFromBytes(("AAPS-cgm" + bgReading.date).toByteArray()).toString()) { + + @Expose + internal var units: String = "mg/dL" + @Expose + internal var value: Int = 0 + + init { + this.type = "cbg" + value = bgReading.value.toInt() + } + + companion object { + internal fun fromBgReadings(bgReadingList: List): List { + val results = LinkedList() + for (bgReading in bgReadingList) { + results.add(SensorGlucoseElement(bgReading)) + } + return results + } + } +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/elements/WizardElement.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/elements/WizardElement.kt new file mode 100644 index 0000000000..d7641862fe --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/elements/WizardElement.kt @@ -0,0 +1,68 @@ +package info.nightscout.androidaps.plugins.general.tidepool.elements + +import com.google.gson.annotations.Expose +import info.nightscout.androidaps.plugins.treatments.Treatment +import java.util.* + +class WizardElement(treatment: Treatment) + : BaseElement(treatment.date, UUID.nameUUIDFromBytes(("AAPS-wizard" + treatment.date).toByteArray()).toString()) { + + @Expose + var units = "mg/dL" + @Expose + var carbInput: Double = 0.toDouble() + @Expose + var insulinCarbRatio: Double = 0.toDouble() + @Expose + var bolus: BolusElement? = null + + init { + type = "wizard" + carbInput = treatment.carbs + insulinCarbRatio = treatment.ic + if (treatment.insulin > 0) { + bolus = BolusElement(treatment) + } else { + val fake = Treatment() + fake.insulin = 0.0001 + fake.date = treatment.date + bolus = BolusElement(fake) // fake insulin record + } + } +} + +/* TODO fill the rest +{ + "type": "wizard", + "bgInput": 16.152676653942503, + "bgTarget": { + "low": 3.6079861941795968, + "high": 6.938434988806917 + }, + "bolus": "22239d4d592b48ae920b28971cceb48b", + "carbInput": 57, + "insulinCarbRatio": 24, + "insulinOnBoard": 24.265, + "insulinSensitivity": 4.329583433015516, + "recommended": { + "carb": 2.5, + "correction": 2.25, + "net": 0 + }, + "units": "mmol/L", + "_active": true, + "_groupId": "abcdef", + "_schemaVersion": 0, + "_version": 0, + "clockDriftOffset": 0, + "conversionOffset": 0, + "createdTime": "2018-05-14T08:17:14.353Z", + "deviceId": "DevId0987654321", + "deviceTime": "2018-05-14T18:17:09", + "guid": "18d90ea0-5915-4e95-a8b2-cb22819ce696", + "id": "087c94ccdae84eb5a76b8205a244ec6b", + "time": "2018-05-14T08:17:09.353Z", + "timezoneOffset": 600, + "uploadId": "SampleUploadId" +} + */ \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/events/EventTidepoolDoUpload.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/events/EventTidepoolDoUpload.kt new file mode 100644 index 0000000000..d20868f348 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/events/EventTidepoolDoUpload.kt @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.general.tidepool.events + +import info.nightscout.androidaps.events.Event + +class EventTidepoolDoUpload : Event() \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/events/EventTidepoolResetData.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/events/EventTidepoolResetData.kt new file mode 100644 index 0000000000..833353e6b0 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/events/EventTidepoolResetData.kt @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.general.tidepool.events + +import info.nightscout.androidaps.events.Event + +class EventTidepoolResetData :Event() \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/events/EventTidepoolStatus.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/events/EventTidepoolStatus.kt new file mode 100644 index 0000000000..aa69c11e95 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/events/EventTidepoolStatus.kt @@ -0,0 +1,32 @@ +package info.nightscout.androidaps.plugins.general.tidepool.events + +import info.nightscout.androidaps.events.Event +import info.nightscout.androidaps.logging.L +import info.nightscout.androidaps.utils.DateUtil +import info.nightscout.androidaps.utils.LocaleHelper +import org.slf4j.LoggerFactory +import java.text.SimpleDateFormat + +class EventTidepoolStatus(val status: String) : Event() { + private val log = LoggerFactory.getLogger(L.TIDEPOOL) + + var date: Long = DateUtil.now() + + init { + if (L.isEnabled(L.TIDEPOOL)) + log.debug("New status: $status") + } + + private var timeFormat = SimpleDateFormat("HH:mm:ss", LocaleHelper.getLocale()) + + fun toPreparedHtml(): StringBuilder { + val stringBuilder = StringBuilder() + stringBuilder.append(timeFormat.format(date)) + stringBuilder.append(" ") + stringBuilder.append(status) + stringBuilder.append(" ") + stringBuilder.append("
") + return stringBuilder + } + +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/events/EventTidepoolUpdateGUI.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/events/EventTidepoolUpdateGUI.kt new file mode 100644 index 0000000000..de2b353dc0 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/events/EventTidepoolUpdateGUI.kt @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.general.tidepool.events + +import info.nightscout.androidaps.events.Event + +class EventTidepoolUpdateGUI : Event() diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/messages/AuthReplyMessage.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/messages/AuthReplyMessage.kt new file mode 100644 index 0000000000..57fa45c691 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/messages/AuthReplyMessage.kt @@ -0,0 +1,23 @@ +package info.nightscout.androidaps.plugins.general.tidepool.messages + +import com.google.gson.annotations.Expose +import com.google.gson.annotations.SerializedName + +class AuthReplyMessage { + + @Expose + @SerializedName("emailVerified") + internal var emailVerified: Boolean? = null + @Expose + @SerializedName("emails") + internal var emailList: List? = null + @Expose + @SerializedName("termsAccepted") + internal var termsDate: String? = null + @Expose + @SerializedName("userid") + internal var userid: String? = null + @Expose + @SerializedName("username") + internal var username: String? = null +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/messages/AuthRequestMessage.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/messages/AuthRequestMessage.kt new file mode 100644 index 0000000000..33c230ea75 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/messages/AuthRequestMessage.kt @@ -0,0 +1,17 @@ +package info.nightscout.androidaps.plugins.general.tidepool.messages + +import info.nightscout.androidaps.R +import info.nightscout.androidaps.utils.SP +import info.nightscout.androidaps.utils.StringUtils +import okhttp3.Credentials + +class AuthRequestMessage : BaseMessage() { + companion object { + fun getAuthRequestHeader(): String? { + val username = SP.getString(R.string.key_tidepool_username, null) + val password = SP.getString(R.string.key_tidepool_password, null) + + return if (StringUtils.emptyString(username) || StringUtils.emptyString(password)) null else Credentials.basic(username.trim { it <= ' ' }, password) + } + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/messages/BaseMessage.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/messages/BaseMessage.kt new file mode 100644 index 0000000000..d3cdffcf8c --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/messages/BaseMessage.kt @@ -0,0 +1,16 @@ +package info.nightscout.androidaps.plugins.general.tidepool.messages + +import info.nightscout.androidaps.plugins.general.tidepool.utils.GsonInstance +import okhttp3.MediaType +import okhttp3.RequestBody + +open class BaseMessage { + private fun toS(): String { + return GsonInstance.defaultGsonInstance().toJson(this) ?: "null" + } + + fun getBody(): RequestBody { + return RequestBody.create(MediaType.parse("application/json"), this.toS()) + } + +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/messages/CloseDatasetRequestMessage.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/messages/CloseDatasetRequestMessage.kt new file mode 100644 index 0000000000..f8f6780971 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/messages/CloseDatasetRequestMessage.kt @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.general.tidepool.messages + +import com.google.gson.annotations.Expose + +class CloseDatasetRequestMessage : BaseMessage() { + @Expose + internal var dataState = "closed" +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/messages/DatasetReplyMessage.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/messages/DatasetReplyMessage.kt new file mode 100644 index 0000000000..f19070624b --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/messages/DatasetReplyMessage.kt @@ -0,0 +1,42 @@ +package info.nightscout.androidaps.plugins.general.tidepool.messages + + +class DatasetReplyMessage { + + internal var data: Data? = null + + // openDataSet and others return this in the root of the json reply it seems + internal var id: String? = null + internal var uploadId: String? = null + + inner class Data { + internal var createdTime: String? = null + internal var deviceId: String? = null + internal var id: String? = null + internal var time: String? = null + internal var timezone: String? = null + internal var timezoneOffset: Int = 0 + internal var type: String? = null + internal var uploadId: String? = null + internal var client: Client? = null + internal var computerTime: String? = null + internal var dataSetType: String? = null + internal var deviceManufacturers: List? = null + internal var deviceModel: String? = null + internal var deviceSerialNumber: String? = null + internal var deviceTags: List? = null + internal var timeProcessing: String? = null + internal var version: String? = null + // meta + } + + inner class Client { + internal var name: String? = null + internal var version: String? = null + + } + + fun getUploadId(): String? { + return data?.uploadId ?: uploadId + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/messages/OpenDatasetRequestMessage.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/messages/OpenDatasetRequestMessage.kt new file mode 100644 index 0000000000..38b93b2f7b --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/messages/OpenDatasetRequestMessage.kt @@ -0,0 +1,57 @@ +package info.nightscout.androidaps.plugins.general.tidepool.messages + +import com.google.gson.annotations.Expose +import info.nightscout.androidaps.BuildConfig +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin +import info.nightscout.androidaps.plugins.general.tidepool.comm.TidepoolUploader +import info.nightscout.androidaps.utils.DateUtil +import info.nightscout.androidaps.utils.InstanceId +import info.nightscout.androidaps.utils.T +import java.util.* + +class OpenDatasetRequestMessage : BaseMessage() { + + @Expose + var deviceId: String = TidepoolUploader.PUMPTYPE + ":" + (ConfigBuilderPlugin.getPlugin().activePump?.serialNumber() + ?: InstanceId.instanceId()) + @Expose + var time = DateUtil.toISOAsUTC(DateUtil.now()) + @Expose + var timezoneOffset = (DateUtil.getTimeZoneOffsetMs() / T.mins(1).msecs()).toInt() + @Expose + var type = "upload" + //public String byUser; + @Expose + var client = ClientInfo() + @Expose + var computerTime = DateUtil.toISONoZone(DateUtil.now()) + @Expose + var dataSetType = "continuous" + @Expose + var deviceManufacturers = arrayOf(TidepoolUploader.PUMPTYPE) + @Expose + var deviceModel = TidepoolUploader.PUMPTYPE + @Expose + var deviceTags = arrayOf("bgm", "cgm", "insulin-pump") + @Expose + var deduplicator = Deduplicator() + @Expose + var timeProcessing = "none" + @Expose + var timezone = TimeZone.getDefault().id + @Expose + var version = BuildConfig.VERSION_NAME + + inner class ClientInfo { + @Expose + val name = BuildConfig.APPLICATION_ID + @Expose + val version = TidepoolUploader.VERSION + } + + inner class Deduplicator { + @Expose + val name = "org.tidepool.deduplicator.dataset.delete.origin" + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/messages/UploadReplyMessage.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/messages/UploadReplyMessage.kt new file mode 100644 index 0000000000..2054eb237a --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/messages/UploadReplyMessage.kt @@ -0,0 +1,6 @@ +package info.nightscout.androidaps.plugins.general.tidepool.messages + +class UploadReplyMessage { + + internal var data: List? = null +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/utils/GsonInstance.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/utils/GsonInstance.kt new file mode 100644 index 0000000000..2c7ceb81d0 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/utils/GsonInstance.kt @@ -0,0 +1,17 @@ +package info.nightscout.androidaps.plugins.general.tidepool.utils + +import com.google.gson.Gson +import com.google.gson.GsonBuilder + +object GsonInstance { + private var gson_instance: Gson? = null + + fun defaultGsonInstance(): Gson { + if (gson_instance == null) { + gson_instance = GsonBuilder() + .excludeFieldsWithoutExposeAnnotation() + .create() + } + return gson_instance as Gson + } +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/utils/RateLimit.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/utils/RateLimit.kt new file mode 100644 index 0000000000..88f09abdc2 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/utils/RateLimit.kt @@ -0,0 +1,31 @@ +package info.nightscout.androidaps.plugins.general.tidepool.utils + +import info.nightscout.androidaps.logging.L +import info.nightscout.androidaps.utils.DateUtil +import info.nightscout.androidaps.utils.T +import org.slf4j.LoggerFactory +import java.util.* + +object RateLimit { + + private val rateLimits = HashMap() + + private val log = LoggerFactory.getLogger(L.TIDEPOOL) + + // return true if below rate limit + @Synchronized + fun rateLimit(name: String, seconds: Int): Boolean { + // check if over limit + rateLimits[name]?.let { + if (DateUtil.now() - it < T.secs(seconds.toLong()).msecs()) { + if (L.isEnabled(L.TIDEPOOL)) + log.debug("$name rate limited: $seconds seconds") + return false + } + } + // not over limit + rateLimits[name] = DateUtil.now() + return true + } +} + diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/versionChecker/VersionCheckerPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/versionChecker/VersionCheckerPlugin.kt new file mode 100644 index 0000000000..c0335ea64a --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/versionChecker/VersionCheckerPlugin.kt @@ -0,0 +1,72 @@ +package info.nightscout.androidaps.plugins.general.versionChecker + +import info.nightscout.androidaps.MainApp +import info.nightscout.androidaps.R +import info.nightscout.androidaps.interfaces.* +import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification +import info.nightscout.androidaps.plugins.general.overview.notifications.Notification +import info.nightscout.androidaps.utils.SP +import java.util.concurrent.TimeUnit + +/** + * Usually we would have a class here. + * Instead of having a class we can use an object directly inherited from PluginBase. + * This is a lazy loading singleton only loaded when actually used. + * */ + +object VersionCheckerPlugin : PluginBase(PluginDescription() + .mainType(PluginType.CONSTRAINTS) + .neverVisible(true) + .alwaysEnabled(true) + .showInList(false) + .pluginName(R.string.versionChecker)), ConstraintsInterface { + + override fun isClosedLoopAllowed(value: Constraint): Constraint { + checkWarning() + triggerCheckVersion() + return if (isOldVersion(GRACE_PERIOD_VERY_OLD)) + value.set(false, MainApp.gs(R.string.very_old_version), this) + else + value + } + + private fun checkWarning() { + val now = System.currentTimeMillis() + + if (!SP.contains(R.string.key_last_versionchecker_plugin_warning)) { + SP.putLong(R.string.key_last_versionchecker_plugin_warning, now) + return + } + + + if (isOldVersion(GRACE_PERIOD_WARNING) && shouldWarnAgain(now)) { + // store last notification time + SP.putLong(R.string.key_last_versionchecker_plugin_warning, now) + + //notify + val message = MainApp.gs(R.string.new_version_warning, Math.round((now - SP.getLong(R.string.key_last_time_this_version_detected, now)) / TimeUnit.DAYS.toMillis(1).toDouble())) + val notification = Notification(Notification.OLDVERSION, message, Notification.NORMAL) + MainApp.bus().post(EventNewNotification(notification)) + } + } + + private fun shouldWarnAgain(now: Long) = + now > SP.getLong(R.string.key_last_versionchecker_plugin_warning, 0) + WARN_EVERY + + override fun applyMaxIOBConstraints(maxIob: Constraint): Constraint = + if (isOldVersion(GRACE_PERIOD_OLD)) + maxIob.set(0.toDouble(), MainApp.gs(R.string.old_version), this) + else + maxIob + + private fun isOldVersion(gracePeriod: Long): Boolean { + val now = System.currentTimeMillis() + return now > SP.getLong(R.string.key_last_time_this_version_detected, 0) + gracePeriod + } + + val WARN_EVERY = TimeUnit.DAYS.toMillis(1) + val GRACE_PERIOD_WARNING = TimeUnit.DAYS.toMillis(30) + val GRACE_PERIOD_OLD = TimeUnit.DAYS.toMillis(60) + val GRACE_PERIOD_VERY_OLD = TimeUnit.DAYS.toMillis(90) + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/versionChecker/VersionCheckerUtils.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/versionChecker/VersionCheckerUtils.kt new file mode 100644 index 0000000000..daebb5deb6 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/versionChecker/VersionCheckerUtils.kt @@ -0,0 +1,100 @@ +package info.nightscout.androidaps.plugins.general.versionChecker + +import android.content.Context +import android.net.ConnectivityManager +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.general.overview.events.EventNewNotification +import info.nightscout.androidaps.plugins.general.overview.notifications.Notification +import info.nightscout.androidaps.utils.SP +import org.slf4j.LoggerFactory +import java.io.IOException +import java.net.URL +import java.util.concurrent.TimeUnit + + +// check network connection +fun isConnected(): Boolean { + val connMgr = MainApp.instance().applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager + return connMgr.activeNetworkInfo?.isConnected ?: false +} + +fun findVersion(file :String?): String? { + val regex = "(.*)version(.*)\"(((\\d+)\\.)+(\\d+))\"(.*)".toRegex() + return file?.lines()?.filter { regex.matches(it) }?.mapNotNull { regex.matchEntire(it)?.groupValues?.getOrNull(3) }?.firstOrNull() +} + +private val log = LoggerFactory.getLogger(L.CORE) + + +fun triggerCheckVersion() { + + if (!SP.contains(R.string.key_last_time_this_version_detected)) { + // On a new installation, set it as 30 days old in order to warn that there is a new version. + SP.putLong(R.string.key_last_time_this_version_detected, System.currentTimeMillis() - TimeUnit.DAYS.toMillis(30)) + } + + // If we are good, only check once every day. + if (System.currentTimeMillis() > SP.getLong(R.string.key_last_time_this_version_detected, 0) + CHECK_EVERY) { + checkVersion() + } +} + +private fun checkVersion() = if (isConnected()) { + Thread { + try { + val version: String? = findVersion(URL("https://raw.githubusercontent.com/MilosKozak/AndroidAPS/master/app/build.gradle").readText()) + compareWithCurrentVersion(version, BuildConfig.VERSION_NAME) + } catch (e: IOException) { + log.debug("Github master version check error: $e") + } + }.start() +} else + log.debug("Github master version no checked. No connectivity") + +fun compareWithCurrentVersion(newVersion: String?, currentVersion: String) { + val comparison: Int? = newVersion?.versionStrip()?.compareTo(currentVersion.versionStrip()) + when { + comparison == null -> onVersionNotDetectable() + comparison == 0 -> onSameVersionDetected() + comparison > 0 -> onNewVersionDetected(currentVersion = currentVersion, newVersion = newVersion) + else -> onOlderVersionDetected() + } +} + +private fun onOlderVersionDetected() { + log.debug("Version newer than master. Are you developer?") + SP.putLong(R.string.key_last_time_this_version_detected, System.currentTimeMillis()) +} + +fun onSameVersionDetected() { + SP.putLong(R.string.key_last_time_this_version_detected, System.currentTimeMillis()) +} + +fun onVersionNotDetectable() { + log.debug("fetch failed, ignore and smartcast to non-null") +} + +fun onNewVersionDetected(currentVersion: String, newVersion: String?) { + val now = System.currentTimeMillis() + if (now > SP.getLong(R.string.key_last_versionchecker_warning, 0) + WARN_EVERY) { + log.debug("Version ${currentVersion} outdated. Found $newVersion") + val notification = Notification(Notification.NEWVERSIONDETECTED, String.format(MainApp.gs(R.string.versionavailable), newVersion.toString()), Notification.LOW) + MainApp.bus().post(EventNewNotification(notification)) + SP.putLong(R.string.key_last_versionchecker_warning, now) + } +} + +fun String.versionStrip() = this.mapNotNull { + when (it) { + in '0'..'9' -> it + '.' -> it + else -> null + } +}.joinToString(separator = "") + + +val CHECK_EVERY = TimeUnit.DAYS.toMillis(1) +val WARN_EVERY = TimeUnit.DAYS.toMillis(1) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/ActionStringHandler.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/ActionStringHandler.java index 1a01a783cd..addc6517ec 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/ActionStringHandler.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/ActionStringHandler.java @@ -3,7 +3,7 @@ package info.nightscout.androidaps.plugins.general.wear; import android.app.NotificationManager; import android.content.Context; import android.os.HandlerThread; -import android.support.annotation.NonNull; +import androidx.annotation.NonNull; import java.text.DateFormat; import java.text.DecimalFormat; @@ -207,6 +207,7 @@ public class ActionStringHandler { int percentage = Integer.parseInt(act[2]); Profile profile = ProfileFunctions.getInstance().getProfile(); + String profileName = ProfileFunctions.getInstance().getProfileName(); if (profile == null) { sendError("No profile found!"); return; @@ -226,45 +227,38 @@ public class ActionStringHandler { DecimalFormat format = new DecimalFormat("0.00"); DecimalFormat formatInt = new DecimalFormat("0"); - BolusWizard bolusWizard = new BolusWizard(); - bolusWizard.doCalc(profile, useTT ? TreatmentsPlugin.getPlugin().getTempTargetFromHistory() : null, - carbsAfterConstraints, useCOB?cobInfo.displayCob:0d, useBG ? bgReading.valueToUnits(profile.getUnits()) : 0d, - 0d, percentage, useBolusIOB, useBasalIOB, false, useTrend); + BolusWizard bolusWizard = new BolusWizard(profile, profileName, TreatmentsPlugin.getPlugin().getTempTargetFromHistory(), + carbsAfterConstraints, cobInfo.displayCob, bgReading.valueToUnits(profile.getUnits()), + 0d, percentage, useBG, useCOB, useBolusIOB, useBasalIOB, false, useTT, useTrend); - Double insulinAfterConstraints = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(bolusWizard.calculatedTotalInsulin)).value(); - if (Math.abs(insulinAfterConstraints - bolusWizard.calculatedTotalInsulin) >= 0.01) { + if (Math.abs(bolusWizard.getInsulinAfterConstraints() - bolusWizard.getCalculatedTotalInsulin()) >= 0.01) { sendError("Insulin constraint violation!" + - "\nCannot deliver " + format.format(bolusWizard.calculatedTotalInsulin) + "!"); + "\nCannot deliver " + format.format(bolusWizard.getCalculatedTotalInsulin()) + "!"); return; } - - if (bolusWizard.calculatedTotalInsulin < 0) { - bolusWizard.calculatedTotalInsulin = 0d; - } - - if (bolusWizard.calculatedTotalInsulin <= 0 && bolusWizard.carbs <= 0) { + if (bolusWizard.getCalculatedTotalInsulin() <= 0 && bolusWizard.getCarbs() <= 0) { rAction = "info"; rTitle = "INFO"; } else { rAction = actionstring; } - rMessage += "Carbs: " + bolusWizard.carbs + "g"; - rMessage += "\nBolus: " + format.format(bolusWizard.calculatedTotalInsulin) + "U"; + rMessage += "Carbs: " + bolusWizard.getCarbs() + "g"; + rMessage += "\nBolus: " + format.format(bolusWizard.getCalculatedTotalInsulin()) + "U"; rMessage += "\n_____________"; - rMessage += "\nCalc (IC:" + DecimalFormatter.to1Decimal(bolusWizard.ic) + ", " + "ISF:" + DecimalFormatter.to1Decimal(bolusWizard.sens) + "): "; - rMessage += "\nFrom Carbs: " + format.format(bolusWizard.insulinFromCarbs) + "U"; + rMessage += "\nCalc (IC:" + DecimalFormatter.to1Decimal(bolusWizard.getIc()) + ", " + "ISF:" + DecimalFormatter.to1Decimal(bolusWizard.getSens()) + "): "; + rMessage += "\nFrom Carbs: " + format.format(bolusWizard.getInsulinFromCarbs()) + "U"; if (useCOB) - rMessage += "\nFrom" + formatInt.format(cobInfo.displayCob) + "g COB : " + format.format(bolusWizard.insulinFromCOB) + "U"; - if (useBG) rMessage += "\nFrom BG: " + format.format(bolusWizard.insulinFromBG) + "U"; + rMessage += "\nFrom" + formatInt.format(cobInfo.displayCob) + "g COB : " + format.format(bolusWizard.getInsulinFromCOB()) + "U"; + if (useBG) rMessage += "\nFrom BG: " + format.format(bolusWizard.getInsulinFromBG()) + "U"; if (useBolusIOB) - rMessage += "\nBolus IOB: " + format.format(bolusWizard.insulingFromBolusIOB) + "U"; + rMessage += "\nBolus IOB: " + format.format(bolusWizard.getInsulinFromBolusIOB()) + "U"; if (useBasalIOB) - rMessage += "\nBasal IOB: " + format.format(bolusWizard.insulingFromBasalsIOB) + "U"; + rMessage += "\nBasal IOB: " + format.format(bolusWizard.getInsulinFromBasalsIOB()) + "U"; if (useTrend) - rMessage += "\nFrom 15' trend: " + format.format(bolusWizard.insulinFromTrend) + "U"; + rMessage += "\nFrom 15' trend: " + format.format(bolusWizard.getInsulinFromTrend()) + "U"; if (percentage != 100) { - rMessage += "\nPercentage: " + format.format(bolusWizard.totalBeforePercentageAdjustment) + "U * " + percentage + "% -> ~" + format.format(bolusWizard.calculatedTotalInsulin) + "U"; + rMessage += "\nPercentage: " + format.format(bolusWizard.getTotalBeforePercentageAdjustment()) + "U * " + percentage + "% -> ~" + format.format(bolusWizard.getCalculatedTotalInsulin()) + "U"; } lastBolusWizard = bolusWizard; @@ -628,7 +622,7 @@ public class ActionStringHandler { if (lastBolusWizard != null) { //use last calculation as confirmed string matches - doBolus(lastBolusWizard.calculatedTotalInsulin, lastBolusWizard.carbs); + doBolus(lastBolusWizard.getCalculatedTotalInsulin(), lastBolusWizard.getCarbs()); lastBolusWizard = null; } } else if ("bolus".equals(act[0])) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/WearFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/WearFragment.java index 701784e9d9..9eb157de24 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/WearFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/WearFragment.java @@ -1,7 +1,7 @@ package info.nightscout.androidaps.plugins.general.wear; import android.os.Bundle; -import android.support.v4.app.Fragment; +import androidx.fragment.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/wearintegration/WatchUpdaterService.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/wearintegration/WatchUpdaterService.java index 86b56ba130..6f2f59faa1 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/wearintegration/WatchUpdaterService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/wearintegration/WatchUpdaterService.java @@ -17,7 +17,7 @@ import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; import android.preference.PreferenceManager; -import android.support.annotation.NonNull; +import androidx.annotation.NonNull; import android.util.Log; import com.google.android.gms.common.ConnectionResult; @@ -32,17 +32,11 @@ import com.google.android.gms.wearable.PutDataRequest; import com.google.android.gms.wearable.Wearable; import com.google.android.gms.wearable.WearableListenerService; -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.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.Profile; import info.nightscout.androidaps.db.BgReading; @@ -55,15 +49,11 @@ import info.nightscout.androidaps.interfaces.PluginType; import info.nightscout.androidaps.interfaces.TreatmentsInterface; import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin; import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; import info.nightscout.androidaps.plugins.general.nsclient.data.NSDeviceStatus; import info.nightscout.androidaps.plugins.general.overview.OverviewPlugin; import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; import info.nightscout.androidaps.plugins.general.wear.ActionStringHandler; import info.nightscout.androidaps.plugins.general.wear.WearPlugin; -import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin; -import info.nightscout.androidaps.plugins.treatments.Treatment; -import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; import info.nightscout.androidaps.utils.DecimalFormatter; import info.nightscout.androidaps.utils.SP; import info.nightscout.androidaps.utils.SafeParse; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/xdripStatusline/StatuslinePlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/xdripStatusline/StatuslinePlugin.java index fe89cc8304..2421a1561e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/xdripStatusline/StatuslinePlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/xdripStatusline/StatuslinePlugin.java @@ -5,7 +5,7 @@ import android.content.Intent; import android.content.SharedPreferences; import android.os.Bundle; import android.preference.PreferenceManager; -import android.support.annotation.NonNull; +import androidx.annotation.NonNull; import com.squareup.otto.Subscribe; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/insulin/InsulinFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/insulin/InsulinFragment.java index bcf445d0d1..02e9256a8a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/insulin/InsulinFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/insulin/InsulinFragment.java @@ -1,7 +1,7 @@ package info.nightscout.androidaps.plugins.insulin; import android.os.Bundle; -import android.support.v4.app.Fragment; +import androidx.fragment.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/CobInfo.java b/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/CobInfo.java index 12d5cd5c11..fb99067008 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/CobInfo.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/CobInfo.java @@ -1,7 +1,7 @@ package info.nightscout.androidaps.plugins.iob.iobCobCalculator; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import info.nightscout.androidaps.utils.DecimalFormatter; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/GlucoseStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/GlucoseStatus.java new file mode 100644 index 0000000000..159c5865af --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/GlucoseStatus.java @@ -0,0 +1,180 @@ +package info.nightscout.androidaps.plugins.iob.iobCobCalculator; + +import androidx.annotation.Nullable; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; + +import info.nightscout.androidaps.db.BgReading; +import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.DecimalFormatter; +import info.nightscout.androidaps.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; + + + public String log() { + return "Glucose: " + DecimalFormatter.to0Decimal(glucose) + " mg/dl " + + "Delta: " + DecimalFormatter.to0Decimal(delta) + " mg/dl" + + "Short avg. delta: " + " " + DecimalFormatter.to2Decimal(short_avgdelta) + " mg/dl " + + "Long avg. delta: " + 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); + + synchronized (IobCobCalculatorPlugin.getPlugin().getDataLock()) { + + List data = IobCobCalculatorPlugin.getPlugin().getBgReadings(); + + if (data == null) { + if (L.isEnabled(L.GLUCOSE)) + log.debug("data=null"); + return null; + } + + int sizeRecords = data.size(); + if (sizeRecords == 0) { + if (L.isEnabled(L.GLUCOSE)) + log.debug("sizeRecords==0"); + return null; + } + + if (data.get(0).date < DateUtil.now() - 7 * 60 * 1000L && !allowOldData) { + if (L.isEnabled(L.GLUCOSE)) + log.debug("olddata"); + 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; + if (L.isEnabled(L.GLUCOSE)) + log.debug("sizeRecords==1"); + return status.round(); + } + + ArrayList now_value_list = new ArrayList<>(); + ArrayList last_deltas = new ArrayList<>(); + ArrayList short_deltas = new ArrayList<>(); + ArrayList long_deltas = new ArrayList<>(); + + // Use the latest sgv value in the now calculations + now_value_list.add(now.value); + + for (int i = 1; i < sizeRecords; i++) { + if (data.get(i).value > 38) { + BgReading then = data.get(i); + long then_date = then.date; + double avgdelta; + 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; + + if (L.isEnabled(L.GLUCOSE)) + log.debug(then.toString() + " minutesago=" + minutesago + " avgdelta=" + avgdelta); + + // use the average of all data points in the last 2.5m for all further "now" calculations + if (0 < minutesago && minutesago < 2.5) { + // Keep and average all values within the last 2.5 minutes + now_value_list.add(then.value); + now.value = average(now_value_list); + // 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); + } else { + // Do not process any more records after >= 42.5 minutes + break; + } + } + } + + 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 + + if (L.isEnabled(L.GLUCOSE)) + log.debug(status.log()); + 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/plugins/iob/iobCobCalculator/IobCobCalculatorPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/IobCobCalculatorPlugin.java index 45eeded757..f7c050a4fe 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/IobCobCalculatorPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/IobCobCalculatorPlugin.java @@ -1,9 +1,9 @@ package info.nightscout.androidaps.plugins.iob.iobCobCalculator; import android.os.SystemClock; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.util.LongSparseArray; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.collection.LongSparseArray; import com.squareup.otto.Subscribe; @@ -66,7 +66,7 @@ public class IobCobCalculatorPlugin extends PluginBase { private volatile List bgReadings = null; // newest at index 0 private volatile List bucketed_data = null; - final Object dataLock = new Object(); + private final Object dataLock = new Object(); boolean stopCalculationTrigger = false; private Thread thread = null; @@ -109,6 +109,10 @@ public class IobCobCalculatorPlugin extends PluginBase { return bucketed_data; } + public Object getDataLock() { + return dataLock; + } + // roundup to whole minute public static long roundUpTime(long time) { if (time % 60000 == 0) @@ -420,28 +424,30 @@ public class IobCobCalculatorPlugin extends PluginBase { } public BasalData getBasalData(Profile profile, long time) { - long now = System.currentTimeMillis(); - time = roundUpTime(time); - BasalData retval = basalDataTable.get(time); - if (retval == null) { - retval = new BasalData(); - TemporaryBasal tb = TreatmentsPlugin.getPlugin().getTempBasalFromHistory(time); - retval.basal = profile.getBasal(time); - if (tb != null) { - retval.isTempBasalRunning = true; - retval.tempBasalAbsolute = tb.tempBasalConvertedToAbsolute(time, profile); + synchronized (dataLock) { + long now = System.currentTimeMillis(); + time = roundUpTime(time); + BasalData retval = basalDataTable.get(time); + if (retval == null) { + retval = new BasalData(); + TemporaryBasal tb = TreatmentsPlugin.getPlugin().getTempBasalFromHistory(time); + retval.basal = profile.getBasal(time); + if (tb != null) { + retval.isTempBasalRunning = true; + retval.tempBasalAbsolute = tb.tempBasalConvertedToAbsolute(time, profile); + } else { + retval.isTempBasalRunning = false; + retval.tempBasalAbsolute = retval.basal; + } + if (time < now) { + basalDataTable.append(time, retval); + } + //log.debug(">>> getBasalData Cache miss " + new Date(time).toLocaleString()); } else { - retval.isTempBasalRunning = false; - retval.tempBasalAbsolute = retval.basal; + //log.debug(">>> getBasalData Cache hit " + new Date(time).toLocaleString()); } - if (time < now) { - basalDataTable.append(time, retval); - } - //log.debug(">>> getBasalData Cache miss " + new Date(time).toLocaleString()); - } else { - //log.debug(">>> getBasalData Cache hit " + new Date(time).toLocaleString()); + return retval; } - return retval; } @Nullable diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/IobCobOref1Thread.java b/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/IobCobOref1Thread.java index 492f3c0ff1..8ca13a6694 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/IobCobOref1Thread.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/IobCobOref1Thread.java @@ -3,7 +3,7 @@ package info.nightscout.androidaps.plugins.iob.iobCobCalculator; import android.content.Context; import android.os.PowerManager; import android.os.SystemClock; -import android.support.v4.util.LongSparseArray; +import androidx.collection.LongSparseArray; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -96,7 +96,7 @@ public class IobCobOref1Thread extends Thread { long oldestTimeWithData = iobCobCalculatorPlugin.calculateDetectionStart(end, limitDataToOldestAvailable); - synchronized (iobCobCalculatorPlugin.dataLock) { + synchronized (iobCobCalculatorPlugin.getDataLock()) { if (bgDataReload) { iobCobCalculatorPlugin.loadBgData(end); iobCobCalculatorPlugin.createBucketedData(); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/IobCobThread.java b/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/IobCobThread.java index 2aacb4f453..943637fd4e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/IobCobThread.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/IobCobThread.java @@ -3,7 +3,7 @@ package info.nightscout.androidaps.plugins.iob.iobCobCalculator; import android.content.Context; import android.os.PowerManager; import android.os.SystemClock; -import android.support.v4.util.LongSparseArray; +import androidx.collection.LongSparseArray; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -95,7 +95,7 @@ public class IobCobThread extends Thread { long oldestTimeWithData = iobCobCalculatorPlugin.calculateDetectionStart(end, limitDataToOldestAvailable); - synchronized (iobCobCalculatorPlugin.dataLock) { + synchronized (iobCobCalculatorPlugin.getDataLock()) { if (bgDataReload) { iobCobCalculatorPlugin.loadBgData(end); iobCobCalculatorPlugin.createBucketedData(); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/profile/local/LocalProfileFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/profile/local/LocalProfileFragment.java index ec5dc55fa8..9fe86c087f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/profile/local/LocalProfileFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/profile/local/LocalProfileFragment.java @@ -3,7 +3,7 @@ package info.nightscout.androidaps.plugins.profile.local; import android.app.Activity; import android.os.Bundle; -import android.support.annotation.NonNull; +import androidx.annotation.NonNull; import android.text.Editable; import android.text.TextWatcher; import android.view.LayoutInflater; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/profile/local/LocalProfilePlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/profile/local/LocalProfilePlugin.java index 06f979876c..089611b40d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/profile/local/LocalProfilePlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/profile/local/LocalProfilePlugin.java @@ -1,6 +1,6 @@ package info.nightscout.androidaps.plugins.profile.local; -import android.support.annotation.NonNull; +import androidx.annotation.NonNull; import org.json.JSONArray; import org.json.JSONException; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/profile/ns/NSProfilePlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/profile/ns/NSProfilePlugin.java index 11c38d1492..f741316732 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/profile/ns/NSProfilePlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/profile/ns/NSProfilePlugin.java @@ -2,7 +2,7 @@ package info.nightscout.androidaps.plugins.profile.ns; import android.content.Intent; import android.os.Bundle; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import org.json.JSONException; import org.json.JSONObject; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ComboFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ComboFragment.java index a533821d59..1a924fa9f5 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ComboFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ComboFragment.java @@ -5,7 +5,7 @@ import android.app.Activity; import android.graphics.Color; import android.graphics.Typeface; import android.os.Bundle; -import android.support.annotation.NonNull; +import androidx.annotation.NonNull; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ComboPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ComboPlugin.java index 557ba42168..7b6bf2d452 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ComboPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ComboPlugin.java @@ -2,10 +2,10 @@ package info.nightscout.androidaps.plugins.pump.combo; import android.content.DialogInterface; import android.os.SystemClock; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.app.FragmentActivity; -import android.support.v7.app.AlertDialog; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.FragmentActivity; +import androidx.appcompat.app.AlertDialog; import org.json.JSONObject; import org.slf4j.Logger; @@ -65,6 +65,7 @@ import info.nightscout.androidaps.plugins.pump.common.defs.PumpType; 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.InstanceId; import info.nightscout.androidaps.utils.SP; /** * Created by mike on 05.08.2016. @@ -1312,10 +1313,20 @@ public class ComboPlugin extends PluginBase implements PumpInterface, Constraint } @Override - public String deviceID() { + public String manufacter() { + return "Roche"; + } + + @Override + public String model() { return "Combo"; } + @Override + public String serialNumber() { + return InstanceId.INSTANCE.instanceId(); // TODO replace by real serial + } + @Override public PumpDescription getPumpDescription() { return pumpDescription; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ComboPump.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ComboPump.java index cfe459fb58..c5d7fa0115 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ComboPump.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ComboPump.java @@ -1,7 +1,7 @@ package info.nightscout.androidaps.plugins.pump.combo; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import java.util.ArrayList; import java.util.List; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/CommandResult.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/CommandResult.java index 180f10f69d..9febf0e86a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/CommandResult.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/CommandResult.java @@ -1,6 +1,6 @@ package info.nightscout.androidaps.plugins.pump.combo.ruffyscripter; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import java.util.LinkedList; import java.util.List; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/RuffyScripter.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/RuffyScripter.java index eb01c92c60..c057b9244b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/RuffyScripter.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/RuffyScripter.java @@ -7,8 +7,8 @@ import android.content.ServiceConnection; import android.os.IBinder; import android.os.RemoteException; import android.os.SystemClock; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import com.google.common.base.Joiner; @@ -242,6 +242,7 @@ public class RuffyScripter implements RuffyCommands { Thread cmdThread = null; try { activeCmd = cmd; + unparsableMenuEncountered = false; long connectStart = System.currentTimeMillis(); ensureConnected(); log.debug("Connection ready to execute cmd " + cmd); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/WarningOrErrorCode.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/WarningOrErrorCode.java index ae4723046e..7692afe84e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/WarningOrErrorCode.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/WarningOrErrorCode.java @@ -1,6 +1,6 @@ package info.nightscout.androidaps.plugins.pump.combo.ruffyscripter; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; public class WarningOrErrorCode { @Nullable diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/commands/BaseCommand.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/commands/BaseCommand.java index 6cd89f2938..1de9392cba 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/commands/BaseCommand.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/commands/BaseCommand.java @@ -1,6 +1,6 @@ package info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.commands; -import android.support.annotation.NonNull; +import androidx.annotation.NonNull; import org.monkey.d.ruffy.ruffy.driver.display.MenuAttribute; import org.monkey.d.ruffy.ruffy.driver.display.MenuType; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/commands/ReadHistoryCommand.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/commands/ReadHistoryCommand.java index 5f23b7e66d..b50ccaeb2c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/commands/ReadHistoryCommand.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/commands/ReadHistoryCommand.java @@ -1,6 +1,6 @@ package info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.commands; -import android.support.annotation.NonNull; +import androidx.annotation.NonNull; import org.monkey.d.ruffy.ruffy.driver.display.MenuAttribute; import org.monkey.d.ruffy.ruffy.driver.display.MenuType; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/history/PumpHistory.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/history/PumpHistory.java index 0fffe13c50..b9e9c704a0 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/history/PumpHistory.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/history/PumpHistory.java @@ -1,6 +1,6 @@ package info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.history; -import android.support.annotation.NonNull; +import androidx.annotation.NonNull; import java.util.ArrayList; import java.util.LinkedList; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpType.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpType.java index 9a7e351bf1..ecea843aa8 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpType.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpType.java @@ -7,7 +7,7 @@ import java.util.Map; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.plugins.pump.common.data.DoseSettings; - +import info.nightscout.androidaps.utils.Round; /** @@ -18,121 +18,123 @@ import info.nightscout.androidaps.plugins.pump.common.data.DoseSettings; public enum PumpType { - GenericAAPS("Generic AAPS", 0.1d, null, // - new DoseSettings(0.05d, 30, 8*60, 0.05d), // + GenericAAPS("Generic AAPS", "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", "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", "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", "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", "Roche", "Insight", 0.05d, DoseStepSize.InsightBolus, // + new DoseSettings(0.05d, 15, 24 * 60, 0.05d), // PumpTempBasalType.Percent, - new DoseSettings(10, 15, 24*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", 0.01d, null, // - new DoseSettings(0.01d, 15, 24*60, 0.05d), // + AccuChekInsightBluetooth("Accu-Chek Insight", "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, // + 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","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", "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", "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", "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", "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", "Medtronic", "512/712", 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, // + new DoseSettings(0.05d, 30, 24 * 60, 0d, 35d), PumpCapability.BasalRate_Duration30minAllowed, // 0.05d, 0.05d, null, PumpCapability.VirtualPumpCapabilities), // TODO - 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)", "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, // + new DoseSettings(0.05d, 30, 24 * 60, 0d, 35d), PumpCapability.BasalRate_Duration30minAllowed, // 0.025d, 0.025d, DoseStepSize.MedtronicVeoBasal, PumpCapability.VirtualPumpCapabilities), // - 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", "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", "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), // ; private String description; + private String manufacter; + private String model; private double bolusSize; private DoseStepSize specialBolusSize; private DoseSettings extendedBolusSettings; @@ -146,10 +148,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()) { @@ -158,33 +159,36 @@ public enum PumpType { } - PumpType(String description, PumpType parent) + PumpType(String description, String model, PumpType parent) { this.description = description; this.parent = parent; + parent.model = model; } - PumpType(String description, PumpType parent, PumpCapability pumpCapability) + 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, // + PumpType(String description, String manufacter, String model, 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); + this(description, manufacter, model, bolusSize, specialBolusSize, extendedBolusSettings, pumpTempBasalType, tbrSettings, specialBasalDurations, baseBasalMinValue, null, baseBasalStep, baseBasalSpecialSteps, pumpCapability); } - PumpType(String description, double bolusSize, DoseStepSize specialBolusSize, // + PumpType(String description, String manufacter, 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 baseBasalMaxValue, double baseBasalStep, DoseStepSize baseBasalSpecialSteps, PumpCapability pumpCapability) { this.description = description; + this.manufacter = manufacter; + this.model = model; this.bolusSize = bolusSize; this.specialBolusSize = specialBolusSize; this.extendedBolusSettings = extendedBolusSettings; @@ -203,6 +207,14 @@ public enum PumpType { return description; } + public String getManufacter() { + return isParentSet() ? parent.manufacter : manufacter; + } + + public String getModel() { + return isParentSet() ? parent.model : model; + } + public PumpCapability getPumpCapability() { if (isParentSet()) @@ -261,20 +273,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; } } @@ -282,7 +289,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(); @@ -291,24 +298,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; @@ -316,18 +321,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; } @@ -338,20 +340,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; @@ -371,7 +377,7 @@ public enum PumpType { bolusAmount = extendedBolusSettings.getMaxDose(); } - return Math.round(bolusAmount / bolusStepSize) * bolusStepSize; + return Round.roundTo(bolusAmount, bolusStepSize); } @@ -393,7 +399,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/danaR/AbstractDanaRPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/AbstractDanaRPlugin.java index 749307e1a7..b8b5409607 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/AbstractDanaRPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/AbstractDanaRPlugin.java @@ -1,6 +1,6 @@ package info.nightscout.androidaps.plugins.pump.danaR; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import org.json.JSONException; import org.json.JSONObject; @@ -376,7 +376,12 @@ public abstract class AbstractDanaRPlugin extends PluginBase implements PumpInte } @Override - public String deviceID() { + public String manufacter() { + return "SOOIL"; + }; + + @Override + public String serialNumber() { return DanaRPump.getInstance().serialNumber; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/DanaRFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/DanaRFragment.java index e044a2db27..30e99ebbe2 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/DanaRFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/DanaRFragment.java @@ -5,7 +5,7 @@ import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.os.Handler; -import android.support.v4.app.FragmentManager; +import androidx.fragment.app.FragmentManager; import android.text.Spanned; import android.view.LayoutInflater; import android.view.View; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/DanaRPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/DanaRPlugin.java index 2f7484cd6f..cbb06656fd 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/DanaRPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/DanaRPlugin.java @@ -5,8 +5,8 @@ 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 androidx.fragment.app.FragmentActivity; +import androidx.appcompat.app.AlertDialog; import com.squareup.otto.Subscribe; @@ -360,6 +360,11 @@ public class DanaRPlugin extends AbstractDanaRPlugin { return result; } + @Override + public String model() { + return "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/pump/danaR/Dialogs/ProfileViewDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/Dialogs/ProfileViewDialog.java index 2b09b180cf..06cfc289ad 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/Dialogs/ProfileViewDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/Dialogs/ProfileViewDialog.java @@ -1,7 +1,7 @@ package info.nightscout.androidaps.plugins.pump.danaR.dialogs; import android.os.Bundle; -import android.support.v4.app.DialogFragment; +import androidx.fragment.app.DialogFragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/activities/DanaRHistoryActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/activities/DanaRHistoryActivity.java index 95c9f25e37..617f99071d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/activities/DanaRHistoryActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/activities/DanaRHistoryActivity.java @@ -4,9 +4,9 @@ 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 androidx.cardview.widget.CardView; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgStatusBolusExtended.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgStatusBolusExtended.java index 9b27561d5a..aa272b546d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgStatusBolusExtended.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgStatusBolusExtended.java @@ -1,6 +1,6 @@ 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; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgStatusTempBasal.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgStatusTempBasal.java index 76fa0e9f43..00b3bf5f69 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/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.pump.danaR.comm; -import android.support.annotation.NonNull; +import androidx.annotation.NonNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRKorean/DanaRKoreanPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRKorean/DanaRKoreanPlugin.java index 3b4aa0ee4c..84e9cdf1e1 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRKorean/DanaRKoreanPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRKorean/DanaRKoreanPlugin.java @@ -5,8 +5,8 @@ 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 androidx.fragment.app.FragmentActivity; +import androidx.appcompat.app.AlertDialog; import com.squareup.otto.Subscribe; @@ -364,6 +364,11 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin { return result; } + @Override + public String model() { + return "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/danaRS/DanaRSPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/DanaRSPlugin.java index ddbb8547ae..4ec17af6d8 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/DanaRSPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/DanaRSPlugin.java @@ -5,9 +5,9 @@ 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 androidx.annotation.Nullable; +import androidx.fragment.app.FragmentActivity; +import androidx.appcompat.app.AlertDialog; import com.squareup.otto.Subscribe; @@ -769,7 +769,17 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte } @Override - public String deviceID() { + public String manufacter() { + return "SOOIL"; + } + + @Override + public String model() { + return "DanaRS"; + } + + @Override + public String serialNumber() { return DanaRPump.getInstance().serialNumber; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/activities/BLEScanActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/activities/BLEScanActivity.java index 502c18cbc9..e790fe7bfb 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/activities/BLEScanActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/activities/BLEScanActivity.java @@ -7,7 +7,7 @@ import android.bluetooth.le.ScanCallback; import android.bluetooth.le.ScanResult; import android.os.Bundle; import android.os.Handler; -import android.support.v7.app.AppCompatActivity; +import androidx.appcompat.app.AppCompatActivity; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/activities/PairingHelperActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/activities/PairingHelperActivity.java index a98d541963..6282ff8d0f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/activities/PairingHelperActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/activities/PairingHelperActivity.java @@ -1,6 +1,6 @@ package info.nightscout.androidaps.plugins.pump.danaRS.activities; -import android.support.v7.app.AppCompatActivity; +import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; public class PairingHelperActivity extends AppCompatActivity { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/activities/PairingProgressDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/activities/PairingProgressDialog.java index 1d9943a5f5..544b0c862e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/activities/PairingProgressDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/activities/PairingProgressDialog.java @@ -5,7 +5,7 @@ import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; -import android.support.v4.app.DialogFragment; +import androidx.fragment.app.DialogFragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/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 index 5724c5ff80..117baf23ff 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/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.pump.danaRS.comm; -import android.support.annotation.NonNull; +import androidx.annotation.NonNull; import com.cozmo.danar.util.BleCommandUtil; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/DanaRv2Plugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/DanaRv2Plugin.java index 9e3ca499d0..13af8fff1b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/DanaRv2Plugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/DanaRv2Plugin.java @@ -5,8 +5,8 @@ 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 androidx.fragment.app.FragmentActivity; +import androidx.appcompat.app.AlertDialog; import com.squareup.otto.Subscribe; @@ -402,6 +402,11 @@ public class DanaRv2Plugin extends AbstractDanaRPlugin { } } + @Override + public String model() { + return "DanaRv2"; + } + @Override public PumpEnactResult loadEvents() { return sExecutionService.loadEvents(); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/comm/MsgStatusBolusExtended_v2.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/comm/MsgStatusBolusExtended_v2.java index 578be6d4b6..a829b3afcb 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/comm/MsgStatusBolusExtended_v2.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/comm/MsgStatusBolusExtended_v2.java @@ -1,6 +1,6 @@ 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; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/comm/MsgStatusTempBasal_v2.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/comm/MsgStatusTempBasal_v2.java index a92c534d92..19a0a2b6ce 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/comm/MsgStatusTempBasal_v2.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/comm/MsgStatusTempBasal_v2.java @@ -1,6 +1,6 @@ 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; 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 index d851389aaf..26555898c0 100644 --- 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 @@ -15,7 +15,7 @@ import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.Vibrator; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; 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 index 26f5180f47..b973424d71 100644 --- 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 @@ -3,8 +3,8 @@ package info.nightscout.androidaps.plugins.pump.insight; import android.os.Bundle; import android.os.Handler; import android.os.Looper; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; 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 index c5b505a3d3..9114b38b40 100644 --- 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 @@ -168,7 +168,8 @@ public class LocalInsightPlugin extends PluginBase implements PumpInterface, Con .mainType(PluginType.PUMP) .description(R.string.description_pump_insight_local) .fragmentClass(LocalInsightFragment.class.getName()) - .preferencesId(R.xml.pref_insight_local)); + .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); @@ -416,8 +417,8 @@ public class LocalInsightPlugin extends PluginBase implements PumpInterface, Con 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; + 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(); @@ -470,8 +471,8 @@ public class LocalInsightPlugin extends PluginBase implements PumpInterface, Con if (activeBasalProfile != BasalProfile.PROFILE_1) return false; for (int i = 0; i < profileBlocks.size(); i++) { BasalProfileBlock profileBlock = profileBlocks.get(i); - Profile.BasalValue basalValue = profile.getBasalValues()[i]; - Profile.BasalValue nextValue = null; + 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) @@ -944,9 +945,19 @@ public class LocalInsightPlugin extends PluginBase implements PumpInterface, Con } @Override - public String deviceID() { - if (connectionService == null || alertService == null) return null; - return connectionService.getPumpSystemIdentification().getSerialNumber(); + public String manufacter() { + return "Roche"; + } + + @Override + public String model() { + return "Insight"; + } + + @Override + public String serialNumber() { + if (connectionService == null || alertService == null) return "Unknown"; + return connectionService.getPumpSystemIdentification().getSerialNumber(); } public PumpEnactResult stopPump() { 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 index c40cb99ed6..b255be2dd6 100644 --- 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 @@ -5,8 +5,8 @@ import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; -import android.support.v4.content.ContextCompat; -import android.support.v7.app.AppCompatActivity; +import androidx.core.content.ContextCompat; +import androidx.appcompat.app.AppCompatActivity; import android.text.Html; import android.view.View; import android.view.WindowManager; @@ -40,7 +40,7 @@ public class InsightAlertActivity extends AppCompatActivity { alertService.setAlertActivity(InsightAlertActivity.this); alert = alertService.getAlert(); if (alert == null) finish(); - update(alert); + else update(alert); } @Override 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 index 7ea52ed271..535d3d8bdb 100644 --- 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 @@ -10,11 +10,11 @@ import android.content.IntentFilter; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v7.app.AppCompatActivity; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -160,20 +160,25 @@ public class InsightPairingActivity extends AppCompatActivity implements Insight private void startBLScan() { if (!scanning) { BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); - 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; + 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.getDefaultAdapter().cancelDiscovery(); + BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); + if (bluetoothAdapter != null) { + bluetoothAdapter.cancelDiscovery(); + } scanning = false; } } 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 index 8580b30dca..9e6ee03d77 100644 --- 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 @@ -5,8 +5,8 @@ import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; -import android.support.annotation.Nullable; -import android.support.v7.app.AppCompatActivity; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; import android.view.View; import android.widget.TextView; 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 index e964c9fa20..cecb631776 100644 --- 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 @@ -8,7 +8,7 @@ import android.content.Intent; import android.os.Binder; import android.os.IBinder; import android.os.PowerManager; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/mdi/MDIPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/mdi/MDIPlugin.java index 89d1184581..13c2853ac7 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/mdi/MDIPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/mdi/MDIPlugin.java @@ -23,6 +23,7 @@ import info.nightscout.androidaps.plugins.general.actions.defs.CustomAction; import info.nightscout.androidaps.plugins.general.actions.defs.CustomActionType; import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.InstanceId; /** @@ -236,10 +237,20 @@ public class MDIPlugin extends PluginBase implements PumpInterface { } @Override - public String deviceID() { + public String manufacter() { + return "AndroidAPS"; + } + + @Override + public String model() { return "MDI"; } + @Override + public String serialNumber() { + return InstanceId.INSTANCE.instanceId(); + } + @Override public PumpDescription getPumpDescription() { return pumpDescription; @@ -247,7 +258,7 @@ public class MDIPlugin extends PluginBase implements PumpInterface { @Override public String shortStatus(boolean veryShort) { - return deviceID(); + return model(); } @Override diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/virtual/VirtualPumpFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/virtual/VirtualPumpFragment.java index 0b764f5382..be9bf17c85 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/virtual/VirtualPumpFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/virtual/VirtualPumpFragment.java @@ -4,7 +4,7 @@ package info.nightscout.androidaps.plugins.pump.virtual; import android.app.Activity; import android.os.Bundle; import android.os.Handler; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -20,8 +20,6 @@ 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.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.pump.virtual.events.EventVirtualPumpUpdateGui; import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/virtual/VirtualPumpPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/virtual/VirtualPumpPlugin.java index 461f71c31d..31b0e5456f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/virtual/VirtualPumpPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/virtual/VirtualPumpPlugin.java @@ -39,6 +39,7 @@ 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.InstanceId; import info.nightscout.androidaps.utils.SP; @@ -437,8 +438,18 @@ public class VirtualPumpPlugin extends PluginBase implements PumpInterface { } @Override - public String deviceID() { - return "VirtualPump"; + public String manufacter() { + return pumpDescription.pumpType.getManufacter(); + } + + @Override + public String model() { + return pumpDescription.pumpType.getModel(); + } + + @Override + public String serialNumber() { + return InstanceId.INSTANCE.instanceId(); } @Override 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 index 8e33b16302..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; -import android.support.v4.util.LongSparseArray; +import androidx.collection.LongSparseArray; import org.slf4j.Logger; import org.slf4j.LoggerFactory; 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 index 83800e1721..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; -import android.support.v4.util.LongSparseArray; +import androidx.collection.LongSparseArray; import org.slf4j.Logger; import org.slf4j.LoggerFactory; 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 index 3ce5c4861c..bbd987e6bd 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; -import android.support.v4.util.LongSparseArray; +import androidx.collection.LongSparseArray; import org.slf4j.Logger; import org.slf4j.LoggerFactory; 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 index 5b7268b560..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; -import android.support.v4.util.LongSparseArray; +import androidx.collection.LongSparseArray; import org.slf4j.Logger; import org.slf4j.LoggerFactory; 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 index 211cbb0bb0..269ee2b3f5 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 @@ -4,10 +4,10 @@ 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 androidx.annotation.NonNull; +import androidx.appcompat.app.AlertDialog; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; 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 3ba10564e6..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/SourceDexcomG5Plugin.java +++ /dev/null @@ -1,232 +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 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.services.Intents; -import info.nightscout.androidaps.utils.DateUtil; -import info.nightscout.androidaps.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_bgsource) - .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; - - if (intent.getAction().equals(Intents.DEXCOMG5_BG)) - handleNewDataOld(intent); - - if (intent.getAction().equals(Intents.DEXCOMG5_BG_NEW)) - handleNewDataNew(intent); - } - - public void handleNewDataOld(Intent intent) { - // onHandleIntent Bundle{ data => [{"m_time":1511939180,"m_trend":"NotComputable","m_value":335}]; android.support.content.wakelockid => 95; }Bundle - - 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, "AndroidAPS-DexcomG5"); - } - if (isNew && SP.getBoolean(R.string.key_dexcomg5_xdripupload, false)) { - NSUpload.sendToXdrip(bgReading); - } - } - - } catch (JSONException e) { - log.error("Exception: ", e); - } - } - - public void handleNewDataNew(Intent intent) { - - Bundle bundle = intent.getExtras(); - if (bundle == null) return; - - if (L.isEnabled(L.BGSOURCE)) { - if (bundle.containsKey("transmitterSystemTime")) - log.debug("transmitterSystemTime: " + DateUtil.dateAndTimeFullString(bundle.getLong("transmitterSystemTime"))); - if (bundle.containsKey("transmitterRemainingTime")) - log.debug("transmitterRemainingTime: " + DateUtil.dateAndTimeFullString(bundle.getLong("transmitterRemainingTime"))); - log.debug("transmitterId: " + bundle.getString("transmitterId")); - if (bundle.containsKey("transmitterActivatedOn")) - log.debug("transmitterActivatedOn: " + DateUtil.dateAndTimeFullString(bundle.getLong("transmitterActivatedOn"))); - log.debug("transmitterVersion: " + bundle.getString("transmitterVersion")); - log.debug("transmitterSoftwareNumber: " + bundle.getString("transmitterSoftwareNumber")); - log.debug("transmitterStorageTimeDays: " + bundle.getInt("transmitterStorageTimeDays")); - log.debug("transmitterApiVersion: " + bundle.getInt("transmitterApiVersion")); - log.debug("transmitterMaxRuntimeDays: " + bundle.getInt("transmitterMaxRuntimeDays")); - log.debug("transmitterMaxStorageTimeDays: " + bundle.getInt("transmitterMaxStorageTimeDays")); - log.debug("transmitterCGMProcessorFirmwareVersion: " + bundle.getString("transmitterCGMProcessorFirmwareVersion")); - log.debug("transmitterBleRadioFirmwareVersion: " + bundle.getString("transmitterBleRadioFirmwareVersion")); - log.debug("transmitterHardwareVersion: " + bundle.getInt("transmitterHardwareVersion")); - log.debug("transmitterBleSoftDeviceVersion: " + bundle.getString("transmitterBleSoftDeviceVersion")); - log.debug("transmitterNordicAsicHwID: " + bundle.getInt("transmitterNordicAsicHwID")); - log.debug("transmitterSessionTimeDays: " + bundle.getInt("transmitterSessionTimeDays")); - log.debug("transmitterFeatureFlags: " + bundle.getInt("transmitterFeatureFlags")); - } - - if (bundle.containsKey("sensorInsertionTime")) { - long sensorInsertionTime = bundle.getLong("sensorInsertionTime"); - if (L.isEnabled(L.BGSOURCE)) - log.debug("sensorInsertionTime: " + DateUtil.dateAndTimeFullString(sensorInsertionTime)); - if (SP.getBoolean(R.string.key_dexcom_lognssensorchange, false)) { - try { - if (MainApp.getDbHelper().getCareportalEventFromTimestamp(sensorInsertionTime) == null) { - JSONObject data = new JSONObject(); - data.put("enteredBy", "AndroidAPS-DexcomG5"); - data.put("created_at", DateUtil.toISOString(sensorInsertionTime)); - data.put("eventType", CareportalEvent.SENSORCHANGE); - NSUpload.uploadCareportalEntryToNS(data); - } - } catch (JSONException e) { - log.error("Unhandled exception", e); - } - } - } - - if (bundle.containsKey("glucoseValues")) { - int[] glucoseValues = bundle.getIntArray("glucoseValues"); - int[] glucoseRecordIDs = bundle.getIntArray("glucoseRecordIDs"); - long[] glucoseRecordedTimestamps = bundle.getLongArray("glucoseRecordedTimestamps"); - long[] glucoseSessionStartTimes = bundle.getLongArray("glucoseSessionStartTimes"); - long[] glucoseSystemTimestamps = bundle.getLongArray("glucoseSystemTimestamps"); - String[] glucoseTransmitterIDS = bundle.getStringArray("glucoseTransmitterIDS"); - long[] glucoseTransmitterTimestamps = bundle.getLongArray("glucoseTransmitterTimestamps"); - String[] glucoseTrendsArrows = bundle.getStringArray("glucoseTrendsArrows"); - boolean[] glucoseWasBackfilled = bundle.getBooleanArray("glucoseWasBackfilled"); - - if (L.isEnabled(L.BGSOURCE)) { - log.debug("glucoseValues", Arrays.toString(glucoseValues)); - log.debug("glucoseRecordIDs", Arrays.toString(glucoseRecordIDs)); - log.debug("glucoseRecordedTimestamps", Arrays.toString(glucoseRecordedTimestamps)); - log.debug("glucoseSessionStartTimes", Arrays.toString(glucoseSessionStartTimes)); - log.debug("glucoseSystemTimestamps", Arrays.toString(glucoseSystemTimestamps)); - log.debug("glucoseTransmitterIDS", Arrays.toString(glucoseTransmitterIDS)); - log.debug("glucoseTransmitterTimestamps", Arrays.toString(glucoseTransmitterTimestamps)); - log.debug("glucoseTrendsArrows", Arrays.toString(glucoseTrendsArrows)); - log.debug("glucoseWasBackfilled", Arrays.toString(glucoseWasBackfilled)); - } - - for (int i = 0; i < glucoseValues.length; i++) { - BgReading bgReading = new BgReading(); - bgReading.value = glucoseValues[i]; - bgReading.direction = glucoseTrendsArrows[i]; - bgReading.date = glucoseTransmitterTimestamps[i]; - bgReading.raw = 0; - boolean isNew = MainApp.getDbHelper().createIfNotExists(bgReading, "DexcomG5"); - if (isNew && SP.getBoolean(R.string.key_dexcomg5_nsupload, false)) { - NSUpload.uploadBg(bgReading, "AndroidAPS-DexcomG5"); - } - if (isNew && SP.getBoolean(R.string.key_dexcomg5_xdripupload, false)) { - NSUpload.sendToXdrip(bgReading); - } - } - } - - if (bundle.containsKey("meterValues")) { - String[] meterEntryTypes = bundle.getStringArray("meterEntryTypes"); - long[] meterTimestamps = bundle.getLongArray("meterTimestamps"); - int[] meterValues = bundle.getIntArray("meterValues"); - long[] meterRecordedTimestamps = bundle.getLongArray("meterRecordedTimestamps"); - int[] meterTransmitterIDs = bundle.getIntArray("meterTransmitterIDs"); - long[] meterTransmitterTimestamps = bundle.getLongArray("meterTransmitterTimestamps"); - - if (L.isEnabled(L.BGSOURCE)) { - log.debug("meterValues", Arrays.toString(meterValues)); - log.debug("meterEntryTypes", Arrays.toString(meterEntryTypes)); - log.debug("meterTimestamps", Arrays.toString(meterTimestamps)); - log.debug("meterTransmitterTimestamps", Arrays.toString(meterTransmitterTimestamps)); - log.debug("meterRecordedTimestamps", Arrays.toString(meterRecordedTimestamps)); - log.debug("meterTransmitterIDs", Arrays.toString(meterTransmitterIDs)); - } - - for (int i = 0; i < meterValues.length; i++) { - try { - if (MainApp.getDbHelper().getCareportalEventFromTimestamp(meterTimestamps[i]) == null) { - JSONObject data = new JSONObject(); - data.put("enteredBy", "AndroidAPS-DexcomG5"); - data.put("created_at", DateUtil.toISOString(meterTimestamps[i])); - data.put("eventType", CareportalEvent.BGCHECK); - data.put("glucoseType", "Finger"); - data.put("glucose", meterValues[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/SourceDexcomG6Plugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/source/SourceDexcomG6Plugin.java deleted file mode 100644 index ad63a9b9ae..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/SourceDexcomG6Plugin.java +++ /dev/null @@ -1,174 +0,0 @@ -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 30.11.2018. - */ - -public class SourceDexcomG6Plugin extends PluginBase implements BgSourceInterface { - private static Logger log = LoggerFactory.getLogger(L.BGSOURCE); - - private static SourceDexcomG6Plugin plugin = null; - - public static SourceDexcomG6Plugin getPlugin() { - if (plugin == null) - plugin = new SourceDexcomG6Plugin(); - return plugin; - } - - private SourceDexcomG6Plugin() { - super(new PluginDescription() - .mainType(PluginType.BGSOURCE) - .fragmentClass(BGSourceFragment.class.getName()) - .pluginName(R.string.DexcomG6) - .shortName(R.string.dexcomG6_shortname) - .preferencesId(R.xml.pref_bgsource) - .description(R.string.description_source_dexcom_g6) - ); - } - - @Override - public boolean advancedFilteringSupported() { - return true; - } - - @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("transmitterSystemTime")) - log.debug("transmitterSystemTime: " + DateUtil.dateAndTimeFullString(bundle.getLong("transmitterSystemTime"))); - log.debug("transmitterId: " + bundle.getString("transmitterId")); - if (bundle.containsKey("transmitterActivatedOn")) - log.debug("transmitterActivatedOn: " + DateUtil.dateAndTimeFullString(bundle.getLong("transmitterActivatedOn"))); - log.debug("transmitterVersion: " + bundle.getString("transmitterVersion")); - log.debug("transmitterSoftwareNumber: " + bundle.getString("transmitterSoftwareNumber")); - log.debug("transmitterStorageTimeDays: " + bundle.getInt("transmitterStorageTimeDays")); - log.debug("transmitterApiVersion: " + bundle.getInt("transmitterApiVersion")); - log.debug("transmitterMaxRuntimeDays: " + bundle.getInt("transmitterMaxRuntimeDays")); - log.debug("transmitterMaxStorageTimeDays: " + bundle.getInt("transmitterMaxStorageTimeDays")); - log.debug("transmitterCGMProcessorFirmwareVersion: " + bundle.getString("transmitterCGMProcessorFirmwareVersion")); - log.debug("transmitterBleRadioFirmwareVersion: " + bundle.getString("transmitterBleRadioFirmwareVersion")); - log.debug("transmitterHardwareVersion: " + bundle.getInt("transmitterHardwareVersion")); - log.debug("transmitterBleSoftDeviceVersion: " + bundle.getString("transmitterBleSoftDeviceVersion")); - log.debug("transmitterNordicAsicHwID: " + bundle.getInt("transmitterNordicAsicHwID")); - log.debug("transmitterSessionTimeDays: " + bundle.getInt("transmitterSessionTimeDays")); - log.debug("transmitterFeatureFlags: " + bundle.getInt("transmitterFeatureFlags")); - - if (bundle.containsKey("sensorCode")) - log.debug("sensorCode: " + bundle.getString("sensorCode")); - } - - if (bundle.containsKey("sensorInsertionTime")) { - long sensorInsertionTime = bundle.getLong("sensorInsertionTime"); - if (L.isEnabled(L.BGSOURCE)) - log.debug("sensorInsertionTime: " + DateUtil.dateAndTimeFullString(sensorInsertionTime)); - if (SP.getBoolean(R.string.key_dexcom_lognssensorchange, false)) { - try { - if (MainApp.getDbHelper().getCareportalEventFromTimestamp(sensorInsertionTime) == null) { - JSONObject data = new JSONObject(); - data.put("enteredBy", "AndroidAPS-DexcomG6"); - data.put("created_at", DateUtil.toISOString(sensorInsertionTime)); - data.put("eventType", CareportalEvent.SENSORCHANGE); - NSUpload.uploadCareportalEntryToNS(data); - } - } catch (JSONException e) { - log.error("Unhandled exception", e); - } - } - } - - if (bundle.containsKey("evgTimestamps")) { - long[] timestamps = bundle.getLongArray("evgTimestamps"); - long[] transmitterTimes = bundle.getLongArray("transmitterTimes"); - int[] evgs = bundle.getIntArray("evgs"); - int[] predictiveEVGs = bundle.getIntArray("predictiveEVGs"); - String[] trendArrows = bundle.getStringArray("trendArrows"); - - if (L.isEnabled(L.BGSOURCE)) { - log.debug("timestamps", Arrays.toString(timestamps)); - log.debug("transmitterTimes", Arrays.toString(transmitterTimes)); - log.debug("evgs", Arrays.toString(evgs)); - log.debug("predictiveEVGs", Arrays.toString(predictiveEVGs)); - log.debug("trendArrows", Arrays.toString(trendArrows)); - } - - for (int i = 0; i < transmitterTimes.length; i++) { - BgReading bgReading = new BgReading(); - bgReading.value = evgs[i]; - bgReading.direction = trendArrows[i]; - bgReading.date = timestamps[i]; - bgReading.raw = 0; - boolean isNew = MainApp.getDbHelper().createIfNotExists(bgReading, "DexcomG6"); - if (isNew && SP.getBoolean(R.string.key_dexcomg5_nsupload, false)) { - NSUpload.uploadBg(bgReading, "AndroidAPS-DexcomG6"); - } - if (isNew && SP.getBoolean(R.string.key_dexcomg5_xdripupload, false)) { - NSUpload.sendToXdrip(bgReading); - } - } - } - - if (bundle.containsKey("meterValues")) { - int[] meterValues = bundle.getIntArray("meterValues"); - String[] meterEntryTypes = bundle.getStringArray("meterEntryTypes"); - long[] meterTimestamps = bundle.getLongArray("meterTimestamps"); - long[] meterTransmitterTimestamps = bundle.getLongArray("meterTransmitterTimestamps"); - long[] meterRecordedTimestamps = bundle.getLongArray("meterRecordedTimestamps"); - int[] meterRecordIDs = bundle.getIntArray("meterRecordIDs"); - - if (L.isEnabled(L.BGSOURCE)) { - log.debug("meterValues", Arrays.toString(meterValues)); - log.debug("meterEntryTypes", Arrays.toString(meterEntryTypes)); - log.debug("meterTimestamps", Arrays.toString(meterTimestamps)); - log.debug("meterTransmitterTimestamps", Arrays.toString(meterTransmitterTimestamps)); - log.debug("meterRecordedTimestamps", Arrays.toString(meterRecordedTimestamps)); - log.debug("meterRecordIDs", Arrays.toString(meterRecordIDs)); - } - - for (int i = 0; i < meterValues.length; i++) { - try { - if (MainApp.getDbHelper().getCareportalEventFromTimestamp(meterTimestamps[i]) == null) { - JSONObject data = new JSONObject(); - data.put("enteredBy", "AndroidAPS-DexcomG6"); - data.put("created_at", DateUtil.toISOString(meterTimestamps[i])); - data.put("eventType", CareportalEvent.BGCHECK); - data.put("glucoseType", "Finger"); - data.put("glucose", meterValues[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/SourceDexcomPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/SourceDexcomPlugin.kt new file mode 100644 index 0000000000..6119c07c37 --- /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 android.os.Build +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 (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && 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 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")) { + if (SP.getBoolean(R.string.key_dexcomg5_nsupload, false)) { + NSUpload.uploadBg(bgReading, "AndroidAPS-DexcomG6") + } + 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") + 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") + 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/treatments/CarbsGenerator.java b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/CarbsGenerator.java index ac9be50a23..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,7 +1,7 @@ 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; 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 index dbf1a89c37..9a26e4f4e9 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,7 +1,7 @@ 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; @@ -16,9 +16,11 @@ 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.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.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; @@ -142,6 +144,15 @@ public class Treatment implements DataPointWithLabelInterface { 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 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 index 7bb4774911..be1ca8e8e6 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 @@ -2,7 +2,7 @@ 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; @@ -190,8 +190,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)); @@ -499,6 +500,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 index d30565b4a7..192952057d 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,8 +1,8 @@ package info.nightscout.androidaps.plugins.treatments; import android.os.Bundle; -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentTransaction; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentTransaction; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; 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 index f06902a1a9..0cc8afc571 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 @@ -2,7 +2,7 @@ package info.nightscout.androidaps.plugins.treatments; import android.content.Intent; import android.os.Bundle; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.firebase.analytics.FirebaseAnalytics; import com.squareup.otto.Subscribe; @@ -536,7 +536,7 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface } @Override - public Intervals getTemporaryBasalsFromHistory() { + public NonOverlappingIntervals getTemporaryBasalsFromHistory() { synchronized (tempBasals) { return new NonOverlappingIntervals<>(tempBasals); } 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 index c38672311b..e068e094f1 100644 --- 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 @@ -1,7 +1,7 @@ package info.nightscout.androidaps.plugins.treatments.dialogs; import android.os.Bundle; -import android.support.v4.app.DialogFragment; +import androidx.fragment.app.DialogFragment; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; 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 index c8db29b617..a3b6234a22 100644 --- 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 @@ -1,7 +1,7 @@ package info.nightscout.androidaps.plugins.treatments.fragments; import android.os.Bundle; -import android.support.v4.app.DialogFragment; +import androidx.fragment.app.DialogFragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; 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 index 26a8494dd7..c2320fc3ce 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 @@ -6,12 +6,12 @@ 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 androidx.fragment.app.FragmentManager; +import androidx.core.content.ContextCompat; +import androidx.appcompat.app.AlertDialog; +import androidx.cardview.widget.CardView; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; 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 index 2f45f67c3b..2ec61597d7 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 @@ -6,10 +6,10 @@ 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 androidx.appcompat.app.AlertDialog; +import androidx.cardview.widget.CardView; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; 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 index 766190e378..24a5185ef0 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 @@ -5,11 +5,11 @@ 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 androidx.core.content.ContextCompat; +import androidx.appcompat.app.AlertDialog; +import androidx.cardview.widget.CardView; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; 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 index c59d5e1836..5d5919f69f 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 @@ -6,12 +6,12 @@ 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 androidx.fragment.app.FragmentManager; +import androidx.core.content.ContextCompat; +import androidx.appcompat.app.AlertDialog; +import androidx.cardview.widget.CardView; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; 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 index eda62a8318..56b887c295 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 @@ -6,11 +6,11 @@ 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 androidx.core.content.ContextCompat; +import androidx.appcompat.app.AlertDialog; +import androidx.cardview.widget.CardView; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; 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 index 7b935d354e..6aed7aea43 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 @@ -4,12 +4,12 @@ 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 androidx.annotation.NonNull; +import androidx.core.content.ContextCompat; +import androidx.appcompat.app.AlertDialog; +import androidx.cardview.widget.CardView; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; 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 e4fbacc43c..edfb2aeff1 100644 --- a/app/src/main/java/info/nightscout/androidaps/queue/CommandQueue.java +++ b/app/src/main/java/info/nightscout/androidaps/queue/CommandQueue.java @@ -3,7 +3,7 @@ package info.nightscout.androidaps.queue; import android.content.Context; import android.content.Intent; import android.os.SystemClock; -import android.support.v7.app.AppCompatActivity; +import androidx.appcompat.app.AppCompatActivity; import android.text.Html; import android.text.Spanned; @@ -143,11 +143,11 @@ public class CommandQueue { return queue.size(); } - public Command performing() { + Command performing() { return performing; } - public void resetPerforming() { + void resetPerforming() { performing = null; } @@ -386,10 +386,10 @@ public class CommandQueue { } // 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)); 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 0962952221..a7e106c042 100644 --- a/app/src/main/java/info/nightscout/androidaps/queue/QueueThread.java +++ b/app/src/main/java/info/nightscout/androidaps/queue/QueueThread.java @@ -141,15 +141,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()); + MainApp.bus().post(new EventQueueChanged()); + queue.performing().execute(); + queue.resetPerforming(); + MainApp.bus().post(new EventQueueChanged()); + lastCommandTime = System.currentTimeMillis(); + SystemClock.sleep(100); + continue; + } } } @@ -173,7 +175,7 @@ public class QueueThread extends Thread { } } } finally { - if (mWakeLock != null) + 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/receivers/ChargingStateReceiver.java b/app/src/main/java/info/nightscout/androidaps/receivers/ChargingStateReceiver.java index b10c2e99e5..349e1771b9 100644 --- a/app/src/main/java/info/nightscout/androidaps/receivers/ChargingStateReceiver.java +++ b/app/src/main/java/info/nightscout/androidaps/receivers/ChargingStateReceiver.java @@ -10,12 +10,15 @@ import info.nightscout.androidaps.events.EventChargingState; 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); + lastEvent = event; } public EventChargingState grabChargingState(Context context) { @@ -32,4 +35,7 @@ public class ChargingStateReceiver extends BroadcastReceiver { return event; } + static public boolean isCharging() { + return lastEvent != null && lastEvent.isCharging; + } } \ 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/NetworkChangeReceiver.java b/app/src/main/java/info/nightscout/androidaps/receivers/NetworkChangeReceiver.java index 9a3108e98c..4a462906b3 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; @@ -21,6 +21,8 @@ public class NetworkChangeReceiver extends BroadcastReceiver { private static Logger log = LoggerFactory.getLogger(L.CORE); + private static EventNetworkChange lastEvent = null; + @Override public void onReceive(final Context context, final Intent intent) { EventNetworkChange event = grabNetworkStatus(context); @@ -61,6 +63,11 @@ public class NetworkChangeReceiver extends BroadcastReceiver { log.debug("NETCHANGE: Disconnected."); } + lastEvent = event; return event; } + + public static boolean isWifiConnected() { + return lastEvent != null && lastEvent.wifiConnected; + } } \ 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..a62f2c6fb7 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 @@ -40,6 +41,8 @@ public class AlarmSoundService extends Service { } 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)) @@ -75,8 +78,11 @@ public class AlarmSoundService extends Service { @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 b98ff6bf94..6b8ac46f11 100644 --- a/app/src/main/java/info/nightscout/androidaps/services/DataService.java +++ b/app/src/main/java/info/nightscout/androidaps/services/DataService.java @@ -25,8 +25,7 @@ import info.nightscout.androidaps.plugins.general.overview.notifications.Notific import info.nightscout.androidaps.plugins.profile.ns.NSProfilePlugin; import info.nightscout.androidaps.plugins.pump.danaR.activities.DanaRNSHistorySync; import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin; -import info.nightscout.androidaps.plugins.source.SourceDexcomG5Plugin; -import info.nightscout.androidaps.plugins.source.SourceDexcomG6Plugin; +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; @@ -69,12 +68,8 @@ 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.DEXCOMG5_BG_NEW.equals(action)) { - SourceDexcomG5Plugin.getPlugin().handleNewData(intent); - } else if (Intents.DEXCOMG6_BG.equals(action)) { - SourceDexcomG6Plugin.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)) { 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 5011215b45..a5b26561b5 100644 --- a/app/src/main/java/info/nightscout/androidaps/services/Intents.java +++ b/app/src/main/java/info/nightscout/androidaps/services/Intents.java @@ -48,9 +48,7 @@ public interface Intents { String GLIMP_BG = "it.ct.glicemia.ACTION_GLUCOSE_MEASURED"; - String DEXCOMG5_BG = "com.dexcom.cgm.DATA"; - String DEXCOMG5_BG_NEW = "com.dexcom.cgm.g5.AndroidAPSEVGCallback.BROADCAST"; - String DEXCOMG6_BG = "com.dexcom.cgm.AndroidAPSEVGCallback.BROADCAST"; + String DEXCOM_BG = "com.dexcom.cgm.EXTERNAL_BROADCAST"; String EVERSENSE_BG = "com.senseonics.AndroidAPSEventSubscriber.BROADCAST"; String POCTECH_BG = "com.china.poctech.data"; 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 1d143d073f..3be94c494e 100644 --- a/app/src/main/java/info/nightscout/androidaps/setupwizard/SWDefinition.java +++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/SWDefinition.java @@ -3,7 +3,7 @@ package info.nightscout.androidaps.setupwizard; import android.Manifest; import android.content.Intent; import android.os.Build; -import android.support.v7.app.AppCompatActivity; +import androidx.appcompat.app.AppCompatActivity; import com.squareup.otto.Subscribe; 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 9049ad7463..777463583d 100644 --- a/app/src/main/java/info/nightscout/androidaps/setupwizard/SetupWizardActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/SetupWizardActivity.java @@ -3,9 +3,9 @@ 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 androidx.core.app.ActivityCompat; +import androidx.appcompat.app.AlertDialog; +import androidx.appcompat.app.AppCompatActivity; import android.view.View; import android.widget.LinearLayout; import android.widget.ScrollView; 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 4e8113c73c..6206cb0d9a 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 @@ -12,6 +12,7 @@ import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.plugins.bus.RxBus; import info.nightscout.androidaps.events.EventPreferenceChange; import info.nightscout.androidaps.logging.L; import info.nightscout.androidaps.setupwizard.events.EventSWUpdate; @@ -98,6 +99,7 @@ public class SWItem { if (L.isEnabled(L.CORE)) log.debug("Firing EventPreferenceChange"); MainApp.bus().post(new EventPreferenceChange(preferenceId)); + RxBus.INSTANCE.send(new EventPreferenceChange(preferenceId)); MainApp.bus().post(new EventSWUpdate()); scheduledEventPost = null; } 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 53b3700c72..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; diff --git a/app/src/main/java/info/nightscout/androidaps/utils/AndroidPermission.java b/app/src/main/java/info/nightscout/androidaps/utils/AndroidPermission.java index 3f6c3a3ce0..527a98dda2 100644 --- a/app/src/main/java/info/nightscout/androidaps/utils/AndroidPermission.java +++ b/app/src/main/java/info/nightscout/androidaps/utils/AndroidPermission.java @@ -5,8 +5,8 @@ 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 androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; diff --git a/app/src/main/java/info/nightscout/androidaps/utils/BolusWizard.java b/app/src/main/java/info/nightscout/androidaps/utils/BolusWizard.java deleted file mode 100644 index e47a74e17f..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/utils/BolusWizard.java +++ /dev/null @@ -1,183 +0,0 @@ -package info.nightscout.androidaps.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/androidaps/utils/BolusWizard.kt b/app/src/main/java/info/nightscout/androidaps/utils/BolusWizard.kt new file mode 100644 index 0000000000..e9a1b180c2 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/utils/BolusWizard.kt @@ -0,0 +1,344 @@ +package info.nightscout.androidaps.utils + +import android.content.Context +import android.content.Intent +import android.text.Html +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.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.treatments.TreatmentsPlugin +import info.nightscout.androidaps.queue.Callback +import org.json.JSONException +import org.json.JSONObject +import org.slf4j.LoggerFactory +import java.util.* + +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 + + var targetBGLow = 0.0 + private set + + var targetBGHigh = 0.0 + private set + + var bgDiff = 0.0 + private set + + 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 + + var accepted = false + private set + + // 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) { + if (bg >= targetBGLow && bg <= targetBGHigh) { + bgDiff = 0.0 + } else if (bg <= targetBGLow) { + bgDiff = bg - targetBGLow + } else { + bgDiff = 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 + } + } + + + // Insuling 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()) + } + + 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) + } 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) + confirmMessage += "
" + MainApp.gs(R.string.bolus) + ": " + "" + DecimalFormatter.toPumpSupportedBolus(insulinAfterConstraints) + "U" + "" + if (carbs > 0) + confirmMessage += "
" + MainApp.gs(R.string.carbs) + ": " + "" + carbs + "g" + "" + + if (Math.abs(insulinAfterConstraints - calculatedTotalInsulin) > pump.getPumpDescription().pumpType.determineCorrectBolusStepSize(insulinAfterConstraints)) { + confirmMessage += "
" + MainApp.gs(R.string.bolusconstraintapplied) + "" + } + + return confirmMessage + } + + fun confirmAndExecute(context: Context) { + val profile = ProfileFunctions.getInstance().profile + val pump = ConfigBuilderPlugin.getPlugin().activePump + + if (pump != null && profile != null && (calculatedTotalInsulin > 0.0 || carbs > 0.0)) { + val confirmMessage = confirmMessageAfterConstraints(pump) + + val builder = AlertDialog.Builder(context) + builder.setTitle(MainApp.gs(R.string.confirmation)) + builder.setMessage(Html.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) + MainApp.bus().post(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/androidaps/utils/DateUtil.java b/app/src/main/java/info/nightscout/androidaps/utils/DateUtil.java index 7cc4424244..951ed08407 100644 --- a/app/src/main/java/info/nightscout/androidaps/utils/DateUtil.java +++ b/app/src/main/java/info/nightscout/androidaps/utils/DateUtil.java @@ -1,6 +1,6 @@ package info.nightscout.androidaps.utils; -import android.support.v4.util.LongSparseArray; +import androidx.collection.LongSparseArray; import org.joda.time.DateTime; import org.joda.time.format.DateTimeFormat; @@ -8,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; @@ -71,6 +73,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 @@ -187,4 +201,80 @@ public class DateUtil { long diff = Math.abs(date - now()); return diff < T.mins(2).msecs(); } + + 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/androidaps/utils/FabricPrivacy.java b/app/src/main/java/info/nightscout/androidaps/utils/FabricPrivacy.java index 54f06bfaf0..3dd7fe4fd9 100644 --- a/app/src/main/java/info/nightscout/androidaps/utils/FabricPrivacy.java +++ b/app/src/main/java/info/nightscout/androidaps/utils/FabricPrivacy.java @@ -121,7 +121,7 @@ public class FabricPrivacy { .replace(".net/", ":"); MainApp.getFirebaseAnalytics().setUserProperty("Mode", BuildConfig.APPLICATION_ID + "-" + closedLoopEnabled); - MainApp.getFirebaseAnalytics().setUserProperty("Language", LocaleHelper.getLanguage(MainApp.instance())); + MainApp.getFirebaseAnalytics().setUserProperty("Language", LocaleHelper.getLanguage()); MainApp.getFirebaseAnalytics().setUserProperty("Version", BuildConfig.VERSION); MainApp.getFirebaseAnalytics().setUserProperty("HEAD", BuildConfig.HEAD); MainApp.getFirebaseAnalytics().setUserProperty("Remote", remote); 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/androidaps/utils/JsonHelper.java b/app/src/main/java/info/nightscout/androidaps/utils/JsonHelper.java index 8f7d9611b1..c130353419 100644 --- a/app/src/main/java/info/nightscout/androidaps/utils/JsonHelper.java +++ b/app/src/main/java/info/nightscout/androidaps/utils/JsonHelper.java @@ -1,6 +1,6 @@ package info.nightscout.androidaps.utils; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import org.json.JSONException; import org.json.JSONObject; diff --git a/app/src/main/java/info/nightscout/androidaps/utils/LocaleHelper.java b/app/src/main/java/info/nightscout/androidaps/utils/LocaleHelper.java index bf0b2796ee..d2e4c0622b 100644 --- a/app/src/main/java/info/nightscout/androidaps/utils/LocaleHelper.java +++ b/app/src/main/java/info/nightscout/androidaps/utils/LocaleHelper.java @@ -21,17 +21,17 @@ 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()); + String lang = getPersistedData(Locale.getDefault().getLanguage()); setLocale(context, lang); } public static void onCreate(Context context, String defaultLanguage) { - String lang = getPersistedData(context, defaultLanguage); + String lang = getPersistedData(defaultLanguage); setLocale(context, lang); } - public static String getLanguage(Context context) { - return getPersistedData(context, Locale.getDefault().getLanguage()); + public static String getLanguage() { + return getPersistedData(Locale.getDefault().getLanguage()); } public static void setLocale(Context context, String language) { @@ -39,7 +39,7 @@ public class LocaleHelper { updateResources(context, language); } - private static String getPersistedData(Context context, String defaultLanguage) { + private static String getPersistedData(String defaultLanguage) { return SP.getString(SELECTED_LANGUAGE, defaultLanguage); } @@ -62,4 +62,8 @@ public class LocaleHelper { resources.updateConfiguration(configuration, resources.getDisplayMetrics()); } + + public static Locale getLocale() { + return new Locale(getPersistedData("en")); + } } \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/utils/OKDialog.java b/app/src/main/java/info/nightscout/androidaps/utils/OKDialog.java index 00b3c29692..98d8845ff8 100644 --- a/app/src/main/java/info/nightscout/androidaps/utils/OKDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/utils/OKDialog.java @@ -5,8 +5,8 @@ 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; diff --git a/app/src/main/java/info/nightscout/androidaps/utils/SingleClickButton.java b/app/src/main/java/info/nightscout/androidaps/utils/SingleClickButton.java index eef4ca57fe..74500ebdbc 100644 --- a/app/src/main/java/info/nightscout/androidaps/utils/SingleClickButton.java +++ b/app/src/main/java/info/nightscout/androidaps/utils/SingleClickButton.java @@ -3,7 +3,7 @@ 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/StringUtils.java b/app/src/main/java/info/nightscout/androidaps/utils/StringUtils.java index cad2b76291..74e8da7c9d 100644 --- a/app/src/main/java/info/nightscout/androidaps/utils/StringUtils.java +++ b/app/src/main/java/info/nightscout/androidaps/utils/StringUtils.java @@ -1,5 +1,8 @@ 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/androidaps/utils/T.java b/app/src/main/java/info/nightscout/androidaps/utils/T.java index 2a9bcfc42c..5671f0725c 100644 --- a/app/src/main/java/info/nightscout/androidaps/utils/T.java +++ b/app/src/main/java/info/nightscout/androidaps/utils/T.java @@ -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/androidaps/utils/TimeListEdit.java b/app/src/main/java/info/nightscout/androidaps/utils/TimeListEdit.java index d120e102d1..c8f767f77e 100644 --- a/app/src/main/java/info/nightscout/androidaps/utils/TimeListEdit.java +++ b/app/src/main/java/info/nightscout/androidaps/utils/TimeListEdit.java @@ -2,8 +2,8 @@ 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 androidx.core.content.ContextCompat; +import androidx.core.widget.TextViewCompat; import android.text.Editable; import android.text.TextWatcher; import android.view.Gravity; diff --git a/app/src/main/java/info/nightscout/androidaps/utils/VersionChecker.java b/app/src/main/java/info/nightscout/androidaps/utils/VersionChecker.java deleted file mode 100644 index fd636b4596..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/utils/VersionChecker.java +++ /dev/null @@ -1,100 +0,0 @@ -package info.nightscout.androidaps.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.general.overview.events.EventNewNotification; -import info.nightscout.androidaps.plugins.general.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) { - 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 m.group(3); - } 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/info/nightscout/androidaps/utils/XdripCalibrations.java b/app/src/main/java/info/nightscout/androidaps/utils/XdripCalibrations.java index 99961a156b..f7b8761823 100644 --- a/app/src/main/java/info/nightscout/androidaps/utils/XdripCalibrations.java +++ b/app/src/main/java/info/nightscout/androidaps/utils/XdripCalibrations.java @@ -5,7 +5,7 @@ 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; diff --git a/app/src/main/res/layout/activity_historybrowse.xml b/app/src/main/res/layout/activity_historybrowse.xml index 96b2b5871c..84f52f48c8 100644 --- a/app/src/main/res/layout/activity_historybrowse.xml +++ b/app/src/main/res/layout/activity_historybrowse.xml @@ -1,5 +1,5 @@ - - + diff --git a/app/src/main/res/layout/activity_insight_pairing.xml b/app/src/main/res/layout/activity_insight_pairing.xml index d90b5f091d..83412a8645 100644 --- a/app/src/main/res/layout/activity_insight_pairing.xml +++ b/app/src/main/res/layout/activity_insight_pairing.xml @@ -18,7 +18,7 @@ android:text="@string/searching_for_devices" android:textSize="20sp" /> - - - - - + - - - - + \ No newline at end of file diff --git a/app/src/main/res/layout/bgsource_fragment.xml b/app/src/main/res/layout/bgsource_fragment.xml index 73829c12d4..6619b6bafa 100644 --- a/app/src/main/res/layout/bgsource_fragment.xml +++ b/app/src/main/res/layout/bgsource_fragment.xml @@ -10,12 +10,12 @@ android:layout_height="match_parent" android:orientation="vertical"> - - + diff --git a/app/src/main/res/layout/bgsource_item.xml b/app/src/main/res/layout/bgsource_item.xml index acd0454327..4cb3be97b8 100644 --- a/app/src/main/res/layout/bgsource_item.xml +++ b/app/src/main/res/layout/bgsource_item.xml @@ -1,5 +1,5 @@ - - + diff --git a/app/src/main/res/layout/careportal_fragment.xml b/app/src/main/res/layout/careportal_fragment.xml index 1e4c72dd72..a9791a1b88 100644 --- a/app/src/main/res/layout/careportal_fragment.xml +++ b/app/src/main/res/layout/careportal_fragment.xml @@ -45,7 +45,7 @@ android:paddingStart="15dp" android:text="@string/careportal_activity_label" /> - - + - - + - - + - - + diff --git a/app/src/main/res/layout/danar_history_item.xml b/app/src/main/res/layout/danar_history_item.xml index 6df07edd62..b03a26f55a 100644 --- a/app/src/main/res/layout/danar_history_item.xml +++ b/app/src/main/res/layout/danar_history_item.xml @@ -1,5 +1,5 @@ - - + diff --git a/app/src/main/res/layout/danar_historyactivity.xml b/app/src/main/res/layout/danar_historyactivity.xml index 8c7f8a8e6e..f3cc2ece29 100644 --- a/app/src/main/res/layout/danar_historyactivity.xml +++ b/app/src/main/res/layout/danar_historyactivity.xml @@ -50,7 +50,7 @@ android:layout_gravity="center_horizontal" android:gravity="center_horizontal" /> - - - + diff --git a/app/src/main/res/layout/food_item.xml b/app/src/main/res/layout/food_item.xml index d4efc403a3..b6b6adbcf8 100644 --- a/app/src/main/res/layout/food_item.xml +++ b/app/src/main/res/layout/food_item.xml @@ -1,5 +1,5 @@ - - + diff --git a/app/src/main/res/layout/objectives_fragment.xml b/app/src/main/res/layout/objectives_fragment.xml index f2b18e703d..56edc011f9 100644 --- a/app/src/main/res/layout/objectives_fragment.xml +++ b/app/src/main/res/layout/objectives_fragment.xml @@ -31,7 +31,7 @@ android:text="Reset" /> - - - + diff --git a/app/src/main/res/layout/overview_fragment.xml b/app/src/main/res/layout/overview_fragment.xml index a21cf30d03..2192ac62f4 100644 --- a/app/src/main/res/layout/overview_fragment.xml +++ b/app/src/main/res/layout/overview_fragment.xml @@ -20,12 +20,12 @@ android:layout_height="wrap_content" android:orientation="vertical"> - - + - - + - - + - - + - - + diff --git a/app/src/main/res/layout/overview_quickwizardlist_activity.xml b/app/src/main/res/layout/overview_quickwizardlist_activity.xml index 227f946486..3ef067d044 100644 --- a/app/src/main/res/layout/overview_quickwizardlist_activity.xml +++ b/app/src/main/res/layout/overview_quickwizardlist_activity.xml @@ -29,7 +29,7 @@ android:layout_height="wrap_content" android:id="@+id/overview_quickwizardactivity_add_button" /> - diff --git a/app/src/main/res/layout/overview_quickwizardlist_item.xml b/app/src/main/res/layout/overview_quickwizardlist_item.xml index 429e2ca2de..5d186ffaf4 100644 --- a/app/src/main/res/layout/overview_quickwizardlist_item.xml +++ b/app/src/main/res/layout/overview_quickwizardlist_item.xml @@ -1,5 +1,5 @@ - - + diff --git a/app/src/main/res/layout/tidepool_fragment.xml b/app/src/main/res/layout/tidepool_fragment.xml new file mode 100644 index 0000000000..2640e96893 --- /dev/null +++ b/app/src/main/res/layout/tidepool_fragment.xml @@ -0,0 +1,74 @@ + + + + + +