Merge branch 'dev' into signature_verifier
This commit is contained in:
commit
b448bbe670
|
@ -2,19 +2,19 @@ language: android
|
||||||
jdk: oraclejdk8
|
jdk: oraclejdk8
|
||||||
env:
|
env:
|
||||||
matrix:
|
matrix:
|
||||||
- ANDROID_TARGET=android-23 ANDROID_ABI=x86 org.gradle.jvmargs=-XX:-OmitStackTraceInFastThrow
|
- ANDROID_TARGET=android-28 ANDROID_ABI=x86 org.gradle.jvmargs=-XX:-OmitStackTraceInFastThrow
|
||||||
android:
|
android:
|
||||||
components:
|
components:
|
||||||
- platform-tools
|
- platform-tools
|
||||||
- tools
|
- tools
|
||||||
- build-tools-27.0.2
|
- build-tools-28.0.3
|
||||||
- android-23
|
- android-28
|
||||||
- extra-google-m2repository
|
- extra-google-m2repository
|
||||||
- extra-android-m2repository
|
- extra-android-m2repository
|
||||||
- extra-google-google_play_services
|
- extra-google-google_play_services
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
- yes | sdkmanager "platforms;android-27"
|
#- yes | sdkmanager "platforms;android-28"
|
||||||
|
|
||||||
script:
|
script:
|
||||||
# Unit Test
|
# Unit Test
|
||||||
|
|
121
app/build.gradle
121
app/build.gradle
|
@ -6,23 +6,30 @@ buildscript {
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'io.fabric.tools:gradle:1.+'
|
classpath 'io.fabric.tools:gradle:1.+'
|
||||||
classpath 'com.dicedmelon.gradle:jacoco-android:0.1.3'
|
classpath 'com.dicedmelon.gradle:jacoco-android:0.1.4'
|
||||||
|
classpath 'de.undercouch:gradle-download-task:3.4.3'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
apply plugin: "com.android.application"
|
apply plugin: 'com.android.application'
|
||||||
apply plugin: 'kotlin-android-extensions'
|
|
||||||
apply plugin: 'kotlin-android'
|
apply plugin: 'kotlin-android'
|
||||||
|
apply plugin: 'kotlin-android-extensions'
|
||||||
apply plugin: 'com.google.gms.google-services'
|
apply plugin: 'com.google.gms.google-services'
|
||||||
apply plugin: "io.fabric"
|
apply plugin: 'io.fabric'
|
||||||
apply plugin: "jacoco-android"
|
apply plugin: 'jacoco-android'
|
||||||
apply plugin: 'com.jakewharton.butterknife'
|
apply plugin: 'com.jakewharton.butterknife'
|
||||||
|
apply plugin: 'de.undercouch.download'
|
||||||
|
|
||||||
|
|
||||||
|
jacoco {
|
||||||
|
toolVersion = "0.8.3"
|
||||||
|
}
|
||||||
|
|
||||||
ext {
|
ext {
|
||||||
supportLibraryVersion = "27.1.1"
|
supportLibraryVersion = "28.0.0"
|
||||||
ormLiteVersion = "4.46"
|
ormLiteVersion = "4.46"
|
||||||
powermockVersion = "1.7.3"
|
powermockVersion = "1.7.3"
|
||||||
dexmakerVersion = "1.2"
|
dexmakerVersion = "1.2"
|
||||||
butterknifeVersion = "8.8.1"
|
butterknifeVersion = "10.1.0"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -79,7 +86,7 @@ def allCommited = { ->
|
||||||
try {
|
try {
|
||||||
def stdout = new ByteArrayOutputStream()
|
def stdout = new ByteArrayOutputStream()
|
||||||
exec {
|
exec {
|
||||||
commandLine 'git', 'status'
|
commandLine 'git', 'status', '-s'
|
||||||
standardOutput = stdout
|
standardOutput = stdout
|
||||||
}
|
}
|
||||||
String commitObject = stdout.toString().trim()
|
String commitObject = stdout.toString().trim()
|
||||||
|
@ -87,7 +94,8 @@ def allCommited = { ->
|
||||||
} catch (ignored) {
|
} catch (ignored) {
|
||||||
return false; // NoGitSystemAvailable
|
return false; // NoGitSystemAvailable
|
||||||
}
|
}
|
||||||
return stringBuilder.toString().contains("nothing to commit")
|
return stringBuilder.toString().isEmpty()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.matching { it instanceof Test }.all {
|
tasks.matching { it instanceof Test }.all {
|
||||||
|
@ -96,19 +104,19 @@ tasks.matching { it instanceof Test }.all {
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 27
|
compileSdkVersion 28
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdkVersion 21
|
minSdkVersion 23
|
||||||
targetSdkVersion 25
|
targetSdkVersion 28
|
||||||
multiDexEnabled true
|
multiDexEnabled true
|
||||||
versionCode 1500
|
versionCode 1500
|
||||||
version "2.3.1-dev"
|
version "2.4-dev"
|
||||||
buildConfigField "String", "VERSION", '"' + version + '"'
|
buildConfigField "String", "VERSION", '"' + version + '"'
|
||||||
buildConfigField "String", "BUILDVERSION", '"' + generateGitBuild() + '-' + generateDate() + '"'
|
buildConfigField "String", "BUILDVERSION", '"' + generateGitBuild() + '-' + generateDate() + '"'
|
||||||
buildConfigField "String", "REMOTE", '"' + generateGitRemote() + '"'
|
buildConfigField "String", "REMOTE", '"' + generateGitRemote() + '"'
|
||||||
buildConfigField "String", "HEAD", '"' + generateGitBuild() + '"'
|
buildConfigField "String", "HEAD", '"' + generateGitBuild() + '"'
|
||||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
// if you change minSdkVersion to less than 11, you need to change executeTask for wear
|
// if you change minSdkVersion to less than 11, you need to change executeTask for wear
|
||||||
|
|
||||||
ndk {
|
ndk {
|
||||||
|
@ -187,8 +195,15 @@ android {
|
||||||
}
|
}
|
||||||
|
|
||||||
testOptions {
|
testOptions {
|
||||||
unitTests.returnDefaultValues = true
|
unitTests {
|
||||||
unitTests.includeAndroidResources = true
|
returnDefaultValues = true
|
||||||
|
includeAndroidResources = true
|
||||||
|
|
||||||
|
all {
|
||||||
|
maxParallelForks = 10
|
||||||
|
forkEvery = 20
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
useLibrary "org.apache.http.legacy"
|
useLibrary "org.apache.http.legacy"
|
||||||
|
@ -200,34 +215,34 @@ allprojects {
|
||||||
flatDir {
|
flatDir {
|
||||||
dirs 'libs'
|
dirs 'libs'
|
||||||
}
|
}
|
||||||
|
maven { url 'https://jitpack.io' }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
configurations {
|
|
||||||
libs
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
wearApp project(':wear')
|
wearApp project(':wear')
|
||||||
|
|
||||||
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||||
implementation 'com.google.android.gms:play-services-wearable:16.0.1'
|
implementation 'com.google.android.gms:play-services-wearable:17.0.0'
|
||||||
implementation 'com.google.firebase:firebase-core:16.0.8'
|
implementation 'com.google.firebase:firebase-core:17.0.1'
|
||||||
implementation("com.crashlytics.sdk.android:crashlytics:2.9.9@aar") {
|
implementation("com.crashlytics.sdk.android:crashlytics:2.9.9@aar") {
|
||||||
transitive = true;
|
transitive = true;
|
||||||
}
|
}
|
||||||
libs "MilosKozak:danars-support-lib:master@zip"
|
|
||||||
|
|
||||||
implementation "com.android.support:appcompat-v7:${supportLibraryVersion}"
|
implementation 'androidx.appcompat:appcompat:1.0.2'
|
||||||
implementation "com.android.support:support-v13:${supportLibraryVersion}"
|
implementation 'androidx.legacy:legacy-support-v13:1.0.0'
|
||||||
implementation "com.android.support:support-v4:${supportLibraryVersion}"
|
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
||||||
implementation "com.android.support:cardview-v7:${supportLibraryVersion}"
|
implementation 'androidx.cardview:cardview:1.0.0'
|
||||||
implementation "com.android.support:recyclerview-v7:${supportLibraryVersion}"
|
implementation 'androidx.recyclerview:recyclerview:1.0.0'
|
||||||
implementation "com.android.support:gridlayout-v7:${supportLibraryVersion}"
|
implementation 'androidx.gridlayout:gridlayout:1.0.0'
|
||||||
implementation "com.android.support:design:${supportLibraryVersion}"
|
implementation 'com.google.android.material:material:1.0.0'
|
||||||
implementation "com.android.support:percent:${supportLibraryVersion}"
|
implementation 'androidx.percentlayout:percentlayout:1.0.0'
|
||||||
implementation "com.wdullaer:materialdatetimepicker:2.3.0"
|
implementation "com.wdullaer:materialdatetimepicker:2.3.0"
|
||||||
|
|
||||||
|
// Otto bus will be replaced by rx
|
||||||
implementation "com.squareup:otto:1.3.7"
|
implementation "com.squareup:otto:1.3.7"
|
||||||
|
implementation "io.reactivex.rxjava2:rxandroid:2.1.1"
|
||||||
|
|
||||||
implementation "com.j256.ormlite:ormlite-core:${ormLiteVersion}"
|
implementation "com.j256.ormlite:ormlite-core:${ormLiteVersion}"
|
||||||
implementation "com.j256.ormlite:ormlite-android:${ormLiteVersion}"
|
implementation "com.j256.ormlite:ormlite-android:${ormLiteVersion}"
|
||||||
implementation("com.github.tony19:logback-android-classic:1.1.1-6") {
|
implementation("com.github.tony19:logback-android-classic:1.1.1-6") {
|
||||||
|
@ -238,7 +253,7 @@ dependencies {
|
||||||
// Graphview cannot be upgraded
|
// Graphview cannot be upgraded
|
||||||
implementation "com.jjoe64:graphview:4.0.1"
|
implementation "com.jjoe64:graphview:4.0.1"
|
||||||
implementation "com.joanzapata.iconify:android-iconify-fontawesome:2.1.1"
|
implementation "com.joanzapata.iconify:android-iconify-fontawesome:2.1.1"
|
||||||
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
|
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
||||||
implementation(name: "android-edittext-validator-v1.3.4-mod", ext: "aar")
|
implementation(name: "android-edittext-validator-v1.3.4-mod", ext: "aar")
|
||||||
implementation 'com.madgag.spongycastle:core:1.58.0.0'
|
implementation 'com.madgag.spongycastle:core:1.58.0.0'
|
||||||
|
|
||||||
|
@ -249,7 +264,7 @@ dependencies {
|
||||||
// excluding org.json which is provided by Android
|
// excluding org.json which is provided by Android
|
||||||
exclude group: "org.json", module: "json"
|
exclude group: "org.json", module: "json"
|
||||||
}
|
}
|
||||||
implementation "com.google.code.gson:gson:2.8.2"
|
implementation "com.google.code.gson:gson:2.8.5"
|
||||||
implementation "com.google.guava:guava:24.1-jre"
|
implementation "com.google.guava:guava:24.1-jre"
|
||||||
|
|
||||||
implementation "net.danlew:android.joda:2.9.9.1"
|
implementation "net.danlew:android.joda:2.9.9.1"
|
||||||
|
@ -260,6 +275,8 @@ dependencies {
|
||||||
implementation "com.jakewharton:butterknife:${butterknifeVersion}"
|
implementation "com.jakewharton:butterknife:${butterknifeVersion}"
|
||||||
annotationProcessor "com.jakewharton:butterknife-compiler:${butterknifeVersion}"
|
annotationProcessor "com.jakewharton:butterknife-compiler:${butterknifeVersion}"
|
||||||
|
|
||||||
|
implementation 'com.github.DavidProdinger:weekdays-selector:1.0.4'
|
||||||
|
|
||||||
testImplementation "junit:junit:4.12"
|
testImplementation "junit:junit:4.12"
|
||||||
testImplementation "org.json:json:20140107"
|
testImplementation "org.json:json:20140107"
|
||||||
testImplementation "org.mockito:mockito-core:2.8.47"
|
testImplementation "org.mockito:mockito-core:2.8.47"
|
||||||
|
@ -268,26 +285,48 @@ dependencies {
|
||||||
testImplementation "org.powermock:powermock-module-junit4-rule:${powermockVersion}"
|
testImplementation "org.powermock:powermock-module-junit4-rule:${powermockVersion}"
|
||||||
testImplementation "org.powermock:powermock-module-junit4:${powermockVersion}"
|
testImplementation "org.powermock:powermock-module-junit4:${powermockVersion}"
|
||||||
testImplementation "joda-time:joda-time:2.9.9"
|
testImplementation "joda-time:joda-time:2.9.9"
|
||||||
testImplementation "com.google.truth:truth:0.39"
|
testImplementation("com.google.truth:truth:0.39") {
|
||||||
testImplementation 'org.robolectric:robolectric:3.8'
|
exclude group: "com.google.guava", module: "guava"
|
||||||
|
}
|
||||||
|
testImplementation("org.robolectric:robolectric:4.2.1") {
|
||||||
|
exclude group: "com.google.guava", module: "guava"
|
||||||
|
}
|
||||||
testImplementation "org.skyscreamer:jsonassert:1.5.0"
|
testImplementation "org.skyscreamer:jsonassert:1.5.0"
|
||||||
|
testImplementation "org.hamcrest:hamcrest-all:1.3"
|
||||||
|
testImplementation("uk.org.lidalia:slf4j-test:1.2.0") {
|
||||||
|
exclude group: "com.google.guava", module: "guava"
|
||||||
|
}
|
||||||
|
|
||||||
androidTestImplementation "org.mockito:mockito-core:2.8.47"
|
androidTestImplementation "org.mockito:mockito-core:2.8.47"
|
||||||
androidTestImplementation "com.google.dexmaker:dexmaker:${dexmakerVersion}"
|
androidTestImplementation "com.google.dexmaker:dexmaker:${dexmakerVersion}"
|
||||||
androidTestImplementation "com.google.dexmaker:dexmaker-mockito:${dexmakerVersion}"
|
androidTestImplementation "com.google.dexmaker:dexmaker-mockito:${dexmakerVersion}"
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||||
|
implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
|
||||||
|
|
||||||
|
|
||||||
|
// new for tidepool
|
||||||
|
implementation 'com.squareup.okhttp3:okhttp:3.10.0'
|
||||||
|
implementation 'com.squareup.okhttp3:logging-interceptor:3.10.0'
|
||||||
|
implementation "com.squareup.retrofit2:retrofit:2.4.0"
|
||||||
|
implementation "com.squareup.retrofit2:adapter-rxjava2:2.4.0"
|
||||||
|
implementation "com.squareup.retrofit2:converter-gson:2.4.0"
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
task unzip(type: Copy) {
|
|
||||||
def zipPath = configurations.libs.find { it.name.startsWith("danars") }
|
|
||||||
def zipFile = file(zipPath)
|
|
||||||
def outputDir = file("${buildDir}/unpacked/dist")
|
|
||||||
|
|
||||||
from zipTree(zipFile)
|
task downloadZipFile(type: Download) {
|
||||||
|
src 'https://github.com/MilosKozak/danars-support-lib/archive/master.zip'
|
||||||
|
dest new File(buildDir, 'danars.zip')
|
||||||
|
}
|
||||||
|
|
||||||
|
task downloadAndUnzipFile(dependsOn: downloadZipFile, type: Copy) {
|
||||||
|
from zipTree(downloadZipFile.dest)
|
||||||
|
def outputDir = file("${buildDir}/unpacked/dist")
|
||||||
into outputDir
|
into outputDir
|
||||||
}
|
}
|
||||||
|
|
||||||
task copyLibs(dependsOn: unzip, type: Copy) {
|
|
||||||
|
task copyLibs(dependsOn: downloadAndUnzipFile, type: Copy) {
|
||||||
def src = file("${buildDir}/unpacked/dist/danars-support-lib-master")
|
def src = file("${buildDir}/unpacked/dist/danars-support-lib-master")
|
||||||
def target = file("src/main/jniLibs/")
|
def target = file("src/main/jniLibs/")
|
||||||
|
|
||||||
|
|
|
@ -17,10 +17,12 @@
|
||||||
<uses-permission android:name="android.permission.VIBRATE" />
|
<uses-permission android:name="android.permission.VIBRATE" />
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="com.google.android.permission.PROVIDE_BACKGROUND" />
|
<uses-permission android:name="com.google.android.permission.PROVIDE_BACKGROUND" />
|
||||||
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||||
<uses-permission android:name="sugar.free.sightremote.HISTORY_BROADCASTS" />
|
<uses-permission android:name="com.dexcom.cgm.EXTERNAL_PERMISSION" />
|
||||||
|
|
||||||
<uses-permission-sdk-23 android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
|
<uses-permission-sdk-23 android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
|
||||||
|
|
||||||
|
@ -34,13 +36,15 @@
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:roundIcon="${appIconRound}"
|
android:roundIcon="${appIconRound}"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/AppTheme.NoActionBar">
|
android:theme="@style/AppTheme.NoActionBar"
|
||||||
|
android:fullBackupContent="true">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="com.google.android.gms.car.application"
|
android:name="com.google.android.gms.car.application"
|
||||||
android:resource="@xml/automotive_app_desc" />
|
android:resource="@xml/automotive_app_desc" />
|
||||||
|
|
||||||
<activity android:name=".MainActivity">
|
<activity android:name=".MainActivity">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.VIEW" />
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
@ -85,10 +89,8 @@
|
||||||
<action android:name="com.eveningoutpost.dexdrip.NS_EMULATOR"/>
|
<action android:name="com.eveningoutpost.dexdrip.NS_EMULATOR"/>
|
||||||
<!-- Receiver from glimp -->
|
<!-- Receiver from glimp -->
|
||||||
<action android:name="it.ct.glicemia.ACTION_GLUCOSE_MEASURED"/>
|
<action android:name="it.ct.glicemia.ACTION_GLUCOSE_MEASURED"/>
|
||||||
<!-- Receiver from DexcomG5 -->
|
<!-- Receiver from Dexcom -->
|
||||||
<action android:name="com.dexcom.cgm.DATA"/>
|
<action android:name="com.dexcom.cgm.EXTERNAL_BROADCAST"/>
|
||||||
<action android:name="com.dexcom.cgm.AndroidAPSEVGCallback.BROADCAST"/>
|
|
||||||
<action android:name="com.dexcom.cgm.g5.AndroidAPSEVGCallback.BROADCAST"/>
|
|
||||||
<!-- Receiver from Poctech -->
|
<!-- Receiver from Poctech -->
|
||||||
<action android:name="com.china.poctech.data"/>
|
<action android:name="com.china.poctech.data"/>
|
||||||
<!-- Receiver from Tomato -->
|
<!-- Receiver from Tomato -->
|
||||||
|
@ -147,7 +149,7 @@
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
<provider
|
<provider
|
||||||
android:name="android.support.v4.content.FileProvider"
|
android:name="androidx.core.content.FileProvider"
|
||||||
android:authorities="${applicationId}.fileprovider"
|
android:authorities="${applicationId}.fileprovider"
|
||||||
android:exported="false"
|
android:exported="false"
|
||||||
android:grantUriPermissions="true">
|
android:grantUriPermissions="true">
|
||||||
|
@ -160,6 +162,9 @@
|
||||||
<service
|
<service
|
||||||
android:name=".services.DataService"
|
android:name=".services.DataService"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
|
<service
|
||||||
|
android:name=".services.LocationService"
|
||||||
|
android:exported="false" />
|
||||||
<service
|
<service
|
||||||
android:name=".plugins.pump.danaR.services.DanaRExecutionService"
|
android:name=".plugins.pump.danaR.services.DanaRExecutionService"
|
||||||
android:enabled="true"
|
android:enabled="true"
|
||||||
|
@ -281,6 +286,27 @@
|
||||||
android:name=".plugins.pump.insight.activities.InsightPairingInformationActivity"
|
android:name=".plugins.pump.insight.activities.InsightPairingInformationActivity"
|
||||||
android:label="@string/pairing_information"
|
android:label="@string/pairing_information"
|
||||||
android:theme="@style/AppTheme" />
|
android:theme="@style/AppTheme" />
|
||||||
|
<activity android:name=".activities.RequestDexcomPermissionActivity" />
|
||||||
|
|
||||||
|
<!-- 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">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="info.nightscout.androidaps.plugins.PumpCommon.dialog.RileyLinkBLEScanActivity" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
</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"/>
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|
|
@ -31,7 +31,7 @@ public class Constants {
|
||||||
public static final long remoteBolusMinDistance = 15 * 60 * 1000L;
|
public static final long remoteBolusMinDistance = 15 * 60 * 1000L;
|
||||||
|
|
||||||
// Circadian Percentage Profile
|
// Circadian Percentage Profile
|
||||||
public static final int CPP_MIN_PERCENTAGE = 50;
|
public static final int CPP_MIN_PERCENTAGE = 30;
|
||||||
public static final int CPP_MAX_PERCENTAGE = 200;
|
public static final int CPP_MAX_PERCENTAGE = 200;
|
||||||
public static final int CPP_MIN_TIMESHIFT = -6;
|
public static final int CPP_MIN_TIMESHIFT = -6;
|
||||||
public static final int CPP_MAX_TIMESHIFT = 23;
|
public static final int CPP_MAX_TIMESHIFT = 23;
|
||||||
|
|
|
@ -7,16 +7,16 @@ import android.graphics.Rect;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.PersistableBundle;
|
import android.os.PersistableBundle;
|
||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
import android.support.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import android.support.design.widget.NavigationView;
|
import com.google.android.material.navigation.NavigationView;
|
||||||
import android.support.design.widget.TabLayout;
|
import com.google.android.material.tabs.TabLayout;
|
||||||
import android.support.v4.app.ActivityCompat;
|
import androidx.core.app.ActivityCompat;
|
||||||
import android.support.v4.view.ViewPager;
|
import androidx.viewpager.widget.ViewPager;
|
||||||
import android.support.v4.widget.DrawerLayout;
|
import androidx.drawerlayout.widget.DrawerLayout;
|
||||||
import android.support.v7.app.ActionBarDrawerToggle;
|
import androidx.appcompat.app.ActionBarDrawerToggle;
|
||||||
import android.support.v7.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
import android.support.v7.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
import android.support.v7.widget.Toolbar;
|
import androidx.appcompat.widget.Toolbar;
|
||||||
import android.text.SpannableString;
|
import android.text.SpannableString;
|
||||||
import android.text.method.LinkMovementMethod;
|
import android.text.method.LinkMovementMethod;
|
||||||
import android.text.util.Linkify;
|
import android.text.util.Linkify;
|
||||||
|
|
|
@ -1,12 +1,18 @@
|
||||||
package info.nightscout.androidaps;
|
package info.nightscout.androidaps;
|
||||||
|
|
||||||
import android.app.Application;
|
import android.app.Application;
|
||||||
|
import android.bluetooth.BluetoothAdapter;
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
import android.support.annotation.Nullable;
|
import android.util.Log;
|
||||||
import android.support.annotation.PluralsRes;
|
|
||||||
import android.support.v4.content.LocalBroadcastManager;
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.annotation.PluralsRes;
|
||||||
|
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||||
|
|
||||||
import com.crashlytics.android.Crashlytics;
|
import com.crashlytics.android.Crashlytics;
|
||||||
import com.google.firebase.analytics.FirebaseAnalytics;
|
import com.google.firebase.analytics.FirebaseAnalytics;
|
||||||
|
@ -39,6 +45,7 @@ import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugi
|
||||||
import info.nightscout.androidaps.plugins.constraints.safety.SafetyPlugin;
|
import info.nightscout.androidaps.plugins.constraints.safety.SafetyPlugin;
|
||||||
import info.nightscout.androidaps.plugins.constraints.storage.StorageConstraintPlugin;
|
import info.nightscout.androidaps.plugins.constraints.storage.StorageConstraintPlugin;
|
||||||
import info.nightscout.androidaps.plugins.general.actions.ActionsFragment;
|
import info.nightscout.androidaps.plugins.general.actions.ActionsFragment;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.AutomationPlugin;
|
||||||
import info.nightscout.androidaps.plugins.general.careportal.CareportalPlugin;
|
import info.nightscout.androidaps.plugins.general.careportal.CareportalPlugin;
|
||||||
import info.nightscout.androidaps.plugins.general.food.FoodPlugin;
|
import info.nightscout.androidaps.plugins.general.food.FoodPlugin;
|
||||||
import info.nightscout.androidaps.plugins.general.maintenance.LoggerUtils;
|
import info.nightscout.androidaps.plugins.general.maintenance.LoggerUtils;
|
||||||
|
@ -51,6 +58,7 @@ import info.nightscout.androidaps.plugins.general.overview.OverviewPlugin;
|
||||||
import info.nightscout.androidaps.plugins.general.persistentNotification.PersistentNotificationPlugin;
|
import info.nightscout.androidaps.plugins.general.persistentNotification.PersistentNotificationPlugin;
|
||||||
import info.nightscout.androidaps.plugins.general.signatureVerifier.SignatureVerifier;
|
import info.nightscout.androidaps.plugins.general.signatureVerifier.SignatureVerifier;
|
||||||
import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin;
|
import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin;
|
||||||
|
import info.nightscout.androidaps.plugins.general.tidepool.TidepoolPlugin;
|
||||||
import info.nightscout.androidaps.plugins.general.versionChecker.VersionCheckerPlugin;
|
import info.nightscout.androidaps.plugins.general.versionChecker.VersionCheckerPlugin;
|
||||||
import info.nightscout.androidaps.plugins.general.wear.WearPlugin;
|
import info.nightscout.androidaps.plugins.general.wear.WearPlugin;
|
||||||
import info.nightscout.androidaps.plugins.general.xdripStatusline.StatuslinePlugin;
|
import info.nightscout.androidaps.plugins.general.xdripStatusline.StatuslinePlugin;
|
||||||
|
@ -62,19 +70,21 @@ import info.nightscout.androidaps.plugins.profile.local.LocalProfilePlugin;
|
||||||
import info.nightscout.androidaps.plugins.profile.ns.NSProfilePlugin;
|
import info.nightscout.androidaps.plugins.profile.ns.NSProfilePlugin;
|
||||||
import info.nightscout.androidaps.plugins.profile.simple.SimpleProfilePlugin;
|
import info.nightscout.androidaps.plugins.profile.simple.SimpleProfilePlugin;
|
||||||
import info.nightscout.androidaps.plugins.pump.combo.ComboPlugin;
|
import info.nightscout.androidaps.plugins.pump.combo.ComboPlugin;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkConst;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil;
|
||||||
import info.nightscout.androidaps.plugins.pump.danaR.DanaRPlugin;
|
import info.nightscout.androidaps.plugins.pump.danaR.DanaRPlugin;
|
||||||
import info.nightscout.androidaps.plugins.pump.danaRKorean.DanaRKoreanPlugin;
|
import info.nightscout.androidaps.plugins.pump.danaRKorean.DanaRKoreanPlugin;
|
||||||
import info.nightscout.androidaps.plugins.pump.danaRS.DanaRSPlugin;
|
import info.nightscout.androidaps.plugins.pump.danaRS.DanaRSPlugin;
|
||||||
import info.nightscout.androidaps.plugins.pump.danaRv2.DanaRv2Plugin;
|
import info.nightscout.androidaps.plugins.pump.danaRv2.DanaRv2Plugin;
|
||||||
import info.nightscout.androidaps.plugins.pump.insight.LocalInsightPlugin;
|
import info.nightscout.androidaps.plugins.pump.insight.LocalInsightPlugin;
|
||||||
import info.nightscout.androidaps.plugins.pump.mdi.MDIPlugin;
|
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.pump.virtual.VirtualPumpPlugin;
|
||||||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityAAPSPlugin;
|
import info.nightscout.androidaps.plugins.sensitivity.SensitivityAAPSPlugin;
|
||||||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref0Plugin;
|
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref0Plugin;
|
||||||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin;
|
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin;
|
||||||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAveragePlugin;
|
import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAveragePlugin;
|
||||||
import info.nightscout.androidaps.plugins.source.SourceDexcomG5Plugin;
|
import info.nightscout.androidaps.plugins.source.SourceDexcomPlugin;
|
||||||
import info.nightscout.androidaps.plugins.source.SourceDexcomG6Plugin;
|
|
||||||
import info.nightscout.androidaps.plugins.source.SourceEversensePlugin;
|
import info.nightscout.androidaps.plugins.source.SourceEversensePlugin;
|
||||||
import info.nightscout.androidaps.plugins.source.SourceGlimpPlugin;
|
import info.nightscout.androidaps.plugins.source.SourceGlimpPlugin;
|
||||||
import info.nightscout.androidaps.plugins.source.SourceMM640gPlugin;
|
import info.nightscout.androidaps.plugins.source.SourceMM640gPlugin;
|
||||||
|
@ -86,6 +96,7 @@ import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
|
||||||
import info.nightscout.androidaps.receivers.DataReceiver;
|
import info.nightscout.androidaps.receivers.DataReceiver;
|
||||||
import info.nightscout.androidaps.receivers.KeepAliveReceiver;
|
import info.nightscout.androidaps.receivers.KeepAliveReceiver;
|
||||||
import info.nightscout.androidaps.receivers.NSAlarmReceiver;
|
import info.nightscout.androidaps.receivers.NSAlarmReceiver;
|
||||||
|
import info.nightscout.androidaps.receivers.TimeDateOrTZChangeReceiver;
|
||||||
import info.nightscout.androidaps.services.Intents;
|
import info.nightscout.androidaps.services.Intents;
|
||||||
import info.nightscout.androidaps.utils.FabricPrivacy;
|
import info.nightscout.androidaps.utils.FabricPrivacy;
|
||||||
import io.fabric.sdk.android.Fabric;
|
import io.fabric.sdk.android.Fabric;
|
||||||
|
@ -113,6 +124,8 @@ public class MainApp extends Application {
|
||||||
private static AckAlarmReceiver ackAlarmReciever = new AckAlarmReceiver();
|
private static AckAlarmReceiver ackAlarmReciever = new AckAlarmReceiver();
|
||||||
private static DBAccessReceiver dbAccessReciever = new DBAccessReceiver();
|
private static DBAccessReceiver dbAccessReciever = new DBAccessReceiver();
|
||||||
private LocalBroadcastManager lbm;
|
private LocalBroadcastManager lbm;
|
||||||
|
BroadcastReceiver btReceiver;
|
||||||
|
TimeDateOrTZChangeReceiver timeDateOrTZChangeReceiver;
|
||||||
|
|
||||||
public static boolean devBranch;
|
public static boolean devBranch;
|
||||||
public static boolean engineeringMode;
|
public static boolean engineeringMode;
|
||||||
|
@ -146,7 +159,7 @@ public class MainApp extends Application {
|
||||||
File engineeringModeSemaphore = new File(extFilesDir, "engineering_mode");
|
File engineeringModeSemaphore = new File(extFilesDir, "engineering_mode");
|
||||||
|
|
||||||
engineeringMode = engineeringModeSemaphore.exists() && engineeringModeSemaphore.isFile();
|
engineeringMode = engineeringModeSemaphore.exists() && engineeringModeSemaphore.isFile();
|
||||||
devBranch = BuildConfig.VERSION.contains("dev");
|
devBranch = BuildConfig.VERSION.contains("-") || BuildConfig.VERSION.matches(".*[a-zA-Z]+.*");
|
||||||
|
|
||||||
sBus = L.isEnabled(L.EVENTS) && devBranch ? new LoggingBus(ThreadEnforcer.ANY) : new Bus(ThreadEnforcer.ANY);
|
sBus = L.isEnabled(L.EVENTS) && devBranch ? new LoggingBus(ThreadEnforcer.ANY) : new Bus(ThreadEnforcer.ANY);
|
||||||
|
|
||||||
|
@ -154,6 +167,7 @@ public class MainApp extends Application {
|
||||||
|
|
||||||
//trigger here to see the new version on app start after an update
|
//trigger here to see the new version on app start after an update
|
||||||
triggerCheckVersion();
|
triggerCheckVersion();
|
||||||
|
//setBTReceiver();
|
||||||
|
|
||||||
if (pluginsList == null) {
|
if (pluginsList == null) {
|
||||||
pluginsList = new ArrayList<>();
|
pluginsList = new ArrayList<>();
|
||||||
|
@ -175,6 +189,7 @@ public class MainApp extends Application {
|
||||||
if (Config.PUMPDRIVERS) pluginsList.add(LocalInsightPlugin.getPlugin());
|
if (Config.PUMPDRIVERS) pluginsList.add(LocalInsightPlugin.getPlugin());
|
||||||
pluginsList.add(CareportalPlugin.getPlugin());
|
pluginsList.add(CareportalPlugin.getPlugin());
|
||||||
if (Config.PUMPDRIVERS) pluginsList.add(ComboPlugin.getPlugin());
|
if (Config.PUMPDRIVERS) pluginsList.add(ComboPlugin.getPlugin());
|
||||||
|
if (Config.PUMPDRIVERS && engineeringMode) pluginsList.add(MedtronicPumpPlugin.getPlugin());
|
||||||
if (Config.MDI) pluginsList.add(MDIPlugin.getPlugin());
|
if (Config.MDI) pluginsList.add(MDIPlugin.getPlugin());
|
||||||
pluginsList.add(VirtualPumpPlugin.getPlugin());
|
pluginsList.add(VirtualPumpPlugin.getPlugin());
|
||||||
if (Config.APS) pluginsList.add(LoopPlugin.getPlugin());
|
if (Config.APS) pluginsList.add(LoopPlugin.getPlugin());
|
||||||
|
@ -194,8 +209,7 @@ public class MainApp extends Application {
|
||||||
pluginsList.add(SourceNSClientPlugin.getPlugin());
|
pluginsList.add(SourceNSClientPlugin.getPlugin());
|
||||||
pluginsList.add(SourceMM640gPlugin.getPlugin());
|
pluginsList.add(SourceMM640gPlugin.getPlugin());
|
||||||
pluginsList.add(SourceGlimpPlugin.getPlugin());
|
pluginsList.add(SourceGlimpPlugin.getPlugin());
|
||||||
pluginsList.add(SourceDexcomG5Plugin.getPlugin());
|
pluginsList.add(SourceDexcomPlugin.INSTANCE);
|
||||||
pluginsList.add(SourceDexcomG6Plugin.getPlugin());
|
|
||||||
pluginsList.add(SourcePoctechPlugin.getPlugin());
|
pluginsList.add(SourcePoctechPlugin.getPlugin());
|
||||||
pluginsList.add(SourceTomatoPlugin.getPlugin());
|
pluginsList.add(SourceTomatoPlugin.getPlugin());
|
||||||
pluginsList.add(SourceEversensePlugin.getPlugin());
|
pluginsList.add(SourceEversensePlugin.getPlugin());
|
||||||
|
@ -206,7 +220,11 @@ public class MainApp extends Application {
|
||||||
pluginsList.add(StatuslinePlugin.initPlugin(this));
|
pluginsList.add(StatuslinePlugin.initPlugin(this));
|
||||||
pluginsList.add(PersistentNotificationPlugin.getPlugin());
|
pluginsList.add(PersistentNotificationPlugin.getPlugin());
|
||||||
pluginsList.add(NSClientPlugin.getPlugin());
|
pluginsList.add(NSClientPlugin.getPlugin());
|
||||||
|
if (engineeringMode)
|
||||||
|
pluginsList.add(TidepoolPlugin.INSTANCE);
|
||||||
pluginsList.add(MaintenancePlugin.initPlugin(this));
|
pluginsList.add(MaintenancePlugin.initPlugin(this));
|
||||||
|
if (engineeringMode)
|
||||||
|
pluginsList.add(AutomationPlugin.INSTANCE);
|
||||||
|
|
||||||
pluginsList.add(ConfigBuilderPlugin.getPlugin());
|
pluginsList.add(ConfigBuilderPlugin.getPlugin());
|
||||||
|
|
||||||
|
@ -254,6 +272,10 @@ public class MainApp extends Application {
|
||||||
|
|
||||||
//register dbaccess
|
//register dbaccess
|
||||||
lbm.registerReceiver(dbAccessReciever, new IntentFilter(Intents.ACTION_DATABASE));
|
lbm.registerReceiver(dbAccessReciever, new IntentFilter(Intents.ACTION_DATABASE));
|
||||||
|
|
||||||
|
this.timeDateOrTZChangeReceiver = new TimeDateOrTZChangeReceiver();
|
||||||
|
this.timeDateOrTZChangeReceiver.registerBroadcasts(this);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startKeepAliveService() {
|
private void startKeepAliveService() {
|
||||||
|
@ -439,5 +461,19 @@ public class MainApp extends Application {
|
||||||
sDatabaseHelper.close();
|
sDatabaseHelper.close();
|
||||||
sDatabaseHelper = null;
|
sDatabaseHelper = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (btReceiver != null) {
|
||||||
|
unregisterReceiver(btReceiver);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (timeDateOrTZChangeReceiver!=null) {
|
||||||
|
unregisterReceiver(timeDateOrTZChangeReceiver);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int dpToPx(int dp) {
|
||||||
|
float scale = sResources.getDisplayMetrics().density;
|
||||||
|
return (int) (dp * scale + 0.5f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,9 +2,9 @@ package info.nightscout.androidaps.activities;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
import android.support.v4.content.res.ResourcesCompat;
|
import androidx.core.content.res.ResourcesCompat;
|
||||||
import android.support.v7.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
import android.support.v7.widget.PopupMenu;
|
import androidx.appcompat.widget.PopupMenu;
|
||||||
import android.text.SpannableString;
|
import android.text.SpannableString;
|
||||||
import android.text.style.ForegroundColorSpan;
|
import android.text.style.ForegroundColorSpan;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
|
@ -52,7 +52,7 @@ public class HistoryBrowseActivity extends AppCompatActivity {
|
||||||
ImageButton chartButton;
|
ImageButton chartButton;
|
||||||
|
|
||||||
boolean showBasal = true;
|
boolean showBasal = true;
|
||||||
boolean showIob, showCob, showDev, showRat, showDevslope;
|
boolean showIob, showCob, showDev, showRat, showActPrim, showActSec, showDevslope;
|
||||||
|
|
||||||
|
|
||||||
@BindView(R.id.historybrowse_date)
|
@BindView(R.id.historybrowse_date)
|
||||||
|
@ -285,6 +285,10 @@ public class HistoryBrowseActivity extends AppCompatActivity {
|
||||||
// set manual x bounds to have nice steps
|
// set manual x bounds to have nice steps
|
||||||
graphData.formatAxis(fromTime, toTime);
|
graphData.formatAxis(fromTime, toTime);
|
||||||
|
|
||||||
|
if(showActPrim) {
|
||||||
|
graphData.addActivity(fromTime, toTime, false,1d);
|
||||||
|
}
|
||||||
|
|
||||||
// Treatments
|
// Treatments
|
||||||
graphData.addTreatments(fromTime, toTime);
|
graphData.addTreatments(fromTime, toTime);
|
||||||
|
|
||||||
|
@ -305,6 +309,7 @@ public class HistoryBrowseActivity extends AppCompatActivity {
|
||||||
boolean useCobForScale = false;
|
boolean useCobForScale = false;
|
||||||
boolean useDevForScale = false;
|
boolean useDevForScale = false;
|
||||||
boolean useRatioForScale = false;
|
boolean useRatioForScale = false;
|
||||||
|
boolean useIAForScale = false;
|
||||||
boolean useDSForScale = false;
|
boolean useDSForScale = false;
|
||||||
|
|
||||||
if (showIob) {
|
if (showIob) {
|
||||||
|
@ -315,6 +320,8 @@ public class HistoryBrowseActivity extends AppCompatActivity {
|
||||||
useDevForScale = true;
|
useDevForScale = true;
|
||||||
} else if (showRat) {
|
} else if (showRat) {
|
||||||
useRatioForScale = true;
|
useRatioForScale = true;
|
||||||
|
} else if (showActSec) {
|
||||||
|
useIAForScale = true;
|
||||||
} else if (showDevslope) {
|
} else if (showDevslope) {
|
||||||
useDSForScale = true;
|
useDSForScale = true;
|
||||||
}
|
}
|
||||||
|
@ -327,6 +334,8 @@ public class HistoryBrowseActivity extends AppCompatActivity {
|
||||||
secondGraphData.addDeviations(fromTime, toTime, useDevForScale, 1d);
|
secondGraphData.addDeviations(fromTime, toTime, useDevForScale, 1d);
|
||||||
if (showRat)
|
if (showRat)
|
||||||
secondGraphData.addRatio(fromTime, toTime, useRatioForScale, 1d);
|
secondGraphData.addRatio(fromTime, toTime, useRatioForScale, 1d);
|
||||||
|
if (showActSec)
|
||||||
|
secondGraphData.addActivity(fromTime, toTime, useIAForScale, useIAForScale? 2d: 1d);
|
||||||
if (showDevslope)
|
if (showDevslope)
|
||||||
secondGraphData.addDeviationSlope(fromTime, toTime, useDSForScale, 1d);
|
secondGraphData.addDeviationSlope(fromTime, toTime, useDSForScale, 1d);
|
||||||
|
|
||||||
|
@ -337,14 +346,14 @@ public class HistoryBrowseActivity extends AppCompatActivity {
|
||||||
|
|
||||||
// do GUI update
|
// do GUI update
|
||||||
runOnUiThread(() -> {
|
runOnUiThread(() -> {
|
||||||
if (showIob || showCob || showDev || showRat || showDevslope) {
|
if (showIob || showCob || showDev || showRat || showActSec || showDevslope) {
|
||||||
iobGraph.setVisibility(View.VISIBLE);
|
iobGraph.setVisibility(View.VISIBLE);
|
||||||
} else {
|
} else {
|
||||||
iobGraph.setVisibility(View.GONE);
|
iobGraph.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
// finally enforce drawing of graphs
|
// finally enforce drawing of graphs
|
||||||
graphData.performUpdate();
|
graphData.performUpdate();
|
||||||
if (showIob || showCob || showDev || showRat || showDevslope)
|
if (showIob || showCob || showDev || showRat || showActSec || showDevslope)
|
||||||
secondGraphData.performUpdate();
|
secondGraphData.performUpdate();
|
||||||
});
|
});
|
||||||
}).start();
|
}).start();
|
||||||
|
@ -353,22 +362,37 @@ public class HistoryBrowseActivity extends AppCompatActivity {
|
||||||
private void setupChartMenu() {
|
private void setupChartMenu() {
|
||||||
chartButton = (ImageButton) findViewById(R.id.overview_chartMenuButton);
|
chartButton = (ImageButton) findViewById(R.id.overview_chartMenuButton);
|
||||||
chartButton.setOnClickListener(v -> {
|
chartButton.setOnClickListener(v -> {
|
||||||
MenuItem item;
|
MenuItem item,dividerItem;
|
||||||
CharSequence title;
|
CharSequence title;
|
||||||
|
int titleMaxChars = 0;
|
||||||
SpannableString s;
|
SpannableString s;
|
||||||
PopupMenu popup = new PopupMenu(v.getContext(), v);
|
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));
|
item = popup.getMenu().add(Menu.NONE, OverviewFragment.CHARTTYPE.BAS.ordinal(), Menu.NONE, MainApp.gs(R.string.overview_show_basals));
|
||||||
title = item.getTitle();
|
title = item.getTitle();
|
||||||
|
if (titleMaxChars < title.length()) titleMaxChars = title.length();
|
||||||
s = new SpannableString(title);
|
s = new SpannableString(title);
|
||||||
s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.basal, null)), 0, s.length(), 0);
|
s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.basal, null)), 0, s.length(), 0);
|
||||||
item.setTitle(s);
|
item.setTitle(s);
|
||||||
item.setCheckable(true);
|
item.setCheckable(true);
|
||||||
item.setChecked(showBasal);
|
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));
|
item = popup.getMenu().add(Menu.NONE, OverviewFragment.CHARTTYPE.IOB.ordinal(), Menu.NONE, MainApp.gs(R.string.overview_show_iob));
|
||||||
title = item.getTitle();
|
title = item.getTitle();
|
||||||
|
if (titleMaxChars < title.length()) titleMaxChars = title.length();
|
||||||
s = new SpannableString(title);
|
s = new SpannableString(title);
|
||||||
s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.iob, null)), 0, s.length(), 0);
|
s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.iob, null)), 0, s.length(), 0);
|
||||||
item.setTitle(s);
|
item.setTitle(s);
|
||||||
|
@ -377,6 +401,7 @@ public class HistoryBrowseActivity extends AppCompatActivity {
|
||||||
|
|
||||||
item = popup.getMenu().add(Menu.NONE, OverviewFragment.CHARTTYPE.COB.ordinal(), Menu.NONE, MainApp.gs(R.string.overview_show_cob));
|
item = popup.getMenu().add(Menu.NONE, OverviewFragment.CHARTTYPE.COB.ordinal(), Menu.NONE, MainApp.gs(R.string.overview_show_cob));
|
||||||
title = item.getTitle();
|
title = item.getTitle();
|
||||||
|
if (titleMaxChars < title.length()) titleMaxChars = title.length();
|
||||||
s = new SpannableString(title);
|
s = new SpannableString(title);
|
||||||
s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.cob, null)), 0, s.length(), 0);
|
s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.cob, null)), 0, s.length(), 0);
|
||||||
item.setTitle(s);
|
item.setTitle(s);
|
||||||
|
@ -385,6 +410,7 @@ public class HistoryBrowseActivity extends AppCompatActivity {
|
||||||
|
|
||||||
item = popup.getMenu().add(Menu.NONE, OverviewFragment.CHARTTYPE.DEV.ordinal(), Menu.NONE, MainApp.gs(R.string.overview_show_deviations));
|
item = popup.getMenu().add(Menu.NONE, OverviewFragment.CHARTTYPE.DEV.ordinal(), Menu.NONE, MainApp.gs(R.string.overview_show_deviations));
|
||||||
title = item.getTitle();
|
title = item.getTitle();
|
||||||
|
if (titleMaxChars < title.length()) titleMaxChars = title.length();
|
||||||
s = new SpannableString(title);
|
s = new SpannableString(title);
|
||||||
s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.deviations, null)), 0, s.length(), 0);
|
s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.deviations, null)), 0, s.length(), 0);
|
||||||
item.setTitle(s);
|
item.setTitle(s);
|
||||||
|
@ -393,15 +419,27 @@ public class HistoryBrowseActivity extends AppCompatActivity {
|
||||||
|
|
||||||
item = popup.getMenu().add(Menu.NONE, OverviewFragment.CHARTTYPE.SEN.ordinal(), Menu.NONE, MainApp.gs(R.string.overview_show_sensitivity));
|
item = popup.getMenu().add(Menu.NONE, OverviewFragment.CHARTTYPE.SEN.ordinal(), Menu.NONE, MainApp.gs(R.string.overview_show_sensitivity));
|
||||||
title = item.getTitle();
|
title = item.getTitle();
|
||||||
|
if (titleMaxChars < title.length()) titleMaxChars = title.length();
|
||||||
s = new SpannableString(title);
|
s = new SpannableString(title);
|
||||||
s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.ratio, null)), 0, s.length(), 0);
|
s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.ratio, null)), 0, s.length(), 0);
|
||||||
item.setTitle(s);
|
item.setTitle(s);
|
||||||
item.setCheckable(true);
|
item.setCheckable(true);
|
||||||
item.setChecked(showRat);
|
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) {
|
if (MainApp.devBranch) {
|
||||||
item = popup.getMenu().add(Menu.NONE, OverviewFragment.CHARTTYPE.DEVSLOPE.ordinal(), Menu.NONE, "Deviation slope");
|
item = popup.getMenu().add(Menu.NONE, OverviewFragment.CHARTTYPE.DEVSLOPE.ordinal(), Menu.NONE, "Deviation slope");
|
||||||
title = item.getTitle();
|
title = item.getTitle();
|
||||||
|
if (titleMaxChars < title.length()) titleMaxChars = title.length();
|
||||||
s = new SpannableString(title);
|
s = new SpannableString(title);
|
||||||
s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.devslopepos, null)), 0, s.length(), 0);
|
s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.devslopepos, null)), 0, s.length(), 0);
|
||||||
item.setTitle(s);
|
item.setTitle(s);
|
||||||
|
@ -409,6 +447,10 @@ public class HistoryBrowseActivity extends AppCompatActivity {
|
||||||
item.setChecked(showDevslope);
|
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 -> {
|
popup.setOnMenuItemClickListener(item1 -> {
|
||||||
if (item1.getItemId() == OverviewFragment.CHARTTYPE.BAS.ordinal()) {
|
if (item1.getItemId() == OverviewFragment.CHARTTYPE.BAS.ordinal()) {
|
||||||
showBasal = !item1.isChecked();
|
showBasal = !item1.isChecked();
|
||||||
|
@ -420,6 +462,10 @@ public class HistoryBrowseActivity extends AppCompatActivity {
|
||||||
showDev = !item1.isChecked();
|
showDev = !item1.isChecked();
|
||||||
} else if (item1.getItemId() == OverviewFragment.CHARTTYPE.SEN.ordinal()) {
|
} else if (item1.getItemId() == OverviewFragment.CHARTTYPE.SEN.ordinal()) {
|
||||||
showRat = !item1.isChecked();
|
showRat = !item1.isChecked();
|
||||||
|
} else if (item1.getItemId() == OverviewFragment.CHARTTYPE.ACTPRIM.ordinal()) {
|
||||||
|
showActPrim = !item1.isChecked();
|
||||||
|
} else if (item1.getItemId() == OverviewFragment.CHARTTYPE.ACTSEC.ordinal()) {
|
||||||
|
showActSec = !item1.isChecked();
|
||||||
} else if (item1.getItemId() == OverviewFragment.CHARTTYPE.DEVSLOPE.ordinal()) {
|
} else if (item1.getItemId() == OverviewFragment.CHARTTYPE.DEVSLOPE.ordinal()) {
|
||||||
showDevslope = !item1.isChecked();
|
showDevslope = !item1.isChecked();
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,12 +15,15 @@ import android.text.TextUtils;
|
||||||
import info.nightscout.androidaps.Config;
|
import info.nightscout.androidaps.Config;
|
||||||
import info.nightscout.androidaps.MainApp;
|
import info.nightscout.androidaps.MainApp;
|
||||||
import info.nightscout.androidaps.R;
|
import info.nightscout.androidaps.R;
|
||||||
|
import info.nightscout.androidaps.plugins.bus.RxBus;
|
||||||
import info.nightscout.androidaps.events.EventPreferenceChange;
|
import info.nightscout.androidaps.events.EventPreferenceChange;
|
||||||
import info.nightscout.androidaps.events.EventRefreshGui;
|
import info.nightscout.androidaps.events.EventRefreshGui;
|
||||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||||
import info.nightscout.androidaps.interfaces.PluginType;
|
import info.nightscout.androidaps.interfaces.PluginType;
|
||||||
import info.nightscout.androidaps.plugins.general.careportal.CareportalPlugin;
|
import info.nightscout.androidaps.plugins.general.careportal.CareportalPlugin;
|
||||||
import info.nightscout.androidaps.plugins.constraints.safety.SafetyPlugin;
|
import info.nightscout.androidaps.plugins.constraints.safety.SafetyPlugin;
|
||||||
|
import info.nightscout.androidaps.plugins.general.tidepool.TidepoolPlugin;
|
||||||
|
import info.nightscout.androidaps.plugins.general.tidepool.comm.TidepoolUploader;
|
||||||
import info.nightscout.androidaps.plugins.insulin.InsulinOrefFreePeakPlugin;
|
import info.nightscout.androidaps.plugins.insulin.InsulinOrefFreePeakPlugin;
|
||||||
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin;
|
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin;
|
||||||
import info.nightscout.androidaps.plugins.general.nsclient.NSClientPlugin;
|
import info.nightscout.androidaps.plugins.general.nsclient.NSClientPlugin;
|
||||||
|
@ -33,18 +36,20 @@ import info.nightscout.androidaps.plugins.pump.danaRKorean.DanaRKoreanPlugin;
|
||||||
import info.nightscout.androidaps.plugins.pump.danaRS.DanaRSPlugin;
|
import info.nightscout.androidaps.plugins.pump.danaRS.DanaRSPlugin;
|
||||||
import info.nightscout.androidaps.plugins.pump.danaRv2.DanaRv2Plugin;
|
import info.nightscout.androidaps.plugins.pump.danaRv2.DanaRv2Plugin;
|
||||||
import info.nightscout.androidaps.plugins.pump.insight.LocalInsightPlugin;
|
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.pump.virtual.VirtualPumpPlugin;
|
||||||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityAAPSPlugin;
|
import info.nightscout.androidaps.plugins.sensitivity.SensitivityAAPSPlugin;
|
||||||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref0Plugin;
|
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref0Plugin;
|
||||||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin;
|
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin;
|
||||||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAveragePlugin;
|
import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAveragePlugin;
|
||||||
import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin;
|
import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin;
|
||||||
import info.nightscout.androidaps.plugins.source.SourceDexcomG5Plugin;
|
|
||||||
import info.nightscout.androidaps.plugins.general.wear.WearPlugin;
|
import info.nightscout.androidaps.plugins.general.wear.WearPlugin;
|
||||||
import info.nightscout.androidaps.plugins.general.xdripStatusline.StatuslinePlugin;
|
import info.nightscout.androidaps.plugins.general.xdripStatusline.StatuslinePlugin;
|
||||||
|
import info.nightscout.androidaps.plugins.source.SourceDexcomPlugin;
|
||||||
import info.nightscout.androidaps.utils.LocaleHelper;
|
import info.nightscout.androidaps.utils.LocaleHelper;
|
||||||
import info.nightscout.androidaps.utils.OKDialog;
|
import info.nightscout.androidaps.utils.OKDialog;
|
||||||
import info.nightscout.androidaps.utils.SP;
|
import info.nightscout.androidaps.utils.SP;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.AutomationPlugin;
|
||||||
|
|
||||||
public class PreferencesActivity extends PreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener {
|
public class PreferencesActivity extends PreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||||
MyPreferenceFragment myPreferenceFragment;
|
MyPreferenceFragment myPreferenceFragment;
|
||||||
|
@ -63,6 +68,7 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
|
||||||
@Override
|
@Override
|
||||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
||||||
MainApp.bus().post(new EventPreferenceChange(key));
|
MainApp.bus().post(new EventPreferenceChange(key));
|
||||||
|
RxBus.INSTANCE.send(new EventPreferenceChange(key));
|
||||||
if (key.equals("language")) {
|
if (key.equals("language")) {
|
||||||
String lang = sharedPreferences.getString("language", "en");
|
String lang = sharedPreferences.getString("language", "en");
|
||||||
LocaleHelper.setLocale(getApplicationContext(), lang);
|
LocaleHelper.setLocale(getApplicationContext(), lang);
|
||||||
|
@ -93,7 +99,7 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
|
||||||
} else if (editTextPref.getText() != null) {
|
} else if (editTextPref.getText() != null) {
|
||||||
((EditTextPreference) pref).setDialogMessage(editTextPref.getDialogMessage());
|
((EditTextPreference) pref).setDialogMessage(editTextPref.getDialogMessage());
|
||||||
pref.setSummary(editTextPref.getText());
|
pref.setSummary(editTextPref.getText());
|
||||||
} else if (pref.getKey().contains("smscommunicator_allowednumbers") && TextUtils.isEmpty(editTextPref.getText().trim())) {
|
} else if (pref.getKey().contains("smscommunicator_allowednumbers") && (editTextPref.getText() == null || TextUtils.isEmpty(editTextPref.getText().trim()))) {
|
||||||
pref.setSummary(MainApp.gs(R.string.smscommunicator_allowednumbers_summary));
|
pref.setSummary(MainApp.gs(R.string.smscommunicator_allowednumbers_summary));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -144,7 +150,7 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
|
||||||
|
|
||||||
addPreferencesFromResource(R.xml.pref_overview);
|
addPreferencesFromResource(R.xml.pref_overview);
|
||||||
|
|
||||||
addPreferencesFromResourceIfEnabled(SourceDexcomG5Plugin.getPlugin(), PluginType.BGSOURCE);
|
addPreferencesFromResourceIfEnabled(SourceDexcomPlugin.INSTANCE, PluginType.BGSOURCE);
|
||||||
addPreferencesFromResourceIfEnabled(CareportalPlugin.getPlugin(), PluginType.GENERAL);
|
addPreferencesFromResourceIfEnabled(CareportalPlugin.getPlugin(), PluginType.GENERAL);
|
||||||
addPreferencesFromResourceIfEnabled(SafetyPlugin.getPlugin(), PluginType.CONSTRAINTS);
|
addPreferencesFromResourceIfEnabled(SafetyPlugin.getPlugin(), PluginType.CONSTRAINTS);
|
||||||
if (Config.APS) {
|
if (Config.APS) {
|
||||||
|
@ -166,6 +172,7 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
|
||||||
addPreferencesFromResourceIfEnabled(DanaRSPlugin.getPlugin(), PluginType.PUMP);
|
addPreferencesFromResourceIfEnabled(DanaRSPlugin.getPlugin(), PluginType.PUMP);
|
||||||
addPreferencesFromResourceIfEnabled(LocalInsightPlugin.getPlugin(), PluginType.PUMP);
|
addPreferencesFromResourceIfEnabled(LocalInsightPlugin.getPlugin(), PluginType.PUMP);
|
||||||
addPreferencesFromResourceIfEnabled(ComboPlugin.getPlugin(), PluginType.PUMP);
|
addPreferencesFromResourceIfEnabled(ComboPlugin.getPlugin(), PluginType.PUMP);
|
||||||
|
addPreferencesFromResourceIfEnabled(MedtronicPumpPlugin.getPlugin(), PluginType.PUMP);
|
||||||
|
|
||||||
if (DanaRPlugin.getPlugin().isEnabled(PluginType.PROFILE)
|
if (DanaRPlugin.getPlugin().isEnabled(PluginType.PROFILE)
|
||||||
|| DanaRKoreanPlugin.getPlugin().isEnabled(PluginType.PROFILE)
|
|| DanaRKoreanPlugin.getPlugin().isEnabled(PluginType.PROFILE)
|
||||||
|
@ -182,7 +189,9 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
|
||||||
addPreferencesFromResourceIfEnabled(InsulinOrefFreePeakPlugin.getPlugin(), PluginType.INSULIN);
|
addPreferencesFromResourceIfEnabled(InsulinOrefFreePeakPlugin.getPlugin(), PluginType.INSULIN);
|
||||||
|
|
||||||
addPreferencesFromResourceIfEnabled(NSClientPlugin.getPlugin(), PluginType.GENERAL);
|
addPreferencesFromResourceIfEnabled(NSClientPlugin.getPlugin(), PluginType.GENERAL);
|
||||||
|
addPreferencesFromResourceIfEnabled(TidepoolPlugin.INSTANCE, PluginType.GENERAL);
|
||||||
addPreferencesFromResourceIfEnabled(SmsCommunicatorPlugin.getPlugin(), PluginType.GENERAL);
|
addPreferencesFromResourceIfEnabled(SmsCommunicatorPlugin.getPlugin(), PluginType.GENERAL);
|
||||||
|
addPreferencesFromResourceIfEnabled(AutomationPlugin.INSTANCE, PluginType.GENERAL);
|
||||||
|
|
||||||
addPreferencesFromResource(R.xml.pref_others);
|
addPreferencesFromResource(R.xml.pref_others);
|
||||||
addPreferencesFromResource(R.xml.pref_datachoices);
|
addPreferencesFromResource(R.xml.pref_datachoices);
|
||||||
|
@ -192,7 +201,7 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Config.NSCLIENT) {
|
if (Config.NSCLIENT) {
|
||||||
PreferenceScreen scrnAdvancedSettings = (PreferenceScreen)findPreference(getString(R.string.key_advancedsettings));
|
PreferenceScreen scrnAdvancedSettings = (PreferenceScreen) findPreference(getString(R.string.key_advancedsettings));
|
||||||
if (scrnAdvancedSettings != null) {
|
if (scrnAdvancedSettings != null) {
|
||||||
scrnAdvancedSettings.removePreference(getPreference(getString(R.string.key_statuslights_res_warning)));
|
scrnAdvancedSettings.removePreference(getPreference(getString(R.string.key_statuslights_res_warning)));
|
||||||
scrnAdvancedSettings.removePreference(getPreference(getString(R.string.key_statuslights_res_critical)));
|
scrnAdvancedSettings.removePreference(getPreference(getString(R.string.key_statuslights_res_critical)));
|
||||||
|
@ -203,6 +212,13 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
|
||||||
}
|
}
|
||||||
|
|
||||||
initSummary(getPreferenceScreen());
|
initSummary(getPreferenceScreen());
|
||||||
|
|
||||||
|
final Preference tidepoolTestLogin = findPreference(MainApp.gs(R.string.key_tidepool_test_login));
|
||||||
|
if (tidepoolTestLogin != null)
|
||||||
|
tidepoolTestLogin.setOnPreferenceClickListener(preference -> {
|
||||||
|
TidepoolUploader.INSTANCE.testLogin(getActivity());
|
||||||
|
return false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
package info.nightscout.androidaps.activities
|
||||||
|
|
||||||
|
import android.os.Build
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import info.nightscout.androidaps.plugins.source.SourceDexcomPlugin
|
||||||
|
|
||||||
|
class RequestDexcomPermissionActivity : AppCompatActivity() {
|
||||||
|
|
||||||
|
private val requestCode = "AndroidAPS <3".map { it.toInt() }.sum()
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
|
requestPermissions(arrayOf(SourceDexcomPlugin.PERMISSION), requestCode)
|
||||||
|
} else {
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -2,9 +2,9 @@ package info.nightscout.androidaps.activities;
|
||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import android.support.v4.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import android.support.v7.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ import android.app.Activity;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v7.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
package info.nightscout.androidaps.data;
|
package info.nightscout.androidaps.data;
|
||||||
|
|
||||||
import android.support.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.Constants;
|
import info.nightscout.androidaps.Constants;
|
||||||
import info.nightscout.androidaps.MainApp;
|
import info.nightscout.androidaps.MainApp;
|
||||||
import info.nightscout.androidaps.interfaces.Constraint;
|
import info.nightscout.androidaps.interfaces.Constraint;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package info.nightscout.androidaps.data;
|
package info.nightscout.androidaps.data;
|
||||||
|
|
||||||
import android.support.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import android.support.v4.util.LongSparseArray;
|
import androidx.collection.LongSparseArray;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
package info.nightscout.androidaps.data;
|
package info.nightscout.androidaps.data;
|
||||||
|
|
||||||
|
|
||||||
import android.support.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import android.support.v4.util.LongSparseArray;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.db.TemporaryBasal;
|
|
||||||
import info.nightscout.androidaps.interfaces.Interval;
|
import info.nightscout.androidaps.interfaces.Interval;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -21,7 +19,7 @@ public class NonOverlappingIntervals<T extends Interval> extends Intervals<T> {
|
||||||
rawData = other.rawData.clone();
|
rawData = other.rawData.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected synchronized void merge() {
|
public synchronized void merge() {
|
||||||
for (int index = 0; index < rawData.size() - 1; index++) {
|
for (int index = 0; index < rawData.size() - 1; index++) {
|
||||||
Interval i = rawData.valueAt(index);
|
Interval i = rawData.valueAt(index);
|
||||||
long startOfNewer = rawData.valueAt(index + 1).start();
|
long startOfNewer = rawData.valueAt(index + 1).start();
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package info.nightscout.androidaps.data;
|
package info.nightscout.androidaps.data;
|
||||||
|
|
||||||
|
|
||||||
import android.support.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import info.nightscout.androidaps.interfaces.Interval;
|
import info.nightscout.androidaps.interfaces.Interval;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package info.nightscout.androidaps.data;
|
package info.nightscout.androidaps.data;
|
||||||
|
|
||||||
import android.support.v4.util.LongSparseArray;
|
import androidx.collection.LongSparseArray;
|
||||||
|
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
|
@ -400,6 +400,19 @@ public class Profile {
|
||||||
return getValuesList(isf_v, null, new DecimalFormat("0.0"), getUnits() + MainApp.gs(R.string.profile_per_unit));
|
return getValuesList(isf_v, null, new DecimalFormat("0.0"), getUnits() + MainApp.gs(R.string.profile_per_unit));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ProfileValue[] getIsfs() {
|
||||||
|
if (isf_v == null)
|
||||||
|
isf_v = convertToSparseArray(ic);
|
||||||
|
ProfileValue[] ret = new ProfileValue[isf_v.size()];
|
||||||
|
|
||||||
|
for (Integer index = 0; index < isf_v.size(); index++) {
|
||||||
|
Integer tas = (int) isf_v.keyAt(index);
|
||||||
|
double value = isf_v.valueAt(index);
|
||||||
|
ret[index] = new ProfileValue(tas, value);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
public double getIc() {
|
public double getIc() {
|
||||||
return getIcTimeFromMidnight(secondsFromMidnight());
|
return getIcTimeFromMidnight(secondsFromMidnight());
|
||||||
}
|
}
|
||||||
|
@ -420,6 +433,19 @@ public class Profile {
|
||||||
return getValuesList(ic_v, null, new DecimalFormat("0.0"), MainApp.gs(R.string.profile_carbs_per_unit));
|
return getValuesList(ic_v, null, new DecimalFormat("0.0"), MainApp.gs(R.string.profile_carbs_per_unit));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ProfileValue[] getIcs() {
|
||||||
|
if (ic_v == null)
|
||||||
|
ic_v = convertToSparseArray(ic);
|
||||||
|
ProfileValue[] ret = new ProfileValue[ic_v.size()];
|
||||||
|
|
||||||
|
for (Integer index = 0; index < ic_v.size(); index++) {
|
||||||
|
Integer tas = (int) ic_v.keyAt(index);
|
||||||
|
double value = ic_v.valueAt(index);
|
||||||
|
ret[index] = new ProfileValue(tas, value);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
public double getBasal() {
|
public double getBasal() {
|
||||||
return getBasalTimeFromMidnight(secondsFromMidnight());
|
return getBasalTimeFromMidnight(secondsFromMidnight());
|
||||||
}
|
}
|
||||||
|
@ -441,8 +467,8 @@ public class Profile {
|
||||||
return getValuesList(basal_v, null, new DecimalFormat("0.00"), MainApp.gs(R.string.profile_ins_units_per_hout));
|
return getValuesList(basal_v, null, new DecimalFormat("0.00"), MainApp.gs(R.string.profile_ins_units_per_hout));
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BasalValue {
|
public class ProfileValue {
|
||||||
public BasalValue(int timeAsSeconds, double value) {
|
public ProfileValue(int timeAsSeconds, double value) {
|
||||||
this.timeAsSeconds = timeAsSeconds;
|
this.timeAsSeconds = timeAsSeconds;
|
||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
@ -451,15 +477,15 @@ public class Profile {
|
||||||
public double value;
|
public double value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized BasalValue[] getBasalValues() {
|
public synchronized ProfileValue[] getBasalValues() {
|
||||||
if (basal_v == null)
|
if (basal_v == null)
|
||||||
basal_v = convertToSparseArray(basal);
|
basal_v = convertToSparseArray(basal);
|
||||||
BasalValue[] ret = new BasalValue[basal_v.size()];
|
ProfileValue[] ret = new ProfileValue[basal_v.size()];
|
||||||
|
|
||||||
for (Integer index = 0; index < basal_v.size(); index++) {
|
for (Integer index = 0; index < basal_v.size(); index++) {
|
||||||
Integer tas = (int) basal_v.keyAt(index);
|
Integer tas = (int) basal_v.keyAt(index);
|
||||||
double value = basal_v.valueAt(index);
|
double value = basal_v.valueAt(index);
|
||||||
ret[index] = new BasalValue(tas, value);
|
ret[index] = new ProfileValue(tas, value);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -500,6 +526,49 @@ public class Profile {
|
||||||
return getValueToTime(targetHigh_v, timeAsSeconds);
|
return getValueToTime(targetHigh_v, timeAsSeconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class TargetValue {
|
||||||
|
public TargetValue(int timeAsSeconds, double low, double high) {
|
||||||
|
this.timeAsSeconds = timeAsSeconds;
|
||||||
|
this.low = low;
|
||||||
|
this.high = high;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int timeAsSeconds;
|
||||||
|
public double low;
|
||||||
|
public double high;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TargetValue[] getTargets() {
|
||||||
|
if (targetLow_v == null)
|
||||||
|
targetLow_v = convertToSparseArray(targetLow);
|
||||||
|
if (targetHigh_v == null)
|
||||||
|
targetHigh_v = convertToSparseArray(targetHigh);
|
||||||
|
TargetValue[] ret = new TargetValue[targetLow_v.size()];
|
||||||
|
|
||||||
|
for (Integer index = 0; index < targetLow_v.size(); index++) {
|
||||||
|
Integer tas = (int) targetLow_v.keyAt(index);
|
||||||
|
double low = targetLow_v.valueAt(index);
|
||||||
|
double high = targetHigh_v.valueAt(index);
|
||||||
|
ret[index] = new TargetValue(tas, low, high);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProfileValue[] getSingleTargets() {
|
||||||
|
if (targetLow_v == null)
|
||||||
|
targetLow_v = convertToSparseArray(targetLow);
|
||||||
|
if (targetHigh_v == null)
|
||||||
|
targetHigh_v = convertToSparseArray(targetHigh);
|
||||||
|
ProfileValue[] ret = new ProfileValue[targetLow_v.size()];
|
||||||
|
|
||||||
|
for (Integer index = 0; index < targetLow_v.size(); index++) {
|
||||||
|
Integer tas = (int) targetLow_v.keyAt(index);
|
||||||
|
double target = (targetLow_v.valueAt(index) + targetHigh_v.valueAt(index)) / 2;
|
||||||
|
ret[index] = new ProfileValue(tas, target);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
public String getTargetList() {
|
public String getTargetList() {
|
||||||
if (targetLow_v == null)
|
if (targetLow_v == null)
|
||||||
targetLow_v = convertToSparseArray(targetLow);
|
targetLow_v = convertToSparseArray(targetLow);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package info.nightscout.androidaps.data;
|
package info.nightscout.androidaps.data;
|
||||||
|
|
||||||
import android.support.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import android.support.v4.util.LongSparseArray;
|
import androidx.collection.LongSparseArray;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package info.nightscout.androidaps.data;
|
package info.nightscout.androidaps.data;
|
||||||
|
|
||||||
import android.support.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import android.support.v4.util.ArrayMap;
|
import androidx.collection.ArrayMap;
|
||||||
|
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
|
@ -45,6 +45,11 @@ public class PumpEnactResult {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PumpEnactResult comment(int comment) {
|
||||||
|
this.comment = MainApp.gs(comment);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public PumpEnactResult duration(int duration) {
|
public PumpEnactResult duration(int duration) {
|
||||||
this.duration = duration;
|
this.duration = duration;
|
||||||
return this;
|
return this;
|
||||||
|
|
|
@ -50,7 +50,7 @@ public class QuickWizardEntry {
|
||||||
useTemptarget: 0
|
useTemptarget: 0
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
public QuickWizardEntry() {
|
QuickWizardEntry() {
|
||||||
String emptyData = "{\"buttonText\":\"\",\"carbs\":0,\"validFrom\":0,\"validTo\":86340}";
|
String emptyData = "{\"buttonText\":\"\",\"carbs\":0,\"validFrom\":0,\"validTo\":86340}";
|
||||||
try {
|
try {
|
||||||
storage = new JSONObject(emptyData);
|
storage = new JSONObject(emptyData);
|
||||||
|
@ -60,18 +60,17 @@ public class QuickWizardEntry {
|
||||||
position = -1;
|
position = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public QuickWizardEntry(JSONObject entry, int position) {
|
QuickWizardEntry(JSONObject entry, int position) {
|
||||||
storage = entry;
|
storage = entry;
|
||||||
this.position = position;
|
this.position = position;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Boolean isActive() {
|
Boolean isActive() {
|
||||||
return Profile.secondsFromMidnight() >= validFrom() && Profile.secondsFromMidnight() <= validTo();
|
return Profile.secondsFromMidnight() >= validFrom() && Profile.secondsFromMidnight() <= validTo();
|
||||||
}
|
}
|
||||||
|
|
||||||
public BolusWizard doCalc(Profile profile, TempTarget tempTarget, BgReading lastBG, boolean _synchronized) {
|
public BolusWizard doCalc(Profile profile, String profileName, BgReading lastBG, boolean _synchronized) {
|
||||||
BolusWizard wizard = new BolusWizard();
|
final TempTarget tempTarget = TreatmentsPlugin.getPlugin().getTempTargetFromHistory();
|
||||||
|
|
||||||
//BG
|
//BG
|
||||||
double bg = 0;
|
double bg = 0;
|
||||||
if (lastBG != null && useBG() == YES) {
|
if (lastBG != null && useBG() == YES) {
|
||||||
|
@ -86,11 +85,6 @@ public class QuickWizardEntry {
|
||||||
cob = cobInfo.displayCob;
|
cob = cobInfo.displayCob;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Temp target
|
|
||||||
if (useTempTarget() == NO) {
|
|
||||||
tempTarget = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bolus IOB
|
// Bolus IOB
|
||||||
boolean bolusIOB = false;
|
boolean bolusIOB = false;
|
||||||
if (useBolusIOB() == YES) {
|
if (useBolusIOB() == YES) {
|
||||||
|
@ -130,8 +124,7 @@ public class QuickWizardEntry {
|
||||||
trend = true;
|
trend = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
wizard.doCalc(profile, tempTarget, carbs(), cob, bg, 0d, bolusIOB, basalIOB, superBolus, trend);
|
return new BolusWizard(profile, profileName, tempTarget, carbs(), cob, bg, 0d, 100, true, useCOB() == YES, bolusIOB, basalIOB, superBolus, useTempTarget() == YES, trend, "QuickWizard");
|
||||||
return wizard;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String buttonText() {
|
public String buttonText() {
|
||||||
|
|
|
@ -3,7 +3,7 @@ package info.nightscout.androidaps.db;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.database.DatabaseUtils;
|
import android.database.DatabaseUtils;
|
||||||
import android.database.sqlite.SQLiteDatabase;
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
import android.support.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper;
|
import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper;
|
||||||
import com.j256.ormlite.dao.CloseableIterator;
|
import com.j256.ormlite.dao.CloseableIterator;
|
||||||
|
@ -21,6 +21,8 @@ import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.GregorianCalendar;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
@ -29,6 +31,7 @@ import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import info.nightscout.androidaps.Constants;
|
import info.nightscout.androidaps.Constants;
|
||||||
import info.nightscout.androidaps.MainApp;
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
import info.nightscout.androidaps.plugins.bus.RxBus;
|
||||||
import info.nightscout.androidaps.data.OverlappingIntervals;
|
import info.nightscout.androidaps.data.OverlappingIntervals;
|
||||||
import info.nightscout.androidaps.data.Profile;
|
import info.nightscout.androidaps.data.Profile;
|
||||||
import info.nightscout.androidaps.data.ProfileStore;
|
import info.nightscout.androidaps.data.ProfileStore;
|
||||||
|
@ -410,6 +413,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
if (L.isEnabled(L.DATABASE))
|
if (L.isEnabled(L.DATABASE))
|
||||||
log.debug("Firing EventNewBg");
|
log.debug("Firing EventNewBg");
|
||||||
MainApp.bus().post(new EventNewBG(bgReading));
|
MainApp.bus().post(new EventNewBG(bgReading));
|
||||||
|
RxBus.INSTANCE.send(new EventNewBG(bgReading));
|
||||||
scheduledBgPost = null;
|
scheduledBgPost = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -434,7 +438,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
for (int i = 0; i < bgList.size(); i++)
|
for (int i = 0; i < bgList.size(); i++)
|
||||||
if (bgList.get(i).value > 39)
|
if (bgList.get(i).value >= 39)
|
||||||
return bgList.get(i);
|
return bgList.get(i);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -534,6 +538,24 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
return tddList;
|
return tddList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<TDD> getTDDsForLastXDays(int days) {
|
||||||
|
List<TDD> tddList;
|
||||||
|
GregorianCalendar gc = new GregorianCalendar();
|
||||||
|
gc.add(Calendar.DAY_OF_YEAR, (-1) * days);
|
||||||
|
|
||||||
|
try {
|
||||||
|
QueryBuilder<TDD, String> queryBuilder = getDaoTDD().queryBuilder();
|
||||||
|
queryBuilder.orderBy("date", false);
|
||||||
|
Where<TDD, String> where = queryBuilder.where();
|
||||||
|
where.ge("date", gc.getTimeInMillis());
|
||||||
|
PreparedQuery<TDD> preparedQuery = queryBuilder.prepare();
|
||||||
|
tddList = getDaoTDD().query(preparedQuery);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
log.error("Unhandled exception", e);
|
||||||
|
tddList = new ArrayList<>();
|
||||||
|
}
|
||||||
|
return tddList;
|
||||||
|
}
|
||||||
|
|
||||||
// ------------- DbRequests handling -------------------
|
// ------------- DbRequests handling -------------------
|
||||||
|
|
||||||
|
@ -596,7 +618,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------- TREATMENT HANDLING -------------------
|
// -------------------- TEMPTARGET HANDLING -------------------
|
||||||
|
|
||||||
public static void updateEarliestDataChange(long newDate) {
|
public static void updateEarliestDataChange(long newDate) {
|
||||||
if (earliestDataChange == null) {
|
if (earliestDataChange == null) {
|
||||||
|
@ -627,6 +649,23 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
return new ArrayList<TempTarget>();
|
return new ArrayList<TempTarget>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<TempTarget> getTemptargetsDataFromTime(long from, long to, boolean ascending) {
|
||||||
|
try {
|
||||||
|
Dao<TempTarget, Long> daoTempTargets = getDaoTempTargets();
|
||||||
|
List<TempTarget> tempTargets;
|
||||||
|
QueryBuilder<TempTarget, Long> queryBuilder = daoTempTargets.queryBuilder();
|
||||||
|
queryBuilder.orderBy("date", ascending);
|
||||||
|
Where where = queryBuilder.where();
|
||||||
|
where.between("date", from, to);
|
||||||
|
PreparedQuery<TempTarget> preparedQuery = queryBuilder.prepare();
|
||||||
|
tempTargets = daoTempTargets.query(preparedQuery);
|
||||||
|
return tempTargets;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
log.error("Unhandled exception", e);
|
||||||
|
}
|
||||||
|
return new ArrayList<TempTarget>();
|
||||||
|
}
|
||||||
|
|
||||||
public boolean createOrUpdate(TempTarget tempTarget) {
|
public boolean createOrUpdate(TempTarget tempTarget) {
|
||||||
try {
|
try {
|
||||||
TempTarget old;
|
TempTarget old;
|
||||||
|
@ -852,6 +891,31 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
log.debug("TEMPBASAL: Already exists from: " + Source.getString(tempBasal.source) + " " + tempBasal.toString());
|
log.debug("TEMPBASAL: Already exists from: " + Source.getString(tempBasal.source) + " " + tempBasal.toString());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// search by date (in case its standard record that has become pump record)
|
||||||
|
QueryBuilder<TemporaryBasal, Long> queryBuilder2 = getDaoTemporaryBasal().queryBuilder();
|
||||||
|
Where where2 = queryBuilder2.where();
|
||||||
|
where2.eq("date", tempBasal.date);
|
||||||
|
PreparedQuery<TemporaryBasal> preparedQuery2 = queryBuilder2.prepare();
|
||||||
|
List<TemporaryBasal> trList2 = getDaoTemporaryBasal().query(preparedQuery2);
|
||||||
|
|
||||||
|
if (trList2.size() > 0) {
|
||||||
|
old = trList2.get(0);
|
||||||
|
|
||||||
|
old.copyFromPump(tempBasal);
|
||||||
|
old.source = Source.PUMP;
|
||||||
|
|
||||||
|
if (L.isEnabled(L.DATABASE))
|
||||||
|
log.debug("TEMPBASAL: Updated record with Pump Data : " + Source.getString(tempBasal.source) + " " + tempBasal.toString());
|
||||||
|
|
||||||
|
getDaoTemporaryBasal().update(old);
|
||||||
|
|
||||||
|
updateEarliestDataChange(tempBasal.date);
|
||||||
|
scheduleTemporaryBasalChange();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
getDaoTemporaryBasal().create(tempBasal);
|
getDaoTemporaryBasal().create(tempBasal);
|
||||||
if (L.isEnabled(L.DATABASE))
|
if (L.isEnabled(L.DATABASE))
|
||||||
log.debug("TEMPBASAL: New record from: " + Source.getString(tempBasal.source) + " " + tempBasal.toString());
|
log.debug("TEMPBASAL: New record from: " + Source.getString(tempBasal.source) + " " + tempBasal.toString());
|
||||||
|
@ -950,6 +1014,22 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
return new ArrayList<TemporaryBasal>();
|
return new ArrayList<TemporaryBasal>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<TemporaryBasal> getTemporaryBasalsDataFromTime(long from, long to, boolean ascending) {
|
||||||
|
try {
|
||||||
|
List<TemporaryBasal> tempbasals;
|
||||||
|
QueryBuilder<TemporaryBasal, Long> queryBuilder = getDaoTemporaryBasal().queryBuilder();
|
||||||
|
queryBuilder.orderBy("date", ascending);
|
||||||
|
Where where = queryBuilder.where();
|
||||||
|
where.between("date", from, to);
|
||||||
|
PreparedQuery<TemporaryBasal> preparedQuery = queryBuilder.prepare();
|
||||||
|
tempbasals = getDaoTemporaryBasal().query(preparedQuery);
|
||||||
|
return tempbasals;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
log.error("Unhandled exception", e);
|
||||||
|
}
|
||||||
|
return new ArrayList<TemporaryBasal>();
|
||||||
|
}
|
||||||
|
|
||||||
private static void scheduleTemporaryBasalChange() {
|
private static void scheduleTemporaryBasalChange() {
|
||||||
class PostRunnable implements Runnable {
|
class PostRunnable implements Runnable {
|
||||||
public void run() {
|
public void run() {
|
||||||
|
@ -1076,6 +1156,29 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public TemporaryBasal findTempBasalByPumpId(Long pumpId) {
|
||||||
|
try {
|
||||||
|
QueryBuilder<TemporaryBasal, Long> queryBuilder = null;
|
||||||
|
queryBuilder = getDaoTemporaryBasal().queryBuilder();
|
||||||
|
queryBuilder.orderBy("date", false);
|
||||||
|
Where where = queryBuilder.where();
|
||||||
|
where.eq("pumpId", pumpId);
|
||||||
|
PreparedQuery<TemporaryBasal> preparedQuery = queryBuilder.prepare();
|
||||||
|
List<TemporaryBasal> list = getDaoTemporaryBasal().query(preparedQuery);
|
||||||
|
|
||||||
|
if (list.size() > 0)
|
||||||
|
return list.get(0);
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
|
||||||
|
} catch (SQLException e) {
|
||||||
|
log.error("Unhandled exception", e);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ------------ ExtendedBolus handling ---------------
|
// ------------ ExtendedBolus handling ---------------
|
||||||
|
|
||||||
public boolean createOrUpdate(ExtendedBolus extendedBolus) {
|
public boolean createOrUpdate(ExtendedBolus extendedBolus) {
|
||||||
|
@ -1354,6 +1457,23 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<CareportalEvent> getCareportalEvents(long start, long end, boolean ascending) {
|
||||||
|
try {
|
||||||
|
List<CareportalEvent> careportalEvents;
|
||||||
|
QueryBuilder<CareportalEvent, Long> queryBuilder = getDaoCareportalEvents().queryBuilder();
|
||||||
|
queryBuilder.orderBy("date", ascending);
|
||||||
|
Where where = queryBuilder.where();
|
||||||
|
where.between("date", start, end);
|
||||||
|
PreparedQuery<CareportalEvent> preparedQuery = queryBuilder.prepare();
|
||||||
|
careportalEvents = getDaoCareportalEvents().query(preparedQuery);
|
||||||
|
preprocessOpenAPSOfflineEvents(careportalEvents);
|
||||||
|
return careportalEvents;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
log.error("Unhandled exception", e);
|
||||||
|
}
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
public void preprocessOpenAPSOfflineEvents(List<CareportalEvent> list) {
|
public void preprocessOpenAPSOfflineEvents(List<CareportalEvent> list) {
|
||||||
OverlappingIntervals offlineEvents = new OverlappingIntervals();
|
OverlappingIntervals offlineEvents = new OverlappingIntervals();
|
||||||
for (int i = 0; i < list.size(); i++) {
|
for (int i = 0; i < list.size(); i++) {
|
||||||
|
@ -1507,6 +1627,24 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<ProfileSwitch> getProfileSwitchEventsFromTime(long from, long to, boolean ascending) {
|
||||||
|
try {
|
||||||
|
Dao<ProfileSwitch, Long> daoProfileSwitch = getDaoProfileSwitch();
|
||||||
|
List<ProfileSwitch> profileSwitches;
|
||||||
|
QueryBuilder<ProfileSwitch, Long> queryBuilder = daoProfileSwitch.queryBuilder();
|
||||||
|
queryBuilder.orderBy("date", ascending);
|
||||||
|
queryBuilder.limit(100L);
|
||||||
|
Where where = queryBuilder.where();
|
||||||
|
where.between("date", from, to);
|
||||||
|
PreparedQuery<ProfileSwitch> preparedQuery = queryBuilder.prepare();
|
||||||
|
profileSwitches = daoProfileSwitch.query(preparedQuery);
|
||||||
|
return profileSwitches;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
log.error("Unhandled exception", e);
|
||||||
|
}
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
public boolean createOrUpdate(ProfileSwitch profileSwitch) {
|
public boolean createOrUpdate(ProfileSwitch profileSwitch) {
|
||||||
try {
|
try {
|
||||||
ProfileSwitch old;
|
ProfileSwitch old;
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
package info.nightscout.androidaps.db;
|
||||||
|
|
||||||
|
public interface DbObjectBase {
|
||||||
|
|
||||||
|
long getDate();
|
||||||
|
|
||||||
|
long getPumpId();
|
||||||
|
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
package info.nightscout.androidaps.db;
|
package info.nightscout.androidaps.db;
|
||||||
|
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.support.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import com.j256.ormlite.field.DatabaseField;
|
import com.j256.ormlite.field.DatabaseField;
|
||||||
import com.j256.ormlite.table.DatabaseTable;
|
import com.j256.ormlite.table.DatabaseTable;
|
||||||
|
|
|
@ -6,9 +6,8 @@ import com.j256.ormlite.table.DatabaseTable;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.logging.L;
|
import info.nightscout.androidaps.logging.L;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by mike on 20.09.2017.
|
* Created by mike on 20.09.2017.
|
||||||
|
@ -45,4 +44,16 @@ public class TDD {
|
||||||
this.basal = basal;
|
this.basal = basal;
|
||||||
this.total = total;
|
this.total = total;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "TDD [" +
|
||||||
|
"date=" + date +
|
||||||
|
"date(str)=" + DateTimeUtil.toStringFromTimeInMillis(date) +
|
||||||
|
", bolus=" + bolus +
|
||||||
|
", basal=" + basal +
|
||||||
|
", total=" + total +
|
||||||
|
']';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,9 @@ import org.slf4j.LoggerFactory;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import info.nightscout.androidaps.Constants;
|
import info.nightscout.androidaps.Constants;
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
import info.nightscout.androidaps.R;
|
||||||
|
import info.nightscout.androidaps.data.Profile;
|
||||||
import info.nightscout.androidaps.interfaces.Interval;
|
import info.nightscout.androidaps.interfaces.Interval;
|
||||||
import info.nightscout.androidaps.logging.L;
|
import info.nightscout.androidaps.logging.L;
|
||||||
import info.nightscout.androidaps.utils.DateUtil;
|
import info.nightscout.androidaps.utils.DateUtil;
|
||||||
|
@ -191,4 +194,11 @@ public class TempTarget implements Interval {
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String friendlyDescription(String units) {
|
||||||
|
return Profile.toTargetRangeString(low, high, Constants.MGDL, units) +
|
||||||
|
units +
|
||||||
|
"@" + MainApp.gs(R.string.mins, durationInMinutes) +
|
||||||
|
(reason != null && !reason.equals("") ? "(" + reason + ")" : "");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ import info.nightscout.androidaps.utils.SP;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@DatabaseTable(tableName = DatabaseHelper.DATABASE_TEMPORARYBASALS)
|
@DatabaseTable(tableName = DatabaseHelper.DATABASE_TEMPORARYBASALS)
|
||||||
public class TemporaryBasal implements Interval {
|
public class TemporaryBasal implements Interval, DbObjectBase {
|
||||||
private static Logger log = LoggerFactory.getLogger(L.DATABASE);
|
private static Logger log = LoggerFactory.getLogger(L.DATABASE);
|
||||||
|
|
||||||
@DatabaseField(id = true)
|
@DatabaseField(id = true)
|
||||||
|
@ -156,6 +156,14 @@ public class TemporaryBasal implements Interval {
|
||||||
netExtendedRate = t.netExtendedRate;
|
netExtendedRate = t.netExtendedRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void copyFromPump(TemporaryBasal t) {
|
||||||
|
durationInMinutes = t.durationInMinutes;
|
||||||
|
isAbsolute = t.isAbsolute;
|
||||||
|
percentRate = t.percentRate;
|
||||||
|
absoluteRate = t.absoluteRate;
|
||||||
|
pumpId = t.pumpId;
|
||||||
|
}
|
||||||
|
|
||||||
// -------- Interval interface ---------
|
// -------- Interval interface ---------
|
||||||
|
|
||||||
Long cuttedEnd = null;
|
Long cuttedEnd = null;
|
||||||
|
@ -416,4 +424,13 @@ public class TemporaryBasal implements Interval {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getDate() {
|
||||||
|
return this.date;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getPumpId() {
|
||||||
|
return this.pumpId;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
package info.nightscout.androidaps.events;
|
||||||
|
|
||||||
|
public class EventCustomActionsChanged extends Event {
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
package info.nightscout.androidaps.events;
|
||||||
|
|
||||||
|
import android.location.Location;
|
||||||
|
|
||||||
|
public class EventLocationChange extends Event {
|
||||||
|
public Location location;
|
||||||
|
|
||||||
|
public EventLocationChange(Location location) {
|
||||||
|
this.location = location;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
package info.nightscout.androidaps.events;
|
package info.nightscout.androidaps.events;
|
||||||
|
|
||||||
import android.support.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import info.nightscout.androidaps.db.BgReading;
|
import info.nightscout.androidaps.db.BgReading;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package info.nightscout.androidaps.events;
|
package info.nightscout.androidaps.events;
|
||||||
|
|
||||||
import android.support.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import info.nightscout.androidaps.plugins.treatments.Treatment;
|
import info.nightscout.androidaps.plugins.treatments.Treatment;
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
package info.nightscout.androidaps.interfaces;
|
package info.nightscout.androidaps.interfaces;
|
||||||
|
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
import android.support.v4.app.FragmentActivity;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
|
import androidx.fragment.app.FragmentActivity;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.R;
|
||||||
|
import info.nightscout.androidaps.utils.SP;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ -42,6 +45,28 @@ public abstract class PluginBase {
|
||||||
pluginSwitcher.invoke();
|
pluginSwitcher.invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void confirmPumpPluginActivation(ConfigBuilderFragment.PluginViewHolder.PluginSwitcher pluginSwitcher, FragmentActivity activity) {
|
||||||
|
boolean allowHardwarePump = SP.getBoolean("allow_hardware_pump", false);
|
||||||
|
if (allowHardwarePump || activity == null) {
|
||||||
|
pluginSwitcher.invoke();
|
||||||
|
} else {
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||||
|
builder.setMessage(R.string.allow_hardware_pump_text)
|
||||||
|
.setPositiveButton(R.string.yes, (dialog, id) -> {
|
||||||
|
pluginSwitcher.invoke();
|
||||||
|
SP.putBoolean("allow_hardware_pump", true);
|
||||||
|
if (L.isEnabled(L.PUMP))
|
||||||
|
log.debug("First time HW pump allowed!");
|
||||||
|
})
|
||||||
|
.setNegativeButton(R.string.cancel, (dialog, id) -> {
|
||||||
|
pluginSwitcher.cancel();
|
||||||
|
if (L.isEnabled(L.PUMP))
|
||||||
|
log.debug("User does not allow switching to HW pump!");
|
||||||
|
});
|
||||||
|
builder.create().show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// public PluginType getType() {
|
// public PluginType getType() {
|
||||||
// return mainType;
|
// return mainType;
|
||||||
// }
|
// }
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package info.nightscout.androidaps.interfaces;
|
package info.nightscout.androidaps.interfaces;
|
||||||
|
|
||||||
import android.support.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import info.nightscout.androidaps.data.ProfileStore;
|
import info.nightscout.androidaps.data.ProfileStore;
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,10 @@ import java.util.List;
|
||||||
import info.nightscout.androidaps.data.DetailedBolusInfo;
|
import info.nightscout.androidaps.data.DetailedBolusInfo;
|
||||||
import info.nightscout.androidaps.data.Profile;
|
import info.nightscout.androidaps.data.Profile;
|
||||||
import info.nightscout.androidaps.data.PumpEnactResult;
|
import info.nightscout.androidaps.data.PumpEnactResult;
|
||||||
|
import info.nightscout.androidaps.plugins.common.ManufacturerType;
|
||||||
import info.nightscout.androidaps.plugins.general.actions.defs.CustomAction;
|
import info.nightscout.androidaps.plugins.general.actions.defs.CustomAction;
|
||||||
import info.nightscout.androidaps.plugins.general.actions.defs.CustomActionType;
|
import info.nightscout.androidaps.plugins.general.actions.defs.CustomActionType;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by mike on 04.06.2016.
|
* Created by mike on 04.06.2016.
|
||||||
|
@ -53,7 +55,9 @@ public interface PumpInterface {
|
||||||
|
|
||||||
// Status to be passed to NS
|
// Status to be passed to NS
|
||||||
JSONObject getJSONStatus(Profile profile, String profileName);
|
JSONObject getJSONStatus(Profile profile, String profileName);
|
||||||
String deviceID();
|
ManufacturerType manufacturer();
|
||||||
|
PumpType model();
|
||||||
|
String serialNumber();
|
||||||
|
|
||||||
// Pump capabilities
|
// Pump capabilities
|
||||||
PumpDescription getPumpDescription();
|
PumpDescription getPumpDescription();
|
||||||
|
@ -71,4 +75,10 @@ public interface PumpInterface {
|
||||||
|
|
||||||
void executeCustomAction(CustomActionType customActionType);
|
void executeCustomAction(CustomActionType customActionType);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method will be called when time or Timezone changes, and pump driver can then do a specific action (for
|
||||||
|
* example update clock on pump).
|
||||||
|
*/
|
||||||
|
void timeDateOrTimeZoneChanged();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import java.util.List;
|
||||||
import info.nightscout.androidaps.data.DetailedBolusInfo;
|
import info.nightscout.androidaps.data.DetailedBolusInfo;
|
||||||
import info.nightscout.androidaps.data.IobTotal;
|
import info.nightscout.androidaps.data.IobTotal;
|
||||||
import info.nightscout.androidaps.data.MealData;
|
import info.nightscout.androidaps.data.MealData;
|
||||||
|
import info.nightscout.androidaps.data.NonOverlappingIntervals;
|
||||||
import info.nightscout.androidaps.data.Profile;
|
import info.nightscout.androidaps.data.Profile;
|
||||||
import info.nightscout.androidaps.db.ExtendedBolus;
|
import info.nightscout.androidaps.db.ExtendedBolus;
|
||||||
import info.nightscout.androidaps.db.ProfileSwitch;
|
import info.nightscout.androidaps.db.ProfileSwitch;
|
||||||
|
@ -31,6 +32,7 @@ public interface TreatmentsInterface {
|
||||||
|
|
||||||
List<Treatment> getTreatmentsFromHistory();
|
List<Treatment> getTreatmentsFromHistory();
|
||||||
List<Treatment> getTreatments5MinBackFromHistory(long time);
|
List<Treatment> getTreatments5MinBackFromHistory(long time);
|
||||||
|
List<Treatment> getTreatmentsFromHistoryAfterTimestamp(long timestamp);
|
||||||
long getLastBolusTime();
|
long getLastBolusTime();
|
||||||
|
|
||||||
// real basals (not faked by extended bolus)
|
// real basals (not faked by extended bolus)
|
||||||
|
@ -42,7 +44,7 @@ public interface TreatmentsInterface {
|
||||||
// basal that can be faked by extended boluses
|
// basal that can be faked by extended boluses
|
||||||
boolean isTempBasalInProgress();
|
boolean isTempBasalInProgress();
|
||||||
TemporaryBasal getTempBasalFromHistory(long time);
|
TemporaryBasal getTempBasalFromHistory(long time);
|
||||||
Intervals<TemporaryBasal> getTemporaryBasalsFromHistory();
|
NonOverlappingIntervals<TemporaryBasal> getTemporaryBasalsFromHistory();
|
||||||
|
|
||||||
boolean isInHistoryExtendedBoluslInProgress();
|
boolean isInHistoryExtendedBoluslInProgress();
|
||||||
ExtendedBolus getExtendedBolusFromHistory(long time);
|
ExtendedBolus getExtendedBolusFromHistory(long time);
|
||||||
|
|
|
@ -77,6 +77,7 @@ public class L {
|
||||||
|
|
||||||
public static final String CORE = "CORE";
|
public static final String CORE = "CORE";
|
||||||
public static final String AUTOSENS = "AUTOSENS";
|
public static final String AUTOSENS = "AUTOSENS";
|
||||||
|
public static final String AUTOMATION = "AUTOMATION";
|
||||||
public static final String EVENTS = "EVENTS";
|
public static final String EVENTS = "EVENTS";
|
||||||
public static final String GLUCOSE = "GLUCOSE";
|
public static final String GLUCOSE = "GLUCOSE";
|
||||||
public static final String BGSOURCE = "BGSOURCE";
|
public static final String BGSOURCE = "BGSOURCE";
|
||||||
|
@ -87,6 +88,7 @@ public class L {
|
||||||
public static final String DATAFOOD = "DATAFOOD";
|
public static final String DATAFOOD = "DATAFOOD";
|
||||||
public static final String DATATREATMENTS = "DATATREATMENTS";
|
public static final String DATATREATMENTS = "DATATREATMENTS";
|
||||||
public static final String NSCLIENT = "NSCLIENT";
|
public static final String NSCLIENT = "NSCLIENT";
|
||||||
|
public static final String TIDEPOOL = "TIDEPOOL";
|
||||||
public static final String CONSTRAINTS = "CONSTRAINTS";
|
public static final String CONSTRAINTS = "CONSTRAINTS";
|
||||||
public static final String PUMP = "PUMP";
|
public static final String PUMP = "PUMP";
|
||||||
public static final String PUMPQUEUE = "PUMPQUEUE";
|
public static final String PUMPQUEUE = "PUMPQUEUE";
|
||||||
|
@ -96,11 +98,13 @@ public class L {
|
||||||
public static final String PROFILE = "PROFILE";
|
public static final String PROFILE = "PROFILE";
|
||||||
public static final String CONFIGBUILDER = "CONFIGBUILDER";
|
public static final String CONFIGBUILDER = "CONFIGBUILDER";
|
||||||
public static final String UI = "UI";
|
public static final String UI = "UI";
|
||||||
|
public static final String LOCATION = "LOCATION";
|
||||||
public static final String SMS = "SMS";
|
public static final String SMS = "SMS";
|
||||||
|
|
||||||
private static void initialize() {
|
private static void initialize() {
|
||||||
logElements = new ArrayList<>();
|
logElements = new ArrayList<>();
|
||||||
logElements.add(new LogElement(APS, true));
|
logElements.add(new LogElement(APS, true));
|
||||||
|
logElements.add(new LogElement(AUTOMATION, true));
|
||||||
logElements.add(new LogElement(AUTOSENS, false));
|
logElements.add(new LogElement(AUTOSENS, false));
|
||||||
logElements.add(new LogElement(BGSOURCE, true));
|
logElements.add(new LogElement(BGSOURCE, true));
|
||||||
logElements.add(new LogElement(GLUCOSE, false));
|
logElements.add(new LogElement(GLUCOSE, false));
|
||||||
|
@ -112,8 +116,10 @@ public class L {
|
||||||
logElements.add(new LogElement(DATASERVICE, true));
|
logElements.add(new LogElement(DATASERVICE, true));
|
||||||
logElements.add(new LogElement(DATATREATMENTS, true));
|
logElements.add(new LogElement(DATATREATMENTS, true));
|
||||||
logElements.add(new LogElement(EVENTS, false, true));
|
logElements.add(new LogElement(EVENTS, false, true));
|
||||||
|
logElements.add(new LogElement(LOCATION, true));
|
||||||
logElements.add(new LogElement(NOTIFICATION, true));
|
logElements.add(new LogElement(NOTIFICATION, true));
|
||||||
logElements.add(new LogElement(NSCLIENT, true));
|
logElements.add(new LogElement(NSCLIENT, true));
|
||||||
|
logElements.add(new LogElement(TIDEPOOL, true));
|
||||||
logElements.add(new LogElement(OVERVIEW, true));
|
logElements.add(new LogElement(OVERVIEW, true));
|
||||||
logElements.add(new LogElement(PROFILE, true));
|
logElements.add(new LogElement(PROFILE, true));
|
||||||
logElements.add(new LogElement(PUMP, true));
|
logElements.add(new LogElement(PUMP, true));
|
||||||
|
|
|
@ -10,8 +10,8 @@ import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
import android.support.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import android.support.v4.app.NotificationCompat;
|
import androidx.core.app.NotificationCompat;
|
||||||
|
|
||||||
import com.squareup.otto.Subscribe;
|
import com.squareup.otto.Subscribe;
|
||||||
|
|
||||||
|
@ -644,6 +644,17 @@ public class LoopPlugin extends PluginBase {
|
||||||
TreatmentsInterface activeTreatments = TreatmentsPlugin.getPlugin();
|
TreatmentsInterface activeTreatments = TreatmentsPlugin.getPlugin();
|
||||||
|
|
||||||
LoopPlugin.getPlugin().disconnectTo(System.currentTimeMillis() + durationInMinutes * 60 * 1000L);
|
LoopPlugin.getPlugin().disconnectTo(System.currentTimeMillis() + durationInMinutes * 60 * 1000L);
|
||||||
|
|
||||||
|
if (pump.getPumpDescription().tempBasalStyle == PumpDescription.ABSOLUTE) {
|
||||||
|
ConfigBuilderPlugin.getPlugin().getCommandQueue().tempBasalAbsolute(0, durationInMinutes, true, profile, new Callback() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (!result.success) {
|
||||||
|
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.tempbasaldeliveryerror));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
ConfigBuilderPlugin.getPlugin().getCommandQueue().tempBasalPercent(0, durationInMinutes, true, profile, new Callback() {
|
ConfigBuilderPlugin.getPlugin().getCommandQueue().tempBasalPercent(0, durationInMinutes, true, profile, new Callback() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
@ -652,6 +663,8 @@ public class LoopPlugin extends PluginBase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (pump.getPumpDescription().isExtendedBolusCapable && activeTreatments.isInHistoryExtendedBoluslInProgress()) {
|
if (pump.getPumpDescription().isExtendedBolusCapable && activeTreatments.isInHistoryExtendedBoluslInProgress()) {
|
||||||
ConfigBuilderPlugin.getPlugin().getCommandQueue().cancelExtended(new Callback() {
|
ConfigBuilderPlugin.getPlugin().getCommandQueue().cancelExtended(new Callback() {
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
package info.nightscout.androidaps.plugins.bus
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.events.Event
|
||||||
|
import io.reactivex.Observable
|
||||||
|
import io.reactivex.schedulers.Schedulers
|
||||||
|
import io.reactivex.subjects.PublishSubject
|
||||||
|
|
||||||
|
// Use object so we have a singleton instance
|
||||||
|
object RxBus {
|
||||||
|
|
||||||
|
private val publisher = PublishSubject.create<Event>()
|
||||||
|
|
||||||
|
fun send(event: Event) {
|
||||||
|
publisher.onNext(event)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Listen should return an Observable and not the publisher
|
||||||
|
// Using ofType we filter only events that match that class type
|
||||||
|
fun <T> toObservable(eventType: Class<T>): Observable<T> =
|
||||||
|
publisher
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.ofType(eventType)
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package info.nightscout.androidaps.plugins.common;
|
||||||
|
|
||||||
|
public enum ManufacturerType {
|
||||||
|
|
||||||
|
AndroidAPS("AndroidAPS"),
|
||||||
|
Medtronic("Medtronic"),
|
||||||
|
Sooil("SOOIL"),
|
||||||
|
|
||||||
|
Tandem("Tandem"),
|
||||||
|
Insulet("Insulet"),
|
||||||
|
Animas("Animas"), Cellnovo("Cellnovo"), Roche("Roche");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
ManufacturerType(String description) {
|
||||||
|
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
package info.nightscout.androidaps.plugins.common;
|
package info.nightscout.androidaps.plugins.common;
|
||||||
|
|
||||||
import android.support.v4.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
|
|
||||||
import butterknife.Unbinder;
|
import butterknife.Unbinder;
|
||||||
import info.nightscout.androidaps.MainApp;
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
|
|
@ -3,8 +3,8 @@ package info.nightscout.androidaps.plugins.configBuilder;
|
||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import android.support.annotation.StringRes;
|
import androidx.annotation.StringRes;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package info.nightscout.androidaps.plugins.configBuilder;
|
package info.nightscout.androidaps.plugins.configBuilder;
|
||||||
|
|
||||||
import android.support.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
@ -232,26 +232,32 @@ public class ConfigBuilderPlugin extends PluginBase {
|
||||||
return commandQueue;
|
return commandQueue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public BgSourceInterface getActiveBgSource() {
|
public BgSourceInterface getActiveBgSource() {
|
||||||
return activeBgSource;
|
return activeBgSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public ProfileInterface getActiveProfileInterface() {
|
public ProfileInterface getActiveProfileInterface() {
|
||||||
return activeProfile;
|
return activeProfile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public InsulinInterface getActiveInsulin() {
|
public InsulinInterface getActiveInsulin() {
|
||||||
return activeInsulin;
|
return activeInsulin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public APSInterface getActiveAPS() {
|
public APSInterface getActiveAPS() {
|
||||||
return activeAPS;
|
return activeAPS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public PumpInterface getActivePump() {
|
public PumpInterface getActivePump() {
|
||||||
return activePump;
|
return activePump;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public SensitivityInterface getActiveSensitivity() {
|
public SensitivityInterface getActiveSensitivity() {
|
||||||
return activeSensitivity;
|
return activeSensitivity;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package info.nightscout.androidaps.plugins.configBuilder;
|
package info.nightscout.androidaps.plugins.configBuilder;
|
||||||
|
|
||||||
import android.support.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
|
@ -2,7 +2,7 @@ package info.nightscout.androidaps.plugins.configBuilder;
|
||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import com.google.firebase.analytics.FirebaseAnalytics;
|
import com.google.firebase.analytics.FirebaseAnalytics;
|
||||||
import com.squareup.otto.Subscribe;
|
import com.squareup.otto.Subscribe;
|
||||||
|
|
|
@ -4,11 +4,11 @@ import android.app.Activity;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.support.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import android.support.v7.widget.CardView;
|
import androidx.cardview.widget.CardView;
|
||||||
import android.support.v7.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import android.support.v7.widget.LinearSmoothScroller;
|
import androidx.recyclerview.widget.LinearSmoothScroller;
|
||||||
import android.support.v7.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
import android.text.Html;
|
import android.text.Html;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package info.nightscout.androidaps.plugins.constraints.objectives.objectives;
|
package info.nightscout.androidaps.plugins.constraints.objectives.objectives;
|
||||||
|
|
||||||
import android.support.annotation.StringRes;
|
import androidx.annotation.StringRes;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
|
@ -13,10 +13,10 @@ import info.nightscout.androidaps.interfaces.PluginDescription;
|
||||||
import info.nightscout.androidaps.interfaces.PluginType;
|
import info.nightscout.androidaps.interfaces.PluginType;
|
||||||
import info.nightscout.androidaps.interfaces.PumpDescription;
|
import info.nightscout.androidaps.interfaces.PumpDescription;
|
||||||
import info.nightscout.androidaps.interfaces.PumpInterface;
|
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||||
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
|
|
||||||
import info.nightscout.androidaps.plugins.aps.openAPSAMA.OpenAPSAMAPlugin;
|
import info.nightscout.androidaps.plugins.aps.openAPSAMA.OpenAPSAMAPlugin;
|
||||||
import info.nightscout.androidaps.plugins.aps.openAPSMA.OpenAPSMAPlugin;
|
import info.nightscout.androidaps.plugins.aps.openAPSMA.OpenAPSMAPlugin;
|
||||||
import info.nightscout.androidaps.plugins.aps.openAPSSMB.OpenAPSSMBPlugin;
|
import info.nightscout.androidaps.plugins.aps.openAPSSMB.OpenAPSSMBPlugin;
|
||||||
|
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
|
||||||
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification;
|
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification;
|
||||||
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification;
|
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification;
|
||||||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin;
|
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin;
|
||||||
|
@ -196,7 +196,7 @@ public class SafetyPlugin extends PluginBase implements ConstraintsInterface {
|
||||||
|
|
||||||
PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump();
|
PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump();
|
||||||
if (pump != null) {
|
if (pump != null) {
|
||||||
double rounded = Round.roundTo(insulin.value(), pump.getPumpDescription().pumpType.determineCorrectBolusSize(insulin.value()));
|
double rounded = pump.getPumpDescription().pumpType.determineCorrectBolusSize(insulin.value());
|
||||||
insulin.setIfDifferent(rounded, MainApp.gs(R.string.pumplimit), this);
|
insulin.setIfDifferent(rounded, MainApp.gs(R.string.pumplimit), this);
|
||||||
}
|
}
|
||||||
return insulin;
|
return insulin;
|
||||||
|
@ -213,7 +213,7 @@ public class SafetyPlugin extends PluginBase implements ConstraintsInterface {
|
||||||
|
|
||||||
PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump();
|
PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump();
|
||||||
if (pump != null) {
|
if (pump != null) {
|
||||||
double rounded = Round.roundTo(insulin.value(), pump.getPumpDescription().pumpType.determineCorrectExtendedBolusSize(insulin.value()));
|
double rounded = pump.getPumpDescription().pumpType.determineCorrectExtendedBolusSize(insulin.value());
|
||||||
insulin.setIfDifferent(rounded, MainApp.gs(R.string.pumplimit), this);
|
insulin.setIfDifferent(rounded, MainApp.gs(R.string.pumplimit), this);
|
||||||
}
|
}
|
||||||
return insulin;
|
return insulin;
|
||||||
|
|
|
@ -5,8 +5,8 @@ import android.app.Activity;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v4.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import android.support.v4.app.FragmentManager;
|
import androidx.fragment.app.FragmentManager;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
@ -26,6 +26,7 @@ import info.nightscout.androidaps.activities.HistoryBrowseActivity;
|
||||||
import info.nightscout.androidaps.activities.TDDStatsActivity;
|
import info.nightscout.androidaps.activities.TDDStatsActivity;
|
||||||
import info.nightscout.androidaps.db.ExtendedBolus;
|
import info.nightscout.androidaps.db.ExtendedBolus;
|
||||||
import info.nightscout.androidaps.db.TemporaryBasal;
|
import info.nightscout.androidaps.db.TemporaryBasal;
|
||||||
|
import info.nightscout.androidaps.events.EventCustomActionsChanged;
|
||||||
import info.nightscout.androidaps.events.EventExtendedBolusChange;
|
import info.nightscout.androidaps.events.EventExtendedBolusChange;
|
||||||
import info.nightscout.androidaps.events.EventInitializationChanged;
|
import info.nightscout.androidaps.events.EventInitializationChanged;
|
||||||
import info.nightscout.androidaps.events.EventRefreshOverview;
|
import info.nightscout.androidaps.events.EventRefreshOverview;
|
||||||
|
@ -133,6 +134,11 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL
|
||||||
updateGUI();
|
updateGUI();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onStatusEvent(final EventCustomActionsChanged ev) {
|
||||||
|
updateGUI();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void updateGUI() {
|
protected void updateGUI() {
|
||||||
Activity activity = getActivity();
|
Activity activity = getActivity();
|
||||||
|
@ -247,6 +253,9 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL
|
||||||
|
|
||||||
for (CustomAction customAction : customActions) {
|
for (CustomAction customAction : customActions) {
|
||||||
|
|
||||||
|
if (!customAction.isEnabled())
|
||||||
|
continue;
|
||||||
|
|
||||||
SingleClickButton btn = new SingleClickButton(getContext(), null, android.R.attr.buttonStyle);
|
SingleClickButton btn = new SingleClickButton(getContext(), null, android.R.attr.buttonStyle);
|
||||||
btn.setText(MainApp.gs(customAction.getName()));
|
btn.setText(MainApp.gs(customAction.getName()));
|
||||||
|
|
||||||
|
@ -264,10 +273,8 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL
|
||||||
|
|
||||||
this.pumpCustomActions.put(MainApp.gs(customAction.getName()), customAction);
|
this.pumpCustomActions.put(MainApp.gs(customAction.getName()), customAction);
|
||||||
this.pumpCustomButtons.add(btn);
|
this.pumpCustomButtons.add(btn);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -283,7 +290,6 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL
|
||||||
}
|
}
|
||||||
|
|
||||||
pumpCustomButtons.clear();
|
pumpCustomButtons.clear();
|
||||||
pumpCustomActions.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -12,31 +12,36 @@ public class CustomAction {
|
||||||
private String iconName;
|
private String iconName;
|
||||||
private CustomActionType customActionType;
|
private CustomActionType customActionType;
|
||||||
private int iconResourceId;
|
private int iconResourceId;
|
||||||
|
private boolean enabled = true;
|
||||||
|
|
||||||
|
|
||||||
public CustomAction(int nameResourceId, CustomActionType actionType) {
|
public CustomAction(int nameResourceId, CustomActionType actionType) {
|
||||||
this.name = nameResourceId;
|
this(nameResourceId, actionType, R.drawable.icon_actions_profileswitch, true);
|
||||||
this.customActionType = actionType;
|
|
||||||
this.iconResourceId = R.drawable.icon_actions_profileswitch;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public CustomAction(int nameResourceId, CustomActionType actionType, int iconResourceId) {
|
public CustomAction(int nameResourceId, CustomActionType actionType, int iconResourceId) {
|
||||||
|
this(nameResourceId, actionType, iconResourceId, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CustomAction(int nameResourceId, CustomActionType actionType, boolean enabled) {
|
||||||
|
this(nameResourceId, actionType, R.drawable.icon_actions_profileswitch, enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CustomAction(int nameResourceId, CustomActionType actionType, int iconResourceId, boolean enabled) {
|
||||||
this.name = nameResourceId;
|
this.name = nameResourceId;
|
||||||
this.customActionType = actionType;
|
this.customActionType = actionType;
|
||||||
this.iconResourceId = iconResourceId;
|
this.iconResourceId = iconResourceId;
|
||||||
|
this.enabled = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public int getName() {
|
public int getName() {
|
||||||
|
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public CustomActionType getCustomActionType() {
|
public CustomActionType getCustomActionType() {
|
||||||
|
|
||||||
return customActionType;
|
return customActionType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,4 +49,15 @@ public class CustomAction {
|
||||||
public int getIconResourceId() {
|
public int getIconResourceId() {
|
||||||
return iconResourceId;
|
return iconResourceId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean isEnabled() {
|
||||||
|
return enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setEnabled(boolean enabled) {
|
||||||
|
this.enabled = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,8 @@ package info.nightscout.androidaps.plugins.general.actions.dialogs;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v4.app.DialogFragment;
|
import androidx.fragment.app.DialogFragment;
|
||||||
import android.support.v7.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
import android.text.Html;
|
import android.text.Html;
|
||||||
import android.text.TextWatcher;
|
import android.text.TextWatcher;
|
||||||
|
@ -103,7 +103,7 @@ public class FillDialog extends DialogFragment implements OnClickListener {
|
||||||
Double maxInsulin = MainApp.getConstraintChecker().getMaxBolusAllowed().value();
|
Double maxInsulin = MainApp.getConstraintChecker().getMaxBolusAllowed().value();
|
||||||
double bolusstep = ConfigBuilderPlugin.getPlugin().getActivePump().getPumpDescription().bolusStep;
|
double bolusstep = ConfigBuilderPlugin.getPlugin().getActivePump().getPumpDescription().bolusStep;
|
||||||
editInsulin = view.findViewById(R.id.fill_insulinamount);
|
editInsulin = view.findViewById(R.id.fill_insulinamount);
|
||||||
editInsulin.setParams(0d, 0d, maxInsulin, bolusstep, DecimalFormatter.pumpSupportedBolusFormat(), false, textWatcher);
|
editInsulin.setParams(0d, 0d, maxInsulin, bolusstep, DecimalFormatter.pumpSupportedBolusFormat(), false, view.findViewById(R.id.ok), textWatcher);
|
||||||
|
|
||||||
|
|
||||||
Button preset1Button = view.findViewById(R.id.fill_preset_button1);
|
Button preset1Button = view.findViewById(R.id.fill_preset_button1);
|
||||||
|
@ -184,7 +184,7 @@ public class FillDialog extends DialogFragment implements OnClickListener {
|
||||||
confirmMessage.add("");
|
confirmMessage.add("");
|
||||||
confirmMessage.add(MainApp.gs(R.string.bolus) + ": " + "<font color='" + MainApp.gc(R.color.colorCarbsButton) + "'>" + DecimalFormatter.toPumpSupportedBolus(insulinAfterConstraints) + "U" + "</font>");
|
confirmMessage.add(MainApp.gs(R.string.bolus) + ": " + "<font color='" + MainApp.gc(R.color.colorCarbsButton) + "'>" + DecimalFormatter.toPumpSupportedBolus(insulinAfterConstraints) + "U" + "</font>");
|
||||||
if (Math.abs(insulinAfterConstraints - insulin) > 0.01d)
|
if (Math.abs(insulinAfterConstraints - insulin) > 0.01d)
|
||||||
confirmMessage.add("<font color='" + MainApp.gc(R.color.low) + "'>" + MainApp.gs(R.string.bolusconstraintapplied) + "</font>");
|
confirmMessage.add(MainApp.gs(R.string.bolusconstraintappliedwarning, MainApp.gc(R.color.warning), insulin, insulinAfterConstraints));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pumpSiteChangeCheckbox.isChecked())
|
if (pumpSiteChangeCheckbox.isChecked())
|
||||||
|
|
|
@ -4,8 +4,8 @@ import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v4.app.DialogFragment;
|
import androidx.fragment.app.DialogFragment;
|
||||||
import android.support.v7.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
@ -42,12 +42,12 @@ public class NewExtendedBolusDialog extends DialogFragment implements View.OnCli
|
||||||
|
|
||||||
Double maxInsulin = MainApp.getConstraintChecker().getMaxExtendedBolusAllowed().value();
|
Double maxInsulin = MainApp.getConstraintChecker().getMaxExtendedBolusAllowed().value();
|
||||||
editInsulin = (NumberPicker) view.findViewById(R.id.overview_newextendedbolus_insulin);
|
editInsulin = (NumberPicker) view.findViewById(R.id.overview_newextendedbolus_insulin);
|
||||||
editInsulin.setParams(0d, 0d, maxInsulin, 0.1d, new DecimalFormat("0.00"), false);
|
editInsulin.setParams(0d, 0d, maxInsulin, 0.1d, new DecimalFormat("0.00"), false, view.findViewById(R.id.ok));
|
||||||
|
|
||||||
double extendedDurationStep = ConfigBuilderPlugin.getPlugin().getActivePump().getPumpDescription().extendedBolusDurationStep;
|
double extendedDurationStep = ConfigBuilderPlugin.getPlugin().getActivePump().getPumpDescription().extendedBolusDurationStep;
|
||||||
double extendedMaxDuration = ConfigBuilderPlugin.getPlugin().getActivePump().getPumpDescription().extendedBolusMaxDuration;
|
double extendedMaxDuration = ConfigBuilderPlugin.getPlugin().getActivePump().getPumpDescription().extendedBolusMaxDuration;
|
||||||
editDuration = (NumberPicker) view.findViewById(R.id.overview_newextendedbolus_duration);
|
editDuration = (NumberPicker) view.findViewById(R.id.overview_newextendedbolus_duration);
|
||||||
editDuration.setParams(extendedDurationStep, extendedDurationStep, extendedMaxDuration, extendedDurationStep, new DecimalFormat("0"), false);
|
editDuration.setParams(extendedDurationStep, extendedDurationStep, extendedMaxDuration, extendedDurationStep, new DecimalFormat("0"), false, view.findViewById(R.id.ok));
|
||||||
|
|
||||||
view.findViewById(R.id.ok).setOnClickListener(this);
|
view.findViewById(R.id.ok).setOnClickListener(this);
|
||||||
view.findViewById(R.id.cancel).setOnClickListener(this);
|
view.findViewById(R.id.cancel).setOnClickListener(this);
|
||||||
|
|
|
@ -3,8 +3,8 @@ package info.nightscout.androidaps.plugins.general.actions.dialogs;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v4.app.DialogFragment;
|
import androidx.fragment.app.DialogFragment;
|
||||||
import android.support.v7.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
@ -66,17 +66,17 @@ public class NewTempBasalDialog extends DialogFragment implements View.OnClickLi
|
||||||
basalPercent = (NumberPicker) view.findViewById(R.id.overview_newtempbasal_basalpercentinput);
|
basalPercent = (NumberPicker) view.findViewById(R.id.overview_newtempbasal_basalpercentinput);
|
||||||
double maxTempPercent = pumpDescription.maxTempPercent;
|
double maxTempPercent = pumpDescription.maxTempPercent;
|
||||||
double tempPercentStep = pumpDescription.tempPercentStep;
|
double tempPercentStep = pumpDescription.tempPercentStep;
|
||||||
basalPercent.setParams(100d, 0d, maxTempPercent, tempPercentStep, new DecimalFormat("0"), true);
|
basalPercent.setParams(100d, 0d, maxTempPercent, tempPercentStep, new DecimalFormat("0"), true, view.findViewById(R.id.ok));
|
||||||
|
|
||||||
Profile profile = ProfileFunctions.getInstance().getProfile();
|
Profile profile = ProfileFunctions.getInstance().getProfile();
|
||||||
Double currentBasal = profile != null ? profile.getBasal() : 0d;
|
Double currentBasal = profile != null ? profile.getBasal() : 0d;
|
||||||
basalAbsolute = (NumberPicker) view.findViewById(R.id.overview_newtempbasal_basalabsoluteinput);
|
basalAbsolute = (NumberPicker) view.findViewById(R.id.overview_newtempbasal_basalabsoluteinput);
|
||||||
basalAbsolute.setParams(currentBasal, 0d, pumpDescription.maxTempAbsolute, pumpDescription.tempAbsoluteStep, new DecimalFormat("0.00"), true);
|
basalAbsolute.setParams(currentBasal, 0d, pumpDescription.maxTempAbsolute, pumpDescription.tempAbsoluteStep, new DecimalFormat("0.00"), true, view.findViewById(R.id.ok));
|
||||||
|
|
||||||
double tempDurationStep = pumpDescription.tempDurationStep;
|
double tempDurationStep = pumpDescription.tempDurationStep;
|
||||||
double tempMaxDuration = pumpDescription.tempMaxDuration;
|
double tempMaxDuration = pumpDescription.tempMaxDuration;
|
||||||
duration = (NumberPicker) view.findViewById(R.id.overview_newtempbasal_duration);
|
duration = (NumberPicker) view.findViewById(R.id.overview_newtempbasal_duration);
|
||||||
duration.setParams(tempDurationStep, tempDurationStep, tempMaxDuration, tempDurationStep, new DecimalFormat("0"), false);
|
duration.setParams(tempDurationStep, tempDurationStep, tempMaxDuration, tempDurationStep, new DecimalFormat("0"), false, view.findViewById(R.id.ok));
|
||||||
|
|
||||||
if ((pumpDescription.tempBasalStyle & PumpDescription.PERCENT) == PumpDescription.PERCENT && (pumpDescription.tempBasalStyle & PumpDescription.ABSOLUTE) == PumpDescription.ABSOLUTE) {
|
if ((pumpDescription.tempBasalStyle & PumpDescription.PERCENT) == PumpDescription.PERCENT && (pumpDescription.tempBasalStyle & PumpDescription.ABSOLUTE) == PumpDescription.ABSOLUTE) {
|
||||||
// Both allowed
|
// Both allowed
|
||||||
|
|
|
@ -0,0 +1,90 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.actions.Action;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.triggers.Trigger;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerConnector;
|
||||||
|
|
||||||
|
public class AutomationEvent {
|
||||||
|
|
||||||
|
private Trigger trigger = new TriggerConnector();
|
||||||
|
private List<Action> actions = new ArrayList<>();
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
public void setTitle(String title) {
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTrigger(Trigger trigger) {
|
||||||
|
this.trigger = trigger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Trigger getTrigger() {
|
||||||
|
return trigger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Action> getActions() {
|
||||||
|
return actions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TriggerConnector getPreconditions() {
|
||||||
|
TriggerConnector trigger = new TriggerConnector(TriggerConnector.Type.AND);
|
||||||
|
for (Action action : actions) {
|
||||||
|
if (action.precondition != null)
|
||||||
|
trigger.add(action.precondition);
|
||||||
|
}
|
||||||
|
return trigger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addAction(Action action) {
|
||||||
|
actions.add(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toJSON() {
|
||||||
|
JSONObject o = new JSONObject();
|
||||||
|
try {
|
||||||
|
// title
|
||||||
|
o.put("title", title);
|
||||||
|
// trigger
|
||||||
|
o.put("trigger", trigger.toJSON());
|
||||||
|
// actions
|
||||||
|
JSONArray array = new JSONArray();
|
||||||
|
for (Action a : actions) {
|
||||||
|
array.put(a.toJSON());
|
||||||
|
}
|
||||||
|
o.put("actions", array);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return o.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public AutomationEvent fromJSON(String data) {
|
||||||
|
try {
|
||||||
|
JSONObject d = new JSONObject(data);
|
||||||
|
// title
|
||||||
|
title = d.optString("title", "");
|
||||||
|
// trigger
|
||||||
|
trigger = Trigger.instantiate(d.getString("trigger"));
|
||||||
|
// actions
|
||||||
|
JSONArray array = d.getJSONArray("actions");
|
||||||
|
actions.clear();
|
||||||
|
for (int i = 0; i < array.length(); i++) {
|
||||||
|
actions.add(Action.instantiate(new JSONObject(array.getString(i))));
|
||||||
|
}
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.dialogs.EditEventDialog
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.events.EventAutomationDataChanged
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.events.EventAutomationUpdateGui
|
||||||
|
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||||
|
import io.reactivex.disposables.CompositeDisposable
|
||||||
|
import io.reactivex.disposables.Disposable
|
||||||
|
import kotlinx.android.synthetic.main.automation_fragment.*
|
||||||
|
|
||||||
|
class AutomationFragment : Fragment() {
|
||||||
|
|
||||||
|
private var disposable: CompositeDisposable = CompositeDisposable()
|
||||||
|
private var eventListAdapter: EventListAdapter? = null
|
||||||
|
|
||||||
|
operator fun CompositeDisposable.plusAssign(disposable: Disposable) {
|
||||||
|
add(disposable)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||||
|
return inflater.inflate(R.layout.automation_fragment, container, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
|
eventListAdapter = EventListAdapter(AutomationPlugin.automationEvents, fragmentManager)
|
||||||
|
automation_eventListView.layoutManager = LinearLayoutManager(context)
|
||||||
|
automation_eventListView.adapter = eventListAdapter
|
||||||
|
|
||||||
|
automation_fabAddEvent.setOnClickListener {
|
||||||
|
val dialog = EditEventDialog()
|
||||||
|
val args = Bundle()
|
||||||
|
args.putString("event", AutomationEvent().toJSON())
|
||||||
|
args.putInt("position", -1) // New event
|
||||||
|
dialog.arguments = args
|
||||||
|
fragmentManager?.let { dialog.show(it, "EditEventDialog") }
|
||||||
|
}
|
||||||
|
|
||||||
|
disposable += RxBus
|
||||||
|
.toObservable(EventAutomationUpdateGui::class.java)
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe({
|
||||||
|
eventListAdapter?.notifyDataSetChanged()
|
||||||
|
val sb = StringBuilder()
|
||||||
|
for (l in AutomationPlugin.executionLog) {
|
||||||
|
sb.append(l)
|
||||||
|
sb.append("\n")
|
||||||
|
}
|
||||||
|
automation_logView.text = sb.toString()
|
||||||
|
}, {})
|
||||||
|
disposable += RxBus
|
||||||
|
.toObservable(EventAutomationDataChanged::class.java)
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe({
|
||||||
|
eventListAdapter?.notifyDataSetChanged()
|
||||||
|
}, {})
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStop() {
|
||||||
|
super.onStop()
|
||||||
|
disposable.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,213 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Handler
|
||||||
|
import info.nightscout.androidaps.MainApp
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.events.EventChargingState
|
||||||
|
import info.nightscout.androidaps.events.EventLocationChange
|
||||||
|
import info.nightscout.androidaps.events.EventNetworkChange
|
||||||
|
import info.nightscout.androidaps.events.EventPreferenceChange
|
||||||
|
import info.nightscout.androidaps.interfaces.PluginBase
|
||||||
|
import info.nightscout.androidaps.interfaces.PluginDescription
|
||||||
|
import info.nightscout.androidaps.interfaces.PluginType
|
||||||
|
import info.nightscout.androidaps.logging.L
|
||||||
|
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.actions.*
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.events.EventAutomationDataChanged
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.events.EventAutomationUpdateGui
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.triggers.*
|
||||||
|
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutosensCalculationFinished
|
||||||
|
import info.nightscout.androidaps.queue.Callback
|
||||||
|
import info.nightscout.androidaps.services.LocationService
|
||||||
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
|
import info.nightscout.androidaps.utils.SP
|
||||||
|
import info.nightscout.androidaps.utils.T
|
||||||
|
import io.reactivex.disposables.CompositeDisposable
|
||||||
|
import io.reactivex.disposables.Disposable
|
||||||
|
import io.reactivex.schedulers.Schedulers
|
||||||
|
import org.json.JSONArray
|
||||||
|
import org.json.JSONException
|
||||||
|
import org.json.JSONObject
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
object AutomationPlugin : PluginBase(PluginDescription()
|
||||||
|
.mainType(PluginType.GENERAL)
|
||||||
|
.fragmentClass(AutomationFragment::class.qualifiedName)
|
||||||
|
.pluginName(R.string.automation)
|
||||||
|
.shortName(R.string.automation_short)
|
||||||
|
.preferencesId(R.xml.pref_automation)
|
||||||
|
.description(R.string.automation_description)) {
|
||||||
|
|
||||||
|
private val log = LoggerFactory.getLogger(L.AUTOMATION)
|
||||||
|
private var disposable: CompositeDisposable = CompositeDisposable()
|
||||||
|
|
||||||
|
private const val key_AUTOMATION_EVENTS = "AUTOMATION_EVENTS"
|
||||||
|
|
||||||
|
val automationEvents = ArrayList<AutomationEvent>()
|
||||||
|
var executionLog: MutableList<String> = ArrayList()
|
||||||
|
|
||||||
|
private val loopHandler = Handler()
|
||||||
|
private lateinit var refreshLoop: Runnable
|
||||||
|
|
||||||
|
init {
|
||||||
|
refreshLoop = Runnable {
|
||||||
|
processActions()
|
||||||
|
loopHandler.postDelayed(refreshLoop, T.mins(1).msecs())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun CompositeDisposable.plusAssign(disposable: Disposable) {
|
||||||
|
add(disposable)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStart() {
|
||||||
|
val context = MainApp.instance().applicationContext
|
||||||
|
context.startService(Intent(context, LocationService::class.java))
|
||||||
|
|
||||||
|
super.onStart()
|
||||||
|
loadFromSP()
|
||||||
|
loopHandler.postDelayed(refreshLoop, T.mins(1).msecs())
|
||||||
|
|
||||||
|
disposable += RxBus
|
||||||
|
.toObservable(EventPreferenceChange::class.java)
|
||||||
|
.observeOn(Schedulers.io())
|
||||||
|
.subscribe({ e ->
|
||||||
|
if (e.isChanged(R.string.key_location)) {
|
||||||
|
val ctx = MainApp.instance().applicationContext
|
||||||
|
ctx.stopService(Intent(ctx, LocationService::class.java))
|
||||||
|
ctx.startService(Intent(ctx, LocationService::class.java))
|
||||||
|
}
|
||||||
|
}, {})
|
||||||
|
disposable += RxBus
|
||||||
|
.toObservable(EventAutomationDataChanged::class.java)
|
||||||
|
.observeOn(Schedulers.io())
|
||||||
|
.subscribe({ storeToSP() }, {})
|
||||||
|
disposable += RxBus
|
||||||
|
.toObservable(EventLocationChange::class.java)
|
||||||
|
.observeOn(Schedulers.io())
|
||||||
|
.subscribe({ e ->
|
||||||
|
e?.let {
|
||||||
|
log.debug("Grabbed location: $it.location.latitude $it.location.longitude Provider: $it.location.provider")
|
||||||
|
processActions()
|
||||||
|
}
|
||||||
|
}, {})
|
||||||
|
disposable += RxBus
|
||||||
|
.toObservable(EventChargingState::class.java)
|
||||||
|
.observeOn(Schedulers.io())
|
||||||
|
.subscribe({ processActions() }, {})
|
||||||
|
disposable += RxBus
|
||||||
|
.toObservable(EventNetworkChange::class.java)
|
||||||
|
.observeOn(Schedulers.io())
|
||||||
|
.subscribe({ processActions() }, {})
|
||||||
|
disposable += RxBus
|
||||||
|
.toObservable(EventAutosensCalculationFinished::class.java)
|
||||||
|
.observeOn(Schedulers.io())
|
||||||
|
.subscribe({ processActions() }, {})
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStop() {
|
||||||
|
disposable.clear()
|
||||||
|
loopHandler.removeCallbacks(refreshLoop)
|
||||||
|
val context = MainApp.instance().applicationContext
|
||||||
|
context.stopService(Intent(context, LocationService::class.java))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun storeToSP() {
|
||||||
|
val array = JSONArray()
|
||||||
|
try {
|
||||||
|
for (event in automationEvents) {
|
||||||
|
array.put(JSONObject(event.toJSON()))
|
||||||
|
}
|
||||||
|
} catch (e: JSONException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
|
||||||
|
SP.putString(key_AUTOMATION_EVENTS, array.toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun loadFromSP() {
|
||||||
|
automationEvents.clear()
|
||||||
|
val data = SP.getString(key_AUTOMATION_EVENTS, "")
|
||||||
|
if (data != "") {
|
||||||
|
try {
|
||||||
|
val array = JSONArray(data)
|
||||||
|
for (i in 0 until array.length()) {
|
||||||
|
val o = array.getJSONObject(i)
|
||||||
|
val event = AutomationEvent().fromJSON(o.toString())
|
||||||
|
automationEvents.add(event)
|
||||||
|
}
|
||||||
|
} catch (e: JSONException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
|
private fun processActions() {
|
||||||
|
if (!isEnabled(PluginType.GENERAL))
|
||||||
|
return
|
||||||
|
|
||||||
|
if (L.isEnabled(L.AUTOMATION))
|
||||||
|
log.debug("processActions")
|
||||||
|
for (event in automationEvents) {
|
||||||
|
if (event.trigger.shouldRun() && event.preconditions.shouldRun()) {
|
||||||
|
val actions = event.actions
|
||||||
|
for (action in actions) {
|
||||||
|
action.doAction(object : Callback() {
|
||||||
|
override fun run() {
|
||||||
|
val sb = StringBuilder()
|
||||||
|
sb.append(DateUtil.timeString(DateUtil.now()))
|
||||||
|
sb.append(" ")
|
||||||
|
sb.append(if (result.success) "☺" else "X")
|
||||||
|
sb.append(" ")
|
||||||
|
sb.append(event.title)
|
||||||
|
sb.append(": ")
|
||||||
|
sb.append(action.shortDescription())
|
||||||
|
sb.append(": ")
|
||||||
|
sb.append(result.comment)
|
||||||
|
executionLog.add(sb.toString())
|
||||||
|
if (L.isEnabled(L.AUTOMATION))
|
||||||
|
log.debug("Executed: $sb")
|
||||||
|
RxBus.send(EventAutomationUpdateGui())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
event.trigger.executed(DateUtil.now())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
storeToSP() // save last run time
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getActionDummyObjects(): List<Action> {
|
||||||
|
return listOf(
|
||||||
|
//ActionLoopDisable(),
|
||||||
|
//ActionLoopEnable(),
|
||||||
|
//ActionLoopResume(),
|
||||||
|
//ActionLoopSuspend(),
|
||||||
|
ActionStartTempTarget(),
|
||||||
|
ActionStopTempTarget(),
|
||||||
|
ActionNotification(),
|
||||||
|
ActionProfileSwitchPercent()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getTriggerDummyObjects(): List<Trigger> {
|
||||||
|
return listOf(
|
||||||
|
TriggerTime(),
|
||||||
|
TriggerRecurringTime(),
|
||||||
|
TriggerBg(),
|
||||||
|
TriggerDelta(),
|
||||||
|
TriggerIob(),
|
||||||
|
TriggerCOB(),
|
||||||
|
TriggerProfilePercent(),
|
||||||
|
TriggerTempTarget(),
|
||||||
|
TriggerWifiSsid(),
|
||||||
|
TriggerLocation(),
|
||||||
|
TriggerAutosensValue(),
|
||||||
|
TriggerBolusAgo()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,120 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.RelativeLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.DrawableRes;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.fragment.app.FragmentManager;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
import info.nightscout.androidaps.R;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.actions.Action;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.dialogs.EditEventDialog;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerConnector;
|
||||||
|
|
||||||
|
class EventListAdapter extends RecyclerView.Adapter<EventListAdapter.ViewHolder> {
|
||||||
|
private final List<AutomationEvent> mEventList;
|
||||||
|
private final FragmentManager mFragmentManager;
|
||||||
|
|
||||||
|
EventListAdapter(List<AutomationEvent> events, FragmentManager fragmentManager) {
|
||||||
|
this.mEventList = events;
|
||||||
|
this.mFragmentManager = fragmentManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||||
|
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.automation_event_item, parent, false);
|
||||||
|
return new ViewHolder(v, parent.getContext());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addImage(@DrawableRes int res, Context context, LinearLayout layout) {
|
||||||
|
ImageView iv = new ImageView(context);
|
||||||
|
iv.setImageResource(res);
|
||||||
|
iv.setLayoutParams(new LinearLayout.LayoutParams(MainApp.dpToPx(24), MainApp.dpToPx(24)));
|
||||||
|
layout.addView(iv);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
||||||
|
final AutomationEvent event = mEventList.get(position);
|
||||||
|
holder.eventTitle.setText(event.getTitle());
|
||||||
|
holder.iconLayout.removeAllViews();
|
||||||
|
|
||||||
|
// trigger icons
|
||||||
|
HashSet<Integer> triggerIcons = new HashSet<>();
|
||||||
|
TriggerConnector.fillIconSet((TriggerConnector) event.getTrigger(), triggerIcons);
|
||||||
|
for (int res : triggerIcons) {
|
||||||
|
addImage(res, holder.context, holder.iconLayout);
|
||||||
|
}
|
||||||
|
|
||||||
|
// arrow icon
|
||||||
|
ImageView iv = new ImageView(holder.context);
|
||||||
|
iv.setImageResource(R.drawable.ic_arrow_forward_white_24dp);
|
||||||
|
iv.setLayoutParams(new LinearLayout.LayoutParams(MainApp.dpToPx(24), MainApp.dpToPx(24)));
|
||||||
|
iv.setPadding(MainApp.dpToPx(4), 0, MainApp.dpToPx(4), 0);
|
||||||
|
holder.iconLayout.addView(iv);
|
||||||
|
|
||||||
|
// action icons
|
||||||
|
HashSet<Integer> actionIcons = new HashSet<>();
|
||||||
|
for (Action action : event.getActions()) {
|
||||||
|
if (action.icon().isPresent())
|
||||||
|
actionIcons.add(action.icon().get());
|
||||||
|
}
|
||||||
|
for (int res : actionIcons) {
|
||||||
|
addImage(res, holder.context, holder.iconLayout);
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove event
|
||||||
|
holder.iconTrash.setOnClickListener(v -> {
|
||||||
|
mEventList.remove(event);
|
||||||
|
notifyDataSetChanged();
|
||||||
|
});
|
||||||
|
|
||||||
|
// edit event
|
||||||
|
holder.rootLayout.setOnClickListener(v -> {
|
||||||
|
//EditEventDialog dialog = EditEventDialog.Companion.newInstance(event, false);
|
||||||
|
EditEventDialog dialog = new EditEventDialog();
|
||||||
|
Bundle args = new Bundle();
|
||||||
|
args.putString("event", event.toJSON());
|
||||||
|
args.putInt("position", position);
|
||||||
|
dialog.setArguments(args);
|
||||||
|
if (mFragmentManager != null)
|
||||||
|
dialog.show(mFragmentManager, "EditEventDialog");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return mEventList.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
static class ViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
final RelativeLayout rootLayout;
|
||||||
|
final LinearLayout iconLayout;
|
||||||
|
final TextView eventTitle;
|
||||||
|
final Context context;
|
||||||
|
final ImageView iconTrash;
|
||||||
|
|
||||||
|
ViewHolder(View view, Context context) {
|
||||||
|
super(view);
|
||||||
|
this.context = context;
|
||||||
|
eventTitle = view.findViewById(R.id.viewEventTitle);
|
||||||
|
rootLayout = view.findViewById(R.id.rootLayout);
|
||||||
|
iconLayout = view.findViewById(R.id.iconLayout);
|
||||||
|
iconTrash = view.findViewById(R.id.iconTrash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,104 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.actions;
|
||||||
|
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.triggers.Trigger;
|
||||||
|
import info.nightscout.androidaps.queue.Callback;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Action ideas:
|
||||||
|
|
||||||
|
* cancel temp target
|
||||||
|
* change preference setting
|
||||||
|
* enable/disable plugin
|
||||||
|
* create notification
|
||||||
|
* create ugly alarm
|
||||||
|
* create profile switch
|
||||||
|
* set/cancel tbr
|
||||||
|
* set/cancel extended bolus
|
||||||
|
* run bolus wizard
|
||||||
|
|
||||||
|
Trigger ideas:
|
||||||
|
|
||||||
|
* location (close to)
|
||||||
|
* connected to specific wifi
|
||||||
|
* internet available/not available
|
||||||
|
* nsclient connected/disconnected
|
||||||
|
* iob
|
||||||
|
* cob
|
||||||
|
* autosens value
|
||||||
|
* delta, short delta, long delta
|
||||||
|
* last bolus ago
|
||||||
|
* is tbr running
|
||||||
|
* bolus wizard result
|
||||||
|
* loop is enabled, disabled, suspended, running
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
public abstract class Action {
|
||||||
|
|
||||||
|
public Trigger precondition = null;
|
||||||
|
|
||||||
|
public abstract int friendlyName();
|
||||||
|
|
||||||
|
public abstract String shortDescription();
|
||||||
|
|
||||||
|
public abstract void doAction(Callback callback);
|
||||||
|
|
||||||
|
public void generateDialog(LinearLayout root) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasDialog() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toJSON() {
|
||||||
|
JSONObject o = new JSONObject();
|
||||||
|
try {
|
||||||
|
o.put("type", this.getClass().getName());
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return o.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract Optional<Integer> icon();
|
||||||
|
|
||||||
|
public Action fromJSON(String data) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static Action instantiate(JSONObject object) {
|
||||||
|
try {
|
||||||
|
String type = object.getString("type");
|
||||||
|
JSONObject data = object.optJSONObject("data");
|
||||||
|
Class clazz = Class.forName(type);
|
||||||
|
return ((Action) clazz.newInstance()).fromJSON(data != null ? data.toString() : "");
|
||||||
|
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void apply(Action a) {
|
||||||
|
try {
|
||||||
|
JSONObject object = new JSONObject(a.toJSON());
|
||||||
|
String type = object.getString("type");
|
||||||
|
JSONObject data = object.getJSONObject("data");
|
||||||
|
if (type.equals(getClass().getName())) {
|
||||||
|
fromJSON(data.toString());
|
||||||
|
}
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.actions;
|
||||||
|
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
import info.nightscout.androidaps.R;
|
||||||
|
import info.nightscout.androidaps.data.PumpEnactResult;
|
||||||
|
import info.nightscout.androidaps.events.EventRefreshOverview;
|
||||||
|
import info.nightscout.androidaps.interfaces.PluginType;
|
||||||
|
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin;
|
||||||
|
import info.nightscout.androidaps.plugins.bus.RxBus;
|
||||||
|
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
|
||||||
|
import info.nightscout.androidaps.queue.Callback;
|
||||||
|
|
||||||
|
public class ActionLoopDisable extends Action {
|
||||||
|
@Override
|
||||||
|
public int friendlyName() {
|
||||||
|
return R.string.disableloop;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String shortDescription() {
|
||||||
|
return MainApp.gs(R.string.disableloop);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doAction(Callback callback) {
|
||||||
|
if (LoopPlugin.getPlugin().isEnabled(PluginType.LOOP)) {
|
||||||
|
LoopPlugin.getPlugin().setPluginEnabled(PluginType.LOOP, false);
|
||||||
|
ConfigBuilderPlugin.getPlugin().storeSettings("ActionLoopDisable");
|
||||||
|
ConfigBuilderPlugin.getPlugin().getCommandQueue().cancelTempBasal(true, new Callback() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
RxBus.INSTANCE.send(new EventRefreshOverview("ActionLoopDisable"));
|
||||||
|
if (callback != null)
|
||||||
|
callback.result(result).run();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
if (callback != null)
|
||||||
|
callback.result(new PumpEnactResult().success(true).comment(R.string.alreadydisabled)).run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Integer> icon() {
|
||||||
|
return Optional.of(R.drawable.ic_stop_24dp);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.actions;
|
||||||
|
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
import info.nightscout.androidaps.R;
|
||||||
|
import info.nightscout.androidaps.data.PumpEnactResult;
|
||||||
|
import info.nightscout.androidaps.events.EventRefreshOverview;
|
||||||
|
import info.nightscout.androidaps.interfaces.PluginType;
|
||||||
|
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin;
|
||||||
|
import info.nightscout.androidaps.plugins.bus.RxBus;
|
||||||
|
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
|
||||||
|
import info.nightscout.androidaps.queue.Callback;
|
||||||
|
|
||||||
|
public class ActionLoopEnable extends Action {
|
||||||
|
@Override
|
||||||
|
public int friendlyName() {
|
||||||
|
return R.string.enableloop;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String shortDescription() {
|
||||||
|
return MainApp.gs(R.string.enableloop);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doAction(Callback callback) {
|
||||||
|
if (!LoopPlugin.getPlugin().isEnabled(PluginType.LOOP)) {
|
||||||
|
LoopPlugin.getPlugin().setPluginEnabled(PluginType.LOOP, true);
|
||||||
|
ConfigBuilderPlugin.getPlugin().storeSettings("ActionLoopEnable");
|
||||||
|
RxBus.INSTANCE.send(new EventRefreshOverview("ActionLoopEnable"));
|
||||||
|
if (callback != null)
|
||||||
|
callback.result(new PumpEnactResult().success(true).comment(R.string.ok)).run();
|
||||||
|
} else {
|
||||||
|
if (callback != null)
|
||||||
|
callback.result(new PumpEnactResult().success(true).comment(R.string.alreadyenabled)).run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Integer> icon() {
|
||||||
|
return Optional.of(R.drawable.ic_play_circle_outline_24dp);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.actions;
|
||||||
|
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
import info.nightscout.androidaps.R;
|
||||||
|
import info.nightscout.androidaps.data.PumpEnactResult;
|
||||||
|
import info.nightscout.androidaps.events.EventRefreshOverview;
|
||||||
|
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin;
|
||||||
|
import info.nightscout.androidaps.plugins.bus.RxBus;
|
||||||
|
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
|
||||||
|
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload;
|
||||||
|
import info.nightscout.androidaps.queue.Callback;
|
||||||
|
|
||||||
|
public class ActionLoopResume extends Action {
|
||||||
|
@Override
|
||||||
|
public int friendlyName() {
|
||||||
|
return R.string.resumeloop;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String shortDescription() {
|
||||||
|
return MainApp.gs(R.string.resumeloop);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doAction(Callback callback) {
|
||||||
|
if (LoopPlugin.getPlugin().isSuspended()) {
|
||||||
|
LoopPlugin.getPlugin().suspendTo(0);
|
||||||
|
ConfigBuilderPlugin.getPlugin().storeSettings("ActionLoopResume");
|
||||||
|
NSUpload.uploadOpenAPSOffline(0);
|
||||||
|
RxBus.INSTANCE.send(new EventRefreshOverview("ActionLoopResume"));
|
||||||
|
if (callback != null)
|
||||||
|
callback.result(new PumpEnactResult().success(true).comment(R.string.ok)).run();
|
||||||
|
} else {
|
||||||
|
if (callback != null)
|
||||||
|
callback.result(new PumpEnactResult().success(true).comment(R.string.notsuspended)).run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Integer> icon() {
|
||||||
|
return Optional.of(R.drawable.ic_replay_24dp);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,91 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.actions;
|
||||||
|
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
import info.nightscout.androidaps.R;
|
||||||
|
import info.nightscout.androidaps.data.PumpEnactResult;
|
||||||
|
import info.nightscout.androidaps.events.EventRefreshOverview;
|
||||||
|
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin;
|
||||||
|
import info.nightscout.androidaps.plugins.bus.RxBus;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.InputDuration;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.LabelWithElement;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuilder;
|
||||||
|
import info.nightscout.androidaps.queue.Callback;
|
||||||
|
import info.nightscout.androidaps.utils.JsonHelper;
|
||||||
|
|
||||||
|
public class ActionLoopSuspend extends Action {
|
||||||
|
public InputDuration minutes = new InputDuration(0, InputDuration.TimeUnit.MINUTES);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int friendlyName() {
|
||||||
|
return R.string.suspendloop;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String shortDescription() {
|
||||||
|
return MainApp.gs(R.string.suspendloopforXmin, minutes.getMinutes());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doAction(Callback callback) {
|
||||||
|
if (!LoopPlugin.getPlugin().isSuspended()) {
|
||||||
|
LoopPlugin.getPlugin().suspendLoop(minutes.getMinutes());
|
||||||
|
RxBus.INSTANCE.send(new EventRefreshOverview("ActionLoopSuspend"));
|
||||||
|
if (callback != null)
|
||||||
|
callback.result(new PumpEnactResult().success(true).comment(R.string.ok)).run();
|
||||||
|
} else {
|
||||||
|
if (callback != null)
|
||||||
|
callback.result(new PumpEnactResult().success(true).comment(R.string.alreadysuspended)).run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Integer> icon() {
|
||||||
|
return Optional.of(R.drawable.ic_pause_circle_outline_24dp);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toJSON() {
|
||||||
|
JSONObject o = new JSONObject();
|
||||||
|
JSONObject data = new JSONObject();
|
||||||
|
try {
|
||||||
|
data.put("minutes", minutes.getMinutes());
|
||||||
|
o.put("type", this.getClass().getName());
|
||||||
|
o.put("data", data);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return o.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Action fromJSON(String data) {
|
||||||
|
try {
|
||||||
|
JSONObject o = new JSONObject(data);
|
||||||
|
minutes.setMinutes(JsonHelper.safeGetInt(o, "minutes"));
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasDialog() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void generateDialog(LinearLayout root) {
|
||||||
|
|
||||||
|
new LayoutBuilder()
|
||||||
|
.add(new LabelWithElement(MainApp.gs(R.string.careportal_newnstreatment_duration_min_label), "", minutes))
|
||||||
|
.build(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,91 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.actions;
|
||||||
|
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
import info.nightscout.androidaps.R;
|
||||||
|
import info.nightscout.androidaps.data.PumpEnactResult;
|
||||||
|
import info.nightscout.androidaps.events.EventRefreshOverview;
|
||||||
|
import info.nightscout.androidaps.plugins.bus.RxBus;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.InputString;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.LabelWithElement;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuilder;
|
||||||
|
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload;
|
||||||
|
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification;
|
||||||
|
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification;
|
||||||
|
import info.nightscout.androidaps.queue.Callback;
|
||||||
|
import info.nightscout.androidaps.utils.JsonHelper;
|
||||||
|
|
||||||
|
public class ActionNotification extends Action {
|
||||||
|
public InputString text = new InputString();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int friendlyName() {
|
||||||
|
return R.string.notification;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String shortDescription() {
|
||||||
|
return MainApp.gs(R.string.notification_message, text.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doAction(Callback callback) {
|
||||||
|
Notification notification = new Notification(Notification.USERMESSAGE, text.getValue(), Notification.URGENT);
|
||||||
|
RxBus.INSTANCE.send(new EventNewNotification(notification));
|
||||||
|
NSUpload.uploadError(text.getValue());
|
||||||
|
RxBus.INSTANCE.send(new EventRefreshOverview("ActionNotification"));
|
||||||
|
if (callback != null)
|
||||||
|
callback.result(new PumpEnactResult().success(true).comment(R.string.ok)).run();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Integer> icon() {
|
||||||
|
return Optional.of(R.drawable.ic_notifications);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toJSON() {
|
||||||
|
JSONObject o = new JSONObject();
|
||||||
|
JSONObject data = new JSONObject();
|
||||||
|
try {
|
||||||
|
data.put("text", text.getValue());
|
||||||
|
o.put("type", this.getClass().getName());
|
||||||
|
o.put("data", data);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return o.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Action fromJSON(String data) {
|
||||||
|
try {
|
||||||
|
JSONObject o = new JSONObject(data);
|
||||||
|
text.setValue(JsonHelper.safeGetString(o, "text"));
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasDialog() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void generateDialog(LinearLayout root) {
|
||||||
|
|
||||||
|
new LayoutBuilder()
|
||||||
|
.add(new LabelWithElement(MainApp.gs(R.string.message_short), "", text))
|
||||||
|
.build(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,95 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.actions;
|
||||||
|
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
import info.nightscout.androidaps.R;
|
||||||
|
import info.nightscout.androidaps.data.PumpEnactResult;
|
||||||
|
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.Comparator;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.InputDuration;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.InputPercent;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.LabelWithElement;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuilder;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerProfilePercent;
|
||||||
|
import info.nightscout.androidaps.queue.Callback;
|
||||||
|
import info.nightscout.androidaps.utils.JsonHelper;
|
||||||
|
|
||||||
|
public class ActionProfileSwitchPercent extends Action {
|
||||||
|
InputPercent pct = new InputPercent();
|
||||||
|
InputDuration duration = new InputDuration(0, InputDuration.TimeUnit.MINUTES);
|
||||||
|
|
||||||
|
public ActionProfileSwitchPercent() {
|
||||||
|
precondition = new TriggerProfilePercent().comparator(Comparator.Compare.IS_EQUAL).setValue(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int friendlyName() {
|
||||||
|
return R.string.profilepercentage;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String shortDescription() {
|
||||||
|
if (duration.getMinutes() == 0)
|
||||||
|
return MainApp.gs(R.string.startprofileforever, (int) pct.getValue());
|
||||||
|
else
|
||||||
|
return MainApp.gs(R.string.startprofile, (int) pct.getValue(), duration.getMinutes());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doAction(Callback callback) {
|
||||||
|
ProfileFunctions.doProfileSwitch((int) duration.getValue(), (int) pct.getValue(), 0);
|
||||||
|
if (callback != null)
|
||||||
|
callback.result(new PumpEnactResult().success(true).comment(R.string.ok)).run();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void generateDialog(LinearLayout root) {
|
||||||
|
new LayoutBuilder()
|
||||||
|
.add(new LabelWithElement(MainApp.gs(R.string.percent_u), "", pct))
|
||||||
|
.add(new LabelWithElement(MainApp.gs(R.string.careportal_newnstreatment_duration_min_label), "", duration))
|
||||||
|
.build(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasDialog() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toJSON() {
|
||||||
|
JSONObject o = new JSONObject();
|
||||||
|
try {
|
||||||
|
o.put("type", ActionProfileSwitchPercent.class.getName());
|
||||||
|
JSONObject data = new JSONObject();
|
||||||
|
data.put("percentage", pct.getValue());
|
||||||
|
data.put("durationInMinutes", duration.getMinutes());
|
||||||
|
o.put("data", data);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return o.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Action fromJSON(String data) {
|
||||||
|
try {
|
||||||
|
JSONObject d = new JSONObject(data);
|
||||||
|
pct.setValue(JsonHelper.safeGetInt(d, "percentage"));
|
||||||
|
duration.setMinutes(JsonHelper.safeGetInt(d, "durationInMinutes"));
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Integer> icon() {
|
||||||
|
return Optional.of(R.drawable.icon_actions_profileswitch);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,119 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.actions;
|
||||||
|
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.Constants;
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
import info.nightscout.androidaps.R;
|
||||||
|
import info.nightscout.androidaps.data.Profile;
|
||||||
|
import info.nightscout.androidaps.data.PumpEnactResult;
|
||||||
|
import info.nightscout.androidaps.db.Source;
|
||||||
|
import info.nightscout.androidaps.db.TempTarget;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.ComparatorExists;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.InputBg;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.InputDuration;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.LabelWithElement;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuilder;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerTempTarget;
|
||||||
|
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
|
||||||
|
import info.nightscout.androidaps.queue.Callback;
|
||||||
|
import info.nightscout.androidaps.utils.DateUtil;
|
||||||
|
import info.nightscout.androidaps.utils.JsonHelper;
|
||||||
|
|
||||||
|
public class ActionStartTempTarget extends Action {
|
||||||
|
String reason = "";
|
||||||
|
InputBg value = new InputBg();
|
||||||
|
InputDuration duration = new InputDuration(0, InputDuration.TimeUnit.MINUTES);
|
||||||
|
private TempTarget tempTarget;
|
||||||
|
|
||||||
|
public ActionStartTempTarget() {
|
||||||
|
precondition = new TriggerTempTarget().comparator(ComparatorExists.Compare.NOT_EXISTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int friendlyName() {
|
||||||
|
return R.string.starttemptarget;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String shortDescription() {
|
||||||
|
tempTarget = new TempTarget()
|
||||||
|
.date(DateUtil.now())
|
||||||
|
.duration(duration.getMinutes())
|
||||||
|
.reason(reason)
|
||||||
|
.source(Source.USER)
|
||||||
|
.low(Profile.toMgdl(value.getValue(), value.getUnits()))
|
||||||
|
.high(Profile.toMgdl(value.getValue(), value.getUnits()));
|
||||||
|
return MainApp.gs(R.string.starttemptarget) + ": " + (tempTarget == null ? "null" : tempTarget.friendlyDescription(value.getUnits()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doAction(Callback callback) {
|
||||||
|
tempTarget = new TempTarget()
|
||||||
|
.date(DateUtil.now())
|
||||||
|
.duration(duration.getMinutes())
|
||||||
|
.reason(reason)
|
||||||
|
.source(Source.USER)
|
||||||
|
.low(Profile.toMgdl(value.getValue(), value.getUnits()))
|
||||||
|
.high(Profile.toMgdl(value.getValue(), value.getUnits()));
|
||||||
|
TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget);
|
||||||
|
if (callback != null)
|
||||||
|
callback.result(new PumpEnactResult().success(true).comment(R.string.ok)).run();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void generateDialog(LinearLayout root) {
|
||||||
|
int unitResId = value.getUnits().equals(Constants.MGDL) ? R.string.mgdl : R.string.mmol;
|
||||||
|
|
||||||
|
new LayoutBuilder()
|
||||||
|
.add(new LabelWithElement(MainApp.gs(R.string.careportal_temporarytarget), MainApp.gs(unitResId), value))
|
||||||
|
.add(new LabelWithElement(MainApp.gs(R.string.careportal_newnstreatment_duration_min_label), "", duration))
|
||||||
|
.build(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasDialog() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toJSON() {
|
||||||
|
JSONObject o = new JSONObject();
|
||||||
|
try {
|
||||||
|
o.put("type", ActionStartTempTarget.class.getName());
|
||||||
|
JSONObject data = new JSONObject();
|
||||||
|
data.put("reason", reason);
|
||||||
|
data.put("value", value.getValue());
|
||||||
|
data.put("units", value.getUnits());
|
||||||
|
data.put("durationInMinutes", duration.getMinutes());
|
||||||
|
o.put("data", data);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return o.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Action fromJSON(String data) {
|
||||||
|
try {
|
||||||
|
JSONObject d = new JSONObject(data);
|
||||||
|
reason = JsonHelper.safeGetString(d, "reason");
|
||||||
|
value.setUnits(JsonHelper.safeGetString(d, "units"));
|
||||||
|
value.setValue(JsonHelper.safeGetDouble(d, "value"));
|
||||||
|
duration.setMinutes(JsonHelper.safeGetInt(d, "durationInMinutes"));
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Integer> icon() {
|
||||||
|
return Optional.of(R.drawable.icon_cp_cgm_target);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.actions;
|
||||||
|
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
import info.nightscout.androidaps.R;
|
||||||
|
import info.nightscout.androidaps.data.PumpEnactResult;
|
||||||
|
import info.nightscout.androidaps.db.Source;
|
||||||
|
import info.nightscout.androidaps.db.TempTarget;
|
||||||
|
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
|
||||||
|
import info.nightscout.androidaps.queue.Callback;
|
||||||
|
import info.nightscout.androidaps.utils.DateUtil;
|
||||||
|
import info.nightscout.androidaps.utils.JsonHelper;
|
||||||
|
|
||||||
|
public class ActionStopTempTarget extends Action {
|
||||||
|
String reason = "";
|
||||||
|
private TempTarget tempTarget;
|
||||||
|
|
||||||
|
public ActionStopTempTarget() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int friendlyName() {
|
||||||
|
return R.string.stoptemptarget;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String shortDescription() {
|
||||||
|
return MainApp.gs(R.string.stoptemptarget);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doAction(Callback callback) {
|
||||||
|
tempTarget = new TempTarget().date(DateUtil.now()).duration(0).reason(reason).source(Source.USER).low(0).high(0);
|
||||||
|
TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget);
|
||||||
|
if (callback != null)
|
||||||
|
callback.result(new PumpEnactResult().success(true).comment(R.string.ok)).run();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasDialog() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toJSON() {
|
||||||
|
JSONObject o = new JSONObject();
|
||||||
|
try {
|
||||||
|
o.put("type", ActionStopTempTarget.class.getName());
|
||||||
|
JSONObject data = new JSONObject();
|
||||||
|
data.put("reason", reason);
|
||||||
|
o.put("data", data);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return o.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Action fromJSON(String data) {
|
||||||
|
try {
|
||||||
|
JSONObject d = new JSONObject(data);
|
||||||
|
reason = JsonHelper.safeGetString(d, "reason");
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Integer> icon() {
|
||||||
|
return Optional.of(R.drawable.ic_stop_24dp);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.dialogs
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.ImageView
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.fragment.app.FragmentManager
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.actions.Action
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.events.EventAutomationUpdateGui
|
||||||
|
|
||||||
|
class ActionListAdapter(private val fragmentManager: FragmentManager, private val actionList: MutableList<Action>) : RecyclerView.Adapter<ActionListAdapter.ViewHolder>() {
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||||
|
val v = LayoutInflater.from(parent.context).inflate(R.layout.automation_action_item, parent, false)
|
||||||
|
return ViewHolder(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||||
|
val action = actionList[position]
|
||||||
|
holder.bind(action, fragmentManager, this, position, actionList)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemCount(): Int {
|
||||||
|
return actionList.size
|
||||||
|
}
|
||||||
|
|
||||||
|
class ViewHolder(val view: View) : RecyclerView.ViewHolder(view) {
|
||||||
|
|
||||||
|
fun bind(action: Action, fragmentManager: FragmentManager, recyclerView: RecyclerView.Adapter<ViewHolder>, position : Int, actionList: MutableList<Action>) {
|
||||||
|
view.findViewById<LinearLayout>(R.id.automation_layoutText).setOnClickListener {
|
||||||
|
if (action.hasDialog()) {
|
||||||
|
val args = Bundle()
|
||||||
|
args.putInt("actionPosition", position)
|
||||||
|
args.putString("action", action.toJSON())
|
||||||
|
val dialog = EditActionDialog()
|
||||||
|
dialog.arguments = args
|
||||||
|
dialog.show(fragmentManager, "EditActionDialog")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
view.findViewById<ImageView>(R.id.automation_iconTrash).setOnClickListener {
|
||||||
|
actionList.remove(action)
|
||||||
|
recyclerView.notifyDataSetChanged()
|
||||||
|
RxBus.send(EventAutomationUpdateGui())
|
||||||
|
}
|
||||||
|
view.findViewById<TextView>(R.id.automation_viewActionTitle).text = action.shortDescription()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,85 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.dialogs
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.RadioButton
|
||||||
|
import androidx.fragment.app.DialogFragment
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.AutomationPlugin
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.actions.Action
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.events.EventAutomationAddAction
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.events.EventAutomationUpdateGui
|
||||||
|
import kotlinx.android.synthetic.main.automation_dialog_choose_action.*
|
||||||
|
import kotlinx.android.synthetic.main.okcancel.*
|
||||||
|
|
||||||
|
class ChooseActionDialog : DialogFragment() {
|
||||||
|
|
||||||
|
var checkedIndex = -1
|
||||||
|
|
||||||
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?): View? {
|
||||||
|
// restore checked radio button
|
||||||
|
savedInstanceState?.let { bundle ->
|
||||||
|
checkedIndex = bundle.getInt("checkedIndex")
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog.setCanceledOnTouchOutside(false)
|
||||||
|
return inflater.inflate(R.layout.automation_dialog_choose_action, container, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
|
for (a in AutomationPlugin.getActionDummyObjects()) {
|
||||||
|
val radioButton = RadioButton(context)
|
||||||
|
radioButton.setText(a.friendlyName())
|
||||||
|
radioButton.tag = a.javaClass
|
||||||
|
automation_radioGroup.addView(radioButton)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (checkedIndex != -1)
|
||||||
|
(automation_radioGroup.getChildAt(checkedIndex) as RadioButton).isChecked = true
|
||||||
|
|
||||||
|
// OK button
|
||||||
|
ok.setOnClickListener {
|
||||||
|
dismiss()
|
||||||
|
instantiateAction()?.let {
|
||||||
|
RxBus.send(EventAutomationAddAction(it))
|
||||||
|
RxBus.send(EventAutomationUpdateGui())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cancel button
|
||||||
|
cancel.setOnClickListener { dismiss() }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSaveInstanceState(bundle: Bundle) {
|
||||||
|
bundle.putInt("checkedIndex", determineCheckedIndex())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun instantiateAction(): Action? {
|
||||||
|
return getActionClass()?.let {
|
||||||
|
it.newInstance() as Action
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getActionClass(): Class<*>? {
|
||||||
|
val radioButtonID = automation_radioGroup.checkedRadioButtonId
|
||||||
|
val radioButton = automation_radioGroup.findViewById<RadioButton>(radioButtonID)
|
||||||
|
return radioButton?.let {
|
||||||
|
it.tag as Class<*>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun determineCheckedIndex(): Int {
|
||||||
|
for (i in 0 until automation_radioGroup.childCount) {
|
||||||
|
if ((automation_radioGroup.getChildAt(i) as RadioButton).isChecked)
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,89 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.dialogs
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.RadioButton
|
||||||
|
import androidx.fragment.app.DialogFragment
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.AutomationPlugin
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.triggers.Trigger
|
||||||
|
import kotlinx.android.synthetic.main.automation_dialog_choose_trigger.*
|
||||||
|
import kotlinx.android.synthetic.main.okcancel.*
|
||||||
|
|
||||||
|
class ChooseTriggerDialog : DialogFragment() {
|
||||||
|
|
||||||
|
private var checkedIndex = -1
|
||||||
|
|
||||||
|
private var clickListener: OnClickListener? = null
|
||||||
|
|
||||||
|
interface OnClickListener {
|
||||||
|
fun onClick(newTriggerObject: Trigger?)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?): View? {
|
||||||
|
// restore checked radio button
|
||||||
|
savedInstanceState?.let { bundle ->
|
||||||
|
checkedIndex = bundle.getInt("checkedIndex")
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog.setCanceledOnTouchOutside(false)
|
||||||
|
return inflater.inflate(R.layout.automation_dialog_choose_trigger, container, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
|
for (t in AutomationPlugin.getTriggerDummyObjects()) {
|
||||||
|
val radioButton = RadioButton(context)
|
||||||
|
radioButton.setText(t.friendlyName())
|
||||||
|
radioButton.tag = t.javaClass
|
||||||
|
automation_chooseTriggerRadioGroup.addView(radioButton)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (checkedIndex != -1)
|
||||||
|
(automation_chooseTriggerRadioGroup.getChildAt(checkedIndex) as RadioButton).isChecked = true
|
||||||
|
|
||||||
|
// OK button
|
||||||
|
ok.setOnClickListener {
|
||||||
|
dismiss()
|
||||||
|
clickListener?.onClick(instantiateTrigger())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cancel button
|
||||||
|
cancel.setOnClickListener { dismiss() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setOnClickListener(clickListener: OnClickListener) {
|
||||||
|
this.clickListener = clickListener
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSaveInstanceState(bundle: Bundle) {
|
||||||
|
bundle.putInt("checkedIndex", determineCheckedIndex())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun instantiateTrigger(): Trigger? {
|
||||||
|
return getTriggerClass()?.let {
|
||||||
|
it.newInstance() as Trigger
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getTriggerClass(): Class<*>? {
|
||||||
|
val radioButtonID = automation_chooseTriggerRadioGroup.checkedRadioButtonId
|
||||||
|
val radioButton = automation_chooseTriggerRadioGroup.findViewById<RadioButton>(radioButtonID)
|
||||||
|
return radioButton?.let {
|
||||||
|
it.tag as Class<*>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun determineCheckedIndex(): Int {
|
||||||
|
for (i in 0 until automation_chooseTriggerRadioGroup.childCount) {
|
||||||
|
if ((automation_chooseTriggerRadioGroup.getChildAt(i) as RadioButton).isChecked)
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.dialogs
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.Button
|
||||||
|
import androidx.fragment.app.DialogFragment
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.actions.Action
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.events.EventAutomationUpdateAction
|
||||||
|
import kotlinx.android.synthetic.main.automation_dialog_action.*
|
||||||
|
import kotlinx.android.synthetic.main.okcancel.*
|
||||||
|
import org.json.JSONObject
|
||||||
|
|
||||||
|
class EditActionDialog : DialogFragment() {
|
||||||
|
|
||||||
|
private var action: Action? = null
|
||||||
|
private var actionPosition: Int = -1
|
||||||
|
|
||||||
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?): View? {
|
||||||
|
// load data from bundle
|
||||||
|
(savedInstanceState ?: arguments)?.let { bundle ->
|
||||||
|
actionPosition = bundle.getInt("actionPosition", -1)
|
||||||
|
bundle.getString("action")?.let { action = Action.instantiate(JSONObject(it)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog.setCanceledOnTouchOutside(false)
|
||||||
|
return inflater.inflate(R.layout.automation_dialog_action, container, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
|
action?.let {
|
||||||
|
automation_actionTitle.setText(it.friendlyName())
|
||||||
|
automation_editActionLayout.removeAllViews()
|
||||||
|
it.generateDialog(automation_editActionLayout)
|
||||||
|
}
|
||||||
|
|
||||||
|
// OK button
|
||||||
|
ok.setOnClickListener {
|
||||||
|
dismiss()
|
||||||
|
action?.let {
|
||||||
|
RxBus.send(EventAutomationUpdateAction(it, actionPosition))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cancel button
|
||||||
|
cancel.setOnClickListener { dismiss() }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSaveInstanceState(bundle: Bundle) {
|
||||||
|
super.onSaveInstanceState(bundle)
|
||||||
|
action?.let {
|
||||||
|
bundle.putInt("actionPosition", actionPosition)
|
||||||
|
bundle.putString("action", it.toJSON())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,154 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.dialogs
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.fragment.app.DialogFragment
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.AutomationEvent
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.AutomationPlugin
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.events.*
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerConnector
|
||||||
|
import info.nightscout.androidaps.utils.ToastUtils
|
||||||
|
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||||
|
import io.reactivex.disposables.CompositeDisposable
|
||||||
|
import kotlinx.android.synthetic.main.automation_dialog_event.*
|
||||||
|
import kotlinx.android.synthetic.main.okcancel.*
|
||||||
|
|
||||||
|
class EditEventDialog : DialogFragment() {
|
||||||
|
|
||||||
|
private var actionListAdapter: ActionListAdapter? = null
|
||||||
|
private var event: AutomationEvent = AutomationEvent()
|
||||||
|
private var position: Int = -1
|
||||||
|
|
||||||
|
private var disposable: CompositeDisposable = CompositeDisposable()
|
||||||
|
|
||||||
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?): View? {
|
||||||
|
// load data from bundle
|
||||||
|
(savedInstanceState ?: arguments)?.let { bundle ->
|
||||||
|
position = bundle.getInt("position", -1)
|
||||||
|
bundle.getString("event")?.let { event = AutomationEvent().fromJSON(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog.setCanceledOnTouchOutside(false)
|
||||||
|
return inflater.inflate(R.layout.automation_dialog_event, container, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
|
automation_inputEventTitle.setText(event.title)
|
||||||
|
automation_triggerDescription.text = event.trigger.friendlyDescription()
|
||||||
|
|
||||||
|
automation_editTrigger.setOnClickListener {
|
||||||
|
val args = Bundle()
|
||||||
|
args.putString("trigger", event.trigger.toJSON())
|
||||||
|
val dialog = EditTriggerDialog()
|
||||||
|
dialog.arguments = args
|
||||||
|
fragmentManager?.let { dialog.show(it, "EditTriggerDialog") }
|
||||||
|
}
|
||||||
|
|
||||||
|
// setup action list view
|
||||||
|
fragmentManager?.let { actionListAdapter = ActionListAdapter(it, event.actions) }
|
||||||
|
automation_actionListView.layoutManager = LinearLayoutManager(context)
|
||||||
|
automation_actionListView.adapter = actionListAdapter
|
||||||
|
|
||||||
|
automation_addAction.setOnClickListener { fragmentManager?.let { ChooseActionDialog().show(it, "ChooseActionDialog") } }
|
||||||
|
|
||||||
|
// OK button
|
||||||
|
ok.setOnClickListener {
|
||||||
|
// check for title
|
||||||
|
val title = automation_inputEventTitle.text.toString()
|
||||||
|
if (title.isEmpty()) {
|
||||||
|
ToastUtils.showToastInUiThread(context, R.string.automation_missing_task_name)
|
||||||
|
return@setOnClickListener
|
||||||
|
}
|
||||||
|
event.title = title
|
||||||
|
// check for at least one trigger
|
||||||
|
val con = event.trigger as TriggerConnector
|
||||||
|
if (con.size() == 0) {
|
||||||
|
ToastUtils.showToastInUiThread(context, R.string.automation_missing_trigger)
|
||||||
|
return@setOnClickListener
|
||||||
|
}
|
||||||
|
// check for at least one action
|
||||||
|
if (event.actions.isEmpty()) {
|
||||||
|
ToastUtils.showToastInUiThread(context, R.string.automation_missing_action)
|
||||||
|
return@setOnClickListener
|
||||||
|
}
|
||||||
|
// store
|
||||||
|
if (position == -1)
|
||||||
|
AutomationPlugin.automationEvents.add(event)
|
||||||
|
else
|
||||||
|
AutomationPlugin.automationEvents[position] = event
|
||||||
|
|
||||||
|
dismiss()
|
||||||
|
RxBus.send(EventAutomationDataChanged())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cancel button
|
||||||
|
cancel.setOnClickListener { dismiss() }
|
||||||
|
|
||||||
|
showPreconditions()
|
||||||
|
|
||||||
|
disposable.add(RxBus
|
||||||
|
.toObservable(EventAutomationUpdateGui::class.java)
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe({
|
||||||
|
actionListAdapter?.notifyDataSetChanged()
|
||||||
|
showPreconditions()
|
||||||
|
}, {})
|
||||||
|
)
|
||||||
|
disposable.add(RxBus
|
||||||
|
.toObservable(EventAutomationAddAction::class.java)
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe({
|
||||||
|
event.addAction(it.action)
|
||||||
|
actionListAdapter?.notifyDataSetChanged()
|
||||||
|
}, {})
|
||||||
|
)
|
||||||
|
disposable.add(RxBus
|
||||||
|
.toObservable(EventAutomationUpdateTrigger::class.java)
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe({
|
||||||
|
event.trigger = it.trigger
|
||||||
|
automation_triggerDescription.text = event.trigger.friendlyDescription()
|
||||||
|
}, {})
|
||||||
|
)
|
||||||
|
disposable.add(RxBus
|
||||||
|
.toObservable(EventAutomationUpdateAction::class.java)
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe({
|
||||||
|
event.actions[it.position] = it.action
|
||||||
|
actionListAdapter?.notifyDataSetChanged()
|
||||||
|
}, {})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroyView() {
|
||||||
|
super.onDestroyView()
|
||||||
|
disposable.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSaveInstanceState(bundle: Bundle) {
|
||||||
|
super.onSaveInstanceState(bundle)
|
||||||
|
bundle.putString("event", event.toJSON())
|
||||||
|
bundle.putInt("position", position)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showPreconditions() {
|
||||||
|
val forcedTriggers = event.preconditions
|
||||||
|
if (forcedTriggers.size() > 0) {
|
||||||
|
automation_forcedTriggerDescription.visibility = View.VISIBLE
|
||||||
|
automation_forcedTriggerDescriptionLabel.visibility = View.VISIBLE
|
||||||
|
automation_forcedTriggerDescription.text = forcedTriggers.friendlyDescription()
|
||||||
|
} else {
|
||||||
|
automation_forcedTriggerDescription.visibility = View.GONE
|
||||||
|
automation_forcedTriggerDescriptionLabel.visibility = View.GONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.dialogs
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.fragment.app.DialogFragment
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.events.EventAutomationUpdateTrigger
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.triggers.Trigger
|
||||||
|
import kotlinx.android.synthetic.main.automation_dialog_edit_trigger.*
|
||||||
|
import kotlinx.android.synthetic.main.okcancel.*
|
||||||
|
|
||||||
|
class EditTriggerDialog : DialogFragment() {
|
||||||
|
|
||||||
|
private var trigger: Trigger? = null
|
||||||
|
|
||||||
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?): View? {
|
||||||
|
// load data from bundle
|
||||||
|
(savedInstanceState ?: arguments)?.let { bundle ->
|
||||||
|
bundle.getString("trigger")?.let { trigger = Trigger.instantiate(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog.setCanceledOnTouchOutside(false)
|
||||||
|
return inflater.inflate(R.layout.automation_dialog_edit_trigger, container, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
|
// display root trigger
|
||||||
|
trigger?.let { it.generateDialog(automation_layoutTrigger, fragmentManager) }
|
||||||
|
|
||||||
|
// OK button
|
||||||
|
ok.setOnClickListener {
|
||||||
|
dismiss()
|
||||||
|
RxBus.send(EventAutomationUpdateTrigger(trigger!!))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cancel button
|
||||||
|
cancel.setOnClickListener { dismiss() }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSaveInstanceState(bundle: Bundle) {
|
||||||
|
super.onSaveInstanceState(bundle)
|
||||||
|
trigger?.let { bundle.putString("trigger", it.toJSON()) }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,186 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.dialogs;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.AdapterView;
|
||||||
|
import android.widget.ArrayAdapter;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.Spinner;
|
||||||
|
|
||||||
|
import androidx.fragment.app.FragmentManager;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
import info.nightscout.androidaps.R;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.triggers.Trigger;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerConnector;
|
||||||
|
|
||||||
|
public class TriggerListAdapter {
|
||||||
|
private final LinearLayout mRootLayout;
|
||||||
|
private final FragmentManager mFragmentManager;
|
||||||
|
private final Context mContext;
|
||||||
|
private final TriggerConnector mRootConnector;
|
||||||
|
|
||||||
|
public TriggerListAdapter(FragmentManager fragmentManager, Context context, LinearLayout rootLayout, TriggerConnector rootTrigger) {
|
||||||
|
mRootLayout = rootLayout;
|
||||||
|
mFragmentManager = fragmentManager;
|
||||||
|
mContext = context;
|
||||||
|
mRootConnector = rootTrigger;
|
||||||
|
build(fragmentManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Context getContext() {
|
||||||
|
return mContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
private FragmentManager getFM() {
|
||||||
|
return mFragmentManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void destroy() {
|
||||||
|
mRootLayout.removeAllViews();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void build(FragmentManager fragmentManager) {
|
||||||
|
for (int i = 0; i < mRootConnector.size(); ++i) {
|
||||||
|
final Trigger trigger = mRootConnector.get(i);
|
||||||
|
|
||||||
|
// spinner
|
||||||
|
if (i > 0) {
|
||||||
|
createSpinner(trigger);
|
||||||
|
}
|
||||||
|
|
||||||
|
// trigger layout
|
||||||
|
trigger.generateDialog(mRootLayout, fragmentManager);
|
||||||
|
|
||||||
|
// buttons
|
||||||
|
createButtons(fragmentManager, trigger);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mRootConnector.size() == 0) {
|
||||||
|
Button buttonAdd = new Button(mContext);
|
||||||
|
buttonAdd.setText(MainApp.gs(R.string.addnew));
|
||||||
|
buttonAdd.setOnClickListener(v -> {
|
||||||
|
ChooseTriggerDialog dialog = new ChooseTriggerDialog();
|
||||||
|
dialog.setOnClickListener(newTriggerObject -> {
|
||||||
|
mRootConnector.add(newTriggerObject);
|
||||||
|
rebuild(fragmentManager);
|
||||||
|
});
|
||||||
|
dialog.show(fragmentManager, "ChooseTriggerDialog");
|
||||||
|
});
|
||||||
|
mRootLayout.addView(buttonAdd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Spinner createSpinner() {
|
||||||
|
Spinner spinner = new Spinner(mContext);
|
||||||
|
ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<>(mContext, android.R.layout.simple_spinner_item, TriggerConnector.Type.labels());
|
||||||
|
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||||
|
spinner.setAdapter(spinnerArrayAdapter);
|
||||||
|
return spinner;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createSpinner(Trigger trigger) {
|
||||||
|
final TriggerConnector connector = trigger.getConnector();
|
||||||
|
final int initialPosition = connector.getConnectorType().ordinal();
|
||||||
|
Spinner spinner = createSpinner();
|
||||||
|
spinner.setSelection(initialPosition);
|
||||||
|
spinner.setBackgroundColor(MainApp.gc(R.color.black_overlay));
|
||||||
|
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
|
||||||
|
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||||
|
LinearLayout.LayoutParams.WRAP_CONTENT
|
||||||
|
);
|
||||||
|
params.setMargins(0, MainApp.dpToPx(8), 0, MainApp.dpToPx(8));
|
||||||
|
spinner.setLayoutParams(params);
|
||||||
|
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
||||||
|
@Override
|
||||||
|
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
||||||
|
if (position != initialPosition) {
|
||||||
|
// connector type changed
|
||||||
|
changeConnector(getFM(), trigger, connector, TriggerConnector.Type.values()[position]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNothingSelected(AdapterView<?> parent) {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
mRootLayout.addView(spinner);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createButtons(FragmentManager fragmentManager, Trigger trigger) {
|
||||||
|
// do not create buttons for TriggerConnector
|
||||||
|
if (trigger instanceof TriggerConnector) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Button Layout
|
||||||
|
LinearLayout buttonLayout = new LinearLayout(mContext);
|
||||||
|
buttonLayout.setOrientation(LinearLayout.HORIZONTAL);
|
||||||
|
buttonLayout.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||||
|
mRootLayout.addView(buttonLayout);
|
||||||
|
|
||||||
|
// Button [-]
|
||||||
|
Button buttonRemove = new Button(mContext);
|
||||||
|
buttonRemove.setText(MainApp.gs(R.string.delete_short));
|
||||||
|
buttonRemove.setOnClickListener(v -> {
|
||||||
|
final TriggerConnector connector = trigger.getConnector();
|
||||||
|
connector.remove(trigger);
|
||||||
|
connector.simplify().rebuildView(getFM());
|
||||||
|
});
|
||||||
|
buttonLayout.addView(buttonRemove);
|
||||||
|
|
||||||
|
// Button [+]
|
||||||
|
Button buttonAdd = new Button(mContext);
|
||||||
|
buttonAdd.setText(MainApp.gs(R.string.add_short));
|
||||||
|
buttonAdd.setOnClickListener(v -> {
|
||||||
|
ChooseTriggerDialog dialog = new ChooseTriggerDialog();
|
||||||
|
dialog.show(fragmentManager, "ChooseTriggerDialog");
|
||||||
|
dialog.setOnClickListener(newTriggerObject -> {
|
||||||
|
TriggerConnector connector = trigger.getConnector();
|
||||||
|
connector.add(connector.pos(trigger) + 1, newTriggerObject);
|
||||||
|
connector.simplify().rebuildView(getFM());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
buttonLayout.addView(buttonAdd);
|
||||||
|
|
||||||
|
// Button [*]
|
||||||
|
Button buttonCopy = new Button(mContext);
|
||||||
|
buttonCopy.setText(MainApp.gs(R.string.copy_short));
|
||||||
|
buttonCopy.setOnClickListener(v -> {
|
||||||
|
TriggerConnector connector = trigger.getConnector();
|
||||||
|
connector.add(connector.pos(trigger) + 1, trigger.duplicate());
|
||||||
|
connector.simplify().rebuildView(getFM());
|
||||||
|
});
|
||||||
|
buttonLayout.addView(buttonCopy);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void rebuild(FragmentManager fragmentManager) {
|
||||||
|
destroy();
|
||||||
|
build(fragmentManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void changeConnector(final FragmentManager fragmentManager, final Trigger trigger, final TriggerConnector connector, final TriggerConnector.Type newConnectorType) {
|
||||||
|
if (connector.size() > 2) {
|
||||||
|
// split connector
|
||||||
|
int pos = connector.pos(trigger) - 1;
|
||||||
|
|
||||||
|
TriggerConnector newConnector = new TriggerConnector(newConnectorType);
|
||||||
|
|
||||||
|
// move trigger from pos and pos+1 into new connector
|
||||||
|
for (int i = 0; i < 2; ++i) {
|
||||||
|
Trigger t = connector.get(pos);
|
||||||
|
newConnector.add(t);
|
||||||
|
connector.remove(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
connector.add(pos, newConnector);
|
||||||
|
} else {
|
||||||
|
connector.changeConnectorType(newConnectorType);
|
||||||
|
}
|
||||||
|
|
||||||
|
connector.simplify().rebuildView(fragmentManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,123 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.elements;
|
||||||
|
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.AdapterView;
|
||||||
|
import android.widget.ArrayAdapter;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.Spinner;
|
||||||
|
|
||||||
|
import androidx.annotation.StringRes;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
import info.nightscout.androidaps.R;
|
||||||
|
|
||||||
|
public class Comparator extends Element {
|
||||||
|
public enum Compare {
|
||||||
|
IS_LESSER,
|
||||||
|
IS_EQUAL_OR_LESSER,
|
||||||
|
IS_EQUAL,
|
||||||
|
IS_EQUAL_OR_GREATER,
|
||||||
|
IS_GREATER,
|
||||||
|
IS_NOT_AVAILABLE;
|
||||||
|
|
||||||
|
public @StringRes
|
||||||
|
int getStringRes() {
|
||||||
|
switch (this) {
|
||||||
|
case IS_LESSER:
|
||||||
|
return R.string.islesser;
|
||||||
|
case IS_EQUAL_OR_LESSER:
|
||||||
|
return R.string.isequalorlesser;
|
||||||
|
case IS_EQUAL:
|
||||||
|
return R.string.isequal;
|
||||||
|
case IS_EQUAL_OR_GREATER:
|
||||||
|
return R.string.isequalorgreater;
|
||||||
|
case IS_GREATER:
|
||||||
|
return R.string.isgreater;
|
||||||
|
case IS_NOT_AVAILABLE:
|
||||||
|
return R.string.isnotavailable;
|
||||||
|
default:
|
||||||
|
return R.string.unknown;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends Comparable> boolean check(T obj1, T obj2) {
|
||||||
|
if (obj1 == null || obj2 == null)
|
||||||
|
return this.equals(IS_NOT_AVAILABLE);
|
||||||
|
|
||||||
|
int comparison = obj1.compareTo(obj2);
|
||||||
|
switch (this) {
|
||||||
|
case IS_LESSER:
|
||||||
|
return comparison < 0;
|
||||||
|
case IS_EQUAL_OR_LESSER:
|
||||||
|
return comparison <= 0;
|
||||||
|
case IS_EQUAL:
|
||||||
|
return comparison == 0;
|
||||||
|
case IS_EQUAL_OR_GREATER:
|
||||||
|
return comparison >= 0;
|
||||||
|
case IS_GREATER:
|
||||||
|
return comparison > 0;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<String> labels() {
|
||||||
|
List<String> list = new ArrayList<>();
|
||||||
|
for (Compare c : Compare.values()) {
|
||||||
|
list.add(MainApp.gs(c.getStringRes()));
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Compare compare = Compare.IS_EQUAL;
|
||||||
|
|
||||||
|
public Comparator() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Comparator(Comparator another) {
|
||||||
|
super();
|
||||||
|
compare = another.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addToLayout(LinearLayout root) {
|
||||||
|
Spinner spinner = new Spinner(root.getContext());
|
||||||
|
ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<>(root.getContext(), android.R.layout.simple_spinner_item, Compare.labels());
|
||||||
|
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||||
|
spinner.setAdapter(spinnerArrayAdapter);
|
||||||
|
LinearLayout.LayoutParams spinnerParams = new LinearLayout.LayoutParams(
|
||||||
|
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||||
|
LinearLayout.LayoutParams.WRAP_CONTENT
|
||||||
|
);
|
||||||
|
spinnerParams.setMargins(0, MainApp.dpToPx(4), 0, MainApp.dpToPx(4));
|
||||||
|
spinner.setLayoutParams(spinnerParams);
|
||||||
|
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
||||||
|
@Override
|
||||||
|
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
||||||
|
compare = Compare.values()[position];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNothingSelected(AdapterView<?> parent) {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
spinner.setSelection(compare.ordinal());
|
||||||
|
root.addView(spinner);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public Compare getValue() {
|
||||||
|
return compare;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Comparator setValue(Compare compare) {
|
||||||
|
this.compare = compare;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,90 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.elements;
|
||||||
|
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.AdapterView;
|
||||||
|
import android.widget.ArrayAdapter;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.Spinner;
|
||||||
|
|
||||||
|
import androidx.annotation.StringRes;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
import info.nightscout.androidaps.R;
|
||||||
|
|
||||||
|
public class ComparatorExists extends Element {
|
||||||
|
public enum Compare {
|
||||||
|
EXISTS,
|
||||||
|
NOT_EXISTS;
|
||||||
|
|
||||||
|
public @StringRes
|
||||||
|
int getStringRes() {
|
||||||
|
switch (this) {
|
||||||
|
case EXISTS:
|
||||||
|
return R.string.exists;
|
||||||
|
case NOT_EXISTS:
|
||||||
|
return R.string.notexists;
|
||||||
|
default:
|
||||||
|
return R.string.unknown;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<String> labels() {
|
||||||
|
List<String> list = new ArrayList<>();
|
||||||
|
for (Compare c : Compare.values()) {
|
||||||
|
list.add(MainApp.gs(c.getStringRes()));
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Compare compare = Compare.EXISTS;
|
||||||
|
|
||||||
|
public ComparatorExists() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ComparatorExists(ComparatorExists another) {
|
||||||
|
super();
|
||||||
|
compare = another.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addToLayout(LinearLayout root) {
|
||||||
|
Spinner spinner = new Spinner(root.getContext());
|
||||||
|
ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<>(root.getContext(), android.R.layout.simple_spinner_item, Compare.labels());
|
||||||
|
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||||
|
spinner.setAdapter(spinnerArrayAdapter);
|
||||||
|
LinearLayout.LayoutParams spinnerParams = new LinearLayout.LayoutParams(
|
||||||
|
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||||
|
LinearLayout.LayoutParams.WRAP_CONTENT
|
||||||
|
);
|
||||||
|
spinnerParams.setMargins(0, MainApp.dpToPx(4), 0, MainApp.dpToPx(4));
|
||||||
|
spinner.setLayoutParams(spinnerParams);
|
||||||
|
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
||||||
|
@Override
|
||||||
|
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
||||||
|
compare = Compare.values()[position];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNothingSelected(AdapterView<?> parent) {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
spinner.setSelection(compare.ordinal());
|
||||||
|
root.addView(spinner);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public Compare getValue() {
|
||||||
|
return compare;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ComparatorExists setValue(Compare compare) {
|
||||||
|
this.compare = compare;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.elements;
|
||||||
|
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
|
public abstract class Element {
|
||||||
|
public abstract void addToLayout(LinearLayout root);
|
||||||
|
}
|
|
@ -0,0 +1,99 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.elements;
|
||||||
|
|
||||||
|
import android.text.Editable;
|
||||||
|
import android.text.TextWatcher;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
|
import java.text.DecimalFormat;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.Constants;
|
||||||
|
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
|
||||||
|
import info.nightscout.androidaps.utils.NumberPicker;
|
||||||
|
|
||||||
|
public class InputBg extends Element {
|
||||||
|
|
||||||
|
final TextWatcher textWatcher = new TextWatcher() {
|
||||||
|
@Override
|
||||||
|
public void afterTextChanged(Editable s) {
|
||||||
|
if (units.equals(Constants.MMOL)) {
|
||||||
|
value = Math.max(value, 4d);
|
||||||
|
value = Math.min(value, 15d);
|
||||||
|
} else {
|
||||||
|
value = Math.max(value, 72d);
|
||||||
|
value = Math.min(value, 270d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private String units = Constants.MGDL;
|
||||||
|
private double value;
|
||||||
|
double minValue;
|
||||||
|
private double maxValue;
|
||||||
|
private double step;
|
||||||
|
private DecimalFormat decimalFormat;
|
||||||
|
|
||||||
|
public InputBg() {
|
||||||
|
super();
|
||||||
|
setUnits(ProfileFunctions.getInstance().getProfileUnits());
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputBg(InputBg another) {
|
||||||
|
super();
|
||||||
|
value = another.getValue();
|
||||||
|
setUnits(another.getUnits());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addToLayout(LinearLayout root) {
|
||||||
|
NumberPicker numberPicker = new NumberPicker(root.getContext(), null);
|
||||||
|
numberPicker.setParams(value, minValue, maxValue, step, decimalFormat, true, null, textWatcher);
|
||||||
|
numberPicker.setOnValueChangedListener(value -> this.value = value);
|
||||||
|
root.addView(numberPicker);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUnits() {
|
||||||
|
return units;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputBg setUnits(String units) {
|
||||||
|
// set default initial value
|
||||||
|
if (units.equals(Constants.MMOL)) {
|
||||||
|
// mmol
|
||||||
|
minValue = 2;
|
||||||
|
maxValue = 30;
|
||||||
|
step = 0.1;
|
||||||
|
decimalFormat = new DecimalFormat("0.0");
|
||||||
|
} else {
|
||||||
|
// mg/dL
|
||||||
|
minValue = 40;
|
||||||
|
maxValue = 540;
|
||||||
|
step = 1;
|
||||||
|
decimalFormat = new DecimalFormat("0");
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure that value is in range
|
||||||
|
textWatcher.afterTextChanged(null);
|
||||||
|
|
||||||
|
this.units = units;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputBg setValue(double value) {
|
||||||
|
this.value = value;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.elements;
|
||||||
|
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
|
public class InputButton extends Element {
|
||||||
|
|
||||||
|
String text;
|
||||||
|
Runnable runnable;
|
||||||
|
|
||||||
|
public InputButton(String text, Runnable runnable) {
|
||||||
|
this.text = text;
|
||||||
|
this.runnable = runnable;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addToLayout(LinearLayout root) {
|
||||||
|
Button button = new Button(root.getContext());
|
||||||
|
|
||||||
|
button.setText(text);
|
||||||
|
button.setOnClickListener(view -> {
|
||||||
|
if (runnable != null)
|
||||||
|
runnable.run();
|
||||||
|
});
|
||||||
|
|
||||||
|
root.addView(button);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,151 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.elements;
|
||||||
|
|
||||||
|
import android.text.Editable;
|
||||||
|
import android.text.TextWatcher;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.AdapterView;
|
||||||
|
import android.widget.ArrayAdapter;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.Spinner;
|
||||||
|
|
||||||
|
import androidx.annotation.StringRes;
|
||||||
|
|
||||||
|
import java.text.DecimalFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
import info.nightscout.androidaps.R;
|
||||||
|
import info.nightscout.androidaps.utils.NumberPicker;
|
||||||
|
|
||||||
|
public class InputDelta extends Element {
|
||||||
|
private Comparator.Compare compare = Comparator.Compare.IS_EQUAL;
|
||||||
|
final TextWatcher textWatcher = new TextWatcher() {
|
||||||
|
@Override
|
||||||
|
public void afterTextChanged(Editable s) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public enum DeltaType {
|
||||||
|
DELTA,
|
||||||
|
SHORT_AVERAGE,
|
||||||
|
LONG_AVERAGE;
|
||||||
|
|
||||||
|
public @StringRes
|
||||||
|
int getStringRes() {
|
||||||
|
switch (this) {
|
||||||
|
case DELTA:
|
||||||
|
return R.string.delta;
|
||||||
|
case SHORT_AVERAGE:
|
||||||
|
return R.string.short_avgdelta;
|
||||||
|
case LONG_AVERAGE:
|
||||||
|
return R.string.long_avgdelta;
|
||||||
|
default:
|
||||||
|
return R.string.unknown;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<String> labels() {
|
||||||
|
List<String> list = new ArrayList<>();
|
||||||
|
for (DeltaType d : DeltaType.values()) {
|
||||||
|
list.add(MainApp.gs(d.getStringRes()));
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private double value;
|
||||||
|
double minValue;
|
||||||
|
double maxValue;
|
||||||
|
private double step;
|
||||||
|
private DecimalFormat decimalFormat;
|
||||||
|
private DeltaType deltaType;
|
||||||
|
|
||||||
|
NumberPicker numberPicker;
|
||||||
|
|
||||||
|
public InputDelta() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputDelta(double value, double minValue, double maxValue, double step, DecimalFormat decimalFormat, DeltaType deltaType) {
|
||||||
|
super();
|
||||||
|
this.value = value;
|
||||||
|
this.minValue = minValue;
|
||||||
|
this.maxValue = maxValue;
|
||||||
|
this.step = step;
|
||||||
|
this.decimalFormat = decimalFormat;
|
||||||
|
this.deltaType = deltaType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputDelta(InputDelta another) {
|
||||||
|
super();
|
||||||
|
value = another.getValue();
|
||||||
|
minValue = another.minValue;
|
||||||
|
maxValue = another.maxValue;
|
||||||
|
step = another.step;
|
||||||
|
decimalFormat = another.decimalFormat;
|
||||||
|
deltaType = another.deltaType;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addToLayout(LinearLayout root) {
|
||||||
|
Spinner spinner = new Spinner(root.getContext());
|
||||||
|
ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<>(root.getContext(), android.R.layout.simple_spinner_item, DeltaType.labels());
|
||||||
|
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||||
|
spinner.setAdapter(spinnerArrayAdapter);
|
||||||
|
LinearLayout.LayoutParams spinnerParams = new LinearLayout.LayoutParams(
|
||||||
|
LinearLayout.LayoutParams.WRAP_CONTENT,
|
||||||
|
LinearLayout.LayoutParams.WRAP_CONTENT
|
||||||
|
);
|
||||||
|
spinnerParams.setMargins(0, MainApp.dpToPx(4), 0, MainApp.dpToPx(4));
|
||||||
|
spinner.setLayoutParams(spinnerParams);
|
||||||
|
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
||||||
|
@Override
|
||||||
|
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
||||||
|
deltaType = DeltaType.values()[position];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNothingSelected(AdapterView<?> parent) {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
spinner.setSelection(this.deltaType.ordinal());
|
||||||
|
// root.addView(spinner);
|
||||||
|
numberPicker = new NumberPicker(root.getContext(), null);
|
||||||
|
numberPicker.setParams(value, minValue, maxValue, step, decimalFormat, true, null, textWatcher);
|
||||||
|
numberPicker.setOnValueChangedListener(value -> this.value = value);
|
||||||
|
LinearLayout l = new LinearLayout(root.getContext());
|
||||||
|
l.setOrientation(LinearLayout.VERTICAL);
|
||||||
|
l.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||||
|
l.addView(spinner);
|
||||||
|
l.addView(numberPicker);
|
||||||
|
root.addView(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputDelta setValue(double value, DeltaType type) {
|
||||||
|
this.value = value;
|
||||||
|
this.deltaType = type;
|
||||||
|
if (numberPicker != null)
|
||||||
|
numberPicker.setValue(value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DeltaType getDeltaType() {
|
||||||
|
return deltaType;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.elements;
|
||||||
|
|
||||||
|
import android.text.Editable;
|
||||||
|
import android.text.TextWatcher;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
|
import java.text.DecimalFormat;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.utils.NumberPicker;
|
||||||
|
|
||||||
|
public class InputDouble extends Element {
|
||||||
|
|
||||||
|
final TextWatcher textWatcher = new TextWatcher() {
|
||||||
|
@Override
|
||||||
|
public void afterTextChanged(Editable s) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private double value;
|
||||||
|
double minValue;
|
||||||
|
double maxValue;
|
||||||
|
private double step;
|
||||||
|
private DecimalFormat decimalFormat;
|
||||||
|
|
||||||
|
NumberPicker numberPicker;
|
||||||
|
|
||||||
|
public InputDouble() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputDouble(double value, double minValue, double maxValue, double step, DecimalFormat decimalFormat) {
|
||||||
|
super();
|
||||||
|
this.value = value;
|
||||||
|
this.minValue = minValue;
|
||||||
|
this.maxValue = maxValue;
|
||||||
|
this.step = step;
|
||||||
|
this.decimalFormat = decimalFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputDouble(InputDouble another) {
|
||||||
|
super();
|
||||||
|
value = another.getValue();
|
||||||
|
minValue = another.minValue;
|
||||||
|
maxValue = another.maxValue;
|
||||||
|
step = another.step;
|
||||||
|
decimalFormat = another.decimalFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addToLayout(LinearLayout root) {
|
||||||
|
numberPicker = new NumberPicker(root.getContext(), null);
|
||||||
|
numberPicker.setParams(value, minValue, maxValue, step, decimalFormat, true, null, textWatcher);
|
||||||
|
numberPicker.setOnValueChangedListener(value -> this.value = value);
|
||||||
|
root.addView(numberPicker);
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputDouble setValue(double value) {
|
||||||
|
this.value = value;
|
||||||
|
if (numberPicker != null)
|
||||||
|
numberPicker.setValue(value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.elements;
|
||||||
|
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
|
import java.text.DecimalFormat;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.utils.NumberPicker;
|
||||||
|
|
||||||
|
public class InputDuration extends Element {
|
||||||
|
public enum TimeUnit {
|
||||||
|
MINUTES,
|
||||||
|
HOURS
|
||||||
|
}
|
||||||
|
|
||||||
|
private TimeUnit unit;
|
||||||
|
private int value;
|
||||||
|
|
||||||
|
public InputDuration(int value, TimeUnit unit) {
|
||||||
|
this.unit = unit;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addToLayout(LinearLayout root) {
|
||||||
|
NumberPicker numberPicker = new NumberPicker(root.getContext(), null);
|
||||||
|
if (unit.equals(TimeUnit.MINUTES)) {
|
||||||
|
// Minutes
|
||||||
|
numberPicker.setParams(0d, 0d, 24 * 60d, 10d, new DecimalFormat("0"), false, null);
|
||||||
|
} else {
|
||||||
|
// Hours
|
||||||
|
numberPicker.setParams(0d, 0d, 24d, 1d, new DecimalFormat("0"), false, null);
|
||||||
|
}
|
||||||
|
numberPicker.setValue((double) value);
|
||||||
|
numberPicker.setOnValueChangedListener(value -> this.value = (int) value);
|
||||||
|
root.addView(numberPicker);
|
||||||
|
}
|
||||||
|
|
||||||
|
TimeUnit getUnit() {
|
||||||
|
return unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMinutes(int value) {
|
||||||
|
if (unit.equals(TimeUnit.MINUTES)) {
|
||||||
|
this.value = value;
|
||||||
|
} else {
|
||||||
|
this.value = value / 60;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMinutes() {
|
||||||
|
if (unit.equals(TimeUnit.MINUTES)) {
|
||||||
|
return value;
|
||||||
|
} else {
|
||||||
|
return value * 60;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.elements;
|
||||||
|
|
||||||
|
import android.text.Editable;
|
||||||
|
import android.text.TextWatcher;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
|
import java.text.DecimalFormat;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.utils.NumberPicker;
|
||||||
|
|
||||||
|
public class InputInsulin extends Element {
|
||||||
|
|
||||||
|
final TextWatcher textWatcher = new TextWatcher() {
|
||||||
|
@Override
|
||||||
|
public void afterTextChanged(Editable s) {
|
||||||
|
value = Math.max(value, -20d);
|
||||||
|
value = Math.min(value, 20d);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private double value;
|
||||||
|
|
||||||
|
public InputInsulin() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputInsulin(InputInsulin another) {
|
||||||
|
super();
|
||||||
|
value = another.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addToLayout(LinearLayout root) {
|
||||||
|
NumberPicker numberPicker = new NumberPicker(root.getContext(), null);
|
||||||
|
numberPicker.setParams(0d, -20d, 20d, 0.1, new DecimalFormat("0.0"), true, null, textWatcher);
|
||||||
|
numberPicker.setValue(value);
|
||||||
|
numberPicker.setOnValueChangedListener(value -> this.value = value);
|
||||||
|
root.addView(numberPicker);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputInsulin setValue(double value) {
|
||||||
|
this.value = value;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.elements;
|
||||||
|
|
||||||
|
import android.text.Editable;
|
||||||
|
import android.text.TextWatcher;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
|
import java.text.DecimalFormat;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.utils.NumberPicker;
|
||||||
|
|
||||||
|
public class InputPercent extends Element {
|
||||||
|
|
||||||
|
final TextWatcher textWatcher = new TextWatcher() {
|
||||||
|
@Override
|
||||||
|
public void afterTextChanged(Editable s) {
|
||||||
|
value = Math.max(value, 70d);
|
||||||
|
value = Math.min(value, 130d);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private double value;
|
||||||
|
|
||||||
|
public InputPercent() {
|
||||||
|
super();
|
||||||
|
value = 100d;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputPercent(InputPercent another) {
|
||||||
|
super();
|
||||||
|
value = another.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addToLayout(LinearLayout root) {
|
||||||
|
NumberPicker numberPicker = new NumberPicker(root.getContext(), null);
|
||||||
|
numberPicker.setParams(100d, 70d, 130d, 5d, new DecimalFormat("0"), true, null, textWatcher);
|
||||||
|
numberPicker.setValue(value);
|
||||||
|
numberPicker.setOnValueChangedListener(value -> this.value = value);
|
||||||
|
root.addView(numberPicker);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputPercent setValue(double value) {
|
||||||
|
this.value = value;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.elements;
|
||||||
|
|
||||||
|
import android.text.Editable;
|
||||||
|
import android.text.TextWatcher;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.EditText;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
|
public class InputString extends Element {
|
||||||
|
|
||||||
|
TextWatcher textWatcher = new TextWatcher() {
|
||||||
|
@Override
|
||||||
|
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterTextChanged(Editable s) {
|
||||||
|
value = s.toString();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private String value = "";
|
||||||
|
|
||||||
|
public InputString() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputString(InputString another) {
|
||||||
|
super();
|
||||||
|
value = another.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addToLayout(LinearLayout root) {
|
||||||
|
EditText editText = new EditText(root.getContext());
|
||||||
|
editText.setText(value);
|
||||||
|
editText.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||||
|
editText.addTextChangedListener(textWatcher);
|
||||||
|
root.addView(editText);
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputString setValue(String value) {
|
||||||
|
this.value = value;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.elements;
|
||||||
|
|
||||||
|
import android.graphics.Typeface;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
|
||||||
|
public class LabelWithElement extends Element {
|
||||||
|
final Element element;
|
||||||
|
final String textPre;
|
||||||
|
final String textPost;
|
||||||
|
|
||||||
|
public LabelWithElement(String textPre, String textPost, Element element) {
|
||||||
|
this.element = element;
|
||||||
|
this.textPre = textPre;
|
||||||
|
this.textPost = textPost;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addToLayout(LinearLayout root) {
|
||||||
|
// container layout
|
||||||
|
LinearLayout layout = new LinearLayout(root.getContext());
|
||||||
|
layout.setOrientation(LinearLayout.HORIZONTAL);
|
||||||
|
layout.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
|
ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||||
|
|
||||||
|
// text view pre element
|
||||||
|
int px = MainApp.dpToPx(10);
|
||||||
|
TextView textViewPre = new TextView(root.getContext());
|
||||||
|
textViewPre.setText(textPre);
|
||||||
|
textViewPre.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
|
||||||
|
ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||||
|
//textViewPre.setWidth(MainApp.dpToPx(120));
|
||||||
|
textViewPre.setPadding(px, px, px, px);
|
||||||
|
textViewPre.setTypeface(textViewPre.getTypeface(), Typeface.BOLD);
|
||||||
|
layout.addView(textViewPre);
|
||||||
|
|
||||||
|
// add element to layout
|
||||||
|
element.addToLayout(layout);
|
||||||
|
|
||||||
|
// text view post element
|
||||||
|
if (textPost != null) {
|
||||||
|
px = MainApp.dpToPx(5);
|
||||||
|
TextView textViewPost = new TextView(root.getContext());
|
||||||
|
textViewPost.setText(textPost);
|
||||||
|
textViewPost.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
|
||||||
|
ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||||
|
//textViewPost.setWidth(MainApp.dpToPx(45));
|
||||||
|
textViewPost.setPadding(px, px, px, px);
|
||||||
|
textViewPost.setTypeface(textViewPost.getTypeface(), Typeface.BOLD);
|
||||||
|
layout.addView(textViewPost);
|
||||||
|
}
|
||||||
|
|
||||||
|
// add layout to root layout
|
||||||
|
root.addView(layout);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.elements;
|
||||||
|
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class LayoutBuilder {
|
||||||
|
ArrayList<Element> mElements = new ArrayList<>();
|
||||||
|
|
||||||
|
public LayoutBuilder add(Element element) {
|
||||||
|
mElements.add(element);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LayoutBuilder add(Element element, boolean condition) {
|
||||||
|
if (condition) mElements.add(element);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void build(LinearLayout layout) {
|
||||||
|
for (Element e : mElements) {
|
||||||
|
e.addToLayout(layout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.elements;
|
||||||
|
|
||||||
|
import android.graphics.Typeface;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
import info.nightscout.androidaps.R;
|
||||||
|
|
||||||
|
public class StaticLabel extends Element {
|
||||||
|
String label;
|
||||||
|
|
||||||
|
public StaticLabel(String label) {
|
||||||
|
super();
|
||||||
|
this.label = label;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StaticLabel(int resourceId) {
|
||||||
|
super();
|
||||||
|
this.label = MainApp.gs(resourceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addToLayout(LinearLayout root) {
|
||||||
|
// text view pre element
|
||||||
|
int px = MainApp.dpToPx(10);
|
||||||
|
TextView textView = new TextView(root.getContext());
|
||||||
|
textView.setText(label);
|
||||||
|
// textViewPre.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||||
|
textView.setPadding(px, px, px, px);
|
||||||
|
textView.setTypeface(textView.getTypeface(), Typeface.BOLD);
|
||||||
|
textView.setBackgroundColor(MainApp.gc(R.color.mdtp_line_dark));
|
||||||
|
// add element to layout
|
||||||
|
root.addView(textView);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.events
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.events.Event
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.actions.Action
|
||||||
|
|
||||||
|
class EventAutomationAddAction(val action: Action) : Event()
|
|
@ -0,0 +1,5 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.events
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.events.Event
|
||||||
|
|
||||||
|
class EventAutomationDataChanged : Event()
|
|
@ -0,0 +1,7 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.events
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.events.Event
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.actions.Action
|
||||||
|
|
||||||
|
class EventAutomationUpdateAction(val action: Action, val position : Int) : Event() {
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.events
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.events.Event
|
||||||
|
|
||||||
|
class EventAutomationUpdateGui : Event()
|
|
@ -0,0 +1,6 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.events
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.events.Event
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.triggers.Trigger
|
||||||
|
|
||||||
|
class EventAutomationUpdateTrigger(val trigger: Trigger) : Event()
|
|
@ -0,0 +1,94 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.triggers;
|
||||||
|
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.ContextWrapper;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.fragment.app.FragmentManager;
|
||||||
|
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
public abstract class Trigger {
|
||||||
|
|
||||||
|
TriggerConnector connector = null;
|
||||||
|
long lastRun;
|
||||||
|
|
||||||
|
Trigger() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public TriggerConnector getConnector() {
|
||||||
|
return connector;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract boolean shouldRun();
|
||||||
|
|
||||||
|
|
||||||
|
public abstract String toJSON();
|
||||||
|
|
||||||
|
/*package*/
|
||||||
|
abstract Trigger fromJSON(String data);
|
||||||
|
|
||||||
|
public abstract int friendlyName();
|
||||||
|
|
||||||
|
public abstract String friendlyDescription();
|
||||||
|
|
||||||
|
public abstract Optional<Integer> icon();
|
||||||
|
|
||||||
|
public void executed(long time) {
|
||||||
|
lastRun = time;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getLastRun() {
|
||||||
|
return lastRun;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract Trigger duplicate();
|
||||||
|
|
||||||
|
public static Trigger instantiate(String json) {
|
||||||
|
try {
|
||||||
|
return instantiate(new JSONObject(json));
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static Trigger instantiate(JSONObject object) {
|
||||||
|
try {
|
||||||
|
String type = object.getString("type");
|
||||||
|
JSONObject data = object.getJSONObject("data");
|
||||||
|
Class clazz = Class.forName(type);
|
||||||
|
return ((Trigger) clazz.newInstance()).fromJSON(data.toString());
|
||||||
|
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void generateDialog(LinearLayout root, FragmentManager fragmentManager) {
|
||||||
|
TextView title = new TextView(root.getContext());
|
||||||
|
title.setText(friendlyName());
|
||||||
|
root.addView(title);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
Activity scanForActivity(Context cont) {
|
||||||
|
if (cont == null)
|
||||||
|
return null;
|
||||||
|
else if (cont instanceof Activity)
|
||||||
|
return (Activity) cont;
|
||||||
|
else if (cont instanceof ContextWrapper)
|
||||||
|
return scanForActivity(((ContextWrapper) cont).getBaseContext());
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,153 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.triggers;
|
||||||
|
|
||||||
|
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
|
import androidx.fragment.app.FragmentManager;
|
||||||
|
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.text.DecimalFormat;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
import info.nightscout.androidaps.R;
|
||||||
|
import info.nightscout.androidaps.logging.L;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.Comparator;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.InputDouble;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.LabelWithElement;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuilder;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.StaticLabel;
|
||||||
|
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensData;
|
||||||
|
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin;
|
||||||
|
import info.nightscout.androidaps.utils.DateUtil;
|
||||||
|
import info.nightscout.androidaps.utils.JsonHelper;
|
||||||
|
import info.nightscout.androidaps.utils.SP;
|
||||||
|
import info.nightscout.androidaps.utils.T;
|
||||||
|
|
||||||
|
public class TriggerAutosensValue extends Trigger {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
|
||||||
|
private final int minValue = (int) (SP.getDouble("openapsama_autosens_min", 0.7d) * 100);
|
||||||
|
private final int maxValue = (int) (SP.getDouble("openapsama_autosens_max", 1.2d) * 100);
|
||||||
|
private final double step = 1;
|
||||||
|
private DecimalFormat decimalFormat = new DecimalFormat("1");
|
||||||
|
private InputDouble value = new InputDouble(100, (double) minValue, (double) maxValue, step, decimalFormat);
|
||||||
|
private Comparator comparator = new Comparator();
|
||||||
|
|
||||||
|
public TriggerAutosensValue() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
private TriggerAutosensValue(TriggerAutosensValue triggerAutosensValue) {
|
||||||
|
super();
|
||||||
|
value = new InputDouble(triggerAutosensValue.value);
|
||||||
|
lastRun = triggerAutosensValue.lastRun;
|
||||||
|
comparator = new Comparator(triggerAutosensValue.comparator);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getValue() {
|
||||||
|
return value.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Comparator getComparator() {
|
||||||
|
return comparator;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized boolean shouldRun() {
|
||||||
|
AutosensData autosensData = IobCobCalculatorPlugin.getPlugin().getLastAutosensData("Automation trigger");
|
||||||
|
if (autosensData == null)
|
||||||
|
if (comparator.getValue() == Comparator.Compare.IS_NOT_AVAILABLE)
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (lastRun > DateUtil.now() - T.mins(5).msecs())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
boolean doRun = comparator.getValue().check((autosensData.autosensResult.ratio), getValue() / 100d);
|
||||||
|
if (doRun) {
|
||||||
|
if (L.isEnabled(L.AUTOMATION))
|
||||||
|
log.debug("Ready for execution: " + friendlyDescription());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized String toJSON() {
|
||||||
|
JSONObject o = new JSONObject();
|
||||||
|
try {
|
||||||
|
o.put("type", TriggerAutosensValue.class.getName());
|
||||||
|
JSONObject data = new JSONObject();
|
||||||
|
data.put("value", getValue());
|
||||||
|
data.put("lastRun", lastRun);
|
||||||
|
data.put("comparator", comparator.getValue().toString());
|
||||||
|
o.put("data", data);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return o.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
Trigger fromJSON(String data) {
|
||||||
|
try {
|
||||||
|
JSONObject d = new JSONObject(data);
|
||||||
|
value.setValue(JsonHelper.safeGetDouble(d, "value"));
|
||||||
|
lastRun = JsonHelper.safeGetLong(d, "lastRun");
|
||||||
|
comparator.setValue(Comparator.Compare.valueOf(JsonHelper.safeGetString(d, "comparator")));
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int friendlyName() {
|
||||||
|
return R.string.autosenslabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String friendlyDescription() {
|
||||||
|
return MainApp.gs(R.string.autosenscompared, MainApp.gs(comparator.getValue().getStringRes()), getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Integer> icon() {
|
||||||
|
return Optional.of(R.drawable.as);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Trigger duplicate() {
|
||||||
|
return new TriggerAutosensValue(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
TriggerAutosensValue setValue(int requestedValue) {
|
||||||
|
this.value.setValue(requestedValue);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
TriggerAutosensValue lastRun(long lastRun) {
|
||||||
|
this.lastRun = lastRun;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
TriggerAutosensValue comparator(Comparator.Compare compare) {
|
||||||
|
this.comparator = new Comparator().setValue(compare);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void generateDialog(LinearLayout root, FragmentManager fragmentManager) {
|
||||||
|
new LayoutBuilder()
|
||||||
|
.add(new StaticLabel(R.string.autosenslabel))
|
||||||
|
.add(comparator)
|
||||||
|
.add(new LabelWithElement(MainApp.gs(R.string.autosenslabel) + ": ", "", value))
|
||||||
|
.build(root);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,169 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.triggers;
|
||||||
|
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
|
import androidx.fragment.app.FragmentManager;
|
||||||
|
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.Constants;
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
import info.nightscout.androidaps.R;
|
||||||
|
import info.nightscout.androidaps.data.Profile;
|
||||||
|
import info.nightscout.androidaps.logging.L;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.Comparator;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.InputBg;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.LabelWithElement;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuilder;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.StaticLabel;
|
||||||
|
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus;
|
||||||
|
import info.nightscout.androidaps.utils.DateUtil;
|
||||||
|
import info.nightscout.androidaps.utils.JsonHelper;
|
||||||
|
import info.nightscout.androidaps.utils.T;
|
||||||
|
|
||||||
|
public class TriggerBg extends Trigger {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
|
||||||
|
|
||||||
|
private InputBg bg = new InputBg();
|
||||||
|
private Comparator comparator = new Comparator();
|
||||||
|
|
||||||
|
public TriggerBg() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
private TriggerBg(TriggerBg triggerBg) {
|
||||||
|
super();
|
||||||
|
bg = new InputBg(triggerBg.bg);
|
||||||
|
comparator = new Comparator(triggerBg.comparator);
|
||||||
|
lastRun = triggerBg.lastRun;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getValue() {
|
||||||
|
return bg.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Comparator getComparator() {
|
||||||
|
return comparator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUnits() {
|
||||||
|
return bg.getUnits();
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getLastRun() {
|
||||||
|
return lastRun;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized boolean shouldRun() {
|
||||||
|
GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData();
|
||||||
|
|
||||||
|
if (lastRun > DateUtil.now() - T.mins(5).msecs())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (glucoseStatus == null && comparator.getValue().equals(Comparator.Compare.IS_NOT_AVAILABLE)) {
|
||||||
|
if (L.isEnabled(L.AUTOMATION))
|
||||||
|
log.debug("Ready for execution: " + friendlyDescription());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (glucoseStatus == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
boolean doRun = comparator.getValue().check(glucoseStatus.glucose, Profile.toMgdl(bg.getValue(), bg.getUnits()));
|
||||||
|
if (doRun) {
|
||||||
|
if (L.isEnabled(L.AUTOMATION))
|
||||||
|
log.debug("Ready for execution: " + friendlyDescription());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized String toJSON() {
|
||||||
|
JSONObject o = new JSONObject();
|
||||||
|
try {
|
||||||
|
o.put("type", TriggerBg.class.getName());
|
||||||
|
JSONObject data = new JSONObject();
|
||||||
|
data.put("bg", bg.getValue());
|
||||||
|
data.put("lastRun", lastRun);
|
||||||
|
data.put("comparator", comparator.getValue().toString());
|
||||||
|
data.put("units", bg.getUnits());
|
||||||
|
o.put("data", data);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return o.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
Trigger fromJSON(String data) {
|
||||||
|
try {
|
||||||
|
JSONObject d = new JSONObject(data);
|
||||||
|
bg.setUnits(JsonHelper.safeGetString(d, "units"));
|
||||||
|
bg.setValue(JsonHelper.safeGetDouble(d, "bg"));
|
||||||
|
lastRun = JsonHelper.safeGetLong(d, "lastRun");
|
||||||
|
comparator.setValue(Comparator.Compare.valueOf(JsonHelper.safeGetString(d, "comparator")));
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int friendlyName() {
|
||||||
|
return R.string.glucose;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String friendlyDescription() {
|
||||||
|
if (comparator.getValue().equals(Comparator.Compare.IS_NOT_AVAILABLE))
|
||||||
|
return MainApp.gs(R.string.glucoseisnotavailable);
|
||||||
|
else {
|
||||||
|
return MainApp.gs(bg.getUnits().equals(Constants.MGDL) ? R.string.glucosecomparedmgdl : R.string.glucosecomparedmmol, MainApp.gs(comparator.getValue().getStringRes()), bg.getValue(), bg.getUnits());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Integer> icon() {
|
||||||
|
return Optional.of(R.drawable.icon_cp_bgcheck);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Trigger duplicate() {
|
||||||
|
return new TriggerBg(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
TriggerBg setValue(double value) {
|
||||||
|
bg.setValue(value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
TriggerBg lastRun(long lastRun) {
|
||||||
|
this.lastRun = lastRun;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
TriggerBg comparator(Comparator.Compare compare) {
|
||||||
|
this.comparator = new Comparator().setValue(compare);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
TriggerBg setUnits(String units) {
|
||||||
|
bg.setUnits(units);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void generateDialog(LinearLayout root, FragmentManager fragmentManager) {
|
||||||
|
new LayoutBuilder()
|
||||||
|
.add(new StaticLabel(R.string.glucose))
|
||||||
|
.add(comparator)
|
||||||
|
.add(new LabelWithElement(MainApp.gs(R.string.glucose_u, bg.getUnits()), "", bg))
|
||||||
|
.build(root);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,154 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.triggers;
|
||||||
|
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
|
import androidx.fragment.app.FragmentManager;
|
||||||
|
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.text.DecimalFormat;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
import info.nightscout.androidaps.R;
|
||||||
|
import info.nightscout.androidaps.logging.L;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.Comparator;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.InputDuration;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.LabelWithElement;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuilder;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.StaticLabel;
|
||||||
|
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
|
||||||
|
import info.nightscout.androidaps.utils.DateUtil;
|
||||||
|
import info.nightscout.androidaps.utils.JsonHelper;
|
||||||
|
import info.nightscout.androidaps.utils.T;
|
||||||
|
|
||||||
|
public class TriggerBolusAgo extends Trigger {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
|
||||||
|
private final double step = 1;
|
||||||
|
private DecimalFormat decimalFormat = new DecimalFormat("1");
|
||||||
|
public InputDuration minutesAgo = new InputDuration(0, InputDuration.TimeUnit.MINUTES);
|
||||||
|
private Comparator comparator = new Comparator();
|
||||||
|
|
||||||
|
public TriggerBolusAgo() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
private TriggerBolusAgo(TriggerBolusAgo triggerBolusAgo) {
|
||||||
|
super();
|
||||||
|
minutesAgo = new InputDuration(triggerBolusAgo.minutesAgo.getMinutes(), InputDuration.TimeUnit.MINUTES);
|
||||||
|
lastRun = triggerBolusAgo.lastRun;
|
||||||
|
comparator = new Comparator(triggerBolusAgo.comparator);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getValue() {
|
||||||
|
return minutesAgo.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Comparator getComparator() {
|
||||||
|
return comparator;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized boolean shouldRun() {
|
||||||
|
|
||||||
|
if (lastRun > DateUtil.now() - T.mins(5).msecs())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
long lastBolusTime = TreatmentsPlugin.getPlugin().getLastBolusTime(false);
|
||||||
|
|
||||||
|
if (lastBolusTime == 0)
|
||||||
|
if (comparator.getValue() == Comparator.Compare.IS_NOT_AVAILABLE)
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
|
||||||
|
double minutesAgo = (double) (DateUtil.now() - lastBolusTime) / (60 * 1000);
|
||||||
|
if (L.isEnabled(L.AUTOMATION))
|
||||||
|
log.debug("LastBolus min ago: " + minutesAgo);
|
||||||
|
|
||||||
|
boolean doRun = comparator.getValue().check((minutesAgo), getValue());
|
||||||
|
if (doRun) {
|
||||||
|
if (L.isEnabled(L.AUTOMATION))
|
||||||
|
log.debug("Ready for execution: " + friendlyDescription());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized String toJSON() {
|
||||||
|
JSONObject o = new JSONObject();
|
||||||
|
try {
|
||||||
|
o.put("type", TriggerBolusAgo.class.getName());
|
||||||
|
JSONObject data = new JSONObject();
|
||||||
|
data.put("minutesAgo", getValue());
|
||||||
|
data.put("lastRun", lastRun);
|
||||||
|
data.put("comparator", comparator.getValue().toString());
|
||||||
|
o.put("data", data);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return o.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
Trigger fromJSON(String data) {
|
||||||
|
try {
|
||||||
|
JSONObject d = new JSONObject(data);
|
||||||
|
minutesAgo.setMinutes(JsonHelper.safeGetInt(d, "minutesAgo"));
|
||||||
|
lastRun = JsonHelper.safeGetLong(d, "lastRun");
|
||||||
|
comparator.setValue(Comparator.Compare.valueOf(JsonHelper.safeGetString(d, "comparator")));
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int friendlyName() {
|
||||||
|
return R.string.lastboluslabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String friendlyDescription() {
|
||||||
|
return MainApp.gs(R.string.lastboluscompared, MainApp.gs(comparator.getValue().getStringRes()), (int) getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Integer> icon() {
|
||||||
|
return Optional.of(R.drawable.icon_bolus);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Trigger duplicate() {
|
||||||
|
return new TriggerBolusAgo(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
TriggerBolusAgo setValue(int requestedValue) {
|
||||||
|
this.minutesAgo.setMinutes(requestedValue);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
TriggerBolusAgo lastRun(long lastRun) {
|
||||||
|
this.lastRun = lastRun;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
TriggerBolusAgo comparator(Comparator.Compare compare) {
|
||||||
|
this.comparator = new Comparator().setValue(compare);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void generateDialog(LinearLayout root, FragmentManager fragmentManager) {
|
||||||
|
new LayoutBuilder()
|
||||||
|
.add(new StaticLabel(R.string.lastboluslabel))
|
||||||
|
.add(comparator)
|
||||||
|
.add(new LabelWithElement(MainApp.gs(R.string.lastboluslabel) + ": ", "", minutesAgo))
|
||||||
|
.build(root);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,153 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.triggers;
|
||||||
|
|
||||||
|
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
|
import androidx.fragment.app.FragmentManager;
|
||||||
|
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.text.DecimalFormat;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
import info.nightscout.androidaps.R;
|
||||||
|
import info.nightscout.androidaps.logging.L;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.Comparator;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.InputDouble;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.LabelWithElement;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuilder;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.StaticLabel;
|
||||||
|
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.CobInfo;
|
||||||
|
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin;
|
||||||
|
import info.nightscout.androidaps.utils.DateUtil;
|
||||||
|
import info.nightscout.androidaps.utils.JsonHelper;
|
||||||
|
import info.nightscout.androidaps.utils.SP;
|
||||||
|
import info.nightscout.androidaps.utils.T;
|
||||||
|
|
||||||
|
public class TriggerCOB extends Trigger {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
|
||||||
|
private final int minValue = 0;
|
||||||
|
private final int maxValue = (int) (SP.getInt(R.string.key_treatmentssafety_maxcarbs, 48));
|
||||||
|
private final double step = 1;
|
||||||
|
private DecimalFormat decimalFormat = new DecimalFormat("1");
|
||||||
|
private InputDouble value = new InputDouble(0, (double) minValue, (double) maxValue, step, decimalFormat);
|
||||||
|
private Comparator comparator = new Comparator();
|
||||||
|
|
||||||
|
public TriggerCOB() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
private TriggerCOB(TriggerCOB triggerCOB) {
|
||||||
|
super();
|
||||||
|
value = new InputDouble(triggerCOB.value);
|
||||||
|
lastRun = triggerCOB.lastRun;
|
||||||
|
comparator = new Comparator(triggerCOB.comparator);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getValue() {
|
||||||
|
return value.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Comparator getComparator() {
|
||||||
|
return comparator;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized boolean shouldRun() {
|
||||||
|
CobInfo cobInfo = IobCobCalculatorPlugin.getPlugin().getCobInfo(false, "AutomationTriggerCOB");
|
||||||
|
if (cobInfo == null)
|
||||||
|
if (comparator.getValue() == Comparator.Compare.IS_NOT_AVAILABLE)
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (lastRun > DateUtil.now() - T.mins(5).msecs())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
boolean doRun = comparator.getValue().check((cobInfo.displayCob), getValue());
|
||||||
|
if (doRun) {
|
||||||
|
if (L.isEnabled(L.AUTOMATION))
|
||||||
|
log.debug("Ready for execution: " + friendlyDescription());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized String toJSON() {
|
||||||
|
JSONObject o = new JSONObject();
|
||||||
|
try {
|
||||||
|
o.put("type", TriggerCOB.class.getName());
|
||||||
|
JSONObject data = new JSONObject();
|
||||||
|
data.put("carbs", getValue());
|
||||||
|
data.put("lastRun", lastRun);
|
||||||
|
data.put("comparator", comparator.getValue().toString());
|
||||||
|
o.put("data", data);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return o.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
Trigger fromJSON(String data) {
|
||||||
|
try {
|
||||||
|
JSONObject d = new JSONObject(data);
|
||||||
|
value.setValue(JsonHelper.safeGetDouble(d, "carbs"));
|
||||||
|
lastRun = JsonHelper.safeGetLong(d, "lastRun");
|
||||||
|
comparator.setValue(Comparator.Compare.valueOf(JsonHelper.safeGetString(d, "comparator")));
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int friendlyName() {
|
||||||
|
return R.string.triggercoblabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String friendlyDescription() {
|
||||||
|
return MainApp.gs(R.string.cobcompared, MainApp.gs(comparator.getValue().getStringRes()), getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Integer> icon() {
|
||||||
|
return Optional.of(R.drawable.icon_cp_bolus_carbs);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Trigger duplicate() {
|
||||||
|
return new TriggerCOB(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
TriggerCOB setValue(int requestedValue) {
|
||||||
|
this.value.setValue(requestedValue);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
TriggerCOB lastRun(long lastRun) {
|
||||||
|
this.lastRun = lastRun;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
TriggerCOB comparator(Comparator.Compare compare) {
|
||||||
|
this.comparator = new Comparator().setValue(compare);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void generateDialog(LinearLayout root, FragmentManager fragmentManager) {
|
||||||
|
new LayoutBuilder()
|
||||||
|
.add(new StaticLabel(R.string.triggercoblabel))
|
||||||
|
.add(comparator)
|
||||||
|
.add(new LabelWithElement(MainApp.gs(R.string.triggercoblabel) + ": ", "", value))
|
||||||
|
.build(root);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,277 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.triggers;
|
||||||
|
|
||||||
|
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
|
import androidx.annotation.StringRes;
|
||||||
|
import androidx.fragment.app.FragmentManager;
|
||||||
|
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
|
||||||
|
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.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
import info.nightscout.androidaps.R;
|
||||||
|
import info.nightscout.androidaps.logging.L;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.dialogs.TriggerListAdapter;
|
||||||
|
import info.nightscout.androidaps.utils.JsonHelper;
|
||||||
|
|
||||||
|
public class TriggerConnector extends Trigger {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
|
||||||
|
|
||||||
|
public enum Type {
|
||||||
|
AND,
|
||||||
|
OR,
|
||||||
|
XOR;
|
||||||
|
|
||||||
|
public boolean apply(boolean a, boolean b) {
|
||||||
|
switch (this) {
|
||||||
|
case AND:
|
||||||
|
return a && b;
|
||||||
|
case OR:
|
||||||
|
return a || b;
|
||||||
|
case XOR:
|
||||||
|
return a ^ b;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public @StringRes
|
||||||
|
int getStringRes() {
|
||||||
|
switch (this) {
|
||||||
|
case OR:
|
||||||
|
return R.string.or;
|
||||||
|
case XOR:
|
||||||
|
return R.string.xor;
|
||||||
|
|
||||||
|
default:
|
||||||
|
case AND:
|
||||||
|
return R.string.and;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<String> labels() {
|
||||||
|
List<String> list = new ArrayList<>();
|
||||||
|
for (Type t : values()) {
|
||||||
|
list.add(MainApp.gs(t.getStringRes()));
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void fillIconSet(TriggerConnector connector, HashSet<Integer> set) {
|
||||||
|
for (Trigger t : connector.list) {
|
||||||
|
if (t instanceof TriggerConnector) {
|
||||||
|
fillIconSet((TriggerConnector) t, set);
|
||||||
|
} else {
|
||||||
|
Optional<Integer> icon = t.icon();
|
||||||
|
if (icon.isPresent()) {
|
||||||
|
set.add(icon.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<Trigger> list = new ArrayList<>();
|
||||||
|
private Type connectorType;
|
||||||
|
|
||||||
|
public TriggerConnector() {
|
||||||
|
connectorType = Type.AND;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TriggerConnector(Type connectorType) {
|
||||||
|
this.connectorType = connectorType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void changeConnectorType(Type type) {
|
||||||
|
this.connectorType = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type getConnectorType() {
|
||||||
|
return connectorType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void add(Trigger t) {
|
||||||
|
list.add(t);
|
||||||
|
t.connector = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void add(int pos, Trigger t) {
|
||||||
|
list.add(pos, t);
|
||||||
|
t.connector = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized boolean remove(Trigger t) {
|
||||||
|
return list.remove(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int size() {
|
||||||
|
return list.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Trigger get(int i) {
|
||||||
|
return list.get(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int pos(Trigger trigger) {
|
||||||
|
for (int i = 0; i < list.size(); ++i) {
|
||||||
|
if (list.get(i) == trigger) return i;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized boolean shouldRun() {
|
||||||
|
boolean result = true;
|
||||||
|
|
||||||
|
// check first trigger
|
||||||
|
if (list.size() > 0)
|
||||||
|
result = list.get(0).shouldRun();
|
||||||
|
|
||||||
|
// check all others
|
||||||
|
for (int i = 1; i < list.size(); ++i) {
|
||||||
|
result = connectorType.apply(result, list.get(i).shouldRun());
|
||||||
|
}
|
||||||
|
if (result)
|
||||||
|
if (L.isEnabled(L.AUTOMATION))
|
||||||
|
log.debug("Ready for execution: " + friendlyDescription().replace("\n", " "));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized String toJSON() {
|
||||||
|
JSONObject o = new JSONObject();
|
||||||
|
try {
|
||||||
|
o.put("type", TriggerConnector.class.getName());
|
||||||
|
JSONObject data = new JSONObject();
|
||||||
|
data.put("connectorType", connectorType.toString());
|
||||||
|
JSONArray array = new JSONArray();
|
||||||
|
for (Trigger t : list) {
|
||||||
|
array.put(t.toJSON());
|
||||||
|
}
|
||||||
|
data.put("triggerList", array);
|
||||||
|
o.put("data", data);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return o.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
Trigger fromJSON(String data) {
|
||||||
|
try {
|
||||||
|
JSONObject d = new JSONObject(data);
|
||||||
|
connectorType = Type.valueOf(JsonHelper.safeGetString(d, "connectorType"));
|
||||||
|
JSONArray array = d.getJSONArray("triggerList");
|
||||||
|
list.clear();
|
||||||
|
for (int i = 0; i < array.length(); i++) {
|
||||||
|
Trigger newItem = instantiate(new JSONObject(array.getString(i)));
|
||||||
|
add(newItem);
|
||||||
|
}
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int friendlyName() {
|
||||||
|
return connectorType.getStringRes();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String friendlyDescription() {
|
||||||
|
int counter = 0;
|
||||||
|
StringBuilder result = new StringBuilder();
|
||||||
|
for (Trigger t : list) {
|
||||||
|
if (counter++ > 0) result.append("\n").append(MainApp.gs(friendlyName())).append("\n");
|
||||||
|
result.append(t.friendlyDescription());
|
||||||
|
}
|
||||||
|
return result.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Integer> icon() {
|
||||||
|
return Optional.absent();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void executed(long time) {
|
||||||
|
for (int i = 0; i < list.size(); ++i) {
|
||||||
|
list.get(i).executed(time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Trigger duplicate() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private TriggerListAdapter adapter;
|
||||||
|
|
||||||
|
public void rebuildView(FragmentManager fragmentManager) {
|
||||||
|
if (adapter != null)
|
||||||
|
adapter.rebuild(fragmentManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void generateDialog(LinearLayout root, FragmentManager fragmentManager) {
|
||||||
|
final int padding = MainApp.dpToPx(5);
|
||||||
|
|
||||||
|
root.setPadding(padding, padding, padding, padding);
|
||||||
|
root.setBackgroundResource(R.drawable.border_automation_unit);
|
||||||
|
|
||||||
|
LinearLayout triggerListLayout = new LinearLayout(root.getContext());
|
||||||
|
triggerListLayout.setOrientation(LinearLayout.VERTICAL);
|
||||||
|
triggerListLayout.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||||
|
root.addView(triggerListLayout);
|
||||||
|
|
||||||
|
adapter = new TriggerListAdapter(fragmentManager, root.getContext(), triggerListLayout, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TriggerConnector simplify() {
|
||||||
|
// simplify children
|
||||||
|
for (int i = 0; i < size(); ++i) {
|
||||||
|
if (get(i) instanceof TriggerConnector) {
|
||||||
|
TriggerConnector t = (TriggerConnector) get(i);
|
||||||
|
t.simplify();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// drop connector with only 1 element
|
||||||
|
if (size() == 1 && get(0) instanceof TriggerConnector) {
|
||||||
|
TriggerConnector c = (TriggerConnector) get(0);
|
||||||
|
remove(c);
|
||||||
|
changeConnectorType(c.getConnectorType());
|
||||||
|
for (Trigger t : c.list) {
|
||||||
|
add(t);
|
||||||
|
}
|
||||||
|
c.list.clear();
|
||||||
|
return simplify();
|
||||||
|
}
|
||||||
|
|
||||||
|
// merge connectors
|
||||||
|
if (connector != null && (connector.getConnectorType().equals(connectorType) || size() == 1)) {
|
||||||
|
final int pos = connector.pos(this);
|
||||||
|
connector.remove(this);
|
||||||
|
// move triggers of child connector into parent connector
|
||||||
|
for (int i = size() - 1; i >= 0; --i) {
|
||||||
|
connector.add(pos, get(i));
|
||||||
|
}
|
||||||
|
list.clear();
|
||||||
|
return connector.simplify();
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,208 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.triggers;
|
||||||
|
|
||||||
|
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
|
import androidx.fragment.app.FragmentManager;
|
||||||
|
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.text.DecimalFormat;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.Constants;
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
import info.nightscout.androidaps.R;
|
||||||
|
import info.nightscout.androidaps.data.Profile;
|
||||||
|
import info.nightscout.androidaps.logging.L;
|
||||||
|
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.Comparator;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.InputDelta;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.InputDelta.DeltaType;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.LabelWithElement;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuilder;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.StaticLabel;
|
||||||
|
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus;
|
||||||
|
import info.nightscout.androidaps.utils.DateUtil;
|
||||||
|
import info.nightscout.androidaps.utils.JsonHelper;
|
||||||
|
import info.nightscout.androidaps.utils.T;
|
||||||
|
|
||||||
|
public class TriggerDelta extends Trigger {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
|
||||||
|
private double minValue = 0d;
|
||||||
|
private double maxValue = 1d;
|
||||||
|
private double step = 1;
|
||||||
|
private DecimalFormat decimalFormat = new DecimalFormat("1");
|
||||||
|
private String units;
|
||||||
|
private DeltaType deltaType;
|
||||||
|
|
||||||
|
private InputDelta value = new InputDelta( (double) minValue,(double) minValue, (double) maxValue, step, decimalFormat, deltaType);
|
||||||
|
private Comparator comparator = new Comparator();
|
||||||
|
|
||||||
|
public TriggerDelta() {
|
||||||
|
super();
|
||||||
|
this.units = ProfileFunctions.getInstance().getProfileUnits();
|
||||||
|
initializer();
|
||||||
|
}
|
||||||
|
|
||||||
|
private TriggerDelta(TriggerDelta triggerDelta) {
|
||||||
|
super();
|
||||||
|
this.units = ProfileFunctions.getInstance().getProfileUnits();
|
||||||
|
initializer();
|
||||||
|
value = triggerDelta.value;
|
||||||
|
lastRun = triggerDelta.lastRun;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getValue() {
|
||||||
|
deltaType = value.getDeltaType();
|
||||||
|
return value.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public DeltaType getType() {
|
||||||
|
return deltaType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUnits() {
|
||||||
|
return this.units;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Comparator getComparator() {
|
||||||
|
return comparator;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized boolean shouldRun() {
|
||||||
|
GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData();
|
||||||
|
if (glucoseStatus == null)
|
||||||
|
if (comparator.getValue() == Comparator.Compare.IS_NOT_AVAILABLE)
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Setting type of delta
|
||||||
|
double delta;
|
||||||
|
|
||||||
|
if (deltaType == DeltaType.SHORT_AVERAGE)
|
||||||
|
delta = glucoseStatus.short_avgdelta;
|
||||||
|
else if (deltaType == DeltaType.LONG_AVERAGE)
|
||||||
|
delta = glucoseStatus.long_avgdelta;
|
||||||
|
else
|
||||||
|
delta = glucoseStatus.delta;
|
||||||
|
|
||||||
|
if (lastRun > DateUtil.now() - T.mins(5).msecs())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
boolean doRun = comparator.getValue().check(delta, Profile.toMgdl(value.getValue(), this.units));
|
||||||
|
if (doRun) {
|
||||||
|
if (L.isEnabled(L.AUTOMATION))
|
||||||
|
log.debug("Ready for execution: delta is " + delta + " " + friendlyDescription());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized String toJSON() {
|
||||||
|
JSONObject o = new JSONObject();
|
||||||
|
try {
|
||||||
|
o.put("type", TriggerDelta.class.getName());
|
||||||
|
JSONObject data = new JSONObject();
|
||||||
|
data.put("value", getValue());
|
||||||
|
data.put("units", units);
|
||||||
|
data.put("lastRun", lastRun);
|
||||||
|
data.put("deltaType", getType());
|
||||||
|
data.put("comparator", comparator.getValue().toString());
|
||||||
|
o.put("data", data);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return o.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
Trigger fromJSON(String data) {
|
||||||
|
try {
|
||||||
|
JSONObject d = new JSONObject(data);
|
||||||
|
units = JsonHelper.safeGetString(d, "units");
|
||||||
|
deltaType = DeltaType.valueOf(JsonHelper.safeGetString(d, "deltaType", ""));
|
||||||
|
value.setValue(JsonHelper.safeGetDouble(d, "value"), deltaType);
|
||||||
|
lastRun = JsonHelper.safeGetLong(d, "lastRun");
|
||||||
|
comparator.setValue(Comparator.Compare.valueOf(JsonHelper.safeGetString(d, "comparator")));
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int friendlyName() {
|
||||||
|
return R.string.deltalabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String friendlyDescription() {
|
||||||
|
return MainApp.gs(R.string.deltacompared, MainApp.gs(comparator.getValue().getStringRes()), getValue(), MainApp.gs(deltaType.getStringRes()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Integer> icon() {
|
||||||
|
return Optional.of(R.drawable.icon_auto_delta);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Trigger duplicate() {
|
||||||
|
return new TriggerDelta(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
TriggerDelta setValue(double requestedValue, DeltaType requestedType) {
|
||||||
|
this.value.setValue(requestedValue, requestedType);
|
||||||
|
this.deltaType = requestedType;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
TriggerDelta setUnits(String units) {
|
||||||
|
this.units = units;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void initializer(){
|
||||||
|
if (this.units.equals(Constants.MMOL)) {
|
||||||
|
this.maxValue = 4d;
|
||||||
|
this.minValue = -4d;
|
||||||
|
this.step = 0.1d;
|
||||||
|
this.decimalFormat = new DecimalFormat("0.1");
|
||||||
|
this.deltaType = DeltaType.DELTA;
|
||||||
|
} else {
|
||||||
|
this.maxValue = 72d;
|
||||||
|
this.minValue = -72d;
|
||||||
|
this.step = 1d;
|
||||||
|
this.deltaType = DeltaType.DELTA;
|
||||||
|
}
|
||||||
|
value = new InputDelta( (double) minValue,(double) minValue, (double) maxValue, step, decimalFormat, deltaType);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TriggerDelta lastRun(long lastRun) {
|
||||||
|
this.lastRun = lastRun;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
TriggerDelta comparator(Comparator.Compare compare) {
|
||||||
|
this.comparator = new Comparator().setValue(compare);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void generateDialog(LinearLayout root, FragmentManager fragmentManager) {
|
||||||
|
new LayoutBuilder()
|
||||||
|
.add(new StaticLabel(R.string.deltalabel))
|
||||||
|
.add(comparator)
|
||||||
|
.add(new LabelWithElement(MainApp.gs(R.string.deltalabel) + ": ", "", value))
|
||||||
|
.build(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,146 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.triggers;
|
||||||
|
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
|
import androidx.fragment.app.FragmentManager;
|
||||||
|
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
|
||||||
|
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.data.IobTotal;
|
||||||
|
import info.nightscout.androidaps.data.Profile;
|
||||||
|
import info.nightscout.androidaps.logging.L;
|
||||||
|
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.Comparator;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.InputInsulin;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.LabelWithElement;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuilder;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.StaticLabel;
|
||||||
|
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin;
|
||||||
|
import info.nightscout.androidaps.utils.DateUtil;
|
||||||
|
import info.nightscout.androidaps.utils.JsonHelper;
|
||||||
|
import info.nightscout.androidaps.utils.T;
|
||||||
|
|
||||||
|
public class TriggerIob extends Trigger {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
|
||||||
|
|
||||||
|
private InputInsulin insulin = new InputInsulin();
|
||||||
|
private Comparator comparator = new Comparator();
|
||||||
|
|
||||||
|
public TriggerIob() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
private TriggerIob(TriggerIob triggerIob) {
|
||||||
|
super();
|
||||||
|
insulin = new InputInsulin(triggerIob.insulin);
|
||||||
|
comparator = new Comparator(triggerIob.comparator);
|
||||||
|
lastRun = triggerIob.lastRun;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getValue() {
|
||||||
|
return insulin.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Comparator getComparator() {
|
||||||
|
return comparator;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized boolean shouldRun() {
|
||||||
|
Profile profile = ProfileFunctions.getInstance().getProfile();
|
||||||
|
if (profile == null)
|
||||||
|
return false;
|
||||||
|
IobTotal iob = IobCobCalculatorPlugin.getPlugin().calculateFromTreatmentsAndTempsSynchronized(DateUtil.now(), profile);
|
||||||
|
|
||||||
|
if (lastRun > DateUtil.now() - T.mins(5).msecs())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
boolean doRun = comparator.getValue().check(iob.iob, getValue());
|
||||||
|
if (doRun) {
|
||||||
|
if (L.isEnabled(L.AUTOMATION))
|
||||||
|
log.debug("Ready for execution: " + friendlyDescription());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized String toJSON() {
|
||||||
|
JSONObject o = new JSONObject();
|
||||||
|
try {
|
||||||
|
o.put("type", TriggerIob.class.getName());
|
||||||
|
JSONObject data = new JSONObject();
|
||||||
|
data.put("insulin", getValue());
|
||||||
|
data.put("lastRun", lastRun);
|
||||||
|
data.put("comparator", comparator.getValue().toString());
|
||||||
|
o.put("data", data);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return o.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
Trigger fromJSON(String data) {
|
||||||
|
try {
|
||||||
|
JSONObject d = new JSONObject(data);
|
||||||
|
insulin.setValue(JsonHelper.safeGetDouble(d, "insulin"));
|
||||||
|
lastRun = JsonHelper.safeGetLong(d, "lastRun");
|
||||||
|
comparator.setValue(Comparator.Compare.valueOf(JsonHelper.safeGetString(d, "comparator")));
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int friendlyName() {
|
||||||
|
return R.string.iob;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String friendlyDescription() {
|
||||||
|
return MainApp.gs(R.string.iobcompared, MainApp.gs(comparator.getValue().getStringRes()), getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Integer> icon() {
|
||||||
|
return Optional.of(R.drawable.ic_keyboard_capslock);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Trigger duplicate() {
|
||||||
|
return new TriggerIob(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
TriggerIob setValue(double threshold) {
|
||||||
|
insulin.setValue(threshold);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
TriggerIob lastRun(long lastRun) {
|
||||||
|
this.lastRun = lastRun;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
TriggerIob comparator(Comparator.Compare compare) {
|
||||||
|
this.comparator = new Comparator().setValue(compare);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void generateDialog(LinearLayout root, FragmentManager fragmentManager) {
|
||||||
|
new LayoutBuilder()
|
||||||
|
.add(new StaticLabel(R.string.iob))
|
||||||
|
.add(comparator)
|
||||||
|
.add(new LabelWithElement(MainApp.gs(R.string.iob_u), "", insulin))
|
||||||
|
.build(root);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,167 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.triggers;
|
||||||
|
|
||||||
|
import android.location.Location;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
|
import androidx.fragment.app.FragmentManager;
|
||||||
|
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.text.DecimalFormat;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
import info.nightscout.androidaps.R;
|
||||||
|
import info.nightscout.androidaps.logging.L;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.InputButton;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.InputDouble;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.InputString;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.LabelWithElement;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuilder;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.StaticLabel;
|
||||||
|
import info.nightscout.androidaps.services.LocationService;
|
||||||
|
import info.nightscout.androidaps.utils.DateUtil;
|
||||||
|
import info.nightscout.androidaps.utils.JsonHelper;
|
||||||
|
import info.nightscout.androidaps.utils.T;
|
||||||
|
|
||||||
|
public class TriggerLocation extends Trigger {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
|
||||||
|
|
||||||
|
InputDouble latitude = new InputDouble(0d, -90d, +90d, 0.000001d, new DecimalFormat("0.000000"));
|
||||||
|
InputDouble longitude = new InputDouble(0d, -180d, +180d, 0.000001d, new DecimalFormat("0.000000"));
|
||||||
|
InputDouble distance = new InputDouble(200d, 0, 100000, 10d, new DecimalFormat("0"));
|
||||||
|
InputString name = new InputString();
|
||||||
|
|
||||||
|
private Runnable buttonAction = () -> {
|
||||||
|
Location location = LocationService.getLastLocation();
|
||||||
|
if (location != null) {
|
||||||
|
latitude.setValue(location.getLatitude());
|
||||||
|
longitude.setValue(location.getLongitude());
|
||||||
|
log.debug(String.format("Grabbed location: %f %f", latitude.getValue(), longitude.getValue()));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public TriggerLocation() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
private TriggerLocation(TriggerLocation triggerLocation) {
|
||||||
|
super();
|
||||||
|
latitude = new InputDouble(triggerLocation.latitude.getValue(), -90d, +90d, 0.00001d, new DecimalFormat("0.00000"));
|
||||||
|
longitude = new InputDouble(triggerLocation.longitude.getValue(), -180d, +180d, 0.00001d, new DecimalFormat("0.00000"));
|
||||||
|
distance = new InputDouble(200d, 0, 100000, 10d, new DecimalFormat("0"));
|
||||||
|
lastRun = triggerLocation.lastRun;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized boolean shouldRun() {
|
||||||
|
Location location = LocationService.getLastLocation();
|
||||||
|
if (location == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (lastRun > DateUtil.now() - T.mins(5).msecs())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Location a = new Location("Trigger");
|
||||||
|
a.setLatitude(latitude.getValue());
|
||||||
|
a.setLongitude(longitude.getValue());
|
||||||
|
double calculatedDistance = location.distanceTo(a);
|
||||||
|
|
||||||
|
if (calculatedDistance < distance.getValue()) {
|
||||||
|
if (L.isEnabled(L.AUTOMATION))
|
||||||
|
log.debug("Ready for execution: " + friendlyDescription());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized String toJSON() {
|
||||||
|
JSONObject o = new JSONObject();
|
||||||
|
try {
|
||||||
|
o.put("type", TriggerLocation.class.getName());
|
||||||
|
JSONObject data = new JSONObject();
|
||||||
|
data.put("latitude", latitude.getValue());
|
||||||
|
data.put("longitude", longitude.getValue());
|
||||||
|
data.put("distance", distance.getValue());
|
||||||
|
data.put("name", name.getValue());
|
||||||
|
data.put("lastRun", lastRun);
|
||||||
|
o.put("data", data);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return o.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
Trigger fromJSON(String data) {
|
||||||
|
try {
|
||||||
|
JSONObject d = new JSONObject(data);
|
||||||
|
latitude.setValue(JsonHelper.safeGetDouble(d, "latitude"));
|
||||||
|
longitude.setValue(JsonHelper.safeGetDouble(d, "longitude"));
|
||||||
|
distance.setValue(JsonHelper.safeGetDouble(d, "distance"));
|
||||||
|
name.setValue(JsonHelper.safeGetString(d, "name"));
|
||||||
|
lastRun = JsonHelper.safeGetLong(d, "lastRun");
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int friendlyName() {
|
||||||
|
return R.string.location;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String friendlyDescription() {
|
||||||
|
return MainApp.gs(R.string.locationis, name.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Integer> icon() {
|
||||||
|
return Optional.of(R.drawable.ic_location_on);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Trigger duplicate() {
|
||||||
|
return new TriggerLocation(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TriggerLocation setLatitude(double value) {
|
||||||
|
latitude.setValue(value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
TriggerLocation setLongitude(double value) {
|
||||||
|
longitude.setValue(value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
TriggerLocation setdistance(double value) {
|
||||||
|
distance.setValue(value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
TriggerLocation lastRun(long lastRun) {
|
||||||
|
this.lastRun = lastRun;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void generateDialog(LinearLayout root, FragmentManager fragmentManager) {
|
||||||
|
new LayoutBuilder()
|
||||||
|
.add(new StaticLabel(R.string.location))
|
||||||
|
.add(new LabelWithElement(MainApp.gs(R.string.name_short), "", name))
|
||||||
|
.add(new LabelWithElement(MainApp.gs(R.string.latitude_short), "", latitude))
|
||||||
|
.add(new LabelWithElement(MainApp.gs(R.string.longitude_short), "", longitude))
|
||||||
|
.add(new LabelWithElement(MainApp.gs(R.string.distance_short), "", distance))
|
||||||
|
.add(new InputButton(MainApp.gs(R.string.currentlocation), buttonAction), LocationService.getLastLocation() != null)
|
||||||
|
.build(root);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,152 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.automation.triggers;
|
||||||
|
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
|
import androidx.fragment.app.FragmentManager;
|
||||||
|
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
|
||||||
|
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.data.Profile;
|
||||||
|
import info.nightscout.androidaps.logging.L;
|
||||||
|
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.Comparator;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.InputPercent;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.LabelWithElement;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuilder;
|
||||||
|
import info.nightscout.androidaps.plugins.general.automation.elements.StaticLabel;
|
||||||
|
import info.nightscout.androidaps.utils.DateUtil;
|
||||||
|
import info.nightscout.androidaps.utils.JsonHelper;
|
||||||
|
import info.nightscout.androidaps.utils.T;
|
||||||
|
|
||||||
|
public class TriggerProfilePercent extends Trigger {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
|
||||||
|
|
||||||
|
private InputPercent pct = new InputPercent();
|
||||||
|
private Comparator comparator = new Comparator();
|
||||||
|
|
||||||
|
public TriggerProfilePercent() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
private TriggerProfilePercent(TriggerProfilePercent triggerProfilePercent) {
|
||||||
|
super();
|
||||||
|
pct = new InputPercent(triggerProfilePercent.pct);
|
||||||
|
comparator = new Comparator(triggerProfilePercent.comparator);
|
||||||
|
lastRun = triggerProfilePercent.lastRun;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getValue() {
|
||||||
|
return pct.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Comparator getComparator() {
|
||||||
|
return comparator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getLastRun() {
|
||||||
|
return lastRun;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized boolean shouldRun() {
|
||||||
|
if (lastRun > DateUtil.now() - T.mins(5).msecs())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Profile profile = ProfileFunctions.getInstance().getProfile();
|
||||||
|
if (profile == null && comparator.getValue().equals(Comparator.Compare.IS_NOT_AVAILABLE)) {
|
||||||
|
if (L.isEnabled(L.AUTOMATION))
|
||||||
|
log.debug("Ready for execution: " + friendlyDescription());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (profile == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
boolean doRun = comparator.getValue().check((double) profile.getPercentage(), pct.getValue());
|
||||||
|
if (doRun) {
|
||||||
|
if (L.isEnabled(L.AUTOMATION))
|
||||||
|
log.debug("Ready for execution: " + friendlyDescription());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized String toJSON() {
|
||||||
|
JSONObject o = new JSONObject();
|
||||||
|
try {
|
||||||
|
o.put("type", TriggerProfilePercent.class.getName());
|
||||||
|
JSONObject data = new JSONObject();
|
||||||
|
data.put("percentage", pct.getValue());
|
||||||
|
data.put("lastRun", lastRun);
|
||||||
|
data.put("comparator", comparator.getValue().toString());
|
||||||
|
o.put("data", data);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return o.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
Trigger fromJSON(String data) {
|
||||||
|
try {
|
||||||
|
JSONObject d = new JSONObject(data);
|
||||||
|
pct.setValue(JsonHelper.safeGetDouble(d, "percentage"));
|
||||||
|
lastRun = JsonHelper.safeGetLong(d, "lastRun");
|
||||||
|
comparator.setValue(Comparator.Compare.valueOf(JsonHelper.safeGetString(d, "comparator")));
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int friendlyName() {
|
||||||
|
return R.string.profilepercentage;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String friendlyDescription() {
|
||||||
|
return MainApp.gs(R.string.percentagecompared, MainApp.gs(comparator.getValue().getStringRes()), (int) pct.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Integer> icon() {
|
||||||
|
return Optional.of(R.drawable.icon_actions_profileswitch);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Trigger duplicate() {
|
||||||
|
return new TriggerProfilePercent(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TriggerProfilePercent setValue(double value) {
|
||||||
|
pct.setValue(value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
TriggerProfilePercent lastRun(long lastRun) {
|
||||||
|
this.lastRun = lastRun;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TriggerProfilePercent comparator(Comparator.Compare compare) {
|
||||||
|
this.comparator = new Comparator().setValue(compare);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void generateDialog(LinearLayout root, FragmentManager fragmentManager) {
|
||||||
|
new LayoutBuilder()
|
||||||
|
.add(new StaticLabel(R.string.profilepercentage))
|
||||||
|
.add(comparator)
|
||||||
|
.add(new LabelWithElement(MainApp.gs(R.string.percent_u), "", pct))
|
||||||
|
.build(root);
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue