commit
95abf17ff4
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -8,7 +8,6 @@
|
|||
build/
|
||||
.idea/*
|
||||
!.idea/codeStyles/
|
||||
app/src/main/jniLibs
|
||||
full/
|
||||
debug/
|
||||
release/
|
||||
|
|
|
@ -2,11 +2,31 @@
|
|||
<code_scheme name="Project" version="173">
|
||||
<option name="AUTODETECT_INDENTS" value="false" />
|
||||
<JetCodeStyleSettings>
|
||||
<option name="PACKAGES_TO_USE_STAR_IMPORTS">
|
||||
<value>
|
||||
<package name="java.util" alias="false" withSubpackages="false" />
|
||||
<package name="kotlinx.android.synthetic" alias="false" withSubpackages="true" />
|
||||
<package name="io.ktor" alias="false" withSubpackages="true" />
|
||||
</value>
|
||||
</option>
|
||||
<option name="PACKAGES_IMPORT_LAYOUT">
|
||||
<value>
|
||||
<package name="" alias="false" withSubpackages="true" />
|
||||
<package name="java" alias="false" withSubpackages="true" />
|
||||
<package name="javax" alias="false" withSubpackages="true" />
|
||||
<package name="kotlin" alias="false" withSubpackages="true" />
|
||||
<package name="" alias="true" withSubpackages="true" />
|
||||
</value>
|
||||
</option>
|
||||
<option name="ALIGN_IN_COLUMNS_CASE_BRANCH" value="true" />
|
||||
<option name="NAME_COUNT_TO_USE_STAR_IMPORT" value="6" />
|
||||
<option name="NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS" value="6" />
|
||||
<option name="BLANK_LINES_AROUND_BLOCK_WHEN_BRANCHES" value="1" />
|
||||
</JetCodeStyleSettings>
|
||||
<codeStyleSettings language="JAVA">
|
||||
<option name="METHOD_ANNOTATION_WRAP" value="0" />
|
||||
<option name="FIELD_ANNOTATION_WRAP" value="0" />
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="XML">
|
||||
<indentOptions>
|
||||
<option name="CONTINUATION_INDENT_SIZE" value="4" />
|
||||
|
@ -126,6 +146,8 @@
|
|||
<option name="KEEP_BLANK_LINES_IN_CODE" value="1" />
|
||||
<option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="1" />
|
||||
<option name="BLANK_LINES_AFTER_CLASS_HEADER" value="1" />
|
||||
<option name="METHOD_ANNOTATION_WRAP" value="5" />
|
||||
<option name="FIELD_ANNOTATION_WRAP" value="0" />
|
||||
<indentOptions>
|
||||
<option name="CONTINUATION_INDENT_SIZE" value="4" />
|
||||
</indentOptions>
|
||||
|
|
|
@ -8,7 +8,7 @@ android:
|
|||
components:
|
||||
- platform-tools
|
||||
- tools
|
||||
- build-tools-28.0.3
|
||||
- build-tools-29.0.2
|
||||
- android-28
|
||||
- extra-google-m2repository
|
||||
- extra-android-m2repository
|
||||
|
|
|
@ -42,7 +42,7 @@ Hints
|
|||
-----
|
||||
|
||||
* Start small, it is easier to review smaller changes that affect fewer parts of code
|
||||
* Take a look into Issues list (https://github.com/MilosKozak/AndroidAPS/issues) - maybe there is somthing you can fix or implement
|
||||
* Take a look into Issues list (https://github.com/nightscout/AndroidAPS/issues) - maybe there is something you can fix or implement
|
||||
* For new features, make sure there is Issue to track progress and have on-topic discussion
|
||||
* Reach out to community, discuss idea on Gitter (https://gitter.im/MilosKozak/AndroidAPS)
|
||||
* Speak with other developers to minimise merge conflicts. Find out who worked, working or plan to work on speciffic issue or part of app
|
||||
|
|
|
@ -6,5 +6,5 @@ Reporting bugs
|
|||
upper-right corner).
|
||||
- Obtain the app's log files, which can be found on the phone in
|
||||
_/storage/emulated/0/Android/data/info.nightscout.androidaps/_
|
||||
See https://github.com/MilosKozak/AndroidAPS/wiki/Accessing-logfiles
|
||||
- Open an issue at https://github.com/MilosKozak/AndroidAPS/issues/new
|
||||
See https://androidaps.readthedocs.io/en/latest/EN/Usage/Accessing-logfiles.html
|
||||
- Open an issue at https://github.com/nightscout/AndroidAPS/issues/new
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
# AndroidAPS
|
||||
|
||||
* Check the wiki: http://wiki.androidaps.org
|
||||
* Check the wiki: https://androidaps.readthedocs.io
|
||||
* Everyone who’s been looping with AndroidAPS needs to fill out the form after 3 days of looping https://docs.google.com/forms/d/14KcMjlINPMJHVt28MDRupa4sz4DDIooI4SrW0P3HSN8/viewform?c=0&w=1
|
||||
|
||||
[![Gitter](https://badges.gitter.im/MilosKozak/AndroidAPS.svg)](https://gitter.im/MilosKozak/AndroidAPS?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
[![Build status](https://travis-ci.org/MilosKozak/AndroidAPS.svg?branch=master)](https://travis-ci.org/MilosKozak/AndroidAPS)
|
||||
[![Build status](https://travis-ci.org/nightscout/AndroidAPS.svg?branch=master)](https://travis-ci.org/nightscout/AndroidAPS)
|
||||
[![Crowdin](https://d322cqt584bo4o.cloudfront.net/androidaps/localized.svg)](https://translations.androidaps.org/project/androidaps)
|
||||
[![Documentation Status](https://readthedocs.org/projects/androidaps/badge/?version=latest)](https://androidaps.readthedocs.io/en/latest/?badge=latest)
|
||||
[![codecov](https://codecov.io/gh/MilosKozak/AndroidAPS/branch/master/graph/badge.svg)](https://codecov.io/gh/MilosKozak/AndroidAPS)
|
||||
|
|
185
app/build.gradle
185
app/build.gradle
|
@ -1,40 +1,39 @@
|
|||
buildscript {
|
||||
repositories {
|
||||
maven { url 'https://maven.fabric.io/public' }
|
||||
jcenter()
|
||||
maven { url "https://plugins.gradle.org/m2/" } // jacoco 0.2
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'io.fabric.tools:gradle:1.+'
|
||||
classpath 'com.dicedmelon.gradle:jacoco-android:0.1.4'
|
||||
classpath 'de.undercouch:gradle-download-task:3.4.3'
|
||||
//classpath 'com.dicedmelon.gradle:jacoco-android:0.1.4'
|
||||
classpath 'com.hiya:jacoco-android:0.2'
|
||||
}
|
||||
}
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
apply plugin: 'kotlin-kapt'
|
||||
apply plugin: 'com.google.gms.google-services'
|
||||
apply plugin: 'io.fabric'
|
||||
apply plugin: 'jacoco-android'
|
||||
apply plugin: 'de.undercouch.download'
|
||||
|
||||
//apply plugin: 'jacoco-android'
|
||||
apply plugin: 'com.hiya.jacoco-android'
|
||||
apply plugin: 'com.google.firebase.crashlytics'
|
||||
|
||||
jacoco {
|
||||
toolVersion = "0.8.3"
|
||||
}
|
||||
|
||||
ext {
|
||||
supportLibraryVersion = "28.0.0"
|
||||
ormLiteVersion = "4.46"
|
||||
powermockVersion = "1.7.3"
|
||||
dexmakerVersion = "1.2"
|
||||
retrofit2Version = '2.9.0'
|
||||
okhttp3Version = '4.7.2'
|
||||
}
|
||||
|
||||
|
||||
repositories {
|
||||
maven { url 'https://maven.fabric.io/public' }
|
||||
jcenter { url "https://jcenter.bintray.com/" }
|
||||
mavenCentral()
|
||||
google()
|
||||
}
|
||||
|
||||
def generateGitBuild = { ->
|
||||
|
@ -79,6 +78,23 @@ def isMaster = { ->
|
|||
return !version.contains('-')
|
||||
}
|
||||
|
||||
def gitAvailable = { ->
|
||||
StringBuilder stringBuilder = new StringBuilder()
|
||||
try {
|
||||
def stdout = new ByteArrayOutputStream()
|
||||
exec {
|
||||
commandLine 'git', '--version'
|
||||
standardOutput = stdout
|
||||
}
|
||||
String commitObject = stdout.toString().trim()
|
||||
stringBuilder.append(commitObject)
|
||||
} catch (ignored) {
|
||||
return false // NoGitSystemAvailable
|
||||
}
|
||||
return !stringBuilder.toString().isEmpty()
|
||||
|
||||
}
|
||||
|
||||
def allCommited = { ->
|
||||
StringBuilder stringBuilder = new StringBuilder()
|
||||
try {
|
||||
|
@ -103,13 +119,14 @@ tasks.matching { it instanceof Test }.all {
|
|||
|
||||
android {
|
||||
compileSdkVersion 28
|
||||
ndkVersion "21.1.6352462"
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 23
|
||||
minSdkVersion 24
|
||||
targetSdkVersion 28
|
||||
multiDexEnabled true
|
||||
versionCode 1500
|
||||
version "2.6.1.4"
|
||||
version "2.7.0-dev"
|
||||
buildConfigField "String", "VERSION", '"' + version + '"'
|
||||
buildConfigField "String", "BUILDVERSION", '"' + generateGitBuild() + '-' + generateDate() + '"'
|
||||
buildConfigField "String", "REMOTE", '"' + generateGitRemote() + '"'
|
||||
|
@ -125,12 +142,6 @@ android {
|
|||
jvmTarget = '1.8'
|
||||
}
|
||||
lintOptions {
|
||||
// TODO remove once wear dependency com.google.android.gms:play-services-wearable:7.3.0
|
||||
// has been upgraded (requiring significant code changes), which currently fails release
|
||||
// build with a deprecation warning
|
||||
// abortOnError false
|
||||
// (disabled entirely to avoid reports on the error, which would still be displayed
|
||||
// and it's easy to overlook that it's ignored)
|
||||
checkReleaseBuilds false
|
||||
disable 'MissingTranslation'
|
||||
disable 'ExtraTranslation'
|
||||
|
@ -145,6 +156,7 @@ android {
|
|||
}
|
||||
firebaseDisable {
|
||||
System.setProperty("disableFirebase", "true")
|
||||
ext.enableCrashlytics = false
|
||||
}
|
||||
}
|
||||
productFlavors {
|
||||
|
@ -208,6 +220,10 @@ android {
|
|||
}
|
||||
|
||||
useLibrary "org.apache.http.legacy"
|
||||
|
||||
configurations.all {
|
||||
resolutionStrategy.force 'com.google.code.findbugs:jsr305:1.3.9'
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
|
@ -223,41 +239,49 @@ allprojects {
|
|||
dependencies {
|
||||
wearApp project(':wear')
|
||||
|
||||
implementation project(':core')
|
||||
implementation project(':dana')
|
||||
implementation project(':danars')
|
||||
implementation project(':danar')
|
||||
implementation project(':rileylink')
|
||||
implementation project(':medtronic')
|
||||
|
||||
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||
implementation 'com.google.android.gms:play-services-wearable:17.0.0'
|
||||
implementation 'com.google.firebase:firebase-core:17.2.1'
|
||||
implementation 'com.google.firebase:firebase-auth:19.2.0'
|
||||
implementation 'com.google.firebase:firebase-database:19.2.0'
|
||||
implementation('com.crashlytics.sdk.android:crashlytics:2.10.1@aar') {
|
||||
transitive = true;
|
||||
}
|
||||
implementation "com.google.android.gms:play-services-location:17.0.0"
|
||||
implementation 'com.google.firebase:firebase-core:17.4.3'
|
||||
implementation 'com.google.firebase:firebase-auth:19.3.1'
|
||||
implementation 'com.google.firebase:firebase-database:19.3.1'
|
||||
|
||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||
implementation 'androidx.legacy:legacy-support-v13:1.0.0'
|
||||
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
||||
implementation 'androidx.cardview:cardview:1.0.0'
|
||||
implementation 'androidx.biometric:biometric:1.0.1'
|
||||
implementation 'androidx.recyclerview:recyclerview:1.1.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:4.2.3'
|
||||
implementation "androidx.preference:preference-ktx:1.1.1"
|
||||
implementation "androidx.activity:activity-ktx:${activityVersion}"
|
||||
implementation "androidx.fragment:fragment:${fragmentVersion}"
|
||||
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
||||
implementation 'com.google.android.material:material:1.1.0'
|
||||
|
||||
implementation "io.reactivex.rxjava2:rxandroid:2.1.1"
|
||||
implementation "io.reactivex.rxjava2:rxandroid:${rxandroid_version}"
|
||||
|
||||
implementation "com.j256.ormlite:ormlite-core:${ormLiteVersion}"
|
||||
implementation "com.j256.ormlite:ormlite-android:${ormLiteVersion}"
|
||||
implementation("com.github.tony19:logback-android-classic:1.1.1-6") {
|
||||
exclude group: "com.google.android", module: "android"
|
||||
}
|
||||
implementation "org.apache.commons:commons-lang3:3.9"
|
||||
implementation "org.slf4j:slf4j-api:1.7.29"
|
||||
implementation 'org.apache.commons:commons-lang3:3.10'
|
||||
implementation 'org.slf4j:slf4j-api:1.7.30'
|
||||
// Graphview cannot be upgraded
|
||||
implementation "com.jjoe64:graphview:4.0.1"
|
||||
implementation "com.joanzapata.iconify:android-iconify-fontawesome:2.2.2"
|
||||
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'
|
||||
|
||||
// Omnipod wizard
|
||||
implementation(name: "com.atech-software.android.library.wizardpager-1.1.4", ext: "aar")
|
||||
implementation("com.google.android:flexbox:0.3.0") {
|
||||
exclude group: "com.android.support"
|
||||
}
|
||||
|
@ -266,82 +290,79 @@ dependencies {
|
|||
exclude group: "org.json", module: "json"
|
||||
}
|
||||
implementation "com.google.code.gson:gson:2.8.6"
|
||||
implementation ("com.google.guava:guava:24.1-jre") {
|
||||
implementation('com.google.guava:guava:29.0-jre') {
|
||||
exclude group: "com.google.code.findbugs", module: "jsr305"
|
||||
}
|
||||
implementation 'com.google.code.findbugs:jsr305:3.0.2'
|
||||
|
||||
implementation "net.danlew:android.joda:2.10.3"
|
||||
implementation 'net.danlew:android.joda:2.10.6'
|
||||
|
||||
implementation 'org.mozilla:rhino:1.7.11'
|
||||
implementation 'org.mozilla:rhino:1.7.12'
|
||||
|
||||
implementation 'com.github.DavidProdinger:weekdays-selector:1.1.0'
|
||||
|
||||
testImplementation "junit:junit:4.12"
|
||||
testImplementation "org.json:json:20190722"
|
||||
implementation 'com.github.kenglxn.QRGen:android:2.6.0'
|
||||
implementation 'com.eatthepath:java-otp:0.2.0'
|
||||
|
||||
testImplementation "junit:junit:4.13"
|
||||
testImplementation 'org.json:json:20200518'
|
||||
testImplementation "org.mockito:mockito-core:2.8.47"
|
||||
testImplementation "org.powermock:powermock-api-mockito2:${powermockVersion}"
|
||||
testImplementation "org.powermock:powermock-module-junit4-rule-agent:${powermockVersion}"
|
||||
testImplementation "org.powermock:powermock-module-junit4-rule:${powermockVersion}"
|
||||
testImplementation "org.powermock:powermock-module-junit4:${powermockVersion}"
|
||||
testImplementation "joda-time:joda-time:2.10.5"
|
||||
testImplementation("com.google.truth:truth:0.39") {
|
||||
testImplementation 'joda-time:joda-time:2.10.6'
|
||||
testImplementation('com.google.truth:truth:1.0.1') {
|
||||
exclude group: "com.google.guava", module: "guava"
|
||||
exclude group: "com.google.code.findbugs", module: "jsr305"
|
||||
}
|
||||
testImplementation "org.skyscreamer:jsonassert:1.5.0"
|
||||
testImplementation "org.hamcrest:hamcrest-all:1.3"
|
||||
/*
|
||||
testImplementation("uk.org.lidalia:slf4j-test:1.2.0") {
|
||||
exclude group: "com.google.guava", module: "guava"
|
||||
}
|
||||
*/
|
||||
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
|
||||
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutinesVersion"
|
||||
|
||||
// new for tidepool
|
||||
implementation 'com.squareup.okhttp3:okhttp:4.2.2'
|
||||
implementation 'com.squareup.okhttp3:logging-interceptor:4.2.2'
|
||||
implementation "com.squareup.retrofit2:retrofit:2.6.2"
|
||||
implementation "com.squareup.retrofit2:adapter-rxjava2:2.6.2"
|
||||
implementation "com.squareup.retrofit2:converter-gson:2.6.2"
|
||||
implementation "com.squareup.okhttp3:okhttp:$okhttp3Version"
|
||||
implementation "com.squareup.okhttp3:logging-interceptor:$okhttp3Version"
|
||||
implementation "com.squareup.retrofit2:retrofit:$retrofit2Version"
|
||||
implementation "com.squareup.retrofit2:adapter-rxjava2:$retrofit2Version"
|
||||
implementation "com.squareup.retrofit2:converter-gson:$retrofit2Version"
|
||||
|
||||
// Phone checker
|
||||
implementation 'com.scottyab:rootbeer-lib:0.0.7'
|
||||
|
||||
implementation 'com.scottyab:rootbeer-lib:0.0.8'
|
||||
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0-alpha03'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
|
||||
androidTestImplementation 'androidx.test:rules:1.3.0-alpha03'
|
||||
androidTestImplementation 'androidx.test:rules:1.3.0-beta01'
|
||||
androidTestImplementation 'com.google.code.findbugs:jsr305:3.0.2'
|
||||
|
||||
/* Dagger2 - We are going to use dagger.android which includes
|
||||
* support for Activity and fragment injection so we need to include
|
||||
* the following dependencies */
|
||||
implementation "com.google.dagger:dagger-android:$dagger_version"
|
||||
implementation "com.google.dagger:dagger-android-support:$dagger_version"
|
||||
annotationProcessor "com.google.dagger:dagger-compiler:$dagger_version"
|
||||
annotationProcessor "com.google.dagger:dagger-android-processor:$dagger_version"
|
||||
kapt "com.google.dagger:dagger-android-processor:$dagger_version"
|
||||
|
||||
/* Dagger2 - default dependency */
|
||||
kapt "com.google.dagger:dagger-compiler:$dagger_version"
|
||||
|
||||
androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0'
|
||||
|
||||
//WorkManager
|
||||
implementation 'androidx.work:work-runtime:2.3.4'
|
||||
implementation 'androidx.work:work-runtime-ktx:2.3.4'
|
||||
implementation 'androidx.work:work-rxjava2:2.3.4'
|
||||
|
||||
implementation 'com.google.androidbrowserhelper:androidbrowserhelper:1.1.0'
|
||||
|
||||
implementation 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava'
|
||||
}
|
||||
|
||||
|
||||
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: downloadAndUnzipFile, type: Copy) {
|
||||
def src = file("${buildDir}/unpacked/dist/danars-support-lib-master")
|
||||
def target = file("src/main/jniLibs/")
|
||||
|
||||
from src
|
||||
into target
|
||||
}
|
||||
|
||||
task full_clean(type: Delete) {
|
||||
delete file("src/main/jniLibs")
|
||||
}
|
||||
/*
|
||||
// Run 'adb' shell command to clear application data of main app for 'debug' variant
|
||||
task clearMainAppData(type: Exec) {
|
||||
|
@ -373,14 +394,16 @@ tasks.whenTaskAdded { task ->
|
|||
}
|
||||
}
|
||||
*/
|
||||
clean.dependsOn full_clean
|
||||
preBuild.dependsOn copyLibs
|
||||
|
||||
printf('--------------\n')
|
||||
printf('isMaster: %s\n', isMaster().toString())
|
||||
printf('gitAvailable: %s\n', gitAvailable().toString())
|
||||
printf('allCommited: %s\n', allCommited().toString())
|
||||
printf('--------------\n')
|
||||
if (isMaster() && !gitAvailable()) {
|
||||
throw new GradleException('GIT system is not available. On Windows try to run Android Studio as an Administrator. Check if GIT is installed and Studio have permissions to use it')
|
||||
}
|
||||
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')
|
||||
throw new GradleException('There are uncommitted changes. Clone sources again as described in wiki and do not allow gradle update')
|
||||
}
|
||||
|
||||
|
|
Binary file not shown.
|
@ -8,43 +8,54 @@ import androidx.test.rule.GrantPermissionRule
|
|||
import info.nightscout.androidaps.data.Profile
|
||||
import info.nightscout.androidaps.interfaces.PluginBase
|
||||
import info.nightscout.androidaps.interfaces.PluginType
|
||||
import info.nightscout.androidaps.interfaces.PumpInterface
|
||||
import info.nightscout.androidaps.logging.L
|
||||
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin
|
||||
import info.nightscout.androidaps.plugins.aps.openAPSSMB.OpenAPSSMBPlugin
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||
import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin
|
||||
import info.nightscout.androidaps.plugins.general.actions.ActionsPlugin
|
||||
import info.nightscout.androidaps.plugins.insulin.InsulinOrefUltraRapidActingPlugin
|
||||
import info.nightscout.androidaps.plugins.profile.local.LocalProfilePlugin
|
||||
import info.nightscout.androidaps.plugins.pump.danaRv2.DanaRv2Plugin
|
||||
import info.nightscout.androidaps.danaRv2.DanaRv2Plugin
|
||||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin
|
||||
import info.nightscout.androidaps.plugins.source.RandomBgPlugin
|
||||
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.SP
|
||||
import info.nightscout.androidaps.utils.isRunningTest
|
||||
import info.nightscout.androidaps.utils.extensions.isRunningTest
|
||||
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
||||
import org.json.JSONObject
|
||||
import org.junit.Assert
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.slf4j.LoggerFactory
|
||||
import javax.inject.Inject
|
||||
|
||||
@LargeTest
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class RealPumpTest {
|
||||
|
||||
private val log = LoggerFactory.getLogger(L.CORE)
|
||||
|
||||
companion object {
|
||||
val pump: PumpInterface = DanaRv2Plugin.getPlugin()
|
||||
const val R_PASSWORD = 1234
|
||||
const val R_SERIAL = "PBB00013LR_P"
|
||||
}
|
||||
|
||||
private val validProfile = "{\"dia\":\"6\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"10\"},{\"time\":\"2:00\",\"value\":\"11\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"0.1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"5\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}"
|
||||
|
||||
@Inject lateinit var pump : info.nightscout.androidaps.danaRv2.DanaRv2Plugin
|
||||
@Inject lateinit var randomBgPlugin :RandomBgPlugin
|
||||
@Inject lateinit var localProfilePlugin: LocalProfilePlugin
|
||||
@Inject lateinit var profileFunction: ProfileFunction
|
||||
@Inject lateinit var insulinOrefUltraRapidActingPlugin: InsulinOrefUltraRapidActingPlugin
|
||||
@Inject lateinit var sensitivityOref1Plugin: SensitivityOref1Plugin
|
||||
@Inject lateinit var openAPSSMBPlugin: OpenAPSSMBPlugin
|
||||
@Inject lateinit var loopPlugin: LoopPlugin
|
||||
@Inject lateinit var actionsPlugin: ActionsPlugin
|
||||
@Inject lateinit var configBuilderPlugin: ConfigBuilderPlugin
|
||||
@Inject lateinit var objectivesPlugin: ObjectivesPlugin
|
||||
@Inject lateinit var treatmentsPlugin: TreatmentsPlugin
|
||||
@Inject lateinit var sp: SP
|
||||
|
||||
@Rule
|
||||
@JvmField
|
||||
var mActivityTestRule = ActivityTestRule(MainActivity::class.java)
|
||||
|
@ -60,42 +71,43 @@ class RealPumpTest {
|
|||
|
||||
@Before
|
||||
fun clear() {
|
||||
SP.clear()
|
||||
SP.putBoolean(R.string.key_setupwizard_processed, true)
|
||||
SP.putString(R.string.key_aps_mode, "closed")
|
||||
sp.clear()
|
||||
sp.putBoolean(R.string.key_setupwizard_processed, true)
|
||||
sp.putString(R.string.key_aps_mode, "closed")
|
||||
MainApp.getDbHelper().resetDatabases()
|
||||
MainApp.devBranch = false
|
||||
}
|
||||
|
||||
private fun preparePlugins() {
|
||||
// Source
|
||||
RandomBgPlugin.performPluginSwitch(true, PluginType.BGSOURCE)
|
||||
configBuilderPlugin.performPluginSwitch(randomBgPlugin,true, PluginType.BGSOURCE)
|
||||
// Profile
|
||||
LocalProfilePlugin.performPluginSwitch(true, PluginType.PROFILE)
|
||||
configBuilderPlugin.performPluginSwitch(localProfilePlugin, true, PluginType.PROFILE)
|
||||
val profile = Profile(JSONObject(validProfile), Constants.MGDL)
|
||||
Assert.assertTrue(profile.isValid("Test"))
|
||||
LocalProfilePlugin.profiles.clear()
|
||||
LocalProfilePlugin.numOfProfiles = 0
|
||||
val singleProfile = LocalProfilePlugin.SingleProfile().copyFrom(profile, "TestProfile")
|
||||
LocalProfilePlugin.addProfile(singleProfile)
|
||||
ProfileFunctions.doProfileSwitch(LocalProfilePlugin.createProfileStore(), "TestProfile", 0, 100, 0, DateUtil.now())
|
||||
localProfilePlugin.profiles.clear()
|
||||
localProfilePlugin.numOfProfiles = 0
|
||||
val singleProfile = LocalProfilePlugin.SingleProfile().copyFrom(localProfilePlugin.rawProfile, profile, "TestProfile")
|
||||
localProfilePlugin.addProfile(singleProfile)
|
||||
val profileSwitch = profileFunction.prepareProfileSwitch(localProfilePlugin.createProfileStore(), "TestProfile", 0, 100, 0, DateUtil.now())
|
||||
treatmentsPlugin.addToHistoryProfileSwitch(profileSwitch)
|
||||
// Insulin
|
||||
InsulinOrefUltraRapidActingPlugin.getPlugin().performPluginSwitch(true, PluginType.INSULIN)
|
||||
configBuilderPlugin.performPluginSwitch(insulinOrefUltraRapidActingPlugin, true, PluginType.INSULIN)
|
||||
// Pump
|
||||
SP.putInt(R.string.key_danar_password, R_PASSWORD)
|
||||
SP.putString(R.string.key_danar_bt_name, R_SERIAL)
|
||||
(pump as PluginBase).performPluginSwitch(true, PluginType.PUMP)
|
||||
sp.putInt(R.string.key_danar_password, R_PASSWORD)
|
||||
sp.putString(R.string.key_danar_bt_name, R_SERIAL)
|
||||
configBuilderPlugin.performPluginSwitch((pump as PluginBase), true, PluginType.PUMP)
|
||||
// Sensitivity
|
||||
SensitivityOref1Plugin.getPlugin().performPluginSwitch(true, PluginType.SENSITIVITY)
|
||||
configBuilderPlugin.performPluginSwitch(sensitivityOref1Plugin, true, PluginType.SENSITIVITY)
|
||||
// APS
|
||||
OpenAPSSMBPlugin.getPlugin().performPluginSwitch(true, PluginType.APS)
|
||||
LoopPlugin.getPlugin().performPluginSwitch(true, PluginType.LOOP)
|
||||
configBuilderPlugin.performPluginSwitch(openAPSSMBPlugin, true, PluginType.APS)
|
||||
configBuilderPlugin.performPluginSwitch(loopPlugin, true, PluginType.LOOP)
|
||||
|
||||
// Enable common
|
||||
ActionsPlugin.performPluginSwitch(true, PluginType.GENERAL)
|
||||
configBuilderPlugin.performPluginSwitch(actionsPlugin, true, PluginType.GENERAL)
|
||||
|
||||
// Disable unneeded
|
||||
MainApp.getPluginsList().remove(ObjectivesPlugin)
|
||||
MainApp.getPluginsList().remove(objectivesPlugin)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -104,12 +116,12 @@ class RealPumpTest {
|
|||
preparePlugins()
|
||||
|
||||
while (!pump.isInitialized) {
|
||||
log.debug("Waiting for initialization")
|
||||
//log.debug("Waiting for initialization")
|
||||
SystemClock.sleep(1000)
|
||||
}
|
||||
|
||||
while (true) {
|
||||
log.debug("Tick")
|
||||
//log.debug("Tick")
|
||||
SystemClock.sleep(1000)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,6 @@ import androidx.test.rule.GrantPermissionRule
|
|||
import info.nightscout.androidaps.interfaces.PluginType
|
||||
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin
|
||||
import info.nightscout.androidaps.plugins.aps.openAPSSMB.OpenAPSSMBPlugin
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions
|
||||
import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin
|
||||
import info.nightscout.androidaps.plugins.profile.local.LocalProfilePlugin
|
||||
import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin
|
||||
|
@ -28,8 +27,7 @@ import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin
|
|||
import info.nightscout.androidaps.plugins.source.RandomBgPlugin
|
||||
import info.nightscout.androidaps.setupwizard.SetupWizardActivity
|
||||
import info.nightscout.androidaps.utils.HardLimits
|
||||
import info.nightscout.androidaps.utils.SP
|
||||
import info.nightscout.androidaps.utils.isRunningTest
|
||||
import info.nightscout.androidaps.utils.extensions.isRunningTest
|
||||
import org.hamcrest.CoreMatchers.allOf
|
||||
import org.hamcrest.Description
|
||||
import org.hamcrest.Matcher
|
||||
|
@ -60,7 +58,7 @@ class SetupWizardActivityTest {
|
|||
|
||||
@Before
|
||||
fun clear() {
|
||||
SP.clear()
|
||||
sp.clear()
|
||||
}
|
||||
/*
|
||||
|
||||
|
@ -77,7 +75,7 @@ adb shell settings put global animator_duration_scale 0 &
|
|||
|
||||
@Test
|
||||
fun setupWizardActivityTest() {
|
||||
SP.clear()
|
||||
sp.clear()
|
||||
Assert.assertTrue(isRunningTest())
|
||||
// Welcome page
|
||||
onView(withId(R.id.next_button)).perform(click())
|
||||
|
|
|
@ -38,7 +38,14 @@
|
|||
android:roundIcon="${appIconRound}"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme.Launcher"
|
||||
android:fullBackupContent="true">
|
||||
android:fullBackupOnly="false"
|
||||
android:backupAgent=".utils.SPBackupAgent"
|
||||
android:restoreAnyVersion="true">
|
||||
|
||||
<meta-data
|
||||
android:name="com.google.android.backup.api_key"
|
||||
android:value="AEdPqrEAAAAI3JiApyMrbP2QFzZ2fYfCPsgjkRp53Dm2S1-zPQ" />
|
||||
|
||||
<meta-data
|
||||
android:name="com.google.android.gms.car.application"
|
||||
android:resource="@xml/automotive_app_desc" />
|
||||
|
@ -51,15 +58,6 @@
|
|||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name=".activities.PreferencesActivity" />
|
||||
<activity
|
||||
android:name=".activities.BolusProgressHelperActivity"
|
||||
android:theme="@style/Theme.AppCompat.Translucent" />
|
||||
<activity
|
||||
android:name=".activities.ErrorHelperActivity"
|
||||
android:theme="@style/Theme.AppCompat.Translucent" />
|
||||
<activity android:name=".plugins.pump.danaR.activities.DanaRHistoryActivity" />
|
||||
<activity android:name=".plugins.pump.danaR.activities.DanaRUserOptionsActivity" />
|
||||
<activity android:name=".activities.TDDStatsActivity" />
|
||||
<activity android:name=".plugins.general.overview.activities.QuickWizardListActivity">
|
||||
<intent-filter>
|
||||
<action android:name="info.nightscout.androidaps.plugins.general.overview.activities.QuickWizardListActivity" />
|
||||
|
@ -67,16 +65,11 @@
|
|||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name=".plugins.pump.danaRS.activities.BLEScanActivity">
|
||||
<intent-filter>
|
||||
<action android:name="info.nightscout.androidaps.plugins.PumpDanaRS.activities.BLEScanActivity" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name=".plugins.pump.danaRS.activities.PairingHelperActivity" />
|
||||
<activity android:name=".activities.HistoryBrowseActivity" />
|
||||
<activity android:name=".plugins.general.maintenance.activities.PrefImportListActivity" />
|
||||
<activity android:name=".historyBrowser.HistoryBrowseActivity" />
|
||||
<activity android:name=".activities.SurveyActivity" />
|
||||
<activity android:name=".activities.ProfileHelperActivity"
|
||||
android:theme="@style/ProfileHelperAppTheme" />
|
||||
<activity android:name=".activities.StatsActivity" />
|
||||
|
||||
<!-- Receive new BG readings from other local apps -->
|
||||
|
@ -114,6 +107,9 @@
|
|||
<!-- Receiver keepalive, scheduled every 30 min -->
|
||||
<receiver android:name=".receivers.KeepAliveReceiver" />
|
||||
|
||||
<!-- Receive ignore 5m, 15m, 30m requests for carb notifications -->
|
||||
<receiver android:name=".plugins.aps.loop.CarbSuggestionReceiver"></receiver>
|
||||
|
||||
<!-- Auto start -->
|
||||
<receiver
|
||||
android:name=".receivers.AutoStartReceiver"
|
||||
|
@ -141,22 +137,6 @@
|
|||
<service
|
||||
android:name=".services.LocationService"
|
||||
android:exported="false" />
|
||||
<service
|
||||
android:name=".plugins.pump.danaR.services.DanaRExecutionService"
|
||||
android:enabled="true"
|
||||
android:exported="false" />
|
||||
<service
|
||||
android:name=".plugins.pump.danaRKorean.services.DanaRKoreanExecutionService"
|
||||
android:enabled="true"
|
||||
android:exported="false" />
|
||||
<service
|
||||
android:name=".plugins.pump.danaRv2.services.DanaRv2ExecutionService"
|
||||
android:enabled="true"
|
||||
android:exported="false" />
|
||||
<service
|
||||
android:name=".plugins.pump.danaRS.services.DanaRSService"
|
||||
android:enabled="true"
|
||||
android:exported="true" />
|
||||
<service
|
||||
android:name=".plugins.general.wear.wearintegration.WatchUpdaterService"
|
||||
android:exported="true">
|
||||
|
@ -265,23 +245,34 @@
|
|||
android:label="@string/pairing_information"
|
||||
android:theme="@style/AppTheme" />
|
||||
<activity android:name=".activities.RequestDexcomPermissionActivity" />
|
||||
<activity android:name=".plugins.general.smsCommunicator.activities.SmsCommunicatorOtpActivity">
|
||||
<intent-filter>
|
||||
<action android:name="info.nightscout.androidaps.plugins.general.smsCommunicator.activities.SmsCommunicatorOtpActivity" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<!-- Medtronic service and activities -->
|
||||
<service
|
||||
android:name=".plugins.pump.medtronic.service.RileyLinkMedtronicService"
|
||||
android:enabled="true"
|
||||
android:exported="true" />
|
||||
<activity android:name=".plugins.pump.common.dialog.RileyLinkBLEScanActivity">
|
||||
|
||||
<activity android:name=".plugins.pump.medtronic.dialog.MedtronicHistoryActivity" />
|
||||
<activity android:name=".plugins.general.openhumans.OpenHumansLoginActivity"
|
||||
android:launchMode="singleTop">
|
||||
<intent-filter>
|
||||
<action android:name="info.nightscout.androidaps.plugins.PumpCommon.dialog.RileyLinkBLEScanActivity" />
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data
|
||||
android:host="setup-openhumans"
|
||||
android:scheme="androidaps" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".plugins.pump.common.hw.rileylink.dialog.RileyLinkStatusActivity"
|
||||
android:label="@string/title_activity_rileylink_settings"
|
||||
android:theme="@style/Theme.AppCompat.NoTitle" />
|
||||
<activity android:name=".plugins.pump.medtronic.dialog.MedtronicHistoryActivity" />
|
||||
|
||||
<uses-library android:name="org.apache.http.legacy" android:required="false"/>
|
||||
|
||||
|
|
|
@ -470,7 +470,7 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
|
|||
var maxSafeBasal = tempBasalFunctions.getMaxSafeBasal(profile);
|
||||
|
||||
if (rate > maxSafeBasal) {
|
||||
rT.reason += "adj. req. rate: "+rate+" to maxSafeBasal: "+maxSafeBasal+", ";
|
||||
rT.reason += "adj. req. rate: "+round(rate, 2)+" to maxSafeBasal: "+maxSafeBasal+", ";
|
||||
rate = round_basal(maxSafeBasal, profile);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,316 +0,0 @@
|
|||
/*
|
||||
Determine Basal
|
||||
|
||||
Released under MIT license. See the accompanying LICENSE.txt file for
|
||||
full terms and conditions
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
var determine_basal = function determine_basal(glucose_status, currenttemp, iob_data, profile, offline, meal_data, setTempBasal) {
|
||||
var rT = { //short for requestedTemp
|
||||
};
|
||||
|
||||
if (typeof profile === 'undefined' || typeof profile.current_basal === 'undefined') {
|
||||
rT.error ='Error: could not get current basal rate';
|
||||
return rT;
|
||||
}
|
||||
|
||||
var bg = glucose_status.glucose;
|
||||
if (bg < 38) { //Dexcom is in ??? mode or calibrating, do nothing. Asked @benwest for raw data in iter_glucose
|
||||
rT.error = "CGM is calibrating or in ??? state";
|
||||
return rT;
|
||||
}
|
||||
|
||||
var max_iob = profile.max_iob; // maximum amount of non-bolus IOB OpenAPS will ever deliver
|
||||
|
||||
// if target_bg is set, great. otherwise, if min and max are set, then set target to their average
|
||||
var target_bg;
|
||||
if (typeof profile.target_bg !== 'undefined') {
|
||||
target_bg = profile.target_bg;
|
||||
} else {
|
||||
if (typeof profile.min_bg !== 'undefined' && typeof profile.max_bg !== 'undefined') {
|
||||
target_bg = (profile.min_bg + profile.max_bg) / 2;
|
||||
} else {
|
||||
rT.error ='Error: could not determine target_bg';
|
||||
return rT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (typeof iob_data === 'undefined' ) {
|
||||
rT.error ='Error: iob_data undefined';
|
||||
return rT;
|
||||
}
|
||||
|
||||
if (typeof iob_data.activity === 'undefined' || typeof iob_data.iob === 'undefined' || typeof iob_data.activity === 'undefined') {
|
||||
rT.error ='Error: iob_data missing some property';
|
||||
return rT;
|
||||
}
|
||||
|
||||
var tick;
|
||||
|
||||
if (glucose_status.delta >= 0) {
|
||||
tick = "+" + glucose_status.delta;
|
||||
} else {
|
||||
tick = glucose_status.delta;
|
||||
}
|
||||
var minDelta = Math.min(glucose_status.delta, glucose_status.avgdelta);
|
||||
//var maxDelta = Math.max(glucose_status.delta, glucose_status.avgdelta);
|
||||
|
||||
|
||||
//calculate BG impact: the amount BG "should" be rising or falling based on insulin activity alone
|
||||
var bgi = Math.round(( -iob_data.activity * profile.sens * 5 )*100)/100;
|
||||
// project positive deviations for 15 minutes
|
||||
var deviation = Math.round( 15 / 5 * ( glucose_status.avgdelta - bgi ) );
|
||||
// project negative deviations for 30 minutes
|
||||
if (deviation < 0) {
|
||||
deviation = Math.round( 30 / 5 * ( glucose_status.avgdelta - bgi ) );
|
||||
}
|
||||
//console.log("Avg.Delta: " + glucose_status.avgdelta.toFixed(1) + ", BGI: " + bgi.toFixed(1) + " 15m activity projection: " + deviation.toFixed(0));
|
||||
|
||||
// calculate the naive (bolus calculator math) eventual BG based on net IOB and sensitivity
|
||||
var naive_eventualBG = Math.round( bg - (iob_data.iob * profile.sens) );
|
||||
// and adjust it for the deviation above
|
||||
var eventualBG = naive_eventualBG + deviation;
|
||||
// calculate what portion of that is due to bolussnooze
|
||||
var bolusContrib = iob_data.bolussnooze * profile.sens;
|
||||
// and add it back in to get snoozeBG, plus another 50% to avoid low-temping at mealtime
|
||||
var naive_snoozeBG = Math.round( naive_eventualBG + 1.5 * bolusContrib );
|
||||
// adjust that for deviation like we did eventualBG
|
||||
var snoozeBG = naive_snoozeBG + deviation;
|
||||
|
||||
//console.log("BG: " + bg +"(" + tick + ","+glucose_status.avgdelta.toFixed(1)+")"+ " -> " + eventualBG + "-" + snoozeBG + " (Unadjusted: " + naive_eventualBG + "-" + naive_snoozeBG + "), BGI: " + bgi);
|
||||
|
||||
var expectedDelta = Math.round(( bgi + ( target_bg - eventualBG ) / ( profile.dia * 60 / 5 ) )*10)/10;
|
||||
//console.log("expectedDelta: " + expectedDelta);
|
||||
|
||||
if (typeof eventualBG === 'undefined' || isNaN(eventualBG)) {
|
||||
rT.error ='Error: could not calculate eventualBG';
|
||||
return rT;
|
||||
}
|
||||
|
||||
// min_bg of 90 -> threshold of 70, 110 -> 80, and 130 -> 90
|
||||
var threshold = profile.min_bg - 0.5*(profile.min_bg-50);
|
||||
|
||||
rT = {
|
||||
'temp': 'absolute'
|
||||
, 'bg': bg
|
||||
, 'tick': tick
|
||||
, 'eventualBG': eventualBG
|
||||
, 'snoozeBG': snoozeBG
|
||||
};
|
||||
|
||||
var basaliob;
|
||||
if (iob_data.basaliob) { basaliob = iob_data.basaliob; }
|
||||
else { basaliob = iob_data.iob - iob_data.bolussnooze; }
|
||||
// allow meal assist to run when carbs are just barely covered
|
||||
if (minDelta > Math.max(3, bgi) && ( (meal_data.carbs > 0 && (1.1 * meal_data.carbs/profile.carb_ratio > meal_data.boluses + basaliob)) || ( deviation > 25 && minDelta > 7 ) ) ) {
|
||||
// ignore all covered IOB, and just set eventualBG to the current bg
|
||||
eventualBG = Math.max(bg,eventualBG) + deviation;
|
||||
rT.eventualBG = eventualBG;
|
||||
profile.min_bg = 80;
|
||||
target_bg = (profile.min_bg + profile.max_bg) / 2;
|
||||
expectedDelta = Math.round(( bgi + ( target_bg - eventualBG ) / ( profile.dia * 60 / 5 ) )*10)/10;
|
||||
rT.mealAssist = "On: Carbs: " + meal_data.carbs + " Boluses: " + meal_data.boluses + " Target: " + target_bg + " Deviation: " + deviation + " BGI: " + bgi;
|
||||
} else {
|
||||
rT.mealAssist = "Off: Carbs: " + meal_data.carbs + " Boluses: " + meal_data.boluses + " Target: " + target_bg + " Deviation: " + deviation + " BGI: " + bgi;
|
||||
}
|
||||
if (bg < threshold) { // low glucose suspend mode: BG is < ~80
|
||||
rT.reason = "BG " + bg + "<" + threshold;
|
||||
if ((glucose_status.delta <= 0 && glucose_status.avgdelta <= 0) || (glucose_status.delta < expectedDelta && glucose_status.avgdelta < expectedDelta)) {
|
||||
// BG is still falling / rising slower than predicted
|
||||
return setTempBasal(0, 30, profile, rT, offline);
|
||||
}
|
||||
if (glucose_status.delta > glucose_status.avgdelta) {
|
||||
rT.reason += ", delta " + glucose_status.delta + ">0";
|
||||
} else {
|
||||
rT.reason += ", avg delta " + glucose_status.avgdelta.toFixed(2) + ">0";
|
||||
}
|
||||
if (currenttemp.rate > profile.current_basal) { // if a high-temp is running
|
||||
rT.reason += ", cancel high temp";
|
||||
return setTempBasal(0, 0, profile, rT, offline); // cancel high temp
|
||||
} else if (currenttemp.duration && eventualBG > profile.max_bg) { // if low-temped and predicted to go high from negative IOB
|
||||
rT.reason += ", cancel low temp";
|
||||
return setTempBasal(0, 0, profile, rT, offline); // cancel low temp
|
||||
}
|
||||
rT.reason += "; no high-temp to cancel";
|
||||
return rT;
|
||||
}
|
||||
if (eventualBG < profile.min_bg) { // if eventual BG is below target:
|
||||
if (rT.mealAssist.indexOf("On") == 0) {
|
||||
rT.reason = "Meal assist: " + meal_data.carbs + "g, " + meal_data.boluses + "U";
|
||||
} else {
|
||||
rT.reason = "Eventual BG " + eventualBG + "<" + profile.min_bg;
|
||||
// if 5m or 15m avg BG is rising faster than expected delta
|
||||
if (minDelta > expectedDelta && minDelta > 0) {
|
||||
if (glucose_status.delta > glucose_status.avgdelta) {
|
||||
rT.reason += ", but Delta " + tick + " > Exp. Delta " + expectedDelta;
|
||||
} else {
|
||||
rT.reason += ", but Avg. Delta " + glucose_status.avgdelta.toFixed(2) + " > Exp. Delta " + expectedDelta;
|
||||
}
|
||||
if (currenttemp.duration > 0) { // if there is currently any temp basal running
|
||||
rT.reason = rT.reason += "; cancel";
|
||||
return setTempBasal(0, 0, profile, rT, offline); // cancel temp
|
||||
} else {
|
||||
rT.reason = rT.reason += "; no temp to cancel";
|
||||
return rT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (eventualBG < profile.min_bg) {
|
||||
// if this is just due to boluses, we can snooze until the bolus IOB decays (at double speed)
|
||||
if (snoozeBG > profile.min_bg) { // if adding back in the bolus contribution BG would be above min
|
||||
// if BG is falling and high-temped, or rising and low-temped, cancel
|
||||
// compare against zero here, not BGI, because BGI will be highly negative from boluses and no carbs
|
||||
if (glucose_status.delta < 0 && currenttemp.duration > 0 && currenttemp.rate > profile.current_basal) {
|
||||
rT.reason += tick + ", and temp " + currenttemp.rate + " > basal " + profile.current_basal;
|
||||
return setTempBasal(0, 0, profile, rT, offline); // cancel temp
|
||||
} else if (glucose_status.delta > 0 && currenttemp.duration > 0 && currenttemp.rate < profile.current_basal) {
|
||||
rT.reason += tick + ", and temp " + currenttemp.rate + " < basal " + profile.current_basal;
|
||||
return setTempBasal(0, 0, profile, rT, offline); // cancel temp
|
||||
}
|
||||
|
||||
rT.reason += ", bolus snooze: eventual BG range " + eventualBG + "-" + snoozeBG;
|
||||
return rT;
|
||||
} else {
|
||||
// calculate 30m low-temp required to get projected BG up to target
|
||||
// use snoozeBG to more gradually ramp in any counteraction of the user's boluses
|
||||
// multiply by 2 to low-temp faster for increased hypo safety
|
||||
var insulinReq = 2 * Math.min(0, (snoozeBG - target_bg) / profile.sens);
|
||||
if (minDelta < 0 && minDelta > expectedDelta) {
|
||||
// if we're barely falling, newinsulinReq should be barely negative
|
||||
rT.reason += ", Snooze BG " + snoozeBG;
|
||||
var newinsulinReq = Math.round(( insulinReq * (minDelta / expectedDelta) ) * 100)/100;
|
||||
//console.log("Increasing insulinReq from " + insulinReq + " to " + newinsulinReq);
|
||||
insulinReq = newinsulinReq;
|
||||
}
|
||||
// rate required to deliver insulinReq less insulin over 30m:
|
||||
var rate = profile.current_basal + (2 * insulinReq);
|
||||
rate = Math.round( rate * 1000 ) / 1000;
|
||||
// if required temp < existing temp basal
|
||||
var insulinScheduled = currenttemp.duration * (currenttemp.rate - profile.current_basal) / 60;
|
||||
if (insulinScheduled < insulinReq - 0.2) { // if current temp would deliver >0.2U less than the required insulin, raise the rate
|
||||
rT.reason = currenttemp.duration + "m@" + (currenttemp.rate - profile.current_basal).toFixed(3) + " = " + insulinScheduled.toFixed(3) + " < req " + insulinReq + "-0.2U";
|
||||
return setTempBasal(rate, 30, profile, rT, offline);
|
||||
}
|
||||
if (typeof currenttemp.rate !== 'undefined' && (currenttemp.duration > 5 && rate > currenttemp.rate - 0.1)) {
|
||||
rT.reason += ", temp " + currenttemp.rate + " ~< req " + rate + "U/hr";
|
||||
return rT;
|
||||
} else {
|
||||
rT.reason += ", setting " + rate + "U/hr";
|
||||
return setTempBasal(rate, 30, profile, rT, offline);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if eventual BG is above min but BG is falling faster than expected Delta
|
||||
if (minDelta < expectedDelta) {
|
||||
if (glucose_status.delta < glucose_status.avgdelta) {
|
||||
rT.reason = "Eventual BG " + eventualBG + ">" + profile.min_bg + " but Delta " + tick + " < Exp. Delta " + expectedDelta;
|
||||
} else {
|
||||
rT.reason = "Eventual BG " + eventualBG + ">" + profile.min_bg + " but Avg. Delta " + glucose_status.avgdelta.toFixed(2) + " < Exp. Delta " + expectedDelta;
|
||||
}
|
||||
if (currenttemp.duration > 0) { // if there is currently any temp basal running
|
||||
rT.reason = rT.reason += "; cancel";
|
||||
return setTempBasal(0, 0, profile, rT, offline); // cancel temp
|
||||
} else {
|
||||
rT.reason = rT.reason += "; no temp to cancel";
|
||||
return rT;
|
||||
}
|
||||
}
|
||||
|
||||
if (eventualBG < profile.max_bg) {
|
||||
rT.reason = eventualBG + " is in range. No temp required";
|
||||
if (currenttemp.duration > 0) { // if there is currently any temp basal running
|
||||
rT.reason = rT.reason += "; cancel";
|
||||
return setTempBasal(0, 0, profile, rT, offline); // cancel temp
|
||||
}
|
||||
if (offline == 'Offline') {
|
||||
// if no temp is running or required, set the current basal as a temp, so you can see on the pump that the loop is working
|
||||
if ((!currenttemp.duration || (currenttemp.rate == profile.current_basal)) && !rT.duration) {
|
||||
rT.reason = rT.reason + "; setting current basal of " + profile.current_basal + " as temp";
|
||||
return setTempBasal(profile.current_basal, 30, profile, rT, offline);
|
||||
}
|
||||
}
|
||||
return rT;
|
||||
}
|
||||
|
||||
if (snoozeBG < profile.max_bg) {
|
||||
rT.reason = snoozeBG + " < " + profile.max_bg;
|
||||
if (currenttemp.duration > 0) { // if there is currently any temp basal running
|
||||
rT.reason = rT.reason += "; cancel";
|
||||
return setTempBasal(0, 0, profile, rT, offline); // cancel temp
|
||||
} else {
|
||||
rT.reason = rT.reason += "; no temp to cancel";
|
||||
return rT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// eventual BG is at/above target:
|
||||
// if iob is over max, just cancel any temps
|
||||
var basaliob;
|
||||
if (iob_data.basaliob) { basaliob = iob_data.basaliob; }
|
||||
else { basaliob = iob_data.iob - iob_data.bolussnooze; }
|
||||
rT.reason = "Eventual BG " + eventualBG + ">=" + profile.max_bg + ", ";
|
||||
if (basaliob > max_iob) {
|
||||
rT.reason = "basaliob " + basaliob + " > max_iob " + max_iob;
|
||||
return setTempBasal(0, 0, profile, rT, offline);
|
||||
} else { // otherwise, calculate 30m high-temp required to get projected BG down to target
|
||||
|
||||
// insulinReq is the additional insulin required to get down to max bg:
|
||||
// if in meal assist mode, check if snoozeBG is lower, as eventualBG is not dependent on IOB
|
||||
var insulinReq = (Math.min(snoozeBG,eventualBG) - target_bg) / profile.sens;
|
||||
if (minDelta < 0 && minDelta > expectedDelta) {
|
||||
var newinsulinReq = Math.round(( insulinReq * (1 - (minDelta / expectedDelta)) ) * 100)/100;
|
||||
//console.log("Reducing insulinReq from " + insulinReq + " to " + newinsulinReq);
|
||||
insulinReq = newinsulinReq;
|
||||
}
|
||||
// if that would put us over max_iob, then reduce accordingly
|
||||
if (insulinReq > max_iob-basaliob) {
|
||||
rT.reason = "max_iob " + max_iob + ", ";
|
||||
insulinReq = max_iob-basaliob;
|
||||
}
|
||||
|
||||
// rate required to deliver insulinReq more insulin over 30m:
|
||||
var rate = profile.current_basal + (2 * insulinReq);
|
||||
rate = Math.round( rate * 1000 ) / 1000;
|
||||
|
||||
var maxSafeBasal = Math.min(profile.max_basal, 3 * profile.max_daily_basal, 4 * profile.current_basal);
|
||||
if (rate > maxSafeBasal) {
|
||||
rT.reason += "adj. req. rate:"+rate.toFixed(1) +" to maxSafeBasal:"+maxSafeBasal.toFixed(1)+", ";
|
||||
rate = maxSafeBasal;
|
||||
}
|
||||
|
||||
var insulinScheduled = currenttemp.duration * (currenttemp.rate - profile.current_basal) / 60;
|
||||
if (insulinScheduled > insulinReq + 0.2) { // if current temp would deliver >0.2U more than the required insulin, lower the rate
|
||||
rT.reason = currenttemp.duration + "m@" + (currenttemp.rate - profile.current_basal).toFixed(3) + " = " + insulinScheduled.toFixed(3) + " > req " + insulinReq + "+0.2U";
|
||||
return setTempBasal(rate, 30, profile, rT, offline);
|
||||
}
|
||||
|
||||
if (typeof currenttemp.duration == 'undefined' || currenttemp.duration == 0) { // no temp is set
|
||||
rT.reason += "no temp, setting " + rate + "U/hr";
|
||||
return setTempBasal(rate, 30, profile, rT, offline);
|
||||
}
|
||||
|
||||
if (currenttemp.duration > 5 && rate < currenttemp.rate + 0.1) { // if required temp <~ existing temp basal
|
||||
rT.reason += "temp " + currenttemp.rate + " >~ req " + rate + "U/hr";
|
||||
return rT;
|
||||
}
|
||||
|
||||
// required temp > existing temp basal
|
||||
rT.reason += "temp " + currenttemp.rate + "<" + rate + "U/hr";
|
||||
return setTempBasal(rate, 30, profile, rT, offline);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
module.exports = determine_basal;
|
|
@ -31,14 +31,13 @@ function calculate_expected_delta(target_bg, eventual_bg, bgi) {
|
|||
// (hours * mins_per_hour) / 5 = how many 5 minute periods in 2h = 24
|
||||
var five_min_blocks = (2 * 60) / 5;
|
||||
var target_delta = target_bg - eventual_bg;
|
||||
var expectedDelta = round(bgi + (target_delta / five_min_blocks), 1);
|
||||
return expectedDelta;
|
||||
return /* expectedDelta */ round(bgi + (target_delta / five_min_blocks), 1);
|
||||
}
|
||||
|
||||
|
||||
function convert_bg(value, profile)
|
||||
{
|
||||
if (profile.out_units == "mmol/L")
|
||||
if (profile.out_units === "mmol/L")
|
||||
{
|
||||
return round(value / 18, 1).toFixed(1);
|
||||
}
|
||||
|
@ -48,10 +47,76 @@ function convert_bg(value, profile)
|
|||
}
|
||||
}
|
||||
|
||||
var determine_basal = function determine_basal(glucose_status, currenttemp, iob_data, profile, autosens_data, meal_data, tempBasalFunctions, microBolusAllowed, reservoir_data) {
|
||||
function enable_smb(
|
||||
profile,
|
||||
microBolusAllowed,
|
||||
meal_data,
|
||||
target_bg
|
||||
) {
|
||||
// disable SMB when a high temptarget is set
|
||||
if (! microBolusAllowed) {
|
||||
console.error("SMB disabled (!microBolusAllowed)");
|
||||
return false;
|
||||
} else if (! profile.allowSMB_with_high_temptarget && profile.temptargetSet && target_bg > 100) {
|
||||
console.error("SMB disabled due to high temptarget of",target_bg);
|
||||
return false;
|
||||
} else if (meal_data.bwFound === true && profile.A52_risk_enable === false) {
|
||||
console.error("SMB disabled due to Bolus Wizard activity in the last 6 hours.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// enable SMB/UAM if always-on (unless previously disabled for high temptarget)
|
||||
if (profile.enableSMB_always === true) {
|
||||
if (meal_data.bwFound) {
|
||||
console.error("Warning: SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard");
|
||||
} else {
|
||||
console.error("SMB enabled due to enableSMB_always");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// enable SMB/UAM (if enabled in preferences) while we have COB
|
||||
if (profile.enableSMB_with_COB === true && meal_data.mealCOB) {
|
||||
if (meal_data.bwCarbs) {
|
||||
console.error("Warning: SMB enabled with Bolus Wizard carbs: be sure to easy bolus 30s before using Bolus Wizard");
|
||||
} else {
|
||||
console.error("SMB enabled for COB of",meal_data.mealCOB);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// enable SMB/UAM (if enabled in preferences) for a full 6 hours after any carb entry
|
||||
// (6 hours is defined in carbWindow in lib/meal/total.js)
|
||||
if (profile.enableSMB_after_carbs === true && meal_data.carbs ) {
|
||||
if (meal_data.bwCarbs) {
|
||||
console.error("Warning: SMB enabled with Bolus Wizard carbs: be sure to easy bolus 30s before using Bolus Wizard");
|
||||
} else {
|
||||
console.error("SMB enabled for 6h after carb entry");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// enable SMB/UAM (if enabled in preferences) if a low temptarget is set
|
||||
if (profile.enableSMB_with_temptarget === true && (profile.temptargetSet && target_bg < 100)) {
|
||||
if (meal_data.bwFound) {
|
||||
console.error("Warning: SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard");
|
||||
} else {
|
||||
console.error("SMB enabled for temptarget of",convert_bg(target_bg, profile));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
console.error("SMB disabled (no enableSMB preferences active or no condition satisfied)");
|
||||
return false;
|
||||
}
|
||||
|
||||
var determine_basal = function determine_basal(glucose_status, currenttemp, iob_data, profile, autosens_data, meal_data, tempBasalFunctions, microBolusAllowed, reservoir_data, currentTime) {
|
||||
var rT = {}; //short for requestedTemp
|
||||
|
||||
var deliverAt = new Date();
|
||||
if (currentTime) {
|
||||
deliverAt = new Date(currentTime);
|
||||
}
|
||||
|
||||
if (typeof profile === 'undefined' || typeof profile.current_basal === 'undefined') {
|
||||
rT.error ='Error: could not get current basal rate';
|
||||
|
@ -61,26 +126,41 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
|
|||
var basal = profile_current_basal;
|
||||
|
||||
var systemTime = new Date();
|
||||
if (currentTime) {
|
||||
systemTime = currentTime;
|
||||
}
|
||||
var bgTime = new Date(glucose_status.date);
|
||||
var minAgo = round( (systemTime - bgTime) / 60 / 1000 ,1);
|
||||
|
||||
var bg = glucose_status.glucose;
|
||||
if (bg < 39) { //Dexcom is in ??? mode or calibrating
|
||||
rT.reason = "CGM is calibrating or in ??? state";
|
||||
var noise = glucose_status.noise;
|
||||
// 38 is an xDrip error state that usually indicates sensor failure
|
||||
// all other BG values between 11 and 37 mg/dL reflect non-error-code BG values, so we should zero temp for those
|
||||
if (bg <= 10 || bg === 38 || noise >= 3) { //Dexcom is in ??? mode or calibrating, or xDrip reports high noise
|
||||
rT.reason = "CGM is calibrating, in ??? state, or noise is high";
|
||||
}
|
||||
if (minAgo > 12 || minAgo < -5) { // Dexcom data is too old, or way in the future
|
||||
rT.reason = "If current system time "+systemTime+" is correct, then BG data is too old. The last BG data was read "+minAgo+"m ago at "+bgTime;
|
||||
// if BG is too old/noisy, or is changing less than 1 mg/dL/5m for 45m, cancel any high temps and shorten any long zero temps
|
||||
//cherry pick from oref upstream dev cb8e94990301277fb1016c778b4e9efa55a6edbc
|
||||
} else if ( bg > 60 && glucose_status.delta == 0 && glucose_status.short_avgdelta > -1 && glucose_status.short_avgdelta < 1 && glucose_status.long_avgdelta > -1 && glucose_status.long_avgdelta < 1 ) {
|
||||
if ( glucose_status.last_cal && glucose_status.last_cal < 3 ) {
|
||||
rT.reason = "CGM was just calibrated";
|
||||
} else {
|
||||
rT.reason = "Error: CGM data is unchanged for the past ~45m";
|
||||
}
|
||||
}
|
||||
if (bg < 39 || minAgo > 12 || minAgo < -5) {
|
||||
if (currenttemp.rate >= basal) { // high temp is running
|
||||
rT.reason += ". Canceling high temp basal of "+currenttemp.rate;
|
||||
//cherry pick from oref upstream dev cb8e94990301277fb1016c778b4e9efa55a6edbc
|
||||
if (bg <= 10 || bg === 38 || noise >= 3 || minAgo > 12 || minAgo < -5 || ( bg > 60 && glucose_status.delta == 0 && glucose_status.short_avgdelta > -1 && glucose_status.short_avgdelta < 1 && glucose_status.long_avgdelta > -1 && glucose_status.long_avgdelta < 1 ) ) {
|
||||
if (currenttemp.rate > basal) { // high temp is running
|
||||
rT.reason += ". Replacing high temp basal of "+currenttemp.rate+" with neutral temp of "+basal;
|
||||
rT.deliverAt = deliverAt;
|
||||
rT.temp = 'absolute';
|
||||
rT.duration = 0;
|
||||
rT.rate = 0;
|
||||
rT.duration = 30;
|
||||
rT.rate = basal;
|
||||
return rT;
|
||||
//return tempBasalFunctions.setTempBasal(basal, 30, profile, rT, currenttemp);
|
||||
} else if ( currenttemp.rate == 0 && currenttemp.duration > 30 ) { //shorten long zero temps to 30m
|
||||
} else if ( currenttemp.rate === 0 && currenttemp.duration > 30 ) { //shorten long zero temps to 30m
|
||||
rT.reason += ". Shortening " + currenttemp.duration + "m long zero temp to 30m. ";
|
||||
rT.deliverAt = deliverAt;
|
||||
rT.temp = 'absolute';
|
||||
|
@ -115,14 +195,14 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
|
|||
|
||||
var sensitivityRatio;
|
||||
var high_temptarget_raises_sensitivity = profile.exercise_mode || profile.high_temptarget_raises_sensitivity;
|
||||
var normalTarget = 100; // evaluate high/low temptarget against 100, not scheduled basal (which might change)
|
||||
var normalTarget = 100; // evaluate high/low temptarget against 100, not scheduled target (which might change)
|
||||
if ( profile.half_basal_exercise_target ) {
|
||||
var halfBasalTarget = profile.half_basal_exercise_target;
|
||||
} else {
|
||||
var halfBasalTarget = 160; // when temptarget is 160 mg/dL, run 50% basal (120 = 75%; 140 = 60%)
|
||||
halfBasalTarget = 160; // when temptarget is 160 mg/dL, run 50% basal (120 = 75%; 140 = 60%)
|
||||
// 80 mg/dL with low_temptarget_lowers_sensitivity would give 1.5x basal, but is limited to autosens_max (1.2x by default)
|
||||
}
|
||||
if ( high_temptarget_raises_sensitivity && profile.temptargetSet && target_bg > normalTarget + 10
|
||||
if ( high_temptarget_raises_sensitivity && profile.temptargetSet && target_bg > normalTarget
|
||||
|| profile.low_temptarget_lowers_sensitivity && profile.temptargetSet && target_bg < normalTarget ) {
|
||||
// w/ target 100, temp target 110 = .89, 120 = 0.8, 140 = 0.67, 160 = .57, and 200 = .44
|
||||
// e.g.: Sensitivity ratio set to 0.8 based on temp target of 120; Adjusting basal from 1.65 to 1.35; ISF from 58.9 to 73.6
|
||||
|
@ -132,36 +212,36 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
|
|||
// limit sensitivityRatio to profile.autosens_max (1.2x by default)
|
||||
sensitivityRatio = Math.min(sensitivityRatio, profile.autosens_max);
|
||||
sensitivityRatio = round(sensitivityRatio,2);
|
||||
console.error("Sensitivity ratio set to "+sensitivityRatio+" based on temp target of "+target_bg+"; ");
|
||||
} else if (typeof autosens_data !== 'undefined' ) {
|
||||
console.log("Sensitivity ratio set to "+sensitivityRatio+" based on temp target of "+target_bg+"; ");
|
||||
} else if (typeof autosens_data !== 'undefined' && autosens_data) {
|
||||
sensitivityRatio = autosens_data.ratio;
|
||||
console.error("Autosens ratio: "+sensitivityRatio+"; ");
|
||||
console.log("Autosens ratio: "+sensitivityRatio+"; ");
|
||||
}
|
||||
if (sensitivityRatio) {
|
||||
basal = profile.current_basal * sensitivityRatio;
|
||||
basal = round_basal(basal, profile);
|
||||
if (basal != profile_current_basal) {
|
||||
console.error("Adjusting basal from "+profile_current_basal+" to "+basal+"; ");
|
||||
if (basal !== profile_current_basal) {
|
||||
console.log("Adjusting basal from "+profile_current_basal+" to "+basal+"; ");
|
||||
} else {
|
||||
console.error("Basal unchanged: "+basal+"; ");
|
||||
console.log("Basal unchanged: "+basal+"; ");
|
||||
}
|
||||
}
|
||||
|
||||
// adjust min, max, and target BG for sensitivity, such that 50% increase in ISF raises target from 100 to 120
|
||||
if (profile.temptargetSet) {
|
||||
//console.error("Temp Target set, not adjusting with autosens; ");
|
||||
} else if (typeof autosens_data !== 'undefined' ) {
|
||||
//console.log("Temp Target set, not adjusting with autosens; ");
|
||||
} else if (typeof autosens_data !== 'undefined' && autosens_data) {
|
||||
if ( profile.sensitivity_raises_target && autosens_data.ratio < 1 || profile.resistance_lowers_target && autosens_data.ratio > 1 ) {
|
||||
// with a target of 100, default 0.7-1.2 autosens min/max range would allow a 93-117 target range
|
||||
min_bg = round((min_bg - 60) / autosens_data.ratio) + 60;
|
||||
max_bg = round((max_bg - 60) / autosens_data.ratio) + 60;
|
||||
new_target_bg = round((target_bg - 60) / autosens_data.ratio) + 60;
|
||||
var new_target_bg = round((target_bg - 60) / autosens_data.ratio) + 60;
|
||||
// don't allow target_bg below 80
|
||||
new_target_bg = Math.max(80, new_target_bg);
|
||||
if (target_bg == new_target_bg) {
|
||||
console.error("target_bg unchanged: "+new_target_bg+"; ");
|
||||
if (target_bg === new_target_bg) {
|
||||
console.log("target_bg unchanged: "+new_target_bg+"; ");
|
||||
} else {
|
||||
console.error("target_bg from "+target_bg+" to "+new_target_bg+"; ");
|
||||
console.log("target_bg from "+target_bg+" to "+new_target_bg+"; ");
|
||||
}
|
||||
target_bg = new_target_bg;
|
||||
}
|
||||
|
@ -197,34 +277,33 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
|
|||
|
||||
var profile_sens = round(profile.sens,1)
|
||||
var sens = profile.sens;
|
||||
if (typeof autosens_data !== 'undefined' ) {
|
||||
if (typeof autosens_data !== 'undefined' && autosens_data) {
|
||||
sens = profile.sens / sensitivityRatio;
|
||||
sens = round(sens, 1);
|
||||
if (sens != profile_sens) {
|
||||
console.error("ISF from "+profile_sens+" to "+sens);
|
||||
if (sens !== profile_sens) {
|
||||
console.log("ISF from "+profile_sens+" to "+sens);
|
||||
} else {
|
||||
console.error("ISF unchanged: "+sens);
|
||||
console.log("ISF unchanged: "+sens);
|
||||
}
|
||||
//console.error(" (autosens ratio "+sensitivityRatio+")");
|
||||
//console.log(" (autosens ratio "+sensitivityRatio+")");
|
||||
}
|
||||
console.error("; CR:",profile.carb_ratio);
|
||||
|
||||
// compare currenttemp to iob_data.lastTemp and cancel temp if they don't match
|
||||
var lastTempAge;
|
||||
if (typeof iob_data.lastTemp !== 'undefined' ) {
|
||||
lastTempAge = round(( new Date().getTime() - iob_data.lastTemp.date ) / 60000); // in minutes
|
||||
// } ---- added to not produce errors
|
||||
lastTempAge = round(( new Date(systemTime).getTime() - iob_data.lastTemp.date ) / 60000); // in minutes
|
||||
} else {
|
||||
lastTempAge = 0;
|
||||
}
|
||||
//console.error("currenttemp:",currenttemp,"lastTemp:",JSON.stringify(iob_data.lastTemp),"lastTempAge:",lastTempAge,"m");
|
||||
tempModulus = (lastTempAge + currenttemp.duration) % 30;
|
||||
var tempModulus = (lastTempAge + currenttemp.duration) % 30;
|
||||
console.error("currenttemp:",currenttemp,"lastTempAge:",lastTempAge,"m","tempModulus:",tempModulus,"m");
|
||||
rT.temp = 'absolute';
|
||||
rT.deliverAt = deliverAt;
|
||||
if ( microBolusAllowed && currenttemp && iob_data.lastTemp && currenttemp.rate != iob_data.lastTemp.rate ) {
|
||||
rT.reason = "Warning: currenttemp rate "+currenttemp.rate+" != lastTemp rate "+iob_data.lastTemp.rate+" from pumphistory; setting neutral temp of "+basal+".";
|
||||
return tempBasalFunctions.setTempBasal(basal, 30, profile, rT, currenttemp);
|
||||
if ( microBolusAllowed && currenttemp && iob_data.lastTemp && currenttemp.rate !== iob_data.lastTemp.rate && lastTempAge > 10 && currenttemp.duration ) {
|
||||
rT.reason = "Warning: currenttemp rate "+currenttemp.rate+" != lastTemp rate "+iob_data.lastTemp.rate+" from pumphistory; canceling temp";
|
||||
return tempBasalFunctions.setTempBasal(0, 0, profile, rT, currenttemp);
|
||||
}
|
||||
if ( currenttemp && iob_data.lastTemp && currenttemp.duration > 0 ) {
|
||||
// TODO: fix this (lastTemp.duration is how long it has run; currenttemp.duration is time left
|
||||
|
@ -234,10 +313,10 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
|
|||
//}
|
||||
//console.error(lastTempAge, round(iob_data.lastTemp.duration,1), round(lastTempAge - iob_data.lastTemp.duration,1));
|
||||
var lastTempEnded = lastTempAge - iob_data.lastTemp.duration
|
||||
if ( lastTempEnded > 5 ) {
|
||||
rT.reason = "Warning: currenttemp running but lastTemp from pumphistory ended "+lastTempEnded+"m ago; setting neutral temp of "+basal+".";
|
||||
if ( lastTempEnded > 5 && lastTempAge > 10 ) {
|
||||
rT.reason = "Warning: currenttemp running but lastTemp from pumphistory ended "+lastTempEnded+"m ago; canceling temp";
|
||||
//console.error(currenttemp, round(iob_data.lastTemp,1), round(lastTempAge,1));
|
||||
return tempBasalFunctions.setTempBasal(basal, 30, profile, rT, currenttemp);
|
||||
return tempBasalFunctions.setTempBasal(0, 0, profile, rT, currenttemp);
|
||||
}
|
||||
// TODO: figure out a way to do this check that doesn't fail across basal schedule boundaries
|
||||
//if ( tempModulus < 25 && tempModulus > 5 ) {
|
||||
|
@ -264,37 +343,44 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
|
|||
if (iob_data.iob > 0) {
|
||||
var naive_eventualBG = round( bg - (iob_data.iob * sens) );
|
||||
} else { // if IOB is negative, be more conservative and use the lower of sens, profile.sens
|
||||
var naive_eventualBG = round( bg - (iob_data.iob * Math.min(sens, profile.sens) ) );
|
||||
naive_eventualBG = round( bg - (iob_data.iob * Math.min(sens, profile.sens) ) );
|
||||
}
|
||||
// and adjust it for the deviation above
|
||||
var eventualBG = naive_eventualBG + deviation;
|
||||
// calculate what portion of that is due to bolussnooze
|
||||
//var bolusContrib = iob_data.bolussnooze * sens;
|
||||
// and add it back in to get snoozeBG, plus another 50% to avoid low-temping at mealtime
|
||||
//var naive_snoozeBG = round( naive_eventualBG + 1.5 * bolusContrib );
|
||||
// adjust that for deviation like we did eventualBG
|
||||
//var snoozeBG = naive_snoozeBG + deviation;
|
||||
|
||||
// adjust target BG range if needed to safely bring down high BG faster without causing lows
|
||||
if ( bg > max_bg && profile.adv_target_adjustments && ! profile.temptargetSet ) {
|
||||
// raise target for noisy / raw CGM data
|
||||
if (glucose_status.noise >= 2) {
|
||||
// increase target at least 10% (default 30%) for raw / noisy data
|
||||
var noisyCGMTargetMultiplier = Math.max( 1.1, profile.noisyCGMTargetMultiplier );
|
||||
// don't allow maxRaw above 250
|
||||
var maxRaw = Math.min( 250, profile.maxRaw );
|
||||
var adjustedMinBG = round(Math.min(200, min_bg * noisyCGMTargetMultiplier ));
|
||||
var adjustedTargetBG = round(Math.min(200, target_bg * noisyCGMTargetMultiplier ));
|
||||
var adjustedMaxBG = round(Math.min(200, max_bg * noisyCGMTargetMultiplier ));
|
||||
console.log("Raising target_bg for noisy / raw CGM data, from "+target_bg+" to "+adjustedTargetBG+"; ");
|
||||
min_bg = adjustedMinBG;
|
||||
target_bg = adjustedTargetBG;
|
||||
max_bg = adjustedMaxBG;
|
||||
// adjust target BG range if configured to bring down high BG faster
|
||||
} else if ( bg > max_bg && profile.adv_target_adjustments && ! profile.temptargetSet ) {
|
||||
// with target=100, as BG rises from 100 to 160, adjustedTarget drops from 100 to 80
|
||||
var adjustedMinBG = round(Math.max(80, min_bg - (bg - min_bg)/3 ),0);
|
||||
var adjustedTargetBG =round( Math.max(80, target_bg - (bg - target_bg)/3 ),0);
|
||||
var adjustedMaxBG = round(Math.max(80, max_bg - (bg - max_bg)/3 ),0);
|
||||
adjustedMinBG = round(Math.max(80, min_bg - (bg - min_bg)/3 ),0);
|
||||
adjustedTargetBG =round( Math.max(80, target_bg - (bg - target_bg)/3 ),0);
|
||||
adjustedMaxBG = round(Math.max(80, max_bg - (bg - max_bg)/3 ),0);
|
||||
// if eventualBG, naive_eventualBG, and target_bg aren't all above adjustedMinBG, don’t use it
|
||||
//console.error("naive_eventualBG:",naive_eventualBG+", eventualBG:",eventualBG);
|
||||
if (eventualBG > adjustedMinBG && naive_eventualBG > adjustedMinBG && min_bg > adjustedMinBG) {
|
||||
console.error("Adjusting targets for high BG: min_bg from "+min_bg+" to "+adjustedMinBG+"; ");
|
||||
console.log("Adjusting targets for high BG: min_bg from "+min_bg+" to "+adjustedMinBG+"; ");
|
||||
min_bg = adjustedMinBG;
|
||||
} else {
|
||||
console.error("min_bg unchanged: "+min_bg+"; ");
|
||||
console.log("min_bg unchanged: "+min_bg+"; ");
|
||||
}
|
||||
// if eventualBG, naive_eventualBG, and target_bg aren't all above adjustedTargetBG, don’t use it
|
||||
if (eventualBG > adjustedTargetBG && naive_eventualBG > adjustedTargetBG && target_bg > adjustedTargetBG) {
|
||||
console.error("target_bg from "+target_bg+" to "+adjustedTargetBG+"; ");
|
||||
console.log("target_bg from "+target_bg+" to "+adjustedTargetBG+"; ");
|
||||
target_bg = adjustedTargetBG;
|
||||
} else {
|
||||
console.error("target_bg unchanged: "+target_bg+"; ");
|
||||
console.log("target_bg unchanged: "+target_bg+"; ");
|
||||
}
|
||||
// if eventualBG, naive_eventualBG, and max_bg aren't all above adjustedMaxBG, don’t use it
|
||||
if (eventualBG > adjustedMaxBG && naive_eventualBG > adjustedMaxBG && max_bg > adjustedMaxBG) {
|
||||
|
@ -321,7 +407,7 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
|
|||
, 'bg': bg
|
||||
, 'tick': tick
|
||||
, 'eventualBG': eventualBG
|
||||
//, 'snoozeBG': snoozeBG
|
||||
, 'targetBG': target_bg
|
||||
, 'insulinReq': 0
|
||||
, 'reservoir' : reservoir_data // The expected reservoir volume at which to deliver the microbolus (the reservoir volume from right before the last pumphistory run)
|
||||
, 'deliverAt' : deliverAt // The time at which the microbolus should be delivered
|
||||
|
@ -341,71 +427,13 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
|
|||
ZTpredBGs.push(bg);
|
||||
UAMpredBGs.push(bg);
|
||||
|
||||
// enable SMB whenever we have COB or UAM is enabled
|
||||
// SMB is disabled by default, unless explicitly enabled in preferences.json
|
||||
var enableSMB=false;
|
||||
// disable SMB when a high temptarget is set
|
||||
if (! microBolusAllowed) {
|
||||
console.error("SMB disabled (!microBolusAllowed)")
|
||||
} else if (! profile.allowSMB_with_high_temptarget && profile.temptargetSet && target_bg > 100) {
|
||||
console.error("SMB disabled due to high temptarget of",target_bg);
|
||||
enableSMB=false;
|
||||
// enable SMB/UAM (if enabled in preferences) while we have COB
|
||||
} else if (profile.enableSMB_with_COB === true && meal_data.mealCOB) {
|
||||
if (meal_data.bwCarbs) {
|
||||
if (profile.A52_risk_enable) {
|
||||
console.error("Warning: SMB enabled with Bolus Wizard carbs: be sure to easy bolus 30s before using Bolus Wizard")
|
||||
enableSMB=true;
|
||||
} else {
|
||||
console.error("SMB not enabled for Bolus Wizard COB");
|
||||
}
|
||||
} else {
|
||||
console.error("SMB enabled for COB of",meal_data.mealCOB);
|
||||
enableSMB=true;
|
||||
}
|
||||
// enable SMB/UAM (if enabled in preferences) for a full 6 hours after any carb entry
|
||||
// (6 hours is defined in carbWindow in lib/meal/total.js)
|
||||
} else if (profile.enableSMB_after_carbs === true && meal_data.carbs ) {
|
||||
if (meal_data.bwCarbs) {
|
||||
if (profile.A52_risk_enable) {
|
||||
console.error("Warning: SMB enabled with Bolus Wizard carbs: be sure to easy bolus 30s before using Bolus Wizard")
|
||||
enableSMB=true;
|
||||
} else {
|
||||
console.error("SMB not enabled for Bolus Wizard carbs");
|
||||
}
|
||||
} else {
|
||||
console.error("SMB enabled for 6h after carb entry");
|
||||
enableSMB=true;
|
||||
}
|
||||
// enable SMB/UAM (if enabled in preferences) if a low temptarget is set
|
||||
} else if (profile.enableSMB_with_temptarget === true && (profile.temptargetSet && target_bg < 100)) {
|
||||
if (meal_data.bwFound) {
|
||||
if (profile.A52_risk_enable) {
|
||||
console.error("Warning: SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard")
|
||||
enableSMB=true;
|
||||
} else {
|
||||
console.error("enableSMB_with_temptarget not supported within 6h of using Bolus Wizard");
|
||||
}
|
||||
} else {
|
||||
console.error("SMB enabled for temptarget of",convert_bg(target_bg, profile));
|
||||
enableSMB=true;
|
||||
}
|
||||
// enable SMB/UAM if always-on (unless previously disabled for high temptarget)
|
||||
} else if (profile.enableSMB_always === true) {
|
||||
if (meal_data.bwFound) {
|
||||
if (profile.A52_risk_enable === true) {
|
||||
console.error("Warning: SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard")
|
||||
enableSMB=true;
|
||||
} else {
|
||||
console.error("enableSMB_always not supported within 6h of using Bolus Wizard");
|
||||
}
|
||||
} else {
|
||||
console.error("SMB enabled due to enableSMB_always");
|
||||
enableSMB=true;
|
||||
}
|
||||
} else {
|
||||
console.error("SMB disabled (no enableSMB preferences active)");
|
||||
}
|
||||
var enableSMB = enable_smb(
|
||||
profile,
|
||||
microBolusAllowed,
|
||||
meal_data,
|
||||
target_bg
|
||||
);
|
||||
|
||||
// enable UAM (if enabled in preferences)
|
||||
var enableUAM=(profile.enableUAM);
|
||||
|
||||
|
@ -417,43 +445,48 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
|
|||
// calculate current carb absorption rate, and how long to absorb all carbs
|
||||
// CI = current carb impact on BG in mg/dL/5m
|
||||
ci = round((minDelta - bgi),1);
|
||||
uci = round((minDelta - bgi),1);
|
||||
var uci = round((minDelta - bgi),1);
|
||||
// ISF (mg/dL/U) / CR (g/U) = CSF (mg/dL/g)
|
||||
if (profile.temptargetSet) {
|
||||
|
||||
// TODO: remove commented-out code for old behavior
|
||||
//if (profile.temptargetSet) {
|
||||
// if temptargetSet, use unadjusted profile.sens to allow activity mode sensitivityRatio to adjust CR
|
||||
var csf = profile.sens / profile.carb_ratio;
|
||||
} else {
|
||||
//var csf = profile.sens / profile.carb_ratio;
|
||||
//} else {
|
||||
// otherwise, use autosens-adjusted sens to counteract autosens meal insulin dosing adjustments
|
||||
// so that autotuned CR is still in effect even when basals and ISF are being adjusted by autosens
|
||||
var csf = sens / profile.carb_ratio;
|
||||
}
|
||||
//var csf = sens / profile.carb_ratio;
|
||||
//}
|
||||
// use autosens-adjusted sens to counteract autosens meal insulin dosing adjustments so that
|
||||
// autotuned CR is still in effect even when basals and ISF are being adjusted by TT or autosens
|
||||
// this avoids overdosing insulin for large meals when low temp targets are active
|
||||
csf = sens / profile.carb_ratio;
|
||||
console.error("profile.sens:",profile.sens,"sens:",sens,"CSF:",csf);
|
||||
|
||||
var maxCarbAbsorptionRate = 30; // g/h; maximum rate to assume carbs will absorb if no CI observed
|
||||
// limit Carb Impact to maxCarbAbsorptionRate * csf in mg/dL per 5m
|
||||
maxCI = round(maxCarbAbsorptionRate*csf*5/60,1)
|
||||
var maxCI = round(maxCarbAbsorptionRate*csf*5/60,1)
|
||||
if (ci > maxCI) {
|
||||
console.error("Limiting carb impact from",ci,"to",maxCI,"mg/dL/5m (",maxCarbAbsorptionRate,"g/h )");
|
||||
ci = maxCI;
|
||||
}
|
||||
// set meal_carbimpact high enough to absorb all meal carbs over 6 hours
|
||||
// total_impact (mg/dL) = CSF (mg/dL/g) * carbs (g)
|
||||
//console.error(csf * meal_data.carbs);
|
||||
// meal_carbimpact (mg/dL/5m) = CSF (mg/dL/g) * carbs (g) / 6 (h) * (1h/60m) * 5 (m/5m) * 2 (for linear decay)
|
||||
//var meal_carbimpact = round((csf * meal_data.carbs / 6 / 60 * 5 * 2),1)
|
||||
var remainingCATimeMin = 3; // h; before carb absorption starts
|
||||
// adjust remainingCATime (instead of CR) for autosens
|
||||
remainingCATimeMin = remainingCATimeMin / sensitivityRatio;
|
||||
var remainingCATimeMin = 3; // h; duration of expected not-yet-observed carb absorption
|
||||
// adjust remainingCATime (instead of CR) for autosens if sensitivityRatio defined
|
||||
if (sensitivityRatio){
|
||||
remainingCATimeMin = remainingCATimeMin / sensitivityRatio;
|
||||
}
|
||||
// 20 g/h means that anything <= 60g will get a remainingCATimeMin, 80g will get 4h, and 120g 6h
|
||||
// when actual absorption ramps up it will take over from remainingCATime
|
||||
var assumedCarbAbsorptionRate = 20; // g/h; maximum rate to assume carbs will absorb if no CI observed
|
||||
var remainingCATime = remainingCATimeMin; // added by mike https://github.com/openaps/oref0/issues/884
|
||||
var remainingCATime = remainingCATimeMin;
|
||||
if (meal_data.carbs) {
|
||||
// if carbs * assumedCarbAbsorptionRate > remainingCATimeMin, raise it
|
||||
// so <= 90g is assumed to take 3h, and 120g=4h
|
||||
remainingCATimeMin = Math.max(remainingCATimeMin, meal_data.mealCOB/assumedCarbAbsorptionRate);
|
||||
var lastCarbAge = round(( new Date().getTime() - meal_data.lastCarbTime ) / 60000);
|
||||
var lastCarbAge = round(( new Date(systemTime).getTime() - meal_data.lastCarbTime ) / 60000);
|
||||
//console.error(meal_data.lastCarbTime, lastCarbAge);
|
||||
|
||||
fractionCOBAbsorbed = ( meal_data.carbs - meal_data.mealCOB ) / meal_data.carbs;
|
||||
var fractionCOBAbsorbed = ( meal_data.carbs - meal_data.mealCOB ) / meal_data.carbs;
|
||||
remainingCATime = remainingCATimeMin + 1.5 * lastCarbAge/60;
|
||||
remainingCATime = round(remainingCATime,1);
|
||||
//console.error(fractionCOBAbsorbed, remainingCATimeAdjustment, remainingCATime)
|
||||
|
@ -478,7 +511,6 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
|
|||
// remainingCIpeak (mg/dL/5m) = remainingCarbs (g) * CSF (mg/dL/g) * 5 (m/5m) * 1h/60m / (remainingCATime/2) (h)
|
||||
var remainingCIpeak = remainingCarbs * csf * 5 / 60 / (remainingCATime/2);
|
||||
//console.error(profile.min_5m_carbimpact,ci,totalCI,totalCA,remainingCarbs,remainingCI,remainingCATime);
|
||||
//if (meal_data.mealCOB * 3 > meal_data.carbs) { }
|
||||
|
||||
// calculate peak deviation in last hour, and slope from that to current deviation
|
||||
var slopeFromMaxDeviation = round(meal_data.slopeFromMaxDeviation,2);
|
||||
|
@ -488,17 +520,17 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
|
|||
var slopeFromDeviations = Math.min(slopeFromMaxDeviation,-slopeFromMinDeviation/3);
|
||||
//console.error(slopeFromMaxDeviation);
|
||||
|
||||
aci = 10;
|
||||
var aci = 10;
|
||||
//5m data points = g * (1U/10g) * (40mg/dL/1U) / (mg/dL/5m)
|
||||
// duration (in 5m data points) = COB (g) * CSF (mg/dL/g) / ci (mg/dL/5m)
|
||||
// limit cid to remainingCATime hours: the reset goes to remainingCI
|
||||
if (ci == 0) {
|
||||
if (ci === 0) {
|
||||
// avoid divide by zero
|
||||
cid = 0;
|
||||
} else {
|
||||
cid = Math.min(remainingCATime*60/5/2,Math.max(0, meal_data.mealCOB * csf / ci ));
|
||||
}
|
||||
acid = Math.max(0, meal_data.mealCOB * csf / aci );
|
||||
var acid = Math.max(0, meal_data.mealCOB * csf / aci );
|
||||
// duration (hours) = duration (5m) * 5 / 60 * 2 (to account for linear decay)
|
||||
console.error("Carb Impact:",ci,"mg/dL per 5m; CI Duration:",round(cid*5/60*2,1),"hours; remaining CI (~2h peak):",round(remainingCIpeak,1),"mg/dL per 5m");
|
||||
//console.error("Accel. Carb Impact:",aci,"mg/dL per 5m; ACI Duration:",round(acid*5/60*2,1),"hours");
|
||||
|
@ -529,18 +561,18 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
|
|||
try {
|
||||
iobArray.forEach(function(iobTick) {
|
||||
//console.error(iobTick);
|
||||
predBGI = round(( -iobTick.activity * sens * 5 ), 2);
|
||||
predZTBGI = round(( -iobTick.iobWithZeroTemp.activity * sens * 5 ), 2);
|
||||
var predBGI = round(( -iobTick.activity * sens * 5 ), 2);
|
||||
var predZTBGI = round(( -iobTick.iobWithZeroTemp.activity * sens * 5 ), 2);
|
||||
// for IOBpredBGs, predicted deviation impact drops linearly from current deviation down to zero
|
||||
// over 60 minutes (data points every 5m)
|
||||
predDev = ci * ( 1 - Math.min(1,IOBpredBGs.length/(60/5)) );
|
||||
var predDev = ci * ( 1 - Math.min(1,IOBpredBGs.length/(60/5)) );
|
||||
IOBpredBG = IOBpredBGs[IOBpredBGs.length-1] + predBGI + predDev;
|
||||
// calculate predBGs with long zero temp without deviations
|
||||
ZTpredBG = ZTpredBGs[ZTpredBGs.length-1] + predZTBGI;
|
||||
var ZTpredBG = ZTpredBGs[ZTpredBGs.length-1] + predZTBGI;
|
||||
// for COBpredBGs, predicted carb impact drops linearly from current carb impact down to zero
|
||||
// eventually accounting for all carbs (if they can be absorbed over DIA)
|
||||
predCI = Math.max(0, Math.max(0,ci) * ( 1 - COBpredBGs.length/Math.max(cid*2,1) ) );
|
||||
predACI = Math.max(0, Math.max(0,aci) * ( 1 - COBpredBGs.length/Math.max(acid*2,1) ) );
|
||||
var predCI = Math.max(0, Math.max(0,ci) * ( 1 - COBpredBGs.length/Math.max(cid*2,1) ) );
|
||||
var predACI = Math.max(0, Math.max(0,aci) * ( 1 - COBpredBGs.length/Math.max(acid*2,1) ) );
|
||||
// if any carbs aren't absorbed after remainingCATime hours, assume they'll absorb in a /\ shaped
|
||||
// bilinear curve peaking at remainingCIpeak at remainingCATime/2 hours (remainingCATime/2*12 * 5m)
|
||||
// and ending at remainingCATime h (remainingCATime*12 * 5m intervals)
|
||||
|
@ -549,18 +581,18 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
|
|||
remainingCItotal += predCI+remainingCI;
|
||||
remainingCIs.push(round(remainingCI,0));
|
||||
predCIs.push(round(predCI,0));
|
||||
//console.error(round(predCI,1)+"+"+round(remainingCI,1)+" ");
|
||||
//console.log(round(predCI,1)+"+"+round(remainingCI,1)+" ");
|
||||
COBpredBG = COBpredBGs[COBpredBGs.length-1] + predBGI + Math.min(0,predDev) + predCI + remainingCI;
|
||||
aCOBpredBG = aCOBpredBGs[aCOBpredBGs.length-1] + predBGI + Math.min(0,predDev) + predACI;
|
||||
var aCOBpredBG = aCOBpredBGs[aCOBpredBGs.length-1] + predBGI + Math.min(0,predDev) + predACI;
|
||||
// for UAMpredBGs, predicted carb impact drops at slopeFromDeviations
|
||||
// calculate predicted CI from UAM based on slopeFromDeviations
|
||||
predUCIslope = Math.max(0, uci + ( UAMpredBGs.length*slopeFromDeviations ) );
|
||||
var predUCIslope = Math.max(0, uci + ( UAMpredBGs.length*slopeFromDeviations ) );
|
||||
// if slopeFromDeviations is too flat, predicted deviation impact drops linearly from
|
||||
// current deviation down to zero over 3h (data points every 5m)
|
||||
predUCImax = Math.max(0, uci * ( 1 - UAMpredBGs.length/Math.max(3*60/5,1) ) );
|
||||
var predUCImax = Math.max(0, uci * ( 1 - UAMpredBGs.length/Math.max(3*60/5,1) ) );
|
||||
//console.error(predUCIslope, predUCImax);
|
||||
// predicted CI from UAM is the lesser of CI based on deviationSlope or DIA
|
||||
predUCI = Math.min(predUCIslope, predUCImax);
|
||||
var predUCI = Math.min(predUCIslope, predUCImax);
|
||||
if(predUCI>0) {
|
||||
//console.error(UAMpredBGs.length,slopeFromDeviations, predUCI);
|
||||
UAMduration=round((UAMpredBGs.length+1)*5/60,1);
|
||||
|
@ -582,7 +614,7 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
|
|||
// set minPredBGs starting when currently-dosed insulin activity will peak
|
||||
// look ahead 60m (regardless of insulin type) so as to be less aggressive on slower insulins
|
||||
var insulinPeakTime = 60;
|
||||
// add 30m to allow for insluin delivery (SMBs or temps)
|
||||
// add 30m to allow for insulin delivery (SMBs or temps)
|
||||
insulinPeakTime = 90;
|
||||
var insulinPeak5m = (insulinPeakTime/60)*12;
|
||||
//console.error(insulinPeakTime, insulinPeak5m, profile.insulinPeakTime, profile.curve);
|
||||
|
@ -599,19 +631,18 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
|
|||
// set eventualBG to include effect of carbs
|
||||
//console.error("PredBGs:",JSON.stringify(predBGs));
|
||||
} catch (e) {
|
||||
console.error("Problem with iobArray. Optional feature Advanced Meal Assist disabled:",e);
|
||||
console.error("Problem with iobArray. Optional feature Advanced Meal Assist disabled");
|
||||
}
|
||||
if (meal_data.mealCOB) {
|
||||
console.error("predCIs (mg/dL/5m):",predCIs.join(" "));
|
||||
console.error("remainingCIs: ",remainingCIs.join(" "));
|
||||
}
|
||||
//,"totalCA:",round(totalCA,2),"remainingCItotal/csf+totalCA:",round(remainingCItotal/csf+totalCA,2));
|
||||
rT.predBGs = {};
|
||||
IOBpredBGs.forEach(function(p, i, theArray) {
|
||||
theArray[i] = round(Math.min(401,Math.max(39,p)));
|
||||
});
|
||||
for (var i=IOBpredBGs.length-1; i > 12; i--) {
|
||||
if (IOBpredBGs[i-1] != IOBpredBGs[i]) { break; }
|
||||
if (IOBpredBGs[i-1] !== IOBpredBGs[i]) { break; }
|
||||
else { IOBpredBGs.pop(); }
|
||||
}
|
||||
rT.predBGs.IOB = IOBpredBGs;
|
||||
|
@ -619,10 +650,9 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
|
|||
ZTpredBGs.forEach(function(p, i, theArray) {
|
||||
theArray[i] = round(Math.min(401,Math.max(39,p)));
|
||||
});
|
||||
for (var i=ZTpredBGs.length-1; i > 6; i--) {
|
||||
//if (ZTpredBGs[i-1] != ZTpredBGs[i]) { break; }
|
||||
for (i=ZTpredBGs.length-1; i > 6; i--) {
|
||||
// stop displaying ZTpredBGs once they're rising and above target
|
||||
if (ZTpredBGs[i-1] >= ZTpredBGs[i] || ZTpredBGs[i] < target_bg) { break; }
|
||||
if (ZTpredBGs[i-1] >= ZTpredBGs[i] || ZTpredBGs[i] <= target_bg) { break; }
|
||||
else { ZTpredBGs.pop(); }
|
||||
}
|
||||
rT.predBGs.ZT = ZTpredBGs;
|
||||
|
@ -631,19 +661,17 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
|
|||
aCOBpredBGs.forEach(function(p, i, theArray) {
|
||||
theArray[i] = round(Math.min(401,Math.max(39,p)));
|
||||
});
|
||||
for (var i=aCOBpredBGs.length-1; i > 12; i--) {
|
||||
if (aCOBpredBGs[i-1] != aCOBpredBGs[i]) { break; }
|
||||
for (i=aCOBpredBGs.length-1; i > 12; i--) {
|
||||
if (aCOBpredBGs[i-1] !== aCOBpredBGs[i]) { break; }
|
||||
else { aCOBpredBGs.pop(); }
|
||||
}
|
||||
// disable for now. may want to add a preference to re-enable
|
||||
//rT.predBGs.aCOB = aCOBpredBGs;
|
||||
}
|
||||
if (meal_data.mealCOB > 0 && ( ci > 0 || remainingCIpeak > 0 )) {
|
||||
COBpredBGs.forEach(function(p, i, theArray) {
|
||||
theArray[i] = round(Math.min(401,Math.max(39,p)));
|
||||
});
|
||||
for (var i=COBpredBGs.length-1; i > 12; i--) {
|
||||
if (COBpredBGs[i-1] != COBpredBGs[i]) { break; }
|
||||
for (i=COBpredBGs.length-1; i > 12; i--) {
|
||||
if (COBpredBGs[i-1] !== COBpredBGs[i]) { break; }
|
||||
else { COBpredBGs.pop(); }
|
||||
}
|
||||
rT.predBGs.COB = COBpredBGs;
|
||||
|
@ -655,8 +683,8 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
|
|||
UAMpredBGs.forEach(function(p, i, theArray) {
|
||||
theArray[i] = round(Math.min(401,Math.max(39,p)));
|
||||
});
|
||||
for (var i=UAMpredBGs.length-1; i > 12; i--) {
|
||||
if (UAMpredBGs[i-1] != UAMpredBGs[i]) { break; }
|
||||
for (i=UAMpredBGs.length-1; i > 12; i--) {
|
||||
if (UAMpredBGs[i-1] !== UAMpredBGs[i]) { break; }
|
||||
else { UAMpredBGs.pop(); }
|
||||
}
|
||||
rT.predBGs.UAM = UAMpredBGs;
|
||||
|
@ -666,7 +694,7 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
|
|||
}
|
||||
}
|
||||
|
||||
// set eventualBG and snoozeBG based on COB or UAM predBGs
|
||||
// set eventualBG based on COB or UAM predBGs
|
||||
rT.eventualBG = eventualBG;
|
||||
}
|
||||
|
||||
|
@ -733,14 +761,6 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
|
|||
//console.error("minUAMPredBG:",minUAMPredBG,"minZTGuardBG:",minZTGuardBG,"minZTUAMPredBG:",minZTUAMPredBG);
|
||||
// if any carbs have been entered recently
|
||||
if (meal_data.carbs) {
|
||||
// average the minIOBPredBG and minUAMPredBG if available
|
||||
/*
|
||||
if ( minUAMPredBG < 999 ) {
|
||||
avgMinPredBG = round( (minIOBPredBG+minUAMPredBG)/2 );
|
||||
} else {
|
||||
avgMinPredBG = minIOBPredBG;
|
||||
}
|
||||
*/
|
||||
|
||||
// if UAM is disabled, use max of minIOBPredBG, minCOBPredBG
|
||||
if ( ! enableUAM && minCOBPredBG < 999 ) {
|
||||
|
@ -748,30 +768,29 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
|
|||
// if we have COB, use minCOBPredBG, or blendedMinPredBG if it's higher
|
||||
} else if ( minCOBPredBG < 999 ) {
|
||||
// calculate blendedMinPredBG based on how many carbs remain as COB
|
||||
//blendedMinPredBG = fractionCarbsLeft*minCOBPredBG + (1-fractionCarbsLeft)*minUAMPredBG;
|
||||
blendedMinPredBG = fractionCarbsLeft*minCOBPredBG + (1-fractionCarbsLeft)*minZTUAMPredBG;
|
||||
var blendedMinPredBG = fractionCarbsLeft*minCOBPredBG + (1-fractionCarbsLeft)*minZTUAMPredBG;
|
||||
// if blendedMinPredBG > minCOBPredBG, use that instead
|
||||
minPredBG = round(Math.max(minIOBPredBG, minCOBPredBG, blendedMinPredBG));
|
||||
// if carbs have been entered, but have expired, use minUAMPredBG
|
||||
} else {
|
||||
//minPredBG = minUAMPredBG;
|
||||
} else if ( enableUAM ) {
|
||||
minPredBG = minZTUAMPredBG;
|
||||
} else {
|
||||
minPredBG = minGuardBG;
|
||||
}
|
||||
// in pure UAM mode, use the higher of minIOBPredBG,minUAMPredBG
|
||||
} else if ( enableUAM ) {
|
||||
//minPredBG = round(Math.max(minIOBPredBG,minUAMPredBG));
|
||||
minPredBG = round(Math.max(minIOBPredBG,minZTUAMPredBG));
|
||||
}
|
||||
|
||||
// make sure minPredBG isn't higher than avgPredBG
|
||||
minPredBG = Math.min( minPredBG, avgPredBG );
|
||||
|
||||
console.error("minPredBG: "+minPredBG+" minIOBPredBG: "+minIOBPredBG+" minZTGuardBG: "+minZTGuardBG);
|
||||
console.log("minPredBG: "+minPredBG+" minIOBPredBG: "+minIOBPredBG+" minZTGuardBG: "+minZTGuardBG);
|
||||
if (minCOBPredBG < 999) {
|
||||
console.error(" minCOBPredBG: "+minCOBPredBG);
|
||||
console.log(" minCOBPredBG: "+minCOBPredBG);
|
||||
}
|
||||
if (minUAMPredBG < 999) {
|
||||
console.error(" minUAMPredBG: "+minUAMPredBG);
|
||||
console.log(" minUAMPredBG: "+minUAMPredBG);
|
||||
}
|
||||
console.error(" avgPredBG:",avgPredBG,"COB:",meal_data.mealCOB,"/",meal_data.carbs);
|
||||
// But if the COB line falls off a cliff, don't trust UAM too much:
|
||||
|
@ -782,7 +801,7 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
|
|||
|
||||
rT.COB=meal_data.mealCOB;
|
||||
rT.IOB=iob_data.iob;
|
||||
rT.reason="COB: " + meal_data.mealCOB + ", Dev: " + convert_bg(deviation, profile) + ", BGI: " + convert_bg(bgi, profile) + ", ISF: " + convert_bg(sens, profile) + ", CR: " + round(profile.carb_ratio, 2) + ", Target: " + convert_bg(target_bg, profile) + ", minPredBG " + convert_bg(minPredBG, profile) + ", minGuardBG " + convert_bg(minGuardBG, profile) + ", IOBpredBG " + convert_bg(lastIOBpredBG, profile);
|
||||
rT.reason="COB: " + round(meal_data.mealCOB, 1) + ", Dev: " + convert_bg(deviation, profile) + ", BGI: " + convert_bg(bgi, profile) + ", ISF: " + convert_bg(sens, profile) + ", CR: " + round(profile.carb_ratio, 2) + ", Target: " + convert_bg(target_bg, profile) + ", minPredBG " + convert_bg(minPredBG, profile) + ", minGuardBG " + convert_bg(minGuardBG, profile) + ", IOBpredBG " + convert_bg(lastIOBpredBG, profile);
|
||||
if (lastCOBpredBG > 0) {
|
||||
rT.reason += ", COBpredBG " + convert_bg(lastCOBpredBG, profile);
|
||||
}
|
||||
|
@ -790,9 +809,7 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
|
|||
rT.reason += ", UAMpredBG " + convert_bg(lastUAMpredBG, profile)
|
||||
}
|
||||
rT.reason += "; ";
|
||||
//var bgUndershoot = threshold - Math.min(minGuardBG, Math.max( naive_eventualBG, eventualBG ));
|
||||
// use naive_eventualBG if above 40, but switch to minGuardBG if both eventualBGs hit floor of 39
|
||||
//var carbsReqBG = Math.max( naive_eventualBG, eventualBG );
|
||||
var carbsReqBG = naive_eventualBG;
|
||||
if ( carbsReqBG < 40 ) {
|
||||
carbsReqBG = Math.min( minGuardBG, carbsReqBG );
|
||||
|
@ -802,14 +819,14 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
|
|||
var minutesAboveMinBG = 240;
|
||||
var minutesAboveThreshold = 240;
|
||||
if (meal_data.mealCOB > 0 && ( ci > 0 || remainingCIpeak > 0 )) {
|
||||
for (var i=0; i<COBpredBGs.length; i++) {
|
||||
for (i=0; i<COBpredBGs.length; i++) {
|
||||
//console.error(COBpredBGs[i], min_bg);
|
||||
if ( COBpredBGs[i] < min_bg ) {
|
||||
minutesAboveMinBG = 5*i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (var i=0; i<COBpredBGs.length; i++) {
|
||||
for (i=0; i<COBpredBGs.length; i++) {
|
||||
//console.error(COBpredBGs[i], threshold);
|
||||
if ( COBpredBGs[i] < threshold ) {
|
||||
minutesAboveThreshold = 5*i;
|
||||
|
@ -817,14 +834,14 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
|
|||
}
|
||||
}
|
||||
} else {
|
||||
for (var i=0; i<IOBpredBGs.length; i++) {
|
||||
for (i=0; i<IOBpredBGs.length; i++) {
|
||||
//console.error(IOBpredBGs[i], min_bg);
|
||||
if ( IOBpredBGs[i] < min_bg ) {
|
||||
minutesAboveMinBG = 5*i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (var i=0; i<IOBpredBGs.length; i++) {
|
||||
for (i=0; i<IOBpredBGs.length; i++) {
|
||||
//console.error(IOBpredBGs[i], threshold);
|
||||
if ( IOBpredBGs[i] < threshold ) {
|
||||
minutesAboveThreshold = 5*i;
|
||||
|
@ -848,9 +865,8 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
|
|||
if ( minutesAboveThreshold < 240 || minutesAboveMinBG < 60 ) {
|
||||
console.error("BG projected to remain above",convert_bg(threshold,profile),"for",minutesAboveThreshold,"minutes");
|
||||
}
|
||||
// include at least minutesAboveMinBG worth of zero temps in calculating carbsReq
|
||||
// include at least minutesAboveThreshold worth of zero temps in calculating carbsReq
|
||||
// always include at least 30m worth of zero temp (carbs to 80, low temp up to target)
|
||||
//var zeroTempDuration = Math.max(30,minutesAboveMinBG);
|
||||
var zeroTempDuration = minutesAboveThreshold;
|
||||
// BG undershoot, minus effect of zero temps until hitting min_bg, converted to grams, minus COB
|
||||
var zeroTempEffect = profile.current_basal*sens*zeroTempDuration/60;
|
||||
|
@ -862,8 +878,10 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
|
|||
console.error("naive_eventualBG:",naive_eventualBG,"bgUndershoot:",bgUndershoot,"zeroTempDuration:",zeroTempDuration,"zeroTempEffect:",zeroTempEffect,"carbsReq:",carbsReq);
|
||||
if ( carbsReq >= profile.carbsReqThreshold && minutesAboveThreshold <= 45 ) {
|
||||
rT.carbsReq = carbsReq;
|
||||
rT.carbsReqWithin = minutesAboveThreshold;
|
||||
rT.reason += carbsReq + " add'l carbs req w/in " + minutesAboveThreshold + "m; ";
|
||||
}
|
||||
|
||||
// don't low glucose suspend if IOB is already super negative and BG is rising faster than predicted
|
||||
if (bg < threshold && iob_data.iob < -profile.current_basal*20/60 && minDelta > 0 && minDelta > expectedDelta) {
|
||||
rT.reason += "IOB "+iob_data.iob+" < " + round(-profile.current_basal*20/60,2);
|
||||
|
@ -871,7 +889,7 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
|
|||
// predictive low glucose suspend mode: BG is / is projected to be < threshold
|
||||
} else if ( bg < threshold || minGuardBG < threshold ) {
|
||||
rT.reason += "minGuardBG " + convert_bg(minGuardBG, profile) + "<" + convert_bg(threshold, profile);
|
||||
var bgUndershoot = target_bg - minGuardBG;
|
||||
bgUndershoot = target_bg - minGuardBG;
|
||||
var worstCaseInsulinReq = bgUndershoot / sens;
|
||||
var durationReq = round(60*worstCaseInsulinReq / profile.current_basal);
|
||||
durationReq = round(durationReq/30)*30;
|
||||
|
@ -880,6 +898,13 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
|
|||
return tempBasalFunctions.setTempBasal(0, durationReq, profile, rT, currenttemp);
|
||||
}
|
||||
|
||||
// if not in LGS mode, cancel temps before the top of the hour to reduce beeping/vibration
|
||||
// console.error(profile.skip_neutral_temps, rT.deliverAt.getMinutes());
|
||||
if ( profile.skip_neutral_temps && rT.deliverAt.getMinutes() >= 55 ) {
|
||||
rT.reason += "; Canceling temp at " + rT.deliverAt.getMinutes() + "m past the hour. ";
|
||||
return tempBasalFunctions.setTempBasal(0, 0, profile, rT, currenttemp);
|
||||
}
|
||||
|
||||
if (eventualBG < min_bg) { // if eventual BG is below target:
|
||||
rT.reason += "Eventual BG " + convert_bg(eventualBG, profile) + " < " + convert_bg(min_bg, profile);
|
||||
// if 5m or 30m avg BG is rising faster than expected delta
|
||||
|
@ -904,9 +929,7 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
|
|||
}
|
||||
|
||||
// calculate 30m low-temp required to get projected BG up to target
|
||||
// use snoozeBG to more gradually ramp in any counteraction of the user's boluses
|
||||
// multiply by 2 to low-temp faster for increased hypo safety
|
||||
//var insulinReq = 2 * Math.min(0, (snoozeBG - target_bg) / sens);
|
||||
var insulinReq = 2 * Math.min(0, (eventualBG - target_bg) / sens);
|
||||
insulinReq = round( insulinReq , 2);
|
||||
// calculate naiveInsulinReq based on naive_eventualBG
|
||||
|
@ -914,7 +937,6 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
|
|||
naiveInsulinReq = round( naiveInsulinReq , 2);
|
||||
if (minDelta < 0 && minDelta > expectedDelta) {
|
||||
// if we're barely falling, newinsulinReq should be barely negative
|
||||
//rT.reason += ", Snooze BG " + convert_bg(snoozeBG, profile);
|
||||
var newinsulinReq = round(( insulinReq * (minDelta / expectedDelta) ), 2);
|
||||
//console.error("Increasing insulinReq from " + insulinReq + " to " + newinsulinReq);
|
||||
insulinReq = newinsulinReq;
|
||||
|
@ -922,6 +944,7 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
|
|||
// rate required to deliver insulinReq less insulin over 30m:
|
||||
var rate = basal + (2 * insulinReq);
|
||||
rate = round_basal(rate, profile);
|
||||
|
||||
// if required temp < existing temp basal
|
||||
var insulinScheduled = currenttemp.duration * (currenttemp.rate - basal) / 60;
|
||||
// if current temp would deliver a lot (30% of basal) less than the required insulin,
|
||||
|
@ -937,18 +960,17 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
|
|||
} else {
|
||||
// calculate a long enough zero temp to eventually correct back up to target
|
||||
if ( rate <=0 ) {
|
||||
var bgUndershoot = target_bg - naive_eventualBG;
|
||||
var worstCaseInsulinReq = bgUndershoot / sens;
|
||||
var durationReq = round(60*worstCaseInsulinReq / profile.current_basal);
|
||||
bgUndershoot = target_bg - naive_eventualBG;
|
||||
worstCaseInsulinReq = bgUndershoot / sens;
|
||||
durationReq = round(60*worstCaseInsulinReq / profile.current_basal);
|
||||
if (durationReq < 0) {
|
||||
durationReq = 0;
|
||||
// don't set an SMB zero temp longer than 60 minutess
|
||||
// don't set a temp longer than 120 minutes
|
||||
} else {
|
||||
durationReq = round(durationReq/30)*30;
|
||||
durationReq = Math.min(60,Math.max(0,durationReq));
|
||||
durationReq = Math.min(120,Math.max(0,durationReq));
|
||||
}
|
||||
//console.error(durationReq);
|
||||
//rT.reason += "insulinReq " + insulinReq + "; "
|
||||
if (durationReq > 0) {
|
||||
rT.reason += ", setting " + durationReq + "m zero temp. ";
|
||||
return tempBasalFunctions.setTempBasal(rate, durationReq, profile, rT, currenttemp);
|
||||
|
@ -995,8 +1017,7 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
|
|||
|
||||
// eventual BG is at/above target
|
||||
// if iob is over max, just cancel any temps
|
||||
// if we're not here because of SMB, eventual BG is at/above target
|
||||
if (! (microBolusAllowed && rT.COB)) {
|
||||
if ( eventualBG >= max_bg ) {
|
||||
rT.reason += "Eventual BG " + convert_bg(eventualBG, profile) + " >= " + convert_bg(max_bg, profile) + ", ";
|
||||
}
|
||||
if (iob_data.iob > max_iob) {
|
||||
|
@ -1012,15 +1033,7 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
|
|||
|
||||
// insulinReq is the additional insulin required to get minPredBG down to target_bg
|
||||
//console.error(minPredBG,eventualBG);
|
||||
//var insulinReq = round( (Math.min(minPredBG,eventualBG) - target_bg) / sens, 2);
|
||||
var insulinReq = round( (Math.min(minPredBG,eventualBG) - target_bg) / sens, 2);
|
||||
// when dropping, but not as fast as expected, reduce insulinReq proportionally
|
||||
// to the what fraction of expectedDelta we're dropping at
|
||||
//if (minDelta < 0 && minDelta > expectedDelta) {
|
||||
//var newinsulinReq = round(( insulinReq * (1 - (minDelta / expectedDelta)) ), 2);
|
||||
//console.error("Reducing insulinReq from " + insulinReq + " to " + newinsulinReq + " for minDelta " + minDelta + " vs. expectedDelta " + expectedDelta);
|
||||
//insulinReq = newinsulinReq;
|
||||
//}
|
||||
insulinReq = round( (Math.min(minPredBG,eventualBG) - target_bg) / sens, 2);
|
||||
// if that would put us over max_iob, then reduce accordingly
|
||||
if (insulinReq > max_iob-iob_data.iob) {
|
||||
rT.reason += "max_iob " + max_iob + ", ";
|
||||
|
@ -1028,49 +1041,56 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
|
|||
}
|
||||
|
||||
// rate required to deliver insulinReq more insulin over 30m:
|
||||
var rate = basal + (2 * insulinReq);
|
||||
rate = basal + (2 * insulinReq);
|
||||
rate = round_basal(rate, profile);
|
||||
insulinReq = round(insulinReq,3);
|
||||
rT.insulinReq = insulinReq;
|
||||
//console.error(iob_data.lastBolusTime);
|
||||
// minutes since last bolus
|
||||
var lastBolusAge = round(( new Date().getTime() - iob_data.lastBolusTime ) / 60000,1);
|
||||
var lastBolusAge = round(( new Date(systemTime).getTime() - iob_data.lastBolusTime ) / 60000,1);
|
||||
//console.error(lastBolusAge);
|
||||
//console.error(profile.temptargetSet, target_bg, rT.COB);
|
||||
// only allow microboluses with COB or low temp targets, or within DIA hours of a bolus
|
||||
if (microBolusAllowed && enableSMB && bg > threshold) {
|
||||
// never bolus more than maxSMBBasalMinutes worth of basal
|
||||
mealInsulinReq = round( meal_data.mealCOB / profile.carb_ratio ,3);
|
||||
if (typeof profile.maxSMBBasalMinutes == 'undefined' ) {
|
||||
maxBolus = round( profile.current_basal * 30 / 60 ,1);
|
||||
var mealInsulinReq = round( meal_data.mealCOB / profile.carb_ratio ,3);
|
||||
if (typeof profile.maxSMBBasalMinutes === 'undefined' ) {
|
||||
var maxBolus = round( profile.current_basal * 30 / 60 ,1);
|
||||
console.error("profile.maxSMBBasalMinutes undefined: defaulting to 30m");
|
||||
// if IOB covers more than COB, limit maxBolus to 30m of basal
|
||||
} else if ( iob_data.iob > mealInsulinReq && iob_data.iob > 0 ) {
|
||||
console.error("IOB",iob_data.iob,"> COB",meal_data.mealCOB+"; mealInsulinReq =",mealInsulinReq);
|
||||
maxBolus = round( profile.current_basal * 30 / 60 ,1);
|
||||
if (profile.maxUAMSMBBasalMinutes) {
|
||||
console.error("profile.maxUAMSMBBasalMinutes:",profile.maxUAMSMBBasalMinutes,"profile.current_basal:",profile.current_basal);
|
||||
maxBolus = round( profile.current_basal * profile.maxUAMSMBBasalMinutes / 60 ,1);
|
||||
} else {
|
||||
console.error("profile.maxUAMSMBBasalMinutes undefined: defaulting to 30m");
|
||||
maxBolus = round( profile.current_basal * 30 / 60 ,1);
|
||||
}
|
||||
} else {
|
||||
console.error("profile.maxSMBBasalMinutes:",profile.maxSMBBasalMinutes,"profile.current_basal:",profile.current_basal);
|
||||
maxBolus = round( profile.current_basal * profile.maxSMBBasalMinutes / 60 ,1);
|
||||
}
|
||||
// bolus 1/2 the insulinReq, up to maxBolus, rounding down to nearest 0.1U
|
||||
microBolus = Math.floor(Math.min(insulinReq/2,maxBolus)*10)/10;
|
||||
// bolus 1/2 the insulinReq, up to maxBolus, rounding down to nearest bolus increment
|
||||
var roundSMBTo = 1 / profile.bolus_increment;
|
||||
var microBolus = Math.floor(Math.min(insulinReq/2,maxBolus)*roundSMBTo)/roundSMBTo;
|
||||
// calculate a long enough zero temp to eventually correct back up to target
|
||||
var smbTarget = target_bg;
|
||||
var worstCaseInsulinReq = (smbTarget - (naive_eventualBG + minIOBPredBG)/2 ) / sens;
|
||||
var durationReq = round(60*worstCaseInsulinReq / profile.current_basal);
|
||||
worstCaseInsulinReq = (smbTarget - (naive_eventualBG + minIOBPredBG)/2 ) / sens;
|
||||
durationReq = round(60*worstCaseInsulinReq / profile.current_basal);
|
||||
|
||||
// if insulinReq > 0 but not enough for a microBolus, don't set an SMB zero temp
|
||||
if (insulinReq > 0 && microBolus < 0.1) {
|
||||
if (insulinReq > 0 && microBolus < profile.bolus_increment) {
|
||||
durationReq = 0;
|
||||
}
|
||||
|
||||
var smbLowTempReq = 0;
|
||||
if (durationReq <= 0) {
|
||||
durationReq = 0;
|
||||
// don't set a temp longer than 120 minutes
|
||||
// don't set an SMB zero temp longer than 60 minutes
|
||||
} else if (durationReq >= 30) {
|
||||
durationReq = round(durationReq/30)*30;
|
||||
durationReq = Math.min(120,Math.max(0,durationReq));
|
||||
durationReq = Math.min(60,Math.max(0,durationReq));
|
||||
} else {
|
||||
// if SMB durationReq is less than 30m, set a nonzero low temp
|
||||
smbLowTempReq = round( basal * durationReq/30 ,2);
|
||||
|
@ -1085,17 +1105,23 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
|
|||
}
|
||||
rT.reason += ". ";
|
||||
|
||||
//allow SMBs every 3 minutes
|
||||
var nextBolusMins = round(3-lastBolusAge,1);
|
||||
//allow SMBs every 3 minutes by default
|
||||
var SMBInterval = 3;
|
||||
if (profile.SMBInterval) {
|
||||
// allow SMBIntervals between 1 and 10 minutes
|
||||
SMBInterval = Math.min(10,Math.max(1,profile.SMBInterval));
|
||||
}
|
||||
var nextBolusMins = round(SMBInterval-lastBolusAge,0);
|
||||
var nextBolusSeconds = round((SMBInterval - lastBolusAge) * 60, 0) % 60;
|
||||
//console.error(naive_eventualBG, insulinReq, worstCaseInsulinReq, durationReq);
|
||||
console.error("naive_eventualBG",naive_eventualBG+",",durationReq+"m "+smbLowTempReq+"U/h temp needed; last bolus",lastBolusAge+"m ago; maxBolus: "+maxBolus);
|
||||
if (lastBolusAge > 3) {
|
||||
if (lastBolusAge > SMBInterval) {
|
||||
if (microBolus > 0) {
|
||||
rT.units = microBolus;
|
||||
rT.reason += "Microbolusing " + microBolus + "U. ";
|
||||
}
|
||||
} else {
|
||||
rT.reason += "Waiting " + nextBolusMins + "m to microbolus again. ";
|
||||
rT.reason += "Waiting " + nextBolusMins + "m " + nextBolusSeconds + "s to microbolus again. ";
|
||||
}
|
||||
//rT.reason += ". ";
|
||||
|
||||
|
@ -1106,27 +1132,22 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
|
|||
return rT;
|
||||
}
|
||||
|
||||
// if insulinReq is negative, snoozeBG > target_bg, and lastCOBpredBG > target_bg, set a neutral temp
|
||||
//if (insulinReq < 0 && snoozeBG > target_bg && lastCOBpredBG > target_bg) {
|
||||
//rT.reason += "; SMB bolus snooze: setting current basal of " + basal + " as temp. ";
|
||||
//return tempBasalFunctions.setTempBasal(basal, 30, profile, rT, currenttemp);
|
||||
//}
|
||||
}
|
||||
|
||||
var maxSafeBasal = tempBasalFunctions.getMaxSafeBasal(profile);
|
||||
|
||||
if (rate > maxSafeBasal) {
|
||||
rT.reason += "adj. req. rate: "+rate+" to maxSafeBasal: "+maxSafeBasal+", ";
|
||||
rT.reason += "adj. req. rate: "+round(rate, 2)+" to maxSafeBasal: "+maxSafeBasal+", ";
|
||||
rate = round_basal(maxSafeBasal, profile);
|
||||
}
|
||||
|
||||
var insulinScheduled = currenttemp.duration * (currenttemp.rate - basal) / 60;
|
||||
insulinScheduled = currenttemp.duration * (currenttemp.rate - basal) / 60;
|
||||
if (insulinScheduled >= insulinReq * 2) { // if current temp would deliver >2x more than the required insulin, lower the rate
|
||||
rT.reason += currenttemp.duration + "m@" + (currenttemp.rate).toFixed(2) + " > 2 * insulinReq. Setting temp basal of " + rate + "U/hr. ";
|
||||
return tempBasalFunctions.setTempBasal(rate, 30, profile, rT, currenttemp);
|
||||
}
|
||||
|
||||
if (typeof currenttemp.duration == 'undefined' || currenttemp.duration == 0) { // no temp is set
|
||||
if (typeof currenttemp.duration === 'undefined' || currenttemp.duration === 0) { // no temp is set
|
||||
rT.reason += "no temp, setting " + rate + "U/hr. ";
|
||||
return tempBasalFunctions.setTempBasal(rate, 30, profile, rT, currenttemp);
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
<maxHistory>120</maxHistory>
|
||||
</rollingPolicy>
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %.-1level/%logger: [%class{0}.%M\(\):%line]: %msg%n</pattern>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %.-1level/%logger: %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
|
@ -27,7 +27,7 @@
|
|||
<pattern>%logger{0}</pattern>
|
||||
</tagEncoder>
|
||||
<encoder>
|
||||
<pattern>[%thread] [%class{0}.%M\(\):%line]: %msg%n</pattern>
|
||||
<pattern>[%thread]: %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
|
|
|
@ -1,120 +0,0 @@
|
|||
package com.cozmo.danar.util;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
|
||||
public class BleCommandUtil {
|
||||
public static final int DANAR_PACKET__TYPE_ENCRYPTION_REQUEST = 0x01;
|
||||
public static final int DANAR_PACKET__TYPE_ENCRYPTION_RESPONSE = 0x02;
|
||||
public static final int DANAR_PACKET__TYPE_COMMAND = 0xA1;
|
||||
public static final int DANAR_PACKET__TYPE_RESPONSE = 0xB2;
|
||||
public static final int DANAR_PACKET__TYPE_NOTIFY = 0xC3;
|
||||
|
||||
public static final int DANAR_PACKET__OPCODE_ENCRYPTION__PUMP_CHECK = 0x00;
|
||||
public static final int DANAR_PACKET__OPCODE_ENCRYPTION__CHECK_PASSKEY = 0xD0;
|
||||
public static final int DANAR_PACKET__OPCODE_ENCRYPTION__PASSKEY_REQUEST = 0xD1;
|
||||
public static final int DANAR_PACKET__OPCODE_ENCRYPTION__PASSKEY_RETURN = 0xD2;
|
||||
public static final int DANAR_PACKET__OPCODE_ENCRYPTION__TIME_INFORMATION = 0x01;
|
||||
|
||||
public static final int DANAR_PACKET__OPCODE_NOTIFY__DELIVERY_COMPLETE = 0x01;
|
||||
public static final int DANAR_PACKET__OPCODE_NOTIFY__DELIVERY_RATE_DISPLAY = 0x02;
|
||||
public static final int DANAR_PACKET__OPCODE_NOTIFY__ALARM = 0x03;
|
||||
public static final int DANAR_PACKET__OPCODE_NOTIFY__MISSED_BOLUS_ALARM = 0x04;
|
||||
|
||||
public static final int DANAR_PACKET__OPCODE_REVIEW__INITIAL_SCREEN_INFORMATION = 0x02;
|
||||
public static final int DANAR_PACKET__OPCODE_REVIEW__DELIVERY_STATUS = 0x03;
|
||||
public static final int DANAR_PACKET__OPCODE_REVIEW__GET_PASSWORD = 0x04;
|
||||
|
||||
public static final int DANAR_PACKET__OPCODE_REVIEW__BOLUS_AVG = 0x10;
|
||||
public static final int DANAR_PACKET__OPCODE_REVIEW__BOLUS = 0x11;
|
||||
public static final int DANAR_PACKET__OPCODE_REVIEW__DAILY = 0x12;
|
||||
public static final int DANAR_PACKET__OPCODE_REVIEW__PRIME = 0x13;
|
||||
public static final int DANAR_PACKET__OPCODE_REVIEW__REFILL = 0x14;
|
||||
public static final int DANAR_PACKET__OPCODE_REVIEW__BLOOD_GLUCOSE = 0x15;
|
||||
public static final int DANAR_PACKET__OPCODE_REVIEW__CARBOHYDRATE = 0x16;
|
||||
public static final int DANAR_PACKET__OPCODE_REVIEW__TEMPORARY = 0x17;
|
||||
public static final int DANAR_PACKET__OPCODE_REVIEW__SUSPEND = 0x18;
|
||||
public static final int DANAR_PACKET__OPCODE_REVIEW__ALARM = 0x19;
|
||||
public static final int DANAR_PACKET__OPCODE_REVIEW__BASAL = 0x1A;
|
||||
public static final int DANAR_PACKET__OPCODE_REVIEW__ALL_HISTORY = 0x1F;
|
||||
public static final int DANAR_PACKET__OPCODE_REVIEW__GET_SHIPPING_INFORMATION = 0x20;
|
||||
public static final int DANAR_PACKET__OPCODE_REVIEW__GET_PUMP_CHECK = 0x21;
|
||||
public static final int DANAR_PACKET__OPCODE_REVIEW__GET_USER_TIME_CHANGE_FLAG = 0x22;
|
||||
public static final int DANAR_PACKET__OPCODE_REVIEW__SET_USER_TIME_CHANGE_FLAG_CLEAR = 0x23;
|
||||
public static final int DANAR_PACKET__OPCODE_REVIEW__GET_MORE_INFORMATION = 0x24;
|
||||
public static final int DANAR_PACKET__OPCODE_REVIEW__SET_HISTORY_UPLOAD_MODE = 0x25;
|
||||
public static final int DANAR_PACKET__OPCODE_REVIEW__GET_TODAY_DELIVERY_TOTAL = 0x26;
|
||||
|
||||
public static final int DANAR_PACKET__OPCODE_BOLUS__GET_STEP_BOLUS_INFORMATION = 0x40;
|
||||
public static final int DANAR_PACKET__OPCODE_BOLUS__GET_EXTENDED_BOLUS_STATE = 0x41;
|
||||
public static final int DANAR_PACKET__OPCODE_BOLUS__GET_EXTENDED_BOLUS = 0x42;
|
||||
public static final int DANAR_PACKET__OPCODE_BOLUS__GET_DUAL_BOLUS = 0x43;
|
||||
public static final int DANAR_PACKET__OPCODE_BOLUS__SET_STEP_BOLUS_STOP = 0x44;
|
||||
public static final int DANAR_PACKET__OPCODE_BOLUS__GET_CARBOHYDRATE_CALCULATION_INFORMATION = 0x45;
|
||||
public static final int DANAR_PACKET__OPCODE_BOLUS__GET_EXTENDED_MENU_OPTION_STATE = 0x46;
|
||||
public static final int DANAR_PACKET__OPCODE_BOLUS__SET_EXTENDED_BOLUS = 0x47;
|
||||
public static final int DANAR_PACKET__OPCODE_BOLUS__SET_DUAL_BOLUS = 0x48;
|
||||
public static final int DANAR_PACKET__OPCODE_BOLUS__SET_EXTENDED_BOLUS_CANCEL = 0x49;
|
||||
public static final int DANAR_PACKET__OPCODE_BOLUS__SET_STEP_BOLUS_START = 0x4A;
|
||||
public static final int DANAR_PACKET__OPCODE_BOLUS__GET_CALCULATION_INFORMATION = 0x4B;
|
||||
public static final int DANAR_PACKET__OPCODE_BOLUS__GET_BOLUS_RATE = 0x4C;
|
||||
public static final int DANAR_PACKET__OPCODE_BOLUS__SET_BOLUS_RATE = 0x4D;
|
||||
public static final int DANAR_PACKET__OPCODE_BOLUS__GET_CIR_CF_ARRAY = 0x4E;
|
||||
public static final int DANAR_PACKET__OPCODE_BOLUS__SET_CIR_CF_ARRAY = 0x4F;
|
||||
public static final int DANAR_PACKET__OPCODE_BOLUS__GET_BOLUS_OPTION = 0x50;
|
||||
public static final int DANAR_PACKET__OPCODE_BOLUS__SET_BOLUS_OPTION = 0x51;
|
||||
|
||||
public static final int DANAR_PACKET__OPCODE_BASAL__SET_TEMPORARY_BASAL = 0x60;
|
||||
public static final int DANAR_PACKET__OPCODE_BASAL__TEMPORARY_BASAL_STATE = 0x61;
|
||||
public static final int DANAR_PACKET__OPCODE_BASAL__CANCEL_TEMPORARY_BASAL = 0x62;
|
||||
public static final int DANAR_PACKET__OPCODE_BASAL__GET_PROFILE_NUMBER = 0x63;
|
||||
public static final int DANAR_PACKET__OPCODE_BASAL__SET_PROFILE_NUMBER = 0x64;
|
||||
public static final int DANAR_PACKET__OPCODE_BASAL__GET_PROFILE_BASAL_RATE = 0x65;
|
||||
public static final int DANAR_PACKET__OPCODE_BASAL__SET_PROFILE_BASAL_RATE = 0x66;
|
||||
public static final int DANAR_PACKET__OPCODE_BASAL__GET_BASAL_RATE = 0x67;
|
||||
public static final int DANAR_PACKET__OPCODE_BASAL__SET_BASAL_RATE = 0x68;
|
||||
public static final int DANAR_PACKET__OPCODE_BASAL__SET_SUSPEND_ON = 0x69;
|
||||
public static final int DANAR_PACKET__OPCODE_BASAL__SET_SUSPEND_OFF = 0x6A;
|
||||
|
||||
public static final int DANAR_PACKET__OPCODE_OPTION__GET_PUMP_TIME = 0x70;
|
||||
public static final int DANAR_PACKET__OPCODE_OPTION__SET_PUMP_TIME = 0x71;
|
||||
public static final int DANAR_PACKET__OPCODE_OPTION__GET_USER_OPTION = 0x72;
|
||||
public static final int DANAR_PACKET__OPCODE_OPTION__SET_USER_OPTION = 0x73;
|
||||
|
||||
public static final int DANAR_PACKET__OPCODE_BASAL__APS_SET_TEMPORARY_BASAL = 0xC1;
|
||||
public static final int DANAR_PACKET__OPCODE__APS_HISTORY_EVENTS = 0xC2;
|
||||
public static final int DANAR_PACKET__OPCODE__APS_SET_EVENT_HISTORY = 0xC3;
|
||||
|
||||
public static final int DANAR_PACKET__OPCODE_ETC__SET_HISTORY_SAVE = 0xE0;
|
||||
public static final int DANAR_PACKET__OPCODE_ETC__KEEP_CONNECTION = 0xFF;
|
||||
|
||||
static {
|
||||
System.loadLibrary("BleCommandUtil");
|
||||
}
|
||||
|
||||
private static native byte[] getEncryptedPacketJni(Object context, int opcode, byte[] bytes, String deviceName);
|
||||
|
||||
private static native byte[] getDecryptedPacketJni(Object context, byte[] bytes);
|
||||
|
||||
// ---------------------------------------------------------
|
||||
|
||||
private static BleCommandUtil mInstance = null;
|
||||
|
||||
public static BleCommandUtil getInstance() {
|
||||
if (mInstance == null) {
|
||||
mInstance = new BleCommandUtil();
|
||||
}
|
||||
return mInstance;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------
|
||||
|
||||
public byte[] getEncryptedPacket(int opcode, byte[] bytes, String deviceName) {
|
||||
return getEncryptedPacketJni(MainApp.instance().getApplicationContext(), opcode, bytes, deviceName);
|
||||
}
|
||||
|
||||
public byte[] getDecryptedPacket(byte[] bytes) {
|
||||
return getDecryptedPacketJni(MainApp.instance().getApplicationContext(), bytes);
|
||||
}
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
package info.nightscout.androidaps;
|
||||
|
||||
/**
|
||||
* Created by mike on 07.06.2016.
|
||||
*/
|
||||
public class Config {
|
||||
public static int SUPPORTEDNSVERSION = 1002; // 0.10.00
|
||||
|
||||
public static final boolean APS = BuildConfig.FLAVOR.equals("full");
|
||||
|
||||
public static final boolean NSCLIENT = BuildConfig.FLAVOR.equals("nsclient") || BuildConfig.FLAVOR.equals("nsclient2");
|
||||
public static final boolean PUMPCONTROL = BuildConfig.FLAVOR.equals("pumpcontrol");
|
||||
|
||||
public static final boolean PUMPDRIVERS = BuildConfig.FLAVOR.equals("full") || BuildConfig.FLAVOR.equals("pumpcontrol");
|
||||
}
|
15
app/src/main/java/info/nightscout/androidaps/Config.kt
Normal file
15
app/src/main/java/info/nightscout/androidaps/Config.kt
Normal file
|
@ -0,0 +1,15 @@
|
|||
package info.nightscout.androidaps
|
||||
|
||||
import info.nightscout.androidaps.interfaces.ConfigInterface
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class Config @Inject constructor(): ConfigInterface{
|
||||
|
||||
override val SUPPORTEDNSVERSION = 1002 // 0.10.00
|
||||
override val APS = BuildConfig.FLAVOR == "full"
|
||||
override val NSCLIENT = BuildConfig.FLAVOR == "nsclient" || BuildConfig.FLAVOR == "nsclient2"
|
||||
override val PUMPCONTROL = BuildConfig.FLAVOR == "pumpcontrol"
|
||||
override val PUMPDRIVERS = BuildConfig.FLAVOR == "full" || BuildConfig.FLAVOR == "pumpcontrol"
|
||||
}
|
|
@ -1,345 +0,0 @@
|
|||
package info.nightscout.androidaps;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Bundle;
|
||||
import android.os.PersistableBundle;
|
||||
import android.text.SpannableString;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.text.util.Linkify;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.EditText;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.ActionBarDrawerToggle;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.drawerlayout.widget.DrawerLayout;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
|
||||
import com.google.android.material.navigation.NavigationView;
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
import com.joanzapata.iconify.Iconify;
|
||||
import com.joanzapata.iconify.fonts.FontAwesomeModule;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import info.nightscout.androidaps.activities.HistoryBrowseActivity;
|
||||
import info.nightscout.androidaps.activities.NoSplashAppCompatActivity;
|
||||
import info.nightscout.androidaps.activities.PreferencesActivity;
|
||||
import info.nightscout.androidaps.activities.SingleFragmentActivity;
|
||||
import info.nightscout.androidaps.activities.StatsActivity;
|
||||
import info.nightscout.androidaps.events.EventAppExit;
|
||||
import info.nightscout.androidaps.events.EventPreferenceChange;
|
||||
import info.nightscout.androidaps.events.EventRebuildTabs;
|
||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||
import info.nightscout.androidaps.interfaces.PluginType;
|
||||
import info.nightscout.androidaps.logging.L;
|
||||
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin;
|
||||
import info.nightscout.androidaps.plugins.bus.RxBus;
|
||||
import info.nightscout.androidaps.plugins.constraints.versionChecker.VersionCheckerUtilsKt;
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.data.NSSettingsStatus;
|
||||
import info.nightscout.androidaps.setupwizard.SetupWizardActivity;
|
||||
import info.nightscout.androidaps.tabs.TabPageAdapter;
|
||||
import info.nightscout.androidaps.utils.AndroidPermission;
|
||||
import info.nightscout.androidaps.utils.FabricPrivacy;
|
||||
import info.nightscout.androidaps.utils.LocaleHelper;
|
||||
import info.nightscout.androidaps.utils.OKDialog;
|
||||
import info.nightscout.androidaps.utils.PasswordProtection;
|
||||
import info.nightscout.androidaps.utils.SP;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.disposables.CompositeDisposable;
|
||||
|
||||
import static info.nightscout.androidaps.utils.EspressoTestHelperKt.isRunningRealPumpTest;
|
||||
|
||||
public class MainActivity extends NoSplashAppCompatActivity {
|
||||
private static Logger log = LoggerFactory.getLogger(L.CORE);
|
||||
private CompositeDisposable disposable = new CompositeDisposable();
|
||||
|
||||
private ActionBarDrawerToggle actionBarDrawerToggle;
|
||||
|
||||
private MenuItem pluginPreferencesMenuItem;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
Iconify.with(new FontAwesomeModule());
|
||||
LocaleHelper.INSTANCE.update(getApplicationContext());
|
||||
|
||||
setContentView(R.layout.activity_main);
|
||||
setSupportActionBar(findViewById(R.id.toolbar));
|
||||
getSupportActionBar().setDisplayShowTitleEnabled(false);
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
getSupportActionBar().setHomeButtonEnabled(true);
|
||||
|
||||
DrawerLayout drawerLayout = findViewById(R.id.drawer_layout);
|
||||
actionBarDrawerToggle = new ActionBarDrawerToggle(this, drawerLayout, R.string.open_navigation, R.string.close_navigation);
|
||||
drawerLayout.addDrawerListener(actionBarDrawerToggle);
|
||||
actionBarDrawerToggle.syncState();
|
||||
|
||||
// initialize screen wake lock
|
||||
processPreferenceChange(new EventPreferenceChange(R.string.key_keep_screen_on));
|
||||
|
||||
final ViewPager viewPager = findViewById(R.id.pager);
|
||||
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
|
||||
@Override
|
||||
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageSelected(int position) {
|
||||
checkPluginPreferences(viewPager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScrollStateChanged(int state) {
|
||||
}
|
||||
});
|
||||
|
||||
//Check here if loop plugin is disabled. Else check via constraints
|
||||
if (!LoopPlugin.getPlugin().isEnabled(PluginType.LOOP))
|
||||
VersionCheckerUtilsKt.triggerCheckVersion();
|
||||
|
||||
FabricPrivacy.setUserStats();
|
||||
|
||||
setupTabs();
|
||||
setupViews();
|
||||
|
||||
disposable.add(RxBus.INSTANCE
|
||||
.toObservable(EventRebuildTabs.class)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(event -> {
|
||||
LocaleHelper.INSTANCE.update(getApplicationContext());
|
||||
if (event.getRecreate()) {
|
||||
recreate();
|
||||
} else {
|
||||
setupTabs();
|
||||
setupViews();
|
||||
}
|
||||
setWakeLock();
|
||||
}, FabricPrivacy::logException)
|
||||
);
|
||||
disposable.add(RxBus.INSTANCE
|
||||
.toObservable(EventPreferenceChange.class)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(this::processPreferenceChange, FabricPrivacy::logException)
|
||||
);
|
||||
|
||||
if (!SP.getBoolean(R.string.key_setupwizard_processed, false) && !isRunningRealPumpTest()) {
|
||||
Intent intent = new Intent(this, SetupWizardActivity.class);
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
AndroidPermission.notifyForStoragePermission(this);
|
||||
AndroidPermission.notifyForBatteryOptimizationPermission(this);
|
||||
if (Config.PUMPDRIVERS) {
|
||||
AndroidPermission.notifyForLocationPermissions(this);
|
||||
AndroidPermission.notifyForSMSPermissions(this);
|
||||
AndroidPermission.notifyForSystemWindowPermissions(this);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkPluginPreferences(ViewPager viewPager) {
|
||||
if (pluginPreferencesMenuItem == null) return;
|
||||
if (((TabPageAdapter) viewPager.getAdapter()).getPluginAt(viewPager.getCurrentItem()).getPreferencesId() != -1)
|
||||
pluginPreferencesMenuItem.setEnabled(true);
|
||||
else pluginPreferencesMenuItem.setEnabled(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPostCreate(@Nullable Bundle savedInstanceState, @Nullable PersistableBundle persistentState) {
|
||||
super.onPostCreate(savedInstanceState, persistentState);
|
||||
actionBarDrawerToggle.syncState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
disposable.clear();
|
||||
}
|
||||
|
||||
private void setWakeLock() {
|
||||
boolean keepScreenOn = SP.getBoolean(R.string.key_keep_screen_on, false);
|
||||
if (keepScreenOn)
|
||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
else
|
||||
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
}
|
||||
|
||||
public void processPreferenceChange(final EventPreferenceChange ev) {
|
||||
if (ev.isChanged(R.string.key_keep_screen_on))
|
||||
setWakeLock();
|
||||
}
|
||||
|
||||
private void setupViews() {
|
||||
TabPageAdapter pageAdapter = new TabPageAdapter(getSupportFragmentManager(), this);
|
||||
NavigationView navigationView = findViewById(R.id.navigation_view);
|
||||
navigationView.setNavigationItemSelectedListener(menuItem -> true);
|
||||
Menu menu = navigationView.getMenu();
|
||||
menu.clear();
|
||||
for (PluginBase p : MainApp.getPluginsList()) {
|
||||
pageAdapter.registerNewFragment(p);
|
||||
if (p.hasFragment() && !p.isFragmentVisible() && p.isEnabled(p.pluginDescription.getType()) && !p.pluginDescription.neverVisible) {
|
||||
MenuItem menuItem = menu.add(p.getName());
|
||||
menuItem.setCheckable(true);
|
||||
menuItem.setOnMenuItemClickListener(item -> {
|
||||
Intent intent = new Intent(this, SingleFragmentActivity.class);
|
||||
intent.putExtra("plugin", MainApp.getPluginsList().indexOf(p));
|
||||
startActivity(intent);
|
||||
((DrawerLayout) findViewById(R.id.drawer_layout)).closeDrawers();
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
ViewPager mPager = findViewById(R.id.pager);
|
||||
mPager.setAdapter(pageAdapter);
|
||||
//if (switchToLast)
|
||||
// mPager.setCurrentItem(pageAdapter.getCount() - 1, false);
|
||||
checkPluginPreferences(mPager);
|
||||
}
|
||||
|
||||
private void setupTabs() {
|
||||
ViewPager viewPager = findViewById(R.id.pager);
|
||||
TabLayout normalTabs = findViewById(R.id.tabs_normal);
|
||||
normalTabs.setupWithViewPager(viewPager, true);
|
||||
TabLayout compactTabs = findViewById(R.id.tabs_compact);
|
||||
compactTabs.setupWithViewPager(viewPager, true);
|
||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||
if (SP.getBoolean("short_tabtitles", false)) {
|
||||
normalTabs.setVisibility(View.GONE);
|
||||
compactTabs.setVisibility(View.VISIBLE);
|
||||
toolbar.setLayoutParams(new LinearLayout.LayoutParams(Toolbar.LayoutParams.MATCH_PARENT, (int) getResources().getDimension(R.dimen.compact_height)));
|
||||
} else {
|
||||
normalTabs.setVisibility(View.VISIBLE);
|
||||
compactTabs.setVisibility(View.GONE);
|
||||
TypedValue typedValue = new TypedValue();
|
||||
if (getTheme().resolveAttribute(R.attr.actionBarSize, typedValue, true)) {
|
||||
toolbar.setLayoutParams(new LinearLayout.LayoutParams(Toolbar.LayoutParams.MATCH_PARENT,
|
||||
TypedValue.complexToDimensionPixelSize(typedValue.data, getResources().getDisplayMetrics())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
if (permissions.length != 0) {
|
||||
if (ActivityCompat.checkSelfPermission(this, permissions[0]) == PackageManager.PERMISSION_GRANTED) {
|
||||
switch (requestCode) {
|
||||
case AndroidPermission.CASE_STORAGE:
|
||||
//show dialog after permission is granted
|
||||
OKDialog.show(this, "", MainApp.gs(R.string.alert_dialog_storage_permission_text));
|
||||
break;
|
||||
case AndroidPermission.CASE_LOCATION:
|
||||
case AndroidPermission.CASE_SMS:
|
||||
case AndroidPermission.CASE_BATTERY:
|
||||
case AndroidPermission.CASE_PHONE_STATE:
|
||||
case AndroidPermission.CASE_SYSTEM_WINDOW:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchTouchEvent(MotionEvent event) {
|
||||
if (event.getAction() == MotionEvent.ACTION_DOWN) {
|
||||
View v = getCurrentFocus();
|
||||
if (v instanceof EditText) {
|
||||
Rect outRect = new Rect();
|
||||
v.getGlobalVisibleRect(outRect);
|
||||
if (!outRect.contains((int) event.getRawX(), (int) event.getRawY())) {
|
||||
v.clearFocus();
|
||||
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.dispatchTouchEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.menu_main, menu);
|
||||
pluginPreferencesMenuItem = menu.findItem(R.id.nav_plugin_preferences);
|
||||
checkPluginPreferences(findViewById(R.id.pager));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
int id = item.getItemId();
|
||||
switch (id) {
|
||||
case R.id.nav_preferences:
|
||||
PasswordProtection.QueryPassword(this, R.string.settings_password, "settings_password", () -> {
|
||||
Intent i = new Intent(this, PreferencesActivity.class);
|
||||
i.putExtra("id", -1);
|
||||
startActivity(i);
|
||||
}, null);
|
||||
return true;
|
||||
case R.id.nav_historybrowser:
|
||||
startActivity(new Intent(this, HistoryBrowseActivity.class));
|
||||
return true;
|
||||
case R.id.nav_setupwizard:
|
||||
startActivity(new Intent(this, SetupWizardActivity.class));
|
||||
return true;
|
||||
case R.id.nav_about:
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setTitle(MainApp.gs(R.string.app_name) + " " + BuildConfig.VERSION);
|
||||
builder.setIcon(MainApp.getIcon());
|
||||
String message = "Build: " + BuildConfig.BUILDVERSION + "\n";
|
||||
message += "Flavor: " + BuildConfig.FLAVOR + BuildConfig.BUILD_TYPE + "\n";
|
||||
message += MainApp.gs(R.string.configbuilder_nightscoutversion_label) + " " + NSSettingsStatus.getInstance().nightscoutVersionName;
|
||||
if (MainApp.engineeringMode)
|
||||
message += "\n" + MainApp.gs(R.string.engineering_mode_enabled);
|
||||
message += MainApp.gs(R.string.about_link_urls);
|
||||
final SpannableString messageSpanned = new SpannableString(message);
|
||||
Linkify.addLinks(messageSpanned, Linkify.WEB_URLS);
|
||||
builder.setMessage(messageSpanned);
|
||||
builder.setPositiveButton(MainApp.gs(R.string.ok), null);
|
||||
AlertDialog alertDialog = builder.create();
|
||||
alertDialog.show();
|
||||
((TextView) alertDialog.findViewById(android.R.id.message)).setMovementMethod(LinkMovementMethod.getInstance());
|
||||
return true;
|
||||
case R.id.nav_exit:
|
||||
log.debug("Exiting");
|
||||
RxBus.INSTANCE.send(new EventAppExit());
|
||||
finish();
|
||||
System.runFinalization();
|
||||
System.exit(0);
|
||||
return true;
|
||||
case R.id.nav_plugin_preferences:
|
||||
ViewPager viewPager = findViewById(R.id.pager);
|
||||
final PluginBase plugin = ((TabPageAdapter) viewPager.getAdapter()).getPluginAt(viewPager.getCurrentItem());
|
||||
PasswordProtection.QueryPassword(this, R.string.settings_password, "settings_password", () -> {
|
||||
Intent i = new Intent(this, PreferencesActivity.class);
|
||||
i.putExtra("id", plugin.getPreferencesId());
|
||||
startActivity(i);
|
||||
}, null);
|
||||
return true;
|
||||
/*
|
||||
case R.id.nav_survey:
|
||||
startActivity(new Intent(this, SurveyActivity.class));
|
||||
return true;
|
||||
*/
|
||||
case R.id.nav_stats:
|
||||
startActivity(new Intent(this, StatsActivity.class));
|
||||
return true;
|
||||
}
|
||||
return actionBarDrawerToggle.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
371
app/src/main/java/info/nightscout/androidaps/MainActivity.kt
Normal file
371
app/src/main/java/info/nightscout/androidaps/MainActivity.kt
Normal file
|
@ -0,0 +1,371 @@
|
|||
package info.nightscout.androidaps
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.graphics.Rect
|
||||
import android.os.Bundle
|
||||
import android.os.PersistableBundle
|
||||
import android.text.SpannableString
|
||||
import android.text.method.LinkMovementMethod
|
||||
import android.text.util.Linkify
|
||||
import android.util.TypedValue
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.view.WindowManager
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import android.widget.EditText
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.ActionBarDrawerToggle
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.viewpager2.widget.ViewPager2
|
||||
import com.google.android.material.tabs.TabLayoutMediator
|
||||
import com.joanzapata.iconify.Iconify
|
||||
import com.joanzapata.iconify.fonts.FontAwesomeModule
|
||||
import info.nightscout.androidaps.activities.ProfileHelperActivity
|
||||
import info.nightscout.androidaps.activities.NoSplashAppCompatActivity
|
||||
import info.nightscout.androidaps.activities.PreferencesActivity
|
||||
import info.nightscout.androidaps.activities.SingleFragmentActivity
|
||||
import info.nightscout.androidaps.activities.StatsActivity
|
||||
import info.nightscout.androidaps.events.EventAppExit
|
||||
import info.nightscout.androidaps.events.EventPreferenceChange
|
||||
import info.nightscout.androidaps.events.EventRebuildTabs
|
||||
import info.nightscout.androidaps.historyBrowser.HistoryBrowseActivity
|
||||
import info.nightscout.androidaps.interfaces.ActivePluginProvider
|
||||
import info.nightscout.androidaps.interfaces.PluginType
|
||||
import info.nightscout.androidaps.logging.AAPSLogger
|
||||
import info.nightscout.androidaps.logging.LTag
|
||||
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin
|
||||
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
||||
import info.nightscout.androidaps.plugins.constraints.signatureVerifier.SignatureVerifierPlugin
|
||||
import info.nightscout.androidaps.plugins.constraints.versionChecker.VersionCheckerUtils
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.data.NSSettingsStatus
|
||||
import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin
|
||||
import info.nightscout.androidaps.setupwizard.SetupWizardActivity
|
||||
import info.nightscout.androidaps.utils.AndroidPermission
|
||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
||||
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
|
||||
import info.nightscout.androidaps.utils.extensions.isRunningRealPumpTest
|
||||
import info.nightscout.androidaps.utils.locale.LocaleHelper
|
||||
import info.nightscout.androidaps.utils.protection.ProtectionCheck
|
||||
import info.nightscout.androidaps.utils.resources.IconsProvider
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
||||
import info.nightscout.androidaps.utils.tabs.TabPageAdapter
|
||||
import info.nightscout.androidaps.utils.ui.UIRunnable
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import kotlinx.android.synthetic.main.activity_main.*
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
class MainActivity : NoSplashAppCompatActivity() {
|
||||
private val disposable = CompositeDisposable()
|
||||
|
||||
@Inject lateinit var aapsLogger: AAPSLogger
|
||||
@Inject lateinit var rxBus: RxBusWrapper
|
||||
@Inject lateinit var androidPermission: AndroidPermission
|
||||
@Inject lateinit var sp: SP
|
||||
@Inject lateinit var resourceHelper: ResourceHelper
|
||||
@Inject lateinit var versionCheckerUtils: VersionCheckerUtils
|
||||
@Inject lateinit var smsCommunicatorPlugin: SmsCommunicatorPlugin
|
||||
@Inject lateinit var loopPlugin: LoopPlugin
|
||||
@Inject lateinit var nsSettingsStatus: NSSettingsStatus
|
||||
@Inject lateinit var buildHelper: BuildHelper
|
||||
@Inject lateinit var activePlugin: ActivePluginProvider
|
||||
@Inject lateinit var fabricPrivacy: FabricPrivacy
|
||||
@Inject lateinit var protectionCheck: ProtectionCheck
|
||||
@Inject lateinit var iconsProvider: IconsProvider
|
||||
@Inject lateinit var constraintChecker: ConstraintChecker
|
||||
@Inject lateinit var signatureVerifierPlugin: SignatureVerifierPlugin
|
||||
@Inject lateinit var config: Config
|
||||
|
||||
private lateinit var actionBarDrawerToggle: ActionBarDrawerToggle
|
||||
private var pluginPreferencesMenuItem: MenuItem? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
Iconify.with(FontAwesomeModule())
|
||||
LocaleHelper.update(applicationContext)
|
||||
setContentView(R.layout.activity_main)
|
||||
setSupportActionBar(toolbar)
|
||||
supportActionBar?.setDisplayShowTitleEnabled(false)
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
supportActionBar?.setHomeButtonEnabled(true)
|
||||
actionBarDrawerToggle = ActionBarDrawerToggle(this, main_drawer_layout, R.string.open_navigation, R.string.close_navigation).also {
|
||||
main_drawer_layout.addDrawerListener(it)
|
||||
it.syncState()
|
||||
}
|
||||
|
||||
// initialize screen wake lock
|
||||
processPreferenceChange(EventPreferenceChange(resourceHelper.gs(R.string.key_keep_screen_on)))
|
||||
main_pager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
|
||||
override fun onPageScrollStateChanged(state: Int) {}
|
||||
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}
|
||||
override fun onPageSelected(position: Int) {
|
||||
checkPluginPreferences(main_pager)
|
||||
}
|
||||
})
|
||||
|
||||
//Check here if loop plugin is disabled. Else check via constraints
|
||||
if (!loopPlugin.isEnabled(PluginType.LOOP)) versionCheckerUtils.triggerCheckVersion()
|
||||
setUserStats()
|
||||
setupViews()
|
||||
disposable.add(rxBus
|
||||
.toObservable(EventRebuildTabs::class.java)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({
|
||||
if (it.recreate) recreate()
|
||||
else setupViews()
|
||||
setWakeLock()
|
||||
}) { fabricPrivacy::logException }
|
||||
)
|
||||
disposable.add(rxBus
|
||||
.toObservable(EventPreferenceChange::class.java)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({ processPreferenceChange(it) }) { fabricPrivacy::logException }
|
||||
)
|
||||
if (!sp.getBoolean(R.string.key_setupwizard_processed, false) && !isRunningRealPumpTest()) {
|
||||
val intent = Intent(this, SetupWizardActivity::class.java)
|
||||
startActivity(intent)
|
||||
}
|
||||
androidPermission.notifyForStoragePermission(this)
|
||||
androidPermission.notifyForBatteryOptimizationPermission(this)
|
||||
androidPermission.notifyForLocationPermissions(this)
|
||||
if (config.PUMPDRIVERS) {
|
||||
androidPermission.notifyForSMSPermissions(this, smsCommunicatorPlugin)
|
||||
androidPermission.notifyForSystemWindowPermissions(this)
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkPluginPreferences(viewPager: ViewPager2) {
|
||||
if (viewPager.currentItem >= 0) pluginPreferencesMenuItem?.isEnabled = (viewPager.adapter as TabPageAdapter).getPluginAt(viewPager.currentItem).preferencesId != -1
|
||||
}
|
||||
|
||||
override fun onPostCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
|
||||
super.onPostCreate(savedInstanceState, persistentState)
|
||||
actionBarDrawerToggle.syncState()
|
||||
}
|
||||
|
||||
public override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
disposable.clear()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
protectionCheck.queryProtection(this, ProtectionCheck.Protection.APPLICATION, null,
|
||||
UIRunnable(Runnable { OKDialog.show(this, "", resourceHelper.gs(R.string.authorizationfailed), Runnable { finish() }) }),
|
||||
UIRunnable(Runnable { OKDialog.show(this, "", resourceHelper.gs(R.string.authorizationfailed), Runnable { finish() }) })
|
||||
)
|
||||
}
|
||||
|
||||
private fun setWakeLock() {
|
||||
val keepScreenOn = sp.getBoolean(R.string.key_keep_screen_on, false)
|
||||
if (keepScreenOn) window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) else window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||
}
|
||||
|
||||
private fun processPreferenceChange(ev: EventPreferenceChange) {
|
||||
if (ev.isChanged(resourceHelper, R.string.key_keep_screen_on)) setWakeLock()
|
||||
if (ev.isChanged(resourceHelper, R.string.key_skin)) recreate()
|
||||
}
|
||||
|
||||
private fun setupViews() {
|
||||
// Menu
|
||||
val pageAdapter = TabPageAdapter(this)
|
||||
main_navigation_view.setNavigationItemSelectedListener { true }
|
||||
val menu = main_navigation_view.menu.also { it.clear() }
|
||||
for (p in activePlugin.pluginsList) {
|
||||
pageAdapter.registerNewFragment(p)
|
||||
if (p.isEnabled() && p.hasFragment() && !p.isFragmentVisible() && !p.pluginDescription.neverVisible) {
|
||||
val menuItem = menu.add(p.name)
|
||||
menuItem.isCheckable = true
|
||||
menuItem.setOnMenuItemClickListener {
|
||||
val intent = Intent(this, SingleFragmentActivity::class.java)
|
||||
intent.putExtra("plugin", activePlugin.pluginsList.indexOf(p))
|
||||
startActivity(intent)
|
||||
main_drawer_layout.closeDrawers()
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
main_pager.adapter = pageAdapter
|
||||
main_pager.offscreenPageLimit = 8 // This may cause more memory consumption
|
||||
checkPluginPreferences(main_pager)
|
||||
|
||||
// Tabs
|
||||
if (sp.getBoolean(R.string.key_short_tabtitles, false)) {
|
||||
tabs_normal.visibility = View.GONE
|
||||
tabs_compact.visibility = View.VISIBLE
|
||||
toolbar.layoutParams = LinearLayout.LayoutParams(Toolbar.LayoutParams.MATCH_PARENT, resources.getDimension(R.dimen.compact_height).toInt())
|
||||
TabLayoutMediator(tabs_compact, main_pager) { tab, position ->
|
||||
tab.text = (main_pager.adapter as TabPageAdapter).getPluginAt(position).nameShort
|
||||
}.attach()
|
||||
} else {
|
||||
tabs_normal.visibility = View.VISIBLE
|
||||
tabs_compact.visibility = View.GONE
|
||||
val typedValue = TypedValue()
|
||||
if (theme.resolveAttribute(R.attr.actionBarSize, typedValue, true)) {
|
||||
toolbar.layoutParams = LinearLayout.LayoutParams(Toolbar.LayoutParams.MATCH_PARENT,
|
||||
TypedValue.complexToDimensionPixelSize(typedValue.data, resources.displayMetrics))
|
||||
}
|
||||
TabLayoutMediator(tabs_normal, main_pager) { tab, position ->
|
||||
tab.text = (main_pager.adapter as TabPageAdapter).getPluginAt(position).name
|
||||
}.attach()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||
if (permissions.isNotEmpty()) {
|
||||
if (ActivityCompat.checkSelfPermission(this, permissions[0]) == PackageManager.PERMISSION_GRANTED) {
|
||||
when (requestCode) {
|
||||
AndroidPermission.CASE_STORAGE -> //show dialog after permission is granted
|
||||
OKDialog.show(this, "", resourceHelper.gs(R.string.alert_dialog_storage_permission_text))
|
||||
|
||||
AndroidPermission.CASE_LOCATION, AndroidPermission.CASE_SMS, AndroidPermission.CASE_BATTERY, AndroidPermission.CASE_PHONE_STATE, AndroidPermission.CASE_SYSTEM_WINDOW -> {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun dispatchTouchEvent(event: MotionEvent): Boolean {
|
||||
if (event.action == MotionEvent.ACTION_DOWN) {
|
||||
val v = currentFocus
|
||||
if (v is EditText) {
|
||||
val outRect = Rect()
|
||||
v.getGlobalVisibleRect(outRect)
|
||||
if (!outRect.contains(event.rawX.toInt(), event.rawY.toInt())) {
|
||||
v.clearFocus()
|
||||
val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
|
||||
imm.hideSoftInputFromWindow(v.getWindowToken(), 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.dispatchTouchEvent(event)
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
menuInflater.inflate(R.menu.menu_main, menu)
|
||||
pluginPreferencesMenuItem = menu.findItem(R.id.nav_plugin_preferences)
|
||||
checkPluginPreferences(main_pager)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
when (item.itemId) {
|
||||
R.id.nav_preferences -> {
|
||||
protectionCheck.queryProtection(this, ProtectionCheck.Protection.PREFERENCES, Runnable {
|
||||
val i = Intent(this, PreferencesActivity::class.java)
|
||||
i.putExtra("id", -1)
|
||||
startActivity(i)
|
||||
})
|
||||
return true
|
||||
}
|
||||
|
||||
R.id.nav_historybrowser -> {
|
||||
startActivity(Intent(this, HistoryBrowseActivity::class.java))
|
||||
return true
|
||||
}
|
||||
|
||||
R.id.nav_setupwizard -> {
|
||||
startActivity(Intent(this, SetupWizardActivity::class.java))
|
||||
return true
|
||||
}
|
||||
|
||||
R.id.nav_about -> {
|
||||
var message = "Build: ${BuildConfig.BUILDVERSION}\n"
|
||||
message += "Flavor: ${BuildConfig.FLAVOR}${BuildConfig.BUILD_TYPE}\n"
|
||||
message += "${resourceHelper.gs(R.string.configbuilder_nightscoutversion_label)} ${nsSettingsStatus.nightscoutVersionName}"
|
||||
if (buildHelper.isEngineeringMode()) message += "\n${resourceHelper.gs(R.string.engineering_mode_enabled)}"
|
||||
message += resourceHelper.gs(R.string.about_link_urls)
|
||||
val messageSpanned = SpannableString(message)
|
||||
Linkify.addLinks(messageSpanned, Linkify.WEB_URLS)
|
||||
AlertDialog.Builder(this)
|
||||
.setTitle(resourceHelper.gs(R.string.app_name) + " " + BuildConfig.VERSION)
|
||||
.setIcon(iconsProvider.getIcon())
|
||||
.setMessage(messageSpanned)
|
||||
.setPositiveButton(resourceHelper.gs(R.string.ok), null)
|
||||
.create().also {
|
||||
it.show()
|
||||
(it.findViewById<View>(android.R.id.message) as TextView).movementMethod = LinkMovementMethod.getInstance()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
R.id.nav_exit -> {
|
||||
aapsLogger.debug(LTag.CORE, "Exiting")
|
||||
rxBus.send(EventAppExit())
|
||||
finish()
|
||||
System.runFinalization()
|
||||
exitProcess(0)
|
||||
}
|
||||
|
||||
R.id.nav_plugin_preferences -> {
|
||||
val plugin = (main_pager.adapter as TabPageAdapter).getPluginAt(main_pager.currentItem)
|
||||
protectionCheck.queryProtection(this, ProtectionCheck.Protection.PREFERENCES, Runnable {
|
||||
val i = Intent(this, PreferencesActivity::class.java)
|
||||
i.putExtra("id", plugin.preferencesId)
|
||||
startActivity(i)
|
||||
})
|
||||
return true
|
||||
}
|
||||
/*
|
||||
R.id.nav_survey -> {
|
||||
startActivity(Intent(this, SurveyActivity::class.java))
|
||||
return true
|
||||
}
|
||||
*/
|
||||
R.id.nav_defaultprofile -> {
|
||||
startActivity(Intent(this, ProfileHelperActivity::class.java))
|
||||
return true
|
||||
}
|
||||
|
||||
R.id.nav_stats -> {
|
||||
startActivity(Intent(this, StatsActivity::class.java))
|
||||
return true
|
||||
}
|
||||
}
|
||||
return actionBarDrawerToggle.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
// Correct place for calling setUserStats() would be probably MainApp
|
||||
// but we need to have it called at least once a day. Thus this location
|
||||
|
||||
private fun setUserStats() {
|
||||
if (!fabricPrivacy.fabricEnabled()) return
|
||||
val closedLoopEnabled = if (constraintChecker.isClosedLoopAllowed().value()) "CLOSED_LOOP_ENABLED" else "CLOSED_LOOP_DISABLED"
|
||||
// Size is limited to 36 chars
|
||||
val remote = BuildConfig.REMOTE.toLowerCase(Locale.getDefault())
|
||||
.replace("https://", "")
|
||||
.replace("http://", "")
|
||||
.replace(".git", "")
|
||||
.replace(".com/", ":")
|
||||
.replace(".org/", ":")
|
||||
.replace(".net/", ":")
|
||||
fabricPrivacy.firebaseAnalytics.setUserProperty("Mode", BuildConfig.APPLICATION_ID + "-" + closedLoopEnabled)
|
||||
fabricPrivacy.firebaseAnalytics.setUserProperty("Language", sp.getString(R.string.key_language, Locale.getDefault().language))
|
||||
fabricPrivacy.firebaseAnalytics.setUserProperty("Version", BuildConfig.VERSION)
|
||||
fabricPrivacy.firebaseAnalytics.setUserProperty("HEAD", BuildConfig.HEAD)
|
||||
fabricPrivacy.firebaseAnalytics.setUserProperty("Remote", remote)
|
||||
val hashes: List<String> = signatureVerifierPlugin.shortHashes()
|
||||
if (hashes.isNotEmpty()) fabricPrivacy.firebaseAnalytics.setUserProperty("Hash", hashes[0])
|
||||
activePlugin.activePump.let { fabricPrivacy.firebaseAnalytics.setUserProperty("Pump", it::class.java.simpleName) }
|
||||
if (!config.NSCLIENT && !config.PUMPCONTROL)
|
||||
activePlugin.activeAPS.let { fabricPrivacy.firebaseAnalytics.setUserProperty("Aps", it::class.java.simpleName) }
|
||||
activePlugin.activeBgSource.let { fabricPrivacy.firebaseAnalytics.setUserProperty("BgSource", it::class.java.simpleName) }
|
||||
fabricPrivacy.firebaseAnalytics.setUserProperty("Profile", activePlugin.activeProfileInterface.javaClass.simpleName)
|
||||
activePlugin.activeSensitivity.let { fabricPrivacy.firebaseAnalytics.setUserProperty("Sensitivity", it::class.java.simpleName) }
|
||||
activePlugin.activeInsulin.let { fabricPrivacy.firebaseAnalytics.setUserProperty("Insulin", it::class.java.simpleName) }
|
||||
}
|
||||
|
||||
}
|
|
@ -1,448 +1,170 @@
|
|||
package info.nightscout.androidaps;
|
||||
|
||||
import android.app.Application;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.res.Resources;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.os.SystemClock;
|
||||
|
||||
import androidx.annotation.ColorRes;
|
||||
import androidx.annotation.PluralsRes;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
|
||||
import com.crashlytics.android.Crashlytics;
|
||||
import com.google.firebase.analytics.FirebaseAnalytics;
|
||||
import com.j256.ormlite.android.apptools.OpenHelperManager;
|
||||
|
||||
import net.danlew.android.joda.JodaTimeAndroid;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import java.util.List;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import info.nightscout.androidaps.data.ConstraintChecker;
|
||||
import info.nightscout.androidaps.data.Profile;
|
||||
import dagger.android.AndroidInjector;
|
||||
import dagger.android.DaggerApplication;
|
||||
import info.nightscout.androidaps.db.DatabaseHelper;
|
||||
import info.nightscout.androidaps.db.StaticInjector;
|
||||
import info.nightscout.androidaps.dependencyInjection.DaggerAppComponent;
|
||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||
import info.nightscout.androidaps.interfaces.PluginType;
|
||||
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||
import info.nightscout.androidaps.logging.L;
|
||||
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin;
|
||||
import info.nightscout.androidaps.plugins.aps.openAPSAMA.OpenAPSAMAPlugin;
|
||||
import info.nightscout.androidaps.plugins.aps.openAPSMA.OpenAPSMAPlugin;
|
||||
import info.nightscout.androidaps.plugins.aps.openAPSSMB.OpenAPSSMBPlugin;
|
||||
import info.nightscout.androidaps.logging.AAPSLogger;
|
||||
import info.nightscout.androidaps.logging.LTag;
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
|
||||
import info.nightscout.androidaps.plugins.constraints.dstHelper.DstHelperPlugin;
|
||||
import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin;
|
||||
import info.nightscout.androidaps.plugins.constraints.safety.SafetyPlugin;
|
||||
import info.nightscout.androidaps.plugins.constraints.signatureVerifier.SignatureVerifierPlugin;
|
||||
import info.nightscout.androidaps.plugins.constraints.storage.StorageConstraintPlugin;
|
||||
import info.nightscout.androidaps.plugins.constraints.versionChecker.VersionCheckerPlugin;
|
||||
import info.nightscout.androidaps.plugins.general.actions.ActionsPlugin;
|
||||
import info.nightscout.androidaps.plugins.general.automation.AutomationPlugin;
|
||||
import info.nightscout.androidaps.plugins.general.careportal.CareportalPlugin;
|
||||
import info.nightscout.androidaps.plugins.general.food.FoodPlugin;
|
||||
import info.nightscout.androidaps.plugins.general.maintenance.LoggerUtils;
|
||||
import info.nightscout.androidaps.plugins.general.maintenance.MaintenancePlugin;
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.NSClientPlugin;
|
||||
import info.nightscout.androidaps.plugins.configBuilder.PluginStore;
|
||||
import info.nightscout.androidaps.plugins.constraints.versionChecker.VersionCheckerUtils;
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload;
|
||||
import info.nightscout.androidaps.plugins.general.overview.OverviewPlugin;
|
||||
import info.nightscout.androidaps.plugins.general.persistentNotification.PersistentNotificationPlugin;
|
||||
import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin;
|
||||
import info.nightscout.androidaps.plugins.general.wear.WearPlugin;
|
||||
import info.nightscout.androidaps.plugins.general.xdripStatusline.StatuslinePlugin;
|
||||
import info.nightscout.androidaps.plugins.insulin.InsulinOrefFreePeakPlugin;
|
||||
import info.nightscout.androidaps.plugins.insulin.InsulinOrefRapidActingPlugin;
|
||||
import info.nightscout.androidaps.plugins.insulin.InsulinOrefUltraRapidActingPlugin;
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin;
|
||||
import info.nightscout.androidaps.plugins.profile.local.LocalProfilePlugin;
|
||||
import info.nightscout.androidaps.plugins.profile.ns.NSProfilePlugin;
|
||||
import info.nightscout.androidaps.plugins.pump.combo.ComboPlugin;
|
||||
import info.nightscout.androidaps.plugins.pump.danaR.DanaRPlugin;
|
||||
import info.nightscout.androidaps.plugins.pump.danaRKorean.DanaRKoreanPlugin;
|
||||
import info.nightscout.androidaps.plugins.pump.danaRS.DanaRSPlugin;
|
||||
import info.nightscout.androidaps.plugins.pump.danaRv2.DanaRv2Plugin;
|
||||
import info.nightscout.androidaps.plugins.pump.insight.LocalInsightPlugin;
|
||||
import info.nightscout.androidaps.plugins.pump.mdi.MDIPlugin;
|
||||
import info.nightscout.androidaps.plugins.pump.medtronic.MedtronicPumpPlugin;
|
||||
import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin;
|
||||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityAAPSPlugin;
|
||||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref0Plugin;
|
||||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin;
|
||||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAveragePlugin;
|
||||
import info.nightscout.androidaps.plugins.source.RandomBgPlugin;
|
||||
import info.nightscout.androidaps.plugins.source.SourceDexcomPlugin;
|
||||
import info.nightscout.androidaps.plugins.source.SourceEversensePlugin;
|
||||
import info.nightscout.androidaps.plugins.source.SourceGlimpPlugin;
|
||||
import info.nightscout.androidaps.plugins.source.SourceMM640gPlugin;
|
||||
import info.nightscout.androidaps.plugins.source.SourceNSClientPlugin;
|
||||
import info.nightscout.androidaps.plugins.source.SourcePoctechPlugin;
|
||||
import info.nightscout.androidaps.plugins.source.SourceTomatoPlugin;
|
||||
import info.nightscout.androidaps.plugins.source.SourceXdripPlugin;
|
||||
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
|
||||
import info.nightscout.androidaps.receivers.BTReceiver;
|
||||
import info.nightscout.androidaps.receivers.ChargingStateReceiver;
|
||||
import info.nightscout.androidaps.receivers.DataReceiver;
|
||||
import info.nightscout.androidaps.receivers.KeepAliveReceiver;
|
||||
import info.nightscout.androidaps.receivers.NSAlarmReceiver;
|
||||
import info.nightscout.androidaps.receivers.NetworkChangeReceiver;
|
||||
import info.nightscout.androidaps.receivers.TimeDateOrTZChangeReceiver;
|
||||
import info.nightscout.androidaps.services.Intents;
|
||||
import info.nightscout.androidaps.utils.ActivityMonitor;
|
||||
import info.nightscout.androidaps.utils.FabricPrivacy;
|
||||
import info.nightscout.androidaps.utils.LocaleHelper;
|
||||
import info.nightscout.androidaps.utils.SP;
|
||||
import io.fabric.sdk.android.Fabric;
|
||||
import info.nightscout.androidaps.utils.locale.LocaleHelper;
|
||||
import info.nightscout.androidaps.utils.sharedPreferences.SP;
|
||||
|
||||
import static info.nightscout.androidaps.plugins.constraints.versionChecker.VersionCheckerUtilsKt.triggerCheckVersion;
|
||||
public class MainApp extends DaggerApplication {
|
||||
|
||||
static MainApp sInstance;
|
||||
private static Resources sResources;
|
||||
|
||||
public class MainApp extends Application {
|
||||
private static Logger log = LoggerFactory.getLogger(L.CORE);
|
||||
static DatabaseHelper sDatabaseHelper = null;
|
||||
|
||||
private static MainApp sInstance;
|
||||
public static Resources sResources;
|
||||
@Inject PluginStore pluginStore;
|
||||
@Inject AAPSLogger aapsLogger;
|
||||
@Inject ActivityMonitor activityMonitor;
|
||||
@Inject VersionCheckerUtils versionCheckersUtils;
|
||||
@Inject SP sp;
|
||||
@Inject NSUpload nsUpload;
|
||||
@Inject Config config;
|
||||
|
||||
private static FirebaseAnalytics mFirebaseAnalytics;
|
||||
@Inject ConfigBuilderPlugin configBuilderPlugin;
|
||||
@Inject KeepAliveReceiver.KeepAliveManager keepAliveManager;
|
||||
@Inject List<PluginBase> plugins;
|
||||
|
||||
private static DatabaseHelper sDatabaseHelper = null;
|
||||
private static ConstraintChecker sConstraintsChecker = null;
|
||||
|
||||
private static ArrayList<PluginBase> pluginsList = null;
|
||||
|
||||
private static DataReceiver dataReceiver = new DataReceiver();
|
||||
private static NSAlarmReceiver alarmReceiver = new NSAlarmReceiver();
|
||||
TimeDateOrTZChangeReceiver timeDateOrTZChangeReceiver;
|
||||
|
||||
public static boolean devBranch;
|
||||
public static boolean engineeringMode;
|
||||
@Inject StaticInjector staticInjector; // TODO avoid , here fake only to initialize
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
log.debug("onCreate");
|
||||
|
||||
aapsLogger.debug("onCreate");
|
||||
sInstance = this;
|
||||
sResources = getResources();
|
||||
LocaleHelper.INSTANCE.update(this);
|
||||
sConstraintsChecker = new ConstraintChecker();
|
||||
sDatabaseHelper = OpenHelperManager.getHelper(sInstance, DatabaseHelper.class);
|
||||
|
||||
/*
|
||||
Thread.setDefaultUncaughtExceptionHandler((thread, ex) -> {
|
||||
if (ex instanceof InternalError) {
|
||||
// usually the app trying to spawn a thread while being killed
|
||||
return;
|
||||
}
|
||||
|
||||
log.error("Uncaught exception crashing app", ex);
|
||||
aapsLogger.error("Uncaught exception crashing app", ex);
|
||||
});
|
||||
|
||||
try {
|
||||
if (FabricPrivacy.fabricEnabled()) {
|
||||
Fabric.with(this, new Crashlytics());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("Error with Fabric init! " + e);
|
||||
}
|
||||
|
||||
registerActivityLifecycleCallbacks(ActivityMonitor.INSTANCE);
|
||||
|
||||
mFirebaseAnalytics = FirebaseAnalytics.getInstance(this);
|
||||
mFirebaseAnalytics.setAnalyticsCollectionEnabled(!Boolean.getBoolean("disableFirebase"));
|
||||
*/
|
||||
registerActivityLifecycleCallbacks(activityMonitor);
|
||||
|
||||
JodaTimeAndroid.init(this);
|
||||
|
||||
log.info("Version: " + BuildConfig.VERSION_NAME);
|
||||
log.info("BuildVersion: " + BuildConfig.BUILDVERSION);
|
||||
log.info("Remote: " + BuildConfig.REMOTE);
|
||||
|
||||
String extFilesDir = LoggerUtils.getLogDirectory();
|
||||
File engineeringModeSemaphore = new File(extFilesDir, "engineering_mode");
|
||||
|
||||
engineeringMode = engineeringModeSemaphore.exists() && engineeringModeSemaphore.isFile();
|
||||
devBranch = BuildConfig.VERSION.contains("-") || BuildConfig.VERSION.matches(".*[a-zA-Z]+.*");
|
||||
aapsLogger.debug("Version: " + BuildConfig.VERSION_NAME);
|
||||
aapsLogger.debug("BuildVersion: " + BuildConfig.BUILDVERSION);
|
||||
aapsLogger.debug("Remote: " + BuildConfig.REMOTE);
|
||||
|
||||
registerLocalBroadcastReceiver();
|
||||
|
||||
//trigger here to see the new version on app start after an update
|
||||
triggerCheckVersion();
|
||||
versionCheckersUtils.triggerCheckVersion();
|
||||
|
||||
if (pluginsList == null) {
|
||||
pluginsList = new ArrayList<>();
|
||||
// Register all tabs in app here
|
||||
pluginsList.add(OverviewPlugin.INSTANCE);
|
||||
pluginsList.add(IobCobCalculatorPlugin.getPlugin());
|
||||
if (!Config.NSCLIENT) pluginsList.add(ActionsPlugin.INSTANCE);
|
||||
pluginsList.add(InsulinOrefRapidActingPlugin.getPlugin());
|
||||
pluginsList.add(InsulinOrefUltraRapidActingPlugin.getPlugin());
|
||||
pluginsList.add(InsulinOrefFreePeakPlugin.getPlugin());
|
||||
pluginsList.add(SensitivityOref0Plugin.getPlugin());
|
||||
pluginsList.add(SensitivityAAPSPlugin.getPlugin());
|
||||
pluginsList.add(SensitivityWeightedAveragePlugin.getPlugin());
|
||||
pluginsList.add(SensitivityOref1Plugin.getPlugin());
|
||||
if (Config.PUMPDRIVERS) pluginsList.add(DanaRPlugin.getPlugin());
|
||||
if (Config.PUMPDRIVERS) pluginsList.add(DanaRKoreanPlugin.getPlugin());
|
||||
if (Config.PUMPDRIVERS) pluginsList.add(DanaRv2Plugin.getPlugin());
|
||||
if (Config.PUMPDRIVERS) pluginsList.add(DanaRSPlugin.getPlugin());
|
||||
if (Config.PUMPDRIVERS) pluginsList.add(LocalInsightPlugin.getPlugin());
|
||||
if (Config.PUMPDRIVERS) pluginsList.add(ComboPlugin.getPlugin());
|
||||
if (Config.PUMPDRIVERS) pluginsList.add(MedtronicPumpPlugin.getPlugin());
|
||||
if (!Config.NSCLIENT) pluginsList.add(MDIPlugin.getPlugin());
|
||||
pluginsList.add(VirtualPumpPlugin.getPlugin());
|
||||
if (Config.NSCLIENT) pluginsList.add(CareportalPlugin.getPlugin());
|
||||
if (Config.APS) pluginsList.add(LoopPlugin.getPlugin());
|
||||
if (Config.APS) pluginsList.add(OpenAPSMAPlugin.getPlugin());
|
||||
if (Config.APS) pluginsList.add(OpenAPSAMAPlugin.getPlugin());
|
||||
if (Config.APS) pluginsList.add(OpenAPSSMBPlugin.getPlugin());
|
||||
pluginsList.add(NSProfilePlugin.getPlugin());
|
||||
if (!Config.NSCLIENT) pluginsList.add(LocalProfilePlugin.INSTANCE);
|
||||
pluginsList.add(TreatmentsPlugin.getPlugin());
|
||||
if (!Config.NSCLIENT) pluginsList.add(SafetyPlugin.getPlugin());
|
||||
if (!Config.NSCLIENT) pluginsList.add(VersionCheckerPlugin.INSTANCE);
|
||||
if (Config.APS) pluginsList.add(StorageConstraintPlugin.getPlugin());
|
||||
if (Config.APS) pluginsList.add(SignatureVerifierPlugin.getPlugin());
|
||||
if (Config.APS) pluginsList.add(ObjectivesPlugin.INSTANCE);
|
||||
pluginsList.add(SourceXdripPlugin.getPlugin());
|
||||
pluginsList.add(SourceNSClientPlugin.getPlugin());
|
||||
pluginsList.add(SourceMM640gPlugin.getPlugin());
|
||||
pluginsList.add(SourceGlimpPlugin.getPlugin());
|
||||
pluginsList.add(SourceDexcomPlugin.INSTANCE);
|
||||
pluginsList.add(SourcePoctechPlugin.getPlugin());
|
||||
pluginsList.add(SourceTomatoPlugin.getPlugin());
|
||||
pluginsList.add(SourceEversensePlugin.getPlugin());
|
||||
pluginsList.add(RandomBgPlugin.INSTANCE);
|
||||
if (!Config.NSCLIENT) pluginsList.add(SmsCommunicatorPlugin.INSTANCE);
|
||||
pluginsList.add(FoodPlugin.getPlugin());
|
||||
// Register all tabs in app here
|
||||
pluginStore.setPlugins(plugins);
|
||||
configBuilderPlugin.initialize();
|
||||
|
||||
pluginsList.add(WearPlugin.initPlugin(this));
|
||||
pluginsList.add(StatuslinePlugin.initPlugin(this));
|
||||
pluginsList.add(PersistentNotificationPlugin.getPlugin());
|
||||
pluginsList.add(NSClientPlugin.getPlugin());
|
||||
// if (engineeringMode) pluginsList.add(TidepoolPlugin.INSTANCE);
|
||||
pluginsList.add(MaintenancePlugin.initPlugin(this));
|
||||
pluginsList.add(AutomationPlugin.INSTANCE);
|
||||
nsUpload.uploadAppStart();
|
||||
|
||||
pluginsList.add(ConfigBuilderPlugin.getPlugin());
|
||||
|
||||
pluginsList.add(DstHelperPlugin.getPlugin());
|
||||
|
||||
|
||||
ConfigBuilderPlugin.getPlugin().initialize();
|
||||
}
|
||||
|
||||
NSUpload.uploadAppStart();
|
||||
|
||||
final PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump();
|
||||
if (pump != null) {
|
||||
new Thread(() -> {
|
||||
SystemClock.sleep(5000);
|
||||
ConfigBuilderPlugin.getPlugin().getCommandQueue().readStatus("Initialization", null);
|
||||
}).start();
|
||||
}
|
||||
|
||||
new Thread(() -> KeepAliveReceiver.setAlarm(this)).start();
|
||||
new Thread(() -> keepAliveManager.setAlarm(this)).start();
|
||||
doMigrations();
|
||||
}
|
||||
|
||||
|
||||
private void doMigrations() {
|
||||
|
||||
// guarantee that the unreachable threshold is at least 30 and of type String
|
||||
// Added in 1.57 at 21.01.2018
|
||||
int unreachable_threshold = SP.getInt(R.string.key_pump_unreachable_threshold, 30);
|
||||
SP.remove(R.string.key_pump_unreachable_threshold);
|
||||
if (unreachable_threshold < 30) unreachable_threshold = 30;
|
||||
SP.putString(R.string.key_pump_unreachable_threshold, Integer.toString(unreachable_threshold));
|
||||
|
||||
// 2.5 -> 2.6
|
||||
if (!SP.contains(R.string.key_units)) {
|
||||
String newUnits = Constants.MGDL;
|
||||
Profile p = ProfileFunctions.getInstance().getProfile();
|
||||
if (p != null && p.getData() != null && p.getData().has("units")) {
|
||||
try {
|
||||
newUnits = p.getData().getString("units");
|
||||
} catch (JSONException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
}
|
||||
SP.putString(R.string.key_units, newUnits);
|
||||
}
|
||||
// set values for different builds
|
||||
if (!sp.contains(R.string.key_ns_alarms))
|
||||
sp.putBoolean(R.string.key_ns_alarms, config.getNSCLIENT());
|
||||
if (!sp.contains(R.string.key_ns_announcements))
|
||||
sp.putBoolean(R.string.key_ns_announcements, config.getNSCLIENT());
|
||||
if (!sp.contains(R.string.key_language))
|
||||
sp.putString(R.string.key_language, "default");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AndroidInjector<? extends DaggerApplication> applicationInjector() {
|
||||
return DaggerAppComponent
|
||||
.builder()
|
||||
.application(this)
|
||||
.build();
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void registerLocalBroadcastReceiver() {
|
||||
LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(this);
|
||||
lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_TREATMENT));
|
||||
lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_CHANGED_TREATMENT));
|
||||
lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_REMOVED_TREATMENT));
|
||||
lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_FOOD));
|
||||
lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_CHANGED_FOOD));
|
||||
lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_REMOVED_FOOD));
|
||||
lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_SGV));
|
||||
lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_PROFILE));
|
||||
lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_STATUS));
|
||||
lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_MBG));
|
||||
lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_DEVICESTATUS));
|
||||
lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_CAL));
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(Intents.ACTION_NEW_TREATMENT);
|
||||
filter.addAction(Intents.ACTION_CHANGED_TREATMENT);
|
||||
filter.addAction(Intents.ACTION_REMOVED_TREATMENT);
|
||||
filter.addAction(Intents.ACTION_NEW_SGV);
|
||||
filter.addAction(Intents.ACTION_NEW_PROFILE);
|
||||
filter.addAction(Intents.ACTION_NEW_MBG);
|
||||
filter.addAction(Intents.ACTION_NEW_CAL);
|
||||
LocalBroadcastManager.getInstance(this).registerReceiver(new DataReceiver(), filter);
|
||||
|
||||
//register alarms
|
||||
lbm.registerReceiver(alarmReceiver, new IntentFilter(Intents.ACTION_ALARM));
|
||||
lbm.registerReceiver(alarmReceiver, new IntentFilter(Intents.ACTION_ANNOUNCEMENT));
|
||||
lbm.registerReceiver(alarmReceiver, new IntentFilter(Intents.ACTION_CLEAR_ALARM));
|
||||
lbm.registerReceiver(alarmReceiver, new IntentFilter(Intents.ACTION_URGENT_ALARM));
|
||||
filter = new IntentFilter();
|
||||
filter.addAction(Intent.ACTION_TIME_CHANGED);
|
||||
filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
|
||||
registerReceiver(new TimeDateOrTZChangeReceiver(), filter);
|
||||
|
||||
this.timeDateOrTZChangeReceiver = new TimeDateOrTZChangeReceiver();
|
||||
this.timeDateOrTZChangeReceiver.registerBroadcasts(this);
|
||||
filter = new IntentFilter();
|
||||
filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
|
||||
filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
|
||||
filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
|
||||
registerReceiver(new NetworkChangeReceiver(), filter);
|
||||
|
||||
IntentFilter intentFilter = new IntentFilter();
|
||||
intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
|
||||
intentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
|
||||
intentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION );
|
||||
registerReceiver(new NetworkChangeReceiver(), intentFilter);
|
||||
registerReceiver(new ChargingStateReceiver(), new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
|
||||
}
|
||||
filter = new IntentFilter();
|
||||
filter.addAction(Intent.ACTION_POWER_CONNECTED);
|
||||
filter.addAction(Intent.ACTION_POWER_DISCONNECTED);
|
||||
filter.addAction(Intent.ACTION_BATTERY_CHANGED);
|
||||
registerReceiver(new ChargingStateReceiver(), filter);
|
||||
|
||||
public static String gs(@StringRes int id) {
|
||||
return sResources.getString(id);
|
||||
}
|
||||
|
||||
public static String gs(@StringRes int id, Object... args) {
|
||||
return sResources.getString(id, args);
|
||||
}
|
||||
|
||||
public static String gq(@PluralsRes int id, int quantity, Object... args) {
|
||||
return sResources.getQuantityString(id, quantity, args);
|
||||
}
|
||||
|
||||
public static int gc(@ColorRes int id) {
|
||||
return ContextCompat.getColor(instance(), id);
|
||||
}
|
||||
|
||||
public static MainApp instance() {
|
||||
return sInstance;
|
||||
filter = new IntentFilter();
|
||||
filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
|
||||
filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
|
||||
registerReceiver(new BTReceiver(), filter);
|
||||
}
|
||||
|
||||
public static DatabaseHelper getDbHelper() {
|
||||
return sDatabaseHelper;
|
||||
}
|
||||
|
||||
public static FirebaseAnalytics getFirebaseAnalytics() {
|
||||
return mFirebaseAnalytics;
|
||||
}
|
||||
|
||||
public static ConstraintChecker getConstraintChecker() {
|
||||
return sConstraintsChecker;
|
||||
}
|
||||
|
||||
public static ArrayList<PluginBase> getPluginsList() {
|
||||
return pluginsList;
|
||||
}
|
||||
|
||||
public static ArrayList<PluginBase> getSpecificPluginsList(PluginType type) {
|
||||
ArrayList<PluginBase> newList = new ArrayList<>();
|
||||
|
||||
if (pluginsList != null) {
|
||||
for (PluginBase p : pluginsList) {
|
||||
if (p.getType() == type)
|
||||
newList.add(p);
|
||||
}
|
||||
} else {
|
||||
log.error("pluginsList=null");
|
||||
}
|
||||
return newList;
|
||||
}
|
||||
|
||||
public static ArrayList<PluginBase> getSpecificPluginsVisibleInList(PluginType type) {
|
||||
ArrayList<PluginBase> newList = new ArrayList<>();
|
||||
|
||||
if (pluginsList != null) {
|
||||
for (PluginBase p : pluginsList) {
|
||||
if (p.getType() == type)
|
||||
if (p.showInList(type))
|
||||
newList.add(p);
|
||||
}
|
||||
} else {
|
||||
log.error("pluginsList=null");
|
||||
}
|
||||
return newList;
|
||||
}
|
||||
|
||||
public static ArrayList<PluginBase> getSpecificPluginsListByInterface(Class interfaceClass) {
|
||||
ArrayList<PluginBase> newList = new ArrayList<>();
|
||||
|
||||
if (pluginsList != null) {
|
||||
for (PluginBase p : pluginsList) {
|
||||
if (p.getClass() != ConfigBuilderPlugin.class && interfaceClass.isAssignableFrom(p.getClass()))
|
||||
newList.add(p);
|
||||
}
|
||||
} else {
|
||||
log.error("pluginsList=null");
|
||||
}
|
||||
return newList;
|
||||
}
|
||||
|
||||
public static ArrayList<PluginBase> getSpecificPluginsVisibleInListByInterface(Class interfaceClass, PluginType type) {
|
||||
ArrayList<PluginBase> newList = new ArrayList<>();
|
||||
|
||||
if (pluginsList != null) {
|
||||
for (PluginBase p : pluginsList) {
|
||||
if (p.getClass() != ConfigBuilderPlugin.class && interfaceClass.isAssignableFrom(p.getClass()))
|
||||
if (p.showInList(type))
|
||||
newList.add(p);
|
||||
}
|
||||
} else {
|
||||
log.error("pluginsList=null");
|
||||
}
|
||||
return newList;
|
||||
}
|
||||
|
||||
public static boolean isEngineeringModeOrRelease() {
|
||||
if (!Config.APS)
|
||||
return true;
|
||||
return engineeringMode || !devBranch;
|
||||
}
|
||||
|
||||
public static boolean isDev() {
|
||||
return devBranch;
|
||||
}
|
||||
|
||||
public static int getIcon() {
|
||||
if (Config.NSCLIENT)
|
||||
return R.mipmap.ic_yellowowl;
|
||||
else if (Config.PUMPCONTROL)
|
||||
return R.mipmap.ic_pumpcontrol;
|
||||
else
|
||||
return R.mipmap.ic_launcher;
|
||||
}
|
||||
|
||||
public static int getNotificationIcon() {
|
||||
if (Config.NSCLIENT)
|
||||
return R.drawable.ic_notif_nsclient;
|
||||
else if (Config.PUMPCONTROL)
|
||||
return R.drawable.ic_notif_pumpcontrol;
|
||||
else
|
||||
return R.drawable.ic_notif_aaps;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTerminate() {
|
||||
if (L.isEnabled(L.CORE))
|
||||
log.debug("onTerminate");
|
||||
|
||||
if (timeDateOrTZChangeReceiver != null)
|
||||
unregisterReceiver(timeDateOrTZChangeReceiver);
|
||||
unregisterActivityLifecycleCallbacks(ActivityMonitor.INSTANCE);
|
||||
KeepAliveReceiver.cancelAlarm(this);
|
||||
aapsLogger.debug(LTag.CORE, "onTerminate");
|
||||
unregisterActivityLifecycleCallbacks(activityMonitor);
|
||||
keepAliveManager.cancelAlarm(this);
|
||||
super.onTerminate();
|
||||
}
|
||||
|
||||
public static int dpToPx(int dp) {
|
||||
float scale = sResources.getDisplayMetrics().density;
|
||||
return (int) (dp * scale + 0.5f);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
package info.nightscout.androidaps.activities
|
||||
|
||||
import android.content.Context
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import info.nightscout.androidaps.utils.LocaleHelper
|
||||
|
||||
open class DialogAppCompatActivity : AppCompatActivity() {
|
||||
public override fun attachBaseContext(newBase: Context) {
|
||||
super.attachBaseContext(LocaleHelper.wrap(newBase))
|
||||
}
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
package info.nightscout.androidaps.activities
|
||||
|
||||
import android.os.Bundle
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.dialogs.ErrorDialog
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
|
||||
import info.nightscout.androidaps.utils.SP
|
||||
|
||||
class ErrorHelperActivity : DialogAppCompatActivity() {
|
||||
|
||||
@Override
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
val errorDialog = ErrorDialog()
|
||||
errorDialog.helperActivity = this
|
||||
errorDialog.status = intent.getStringExtra("status")
|
||||
errorDialog.sound = intent.getIntExtra("soundid", R.raw.error)
|
||||
errorDialog.title = intent.getStringExtra("title")
|
||||
errorDialog.show(supportFragmentManager, "Error")
|
||||
|
||||
if (SP.getBoolean(R.string.key_ns_create_announcements_from_errors, true)) {
|
||||
NSUpload.uploadError(intent.getStringExtra("status"))
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,481 +0,0 @@
|
|||
package info.nightscout.androidaps.activities;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.os.SystemClock;
|
||||
import android.text.SpannableString;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.appcompat.widget.PopupMenu;
|
||||
import androidx.core.content.res.ResourcesCompat;
|
||||
|
||||
import com.jjoe64.graphview.GraphView;
|
||||
import com.wdullaer.materialdatetimepicker.date.DatePickerDialog;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.data.Profile;
|
||||
import info.nightscout.androidaps.events.EventCustomCalculationFinished;
|
||||
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||
import info.nightscout.androidaps.plugins.bus.RxBus;
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
|
||||
import info.nightscout.androidaps.plugins.general.overview.OverviewFragment;
|
||||
import info.nightscout.androidaps.plugins.general.overview.OverviewPlugin;
|
||||
import info.nightscout.androidaps.plugins.general.overview.graphData.GraphData;
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin;
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutosensCalculationFinished;
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventIobCalculationProgress;
|
||||
import info.nightscout.androidaps.utils.DateUtil;
|
||||
import info.nightscout.androidaps.utils.FabricPrivacy;
|
||||
import info.nightscout.androidaps.utils.SP;
|
||||
import info.nightscout.androidaps.utils.T;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.disposables.CompositeDisposable;
|
||||
|
||||
public class HistoryBrowseActivity extends NoSplashAppCompatActivity {
|
||||
private static Logger log = LoggerFactory.getLogger(HistoryBrowseActivity.class);
|
||||
private CompositeDisposable disposable = new CompositeDisposable();
|
||||
|
||||
ImageButton chartButton;
|
||||
|
||||
boolean showBasal = true;
|
||||
boolean showIob, showCob, showDev, showRat, showActPrim, showActSec, showDevslope;
|
||||
|
||||
|
||||
Button buttonDate;
|
||||
Button buttonZoom;
|
||||
GraphView bgGraph;
|
||||
GraphView iobGraph;
|
||||
SeekBar seekBar;
|
||||
TextView noProfile;
|
||||
TextView iobCalculationProgressView;
|
||||
|
||||
private int rangeToDisplay = 24; // for graph
|
||||
private long start = 0;
|
||||
|
||||
IobCobCalculatorPlugin iobCobCalculatorPlugin;
|
||||
|
||||
EventCustomCalculationFinished eventCustomCalculationFinished = new EventCustomCalculationFinished();
|
||||
|
||||
public HistoryBrowseActivity() {
|
||||
iobCobCalculatorPlugin = new IobCobCalculatorPlugin();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_historybrowse);
|
||||
|
||||
buttonDate = findViewById(R.id.historybrowse_date);
|
||||
buttonZoom = findViewById(R.id.historybrowse_zoom);
|
||||
bgGraph = findViewById(R.id.historyybrowse_bggraph);
|
||||
iobGraph = findViewById(R.id.historybrowse_iobgraph);
|
||||
seekBar = findViewById(R.id.historybrowse_seekBar);
|
||||
noProfile = findViewById(R.id.historybrowse_noprofile);
|
||||
iobCalculationProgressView = findViewById(R.id.overview_iobcalculationprogess);
|
||||
|
||||
findViewById(R.id.historybrowse_left).setOnClickListener(v -> {
|
||||
start -= T.hours(rangeToDisplay).msecs();
|
||||
updateGUI("onClickLeft");
|
||||
runCalculation("onClickLeft");
|
||||
});
|
||||
|
||||
findViewById(R.id.historybrowse_right).setOnClickListener(v -> {
|
||||
start += T.hours(rangeToDisplay).msecs();
|
||||
updateGUI("onClickRight");
|
||||
runCalculation("onClickRight");
|
||||
});
|
||||
|
||||
findViewById(R.id.historybrowse_end).setOnClickListener(v -> {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTimeInMillis(System.currentTimeMillis());
|
||||
calendar.set(Calendar.MILLISECOND, 0);
|
||||
calendar.set(Calendar.SECOND, 0);
|
||||
calendar.set(Calendar.MINUTE, 0);
|
||||
calendar.set(Calendar.HOUR_OF_DAY, 0);
|
||||
start = calendar.getTimeInMillis();
|
||||
updateGUI("onClickEnd");
|
||||
runCalculation("onClickEnd");
|
||||
});
|
||||
|
||||
findViewById(R.id.historybrowse_zoom).setOnClickListener(v -> {
|
||||
rangeToDisplay += 6;
|
||||
rangeToDisplay = rangeToDisplay > 24 ? 6 : rangeToDisplay;
|
||||
updateGUI("rangeChange");
|
||||
});
|
||||
|
||||
findViewById(R.id.historybrowse_zoom).setOnLongClickListener(v -> {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTimeInMillis(start);
|
||||
calendar.set(Calendar.MILLISECOND, 0);
|
||||
calendar.set(Calendar.SECOND, 0);
|
||||
calendar.set(Calendar.MINUTE, 0);
|
||||
calendar.set(Calendar.HOUR_OF_DAY, 0);
|
||||
start = calendar.getTimeInMillis();
|
||||
updateGUI("resetToMidnight");
|
||||
runCalculation("onLongClickZoom");
|
||||
return true;
|
||||
});
|
||||
|
||||
findViewById(R.id.historybrowse_date).setOnClickListener(v -> {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTime(new Date(start));
|
||||
DatePickerDialog dpd = DatePickerDialog.newInstance(
|
||||
(view, year, monthOfYear, dayOfMonth) -> {
|
||||
Date date = new Date(0);
|
||||
date.setYear(year - 1900);
|
||||
date.setMonth(monthOfYear);
|
||||
date.setDate(dayOfMonth);
|
||||
date.setHours(0);
|
||||
start = date.getTime();
|
||||
updateGUI("onClickDate");
|
||||
runCalculation("onClickDate");
|
||||
},
|
||||
calendar.get(Calendar.YEAR),
|
||||
calendar.get(Calendar.MONTH),
|
||||
calendar.get(Calendar.DAY_OF_MONTH)
|
||||
);
|
||||
dpd.setThemeDark(true);
|
||||
dpd.dismissOnPause(true);
|
||||
dpd.show(getSupportFragmentManager(), "Datepickerdialog");
|
||||
});
|
||||
|
||||
bgGraph.getGridLabelRenderer().setGridColor(MainApp.gc(R.color.graphgrid));
|
||||
bgGraph.getGridLabelRenderer().reloadStyles();
|
||||
iobGraph.getGridLabelRenderer().setGridColor(MainApp.gc(R.color.graphgrid));
|
||||
iobGraph.getGridLabelRenderer().reloadStyles();
|
||||
iobGraph.getGridLabelRenderer().setHorizontalLabelsVisible(false);
|
||||
bgGraph.getGridLabelRenderer().setLabelVerticalWidth(50);
|
||||
iobGraph.getGridLabelRenderer().setLabelVerticalWidth(50);
|
||||
iobGraph.getGridLabelRenderer().setNumVerticalLabels(5);
|
||||
|
||||
setupChartMenu();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
disposable.clear();
|
||||
iobCobCalculatorPlugin.stopCalculation("onPause");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
disposable.add(RxBus.INSTANCE
|
||||
.toObservable(EventAutosensCalculationFinished.class)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(event -> {
|
||||
if (event.getCause() == eventCustomCalculationFinished) {
|
||||
log.debug("EventAutosensCalculationFinished");
|
||||
synchronized (HistoryBrowseActivity.this) {
|
||||
updateGUI("EventAutosensCalculationFinished");
|
||||
}
|
||||
}
|
||||
}, FabricPrivacy::logException)
|
||||
);
|
||||
disposable.add(RxBus.INSTANCE
|
||||
.toObservable(EventIobCalculationProgress.class)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(event -> {
|
||||
if (iobCalculationProgressView != null)
|
||||
iobCalculationProgressView.setText(event.getProgress());
|
||||
}, FabricPrivacy::logException)
|
||||
);
|
||||
// set start of current day
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTimeInMillis(System.currentTimeMillis());
|
||||
calendar.set(Calendar.MILLISECOND, 0);
|
||||
calendar.set(Calendar.SECOND, 0);
|
||||
calendar.set(Calendar.MINUTE, 0);
|
||||
calendar.set(Calendar.HOUR_OF_DAY, 0);
|
||||
start = calendar.getTimeInMillis();
|
||||
runCalculation("onResume");
|
||||
SystemClock.sleep(1000);
|
||||
updateGUI("onResume");
|
||||
}
|
||||
|
||||
private void runCalculation(String from) {
|
||||
long end = start + T.hours(rangeToDisplay).msecs();
|
||||
iobCobCalculatorPlugin.stopCalculation(from);
|
||||
iobCobCalculatorPlugin.clearCache();
|
||||
iobCobCalculatorPlugin.runCalculation(from, end, true, false, eventCustomCalculationFinished);
|
||||
}
|
||||
|
||||
void updateGUI(String from) {
|
||||
log.debug("updateGUI from: " + from);
|
||||
|
||||
if (noProfile == null || buttonDate == null || buttonZoom == null || bgGraph == null || iobGraph == null || seekBar == null)
|
||||
return;
|
||||
|
||||
final PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump();
|
||||
final Profile profile = ProfileFunctions.getInstance().getProfile();
|
||||
|
||||
if (profile == null) {
|
||||
noProfile.setVisibility(View.VISIBLE);
|
||||
return;
|
||||
} else {
|
||||
noProfile.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
final double lowLine = OverviewPlugin.INSTANCE.determineLowLine();
|
||||
final double highLine = OverviewPlugin.INSTANCE.determineHighLine();
|
||||
|
||||
buttonDate.setText(DateUtil.dateAndTimeString(start));
|
||||
buttonZoom.setText(String.valueOf(rangeToDisplay));
|
||||
|
||||
final boolean showPrediction = false;
|
||||
|
||||
showBasal = SP.getBoolean("hist_showbasals", true);
|
||||
showIob = SP.getBoolean("hist_showiob", true);
|
||||
showCob = SP.getBoolean("hist_showcob", true);
|
||||
showDev = SP.getBoolean("hist_showdeviations", false);
|
||||
showRat = SP.getBoolean("hist_showratios", false);
|
||||
showActPrim = SP.getBoolean("hist_showactivityprimary", false);
|
||||
showActSec = SP.getBoolean("hist_showactivitysecondary", false);
|
||||
showDevslope = SP.getBoolean("hist_showdevslope", false);
|
||||
|
||||
int hoursToFetch;
|
||||
final long toTime;
|
||||
final long fromTime;
|
||||
//if (showPrediction) {
|
||||
//int predHours = (int) (Math.ceil(((DetermineBasalResultAMA) finalLastRun.constraintsProcessed).getLatestPredictionsTime() - System.currentTimeMillis()) / (60 * 60 * 1000));
|
||||
//predHours = Math.min(2, predHours);
|
||||
//predHours = Math.max(0, predHours);
|
||||
//hoursToFetch = rangeToDisplay - predHours;
|
||||
//toTime = calendar.getTimeInMillis() + 100000; // little bit more to avoid wrong rounding - Graphview specific
|
||||
//fromTime = toTime - hoursToFetch * 60 * 60 * 1000L;
|
||||
//endTime = toTime + predHours * 60 * 60 * 1000L;
|
||||
//} else {
|
||||
fromTime = start + T.secs(100).msecs();
|
||||
toTime = start + T.hours(rangeToDisplay).msecs();
|
||||
//}
|
||||
|
||||
log.debug("Period: " + DateUtil.dateAndTimeString(fromTime) + " - " + DateUtil.dateAndTimeString(toTime));
|
||||
|
||||
final long pointer = System.currentTimeMillis();
|
||||
|
||||
// ------------------ 1st graph
|
||||
|
||||
final GraphData graphData = new GraphData(bgGraph, iobCobCalculatorPlugin);
|
||||
|
||||
// **** In range Area ****
|
||||
graphData.addInRangeArea(fromTime, toTime, lowLine, highLine);
|
||||
|
||||
// **** BG ****
|
||||
if (showPrediction)
|
||||
//graphData.addBgReadings(fromTime, toTime, lowLine, highLine, (DetermineBasalResultAMA) finalLastRun.constraintsProcessed);
|
||||
;
|
||||
else
|
||||
graphData.addBgReadings(fromTime, toTime, lowLine, highLine, null);
|
||||
|
||||
// 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);
|
||||
|
||||
// add basal data
|
||||
if (pump.getPumpDescription().isTempBasalCapable && showBasal) {
|
||||
graphData.addBasals(fromTime, toTime, lowLine / graphData.maxY / 1.2d);
|
||||
}
|
||||
|
||||
// **** NOW line ****
|
||||
graphData.addNowLine(pointer);
|
||||
|
||||
// ------------------ 2nd graph
|
||||
|
||||
new Thread(() -> {
|
||||
final GraphData secondGraphData = new GraphData(iobGraph, iobCobCalculatorPlugin);
|
||||
|
||||
boolean useIobForScale = false;
|
||||
boolean useCobForScale = false;
|
||||
boolean useDevForScale = false;
|
||||
boolean useRatioForScale = false;
|
||||
boolean useIAForScale = false;
|
||||
boolean useDSForScale = false;
|
||||
|
||||
if (showIob) {
|
||||
useIobForScale = true;
|
||||
} else if (showCob) {
|
||||
useCobForScale = true;
|
||||
} else if (showDev) {
|
||||
useDevForScale = true;
|
||||
} else if (showRat) {
|
||||
useRatioForScale = true;
|
||||
} else if (showActSec) {
|
||||
useIAForScale = true;
|
||||
} else if (showDevslope) {
|
||||
useDSForScale = true;
|
||||
}
|
||||
|
||||
if (showIob)
|
||||
secondGraphData.addIob(fromTime, toTime, useIobForScale, 1d, showPrediction);
|
||||
if (showCob)
|
||||
secondGraphData.addCob(fromTime, toTime, useCobForScale, useCobForScale ? 1d : 0.5d);
|
||||
if (showDev)
|
||||
secondGraphData.addDeviations(fromTime, toTime, useDevForScale, 1d);
|
||||
if (showRat)
|
||||
secondGraphData.addRatio(fromTime, toTime, useRatioForScale, 1d);
|
||||
if (showActSec)
|
||||
secondGraphData.addActivity(fromTime, toTime, useIAForScale, useIAForScale ? 2d : 1d);
|
||||
if (showDevslope)
|
||||
secondGraphData.addDeviationSlope(fromTime, toTime, useDSForScale, 1d);
|
||||
|
||||
// **** NOW line ****
|
||||
// set manual x bounds to have nice steps
|
||||
secondGraphData.formatAxis(fromTime, toTime);
|
||||
secondGraphData.addNowLine(pointer);
|
||||
|
||||
// do GUI update
|
||||
runOnUiThread(() -> {
|
||||
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 || showActSec || showDevslope)
|
||||
secondGraphData.performUpdate();
|
||||
});
|
||||
}).start();
|
||||
}
|
||||
|
||||
private void setupChartMenu() {
|
||||
chartButton = (ImageButton) findViewById(R.id.overview_chartMenuButton);
|
||||
chartButton.setOnClickListener(v -> {
|
||||
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);
|
||||
item.setCheckable(true);
|
||||
item.setChecked(showIob);
|
||||
|
||||
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);
|
||||
item.setCheckable(true);
|
||||
item.setChecked(showCob);
|
||||
|
||||
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);
|
||||
item.setCheckable(true);
|
||||
item.setChecked(showDev);
|
||||
|
||||
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);
|
||||
item.setCheckable(true);
|
||||
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()) {
|
||||
SP.putBoolean("hist_showbasals", !item1.isChecked());
|
||||
} else if (item1.getItemId() == OverviewFragment.CHARTTYPE.IOB.ordinal()) {
|
||||
SP.putBoolean("hist_showiob", !item1.isChecked());
|
||||
} else if (item1.getItemId() == OverviewFragment.CHARTTYPE.COB.ordinal()) {
|
||||
SP.putBoolean("hist_showcob", !item1.isChecked());
|
||||
} else if (item1.getItemId() == OverviewFragment.CHARTTYPE.DEV.ordinal()) {
|
||||
SP.putBoolean("hist_showdeviations", !item1.isChecked());
|
||||
} else if (item1.getItemId() == OverviewFragment.CHARTTYPE.SEN.ordinal()) {
|
||||
SP.putBoolean("hist_showratios", !item1.isChecked());
|
||||
} else if (item1.getItemId() == OverviewFragment.CHARTTYPE.ACTPRIM.ordinal()) {
|
||||
SP.putBoolean("hist_showactivityprimary", !item1.isChecked());
|
||||
} else if (item1.getItemId() == OverviewFragment.CHARTTYPE.ACTSEC.ordinal()) {
|
||||
SP.putBoolean("hist_showactivitysecondary", !item1.isChecked());
|
||||
} else if (item1.getItemId() == OverviewFragment.CHARTTYPE.DEVSLOPE.ordinal()) {
|
||||
SP.putBoolean("hist_showdevslope", !item1.isChecked());
|
||||
}
|
||||
updateGUI("onGraphCheckboxesCheckedChanged");
|
||||
return true;
|
||||
});
|
||||
chartButton.setImageResource(R.drawable.ic_arrow_drop_up_white_24dp);
|
||||
popup.setOnDismissListener(menu -> chartButton.setImageResource(R.drawable.ic_arrow_drop_down_white_24dp));
|
||||
popup.show();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,389 @@
|
|||
package info.nightscout.androidaps.activities
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener
|
||||
import android.os.Bundle
|
||||
import androidx.annotation.XmlRes
|
||||
import androidx.preference.*
|
||||
import dagger.android.AndroidInjector
|
||||
import dagger.android.DispatchingAndroidInjector
|
||||
import dagger.android.HasAndroidInjector
|
||||
import dagger.android.support.AndroidSupportInjection
|
||||
import info.nightscout.androidaps.Config
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.danaRKorean.DanaRKoreanPlugin
|
||||
import info.nightscout.androidaps.danaRv2.DanaRv2Plugin
|
||||
import info.nightscout.androidaps.danar.DanaRPlugin
|
||||
import info.nightscout.androidaps.danars.DanaRSPlugin
|
||||
import info.nightscout.androidaps.data.Profile
|
||||
import info.nightscout.androidaps.events.EventPreferenceChange
|
||||
import info.nightscout.androidaps.events.EventRebuildTabs
|
||||
import info.nightscout.androidaps.interfaces.PluginBase
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin
|
||||
import info.nightscout.androidaps.plugins.aps.openAPSAMA.OpenAPSAMAPlugin
|
||||
import info.nightscout.androidaps.plugins.aps.openAPSSMB.OpenAPSSMBPlugin
|
||||
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
||||
import info.nightscout.androidaps.plugins.configBuilder.PluginStore
|
||||
import info.nightscout.androidaps.plugins.constraints.safety.SafetyPlugin
|
||||
import info.nightscout.androidaps.plugins.general.automation.AutomationPlugin
|
||||
import info.nightscout.androidaps.plugins.general.maintenance.MaintenancePlugin
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.NSClientPlugin
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.data.NSSettingsStatus
|
||||
import info.nightscout.androidaps.plugins.general.openhumans.OpenHumansUploader
|
||||
import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin
|
||||
import info.nightscout.androidaps.plugins.general.tidepool.TidepoolPlugin
|
||||
import info.nightscout.androidaps.plugins.general.wear.WearPlugin
|
||||
import info.nightscout.androidaps.plugins.general.xdripStatusline.StatusLinePlugin
|
||||
import info.nightscout.androidaps.plugins.insulin.InsulinOrefFreePeakPlugin
|
||||
import info.nightscout.androidaps.plugins.pump.combo.ComboPlugin
|
||||
import info.nightscout.androidaps.plugins.pump.insight.LocalInsightPlugin
|
||||
import info.nightscout.androidaps.plugins.pump.medtronic.MedtronicPumpPlugin
|
||||
import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin
|
||||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityAAPSPlugin
|
||||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin
|
||||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAveragePlugin
|
||||
import info.nightscout.androidaps.plugins.source.DexcomPlugin
|
||||
import info.nightscout.androidaps.plugins.source.EversensePlugin
|
||||
import info.nightscout.androidaps.plugins.source.GlimpPlugin
|
||||
import info.nightscout.androidaps.plugins.source.PoctechPlugin
|
||||
import info.nightscout.androidaps.plugins.source.TomatoPlugin
|
||||
import info.nightscout.androidaps.utils.SafeParse
|
||||
import info.nightscout.androidaps.utils.alertDialogs.OKDialog.show
|
||||
import info.nightscout.androidaps.utils.protection.PasswordCheck
|
||||
import info.nightscout.androidaps.utils.protection.ProtectionCheck
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
||||
import javax.inject.Inject
|
||||
|
||||
class MyPreferenceFragment : PreferenceFragmentCompat(), OnSharedPreferenceChangeListener, HasAndroidInjector {
|
||||
|
||||
private var pluginId = -1
|
||||
|
||||
@Inject lateinit var rxBus: RxBusWrapper
|
||||
@Inject lateinit var resourceHelper: ResourceHelper
|
||||
@Inject lateinit var sp: SP
|
||||
@Inject lateinit var profileFunction: ProfileFunction
|
||||
@Inject lateinit var pluginStore: PluginStore
|
||||
@Inject lateinit var config: Config
|
||||
|
||||
@Inject lateinit var automationPlugin: AutomationPlugin
|
||||
@Inject lateinit var danaRPlugin: DanaRPlugin
|
||||
@Inject lateinit var danaRKoreanPlugin: DanaRKoreanPlugin
|
||||
@Inject lateinit var danaRv2Plugin: DanaRv2Plugin
|
||||
@Inject lateinit var danaRSPlugin: DanaRSPlugin
|
||||
@Inject lateinit var comboPlugin: ComboPlugin
|
||||
@Inject lateinit var insulinOrefFreePeakPlugin: InsulinOrefFreePeakPlugin
|
||||
@Inject lateinit var loopPlugin: LoopPlugin
|
||||
@Inject lateinit var localInsightPlugin: LocalInsightPlugin
|
||||
@Inject lateinit var medtronicPumpPlugin: MedtronicPumpPlugin
|
||||
@Inject lateinit var nsClientPlugin: NSClientPlugin
|
||||
@Inject lateinit var openAPSAMAPlugin: OpenAPSAMAPlugin
|
||||
@Inject lateinit var openAPSSMBPlugin: OpenAPSSMBPlugin
|
||||
@Inject lateinit var safetyPlugin: SafetyPlugin
|
||||
@Inject lateinit var sensitivityAAPSPlugin: SensitivityAAPSPlugin
|
||||
@Inject lateinit var sensitivityOref1Plugin: SensitivityOref1Plugin
|
||||
@Inject lateinit var sensitivityWeightedAveragePlugin: SensitivityWeightedAveragePlugin
|
||||
@Inject lateinit var dexcomPlugin: DexcomPlugin
|
||||
@Inject lateinit var eversensePlugin: EversensePlugin
|
||||
@Inject lateinit var glimpPlugin: GlimpPlugin
|
||||
@Inject lateinit var poctechPlugin: PoctechPlugin
|
||||
@Inject lateinit var tomatoPlugin: TomatoPlugin
|
||||
@Inject lateinit var smsCommunicatorPlugin: SmsCommunicatorPlugin
|
||||
@Inject lateinit var statusLinePlugin: StatusLinePlugin
|
||||
@Inject lateinit var tidepoolPlugin: TidepoolPlugin
|
||||
@Inject lateinit var virtualPumpPlugin: VirtualPumpPlugin
|
||||
@Inject lateinit var wearPlugin: WearPlugin
|
||||
@Inject lateinit var maintenancePlugin: MaintenancePlugin
|
||||
|
||||
@Inject lateinit var passwordCheck: PasswordCheck
|
||||
@Inject lateinit var nsSettingStatus: NSSettingsStatus
|
||||
@Inject lateinit var openHumansUploader: OpenHumansUploader
|
||||
|
||||
// TODO why?
|
||||
@Inject lateinit var androidInjector: DispatchingAndroidInjector<Any>
|
||||
|
||||
override fun androidInjector(): AndroidInjector<Any> = androidInjector
|
||||
|
||||
override fun onAttach(context: Context) {
|
||||
AndroidSupportInjection.inject(this)
|
||||
super.onAttach(context)
|
||||
}
|
||||
|
||||
override fun setArguments(args: Bundle?) {
|
||||
super.setArguments(args)
|
||||
pluginId = args?.getInt("id") ?: -1
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
outState.putInt("id", pluginId)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
PreferenceManager
|
||||
.getDefaultSharedPreferences(context)
|
||||
.unregisterOnSharedPreferenceChangeListener(this)
|
||||
}
|
||||
|
||||
private fun addPreferencesFromResourceIfEnabled(p: PluginBase?, rootKey: String?, enabled: Boolean) {
|
||||
if (enabled) addPreferencesFromResourceIfEnabled(p, rootKey)
|
||||
}
|
||||
|
||||
private fun addPreferencesFromResourceIfEnabled(p: PluginBase?, rootKey: String?) {
|
||||
if (p!!.isEnabled() && p.preferencesId != -1)
|
||||
addPreferencesFromResource(p.preferencesId, rootKey)
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
PreferenceManager
|
||||
.getDefaultSharedPreferences(context)
|
||||
.registerOnSharedPreferenceChangeListener(this)
|
||||
}
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
(savedInstanceState ?: arguments)?.let { bundle ->
|
||||
if (bundle.containsKey("id")) {
|
||||
pluginId = bundle.getInt("id")
|
||||
}
|
||||
}
|
||||
if (pluginId != -1) {
|
||||
addPreferencesFromResource(pluginId, rootKey)
|
||||
} else {
|
||||
addPreferencesFromResource(R.xml.pref_general, rootKey)
|
||||
addPreferencesFromResource(R.xml.pref_overview, rootKey)
|
||||
addPreferencesFromResourceIfEnabled(safetyPlugin, rootKey)
|
||||
addPreferencesFromResourceIfEnabled(eversensePlugin, rootKey)
|
||||
addPreferencesFromResourceIfEnabled(dexcomPlugin, rootKey)
|
||||
addPreferencesFromResourceIfEnabled(tomatoPlugin, rootKey)
|
||||
addPreferencesFromResourceIfEnabled(poctechPlugin, rootKey)
|
||||
addPreferencesFromResourceIfEnabled(glimpPlugin, rootKey)
|
||||
addPreferencesFromResourceIfEnabled(loopPlugin, rootKey, config.APS)
|
||||
addPreferencesFromResourceIfEnabled(openAPSAMAPlugin, rootKey, config.APS)
|
||||
addPreferencesFromResourceIfEnabled(openAPSSMBPlugin, rootKey, config.APS)
|
||||
addPreferencesFromResourceIfEnabled(sensitivityAAPSPlugin, rootKey)
|
||||
addPreferencesFromResourceIfEnabled(sensitivityWeightedAveragePlugin, rootKey)
|
||||
addPreferencesFromResourceIfEnabled(sensitivityOref1Plugin, rootKey)
|
||||
addPreferencesFromResourceIfEnabled(danaRPlugin, rootKey, config.PUMPDRIVERS)
|
||||
addPreferencesFromResourceIfEnabled(danaRKoreanPlugin, rootKey, config.PUMPDRIVERS)
|
||||
addPreferencesFromResourceIfEnabled(danaRv2Plugin, rootKey, config.PUMPDRIVERS)
|
||||
addPreferencesFromResourceIfEnabled(danaRSPlugin, rootKey, config.PUMPDRIVERS)
|
||||
addPreferencesFromResourceIfEnabled(localInsightPlugin, rootKey, config.PUMPDRIVERS)
|
||||
addPreferencesFromResourceIfEnabled(comboPlugin, rootKey, config.PUMPDRIVERS)
|
||||
addPreferencesFromResourceIfEnabled(medtronicPumpPlugin, rootKey, config.PUMPDRIVERS)
|
||||
addPreferencesFromResourceIfEnabled(virtualPumpPlugin, rootKey, !config.NSCLIENT)
|
||||
addPreferencesFromResourceIfEnabled(insulinOrefFreePeakPlugin, rootKey)
|
||||
addPreferencesFromResourceIfEnabled(nsClientPlugin, rootKey)
|
||||
addPreferencesFromResourceIfEnabled(tidepoolPlugin, rootKey)
|
||||
addPreferencesFromResourceIfEnabled(smsCommunicatorPlugin, rootKey)
|
||||
addPreferencesFromResourceIfEnabled(automationPlugin, rootKey)
|
||||
addPreferencesFromResourceIfEnabled(wearPlugin, rootKey)
|
||||
addPreferencesFromResourceIfEnabled(statusLinePlugin, rootKey)
|
||||
addPreferencesFromResource(R.xml.pref_alerts, rootKey) // TODO not organized well
|
||||
addPreferencesFromResource(R.xml.pref_datachoices, rootKey)
|
||||
addPreferencesFromResourceIfEnabled(maintenancePlugin, rootKey)
|
||||
addPreferencesFromResourceIfEnabled(openHumansUploader, rootKey)
|
||||
}
|
||||
initSummary(preferenceScreen, pluginId != -1)
|
||||
preprocessPreferences()
|
||||
}
|
||||
|
||||
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) {
|
||||
rxBus.send(EventPreferenceChange(key))
|
||||
if (key == resourceHelper.gs(R.string.key_language)) {
|
||||
rxBus.send(EventRebuildTabs(true))
|
||||
//recreate() does not update language so better close settings
|
||||
activity?.finish()
|
||||
}
|
||||
if (key == resourceHelper.gs(R.string.key_short_tabtitles)) {
|
||||
rxBus.send(EventRebuildTabs())
|
||||
}
|
||||
if (key == resourceHelper.gs(R.string.key_units)) {
|
||||
activity?.recreate()
|
||||
return
|
||||
}
|
||||
if (key == resourceHelper.gs(R.string.key_openapsama_useautosens) && sp.getBoolean(R.string.key_openapsama_useautosens, false)) {
|
||||
activity?.let {
|
||||
show(it, resourceHelper.gs(R.string.configbuilder_sensitivity), resourceHelper.gs(R.string.sensitivity_warning))
|
||||
}
|
||||
}
|
||||
checkForBiometricFallback(key)
|
||||
|
||||
updatePrefSummary(findPreference(key))
|
||||
preprocessPreferences()
|
||||
}
|
||||
|
||||
private fun preprocessPreferences() {
|
||||
for (plugin in pluginStore.plugins) {
|
||||
plugin.preprocessPreferences(this)
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkForBiometricFallback(key: String) {
|
||||
// Biometric protection activated without set master password
|
||||
if ((resourceHelper.gs(R.string.key_settings_protection) == key ||
|
||||
resourceHelper.gs(R.string.key_application_protection) == key ||
|
||||
resourceHelper.gs(R.string.key_bolus_protection) == key) &&
|
||||
sp.getString(R.string.key_master_password, "") == "" &&
|
||||
sp.getInt(key, ProtectionCheck.ProtectionType.NONE.ordinal) == ProtectionCheck.ProtectionType.BIOMETRIC.ordinal
|
||||
) {
|
||||
activity?.let {
|
||||
val title = resourceHelper.gs(R.string.unsecure_fallback_biometric)
|
||||
val message = resourceHelper.gs(R.string.master_password_missing, resourceHelper.gs(R.string.configbuilder_general), resourceHelper.gs(R.string.protection))
|
||||
show(it, title = title, message = message)
|
||||
}
|
||||
}
|
||||
|
||||
// Master password erased with activated Biometric protection
|
||||
val isBiometricActivated = sp.getInt(R.string.key_settings_protection, ProtectionCheck.ProtectionType.NONE.ordinal) == ProtectionCheck.ProtectionType.BIOMETRIC.ordinal ||
|
||||
sp.getInt(R.string.key_application_protection, ProtectionCheck.ProtectionType.NONE.ordinal) == ProtectionCheck.ProtectionType.BIOMETRIC.ordinal ||
|
||||
sp.getInt(R.string.key_bolus_protection, ProtectionCheck.ProtectionType.NONE.ordinal) == ProtectionCheck.ProtectionType.BIOMETRIC.ordinal
|
||||
if (resourceHelper.gs(R.string.key_master_password) == key && sp.getString(key, "") == "" && isBiometricActivated) {
|
||||
activity?.let {
|
||||
val title = resourceHelper.gs(R.string.unsecure_fallback_biometric)
|
||||
val message = resourceHelper.gs(R.string.unsecure_fallback_descriotion_biometric)
|
||||
show(it, title = title, message = message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("RestrictedApi")
|
||||
private fun addPreferencesFromResource(@XmlRes preferencesResId: Int, key: String?) {
|
||||
val xmlRoot = preferenceManager.inflateFromResource(context,
|
||||
preferencesResId, null)
|
||||
val root: Preference?
|
||||
if (key != null) {
|
||||
root = xmlRoot.findPreference(key)
|
||||
if (root == null) return
|
||||
require(root is PreferenceScreen) {
|
||||
("Preference object with key " + key
|
||||
+ " is not a PreferenceScreen")
|
||||
}
|
||||
preferenceScreen = root
|
||||
} else {
|
||||
addPreferencesFromResource(preferencesResId)
|
||||
}
|
||||
}
|
||||
|
||||
private fun adjustUnitDependentPrefs(pref: Preference) { // convert preferences values to current units
|
||||
val unitDependent = arrayOf(
|
||||
resourceHelper.gs(R.string.key_hypo_target),
|
||||
resourceHelper.gs(R.string.key_activity_target),
|
||||
resourceHelper.gs(R.string.key_eatingsoon_target),
|
||||
resourceHelper.gs(R.string.key_high_mark),
|
||||
resourceHelper.gs(R.string.key_low_mark)
|
||||
)
|
||||
if (unitDependent.toList().contains(pref.key) && pref is EditTextPreference) {
|
||||
val converted = Profile.toCurrentUnits(profileFunction, SafeParse.stringToDouble(pref.text))
|
||||
pref.summary = converted.toString()
|
||||
}
|
||||
}
|
||||
|
||||
private fun updatePrefSummary(pref: Preference?) {
|
||||
if (pref is ListPreference) {
|
||||
pref.setSummary(pref.entry)
|
||||
// Preferences
|
||||
// Preferences
|
||||
if (pref.getKey() == resourceHelper.gs(R.string.key_settings_protection)) {
|
||||
val pass: Preference? = findPreference(resourceHelper.gs(R.string.key_settings_password))
|
||||
if (pass != null) pass.isEnabled = pref.value == ProtectionCheck.ProtectionType.CUSTOM_PASSWORD.ordinal.toString()
|
||||
}
|
||||
// Application
|
||||
// Application
|
||||
if (pref.getKey() == resourceHelper.gs(R.string.key_application_protection)) {
|
||||
val pass: Preference? = findPreference(resourceHelper.gs(R.string.key_application_password))
|
||||
if (pass != null) pass.isEnabled = pref.value == ProtectionCheck.ProtectionType.CUSTOM_PASSWORD.ordinal.toString()
|
||||
}
|
||||
// Bolus
|
||||
// Bolus
|
||||
if (pref.getKey() == resourceHelper.gs(R.string.key_bolus_protection)) {
|
||||
val pass: Preference? = findPreference(resourceHelper.gs(R.string.key_bolus_password))
|
||||
if (pass != null) pass.isEnabled = pref.value == ProtectionCheck.ProtectionType.CUSTOM_PASSWORD.ordinal.toString()
|
||||
}
|
||||
}
|
||||
if (pref is EditTextPreference) {
|
||||
if (pref.getKey().contains("password") || pref.getKey().contains("secret")) {
|
||||
pref.setSummary("******")
|
||||
} else if (pref.text != null) {
|
||||
pref.dialogMessage = pref.dialogMessage
|
||||
pref.setSummary(pref.text)
|
||||
}
|
||||
}
|
||||
|
||||
for (plugin in pluginStore.plugins) {
|
||||
pref?.let { it.key?.let { plugin.updatePreferenceSummary(pref) } }
|
||||
}
|
||||
|
||||
val hmacPasswords = arrayOf(
|
||||
resourceHelper.gs(R.string.key_bolus_password),
|
||||
resourceHelper.gs(R.string.key_master_password),
|
||||
resourceHelper.gs(R.string.key_application_password),
|
||||
resourceHelper.gs(R.string.key_settings_password)
|
||||
)
|
||||
|
||||
if (pref is Preference) {
|
||||
if ((pref.key != null) && (hmacPasswords.contains(pref.key))) {
|
||||
if (sp.getString(pref.key, "").startsWith("hmac:")) {
|
||||
pref.summary = "******"
|
||||
} else {
|
||||
pref.summary = resourceHelper.gs(R.string.password_not_set)
|
||||
}
|
||||
}
|
||||
}
|
||||
pref?.let { adjustUnitDependentPrefs(it) }
|
||||
}
|
||||
|
||||
private fun initSummary(p: Preference, isSinglePreference: Boolean) {
|
||||
p.isIconSpaceReserved = false // remove extra spacing on left after migration to androidx
|
||||
// expand single plugin preference by default
|
||||
if (p is PreferenceScreen && isSinglePreference) {
|
||||
if (p.size > 0 && p.getPreference(0) is PreferenceCategory)
|
||||
(p.getPreference(0) as PreferenceCategory).initialExpandedChildrenCount = Int.MAX_VALUE
|
||||
}
|
||||
if (p is PreferenceGroup) {
|
||||
for (i in 0 until p.preferenceCount) {
|
||||
initSummary(p.getPreference(i), isSinglePreference)
|
||||
}
|
||||
} else {
|
||||
updatePrefSummary(p)
|
||||
}
|
||||
}
|
||||
|
||||
// We use Preference and custom editor instead of EditTextPreference
|
||||
// to hash password while it is saved and never have to show it, even hashed
|
||||
|
||||
override fun onPreferenceTreeClick(preference: Preference?): Boolean {
|
||||
context?.let { context ->
|
||||
if (preference != null) {
|
||||
if (preference.key == resourceHelper.gs(R.string.key_master_password)) {
|
||||
passwordCheck.queryPassword(context, R.string.current_master_password, R.string.key_master_password, {
|
||||
passwordCheck.setPassword(context, R.string.master_password, R.string.key_master_password)
|
||||
})
|
||||
return true
|
||||
}
|
||||
if (preference.key == resourceHelper.gs(R.string.key_settings_password)) {
|
||||
passwordCheck.setPassword(context, R.string.settings_password, R.string.key_settings_password)
|
||||
return true
|
||||
}
|
||||
if (preference.key == resourceHelper.gs(R.string.key_bolus_password)) {
|
||||
passwordCheck.setPassword(context, R.string.bolus_password, R.string.key_bolus_password)
|
||||
return true
|
||||
}
|
||||
if (preference.key == resourceHelper.gs(R.string.key_application_password)) {
|
||||
passwordCheck.setPassword(context, R.string.application_password, R.string.key_application_password)
|
||||
return true
|
||||
}
|
||||
// NSClient copy settings
|
||||
if (preference.key == resourceHelper.gs(R.string.key_statuslights_copy_ns)) {
|
||||
nsSettingStatus.copyStatusLightsNsSettings(context)
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.onPreferenceTreeClick(preference)
|
||||
}
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
package info.nightscout.androidaps.activities
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.utils.LocaleHelper
|
||||
|
||||
open class NoSplashAppCompatActivity : AppCompatActivity() {
|
||||
public override fun onCreate(savedInstanceState: Bundle?) {
|
||||
setTheme(R.style.AppTheme_NoActionBar)
|
||||
super.onCreate(savedInstanceState)
|
||||
}
|
||||
|
||||
public override fun attachBaseContext(newBase: Context) {
|
||||
super.attachBaseContext(LocaleHelper.wrap(newBase))
|
||||
}
|
||||
}
|
|
@ -1,250 +0,0 @@
|
|||
package info.nightscout.androidaps.activities;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.preference.EditTextPreference;
|
||||
import android.preference.ListPreference;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceActivity;
|
||||
import android.preference.PreferenceFragment;
|
||||
import android.preference.PreferenceGroup;
|
||||
import android.preference.PreferenceManager;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.data.Profile;
|
||||
import info.nightscout.androidaps.events.EventPreferenceChange;
|
||||
import info.nightscout.androidaps.events.EventRebuildTabs;
|
||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||
import info.nightscout.androidaps.interfaces.PluginType;
|
||||
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin;
|
||||
import info.nightscout.androidaps.plugins.aps.openAPSAMA.OpenAPSAMAPlugin;
|
||||
import info.nightscout.androidaps.plugins.aps.openAPSMA.OpenAPSMAPlugin;
|
||||
import info.nightscout.androidaps.plugins.aps.openAPSSMB.OpenAPSSMBPlugin;
|
||||
import info.nightscout.androidaps.plugins.bus.RxBus;
|
||||
import info.nightscout.androidaps.plugins.constraints.safety.SafetyPlugin;
|
||||
import info.nightscout.androidaps.plugins.general.automation.AutomationPlugin;
|
||||
import info.nightscout.androidaps.plugins.general.careportal.CareportalPlugin;
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.NSClientPlugin;
|
||||
import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin;
|
||||
import info.nightscout.androidaps.plugins.general.tidepool.TidepoolPlugin;
|
||||
import info.nightscout.androidaps.plugins.general.wear.WearPlugin;
|
||||
import info.nightscout.androidaps.plugins.general.xdripStatusline.StatuslinePlugin;
|
||||
import info.nightscout.androidaps.plugins.insulin.InsulinOrefFreePeakPlugin;
|
||||
import info.nightscout.androidaps.plugins.pump.combo.ComboPlugin;
|
||||
import info.nightscout.androidaps.plugins.pump.danaR.DanaRPlugin;
|
||||
import info.nightscout.androidaps.plugins.pump.danaRKorean.DanaRKoreanPlugin;
|
||||
import info.nightscout.androidaps.plugins.pump.danaRS.DanaRSPlugin;
|
||||
import info.nightscout.androidaps.plugins.pump.danaRv2.DanaRv2Plugin;
|
||||
import info.nightscout.androidaps.plugins.pump.insight.LocalInsightPlugin;
|
||||
import info.nightscout.androidaps.plugins.pump.medtronic.MedtronicPumpPlugin;
|
||||
import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin;
|
||||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityAAPSPlugin;
|
||||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref0Plugin;
|
||||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin;
|
||||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAveragePlugin;
|
||||
import info.nightscout.androidaps.plugins.source.SourceDexcomPlugin;
|
||||
import info.nightscout.androidaps.utils.LocaleHelper;
|
||||
import info.nightscout.androidaps.utils.OKDialog;
|
||||
import info.nightscout.androidaps.utils.SP;
|
||||
import info.nightscout.androidaps.utils.SafeParse;
|
||||
|
||||
public class PreferencesActivity extends PreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
MyPreferenceFragment myPreferenceFragment;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
setTheme(R.style.AppTheme_NoActionBar);
|
||||
super.onCreate(savedInstanceState);
|
||||
myPreferenceFragment = new MyPreferenceFragment();
|
||||
Bundle args = new Bundle();
|
||||
args.putInt("id", getIntent().getIntExtra("id", -1));
|
||||
myPreferenceFragment.setArguments(args);
|
||||
getFragmentManager().beginTransaction().replace(android.R.id.content, myPreferenceFragment).commit();
|
||||
PreferenceManager.getDefaultSharedPreferences(this).registerOnSharedPreferenceChangeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
PreferenceManager.getDefaultSharedPreferences(this).unregisterOnSharedPreferenceChangeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attachBaseContext(Context newBase) {
|
||||
super.attachBaseContext(LocaleHelper.INSTANCE.wrap(newBase));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
||||
RxBus.INSTANCE.send(new EventPreferenceChange(key));
|
||||
if (key.equals(MainApp.gs(R.string.key_language))) {
|
||||
RxBus.INSTANCE.send(new EventRebuildTabs(true));
|
||||
//recreate() does not update language so better close settings
|
||||
finish();
|
||||
}
|
||||
if (key.equals(MainApp.gs(R.string.key_short_tabtitles))) {
|
||||
RxBus.INSTANCE.send(new EventRebuildTabs());
|
||||
}
|
||||
if (key.equals(MainApp.gs(R.string.key_units))) {
|
||||
recreate();
|
||||
return;
|
||||
}
|
||||
if (key.equals(MainApp.gs(R.string.key_openapsama_useautosens)) && SP.getBoolean(R.string.key_openapsama_useautosens, false)) {
|
||||
OKDialog.show(this, MainApp.gs(R.string.configbuilder_sensitivity), MainApp.gs(R.string.sensitivity_warning));
|
||||
}
|
||||
updatePrefSummary(myPreferenceFragment.findPreference(key));
|
||||
}
|
||||
|
||||
private static void adjustUnitDependentPrefs(Preference pref) {
|
||||
// convert preferences values to current units
|
||||
String[] unitDependent = new String[]{
|
||||
MainApp.gs(R.string.key_hypo_target),
|
||||
MainApp.gs(R.string.key_activity_target),
|
||||
MainApp.gs(R.string.key_eatingsoon_target),
|
||||
MainApp.gs(R.string.key_high_mark),
|
||||
MainApp.gs(R.string.key_low_mark)
|
||||
};
|
||||
if (Arrays.asList(unitDependent).contains(pref.getKey())) {
|
||||
EditTextPreference editTextPref = (EditTextPreference) pref;
|
||||
String converted = Profile.toCurrentUnitsString(SafeParse.stringToDouble(editTextPref.getText()));
|
||||
editTextPref.setSummary(converted);
|
||||
editTextPref.setText(converted);
|
||||
}
|
||||
}
|
||||
|
||||
private static void updatePrefSummary(Preference pref) {
|
||||
if (pref instanceof ListPreference) {
|
||||
ListPreference listPref = (ListPreference) pref;
|
||||
pref.setSummary(listPref.getEntry());
|
||||
}
|
||||
if (pref instanceof EditTextPreference) {
|
||||
EditTextPreference editTextPref = (EditTextPreference) pref;
|
||||
if (pref.getKey().contains("password") || pref.getKey().contains("secret")) {
|
||||
pref.setSummary("******");
|
||||
} else if (editTextPref.getText() != null) {
|
||||
((EditTextPreference) pref).setDialogMessage(editTextPref.getDialogMessage());
|
||||
pref.setSummary(editTextPref.getText());
|
||||
} else {
|
||||
for (PluginBase plugin : MainApp.getPluginsList()) {
|
||||
plugin.updatePreferenceSummary(pref);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pref != null)
|
||||
adjustUnitDependentPrefs(pref);
|
||||
}
|
||||
|
||||
public static void initSummary(Preference p) {
|
||||
if (p instanceof PreferenceGroup) {
|
||||
PreferenceGroup pGrp = (PreferenceGroup) p;
|
||||
for (int i = 0; i < pGrp.getPreferenceCount(); i++) {
|
||||
initSummary(pGrp.getPreference(i));
|
||||
}
|
||||
} else {
|
||||
updatePrefSummary(p);
|
||||
}
|
||||
}
|
||||
|
||||
public static class MyPreferenceFragment extends PreferenceFragment {
|
||||
private Integer id;
|
||||
|
||||
@Override
|
||||
public void setArguments(Bundle args) {
|
||||
super.setArguments(args);
|
||||
id = args.getInt("id");
|
||||
}
|
||||
|
||||
void addPreferencesFromResourceIfEnabled(PluginBase p, PluginType type) {
|
||||
if (p.isEnabled(type) && p.getPreferencesId() != -1)
|
||||
addPreferencesFromResource(p.getPreferencesId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
if (savedInstanceState != null && savedInstanceState.containsKey("id")) {
|
||||
id = savedInstanceState.getInt("id");
|
||||
}
|
||||
|
||||
if (id != -1) {
|
||||
addPreferencesFromResource(id);
|
||||
} else {
|
||||
|
||||
if (!Config.NSCLIENT) {
|
||||
addPreferencesFromResource(R.xml.pref_password);
|
||||
}
|
||||
addPreferencesFromResource(R.xml.pref_general);
|
||||
addPreferencesFromResource(R.xml.pref_age);
|
||||
|
||||
addPreferencesFromResource(R.xml.pref_overview);
|
||||
|
||||
addPreferencesFromResourceIfEnabled(SourceDexcomPlugin.INSTANCE, PluginType.BGSOURCE);
|
||||
addPreferencesFromResourceIfEnabled(CareportalPlugin.getPlugin(), PluginType.GENERAL);
|
||||
addPreferencesFromResourceIfEnabled(SafetyPlugin.getPlugin(), PluginType.CONSTRAINTS);
|
||||
if (Config.APS) {
|
||||
addPreferencesFromResourceIfEnabled(LoopPlugin.getPlugin(), PluginType.LOOP);
|
||||
addPreferencesFromResourceIfEnabled(OpenAPSMAPlugin.getPlugin(), PluginType.APS);
|
||||
addPreferencesFromResourceIfEnabled(OpenAPSAMAPlugin.getPlugin(), PluginType.APS);
|
||||
addPreferencesFromResourceIfEnabled(OpenAPSSMBPlugin.getPlugin(), PluginType.APS);
|
||||
}
|
||||
|
||||
addPreferencesFromResourceIfEnabled(SensitivityAAPSPlugin.getPlugin(), PluginType.SENSITIVITY);
|
||||
addPreferencesFromResourceIfEnabled(SensitivityWeightedAveragePlugin.getPlugin(), PluginType.SENSITIVITY);
|
||||
addPreferencesFromResourceIfEnabled(SensitivityOref0Plugin.getPlugin(), PluginType.SENSITIVITY);
|
||||
addPreferencesFromResourceIfEnabled(SensitivityOref1Plugin.getPlugin(), PluginType.SENSITIVITY);
|
||||
|
||||
if (Config.PUMPDRIVERS) {
|
||||
addPreferencesFromResourceIfEnabled(DanaRPlugin.getPlugin(), PluginType.PUMP);
|
||||
addPreferencesFromResourceIfEnabled(DanaRKoreanPlugin.getPlugin(), PluginType.PUMP);
|
||||
addPreferencesFromResourceIfEnabled(DanaRv2Plugin.getPlugin(), PluginType.PUMP);
|
||||
addPreferencesFromResourceIfEnabled(DanaRSPlugin.getPlugin(), PluginType.PUMP);
|
||||
addPreferencesFromResourceIfEnabled(LocalInsightPlugin.getPlugin(), PluginType.PUMP);
|
||||
addPreferencesFromResourceIfEnabled(ComboPlugin.getPlugin(), PluginType.PUMP);
|
||||
addPreferencesFromResourceIfEnabled(MedtronicPumpPlugin.getPlugin(), PluginType.PUMP);
|
||||
|
||||
if (DanaRPlugin.getPlugin().isEnabled(PluginType.PROFILE)
|
||||
|| DanaRKoreanPlugin.getPlugin().isEnabled(PluginType.PROFILE)
|
||||
|| DanaRv2Plugin.getPlugin().isEnabled(PluginType.PROFILE)
|
||||
|| DanaRSPlugin.getPlugin().isEnabled(PluginType.PROFILE)) {
|
||||
addPreferencesFromResource(R.xml.pref_danarprofile);
|
||||
}
|
||||
}
|
||||
|
||||
if (!Config.NSCLIENT) {
|
||||
addPreferencesFromResourceIfEnabled(VirtualPumpPlugin.getPlugin(), PluginType.PUMP);
|
||||
}
|
||||
|
||||
addPreferencesFromResourceIfEnabled(InsulinOrefFreePeakPlugin.getPlugin(), PluginType.INSULIN);
|
||||
|
||||
addPreferencesFromResourceIfEnabled(NSClientPlugin.getPlugin(), PluginType.GENERAL);
|
||||
addPreferencesFromResourceIfEnabled(TidepoolPlugin.INSTANCE, PluginType.GENERAL);
|
||||
addPreferencesFromResourceIfEnabled(SmsCommunicatorPlugin.INSTANCE, PluginType.GENERAL);
|
||||
addPreferencesFromResourceIfEnabled(AutomationPlugin.INSTANCE, PluginType.GENERAL);
|
||||
|
||||
addPreferencesFromResource(R.xml.pref_others);
|
||||
addPreferencesFromResource(R.xml.pref_datachoices);
|
||||
|
||||
addPreferencesFromResourceIfEnabled(WearPlugin.getPlugin(), PluginType.GENERAL);
|
||||
addPreferencesFromResourceIfEnabled(StatuslinePlugin.getPlugin(), PluginType.GENERAL);
|
||||
}
|
||||
|
||||
initSummary(getPreferenceScreen());
|
||||
|
||||
for (PluginBase plugin : MainApp.getPluginsList()) {
|
||||
plugin.preprocessPreferences(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putInt("id", id);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
package info.nightscout.androidaps.activities
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import androidx.preference.PreferenceFragmentCompat
|
||||
import androidx.preference.PreferenceScreen
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.utils.locale.LocaleHelper
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import javax.inject.Inject
|
||||
|
||||
class PreferencesActivity : NoSplashAppCompatActivity(), PreferenceFragmentCompat.OnPreferenceStartScreenCallback {
|
||||
|
||||
@Inject lateinit var resourceHelper: ResourceHelper
|
||||
|
||||
var preferenceId = 0
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_single_fragment)
|
||||
title = resourceHelper.gs(R.string.nav_preferences)
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
supportActionBar?.setDisplayShowHomeEnabled(true)
|
||||
val myPreferenceFragment = MyPreferenceFragment()
|
||||
preferenceId = intent.getIntExtra("id", -1)
|
||||
val args = Bundle()
|
||||
args.putInt("id", preferenceId)
|
||||
myPreferenceFragment.arguments = args
|
||||
supportFragmentManager.beginTransaction().replace(R.id.frame_layout, myPreferenceFragment).commit()
|
||||
}
|
||||
|
||||
override fun onPreferenceStartScreen(caller: PreferenceFragmentCompat, pref: PreferenceScreen): Boolean {
|
||||
val fragment = MyPreferenceFragment()
|
||||
val args = Bundle()
|
||||
args.putString(PreferenceFragmentCompat.ARG_PREFERENCE_ROOT, pref.key)
|
||||
args.putInt("id", preferenceId)
|
||||
fragment.arguments = args
|
||||
supportFragmentManager.beginTransaction()
|
||||
.replace(R.id.frame_layout, fragment, pref.key)
|
||||
.addToBackStack(pref.key)
|
||||
.commit()
|
||||
return true
|
||||
}
|
||||
|
||||
override fun attachBaseContext(newBase: Context) {
|
||||
super.attachBaseContext(LocaleHelper.wrap(newBase))
|
||||
}
|
||||
}
|
|
@ -0,0 +1,288 @@
|
|||
package info.nightscout.androidaps.activities
|
||||
|
||||
import android.content.res.ColorStateList
|
||||
import android.os.Bundle
|
||||
import android.text.Editable
|
||||
import android.text.TextWatcher
|
||||
import android.view.Menu
|
||||
import android.widget.PopupMenu
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.data.Profile
|
||||
import info.nightscout.androidaps.data.defaultProfile.DefaultProfile
|
||||
import info.nightscout.androidaps.data.defaultProfile.DefaultProfileDPV
|
||||
import info.nightscout.androidaps.db.ProfileSwitch
|
||||
import info.nightscout.androidaps.dialogs.ProfileViewerDialog
|
||||
import info.nightscout.androidaps.interfaces.ActivePluginProvider
|
||||
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||
import info.nightscout.androidaps.logging.AAPSLogger
|
||||
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
||||
import info.nightscout.androidaps.plugins.profile.local.LocalProfilePlugin
|
||||
import info.nightscout.androidaps.plugins.profile.local.events.EventLocalProfileChanged
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.T
|
||||
import info.nightscout.androidaps.utils.ToastUtils
|
||||
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
||||
import info.nightscout.androidaps.utils.extensions.toVisibility
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import info.nightscout.androidaps.utils.stats.TddCalculator
|
||||
import kotlinx.android.synthetic.main.activity_profilehelper.*
|
||||
import java.text.DecimalFormat
|
||||
import javax.inject.Inject
|
||||
|
||||
class ProfileHelperActivity : NoSplashAppCompatActivity() {
|
||||
@Inject lateinit var aapsLogger: AAPSLogger
|
||||
@Inject lateinit var resourceHelper: ResourceHelper
|
||||
@Inject lateinit var tddCalculator: TddCalculator
|
||||
@Inject lateinit var profileFunction: ProfileFunction
|
||||
@Inject lateinit var defaultProfile: DefaultProfile
|
||||
@Inject lateinit var defaultProfileDPV: DefaultProfileDPV
|
||||
@Inject lateinit var localProfilePlugin: LocalProfilePlugin
|
||||
@Inject lateinit var rxBus: RxBusWrapper
|
||||
@Inject lateinit var dateUtil: DateUtil
|
||||
@Inject lateinit var activePlugin: ActivePluginProvider
|
||||
@Inject lateinit var databaseHelper: DatabaseHelperInterface
|
||||
|
||||
enum class ProfileType {
|
||||
MOTOL_DEFAULT,
|
||||
DPV_DEFAULT,
|
||||
CURRENT,
|
||||
AVAILABLE_PROFILE,
|
||||
PROFILE_SWITCH
|
||||
}
|
||||
|
||||
private var tabSelected = 0
|
||||
private val typeSelected = arrayOf(ProfileType.MOTOL_DEFAULT, ProfileType.CURRENT)
|
||||
|
||||
private val ageUsed = arrayOf(15.0, 15.0)
|
||||
private val weightUsed = arrayOf(0.0, 0.0)
|
||||
private val tddUsed = arrayOf(0.0, 0.0)
|
||||
private val pctUsed = arrayOf(32.0, 32.0)
|
||||
|
||||
private lateinit var profileList: ArrayList<CharSequence>
|
||||
private val profileUsed = arrayOf(0, 0)
|
||||
|
||||
private lateinit var profileSwitch: List<ProfileSwitch>
|
||||
private val profileSwitchUsed = arrayOf(0, 0)
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_profilehelper)
|
||||
|
||||
profilehelper_menu1.setOnClickListener {
|
||||
switchTab(0, typeSelected[0])
|
||||
}
|
||||
profilehelper_menu2.setOnClickListener {
|
||||
switchTab(1, typeSelected[1])
|
||||
}
|
||||
|
||||
profilehelper_profiletype.setOnClickListener {
|
||||
PopupMenu(this, profilehelper_profiletype).apply {
|
||||
menuInflater.inflate(R.menu.menu_profilehelper, menu)
|
||||
setOnMenuItemClickListener { item ->
|
||||
profilehelper_profiletype.setText(item.title)
|
||||
when (item.itemId) {
|
||||
R.id.menu_default -> switchTab(tabSelected, ProfileType.MOTOL_DEFAULT)
|
||||
R.id.menu_default_dpv -> switchTab(tabSelected, ProfileType.DPV_DEFAULT)
|
||||
R.id.menu_current -> switchTab(tabSelected, ProfileType.CURRENT)
|
||||
R.id.menu_available -> switchTab(tabSelected, ProfileType.AVAILABLE_PROFILE)
|
||||
R.id.menu_profileswitch -> switchTab(tabSelected, ProfileType.PROFILE_SWITCH)
|
||||
}
|
||||
true
|
||||
}
|
||||
show()
|
||||
}
|
||||
}
|
||||
|
||||
// Active profile
|
||||
profileList = activePlugin.activeProfileInterface.profile?.getProfileList() ?: ArrayList()
|
||||
|
||||
profilehelper_available_profile_list.setOnClickListener {
|
||||
PopupMenu(this, profilehelper_available_profile_list).apply {
|
||||
var order = 0
|
||||
for (name in profileList) menu.add(Menu.NONE, order, order++, name)
|
||||
setOnMenuItemClickListener { item ->
|
||||
profilehelper_available_profile_list.setText(item.title)
|
||||
profileUsed[tabSelected] = item.itemId
|
||||
true
|
||||
}
|
||||
show()
|
||||
}
|
||||
}
|
||||
|
||||
// Profile switch
|
||||
profileSwitch = databaseHelper.getProfileSwitchData(dateUtil._now() - T.months(2).msecs(), true)
|
||||
|
||||
profilehelper_profileswitch_list.setOnClickListener {
|
||||
PopupMenu(this, profilehelper_profileswitch_list).apply {
|
||||
var order = 0
|
||||
for (name in profileSwitch) menu.add(Menu.NONE, order, order++, name.customizedName)
|
||||
setOnMenuItemClickListener { item ->
|
||||
profilehelper_profileswitch_list.setText(item.title)
|
||||
profileSwitchUsed[tabSelected] = item.itemId
|
||||
true
|
||||
}
|
||||
show()
|
||||
}
|
||||
}
|
||||
|
||||
// Default profile
|
||||
profilehelper_copytolocalprofile.setOnClickListener {
|
||||
val age = ageUsed[tabSelected]
|
||||
val weight = weightUsed[tabSelected]
|
||||
val tdd = tddUsed[tabSelected]
|
||||
val pct = pctUsed[tabSelected]
|
||||
val profile = if (typeSelected[tabSelected] == ProfileType.MOTOL_DEFAULT) defaultProfile.profile(age, tdd, weight, profileFunction.getUnits())
|
||||
else defaultProfileDPV.profile(age, tdd, pct / 100.0, profileFunction.getUnits())
|
||||
profile?.let {
|
||||
OKDialog.showConfirmation(this, resourceHelper.gs(R.string.careportal_profileswitch), resourceHelper.gs(R.string.copytolocalprofile), Runnable {
|
||||
localProfilePlugin.addProfile(localProfilePlugin.copyFrom(it, "DefaultProfile" + dateUtil.dateAndTimeAndSecondsString(dateUtil._now())))
|
||||
rxBus.send(EventLocalProfileChanged())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
profilehelper_age.setParams(0.0, 1.0, 18.0, 1.0, DecimalFormat("0"), false, null)
|
||||
profilehelper_weight.setParams(0.0, 0.0, 150.0, 1.0, DecimalFormat("0"), false, null, object : TextWatcher {
|
||||
override fun afterTextChanged(s: Editable) {}
|
||||
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
|
||||
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
|
||||
profilehelper_tdd_row.visibility = (profilehelper_weight.value == 0.0).toVisibility()
|
||||
}
|
||||
})
|
||||
profilehelper_tdd.setParams(0.0, 0.0, 200.0, 1.0, DecimalFormat("0"), false, null, object : TextWatcher {
|
||||
override fun afterTextChanged(s: Editable) {}
|
||||
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
|
||||
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
|
||||
profilehelper_weight_row.visibility = (profilehelper_tdd.value == 0.0).toVisibility()
|
||||
}
|
||||
})
|
||||
|
||||
profilehelper_basalpctfromtdd.setParams(32.0, 32.0, 37.0, 1.0, DecimalFormat("0"), false, null)
|
||||
|
||||
profilehelper_tdds.text = tddCalculator.stats()
|
||||
|
||||
// Current profile
|
||||
profilehelper_current_profile_text.text = profileFunction.getProfileName()
|
||||
|
||||
// General
|
||||
profilehelper_compareprofile.setOnClickListener {
|
||||
storeValues()
|
||||
for (i in 0..1) {
|
||||
if (typeSelected[i] == ProfileType.MOTOL_DEFAULT) {
|
||||
if (ageUsed[i] < 1 || ageUsed[i] > 18) {
|
||||
ToastUtils.showToastInUiThread(this, R.string.invalidage)
|
||||
return@setOnClickListener
|
||||
}
|
||||
if ((weightUsed[i] < 5 || weightUsed[i] > 150) && tddUsed[i] == 0.0) {
|
||||
ToastUtils.showToastInUiThread(this, R.string.invalidweight)
|
||||
return@setOnClickListener
|
||||
}
|
||||
if ((tddUsed[i] < 5 || tddUsed[i] > 150) && weightUsed[i] == 0.0) {
|
||||
ToastUtils.showToastInUiThread(this, R.string.invalidweight)
|
||||
return@setOnClickListener
|
||||
}
|
||||
}
|
||||
if (typeSelected[i] == ProfileType.DPV_DEFAULT) {
|
||||
if (ageUsed[i] < 1 || ageUsed[i] > 18) {
|
||||
ToastUtils.showToastInUiThread(this, R.string.invalidage)
|
||||
return@setOnClickListener
|
||||
}
|
||||
if (tddUsed[i] < 5 || tddUsed[i] > 150) {
|
||||
ToastUtils.showToastInUiThread(this, R.string.invalidweight)
|
||||
return@setOnClickListener
|
||||
}
|
||||
if ((pctUsed[i] < 32 || pctUsed[i] > 37)) {
|
||||
ToastUtils.showToastInUiThread(this, R.string.invalidpct)
|
||||
return@setOnClickListener
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getProfile(ageUsed[0], tddUsed[0], weightUsed[0], pctUsed[0] / 100.0, 0)?.let { profile0 ->
|
||||
getProfile(ageUsed[1], tddUsed[1], weightUsed[1], pctUsed[1] / 100.0, 1)?.let { profile1 ->
|
||||
ProfileViewerDialog().also { pvd ->
|
||||
pvd.arguments = Bundle().also {
|
||||
it.putLong("time", DateUtil.now())
|
||||
it.putInt("mode", ProfileViewerDialog.Mode.PROFILE_COMPARE.ordinal)
|
||||
it.putString("customProfile", profile0.data.toString())
|
||||
it.putString("customProfile2", profile1.data.toString())
|
||||
it.putString("customProfileUnits", profileFunction.getUnits())
|
||||
it.putString("customProfileName", getProfileName(ageUsed[0], tddUsed[0], weightUsed[0], pctUsed[0] / 100.0, 0) + "\n" + getProfileName(ageUsed[1], tddUsed[1], weightUsed[1], pctUsed[1] / 100.0, 1))
|
||||
}
|
||||
}.show(supportFragmentManager, "ProfileViewDialog")
|
||||
return@setOnClickListener
|
||||
}
|
||||
}
|
||||
ToastUtils.showToastInUiThread(this, R.string.invalidinput)
|
||||
}
|
||||
|
||||
switchTab(0, typeSelected[0], false)
|
||||
}
|
||||
|
||||
private fun getProfile(age: Double, tdd: Double, weight: Double, basalPct: Double, tab: Int): Profile? =
|
||||
when (typeSelected[tab]) {
|
||||
ProfileType.MOTOL_DEFAULT -> defaultProfile.profile(age, tdd, weight, profileFunction.getUnits())
|
||||
ProfileType.DPV_DEFAULT -> defaultProfileDPV.profile(age, tdd, basalPct, profileFunction.getUnits())
|
||||
ProfileType.CURRENT -> profileFunction.getProfile()?.convertToNonCustomizedProfile()
|
||||
ProfileType.AVAILABLE_PROFILE -> activePlugin.activeProfileInterface.profile?.getSpecificProfile(profileList[profileUsed[tab]].toString())
|
||||
ProfileType.PROFILE_SWITCH -> profileSwitch[profileSwitchUsed[tab]].profileObject?.convertToNonCustomizedProfile()
|
||||
}
|
||||
|
||||
private fun getProfileName(age: Double, tdd: Double, weight: Double, basalSumPct: Double, tab: Int): String =
|
||||
when (typeSelected[tab]) {
|
||||
ProfileType.MOTOL_DEFAULT -> if (tdd > 0) resourceHelper.gs(R.string.formatwithtdd, age, tdd) else resourceHelper.gs(R.string.formatwithweight, age, weight)
|
||||
ProfileType.DPV_DEFAULT -> resourceHelper.gs(R.string.formatwittddandpct, age, tdd, (basalSumPct * 100).toInt())
|
||||
ProfileType.CURRENT -> profileFunction.getProfileName()
|
||||
ProfileType.AVAILABLE_PROFILE -> profileList[profileUsed[tab]].toString()
|
||||
ProfileType.PROFILE_SWITCH -> profileSwitch[profileSwitchUsed[tab]].customizedName
|
||||
}
|
||||
|
||||
private fun storeValues() {
|
||||
ageUsed[tabSelected] = profilehelper_age.value
|
||||
weightUsed[tabSelected] = profilehelper_weight.value
|
||||
tddUsed[tabSelected] = profilehelper_tdd.value
|
||||
pctUsed[tabSelected] = profilehelper_basalpctfromtdd.value
|
||||
}
|
||||
|
||||
private fun switchTab(tab: Int, newContent: ProfileType, storeOld: Boolean = true) {
|
||||
setBackgroundColorOnSelected(tab)
|
||||
// Store values for selected tab. listBox values are stored on selection change
|
||||
if (storeOld) storeValues()
|
||||
|
||||
tabSelected = tab
|
||||
typeSelected[tabSelected] = newContent
|
||||
profilehelper_profiletype_title.defaultHintTextColor = ColorStateList.valueOf(resourceHelper.gc(if (tab == 0) R.color.tabBgColorSelected else R.color.examinedProfile))
|
||||
|
||||
// show new content
|
||||
profilehelper_profiletype.setText(
|
||||
when (typeSelected[tabSelected]) {
|
||||
ProfileType.MOTOL_DEFAULT -> resourceHelper.gs(R.string.motoldefaultprofile)
|
||||
ProfileType.DPV_DEFAULT -> resourceHelper.gs(R.string.dpvdefaultprofile)
|
||||
ProfileType.CURRENT -> resourceHelper.gs(R.string.currentprofile)
|
||||
ProfileType.AVAILABLE_PROFILE -> resourceHelper.gs(R.string.availableprofile)
|
||||
ProfileType.PROFILE_SWITCH -> resourceHelper.gs(R.string.careportal_profileswitch)
|
||||
})
|
||||
profilehelper_default_profile.visibility = (newContent == ProfileType.MOTOL_DEFAULT || newContent == ProfileType.DPV_DEFAULT).toVisibility()
|
||||
profilehelper_current_profile.visibility = (newContent == ProfileType.CURRENT).toVisibility()
|
||||
profilehelper_available_profile.visibility = (newContent == ProfileType.AVAILABLE_PROFILE).toVisibility()
|
||||
profilehelper_profile_switch.visibility = (newContent == ProfileType.PROFILE_SWITCH).toVisibility()
|
||||
|
||||
// restore selected values
|
||||
profilehelper_age.value = ageUsed[tabSelected]
|
||||
profilehelper_weight.value = weightUsed[tabSelected]
|
||||
profilehelper_tdd.value = tddUsed[tabSelected]
|
||||
profilehelper_basalpctfromtdd.value = pctUsed[tabSelected]
|
||||
|
||||
profilehelper_basalpctfromtdd_row.visibility = (newContent == ProfileType.DPV_DEFAULT).toVisibility()
|
||||
if (profileList.isNotEmpty())
|
||||
profilehelper_available_profile_list.setText(profileList[profileUsed[tabSelected]].toString())
|
||||
if (profileSwitch.isNotEmpty())
|
||||
profilehelper_profileswitch_list.setText(profileSwitch[profileSwitchUsed[tabSelected]].customizedName)
|
||||
}
|
||||
|
||||
private fun setBackgroundColorOnSelected(tab: Int) {
|
||||
profilehelper_menu1.setBackgroundColor(resourceHelper.gc(if (tab == 1) R.color.defaultbackground else R.color.tabBgColorSelected))
|
||||
profilehelper_menu2.setBackgroundColor(resourceHelper.gc(if (tab == 0) R.color.defaultbackground else R.color.examinedProfile))
|
||||
}
|
||||
}
|
|
@ -1,15 +1,17 @@
|
|||
package info.nightscout.androidaps.activities
|
||||
|
||||
import android.os.Bundle
|
||||
import info.nightscout.androidaps.plugins.source.SourceDexcomPlugin
|
||||
import info.nightscout.androidaps.plugins.source.DexcomPlugin
|
||||
import javax.inject.Inject
|
||||
|
||||
class RequestDexcomPermissionActivity : DialogAppCompatActivity() {
|
||||
@Inject lateinit var dexcomPlugin: DexcomPlugin
|
||||
|
||||
private val requestCode = "AndroidAPS <3".map { it.toInt() }.sum()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
requestPermissions(arrayOf(SourceDexcomPlugin.PERMISSION), requestCode)
|
||||
requestPermissions(arrayOf(DexcomPlugin.PERMISSION), requestCode)
|
||||
}
|
||||
|
||||
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
|
||||
|
|
|
@ -5,19 +5,24 @@ import android.content.Intent
|
|||
import android.os.Bundle
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import info.nightscout.androidaps.MainApp
|
||||
import dagger.android.support.DaggerAppCompatActivity
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.interfaces.PluginBase
|
||||
import info.nightscout.androidaps.utils.LocaleHelper
|
||||
import info.nightscout.androidaps.utils.PasswordProtection
|
||||
import info.nightscout.androidaps.plugins.configBuilder.PluginStore
|
||||
import info.nightscout.androidaps.utils.locale.LocaleHelper
|
||||
import info.nightscout.androidaps.utils.protection.ProtectionCheck
|
||||
import javax.inject.Inject
|
||||
|
||||
class SingleFragmentActivity : DaggerAppCompatActivity() {
|
||||
@Inject lateinit var pluginStore: PluginStore
|
||||
@Inject lateinit var protectionCheck: ProtectionCheck
|
||||
|
||||
class SingleFragmentActivity : AppCompatActivity() {
|
||||
private var plugin: PluginBase? = null
|
||||
|
||||
public override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_single_fragment)
|
||||
plugin = MainApp.getPluginsList()[intent.getIntExtra("plugin", -1)]
|
||||
plugin = pluginStore.plugins[intent.getIntExtra("plugin", -1)]
|
||||
title = plugin?.name
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
supportActionBar?.setDisplayShowHomeEnabled(true)
|
||||
|
@ -32,7 +37,7 @@ class SingleFragmentActivity : AppCompatActivity() {
|
|||
finish()
|
||||
return true
|
||||
} else if (item.itemId == R.id.nav_plugin_preferences) {
|
||||
PasswordProtection.QueryPassword(this, R.string.settings_password, "settings_password", Runnable {
|
||||
protectionCheck.queryProtection(this, ProtectionCheck.Protection.PREFERENCES, Runnable {
|
||||
val i = Intent(this, PreferencesActivity::class.java)
|
||||
i.putExtra("id", plugin?.preferencesId)
|
||||
startActivity(i)
|
||||
|
|
|
@ -1,28 +1,34 @@
|
|||
package info.nightscout.androidaps.activities
|
||||
|
||||
import android.os.Bundle
|
||||
import info.nightscout.androidaps.MainApp
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.utils.ActivityMonitor
|
||||
import info.nightscout.androidaps.utils.OKDialog
|
||||
import info.nightscout.androidaps.utils.TddCalculator
|
||||
import info.nightscout.androidaps.utils.TirCalculator
|
||||
import kotlinx.android.synthetic.main.stats_activity.*
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
||||
import info.nightscout.androidaps.utils.stats.TddCalculator
|
||||
import info.nightscout.androidaps.utils.stats.TirCalculator
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import kotlinx.android.synthetic.main.activity_stats.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class StatsActivity : NoSplashAppCompatActivity() {
|
||||
@Inject lateinit var tddCalculator: TddCalculator
|
||||
@Inject lateinit var tirCalculator: TirCalculator
|
||||
@Inject lateinit var resourceHelper: ResourceHelper
|
||||
@Inject lateinit var activityMonitor: ActivityMonitor
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.stats_activity)
|
||||
setContentView(R.layout.activity_stats)
|
||||
|
||||
stats_tdds.text = TddCalculator.stats()
|
||||
stats_tir.text = TirCalculator.stats()
|
||||
stats_activity.text = ActivityMonitor.stats()
|
||||
stats_tdds.text = tddCalculator.stats()
|
||||
stats_tir.text = tirCalculator.stats()
|
||||
stats_activity.text = activityMonitor.stats()
|
||||
|
||||
ok.setOnClickListener { finish() }
|
||||
stats_reset.setOnClickListener {
|
||||
OKDialog.showConfirmation(this, MainApp.gs(R.string.doyouwantresetstats), Runnable {
|
||||
ActivityMonitor.reset()
|
||||
OKDialog.showConfirmation(this, resourceHelper.gs(R.string.doyouwantresetstats), Runnable {
|
||||
activityMonitor.reset()
|
||||
recreate()
|
||||
})
|
||||
}
|
||||
|
|
|
@ -6,29 +6,45 @@ import com.google.firebase.auth.FirebaseAuth
|
|||
import com.google.firebase.database.FirebaseDatabase
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.data.defaultProfile.DefaultProfile
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions
|
||||
import info.nightscout.androidaps.dialogs.ProfileViewerDialog
|
||||
import info.nightscout.androidaps.utils.*
|
||||
import kotlinx.android.synthetic.main.survey_activity.*
|
||||
import org.slf4j.LoggerFactory
|
||||
import info.nightscout.androidaps.interfaces.ActivePluginProvider
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||
import info.nightscout.androidaps.logging.AAPSLogger
|
||||
import info.nightscout.androidaps.logging.LTag
|
||||
import info.nightscout.androidaps.utils.ActivityMonitor
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.InstanceId
|
||||
import info.nightscout.androidaps.utils.SafeParse
|
||||
import info.nightscout.androidaps.utils.ToastUtils
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import info.nightscout.androidaps.utils.stats.TddCalculator
|
||||
import info.nightscout.androidaps.utils.stats.TirCalculator
|
||||
import kotlinx.android.synthetic.main.activity_survey.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class SurveyActivity : NoSplashAppCompatActivity() {
|
||||
private val log = LoggerFactory.getLogger(SurveyActivity::class.java)
|
||||
@Inject lateinit var aapsLogger: AAPSLogger
|
||||
@Inject lateinit var resourceHelper: ResourceHelper
|
||||
@Inject lateinit var activePlugin: ActivePluginProvider
|
||||
@Inject lateinit var tddCalculator: TddCalculator
|
||||
@Inject lateinit var tirCalculator: TirCalculator
|
||||
@Inject lateinit var profileFunction: ProfileFunction
|
||||
@Inject lateinit var activityMonitor: ActivityMonitor
|
||||
@Inject lateinit var defaultProfile: DefaultProfile
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.survey_activity)
|
||||
setContentView(R.layout.activity_survey)
|
||||
|
||||
survey_id.text = InstanceId.instanceId()
|
||||
|
||||
val profileStore = ConfigBuilderPlugin.getPlugin().activeProfileInterface?.profile
|
||||
val profileStore = activePlugin.activeProfileInterface.profile
|
||||
val profileList = profileStore?.getProfileList() ?: return
|
||||
survey_spinner.adapter = ArrayAdapter(this, R.layout.spinner_centered, profileList)
|
||||
|
||||
survey_tdds.text = TddCalculator.stats()
|
||||
survey_tir.text = TirCalculator.stats()
|
||||
survey_activity.text = ActivityMonitor.stats()
|
||||
survey_tdds.text = tddCalculator.stats()
|
||||
survey_tir.text = tirCalculator.stats()
|
||||
survey_activity.text = activityMonitor.stats()
|
||||
|
||||
survey_profile.setOnClickListener {
|
||||
val age = SafeParse.stringToDouble(survey_age.text.toString())
|
||||
|
@ -46,16 +62,20 @@ class SurveyActivity : NoSplashAppCompatActivity() {
|
|||
ToastUtils.showToastInUiThread(this, R.string.invalidweight)
|
||||
return@setOnClickListener
|
||||
}
|
||||
val profile = DefaultProfile().profile(age, tdd, weight, ProfileFunctions.getSystemUnits())
|
||||
val args = Bundle()
|
||||
args.putLong("time", DateUtil.now())
|
||||
args.putInt("mode", ProfileViewerDialog.Mode.CUSTOM_PROFILE.ordinal)
|
||||
args.putString("customProfile", profile.data.toString())
|
||||
args.putString("customProfileUnits", profile.units)
|
||||
args.putString("customProfileName", "Age: $age TDD: $tdd Weight: $weight")
|
||||
val pvd = ProfileViewerDialog()
|
||||
pvd.arguments = args
|
||||
pvd.show(supportFragmentManager, "ProfileViewDialog")
|
||||
profileFunction.getProfile()?.let { runningProfile ->
|
||||
defaultProfile.profile(age, tdd, weight, profileFunction.getUnits())?.let { profile ->
|
||||
ProfileViewerDialog().also { pvd ->
|
||||
pvd.arguments = Bundle().also {
|
||||
it.putLong("time", DateUtil.now())
|
||||
it.putInt("mode", ProfileViewerDialog.Mode.PROFILE_COMPARE.ordinal)
|
||||
it.putString("customProfile", runningProfile.data.toString())
|
||||
it.putString("customProfile2", profile.data.toString())
|
||||
it.putString("customProfileUnits", profile.units)
|
||||
it.putString("customProfileName", "Age: $age TDD: $tdd Weight: $weight")
|
||||
}
|
||||
}.show(supportFragmentManager, "ProfileViewDialog")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
survey_submit.setOnClickListener {
|
||||
|
@ -83,13 +103,13 @@ class SurveyActivity : NoSplashAppCompatActivity() {
|
|||
auth.signInAnonymously()
|
||||
.addOnCompleteListener(this) { task ->
|
||||
if (task.isSuccessful) {
|
||||
log.debug("signInAnonymously:success")
|
||||
// val user = auth.currentUser // TODO: do we need this, seems unused?
|
||||
aapsLogger.debug(LTag.CORE, "signInAnonymously:success")
|
||||
//val user = auth.currentUser // TODO: do we need this, seems unused?
|
||||
|
||||
val database = FirebaseDatabase.getInstance().reference
|
||||
database.child("survey").child(r.id).setValue(r)
|
||||
} else {
|
||||
log.error("signInAnonymously:failure", task.exception)
|
||||
aapsLogger.error("signInAnonymously:failure", task.exception!!)
|
||||
ToastUtils.showToastInUiThread(this, "Authentication failed.")
|
||||
//updateUI(null)
|
||||
}
|
||||
|
|
|
@ -1,550 +0,0 @@
|
|||
package info.nightscout.androidaps.activities;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TableLayout;
|
||||
import android.widget.TableRow;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.data.Profile;
|
||||
import info.nightscout.androidaps.db.TDD;
|
||||
import info.nightscout.androidaps.events.EventPumpStatusChanged;
|
||||
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||
import info.nightscout.androidaps.plugins.bus.RxBus;
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
|
||||
import info.nightscout.androidaps.plugins.pump.danaR.DanaRPlugin;
|
||||
import info.nightscout.androidaps.plugins.pump.danaR.events.EventDanaRSyncStatus;
|
||||
import info.nightscout.androidaps.plugins.pump.danaRKorean.DanaRKoreanPlugin;
|
||||
import info.nightscout.androidaps.plugins.pump.danaRS.DanaRSPlugin;
|
||||
import info.nightscout.androidaps.plugins.pump.danaRv2.DanaRv2Plugin;
|
||||
import info.nightscout.androidaps.plugins.pump.insight.LocalInsightPlugin;
|
||||
import info.nightscout.androidaps.queue.Callback;
|
||||
import info.nightscout.androidaps.utils.DecimalFormatter;
|
||||
import info.nightscout.androidaps.utils.FabricPrivacy;
|
||||
import info.nightscout.androidaps.utils.SP;
|
||||
import info.nightscout.androidaps.utils.SafeParse;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.disposables.CompositeDisposable;
|
||||
|
||||
public class TDDStatsActivity extends NoSplashAppCompatActivity {
|
||||
private static Logger log = LoggerFactory.getLogger(TDDStatsActivity.class);
|
||||
private CompositeDisposable disposable = new CompositeDisposable();
|
||||
|
||||
TextView statusView, statsMessage, totalBaseBasal2;
|
||||
EditText totalBaseBasal;
|
||||
Button reloadButton;
|
||||
LinearLayoutManager llm;
|
||||
TableLayout tl, ctl, etl;
|
||||
String TBB;
|
||||
double magicNumber;
|
||||
DecimalFormat decimalFormat;
|
||||
|
||||
List<TDD> historyList = new ArrayList<>();
|
||||
List<TDD> dummies;
|
||||
|
||||
public TDDStatsActivity() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
disposable.add(RxBus.INSTANCE
|
||||
.toObservable(EventPumpStatusChanged.class)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(event -> statusView.setText(event.getStatus()), FabricPrivacy::logException)
|
||||
);
|
||||
disposable.add(RxBus.INSTANCE
|
||||
.toObservable(EventDanaRSyncStatus.class)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(event -> {
|
||||
log.debug("EventDanaRSyncStatus: " + event.getMessage());
|
||||
statusView.setText(event.getMessage());
|
||||
}, FabricPrivacy::logException)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
disposable.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchTouchEvent(MotionEvent event) {
|
||||
if (event.getAction() == MotionEvent.ACTION_DOWN) {
|
||||
View myView = getCurrentFocus();
|
||||
if (myView instanceof EditText) {
|
||||
Rect rect = new Rect();
|
||||
myView.getGlobalVisibleRect(rect);
|
||||
if (!rect.contains((int) event.getRawX(), (int) event.getRawY())) {
|
||||
myView.clearFocus();
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.dispatchTouchEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.danar_statsactivity);
|
||||
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
|
||||
statusView = (TextView) findViewById(R.id.danar_stats_connection_status);
|
||||
reloadButton = (Button) findViewById(R.id.danar_statsreload);
|
||||
totalBaseBasal = (EditText) findViewById(R.id.danar_stats_editTotalBaseBasal);
|
||||
totalBaseBasal2 = (TextView) findViewById(R.id.danar_stats_editTotalBaseBasal2);
|
||||
statsMessage = (TextView) findViewById(R.id.danar_stats_Message);
|
||||
|
||||
statusView.setVisibility(View.GONE);
|
||||
statsMessage.setVisibility(View.GONE);
|
||||
|
||||
totalBaseBasal2.setEnabled(false);
|
||||
totalBaseBasal2.setClickable(false);
|
||||
totalBaseBasal2.setFocusable(false);
|
||||
totalBaseBasal2.setInputType(0);
|
||||
|
||||
decimalFormat = new DecimalFormat("0.000");
|
||||
llm = new LinearLayoutManager(this);
|
||||
|
||||
TBB = SP.getString("TBB", "10.00");
|
||||
|
||||
Profile profile = ProfileFunctions.getInstance().getProfile();
|
||||
if (profile != null) {
|
||||
double cppTBB = profile.baseBasalSum();
|
||||
TBB = decimalFormat.format(cppTBB);
|
||||
SP.putString("TBB", TBB);
|
||||
}
|
||||
totalBaseBasal.setText(TBB);
|
||||
|
||||
if (!ConfigBuilderPlugin.getPlugin().getActivePump().getPumpDescription().needsManualTDDLoad)
|
||||
reloadButton.setVisibility(View.GONE);
|
||||
|
||||
// stats table
|
||||
tl = (TableLayout) findViewById(R.id.main_table);
|
||||
TableRow tr_head = new TableRow(this);
|
||||
tr_head.setBackgroundColor(Color.DKGRAY);
|
||||
tr_head.setLayoutParams(new TableLayout.LayoutParams(
|
||||
TableLayout.LayoutParams.MATCH_PARENT,
|
||||
TableLayout.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
TextView label_date = new TextView(this);
|
||||
label_date.setText(MainApp.gs(R.string.danar_stats_date));
|
||||
label_date.setTextColor(Color.WHITE);
|
||||
tr_head.addView(label_date);
|
||||
|
||||
TextView label_basalrate = new TextView(this);
|
||||
label_basalrate.setText(MainApp.gs(R.string.danar_stats_basalrate));
|
||||
label_basalrate.setTextColor(Color.WHITE);
|
||||
tr_head.addView(label_basalrate);
|
||||
|
||||
TextView label_bolus = new TextView(this);
|
||||
label_bolus.setText(MainApp.gs(R.string.danar_stats_bolus));
|
||||
label_bolus.setTextColor(Color.WHITE);
|
||||
tr_head.addView(label_bolus);
|
||||
|
||||
TextView label_tdd = new TextView(this);
|
||||
label_tdd.setText(MainApp.gs(R.string.danar_stats_tdd));
|
||||
label_tdd.setTextColor(Color.WHITE);
|
||||
tr_head.addView(label_tdd);
|
||||
|
||||
TextView label_ratio = new TextView(this);
|
||||
label_ratio.setText(MainApp.gs(R.string.danar_stats_ratio));
|
||||
label_ratio.setTextColor(Color.WHITE);
|
||||
tr_head.addView(label_ratio);
|
||||
|
||||
// add stats headers to tables
|
||||
tl.addView(tr_head, new TableLayout.LayoutParams(
|
||||
TableLayout.LayoutParams.MATCH_PARENT,
|
||||
TableLayout.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
// cumulative table
|
||||
ctl = (TableLayout) findViewById(R.id.cumulative_table);
|
||||
TableRow ctr_head = new TableRow(this);
|
||||
ctr_head.setBackgroundColor(Color.DKGRAY);
|
||||
ctr_head.setLayoutParams(new TableLayout.LayoutParams(
|
||||
TableLayout.LayoutParams.MATCH_PARENT,
|
||||
TableLayout.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
TextView label_cum_amount_days = new TextView(this);
|
||||
label_cum_amount_days.setText(MainApp.gs(R.string.danar_stats_amount_days));
|
||||
label_cum_amount_days.setTextColor(Color.WHITE);
|
||||
ctr_head.addView(label_cum_amount_days);
|
||||
|
||||
TextView label_cum_tdd = new TextView(this);
|
||||
label_cum_tdd.setText(MainApp.gs(R.string.danar_stats_tdd));
|
||||
label_cum_tdd.setTextColor(Color.WHITE);
|
||||
ctr_head.addView(label_cum_tdd);
|
||||
|
||||
TextView label_cum_ratio = new TextView(this);
|
||||
label_cum_ratio.setText(MainApp.gs(R.string.danar_stats_ratio));
|
||||
label_cum_ratio.setTextColor(Color.WHITE);
|
||||
ctr_head.addView(label_cum_ratio);
|
||||
|
||||
// add cummulative headers to tables
|
||||
ctl.addView(ctr_head, new TableLayout.LayoutParams(
|
||||
TableLayout.LayoutParams.MATCH_PARENT,
|
||||
TableLayout.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
// expontial table
|
||||
etl = (TableLayout) findViewById(R.id.expweight_table);
|
||||
TableRow etr_head = new TableRow(this);
|
||||
etr_head.setBackgroundColor(Color.DKGRAY);
|
||||
etr_head.setLayoutParams(new TableLayout.LayoutParams(
|
||||
TableLayout.LayoutParams.MATCH_PARENT,
|
||||
TableLayout.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
TextView label_exp_weight = new TextView(this);
|
||||
label_exp_weight.setText(MainApp.gs(R.string.danar_stats_weight));
|
||||
label_exp_weight.setTextColor(Color.WHITE);
|
||||
etr_head.addView(label_exp_weight);
|
||||
|
||||
TextView label_exp_tdd = new TextView(this);
|
||||
label_exp_tdd.setText(MainApp.gs(R.string.danar_stats_tdd));
|
||||
label_exp_tdd.setTextColor(Color.WHITE);
|
||||
etr_head.addView(label_exp_tdd);
|
||||
|
||||
TextView label_exp_ratio = new TextView(this);
|
||||
label_exp_ratio.setText(MainApp.gs(R.string.danar_stats_ratio));
|
||||
label_exp_ratio.setTextColor(Color.WHITE);
|
||||
etr_head.addView(label_exp_ratio);
|
||||
|
||||
// add expontial headers to tables
|
||||
etl.addView(etr_head, new TableLayout.LayoutParams(
|
||||
TableLayout.LayoutParams.MATCH_PARENT,
|
||||
TableLayout.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
reloadButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
reloadButton.setVisibility(View.GONE);
|
||||
statusView.setVisibility(View.VISIBLE);
|
||||
statsMessage.setVisibility(View.VISIBLE);
|
||||
statsMessage.setText(MainApp.gs(R.string.danar_stats_warning_Message));
|
||||
}
|
||||
});
|
||||
ConfigBuilderPlugin.getPlugin().getCommandQueue().loadTDDs(new Callback() {
|
||||
@Override
|
||||
public void run() {
|
||||
loadDataFromDB();
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
reloadButton.setVisibility(View.VISIBLE);
|
||||
statusView.setVisibility(View.GONE);
|
||||
statsMessage.setVisibility(View.GONE);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
totalBaseBasal.setOnEditorActionListener(new TextView.OnEditorActionListener() {
|
||||
@Override
|
||||
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
|
||||
if (actionId == EditorInfo.IME_ACTION_DONE) {
|
||||
totalBaseBasal.clearFocus();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
totalBaseBasal.setOnFocusChangeListener(new View.OnFocusChangeListener() {
|
||||
@Override
|
||||
public void onFocusChange(View v, boolean hasFocus) {
|
||||
if (hasFocus) {
|
||||
totalBaseBasal.getText().clear();
|
||||
} else {
|
||||
SP.putString("TBB", totalBaseBasal.getText().toString());
|
||||
TBB = SP.getString("TBB", "");
|
||||
loadDataFromDB();
|
||||
InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
|
||||
imm.hideSoftInputFromWindow(totalBaseBasal.getWindowToken(), 0);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
loadDataFromDB();
|
||||
}
|
||||
|
||||
private void loadDataFromDB() {
|
||||
historyList = MainApp.getDbHelper().getTDDs();
|
||||
|
||||
//only use newest 10
|
||||
historyList = historyList.subList(0, Math.min(10, historyList.size()));
|
||||
|
||||
//fill single gaps
|
||||
dummies = new LinkedList();
|
||||
DateFormat df = new SimpleDateFormat("dd.MM.");
|
||||
for (int i = 0; i < historyList.size() - 1; i++) {
|
||||
TDD elem1 = historyList.get(i);
|
||||
TDD elem2 = historyList.get(i + 1);
|
||||
|
||||
if (!df.format(new Date(elem1.date)).equals(df.format(new Date(elem2.date + 25 * 60 * 60 * 1000)))) {
|
||||
TDD dummy = new TDD();
|
||||
dummy.date = elem1.date - 24 * 60 * 60 * 1000;
|
||||
dummy.basal = elem1.basal / 2;
|
||||
dummy.bolus = elem1.bolus / 2;
|
||||
dummies.add(dummy);
|
||||
elem1.basal /= 2;
|
||||
elem1.bolus /= 2;
|
||||
}
|
||||
}
|
||||
historyList.addAll(dummies);
|
||||
Collections.sort(historyList, new Comparator<TDD>() {
|
||||
@Override
|
||||
public int compare(TDD lhs, TDD rhs) {
|
||||
return (int) (rhs.date - lhs.date);
|
||||
}
|
||||
});
|
||||
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
cleanTable(tl);
|
||||
cleanTable(ctl);
|
||||
cleanTable(etl);
|
||||
DateFormat df = new SimpleDateFormat("dd.MM.");
|
||||
|
||||
if (TextUtils.isEmpty(TBB)) {
|
||||
totalBaseBasal.setError("Please Enter Total Base Basal");
|
||||
return;
|
||||
} else {
|
||||
magicNumber = SafeParse.stringToDouble(TBB);
|
||||
}
|
||||
|
||||
magicNumber *= 2;
|
||||
totalBaseBasal2.setText(decimalFormat.format(magicNumber));
|
||||
|
||||
int i = 0;
|
||||
double sum = 0d;
|
||||
double weighted03 = 0d;
|
||||
double weighted05 = 0d;
|
||||
double weighted07 = 0d;
|
||||
|
||||
|
||||
//TDD table
|
||||
for (TDD record : historyList) {
|
||||
double tdd = record.getTotal();
|
||||
|
||||
// Create the table row
|
||||
TableRow tr = new TableRow(TDDStatsActivity.this);
|
||||
if (i % 2 != 0) tr.setBackgroundColor(Color.DKGRAY);
|
||||
if (dummies.contains(record)) {
|
||||
tr.setBackgroundColor(Color.argb(125, 255, 0, 0));
|
||||
}
|
||||
tr.setId(100 + i);
|
||||
tr.setLayoutParams(new TableLayout.LayoutParams(
|
||||
TableLayout.LayoutParams.MATCH_PARENT,
|
||||
TableLayout.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
// Here create the TextView dynamically
|
||||
TextView labelDATE = new TextView(TDDStatsActivity.this);
|
||||
labelDATE.setId(200 + i);
|
||||
labelDATE.setText(df.format(new Date(record.date)));
|
||||
labelDATE.setTextColor(Color.WHITE);
|
||||
tr.addView(labelDATE);
|
||||
|
||||
TextView labelBASAL = new TextView(TDDStatsActivity.this);
|
||||
labelBASAL.setId(300 + i);
|
||||
labelBASAL.setText(DecimalFormatter.to2Decimal(record.basal) + " U");
|
||||
labelBASAL.setTextColor(Color.WHITE);
|
||||
tr.addView(labelBASAL);
|
||||
|
||||
TextView labelBOLUS = new TextView(TDDStatsActivity.this);
|
||||
labelBOLUS.setId(400 + i);
|
||||
labelBOLUS.setText(DecimalFormatter.to2Decimal(record.bolus) + " U");
|
||||
labelBOLUS.setTextColor(Color.WHITE);
|
||||
tr.addView(labelBOLUS);
|
||||
|
||||
TextView labelTDD = new TextView(TDDStatsActivity.this);
|
||||
labelTDD.setId(500 + i);
|
||||
labelTDD.setText(DecimalFormatter.to2Decimal(tdd) + " U");
|
||||
labelTDD.setTextColor(Color.WHITE);
|
||||
tr.addView(labelTDD);
|
||||
|
||||
TextView labelRATIO = new TextView(TDDStatsActivity.this);
|
||||
labelRATIO.setId(600 + i);
|
||||
labelRATIO.setText(Math.round(100 * tdd / magicNumber) + " %");
|
||||
labelRATIO.setTextColor(Color.WHITE);
|
||||
tr.addView(labelRATIO);
|
||||
|
||||
// add stats rows to tables
|
||||
tl.addView(tr, new TableLayout.LayoutParams(
|
||||
TableLayout.LayoutParams.MATCH_PARENT,
|
||||
TableLayout.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
|
||||
//cumulative TDDs
|
||||
for (TDD record : historyList) {
|
||||
if (!historyList.isEmpty() && df.format(new Date(record.date)).equals(df.format(new Date()))) {
|
||||
//Today should not be included
|
||||
continue;
|
||||
}
|
||||
i++;
|
||||
|
||||
sum = sum + record.getTotal();
|
||||
|
||||
// Create the cumtable row
|
||||
TableRow ctr = new TableRow(TDDStatsActivity.this);
|
||||
if (i % 2 == 0) ctr.setBackgroundColor(Color.DKGRAY);
|
||||
ctr.setId(700 + i);
|
||||
ctr.setLayoutParams(new TableLayout.LayoutParams(
|
||||
TableLayout.LayoutParams.MATCH_PARENT,
|
||||
TableLayout.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
// Here create the TextView dynamically
|
||||
TextView labelDAYS = new TextView(TDDStatsActivity.this);
|
||||
labelDAYS.setId(800 + i);
|
||||
labelDAYS.setText("" + i);
|
||||
labelDAYS.setTextColor(Color.WHITE);
|
||||
ctr.addView(labelDAYS);
|
||||
|
||||
TextView labelCUMTDD = new TextView(TDDStatsActivity.this);
|
||||
labelCUMTDD.setId(900 + i);
|
||||
labelCUMTDD.setText(DecimalFormatter.to2Decimal(sum / i) + " U");
|
||||
labelCUMTDD.setTextColor(Color.WHITE);
|
||||
ctr.addView(labelCUMTDD);
|
||||
|
||||
TextView labelCUMRATIO = new TextView(TDDStatsActivity.this);
|
||||
labelCUMRATIO.setId(1000 + i);
|
||||
labelCUMRATIO.setText(Math.round(100 * sum / i / magicNumber) + " %");
|
||||
labelCUMRATIO.setTextColor(Color.WHITE);
|
||||
ctr.addView(labelCUMRATIO);
|
||||
|
||||
// add cummulative rows to tables
|
||||
ctl.addView(ctr, new TableLayout.LayoutParams(
|
||||
TableLayout.LayoutParams.MATCH_PARENT,
|
||||
TableLayout.LayoutParams.WRAP_CONTENT));
|
||||
}
|
||||
|
||||
if (isOldData(historyList) && ConfigBuilderPlugin.getPlugin().getActivePump().getPumpDescription().needsManualTDDLoad) {
|
||||
statsMessage.setVisibility(View.VISIBLE);
|
||||
statsMessage.setText(MainApp.gs(R.string.danar_stats_olddata_Message));
|
||||
|
||||
} else {
|
||||
tl.setBackgroundColor(Color.TRANSPARENT);
|
||||
}
|
||||
|
||||
if (!historyList.isEmpty() && df.format(new Date(historyList.get(0).date)).equals(df.format(new Date()))) {
|
||||
//Today should not be included
|
||||
historyList.remove(0);
|
||||
}
|
||||
|
||||
Collections.reverse(historyList);
|
||||
|
||||
i = 0;
|
||||
|
||||
for (TDD record : historyList) {
|
||||
double tdd = record.getTotal();
|
||||
if (i == 0) {
|
||||
weighted03 = tdd;
|
||||
weighted05 = tdd;
|
||||
weighted07 = tdd;
|
||||
|
||||
} else {
|
||||
weighted07 = (weighted07 * 0.3 + tdd * 0.7);
|
||||
weighted05 = (weighted05 * 0.5 + tdd * 0.5);
|
||||
weighted03 = (weighted03 * 0.7 + tdd * 0.3);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
// Create the exptable row
|
||||
TableRow etr = new TableRow(TDDStatsActivity.this);
|
||||
if (i % 2 != 0) etr.setBackgroundColor(Color.DKGRAY);
|
||||
etr.setId(1100 + i);
|
||||
etr.setLayoutParams(new TableLayout.LayoutParams(
|
||||
TableLayout.LayoutParams.MATCH_PARENT,
|
||||
TableLayout.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
// Here create the TextView dynamically
|
||||
TextView labelWEIGHT = new TextView(TDDStatsActivity.this);
|
||||
labelWEIGHT.setId(1200 + i);
|
||||
labelWEIGHT.setText("0.3\n" + "0.5\n" + "0.7");
|
||||
labelWEIGHT.setTextColor(Color.WHITE);
|
||||
etr.addView(labelWEIGHT);
|
||||
|
||||
TextView labelEXPTDD = new TextView(TDDStatsActivity.this);
|
||||
labelEXPTDD.setId(1300 + i);
|
||||
labelEXPTDD.setText(DecimalFormatter.to2Decimal(weighted03)
|
||||
+ " U\n" + DecimalFormatter.to2Decimal(weighted05)
|
||||
+ " U\n" + DecimalFormatter.to2Decimal(weighted07) + " U");
|
||||
labelEXPTDD.setTextColor(Color.WHITE);
|
||||
etr.addView(labelEXPTDD);
|
||||
|
||||
TextView labelEXPRATIO = new TextView(TDDStatsActivity.this);
|
||||
labelEXPRATIO.setId(1400 + i);
|
||||
labelEXPRATIO.setText(Math.round(100 * weighted03 / magicNumber) + " %\n"
|
||||
+ Math.round(100 * weighted05 / magicNumber) + " %\n"
|
||||
+ Math.round(100 * weighted07 / magicNumber) + " %");
|
||||
labelEXPRATIO.setTextColor(Color.WHITE);
|
||||
etr.addView(labelEXPRATIO);
|
||||
|
||||
// add exponentail rows to tables
|
||||
etl.addView(etr, new TableLayout.LayoutParams(
|
||||
TableLayout.LayoutParams.MATCH_PARENT,
|
||||
TableLayout.LayoutParams.WRAP_CONTENT));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void cleanTable(TableLayout table) {
|
||||
int childCount = table.getChildCount();
|
||||
// Remove all rows except the first one
|
||||
if (childCount > 1) {
|
||||
table.removeViews(1, childCount - 1);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isOldData(List<TDD> historyList) {
|
||||
Object activePump = ConfigBuilderPlugin.getPlugin().getActivePump();
|
||||
PumpInterface dana = DanaRPlugin.getPlugin();
|
||||
PumpInterface danaRS = DanaRSPlugin.getPlugin();
|
||||
PumpInterface danaV2 = DanaRv2Plugin.getPlugin();
|
||||
PumpInterface danaKorean = DanaRKoreanPlugin.getPlugin();
|
||||
PumpInterface insight = LocalInsightPlugin.getPlugin();
|
||||
|
||||
boolean startsYesterday = activePump == dana || activePump == danaRS || activePump == danaV2 || activePump == danaKorean || activePump == insight;
|
||||
|
||||
DateFormat df = new SimpleDateFormat("dd.MM.");
|
||||
return (historyList.size() < 3 || !(df.format(new Date(historyList.get(0).date)).equals(df.format(new Date(System.currentTimeMillis() - (startsYesterday ? 1000 * 60 * 60 * 24 : 0))))));
|
||||
}
|
||||
}
|
|
@ -1,237 +0,0 @@
|
|||
package info.nightscout.androidaps.data;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import info.nightscout.androidaps.Constants;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.interfaces.Constraint;
|
||||
import info.nightscout.androidaps.interfaces.ConstraintsInterface;
|
||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||
import info.nightscout.androidaps.interfaces.PluginType;
|
||||
|
||||
/**
|
||||
* Created by mike on 19.03.2018.
|
||||
*/
|
||||
|
||||
public class ConstraintChecker implements ConstraintsInterface {
|
||||
|
||||
public Constraint<Boolean> isLoopInvokationAllowed() {
|
||||
return isLoopInvocationAllowed(new Constraint<>(true));
|
||||
}
|
||||
|
||||
public Constraint<Boolean> isClosedLoopAllowed() {
|
||||
return isClosedLoopAllowed(new Constraint<>(true));
|
||||
}
|
||||
|
||||
public Constraint<Boolean> isAutosensModeEnabled() {
|
||||
return isAutosensModeEnabled(new Constraint<>(true));
|
||||
}
|
||||
|
||||
public Constraint<Boolean> isAMAModeEnabled() {
|
||||
return isAMAModeEnabled(new Constraint<>(true));
|
||||
}
|
||||
|
||||
public Constraint<Boolean> isSMBModeEnabled() {
|
||||
return isSMBModeEnabled(new Constraint<>(true));
|
||||
}
|
||||
|
||||
public Constraint<Boolean> isUAMEnabled() {
|
||||
return isUAMEnabled(new Constraint<>(true));
|
||||
}
|
||||
|
||||
public Constraint<Boolean> isAdvancedFilteringEnabled() {
|
||||
return isAdvancedFilteringEnabled(new Constraint<>(true));
|
||||
}
|
||||
|
||||
public Constraint<Boolean> isSuperBolusEnabled() {
|
||||
return isSuperBolusEnabled(new Constraint<>(true));
|
||||
}
|
||||
|
||||
public Constraint<Double> getMaxBasalAllowed(Profile profile) {
|
||||
return applyBasalConstraints(new Constraint<>(Constants.REALLYHIGHBASALRATE), profile);
|
||||
}
|
||||
|
||||
public Constraint<Integer> getMaxBasalPercentAllowed(Profile profile) {
|
||||
return applyBasalPercentConstraints(new Constraint<>(Constants.REALLYHIGHPERCENTBASALRATE), profile);
|
||||
}
|
||||
|
||||
public Constraint<Double> getMaxBolusAllowed() {
|
||||
return applyBolusConstraints(new Constraint<>(Constants.REALLYHIGHBOLUS));
|
||||
}
|
||||
|
||||
public Constraint<Double> getMaxExtendedBolusAllowed() {
|
||||
return applyExtendedBolusConstraints(new Constraint<>(Constants.REALLYHIGHBOLUS));
|
||||
}
|
||||
|
||||
public Constraint<Integer> getMaxCarbsAllowed() {
|
||||
return applyCarbsConstraints(new Constraint<>(Constants.REALLYHIGHCARBS));
|
||||
}
|
||||
|
||||
public Constraint<Double> getMaxIOBAllowed() {
|
||||
return applyMaxIOBConstraints(new Constraint<>(Constants.REALLYHIGHIOB));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Constraint<Boolean> isLoopInvocationAllowed(@NonNull Constraint<Boolean> value) {
|
||||
|
||||
ArrayList<PluginBase> constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
|
||||
for (PluginBase p : constraintsPlugins) {
|
||||
ConstraintsInterface constraint = (ConstraintsInterface) p;
|
||||
if (!p.isEnabled(PluginType.CONSTRAINTS)) continue;
|
||||
constraint.isLoopInvocationAllowed(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Constraint<Boolean> isClosedLoopAllowed(@NonNull Constraint<Boolean> value) {
|
||||
|
||||
ArrayList<PluginBase> constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
|
||||
for (PluginBase p : constraintsPlugins) {
|
||||
ConstraintsInterface constraint = (ConstraintsInterface) p;
|
||||
if (!p.isEnabled(PluginType.CONSTRAINTS)) continue;
|
||||
constraint.isClosedLoopAllowed(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Constraint<Boolean> isAutosensModeEnabled(@NonNull Constraint<Boolean> value) {
|
||||
|
||||
ArrayList<PluginBase> constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
|
||||
for (PluginBase p : constraintsPlugins) {
|
||||
ConstraintsInterface constraint = (ConstraintsInterface) p;
|
||||
if (!p.isEnabled(PluginType.CONSTRAINTS)) continue;
|
||||
constraint.isAutosensModeEnabled(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Constraint<Boolean> isAMAModeEnabled(@NonNull Constraint<Boolean> value) {
|
||||
|
||||
ArrayList<PluginBase> constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
|
||||
for (PluginBase p : constraintsPlugins) {
|
||||
ConstraintsInterface constrain = (ConstraintsInterface) p;
|
||||
if (!p.isEnabled(PluginType.CONSTRAINTS)) continue;
|
||||
constrain.isAMAModeEnabled(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Constraint<Boolean> isSMBModeEnabled(@NonNull Constraint<Boolean> value) {
|
||||
|
||||
ArrayList<PluginBase> constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
|
||||
for (PluginBase p : constraintsPlugins) {
|
||||
ConstraintsInterface constraint = (ConstraintsInterface) p;
|
||||
if (!p.isEnabled(PluginType.CONSTRAINTS)) continue;
|
||||
constraint.isSMBModeEnabled(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Constraint<Boolean> isUAMEnabled(@NonNull Constraint<Boolean> value) {
|
||||
|
||||
ArrayList<PluginBase> constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
|
||||
for (PluginBase p : constraintsPlugins) {
|
||||
ConstraintsInterface constraint = (ConstraintsInterface) p;
|
||||
if (!p.isEnabled(PluginType.CONSTRAINTS)) continue;
|
||||
constraint.isUAMEnabled(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Constraint<Boolean> isAdvancedFilteringEnabled(@NonNull Constraint<Boolean> value) {
|
||||
ArrayList<PluginBase> constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
|
||||
for (PluginBase p : constraintsPlugins) {
|
||||
ConstraintsInterface constraint = (ConstraintsInterface) p;
|
||||
if (!p.isEnabled(PluginType.CONSTRAINTS)) continue;
|
||||
constraint.isAdvancedFilteringEnabled(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Constraint<Boolean> isSuperBolusEnabled(@NonNull Constraint<Boolean> value) {
|
||||
ArrayList<PluginBase> constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
|
||||
for (PluginBase p : constraintsPlugins) {
|
||||
ConstraintsInterface constraint = (ConstraintsInterface) p;
|
||||
if (!p.isEnabled(PluginType.CONSTRAINTS)) continue;
|
||||
constraint.isSuperBolusEnabled(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Constraint<Double> applyBasalConstraints(@NonNull Constraint<Double> absoluteRate, Profile profile) {
|
||||
ArrayList<PluginBase> constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
|
||||
for (PluginBase p : constraintsPlugins) {
|
||||
ConstraintsInterface constraint = (ConstraintsInterface) p;
|
||||
if (!p.isEnabled(PluginType.CONSTRAINTS)) continue;
|
||||
constraint.applyBasalConstraints(absoluteRate, profile);
|
||||
}
|
||||
return absoluteRate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Constraint<Integer> applyBasalPercentConstraints(@NonNull Constraint<Integer> percentRate, Profile profile) {
|
||||
ArrayList<PluginBase> constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
|
||||
for (PluginBase p : constraintsPlugins) {
|
||||
ConstraintsInterface constrain = (ConstraintsInterface) p;
|
||||
if (!p.isEnabled(PluginType.CONSTRAINTS)) continue;
|
||||
constrain.applyBasalPercentConstraints(percentRate, profile);
|
||||
}
|
||||
return percentRate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Constraint<Double> applyBolusConstraints(@NonNull Constraint<Double> insulin) {
|
||||
ArrayList<PluginBase> constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
|
||||
for (PluginBase p : constraintsPlugins) {
|
||||
ConstraintsInterface constrain = (ConstraintsInterface) p;
|
||||
if (!p.isEnabled(PluginType.CONSTRAINTS)) continue;
|
||||
constrain.applyBolusConstraints(insulin);
|
||||
}
|
||||
return insulin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Constraint<Double> applyExtendedBolusConstraints(@NonNull Constraint<Double> insulin) {
|
||||
ArrayList<PluginBase> constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
|
||||
for (PluginBase p : constraintsPlugins) {
|
||||
ConstraintsInterface constrain = (ConstraintsInterface) p;
|
||||
if (!p.isEnabled(PluginType.CONSTRAINTS)) continue;
|
||||
constrain.applyExtendedBolusConstraints(insulin);
|
||||
}
|
||||
return insulin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Constraint<Integer> applyCarbsConstraints(@NonNull Constraint<Integer> carbs) {
|
||||
ArrayList<PluginBase> constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
|
||||
for (PluginBase p : constraintsPlugins) {
|
||||
ConstraintsInterface constrain = (ConstraintsInterface) p;
|
||||
if (!p.isEnabled(PluginType.CONSTRAINTS)) continue;
|
||||
constrain.applyCarbsConstraints(carbs);
|
||||
}
|
||||
return carbs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Constraint<Double> applyMaxIOBConstraints(@NonNull Constraint<Double> maxIob) {
|
||||
ArrayList<PluginBase> constraintsPlugins = MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
|
||||
for (PluginBase p : constraintsPlugins) {
|
||||
ConstraintsInterface constrain = (ConstraintsInterface) p;
|
||||
if (!p.isEnabled(PluginType.CONSTRAINTS)) continue;
|
||||
constrain.applyMaxIOBConstraints(maxIob);
|
||||
}
|
||||
return maxIob;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,60 +0,0 @@
|
|||
package info.nightscout.androidaps.data
|
||||
|
||||
import androidx.collection.ArrayMap
|
||||
import info.nightscout.androidaps.utils.JsonHelper
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.util.*
|
||||
|
||||
class ProfileStore(val data: JSONObject) {
|
||||
private val log = LoggerFactory.getLogger(ProfileStore::class.java)
|
||||
|
||||
private val cachedObjects = ArrayMap<String, Profile>()
|
||||
|
||||
private fun getStore(): JSONObject? {
|
||||
try {
|
||||
if (data.has("store")) return data.getJSONObject("store")
|
||||
} catch (e: JSONException) {
|
||||
log.error("Unhandled exception", e)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
fun getDefaultProfile(): Profile? = getDefaultProfileName()?.let { getSpecificProfile(it) }
|
||||
|
||||
fun getDefaultProfileName(): String? {
|
||||
val defaultProfileName = data.getString("defaultProfile")
|
||||
return getStore()?.has(defaultProfileName)?.let { defaultProfileName }
|
||||
}
|
||||
|
||||
fun getProfileList(): ArrayList<CharSequence> {
|
||||
val ret = ArrayList<CharSequence>()
|
||||
getStore()?.keys()?.let { keys ->
|
||||
while (keys.hasNext()) {
|
||||
val profileName = keys.next() as String
|
||||
ret.add(profileName)
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
fun getSpecificProfile(profileName: String): Profile? {
|
||||
var profile: Profile? = null
|
||||
getStore()?.let { store ->
|
||||
if (store.has(profileName)) {
|
||||
profile = cachedObjects[profileName]
|
||||
if (profile == null) {
|
||||
JsonHelper.safeGetJSONObject(store, profileName, null)?.let { profileObject ->
|
||||
// take units from profile and if N/A from store
|
||||
JsonHelper.safeGetStringAllowNull(profileObject, "units", JsonHelper.safeGetString(data, "units"))?.let { units ->
|
||||
profile = Profile(profileObject, units)
|
||||
cachedObjects[profileName] = profile
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return profile
|
||||
}
|
||||
}
|
|
@ -1,194 +0,0 @@
|
|||
package info.nightscout.androidaps.data;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.logging.L;
|
||||
import info.nightscout.androidaps.utils.DecimalFormatter;
|
||||
import info.nightscout.androidaps.utils.Round;
|
||||
|
||||
public class PumpEnactResult {
|
||||
private static Logger log = LoggerFactory.getLogger(L.APS);
|
||||
|
||||
public boolean success = false; // request was processed successfully (but possible no change was needed)
|
||||
public boolean enacted = false; // request was processed successfully and change has been made
|
||||
public String comment = "";
|
||||
|
||||
// Result of basal change
|
||||
public int duration = -1; // duration set [minutes]
|
||||
public double absolute = -1d; // absolute rate [U/h] , isPercent = false
|
||||
public int percent = -1; // percent of current basal [%] (100% = current basal), isPercent = true
|
||||
public boolean isPercent = false; // if true percent is used, otherwise absolute
|
||||
public boolean isTempCancel = false; // if true we are caceling temp basal
|
||||
// Result of treatment delivery
|
||||
public double bolusDelivered = 0d; // real value of delivered insulin
|
||||
public double carbsDelivered = 0d; // real value of delivered carbs
|
||||
|
||||
public boolean queued = false;
|
||||
|
||||
public PumpEnactResult success(boolean success) {
|
||||
this.success = success;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PumpEnactResult enacted(boolean enacted) {
|
||||
this.enacted = enacted;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PumpEnactResult comment(String comment) {
|
||||
this.comment = comment;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PumpEnactResult comment(int comment) {
|
||||
this.comment = MainApp.gs(comment);
|
||||
return this;
|
||||
}
|
||||
|
||||
public PumpEnactResult duration(int duration) {
|
||||
this.duration = duration;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PumpEnactResult absolute(double absolute) {
|
||||
this.absolute = absolute;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PumpEnactResult percent(int percent) {
|
||||
this.percent = percent;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PumpEnactResult isPercent(boolean isPercent) {
|
||||
this.isPercent = isPercent;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PumpEnactResult isTempCancel(boolean isTempCancel) {
|
||||
this.isTempCancel = isTempCancel;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PumpEnactResult bolusDelivered(double bolusDelivered) {
|
||||
this.bolusDelivered = bolusDelivered;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PumpEnactResult carbsDelivered(double carbsDelivered) {
|
||||
this.carbsDelivered = carbsDelivered;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PumpEnactResult queued(boolean queued) {
|
||||
this.queued = queued;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String log() {
|
||||
return "Success: " + success +
|
||||
" Enacted: " + enacted +
|
||||
" Comment: " + comment +
|
||||
" Duration: " + duration +
|
||||
" Absolute: " + absolute +
|
||||
" Percent: " + percent +
|
||||
" IsPercent: " + isPercent +
|
||||
" IsTempCancel: " + isTempCancel +
|
||||
" bolusDelivered: " + bolusDelivered +
|
||||
" carbsDelivered: " + carbsDelivered +
|
||||
" Queued: " + queued;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String ret = MainApp.gs(R.string.success) + ": " + success;
|
||||
if (enacted) {
|
||||
if (bolusDelivered > 0) {
|
||||
ret += "\n" + MainApp.gs(R.string.enacted) + ": " + enacted;
|
||||
ret += "\n" + MainApp.gs(R.string.comment) + ": " + comment;
|
||||
ret += "\n" + MainApp.gs(R.string.configbuilder_insulin)
|
||||
+ ": " + bolusDelivered + " " + MainApp.gs(R.string.insulin_unit_shortname);
|
||||
} else if (isTempCancel) {
|
||||
ret += "\n" + MainApp.gs(R.string.enacted) + ": " + enacted;
|
||||
if (!comment.isEmpty())
|
||||
ret += "\n" + MainApp.gs(R.string.comment) + ": " + comment;
|
||||
ret += "\n" + MainApp.gs(R.string.canceltemp);
|
||||
} else if (isPercent) {
|
||||
ret += "\n" + MainApp.gs(R.string.enacted) + ": " + enacted;
|
||||
if (!comment.isEmpty())
|
||||
ret += "\n" + MainApp.gs(R.string.comment) + ": " + comment;
|
||||
ret += "\n" + MainApp.gs(R.string.duration) + ": " + duration + " min";
|
||||
ret += "\n" + MainApp.gs(R.string.percent) + ": " + percent + "%";
|
||||
} else {
|
||||
ret += "\n" + MainApp.gs(R.string.enacted) + ": " + enacted;
|
||||
if (!comment.isEmpty())
|
||||
ret += "\n" + MainApp.gs(R.string.comment) + ": " + comment;
|
||||
ret += "\n" + MainApp.gs(R.string.duration) + ": " + duration + " min";
|
||||
ret += "\n" + MainApp.gs(R.string.absolute) + ": " + absolute + " U/h";
|
||||
}
|
||||
} else {
|
||||
ret += "\n" + MainApp.gs(R.string.comment) + ": " + comment;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public String toHtml() {
|
||||
String ret = "<b>" + MainApp.gs(R.string.success) + "</b>: " + success;
|
||||
if (queued) {
|
||||
ret = MainApp.gs(R.string.waitingforpumpresult);
|
||||
} else if (enacted) {
|
||||
if (bolusDelivered > 0) {
|
||||
ret += "<br><b>" + MainApp.gs(R.string.enacted) + "</b>: " + enacted;
|
||||
if (!comment.isEmpty())
|
||||
ret += "<br><b>" + MainApp.gs(R.string.comment) + "</b>: " + comment;
|
||||
ret += "<br><b>" + MainApp.gs(R.string.smb_shortname) + "</b>: " + bolusDelivered + " " + MainApp.gs(R.string.insulin_unit_shortname);
|
||||
} else if (isTempCancel) {
|
||||
ret += "<br><b>" + MainApp.gs(R.string.enacted) + "</b>: " + enacted;
|
||||
ret += "<br><b>" + MainApp.gs(R.string.comment) + "</b>: " + comment +
|
||||
"<br>" + MainApp.gs(R.string.canceltemp);
|
||||
} else if (isPercent && percent != -1) {
|
||||
ret += "<br><b>" + MainApp.gs(R.string.enacted) + "</b>: " + enacted;
|
||||
if (!comment.isEmpty())
|
||||
ret += "<br><b>" + MainApp.gs(R.string.comment) + "</b>: " + comment;
|
||||
ret += "<br><b>" + MainApp.gs(R.string.duration) + "</b>: " + duration + " min";
|
||||
ret += "<br><b>" + MainApp.gs(R.string.percent) + "</b>: " + percent + "%";
|
||||
} else if (absolute != -1) {
|
||||
ret += "<br><b>" + MainApp.gs(R.string.enacted) + "</b>: " + enacted;
|
||||
if (!comment.isEmpty())
|
||||
ret += "<br><b>" + MainApp.gs(R.string.comment) + "</b>: " + comment;
|
||||
ret += "<br><b>" + MainApp.gs(R.string.duration) + "</b>: " + duration + " min";
|
||||
ret += "<br><b>" + MainApp.gs(R.string.absolute) + "</b>: " + DecimalFormatter.to2Decimal(absolute) + " U/h";
|
||||
}
|
||||
} else {
|
||||
ret += "<br><b>" + MainApp.gs(R.string.comment) + "</b>: " + comment;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public JSONObject json(Profile profile) {
|
||||
JSONObject result = new JSONObject();
|
||||
try {
|
||||
if (bolusDelivered > 0) {
|
||||
result.put("smb", bolusDelivered);
|
||||
} else if (isTempCancel) {
|
||||
result.put("rate", 0);
|
||||
result.put("duration", 0);
|
||||
} else if (isPercent) {
|
||||
// Nightscout is expecting absolute value
|
||||
Double abs = Round.roundTo(profile.getBasal() * percent / 100, 0.01);
|
||||
result.put("rate", abs);
|
||||
result.put("duration", duration);
|
||||
} else {
|
||||
result.put("rate", absolute);
|
||||
result.put("duration", duration);
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
package info.nightscout.androidaps.data
|
||||
|
||||
import info.nightscout.androidaps.utils.SP
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONObject
|
||||
|
||||
object QuickWizard {
|
||||
private var storage = JSONArray()
|
||||
|
||||
init {
|
||||
setData(JSONArray(SP.getString("QuickWizard", "[]")))
|
||||
}
|
||||
|
||||
fun getActive(): QuickWizardEntry? {
|
||||
for (i in 0 until storage.length()) {
|
||||
val entry = QuickWizardEntry(storage.get(i) as JSONObject, i)
|
||||
if (entry.isActive) return entry
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
fun setData(newData: JSONArray) {
|
||||
storage = newData
|
||||
}
|
||||
|
||||
fun save() {
|
||||
SP.putString("QuickWizard", storage.toString())
|
||||
}
|
||||
|
||||
fun size(): Int = storage.length()
|
||||
|
||||
operator fun get(position: Int): QuickWizardEntry =
|
||||
QuickWizardEntry(storage.get(position) as JSONObject, position)
|
||||
|
||||
|
||||
fun newEmptyItem(): QuickWizardEntry {
|
||||
return QuickWizardEntry()
|
||||
}
|
||||
|
||||
fun addOrUpdate(newItem: QuickWizardEntry) {
|
||||
if (newItem.position == -1)
|
||||
storage.put(newItem.storage)
|
||||
else
|
||||
storage.put(newItem.position, newItem.storage)
|
||||
save()
|
||||
}
|
||||
|
||||
fun remove(position: Int) {
|
||||
storage.remove(position)
|
||||
save()
|
||||
}
|
||||
}
|
|
@ -1,238 +0,0 @@
|
|||
package info.nightscout.androidaps.data;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.db.BgReading;
|
||||
import info.nightscout.androidaps.db.TempTarget;
|
||||
import info.nightscout.androidaps.interfaces.TreatmentsInterface;
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.CobInfo;
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus;
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin;
|
||||
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin;
|
||||
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
|
||||
import info.nightscout.androidaps.utils.BolusWizard;
|
||||
import info.nightscout.androidaps.utils.DateUtil;
|
||||
import info.nightscout.androidaps.utils.SP;
|
||||
|
||||
/**
|
||||
* Created by mike on 25.12.2017.
|
||||
*/
|
||||
|
||||
public class QuickWizardEntry {
|
||||
private static Logger log = LoggerFactory.getLogger(QuickWizardEntry.class);
|
||||
|
||||
public JSONObject storage;
|
||||
public int position;
|
||||
|
||||
public static final int YES = 0;
|
||||
public static final int NO = 1;
|
||||
public static final int POSITIVE_ONLY = 2;
|
||||
public static final int NEGATIVE_ONLY = 3;
|
||||
|
||||
/*
|
||||
{
|
||||
buttonText: "Meal",
|
||||
carbs: 36,
|
||||
validFrom: 8 * 60 * 60, // seconds from midnight
|
||||
validTo: 9 * 60 * 60, // seconds from midnight
|
||||
useBG: 0,
|
||||
useCOB: 0,
|
||||
useBolusIOB: 0,
|
||||
useBasalIOB: 0,
|
||||
useTrend: 0,
|
||||
useSuperBolus: 0,
|
||||
useTemptarget: 0
|
||||
}
|
||||
*/
|
||||
QuickWizardEntry() {
|
||||
String emptyData = "{\"buttonText\":\"\",\"carbs\":0,\"validFrom\":0,\"validTo\":86340}";
|
||||
try {
|
||||
storage = new JSONObject(emptyData);
|
||||
} catch (JSONException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
position = -1;
|
||||
}
|
||||
|
||||
QuickWizardEntry(JSONObject entry, int position) {
|
||||
storage = entry;
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
Boolean isActive() {
|
||||
return Profile.secondsFromMidnight() >= validFrom() && Profile.secondsFromMidnight() <= validTo();
|
||||
}
|
||||
|
||||
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) {
|
||||
bg = lastBG.valueToUnits(ProfileFunctions.getSystemUnits());
|
||||
}
|
||||
|
||||
// COB
|
||||
double cob = 0d;
|
||||
if (useCOB() == YES) {
|
||||
CobInfo cobInfo = IobCobCalculatorPlugin.getPlugin().getCobInfo(_synchronized, "QuickWizard COB");
|
||||
if (cobInfo.displayCob != null)
|
||||
cob = cobInfo.displayCob;
|
||||
}
|
||||
|
||||
// Bolus IOB
|
||||
boolean bolusIOB = false;
|
||||
if (useBolusIOB() == YES) {
|
||||
bolusIOB = true;
|
||||
}
|
||||
|
||||
// Basal IOB
|
||||
TreatmentsInterface treatments = TreatmentsPlugin.getPlugin();
|
||||
treatments.updateTotalIOBTempBasals();
|
||||
IobTotal basalIob = treatments.getLastCalculationTempBasals().round();
|
||||
boolean basalIOB = false;
|
||||
if (useBasalIOB() == YES) {
|
||||
basalIOB = true;
|
||||
} else if (useBasalIOB() == POSITIVE_ONLY && basalIob.iob > 0) {
|
||||
basalIOB = true;
|
||||
} else if (useBasalIOB() == NEGATIVE_ONLY && basalIob.iob < 0) {
|
||||
basalIOB = true;
|
||||
}
|
||||
|
||||
// SuperBolus
|
||||
boolean superBolus = false;
|
||||
if (useSuperBolus() == YES && SP.getBoolean(R.string.key_usesuperbolus, false)) {
|
||||
superBolus = true;
|
||||
}
|
||||
final LoopPlugin loopPlugin = LoopPlugin.getPlugin();
|
||||
if (loopPlugin.isEnabled(loopPlugin.getType()) && loopPlugin.isSuperBolus())
|
||||
superBolus = false;
|
||||
|
||||
// Trend
|
||||
GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData();
|
||||
boolean trend = false;
|
||||
if (useTrend() == YES) {
|
||||
trend = true;
|
||||
} else if (useTrend() == POSITIVE_ONLY && glucoseStatus != null && glucoseStatus.short_avgdelta > 0) {
|
||||
trend = true;
|
||||
} else if (useTrend() == NEGATIVE_ONLY && glucoseStatus != null && glucoseStatus.short_avgdelta < 0) {
|
||||
trend = true;
|
||||
}
|
||||
|
||||
double percentage = SP.getDouble(R.string.key_boluswizard_percentage, 100.0);
|
||||
return new BolusWizard(profile, profileName, tempTarget, carbs(), cob, bg, 0d, percentage, true, useCOB() == YES, bolusIOB, basalIOB, superBolus, useTempTarget() == YES, trend, "QuickWizard");
|
||||
}
|
||||
|
||||
public String buttonText() {
|
||||
try {
|
||||
return storage.getString("buttonText");
|
||||
} catch (JSONException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public Integer carbs() {
|
||||
try {
|
||||
return storage.getInt("carbs");
|
||||
} catch (JSONException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public Date validFromDate() {
|
||||
return DateUtil.toDate(validFrom());
|
||||
}
|
||||
|
||||
public Date validToDate() {
|
||||
return DateUtil.toDate(validTo());
|
||||
}
|
||||
|
||||
public Integer validFrom() {
|
||||
try {
|
||||
return storage.getInt("validFrom");
|
||||
} catch (JSONException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public Integer validTo() {
|
||||
try {
|
||||
return storage.getInt("validTo");
|
||||
} catch (JSONException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int useBG() {
|
||||
try {
|
||||
return storage.getInt("useBG");
|
||||
} catch (JSONException e) {
|
||||
//log.error("Unhandled exception", e);
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
public int useCOB() {
|
||||
try {
|
||||
return storage.getInt("useCOB");
|
||||
} catch (JSONException e) {
|
||||
//log.error("Unhandled exception", e);
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
public int useBolusIOB() {
|
||||
try {
|
||||
return storage.getInt("useBolusIOB");
|
||||
} catch (JSONException e) {
|
||||
//log.error("Unhandled exception", e);
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
public int useBasalIOB() {
|
||||
try {
|
||||
return storage.getInt("useBasalIOB");
|
||||
} catch (JSONException e) {
|
||||
//log.error("Unhandled exception", e);
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
public int useTrend() {
|
||||
try {
|
||||
return storage.getInt("useTrend");
|
||||
} catch (JSONException e) {
|
||||
//log.error("Unhandled exception", e);
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
public int useSuperBolus() {
|
||||
try {
|
||||
return storage.getInt("useSuperBolus");
|
||||
} catch (JSONException e) {
|
||||
//log.error("Unhandled exception", e);
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
public int useTempTarget() {
|
||||
try {
|
||||
return storage.getInt("useTempTarget");
|
||||
} catch (JSONException e) {
|
||||
//log.error("Unhandled exception", e);
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
}
|
|
@ -1,298 +0,0 @@
|
|||
package info.nightscout.androidaps.db;
|
||||
|
||||
import com.j256.ormlite.field.DatabaseField;
|
||||
import com.j256.ormlite.table.DatabaseTable;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import info.nightscout.androidaps.Constants;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.logging.L;
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.data.NSSgv;
|
||||
import info.nightscout.androidaps.plugins.general.overview.OverviewPlugin;
|
||||
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.DataPointWithLabelInterface;
|
||||
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.PointsWithLabelGraphSeries;
|
||||
import info.nightscout.androidaps.utils.DecimalFormatter;
|
||||
import info.nightscout.androidaps.utils.T;
|
||||
|
||||
@DatabaseTable(tableName = DatabaseHelper.DATABASE_BGREADINGS)
|
||||
public class BgReading implements DataPointWithLabelInterface {
|
||||
private static Logger log = LoggerFactory.getLogger(L.GLUCOSE);
|
||||
|
||||
@DatabaseField(id = true)
|
||||
public long date;
|
||||
|
||||
@DatabaseField
|
||||
public boolean isValid = true;
|
||||
|
||||
@DatabaseField
|
||||
public double value;
|
||||
@DatabaseField
|
||||
public String direction;
|
||||
@DatabaseField
|
||||
public double raw;
|
||||
|
||||
@DatabaseField
|
||||
public int source = Source.NONE;
|
||||
@DatabaseField
|
||||
public String _id = null; // NS _id
|
||||
|
||||
public boolean isCOBPrediction = false; // true when drawing predictions as bg points (COB)
|
||||
public boolean isaCOBPrediction = false; // true when drawing predictions as bg points (aCOB)
|
||||
public boolean isIOBPrediction = false; // true when drawing predictions as bg points (IOB)
|
||||
public boolean isUAMPrediction = false; // true when drawing predictions as bg points (UAM)
|
||||
public boolean isZTPrediction = false; // true when drawing predictions as bg points (ZT)
|
||||
|
||||
public BgReading() {
|
||||
}
|
||||
|
||||
public BgReading(NSSgv sgv) {
|
||||
date = sgv.getMills();
|
||||
value = sgv.getMgdl();
|
||||
raw = sgv.getFiltered() != null ? sgv.getFiltered() : value;
|
||||
direction = sgv.getDirection();
|
||||
_id = sgv.getId();
|
||||
}
|
||||
|
||||
public Double valueToUnits(String units) {
|
||||
if (units.equals(Constants.MGDL))
|
||||
return value;
|
||||
else
|
||||
return value * Constants.MGDL_TO_MMOLL;
|
||||
}
|
||||
|
||||
public String valueToUnitsToString(String units) {
|
||||
if (units.equals(Constants.MGDL)) return DecimalFormatter.to0Decimal(value);
|
||||
else return DecimalFormatter.to1Decimal(value * Constants.MGDL_TO_MMOLL);
|
||||
}
|
||||
|
||||
public String directionToSymbol() {
|
||||
String symbol = "";
|
||||
if (direction == null)
|
||||
direction = calculateDirection();
|
||||
|
||||
if (direction.compareTo("DoubleDown") == 0) {
|
||||
symbol = "\u21ca";
|
||||
} else if (direction.compareTo("SingleDown") == 0) {
|
||||
symbol = "\u2193";
|
||||
} else if (direction.compareTo("FortyFiveDown") == 0) {
|
||||
symbol = "\u2198";
|
||||
} else if (direction.compareTo("Flat") == 0) {
|
||||
symbol = "\u2192";
|
||||
} else if (direction.compareTo("FortyFiveUp") == 0) {
|
||||
symbol = "\u2197";
|
||||
} else if (direction.compareTo("SingleUp") == 0) {
|
||||
symbol = "\u2191";
|
||||
} else if (direction.compareTo("DoubleUp") == 0) {
|
||||
symbol = "\u21c8";
|
||||
} else if (isSlopeNameInvalid(direction)) {
|
||||
symbol = "??";
|
||||
}
|
||||
return symbol;
|
||||
}
|
||||
|
||||
private static boolean isSlopeNameInvalid(String direction) {
|
||||
return direction.compareTo("NOT_COMPUTABLE") == 0 ||
|
||||
direction.compareTo("NOT COMPUTABLE") == 0 ||
|
||||
direction.compareTo("OUT_OF_RANGE") == 0 ||
|
||||
direction.compareTo("OUT OF RANGE") == 0 ||
|
||||
direction.compareTo("NONE") == 0 ||
|
||||
direction.compareTo("NotComputable") == 0;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "BgReading{" +
|
||||
"date=" + date +
|
||||
", date=" + new Date(date).toLocaleString() +
|
||||
", value=" + value +
|
||||
", direction=" + direction +
|
||||
", raw=" + raw +
|
||||
'}';
|
||||
}
|
||||
|
||||
public boolean isDataChanging(BgReading other) {
|
||||
if (date != other.date) {
|
||||
if (L.isEnabled(L.GLUCOSE))
|
||||
log.error("Comparing different");
|
||||
return false;
|
||||
}
|
||||
if (value != other.value)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isEqual(BgReading other) {
|
||||
if (date != other.date) {
|
||||
if (L.isEnabled(L.GLUCOSE))
|
||||
log.error("Comparing different");
|
||||
return false;
|
||||
}
|
||||
if (value != other.value)
|
||||
return false;
|
||||
if (raw != other.raw)
|
||||
return false;
|
||||
if (!Objects.equals(direction, other.direction))
|
||||
return false;
|
||||
if (!Objects.equals(_id, other._id))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void copyFrom(BgReading other) {
|
||||
if (date != other.date) {
|
||||
if (L.isEnabled(L.GLUCOSE))
|
||||
log.error("Copying different");
|
||||
return;
|
||||
}
|
||||
value = other.value;
|
||||
raw = other.raw;
|
||||
direction = other.direction;
|
||||
_id = other._id;
|
||||
}
|
||||
|
||||
public BgReading date(long date) {
|
||||
this.date = date;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BgReading date(Date date) {
|
||||
this.date = date.getTime();
|
||||
return this;
|
||||
}
|
||||
|
||||
public BgReading value(double value) {
|
||||
this.value = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
// ------------------ DataPointWithLabelInterface ------------------
|
||||
@Override
|
||||
public double getX() {
|
||||
return date;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getY() {
|
||||
return valueToUnits(ProfileFunctions.getSystemUnits());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setY(double y) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLabel() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getDuration() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PointsWithLabelGraphSeries.Shape getShape() {
|
||||
if (isPrediction())
|
||||
return PointsWithLabelGraphSeries.Shape.PREDICTION;
|
||||
else
|
||||
return PointsWithLabelGraphSeries.Shape.BG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getSize() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getColor() {
|
||||
String units = ProfileFunctions.getSystemUnits();
|
||||
Double lowLine = OverviewPlugin.INSTANCE.determineLowLine();
|
||||
Double highLine = OverviewPlugin.INSTANCE.determineHighLine();
|
||||
int color = MainApp.gc(R.color.inrange);
|
||||
if (isPrediction())
|
||||
return getPredectionColor();
|
||||
else if (valueToUnits(units) < lowLine)
|
||||
color = MainApp.gc(R.color.low);
|
||||
else if (valueToUnits(units) > highLine)
|
||||
color = MainApp.gc(R.color.high);
|
||||
return color;
|
||||
}
|
||||
|
||||
public int getPredectionColor() {
|
||||
if (isIOBPrediction)
|
||||
return MainApp.gc(R.color.iob);
|
||||
if (isCOBPrediction)
|
||||
return MainApp.gc(R.color.cob);
|
||||
if (isaCOBPrediction)
|
||||
return 0x80FFFFFF & MainApp.gc(R.color.cob);
|
||||
if (isUAMPrediction)
|
||||
return MainApp.gc(R.color.uam);
|
||||
if (isZTPrediction)
|
||||
return MainApp.gc(R.color.zt);
|
||||
return R.color.mdtp_white;
|
||||
}
|
||||
|
||||
private boolean isPrediction() {
|
||||
return isaCOBPrediction || isCOBPrediction || isIOBPrediction || isUAMPrediction || isZTPrediction;
|
||||
}
|
||||
|
||||
|
||||
// Copied from xDrip+
|
||||
String calculateDirection() {
|
||||
// Rework to get bgreaings from internal DB and calculate on that base
|
||||
|
||||
List<BgReading> bgReadingsList = MainApp.getDbHelper().getAllBgreadingsDataFromTime(this.date - T.mins(10).msecs(), false);
|
||||
if (bgReadingsList == null || bgReadingsList.size() < 2)
|
||||
return "NONE";
|
||||
BgReading current = bgReadingsList.get(1);
|
||||
BgReading previous = bgReadingsList.get(0);
|
||||
|
||||
if (bgReadingsList.get(1).date < bgReadingsList.get(0).date) {
|
||||
current = bgReadingsList.get(0);
|
||||
previous = bgReadingsList.get(1);
|
||||
}
|
||||
|
||||
double slope;
|
||||
|
||||
// Avoid division by 0
|
||||
if (current.date == previous.date)
|
||||
slope = 0;
|
||||
else
|
||||
slope = (previous.value - current.value) / (previous.date - current.date);
|
||||
|
||||
if (L.isEnabled(L.GLUCOSE))
|
||||
log.debug("Slope is :" + slope + " delta " + (previous.value - current.value) + " date difference " + (current.date - previous.date));
|
||||
|
||||
double slope_by_minute = slope * 60000;
|
||||
String arrow = "NONE";
|
||||
|
||||
if (slope_by_minute <= (-3.5)) {
|
||||
arrow = "DoubleDown";
|
||||
} else if (slope_by_minute <= (-2)) {
|
||||
arrow = "SingleDown";
|
||||
} else if (slope_by_minute <= (-1)) {
|
||||
arrow = "FortyFiveDown";
|
||||
} else if (slope_by_minute <= (1)) {
|
||||
arrow = "Flat";
|
||||
} else if (slope_by_minute <= (2)) {
|
||||
arrow = "FortyFiveUp";
|
||||
} else if (slope_by_minute <= (3.5)) {
|
||||
arrow = "SingleUp";
|
||||
} else if (slope_by_minute <= (40)) {
|
||||
arrow = "DoubleUp";
|
||||
}
|
||||
if (L.isEnabled(L.GLUCOSE))
|
||||
log.debug("Direction set to: " + arrow);
|
||||
return arrow;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,115 @@
|
|||
package info.nightscout.androidaps.db;
|
||||
|
||||
import com.j256.ormlite.dao.CloseableIterator;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface;
|
||||
|
||||
@Singleton
|
||||
public class DatabaseHelperProvider implements DatabaseHelperInterface {
|
||||
|
||||
@Inject DatabaseHelperProvider() {
|
||||
}
|
||||
|
||||
@NotNull @Override public List<BgReading> getAllBgreadingsDataFromTime(long mills, boolean ascending) {
|
||||
return MainApp.getDbHelper().getAllBgreadingsDataFromTime(mills, ascending);
|
||||
}
|
||||
|
||||
@Override public void createOrUpdate(@NotNull CareportalEvent careportalEvent) {
|
||||
MainApp.getDbHelper().createOrUpdate(careportalEvent);
|
||||
}
|
||||
|
||||
@Override public void createOrUpdate(@NotNull DanaRHistoryRecord record) {
|
||||
MainApp.getDbHelper().createOrUpdate(record);
|
||||
}
|
||||
|
||||
@Override public void createOrUpdate(@NotNull OmnipodHistoryRecord record) {
|
||||
MainApp.getDbHelper().createOrUpdate(record);
|
||||
}
|
||||
|
||||
@NotNull @Override public List<DanaRHistoryRecord> getDanaRHistoryRecordsByType(byte type) {
|
||||
return MainApp.getDbHelper().getDanaRHistoryRecordsByType(type);
|
||||
}
|
||||
|
||||
@NotNull @Override public List<TDD> getTDDs() {
|
||||
return MainApp.getDbHelper().getTDDs();
|
||||
}
|
||||
|
||||
@Override public long size(@NotNull String table) {
|
||||
return MainApp.getDbHelper().size(table);
|
||||
}
|
||||
|
||||
@Override public void create(@NotNull DbRequest record) {
|
||||
try {
|
||||
MainApp.getDbHelper().create(record);
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void deleteAllDbRequests() {
|
||||
MainApp.getDbHelper().deleteAllDbRequests();
|
||||
}
|
||||
|
||||
@Override public int deleteDbRequest(@NotNull String id) {
|
||||
return MainApp.getDbHelper().deleteDbRequest(id);
|
||||
}
|
||||
|
||||
@Override public void deleteDbRequestbyMongoId(@NotNull String action, @NotNull String _id) {
|
||||
MainApp.getDbHelper().deleteDbRequestbyMongoId(action, _id);
|
||||
}
|
||||
|
||||
@NotNull @Override public CloseableIterator<DbRequest> getDbRequestInterator() {
|
||||
return MainApp.getDbHelper().getDbRequestInterator();
|
||||
}
|
||||
|
||||
@Override public long roundDateToSec(long date) {
|
||||
return MainApp.getDbHelper().roundDateToSec(date);
|
||||
}
|
||||
|
||||
@Override public void createOrUpdateTDD(@NotNull TDD record) {
|
||||
MainApp.getDbHelper().createOrUpdateTDD(record);
|
||||
}
|
||||
|
||||
@Override public void createOrUpdate(@NotNull TemporaryBasal tempBasal) {
|
||||
MainApp.getDbHelper().createOrUpdate(tempBasal);
|
||||
}
|
||||
|
||||
@NotNull @Override public TemporaryBasal findTempBasalByPumpId(long id) {
|
||||
return MainApp.getDbHelper().findTempBasalByPumpId(id);
|
||||
}
|
||||
|
||||
@NotNull @Override public List<TemporaryBasal> getTemporaryBasalsDataFromTime(long mills, boolean ascending) {
|
||||
return MainApp.getDbHelper().getTemporaryBasalsDataFromTime(mills, ascending);
|
||||
}
|
||||
|
||||
@Override public CareportalEvent getCareportalEventFromTimestamp(long timestamp) {
|
||||
return MainApp.getDbHelper().getCareportalEventFromTimestamp(timestamp);
|
||||
}
|
||||
|
||||
@NotNull @Override public List<OmnipodHistoryRecord> getAllOmnipodHistoryRecordsFromTimestamp(long timestamp, boolean ascending) {
|
||||
return MainApp.getDbHelper().getAllOmnipodHistoryRecordsFromTimeStamp(timestamp, ascending);
|
||||
}
|
||||
|
||||
@Nullable @Override public OmnipodHistoryRecord findOmnipodHistoryRecordByPumpId(long pumpId) {
|
||||
return MainApp.getDbHelper().findOmnipodHistoryRecordByPumpId(pumpId);
|
||||
}
|
||||
|
||||
@NotNull @Override public List<TDD> getTDDsForLastXDays(int days) {
|
||||
return MainApp.getDbHelper().getTDDsForLastXDays(days);
|
||||
}
|
||||
|
||||
@NotNull @Override public List<ProfileSwitch> getProfileSwitchData(long from, boolean ascending) {
|
||||
return MainApp.getDbHelper().getProfileSwitchData(from, ascending);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package info.nightscout.androidaps.db
|
||||
|
||||
import com.j256.ormlite.field.DatabaseField
|
||||
import com.j256.ormlite.table.DatabaseTable
|
||||
|
||||
@DatabaseTable(tableName = DatabaseHelper.DATABASE_OPEN_HUMANS_QUEUE)
|
||||
data class OHQueueItem @JvmOverloads constructor(
|
||||
@DatabaseField(generatedId = true)
|
||||
val id: Long = 0,
|
||||
@DatabaseField
|
||||
val file: String = "",
|
||||
@DatabaseField
|
||||
val content: String = ""
|
||||
)
|
|
@ -1,70 +0,0 @@
|
|||
package info.nightscout.androidaps.db;
|
||||
|
||||
import com.j256.ormlite.field.DatabaseField;
|
||||
import com.j256.ormlite.table.DatabaseTable;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.logging.L;
|
||||
import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil;
|
||||
import info.nightscout.androidaps.utils.DateUtil;
|
||||
|
||||
/**
|
||||
* Created by mike on 20.09.2017.
|
||||
*/
|
||||
|
||||
|
||||
@DatabaseTable(tableName = DatabaseHelper.DATABASE_TDDS)
|
||||
public class TDD {
|
||||
private static Logger log = LoggerFactory.getLogger(L.DATABASE);
|
||||
|
||||
@DatabaseField(id = true)
|
||||
public long date;
|
||||
|
||||
@DatabaseField
|
||||
public double bolus;
|
||||
|
||||
@DatabaseField
|
||||
public double basal;
|
||||
|
||||
@DatabaseField
|
||||
public double total;
|
||||
|
||||
|
||||
public double getTotal(){
|
||||
return (total > 0d) ? total:(bolus+basal);
|
||||
}
|
||||
|
||||
|
||||
public TDD() { }
|
||||
|
||||
public TDD(long date, double bolus, double basal, double total){
|
||||
this.date = date;
|
||||
this.bolus = bolus;
|
||||
this.basal = basal;
|
||||
this.total = total;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TDD [" +
|
||||
"date=" + date +
|
||||
"date(str)=" + DateTimeUtil.toStringFromTimeInMillis(date) +
|
||||
", bolus=" + bolus +
|
||||
", basal=" + basal +
|
||||
", total=" + total +
|
||||
']';
|
||||
}
|
||||
|
||||
public String toText() {
|
||||
return MainApp.gs(R.string.tddformat, DateUtil.dateStringShort(date), total, bolus, basal);
|
||||
}
|
||||
|
||||
public String toText(int days) {
|
||||
return MainApp.gs(R.string.tddformat, String.format("%d ", days) + MainApp.gs(R.string.days), total, bolus, basal);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package info.nightscout.androidaps.dependencyInjection
|
||||
|
||||
import dagger.Module
|
||||
import dagger.android.ContributesAndroidInjector
|
||||
import info.nightscout.androidaps.plugins.aps.logger.LoggerCallback
|
||||
import info.nightscout.androidaps.plugins.aps.loop.APSResult
|
||||
import info.nightscout.androidaps.plugins.aps.openAPSAMA.DetermineBasalAdapterAMAJS
|
||||
import info.nightscout.androidaps.plugins.aps.openAPSAMA.DetermineBasalResultAMA
|
||||
import info.nightscout.androidaps.plugins.aps.openAPSSMB.DetermineBasalAdapterSMBJS
|
||||
import info.nightscout.androidaps.plugins.aps.openAPSSMB.DetermineBasalResultSMB
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.data.AutosensData
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobOref1Thread
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobThread
|
||||
|
||||
@Module
|
||||
@Suppress("unused")
|
||||
abstract class APSModule {
|
||||
|
||||
@ContributesAndroidInjector abstract fun loggerCallbackInjector(): LoggerCallback
|
||||
@ContributesAndroidInjector abstract fun determineBasalResultSMBInjector(): DetermineBasalResultSMB
|
||||
@ContributesAndroidInjector abstract fun determineBasalResultAMAInjector(): DetermineBasalResultAMA
|
||||
@ContributesAndroidInjector abstract fun determineBasalAdapterAMAJSInjector(): DetermineBasalAdapterAMAJS
|
||||
@ContributesAndroidInjector abstract fun determineBasalAdapterSMBJSInjector(): DetermineBasalAdapterSMBJS
|
||||
@ContributesAndroidInjector abstract fun iobCobThreadInjector(): IobCobThread
|
||||
@ContributesAndroidInjector abstract fun iobCobOref1ThreadInjector(): IobCobOref1Thread
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
package info.nightscout.androidaps.dependencyInjection
|
||||
|
||||
import dagger.Module
|
||||
import dagger.android.ContributesAndroidInjector
|
||||
import info.nightscout.androidaps.MainActivity
|
||||
import info.nightscout.androidaps.activities.*
|
||||
import info.nightscout.androidaps.historyBrowser.HistoryBrowseActivity
|
||||
import info.nightscout.androidaps.plugins.general.maintenance.activities.LogSettingActivity
|
||||
import info.nightscout.androidaps.plugins.general.maintenance.activities.PrefImportListActivity
|
||||
import info.nightscout.androidaps.plugins.general.openhumans.OpenHumansLoginActivity
|
||||
import info.nightscout.androidaps.plugins.general.overview.activities.QuickWizardListActivity
|
||||
import info.nightscout.androidaps.plugins.general.smsCommunicator.activities.SmsCommunicatorOtpActivity
|
||||
import info.nightscout.androidaps.plugins.pump.common.dialog.RileyLinkBLEScanActivity
|
||||
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.dialog.RileyLinkStatusActivity
|
||||
import info.nightscout.androidaps.plugins.pump.insight.activities.InsightAlertActivity
|
||||
import info.nightscout.androidaps.plugins.pump.insight.activities.InsightPairingActivity
|
||||
import info.nightscout.androidaps.plugins.pump.insight.activities.InsightPairingInformationActivity
|
||||
import info.nightscout.androidaps.plugins.pump.medtronic.dialog.MedtronicHistoryActivity
|
||||
import info.nightscout.androidaps.setupwizard.SetupWizardActivity
|
||||
|
||||
@Module
|
||||
@Suppress("unused")
|
||||
abstract class ActivitiesModule {
|
||||
|
||||
@ContributesAndroidInjector abstract fun contributesHistoryBrowseActivity(): HistoryBrowseActivity
|
||||
@ContributesAndroidInjector abstract fun contributesInsightAlertActivity(): InsightAlertActivity
|
||||
@ContributesAndroidInjector abstract fun contributesInsightPairingActivity(): InsightPairingActivity
|
||||
@ContributesAndroidInjector abstract fun contributesInsightPairingInformationActivity(): InsightPairingInformationActivity
|
||||
@ContributesAndroidInjector abstract fun contributesLogSettingActivity(): LogSettingActivity
|
||||
@ContributesAndroidInjector abstract fun contributeMainActivity(): MainActivity
|
||||
@ContributesAndroidInjector abstract fun contributesMedtronicHistoryActivity(): MedtronicHistoryActivity
|
||||
@ContributesAndroidInjector abstract fun contributesPreferencesActivity(): PreferencesActivity
|
||||
@ContributesAndroidInjector abstract fun contributesQuickWizardListActivity(): QuickWizardListActivity
|
||||
@ContributesAndroidInjector abstract fun contributesRequestDexcomPermissionActivity(): RequestDexcomPermissionActivity
|
||||
@ContributesAndroidInjector abstract fun contributesRileyLinkStatusActivity(): RileyLinkStatusActivity
|
||||
@ContributesAndroidInjector abstract fun contributesRileyLinkBLEScanActivity(): RileyLinkBLEScanActivity
|
||||
@ContributesAndroidInjector abstract fun contributesSetupWizardActivity(): SetupWizardActivity
|
||||
@ContributesAndroidInjector abstract fun contributesSingleFragmentActivity(): SingleFragmentActivity
|
||||
@ContributesAndroidInjector abstract fun contributesSmsCommunicatorOtpActivity(): SmsCommunicatorOtpActivity
|
||||
@ContributesAndroidInjector abstract fun contributesStatsActivity(): StatsActivity
|
||||
@ContributesAndroidInjector abstract fun contributesSurveyActivity(): SurveyActivity
|
||||
@ContributesAndroidInjector abstract fun contributesDefaultProfileActivity(): ProfileHelperActivity
|
||||
@ContributesAndroidInjector abstract fun contributesPrefImportListActivity(): PrefImportListActivity
|
||||
@ContributesAndroidInjector abstract fun contributesOpenHumansLoginActivity(): OpenHumansLoginActivity
|
||||
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
package info.nightscout.androidaps.dependencyInjection
|
||||
|
||||
import dagger.BindsInstance
|
||||
import dagger.Component
|
||||
import dagger.android.AndroidInjectionModule
|
||||
import dagger.android.AndroidInjector
|
||||
import info.nightscout.androidaps.MainApp
|
||||
import info.nightscout.androidaps.core.di.CoreModule
|
||||
import info.nightscout.androidaps.dana.di.DanaModule
|
||||
import info.nightscout.androidaps.danar.di.DanaRModule
|
||||
import info.nightscout.androidaps.danars.di.DanaRSModule
|
||||
import info.nightscout.androidaps.plugins.pump.common.dagger.RileyLinkModule
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
@Component(
|
||||
modules = [
|
||||
AndroidInjectionModule::class,
|
||||
PluginsModule::class,
|
||||
SkinsModule::class,
|
||||
ActivitiesModule::class,
|
||||
FragmentsModule::class,
|
||||
AppModule::class,
|
||||
ReceiversModule::class,
|
||||
ServicesModule::class,
|
||||
AutomationModule::class,
|
||||
CommandQueueModule::class,
|
||||
ObjectivesModule::class,
|
||||
WizardModule::class,
|
||||
RileyLinkModule::class,
|
||||
MedtronicModule::class,
|
||||
APSModule::class,
|
||||
PreferencesModule::class,
|
||||
OverviewModule::class,
|
||||
DataClassesModule::class,
|
||||
SMSModule::class,
|
||||
UIModule::class,
|
||||
CoreModule::class,
|
||||
DanaModule::class,
|
||||
DanaRModule::class,
|
||||
DanaRSModule::class,
|
||||
OHUploaderModule::class
|
||||
]
|
||||
)
|
||||
interface AppComponent : AndroidInjector<MainApp> {
|
||||
|
||||
@Component.Builder
|
||||
interface Builder {
|
||||
|
||||
@BindsInstance
|
||||
fun application(mainApp: MainApp): Builder
|
||||
|
||||
fun build(): AppComponent
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
package info.nightscout.androidaps.dependencyInjection
|
||||
|
||||
import android.content.Context
|
||||
import dagger.Binds
|
||||
import dagger.Lazy
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.Config
|
||||
import info.nightscout.androidaps.MainApp
|
||||
import info.nightscout.androidaps.db.DatabaseHelperProvider
|
||||
import info.nightscout.androidaps.interfaces.*
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
|
||||
import info.nightscout.androidaps.plugins.configBuilder.PluginStore
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.UploadQueue
|
||||
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
|
||||
import info.nightscout.androidaps.queue.CommandQueue
|
||||
import info.nightscout.androidaps.utils.androidNotification.NotificationHolder
|
||||
import info.nightscout.androidaps.utils.storage.FileStorage
|
||||
import info.nightscout.androidaps.utils.storage.Storage
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Module(includes = [
|
||||
AppModule.AppBindings::class
|
||||
])
|
||||
open class AppModule {
|
||||
|
||||
@Provides
|
||||
fun providesPlugins(configInterface: ConfigInterface,
|
||||
@PluginsModule.AllConfigs allConfigs: Map<@JvmSuppressWildcards Int, @JvmSuppressWildcards PluginBase>,
|
||||
@PluginsModule.PumpDriver pumpDrivers: Lazy<Map<@JvmSuppressWildcards Int, @JvmSuppressWildcards PluginBase>>,
|
||||
@PluginsModule.NotNSClient notNsClient: Lazy<Map<@JvmSuppressWildcards Int, @JvmSuppressWildcards PluginBase>>,
|
||||
@PluginsModule.APS aps: Lazy<Map<@JvmSuppressWildcards Int, @JvmSuppressWildcards PluginBase>>)
|
||||
: List<@JvmSuppressWildcards PluginBase> {
|
||||
val plugins = allConfigs.toMutableMap()
|
||||
if (configInterface.PUMPDRIVERS) plugins += pumpDrivers.get()
|
||||
if (configInterface.APS) plugins += aps.get()
|
||||
if (!configInterface.NSCLIENT) plugins += notNsClient.get()
|
||||
return plugins.toList().sortedBy { it.first }.map { it.second }
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideStorage(): Storage {
|
||||
return FileStorage()
|
||||
}
|
||||
|
||||
@Module
|
||||
interface AppBindings {
|
||||
|
||||
@Binds fun bindContext(mainApp: MainApp): Context
|
||||
@Binds fun bindInjector(mainApp: MainApp): HasAndroidInjector
|
||||
@Binds fun bindActivePluginProvider(pluginStore: PluginStore): ActivePluginProvider
|
||||
@Binds fun bindCommandQueueProvider(commandQueue: CommandQueue): CommandQueueProvider
|
||||
@Binds fun bindConfigInterface(config: Config): ConfigInterface
|
||||
@Binds fun bindConfigBuilderInterface(configBuilderPlugin: ConfigBuilderPlugin): ConfigBuilderInterface
|
||||
@Binds fun bindTreatmentInterface(treatmentsPlugin: TreatmentsPlugin): TreatmentsInterface
|
||||
@Binds fun bindDatabaseHelperInterface(databaseHelperProvider: DatabaseHelperProvider): DatabaseHelperInterface
|
||||
@Binds fun bindUploadQueueInterface(uploadQueue: UploadQueue): UploadQueueInterface
|
||||
@Binds fun bindNotificationHolderInterface(notificationHolder: NotificationHolder): NotificationHolderInterface
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
package info.nightscout.androidaps.dependencyInjection
|
||||
|
||||
import dagger.Module
|
||||
import dagger.android.ContributesAndroidInjector
|
||||
import info.nightscout.androidaps.plugins.general.automation.AutomationEvent
|
||||
import info.nightscout.androidaps.plugins.general.automation.actions.*
|
||||
import info.nightscout.androidaps.plugins.general.automation.elements.*
|
||||
import info.nightscout.androidaps.plugins.general.automation.triggers.*
|
||||
import info.nightscout.androidaps.queue.CommandQueue
|
||||
import info.nightscout.androidaps.queue.commands.*
|
||||
|
||||
@Module
|
||||
@Suppress("unused")
|
||||
abstract class AutomationModule {
|
||||
@ContributesAndroidInjector abstract fun automationEventInjector(): AutomationEvent
|
||||
|
||||
@ContributesAndroidInjector abstract fun triggerInjector(): Trigger
|
||||
@ContributesAndroidInjector abstract fun triggerAutosensValueInjector(): TriggerAutosensValue
|
||||
@ContributesAndroidInjector abstract fun triggerBgInjector(): TriggerBg
|
||||
@ContributesAndroidInjector abstract fun triggerBolusAgoInjector(): TriggerBolusAgo
|
||||
@ContributesAndroidInjector abstract fun triggerCOBInjector(): TriggerCOB
|
||||
@ContributesAndroidInjector abstract fun triggerConnectorInjector(): TriggerConnector
|
||||
@ContributesAndroidInjector abstract fun triggerDeltaInjector(): TriggerDelta
|
||||
@ContributesAndroidInjector abstract fun triggerDummyInjector(): TriggerDummy
|
||||
@ContributesAndroidInjector abstract fun triggerIobInjector(): TriggerIob
|
||||
@ContributesAndroidInjector abstract fun triggerLocationInjector(): TriggerLocation
|
||||
@ContributesAndroidInjector abstract fun triggerProfilePercentInjector(): TriggerProfilePercent
|
||||
@ContributesAndroidInjector abstract fun triggerPumpLastConnectionInjector(): TriggerPumpLastConnection
|
||||
@ContributesAndroidInjector abstract fun triggerBTDeviceInjector(): TriggerBTDevice
|
||||
@ContributesAndroidInjector abstract fun triggerRecurringTimeInjector(): TriggerRecurringTime
|
||||
@ContributesAndroidInjector abstract fun triggerTempTargetInjector(): TriggerTempTarget
|
||||
@ContributesAndroidInjector abstract fun triggerTime(): TriggerTime
|
||||
@ContributesAndroidInjector abstract fun triggerTimeRangeInjector(): TriggerTimeRange
|
||||
@ContributesAndroidInjector abstract fun triggerWifiSsidInjector(): TriggerWifiSsid
|
||||
|
||||
@ContributesAndroidInjector abstract fun actionInjector(): Action
|
||||
@ContributesAndroidInjector abstract fun actionLoopDisableInjector(): ActionLoopDisable
|
||||
@ContributesAndroidInjector abstract fun actionLoopEnableInjector(): ActionLoopEnable
|
||||
@ContributesAndroidInjector abstract fun actionLoopResumeInjector(): ActionLoopResume
|
||||
@ContributesAndroidInjector abstract fun actionLoopSuspendInjector(): ActionLoopSuspend
|
||||
@ContributesAndroidInjector abstract fun actionNotificationInjector(): ActionNotification
|
||||
@ContributesAndroidInjector abstract fun actionProfileSwitchInjector(): ActionProfileSwitch
|
||||
@ContributesAndroidInjector abstract fun actionProfileSwitchPercentInjector(): ActionProfileSwitchPercent
|
||||
@ContributesAndroidInjector abstract fun actionSendSMSInjector(): ActionSendSMS
|
||||
@ContributesAndroidInjector abstract fun actionStartTempTargetInjector(): ActionStartTempTarget
|
||||
@ContributesAndroidInjector abstract fun actionStopTempTargetInjector(): ActionStopTempTarget
|
||||
@ContributesAndroidInjector abstract fun actionDummyInjector(): ActionDummy
|
||||
|
||||
@ContributesAndroidInjector abstract fun elementInjector(): Element
|
||||
@ContributesAndroidInjector abstract fun inputBgInjector(): InputBg
|
||||
@ContributesAndroidInjector abstract fun inputButtonInjector(): InputButton
|
||||
@ContributesAndroidInjector abstract fun comparatorInjector(): Comparator
|
||||
@ContributesAndroidInjector abstract fun comparatorConnectInjector(): ComparatorConnect
|
||||
@ContributesAndroidInjector abstract fun comparatorExistsInjector(): ComparatorExists
|
||||
@ContributesAndroidInjector abstract fun inputDateTimeInjector(): InputDateTime
|
||||
@ContributesAndroidInjector abstract fun inputDeltaInjector(): InputDelta
|
||||
@ContributesAndroidInjector abstract fun inputDoubleInjector(): InputDouble
|
||||
@ContributesAndroidInjector abstract fun inputDropdownMenuInjector(): InputDropdownMenu
|
||||
@ContributesAndroidInjector abstract fun inputDurationInjector(): InputDuration
|
||||
@ContributesAndroidInjector abstract fun inputInsulinInjector(): InputInsulin
|
||||
@ContributesAndroidInjector abstract fun inputLocationModeInjector(): InputLocationMode
|
||||
@ContributesAndroidInjector abstract fun inputPercentInjector(): InputPercent
|
||||
@ContributesAndroidInjector abstract fun inputProfileNameInjector(): InputProfileName
|
||||
@ContributesAndroidInjector abstract fun inputStringInjector(): InputString
|
||||
@ContributesAndroidInjector abstract fun inputTempTargetInjector(): InputTempTarget
|
||||
@ContributesAndroidInjector abstract fun inputTimeRangeInjector(): InputTimeRange
|
||||
@ContributesAndroidInjector abstract fun inputTimeInjector(): InputTime
|
||||
@ContributesAndroidInjector abstract fun inputWeekDayInjector(): InputWeekDay
|
||||
@ContributesAndroidInjector abstract fun labelWithElementInjector(): LabelWithElement
|
||||
@ContributesAndroidInjector abstract fun staticLabelInjector(): StaticLabel
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package info.nightscout.androidaps.dependencyInjection
|
||||
|
||||
import dagger.Module
|
||||
import dagger.android.ContributesAndroidInjector
|
||||
import info.nightscout.androidaps.queue.CommandQueue
|
||||
import info.nightscout.androidaps.queue.commands.*
|
||||
|
||||
@Module
|
||||
@Suppress("unused")
|
||||
abstract class CommandQueueModule {
|
||||
|
||||
@ContributesAndroidInjector abstract fun commandQueueInjector(): CommandQueue
|
||||
@ContributesAndroidInjector abstract fun commandBolusInjector(): CommandBolus
|
||||
@ContributesAndroidInjector abstract fun commandCancelExtendedBolusInjector(): CommandCancelExtendedBolus
|
||||
@ContributesAndroidInjector abstract fun commandCancelTempBasalInjector(): CommandCancelTempBasal
|
||||
@ContributesAndroidInjector abstract fun commandExtendedBolusInjector(): CommandExtendedBolus
|
||||
@ContributesAndroidInjector abstract fun commandInsightSetTBROverNotificationInjector(): CommandInsightSetTBROverNotification
|
||||
@ContributesAndroidInjector abstract fun commandLoadEventsInjector(): CommandLoadEvents
|
||||
@ContributesAndroidInjector abstract fun commandLoadHistoryInjector(): CommandLoadHistory
|
||||
@ContributesAndroidInjector abstract fun commandLoadTDDsInjector(): CommandLoadTDDs
|
||||
@ContributesAndroidInjector abstract fun commandReadStatusInjector(): CommandReadStatus
|
||||
@ContributesAndroidInjector abstract fun commandSetProfileInjector(): CommandSetProfile
|
||||
@ContributesAndroidInjector abstract fun commandCommandSMBBolusInjector(): CommandSMBBolus
|
||||
@ContributesAndroidInjector abstract fun commandStartPumpInjector(): CommandStartPump
|
||||
@ContributesAndroidInjector abstract fun commandStopPumpInjector(): CommandStopPump
|
||||
@ContributesAndroidInjector abstract fun commandTempBasalAbsoluteInjector(): CommandTempBasalAbsolute
|
||||
@ContributesAndroidInjector abstract fun commandTempBasalPercentInjector(): CommandTempBasalPercent
|
||||
@ContributesAndroidInjector abstract fun commandSetUserSettingsInjector(): CommandSetUserSettings
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package info.nightscout.androidaps.dependencyInjection
|
||||
|
||||
import dagger.Module
|
||||
import dagger.android.ContributesAndroidInjector
|
||||
import info.nightscout.androidaps.data.Profile
|
||||
import info.nightscout.androidaps.db.*
|
||||
import info.nightscout.androidaps.interfaces.ProfileStore
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus
|
||||
import info.nightscout.androidaps.plugins.general.food.FoodService
|
||||
import info.nightscout.androidaps.plugins.treatments.TreatmentService
|
||||
import info.nightscout.androidaps.utils.wizard.BolusWizard
|
||||
import info.nightscout.androidaps.utils.wizard.QuickWizardEntry
|
||||
|
||||
@Module
|
||||
@Suppress("unused")
|
||||
abstract class DataClassesModule {
|
||||
|
||||
@ContributesAndroidInjector abstract fun glucoseStatusInjector(): GlucoseStatus
|
||||
|
||||
@ContributesAndroidInjector abstract fun DatabaseHelperInjector(): DatabaseHelper
|
||||
@ContributesAndroidInjector abstract fun treatmentServiceInjector(): TreatmentService
|
||||
@ContributesAndroidInjector abstract fun foodServiceInjector(): FoodService
|
||||
|
||||
@ContributesAndroidInjector abstract fun bolusWizardInjector(): BolusWizard
|
||||
@ContributesAndroidInjector abstract fun quickWizardEntryInjector(): QuickWizardEntry
|
||||
}
|
|
@ -0,0 +1,129 @@
|
|||
package info.nightscout.androidaps.dependencyInjection
|
||||
|
||||
import dagger.Module
|
||||
import dagger.android.ContributesAndroidInjector
|
||||
import info.nightscout.androidaps.activities.MyPreferenceFragment
|
||||
import info.nightscout.androidaps.dialogs.*
|
||||
import info.nightscout.androidaps.plugins.aps.loop.LoopFragment
|
||||
import info.nightscout.androidaps.plugins.aps.openAPSAMA.OpenAPSAMAFragment
|
||||
import info.nightscout.androidaps.plugins.aps.openAPSSMB.OpenAPSSMBFragment
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderFragment
|
||||
import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesFragment
|
||||
import info.nightscout.androidaps.plugins.constraints.objectives.activities.ObjectivesExamDialog
|
||||
import info.nightscout.androidaps.plugins.general.actions.ActionsFragment
|
||||
import info.nightscout.androidaps.plugins.general.automation.AutomationFragment
|
||||
import info.nightscout.androidaps.plugins.general.automation.dialogs.ChooseActionDialog
|
||||
import info.nightscout.androidaps.plugins.general.automation.dialogs.ChooseTriggerDialog
|
||||
import info.nightscout.androidaps.plugins.general.automation.dialogs.EditActionDialog
|
||||
import info.nightscout.androidaps.plugins.general.automation.dialogs.EditEventDialog
|
||||
import info.nightscout.androidaps.plugins.general.automation.dialogs.EditTriggerDialog
|
||||
import info.nightscout.androidaps.plugins.general.food.FoodFragment
|
||||
import info.nightscout.androidaps.plugins.general.maintenance.MaintenanceFragment
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.NSClientFragment
|
||||
import info.nightscout.androidaps.plugins.general.openhumans.OpenHumansFragment
|
||||
import info.nightscout.androidaps.plugins.general.openhumans.OpenHumansLoginActivity
|
||||
import info.nightscout.androidaps.plugins.general.overview.OverviewFragment
|
||||
import info.nightscout.androidaps.plugins.general.overview.dialogs.EditQuickWizardDialog
|
||||
import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorFragment
|
||||
import info.nightscout.androidaps.plugins.general.tidepool.TidepoolFragment
|
||||
import info.nightscout.androidaps.plugins.general.wear.WearFragment
|
||||
import info.nightscout.androidaps.plugins.insulin.InsulinFragment
|
||||
import info.nightscout.androidaps.plugins.profile.local.LocalProfileFragment
|
||||
import info.nightscout.androidaps.plugins.profile.ns.NSProfileFragment
|
||||
import info.nightscout.androidaps.plugins.pump.combo.ComboFragment
|
||||
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.dialog.RileyLinkStatusGeneralFragment
|
||||
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.dialog.RileyLinkStatusHistoryFragment
|
||||
import info.nightscout.androidaps.plugins.pump.insight.LocalInsightFragment
|
||||
import info.nightscout.androidaps.plugins.pump.medtronic.MedtronicFragment
|
||||
import info.nightscout.androidaps.plugins.pump.medtronic.dialog.RileyLinkStatusDeviceMedtronic
|
||||
import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpFragment
|
||||
import info.nightscout.androidaps.plugins.source.BGSourceFragment
|
||||
import info.nightscout.androidaps.plugins.treatments.TreatmentsFragment
|
||||
import info.nightscout.androidaps.plugins.treatments.fragments.*
|
||||
import info.nightscout.androidaps.utils.protection.PasswordCheck
|
||||
|
||||
@Module
|
||||
@Suppress("unused")
|
||||
abstract class FragmentsModule {
|
||||
|
||||
@ContributesAndroidInjector abstract fun contributesPreferencesFragment(): MyPreferenceFragment
|
||||
|
||||
@ContributesAndroidInjector abstract fun contributesActionsFragment(): ActionsFragment
|
||||
@ContributesAndroidInjector abstract fun contributesAutomationFragment(): AutomationFragment
|
||||
@ContributesAndroidInjector abstract fun contributesBGSourceFragment(): BGSourceFragment
|
||||
@ContributesAndroidInjector abstract fun contributesComboFragment(): ComboFragment
|
||||
|
||||
@ContributesAndroidInjector
|
||||
abstract fun contributesConfigBuilderFragment(): ConfigBuilderFragment
|
||||
|
||||
@ContributesAndroidInjector abstract fun contributesFoodFragment(): FoodFragment
|
||||
@ContributesAndroidInjector abstract fun contributesInsulinFragment(): InsulinFragment
|
||||
@ContributesAndroidInjector abstract fun contributesLocalProfileFragment(): LocalProfileFragment
|
||||
@ContributesAndroidInjector abstract fun contributesObjectivesFragment(): ObjectivesFragment
|
||||
@ContributesAndroidInjector abstract fun contributesOpenAPSAMAFragment(): OpenAPSAMAFragment
|
||||
@ContributesAndroidInjector abstract fun contributesOpenAPSSMBFragment(): OpenAPSSMBFragment
|
||||
@ContributesAndroidInjector abstract fun contributesOverviewFragment(): OverviewFragment
|
||||
@ContributesAndroidInjector abstract fun contributesLocalInsightFragment(): LocalInsightFragment
|
||||
@ContributesAndroidInjector abstract fun contributesLoopFragment(): LoopFragment
|
||||
@ContributesAndroidInjector abstract fun contributesMaintenanceFragment(): MaintenanceFragment
|
||||
@ContributesAndroidInjector abstract fun contributesMedtronicFragment(): MedtronicFragment
|
||||
@ContributesAndroidInjector abstract fun contributesNSProfileFragment(): NSProfileFragment
|
||||
@ContributesAndroidInjector abstract fun contributesNSClientFragment(): NSClientFragment
|
||||
@ContributesAndroidInjector
|
||||
abstract fun contributesSmsCommunicatorFragment(): SmsCommunicatorFragment
|
||||
@ContributesAndroidInjector abstract fun contributesWearFragment(): WearFragment
|
||||
|
||||
@ContributesAndroidInjector abstract fun contributesTidepoolFragment(): TidepoolFragment
|
||||
@ContributesAndroidInjector abstract fun contributesTreatmentsFragment(): TreatmentsFragment
|
||||
@ContributesAndroidInjector
|
||||
abstract fun contributesTreatmentsBolusFragment(): TreatmentsBolusFragment
|
||||
@ContributesAndroidInjector
|
||||
abstract fun contributesTreatmentsTemporaryBasalsFragment(): TreatmentsTemporaryBasalsFragment
|
||||
@ContributesAndroidInjector
|
||||
abstract fun contributesTreatmentsTempTargetFragment(): TreatmentsTempTargetFragment
|
||||
@ContributesAndroidInjector
|
||||
abstract fun contributesTreatmentsExtendedBolusesFragment(): TreatmentsExtendedBolusesFragment
|
||||
@ContributesAndroidInjector
|
||||
abstract fun contributesTreatmentsCareportalFragment(): TreatmentsCareportalFragment
|
||||
@ContributesAndroidInjector
|
||||
abstract fun contributesTreatmentsProfileSwitchFragment(): TreatmentsProfileSwitchFragment
|
||||
|
||||
@ContributesAndroidInjector abstract fun contributesVirtualPumpFragment(): VirtualPumpFragment
|
||||
|
||||
@ContributesAndroidInjector abstract fun contributesOpenHumansFragment(): OpenHumansFragment
|
||||
|
||||
@ContributesAndroidInjector abstract fun contributesCalibrationDialog(): CalibrationDialog
|
||||
@ContributesAndroidInjector abstract fun contributesCarbsDialog(): CarbsDialog
|
||||
@ContributesAndroidInjector abstract fun contributesCareDialog(): CareDialog
|
||||
@ContributesAndroidInjector abstract fun contributesEditActionDialog(): EditActionDialog
|
||||
@ContributesAndroidInjector abstract fun contributesEditEventDialog(): EditEventDialog
|
||||
@ContributesAndroidInjector abstract fun contributesEditTriggerDialog(): EditTriggerDialog
|
||||
|
||||
@ContributesAndroidInjector
|
||||
abstract fun contributesEditQuickWizardDialog(): EditQuickWizardDialog
|
||||
|
||||
@ContributesAndroidInjector abstract fun contributesExtendedBolusDialog(): ExtendedBolusDialog
|
||||
@ContributesAndroidInjector abstract fun contributesFillDialog(): FillDialog
|
||||
@ContributesAndroidInjector abstract fun contributesChooseActionDialog(): ChooseActionDialog
|
||||
@ContributesAndroidInjector abstract fun contributesChooseTriggerDialog(): ChooseTriggerDialog
|
||||
@ContributesAndroidInjector abstract fun contributesInsulinDialog(): InsulinDialog
|
||||
@ContributesAndroidInjector abstract fun contributesObjectivesExamDialog(): ObjectivesExamDialog
|
||||
@ContributesAndroidInjector abstract fun contributesProfileSwitchDialog(): ProfileSwitchDialog
|
||||
@ContributesAndroidInjector abstract fun contributesTempBasalDialog(): TempBasalDialog
|
||||
@ContributesAndroidInjector abstract fun contributesTempTargetDialog(): TempTargetDialog
|
||||
@ContributesAndroidInjector abstract fun contributesTreatmentDialog(): TreatmentDialog
|
||||
@ContributesAndroidInjector abstract fun contributesWizardDialog(): WizardDialog
|
||||
@ContributesAndroidInjector abstract fun contributesWizardInfoDialog(): WizardInfoDialog
|
||||
|
||||
@ContributesAndroidInjector
|
||||
abstract fun contributesExchangeAuthTokenDialot(): OpenHumansLoginActivity.ExchangeAuthTokenDialog
|
||||
|
||||
@ContributesAndroidInjector abstract fun contributesPasswordCheck(): PasswordCheck
|
||||
|
||||
@ContributesAndroidInjector
|
||||
abstract fun contributesRileyLinkStatusGeneral(): RileyLinkStatusGeneralFragment
|
||||
@ContributesAndroidInjector
|
||||
abstract fun contributesRileyLinkStatusHistoryFragment(): RileyLinkStatusHistoryFragment
|
||||
@ContributesAndroidInjector
|
||||
abstract fun contributesRileyLinkStatusDeviceMedtronic(): RileyLinkStatusDeviceMedtronic
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package info.nightscout.androidaps.dependencyInjection
|
||||
|
||||
import dagger.Module
|
||||
import dagger.android.ContributesAndroidInjector
|
||||
import info.nightscout.androidaps.plugins.pump.medtronic.comm.MedtronicCommunicationManager
|
||||
import info.nightscout.androidaps.plugins.pump.medtronic.comm.ui.MedtronicUITask
|
||||
|
||||
@Module
|
||||
@Suppress("unused")
|
||||
abstract class MedtronicModule {
|
||||
@ContributesAndroidInjector abstract fun medtronicCommunicationManagerProvider(): MedtronicCommunicationManager
|
||||
@ContributesAndroidInjector abstract fun medtronicUITaskProvider(): MedtronicUITask
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package info.nightscout.androidaps.dependencyInjection
|
||||
|
||||
import dagger.Module
|
||||
import dagger.android.ContributesAndroidInjector
|
||||
import info.nightscout.androidaps.plugins.general.openhumans.OHUploadWorker
|
||||
|
||||
@Module
|
||||
@Suppress("unused")
|
||||
abstract class OHUploaderModule {
|
||||
|
||||
@ContributesAndroidInjector abstract fun contributesOHUploadWorkerInjector(): OHUploadWorker
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package info.nightscout.androidaps.dependencyInjection
|
||||
|
||||
import dagger.Module
|
||||
import dagger.android.ContributesAndroidInjector
|
||||
import info.nightscout.androidaps.plugins.constraints.objectives.objectives.*
|
||||
|
||||
@Module
|
||||
@Suppress("unused")
|
||||
abstract class ObjectivesModule {
|
||||
|
||||
@ContributesAndroidInjector abstract fun objectiveInjector(): Objective
|
||||
@ContributesAndroidInjector abstract fun objective0Injector(): Objective0
|
||||
@ContributesAndroidInjector abstract fun objective1Injector(): Objective1
|
||||
@ContributesAndroidInjector abstract fun objective2Injector(): Objective2
|
||||
@ContributesAndroidInjector abstract fun objective3Injector(): Objective3
|
||||
@ContributesAndroidInjector abstract fun objective4Injector(): Objective4
|
||||
@ContributesAndroidInjector abstract fun objective5Injector(): Objective5
|
||||
@ContributesAndroidInjector abstract fun objective6Injector(): Objective6
|
||||
@ContributesAndroidInjector abstract fun objective7Injector(): Objective7
|
||||
@ContributesAndroidInjector abstract fun objective8Injector(): Objective8
|
||||
@ContributesAndroidInjector abstract fun objective9Injector(): Objective9
|
||||
@ContributesAndroidInjector abstract fun objective10Injector(): Objective10
|
||||
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package info.nightscout.androidaps.dependencyInjection
|
||||
|
||||
import dagger.Module
|
||||
import dagger.android.ContributesAndroidInjector
|
||||
import info.nightscout.androidaps.plugins.general.overview.graphData.GraphData
|
||||
import info.nightscout.androidaps.plugins.general.overview.notifications.NotificationWithAction
|
||||
|
||||
@Module
|
||||
@Suppress("unused")
|
||||
abstract class OverviewModule {
|
||||
@ContributesAndroidInjector abstract fun notificationWithActionInjector(): NotificationWithAction
|
||||
|
||||
@ContributesAndroidInjector abstract fun graphDataInjector(): GraphData
|
||||
}
|
|
@ -0,0 +1,361 @@
|
|||
package info.nightscout.androidaps.dependencyInjection
|
||||
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.multibindings.IntKey
|
||||
import dagger.multibindings.IntoMap
|
||||
import info.nightscout.androidaps.danaRKorean.DanaRKoreanPlugin
|
||||
import info.nightscout.androidaps.danaRv2.DanaRv2Plugin
|
||||
import info.nightscout.androidaps.danar.DanaRPlugin
|
||||
import info.nightscout.androidaps.danars.DanaRSPlugin
|
||||
import info.nightscout.androidaps.interfaces.PluginBase
|
||||
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin
|
||||
import info.nightscout.androidaps.plugins.aps.openAPSAMA.OpenAPSAMAPlugin
|
||||
import info.nightscout.androidaps.plugins.aps.openAPSSMB.OpenAPSSMBPlugin
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
|
||||
import info.nightscout.androidaps.plugins.constraints.dstHelper.DstHelperPlugin
|
||||
import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin
|
||||
import info.nightscout.androidaps.plugins.constraints.safety.SafetyPlugin
|
||||
import info.nightscout.androidaps.plugins.constraints.signatureVerifier.SignatureVerifierPlugin
|
||||
import info.nightscout.androidaps.plugins.constraints.storage.StorageConstraintPlugin
|
||||
import info.nightscout.androidaps.plugins.constraints.versionChecker.VersionCheckerPlugin
|
||||
import info.nightscout.androidaps.plugins.general.actions.ActionsPlugin
|
||||
import info.nightscout.androidaps.plugins.general.automation.AutomationPlugin
|
||||
import info.nightscout.androidaps.plugins.general.dataBroadcaster.DataBroadcastPlugin
|
||||
import info.nightscout.androidaps.plugins.general.food.FoodPlugin
|
||||
import info.nightscout.androidaps.plugins.general.maintenance.MaintenancePlugin
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.NSClientPlugin
|
||||
import info.nightscout.androidaps.plugins.general.openhumans.OpenHumansUploader
|
||||
import info.nightscout.androidaps.plugins.general.overview.OverviewPlugin
|
||||
import info.nightscout.androidaps.plugins.general.persistentNotification.PersistentNotificationPlugin
|
||||
import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin
|
||||
import info.nightscout.androidaps.plugins.general.wear.WearPlugin
|
||||
import info.nightscout.androidaps.plugins.general.xdripStatusline.StatusLinePlugin
|
||||
import info.nightscout.androidaps.plugins.insulin.InsulinOrefFreePeakPlugin
|
||||
import info.nightscout.androidaps.plugins.insulin.InsulinOrefRapidActingPlugin
|
||||
import info.nightscout.androidaps.plugins.insulin.InsulinOrefUltraRapidActingPlugin
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
|
||||
import info.nightscout.androidaps.plugins.profile.local.LocalProfilePlugin
|
||||
import info.nightscout.androidaps.plugins.profile.ns.NSProfilePlugin
|
||||
import info.nightscout.androidaps.plugins.pump.combo.ComboPlugin
|
||||
import info.nightscout.androidaps.plugins.pump.insight.LocalInsightPlugin
|
||||
import info.nightscout.androidaps.plugins.pump.mdi.MDIPlugin
|
||||
import info.nightscout.androidaps.plugins.pump.medtronic.MedtronicPumpPlugin
|
||||
import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin
|
||||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityAAPSPlugin
|
||||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin
|
||||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAveragePlugin
|
||||
import info.nightscout.androidaps.plugins.source.*
|
||||
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
|
||||
import javax.inject.Qualifier
|
||||
|
||||
@Module
|
||||
abstract class PluginsModule {
|
||||
|
||||
@Binds
|
||||
@AllConfigs
|
||||
@IntoMap
|
||||
@IntKey(0)
|
||||
abstract fun bindOverviewPlugin(plugin: OverviewPlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@AllConfigs
|
||||
@IntoMap
|
||||
@IntKey(10)
|
||||
abstract fun bindIobCobCalculatorPlugin(plugin: IobCobCalculatorPlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@AllConfigs
|
||||
@IntoMap
|
||||
@IntKey(20)
|
||||
abstract fun bindActionsPlugin(plugin: ActionsPlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@AllConfigs
|
||||
@IntoMap
|
||||
@IntKey(30)
|
||||
abstract fun bindInsulinOrefRapidActingPlugin(plugin: InsulinOrefRapidActingPlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@AllConfigs
|
||||
@IntoMap
|
||||
@IntKey(40)
|
||||
abstract fun bindInsulinOrefUltraRapidActingPlugin(plugin: InsulinOrefUltraRapidActingPlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@AllConfigs
|
||||
@IntoMap
|
||||
@IntKey(50)
|
||||
abstract fun bindInsulinOrefFreePeakPlugin(plugin: InsulinOrefFreePeakPlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@AllConfigs
|
||||
@IntoMap
|
||||
@IntKey(60)
|
||||
abstract fun bindSensitivityAAPSPlugin(plugin: SensitivityAAPSPlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@AllConfigs
|
||||
@IntoMap
|
||||
@IntKey(70)
|
||||
abstract fun bindSensitivityWeightedAveragePlugin(plugin: SensitivityWeightedAveragePlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@AllConfigs
|
||||
@IntoMap
|
||||
@IntKey(80)
|
||||
abstract fun bindSensitivityOref1Plugin(plugin: SensitivityOref1Plugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@PumpDriver
|
||||
@IntoMap
|
||||
@IntKey(90)
|
||||
abstract fun bindDanaRPlugin(plugin: DanaRPlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@PumpDriver
|
||||
@IntoMap
|
||||
@IntKey(100)
|
||||
abstract fun bindDanaRKoreanPlugin(plugin: DanaRKoreanPlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@PumpDriver
|
||||
@IntoMap
|
||||
@IntKey(110)
|
||||
abstract fun bindDanaRv2Plugin(plugin: DanaRv2Plugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@PumpDriver
|
||||
@IntoMap
|
||||
@IntKey(120)
|
||||
abstract fun bindDanaRSPlugin(plugin: DanaRSPlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@PumpDriver
|
||||
@IntoMap
|
||||
@IntKey(130)
|
||||
abstract fun bindLocalInsightPlugin(plugin: LocalInsightPlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@PumpDriver
|
||||
@IntoMap
|
||||
@IntKey(140)
|
||||
abstract fun bindComboPlugin(plugin: ComboPlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@PumpDriver
|
||||
@IntoMap
|
||||
@IntKey(150)
|
||||
abstract fun bindMedtronicPumpPlugin(plugin: MedtronicPumpPlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@NotNSClient
|
||||
@IntoMap
|
||||
@IntKey(160)
|
||||
abstract fun bindMDIPlugin(plugin: MDIPlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@AllConfigs
|
||||
@IntoMap
|
||||
@IntKey(170)
|
||||
abstract fun bindVirtualPumpPlugin(plugin: VirtualPumpPlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@APS
|
||||
@IntoMap
|
||||
@IntKey(190)
|
||||
abstract fun bindLoopPlugin(plugin: LoopPlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@APS
|
||||
@IntoMap
|
||||
@IntKey(210)
|
||||
abstract fun bindOpenAPSAMAPlugin(plugin: OpenAPSAMAPlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@APS
|
||||
@IntoMap
|
||||
@IntKey(220)
|
||||
abstract fun bindOpenAPSSMBPlugin(plugin: OpenAPSSMBPlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@AllConfigs
|
||||
@IntoMap
|
||||
@IntKey(230)
|
||||
abstract fun bindNSProfilePlugin(plugin: NSProfilePlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@NotNSClient
|
||||
@IntoMap
|
||||
@IntKey(240)
|
||||
abstract fun bindLocalProfilePlugin(plugin: LocalProfilePlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@APS
|
||||
@IntoMap
|
||||
@IntKey(250)
|
||||
abstract fun bindAutomationPlugin(plugin: AutomationPlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@AllConfigs
|
||||
@IntoMap
|
||||
@IntKey(260)
|
||||
abstract fun bindTreatmentsPlugin(plugin: TreatmentsPlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@AllConfigs
|
||||
@IntoMap
|
||||
@IntKey(265)
|
||||
abstract fun bindSafetyPlugin(plugin: SafetyPlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@NotNSClient
|
||||
@IntoMap
|
||||
@IntKey(270)
|
||||
abstract fun bindVersionCheckerPlugin(plugin: VersionCheckerPlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@NotNSClient
|
||||
@IntoMap
|
||||
@IntKey(280)
|
||||
abstract fun bindSmsCommunicatorPlugin(plugin: SmsCommunicatorPlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@APS
|
||||
@IntoMap
|
||||
@IntKey(290)
|
||||
abstract fun bindStorageConstraintPlugin(plugin: StorageConstraintPlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@APS
|
||||
@IntoMap
|
||||
@IntKey(300)
|
||||
abstract fun bindSignatureVerifierPlugin(plugin: SignatureVerifierPlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@APS
|
||||
@IntoMap
|
||||
@IntKey(310)
|
||||
abstract fun bindObjectivesPlugin(plugin: ObjectivesPlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@AllConfigs
|
||||
@IntoMap
|
||||
@IntKey(320)
|
||||
abstract fun bindFoodPlugin(plugin: FoodPlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@AllConfigs
|
||||
@IntoMap
|
||||
@IntKey(330)
|
||||
abstract fun bindWearPlugin(plugin: WearPlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@AllConfigs
|
||||
@IntoMap
|
||||
@IntKey(340)
|
||||
abstract fun bindStatusLinePlugin(plugin: StatusLinePlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@AllConfigs
|
||||
@IntoMap
|
||||
@IntKey(350)
|
||||
abstract fun bindPersistentNotificationPlugin(plugin: PersistentNotificationPlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@AllConfigs
|
||||
@IntoMap
|
||||
@IntKey(360)
|
||||
abstract fun bindNSClientPlugin(plugin: NSClientPlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@AllConfigs
|
||||
@IntoMap
|
||||
@IntKey(370)
|
||||
abstract fun bindMaintenancePlugin(plugin: MaintenancePlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@AllConfigs
|
||||
@IntoMap
|
||||
@IntKey(380)
|
||||
abstract fun bindDstHelperPlugin(plugin: DstHelperPlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@AllConfigs
|
||||
@IntoMap
|
||||
@IntKey(390)
|
||||
abstract fun bindDataBroadcastPlugin(plugin: DataBroadcastPlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@AllConfigs
|
||||
@IntoMap
|
||||
@IntKey(400)
|
||||
abstract fun bindXdripPlugin(plugin: XdripPlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@AllConfigs
|
||||
@IntoMap
|
||||
@IntKey(410)
|
||||
abstract fun bindNSClientSourcePlugin(plugin: NSClientSourcePlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@AllConfigs
|
||||
@IntoMap
|
||||
@IntKey(420)
|
||||
abstract fun bindMM640gPlugin(plugin: MM640gPlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@AllConfigs
|
||||
@IntoMap
|
||||
@IntKey(430)
|
||||
abstract fun bindGlimpPlugin(plugin: GlimpPlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@AllConfigs
|
||||
@IntoMap
|
||||
@IntKey(440)
|
||||
abstract fun bindDexcomPlugin(plugin: DexcomPlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@AllConfigs
|
||||
@IntoMap
|
||||
@IntKey(450)
|
||||
abstract fun bindPoctechPlugin(plugin: PoctechPlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@AllConfigs
|
||||
@IntoMap
|
||||
@IntKey(460)
|
||||
abstract fun bindTomatoPlugin(plugin: TomatoPlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@AllConfigs
|
||||
@IntoMap
|
||||
@IntKey(470)
|
||||
abstract fun bindRandomBgPlugin(plugin: RandomBgPlugin): PluginBase
|
||||
|
||||
@Binds
|
||||
@NotNSClient
|
||||
@IntoMap
|
||||
@IntKey(480)
|
||||
abstract fun bindOpenHumansPlugin(plugin: OpenHumansUploader): PluginBase
|
||||
|
||||
@Binds
|
||||
@AllConfigs
|
||||
@IntoMap
|
||||
@IntKey(490)
|
||||
abstract fun bindConfigBuilderPlugin(plugin: ConfigBuilderPlugin): PluginBase
|
||||
|
||||
@Qualifier
|
||||
annotation class AllConfigs
|
||||
|
||||
@Qualifier
|
||||
annotation class PumpDriver
|
||||
|
||||
@Qualifier
|
||||
annotation class NotNSClient
|
||||
|
||||
@Qualifier
|
||||
annotation class APS
|
||||
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package info.nightscout.androidaps.dependencyInjection
|
||||
|
||||
import dagger.Module
|
||||
import dagger.android.ContributesAndroidInjector
|
||||
import info.nightscout.androidaps.plugins.general.maintenance.ImportExportPrefs
|
||||
import info.nightscout.androidaps.plugins.general.maintenance.PrefFileListProvider
|
||||
import info.nightscout.androidaps.plugins.general.maintenance.formats.ClassicPrefsFormat
|
||||
import info.nightscout.androidaps.plugins.general.maintenance.formats.EncryptedPrefsFormat
|
||||
import info.nightscout.androidaps.utils.CryptoUtil
|
||||
|
||||
@Module
|
||||
@Suppress("unused")
|
||||
abstract class PreferencesModule {
|
||||
|
||||
@ContributesAndroidInjector abstract fun cryptoUtilInjector(): CryptoUtil
|
||||
@ContributesAndroidInjector abstract fun importExportPrefsInjector(): ImportExportPrefs
|
||||
@ContributesAndroidInjector abstract fun encryptedPrefsFormatInjector(): EncryptedPrefsFormat
|
||||
@ContributesAndroidInjector abstract fun classicPrefsFormatInjector(): ClassicPrefsFormat
|
||||
@ContributesAndroidInjector abstract fun prefImportListProviderInjector(): PrefFileListProvider
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package info.nightscout.androidaps.dependencyInjection
|
||||
|
||||
import dagger.Module
|
||||
import dagger.android.ContributesAndroidInjector
|
||||
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.RileyLinkBluetoothStateReceiver
|
||||
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.RileyLinkBroadcastReceiver
|
||||
import info.nightscout.androidaps.plugins.aps.loop.CarbSuggestionReceiver
|
||||
import info.nightscout.androidaps.receivers.*
|
||||
|
||||
|
||||
@Module
|
||||
@Suppress("unused")
|
||||
abstract class ReceiversModule {
|
||||
|
||||
@ContributesAndroidInjector abstract fun contributesBTReceiver(): BTReceiver
|
||||
@ContributesAndroidInjector abstract fun contributesChargingStateReceiver(): ChargingStateReceiver
|
||||
@ContributesAndroidInjector abstract fun contributesDataReceiver(): DataReceiver
|
||||
@ContributesAndroidInjector abstract fun contributesKeepAliveReceiver(): KeepAliveReceiver
|
||||
@ContributesAndroidInjector abstract fun contributesRileyLinkBluetoothStateReceiver(): RileyLinkBluetoothStateReceiver
|
||||
@ContributesAndroidInjector abstract fun contributesSmsReceiver(): SmsReceiver
|
||||
@ContributesAndroidInjector abstract fun contributesTimeDateOrTZChangeReceiver(): TimeDateOrTZChangeReceiver
|
||||
@ContributesAndroidInjector abstract fun contributesCarbSuggestionReceiver(): CarbSuggestionReceiver
|
||||
@ContributesAndroidInjector abstract fun contributesRileyLinkBroadcastReceiver(): RileyLinkBroadcastReceiver
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package info.nightscout.androidaps.dependencyInjection
|
||||
|
||||
import dagger.Module
|
||||
import dagger.android.ContributesAndroidInjector
|
||||
import info.nightscout.androidaps.plugins.general.smsCommunicator.AuthRequest
|
||||
|
||||
@Module
|
||||
@Suppress("unused")
|
||||
abstract class SMSModule {
|
||||
|
||||
@ContributesAndroidInjector abstract fun authRequestInjector(): AuthRequest
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package info.nightscout.androidaps.dependencyInjection
|
||||
|
||||
import dagger.Module
|
||||
import dagger.android.ContributesAndroidInjector
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.services.NSClientService
|
||||
import info.nightscout.androidaps.plugins.general.overview.notifications.DismissNotificationService
|
||||
import info.nightscout.androidaps.plugins.general.persistentNotification.DummyService
|
||||
import info.nightscout.androidaps.plugins.general.wear.wearintegration.WatchUpdaterService
|
||||
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.RileyLinkService
|
||||
import info.nightscout.androidaps.plugins.pump.insight.InsightAlertService
|
||||
import info.nightscout.androidaps.plugins.pump.insight.connection_service.InsightConnectionService
|
||||
import info.nightscout.androidaps.plugins.pump.medtronic.service.RileyLinkMedtronicService
|
||||
import info.nightscout.androidaps.services.AlarmSoundService
|
||||
import info.nightscout.androidaps.services.DataService
|
||||
import info.nightscout.androidaps.services.LocationService
|
||||
|
||||
@Module
|
||||
@Suppress("unused")
|
||||
abstract class ServicesModule {
|
||||
|
||||
@ContributesAndroidInjector abstract fun contributesAlarmSoundService(): AlarmSoundService
|
||||
@ContributesAndroidInjector abstract fun contributesDataService(): DataService
|
||||
@ContributesAndroidInjector abstract fun contributesDismissNotificationService(): DismissNotificationService
|
||||
@ContributesAndroidInjector abstract fun contributesDummyService(): DummyService
|
||||
@ContributesAndroidInjector abstract fun contributesLocationService(): LocationService
|
||||
@ContributesAndroidInjector abstract fun contributesNSClientService(): NSClientService
|
||||
@ContributesAndroidInjector abstract fun contributesWatchUpdaterService(): WatchUpdaterService
|
||||
@ContributesAndroidInjector abstract fun contributesInsightAlertService(): InsightAlertService
|
||||
@ContributesAndroidInjector abstract fun contributesInsightConnectionService(): InsightConnectionService
|
||||
@ContributesAndroidInjector abstract fun contributesRileyLinkService(): RileyLinkService
|
||||
@ContributesAndroidInjector abstract fun contributesRileyLinkMedtronicService(): RileyLinkMedtronicService
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
package info.nightscout.androidaps.dependencyInjection
|
||||
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.multibindings.IntKey
|
||||
import dagger.multibindings.IntoMap
|
||||
import info.nightscout.androidaps.skins.SkinButtonsOn
|
||||
import info.nightscout.androidaps.skins.SkinClassic
|
||||
import info.nightscout.androidaps.skins.SkinInterface
|
||||
import info.nightscout.androidaps.skins.SkinLargeDisplay
|
||||
import javax.inject.Qualifier
|
||||
|
||||
@Module
|
||||
open class SkinsModule {
|
||||
|
||||
@Provides
|
||||
@Skin
|
||||
@IntoMap
|
||||
@IntKey(0)
|
||||
fun bindsSkinClassic(skinClassic: SkinClassic): SkinInterface = skinClassic
|
||||
|
||||
@Provides
|
||||
@Skin
|
||||
@IntoMap
|
||||
@IntKey(10)
|
||||
fun bindsSkinButtonsOn(skinButtonsOn: SkinButtonsOn): SkinInterface = skinButtonsOn
|
||||
|
||||
@Provides
|
||||
@Skin
|
||||
@IntoMap
|
||||
@IntKey(20)
|
||||
fun bindsSkinLargeDisplay(skinLargeDisplay: SkinLargeDisplay): SkinInterface = skinLargeDisplay
|
||||
|
||||
@Qualifier
|
||||
annotation class Skin
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package info.nightscout.androidaps.dependencyInjection
|
||||
|
||||
import dagger.Module
|
||||
import dagger.android.ContributesAndroidInjector
|
||||
import info.nightscout.androidaps.skins.SkinListPreference
|
||||
|
||||
@Module
|
||||
@Suppress("unused")
|
||||
abstract class UIModule {
|
||||
@ContributesAndroidInjector abstract fun skinListPreferenceInjector(): SkinListPreference
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package info.nightscout.androidaps.dependencyInjection
|
||||
|
||||
import dagger.Module
|
||||
import dagger.android.ContributesAndroidInjector
|
||||
import info.nightscout.androidaps.setupwizard.SWEventListener
|
||||
import info.nightscout.androidaps.setupwizard.SWScreen
|
||||
import info.nightscout.androidaps.setupwizard.elements.*
|
||||
|
||||
@Module
|
||||
@Suppress("unused")
|
||||
abstract class WizardModule {
|
||||
|
||||
@ContributesAndroidInjector abstract fun swBreakInjector(): SWBreak
|
||||
@ContributesAndroidInjector abstract fun swButtonInjector(): SWButton
|
||||
@ContributesAndroidInjector abstract fun swEditNumberWithUnitsInjector(): SWEditNumberWithUnits
|
||||
@ContributesAndroidInjector abstract fun swEditStringInjector(): SWEditString
|
||||
@ContributesAndroidInjector abstract fun swEditEncryptedPasswordInjector(): SWEditEncryptedPassword
|
||||
@ContributesAndroidInjector abstract fun swEditUrlInjector(): SWEditUrl
|
||||
@ContributesAndroidInjector abstract fun swFragmentInjector(): SWFragment
|
||||
@ContributesAndroidInjector abstract fun swHtmlLinkInjector(): SWHtmlLink
|
||||
@ContributesAndroidInjector abstract fun swInfotextInjector(): SWInfotext
|
||||
@ContributesAndroidInjector abstract fun swItemInjector(): SWItem
|
||||
@ContributesAndroidInjector abstract fun swPluginInjector(): SWPlugin
|
||||
@ContributesAndroidInjector abstract fun swRadioButtonInjector(): SWRadioButton
|
||||
@ContributesAndroidInjector abstract fun swScreenInjector(): SWScreen
|
||||
@ContributesAndroidInjector abstract fun swEventListenerInjector(): SWEventListener
|
||||
}
|
|
@ -1,165 +0,0 @@
|
|||
package info.nightscout.androidaps.dialogs
|
||||
|
||||
import android.app.Activity
|
||||
import android.os.Bundle
|
||||
import android.os.SystemClock
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.Window
|
||||
import android.view.WindowManager
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import info.nightscout.androidaps.MainApp
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.activities.BolusProgressHelperActivity
|
||||
import info.nightscout.androidaps.events.EventPumpStatusChanged
|
||||
import info.nightscout.androidaps.logging.L
|
||||
import info.nightscout.androidaps.plugins.bus.RxBus.toObservable
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
|
||||
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissBolusProgressIfRunning
|
||||
import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress
|
||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import kotlinx.android.synthetic.main.dialog_bolusprogress.*
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
class BolusProgressDialog : DialogFragment() {
|
||||
private val log = LoggerFactory.getLogger(L.UI)
|
||||
private val disposable = CompositeDisposable()
|
||||
|
||||
companion object {
|
||||
private val DEFAULT_STATE = MainApp.gs(R.string.waitingforpump)
|
||||
|
||||
@JvmField
|
||||
var bolusEnded = false
|
||||
|
||||
@JvmField
|
||||
var stopPressed = false
|
||||
}
|
||||
|
||||
private var running = true
|
||||
private var amount = 0.0
|
||||
private var state: String? = null
|
||||
private var helpActivity: BolusProgressHelperActivity? = null
|
||||
|
||||
fun setInsulin(amount: Double): BolusProgressDialog {
|
||||
this.amount = amount
|
||||
bolusEnded = false
|
||||
return this
|
||||
}
|
||||
|
||||
fun setHelperActivity(activity: BolusProgressHelperActivity): BolusProgressDialog {
|
||||
helpActivity = activity
|
||||
return this
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
dialog?.window?.requestFeature(Window.FEATURE_NO_TITLE)
|
||||
dialog?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN)
|
||||
isCancelable = false
|
||||
dialog?.setCanceledOnTouchOutside(false)
|
||||
return inflater.inflate(R.layout.dialog_bolusprogress, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
savedInstanceState?.let {
|
||||
amount = it.getDouble("amount")
|
||||
}
|
||||
overview_bolusprogress_title.text = String.format(MainApp.gs(R.string.overview_bolusprogress_goingtodeliver), amount)
|
||||
overview_bolusprogress_stop.setOnClickListener {
|
||||
if (L.isEnabled(L.UI)) log.debug("Stop bolus delivery button pressed")
|
||||
stopPressed = true
|
||||
overview_bolusprogress_stoppressed.visibility = View.VISIBLE
|
||||
overview_bolusprogress_stop.visibility = View.INVISIBLE
|
||||
ConfigBuilderPlugin.getPlugin().commandQueue.cancelAllBoluses()
|
||||
}
|
||||
overview_bolusprogress_progressbar.max = 100
|
||||
state = savedInstanceState?.getString("state", DEFAULT_STATE) ?: DEFAULT_STATE
|
||||
overview_bolusprogress_status.text = state
|
||||
stopPressed = false
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
dialog?.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
if (L.isEnabled(L.UI)) log.debug("onResume")
|
||||
if (!ConfigBuilderPlugin.getPlugin().commandQueue.bolusInQueue())
|
||||
bolusEnded = true
|
||||
|
||||
if (bolusEnded) dismiss()
|
||||
else running = true
|
||||
|
||||
disposable.add(toObservable(EventPumpStatusChanged::class.java)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({ overview_bolusprogress_status.text = it.getStatus() }) { FabricPrivacy.logException(it) }
|
||||
)
|
||||
disposable.add(toObservable(EventDismissBolusProgressIfRunning::class.java)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({ if (running) dismiss() }) { FabricPrivacy.logException(it) }
|
||||
)
|
||||
disposable.add(toObservable(EventOverviewBolusProgress::class.java)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({
|
||||
if (L.isEnabled(L.UI)) log.debug("Status: " + it.status + " Percent: " + it.percent)
|
||||
overview_bolusprogress_status.text = it.status
|
||||
overview_bolusprogress_progressbar.progress = it.percent
|
||||
if (it.percent == 100) {
|
||||
overview_bolusprogress_stop.visibility = View.INVISIBLE
|
||||
scheduleDismiss()
|
||||
}
|
||||
state = it.status
|
||||
}) { FabricPrivacy.logException(it) }
|
||||
)
|
||||
}
|
||||
|
||||
override fun dismiss() {
|
||||
if (L.isEnabled(L.UI)) log.debug("dismiss")
|
||||
try {
|
||||
super.dismiss()
|
||||
} catch (e: IllegalStateException) {
|
||||
// dialog not running yet. onResume will try again. Set bolusEnded to make extra
|
||||
// sure onResume will catch this
|
||||
bolusEnded = true
|
||||
log.error("Unhandled exception", e)
|
||||
}
|
||||
helpActivity?.finish()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
if (L.isEnabled(L.UI)) log.debug("onPause")
|
||||
running = false
|
||||
disposable.clear()
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
outState.putString("state", state)
|
||||
outState.putDouble("amount", amount)
|
||||
}
|
||||
|
||||
private fun scheduleDismiss() {
|
||||
if (L.isEnabled(L.UI)) log.debug("scheduleDismiss")
|
||||
Thread(Runnable {
|
||||
SystemClock.sleep(5000)
|
||||
bolusEnded = true
|
||||
val activity: Activity? = activity
|
||||
activity?.runOnUiThread {
|
||||
if (running) {
|
||||
if (L.isEnabled(L.UI)) log.debug("executing")
|
||||
try {
|
||||
dismiss()
|
||||
} catch (e: Exception) {
|
||||
log.error("Unhandled exception", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}).start()
|
||||
}
|
||||
}
|
|
@ -5,22 +5,29 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.google.common.base.Joiner
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.Constants
|
||||
import info.nightscout.androidaps.MainApp
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.data.Profile
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus
|
||||
import info.nightscout.androidaps.utils.HtmlHelper
|
||||
import info.nightscout.androidaps.utils.OKDialog
|
||||
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
||||
import info.nightscout.androidaps.utils.XdripCalibrations
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import kotlinx.android.synthetic.main.dialog_calibration.*
|
||||
import kotlinx.android.synthetic.main.okcancel.*
|
||||
import java.text.DecimalFormat
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class CalibrationDialog : DialogFragmentWithDate() {
|
||||
|
||||
@Inject lateinit var injector: HasAndroidInjector
|
||||
@Inject lateinit var resourceHelper: ResourceHelper
|
||||
@Inject lateinit var profileFunction: ProfileFunction
|
||||
@Inject lateinit var xdripCalibrations: XdripCalibrations
|
||||
|
||||
override fun onSaveInstanceState(savedInstanceState: Bundle) {
|
||||
super.onSaveInstanceState(savedInstanceState)
|
||||
savedInstanceState.putDouble("overview_calibration_bg", overview_calibration_bg.value)
|
||||
|
@ -35,8 +42,8 @@ class CalibrationDialog : DialogFragmentWithDate() {
|
|||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
val units = ProfileFunctions.getSystemUnits()
|
||||
val bg = Profile.fromMgdlToUnits(GlucoseStatus.getGlucoseStatusData()?.glucose
|
||||
val units = profileFunction.getUnits()
|
||||
val bg = Profile.fromMgdlToUnits(GlucoseStatus(injector).glucoseStatusData?.glucose
|
||||
?: 0.0, units)
|
||||
if (units == Constants.MMOL)
|
||||
overview_calibration_bg.setParams(savedInstanceState?.getDouble("overview_calibration_bg")
|
||||
|
@ -44,25 +51,25 @@ class CalibrationDialog : DialogFragmentWithDate() {
|
|||
else
|
||||
overview_calibration_bg.setParams(savedInstanceState?.getDouble("overview_calibration_bg")
|
||||
?: bg, 36.0, 500.0, 1.0, DecimalFormat("0"), false, ok)
|
||||
overview_calibration_units.text = if (units == Constants.MMOL) MainApp.gs(R.string.mmol) else MainApp.gs(R.string.mgdl)
|
||||
overview_calibration_units.text = if (units == Constants.MMOL) resourceHelper.gs(R.string.mmol) else resourceHelper.gs(R.string.mgdl)
|
||||
}
|
||||
|
||||
override fun submit() :Boolean {
|
||||
val units = ProfileFunctions.getSystemUnits()
|
||||
val unitLabel = if (units == Constants.MMOL) MainApp.gs(R.string.mmol) else MainApp.gs(R.string.mgdl)
|
||||
override fun submit(): Boolean {
|
||||
val units = profileFunction.getUnits()
|
||||
val unitLabel = if (units == Constants.MMOL) resourceHelper.gs(R.string.mmol) else resourceHelper.gs(R.string.mgdl)
|
||||
val actions: LinkedList<String?> = LinkedList()
|
||||
val bg = overview_calibration_bg.value
|
||||
actions.add(MainApp.gs(R.string.treatments_wizard_bg_label) + ": " + Profile.toCurrentUnitsString(bg) + " " + unitLabel)
|
||||
actions.add(resourceHelper.gs(R.string.treatments_wizard_bg_label) + ": " + Profile.toCurrentUnitsString(profileFunction, bg) + " " + unitLabel)
|
||||
if (bg > 0) {
|
||||
activity?.let { activity ->
|
||||
OKDialog.showConfirmation(activity, MainApp.gs(R.string.overview_calibration), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
|
||||
log.debug("USER ENTRY: CALIBRATION $bg")
|
||||
XdripCalibrations.sendIntent(bg)
|
||||
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.overview_calibration), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
|
||||
aapsLogger.debug("USER ENTRY: CALIBRATION $bg")
|
||||
xdripCalibrations.sendIntent(bg)
|
||||
})
|
||||
}
|
||||
} else
|
||||
activity?.let { activity ->
|
||||
OKDialog.show(activity, MainApp.gs(R.string.overview_calibration), MainApp.gs(R.string.no_action_selected))
|
||||
OKDialog.show(activity, resourceHelper.gs(R.string.overview_calibration), resourceHelper.gs(R.string.no_action_selected))
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -12,23 +12,41 @@ import info.nightscout.androidaps.MainApp
|
|||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.data.Profile
|
||||
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.interfaces.Constraint
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
|
||||
import info.nightscout.androidaps.plugins.treatments.CarbsGenerator
|
||||
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
|
||||
import info.nightscout.androidaps.utils.*
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.DecimalFormatter
|
||||
import info.nightscout.androidaps.utils.DefaultValueHelper
|
||||
import info.nightscout.androidaps.utils.HtmlHelper
|
||||
import info.nightscout.androidaps.utils.ToastUtils
|
||||
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
||||
import info.nightscout.androidaps.utils.extensions.formatColor
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import kotlinx.android.synthetic.main.dialog_carbs.*
|
||||
import kotlinx.android.synthetic.main.notes.*
|
||||
import kotlinx.android.synthetic.main.okcancel.*
|
||||
import java.text.DecimalFormat
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
import kotlin.math.max
|
||||
|
||||
class CarbsDialog : DialogFragmentWithDate() {
|
||||
@Inject lateinit var mainApp: MainApp
|
||||
@Inject lateinit var resourceHelper: ResourceHelper
|
||||
@Inject lateinit var constraintChecker: ConstraintChecker
|
||||
@Inject lateinit var defaultValueHelper: DefaultValueHelper
|
||||
@Inject lateinit var treatmentsPlugin: TreatmentsPlugin
|
||||
@Inject lateinit var profileFunction: ProfileFunction
|
||||
@Inject lateinit var iobCobCalculatorPlugin: IobCobCalculatorPlugin
|
||||
@Inject lateinit var nsUpload: NSUpload
|
||||
@Inject lateinit var carbsGenerator: CarbsGenerator
|
||||
|
||||
companion object {
|
||||
private const val FAV1_DEFAULT = 5
|
||||
|
@ -36,8 +54,6 @@ class CarbsDialog : DialogFragmentWithDate() {
|
|||
private const val FAV3_DEFAULT = 20
|
||||
}
|
||||
|
||||
private val maxCarbs = MainApp.getConstraintChecker().maxCarbsAllowed.value().toDouble()
|
||||
|
||||
private val textWatcher: TextWatcher = object : TextWatcher {
|
||||
override fun afterTextChanged(s: Editable) {
|
||||
validateInputs()
|
||||
|
@ -48,18 +64,19 @@ class CarbsDialog : DialogFragmentWithDate() {
|
|||
}
|
||||
|
||||
private fun validateInputs() {
|
||||
val maxCarbs = constraintChecker.getMaxCarbsAllowed().value().toDouble()
|
||||
val time = overview_carbs_time.value.toInt()
|
||||
if (time > 12 * 60 || time < -12 * 60) {
|
||||
overview_carbs_time.value = 0.0
|
||||
ToastUtils.showToastInUiThread(MainApp.instance().applicationContext, MainApp.gs(R.string.constraintapllied))
|
||||
ToastUtils.showToastInUiThread(mainApp, resourceHelper.gs(R.string.constraintapllied))
|
||||
}
|
||||
if (overview_carbs_duration.value > 10) {
|
||||
overview_carbs_duration.value = 0.0
|
||||
ToastUtils.showToastInUiThread(MainApp.instance().applicationContext, MainApp.gs(R.string.constraintapllied))
|
||||
ToastUtils.showToastInUiThread(mainApp, resourceHelper.gs(R.string.constraintapllied))
|
||||
}
|
||||
if (overview_carbs_carbs.value.toInt() > maxCarbs) {
|
||||
overview_carbs_carbs.value = 0.0
|
||||
ToastUtils.showToastInUiThread(MainApp.instance().applicationContext, MainApp.gs(R.string.carbsconstraintapplied))
|
||||
ToastUtils.showToastInUiThread(mainApp, resourceHelper.gs(R.string.carbsconstraintapplied))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -79,6 +96,7 @@ class CarbsDialog : DialogFragmentWithDate() {
|
|||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
val maxCarbs = constraintChecker.getMaxCarbsAllowed().value().toDouble()
|
||||
overview_carbs_time.setParams(savedInstanceState?.getDouble("overview_carbs_time")
|
||||
?: 0.0, -12 * 60.0, 12 * 60.0, 5.0, DecimalFormat("0"), false, ok, textWatcher)
|
||||
|
||||
|
@ -88,30 +106,30 @@ class CarbsDialog : DialogFragmentWithDate() {
|
|||
overview_carbs_carbs.setParams(savedInstanceState?.getDouble("overview_carbs_carbs")
|
||||
?: 0.0, 0.0, maxCarbs, 1.0, DecimalFormat("0"), false, ok, textWatcher)
|
||||
|
||||
overview_carbs_plus1.text = toSignedString(SP.getInt(R.string.key_carbs_button_increment_1, FAV1_DEFAULT))
|
||||
overview_carbs_plus1.text = toSignedString(sp.getInt(R.string.key_carbs_button_increment_1, FAV1_DEFAULT))
|
||||
overview_carbs_plus1.setOnClickListener {
|
||||
overview_carbs_carbs.value = max(0.0, overview_carbs_carbs.value
|
||||
+ SP.getInt(R.string.key_carbs_button_increment_1, FAV1_DEFAULT))
|
||||
+ sp.getInt(R.string.key_carbs_button_increment_1, FAV1_DEFAULT))
|
||||
validateInputs()
|
||||
}
|
||||
|
||||
overview_carbs_plus2.text = toSignedString(SP.getInt(R.string.key_carbs_button_increment_2, FAV2_DEFAULT))
|
||||
overview_carbs_plus2.text = toSignedString(sp.getInt(R.string.key_carbs_button_increment_2, FAV2_DEFAULT))
|
||||
overview_carbs_plus2.setOnClickListener {
|
||||
overview_carbs_carbs.value = max(0.0, overview_carbs_carbs.value
|
||||
+ SP.getInt(R.string.key_carbs_button_increment_2, FAV2_DEFAULT))
|
||||
+ sp.getInt(R.string.key_carbs_button_increment_2, FAV2_DEFAULT))
|
||||
validateInputs()
|
||||
}
|
||||
|
||||
overview_carbs_plus3.text = toSignedString(SP.getInt(R.string.key_carbs_button_increment_3, FAV3_DEFAULT))
|
||||
overview_carbs_plus3.text = toSignedString(sp.getInt(R.string.key_carbs_button_increment_3, FAV3_DEFAULT))
|
||||
overview_carbs_plus3.setOnClickListener {
|
||||
overview_carbs_carbs.value = max(0.0, overview_carbs_carbs.value
|
||||
+ SP.getInt(R.string.key_carbs_button_increment_3, FAV3_DEFAULT))
|
||||
+ sp.getInt(R.string.key_carbs_button_increment_3, FAV3_DEFAULT))
|
||||
validateInputs()
|
||||
}
|
||||
|
||||
DatabaseHelper.actualBg()?.let { bgReading ->
|
||||
iobCobCalculatorPlugin.actualBg()?.let { bgReading ->
|
||||
if (bgReading.value < 72)
|
||||
overview_carbs_hypo_tt.setChecked(true)
|
||||
overview_carbs_hypo_tt.isChecked = true
|
||||
}
|
||||
overview_carbs_hypo_tt.setOnClickListener {
|
||||
overview_carbs_activity_tt.isChecked = false
|
||||
|
@ -133,95 +151,102 @@ class CarbsDialog : DialogFragmentWithDate() {
|
|||
|
||||
override fun submit(): Boolean {
|
||||
val carbs = overview_carbs_carbs.value.toInt()
|
||||
val carbsAfterConstraints = MainApp.getConstraintChecker().applyCarbsConstraints(Constraint(carbs)).value()
|
||||
val units = ProfileFunctions.getSystemUnits()
|
||||
val activityTTDuration = DefaultValueHelper.determineActivityTTDuration()
|
||||
val activityTT = DefaultValueHelper.determineActivityTT()
|
||||
val eatingSoonTTDuration = DefaultValueHelper.determineEatingSoonTTDuration()
|
||||
val eatingSoonTT = DefaultValueHelper.determineEatingSoonTT()
|
||||
val hypoTTDuration = DefaultValueHelper.determineHypoTTDuration()
|
||||
val hypoTT = DefaultValueHelper.determineHypoTT()
|
||||
val carbsAfterConstraints = constraintChecker.applyCarbsConstraints(Constraint(carbs)).value()
|
||||
val units = profileFunction.getUnits()
|
||||
val activityTTDuration = defaultValueHelper.determineActivityTTDuration()
|
||||
val activityTT = defaultValueHelper.determineActivityTT()
|
||||
val eatingSoonTTDuration = defaultValueHelper.determineEatingSoonTTDuration()
|
||||
val eatingSoonTT = defaultValueHelper.determineEatingSoonTT()
|
||||
val hypoTTDuration = defaultValueHelper.determineHypoTTDuration()
|
||||
val hypoTT = defaultValueHelper.determineHypoTT()
|
||||
val actions: LinkedList<String?> = LinkedList()
|
||||
val unitLabel = if (units == Constants.MMOL) MainApp.gs(R.string.mmol) else MainApp.gs(R.string.mgdl)
|
||||
val unitLabel = if (units == Constants.MMOL) resourceHelper.gs(R.string.mmol) else resourceHelper.gs(R.string.mgdl)
|
||||
|
||||
val activitySelected = overview_carbs_activity_tt.isChecked
|
||||
if (activitySelected)
|
||||
actions.add(MainApp.gs(R.string.temptargetshort) + ": " + "<font color='" + MainApp.gc(R.color.tempTargetConfirmation) + "'>" + DecimalFormatter.to1Decimal(activityTT) + " " + unitLabel + " (" + activityTTDuration + " " + MainApp.gs(R.string.unit_minute_short) + ")</font>")
|
||||
actions.add(resourceHelper.gs(R.string.temptargetshort) + ": " + (DecimalFormatter.to1Decimal(activityTT) + " " + unitLabel + " (" + resourceHelper.gs(R.string.format_mins, activityTTDuration) + ")").formatColor(resourceHelper, R.color.tempTargetConfirmation))
|
||||
val eatingSoonSelected = overview_carbs_eating_soon_tt.isChecked
|
||||
if (eatingSoonSelected)
|
||||
actions.add(MainApp.gs(R.string.temptargetshort) + ": " + "<font color='" + MainApp.gc(R.color.tempTargetConfirmation) + "'>" + DecimalFormatter.to1Decimal(eatingSoonTT) + " " + unitLabel + " (" + eatingSoonTTDuration + " " + MainApp.gs(R.string.unit_minute_short) + ")</font>")
|
||||
actions.add(resourceHelper.gs(R.string.temptargetshort) + ": " + (DecimalFormatter.to1Decimal(eatingSoonTT) + " " + unitLabel + " (" + resourceHelper.gs(R.string.format_mins, eatingSoonTTDuration) + ")").formatColor(resourceHelper, R.color.tempTargetConfirmation))
|
||||
val hypoSelected = overview_carbs_hypo_tt.isChecked
|
||||
if (hypoSelected)
|
||||
actions.add(MainApp.gs(R.string.temptargetshort) + ": " + "<font color='" + MainApp.gc(R.color.tempTargetConfirmation) + "'>" + DecimalFormatter.to1Decimal(hypoTT) + " " + unitLabel + " (" + hypoTTDuration + " " + MainApp.gs(R.string.unit_minute_short) + ")</font>")
|
||||
actions.add(resourceHelper.gs(R.string.temptargetshort) + ": " + (DecimalFormatter.to1Decimal(hypoTT) + " " + unitLabel + " (" + resourceHelper.gs(R.string.format_mins, hypoTTDuration) + ")").formatColor(resourceHelper, R.color.tempTargetConfirmation))
|
||||
|
||||
val timeOffset = overview_carbs_time.value.toInt()
|
||||
eventTime -= eventTime % 1000
|
||||
val time = eventTime + timeOffset * 1000 * 60
|
||||
if (timeOffset != 0)
|
||||
actions.add(MainApp.gs(R.string.time) + ": " + DateUtil.dateAndTimeString(time))
|
||||
actions.add(resourceHelper.gs(R.string.time) + ": " + dateUtil.dateAndTimeString(time))
|
||||
val duration = overview_carbs_duration.value.toInt()
|
||||
if (duration > 0)
|
||||
actions.add(MainApp.gs(R.string.duration) + ": " + duration + MainApp.gs(R.string.shorthour))
|
||||
actions.add(resourceHelper.gs(R.string.duration) + ": " + duration + resourceHelper.gs(R.string.shorthour))
|
||||
if (carbsAfterConstraints > 0) {
|
||||
actions.add(MainApp.gs(R.string.carbs) + ": " + "<font color='" + MainApp.gc(R.color.carbs) + "'>" + MainApp.gs(R.string.format_carbs, carbsAfterConstraints) + "</font>")
|
||||
actions.add(resourceHelper.gs(R.string.carbs) + ": " + "<font color='" + resourceHelper.gc(R.color.carbs) + "'>" + resourceHelper.gs(R.string.format_carbs, carbsAfterConstraints) + "</font>")
|
||||
if (carbsAfterConstraints != carbs)
|
||||
actions.add("<font color='" + MainApp.gc(R.color.warning) + "'>" + MainApp.gs(R.string.carbsconstraintapplied) + "</font>")
|
||||
actions.add("<font color='" + resourceHelper.gc(R.color.warning) + "'>" + resourceHelper.gs(R.string.carbsconstraintapplied) + "</font>")
|
||||
}
|
||||
val notes = notes.text.toString()
|
||||
if (notes.isNotEmpty())
|
||||
actions.add(MainApp.gs(R.string.careportal_newnstreatment_notes_label) + ": " + notes)
|
||||
actions.add(resourceHelper.gs(R.string.careportal_newnstreatment_notes_label) + ": " + notes)
|
||||
|
||||
if (eventTimeChanged)
|
||||
actions.add(MainApp.gs(R.string.time) + ": " + DateUtil.dateAndTimeString(eventTime))
|
||||
actions.add(resourceHelper.gs(R.string.time) + ": " + dateUtil.dateAndTimeString(eventTime))
|
||||
|
||||
if (carbsAfterConstraints > 0 || activitySelected || eatingSoonSelected || hypoSelected) {
|
||||
activity?.let { activity ->
|
||||
OKDialog.showConfirmation(activity, MainApp.gs(R.string.carbs), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
|
||||
if (activitySelected) {
|
||||
log.debug("USER ENTRY: TEMPTARGET ACTIVITY $activityTT duration: $activityTTDuration")
|
||||
val tempTarget = TempTarget()
|
||||
.date(eventTime)
|
||||
.duration(activityTTDuration)
|
||||
.reason(MainApp.gs(R.string.activity))
|
||||
.source(Source.USER)
|
||||
.low(Profile.toMgdl(activityTT, ProfileFunctions.getSystemUnits()))
|
||||
.high(Profile.toMgdl(activityTT, ProfileFunctions.getSystemUnits()))
|
||||
TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget)
|
||||
} else if (eatingSoonSelected) {
|
||||
log.debug("USER ENTRY: TEMPTARGET EATING SOON $eatingSoonTT duration: $eatingSoonTTDuration")
|
||||
val tempTarget = TempTarget()
|
||||
.date(eventTime)
|
||||
.duration(eatingSoonTTDuration)
|
||||
.reason(MainApp.gs(R.string.eatingsoon))
|
||||
.source(Source.USER)
|
||||
.low(Profile.toMgdl(eatingSoonTT, ProfileFunctions.getSystemUnits()))
|
||||
.high(Profile.toMgdl(eatingSoonTT, ProfileFunctions.getSystemUnits()))
|
||||
TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget)
|
||||
} else if (hypoSelected) {
|
||||
log.debug("USER ENTRY: TEMPTARGET HYPO $hypoTT duration: $hypoTTDuration")
|
||||
val tempTarget = TempTarget()
|
||||
.date(eventTime)
|
||||
.duration(hypoTTDuration)
|
||||
.reason(MainApp.gs(R.string.hypo))
|
||||
.source(Source.USER)
|
||||
.low(Profile.toMgdl(hypoTT, ProfileFunctions.getSystemUnits()))
|
||||
.high(Profile.toMgdl(hypoTT, ProfileFunctions.getSystemUnits()))
|
||||
TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget)
|
||||
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.carbs), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
|
||||
when {
|
||||
activitySelected -> {
|
||||
aapsLogger.debug("USER ENTRY: TEMPTARGET ACTIVITY $activityTT duration: $activityTTDuration")
|
||||
val tempTarget = TempTarget()
|
||||
.date(System.currentTimeMillis())
|
||||
.duration(activityTTDuration)
|
||||
.reason(resourceHelper.gs(R.string.activity))
|
||||
.source(Source.USER)
|
||||
.low(Profile.toMgdl(activityTT, profileFunction.getUnits()))
|
||||
.high(Profile.toMgdl(activityTT, profileFunction.getUnits()))
|
||||
treatmentsPlugin.addToHistoryTempTarget(tempTarget)
|
||||
}
|
||||
|
||||
eatingSoonSelected -> {
|
||||
aapsLogger.debug("USER ENTRY: TEMPTARGET EATING SOON $eatingSoonTT duration: $eatingSoonTTDuration")
|
||||
val tempTarget = TempTarget()
|
||||
.date(System.currentTimeMillis())
|
||||
.duration(eatingSoonTTDuration)
|
||||
.reason(resourceHelper.gs(R.string.eatingsoon))
|
||||
.source(Source.USER)
|
||||
.low(Profile.toMgdl(eatingSoonTT, profileFunction.getUnits()))
|
||||
.high(Profile.toMgdl(eatingSoonTT, profileFunction.getUnits()))
|
||||
treatmentsPlugin.addToHistoryTempTarget(tempTarget)
|
||||
}
|
||||
|
||||
hypoSelected -> {
|
||||
aapsLogger.debug("USER ENTRY: TEMPTARGET HYPO $hypoTT duration: $hypoTTDuration")
|
||||
val tempTarget = TempTarget()
|
||||
.date(System.currentTimeMillis())
|
||||
.duration(hypoTTDuration)
|
||||
.reason(resourceHelper.gs(R.string.hypo))
|
||||
.source(Source.USER)
|
||||
.low(Profile.toMgdl(hypoTT, profileFunction.getUnits()))
|
||||
.high(Profile.toMgdl(hypoTT, profileFunction.getUnits()))
|
||||
treatmentsPlugin.addToHistoryTempTarget(tempTarget)
|
||||
}
|
||||
}
|
||||
if (carbsAfterConstraints > 0) {
|
||||
if (duration == 0) {
|
||||
log.debug("USER ENTRY: CARBS $carbsAfterConstraints time: $time")
|
||||
CarbsGenerator.createCarb(carbsAfterConstraints, time, CareportalEvent.CARBCORRECTION, notes)
|
||||
aapsLogger.debug("USER ENTRY: CARBS $carbsAfterConstraints time: $time")
|
||||
carbsGenerator.createCarb(carbsAfterConstraints, time, CareportalEvent.CARBCORRECTION, notes)
|
||||
} else {
|
||||
log.debug("USER ENTRY: CARBS $carbsAfterConstraints time: $time duration: $duration")
|
||||
CarbsGenerator.generateCarbs(carbsAfterConstraints, time, duration, notes)
|
||||
NSUpload.uploadEvent(CareportalEvent.NOTE, time - 2000, MainApp.gs(R.string.generated_ecarbs_note, carbsAfterConstraints, duration, timeOffset))
|
||||
aapsLogger.debug("USER ENTRY: CARBS $carbsAfterConstraints time: $time duration: $duration")
|
||||
carbsGenerator.generateCarbs(carbsAfterConstraints, time, duration, notes)
|
||||
nsUpload.uploadEvent(CareportalEvent.NOTE, DateUtil.now() - 2000, resourceHelper.gs(R.string.generated_ecarbs_note, carbsAfterConstraints, duration, timeOffset))
|
||||
}
|
||||
}
|
||||
}, null)
|
||||
}
|
||||
} else
|
||||
activity?.let { activity ->
|
||||
OKDialog.show(activity, MainApp.gs(R.string.carbs), MainApp.gs(R.string.no_action_selected))
|
||||
OKDialog.show(activity, resourceHelper.gs(R.string.carbs), resourceHelper.gs(R.string.no_action_selected))
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -6,41 +6,51 @@ import android.text.TextWatcher
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Button
|
||||
import androidx.annotation.StringRes
|
||||
import com.google.common.base.Joiner
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.Constants
|
||||
import info.nightscout.androidaps.MainApp
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.data.Profile
|
||||
import info.nightscout.androidaps.db.CareportalEvent
|
||||
import info.nightscout.androidaps.db.Source
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.HtmlHelper
|
||||
import info.nightscout.androidaps.utils.OKDialog
|
||||
import info.nightscout.androidaps.utils.SP
|
||||
import info.nightscout.androidaps.utils.Translator
|
||||
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import kotlinx.android.synthetic.main.dialog_care.*
|
||||
import kotlinx.android.synthetic.main.notes.*
|
||||
import kotlinx.android.synthetic.main.okcancel.*
|
||||
import org.json.JSONObject
|
||||
import java.text.DecimalFormat
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class CareDialog : DialogFragmentWithDate() {
|
||||
@Inject lateinit var injector: HasAndroidInjector
|
||||
@Inject lateinit var mainApp: MainApp
|
||||
@Inject lateinit var resourceHelper: ResourceHelper
|
||||
@Inject lateinit var profileFunction: ProfileFunction
|
||||
@Inject lateinit var nsUpload: NSUpload
|
||||
@Inject lateinit var translator: Translator
|
||||
|
||||
enum class EventType {
|
||||
BGCHECK,
|
||||
SENSOR_INSERT,
|
||||
BATTERY_CHANGE,
|
||||
NOTE,
|
||||
EXERCISE
|
||||
EXERCISE,
|
||||
QUESTION,
|
||||
ANNOUNCEMENT
|
||||
}
|
||||
|
||||
private var options: EventType = EventType.BGCHECK
|
||||
|
||||
@StringRes
|
||||
private var event: Int = R.string.none
|
||||
|
||||
|
@ -73,39 +83,47 @@ class CareDialog : DialogFragmentWithDate() {
|
|||
}
|
||||
|
||||
actions_care_icon.setImageResource(when (options) {
|
||||
EventType.BGCHECK -> R.drawable.icon_cp_bgcheck
|
||||
EventType.SENSOR_INSERT -> R.drawable.icon_cp_cgm_insert
|
||||
EventType.BATTERY_CHANGE -> R.drawable.icon_cp_pump_battery
|
||||
EventType.NOTE -> R.drawable.icon_cp_note
|
||||
EventType.EXERCISE -> R.drawable.icon_cp_exercise
|
||||
EventType.BGCHECK -> R.drawable.ic_cp_bgcheck
|
||||
EventType.SENSOR_INSERT -> R.drawable.ic_cp_cgm_insert
|
||||
EventType.BATTERY_CHANGE -> R.drawable.ic_cp_pump_battery
|
||||
EventType.NOTE -> R.drawable.ic_cp_note
|
||||
EventType.EXERCISE -> R.drawable.ic_cp_exercise
|
||||
EventType.QUESTION -> R.drawable.ic_cp_question
|
||||
EventType.ANNOUNCEMENT -> R.drawable.ic_cp_announcement
|
||||
})
|
||||
actions_care_title.text = MainApp.gs(when (options) {
|
||||
actions_care_title.text = resourceHelper.gs(when (options) {
|
||||
EventType.BGCHECK -> R.string.careportal_bgcheck
|
||||
EventType.SENSOR_INSERT -> R.string.careportal_cgmsensorinsert
|
||||
EventType.BATTERY_CHANGE -> R.string.careportal_pumpbatterychange
|
||||
EventType.NOTE -> R.string.careportal_note
|
||||
EventType.EXERCISE -> R.string.careportal_exercise
|
||||
EventType.QUESTION -> R.string.careportal_question
|
||||
EventType.ANNOUNCEMENT -> R.string.careportal_announcement
|
||||
})
|
||||
|
||||
when (options) {
|
||||
EventType.QUESTION,
|
||||
EventType.ANNOUNCEMENT,
|
||||
EventType.BGCHECK -> {
|
||||
action_care_duration_layout.visibility = View.GONE
|
||||
}
|
||||
|
||||
EventType.SENSOR_INSERT,
|
||||
EventType.BATTERY_CHANGE -> {
|
||||
action_care_bg_layout.visibility = View.GONE
|
||||
actions_care_bgsource.visibility = View.GONE
|
||||
action_care_duration_layout.visibility = View.GONE
|
||||
}
|
||||
|
||||
EventType.NOTE,
|
||||
EventType.EXERCISE -> {
|
||||
EventType.EXERCISE -> {
|
||||
action_care_bg_layout.visibility = View.GONE
|
||||
actions_care_bgsource.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
val bg = Profile.fromMgdlToUnits(GlucoseStatus.getGlucoseStatusData()?.glucose
|
||||
?: 0.0, ProfileFunctions.getSystemUnits())
|
||||
val bg = Profile.fromMgdlToUnits(GlucoseStatus(injector).getGlucoseStatusData()?.glucose
|
||||
?: 0.0, profileFunction.getUnits())
|
||||
val bgTextWatcher: TextWatcher = object : TextWatcher {
|
||||
override fun afterTextChanged(s: Editable) {}
|
||||
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
|
||||
|
@ -114,52 +132,52 @@ class CareDialog : DialogFragmentWithDate() {
|
|||
}
|
||||
}
|
||||
|
||||
if (ProfileFunctions.getSystemUnits() == Constants.MMOL) {
|
||||
actions_care_bgunits.text = MainApp.gs(R.string.mmol)
|
||||
if (profileFunction.getUnits() == Constants.MMOL) {
|
||||
actions_care_bgunits.text = resourceHelper.gs(R.string.mmol)
|
||||
actions_care_bg.setParams(savedInstanceState?.getDouble("actions_care_bg")
|
||||
?: bg, 2.0, 30.0, 0.1, DecimalFormat("0.0"), false, ok, bgTextWatcher)
|
||||
} else {
|
||||
actions_care_bgunits.text = MainApp.gs(R.string.mgdl)
|
||||
actions_care_bgunits.text = resourceHelper.gs(R.string.mgdl)
|
||||
actions_care_bg.setParams(savedInstanceState?.getDouble("actions_care_bg")
|
||||
?: bg, 36.0, 500.0, 1.0, DecimalFormat("0"), false, ok, bgTextWatcher)
|
||||
}
|
||||
actions_care_duration.setParams(savedInstanceState?.getDouble("actions_care_duration")
|
||||
?: 0.0, 0.0, Constants.MAX_PROFILE_SWITCH_DURATION, 10.0, DecimalFormat("0"), false, ok)
|
||||
if (options == EventType.NOTE)
|
||||
if (options == EventType.NOTE || options == EventType.QUESTION || options == EventType.ANNOUNCEMENT)
|
||||
notes_layout?.visibility = View.VISIBLE // independent to preferences
|
||||
}
|
||||
|
||||
override fun submit(): Boolean {
|
||||
val enteredBy = SP.getString("careportal_enteredby", "")
|
||||
val unitResId = if (ProfileFunctions.getSystemUnits() == Constants.MGDL) R.string.mgdl else R.string.mmol
|
||||
val enteredBy = sp.getString("careportal_enteredby", "")
|
||||
val unitResId = if (profileFunction.getUnits() == Constants.MGDL) R.string.mgdl else R.string.mmol
|
||||
|
||||
val json = JSONObject()
|
||||
val actions: LinkedList<String> = LinkedList()
|
||||
if (options == EventType.BGCHECK) {
|
||||
if (options == EventType.BGCHECK || options == EventType.QUESTION || options == EventType.ANNOUNCEMENT) {
|
||||
val type =
|
||||
when {
|
||||
actions_care_meter.isChecked -> "Finger"
|
||||
actions_care_sensor.isChecked -> "Sensor"
|
||||
else -> "Manual"
|
||||
actions_care_meter.isChecked -> CareportalEvent.FINGER
|
||||
actions_care_sensor.isChecked -> CareportalEvent.SENSOR
|
||||
else -> CareportalEvent.MANUAL
|
||||
}
|
||||
actions.add(MainApp.gs(R.string.careportal_newnstreatment_glucosetype) + ": " + Translator.translate(type))
|
||||
actions.add(MainApp.gs(R.string.treatments_wizard_bg_label) + ": " + Profile.toCurrentUnitsString(actions_care_bg.value) + " " + MainApp.gs(unitResId))
|
||||
actions.add(resourceHelper.gs(R.string.careportal_newnstreatment_glucosetype) + ": " + translator.translate(type))
|
||||
actions.add(resourceHelper.gs(R.string.treatments_wizard_bg_label) + ": " + Profile.toCurrentUnitsString(profileFunction, actions_care_bg.value) + " " + resourceHelper.gs(unitResId))
|
||||
json.put("glucose", actions_care_bg.value)
|
||||
json.put("glucoseType", type)
|
||||
}
|
||||
if (options == EventType.NOTE || options == EventType.EXERCISE) {
|
||||
actions.add(MainApp.gs(R.string.careportal_newnstreatment_duration_label) + ": " + MainApp.gs(R.string.format_mins, actions_care_duration.value.toInt()))
|
||||
actions.add(resourceHelper.gs(R.string.careportal_newnstreatment_duration_label) + ": " + resourceHelper.gs(R.string.format_mins, actions_care_duration.value.toInt()))
|
||||
json.put("duration", actions_care_duration.value.toInt())
|
||||
}
|
||||
val notes = notes.text.toString()
|
||||
if (notes.isNotEmpty()) {
|
||||
actions.add(MainApp.gs(R.string.careportal_newnstreatment_notes_label) + ": " + notes)
|
||||
actions.add(resourceHelper.gs(R.string.careportal_newnstreatment_notes_label) + ": " + notes)
|
||||
json.put("notes", notes)
|
||||
}
|
||||
eventTime -= eventTime % 1000
|
||||
|
||||
if (eventTimeChanged)
|
||||
actions.add(MainApp.gs(R.string.time) + ": " + DateUtil.dateAndTimeString(eventTime))
|
||||
actions.add(resourceHelper.gs(R.string.time) + ": " + dateUtil.dateAndTimeString(eventTime))
|
||||
|
||||
json.put("created_at", DateUtil.toISOString(eventTime))
|
||||
json.put("mills", eventTime)
|
||||
|
@ -169,14 +187,16 @@ class CareDialog : DialogFragmentWithDate() {
|
|||
EventType.BATTERY_CHANGE -> CareportalEvent.PUMPBATTERYCHANGE
|
||||
EventType.NOTE -> CareportalEvent.NOTE
|
||||
EventType.EXERCISE -> CareportalEvent.EXERCISE
|
||||
EventType.QUESTION -> CareportalEvent.QUESTION
|
||||
EventType.ANNOUNCEMENT -> CareportalEvent.ANNOUNCEMENT
|
||||
})
|
||||
json.put("units", ProfileFunctions.getSystemUnits())
|
||||
json.put("units", profileFunction.getUnits())
|
||||
if (enteredBy.isNotEmpty())
|
||||
json.put("enteredBy", enteredBy)
|
||||
|
||||
activity?.let { activity ->
|
||||
OKDialog.showConfirmation(activity, MainApp.gs(event), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
|
||||
val careportalEvent = CareportalEvent()
|
||||
OKDialog.showConfirmation(activity, resourceHelper.gs(event), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
|
||||
val careportalEvent = CareportalEvent(injector)
|
||||
careportalEvent.date = eventTime
|
||||
careportalEvent.source = Source.USER
|
||||
careportalEvent.eventType = when (options) {
|
||||
|
@ -185,11 +205,13 @@ class CareDialog : DialogFragmentWithDate() {
|
|||
EventType.BATTERY_CHANGE -> CareportalEvent.PUMPBATTERYCHANGE
|
||||
EventType.NOTE -> CareportalEvent.NOTE
|
||||
EventType.EXERCISE -> CareportalEvent.EXERCISE
|
||||
EventType.QUESTION -> CareportalEvent.QUESTION
|
||||
EventType.ANNOUNCEMENT -> CareportalEvent.ANNOUNCEMENT
|
||||
}
|
||||
careportalEvent.json = json.toString()
|
||||
log.debug("USER ENTRY: CAREPORTAL ${careportalEvent.eventType} json: ${careportalEvent.json}")
|
||||
aapsLogger.debug("USER ENTRY: CAREPORTAL ${careportalEvent.eventType} json: ${careportalEvent.json}")
|
||||
MainApp.getDbHelper().createOrUpdate(careportalEvent)
|
||||
NSUpload.uploadCareportalEntryToNS(json)
|
||||
nsUpload.uploadCareportalEntryToNS(json)
|
||||
}, null)
|
||||
}
|
||||
return true
|
||||
|
|
|
@ -8,19 +8,25 @@ import android.view.View
|
|||
import android.view.ViewGroup
|
||||
import android.view.Window
|
||||
import android.view.WindowManager
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import dagger.android.support.DaggerDialogFragment
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.logging.AAPSLogger
|
||||
import info.nightscout.androidaps.logging.LTag
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.SP
|
||||
import info.nightscout.androidaps.utils.toVisibility
|
||||
import info.nightscout.androidaps.utils.extensions.toVisibility
|
||||
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
||||
import kotlinx.android.synthetic.main.datetime.*
|
||||
import kotlinx.android.synthetic.main.notes.*
|
||||
import kotlinx.android.synthetic.main.okcancel.*
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
|
||||
abstract class DialogFragmentWithDate : DialogFragment() {
|
||||
val log = LoggerFactory.getLogger(DialogFragmentWithDate::class.java)
|
||||
abstract class DialogFragmentWithDate : DaggerDialogFragment() {
|
||||
|
||||
@Inject lateinit var aapsLogger: AAPSLogger
|
||||
@Inject lateinit var sp: SP
|
||||
@Inject lateinit var dateUtil: DateUtil
|
||||
|
||||
var eventTime = DateUtil.now()
|
||||
var eventTimeChanged = false
|
||||
|
@ -29,6 +35,7 @@ abstract class DialogFragmentWithDate : DialogFragment() {
|
|||
private var okClicked: Boolean = false
|
||||
|
||||
companion object {
|
||||
|
||||
private var seconds: Int = (Math.random() * 59.0).toInt()
|
||||
}
|
||||
|
||||
|
@ -54,7 +61,7 @@ abstract class DialogFragmentWithDate : DialogFragment() {
|
|||
eventTime = savedInstanceState?.getLong("eventTime") ?: DateUtil.now()
|
||||
eventTimeChanged = savedInstanceState?.getBoolean("eventTimeChanged") ?: false
|
||||
overview_eventdate?.text = DateUtil.dateString(eventTime)
|
||||
overview_eventtime?.text = DateUtil.timeString(eventTime)
|
||||
overview_eventtime?.text = dateUtil.timeString(eventTime)
|
||||
|
||||
// create an OnDateSetListener
|
||||
val dateSetListener = DatePickerDialog.OnDateSetListener { _, year, monthOfYear, dayOfMonth ->
|
||||
|
@ -89,7 +96,7 @@ abstract class DialogFragmentWithDate : DialogFragment() {
|
|||
cal.set(Calendar.SECOND, seconds++) // randomize seconds to prevent creating record of the same time, if user choose time manually
|
||||
eventTime = cal.timeInMillis
|
||||
eventTimeChanged = true
|
||||
overview_eventtime?.text = DateUtil.timeString(eventTime)
|
||||
overview_eventtime?.text = dateUtil.timeString(eventTime)
|
||||
}
|
||||
|
||||
overview_eventtime?.setOnClickListener {
|
||||
|
@ -104,12 +111,12 @@ abstract class DialogFragmentWithDate : DialogFragment() {
|
|||
}
|
||||
}
|
||||
|
||||
notes_layout?.visibility = SP.getBoolean(R.string.key_show_notes_entry_dialogs, false).toVisibility()
|
||||
notes_layout?.visibility = sp.getBoolean(R.string.key_show_notes_entry_dialogs, false).toVisibility()
|
||||
|
||||
ok.setOnClickListener {
|
||||
synchronized(okClicked) {
|
||||
if (okClicked) {
|
||||
log.debug("guarding: ok already clicked")
|
||||
aapsLogger.warn(LTag.UI, "guarding: ok already clicked")
|
||||
} else {
|
||||
okClicked = true
|
||||
if (submit()) dismiss()
|
||||
|
@ -120,5 +127,16 @@ abstract class DialogFragmentWithDate : DialogFragment() {
|
|||
cancel.setOnClickListener { dismiss() }
|
||||
}
|
||||
|
||||
override fun show(manager: FragmentManager, tag: String?) {
|
||||
try {
|
||||
manager.beginTransaction().let {
|
||||
it.add(this, tag)
|
||||
it.commitAllowingStateLoss()
|
||||
}
|
||||
} catch (e: IllegalStateException) {
|
||||
aapsLogger.debug(e.localizedMessage)
|
||||
}
|
||||
}
|
||||
|
||||
abstract fun submit(): Boolean
|
||||
}
|
|
@ -9,19 +9,29 @@ import com.google.common.base.Joiner
|
|||
import info.nightscout.androidaps.MainApp
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.activities.ErrorHelperActivity
|
||||
import info.nightscout.androidaps.interfaces.ActivePluginProvider
|
||||
import info.nightscout.androidaps.interfaces.CommandQueueProvider
|
||||
import info.nightscout.androidaps.interfaces.Constraint
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
||||
import info.nightscout.androidaps.queue.Callback
|
||||
import info.nightscout.androidaps.utils.HtmlHelper
|
||||
import info.nightscout.androidaps.utils.OKDialog
|
||||
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
||||
import info.nightscout.androidaps.utils.SafeParse
|
||||
import info.nightscout.androidaps.utils.extensions.formatColor
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import kotlinx.android.synthetic.main.dialog_extendedbolus.*
|
||||
import kotlinx.android.synthetic.main.okcancel.*
|
||||
import java.text.DecimalFormat
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
import kotlin.math.abs
|
||||
|
||||
class ExtendedBolusDialog : DialogFragmentWithDate() {
|
||||
@Inject lateinit var mainApp: MainApp
|
||||
@Inject lateinit var resourceHelper: ResourceHelper
|
||||
@Inject lateinit var constraintChecker: ConstraintChecker
|
||||
@Inject lateinit var commandQueue: CommandQueueProvider
|
||||
@Inject lateinit var activePlugin: ActivePluginProvider
|
||||
|
||||
override fun onSaveInstanceState(savedInstanceState: Bundle) {
|
||||
super.onSaveInstanceState(savedInstanceState)
|
||||
|
@ -38,9 +48,9 @@ class ExtendedBolusDialog : DialogFragmentWithDate() {
|
|||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
val pumpDescription = ConfigBuilderPlugin.getPlugin().activePump?.pumpDescription ?: return
|
||||
val pumpDescription = activePlugin.activePump.pumpDescription
|
||||
|
||||
val maxInsulin = MainApp.getConstraintChecker().maxExtendedBolusAllowed.value()
|
||||
val maxInsulin = constraintChecker.getMaxExtendedBolusAllowed().value()
|
||||
val extendedStep = pumpDescription.extendedBolusStep
|
||||
actions_extendedbolus_insulin.setParams(savedInstanceState?.getDouble("actions_extendedbolus_insulin")
|
||||
?: extendedStep, extendedStep, maxInsulin, extendedStep, DecimalFormat("0.00"), false, ok)
|
||||
|
@ -53,26 +63,26 @@ class ExtendedBolusDialog : DialogFragmentWithDate() {
|
|||
|
||||
override fun submit(): Boolean {
|
||||
val insulin = SafeParse.stringToDouble(actions_extendedbolus_insulin.text)
|
||||
val durationInMinutes = SafeParse.stringToInt(actions_extendedbolus_duration.text)
|
||||
val durationInMinutes = actions_extendedbolus_duration.value.toInt()
|
||||
val actions: LinkedList<String> = LinkedList()
|
||||
val insulinAfterConstraint = MainApp.getConstraintChecker().applyExtendedBolusConstraints(Constraint(insulin)).value()
|
||||
actions.add(MainApp.gs(R.string.formatinsulinunits, insulinAfterConstraint))
|
||||
actions.add(MainApp.gs(R.string.duration) + ": " + MainApp.gs(R.string.format_mins, durationInMinutes))
|
||||
val insulinAfterConstraint = constraintChecker.applyExtendedBolusConstraints(Constraint(insulin)).value()
|
||||
actions.add(resourceHelper.gs(R.string.formatinsulinunits, insulinAfterConstraint))
|
||||
actions.add(resourceHelper.gs(R.string.duration) + ": " + resourceHelper.gs(R.string.format_mins, durationInMinutes))
|
||||
if (abs(insulinAfterConstraint - insulin) > 0.01)
|
||||
actions.add("<font color='" + MainApp.gc(R.color.warning) + "'>" + MainApp.gs(R.string.constraintapllied) + "</font>")
|
||||
actions.add(resourceHelper.gs(R.string.constraintapllied).formatColor(resourceHelper, R.color.warning))
|
||||
|
||||
activity?.let { activity ->
|
||||
OKDialog.showConfirmation(activity, MainApp.gs(R.string.extended_bolus), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
|
||||
log.debug("USER ENTRY: EXTENDED BOLUS $insulinAfterConstraint duration: $durationInMinutes")
|
||||
ConfigBuilderPlugin.getPlugin().commandQueue.extendedBolus(insulinAfterConstraint, durationInMinutes, object : Callback() {
|
||||
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.extended_bolus), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
|
||||
aapsLogger.debug("USER ENTRY: EXTENDED BOLUS $insulinAfterConstraint duration: $durationInMinutes")
|
||||
commandQueue.extendedBolus(insulinAfterConstraint, durationInMinutes, object : Callback() {
|
||||
override fun run() {
|
||||
if (!result.success) {
|
||||
val i = Intent(MainApp.instance(), ErrorHelperActivity::class.java)
|
||||
val i = Intent(mainApp, ErrorHelperActivity::class.java)
|
||||
i.putExtra("soundid", R.raw.boluserror)
|
||||
i.putExtra("status", result.comment)
|
||||
i.putExtra("title", MainApp.gs(R.string.treatmentdeliveryerror))
|
||||
i.putExtra("title", resourceHelper.gs(R.string.treatmentdeliveryerror))
|
||||
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
MainApp.instance().startActivity(i)
|
||||
mainApp.startActivity(i)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
@ -1,35 +1,47 @@
|
|||
package info.nightscout.androidaps.dialogs
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.google.common.base.Joiner
|
||||
import info.nightscout.androidaps.MainApp
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.activities.ErrorHelperActivity
|
||||
import info.nightscout.androidaps.data.DetailedBolusInfo
|
||||
import info.nightscout.androidaps.db.CareportalEvent
|
||||
import info.nightscout.androidaps.db.Source
|
||||
import info.nightscout.androidaps.interfaces.ActivePluginProvider
|
||||
import info.nightscout.androidaps.interfaces.CommandQueueProvider
|
||||
import info.nightscout.androidaps.interfaces.Constraint
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
|
||||
import info.nightscout.androidaps.queue.Callback
|
||||
import info.nightscout.androidaps.utils.*
|
||||
import info.nightscout.androidaps.utils.DecimalFormatter
|
||||
import info.nightscout.androidaps.utils.HtmlHelper
|
||||
import info.nightscout.androidaps.utils.SafeParse
|
||||
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
||||
import info.nightscout.androidaps.utils.extensions.formatColor
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import kotlinx.android.synthetic.main.dialog_fill.*
|
||||
import kotlinx.android.synthetic.main.notes.*
|
||||
import kotlinx.android.synthetic.main.okcancel.*
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
import kotlin.math.abs
|
||||
|
||||
class FillDialog : DialogFragmentWithDate() {
|
||||
@Inject lateinit var constraintChecker: ConstraintChecker
|
||||
@Inject lateinit var resourceHelper: ResourceHelper
|
||||
@Inject lateinit var ctx: Context
|
||||
@Inject lateinit var nsUpload: NSUpload
|
||||
@Inject lateinit var commandQueue: CommandQueueProvider
|
||||
@Inject lateinit var activePlugin: ActivePluginProvider
|
||||
|
||||
override fun onSaveInstanceState(savedInstanceState: Bundle) {
|
||||
super.onSaveInstanceState(savedInstanceState)
|
||||
savedInstanceState.putDouble("fill_insulinamount", fill_insulinamount.value)
|
||||
savedInstanceState.putDouble("fill_insulin_amount", fill_insulinamount.value)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
|
@ -41,30 +53,30 @@ class FillDialog : DialogFragmentWithDate() {
|
|||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
val maxInsulin = MainApp.getConstraintChecker().maxBolusAllowed.value()
|
||||
val bolusStep = ConfigBuilderPlugin.getPlugin().activePump!!.pumpDescription.bolusStep
|
||||
fill_insulinamount.setParams(savedInstanceState?.getDouble("fill_insulinamount")
|
||||
?: 0.0, 0.0, maxInsulin, bolusStep, DecimalFormatter.pumpSupportedBolusFormat(), true, ok)
|
||||
val amount1 = SP.getDouble("fill_button1", 0.3)
|
||||
val maxInsulin = constraintChecker.getMaxBolusAllowed().value()
|
||||
val bolusStep = activePlugin.activePump.pumpDescription.bolusStep
|
||||
fill_insulinamount.setParams(savedInstanceState?.getDouble("fill_insulin_amount")
|
||||
?: 0.0, 0.0, maxInsulin, bolusStep, DecimalFormatter.pumpSupportedBolusFormat(activePlugin.activePump), true, ok)
|
||||
val amount1 = sp.getDouble("fill_button1", 0.3)
|
||||
if (amount1 > 0) {
|
||||
fill_preset_button1.visibility = View.VISIBLE
|
||||
fill_preset_button1.text = DecimalFormatter.toPumpSupportedBolus(amount1) // + "U");
|
||||
fill_preset_button1.text = DecimalFormatter.toPumpSupportedBolus(amount1, activePlugin.activePump) // + "U");
|
||||
fill_preset_button1.setOnClickListener { fill_insulinamount.value = amount1 }
|
||||
} else {
|
||||
fill_preset_button1.visibility = View.GONE
|
||||
}
|
||||
val amount2 = SP.getDouble("fill_button2", 0.0)
|
||||
val amount2 = sp.getDouble("fill_button2", 0.0)
|
||||
if (amount2 > 0) {
|
||||
fill_preset_button2.visibility = View.VISIBLE
|
||||
fill_preset_button2.text = DecimalFormatter.toPumpSupportedBolus(amount2) // + "U");
|
||||
fill_preset_button2.text = DecimalFormatter.toPumpSupportedBolus(amount2, activePlugin.activePump) // + "U");
|
||||
fill_preset_button2.setOnClickListener { fill_insulinamount.value = amount2 }
|
||||
} else {
|
||||
fill_preset_button2.visibility = View.GONE
|
||||
}
|
||||
val amount3 = SP.getDouble("fill_button3", 0.0)
|
||||
val amount3 = sp.getDouble("fill_button3", 0.0)
|
||||
if (amount3 > 0) {
|
||||
fill_preset_button3.visibility = View.VISIBLE
|
||||
fill_preset_button3.text = DecimalFormatter.toPumpSupportedBolus(amount3) // + "U");
|
||||
fill_preset_button3.text = DecimalFormatter.toPumpSupportedBolus(amount3, activePlugin.activePump) // + "U");
|
||||
fill_preset_button3.setOnClickListener { fill_insulinamount.value = amount3 }
|
||||
} else {
|
||||
fill_preset_button3.visibility = View.GONE
|
||||
|
@ -76,49 +88,49 @@ class FillDialog : DialogFragmentWithDate() {
|
|||
val insulin = SafeParse.stringToDouble(fill_insulinamount.text)
|
||||
val actions: LinkedList<String?> = LinkedList()
|
||||
|
||||
val insulinAfterConstraints = MainApp.getConstraintChecker().applyBolusConstraints(Constraint(insulin)).value()
|
||||
val insulinAfterConstraints = constraintChecker.applyBolusConstraints(Constraint(insulin)).value()
|
||||
if (insulinAfterConstraints > 0) {
|
||||
actions.add(MainApp.gs(R.string.fillwarning))
|
||||
actions.add(resourceHelper.gs(R.string.fillwarning))
|
||||
actions.add("")
|
||||
actions.add(MainApp.gs(R.string.bolus) + ": " + "<font color='" + MainApp.gc(R.color.colorInsulinButton) + "'>" + DecimalFormatter.toPumpSupportedBolus(insulinAfterConstraints) + MainApp.gs(R.string.insulin_unit_shortname) + "</font>")
|
||||
actions.add(resourceHelper.gs(R.string.bolus) + ": " + DecimalFormatter.toPumpSupportedBolus(insulinAfterConstraints, activePlugin.activePump, resourceHelper).formatColor(resourceHelper, R.color.colorInsulinButton))
|
||||
if (abs(insulinAfterConstraints - insulin) > 0.01)
|
||||
actions.add(MainApp.gs(R.string.bolusconstraintappliedwarning, MainApp.gc(R.color.warning), insulin, insulinAfterConstraints))
|
||||
actions.add(resourceHelper.gs(R.string.bolusconstraintappliedwarn, insulin, insulinAfterConstraints).formatColor(resourceHelper, R.color.warning))
|
||||
}
|
||||
val siteChange = fill_catheter_change.isChecked
|
||||
if (siteChange)
|
||||
actions.add("" + "<font color='" + MainApp.gc(R.color.actionsConfirm) + "'>" + MainApp.gs(R.string.record_pump_site_change) + "</font>")
|
||||
actions.add(resourceHelper.gs(R.string.record_pump_site_change).formatColor(resourceHelper, R.color.actionsConfirm))
|
||||
val insulinChange = fill_cartridge_change.isChecked
|
||||
if (insulinChange)
|
||||
actions.add("" + "<font color='" + MainApp.gc(R.color.actionsConfirm) + "'>" + MainApp.gs(R.string.record_insulin_cartridge_change) + "</font>")
|
||||
actions.add(resourceHelper.gs(R.string.record_insulin_cartridge_change).formatColor(resourceHelper, R.color.actionsConfirm))
|
||||
val notes = notes.text.toString()
|
||||
if (notes.isNotEmpty())
|
||||
actions.add(MainApp.gs(R.string.careportal_newnstreatment_notes_label) + ": " + notes)
|
||||
actions.add(resourceHelper.gs(R.string.careportal_newnstreatment_notes_label) + ": " + notes)
|
||||
eventTime -= eventTime % 1000
|
||||
|
||||
if (eventTimeChanged)
|
||||
actions.add(MainApp.gs(R.string.time) + ": " + DateUtil.dateAndTimeString(eventTime))
|
||||
actions.add(resourceHelper.gs(R.string.time) + ": " + dateUtil.dateAndTimeString(eventTime))
|
||||
|
||||
if (insulinAfterConstraints > 0 || fill_catheter_change.isChecked || fill_cartridge_change.isChecked) {
|
||||
activity?.let { activity ->
|
||||
OKDialog.showConfirmation(activity, MainApp.gs(R.string.primefill), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
|
||||
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.primefill), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
|
||||
if (insulinAfterConstraints > 0) {
|
||||
log.debug("USER ENTRY: PRIME BOLUS $insulinAfterConstraints")
|
||||
aapsLogger.debug("USER ENTRY: PRIME BOLUS $insulinAfterConstraints")
|
||||
requestPrimeBolus(insulinAfterConstraints, notes)
|
||||
}
|
||||
if (siteChange) {
|
||||
log.debug("USER ENTRY: SITE CHANGE")
|
||||
generateCareportalEvent(CareportalEvent.SITECHANGE, eventTime, notes)
|
||||
aapsLogger.debug("USER ENTRY: SITE CHANGE")
|
||||
nsUpload.generateCareportalEvent(CareportalEvent.SITECHANGE, eventTime, notes)
|
||||
}
|
||||
if (insulinChange) {
|
||||
// add a second for case of both checked
|
||||
log.debug("USER ENTRY: INSULIN CHANGE")
|
||||
generateCareportalEvent(CareportalEvent.INSULINCHANGE, eventTime + 1000, notes)
|
||||
aapsLogger.debug("USER ENTRY: INSULIN CHANGE")
|
||||
nsUpload.generateCareportalEvent(CareportalEvent.INSULINCHANGE, eventTime + 1000, notes)
|
||||
}
|
||||
}, null)
|
||||
}
|
||||
} else {
|
||||
activity?.let { activity ->
|
||||
OKDialog.show(activity, MainApp.gs(R.string.primefill), MainApp.gs(R.string.no_action_selected))
|
||||
OKDialog.show(activity, resourceHelper.gs(R.string.primefill), resourceHelper.gs(R.string.no_action_selected))
|
||||
}
|
||||
}
|
||||
dismiss()
|
||||
|
@ -132,41 +144,17 @@ class FillDialog : DialogFragmentWithDate() {
|
|||
detailedBolusInfo.source = Source.USER
|
||||
detailedBolusInfo.isValid = false // do not count it in IOB (for pump history)
|
||||
detailedBolusInfo.notes = notes
|
||||
ConfigBuilderPlugin.getPlugin().commandQueue.bolus(detailedBolusInfo, object : Callback() {
|
||||
commandQueue.bolus(detailedBolusInfo, object : Callback() {
|
||||
override fun run() {
|
||||
if (!result.success) {
|
||||
val i = Intent(MainApp.instance(), ErrorHelperActivity::class.java)
|
||||
val i = Intent(ctx, ErrorHelperActivity::class.java)
|
||||
i.putExtra("soundid", R.raw.boluserror)
|
||||
i.putExtra("status", result.comment)
|
||||
i.putExtra("title", MainApp.gs(R.string.treatmentdeliveryerror))
|
||||
i.putExtra("title", resourceHelper.gs(R.string.treatmentdeliveryerror))
|
||||
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
MainApp.instance().startActivity(i)
|
||||
ctx.startActivity(i)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun generateCareportalEvent(eventType: String, time: Long, notes: String) {
|
||||
val careportalEvent = CareportalEvent()
|
||||
careportalEvent.source = Source.USER
|
||||
careportalEvent.date = time
|
||||
careportalEvent.json = generateJson(eventType, time, notes).toString()
|
||||
careportalEvent.eventType = eventType
|
||||
MainApp.getDbHelper().createOrUpdate(careportalEvent)
|
||||
NSUpload.uploadEvent(eventType, time, notes)
|
||||
}
|
||||
|
||||
private fun generateJson(careportalEvent: String, time: Long, notes: String): JSONObject {
|
||||
val data = JSONObject()
|
||||
try {
|
||||
data.put("eventType", careportalEvent)
|
||||
data.put("created_at", DateUtil.toISOString(time))
|
||||
data.put("mills", time)
|
||||
data.put("enteredBy", SP.getString("careportal_enteredby", MainApp.gs(R.string.app_name)))
|
||||
if (notes.isNotEmpty()) data.put("notes", notes)
|
||||
} catch (ignored: JSONException) {
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package info.nightscout.androidaps.dialogs
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.text.Editable
|
||||
|
@ -8,8 +9,8 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.google.common.base.Joiner
|
||||
import info.nightscout.androidaps.Config
|
||||
import info.nightscout.androidaps.Constants
|
||||
import info.nightscout.androidaps.MainApp
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.activities.ErrorHelperActivity
|
||||
import info.nightscout.androidaps.data.DetailedBolusInfo
|
||||
|
@ -17,21 +18,36 @@ 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.interfaces.ActivePluginProvider
|
||||
import info.nightscout.androidaps.interfaces.CommandQueueProvider
|
||||
import info.nightscout.androidaps.interfaces.Constraint
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions
|
||||
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||
import info.nightscout.androidaps.queue.Callback
|
||||
import info.nightscout.androidaps.utils.*
|
||||
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
||||
import info.nightscout.androidaps.utils.extensions.formatColor
|
||||
import info.nightscout.androidaps.utils.extensions.toSignedString
|
||||
import info.nightscout.androidaps.utils.extensions.toVisibility
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import kotlinx.android.synthetic.main.dialog_insulin.*
|
||||
import kotlinx.android.synthetic.main.notes.*
|
||||
import kotlinx.android.synthetic.main.okcancel.*
|
||||
import java.text.DecimalFormat
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.max
|
||||
|
||||
class InsulinDialog : DialogFragmentWithDate() {
|
||||
@Inject lateinit var constraintChecker: ConstraintChecker
|
||||
@Inject lateinit var resourceHelper: ResourceHelper
|
||||
@Inject lateinit var defaultValueHelper: DefaultValueHelper
|
||||
@Inject lateinit var profileFunction: ProfileFunction
|
||||
@Inject lateinit var commandQueue: CommandQueueProvider
|
||||
@Inject lateinit var activePlugin: ActivePluginProvider
|
||||
@Inject lateinit var ctx: Context
|
||||
@Inject lateinit var config: Config
|
||||
|
||||
companion object {
|
||||
private const val PLUS1_DEFAULT = 0.5
|
||||
|
@ -39,8 +55,6 @@ class InsulinDialog : DialogFragmentWithDate() {
|
|||
private const val PLUS3_DEFAULT = 2.0
|
||||
}
|
||||
|
||||
private val maxInsulin = MainApp.getConstraintChecker().maxBolusAllowed.value()
|
||||
|
||||
private val textWatcher: TextWatcher = object : TextWatcher {
|
||||
override fun afterTextChanged(s: Editable) {
|
||||
validateInputs()
|
||||
|
@ -51,13 +65,14 @@ class InsulinDialog : DialogFragmentWithDate() {
|
|||
}
|
||||
|
||||
private fun validateInputs() {
|
||||
val maxInsulin = constraintChecker.getMaxBolusAllowed().value()
|
||||
if (abs(overview_insulin_time.value.toInt()) > 12 * 60) {
|
||||
overview_insulin_time.value = 0.0
|
||||
ToastUtils.showToastInUiThread(MainApp.instance().applicationContext, MainApp.gs(R.string.constraintapllied))
|
||||
ToastUtils.showToastInUiThread(context, resourceHelper.gs(R.string.constraintapllied))
|
||||
}
|
||||
if (overview_insulin_amount.value > maxInsulin) {
|
||||
overview_insulin_amount.value = 0.0
|
||||
ToastUtils.showToastInUiThread(MainApp.instance().applicationContext, MainApp.gs(R.string.bolusconstraintapplied))
|
||||
ToastUtils.showToastInUiThread(context, resourceHelper.gs(R.string.bolusconstraintapplied))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,27 +91,33 @@ class InsulinDialog : DialogFragmentWithDate() {
|
|||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
if (config.NSCLIENT) {
|
||||
overview_insulin_record_only.isChecked = true
|
||||
overview_insulin_record_only.isEnabled = false
|
||||
}
|
||||
val maxInsulin = constraintChecker.getMaxBolusAllowed().value()
|
||||
|
||||
overview_insulin_time.setParams(savedInstanceState?.getDouble("overview_insulin_time")
|
||||
?: 0.0, -12 * 60.0, 12 * 60.0, 5.0, DecimalFormat("0"), false, ok, textWatcher)
|
||||
overview_insulin_amount.setParams(savedInstanceState?.getDouble("overview_insulin_amount")
|
||||
?: 0.0, 0.0, maxInsulin, ConfigBuilderPlugin.getPlugin().activePump!!.pumpDescription.bolusStep, DecimalFormatter.pumpSupportedBolusFormat(), false, ok, textWatcher)
|
||||
?: 0.0, 0.0, maxInsulin, activePlugin.activePump.pumpDescription.bolusStep, DecimalFormatter.pumpSupportedBolusFormat(activePlugin.activePump), false, ok, textWatcher)
|
||||
|
||||
overview_insulin_plus05.text = toSignedString(SP.getDouble(MainApp.gs(R.string.key_insulin_button_increment_1), PLUS1_DEFAULT))
|
||||
overview_insulin_plus05.text = sp.getDouble(resourceHelper.gs(R.string.key_insulin_button_increment_1), PLUS1_DEFAULT).toSignedString(activePlugin.activePump)
|
||||
overview_insulin_plus05.setOnClickListener {
|
||||
overview_insulin_amount.value = max(0.0, overview_insulin_amount.value
|
||||
+ SP.getDouble(MainApp.gs(R.string.key_insulin_button_increment_1), PLUS1_DEFAULT))
|
||||
+ sp.getDouble(resourceHelper.gs(R.string.key_insulin_button_increment_1), PLUS1_DEFAULT))
|
||||
validateInputs()
|
||||
}
|
||||
overview_insulin_plus10.text = toSignedString(SP.getDouble(MainApp.gs(R.string.key_insulin_button_increment_2), PLUS2_DEFAULT))
|
||||
overview_insulin_plus10.text = sp.getDouble(resourceHelper.gs(R.string.key_insulin_button_increment_2), PLUS2_DEFAULT).toSignedString(activePlugin.activePump)
|
||||
overview_insulin_plus10.setOnClickListener {
|
||||
overview_insulin_amount.value = max(0.0, overview_insulin_amount.value
|
||||
+ SP.getDouble(MainApp.gs(R.string.key_insulin_button_increment_2), PLUS2_DEFAULT))
|
||||
+ sp.getDouble(resourceHelper.gs(R.string.key_insulin_button_increment_2), PLUS2_DEFAULT))
|
||||
validateInputs()
|
||||
}
|
||||
overview_insulin_plus20.text = toSignedString(SP.getDouble(MainApp.gs(R.string.key_insulin_button_increment_3), PLUS3_DEFAULT))
|
||||
overview_insulin_plus20.text = sp.getDouble(resourceHelper.gs(R.string.key_insulin_button_increment_3), PLUS3_DEFAULT).toSignedString(activePlugin.activePump)
|
||||
overview_insulin_plus20.setOnClickListener {
|
||||
overview_insulin_amount.value = Math.max(0.0, overview_insulin_amount.value
|
||||
+ SP.getDouble(MainApp.gs(R.string.key_insulin_button_increment_3), PLUS3_DEFAULT))
|
||||
overview_insulin_amount.value = max(0.0, overview_insulin_amount.value
|
||||
+ sp.getDouble(resourceHelper.gs(R.string.key_insulin_button_increment_3), PLUS3_DEFAULT))
|
||||
validateInputs()
|
||||
}
|
||||
|
||||
|
@ -106,56 +127,50 @@ class InsulinDialog : DialogFragmentWithDate() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun toSignedString(value: Double): String {
|
||||
val formatted = DecimalFormatter.toPumpSupportedBolus(value)
|
||||
return if (value > 0) "+$formatted" else formatted
|
||||
}
|
||||
|
||||
override fun submit(): Boolean {
|
||||
val pumpDescription = ConfigBuilderPlugin.getPlugin().activePump?.pumpDescription
|
||||
?: return false
|
||||
val pumpDescription = activePlugin.activePump.pumpDescription
|
||||
val insulin = SafeParse.stringToDouble(overview_insulin_amount.text)
|
||||
val insulinAfterConstraints = MainApp.getConstraintChecker().applyBolusConstraints(Constraint(insulin)).value()
|
||||
val insulinAfterConstraints = constraintChecker.applyBolusConstraints(Constraint(insulin)).value()
|
||||
val actions: LinkedList<String?> = LinkedList()
|
||||
val units = ProfileFunctions.getSystemUnits()
|
||||
val unitLabel = if (units == Constants.MMOL) MainApp.gs(R.string.mmol) else MainApp.gs(R.string.mgdl)
|
||||
val units = profileFunction.getUnits()
|
||||
val unitLabel = if (units == Constants.MMOL) resourceHelper.gs(R.string.mmol) else resourceHelper.gs(R.string.mgdl)
|
||||
val recordOnlyChecked = overview_insulin_record_only.isChecked
|
||||
val eatingSoonChecked = overview_insulin_start_eating_soon_tt.isChecked
|
||||
|
||||
if (insulinAfterConstraints > 0) {
|
||||
actions.add(MainApp.gs(R.string.bolus) + ": " + "<font color='" + MainApp.gc(R.color.bolus) + "'>" + DecimalFormatter.toPumpSupportedBolus(insulinAfterConstraints) + MainApp.gs(R.string.insulin_unit_shortname) + "</font>")
|
||||
actions.add(resourceHelper.gs(R.string.bolus) + ": " + DecimalFormatter.toPumpSupportedBolus(insulinAfterConstraints, activePlugin.activePump, resourceHelper).formatColor(resourceHelper, R.color.bolus))
|
||||
if (recordOnlyChecked)
|
||||
actions.add("<font color='" + MainApp.gc(R.color.warning) + "'>" + MainApp.gs(R.string.bolusrecordedonly) + "</font>")
|
||||
actions.add(resourceHelper.gs(R.string.bolusrecordedonly).formatColor(resourceHelper, R.color.warning))
|
||||
if (abs(insulinAfterConstraints - insulin) > pumpDescription.pumpType.determineCorrectBolusStepSize(insulinAfterConstraints))
|
||||
actions.add(MainApp.gs(R.string.bolusconstraintappliedwarning, MainApp.gc(R.color.warning), insulin, insulinAfterConstraints))
|
||||
actions.add(resourceHelper.gs(R.string.bolusconstraintappliedwarn, insulin, insulinAfterConstraints).formatColor(resourceHelper, R.color.warning))
|
||||
}
|
||||
val eatingSoonTTDuration = DefaultValueHelper.determineEatingSoonTTDuration()
|
||||
val eatingSoonTT = DefaultValueHelper.determineEatingSoonTT()
|
||||
val eatingSoonTTDuration = defaultValueHelper.determineEatingSoonTTDuration()
|
||||
val eatingSoonTT = defaultValueHelper.determineEatingSoonTT()
|
||||
if (eatingSoonChecked)
|
||||
actions.add(MainApp.gs(R.string.temptargetshort) + ": " + "<font color='" + MainApp.gc(R.color.tempTargetConfirmation) + "'>" + DecimalFormatter.to1Decimal(eatingSoonTT) + " " + unitLabel + " (" + eatingSoonTTDuration + " " + MainApp.gs(R.string.unit_minute_short) + ")</font>")
|
||||
actions.add(resourceHelper.gs(R.string.temptargetshort) + ": " + (DecimalFormatter.to1Decimal(eatingSoonTT) + " " + unitLabel + " (" + resourceHelper.gs(R.string.format_mins, eatingSoonTTDuration) + ")").formatColor(resourceHelper, R.color.tempTargetConfirmation))
|
||||
|
||||
val timeOffset = overview_insulin_time.value.toInt()
|
||||
val time = DateUtil.now() + T.mins(timeOffset.toLong()).msecs()
|
||||
if (timeOffset != 0)
|
||||
actions.add(MainApp.gs(R.string.time) + ": " + DateUtil.dateAndTimeString(time))
|
||||
actions.add(resourceHelper.gs(R.string.time) + ": " + dateUtil.dateAndTimeString(time))
|
||||
|
||||
val notes = notes.text.toString()
|
||||
if (notes.isNotEmpty())
|
||||
actions.add(MainApp.gs(R.string.careportal_newnstreatment_notes_label) + ": " + notes)
|
||||
actions.add(resourceHelper.gs(R.string.careportal_newnstreatment_notes_label) + ": " + notes)
|
||||
|
||||
if (insulinAfterConstraints > 0 || eatingSoonChecked) {
|
||||
activity?.let { activity ->
|
||||
OKDialog.showConfirmation(activity, MainApp.gs(R.string.bolus), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
|
||||
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.bolus), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
|
||||
if (eatingSoonChecked) {
|
||||
log.debug("USER ENTRY: TEMPTARGET EATING SOON $eatingSoonTT duration: $eatingSoonTTDuration")
|
||||
aapsLogger.debug("USER ENTRY: TEMPTARGET EATING SOON $eatingSoonTT duration: $eatingSoonTTDuration")
|
||||
val tempTarget = TempTarget()
|
||||
.date(System.currentTimeMillis())
|
||||
.duration(eatingSoonTTDuration)
|
||||
.reason(MainApp.gs(R.string.eatingsoon))
|
||||
.reason(resourceHelper.gs(R.string.eatingsoon))
|
||||
.source(Source.USER)
|
||||
.low(Profile.toMgdl(eatingSoonTT, ProfileFunctions.getSystemUnits()))
|
||||
.high(Profile.toMgdl(eatingSoonTT, ProfileFunctions.getSystemUnits()))
|
||||
TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget)
|
||||
.low(Profile.toMgdl(eatingSoonTT, profileFunction.getUnits()))
|
||||
.high(Profile.toMgdl(eatingSoonTT, profileFunction.getUnits()))
|
||||
activePlugin.activeTreatments.addToHistoryTempTarget(tempTarget)
|
||||
}
|
||||
if (insulinAfterConstraints > 0) {
|
||||
val detailedBolusInfo = DetailedBolusInfo()
|
||||
|
@ -165,21 +180,21 @@ class InsulinDialog : DialogFragmentWithDate() {
|
|||
detailedBolusInfo.source = Source.USER
|
||||
detailedBolusInfo.notes = notes
|
||||
if (recordOnlyChecked) {
|
||||
log.debug("USER ENTRY: BOLUS RECORD ONLY $insulinAfterConstraints")
|
||||
aapsLogger.debug("USER ENTRY: BOLUS RECORD ONLY $insulinAfterConstraints")
|
||||
detailedBolusInfo.date = time
|
||||
TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, false)
|
||||
activePlugin.activeTreatments.addToHistoryTreatment(detailedBolusInfo, false)
|
||||
} else {
|
||||
log.debug("USER ENTRY: BOLUS $insulinAfterConstraints")
|
||||
aapsLogger.debug("USER ENTRY: BOLUS $insulinAfterConstraints")
|
||||
detailedBolusInfo.date = DateUtil.now()
|
||||
ConfigBuilderPlugin.getPlugin().commandQueue.bolus(detailedBolusInfo, object : Callback() {
|
||||
commandQueue.bolus(detailedBolusInfo, object : Callback() {
|
||||
override fun run() {
|
||||
if (!result.success) {
|
||||
val i = Intent(MainApp.instance(), ErrorHelperActivity::class.java)
|
||||
val i = Intent(ctx, ErrorHelperActivity::class.java)
|
||||
i.putExtra("soundid", R.raw.boluserror)
|
||||
i.putExtra("status", result.comment)
|
||||
i.putExtra("title", MainApp.gs(R.string.treatmentdeliveryerror))
|
||||
i.putExtra("title", resourceHelper.gs(R.string.treatmentdeliveryerror))
|
||||
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
MainApp.instance().startActivity(i)
|
||||
ctx.startActivity(i)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -189,7 +204,7 @@ class InsulinDialog : DialogFragmentWithDate() {
|
|||
}
|
||||
} else
|
||||
activity?.let { activity ->
|
||||
OKDialog.show(activity, MainApp.gs(R.string.bolus), MainApp.gs(R.string.no_action_selected))
|
||||
OKDialog.show(activity, resourceHelper.gs(R.string.bolus), resourceHelper.gs(R.string.no_action_selected))
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -7,21 +7,28 @@ import android.view.ViewGroup
|
|||
import android.widget.ArrayAdapter
|
||||
import com.google.common.base.Joiner
|
||||
import info.nightscout.androidaps.Constants
|
||||
import info.nightscout.androidaps.MainApp
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions
|
||||
import info.nightscout.androidaps.interfaces.ActivePluginProvider
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.HtmlHelper
|
||||
import info.nightscout.androidaps.utils.OKDialog
|
||||
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import kotlinx.android.synthetic.main.dialog_profileswitch.*
|
||||
import kotlinx.android.synthetic.main.notes.*
|
||||
import kotlinx.android.synthetic.main.okcancel.*
|
||||
import java.text.DecimalFormat
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class ProfileSwitchDialog : DialogFragmentWithDate() {
|
||||
@Inject lateinit var resourceHelper: ResourceHelper
|
||||
@Inject lateinit var profileFunction: ProfileFunction
|
||||
@Inject lateinit var treatmentsPlugin: TreatmentsPlugin
|
||||
@Inject lateinit var activePlugin: ActivePluginProvider
|
||||
|
||||
var profileIndex: Int? = null
|
||||
|
||||
override fun onSaveInstanceState(savedInstanceState: Bundle) {
|
||||
super.onSaveInstanceState(savedInstanceState)
|
||||
|
@ -33,6 +40,9 @@ class ProfileSwitchDialog : DialogFragmentWithDate() {
|
|||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
onCreateViewGeneral()
|
||||
arguments?.let { bundle ->
|
||||
profileIndex = bundle.getInt("profileIndex", 0)
|
||||
}
|
||||
return inflater.inflate(R.layout.dialog_profileswitch, container, false)
|
||||
}
|
||||
|
||||
|
@ -48,21 +58,24 @@ class ProfileSwitchDialog : DialogFragmentWithDate() {
|
|||
|
||||
// profile
|
||||
context?.let { context ->
|
||||
val profileStore = ConfigBuilderPlugin.getPlugin().activeProfileInterface?.profile
|
||||
val profileStore = activePlugin.activeProfileInterface.profile
|
||||
?: return
|
||||
val profileList = profileStore.getProfileList()
|
||||
val adapter = ArrayAdapter(context, R.layout.spinner_centered, profileList)
|
||||
overview_profileswitch_profile.adapter = adapter
|
||||
// set selected to actual profile
|
||||
for (p in profileList.indices)
|
||||
if (profileList[p] == ProfileFunctions.getInstance().getProfileName(false))
|
||||
overview_profileswitch_profile.setSelection(p)
|
||||
if (profileIndex != null)
|
||||
overview_profileswitch_profile.setSelection(profileIndex as Int)
|
||||
else
|
||||
for (p in profileList.indices)
|
||||
if (profileList[p] == profileFunction.getProfileName(false))
|
||||
overview_profileswitch_profile.setSelection(p)
|
||||
} ?: return
|
||||
|
||||
TreatmentsPlugin.getPlugin().getProfileSwitchFromHistory(DateUtil.now())?.let { ps ->
|
||||
treatmentsPlugin.getProfileSwitchFromHistory(DateUtil.now())?.let { ps ->
|
||||
if (ps.isCPP) {
|
||||
overview_profileswitch_reuselayout.visibility = View.VISIBLE
|
||||
overview_profileswitch_reusebutton.text = MainApp.gs(R.string.reuse) + " " + ps.percentage + "% " + ps.timeshift + "h"
|
||||
overview_profileswitch_reusebutton.text = resourceHelper.gs(R.string.reuse) + " " + ps.percentage + "% " + ps.timeshift + "h"
|
||||
overview_profileswitch_reusebutton.setOnClickListener {
|
||||
overview_profileswitch_percentage.value = ps.percentage.toDouble()
|
||||
overview_profileswitch_timeshift.value = ps.timeshift.toDouble()
|
||||
|
@ -74,31 +87,31 @@ class ProfileSwitchDialog : DialogFragmentWithDate() {
|
|||
}
|
||||
|
||||
override fun submit(): Boolean {
|
||||
val profileStore = ConfigBuilderPlugin.getPlugin().activeProfileInterface?.profile
|
||||
val profileStore = activePlugin.activeProfileInterface.profile
|
||||
?: return false
|
||||
|
||||
val actions: LinkedList<String> = LinkedList()
|
||||
val duration = overview_profileswitch_duration.value.toInt()
|
||||
if (duration > 0)
|
||||
actions.add(MainApp.gs(R.string.duration) + ": " + MainApp.gs(R.string.format_mins, duration))
|
||||
actions.add(resourceHelper.gs(R.string.duration) + ": " + resourceHelper.gs(R.string.format_mins, duration))
|
||||
val profile = overview_profileswitch_profile.selectedItem.toString()
|
||||
actions.add(MainApp.gs(R.string.profile) + ": " + profile)
|
||||
actions.add(resourceHelper.gs(R.string.profile) + ": " + profile)
|
||||
val percent = overview_profileswitch_percentage.value.toInt()
|
||||
if (percent != 100)
|
||||
actions.add(MainApp.gs(R.string.percent) + ": " + percent + "%")
|
||||
actions.add(resourceHelper.gs(R.string.percent) + ": " + percent + "%")
|
||||
val timeShift = overview_profileswitch_timeshift.value.toInt()
|
||||
if (timeShift != 0)
|
||||
actions.add(MainApp.gs(R.string.careportal_newnstreatment_timeshift_label) + ": " + MainApp.gs(R.string.format_hours, timeShift.toDouble()))
|
||||
actions.add(resourceHelper.gs(R.string.careportal_newnstreatment_timeshift_label) + ": " + resourceHelper.gs(R.string.format_hours, timeShift.toDouble()))
|
||||
val notes = notes.text.toString()
|
||||
if (notes.isNotEmpty())
|
||||
actions.add(MainApp.gs(R.string.careportal_newnstreatment_notes_label) + ": " + notes)
|
||||
actions.add(resourceHelper.gs(R.string.careportal_newnstreatment_notes_label) + ": " + notes)
|
||||
if (eventTimeChanged)
|
||||
actions.add(MainApp.gs(R.string.time) + ": " + DateUtil.dateAndTimeString(eventTime))
|
||||
actions.add(resourceHelper.gs(R.string.time) + ": " + dateUtil.dateAndTimeString(eventTime))
|
||||
|
||||
activity?.let { activity ->
|
||||
OKDialog.showConfirmation(activity, MainApp.gs(R.string.careportal_profileswitch), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
|
||||
log.debug("USER ENTRY: PROFILE SWITCH $profile percent: $percent timeshift: $timeShift duration: $duration")
|
||||
ProfileFunctions.doProfileSwitch(profileStore, profile, duration, percent, timeShift, eventTime)
|
||||
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.careportal_profileswitch), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
|
||||
aapsLogger.debug("USER ENTRY: PROFILE SWITCH $profile percent: $percent timeshift: $timeShift duration: $duration")
|
||||
treatmentsPlugin.doProfileSwitch(profileStore, profile, duration, percent, timeShift, eventTime)
|
||||
})
|
||||
}
|
||||
return true
|
||||
|
|
|
@ -1,108 +0,0 @@
|
|||
package info.nightscout.androidaps.dialogs
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.Window
|
||||
import android.view.WindowManager
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import info.nightscout.androidaps.Constants
|
||||
import info.nightscout.androidaps.MainApp
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.data.Profile
|
||||
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import kotlinx.android.synthetic.main.close.*
|
||||
import kotlinx.android.synthetic.main.dialog_profileviewer.*
|
||||
import org.json.JSONObject
|
||||
|
||||
class ProfileViewerDialog : DialogFragment() {
|
||||
private var time: Long = 0
|
||||
|
||||
enum class Mode(val i: Int) {
|
||||
RUNNING_PROFILE(1),
|
||||
CUSTOM_PROFILE(2)
|
||||
}
|
||||
|
||||
private var mode: Mode = Mode.RUNNING_PROFILE
|
||||
private var customProfileJson: String = ""
|
||||
private var customProfileName: String = ""
|
||||
private var customProfileUnits: String = Constants.MGDL
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
// load data from bundle
|
||||
(savedInstanceState ?: arguments)?.let { bundle ->
|
||||
time = bundle.getLong("time", 0)
|
||||
mode = Mode.values()[bundle.getInt("mode", Mode.RUNNING_PROFILE.ordinal)]
|
||||
customProfileJson = bundle.getString("customProfile", "")
|
||||
customProfileUnits = bundle.getString("customProfileUnits", Constants.MGDL)
|
||||
customProfileName = bundle.getString("customProfileName", "")
|
||||
}
|
||||
|
||||
dialog?.window?.requestFeature(Window.FEATURE_NO_TITLE)
|
||||
dialog?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN)
|
||||
isCancelable = true
|
||||
dialog?.setCanceledOnTouchOutside(false)
|
||||
|
||||
return inflater.inflate(R.layout.dialog_profileviewer, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
close.setOnClickListener { dismiss() }
|
||||
|
||||
val profile: Profile?
|
||||
val profileName: String?
|
||||
val date: String?
|
||||
when (mode) {
|
||||
Mode.RUNNING_PROFILE -> {
|
||||
profile = TreatmentsPlugin.getPlugin().getProfileSwitchFromHistory(time)?.profileObject
|
||||
profileName = TreatmentsPlugin.getPlugin().getProfileSwitchFromHistory(time)?.customizedName
|
||||
date = DateUtil.dateAndTimeString(TreatmentsPlugin.getPlugin().getProfileSwitchFromHistory(time)?.date
|
||||
?: 0)
|
||||
profileview_datelayout.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
Mode.CUSTOM_PROFILE -> {
|
||||
profile = Profile(JSONObject(customProfileJson), customProfileUnits)
|
||||
profileName = customProfileName
|
||||
date = ""
|
||||
profileview_datelayout.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
profileview_noprofile.visibility = View.VISIBLE
|
||||
|
||||
profile?.let {
|
||||
profileview_units.text = it.units
|
||||
profileview_dia.text = MainApp.gs(R.string.format_hours, it.dia)
|
||||
profileview_activeprofile.text = profileName
|
||||
profileview_date.text = date
|
||||
profileview_ic.text = it.icList
|
||||
profileview_isf.text = it.isfList
|
||||
profileview_basal.text = it.basalList
|
||||
profileview_target.text = it.targetList
|
||||
basal_graph.show(it)
|
||||
|
||||
profileview_noprofile.visibility = View.GONE
|
||||
profileview_invalidprofile.visibility = if (it.isValid("ProfileViewDialog")) View.GONE else View.VISIBLE
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
dialog?.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(bundle: Bundle) {
|
||||
super.onSaveInstanceState(bundle)
|
||||
bundle.putLong("time", time)
|
||||
bundle.putInt("mode", mode.ordinal)
|
||||
bundle.putString("customProfile", customProfileJson)
|
||||
bundle.putString("customProfileName", customProfileName)
|
||||
bundle.putString("customProfileUnits", customProfileUnits)
|
||||
}
|
||||
|
||||
}
|
|
@ -1,29 +1,41 @@
|
|||
package info.nightscout.androidaps.dialogs
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.google.common.base.Joiner
|
||||
import info.nightscout.androidaps.MainApp
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.activities.ErrorHelperActivity
|
||||
import info.nightscout.androidaps.interfaces.ActivePluginProvider
|
||||
import info.nightscout.androidaps.interfaces.CommandQueueProvider
|
||||
import info.nightscout.androidaps.interfaces.Constraint
|
||||
import info.nightscout.androidaps.interfaces.PumpDescription
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||
import info.nightscout.androidaps.queue.Callback
|
||||
import info.nightscout.androidaps.utils.HtmlHelper
|
||||
import info.nightscout.androidaps.utils.OKDialog
|
||||
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
||||
import info.nightscout.androidaps.utils.SafeParse
|
||||
import info.nightscout.androidaps.utils.extensions.formatColor
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import kotlinx.android.synthetic.main.dialog_tempbasal.*
|
||||
import kotlinx.android.synthetic.main.okcancel.*
|
||||
import java.text.DecimalFormat
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
import kotlin.math.abs
|
||||
|
||||
class TempBasalDialog : DialogFragmentWithDate() {
|
||||
@Inject lateinit var constraintChecker: ConstraintChecker
|
||||
@Inject lateinit var resourceHelper: ResourceHelper
|
||||
@Inject lateinit var profileFunction: ProfileFunction
|
||||
@Inject lateinit var activePlugin: ActivePluginProvider
|
||||
@Inject lateinit var commandQueue: CommandQueueProvider
|
||||
@Inject lateinit var ctx: Context
|
||||
|
||||
private var isPercentPump = true
|
||||
|
||||
override fun onSaveInstanceState(savedInstanceState: Bundle) {
|
||||
|
@ -42,8 +54,8 @@ class TempBasalDialog : DialogFragmentWithDate() {
|
|||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
val pumpDescription = ConfigBuilderPlugin.getPlugin().activePump?.pumpDescription ?: return
|
||||
val profile = ProfileFunctions.getInstance().profile ?: return
|
||||
val pumpDescription = activePlugin.activePump.pumpDescription
|
||||
val profile = profileFunction.getProfile() ?: return
|
||||
|
||||
val maxTempPercent = pumpDescription.maxTempPercent.toDouble()
|
||||
val tempPercentStep = pumpDescription.tempPercentStep.toDouble()
|
||||
|
@ -72,43 +84,43 @@ class TempBasalDialog : DialogFragmentWithDate() {
|
|||
override fun submit(): Boolean {
|
||||
var percent = 0
|
||||
var absolute = 0.0
|
||||
val durationInMinutes = SafeParse.stringToInt(actions_tempbasal_duration.text)
|
||||
val profile = ProfileFunctions.getInstance().profile ?: return false
|
||||
val durationInMinutes = actions_tempbasal_duration.value.toInt()
|
||||
val profile = profileFunction.getProfile() ?: return false
|
||||
val actions: LinkedList<String> = LinkedList()
|
||||
if (isPercentPump) {
|
||||
val basalPercentInput = SafeParse.stringToInt(actions_tempbasal_basalpercentinput.text)
|
||||
percent = MainApp.getConstraintChecker().applyBasalPercentConstraints(Constraint(basalPercentInput), profile).value()
|
||||
actions.add(MainApp.gs(R.string.pump_tempbasal_label)+ ": $percent%")
|
||||
actions.add(MainApp.gs(R.string.duration) + ": " + MainApp.gs(R.string.format_mins, durationInMinutes))
|
||||
if (percent != basalPercentInput) actions.add(MainApp.gs(R.string.constraintapllied))
|
||||
percent = constraintChecker.applyBasalPercentConstraints(Constraint(basalPercentInput), profile).value()
|
||||
actions.add(resourceHelper.gs(R.string.tempbasal_label) + ": $percent%")
|
||||
actions.add(resourceHelper.gs(R.string.duration) + ": " + resourceHelper.gs(R.string.format_mins, durationInMinutes))
|
||||
if (percent != basalPercentInput) actions.add(resourceHelper.gs(R.string.constraintapllied))
|
||||
} else {
|
||||
val basalAbsoluteInput = SafeParse.stringToDouble(actions_tempbasal_basalabsoluteinput.text)
|
||||
absolute = MainApp.getConstraintChecker().applyBasalConstraints(Constraint(basalAbsoluteInput), profile).value()
|
||||
actions.add(MainApp.gs(R.string.pump_tempbasal_label)+ ": " + MainApp.gs(R.string.pump_basebasalrate, absolute))
|
||||
actions.add(MainApp.gs(R.string.duration) + ": " + MainApp.gs(R.string.format_mins, durationInMinutes))
|
||||
absolute = constraintChecker.applyBasalConstraints(Constraint(basalAbsoluteInput), profile).value()
|
||||
actions.add(resourceHelper.gs(R.string.tempbasal_label) + ": " + resourceHelper.gs(R.string.pump_basebasalrate, absolute))
|
||||
actions.add(resourceHelper.gs(R.string.duration) + ": " + resourceHelper.gs(R.string.format_mins, durationInMinutes))
|
||||
if (abs(absolute - basalAbsoluteInput) > 0.01)
|
||||
actions.add("<font color='" + MainApp.gc(R.color.warning) + "'>" + MainApp.gs(R.string.constraintapllied) + "</font>")
|
||||
actions.add(resourceHelper.gs(R.string.constraintapllied).formatColor(resourceHelper, R.color.warning))
|
||||
}
|
||||
activity?.let { activity ->
|
||||
OKDialog.showConfirmation(activity, MainApp.gs(R.string.pump_tempbasal_label), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
|
||||
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.tempbasal_label), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
|
||||
val callback: Callback = object : Callback() {
|
||||
override fun run() {
|
||||
if (!result.success) {
|
||||
val i = Intent(MainApp.instance(), ErrorHelperActivity::class.java)
|
||||
val i = Intent(ctx, ErrorHelperActivity::class.java)
|
||||
i.putExtra("soundid", R.raw.boluserror)
|
||||
i.putExtra("status", result.comment)
|
||||
i.putExtra("title", MainApp.gs(R.string.tempbasaldeliveryerror))
|
||||
i.putExtra("title", resourceHelper.gs(R.string.tempbasaldeliveryerror))
|
||||
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
MainApp.instance().startActivity(i)
|
||||
ctx.startActivity(i)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isPercentPump) {
|
||||
log.debug("USER ENTRY: TEMP BASAL $percent% duration: $durationInMinutes")
|
||||
ConfigBuilderPlugin.getPlugin().commandQueue.tempBasalPercent(percent, durationInMinutes, true, profile, callback)
|
||||
aapsLogger.debug("USER ENTRY: TEMP BASAL $percent% duration: $durationInMinutes")
|
||||
commandQueue.tempBasalPercent(percent, durationInMinutes, true, profile, callback)
|
||||
} else {
|
||||
log.debug("USER ENTRY: TEMP BASAL $absolute duration: $durationInMinutes")
|
||||
ConfigBuilderPlugin.getPlugin().commandQueue.tempBasalAbsolute(absolute, durationInMinutes, true, profile, callback)
|
||||
aapsLogger.debug("USER ENTRY: TEMP BASAL $absolute duration: $durationInMinutes")
|
||||
commandQueue.tempBasalAbsolute(absolute, durationInMinutes, true, profile, callback)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -9,24 +9,29 @@ import android.widget.ArrayAdapter
|
|||
import com.google.common.base.Joiner
|
||||
import com.google.common.collect.Lists
|
||||
import info.nightscout.androidaps.Constants
|
||||
import info.nightscout.androidaps.MainApp
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.data.Profile
|
||||
import info.nightscout.androidaps.db.Source
|
||||
import info.nightscout.androidaps.db.TempTarget
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.DefaultValueHelper
|
||||
import info.nightscout.androidaps.utils.HtmlHelper
|
||||
import info.nightscout.androidaps.utils.OKDialog
|
||||
import info.nightscout.androidaps.utils.SP
|
||||
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import kotlinx.android.synthetic.main.dialog_temptarget.*
|
||||
import kotlinx.android.synthetic.main.okcancel.*
|
||||
import java.text.DecimalFormat
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class TempTargetDialog : DialogFragmentWithDate() {
|
||||
@Inject lateinit var constraintChecker: ConstraintChecker
|
||||
@Inject lateinit var resourceHelper: ResourceHelper
|
||||
@Inject lateinit var profileFunction: ProfileFunction
|
||||
@Inject lateinit var defaultValueHelper: DefaultValueHelper
|
||||
@Inject lateinit var treatmentsPlugin: TreatmentsPlugin
|
||||
|
||||
override fun onSaveInstanceState(savedInstanceState: Bundle) {
|
||||
super.onSaveInstanceState(savedInstanceState)
|
||||
|
@ -46,7 +51,7 @@ class TempTargetDialog : DialogFragmentWithDate() {
|
|||
overview_temptarget_duration.setParams(savedInstanceState?.getDouble("overview_temptarget_duration")
|
||||
?: 0.0, 0.0, Constants.MAX_PROFILE_SWITCH_DURATION, 10.0, DecimalFormat("0"), false, ok)
|
||||
|
||||
if (ProfileFunctions.getSystemUnits() == Constants.MMOL)
|
||||
if (profileFunction.getUnits() == Constants.MMOL)
|
||||
overview_temptarget_temptarget.setParams(
|
||||
savedInstanceState?.getDouble("overview_temptarget_temptarget")
|
||||
?: Constants.MIN_TT_MMOL,
|
||||
|
@ -57,45 +62,45 @@ class TempTargetDialog : DialogFragmentWithDate() {
|
|||
?: Constants.MIN_TT_MGDL,
|
||||
Constants.MIN_TT_MGDL, Constants.MAX_TT_MGDL, 1.0, DecimalFormat("0"), false, ok)
|
||||
|
||||
val units = ProfileFunctions.getSystemUnits()
|
||||
overview_temptarget_units.text = if (units == Constants.MMOL) MainApp.gs(R.string.mmol) else MainApp.gs(R.string.mgdl)
|
||||
val units = profileFunction.getUnits()
|
||||
overview_temptarget_units.text = if (units == Constants.MMOL) resourceHelper.gs(R.string.mmol) else resourceHelper.gs(R.string.mgdl)
|
||||
// temp target
|
||||
context?.let { context ->
|
||||
val reasonList: List<String> = Lists.newArrayList(
|
||||
MainApp.gs(R.string.manual),
|
||||
MainApp.gs(R.string.cancel),
|
||||
MainApp.gs(R.string.eatingsoon),
|
||||
MainApp.gs(R.string.activity),
|
||||
MainApp.gs(R.string.hypo)
|
||||
resourceHelper.gs(R.string.manual),
|
||||
resourceHelper.gs(R.string.cancel),
|
||||
resourceHelper.gs(R.string.eatingsoon),
|
||||
resourceHelper.gs(R.string.activity),
|
||||
resourceHelper.gs(R.string.hypo)
|
||||
)
|
||||
val adapterReason = ArrayAdapter(context, R.layout.spinner_centered, reasonList)
|
||||
overview_temptarget_reason.adapter = adapterReason
|
||||
overview_temptarget_reason.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||
override fun onItemSelected(parent: AdapterView<*>?, view: View, position: Int, id: Long) {
|
||||
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
|
||||
val defaultDuration: Double
|
||||
val defaultTarget: Double
|
||||
when (reasonList[position]) {
|
||||
MainApp.gs(R.string.eatingsoon) -> {
|
||||
defaultDuration = DefaultValueHelper.determineEatingSoonTTDuration().toDouble()
|
||||
defaultTarget = DefaultValueHelper.determineEatingSoonTT()
|
||||
resourceHelper.gs(R.string.eatingsoon) -> {
|
||||
defaultDuration = defaultValueHelper.determineEatingSoonTTDuration().toDouble()
|
||||
defaultTarget = defaultValueHelper.determineEatingSoonTT()
|
||||
}
|
||||
|
||||
MainApp.gs(R.string.activity) -> {
|
||||
defaultDuration = DefaultValueHelper.determineActivityTTDuration().toDouble()
|
||||
defaultTarget = DefaultValueHelper.determineActivityTT()
|
||||
resourceHelper.gs(R.string.activity) -> {
|
||||
defaultDuration = defaultValueHelper.determineActivityTTDuration().toDouble()
|
||||
defaultTarget = defaultValueHelper.determineActivityTT()
|
||||
}
|
||||
|
||||
MainApp.gs(R.string.hypo) -> {
|
||||
defaultDuration = DefaultValueHelper.determineHypoTTDuration().toDouble()
|
||||
defaultTarget = DefaultValueHelper.determineHypoTT()
|
||||
resourceHelper.gs(R.string.hypo) -> {
|
||||
defaultDuration = defaultValueHelper.determineHypoTTDuration().toDouble()
|
||||
defaultTarget = defaultValueHelper.determineHypoTT()
|
||||
}
|
||||
|
||||
MainApp.gs(R.string.cancel) -> {
|
||||
resourceHelper.gs(R.string.cancel) -> {
|
||||
defaultDuration = 0.0
|
||||
defaultTarget = 0.0
|
||||
}
|
||||
|
||||
else -> {
|
||||
else -> {
|
||||
defaultDuration = overview_temptarget_duration.value
|
||||
defaultTarget = overview_temptarget_temptarget.value
|
||||
}
|
||||
|
@ -112,40 +117,40 @@ class TempTargetDialog : DialogFragmentWithDate() {
|
|||
override fun submit(): Boolean {
|
||||
val actions: LinkedList<String> = LinkedList()
|
||||
val reason = overview_temptarget_reason.selectedItem.toString()
|
||||
val unitResId = if (ProfileFunctions.getSystemUnits() == Constants.MGDL) R.string.mgdl else R.string.mmol
|
||||
val unitResId = if (profileFunction.getUnits() == Constants.MGDL) R.string.mgdl else R.string.mmol
|
||||
val target = overview_temptarget_temptarget.value
|
||||
val duration = overview_temptarget_duration.value.toInt()
|
||||
if (target != 0.0 && duration != 0) {
|
||||
actions.add(MainApp.gs(R.string.reason) + ": " + reason)
|
||||
actions.add(MainApp.gs(R.string.nsprofileview_target_label) + ": " + Profile.toCurrentUnitsString(target) + " " + MainApp.gs(unitResId))
|
||||
actions.add(MainApp.gs(R.string.duration) + ": " + MainApp.gs(R.string.format_mins, duration))
|
||||
actions.add(resourceHelper.gs(R.string.reason) + ": " + reason)
|
||||
actions.add(resourceHelper.gs(R.string.target_label) + ": " + Profile.toCurrentUnitsString(profileFunction, target) + " " + resourceHelper.gs(unitResId))
|
||||
actions.add(resourceHelper.gs(R.string.duration) + ": " + resourceHelper.gs(R.string.format_mins, duration))
|
||||
} else {
|
||||
actions.add(MainApp.gs(R.string.stoptemptarget))
|
||||
actions.add(resourceHelper.gs(R.string.stoptemptarget))
|
||||
}
|
||||
if (eventTimeChanged)
|
||||
actions.add(MainApp.gs(R.string.time) + ": " + DateUtil.dateAndTimeString(eventTime))
|
||||
actions.add(resourceHelper.gs(R.string.time) + ": " + dateUtil.dateAndTimeString(eventTime))
|
||||
|
||||
activity?.let { activity ->
|
||||
OKDialog.showConfirmation(activity, MainApp.gs(R.string.careportal_temporarytarget), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
|
||||
log.debug("USER ENTRY: TEMP TARGET $target duration: $duration")
|
||||
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.careportal_temporarytarget), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
|
||||
aapsLogger.debug("USER ENTRY: TEMP TARGET $target duration: $duration")
|
||||
if (target == 0.0 || duration == 0) {
|
||||
val tempTarget = TempTarget()
|
||||
.date(eventTime)
|
||||
.duration(0)
|
||||
.low(0.0).high(0.0)
|
||||
.source(Source.USER)
|
||||
TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget)
|
||||
treatmentsPlugin.addToHistoryTempTarget(tempTarget)
|
||||
} else {
|
||||
val tempTarget = TempTarget()
|
||||
.date(eventTime)
|
||||
.duration(duration.toInt())
|
||||
.duration(duration)
|
||||
.reason(reason)
|
||||
.source(Source.USER)
|
||||
.low(Profile.toMgdl(target, ProfileFunctions.getSystemUnits()))
|
||||
.high(Profile.toMgdl(target, ProfileFunctions.getSystemUnits()))
|
||||
TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget)
|
||||
.low(Profile.toMgdl(target, profileFunction.getUnits()))
|
||||
.high(Profile.toMgdl(target, profileFunction.getUnits()))
|
||||
treatmentsPlugin.addToHistoryTempTarget(tempTarget)
|
||||
}
|
||||
if (duration == 10) SP.putBoolean(R.string.key_objectiveusetemptarget, true)
|
||||
if (duration == 10) sp.putBoolean(R.string.key_objectiveusetemptarget, true)
|
||||
})
|
||||
}
|
||||
return true
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package info.nightscout.androidaps.dialogs
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.text.Editable
|
||||
|
@ -8,30 +9,39 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.google.common.base.Joiner
|
||||
import info.nightscout.androidaps.MainApp
|
||||
import info.nightscout.androidaps.Config
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.activities.ErrorHelperActivity
|
||||
import info.nightscout.androidaps.data.DetailedBolusInfo
|
||||
import info.nightscout.androidaps.db.CareportalEvent
|
||||
import info.nightscout.androidaps.db.Source
|
||||
import info.nightscout.androidaps.interfaces.ActivePluginProvider
|
||||
import info.nightscout.androidaps.interfaces.CommandQueueProvider
|
||||
import info.nightscout.androidaps.interfaces.Constraint
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
|
||||
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
||||
import info.nightscout.androidaps.queue.Callback
|
||||
import info.nightscout.androidaps.utils.DecimalFormatter
|
||||
import info.nightscout.androidaps.utils.HtmlHelper
|
||||
import info.nightscout.androidaps.utils.OKDialog
|
||||
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
||||
import info.nightscout.androidaps.utils.SafeParse
|
||||
import info.nightscout.androidaps.utils.ToastUtils
|
||||
import info.nightscout.androidaps.utils.extensions.formatColor
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import kotlinx.android.synthetic.main.dialog_insulin.*
|
||||
import kotlinx.android.synthetic.main.dialog_treatment.*
|
||||
import kotlinx.android.synthetic.main.okcancel.*
|
||||
import java.text.DecimalFormat
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
import kotlin.math.abs
|
||||
|
||||
class TreatmentDialog : DialogFragmentWithDate() {
|
||||
private var maxCarbs = MainApp.getConstraintChecker().maxCarbsAllowed.value().toDouble()
|
||||
private var maxInsulin = MainApp.getConstraintChecker().maxBolusAllowed.value()
|
||||
@Inject lateinit var constraintChecker: ConstraintChecker
|
||||
@Inject lateinit var resourceHelper: ResourceHelper
|
||||
@Inject lateinit var activePlugin: ActivePluginProvider
|
||||
@Inject lateinit var commandQueue: CommandQueueProvider
|
||||
@Inject lateinit var ctx: Context
|
||||
@Inject lateinit var config: Config
|
||||
|
||||
private val textWatcher: TextWatcher = object : TextWatcher {
|
||||
override fun afterTextChanged(s: Editable) {}
|
||||
|
@ -42,13 +52,15 @@ class TreatmentDialog : DialogFragmentWithDate() {
|
|||
}
|
||||
|
||||
private fun validateInputs() {
|
||||
val maxCarbs = constraintChecker.getMaxCarbsAllowed().value().toDouble()
|
||||
val maxInsulin = constraintChecker.getMaxBolusAllowed().value()
|
||||
if (SafeParse.stringToInt(overview_treatment_carbs.text) > maxCarbs) {
|
||||
overview_treatment_carbs.value = 0.0
|
||||
ToastUtils.showToastInUiThread(MainApp.instance().applicationContext, MainApp.gs(R.string.carbsconstraintapplied))
|
||||
ToastUtils.showToastInUiThread(context, resourceHelper.gs(R.string.carbsconstraintapplied))
|
||||
}
|
||||
if (SafeParse.stringToDouble(overview_treatment_insulin.text) > maxInsulin) {
|
||||
overview_treatment_insulin.value = 0.0
|
||||
ToastUtils.showToastInUiThread(MainApp.instance().applicationContext, MainApp.gs(R.string.bolusconstraintapplied))
|
||||
ToastUtils.showToastInUiThread(context, resourceHelper.gs(R.string.bolusconstraintapplied))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -67,39 +79,44 @@ class TreatmentDialog : DialogFragmentWithDate() {
|
|||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
val pumpDescription = ConfigBuilderPlugin.getPlugin().activePump?.pumpDescription ?: return
|
||||
if (config.NSCLIENT) {
|
||||
overview_treatment_record_only.isChecked = true
|
||||
overview_treatment_record_only.isEnabled = false
|
||||
}
|
||||
val maxCarbs = constraintChecker.getMaxCarbsAllowed().value().toDouble()
|
||||
val maxInsulin = constraintChecker.getMaxBolusAllowed().value()
|
||||
val pumpDescription = activePlugin.activePump.pumpDescription
|
||||
overview_treatment_carbs.setParams(savedInstanceState?.getDouble("overview_treatment_carbs")
|
||||
?: 0.0, 0.0, maxCarbs, 1.0, DecimalFormat("0"), false, ok, textWatcher)
|
||||
overview_treatment_insulin.setParams(savedInstanceState?.getDouble("overview_treatment_insulin")
|
||||
?: 0.0, 0.0, maxInsulin, pumpDescription.bolusStep, DecimalFormatter.pumpSupportedBolusFormat(), false, ok, textWatcher)
|
||||
?: 0.0, 0.0, maxInsulin, pumpDescription.bolusStep, DecimalFormatter.pumpSupportedBolusFormat(activePlugin.activePump), false, ok, textWatcher)
|
||||
}
|
||||
|
||||
override fun submit(): Boolean {
|
||||
val pumpDescription = ConfigBuilderPlugin.getPlugin().activePump?.pumpDescription
|
||||
?: return false
|
||||
val pumpDescription = activePlugin.activePump.pumpDescription
|
||||
val insulin = SafeParse.stringToDouble(overview_treatment_insulin.text)
|
||||
val carbs = SafeParse.stringToInt(overview_treatment_carbs.text)
|
||||
val recordOnlyChecked = overview_treatment_record_only.isChecked
|
||||
val actions: LinkedList<String?> = LinkedList()
|
||||
val insulinAfterConstraints = MainApp.getConstraintChecker().applyBolusConstraints(Constraint(insulin)).value()
|
||||
val carbsAfterConstraints = MainApp.getConstraintChecker().applyCarbsConstraints(Constraint(carbs)).value()
|
||||
val insulinAfterConstraints = constraintChecker.applyBolusConstraints(Constraint(insulin)).value()
|
||||
val carbsAfterConstraints = constraintChecker.applyCarbsConstraints(Constraint(carbs)).value()
|
||||
|
||||
if (insulinAfterConstraints > 0) {
|
||||
actions.add(MainApp.gs(R.string.bolus) + ": " + "<font color='" + MainApp.gc(R.color.bolus) + "'>" + DecimalFormatter.toPumpSupportedBolus(insulinAfterConstraints) + MainApp.gs(R.string.insulin_unit_shortname) + "</font>")
|
||||
actions.add(resourceHelper.gs(R.string.bolus) + ": " + DecimalFormatter.toPumpSupportedBolus(insulinAfterConstraints, activePlugin.activePump, resourceHelper).formatColor(resourceHelper, R.color.bolus))
|
||||
if (recordOnlyChecked)
|
||||
actions.add("<font color='" + MainApp.gc(R.color.warning) + "'>" + MainApp.gs(R.string.bolusrecordedonly) + "</font>")
|
||||
actions.add(resourceHelper.gs(R.string.bolusrecordedonly).formatColor(resourceHelper, R.color.warning))
|
||||
if (abs(insulinAfterConstraints - insulin) > pumpDescription.pumpType.determineCorrectBolusStepSize(insulinAfterConstraints))
|
||||
actions.add(MainApp.gs(R.string.bolusconstraintappliedwarning, MainApp.gc(R.color.warning), insulin, insulinAfterConstraints))
|
||||
actions.add(resourceHelper.gs(R.string.bolusconstraintappliedwarn, insulin, insulinAfterConstraints).formatColor(resourceHelper, R.color.warning))
|
||||
}
|
||||
if (carbsAfterConstraints > 0) {
|
||||
actions.add(MainApp.gs(R.string.carbs) + ": " + "<font color='" + MainApp.gc(R.color.carbs) + "'>" + MainApp.gs(R.string.format_carbs, carbsAfterConstraints) + "</font>")
|
||||
actions.add(resourceHelper.gs(R.string.carbs) + ": " + resourceHelper.gs(R.string.format_carbs, carbsAfterConstraints).formatColor(resourceHelper, R.color.carbs))
|
||||
if (carbsAfterConstraints != carbs)
|
||||
actions.add("<font color='" + MainApp.gc(R.color.warning) + "'>" + MainApp.gs(R.string.carbsconstraintapplied) + "</font>")
|
||||
actions.add(resourceHelper.gs(R.string.carbsconstraintapplied).formatColor(resourceHelper, R.color.warning))
|
||||
}
|
||||
if (insulinAfterConstraints > 0 || carbsAfterConstraints > 0) {
|
||||
activity?.let { activity ->
|
||||
OKDialog.showConfirmation(activity, MainApp.gs(R.string.overview_treatment_label), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
|
||||
log.debug("USER ENTRY: BOLUS insulin $insulin carbs: $carbs")
|
||||
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.overview_treatment_label), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
|
||||
aapsLogger.debug("USER ENTRY: BOLUS insulin $insulin carbs: $carbs")
|
||||
val detailedBolusInfo = DetailedBolusInfo()
|
||||
if (insulinAfterConstraints == 0.0) detailedBolusInfo.eventType = CareportalEvent.CARBCORRECTION
|
||||
if (carbsAfterConstraints == 0) detailedBolusInfo.eventType = CareportalEvent.CORRECTIONBOLUS
|
||||
|
@ -108,25 +125,25 @@ class TreatmentDialog : DialogFragmentWithDate() {
|
|||
detailedBolusInfo.context = context
|
||||
detailedBolusInfo.source = Source.USER
|
||||
if (!(recordOnlyChecked && (detailedBolusInfo.insulin > 0 || pumpDescription.storesCarbInfo))) {
|
||||
ConfigBuilderPlugin.getPlugin().commandQueue.bolus(detailedBolusInfo, object : Callback() {
|
||||
commandQueue.bolus(detailedBolusInfo, object : Callback() {
|
||||
override fun run() {
|
||||
if (!result.success) {
|
||||
val i = Intent(MainApp.instance(), ErrorHelperActivity::class.java)
|
||||
val i = Intent(ctx, ErrorHelperActivity::class.java)
|
||||
i.putExtra("soundid", R.raw.boluserror)
|
||||
i.putExtra("status", result.comment)
|
||||
i.putExtra("title", MainApp.gs(R.string.treatmentdeliveryerror))
|
||||
i.putExtra("title", resourceHelper.gs(R.string.treatmentdeliveryerror))
|
||||
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
MainApp.instance().startActivity(i)
|
||||
ctx.startActivity(i)
|
||||
}
|
||||
}
|
||||
})
|
||||
} else
|
||||
TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, false)
|
||||
activePlugin.activeTreatments.addToHistoryTreatment(detailedBolusInfo, false)
|
||||
})
|
||||
}
|
||||
} else
|
||||
activity?.let { activity ->
|
||||
OKDialog.show(activity, MainApp.gs(R.string.overview_treatment_label), MainApp.gs(R.string.no_action_selected))
|
||||
OKDialog.show(activity, resourceHelper.gs(R.string.overview_treatment_label), resourceHelper.gs(R.string.no_action_selected))
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -12,31 +12,52 @@ import android.widget.AdapterView
|
|||
import android.widget.AdapterView.OnItemSelectedListener
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.CompoundButton
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import dagger.android.support.DaggerDialogFragment
|
||||
import info.nightscout.androidaps.Constants
|
||||
import info.nightscout.androidaps.MainApp
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.data.Profile
|
||||
import info.nightscout.androidaps.db.BgReading
|
||||
import info.nightscout.androidaps.db.DatabaseHelper
|
||||
import info.nightscout.androidaps.interfaces.ActivePluginProvider
|
||||
import info.nightscout.androidaps.interfaces.Constraint
|
||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||
import info.nightscout.androidaps.logging.AAPSLogger
|
||||
import info.nightscout.androidaps.logging.LTag
|
||||
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
||||
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.utils.*
|
||||
import info.nightscout.androidaps.utils.DecimalFormatter
|
||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||
import info.nightscout.androidaps.utils.SafeParse
|
||||
import info.nightscout.androidaps.utils.ToastUtils
|
||||
import info.nightscout.androidaps.utils.extensions.toVisibility
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
||||
import info.nightscout.androidaps.utils.wizard.BolusWizard
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import kotlinx.android.synthetic.main.dialog_wizard.*
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.text.DecimalFormat
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
import kotlin.math.abs
|
||||
|
||||
class WizardDialog : DialogFragment() {
|
||||
private val log = LoggerFactory.getLogger(WizardDialog::class.java)
|
||||
class WizardDialog : DaggerDialogFragment() {
|
||||
|
||||
@Inject lateinit var aapsLogger: AAPSLogger
|
||||
@Inject lateinit var constraintChecker: ConstraintChecker
|
||||
@Inject lateinit var mainApp: MainApp
|
||||
@Inject lateinit var sp: SP
|
||||
@Inject lateinit var rxBus: RxBusWrapper
|
||||
@Inject lateinit var fabricPrivacy: FabricPrivacy
|
||||
@Inject lateinit var resourceHelper: ResourceHelper
|
||||
@Inject lateinit var profileFunction: ProfileFunction
|
||||
@Inject lateinit var treatmentsPlugin: TreatmentsPlugin
|
||||
@Inject lateinit var activePlugin: ActivePluginProvider
|
||||
@Inject lateinit var iobCobCalculatorPlugin: IobCobCalculatorPlugin
|
||||
|
||||
private var wizard: BolusWizard? = null
|
||||
|
||||
|
@ -79,29 +100,32 @@ class WizardDialog : DialogFragment() {
|
|||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
loadCheckedStates()
|
||||
processCobCheckBox()
|
||||
treatments_wizard_sbcheckbox.visibility = SP.getBoolean(R.string.key_usesuperbolus, false).toVisibility()
|
||||
treatments_wizard_notes_layout.visibility = SP.getBoolean(R.string.key_show_notes_entry_dialogs, false).toVisibility()
|
||||
treatments_wizard_sbcheckbox.visibility = sp.getBoolean(R.string.key_usesuperbolus, false).toVisibility()
|
||||
treatments_wizard_notes_layout.visibility = sp.getBoolean(R.string.key_show_notes_entry_dialogs, false).toVisibility()
|
||||
|
||||
val maxCarbs = MainApp.getConstraintChecker().maxCarbsAllowed.value()
|
||||
val maxCorrection = MainApp.getConstraintChecker().maxBolusAllowed.value()
|
||||
val maxCarbs = constraintChecker.getMaxCarbsAllowed().value()
|
||||
val maxCorrection = constraintChecker.getMaxBolusAllowed().value()
|
||||
|
||||
treatments_wizard_bg_input.setParams(savedInstanceState?.getDouble("treatments_wizard_bg_input")
|
||||
?: 0.0, 0.0, 500.0, 0.1, DecimalFormat("0.0"), false, ok, textWatcher)
|
||||
if (profileFunction.getUnits() == Constants.MGDL)
|
||||
treatments_wizard_bg_input.setParams(savedInstanceState?.getDouble("treatments_wizard_bg_input")
|
||||
?: 0.0, 0.0, 500.0, 1.0, DecimalFormat("0.0"), false, ok, textWatcher)
|
||||
else
|
||||
treatments_wizard_bg_input.setParams(savedInstanceState?.getDouble("treatments_wizard_bg_input")
|
||||
?: 0.0, 0.0, 30.0, 0.1, DecimalFormat("0.0"), false, ok, textWatcher)
|
||||
treatments_wizard_carbs_input.setParams(savedInstanceState?.getDouble("treatments_wizard_carbs_input")
|
||||
?: 0.0, 0.0, maxCarbs.toDouble(), 1.0, DecimalFormat("0"), false, ok, textWatcher)
|
||||
val bolusStep = ConfigBuilderPlugin.getPlugin().activePump?.pumpDescription?.bolusStep
|
||||
?: 0.1
|
||||
val bolusStep = activePlugin.activePump.pumpDescription.bolusStep
|
||||
treatments_wizard_correction_input.setParams(savedInstanceState?.getDouble("treatments_wizard_correction_input")
|
||||
?: 0.0, -maxCorrection, maxCorrection, bolusStep, DecimalFormatter.pumpSupportedBolusFormat(), false, ok, textWatcher)
|
||||
?: 0.0, -maxCorrection, maxCorrection, bolusStep, DecimalFormatter.pumpSupportedBolusFormat(activePlugin.activePump), false, ok, textWatcher)
|
||||
treatments_wizard_carb_time_input.setParams(savedInstanceState?.getDouble("treatments_wizard_carb_time_input")
|
||||
?: 0.0, -60.0, 60.0, 5.0, DecimalFormat("0"), false, ok, textWatcher)
|
||||
initDialog()
|
||||
|
||||
treatments_wizard_percent_used.text = MainApp.gs(R.string.format_percent, SP.getInt(R.string.key_boluswizard_percentage, 100))
|
||||
treatments_wizard_percent_used.text = resourceHelper.gs(R.string.format_percent, sp.getInt(R.string.key_boluswizard_percentage, 100))
|
||||
// ok button
|
||||
ok.setOnClickListener {
|
||||
if (okClicked) {
|
||||
log.debug("guarding: ok already clicked")
|
||||
aapsLogger.debug(LTag.UI, "guarding: ok already clicked")
|
||||
} else {
|
||||
okClicked = true
|
||||
calculateInsulin()
|
||||
|
@ -122,13 +146,13 @@ class WizardDialog : DialogFragment() {
|
|||
treatments_wizard_bgtrendcheckbox.setOnCheckedChangeListener(::onCheckedChanged)
|
||||
treatments_wizard_sbcheckbox.setOnCheckedChangeListener(::onCheckedChanged)
|
||||
|
||||
val showCalc = SP.getBoolean(MainApp.gs(R.string.key_wizard_calculation_visible), false)
|
||||
val showCalc = sp.getBoolean(resourceHelper.gs(R.string.key_wizard_calculation_visible), false)
|
||||
treatments_wizard_delimiter.visibility = showCalc.toVisibility()
|
||||
treatments_wizard_resulttable.visibility = showCalc.toVisibility()
|
||||
treatments_wizard_calculationcheckbox.isChecked = showCalc
|
||||
treatments_wizard_calculationcheckbox.setOnCheckedChangeListener { _, isChecked ->
|
||||
run {
|
||||
SP.putBoolean(MainApp.gs(R.string.key_wizard_calculation_visible), isChecked)
|
||||
sp.putBoolean(resourceHelper.gs(R.string.key_wizard_calculation_visible), isChecked)
|
||||
treatments_wizard_delimiter.visibility = isChecked.toVisibility()
|
||||
treatments_wizard_resulttable.visibility = isChecked.toVisibility()
|
||||
}
|
||||
|
@ -136,7 +160,7 @@ class WizardDialog : DialogFragment() {
|
|||
// profile spinner
|
||||
treatments_wizard_profile.onItemSelectedListener = object : OnItemSelectedListener {
|
||||
override fun onNothingSelected(parent: AdapterView<*>?) {
|
||||
ToastUtils.showToastInUiThread(MainApp.instance().applicationContext, MainApp.gs(R.string.noprofileselected))
|
||||
ToastUtils.showToastInUiThread(mainApp, resourceHelper.gs(R.string.noprofileselected))
|
||||
ok.visibility = View.GONE
|
||||
}
|
||||
|
||||
|
@ -146,14 +170,12 @@ class WizardDialog : DialogFragment() {
|
|||
}
|
||||
}
|
||||
// bus
|
||||
disposable.add(RxBus
|
||||
disposable.add(rxBus
|
||||
.toObservable(EventAutosensCalculationFinished::class.java)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({
|
||||
activity?.runOnUiThread { calculateInsulin() }
|
||||
}, {
|
||||
FabricPrivacy.logException(it)
|
||||
})
|
||||
}, { fabricPrivacy.logException(it) })
|
||||
)
|
||||
|
||||
}
|
||||
|
@ -165,7 +187,7 @@ class WizardDialog : DialogFragment() {
|
|||
|
||||
private fun onCheckedChanged(buttonView: CompoundButton, @Suppress("UNUSED_PARAMETER") state: Boolean) {
|
||||
saveCheckedStates()
|
||||
treatments_wizard_ttcheckbox.isEnabled = treatments_wizard_bgcheckbox.isChecked && TreatmentsPlugin.getPlugin().tempTargetFromHistory != null
|
||||
treatments_wizard_ttcheckbox.isEnabled = treatments_wizard_bgcheckbox.isChecked && treatmentsPlugin.tempTargetFromHistory != null
|
||||
if (buttonView.id == treatments_wizard_cobcheckbox.id)
|
||||
processCobCheckBox()
|
||||
calculateInsulin()
|
||||
|
@ -184,34 +206,34 @@ class WizardDialog : DialogFragment() {
|
|||
}
|
||||
|
||||
private fun saveCheckedStates() {
|
||||
SP.putBoolean(MainApp.gs(R.string.key_wizard_include_cob), treatments_wizard_cobcheckbox.isChecked)
|
||||
SP.putBoolean(MainApp.gs(R.string.key_wizard_include_trend_bg), treatments_wizard_bgtrendcheckbox.isChecked)
|
||||
sp.putBoolean(resourceHelper.gs(R.string.key_wizard_include_cob), treatments_wizard_cobcheckbox.isChecked)
|
||||
sp.putBoolean(resourceHelper.gs(R.string.key_wizard_include_trend_bg), treatments_wizard_bgtrendcheckbox.isChecked)
|
||||
}
|
||||
|
||||
private fun loadCheckedStates() {
|
||||
treatments_wizard_bgtrendcheckbox.isChecked = SP.getBoolean(MainApp.gs(R.string.key_wizard_include_trend_bg), false)
|
||||
treatments_wizard_cobcheckbox.isChecked = SP.getBoolean(MainApp.gs(R.string.key_wizard_include_cob), false)
|
||||
treatments_wizard_bgtrendcheckbox.isChecked = sp.getBoolean(resourceHelper.gs(R.string.key_wizard_include_trend_bg), false)
|
||||
treatments_wizard_cobcheckbox.isChecked = sp.getBoolean(resourceHelper.gs(R.string.key_wizard_include_cob), false)
|
||||
}
|
||||
|
||||
private fun initDialog() {
|
||||
val profile = ProfileFunctions.getInstance().profile
|
||||
val profileStore = ConfigBuilderPlugin.getPlugin().activeProfileInterface?.profile
|
||||
val profile = profileFunction.getProfile()
|
||||
val profileStore = activePlugin.activeProfileInterface.profile
|
||||
|
||||
if (profile == null || profileStore == null) {
|
||||
ToastUtils.showToastInUiThread(MainApp.instance().applicationContext, MainApp.gs(R.string.noprofile))
|
||||
ToastUtils.showToastInUiThread(mainApp, resourceHelper.gs(R.string.noprofile))
|
||||
dismiss()
|
||||
return
|
||||
}
|
||||
|
||||
val profileList: ArrayList<CharSequence>
|
||||
profileList = profileStore.getProfileList()
|
||||
profileList.add(0, MainApp.gs(R.string.active))
|
||||
profileList.add(0, resourceHelper.gs(R.string.active))
|
||||
context?.let { context ->
|
||||
val adapter = ArrayAdapter(context, R.layout.spinner_centered, profileList)
|
||||
treatments_wizard_profile.adapter = adapter
|
||||
} ?: return
|
||||
|
||||
val units = ProfileFunctions.getSystemUnits()
|
||||
val units = profileFunction.getUnits()
|
||||
treatments_wizard_bgunits.text = units
|
||||
if (units == Constants.MGDL)
|
||||
treatments_wizard_bg_input.setStep(1.0)
|
||||
|
@ -219,38 +241,38 @@ class WizardDialog : DialogFragment() {
|
|||
treatments_wizard_bg_input.setStep(0.1)
|
||||
|
||||
// Set BG if not old
|
||||
val lastBg = DatabaseHelper.actualBg()
|
||||
val lastBg = iobCobCalculatorPlugin.actualBg()
|
||||
|
||||
if (lastBg != null) {
|
||||
treatments_wizard_bg_input.value = lastBg.valueToUnits(units)
|
||||
} else {
|
||||
treatments_wizard_bg_input.value = 0.0
|
||||
}
|
||||
treatments_wizard_ttcheckbox.isEnabled = TreatmentsPlugin.getPlugin().tempTargetFromHistory != null
|
||||
treatments_wizard_ttcheckbox.isEnabled = treatmentsPlugin.tempTargetFromHistory != null
|
||||
|
||||
// IOB calculation
|
||||
TreatmentsPlugin.getPlugin().updateTotalIOBTreatments()
|
||||
val bolusIob = TreatmentsPlugin.getPlugin().lastCalculationTreatments.round()
|
||||
TreatmentsPlugin.getPlugin().updateTotalIOBTempBasals()
|
||||
val basalIob = TreatmentsPlugin.getPlugin().lastCalculationTempBasals.round()
|
||||
treatmentsPlugin.updateTotalIOBTreatments()
|
||||
val bolusIob = treatmentsPlugin.lastCalculationTreatments.round()
|
||||
treatmentsPlugin.updateTotalIOBTempBasals()
|
||||
val basalIob = treatmentsPlugin.lastCalculationTempBasals.round()
|
||||
|
||||
treatments_wizard_bolusiobinsulin.text = StringUtils.formatInsulin(-bolusIob.iob)
|
||||
treatments_wizard_basaliobinsulin.text = StringUtils.formatInsulin(-basalIob.basaliob)
|
||||
treatments_wizard_bolusiobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, -bolusIob.iob)
|
||||
treatments_wizard_basaliobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, -basalIob.basaliob)
|
||||
|
||||
calculateInsulin()
|
||||
|
||||
treatments_wizard_percent_used.visibility = (SP.getInt(R.string.key_boluswizard_percentage, 100) != 100).toVisibility()
|
||||
treatments_wizard_percent_used.visibility = (sp.getInt(R.string.key_boluswizard_percentage, 100) != 100).toVisibility()
|
||||
}
|
||||
|
||||
private fun calculateInsulin() {
|
||||
val profileStore = ConfigBuilderPlugin.getPlugin().activeProfileInterface?.profile
|
||||
if (treatments_wizard_profile.selectedItem == null || profileStore == null)
|
||||
val profileStore = activePlugin.activeProfileInterface.profile
|
||||
if (treatments_wizard_profile?.selectedItem == null || profileStore == null)
|
||||
return // not initialized yet
|
||||
var profileName = treatments_wizard_profile.selectedItem.toString()
|
||||
val specificProfile: Profile?
|
||||
if (profileName == MainApp.gs(R.string.active)) {
|
||||
specificProfile = ProfileFunctions.getInstance().profile
|
||||
profileName = ProfileFunctions.getInstance().profileName
|
||||
if (profileName == resourceHelper.gs(R.string.active)) {
|
||||
specificProfile = profileFunction.getProfile()
|
||||
profileName = profileFunction.getProfileName()
|
||||
} else
|
||||
specificProfile = profileStore.getSpecificProfile(profileName)
|
||||
|
||||
|
@ -260,27 +282,27 @@ class WizardDialog : DialogFragment() {
|
|||
var bg = SafeParse.stringToDouble(treatments_wizard_bg_input.text)
|
||||
val carbs = SafeParse.stringToInt(treatments_wizard_carbs_input.text)
|
||||
val correction = SafeParse.stringToDouble(treatments_wizard_correction_input.text)
|
||||
val carbsAfterConstraint = MainApp.getConstraintChecker().applyCarbsConstraints(Constraint(carbs)).value()
|
||||
val carbsAfterConstraint = constraintChecker.applyCarbsConstraints(Constraint(carbs)).value()
|
||||
if (abs(carbs - carbsAfterConstraint) > 0.01) {
|
||||
treatments_wizard_carbs_input.value = 0.0
|
||||
ToastUtils.showToastInUiThread(MainApp.instance().applicationContext, MainApp.gs(R.string.carbsconstraintapplied))
|
||||
ToastUtils.showToastInUiThread(mainApp, resourceHelper.gs(R.string.carbsconstraintapplied))
|
||||
return
|
||||
}
|
||||
|
||||
bg = if (treatments_wizard_bgcheckbox.isChecked) bg else 0.0
|
||||
val tempTarget = if (treatments_wizard_ttcheckbox.isChecked) TreatmentsPlugin.getPlugin().tempTargetFromHistory else null
|
||||
val tempTarget = if (treatments_wizard_ttcheckbox.isChecked) treatmentsPlugin.tempTargetFromHistory else null
|
||||
|
||||
// COB
|
||||
var cob = 0.0
|
||||
if (treatments_wizard_cobcheckbox.isChecked) {
|
||||
val cobInfo = IobCobCalculatorPlugin.getPlugin().getCobInfo(false, "Wizard COB")
|
||||
val cobInfo = iobCobCalculatorPlugin.getCobInfo(false, "Wizard COB")
|
||||
cobInfo.displayCob?.let { cob = it }
|
||||
}
|
||||
|
||||
val carbTime = SafeParse.stringToInt(treatments_wizard_carb_time_input.text)
|
||||
|
||||
wizard = BolusWizard(specificProfile, profileName, tempTarget, carbsAfterConstraint, cob, bg, correction,
|
||||
SP.getInt(R.string.key_boluswizard_percentage, 100).toDouble(),
|
||||
wizard = BolusWizard(mainApp).doCalc(specificProfile, profileName, tempTarget, carbsAfterConstraint, cob, bg, correction,
|
||||
sp.getInt(R.string.key_boluswizard_percentage, 100).toDouble(),
|
||||
treatments_wizard_bgcheckbox.isChecked,
|
||||
treatments_wizard_cobcheckbox.isChecked,
|
||||
treatments_wizard_bolusiobcheckbox.isChecked,
|
||||
|
@ -291,50 +313,61 @@ class WizardDialog : DialogFragment() {
|
|||
treatment_wizard_notes.text.toString(), carbTime)
|
||||
|
||||
wizard?.let { wizard ->
|
||||
treatments_wizard_bg.text = String.format(MainApp.gs(R.string.format_bg_isf), BgReading().value(Profile.toMgdl(bg, ProfileFunctions.getSystemUnits())).valueToUnitsToString(ProfileFunctions.getSystemUnits()), wizard.sens)
|
||||
treatments_wizard_bginsulin.text = StringUtils.formatInsulin(wizard.insulinFromBG)
|
||||
treatments_wizard_bg.text = String.format(resourceHelper.gs(R.string.format_bg_isf), BgReading().value(Profile.toMgdl(bg, profileFunction.getUnits())).valueToUnitsToString(profileFunction.getUnits()), wizard.sens)
|
||||
treatments_wizard_bginsulin.text = resourceHelper.gs(R.string.formatinsulinunits, wizard.insulinFromBG)
|
||||
|
||||
treatments_wizard_carbs.text = String.format(MainApp.gs(R.string.format_carbs_ic), carbs.toDouble(), wizard.ic)
|
||||
treatments_wizard_carbsinsulin.text = StringUtils.formatInsulin(wizard.insulinFromCarbs)
|
||||
treatments_wizard_carbs.text = String.format(resourceHelper.gs(R.string.format_carbs_ic), carbs.toDouble(), wizard.ic)
|
||||
treatments_wizard_carbsinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, wizard.insulinFromCarbs)
|
||||
|
||||
treatments_wizard_bolusiobinsulin.text = StringUtils.formatInsulin(wizard.insulinFromBolusIOB)
|
||||
treatments_wizard_basaliobinsulin.text = StringUtils.formatInsulin(wizard.insulinFromBasalsIOB)
|
||||
treatments_wizard_bolusiobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, wizard.insulinFromBolusIOB)
|
||||
treatments_wizard_basaliobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, wizard.insulinFromBasalsIOB)
|
||||
|
||||
treatments_wizard_correctioninsulin.text = StringUtils.formatInsulin(wizard.insulinFromCorrection)
|
||||
treatments_wizard_correctioninsulin.text = resourceHelper.gs(R.string.formatinsulinunits, wizard.insulinFromCorrection)
|
||||
|
||||
// Superbolus
|
||||
treatments_wizard_sb.text = if (treatments_wizard_sbcheckbox.isChecked) MainApp.gs(R.string.twohours) else ""
|
||||
treatments_wizard_sbinsulin.text = StringUtils.formatInsulin(wizard.insulinFromSuperBolus)
|
||||
treatments_wizard_sb.text = if (treatments_wizard_sbcheckbox.isChecked) resourceHelper.gs(R.string.twohours) else ""
|
||||
treatments_wizard_sbinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, wizard.insulinFromSuperBolus)
|
||||
|
||||
// Trend
|
||||
if (treatments_wizard_bgtrendcheckbox.isChecked && wizard.glucoseStatus != null) {
|
||||
treatments_wizard_bgtrend.text = ((if (wizard.trend > 0) "+" else "")
|
||||
+ Profile.toUnitsString(wizard.trend * 3, wizard.trend * 3 / Constants.MMOLL_TO_MGDL, ProfileFunctions.getSystemUnits())
|
||||
+ " " + ProfileFunctions.getSystemUnits())
|
||||
+ Profile.toUnitsString(wizard.trend * 3, wizard.trend * 3 / Constants.MMOLL_TO_MGDL, profileFunction.getUnits())
|
||||
+ " " + profileFunction.getUnits())
|
||||
} else {
|
||||
treatments_wizard_bgtrend.text = ""
|
||||
}
|
||||
treatments_wizard_bgtrendinsulin.text = StringUtils.formatInsulin(wizard.insulinFromTrend)
|
||||
treatments_wizard_bgtrendinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, wizard.insulinFromTrend)
|
||||
|
||||
// COB
|
||||
if (treatments_wizard_cobcheckbox.isChecked) {
|
||||
treatments_wizard_cob.text = String.format(MainApp.gs(R.string.format_cob_ic), cob, wizard.ic)
|
||||
treatments_wizard_cobinsulin.text = StringUtils.formatInsulin(wizard.insulinFromCOB)
|
||||
treatments_wizard_cob.text = String.format(resourceHelper.gs(R.string.format_cob_ic), cob, wizard.ic)
|
||||
treatments_wizard_cobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, wizard.insulinFromCOB)
|
||||
} else {
|
||||
treatments_wizard_cob.text = ""
|
||||
treatments_wizard_cobinsulin.text = ""
|
||||
}
|
||||
|
||||
if (wizard.calculatedTotalInsulin > 0.0 || carbsAfterConstraint > 0.0) {
|
||||
val insulinText = if (wizard.calculatedTotalInsulin > 0.0) MainApp.gs(R.string.formatinsulinunits, wizard.calculatedTotalInsulin) else ""
|
||||
val carbsText = if (carbsAfterConstraint > 0.0) MainApp.gs(R.string.format_carbs, carbsAfterConstraint) else ""
|
||||
treatments_wizard_total.text = MainApp.gs(R.string.result_insulin_carbs, insulinText, carbsText)
|
||||
val insulinText = if (wizard.calculatedTotalInsulin > 0.0) resourceHelper.gs(R.string.formatinsulinunits, wizard.calculatedTotalInsulin) else ""
|
||||
val carbsText = if (carbsAfterConstraint > 0.0) resourceHelper.gs(R.string.format_carbs, carbsAfterConstraint) else ""
|
||||
treatments_wizard_total.text = resourceHelper.gs(R.string.result_insulin_carbs, insulinText, carbsText)
|
||||
ok.visibility = View.VISIBLE
|
||||
} else {
|
||||
treatments_wizard_total.text = MainApp.gs(R.string.missing_carbs, wizard.carbsEquivalent.toInt())
|
||||
treatments_wizard_total.text = resourceHelper.gs(R.string.missing_carbs, wizard.carbsEquivalent.toInt())
|
||||
ok.visibility = View.INVISIBLE
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun show(manager: FragmentManager, tag: String?) {
|
||||
try {
|
||||
manager.beginTransaction().let {
|
||||
it.add(this, tag)
|
||||
it.commitAllowingStateLoss()
|
||||
}
|
||||
} catch (e: IllegalStateException) {
|
||||
aapsLogger.debug(e.localizedMessage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
package info.nightscout.androidaps.dialogs
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.Window
|
||||
import android.view.WindowManager
|
||||
import dagger.android.support.DaggerDialogFragment
|
||||
import info.nightscout.androidaps.Constants
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||
import info.nightscout.androidaps.utils.DecimalFormatter
|
||||
import info.nightscout.androidaps.utils.JsonHelper
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import kotlinx.android.synthetic.main.dialog_wizardinfo.*
|
||||
import org.json.JSONObject
|
||||
import javax.inject.Inject
|
||||
|
||||
class WizardInfoDialog : DaggerDialogFragment() {
|
||||
@Inject lateinit var resourceHelper: ResourceHelper
|
||||
@Inject lateinit var profileFunction: ProfileFunction
|
||||
|
||||
private var json: JSONObject? = null
|
||||
|
||||
fun setData(json: JSONObject) {
|
||||
this.json = json
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
dialog?.window?.requestFeature(Window.FEATURE_NO_TITLE)
|
||||
dialog?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN)
|
||||
isCancelable = true
|
||||
dialog?.setCanceledOnTouchOutside(false)
|
||||
return inflater.inflate(R.layout.dialog_wizardinfo, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
close.setOnClickListener { dismiss() }
|
||||
val units = profileFunction.getUnits()
|
||||
val bgString =
|
||||
if (units == Constants.MGDL) DecimalFormatter.to0Decimal(JsonHelper.safeGetDouble(json, "bg"))
|
||||
else DecimalFormatter.to1Decimal(JsonHelper.safeGetDouble(json, "bg"))
|
||||
// BG
|
||||
treatments_wizard_bg.text = resourceHelper.gs(R.string.format_bg_isf, bgString, JsonHelper.safeGetDouble(json, "isf"))
|
||||
treatments_wizard_bginsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "insulinbg"))
|
||||
treatments_wizard_bgcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "insulinbgused")
|
||||
treatments_wizard_ttcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "ttused")
|
||||
// Trend
|
||||
treatments_wizard_bgtrend.text = JsonHelper.safeGetString(json, "trend")
|
||||
treatments_wizard_bgtrendinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "insulintrend"))
|
||||
treatments_wizard_bgtrendcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "trendused")
|
||||
// COB
|
||||
treatments_wizard_cob.text = resourceHelper.gs(R.string.format_cob_ic, JsonHelper.safeGetDouble(json, "cob"), JsonHelper.safeGetDouble(json, "ic"))
|
||||
treatments_wizard_cobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "insulincob"))
|
||||
treatments_wizard_cobcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "cobused")
|
||||
// Bolus IOB
|
||||
treatments_wizard_bolusiobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "bolusiob"))
|
||||
treatments_wizard_bolusiobcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "bolusiobused")
|
||||
// Basal IOB
|
||||
treatments_wizard_basaliobinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "basaliob"))
|
||||
treatments_wizard_basaliobcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "basaliobused")
|
||||
// Superbolus
|
||||
treatments_wizard_sbinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "insulinsuperbolus"))
|
||||
treatments_wizard_sbcheckbox.isChecked = JsonHelper.safeGetBoolean(json, "superbolusused")
|
||||
// Carbs
|
||||
treatments_wizard_carbs.text = resourceHelper.gs(R.string.format_carbs_ic, JsonHelper.safeGetDouble(json, "carbs"), JsonHelper.safeGetDouble(json, "ic"))
|
||||
treatments_wizard_carbsinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "insulincarbs"))
|
||||
// Correction
|
||||
treatments_wizard_correctioninsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "othercorrection"))
|
||||
// Profile
|
||||
treatments_wizard_profile.text = JsonHelper.safeGetString(json, "profile")
|
||||
// Notes
|
||||
treatments_wizard_notes.text = JsonHelper.safeGetString(json, "notes")
|
||||
// Percentage
|
||||
treatments_wizard_percent_used.text = DecimalFormatter.to0Decimal(JsonHelper.safeGetDouble(json, "percentageCorrection", 100.0)) + "%"
|
||||
// Total
|
||||
treatments_wizard_totalinsulin.text = resourceHelper.gs(R.string.formatinsulinunits, JsonHelper.safeGetDouble(json, "insulin"))
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
dialog?.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
}
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
package info.nightscout.androidaps.events
|
||||
|
||||
class EventChargingState(val isCharging: Boolean) : Event()
|
|
@ -1,16 +0,0 @@
|
|||
package info.nightscout.androidaps.events
|
||||
|
||||
import info.nightscout.androidaps.utils.StringUtils
|
||||
|
||||
class EventNetworkChange : Event() {
|
||||
|
||||
var mobileConnected = false
|
||||
var wifiConnected = false
|
||||
|
||||
var ssid = ""
|
||||
var roaming = false
|
||||
|
||||
fun connectedSsid(): String {
|
||||
return StringUtils.removeSurroundingQuotes(ssid)
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
package info.nightscout.androidaps.events
|
||||
|
||||
import android.os.Bundle
|
||||
import org.json.JSONArray
|
||||
|
||||
/**
|
||||
* Event which is published with data fetched from NightScout specific for the
|
||||
|
@ -10,7 +10,8 @@ import android.os.Bundle
|
|||
* subscriber.
|
||||
*/
|
||||
|
||||
class EventNsFood(val mode: Int, val payload: Bundle) : Event() {
|
||||
class EventNsFood(val mode: Int, val foods: JSONArray) : Event() {
|
||||
|
||||
companion object {
|
||||
val ADD = 0
|
||||
val UPDATE = 1
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
package info.nightscout.androidaps.events
|
||||
|
||||
import info.nightscout.androidaps.MainApp
|
||||
|
||||
class EventPreferenceChange : Event {
|
||||
private var changedKey: String? = null
|
||||
|
||||
constructor(key: String) {
|
||||
changedKey = key
|
||||
}
|
||||
|
||||
constructor(resourceID: Int) {
|
||||
changedKey = MainApp.gs(resourceID)
|
||||
}
|
||||
|
||||
fun isChanged(id: Int): Boolean {
|
||||
return changedKey == MainApp.gs(id)
|
||||
}
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
package info.nightscout.androidaps.events
|
||||
|
||||
import info.nightscout.androidaps.MainApp
|
||||
import info.nightscout.androidaps.R
|
||||
|
||||
class EventPumpStatusChanged : EventStatus {
|
||||
|
||||
enum class Status {
|
||||
CONNECTING,
|
||||
CONNECTED,
|
||||
HANDSHAKING,
|
||||
PERFORMING,
|
||||
DISCONNECTING,
|
||||
DISCONNECTED
|
||||
}
|
||||
|
||||
var sStatus: Status = Status.DISCONNECTED
|
||||
var sSecondsElapsed = 0
|
||||
var sPerfomingAction = ""
|
||||
var error = ""
|
||||
|
||||
constructor(status: Status) {
|
||||
sStatus = status
|
||||
sSecondsElapsed = 0
|
||||
error = ""
|
||||
}
|
||||
|
||||
constructor(status: Status, secondsElapsed: Int) {
|
||||
sStatus = status
|
||||
sSecondsElapsed = secondsElapsed
|
||||
error = ""
|
||||
}
|
||||
|
||||
constructor(status: Status, error: String) {
|
||||
sStatus = status
|
||||
sSecondsElapsed = 0
|
||||
this.error = error
|
||||
}
|
||||
|
||||
constructor(action: String) {
|
||||
sStatus = Status.PERFORMING
|
||||
sSecondsElapsed = 0
|
||||
sPerfomingAction = action
|
||||
}
|
||||
|
||||
// status for startup wizard
|
||||
override fun getStatus(): String {
|
||||
if (sStatus == Status.CONNECTING)
|
||||
return String.format(MainApp.gs(R.string.danar_history_connectingfor), sSecondsElapsed)
|
||||
else if (sStatus == Status.HANDSHAKING)
|
||||
return MainApp.gs(R.string.handshaking)
|
||||
else if (sStatus == Status.CONNECTED)
|
||||
return MainApp.gs(R.string.connected)
|
||||
else if (sStatus == Status.PERFORMING)
|
||||
return sPerfomingAction
|
||||
else if (sStatus == Status.DISCONNECTING)
|
||||
return MainApp.gs(R.string.disconnecting)
|
||||
else if (sStatus == Status.DISCONNECTED)
|
||||
return ""
|
||||
return ""
|
||||
}
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
package info.nightscout.androidaps.events
|
||||
|
||||
class EventRebuildTabs @JvmOverloads constructor(var recreate: Boolean = false) : Event()
|
|
@ -1,3 +0,0 @@
|
|||
package info.nightscout.androidaps.events
|
||||
|
||||
class EventRefreshOverview(var from: String) : Event()
|
|
@ -1,6 +0,0 @@
|
|||
package info.nightscout.androidaps.events
|
||||
|
||||
// pass string to startup wizard
|
||||
abstract class EventStatus :Event() {
|
||||
abstract fun getStatus() : String
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
package info.nightscout.androidaps.events
|
||||
|
||||
import info.nightscout.androidaps.plugins.treatments.Treatment
|
||||
import info.nightscout.androidaps.db.Treatment
|
||||
|
||||
class EventTreatmentChange(val treatment: Treatment?) : EventLoop()
|
||||
|
|
|
@ -0,0 +1,371 @@
|
|||
package info.nightscout.androidaps.historyBrowser
|
||||
|
||||
import android.app.DatePickerDialog
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.util.DisplayMetrics
|
||||
import android.view.ViewGroup
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.RelativeLayout
|
||||
import android.widget.TextView
|
||||
import com.jjoe64.graphview.GraphView
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.activities.NoSplashAppCompatActivity
|
||||
import info.nightscout.androidaps.events.EventCustomCalculationFinished
|
||||
import info.nightscout.androidaps.events.EventRefreshOverview
|
||||
import info.nightscout.androidaps.interfaces.ActivePluginProvider
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||
import info.nightscout.androidaps.logging.AAPSLogger
|
||||
import info.nightscout.androidaps.logging.LTag
|
||||
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
||||
import info.nightscout.androidaps.plugins.general.overview.OverviewMenus
|
||||
import info.nightscout.androidaps.plugins.general.overview.graphData.GraphData
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutosensBgLoaded
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutosensCalculationFinished
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventIobCalculationProgress
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.DefaultValueHelper
|
||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||
import info.nightscout.androidaps.utils.T
|
||||
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
|
||||
import info.nightscout.androidaps.utils.extensions.toVisibility
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import kotlinx.android.synthetic.main.activity_historybrowse.*
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class HistoryBrowseActivity : NoSplashAppCompatActivity() {
|
||||
@Inject lateinit var injector: HasAndroidInjector
|
||||
@Inject lateinit var aapsLogger: AAPSLogger
|
||||
@Inject lateinit var rxBus: RxBusWrapper
|
||||
@Inject lateinit var sp: SP
|
||||
@Inject lateinit var resourceHelper: ResourceHelper
|
||||
@Inject lateinit var profileFunction: ProfileFunction
|
||||
@Inject lateinit var defaultValueHelper: DefaultValueHelper
|
||||
@Inject lateinit var iobCobCalculatorPluginHistory: IobCobCalculatorPluginHistory
|
||||
@Inject lateinit var treatmentsPluginHistory: TreatmentsPluginHistory
|
||||
@Inject lateinit var activePlugin: ActivePluginProvider
|
||||
@Inject lateinit var buildHelper: BuildHelper
|
||||
@Inject lateinit var fabricPrivacy: FabricPrivacy
|
||||
@Inject lateinit var overviewMenus: OverviewMenus
|
||||
@Inject lateinit var dateUtil: DateUtil
|
||||
|
||||
private val disposable = CompositeDisposable()
|
||||
|
||||
private val secondaryGraphs = ArrayList<GraphView>()
|
||||
private val secondaryGraphsLabel = ArrayList<TextView>()
|
||||
|
||||
private var axisWidth: Int = 0
|
||||
private var rangeToDisplay = 24 // for graph
|
||||
private var start: Long = 0
|
||||
|
||||
private var eventCustomCalculationFinished = EventCustomCalculationFinished()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_historybrowse)
|
||||
|
||||
historybrowse_left.setOnClickListener {
|
||||
start -= T.hours(rangeToDisplay.toLong()).msecs()
|
||||
runCalculation("onClickLeft")
|
||||
}
|
||||
historybrowse_right.setOnClickListener {
|
||||
start += T.hours(rangeToDisplay.toLong()).msecs()
|
||||
runCalculation("onClickRight")
|
||||
}
|
||||
historybrowse_end.setOnClickListener {
|
||||
val calendar = Calendar.getInstance()
|
||||
calendar.timeInMillis = System.currentTimeMillis()
|
||||
calendar[Calendar.MILLISECOND] = 0
|
||||
calendar[Calendar.SECOND] = 0
|
||||
calendar[Calendar.MINUTE] = 0
|
||||
calendar[Calendar.HOUR_OF_DAY] = 0
|
||||
start = calendar.timeInMillis
|
||||
runCalculation("onClickEnd")
|
||||
}
|
||||
historybrowse_zoom.setOnClickListener {
|
||||
rangeToDisplay += 6
|
||||
rangeToDisplay = if (rangeToDisplay > 24) 6 else rangeToDisplay
|
||||
updateGUI("rangeChange", false)
|
||||
}
|
||||
historybrowse_zoom.setOnLongClickListener {
|
||||
val calendar = Calendar.getInstance()
|
||||
calendar.timeInMillis = start
|
||||
calendar[Calendar.MILLISECOND] = 0
|
||||
calendar[Calendar.SECOND] = 0
|
||||
calendar[Calendar.MINUTE] = 0
|
||||
calendar[Calendar.HOUR_OF_DAY] = 0
|
||||
start = calendar.timeInMillis
|
||||
runCalculation("onLongClickZoom")
|
||||
true
|
||||
}
|
||||
|
||||
// create an OnDateSetListener
|
||||
val dateSetListener = DatePickerDialog.OnDateSetListener { _, year, monthOfYear, dayOfMonth ->
|
||||
val cal = Calendar.getInstance()
|
||||
cal.timeInMillis = start
|
||||
cal[Calendar.YEAR] = year
|
||||
cal[Calendar.MONTH] = monthOfYear
|
||||
cal[Calendar.DAY_OF_MONTH] = dayOfMonth
|
||||
cal[Calendar.MILLISECOND] = 0
|
||||
cal[Calendar.SECOND] = 0
|
||||
cal[Calendar.MINUTE] = 0
|
||||
cal[Calendar.HOUR_OF_DAY] = 0
|
||||
start = cal.timeInMillis
|
||||
historybrowse_date?.text = dateUtil.dateAndTimeString(start)
|
||||
runCalculation("onClickDate")
|
||||
}
|
||||
|
||||
historybrowse_date.setOnClickListener {
|
||||
val cal = Calendar.getInstance()
|
||||
cal.timeInMillis = start
|
||||
DatePickerDialog(this, dateSetListener,
|
||||
cal.get(Calendar.YEAR),
|
||||
cal.get(Calendar.MONTH),
|
||||
cal.get(Calendar.DAY_OF_MONTH)
|
||||
).show()
|
||||
}
|
||||
|
||||
val dm = DisplayMetrics()
|
||||
windowManager?.defaultDisplay?.getMetrics(dm)
|
||||
|
||||
axisWidth = if (dm.densityDpi <= 120) 3 else if (dm.densityDpi <= 160) 10 else if (dm.densityDpi <= 320) 35 else if (dm.densityDpi <= 420) 50 else if (dm.densityDpi <= 560) 70 else 80
|
||||
historybrowse_bggraph?.gridLabelRenderer?.gridColor = resourceHelper.gc(R.color.graphgrid)
|
||||
historybrowse_bggraph?.gridLabelRenderer?.reloadStyles()
|
||||
historybrowse_bggraph?.gridLabelRenderer?.labelVerticalWidth = axisWidth
|
||||
|
||||
overviewMenus.setupChartMenu(overview_chartMenuButton)
|
||||
prepareGraphs()
|
||||
savedInstanceState?.let { bundle ->
|
||||
rangeToDisplay = bundle.getInt("rangeToDisplay", 0)
|
||||
start = bundle.getLong("start", 0)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public override fun onPause() {
|
||||
super.onPause()
|
||||
disposable.clear()
|
||||
iobCobCalculatorPluginHistory.stopCalculation("onPause")
|
||||
}
|
||||
|
||||
public override fun onResume() {
|
||||
super.onResume()
|
||||
disposable.add(rxBus
|
||||
.toObservable(EventAutosensCalculationFinished::class.java)
|
||||
.observeOn(Schedulers.io())
|
||||
.subscribe({
|
||||
// catch only events from iobCobCalculatorPluginHistory
|
||||
if (it.cause is EventCustomCalculationFinished) {
|
||||
updateGUI("EventAutosensCalculationFinished", bgOnly = false)
|
||||
}
|
||||
}) { fabricPrivacy::logException }
|
||||
)
|
||||
disposable.add(rxBus
|
||||
.toObservable(EventAutosensBgLoaded::class.java)
|
||||
.observeOn(Schedulers.io())
|
||||
.subscribe({
|
||||
// catch only events from iobCobCalculatorPluginHistory
|
||||
if (it.cause is EventCustomCalculationFinished) {
|
||||
updateGUI("EventAutosensCalculationFinished", bgOnly = true)
|
||||
}
|
||||
}) { fabricPrivacy::logException }
|
||||
)
|
||||
disposable.add(rxBus
|
||||
.toObservable(EventIobCalculationProgress::class.java)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({ overview_iobcalculationprogess?.text = it.progress }) { fabricPrivacy::logException }
|
||||
)
|
||||
disposable.add(rxBus
|
||||
.toObservable(EventRefreshOverview::class.java)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({
|
||||
if (it.now) {
|
||||
prepareGraphs()
|
||||
updateGUI("EventRefreshOverview", bgOnly = false)
|
||||
}
|
||||
}) { fabricPrivacy::logException }
|
||||
)
|
||||
if (start == 0L) {
|
||||
// set start of current day
|
||||
val calendar = Calendar.getInstance()
|
||||
calendar.timeInMillis = System.currentTimeMillis()
|
||||
calendar[Calendar.MILLISECOND] = 0
|
||||
calendar[Calendar.SECOND] = 0
|
||||
calendar[Calendar.MINUTE] = 0
|
||||
calendar[Calendar.HOUR_OF_DAY] = 0
|
||||
start = calendar.timeInMillis
|
||||
runCalculation("onResume")
|
||||
} else {
|
||||
updateGUI("onResume", bgOnly = false)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
outState.putInt("rangeToDisplay", rangeToDisplay)
|
||||
outState.putLong("start", start)
|
||||
|
||||
}
|
||||
|
||||
private fun prepareGraphs() {
|
||||
val numOfGraphs = overviewMenus.setting.size
|
||||
|
||||
if (numOfGraphs != secondaryGraphs.size - 1) {
|
||||
//aapsLogger.debug("New secondary graph count ${numOfGraphs-1}")
|
||||
// rebuild needed
|
||||
secondaryGraphs.clear()
|
||||
secondaryGraphsLabel.clear()
|
||||
history_iobgraph.removeAllViews()
|
||||
for (i in 1 until numOfGraphs) {
|
||||
val relativeLayout = RelativeLayout(this)
|
||||
relativeLayout.layoutParams = RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
|
||||
val graph = GraphView(this)
|
||||
graph.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, resourceHelper.dpToPx(100)).also { it.setMargins(0, resourceHelper.dpToPx(15), 0, resourceHelper.dpToPx(10)) }
|
||||
graph.gridLabelRenderer?.gridColor = resourceHelper.gc(R.color.graphgrid)
|
||||
graph.gridLabelRenderer?.reloadStyles()
|
||||
graph.gridLabelRenderer?.isHorizontalLabelsVisible = false
|
||||
graph.gridLabelRenderer?.labelVerticalWidth = axisWidth
|
||||
graph.gridLabelRenderer?.numVerticalLabels = 3
|
||||
graph.viewport.backgroundColor = Color.argb(20, 255, 255, 255) // 8% of gray
|
||||
relativeLayout.addView(graph)
|
||||
|
||||
val label = TextView(this)
|
||||
val layoutParams = RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT).also { it.setMargins(resourceHelper.dpToPx(30), resourceHelper.dpToPx(25), 0, 0) }
|
||||
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP)
|
||||
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT)
|
||||
label.layoutParams = layoutParams
|
||||
relativeLayout.addView(label)
|
||||
secondaryGraphsLabel.add(label)
|
||||
|
||||
history_iobgraph.addView(relativeLayout)
|
||||
secondaryGraphs.add(graph)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun runCalculation(from: String) {
|
||||
GlobalScope.launch(Dispatchers.Default) {
|
||||
treatmentsPluginHistory.initializeData(start - T.hours(8).msecs())
|
||||
val end = start + T.hours(rangeToDisplay.toLong()).msecs()
|
||||
iobCobCalculatorPluginHistory.stopCalculation(from)
|
||||
iobCobCalculatorPluginHistory.clearCache()
|
||||
iobCobCalculatorPluginHistory.runCalculation(from, end, true, false, eventCustomCalculationFinished)
|
||||
}
|
||||
}
|
||||
|
||||
fun updateGUI(from: String, bgOnly: Boolean) {
|
||||
aapsLogger.debug(LTag.UI, "updateGUI from: $from")
|
||||
val pump = activePlugin.activePump
|
||||
val profile = profileFunction.getProfile()
|
||||
|
||||
val lowLine = defaultValueHelper.determineLowLine()
|
||||
val highLine = defaultValueHelper.determineHighLine()
|
||||
|
||||
GlobalScope.launch(Dispatchers.Main) {
|
||||
historybrowse_noprofile?.visibility = (profile == null).toVisibility()
|
||||
profile ?: return@launch
|
||||
|
||||
historybrowse_bggraph ?: return@launch
|
||||
historybrowse_date?.text = dateUtil.dateAndTimeString(start)
|
||||
historybrowse_zoom?.text = rangeToDisplay.toString()
|
||||
val graphData = GraphData(injector, historybrowse_bggraph, iobCobCalculatorPluginHistory, treatmentsPluginHistory)
|
||||
val secondaryGraphsData: ArrayList<GraphData> = ArrayList()
|
||||
|
||||
// do preparation in different thread
|
||||
withContext(Dispatchers.Default) {
|
||||
val fromTime: Long = start + T.secs(100).msecs()
|
||||
val toTime: Long = start + T.hours(rangeToDisplay.toLong()).msecs() + T.secs(100).msecs()
|
||||
aapsLogger.debug(LTag.UI, "Period: " + dateUtil.dateAndTimeString(fromTime) + " - " + dateUtil.dateAndTimeString(toTime))
|
||||
val pointer = System.currentTimeMillis()
|
||||
|
||||
// **** In range Area ****
|
||||
graphData.addInRangeArea(fromTime, toTime, lowLine, highLine)
|
||||
|
||||
// **** BG ****
|
||||
graphData.addBgReadings(fromTime, toTime, lowLine, highLine, null)
|
||||
|
||||
// set manual x bounds to have nice steps
|
||||
graphData.formatAxis(fromTime, toTime)
|
||||
|
||||
// add target line
|
||||
graphData.addTargetLine(fromTime, toTime, profile, null)
|
||||
|
||||
// **** NOW line ****
|
||||
graphData.addNowLine(pointer)
|
||||
|
||||
if (!bgOnly) {
|
||||
// Treatments
|
||||
graphData.addTreatments(fromTime, toTime)
|
||||
if (overviewMenus.setting[0][OverviewMenus.CharType.ACT.ordinal])
|
||||
graphData.addActivity(fromTime, toTime, false, 0.8)
|
||||
|
||||
// add basal data
|
||||
if (pump.pumpDescription.isTempBasalCapable && overviewMenus.setting[0][OverviewMenus.CharType.BAS.ordinal]) {
|
||||
graphData.addBasals(fromTime, toTime, lowLine / graphData.maxY / 1.2)
|
||||
}
|
||||
// ------------------ 2nd graph
|
||||
for (g in 0 until secondaryGraphs.size) {
|
||||
val secondGraphData = GraphData(injector, secondaryGraphs[g], iobCobCalculatorPluginHistory, treatmentsPluginHistory)
|
||||
var useIobForScale = false
|
||||
var useCobForScale = false
|
||||
var useDevForScale = false
|
||||
var useRatioForScale = false
|
||||
var useDSForScale = false
|
||||
var useIAForScale = false
|
||||
var useABSForScale = false
|
||||
when {
|
||||
overviewMenus.setting[g + 1][OverviewMenus.CharType.IOB.ordinal] -> useIobForScale = true
|
||||
overviewMenus.setting[g + 1][OverviewMenus.CharType.COB.ordinal] -> useCobForScale = true
|
||||
overviewMenus.setting[g + 1][OverviewMenus.CharType.DEV.ordinal] -> useDevForScale = true
|
||||
overviewMenus.setting[g + 1][OverviewMenus.CharType.SEN.ordinal] -> useRatioForScale = true
|
||||
overviewMenus.setting[g + 1][OverviewMenus.CharType.ACT.ordinal] -> useIAForScale = true
|
||||
overviewMenus.setting[g + 1][OverviewMenus.CharType.ABS.ordinal] -> useABSForScale = true
|
||||
overviewMenus.setting[g + 1][OverviewMenus.CharType.DEVSLOPE.ordinal] -> useDSForScale = true
|
||||
}
|
||||
|
||||
if (overviewMenus.setting[g + 1][OverviewMenus.CharType.IOB.ordinal]) secondGraphData.addIob(fromTime, toTime, useIobForScale, 1.0, overviewMenus.setting[g + 1][OverviewMenus.CharType.PRE.ordinal])
|
||||
if (overviewMenus.setting[g + 1][OverviewMenus.CharType.COB.ordinal]) secondGraphData.addCob(fromTime, toTime, useCobForScale, if (useCobForScale) 1.0 else 0.5)
|
||||
if (overviewMenus.setting[g + 1][OverviewMenus.CharType.DEV.ordinal]) secondGraphData.addDeviations(fromTime, toTime, useDevForScale, 1.0)
|
||||
if (overviewMenus.setting[g + 1][OverviewMenus.CharType.SEN.ordinal]) secondGraphData.addRatio(fromTime, toTime, useRatioForScale, 1.0)
|
||||
if (overviewMenus.setting[g + 1][OverviewMenus.CharType.ACT.ordinal]) secondGraphData.addActivity(fromTime, toTime, useIAForScale, 0.8)
|
||||
if (overviewMenus.setting[g + 1][OverviewMenus.CharType.ABS.ordinal]) secondGraphData.addAbsIob(fromTime, toTime, useABSForScale, 1.0)
|
||||
if (overviewMenus.setting[g + 1][OverviewMenus.CharType.DEVSLOPE.ordinal] && buildHelper.isDev()) secondGraphData.addDeviationSlope(fromTime, toTime, useDSForScale, 1.0)
|
||||
|
||||
// set manual x bounds to have nice steps
|
||||
secondGraphData.formatAxis(fromTime, toTime)
|
||||
secondGraphData.addNowLine(pointer)
|
||||
secondaryGraphsData.add(secondGraphData)
|
||||
}
|
||||
}
|
||||
}
|
||||
// finally enforce drawing of graphs in UI thread
|
||||
graphData.performUpdate()
|
||||
if (!bgOnly)
|
||||
for (g in 0 until secondaryGraphs.size) {
|
||||
secondaryGraphsLabel[g].text = overviewMenus.enabledTypes(g + 1)
|
||||
secondaryGraphs[g].visibility = (!bgOnly && (
|
||||
overviewMenus.setting[g + 1][OverviewMenus.CharType.IOB.ordinal] ||
|
||||
overviewMenus.setting[g + 1][OverviewMenus.CharType.COB.ordinal] ||
|
||||
overviewMenus.setting[g + 1][OverviewMenus.CharType.DEV.ordinal] ||
|
||||
overviewMenus.setting[g + 1][OverviewMenus.CharType.SEN.ordinal] ||
|
||||
overviewMenus.setting[g + 1][OverviewMenus.CharType.ACT.ordinal] ||
|
||||
overviewMenus.setting[g + 1][OverviewMenus.CharType.ABS.ordinal] ||
|
||||
overviewMenus.setting[g + 1][OverviewMenus.CharType.DEVSLOPE.ordinal]
|
||||
)).toVisibility()
|
||||
secondaryGraphsData[g].performUpdate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package info.nightscout.androidaps.historyBrowser
|
||||
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.interfaces.ActivePluginProvider
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||
import info.nightscout.androidaps.logging.AAPSLogger
|
||||
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
|
||||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityAAPSPlugin
|
||||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin
|
||||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAveragePlugin
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class IobCobCalculatorPluginHistory @Inject constructor(
|
||||
injector: HasAndroidInjector,
|
||||
aapsLogger: AAPSLogger,
|
||||
rxBus: RxBusWrapper,
|
||||
sp: SP,
|
||||
resourceHelper: ResourceHelper,
|
||||
profileFunction: ProfileFunction,
|
||||
activePlugin: ActivePluginProvider,
|
||||
treatmentsPluginHistory: TreatmentsPluginHistory,
|
||||
sensitivityOref1Plugin: SensitivityOref1Plugin,
|
||||
sensitivityAAPSPlugin: SensitivityAAPSPlugin,
|
||||
sensitivityWeightedAveragePlugin: SensitivityWeightedAveragePlugin,
|
||||
fabricPrivacy: FabricPrivacy,
|
||||
dateUtil: DateUtil
|
||||
) : IobCobCalculatorPlugin(injector, aapsLogger, rxBus, sp, resourceHelper, profileFunction,
|
||||
activePlugin, treatmentsPluginHistory, sensitivityOref1Plugin, sensitivityAAPSPlugin, sensitivityWeightedAveragePlugin, fabricPrivacy, dateUtil) {
|
||||
|
||||
override fun onStart() { // do not attach to rxbus
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package info.nightscout.androidaps.historyBrowser
|
||||
|
||||
import android.content.Context
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.interfaces.ActivePluginProvider
|
||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||
import info.nightscout.androidaps.logging.AAPSLogger
|
||||
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
|
||||
import info.nightscout.androidaps.plugins.treatments.TreatmentService
|
||||
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class TreatmentsPluginHistory @Inject constructor(
|
||||
injector: HasAndroidInjector,
|
||||
aapsLogger: AAPSLogger,
|
||||
rxBus: RxBusWrapper,
|
||||
resourceHelper: ResourceHelper,
|
||||
context: Context,
|
||||
sp: SP,
|
||||
profileFunction: ProfileFunction,
|
||||
activePlugin: ActivePluginProvider,
|
||||
nsUpload: NSUpload,
|
||||
fabricPrivacy: FabricPrivacy, dateUtil: DateUtil
|
||||
) : TreatmentsPlugin(injector, aapsLogger, rxBus, resourceHelper, context, sp, profileFunction, activePlugin, nsUpload, fabricPrivacy, dateUtil) {
|
||||
|
||||
init {
|
||||
onStart()
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
service = TreatmentService(injector)
|
||||
initializeData(range())
|
||||
}
|
||||
}
|
|
@ -1,144 +0,0 @@
|
|||
package info.nightscout.androidaps.interfaces;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import info.nightscout.androidaps.logging.L;
|
||||
|
||||
/**
|
||||
* Created by mike on 19.03.2018.
|
||||
*/
|
||||
|
||||
public class Constraint<T extends Comparable> {
|
||||
private static Logger log = LoggerFactory.getLogger(L.CONSTRAINTS);
|
||||
|
||||
T value;
|
||||
T originalValue;
|
||||
|
||||
List<String> reasons = new ArrayList<>();
|
||||
List<String> mostLimiting = new ArrayList<>();
|
||||
|
||||
public Constraint(T value) {
|
||||
this.value = value;
|
||||
this.originalValue = value;
|
||||
}
|
||||
|
||||
public T value() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public T originalValue() {
|
||||
return originalValue;
|
||||
}
|
||||
|
||||
public Constraint<T> set(T value) {
|
||||
this.value = value;
|
||||
this.originalValue = value;
|
||||
if (L.isEnabled(L.CONSTRAINTS))
|
||||
log.debug("Setting value " + value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Constraint<T> set(T value, String reason, Object from) {
|
||||
if (L.isEnabled(L.CONSTRAINTS))
|
||||
log.debug("Setting value " + this.value + " -> " + value + " (" + reason + ")[" + translateFrom(from) + "]");
|
||||
this.value = value;
|
||||
addReason(reason, from);
|
||||
addMostLimingReason(reason, from);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Constraint<T> setIfDifferent(T value, String reason, Object from) {
|
||||
if (!this.value.equals(value)) {
|
||||
if (L.isEnabled(L.CONSTRAINTS))
|
||||
log.debug("Setting because of different value " + this.value + " -> " + value + " (" + reason + ")[" + translateFrom(from) + "]");
|
||||
this.value = value;
|
||||
addReason(reason, from);
|
||||
addMostLimingReason(reason, from);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Constraint<T> setIfSmaller(T value, String reason, Object from) {
|
||||
if (value.compareTo(this.value) < 0) {
|
||||
if (L.isEnabled(L.CONSTRAINTS))
|
||||
log.debug("Setting because of smaller value " + this.value + " -> " + value + " (" + reason + ")[" + translateFrom(from) + "]");
|
||||
this.value = value;
|
||||
mostLimiting.clear();
|
||||
addMostLimingReason(reason, from);
|
||||
}
|
||||
if (value.compareTo(this.originalValue) < 0) {
|
||||
addReason(reason, from);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Constraint<T> setIfGreater(T value, String reason, Object from) {
|
||||
if (value.compareTo(this.value) > 0) {
|
||||
if (L.isEnabled(L.CONSTRAINTS))
|
||||
log.debug("Setting because of greater value " + this.value + " -> " + value + " (" + reason + ")[" + translateFrom(from) + "]");
|
||||
this.value = value;
|
||||
mostLimiting.clear();
|
||||
addMostLimingReason(reason, from);
|
||||
}
|
||||
if (value.compareTo(this.originalValue) > 0) {
|
||||
addReason(reason, from);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
private String translateFrom(Object from) {
|
||||
return from.getClass().getSimpleName().replace("Plugin", "");
|
||||
}
|
||||
|
||||
public Constraint addReason(String reason, Object from) {
|
||||
reasons.add(translateFrom(from) + ": " + reason);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Constraint addMostLimingReason(String reason, Object from) {
|
||||
mostLimiting.add(translateFrom(from) + ": " + reason);
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getReasons() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int count = 0;
|
||||
for (String r : reasons) {
|
||||
if (count++ != 0) sb.append("\n");
|
||||
sb.append(r);
|
||||
}
|
||||
if (L.isEnabled(L.CONSTRAINTS))
|
||||
log.debug("Limiting origial value: " + originalValue + " to " + value + ". Reason: " + sb.toString());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public List<String> getReasonList() {
|
||||
return reasons;
|
||||
}
|
||||
|
||||
public String getMostLimitedReasons() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int count = 0;
|
||||
for (String r : mostLimiting) {
|
||||
if (count++ != 0) sb.append("\n");
|
||||
sb.append(r);
|
||||
}
|
||||
if (L.isEnabled(L.CONSTRAINTS))
|
||||
log.debug("Limiting origial value: " + originalValue + " to " + value + ". Reason: " + sb.toString());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public List<String> getMostLimitedReasonList() {
|
||||
return mostLimiting;
|
||||
}
|
||||
|
||||
public void copyReasons(Constraint<?> another) {
|
||||
for (String s : another.getReasonList()) {
|
||||
reasons.add(s);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
package info.nightscout.androidaps.interfaces;
|
||||
|
||||
import info.nightscout.androidaps.data.Profile;
|
||||
|
||||
/**
|
||||
* Created by mike on 15.06.2016.
|
||||
*/
|
||||
public interface ConstraintsInterface {
|
||||
|
||||
default Constraint<Boolean> isLoopInvocationAllowed(Constraint<Boolean> value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
default Constraint<Boolean> isClosedLoopAllowed(Constraint<Boolean> value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
default Constraint<Boolean> isAutosensModeEnabled(Constraint<Boolean> value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
default Constraint<Boolean> isAMAModeEnabled(Constraint<Boolean> value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
default Constraint<Boolean> isSMBModeEnabled(Constraint<Boolean> value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
default Constraint<Boolean> isUAMEnabled(Constraint<Boolean> value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
default Constraint<Boolean> isAdvancedFilteringEnabled(Constraint<Boolean> value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
default Constraint<Boolean> isSuperBolusEnabled(Constraint<Boolean> value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
default Constraint<Double> applyBasalConstraints(Constraint<Double> absoluteRate, Profile profile) {
|
||||
return absoluteRate;
|
||||
}
|
||||
|
||||
default Constraint<Integer> applyBasalPercentConstraints(Constraint<Integer> percentRate, Profile profile) {
|
||||
return percentRate;
|
||||
}
|
||||
|
||||
default Constraint<Double> applyBolusConstraints(Constraint<Double> insulin) {
|
||||
return insulin;
|
||||
}
|
||||
|
||||
default Constraint<Double> applyExtendedBolusConstraints(Constraint<Double> insulin) {
|
||||
return insulin;
|
||||
}
|
||||
|
||||
default Constraint<Integer> applyCarbsConstraints(Constraint<Integer> carbs) {
|
||||
return carbs;
|
||||
}
|
||||
|
||||
default Constraint<Double> applyMaxIOBConstraints(Constraint<Double> maxIob) {
|
||||
return maxIob;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,223 +0,0 @@
|
|||
package info.nightscout.androidaps.interfaces;
|
||||
|
||||
import android.os.SystemClock;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceFragment;
|
||||
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.events.EventConfigBuilderChange;
|
||||
import info.nightscout.androidaps.events.EventRebuildTabs;
|
||||
import info.nightscout.androidaps.logging.L;
|
||||
import info.nightscout.androidaps.plugins.bus.RxBus;
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.configBuilder.EventConfigBuilderUpdateGui;
|
||||
import info.nightscout.androidaps.queue.CommandQueue;
|
||||
import info.nightscout.androidaps.utils.OKDialog;
|
||||
import info.nightscout.androidaps.utils.SP;
|
||||
|
||||
/**
|
||||
* Created by mike on 09.06.2016.
|
||||
*/
|
||||
public abstract class PluginBase {
|
||||
private static Logger log = LoggerFactory.getLogger(L.CORE);
|
||||
|
||||
public enum State {
|
||||
NOT_INITIALIZED,
|
||||
ENABLED,
|
||||
DISABLED
|
||||
}
|
||||
|
||||
private State state = State.NOT_INITIALIZED;
|
||||
private boolean isFragmentVisible = false;
|
||||
public PluginDescription pluginDescription;
|
||||
|
||||
|
||||
// Specific plugin with more Interfaces
|
||||
protected boolean isProfileInterfaceEnabled = false;
|
||||
|
||||
public PluginBase(PluginDescription pluginDescription) {
|
||||
this.pluginDescription = pluginDescription;
|
||||
}
|
||||
|
||||
// Default always calls invoke
|
||||
// Plugins that have special constraints if they get switched to may override this method
|
||||
public void switchAllowed(boolean newState, FragmentActivity activity, PluginType type) {
|
||||
performPluginSwitch(newState, type);
|
||||
}
|
||||
|
||||
protected void confirmPumpPluginActivation(boolean newState, FragmentActivity activity, PluginType type) {
|
||||
if (type == PluginType.PUMP) {
|
||||
boolean allowHardwarePump = SP.getBoolean("allow_hardware_pump", false);
|
||||
if (allowHardwarePump || activity == null) {
|
||||
performPluginSwitch(newState, type);
|
||||
} else {
|
||||
OKDialog.showConfirmation(activity, MainApp.gs(R.string.allow_hardware_pump_text), () -> {
|
||||
performPluginSwitch(newState, type);
|
||||
SP.putBoolean("allow_hardware_pump", true);
|
||||
if (L.isEnabled(L.PUMP))
|
||||
log.debug("First time HW pump allowed!");
|
||||
}, () -> {
|
||||
RxBus.INSTANCE.send(new EventConfigBuilderUpdateGui());
|
||||
if (L.isEnabled(L.PUMP))
|
||||
log.debug("User does not allow switching to HW pump!");
|
||||
});
|
||||
}
|
||||
} else {
|
||||
performPluginSwitch(newState, type);
|
||||
}
|
||||
}
|
||||
|
||||
public void performPluginSwitch(boolean enabled, PluginType type) {
|
||||
setPluginEnabled(type, enabled);
|
||||
setFragmentVisible(type, enabled);
|
||||
ConfigBuilderPlugin.getPlugin().processOnEnabledCategoryChanged(this, getType());
|
||||
ConfigBuilderPlugin.getPlugin().storeSettings("CheckedCheckboxEnabled");
|
||||
RxBus.INSTANCE.send(new EventRebuildTabs());
|
||||
RxBus.INSTANCE.send(new EventConfigBuilderChange());
|
||||
RxBus.INSTANCE.send(new EventConfigBuilderUpdateGui());
|
||||
ConfigBuilderPlugin.getPlugin().logPluginStatus();
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
if (pluginDescription.pluginName == -1)
|
||||
return "UKNOWN";
|
||||
else
|
||||
return MainApp.gs(pluginDescription.pluginName);
|
||||
}
|
||||
|
||||
public String getNameShort() {
|
||||
if (pluginDescription.shortName == -1)
|
||||
return getName();
|
||||
String name = MainApp.gs(pluginDescription.shortName);
|
||||
if (!name.trim().isEmpty()) //only if translation exists
|
||||
return name;
|
||||
// use long name as fallback
|
||||
return getName();
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
if (pluginDescription.description == -1) return null;
|
||||
else return MainApp.gs(pluginDescription.description);
|
||||
}
|
||||
|
||||
public PluginType getType() {
|
||||
return pluginDescription.mainType;
|
||||
}
|
||||
|
||||
public int getPreferencesId() {
|
||||
return pluginDescription.preferencesId;
|
||||
}
|
||||
|
||||
public boolean isEnabled(PluginType type) {
|
||||
if (pluginDescription.alwaysEnabled && type == pluginDescription.mainType)
|
||||
return true;
|
||||
if (pluginDescription.mainType == PluginType.CONSTRAINTS && type == PluginType.CONSTRAINTS)
|
||||
return true;
|
||||
if (type == pluginDescription.mainType)
|
||||
return state == State.ENABLED && specialEnableCondition();
|
||||
if (type == PluginType.CONSTRAINTS && pluginDescription.mainType == PluginType.PUMP && isEnabled(PluginType.PUMP))
|
||||
return true;
|
||||
if (type == PluginType.CONSTRAINTS && pluginDescription.mainType == PluginType.APS && isEnabled(PluginType.APS))
|
||||
return true;
|
||||
if (type == PluginType.PROFILE && pluginDescription.mainType == PluginType.PUMP)
|
||||
return isProfileInterfaceEnabled;
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean hasFragment() {
|
||||
return pluginDescription.fragmentClass != null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* So far plugin can have it's main type + ConstraintInterface + ProfileInterface
|
||||
* ConstraintInterface is enabled if main plugin is enabled
|
||||
* ProfileInterface can be enabled only if main iterface is enable
|
||||
*/
|
||||
|
||||
public void setPluginEnabled(PluginType type, boolean newState) {
|
||||
if (type == pluginDescription.mainType) {
|
||||
if (newState == true) { // enabling plugin
|
||||
if (state != State.ENABLED) {
|
||||
onStateChange(type, state, State.ENABLED);
|
||||
state = State.ENABLED;
|
||||
if (L.isEnabled(L.CORE))
|
||||
log.debug("Starting: " + getName());
|
||||
onStart();
|
||||
}
|
||||
} else { // disabling plugin
|
||||
if (state == State.ENABLED) {
|
||||
onStateChange(type, state, State.DISABLED);
|
||||
state = State.DISABLED;
|
||||
onStop();
|
||||
if (L.isEnabled(L.CORE))
|
||||
log.debug("Stopping: " + getName());
|
||||
}
|
||||
}
|
||||
} else if (type == PluginType.PROFILE) {
|
||||
isProfileInterfaceEnabled = newState;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void setFragmentVisible(PluginType type, boolean fragmentVisible) {
|
||||
if (type == pluginDescription.mainType) {
|
||||
isFragmentVisible = fragmentVisible && specialEnableCondition();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isFragmentVisible() {
|
||||
if (pluginDescription.alwaysVisible)
|
||||
return true;
|
||||
if (pluginDescription.neverVisible)
|
||||
return false;
|
||||
return isFragmentVisible;
|
||||
}
|
||||
|
||||
public boolean showInList(PluginType type) {
|
||||
if (pluginDescription.mainType == type)
|
||||
return pluginDescription.showInList && specialShowInListCondition();
|
||||
|
||||
if (type == PluginType.PROFILE && pluginDescription.mainType == PluginType.PUMP)
|
||||
return isEnabled(PluginType.PUMP);
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean specialEnableCondition() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean specialShowInListCondition() {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void onStart() {
|
||||
if (getType() == PluginType.PUMP) {
|
||||
new Thread(() -> {
|
||||
SystemClock.sleep(3000);
|
||||
CommandQueue commandQueue = ConfigBuilderPlugin.getPlugin().getCommandQueue();
|
||||
if (commandQueue != null)
|
||||
commandQueue.readStatus("Pump driver changed.", null);
|
||||
}).start();
|
||||
}
|
||||
}
|
||||
|
||||
protected void onStop() {
|
||||
}
|
||||
|
||||
protected void onStateChange(PluginType type, State oldState, State newState) {
|
||||
}
|
||||
|
||||
public void preprocessPreferences(@NotNull final PreferenceFragment preferenceFragment) {
|
||||
}
|
||||
|
||||
public void updatePreferenceSummary(@NotNull final Preference pref) {
|
||||
}
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
package info.nightscout.androidaps.interfaces;
|
||||
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult;
|
||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin;
|
||||
|
||||
/**
|
||||
* Created by mike on 24.06.2017.
|
||||
*/
|
||||
|
||||
public interface SensitivityInterface {
|
||||
|
||||
double MIN_HOURS = 1;
|
||||
double MIN_HOURS_FULL_AUTOSENS = 4;
|
||||
|
||||
AutosensResult detectSensitivity(IobCobCalculatorPlugin plugin, long fromTime, long toTime);
|
||||
|
||||
}
|
|
@ -1,133 +0,0 @@
|
|||
package info.nightscout.androidaps.logging;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import info.nightscout.androidaps.utils.SP;
|
||||
|
||||
public class L {
|
||||
|
||||
public static class LogElement {
|
||||
public String name;
|
||||
boolean defaultValue;
|
||||
public boolean enabled;
|
||||
boolean requiresRestart = false;
|
||||
|
||||
LogElement(String name, boolean defaultValue) {
|
||||
this.name = name;
|
||||
this.defaultValue = defaultValue;
|
||||
enabled = SP.getBoolean(getSPName(), defaultValue);
|
||||
}
|
||||
|
||||
LogElement(String name, boolean defaultValue, boolean requiresRestart) {
|
||||
this.name = name;
|
||||
this.defaultValue = defaultValue;
|
||||
this.requiresRestart = requiresRestart;
|
||||
enabled = SP.getBoolean(getSPName(), defaultValue);
|
||||
}
|
||||
|
||||
LogElement(boolean defaultValue) {
|
||||
this.name = "NONEXISTING";
|
||||
this.defaultValue = defaultValue;
|
||||
enabled = defaultValue;
|
||||
}
|
||||
|
||||
private String getSPName() {
|
||||
return "log_" + name;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
SP.putBoolean(getSPName(), enabled);
|
||||
}
|
||||
|
||||
void resetToDefault() {
|
||||
setEnabled(defaultValue);
|
||||
}
|
||||
}
|
||||
|
||||
private static List<LogElement> logElements;
|
||||
|
||||
static {
|
||||
initialize();
|
||||
}
|
||||
|
||||
private static LogElement findByName(String name) {
|
||||
for (LogElement element : logElements) {
|
||||
if (element.name.equals(name))
|
||||
return element;
|
||||
}
|
||||
return new LogElement(false);
|
||||
}
|
||||
|
||||
public static boolean isEnabled(String name) {
|
||||
return findByName(name).enabled;
|
||||
}
|
||||
|
||||
public static List<LogElement> getLogElements() {
|
||||
return logElements;
|
||||
}
|
||||
|
||||
public static void resetToDefaults() {
|
||||
for (LogElement element : logElements) {
|
||||
element.resetToDefault();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static final String CORE = "CORE";
|
||||
public static final String AUTOSENS = "AUTOSENS";
|
||||
public static final String AUTOMATION = "AUTOMATION";
|
||||
public static final String EVENTS = "EVENTS";
|
||||
public static final String GLUCOSE = "GLUCOSE";
|
||||
public static final String BGSOURCE = "BGSOURCE";
|
||||
public static final String OVERVIEW = "OVERVIEW";
|
||||
public static final String NOTIFICATION = "NOTIFICATION";
|
||||
public static final String DATASERVICE = "DATASERVICE";
|
||||
public static final String DATABASE = "DATABASE";
|
||||
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";
|
||||
public static final String PUMPCOMM = "PUMPCOMM";
|
||||
public static final String PUMPBTCOMM = "PUMPBTCOMM";
|
||||
public static final String APS = "APS";
|
||||
public static final String PROFILE = "PROFILE";
|
||||
public static final String CONFIGBUILDER = "CONFIGBUILDER";
|
||||
public static final String UI = "UI";
|
||||
public static final String LOCATION = "LOCATION";
|
||||
public static final String SMS = "SMS";
|
||||
|
||||
private static void initialize() {
|
||||
logElements = new ArrayList<>();
|
||||
logElements.add(new LogElement(APS, true));
|
||||
logElements.add(new LogElement(AUTOMATION, true));
|
||||
logElements.add(new LogElement(AUTOSENS, false));
|
||||
logElements.add(new LogElement(BGSOURCE, true));
|
||||
logElements.add(new LogElement(GLUCOSE, false));
|
||||
logElements.add(new LogElement(CONFIGBUILDER, false));
|
||||
logElements.add(new LogElement(CONSTRAINTS, true));
|
||||
logElements.add(new LogElement(CORE, true));
|
||||
logElements.add(new LogElement(DATABASE, true));
|
||||
logElements.add(new LogElement(DATAFOOD, false));
|
||||
logElements.add(new LogElement(DATASERVICE, true));
|
||||
logElements.add(new LogElement(DATATREATMENTS, true));
|
||||
logElements.add(new LogElement(EVENTS, false, true));
|
||||
logElements.add(new LogElement(LOCATION, true));
|
||||
logElements.add(new LogElement(NOTIFICATION, true));
|
||||
logElements.add(new LogElement(NSCLIENT, true));
|
||||
logElements.add(new LogElement(TIDEPOOL, true));
|
||||
logElements.add(new LogElement(OVERVIEW, true));
|
||||
logElements.add(new LogElement(PROFILE, true));
|
||||
logElements.add(new LogElement(PUMP, true));
|
||||
logElements.add(new LogElement(PUMPBTCOMM, false));
|
||||
logElements.add(new LogElement(PUMPCOMM, true));
|
||||
logElements.add(new LogElement(PUMPQUEUE, true));
|
||||
logElements.add(new LogElement(SMS, true));
|
||||
logElements.add(new LogElement(UI, true));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package info.nightscout.androidaps.plugins.aps.events
|
||||
|
||||
import info.nightscout.androidaps.events.EventUpdateGui
|
||||
|
||||
class EventOpenAPSUpdateGui : EventUpdateGui()
|
|
@ -0,0 +1,5 @@
|
|||
package info.nightscout.androidaps.plugins.aps.events
|
||||
|
||||
import info.nightscout.androidaps.events.EventUpdateGui
|
||||
|
||||
class EventOpenAPSUpdateResultGui(val text: String) : EventUpdateGui()
|
|
@ -0,0 +1,63 @@
|
|||
package info.nightscout.androidaps.plugins.aps.logger;
|
||||
|
||||
import org.mozilla.javascript.ScriptableObject;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import info.nightscout.androidaps.db.StaticInjector;
|
||||
import info.nightscout.androidaps.logging.AAPSLogger;
|
||||
import info.nightscout.androidaps.logging.LTag;
|
||||
|
||||
/**
|
||||
* Created by adrian on 15/10/17.
|
||||
*/
|
||||
|
||||
|
||||
public class LoggerCallback extends ScriptableObject {
|
||||
|
||||
@Inject
|
||||
AAPSLogger aapsLogger;
|
||||
|
||||
private static StringBuffer errorBuffer = new StringBuffer();
|
||||
private static StringBuffer logBuffer = new StringBuffer();
|
||||
|
||||
|
||||
public LoggerCallback() {
|
||||
//empty constructor needed for Rhino
|
||||
errorBuffer = new StringBuffer();
|
||||
logBuffer = new StringBuffer();
|
||||
StaticInjector.Companion.getInstance().androidInjector().inject(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getClassName() {
|
||||
return "LoggerCallback";
|
||||
}
|
||||
|
||||
public void jsConstructor() {
|
||||
//empty constructor on JS site; could work as setter
|
||||
}
|
||||
|
||||
public void jsFunction_log(Object obj1) {
|
||||
aapsLogger.debug(LTag.APS, obj1.toString().trim());
|
||||
logBuffer.append(obj1.toString());
|
||||
}
|
||||
|
||||
public void jsFunction_error(Object obj1) {
|
||||
aapsLogger.error(LTag.APS, obj1.toString().trim());
|
||||
errorBuffer.append(obj1.toString());
|
||||
}
|
||||
|
||||
|
||||
public static String getScriptDebug() {
|
||||
String ret = "";
|
||||
if (errorBuffer.length() > 0) {
|
||||
ret += "e:\n" + errorBuffer.toString();
|
||||
}
|
||||
if (ret.length() > 0 && logBuffer.length() > 0) ret += '\n';
|
||||
if (logBuffer.length() > 0) {
|
||||
ret += "d:\n" + logBuffer.toString();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
|
@ -1,405 +0,0 @@
|
|||
package info.nightscout.androidaps.plugins.aps.loop;
|
||||
|
||||
import android.text.Html;
|
||||
import android.text.Spanned;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.data.IobTotal;
|
||||
import info.nightscout.androidaps.data.Profile;
|
||||
import info.nightscout.androidaps.db.BgReading;
|
||||
import info.nightscout.androidaps.db.TemporaryBasal;
|
||||
import info.nightscout.androidaps.interfaces.Constraint;
|
||||
import info.nightscout.androidaps.interfaces.PumpDescription;
|
||||
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||
import info.nightscout.androidaps.logging.L;
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
|
||||
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
|
||||
import info.nightscout.androidaps.utils.DecimalFormatter;
|
||||
import info.nightscout.androidaps.utils.SP;
|
||||
|
||||
/**
|
||||
* Created by mike on 09.06.2016.
|
||||
*/
|
||||
public class APSResult {
|
||||
private static Logger log = LoggerFactory.getLogger(L.APS);
|
||||
|
||||
public long date = 0;
|
||||
public String reason;
|
||||
public double rate;
|
||||
public int percent;
|
||||
public boolean usePercent = false;
|
||||
public int duration;
|
||||
public boolean tempBasalRequested = false;
|
||||
public boolean bolusRequested = false;
|
||||
public IobTotal iob;
|
||||
public JSONObject json = new JSONObject();
|
||||
public boolean hasPredictions = false;
|
||||
public double smb = 0d; // super micro bolus in units
|
||||
public long deliverAt = 0;
|
||||
|
||||
public Constraint<Double> inputConstraints;
|
||||
|
||||
public Constraint<Double> rateConstraint;
|
||||
public Constraint<Integer> percentConstraint;
|
||||
public Constraint<Double> smbConstraint;
|
||||
|
||||
public APSResult rate(double rate) {
|
||||
this.rate = rate;
|
||||
return this;
|
||||
}
|
||||
|
||||
public APSResult duration(int duration) {
|
||||
this.duration = duration;
|
||||
return this;
|
||||
}
|
||||
|
||||
public APSResult percent(int percent) {
|
||||
this.percent = percent;
|
||||
return this;
|
||||
}
|
||||
|
||||
public APSResult tempBasalRequested(boolean tempBasalRequested) {
|
||||
this.tempBasalRequested = tempBasalRequested;
|
||||
return this;
|
||||
}
|
||||
|
||||
public APSResult usePercent(boolean usePercent) {
|
||||
this.usePercent = usePercent;
|
||||
return this;
|
||||
}
|
||||
|
||||
public APSResult json(JSONObject json) {
|
||||
this.json = json;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump();
|
||||
if (isChangeRequested()) {
|
||||
String ret;
|
||||
// rate
|
||||
if (rate == 0 && duration == 0)
|
||||
ret = MainApp.gs(R.string.canceltemp) + "\n";
|
||||
else if (rate == -1)
|
||||
ret = MainApp.gs(R.string.let_temp_basal_run) + "\n";
|
||||
else if (usePercent)
|
||||
ret = MainApp.gs(R.string.rate) + ": " + DecimalFormatter.to2Decimal(percent) + "% " +
|
||||
"(" + DecimalFormatter.to2Decimal(percent * pump.getBaseBasalRate() / 100d) + " U/h)\n" +
|
||||
MainApp.gs(R.string.duration) + ": " + DecimalFormatter.to2Decimal(duration) + " min\n";
|
||||
else
|
||||
ret = MainApp.gs(R.string.rate) + ": " + DecimalFormatter.to2Decimal(rate) + " U/h " +
|
||||
"(" + DecimalFormatter.to2Decimal(rate / pump.getBaseBasalRate() * 100) + "%) \n" +
|
||||
MainApp.gs(R.string.duration) + ": " + DecimalFormatter.to2Decimal(duration) + " min\n";
|
||||
|
||||
// smb
|
||||
if (smb != 0)
|
||||
ret += ("SMB: " + DecimalFormatter.toPumpSupportedBolus(smb) + " U\n");
|
||||
|
||||
// reason
|
||||
ret += MainApp.gs(R.string.reason) + ": " + reason;
|
||||
return ret;
|
||||
} else
|
||||
return MainApp.gs(R.string.nochangerequested);
|
||||
}
|
||||
|
||||
public Spanned toSpanned() {
|
||||
final PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump();
|
||||
if (isChangeRequested()) {
|
||||
String ret;
|
||||
// rate
|
||||
if (rate == 0 && duration == 0)
|
||||
ret = MainApp.gs(R.string.canceltemp) + "<br>";
|
||||
else if (rate == -1)
|
||||
ret = MainApp.gs(R.string.let_temp_basal_run) + "<br>";
|
||||
else if (usePercent)
|
||||
ret = "<b>" + MainApp.gs(R.string.rate) + "</b>: " + DecimalFormatter.to2Decimal(percent) + "% " +
|
||||
"(" + DecimalFormatter.to2Decimal(percent * pump.getBaseBasalRate() / 100d) + " U/h)<br>" +
|
||||
"<b>" + MainApp.gs(R.string.duration) + "</b>: " + DecimalFormatter.to2Decimal(duration) + " min<br>";
|
||||
else
|
||||
ret = "<b>" + MainApp.gs(R.string.rate) + "</b>: " + DecimalFormatter.to2Decimal(rate) + " U/h " +
|
||||
"(" + DecimalFormatter.to2Decimal(rate / pump.getBaseBasalRate() * 100d) + "%) <br>" +
|
||||
"<b>" + MainApp.gs(R.string.duration) + "</b>: " + DecimalFormatter.to2Decimal(duration) + " min<br>";
|
||||
|
||||
// smb
|
||||
if (smb != 0)
|
||||
ret += ("<b>" + "SMB" + "</b>: " + DecimalFormatter.toPumpSupportedBolus(smb) + " U<br>");
|
||||
|
||||
// reason
|
||||
ret += "<b>" + MainApp.gs(R.string.reason) + "</b>: " + reason.replace("<", "<").replace(">", ">");
|
||||
return Html.fromHtml(ret);
|
||||
} else
|
||||
return Html.fromHtml(MainApp.gs(R.string.nochangerequested));
|
||||
}
|
||||
|
||||
public APSResult() {
|
||||
}
|
||||
|
||||
public APSResult clone() {
|
||||
APSResult newResult = new APSResult();
|
||||
doClone(newResult);
|
||||
return newResult;
|
||||
}
|
||||
|
||||
protected void doClone(APSResult newResult) {
|
||||
newResult.date = date;
|
||||
newResult.reason = reason != null ? new String(reason) : null;
|
||||
newResult.rate = rate;
|
||||
newResult.duration = duration;
|
||||
newResult.tempBasalRequested = tempBasalRequested;
|
||||
newResult.bolusRequested = bolusRequested;
|
||||
newResult.iob = iob;
|
||||
try {
|
||||
newResult.json = new JSONObject(json.toString());
|
||||
} catch (JSONException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
newResult.hasPredictions = hasPredictions;
|
||||
newResult.smb = smb;
|
||||
newResult.deliverAt = deliverAt;
|
||||
newResult.rateConstraint = rateConstraint;
|
||||
newResult.smbConstraint = smbConstraint;
|
||||
newResult.percent = percent;
|
||||
newResult.usePercent = usePercent;
|
||||
}
|
||||
|
||||
|
||||
public JSONObject json() {
|
||||
JSONObject json = new JSONObject();
|
||||
try {
|
||||
if (isChangeRequested()) {
|
||||
json.put("rate", rate);
|
||||
json.put("duration", duration);
|
||||
json.put("reason", reason);
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
public List<BgReading> getPredictions() {
|
||||
List<BgReading> array = new ArrayList<>();
|
||||
try {
|
||||
long startTime = date;
|
||||
if (json != null && json.has("predBGs")) {
|
||||
JSONObject predBGs = json.getJSONObject("predBGs");
|
||||
if (predBGs.has("IOB")) {
|
||||
JSONArray iob = predBGs.getJSONArray("IOB");
|
||||
for (int i = 1; i < iob.length(); i++) {
|
||||
BgReading bg = new BgReading();
|
||||
bg.value = iob.getInt(i);
|
||||
bg.date = startTime + i * 5 * 60 * 1000L;
|
||||
bg.isIOBPrediction = true;
|
||||
array.add(bg);
|
||||
}
|
||||
}
|
||||
if (predBGs.has("aCOB")) {
|
||||
JSONArray iob = predBGs.getJSONArray("aCOB");
|
||||
for (int i = 1; i < iob.length(); i++) {
|
||||
BgReading bg = new BgReading();
|
||||
bg.value = iob.getInt(i);
|
||||
bg.date = startTime + i * 5 * 60 * 1000L;
|
||||
bg.isaCOBPrediction = true;
|
||||
array.add(bg);
|
||||
}
|
||||
}
|
||||
if (predBGs.has("COB")) {
|
||||
JSONArray iob = predBGs.getJSONArray("COB");
|
||||
for (int i = 1; i < iob.length(); i++) {
|
||||
BgReading bg = new BgReading();
|
||||
bg.value = iob.getInt(i);
|
||||
bg.date = startTime + i * 5 * 60 * 1000L;
|
||||
bg.isCOBPrediction = true;
|
||||
array.add(bg);
|
||||
}
|
||||
}
|
||||
if (predBGs.has("UAM")) {
|
||||
JSONArray iob = predBGs.getJSONArray("UAM");
|
||||
for (int i = 1; i < iob.length(); i++) {
|
||||
BgReading bg = new BgReading();
|
||||
bg.value = iob.getInt(i);
|
||||
bg.date = startTime + i * 5 * 60 * 1000L;
|
||||
bg.isUAMPrediction = true;
|
||||
array.add(bg);
|
||||
}
|
||||
}
|
||||
if (predBGs.has("ZT")) {
|
||||
JSONArray iob = predBGs.getJSONArray("ZT");
|
||||
for (int i = 1; i < iob.length(); i++) {
|
||||
BgReading bg = new BgReading();
|
||||
bg.value = iob.getInt(i);
|
||||
bg.date = startTime + i * 5 * 60 * 1000L;
|
||||
bg.isZTPrediction = true;
|
||||
array.add(bg);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
public long getLatestPredictionsTime() {
|
||||
long latest = 0;
|
||||
try {
|
||||
long startTime = date;
|
||||
if (json != null && json.has("predBGs")) {
|
||||
JSONObject predBGs = json.getJSONObject("predBGs");
|
||||
if (predBGs.has("IOB")) {
|
||||
JSONArray iob = predBGs.getJSONArray("IOB");
|
||||
latest = Math.max(latest, startTime + (iob.length() - 1) * 5 * 60 * 1000L);
|
||||
}
|
||||
if (predBGs.has("aCOB")) {
|
||||
JSONArray iob = predBGs.getJSONArray("aCOB");
|
||||
latest = Math.max(latest, startTime + (iob.length() - 1) * 5 * 60 * 1000L);
|
||||
}
|
||||
if (predBGs.has("COB")) {
|
||||
JSONArray iob = predBGs.getJSONArray("COB");
|
||||
latest = Math.max(latest, startTime + (iob.length() - 1) * 5 * 60 * 1000L);
|
||||
}
|
||||
if (predBGs.has("UAM")) {
|
||||
JSONArray iob = predBGs.getJSONArray("UAM");
|
||||
latest = Math.max(latest, startTime + (iob.length() - 1) * 5 * 60 * 1000L);
|
||||
}
|
||||
if (predBGs.has("ZT")) {
|
||||
JSONArray iob = predBGs.getJSONArray("ZT");
|
||||
latest = Math.max(latest, startTime + (iob.length() - 1) * 5 * 60 * 1000L);
|
||||
}
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
|
||||
return latest;
|
||||
}
|
||||
|
||||
public boolean isChangeRequested() {
|
||||
Constraint<Boolean> closedLoopEnabled = MainApp.getConstraintChecker().isClosedLoopAllowed();
|
||||
// closed loop mode: handle change at driver level
|
||||
if (closedLoopEnabled.value()) {
|
||||
if (L.isEnabled(L.APS))
|
||||
log.debug("DEFAULT: Closed mode");
|
||||
return tempBasalRequested || bolusRequested;
|
||||
}
|
||||
|
||||
// open loop mode: try to limit request
|
||||
if (!tempBasalRequested && !bolusRequested) {
|
||||
if (L.isEnabled(L.APS))
|
||||
log.debug("FALSE: No request");
|
||||
return false;
|
||||
}
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
TemporaryBasal activeTemp = TreatmentsPlugin.getPlugin().getTempBasalFromHistory(now);
|
||||
PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump();
|
||||
Profile profile = ProfileFunctions.getInstance().getProfile();
|
||||
|
||||
if (profile == null) {
|
||||
log.error("FALSE: No Profile");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (usePercent) {
|
||||
if (activeTemp == null && percent == 100) {
|
||||
if (L.isEnabled(L.APS))
|
||||
log.debug("FALSE: No temp running, asking cancel temp");
|
||||
return false;
|
||||
}
|
||||
if (activeTemp != null && Math.abs(percent - activeTemp.tempBasalConvertedToPercent(now, profile)) < pump.getPumpDescription().basalStep) {
|
||||
if (L.isEnabled(L.APS))
|
||||
log.debug("FALSE: Temp equal");
|
||||
return false;
|
||||
}
|
||||
// always report zerotemp
|
||||
if (percent == 0) {
|
||||
if (L.isEnabled(L.APS))
|
||||
log.debug("TRUE: Zero temp");
|
||||
return true;
|
||||
}
|
||||
// always report hightemp
|
||||
if (pump != null && pump.getPumpDescription().tempBasalStyle == PumpDescription.PERCENT) {
|
||||
double pumpLimit = pump.getPumpDescription().pumpType.getTbrSettings().getMaxDose();
|
||||
if (percent == pumpLimit) {
|
||||
if (L.isEnabled(L.APS))
|
||||
log.debug("TRUE: Pump limit");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// report change bigger than 30%
|
||||
double percentMinChangeChange = SP.getDouble(R.string.key_loop_openmode_min_change, 30d);
|
||||
percentMinChangeChange /= 100d;
|
||||
double lowThreshold = 1 - percentMinChangeChange;
|
||||
double highThreshold = 1 + percentMinChangeChange;
|
||||
double change = percent / 100d;
|
||||
if (activeTemp != null)
|
||||
change = percent / (double) activeTemp.tempBasalConvertedToPercent(now, profile);
|
||||
|
||||
if (change < lowThreshold || change > highThreshold) {
|
||||
if (L.isEnabled(L.APS))
|
||||
log.debug("TRUE: Outside allowed range " + (change * 100d) + "%");
|
||||
return true;
|
||||
} else {
|
||||
if (L.isEnabled(L.APS))
|
||||
log.debug("TRUE: Inside allowed range " + (change * 100d) + "%");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (activeTemp == null && rate == pump.getBaseBasalRate()) {
|
||||
if (L.isEnabled(L.APS))
|
||||
log.debug("FALSE: No temp running, asking cancel temp");
|
||||
return false;
|
||||
}
|
||||
if (activeTemp != null && Math.abs(rate - activeTemp.tempBasalConvertedToAbsolute(now, profile)) < pump.getPumpDescription().basalStep) {
|
||||
if (L.isEnabled(L.APS))
|
||||
log.debug("FALSE: Temp equal");
|
||||
return false;
|
||||
}
|
||||
// always report zerotemp
|
||||
if (rate == 0) {
|
||||
if (L.isEnabled(L.APS))
|
||||
log.debug("TRUE: Zero temp");
|
||||
return true;
|
||||
}
|
||||
// always report hightemp
|
||||
if (pump != null && pump.getPumpDescription().tempBasalStyle == PumpDescription.ABSOLUTE) {
|
||||
double pumpLimit = pump.getPumpDescription().pumpType.getTbrSettings().getMaxDose();
|
||||
if (rate == pumpLimit) {
|
||||
if (L.isEnabled(L.APS))
|
||||
log.debug("TRUE: Pump limit");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// report change bigger than 30%
|
||||
double percentMinChangeChange = SP.getDouble(R.string.key_loop_openmode_min_change, 30d);
|
||||
percentMinChangeChange /= 100d;
|
||||
double lowThreshold = 1 - percentMinChangeChange;
|
||||
double highThreshold = 1 + percentMinChangeChange;
|
||||
double change = rate / profile.getBasal();
|
||||
if (activeTemp != null)
|
||||
change = rate / activeTemp.tempBasalConvertedToAbsolute(now, profile);
|
||||
|
||||
if (change < lowThreshold || change > highThreshold) {
|
||||
if (L.isEnabled(L.APS))
|
||||
log.debug("TRUE: Outside allowed range " + (change * 100d) + "%");
|
||||
return true;
|
||||
} else {
|
||||
if (L.isEnabled(L.APS))
|
||||
log.debug("TRUE: Inside allowed range " + (change * 100d) + "%");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue