Merge branch 'dev' of https://github.com/MilosKozak/AndroidAPS into dev
This commit is contained in:
commit
acff61339c
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -7,3 +7,7 @@
|
|||
*.apk
|
||||
build/
|
||||
.idea/
|
||||
app/src/main/jniLibs
|
||||
full/
|
||||
debug/
|
||||
release/
|
16
.travis.yml
16
.travis.yml
|
@ -2,7 +2,7 @@ language: android
|
|||
jdk: oraclejdk8
|
||||
env:
|
||||
matrix:
|
||||
- ANDROID_TARGET=android-23 ANDROID_ABI=x86
|
||||
- ANDROID_TARGET=android-23 ANDROID_ABI=x86 org.gradle.jvmargs=-XX:-OmitStackTraceInFastThrow
|
||||
android:
|
||||
components:
|
||||
- platform-tools
|
||||
|
@ -18,7 +18,17 @@ before_install:
|
|||
|
||||
script:
|
||||
# Unit Test
|
||||
- ./gradlew test jacocoTestReport
|
||||
- ./gradlew -Pcoverage testFullDebugUnitTest jacocoTestFullDebugUnitTestReport
|
||||
|
||||
after_success:
|
||||
- bash <(curl -s https://codecov.io/bash)
|
||||
- bash <(curl -s https://codecov.io/bash)
|
||||
|
||||
before_cache:
|
||||
- rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
|
||||
- rm -fr $HOME/.gradle/caches/*/plugin-resolution/
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.gradle/caches/
|
||||
- $HOME/.gradle/wrapper/
|
||||
- $HOME/.android/build-cache
|
1
app/.gitignore
vendored
1
app/.gitignore
vendored
|
@ -1 +0,0 @@
|
|||
/build
|
164
app/build.gradle
164
app/build.gradle
|
@ -15,15 +15,17 @@ apply plugin: "jacoco-android"
|
|||
apply plugin: 'com.jakewharton.butterknife'
|
||||
|
||||
ext {
|
||||
supportLibraryVersion = "27.0.2"
|
||||
supportLibraryVersion = "27.1.0"
|
||||
ormLiteVersion = "4.46"
|
||||
powermockVersion = "1.7.3"
|
||||
dexmakerVersion = "1.2"
|
||||
butterknifeVersion = "8.8.1"
|
||||
}
|
||||
|
||||
|
||||
repositories {
|
||||
maven { url 'https://maven.fabric.io/public' }
|
||||
jcenter { url "https://jcenter.bintray.com/" }
|
||||
}
|
||||
|
||||
def generateGitBuild = { ->
|
||||
|
@ -47,19 +49,24 @@ def generateGitBuild = { ->
|
|||
return stringBuilder.toString()
|
||||
}
|
||||
|
||||
tasks.matching {it instanceof Test}.all {
|
||||
testLogging.events = ["failed", "skipped", "started"]
|
||||
testLogging.exceptionFormat = "full"
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 27
|
||||
buildToolsVersion "${supportLibraryVersion}"
|
||||
|
||||
defaultConfig {
|
||||
applicationId "info.nightscout.androidaps"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 23
|
||||
targetSdkVersion 25
|
||||
multiDexEnabled true
|
||||
versionCode 1500
|
||||
version "1.58"
|
||||
version "1.60e-dev"
|
||||
buildConfigField "String", "VERSION", '"' + version + '"'
|
||||
buildConfigField "String", "BUILDVERSION", generateGitBuild()
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
|
||||
ndk {
|
||||
moduleName "BleCommandUtil"
|
||||
|
@ -69,7 +76,7 @@ android {
|
|||
// TODO remove once wear dependency com.google.android.gms:play-services-wearable:7.3.0
|
||||
// has been upgraded (requiring significant code changes), which currently fails release
|
||||
// build with a deprecation warning
|
||||
//abortOnError false
|
||||
abortOnError false
|
||||
// (disabled entirely to avoid reports on the error, which would still be displayed
|
||||
// and it's easy to overlook that it's ignored)
|
||||
checkReleaseBuilds false
|
||||
|
@ -82,7 +89,7 @@ android {
|
|||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
debug {
|
||||
testCoverageEnabled true
|
||||
testCoverageEnabled (project.hasProperty('coverage') ? true : false)
|
||||
}
|
||||
}
|
||||
productFlavors {
|
||||
|
@ -97,21 +104,6 @@ android {
|
|||
buildConfigField "boolean", "APS", "true"
|
||||
buildConfigField "boolean", "PUMPDRIVERS", "true"
|
||||
buildConfigField "boolean", "NSCLIENTOLNY", "false"
|
||||
buildConfigField "boolean", "CLOSEDLOOP", "true"
|
||||
buildConfigField "boolean", "G5UPLOADER", "false"
|
||||
buildConfigField "boolean", "PUMPCONTROL", "false"
|
||||
}
|
||||
openloop {
|
||||
dimension "standard"
|
||||
resValue "string", "app_name", "AndroidAPS"
|
||||
versionName version
|
||||
manifestPlaceholders = [
|
||||
appIcon: "@mipmap/blueowl"
|
||||
]
|
||||
buildConfigField "boolean", "APS", "true"
|
||||
buildConfigField "boolean", "PUMPDRIVERS", "true"
|
||||
buildConfigField "boolean", "NSCLIENTOLNY", "false"
|
||||
buildConfigField "boolean", "CLOSEDLOOP", "false"
|
||||
buildConfigField "boolean", "G5UPLOADER", "false"
|
||||
buildConfigField "boolean", "PUMPCONTROL", "false"
|
||||
}
|
||||
|
@ -125,7 +117,6 @@ android {
|
|||
buildConfigField "boolean", "APS", "false"
|
||||
buildConfigField "boolean", "PUMPDRIVERS", "true"
|
||||
buildConfigField "boolean", "NSCLIENTOLNY", "false"
|
||||
buildConfigField "boolean", "CLOSEDLOOP", "false"
|
||||
buildConfigField "boolean", "G5UPLOADER", "false"
|
||||
buildConfigField "boolean", "PUMPCONTROL", "true"
|
||||
}
|
||||
|
@ -139,7 +130,6 @@ android {
|
|||
buildConfigField "boolean", "APS", "false"
|
||||
buildConfigField "boolean", "PUMPDRIVERS", "false"
|
||||
buildConfigField "boolean", "NSCLIENTOLNY", "true"
|
||||
buildConfigField "boolean", "CLOSEDLOOP", "false"
|
||||
buildConfigField "boolean", "G5UPLOADER", "false"
|
||||
buildConfigField "boolean", "PUMPCONTROL", "false"
|
||||
}
|
||||
|
@ -153,12 +143,20 @@ android {
|
|||
buildConfigField "boolean", "APS", "false"
|
||||
buildConfigField "boolean", "PUMPDRIVERS", "false"
|
||||
buildConfigField "boolean", "NSCLIENTOLNY", "false"
|
||||
buildConfigField "boolean", "CLOSEDLOOP", "false"
|
||||
buildConfigField "boolean", "G5UPLOADER", "true"
|
||||
buildConfigField "boolean", "PUMPCONTROL", "false"
|
||||
}
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
testOptions {
|
||||
unitTests.returnDefaultValues = true
|
||||
unitTests.includeAndroidResources = true
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
|
@ -169,62 +167,100 @@ allprojects {
|
|||
}
|
||||
}
|
||||
|
||||
configurations {
|
||||
libs
|
||||
}
|
||||
|
||||
dependencies {
|
||||
wearApp project(':wear')
|
||||
|
||||
compile fileTree(include: ['*.jar'], dir: 'libs')
|
||||
compile("com.crashlytics.sdk.android:crashlytics:2.6.7@aar") {
|
||||
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||
implementation("com.crashlytics.sdk.android:crashlytics:2.6.7@aar") {
|
||||
transitive = true;
|
||||
}
|
||||
compile("com.crashlytics.sdk.android:answers:1.3.12@aar") {
|
||||
implementation("com.crashlytics.sdk.android:answers:1.3.12@aar") {
|
||||
transitive = true;
|
||||
}
|
||||
libs "MilosKozak:danars-support-lib:master@zip"
|
||||
|
||||
compile "com.android.support:appcompat-v7:${supportLibraryVersion}"
|
||||
compile "com.android.support:support-v4:${supportLibraryVersion}"
|
||||
compile "com.android.support:cardview-v7:${supportLibraryVersion}"
|
||||
compile "com.android.support:recyclerview-v7:${supportLibraryVersion}"
|
||||
compile "com.android.support:gridlayout-v7:${supportLibraryVersion}"
|
||||
compile "com.android.support:design:${supportLibraryVersion}"
|
||||
compile "com.android.support:percent:${supportLibraryVersion}"
|
||||
compile "com.wdullaer:materialdatetimepicker:2.3.0"
|
||||
compile "com.squareup:otto:1.3.7"
|
||||
compile "com.j256.ormlite:ormlite-core:${ormLiteVersion}"
|
||||
compile "com.j256.ormlite:ormlite-android:${ormLiteVersion}"
|
||||
compile("com.github.tony19:logback-android-classic:1.1.1-6") {
|
||||
implementation "com.android.support:appcompat-v7:${supportLibraryVersion}"
|
||||
implementation "com.android.support:support-v4:${supportLibraryVersion}"
|
||||
implementation "com.android.support:cardview-v7:${supportLibraryVersion}"
|
||||
implementation "com.android.support:recyclerview-v7:${supportLibraryVersion}"
|
||||
implementation "com.android.support:gridlayout-v7:${supportLibraryVersion}"
|
||||
implementation "com.android.support:design:${supportLibraryVersion}"
|
||||
implementation "com.android.support:percent:${supportLibraryVersion}"
|
||||
implementation "com.wdullaer:materialdatetimepicker:2.3.0"
|
||||
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
|
||||
implementation "com.squareup:otto:1.3.7"
|
||||
implementation "com.j256.ormlite:ormlite-core:${ormLiteVersion}"
|
||||
implementation "com.j256.ormlite:ormlite-android:${ormLiteVersion}"
|
||||
implementation("com.github.tony19:logback-android-classic:1.1.1-6") {
|
||||
exclude group: "com.google.android", module: "android"
|
||||
}
|
||||
compile "org.apache.commons:commons-lang3:3.6"
|
||||
compile "org.slf4j:slf4j-api:1.7.12"
|
||||
compile "com.jjoe64:graphview:4.0.1"
|
||||
compile "com.joanzapata.iconify:android-iconify-fontawesome:2.1.1"
|
||||
compile "com.google.android.gms:play-services-wearable:7.5.0"
|
||||
compile(name: "android-edittext-validator-v1.3.4-mod", ext: "aar")
|
||||
compile("com.google.android:flexbox:0.3.0") {
|
||||
implementation "org.apache.commons:commons-lang3:3.6"
|
||||
implementation "org.slf4j:slf4j-api:1.7.12"
|
||||
implementation "com.jjoe64:graphview:4.0.1"
|
||||
implementation "com.joanzapata.iconify:android-iconify-fontawesome:2.1.1"
|
||||
implementation "com.google.android.gms:play-services-wearable:7.5.0"
|
||||
implementation(name: "android-edittext-validator-v1.3.4-mod", ext: "aar")
|
||||
implementation(name: "sightparser-release", ext: "aar")
|
||||
|
||||
implementation("com.google.android:flexbox:0.3.0") {
|
||||
exclude group: "com.android.support"
|
||||
}
|
||||
compile("io.socket:socket.io-client:0.8.3") {
|
||||
implementation("io.socket:socket.io-client:1.0.0") {
|
||||
// excluding org.json which is provided by Android
|
||||
exclude group: "org.json", module: "json"
|
||||
}
|
||||
compile "com.google.code.gson:gson:2.7"
|
||||
compile "com.google.guava:guava:20.0"
|
||||
implementation "com.google.code.gson:gson:2.7"
|
||||
implementation "com.google.guava:guava:20.0"
|
||||
|
||||
compile "net.danlew:android.joda:2.9.9.1"
|
||||
implementation "net.danlew:android.joda:2.9.9.1"
|
||||
implementation "uk.com.robust-it:cloning:1.9.9"
|
||||
|
||||
api "com.jakewharton:butterknife:8.8.1"
|
||||
annotationProcessor "com.jakewharton:butterknife-compiler:8.8.1"
|
||||
implementation 'org.mozilla:rhino:1.7.7.2'
|
||||
|
||||
testCompile "junit:junit:4.12"
|
||||
testCompile "org.json:json:20140107"
|
||||
testCompile "org.mockito:mockito-core:2.7.22"
|
||||
testCompile "org.powermock:powermock-api-mockito2:${powermockVersion}"
|
||||
testCompile "org.powermock:powermock-module-junit4-rule-agent:${powermockVersion}"
|
||||
testCompile "org.powermock:powermock-module-junit4-rule:${powermockVersion}"
|
||||
testCompile "org.powermock:powermock-module-junit4:${powermockVersion}"
|
||||
testCompile "joda-time:joda-time:2.9.4.2"
|
||||
implementation "com.jakewharton:butterknife:${butterknifeVersion}"
|
||||
annotationProcessor "com.jakewharton:butterknife-compiler:${butterknifeVersion}"
|
||||
|
||||
androidTestCompile "org.mockito:mockito-core:2.7.22"
|
||||
androidTestCompile "com.google.dexmaker:dexmaker:${dexmakerVersion}"
|
||||
androidTestCompile "com.google.dexmaker:dexmaker-mockito:${dexmakerVersion}"
|
||||
testImplementation "junit:junit:4.12"
|
||||
testImplementation "org.json:json:20140107"
|
||||
testImplementation "org.mockito:mockito-core:2.7.22"
|
||||
testImplementation "org.powermock:powermock-api-mockito2:${powermockVersion}"
|
||||
testImplementation "org.powermock:powermock-module-junit4-rule-agent:${powermockVersion}"
|
||||
testImplementation "org.powermock:powermock-module-junit4-rule:${powermockVersion}"
|
||||
testImplementation "org.powermock:powermock-module-junit4:${powermockVersion}"
|
||||
testImplementation "joda-time:joda-time:2.9.4.2"
|
||||
testImplementation "com.google.truth:truth:0.39"
|
||||
testImplementation 'org.robolectric:robolectric:3.8'
|
||||
testImplementation "org.skyscreamer:jsonassert:1.5.0"
|
||||
|
||||
androidTestImplementation "org.mockito:mockito-core:2.7.22"
|
||||
androidTestImplementation "com.google.dexmaker:dexmaker:${dexmakerVersion}"
|
||||
androidTestImplementation "com.google.dexmaker:dexmaker-mockito:${dexmakerVersion}"
|
||||
}
|
||||
|
||||
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)
|
||||
into outputDir
|
||||
}
|
||||
|
||||
task copyLibs(dependsOn: unzip, type: Copy) {
|
||||
def src = file("${buildDir}/unpacked/dist/danars-support-lib-master")
|
||||
def target = file("src/main/jniLibs/")
|
||||
|
||||
from src
|
||||
into target
|
||||
}
|
||||
|
||||
task full_clean(type: Delete) {
|
||||
delete file("src/main/jniLibs")
|
||||
}
|
||||
|
||||
clean.dependsOn full_clean
|
||||
preBuild.dependsOn copyLibs
|
Binary file not shown.
BIN
app/libs/sightparser-release.aar
Normal file
BIN
app/libs/sightparser-release.aar
Normal file
Binary file not shown.
|
@ -15,9 +15,11 @@
|
|||
<uses-permission android:name="android.permission.SEND_MMS" />
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="com.google.android.permission.PROVIDE_BACKGROUND" />
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
<uses-permission android:name="sugar.free.sightremote.HISTORY_BROADCASTS" />
|
||||
|
||||
<uses-permission-sdk-23 android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
|
||||
|
||||
|
@ -47,7 +49,7 @@
|
|||
android:theme="@style/Theme.AppCompat.Translucent" />
|
||||
<activity android:name=".AgreementActivity" />
|
||||
<activity android:name=".plugins.PumpDanaR.activities.DanaRHistoryActivity" />
|
||||
<activity android:name=".plugins.PumpDanaR.activities.DanaRStatsActivity" />
|
||||
<activity android:name=".TDDStatsActivity" />
|
||||
<activity android:name=".plugins.Overview.activities.QuickWizardListActivity">
|
||||
<intent-filter>
|
||||
<action android:name="info.nightscout.androidaps.plugins.Overview.activities.QuickWizardListActivity" />
|
||||
|
@ -61,6 +63,7 @@
|
|||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name=".plugins.PumpDanaRS.activities.PairingHelperActivity" />
|
||||
<activity android:name=".HistoryBrowseActivity" />
|
||||
|
||||
<receiver
|
||||
android:name=".receivers.DataReceiver"
|
||||
|
@ -110,6 +113,14 @@
|
|||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<!-- Network change local receiver -->
|
||||
<receiver android:name=".receivers.NetworkChangeReceiver">
|
||||
<intent-filter>
|
||||
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
|
||||
<action android:name="android.net.wifi.WIFI_STATE_CHANGED" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<!-- Service processing incomming data -->
|
||||
<service
|
||||
android:name=".Services.DataService"
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
// IRTHandler.aidl
|
||||
package org.monkey.d.ruffy.ruffy.driver;
|
||||
|
||||
// Declare any non-default types here with import statements
|
||||
import org.monkey.d.ruffy.ruffy.driver.display.Menu;
|
||||
|
||||
interface IRTHandler {
|
||||
void log(String message);
|
||||
void fail(String message);
|
||||
|
||||
void requestBluetooth();
|
||||
void rtStopped();
|
||||
void rtStarted();
|
||||
|
||||
void rtClearDisplay();
|
||||
void rtUpdateDisplay(in byte[] quarter, int which);
|
||||
|
||||
void rtDisplayHandleMenu(in Menu menu);
|
||||
void rtDisplayHandleNoMenu();
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
// IRuffyService.aidl
|
||||
package org.monkey.d.ruffy.ruffy.driver;
|
||||
|
||||
// Declare any non-default types here with import statements
|
||||
import org.monkey.d.ruffy.ruffy.driver.IRTHandler;
|
||||
|
||||
interface IRuffyService {
|
||||
|
||||
void setHandler(IRTHandler handler);
|
||||
|
||||
/** Connect to the pump
|
||||
*
|
||||
* @return 0 if successful, -1 otherwise
|
||||
*/
|
||||
int doRTConnect();
|
||||
|
||||
/** Disconnect from the pump */
|
||||
void doRTDisconnect();
|
||||
|
||||
void rtSendKey(byte keyCode, boolean changed);
|
||||
void resetPairing();
|
||||
boolean isConnected();
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
package org.monkey.d.ruffy.ruffy.driver.display;
|
||||
|
||||
parcelable Menu;
|
|
@ -0,0 +1 @@
|
|||
//b916a900c0899ef58ad58c7427d1c30d3c8731f4
|
61
app/src/main/assets/OpenAPSSMB/basal-set-temp.js
Normal file
61
app/src/main/assets/OpenAPSSMB/basal-set-temp.js
Normal file
|
@ -0,0 +1,61 @@
|
|||
'use strict';
|
||||
|
||||
function reason(rT, msg) {
|
||||
rT.reason = (rT.reason ? rT.reason + '. ' : '') + msg;
|
||||
console.error(msg);
|
||||
}
|
||||
|
||||
var tempBasalFunctions = {};
|
||||
|
||||
tempBasalFunctions.getMaxSafeBasal = function getMaxSafeBasal(profile) {
|
||||
|
||||
var max_daily_safety_multiplier = (isNaN(profile.max_daily_safety_multiplier) || profile.max_daily_safety_multiplier == null) ? 3 : profile.max_daily_safety_multiplier;
|
||||
var current_basal_safety_multiplier = (isNaN(profile.current_basal_safety_multiplier) || profile.current_basal_safety_multiplier == null) ? 4 : profile.current_basal_safety_multiplier;
|
||||
|
||||
return Math.min(profile.max_basal, max_daily_safety_multiplier * profile.max_daily_basal, current_basal_safety_multiplier * profile.current_basal);
|
||||
};
|
||||
|
||||
tempBasalFunctions.setTempBasal = function setTempBasal(rate, duration, profile, rT, currenttemp) {
|
||||
//var maxSafeBasal = Math.min(profile.max_basal, 3 * profile.max_daily_basal, 4 * profile.current_basal);
|
||||
|
||||
var maxSafeBasal = tempBasalFunctions.getMaxSafeBasal(profile);
|
||||
var round_basal = require('./round-basal');
|
||||
|
||||
if (rate < 0) {
|
||||
rate = 0;
|
||||
} // if >30m @ 0 required, zero temp will be extended to 30m instead
|
||||
else if (rate > maxSafeBasal) {
|
||||
rate = maxSafeBasal;
|
||||
}
|
||||
|
||||
var suggestedRate = round_basal(rate, profile);
|
||||
if (typeof(currenttemp) !== 'undefined' && typeof(currenttemp.duration) !== 'undefined' && typeof(currenttemp.rate) !== 'undefined' && currenttemp.duration > (duration-10) && currenttemp.duration <= 120 && suggestedRate <= currenttemp.rate * 1.2 && suggestedRate >= currenttemp.rate * 0.8) {
|
||||
rT.reason += " "+currenttemp.duration+"m left and " + currenttemp.rate + " ~ req " + suggestedRate + "U/hr: no temp required";
|
||||
return rT;
|
||||
}
|
||||
|
||||
if (suggestedRate === profile.current_basal) {
|
||||
if (profile.skip_neutral_temps) {
|
||||
if (typeof(currenttemp) !== 'undefined' && typeof(currenttemp.duration) !== 'undefined' && currenttemp.duration > 0) {
|
||||
reason(rT, 'Suggested rate is same as profile rate, a temp basal is active, canceling current temp');
|
||||
rT.duration = 0;
|
||||
rT.rate = 0;
|
||||
return rT;
|
||||
} else {
|
||||
reason(rT, 'Suggested rate is same as profile rate, no temp basal is active, doing nothing');
|
||||
return rT;
|
||||
}
|
||||
} else {
|
||||
reason(rT, 'Setting neutral temp basal of ' + profile.current_basal + 'U/hr');
|
||||
rT.duration = duration;
|
||||
rT.rate = suggestedRate;
|
||||
return rT;
|
||||
}
|
||||
} else {
|
||||
rT.duration = duration;
|
||||
rT.rate = suggestedRate;
|
||||
return rT;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = tempBasalFunctions;
|
1146
app/src/main/assets/OpenAPSSMB/determine-basal.js
Normal file
1146
app/src/main/assets/OpenAPSSMB/determine-basal.js
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
|||
<configuration>
|
||||
<!-- Create a file appender for a log in the application's data directory -->
|
||||
<property name="EXT_FILES_DIR" value="${EXT_DIR:-/sdcard}/Android/data/${PACKAGE_NAME}/files"/>
|
||||
<property scope="context" name="EXT_FILES_DIR" value="${EXT_DIR:-/sdcard}/Android/data/${PACKAGE_NAME}/files"/>
|
||||
<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${EXT_FILES_DIR}/AndroidAPS.log</file>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
|
|
|
@ -13,10 +13,9 @@ public class Config {
|
|||
public static final boolean G5UPLOADER = BuildConfig.G5UPLOADER;
|
||||
public static final boolean PUMPCONTROL = BuildConfig.PUMPCONTROL;
|
||||
|
||||
public static final boolean DANAR = BuildConfig.PUMPDRIVERS;
|
||||
public static final boolean HWPUMPS = BuildConfig.PUMPDRIVERS;
|
||||
|
||||
public static final boolean ACTION = !BuildConfig.NSCLIENTOLNY && !BuildConfig.G5UPLOADER;
|
||||
public static final boolean VIRTUALPUMP = !BuildConfig.NSCLIENTOLNY && !BuildConfig.G5UPLOADER;
|
||||
public static final boolean MDI = !BuildConfig.NSCLIENTOLNY && !BuildConfig.G5UPLOADER;
|
||||
public static final boolean OTHERPROFILES = !BuildConfig.NSCLIENTOLNY && !BuildConfig.G5UPLOADER;
|
||||
public static final boolean SAFETY = !BuildConfig.NSCLIENTOLNY && !BuildConfig.G5UPLOADER;
|
||||
|
@ -31,12 +30,12 @@ public class Config {
|
|||
public static final boolean logPumpComm = true;
|
||||
public static final boolean logPrefsChange = true;
|
||||
public static final boolean logConfigBuilder = true;
|
||||
public static final boolean logConstraintsChanges = true;
|
||||
public static final boolean logNSUpload = true;
|
||||
public static final boolean logPumpActions = true;
|
||||
public static final boolean logCongigBuilderActions = true;
|
||||
public static final boolean logAutosensData = false;
|
||||
public static final boolean logEvents = false;
|
||||
public static final boolean logProfile = false;
|
||||
|
||||
// DanaR specific
|
||||
public static final boolean logDanaBTComm = true;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package info.nightscout.androidaps;
|
||||
|
||||
import com.j256.ormlite.stmt.query.In;
|
||||
import info.nightscout.utils.T;
|
||||
|
||||
/**
|
||||
* Created by mike on 07.06.2016.
|
||||
|
@ -14,10 +14,11 @@ public class Constants {
|
|||
|
||||
public static final double defaultDIA = 3d;
|
||||
|
||||
public static final double basalAbsoluteOnlyForCheckLimit = 10101010d;
|
||||
public static final Integer basalPercentOnlyForCheckLimit = 10101010;
|
||||
public static final double bolusOnlyForCheckLimit = 10101010d;
|
||||
public static final Integer carbsOnlyForCheckLimit = 10101010;
|
||||
public static final Double REALLYHIGHBASALRATE = 1111111d;
|
||||
public static final Integer REALLYHIGHPERCENTBASALRATE = 1111111;
|
||||
public static final double REALLYHIGHBOLUS = 1111111d;
|
||||
public static final Integer REALLYHIGHCARBS = 1111111;
|
||||
public static final double REALLYHIGHIOB = 1111111d;
|
||||
|
||||
public static final Integer notificationID = 556677;
|
||||
|
||||
|
@ -35,20 +36,20 @@ public class Constants {
|
|||
public static final int CPP_MIN_TIMESHIFT = -6;
|
||||
public static final int CPP_MAX_TIMESHIFT = 23;
|
||||
|
||||
// Very Hard Limits Ranges
|
||||
// First value is the Lowest and second value is the Highest a Limit can define
|
||||
public static final int[] VERY_HARD_LIMIT_MIN_BG = {72,180};
|
||||
public static final int[] VERY_HARD_LIMIT_MAX_BG = {90,270};
|
||||
public static final int[] VERY_HARD_LIMIT_TARGET_BG = {80,200};
|
||||
|
||||
// Very Hard Limits Ranges for Temp Targets
|
||||
public static final int[] VERY_HARD_LIMIT_TEMP_MIN_BG = {72,180};
|
||||
public static final int[] VERY_HARD_LIMIT_TEMP_MAX_BG = {72,270};
|
||||
public static final int[] VERY_HARD_LIMIT_TEMP_TARGET_BG = {72,200};
|
||||
|
||||
//DanaR
|
||||
public static final double dailyLimitWarning = 0.95d;
|
||||
|
||||
// Temp targets
|
||||
public static final int defaultActivityTTDuration = 90; // min
|
||||
public static final double defaultActivityTTmgdl = 140d;
|
||||
public static final double defaultActivityTTmmol = 8d;
|
||||
public static final int defaultEatingSoonTTDuration = 45; // min
|
||||
public static final double defaultEatingSoonTTmgdl = 90d;
|
||||
public static final double defaultEatingSoonTTmmol = 5d;
|
||||
public static final int defaultHypoTTDuration = 30; // min
|
||||
public static final double defaultHypoTTmgdl = 120d;
|
||||
public static final double defaultHypoTTmmol = 6.5d;
|
||||
|
||||
//NSClientInternal
|
||||
public static final int MAX_LOG_LINES = 100;
|
||||
|
||||
|
@ -58,8 +59,12 @@ public class Constants {
|
|||
|
||||
//Autosens
|
||||
public static final double DEVIATION_TO_BE_EQUAL = 2.0;
|
||||
public static final double DEFAULT_MAX_ABSORPTION_TIME = 6.0;
|
||||
|
||||
// Pump
|
||||
public static final int PUMP_MAX_CONNECTION_TIME_IN_SECONDS = 120 - 1;
|
||||
public static final int MIN_WATCHDOG_INTERVAL_IN_SECONDS = 12 * 60;
|
||||
|
||||
//SMS Communicator
|
||||
public static final long SMS_CONFIRM_TIMEOUT = T.mins(5).msecs();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,404 @@
|
|||
package info.nightscout.androidaps;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.content.res.ResourcesCompat;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.PopupMenu;
|
||||
import android.text.SpannableString;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.jjoe64.graphview.GraphView;
|
||||
import com.squareup.otto.Subscribe;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Calendar;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
import butterknife.OnLongClick;
|
||||
import info.nightscout.androidaps.data.Profile;
|
||||
import info.nightscout.androidaps.events.EventCustomCalculationFinished;
|
||||
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin;
|
||||
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventAutosensCalculationFinished;
|
||||
import info.nightscout.androidaps.plugins.Overview.OverviewFragment;
|
||||
import info.nightscout.androidaps.plugins.Overview.OverviewPlugin;
|
||||
import info.nightscout.androidaps.plugins.Overview.graphData.GraphData;
|
||||
import info.nightscout.utils.DateUtil;
|
||||
import info.nightscout.utils.SP;
|
||||
|
||||
public class HistoryBrowseActivity extends AppCompatActivity {
|
||||
private static Logger log = LoggerFactory.getLogger(HistoryBrowseActivity.class);
|
||||
|
||||
|
||||
ImageButton chartButton;
|
||||
|
||||
boolean showBasal = true;
|
||||
boolean showIob, showCob, showDev, showRat, showDevslope;
|
||||
|
||||
|
||||
@BindView(R.id.historybrowse_date)
|
||||
Button buttonDate;
|
||||
@BindView(R.id.historybrowse_zoom)
|
||||
Button buttonZoom;
|
||||
@BindView(R.id.historyybrowse_bggraph)
|
||||
GraphView bgGraph;
|
||||
@BindView(R.id.historybrowse_iobgraph)
|
||||
GraphView iobGraph;
|
||||
@BindView(R.id.historybrowse_seekBar)
|
||||
SeekBar seekBar;
|
||||
@BindView(R.id.historybrowse_noprofile)
|
||||
TextView noProfile;
|
||||
|
||||
private int rangeToDisplay = 24; // for graph
|
||||
private long start;
|
||||
|
||||
IobCobCalculatorPlugin iobCobCalculatorPlugin;
|
||||
|
||||
EventCustomCalculationFinished eventCustomCalculationFinished = new EventCustomCalculationFinished();
|
||||
|
||||
public HistoryBrowseActivity() {
|
||||
iobCobCalculatorPlugin = new IobCobCalculatorPlugin();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_historybrowse);
|
||||
|
||||
ButterKnife.bind(this);
|
||||
|
||||
bgGraph.getGridLabelRenderer().setGridColor(MainApp.sResources.getColor(R.color.graphgrid));
|
||||
bgGraph.getGridLabelRenderer().reloadStyles();
|
||||
iobGraph.getGridLabelRenderer().setGridColor(MainApp.sResources.getColor(R.color.graphgrid));
|
||||
iobGraph.getGridLabelRenderer().reloadStyles();
|
||||
iobGraph.getGridLabelRenderer().setHorizontalLabelsVisible(false);
|
||||
bgGraph.getGridLabelRenderer().setLabelVerticalWidth(50);
|
||||
iobGraph.getGridLabelRenderer().setLabelVerticalWidth(50);
|
||||
iobGraph.getGridLabelRenderer().setNumVerticalLabels(5);
|
||||
|
||||
setupChartMenu();
|
||||
|
||||
// set start of current day
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTimeInMillis(System.currentTimeMillis());
|
||||
calendar.set(Calendar.MILLISECOND, 0);
|
||||
calendar.set(Calendar.SECOND, 0);
|
||||
calendar.set(Calendar.MINUTE, 0);
|
||||
calendar.set(Calendar.HOUR_OF_DAY, 0);
|
||||
start = calendar.getTimeInMillis();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
updateGUI("onResume");
|
||||
}
|
||||
|
||||
|
||||
@OnClick(R.id.historybrowse_start)
|
||||
void onClickStart() {
|
||||
}
|
||||
|
||||
@OnClick(R.id.historybrowse_left)
|
||||
void onClickLeft() {
|
||||
start -= rangeToDisplay * 60 * 60 * 1000L;
|
||||
updateGUI("left");
|
||||
iobCobCalculatorPlugin.clearCache();
|
||||
iobCobCalculatorPlugin.runCalculation("onClickLeft", start, true, eventCustomCalculationFinished);
|
||||
}
|
||||
|
||||
@OnClick(R.id.historybrowse_right)
|
||||
void onClickRight() {
|
||||
start += rangeToDisplay * 60 * 60 * 1000L;
|
||||
updateGUI("right");
|
||||
iobCobCalculatorPlugin.clearCache();
|
||||
iobCobCalculatorPlugin.runCalculation("onClickRight", start, true, eventCustomCalculationFinished);
|
||||
}
|
||||
|
||||
@OnClick(R.id.historybrowse_end)
|
||||
void onClickEnd() {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTimeInMillis(System.currentTimeMillis());
|
||||
calendar.set(Calendar.MILLISECOND, 0);
|
||||
calendar.set(Calendar.SECOND, 0);
|
||||
calendar.set(Calendar.MINUTE, 0);
|
||||
calendar.set(Calendar.HOUR_OF_DAY, 0);
|
||||
start = calendar.getTimeInMillis();
|
||||
updateGUI("resetToMidnight");
|
||||
iobCobCalculatorPlugin.clearCache();
|
||||
iobCobCalculatorPlugin.runCalculation("onClickEnd", start, true, eventCustomCalculationFinished);
|
||||
}
|
||||
|
||||
@OnClick(R.id.historybrowse_zoom)
|
||||
void onClickZoom() {
|
||||
rangeToDisplay += 6;
|
||||
rangeToDisplay = rangeToDisplay > 24 ? 6 : rangeToDisplay;
|
||||
updateGUI("rangeChange");
|
||||
}
|
||||
|
||||
@OnLongClick(R.id.historybrowse_zoom)
|
||||
boolean onLongClickZoom() {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTimeInMillis(start);
|
||||
calendar.set(Calendar.MILLISECOND, 0);
|
||||
calendar.set(Calendar.SECOND, 0);
|
||||
calendar.set(Calendar.MINUTE, 0);
|
||||
calendar.set(Calendar.HOUR_OF_DAY, 0);
|
||||
start = calendar.getTimeInMillis();
|
||||
updateGUI("resetToMidnight");
|
||||
iobCobCalculatorPlugin.clearCache();
|
||||
iobCobCalculatorPlugin.runCalculation("onLongClickZoom", start, true, eventCustomCalculationFinished);
|
||||
return true;
|
||||
}
|
||||
|
||||
@OnClick(R.id.historybrowse_date)
|
||||
void onClickDate() {
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onStatusEvent(final EventAutosensCalculationFinished e) {
|
||||
Activity activity = this;
|
||||
if (activity != null && e.cause == eventCustomCalculationFinished) {
|
||||
log.debug("EventAutosensCalculationFinished");
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
updateGUI("EventAutosensCalculationFinished");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void updateGUI(String from) {
|
||||
final PumpInterface pump = ConfigBuilderPlugin.getActivePump();
|
||||
final Profile profile = MainApp.getConfigBuilder().getProfile();
|
||||
|
||||
if (profile == null) {
|
||||
noProfile.setVisibility(View.VISIBLE);
|
||||
return;
|
||||
} else {
|
||||
noProfile.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
final String units = profile.getUnits();
|
||||
|
||||
double lowLineSetting = SP.getDouble("low_mark", Profile.fromMgdlToUnits(OverviewPlugin.bgTargetLow, units));
|
||||
double highLineSetting = SP.getDouble("high_mark", Profile.fromMgdlToUnits(OverviewPlugin.bgTargetHigh, units));
|
||||
|
||||
if (lowLineSetting < 1)
|
||||
lowLineSetting = Profile.fromMgdlToUnits(76d, units);
|
||||
if (highLineSetting < 1)
|
||||
highLineSetting = Profile.fromMgdlToUnits(180d, units);
|
||||
|
||||
final double lowLine = lowLineSetting;
|
||||
final double highLine = highLineSetting;
|
||||
|
||||
final boolean showPrediction = false;
|
||||
|
||||
int hoursToFetch;
|
||||
final long toTime;
|
||||
final long fromTime;
|
||||
//if (showPrediction) {
|
||||
//int predHours = (int) (Math.ceil(((DetermineBasalResultAMA) finalLastRun.constraintsProcessed).getLatestPredictionsTime() - System.currentTimeMillis()) / (60 * 60 * 1000));
|
||||
//predHours = Math.min(2, predHours);
|
||||
//predHours = Math.max(0, predHours);
|
||||
//hoursToFetch = rangeToDisplay - predHours;
|
||||
//toTime = calendar.getTimeInMillis() + 100000; // little bit more to avoid wrong rounding - Graphview specific
|
||||
//fromTime = toTime - hoursToFetch * 60 * 60 * 1000L;
|
||||
//endTime = toTime + predHours * 60 * 60 * 1000L;
|
||||
//} else {
|
||||
fromTime = start + 100000;
|
||||
toTime = start + rangeToDisplay * 60 * 60 * 1000L;
|
||||
//}
|
||||
|
||||
buttonDate.setText(DateUtil.dateAndTimeString(start));
|
||||
buttonZoom.setText(String.valueOf(rangeToDisplay));
|
||||
|
||||
log.debug("Period: " + DateUtil.dateAndTimeString(fromTime) + " - " + DateUtil.dateAndTimeString(toTime));
|
||||
|
||||
final long pointer = System.currentTimeMillis();
|
||||
|
||||
// ------------------ 1st graph
|
||||
|
||||
final GraphData graphData = new GraphData(bgGraph, IobCobCalculatorPlugin.getPlugin());
|
||||
|
||||
// **** In range Area ****
|
||||
graphData.addInRangeArea(fromTime, toTime, lowLine, highLine);
|
||||
|
||||
// **** BG ****
|
||||
if (showPrediction)
|
||||
//graphData.addBgReadings(fromTime, toTime, lowLine, highLine, (DetermineBasalResultAMA) finalLastRun.constraintsProcessed);
|
||||
;
|
||||
else
|
||||
graphData.addBgReadings(fromTime, toTime, lowLine, highLine, null);
|
||||
|
||||
// set manual x bounds to have nice steps
|
||||
graphData.formatAxis(fromTime, toTime);
|
||||
|
||||
// Treatments
|
||||
graphData.addTreatments(fromTime, toTime);
|
||||
|
||||
// add basal data
|
||||
if (pump.getPumpDescription().isTempBasalCapable && showBasal) {
|
||||
graphData.addBasals(fromTime, toTime, lowLine / graphData.maxY / 1.2d);
|
||||
}
|
||||
|
||||
// **** NOW line ****
|
||||
graphData.addNowLine(pointer);
|
||||
|
||||
// ------------------ 2nd graph
|
||||
|
||||
final GraphData secondGraphData = new GraphData(iobGraph, iobCobCalculatorPlugin);
|
||||
|
||||
boolean useIobForScale = false;
|
||||
boolean useCobForScale = false;
|
||||
boolean useDevForScale = false;
|
||||
boolean useRatioForScale = false;
|
||||
boolean useDevSlopeForScale = false;
|
||||
|
||||
if (showIob) {
|
||||
useIobForScale = true;
|
||||
} else if (showCob) {
|
||||
useCobForScale = true;
|
||||
} else if (showDev) {
|
||||
useDevForScale = true;
|
||||
} else if (showRat) {
|
||||
useRatioForScale = true;
|
||||
} else if (showDevslope) {
|
||||
useDevSlopeForScale = true;
|
||||
}
|
||||
|
||||
if (showIob)
|
||||
secondGraphData.addIob(fromTime, toTime, useIobForScale, 1d);
|
||||
if (showCob)
|
||||
secondGraphData.addCob(fromTime, toTime, useCobForScale, useCobForScale ? 1d : 0.5d);
|
||||
if (showDev)
|
||||
secondGraphData.addDeviations(fromTime, toTime, useDevForScale, 1d);
|
||||
if (showRat)
|
||||
secondGraphData.addRatio(fromTime, toTime, useRatioForScale, 1d);
|
||||
if (showDevslope)
|
||||
secondGraphData.addDeviationSlope(fromTime, toTime, useDevSlopeForScale, 1d);
|
||||
|
||||
// **** NOW line ****
|
||||
// set manual x bounds to have nice steps
|
||||
secondGraphData.formatAxis(fromTime, toTime);
|
||||
secondGraphData.addNowLine(pointer);
|
||||
|
||||
// do GUI update
|
||||
if (showIob || showCob || showDev || showRat || showDevslope) {
|
||||
iobGraph.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
iobGraph.setVisibility(View.GONE);
|
||||
}
|
||||
// finally enforce drawing of graphs
|
||||
graphData.performUpdate();
|
||||
secondGraphData.performUpdate();
|
||||
}
|
||||
|
||||
private void setupChartMenu() {
|
||||
chartButton = (ImageButton) findViewById(R.id.overview_chartMenuButton);
|
||||
chartButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
MenuItem item;
|
||||
CharSequence title;
|
||||
SpannableString s;
|
||||
PopupMenu popup = new PopupMenu(v.getContext(), v);
|
||||
|
||||
|
||||
item = popup.getMenu().add(Menu.NONE, OverviewFragment.CHARTTYPE.BAS.ordinal(), Menu.NONE, MainApp.gs(R.string.overview_show_basals));
|
||||
title = item.getTitle();
|
||||
s = new SpannableString(title);
|
||||
s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.basal, null)), 0, s.length(), 0);
|
||||
item.setTitle(s);
|
||||
item.setCheckable(true);
|
||||
item.setChecked(showBasal);
|
||||
|
||||
item = popup.getMenu().add(Menu.NONE, OverviewFragment.CHARTTYPE.IOB.ordinal(), Menu.NONE, MainApp.gs(R.string.overview_show_iob));
|
||||
title = item.getTitle();
|
||||
s = new SpannableString(title);
|
||||
s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.iob, null)), 0, s.length(), 0);
|
||||
item.setTitle(s);
|
||||
item.setCheckable(true);
|
||||
item.setChecked(showIob);
|
||||
|
||||
item = popup.getMenu().add(Menu.NONE, OverviewFragment.CHARTTYPE.COB.ordinal(), Menu.NONE, MainApp.gs(R.string.overview_show_cob));
|
||||
title = item.getTitle();
|
||||
s = new SpannableString(title);
|
||||
s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.cob, null)), 0, s.length(), 0);
|
||||
item.setTitle(s);
|
||||
item.setCheckable(true);
|
||||
item.setChecked(showCob);
|
||||
|
||||
item = popup.getMenu().add(Menu.NONE, OverviewFragment.CHARTTYPE.DEV.ordinal(), Menu.NONE, MainApp.gs(R.string.overview_show_deviations));
|
||||
title = item.getTitle();
|
||||
s = new SpannableString(title);
|
||||
s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.deviations, null)), 0, s.length(), 0);
|
||||
item.setTitle(s);
|
||||
item.setCheckable(true);
|
||||
item.setChecked(showDev);
|
||||
|
||||
item = popup.getMenu().add(Menu.NONE, OverviewFragment.CHARTTYPE.SEN.ordinal(), Menu.NONE, MainApp.gs(R.string.overview_show_sensitivity));
|
||||
title = item.getTitle();
|
||||
s = new SpannableString(title);
|
||||
s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.ratio, null)), 0, s.length(), 0);
|
||||
item.setTitle(s);
|
||||
item.setCheckable(true);
|
||||
item.setChecked(showRat);
|
||||
|
||||
if (MainApp.devBranch) {
|
||||
item = popup.getMenu().add(Menu.NONE, OverviewFragment.CHARTTYPE.DEVSLOPE.ordinal(), Menu.NONE, "Deviation slope");
|
||||
title = item.getTitle();
|
||||
s = new SpannableString(title);
|
||||
s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.devslopepos, null)), 0, s.length(), 0);
|
||||
item.setTitle(s);
|
||||
item.setCheckable(true);
|
||||
item.setChecked(showDevslope);
|
||||
}
|
||||
|
||||
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
if (item.getItemId() == OverviewFragment.CHARTTYPE.BAS.ordinal()) {
|
||||
showBasal = !item.isChecked();
|
||||
} else if (item.getItemId() == OverviewFragment.CHARTTYPE.IOB.ordinal()) {
|
||||
showIob = !item.isChecked();
|
||||
} else if (item.getItemId() == OverviewFragment.CHARTTYPE.COB.ordinal()) {
|
||||
showCob = !item.isChecked();
|
||||
} else if (item.getItemId() == OverviewFragment.CHARTTYPE.DEV.ordinal()) {
|
||||
showDev = !item.isChecked();
|
||||
} else if (item.getItemId() == OverviewFragment.CHARTTYPE.SEN.ordinal()) {
|
||||
showRat = !item.isChecked();
|
||||
} else if (item.getItemId() == OverviewFragment.CHARTTYPE.DEVSLOPE.ordinal()) {
|
||||
showDevslope = !item.isChecked();
|
||||
}
|
||||
updateGUI("onGraphCheckboxesCheckedChanged");
|
||||
return true;
|
||||
}
|
||||
});
|
||||
chartButton.setImageResource(R.drawable.ic_arrow_drop_up_white_24dp);
|
||||
popup.setOnDismissListener(new PopupMenu.OnDismissListener() {
|
||||
@Override
|
||||
public void onDismiss(PopupMenu menu) {
|
||||
chartButton.setImageResource(R.drawable.ic_arrow_drop_down_white_24dp);
|
||||
}
|
||||
});
|
||||
popup.show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -19,6 +19,9 @@ import android.support.v4.view.ViewPager;
|
|||
import android.support.v7.app.AlertDialog;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.PopupMenu;
|
||||
import android.text.SpannableString;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.text.util.Linkify;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.MotionEvent;
|
||||
|
@ -27,6 +30,7 @@ import android.view.WindowManager;
|
|||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.joanzapata.iconify.Iconify;
|
||||
import com.joanzapata.iconify.fonts.FontAwesomeModule;
|
||||
|
@ -35,14 +39,16 @@ import com.squareup.otto.Subscribe;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import info.nightscout.androidaps.Services.AlarmSoundService;
|
||||
import info.nightscout.androidaps.data.Profile;
|
||||
import info.nightscout.androidaps.events.EventAppExit;
|
||||
import info.nightscout.androidaps.events.EventFeatureRunning;
|
||||
import info.nightscout.androidaps.events.EventPreferenceChange;
|
||||
import info.nightscout.androidaps.events.EventRefreshGui;
|
||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.Food.FoodPlugin;
|
||||
import info.nightscout.androidaps.plugins.Overview.events.EventSetWakeLock;
|
||||
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
|
||||
import info.nightscout.androidaps.tabs.SlidingTabLayout;
|
||||
import info.nightscout.androidaps.tabs.TabPageAdapter;
|
||||
import info.nightscout.utils.ImportExportPrefs;
|
||||
|
@ -112,9 +118,9 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
|
|||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if(ev.recreate) {
|
||||
if (ev.recreate) {
|
||||
recreate();
|
||||
}else {
|
||||
} else {
|
||||
try { // activity may be destroyed
|
||||
setUpTabs(true);
|
||||
} catch (IllegalStateException e) {
|
||||
|
@ -171,7 +177,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
|
|||
// Added in 1.57 at 21.01.2018
|
||||
Integer unreachable_threshold = SP.getInt(R.string.key_pump_unreachable_threshold, 30);
|
||||
SP.remove(R.string.key_pump_unreachable_threshold);
|
||||
if(unreachable_threshold < 30) unreachable_threshold = 30;
|
||||
if (unreachable_threshold < 30) unreachable_threshold = 30;
|
||||
SP.putString(R.string.key_pump_unreachable_threshold, unreachable_threshold.toString());
|
||||
}
|
||||
|
||||
|
@ -222,6 +228,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
|
|||
super.onResume();
|
||||
askForSMSPermissions();
|
||||
askForLocationPermissions();
|
||||
MainApp.bus().post(new EventFeatureRunning(EventFeatureRunning.Feature.MAIN));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -240,7 +247,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
|
|||
if (!pm.isIgnoringBatteryOptimizations(packageName)) {
|
||||
log.debug("Requesting ignore battery optimization");
|
||||
|
||||
OKDialog.show(this, getString(R.string.pleaseallowpermission), String.format(getString(R.string.needwhitelisting), getString(R.string.app_name)), new Runnable() {
|
||||
OKDialog.show(this, MainApp.gs(R.string.pleaseallowpermission), String.format(MainApp.gs(R.string.needwhitelisting), MainApp.gs(R.string.app_name)), new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
@ -253,7 +260,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
|
|||
startActivity(intent);
|
||||
|
||||
} catch (ActivityNotFoundException e) {
|
||||
final String msg = getString(R.string.batteryoptimalizationerror);
|
||||
final String msg = MainApp.gs(R.string.batteryoptimalizationerror);
|
||||
ToastUtils.showToastInUiThread(getApplicationContext(), msg);
|
||||
log.error(msg);
|
||||
}
|
||||
|
@ -358,6 +365,9 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
|
|||
}
|
||||
}, null);
|
||||
break;
|
||||
case R.id.nav_historybrowser:
|
||||
startActivity(new Intent(v.getContext(), HistoryBrowseActivity.class));
|
||||
break;
|
||||
case R.id.nav_resetdb:
|
||||
new AlertDialog.Builder(v.getContext())
|
||||
.setTitle(R.string.nav_resetdb)
|
||||
|
@ -367,6 +377,10 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
|
|||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
MainApp.getDbHelper().resetDatabases();
|
||||
// should be handled by Plugin-Interface and
|
||||
// additional service interface and plugin registry
|
||||
FoodPlugin.getPlugin().getService().resetFood();
|
||||
TreatmentsPlugin.getPlugin().getService().resetTreatments();
|
||||
}
|
||||
})
|
||||
.create()
|
||||
|
@ -385,17 +399,24 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
|
|||
break;
|
||||
case R.id.nav_about:
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(v.getContext());
|
||||
builder.setTitle(getString(R.string.app_name) + " " + BuildConfig.VERSION);
|
||||
if (Config.NSCLIENT|| Config.G5UPLOADER)
|
||||
builder.setTitle(MainApp.gs(R.string.app_name) + " " + BuildConfig.VERSION);
|
||||
if (Config.NSCLIENT || Config.G5UPLOADER)
|
||||
builder.setIcon(R.mipmap.yellowowl);
|
||||
else
|
||||
builder.setIcon(R.mipmap.blueowl);
|
||||
String message = "Build: " + BuildConfig.BUILDVERSION + "\n";
|
||||
message += MainApp.sResources.getString(R.string.configbuilder_nightscoutversion_label) + " " + ConfigBuilderPlugin.nightscoutVersionName;
|
||||
builder.setMessage(message);
|
||||
builder.setPositiveButton(MainApp.sResources.getString(R.string.ok), null);
|
||||
message += "Flavor: " + BuildConfig.FLAVOR + BuildConfig.BUILD_TYPE + "\n";
|
||||
message += MainApp.gs(R.string.configbuilder_nightscoutversion_label) + " " + ConfigBuilderPlugin.nightscoutVersionName;
|
||||
if (MainApp.engineeringMode)
|
||||
message += "\n" + MainApp.gs(R.string.engineering_mode_enabled);
|
||||
message += MainApp.gs(R.string.about_link_urls);
|
||||
final SpannableString messageSpanned = new SpannableString(message);
|
||||
Linkify.addLinks(messageSpanned, Linkify.WEB_URLS);
|
||||
builder.setMessage(messageSpanned);
|
||||
builder.setPositiveButton(MainApp.gs(R.string.ok), null);
|
||||
AlertDialog alertDialog = builder.create();
|
||||
alertDialog.show();
|
||||
((TextView)alertDialog.findViewById(android.R.id.message)).setMovementMethod(LinkMovementMethod.getInstance());
|
||||
break;
|
||||
case R.id.nav_exit:
|
||||
log.debug("Exiting");
|
||||
|
|
|
@ -20,57 +20,63 @@ import net.danlew.android.joda.JodaTimeAndroid;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import ch.qos.logback.classic.LoggerContext;
|
||||
import info.nightscout.androidaps.Services.Intents;
|
||||
import info.nightscout.androidaps.data.ConstraintChecker;
|
||||
import info.nightscout.androidaps.db.DatabaseHelper;
|
||||
import info.nightscout.androidaps.interfaces.InsulinInterface;
|
||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||
import info.nightscout.androidaps.interfaces.PluginType;
|
||||
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||
import info.nightscout.androidaps.plugins.Actions.ActionsFragment;
|
||||
import info.nightscout.androidaps.plugins.Careportal.CareportalPlugin;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.ConstraintsObjectives.ObjectivesPlugin;
|
||||
import info.nightscout.androidaps.plugins.ConstraintsSafety.SafetyPlugin;
|
||||
import info.nightscout.androidaps.plugins.Food.FoodPlugin;
|
||||
import info.nightscout.androidaps.plugins.Insulin.InsulinFastactingPlugin;
|
||||
import info.nightscout.androidaps.plugins.Insulin.InsulinFastactingProlongedPlugin;
|
||||
import info.nightscout.androidaps.plugins.Insulin.InsulinOrefFreePeakPlugin;
|
||||
import info.nightscout.androidaps.plugins.Insulin.InsulinOrefRapidActingPlugin;
|
||||
import info.nightscout.androidaps.plugins.Insulin.InsulinOrefUltraRapidActingPlugin;
|
||||
import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin;
|
||||
import info.nightscout.androidaps.plugins.Loop.LoopPlugin;
|
||||
import info.nightscout.androidaps.plugins.NSClientInternal.NSClientInternalPlugin;
|
||||
import info.nightscout.androidaps.plugins.NSClientInternal.NSClientPlugin;
|
||||
import info.nightscout.androidaps.plugins.NSClientInternal.receivers.AckAlarmReceiver;
|
||||
import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin;
|
||||
import info.nightscout.androidaps.plugins.OpenAPSMA.OpenAPSMAPlugin;
|
||||
import info.nightscout.androidaps.plugins.OpenAPSSMB.OpenAPSSMBPlugin;
|
||||
import info.nightscout.androidaps.plugins.Overview.OverviewPlugin;
|
||||
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
|
||||
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
|
||||
import info.nightscout.androidaps.plugins.Persistentnotification.PersistentNotificationPlugin;
|
||||
import info.nightscout.androidaps.plugins.ProfileCircadianPercentage.CircadianPercentageProfileFragment;
|
||||
import info.nightscout.androidaps.plugins.ProfileLocal.LocalProfilePlugin;
|
||||
import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin;
|
||||
import info.nightscout.androidaps.plugins.ProfileSimple.SimpleProfilePlugin;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ComboPlugin;
|
||||
import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin;
|
||||
import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin;
|
||||
import info.nightscout.androidaps.plugins.PumpDanaRS.DanaRSPlugin;
|
||||
import info.nightscout.androidaps.plugins.PumpDanaRv2.DanaRv2Plugin;
|
||||
import info.nightscout.androidaps.plugins.PumpInsight.InsightPlugin;
|
||||
import info.nightscout.androidaps.plugins.PumpMDI.MDIPlugin;
|
||||
import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin;
|
||||
import info.nightscout.androidaps.plugins.SensitivityAAPS.SensitivityAAPSPlugin;
|
||||
import info.nightscout.androidaps.plugins.SensitivityOref0.SensitivityOref0Plugin;
|
||||
import info.nightscout.androidaps.plugins.SensitivityWeightedAverage.SensitivityWeightedAveragePlugin;
|
||||
import info.nightscout.androidaps.plugins.SmsCommunicator.SmsCommunicatorPlugin;
|
||||
import info.nightscout.androidaps.plugins.SourceDexcomG5.SourceDexcomG5Plugin;
|
||||
import info.nightscout.androidaps.plugins.SourceGlimp.SourceGlimpPlugin;
|
||||
import info.nightscout.androidaps.plugins.SourceMM640g.SourceMM640gPlugin;
|
||||
import info.nightscout.androidaps.plugins.SourceNSClient.SourceNSClientPlugin;
|
||||
import info.nightscout.androidaps.plugins.SourceXdrip.SourceXdripPlugin;
|
||||
import info.nightscout.androidaps.plugins.Source.SourceDexcomG5Plugin;
|
||||
import info.nightscout.androidaps.plugins.Source.SourceGlimpPlugin;
|
||||
import info.nightscout.androidaps.plugins.Source.SourceMM640gPlugin;
|
||||
import info.nightscout.androidaps.plugins.Source.SourceNSClientPlugin;
|
||||
import info.nightscout.androidaps.plugins.Source.SourceXdripPlugin;
|
||||
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
|
||||
import info.nightscout.androidaps.plugins.Wear.WearPlugin;
|
||||
import info.nightscout.androidaps.plugins.XDripStatusline.StatuslinePlugin;
|
||||
import info.nightscout.androidaps.receivers.DataReceiver;
|
||||
import info.nightscout.androidaps.receivers.KeepAliveReceiver;
|
||||
import info.nightscout.androidaps.receivers.NSAlarmReceiver;
|
||||
import info.nightscout.utils.FabricPrivacy;
|
||||
import info.nightscout.utils.NSUpload;
|
||||
import io.fabric.sdk.android.Fabric;
|
||||
|
||||
|
@ -85,6 +91,7 @@ public class MainApp extends Application {
|
|||
|
||||
private static DatabaseHelper sDatabaseHelper = null;
|
||||
private static ConfigBuilderPlugin sConfigBuilder = null;
|
||||
private static ConstraintChecker sConstraintsChecker = null;
|
||||
|
||||
private static ArrayList<PluginBase> pluginsList = null;
|
||||
|
||||
|
@ -93,20 +100,39 @@ public class MainApp extends Application {
|
|||
private static AckAlarmReceiver ackAlarmReciever = new AckAlarmReceiver();
|
||||
private LocalBroadcastManager lbm;
|
||||
|
||||
public static boolean devBranch;
|
||||
public static boolean engineeringMode;
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
Fabric.with(this, new Crashlytics());
|
||||
Fabric.with(this, new Answers());
|
||||
sInstance = this;
|
||||
sResources = getResources();
|
||||
sConstraintsChecker = new ConstraintChecker(this);
|
||||
sDatabaseHelper = OpenHelperManager.getHelper(sInstance, DatabaseHelper.class);
|
||||
|
||||
try {
|
||||
if (FabricPrivacy.fabricEnabled()) {
|
||||
Fabric.with(this, new Crashlytics());
|
||||
Fabric.with(this, new Answers());
|
||||
Crashlytics.setString("BUILDVERSION", BuildConfig.BUILDVERSION);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
android.util.Log.e("ANDROIDAPS", "Error with Fabric init! " + e);
|
||||
}
|
||||
|
||||
JodaTimeAndroid.init(this);
|
||||
Crashlytics.setString("BUILDVERSION", BuildConfig.BUILDVERSION);
|
||||
|
||||
log.info("Version: " + BuildConfig.VERSION_NAME);
|
||||
log.info("BuildVersion: " + BuildConfig.BUILDVERSION);
|
||||
|
||||
sBus = Config.logEvents ? new LoggingBus(ThreadEnforcer.ANY) : new Bus(ThreadEnforcer.ANY);
|
||||
String extFilesDir = this.getLogDirectory();
|
||||
File engineeringModeSemaphore = new File(extFilesDir, "engineering_mode");
|
||||
|
||||
sInstance = this;
|
||||
sResources = getResources();
|
||||
engineeringMode = engineeringModeSemaphore.exists() && engineeringModeSemaphore.isFile();
|
||||
devBranch = BuildConfig.VERSION.contains("dev");
|
||||
|
||||
sBus = Config.logEvents ? new LoggingBus(ThreadEnforcer.ANY) : new Bus(ThreadEnforcer.ANY);
|
||||
|
||||
registerLocalBroadcastReceiver();
|
||||
|
||||
|
@ -116,29 +142,29 @@ public class MainApp extends Application {
|
|||
pluginsList.add(OverviewPlugin.getPlugin());
|
||||
pluginsList.add(IobCobCalculatorPlugin.getPlugin());
|
||||
if (Config.ACTION) pluginsList.add(ActionsFragment.getPlugin());
|
||||
pluginsList.add(InsulinFastactingPlugin.getPlugin());
|
||||
pluginsList.add(InsulinFastactingProlongedPlugin.getPlugin());
|
||||
pluginsList.add(InsulinOrefRapidActingPlugin.getPlugin());
|
||||
pluginsList.add(InsulinOrefUltraRapidActingPlugin.getPlugin());
|
||||
pluginsList.add(InsulinOrefFreePeakPlugin.getPlugin());
|
||||
pluginsList.add(SensitivityOref0Plugin.getPlugin());
|
||||
pluginsList.add(SensitivityAAPSPlugin.getPlugin());
|
||||
pluginsList.add(SensitivityWeightedAveragePlugin.getPlugin());
|
||||
if (Config.DANAR) pluginsList.add(DanaRPlugin.getPlugin());
|
||||
if (Config.DANAR) pluginsList.add(DanaRKoreanPlugin.getPlugin());
|
||||
if (Config.DANAR) pluginsList.add(DanaRv2Plugin.getPlugin());
|
||||
if (Config.DANAR) pluginsList.add(DanaRSPlugin.getPlugin());
|
||||
if (Config.HWPUMPS) pluginsList.add(DanaRPlugin.getPlugin());
|
||||
if (Config.HWPUMPS) pluginsList.add(DanaRKoreanPlugin.getPlugin());
|
||||
if (Config.HWPUMPS) pluginsList.add(DanaRv2Plugin.getPlugin());
|
||||
if (Config.HWPUMPS) pluginsList.add(DanaRSPlugin.getPlugin());
|
||||
pluginsList.add(CareportalPlugin.getPlugin());
|
||||
if (Config.HWPUMPS && engineeringMode)
|
||||
pluginsList.add(InsightPlugin.getPlugin()); // <-- Enable Insight plugin here
|
||||
if (Config.HWPUMPS) pluginsList.add(ComboPlugin.getPlugin());
|
||||
if (Config.MDI) pluginsList.add(MDIPlugin.getPlugin());
|
||||
if (Config.VIRTUALPUMP) pluginsList.add(VirtualPumpPlugin.getPlugin());
|
||||
pluginsList.add(VirtualPumpPlugin.getPlugin());
|
||||
if (Config.APS) pluginsList.add(LoopPlugin.getPlugin());
|
||||
if (Config.APS) pluginsList.add(OpenAPSMAPlugin.getPlugin());
|
||||
if (Config.APS) pluginsList.add(OpenAPSAMAPlugin.getPlugin());
|
||||
if (Config.APS) pluginsList.add(OpenAPSSMBPlugin.getPlugin());
|
||||
pluginsList.add(NSProfilePlugin.getPlugin());
|
||||
if (Config.OTHERPROFILES) pluginsList.add(SimpleProfilePlugin.getPlugin());
|
||||
if (Config.OTHERPROFILES) pluginsList.add(LocalProfilePlugin.getPlugin());
|
||||
if (Config.OTHERPROFILES)
|
||||
pluginsList.add(CircadianPercentageProfileFragment.getPlugin());
|
||||
pluginsList.add(TreatmentsPlugin.getPlugin());
|
||||
if (Config.SAFETY) pluginsList.add(SafetyPlugin.getPlugin());
|
||||
if (Config.APS) pluginsList.add(ObjectivesPlugin.getPlugin());
|
||||
|
@ -158,33 +184,33 @@ public class MainApp extends Application {
|
|||
pluginsList.add(WearPlugin.initPlugin(this));
|
||||
pluginsList.add(StatuslinePlugin.initPlugin(this));
|
||||
pluginsList.add(new PersistentNotificationPlugin(this));
|
||||
pluginsList.add(NSClientInternalPlugin.getPlugin());
|
||||
pluginsList.add(NSClientPlugin.getPlugin());
|
||||
|
||||
pluginsList.add(sConfigBuilder = ConfigBuilderFragment.getPlugin());
|
||||
pluginsList.add(sConfigBuilder = ConfigBuilderPlugin.getPlugin());
|
||||
|
||||
MainApp.getConfigBuilder().initialize();
|
||||
}
|
||||
NSUpload.uploadAppStart();
|
||||
if (Config.NSCLIENT)
|
||||
Answers.getInstance().logCustom(new CustomEvent("AppStart-NSClient"));
|
||||
else if (Config.G5UPLOADER)
|
||||
Answers.getInstance().logCustom(new CustomEvent("AppStart-G5Uploader"));
|
||||
else if (Config.PUMPCONTROL)
|
||||
Answers.getInstance().logCustom(new CustomEvent("AppStart-PumpControl"));
|
||||
else if (MainApp.getConfigBuilder().isClosedModeEnabled())
|
||||
Answers.getInstance().logCustom(new CustomEvent("AppStart-ClosedLoop"));
|
||||
else
|
||||
Answers.getInstance().logCustom(new CustomEvent("AppStart-OpenLoop"));
|
||||
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (Config.NSCLIENT)
|
||||
FabricPrivacy.getInstance().logCustom(new CustomEvent("AppStart-NSClient"));
|
||||
else if (Config.G5UPLOADER)
|
||||
FabricPrivacy.getInstance().logCustom(new CustomEvent("AppStart-G5Uploader"));
|
||||
else if (Config.PUMPCONTROL)
|
||||
FabricPrivacy.getInstance().logCustom(new CustomEvent("AppStart-PumpControl"));
|
||||
else if (MainApp.getConstraintChecker().isClosedLoopAllowed().value())
|
||||
FabricPrivacy.getInstance().logCustom(new CustomEvent("AppStart-ClosedLoop"));
|
||||
else
|
||||
FabricPrivacy.getInstance().logCustom(new CustomEvent("AppStart-OpenLoop"));
|
||||
|
||||
final PumpInterface pump = ConfigBuilderPlugin.getActivePump();
|
||||
if (pump != null) {
|
||||
new Thread(() -> {
|
||||
SystemClock.sleep(5000);
|
||||
ConfigBuilderPlugin.getCommandQueue().readStatus("Initialization", null);
|
||||
startKeepAliveService();
|
||||
}
|
||||
}).start();
|
||||
|
||||
}).start();
|
||||
}
|
||||
}
|
||||
|
||||
private void registerLocalBroadcastReceiver() {
|
||||
|
@ -219,12 +245,27 @@ public class MainApp extends Application {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public void stopKeepAliveService() {
|
||||
if (keepAliveReceiver != null)
|
||||
KeepAliveReceiver.cancelAlarm(this);
|
||||
}
|
||||
|
||||
public static void subscribe(Object subscriber) {
|
||||
try {
|
||||
bus().register(subscriber);
|
||||
} catch (IllegalArgumentException e) {
|
||||
// already registered
|
||||
}
|
||||
}
|
||||
|
||||
public static void unsubscribe(Object subscriber) {
|
||||
try {
|
||||
bus().unregister(subscriber);
|
||||
} catch (IllegalArgumentException e) {
|
||||
// already unregistered
|
||||
}
|
||||
}
|
||||
|
||||
public static Bus bus() {
|
||||
return sBus;
|
||||
}
|
||||
|
@ -237,14 +278,15 @@ public class MainApp extends Application {
|
|||
return sResources.getString(id, args);
|
||||
}
|
||||
|
||||
public static int gc(int id) {
|
||||
return sResources.getColor(id);
|
||||
}
|
||||
|
||||
public static MainApp instance() {
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
public static DatabaseHelper getDbHelper() {
|
||||
if (sDatabaseHelper == null) {
|
||||
sDatabaseHelper = OpenHelperManager.getHelper(sInstance, DatabaseHelper.class);
|
||||
}
|
||||
return sDatabaseHelper;
|
||||
}
|
||||
|
||||
|
@ -259,11 +301,15 @@ public class MainApp extends Application {
|
|||
return sConfigBuilder;
|
||||
}
|
||||
|
||||
public static ConstraintChecker getConstraintChecker() {
|
||||
return sConstraintsChecker;
|
||||
}
|
||||
|
||||
public static ArrayList<PluginBase> getPluginsList() {
|
||||
return pluginsList;
|
||||
}
|
||||
|
||||
public static ArrayList<PluginBase> getSpecificPluginsList(int type) {
|
||||
public static ArrayList<PluginBase> getSpecificPluginsList(PluginType type) {
|
||||
ArrayList<PluginBase> newList = new ArrayList<>();
|
||||
|
||||
if (pluginsList != null) {
|
||||
|
@ -277,20 +323,7 @@ public class MainApp extends Application {
|
|||
return newList;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static InsulinInterface getInsulinIterfaceById(int id) {
|
||||
if (pluginsList != null) {
|
||||
for (PluginBase p : pluginsList) {
|
||||
if (p.getType() == PluginBase.INSULIN && ((InsulinInterface) p).getId() == id)
|
||||
return (InsulinInterface) p;
|
||||
}
|
||||
} else {
|
||||
log.error("InsulinInterface not found");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static ArrayList<PluginBase> getSpecificPluginsVisibleInList(int type) {
|
||||
public static ArrayList<PluginBase> getSpecificPluginsVisibleInList(PluginType type) {
|
||||
ArrayList<PluginBase> newList = new ArrayList<>();
|
||||
|
||||
if (pluginsList != null) {
|
||||
|
@ -319,7 +352,7 @@ public class MainApp extends Application {
|
|||
return newList;
|
||||
}
|
||||
|
||||
public static ArrayList<PluginBase> getSpecificPluginsVisibleInListByInterface(Class interfaceClass, int type) {
|
||||
public static ArrayList<PluginBase> getSpecificPluginsVisibleInListByInterface(Class interfaceClass, PluginType type) {
|
||||
ArrayList<PluginBase> newList = new ArrayList<>();
|
||||
|
||||
if (pluginsList != null) {
|
||||
|
@ -347,9 +380,27 @@ public class MainApp extends Application {
|
|||
return null;
|
||||
}
|
||||
|
||||
public static boolean isEngineeringModeOrRelease() {
|
||||
if (!BuildConfig.APS)
|
||||
return true;
|
||||
return engineeringMode || !devBranch;
|
||||
}
|
||||
|
||||
public static boolean isDev() {
|
||||
return devBranch;
|
||||
}
|
||||
|
||||
public String getLogDirectory() {
|
||||
LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
|
||||
return lc.getProperty("EXT_FILES_DIR");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTerminate() {
|
||||
super.onTerminate();
|
||||
sDatabaseHelper.close();
|
||||
if (sDatabaseHelper != null) {
|
||||
sDatabaseHelper.close();
|
||||
sDatabaseHelper = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
package info.nightscout.androidaps;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.preference.EditTextPreference;
|
||||
import android.preference.ListPreference;
|
||||
import android.preference.MultiSelectListPreference;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceActivity;
|
||||
import android.preference.PreferenceFragment;
|
||||
|
@ -16,23 +14,27 @@ import android.text.TextUtils;
|
|||
import info.nightscout.androidaps.events.EventPreferenceChange;
|
||||
import info.nightscout.androidaps.events.EventRefreshGui;
|
||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||
import info.nightscout.androidaps.interfaces.PluginType;
|
||||
import info.nightscout.androidaps.plugins.Careportal.CareportalPlugin;
|
||||
import info.nightscout.androidaps.plugins.ConstraintsSafety.SafetyPlugin;
|
||||
import info.nightscout.androidaps.plugins.Insulin.InsulinOrefFreePeakPlugin;
|
||||
import info.nightscout.androidaps.plugins.Loop.LoopPlugin;
|
||||
import info.nightscout.androidaps.plugins.NSClientInternal.NSClientInternalPlugin;
|
||||
import info.nightscout.androidaps.plugins.NSClientInternal.NSClientPlugin;
|
||||
import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin;
|
||||
import info.nightscout.androidaps.plugins.OpenAPSMA.OpenAPSMAPlugin;
|
||||
import info.nightscout.androidaps.plugins.OpenAPSSMB.OpenAPSSMBPlugin;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ComboPlugin;
|
||||
import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin;
|
||||
import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin;
|
||||
import info.nightscout.androidaps.plugins.PumpDanaRS.DanaRSPlugin;
|
||||
import info.nightscout.androidaps.plugins.PumpDanaRv2.DanaRv2Plugin;
|
||||
import info.nightscout.androidaps.plugins.PumpInsight.InsightPlugin;
|
||||
import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin;
|
||||
import info.nightscout.androidaps.plugins.SensitivityAAPS.SensitivityAAPSPlugin;
|
||||
import info.nightscout.androidaps.plugins.SensitivityOref0.SensitivityOref0Plugin;
|
||||
import info.nightscout.androidaps.plugins.SensitivityWeightedAverage.SensitivityWeightedAveragePlugin;
|
||||
import info.nightscout.androidaps.plugins.SmsCommunicator.SmsCommunicatorPlugin;
|
||||
import info.nightscout.androidaps.plugins.SourceDexcomG5.SourceDexcomG5Plugin;
|
||||
import info.nightscout.androidaps.plugins.Source.SourceDexcomG5Plugin;
|
||||
import info.nightscout.androidaps.plugins.Wear.WearPlugin;
|
||||
import info.nightscout.androidaps.plugins.XDripStatusline.StatuslinePlugin;
|
||||
import info.nightscout.utils.LocaleHelper;
|
||||
|
@ -66,8 +68,8 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
|
|||
if (key.equals("short_tabtitles")) {
|
||||
MainApp.bus().post(new EventRefreshGui());
|
||||
}
|
||||
if (key.equals("openapsama_useautosens") && SP.getBoolean("openapsama_useautosens", false)) {
|
||||
OKDialog.show(this, MainApp.sResources.getString(R.string.configbuilder_sensitivity), MainApp.sResources.getString(R.string.sensitivity_warning), null);
|
||||
if (key.equals(MainApp.gs(R.string.key_openapsama_useautosens)) && SP.getBoolean(R.string.key_openapsama_useautosens, false)) {
|
||||
OKDialog.show(this, MainApp.gs(R.string.configbuilder_sensitivity), MainApp.gs(R.string.sensitivity_warning), null);
|
||||
}
|
||||
updatePrefSummary(myPreferenceFragment.getPreference(key));
|
||||
}
|
||||
|
@ -81,13 +83,13 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
|
|||
EditTextPreference editTextPref = (EditTextPreference) pref;
|
||||
if (pref.getKey().contains("password") || pref.getKey().contains("secret")) {
|
||||
pref.setSummary("******");
|
||||
} else if (pref.getKey().equals(MainApp.sResources.getString(R.string.key_danars_name))) {
|
||||
} else if (pref.getKey().equals(MainApp.gs(R.string.key_danars_name))) {
|
||||
pref.setSummary(SP.getString(R.string.key_danars_name, ""));
|
||||
} else if (editTextPref.getText() != null && !editTextPref.getText().equals("")) {
|
||||
((EditTextPreference) pref).setDialogMessage(editTextPref.getDialogMessage());
|
||||
pref.setSummary(editTextPref.getText());
|
||||
} else if (pref.getKey().contains("smscommunicator_allowednumbers") && TextUtils.isEmpty(editTextPref.getText().trim())) {
|
||||
pref.setSummary(MainApp.sResources.getString(R.string.smscommunicator_allowednumbers_summary));
|
||||
pref.setSummary(MainApp.gs(R.string.smscommunicator_allowednumbers_summary));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -112,7 +114,7 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
|
|||
id = args.getInt("id");
|
||||
}
|
||||
|
||||
void addPreferencesFromResourceIfEnabled(PluginBase p, int type) {
|
||||
void addPreferencesFromResourceIfEnabled(PluginBase p, PluginType type) {
|
||||
if (p.isEnabled(type) && p.getPreferencesId() != -1)
|
||||
addPreferencesFromResource(p.getPreferencesId());
|
||||
}
|
||||
|
@ -127,60 +129,62 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
|
|||
|
||||
if (id != -1) {
|
||||
addPreferencesFromResource(id);
|
||||
addPreferencesFromResource(R.xml.pref_advanced);
|
||||
} else {
|
||||
|
||||
if (!Config.NSCLIENT && !Config.G5UPLOADER) {
|
||||
addPreferencesFromResource(R.xml.pref_password);
|
||||
}
|
||||
addPreferencesFromResource(R.xml.pref_age);
|
||||
addPreferencesFromResource(R.xml.pref_language);
|
||||
|
||||
if (!Config.NSCLIENT && !Config.G5UPLOADER) {
|
||||
addPreferencesFromResource(R.xml.pref_quickwizard);
|
||||
}
|
||||
addPreferencesFromResourceIfEnabled(SourceDexcomG5Plugin.getPlugin(), PluginBase.BGSOURCE);
|
||||
addPreferencesFromResourceIfEnabled(CareportalPlugin.getPlugin(), PluginBase.GENERAL);
|
||||
addPreferencesFromResourceIfEnabled(SafetyPlugin.getPlugin(), PluginBase.CONSTRAINTS);
|
||||
addPreferencesFromResource(R.xml.pref_overview);
|
||||
|
||||
addPreferencesFromResourceIfEnabled(SourceDexcomG5Plugin.getPlugin(), PluginType.BGSOURCE);
|
||||
addPreferencesFromResourceIfEnabled(CareportalPlugin.getPlugin(), PluginType.GENERAL);
|
||||
addPreferencesFromResourceIfEnabled(SafetyPlugin.getPlugin(), PluginType.CONSTRAINTS);
|
||||
if (Config.APS) {
|
||||
addPreferencesFromResourceIfEnabled(LoopPlugin.getPlugin(), PluginBase.LOOP);
|
||||
addPreferencesFromResourceIfEnabled(OpenAPSMAPlugin.getPlugin(), PluginBase.APS);
|
||||
addPreferencesFromResourceIfEnabled(OpenAPSAMAPlugin.getPlugin(), PluginBase.APS);
|
||||
addPreferencesFromResourceIfEnabled(LoopPlugin.getPlugin(), PluginType.LOOP);
|
||||
addPreferencesFromResourceIfEnabled(OpenAPSMAPlugin.getPlugin(), PluginType.APS);
|
||||
addPreferencesFromResourceIfEnabled(OpenAPSAMAPlugin.getPlugin(), PluginType.APS);
|
||||
addPreferencesFromResourceIfEnabled(OpenAPSSMBPlugin.getPlugin(), PluginType.APS);
|
||||
}
|
||||
|
||||
addPreferencesFromResourceIfEnabled(SensitivityAAPSPlugin.getPlugin(), PluginBase.SENSITIVITY);
|
||||
addPreferencesFromResourceIfEnabled(SensitivityWeightedAveragePlugin.getPlugin(), PluginBase.SENSITIVITY);
|
||||
addPreferencesFromResourceIfEnabled(SensitivityOref0Plugin.getPlugin(), PluginBase.SENSITIVITY);
|
||||
addPreferencesFromResourceIfEnabled(SensitivityAAPSPlugin.getPlugin(), PluginType.SENSITIVITY);
|
||||
addPreferencesFromResourceIfEnabled(SensitivityWeightedAveragePlugin.getPlugin(), PluginType.SENSITIVITY);
|
||||
addPreferencesFromResourceIfEnabled(SensitivityOref0Plugin.getPlugin(), PluginType.SENSITIVITY);
|
||||
|
||||
if (Config.DANAR) {
|
||||
addPreferencesFromResourceIfEnabled(DanaRPlugin.getPlugin(), PluginBase.PUMP);
|
||||
addPreferencesFromResourceIfEnabled(DanaRKoreanPlugin.getPlugin(), PluginBase.PUMP);
|
||||
addPreferencesFromResourceIfEnabled(DanaRv2Plugin.getPlugin(), PluginBase.PUMP);
|
||||
addPreferencesFromResourceIfEnabled(DanaRSPlugin.getPlugin(), PluginBase.PUMP);
|
||||
if (Config.HWPUMPS) {
|
||||
addPreferencesFromResourceIfEnabled(DanaRPlugin.getPlugin(), PluginType.PUMP);
|
||||
addPreferencesFromResourceIfEnabled(DanaRKoreanPlugin.getPlugin(), PluginType.PUMP);
|
||||
addPreferencesFromResourceIfEnabled(DanaRv2Plugin.getPlugin(), PluginType.PUMP);
|
||||
addPreferencesFromResourceIfEnabled(DanaRSPlugin.getPlugin(), PluginType.PUMP);
|
||||
addPreferencesFromResourceIfEnabled(InsightPlugin.getPlugin(), PluginType.PUMP);
|
||||
addPreferencesFromResourceIfEnabled(ComboPlugin.getPlugin(), PluginType.PUMP);
|
||||
|
||||
if (DanaRPlugin.getPlugin().isEnabled(PluginBase.PROFILE)
|
||||
|| DanaRKoreanPlugin.getPlugin().isEnabled(PluginBase.PROFILE)
|
||||
|| DanaRv2Plugin.getPlugin().isEnabled(PluginBase.PROFILE)
|
||||
|| DanaRSPlugin.getPlugin().isEnabled(PluginBase.PROFILE)) {
|
||||
if (DanaRPlugin.getPlugin().isEnabled(PluginType.PROFILE)
|
||||
|| DanaRKoreanPlugin.getPlugin().isEnabled(PluginType.PROFILE)
|
||||
|| DanaRv2Plugin.getPlugin().isEnabled(PluginType.PROFILE)
|
||||
|| DanaRSPlugin.getPlugin().isEnabled(PluginType.PROFILE)) {
|
||||
addPreferencesFromResource(R.xml.pref_danarprofile);
|
||||
}
|
||||
}
|
||||
|
||||
if (!Config.NSCLIENT && !Config.G5UPLOADER) {
|
||||
addPreferencesFromResourceIfEnabled(VirtualPumpPlugin.getPlugin(), PluginBase.PUMP);
|
||||
addPreferencesFromResourceIfEnabled(VirtualPumpPlugin.getPlugin(), PluginType.PUMP);
|
||||
}
|
||||
|
||||
addPreferencesFromResourceIfEnabled(InsulinOrefFreePeakPlugin.getPlugin(), PluginBase.INSULIN);
|
||||
addPreferencesFromResourceIfEnabled(InsulinOrefFreePeakPlugin.getPlugin(), PluginType.INSULIN);
|
||||
|
||||
addPreferencesFromResourceIfEnabled(NSClientInternalPlugin.getPlugin(), PluginBase.GENERAL);
|
||||
addPreferencesFromResourceIfEnabled(SmsCommunicatorPlugin.getPlugin(), PluginBase.GENERAL);
|
||||
addPreferencesFromResourceIfEnabled(NSClientPlugin.getPlugin(), PluginType.GENERAL);
|
||||
addPreferencesFromResourceIfEnabled(SmsCommunicatorPlugin.getPlugin(), PluginType.GENERAL);
|
||||
|
||||
if (!Config.NSCLIENT && !Config.G5UPLOADER) {
|
||||
addPreferencesFromResource(R.xml.pref_others);
|
||||
}
|
||||
addPreferencesFromResource(R.xml.pref_advanced);
|
||||
addPreferencesFromResource(R.xml.pref_datachoices);
|
||||
|
||||
addPreferencesFromResourceIfEnabled(WearPlugin.getPlugin(), PluginBase.GENERAL);
|
||||
addPreferencesFromResourceIfEnabled(StatuslinePlugin.getPlugin(), PluginBase.GENERAL);
|
||||
addPreferencesFromResourceIfEnabled(WearPlugin.getPlugin(), PluginType.GENERAL);
|
||||
addPreferencesFromResourceIfEnabled(StatuslinePlugin.getPlugin(), PluginType.GENERAL);
|
||||
}
|
||||
|
||||
initSummary(getPreferenceScreen());
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
package info.nightscout.androidaps.Services;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.AssetFileDescriptor;
|
||||
import android.media.AudioManager;
|
||||
import android.media.MediaPlayer;
|
||||
import android.os.IBinder;
|
||||
|
||||
|
@ -53,7 +55,10 @@ public class AlarmSoundService extends Service {
|
|||
log.error("Unhandled exception", e);
|
||||
}
|
||||
player.setLooping(true); // Set looping
|
||||
player.setVolume(100, 100);
|
||||
AudioManager manager = (AudioManager)this.getSystemService(Context.AUDIO_SERVICE);
|
||||
if (manager == null || !manager.isMusicActive()) {
|
||||
player.setVolume(100, 100);
|
||||
}
|
||||
|
||||
try {
|
||||
player.prepare();
|
||||
|
|
|
@ -18,7 +18,8 @@ import info.nightscout.androidaps.R;
|
|||
import info.nightscout.androidaps.data.ProfileStore;
|
||||
import info.nightscout.androidaps.db.BgReading;
|
||||
import info.nightscout.androidaps.db.CareportalEvent;
|
||||
import info.nightscout.androidaps.events.EventNewBasalProfile;
|
||||
import info.nightscout.androidaps.events.EventNsFood;
|
||||
import info.nightscout.androidaps.events.EventNsTreatment;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.ConstraintsObjectives.ObjectivesPlugin;
|
||||
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSDeviceStatus;
|
||||
|
@ -33,13 +34,14 @@ import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin;
|
|||
import info.nightscout.androidaps.plugins.ProfileNS.events.EventNSProfileUpdateGUI;
|
||||
import info.nightscout.androidaps.plugins.PumpDanaR.activities.DanaRNSHistorySync;
|
||||
import info.nightscout.androidaps.plugins.SmsCommunicator.events.EventNewSMS;
|
||||
import info.nightscout.androidaps.plugins.SourceDexcomG5.SourceDexcomG5Plugin;
|
||||
import info.nightscout.androidaps.plugins.SourceGlimp.SourceGlimpPlugin;
|
||||
import info.nightscout.androidaps.plugins.SourceMM640g.SourceMM640gPlugin;
|
||||
import info.nightscout.androidaps.plugins.SourceNSClient.SourceNSClientPlugin;
|
||||
import info.nightscout.androidaps.plugins.SourceXdrip.SourceXdripPlugin;
|
||||
import info.nightscout.androidaps.plugins.Source.SourceDexcomG5Plugin;
|
||||
import info.nightscout.androidaps.plugins.Source.SourceGlimpPlugin;
|
||||
import info.nightscout.androidaps.plugins.Source.SourceMM640gPlugin;
|
||||
import info.nightscout.androidaps.plugins.Source.SourceNSClientPlugin;
|
||||
import info.nightscout.androidaps.plugins.Source.SourceXdripPlugin;
|
||||
import info.nightscout.androidaps.receivers.DataReceiver;
|
||||
import info.nightscout.utils.BundleLogger;
|
||||
import info.nightscout.utils.JsonHelper;
|
||||
import info.nightscout.utils.NSUpload;
|
||||
import info.nightscout.utils.SP;
|
||||
|
||||
|
@ -62,32 +64,37 @@ public class DataService extends IntentService {
|
|||
protected void onHandleIntent(final Intent intent) {
|
||||
if (Config.logFunctionCalls)
|
||||
log.debug("onHandleIntent " + BundleLogger.log(intent.getExtras()));
|
||||
|
||||
if (ConfigBuilderPlugin.getActiveBgSource().getClass().equals(SourceXdripPlugin.class)) {
|
||||
if (ConfigBuilderPlugin.getPlugin().getActiveBgSource() == null) {
|
||||
xDripEnabled = true;
|
||||
nsClientEnabled = false;
|
||||
mm640gEnabled = false;
|
||||
glimpEnabled = false;
|
||||
dexcomG5Enabled = false;
|
||||
} else if (ConfigBuilderPlugin.getActiveBgSource().getClass().equals(SourceNSClientPlugin.class)) {
|
||||
} else if (ConfigBuilderPlugin.getPlugin().getActiveBgSource().getClass().equals(SourceXdripPlugin.class)) {
|
||||
xDripEnabled = true;
|
||||
nsClientEnabled = false;
|
||||
mm640gEnabled = false;
|
||||
glimpEnabled = false;
|
||||
dexcomG5Enabled = false;
|
||||
} else if (ConfigBuilderPlugin.getPlugin().getActiveBgSource().getClass().equals(SourceNSClientPlugin.class)) {
|
||||
xDripEnabled = false;
|
||||
nsClientEnabled = true;
|
||||
mm640gEnabled = false;
|
||||
glimpEnabled = false;
|
||||
dexcomG5Enabled = false;
|
||||
} else if (ConfigBuilderPlugin.getActiveBgSource().getClass().equals(SourceMM640gPlugin.class)) {
|
||||
} else if (ConfigBuilderPlugin.getPlugin().getActiveBgSource().getClass().equals(SourceMM640gPlugin.class)) {
|
||||
xDripEnabled = false;
|
||||
nsClientEnabled = false;
|
||||
mm640gEnabled = true;
|
||||
glimpEnabled = false;
|
||||
dexcomG5Enabled = false;
|
||||
} else if (ConfigBuilderPlugin.getActiveBgSource().getClass().equals(SourceGlimpPlugin.class)) {
|
||||
} else if (ConfigBuilderPlugin.getPlugin().getActiveBgSource().getClass().equals(SourceGlimpPlugin.class)) {
|
||||
xDripEnabled = false;
|
||||
nsClientEnabled = false;
|
||||
mm640gEnabled = false;
|
||||
glimpEnabled = true;
|
||||
dexcomG5Enabled = false;
|
||||
} else if (ConfigBuilderPlugin.getActiveBgSource().getClass().equals(SourceDexcomG5Plugin.class)) {
|
||||
} else if (ConfigBuilderPlugin.getPlugin().getActiveBgSource().getClass().equals(SourceDexcomG5Plugin.class)) {
|
||||
xDripEnabled = false;
|
||||
nsClientEnabled = false;
|
||||
mm640gEnabled = false;
|
||||
|
@ -95,7 +102,7 @@ public class DataService extends IntentService {
|
|||
dexcomG5Enabled = true;
|
||||
}
|
||||
|
||||
boolean isNSProfile = ConfigBuilderPlugin.getActiveProfileInterface().getClass().equals(NSProfilePlugin.class);
|
||||
boolean isNSProfile = MainApp.getConfigBuilder().getActiveProfileInterface() != null && MainApp.getConfigBuilder().getActiveProfileInterface().getClass().equals(NSProfilePlugin.class);
|
||||
|
||||
boolean acceptNSData = !SP.getBoolean(R.string.key_ns_upload_only, false);
|
||||
Bundle bundles = intent.getExtras();
|
||||
|
@ -123,8 +130,8 @@ public class DataService extends IntentService {
|
|||
handleNewDataFromDexcomG5(intent);
|
||||
}
|
||||
} else if (Intents.ACTION_NEW_SGV.equals(action)) {
|
||||
// always backfill SGV from NS
|
||||
handleNewDataFromNSClient(intent);
|
||||
if (nsClientEnabled || SP.getBoolean(R.string.key_ns_autobackfill, true))
|
||||
handleNewDataFromNSClient(intent);
|
||||
// Objectives 0
|
||||
ObjectivesPlugin.bgIsAvailableInNS = true;
|
||||
ObjectivesPlugin.saveProgress();
|
||||
|
@ -190,7 +197,8 @@ public class DataService extends IntentService {
|
|||
bgReading.direction = bundle.getString(Intents.EXTRA_BG_SLOPE_NAME);
|
||||
bgReading.date = bundle.getLong(Intents.EXTRA_TIMESTAMP);
|
||||
bgReading.raw = bundle.getDouble(Intents.EXTRA_RAW);
|
||||
|
||||
String source = bundle.getString(Intents.XDRIP_DATA_SOURCE_DESCRIPTION, "no Source specified");
|
||||
SourceXdripPlugin.getPlugin().setSource(source);
|
||||
MainApp.getDbHelper().createIfNotExists(bgReading, "XDRIP");
|
||||
}
|
||||
|
||||
|
@ -222,7 +230,7 @@ public class DataService extends IntentService {
|
|||
try {
|
||||
JSONArray jsonArray = new JSONArray(data);
|
||||
log.debug("Received Dexcom Data size:" + jsonArray.length());
|
||||
for(int i = 0; i < jsonArray.length(); i++) {
|
||||
for (int i = 0; i < jsonArray.length(); i++) {
|
||||
JSONObject json = jsonArray.getJSONObject(i);
|
||||
bgReading.value = json.getInt("m_value");
|
||||
bgReading.direction = json.getString("m_trend");
|
||||
|
@ -296,7 +304,7 @@ public class DataService extends IntentService {
|
|||
log.debug("Got versions: NSClient: " + ConfigBuilderPlugin.nsClientVersionName + " Nightscout: " + ConfigBuilderPlugin.nightscoutVersionName);
|
||||
try {
|
||||
if (ConfigBuilderPlugin.nsClientVersionCode < MainApp.instance().getPackageManager().getPackageInfo(MainApp.instance().getPackageName(), 0).versionCode) {
|
||||
Notification notification = new Notification(Notification.OLD_NSCLIENT, MainApp.sResources.getString(R.string.unsupportedclientver), Notification.URGENT);
|
||||
Notification notification = new Notification(Notification.OLD_NSCLIENT, MainApp.gs(R.string.unsupportedclientver), Notification.URGENT);
|
||||
MainApp.bus().post(new EventNewNotification(notification));
|
||||
} else {
|
||||
MainApp.bus().post(new EventDismissNotification(Notification.OLD_NSCLIENT));
|
||||
|
@ -305,13 +313,13 @@ public class DataService extends IntentService {
|
|||
log.error("Unhandled exception", e);
|
||||
}
|
||||
if (ConfigBuilderPlugin.nightscoutVersionCode < Config.SUPPORTEDNSVERSION) {
|
||||
Notification notification = new Notification(Notification.OLD_NS, MainApp.sResources.getString(R.string.unsupportednsversion), Notification.NORMAL);
|
||||
Notification notification = new Notification(Notification.OLD_NS, MainApp.gs(R.string.unsupportednsversion), Notification.NORMAL);
|
||||
MainApp.bus().post(new EventNewNotification(notification));
|
||||
} else {
|
||||
MainApp.bus().post(new EventDismissNotification(Notification.OLD_NS));
|
||||
}
|
||||
} else {
|
||||
Notification notification = new Notification(Notification.OLD_NSCLIENT, MainApp.sResources.getString(R.string.unsupportedclientver), Notification.URGENT);
|
||||
Notification notification = new Notification(Notification.OLD_NSCLIENT, MainApp.gs(R.string.unsupportedclientver), Notification.URGENT);
|
||||
MainApp.bus().post(new EventNewNotification(notification));
|
||||
}
|
||||
if (bundles.containsKey("status")) {
|
||||
|
@ -365,11 +373,8 @@ public class DataService extends IntentService {
|
|||
String activeProfile = bundles.getString("activeprofile");
|
||||
String profile = bundles.getString("profile");
|
||||
ProfileStore profileStore = new ProfileStore(new JSONObject(profile));
|
||||
NSProfilePlugin.storeNewProfile(profileStore);
|
||||
NSProfilePlugin.getPlugin().storeNewProfile(profileStore);
|
||||
MainApp.bus().post(new EventNSProfileUpdateGUI());
|
||||
// if there are no profile switches this should lead to profile update
|
||||
if (MainApp.getConfigBuilder().getProfileSwitchesFromHistory().size() == 0)
|
||||
MainApp.bus().post(new EventNewBasalProfile());
|
||||
if (Config.logIncommingData)
|
||||
log.debug("Received profileStore: " + activeProfile + " " + profile);
|
||||
} catch (JSONException e) {
|
||||
|
@ -380,19 +385,18 @@ public class DataService extends IntentService {
|
|||
if (intent.getAction().equals(Intents.ACTION_NEW_TREATMENT) || intent.getAction().equals(Intents.ACTION_CHANGED_TREATMENT)) {
|
||||
try {
|
||||
if (bundles.containsKey("treatment")) {
|
||||
String trstring = bundles.getString("treatment");
|
||||
handleAddChangeDataFromNS(trstring);
|
||||
JSONObject json = new JSONObject(bundles.getString("treatment"));
|
||||
handleTreatmentFromNS(json, intent);
|
||||
}
|
||||
if (bundles.containsKey("treatments")) {
|
||||
String trstring = bundles.getString("treatments");
|
||||
JSONArray jsonArray = new JSONArray(trstring);
|
||||
for (int i = 0; i < jsonArray.length(); i++) {
|
||||
JSONObject trJson = jsonArray.getJSONObject(i);
|
||||
String trstr = trJson.toString();
|
||||
handleAddChangeDataFromNS(trstr);
|
||||
JSONObject json = jsonArray.getJSONObject(i);
|
||||
handleTreatmentFromNS(json, intent);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
} catch (JSONException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
}
|
||||
|
@ -401,21 +405,19 @@ public class DataService extends IntentService {
|
|||
try {
|
||||
if (bundles.containsKey("treatment")) {
|
||||
String trstring = bundles.getString("treatment");
|
||||
JSONObject trJson = new JSONObject(trstring);
|
||||
String _id = trJson.getString("_id");
|
||||
handleRemovedRecordFromNS(_id);
|
||||
JSONObject json = new JSONObject(trstring);
|
||||
handleTreatmentFromNS(json);
|
||||
}
|
||||
|
||||
if (bundles.containsKey("treatments")) {
|
||||
String trstring = bundles.getString("treatments");
|
||||
JSONArray jsonArray = new JSONArray(trstring);
|
||||
for (int i = 0; i < jsonArray.length(); i++) {
|
||||
JSONObject trJson = jsonArray.getJSONObject(i);
|
||||
String _id = trJson.getString("_id");
|
||||
handleRemovedRecordFromNS(_id);
|
||||
JSONObject json = jsonArray.getJSONObject(i);
|
||||
handleTreatmentFromNS(json);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
} catch (JSONException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
}
|
||||
|
@ -474,59 +476,25 @@ public class DataService extends IntentService {
|
|||
}
|
||||
}
|
||||
|
||||
if (intent.getAction().equals(Intents.ACTION_NEW_FOOD) || intent.getAction().equals(Intents.ACTION_CHANGED_FOOD)) {
|
||||
try {
|
||||
if (bundles.containsKey("food")) {
|
||||
String trstring = bundles.getString("food");
|
||||
handleAddChangeFoodRecord(new JSONObject(trstring));
|
||||
}
|
||||
if (bundles.containsKey("foods")) {
|
||||
String trstring = bundles.getString("foods");
|
||||
JSONArray jsonArray = new JSONArray(trstring);
|
||||
for (int i = 0; i < jsonArray.length(); i++) {
|
||||
JSONObject trJson = jsonArray.getJSONObject(i);
|
||||
handleAddChangeFoodRecord(trJson);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
if (intent.getAction().equals(Intents.ACTION_NEW_FOOD)
|
||||
|| intent.getAction().equals(Intents.ACTION_CHANGED_FOOD)) {
|
||||
int mode = Intents.ACTION_NEW_FOOD.equals(intent.getAction()) ? EventNsFood.ADD : EventNsFood.UPDATE;
|
||||
EventNsFood evt = new EventNsFood(mode, bundles);
|
||||
MainApp.bus().post(evt);
|
||||
}
|
||||
|
||||
if (intent.getAction().equals(Intents.ACTION_REMOVED_FOOD)) {
|
||||
try {
|
||||
if (bundles.containsKey("food")) {
|
||||
String trstring = bundles.getString("food");
|
||||
JSONObject trJson = new JSONObject(trstring);
|
||||
String _id = trJson.getString("_id");
|
||||
handleRemovedFoodRecord(_id);
|
||||
}
|
||||
|
||||
if (bundles.containsKey("foods")) {
|
||||
String trstring = bundles.getString("foods");
|
||||
JSONArray jsonArray = new JSONArray(trstring);
|
||||
for (int i = 0; i < jsonArray.length(); i++) {
|
||||
JSONObject trJson = jsonArray.getJSONObject(i);
|
||||
String _id = trJson.getString("_id");
|
||||
handleRemovedFoodRecord(_id);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
EventNsFood evt = new EventNsFood(EventNsFood.REMOVE, bundles);
|
||||
MainApp.bus().post(evt);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleRemovedFoodRecord(String _id) {
|
||||
MainApp.getDbHelper().foodHelper.deleteFoodById(_id);
|
||||
}
|
||||
|
||||
public void handleAddChangeFoodRecord(JSONObject trJson) throws JSONException {
|
||||
MainApp.getDbHelper().foodHelper.createFoodFromJsonIfNotExists(trJson);
|
||||
}
|
||||
|
||||
private void handleRemovedRecordFromNS(String _id) {
|
||||
MainApp.getDbHelper().deleteTreatmentById(_id);
|
||||
private void handleTreatmentFromNS(JSONObject json) {
|
||||
// new DB model
|
||||
EventNsTreatment evtTreatment = new EventNsTreatment(EventNsTreatment.REMOVE, json);
|
||||
MainApp.bus().post(evtTreatment);
|
||||
// old DB model
|
||||
String _id = JsonHelper.safeGetString(json, "_id");
|
||||
MainApp.getDbHelper().deleteTempTargetById(_id);
|
||||
MainApp.getDbHelper().deleteTempBasalById(_id);
|
||||
MainApp.getDbHelper().deleteExtendedBolusById(_id);
|
||||
|
@ -534,85 +502,53 @@ public class DataService extends IntentService {
|
|||
MainApp.getDbHelper().deleteProfileSwitchById(_id);
|
||||
}
|
||||
|
||||
private void handleAddChangeDataFromNS(String trstring) throws JSONException {
|
||||
JSONObject trJson = new JSONObject(trstring);
|
||||
handleDanaRHistoryRecords(trJson); // update record _id in history
|
||||
handleAddChangeTempTargetRecord(trJson);
|
||||
handleAddChangeTempBasalRecord(trJson);
|
||||
handleAddChangeExtendedBolusRecord(trJson);
|
||||
handleAddChangeCareportalEventRecord(trJson);
|
||||
handleAddChangeTreatmentRecord(trJson);
|
||||
handleAddChangeProfileSwitchRecord(trJson);
|
||||
}
|
||||
|
||||
public void handleDanaRHistoryRecords(JSONObject trJson) {
|
||||
if (trJson.has(DanaRNSHistorySync.DANARSIGNATURE)) {
|
||||
MainApp.getDbHelper().updateDanaRHistoryRecordId(trJson);
|
||||
}
|
||||
}
|
||||
|
||||
public void handleAddChangeTreatmentRecord(JSONObject trJson) throws JSONException {
|
||||
if (trJson.has("insulin") || trJson.has("carbs")) {
|
||||
MainApp.getDbHelper().createTreatmentFromJsonIfNotExists(trJson);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public void handleAddChangeTempTargetRecord(JSONObject trJson) throws JSONException {
|
||||
if (trJson.has("eventType") && trJson.getString("eventType").equals(CareportalEvent.TEMPORARYTARGET)) {
|
||||
MainApp.getDbHelper().createTemptargetFromJsonIfNotExists(trJson);
|
||||
}
|
||||
}
|
||||
|
||||
public void handleAddChangeTempBasalRecord(JSONObject trJson) throws JSONException {
|
||||
if (trJson.has("eventType") && trJson.getString("eventType").equals(CareportalEvent.TEMPBASAL)) {
|
||||
MainApp.getDbHelper().createTempBasalFromJsonIfNotExists(trJson);
|
||||
}
|
||||
}
|
||||
|
||||
public void handleAddChangeExtendedBolusRecord(JSONObject trJson) throws JSONException {
|
||||
if (trJson.has("eventType") && trJson.getString("eventType").equals(CareportalEvent.COMBOBOLUS)) {
|
||||
MainApp.getDbHelper().createExtendedBolusFromJsonIfNotExists(trJson);
|
||||
}
|
||||
}
|
||||
|
||||
public void handleAddChangeCareportalEventRecord(JSONObject trJson) throws JSONException {
|
||||
if (trJson.has("insulin") && trJson.getDouble("insulin") > 0)
|
||||
return;
|
||||
if (trJson.has("carbs") && trJson.getDouble("carbs") > 0)
|
||||
return;
|
||||
if (trJson.has("eventType") && (
|
||||
trJson.getString("eventType").equals(CareportalEvent.SITECHANGE) ||
|
||||
trJson.getString("eventType").equals(CareportalEvent.INSULINCHANGE) ||
|
||||
trJson.getString("eventType").equals(CareportalEvent.SENSORCHANGE) ||
|
||||
trJson.getString("eventType").equals(CareportalEvent.BGCHECK) ||
|
||||
trJson.getString("eventType").equals(CareportalEvent.NOTE) ||
|
||||
trJson.getString("eventType").equals(CareportalEvent.NONE) ||
|
||||
trJson.getString("eventType").equals(CareportalEvent.ANNOUNCEMENT) ||
|
||||
trJson.getString("eventType").equals(CareportalEvent.QUESTION) ||
|
||||
trJson.getString("eventType").equals(CareportalEvent.EXERCISE) ||
|
||||
trJson.getString("eventType").equals(CareportalEvent.OPENAPSOFFLINE) ||
|
||||
trJson.getString("eventType").equals(CareportalEvent.PUMPBATTERYCHANGE)
|
||||
)) {
|
||||
MainApp.getDbHelper().createCareportalEventFromJsonIfNotExists(trJson);
|
||||
private void handleTreatmentFromNS(JSONObject json, Intent intent) throws JSONException {
|
||||
// new DB model
|
||||
int mode = Intents.ACTION_NEW_TREATMENT.equals(intent.getAction()) ? EventNsTreatment.ADD : EventNsTreatment.UPDATE;
|
||||
double insulin = JsonHelper.safeGetDouble(json, "insulin");
|
||||
double carbs = JsonHelper.safeGetDouble(json, "carbs");
|
||||
String eventType = JsonHelper.safeGetString(json, "eventType");
|
||||
if (insulin > 0 || carbs > 0) {
|
||||
EventNsTreatment evtTreatment = new EventNsTreatment(mode, json);
|
||||
MainApp.bus().post(evtTreatment);
|
||||
} else if (json.has(DanaRNSHistorySync.DANARSIGNATURE)) {
|
||||
// old DB model
|
||||
MainApp.getDbHelper().updateDanaRHistoryRecordId(json);
|
||||
} else if (eventType.equals(CareportalEvent.TEMPORARYTARGET)) {
|
||||
MainApp.getDbHelper().createTemptargetFromJsonIfNotExists(json);
|
||||
} else if (eventType.equals(CareportalEvent.TEMPBASAL)) {
|
||||
MainApp.getDbHelper().createTempBasalFromJsonIfNotExists(json);
|
||||
} else if (eventType.equals(CareportalEvent.COMBOBOLUS)) {
|
||||
MainApp.getDbHelper().createExtendedBolusFromJsonIfNotExists(json);
|
||||
} else if (eventType.equals(CareportalEvent.PROFILESWITCH)) {
|
||||
MainApp.getDbHelper().createProfileSwitchFromJsonIfNotExists(json);
|
||||
} else if (eventType.equals(CareportalEvent.SITECHANGE) ||
|
||||
eventType.equals(CareportalEvent.INSULINCHANGE) ||
|
||||
eventType.equals(CareportalEvent.SENSORCHANGE) ||
|
||||
eventType.equals(CareportalEvent.BGCHECK) ||
|
||||
eventType.equals(CareportalEvent.NOTE) ||
|
||||
eventType.equals(CareportalEvent.NONE) ||
|
||||
eventType.equals(CareportalEvent.ANNOUNCEMENT) ||
|
||||
eventType.equals(CareportalEvent.QUESTION) ||
|
||||
eventType.equals(CareportalEvent.EXERCISE) ||
|
||||
eventType.equals(CareportalEvent.OPENAPSOFFLINE) ||
|
||||
eventType.equals(CareportalEvent.PUMPBATTERYCHANGE)) {
|
||||
MainApp.getDbHelper().createCareportalEventFromJsonIfNotExists(json);
|
||||
}
|
||||
|
||||
if (trJson.has("eventType") && trJson.getString("eventType").equals(CareportalEvent.ANNOUNCEMENT)) {
|
||||
long date = trJson.getLong("mills");
|
||||
if (eventType.equals(CareportalEvent.ANNOUNCEMENT)) {
|
||||
long date = JsonHelper.safeGetLong(json,"mills");
|
||||
long now = System.currentTimeMillis();
|
||||
if (date > now - 15 * 60 * 1000L && trJson.has("notes")) {
|
||||
Notification announcement = new Notification(Notification.NSANNOUNCEMENT, trJson.getString("notes"), Notification.ANNOUNCEMENT, 60);
|
||||
String enteredBy = JsonHelper.safeGetString(json, "enteredBy", "");
|
||||
String notes = JsonHelper.safeGetString(json, "notes", "");
|
||||
if (date > now - 15 * 60 * 1000L && !notes.isEmpty()
|
||||
&& !enteredBy.equals(SP.getString("careportal_enteredby", "AndroidAPS"))) {
|
||||
Notification announcement = new Notification(Notification.NSANNOUNCEMENT, notes, Notification.ANNOUNCEMENT, 60);
|
||||
MainApp.bus().post(new EventNewNotification(announcement));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void handleAddChangeProfileSwitchRecord(JSONObject trJson) throws JSONException {
|
||||
if (trJson.has("eventType") && trJson.getString("eventType").equals(CareportalEvent.PROFILESWITCH)) {
|
||||
MainApp.getDbHelper().createProfileSwitchFromJsonIfNotExists(trJson);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleNewSMS(Intent intent) {
|
||||
Bundle bundle = intent.getExtras();
|
||||
if (bundle == null) return;
|
||||
|
|
|
@ -37,6 +37,8 @@ public interface Intents {
|
|||
String EXTRA_SENSOR_BATTERY = "com.eveningoutpost.dexdrip.Extras.SensorBattery";
|
||||
String EXTRA_TIMESTAMP = "com.eveningoutpost.dexdrip.Extras.Time";
|
||||
String EXTRA_RAW = "com.eveningoutpost.dexdrip.Extras.Raw";
|
||||
String XDRIP_DATA_SOURCE_DESCRIPTION = "com.eveningoutpost.dexdrip.Extras.SourceDesc";
|
||||
|
||||
|
||||
String ACTION_NEW_BG_ESTIMATE_NO_DATA = "com.eveningoutpost.dexdrip.BgEstimateNoData";
|
||||
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
package info.nightscout.androidaps.plugins.PumpDanaR.activities;
|
||||
package info.nightscout.androidaps;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.text.TextUtils;
|
||||
import android.view.KeyEvent;
|
||||
|
@ -35,21 +33,26 @@ import java.util.Date;
|
|||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.data.Profile;
|
||||
import info.nightscout.androidaps.db.DanaRHistoryRecord;
|
||||
import info.nightscout.androidaps.db.TDD;
|
||||
import info.nightscout.androidaps.events.EventPumpStatusChanged;
|
||||
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin;
|
||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes;
|
||||
import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRSyncStatus;
|
||||
import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin;
|
||||
import info.nightscout.androidaps.plugins.PumpDanaRS.DanaRSPlugin;
|
||||
import info.nightscout.androidaps.plugins.PumpDanaRv2.DanaRv2Plugin;
|
||||
import info.nightscout.androidaps.plugins.PumpInsight.InsightPlugin;
|
||||
import info.nightscout.androidaps.queue.Callback;
|
||||
import info.nightscout.utils.DecimalFormatter;
|
||||
import info.nightscout.utils.SP;
|
||||
import info.nightscout.utils.SafeParse;
|
||||
|
||||
public class DanaRStatsActivity extends Activity {
|
||||
private static Logger log = LoggerFactory.getLogger(DanaRStatsActivity.class);
|
||||
public class TDDStatsActivity extends Activity {
|
||||
private static Logger log = LoggerFactory.getLogger(TDDStatsActivity.class);
|
||||
|
||||
TextView statusView, statsMessage, totalBaseBasal2;
|
||||
EditText totalBaseBasal;
|
||||
|
@ -60,10 +63,10 @@ public class DanaRStatsActivity extends Activity {
|
|||
double magicNumber;
|
||||
DecimalFormat decimalFormat;
|
||||
|
||||
List<DanaRHistoryRecord> historyList = new ArrayList<>();
|
||||
List<DanaRHistoryRecord> dummies;
|
||||
List<TDD> historyList = new ArrayList<>();
|
||||
List<TDD> dummies;
|
||||
|
||||
public DanaRStatsActivity() {
|
||||
public TDDStatsActivity() {
|
||||
super();
|
||||
}
|
||||
|
||||
|
@ -126,6 +129,9 @@ public class DanaRStatsActivity extends Activity {
|
|||
}
|
||||
totalBaseBasal.setText(TBB);
|
||||
|
||||
if (!ConfigBuilderPlugin.getActivePump().getPumpDescription().needsManualTDDLoad)
|
||||
reloadButton.setVisibility(View.GONE);
|
||||
|
||||
// stats table
|
||||
tl = (TableLayout) findViewById(R.id.main_table);
|
||||
TableRow tr_head = new TableRow(this);
|
||||
|
@ -135,27 +141,27 @@ public class DanaRStatsActivity extends Activity {
|
|||
TableLayout.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
TextView label_date = new TextView(this);
|
||||
label_date.setText(getString(R.string.danar_stats_date));
|
||||
label_date.setText(MainApp.gs(R.string.danar_stats_date));
|
||||
label_date.setTextColor(Color.WHITE);
|
||||
tr_head.addView(label_date);
|
||||
|
||||
TextView label_basalrate = new TextView(this);
|
||||
label_basalrate.setText(getString(R.string.danar_stats_basalrate));
|
||||
label_basalrate.setText(MainApp.gs(R.string.danar_stats_basalrate));
|
||||
label_basalrate.setTextColor(Color.WHITE);
|
||||
tr_head.addView(label_basalrate);
|
||||
|
||||
TextView label_bolus = new TextView(this);
|
||||
label_bolus.setText(getString(R.string.danar_stats_bolus));
|
||||
label_bolus.setText(MainApp.gs(R.string.danar_stats_bolus));
|
||||
label_bolus.setTextColor(Color.WHITE);
|
||||
tr_head.addView(label_bolus);
|
||||
|
||||
TextView label_tdd = new TextView(this);
|
||||
label_tdd.setText(getString(R.string.danar_stats_tdd));
|
||||
label_tdd.setText(MainApp.gs(R.string.danar_stats_tdd));
|
||||
label_tdd.setTextColor(Color.WHITE);
|
||||
tr_head.addView(label_tdd);
|
||||
|
||||
TextView label_ratio = new TextView(this);
|
||||
label_ratio.setText(getString(R.string.danar_stats_ratio));
|
||||
label_ratio.setText(MainApp.gs(R.string.danar_stats_ratio));
|
||||
label_ratio.setTextColor(Color.WHITE);
|
||||
tr_head.addView(label_ratio);
|
||||
|
||||
|
@ -173,17 +179,17 @@ public class DanaRStatsActivity extends Activity {
|
|||
TableLayout.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
TextView label_cum_amount_days = new TextView(this);
|
||||
label_cum_amount_days.setText(getString(R.string.danar_stats_amount_days));
|
||||
label_cum_amount_days.setText(MainApp.gs(R.string.danar_stats_amount_days));
|
||||
label_cum_amount_days.setTextColor(Color.WHITE);
|
||||
ctr_head.addView(label_cum_amount_days);
|
||||
|
||||
TextView label_cum_tdd = new TextView(this);
|
||||
label_cum_tdd.setText(getString(R.string.danar_stats_tdd));
|
||||
label_cum_tdd.setText(MainApp.gs(R.string.danar_stats_tdd));
|
||||
label_cum_tdd.setTextColor(Color.WHITE);
|
||||
ctr_head.addView(label_cum_tdd);
|
||||
|
||||
TextView label_cum_ratio = new TextView(this);
|
||||
label_cum_ratio.setText(getString(R.string.danar_stats_ratio));
|
||||
label_cum_ratio.setText(MainApp.gs(R.string.danar_stats_ratio));
|
||||
label_cum_ratio.setTextColor(Color.WHITE);
|
||||
ctr_head.addView(label_cum_ratio);
|
||||
|
||||
|
@ -201,17 +207,17 @@ public class DanaRStatsActivity extends Activity {
|
|||
TableLayout.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
TextView label_exp_weight = new TextView(this);
|
||||
label_exp_weight.setText(getString(R.string.danar_stats_weight));
|
||||
label_exp_weight.setText(MainApp.gs(R.string.danar_stats_weight));
|
||||
label_exp_weight.setTextColor(Color.WHITE);
|
||||
etr_head.addView(label_exp_weight);
|
||||
|
||||
TextView label_exp_tdd = new TextView(this);
|
||||
label_exp_tdd.setText(getString(R.string.danar_stats_tdd));
|
||||
label_exp_tdd.setText(MainApp.gs(R.string.danar_stats_tdd));
|
||||
label_exp_tdd.setTextColor(Color.WHITE);
|
||||
etr_head.addView(label_exp_tdd);
|
||||
|
||||
TextView label_exp_ratio = new TextView(this);
|
||||
label_exp_ratio.setText(getString(R.string.danar_stats_ratio));
|
||||
label_exp_ratio.setText(MainApp.gs(R.string.danar_stats_ratio));
|
||||
label_exp_ratio.setTextColor(Color.WHITE);
|
||||
etr_head.addView(label_exp_ratio);
|
||||
|
||||
|
@ -229,13 +235,13 @@ public class DanaRStatsActivity extends Activity {
|
|||
reloadButton.setVisibility(View.GONE);
|
||||
statusView.setVisibility(View.VISIBLE);
|
||||
statsMessage.setVisibility(View.VISIBLE);
|
||||
statsMessage.setText(getString(R.string.danar_stats_warning_Message));
|
||||
statsMessage.setText(MainApp.gs(R.string.danar_stats_warning_Message));
|
||||
}
|
||||
});
|
||||
ConfigBuilderPlugin.getCommandQueue().loadHistory(RecordTypes.RECORD_TYPE_DAILY, new Callback() {
|
||||
ConfigBuilderPlugin.getCommandQueue().loadTDDs( new Callback() {
|
||||
@Override
|
||||
public void run() {
|
||||
loadDataFromDB(RecordTypes.RECORD_TYPE_DAILY);
|
||||
loadDataFromDB();
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
@ -268,18 +274,18 @@ public class DanaRStatsActivity extends Activity {
|
|||
} else {
|
||||
SP.putString("TBB", totalBaseBasal.getText().toString());
|
||||
TBB = SP.getString("TBB", "");
|
||||
loadDataFromDB(RecordTypes.RECORD_TYPE_DAILY);
|
||||
loadDataFromDB();
|
||||
InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
|
||||
imm.hideSoftInputFromWindow(totalBaseBasal.getWindowToken(), 0);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
loadDataFromDB(RecordTypes.RECORD_TYPE_DAILY);
|
||||
loadDataFromDB();
|
||||
}
|
||||
|
||||
private void loadDataFromDB(byte type) {
|
||||
historyList = MainApp.getDbHelper().getDanaRHistoryRecordsByType(type);
|
||||
private void loadDataFromDB() {
|
||||
historyList = MainApp.getDbHelper().getTDDs();
|
||||
|
||||
//only use newest 10
|
||||
historyList = historyList.subList(0, Math.min(10, historyList.size()));
|
||||
|
@ -288,24 +294,24 @@ public class DanaRStatsActivity extends Activity {
|
|||
dummies = new LinkedList();
|
||||
DateFormat df = new SimpleDateFormat("dd.MM.");
|
||||
for (int i = 0; i < historyList.size() - 1; i++) {
|
||||
DanaRHistoryRecord elem1 = historyList.get(i);
|
||||
DanaRHistoryRecord elem2 = historyList.get(i + 1);
|
||||
TDD elem1 = historyList.get(i);
|
||||
TDD elem2 = historyList.get(i + 1);
|
||||
|
||||
if (!df.format(new Date(elem1.recordDate)).equals(df.format(new Date(elem2.recordDate + 25 * 60 * 60 * 1000)))) {
|
||||
DanaRHistoryRecord dummy = new DanaRHistoryRecord();
|
||||
dummy.recordDate = elem1.recordDate - 24 * 60 * 60 * 1000;
|
||||
dummy.recordDailyBasal = elem1.recordDailyBasal / 2;
|
||||
dummy.recordDailyBolus = elem1.recordDailyBolus / 2;
|
||||
if (!df.format(new Date(elem1.date)).equals(df.format(new Date(elem2.date + 25 * 60 * 60 * 1000)))) {
|
||||
TDD dummy = new TDD();
|
||||
dummy.date = elem1.date - 24 * 60 * 60 * 1000;
|
||||
dummy.basal = elem1.basal / 2;
|
||||
dummy.bolus = elem1.bolus / 2;
|
||||
dummies.add(dummy);
|
||||
elem1.recordDailyBasal /= 2;
|
||||
elem1.recordDailyBolus /= 2;
|
||||
elem1.basal /= 2;
|
||||
elem1.bolus /= 2;
|
||||
}
|
||||
}
|
||||
historyList.addAll(dummies);
|
||||
Collections.sort(historyList, new Comparator<DanaRHistoryRecord>() {
|
||||
Collections.sort(historyList, new Comparator<TDD>() {
|
||||
@Override
|
||||
public int compare(DanaRHistoryRecord lhs, DanaRHistoryRecord rhs) {
|
||||
return (int) (rhs.recordDate - lhs.recordDate);
|
||||
public int compare(TDD lhs, TDD rhs) {
|
||||
return (int) (rhs.date - lhs.date);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -333,11 +339,13 @@ public class DanaRStatsActivity extends Activity {
|
|||
double weighted05 = 0d;
|
||||
double weighted07 = 0d;
|
||||
|
||||
for (DanaRHistoryRecord record : historyList) {
|
||||
double tdd = record.recordDailyBolus + record.recordDailyBasal;
|
||||
|
||||
//TDD table
|
||||
for (TDD record : historyList) {
|
||||
double tdd = record.getTotal();
|
||||
|
||||
// Create the table row
|
||||
TableRow tr = new TableRow(DanaRStatsActivity.this);
|
||||
TableRow tr = new TableRow(TDDStatsActivity.this);
|
||||
if (i % 2 != 0) tr.setBackgroundColor(Color.DKGRAY);
|
||||
if (dummies.contains(record)) {
|
||||
tr.setBackgroundColor(Color.argb(125, 255, 0, 0));
|
||||
|
@ -348,31 +356,31 @@ public class DanaRStatsActivity extends Activity {
|
|||
TableLayout.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
// Here create the TextView dynamically
|
||||
TextView labelDATE = new TextView(DanaRStatsActivity.this);
|
||||
TextView labelDATE = new TextView(TDDStatsActivity.this);
|
||||
labelDATE.setId(200 + i);
|
||||
labelDATE.setText(df.format(new Date(record.recordDate)));
|
||||
labelDATE.setText(df.format(new Date(record.date)));
|
||||
labelDATE.setTextColor(Color.WHITE);
|
||||
tr.addView(labelDATE);
|
||||
|
||||
TextView labelBASAL = new TextView(DanaRStatsActivity.this);
|
||||
TextView labelBASAL = new TextView(TDDStatsActivity.this);
|
||||
labelBASAL.setId(300 + i);
|
||||
labelBASAL.setText(DecimalFormatter.to2Decimal(record.recordDailyBasal) + " U");
|
||||
labelBASAL.setText(DecimalFormatter.to2Decimal(record.basal) + " U");
|
||||
labelBASAL.setTextColor(Color.WHITE);
|
||||
tr.addView(labelBASAL);
|
||||
|
||||
TextView labelBOLUS = new TextView(DanaRStatsActivity.this);
|
||||
TextView labelBOLUS = new TextView(TDDStatsActivity.this);
|
||||
labelBOLUS.setId(400 + i);
|
||||
labelBOLUS.setText(DecimalFormatter.to2Decimal(record.recordDailyBolus) + " U");
|
||||
labelBOLUS.setText(DecimalFormatter.to2Decimal(record.bolus) + " U");
|
||||
labelBOLUS.setTextColor(Color.WHITE);
|
||||
tr.addView(labelBOLUS);
|
||||
|
||||
TextView labelTDD = new TextView(DanaRStatsActivity.this);
|
||||
TextView labelTDD = new TextView(TDDStatsActivity.this);
|
||||
labelTDD.setId(500 + i);
|
||||
labelTDD.setText(DecimalFormatter.to2Decimal(tdd) + " U");
|
||||
labelTDD.setTextColor(Color.WHITE);
|
||||
tr.addView(labelTDD);
|
||||
|
||||
TextView labelRATIO = new TextView(DanaRStatsActivity.this);
|
||||
TextView labelRATIO = new TextView(TDDStatsActivity.this);
|
||||
labelRATIO.setId(600 + i);
|
||||
labelRATIO.setText(Math.round(100 * tdd / magicNumber) + " %");
|
||||
labelRATIO.setTextColor(Color.WHITE);
|
||||
|
@ -383,11 +391,23 @@ public class DanaRStatsActivity extends Activity {
|
|||
TableLayout.LayoutParams.MATCH_PARENT,
|
||||
TableLayout.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
sum = sum + tdd;
|
||||
i++;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
|
||||
//cumulative TDDs
|
||||
for (TDD record : historyList) {
|
||||
if(!historyList.isEmpty() && df.format(new Date(record.date)).equals(df.format(new Date()))) {
|
||||
//Today should not be included
|
||||
continue;
|
||||
}
|
||||
i++;
|
||||
|
||||
sum = sum + record.getTotal();
|
||||
|
||||
// Create the cumtable row
|
||||
TableRow ctr = new TableRow(DanaRStatsActivity.this);
|
||||
TableRow ctr = new TableRow(TDDStatsActivity.this);
|
||||
if (i % 2 == 0) ctr.setBackgroundColor(Color.DKGRAY);
|
||||
ctr.setId(700 + i);
|
||||
ctr.setLayoutParams(new TableLayout.LayoutParams(
|
||||
|
@ -395,19 +415,19 @@ public class DanaRStatsActivity extends Activity {
|
|||
TableLayout.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
// Here create the TextView dynamically
|
||||
TextView labelDAYS = new TextView(DanaRStatsActivity.this);
|
||||
TextView labelDAYS = new TextView(TDDStatsActivity.this);
|
||||
labelDAYS.setId(800 + i);
|
||||
labelDAYS.setText("" + i);
|
||||
labelDAYS.setTextColor(Color.WHITE);
|
||||
ctr.addView(labelDAYS);
|
||||
|
||||
TextView labelCUMTDD = new TextView(DanaRStatsActivity.this);
|
||||
TextView labelCUMTDD = new TextView(TDDStatsActivity.this);
|
||||
labelCUMTDD.setId(900 + i);
|
||||
labelCUMTDD.setText(DecimalFormatter.to2Decimal(sum / i) + " U");
|
||||
labelCUMTDD.setTextColor(Color.WHITE);
|
||||
ctr.addView(labelCUMTDD);
|
||||
|
||||
TextView labelCUMRATIO = new TextView(DanaRStatsActivity.this);
|
||||
TextView labelCUMRATIO = new TextView(TDDStatsActivity.this);
|
||||
labelCUMRATIO.setId(1000 + i);
|
||||
labelCUMRATIO.setText(Math.round(100 * sum / i / magicNumber) + " %");
|
||||
labelCUMRATIO.setTextColor(Color.WHITE);
|
||||
|
@ -419,20 +439,25 @@ public class DanaRStatsActivity extends Activity {
|
|||
TableLayout.LayoutParams.WRAP_CONTENT));
|
||||
}
|
||||
|
||||
if (historyList.size() < 3 || !(df.format(new Date(historyList.get(0).recordDate)).equals(df.format(new Date(System.currentTimeMillis() - 1000 * 60 * 60 * 24))))) {
|
||||
if (isOldData(historyList) && ConfigBuilderPlugin.getActivePump().getPumpDescription().needsManualTDDLoad) {
|
||||
statsMessage.setVisibility(View.VISIBLE);
|
||||
statsMessage.setText(getString(R.string.danar_stats_olddata_Message));
|
||||
statsMessage.setText(MainApp.gs(R.string.danar_stats_olddata_Message));
|
||||
|
||||
} else {
|
||||
tl.setBackgroundColor(Color.TRANSPARENT);
|
||||
}
|
||||
|
||||
if(!historyList.isEmpty() && df.format(new Date(historyList.get(0).date)).equals(df.format(new Date()))) {
|
||||
//Today should not be included
|
||||
historyList.remove(0);
|
||||
}
|
||||
|
||||
Collections.reverse(historyList);
|
||||
|
||||
i = 0;
|
||||
|
||||
for (DanaRHistoryRecord record : historyList) {
|
||||
double tdd = record.recordDailyBolus + record.recordDailyBasal;
|
||||
for (TDD record : historyList) {
|
||||
double tdd = record.getTotal();
|
||||
if (i == 0) {
|
||||
weighted03 = tdd;
|
||||
weighted05 = tdd;
|
||||
|
@ -447,7 +472,7 @@ public class DanaRStatsActivity extends Activity {
|
|||
}
|
||||
|
||||
// Create the exptable row
|
||||
TableRow etr = new TableRow(DanaRStatsActivity.this);
|
||||
TableRow etr = new TableRow(TDDStatsActivity.this);
|
||||
if (i % 2 != 0) etr.setBackgroundColor(Color.DKGRAY);
|
||||
etr.setId(1100 + i);
|
||||
etr.setLayoutParams(new TableLayout.LayoutParams(
|
||||
|
@ -455,13 +480,13 @@ public class DanaRStatsActivity extends Activity {
|
|||
TableLayout.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
// Here create the TextView dynamically
|
||||
TextView labelWEIGHT = new TextView(DanaRStatsActivity.this);
|
||||
TextView labelWEIGHT = new TextView(TDDStatsActivity.this);
|
||||
labelWEIGHT.setId(1200 + i);
|
||||
labelWEIGHT.setText("0.3\n" + "0.5\n" + "0.7");
|
||||
labelWEIGHT.setTextColor(Color.WHITE);
|
||||
etr.addView(labelWEIGHT);
|
||||
|
||||
TextView labelEXPTDD = new TextView(DanaRStatsActivity.this);
|
||||
TextView labelEXPTDD = new TextView(TDDStatsActivity.this);
|
||||
labelEXPTDD.setId(1300 + i);
|
||||
labelEXPTDD.setText(DecimalFormatter.to2Decimal(weighted03)
|
||||
+ " U\n" + DecimalFormatter.to2Decimal(weighted05)
|
||||
|
@ -469,7 +494,7 @@ public class DanaRStatsActivity extends Activity {
|
|||
labelEXPTDD.setTextColor(Color.WHITE);
|
||||
etr.addView(labelEXPTDD);
|
||||
|
||||
TextView labelEXPRATIO = new TextView(DanaRStatsActivity.this);
|
||||
TextView labelEXPRATIO = new TextView(TDDStatsActivity.this);
|
||||
labelEXPRATIO.setId(1400 + i);
|
||||
labelEXPRATIO.setText(Math.round(100 * weighted03 / magicNumber) + " %\n"
|
||||
+ Math.round(100 * weighted05 / magicNumber) + " %\n"
|
||||
|
@ -516,4 +541,19 @@ public class DanaRStatsActivity extends Activity {
|
|||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public static boolean isOldData(List<TDD> historyList) {
|
||||
Object activePump = MainApp.getConfigBuilder().getActivePump();
|
||||
PumpInterface dana = MainApp.getSpecificPlugin(DanaRPlugin.class);
|
||||
PumpInterface danaRS = MainApp.getSpecificPlugin(DanaRSPlugin.class);
|
||||
PumpInterface danaV2 = MainApp.getSpecificPlugin(DanaRv2Plugin.class);
|
||||
PumpInterface danaKorean = MainApp.getSpecificPlugin(DanaRKoreanPlugin.class);
|
||||
PumpInterface insight = MainApp.getSpecificPlugin(InsightPlugin.class);
|
||||
|
||||
boolean startsYesterday = activePump == dana || activePump == danaRS || activePump == danaV2 || activePump == danaKorean || activePump == insight;
|
||||
|
||||
DateFormat df = new SimpleDateFormat("dd.MM.");
|
||||
return (historyList.size() < 3 || !(df.format(new Date(historyList.get(0).date)).equals(df.format(new Date(System.currentTimeMillis() - (startsYesterday?1000 * 60 * 60 * 24:0))))));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,198 @@
|
|||
package info.nightscout.androidaps.data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import info.nightscout.androidaps.Constants;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.interfaces.BgSourceInterface;
|
||||
import info.nightscout.androidaps.interfaces.Constraint;
|
||||
import info.nightscout.androidaps.interfaces.ConstraintsInterface;
|
||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||
import info.nightscout.androidaps.interfaces.PluginType;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||
|
||||
/**
|
||||
* Created by mike on 19.03.2018.
|
||||
*/
|
||||
|
||||
public class ConstraintChecker implements ConstraintsInterface {
|
||||
|
||||
private MainApp mainApp;
|
||||
|
||||
public ConstraintChecker(MainApp mainApp) {
|
||||
this.mainApp = mainApp;
|
||||
}
|
||||
|
||||
|
||||
public Constraint<Boolean> isLoopInvokationAllowed() {
|
||||
return isLoopInvokationAllowed(new Constraint<>(true));
|
||||
}
|
||||
|
||||
public Constraint<Boolean> isClosedLoopAllowed() {
|
||||
return isClosedLoopAllowed(new Constraint<>(true));
|
||||
}
|
||||
|
||||
public Constraint<Boolean> isAutosensModeEnabled() {
|
||||
return isAutosensModeEnabled(new Constraint<>(true));
|
||||
}
|
||||
|
||||
public Constraint<Boolean> isAMAModeEnabled() {
|
||||
return isAMAModeEnabled(new Constraint<>(true));
|
||||
}
|
||||
|
||||
public Constraint<Boolean> isSMBModeEnabled() {
|
||||
return isSMBModeEnabled(new Constraint<>(true));
|
||||
}
|
||||
|
||||
public Constraint<Boolean> isAdvancedFilteringEnabled() {
|
||||
return isAdvancedFilteringEnabled(new Constraint<>(true));
|
||||
}
|
||||
|
||||
public Constraint<Double> getMaxBasalAllowed(Profile profile) {
|
||||
return applyBasalConstraints(new Constraint<>(Constants.REALLYHIGHBASALRATE), profile);
|
||||
}
|
||||
|
||||
public Constraint<Integer> getMaxBasalPercentAllowed(Profile profile) {
|
||||
return applyBasalPercentConstraints(new Constraint<>(Constants.REALLYHIGHPERCENTBASALRATE), profile);
|
||||
}
|
||||
|
||||
public Constraint<Double> getMaxBolusAllowed() {
|
||||
return applyBolusConstraints(new Constraint<>(Constants.REALLYHIGHBOLUS));
|
||||
}
|
||||
|
||||
public Constraint<Integer> getMaxCarbsAllowed() {
|
||||
return applyCarbsConstraints(new Constraint<>(Constants.REALLYHIGHCARBS));
|
||||
}
|
||||
|
||||
public Constraint<Double> getMaxIOBAllowed() {
|
||||
return applyMaxIOBConstraints(new Constraint<>(Constants.REALLYHIGHIOB));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Constraint<Boolean> isLoopInvokationAllowed(Constraint<Boolean> value) {
|
||||
|
||||
ArrayList<PluginBase> constraintsPlugins = mainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
|
||||
for (PluginBase p : constraintsPlugins) {
|
||||
ConstraintsInterface constraint = (ConstraintsInterface) p;
|
||||
if (!p.isEnabled(PluginType.CONSTRAINTS)) continue;
|
||||
constraint.isLoopInvokationAllowed(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Constraint<Boolean> isClosedLoopAllowed(Constraint<Boolean> value) {
|
||||
|
||||
ArrayList<PluginBase> constraintsPlugins = mainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
|
||||
for (PluginBase p : constraintsPlugins) {
|
||||
ConstraintsInterface constraint = (ConstraintsInterface) p;
|
||||
if (!p.isEnabled(PluginType.CONSTRAINTS)) continue;
|
||||
constraint.isClosedLoopAllowed(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Constraint<Boolean> isAutosensModeEnabled(Constraint<Boolean> value) {
|
||||
|
||||
ArrayList<PluginBase> constraintsPlugins = mainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
|
||||
for (PluginBase p : constraintsPlugins) {
|
||||
ConstraintsInterface constraint = (ConstraintsInterface) p;
|
||||
if (!p.isEnabled(PluginType.CONSTRAINTS)) continue;
|
||||
constraint.isAutosensModeEnabled(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Constraint<Boolean> isAMAModeEnabled(Constraint<Boolean> value) {
|
||||
|
||||
ArrayList<PluginBase> constraintsPlugins = mainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
|
||||
for (PluginBase p : constraintsPlugins) {
|
||||
ConstraintsInterface constrain = (ConstraintsInterface) p;
|
||||
if (!p.isEnabled(PluginType.CONSTRAINTS)) continue;
|
||||
constrain.isAMAModeEnabled(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Constraint<Boolean> isSMBModeEnabled(Constraint<Boolean> value) {
|
||||
|
||||
ArrayList<PluginBase> constraintsPlugins = mainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
|
||||
for (PluginBase p : constraintsPlugins) {
|
||||
ConstraintsInterface constraint = (ConstraintsInterface) p;
|
||||
if (!p.isEnabled(PluginType.CONSTRAINTS)) continue;
|
||||
constraint.isSMBModeEnabled(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Constraint<Boolean> isAdvancedFilteringEnabled(Constraint<Boolean> value) {
|
||||
ArrayList<PluginBase> constraintsPlugins = mainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
|
||||
for (PluginBase p : constraintsPlugins) {
|
||||
ConstraintsInterface constraint = (ConstraintsInterface) p;
|
||||
if (!p.isEnabled(PluginType.CONSTRAINTS)) continue;
|
||||
constraint.isAdvancedFilteringEnabled(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Constraint<Double> applyBasalConstraints(Constraint<Double> absoluteRate, Profile profile) {
|
||||
ArrayList<PluginBase> constraintsPlugins = mainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
|
||||
for (PluginBase p : constraintsPlugins) {
|
||||
ConstraintsInterface constraint = (ConstraintsInterface) p;
|
||||
if (!p.isEnabled(PluginType.CONSTRAINTS)) continue;
|
||||
constraint.applyBasalConstraints(absoluteRate, profile);
|
||||
}
|
||||
return absoluteRate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Constraint<Integer> applyBasalPercentConstraints(Constraint<Integer> percentRate, Profile profile) {
|
||||
ArrayList<PluginBase> constraintsPlugins = mainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
|
||||
for (PluginBase p : constraintsPlugins) {
|
||||
ConstraintsInterface constrain = (ConstraintsInterface) p;
|
||||
if (!p.isEnabled(PluginType.CONSTRAINTS)) continue;
|
||||
constrain.applyBasalPercentConstraints(percentRate, profile);
|
||||
}
|
||||
return percentRate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Constraint<Double> applyBolusConstraints(Constraint<Double> insulin) {
|
||||
ArrayList<PluginBase> constraintsPlugins = mainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
|
||||
for (PluginBase p : constraintsPlugins) {
|
||||
ConstraintsInterface constrain = (ConstraintsInterface) p;
|
||||
if (!p.isEnabled(PluginType.CONSTRAINTS)) continue;
|
||||
constrain.applyBolusConstraints(insulin);
|
||||
}
|
||||
return insulin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Constraint<Integer> applyCarbsConstraints(Constraint<Integer> carbs) {
|
||||
ArrayList<PluginBase> constraintsPlugins = mainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
|
||||
for (PluginBase p : constraintsPlugins) {
|
||||
ConstraintsInterface constrain = (ConstraintsInterface) p;
|
||||
if (!p.isEnabled(PluginType.CONSTRAINTS)) continue;
|
||||
constrain.applyCarbsConstraints(carbs);
|
||||
}
|
||||
return carbs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Constraint<Double> applyMaxIOBConstraints(Constraint<Double> maxIob) {
|
||||
ArrayList<PluginBase> constraintsPlugins = mainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
|
||||
for (PluginBase p : constraintsPlugins) {
|
||||
ConstraintsInterface constrain = (ConstraintsInterface) p;
|
||||
if (!p.isEnabled(PluginType.CONSTRAINTS)) continue;
|
||||
constrain.applyMaxIOBConstraints(maxIob);
|
||||
}
|
||||
return maxIob;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -2,14 +2,14 @@ package info.nightscout.androidaps.data;
|
|||
|
||||
import android.content.Context;
|
||||
|
||||
import com.rits.cloning.Cloner;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.db.CareportalEvent;
|
||||
import info.nightscout.androidaps.db.Source;
|
||||
import info.nightscout.androidaps.interfaces.InsulinInterface;
|
||||
|
||||
/**
|
||||
* Created by mike on 29.05.2017.
|
||||
|
@ -29,6 +29,28 @@ public class DetailedBolusInfo {
|
|||
public Context context = null; // context for progress dialog
|
||||
public long pumpId = 0; // id of record if comming from pump history (not a newly created treatment)
|
||||
public boolean isSMB = false; // is a Super-MicroBolus
|
||||
public long deliverAt = 0; // SMB should be delivered within 1 min from this time
|
||||
public String notes = null;
|
||||
|
||||
public DetailedBolusInfo copy() {
|
||||
DetailedBolusInfo n = new DetailedBolusInfo();
|
||||
n.date = date;
|
||||
n.eventType = eventType;
|
||||
n.insulin = insulin;
|
||||
n.carbs = carbs;
|
||||
n.source = source;
|
||||
n.isValid = isValid;
|
||||
n.glucose = glucose;
|
||||
n.glucoseType = glucoseType;
|
||||
n.carbTime = carbTime;
|
||||
n.boluscalc = boluscalc;
|
||||
n.context = context;
|
||||
n.pumpId = pumpId;
|
||||
n.isSMB = isSMB;
|
||||
n.deliverAt = deliverAt;
|
||||
n.notes = notes;
|
||||
return n;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
|
@ -37,6 +59,7 @@ public class DetailedBolusInfo {
|
|||
" carbs: " + carbs +
|
||||
" isValid: " + isValid +
|
||||
" carbTime: " + carbTime +
|
||||
" isSMB: " + isSMB;
|
||||
" isSMB: " + isSMB +
|
||||
" deliverAt: " + new Date(deliverAt).toLocaleString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ import java.util.List;
|
|||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.db.BgReading;
|
||||
import info.nightscout.utils.DateUtil;
|
||||
import info.nightscout.utils.DecimalFormatter;
|
||||
import info.nightscout.utils.Round;
|
||||
|
||||
|
@ -35,21 +36,15 @@ public class GlucoseStatus {
|
|||
public double avgdelta = 0d;
|
||||
public double short_avgdelta = 0d;
|
||||
public double long_avgdelta = 0d;
|
||||
public long date = 0L;
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return MainApp.sResources.getString(R.string.glucose) + " " + DecimalFormatter.to0Decimal(glucose) + " mg/dl\n" +
|
||||
MainApp.sResources.getString(R.string.delta) + " " + DecimalFormatter.to0Decimal(delta) + " mg/dl\n" +
|
||||
MainApp.sResources.getString(R.string.short_avgdelta) + " " + DecimalFormatter.to2Decimal(short_avgdelta) + " mg/dl\n" +
|
||||
MainApp.sResources.getString(R.string.long_avgdelta) + " " + DecimalFormatter.to2Decimal(long_avgdelta) + " mg/dl";
|
||||
}
|
||||
|
||||
public Spanned toSpanned() {
|
||||
return Html.fromHtml("<b>" + MainApp.sResources.getString(R.string.glucose) + "</b>: " + DecimalFormatter.to0Decimal(glucose) + " mg/dl<br>" +
|
||||
"<b>" + MainApp.sResources.getString(R.string.delta) + "</b>: " + DecimalFormatter.to0Decimal(delta) + " mg/dl<br>" +
|
||||
"<b>" + MainApp.sResources.getString(R.string.short_avgdelta) + "</b>: " + DecimalFormatter.to2Decimal(short_avgdelta) + " mg/dl<br>" +
|
||||
"<b>" + MainApp.sResources.getString(R.string.long_avgdelta) + "</b>: " + DecimalFormatter.to2Decimal(long_avgdelta) + " mg/dl");
|
||||
return MainApp.gs(R.string.glucose) + " " + DecimalFormatter.to0Decimal(glucose) + " mg/dl\n" +
|
||||
MainApp.gs(R.string.delta) + " " + DecimalFormatter.to0Decimal(delta) + " mg/dl\n" +
|
||||
MainApp.gs(R.string.short_avgdelta) + " " + DecimalFormatter.to2Decimal(short_avgdelta) + " mg/dl\n" +
|
||||
MainApp.gs(R.string.long_avgdelta) + " " + DecimalFormatter.to2Decimal(long_avgdelta) + " mg/dl";
|
||||
}
|
||||
|
||||
public GlucoseStatus() {
|
||||
|
@ -74,11 +69,15 @@ public class GlucoseStatus {
|
|||
@Nullable
|
||||
public static GlucoseStatus getGlucoseStatusData(boolean allowOldData) {
|
||||
// load 45min
|
||||
long fromtime = (long) (System.currentTimeMillis() - 60 * 1000L * 45);
|
||||
long fromtime = DateUtil.now() - 60 * 1000L * 45;
|
||||
List<BgReading> data = MainApp.getDbHelper().getBgreadingsDataFromTime(fromtime, false);
|
||||
|
||||
int sizeRecords = data.size();
|
||||
if (sizeRecords < 1 || (data.get(0).date < System.currentTimeMillis() - 7 * 60 * 1000L && !allowOldData)) {
|
||||
if (sizeRecords == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (data.get(0).date < DateUtil.now() - 7 * 60 * 1000L && !allowOldData) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -86,13 +85,14 @@ public class GlucoseStatus {
|
|||
long now_date = now.date;
|
||||
double change;
|
||||
|
||||
if (sizeRecords < 2) {
|
||||
if (sizeRecords == 1) {
|
||||
GlucoseStatus status = new GlucoseStatus();
|
||||
status.glucose = now.value;
|
||||
status.short_avgdelta = 0d;
|
||||
status.delta = 0d;
|
||||
status.long_avgdelta = 0d;
|
||||
status.avgdelta = 0d; // for OpenAPS MA
|
||||
status.date = now_date;
|
||||
return status.round();
|
||||
}
|
||||
|
||||
|
@ -133,6 +133,7 @@ public class GlucoseStatus {
|
|||
|
||||
GlucoseStatus status = new GlucoseStatus();
|
||||
status.glucose = now.value;
|
||||
status.date = now_date;
|
||||
|
||||
status.short_avgdelta = average(short_deltas);
|
||||
|
||||
|
|
|
@ -16,7 +16,11 @@ import info.nightscout.androidaps.interfaces.Interval;
|
|||
|
||||
public abstract class Intervals<T extends Interval> {
|
||||
|
||||
LongSparseArray<T> rawData = new LongSparseArray<T>(); // oldest at index 0
|
||||
LongSparseArray<T> rawData; // oldest at index 0
|
||||
|
||||
public Intervals() {
|
||||
rawData = new LongSparseArray<T>();
|
||||
}
|
||||
|
||||
public synchronized Intervals reset() {
|
||||
rawData = new LongSparseArray<T>();
|
||||
|
@ -27,8 +31,7 @@ public abstract class Intervals<T extends Interval> {
|
|||
|
||||
/**
|
||||
* The List must be sorted by `T.start()` in ascending order
|
||||
*
|
||||
* */
|
||||
*/
|
||||
public synchronized void add(List<T> list) {
|
||||
for (T interval : list) {
|
||||
rawData.put(interval.start(), interval);
|
||||
|
@ -36,6 +39,10 @@ public abstract class Intervals<T extends Interval> {
|
|||
merge();
|
||||
}
|
||||
|
||||
public synchronized void add(T interval) {
|
||||
rawData.put(interval.start(), interval);
|
||||
merge();
|
||||
}
|
||||
|
||||
|
||||
public synchronized List<T> getList() {
|
||||
|
@ -47,7 +54,7 @@ public abstract class Intervals<T extends Interval> {
|
|||
|
||||
public synchronized List<T> getReversedList() {
|
||||
List<T> list = new ArrayList<>();
|
||||
for (int i = rawData.size() -1; i>=0; i--)
|
||||
for (int i = rawData.size() - 1; i >= 0; i--)
|
||||
list.add(rawData.valueAt(i));
|
||||
return list;
|
||||
}
|
||||
|
@ -86,5 +93,4 @@ public abstract class Intervals<T extends Interval> {
|
|||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -7,6 +7,16 @@ public class Iob {
|
|||
public double iobContrib = 0d;
|
||||
public double activityContrib = 0d;
|
||||
|
||||
public Iob iobContrib(double iobContrib) {
|
||||
this.iobContrib = iobContrib;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Iob activityContrib(double activityContrib) {
|
||||
this.activityContrib = activityContrib;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Iob plus(Iob iob) {
|
||||
iobContrib += iob.iobContrib;
|
||||
activityContrib += iob.activityContrib;
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package info.nightscout.androidaps.data;
|
||||
|
||||
import com.rits.cloning.Cloner;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -21,8 +23,8 @@ public class IobTotal {
|
|||
public double hightempinsulin;
|
||||
|
||||
// oref1
|
||||
public double microBolusInsulin;
|
||||
public double microBolusIOB;
|
||||
public long lastBolusTime;
|
||||
public IobTotal iobWithZeroTemp;
|
||||
|
||||
public double netInsulin = 0d; // for calculations from temp basals only
|
||||
public double netRatio = 0d; // net ratio at start of temp basal
|
||||
|
@ -31,6 +33,12 @@ public class IobTotal {
|
|||
|
||||
long time;
|
||||
|
||||
|
||||
public IobTotal copy() {
|
||||
Cloner cloner = new Cloner();
|
||||
return cloner.deepClone(this);
|
||||
}
|
||||
|
||||
public IobTotal(long time) {
|
||||
this.iob = 0d;
|
||||
this.activity = 0d;
|
||||
|
@ -38,8 +46,7 @@ public class IobTotal {
|
|||
this.basaliob = 0d;
|
||||
this.netbasalinsulin = 0d;
|
||||
this.hightempinsulin = 0d;
|
||||
this.microBolusInsulin = 0d;
|
||||
this.microBolusIOB = 0d;
|
||||
this.lastBolusTime = 0;
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
|
@ -52,8 +59,6 @@ public class IobTotal {
|
|||
hightempinsulin += other.hightempinsulin;
|
||||
netInsulin += other.netInsulin;
|
||||
extendedBolusInsulin += other.extendedBolusInsulin;
|
||||
microBolusInsulin += other.microBolusInsulin;
|
||||
microBolusIOB += other.microBolusIOB;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -62,11 +67,13 @@ public class IobTotal {
|
|||
result.iob = bolusIOB.iob + basalIob.basaliob;
|
||||
result.activity = bolusIOB.activity + basalIob.activity;
|
||||
result.bolussnooze = bolusIOB.bolussnooze;
|
||||
result.basaliob = basalIob.basaliob;
|
||||
result.netbasalinsulin = basalIob.netbasalinsulin;
|
||||
result.hightempinsulin = basalIob.hightempinsulin;
|
||||
result.microBolusInsulin = bolusIOB.microBolusInsulin + basalIob.microBolusInsulin;
|
||||
result.microBolusIOB = bolusIOB.microBolusIOB + basalIob.microBolusIOB;
|
||||
result.basaliob = bolusIOB.basaliob + basalIob.basaliob;
|
||||
result.netbasalinsulin = bolusIOB.netbasalinsulin + basalIob.netbasalinsulin;
|
||||
result.hightempinsulin = basalIob.hightempinsulin + bolusIOB.hightempinsulin;
|
||||
result.netInsulin = basalIob.netInsulin + bolusIOB.netInsulin;
|
||||
result.extendedBolusInsulin = basalIob.extendedBolusInsulin + bolusIOB.extendedBolusInsulin;
|
||||
result.lastBolusTime = bolusIOB.lastBolusTime;
|
||||
result.iobWithZeroTemp = basalIob.iobWithZeroTemp;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -77,8 +84,8 @@ public class IobTotal {
|
|||
this.basaliob = Round.roundTo(this.basaliob, 0.001);
|
||||
this.netbasalinsulin = Round.roundTo(this.netbasalinsulin, 0.001);
|
||||
this.hightempinsulin = Round.roundTo(this.hightempinsulin, 0.001);
|
||||
this.microBolusInsulin = Round.roundTo(this.microBolusInsulin, 0.001);
|
||||
this.microBolusIOB = Round.roundTo(this.microBolusIOB, 0.001);
|
||||
this.netInsulin = Round.roundTo(this.netInsulin, 0.001);
|
||||
this.extendedBolusInsulin = Round.roundTo(this.extendedBolusInsulin, 0.001);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -102,7 +109,24 @@ public class IobTotal {
|
|||
json.put("basaliob", basaliob);
|
||||
json.put("bolussnooze", bolussnooze);
|
||||
json.put("activity", activity);
|
||||
json.put("lastBolusTime", lastBolusTime);
|
||||
json.put("time", DateUtil.toISOString(new Date(time)));
|
||||
/*
|
||||
|
||||
This is requested by SMB determine_basal but by based on Scott's info
|
||||
it's MDT specific safety check only
|
||||
It's causing rounding issues in determine_basal
|
||||
|
||||
JSONObject lastTemp = new JSONObject();
|
||||
lastTemp.put("date", lastTempDate);
|
||||
lastTemp.put("rate", lastTempRate);
|
||||
lastTemp.put("duration", lastTempDuration);
|
||||
json.put("lastTemp", lastTemp);
|
||||
*/
|
||||
if (iobWithZeroTemp != null) {
|
||||
JSONObject iwzt = iobWithZeroTemp.determineBasalJson();
|
||||
json.put("iobWithZeroTemp", iwzt);
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
|
|
|
@ -7,4 +7,9 @@ public class MealData {
|
|||
public double boluses = 0d;
|
||||
public double carbs = 0d;
|
||||
public double mealCOB = 0.0d;
|
||||
public double slopeFromMaxDeviation = 0;
|
||||
public double slopeFromMinDeviation = 999;
|
||||
public long lastBolusTime;
|
||||
public long lastCarbTime = 0L;
|
||||
public double usedMinCarbsImpact = 0d;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,9 @@ package info.nightscout.androidaps.data;
|
|||
|
||||
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.util.LongSparseArray;
|
||||
|
||||
import info.nightscout.androidaps.db.TemporaryBasal;
|
||||
import info.nightscout.androidaps.interfaces.Interval;
|
||||
|
||||
/**
|
||||
|
@ -11,6 +13,14 @@ import info.nightscout.androidaps.interfaces.Interval;
|
|||
|
||||
public class NonOverlappingIntervals<T extends Interval> extends Intervals<T> {
|
||||
|
||||
public NonOverlappingIntervals() {
|
||||
super();
|
||||
}
|
||||
|
||||
public NonOverlappingIntervals (Intervals<T> other) {
|
||||
rawData = other.rawData.clone();
|
||||
}
|
||||
|
||||
protected synchronized void merge() {
|
||||
for (int index = 0; index < rawData.size() - 1; index++) {
|
||||
Interval i = rawData.valueAt(index);
|
||||
|
@ -27,4 +37,5 @@ public class NonOverlappingIntervals<T extends Interval> extends Intervals<T> {
|
|||
if (index >= 0) return rawData.valueAt(index);
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -11,18 +11,26 @@ import info.nightscout.androidaps.interfaces.Interval;
|
|||
|
||||
public class OverlappingIntervals<T extends Interval> extends Intervals<T> {
|
||||
|
||||
public OverlappingIntervals() {
|
||||
super();
|
||||
}
|
||||
|
||||
public OverlappingIntervals(Intervals<T> other) {
|
||||
rawData = other.rawData.clone();
|
||||
}
|
||||
|
||||
protected synchronized void merge() {
|
||||
boolean needToCut = false;
|
||||
long cutTime = 0;
|
||||
|
||||
for (int index = rawData.size()-1; index >= 0; index--) { //begin with newest
|
||||
for (int index = rawData.size() - 1; index >= 0; index--) { //begin with newest
|
||||
Interval cur = rawData.valueAt(index);
|
||||
if (cur.isEndingEvent()){
|
||||
if (cur.isEndingEvent()) {
|
||||
needToCut = true;
|
||||
cutTime = cur.start();
|
||||
} else {
|
||||
//event that is no EndingEvent might need to be stopped by an ending event
|
||||
if(needToCut&&cur.end() > cutTime){
|
||||
if (needToCut && cur.end() > cutTime) {
|
||||
cur.cutEndTo(cutTime);
|
||||
}
|
||||
}
|
||||
|
@ -31,9 +39,9 @@ public class OverlappingIntervals<T extends Interval> extends Intervals<T> {
|
|||
|
||||
@Nullable
|
||||
public synchronized T getValueByInterval(long time) {
|
||||
for (int index = rawData.size()-1; index >= 0; index--) { //begin with newest
|
||||
for (int index = rawData.size() - 1; index >= 0; index--) { //begin with newest
|
||||
T cur = rawData.valueAt(index);
|
||||
if (cur.match(time)){
|
||||
if (cur.match(time)) {
|
||||
return cur;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,8 +2,6 @@ package info.nightscout.androidaps.data;
|
|||
|
||||
import android.support.v4.util.LongSparseArray;
|
||||
|
||||
import com.crashlytics.android.Crashlytics;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
@ -14,56 +12,76 @@ import java.text.DecimalFormat;
|
|||
import java.util.Calendar;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.Constants;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.interfaces.PumpDescription;
|
||||
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
|
||||
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
|
||||
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
|
||||
import info.nightscout.utils.DateUtil;
|
||||
import info.nightscout.utils.DecimalFormatter;
|
||||
import info.nightscout.utils.ToastUtils;
|
||||
import info.nightscout.utils.FabricPrivacy;
|
||||
|
||||
public class Profile {
|
||||
private static Logger log = LoggerFactory.getLogger(Profile.class);
|
||||
|
||||
private JSONObject json;
|
||||
private String units = null;
|
||||
private double dia = Constants.defaultDIA;
|
||||
private TimeZone timeZone = TimeZone.getDefault();
|
||||
private String units;
|
||||
private double dia;
|
||||
private TimeZone timeZone;
|
||||
private JSONArray isf;
|
||||
private LongSparseArray<Double> isf_v = null; // oldest at index 0
|
||||
private LongSparseArray<Double> isf_v; // oldest at index 0
|
||||
private JSONArray ic;
|
||||
private LongSparseArray<Double> ic_v = null; // oldest at index 0
|
||||
private LongSparseArray<Double> ic_v; // oldest at index 0
|
||||
private JSONArray basal;
|
||||
private LongSparseArray<Double> basal_v = null; // oldest at index 0
|
||||
private LongSparseArray<Double> basal_v; // oldest at index 0
|
||||
private JSONArray targetLow;
|
||||
private LongSparseArray<Double> targetLow_v = null; // oldest at index 0
|
||||
private LongSparseArray<Double> targetLow_v; // oldest at index 0
|
||||
private JSONArray targetHigh;
|
||||
private LongSparseArray<Double> targetHigh_v = null; // oldest at index 0
|
||||
private LongSparseArray<Double> targetHigh_v; // oldest at index 0
|
||||
|
||||
private int percentage = 100;
|
||||
private int timeshift = 0;
|
||||
private int percentage;
|
||||
private int timeshift;
|
||||
|
||||
private boolean isValid = true;
|
||||
private boolean isValidated = false;
|
||||
protected boolean isValid;
|
||||
protected boolean isValidated;
|
||||
|
||||
// Default constructor for tests
|
||||
protected Profile() {
|
||||
}
|
||||
|
||||
// Constructor from profileStore JSON
|
||||
public Profile(JSONObject json, String units) {
|
||||
this(json, 100, 0);
|
||||
init(json, 100, 0);
|
||||
if (this.units == null) {
|
||||
if (units != null)
|
||||
this.units = units;
|
||||
else {
|
||||
Crashlytics.log("Profile failover failed too");
|
||||
FabricPrivacy.log("Profile failover failed too");
|
||||
this.units = Constants.MGDL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Profile(JSONObject json, int percentage, int timeshift) {
|
||||
init(json, percentage, timeshift);
|
||||
}
|
||||
|
||||
protected void init(JSONObject json, int percentage, int timeshift) {
|
||||
units = null;
|
||||
dia = Constants.defaultDIA;
|
||||
timeZone = TimeZone.getDefault();
|
||||
isf_v = null;
|
||||
ic_v = null;
|
||||
basal_v = null;
|
||||
targetLow_v = null;
|
||||
targetHigh_v = null;
|
||||
|
||||
isValid = true;
|
||||
isValidated = false;
|
||||
|
||||
this.percentage = percentage;
|
||||
this.timeshift = timeshift;
|
||||
this.json = json;
|
||||
|
@ -77,53 +95,12 @@ public class Profile {
|
|||
if (json.has("timezone"))
|
||||
timeZone = TimeZone.getTimeZone(json.getString("timezone"));
|
||||
isf = json.getJSONArray("sens");
|
||||
if (getIsf(0) == null) {
|
||||
int defaultISF = units.equals(Constants.MGDL) ? 400 : 20;
|
||||
isf = new JSONArray("[{\"time\":\"00:00\",\"value\":\"" + defaultISF + "\",\"timeAsSeconds\":\"0\"}]");
|
||||
Notification noisf = new Notification(Notification.ISF_MISSING, MainApp.sResources.getString(R.string.isfmissing), Notification.URGENT);
|
||||
MainApp.bus().post(new EventNewNotification(noisf));
|
||||
} else {
|
||||
MainApp.bus().post(new EventDismissNotification(Notification.ISF_MISSING));
|
||||
}
|
||||
ic = json.getJSONArray("carbratio");
|
||||
if (getIc(0) == null) {
|
||||
int defaultIC = 25;
|
||||
ic = new JSONArray("[{\"time\":\"00:00\",\"value\":\"" + defaultIC + "\",\"timeAsSeconds\":\"0\"}]");
|
||||
Notification noic = new Notification(Notification.IC_MISSING, MainApp.sResources.getString(R.string.icmissing), Notification.URGENT);
|
||||
MainApp.bus().post(new EventNewNotification(noic));
|
||||
} else {
|
||||
MainApp.bus().post(new EventDismissNotification(Notification.IC_MISSING));
|
||||
}
|
||||
basal = json.getJSONArray("basal");
|
||||
if (getBasal(0) == null) {
|
||||
double defaultBasal = 0.1d;
|
||||
basal = new JSONArray("[{\"time\":\"00:00\",\"value\":\"" + defaultBasal + "\",\"timeAsSeconds\":\"0\"}]");
|
||||
Notification nobasal = new Notification(Notification.BASAL_MISSING, MainApp.sResources.getString(R.string.basalmissing), Notification.URGENT);
|
||||
MainApp.bus().post(new EventNewNotification(nobasal));
|
||||
} else {
|
||||
MainApp.bus().post(new EventDismissNotification(Notification.BASAL_MISSING));
|
||||
}
|
||||
targetLow = json.getJSONArray("target_low");
|
||||
if (getTargetLow(0) == null) {
|
||||
double defaultLow = units.equals(Constants.MGDL) ? 120 : 6;
|
||||
targetLow = new JSONArray("[{\"time\":\"00:00\",\"value\":\"" + defaultLow + "\",\"timeAsSeconds\":\"0\"}]");
|
||||
Notification notarget = new Notification(Notification.TARGET_MISSING, MainApp.sResources.getString(R.string.targetmissing), Notification.URGENT);
|
||||
MainApp.bus().post(new EventNewNotification(notarget));
|
||||
} else {
|
||||
MainApp.bus().post(new EventDismissNotification(Notification.TARGET_MISSING));
|
||||
}
|
||||
targetHigh = json.getJSONArray("target_high");
|
||||
if (getTargetHigh(0) == null) {
|
||||
double defaultHigh = units.equals(Constants.MGDL) ? 160 : 8;
|
||||
targetHigh = new JSONArray("[{\"time\":\"00:00\",\"value\":\"" + defaultHigh + "\",\"timeAsSeconds\":\"0\"}]");
|
||||
Notification notarget = new Notification(Notification.TARGET_MISSING, MainApp.sResources.getString(R.string.targetmissing), Notification.URGENT);
|
||||
MainApp.bus().post(new EventNewNotification(notarget));
|
||||
} else {
|
||||
MainApp.bus().post(new EventDismissNotification(Notification.TARGET_MISSING));
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.invalidprofile));
|
||||
isValid = false;
|
||||
isValidated = true;
|
||||
}
|
||||
|
@ -132,7 +109,7 @@ public class Profile {
|
|||
public String log() {
|
||||
String ret = "\n";
|
||||
for (Integer hour = 0; hour < 24; hour++) {
|
||||
double value = getBasal((Integer) (hour * 60 * 60));
|
||||
double value = getBasalTimeFromMidnight((Integer) (hour * 60 * 60));
|
||||
ret += "NS basal value for " + hour + ":00 is " + value + "\n";
|
||||
}
|
||||
ret += "NS units: " + getUnits();
|
||||
|
@ -154,6 +131,10 @@ public class Profile {
|
|||
}
|
||||
|
||||
// mmol or mg/dl
|
||||
public void setUnits(String units) {
|
||||
this.units = units;
|
||||
}
|
||||
|
||||
public String getUnits() {
|
||||
return units;
|
||||
}
|
||||
|
@ -163,6 +144,11 @@ public class Profile {
|
|||
}
|
||||
|
||||
private LongSparseArray<Double> convertToSparseArray(JSONArray array) {
|
||||
if (array == null) {
|
||||
isValid = false;
|
||||
return new LongSparseArray<>();
|
||||
}
|
||||
|
||||
double multiplier = getMultiplier(array);
|
||||
|
||||
LongSparseArray<Double> sparse = new LongSparseArray<>();
|
||||
|
@ -217,22 +203,24 @@ public class Profile {
|
|||
|
||||
if (isValid) {
|
||||
// Check for hours alignment
|
||||
for (int index = 0; index < basal_v.size(); index++) {
|
||||
long secondsFromMidnight = basal_v.keyAt(index);
|
||||
if (secondsFromMidnight % 3600 != 0) {
|
||||
Notification notification = new Notification(Notification.BASAL_PROFILE_NOT_ALIGNED_TO_HOURS, String.format(MainApp.gs(R.string.basalprofilenotaligned), from), Notification.NORMAL);
|
||||
MainApp.bus().post(new EventNewNotification(notification));
|
||||
PumpInterface pump = MainApp.getConfigBuilder().getActivePump();
|
||||
if (pump != null && !pump.getPumpDescription().is30minBasalRatesCapable) {
|
||||
for (int index = 0; index < basal_v.size(); index++) {
|
||||
long secondsFromMidnight = basal_v.keyAt(index);
|
||||
if (secondsFromMidnight % 3600 != 0) {
|
||||
Notification notification = new Notification(Notification.BASAL_PROFILE_NOT_ALIGNED_TO_HOURS, String.format(MainApp.gs(R.string.basalprofilenotaligned), from), Notification.NORMAL);
|
||||
MainApp.bus().post(new EventNewNotification(notification));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check for minimal basal value
|
||||
PumpInterface pump = ConfigBuilderPlugin.getActivePump();
|
||||
if (pump != null) {
|
||||
PumpDescription description = pump.getPumpDescription();
|
||||
for (int i = 0; i < basal_v.size(); i++) {
|
||||
if (basal_v.valueAt(i) < description.basalMinimumRate) {
|
||||
basal_v.setValueAt(i, description.basalMinimumRate);
|
||||
MainApp.bus().post(new EventNewNotification(new Notification(Notification.MINIMAL_BASAL_VALUE_REPLACED, String.format(MainApp.gs(R.string.minimalbasalvaluereplaced), from), Notification.NORMAL)));
|
||||
sendBelowMinimumNotification(from);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -246,6 +234,10 @@ public class Profile {
|
|||
return isValid;
|
||||
}
|
||||
|
||||
protected void sendBelowMinimumNotification(String from) {
|
||||
MainApp.bus().post(new EventNewNotification(new Notification(Notification.MINIMAL_BASAL_VALUE_REPLACED, String.format(MainApp.gs(R.string.minimalbasalvaluereplaced), from), Notification.NORMAL)));
|
||||
}
|
||||
|
||||
private void validate(LongSparseArray array) {
|
||||
if (array.size() == 0) {
|
||||
isValid = false;
|
||||
|
@ -259,6 +251,7 @@ public class Profile {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
private Double getValueToTime(JSONArray array, Integer timeAsSeconds) {
|
||||
Double lastValue = null;
|
||||
|
||||
|
@ -278,11 +271,12 @@ public class Profile {
|
|||
}
|
||||
return lastValue;
|
||||
}
|
||||
*/
|
||||
|
||||
Integer getShitfTimeSecs(Integer originalTime) {
|
||||
Integer shiftedTime = originalTime + timeshift * 60 * 60;
|
||||
shiftedTime = (shiftedTime + 24 * 60 * 60) % (24 * 60 * 60);
|
||||
if (timeshift != 0)
|
||||
if (timeshift != 0 && Config.logProfile)
|
||||
log.debug("(Sec) Original time: " + originalTime + " ShiftedTime: " + shiftedTime);
|
||||
return shiftedTime;
|
||||
}
|
||||
|
@ -319,7 +313,7 @@ public class Profile {
|
|||
return multiplier;
|
||||
}
|
||||
|
||||
private Double getValueToTime(LongSparseArray<Double> array, Integer timeAsSeconds) {
|
||||
private double getValueToTime(LongSparseArray<Double> array, Integer timeAsSeconds) {
|
||||
Double lastValue = null;
|
||||
|
||||
for (Integer index = 0; index < array.size(); index++) {
|
||||
|
@ -334,7 +328,7 @@ public class Profile {
|
|||
return lastValue;
|
||||
}
|
||||
|
||||
private String format_HH_MM(Integer timeAsSeconds) {
|
||||
protected String format_HH_MM(Integer timeAsSeconds) {
|
||||
String time;
|
||||
int hour = timeAsSeconds / 60 / 60;
|
||||
int minutes = (timeAsSeconds - hour * 60 * 60) / 60;
|
||||
|
@ -361,51 +355,55 @@ public class Profile {
|
|||
return retValue;
|
||||
}
|
||||
|
||||
public Double getIsf() {
|
||||
return getIsf(secondsFromMidnight(System.currentTimeMillis()));
|
||||
public double getIsf() {
|
||||
return getIsfTimeFromMidnight(secondsFromMidnight(System.currentTimeMillis()));
|
||||
}
|
||||
|
||||
public Double getIsf(long time) {
|
||||
return getIsf(secondsFromMidnight(time));
|
||||
public double getIsf(long time) {
|
||||
return getIsfTimeFromMidnight(secondsFromMidnight(time));
|
||||
}
|
||||
|
||||
public Double getIsf(Integer timeAsSeconds) {
|
||||
double getIsfTimeFromMidnight(int timeAsSeconds) {
|
||||
if (isf_v == null)
|
||||
isf_v = convertToSparseArray(isf);
|
||||
return getValueToTime(isf_v, timeAsSeconds);
|
||||
}
|
||||
|
||||
public String getIsfList() {
|
||||
if (isf_v == null)
|
||||
isf_v = convertToSparseArray(isf);
|
||||
return getValuesList(isf_v, null, new DecimalFormat("0.0"), getUnits() + "/U");
|
||||
}
|
||||
|
||||
public Double getIc() {
|
||||
return getIc(secondsFromMidnight(System.currentTimeMillis()));
|
||||
public double getIc() {
|
||||
return getIcTimeFromMidnight(secondsFromMidnight(System.currentTimeMillis()));
|
||||
}
|
||||
|
||||
public Double getIc(long time) {
|
||||
return getIc(secondsFromMidnight(time));
|
||||
public double getIc(long time) {
|
||||
return getIcTimeFromMidnight(secondsFromMidnight(time));
|
||||
}
|
||||
|
||||
public Double getIc(Integer timeAsSeconds) {
|
||||
public double getIcTimeFromMidnight(int timeAsSeconds) {
|
||||
if (ic_v == null)
|
||||
ic_v = convertToSparseArray(ic);
|
||||
return getValueToTime(ic_v, timeAsSeconds);
|
||||
}
|
||||
|
||||
public String getIcList() {
|
||||
return getValuesList(ic_v, null, new DecimalFormat("0.0"), " g/U");
|
||||
if (ic_v == null)
|
||||
ic_v = convertToSparseArray(ic);
|
||||
return getValuesList(ic_v, null, new DecimalFormat("0.0"), "g/U");
|
||||
}
|
||||
|
||||
public Double getBasal() {
|
||||
return getBasal(secondsFromMidnight(System.currentTimeMillis()));
|
||||
public double getBasal() {
|
||||
return getBasalTimeFromMidnight(secondsFromMidnight(System.currentTimeMillis()));
|
||||
}
|
||||
|
||||
public Double getBasal(long time) {
|
||||
return getBasal(secondsFromMidnight(time));
|
||||
public double getBasal(long time) {
|
||||
return getBasalTimeFromMidnight(secondsFromMidnight(time));
|
||||
}
|
||||
|
||||
public synchronized Double getBasal(Integer timeAsSeconds) {
|
||||
public synchronized double getBasalTimeFromMidnight(int timeAsSeconds) {
|
||||
if (basal_v == null) {
|
||||
basal_v = convertToSparseArray(basal);
|
||||
}
|
||||
|
@ -413,17 +411,19 @@ public class Profile {
|
|||
}
|
||||
|
||||
public String getBasalList() {
|
||||
return getValuesList(basal_v, null, new DecimalFormat("0.00"), "U");
|
||||
if (basal_v == null)
|
||||
basal_v = convertToSparseArray(basal);
|
||||
return getValuesList(basal_v, null, new DecimalFormat("0.00"), "U/h");
|
||||
}
|
||||
|
||||
public class BasalValue {
|
||||
public BasalValue(Integer timeAsSeconds, Double value) {
|
||||
public BasalValue(int timeAsSeconds, double value) {
|
||||
this.timeAsSeconds = timeAsSeconds;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public Integer timeAsSeconds;
|
||||
public Double value;
|
||||
public int timeAsSeconds;
|
||||
public double value;
|
||||
}
|
||||
|
||||
public synchronized BasalValue[] getBasalValues() {
|
||||
|
@ -433,54 +433,66 @@ public class Profile {
|
|||
|
||||
for (Integer index = 0; index < basal_v.size(); 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);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public Double getTargetLow() {
|
||||
return getTargetLow(secondsFromMidnight(System.currentTimeMillis()));
|
||||
public double getTarget(){
|
||||
return getTarget(secondsFromMidnight(System.currentTimeMillis()));
|
||||
}
|
||||
|
||||
public Double getTargetLow(long time) {
|
||||
return getTargetLow(secondsFromMidnight(time));
|
||||
protected double getTarget(int timeAsSeconds) {
|
||||
return (getTargetLowTimeFromMidnight(timeAsSeconds) + getTargetHighTimeFromMidnight(timeAsSeconds))/2;
|
||||
}
|
||||
|
||||
public Double getTargetLow(Integer timeAsSeconds) {
|
||||
public double getTargetLow() {
|
||||
return getTargetLowTimeFromMidnight(secondsFromMidnight(System.currentTimeMillis()));
|
||||
}
|
||||
|
||||
public double getTargetLow(long time) {
|
||||
return getTargetLowTimeFromMidnight(secondsFromMidnight(time));
|
||||
}
|
||||
|
||||
public double getTargetLowTimeFromMidnight(int timeAsSeconds) {
|
||||
if (targetLow_v == null)
|
||||
targetLow_v = convertToSparseArray(targetLow);
|
||||
return getValueToTime(targetLow_v, timeAsSeconds);
|
||||
}
|
||||
|
||||
public Double getTargetHigh() {
|
||||
return getTargetHigh(secondsFromMidnight(System.currentTimeMillis()));
|
||||
public double getTargetHigh() {
|
||||
return getTargetHighTimeFromMidnight(secondsFromMidnight(System.currentTimeMillis()));
|
||||
}
|
||||
|
||||
public Double getTargetHigh(long time) {
|
||||
return getTargetHigh(secondsFromMidnight(time));
|
||||
public double getTargetHigh(long time) {
|
||||
return getTargetHighTimeFromMidnight(secondsFromMidnight(time));
|
||||
}
|
||||
|
||||
public Double getTargetHigh(Integer timeAsSeconds) {
|
||||
public double getTargetHighTimeFromMidnight(int timeAsSeconds) {
|
||||
if (targetHigh_v == null)
|
||||
targetHigh_v = convertToSparseArray(targetHigh);
|
||||
return getValueToTime(targetHigh_v, timeAsSeconds);
|
||||
}
|
||||
|
||||
public String getTargetList() {
|
||||
if (targetLow_v == null)
|
||||
targetLow_v = convertToSparseArray(targetLow);
|
||||
if (targetHigh_v == null)
|
||||
targetHigh_v = convertToSparseArray(targetHigh);
|
||||
return getValuesList(targetLow_v, targetHigh_v, new DecimalFormat("0.0"), getUnits());
|
||||
}
|
||||
|
||||
public double getMaxDailyBasal() {
|
||||
Double max = 0d;
|
||||
for (Integer hour = 0; hour < 24; hour++) {
|
||||
double value = getBasal((Integer) (hour * 60 * 60));
|
||||
double max = 0d;
|
||||
for (int hour = 0; hour < 24; hour++) {
|
||||
double value = getBasalTimeFromMidnight((Integer) (hour * 60 * 60));
|
||||
if (value > max) max = value;
|
||||
}
|
||||
return max;
|
||||
}
|
||||
|
||||
public static Integer secondsFromMidnight() {
|
||||
public static int secondsFromMidnight() {
|
||||
Calendar c = Calendar.getInstance();
|
||||
long now = c.getTimeInMillis();
|
||||
c.set(Calendar.HOUR_OF_DAY, 0);
|
||||
|
@ -491,7 +503,7 @@ public class Profile {
|
|||
return (int) (passed / 1000);
|
||||
}
|
||||
|
||||
public static Integer secondsFromMidnight(long date) {
|
||||
public static int secondsFromMidnight(long date) {
|
||||
Calendar c = Calendar.getInstance();
|
||||
c.setTimeInMillis(date);
|
||||
c.set(Calendar.HOUR_OF_DAY, 0);
|
||||
|
@ -502,22 +514,22 @@ public class Profile {
|
|||
return (int) (passed / 1000);
|
||||
}
|
||||
|
||||
public static Double toMgdl(Double value, String units) {
|
||||
public static double toMgdl(double value, String units) {
|
||||
if (units.equals(Constants.MGDL)) return value;
|
||||
else return value * Constants.MMOLL_TO_MGDL;
|
||||
}
|
||||
|
||||
public static Double toMmol(Double value, String units) {
|
||||
public static double toMmol(double value, String units) {
|
||||
if (units.equals(Constants.MGDL)) return value * Constants.MGDL_TO_MMOLL;
|
||||
else return value;
|
||||
}
|
||||
|
||||
public static Double fromMgdlToUnits(Double value, String units) {
|
||||
public static double fromMgdlToUnits(double value, String units) {
|
||||
if (units.equals(Constants.MGDL)) return value;
|
||||
else return value * Constants.MGDL_TO_MMOLL;
|
||||
}
|
||||
|
||||
public static Double toUnits(Double valueInMgdl, Double valueInMmol, String units) {
|
||||
public static double toUnits(Double valueInMgdl, Double valueInMmol, String units) {
|
||||
if (units.equals(Constants.MGDL)) return valueInMgdl;
|
||||
else return valueInMmol;
|
||||
}
|
||||
|
@ -543,7 +555,7 @@ public class Profile {
|
|||
public double percentageBasalSum() {
|
||||
double result = 0d;
|
||||
for (int i = 0; i < 24; i++) {
|
||||
result += getBasal((Integer) (i * 60 * 60));
|
||||
result += getBasalTimeFromMidnight(i * 60 * 60);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -552,7 +564,7 @@ public class Profile {
|
|||
public double baseBasalSum() {
|
||||
double result = 0d;
|
||||
for (int i = 0; i < 24; i++) {
|
||||
result += getBasal((Integer) (i * 60 * 60)) / getMultiplier(basal_v);
|
||||
result += getBasalTimeFromMidnight(i * 60 * 60) / getMultiplier(basal_v);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -3,10 +3,14 @@ package info.nightscout.androidaps.data;
|
|||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.util.LongSparseArray;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import info.nightscout.androidaps.interfaces.Interval;
|
||||
import info.nightscout.utils.DateUtil;
|
||||
|
||||
/**
|
||||
* Created by mike on 09.05.2017.
|
||||
|
@ -16,8 +20,17 @@ import info.nightscout.androidaps.interfaces.Interval;
|
|||
// When no interval match the lastest record without duration is used
|
||||
|
||||
public class ProfileIntervals<T extends Interval> {
|
||||
private static Logger log = LoggerFactory.getLogger(ProfileIntervals.class);
|
||||
|
||||
private LongSparseArray<T> rawData = new LongSparseArray<>(); // oldest at index 0
|
||||
private LongSparseArray<T> rawData; // oldest at index 0
|
||||
|
||||
public ProfileIntervals () {
|
||||
rawData = new LongSparseArray<>();
|
||||
}
|
||||
|
||||
public ProfileIntervals (ProfileIntervals<T> other) {
|
||||
rawData = other.rawData.clone();
|
||||
}
|
||||
|
||||
public synchronized ProfileIntervals reset() {
|
||||
rawData = new LongSparseArray<>();
|
||||
|
@ -25,8 +38,10 @@ public class ProfileIntervals<T extends Interval> {
|
|||
}
|
||||
|
||||
public synchronized void add(T newInterval) {
|
||||
rawData.put(newInterval.start(), newInterval);
|
||||
merge();
|
||||
if (newInterval.isValid()) {
|
||||
rawData.put(newInterval.start(), newInterval);
|
||||
merge();
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void add(List<T> list) {
|
||||
|
@ -51,6 +66,13 @@ public class ProfileIntervals<T extends Interval> {
|
|||
public synchronized Interval getValueToTime(long time) {
|
||||
int index = binarySearch(time);
|
||||
if (index >= 0) return rawData.valueAt(index);
|
||||
// if we request data older than first record, use oldest with zero duration instead
|
||||
for (index = 0; index < rawData.size(); index++) {
|
||||
if (rawData.valueAt(index).durationInMsec() == 0) {
|
||||
//log.debug("Requested profile for time: " + DateUtil.dateAndTimeString(time) + ". Providing oldest record: " + rawData.valueAt(0).toString());
|
||||
return rawData.valueAt(index);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -107,4 +129,9 @@ public class ProfileIntervals<T extends Interval> {
|
|||
public synchronized T getReversed(int index) {
|
||||
return rawData.valueAt(size() - 1 - index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return rawData.toString();
|
||||
}
|
||||
}
|
|
@ -13,7 +13,7 @@ import info.nightscout.androidaps.R;
|
|||
import info.nightscout.utils.DecimalFormatter;
|
||||
import info.nightscout.utils.Round;
|
||||
|
||||
public class PumpEnactResult extends Object {
|
||||
public class PumpEnactResult {
|
||||
private static Logger log = LoggerFactory.getLogger(PumpEnactResult.class);
|
||||
|
||||
public boolean success = false; // request was processed successfully (but possible no change was needed)
|
||||
|
@ -21,19 +21,19 @@ public class PumpEnactResult extends Object {
|
|||
public String comment = "";
|
||||
|
||||
// Result of basal change
|
||||
public Integer duration = -1; // duration set [minutes]
|
||||
public Double absolute = -1d; // absolute rate [U/h] , isPercent = false
|
||||
public Integer percent = -1; // percent of current basal [%] (100% = current basal), isPercent = true
|
||||
public int duration = -1; // duration set [minutes]
|
||||
public double absolute = -1d; // absolute rate [U/h] , isPercent = false
|
||||
public int percent = -1; // percent of current basal [%] (100% = current basal), isPercent = true
|
||||
public boolean isPercent = false; // if true percent is used, otherwise absolute
|
||||
public boolean isTempCancel = false; // if true we are caceling temp basal
|
||||
// Result of treatment delivery
|
||||
public Double bolusDelivered = 0d; // real value of delivered insulin
|
||||
public Double carbsDelivered = 0d; // real value of delivered carbs
|
||||
public double bolusDelivered = 0d; // real value of delivered insulin
|
||||
public double carbsDelivered = 0d; // real value of delivered carbs
|
||||
|
||||
public boolean queued = false;
|
||||
|
||||
public PumpEnactResult success(boolean success) {
|
||||
this.success = success;
|
||||
this.success = success;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -47,16 +47,21 @@ public class PumpEnactResult extends Object {
|
|||
return this;
|
||||
}
|
||||
|
||||
public PumpEnactResult duration(Integer duration) {
|
||||
public PumpEnactResult duration(int duration) {
|
||||
this.duration = duration;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PumpEnactResult absolute(Double absolute) {
|
||||
public PumpEnactResult absolute(double absolute) {
|
||||
this.absolute = absolute;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PumpEnactResult percent(int percent) {
|
||||
this.percent = percent;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PumpEnactResult isPercent(boolean isPercent) {
|
||||
this.isPercent = isPercent;
|
||||
return this;
|
||||
|
@ -67,12 +72,12 @@ public class PumpEnactResult extends Object {
|
|||
return this;
|
||||
}
|
||||
|
||||
public PumpEnactResult bolusDelivered(Double bolusDelivered) {
|
||||
public PumpEnactResult bolusDelivered(double bolusDelivered) {
|
||||
this.bolusDelivered = bolusDelivered;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PumpEnactResult carbsDelivered(Double carbsDelivered) {
|
||||
public PumpEnactResult carbsDelivered(double carbsDelivered) {
|
||||
this.carbsDelivered = carbsDelivered;
|
||||
return this;
|
||||
}
|
||||
|
@ -82,72 +87,96 @@ public class PumpEnactResult extends Object {
|
|||
return this;
|
||||
}
|
||||
|
||||
public String log() {
|
||||
return "Success: " + success + " Enacted: " + enacted + " Comment: " + comment + " Duration: " + duration + " Absolute: " + absolute + " Percent: " + percent + " IsPercent: " + isPercent + " Queued: " + queued;
|
||||
public String log() {
|
||||
return "Success: " + success +
|
||||
" Enacted: " + enacted +
|
||||
" Comment: " + comment +
|
||||
" Duration: " + duration +
|
||||
" Absolute: " + absolute +
|
||||
" Percent: " + percent +
|
||||
" IsPercent: " + isPercent +
|
||||
" IsTempCancel: " + isTempCancel +
|
||||
" bolusDelivered: " + bolusDelivered +
|
||||
" carbsDelivered: " + carbsDelivered +
|
||||
" Queued: " + queued;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String ret = MainApp.sResources.getString(R.string.success) + ": " + success;
|
||||
String ret = MainApp.gs(R.string.success) + ": " + success;
|
||||
if (enacted) {
|
||||
if (isTempCancel) {
|
||||
ret += "\n" + MainApp.sResources.getString(R.string.enacted) + ": " + enacted;
|
||||
ret += "\n" + MainApp.sResources.getString(R.string.comment) + ": " + comment + "\n" +
|
||||
MainApp.sResources.getString(R.string.canceltemp);
|
||||
if (bolusDelivered > 0) {
|
||||
ret += "\n" + MainApp.gs(R.string.enacted) + ": " + enacted;
|
||||
ret += "\n" + MainApp.gs(R.string.comment) + ": " + comment;
|
||||
ret += "\n" + MainApp.gs(R.string.smb_shortname)
|
||||
+ ": " + bolusDelivered + " " + MainApp.gs(R.string.insulin_unit_shortname);
|
||||
} else if (isTempCancel) {
|
||||
ret += "\n" + MainApp.gs(R.string.enacted) + ": " + enacted;
|
||||
if (!comment.isEmpty())
|
||||
ret += "\n" + MainApp.gs(R.string.comment) + ": " + comment;
|
||||
ret += "\n" + MainApp.gs(R.string.canceltemp);
|
||||
} else if (isPercent) {
|
||||
ret += "\n" + MainApp.sResources.getString(R.string.enacted) + ": " + enacted;
|
||||
ret += "\n" + MainApp.sResources.getString(R.string.comment) + ": " + comment;
|
||||
ret += "\n" + MainApp.sResources.getString(R.string.duration) + ": " + duration + " min";
|
||||
ret += "\n" + MainApp.sResources.getString(R.string.percent) + ": " + percent + "%";
|
||||
ret += "\n" + MainApp.gs(R.string.enacted) + ": " + enacted;
|
||||
if (!comment.isEmpty())
|
||||
ret += "\n" + MainApp.gs(R.string.comment) + ": " + comment;
|
||||
ret += "\n" + MainApp.gs(R.string.duration) + ": " + duration + " min";
|
||||
ret += "\n" + MainApp.gs(R.string.percent) + ": " + percent + "%";
|
||||
} else {
|
||||
ret += "\n" + MainApp.sResources.getString(R.string.enacted) + ": " + enacted;
|
||||
ret += "\n" + MainApp.sResources.getString(R.string.comment) + ": " + comment;
|
||||
ret += "\n" + MainApp.sResources.getString(R.string.duration) + ": " + duration + " min";
|
||||
ret += "\n" + MainApp.sResources.getString(R.string.absolute) + ": " + absolute + " U/h";
|
||||
ret += "\n" + MainApp.gs(R.string.enacted) + ": " + enacted;
|
||||
if (!comment.isEmpty())
|
||||
ret += "\n" + MainApp.gs(R.string.comment) + ": " + comment;
|
||||
ret += "\n" + MainApp.gs(R.string.duration) + ": " + duration + " min";
|
||||
ret += "\n" + MainApp.gs(R.string.absolute) + ": " + absolute + " U/h";
|
||||
}
|
||||
} else {
|
||||
ret += "\n" + MainApp.sResources.getString(R.string.comment) + ": " + comment;
|
||||
ret += "\n" + MainApp.gs(R.string.comment) + ": " + comment;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public Spanned toSpanned() {
|
||||
String ret = MainApp.sResources.getString(R.string.success) + ": " + success;
|
||||
public String toHtml() {
|
||||
String ret = "<b>" + MainApp.gs(R.string.success) + "</b>: " + success;
|
||||
if (queued) {
|
||||
ret = MainApp.sResources.getString(R.string.waitingforpumpresult);
|
||||
ret = MainApp.gs(R.string.waitingforpumpresult);
|
||||
} else if (enacted) {
|
||||
if (isTempCancel) {
|
||||
ret += "<br><b>" + MainApp.sResources.getString(R.string.enacted) + "</b>: " + enacted;
|
||||
ret += "<br><b>" + MainApp.sResources.getString(R.string.comment) + "</b>: " + comment +
|
||||
"<br>" + MainApp.sResources.getString(R.string.canceltemp);
|
||||
} else if (isPercent) {
|
||||
ret += "<br><b>" + MainApp.sResources.getString(R.string.enacted) + "</b>: " + enacted;
|
||||
ret += "<br><b>" + MainApp.sResources.getString(R.string.comment) + "</b>: " + comment;
|
||||
ret += "<br><b>" + MainApp.sResources.getString(R.string.duration) + "</b>: " + duration + " min";
|
||||
ret += "<br><b>" + MainApp.sResources.getString(R.string.percent) + "</b>: " + percent + "%";
|
||||
} else {
|
||||
ret += "<br><b>" + MainApp.sResources.getString(R.string.enacted) + "</b>: " + enacted;
|
||||
ret += "<br><b>" + MainApp.sResources.getString(R.string.comment) + "</b>: " + comment;
|
||||
ret += "<br><b>" + MainApp.sResources.getString(R.string.duration) + "</b>: " + duration + " min";
|
||||
ret += "<br><b>" + MainApp.sResources.getString(R.string.absolute) + "</b>: " + DecimalFormatter.to2Decimal(absolute) + " U/h";
|
||||
if (bolusDelivered > 0) {
|
||||
ret += "<br><b>" + MainApp.gs(R.string.enacted) + "</b>: " + enacted;
|
||||
if (!comment.isEmpty())
|
||||
ret += "<br><b>" + MainApp.gs(R.string.comment) + "</b>: " + comment;
|
||||
ret += "<br><b>" + MainApp.gs(R.string.smb_shortname) + "</b>: " + bolusDelivered + " " + MainApp.gs(R.string.insulin_unit_shortname);
|
||||
} else if (isTempCancel) {
|
||||
ret += "<br><b>" + MainApp.gs(R.string.enacted) + "</b>: " + enacted;
|
||||
ret += "<br><b>" + MainApp.gs(R.string.comment) + "</b>: " + comment +
|
||||
"<br>" + MainApp.gs(R.string.canceltemp);
|
||||
} else if (isPercent && percent != -1) {
|
||||
ret += "<br><b>" + MainApp.gs(R.string.enacted) + "</b>: " + enacted;
|
||||
if (!comment.isEmpty())
|
||||
ret += "<br><b>" + MainApp.gs(R.string.comment) + "</b>: " + comment;
|
||||
ret += "<br><b>" + MainApp.gs(R.string.duration) + "</b>: " + duration + " min";
|
||||
ret += "<br><b>" + MainApp.gs(R.string.percent) + "</b>: " + percent + "%";
|
||||
} else if (absolute != -1) {
|
||||
ret += "<br><b>" + MainApp.gs(R.string.enacted) + "</b>: " + enacted;
|
||||
if (!comment.isEmpty())
|
||||
ret += "<br><b>" + MainApp.gs(R.string.comment) + "</b>: " + comment;
|
||||
ret += "<br><b>" + MainApp.gs(R.string.duration) + "</b>: " + duration + " min";
|
||||
ret += "<br><b>" + MainApp.gs(R.string.absolute) + "</b>: " + DecimalFormatter.to2Decimal(absolute) + " U/h";
|
||||
}
|
||||
} else {
|
||||
ret += "<br><b>" + MainApp.sResources.getString(R.string.comment) + "</b>: " + comment;
|
||||
ret += "<br><b>" + MainApp.gs(R.string.comment) + "</b>: " + comment;
|
||||
}
|
||||
return Html.fromHtml(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public PumpEnactResult() {
|
||||
}
|
||||
|
||||
public JSONObject json() {
|
||||
public JSONObject json(Profile profile) {
|
||||
JSONObject result = new JSONObject();
|
||||
try {
|
||||
if (isTempCancel) {
|
||||
if (bolusDelivered > 0) {
|
||||
result.put("smb", bolusDelivered);
|
||||
} else if (isTempCancel) {
|
||||
result.put("rate", 0);
|
||||
result.put("duration", 0);
|
||||
} else if (isPercent) {
|
||||
// Nightscout is expecting absolute value
|
||||
Double abs = Round.roundTo(MainApp.getConfigBuilder().getProfile().getBasal() * percent / 100, 0.01);
|
||||
Double abs = Round.roundTo(profile.getBasal() * percent / 100, 0.01);
|
||||
result.put("rate", abs);
|
||||
result.put("duration", duration);
|
||||
} else {
|
||||
|
|
|
@ -10,6 +10,7 @@ import org.slf4j.Logger;
|
|||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.utils.SP;
|
||||
|
||||
/**
|
||||
* Created by mike on 12.10.2016.
|
||||
|
@ -25,10 +26,7 @@ public class QuickWizard {
|
|||
}
|
||||
|
||||
public void save() {
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
|
||||
SharedPreferences.Editor editor = preferences.edit();
|
||||
editor.putString("QuickWizard", storage.toString());
|
||||
editor.apply();
|
||||
SP.putString("QuickWizard", storage.toString());
|
||||
}
|
||||
|
||||
public int size() {
|
||||
|
|
|
@ -7,15 +7,14 @@ import org.slf4j.LoggerFactory;
|
|||
|
||||
import java.util.Date;
|
||||
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.db.BgReading;
|
||||
import info.nightscout.androidaps.db.TempTarget;
|
||||
import info.nightscout.androidaps.interfaces.TreatmentsInterface;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData;
|
||||
import info.nightscout.androidaps.plugins.IobCobCalculator.CobInfo;
|
||||
import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin;
|
||||
import info.nightscout.androidaps.plugins.Loop.LoopPlugin;
|
||||
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
|
||||
import info.nightscout.utils.BolusWizard;
|
||||
import info.nightscout.utils.DateUtil;
|
||||
import info.nightscout.utils.SP;
|
||||
|
@ -80,14 +79,10 @@ public class QuickWizardEntry {
|
|||
|
||||
// COB
|
||||
double cob = 0d;
|
||||
AutosensData autosensData;
|
||||
if (_synchronized)
|
||||
autosensData = IobCobCalculatorPlugin.getLastAutosensDataSynchronized("QuickWizard COB");
|
||||
else
|
||||
autosensData = IobCobCalculatorPlugin.getLastAutosensData("QuickWizard COB");
|
||||
|
||||
if (autosensData != null && useCOB() == YES) {
|
||||
cob = autosensData.cob;
|
||||
if (useCOB() == YES) {
|
||||
CobInfo cobInfo = IobCobCalculatorPlugin.getPlugin().getCobInfo(_synchronized, "QuickWizard COB");
|
||||
if (cobInfo.displayCob != null)
|
||||
cob = cobInfo.displayCob;
|
||||
}
|
||||
|
||||
// Temp target
|
||||
|
@ -102,7 +97,7 @@ public class QuickWizardEntry {
|
|||
}
|
||||
|
||||
// Basal IOB
|
||||
TreatmentsInterface treatments = MainApp.getConfigBuilder();
|
||||
TreatmentsInterface treatments = TreatmentsPlugin.getPlugin();
|
||||
treatments.updateTotalIOBTempBasals();
|
||||
IobTotal basalIob = treatments.getLastCalculationTempBasals().round();
|
||||
boolean basalIOB = false;
|
||||
|
@ -119,8 +114,8 @@ public class QuickWizardEntry {
|
|||
if (useSuperBolus() == YES && SP.getBoolean(R.string.key_usesuperbolus, false)) {
|
||||
superBolus = true;
|
||||
}
|
||||
final LoopPlugin activeloop = ConfigBuilderPlugin.getActiveLoop();
|
||||
if (activeloop != null && activeloop.isEnabled(activeloop.getType()) && activeloop.isSuperBolus())
|
||||
final LoopPlugin loopPlugin = LoopPlugin.getPlugin();
|
||||
if (loopPlugin.isEnabled(loopPlugin.getType()) && loopPlugin.isSuperBolus())
|
||||
superBolus = false;
|
||||
|
||||
// Trend
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package info.nightscout.androidaps.db;
|
||||
|
||||
import android.content.res.Resources;
|
||||
|
||||
import com.j256.ormlite.field.DatabaseField;
|
||||
import com.j256.ormlite.table.DatabaseTable;
|
||||
|
||||
|
@ -17,7 +19,6 @@ import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSgv;
|
|||
import info.nightscout.androidaps.plugins.Overview.OverviewPlugin;
|
||||
import info.nightscout.androidaps.plugins.Overview.graphExtensions.DataPointWithLabelInterface;
|
||||
import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLabelGraphSeries;
|
||||
import info.nightscout.utils.DateUtil;
|
||||
import info.nightscout.utils.DecimalFormatter;
|
||||
import info.nightscout.utils.SP;
|
||||
|
||||
|
@ -43,7 +44,11 @@ public class BgReading implements DataPointWithLabelInterface {
|
|||
@DatabaseField
|
||||
public String _id = null; // NS _id
|
||||
|
||||
public boolean isPrediction = false; // true when drawing predictions as bg points
|
||||
public boolean isCOBPrediction = false; // true when drawing predictions as bg points (COB)
|
||||
public boolean isaCOBPrediction = false; // true when drawing predictions as bg points (aCOB)
|
||||
public boolean isIOBPrediction = false; // true when drawing predictions as bg points (IOB)
|
||||
public boolean isUAMPrediction = false; // true when drawing predictions as bg points (UAM)
|
||||
public boolean isZTPrediction = false; // true when drawing predictions as bg points (ZT)
|
||||
|
||||
public BgReading() {
|
||||
}
|
||||
|
@ -184,13 +189,15 @@ public class BgReading implements DataPointWithLabelInterface {
|
|||
|
||||
@Override
|
||||
public PointsWithLabelGraphSeries.Shape getShape() {
|
||||
return PointsWithLabelGraphSeries.Shape.POINT;
|
||||
if (isPrediction())
|
||||
return PointsWithLabelGraphSeries.Shape.PREDICTION;
|
||||
else
|
||||
return PointsWithLabelGraphSeries.Shape.BG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getSize() {
|
||||
boolean isTablet = MainApp.sResources.getBoolean(R.bool.isTablet);
|
||||
return isTablet ? 8 : 5;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -205,8 +212,8 @@ public class BgReading implements DataPointWithLabelInterface {
|
|||
highLine = Profile.fromMgdlToUnits(OverviewPlugin.bgTargetHigh, units);
|
||||
}
|
||||
int color = MainApp.sResources.getColor(R.color.inrange);
|
||||
if (isPrediction)
|
||||
color = MainApp.sResources.getColor(R.color.prediction);
|
||||
if (isPrediction())
|
||||
return getPredectionColor();
|
||||
else if (valueToUnits(units) < lowLine)
|
||||
color = MainApp.sResources.getColor(R.color.low);
|
||||
else if (valueToUnits(units) > highLine)
|
||||
|
@ -214,4 +221,22 @@ public class BgReading implements DataPointWithLabelInterface {
|
|||
return color;
|
||||
}
|
||||
|
||||
public int getPredectionColor() {
|
||||
if (isIOBPrediction)
|
||||
return MainApp.sResources.getColor(R.color.iob);
|
||||
if (isCOBPrediction)
|
||||
return MainApp.sResources.getColor(R.color.cob);
|
||||
if (isaCOBPrediction)
|
||||
return 0x80FFFFFF & MainApp.sResources.getColor(R.color.cob);
|
||||
if (isUAMPrediction)
|
||||
return MainApp.sResources.getColor(R.color.uam);
|
||||
if (isZTPrediction)
|
||||
return MainApp.sResources.getColor(R.color.zt);
|
||||
return R.color.mdtp_white;
|
||||
}
|
||||
|
||||
private boolean isPrediction() {
|
||||
return isaCOBPrediction || isCOBPrediction || isIOBPrediction || isUAMPrediction || isZTPrediction;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import android.graphics.Color;
|
|||
import com.j256.ormlite.field.DatabaseField;
|
||||
import com.j256.ormlite.table.DatabaseTable;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -94,7 +95,15 @@ public class CareportalEvent implements DataPointWithLabelInterface {
|
|||
if (OverviewFragment.shorttextmode)
|
||||
return diff.get(TimeUnit.DAYS) +"d" + diff.get(TimeUnit.HOURS) + "h";
|
||||
else
|
||||
return diff.get(TimeUnit.DAYS) + " " + MainApp.sResources.getString(R.string.days) + " " + diff.get(TimeUnit.HOURS) + " " + MainApp.sResources.getString(R.string.hours);
|
||||
return diff.get(TimeUnit.DAYS) + " " + MainApp.gs(R.string.days) + " " + diff.get(TimeUnit.HOURS) + " " + MainApp.gs(R.string.hours);
|
||||
}
|
||||
|
||||
public boolean isOlderThan(double hours) {
|
||||
Map<TimeUnit, Long> diff = computeDiff(date, System.currentTimeMillis());
|
||||
if(diff.get(TimeUnit.DAYS)*24 + diff.get(TimeUnit.HOURS) > hours)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
public String log() {
|
||||
|
@ -184,7 +193,7 @@ public class CareportalEvent implements DataPointWithLabelInterface {
|
|||
try {
|
||||
JSONObject object = new JSONObject(json);
|
||||
if (object.has("notes"))
|
||||
return object.getString("notes");
|
||||
return StringUtils.abbreviate(object.getString("notes"), 40);
|
||||
} catch (JSONException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
|
@ -253,4 +262,5 @@ public class CareportalEvent implements DataPointWithLabelInterface {
|
|||
return Color.GRAY;
|
||||
return Color.GRAY;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -30,12 +30,10 @@ import java.util.concurrent.TimeUnit;
|
|||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.Constants;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.data.Profile;
|
||||
import info.nightscout.androidaps.data.ProfileStore;
|
||||
import info.nightscout.androidaps.events.EventCareportalEventChange;
|
||||
import info.nightscout.androidaps.events.EventExtendedBolusChange;
|
||||
import info.nightscout.androidaps.events.EventFoodDatabaseChanged;
|
||||
import info.nightscout.androidaps.events.EventNewBG;
|
||||
import info.nightscout.androidaps.events.EventProfileSwitchChange;
|
||||
import info.nightscout.androidaps.events.EventRefreshOverview;
|
||||
|
@ -44,17 +42,23 @@ import info.nightscout.androidaps.events.EventReloadTempBasalData;
|
|||
import info.nightscout.androidaps.events.EventReloadTreatmentData;
|
||||
import info.nightscout.androidaps.events.EventTempBasalChange;
|
||||
import info.nightscout.androidaps.events.EventTempTargetChange;
|
||||
import info.nightscout.androidaps.events.EventTreatmentChange;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventNewHistoryData;
|
||||
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
|
||||
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
|
||||
import info.nightscout.androidaps.plugins.PumpDanaR.activities.DanaRNSHistorySync;
|
||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes;
|
||||
import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin;
|
||||
import info.nightscout.utils.DateUtil;
|
||||
import info.nightscout.utils.JsonHelper;
|
||||
import info.nightscout.utils.NSUpload;
|
||||
import info.nightscout.utils.PercentageSplitter;
|
||||
import info.nightscout.utils.ToastUtils;
|
||||
|
||||
/**
|
||||
* This Helper contains all resource to provide a central DB management functionality. Only methods handling
|
||||
* data-structure (and not the DB content) should be contained in here (meaning DDL and not SQL).
|
||||
* <p>
|
||||
* This class can safely be called from Services, but should not call Services to avoid circular dependencies.
|
||||
* One major issue with this (right now) are the scheduled events, which are put into the service. Therefor all
|
||||
* direct calls to the corresponding methods (eg. resetDatabases) should be done by a central service.
|
||||
*/
|
||||
public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||
private static Logger log = LoggerFactory.getLogger(DatabaseHelper.class);
|
||||
|
||||
|
@ -63,23 +67,19 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
public static final String DATABASE_TEMPORARYBASALS = "TemporaryBasals";
|
||||
public static final String DATABASE_EXTENDEDBOLUSES = "ExtendedBoluses";
|
||||
public static final String DATABASE_TEMPTARGETS = "TempTargets";
|
||||
public static final String DATABASE_TREATMENTS = "Treatments";
|
||||
public static final String DATABASE_DANARHISTORY = "DanaRHistory";
|
||||
public static final String DATABASE_DBREQUESTS = "DBRequests";
|
||||
public static final String DATABASE_CAREPORTALEVENTS = "CareportalEvents";
|
||||
public static final String DATABASE_PROFILESWITCHES = "ProfileSwitches";
|
||||
public static final String DATABASE_FOODS = "Foods";
|
||||
public static final String DATABASE_TDDS = "TDDs";
|
||||
|
||||
private static final int DATABASE_VERSION = 8;
|
||||
|
||||
private static Long earliestDataChange = null;
|
||||
public static Long earliestDataChange = null;
|
||||
|
||||
private static final ScheduledExecutorService bgWorker = Executors.newSingleThreadScheduledExecutor();
|
||||
private static ScheduledFuture<?> scheduledBgPost = null;
|
||||
|
||||
private static final ScheduledExecutorService treatmentsWorker = Executors.newSingleThreadScheduledExecutor();
|
||||
private static ScheduledFuture<?> scheduledTratmentPost = null;
|
||||
|
||||
private static final ScheduledExecutorService tempBasalsWorker = Executors.newSingleThreadScheduledExecutor();
|
||||
private static ScheduledFuture<?> scheduledTemBasalsPost = null;
|
||||
|
||||
|
@ -95,7 +95,8 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
private static final ScheduledExecutorService profileSwitchEventWorker = Executors.newSingleThreadScheduledExecutor();
|
||||
private static ScheduledFuture<?> scheduledProfileSwitchEventPost = null;
|
||||
|
||||
public FoodHelper foodHelper = new FoodHelper(this);
|
||||
private int oldVersion = 0;
|
||||
private int newVersion = 0;
|
||||
|
||||
public DatabaseHelper(Context context) {
|
||||
super(context, DATABASE_NAME, null, DATABASE_VERSION);
|
||||
|
@ -108,7 +109,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
try {
|
||||
log.info("onCreate");
|
||||
TableUtils.createTableIfNotExists(connectionSource, TempTarget.class);
|
||||
TableUtils.createTableIfNotExists(connectionSource, Treatment.class);
|
||||
TableUtils.createTableIfNotExists(connectionSource, BgReading.class);
|
||||
TableUtils.createTableIfNotExists(connectionSource, DanaRHistoryRecord.class);
|
||||
TableUtils.createTableIfNotExists(connectionSource, DbRequest.class);
|
||||
|
@ -116,7 +116,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
TableUtils.createTableIfNotExists(connectionSource, ExtendedBolus.class);
|
||||
TableUtils.createTableIfNotExists(connectionSource, CareportalEvent.class);
|
||||
TableUtils.createTableIfNotExists(connectionSource, ProfileSwitch.class);
|
||||
TableUtils.createTableIfNotExists(connectionSource, Food.class);
|
||||
TableUtils.createTableIfNotExists(connectionSource, TDD.class);
|
||||
} catch (SQLException e) {
|
||||
log.error("Can't create database", e);
|
||||
throw new RuntimeException(e);
|
||||
|
@ -126,14 +126,14 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
@Override
|
||||
public void onUpgrade(SQLiteDatabase database, ConnectionSource connectionSource, int oldVersion, int newVersion) {
|
||||
try {
|
||||
this.oldVersion = oldVersion;
|
||||
this.newVersion = newVersion;
|
||||
|
||||
if (oldVersion == 7 && newVersion == 8) {
|
||||
log.debug("Upgrading database from v7 to v8");
|
||||
TableUtils.dropTable(connectionSource, Treatment.class, true);
|
||||
TableUtils.createTableIfNotExists(connectionSource, Treatment.class);
|
||||
} else {
|
||||
log.info(DatabaseHelper.class.getName(), "onUpgrade");
|
||||
TableUtils.dropTable(connectionSource, TempTarget.class, true);
|
||||
TableUtils.dropTable(connectionSource, Treatment.class, true);
|
||||
TableUtils.dropTable(connectionSource, BgReading.class, true);
|
||||
TableUtils.dropTable(connectionSource, DanaRHistoryRecord.class, true);
|
||||
TableUtils.dropTable(connectionSource, DbRequest.class, true);
|
||||
|
@ -141,7 +141,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
TableUtils.dropTable(connectionSource, ExtendedBolus.class, true);
|
||||
TableUtils.dropTable(connectionSource, CareportalEvent.class, true);
|
||||
TableUtils.dropTable(connectionSource, ProfileSwitch.class, true);
|
||||
TableUtils.dropTable(connectionSource, Food.class, true);
|
||||
onCreate(database, connectionSource);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
|
@ -150,6 +149,14 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
}
|
||||
}
|
||||
|
||||
public int getOldVersion() {
|
||||
return oldVersion;
|
||||
}
|
||||
|
||||
public int getNewVersion() {
|
||||
return newVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the database connections and clear any cached DAOs.
|
||||
*/
|
||||
|
@ -158,40 +165,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
super.close();
|
||||
}
|
||||
|
||||
public void cleanUpDatabases() {
|
||||
// TODO: call it somewhere
|
||||
log.debug("Before BgReadings size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_BGREADINGS));
|
||||
getWritableDatabase().delete(DATABASE_BGREADINGS, "date" + " < '" + (System.currentTimeMillis() - Constants.hoursToKeepInDatabase * 60 * 60 * 1000L) + "'", null);
|
||||
log.debug("After BgReadings size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_BGREADINGS));
|
||||
|
||||
log.debug("Before TempTargets size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_TEMPTARGETS));
|
||||
getWritableDatabase().delete(DATABASE_TEMPTARGETS, "date" + " < '" + (System.currentTimeMillis() - Constants.hoursToKeepInDatabase * 60 * 60 * 1000L) + "'", null);
|
||||
log.debug("After TempTargets size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_TEMPTARGETS));
|
||||
|
||||
log.debug("Before Treatments size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_TREATMENTS));
|
||||
getWritableDatabase().delete(DATABASE_TREATMENTS, "date" + " < '" + (System.currentTimeMillis() - Constants.hoursToKeepInDatabase * 60 * 60 * 1000L) + "'", null);
|
||||
log.debug("After Treatments size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_TREATMENTS));
|
||||
|
||||
log.debug("Before History size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_DANARHISTORY));
|
||||
getWritableDatabase().delete(DATABASE_DANARHISTORY, "recordDate" + " < '" + (System.currentTimeMillis() - Constants.daysToKeepHistoryInDatabase * 24 * 60 * 60 * 1000L) + "'", null);
|
||||
log.debug("After History size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_DANARHISTORY));
|
||||
|
||||
log.debug("Before TemporaryBasals size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_TEMPORARYBASALS));
|
||||
getWritableDatabase().delete(DATABASE_TEMPORARYBASALS, "recordDate" + " < '" + (System.currentTimeMillis() - Constants.daysToKeepHistoryInDatabase * 24 * 60 * 60 * 1000L) + "'", null);
|
||||
log.debug("After TemporaryBasals size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_TEMPORARYBASALS));
|
||||
|
||||
log.debug("Before ExtendedBoluses size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_EXTENDEDBOLUSES));
|
||||
getWritableDatabase().delete(DATABASE_EXTENDEDBOLUSES, "recordDate" + " < '" + (System.currentTimeMillis() - Constants.daysToKeepHistoryInDatabase * 24 * 60 * 60 * 1000L) + "'", null);
|
||||
log.debug("After ExtendedBoluses size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_EXTENDEDBOLUSES));
|
||||
|
||||
log.debug("Before CareportalEvent size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_CAREPORTALEVENTS));
|
||||
getWritableDatabase().delete(DATABASE_CAREPORTALEVENTS, "recordDate" + " < '" + (System.currentTimeMillis() - Constants.daysToKeepHistoryInDatabase * 24 * 60 * 60 * 1000L) + "'", null);
|
||||
log.debug("After CareportalEvent size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_CAREPORTALEVENTS));
|
||||
|
||||
log.debug("Before ProfileSwitch size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_PROFILESWITCHES));
|
||||
getWritableDatabase().delete(DATABASE_PROFILESWITCHES, "recordDate" + " < '" + (System.currentTimeMillis() - Constants.daysToKeepHistoryInDatabase * 24 * 60 * 60 * 1000L) + "'", null);
|
||||
log.debug("After ProfileSwitch size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_PROFILESWITCHES));
|
||||
}
|
||||
|
||||
public long size(String database) {
|
||||
return DatabaseUtils.queryNumEntries(getReadableDatabase(), database);
|
||||
|
@ -202,7 +175,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
public void resetDatabases() {
|
||||
try {
|
||||
TableUtils.dropTable(connectionSource, TempTarget.class, true);
|
||||
TableUtils.dropTable(connectionSource, Treatment.class, true);
|
||||
TableUtils.dropTable(connectionSource, BgReading.class, true);
|
||||
TableUtils.dropTable(connectionSource, DanaRHistoryRecord.class, true);
|
||||
TableUtils.dropTable(connectionSource, DbRequest.class, true);
|
||||
|
@ -210,8 +182,8 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
TableUtils.dropTable(connectionSource, ExtendedBolus.class, true);
|
||||
TableUtils.dropTable(connectionSource, CareportalEvent.class, true);
|
||||
TableUtils.dropTable(connectionSource, ProfileSwitch.class, true);
|
||||
TableUtils.dropTable(connectionSource, TDD.class, true);
|
||||
TableUtils.createTableIfNotExists(connectionSource, TempTarget.class);
|
||||
TableUtils.createTableIfNotExists(connectionSource, Treatment.class);
|
||||
TableUtils.createTableIfNotExists(connectionSource, BgReading.class);
|
||||
TableUtils.createTableIfNotExists(connectionSource, DanaRHistoryRecord.class);
|
||||
TableUtils.createTableIfNotExists(connectionSource, DbRequest.class);
|
||||
|
@ -219,20 +191,18 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
TableUtils.createTableIfNotExists(connectionSource, ExtendedBolus.class);
|
||||
TableUtils.createTableIfNotExists(connectionSource, CareportalEvent.class);
|
||||
TableUtils.createTableIfNotExists(connectionSource, ProfileSwitch.class);
|
||||
foodHelper.resetFood();
|
||||
TableUtils.createTableIfNotExists(connectionSource, TDD.class);
|
||||
updateEarliestDataChange(0);
|
||||
} catch (SQLException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
VirtualPumpPlugin.setFakingStatus(true);
|
||||
scheduleBgChange(); // trigger refresh
|
||||
scheduleBgChange(null); // trigger refresh
|
||||
scheduleTemporaryBasalChange();
|
||||
scheduleTreatmentChange();
|
||||
scheduleExtendedBolusChange();
|
||||
scheduleTemporaryTargetChange();
|
||||
scheduleCareportalEventChange();
|
||||
scheduleProfileSwitchChange();
|
||||
foodHelper.scheduleFoodChange();
|
||||
new java.util.Timer().schedule(
|
||||
new java.util.TimerTask() {
|
||||
@Override
|
||||
|
@ -244,17 +214,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
);
|
||||
}
|
||||
|
||||
public void resetTreatments() {
|
||||
try {
|
||||
TableUtils.dropTable(connectionSource, Treatment.class, true);
|
||||
TableUtils.createTableIfNotExists(connectionSource, Treatment.class);
|
||||
updateEarliestDataChange(0);
|
||||
} catch (SQLException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
scheduleTreatmentChange();
|
||||
}
|
||||
|
||||
public void resetTempTargets() {
|
||||
try {
|
||||
TableUtils.dropTable(connectionSource, TempTarget.class, true);
|
||||
|
@ -308,16 +267,21 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
scheduleProfileSwitchChange();
|
||||
}
|
||||
|
||||
public void resetTDDs() {
|
||||
try {
|
||||
TableUtils.dropTable(connectionSource, TDD.class, true);
|
||||
TableUtils.createTableIfNotExists(connectionSource, TDD.class);
|
||||
} catch (SQLException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------ getDao -------------------------------------------
|
||||
|
||||
private Dao<TempTarget, Long> getDaoTempTargets() throws SQLException {
|
||||
return getDao(TempTarget.class);
|
||||
}
|
||||
|
||||
private Dao<Treatment, Long> getDaoTreatments() throws SQLException {
|
||||
return getDao(Treatment.class);
|
||||
}
|
||||
|
||||
private Dao<BgReading, Long> getDaoBgReadings() throws SQLException {
|
||||
return getDao(BgReading.class);
|
||||
}
|
||||
|
@ -326,6 +290,10 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
return getDao(DanaRHistoryRecord.class);
|
||||
}
|
||||
|
||||
private Dao<TDD, String> getDaoTDD() throws SQLException {
|
||||
return getDao(TDD.class);
|
||||
}
|
||||
|
||||
private Dao<DbRequest, String> getDaoDbRequest() throws SQLException {
|
||||
return getDao(DbRequest.class);
|
||||
}
|
||||
|
@ -346,7 +314,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
return getDao(ProfileSwitch.class);
|
||||
}
|
||||
|
||||
public long roundDateToSec(long date) {
|
||||
public static long roundDateToSec(long date) {
|
||||
return date - date % 1000;
|
||||
}
|
||||
// ------------------- BgReading handling -----------------------
|
||||
|
@ -358,7 +326,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
if (old == null) {
|
||||
getDaoBgReadings().create(bgReading);
|
||||
log.debug("BG: New record from: " + from + " " + bgReading.toString());
|
||||
scheduleBgChange();
|
||||
scheduleBgChange(bgReading);
|
||||
return true;
|
||||
}
|
||||
if (!old.isEqual(bgReading)) {
|
||||
|
@ -366,7 +334,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
old.copyFrom(bgReading);
|
||||
getDaoBgReadings().update(old);
|
||||
log.debug("BG: Updating record from: " + from + " New data: " + old.toString());
|
||||
scheduleBgChange();
|
||||
scheduleBgChange(bgReading);
|
||||
return false;
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
|
@ -380,15 +348,15 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
try {
|
||||
getDaoBgReadings().update(bgReading);
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void scheduleBgChange() {
|
||||
private static void scheduleBgChange(@Nullable final BgReading bgReading) {
|
||||
class PostRunnable implements Runnable {
|
||||
public void run() {
|
||||
log.debug("Firing EventNewBg");
|
||||
MainApp.bus().post(new EventNewBG());
|
||||
MainApp.bus().post(new EventNewBG(bgReading));
|
||||
scheduledBgPost = null;
|
||||
}
|
||||
}
|
||||
|
@ -403,8 +371,8 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
}
|
||||
|
||||
/*
|
||||
* Return last BgReading from database or null if db is empty
|
||||
*/
|
||||
* Return last BgReading from database or null if db is empty
|
||||
*/
|
||||
@Nullable
|
||||
public static BgReading lastBg() {
|
||||
List<BgReading> bgList = null;
|
||||
|
@ -428,9 +396,9 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
}
|
||||
|
||||
/*
|
||||
* Return bg reading if not old ( <9 min )
|
||||
* or null if older
|
||||
*/
|
||||
* Return bg reading if not old ( <9 min )
|
||||
* or null if older
|
||||
*/
|
||||
@Nullable
|
||||
public static BgReading actualBg() {
|
||||
BgReading lastBg = lastBg();
|
||||
|
@ -479,6 +447,33 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
return new ArrayList<BgReading>();
|
||||
}
|
||||
|
||||
// ------------------- TDD handling -----------------------
|
||||
public void createOrUpdateTDD(TDD tdd) {
|
||||
try {
|
||||
Dao<TDD, String> dao = getDaoTDD();
|
||||
dao.createOrUpdate(tdd);
|
||||
} catch (SQLException e) {
|
||||
ToastUtils.showToastInUiThread(MainApp.instance(), "createOrUpdate-Exception");
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
}
|
||||
|
||||
public List<TDD> getTDDs() {
|
||||
List<TDD> tddList;
|
||||
try {
|
||||
QueryBuilder<TDD, String> queryBuilder = getDaoTDD().queryBuilder();
|
||||
queryBuilder.orderBy("date", false);
|
||||
queryBuilder.limit(10L);
|
||||
PreparedQuery<TDD> preparedQuery = queryBuilder.prepare();
|
||||
tddList = getDaoTDD().query(preparedQuery);
|
||||
} catch (SQLException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
tddList = new ArrayList<>();
|
||||
}
|
||||
return tddList;
|
||||
}
|
||||
|
||||
|
||||
// ------------- DbRequests handling -------------------
|
||||
|
||||
public void create(DbRequest dbr) {
|
||||
|
@ -515,7 +510,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
queryBuilder.limit(10L);
|
||||
PreparedQuery<DbRequest> preparedQuery = queryBuilder.prepare();
|
||||
List<DbRequest> dbList = getDaoDbRequest().query(preparedQuery);
|
||||
log.error("deleteDbRequestbyMongoId query size: " + dbList.size());
|
||||
for (DbRequest r : dbList) {
|
||||
delete(r);
|
||||
}
|
||||
|
@ -543,146 +537,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
|
||||
// -------------------- TREATMENT HANDLING -------------------
|
||||
|
||||
// return true if new record is created
|
||||
public boolean createOrUpdate(Treatment treatment) {
|
||||
try {
|
||||
Treatment old;
|
||||
treatment.date = roundDateToSec(treatment.date);
|
||||
|
||||
if (treatment.source == Source.PUMP) {
|
||||
// check for changed from pump change in NS
|
||||
QueryBuilder<Treatment, Long> queryBuilder = getDaoTreatments().queryBuilder();
|
||||
Where where = queryBuilder.where();
|
||||
where.eq("pumpId", treatment.pumpId);
|
||||
PreparedQuery<Treatment> preparedQuery = queryBuilder.prepare();
|
||||
List<Treatment> trList = getDaoTreatments().query(preparedQuery);
|
||||
if (trList.size() > 0) {
|
||||
// do nothing, pump history record cannot be changed
|
||||
return false;
|
||||
}
|
||||
getDaoTreatments().create(treatment);
|
||||
log.debug("TREATMENT: New record from: " + Source.getString(treatment.source) + " " + treatment.toString());
|
||||
updateEarliestDataChange(treatment.date);
|
||||
scheduleTreatmentChange();
|
||||
return true;
|
||||
}
|
||||
if (treatment.source == Source.NIGHTSCOUT) {
|
||||
old = getDaoTreatments().queryForId(treatment.date);
|
||||
if (old != null) {
|
||||
if (!old.isEqual(treatment)) {
|
||||
boolean historyChange = old.isDataChanging(treatment);
|
||||
long oldDate = old.date;
|
||||
getDaoTreatments().delete(old); // need to delete/create because date may change too
|
||||
old.copyFrom(treatment);
|
||||
getDaoTreatments().create(old);
|
||||
log.debug("TREATMENT: Updating record by date from: " + Source.getString(treatment.source) + " " + old.toString());
|
||||
if (historyChange) {
|
||||
updateEarliestDataChange(oldDate);
|
||||
updateEarliestDataChange(old.date);
|
||||
}
|
||||
scheduleTreatmentChange();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// find by NS _id
|
||||
if (treatment._id != null) {
|
||||
QueryBuilder<Treatment, Long> queryBuilder = getDaoTreatments().queryBuilder();
|
||||
Where where = queryBuilder.where();
|
||||
where.eq("_id", treatment._id);
|
||||
PreparedQuery<Treatment> preparedQuery = queryBuilder.prepare();
|
||||
List<Treatment> trList = getDaoTreatments().query(preparedQuery);
|
||||
if (trList.size() > 0) {
|
||||
old = trList.get(0);
|
||||
if (!old.isEqual(treatment)) {
|
||||
boolean historyChange = old.isDataChanging(treatment);
|
||||
long oldDate = old.date;
|
||||
getDaoTreatments().delete(old); // need to delete/create because date may change too
|
||||
old.copyFrom(treatment);
|
||||
getDaoTreatments().create(old);
|
||||
log.debug("TREATMENT: Updating record by _id from: " + Source.getString(treatment.source) + " " + old.toString());
|
||||
if (historyChange) {
|
||||
updateEarliestDataChange(oldDate);
|
||||
updateEarliestDataChange(old.date);
|
||||
}
|
||||
scheduleTreatmentChange();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
getDaoTreatments().create(treatment);
|
||||
log.debug("TREATMENT: New record from: " + Source.getString(treatment.source) + " " + treatment.toString());
|
||||
updateEarliestDataChange(treatment.date);
|
||||
scheduleTreatmentChange();
|
||||
return true;
|
||||
}
|
||||
if (treatment.source == Source.USER) {
|
||||
getDaoTreatments().create(treatment);
|
||||
log.debug("TREATMENT: New record from: " + Source.getString(treatment.source) + " " + treatment.toString());
|
||||
updateEarliestDataChange(treatment.date);
|
||||
scheduleTreatmentChange();
|
||||
return true;
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void delete(Treatment treatment) {
|
||||
try {
|
||||
getDaoTreatments().delete(treatment);
|
||||
updateEarliestDataChange(treatment.date);
|
||||
} catch (SQLException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
scheduleTreatmentChange();
|
||||
}
|
||||
|
||||
public void update(Treatment treatment) {
|
||||
try {
|
||||
getDaoTreatments().update(treatment);
|
||||
updateEarliestDataChange(treatment.date);
|
||||
} catch (SQLException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
scheduleTreatmentChange();
|
||||
}
|
||||
|
||||
public void deleteTreatmentById(String _id) {
|
||||
Treatment stored = findTreatmentById(_id);
|
||||
if (stored != null) {
|
||||
log.debug("TREATMENT: Removing Treatment record from database: " + stored.toString());
|
||||
delete(stored);
|
||||
updateEarliestDataChange(stored.date);
|
||||
scheduleTreatmentChange();
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Treatment findTreatmentById(String _id) {
|
||||
try {
|
||||
Dao<Treatment, Long> daoTreatments = getDaoTreatments();
|
||||
QueryBuilder<Treatment, Long> queryBuilder = daoTreatments.queryBuilder();
|
||||
Where where = queryBuilder.where();
|
||||
where.eq("_id", _id);
|
||||
queryBuilder.limit(10L);
|
||||
PreparedQuery<Treatment> preparedQuery = queryBuilder.prepare();
|
||||
List<Treatment> trList = daoTreatments.query(preparedQuery);
|
||||
if (trList.size() != 1) {
|
||||
//log.debug("Treatment findTreatmentById query size: " + trList.size());
|
||||
return null;
|
||||
} else {
|
||||
//log.debug("Treatment findTreatmentById found: " + trList.get(0).log());
|
||||
return trList.get(0);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void updateEarliestDataChange(long newDate) {
|
||||
public static void updateEarliestDataChange(long newDate) {
|
||||
if (earliestDataChange == null) {
|
||||
earliestDataChange = newDate;
|
||||
return;
|
||||
|
@ -692,73 +547,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
}
|
||||
}
|
||||
|
||||
private static void scheduleTreatmentChange() {
|
||||
class PostRunnable implements Runnable {
|
||||
public void run() {
|
||||
log.debug("Firing EventTreatmentChange");
|
||||
MainApp.bus().post(new EventReloadTreatmentData(new EventTreatmentChange()));
|
||||
if (earliestDataChange != null)
|
||||
MainApp.bus().post(new EventNewHistoryData(earliestDataChange));
|
||||
earliestDataChange = null;
|
||||
scheduledTratmentPost = null;
|
||||
}
|
||||
}
|
||||
// prepare task for execution in 1 sec
|
||||
// cancel waiting task to prevent sending multiple posts
|
||||
if (scheduledTratmentPost != null)
|
||||
scheduledTratmentPost.cancel(false);
|
||||
Runnable task = new PostRunnable();
|
||||
final int sec = 1;
|
||||
scheduledTratmentPost = treatmentsWorker.schedule(task, sec, TimeUnit.SECONDS);
|
||||
|
||||
}
|
||||
|
||||
public List<Treatment> getTreatmentDataFromTime(long mills, boolean ascending) {
|
||||
try {
|
||||
Dao<Treatment, Long> daoTreatments = getDaoTreatments();
|
||||
List<Treatment> treatments;
|
||||
QueryBuilder<Treatment, Long> queryBuilder = daoTreatments.queryBuilder();
|
||||
queryBuilder.orderBy("date", ascending);
|
||||
Where where = queryBuilder.where();
|
||||
where.ge("date", mills);
|
||||
PreparedQuery<Treatment> preparedQuery = queryBuilder.prepare();
|
||||
treatments = daoTreatments.query(preparedQuery);
|
||||
return treatments;
|
||||
} catch (SQLException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
return new ArrayList<Treatment>();
|
||||
}
|
||||
|
||||
public void createTreatmentFromJsonIfNotExists(JSONObject trJson) {
|
||||
try {
|
||||
Treatment treatment = new Treatment();
|
||||
treatment.source = Source.NIGHTSCOUT;
|
||||
treatment.date = roundDateToSec(trJson.getLong("mills"));
|
||||
treatment.carbs = trJson.has("carbs") ? trJson.getDouble("carbs") : 0;
|
||||
treatment.insulin = trJson.has("insulin") ? trJson.getDouble("insulin") : 0d;
|
||||
treatment.pumpId = trJson.has("pumpId") ? trJson.getLong("pumpId") : 0;
|
||||
treatment._id = trJson.getString("_id");
|
||||
if (trJson.has("isSMB"))
|
||||
treatment.isSMB = trJson.getBoolean("isSMB");
|
||||
if (trJson.has("eventType")) {
|
||||
treatment.mealBolus = !trJson.get("eventType").equals("Correction Bolus");
|
||||
double carbs = treatment.carbs;
|
||||
if (trJson.has("boluscalc")) {
|
||||
JSONObject boluscalc = trJson.getJSONObject("boluscalc");
|
||||
if (boluscalc.has("carbs")) {
|
||||
carbs = Math.max(boluscalc.getDouble("carbs"), carbs);
|
||||
}
|
||||
}
|
||||
if (carbs <= 0)
|
||||
treatment.mealBolus = false;
|
||||
}
|
||||
createOrUpdate(treatment);
|
||||
} catch (JSONException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------- TempTargets handling ---------------
|
||||
|
||||
public List<TempTarget> getTemptargetsDataFromTime(long mills, boolean ascending) {
|
||||
|
@ -876,15 +664,15 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
|
||||
public void createTemptargetFromJsonIfNotExists(JSONObject trJson) {
|
||||
try {
|
||||
String units = MainApp.getConfigBuilder().getProfileUnits();
|
||||
TempTarget tempTarget = new TempTarget();
|
||||
tempTarget.date = trJson.getLong("mills");
|
||||
tempTarget.durationInMinutes = trJson.getInt("duration");
|
||||
tempTarget.low = Profile.toMgdl(trJson.getDouble("targetBottom"), units);
|
||||
tempTarget.high = Profile.toMgdl(trJson.getDouble("targetTop"), units);
|
||||
tempTarget.reason = trJson.getString("reason");
|
||||
tempTarget._id = trJson.getString("_id");
|
||||
tempTarget.source = Source.NIGHTSCOUT;
|
||||
String units = JsonHelper.safeGetString(trJson, "units", MainApp.getConfigBuilder().getProfileUnits());
|
||||
TempTarget tempTarget = new TempTarget()
|
||||
.date(trJson.getLong("mills"))
|
||||
.duration(trJson.getInt("duration"))
|
||||
.low(Profile.toMgdl(trJson.getDouble("targetBottom"), units))
|
||||
.high(Profile.toMgdl(trJson.getDouble("targetTop"), units))
|
||||
.reason(trJson.getString("reason"))
|
||||
._id(trJson.getString("_id"))
|
||||
.source(Source.NIGHTSCOUT);
|
||||
createOrUpdate(tempTarget);
|
||||
} catch (JSONException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
|
@ -924,6 +712,12 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
public void createOrUpdate(DanaRHistoryRecord record) {
|
||||
try {
|
||||
getDaoDanaRHistory().createOrUpdate(record);
|
||||
|
||||
//If it is a TDD, store it for stats also.
|
||||
if (record.recordCode == RecordTypes.RECORD_TYPE_DAILY) {
|
||||
createOrUpdateTDD(new TDD(record.recordDate, record.recordDailyBolus, record.recordDailyBasal, 0));
|
||||
}
|
||||
|
||||
} catch (SQLException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
|
@ -1153,10 +947,10 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
}
|
||||
createOrUpdate(extendedBolus);
|
||||
} else {
|
||||
TemporaryBasal tempBasal = new TemporaryBasal();
|
||||
tempBasal.date = trJson.getLong("mills");
|
||||
tempBasal.source = Source.NIGHTSCOUT;
|
||||
tempBasal.pumpId = trJson.has("pumpId") ? trJson.getLong("pumpId") : 0;
|
||||
TemporaryBasal tempBasal = new TemporaryBasal()
|
||||
.date(trJson.getLong("mills"))
|
||||
.source(Source.NIGHTSCOUT)
|
||||
.pumpId(trJson.has("pumpId") ? trJson.getLong("pumpId") : 0);
|
||||
if (trJson.has("duration")) {
|
||||
tempBasal.durationInMinutes = trJson.getInt("duration");
|
||||
}
|
||||
|
@ -1360,37 +1154,10 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
}
|
||||
*/
|
||||
|
||||
public void createExtendedBolusFromJsonIfNotExists(JSONObject trJson) {
|
||||
try {
|
||||
QueryBuilder<ExtendedBolus, Long> queryBuilder = null;
|
||||
queryBuilder = getDaoExtendedBolus().queryBuilder();
|
||||
Where where = queryBuilder.where();
|
||||
where.eq("_id", trJson.getString("_id")).or().eq("date", trJson.getLong("mills"));
|
||||
PreparedQuery<ExtendedBolus> preparedQuery = queryBuilder.prepare();
|
||||
List<ExtendedBolus> list = getDaoExtendedBolus().query(preparedQuery);
|
||||
ExtendedBolus extendedBolus;
|
||||
if (list.size() == 0) {
|
||||
extendedBolus = new ExtendedBolus();
|
||||
extendedBolus.source = Source.NIGHTSCOUT;
|
||||
if (Config.logIncommingData)
|
||||
log.debug("Adding ExtendedBolus record to database: " + trJson.toString());
|
||||
// Record does not exists. add
|
||||
} else if (list.size() == 1) {
|
||||
extendedBolus = list.get(0);
|
||||
if (Config.logIncommingData)
|
||||
log.debug("Updating ExtendedBolus record in database: " + trJson.toString());
|
||||
} else {
|
||||
log.error("Something went wrong");
|
||||
return;
|
||||
}
|
||||
extendedBolus.date = trJson.getLong("mills");
|
||||
extendedBolus.durationInMinutes = trJson.has("duration") ? trJson.getInt("duration") : 0;
|
||||
extendedBolus.insulin = trJson.getDouble("relative");
|
||||
extendedBolus._id = trJson.getString("_id");
|
||||
public void createExtendedBolusFromJsonIfNotExists(JSONObject json) {
|
||||
ExtendedBolus extendedBolus = ExtendedBolus.createFromJson(json);
|
||||
if (extendedBolus != null)
|
||||
createOrUpdate(extendedBolus);
|
||||
} catch (SQLException | JSONException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void scheduleExtendedBolusChange() {
|
||||
|
@ -1436,6 +1203,15 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
scheduleCareportalEventChange();
|
||||
}
|
||||
|
||||
public CareportalEvent getCareportalEventFromTimestamp(long timestamp) {
|
||||
try {
|
||||
return getDaoCareportalEvents().queryForId(timestamp);
|
||||
} catch (SQLException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public CareportalEvent getLastCareportalEvent(String event) {
|
||||
try {
|
||||
|
@ -1489,7 +1265,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
|
||||
public void deleteCareportalEventById(String _id) {
|
||||
try {
|
||||
QueryBuilder<CareportalEvent, Long> queryBuilder = null;
|
||||
QueryBuilder<CareportalEvent, Long> queryBuilder;
|
||||
queryBuilder = getDaoCareportalEvents().queryBuilder();
|
||||
Where where = queryBuilder.where();
|
||||
where.eq("_id", _id);
|
||||
|
@ -1512,7 +1288,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
|
||||
public void createCareportalEventFromJsonIfNotExists(JSONObject trJson) {
|
||||
try {
|
||||
QueryBuilder<CareportalEvent, Long> queryBuilder = null;
|
||||
QueryBuilder<CareportalEvent, Long> queryBuilder;
|
||||
queryBuilder = getDaoCareportalEvents().queryBuilder();
|
||||
Where where = queryBuilder.where();
|
||||
where.eq("_id", trJson.getString("_id")).or().eq("date", trJson.getLong("mills"));
|
||||
|
@ -1569,14 +1345,14 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
List<ProfileSwitch> profileSwitches;
|
||||
QueryBuilder<ProfileSwitch, Long> queryBuilder = daoProfileSwitch.queryBuilder();
|
||||
queryBuilder.orderBy("date", ascending);
|
||||
queryBuilder.limit(20L);
|
||||
queryBuilder.limit(100L);
|
||||
PreparedQuery<ProfileSwitch> preparedQuery = queryBuilder.prepare();
|
||||
profileSwitches = daoProfileSwitch.query(preparedQuery);
|
||||
return profileSwitches;
|
||||
} catch (SQLException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
return new ArrayList<ProfileSwitch>();
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
public boolean createOrUpdate(ProfileSwitch profileSwitch) {
|
||||
|
@ -1693,7 +1469,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
if (trJson.has("profileJson"))
|
||||
profileSwitch.profileJson = trJson.getString("profileJson");
|
||||
else {
|
||||
ProfileStore store = ConfigBuilderPlugin.getActiveProfileInterface().getProfile();
|
||||
ProfileStore store = MainApp.getConfigBuilder().getActiveProfileInterface().getProfile();
|
||||
Profile profile = store.getSpecificProfile(profileSwitch.profileName);
|
||||
if (profile != null) {
|
||||
profileSwitch.profileJson = profile.getData().toString();
|
||||
|
@ -1742,4 +1518,4 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
}
|
||||
|
||||
// ---------------- Food handling ---------------
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,24 +9,25 @@ import android.graphics.Color;
|
|||
import com.j256.ormlite.field.DatabaseField;
|
||||
import com.j256.ormlite.table.DatabaseTable;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Objects;
|
||||
|
||||
import info.nightscout.androidaps.Constants;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.data.Iob;
|
||||
import info.nightscout.androidaps.data.IobTotal;
|
||||
import info.nightscout.androidaps.data.Profile;
|
||||
import info.nightscout.androidaps.interfaces.InsulinInterface;
|
||||
import info.nightscout.androidaps.interfaces.Interval;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.Overview.graphExtensions.DataPointWithLabelInterface;
|
||||
import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLabelGraphSeries;
|
||||
import info.nightscout.androidaps.plugins.Treatments.Treatment;
|
||||
import info.nightscout.utils.DateUtil;
|
||||
import info.nightscout.utils.DecimalFormatter;
|
||||
import info.nightscout.utils.JsonHelper;
|
||||
import info.nightscout.utils.Round;
|
||||
|
||||
/**
|
||||
|
@ -91,6 +92,16 @@ public class ExtendedBolus implements Interval, DataPointWithLabelInterface {
|
|||
pumpId = t.pumpId;
|
||||
}
|
||||
|
||||
public static ExtendedBolus createFromJson(JSONObject json) {
|
||||
ExtendedBolus extendedBolus = new ExtendedBolus();
|
||||
extendedBolus.source = Source.NIGHTSCOUT;
|
||||
extendedBolus.date = JsonHelper.safeGetLong(json, "mills");
|
||||
extendedBolus.durationInMinutes = JsonHelper.safeGetInt(json, "duration");
|
||||
extendedBolus.insulin = JsonHelper.safeGetDouble(json, "relative") / 60 * extendedBolus.durationInMinutes;
|
||||
extendedBolus._id = JsonHelper.safeGetString(json, "_id");
|
||||
extendedBolus.pumpId = JsonHelper.safeGetLong(json, "pumpId");
|
||||
return extendedBolus;
|
||||
}
|
||||
// -------- Interval interface ---------
|
||||
|
||||
Long cuttedEnd = null;
|
||||
|
@ -285,4 +296,5 @@ public class ExtendedBolus implements Interval, DataPointWithLabelInterface {
|
|||
public int getColor() {
|
||||
return Color.CYAN;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,208 +0,0 @@
|
|||
package info.nightscout.androidaps.db;
|
||||
|
||||
import com.j256.ormlite.android.AndroidConnectionSource;
|
||||
import com.j256.ormlite.dao.Dao;
|
||||
import com.j256.ormlite.stmt.PreparedQuery;
|
||||
import com.j256.ormlite.stmt.QueryBuilder;
|
||||
import com.j256.ormlite.stmt.Where;
|
||||
import com.j256.ormlite.table.TableUtils;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.events.EventFoodDatabaseChanged;
|
||||
|
||||
/**
|
||||
* Created by mike on 24.09.2017.
|
||||
*/
|
||||
|
||||
public class FoodHelper {
|
||||
private static Logger log = LoggerFactory.getLogger(FoodHelper.class);
|
||||
|
||||
DatabaseHelper databaseHelper;
|
||||
|
||||
private static final ScheduledExecutorService foodEventWorker = Executors.newSingleThreadScheduledExecutor();
|
||||
private static ScheduledFuture<?> scheduledFoodEventPost = null;
|
||||
|
||||
public FoodHelper(DatabaseHelper databaseHelper) {
|
||||
this.databaseHelper = databaseHelper;
|
||||
}
|
||||
|
||||
private Dao<Food, Long> getDaoFood() throws SQLException {
|
||||
return databaseHelper.getDao(Food.class);
|
||||
}
|
||||
|
||||
public void resetFood() {
|
||||
try {
|
||||
TableUtils.dropTable(databaseHelper.getConnectionSource(), Food.class, true);
|
||||
TableUtils.createTableIfNotExists(databaseHelper.getConnectionSource(), Food.class);
|
||||
} catch (SQLException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
scheduleFoodChange();
|
||||
}
|
||||
|
||||
public List<Food> getFoodData() {
|
||||
try {
|
||||
Dao<Food, Long> daoFood = getDaoFood();
|
||||
List<Food> foods;
|
||||
QueryBuilder<Food, Long> queryBuilder = daoFood.queryBuilder();
|
||||
PreparedQuery<Food> preparedQuery = queryBuilder.prepare();
|
||||
foods = daoFood.query(preparedQuery);
|
||||
return foods;
|
||||
} catch (SQLException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
public boolean createOrUpdate(Food food) {
|
||||
try {
|
||||
// find by NS _id
|
||||
if (food._id != null && !food._id.equals("")) {
|
||||
Food old;
|
||||
|
||||
QueryBuilder<Food, Long> queryBuilder = getDaoFood().queryBuilder();
|
||||
Where where = queryBuilder.where();
|
||||
where.eq("_id", food._id);
|
||||
PreparedQuery<Food> preparedQuery = queryBuilder.prepare();
|
||||
List<Food> found = getDaoFood().query(preparedQuery);
|
||||
if (found.size() > 0) {
|
||||
old = found.get(0);
|
||||
if (!old.isEqual(food)) {
|
||||
getDaoFood().delete(old); // need to delete/create because date may change too
|
||||
old.copyFrom(food);
|
||||
getDaoFood().create(old);
|
||||
log.debug("FOOD: Updating record by _id: " + old.toString());
|
||||
scheduleFoodChange();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
getDaoFood().createOrUpdate(food);
|
||||
log.debug("FOOD: New record: " + food.toString());
|
||||
scheduleFoodChange();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void delete(Food food) {
|
||||
try {
|
||||
getDaoFood().delete(food);
|
||||
scheduleFoodChange();
|
||||
} catch (SQLException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void scheduleFoodChange() {
|
||||
class PostRunnable implements Runnable {
|
||||
public void run() {
|
||||
log.debug("Firing EventFoodChange");
|
||||
MainApp.bus().post(new EventFoodDatabaseChanged());
|
||||
scheduledFoodEventPost = null;
|
||||
}
|
||||
}
|
||||
// prepare task for execution in 1 sec
|
||||
// cancel waiting task to prevent sending multiple posts
|
||||
if (scheduledFoodEventPost != null)
|
||||
scheduledFoodEventPost.cancel(false);
|
||||
Runnable task = new PostRunnable();
|
||||
final int sec = 1;
|
||||
scheduledFoodEventPost = foodEventWorker.schedule(task, sec, TimeUnit.SECONDS);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
{
|
||||
"_id": "551ee3ad368e06e80856e6a9",
|
||||
"type": "food",
|
||||
"category": "Zakladni",
|
||||
"subcategory": "Napoje",
|
||||
"name": "Mleko",
|
||||
"portion": 250,
|
||||
"carbs": 12,
|
||||
"gi": 1,
|
||||
"created_at": "2015-04-14T06:59:16.500Z",
|
||||
"unit": "ml"
|
||||
}
|
||||
*/
|
||||
public void createFoodFromJsonIfNotExists(JSONObject trJson) {
|
||||
try {
|
||||
Food food = new Food();
|
||||
if (trJson.has("type") && trJson.getString("type").equals("food")) {
|
||||
if (trJson.has("_id"))
|
||||
food._id = trJson.getString("_id");
|
||||
if (trJson.has("category"))
|
||||
food.category = trJson.getString("category");
|
||||
if (trJson.has("subcategory"))
|
||||
food.subcategory = trJson.getString("subcategory");
|
||||
if (trJson.has("name"))
|
||||
food.name = trJson.getString("name");
|
||||
if (trJson.has("unit"))
|
||||
food.units = trJson.getString("unit");
|
||||
if (trJson.has("portion"))
|
||||
food.portion = trJson.getDouble("portion");
|
||||
if (trJson.has("carbs"))
|
||||
food.carbs = trJson.getInt("carbs");
|
||||
if (trJson.has("gi"))
|
||||
food.gi = trJson.getInt("gi");
|
||||
if (trJson.has("energy"))
|
||||
food.energy = trJson.getInt("energy");
|
||||
if (trJson.has("protein"))
|
||||
food.protein = trJson.getInt("protein");
|
||||
if (trJson.has("fat"))
|
||||
food.fat = trJson.getInt("fat");
|
||||
}
|
||||
createOrUpdate(food);
|
||||
} catch (JSONException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteFoodById(String _id) {
|
||||
Food stored = findFoodById(_id);
|
||||
if (stored != null) {
|
||||
log.debug("FOOD: Removing Food record from database: " + stored.toString());
|
||||
delete(stored);
|
||||
scheduleFoodChange();
|
||||
}
|
||||
}
|
||||
|
||||
public Food findFoodById(String _id) {
|
||||
try {
|
||||
QueryBuilder<Food, Long> queryBuilder = getDaoFood().queryBuilder();
|
||||
Where where = queryBuilder.where();
|
||||
where.eq("_id", _id);
|
||||
PreparedQuery<Food> preparedQuery = queryBuilder.prepare();
|
||||
List<Food> list = getDaoFood().query(preparedQuery);
|
||||
|
||||
if (list.size() == 1) {
|
||||
return list.get(0);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package info.nightscout.androidaps.db;
|
||||
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
|
||||
/**
|
||||
* Created by triplem on 05.01.18.
|
||||
*/
|
||||
|
||||
public interface ICallback {
|
||||
|
||||
void setPost(ScheduledFuture<?> post);
|
||||
|
||||
ScheduledFuture<?> getPost();
|
||||
|
||||
}
|
|
@ -61,6 +61,31 @@ public class ProfileSwitch implements Interval, DataPointWithLabelInterface {
|
|||
|
||||
private Profile profile = null;
|
||||
|
||||
public ProfileSwitch date(long date) {
|
||||
this.date = date;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ProfileSwitch profileName(String profileName) {
|
||||
this.profileName = profileName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ProfileSwitch profile(Profile profile) {
|
||||
this.profile = profile;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ProfileSwitch source(int source) {
|
||||
this.source = source;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ProfileSwitch duration(int duration) {
|
||||
this.durationInMinutes = duration;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Profile getProfileObject() {
|
||||
if (profile == null)
|
||||
|
|
46
app/src/main/java/info/nightscout/androidaps/db/TDD.java
Normal file
46
app/src/main/java/info/nightscout/androidaps/db/TDD.java
Normal file
|
@ -0,0 +1,46 @@
|
|||
package info.nightscout.androidaps.db;
|
||||
|
||||
import com.j256.ormlite.field.DatabaseField;
|
||||
import com.j256.ormlite.table.DatabaseTable;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Created by mike on 20.09.2017.
|
||||
*/
|
||||
|
||||
|
||||
@DatabaseTable(tableName = DatabaseHelper.DATABASE_TDDS)
|
||||
public class TDD {
|
||||
private static Logger log = LoggerFactory.getLogger(TDD.class);
|
||||
|
||||
@DatabaseField(id = true)
|
||||
public long date;
|
||||
|
||||
@DatabaseField
|
||||
public double bolus;
|
||||
|
||||
@DatabaseField
|
||||
public double basal;
|
||||
|
||||
@DatabaseField
|
||||
public double total;
|
||||
|
||||
|
||||
public double getTotal(){
|
||||
return (total > 0d) ? total:(bolus+basal);
|
||||
}
|
||||
|
||||
|
||||
public TDD() { }
|
||||
|
||||
public TDD(long date, double bolus, double basal, double total){
|
||||
this.date = date;
|
||||
this.bolus = bolus;
|
||||
this.basal = basal;
|
||||
this.total = total;
|
||||
}
|
||||
}
|
|
@ -41,6 +41,10 @@ public class TempTarget implements Interval {
|
|||
@DatabaseField
|
||||
public int durationInMinutes;
|
||||
|
||||
public double target() {
|
||||
return (low + high) / 2;
|
||||
}
|
||||
|
||||
public boolean isEqual(TempTarget other) {
|
||||
if (date != other.date) {
|
||||
return false;
|
||||
|
@ -67,6 +71,41 @@ public class TempTarget implements Interval {
|
|||
reason = t.reason;
|
||||
}
|
||||
|
||||
public TempTarget date(long date) {
|
||||
this.date = date;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TempTarget low(double low) {
|
||||
this.low = low;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TempTarget high(double high) {
|
||||
this.high = high;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TempTarget duration(int duration) {
|
||||
this.durationInMinutes = duration;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TempTarget reason(String reason) {
|
||||
this.reason = reason;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TempTarget _id(String _id) {
|
||||
this._id = _id;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TempTarget source(int source) {
|
||||
this.source = source;
|
||||
return this;
|
||||
}
|
||||
|
||||
// -------- Interval interface ---------
|
||||
|
||||
Long cuttedEnd = null;
|
||||
|
|
|
@ -6,7 +6,6 @@ import com.j256.ormlite.table.DatabaseTable;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Objects;
|
||||
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
|
@ -17,6 +16,7 @@ import info.nightscout.androidaps.data.Profile;
|
|||
import info.nightscout.androidaps.interfaces.InsulinInterface;
|
||||
import info.nightscout.androidaps.interfaces.Interval;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.Treatments.Treatment;
|
||||
import info.nightscout.utils.DateUtil;
|
||||
import info.nightscout.utils.DecimalFormatter;
|
||||
import info.nightscout.utils.SP;
|
||||
|
@ -60,8 +60,36 @@ public class TemporaryBasal implements Interval {
|
|||
public TemporaryBasal() {
|
||||
}
|
||||
|
||||
public TemporaryBasal(long date) {
|
||||
public TemporaryBasal date(long date) {
|
||||
this.date = date;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TemporaryBasal duration(int durationInMinutes) {
|
||||
this.durationInMinutes = durationInMinutes;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TemporaryBasal absolute(double absoluteRate) {
|
||||
this.absoluteRate = absoluteRate;
|
||||
this.isAbsolute = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TemporaryBasal percent(int percentRate) {
|
||||
this.percentRate = percentRate;
|
||||
this.isAbsolute = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TemporaryBasal source(int source) {
|
||||
this.source = source;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TemporaryBasal pumpId(long pumpId) {
|
||||
this.pumpId = pumpId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TemporaryBasal(ExtendedBolus extendedBolus) {
|
||||
|
@ -189,7 +217,7 @@ public class TemporaryBasal implements Interval {
|
|||
|
||||
// -------- Interval interface end ---------
|
||||
|
||||
public IobTotal iobCalc(long time) {
|
||||
public IobTotal iobCalc(long time, Profile profile) {
|
||||
|
||||
if(isFakeExtended){
|
||||
log.error("iobCalc should only be called on Extended boluses separately");
|
||||
|
@ -197,7 +225,6 @@ public class TemporaryBasal implements Interval {
|
|||
}
|
||||
|
||||
IobTotal result = new IobTotal(time);
|
||||
Profile profile = MainApp.getConfigBuilder().getProfile(time);
|
||||
InsulinInterface insulinInterface = ConfigBuilderPlugin.getActiveInsulin();
|
||||
|
||||
int realDuration = getDurationToTime(time);
|
||||
|
@ -262,13 +289,13 @@ public class TemporaryBasal implements Interval {
|
|||
return (remainingMin < 0) ? 0 : Math.round(remainingMin);
|
||||
}
|
||||
|
||||
public double tempBasalConvertedToAbsolute(long time) {
|
||||
public double tempBasalConvertedToAbsolute(long time, Profile profile) {
|
||||
if(isFakeExtended){
|
||||
return MainApp.getConfigBuilder().getProfile(time).getBasal(time) + netExtendedRate;
|
||||
return profile.getBasal(time) + netExtendedRate;
|
||||
} else if (isAbsolute) {
|
||||
return absoluteRate;
|
||||
} else {
|
||||
return MainApp.getConfigBuilder().getProfile(time).getBasal(time) * percentRate / 100;
|
||||
return profile.getBasal(time) * percentRate / 100;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -325,13 +352,13 @@ public class TemporaryBasal implements Interval {
|
|||
if(profile != null) {
|
||||
double basal = profile.getBasal();
|
||||
if(basal != 0){
|
||||
return Math.round(rate*100d/basal) + "% ";
|
||||
return Math.round(rate*100d/basal) + "%";
|
||||
}
|
||||
}
|
||||
}
|
||||
return DecimalFormatter.to2Decimal(rate) + "U/h ";
|
||||
return DecimalFormatter.to2Decimal(rate) + "U/h";
|
||||
} else { // percent
|
||||
return percentRate + "% ";
|
||||
return percentRate + "%";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
package info.nightscout.androidaps.events;
|
||||
|
||||
public class EventChargingState {
|
||||
|
||||
public boolean isCharging = false;
|
||||
|
||||
public EventChargingState() {}
|
||||
|
||||
public EventChargingState(boolean isCharging) {
|
||||
this.isCharging = isCharging;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
package info.nightscout.androidaps.events;
|
||||
|
||||
/**
|
||||
* Created by mike on 13.02.2018.
|
||||
*/
|
||||
|
||||
public class EventCustomCalculationFinished extends Event {
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package info.nightscout.androidaps.events;
|
||||
|
||||
/**
|
||||
* Created by jamorham on 07/02/2018.
|
||||
*
|
||||
* Event to indicate that an app feature is being used, for example bolus wizard being opened
|
||||
*
|
||||
* The purpose this has been created for is to enable opportunistic connection to the pump
|
||||
* so that it is already connected before the user wishes to enact a pump function
|
||||
*
|
||||
*/
|
||||
|
||||
public class EventFeatureRunning extends Event {
|
||||
|
||||
private Feature feature = Feature.UNKNOWN;
|
||||
|
||||
public EventFeatureRunning() {
|
||||
}
|
||||
|
||||
public EventFeatureRunning(Feature feature) {
|
||||
this.feature = feature;
|
||||
}
|
||||
|
||||
public Feature getFeature() {
|
||||
return feature;
|
||||
}
|
||||
|
||||
public enum Feature {
|
||||
UNKNOWN,
|
||||
MAIN,
|
||||
WIZARD,
|
||||
|
||||
JUST_ADD_MORE_HERE
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package info.nightscout.androidaps.events;
|
||||
|
||||
public class EventNetworkChange extends Event {
|
||||
|
||||
public boolean mobileConnected = false;
|
||||
public boolean wifiConnected = false;
|
||||
|
||||
public String ssid = "";
|
||||
public boolean roaming = false;
|
||||
|
||||
public String getSsid() {
|
||||
return ssid.replace("SSID: ","").replaceAll("\"","");
|
||||
}
|
||||
}
|
|
@ -1,7 +1,17 @@
|
|||
package info.nightscout.androidaps.events;
|
||||
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import info.nightscout.androidaps.db.BgReading;
|
||||
|
||||
/**
|
||||
* Created by mike on 05.06.2016.
|
||||
*/
|
||||
public class EventNewBG extends EventLoop {
|
||||
@Nullable
|
||||
public final BgReading bgReading;
|
||||
|
||||
public EventNewBG(BgReading bgReading) {
|
||||
this.bgReading = bgReading;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
package info.nightscout.androidaps.events;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
/**
|
||||
* Event which is published with data fetched from NightScout specific for the
|
||||
* Food-class.
|
||||
*
|
||||
* Payload is the from NS retrieved JSON-String which should be handled by all
|
||||
* subscriber.
|
||||
*/
|
||||
|
||||
public class EventNsFood extends Event {
|
||||
|
||||
public static final int ADD = 0;
|
||||
public static final int UPDATE = 1;
|
||||
public static final int REMOVE = 2;
|
||||
|
||||
private final int mode;
|
||||
|
||||
private final Bundle payload;
|
||||
|
||||
public EventNsFood(int mode, Bundle payload) {
|
||||
this.mode = mode;
|
||||
this.payload = payload;
|
||||
}
|
||||
|
||||
public int getMode() {
|
||||
return mode;
|
||||
}
|
||||
|
||||
public Bundle getPayload() {
|
||||
return payload;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package info.nightscout.androidaps.events;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
|
||||
/**
|
||||
* Event which is published with data fetched from NightScout specific for the
|
||||
* Treatment-class.
|
||||
* <p>
|
||||
* Payload is the from NS retrieved JSON-String which should be handled by all
|
||||
* subscriber.
|
||||
*/
|
||||
|
||||
public class EventNsTreatment extends Event {
|
||||
|
||||
public static final int ADD = 0;
|
||||
public static final int UPDATE = 1;
|
||||
public static final int REMOVE = 2;
|
||||
|
||||
private final int mode;
|
||||
|
||||
private final JSONObject payload;
|
||||
|
||||
public EventNsTreatment(int mode, JSONObject payload) {
|
||||
this.mode = mode;
|
||||
this.payload = payload;
|
||||
}
|
||||
|
||||
public int getMode() {
|
||||
return mode;
|
||||
}
|
||||
|
||||
public JSONObject getPayload() {
|
||||
return payload;
|
||||
}
|
||||
}
|
|
@ -12,11 +12,11 @@ public class EventPreferenceChange extends Event {
|
|||
}
|
||||
|
||||
public EventPreferenceChange(int resourceID) {
|
||||
changedKey = MainApp.sResources.getString(resourceID);
|
||||
changedKey = MainApp.gs(resourceID);
|
||||
}
|
||||
|
||||
public boolean isChanged(int id) {
|
||||
return changedKey.equals(MainApp.sResources.getString(id));
|
||||
return changedKey.equals(MainApp.gs(id));
|
||||
}
|
||||
|
||||
public boolean isChanged(String id) {
|
||||
|
|
|
@ -46,13 +46,13 @@ public class EventPumpStatusChanged extends Event {
|
|||
|
||||
public String textStatus() {
|
||||
if (sStatus == CONNECTING)
|
||||
return String.format(MainApp.sResources.getString(R.string.danar_history_connectingfor), sSecondsElapsed);
|
||||
return String.format(MainApp.gs(R.string.danar_history_connectingfor), sSecondsElapsed);
|
||||
else if (sStatus == CONNECTED)
|
||||
return MainApp.sResources.getString(R.string.connected);
|
||||
return MainApp.gs(R.string.connected);
|
||||
else if (sStatus == PERFORMING)
|
||||
return sPerfomingAction;
|
||||
else if (sStatus == DISCONNECTING)
|
||||
return MainApp.sResources.getString(R.string.disconnecting);
|
||||
return MainApp.gs(R.string.disconnecting);
|
||||
else if (sStatus == DISCONNECTED)
|
||||
return "";
|
||||
return "";
|
||||
|
|
|
@ -1,7 +1,17 @@
|
|||
package info.nightscout.androidaps.events;
|
||||
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import info.nightscout.androidaps.plugins.Treatments.Treatment;
|
||||
|
||||
/**
|
||||
* Created by mike on 04.06.2016.
|
||||
*/
|
||||
public class EventTreatmentChange extends EventLoop {
|
||||
@Nullable
|
||||
public final Treatment treatment;
|
||||
|
||||
public EventTreatmentChange(Treatment treatment) {
|
||||
this.treatment = treatment;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,5 +11,5 @@ public interface APSInterface {
|
|||
public APSResult getLastAPSResult();
|
||||
public Date getLastAPSRun();
|
||||
|
||||
public void invoke(String initiator);
|
||||
public void invoke(String initiator, boolean tempBasalFallback);
|
||||
}
|
||||
|
|
|
@ -4,4 +4,5 @@ package info.nightscout.androidaps.interfaces;
|
|||
* Created by mike on 20.06.2016.
|
||||
*/
|
||||
public interface BgSourceInterface {
|
||||
boolean advancedFilteringSupported();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
package info.nightscout.androidaps.interfaces;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by mike on 19.03.2018.
|
||||
*/
|
||||
|
||||
public class Constraint<T extends Comparable> {
|
||||
private static Logger log = LoggerFactory.getLogger(Constraint.class);
|
||||
|
||||
T value;
|
||||
T originalValue;
|
||||
|
||||
List<String> reasons = new ArrayList<>();
|
||||
List<String> mostLimiting = new ArrayList<>();
|
||||
|
||||
public Constraint(T value) {
|
||||
this.value = value;
|
||||
this.originalValue = value;
|
||||
}
|
||||
|
||||
public T value() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public T originalValue() {
|
||||
return originalValue;
|
||||
}
|
||||
|
||||
public Constraint<T> set(T value) {
|
||||
this.value = value;
|
||||
this.originalValue = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Constraint<T> set(T value, String reason, Object from) {
|
||||
this.value = value;
|
||||
addReason(reason, from);
|
||||
addMostLimingReason(reason, from);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Constraint<T> setIfSmaller(T value, String reason, Object from) {
|
||||
if (value.compareTo(this.value) < 0) {
|
||||
this.value = value;
|
||||
mostLimiting.clear();
|
||||
addMostLimingReason(reason, from);
|
||||
}
|
||||
if (value.compareTo(this.originalValue) < 0) {
|
||||
addReason(reason, from);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Constraint<T> setIfGreater(T value, String reason, Object from) {
|
||||
if (value.compareTo(this.value) > 0) {
|
||||
this.value = value;
|
||||
mostLimiting.clear();
|
||||
addMostLimingReason(reason, from);
|
||||
}
|
||||
if (value.compareTo(this.originalValue) > 0) {
|
||||
addReason(reason, from);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Constraint addReason(String reason, Object from) {
|
||||
reasons.add(from.getClass().getSimpleName().replace("Plugin", "") + ": " + reason);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Constraint addMostLimingReason(String reason, Object from) {
|
||||
mostLimiting.add(from.getClass().getSimpleName().replace("Plugin", "") + ": " + reason);
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getReasons() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int count = 0;
|
||||
for (String r : reasons) {
|
||||
if (count++ != 0) sb.append("\n");
|
||||
sb.append(r);
|
||||
}
|
||||
log.debug("Limiting origial value: " + originalValue + " to " + value + ". Reason: " + sb.toString());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public List<String> getReasonList() {
|
||||
return reasons;
|
||||
}
|
||||
|
||||
public String getMostLimitedReasons() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int count = 0;
|
||||
for (String r : mostLimiting) {
|
||||
if (count++ != 0) sb.append("\n");
|
||||
sb.append(r);
|
||||
}
|
||||
log.debug("Limiting origial value: " + originalValue + " to " + value + ". Reason: " + sb.toString());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public List<String> getMostLimitedReasonList() {
|
||||
return mostLimiting;
|
||||
}
|
||||
|
||||
public void copyReasons(Constraint<?> another) {
|
||||
for (String s: another.getReasonList()) {
|
||||
reasons.add(s);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,30 +1,54 @@
|
|||
package info.nightscout.androidaps.interfaces;
|
||||
|
||||
import info.nightscout.androidaps.plugins.Loop.APSResult;
|
||||
import info.nightscout.androidaps.data.Profile;
|
||||
|
||||
/**
|
||||
* Created by mike on 15.06.2016.
|
||||
*/
|
||||
public interface ConstraintsInterface {
|
||||
|
||||
boolean isLoopEnabled();
|
||||
default Constraint<Boolean> isLoopInvokationAllowed(Constraint<Boolean> value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
boolean isClosedModeEnabled();
|
||||
default Constraint<Boolean> isClosedLoopAllowed(Constraint<Boolean> value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
boolean isAutosensModeEnabled();
|
||||
default Constraint<Boolean> isAutosensModeEnabled(Constraint<Boolean> value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
boolean isAMAModeEnabled();
|
||||
default Constraint<Boolean> isAMAModeEnabled(Constraint<Boolean> value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
boolean isSMBModeEnabled();
|
||||
default Constraint<Boolean> isSMBModeEnabled(Constraint<Boolean> value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
Double applyBasalConstraints(Double absoluteRate);
|
||||
default Constraint<Boolean> isAdvancedFilteringEnabled(Constraint<Boolean> value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
Integer applyBasalConstraints(Integer percentRate);
|
||||
default Constraint<Double> applyBasalConstraints(Constraint<Double> absoluteRate, Profile profile) {
|
||||
return absoluteRate;
|
||||
}
|
||||
|
||||
Double applyBolusConstraints(Double insulin);
|
||||
default Constraint<Integer> applyBasalPercentConstraints(Constraint<Integer> percentRate, Profile profile) {
|
||||
return percentRate;
|
||||
}
|
||||
|
||||
Integer applyCarbsConstraints(Integer carbs);
|
||||
default Constraint<Double> applyBolusConstraints(Constraint<Double> insulin) {
|
||||
return insulin;
|
||||
}
|
||||
|
||||
Double applyMaxIOBConstraints(Double maxIob);
|
||||
default Constraint<Integer> applyCarbsConstraints(Constraint<Integer> carbs) {
|
||||
return carbs;
|
||||
}
|
||||
|
||||
default Constraint<Double> applyMaxIOBConstraints(Constraint<Double> maxIob) {
|
||||
return maxIob;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,25 +1,23 @@
|
|||
package info.nightscout.androidaps.interfaces;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import info.nightscout.androidaps.data.Iob;
|
||||
import info.nightscout.androidaps.db.Treatment;
|
||||
import info.nightscout.androidaps.plugins.Treatments.Treatment;
|
||||
|
||||
/**
|
||||
* Created by mike on 17.04.2017.
|
||||
*/
|
||||
|
||||
public interface InsulinInterface {
|
||||
final int FASTACTINGINSULIN = 0;
|
||||
final int FASTACTINGINSULINPROLONGED = 1;
|
||||
final int OREF_RAPID_ACTING = 2;
|
||||
final int OREF_ULTRA_RAPID_ACTING = 3;
|
||||
final int OREF_FREE_PEAK = 4;
|
||||
int FASTACTINGINSULIN = 0;
|
||||
int FASTACTINGINSULINPROLONGED = 1;
|
||||
int OREF_RAPID_ACTING = 2;
|
||||
int OREF_ULTRA_RAPID_ACTING = 3;
|
||||
int OREF_FREE_PEAK = 4;
|
||||
|
||||
|
||||
int getId();
|
||||
String getFriendlyName();
|
||||
String getComment();
|
||||
double getDia();
|
||||
public Iob iobCalcForTreatment(Treatment treatment, long time, double dia);
|
||||
Iob iobCalcForTreatment(Treatment treatment, long time, double dia);
|
||||
}
|
||||
|
|
|
@ -1,34 +1,165 @@
|
|||
package info.nightscout.androidaps.interfaces;
|
||||
|
||||
import java.util.Date;
|
||||
import android.os.SystemClock;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||
|
||||
/**
|
||||
* Created by mike on 09.06.2016.
|
||||
*/
|
||||
public interface PluginBase {
|
||||
int GENERAL = 1;
|
||||
int TREATMENT = 2;
|
||||
int SENSITIVITY = 3;
|
||||
int PROFILE = 4;
|
||||
int APS = 5;
|
||||
int PUMP = 6;
|
||||
int CONSTRAINTS = 7;
|
||||
int LOOP = 8;
|
||||
int BGSOURCE = 9;
|
||||
int INSULIN = 10;
|
||||
int LAST = 11; // keep always highest number
|
||||
public abstract class PluginBase {
|
||||
private static Logger log = LoggerFactory.getLogger(PluginBase.class);
|
||||
|
||||
int getType();
|
||||
String getFragmentClass();
|
||||
public enum State {
|
||||
NOT_INITIALIZED,
|
||||
ENABLED,
|
||||
DISABLED
|
||||
}
|
||||
|
||||
String getName();
|
||||
String getNameShort();
|
||||
boolean isEnabled(int type);
|
||||
boolean isVisibleInTabs(int type);
|
||||
boolean canBeHidden(int type);
|
||||
boolean hasFragment();
|
||||
boolean showInList(int type);
|
||||
void setFragmentEnabled(int type, boolean fragmentEnabled);
|
||||
void setFragmentVisible(int type, boolean fragmentVisible);
|
||||
int getPreferencesId();
|
||||
private State state = State.NOT_INITIALIZED;
|
||||
private boolean isFragmentVisible = false;
|
||||
public PluginDescription pluginDescription;
|
||||
|
||||
|
||||
// Specific plugin with more Interfaces
|
||||
protected boolean isProfileInterfaceEnabled = false;
|
||||
|
||||
public PluginBase(PluginDescription pluginDescription) {
|
||||
this.pluginDescription = pluginDescription;
|
||||
}
|
||||
|
||||
// public PluginType getType() {
|
||||
// return mainType;
|
||||
// }
|
||||
|
||||
// public String getFragmentClass() {
|
||||
// return fragmentClass;
|
||||
// }
|
||||
|
||||
public String getName() {
|
||||
if (pluginDescription.pluginName == -1)
|
||||
return "UKNOWN";
|
||||
else
|
||||
return MainApp.gs(pluginDescription.pluginName);
|
||||
}
|
||||
|
||||
public String getNameShort() {
|
||||
if (pluginDescription.shortName == -1)
|
||||
return getName();
|
||||
String name = MainApp.gs(pluginDescription.shortName);
|
||||
if (!name.trim().isEmpty()) //only if translation exists
|
||||
return name;
|
||||
// use long name as fallback
|
||||
return getName();
|
||||
}
|
||||
|
||||
public PluginType getType() {
|
||||
return pluginDescription.mainType;
|
||||
}
|
||||
|
||||
public int getPreferencesId() {
|
||||
return pluginDescription.preferencesId;
|
||||
}
|
||||
|
||||
public int getAdvancedPreferencesId() {
|
||||
return pluginDescription.advancedPreferencesId;
|
||||
}
|
||||
|
||||
public boolean isEnabled(PluginType type) {
|
||||
if (pluginDescription.alwaysEnabled && type == pluginDescription.mainType)
|
||||
return true;
|
||||
if (pluginDescription.mainType == PluginType.CONSTRAINTS && type == PluginType.CONSTRAINTS)
|
||||
return true;
|
||||
if (type == pluginDescription.mainType)
|
||||
return state == State.ENABLED && specialEnableCondition();
|
||||
if (type == PluginType.CONSTRAINTS && pluginDescription.mainType == PluginType.PUMP && isEnabled(PluginType.PUMP))
|
||||
return true;
|
||||
if (type == PluginType.PROFILE && pluginDescription.mainType == PluginType.PUMP)
|
||||
return isProfileInterfaceEnabled;
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean hasFragment() {
|
||||
return pluginDescription.fragmentClass != null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* So far plugin can have it's main type + ConstraintInterface + ProfileInterface
|
||||
* ConstraintInterface is enabled if main plugin is enabled
|
||||
* ProfileInterface can be enabled only if main iterface is enable
|
||||
*/
|
||||
|
||||
public void setPluginEnabled(PluginType type, boolean newState) {
|
||||
if (type == pluginDescription.mainType) {
|
||||
if (newState == true) { // enabling plugin
|
||||
if (state != State.ENABLED) {
|
||||
onStateChange(type, state, State.ENABLED);
|
||||
state = State.ENABLED;
|
||||
log.debug("Starting: " + getName());
|
||||
onStart();
|
||||
}
|
||||
} else { // disabling plugin
|
||||
if (state == State.ENABLED) {
|
||||
onStateChange(type, state, State.ENABLED);
|
||||
state = State.DISABLED;
|
||||
onStop();
|
||||
log.debug("Stopping: " + getName());
|
||||
}
|
||||
}
|
||||
} else if (type == PluginType.PROFILE) {
|
||||
isProfileInterfaceEnabled = newState;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void setFragmentVisible(PluginType type, boolean fragmentVisible) {
|
||||
if (type == pluginDescription.mainType) {
|
||||
isFragmentVisible = fragmentVisible && specialEnableCondition();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isFragmentVisible() {
|
||||
if (pluginDescription.alwayVisible)
|
||||
return true;
|
||||
if (pluginDescription.neverVisible)
|
||||
return false;
|
||||
return isFragmentVisible;
|
||||
}
|
||||
|
||||
public boolean showInList(PluginType type) {
|
||||
if (pluginDescription.mainType == type)
|
||||
return pluginDescription.showInList && specialShowInListCondition();
|
||||
|
||||
if (type == PluginType.PROFILE && pluginDescription.mainType == PluginType.PUMP)
|
||||
return isEnabled(PluginType.PUMP);
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean specialEnableCondition() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean specialShowInListCondition() {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void onStart() {
|
||||
if (getType() == PluginType.PUMP) {
|
||||
new Thread(() -> {
|
||||
SystemClock.sleep(3000);
|
||||
ConfigBuilderPlugin.getCommandQueue().readStatus("Pump driver changed.", null);
|
||||
}).start();
|
||||
}
|
||||
}
|
||||
|
||||
protected void onStop() {
|
||||
}
|
||||
|
||||
protected void onStateChange(PluginType type, State oldState, State newState) {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
package info.nightscout.androidaps.interfaces;
|
||||
|
||||
public class PluginDescription {
|
||||
PluginType mainType = PluginType.GENERAL;
|
||||
String fragmentClass = null;
|
||||
public boolean alwayVisible = false;
|
||||
public boolean neverVisible = false;
|
||||
public boolean alwaysEnabled = false;
|
||||
boolean showInList = true;
|
||||
int pluginName = -1;
|
||||
int shortName = -1;
|
||||
int preferencesId = -1;
|
||||
int advancedPreferencesId = -1;
|
||||
public boolean enableByDefault = false;
|
||||
public boolean visibleByDefault = false;
|
||||
|
||||
public PluginDescription mainType(PluginType mainType) {
|
||||
this.mainType = mainType;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PluginDescription fragmentClass(String fragmentClass) {
|
||||
this.fragmentClass = fragmentClass;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PluginDescription alwaysEnabled(boolean alwaysEnabled) {
|
||||
this.alwaysEnabled = alwaysEnabled;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PluginDescription alwayVisible(boolean alwayVisible) {
|
||||
this.alwayVisible = alwayVisible;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PluginDescription neverVisible(boolean neverVisible) {
|
||||
this.neverVisible = neverVisible;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PluginDescription showInList(boolean showInList) {
|
||||
this.showInList = showInList;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PluginDescription pluginName(int pluginName) {
|
||||
this.pluginName = pluginName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PluginDescription shortName(int shortName) {
|
||||
this.shortName = shortName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PluginDescription preferencesId(int preferencesId) {
|
||||
this.preferencesId = preferencesId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PluginDescription advancedPreferencesId(int advancedPreferencesId) {
|
||||
this.advancedPreferencesId = advancedPreferencesId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PluginDescription enableByDefault(boolean enableByDefault) {
|
||||
this.enableByDefault = enableByDefault;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PluginDescription visibleByDefault(boolean visibleByDefault) {
|
||||
this.visibleByDefault = visibleByDefault;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getFragmentClass() {
|
||||
return fragmentClass;
|
||||
}
|
||||
|
||||
public PluginType getType() {
|
||||
return mainType;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package info.nightscout.androidaps.interfaces;
|
||||
|
||||
public enum PluginType {
|
||||
GENERAL,
|
||||
TREATMENT,
|
||||
SENSITIVITY,
|
||||
PROFILE,
|
||||
APS,
|
||||
PUMP,
|
||||
CONSTRAINTS,
|
||||
LOOP,
|
||||
BGSOURCE,
|
||||
INSULIN
|
||||
}
|
|
@ -27,6 +27,8 @@ public class PumpDescription {
|
|||
public double tempAbsoluteStep = 0.05d;
|
||||
|
||||
public int tempDurationStep = 60;
|
||||
public boolean tempDurationStep15mAllowed = false;
|
||||
public boolean tempDurationStep30mAllowed = false;
|
||||
public int tempMaxDuration = 12 * 60;
|
||||
|
||||
|
||||
|
@ -37,4 +39,9 @@ public class PumpDescription {
|
|||
public boolean isRefillingCapable = false;
|
||||
|
||||
public boolean storesCarbInfo = true;
|
||||
|
||||
public boolean is30minBasalRatesCapable = false;
|
||||
|
||||
public boolean supportsTDDs = false;
|
||||
public boolean needsManualTDDLoad = true;
|
||||
}
|
||||
|
|
|
@ -5,8 +5,8 @@ import org.json.JSONObject;
|
|||
import java.util.Date;
|
||||
|
||||
import info.nightscout.androidaps.data.DetailedBolusInfo;
|
||||
import info.nightscout.androidaps.data.PumpEnactResult;
|
||||
import info.nightscout.androidaps.data.Profile;
|
||||
import info.nightscout.androidaps.data.PumpEnactResult;
|
||||
|
||||
/**
|
||||
* Created by mike on 04.06.2016.
|
||||
|
@ -35,8 +35,8 @@ public interface PumpInterface {
|
|||
|
||||
PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo);
|
||||
void stopBolusDelivering();
|
||||
PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean enforceNew);
|
||||
PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, boolean enforceNew);
|
||||
PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, Profile profile, boolean enforceNew);
|
||||
PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, Profile profile, boolean enforceNew);
|
||||
PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes);
|
||||
//some pumps might set a very short temp close to 100% as cancelling a temp can be noisy
|
||||
//when the cancel request is requested by the user (forced), the pump should always do a real cancel
|
||||
|
@ -44,7 +44,7 @@ public interface PumpInterface {
|
|||
PumpEnactResult cancelExtendedBolus();
|
||||
|
||||
// Status to be passed to NS
|
||||
JSONObject getJSONStatus();
|
||||
JSONObject getJSONStatus(Profile profile, String profileName);
|
||||
String deviceID();
|
||||
|
||||
// Pump capabilities
|
||||
|
@ -54,4 +54,7 @@ public interface PumpInterface {
|
|||
String shortStatus(boolean veryShort);
|
||||
|
||||
boolean isFakingTempsByExtendedBoluses();
|
||||
|
||||
PumpEnactResult loadTDDs();
|
||||
|
||||
}
|
||||
|
|
|
@ -5,11 +5,12 @@ import java.util.List;
|
|||
import info.nightscout.androidaps.data.DetailedBolusInfo;
|
||||
import info.nightscout.androidaps.data.IobTotal;
|
||||
import info.nightscout.androidaps.data.MealData;
|
||||
import info.nightscout.androidaps.data.Profile;
|
||||
import info.nightscout.androidaps.db.ExtendedBolus;
|
||||
import info.nightscout.androidaps.db.ProfileSwitch;
|
||||
import info.nightscout.androidaps.db.TempTarget;
|
||||
import info.nightscout.androidaps.db.TemporaryBasal;
|
||||
import info.nightscout.androidaps.db.Treatment;
|
||||
import info.nightscout.androidaps.plugins.Treatments.Treatment;
|
||||
import info.nightscout.androidaps.data.Intervals;
|
||||
import info.nightscout.androidaps.data.ProfileIntervals;
|
||||
|
||||
|
@ -24,12 +25,13 @@ public interface TreatmentsInterface {
|
|||
IobTotal getLastCalculationTreatments();
|
||||
IobTotal getCalculationToTimeTreatments(long time);
|
||||
IobTotal getLastCalculationTempBasals();
|
||||
IobTotal getCalculationToTimeTempBasals(long time);
|
||||
IobTotal getCalculationToTimeTempBasals(long time, Profile profile);
|
||||
|
||||
MealData getMealData();
|
||||
|
||||
List<Treatment> getTreatmentsFromHistory();
|
||||
List<Treatment> getTreatments5MinBackFromHistory(long time);
|
||||
long getLastBolusTime();
|
||||
|
||||
// real basals (not faked by extended bolus)
|
||||
boolean isInHistoryRealTempBasalInProgress();
|
||||
|
@ -40,8 +42,6 @@ public interface TreatmentsInterface {
|
|||
// basal that can be faked by extended boluses
|
||||
boolean isTempBasalInProgress();
|
||||
TemporaryBasal getTempBasalFromHistory(long time);
|
||||
double getTempBasalAbsoluteRateHistory();
|
||||
double getTempBasalRemainingMinutesFromHistory();
|
||||
Intervals<TemporaryBasal> getTemporaryBasalsFromHistory();
|
||||
|
||||
boolean isInHistoryExtendedBoluslInProgress();
|
||||
|
@ -55,6 +55,7 @@ public interface TreatmentsInterface {
|
|||
TempTarget getTempTargetFromHistory();
|
||||
TempTarget getTempTargetFromHistory(long time);
|
||||
Intervals<TempTarget> getTempTargetsFromHistory();
|
||||
void addToHistoryTempTarget(TempTarget tempTarget);
|
||||
|
||||
ProfileSwitch getProfileSwitchFromHistory(long time);
|
||||
ProfileIntervals<ProfileSwitch> getProfileSwitchesFromHistory();
|
||||
|
|
|
@ -2,6 +2,7 @@ package info.nightscout.androidaps.plugins.Actions;
|
|||
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
|
@ -9,14 +10,14 @@ import android.view.LayoutInflater;
|
|||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.crashlytics.android.Crashlytics;
|
||||
import com.crashlytics.android.answers.Answers;
|
||||
import com.crashlytics.android.answers.CustomEvent;
|
||||
import com.squareup.otto.Subscribe;
|
||||
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.HistoryBrowseActivity;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.TDDStatsActivity;
|
||||
import info.nightscout.androidaps.db.ExtendedBolus;
|
||||
import info.nightscout.androidaps.db.TemporaryBasal;
|
||||
import info.nightscout.androidaps.events.EventExtendedBolusChange;
|
||||
|
@ -32,6 +33,8 @@ import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialo
|
|||
import info.nightscout.androidaps.plugins.Careportal.OptionsToShow;
|
||||
import info.nightscout.androidaps.plugins.Common.SubscriberFragment;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
|
||||
import info.nightscout.utils.FabricPrivacy;
|
||||
import info.nightscout.utils.SingleClickButton;
|
||||
|
||||
/**
|
||||
|
@ -52,6 +55,8 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL
|
|||
SingleClickButton tempBasal;
|
||||
SingleClickButton tempBasalCancel;
|
||||
SingleClickButton fill;
|
||||
SingleClickButton tddStats;
|
||||
SingleClickButton history;
|
||||
|
||||
public ActionsFragment() {
|
||||
super();
|
||||
|
@ -71,6 +76,8 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL
|
|||
tempBasal = (SingleClickButton) view.findViewById(R.id.actions_settempbasal);
|
||||
tempBasalCancel = (SingleClickButton) view.findViewById(R.id.actions_canceltempbasal);
|
||||
fill = (SingleClickButton) view.findViewById(R.id.actions_fill);
|
||||
tddStats = view.findViewById(R.id.actions_tddstats);
|
||||
history = view.findViewById(R.id.actions_historybrowser);
|
||||
|
||||
profileSwitch.setOnClickListener(this);
|
||||
tempTarget.setOnClickListener(this);
|
||||
|
@ -79,11 +86,13 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL
|
|||
tempBasal.setOnClickListener(this);
|
||||
tempBasalCancel.setOnClickListener(this);
|
||||
fill.setOnClickListener(this);
|
||||
history.setOnClickListener(this);
|
||||
tddStats.setOnClickListener(this);
|
||||
|
||||
updateGUI();
|
||||
return view;
|
||||
} catch (Exception e) {
|
||||
Crashlytics.logException(e);
|
||||
FabricPrivacy.logException(e);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@ -116,9 +125,14 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL
|
|||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (MainApp.getConfigBuilder().getActiveProfileInterface().getProfile() == null) {
|
||||
tempTarget.setVisibility(View.GONE);
|
||||
if (MainApp.getConfigBuilder().getActiveProfileInterface().getProfile() != null) {
|
||||
profileSwitch.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
profileSwitch.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
if (MainApp.getConfigBuilder().getProfile() == null) {
|
||||
tempTarget.setVisibility(View.GONE);
|
||||
extendedBolus.setVisibility(View.GONE);
|
||||
extendedBolusCancel.setVisibility(View.GONE);
|
||||
tempBasal.setVisibility(View.GONE);
|
||||
|
@ -126,22 +140,25 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL
|
|||
fill.setVisibility(View.GONE);
|
||||
return;
|
||||
}
|
||||
|
||||
final PumpInterface pump = ConfigBuilderPlugin.getActivePump();
|
||||
if (!pump.getPumpDescription().isSetBasalProfileCapable || !pump.isInitialized() || pump.isSuspended())
|
||||
final boolean basalprofileEnabled = MainApp.isEngineeringModeOrRelease()
|
||||
&& pump.getPumpDescription().isSetBasalProfileCapable;
|
||||
|
||||
if (!basalprofileEnabled || !pump.isInitialized() || pump.isSuspended())
|
||||
profileSwitch.setVisibility(View.GONE);
|
||||
else
|
||||
profileSwitch.setVisibility(View.VISIBLE);
|
||||
|
||||
|
||||
if (!pump.getPumpDescription().isExtendedBolusCapable || !pump.isInitialized() || pump.isSuspended() || pump.isFakingTempsByExtendedBoluses()) {
|
||||
extendedBolus.setVisibility(View.GONE);
|
||||
extendedBolusCancel.setVisibility(View.GONE);
|
||||
} else {
|
||||
if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) {
|
||||
ExtendedBolus activeExtendedBolus = TreatmentsPlugin.getPlugin().getExtendedBolusFromHistory(System.currentTimeMillis());
|
||||
if (activeExtendedBolus != null) {
|
||||
extendedBolus.setVisibility(View.GONE);
|
||||
extendedBolusCancel.setVisibility(View.VISIBLE);
|
||||
ExtendedBolus running = MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis());
|
||||
extendedBolusCancel.setText(MainApp.instance().getString(R.string.cancel) + " " + running.toString());
|
||||
extendedBolusCancel.setText(MainApp.gs(R.string.cancel) + " " + activeExtendedBolus.toString());
|
||||
} else {
|
||||
extendedBolus.setVisibility(View.VISIBLE);
|
||||
extendedBolusCancel.setVisibility(View.GONE);
|
||||
|
@ -153,11 +170,11 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL
|
|||
tempBasal.setVisibility(View.GONE);
|
||||
tempBasalCancel.setVisibility(View.GONE);
|
||||
} else {
|
||||
if (MainApp.getConfigBuilder().isTempBasalInProgress()) {
|
||||
final TemporaryBasal activeTemp = TreatmentsPlugin.getPlugin().getTempBasalFromHistory(System.currentTimeMillis());
|
||||
if (activeTemp != null) {
|
||||
tempBasal.setVisibility(View.GONE);
|
||||
tempBasalCancel.setVisibility(View.VISIBLE);
|
||||
final TemporaryBasal activeTemp = MainApp.getConfigBuilder().getTempBasalFromHistory(System.currentTimeMillis());
|
||||
tempBasalCancel.setText(MainApp.instance().getString(R.string.cancel) + " " + activeTemp.toStringShort());
|
||||
tempBasalCancel.setText(MainApp.gs(R.string.cancel) + " " + activeTemp.toStringShort());
|
||||
} else {
|
||||
tempBasal.setVisibility(View.VISIBLE);
|
||||
tempBasalCancel.setVisibility(View.GONE);
|
||||
|
@ -173,6 +190,9 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL
|
|||
tempTarget.setVisibility(View.GONE);
|
||||
else
|
||||
tempTarget.setVisibility(View.VISIBLE);
|
||||
|
||||
if (!ConfigBuilderPlugin.getActivePump().getPumpDescription().supportsTDDs) tddStats.setVisibility(View.GONE);
|
||||
else tddStats.setVisibility(View.VISIBLE);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -201,15 +221,15 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL
|
|||
newExtendedDialog.show(manager, "NewExtendedDialog");
|
||||
break;
|
||||
case R.id.actions_extendedbolus_cancel:
|
||||
if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) {
|
||||
if (TreatmentsPlugin.getPlugin().isInHistoryExtendedBoluslInProgress()) {
|
||||
ConfigBuilderPlugin.getCommandQueue().cancelExtended(null);
|
||||
Answers.getInstance().logCustom(new CustomEvent("CancelExtended"));
|
||||
FabricPrivacy.getInstance().logCustom(new CustomEvent("CancelExtended"));
|
||||
}
|
||||
break;
|
||||
case R.id.actions_canceltempbasal:
|
||||
if (MainApp.getConfigBuilder().isTempBasalInProgress()) {
|
||||
if (TreatmentsPlugin.getPlugin().isTempBasalInProgress()) {
|
||||
ConfigBuilderPlugin.getCommandQueue().cancelTempBasal(true, null);
|
||||
Answers.getInstance().logCustom(new CustomEvent("CancelTemp"));
|
||||
FabricPrivacy.getInstance().logCustom(new CustomEvent("CancelTemp"));
|
||||
}
|
||||
break;
|
||||
case R.id.actions_settempbasal:
|
||||
|
@ -220,6 +240,12 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL
|
|||
FillDialog fillDialog = new FillDialog();
|
||||
fillDialog.show(manager, "FillDialog");
|
||||
break;
|
||||
case R.id.actions_historybrowser:
|
||||
startActivity(new Intent(getContext(), HistoryBrowseActivity.class));
|
||||
break;
|
||||
case R.id.actions_tddstats:
|
||||
startActivity(new Intent(getContext(), TDDStatsActivity.class));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,82 +1,22 @@
|
|||
package info.nightscout.androidaps.plugins.Actions;
|
||||
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||
import info.nightscout.androidaps.interfaces.PluginDescription;
|
||||
import info.nightscout.androidaps.interfaces.PluginType;
|
||||
|
||||
/**
|
||||
* Created by mike on 05.11.2016.
|
||||
*/
|
||||
|
||||
public class ActionsPlugin implements PluginBase {
|
||||
public class ActionsPlugin extends PluginBase {
|
||||
|
||||
private boolean fragmentEnabled = true;
|
||||
private boolean fragmentVisible = true;
|
||||
|
||||
@Override
|
||||
public int getType() {
|
||||
return PluginBase.GENERAL;
|
||||
public ActionsPlugin() {
|
||||
super(new PluginDescription()
|
||||
.mainType(PluginType.GENERAL)
|
||||
.fragmentClass(ActionsFragment.class.getName())
|
||||
.pluginName(R.string.actions)
|
||||
.shortName(R.string.actions_shortname)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFragmentClass() {
|
||||
return ActionsFragment.class.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return MainApp.sResources.getString(R.string.actions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNameShort() {
|
||||
String name = MainApp.sResources.getString(R.string.actions_shortname);
|
||||
if (!name.trim().isEmpty()){
|
||||
//only if translation exists
|
||||
return name;
|
||||
}
|
||||
// use long name as fallback
|
||||
return getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(int type) {
|
||||
return type == GENERAL && fragmentEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVisibleInTabs(int type) {
|
||||
return type == GENERAL && fragmentVisible;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeHidden(int type) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasFragment() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean showInList(int type) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
|
||||
if (type == GENERAL) this.fragmentEnabled = fragmentEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFragmentVisible(int type, boolean fragmentVisible) {
|
||||
if (type == GENERAL) this.fragmentVisible = fragmentVisible;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPreferencesId() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
package info.nightscout.androidaps.plugins.Actions.dialogs;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.text.Editable;
|
||||
import android.text.Html;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
|
@ -13,40 +15,73 @@ import android.view.ViewGroup;
|
|||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.Button;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.EditText;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import com.crashlytics.android.answers.Answers;
|
||||
import com.crashlytics.android.answers.CustomEvent;
|
||||
import com.google.common.base.Joiner;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import info.nightscout.androidaps.Constants;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.data.DetailedBolusInfo;
|
||||
import info.nightscout.androidaps.db.CareportalEvent;
|
||||
import info.nightscout.androidaps.db.Source;
|
||||
import info.nightscout.androidaps.interfaces.Constraint;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.Overview.Dialogs.ErrorHelperActivity;
|
||||
import info.nightscout.androidaps.queue.Callback;
|
||||
import info.nightscout.utils.DecimalFormatter;
|
||||
import info.nightscout.utils.FabricPrivacy;
|
||||
import info.nightscout.utils.NSUpload;
|
||||
import info.nightscout.utils.NumberPicker;
|
||||
import info.nightscout.utils.SP;
|
||||
import info.nightscout.utils.SafeParse;
|
||||
import info.nightscout.utils.ToastUtils;
|
||||
|
||||
import static info.nightscout.utils.DateUtil.now;
|
||||
|
||||
public class FillDialog extends DialogFragment implements OnClickListener {
|
||||
private static Logger log = LoggerFactory.getLogger(FillDialog.class);
|
||||
|
||||
Button deliverButton;
|
||||
private CheckBox pumpSiteChangeCheckbox;
|
||||
private CheckBox insulinCartridgeChangeCheckbox;
|
||||
|
||||
private NumberPicker editInsulin;
|
||||
|
||||
double amount1 = 0d;
|
||||
double amount2 = 0d;
|
||||
double amount3 = 0d;
|
||||
|
||||
NumberPicker editInsulin;
|
||||
private EditText notesEdit;
|
||||
|
||||
public FillDialog() {
|
||||
final private TextWatcher textWatcher = new TextWatcher() {
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
validateInputs();
|
||||
}
|
||||
|
||||
@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 void validateInputs() {
|
||||
int time = editInsulin.getValue().intValue();
|
||||
if (Math.abs(time) > 12 * 60) {
|
||||
editInsulin.setValue(0d);
|
||||
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.constraintapllied));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -54,110 +89,122 @@ public class FillDialog extends DialogFragment implements OnClickListener {
|
|||
Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.actions_fill_dialog, null, false);
|
||||
|
||||
deliverButton = (Button) view.findViewById(R.id.treatments_newtreatment_deliverbutton);
|
||||
view.findViewById(R.id.ok).setOnClickListener(this);
|
||||
view.findViewById(R.id.cancel).setOnClickListener(this);
|
||||
|
||||
deliverButton.setOnClickListener(this);
|
||||
getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
|
||||
getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
|
||||
|
||||
Double maxInsulin = MainApp.getConfigBuilder().applyBolusConstraints(Constants.bolusOnlyForCheckLimit);
|
||||
pumpSiteChangeCheckbox = view.findViewById(R.id.fill_catheter_change);
|
||||
insulinCartridgeChangeCheckbox = view.findViewById(R.id.fill_cartridge_change);
|
||||
|
||||
Double maxInsulin = MainApp.getConstraintChecker().getMaxBolusAllowed().value();
|
||||
double bolusstep = ConfigBuilderPlugin.getActivePump().getPumpDescription().bolusStep;
|
||||
editInsulin = (NumberPicker) view.findViewById(R.id.treatments_newtreatment_insulinamount);
|
||||
editInsulin.setParams(0d, 0d, maxInsulin, bolusstep, new DecimalFormat("0.00"), false);
|
||||
editInsulin = view.findViewById(R.id.fill_insulinamount);
|
||||
editInsulin.setParams(0d, 0d, maxInsulin, bolusstep, DecimalFormatter.pumpSupportedBolusFormat(), false, textWatcher);
|
||||
|
||||
//setup preset buttons
|
||||
Button button1 = (Button) view.findViewById(R.id.fill_preset_button1);
|
||||
Button button2 = (Button) view.findViewById(R.id.fill_preset_button2);
|
||||
Button button3 = (Button) view.findViewById(R.id.fill_preset_button3);
|
||||
View divider = view.findViewById(R.id.fill_preset_divider);
|
||||
|
||||
Button preset1Button = view.findViewById(R.id.fill_preset_button1);
|
||||
amount1 = SP.getDouble("fill_button1", 0.3);
|
||||
amount2 = SP.getDouble("fill_button2", 0d);
|
||||
amount3 = SP.getDouble("fill_button3", 0d);
|
||||
|
||||
if (amount1 > 0) {
|
||||
button1.setVisibility(View.VISIBLE);
|
||||
button1.setText(DecimalFormatter.to2Decimal(amount1) + "U");
|
||||
button1.setOnClickListener(this);
|
||||
preset1Button.setVisibility(View.VISIBLE);
|
||||
preset1Button.setText(DecimalFormatter.toPumpSupportedBolus(amount1)); // + "U");
|
||||
preset1Button.setOnClickListener(this);
|
||||
} else {
|
||||
button1.setVisibility(View.GONE);
|
||||
preset1Button.setVisibility(View.GONE);
|
||||
}
|
||||
Button preset2Button = view.findViewById(R.id.fill_preset_button2);
|
||||
amount2 = SP.getDouble("fill_button2", 0d);
|
||||
if (amount2 > 0) {
|
||||
button2.setVisibility(View.VISIBLE);
|
||||
button2.setText(DecimalFormatter.to2Decimal(amount2) + "U");
|
||||
button2.setOnClickListener(this);
|
||||
preset2Button.setVisibility(View.VISIBLE);
|
||||
preset2Button.setText(DecimalFormatter.toPumpSupportedBolus(amount2)); // + "U");
|
||||
preset2Button.setOnClickListener(this);
|
||||
} else {
|
||||
button2.setVisibility(View.GONE);
|
||||
preset2Button.setVisibility(View.GONE);
|
||||
}
|
||||
Button preset3Button = view.findViewById(R.id.fill_preset_button3);
|
||||
amount3 = SP.getDouble("fill_button3", 0d);
|
||||
if (amount3 > 0) {
|
||||
button3.setVisibility(View.VISIBLE);
|
||||
button3.setText(DecimalFormatter.to2Decimal(amount3) + "U");
|
||||
button3.setOnClickListener(this);
|
||||
preset3Button.setVisibility(View.VISIBLE);
|
||||
preset3Button.setText(DecimalFormatter.toPumpSupportedBolus(amount3)); // + "U");
|
||||
preset3Button.setOnClickListener(this);
|
||||
} else {
|
||||
button3.setVisibility(View.GONE);
|
||||
preset3Button.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
if (button1.getVisibility() == View.GONE && button2.getVisibility() == View.GONE && button3.getVisibility() == View.GONE) {
|
||||
divider.setVisibility(View.GONE);
|
||||
}
|
||||
LinearLayout notesLayout = view.findViewById(R.id.fill_notes_layout);
|
||||
notesLayout.setVisibility(SP.getBoolean(R.string.key_show_notes_entry_dialogs, false) ? View.VISIBLE : View.GONE);
|
||||
notesEdit = view.findViewById(R.id.fill_notes);
|
||||
|
||||
setCancelable(true);
|
||||
getDialog().setCanceledOnTouchOutside(false);
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
if (getDialog() != null)
|
||||
getDialog().getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
switch (view.getId()) {
|
||||
case R.id.treatments_newtreatment_deliverbutton:
|
||||
Double insulin = SafeParse.stringToDouble(editInsulin.getText().toString());
|
||||
confirmAndDeliver(insulin);
|
||||
case R.id.ok:
|
||||
confirmAndDeliver();
|
||||
break;
|
||||
case R.id.cancel:
|
||||
dismiss();
|
||||
break;
|
||||
case R.id.fill_preset_button1:
|
||||
confirmAndDeliver(amount1);
|
||||
editInsulin.setValue(amount1);
|
||||
break;
|
||||
case R.id.fill_preset_button2:
|
||||
confirmAndDeliver(amount2);
|
||||
editInsulin.setValue(amount2);
|
||||
break;
|
||||
case R.id.fill_preset_button3:
|
||||
confirmAndDeliver(amount3);
|
||||
editInsulin.setValue(amount3);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void confirmAndDeliver(Double insulin) {
|
||||
private void confirmAndDeliver() {
|
||||
try {
|
||||
Double insulin = SafeParse.stringToDouble(editInsulin.getText());
|
||||
|
||||
String confirmMessage = getString(R.string.fillwarning) + "\n";
|
||||
List<String> confirmMessage = new LinkedList<>();
|
||||
|
||||
Double insulinAfterConstraints = MainApp.getConfigBuilder().applyBolusConstraints(insulin);
|
||||
confirmMessage += getString(R.string.bolus) + ": " + insulinAfterConstraints + "U";
|
||||
if (insulinAfterConstraints - insulin != 0)
|
||||
confirmMessage += "\n" + getString(R.string.constraintapllied);
|
||||
Double insulinAfterConstraints = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(insulin)).value();
|
||||
if (insulinAfterConstraints > 0) {
|
||||
confirmMessage.add(MainApp.gs(R.string.fillwarning));
|
||||
confirmMessage.add("");
|
||||
confirmMessage.add(MainApp.gs(R.string.bolus) + ": " + "<font color='" + MainApp.gc(R.color.colorCarbsButton) + "'>" + insulinAfterConstraints + "U" + "</font>");
|
||||
if (!insulinAfterConstraints.equals(insulin))
|
||||
confirmMessage.add("<font color='" + MainApp.sResources.getColor(R.color.low) + "'>" + MainApp.gs(R.string.bolusconstraintapplied) + "</font>");
|
||||
}
|
||||
|
||||
if (pumpSiteChangeCheckbox.isChecked())
|
||||
confirmMessage.add("" + "<font color='" + MainApp.sResources.getColor(R.color.high) + "'>" + MainApp.gs(R.string.record_pump_site_change) + "</font>");
|
||||
|
||||
if (insulinCartridgeChangeCheckbox.isChecked())
|
||||
confirmMessage.add("" + "<font color='" + MainApp.sResources.getColor(R.color.high) + "'>" + MainApp.gs(R.string.record_insulin_cartridge_change) + "</font>");
|
||||
|
||||
final String notes = notesEdit.getText().toString();
|
||||
if (!notes.isEmpty()) {
|
||||
confirmMessage.add(MainApp.gs(R.string.careportal_newnstreatment_notes_label) + ": " + notes);
|
||||
}
|
||||
|
||||
final Double finalInsulinAfterConstraints = insulinAfterConstraints;
|
||||
|
||||
final Context context = getContext();
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||
|
||||
builder.setTitle(this.getContext().getString(R.string.confirmation));
|
||||
builder.setMessage(confirmMessage);
|
||||
builder.setPositiveButton(getString(R.string.primefill), new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
builder.setTitle(MainApp.gs(R.string.confirmation));
|
||||
if (insulinAfterConstraints > 0 || pumpSiteChangeCheckbox.isChecked() || insulinCartridgeChangeCheckbox.isChecked()) {
|
||||
builder.setMessage(Html.fromHtml(Joiner.on("<br/>").join(confirmMessage)));
|
||||
builder.setPositiveButton(MainApp.gs(R.string.primefill), (dialog, id) -> {
|
||||
if (finalInsulinAfterConstraints > 0) {
|
||||
DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo();
|
||||
detailedBolusInfo.insulin = finalInsulinAfterConstraints;
|
||||
detailedBolusInfo.context = context;
|
||||
detailedBolusInfo.source = Source.USER;
|
||||
detailedBolusInfo.isValid = false; // do not count it in IOB (for pump history)
|
||||
detailedBolusInfo.notes = notes;
|
||||
ConfigBuilderPlugin.getCommandQueue().bolus(detailedBolusInfo, new Callback() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
@ -165,17 +212,23 @@ public class FillDialog extends DialogFragment implements OnClickListener {
|
|||
Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class);
|
||||
i.putExtra("soundid", R.raw.boluserror);
|
||||
i.putExtra("status", result.comment);
|
||||
i.putExtra("title", MainApp.sResources.getString(R.string.treatmentdeliveryerror));
|
||||
i.putExtra("title", MainApp.gs(R.string.treatmentdeliveryerror));
|
||||
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
MainApp.instance().startActivity(i);
|
||||
}
|
||||
}
|
||||
});
|
||||
Answers.getInstance().logCustom(new CustomEvent("Fill"));
|
||||
FabricPrivacy.getInstance().logCustom(new CustomEvent("Fill"));
|
||||
}
|
||||
}
|
||||
});
|
||||
builder.setNegativeButton(getString(R.string.cancel), null);
|
||||
if (pumpSiteChangeCheckbox.isChecked())
|
||||
NSUpload.uploadEvent(CareportalEvent.SITECHANGE, now(), notes);
|
||||
if (insulinCartridgeChangeCheckbox.isChecked())
|
||||
NSUpload.uploadEvent(CareportalEvent.INSULINCHANGE, now() + 1000, notes);
|
||||
});
|
||||
} else {
|
||||
builder.setMessage(MainApp.gs(R.string.no_action_selected));
|
||||
}
|
||||
builder.setNegativeButton(MainApp.gs(R.string.cancel), null);
|
||||
builder.show();
|
||||
dismiss();
|
||||
} catch (RuntimeException e) {
|
||||
|
|
|
@ -10,20 +10,21 @@ import android.view.LayoutInflater;
|
|||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.crashlytics.android.answers.Answers;
|
||||
import com.crashlytics.android.answers.CustomEvent;
|
||||
|
||||
import org.mozilla.javascript.tools.jsc.Main;
|
||||
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.interfaces.Constraint;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.Overview.Dialogs.ErrorHelperActivity;
|
||||
import info.nightscout.androidaps.queue.Callback;
|
||||
import info.nightscout.utils.FabricPrivacy;
|
||||
import info.nightscout.utils.NumberPicker;
|
||||
import info.nightscout.utils.SafeParse;
|
||||
|
||||
|
@ -39,11 +40,11 @@ public class NewExtendedBolusDialog extends DialogFragment implements View.OnCli
|
|||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
getDialog().setTitle(getString(R.string.overview_extendedbolus_button));
|
||||
getDialog().setTitle(MainApp.gs(R.string.overview_extendedbolus_button));
|
||||
|
||||
View view = inflater.inflate(R.layout.overview_newextendedbolus_dialog, container, false);
|
||||
|
||||
Double maxInsulin = MainApp.getConfigBuilder().applyBolusConstraints(Constants.bolusOnlyForCheckLimit);
|
||||
Double maxInsulin = MainApp.getConstraintChecker().getMaxBolusAllowed().value();
|
||||
editInsulin = (NumberPicker) view.findViewById(R.id.overview_newextendedbolus_insulin);
|
||||
editInsulin.setParams(0d, 0d, maxInsulin, 0.1d, new DecimalFormat("0.00"), false);
|
||||
|
||||
|
@ -68,13 +69,13 @@ public class NewExtendedBolusDialog extends DialogFragment implements View.OnCli
|
|||
Double insulin = SafeParse.stringToDouble(editInsulin.getText());
|
||||
int durationInMinutes = SafeParse.stringToInt(editDuration.getText());
|
||||
|
||||
String confirmMessage = getString(R.string.setextendedbolusquestion);
|
||||
String confirmMessage = MainApp.gs(R.string.setextendedbolusquestion);
|
||||
|
||||
Double insulinAfterConstraint = MainApp.getConfigBuilder().applyBolusConstraints(insulin);
|
||||
Double insulinAfterConstraint = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(insulin)).value();
|
||||
confirmMessage += " " + insulinAfterConstraint + " U ";
|
||||
confirmMessage += getString(R.string.duration) + " " + durationInMinutes + "min ?";
|
||||
confirmMessage += MainApp.gs(R.string.duration) + " " + durationInMinutes + "min ?";
|
||||
if (insulinAfterConstraint - insulin != 0d)
|
||||
confirmMessage += "\n" + getString(R.string.constraintapllied);
|
||||
confirmMessage += "\n" + MainApp.gs(R.string.constraintapllied);
|
||||
insulin = insulinAfterConstraint;
|
||||
|
||||
final Double finalInsulin = insulin;
|
||||
|
@ -82,9 +83,9 @@ public class NewExtendedBolusDialog extends DialogFragment implements View.OnCli
|
|||
|
||||
final Context context = getContext();
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||
builder.setTitle(context.getString(R.string.confirmation));
|
||||
builder.setTitle(MainApp.gs(R.string.confirmation));
|
||||
builder.setMessage(confirmMessage);
|
||||
builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() {
|
||||
builder.setPositiveButton(MainApp.gs(R.string.ok), new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
ConfigBuilderPlugin.getCommandQueue().extendedBolus(finalInsulin, finalDurationInMinutes, new Callback() {
|
||||
@Override
|
||||
|
@ -93,16 +94,16 @@ public class NewExtendedBolusDialog extends DialogFragment implements View.OnCli
|
|||
Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class);
|
||||
i.putExtra("soundid", R.raw.boluserror);
|
||||
i.putExtra("status", result.comment);
|
||||
i.putExtra("title", MainApp.sResources.getString(R.string.treatmentdeliveryerror));
|
||||
i.putExtra("title", MainApp.gs(R.string.treatmentdeliveryerror));
|
||||
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
MainApp.instance().startActivity(i);
|
||||
}
|
||||
}
|
||||
});
|
||||
Answers.getInstance().logCustom(new CustomEvent("ExtendedBolus"));
|
||||
FabricPrivacy.getInstance().logCustom(new CustomEvent("ExtendedBolus"));
|
||||
}
|
||||
});
|
||||
builder.setNegativeButton(getString(R.string.cancel), null);
|
||||
builder.setNegativeButton(MainApp.gs(R.string.cancel), null);
|
||||
builder.show();
|
||||
dismiss();
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package info.nightscout.androidaps.plugins.Actions.dialogs;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
|
@ -13,7 +12,6 @@ import android.widget.LinearLayout;
|
|||
import android.widget.RadioButton;
|
||||
import android.widget.RadioGroup;
|
||||
|
||||
import com.crashlytics.android.answers.Answers;
|
||||
import com.crashlytics.android.answers.CustomEvent;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
|
@ -24,10 +22,12 @@ import java.text.DecimalFormat;
|
|||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.data.Profile;
|
||||
import info.nightscout.androidaps.interfaces.Constraint;
|
||||
import info.nightscout.androidaps.interfaces.PumpDescription;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.Overview.Dialogs.ErrorHelperActivity;
|
||||
import info.nightscout.androidaps.queue.Callback;
|
||||
import info.nightscout.utils.FabricPrivacy;
|
||||
import info.nightscout.utils.NumberPicker;
|
||||
import info.nightscout.utils.SafeParse;
|
||||
|
||||
|
@ -52,7 +52,7 @@ public class NewTempBasalDialog extends DialogFragment implements View.OnClickLi
|
|||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
getDialog().setTitle(getString(R.string.overview_tempbasal_button));
|
||||
getDialog().setTitle(MainApp.gs(R.string.overview_tempbasal_button));
|
||||
|
||||
View view = inflater.inflate(R.layout.overview_newtempbasal_dialog, container, false);
|
||||
|
||||
|
@ -118,21 +118,25 @@ public class NewTempBasalDialog extends DialogFragment implements View.OnClickLi
|
|||
final boolean setAsPercent = percentRadio.isChecked();
|
||||
int durationInMinutes = SafeParse.stringToInt(duration.getText());
|
||||
|
||||
String confirmMessage = getString(R.string.setbasalquestion);
|
||||
Profile profile = MainApp.getConfigBuilder().getProfile();
|
||||
if (profile == null)
|
||||
return;
|
||||
|
||||
String confirmMessage = MainApp.gs(R.string.setbasalquestion);
|
||||
if (setAsPercent) {
|
||||
int basalPercentInput = SafeParse.stringToInt(basalPercent.getText());
|
||||
percent = MainApp.getConfigBuilder().applyBasalConstraints(basalPercentInput);
|
||||
percent = MainApp.getConstraintChecker().applyBasalPercentConstraints(new Constraint<>(basalPercentInput), profile).value();
|
||||
confirmMessage += "\n" + percent + "% ";
|
||||
confirmMessage += "\n" + getString(R.string.duration) + " " + durationInMinutes + "min ?";
|
||||
confirmMessage += "\n" + MainApp.gs(R.string.duration) + " " + durationInMinutes + "min ?";
|
||||
if (percent != basalPercentInput)
|
||||
confirmMessage += "\n" + getString(R.string.constraintapllied);
|
||||
confirmMessage += "\n" + MainApp.gs(R.string.constraintapllied);
|
||||
} else {
|
||||
Double basalAbsoluteInput = SafeParse.stringToDouble(basalAbsolute.getText());
|
||||
absolute = MainApp.getConfigBuilder().applyBasalConstraints(basalAbsoluteInput);
|
||||
absolute = MainApp.getConstraintChecker().applyBasalConstraints(new Constraint<>(basalAbsoluteInput), profile).value();
|
||||
confirmMessage += "\n" + absolute + " U/h ";
|
||||
confirmMessage += "\n" + getString(R.string.duration) + " " + durationInMinutes + "min ?";
|
||||
confirmMessage += "\n" + MainApp.gs(R.string.duration) + " " + durationInMinutes + "min ?";
|
||||
if (absolute - basalAbsoluteInput != 0d)
|
||||
confirmMessage += "\n" + getString(R.string.constraintapllied);
|
||||
confirmMessage += "\n" + MainApp.gs(R.string.constraintapllied);
|
||||
}
|
||||
|
||||
final int finalBasalPercent = percent;
|
||||
|
@ -140,9 +144,9 @@ public class NewTempBasalDialog extends DialogFragment implements View.OnClickLi
|
|||
final int finalDurationInMinutes = durationInMinutes;
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
|
||||
builder.setTitle(this.getContext().getString(R.string.confirmation));
|
||||
builder.setTitle(MainApp.gs(R.string.confirmation));
|
||||
builder.setMessage(confirmMessage);
|
||||
builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() {
|
||||
builder.setPositiveButton(MainApp.gs(R.string.ok), new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
Callback callback = new Callback() {
|
||||
@Override
|
||||
|
@ -151,21 +155,21 @@ public class NewTempBasalDialog extends DialogFragment implements View.OnClickLi
|
|||
Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class);
|
||||
i.putExtra("soundid", R.raw.boluserror);
|
||||
i.putExtra("status", result.comment);
|
||||
i.putExtra("title", MainApp.sResources.getString(R.string.tempbasaldeliveryerror));
|
||||
i.putExtra("title", MainApp.gs(R.string.tempbasaldeliveryerror));
|
||||
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
MainApp.instance().startActivity(i);
|
||||
}
|
||||
}
|
||||
};
|
||||
if (setAsPercent) {
|
||||
ConfigBuilderPlugin.getCommandQueue().tempBasalPercent(finalBasalPercent, finalDurationInMinutes, true, callback);
|
||||
ConfigBuilderPlugin.getCommandQueue().tempBasalPercent(finalBasalPercent, finalDurationInMinutes, true, profile, callback);
|
||||
} else {
|
||||
ConfigBuilderPlugin.getCommandQueue().tempBasalAbsolute(finalBasal, finalDurationInMinutes, true, callback);
|
||||
ConfigBuilderPlugin.getCommandQueue().tempBasalAbsolute(finalBasal, finalDurationInMinutes, true, profile, callback);
|
||||
}
|
||||
Answers.getInstance().logCustom(new CustomEvent("TempBasal"));
|
||||
FabricPrivacy.getInstance().logCustom(new CustomEvent("TempBasal"));
|
||||
}
|
||||
});
|
||||
builder.setNegativeButton(getString(R.string.cancel), null);
|
||||
builder.setNegativeButton(MainApp.gs(R.string.cancel), null);
|
||||
builder.show();
|
||||
dismiss();
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ package info.nightscout.androidaps.plugins.Careportal;
|
|||
|
||||
|
||||
import android.app.Activity;
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.view.LayoutInflater;
|
||||
|
@ -10,10 +11,11 @@ import android.view.ViewGroup;
|
|||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.crashlytics.android.Crashlytics;
|
||||
import com.squareup.otto.Subscribe;
|
||||
|
||||
import info.nightscout.androidaps.BuildConfig;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
|
@ -22,10 +24,12 @@ import info.nightscout.androidaps.db.CareportalEvent;
|
|||
import info.nightscout.androidaps.events.EventCareportalEventChange;
|
||||
import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog;
|
||||
import info.nightscout.androidaps.plugins.Common.SubscriberFragment;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSettingsStatus;
|
||||
import info.nightscout.androidaps.plugins.Overview.OverviewFragment;
|
||||
import info.nightscout.utils.FabricPrivacy;
|
||||
|
||||
public class CareportalFragment extends SubscriberFragment implements View.OnClickListener {
|
||||
private static Logger log = LoggerFactory.getLogger(CareportalFragment.class);
|
||||
|
||||
TextView iage;
|
||||
TextView cage;
|
||||
|
@ -96,7 +100,7 @@ public class CareportalFragment extends SubscriberFragment implements View.OnCli
|
|||
noProfileView = view.findViewById(R.id.profileview_noprofile);
|
||||
butonsLayout = (LinearLayout) view.findViewById(R.id.careportal_buttons);
|
||||
|
||||
ProfileStore profileStore = ConfigBuilderPlugin.getActiveProfileInterface().getProfile();
|
||||
ProfileStore profileStore = MainApp.getConfigBuilder().getActiveProfileInterface().getProfile();
|
||||
if (profileStore == null) {
|
||||
noProfileView.setVisibility(View.VISIBLE);
|
||||
butonsLayout.setVisibility(View.GONE);
|
||||
|
@ -111,7 +115,7 @@ public class CareportalFragment extends SubscriberFragment implements View.OnCli
|
|||
updateGUI();
|
||||
return view;
|
||||
} catch (Exception e) {
|
||||
Crashlytics.logException(e);
|
||||
FabricPrivacy.logException(e);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@ -208,26 +212,54 @@ public class CareportalFragment extends SubscriberFragment implements View.OnCli
|
|||
public static void updateAge(Activity activity, final TextView sage, final TextView iage, final TextView cage, final TextView pbage) {
|
||||
if (activity != null) {
|
||||
activity.runOnUiThread(
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
CareportalEvent careportalEvent;
|
||||
String notavailable = OverviewFragment.shorttextmode ? "-" : MainApp.sResources.getString(R.string.notavailable);
|
||||
if (sage != null) {
|
||||
careportalEvent = MainApp.getDbHelper().getLastCareportalEvent(CareportalEvent.SENSORCHANGE);
|
||||
sage.setText(careportalEvent != null ? careportalEvent.age() : notavailable);
|
||||
() -> {
|
||||
CareportalEvent careportalEvent;
|
||||
NSSettingsStatus nsSettings = new NSSettingsStatus().getInstance();
|
||||
|
||||
double iageUrgent = nsSettings.getExtendedWarnValue("iage", "urgent", 96);
|
||||
double iageWarn = nsSettings.getExtendedWarnValue("iage", "warn", 72);
|
||||
double cageUrgent = nsSettings.getExtendedWarnValue("cage", "urgent", 72);
|
||||
double cageWarn = nsSettings.getExtendedWarnValue("cage", "warn", 48);
|
||||
double sageUrgent = nsSettings.getExtendedWarnValue("sage", "urgent", 166);
|
||||
double sageWarn = nsSettings.getExtendedWarnValue("sage", "warn", 164);
|
||||
double pbageUrgent = nsSettings.getExtendedWarnValue("pgage", "urgent", 360);
|
||||
double pbageWarn = nsSettings.getExtendedWarnValue("pgage", "warn", 240);
|
||||
|
||||
String notavailable = OverviewFragment.shorttextmode ? "-" : MainApp.gs(R.string.notavailable);
|
||||
if (sage != null) {
|
||||
careportalEvent = MainApp.getDbHelper().getLastCareportalEvent(CareportalEvent.SENSORCHANGE);
|
||||
if (careportalEvent != null) {
|
||||
sage.setTextColor(CareportalFragment.determineTextColor(careportalEvent, sageWarn, sageUrgent));
|
||||
sage.setText(careportalEvent.age());
|
||||
} else {
|
||||
sage.setText(notavailable);
|
||||
}
|
||||
if (iage != null) {
|
||||
careportalEvent = MainApp.getDbHelper().getLastCareportalEvent(CareportalEvent.INSULINCHANGE);
|
||||
iage.setText(careportalEvent != null ? careportalEvent.age() : notavailable);
|
||||
}
|
||||
if (iage != null) {
|
||||
careportalEvent = MainApp.getDbHelper().getLastCareportalEvent(CareportalEvent.INSULINCHANGE);
|
||||
if (careportalEvent != null) {
|
||||
iage.setTextColor(CareportalFragment.determineTextColor(careportalEvent, iageWarn, iageUrgent));
|
||||
iage.setText(careportalEvent.age());
|
||||
} else {
|
||||
iage.setText(notavailable);
|
||||
}
|
||||
if (cage != null) {
|
||||
careportalEvent = MainApp.getDbHelper().getLastCareportalEvent(CareportalEvent.SITECHANGE);
|
||||
cage.setText(careportalEvent != null ? careportalEvent.age() : notavailable);
|
||||
}
|
||||
if (cage != null) {
|
||||
careportalEvent = MainApp.getDbHelper().getLastCareportalEvent(CareportalEvent.SITECHANGE);
|
||||
if (careportalEvent != null) {
|
||||
cage.setTextColor(CareportalFragment.determineTextColor(careportalEvent, cageWarn, cageUrgent));
|
||||
cage.setText(careportalEvent.age());
|
||||
} else {
|
||||
cage.setText(notavailable);
|
||||
}
|
||||
if (pbage != null) {
|
||||
careportalEvent = MainApp.getDbHelper().getLastCareportalEvent(CareportalEvent.PUMPBATTERYCHANGE);
|
||||
pbage.setText(careportalEvent != null ? careportalEvent.age() : notavailable);
|
||||
}
|
||||
if (pbage != null) {
|
||||
careportalEvent = MainApp.getDbHelper().getLastCareportalEvent(CareportalEvent.PUMPBATTERYCHANGE);
|
||||
if (careportalEvent != null) {
|
||||
pbage.setTextColor(CareportalFragment.determineTextColor(careportalEvent, pbageWarn, pbageUrgent));
|
||||
pbage.setText(careportalEvent.age());
|
||||
} else {
|
||||
pbage.setText(notavailable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -235,4 +267,15 @@ public class CareportalFragment extends SubscriberFragment implements View.OnCli
|
|||
}
|
||||
}
|
||||
|
||||
public static int determineTextColor(CareportalEvent careportalEvent, double warnThreshold, double urgentThreshold) {
|
||||
if (careportalEvent.isOlderThan(urgentThreshold)) {
|
||||
return MainApp.sResources.getColor(R.color.low);
|
||||
} else if (careportalEvent.isOlderThan(warnThreshold)) {
|
||||
return MainApp.sResources.getColor(R.color.high);
|
||||
} else {
|
||||
return Color.WHITE;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
package info.nightscout.androidaps.plugins.Careportal;
|
||||
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||
import info.nightscout.androidaps.interfaces.PluginDescription;
|
||||
import info.nightscout.androidaps.interfaces.PluginType;
|
||||
|
||||
public class CareportalPlugin implements PluginBase {
|
||||
|
||||
private boolean fragmentEnabled = true;
|
||||
private boolean fragmentVisible = true;
|
||||
public class CareportalPlugin extends PluginBase {
|
||||
|
||||
static CareportalPlugin careportalPlugin;
|
||||
|
||||
|
@ -19,70 +17,13 @@ public class CareportalPlugin implements PluginBase {
|
|||
return careportalPlugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getType() {
|
||||
return PluginBase.GENERAL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFragmentClass() {
|
||||
return CareportalFragment.class.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return MainApp.sResources.getString(R.string.careportal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNameShort() {
|
||||
String name = MainApp.sResources.getString(R.string.careportal_shortname);
|
||||
if (!name.trim().isEmpty()){
|
||||
//only if translation exists
|
||||
return name;
|
||||
}
|
||||
// use long name as fallback
|
||||
return getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(int type) {
|
||||
return type == GENERAL && fragmentEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVisibleInTabs(int type) {
|
||||
return type == GENERAL && fragmentVisible;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeHidden(int type) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasFragment() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean showInList(int type) {
|
||||
return !Config.NSCLIENT && !Config.G5UPLOADER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
|
||||
if (type == GENERAL) this.fragmentEnabled = fragmentEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFragmentVisible(int type, boolean fragmentVisible) {
|
||||
if (type == GENERAL) this.fragmentVisible = fragmentVisible;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPreferencesId() {
|
||||
return R.xml.pref_careportal;
|
||||
public CareportalPlugin() {
|
||||
super(new PluginDescription()
|
||||
.mainType(PluginType.GENERAL)
|
||||
.fragmentClass(CareportalFragment.class.getName())
|
||||
.pluginName(R.string.careportal)
|
||||
.shortName(R.string.careportal_shortname)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,8 +2,6 @@ package info.nightscout.androidaps.plugins.Careportal.Dialogs;
|
|||
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
|
@ -16,15 +14,14 @@ import android.view.ViewGroup;
|
|||
import android.widget.AdapterView;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.Button;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.EditText;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.RadioButton;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.crashlytics.android.answers.Answers;
|
||||
import com.crashlytics.android.answers.CustomEvent;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.wdullaer.materialdatetimepicker.date.DatePickerDialog;
|
||||
import com.wdullaer.materialdatetimepicker.time.RadialPickerLayout;
|
||||
import com.wdullaer.materialdatetimepicker.time.TimePickerDialog;
|
||||
|
@ -38,6 +35,7 @@ import java.text.DecimalFormat;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import info.nightscout.androidaps.Constants;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
|
@ -45,16 +43,18 @@ import info.nightscout.androidaps.R;
|
|||
import info.nightscout.androidaps.data.GlucoseStatus;
|
||||
import info.nightscout.androidaps.data.Profile;
|
||||
import info.nightscout.androidaps.data.ProfileStore;
|
||||
import info.nightscout.androidaps.db.BgReading;
|
||||
import info.nightscout.androidaps.db.CareportalEvent;
|
||||
import info.nightscout.androidaps.db.ProfileSwitch;
|
||||
import info.nightscout.androidaps.db.Source;
|
||||
import info.nightscout.androidaps.db.TempTarget;
|
||||
import info.nightscout.androidaps.events.EventNewBasalProfile;
|
||||
import info.nightscout.androidaps.plugins.Careportal.OptionsToShow;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.Overview.Dialogs.ErrorHelperActivity;
|
||||
import info.nightscout.androidaps.queue.Callback;
|
||||
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
|
||||
import info.nightscout.utils.DateUtil;
|
||||
import info.nightscout.utils.DefaultValueHelper;
|
||||
import info.nightscout.utils.FabricPrivacy;
|
||||
import info.nightscout.utils.HardLimits;
|
||||
import info.nightscout.utils.JsonHelper;
|
||||
import info.nightscout.utils.NSUpload;
|
||||
import info.nightscout.utils.NumberPicker;
|
||||
import info.nightscout.utils.SP;
|
||||
|
@ -70,8 +70,8 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
|
|||
private static String event;
|
||||
|
||||
Profile profile;
|
||||
ProfileStore profileStore;
|
||||
String units;
|
||||
public ProfileStore profileStore;
|
||||
String units = Constants.MGDL;
|
||||
|
||||
TextView eventTypeText;
|
||||
LinearLayout layoutPercent;
|
||||
|
@ -105,13 +105,19 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
|
|||
|
||||
Date eventTime;
|
||||
|
||||
private static Integer seconds = null;
|
||||
|
||||
public void setOptions(OptionsToShow options, int event) {
|
||||
this.options = options;
|
||||
this.event = MainApp.sResources.getString(event);
|
||||
this.event = MainApp.gs(event);
|
||||
}
|
||||
|
||||
public NewNSTreatmentDialog() {
|
||||
super();
|
||||
|
||||
if (seconds == null) {
|
||||
seconds = Double.valueOf(Math.random() * 59).intValue();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -130,7 +136,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
|
|||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
if (options == null) return null;
|
||||
getDialog().setTitle(getString(options.eventName));
|
||||
getDialog().setTitle(MainApp.gs(options.eventName));
|
||||
setStyle(DialogFragment.STYLE_NORMAL, getTheme());
|
||||
View view = inflater.inflate(R.layout.careportal_newnstreatment_dialog, container, false);
|
||||
|
||||
|
@ -166,52 +172,61 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
|
|||
|
||||
// profile
|
||||
profile = MainApp.getConfigBuilder().getProfile();
|
||||
profileStore = ConfigBuilderPlugin.getActiveProfileInterface().getProfile();
|
||||
ArrayList<CharSequence> profileList;
|
||||
units = profile != null ? profile.getUnits() : Constants.MGDL;
|
||||
profileList = profileStore.getProfileList();
|
||||
ArrayAdapter<CharSequence> adapter = new ArrayAdapter<CharSequence>(getContext(),
|
||||
R.layout.spinner_centered, profileList);
|
||||
profileSpinner.setAdapter(adapter);
|
||||
// set selected to actual profile
|
||||
for (int p = 0; p < profileList.size(); p++) {
|
||||
if (profileList.get(p).equals(MainApp.getConfigBuilder().getProfileName(false)))
|
||||
profileSpinner.setSelection(p);
|
||||
profileStore = MainApp.getConfigBuilder().getActiveProfileInterface().getProfile();
|
||||
if (profileStore == null) {
|
||||
if (options.eventType == R.id.careportal_profileswitch) {
|
||||
log.error("Profile switch called but plugin doesn't contain valid profile");
|
||||
}
|
||||
} else {
|
||||
ArrayList<CharSequence> profileList;
|
||||
units = profile != null ? profile.getUnits() : Constants.MGDL;
|
||||
profileList = profileStore.getProfileList();
|
||||
ArrayAdapter<CharSequence> adapter = new ArrayAdapter<>(getContext(),
|
||||
R.layout.spinner_centered, profileList);
|
||||
profileSpinner.setAdapter(adapter);
|
||||
// set selected to actual profile
|
||||
for (int p = 0; p < profileList.size(); p++) {
|
||||
if (profileList.get(p).equals(MainApp.getConfigBuilder().getProfileName(false)))
|
||||
profileSpinner.setSelection(p);
|
||||
}
|
||||
}
|
||||
|
||||
final Double bg = Profile.fromMgdlToUnits(GlucoseStatus.getGlucoseStatusData() != null ? GlucoseStatus.getGlucoseStatusData().glucose : 0d, profile != null ? profile.getUnits() : Constants.MGDL);
|
||||
final Double bg = Profile.fromMgdlToUnits(GlucoseStatus.getGlucoseStatusData() != null ? GlucoseStatus.getGlucoseStatusData().glucose : 0d, units);
|
||||
|
||||
// temp target
|
||||
final ArrayList<CharSequence> reasonList = new ArrayList<CharSequence>();
|
||||
reasonList.add(MainApp.sResources.getString(R.string.manual));
|
||||
reasonList.add(MainApp.sResources.getString(R.string.eatingsoon));
|
||||
reasonList.add(MainApp.sResources.getString(R.string.activity));
|
||||
ArrayAdapter<CharSequence> adapterReason = new ArrayAdapter<CharSequence>(getContext(),
|
||||
final List<String> reasonList = Lists.newArrayList(
|
||||
MainApp.gs(R.string.manual),
|
||||
MainApp.gs(R.string.eatingsoon),
|
||||
MainApp.gs(R.string.activity),
|
||||
MainApp.gs(R.string.hypo));
|
||||
ArrayAdapter<String> adapterReason = new ArrayAdapter<>(getContext(),
|
||||
R.layout.spinner_centered, reasonList);
|
||||
reasonSpinner.setAdapter(adapterReason);
|
||||
reasonSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
||||
@Override
|
||||
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
||||
double defaultDuration = 0;
|
||||
double defaultDuration;
|
||||
double defaultTarget = 0;
|
||||
if (profile != null) {
|
||||
defaultTarget = bg.doubleValue();
|
||||
defaultTarget = bg;
|
||||
}
|
||||
boolean erase = false;
|
||||
|
||||
if (MainApp.sResources.getString(R.string.eatingsoon).equals(reasonList.get(position))) {
|
||||
defaultDuration = SP.getDouble(R.string.key_eatingsoon_duration, 0d);
|
||||
defaultTarget = SP.getDouble(R.string.key_eatingsoon_target, 0d);
|
||||
;
|
||||
} else if (MainApp.sResources.getString(R.string.activity).equals(reasonList.get(position))) {
|
||||
defaultDuration = SP.getDouble(R.string.key_activity_duration, 0d);
|
||||
;
|
||||
defaultTarget = SP.getDouble(R.string.key_activity_target, 0d);
|
||||
;
|
||||
String units = MainApp.getConfigBuilder().getProfileUnits();
|
||||
DefaultValueHelper helper = new DefaultValueHelper();
|
||||
if (MainApp.gs(R.string.eatingsoon).equals(reasonList.get(position))) {
|
||||
defaultDuration = helper.determineEatingSoonTTDuration();
|
||||
defaultTarget = helper.determineEatingSoonTT(units);
|
||||
} else if (MainApp.gs(R.string.activity).equals(reasonList.get(position))) {
|
||||
defaultDuration = helper.determineActivityTTDuration();
|
||||
defaultTarget = helper.determineActivityTT(units);
|
||||
} else if (MainApp.gs(R.string.hypo).equals(reasonList.get(position))) {
|
||||
defaultDuration = helper.determineHypoTTDuration();
|
||||
defaultTarget = helper.determineHypoTT(units);
|
||||
} else {
|
||||
defaultDuration = 0;
|
||||
erase = true;
|
||||
}
|
||||
|
||||
if (defaultTarget != 0 || erase) {
|
||||
editTemptarget.setValue(defaultTarget);
|
||||
}
|
||||
|
@ -256,19 +271,16 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
|
|||
editBg.setParams(bg, 0d, 500d, 1d, new DecimalFormat("0"), false, bgTextWatcher);
|
||||
editTemptarget.setParams(bg, 0d, 500d, 1d, new DecimalFormat("0"), false);
|
||||
}
|
||||
sensorRadioButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||
Double bg = Profile.fromMgdlToUnits(GlucoseStatus.getGlucoseStatusData() != null ? GlucoseStatus.getGlucoseStatusData().glucose : 0d, profile.getUnits());
|
||||
editBg.setValue(bg);
|
||||
}
|
||||
sensorRadioButton.setOnCheckedChangeListener((buttonView, isChecked) -> {
|
||||
Double bg1 = Profile.fromMgdlToUnits(GlucoseStatus.getGlucoseStatusData() != null ? GlucoseStatus.getGlucoseStatusData().glucose : 0d, profile.getUnits());
|
||||
editBg.setValue(bg1);
|
||||
});
|
||||
|
||||
Integer maxCarbs = MainApp.getConfigBuilder().applyCarbsConstraints(Constants.carbsOnlyForCheckLimit);
|
||||
Integer maxCarbs = MainApp.getConstraintChecker().getMaxCarbsAllowed().value();
|
||||
editCarbs = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_carbsinput);
|
||||
editCarbs.setParams(0d, 0d, (double) maxCarbs, 1d, new DecimalFormat("0"), false);
|
||||
|
||||
Double maxInsulin = MainApp.getConfigBuilder().applyBolusConstraints(Constants.bolusOnlyForCheckLimit);
|
||||
Double maxInsulin = MainApp.getConstraintChecker().getMaxBolusAllowed().value();
|
||||
editInsulin = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_insulininput);
|
||||
editInsulin.setParams(0d, 0d, maxInsulin, 0.05d, new DecimalFormat("0.00"), false);
|
||||
|
||||
|
@ -295,7 +307,9 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
|
|||
}
|
||||
};
|
||||
|
||||
Integer maxPercent = MainApp.getConfigBuilder().applyBasalConstraints(Constants.basalPercentOnlyForCheckLimit);
|
||||
Integer maxPercent = 200;
|
||||
if (profile != null)
|
||||
maxPercent = MainApp.getConstraintChecker().getMaxBasalPercentAllowed(profile).value();
|
||||
editPercent = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_percentinput);
|
||||
editPercent.setParams(0d, 0d, (double) maxPercent, 5d, new DecimalFormat("0"), true, percentTextWatcher);
|
||||
|
||||
|
@ -317,7 +331,9 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
|
|||
}
|
||||
};
|
||||
|
||||
Double maxAbsolute = MainApp.getConfigBuilder().applyBasalConstraints(Constants.basalAbsoluteOnlyForCheckLimit);
|
||||
Double maxAbsolute = HardLimits.maxBasal();
|
||||
if (profile != null)
|
||||
maxAbsolute = MainApp.getConstraintChecker().getMaxBasalAllowed(profile).value();
|
||||
editAbsolute = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_absoluteinput);
|
||||
editAbsolute.setParams(0d, 0d, maxAbsolute, 0.05d, new DecimalFormat("0.00"), true, absoluteTextWatcher);
|
||||
|
||||
|
@ -330,19 +346,19 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
|
|||
editTimeshift = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_timeshift);
|
||||
editTimeshift.setParams(0d, (double) Constants.CPP_MIN_TIMESHIFT, (double) Constants.CPP_MAX_TIMESHIFT, 1d, new DecimalFormat("0"), false);
|
||||
|
||||
ProfileSwitch ps = MainApp.getConfigBuilder().getProfileSwitchFromHistory(System.currentTimeMillis());
|
||||
ProfileSwitch ps = TreatmentsPlugin.getPlugin().getProfileSwitchFromHistory(DateUtil.now());
|
||||
if (ps != null && ps.isCPP) {
|
||||
final int percentage = ps.percentage;
|
||||
final int timeshift = ps.timeshift;
|
||||
reuseButton.setText(reuseButton.getText() + " " + percentage + "% " + timeshift + "h");
|
||||
reuseButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
editPercentage.setValue((double) percentage);
|
||||
editTimeshift.setValue((double) timeshift);
|
||||
}
|
||||
reuseButton.setOnClickListener(v -> {
|
||||
editPercentage.setValue((double) percentage);
|
||||
editTimeshift.setValue((double) timeshift);
|
||||
});
|
||||
}
|
||||
if (ps == null) {
|
||||
options.duration = false;
|
||||
}
|
||||
|
||||
showOrHide((ViewGroup) view.findViewById(R.id.careportal_newnstreatment_eventtime_layout), options.date);
|
||||
showOrHide((ViewGroup) view.findViewById(R.id.careportal_newnstreatment_bg_layout), options.bg);
|
||||
|
@ -393,7 +409,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
|
|||
tpd.show(context.getFragmentManager(), "Timepickerdialog");
|
||||
break;
|
||||
case R.id.ok:
|
||||
createNSTreatment();
|
||||
confirmNSTreatmentCreation();
|
||||
dismiss();
|
||||
break;
|
||||
case R.id.cancel:
|
||||
|
@ -407,20 +423,32 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
|
|||
else layout.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
private void updateBGforDateTime() {
|
||||
long millis = eventTime.getTime() - (150 * 1000L); // 2,5 * 60 * 1000
|
||||
List<BgReading> data = MainApp.getDbHelper().getBgreadingsDataFromTime(millis, true);
|
||||
if ((data.size() > 0) &&
|
||||
(data.get(0).date > millis - 7 * 60 * 1000L) &&
|
||||
(data.get(0).date < millis + 7 * 60 * 1000L)) {
|
||||
editBg.setValue(Profile.fromMgdlToUnits(data.get(0).value, profile != null ? profile.getUnits() : Constants.MGDL));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDateSet(DatePickerDialog view, int year, int monthOfYear, int dayOfMonth) {
|
||||
eventTime.setYear(year - 1900);
|
||||
eventTime.setMonth(monthOfYear);
|
||||
eventTime.setDate(dayOfMonth);
|
||||
dateButton.setText(DateUtil.dateString(eventTime));
|
||||
updateBGforDateTime();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTimeSet(RadialPickerLayout view, int hourOfDay, int minute, int second) {
|
||||
eventTime.setHours(hourOfDay);
|
||||
eventTime.setMinutes(minute);
|
||||
eventTime.setSeconds(second);
|
||||
eventTime.setSeconds(this.seconds++); // randomize seconds to prevent creating record of the same time, if user choose time manually
|
||||
timeButton.setText(DateUtil.timeString(eventTime));
|
||||
updateBGforDateTime();
|
||||
}
|
||||
|
||||
|
||||
|
@ -545,221 +573,200 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
|
|||
|
||||
String buildConfirmText(JSONObject data) {
|
||||
String ret = "";
|
||||
try {
|
||||
if (data.has("eventType")) {
|
||||
ret += getString(R.string.careportal_newnstreatment_eventtype);
|
||||
ret += ": ";
|
||||
ret += Translator.translate(data.getString("eventType"));
|
||||
ret += "\n";
|
||||
}
|
||||
if (data.has("glucose")) {
|
||||
ret += getString(R.string.treatments_wizard_bg_label);
|
||||
ret += ": ";
|
||||
ret += data.get("glucose");
|
||||
ret += " " + units + "\n";
|
||||
}
|
||||
if (data.has("glucoseType")) {
|
||||
ret += getString(R.string.careportal_newnstreatment_glucosetype);
|
||||
ret += ": ";
|
||||
ret += Translator.translate(data.getString("glucoseType"));
|
||||
ret += "\n";
|
||||
}
|
||||
if (data.has("carbs")) {
|
||||
ret += getString(R.string.careportal_newnstreatment_carbs_label);
|
||||
ret += ": ";
|
||||
ret += data.get("carbs");
|
||||
ret += " g\n";
|
||||
}
|
||||
if (data.has("insulin")) {
|
||||
ret += getString(R.string.careportal_newnstreatment_insulin_label);
|
||||
ret += ": ";
|
||||
ret += data.get("insulin");
|
||||
ret += " U\n";
|
||||
}
|
||||
if (data.has("duration")) {
|
||||
ret += getString(R.string.careportal_newnstreatment_duration_label);
|
||||
ret += ": ";
|
||||
ret += data.get("duration");
|
||||
ret += " min\n";
|
||||
}
|
||||
if (data.has("percent")) {
|
||||
ret += getString(R.string.careportal_newnstreatment_percent_label);
|
||||
ret += ": ";
|
||||
ret += data.get("percent");
|
||||
ret += " %\n";
|
||||
}
|
||||
if (data.has("absolute")) {
|
||||
ret += getString(R.string.careportal_newnstreatment_absolute_label);
|
||||
ret += ": ";
|
||||
ret += data.get("absolute");
|
||||
ret += " U/h\n";
|
||||
}
|
||||
if (data.has("preBolus")) {
|
||||
ret += getString(R.string.careportal_newnstreatment_carbtime_label);
|
||||
ret += ": ";
|
||||
ret += data.get("preBolus");
|
||||
ret += " min\n";
|
||||
}
|
||||
if (data.has("notes")) {
|
||||
ret += getString(R.string.careportal_newnstreatment_notes_label);
|
||||
ret += ": ";
|
||||
ret += data.get("notes");
|
||||
ret += "\n";
|
||||
}
|
||||
if (data.has("profile")) {
|
||||
ret += getString(R.string.careportal_newnstreatment_profile_label);
|
||||
ret += ": ";
|
||||
ret += data.get("profile");
|
||||
ret += "\n";
|
||||
}
|
||||
if (data.has("percentage")) {
|
||||
ret += getString(R.string.careportal_newnstreatment_percentage_label);
|
||||
ret += ": ";
|
||||
ret += data.get("percentage");
|
||||
ret += " %\n";
|
||||
}
|
||||
if (data.has("timeshift")) {
|
||||
ret += getString(R.string.careportal_newnstreatment_timeshift_label);
|
||||
ret += ": ";
|
||||
ret += data.get("timeshift");
|
||||
ret += " h\n";
|
||||
}
|
||||
if (data.has("targetBottom") && data.has("targetTop")) {
|
||||
ret += getString(R.string.target_range);
|
||||
ret += " ";
|
||||
ret += data.get("targetBottom");
|
||||
ret += " - ";
|
||||
ret += data.get("targetTop");
|
||||
ret += "\n";
|
||||
}
|
||||
if (data.has("created_at")) {
|
||||
ret += getString(R.string.careportal_newnstreatment_eventtime_label);
|
||||
ret += ": ";
|
||||
ret += eventTime.toLocaleString();
|
||||
ret += "\n";
|
||||
}
|
||||
if (data.has("enteredBy")) {
|
||||
ret += getString(R.string.careportal_newnstreatment_enteredby_title);
|
||||
ret += ": ";
|
||||
ret += data.get("enteredBy");
|
||||
ret += "\n";
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
if (data.has("eventType")) {
|
||||
ret += MainApp.gs(R.string.careportal_newnstreatment_eventtype);
|
||||
ret += ": ";
|
||||
ret += Translator.translate(JsonHelper.safeGetString(data, "eventType", ""));
|
||||
ret += "\n";
|
||||
}
|
||||
if (data.has("glucose")) {
|
||||
ret += MainApp.gs(R.string.treatments_wizard_bg_label);
|
||||
ret += ": ";
|
||||
ret += JsonHelper.safeGetObject(data, "glucose", "");
|
||||
ret += " " + units + "\n";
|
||||
}
|
||||
if (data.has("glucoseType")) {
|
||||
ret += MainApp.gs(R.string.careportal_newnstreatment_glucosetype);
|
||||
ret += ": ";
|
||||
ret += Translator.translate(JsonHelper.safeGetString(data, "glucoseType", ""));
|
||||
ret += "\n";
|
||||
}
|
||||
if (data.has("carbs")) {
|
||||
ret += MainApp.gs(R.string.careportal_newnstreatment_carbs_label);
|
||||
ret += ": ";
|
||||
ret += JsonHelper.safeGetObject(data, "carbs", "");
|
||||
ret += " g\n";
|
||||
}
|
||||
if (data.has("insulin")) {
|
||||
ret += MainApp.gs(R.string.careportal_newnstreatment_insulin_label);
|
||||
ret += ": ";
|
||||
ret += JsonHelper.safeGetObject(data, "insulin", "");
|
||||
ret += " U\n";
|
||||
}
|
||||
if (data.has("duration")) {
|
||||
ret += MainApp.gs(R.string.careportal_newnstreatment_duration_label);
|
||||
ret += ": ";
|
||||
ret += JsonHelper.safeGetObject(data, "duration", "");
|
||||
ret += " min\n";
|
||||
}
|
||||
if (data.has("percent")) {
|
||||
ret += MainApp.gs(R.string.careportal_newnstreatment_percent_label);
|
||||
ret += ": ";
|
||||
ret += JsonHelper.safeGetObject(data, "percent", "");
|
||||
ret += " %\n";
|
||||
}
|
||||
if (data.has("absolute")) {
|
||||
ret += MainApp.gs(R.string.careportal_newnstreatment_absolute_label);
|
||||
ret += ": ";
|
||||
ret += JsonHelper.safeGetObject(data, "absolute", "");
|
||||
ret += " U/h\n";
|
||||
}
|
||||
if (data.has("preBolus")) {
|
||||
ret += MainApp.gs(R.string.careportal_newnstreatment_carbtime_label);
|
||||
ret += ": ";
|
||||
ret += JsonHelper.safeGetObject(data, "preBolus", "");
|
||||
ret += " min\n";
|
||||
}
|
||||
if (data.has("notes")) {
|
||||
ret += MainApp.gs(R.string.careportal_newnstreatment_notes_label);
|
||||
ret += ": ";
|
||||
ret += JsonHelper.safeGetObject(data, "notes", "");
|
||||
ret += "\n";
|
||||
}
|
||||
if (data.has("profile")) {
|
||||
ret += MainApp.gs(R.string.careportal_newnstreatment_profile_label);
|
||||
ret += ": ";
|
||||
ret += JsonHelper.safeGetObject(data, "profile", "");
|
||||
ret += "\n";
|
||||
}
|
||||
if (data.has("percentage")) {
|
||||
ret += MainApp.gs(R.string.careportal_newnstreatment_percentage_label);
|
||||
ret += ": ";
|
||||
ret += JsonHelper.safeGetObject(data, "percentage", "");
|
||||
ret += " %\n";
|
||||
}
|
||||
if (data.has("timeshift")) {
|
||||
ret += MainApp.gs(R.string.careportal_newnstreatment_timeshift_label);
|
||||
ret += ": ";
|
||||
ret += JsonHelper.safeGetObject(data, "timeshift", "");
|
||||
ret += " h\n";
|
||||
}
|
||||
if (data.has("targetBottom") && data.has("targetTop")) {
|
||||
ret += MainApp.gs(R.string.target_range);
|
||||
ret += " ";
|
||||
ret += JsonHelper.safeGetObject(data, "targetBottom", "");
|
||||
ret += " - ";
|
||||
ret += JsonHelper.safeGetObject(data, "targetTop", "");
|
||||
ret += "\n";
|
||||
}
|
||||
if (data.has("created_at")) {
|
||||
ret += MainApp.gs(R.string.careportal_newnstreatment_eventtime_label);
|
||||
ret += ": ";
|
||||
ret += eventTime.toLocaleString();
|
||||
ret += "\n";
|
||||
}
|
||||
if (data.has("enteredBy")) {
|
||||
ret += MainApp.gs(R.string.careportal_newnstreatment_enteredby_title);
|
||||
ret += ": ";
|
||||
ret += JsonHelper.safeGetObject(data, "enteredBy", "");
|
||||
ret += "\n";
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void createNSTreatment() {
|
||||
final JSONObject data = gatherData();
|
||||
String confirmText = buildConfirmText(data);
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
|
||||
builder.setTitle(getContext().getString(R.string.confirmation));
|
||||
builder.setMessage(confirmText);
|
||||
builder.setPositiveButton(getContext().getString(R.string.ok), new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
if (options.executeProfileSwitch) {
|
||||
if (data.has("profile")) {
|
||||
try {
|
||||
doProfileSwitch(profileStore, data.getString("profile"), data.getInt("duration"), data.getInt("percentage"), data.getInt("timeshift"));
|
||||
} catch (JSONException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
}
|
||||
} else if (options.executeTempTarget) {
|
||||
try {
|
||||
if ((data.has("targetBottom") && data.has("targetTop")) || (data.has("duration") && data.getInt("duration") == 0)) {
|
||||
TempTarget tempTarget = new TempTarget();
|
||||
tempTarget.date = eventTime.getTime();
|
||||
tempTarget.durationInMinutes = data.getInt("duration");
|
||||
tempTarget.reason = data.getString("reason");
|
||||
tempTarget.source = Source.USER;
|
||||
if (tempTarget.durationInMinutes != 0) {
|
||||
tempTarget.low = Profile.toMgdl(data.getDouble("targetBottom"), profile.getUnits());
|
||||
tempTarget.high = Profile.toMgdl(data.getDouble("targetTop"), profile.getUnits());
|
||||
} else {
|
||||
tempTarget.low = 0;
|
||||
tempTarget.high = 0;
|
||||
}
|
||||
log.debug("Creating new TempTarget db record: " + tempTarget.toString());
|
||||
MainApp.getDbHelper().createOrUpdate(tempTarget);
|
||||
NSUpload.uploadCareportalEntryToNS(data);
|
||||
Answers.getInstance().logCustom(new CustomEvent("TempTarget"));
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
} else {
|
||||
NSUpload.uploadCareportalEntryToNS(data);
|
||||
Answers.getInstance().logCustom(new CustomEvent("NSTreatment"));
|
||||
}
|
||||
}
|
||||
});
|
||||
builder.setNegativeButton(getContext().getString(R.string.cancel), null);
|
||||
builder.show();
|
||||
void confirmNSTreatmentCreation() {
|
||||
if (context != null) {
|
||||
final JSONObject data = gatherData();
|
||||
final String confirmText = buildConfirmText(data);
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||
builder.setTitle(MainApp.gs(R.string.confirmation));
|
||||
builder.setMessage(confirmText);
|
||||
builder.setPositiveButton(MainApp.gs(R.string.ok), (dialog, id) -> createNSTreatment(data));
|
||||
builder.setNegativeButton(MainApp.gs(R.string.cancel), null);
|
||||
builder.show();
|
||||
}
|
||||
}
|
||||
|
||||
public static void doProfileSwitch(final ProfileStore profileStore, final String profileName, final int duration, final int percentage, final int timeshift) {
|
||||
|
||||
public void createNSTreatment(JSONObject data) {
|
||||
if (options.executeProfileSwitch) {
|
||||
if (data.has("profile")) {
|
||||
doProfileSwitch(profileStore, JsonHelper.safeGetString(data, "profile"), JsonHelper.safeGetInt(data, "duration"), JsonHelper.safeGetInt(data, "percentage"), JsonHelper.safeGetInt(data, "timeshift"));
|
||||
}
|
||||
} else if (options.executeTempTarget) {
|
||||
final int duration = JsonHelper.safeGetInt(data, "duration");
|
||||
final double targetBottom = JsonHelper.safeGetDouble(data, "targetBottom");
|
||||
final double targetTop = JsonHelper.safeGetDouble(data, "targetTop");
|
||||
final String reason = JsonHelper.safeGetString(data, "reason", "");
|
||||
if ((targetBottom != 0d && targetTop != 0d) || duration == 0) {
|
||||
TempTarget tempTarget = new TempTarget()
|
||||
.date(eventTime.getTime())
|
||||
.duration(duration)
|
||||
.reason(reason)
|
||||
.source(Source.USER);
|
||||
if (tempTarget.durationInMinutes != 0) {
|
||||
tempTarget.low(Profile.toMgdl(targetBottom, profile.getUnits()))
|
||||
.high(Profile.toMgdl(targetTop, profile.getUnits()));
|
||||
} else {
|
||||
tempTarget.low(0).high(0);
|
||||
}
|
||||
TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget);
|
||||
FabricPrivacy.getInstance().logCustom(new CustomEvent("TempTarget"));
|
||||
}
|
||||
} else {
|
||||
if (JsonHelper.safeGetString(data, "eventType").equals(CareportalEvent.PROFILESWITCH)) {
|
||||
ProfileSwitch profileSwitch = prepareProfileSwitch(
|
||||
profileStore,
|
||||
JsonHelper.safeGetString(data, "profile"),
|
||||
JsonHelper.safeGetInt(data, "duration"),
|
||||
JsonHelper.safeGetInt(data, "percentage"),
|
||||
JsonHelper.safeGetInt(data, "timeshift"),
|
||||
eventTime.getTime()
|
||||
);
|
||||
NSUpload.uploadProfileSwitch(profileSwitch);
|
||||
} else {
|
||||
NSUpload.uploadCareportalEntryToNS(data);
|
||||
}
|
||||
FabricPrivacy.getInstance().logCustom(new CustomEvent("NSTreatment"));
|
||||
}
|
||||
}
|
||||
|
||||
public static ProfileSwitch prepareProfileSwitch(final ProfileStore profileStore, final String profileName, final int duration, final int percentage, final int timeshift, long date) {
|
||||
ProfileSwitch profileSwitch = new ProfileSwitch();
|
||||
profileSwitch.date = System.currentTimeMillis();
|
||||
profileSwitch.date = date;
|
||||
profileSwitch.source = Source.USER;
|
||||
profileSwitch.profileName = profileName;
|
||||
profileSwitch.profileJson = profileStore.getSpecificProfile(profileName).getData().toString();
|
||||
profileSwitch.profilePlugin = ConfigBuilderPlugin.getActiveProfileInterface().getClass().getName();
|
||||
profileSwitch.profilePlugin = MainApp.getConfigBuilder().getActiveProfileInterface().getClass().getName();
|
||||
profileSwitch.durationInMinutes = duration;
|
||||
profileSwitch.isCPP = percentage != 100 || timeshift != 0;
|
||||
profileSwitch.timeshift = timeshift;
|
||||
profileSwitch.percentage = percentage;
|
||||
MainApp.getConfigBuilder().addToHistoryProfileSwitch(profileSwitch);
|
||||
return profileSwitch;
|
||||
}
|
||||
|
||||
ConfigBuilderPlugin.getCommandQueue().setProfile(profileSwitch.getProfileObject(), new Callback() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!result.success) {
|
||||
Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class);
|
||||
i.putExtra("soundid", R.raw.boluserror);
|
||||
i.putExtra("status", result.comment);
|
||||
i.putExtra("title", MainApp.sResources.getString(R.string.failedupdatebasalprofile));
|
||||
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
MainApp.instance().startActivity(i);
|
||||
}
|
||||
MainApp.bus().post(new EventNewBasalProfile());
|
||||
}
|
||||
});
|
||||
Answers.getInstance().logCustom(new CustomEvent("ProfileSwitch"));
|
||||
public static void doProfileSwitch(final ProfileStore profileStore, final String profileName, final int duration, final int percentage, final int timeshift) {
|
||||
ProfileSwitch profileSwitch = prepareProfileSwitch(profileStore, profileName, duration, percentage, timeshift, System.currentTimeMillis());
|
||||
TreatmentsPlugin.getPlugin().addToHistoryProfileSwitch(profileSwitch);
|
||||
FabricPrivacy.getInstance().logCustom(new CustomEvent("ProfileSwitch"));
|
||||
}
|
||||
|
||||
public static void doProfileSwitch(final int duration, final int percentage, final int timeshift) {
|
||||
ProfileSwitch profileSwitch = MainApp.getConfigBuilder().getProfileSwitchFromHistory(System.currentTimeMillis());
|
||||
ProfileSwitch profileSwitch = TreatmentsPlugin.getPlugin().getProfileSwitchFromHistory(System.currentTimeMillis());
|
||||
if (profileSwitch != null) {
|
||||
profileSwitch = new ProfileSwitch();
|
||||
profileSwitch.date = System.currentTimeMillis();
|
||||
profileSwitch.source = Source.USER;
|
||||
profileSwitch.profileName = MainApp.getConfigBuilder().getProfileName(System.currentTimeMillis(), false);
|
||||
profileSwitch.profileJson = MainApp.getConfigBuilder().getProfile().getData().toString();
|
||||
profileSwitch.profilePlugin = ConfigBuilderPlugin.getActiveProfileInterface().getClass().getName();
|
||||
profileSwitch.profilePlugin = MainApp.getConfigBuilder().getActiveProfileInterface().getClass().getName();
|
||||
profileSwitch.durationInMinutes = duration;
|
||||
profileSwitch.isCPP = percentage != 100 || timeshift != 0;
|
||||
profileSwitch.timeshift = timeshift;
|
||||
profileSwitch.percentage = percentage;
|
||||
MainApp.getConfigBuilder().addToHistoryProfileSwitch(profileSwitch);
|
||||
|
||||
ConfigBuilderPlugin.getCommandQueue().setProfile(profileSwitch.getProfileObject(), new Callback() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!result.success) {
|
||||
Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class);
|
||||
i.putExtra("soundid", R.raw.boluserror);
|
||||
i.putExtra("status", result.comment);
|
||||
i.putExtra("title", MainApp.sResources.getString(R.string.failedupdatebasalprofile));
|
||||
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
MainApp.instance().startActivity(i);
|
||||
}
|
||||
MainApp.bus().post(new EventNewBasalProfile());
|
||||
}
|
||||
});
|
||||
Answers.getInstance().logCustom(new CustomEvent("ProfileSwitch"));
|
||||
TreatmentsPlugin.getPlugin().addToHistoryProfileSwitch(profileSwitch);
|
||||
FabricPrivacy.getInstance().logCustom(new CustomEvent("ProfileSwitch"));
|
||||
} else {
|
||||
log.error("No profile switch existing");
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ package info.nightscout.androidaps.plugins.ConfigBuilder;
|
|||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
@ -17,12 +17,14 @@ import android.widget.ListAdapter;
|
|||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.crashlytics.android.Crashlytics;
|
||||
import com.crashlytics.android.answers.Answers;
|
||||
import com.crashlytics.android.answers.CustomEvent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.PreferencesActivity;
|
||||
import info.nightscout.androidaps.R;
|
||||
|
@ -33,43 +35,59 @@ import info.nightscout.androidaps.interfaces.BgSourceInterface;
|
|||
import info.nightscout.androidaps.interfaces.ConstraintsInterface;
|
||||
import info.nightscout.androidaps.interfaces.InsulinInterface;
|
||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||
import info.nightscout.androidaps.interfaces.PluginType;
|
||||
import info.nightscout.androidaps.interfaces.ProfileInterface;
|
||||
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||
import info.nightscout.androidaps.interfaces.SensitivityInterface;
|
||||
import info.nightscout.androidaps.plugins.Insulin.InsulinFastactingPlugin;
|
||||
import info.nightscout.androidaps.plugins.Common.SubscriberFragment;
|
||||
import info.nightscout.androidaps.plugins.Insulin.InsulinOrefRapidActingPlugin;
|
||||
import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin;
|
||||
import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin;
|
||||
import info.nightscout.androidaps.plugins.SensitivityOref0.SensitivityOref0Plugin;
|
||||
import info.nightscout.utils.FabricPrivacy;
|
||||
import info.nightscout.utils.PasswordProtection;
|
||||
|
||||
|
||||
public class ConfigBuilderFragment extends Fragment {
|
||||
|
||||
static ConfigBuilderPlugin configBuilderPlugin = new ConfigBuilderPlugin();
|
||||
|
||||
static public ConfigBuilderPlugin getPlugin() {
|
||||
return configBuilderPlugin;
|
||||
}
|
||||
public class ConfigBuilderFragment extends SubscriberFragment {
|
||||
|
||||
@BindView(R.id.configbuilder_insulinlistview)
|
||||
ListView insulinListView;
|
||||
@BindView(R.id.configbuilder_sensitivitylistview)
|
||||
ListView sensitivityListView;
|
||||
@BindView(R.id.configbuilder_bgsourcelistview)
|
||||
ListView bgsourceListView;
|
||||
@BindView(R.id.configbuilder_bgsourcelabel)
|
||||
TextView bgsourceLabel;
|
||||
@BindView(R.id.configbuilder_pumplistview)
|
||||
ListView pumpListView;
|
||||
@BindView(R.id.configbuilder_pumplabel)
|
||||
TextView pumpLabel;
|
||||
@BindView(R.id.configbuilder_looplistview)
|
||||
ListView loopListView;
|
||||
@BindView(R.id.configbuilder_looplabel)
|
||||
TextView loopLabel;
|
||||
@BindView(R.id.configbuilder_treatmentslistview)
|
||||
ListView treatmentsListView;
|
||||
@BindView(R.id.configbuilder_treatmentslabel)
|
||||
TextView treatmentsLabel;
|
||||
@BindView(R.id.configbuilder_profilelistview)
|
||||
ListView profileListView;
|
||||
@BindView(R.id.configbuilder_profilelabel)
|
||||
TextView profileLabel;
|
||||
@BindView(R.id.configbuilder_apslistview)
|
||||
ListView apsListView;
|
||||
@BindView(R.id.configbuilder_apslabel)
|
||||
TextView apsLabel;
|
||||
@BindView(R.id.configbuilder_constraintslistview)
|
||||
ListView constraintsListView;
|
||||
@BindView(R.id.configbuilder_constraintslabel)
|
||||
TextView constraintsLabel;
|
||||
@BindView(R.id.configbuilder_generallistview)
|
||||
ListView generalListView;
|
||||
|
||||
@BindView(R.id.configbuilder_mainlayout)
|
||||
LinearLayout mainLayout;
|
||||
@BindView(R.id.configbuilder_unlock)
|
||||
Button unlock;
|
||||
|
||||
PluginCustomAdapter insulinDataAdapter = null;
|
||||
|
@ -84,105 +102,83 @@ public class ConfigBuilderFragment extends Fragment {
|
|||
PluginCustomAdapter generalDataAdapter = null;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
try {
|
||||
View view = inflater.inflate(R.layout.configbuilder_fragment, container, false);
|
||||
|
||||
insulinListView = (ListView) view.findViewById(R.id.configbuilder_insulinlistview);
|
||||
sensitivityListView = (ListView) view.findViewById(R.id.configbuilder_sensitivitylistview);
|
||||
bgsourceListView = (ListView) view.findViewById(R.id.configbuilder_bgsourcelistview);
|
||||
bgsourceLabel = (TextView) view.findViewById(R.id.configbuilder_bgsourcelabel);
|
||||
pumpListView = (ListView) view.findViewById(R.id.configbuilder_pumplistview);
|
||||
pumpLabel = (TextView) view.findViewById(R.id.configbuilder_pumplabel);
|
||||
loopListView = (ListView) view.findViewById(R.id.configbuilder_looplistview);
|
||||
loopLabel = (TextView) view.findViewById(R.id.configbuilder_looplabel);
|
||||
treatmentsListView = (ListView) view.findViewById(R.id.configbuilder_treatmentslistview);
|
||||
treatmentsLabel = (TextView) view.findViewById(R.id.configbuilder_treatmentslabel);
|
||||
profileListView = (ListView) view.findViewById(R.id.configbuilder_profilelistview);
|
||||
profileLabel = (TextView) view.findViewById(R.id.configbuilder_profilelabel);
|
||||
apsListView = (ListView) view.findViewById(R.id.configbuilder_apslistview);
|
||||
apsLabel = (TextView) view.findViewById(R.id.configbuilder_apslabel);
|
||||
constraintsListView = (ListView) view.findViewById(R.id.configbuilder_constraintslistview);
|
||||
constraintsLabel = (TextView) view.findViewById(R.id.configbuilder_constraintslabel);
|
||||
generalListView = (ListView) view.findViewById(R.id.configbuilder_generallistview);
|
||||
unbinder = ButterKnife.bind(this, view);
|
||||
|
||||
mainLayout = (LinearLayout) view.findViewById(R.id.configbuilder_mainlayout);
|
||||
unlock = (Button) view.findViewById(R.id.configbuilder_unlock);
|
||||
|
||||
setViews();
|
||||
|
||||
if (PasswordProtection.isLocked("settings_password")) {
|
||||
if (PasswordProtection.isLocked("settings_password"))
|
||||
mainLayout.setVisibility(View.GONE);
|
||||
unlock.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
PasswordProtection.QueryPassword(getContext(), R.string.settings_password, "settings_password", new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mainLayout.setVisibility(View.VISIBLE);
|
||||
unlock.setVisibility(View.GONE);
|
||||
}
|
||||
}, null);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
else
|
||||
unlock.setVisibility(View.GONE);
|
||||
}
|
||||
return view;
|
||||
} catch (Exception e) {
|
||||
Crashlytics.logException(e);
|
||||
FabricPrivacy.logException(e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
void setViews() {
|
||||
insulinDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInListByInterface(InsulinInterface.class, PluginBase.INSULIN), PluginBase.INSULIN);
|
||||
@OnClick(R.id.configbuilder_unlock)
|
||||
public void onClickUnlock() {
|
||||
PasswordProtection.QueryPassword(getContext(), R.string.settings_password, "settings_password", () -> {
|
||||
mainLayout.setVisibility(View.VISIBLE);
|
||||
unlock.setVisibility(View.GONE);
|
||||
}, null);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void updateGUI() {
|
||||
|
||||
insulinDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInListByInterface(InsulinInterface.class, PluginType.INSULIN), PluginType.INSULIN);
|
||||
insulinListView.setAdapter(insulinDataAdapter);
|
||||
setListViewHeightBasedOnChildren(insulinListView);
|
||||
bgsourceDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInListByInterface(BgSourceInterface.class, PluginBase.BGSOURCE), PluginBase.BGSOURCE);
|
||||
bgsourceDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInListByInterface(BgSourceInterface.class, PluginType.BGSOURCE), PluginType.BGSOURCE);
|
||||
bgsourceListView.setAdapter(bgsourceDataAdapter);
|
||||
if (MainApp.getSpecificPluginsVisibleInList(PluginBase.BGSOURCE).size() == 0)
|
||||
if (MainApp.getSpecificPluginsVisibleInList(PluginType.BGSOURCE).size() == 0)
|
||||
bgsourceLabel.setVisibility(View.GONE);
|
||||
setListViewHeightBasedOnChildren(bgsourceListView);
|
||||
pumpDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInList(PluginBase.PUMP), PluginBase.PUMP);
|
||||
pumpDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInList(PluginType.PUMP), PluginType.PUMP);
|
||||
pumpListView.setAdapter(pumpDataAdapter);
|
||||
if (MainApp.getSpecificPluginsVisibleInList(PluginBase.PUMP).size() == 0)
|
||||
if (MainApp.getSpecificPluginsVisibleInList(PluginType.PUMP).size() == 0 || Config.NSCLIENT || Config.G5UPLOADER) {
|
||||
pumpLabel.setVisibility(View.GONE);
|
||||
pumpListView.setVisibility(View.GONE);
|
||||
}
|
||||
setListViewHeightBasedOnChildren(pumpListView);
|
||||
loopDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInList(PluginBase.LOOP), PluginBase.LOOP);
|
||||
loopDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInList(PluginType.LOOP), PluginType.LOOP);
|
||||
loopListView.setAdapter(loopDataAdapter);
|
||||
setListViewHeightBasedOnChildren(loopListView);
|
||||
if (MainApp.getSpecificPluginsVisibleInList(PluginBase.LOOP).size() == 0)
|
||||
if (MainApp.getSpecificPluginsVisibleInList(PluginType.LOOP).size() == 0)
|
||||
loopLabel.setVisibility(View.GONE);
|
||||
treatmentDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInList(PluginBase.TREATMENT), PluginBase.TREATMENT);
|
||||
treatmentDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInList(PluginType.TREATMENT), PluginType.TREATMENT);
|
||||
treatmentsListView.setAdapter(treatmentDataAdapter);
|
||||
setListViewHeightBasedOnChildren(treatmentsListView);
|
||||
if (MainApp.getSpecificPluginsVisibleInList(PluginBase.TREATMENT).size() == 0)
|
||||
if (MainApp.getSpecificPluginsVisibleInList(PluginType.TREATMENT).size() == 0)
|
||||
treatmentsLabel.setVisibility(View.GONE);
|
||||
profileDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInListByInterface(ProfileInterface.class, PluginBase.PROFILE), PluginBase.PROFILE);
|
||||
profileDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInListByInterface(ProfileInterface.class, PluginType.PROFILE), PluginType.PROFILE);
|
||||
profileListView.setAdapter(profileDataAdapter);
|
||||
if (MainApp.getSpecificPluginsVisibleInList(PluginBase.PROFILE).size() == 0)
|
||||
if (MainApp.getSpecificPluginsVisibleInList(PluginType.PROFILE).size() == 0)
|
||||
profileLabel.setVisibility(View.GONE);
|
||||
setListViewHeightBasedOnChildren(profileListView);
|
||||
apsDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInList(PluginBase.APS), PluginBase.APS);
|
||||
apsDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInList(PluginType.APS), PluginType.APS);
|
||||
apsListView.setAdapter(apsDataAdapter);
|
||||
setListViewHeightBasedOnChildren(apsListView);
|
||||
if (MainApp.getSpecificPluginsVisibleInList(PluginBase.APS).size() == 0)
|
||||
if (MainApp.getSpecificPluginsVisibleInList(PluginType.APS).size() == 0)
|
||||
apsLabel.setVisibility(View.GONE);
|
||||
sensivityDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInListByInterface(SensitivityInterface.class, PluginBase.SENSITIVITY), PluginBase.SENSITIVITY);
|
||||
sensivityDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInListByInterface(SensitivityInterface.class, PluginType.SENSITIVITY), PluginType.SENSITIVITY);
|
||||
sensitivityListView.setAdapter(sensivityDataAdapter);
|
||||
setListViewHeightBasedOnChildren(sensitivityListView);
|
||||
constraintsDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInListByInterface(ConstraintsInterface.class, PluginBase.CONSTRAINTS), PluginBase.CONSTRAINTS);
|
||||
constraintsDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInListByInterface(ConstraintsInterface.class, PluginType.CONSTRAINTS), PluginType.CONSTRAINTS);
|
||||
constraintsListView.setAdapter(constraintsDataAdapter);
|
||||
setListViewHeightBasedOnChildren(constraintsListView);
|
||||
if (MainApp.getSpecificPluginsVisibleInList(PluginBase.CONSTRAINTS).size() == 0)
|
||||
if (MainApp.getSpecificPluginsVisibleInList(PluginType.CONSTRAINTS).size() == 0)
|
||||
constraintsLabel.setVisibility(View.GONE);
|
||||
generalDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInList(PluginBase.GENERAL), PluginBase.GENERAL);
|
||||
generalDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInList(PluginType.GENERAL), PluginType.GENERAL);
|
||||
generalListView.setAdapter(generalDataAdapter);
|
||||
setListViewHeightBasedOnChildren(generalListView);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -192,10 +188,10 @@ public class ConfigBuilderFragment extends Fragment {
|
|||
private class PluginCustomAdapter extends ArrayAdapter<PluginBase> {
|
||||
|
||||
private ArrayList<PluginBase> pluginList;
|
||||
final private int type;
|
||||
final private PluginType type;
|
||||
|
||||
public PluginCustomAdapter(Context context, int textViewResourceId,
|
||||
ArrayList<PluginBase> pluginList, int type) {
|
||||
PluginCustomAdapter(Context context, int textViewResourceId,
|
||||
ArrayList<PluginBase> pluginList, PluginType type) {
|
||||
super(context, textViewResourceId, pluginList);
|
||||
this.pluginList = new ArrayList<>();
|
||||
this.pluginList.addAll(pluginList);
|
||||
|
@ -209,10 +205,11 @@ public class ConfigBuilderFragment extends Fragment {
|
|||
ImageView settings;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public View getView(int position, View view, ViewGroup parent) {
|
||||
public View getView(int position, View view, @NonNull ViewGroup parent) {
|
||||
|
||||
PluginViewHolder holder = null;
|
||||
PluginViewHolder holder;
|
||||
PluginBase plugin = pluginList.get(position);
|
||||
|
||||
if (view == null) {
|
||||
|
@ -231,60 +228,45 @@ public class ConfigBuilderFragment extends Fragment {
|
|||
|
||||
view.setTag(holder);
|
||||
|
||||
holder.checkboxEnabled.setOnClickListener(new View.OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
CheckBox cb = (CheckBox) v;
|
||||
PluginBase plugin = (PluginBase) cb.getTag();
|
||||
plugin.setFragmentEnabled(type, cb.isChecked());
|
||||
plugin.setFragmentVisible(type, cb.isChecked());
|
||||
onEnabledCategoryChanged(plugin, type);
|
||||
configBuilderPlugin.storeSettings();
|
||||
MainApp.bus().post(new EventRefreshGui());
|
||||
MainApp.bus().post(new EventConfigBuilderChange());
|
||||
getPlugin().logPluginStatus();
|
||||
Answers.getInstance().logCustom(new CustomEvent("ConfigurationChange"));
|
||||
}
|
||||
holder.checkboxEnabled.setOnClickListener(v -> {
|
||||
CheckBox cb = (CheckBox) v;
|
||||
PluginBase plugin1 = (PluginBase) cb.getTag();
|
||||
plugin1.setPluginEnabled(type, cb.isChecked());
|
||||
plugin1.setFragmentVisible(type, cb.isChecked());
|
||||
onEnabledCategoryChanged(plugin1, type);
|
||||
ConfigBuilderPlugin.getPlugin().storeSettings("CheckedCheckboxEnabled");
|
||||
MainApp.bus().post(new EventRefreshGui());
|
||||
MainApp.bus().post(new EventConfigBuilderChange());
|
||||
ConfigBuilderPlugin.getPlugin().logPluginStatus();
|
||||
FabricPrivacy.getInstance().logCustom(new CustomEvent("ConfigurationChange"));
|
||||
});
|
||||
|
||||
holder.checkboxVisible.setOnClickListener(new View.OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
CheckBox cb = (CheckBox) v;
|
||||
PluginBase plugin = (PluginBase) cb.getTag();
|
||||
plugin.setFragmentVisible(type, cb.isChecked());
|
||||
configBuilderPlugin.storeSettings();
|
||||
MainApp.bus().post(new EventRefreshGui());
|
||||
getPlugin().logPluginStatus();
|
||||
}
|
||||
holder.checkboxVisible.setOnClickListener(v -> {
|
||||
CheckBox cb = (CheckBox) v;
|
||||
PluginBase plugin12 = (PluginBase) cb.getTag();
|
||||
plugin12.setFragmentVisible(type, cb.isChecked());
|
||||
ConfigBuilderPlugin.getPlugin().storeSettings("CheckedCheckboxVisible");
|
||||
MainApp.bus().post(new EventRefreshGui());
|
||||
ConfigBuilderPlugin.getPlugin().logPluginStatus();
|
||||
});
|
||||
|
||||
holder.settings.setOnClickListener(new View.OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
final PluginBase plugin = (PluginBase) v.getTag();
|
||||
PasswordProtection.QueryPassword(getContext(), R.string.settings_password, "settings_password", new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Intent i = new Intent(getContext(), PreferencesActivity.class);
|
||||
i.putExtra("id", plugin.getPreferencesId());
|
||||
startActivity(i);
|
||||
}
|
||||
}, null);
|
||||
}
|
||||
holder.settings.setOnClickListener(v -> {
|
||||
final PluginBase plugin13 = (PluginBase) v.getTag();
|
||||
PasswordProtection.QueryPassword(getContext(), R.string.settings_password, "settings_password", () -> {
|
||||
Intent i = new Intent(getContext(), PreferencesActivity.class);
|
||||
i.putExtra("id", plugin13.getPreferencesId());
|
||||
startActivity(i);
|
||||
}, null);
|
||||
});
|
||||
|
||||
holder.name.setOnLongClickListener(new View.OnLongClickListener() {
|
||||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
final PluginBase plugin = (PluginBase) v.getTag();
|
||||
PasswordProtection.QueryPassword(getContext(), R.string.settings_password, "settings_password", new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Intent i = new Intent(getContext(), PreferencesActivity.class);
|
||||
i.putExtra("id", plugin.getPreferencesId());
|
||||
startActivity(i);
|
||||
}
|
||||
}, null);
|
||||
return false;
|
||||
}
|
||||
holder.name.setOnLongClickListener(v -> {
|
||||
final PluginBase plugin14 = (PluginBase) v.getTag();
|
||||
PasswordProtection.QueryPassword(getContext(), R.string.settings_password, "settings_password", () -> {
|
||||
Intent i = new Intent(getContext(), PreferencesActivity.class);
|
||||
i.putExtra("id", plugin14.getPreferencesId());
|
||||
startActivity(i);
|
||||
}, null);
|
||||
return false;
|
||||
});
|
||||
|
||||
} else {
|
||||
|
@ -293,15 +275,18 @@ public class ConfigBuilderFragment extends Fragment {
|
|||
|
||||
holder.name.setText(plugin.getName());
|
||||
holder.checkboxEnabled.setChecked(plugin.isEnabled(type));
|
||||
holder.checkboxVisible.setChecked(plugin.isVisibleInTabs(type));
|
||||
holder.checkboxVisible.setChecked(plugin.isFragmentVisible());
|
||||
holder.name.setTag(plugin);
|
||||
holder.checkboxEnabled.setTag(plugin);
|
||||
holder.checkboxVisible.setTag(plugin);
|
||||
holder.settings.setTag(plugin);
|
||||
|
||||
if (!plugin.canBeHidden(type)) {
|
||||
if (plugin.pluginDescription.alwaysEnabled) {
|
||||
holder.checkboxEnabled.setEnabled(false);
|
||||
}
|
||||
|
||||
if (plugin.pluginDescription.alwayVisible) {
|
||||
holder.checkboxEnabled.setEnabled(false);
|
||||
holder.checkboxVisible.setEnabled(false);
|
||||
}
|
||||
|
||||
if (!plugin.isEnabled(type)) {
|
||||
|
@ -313,19 +298,19 @@ public class ConfigBuilderFragment extends Fragment {
|
|||
}
|
||||
|
||||
// Hide enabled control and force enabled plugin if there is only one plugin available
|
||||
if (type == PluginBase.INSULIN || type == PluginBase.PUMP || type == PluginBase.TREATMENT || type == PluginBase.PROFILE || type == PluginBase.SENSITIVITY)
|
||||
if (type == PluginType.INSULIN || type == PluginType.PUMP || type == PluginType.SENSITIVITY)
|
||||
if (pluginList.size() < 2) {
|
||||
holder.checkboxEnabled.setEnabled(false);
|
||||
plugin.setFragmentEnabled(type, true);
|
||||
getPlugin().storeSettings();
|
||||
plugin.setPluginEnabled(type, true);
|
||||
ConfigBuilderPlugin.getPlugin().storeSettings("ForceEnable");
|
||||
}
|
||||
|
||||
// Constraints cannot be disabled
|
||||
if (type == PluginBase.CONSTRAINTS)
|
||||
if (type == PluginType.CONSTRAINTS)
|
||||
holder.checkboxEnabled.setEnabled(false);
|
||||
|
||||
// Hide disabled profiles by default
|
||||
if (type == PluginBase.PROFILE) {
|
||||
if (type == PluginType.PROFILE) {
|
||||
if (!plugin.isEnabled(type)) {
|
||||
holder.checkboxVisible.setEnabled(false);
|
||||
holder.checkboxVisible.setChecked(false);
|
||||
|
@ -335,9 +320,9 @@ public class ConfigBuilderFragment extends Fragment {
|
|||
}
|
||||
|
||||
// Disable profile control for pump profiles if pump is not enabled
|
||||
if (type == PluginBase.PROFILE) {
|
||||
if (type == PluginType.PROFILE) {
|
||||
if (PumpInterface.class.isAssignableFrom(plugin.getClass())) {
|
||||
if (!plugin.isEnabled(PluginBase.PUMP)) {
|
||||
if (!plugin.isEnabled(PluginType.PUMP)) {
|
||||
holder.checkboxEnabled.setEnabled(false);
|
||||
holder.checkboxEnabled.setChecked(false);
|
||||
}
|
||||
|
@ -354,32 +339,32 @@ public class ConfigBuilderFragment extends Fragment {
|
|||
|
||||
}
|
||||
|
||||
void onEnabledCategoryChanged(PluginBase changedPlugin, int type) {
|
||||
void onEnabledCategoryChanged(PluginBase changedPlugin, PluginType type) {
|
||||
ArrayList<PluginBase> pluginsInCategory = null;
|
||||
switch (type) {
|
||||
// Multiple selection allowed
|
||||
case PluginBase.GENERAL:
|
||||
case PluginBase.CONSTRAINTS:
|
||||
case PluginBase.LOOP:
|
||||
case GENERAL:
|
||||
case CONSTRAINTS:
|
||||
case LOOP:
|
||||
break;
|
||||
// Single selection allowed
|
||||
case PluginBase.INSULIN:
|
||||
case INSULIN:
|
||||
pluginsInCategory = MainApp.getSpecificPluginsListByInterface(InsulinInterface.class);
|
||||
break;
|
||||
case PluginBase.SENSITIVITY:
|
||||
case SENSITIVITY:
|
||||
pluginsInCategory = MainApp.getSpecificPluginsListByInterface(SensitivityInterface.class);
|
||||
break;
|
||||
case PluginBase.APS:
|
||||
case APS:
|
||||
pluginsInCategory = MainApp.getSpecificPluginsListByInterface(APSInterface.class);
|
||||
break;
|
||||
case PluginBase.PROFILE:
|
||||
case PROFILE:
|
||||
pluginsInCategory = MainApp.getSpecificPluginsListByInterface(ProfileInterface.class);
|
||||
break;
|
||||
case PluginBase.BGSOURCE:
|
||||
case BGSOURCE:
|
||||
pluginsInCategory = MainApp.getSpecificPluginsListByInterface(BgSourceInterface.class);
|
||||
break;
|
||||
case PluginBase.TREATMENT:
|
||||
case PluginBase.PUMP:
|
||||
case TREATMENT:
|
||||
case PUMP:
|
||||
pluginsInCategory = MainApp.getSpecificPluginsListByInterface(PumpInterface.class);
|
||||
break;
|
||||
}
|
||||
|
@ -390,23 +375,23 @@ public class ConfigBuilderFragment extends Fragment {
|
|||
if (p.getName().equals(changedPlugin.getName())) {
|
||||
// this is new selected
|
||||
} else {
|
||||
p.setFragmentEnabled(type, false);
|
||||
p.setPluginEnabled(type, false);
|
||||
p.setFragmentVisible(type, false);
|
||||
}
|
||||
}
|
||||
} else { // enable first plugin in list
|
||||
if (type == PluginBase.PUMP)
|
||||
MainApp.getSpecificPlugin(VirtualPumpPlugin.class).setFragmentEnabled(type, true);
|
||||
else if (type == PluginBase.INSULIN)
|
||||
MainApp.getSpecificPlugin(InsulinFastactingPlugin.class).setFragmentEnabled(type, true);
|
||||
else if (type == PluginBase.SENSITIVITY)
|
||||
MainApp.getSpecificPlugin(SensitivityOref0Plugin.class).setFragmentEnabled(type, true);
|
||||
else if (type == PluginBase.PROFILE)
|
||||
MainApp.getSpecificPlugin(NSProfilePlugin.class).setFragmentEnabled(type, true);
|
||||
if (type == PluginType.PUMP)
|
||||
VirtualPumpPlugin.getPlugin().setPluginEnabled(type, true);
|
||||
else if (type == PluginType.INSULIN)
|
||||
InsulinOrefRapidActingPlugin.getPlugin().setPluginEnabled(type, true);
|
||||
else if (type == PluginType.SENSITIVITY)
|
||||
SensitivityOref0Plugin.getPlugin().setPluginEnabled(type, true);
|
||||
else if (type == PluginType.PROFILE)
|
||||
NSProfilePlugin.getPlugin().setPluginEnabled(type, true);
|
||||
else
|
||||
pluginsInCategory.get(0).setFragmentEnabled(type, true);
|
||||
pluginsInCategory.get(0).setPluginEnabled(type, true);
|
||||
}
|
||||
setViews();
|
||||
updateGUI();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -19,13 +19,13 @@ public class DetailedBolusInfoStorage {
|
|||
private static Logger log = LoggerFactory.getLogger(DetailedBolusInfoStorage.class);
|
||||
private static List<DetailedBolusInfo> store = new ArrayList<>();
|
||||
|
||||
public static void add(DetailedBolusInfo detailedBolusInfo) {
|
||||
public static synchronized void add(DetailedBolusInfo detailedBolusInfo) {
|
||||
log.debug("Stored bolus info: " + detailedBolusInfo);
|
||||
store.add(detailedBolusInfo);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static DetailedBolusInfo findDetailedBolusInfo(long bolustime) {
|
||||
public static synchronized DetailedBolusInfo findDetailedBolusInfo(long bolustime) {
|
||||
DetailedBolusInfo found = null;
|
||||
for (int i = 0; i < store.size(); i++) {
|
||||
long infoTime = store.get(i).date;
|
||||
|
@ -38,7 +38,7 @@ public class DetailedBolusInfoStorage {
|
|||
return found;
|
||||
}
|
||||
|
||||
public static void remove(long bolustime) {
|
||||
public static synchronized void remove(long bolustime) {
|
||||
for (int i = 0; i < store.size(); i++) {
|
||||
long infoTime = store.get(i).date;
|
||||
if (bolustime > infoTime - 60 * 1000 && bolustime < infoTime + 60 * 1000) {
|
||||
|
|
|
@ -15,7 +15,6 @@ import android.widget.CheckBox;
|
|||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.crashlytics.android.Crashlytics;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -25,8 +24,11 @@ import java.util.List;
|
|||
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.plugins.Common.SubscriberFragment;
|
||||
import info.nightscout.utils.FabricPrivacy;
|
||||
import info.nightscout.utils.T;
|
||||
|
||||
public class ObjectivesFragment extends Fragment {
|
||||
public class ObjectivesFragment extends SubscriberFragment {
|
||||
private static Logger log = LoggerFactory.getLogger(ObjectivesFragment.class);
|
||||
|
||||
RecyclerView recyclerView;
|
||||
|
@ -57,7 +59,7 @@ public class ObjectivesFragment extends Fragment {
|
|||
holder.position.setText(String.valueOf(position + 1));
|
||||
holder.objective.setText(o.objective);
|
||||
holder.gate.setText(o.gate);
|
||||
holder.duration.setText(context.getString(R.string.objectives_minimalduration) + " " + o.durationInDays + " " + context.getString(R.string.days));
|
||||
holder.duration.setText(MainApp.gs(R.string.objectives_minimalduration) + " " + o.durationInDays + " " + MainApp.gs(R.string.days));
|
||||
holder.progress.setText(requirementsMet.comment);
|
||||
holder.started.setText(o.started.toLocaleString());
|
||||
holder.accomplished.setText(o.accomplished.toLocaleString());
|
||||
|
@ -84,37 +86,52 @@ public class ObjectivesFragment extends Fragment {
|
|||
}
|
||||
});
|
||||
|
||||
Long now = System.currentTimeMillis();
|
||||
if (position > 0 && objectives.get(position - 1).accomplished.getTime() == 0) {
|
||||
// Phase 0: previous not completed
|
||||
holder.startedLayout.setVisibility(View.GONE);
|
||||
holder.durationLayout.setVisibility(View.GONE);
|
||||
holder.progressLayout.setVisibility(View.GONE);
|
||||
holder.verifyLayout.setVisibility(View.GONE);
|
||||
} else if (o.started.getTime() == 0) {
|
||||
// Phase 1: not started
|
||||
holder.durationLayout.setVisibility(View.GONE);
|
||||
holder.progressLayout.setVisibility(View.GONE);
|
||||
holder.verifyLayout.setVisibility(View.GONE);
|
||||
holder.started.setVisibility(View.GONE);
|
||||
} else if (o.started.getTime() > 0 && !enableFake.isChecked() && o.accomplished.getTime() == 0 && !(o.started.getTime() + o.durationInDays * 24 * 60 * 60 * 1000 < now && requirementsMet.done)) {
|
||||
// Phase 2: started, waiting for duration and met requirements
|
||||
holder.startButton.setEnabled(false);
|
||||
holder.verifyLayout.setVisibility(View.GONE);
|
||||
} else if (o.accomplished.getTime() == 0) {
|
||||
// Phase 3: started, after duration, requirements met
|
||||
holder.startButton.setEnabled(false);
|
||||
holder.accomplished.setVisibility(View.INVISIBLE);
|
||||
} else {
|
||||
// Phase 4: verified
|
||||
holder.gateLayout.setVisibility(View.GONE);
|
||||
holder.startedLayout.setVisibility(View.GONE);
|
||||
holder.durationLayout.setVisibility(View.GONE);
|
||||
holder.progressLayout.setVisibility(View.GONE);
|
||||
holder.verifyButton.setVisibility(View.INVISIBLE);
|
||||
long prevObjectiveAccomplishedTime = position > 0 ?
|
||||
objectives.get(position - 1).accomplished.getTime() : -1;
|
||||
|
||||
int phase = modifyVisibility(position, prevObjectiveAccomplishedTime,
|
||||
o.started.getTime(), o.durationInDays,
|
||||
o.accomplished.getTime(), requirementsMet.done, enableFake.isChecked());
|
||||
|
||||
switch (phase) {
|
||||
case 0:
|
||||
// Phase 0: previous not completed
|
||||
holder.startedLayout.setVisibility(View.GONE);
|
||||
holder.durationLayout.setVisibility(View.GONE);
|
||||
holder.progressLayout.setVisibility(View.GONE);
|
||||
holder.verifyLayout.setVisibility(View.GONE);
|
||||
break;
|
||||
case 1:
|
||||
// Phase 1: not started
|
||||
holder.durationLayout.setVisibility(View.GONE);
|
||||
holder.progressLayout.setVisibility(View.GONE);
|
||||
holder.verifyLayout.setVisibility(View.GONE);
|
||||
holder.started.setVisibility(View.GONE);
|
||||
break;
|
||||
case 2:
|
||||
// Phase 2: started, waiting for duration and met requirements
|
||||
holder.startButton.setEnabled(false);
|
||||
holder.verifyLayout.setVisibility(View.GONE);
|
||||
break;
|
||||
case 3:
|
||||
// Phase 3: started, after duration, requirements met
|
||||
holder.startButton.setEnabled(false);
|
||||
holder.accomplished.setVisibility(View.INVISIBLE);
|
||||
break;
|
||||
case 4:
|
||||
// Phase 4: verified
|
||||
holder.gateLayout.setVisibility(View.GONE);
|
||||
holder.startedLayout.setVisibility(View.GONE);
|
||||
holder.durationLayout.setVisibility(View.GONE);
|
||||
holder.progressLayout.setVisibility(View.GONE);
|
||||
holder.verifyButton.setVisibility(View.INVISIBLE);
|
||||
break;
|
||||
default:
|
||||
// should not happen
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return objectives.size();
|
||||
|
@ -163,6 +180,40 @@ public class ObjectivesFragment extends Fragment {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* returns an int, which represents the phase the current objective is at.
|
||||
*
|
||||
* this is mainly used for unit-testing the conditions
|
||||
*
|
||||
* @param currentPosition
|
||||
* @param prevObjectiveAccomplishedTime
|
||||
* @param objectiveStartedTime
|
||||
* @param durationInDays
|
||||
* @param objectiveAccomplishedTime
|
||||
* @param requirementsMet
|
||||
* @return
|
||||
*/
|
||||
public int modifyVisibility(int currentPosition,
|
||||
long prevObjectiveAccomplishedTime,
|
||||
long objectiveStartedTime, int durationInDays,
|
||||
long objectiveAccomplishedTime, boolean requirementsMet,
|
||||
boolean enableFakeValue) {
|
||||
Long now = System.currentTimeMillis();
|
||||
if (currentPosition > 0 && prevObjectiveAccomplishedTime == 0) {
|
||||
return 0;
|
||||
} else if (objectiveStartedTime == 0) {
|
||||
return 1;
|
||||
} else if (objectiveStartedTime > 0 && !enableFakeValue
|
||||
&& objectiveAccomplishedTime == 0
|
||||
&& !(objectiveStartedTime + T.days(durationInDays).msecs() < now && requirementsMet)) {
|
||||
return 2;
|
||||
} else if (objectiveAccomplishedTime == 0) {
|
||||
return 3;
|
||||
} else {
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
|
@ -190,40 +241,39 @@ public class ObjectivesFragment extends Fragment {
|
|||
});
|
||||
|
||||
// Add correct translations to array after app is initialized
|
||||
ObjectivesPlugin.objectives.get(0).objective = MainApp.sResources.getString(R.string.objectives_0_objective);
|
||||
ObjectivesPlugin.objectives.get(1).objective = MainApp.sResources.getString(R.string.objectives_1_objective);
|
||||
ObjectivesPlugin.objectives.get(2).objective = MainApp.sResources.getString(R.string.objectives_2_objective);
|
||||
ObjectivesPlugin.objectives.get(3).objective = MainApp.sResources.getString(R.string.objectives_3_objective);
|
||||
ObjectivesPlugin.objectives.get(4).objective = MainApp.sResources.getString(R.string.objectives_4_objective);
|
||||
ObjectivesPlugin.objectives.get(5).objective = MainApp.sResources.getString(R.string.objectives_5_objective);
|
||||
ObjectivesPlugin.objectives.get(6).objective = MainApp.sResources.getString(R.string.objectives_6_objective);
|
||||
ObjectivesPlugin.objectives.get(7).objective = MainApp.sResources.getString(R.string.objectives_7_objective);
|
||||
ObjectivesPlugin.objectives.get(0).gate = MainApp.sResources.getString(R.string.objectives_0_gate);
|
||||
ObjectivesPlugin.objectives.get(1).gate = MainApp.sResources.getString(R.string.objectives_1_gate);
|
||||
ObjectivesPlugin.objectives.get(2).gate = MainApp.sResources.getString(R.string.objectives_2_gate);
|
||||
ObjectivesPlugin.objectives.get(3).gate = MainApp.sResources.getString(R.string.objectives_3_gate);
|
||||
ObjectivesPlugin.objectives.get(4).gate = MainApp.sResources.getString(R.string.objectives_4_gate);
|
||||
ObjectivesPlugin.objectives.get(5).gate = MainApp.sResources.getString(R.string.objectives_5_gate);
|
||||
ObjectivesPlugin.objectives.get(0).objective = MainApp.gs(R.string.objectives_0_objective);
|
||||
ObjectivesPlugin.objectives.get(1).objective = MainApp.gs(R.string.objectives_1_objective);
|
||||
ObjectivesPlugin.objectives.get(2).objective = MainApp.gs(R.string.objectives_2_objective);
|
||||
ObjectivesPlugin.objectives.get(3).objective = MainApp.gs(R.string.objectives_3_objective);
|
||||
ObjectivesPlugin.objectives.get(4).objective = MainApp.gs(R.string.objectives_4_objective);
|
||||
ObjectivesPlugin.objectives.get(5).objective = MainApp.gs(R.string.objectives_5_objective);
|
||||
ObjectivesPlugin.objectives.get(6).objective = MainApp.gs(R.string.objectives_6_objective);
|
||||
ObjectivesPlugin.objectives.get(7).objective = MainApp.gs(R.string.objectives_7_objective);
|
||||
ObjectivesPlugin.objectives.get(0).gate = MainApp.gs(R.string.objectives_0_gate);
|
||||
ObjectivesPlugin.objectives.get(1).gate = MainApp.gs(R.string.objectives_1_gate);
|
||||
ObjectivesPlugin.objectives.get(2).gate = MainApp.gs(R.string.objectives_2_gate);
|
||||
ObjectivesPlugin.objectives.get(3).gate = MainApp.gs(R.string.objectives_3_gate);
|
||||
ObjectivesPlugin.objectives.get(4).gate = MainApp.gs(R.string.objectives_4_gate);
|
||||
ObjectivesPlugin.objectives.get(5).gate = MainApp.gs(R.string.objectives_5_gate);
|
||||
|
||||
updateGUI();
|
||||
|
||||
return view;
|
||||
} catch (Exception e) {
|
||||
Crashlytics.logException(e);
|
||||
FabricPrivacy.logException(e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
void updateGUI() {
|
||||
@Override
|
||||
public void updateGUI() {
|
||||
Activity activity = getActivity();
|
||||
if (activity != null)
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
RecyclerViewAdapter adapter = new RecyclerViewAdapter(ObjectivesPlugin.objectives);
|
||||
recyclerView.setAdapter(adapter);
|
||||
}
|
||||
activity.runOnUiThread(() -> {
|
||||
RecyclerViewAdapter adapter = new RecyclerViewAdapter(ObjectivesPlugin.objectives);
|
||||
recyclerView.setAdapter(adapter);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -10,25 +10,30 @@ import java.util.ArrayList;
|
|||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import info.nightscout.androidaps.BuildConfig;
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.db.DatabaseHelper;
|
||||
import info.nightscout.androidaps.interfaces.APSInterface;
|
||||
import info.nightscout.androidaps.interfaces.Constraint;
|
||||
import info.nightscout.androidaps.interfaces.ConstraintsInterface;
|
||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||
import info.nightscout.androidaps.interfaces.PluginDescription;
|
||||
import info.nightscout.androidaps.interfaces.PluginType;
|
||||
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.ConstraintsSafety.SafetyPlugin;
|
||||
import info.nightscout.androidaps.plugins.Loop.LoopPlugin;
|
||||
import info.nightscout.androidaps.plugins.NSClientInternal.NSClientInternalPlugin;
|
||||
import info.nightscout.androidaps.plugins.NSClientInternal.NSClientPlugin;
|
||||
import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin;
|
||||
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
|
||||
import info.nightscout.utils.DateUtil;
|
||||
import info.nightscout.utils.SP;
|
||||
|
||||
/**
|
||||
* Created by mike on 05.08.2016.
|
||||
*/
|
||||
public class ObjectivesPlugin implements PluginBase, ConstraintsInterface {
|
||||
public class ObjectivesPlugin extends PluginBase implements ConstraintsInterface {
|
||||
private static Logger log = LoggerFactory.getLogger(ObjectivesPlugin.class);
|
||||
|
||||
private static ObjectivesPlugin objectivesPlugin;
|
||||
|
@ -42,80 +47,26 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface {
|
|||
|
||||
public static List<Objective> objectives;
|
||||
|
||||
private boolean fragmentVisible = true;
|
||||
|
||||
private ObjectivesPlugin() {
|
||||
super(new PluginDescription()
|
||||
.mainType(PluginType.CONSTRAINTS)
|
||||
.fragmentClass(ObjectivesFragment.class.getName())
|
||||
.alwaysEnabled(!Config.NSCLIENT && !Config.G5UPLOADER)
|
||||
.showInList(!Config.NSCLIENT && !Config.G5UPLOADER)
|
||||
.pluginName(R.string.objectives)
|
||||
.shortName(R.string.objectives_shortname)
|
||||
);
|
||||
initializeData();
|
||||
loadProgress();
|
||||
MainApp.bus().register(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFragmentClass() {
|
||||
return ObjectivesFragment.class.getName();
|
||||
public boolean specialEnableCondition() {
|
||||
PumpInterface pump = ConfigBuilderPlugin.getActivePump();
|
||||
return pump == null || pump.getPumpDescription().isTempBasalCapable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getType() {
|
||||
return PluginBase.CONSTRAINTS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return MainApp.instance().getString(R.string.objectives);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNameShort() {
|
||||
String name = MainApp.sResources.getString(R.string.objectives_shortname);
|
||||
if (!name.trim().isEmpty()) {
|
||||
//only if translation exists
|
||||
return name;
|
||||
}
|
||||
// use long name as fallback
|
||||
return getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(int type) {
|
||||
return type == CONSTRAINTS && ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVisibleInTabs(int type) {
|
||||
return type == CONSTRAINTS && fragmentVisible && !Config.NSCLIENT && !Config.G5UPLOADER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeHidden(int type) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasFragment() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean showInList(int type) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFragmentVisible(int type, boolean fragmentVisible) {
|
||||
if (type == CONSTRAINTS) this.fragmentVisible = fragmentVisible;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPreferencesId() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
class Objective {
|
||||
public class Objective {
|
||||
Integer num;
|
||||
String objective;
|
||||
String gate;
|
||||
|
@ -131,6 +82,18 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface {
|
|||
this.durationInDays = durationInDays;
|
||||
this.accomplished = accomplished;
|
||||
}
|
||||
|
||||
public void setStarted(Date started) {
|
||||
this.started = started;
|
||||
}
|
||||
|
||||
boolean isStarted() {
|
||||
return started.getTime() > 0;
|
||||
}
|
||||
|
||||
boolean isFinished() {
|
||||
return accomplished.getTime() != 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Objective 0
|
||||
|
@ -158,37 +121,41 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface {
|
|||
RequirementResult requirementsMet(Integer objNum) {
|
||||
switch (objNum) {
|
||||
case 0:
|
||||
boolean isVirtualPump = VirtualPumpPlugin.getPlugin().isEnabled(PluginBase.PUMP);
|
||||
boolean isVirtualPump = VirtualPumpPlugin.getPlugin().isEnabled(PluginType.PUMP);
|
||||
boolean vpUploadEnabled = SP.getBoolean("virtualpump_uploadstatus", false);
|
||||
boolean vpUploadNeeded = !isVirtualPump || vpUploadEnabled;
|
||||
boolean hasBGData = DatabaseHelper.lastBg() != null;
|
||||
|
||||
boolean apsEnabled = false;
|
||||
APSInterface usedAPS = ConfigBuilderPlugin.getActiveAPS();
|
||||
if (usedAPS != null && ((PluginBase) usedAPS).isEnabled(PluginBase.APS))
|
||||
if (usedAPS != null && ((PluginBase) usedAPS).isEnabled(PluginType.APS))
|
||||
apsEnabled = true;
|
||||
|
||||
return new RequirementResult(hasBGData && bgIsAvailableInNS && pumpStatusIsAvailableInNS && NSClientInternalPlugin.getPlugin().hasWritePermission() && LoopPlugin.getPlugin().isEnabled(PluginBase.LOOP) && apsEnabled && vpUploadNeeded,
|
||||
MainApp.sResources.getString(R.string.objectives_bgavailableinns) + ": " + yesOrNo(bgIsAvailableInNS)
|
||||
+ "\n" + MainApp.sResources.getString(R.string.nsclienthaswritepermission) + ": " + yesOrNo(NSClientInternalPlugin.getPlugin().hasWritePermission())
|
||||
+ (isVirtualPump ? "\n" + MainApp.sResources.getString(R.string.virtualpump_uploadstatus_title) + ": " + yesOrNo(vpUploadEnabled) : "")
|
||||
+ "\n" + MainApp.sResources.getString(R.string.objectives_pumpstatusavailableinns) + ": " + yesOrNo(pumpStatusIsAvailableInNS)
|
||||
+ "\n" + MainApp.sResources.getString(R.string.hasbgdata) + ": " + yesOrNo(hasBGData)
|
||||
+ "\n" + MainApp.sResources.getString(R.string.loopenabled) + ": " + yesOrNo(LoopPlugin.getPlugin().isEnabled(PluginBase.LOOP))
|
||||
+ "\n" + MainApp.sResources.getString(R.string.apsselected) + ": " + yesOrNo(apsEnabled)
|
||||
boolean profileSwitchExists = TreatmentsPlugin.getPlugin().getProfileSwitchFromHistory(DateUtil.now()) != null;
|
||||
|
||||
return new RequirementResult(hasBGData && bgIsAvailableInNS && pumpStatusIsAvailableInNS && NSClientPlugin.getPlugin().hasWritePermission() && LoopPlugin.getPlugin().isEnabled(PluginType.LOOP) && apsEnabled && vpUploadNeeded && profileSwitchExists,
|
||||
MainApp.gs(R.string.objectives_bgavailableinns) + ": " + yesOrNo(bgIsAvailableInNS)
|
||||
+ "\n" + MainApp.gs(R.string.nsclienthaswritepermission) + ": " + yesOrNo(NSClientPlugin.getPlugin().hasWritePermission())
|
||||
+ (isVirtualPump ? "\n" + MainApp.gs(R.string.virtualpump_uploadstatus_title) + ": " + yesOrNo(vpUploadEnabled) : "")
|
||||
+ "\n" + MainApp.gs(R.string.objectives_pumpstatusavailableinns) + ": " + yesOrNo(pumpStatusIsAvailableInNS)
|
||||
+ "\n" + MainApp.gs(R.string.hasbgdata) + ": " + yesOrNo(hasBGData)
|
||||
+ "\n" + MainApp.gs(R.string.loopenabled) + ": " + yesOrNo(LoopPlugin.getPlugin().isEnabled(PluginType.LOOP))
|
||||
+ "\n" + MainApp.gs(R.string.apsselected) + ": " + yesOrNo(apsEnabled)
|
||||
+ "\n" + MainApp.gs(R.string.activate_profile) + ": " + yesOrNo(profileSwitchExists)
|
||||
);
|
||||
case 1:
|
||||
return new RequirementResult(manualEnacts >= manualEnactsNeeded,
|
||||
MainApp.sResources.getString(R.string.objectives_manualenacts) + ": " + manualEnacts + "/" + manualEnactsNeeded);
|
||||
MainApp.gs(R.string.objectives_manualenacts) + ": " + manualEnacts + "/" + manualEnactsNeeded);
|
||||
case 2:
|
||||
return new RequirementResult(true, "");
|
||||
case 3:
|
||||
boolean closedModeEnabled = SafetyPlugin.getPlugin().isClosedModeEnabled();
|
||||
return new RequirementResult(closedModeEnabled, MainApp.sResources.getString(R.string.closedmodeenabled) + ": " + yesOrNo(closedModeEnabled));
|
||||
Constraint<Boolean> closedLoopEnabled = new Constraint<>(true);
|
||||
SafetyPlugin.getPlugin().isClosedLoopAllowed(closedLoopEnabled);
|
||||
return new RequirementResult(closedLoopEnabled.value(), MainApp.gs(R.string.closedmodeenabled) + ": " + yesOrNo(closedLoopEnabled.value()));
|
||||
case 4:
|
||||
double maxIOB = MainApp.getConfigBuilder().applyMaxIOBConstraints(1000d);
|
||||
double maxIOB = MainApp.getConstraintChecker().getMaxIOBAllowed().value();
|
||||
boolean maxIobSet = maxIOB > 0;
|
||||
return new RequirementResult(maxIobSet, MainApp.sResources.getString(R.string.maxiobset) + ": " + yesOrNo(maxIobSet));
|
||||
return new RequirementResult(maxIobSet, MainApp.gs(R.string.maxiobset) + ": " + yesOrNo(maxIobSet));
|
||||
default:
|
||||
return new RequirementResult(true, "");
|
||||
}
|
||||
|
@ -202,49 +169,49 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface {
|
|||
|
||||
objectives = new ArrayList<>();
|
||||
objectives.add(new Objective(0,
|
||||
MainApp.sResources.getString(R.string.objectives_0_objective),
|
||||
MainApp.sResources.getString(R.string.objectives_0_gate),
|
||||
MainApp.gs(R.string.objectives_0_objective),
|
||||
MainApp.gs(R.string.objectives_0_gate),
|
||||
new Date(0),
|
||||
0, // 0 day
|
||||
new Date(0)));
|
||||
objectives.add(new Objective(1,
|
||||
MainApp.sResources.getString(R.string.objectives_1_objective),
|
||||
MainApp.sResources.getString(R.string.objectives_1_gate),
|
||||
MainApp.gs(R.string.objectives_1_objective),
|
||||
MainApp.gs(R.string.objectives_1_gate),
|
||||
new Date(0),
|
||||
7, // 7 days
|
||||
new Date(0)));
|
||||
objectives.add(new Objective(2,
|
||||
MainApp.sResources.getString(R.string.objectives_2_objective),
|
||||
MainApp.sResources.getString(R.string.objectives_2_gate),
|
||||
MainApp.gs(R.string.objectives_2_objective),
|
||||
MainApp.gs(R.string.objectives_2_gate),
|
||||
new Date(0),
|
||||
0, // 0 days
|
||||
new Date(0)));
|
||||
objectives.add(new Objective(3,
|
||||
MainApp.sResources.getString(R.string.objectives_3_objective),
|
||||
MainApp.sResources.getString(R.string.objectives_3_gate),
|
||||
MainApp.gs(R.string.objectives_3_objective),
|
||||
MainApp.gs(R.string.objectives_3_gate),
|
||||
new Date(0),
|
||||
5, // 5 days
|
||||
new Date(0)));
|
||||
objectives.add(new Objective(4,
|
||||
MainApp.sResources.getString(R.string.objectives_4_objective),
|
||||
MainApp.sResources.getString(R.string.objectives_4_gate),
|
||||
MainApp.gs(R.string.objectives_4_objective),
|
||||
MainApp.gs(R.string.objectives_4_gate),
|
||||
new Date(0),
|
||||
1,
|
||||
new Date(0)));
|
||||
objectives.add(new Objective(5,
|
||||
MainApp.sResources.getString(R.string.objectives_5_objective),
|
||||
MainApp.sResources.getString(R.string.objectives_5_gate),
|
||||
MainApp.gs(R.string.objectives_5_objective),
|
||||
MainApp.gs(R.string.objectives_5_gate),
|
||||
new Date(0),
|
||||
7,
|
||||
new Date(0)));
|
||||
objectives.add(new Objective(6,
|
||||
MainApp.sResources.getString(R.string.objectives_6_objective),
|
||||
MainApp.gs(R.string.objectives_6_objective),
|
||||
"",
|
||||
new Date(0),
|
||||
28,
|
||||
new Date(0)));
|
||||
objectives.add(new Objective(7,
|
||||
MainApp.sResources.getString(R.string.objectives_7_objective),
|
||||
MainApp.gs(R.string.objectives_7_objective),
|
||||
"",
|
||||
new Date(0),
|
||||
28,
|
||||
|
@ -294,60 +261,45 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface {
|
|||
* Constraints interface
|
||||
**/
|
||||
@Override
|
||||
public boolean isLoopEnabled() {
|
||||
return objectives.get(0).started.getTime() > 0;
|
||||
public Constraint<Boolean> isLoopInvokationAllowed(Constraint<Boolean> value) {
|
||||
if (!objectives.get(0).isStarted())
|
||||
value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), 1), this);
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isClosedModeEnabled() {
|
||||
return objectives.get(3).started.getTime() > 0;
|
||||
public Constraint<Boolean> isClosedLoopAllowed(Constraint<Boolean> value) {
|
||||
if (!objectives.get(3).isStarted())
|
||||
value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), 4), this);
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAutosensModeEnabled() {
|
||||
return objectives.get(5).started.getTime() > 0;
|
||||
public Constraint<Boolean> isAutosensModeEnabled(Constraint<Boolean> value) {
|
||||
if (!objectives.get(5).isStarted())
|
||||
value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), 6), this);
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAMAModeEnabled() {
|
||||
return objectives.get(6).started.getTime() > 0;
|
||||
public Constraint<Boolean> isAMAModeEnabled(Constraint<Boolean> value) {
|
||||
if (!objectives.get(6).isStarted())
|
||||
value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), 7), this);
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSMBModeEnabled() {
|
||||
return objectives.get(7).started.getTime() > 0;
|
||||
public Constraint<Boolean> isSMBModeEnabled(Constraint<Boolean> value) {
|
||||
if (!objectives.get(7).isStarted())
|
||||
value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), 8), this);
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double applyMaxIOBConstraints(Double maxIob) {
|
||||
if (objectives.get(3).started.getTime() > 0 && objectives.get(3).accomplished.getTime() == 0) {
|
||||
if (Config.logConstraintsChanges)
|
||||
log.debug("Limiting maxIOB " + maxIob + " to " + 0 + "U");
|
||||
return 0d;
|
||||
} else {
|
||||
return maxIob;
|
||||
}
|
||||
public Constraint<Double> applyMaxIOBConstraints(Constraint<Double> maxIob) {
|
||||
if (objectives.get(3).isStarted() && !objectives.get(3).isFinished())
|
||||
maxIob.set(0d, String.format(MainApp.gs(R.string.objectivenotfinished), 4), this);
|
||||
return maxIob;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double applyBasalConstraints(Double absoluteRate) {
|
||||
return absoluteRate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer applyBasalConstraints(Integer percentRate) {
|
||||
return percentRate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double applyBolusConstraints(Double insulin) {
|
||||
return insulin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer applyCarbsConstraints(Integer carbs) {
|
||||
return carbs;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,19 +1,22 @@
|
|||
package info.nightscout.androidaps.plugins.ConstraintsSafety;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import info.nightscout.androidaps.BuildConfig;
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.Constants;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.data.ConstraintChecker;
|
||||
import info.nightscout.androidaps.data.Profile;
|
||||
import info.nightscout.androidaps.interfaces.BgSourceInterface;
|
||||
import info.nightscout.androidaps.interfaces.Constraint;
|
||||
import info.nightscout.androidaps.interfaces.ConstraintsInterface;
|
||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||
import info.nightscout.androidaps.interfaces.PluginDescription;
|
||||
import info.nightscout.androidaps.interfaces.PluginType;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin;
|
||||
import info.nightscout.androidaps.plugins.OpenAPSMA.OpenAPSMAPlugin;
|
||||
import info.nightscout.androidaps.plugins.OpenAPSSMB.OpenAPSSMBPlugin;
|
||||
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
|
||||
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
|
||||
import info.nightscout.utils.DecimalFormatter;
|
||||
import info.nightscout.utils.HardLimits;
|
||||
import info.nightscout.utils.Round;
|
||||
import info.nightscout.utils.SP;
|
||||
|
@ -21,8 +24,7 @@ import info.nightscout.utils.SP;
|
|||
/**
|
||||
* Created by mike on 05.08.2016.
|
||||
*/
|
||||
public class SafetyPlugin implements PluginBase, ConstraintsInterface {
|
||||
private static Logger log = LoggerFactory.getLogger(SafetyPlugin.class);
|
||||
public class SafetyPlugin extends PluginBase implements ConstraintsInterface {
|
||||
|
||||
static SafetyPlugin plugin = null;
|
||||
|
||||
|
@ -32,201 +34,154 @@ public class SafetyPlugin implements PluginBase, ConstraintsInterface {
|
|||
return plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFragmentClass() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getType() {
|
||||
return PluginBase.CONSTRAINTS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return MainApp.instance().getString(R.string.safety);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNameShort() {
|
||||
// use long name as fallback (no tabs)
|
||||
return getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(int type) {
|
||||
return type == CONSTRAINTS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVisibleInTabs(int type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeHidden(int type) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasFragment() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean showInList(int type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFragmentVisible(int type, boolean fragmentVisible) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPreferencesId() {
|
||||
return R.xml.pref_safety;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLoopEnabled() {
|
||||
return ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable;
|
||||
public SafetyPlugin() {
|
||||
super(new PluginDescription()
|
||||
.mainType(PluginType.CONSTRAINTS)
|
||||
.neverVisible(true)
|
||||
.alwaysEnabled(true)
|
||||
.showInList(false)
|
||||
.pluginName(R.string.safety)
|
||||
.preferencesId(R.xml.pref_safety)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constraints interface
|
||||
**/
|
||||
@Override
|
||||
public boolean isClosedModeEnabled() {
|
||||
public Constraint<Boolean> isLoopInvokationAllowed(Constraint<Boolean> value) {
|
||||
if (!ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable)
|
||||
value.set(false, MainApp.gs(R.string.pumpisnottempbasalcapable), this);
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Constraint<Boolean> isClosedLoopAllowed(Constraint<Boolean> value) {
|
||||
String mode = SP.getString("aps_mode", "open");
|
||||
return mode.equals("closed") && BuildConfig.CLOSEDLOOP;
|
||||
if (!mode.equals("closed"))
|
||||
value.set(false, MainApp.gs(R.string.closedmodedisabledinpreferences), this);
|
||||
|
||||
if (!MainApp.isEngineeringModeOrRelease()) {
|
||||
if (value.value()) {
|
||||
Notification n = new Notification(Notification.TOAST_ALARM, MainApp.gs(R.string.closed_loop_disabled_on_dev_branch), Notification.NORMAL);
|
||||
MainApp.bus().post(new EventNewNotification(n));
|
||||
}
|
||||
value.set(false, MainApp.gs(R.string.closed_loop_disabled_on_dev_branch), this);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAutosensModeEnabled() {
|
||||
return true;
|
||||
public Constraint<Boolean> isAutosensModeEnabled(Constraint<Boolean> value) {
|
||||
boolean enabled = SP.getBoolean(R.string.key_openapsama_useautosens, false);
|
||||
if (!enabled)
|
||||
value.set(false, MainApp.gs(R.string.autosensdisabledinpreferences), this);
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAMAModeEnabled() {
|
||||
return true;
|
||||
public Constraint<Boolean> isSMBModeEnabled(Constraint<Boolean> value) {
|
||||
boolean enabled = SP.getBoolean(R.string.key_use_smb, false);
|
||||
if (!enabled)
|
||||
value.set(false, MainApp.gs(R.string.smbdisabledinpreferences), this);
|
||||
ConstraintChecker constraintChecker = MainApp.getConstraintChecker();
|
||||
Constraint<Boolean> closedLoop = constraintChecker.isClosedLoopAllowed();
|
||||
if (!closedLoop.value())
|
||||
value.set(false, MainApp.gs(R.string.smbnotallowedinopenloopmode), this);
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSMBModeEnabled() {
|
||||
return true;
|
||||
public Constraint<Boolean> isAdvancedFilteringEnabled(Constraint<Boolean> value) {
|
||||
BgSourceInterface bgSource = MainApp.getConfigBuilder().getActiveBgSource();
|
||||
|
||||
if (bgSource != null) {
|
||||
if (!bgSource.advancedFilteringSupported())
|
||||
value.set(false, MainApp.gs(R.string.smbalwaysdisabled), this);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double applyBasalConstraints(Double absoluteRate) {
|
||||
Double origAbsoluteRate = absoluteRate;
|
||||
Double maxBasal = SP.getDouble("openapsma_max_basal", 1d);
|
||||
public Constraint<Double> applyBasalConstraints(Constraint<Double> absoluteRate, Profile profile) {
|
||||
|
||||
Profile profile = MainApp.getConfigBuilder().getProfile();
|
||||
if (profile == null) return absoluteRate;
|
||||
if (absoluteRate < 0) absoluteRate = 0d;
|
||||
absoluteRate.setIfGreater(0d, String.format(MainApp.gs(R.string.limitingbasalratio), 0d, MainApp.gs(R.string.itmustbepositivevalue)), this);
|
||||
|
||||
double maxBasal = SP.getDouble(R.string.key_openapsma_max_basal, 1d);
|
||||
absoluteRate.setIfSmaller(maxBasal, String.format(MainApp.gs(R.string.limitingbasalratio), maxBasal, MainApp.gs(R.string.maxvalueinpreferences)), this);
|
||||
|
||||
Integer maxBasalMult = SP.getInt("openapsama_current_basal_safety_multiplier", 4);
|
||||
Integer maxBasalFromDaily = SP.getInt("openapsama_max_daily_safety_multiplier", 3);
|
||||
// Check percentRate but absolute rate too, because we know real current basal in pump
|
||||
Double origRate = absoluteRate;
|
||||
if (absoluteRate > maxBasal) {
|
||||
absoluteRate = maxBasal;
|
||||
if (Config.logConstraintsChanges && origAbsoluteRate != Constants.basalAbsoluteOnlyForCheckLimit)
|
||||
log.debug("Limiting rate " + origRate + " by maxBasal preference to " + absoluteRate + "U/h");
|
||||
}
|
||||
if (absoluteRate > maxBasalMult * profile.getBasal()) {
|
||||
absoluteRate = Math.floor(maxBasalMult * profile.getBasal() * 100) / 100;
|
||||
if (Config.logConstraintsChanges && origAbsoluteRate != Constants.basalAbsoluteOnlyForCheckLimit)
|
||||
log.debug("Limiting rate " + origRate + " by maxBasalMult to " + absoluteRate + "U/h");
|
||||
}
|
||||
if (absoluteRate > profile.getMaxDailyBasal() * maxBasalFromDaily) {
|
||||
absoluteRate = profile.getMaxDailyBasal() * maxBasalFromDaily;
|
||||
if (Config.logConstraintsChanges && origAbsoluteRate != Constants.basalAbsoluteOnlyForCheckLimit)
|
||||
log.debug("Limiting rate " + origRate + " by 3 * maxDailyBasal to " + absoluteRate + "U/h");
|
||||
}
|
||||
Double maxBasalMult = SP.getDouble(R.string.key_openapsama_current_basal_safety_multiplier, 4d);
|
||||
double maxFromBasalMult = Math.floor(maxBasalMult * profile.getBasal() * 100) / 100;
|
||||
absoluteRate.setIfSmaller(maxFromBasalMult, String.format(MainApp.gs(R.string.limitingbasalratio), maxFromBasalMult, MainApp.gs(R.string.maxbasalmultiplier)), this);
|
||||
|
||||
Double maxBasalFromDaily = SP.getDouble(R.string.key_openapsama_max_daily_safety_multiplier, 3d);
|
||||
double maxFromDaily = Math.floor(profile.getMaxDailyBasal() * maxBasalFromDaily * 100) / 100;
|
||||
absoluteRate.setIfSmaller(maxFromDaily, String.format(MainApp.gs(R.string.limitingbasalratio), maxFromDaily, MainApp.gs(R.string.maxdailybasalmultiplier)), this);
|
||||
|
||||
absoluteRate.setIfSmaller(HardLimits.maxBasal(), String.format(MainApp.gs(R.string.limitingbasalratio), HardLimits.maxBasal(), MainApp.gs(R.string.hardlimit)), this);
|
||||
return absoluteRate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer applyBasalConstraints(Integer percentRate) {
|
||||
Integer origPercentRate = percentRate;
|
||||
Double maxBasal = SP.getDouble("openapsma_max_basal", 1d);
|
||||
public Constraint<Integer> applyBasalPercentConstraints(Constraint<Integer> percentRate, Profile profile) {
|
||||
|
||||
Profile profile = MainApp.getConfigBuilder().getProfile();
|
||||
if (profile == null) return percentRate;
|
||||
Double currentBasal = profile.getBasal();
|
||||
Double absoluteRate = currentBasal * ((double) percentRate.originalValue() / 100);
|
||||
|
||||
Double absoluteRate = currentBasal * ((double) percentRate / 100);
|
||||
percentRate.addReason("Percent rate " + percentRate.originalValue() + "% recalculated to " + DecimalFormatter.to2Decimal(absoluteRate) + " U/h with current basal " + DecimalFormatter.to2Decimal(currentBasal) + " U/h", this);
|
||||
|
||||
if (Config.logConstraintsChanges)
|
||||
log.debug("Percent rate " + percentRate + "% recalculated to " + absoluteRate + "U/h with current basal " + currentBasal + "U/h");
|
||||
Constraint<Double> absoluteConstraint = new Constraint<>(absoluteRate);
|
||||
applyBasalConstraints(absoluteConstraint, profile);
|
||||
percentRate.copyReasons(absoluteConstraint);
|
||||
|
||||
if (absoluteRate < 0) absoluteRate = 0d;
|
||||
|
||||
Integer maxBasalMult = SP.getInt("openapsama_current_basal_safety_multiplier", 4);
|
||||
Integer maxBasalFromDaily = SP.getInt("openapsama_max_daily_safety_multiplier", 3);
|
||||
// Check percentRate but absolute rate too, because we know real current basal in pump
|
||||
Double origRate = absoluteRate;
|
||||
if (absoluteRate > maxBasal) {
|
||||
absoluteRate = maxBasal;
|
||||
if (Config.logConstraintsChanges && !Objects.equals(origPercentRate, Constants.basalPercentOnlyForCheckLimit))
|
||||
log.debug("Limiting rate " + origRate + " by maxBasal preference to " + absoluteRate + "U/h");
|
||||
}
|
||||
if (absoluteRate > maxBasalMult * profile.getBasal()) {
|
||||
absoluteRate = Math.floor(maxBasalMult * profile.getBasal() * 100) / 100;
|
||||
if (Config.logConstraintsChanges && !Objects.equals(origPercentRate, Constants.basalPercentOnlyForCheckLimit))
|
||||
log.debug("Limiting rate " + origRate + " by maxBasalMult to " + absoluteRate + "U/h");
|
||||
}
|
||||
if (absoluteRate > profile.getMaxDailyBasal() * maxBasalFromDaily) {
|
||||
absoluteRate = profile.getMaxDailyBasal() * maxBasalFromDaily;
|
||||
if (Config.logConstraintsChanges && !Objects.equals(origPercentRate, Constants.basalPercentOnlyForCheckLimit))
|
||||
log.debug("Limiting rate " + origRate + " by 3 * maxDailyBasal to " + absoluteRate + "U/h");
|
||||
}
|
||||
|
||||
Integer percentRateAfterConst = new Double(absoluteRate / currentBasal * 100).intValue();
|
||||
Integer percentRateAfterConst = Double.valueOf(absoluteConstraint.value() / currentBasal * 100).intValue();
|
||||
if (percentRateAfterConst < 100)
|
||||
percentRateAfterConst = Round.ceilTo((double) percentRateAfterConst, 10d).intValue();
|
||||
else percentRateAfterConst = Round.floorTo((double) percentRateAfterConst, 10d).intValue();
|
||||
|
||||
if (Config.logConstraintsChanges && !Objects.equals(origPercentRate, Constants.basalPercentOnlyForCheckLimit))
|
||||
log.debug("Recalculated percent rate " + percentRate + "% to " + percentRateAfterConst + "%");
|
||||
return percentRateAfterConst;
|
||||
percentRate.set(percentRateAfterConst, String.format(MainApp.gs(R.string.limitingpercentrate), percentRateAfterConst, MainApp.gs(R.string.pumplimit)), this);
|
||||
|
||||
return percentRate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double applyBolusConstraints(Double insulin) {
|
||||
try {
|
||||
Double maxBolus = SP.getDouble("treatmentssafety_maxbolus", 3d);
|
||||
public Constraint<Double> applyBolusConstraints(Constraint<Double> insulin) {
|
||||
insulin.setIfGreater(0d, String.format(MainApp.gs(R.string.limitingbolus), 0d, MainApp.gs(R.string.itmustbepositivevalue)), this);
|
||||
|
||||
if (insulin < 0) insulin = 0d;
|
||||
if (insulin > maxBolus) insulin = maxBolus;
|
||||
} catch (Exception e) {
|
||||
insulin = 0d;
|
||||
}
|
||||
if (insulin > HardLimits.maxBolus()) insulin = HardLimits.maxBolus();
|
||||
Double maxBolus = SP.getDouble(R.string.key_treatmentssafety_maxbolus, 3d);
|
||||
insulin.setIfSmaller(maxBolus, String.format(MainApp.gs(R.string.limitingbolus), maxBolus, MainApp.gs(R.string.maxvalueinpreferences)), this);
|
||||
|
||||
insulin.setIfSmaller(HardLimits.maxBolus(), String.format(MainApp.gs(R.string.limitingbolus), HardLimits.maxBolus(), MainApp.gs(R.string.hardlimit)), this);
|
||||
return insulin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer applyCarbsConstraints(Integer carbs) {
|
||||
try {
|
||||
Integer maxCarbs = SP.getInt("treatmentssafety_maxcarbs", 48);
|
||||
public Constraint<Integer> applyCarbsConstraints(Constraint<Integer> carbs) {
|
||||
carbs.setIfGreater(0, String.format(MainApp.gs(R.string.limitingcarbs), 0, MainApp.gs(R.string.itmustbepositivevalue)), this);
|
||||
|
||||
Integer maxCarbs = SP.getInt(R.string.key_treatmentssafety_maxcarbs, 48);
|
||||
carbs.setIfSmaller(maxCarbs, String.format(MainApp.gs(R.string.limitingcarbs), maxCarbs, MainApp.gs(R.string.maxvalueinpreferences)), this);
|
||||
|
||||
if (carbs < 0) carbs = 0;
|
||||
if (carbs > maxCarbs) carbs = maxCarbs;
|
||||
} catch (Exception e) {
|
||||
carbs = 0;
|
||||
}
|
||||
return carbs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double applyMaxIOBConstraints(Double maxIob) {
|
||||
public Constraint<Double> applyMaxIOBConstraints(Constraint<Double> maxIob) {
|
||||
double maxIobPref;
|
||||
if (OpenAPSSMBPlugin.getPlugin().isEnabled(PluginType.APS))
|
||||
maxIobPref = SP.getDouble(R.string.key_openapssmb_max_iob, 3d);
|
||||
else
|
||||
maxIobPref = SP.getDouble(R.string.key_openapsma_max_iob, 1.5d);
|
||||
maxIob.setIfSmaller(maxIobPref, String.format(MainApp.gs(R.string.limitingiob), maxIobPref, MainApp.gs(R.string.maxvalueinpreferences)), this);
|
||||
|
||||
if (OpenAPSMAPlugin.getPlugin().isEnabled(PluginType.APS))
|
||||
maxIob.setIfSmaller(HardLimits.maxIobAMA(), String.format(MainApp.gs(R.string.limitingiob), HardLimits.maxIobAMA(), MainApp.gs(R.string.hardlimit)), this);
|
||||
if (OpenAPSAMAPlugin.getPlugin().isEnabled(PluginType.APS))
|
||||
maxIob.setIfSmaller(HardLimits.maxIobAMA(), String.format(MainApp.gs(R.string.limitingiob), HardLimits.maxIobAMA(), MainApp.gs(R.string.hardlimit)), this);
|
||||
if (OpenAPSSMBPlugin.getPlugin().isEnabled(PluginType.APS))
|
||||
maxIob.setIfSmaller(HardLimits.maxIobSMB(), String.format(MainApp.gs(R.string.limitingiob), HardLimits.maxIobSMB(), MainApp.gs(R.string.hardlimit)), this);
|
||||
return maxIob;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,21 +1,22 @@
|
|||
package info.nightscout.androidaps.db;
|
||||
package info.nightscout.androidaps.plugins.Food;
|
||||
|
||||
import com.j256.ormlite.field.DatabaseField;
|
||||
import com.j256.ormlite.table.DatabaseTable;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import info.nightscout.utils.JsonHelper;
|
||||
|
||||
/**
|
||||
* Created by mike on 20.09.2017.
|
||||
*/
|
||||
|
||||
|
||||
@DatabaseTable(tableName = DatabaseHelper.DATABASE_FOODS)
|
||||
@DatabaseTable(tableName = Food.TABLE_FOODS)
|
||||
public class Food {
|
||||
private static Logger log = LoggerFactory.getLogger(Food.class);
|
||||
static final String TABLE_FOODS = "Foods";
|
||||
|
||||
@DatabaseField(id = true)
|
||||
public long key;
|
||||
|
@ -60,10 +61,29 @@ public class Food {
|
|||
@DatabaseField
|
||||
public int gi; // not used yet
|
||||
|
||||
public Food() {
|
||||
private Food() {
|
||||
key = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public static Food createFromJson(JSONObject json) throws JSONException {
|
||||
Food food = new Food();
|
||||
if ("food".equals(JsonHelper.safeGetString(json, "type"))) {
|
||||
food._id = JsonHelper.safeGetString(json, "_id");
|
||||
food.category = JsonHelper.safeGetString(json, "category");
|
||||
food.subcategory = JsonHelper.safeGetString(json, "subcategory");
|
||||
food.name = JsonHelper.safeGetString(json, "name");
|
||||
food.units = JsonHelper.safeGetString(json, "unit");
|
||||
food.portion = JsonHelper.safeGetDouble(json, "portion");
|
||||
food.carbs = JsonHelper.safeGetInt(json, "carbs");
|
||||
food.gi = JsonHelper.safeGetInt(json, "gi");
|
||||
food.energy = JsonHelper.safeGetInt(json, "energy");
|
||||
food.protein = JsonHelper.safeGetInt(json, "protein");
|
||||
food.fat = JsonHelper.safeGetInt(json, "fat");
|
||||
}
|
||||
|
||||
return food;
|
||||
}
|
||||
|
||||
public boolean isEqual(Food other) {
|
||||
if (portion != other.portion)
|
||||
return false;
|
||||
|
@ -104,4 +124,22 @@ public class Food {
|
|||
units = other.units;
|
||||
gi = other.gi;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("_id=" + _id + ";");
|
||||
sb.append("isValid=" + isValid + ";");
|
||||
sb.append("name=" + name + ";");
|
||||
sb.append("category=" + category + ";");
|
||||
sb.append("subcategory=" + subcategory + ";");
|
||||
sb.append("portion=" + portion + ";");
|
||||
sb.append("carbs=" + carbs + ";");
|
||||
sb.append("protein=" + protein + ";");
|
||||
sb.append("energy=" + energy + ";");
|
||||
sb.append("units=" + units + ";");
|
||||
sb.append("gi=" + gi + ";");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
|
@ -18,7 +18,6 @@ import android.widget.EditText;
|
|||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.crashlytics.android.Crashlytics;
|
||||
import com.squareup.otto.Subscribe;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
|
@ -27,12 +26,13 @@ import org.slf4j.LoggerFactory;
|
|||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.db.Food;
|
||||
import info.nightscout.androidaps.events.EventFoodDatabaseChanged;
|
||||
import info.nightscout.androidaps.plugins.Common.SubscriberFragment;
|
||||
import info.nightscout.utils.FabricPrivacy;
|
||||
import info.nightscout.utils.NSUpload;
|
||||
import info.nightscout.utils.SpinnerHelper;
|
||||
|
||||
|
@ -54,7 +54,7 @@ public class FoodFragment extends SubscriberFragment {
|
|||
ArrayList<CharSequence> categories;
|
||||
ArrayList<CharSequence> subcategories;
|
||||
|
||||
final String EMPTY = MainApp.sResources.getString(R.string.none);
|
||||
final String EMPTY = MainApp.gs(R.string.none);
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
|
@ -121,7 +121,8 @@ public class FoodFragment extends SubscriberFragment {
|
|||
}
|
||||
});
|
||||
|
||||
RecyclerViewAdapter adapter = new RecyclerViewAdapter(MainApp.getDbHelper().foodHelper.getFoodData());
|
||||
RecyclerViewAdapter adapter = new RecyclerViewAdapter(MainApp
|
||||
.getSpecificPlugin(FoodPlugin.class).getService().getFoodData());
|
||||
recyclerView.setAdapter(adapter);
|
||||
|
||||
loadData();
|
||||
|
@ -130,7 +131,7 @@ public class FoodFragment extends SubscriberFragment {
|
|||
filterData();
|
||||
return view;
|
||||
} catch (Exception e) {
|
||||
Crashlytics.logException(e);
|
||||
FabricPrivacy.logException(e);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@ -144,21 +145,20 @@ public class FoodFragment extends SubscriberFragment {
|
|||
}
|
||||
|
||||
void loadData() {
|
||||
unfiltered = MainApp.getDbHelper().foodHelper.getFoodData();
|
||||
unfiltered = MainApp.getSpecificPlugin(FoodPlugin.class).getService().getFoodData();
|
||||
}
|
||||
|
||||
void fillCategories() {
|
||||
categories = new ArrayList<>();
|
||||
Set<CharSequence> catSet = new HashSet<>();
|
||||
|
||||
for (Food f : unfiltered) {
|
||||
if (f.category != null && !f.category.equals(""))
|
||||
categories.add(f.category);
|
||||
catSet.add(f.category);
|
||||
}
|
||||
|
||||
// make it unique
|
||||
categories = new ArrayList<>(new HashSet<>(categories));
|
||||
|
||||
categories.add(0, MainApp.sResources.getString(R.string.none));
|
||||
categories = new ArrayList<>(catSet);
|
||||
categories.add(0, MainApp.gs(R.string.none));
|
||||
|
||||
ArrayAdapter<CharSequence> adapterCategories = new ArrayAdapter<>(getContext(),
|
||||
R.layout.spinner_centered, categories);
|
||||
|
@ -167,20 +167,20 @@ public class FoodFragment extends SubscriberFragment {
|
|||
|
||||
void fillSubcategories() {
|
||||
String categoryFilter = category.getSelectedItem().toString();
|
||||
subcategories = new ArrayList<>();
|
||||
|
||||
Set<CharSequence> subCatSet = new HashSet<>();
|
||||
|
||||
if (!categoryFilter.equals(EMPTY)) {
|
||||
for (Food f : unfiltered) {
|
||||
if (f.category != null && f.category.equals(categoryFilter))
|
||||
if (f.subcategory != null && !f.subcategory.equals(""))
|
||||
subcategories.add(f.subcategory);
|
||||
subCatSet.add(f.subcategory);
|
||||
}
|
||||
}
|
||||
|
||||
// make it unique
|
||||
subcategories = new ArrayList<>(new HashSet<>(subcategories));
|
||||
|
||||
subcategories.add(0, MainApp.sResources.getString(R.string.none));
|
||||
subcategories = new ArrayList<>(subCatSet);
|
||||
subcategories.add(0, MainApp.gs(R.string.none));
|
||||
|
||||
ArrayAdapter<CharSequence> adapterSubcategories = new ArrayAdapter<>(getContext(),
|
||||
R.layout.spinner_centered, subcategories);
|
||||
|
@ -242,14 +242,14 @@ public class FoodFragment extends SubscriberFragment {
|
|||
holder.ns.setVisibility(food._id != null ? View.VISIBLE : View.GONE);
|
||||
holder.name.setText(food.name);
|
||||
holder.portion.setText(food.portion + food.units);
|
||||
holder.carbs.setText(food.carbs + MainApp.sResources.getString(R.string.shortgramm));
|
||||
holder.fat.setText(MainApp.sResources.getString(R.string.shortfat) + ": " + food.fat + MainApp.sResources.getString(R.string.shortgramm));
|
||||
holder.carbs.setText(food.carbs + MainApp.gs(R.string.shortgramm));
|
||||
holder.fat.setText(MainApp.gs(R.string.shortfat) + ": " + food.fat + MainApp.gs(R.string.shortgramm));
|
||||
if (food.fat == 0)
|
||||
holder.fat.setVisibility(View.INVISIBLE);
|
||||
holder.protein.setText(MainApp.sResources.getString(R.string.shortprotein) + ": " + food.protein + MainApp.sResources.getString(R.string.shortgramm));
|
||||
holder.protein.setText(MainApp.gs(R.string.shortprotein) + ": " + food.protein + MainApp.gs(R.string.shortgramm));
|
||||
if (food.protein == 0)
|
||||
holder.protein.setVisibility(View.INVISIBLE);
|
||||
holder.energy.setText(MainApp.sResources.getString(R.string.shortenergy) + ": " + food.energy + MainApp.sResources.getString(R.string.shortkilojoul));
|
||||
holder.energy.setText(MainApp.gs(R.string.shortenergy) + ": " + food.energy + MainApp.gs(R.string.shortkilojoul));
|
||||
if (food.energy == 0)
|
||||
holder.energy.setVisibility(View.INVISIBLE);
|
||||
holder.remove.setTag(food);
|
||||
|
@ -291,18 +291,18 @@ public class FoodFragment extends SubscriberFragment {
|
|||
|
||||
case R.id.food_remove:
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
|
||||
builder.setTitle(MainApp.sResources.getString(R.string.confirmation));
|
||||
builder.setMessage(MainApp.sResources.getString(R.string.removerecord) + "\n" + food.name);
|
||||
builder.setPositiveButton(MainApp.sResources.getString(R.string.ok), new DialogInterface.OnClickListener() {
|
||||
builder.setTitle(MainApp.gs(R.string.confirmation));
|
||||
builder.setMessage(MainApp.gs(R.string.removerecord) + "\n" + food.name);
|
||||
builder.setPositiveButton(MainApp.gs(R.string.ok), new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
final String _id = food._id;
|
||||
if (_id != null && !_id.equals("")) {
|
||||
NSUpload.removeFoodFromNS(_id);
|
||||
}
|
||||
MainApp.getDbHelper().foodHelper.delete(food);
|
||||
MainApp.getSpecificPlugin(FoodPlugin.class).getService().delete(food);
|
||||
}
|
||||
});
|
||||
builder.setNegativeButton(MainApp.sResources.getString(R.string.cancel), null);
|
||||
builder.setNegativeButton(MainApp.gs(R.string.cancel), null);
|
||||
builder.show();
|
||||
break;
|
||||
|
||||
|
|
|
@ -1,15 +1,14 @@
|
|||
package info.nightscout.androidaps.plugins.Food;
|
||||
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||
import info.nightscout.androidaps.interfaces.PluginDescription;
|
||||
import info.nightscout.androidaps.interfaces.PluginType;
|
||||
|
||||
/**
|
||||
* Created by mike on 05.08.2016.
|
||||
*/
|
||||
public class FoodPlugin implements PluginBase {
|
||||
private boolean fragmentEnabled = true;
|
||||
private boolean fragmentVisible = false;
|
||||
public class FoodPlugin extends PluginBase {
|
||||
|
||||
private static FoodPlugin plugin = null;
|
||||
|
||||
|
@ -19,67 +18,20 @@ public class FoodPlugin implements PluginBase {
|
|||
return plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFragmentClass() {
|
||||
return FoodFragment.class.getName();
|
||||
private FoodService service;
|
||||
|
||||
private FoodPlugin() {
|
||||
super(new PluginDescription()
|
||||
.mainType(PluginType.GENERAL)
|
||||
.fragmentClass(FoodFragment.class.getName())
|
||||
.pluginName(R.string.food)
|
||||
.shortName(R.string.food_short)
|
||||
);
|
||||
this.service = new FoodService();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getType() {
|
||||
return PluginBase.GENERAL;
|
||||
public FoodService getService() {
|
||||
return this.service;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return MainApp.instance().getString(R.string.food);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNameShort() {
|
||||
// use long name as fallback (not visible in tabs)
|
||||
return getName();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(int type) {
|
||||
return type == GENERAL && fragmentEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVisibleInTabs(int type) {
|
||||
return type == GENERAL && fragmentVisible;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeHidden(int type) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasFragment() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean showInList(int type) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
|
||||
if (type == GENERAL) this.fragmentEnabled = fragmentEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFragmentVisible(int type, boolean fragmentVisible) {
|
||||
if (type == GENERAL) this.fragmentVisible = fragmentVisible;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPreferencesId() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,369 @@
|
|||
package info.nightscout.androidaps.plugins.Food;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import com.j256.ormlite.android.apptools.OpenHelperManager;
|
||||
import com.j256.ormlite.android.apptools.OrmLiteBaseService;
|
||||
import com.j256.ormlite.dao.Dao;
|
||||
import com.j256.ormlite.dao.DaoManager;
|
||||
import com.j256.ormlite.support.ConnectionSource;
|
||||
import com.j256.ormlite.table.TableUtils;
|
||||
import com.squareup.otto.Subscribe;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.db.DatabaseHelper;
|
||||
import info.nightscout.androidaps.db.ICallback;
|
||||
import info.nightscout.androidaps.events.Event;
|
||||
import info.nightscout.androidaps.events.EventFoodDatabaseChanged;
|
||||
import info.nightscout.androidaps.events.EventNsFood;
|
||||
|
||||
/**
|
||||
* Created by mike on 24.09.2017.
|
||||
*/
|
||||
|
||||
public class FoodService extends OrmLiteBaseService<DatabaseHelper> {
|
||||
private static Logger log = LoggerFactory.getLogger(FoodService.class);
|
||||
|
||||
private static final ScheduledExecutorService foodEventWorker = Executors.newSingleThreadScheduledExecutor();
|
||||
private static ScheduledFuture<?> scheduledFoodEventPost = null;
|
||||
|
||||
public FoodService() {
|
||||
onCreate();
|
||||
dbInitialize();
|
||||
MainApp.bus().register(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is a simple re-implementation of the database create and up/downgrade functionality
|
||||
* in SQLiteOpenHelper#getDatabaseLocked method.
|
||||
* <p>
|
||||
* It is implemented to be able to late initialize separate plugins of the application.
|
||||
*/
|
||||
protected void dbInitialize() {
|
||||
DatabaseHelper helper = OpenHelperManager.getHelper(this, DatabaseHelper.class);
|
||||
int newVersion = helper.getNewVersion();
|
||||
int oldVersion = helper.getOldVersion();
|
||||
|
||||
if (oldVersion > newVersion) {
|
||||
onDowngrade(this.getConnectionSource(), oldVersion, newVersion);
|
||||
} else {
|
||||
onUpgrade(this.getConnectionSource(), oldVersion, newVersion);
|
||||
}
|
||||
}
|
||||
|
||||
public Dao<Food, Long> getDao() {
|
||||
try {
|
||||
return DaoManager.createDao(this.getConnectionSource(), Food.class);
|
||||
} catch (SQLException e) {
|
||||
log.error("Cannot create Dao for Food.class");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void handleNsEvent(EventNsFood event) {
|
||||
int mode = event.getMode();
|
||||
Bundle payload = event.getPayload();
|
||||
|
||||
try {
|
||||
if (payload.containsKey("food")) {
|
||||
JSONObject json = new JSONObject(payload.getString("food"));
|
||||
if (mode == EventNsFood.ADD || mode == EventNsFood.UPDATE) {
|
||||
this.createFoodFromJsonIfNotExists(json);
|
||||
} else {
|
||||
this.deleteNS(json);
|
||||
}
|
||||
}
|
||||
|
||||
if (payload.containsKey("foods")) {
|
||||
JSONArray array = new JSONArray(payload.getString("foods"));
|
||||
if (mode == EventNsFood.ADD || mode == EventNsFood.UPDATE) {
|
||||
this.createFoodFromJsonIfNotExists(array);
|
||||
} else {
|
||||
this.deleteNS(array);
|
||||
}
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
log.error("Unhandled Exception", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
try {
|
||||
log.info("onCreate");
|
||||
TableUtils.createTableIfNotExists(this.getConnectionSource(), Food.class);
|
||||
} catch (SQLException e) {
|
||||
log.error("Can't create database", e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void onUpgrade(ConnectionSource connectionSource, int oldVersion, int newVersion) {
|
||||
if (oldVersion == 7 && newVersion == 8) {
|
||||
log.debug("Upgrading database from v7 to v8");
|
||||
} else {
|
||||
log.info("onUpgrade");
|
||||
// this.resetFood();
|
||||
}
|
||||
}
|
||||
|
||||
public void onDowngrade(ConnectionSource connectionSource, int oldVersion, int newVersion) {
|
||||
// this method is not supported right now
|
||||
}
|
||||
|
||||
public void resetFood() {
|
||||
try {
|
||||
TableUtils.dropTable(this.getConnectionSource(), Food.class, true);
|
||||
TableUtils.createTableIfNotExists(this.getConnectionSource(), Food.class);
|
||||
} catch (SQLException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
scheduleFoodChange();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A place to centrally register events to be posted, if any data changed.
|
||||
* This should be implemented in an abstract service-class.
|
||||
* <p>
|
||||
* We do need to make sure, that ICallback is extended to be able to handle multiple
|
||||
* events, or handle a list of events.
|
||||
* <p>
|
||||
* on some methods the earliestDataChange event is handled separatly, in that it is checked if it is
|
||||
* set to null by another event already (eg. scheduleExtendedBolusChange).
|
||||
*
|
||||
* @param event
|
||||
* @param eventWorker
|
||||
* @param callback
|
||||
*/
|
||||
private void scheduleEvent(final Event event, ScheduledExecutorService eventWorker,
|
||||
final ICallback callback) {
|
||||
|
||||
class PostRunnable implements Runnable {
|
||||
public void run() {
|
||||
log.debug("Firing EventFoodChange");
|
||||
MainApp.bus().post(event);
|
||||
callback.setPost(null);
|
||||
}
|
||||
}
|
||||
// prepare task for execution in 1 sec
|
||||
// cancel waiting task to prevent sending multiple posts
|
||||
if (callback.getPost() != null)
|
||||
callback.getPost().cancel(false);
|
||||
Runnable task = new PostRunnable();
|
||||
final int sec = 1;
|
||||
callback.setPost(eventWorker.schedule(task, sec, TimeUnit.SECONDS));
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedule a foodChange Event.
|
||||
*/
|
||||
public void scheduleFoodChange() {
|
||||
this.scheduleEvent(new EventFoodDatabaseChanged(), foodEventWorker, new ICallback() {
|
||||
@Override
|
||||
public void setPost(ScheduledFuture<?> post) {
|
||||
scheduledFoodEventPost = post;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScheduledFuture<?> getPost() {
|
||||
return scheduledFoodEventPost;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public List<Food> getFoodData() {
|
||||
try {
|
||||
return this.getDao().queryForAll();
|
||||
} catch (SQLException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
/*
|
||||
{
|
||||
"_id": "551ee3ad368e06e80856e6a9",
|
||||
"type": "food",
|
||||
"category": "Zakladni",
|
||||
"subcategory": "Napoje",
|
||||
"name": "Mleko",
|
||||
"portion": 250,
|
||||
"carbs": 12,
|
||||
"gi": 1,
|
||||
"created_at": "2015-04-14T06:59:16.500Z",
|
||||
"unit": "ml"
|
||||
}
|
||||
*/
|
||||
public void createFoodFromJsonIfNotExists(JSONObject json) {
|
||||
try {
|
||||
Food food = Food.createFromJson(json);
|
||||
this.createFoodFromJsonIfNotExists(food);
|
||||
} catch (JSONException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void createFoodFromJsonIfNotExists(JSONArray array) {
|
||||
try {
|
||||
for (int n = 0; n < array.length(); n++) {
|
||||
JSONObject json = array.getJSONObject(n);
|
||||
Food food = Food.createFromJson(json);
|
||||
this.createFoodFromJsonIfNotExists(food);
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void createFoodFromJsonIfNotExists(Food food) {
|
||||
this.createOrUpdateByNS(food);
|
||||
}
|
||||
|
||||
public void deleteNS(JSONObject json) {
|
||||
try {
|
||||
String _id = json.getString("_id");
|
||||
this.deleteByNSId(_id);
|
||||
} catch (JSONException | SQLException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteNS(JSONArray array) {
|
||||
try {
|
||||
for (int n = 0; n < array.length(); n++) {
|
||||
JSONObject json = array.getJSONObject(n);
|
||||
this.deleteNS(json);
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* deletes an entry by its NS Id.
|
||||
* <p>
|
||||
* Basically a convenience method for findByNSId and delete.
|
||||
*
|
||||
* @param _id
|
||||
*/
|
||||
public void deleteByNSId(String _id) throws SQLException {
|
||||
Food stored = this.findByNSId(_id);
|
||||
if (stored != null) {
|
||||
log.debug("FOOD: Removing Food record from database: " + stored.toString());
|
||||
this.delete(stored);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* deletes the food and sends the foodChange Event
|
||||
* <p>
|
||||
* should be moved ot a Service
|
||||
*
|
||||
* @param food
|
||||
*/
|
||||
public void delete(Food food) {
|
||||
try {
|
||||
this.getDao().delete(food);
|
||||
this.scheduleFoodChange();
|
||||
} catch (SQLException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create of update a food record by the NS (Nightscout) Id.
|
||||
*
|
||||
* @param food
|
||||
* @return
|
||||
*/
|
||||
public boolean createOrUpdateByNS(Food food) {
|
||||
// find by NS _id
|
||||
if (food._id != null && !food._id.equals("")) {
|
||||
Food old = this.findByNSId(food._id);
|
||||
|
||||
if (old != null) {
|
||||
if (!old.isEqual(food)) {
|
||||
this.delete(old); // need to delete/create because date may change too
|
||||
old.copyFrom(food);
|
||||
this.create(old);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
this.createOrUpdate(food);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void createOrUpdate(Food food) {
|
||||
try {
|
||||
this.getDao().createOrUpdate(food);
|
||||
log.debug("FOOD: Created or Updated: " + food.toString());
|
||||
} catch (SQLException e) {
|
||||
log.error("Unable to createOrUpdate Food", e);
|
||||
}
|
||||
this.scheduleFoodChange();
|
||||
}
|
||||
|
||||
public void create(Food food) {
|
||||
try {
|
||||
this.getDao().create(food);
|
||||
log.debug("FOOD: New record: " + food.toString());
|
||||
} catch (SQLException e) {
|
||||
log.error("Unable to create Food", e);
|
||||
}
|
||||
this.scheduleFoodChange();
|
||||
}
|
||||
|
||||
/**
|
||||
* finds food by its NS Id.
|
||||
*
|
||||
* @param _id
|
||||
* @return
|
||||
*/
|
||||
@Nullable
|
||||
public Food findByNSId(String _id) {
|
||||
try {
|
||||
List<Food> list = this.getDao().queryForEq("_id", _id);
|
||||
|
||||
if (list.size() == 1) { // really? if there are more then one result, then we do not return anything...
|
||||
return list.get(0);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -12,7 +12,7 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
|
||||
import info.nightscout.androidaps.data.Iob;
|
||||
import info.nightscout.androidaps.db.Treatment;
|
||||
import info.nightscout.androidaps.plugins.Treatments.Treatment;
|
||||
import info.nightscout.androidaps.interfaces.InsulinInterface;
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,136 +0,0 @@
|
|||
package info.nightscout.androidaps.plugins.Insulin;
|
||||
|
||||
import info.nightscout.androidaps.Constants;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.data.Iob;
|
||||
import info.nightscout.androidaps.db.Treatment;
|
||||
import info.nightscout.androidaps.interfaces.InsulinInterface;
|
||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||
|
||||
/**
|
||||
* Created by mike on 17.04.2017.
|
||||
*/
|
||||
|
||||
public class InsulinFastactingPlugin implements PluginBase, InsulinInterface {
|
||||
|
||||
private boolean fragmentEnabled = true;
|
||||
private boolean fragmentVisible = false;
|
||||
|
||||
private static InsulinFastactingPlugin plugin = null;
|
||||
|
||||
public static InsulinFastactingPlugin getPlugin() {
|
||||
if (plugin == null)
|
||||
plugin = new InsulinFastactingPlugin();
|
||||
return plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getType() {
|
||||
return INSULIN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFragmentClass() {
|
||||
return InsulinFragment.class.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return MainApp.sResources.getString(R.string.fastactinginsulin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNameShort() {
|
||||
return MainApp.sResources.getString(R.string.insulin_shortname);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(int type) {
|
||||
return type == INSULIN && fragmentEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVisibleInTabs(int type) {
|
||||
return type == INSULIN && fragmentVisible;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeHidden(int type) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasFragment() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean showInList(int type) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
|
||||
if (type == INSULIN) this.fragmentEnabled = fragmentEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFragmentVisible(int type, boolean fragmentVisible) {
|
||||
if (type == INSULIN) this.fragmentVisible = fragmentVisible;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPreferencesId() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Insulin interface
|
||||
@Override
|
||||
public int getId() {
|
||||
return FASTACTINGINSULIN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFriendlyName() {
|
||||
return MainApp.sResources.getString(R.string.fastactinginsulin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getComment() {
|
||||
return MainApp.sResources.getString(R.string.fastactinginsulincomment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getDia() {
|
||||
return MainApp.getConfigBuilder().getProfile() != null ? MainApp.getConfigBuilder().getProfile().getDia() : Constants.defaultDIA;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iob iobCalcForTreatment(Treatment treatment, long time, double dia) {
|
||||
Iob result = new Iob();
|
||||
|
||||
double scaleFactor = 3.0 / dia;
|
||||
double peak = 75d;
|
||||
double end = 180d;
|
||||
|
||||
if (treatment.insulin != 0d) {
|
||||
long bolusTime = treatment.date;
|
||||
double minAgo = scaleFactor * (time - bolusTime) / 1000d / 60d;
|
||||
|
||||
if (minAgo < peak) {
|
||||
double x1 = minAgo / 5d + 1;
|
||||
result.iobContrib = treatment.insulin * (1 - 0.001852 * x1 * x1 + 0.001852 * x1);
|
||||
// units: BG (mg/dL) = (BG/U) * U insulin * scalar
|
||||
result.activityContrib = treatment.insulin * (2 / dia / 60 / peak) * minAgo;
|
||||
|
||||
} else if (minAgo < end) {
|
||||
double x2 = (minAgo - 75) / 5;
|
||||
result.iobContrib = treatment.insulin * (0.001323 * x2 * x2 - 0.054233 * x2 + 0.55556);
|
||||
result.activityContrib = treatment.insulin * (2 / dia / 60 - (minAgo - peak) * 2 / dia / 60 / (60 * 3 - peak));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,141 +0,0 @@
|
|||
package info.nightscout.androidaps.plugins.Insulin;
|
||||
|
||||
import info.nightscout.androidaps.Constants;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.data.Iob;
|
||||
import info.nightscout.androidaps.db.Treatment;
|
||||
import info.nightscout.androidaps.interfaces.InsulinInterface;
|
||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||
|
||||
/**
|
||||
* Created by mike on 17.04.2017.
|
||||
*/
|
||||
|
||||
public class InsulinFastactingProlongedPlugin implements PluginBase, InsulinInterface {
|
||||
|
||||
private boolean fragmentEnabled = false;
|
||||
private boolean fragmentVisible = false;
|
||||
|
||||
private static InsulinFastactingProlongedPlugin plugin = null;
|
||||
|
||||
public static InsulinFastactingProlongedPlugin getPlugin() {
|
||||
if (plugin == null)
|
||||
plugin = new InsulinFastactingProlongedPlugin();
|
||||
return plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getType() {
|
||||
return INSULIN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFragmentClass() {
|
||||
return InsulinFragment.class.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return MainApp.sResources.getString(R.string.fastactinginsulinprolonged);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNameShort() {
|
||||
return MainApp.sResources.getString(R.string.insulin_shortname);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(int type) {
|
||||
return type == INSULIN && fragmentEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVisibleInTabs(int type) {
|
||||
return type == INSULIN && fragmentVisible;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeHidden(int type) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasFragment() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean showInList(int type) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
|
||||
if (type == INSULIN) this.fragmentEnabled = fragmentEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFragmentVisible(int type, boolean fragmentVisible) {
|
||||
if (type == INSULIN) this.fragmentVisible = fragmentVisible;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPreferencesId() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Insulin interface
|
||||
@Override
|
||||
public int getId() {
|
||||
return FASTACTINGINSULINPROLONGED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFriendlyName() {
|
||||
return MainApp.sResources.getString(R.string.fastactinginsulinprolonged);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getComment() {
|
||||
return MainApp.sResources.getString(R.string.fastactinginsulincomment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getDia() {
|
||||
return MainApp.getConfigBuilder().getProfile() != null ? MainApp.getConfigBuilder().getProfile().getDia() : Constants.defaultDIA;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iob iobCalcForTreatment(Treatment treatment, long time, double dia) {
|
||||
Iob result = new Iob();
|
||||
|
||||
//Double scaleFactor = 3.0 / dia;
|
||||
double peak = 75d * dia / 6.0;
|
||||
double tail = 180d * dia / 6.0;
|
||||
double end = 360d * dia / 6.0;
|
||||
double Total = 2 * peak + (tail - peak) * 5 / 2 + (end - tail) / 2;
|
||||
|
||||
if (treatment.insulin != 0d) {
|
||||
long bolusTime = treatment.date;
|
||||
double minAgo = (time - bolusTime) / 1000d / 60d;
|
||||
|
||||
if (minAgo < peak) {
|
||||
double x1 = 6 / dia * minAgo / 5d + 1;
|
||||
result.iobContrib = treatment.insulin * (1 - 0.0012595 * x1 * x1 + 0.0012595 * x1);
|
||||
// units: BG (mg/dL) = (BG/U) * U insulin * scalar
|
||||
result.activityContrib = treatment.insulin * ((2 * peak / Total) * 2 / peak / peak * minAgo);
|
||||
} else if (minAgo < tail) {
|
||||
double x2 = (6 / dia * (minAgo - peak)) / 5;
|
||||
result.iobContrib = treatment.insulin * (0.00074 * x2 * x2 - 0.0403 * x2 + 0.69772);
|
||||
result.activityContrib = treatment.insulin * (-((2 * peak / Total) * 2 / peak * 3 / 4) / (tail - peak) * (minAgo - peak) + (2 * peak / Total) * 2 / peak);
|
||||
} else if (minAgo < end) {
|
||||
double x3 = (6 / dia * (minAgo - tail)) / 5;
|
||||
result.iobContrib = treatment.insulin * (0.0001323 * x3 * x3 - 0.0097 * x3 + 0.17776);
|
||||
result.activityContrib = treatment.insulin * (-((2 * peak / Total) * 2 / peak * 1 / 4) / (end - tail) * (minAgo - tail) + (2 * peak / Total) * 2 / peak / 4);
|
||||
}
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -7,11 +7,11 @@ import android.view.View;
|
|||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.crashlytics.android.Crashlytics;
|
||||
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.utils.FabricPrivacy;
|
||||
|
||||
/**
|
||||
* Created by mike on 17.04.2017.
|
||||
|
@ -37,7 +37,7 @@ public class InsulinFragment extends Fragment {
|
|||
|
||||
return view;
|
||||
} catch (Exception e) {
|
||||
Crashlytics.logException(e);
|
||||
FabricPrivacy.logException(e);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
|
|
@ -5,45 +5,31 @@ import com.squareup.otto.Bus;
|
|||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.data.Iob;
|
||||
import info.nightscout.androidaps.db.Treatment;
|
||||
import info.nightscout.androidaps.plugins.Treatments.Treatment;
|
||||
import info.nightscout.androidaps.interfaces.InsulinInterface;
|
||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
|
||||
import info.nightscout.androidaps.interfaces.PluginDescription;
|
||||
import info.nightscout.androidaps.interfaces.PluginType;
|
||||
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
|
||||
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
|
||||
|
||||
/**
|
||||
* Created by adrian on 13.08.2017.
|
||||
*/
|
||||
|
||||
public abstract class InsulinOrefBasePlugin implements PluginBase, InsulinInterface {
|
||||
public abstract class InsulinOrefBasePlugin extends PluginBase implements InsulinInterface {
|
||||
|
||||
public static double MIN_DIA = 5;
|
||||
|
||||
long lastWarned = 0;
|
||||
|
||||
@Override
|
||||
public int getType() {
|
||||
return INSULIN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNameShort() {
|
||||
return MainApp.sResources.getString(R.string.insulin_shortname);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeHidden(int type) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasFragment() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean showInList(int type) {
|
||||
return true;
|
||||
public InsulinOrefBasePlugin() {
|
||||
super(new PluginDescription()
|
||||
.mainType(PluginType.INSULIN)
|
||||
.fragmentClass(InsulinFragment.class.getName())
|
||||
.pluginName(R.string.fastactinginsulin)
|
||||
.shortName(R.string.insulin_shortname)
|
||||
);
|
||||
}
|
||||
|
||||
public Bus getBus() {
|
||||
|
@ -53,7 +39,7 @@ public abstract class InsulinOrefBasePlugin implements PluginBase, InsulinInterf
|
|||
@Override
|
||||
public double getDia() {
|
||||
double dia = getUserDefinedDia();
|
||||
if(dia >= MIN_DIA){
|
||||
if (dia >= MIN_DIA) {
|
||||
return dia;
|
||||
} else {
|
||||
sendShortDiaNotification(dia);
|
||||
|
@ -62,7 +48,7 @@ public abstract class InsulinOrefBasePlugin implements PluginBase, InsulinInterf
|
|||
}
|
||||
|
||||
void sendShortDiaNotification(double dia) {
|
||||
if((System.currentTimeMillis() - lastWarned) > 60*1000) {
|
||||
if ((System.currentTimeMillis() - lastWarned) > 60 * 1000) {
|
||||
lastWarned = System.currentTimeMillis();
|
||||
Notification notification = new Notification(Notification.SHORT_DIA, String.format(this.getNotificationPattern(), dia, MIN_DIA), Notification.URGENT);
|
||||
this.getBus().post(new EventNewNotification(notification));
|
||||
|
@ -70,7 +56,7 @@ public abstract class InsulinOrefBasePlugin implements PluginBase, InsulinInterf
|
|||
}
|
||||
|
||||
public String getNotificationPattern() {
|
||||
return MainApp.sResources.getString(R.string.dia_too_short);
|
||||
return MainApp.gs(R.string.dia_too_short);
|
||||
}
|
||||
|
||||
public double getUserDefinedDia() {
|
||||
|
@ -92,7 +78,7 @@ public abstract class InsulinOrefBasePlugin implements PluginBase, InsulinInterf
|
|||
long bolusTime = treatment.date;
|
||||
double t = (time - bolusTime) / 1000d / 60d;
|
||||
|
||||
double td = getDia()*60; //getDIA() always >= MIN_DIA
|
||||
double td = getDia() * 60; //getDIA() always >= MIN_DIA
|
||||
double tp = peak;
|
||||
|
||||
// force the IOB to 0 if over DIA hours have passed
|
||||
|
@ -109,10 +95,10 @@ public abstract class InsulinOrefBasePlugin implements PluginBase, InsulinInterf
|
|||
|
||||
@Override
|
||||
public String getComment() {
|
||||
String comment = commentStandardText();
|
||||
String comment = commentStandardText();
|
||||
double userDia = getUserDefinedDia();
|
||||
if(userDia < MIN_DIA){
|
||||
comment += "\n" + String.format(MainApp.sResources.getString(R.string.dia_too_short), userDia, MIN_DIA);
|
||||
if (userDia < MIN_DIA) {
|
||||
comment += "\n" + String.format(MainApp.gs(R.string.dia_too_short), userDia, MIN_DIA);
|
||||
}
|
||||
return comment;
|
||||
}
|
||||
|
|
|
@ -10,9 +10,6 @@ import info.nightscout.utils.SP;
|
|||
|
||||
public class InsulinOrefFreePeakPlugin extends InsulinOrefBasePlugin {
|
||||
|
||||
private boolean fragmentEnabled = false;
|
||||
private boolean fragmentVisible = false;
|
||||
|
||||
private static InsulinOrefFreePeakPlugin plugin = null;
|
||||
|
||||
public static InsulinOrefFreePeakPlugin getPlugin() {
|
||||
|
@ -21,56 +18,27 @@ public class InsulinOrefFreePeakPlugin extends InsulinOrefBasePlugin {
|
|||
return plugin;
|
||||
}
|
||||
|
||||
public static final int DEFAULT_PEAK = 75;
|
||||
private static final int DEFAULT_PEAK = 75;
|
||||
|
||||
private InsulinOrefFreePeakPlugin() {
|
||||
super();
|
||||
pluginDescription
|
||||
.pluginName(R.string.free_peak_oref)
|
||||
.preferencesId(R.xml.pref_insulinoreffreepeak);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return OREF_FREE_PEAK;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return MainApp.sResources.getString(R.string.free_peak_oref);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFragmentClass() {
|
||||
return InsulinFragment.class.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFriendlyName() {
|
||||
return MainApp.sResources.getString(R.string.free_peak_oref);
|
||||
return MainApp.gs(R.string.free_peak_oref);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String commentStandardText() {
|
||||
return MainApp.sResources.getString(R.string.insulin_peak_time) + ": " + getPeak();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(int type) {
|
||||
return type == INSULIN && fragmentEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVisibleInTabs(int type) {
|
||||
return type == INSULIN && fragmentVisible;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
|
||||
if (type == INSULIN) this.fragmentEnabled = fragmentEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFragmentVisible(int type, boolean fragmentVisible) {
|
||||
if (type == INSULIN) this.fragmentVisible = fragmentVisible;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPreferencesId() {
|
||||
return R.xml.pref_insulinoreffreepeak;
|
||||
return MainApp.gs(R.string.insulin_peak_time) + ": " + getPeak();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -9,9 +9,6 @@ import info.nightscout.androidaps.R;
|
|||
|
||||
public class InsulinOrefRapidActingPlugin extends InsulinOrefBasePlugin {
|
||||
|
||||
private boolean fragmentEnabled = false;
|
||||
private boolean fragmentVisible = false;
|
||||
|
||||
private static InsulinOrefRapidActingPlugin plugin = null;
|
||||
|
||||
public static InsulinOrefRapidActingPlugin getPlugin() {
|
||||
|
@ -20,56 +17,27 @@ public class InsulinOrefRapidActingPlugin extends InsulinOrefBasePlugin {
|
|||
return plugin;
|
||||
}
|
||||
|
||||
public static final int PEAK = 75;
|
||||
private static final int PEAK = 75;
|
||||
|
||||
private InsulinOrefRapidActingPlugin() {
|
||||
super();
|
||||
pluginDescription
|
||||
.pluginName(R.string.rapid_acting_oref);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return OREF_RAPID_ACTING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return MainApp.sResources.getString(R.string.rapid_acting_oref);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFragmentClass() {
|
||||
return InsulinFragment.class.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFriendlyName() {
|
||||
return MainApp.sResources.getString(R.string.rapid_acting_oref);
|
||||
return MainApp.gs(R.string.rapid_acting_oref);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String commentStandardText() {
|
||||
return MainApp.sResources.getString(R.string.fastactinginsulincomment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(int type) {
|
||||
return type == INSULIN && fragmentEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVisibleInTabs(int type) {
|
||||
return type == INSULIN && fragmentVisible;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
|
||||
if (type == INSULIN) this.fragmentEnabled = fragmentEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFragmentVisible(int type, boolean fragmentVisible) {
|
||||
if (type == INSULIN) this.fragmentVisible = fragmentVisible;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPreferencesId() {
|
||||
return -1;
|
||||
return MainApp.gs(R.string.fastactinginsulincomment);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -9,9 +9,6 @@ import info.nightscout.androidaps.R;
|
|||
|
||||
public class InsulinOrefUltraRapidActingPlugin extends InsulinOrefBasePlugin {
|
||||
|
||||
private boolean fragmentEnabled = false;
|
||||
private boolean fragmentVisible = false;
|
||||
|
||||
private static InsulinOrefUltraRapidActingPlugin plugin = null;
|
||||
|
||||
public static InsulinOrefUltraRapidActingPlugin getPlugin() {
|
||||
|
@ -20,7 +17,13 @@ public class InsulinOrefUltraRapidActingPlugin extends InsulinOrefBasePlugin {
|
|||
return plugin;
|
||||
}
|
||||
|
||||
public static final int PEAK = 55;
|
||||
private static final int PEAK = 55;
|
||||
|
||||
private InsulinOrefUltraRapidActingPlugin() {
|
||||
super();
|
||||
pluginDescription
|
||||
.pluginName(R.string.ultrarapid_oref);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
|
@ -29,47 +32,17 @@ public class InsulinOrefUltraRapidActingPlugin extends InsulinOrefBasePlugin {
|
|||
|
||||
@Override
|
||||
public String getName() {
|
||||
return MainApp.sResources.getString(R.string.ultrarapid_oref);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFragmentClass() {
|
||||
return InsulinFragment.class.getName();
|
||||
return MainApp.gs(R.string.ultrarapid_oref);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFriendlyName() {
|
||||
return MainApp.sResources.getString(R.string.ultrarapid_oref);
|
||||
return MainApp.gs(R.string.ultrarapid_oref);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String commentStandardText() {
|
||||
return MainApp.sResources.getString(R.string.ultrafastactinginsulincomment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(int type) {
|
||||
return type == INSULIN && fragmentEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVisibleInTabs(int type) {
|
||||
return type == INSULIN && fragmentVisible;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
|
||||
if (type == INSULIN) this.fragmentEnabled = fragmentEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFragmentVisible(int type, boolean fragmentVisible) {
|
||||
if (type == INSULIN) this.fragmentVisible = fragmentVisible;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPreferencesId() {
|
||||
return -1;
|
||||
return MainApp.gs(R.string.ultrafastactinginsulincomment);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -7,22 +7,31 @@ import java.util.ArrayList;
|
|||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import info.nightscout.androidaps.Constants;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.data.Profile;
|
||||
import info.nightscout.androidaps.db.Treatment;
|
||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||
import info.nightscout.androidaps.interfaces.PluginType;
|
||||
import info.nightscout.androidaps.plugins.OpenAPSSMB.SMBDefaults;
|
||||
import info.nightscout.androidaps.plugins.Overview.graphExtensions.DataPointWithLabelInterface;
|
||||
import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLabelGraphSeries;
|
||||
import info.nightscout.androidaps.plugins.Overview.graphExtensions.Scale;
|
||||
import info.nightscout.androidaps.plugins.SensitivityAAPS.SensitivityAAPSPlugin;
|
||||
import info.nightscout.androidaps.plugins.SensitivityWeightedAverage.SensitivityWeightedAveragePlugin;
|
||||
import info.nightscout.androidaps.plugins.Treatments.Treatment;
|
||||
import info.nightscout.utils.SP;
|
||||
|
||||
/**
|
||||
* Created by mike on 25.04.2017.
|
||||
*/
|
||||
|
||||
public class AutosensData {
|
||||
public class AutosensData implements DataPointWithLabelInterface {
|
||||
private static Logger log = LoggerFactory.getLogger(AutosensData.class);
|
||||
|
||||
public void setChartTime(long chartTime) {
|
||||
this.chartTime = chartTime;
|
||||
}
|
||||
|
||||
static class CarbsInPast {
|
||||
long time = 0L;
|
||||
double carbs = 0d;
|
||||
|
@ -33,20 +42,21 @@ public class AutosensData {
|
|||
time = t.date;
|
||||
carbs = t.carbs;
|
||||
remaining = t.carbs;
|
||||
if (SensitivityAAPSPlugin.getPlugin().isEnabled(PluginBase.SENSITIVITY) || SensitivityWeightedAveragePlugin.getPlugin().isEnabled(PluginBase.SENSITIVITY)) {
|
||||
double maxAbsorptionHours = SP.getDouble(R.string.key_absorption_maxtime, 4d);
|
||||
if (SensitivityAAPSPlugin.getPlugin().isEnabled(PluginType.SENSITIVITY) || SensitivityWeightedAveragePlugin.getPlugin().isEnabled(PluginType.SENSITIVITY)) {
|
||||
double maxAbsorptionHours = SP.getDouble(R.string.key_absorption_maxtime, Constants.DEFAULT_MAX_ABSORPTION_TIME);
|
||||
Profile profile = MainApp.getConfigBuilder().getProfile(t.date);
|
||||
double sens = Profile.toMgdl(profile.getIsf(t.date), profile.getUnits());
|
||||
double ic = profile.getIc(t.date);
|
||||
min5minCarbImpact = t.carbs / (maxAbsorptionHours * 60 / 5) * sens / ic;
|
||||
log.debug("Min 5m carbs impact for " + carbs + "g @" + new Date(t.date).toLocaleString() + " for " + maxAbsorptionHours + "h calculated to " + min5minCarbImpact + " ISF: " + sens + " IC: " + ic);
|
||||
} else {
|
||||
min5minCarbImpact = SP.getDouble("openapsama_min_5m_carbimpact", 3.0);
|
||||
min5minCarbImpact = SP.getDouble(R.string.key_openapsama_min_5m_carbimpact, SMBDefaults.min_5m_carbimpact);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public long time = 0L;
|
||||
long chartTime;
|
||||
public String pastSensitivity = "";
|
||||
public double deviation = 0d;
|
||||
boolean nonCarbsDeviation = false;
|
||||
|
@ -57,26 +67,39 @@ public class AutosensData {
|
|||
public double cob = 0;
|
||||
public double bgi = 0d;
|
||||
public double delta = 0d;
|
||||
public double avgDelta = 0d;
|
||||
public double avgDeviation = 0d;
|
||||
|
||||
public double autosensRatio = 1d;
|
||||
public double slopeFromMaxDeviation = 0;
|
||||
public double slopeFromMinDeviation = 999;
|
||||
public double usedMinCarbsImpact = 0d;
|
||||
public boolean failoverToMinAbsorbtionRate = false;
|
||||
|
||||
public String log(long time) {
|
||||
return "AutosensData: " + new Date(time).toLocaleString() + " " + pastSensitivity + " Delta=" + delta + " Bgi=" + bgi + " Deviation=" + deviation + " Absorbed=" + absorbed + " CarbsFromBolus=" + carbsFromBolus + " COB=" + cob + " autosensRatio=" + autosensRatio;
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AutosensData: " + new Date(time).toLocaleString() + " " + pastSensitivity + " Delta=" + delta + " avgDelta=" + avgDelta + " Bgi=" + bgi + " Deviation=" + deviation + " avgDeviation=" + avgDeviation + " Absorbed=" + absorbed + " CarbsFromBolus=" + carbsFromBolus + " COB=" + cob + " autosensRatio=" + autosensRatio + " slopeFromMaxDeviation=" + slopeFromMaxDeviation + " slopeFromMinDeviation =" + slopeFromMinDeviation;
|
||||
}
|
||||
|
||||
public int minOld() {
|
||||
return (int) ((System.currentTimeMillis() - time) / 1000 / 60);
|
||||
}
|
||||
|
||||
// remove carbs older than 4h
|
||||
// remove carbs older than timeframe
|
||||
public void removeOldCarbs(long toTime) {
|
||||
double maxAbsorptionHours = Constants.DEFAULT_MAX_ABSORPTION_TIME;
|
||||
if (SensitivityAAPSPlugin.getPlugin().isEnabled(PluginType.SENSITIVITY) || SensitivityWeightedAveragePlugin.getPlugin().isEnabled(PluginType.SENSITIVITY)) {
|
||||
maxAbsorptionHours = SP.getDouble(R.string.key_absorption_maxtime, Constants.DEFAULT_MAX_ABSORPTION_TIME);
|
||||
} else {
|
||||
maxAbsorptionHours = SP.getDouble(R.string.key_absorption_cutoff, Constants.DEFAULT_MAX_ABSORPTION_TIME);
|
||||
}
|
||||
for (int i = 0; i < activeCarbsList.size(); i++) {
|
||||
CarbsInPast c = activeCarbsList.get(i);
|
||||
if (c.time + 4 * 60 * 60 * 1000L < toTime) {
|
||||
if (c.time + maxAbsorptionHours * 60 * 60 * 1000L < toTime) {
|
||||
activeCarbsList.remove(i--);
|
||||
if (c.remaining > 0)
|
||||
cob -= c.remaining;
|
||||
log.debug("Removing carbs at "+ new Date(toTime).toLocaleString() + " + after 4h :" + new Date(c.time).toLocaleString());
|
||||
log.debug("Removing carbs at " + new Date(toTime).toLocaleString() + " + after " + maxAbsorptionHours + "h :" + new Date(c.time).toLocaleString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -93,4 +116,52 @@ public class AutosensData {
|
|||
}
|
||||
}
|
||||
|
||||
// ------- DataPointWithLabelInterface ------
|
||||
|
||||
private Scale scale;
|
||||
|
||||
public void setScale(Scale scale) {
|
||||
this.scale = scale;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getX() {
|
||||
return chartTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getY() {
|
||||
return scale.transform(cob);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setY(double y) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLabel() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getDuration() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PointsWithLabelGraphSeries.Shape getShape() {
|
||||
return PointsWithLabelGraphSeries.Shape.COBFAILOVER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getSize() {
|
||||
return 0.5f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getColor() {
|
||||
return MainApp.gc(R.color.cob);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
package info.nightscout.androidaps.plugins.IobCobCalculator;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import info.nightscout.utils.DecimalFormatter;
|
||||
|
||||
public class CobInfo {
|
||||
/** All COB up to now, including carbs not yet processed by IobCob calculation. */
|
||||
@Nullable
|
||||
public final Double displayCob;
|
||||
public final double futureCarbs;
|
||||
|
||||
public CobInfo(@Nullable Double displayCob, double futureCarbs) {
|
||||
this.displayCob = displayCob;
|
||||
this.futureCarbs = futureCarbs;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public String generateCOBString() {
|
||||
String cobStringResult = "--g";
|
||||
if (displayCob != null) {
|
||||
cobStringResult = DecimalFormatter.to0Decimal(displayCob);
|
||||
if (futureCarbs > 0) {
|
||||
cobStringResult += "(" + DecimalFormatter.to0Decimal(futureCarbs) + ")";
|
||||
}
|
||||
cobStringResult += "g";
|
||||
}
|
||||
return cobStringResult;
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package info.nightscout.androidaps.plugins.IobCobCalculator;
|
||||
|
||||
import android.os.SystemClock;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.util.LongSparseArray;
|
||||
|
||||
|
@ -22,36 +23,30 @@ import info.nightscout.androidaps.data.IobTotal;
|
|||
import info.nightscout.androidaps.data.Profile;
|
||||
import info.nightscout.androidaps.db.BgReading;
|
||||
import info.nightscout.androidaps.db.TemporaryBasal;
|
||||
import info.nightscout.androidaps.events.Event;
|
||||
import info.nightscout.androidaps.events.EventAppInitialized;
|
||||
import info.nightscout.androidaps.events.EventConfigBuilderChange;
|
||||
import info.nightscout.androidaps.events.EventNewBG;
|
||||
import info.nightscout.androidaps.events.EventNewBasalProfile;
|
||||
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.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventNewHistoryData;
|
||||
import info.nightscout.androidaps.plugins.OpenAPSSMB.OpenAPSSMBPlugin;
|
||||
import info.nightscout.androidaps.plugins.Treatments.Treatment;
|
||||
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
|
||||
import info.nightscout.utils.DateUtil;
|
||||
|
||||
import static info.nightscout.utils.DateUtil.now;
|
||||
|
||||
/**
|
||||
* Created by mike on 24.04.2017.
|
||||
*/
|
||||
|
||||
public class IobCobCalculatorPlugin implements PluginBase {
|
||||
private static Logger log = LoggerFactory.getLogger(IobCobCalculatorPlugin.class);
|
||||
|
||||
private static LongSparseArray<IobTotal> iobTable = new LongSparseArray<>(); // oldest at index 0
|
||||
private static LongSparseArray<AutosensData> autosensDataTable = new LongSparseArray<>(); // oldest at index 0
|
||||
private static LongSparseArray<BasalData> basalDataTable = new LongSparseArray<>(); // oldest at index 0
|
||||
|
||||
private static volatile List<BgReading> bgReadings = null; // newest at index 0
|
||||
private static volatile List<BgReading> bucketed_data = null;
|
||||
|
||||
private static double dia = Constants.defaultDIA;
|
||||
|
||||
static final Object dataLock = new Object();
|
||||
|
||||
boolean stopCalculationTrigger = false;
|
||||
IobCobThread thread = null;
|
||||
public class IobCobCalculatorPlugin extends PluginBase {
|
||||
private Logger log = LoggerFactory.getLogger(IobCobCalculatorPlugin.class);
|
||||
|
||||
private static IobCobCalculatorPlugin plugin = null;
|
||||
|
||||
|
@ -61,80 +56,52 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
|||
return plugin;
|
||||
}
|
||||
|
||||
public static LongSparseArray<AutosensData> getAutosensDataTable() {
|
||||
private LongSparseArray<IobTotal> iobTable = new LongSparseArray<>(); // oldest at index 0
|
||||
private LongSparseArray<AutosensData> autosensDataTable = new LongSparseArray<>(); // oldest at index 0
|
||||
private LongSparseArray<BasalData> basalDataTable = new LongSparseArray<>(); // oldest at index 0
|
||||
|
||||
private volatile List<BgReading> bgReadings = null; // newest at index 0
|
||||
private volatile List<BgReading> bucketed_data = null;
|
||||
|
||||
private double dia = Constants.defaultDIA;
|
||||
|
||||
final Object dataLock = new Object();
|
||||
|
||||
boolean stopCalculationTrigger = false;
|
||||
private IobCobThread thread = null;
|
||||
|
||||
public IobCobCalculatorPlugin() {
|
||||
super(new PluginDescription()
|
||||
.mainType(PluginType.GENERAL)
|
||||
.pluginName(R.string.iobcobcalculator)
|
||||
.showInList(false)
|
||||
.neverVisible(true)
|
||||
.alwaysEnabled(true)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
MainApp.bus().register(this);
|
||||
super.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
MainApp.bus().unregister(this);
|
||||
}
|
||||
|
||||
public LongSparseArray<AutosensData> getAutosensDataTable() {
|
||||
return autosensDataTable;
|
||||
}
|
||||
|
||||
public static List<BgReading> getBucketedData() {
|
||||
public List<BgReading> getBucketedData() {
|
||||
return bucketed_data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getType() {
|
||||
return GENERAL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFragmentClass() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "IOB COB Calculator";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNameShort() {
|
||||
return "IOC";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(int type) {
|
||||
return type == GENERAL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVisibleInTabs(int type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeHidden(int type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasFragment() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean showInList(int type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFragmentVisible(int type, boolean fragmentVisible) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPreferencesId() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
IobCobCalculatorPlugin() {
|
||||
MainApp.bus().register(this);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static List<BgReading> getBucketedData(long fromTime) {
|
||||
public List<BgReading> getBucketedData(long fromTime) {
|
||||
//log.debug("Locking getBucketedData");
|
||||
synchronized (dataLock) {
|
||||
if (bucketed_data == null) {
|
||||
|
@ -152,7 +119,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
|||
return null;
|
||||
}
|
||||
|
||||
private static int indexNewerThan(long time) {
|
||||
private int indexNewerThan(long time) {
|
||||
for (int index = 0; index < bucketed_data.size(); index++) {
|
||||
if (bucketed_data.get(index).date < time)
|
||||
return index - 1;
|
||||
|
@ -167,9 +134,9 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
|||
return rouded;
|
||||
}
|
||||
|
||||
void loadBgData() {
|
||||
bgReadings = MainApp.getDbHelper().getBgreadingsDataFromTime((long) (System.currentTimeMillis() - 60 * 60 * 1000L * (24 + dia)), false);
|
||||
log.debug("BG data loaded. Size: " + bgReadings.size());
|
||||
void loadBgData(long start) {
|
||||
bgReadings = MainApp.getDbHelper().getBgreadingsDataFromTime((long) (start - 60 * 60 * 1000L * (24 + dia)), false);
|
||||
log.debug("BG data loaded. Size: " + bgReadings.size() + " Start date: " + DateUtil.dateAndTimeString(start));
|
||||
}
|
||||
|
||||
private boolean isAbout5minData() {
|
||||
|
@ -259,7 +226,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
|||
}
|
||||
|
||||
|
||||
public void createBucketedData5min() {
|
||||
private void createBucketedData5min() {
|
||||
if (bgReadings == null || bgReadings.size() < 3) {
|
||||
bucketed_data = null;
|
||||
return;
|
||||
|
@ -321,22 +288,22 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
|||
log.debug("Bucketed data created. Size: " + bucketed_data.size());
|
||||
}
|
||||
|
||||
public static long oldestDataAvailable() {
|
||||
public long oldestDataAvailable() {
|
||||
long now = System.currentTimeMillis();
|
||||
|
||||
long oldestDataAvailable = MainApp.getConfigBuilder().oldestDataAvailable();
|
||||
long oldestDataAvailable = TreatmentsPlugin.getPlugin().oldestDataAvailable();
|
||||
long getBGDataFrom = Math.max(oldestDataAvailable, (long) (now - 60 * 60 * 1000L * (24 + MainApp.getConfigBuilder().getProfile().getDia())));
|
||||
log.debug("Limiting data to oldest available temps: " + new Date(oldestDataAvailable).toString());
|
||||
return getBGDataFrom;
|
||||
}
|
||||
|
||||
public static IobTotal calculateFromTreatmentsAndTempsSynchronized(long time) {
|
||||
public IobTotal calculateFromTreatmentsAndTempsSynchronized(long time, Profile profile) {
|
||||
synchronized (dataLock) {
|
||||
return calculateFromTreatmentsAndTemps(time);
|
||||
return calculateFromTreatmentsAndTemps(time, profile);
|
||||
}
|
||||
}
|
||||
|
||||
public static IobTotal calculateFromTreatmentsAndTemps(long time) {
|
||||
public IobTotal calculateFromTreatmentsAndTemps(long time, Profile profile) {
|
||||
long now = System.currentTimeMillis();
|
||||
time = roundUpTime(time);
|
||||
if (time < now && iobTable.get(time) != null) {
|
||||
|
@ -345,8 +312,22 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
|||
} else {
|
||||
//log.debug(">>> calculateFromTreatmentsAndTemps Cache miss " + new Date(time).toLocaleString());
|
||||
}
|
||||
IobTotal bolusIob = MainApp.getConfigBuilder().getCalculationToTimeTreatments(time).round();
|
||||
IobTotal basalIob = MainApp.getConfigBuilder().getCalculationToTimeTempBasals(time).round();
|
||||
IobTotal bolusIob = TreatmentsPlugin.getPlugin().getCalculationToTimeTreatments(time).round();
|
||||
IobTotal basalIob = TreatmentsPlugin.getPlugin().getCalculationToTimeTempBasals(time, profile, true, now).round();
|
||||
if (OpenAPSSMBPlugin.getPlugin().isEnabled(PluginType.APS)) {
|
||||
// Add expected zero temp basal for next 240 mins
|
||||
IobTotal basalIobWithZeroTemp = basalIob.copy();
|
||||
TemporaryBasal t = new TemporaryBasal()
|
||||
.date(now + 60 * 1000L)
|
||||
.duration(240)
|
||||
.absolute(0);
|
||||
if (t.date < time) {
|
||||
IobTotal calc = t.iobCalc(time, profile);
|
||||
basalIobWithZeroTemp.plus(calc);
|
||||
}
|
||||
|
||||
basalIob.iobWithZeroTemp = IobTotal.combine(bolusIob, basalIobWithZeroTemp).round();
|
||||
}
|
||||
|
||||
IobTotal iobTotal = IobTotal.combine(bolusIob, basalIob).round();
|
||||
if (time < System.currentTimeMillis()) {
|
||||
|
@ -356,7 +337,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
|||
}
|
||||
|
||||
@Nullable
|
||||
private static Long findPreviousTimeFromBucketedData(long time) {
|
||||
private Long findPreviousTimeFromBucketedData(long time) {
|
||||
if (bucketed_data == null)
|
||||
return null;
|
||||
for (int index = 0; index < bucketed_data.size(); index++) {
|
||||
|
@ -366,17 +347,18 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
|||
return null;
|
||||
}
|
||||
|
||||
public static BasalData getBasalData(long time) {
|
||||
public BasalData getBasalData(long time) {
|
||||
long now = System.currentTimeMillis();
|
||||
time = roundUpTime(time);
|
||||
BasalData retval = basalDataTable.get(time);
|
||||
if (retval == null) {
|
||||
retval = new BasalData();
|
||||
TemporaryBasal tb = MainApp.getConfigBuilder().getTempBasalFromHistory(time);
|
||||
retval.basal = MainApp.getConfigBuilder().getProfile(time).getBasal(time);
|
||||
Profile profile = MainApp.getConfigBuilder().getProfile(time);
|
||||
TemporaryBasal tb = TreatmentsPlugin.getPlugin().getTempBasalFromHistory(time);
|
||||
retval.basal = profile.getBasal(time);
|
||||
if (tb != null) {
|
||||
retval.isTempBasalRunning = true;
|
||||
retval.tempBasalAbsolute = tb.tempBasalConvertedToAbsolute(time);
|
||||
retval.tempBasalAbsolute = tb.tempBasalConvertedToAbsolute(time, profile);
|
||||
} else {
|
||||
retval.isTempBasalRunning = false;
|
||||
retval.tempBasalAbsolute = retval.basal;
|
||||
|
@ -392,7 +374,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
|||
}
|
||||
|
||||
@Nullable
|
||||
public static AutosensData getAutosensData(long time) {
|
||||
public AutosensData getAutosensData(long time) {
|
||||
synchronized (dataLock) {
|
||||
long now = System.currentTimeMillis();
|
||||
if (time > now)
|
||||
|
@ -417,20 +399,47 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
|||
}
|
||||
|
||||
@Nullable
|
||||
public static AutosensData getLastAutosensDataSynchronized(String reason) {
|
||||
public AutosensData getLastAutosensDataSynchronized(String reason) {
|
||||
synchronized (dataLock) {
|
||||
return getLastAutosensData(reason);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@NonNull
|
||||
public CobInfo getCobInfo(boolean _synchronized, String reason) {
|
||||
AutosensData autosensData = _synchronized ? getLastAutosensDataSynchronized(reason) : getLastAutosensData(reason);
|
||||
Double displayCob = null;
|
||||
double futureCarbs = 0;
|
||||
long now = now();
|
||||
List<Treatment> treatments = TreatmentsPlugin.getPlugin().getTreatmentsFromHistory();
|
||||
|
||||
if (autosensData != null) {
|
||||
displayCob = autosensData.cob;
|
||||
for (Treatment treatment : treatments) {
|
||||
if (!treatment.isValid) continue;
|
||||
if (IobCobCalculatorPlugin.roundUpTime(treatment.date) > IobCobCalculatorPlugin.roundUpTime(autosensData.time)
|
||||
&& treatment.date <= now && treatment.carbs > 0) {
|
||||
displayCob += treatment.carbs;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Treatment treatment : treatments) {
|
||||
if (!treatment.isValid) continue;
|
||||
if (treatment.date > now && treatment.carbs > 0) {
|
||||
futureCarbs += treatment.carbs;
|
||||
}
|
||||
}
|
||||
return new CobInfo(displayCob, futureCarbs);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static AutosensData getLastAutosensData(String reason) {
|
||||
public AutosensData getLastAutosensData(String reason) {
|
||||
if (autosensDataTable.size() < 1) {
|
||||
log.debug("AUTOSENSDATA null: autosensDataTable empty (" + reason + ")");
|
||||
return null;
|
||||
}
|
||||
AutosensData data = null;
|
||||
AutosensData data;
|
||||
try {
|
||||
data = autosensDataTable.valueAt(autosensDataTable.size() - 1);
|
||||
} catch (Exception e) {
|
||||
|
@ -444,14 +453,11 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
|||
log.debug("AUTOSENSDATA null: data is old (" + reason + ") size()=" + autosensDataTable.size() + " lastdata=" + DateUtil.dateAndTimeString(data.time));
|
||||
return null;
|
||||
} else {
|
||||
if (data == null)
|
||||
log.debug("AUTOSENSDATA null: data == null (" + " " + reason + ") size()=" + autosensDataTable.size() + " lastdata=" + DateUtil.dateAndTimeString(data.time));
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
public static IobTotal[] calculateIobArrayInDia() {
|
||||
Profile profile = MainApp.getConfigBuilder().getProfile();
|
||||
public IobTotal[] calculateIobArrayInDia(Profile profile) {
|
||||
// predict IOB out to DIA plus 30m
|
||||
long time = System.currentTimeMillis();
|
||||
time = roundUpTime(time);
|
||||
|
@ -460,14 +466,30 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
|||
int pos = 0;
|
||||
for (int i = 0; i < len; i++) {
|
||||
long t = time + i * 5 * 60000;
|
||||
IobTotal iob = calculateFromTreatmentsAndTempsSynchronized(t);
|
||||
IobTotal iob = calculateFromTreatmentsAndTempsSynchronized(t, profile);
|
||||
array[pos] = iob;
|
||||
pos++;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
public static AutosensResult detectSensitivityWithLock(long fromTime, long toTime) {
|
||||
public IobTotal[] calculateIobArrayForSMB(Profile profile) {
|
||||
// predict IOB out to DIA plus 30m
|
||||
long time = System.currentTimeMillis();
|
||||
time = roundUpTime(time);
|
||||
int len = (4 * 60) / 5;
|
||||
IobTotal[] array = new IobTotal[len];
|
||||
int pos = 0;
|
||||
for (int i = 0; i < len; i++) {
|
||||
long t = time + i * 5 * 60000;
|
||||
IobTotal iob = calculateFromTreatmentsAndTempsSynchronized(t, profile);
|
||||
array[pos] = iob;
|
||||
pos++;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
public AutosensResult detectSensitivityWithLock(long fromTime, long toTime) {
|
||||
synchronized (dataLock) {
|
||||
return detectSensitivity(fromTime, toTime);
|
||||
}
|
||||
|
@ -486,14 +508,24 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
|||
}
|
||||
|
||||
@Subscribe
|
||||
@SuppressWarnings("unused")
|
||||
public void onEventAppInitialized(EventAppInitialized ev) {
|
||||
runCalculation("onEventAppInitialized", true);
|
||||
if (this != getPlugin()) {
|
||||
log.debug("Ignoring event for non default instance");
|
||||
return;
|
||||
}
|
||||
runCalculation("onEventAppInitialized", System.currentTimeMillis(), true, ev);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
@SuppressWarnings("unused")
|
||||
public void onEventNewBG(EventNewBG ev) {
|
||||
if (this != getPlugin()) {
|
||||
log.debug("Ignoring event for non default instance");
|
||||
return;
|
||||
}
|
||||
stopCalculation("onEventNewBG");
|
||||
runCalculation("onEventNewBG", true);
|
||||
runCalculation("onEventNewBG", System.currentTimeMillis(), true, ev);
|
||||
}
|
||||
|
||||
private void stopCalculation(String from) {
|
||||
|
@ -507,16 +539,20 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
|||
}
|
||||
}
|
||||
|
||||
private void runCalculation(String from, boolean bgDataReload) {
|
||||
public void runCalculation(String from, long start, boolean bgDataReload, Event cause) {
|
||||
log.debug("Starting calculation thread: " + from);
|
||||
if (thread == null || thread.getState() == Thread.State.TERMINATED) {
|
||||
thread = new IobCobThread(this, from, bgDataReload);
|
||||
thread = new IobCobThread(this, from, start, bgDataReload, cause);
|
||||
thread.start();
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onNewProfile(EventNewBasalProfile ev) {
|
||||
if (this != getPlugin()) {
|
||||
log.debug("Ignoring event for non default instance");
|
||||
return;
|
||||
}
|
||||
if (MainApp.getConfigBuilder() == null)
|
||||
return; // app still initializing
|
||||
Profile profile = MainApp.getConfigBuilder().getProfile();
|
||||
|
@ -532,14 +568,20 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
|||
iobTable = new LongSparseArray<>();
|
||||
autosensDataTable = new LongSparseArray<>();
|
||||
}
|
||||
runCalculation("onNewProfile", false);
|
||||
runCalculation("onNewProfile", System.currentTimeMillis(), false, ev);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onEventPreferenceChange(EventPreferenceChange ev) {
|
||||
if (this != getPlugin()) {
|
||||
log.debug("Ignoring event for non default instance");
|
||||
return;
|
||||
}
|
||||
if (ev.isChanged(R.string.key_openapsama_autosens_period) ||
|
||||
ev.isChanged(R.string.key_age) ||
|
||||
ev.isChanged(R.string.key_absorption_maxtime)
|
||||
ev.isChanged(R.string.key_absorption_maxtime) ||
|
||||
ev.isChanged(R.string.key_openapsama_min_5m_carbimpact) ||
|
||||
ev.isChanged(R.string.key_absorption_cutoff)
|
||||
) {
|
||||
stopCalculation("onEventPreferenceChange");
|
||||
synchronized (dataLock) {
|
||||
|
@ -547,24 +589,32 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
|||
iobTable = new LongSparseArray<>();
|
||||
autosensDataTable = new LongSparseArray<>();
|
||||
}
|
||||
runCalculation("onEventPreferenceChange", false);
|
||||
runCalculation("onEventPreferenceChange", System.currentTimeMillis(), false, ev);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onEventConfigBuilderChange(EventConfigBuilderChange ev) {
|
||||
if (this != getPlugin()) {
|
||||
log.debug("Ignoring event for non default instance");
|
||||
return;
|
||||
}
|
||||
stopCalculation("onEventConfigBuilderChange");
|
||||
synchronized (dataLock) {
|
||||
log.debug("Invalidating cached data because of configuration change. IOB: " + iobTable.size() + " Autosens: " + autosensDataTable.size() + " records");
|
||||
iobTable = new LongSparseArray<>();
|
||||
autosensDataTable = new LongSparseArray<>();
|
||||
}
|
||||
runCalculation("onEventConfigBuilderChange", false);
|
||||
runCalculation("onEventConfigBuilderChange", System.currentTimeMillis(), false, ev);
|
||||
}
|
||||
|
||||
// When historical data is changed (comming from NS etc) finished calculations after this date must be invalidated
|
||||
@Subscribe
|
||||
public void onEventNewHistoryData(EventNewHistoryData ev) {
|
||||
if (this != getPlugin()) {
|
||||
log.debug("Ignoring event for non default instance");
|
||||
return;
|
||||
}
|
||||
//log.debug("Locking onNewHistoryData");
|
||||
stopCalculation("onEventNewHistoryData");
|
||||
synchronized (dataLock) {
|
||||
|
@ -599,10 +649,18 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
|||
}
|
||||
}
|
||||
}
|
||||
runCalculation("onEventNewHistoryData", false);
|
||||
runCalculation("onEventNewHistoryData", System.currentTimeMillis(), false, ev);
|
||||
//log.debug("Releasing onNewHistoryData");
|
||||
}
|
||||
|
||||
public void clearCache() {
|
||||
synchronized (dataLock) {
|
||||
log.debug("Clearing cached data.");
|
||||
iobTable = new LongSparseArray<>();
|
||||
autosensDataTable = new LongSparseArray<>();
|
||||
}
|
||||
}
|
||||
|
||||
// From https://gist.github.com/IceCreamYou/6ffa1b18c4c8f6aeaad2
|
||||
// Returns the value at a given percentile in a sorted numeric array.
|
||||
// "Linear interpolation between closest ranks" method
|
||||
|
|
|
@ -4,6 +4,8 @@ import android.content.Context;
|
|||
import android.os.PowerManager;
|
||||
import android.support.v4.util.LongSparseArray;
|
||||
|
||||
import com.crashlytics.android.answers.CustomEvent;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -11,39 +13,52 @@ import java.util.ArrayList;
|
|||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import info.nightscout.androidaps.BuildConfig;
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.Constants;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.data.IobTotal;
|
||||
import info.nightscout.androidaps.data.Profile;
|
||||
import info.nightscout.androidaps.db.BgReading;
|
||||
import info.nightscout.androidaps.db.Treatment;
|
||||
import info.nightscout.androidaps.events.Event;
|
||||
import info.nightscout.androidaps.interfaces.PluginType;
|
||||
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventAutosensCalculationFinished;
|
||||
import info.nightscout.androidaps.queue.QueueThread;
|
||||
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventIobCalculationProgress;
|
||||
import info.nightscout.androidaps.plugins.OpenAPSSMB.SMBDefaults;
|
||||
import info.nightscout.androidaps.plugins.SensitivityAAPS.SensitivityAAPSPlugin;
|
||||
import info.nightscout.androidaps.plugins.SensitivityWeightedAverage.SensitivityWeightedAveragePlugin;
|
||||
import info.nightscout.androidaps.plugins.Treatments.Treatment;
|
||||
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
|
||||
import info.nightscout.utils.DateUtil;
|
||||
import info.nightscout.utils.FabricPrivacy;
|
||||
import info.nightscout.utils.SP;
|
||||
|
||||
import static info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin.getBucketedData;
|
||||
import static info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin.oldestDataAvailable;
|
||||
import static info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin.roundUpTime;
|
||||
import static info.nightscout.utils.DateUtil.now;
|
||||
|
||||
/**
|
||||
* Created by mike on 23.01.2018.
|
||||
*/
|
||||
|
||||
public class IobCobThread extends Thread {
|
||||
private static Logger log = LoggerFactory.getLogger(QueueThread.class);
|
||||
private static Logger log = LoggerFactory.getLogger(IobCobThread.class);
|
||||
private final Event cause;
|
||||
|
||||
private IobCobCalculatorPlugin iobCobCalculatorPlugin;
|
||||
private boolean bgDataReload;
|
||||
private String from;
|
||||
private long start;
|
||||
|
||||
private PowerManager.WakeLock mWakeLock;
|
||||
|
||||
public IobCobThread(IobCobCalculatorPlugin plugin, String from, boolean bgDataReload) {
|
||||
public IobCobThread(IobCobCalculatorPlugin plugin, String from, long start, boolean bgDataReload, Event cause) {
|
||||
super();
|
||||
|
||||
this.iobCobCalculatorPlugin = plugin;
|
||||
this.bgDataReload = bgDataReload;
|
||||
this.from = from;
|
||||
this.cause = cause;
|
||||
this.start = start;
|
||||
|
||||
PowerManager powerManager = (PowerManager) MainApp.instance().getApplicationContext().getSystemService(Context.POWER_SERVICE);
|
||||
mWakeLock = powerManager.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "iobCobThread");
|
||||
|
@ -57,34 +72,35 @@ public class IobCobThread extends Thread {
|
|||
log.debug("Aborting calculation thread (ConfigBuilder not ready): " + from);
|
||||
return; // app still initializing
|
||||
}
|
||||
if (MainApp.getConfigBuilder().getProfile() == null) {
|
||||
if (!MainApp.getConfigBuilder().isProfileValid("IobCobThread")) {
|
||||
log.debug("Aborting calculation thread (No profile): " + from);
|
||||
return; // app still initializing
|
||||
}
|
||||
//log.debug("Locking calculateSensitivityData");
|
||||
|
||||
Object dataLock = iobCobCalculatorPlugin.dataLock;
|
||||
long oldestTimeWithData = iobCobCalculatorPlugin.oldestDataAvailable();
|
||||
|
||||
long oldestTimeWithData = oldestDataAvailable();
|
||||
|
||||
synchronized (dataLock) {
|
||||
synchronized (iobCobCalculatorPlugin.dataLock) {
|
||||
if (bgDataReload) {
|
||||
iobCobCalculatorPlugin.loadBgData();
|
||||
iobCobCalculatorPlugin.loadBgData(start);
|
||||
iobCobCalculatorPlugin.createBucketedData();
|
||||
}
|
||||
List<BgReading> bucketed_data = getBucketedData();
|
||||
LongSparseArray<AutosensData> autosensDataTable = iobCobCalculatorPlugin.getAutosensDataTable();
|
||||
List<BgReading> bucketed_data = iobCobCalculatorPlugin.getBucketedData();
|
||||
LongSparseArray<AutosensData> autosensDataTable = IobCobCalculatorPlugin.getPlugin().getAutosensDataTable();
|
||||
|
||||
if (bucketed_data == null || bucketed_data.size() < 3) {
|
||||
log.debug("Aborting calculation thread (No bucketed data available): " + from);
|
||||
return;
|
||||
}
|
||||
|
||||
long prevDataTime = roundUpTime(bucketed_data.get(bucketed_data.size() - 3).date);
|
||||
long prevDataTime = IobCobCalculatorPlugin.roundUpTime(bucketed_data.get(bucketed_data.size() - 3).date);
|
||||
log.debug("Prev data time: " + new Date(prevDataTime).toLocaleString());
|
||||
AutosensData previous = autosensDataTable.get(prevDataTime);
|
||||
// start from oldest to be able sub cob
|
||||
for (int i = bucketed_data.size() - 4; i >= 0; i--) {
|
||||
String progress = i + (MainApp.isDev() ? " (" + from + ")" : "");
|
||||
MainApp.bus().post(new EventIobCalculationProgress(progress));
|
||||
|
||||
if (iobCobCalculatorPlugin.stopCalculationTrigger) {
|
||||
iobCobCalculatorPlugin.stopCalculationTrigger = false;
|
||||
log.debug("Aborting calculation thread (trigger): " + from);
|
||||
|
@ -92,10 +108,9 @@ public class IobCobThread extends Thread {
|
|||
}
|
||||
// check if data already exists
|
||||
long bgTime = bucketed_data.get(i).date;
|
||||
bgTime = roundUpTime(bgTime);
|
||||
if (bgTime > System.currentTimeMillis())
|
||||
bgTime = IobCobCalculatorPlugin.roundUpTime(bgTime);
|
||||
if (bgTime > IobCobCalculatorPlugin.roundUpTime(now()))
|
||||
continue;
|
||||
Profile profile = MainApp.getConfigBuilder().getProfile(bgTime);
|
||||
|
||||
AutosensData existing;
|
||||
if ((existing = autosensDataTable.get(bgTime)) != null) {
|
||||
|
@ -103,16 +118,12 @@ public class IobCobThread extends Thread {
|
|||
continue;
|
||||
}
|
||||
|
||||
Profile profile = MainApp.getConfigBuilder().getProfile(bgTime);
|
||||
if (profile == null) {
|
||||
log.debug("Aborting calculation thread (no profile): " + from);
|
||||
return; // profile not set yet
|
||||
}
|
||||
|
||||
if (profile.getIsf(bgTime) == null) {
|
||||
log.debug("Aborting calculation thread (no ISF): " + from);
|
||||
return; // profile not set yet
|
||||
}
|
||||
|
||||
if (Config.logAutosensData)
|
||||
log.debug("Processing calculation thread: " + from + " (" + i + "/" + bucketed_data.size() + ")");
|
||||
|
||||
|
@ -135,13 +146,59 @@ public class IobCobThread extends Thread {
|
|||
continue;
|
||||
}
|
||||
delta = (bg - bucketed_data.get(i + 1).value);
|
||||
avgDelta = (bg - bucketed_data.get(i + 3).value) / 3;
|
||||
|
||||
IobTotal iob = iobCobCalculatorPlugin.calculateFromTreatmentsAndTemps(bgTime);
|
||||
IobTotal iob = iobCobCalculatorPlugin.calculateFromTreatmentsAndTemps(bgTime, profile);
|
||||
|
||||
double bgi = -iob.activity * sens * 5;
|
||||
double deviation = delta - bgi;
|
||||
double avgDeviation = Math.round((avgDelta - bgi) * 1000) / 1000;
|
||||
|
||||
List<Treatment> recentTreatments = MainApp.getConfigBuilder().getTreatments5MinBackFromHistory(bgTime);
|
||||
double slopeFromMaxDeviation = 0;
|
||||
double slopeFromMinDeviation = 999;
|
||||
double maxDeviation = 0;
|
||||
double minDeviation = 999;
|
||||
|
||||
// https://github.com/openaps/oref0/blob/master/lib/determine-basal/cob-autosens.js#L169
|
||||
if (i < bucketed_data.size() - 16) { // we need 1h of data to calculate minDeviationSlope
|
||||
long hourago = bgTime + 10 * 1000 - 60 * 60 * 1000L;
|
||||
AutosensData hourAgoData = IobCobCalculatorPlugin.getPlugin().getAutosensData(hourago);
|
||||
if (hourAgoData != null) {
|
||||
int initialIndex = autosensDataTable.indexOfKey(hourAgoData.time);
|
||||
if (Config.logAutosensData)
|
||||
log.debug(">>>>> bucketed_data.size()=" + bucketed_data.size() + " i=" + i + "hourAgoData=" + hourAgoData.toString());
|
||||
int past = 1;
|
||||
try {
|
||||
for (; past < 12; past++) {
|
||||
AutosensData ad = autosensDataTable.valueAt(initialIndex + past);
|
||||
double deviationSlope = (ad.avgDeviation - avgDeviation) / (ad.time - bgTime) * 1000 * 60 * 5;
|
||||
if (ad.avgDeviation > maxDeviation) {
|
||||
slopeFromMaxDeviation = Math.min(0, deviationSlope);
|
||||
maxDeviation = ad.avgDeviation;
|
||||
}
|
||||
if (ad.avgDeviation < minDeviation) {
|
||||
slopeFromMinDeviation = Math.max(0, deviationSlope);
|
||||
minDeviation = ad.avgDeviation;
|
||||
}
|
||||
|
||||
//if (Config.logAutosensData)
|
||||
// log.debug("Deviations: " + new Date(bgTime) + new Date(ad.time) + " avgDeviation=" + avgDeviation + " deviationSlope=" + deviationSlope + " slopeFromMaxDeviation=" + slopeFromMaxDeviation + " slopeFromMinDeviation=" + slopeFromMinDeviation);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("Unhandled exception", e);
|
||||
FabricPrivacy.logException(e);
|
||||
FabricPrivacy.getInstance().logCustom(new CustomEvent("CatchedError")
|
||||
.putCustomAttribute("buildversion", BuildConfig.BUILDVERSION)
|
||||
.putCustomAttribute("version", BuildConfig.VERSION)
|
||||
.putCustomAttribute("autosensDataTable", iobCobCalculatorPlugin.getAutosensDataTable().toString())
|
||||
.putCustomAttribute("for_data", ">>>>> bucketed_data.size()=" + bucketed_data.size() + " i=" + i + "hourAgoData=" + hourAgoData.toString())
|
||||
.putCustomAttribute("past", past)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<Treatment> recentTreatments = TreatmentsPlugin.getPlugin().getTreatments5MinBackFromHistory(bgTime);
|
||||
for (int ir = 0; ir < recentTreatments.size(); ir++) {
|
||||
autosensData.carbsFromBolus += recentTreatments.get(ir).carbs;
|
||||
autosensData.activeCarbsList.add(new AutosensData.CarbsInPast(recentTreatments.get(ir)));
|
||||
|
@ -152,24 +209,38 @@ public class IobCobThread extends Thread {
|
|||
if (previous != null && previous.cob > 0) {
|
||||
// calculate sum of min carb impact from all active treatments
|
||||
double totalMinCarbsImpact = 0d;
|
||||
for (int ii = 0; ii < autosensData.activeCarbsList.size(); ++ii) {
|
||||
AutosensData.CarbsInPast c = autosensData.activeCarbsList.get(ii);
|
||||
totalMinCarbsImpact += c.min5minCarbImpact;
|
||||
if (SensitivityAAPSPlugin.getPlugin().isEnabled(PluginType.SENSITIVITY) || SensitivityWeightedAveragePlugin.getPlugin().isEnabled(PluginType.SENSITIVITY)) {
|
||||
//when the impact depends on a max time, sum them up as smaller carb sizes make them smaller
|
||||
for (int ii = 0; ii < autosensData.activeCarbsList.size(); ++ii) {
|
||||
AutosensData.CarbsInPast c = autosensData.activeCarbsList.get(ii);
|
||||
totalMinCarbsImpact += c.min5minCarbImpact;
|
||||
}
|
||||
} else {
|
||||
//Oref sensitivity
|
||||
totalMinCarbsImpact = SP.getDouble(R.string.key_openapsama_min_5m_carbimpact, SMBDefaults.min_5m_carbimpact);
|
||||
}
|
||||
|
||||
// figure out how many carbs that represents
|
||||
// but always assume at least 3mg/dL/5m (default) absorption per active treatment
|
||||
double ci = Math.max(deviation, totalMinCarbsImpact);
|
||||
if (ci != deviation)
|
||||
autosensData.failoverToMinAbsorbtionRate = true;
|
||||
autosensData.absorbed = ci * profile.getIc(bgTime) / sens;
|
||||
// and add that to the running total carbsAbsorbed
|
||||
autosensData.cob = Math.max(previous.cob - autosensData.absorbed, 0d);
|
||||
autosensData.substractAbosorbedCarbs();
|
||||
autosensData.usedMinCarbsImpact = totalMinCarbsImpact;
|
||||
}
|
||||
autosensData.removeOldCarbs(bgTime);
|
||||
autosensData.cob += autosensData.carbsFromBolus;
|
||||
autosensData.deviation = deviation;
|
||||
autosensData.bgi = bgi;
|
||||
autosensData.delta = delta;
|
||||
autosensData.avgDelta = avgDelta;
|
||||
autosensData.avgDeviation = avgDeviation;
|
||||
autosensData.slopeFromMaxDeviation = slopeFromMaxDeviation;
|
||||
autosensData.slopeFromMinDeviation = slopeFromMinDeviation;
|
||||
|
||||
|
||||
// calculate autosens only without COB
|
||||
if (autosensData.cob <= 0) {
|
||||
|
@ -191,15 +262,18 @@ public class IobCobThread extends Thread {
|
|||
|
||||
previous = autosensData;
|
||||
autosensDataTable.put(bgTime, autosensData);
|
||||
if (Config.logAutosensData)
|
||||
log.debug("Running detectSensitivity from: " + DateUtil.dateAndTimeString(oldestTimeWithData) + " to: " + DateUtil.dateAndTimeString(bgTime));
|
||||
autosensData.autosensRatio = iobCobCalculatorPlugin.detectSensitivity(oldestTimeWithData, bgTime).ratio;
|
||||
if (Config.logAutosensData)
|
||||
log.debug(autosensData.log(bgTime));
|
||||
log.debug(autosensData.toString());
|
||||
}
|
||||
}
|
||||
MainApp.bus().post(new EventAutosensCalculationFinished());
|
||||
MainApp.bus().post(new EventAutosensCalculationFinished(cause));
|
||||
log.debug("Finishing calculation thread: " + from);
|
||||
} finally {
|
||||
mWakeLock.release();
|
||||
MainApp.bus().post(new EventIobCalculationProgress(""));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package info.nightscout.androidaps.plugins.IobCobCalculator.events;
|
||||
|
||||
import info.nightscout.androidaps.events.Event;
|
||||
import info.nightscout.androidaps.events.EventLoop;
|
||||
|
||||
/**
|
||||
|
@ -7,4 +8,9 @@ import info.nightscout.androidaps.events.EventLoop;
|
|||
*/
|
||||
|
||||
public class EventAutosensCalculationFinished extends EventLoop {
|
||||
public Event cause;
|
||||
|
||||
public EventAutosensCalculationFinished(Event cause) {
|
||||
this.cause = cause;
|
||||
}
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue