Merge pull request #1 from MilosKozak/dev

Merge dev from origin
This commit is contained in:
Andy Rozman 2018-04-30 23:06:33 +01:00 committed by GitHub
commit 904a3d5028
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
446 changed files with 19713 additions and 10760 deletions

3
.gitignore vendored
View file

@ -8,3 +8,6 @@
build/ build/
.idea/ .idea/
app/src/main/jniLibs app/src/main/jniLibs
full/
debug/
release/

View file

@ -2,7 +2,7 @@ language: android
jdk: oraclejdk8 jdk: oraclejdk8
env: env:
matrix: matrix:
- ANDROID_TARGET=android-23 ANDROID_ABI=x86 - ANDROID_TARGET=android-23 ANDROID_ABI=x86 org.gradle.jvmargs=-XX:-OmitStackTraceInFastThrow
android: android:
components: components:
- platform-tools - platform-tools
@ -18,7 +18,17 @@ before_install:
script: script:
# Unit Test # Unit Test
- ./gradlew test jacocoTestReport - ./gradlew -Pcoverage testFullDebugUnitTest jacocoTestFullDebugUnitTestReport
after_success: 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
View file

@ -1 +0,0 @@
/build

View file

@ -15,15 +15,17 @@ apply plugin: "jacoco-android"
apply plugin: 'com.jakewharton.butterknife' apply plugin: 'com.jakewharton.butterknife'
ext { ext {
supportLibraryVersion = "27.0.2" supportLibraryVersion = "27.1.0"
ormLiteVersion = "4.46" ormLiteVersion = "4.46"
powermockVersion = "1.7.3" powermockVersion = "1.7.3"
dexmakerVersion = "1.2" dexmakerVersion = "1.2"
butterknifeVersion = "8.8.1"
} }
repositories { repositories {
maven { url 'https://maven.fabric.io/public' } maven { url 'https://maven.fabric.io/public' }
jcenter { url "https://jcenter.bintray.com/" }
} }
def generateGitBuild = { -> def generateGitBuild = { ->
@ -47,19 +49,24 @@ def generateGitBuild = { ->
return stringBuilder.toString() return stringBuilder.toString()
} }
tasks.matching {it instanceof Test}.all {
testLogging.events = ["failed", "skipped", "started"]
testLogging.exceptionFormat = "full"
}
android { android {
compileSdkVersion 27 compileSdkVersion 27
buildToolsVersion "${supportLibraryVersion}"
defaultConfig { defaultConfig {
applicationId "info.nightscout.androidaps" applicationId "info.nightscout.androidaps"
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 23 targetSdkVersion 25
multiDexEnabled true multiDexEnabled true
versionCode 1500 versionCode 1500
version "1.59-dev" version "1.60e-dev"
buildConfigField "String", "VERSION", '"' + version + '"' buildConfigField "String", "VERSION", '"' + version + '"'
buildConfigField "String", "BUILDVERSION", generateGitBuild() buildConfigField "String", "BUILDVERSION", generateGitBuild()
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
ndk { ndk {
moduleName "BleCommandUtil" moduleName "BleCommandUtil"
@ -69,7 +76,7 @@ android {
// TODO remove once wear dependency com.google.android.gms:play-services-wearable:7.3.0 // 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 // has been upgraded (requiring significant code changes), which currently fails release
// build with a deprecation warning // build with a deprecation warning
//abortOnError false abortOnError false
// (disabled entirely to avoid reports on the error, which would still be displayed // (disabled entirely to avoid reports on the error, which would still be displayed
// and it's easy to overlook that it's ignored) // and it's easy to overlook that it's ignored)
checkReleaseBuilds false checkReleaseBuilds false
@ -82,7 +89,7 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
} }
debug { debug {
testCoverageEnabled true testCoverageEnabled (project.hasProperty('coverage') ? true : false)
} }
} }
productFlavors { productFlavors {
@ -97,21 +104,6 @@ android {
buildConfigField "boolean", "APS", "true" buildConfigField "boolean", "APS", "true"
buildConfigField "boolean", "PUMPDRIVERS", "true" buildConfigField "boolean", "PUMPDRIVERS", "true"
buildConfigField "boolean", "NSCLIENTOLNY", "false" 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", "G5UPLOADER", "false"
buildConfigField "boolean", "PUMPCONTROL", "false" buildConfigField "boolean", "PUMPCONTROL", "false"
} }
@ -125,7 +117,6 @@ android {
buildConfigField "boolean", "APS", "false" buildConfigField "boolean", "APS", "false"
buildConfigField "boolean", "PUMPDRIVERS", "true" buildConfigField "boolean", "PUMPDRIVERS", "true"
buildConfigField "boolean", "NSCLIENTOLNY", "false" buildConfigField "boolean", "NSCLIENTOLNY", "false"
buildConfigField "boolean", "CLOSEDLOOP", "false"
buildConfigField "boolean", "G5UPLOADER", "false" buildConfigField "boolean", "G5UPLOADER", "false"
buildConfigField "boolean", "PUMPCONTROL", "true" buildConfigField "boolean", "PUMPCONTROL", "true"
} }
@ -139,7 +130,6 @@ android {
buildConfigField "boolean", "APS", "false" buildConfigField "boolean", "APS", "false"
buildConfigField "boolean", "PUMPDRIVERS", "false" buildConfigField "boolean", "PUMPDRIVERS", "false"
buildConfigField "boolean", "NSCLIENTOLNY", "true" buildConfigField "boolean", "NSCLIENTOLNY", "true"
buildConfigField "boolean", "CLOSEDLOOP", "false"
buildConfigField "boolean", "G5UPLOADER", "false" buildConfigField "boolean", "G5UPLOADER", "false"
buildConfigField "boolean", "PUMPCONTROL", "false" buildConfigField "boolean", "PUMPCONTROL", "false"
} }
@ -153,7 +143,6 @@ android {
buildConfigField "boolean", "APS", "false" buildConfigField "boolean", "APS", "false"
buildConfigField "boolean", "PUMPDRIVERS", "false" buildConfigField "boolean", "PUMPDRIVERS", "false"
buildConfigField "boolean", "NSCLIENTOLNY", "false" buildConfigField "boolean", "NSCLIENTOLNY", "false"
buildConfigField "boolean", "CLOSEDLOOP", "false"
buildConfigField "boolean", "G5UPLOADER", "true" buildConfigField "boolean", "G5UPLOADER", "true"
buildConfigField "boolean", "PUMPCONTROL", "false" buildConfigField "boolean", "PUMPCONTROL", "false"
} }
@ -165,6 +154,7 @@ android {
testOptions { testOptions {
unitTests.returnDefaultValues = true unitTests.returnDefaultValues = true
unitTests.includeAndroidResources = true
} }
} }
@ -177,75 +167,82 @@ allprojects {
} }
} }
configurations {
libs
}
dependencies { dependencies {
wearApp project(':wear') wearApp project(':wear')
compile fileTree(include: ['*.jar'], dir: 'libs') implementation fileTree(include: ['*.jar'], dir: 'libs')
compile("com.crashlytics.sdk.android:crashlytics:2.6.7@aar") { implementation("com.crashlytics.sdk.android:crashlytics:2.6.7@aar") {
transitive = true; transitive = true;
} }
compile("com.crashlytics.sdk.android:answers:1.3.12@aar") { implementation("com.crashlytics.sdk.android:answers:1.3.12@aar") {
transitive = true; transitive = true;
} }
compile 'MilosKozak:danars-support-lib:master@zip' libs "MilosKozak:danars-support-lib:master@zip"
compile "com.android.support:appcompat-v7:${supportLibraryVersion}" implementation "com.android.support:appcompat-v7:${supportLibraryVersion}"
compile "com.android.support:support-v4:${supportLibraryVersion}" implementation "com.android.support:support-v4:${supportLibraryVersion}"
compile "com.android.support:cardview-v7:${supportLibraryVersion}" implementation "com.android.support:cardview-v7:${supportLibraryVersion}"
compile "com.android.support:recyclerview-v7:${supportLibraryVersion}" implementation "com.android.support:recyclerview-v7:${supportLibraryVersion}"
compile "com.android.support:gridlayout-v7:${supportLibraryVersion}" implementation "com.android.support:gridlayout-v7:${supportLibraryVersion}"
compile "com.android.support:design:${supportLibraryVersion}" implementation "com.android.support:design:${supportLibraryVersion}"
compile "com.android.support:percent:${supportLibraryVersion}" implementation "com.android.support:percent:${supportLibraryVersion}"
compile "com.wdullaer:materialdatetimepicker:2.3.0" implementation "com.wdullaer:materialdatetimepicker:2.3.0"
compile 'com.android.support.constraint:constraint-layout:1.0.2' implementation 'com.android.support.constraint:constraint-layout:1.0.2'
compile "com.squareup:otto:1.3.7" implementation "com.squareup:otto:1.3.7"
compile "com.j256.ormlite:ormlite-core:${ormLiteVersion}" implementation "com.j256.ormlite:ormlite-core:${ormLiteVersion}"
compile "com.j256.ormlite:ormlite-android:${ormLiteVersion}" implementation "com.j256.ormlite:ormlite-android:${ormLiteVersion}"
compile("com.github.tony19:logback-android-classic:1.1.1-6") { implementation("com.github.tony19:logback-android-classic:1.1.1-6") {
exclude group: "com.google.android", module: "android" exclude group: "com.google.android", module: "android"
} }
compile "org.apache.commons:commons-lang3:3.6" implementation "org.apache.commons:commons-lang3:3.6"
compile "org.slf4j:slf4j-api:1.7.12" implementation "org.slf4j:slf4j-api:1.7.12"
compile "com.jjoe64:graphview:4.0.1" implementation "com.jjoe64:graphview:4.0.1"
compile "com.joanzapata.iconify:android-iconify-fontawesome:2.1.1" implementation "com.joanzapata.iconify:android-iconify-fontawesome:2.1.1"
compile "com.google.android.gms:play-services-wearable:7.5.0" implementation "com.google.android.gms:play-services-wearable:7.5.0"
compile(name: "android-edittext-validator-v1.3.4-mod", ext: "aar") implementation(name: "android-edittext-validator-v1.3.4-mod", ext: "aar")
compile(name: "sightparser-release", ext: "aar") implementation(name: "sightparser-release", ext: "aar")
compile("com.google.android:flexbox:0.3.0") { implementation("com.google.android:flexbox:0.3.0") {
exclude group: "com.android.support" exclude group: "com.android.support"
} }
compile("io.socket:socket.io-client:0.8.3") { implementation("io.socket:socket.io-client:0.8.3") {
// excluding org.json which is provided by Android // excluding org.json which is provided by Android
exclude group: "org.json", module: "json" exclude group: "org.json", module: "json"
} }
compile "com.google.code.gson:gson:2.7" implementation "com.google.code.gson:gson:2.7"
compile "com.google.guava:guava:20.0" 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"
compile 'org.mozilla:rhino:1.7.7.2' implementation 'org.mozilla:rhino:1.7.7.2'
api "com.jakewharton:butterknife:8.8.1" implementation "com.jakewharton:butterknife:${butterknifeVersion}"
annotationProcessor "com.jakewharton:butterknife-compiler:8.8.1" annotationProcessor "com.jakewharton:butterknife-compiler:${butterknifeVersion}"
testCompile "junit:junit:4.12" testImplementation "junit:junit:4.12"
testCompile "org.json:json:20140107" testImplementation "org.json:json:20140107"
testCompile "org.mockito:mockito-core:2.7.22" testImplementation "org.mockito:mockito-core:2.7.22"
testCompile "org.powermock:powermock-api-mockito2:${powermockVersion}" testImplementation "org.powermock:powermock-api-mockito2:${powermockVersion}"
testCompile "org.powermock:powermock-module-junit4-rule-agent:${powermockVersion}" testImplementation "org.powermock:powermock-module-junit4-rule-agent:${powermockVersion}"
testCompile "org.powermock:powermock-module-junit4-rule:${powermockVersion}" testImplementation "org.powermock:powermock-module-junit4-rule:${powermockVersion}"
testCompile "org.powermock:powermock-module-junit4:${powermockVersion}" testImplementation "org.powermock:powermock-module-junit4:${powermockVersion}"
testCompile "joda-time:joda-time:2.9.4.2" testImplementation "joda-time:joda-time:2.9.4.2"
testCompile "com.google.truth:truth:0.39" testImplementation "com.google.truth:truth:0.39"
testImplementation 'org.robolectric:robolectric:3.8'
testImplementation "org.skyscreamer:jsonassert:1.5.0"
androidTestCompile "org.mockito:mockito-core:2.7.22" androidTestImplementation "org.mockito:mockito-core:2.7.22"
androidTestCompile "com.google.dexmaker:dexmaker:${dexmakerVersion}" androidTestImplementation "com.google.dexmaker:dexmaker:${dexmakerVersion}"
androidTestCompile "com.google.dexmaker:dexmaker-mockito:${dexmakerVersion}" androidTestImplementation "com.google.dexmaker:dexmaker-mockito:${dexmakerVersion}"
} }
task unzip(type: Copy) { task unzip(type: Copy) {
def zipPath = configurations.compile.find {it.name.startsWith("danars") } def zipPath = configurations.libs.find {it.name.startsWith("danars") }
def zipFile = file(zipPath) def zipFile = file(zipPath)
def outputDir = file("${buildDir}/unpacked/dist") def outputDir = file("${buildDir}/unpacked/dist")

Binary file not shown.

View file

@ -15,9 +15,11 @@
<uses-permission android:name="android.permission.SEND_MMS" /> <uses-permission android:name="android.permission.SEND_MMS" />
<uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="com.google.android.permission.PROVIDE_BACKGROUND" /> <uses-permission android:name="com.google.android.permission.PROVIDE_BACKGROUND" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <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" /> <uses-permission-sdk-23 android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
@ -47,7 +49,7 @@
android:theme="@style/Theme.AppCompat.Translucent" /> android:theme="@style/Theme.AppCompat.Translucent" />
<activity android:name=".AgreementActivity" /> <activity android:name=".AgreementActivity" />
<activity android:name=".plugins.PumpDanaR.activities.DanaRHistoryActivity" /> <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"> <activity android:name=".plugins.Overview.activities.QuickWizardListActivity">
<intent-filter> <intent-filter>
<action android:name="info.nightscout.androidaps.plugins.Overview.activities.QuickWizardListActivity" /> <action android:name="info.nightscout.androidaps.plugins.Overview.activities.QuickWizardListActivity" />
@ -111,6 +113,14 @@
</intent-filter> </intent-filter>
</receiver> </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 processing incomming data -->
<service <service
android:name=".Services.DataService" android:name=".Services.DataService"

View file

@ -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();
}

View file

@ -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();
}

View file

@ -0,0 +1,3 @@
package org.monkey.d.ruffy.ruffy.driver.display;
parcelable Menu;

View file

@ -0,0 +1 @@
//b916a900c0899ef58ad58c7427d1c30d3c8731f4

View file

@ -1,6 +1,6 @@
<configuration> <configuration>
<!-- Create a file appender for a log in the application's data directory --> <!-- 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"> <appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${EXT_FILES_DIR}/AndroidAPS.log</file> <file>${EXT_FILES_DIR}/AndroidAPS.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">

View file

@ -13,10 +13,9 @@ public class Config {
public static final boolean G5UPLOADER = BuildConfig.G5UPLOADER; public static final boolean G5UPLOADER = BuildConfig.G5UPLOADER;
public static final boolean PUMPCONTROL = BuildConfig.PUMPCONTROL; 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 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 MDI = !BuildConfig.NSCLIENTOLNY && !BuildConfig.G5UPLOADER;
public static final boolean OTHERPROFILES = !BuildConfig.NSCLIENTOLNY && !BuildConfig.G5UPLOADER; public static final boolean OTHERPROFILES = !BuildConfig.NSCLIENTOLNY && !BuildConfig.G5UPLOADER;
public static final boolean SAFETY = !BuildConfig.NSCLIENTOLNY && !BuildConfig.G5UPLOADER; public static final boolean SAFETY = !BuildConfig.NSCLIENTOLNY && !BuildConfig.G5UPLOADER;
@ -24,8 +23,6 @@ public class Config {
public static final boolean SMSCOMMUNICATORENABLED = !BuildConfig.NSCLIENTOLNY && !BuildConfig.G5UPLOADER; public static final boolean SMSCOMMUNICATORENABLED = !BuildConfig.NSCLIENTOLNY && !BuildConfig.G5UPLOADER;
public static final boolean displayDeviationSlope = false;
public static final boolean detailedLog = true; public static final boolean detailedLog = true;
public static final boolean logFunctionCalls = true; public static final boolean logFunctionCalls = true;
public static final boolean logIncommingData = true; public static final boolean logIncommingData = true;
@ -33,12 +30,12 @@ public class Config {
public static final boolean logPumpComm = true; public static final boolean logPumpComm = true;
public static final boolean logPrefsChange = true; public static final boolean logPrefsChange = true;
public static final boolean logConfigBuilder = true; public static final boolean logConfigBuilder = true;
public static final boolean logConstraintsChanges = true;
public static final boolean logNSUpload = true; public static final boolean logNSUpload = true;
public static final boolean logPumpActions = true; public static final boolean logPumpActions = true;
public static final boolean logCongigBuilderActions = true; public static final boolean logCongigBuilderActions = true;
public static final boolean logAutosensData = false; public static final boolean logAutosensData = false;
public static final boolean logEvents = false; public static final boolean logEvents = false;
public static final boolean logProfile = false;
// DanaR specific // DanaR specific
public static final boolean logDanaBTComm = true; public static final boolean logDanaBTComm = true;

View file

@ -1,6 +1,6 @@
package info.nightscout.androidaps; package info.nightscout.androidaps;
import com.j256.ormlite.stmt.query.In; import info.nightscout.utils.T;
/** /**
* Created by mike on 07.06.2016. * Created by mike on 07.06.2016.
@ -14,10 +14,11 @@ public class Constants {
public static final double defaultDIA = 3d; public static final double defaultDIA = 3d;
public static final double basalAbsoluteOnlyForCheckLimit = 10101010d; public static final Double REALLYHIGHBASALRATE = 1111111d;
public static final Integer basalPercentOnlyForCheckLimit = 10101010; public static final Integer REALLYHIGHPERCENTBASALRATE = 1111111;
public static final double bolusOnlyForCheckLimit = 10101010d; public static final double REALLYHIGHBOLUS = 1111111d;
public static final Integer carbsOnlyForCheckLimit = 10101010; public static final Integer REALLYHIGHCARBS = 1111111;
public static final double REALLYHIGHIOB = 1111111d;
public static final Integer notificationID = 556677; public static final Integer notificationID = 556677;
@ -40,11 +41,14 @@ public class Constants {
// Temp targets // Temp targets
public static final int defaultActivityTTDuration = 90; // min public static final int defaultActivityTTDuration = 90; // min
public static final double defaultActivityTTmgdl = 90d; public static final double defaultActivityTTmgdl = 140d;
public static final double defaultActivityTTmmol = 5d; public static final double defaultActivityTTmmol = 8d;
public static final int defaultEatingSoonTTDuration = 45; // min public static final int defaultEatingSoonTTDuration = 45; // min
public static final double defaultEatingSoonTTmgdl = 140d; public static final double defaultEatingSoonTTmgdl = 90d;
public static final double defaultEatingSoonTTmmol = 8d; 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 //NSClientInternal
public static final int MAX_LOG_LINES = 100; public static final int MAX_LOG_LINES = 100;
@ -55,8 +59,12 @@ public class Constants {
//Autosens //Autosens
public static final double DEVIATION_TO_BE_EQUAL = 2.0; public static final double DEVIATION_TO_BE_EQUAL = 2.0;
public static final double DEFAULT_MAX_ABSORPTION_TIME = 6.0;
// Pump // Pump
public static final int PUMP_MAX_CONNECTION_TIME_IN_SECONDS = 120 - 1; public static final int PUMP_MAX_CONNECTION_TIME_IN_SECONDS = 120 - 1;
public static final int MIN_WATCHDOG_INTERVAL_IN_SECONDS = 12 * 60; public static final int MIN_WATCHDOG_INTERVAL_IN_SECONDS = 12 * 60;
//SMS Communicator
public static final long SMS_CONFIRM_TIMEOUT = T.mins(5).msecs();
} }

View file

@ -2,11 +2,18 @@ package info.nightscout.androidaps;
import android.app.Activity; import android.app.Activity;
import android.os.Bundle; import android.os.Bundle;
import android.support.v4.content.res.ResourcesCompat;
import android.support.v7.app.AppCompatActivity; 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.view.View;
import android.widget.Button; import android.widget.Button;
import android.widget.CheckBox; import android.widget.ImageButton;
import android.widget.SeekBar; import android.widget.SeekBar;
import android.widget.TextView;
import com.jjoe64.graphview.GraphView; import com.jjoe64.graphview.GraphView;
import com.squareup.otto.Subscribe; import com.squareup.otto.Subscribe;
@ -26,6 +33,7 @@ import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin; import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin;
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventAutosensCalculationFinished; 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.OverviewPlugin;
import info.nightscout.androidaps.plugins.Overview.graphData.GraphData; import info.nightscout.androidaps.plugins.Overview.graphData.GraphData;
import info.nightscout.utils.DateUtil; import info.nightscout.utils.DateUtil;
@ -34,6 +42,13 @@ import info.nightscout.utils.SP;
public class HistoryBrowseActivity extends AppCompatActivity { public class HistoryBrowseActivity extends AppCompatActivity {
private static Logger log = LoggerFactory.getLogger(HistoryBrowseActivity.class); private static Logger log = LoggerFactory.getLogger(HistoryBrowseActivity.class);
ImageButton chartButton;
boolean showBasal = true;
boolean showIob, showCob, showDev, showRat, showDevslope;
@BindView(R.id.historybrowse_date) @BindView(R.id.historybrowse_date)
Button buttonDate; Button buttonDate;
@BindView(R.id.historybrowse_zoom) @BindView(R.id.historybrowse_zoom)
@ -44,19 +59,8 @@ public class HistoryBrowseActivity extends AppCompatActivity {
GraphView iobGraph; GraphView iobGraph;
@BindView(R.id.historybrowse_seekBar) @BindView(R.id.historybrowse_seekBar)
SeekBar seekBar; SeekBar seekBar;
@BindView(R.id.historybrowse_noprofile)
@BindView(R.id.overview_showprediction) TextView noProfile;
CheckBox showPredictionCheckbox;
@BindView(R.id.overview_showbasals)
CheckBox showBasalsCheckbox;
@BindView(R.id.overview_showiob)
CheckBox showIobCheckbox;
@BindView(R.id.overview_showcob)
CheckBox showCobCheckbox;
@BindView(R.id.overview_showdeviations)
CheckBox showDeviationsCheckbox;
@BindView(R.id.overview_showratios)
CheckBox showRatiosCheckbox;
private int rangeToDisplay = 24; // for graph private int rangeToDisplay = 24; // for graph
private long start; private long start;
@ -85,6 +89,8 @@ public class HistoryBrowseActivity extends AppCompatActivity {
iobGraph.getGridLabelRenderer().setLabelVerticalWidth(50); iobGraph.getGridLabelRenderer().setLabelVerticalWidth(50);
iobGraph.getGridLabelRenderer().setNumVerticalLabels(5); iobGraph.getGridLabelRenderer().setNumVerticalLabels(5);
setupChartMenu();
// set start of current day // set start of current day
Calendar calendar = Calendar.getInstance(); Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis()); calendar.setTimeInMillis(System.currentTimeMillis());
@ -162,15 +168,6 @@ public class HistoryBrowseActivity extends AppCompatActivity {
void onClickDate() { void onClickDate() {
} }
@OnClick({R.id.overview_showbasals, R.id.overview_showprediction, R.id.overview_showiob, R.id.overview_showcob, R.id.overview_showdeviations, R.id.overview_showratios})
void onClickDate(View view) {
//((CheckBox) view).toggle();
updateGUI("checkboxToggle");
iobCobCalculatorPlugin.clearCache();
iobCobCalculatorPlugin.runCalculation("onClickDate", start, true, eventCustomCalculationFinished);
}
@Subscribe @Subscribe
public void onStatusEvent(final EventAutosensCalculationFinished e) { public void onStatusEvent(final EventAutosensCalculationFinished e) {
Activity activity = this; Activity activity = this;
@ -188,6 +185,14 @@ public class HistoryBrowseActivity extends AppCompatActivity {
void updateGUI(String from) { void updateGUI(String from) {
final PumpInterface pump = ConfigBuilderPlugin.getActivePump(); final PumpInterface pump = ConfigBuilderPlugin.getActivePump();
final Profile profile = MainApp.getConfigBuilder().getProfile(); final Profile profile = MainApp.getConfigBuilder().getProfile();
if (profile == null) {
noProfile.setVisibility(View.VISIBLE);
return;
} else {
noProfile.setVisibility(View.GONE);
}
final String units = profile.getUnits(); final String units = profile.getUnits();
double lowLineSetting = SP.getDouble("low_mark", Profile.fromMgdlToUnits(OverviewPlugin.bgTargetLow, units)); double lowLineSetting = SP.getDouble("low_mark", Profile.fromMgdlToUnits(OverviewPlugin.bgTargetLow, units));
@ -247,7 +252,7 @@ public class HistoryBrowseActivity extends AppCompatActivity {
graphData.addTreatments(fromTime, toTime); graphData.addTreatments(fromTime, toTime);
// add basal data // add basal data
if (pump.getPumpDescription().isTempBasalCapable && showBasalsCheckbox.isChecked()) { if (pump.getPumpDescription().isTempBasalCapable && showBasal) {
graphData.addBasals(fromTime, toTime, lowLine / graphData.maxY / 1.2d); graphData.addBasals(fromTime, toTime, lowLine / graphData.maxY / 1.2d);
} }
@ -262,25 +267,30 @@ public class HistoryBrowseActivity extends AppCompatActivity {
boolean useCobForScale = false; boolean useCobForScale = false;
boolean useDevForScale = false; boolean useDevForScale = false;
boolean useRatioForScale = false; boolean useRatioForScale = false;
boolean useDevSlopeForScale = false;
if (showIobCheckbox.isChecked()) { if (showIob) {
useIobForScale = true; useIobForScale = true;
} else if (showCobCheckbox.isChecked()) { } else if (showCob) {
useCobForScale = true; useCobForScale = true;
} else if (showDeviationsCheckbox.isChecked()) { } else if (showDev) {
useDevForScale = true; useDevForScale = true;
} else if (showRatiosCheckbox.isChecked()) { } else if (showRat) {
useRatioForScale = true; useRatioForScale = true;
} else if (showDevslope) {
useDevSlopeForScale = true;
} }
if (showIobCheckbox.isChecked()) if (showIob)
secondGraphData.addIob(fromTime, toTime, useIobForScale, 1d); secondGraphData.addIob(fromTime, toTime, useIobForScale, 1d);
if (showCobCheckbox.isChecked()) if (showCob)
secondGraphData.addCob(fromTime, toTime, useCobForScale, useCobForScale ? 1d : 0.5d); secondGraphData.addCob(fromTime, toTime, useCobForScale, useCobForScale ? 1d : 0.5d);
if (showDeviationsCheckbox.isChecked()) if (showDev)
secondGraphData.addDeviations(fromTime, toTime, useDevForScale, 1d); secondGraphData.addDeviations(fromTime, toTime, useDevForScale, 1d);
if (showRatiosCheckbox.isChecked()) if (showRat)
secondGraphData.addRatio(fromTime, toTime, useRatioForScale, 1d); secondGraphData.addRatio(fromTime, toTime, useRatioForScale, 1d);
if (showDevslope)
secondGraphData.addDeviationSlope(fromTime, toTime, useDevSlopeForScale, 1d);
// **** NOW line **** // **** NOW line ****
// set manual x bounds to have nice steps // set manual x bounds to have nice steps
@ -288,7 +298,7 @@ public class HistoryBrowseActivity extends AppCompatActivity {
secondGraphData.addNowLine(pointer); secondGraphData.addNowLine(pointer);
// do GUI update // do GUI update
if (showIobCheckbox.isChecked() || showCobCheckbox.isChecked() || showDeviationsCheckbox.isChecked() || showRatiosCheckbox.isChecked()) { if (showIob || showCob || showDev || showRat || showDevslope) {
iobGraph.setVisibility(View.VISIBLE); iobGraph.setVisibility(View.VISIBLE);
} else { } else {
iobGraph.setVisibility(View.GONE); iobGraph.setVisibility(View.GONE);
@ -297,4 +307,98 @@ public class HistoryBrowseActivity extends AppCompatActivity {
graphData.performUpdate(); graphData.performUpdate();
secondGraphData.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();
}
});
}
} }

View file

@ -19,6 +19,9 @@ import android.support.v4.view.ViewPager;
import android.support.v7.app.AlertDialog; import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity; import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.PopupMenu; 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.MenuInflater;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.MotionEvent; import android.view.MotionEvent;
@ -27,6 +30,7 @@ import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodManager;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ImageButton; import android.widget.ImageButton;
import android.widget.TextView;
import com.joanzapata.iconify.Iconify; import com.joanzapata.iconify.Iconify;
import com.joanzapata.iconify.fonts.FontAwesomeModule; import com.joanzapata.iconify.fonts.FontAwesomeModule;
@ -44,6 +48,7 @@ import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Food.FoodPlugin; import info.nightscout.androidaps.plugins.Food.FoodPlugin;
import info.nightscout.androidaps.plugins.Overview.events.EventSetWakeLock; 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.SlidingTabLayout;
import info.nightscout.androidaps.tabs.TabPageAdapter; import info.nightscout.androidaps.tabs.TabPageAdapter;
import info.nightscout.utils.ImportExportPrefs; import info.nightscout.utils.ImportExportPrefs;
@ -374,7 +379,8 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
MainApp.getDbHelper().resetDatabases(); MainApp.getDbHelper().resetDatabases();
// should be handled by Plugin-Interface and // should be handled by Plugin-Interface and
// additional service interface and plugin registry // additional service interface and plugin registry
MainApp.getSpecificPlugin(FoodPlugin.class).getService().resetFood(); FoodPlugin.getPlugin().getService().resetFood();
TreatmentsPlugin.getPlugin().getService().resetTreatments();
} }
}) })
.create() .create()
@ -399,11 +405,18 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
else else
builder.setIcon(R.mipmap.blueowl); builder.setIcon(R.mipmap.blueowl);
String message = "Build: " + BuildConfig.BUILDVERSION + "\n"; String message = "Build: " + BuildConfig.BUILDVERSION + "\n";
message += MainApp.sResources.getString(R.string.configbuilder_nightscoutversion_label) + " " + ConfigBuilderPlugin.nightscoutVersionName; message += "Flavor: " + BuildConfig.FLAVOR + BuildConfig.BUILD_TYPE + "\n";
builder.setMessage(message); message += getString(R.string.configbuilder_nightscoutversion_label) + " " + ConfigBuilderPlugin.nightscoutVersionName;
if (MainApp.engineeringMode)
message += "\n" + MainApp.gs(R.string.engineering_mode_enabled);
message += getString(R.string.about_link_urls);
final SpannableString messageSpanned = new SpannableString(message);
Linkify.addLinks(messageSpanned, Linkify.WEB_URLS);
builder.setMessage(messageSpanned);
builder.setPositiveButton(MainApp.sResources.getString(R.string.ok), null); builder.setPositiveButton(MainApp.sResources.getString(R.string.ok), null);
AlertDialog alertDialog = builder.create(); AlertDialog alertDialog = builder.create();
alertDialog.show(); alertDialog.show();
((TextView)alertDialog.findViewById(android.R.id.message)).setMovementMethod(LinkMovementMethod.getInstance());
break; break;
case R.id.nav_exit: case R.id.nav_exit:
log.debug("Exiting"); log.debug("Exiting");

View file

@ -20,52 +20,56 @@ import net.danlew.android.joda.JodaTimeAndroid;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import ch.qos.logback.classic.LoggerContext;
import info.nightscout.androidaps.Services.Intents; import info.nightscout.androidaps.Services.Intents;
import info.nightscout.androidaps.data.ConstraintChecker;
import info.nightscout.androidaps.db.DatabaseHelper; import info.nightscout.androidaps.db.DatabaseHelper;
import info.nightscout.androidaps.interfaces.InsulinInterface;
import info.nightscout.androidaps.interfaces.PluginBase; 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.Actions.ActionsFragment;
import info.nightscout.androidaps.plugins.Careportal.CareportalPlugin; 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.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.ConstraintsObjectives.ObjectivesPlugin; import info.nightscout.androidaps.plugins.ConstraintsObjectives.ObjectivesPlugin;
import info.nightscout.androidaps.plugins.ConstraintsSafety.SafetyPlugin; import info.nightscout.androidaps.plugins.ConstraintsSafety.SafetyPlugin;
import info.nightscout.androidaps.plugins.Food.FoodPlugin; 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.InsulinOrefFreePeakPlugin;
import info.nightscout.androidaps.plugins.Insulin.InsulinOrefRapidActingPlugin; import info.nightscout.androidaps.plugins.Insulin.InsulinOrefRapidActingPlugin;
import info.nightscout.androidaps.plugins.Insulin.InsulinOrefUltraRapidActingPlugin; import info.nightscout.androidaps.plugins.Insulin.InsulinOrefUltraRapidActingPlugin;
import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin; import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin;
import info.nightscout.androidaps.plugins.Loop.LoopPlugin; 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.NSClientInternal.receivers.AckAlarmReceiver;
import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin; import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin;
import info.nightscout.androidaps.plugins.OpenAPSMA.OpenAPSMAPlugin; import info.nightscout.androidaps.plugins.OpenAPSMA.OpenAPSMAPlugin;
import info.nightscout.androidaps.plugins.OpenAPSSMB.OpenAPSSMBPlugin; import info.nightscout.androidaps.plugins.OpenAPSSMB.OpenAPSSMBPlugin;
import info.nightscout.androidaps.plugins.Overview.OverviewPlugin; 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.Persistentnotification.PersistentNotificationPlugin;
import info.nightscout.androidaps.plugins.ProfileLocal.LocalProfilePlugin; import info.nightscout.androidaps.plugins.ProfileLocal.LocalProfilePlugin;
import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin; import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin;
import info.nightscout.androidaps.plugins.ProfileSimple.SimpleProfilePlugin; 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.PumpDanaR.DanaRPlugin;
import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin;
import info.nightscout.androidaps.plugins.PumpDanaRS.DanaRSPlugin; import info.nightscout.androidaps.plugins.PumpDanaRS.DanaRSPlugin;
import info.nightscout.androidaps.plugins.PumpDanaRv2.DanaRv2Plugin; import info.nightscout.androidaps.plugins.PumpDanaRv2.DanaRv2Plugin;
import info.nightscout.androidaps.plugins.PumpInsight.InsightPumpPlugin; import info.nightscout.androidaps.plugins.PumpInsight.InsightPlugin;
import info.nightscout.androidaps.plugins.PumpMDI.MDIPlugin; import info.nightscout.androidaps.plugins.PumpMDI.MDIPlugin;
import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin; import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin;
import info.nightscout.androidaps.plugins.SensitivityAAPS.SensitivityAAPSPlugin; import info.nightscout.androidaps.plugins.SensitivityAAPS.SensitivityAAPSPlugin;
import info.nightscout.androidaps.plugins.SensitivityOref0.SensitivityOref0Plugin; import info.nightscout.androidaps.plugins.SensitivityOref0.SensitivityOref0Plugin;
import info.nightscout.androidaps.plugins.SensitivityWeightedAverage.SensitivityWeightedAveragePlugin; import info.nightscout.androidaps.plugins.SensitivityWeightedAverage.SensitivityWeightedAveragePlugin;
import info.nightscout.androidaps.plugins.SmsCommunicator.SmsCommunicatorPlugin; 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.SourceGlimp.SourceGlimpPlugin; import info.nightscout.androidaps.plugins.Source.SourceGlimpPlugin;
import info.nightscout.androidaps.plugins.SourceMM640g.SourceMM640gPlugin; import info.nightscout.androidaps.plugins.Source.SourceMM640gPlugin;
import info.nightscout.androidaps.plugins.SourceNSClient.SourceNSClientPlugin; import info.nightscout.androidaps.plugins.Source.SourceNSClientPlugin;
import info.nightscout.androidaps.plugins.SourceXdrip.SourceXdripPlugin; import info.nightscout.androidaps.plugins.Source.SourceXdripPlugin;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.androidaps.plugins.Wear.WearPlugin; import info.nightscout.androidaps.plugins.Wear.WearPlugin;
import info.nightscout.androidaps.plugins.XDripStatusline.StatuslinePlugin; import info.nightscout.androidaps.plugins.XDripStatusline.StatuslinePlugin;
@ -87,6 +91,7 @@ public class MainApp extends Application {
private static DatabaseHelper sDatabaseHelper = null; private static DatabaseHelper sDatabaseHelper = null;
private static ConfigBuilderPlugin sConfigBuilder = null; private static ConfigBuilderPlugin sConfigBuilder = null;
private static ConstraintChecker sConstraintsChecker = null;
private static ArrayList<PluginBase> pluginsList = null; private static ArrayList<PluginBase> pluginsList = null;
@ -95,11 +100,16 @@ public class MainApp extends Application {
private static AckAlarmReceiver ackAlarmReciever = new AckAlarmReceiver(); private static AckAlarmReceiver ackAlarmReciever = new AckAlarmReceiver();
private LocalBroadcastManager lbm; private LocalBroadcastManager lbm;
public static boolean devBranch;
public static boolean engineeringMode;
@Override @Override
public void onCreate() { public void onCreate() {
super.onCreate(); super.onCreate();
sInstance = this; sInstance = this;
sResources = getResources(); sResources = getResources();
sConstraintsChecker = new ConstraintChecker(this);
sDatabaseHelper = OpenHelperManager.getHelper(sInstance, DatabaseHelper.class);
try { try {
if (FabricPrivacy.fabricEnabled()) { if (FabricPrivacy.fabricEnabled()) {
@ -116,6 +126,12 @@ public class MainApp extends Application {
log.info("Version: " + BuildConfig.VERSION_NAME); log.info("Version: " + BuildConfig.VERSION_NAME);
log.info("BuildVersion: " + BuildConfig.BUILDVERSION); log.info("BuildVersion: " + BuildConfig.BUILDVERSION);
String extFilesDir = this.getLogDirectory();
File engineeringModeSemaphore = new File(extFilesDir, "engineering_mode");
engineeringMode = engineeringModeSemaphore.exists() && engineeringModeSemaphore.isFile();
devBranch = BuildConfig.VERSION.contains("dev");
sBus = Config.logEvents ? new LoggingBus(ThreadEnforcer.ANY) : new Bus(ThreadEnforcer.ANY); sBus = Config.logEvents ? new LoggingBus(ThreadEnforcer.ANY) : new Bus(ThreadEnforcer.ANY);
registerLocalBroadcastReceiver(); registerLocalBroadcastReceiver();
@ -126,22 +142,22 @@ public class MainApp extends Application {
pluginsList.add(OverviewPlugin.getPlugin()); pluginsList.add(OverviewPlugin.getPlugin());
pluginsList.add(IobCobCalculatorPlugin.getPlugin()); pluginsList.add(IobCobCalculatorPlugin.getPlugin());
if (Config.ACTION) pluginsList.add(ActionsFragment.getPlugin()); if (Config.ACTION) pluginsList.add(ActionsFragment.getPlugin());
pluginsList.add(InsulinFastactingPlugin.getPlugin());
pluginsList.add(InsulinFastactingProlongedPlugin.getPlugin());
pluginsList.add(InsulinOrefRapidActingPlugin.getPlugin()); pluginsList.add(InsulinOrefRapidActingPlugin.getPlugin());
pluginsList.add(InsulinOrefUltraRapidActingPlugin.getPlugin()); pluginsList.add(InsulinOrefUltraRapidActingPlugin.getPlugin());
pluginsList.add(InsulinOrefFreePeakPlugin.getPlugin()); pluginsList.add(InsulinOrefFreePeakPlugin.getPlugin());
pluginsList.add(SensitivityOref0Plugin.getPlugin()); pluginsList.add(SensitivityOref0Plugin.getPlugin());
pluginsList.add(SensitivityAAPSPlugin.getPlugin()); pluginsList.add(SensitivityAAPSPlugin.getPlugin());
pluginsList.add(SensitivityWeightedAveragePlugin.getPlugin()); pluginsList.add(SensitivityWeightedAveragePlugin.getPlugin());
if (Config.DANAR) pluginsList.add(DanaRPlugin.getPlugin()); if (Config.HWPUMPS) pluginsList.add(DanaRPlugin.getPlugin());
if (Config.DANAR) pluginsList.add(DanaRKoreanPlugin.getPlugin()); if (Config.HWPUMPS) pluginsList.add(DanaRKoreanPlugin.getPlugin());
if (Config.DANAR) pluginsList.add(DanaRv2Plugin.getPlugin()); if (Config.HWPUMPS) pluginsList.add(DanaRv2Plugin.getPlugin());
if (Config.DANAR) pluginsList.add(DanaRSPlugin.getPlugin()); if (Config.HWPUMPS) pluginsList.add(DanaRSPlugin.getPlugin());
pluginsList.add(CareportalPlugin.getPlugin()); pluginsList.add(CareportalPlugin.getPlugin());
// if (Config.DANAR) pluginsList.add(InsightPumpPlugin.getPlugin()); // <-- Enable Insight plugin here 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.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(LoopPlugin.getPlugin());
if (Config.APS) pluginsList.add(OpenAPSMAPlugin.getPlugin()); if (Config.APS) pluginsList.add(OpenAPSMAPlugin.getPlugin());
if (Config.APS) pluginsList.add(OpenAPSAMAPlugin.getPlugin()); if (Config.APS) pluginsList.add(OpenAPSAMAPlugin.getPlugin());
@ -168,33 +184,33 @@ public class MainApp extends Application {
pluginsList.add(WearPlugin.initPlugin(this)); pluginsList.add(WearPlugin.initPlugin(this));
pluginsList.add(StatuslinePlugin.initPlugin(this)); pluginsList.add(StatuslinePlugin.initPlugin(this));
pluginsList.add(new PersistentNotificationPlugin(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(); MainApp.getConfigBuilder().initialize();
} }
NSUpload.uploadAppStart(); NSUpload.uploadAppStart();
if (Config.NSCLIENT) if (Config.NSCLIENT)
FabricPrivacy.getInstance().logCustom(new CustomEvent("AppStart-NSClient")); FabricPrivacy.getInstance().logCustom(new CustomEvent("AppStart-NSClient"));
else if (Config.G5UPLOADER) else if (Config.G5UPLOADER)
FabricPrivacy.getInstance().logCustom(new CustomEvent("AppStart-G5Uploader")); FabricPrivacy.getInstance().logCustom(new CustomEvent("AppStart-G5Uploader"));
else if (Config.PUMPCONTROL) else if (Config.PUMPCONTROL)
FabricPrivacy.getInstance().logCustom(new CustomEvent("AppStart-PumpControl")); FabricPrivacy.getInstance().logCustom(new CustomEvent("AppStart-PumpControl"));
else if (MainApp.getConfigBuilder().isClosedModeEnabled()) else if (MainApp.getConstraintChecker().isClosedLoopAllowed().value())
FabricPrivacy.getInstance().logCustom(new CustomEvent("AppStart-ClosedLoop")); FabricPrivacy.getInstance().logCustom(new CustomEvent("AppStart-ClosedLoop"));
else else
FabricPrivacy.getInstance().logCustom(new CustomEvent("AppStart-OpenLoop")); FabricPrivacy.getInstance().logCustom(new CustomEvent("AppStart-OpenLoop"));
new Thread(new Runnable() { final PumpInterface pump = ConfigBuilderPlugin.getActivePump();
@Override if (pump != null) {
public void run() { new Thread(() -> {
SystemClock.sleep(5000); SystemClock.sleep(5000);
ConfigBuilderPlugin.getCommandQueue().readStatus("Initialization", null); ConfigBuilderPlugin.getCommandQueue().readStatus("Initialization", null);
startKeepAliveService(); startKeepAliveService();
}
}).start(); }).start();
}
} }
private void registerLocalBroadcastReceiver() { private void registerLocalBroadcastReceiver() {
@ -256,9 +272,6 @@ public class MainApp extends Application {
} }
public static DatabaseHelper getDbHelper() { public static DatabaseHelper getDbHelper() {
if (sDatabaseHelper == null) {
sDatabaseHelper = OpenHelperManager.getHelper(sInstance, DatabaseHelper.class);
}
return sDatabaseHelper; return sDatabaseHelper;
} }
@ -273,11 +286,15 @@ public class MainApp extends Application {
return sConfigBuilder; return sConfigBuilder;
} }
public static ConstraintChecker getConstraintChecker() {
return sConstraintsChecker;
}
public static ArrayList<PluginBase> getPluginsList() { public static ArrayList<PluginBase> getPluginsList() {
return pluginsList; return pluginsList;
} }
public static ArrayList<PluginBase> getSpecificPluginsList(int type) { public static ArrayList<PluginBase> getSpecificPluginsList(PluginType type) {
ArrayList<PluginBase> newList = new ArrayList<>(); ArrayList<PluginBase> newList = new ArrayList<>();
if (pluginsList != null) { if (pluginsList != null) {
@ -291,20 +308,7 @@ public class MainApp extends Application {
return newList; return newList;
} }
@Nullable public static ArrayList<PluginBase> getSpecificPluginsVisibleInList(PluginType type) {
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) {
ArrayList<PluginBase> newList = new ArrayList<>(); ArrayList<PluginBase> newList = new ArrayList<>();
if (pluginsList != null) { if (pluginsList != null) {
@ -333,7 +337,7 @@ public class MainApp extends Application {
return newList; 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<>(); ArrayList<PluginBase> newList = new ArrayList<>();
if (pluginsList != null) { if (pluginsList != null) {
@ -361,9 +365,23 @@ public class MainApp extends Application {
return null; return null;
} }
public static boolean isEngineeringModeOrRelease() {
if (!BuildConfig.APS)
return true;
return engineeringMode || !devBranch;
}
public String getLogDirectory() {
LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
return lc.getProperty("EXT_FILES_DIR");
}
@Override @Override
public void onTerminate() { public void onTerminate() {
super.onTerminate(); super.onTerminate();
if (sDatabaseHelper != null) {
sDatabaseHelper.close(); sDatabaseHelper.close();
sDatabaseHelper = null;
}
} }
} }

View file

@ -1,11 +1,9 @@
package info.nightscout.androidaps; package info.nightscout.androidaps;
import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.os.Bundle; import android.os.Bundle;
import android.preference.EditTextPreference; import android.preference.EditTextPreference;
import android.preference.ListPreference; import android.preference.ListPreference;
import android.preference.MultiSelectListPreference;
import android.preference.Preference; import android.preference.Preference;
import android.preference.PreferenceActivity; import android.preference.PreferenceActivity;
import android.preference.PreferenceFragment; import android.preference.PreferenceFragment;
@ -16,24 +14,27 @@ import android.text.TextUtils;
import info.nightscout.androidaps.events.EventPreferenceChange; import info.nightscout.androidaps.events.EventPreferenceChange;
import info.nightscout.androidaps.events.EventRefreshGui; import info.nightscout.androidaps.events.EventRefreshGui;
import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.plugins.OpenAPSSMB.OpenAPSSMBPlugin; import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.plugins.Careportal.CareportalPlugin; import info.nightscout.androidaps.plugins.Careportal.CareportalPlugin;
import info.nightscout.androidaps.plugins.ConstraintsSafety.SafetyPlugin; import info.nightscout.androidaps.plugins.ConstraintsSafety.SafetyPlugin;
import info.nightscout.androidaps.plugins.Insulin.InsulinOrefFreePeakPlugin; import info.nightscout.androidaps.plugins.Insulin.InsulinOrefFreePeakPlugin;
import info.nightscout.androidaps.plugins.Loop.LoopPlugin; 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.OpenAPSAMA.OpenAPSAMAPlugin;
import info.nightscout.androidaps.plugins.OpenAPSMA.OpenAPSMAPlugin; 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.PumpDanaR.DanaRPlugin;
import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin;
import info.nightscout.androidaps.plugins.PumpDanaRS.DanaRSPlugin; import info.nightscout.androidaps.plugins.PumpDanaRS.DanaRSPlugin;
import info.nightscout.androidaps.plugins.PumpDanaRv2.DanaRv2Plugin; 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.PumpVirtual.VirtualPumpPlugin;
import info.nightscout.androidaps.plugins.SensitivityAAPS.SensitivityAAPSPlugin; import info.nightscout.androidaps.plugins.SensitivityAAPS.SensitivityAAPSPlugin;
import info.nightscout.androidaps.plugins.SensitivityOref0.SensitivityOref0Plugin; import info.nightscout.androidaps.plugins.SensitivityOref0.SensitivityOref0Plugin;
import info.nightscout.androidaps.plugins.SensitivityWeightedAverage.SensitivityWeightedAveragePlugin; import info.nightscout.androidaps.plugins.SensitivityWeightedAverage.SensitivityWeightedAveragePlugin;
import info.nightscout.androidaps.plugins.SmsCommunicator.SmsCommunicatorPlugin; 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.Wear.WearPlugin;
import info.nightscout.androidaps.plugins.XDripStatusline.StatuslinePlugin; import info.nightscout.androidaps.plugins.XDripStatusline.StatuslinePlugin;
import info.nightscout.utils.LocaleHelper; import info.nightscout.utils.LocaleHelper;
@ -67,8 +68,8 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
if (key.equals("short_tabtitles")) { if (key.equals("short_tabtitles")) {
MainApp.bus().post(new EventRefreshGui()); MainApp.bus().post(new EventRefreshGui());
} }
if (key.equals("openapsama_useautosens") && SP.getBoolean("openapsama_useautosens", false)) { if (key.equals(MainApp.gs(R.string.key_openapsama_useautosens)) && SP.getBoolean(R.string.key_openapsama_useautosens, false)) {
OKDialog.show(this, MainApp.sResources.getString(R.string.configbuilder_sensitivity), MainApp.sResources.getString(R.string.sensitivity_warning), null); OKDialog.show(this, MainApp.gs(R.string.configbuilder_sensitivity), MainApp.gs(R.string.sensitivity_warning), null);
} }
updatePrefSummary(myPreferenceFragment.getPreference(key)); updatePrefSummary(myPreferenceFragment.getPreference(key));
} }
@ -82,13 +83,13 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
EditTextPreference editTextPref = (EditTextPreference) pref; EditTextPreference editTextPref = (EditTextPreference) pref;
if (pref.getKey().contains("password") || pref.getKey().contains("secret")) { if (pref.getKey().contains("password") || pref.getKey().contains("secret")) {
pref.setSummary("******"); 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, "")); pref.setSummary(SP.getString(R.string.key_danars_name, ""));
} else if (editTextPref.getText() != null && !editTextPref.getText().equals("")) { } else if (editTextPref.getText() != null && !editTextPref.getText().equals("")) {
((EditTextPreference) pref).setDialogMessage(editTextPref.getDialogMessage()); ((EditTextPreference) pref).setDialogMessage(editTextPref.getDialogMessage());
pref.setSummary(editTextPref.getText()); pref.setSummary(editTextPref.getText());
} else if (pref.getKey().contains("smscommunicator_allowednumbers") && TextUtils.isEmpty(editTextPref.getText().trim())) { } else if (pref.getKey().contains("smscommunicator_allowednumbers") && TextUtils.isEmpty(editTextPref.getText().trim())) {
pref.setSummary(MainApp.sResources.getString(R.string.smscommunicator_allowednumbers_summary)); pref.setSummary(MainApp.gs(R.string.smscommunicator_allowednumbers_summary));
} }
} }
} }
@ -113,7 +114,7 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
id = args.getInt("id"); id = args.getInt("id");
} }
void addPreferencesFromResourceIfEnabled(PluginBase p, int type) { void addPreferencesFromResourceIfEnabled(PluginBase p, PluginType type) {
if (p.isEnabled(type) && p.getPreferencesId() != -1) if (p.isEnabled(type) && p.getPreferencesId() != -1)
addPreferencesFromResource(p.getPreferencesId()); addPreferencesFromResource(p.getPreferencesId());
} }
@ -128,9 +129,7 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
if (id != -1) { if (id != -1) {
addPreferencesFromResource(id); addPreferencesFromResource(id);
addPreferencesFromResource(R.xml.pref_advanced);
} else { } else {
addPreferencesFromResource(R.xml.pref_overview);
if (!Config.NSCLIENT && !Config.G5UPLOADER) { if (!Config.NSCLIENT && !Config.G5UPLOADER) {
addPreferencesFromResource(R.xml.pref_password); addPreferencesFromResource(R.xml.pref_password);
@ -138,53 +137,54 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
addPreferencesFromResource(R.xml.pref_age); addPreferencesFromResource(R.xml.pref_age);
addPreferencesFromResource(R.xml.pref_language); addPreferencesFromResource(R.xml.pref_language);
if (!Config.NSCLIENT && !Config.G5UPLOADER) { addPreferencesFromResource(R.xml.pref_overview);
addPreferencesFromResource(R.xml.pref_quickwizard);
} addPreferencesFromResourceIfEnabled(SourceDexcomG5Plugin.getPlugin(), PluginType.BGSOURCE);
addPreferencesFromResourceIfEnabled(SourceDexcomG5Plugin.getPlugin(), PluginBase.BGSOURCE); addPreferencesFromResourceIfEnabled(CareportalPlugin.getPlugin(), PluginType.GENERAL);
addPreferencesFromResourceIfEnabled(CareportalPlugin.getPlugin(), PluginBase.GENERAL); addPreferencesFromResourceIfEnabled(SafetyPlugin.getPlugin(), PluginType.CONSTRAINTS);
addPreferencesFromResourceIfEnabled(SafetyPlugin.getPlugin(), PluginBase.CONSTRAINTS);
if (Config.APS) { if (Config.APS) {
addPreferencesFromResourceIfEnabled(LoopPlugin.getPlugin(), PluginBase.LOOP); addPreferencesFromResourceIfEnabled(LoopPlugin.getPlugin(), PluginType.LOOP);
addPreferencesFromResourceIfEnabled(OpenAPSMAPlugin.getPlugin(), PluginBase.APS); addPreferencesFromResourceIfEnabled(OpenAPSMAPlugin.getPlugin(), PluginType.APS);
addPreferencesFromResourceIfEnabled(OpenAPSAMAPlugin.getPlugin(), PluginBase.APS); addPreferencesFromResourceIfEnabled(OpenAPSAMAPlugin.getPlugin(), PluginType.APS);
addPreferencesFromResourceIfEnabled(OpenAPSSMBPlugin.getPlugin(), PluginBase.APS); addPreferencesFromResourceIfEnabled(OpenAPSSMBPlugin.getPlugin(), PluginType.APS);
} }
addPreferencesFromResourceIfEnabled(SensitivityAAPSPlugin.getPlugin(), PluginBase.SENSITIVITY); addPreferencesFromResourceIfEnabled(SensitivityAAPSPlugin.getPlugin(), PluginType.SENSITIVITY);
addPreferencesFromResourceIfEnabled(SensitivityWeightedAveragePlugin.getPlugin(), PluginBase.SENSITIVITY); addPreferencesFromResourceIfEnabled(SensitivityWeightedAveragePlugin.getPlugin(), PluginType.SENSITIVITY);
addPreferencesFromResourceIfEnabled(SensitivityOref0Plugin.getPlugin(), PluginBase.SENSITIVITY); addPreferencesFromResourceIfEnabled(SensitivityOref0Plugin.getPlugin(), PluginType.SENSITIVITY);
if (Config.DANAR) { if (Config.HWPUMPS) {
addPreferencesFromResourceIfEnabled(DanaRPlugin.getPlugin(), PluginBase.PUMP); addPreferencesFromResourceIfEnabled(DanaRPlugin.getPlugin(), PluginType.PUMP);
addPreferencesFromResourceIfEnabled(DanaRKoreanPlugin.getPlugin(), PluginBase.PUMP); addPreferencesFromResourceIfEnabled(DanaRKoreanPlugin.getPlugin(), PluginType.PUMP);
addPreferencesFromResourceIfEnabled(DanaRv2Plugin.getPlugin(), PluginBase.PUMP); addPreferencesFromResourceIfEnabled(DanaRv2Plugin.getPlugin(), PluginType.PUMP);
addPreferencesFromResourceIfEnabled(DanaRSPlugin.getPlugin(), PluginBase.PUMP); addPreferencesFromResourceIfEnabled(DanaRSPlugin.getPlugin(), PluginType.PUMP);
addPreferencesFromResourceIfEnabled(InsightPlugin.getPlugin(), PluginType.PUMP);
addPreferencesFromResourceIfEnabled(ComboPlugin.getPlugin(), PluginType.PUMP);
if (DanaRPlugin.getPlugin().isEnabled(PluginBase.PROFILE) if (DanaRPlugin.getPlugin().isEnabled(PluginType.PROFILE)
|| DanaRKoreanPlugin.getPlugin().isEnabled(PluginBase.PROFILE) || DanaRKoreanPlugin.getPlugin().isEnabled(PluginType.PROFILE)
|| DanaRv2Plugin.getPlugin().isEnabled(PluginBase.PROFILE) || DanaRv2Plugin.getPlugin().isEnabled(PluginType.PROFILE)
|| DanaRSPlugin.getPlugin().isEnabled(PluginBase.PROFILE)) { || DanaRSPlugin.getPlugin().isEnabled(PluginType.PROFILE)) {
addPreferencesFromResource(R.xml.pref_danarprofile); addPreferencesFromResource(R.xml.pref_danarprofile);
} }
} }
if (!Config.NSCLIENT && !Config.G5UPLOADER) { 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(NSClientPlugin.getPlugin(), PluginType.GENERAL);
addPreferencesFromResourceIfEnabled(SmsCommunicatorPlugin.getPlugin(), PluginBase.GENERAL); addPreferencesFromResourceIfEnabled(SmsCommunicatorPlugin.getPlugin(), PluginType.GENERAL);
if (!Config.NSCLIENT && !Config.G5UPLOADER) { if (!Config.NSCLIENT && !Config.G5UPLOADER) {
addPreferencesFromResource(R.xml.pref_others); addPreferencesFromResource(R.xml.pref_others);
} }
addPreferencesFromResource(R.xml.pref_advanced); addPreferencesFromResource(R.xml.pref_datachoices);
addPreferencesFromResourceIfEnabled(WearPlugin.getPlugin(), PluginBase.GENERAL); addPreferencesFromResourceIfEnabled(WearPlugin.getPlugin(), PluginType.GENERAL);
addPreferencesFromResourceIfEnabled(StatuslinePlugin.getPlugin(), PluginBase.GENERAL); addPreferencesFromResourceIfEnabled(StatuslinePlugin.getPlugin(), PluginType.GENERAL);
} }
initSummary(getPreferenceScreen()); initSummary(getPreferenceScreen());

View file

@ -18,8 +18,8 @@ import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.ProfileStore; import info.nightscout.androidaps.data.ProfileStore;
import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.db.CareportalEvent; import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.events.EventNewBasalProfile;
import info.nightscout.androidaps.events.EventNsFood; import info.nightscout.androidaps.events.EventNsFood;
import info.nightscout.androidaps.events.EventNsTreatment;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.ConstraintsObjectives.ObjectivesPlugin; import info.nightscout.androidaps.plugins.ConstraintsObjectives.ObjectivesPlugin;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSDeviceStatus; import info.nightscout.androidaps.plugins.NSClientInternal.data.NSDeviceStatus;
@ -34,13 +34,14 @@ import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin;
import info.nightscout.androidaps.plugins.ProfileNS.events.EventNSProfileUpdateGUI; import info.nightscout.androidaps.plugins.ProfileNS.events.EventNSProfileUpdateGUI;
import info.nightscout.androidaps.plugins.PumpDanaR.activities.DanaRNSHistorySync; import info.nightscout.androidaps.plugins.PumpDanaR.activities.DanaRNSHistorySync;
import info.nightscout.androidaps.plugins.SmsCommunicator.events.EventNewSMS; import info.nightscout.androidaps.plugins.SmsCommunicator.events.EventNewSMS;
import info.nightscout.androidaps.plugins.SourceDexcomG5.SourceDexcomG5Plugin; import info.nightscout.androidaps.plugins.Source.SourceDexcomG5Plugin;
import info.nightscout.androidaps.plugins.SourceGlimp.SourceGlimpPlugin; import info.nightscout.androidaps.plugins.Source.SourceGlimpPlugin;
import info.nightscout.androidaps.plugins.SourceMM640g.SourceMM640gPlugin; import info.nightscout.androidaps.plugins.Source.SourceMM640gPlugin;
import info.nightscout.androidaps.plugins.SourceNSClient.SourceNSClientPlugin; import info.nightscout.androidaps.plugins.Source.SourceNSClientPlugin;
import info.nightscout.androidaps.plugins.SourceXdrip.SourceXdripPlugin; import info.nightscout.androidaps.plugins.Source.SourceXdripPlugin;
import info.nightscout.androidaps.receivers.DataReceiver; import info.nightscout.androidaps.receivers.DataReceiver;
import info.nightscout.utils.BundleLogger; import info.nightscout.utils.BundleLogger;
import info.nightscout.utils.JsonHelper;
import info.nightscout.utils.NSUpload; import info.nightscout.utils.NSUpload;
import info.nightscout.utils.SP; import info.nightscout.utils.SP;
@ -63,32 +64,37 @@ public class DataService extends IntentService {
protected void onHandleIntent(final Intent intent) { protected void onHandleIntent(final Intent intent) {
if (Config.logFunctionCalls) if (Config.logFunctionCalls)
log.debug("onHandleIntent " + BundleLogger.log(intent.getExtras())); log.debug("onHandleIntent " + BundleLogger.log(intent.getExtras()));
if (ConfigBuilderPlugin.getPlugin().getActiveBgSource() == null) {
if (ConfigBuilderPlugin.getActiveBgSource().getClass().equals(SourceXdripPlugin.class)) {
xDripEnabled = true; xDripEnabled = true;
nsClientEnabled = false; nsClientEnabled = false;
mm640gEnabled = false; mm640gEnabled = false;
glimpEnabled = false; glimpEnabled = false;
dexcomG5Enabled = 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; xDripEnabled = false;
nsClientEnabled = true; nsClientEnabled = true;
mm640gEnabled = false; mm640gEnabled = false;
glimpEnabled = false; glimpEnabled = false;
dexcomG5Enabled = false; dexcomG5Enabled = false;
} else if (ConfigBuilderPlugin.getActiveBgSource().getClass().equals(SourceMM640gPlugin.class)) { } else if (ConfigBuilderPlugin.getPlugin().getActiveBgSource().getClass().equals(SourceMM640gPlugin.class)) {
xDripEnabled = false; xDripEnabled = false;
nsClientEnabled = false; nsClientEnabled = false;
mm640gEnabled = true; mm640gEnabled = true;
glimpEnabled = false; glimpEnabled = false;
dexcomG5Enabled = false; dexcomG5Enabled = false;
} else if (ConfigBuilderPlugin.getActiveBgSource().getClass().equals(SourceGlimpPlugin.class)) { } else if (ConfigBuilderPlugin.getPlugin().getActiveBgSource().getClass().equals(SourceGlimpPlugin.class)) {
xDripEnabled = false; xDripEnabled = false;
nsClientEnabled = false; nsClientEnabled = false;
mm640gEnabled = false; mm640gEnabled = false;
glimpEnabled = true; glimpEnabled = true;
dexcomG5Enabled = false; dexcomG5Enabled = false;
} else if (ConfigBuilderPlugin.getActiveBgSource().getClass().equals(SourceDexcomG5Plugin.class)) { } else if (ConfigBuilderPlugin.getPlugin().getActiveBgSource().getClass().equals(SourceDexcomG5Plugin.class)) {
xDripEnabled = false; xDripEnabled = false;
nsClientEnabled = false; nsClientEnabled = false;
mm640gEnabled = false; mm640gEnabled = false;
@ -96,7 +102,7 @@ public class DataService extends IntentService {
dexcomG5Enabled = true; 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); boolean acceptNSData = !SP.getBoolean(R.string.key_ns_upload_only, false);
Bundle bundles = intent.getExtras(); Bundle bundles = intent.getExtras();
@ -124,7 +130,7 @@ public class DataService extends IntentService {
handleNewDataFromDexcomG5(intent); handleNewDataFromDexcomG5(intent);
} }
} else if (Intents.ACTION_NEW_SGV.equals(action)) { } else if (Intents.ACTION_NEW_SGV.equals(action)) {
// always backfill SGV from NS if (nsClientEnabled || SP.getBoolean(R.string.key_ns_autobackfill, true))
handleNewDataFromNSClient(intent); handleNewDataFromNSClient(intent);
// Objectives 0 // Objectives 0
ObjectivesPlugin.bgIsAvailableInNS = true; ObjectivesPlugin.bgIsAvailableInNS = true;
@ -191,7 +197,8 @@ public class DataService extends IntentService {
bgReading.direction = bundle.getString(Intents.EXTRA_BG_SLOPE_NAME); bgReading.direction = bundle.getString(Intents.EXTRA_BG_SLOPE_NAME);
bgReading.date = bundle.getLong(Intents.EXTRA_TIMESTAMP); bgReading.date = bundle.getLong(Intents.EXTRA_TIMESTAMP);
bgReading.raw = bundle.getDouble(Intents.EXTRA_RAW); 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"); MainApp.getDbHelper().createIfNotExists(bgReading, "XDRIP");
} }
@ -366,11 +373,8 @@ public class DataService extends IntentService {
String activeProfile = bundles.getString("activeprofile"); String activeProfile = bundles.getString("activeprofile");
String profile = bundles.getString("profile"); String profile = bundles.getString("profile");
ProfileStore profileStore = new ProfileStore(new JSONObject(profile)); ProfileStore profileStore = new ProfileStore(new JSONObject(profile));
NSProfilePlugin.storeNewProfile(profileStore); NSProfilePlugin.getPlugin().storeNewProfile(profileStore);
MainApp.bus().post(new EventNSProfileUpdateGUI()); 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) if (Config.logIncommingData)
log.debug("Received profileStore: " + activeProfile + " " + profile); log.debug("Received profileStore: " + activeProfile + " " + profile);
} catch (JSONException e) { } catch (JSONException e) {
@ -381,19 +385,18 @@ public class DataService extends IntentService {
if (intent.getAction().equals(Intents.ACTION_NEW_TREATMENT) || intent.getAction().equals(Intents.ACTION_CHANGED_TREATMENT)) { if (intent.getAction().equals(Intents.ACTION_NEW_TREATMENT) || intent.getAction().equals(Intents.ACTION_CHANGED_TREATMENT)) {
try { try {
if (bundles.containsKey("treatment")) { if (bundles.containsKey("treatment")) {
String trstring = bundles.getString("treatment"); JSONObject json = new JSONObject(bundles.getString("treatment"));
handleAddChangeDataFromNS(trstring); handleTreatmentFromNS(json, intent);
} }
if (bundles.containsKey("treatments")) { if (bundles.containsKey("treatments")) {
String trstring = bundles.getString("treatments"); String trstring = bundles.getString("treatments");
JSONArray jsonArray = new JSONArray(trstring); JSONArray jsonArray = new JSONArray(trstring);
for (int i = 0; i < jsonArray.length(); i++) { for (int i = 0; i < jsonArray.length(); i++) {
JSONObject trJson = jsonArray.getJSONObject(i); JSONObject json = jsonArray.getJSONObject(i);
String trstr = trJson.toString(); handleTreatmentFromNS(json, intent);
handleAddChangeDataFromNS(trstr);
} }
} }
} catch (Exception e) { } catch (JSONException e) {
log.error("Unhandled exception", e); log.error("Unhandled exception", e);
} }
} }
@ -402,21 +405,19 @@ public class DataService extends IntentService {
try { try {
if (bundles.containsKey("treatment")) { if (bundles.containsKey("treatment")) {
String trstring = bundles.getString("treatment"); String trstring = bundles.getString("treatment");
JSONObject trJson = new JSONObject(trstring); JSONObject json = new JSONObject(trstring);
String _id = trJson.getString("_id"); handleTreatmentFromNS(json);
handleRemovedRecordFromNS(_id);
} }
if (bundles.containsKey("treatments")) { if (bundles.containsKey("treatments")) {
String trstring = bundles.getString("treatments"); String trstring = bundles.getString("treatments");
JSONArray jsonArray = new JSONArray(trstring); JSONArray jsonArray = new JSONArray(trstring);
for (int i = 0; i < jsonArray.length(); i++) { for (int i = 0; i < jsonArray.length(); i++) {
JSONObject trJson = jsonArray.getJSONObject(i); JSONObject json = jsonArray.getJSONObject(i);
String _id = trJson.getString("_id"); handleTreatmentFromNS(json);
handleRemovedRecordFromNS(_id);
} }
} }
} catch (Exception e) { } catch (JSONException e) {
log.error("Unhandled exception", e); log.error("Unhandled exception", e);
} }
} }
@ -488,8 +489,12 @@ public class DataService extends IntentService {
} }
} }
private void handleRemovedRecordFromNS(String _id) { private void handleTreatmentFromNS(JSONObject json) {
MainApp.getDbHelper().deleteTreatmentById(_id); // 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().deleteTempTargetById(_id);
MainApp.getDbHelper().deleteTempBasalById(_id); MainApp.getDbHelper().deleteTempBasalById(_id);
MainApp.getDbHelper().deleteExtendedBolusById(_id); MainApp.getDbHelper().deleteExtendedBolusById(_id);
@ -497,86 +502,53 @@ public class DataService extends IntentService {
MainApp.getDbHelper().deleteProfileSwitchById(_id); MainApp.getDbHelper().deleteProfileSwitchById(_id);
} }
private void handleAddChangeDataFromNS(String trstring) throws JSONException { private void handleTreatmentFromNS(JSONObject json, Intent intent) throws JSONException {
JSONObject trJson = new JSONObject(trstring); // new DB model
handleDanaRHistoryRecords(trJson); // update record _id in history int mode = Intents.ACTION_NEW_TREATMENT.equals(intent.getAction()) ? EventNsTreatment.ADD : EventNsTreatment.UPDATE;
handleAddChangeTempTargetRecord(trJson); double insulin = JsonHelper.safeGetDouble(json, "insulin");
handleAddChangeTempBasalRecord(trJson); double carbs = JsonHelper.safeGetDouble(json, "carbs");
handleAddChangeExtendedBolusRecord(trJson); String eventType = JsonHelper.safeGetString(json, "eventType");
handleAddChangeCareportalEventRecord(trJson); if (insulin > 0 || carbs > 0) {
handleAddChangeTreatmentRecord(trJson); EventNsTreatment evtTreatment = new EventNsTreatment(mode, json);
handleAddChangeProfileSwitchRecord(trJson); 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);
} }
public void handleDanaRHistoryRecords(JSONObject trJson) { if (eventType.equals(CareportalEvent.ANNOUNCEMENT)) {
if (trJson.has(DanaRNSHistorySync.DANARSIGNATURE)) { long date = JsonHelper.safeGetLong(json,"mills");
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);
}
if (trJson.has("eventType") && trJson.getString("eventType").equals(CareportalEvent.ANNOUNCEMENT)) {
long date = trJson.getLong("mills");
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
if (date > now - 15 * 60 * 1000L && trJson.has("notes") String enteredBy = JsonHelper.safeGetString(json, "enteredBy", "");
&& !(trJson.has("enteredBy") && trJson.getString("enteredBy").equals(SP.getString("careportal_enteredby", "AndroidAPS")))) { String notes = JsonHelper.safeGetString(json, "notes", "");
Notification announcement = new Notification(Notification.NSANNOUNCEMENT, trJson.getString("notes"), Notification.ANNOUNCEMENT, 60); 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)); 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) { private void handleNewSMS(Intent intent) {
Bundle bundle = intent.getExtras(); Bundle bundle = intent.getExtras();
if (bundle == null) return; if (bundle == null) return;

View file

@ -37,6 +37,8 @@ public interface Intents {
String EXTRA_SENSOR_BATTERY = "com.eveningoutpost.dexdrip.Extras.SensorBattery"; String EXTRA_SENSOR_BATTERY = "com.eveningoutpost.dexdrip.Extras.SensorBattery";
String EXTRA_TIMESTAMP = "com.eveningoutpost.dexdrip.Extras.Time"; String EXTRA_TIMESTAMP = "com.eveningoutpost.dexdrip.Extras.Time";
String EXTRA_RAW = "com.eveningoutpost.dexdrip.Extras.Raw"; 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"; String ACTION_NEW_BG_ESTIMATE_NO_DATA = "com.eveningoutpost.dexdrip.BgEstimateNoData";

View file

@ -1,11 +1,9 @@
package info.nightscout.androidaps.plugins.PumpDanaR.activities; package info.nightscout.androidaps;
import android.app.Activity; import android.app.Activity;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.Rect; import android.graphics.Rect;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.LinearLayoutManager;
import android.text.TextUtils; import android.text.TextUtils;
import android.view.KeyEvent; import android.view.KeyEvent;
@ -35,21 +33,26 @@ import java.util.Date;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.db.DanaRHistoryRecord; import info.nightscout.androidaps.db.DanaRHistoryRecord;
import info.nightscout.androidaps.db.TDD;
import info.nightscout.androidaps.events.EventPumpStatusChanged; import info.nightscout.androidaps.events.EventPumpStatusChanged;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin;
import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes; import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes;
import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRSyncStatus; 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.androidaps.queue.Callback;
import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.SP; import info.nightscout.utils.SP;
import info.nightscout.utils.SafeParse; import info.nightscout.utils.SafeParse;
public class DanaRStatsActivity extends Activity { public class TDDStatsActivity extends Activity {
private static Logger log = LoggerFactory.getLogger(DanaRStatsActivity.class); private static Logger log = LoggerFactory.getLogger(TDDStatsActivity.class);
TextView statusView, statsMessage, totalBaseBasal2; TextView statusView, statsMessage, totalBaseBasal2;
EditText totalBaseBasal; EditText totalBaseBasal;
@ -60,10 +63,10 @@ public class DanaRStatsActivity extends Activity {
double magicNumber; double magicNumber;
DecimalFormat decimalFormat; DecimalFormat decimalFormat;
List<DanaRHistoryRecord> historyList = new ArrayList<>(); List<TDD> historyList = new ArrayList<>();
List<DanaRHistoryRecord> dummies; List<TDD> dummies;
public DanaRStatsActivity() { public TDDStatsActivity() {
super(); super();
} }
@ -126,6 +129,9 @@ public class DanaRStatsActivity extends Activity {
} }
totalBaseBasal.setText(TBB); totalBaseBasal.setText(TBB);
if (!ConfigBuilderPlugin.getActivePump().getPumpDescription().needsManualTDDLoad)
reloadButton.setVisibility(View.GONE);
// stats table // stats table
tl = (TableLayout) findViewById(R.id.main_table); tl = (TableLayout) findViewById(R.id.main_table);
TableRow tr_head = new TableRow(this); TableRow tr_head = new TableRow(this);
@ -232,10 +238,10 @@ public class DanaRStatsActivity extends Activity {
statsMessage.setText(getString(R.string.danar_stats_warning_Message)); statsMessage.setText(getString(R.string.danar_stats_warning_Message));
} }
}); });
ConfigBuilderPlugin.getCommandQueue().loadHistory(RecordTypes.RECORD_TYPE_DAILY, new Callback() { ConfigBuilderPlugin.getCommandQueue().loadTDDs( new Callback() {
@Override @Override
public void run() { public void run() {
loadDataFromDB(RecordTypes.RECORD_TYPE_DAILY); loadDataFromDB();
runOnUiThread(new Runnable() { runOnUiThread(new Runnable() {
@Override @Override
public void run() { public void run() {
@ -268,18 +274,18 @@ public class DanaRStatsActivity extends Activity {
} else { } else {
SP.putString("TBB", totalBaseBasal.getText().toString()); SP.putString("TBB", totalBaseBasal.getText().toString());
TBB = SP.getString("TBB", ""); TBB = SP.getString("TBB", "");
loadDataFromDB(RecordTypes.RECORD_TYPE_DAILY); loadDataFromDB();
InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(totalBaseBasal.getWindowToken(), 0); imm.hideSoftInputFromWindow(totalBaseBasal.getWindowToken(), 0);
} }
} }
}); });
loadDataFromDB(RecordTypes.RECORD_TYPE_DAILY); loadDataFromDB();
} }
private void loadDataFromDB(byte type) { private void loadDataFromDB() {
historyList = MainApp.getDbHelper().getDanaRHistoryRecordsByType(type); historyList = MainApp.getDbHelper().getTDDs();
//only use newest 10 //only use newest 10
historyList = historyList.subList(0, Math.min(10, historyList.size())); historyList = historyList.subList(0, Math.min(10, historyList.size()));
@ -288,24 +294,24 @@ public class DanaRStatsActivity extends Activity {
dummies = new LinkedList(); dummies = new LinkedList();
DateFormat df = new SimpleDateFormat("dd.MM."); DateFormat df = new SimpleDateFormat("dd.MM.");
for (int i = 0; i < historyList.size() - 1; i++) { for (int i = 0; i < historyList.size() - 1; i++) {
DanaRHistoryRecord elem1 = historyList.get(i); TDD elem1 = historyList.get(i);
DanaRHistoryRecord elem2 = historyList.get(i + 1); TDD elem2 = historyList.get(i + 1);
if (!df.format(new Date(elem1.recordDate)).equals(df.format(new Date(elem2.recordDate + 25 * 60 * 60 * 1000)))) { if (!df.format(new Date(elem1.date)).equals(df.format(new Date(elem2.date + 25 * 60 * 60 * 1000)))) {
DanaRHistoryRecord dummy = new DanaRHistoryRecord(); TDD dummy = new TDD();
dummy.recordDate = elem1.recordDate - 24 * 60 * 60 * 1000; dummy.date = elem1.date - 24 * 60 * 60 * 1000;
dummy.recordDailyBasal = elem1.recordDailyBasal / 2; dummy.basal = elem1.basal / 2;
dummy.recordDailyBolus = elem1.recordDailyBolus / 2; dummy.bolus = elem1.bolus / 2;
dummies.add(dummy); dummies.add(dummy);
elem1.recordDailyBasal /= 2; elem1.basal /= 2;
elem1.recordDailyBolus /= 2; elem1.bolus /= 2;
} }
} }
historyList.addAll(dummies); historyList.addAll(dummies);
Collections.sort(historyList, new Comparator<DanaRHistoryRecord>() { Collections.sort(historyList, new Comparator<TDD>() {
@Override @Override
public int compare(DanaRHistoryRecord lhs, DanaRHistoryRecord rhs) { public int compare(TDD lhs, TDD rhs) {
return (int) (rhs.recordDate - lhs.recordDate); return (int) (rhs.date - lhs.date);
} }
}); });
@ -333,11 +339,13 @@ public class DanaRStatsActivity extends Activity {
double weighted05 = 0d; double weighted05 = 0d;
double weighted07 = 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 // 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 (i % 2 != 0) tr.setBackgroundColor(Color.DKGRAY);
if (dummies.contains(record)) { if (dummies.contains(record)) {
tr.setBackgroundColor(Color.argb(125, 255, 0, 0)); tr.setBackgroundColor(Color.argb(125, 255, 0, 0));
@ -348,31 +356,31 @@ public class DanaRStatsActivity extends Activity {
TableLayout.LayoutParams.WRAP_CONTENT)); TableLayout.LayoutParams.WRAP_CONTENT));
// Here create the TextView dynamically // Here create the TextView dynamically
TextView labelDATE = new TextView(DanaRStatsActivity.this); TextView labelDATE = new TextView(TDDStatsActivity.this);
labelDATE.setId(200 + i); labelDATE.setId(200 + i);
labelDATE.setText(df.format(new Date(record.recordDate))); labelDATE.setText(df.format(new Date(record.date)));
labelDATE.setTextColor(Color.WHITE); labelDATE.setTextColor(Color.WHITE);
tr.addView(labelDATE); tr.addView(labelDATE);
TextView labelBASAL = new TextView(DanaRStatsActivity.this); TextView labelBASAL = new TextView(TDDStatsActivity.this);
labelBASAL.setId(300 + i); labelBASAL.setId(300 + i);
labelBASAL.setText(DecimalFormatter.to2Decimal(record.recordDailyBasal) + " U"); labelBASAL.setText(DecimalFormatter.to2Decimal(record.basal) + " U");
labelBASAL.setTextColor(Color.WHITE); labelBASAL.setTextColor(Color.WHITE);
tr.addView(labelBASAL); tr.addView(labelBASAL);
TextView labelBOLUS = new TextView(DanaRStatsActivity.this); TextView labelBOLUS = new TextView(TDDStatsActivity.this);
labelBOLUS.setId(400 + i); labelBOLUS.setId(400 + i);
labelBOLUS.setText(DecimalFormatter.to2Decimal(record.recordDailyBolus) + " U"); labelBOLUS.setText(DecimalFormatter.to2Decimal(record.bolus) + " U");
labelBOLUS.setTextColor(Color.WHITE); labelBOLUS.setTextColor(Color.WHITE);
tr.addView(labelBOLUS); tr.addView(labelBOLUS);
TextView labelTDD = new TextView(DanaRStatsActivity.this); TextView labelTDD = new TextView(TDDStatsActivity.this);
labelTDD.setId(500 + i); labelTDD.setId(500 + i);
labelTDD.setText(DecimalFormatter.to2Decimal(tdd) + " U"); labelTDD.setText(DecimalFormatter.to2Decimal(tdd) + " U");
labelTDD.setTextColor(Color.WHITE); labelTDD.setTextColor(Color.WHITE);
tr.addView(labelTDD); tr.addView(labelTDD);
TextView labelRATIO = new TextView(DanaRStatsActivity.this); TextView labelRATIO = new TextView(TDDStatsActivity.this);
labelRATIO.setId(600 + i); labelRATIO.setId(600 + i);
labelRATIO.setText(Math.round(100 * tdd / magicNumber) + " %"); labelRATIO.setText(Math.round(100 * tdd / magicNumber) + " %");
labelRATIO.setTextColor(Color.WHITE); labelRATIO.setTextColor(Color.WHITE);
@ -383,11 +391,23 @@ public class DanaRStatsActivity extends Activity {
TableLayout.LayoutParams.MATCH_PARENT, TableLayout.LayoutParams.MATCH_PARENT,
TableLayout.LayoutParams.WRAP_CONTENT)); 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++; i++;
sum = sum + record.getTotal();
// Create the cumtable row // Create the cumtable row
TableRow ctr = new TableRow(DanaRStatsActivity.this); TableRow ctr = new TableRow(TDDStatsActivity.this);
if (i % 2 == 0) ctr.setBackgroundColor(Color.DKGRAY); if (i % 2 == 0) ctr.setBackgroundColor(Color.DKGRAY);
ctr.setId(700 + i); ctr.setId(700 + i);
ctr.setLayoutParams(new TableLayout.LayoutParams( ctr.setLayoutParams(new TableLayout.LayoutParams(
@ -395,19 +415,19 @@ public class DanaRStatsActivity extends Activity {
TableLayout.LayoutParams.WRAP_CONTENT)); TableLayout.LayoutParams.WRAP_CONTENT));
// Here create the TextView dynamically // Here create the TextView dynamically
TextView labelDAYS = new TextView(DanaRStatsActivity.this); TextView labelDAYS = new TextView(TDDStatsActivity.this);
labelDAYS.setId(800 + i); labelDAYS.setId(800 + i);
labelDAYS.setText("" + i); labelDAYS.setText("" + i);
labelDAYS.setTextColor(Color.WHITE); labelDAYS.setTextColor(Color.WHITE);
ctr.addView(labelDAYS); ctr.addView(labelDAYS);
TextView labelCUMTDD = new TextView(DanaRStatsActivity.this); TextView labelCUMTDD = new TextView(TDDStatsActivity.this);
labelCUMTDD.setId(900 + i); labelCUMTDD.setId(900 + i);
labelCUMTDD.setText(DecimalFormatter.to2Decimal(sum / i) + " U"); labelCUMTDD.setText(DecimalFormatter.to2Decimal(sum / i) + " U");
labelCUMTDD.setTextColor(Color.WHITE); labelCUMTDD.setTextColor(Color.WHITE);
ctr.addView(labelCUMTDD); ctr.addView(labelCUMTDD);
TextView labelCUMRATIO = new TextView(DanaRStatsActivity.this); TextView labelCUMRATIO = new TextView(TDDStatsActivity.this);
labelCUMRATIO.setId(1000 + i); labelCUMRATIO.setId(1000 + i);
labelCUMRATIO.setText(Math.round(100 * sum / i / magicNumber) + " %"); labelCUMRATIO.setText(Math.round(100 * sum / i / magicNumber) + " %");
labelCUMRATIO.setTextColor(Color.WHITE); labelCUMRATIO.setTextColor(Color.WHITE);
@ -419,7 +439,7 @@ public class DanaRStatsActivity extends Activity {
TableLayout.LayoutParams.WRAP_CONTENT)); 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.setVisibility(View.VISIBLE);
statsMessage.setText(getString(R.string.danar_stats_olddata_Message)); statsMessage.setText(getString(R.string.danar_stats_olddata_Message));
@ -427,12 +447,17 @@ public class DanaRStatsActivity extends Activity {
tl.setBackgroundColor(Color.TRANSPARENT); 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); Collections.reverse(historyList);
i = 0; i = 0;
for (DanaRHistoryRecord record : historyList) { for (TDD record : historyList) {
double tdd = record.recordDailyBolus + record.recordDailyBasal; double tdd = record.getTotal();
if (i == 0) { if (i == 0) {
weighted03 = tdd; weighted03 = tdd;
weighted05 = tdd; weighted05 = tdd;
@ -447,7 +472,7 @@ public class DanaRStatsActivity extends Activity {
} }
// Create the exptable row // Create the exptable row
TableRow etr = new TableRow(DanaRStatsActivity.this); TableRow etr = new TableRow(TDDStatsActivity.this);
if (i % 2 != 0) etr.setBackgroundColor(Color.DKGRAY); if (i % 2 != 0) etr.setBackgroundColor(Color.DKGRAY);
etr.setId(1100 + i); etr.setId(1100 + i);
etr.setLayoutParams(new TableLayout.LayoutParams( etr.setLayoutParams(new TableLayout.LayoutParams(
@ -455,13 +480,13 @@ public class DanaRStatsActivity extends Activity {
TableLayout.LayoutParams.WRAP_CONTENT)); TableLayout.LayoutParams.WRAP_CONTENT));
// Here create the TextView dynamically // Here create the TextView dynamically
TextView labelWEIGHT = new TextView(DanaRStatsActivity.this); TextView labelWEIGHT = new TextView(TDDStatsActivity.this);
labelWEIGHT.setId(1200 + i); labelWEIGHT.setId(1200 + i);
labelWEIGHT.setText("0.3\n" + "0.5\n" + "0.7"); labelWEIGHT.setText("0.3\n" + "0.5\n" + "0.7");
labelWEIGHT.setTextColor(Color.WHITE); labelWEIGHT.setTextColor(Color.WHITE);
etr.addView(labelWEIGHT); etr.addView(labelWEIGHT);
TextView labelEXPTDD = new TextView(DanaRStatsActivity.this); TextView labelEXPTDD = new TextView(TDDStatsActivity.this);
labelEXPTDD.setId(1300 + i); labelEXPTDD.setId(1300 + i);
labelEXPTDD.setText(DecimalFormatter.to2Decimal(weighted03) labelEXPTDD.setText(DecimalFormatter.to2Decimal(weighted03)
+ " U\n" + DecimalFormatter.to2Decimal(weighted05) + " U\n" + DecimalFormatter.to2Decimal(weighted05)
@ -469,7 +494,7 @@ public class DanaRStatsActivity extends Activity {
labelEXPTDD.setTextColor(Color.WHITE); labelEXPTDD.setTextColor(Color.WHITE);
etr.addView(labelEXPTDD); etr.addView(labelEXPTDD);
TextView labelEXPRATIO = new TextView(DanaRStatsActivity.this); TextView labelEXPRATIO = new TextView(TDDStatsActivity.this);
labelEXPRATIO.setId(1400 + i); labelEXPRATIO.setId(1400 + i);
labelEXPRATIO.setText(Math.round(100 * weighted03 / magicNumber) + " %\n" labelEXPRATIO.setText(Math.round(100 * weighted03 / magicNumber) + " %\n"
+ Math.round(100 * weighted05 / 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))))));
}
} }

View file

@ -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;
}
}

View file

@ -2,14 +2,14 @@ package info.nightscout.androidaps.data;
import android.content.Context; import android.content.Context;
import com.rits.cloning.Cloner;
import org.json.JSONObject; import org.json.JSONObject;
import java.util.Date; import java.util.Date;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.db.CareportalEvent; import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.Source;
import info.nightscout.androidaps.interfaces.InsulinInterface;
/** /**
* Created by mike on 29.05.2017. * Created by mike on 29.05.2017.
@ -30,6 +30,27 @@ public class DetailedBolusInfo {
public long pumpId = 0; // id of record if comming from pump history (not a newly created treatment) 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 boolean isSMB = false; // is a Super-MicroBolus
public long deliverAt = 0; // SMB should be delivered within 1 min from this time 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 @Override
public String toString() { public String toString() {

View file

@ -21,6 +21,7 @@ import java.util.List;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.db.BgReading;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.Round; import info.nightscout.utils.Round;
@ -40,17 +41,10 @@ public class GlucoseStatus {
@Override @Override
public String toString() { public String toString() {
return MainApp.sResources.getString(R.string.glucose) + " " + DecimalFormatter.to0Decimal(glucose) + " mg/dl\n" + return MainApp.gs(R.string.glucose) + " " + DecimalFormatter.to0Decimal(glucose) + " mg/dl\n" +
MainApp.sResources.getString(R.string.delta) + " " + DecimalFormatter.to0Decimal(delta) + " mg/dl\n" + MainApp.gs(R.string.delta) + " " + DecimalFormatter.to0Decimal(delta) + " mg/dl\n" +
MainApp.sResources.getString(R.string.short_avgdelta) + " " + DecimalFormatter.to2Decimal(short_avgdelta) + " mg/dl\n" + MainApp.gs(R.string.short_avgdelta) + " " + DecimalFormatter.to2Decimal(short_avgdelta) + " mg/dl\n" +
MainApp.sResources.getString(R.string.long_avgdelta) + " " + DecimalFormatter.to2Decimal(long_avgdelta) + " mg/dl"; MainApp.gs(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");
} }
public GlucoseStatus() { public GlucoseStatus() {
@ -75,11 +69,15 @@ public class GlucoseStatus {
@Nullable @Nullable
public static GlucoseStatus getGlucoseStatusData(boolean allowOldData) { public static GlucoseStatus getGlucoseStatusData(boolean allowOldData) {
// load 45min // 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); List<BgReading> data = MainApp.getDbHelper().getBgreadingsDataFromTime(fromtime, false);
int sizeRecords = data.size(); 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; return null;
} }
@ -87,13 +85,14 @@ public class GlucoseStatus {
long now_date = now.date; long now_date = now.date;
double change; double change;
if (sizeRecords < 2) { if (sizeRecords == 1) {
GlucoseStatus status = new GlucoseStatus(); GlucoseStatus status = new GlucoseStatus();
status.glucose = now.value; status.glucose = now.value;
status.short_avgdelta = 0d; status.short_avgdelta = 0d;
status.delta = 0d; status.delta = 0d;
status.long_avgdelta = 0d; status.long_avgdelta = 0d;
status.avgdelta = 0d; // for OpenAPS MA status.avgdelta = 0d; // for OpenAPS MA
status.date = now_date;
return status.round(); return status.round();
} }

View file

@ -16,7 +16,11 @@ import info.nightscout.androidaps.interfaces.Interval;
public abstract class Intervals<T extends 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() { public synchronized Intervals reset() {
rawData = new LongSparseArray<T>(); 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 * The List must be sorted by `T.start()` in ascending order
* */
* */
public synchronized void add(List<T> list) { public synchronized void add(List<T> list) {
for (T interval : list) { for (T interval : list) {
rawData.put(interval.start(), interval); rawData.put(interval.start(), interval);
@ -36,6 +39,10 @@ public abstract class Intervals<T extends Interval> {
merge(); merge();
} }
public synchronized void add(T interval) {
rawData.put(interval.start(), interval);
merge();
}
public synchronized List<T> getList() { public synchronized List<T> getList() {
@ -86,5 +93,4 @@ public abstract class Intervals<T extends Interval> {
} }
} }

View file

@ -7,6 +7,16 @@ public class Iob {
public double iobContrib = 0d; public double iobContrib = 0d;
public double activityContrib = 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) { public Iob plus(Iob iob) {
iobContrib += iob.iobContrib; iobContrib += iob.iobContrib;
activityContrib += iob.activityContrib; activityContrib += iob.activityContrib;

View file

@ -1,5 +1,7 @@
package info.nightscout.androidaps.data; package info.nightscout.androidaps.data;
import com.rits.cloning.Cloner;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -22,9 +24,6 @@ public class IobTotal {
// oref1 // oref1
public long lastBolusTime; public long lastBolusTime;
public long lastTempDate;
public int lastTempDuration;
public double lastTempRate;
public IobTotal iobWithZeroTemp; public IobTotal iobWithZeroTemp;
public double netInsulin = 0d; // for calculations from temp basals only public double netInsulin = 0d; // for calculations from temp basals only
@ -35,20 +34,9 @@ public class IobTotal {
long time; long time;
public IobTotal clone() { public IobTotal copy() {
IobTotal copy = new IobTotal(time); Cloner cloner = new Cloner();
copy.iob = iob; return cloner.deepClone(this);
copy.activity = activity;
copy.bolussnooze = bolussnooze;
copy.basaliob = basaliob;
copy.netbasalinsulin = netbasalinsulin;
copy.hightempinsulin = hightempinsulin;
copy.lastBolusTime = lastBolusTime;
copy.lastTempDate = lastTempDate;
copy.lastTempDuration = lastTempDuration;
copy.lastTempRate = lastTempRate;
copy.iobWithZeroTemp = iobWithZeroTemp;
return copy;
} }
public IobTotal(long time) { public IobTotal(long time) {
@ -82,10 +70,9 @@ public class IobTotal {
result.basaliob = bolusIOB.basaliob + basalIob.basaliob; result.basaliob = bolusIOB.basaliob + basalIob.basaliob;
result.netbasalinsulin = bolusIOB.netbasalinsulin + basalIob.netbasalinsulin; result.netbasalinsulin = bolusIOB.netbasalinsulin + basalIob.netbasalinsulin;
result.hightempinsulin = basalIob.hightempinsulin + bolusIOB.hightempinsulin; result.hightempinsulin = basalIob.hightempinsulin + bolusIOB.hightempinsulin;
result.netInsulin = basalIob.netInsulin + bolusIOB.netInsulin;
result.extendedBolusInsulin = basalIob.extendedBolusInsulin + bolusIOB.extendedBolusInsulin;
result.lastBolusTime = bolusIOB.lastBolusTime; result.lastBolusTime = bolusIOB.lastBolusTime;
result.lastTempDate = basalIob.lastTempDate;
result.lastTempRate = basalIob.lastTempRate;
result.lastTempDuration = basalIob.lastTempDuration;
result.iobWithZeroTemp = basalIob.iobWithZeroTemp; result.iobWithZeroTemp = basalIob.iobWithZeroTemp;
return result; return result;
} }
@ -97,6 +84,8 @@ public class IobTotal {
this.basaliob = Round.roundTo(this.basaliob, 0.001); this.basaliob = Round.roundTo(this.basaliob, 0.001);
this.netbasalinsulin = Round.roundTo(this.netbasalinsulin, 0.001); this.netbasalinsulin = Round.roundTo(this.netbasalinsulin, 0.001);
this.hightempinsulin = Round.roundTo(this.hightempinsulin, 0.001); this.hightempinsulin = Round.roundTo(this.hightempinsulin, 0.001);
this.netInsulin = Round.roundTo(this.netInsulin, 0.001);
this.extendedBolusInsulin = Round.roundTo(this.extendedBolusInsulin, 0.001);
return this; return this;
} }

View file

@ -11,4 +11,5 @@ public class MealData {
public double slopeFromMinDeviation = 999; public double slopeFromMinDeviation = 999;
public long lastBolusTime; public long lastBolusTime;
public long lastCarbTime = 0L; public long lastCarbTime = 0L;
public double usedMinCarbsImpact = 0d;
} }

View file

@ -2,7 +2,9 @@ package info.nightscout.androidaps.data;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.v4.util.LongSparseArray;
import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.interfaces.Interval; import info.nightscout.androidaps.interfaces.Interval;
/** /**
@ -11,6 +13,14 @@ import info.nightscout.androidaps.interfaces.Interval;
public class NonOverlappingIntervals<T extends Interval> extends Intervals<T> { 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() { protected synchronized void merge() {
for (int index = 0; index < rawData.size() - 1; index++) { for (int index = 0; index < rawData.size() - 1; index++) {
Interval i = rawData.valueAt(index); Interval i = rawData.valueAt(index);
@ -27,4 +37,5 @@ public class NonOverlappingIntervals<T extends Interval> extends Intervals<T> {
if (index >= 0) return rawData.valueAt(index); if (index >= 0) return rawData.valueAt(index);
return null; return null;
} }
} }

View file

@ -11,6 +11,14 @@ import info.nightscout.androidaps.interfaces.Interval;
public class OverlappingIntervals<T extends Interval> extends Intervals<T> { 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() { protected synchronized void merge() {
boolean needToCut = false; boolean needToCut = false;
long cutTime = 0; long cutTime = 0;

View file

@ -2,8 +2,6 @@ package info.nightscout.androidaps.data;
import android.support.v4.util.LongSparseArray; import android.support.v4.util.LongSparseArray;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
@ -14,46 +12,49 @@ import java.text.DecimalFormat;
import java.util.Calendar; import java.util.Calendar;
import java.util.TimeZone; import java.util.TimeZone;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.Overview.notifications.Notification; import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
import info.nightscout.utils.DateUtil; import info.nightscout.utils.DateUtil;
import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.FabricPrivacy; import info.nightscout.utils.FabricPrivacy;
import info.nightscout.utils.ToastUtils;
public class Profile { public class Profile {
private static Logger log = LoggerFactory.getLogger(Profile.class); private static Logger log = LoggerFactory.getLogger(Profile.class);
private JSONObject json; private JSONObject json;
private String units = null; private String units;
private double dia = Constants.defaultDIA; private double dia;
private TimeZone timeZone = TimeZone.getDefault(); private TimeZone timeZone;
private JSONArray isf; 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 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 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 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 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 percentage;
private int timeshift = 0; private int timeshift;
private boolean isValid = true; protected boolean isValid;
private boolean isValidated = false; protected boolean isValidated;
// Default constructor for tests
protected Profile() {
}
// Constructor from profileStore JSON
public Profile(JSONObject json, String units) { public Profile(JSONObject json, String units) {
this(json, 100, 0); init(json, 100, 0);
if (this.units == null) { if (this.units == null) {
if (units != null) if (units != null)
this.units = units; this.units = units;
@ -65,6 +66,22 @@ public class Profile {
} }
public Profile(JSONObject json, int percentage, int timeshift) { 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.percentage = percentage;
this.timeshift = timeshift; this.timeshift = timeshift;
this.json = json; this.json = json;
@ -78,53 +95,12 @@ public class Profile {
if (json.has("timezone")) if (json.has("timezone"))
timeZone = TimeZone.getTimeZone(json.getString("timezone")); timeZone = TimeZone.getTimeZone(json.getString("timezone"));
isf = json.getJSONArray("sens"); 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"); 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"); 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"); 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"); 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) { } catch (JSONException e) {
log.error("Unhandled exception", e); log.error("Unhandled exception", e);
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.invalidprofile));
isValid = false; isValid = false;
isValidated = true; isValidated = true;
} }
@ -133,7 +109,7 @@ public class Profile {
public String log() { public String log() {
String ret = "\n"; String ret = "\n";
for (Integer hour = 0; hour < 24; hour++) { 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 basal value for " + hour + ":00 is " + value + "\n";
} }
ret += "NS units: " + getUnits(); ret += "NS units: " + getUnits();
@ -155,6 +131,10 @@ public class Profile {
} }
// mmol or mg/dl // mmol or mg/dl
public void setUnits(String units) {
this.units = units;
}
public String getUnits() { public String getUnits() {
return units; return units;
} }
@ -164,6 +144,11 @@ public class Profile {
} }
private LongSparseArray<Double> convertToSparseArray(JSONArray array) { private LongSparseArray<Double> convertToSparseArray(JSONArray array) {
if (array == null) {
isValid = false;
return new LongSparseArray<>();
}
double multiplier = getMultiplier(array); double multiplier = getMultiplier(array);
LongSparseArray<Double> sparse = new LongSparseArray<>(); LongSparseArray<Double> sparse = new LongSparseArray<>();
@ -235,7 +220,7 @@ public class Profile {
for (int i = 0; i < basal_v.size(); i++) { for (int i = 0; i < basal_v.size(); i++) {
if (basal_v.valueAt(i) < description.basalMinimumRate) { if (basal_v.valueAt(i) < description.basalMinimumRate) {
basal_v.setValueAt(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 { } else {
@ -249,6 +234,10 @@ public class Profile {
return isValid; 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) { private void validate(LongSparseArray array) {
if (array.size() == 0) { if (array.size() == 0) {
isValid = false; isValid = false;
@ -262,6 +251,7 @@ public class Profile {
} }
} }
/*
private Double getValueToTime(JSONArray array, Integer timeAsSeconds) { private Double getValueToTime(JSONArray array, Integer timeAsSeconds) {
Double lastValue = null; Double lastValue = null;
@ -281,11 +271,12 @@ public class Profile {
} }
return lastValue; return lastValue;
} }
*/
Integer getShitfTimeSecs(Integer originalTime) { Integer getShitfTimeSecs(Integer originalTime) {
Integer shiftedTime = originalTime + timeshift * 60 * 60; Integer shiftedTime = originalTime + timeshift * 60 * 60;
shiftedTime = (shiftedTime + 24 * 60 * 60) % (24 * 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); log.debug("(Sec) Original time: " + originalTime + " ShiftedTime: " + shiftedTime);
return shiftedTime; return shiftedTime;
} }
@ -322,7 +313,7 @@ public class Profile {
return multiplier; return multiplier;
} }
private Double getValueToTime(LongSparseArray<Double> array, Integer timeAsSeconds) { private double getValueToTime(LongSparseArray<Double> array, Integer timeAsSeconds) {
Double lastValue = null; Double lastValue = null;
for (Integer index = 0; index < array.size(); index++) { for (Integer index = 0; index < array.size(); index++) {
@ -337,7 +328,7 @@ public class Profile {
return lastValue; return lastValue;
} }
private String format_HH_MM(Integer timeAsSeconds) { protected String format_HH_MM(Integer timeAsSeconds) {
String time; String time;
int hour = timeAsSeconds / 60 / 60; int hour = timeAsSeconds / 60 / 60;
int minutes = (timeAsSeconds - hour * 60 * 60) / 60; int minutes = (timeAsSeconds - hour * 60 * 60) / 60;
@ -364,51 +355,55 @@ public class Profile {
return retValue; return retValue;
} }
public Double getIsf() { public double getIsf() {
return getIsf(secondsFromMidnight(System.currentTimeMillis())); return getIsfTimeFromMidnight(secondsFromMidnight(System.currentTimeMillis()));
} }
public Double getIsf(long time) { public double getIsf(long time) {
return getIsf(secondsFromMidnight(time)); return getIsfTimeFromMidnight(secondsFromMidnight(time));
} }
public Double getIsf(Integer timeAsSeconds) { double getIsfTimeFromMidnight(int timeAsSeconds) {
if (isf_v == null) if (isf_v == null)
isf_v = convertToSparseArray(isf); isf_v = convertToSparseArray(isf);
return getValueToTime(isf_v, timeAsSeconds); return getValueToTime(isf_v, timeAsSeconds);
} }
public String getIsfList() { public String getIsfList() {
if (isf_v == null)
isf_v = convertToSparseArray(isf);
return getValuesList(isf_v, null, new DecimalFormat("0.0"), getUnits() + "/U"); return getValuesList(isf_v, null, new DecimalFormat("0.0"), getUnits() + "/U");
} }
public Double getIc() { public double getIc() {
return getIc(secondsFromMidnight(System.currentTimeMillis())); return getIcTimeFromMidnight(secondsFromMidnight(System.currentTimeMillis()));
} }
public Double getIc(long time) { public double getIc(long time) {
return getIc(secondsFromMidnight(time)); return getIcTimeFromMidnight(secondsFromMidnight(time));
} }
public Double getIc(Integer timeAsSeconds) { public double getIcTimeFromMidnight(int timeAsSeconds) {
if (ic_v == null) if (ic_v == null)
ic_v = convertToSparseArray(ic); ic_v = convertToSparseArray(ic);
return getValueToTime(ic_v, timeAsSeconds); return getValueToTime(ic_v, timeAsSeconds);
} }
public String getIcList() { public String getIcList() {
if (ic_v == null)
ic_v = convertToSparseArray(ic);
return getValuesList(ic_v, null, new DecimalFormat("0.0"), "g/U"); return getValuesList(ic_v, null, new DecimalFormat("0.0"), "g/U");
} }
public Double getBasal() { public double getBasal() {
return getBasal(secondsFromMidnight(System.currentTimeMillis())); return getBasalTimeFromMidnight(secondsFromMidnight(System.currentTimeMillis()));
} }
public Double getBasal(long time) { public double getBasal(long time) {
return getBasal(secondsFromMidnight(time)); return getBasalTimeFromMidnight(secondsFromMidnight(time));
} }
public synchronized Double getBasal(Integer timeAsSeconds) { public synchronized double getBasalTimeFromMidnight(int timeAsSeconds) {
if (basal_v == null) { if (basal_v == null) {
basal_v = convertToSparseArray(basal); basal_v = convertToSparseArray(basal);
} }
@ -418,17 +413,17 @@ public class Profile {
public String getBasalList() { public String getBasalList() {
if (basal_v == null) if (basal_v == null)
basal_v = convertToSparseArray(basal); basal_v = convertToSparseArray(basal);
return getValuesList(basal_v, null, new DecimalFormat("0.00"), "U"); return getValuesList(basal_v, null, new DecimalFormat("0.00"), "U/h");
} }
public class BasalValue { public class BasalValue {
public BasalValue(Integer timeAsSeconds, Double value) { public BasalValue(int timeAsSeconds, double value) {
this.timeAsSeconds = timeAsSeconds; this.timeAsSeconds = timeAsSeconds;
this.value = value; this.value = value;
} }
public Integer timeAsSeconds; public int timeAsSeconds;
public Double value; public double value;
} }
public synchronized BasalValue[] getBasalValues() { public synchronized BasalValue[] getBasalValues() {
@ -438,7 +433,7 @@ public class Profile {
for (Integer index = 0; index < basal_v.size(); index++) { for (Integer index = 0; index < basal_v.size(); index++) {
Integer tas = (int) basal_v.keyAt(index); Integer tas = (int) basal_v.keyAt(index);
Double value = basal_v.valueAt(index); double value = basal_v.valueAt(index);
ret[index] = new BasalValue(tas, value); ret[index] = new BasalValue(tas, value);
} }
return ret; return ret;
@ -448,52 +443,56 @@ public class Profile {
return getTarget(secondsFromMidnight(System.currentTimeMillis())); return getTarget(secondsFromMidnight(System.currentTimeMillis()));
} }
private double getTarget(Integer time) { protected double getTarget(int timeAsSeconds) {
return (getTargetLow(time) + getTargetHigh(time))/2; return (getTargetLowTimeFromMidnight(timeAsSeconds) + getTargetHighTimeFromMidnight(timeAsSeconds))/2;
} }
public Double getTargetLow() { public double getTargetLow() {
return getTargetLow(secondsFromMidnight(System.currentTimeMillis())); return getTargetLowTimeFromMidnight(secondsFromMidnight(System.currentTimeMillis()));
} }
public Double getTargetLow(long time) { public double getTargetLow(long time) {
return getTargetLow(secondsFromMidnight(time)); return getTargetLowTimeFromMidnight(secondsFromMidnight(time));
} }
public Double getTargetLow(Integer timeAsSeconds) { public double getTargetLowTimeFromMidnight(int timeAsSeconds) {
if (targetLow_v == null) if (targetLow_v == null)
targetLow_v = convertToSparseArray(targetLow); targetLow_v = convertToSparseArray(targetLow);
return getValueToTime(targetLow_v, timeAsSeconds); return getValueToTime(targetLow_v, timeAsSeconds);
} }
public Double getTargetHigh() { public double getTargetHigh() {
return getTargetHigh(secondsFromMidnight(System.currentTimeMillis())); return getTargetHighTimeFromMidnight(secondsFromMidnight(System.currentTimeMillis()));
} }
public Double getTargetHigh(long time) { public double getTargetHigh(long time) {
return getTargetHigh(secondsFromMidnight(time)); return getTargetHighTimeFromMidnight(secondsFromMidnight(time));
} }
public Double getTargetHigh(Integer timeAsSeconds) { public double getTargetHighTimeFromMidnight(int timeAsSeconds) {
if (targetHigh_v == null) if (targetHigh_v == null)
targetHigh_v = convertToSparseArray(targetHigh); targetHigh_v = convertToSparseArray(targetHigh);
return getValueToTime(targetHigh_v, timeAsSeconds); return getValueToTime(targetHigh_v, timeAsSeconds);
} }
public String getTargetList() { 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()); return getValuesList(targetLow_v, targetHigh_v, new DecimalFormat("0.0"), getUnits());
} }
public double getMaxDailyBasal() { public double getMaxDailyBasal() {
Double max = 0d; double max = 0d;
for (Integer hour = 0; hour < 24; hour++) { for (int hour = 0; hour < 24; hour++) {
double value = getBasal((Integer) (hour * 60 * 60)); double value = getBasalTimeFromMidnight((Integer) (hour * 60 * 60));
if (value > max) max = value; if (value > max) max = value;
} }
return max; return max;
} }
public static Integer secondsFromMidnight() { public static int secondsFromMidnight() {
Calendar c = Calendar.getInstance(); Calendar c = Calendar.getInstance();
long now = c.getTimeInMillis(); long now = c.getTimeInMillis();
c.set(Calendar.HOUR_OF_DAY, 0); c.set(Calendar.HOUR_OF_DAY, 0);
@ -504,7 +503,7 @@ public class Profile {
return (int) (passed / 1000); return (int) (passed / 1000);
} }
public static Integer secondsFromMidnight(long date) { public static int secondsFromMidnight(long date) {
Calendar c = Calendar.getInstance(); Calendar c = Calendar.getInstance();
c.setTimeInMillis(date); c.setTimeInMillis(date);
c.set(Calendar.HOUR_OF_DAY, 0); c.set(Calendar.HOUR_OF_DAY, 0);
@ -515,22 +514,22 @@ public class Profile {
return (int) (passed / 1000); 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; if (units.equals(Constants.MGDL)) return value;
else return value * Constants.MMOLL_TO_MGDL; 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; if (units.equals(Constants.MGDL)) return value * Constants.MGDL_TO_MMOLL;
else return value; 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; if (units.equals(Constants.MGDL)) return value;
else return value * Constants.MGDL_TO_MMOLL; 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; if (units.equals(Constants.MGDL)) return valueInMgdl;
else return valueInMmol; else return valueInMmol;
} }
@ -556,7 +555,7 @@ public class Profile {
public double percentageBasalSum() { public double percentageBasalSum() {
double result = 0d; double result = 0d;
for (int i = 0; i < 24; i++) { for (int i = 0; i < 24; i++) {
result += getBasal((Integer) (i * 60 * 60)); result += getBasalTimeFromMidnight(i * 60 * 60);
} }
return result; return result;
} }
@ -565,7 +564,7 @@ public class Profile {
public double baseBasalSum() { public double baseBasalSum() {
double result = 0d; double result = 0d;
for (int i = 0; i < 24; i++) { 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; return result;
} }

View file

@ -3,10 +3,14 @@ package info.nightscout.androidaps.data;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.v4.util.LongSparseArray; import android.support.v4.util.LongSparseArray;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import info.nightscout.androidaps.interfaces.Interval; import info.nightscout.androidaps.interfaces.Interval;
import info.nightscout.utils.DateUtil;
/** /**
* Created by mike on 09.05.2017. * 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 // When no interval match the lastest record without duration is used
public class ProfileIntervals<T extends Interval> { 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() { public synchronized ProfileIntervals reset() {
rawData = new LongSparseArray<>(); rawData = new LongSparseArray<>();
@ -25,9 +38,11 @@ public class ProfileIntervals<T extends Interval> {
} }
public synchronized void add(T newInterval) { public synchronized void add(T newInterval) {
if (newInterval.isValid()) {
rawData.put(newInterval.start(), newInterval); rawData.put(newInterval.start(), newInterval);
merge(); merge();
} }
}
public synchronized void add(List<T> list) { public synchronized void add(List<T> list) {
for (T interval : list) { for (T interval : list) {
@ -51,6 +66,13 @@ public class ProfileIntervals<T extends Interval> {
public synchronized Interval getValueToTime(long time) { public synchronized Interval getValueToTime(long time) {
int index = binarySearch(time); int index = binarySearch(time);
if (index >= 0) return rawData.valueAt(index); 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; return null;
} }
@ -107,4 +129,9 @@ public class ProfileIntervals<T extends Interval> {
public synchronized T getReversed(int index) { public synchronized T getReversed(int index) {
return rawData.valueAt(size() - 1 - index); return rawData.valueAt(size() - 1 - index);
} }
@Override
public String toString() {
return rawData.toString();
}
} }

View file

@ -13,7 +13,7 @@ import info.nightscout.androidaps.R;
import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.Round; import info.nightscout.utils.Round;
public class PumpEnactResult extends Object { public class PumpEnactResult {
private static Logger log = LoggerFactory.getLogger(PumpEnactResult.class); private static Logger log = LoggerFactory.getLogger(PumpEnactResult.class);
public boolean success = false; // request was processed successfully (but possible no change was needed) public boolean success = false; // request was processed successfully (but possible no change was needed)
@ -21,14 +21,14 @@ public class PumpEnactResult extends Object {
public String comment = ""; public String comment = "";
// Result of basal change // Result of basal change
public Integer duration = -1; // duration set [minutes] public int duration = -1; // duration set [minutes]
public Double absolute = -1d; // absolute rate [U/h] , isPercent = false 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 percent = -1; // percent of current basal [%] (100% = current basal), isPercent = true
public boolean isPercent = false; // if true percent is used, otherwise absolute public boolean isPercent = false; // if true percent is used, otherwise absolute
public boolean isTempCancel = false; // if true we are caceling temp basal public boolean isTempCancel = false; // if true we are caceling temp basal
// Result of treatment delivery // Result of treatment delivery
public Double bolusDelivered = 0d; // real value of delivered insulin public double bolusDelivered = 0d; // real value of delivered insulin
public Double carbsDelivered = 0d; // real value of delivered carbs public double carbsDelivered = 0d; // real value of delivered carbs
public boolean queued = false; public boolean queued = false;
@ -47,20 +47,21 @@ public class PumpEnactResult extends Object {
return this; return this;
} }
public PumpEnactResult duration(Integer duration) { public PumpEnactResult duration(int duration) {
this.duration = duration; this.duration = duration;
return this; return this;
} }
public PumpEnactResult absolute(Double absolute) { public PumpEnactResult absolute(double absolute) {
this.absolute = absolute; this.absolute = absolute;
return this; return this;
} }
public PumpEnactResult percent(Integer percent) { public PumpEnactResult percent(int percent) {
this.percent = percent; this.percent = percent;
return this; return this;
} }
public PumpEnactResult isPercent(boolean isPercent) { public PumpEnactResult isPercent(boolean isPercent) {
this.isPercent = isPercent; this.isPercent = isPercent;
return this; return this;
@ -71,12 +72,12 @@ public class PumpEnactResult extends Object {
return this; return this;
} }
public PumpEnactResult bolusDelivered(Double bolusDelivered) { public PumpEnactResult bolusDelivered(double bolusDelivered) {
this.bolusDelivered = bolusDelivered; this.bolusDelivered = bolusDelivered;
return this; return this;
} }
public PumpEnactResult carbsDelivered(Double carbsDelivered) { public PumpEnactResult carbsDelivered(double carbsDelivered) {
this.carbsDelivered = carbsDelivered; this.carbsDelivered = carbsDelivered;
return this; return this;
} }
@ -87,74 +88,95 @@ public class PumpEnactResult extends Object {
} }
public String log() { public String log() {
return "Success: " + success + " Enacted: " + enacted + " Comment: " + comment + " Duration: " + duration + " Absolute: " + absolute + " Percent: " + percent + " IsPercent: " + isPercent + " Queued: " + queued; 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() { public String toString() {
String ret = MainApp.sResources.getString(R.string.success) + ": " + success; String ret = MainApp.gs(R.string.success) + ": " + success;
if (enacted) { if (enacted) {
if (isTempCancel) { if (bolusDelivered > 0) {
ret += "\n" + MainApp.sResources.getString(R.string.enacted) + ": " + enacted; ret += "\n" + MainApp.gs(R.string.enacted) + ": " + enacted;
ret += "\n" + MainApp.sResources.getString(R.string.comment) + ": " + comment + "\n" + ret += "\n" + MainApp.gs(R.string.comment) + ": " + comment;
MainApp.sResources.getString(R.string.canceltemp); 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) { } else if (isPercent) {
ret += "\n" + MainApp.sResources.getString(R.string.enacted) + ": " + enacted; ret += "\n" + MainApp.gs(R.string.enacted) + ": " + enacted;
ret += "\n" + MainApp.sResources.getString(R.string.comment) + ": " + comment; if (!comment.isEmpty())
ret += "\n" + MainApp.sResources.getString(R.string.duration) + ": " + duration + " min"; ret += "\n" + MainApp.gs(R.string.comment) + ": " + comment;
ret += "\n" + MainApp.sResources.getString(R.string.percent) + ": " + percent + "%"; ret += "\n" + MainApp.gs(R.string.duration) + ": " + duration + " min";
ret += "\n" + MainApp.gs(R.string.percent) + ": " + percent + "%";
} else { } else {
ret += "\n" + MainApp.sResources.getString(R.string.enacted) + ": " + enacted; ret += "\n" + MainApp.gs(R.string.enacted) + ": " + enacted;
ret += "\n" + MainApp.sResources.getString(R.string.comment) + ": " + comment; if (!comment.isEmpty())
ret += "\n" + MainApp.sResources.getString(R.string.duration) + ": " + duration + " min"; ret += "\n" + MainApp.gs(R.string.comment) + ": " + comment;
ret += "\n" + MainApp.sResources.getString(R.string.absolute) + ": " + absolute + " U/h"; ret += "\n" + MainApp.gs(R.string.duration) + ": " + duration + " min";
ret += "\n" + MainApp.gs(R.string.absolute) + ": " + absolute + " U/h";
} }
} else { } else {
ret += "\n" + MainApp.sResources.getString(R.string.comment) + ": " + comment; ret += "\n" + MainApp.gs(R.string.comment) + ": " + comment;
} }
return ret; return ret;
} }
public Spanned toSpanned() { public String toHtml() {
String ret = "<b>" + MainApp.sResources.getString(R.string.success) + "</b>: " + success; String ret = "<b>" + MainApp.gs(R.string.success) + "</b>: " + success;
if (queued) { if (queued) {
ret = MainApp.sResources.getString(R.string.waitingforpumpresult); ret = MainApp.gs(R.string.waitingforpumpresult);
} else if (enacted) { } 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 && percent != -1) {
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 if (absolute != -1) {
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) { if (bolusDelivered > 0) {
ret += "<br><b>" + MainApp.sResources.getString(R.string.bolus) + "</b>: " + DecimalFormatter.to2Decimal(bolusDelivered) + " U"; 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 { } 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(Profile profile) {
}
public JSONObject json() {
JSONObject result = new JSONObject(); JSONObject result = new JSONObject();
try { try {
if (isTempCancel) { if (bolusDelivered > 0) {
result.put("smb", bolusDelivered);
} else if (isTempCancel) {
result.put("rate", 0); result.put("rate", 0);
result.put("duration", 0); result.put("duration", 0);
} else if (isPercent) { } else if (isPercent) {
// Nightscout is expecting absolute value // 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("rate", abs);
result.put("duration", duration); result.put("duration", duration);
} else { } else {

View file

@ -10,6 +10,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.utils.SP;
/** /**
* Created by mike on 12.10.2016. * Created by mike on 12.10.2016.
@ -25,10 +26,7 @@ public class QuickWizard {
} }
public void save() { public void save() {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext()); SP.putString("QuickWizard", storage.toString());
SharedPreferences.Editor editor = preferences.edit();
editor.putString("QuickWizard", storage.toString());
editor.apply();
} }
public int size() { public int size() {

View file

@ -7,15 +7,14 @@ import org.slf4j.LoggerFactory;
import java.util.Date; import java.util.Date;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.db.TempTarget; import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.interfaces.TreatmentsInterface; import info.nightscout.androidaps.interfaces.TreatmentsInterface;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.IobCobCalculator.CobInfo;
import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData;
import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin; import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin;
import info.nightscout.androidaps.plugins.Loop.LoopPlugin; import info.nightscout.androidaps.plugins.Loop.LoopPlugin;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.utils.BolusWizard; import info.nightscout.utils.BolusWizard;
import info.nightscout.utils.DateUtil; import info.nightscout.utils.DateUtil;
import info.nightscout.utils.SP; import info.nightscout.utils.SP;
@ -80,14 +79,10 @@ public class QuickWizardEntry {
// COB // COB
double cob = 0d; double cob = 0d;
AutosensData autosensData; if (useCOB() == YES) {
if (_synchronized) CobInfo cobInfo = IobCobCalculatorPlugin.getPlugin().getCobInfo(_synchronized, "QuickWizard COB");
autosensData = IobCobCalculatorPlugin.getPlugin().getLastAutosensDataSynchronized("QuickWizard COB"); if (cobInfo.displayCob != null)
else cob = cobInfo.displayCob;
autosensData = IobCobCalculatorPlugin.getPlugin().getLastAutosensData("QuickWizard COB");
if (autosensData != null && useCOB() == YES) {
cob = autosensData.cob;
} }
// Temp target // Temp target
@ -102,7 +97,7 @@ public class QuickWizardEntry {
} }
// Basal IOB // Basal IOB
TreatmentsInterface treatments = MainApp.getConfigBuilder(); TreatmentsInterface treatments = TreatmentsPlugin.getPlugin();
treatments.updateTotalIOBTempBasals(); treatments.updateTotalIOBTempBasals();
IobTotal basalIob = treatments.getLastCalculationTempBasals().round(); IobTotal basalIob = treatments.getLastCalculationTempBasals().round();
boolean basalIOB = false; boolean basalIOB = false;
@ -119,8 +114,8 @@ public class QuickWizardEntry {
if (useSuperBolus() == YES && SP.getBoolean(R.string.key_usesuperbolus, false)) { if (useSuperBolus() == YES && SP.getBoolean(R.string.key_usesuperbolus, false)) {
superBolus = true; superBolus = true;
} }
final LoopPlugin activeloop = ConfigBuilderPlugin.getActiveLoop(); final LoopPlugin loopPlugin = LoopPlugin.getPlugin();
if (activeloop != null && activeloop.isEnabled(activeloop.getType()) && activeloop.isSuperBolus()) if (loopPlugin.isEnabled(loopPlugin.getType()) && loopPlugin.isSuperBolus())
superBolus = false; superBolus = false;
// Trend // Trend

View file

@ -195,8 +195,7 @@ public class BgReading implements DataPointWithLabelInterface {
@Override @Override
public float getSize() { public float getSize() {
boolean isTablet = MainApp.sResources.getBoolean(R.bool.isTablet); return 1;
return isTablet ? 8 : 5;
} }
@Override @Override

View file

@ -98,6 +98,14 @@ public class CareportalEvent implements DataPointWithLabelInterface {
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.sResources.getString(R.string.days) + " " + diff.get(TimeUnit.HOURS) + " " + MainApp.sResources.getString(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() { public String log() {
return "CareportalEvent{" + return "CareportalEvent{" +
"date= " + date + "date= " + date +
@ -259,4 +267,5 @@ public class CareportalEvent implements DataPointWithLabelInterface {
public int getSecondColor() { public int getSecondColor() {
return 0; return 0;
} }
} }

View file

@ -8,7 +8,6 @@ import android.support.annotation.Nullable;
import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper; import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper;
import com.j256.ormlite.dao.CloseableIterator; import com.j256.ormlite.dao.CloseableIterator;
import com.j256.ormlite.dao.Dao; import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.dao.DaoManager;
import com.j256.ormlite.stmt.PreparedQuery; import com.j256.ormlite.stmt.PreparedQuery;
import com.j256.ormlite.stmt.QueryBuilder; import com.j256.ormlite.stmt.QueryBuilder;
import com.j256.ormlite.stmt.Where; import com.j256.ormlite.stmt.Where;
@ -31,7 +30,6 @@ import java.util.concurrent.TimeUnit;
import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.ProfileStore; import info.nightscout.androidaps.data.ProfileStore;
import info.nightscout.androidaps.events.EventCareportalEventChange; import info.nightscout.androidaps.events.EventCareportalEventChange;
@ -44,21 +42,19 @@ import info.nightscout.androidaps.events.EventReloadTempBasalData;
import info.nightscout.androidaps.events.EventReloadTreatmentData; import info.nightscout.androidaps.events.EventReloadTreatmentData;
import info.nightscout.androidaps.events.EventTempBasalChange; import info.nightscout.androidaps.events.EventTempBasalChange;
import info.nightscout.androidaps.events.EventTempTargetChange; 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.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.activities.DanaRNSHistorySync;
import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes;
import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin; 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.NSUpload;
import info.nightscout.utils.PercentageSplitter; 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 * 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). * 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. * 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 * 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. * direct calls to the corresponding methods (eg. resetDatabases) should be done by a central service.
@ -71,22 +67,19 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
public static final String DATABASE_TEMPORARYBASALS = "TemporaryBasals"; public static final String DATABASE_TEMPORARYBASALS = "TemporaryBasals";
public static final String DATABASE_EXTENDEDBOLUSES = "ExtendedBoluses"; public static final String DATABASE_EXTENDEDBOLUSES = "ExtendedBoluses";
public static final String DATABASE_TEMPTARGETS = "TempTargets"; 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_DANARHISTORY = "DanaRHistory";
public static final String DATABASE_DBREQUESTS = "DBRequests"; public static final String DATABASE_DBREQUESTS = "DBRequests";
public static final String DATABASE_CAREPORTALEVENTS = "CareportalEvents"; public static final String DATABASE_CAREPORTALEVENTS = "CareportalEvents";
public static final String DATABASE_PROFILESWITCHES = "ProfileSwitches"; public static final String DATABASE_PROFILESWITCHES = "ProfileSwitches";
public static final String DATABASE_TDDS = "TDDs";
private static final int DATABASE_VERSION = 8; 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 final ScheduledExecutorService bgWorker = Executors.newSingleThreadScheduledExecutor();
private static ScheduledFuture<?> scheduledBgPost = null; 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 final ScheduledExecutorService tempBasalsWorker = Executors.newSingleThreadScheduledExecutor();
private static ScheduledFuture<?> scheduledTemBasalsPost = null; private static ScheduledFuture<?> scheduledTemBasalsPost = null;
@ -116,7 +109,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
try { try {
log.info("onCreate"); log.info("onCreate");
TableUtils.createTableIfNotExists(connectionSource, TempTarget.class); TableUtils.createTableIfNotExists(connectionSource, TempTarget.class);
TableUtils.createTableIfNotExists(connectionSource, Treatment.class);
TableUtils.createTableIfNotExists(connectionSource, BgReading.class); TableUtils.createTableIfNotExists(connectionSource, BgReading.class);
TableUtils.createTableIfNotExists(connectionSource, DanaRHistoryRecord.class); TableUtils.createTableIfNotExists(connectionSource, DanaRHistoryRecord.class);
TableUtils.createTableIfNotExists(connectionSource, DbRequest.class); TableUtils.createTableIfNotExists(connectionSource, DbRequest.class);
@ -124,6 +116,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
TableUtils.createTableIfNotExists(connectionSource, ExtendedBolus.class); TableUtils.createTableIfNotExists(connectionSource, ExtendedBolus.class);
TableUtils.createTableIfNotExists(connectionSource, CareportalEvent.class); TableUtils.createTableIfNotExists(connectionSource, CareportalEvent.class);
TableUtils.createTableIfNotExists(connectionSource, ProfileSwitch.class); TableUtils.createTableIfNotExists(connectionSource, ProfileSwitch.class);
TableUtils.createTableIfNotExists(connectionSource, TDD.class);
} catch (SQLException e) { } catch (SQLException e) {
log.error("Can't create database", e); log.error("Can't create database", e);
throw new RuntimeException(e); throw new RuntimeException(e);
@ -138,12 +131,9 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
if (oldVersion == 7 && newVersion == 8) { if (oldVersion == 7 && newVersion == 8) {
log.debug("Upgrading database from v7 to v8"); log.debug("Upgrading database from v7 to v8");
TableUtils.dropTable(connectionSource, Treatment.class, true);
TableUtils.createTableIfNotExists(connectionSource, Treatment.class);
} else { } else {
log.info(DatabaseHelper.class.getName(), "onUpgrade"); log.info(DatabaseHelper.class.getName(), "onUpgrade");
TableUtils.dropTable(connectionSource, TempTarget.class, true); TableUtils.dropTable(connectionSource, TempTarget.class, true);
TableUtils.dropTable(connectionSource, Treatment.class, true);
TableUtils.dropTable(connectionSource, BgReading.class, true); TableUtils.dropTable(connectionSource, BgReading.class, true);
TableUtils.dropTable(connectionSource, DanaRHistoryRecord.class, true); TableUtils.dropTable(connectionSource, DanaRHistoryRecord.class, true);
TableUtils.dropTable(connectionSource, DbRequest.class, true); TableUtils.dropTable(connectionSource, DbRequest.class, true);
@ -175,40 +165,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
super.close(); 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) { public long size(String database) {
return DatabaseUtils.queryNumEntries(getReadableDatabase(), database); return DatabaseUtils.queryNumEntries(getReadableDatabase(), database);
@ -219,7 +175,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
public void resetDatabases() { public void resetDatabases() {
try { try {
TableUtils.dropTable(connectionSource, TempTarget.class, true); TableUtils.dropTable(connectionSource, TempTarget.class, true);
TableUtils.dropTable(connectionSource, Treatment.class, true);
TableUtils.dropTable(connectionSource, BgReading.class, true); TableUtils.dropTable(connectionSource, BgReading.class, true);
TableUtils.dropTable(connectionSource, DanaRHistoryRecord.class, true); TableUtils.dropTable(connectionSource, DanaRHistoryRecord.class, true);
TableUtils.dropTable(connectionSource, DbRequest.class, true); TableUtils.dropTable(connectionSource, DbRequest.class, true);
@ -227,8 +182,8 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
TableUtils.dropTable(connectionSource, ExtendedBolus.class, true); TableUtils.dropTable(connectionSource, ExtendedBolus.class, true);
TableUtils.dropTable(connectionSource, CareportalEvent.class, true); TableUtils.dropTable(connectionSource, CareportalEvent.class, true);
TableUtils.dropTable(connectionSource, ProfileSwitch.class, true); TableUtils.dropTable(connectionSource, ProfileSwitch.class, true);
TableUtils.dropTable(connectionSource, TDD.class, true);
TableUtils.createTableIfNotExists(connectionSource, TempTarget.class); TableUtils.createTableIfNotExists(connectionSource, TempTarget.class);
TableUtils.createTableIfNotExists(connectionSource, Treatment.class);
TableUtils.createTableIfNotExists(connectionSource, BgReading.class); TableUtils.createTableIfNotExists(connectionSource, BgReading.class);
TableUtils.createTableIfNotExists(connectionSource, DanaRHistoryRecord.class); TableUtils.createTableIfNotExists(connectionSource, DanaRHistoryRecord.class);
TableUtils.createTableIfNotExists(connectionSource, DbRequest.class); TableUtils.createTableIfNotExists(connectionSource, DbRequest.class);
@ -236,6 +191,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
TableUtils.createTableIfNotExists(connectionSource, ExtendedBolus.class); TableUtils.createTableIfNotExists(connectionSource, ExtendedBolus.class);
TableUtils.createTableIfNotExists(connectionSource, CareportalEvent.class); TableUtils.createTableIfNotExists(connectionSource, CareportalEvent.class);
TableUtils.createTableIfNotExists(connectionSource, ProfileSwitch.class); TableUtils.createTableIfNotExists(connectionSource, ProfileSwitch.class);
TableUtils.createTableIfNotExists(connectionSource, TDD.class);
updateEarliestDataChange(0); updateEarliestDataChange(0);
} catch (SQLException e) { } catch (SQLException e) {
log.error("Unhandled exception", e); log.error("Unhandled exception", e);
@ -243,7 +199,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
VirtualPumpPlugin.setFakingStatus(true); VirtualPumpPlugin.setFakingStatus(true);
scheduleBgChange(null); // trigger refresh scheduleBgChange(null); // trigger refresh
scheduleTemporaryBasalChange(); scheduleTemporaryBasalChange();
scheduleTreatmentChange(null);
scheduleExtendedBolusChange(); scheduleExtendedBolusChange();
scheduleTemporaryTargetChange(); scheduleTemporaryTargetChange();
scheduleCareportalEventChange(); scheduleCareportalEventChange();
@ -259,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(null);
}
public void resetTempTargets() { public void resetTempTargets() {
try { try {
TableUtils.dropTable(connectionSource, TempTarget.class, true); TableUtils.dropTable(connectionSource, TempTarget.class, true);
@ -323,6 +267,14 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
scheduleProfileSwitchChange(); 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 ------------------------------------------- // ------------------ getDao -------------------------------------------
@ -330,10 +282,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
return getDao(TempTarget.class); return getDao(TempTarget.class);
} }
private Dao<Treatment, Long> getDaoTreatments() throws SQLException {
return getDao(Treatment.class);
}
private Dao<BgReading, Long> getDaoBgReadings() throws SQLException { private Dao<BgReading, Long> getDaoBgReadings() throws SQLException {
return getDao(BgReading.class); return getDao(BgReading.class);
} }
@ -342,6 +290,10 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
return getDao(DanaRHistoryRecord.class); return getDao(DanaRHistoryRecord.class);
} }
private Dao<TDD, String> getDaoTDD() throws SQLException {
return getDao(TDD.class);
}
private Dao<DbRequest, String> getDaoDbRequest() throws SQLException { private Dao<DbRequest, String> getDaoDbRequest() throws SQLException {
return getDao(DbRequest.class); return getDao(DbRequest.class);
} }
@ -362,7 +314,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
return getDao(ProfileSwitch.class); return getDao(ProfileSwitch.class);
} }
public long roundDateToSec(long date) { public static long roundDateToSec(long date) {
return date - date % 1000; return date - date % 1000;
} }
// ------------------- BgReading handling ----------------------- // ------------------- BgReading handling -----------------------
@ -396,7 +348,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
try { try {
getDaoBgReadings().update(bgReading); getDaoBgReadings().update(bgReading);
} catch (SQLException e) { } catch (SQLException e) {
e.printStackTrace(); log.error("Unhandled exception", e);
} }
} }
@ -495,6 +447,33 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
return new ArrayList<BgReading>(); 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 ------------------- // ------------- DbRequests handling -------------------
public void create(DbRequest dbr) { public void create(DbRequest dbr) {
@ -531,7 +510,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
queryBuilder.limit(10L); queryBuilder.limit(10L);
PreparedQuery<DbRequest> preparedQuery = queryBuilder.prepare(); PreparedQuery<DbRequest> preparedQuery = queryBuilder.prepare();
List<DbRequest> dbList = getDaoDbRequest().query(preparedQuery); List<DbRequest> dbList = getDaoDbRequest().query(preparedQuery);
log.error("deleteDbRequestbyMongoId query size: " + dbList.size());
for (DbRequest r : dbList) { for (DbRequest r : dbList) {
delete(r); delete(r);
} }
@ -559,146 +537,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
// -------------------- TREATMENT HANDLING ------------------- // -------------------- TREATMENT HANDLING -------------------
// return true if new record is created public static void updateEarliestDataChange(long newDate) {
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(treatment);
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(treatment);
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(treatment);
return true;
}
}
}
getDaoTreatments().create(treatment);
log.debug("TREATMENT: New record from: " + Source.getString(treatment.source) + " " + treatment.toString());
updateEarliestDataChange(treatment.date);
scheduleTreatmentChange(treatment);
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(treatment);
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(treatment);
}
public void update(Treatment treatment) {
try {
getDaoTreatments().update(treatment);
updateEarliestDataChange(treatment.date);
} catch (SQLException e) {
log.error("Unhandled exception", e);
}
scheduleTreatmentChange(treatment);
}
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(null);
}
}
@Nullable
private 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) {
if (earliestDataChange == null) { if (earliestDataChange == null) {
earliestDataChange = newDate; earliestDataChange = newDate;
return; return;
@ -708,73 +547,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
} }
} }
private static void scheduleTreatmentChange(@Nullable final Treatment treatment) {
class PostRunnable implements Runnable {
public void run() {
log.debug("Firing EventTreatmentChange");
MainApp.bus().post(new EventReloadTreatmentData(new EventTreatmentChange(treatment)));
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 --------------- // ---------------- TempTargets handling ---------------
public List<TempTarget> getTemptargetsDataFromTime(long mills, boolean ascending) { public List<TempTarget> getTemptargetsDataFromTime(long mills, boolean ascending) {
@ -892,15 +664,15 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
public void createTemptargetFromJsonIfNotExists(JSONObject trJson) { public void createTemptargetFromJsonIfNotExists(JSONObject trJson) {
try { try {
String units = MainApp.getConfigBuilder().getProfileUnits(); String units = JsonHelper.safeGetString(trJson, "units", MainApp.getConfigBuilder().getProfileUnits());
TempTarget tempTarget = new TempTarget(); TempTarget tempTarget = new TempTarget()
tempTarget.date = trJson.getLong("mills"); .date(trJson.getLong("mills"))
tempTarget.durationInMinutes = trJson.getInt("duration"); .duration(trJson.getInt("duration"))
tempTarget.low = Profile.toMgdl(trJson.getDouble("targetBottom"), units); .low(Profile.toMgdl(trJson.getDouble("targetBottom"), units))
tempTarget.high = Profile.toMgdl(trJson.getDouble("targetTop"), units); .high(Profile.toMgdl(trJson.getDouble("targetTop"), units))
tempTarget.reason = trJson.getString("reason"); .reason(trJson.getString("reason"))
tempTarget._id = trJson.getString("_id"); ._id(trJson.getString("_id"))
tempTarget.source = Source.NIGHTSCOUT; .source(Source.NIGHTSCOUT);
createOrUpdate(tempTarget); createOrUpdate(tempTarget);
} catch (JSONException e) { } catch (JSONException e) {
log.error("Unhandled exception", e); log.error("Unhandled exception", e);
@ -940,6 +712,12 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
public void createOrUpdate(DanaRHistoryRecord record) { public void createOrUpdate(DanaRHistoryRecord record) {
try { try {
getDaoDanaRHistory().createOrUpdate(record); 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) { } catch (SQLException e) {
log.error("Unhandled exception", e); log.error("Unhandled exception", e);
} }
@ -1169,10 +947,10 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
} }
createOrUpdate(extendedBolus); createOrUpdate(extendedBolus);
} else { } else {
TemporaryBasal tempBasal = new TemporaryBasal(); TemporaryBasal tempBasal = new TemporaryBasal()
tempBasal.date = trJson.getLong("mills"); .date(trJson.getLong("mills"))
tempBasal.source = Source.NIGHTSCOUT; .source(Source.NIGHTSCOUT)
tempBasal.pumpId = trJson.has("pumpId") ? trJson.getLong("pumpId") : 0; .pumpId(trJson.has("pumpId") ? trJson.getLong("pumpId") : 0);
if (trJson.has("duration")) { if (trJson.has("duration")) {
tempBasal.durationInMinutes = trJson.getInt("duration"); tempBasal.durationInMinutes = trJson.getInt("duration");
} }
@ -1376,37 +1154,10 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
} }
*/ */
public void createExtendedBolusFromJsonIfNotExists(JSONObject trJson) { public void createExtendedBolusFromJsonIfNotExists(JSONObject json) {
try { ExtendedBolus extendedBolus = ExtendedBolus.createFromJson(json);
QueryBuilder<ExtendedBolus, Long> queryBuilder = null; if (extendedBolus != 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");
createOrUpdate(extendedBolus); createOrUpdate(extendedBolus);
} catch (SQLException | JSONException e) {
log.error("Unhandled exception", e);
}
} }
private static void scheduleExtendedBolusChange() { private static void scheduleExtendedBolusChange() {
@ -1452,6 +1203,15 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
scheduleCareportalEventChange(); scheduleCareportalEventChange();
} }
public CareportalEvent getCareportalEventFromTimestamp(long timestamp) {
try {
return getDaoCareportalEvents().queryForId(timestamp);
} catch (SQLException e) {
log.error("Unhandled exception", e);
}
return null;
}
@Nullable @Nullable
public CareportalEvent getLastCareportalEvent(String event) { public CareportalEvent getLastCareportalEvent(String event) {
try { try {
@ -1505,7 +1265,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
public void deleteCareportalEventById(String _id) { public void deleteCareportalEventById(String _id) {
try { try {
QueryBuilder<CareportalEvent, Long> queryBuilder = null; QueryBuilder<CareportalEvent, Long> queryBuilder;
queryBuilder = getDaoCareportalEvents().queryBuilder(); queryBuilder = getDaoCareportalEvents().queryBuilder();
Where where = queryBuilder.where(); Where where = queryBuilder.where();
where.eq("_id", _id); where.eq("_id", _id);
@ -1528,7 +1288,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
public void createCareportalEventFromJsonIfNotExists(JSONObject trJson) { public void createCareportalEventFromJsonIfNotExists(JSONObject trJson) {
try { try {
QueryBuilder<CareportalEvent, Long> queryBuilder = null; QueryBuilder<CareportalEvent, Long> queryBuilder;
queryBuilder = getDaoCareportalEvents().queryBuilder(); queryBuilder = getDaoCareportalEvents().queryBuilder();
Where where = queryBuilder.where(); Where where = queryBuilder.where();
where.eq("_id", trJson.getString("_id")).or().eq("date", trJson.getLong("mills")); where.eq("_id", trJson.getString("_id")).or().eq("date", trJson.getLong("mills"));
@ -1585,14 +1345,14 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
List<ProfileSwitch> profileSwitches; List<ProfileSwitch> profileSwitches;
QueryBuilder<ProfileSwitch, Long> queryBuilder = daoProfileSwitch.queryBuilder(); QueryBuilder<ProfileSwitch, Long> queryBuilder = daoProfileSwitch.queryBuilder();
queryBuilder.orderBy("date", ascending); queryBuilder.orderBy("date", ascending);
queryBuilder.limit(20L); queryBuilder.limit(100L);
PreparedQuery<ProfileSwitch> preparedQuery = queryBuilder.prepare(); PreparedQuery<ProfileSwitch> preparedQuery = queryBuilder.prepare();
profileSwitches = daoProfileSwitch.query(preparedQuery); profileSwitches = daoProfileSwitch.query(preparedQuery);
return profileSwitches; return profileSwitches;
} catch (SQLException e) { } catch (SQLException e) {
log.error("Unhandled exception", e); log.error("Unhandled exception", e);
} }
return new ArrayList<ProfileSwitch>(); return new ArrayList<>();
} }
public boolean createOrUpdate(ProfileSwitch profileSwitch) { public boolean createOrUpdate(ProfileSwitch profileSwitch) {
@ -1709,7 +1469,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
if (trJson.has("profileJson")) if (trJson.has("profileJson"))
profileSwitch.profileJson = trJson.getString("profileJson"); profileSwitch.profileJson = trJson.getString("profileJson");
else { else {
ProfileStore store = ConfigBuilderPlugin.getActiveProfileInterface().getProfile(); ProfileStore store = MainApp.getConfigBuilder().getActiveProfileInterface().getProfile();
Profile profile = store.getSpecificProfile(profileSwitch.profileName); Profile profile = store.getSpecificProfile(profileSwitch.profileName);
if (profile != null) { if (profile != null) {
profileSwitch.profileJson = profile.getData().toString(); profileSwitch.profileJson = profile.getData().toString();

View file

@ -9,24 +9,25 @@ import android.graphics.Color;
import com.j256.ormlite.field.DatabaseField; import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable; import com.j256.ormlite.table.DatabaseTable;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.Date;
import java.util.Objects; import java.util.Objects;
import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.data.Iob; import info.nightscout.androidaps.data.Iob;
import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.interfaces.InsulinInterface; import info.nightscout.androidaps.interfaces.InsulinInterface;
import info.nightscout.androidaps.interfaces.Interval; import info.nightscout.androidaps.interfaces.Interval;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Overview.graphExtensions.DataPointWithLabelInterface; import info.nightscout.androidaps.plugins.Overview.graphExtensions.DataPointWithLabelInterface;
import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLabelGraphSeries; import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLabelGraphSeries;
import info.nightscout.androidaps.plugins.Treatments.Treatment;
import info.nightscout.utils.DateUtil; import info.nightscout.utils.DateUtil;
import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.JsonHelper;
import info.nightscout.utils.Round; import info.nightscout.utils.Round;
/** /**
@ -91,6 +92,16 @@ public class ExtendedBolus implements Interval, DataPointWithLabelInterface {
pumpId = t.pumpId; 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 --------- // -------- Interval interface ---------
Long cuttedEnd = null; Long cuttedEnd = null;

View file

@ -61,6 +61,31 @@ public class ProfileSwitch implements Interval, DataPointWithLabelInterface {
private Profile profile = null; 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 @Nullable
public Profile getProfileObject() { public Profile getProfileObject() {
if (profile == null) if (profile == null)

View 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;
}
}

View file

@ -71,6 +71,41 @@ public class TempTarget implements Interval {
reason = t.reason; 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 --------- // -------- Interval interface ---------
Long cuttedEnd = null; Long cuttedEnd = null;

View file

@ -6,7 +6,6 @@ import com.j256.ormlite.table.DatabaseTable;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.Date;
import java.util.Objects; import java.util.Objects;
import info.nightscout.androidaps.MainApp; 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.InsulinInterface;
import info.nightscout.androidaps.interfaces.Interval; import info.nightscout.androidaps.interfaces.Interval;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Treatments.Treatment;
import info.nightscout.utils.DateUtil; import info.nightscout.utils.DateUtil;
import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.SP; import info.nightscout.utils.SP;
@ -60,8 +60,36 @@ public class TemporaryBasal implements Interval {
public TemporaryBasal() { public TemporaryBasal() {
} }
public TemporaryBasal(long date) { public TemporaryBasal date(long date) {
this.date = 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) { public TemporaryBasal(ExtendedBolus extendedBolus) {
@ -189,7 +217,7 @@ public class TemporaryBasal implements Interval {
// -------- Interval interface end --------- // -------- Interval interface end ---------
public IobTotal iobCalc(long time) { public IobTotal iobCalc(long time, Profile profile) {
if(isFakeExtended){ if(isFakeExtended){
log.error("iobCalc should only be called on Extended boluses separately"); 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); IobTotal result = new IobTotal(time);
Profile profile = MainApp.getConfigBuilder().getProfile(time);
InsulinInterface insulinInterface = ConfigBuilderPlugin.getActiveInsulin(); InsulinInterface insulinInterface = ConfigBuilderPlugin.getActiveInsulin();
int realDuration = getDurationToTime(time); int realDuration = getDurationToTime(time);
@ -262,13 +289,13 @@ public class TemporaryBasal implements Interval {
return (remainingMin < 0) ? 0 : Math.round(remainingMin); return (remainingMin < 0) ? 0 : Math.round(remainingMin);
} }
public double tempBasalConvertedToAbsolute(long time) { public double tempBasalConvertedToAbsolute(long time, Profile profile) {
if(isFakeExtended){ if(isFakeExtended){
return MainApp.getConfigBuilder().getProfile(time).getBasal(time) + netExtendedRate; return profile.getBasal(time) + netExtendedRate;
} else if (isAbsolute) { } else if (isAbsolute) {
return absoluteRate; return absoluteRate;
} else { } else {
return MainApp.getConfigBuilder().getProfile(time).getBasal(time) * percentRate / 100; return profile.getBasal(time) * percentRate / 100;
} }
} }

View file

@ -0,0 +1,10 @@
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;
}

View file

@ -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;
}
}

View file

@ -2,7 +2,7 @@ package info.nightscout.androidaps.events;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.plugins.Treatments.Treatment;
/** /**
* Created by mike on 04.06.2016. * Created by mike on 04.06.2016.

View file

@ -11,5 +11,5 @@ public interface APSInterface {
public APSResult getLastAPSResult(); public APSResult getLastAPSResult();
public Date getLastAPSRun(); public Date getLastAPSRun();
public void invoke(String initiator); public void invoke(String initiator, boolean tempBasalFallback);
} }

View file

@ -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);
}
}
}

View file

@ -1,30 +1,54 @@
package info.nightscout.androidaps.interfaces; 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. * Created by mike on 15.06.2016.
*/ */
public interface ConstraintsInterface { 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;
};
} }

View file

@ -1,9 +1,7 @@
package info.nightscout.androidaps.interfaces; package info.nightscout.androidaps.interfaces;
import java.util.Date;
import info.nightscout.androidaps.data.Iob; 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. * Created by mike on 17.04.2017.

View file

@ -1,34 +1,165 @@
package info.nightscout.androidaps.interfaces; 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. * Created by mike on 09.06.2016.
*/ */
public interface PluginBase { public abstract class PluginBase {
int GENERAL = 1; private static Logger log = LoggerFactory.getLogger(PluginBase.class);
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
int getType(); public enum State {
String getFragmentClass(); NOT_INITIALIZED,
ENABLED,
String getName(); DISABLED
String getNameShort(); }
boolean isEnabled(int type);
boolean isVisibleInTabs(int type); private State state = State.NOT_INITIALIZED;
boolean canBeHidden(int type); private boolean isFragmentVisible = false;
boolean hasFragment(); public PluginDescription pluginDescription;
boolean showInList(int type);
void setFragmentEnabled(int type, boolean fragmentEnabled);
void setFragmentVisible(int type, boolean fragmentVisible); // Specific plugin with more Interfaces
int getPreferencesId(); 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) {
}
} }

View file

@ -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;
}
}

View file

@ -0,0 +1,14 @@
package info.nightscout.androidaps.interfaces;
public enum PluginType {
GENERAL,
TREATMENT,
SENSITIVITY,
PROFILE,
APS,
PUMP,
CONSTRAINTS,
LOOP,
BGSOURCE,
INSULIN
}

View file

@ -41,4 +41,7 @@ public class PumpDescription {
public boolean storesCarbInfo = true; public boolean storesCarbInfo = true;
public boolean is30minBasalRatesCapable = false; public boolean is30minBasalRatesCapable = false;
public boolean supportsTDDs = false;
public boolean needsManualTDDLoad = true;
} }

View file

@ -5,8 +5,8 @@ import org.json.JSONObject;
import java.util.Date; import java.util.Date;
import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.PumpEnactResult;
/** /**
* Created by mike on 04.06.2016. * Created by mike on 04.06.2016.
@ -35,8 +35,8 @@ public interface PumpInterface {
PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo); PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo);
void stopBolusDelivering(); void stopBolusDelivering();
PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean enforceNew); PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, Profile profile, boolean enforceNew);
PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, boolean enforceNew); PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, Profile profile, boolean enforceNew);
PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes); PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes);
//some pumps might set a very short temp close to 100% as cancelling a temp can be noisy //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 //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(); PumpEnactResult cancelExtendedBolus();
// Status to be passed to NS // Status to be passed to NS
JSONObject getJSONStatus(); JSONObject getJSONStatus(Profile profile, String profileName);
String deviceID(); String deviceID();
// Pump capabilities // Pump capabilities
@ -54,4 +54,7 @@ public interface PumpInterface {
String shortStatus(boolean veryShort); String shortStatus(boolean veryShort);
boolean isFakingTempsByExtendedBoluses(); boolean isFakingTempsByExtendedBoluses();
PumpEnactResult loadTDDs();
} }

View file

@ -5,11 +5,12 @@ import java.util.List;
import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.data.MealData; import info.nightscout.androidaps.data.MealData;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.db.ExtendedBolus; import info.nightscout.androidaps.db.ExtendedBolus;
import info.nightscout.androidaps.db.ProfileSwitch; import info.nightscout.androidaps.db.ProfileSwitch;
import info.nightscout.androidaps.db.TempTarget; import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.db.TemporaryBasal; 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.Intervals;
import info.nightscout.androidaps.data.ProfileIntervals; import info.nightscout.androidaps.data.ProfileIntervals;
@ -24,7 +25,7 @@ public interface TreatmentsInterface {
IobTotal getLastCalculationTreatments(); IobTotal getLastCalculationTreatments();
IobTotal getCalculationToTimeTreatments(long time); IobTotal getCalculationToTimeTreatments(long time);
IobTotal getLastCalculationTempBasals(); IobTotal getLastCalculationTempBasals();
IobTotal getCalculationToTimeTempBasals(long time); IobTotal getCalculationToTimeTempBasals(long time, Profile profile);
MealData getMealData(); MealData getMealData();
@ -41,8 +42,6 @@ public interface TreatmentsInterface {
// basal that can be faked by extended boluses // basal that can be faked by extended boluses
boolean isTempBasalInProgress(); boolean isTempBasalInProgress();
TemporaryBasal getTempBasalFromHistory(long time); TemporaryBasal getTempBasalFromHistory(long time);
double getTempBasalAbsoluteRateHistory();
double getTempBasalRemainingMinutesFromHistory();
Intervals<TemporaryBasal> getTemporaryBasalsFromHistory(); Intervals<TemporaryBasal> getTemporaryBasalsFromHistory();
boolean isInHistoryExtendedBoluslInProgress(); boolean isInHistoryExtendedBoluslInProgress();
@ -56,6 +55,7 @@ public interface TreatmentsInterface {
TempTarget getTempTargetFromHistory(); TempTarget getTempTargetFromHistory();
TempTarget getTempTargetFromHistory(long time); TempTarget getTempTargetFromHistory(long time);
Intervals<TempTarget> getTempTargetsFromHistory(); Intervals<TempTarget> getTempTargetsFromHistory();
void addToHistoryTempTarget(TempTarget tempTarget);
ProfileSwitch getProfileSwitchFromHistory(long time); ProfileSwitch getProfileSwitchFromHistory(long time);
ProfileIntervals<ProfileSwitch> getProfileSwitchesFromHistory(); ProfileIntervals<ProfileSwitch> getProfileSwitchesFromHistory();

View file

@ -2,6 +2,7 @@ package info.nightscout.androidaps.plugins.Actions;
import android.app.Activity; import android.app.Activity;
import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentManager;
@ -9,13 +10,14 @@ import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import com.crashlytics.android.answers.CustomEvent; import com.crashlytics.android.answers.CustomEvent;
import com.squareup.otto.Subscribe; import com.squareup.otto.Subscribe;
import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.HistoryBrowseActivity;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.TDDStatsActivity;
import info.nightscout.androidaps.db.ExtendedBolus; import info.nightscout.androidaps.db.ExtendedBolus;
import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.events.EventExtendedBolusChange; import info.nightscout.androidaps.events.EventExtendedBolusChange;
@ -31,6 +33,7 @@ import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialo
import info.nightscout.androidaps.plugins.Careportal.OptionsToShow; import info.nightscout.androidaps.plugins.Careportal.OptionsToShow;
import info.nightscout.androidaps.plugins.Common.SubscriberFragment; import info.nightscout.androidaps.plugins.Common.SubscriberFragment;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.utils.FabricPrivacy; import info.nightscout.utils.FabricPrivacy;
import info.nightscout.utils.SingleClickButton; import info.nightscout.utils.SingleClickButton;
@ -52,6 +55,8 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL
SingleClickButton tempBasal; SingleClickButton tempBasal;
SingleClickButton tempBasalCancel; SingleClickButton tempBasalCancel;
SingleClickButton fill; SingleClickButton fill;
SingleClickButton tddStats;
SingleClickButton history;
public ActionsFragment() { public ActionsFragment() {
super(); super();
@ -71,6 +76,8 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL
tempBasal = (SingleClickButton) view.findViewById(R.id.actions_settempbasal); tempBasal = (SingleClickButton) view.findViewById(R.id.actions_settempbasal);
tempBasalCancel = (SingleClickButton) view.findViewById(R.id.actions_canceltempbasal); tempBasalCancel = (SingleClickButton) view.findViewById(R.id.actions_canceltempbasal);
fill = (SingleClickButton) view.findViewById(R.id.actions_fill); 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); profileSwitch.setOnClickListener(this);
tempTarget.setOnClickListener(this); tempTarget.setOnClickListener(this);
@ -79,6 +86,8 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL
tempBasal.setOnClickListener(this); tempBasal.setOnClickListener(this);
tempBasalCancel.setOnClickListener(this); tempBasalCancel.setOnClickListener(this);
fill.setOnClickListener(this); fill.setOnClickListener(this);
history.setOnClickListener(this);
tddStats.setOnClickListener(this);
updateGUI(); updateGUI();
return view; return view;
@ -116,9 +125,14 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL
activity.runOnUiThread(new Runnable() { activity.runOnUiThread(new Runnable() {
@Override @Override
public void run() { public void run() {
if (MainApp.getConfigBuilder().getActiveProfileInterface().getProfile() == null) { if (MainApp.getConfigBuilder().getActiveProfileInterface().getProfile() != null) {
tempTarget.setVisibility(View.GONE); profileSwitch.setVisibility(View.VISIBLE);
} else {
profileSwitch.setVisibility(View.GONE); profileSwitch.setVisibility(View.GONE);
}
if (MainApp.getConfigBuilder().getProfile() == null) {
tempTarget.setVisibility(View.GONE);
extendedBolus.setVisibility(View.GONE); extendedBolus.setVisibility(View.GONE);
extendedBolusCancel.setVisibility(View.GONE); extendedBolusCancel.setVisibility(View.GONE);
tempBasal.setVisibility(View.GONE); tempBasal.setVisibility(View.GONE);
@ -126,18 +140,21 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL
fill.setVisibility(View.GONE); fill.setVisibility(View.GONE);
return; return;
} }
final PumpInterface pump = ConfigBuilderPlugin.getActivePump(); 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); profileSwitch.setVisibility(View.GONE);
else else
profileSwitch.setVisibility(View.VISIBLE); profileSwitch.setVisibility(View.VISIBLE);
if (!pump.getPumpDescription().isExtendedBolusCapable || !pump.isInitialized() || pump.isSuspended() || pump.isFakingTempsByExtendedBoluses()) { if (!pump.getPumpDescription().isExtendedBolusCapable || !pump.isInitialized() || pump.isSuspended() || pump.isFakingTempsByExtendedBoluses()) {
extendedBolus.setVisibility(View.GONE); extendedBolus.setVisibility(View.GONE);
extendedBolusCancel.setVisibility(View.GONE); extendedBolusCancel.setVisibility(View.GONE);
} else { } else {
ExtendedBolus activeExtendedBolus = MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis()); ExtendedBolus activeExtendedBolus = TreatmentsPlugin.getPlugin().getExtendedBolusFromHistory(System.currentTimeMillis());
if (activeExtendedBolus != null) { if (activeExtendedBolus != null) {
extendedBolus.setVisibility(View.GONE); extendedBolus.setVisibility(View.GONE);
extendedBolusCancel.setVisibility(View.VISIBLE); extendedBolusCancel.setVisibility(View.VISIBLE);
@ -153,7 +170,7 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL
tempBasal.setVisibility(View.GONE); tempBasal.setVisibility(View.GONE);
tempBasalCancel.setVisibility(View.GONE); tempBasalCancel.setVisibility(View.GONE);
} else { } else {
final TemporaryBasal activeTemp = MainApp.getConfigBuilder().getTempBasalFromHistory(System.currentTimeMillis()); final TemporaryBasal activeTemp = TreatmentsPlugin.getPlugin().getTempBasalFromHistory(System.currentTimeMillis());
if (activeTemp != null) { if (activeTemp != null) {
tempBasal.setVisibility(View.GONE); tempBasal.setVisibility(View.GONE);
tempBasalCancel.setVisibility(View.VISIBLE); tempBasalCancel.setVisibility(View.VISIBLE);
@ -173,6 +190,9 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL
tempTarget.setVisibility(View.GONE); tempTarget.setVisibility(View.GONE);
else else
tempTarget.setVisibility(View.VISIBLE); tempTarget.setVisibility(View.VISIBLE);
if (!ConfigBuilderPlugin.getActivePump().getPumpDescription().supportsTDDs) tddStats.setVisibility(View.GONE);
else tddStats.setVisibility(View.VISIBLE);
} }
}); });
} }
@ -201,13 +221,13 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL
newExtendedDialog.show(manager, "NewExtendedDialog"); newExtendedDialog.show(manager, "NewExtendedDialog");
break; break;
case R.id.actions_extendedbolus_cancel: case R.id.actions_extendedbolus_cancel:
if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) { if (TreatmentsPlugin.getPlugin().isInHistoryExtendedBoluslInProgress()) {
ConfigBuilderPlugin.getCommandQueue().cancelExtended(null); ConfigBuilderPlugin.getCommandQueue().cancelExtended(null);
FabricPrivacy.getInstance().logCustom(new CustomEvent("CancelExtended")); FabricPrivacy.getInstance().logCustom(new CustomEvent("CancelExtended"));
} }
break; break;
case R.id.actions_canceltempbasal: case R.id.actions_canceltempbasal:
if (MainApp.getConfigBuilder().isTempBasalInProgress()) { if (TreatmentsPlugin.getPlugin().isTempBasalInProgress()) {
ConfigBuilderPlugin.getCommandQueue().cancelTempBasal(true, null); ConfigBuilderPlugin.getCommandQueue().cancelTempBasal(true, null);
FabricPrivacy.getInstance().logCustom(new CustomEvent("CancelTemp")); FabricPrivacy.getInstance().logCustom(new CustomEvent("CancelTemp"));
} }
@ -220,6 +240,12 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL
FillDialog fillDialog = new FillDialog(); FillDialog fillDialog = new FillDialog();
fillDialog.show(manager, "FillDialog"); fillDialog.show(manager, "FillDialog");
break; 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;
} }
} }
} }

View file

@ -1,82 +1,22 @@
package info.nightscout.androidaps.plugins.Actions; package info.nightscout.androidaps.plugins.Actions;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.interfaces.PluginBase; 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. * Created by mike on 05.11.2016.
*/ */
public class ActionsPlugin implements PluginBase { public class ActionsPlugin extends PluginBase {
private boolean fragmentEnabled = true; public ActionsPlugin() {
private boolean fragmentVisible = true; super(new PluginDescription()
.mainType(PluginType.GENERAL)
@Override .fragmentClass(ActionsFragment.class.getName())
public int getType() { .pluginName(R.string.actions)
return PluginBase.GENERAL; .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;
}
} }

View file

@ -1,11 +1,13 @@
package info.nightscout.androidaps.plugins.Actions.dialogs; package info.nightscout.androidaps.plugins.Actions.dialogs;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.support.v4.app.DialogFragment; import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog; 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.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.View.OnClickListener; import android.view.View.OnClickListener;
@ -13,40 +15,73 @@ import android.view.ViewGroup;
import android.view.Window; import android.view.Window;
import android.view.WindowManager; import android.view.WindowManager;
import android.widget.Button; import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.LinearLayout;
import com.crashlytics.android.answers.CustomEvent; import com.crashlytics.android.answers.CustomEvent;
import com.google.common.base.Joiner;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; 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.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.Source;
import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Overview.Dialogs.ErrorHelperActivity; import info.nightscout.androidaps.plugins.Overview.Dialogs.ErrorHelperActivity;
import info.nightscout.androidaps.queue.Callback; import info.nightscout.androidaps.queue.Callback;
import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.FabricPrivacy; import info.nightscout.utils.FabricPrivacy;
import info.nightscout.utils.NSUpload;
import info.nightscout.utils.NumberPicker; import info.nightscout.utils.NumberPicker;
import info.nightscout.utils.SP; import info.nightscout.utils.SP;
import info.nightscout.utils.SafeParse; import info.nightscout.utils.SafeParse;
import info.nightscout.utils.ToastUtils;
import static info.nightscout.utils.DateUtil.now;
public class FillDialog extends DialogFragment implements OnClickListener { public class FillDialog extends DialogFragment implements OnClickListener {
private static Logger log = LoggerFactory.getLogger(FillDialog.class); private static Logger log = LoggerFactory.getLogger(FillDialog.class);
Button deliverButton; private CheckBox pumpSiteChangeCheckbox;
private CheckBox insulinCartridgeChangeCheckbox;
private NumberPicker editInsulin;
double amount1 = 0d; double amount1 = 0d;
double amount2 = 0d; double amount2 = 0d;
double amount3 = 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 @Override
@ -54,110 +89,122 @@ public class FillDialog extends DialogFragment implements OnClickListener {
Bundle savedInstanceState) { Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.actions_fill_dialog, null, false); 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().requestFeature(Window.FEATURE_NO_TITLE);
getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); 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; double bolusstep = ConfigBuilderPlugin.getActivePump().getPumpDescription().bolusStep;
editInsulin = (NumberPicker) view.findViewById(R.id.treatments_newtreatment_insulinamount); editInsulin = view.findViewById(R.id.fill_insulinamount);
editInsulin.setParams(0d, 0d, maxInsulin, bolusstep, new DecimalFormat("0.00"), false); 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); amount1 = SP.getDouble("fill_button1", 0.3);
amount2 = SP.getDouble("fill_button2", 0d);
amount3 = SP.getDouble("fill_button3", 0d);
if (amount1 > 0) { if (amount1 > 0) {
button1.setVisibility(View.VISIBLE); preset1Button.setVisibility(View.VISIBLE);
button1.setText(DecimalFormatter.to2Decimal(amount1) + "U"); preset1Button.setText(DecimalFormatter.toPumpSupportedBolus(amount1)); // + "U");
button1.setOnClickListener(this); preset1Button.setOnClickListener(this);
} else { } 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) { if (amount2 > 0) {
button2.setVisibility(View.VISIBLE); preset2Button.setVisibility(View.VISIBLE);
button2.setText(DecimalFormatter.to2Decimal(amount2) + "U"); preset2Button.setText(DecimalFormatter.toPumpSupportedBolus(amount2)); // + "U");
button2.setOnClickListener(this); preset2Button.setOnClickListener(this);
} else { } 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) { if (amount3 > 0) {
button3.setVisibility(View.VISIBLE); preset3Button.setVisibility(View.VISIBLE);
button3.setText(DecimalFormatter.to2Decimal(amount3) + "U"); preset3Button.setText(DecimalFormatter.toPumpSupportedBolus(amount3)); // + "U");
button3.setOnClickListener(this); preset3Button.setOnClickListener(this);
} else { } else {
button3.setVisibility(View.GONE); preset3Button.setVisibility(View.GONE);
} }
if (button1.getVisibility() == View.GONE && button2.getVisibility() == View.GONE && button3.getVisibility() == View.GONE) { LinearLayout notesLayout = view.findViewById(R.id.fill_notes_layout);
divider.setVisibility(View.GONE); 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); setCancelable(true);
getDialog().setCanceledOnTouchOutside(false); getDialog().setCanceledOnTouchOutside(false);
return view; return view;
} }
@Override
public void onResume() {
super.onResume();
if (getDialog() != null)
getDialog().getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
}
@Override @Override
public void onClick(View view) { public void onClick(View view) {
switch (view.getId()) { switch (view.getId()) {
case R.id.treatments_newtreatment_deliverbutton: case R.id.ok:
Double insulin = SafeParse.stringToDouble(editInsulin.getText().toString()); confirmAndDeliver();
confirmAndDeliver(insulin); break;
case R.id.cancel:
dismiss();
break; break;
case R.id.fill_preset_button1: case R.id.fill_preset_button1:
confirmAndDeliver(amount1); editInsulin.setValue(amount1);
break; break;
case R.id.fill_preset_button2: case R.id.fill_preset_button2:
confirmAndDeliver(amount2); editInsulin.setValue(amount2);
break; break;
case R.id.fill_preset_button3: case R.id.fill_preset_button3:
confirmAndDeliver(amount3); editInsulin.setValue(amount3);
break; break;
} }
} }
private void confirmAndDeliver(Double insulin) { private void confirmAndDeliver() {
try { 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); Double insulinAfterConstraints = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(insulin)).value();
confirmMessage += getString(R.string.bolus) + ": " + insulinAfterConstraints + "U"; if (insulinAfterConstraints > 0) {
if (insulinAfterConstraints - insulin != 0) confirmMessage.add(MainApp.gs(R.string.fillwarning));
confirmMessage += "\n" + getString(R.string.constraintapllied); 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) + "'>" + getString(R.string.record_pump_site_change) + "</font>");
if (insulinCartridgeChangeCheckbox.isChecked())
confirmMessage.add("" + "<font color='" + MainApp.sResources.getColor(R.color.high) + "'>" + getString(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 Double finalInsulinAfterConstraints = insulinAfterConstraints;
final Context context = getContext(); final Context context = getContext();
AlertDialog.Builder builder = new AlertDialog.Builder(context); AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(this.getContext().getString(R.string.confirmation)); builder.setTitle(MainApp.gs(R.string.confirmation));
builder.setMessage(confirmMessage); if (insulinAfterConstraints > 0 || pumpSiteChangeCheckbox.isChecked() || insulinCartridgeChangeCheckbox.isChecked()) {
builder.setPositiveButton(getString(R.string.primefill), new DialogInterface.OnClickListener() { builder.setMessage(Html.fromHtml(Joiner.on("<br/>").join(confirmMessage)));
public void onClick(DialogInterface dialog, int id) { builder.setPositiveButton(getString(R.string.primefill), (dialog, id) -> {
if (finalInsulinAfterConstraints > 0) { if (finalInsulinAfterConstraints > 0) {
DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo();
detailedBolusInfo.insulin = finalInsulinAfterConstraints; detailedBolusInfo.insulin = finalInsulinAfterConstraints;
detailedBolusInfo.context = context; detailedBolusInfo.context = context;
detailedBolusInfo.source = Source.USER; detailedBolusInfo.source = Source.USER;
detailedBolusInfo.isValid = false; // do not count it in IOB (for pump history) detailedBolusInfo.isValid = false; // do not count it in IOB (for pump history)
detailedBolusInfo.notes = notes;
ConfigBuilderPlugin.getCommandQueue().bolus(detailedBolusInfo, new Callback() { ConfigBuilderPlugin.getCommandQueue().bolus(detailedBolusInfo, new Callback() {
@Override @Override
public void run() { public void run() {
@ -173,8 +220,14 @@ public class FillDialog extends DialogFragment implements OnClickListener {
}); });
FabricPrivacy.getInstance().logCustom(new CustomEvent("Fill")); FabricPrivacy.getInstance().logCustom(new CustomEvent("Fill"));
} }
} 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(getString(R.string.cancel), null); builder.setNegativeButton(getString(R.string.cancel), null);
builder.show(); builder.show();
dismiss(); dismiss();

View file

@ -17,9 +17,9 @@ import org.slf4j.LoggerFactory;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Overview.Dialogs.ErrorHelperActivity; import info.nightscout.androidaps.plugins.Overview.Dialogs.ErrorHelperActivity;
import info.nightscout.androidaps.queue.Callback; import info.nightscout.androidaps.queue.Callback;
@ -43,7 +43,7 @@ public class NewExtendedBolusDialog extends DialogFragment implements View.OnCli
View view = inflater.inflate(R.layout.overview_newextendedbolus_dialog, container, false); 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 = (NumberPicker) view.findViewById(R.id.overview_newextendedbolus_insulin);
editInsulin.setParams(0d, 0d, maxInsulin, 0.1d, new DecimalFormat("0.00"), false); editInsulin.setParams(0d, 0d, maxInsulin, 0.1d, new DecimalFormat("0.00"), false);
@ -70,7 +70,7 @@ public class NewExtendedBolusDialog extends DialogFragment implements View.OnCli
String confirmMessage = getString(R.string.setextendedbolusquestion); String confirmMessage = getString(R.string.setextendedbolusquestion);
Double insulinAfterConstraint = MainApp.getConfigBuilder().applyBolusConstraints(insulin); Double insulinAfterConstraint = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(insulin)).value();
confirmMessage += " " + insulinAfterConstraint + " U "; confirmMessage += " " + insulinAfterConstraint + " U ";
confirmMessage += getString(R.string.duration) + " " + durationInMinutes + "min ?"; confirmMessage += getString(R.string.duration) + " " + durationInMinutes + "min ?";
if (insulinAfterConstraint - insulin != 0d) if (insulinAfterConstraint - insulin != 0d)

View file

@ -22,6 +22,7 @@ import java.text.DecimalFormat;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Overview.Dialogs.ErrorHelperActivity; import info.nightscout.androidaps.plugins.Overview.Dialogs.ErrorHelperActivity;
@ -117,17 +118,21 @@ public class NewTempBasalDialog extends DialogFragment implements View.OnClickLi
final boolean setAsPercent = percentRadio.isChecked(); final boolean setAsPercent = percentRadio.isChecked();
int durationInMinutes = SafeParse.stringToInt(duration.getText()); int durationInMinutes = SafeParse.stringToInt(duration.getText());
Profile profile = MainApp.getConfigBuilder().getProfile();
if (profile == null)
return;
String confirmMessage = getString(R.string.setbasalquestion); String confirmMessage = getString(R.string.setbasalquestion);
if (setAsPercent) { if (setAsPercent) {
int basalPercentInput = SafeParse.stringToInt(basalPercent.getText()); 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" + percent + "% ";
confirmMessage += "\n" + getString(R.string.duration) + " " + durationInMinutes + "min ?"; confirmMessage += "\n" + getString(R.string.duration) + " " + durationInMinutes + "min ?";
if (percent != basalPercentInput) if (percent != basalPercentInput)
confirmMessage += "\n" + getString(R.string.constraintapllied); confirmMessage += "\n" + getString(R.string.constraintapllied);
} else { } else {
Double basalAbsoluteInput = SafeParse.stringToDouble(basalAbsolute.getText()); 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" + absolute + " U/h ";
confirmMessage += "\n" + getString(R.string.duration) + " " + durationInMinutes + "min ?"; confirmMessage += "\n" + getString(R.string.duration) + " " + durationInMinutes + "min ?";
if (absolute - basalAbsoluteInput != 0d) if (absolute - basalAbsoluteInput != 0d)
@ -157,9 +162,9 @@ public class NewTempBasalDialog extends DialogFragment implements View.OnClickLi
} }
}; };
if (setAsPercent) { if (setAsPercent) {
ConfigBuilderPlugin.getCommandQueue().tempBasalPercent(finalBasalPercent, finalDurationInMinutes, true, callback); ConfigBuilderPlugin.getCommandQueue().tempBasalPercent(finalBasalPercent, finalDurationInMinutes, true, profile, callback);
} else { } else {
ConfigBuilderPlugin.getCommandQueue().tempBasalAbsolute(finalBasal, finalDurationInMinutes, true, callback); ConfigBuilderPlugin.getCommandQueue().tempBasalAbsolute(finalBasal, finalDurationInMinutes, true, profile, callback);
} }
FabricPrivacy.getInstance().logCustom(new CustomEvent("TempBasal")); FabricPrivacy.getInstance().logCustom(new CustomEvent("TempBasal"));
} }

View file

@ -2,6 +2,7 @@ package info.nightscout.androidaps.plugins.Careportal;
import android.app.Activity; import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle; import android.os.Bundle;
import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentManager;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@ -12,7 +13,9 @@ import android.widget.TextView;
import com.squareup.otto.Subscribe; 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.Config;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
@ -21,11 +24,12 @@ import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.events.EventCareportalEventChange; import info.nightscout.androidaps.events.EventCareportalEventChange;
import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog; import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog;
import info.nightscout.androidaps.plugins.Common.SubscriberFragment; 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.androidaps.plugins.Overview.OverviewFragment;
import info.nightscout.utils.FabricPrivacy; import info.nightscout.utils.FabricPrivacy;
public class CareportalFragment extends SubscriberFragment implements View.OnClickListener { public class CareportalFragment extends SubscriberFragment implements View.OnClickListener {
private static Logger log = LoggerFactory.getLogger(CareportalFragment.class);
TextView iage; TextView iage;
TextView cage; TextView cage;
@ -96,7 +100,7 @@ public class CareportalFragment extends SubscriberFragment implements View.OnCli
noProfileView = view.findViewById(R.id.profileview_noprofile); noProfileView = view.findViewById(R.id.profileview_noprofile);
butonsLayout = (LinearLayout) view.findViewById(R.id.careportal_buttons); butonsLayout = (LinearLayout) view.findViewById(R.id.careportal_buttons);
ProfileStore profileStore = ConfigBuilderPlugin.getActiveProfileInterface().getProfile(); ProfileStore profileStore = MainApp.getConfigBuilder().getActiveProfileInterface().getProfile();
if (profileStore == null) { if (profileStore == null) {
noProfileView.setVisibility(View.VISIBLE); noProfileView.setVisibility(View.VISIBLE);
butonsLayout.setVisibility(View.GONE); butonsLayout.setVisibility(View.GONE);
@ -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) { public static void updateAge(Activity activity, final TextView sage, final TextView iage, final TextView cage, final TextView pbage) {
if (activity != null) { if (activity != null) {
activity.runOnUiThread( activity.runOnUiThread(
new Runnable() { () -> {
@Override
public void run() {
CareportalEvent careportalEvent; 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.sResources.getString(R.string.notavailable); String notavailable = OverviewFragment.shorttextmode ? "-" : MainApp.sResources.getString(R.string.notavailable);
if (sage != null) { if (sage != null) {
careportalEvent = MainApp.getDbHelper().getLastCareportalEvent(CareportalEvent.SENSORCHANGE); careportalEvent = MainApp.getDbHelper().getLastCareportalEvent(CareportalEvent.SENSORCHANGE);
sage.setText(careportalEvent != null ? careportalEvent.age() : notavailable); if (careportalEvent != null) {
sage.setTextColor(CareportalFragment.determineTextColor(careportalEvent, sageWarn, sageUrgent));
sage.setText(careportalEvent.age());
} else {
sage.setText(notavailable);
}
} }
if (iage != null) { if (iage != null) {
careportalEvent = MainApp.getDbHelper().getLastCareportalEvent(CareportalEvent.INSULINCHANGE); careportalEvent = MainApp.getDbHelper().getLastCareportalEvent(CareportalEvent.INSULINCHANGE);
iage.setText(careportalEvent != null ? careportalEvent.age() : notavailable); if (careportalEvent != null) {
iage.setTextColor(CareportalFragment.determineTextColor(careportalEvent, iageWarn, iageUrgent));
iage.setText(careportalEvent.age());
} else {
iage.setText(notavailable);
}
} }
if (cage != null) { if (cage != null) {
careportalEvent = MainApp.getDbHelper().getLastCareportalEvent(CareportalEvent.SITECHANGE); careportalEvent = MainApp.getDbHelper().getLastCareportalEvent(CareportalEvent.SITECHANGE);
cage.setText(careportalEvent != null ? careportalEvent.age() : notavailable); if (careportalEvent != null) {
cage.setTextColor(CareportalFragment.determineTextColor(careportalEvent, cageWarn, cageUrgent));
cage.setText(careportalEvent.age());
} else {
cage.setText(notavailable);
}
} }
if (pbage != null) { if (pbage != null) {
careportalEvent = MainApp.getDbHelper().getLastCareportalEvent(CareportalEvent.PUMPBATTERYCHANGE); careportalEvent = MainApp.getDbHelper().getLastCareportalEvent(CareportalEvent.PUMPBATTERYCHANGE);
pbage.setText(careportalEvent != null ? careportalEvent.age() : notavailable); 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;
} }
}
}

View file

@ -1,14 +1,12 @@
package info.nightscout.androidaps.plugins.Careportal; package info.nightscout.androidaps.plugins.Careportal;
import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType;
public class CareportalPlugin implements PluginBase { public class CareportalPlugin extends PluginBase {
private boolean fragmentEnabled = true;
private boolean fragmentVisible = true;
static CareportalPlugin careportalPlugin; static CareportalPlugin careportalPlugin;
@ -19,70 +17,13 @@ public class CareportalPlugin implements PluginBase {
return careportalPlugin; return careportalPlugin;
} }
@Override public CareportalPlugin() {
public int getType() { super(new PluginDescription()
return PluginBase.GENERAL; .mainType(PluginType.GENERAL)
} .fragmentClass(CareportalFragment.class.getName())
.pluginName(R.string.careportal)
@Override .shortName(R.string.careportal_shortname)
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;
} }
} }

View file

@ -2,8 +2,6 @@ package info.nightscout.androidaps.plugins.Careportal.Dialogs;
import android.app.Activity; import android.app.Activity;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.support.v4.app.DialogFragment; import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog; import android.support.v7.app.AlertDialog;
@ -16,7 +14,6 @@ import android.view.ViewGroup;
import android.widget.AdapterView; import android.widget.AdapterView;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import android.widget.Button; import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.EditText; import android.widget.EditText;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.RadioButton; import android.widget.RadioButton;
@ -24,6 +21,7 @@ import android.widget.Spinner;
import android.widget.TextView; import android.widget.TextView;
import com.crashlytics.android.answers.CustomEvent; import com.crashlytics.android.answers.CustomEvent;
import com.google.common.collect.Lists;
import com.wdullaer.materialdatetimepicker.date.DatePickerDialog; import com.wdullaer.materialdatetimepicker.date.DatePickerDialog;
import com.wdullaer.materialdatetimepicker.time.RadialPickerLayout; import com.wdullaer.materialdatetimepicker.time.RadialPickerLayout;
import com.wdullaer.materialdatetimepicker.time.TimePickerDialog; import com.wdullaer.materialdatetimepicker.time.TimePickerDialog;
@ -50,13 +48,13 @@ import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.db.ProfileSwitch; import info.nightscout.androidaps.db.ProfileSwitch;
import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.Source;
import info.nightscout.androidaps.db.TempTarget; import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.events.EventNewBasalProfile;
import info.nightscout.androidaps.plugins.Careportal.OptionsToShow; import info.nightscout.androidaps.plugins.Careportal.OptionsToShow;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.androidaps.plugins.Overview.Dialogs.ErrorHelperActivity;
import info.nightscout.androidaps.queue.Callback;
import info.nightscout.utils.FabricPrivacy;
import info.nightscout.utils.DateUtil; 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.NSUpload;
import info.nightscout.utils.NumberPicker; import info.nightscout.utils.NumberPicker;
import info.nightscout.utils.SP; import info.nightscout.utils.SP;
@ -72,8 +70,8 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
private static String event; private static String event;
Profile profile; Profile profile;
ProfileStore profileStore; public ProfileStore profileStore;
String units; String units = Constants.MGDL;
TextView eventTypeText; TextView eventTypeText;
LinearLayout layoutPercent; LinearLayout layoutPercent;
@ -107,13 +105,19 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
Date eventTime; Date eventTime;
private static Integer seconds = null;
public void setOptions(OptionsToShow options, int event) { public void setOptions(OptionsToShow options, int event) {
this.options = options; this.options = options;
this.event = MainApp.sResources.getString(event); this.event = MainApp.gs(event);
} }
public NewNSTreatmentDialog() { public NewNSTreatmentDialog() {
super(); super();
if (seconds == null) {
seconds = Double.valueOf(Math.random() * 59).intValue();
}
} }
@Override @Override
@ -132,7 +136,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) { Bundle savedInstanceState) {
if (options == null) return null; if (options == null) return null;
getDialog().setTitle(getString(options.eventName)); getDialog().setTitle(MainApp.gs(options.eventName));
setStyle(DialogFragment.STYLE_NORMAL, getTheme()); setStyle(DialogFragment.STYLE_NORMAL, getTheme());
View view = inflater.inflate(R.layout.careportal_newnstreatment_dialog, container, false); View view = inflater.inflate(R.layout.careportal_newnstreatment_dialog, container, false);
@ -168,11 +172,16 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
// profile // profile
profile = MainApp.getConfigBuilder().getProfile(); profile = MainApp.getConfigBuilder().getProfile();
profileStore = ConfigBuilderPlugin.getActiveProfileInterface().getProfile(); 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; ArrayList<CharSequence> profileList;
units = profile != null ? profile.getUnits() : Constants.MGDL; units = profile != null ? profile.getUnits() : Constants.MGDL;
profileList = profileStore.getProfileList(); profileList = profileStore.getProfileList();
ArrayAdapter<CharSequence> adapter = new ArrayAdapter<CharSequence>(getContext(), ArrayAdapter<CharSequence> adapter = new ArrayAdapter<>(getContext(),
R.layout.spinner_centered, profileList); R.layout.spinner_centered, profileList);
profileSpinner.setAdapter(adapter); profileSpinner.setAdapter(adapter);
// set selected to actual profile // set selected to actual profile
@ -180,40 +189,44 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
if (profileList.get(p).equals(MainApp.getConfigBuilder().getProfileName(false))) if (profileList.get(p).equals(MainApp.getConfigBuilder().getProfileName(false)))
profileSpinner.setSelection(p); 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 // temp target
final ArrayList<CharSequence> reasonList = new ArrayList<CharSequence>(); final List<String> reasonList = Lists.newArrayList(
reasonList.add(MainApp.sResources.getString(R.string.manual)); MainApp.gs(R.string.manual),
reasonList.add(MainApp.sResources.getString(R.string.eatingsoon)); MainApp.gs(R.string.eatingsoon),
reasonList.add(MainApp.sResources.getString(R.string.activity)); MainApp.gs(R.string.activity),
ArrayAdapter<CharSequence> adapterReason = new ArrayAdapter<CharSequence>(getContext(), MainApp.gs(R.string.hypo));
ArrayAdapter<String> adapterReason = new ArrayAdapter<>(getContext(),
R.layout.spinner_centered, reasonList); R.layout.spinner_centered, reasonList);
reasonSpinner.setAdapter(adapterReason); reasonSpinner.setAdapter(adapterReason);
reasonSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { reasonSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override @Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
double defaultDuration = 0; double defaultDuration;
double defaultTarget = 0; double defaultTarget = 0;
if (profile != null) { if (profile != null) {
defaultTarget = bg.doubleValue(); defaultTarget = bg;
} }
boolean erase = false; boolean erase = false;
if (MainApp.sResources.getString(R.string.eatingsoon).equals(reasonList.get(position))) { String units = MainApp.getConfigBuilder().getProfileUnits();
defaultDuration = SP.getDouble(R.string.key_eatingsoon_duration, 0d); DefaultValueHelper helper = new DefaultValueHelper();
defaultTarget = SP.getDouble(R.string.key_eatingsoon_target, 0d); if (MainApp.gs(R.string.eatingsoon).equals(reasonList.get(position))) {
; defaultDuration = helper.determineEatingSoonTTDuration();
} else if (MainApp.sResources.getString(R.string.activity).equals(reasonList.get(position))) { defaultTarget = helper.determineEatingSoonTT(units);
defaultDuration = SP.getDouble(R.string.key_activity_duration, 0d); } else if (MainApp.gs(R.string.activity).equals(reasonList.get(position))) {
; defaultDuration = helper.determineActivityTTDuration();
defaultTarget = SP.getDouble(R.string.key_activity_target, 0d); defaultTarget = helper.determineActivityTT(units);
; } else if (MainApp.gs(R.string.hypo).equals(reasonList.get(position))) {
defaultDuration = helper.determineHypoTTDuration();
defaultTarget = helper.determineHypoTT(units);
} else { } else {
defaultDuration = 0; defaultDuration = 0;
erase = true; erase = true;
} }
if (defaultTarget != 0 || erase) { if (defaultTarget != 0 || erase) {
editTemptarget.setValue(defaultTarget); editTemptarget.setValue(defaultTarget);
} }
@ -258,19 +271,16 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
editBg.setParams(bg, 0d, 500d, 1d, new DecimalFormat("0"), false, bgTextWatcher); editBg.setParams(bg, 0d, 500d, 1d, new DecimalFormat("0"), false, bgTextWatcher);
editTemptarget.setParams(bg, 0d, 500d, 1d, new DecimalFormat("0"), false); editTemptarget.setParams(bg, 0d, 500d, 1d, new DecimalFormat("0"), false);
} }
sensorRadioButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { sensorRadioButton.setOnCheckedChangeListener((buttonView, isChecked) -> {
@Override Double bg1 = Profile.fromMgdlToUnits(GlucoseStatus.getGlucoseStatusData() != null ? GlucoseStatus.getGlucoseStatusData().glucose : 0d, profile.getUnits());
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { editBg.setValue(bg1);
Double bg = Profile.fromMgdlToUnits(GlucoseStatus.getGlucoseStatusData() != null ? GlucoseStatus.getGlucoseStatusData().glucose : 0d, profile.getUnits());
editBg.setValue(bg);
}
}); });
Integer maxCarbs = MainApp.getConfigBuilder().applyCarbsConstraints(Constants.carbsOnlyForCheckLimit); Integer maxCarbs = MainApp.getConstraintChecker().getMaxCarbsAllowed().value();
editCarbs = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_carbsinput); editCarbs = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_carbsinput);
editCarbs.setParams(0d, 0d, (double) maxCarbs, 1d, new DecimalFormat("0"), false); 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 = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_insulininput);
editInsulin.setParams(0d, 0d, maxInsulin, 0.05d, new DecimalFormat("0.00"), false); editInsulin.setParams(0d, 0d, maxInsulin, 0.05d, new DecimalFormat("0.00"), false);
@ -297,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 = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_percentinput);
editPercent.setParams(0d, 0d, (double) maxPercent, 5d, new DecimalFormat("0"), true, percentTextWatcher); editPercent.setParams(0d, 0d, (double) maxPercent, 5d, new DecimalFormat("0"), true, percentTextWatcher);
@ -319,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 = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_absoluteinput);
editAbsolute.setParams(0d, 0d, maxAbsolute, 0.05d, new DecimalFormat("0.00"), true, absoluteTextWatcher); editAbsolute.setParams(0d, 0d, maxAbsolute, 0.05d, new DecimalFormat("0.00"), true, absoluteTextWatcher);
@ -332,19 +346,19 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
editTimeshift = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_timeshift); 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); 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) { if (ps != null && ps.isCPP) {
final int percentage = ps.percentage; final int percentage = ps.percentage;
final int timeshift = ps.timeshift; final int timeshift = ps.timeshift;
reuseButton.setText(reuseButton.getText() + " " + percentage + "% " + timeshift + "h"); reuseButton.setText(reuseButton.getText() + " " + percentage + "% " + timeshift + "h");
reuseButton.setOnClickListener(new View.OnClickListener() { reuseButton.setOnClickListener(v -> {
@Override
public void onClick(View v) {
editPercentage.setValue((double) percentage); editPercentage.setValue((double) percentage);
editTimeshift.setValue((double) timeshift); 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_eventtime_layout), options.date);
showOrHide((ViewGroup) view.findViewById(R.id.careportal_newnstreatment_bg_layout), options.bg); showOrHide((ViewGroup) view.findViewById(R.id.careportal_newnstreatment_bg_layout), options.bg);
@ -395,7 +409,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
tpd.show(context.getFragmentManager(), "Timepickerdialog"); tpd.show(context.getFragmentManager(), "Timepickerdialog");
break; break;
case R.id.ok: case R.id.ok:
createNSTreatment(); confirmNSTreatmentCreation();
dismiss(); dismiss();
break; break;
case R.id.cancel: case R.id.cancel:
@ -432,7 +446,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
public void onTimeSet(RadialPickerLayout view, int hourOfDay, int minute, int second) { public void onTimeSet(RadialPickerLayout view, int hourOfDay, int minute, int second) {
eventTime.setHours(hourOfDay); eventTime.setHours(hourOfDay);
eventTime.setMinutes(minute); 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)); timeButton.setText(DateUtil.timeString(eventTime));
updateBGforDateTime(); updateBGforDateTime();
} }
@ -559,160 +573,152 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
String buildConfirmText(JSONObject data) { String buildConfirmText(JSONObject data) {
String ret = ""; String ret = "";
try {
if (data.has("eventType")) { if (data.has("eventType")) {
ret += getString(R.string.careportal_newnstreatment_eventtype); ret += MainApp.gs(R.string.careportal_newnstreatment_eventtype);
ret += ": "; ret += ": ";
ret += Translator.translate(data.getString("eventType")); ret += Translator.translate(JsonHelper.safeGetString(data, "eventType", ""));
ret += "\n"; ret += "\n";
} }
if (data.has("glucose")) { if (data.has("glucose")) {
ret += getString(R.string.treatments_wizard_bg_label); ret += MainApp.gs(R.string.treatments_wizard_bg_label);
ret += ": "; ret += ": ";
ret += data.get("glucose"); ret += JsonHelper.safeGetObject(data, "glucose", "");
ret += " " + units + "\n"; ret += " " + units + "\n";
} }
if (data.has("glucoseType")) { if (data.has("glucoseType")) {
ret += getString(R.string.careportal_newnstreatment_glucosetype); ret += MainApp.gs(R.string.careportal_newnstreatment_glucosetype);
ret += ": "; ret += ": ";
ret += Translator.translate(data.getString("glucoseType")); ret += Translator.translate(JsonHelper.safeGetString(data, "glucoseType", ""));
ret += "\n"; ret += "\n";
} }
if (data.has("carbs")) { if (data.has("carbs")) {
ret += getString(R.string.careportal_newnstreatment_carbs_label); ret += MainApp.gs(R.string.careportal_newnstreatment_carbs_label);
ret += ": "; ret += ": ";
ret += data.get("carbs"); ret += JsonHelper.safeGetObject(data, "carbs", "");
ret += " g\n"; ret += " g\n";
} }
if (data.has("insulin")) { if (data.has("insulin")) {
ret += getString(R.string.careportal_newnstreatment_insulin_label); ret += MainApp.gs(R.string.careportal_newnstreatment_insulin_label);
ret += ": "; ret += ": ";
ret += data.get("insulin"); ret += JsonHelper.safeGetObject(data, "insulin", "");
ret += " U\n"; ret += " U\n";
} }
if (data.has("duration")) { if (data.has("duration")) {
ret += getString(R.string.careportal_newnstreatment_duration_label); ret += MainApp.gs(R.string.careportal_newnstreatment_duration_label);
ret += ": "; ret += ": ";
ret += data.get("duration"); ret += JsonHelper.safeGetObject(data, "duration", "");
ret += " min\n"; ret += " min\n";
} }
if (data.has("percent")) { if (data.has("percent")) {
ret += getString(R.string.careportal_newnstreatment_percent_label); ret += MainApp.gs(R.string.careportal_newnstreatment_percent_label);
ret += ": "; ret += ": ";
ret += data.get("percent"); ret += JsonHelper.safeGetObject(data, "percent", "");
ret += " %\n"; ret += " %\n";
} }
if (data.has("absolute")) { if (data.has("absolute")) {
ret += getString(R.string.careportal_newnstreatment_absolute_label); ret += MainApp.gs(R.string.careportal_newnstreatment_absolute_label);
ret += ": "; ret += ": ";
ret += data.get("absolute"); ret += JsonHelper.safeGetObject(data, "absolute", "");
ret += " U/h\n"; ret += " U/h\n";
} }
if (data.has("preBolus")) { if (data.has("preBolus")) {
ret += getString(R.string.careportal_newnstreatment_carbtime_label); ret += MainApp.gs(R.string.careportal_newnstreatment_carbtime_label);
ret += ": "; ret += ": ";
ret += data.get("preBolus"); ret += JsonHelper.safeGetObject(data, "preBolus", "");
ret += " min\n"; ret += " min\n";
} }
if (data.has("notes")) { if (data.has("notes")) {
ret += getString(R.string.careportal_newnstreatment_notes_label); ret += MainApp.gs(R.string.careportal_newnstreatment_notes_label);
ret += ": "; ret += ": ";
ret += data.get("notes"); ret += JsonHelper.safeGetObject(data, "notes", "");
ret += "\n"; ret += "\n";
} }
if (data.has("profile")) { if (data.has("profile")) {
ret += getString(R.string.careportal_newnstreatment_profile_label); ret += MainApp.gs(R.string.careportal_newnstreatment_profile_label);
ret += ": "; ret += ": ";
ret += data.get("profile"); ret += JsonHelper.safeGetObject(data, "profile", "");
ret += "\n"; ret += "\n";
} }
if (data.has("percentage")) { if (data.has("percentage")) {
ret += getString(R.string.careportal_newnstreatment_percentage_label); ret += MainApp.gs(R.string.careportal_newnstreatment_percentage_label);
ret += ": "; ret += ": ";
ret += data.get("percentage"); ret += JsonHelper.safeGetObject(data, "percentage", "");
ret += " %\n"; ret += " %\n";
} }
if (data.has("timeshift")) { if (data.has("timeshift")) {
ret += getString(R.string.careportal_newnstreatment_timeshift_label); ret += MainApp.gs(R.string.careportal_newnstreatment_timeshift_label);
ret += ": "; ret += ": ";
ret += data.get("timeshift"); ret += JsonHelper.safeGetObject(data, "timeshift", "");
ret += " h\n"; ret += " h\n";
} }
if (data.has("targetBottom") && data.has("targetTop")) { if (data.has("targetBottom") && data.has("targetTop")) {
ret += getString(R.string.target_range); ret += MainApp.gs(R.string.target_range);
ret += " "; ret += " ";
ret += data.get("targetBottom"); ret += JsonHelper.safeGetObject(data, "targetBottom", "");
ret += " - "; ret += " - ";
ret += data.get("targetTop"); ret += JsonHelper.safeGetObject(data, "targetTop", "");
ret += "\n"; ret += "\n";
} }
if (data.has("created_at")) { if (data.has("created_at")) {
ret += getString(R.string.careportal_newnstreatment_eventtime_label); ret += MainApp.gs(R.string.careportal_newnstreatment_eventtime_label);
ret += ": "; ret += ": ";
ret += eventTime.toLocaleString(); ret += eventTime.toLocaleString();
ret += "\n"; ret += "\n";
} }
if (data.has("enteredBy")) { if (data.has("enteredBy")) {
ret += getString(R.string.careportal_newnstreatment_enteredby_title); ret += MainApp.gs(R.string.careportal_newnstreatment_enteredby_title);
ret += ": "; ret += ": ";
ret += data.get("enteredBy"); ret += JsonHelper.safeGetObject(data, "enteredBy", "");
ret += "\n"; ret += "\n";
} }
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
return ret; return ret;
} }
void createNSTreatment() { void confirmNSTreatmentCreation() {
if (context != null) {
final JSONObject data = gatherData(); final JSONObject data = gatherData();
String confirmText = buildConfirmText(data); final String confirmText = buildConfirmText(data);
AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(getContext().getString(R.string.confirmation)); builder.setTitle(MainApp.gs(R.string.confirmation));
builder.setMessage(confirmText); builder.setMessage(confirmText);
builder.setPositiveButton(getContext().getString(R.string.ok), new DialogInterface.OnClickListener() { builder.setPositiveButton(MainApp.gs(R.string.ok), (dialog, id) -> createNSTreatment(data));
public void onClick(DialogInterface dialog, int id) { builder.setNegativeButton(MainApp.gs(R.string.cancel), null);
builder.show();
}
}
public void createNSTreatment(JSONObject data) {
if (options.executeProfileSwitch) { if (options.executeProfileSwitch) {
if (data.has("profile")) { if (data.has("profile")) {
try { doProfileSwitch(profileStore, JsonHelper.safeGetString(data, "profile"), JsonHelper.safeGetInt(data, "duration"), JsonHelper.safeGetInt(data, "percentage"), JsonHelper.safeGetInt(data, "timeshift"));
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) { } else if (options.executeTempTarget) {
try { final int duration = JsonHelper.safeGetInt(data, "duration");
if ((data.has("targetBottom") && data.has("targetTop")) || (data.has("duration") && data.getInt("duration") == 0)) { final double targetBottom = JsonHelper.safeGetDouble(data, "targetBottom");
TempTarget tempTarget = new TempTarget(); final double targetTop = JsonHelper.safeGetDouble(data, "targetTop");
tempTarget.date = eventTime.getTime(); final String reason = JsonHelper.safeGetString(data, "reason", "");
tempTarget.durationInMinutes = data.getInt("duration"); if ((targetBottom != 0d && targetTop != 0d) || duration == 0) {
tempTarget.reason = data.getString("reason"); TempTarget tempTarget = new TempTarget()
tempTarget.source = Source.USER; .date(eventTime.getTime())
.duration(duration)
.reason(reason)
.source(Source.USER);
if (tempTarget.durationInMinutes != 0) { if (tempTarget.durationInMinutes != 0) {
tempTarget.low = Profile.toMgdl(data.getDouble("targetBottom"), profile.getUnits()); tempTarget.low(Profile.toMgdl(targetBottom, profile.getUnits()))
tempTarget.high = Profile.toMgdl(data.getDouble("targetTop"), profile.getUnits()); .high(Profile.toMgdl(targetTop, profile.getUnits()));
} else { } else {
tempTarget.low = 0; tempTarget.low(0).high(0);
tempTarget.high = 0;
} }
log.debug("Creating new TempTarget db record: " + tempTarget.toString()); TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget);
MainApp.getDbHelper().createOrUpdate(tempTarget);
NSUpload.uploadCareportalEntryToNS(data);
FabricPrivacy.getInstance().logCustom(new CustomEvent("TempTarget")); FabricPrivacy.getInstance().logCustom(new CustomEvent("TempTarget"));
} }
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
} else { } else {
NSUpload.uploadCareportalEntryToNS(data); NSUpload.uploadCareportalEntryToNS(data);
FabricPrivacy.getInstance().logCustom(new CustomEvent("NSTreatment")); FabricPrivacy.getInstance().logCustom(new CustomEvent("NSTreatment"));
} }
} }
});
builder.setNegativeButton(getContext().getString(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 static void doProfileSwitch(final ProfileStore profileStore, final String profileName, final int duration, final int percentage, final int timeshift) {
ProfileSwitch profileSwitch = new ProfileSwitch(); ProfileSwitch profileSwitch = new ProfileSwitch();
@ -720,59 +726,29 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
profileSwitch.source = Source.USER; profileSwitch.source = Source.USER;
profileSwitch.profileName = profileName; profileSwitch.profileName = profileName;
profileSwitch.profileJson = profileStore.getSpecificProfile(profileName).getData().toString(); profileSwitch.profileJson = profileStore.getSpecificProfile(profileName).getData().toString();
profileSwitch.profilePlugin = ConfigBuilderPlugin.getActiveProfileInterface().getClass().getName(); profileSwitch.profilePlugin = MainApp.getConfigBuilder().getActiveProfileInterface().getClass().getName();
profileSwitch.durationInMinutes = duration; profileSwitch.durationInMinutes = duration;
profileSwitch.isCPP = percentage != 100 || timeshift != 0; profileSwitch.isCPP = percentage != 100 || timeshift != 0;
profileSwitch.timeshift = timeshift; profileSwitch.timeshift = timeshift;
profileSwitch.percentage = percentage; profileSwitch.percentage = percentage;
MainApp.getConfigBuilder().addToHistoryProfileSwitch(profileSwitch); TreatmentsPlugin.getPlugin().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());
}
});
FabricPrivacy.getInstance().logCustom(new CustomEvent("ProfileSwitch")); FabricPrivacy.getInstance().logCustom(new CustomEvent("ProfileSwitch"));
} }
public static void doProfileSwitch(final int duration, final int percentage, final int timeshift) { 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) { if (profileSwitch != null) {
profileSwitch = new ProfileSwitch(); profileSwitch = new ProfileSwitch();
profileSwitch.date = System.currentTimeMillis(); profileSwitch.date = System.currentTimeMillis();
profileSwitch.source = Source.USER; profileSwitch.source = Source.USER;
profileSwitch.profileName = MainApp.getConfigBuilder().getProfileName(System.currentTimeMillis(), false); profileSwitch.profileName = MainApp.getConfigBuilder().getProfileName(System.currentTimeMillis(), false);
profileSwitch.profileJson = MainApp.getConfigBuilder().getProfile().getData().toString(); profileSwitch.profileJson = MainApp.getConfigBuilder().getProfile().getData().toString();
profileSwitch.profilePlugin = ConfigBuilderPlugin.getActiveProfileInterface().getClass().getName(); profileSwitch.profilePlugin = MainApp.getConfigBuilder().getActiveProfileInterface().getClass().getName();
profileSwitch.durationInMinutes = duration; profileSwitch.durationInMinutes = duration;
profileSwitch.isCPP = percentage != 100 || timeshift != 0; profileSwitch.isCPP = percentage != 100 || timeshift != 0;
profileSwitch.timeshift = timeshift; profileSwitch.timeshift = timeshift;
profileSwitch.percentage = percentage; profileSwitch.percentage = percentage;
MainApp.getConfigBuilder().addToHistoryProfileSwitch(profileSwitch); TreatmentsPlugin.getPlugin().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());
}
});
FabricPrivacy.getInstance().logCustom(new CustomEvent("ProfileSwitch")); FabricPrivacy.getInstance().logCustom(new CustomEvent("ProfileSwitch"));
} else { } else {
log.error("No profile switch existing"); log.error("No profile switch existing");

View file

@ -4,7 +4,7 @@ package info.nightscout.androidaps.plugins.ConfigBuilder;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.support.v4.app.Fragment; import android.support.annotation.NonNull;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@ -17,11 +17,14 @@ import android.widget.ListAdapter;
import android.widget.ListView; import android.widget.ListView;
import android.widget.TextView; import android.widget.TextView;
import com.crashlytics.android.answers.CustomEvent; import com.crashlytics.android.answers.CustomEvent;
import java.util.ArrayList; 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.MainApp;
import info.nightscout.androidaps.PreferencesActivity; import info.nightscout.androidaps.PreferencesActivity;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
@ -32,10 +35,12 @@ import info.nightscout.androidaps.interfaces.BgSourceInterface;
import info.nightscout.androidaps.interfaces.ConstraintsInterface; import info.nightscout.androidaps.interfaces.ConstraintsInterface;
import info.nightscout.androidaps.interfaces.InsulinInterface; import info.nightscout.androidaps.interfaces.InsulinInterface;
import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.interfaces.ProfileInterface; import info.nightscout.androidaps.interfaces.ProfileInterface;
import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.interfaces.SensitivityInterface; 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.ProfileNS.NSProfilePlugin;
import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin; import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin;
import info.nightscout.androidaps.plugins.SensitivityOref0.SensitivityOref0Plugin; import info.nightscout.androidaps.plugins.SensitivityOref0.SensitivityOref0Plugin;
@ -43,33 +48,46 @@ import info.nightscout.utils.FabricPrivacy;
import info.nightscout.utils.PasswordProtection; import info.nightscout.utils.PasswordProtection;
public class ConfigBuilderFragment extends Fragment { public class ConfigBuilderFragment extends SubscriberFragment {
static ConfigBuilderPlugin configBuilderPlugin = new ConfigBuilderPlugin();
static public ConfigBuilderPlugin getPlugin() {
return configBuilderPlugin;
}
@BindView(R.id.configbuilder_insulinlistview)
ListView insulinListView; ListView insulinListView;
@BindView(R.id.configbuilder_sensitivitylistview)
ListView sensitivityListView; ListView sensitivityListView;
@BindView(R.id.configbuilder_bgsourcelistview)
ListView bgsourceListView; ListView bgsourceListView;
@BindView(R.id.configbuilder_bgsourcelabel)
TextView bgsourceLabel; TextView bgsourceLabel;
@BindView(R.id.configbuilder_pumplistview)
ListView pumpListView; ListView pumpListView;
@BindView(R.id.configbuilder_pumplabel)
TextView pumpLabel; TextView pumpLabel;
@BindView(R.id.configbuilder_looplistview)
ListView loopListView; ListView loopListView;
@BindView(R.id.configbuilder_looplabel)
TextView loopLabel; TextView loopLabel;
@BindView(R.id.configbuilder_treatmentslistview)
ListView treatmentsListView; ListView treatmentsListView;
@BindView(R.id.configbuilder_treatmentslabel)
TextView treatmentsLabel; TextView treatmentsLabel;
@BindView(R.id.configbuilder_profilelistview)
ListView profileListView; ListView profileListView;
@BindView(R.id.configbuilder_profilelabel)
TextView profileLabel; TextView profileLabel;
@BindView(R.id.configbuilder_apslistview)
ListView apsListView; ListView apsListView;
@BindView(R.id.configbuilder_apslabel)
TextView apsLabel; TextView apsLabel;
@BindView(R.id.configbuilder_constraintslistview)
ListView constraintsListView; ListView constraintsListView;
@BindView(R.id.configbuilder_constraintslabel)
TextView constraintsLabel; TextView constraintsLabel;
@BindView(R.id.configbuilder_generallistview)
ListView generalListView; ListView generalListView;
@BindView(R.id.configbuilder_mainlayout)
LinearLayout mainLayout; LinearLayout mainLayout;
@BindView(R.id.configbuilder_unlock)
Button unlock; Button unlock;
PluginCustomAdapter insulinDataAdapter = null; PluginCustomAdapter insulinDataAdapter = null;
@ -84,51 +102,17 @@ public class ConfigBuilderFragment extends Fragment {
PluginCustomAdapter generalDataAdapter = null; PluginCustomAdapter generalDataAdapter = null;
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) { Bundle savedInstanceState) {
try { try {
View view = inflater.inflate(R.layout.configbuilder_fragment, container, false); View view = inflater.inflate(R.layout.configbuilder_fragment, container, false);
insulinListView = (ListView) view.findViewById(R.id.configbuilder_insulinlistview); unbinder = ButterKnife.bind(this, view);
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);
mainLayout = (LinearLayout) view.findViewById(R.id.configbuilder_mainlayout); if (PasswordProtection.isLocked("settings_password"))
unlock = (Button) view.findViewById(R.id.configbuilder_unlock);
setViews();
if (PasswordProtection.isLocked("settings_password")) {
mainLayout.setVisibility(View.GONE); mainLayout.setVisibility(View.GONE);
unlock.setOnClickListener(new View.OnClickListener() { else
@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); unlock.setVisibility(View.GONE);
}
}, null);
}
});
} else {
unlock.setVisibility(View.GONE);
}
return view; return view;
} catch (Exception e) { } catch (Exception e) {
FabricPrivacy.logException(e); FabricPrivacy.logException(e);
@ -137,52 +121,64 @@ public class ConfigBuilderFragment extends Fragment {
return null; return null;
} }
void setViews() { @OnClick(R.id.configbuilder_unlock)
insulinDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInListByInterface(InsulinInterface.class, PluginBase.INSULIN), PluginBase.INSULIN); 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); insulinListView.setAdapter(insulinDataAdapter);
setListViewHeightBasedOnChildren(insulinListView); 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); bgsourceListView.setAdapter(bgsourceDataAdapter);
if (MainApp.getSpecificPluginsVisibleInList(PluginBase.BGSOURCE).size() == 0) if (MainApp.getSpecificPluginsVisibleInList(PluginType.BGSOURCE).size() == 0)
bgsourceLabel.setVisibility(View.GONE); bgsourceLabel.setVisibility(View.GONE);
setListViewHeightBasedOnChildren(bgsourceListView); 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); 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); pumpLabel.setVisibility(View.GONE);
pumpListView.setVisibility(View.GONE);
}
setListViewHeightBasedOnChildren(pumpListView); 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); loopListView.setAdapter(loopDataAdapter);
setListViewHeightBasedOnChildren(loopListView); setListViewHeightBasedOnChildren(loopListView);
if (MainApp.getSpecificPluginsVisibleInList(PluginBase.LOOP).size() == 0) if (MainApp.getSpecificPluginsVisibleInList(PluginType.LOOP).size() == 0)
loopLabel.setVisibility(View.GONE); 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); treatmentsListView.setAdapter(treatmentDataAdapter);
setListViewHeightBasedOnChildren(treatmentsListView); setListViewHeightBasedOnChildren(treatmentsListView);
if (MainApp.getSpecificPluginsVisibleInList(PluginBase.TREATMENT).size() == 0) if (MainApp.getSpecificPluginsVisibleInList(PluginType.TREATMENT).size() == 0)
treatmentsLabel.setVisibility(View.GONE); 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); profileListView.setAdapter(profileDataAdapter);
if (MainApp.getSpecificPluginsVisibleInList(PluginBase.PROFILE).size() == 0) if (MainApp.getSpecificPluginsVisibleInList(PluginType.PROFILE).size() == 0)
profileLabel.setVisibility(View.GONE); profileLabel.setVisibility(View.GONE);
setListViewHeightBasedOnChildren(profileListView); 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); apsListView.setAdapter(apsDataAdapter);
setListViewHeightBasedOnChildren(apsListView); setListViewHeightBasedOnChildren(apsListView);
if (MainApp.getSpecificPluginsVisibleInList(PluginBase.APS).size() == 0) if (MainApp.getSpecificPluginsVisibleInList(PluginType.APS).size() == 0)
apsLabel.setVisibility(View.GONE); 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); sensitivityListView.setAdapter(sensivityDataAdapter);
setListViewHeightBasedOnChildren(sensitivityListView); 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); constraintsListView.setAdapter(constraintsDataAdapter);
setListViewHeightBasedOnChildren(constraintsListView); setListViewHeightBasedOnChildren(constraintsListView);
if (MainApp.getSpecificPluginsVisibleInList(PluginBase.CONSTRAINTS).size() == 0) if (MainApp.getSpecificPluginsVisibleInList(PluginType.CONSTRAINTS).size() == 0)
constraintsLabel.setVisibility(View.GONE); 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); generalListView.setAdapter(generalDataAdapter);
setListViewHeightBasedOnChildren(generalListView); setListViewHeightBasedOnChildren(generalListView);
} }
/* /*
@ -192,10 +188,10 @@ public class ConfigBuilderFragment extends Fragment {
private class PluginCustomAdapter extends ArrayAdapter<PluginBase> { private class PluginCustomAdapter extends ArrayAdapter<PluginBase> {
private ArrayList<PluginBase> pluginList; private ArrayList<PluginBase> pluginList;
final private int type; final private PluginType type;
public PluginCustomAdapter(Context context, int textViewResourceId, PluginCustomAdapter(Context context, int textViewResourceId,
ArrayList<PluginBase> pluginList, int type) { ArrayList<PluginBase> pluginList, PluginType type) {
super(context, textViewResourceId, pluginList); super(context, textViewResourceId, pluginList);
this.pluginList = new ArrayList<>(); this.pluginList = new ArrayList<>();
this.pluginList.addAll(pluginList); this.pluginList.addAll(pluginList);
@ -209,10 +205,11 @@ public class ConfigBuilderFragment extends Fragment {
ImageView settings; ImageView settings;
} }
@NonNull
@Override @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); PluginBase plugin = pluginList.get(position);
if (view == null) { if (view == null) {
@ -231,60 +228,45 @@ public class ConfigBuilderFragment extends Fragment {
view.setTag(holder); view.setTag(holder);
holder.checkboxEnabled.setOnClickListener(new View.OnClickListener() { holder.checkboxEnabled.setOnClickListener(v -> {
public void onClick(View v) {
CheckBox cb = (CheckBox) v; CheckBox cb = (CheckBox) v;
PluginBase plugin = (PluginBase) cb.getTag(); PluginBase plugin1 = (PluginBase) cb.getTag();
plugin.setFragmentEnabled(type, cb.isChecked()); plugin1.setPluginEnabled(type, cb.isChecked());
plugin.setFragmentVisible(type, cb.isChecked()); plugin1.setFragmentVisible(type, cb.isChecked());
onEnabledCategoryChanged(plugin, type); onEnabledCategoryChanged(plugin1, type);
configBuilderPlugin.storeSettings(); ConfigBuilderPlugin.getPlugin().storeSettings("CheckedCheckboxEnabled");
MainApp.bus().post(new EventRefreshGui()); MainApp.bus().post(new EventRefreshGui());
MainApp.bus().post(new EventConfigBuilderChange()); MainApp.bus().post(new EventConfigBuilderChange());
getPlugin().logPluginStatus(); ConfigBuilderPlugin.getPlugin().logPluginStatus();
FabricPrivacy.getInstance().logCustom(new CustomEvent("ConfigurationChange")); FabricPrivacy.getInstance().logCustom(new CustomEvent("ConfigurationChange"));
}
}); });
holder.checkboxVisible.setOnClickListener(new View.OnClickListener() { holder.checkboxVisible.setOnClickListener(v -> {
public void onClick(View v) {
CheckBox cb = (CheckBox) v; CheckBox cb = (CheckBox) v;
PluginBase plugin = (PluginBase) cb.getTag(); PluginBase plugin12 = (PluginBase) cb.getTag();
plugin.setFragmentVisible(type, cb.isChecked()); plugin12.setFragmentVisible(type, cb.isChecked());
configBuilderPlugin.storeSettings(); ConfigBuilderPlugin.getPlugin().storeSettings("CheckedCheckboxVisible");
MainApp.bus().post(new EventRefreshGui()); MainApp.bus().post(new EventRefreshGui());
getPlugin().logPluginStatus(); ConfigBuilderPlugin.getPlugin().logPluginStatus();
}
}); });
holder.settings.setOnClickListener(new View.OnClickListener() { holder.settings.setOnClickListener(v -> {
public void onClick(View v) { final PluginBase plugin13 = (PluginBase) v.getTag();
final PluginBase plugin = (PluginBase) v.getTag(); PasswordProtection.QueryPassword(getContext(), R.string.settings_password, "settings_password", () -> {
PasswordProtection.QueryPassword(getContext(), R.string.settings_password, "settings_password", new Runnable() {
@Override
public void run() {
Intent i = new Intent(getContext(), PreferencesActivity.class); Intent i = new Intent(getContext(), PreferencesActivity.class);
i.putExtra("id", plugin.getPreferencesId()); i.putExtra("id", plugin13.getPreferencesId());
startActivity(i); startActivity(i);
}
}, null); }, null);
}
}); });
holder.name.setOnLongClickListener(new View.OnLongClickListener() { holder.name.setOnLongClickListener(v -> {
@Override final PluginBase plugin14 = (PluginBase) v.getTag();
public boolean onLongClick(View v) { PasswordProtection.QueryPassword(getContext(), R.string.settings_password, "settings_password", () -> {
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); Intent i = new Intent(getContext(), PreferencesActivity.class);
i.putExtra("id", plugin.getPreferencesId()); i.putExtra("id", plugin14.getPreferencesId());
startActivity(i); startActivity(i);
}
}, null); }, null);
return false; return false;
}
}); });
} else { } else {
@ -293,15 +275,18 @@ public class ConfigBuilderFragment extends Fragment {
holder.name.setText(plugin.getName()); holder.name.setText(plugin.getName());
holder.checkboxEnabled.setChecked(plugin.isEnabled(type)); holder.checkboxEnabled.setChecked(plugin.isEnabled(type));
holder.checkboxVisible.setChecked(plugin.isVisibleInTabs(type)); holder.checkboxVisible.setChecked(plugin.isFragmentVisible());
holder.name.setTag(plugin); holder.name.setTag(plugin);
holder.checkboxEnabled.setTag(plugin); holder.checkboxEnabled.setTag(plugin);
holder.checkboxVisible.setTag(plugin); holder.checkboxVisible.setTag(plugin);
holder.settings.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.checkboxEnabled.setEnabled(false);
holder.checkboxVisible.setEnabled(false);
} }
if (!plugin.isEnabled(type)) { 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 // 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) { if (pluginList.size() < 2) {
holder.checkboxEnabled.setEnabled(false); holder.checkboxEnabled.setEnabled(false);
plugin.setFragmentEnabled(type, true); plugin.setPluginEnabled(type, true);
getPlugin().storeSettings(); ConfigBuilderPlugin.getPlugin().storeSettings("ForceEnable");
} }
// Constraints cannot be disabled // Constraints cannot be disabled
if (type == PluginBase.CONSTRAINTS) if (type == PluginType.CONSTRAINTS)
holder.checkboxEnabled.setEnabled(false); holder.checkboxEnabled.setEnabled(false);
// Hide disabled profiles by default // Hide disabled profiles by default
if (type == PluginBase.PROFILE) { if (type == PluginType.PROFILE) {
if (!plugin.isEnabled(type)) { if (!plugin.isEnabled(type)) {
holder.checkboxVisible.setEnabled(false); holder.checkboxVisible.setEnabled(false);
holder.checkboxVisible.setChecked(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 // 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 (PumpInterface.class.isAssignableFrom(plugin.getClass())) {
if (!plugin.isEnabled(PluginBase.PUMP)) { if (!plugin.isEnabled(PluginType.PUMP)) {
holder.checkboxEnabled.setEnabled(false); holder.checkboxEnabled.setEnabled(false);
holder.checkboxEnabled.setChecked(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; ArrayList<PluginBase> pluginsInCategory = null;
switch (type) { switch (type) {
// Multiple selection allowed // Multiple selection allowed
case PluginBase.GENERAL: case GENERAL:
case PluginBase.CONSTRAINTS: case CONSTRAINTS:
case PluginBase.LOOP: case LOOP:
break; break;
// Single selection allowed // Single selection allowed
case PluginBase.INSULIN: case INSULIN:
pluginsInCategory = MainApp.getSpecificPluginsListByInterface(InsulinInterface.class); pluginsInCategory = MainApp.getSpecificPluginsListByInterface(InsulinInterface.class);
break; break;
case PluginBase.SENSITIVITY: case SENSITIVITY:
pluginsInCategory = MainApp.getSpecificPluginsListByInterface(SensitivityInterface.class); pluginsInCategory = MainApp.getSpecificPluginsListByInterface(SensitivityInterface.class);
break; break;
case PluginBase.APS: case APS:
pluginsInCategory = MainApp.getSpecificPluginsListByInterface(APSInterface.class); pluginsInCategory = MainApp.getSpecificPluginsListByInterface(APSInterface.class);
break; break;
case PluginBase.PROFILE: case PROFILE:
pluginsInCategory = MainApp.getSpecificPluginsListByInterface(ProfileInterface.class); pluginsInCategory = MainApp.getSpecificPluginsListByInterface(ProfileInterface.class);
break; break;
case PluginBase.BGSOURCE: case BGSOURCE:
pluginsInCategory = MainApp.getSpecificPluginsListByInterface(BgSourceInterface.class); pluginsInCategory = MainApp.getSpecificPluginsListByInterface(BgSourceInterface.class);
break; break;
case PluginBase.TREATMENT: case TREATMENT:
case PluginBase.PUMP: case PUMP:
pluginsInCategory = MainApp.getSpecificPluginsListByInterface(PumpInterface.class); pluginsInCategory = MainApp.getSpecificPluginsListByInterface(PumpInterface.class);
break; break;
} }
@ -390,23 +375,23 @@ public class ConfigBuilderFragment extends Fragment {
if (p.getName().equals(changedPlugin.getName())) { if (p.getName().equals(changedPlugin.getName())) {
// this is new selected // this is new selected
} else { } else {
p.setFragmentEnabled(type, false); p.setPluginEnabled(type, false);
p.setFragmentVisible(type, false); p.setFragmentVisible(type, false);
} }
} }
} else { // enable first plugin in list } else { // enable first plugin in list
if (type == PluginBase.PUMP) if (type == PluginType.PUMP)
MainApp.getSpecificPlugin(VirtualPumpPlugin.class).setFragmentEnabled(type, true); VirtualPumpPlugin.getPlugin().setPluginEnabled(type, true);
else if (type == PluginBase.INSULIN) else if (type == PluginType.INSULIN)
MainApp.getSpecificPlugin(InsulinFastactingPlugin.class).setFragmentEnabled(type, true); InsulinOrefRapidActingPlugin.getPlugin().setPluginEnabled(type, true);
else if (type == PluginBase.SENSITIVITY) else if (type == PluginType.SENSITIVITY)
MainApp.getSpecificPlugin(SensitivityOref0Plugin.class).setFragmentEnabled(type, true); SensitivityOref0Plugin.getPlugin().setPluginEnabled(type, true);
else if (type == PluginBase.PROFILE) else if (type == PluginType.PROFILE)
MainApp.getSpecificPlugin(NSProfilePlugin.class).setFragmentEnabled(type, true); NSProfilePlugin.getPlugin().setPluginEnabled(type, true);
else else
pluginsInCategory.get(0).setFragmentEnabled(type, true); pluginsInCategory.get(0).setPluginEnabled(type, true);
} }
setViews(); updateGUI();
} }
} }

View file

@ -24,9 +24,10 @@ import java.util.List;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.plugins.Common.SubscriberFragment;
import info.nightscout.utils.FabricPrivacy; import info.nightscout.utils.FabricPrivacy;
public class ObjectivesFragment extends Fragment { public class ObjectivesFragment extends SubscriberFragment {
private static Logger log = LoggerFactory.getLogger(ObjectivesFragment.class); private static Logger log = LoggerFactory.getLogger(ObjectivesFragment.class);
RecyclerView recyclerView; RecyclerView recyclerView;
@ -84,37 +85,52 @@ public class ObjectivesFragment extends Fragment {
} }
}); });
Long now = System.currentTimeMillis(); long prevObjectiveAccomplishedTime = position > 0 ?
if (position > 0 && objectives.get(position - 1).accomplished.getTime() == 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 // Phase 0: previous not completed
holder.startedLayout.setVisibility(View.GONE); holder.startedLayout.setVisibility(View.GONE);
holder.durationLayout.setVisibility(View.GONE); holder.durationLayout.setVisibility(View.GONE);
holder.progressLayout.setVisibility(View.GONE); holder.progressLayout.setVisibility(View.GONE);
holder.verifyLayout.setVisibility(View.GONE); holder.verifyLayout.setVisibility(View.GONE);
} else if (o.started.getTime() == 0) { break;
case 1:
// Phase 1: not started // Phase 1: not started
holder.durationLayout.setVisibility(View.GONE); holder.durationLayout.setVisibility(View.GONE);
holder.progressLayout.setVisibility(View.GONE); holder.progressLayout.setVisibility(View.GONE);
holder.verifyLayout.setVisibility(View.GONE); holder.verifyLayout.setVisibility(View.GONE);
holder.started.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)) { break;
case 2:
// Phase 2: started, waiting for duration and met requirements // Phase 2: started, waiting for duration and met requirements
holder.startButton.setEnabled(false); holder.startButton.setEnabled(false);
holder.verifyLayout.setVisibility(View.GONE); holder.verifyLayout.setVisibility(View.GONE);
} else if (o.accomplished.getTime() == 0) { break;
case 3:
// Phase 3: started, after duration, requirements met // Phase 3: started, after duration, requirements met
holder.startButton.setEnabled(false); holder.startButton.setEnabled(false);
holder.accomplished.setVisibility(View.INVISIBLE); holder.accomplished.setVisibility(View.INVISIBLE);
} else { break;
case 4:
// Phase 4: verified // Phase 4: verified
holder.gateLayout.setVisibility(View.GONE); holder.gateLayout.setVisibility(View.GONE);
holder.startedLayout.setVisibility(View.GONE); holder.startedLayout.setVisibility(View.GONE);
holder.durationLayout.setVisibility(View.GONE); holder.durationLayout.setVisibility(View.GONE);
holder.progressLayout.setVisibility(View.GONE); holder.progressLayout.setVisibility(View.GONE);
holder.verifyButton.setVisibility(View.INVISIBLE); holder.verifyButton.setVisibility(View.INVISIBLE);
break;
default:
// should not happen
} }
} }
@Override @Override
public int getItemCount() { public int getItemCount() {
return objectives.size(); return objectives.size();
@ -163,6 +179,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 + durationInDays * 24 * 60 * 60 * 1000 >= now && requirementsMet)) {
return 2;
} else if (objectiveAccomplishedTime == 0) {
return 3;
} else {
return 4;
}
}
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) { Bundle savedInstanceState) {
@ -204,6 +254,7 @@ public class ObjectivesFragment extends Fragment {
ObjectivesPlugin.objectives.get(3).gate = MainApp.sResources.getString(R.string.objectives_3_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(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(5).gate = MainApp.sResources.getString(R.string.objectives_5_gate);
updateGUI(); updateGUI();
return view; return view;
@ -214,15 +265,13 @@ public class ObjectivesFragment extends Fragment {
return null; return null;
} }
void updateGUI() { @Override
public void updateGUI() {
Activity activity = getActivity(); Activity activity = getActivity();
if (activity != null) if (activity != null)
activity.runOnUiThread(new Runnable() { activity.runOnUiThread(() -> {
@Override
public void run() {
RecyclerViewAdapter adapter = new RecyclerViewAdapter(ObjectivesPlugin.objectives); RecyclerViewAdapter adapter = new RecyclerViewAdapter(ObjectivesPlugin.objectives);
recyclerView.setAdapter(adapter); recyclerView.setAdapter(adapter);
}
}); });
} }

View file

@ -10,25 +10,30 @@ import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import info.nightscout.androidaps.BuildConfig;
import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.db.DatabaseHelper; import info.nightscout.androidaps.db.DatabaseHelper;
import info.nightscout.androidaps.interfaces.APSInterface; import info.nightscout.androidaps.interfaces.APSInterface;
import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.interfaces.ConstraintsInterface; import info.nightscout.androidaps.interfaces.ConstraintsInterface;
import info.nightscout.androidaps.interfaces.PluginBase; 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.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.ConstraintsSafety.SafetyPlugin; import info.nightscout.androidaps.plugins.ConstraintsSafety.SafetyPlugin;
import info.nightscout.androidaps.plugins.Loop.LoopPlugin; 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.PumpVirtual.VirtualPumpPlugin;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.SP; import info.nightscout.utils.SP;
/** /**
* Created by mike on 05.08.2016. * 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 Logger log = LoggerFactory.getLogger(ObjectivesPlugin.class);
private static ObjectivesPlugin objectivesPlugin; private static ObjectivesPlugin objectivesPlugin;
@ -42,80 +47,26 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface {
public static List<Objective> objectives; public static List<Objective> objectives;
private boolean fragmentVisible = true;
private ObjectivesPlugin() { 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(); initializeData();
loadProgress(); loadProgress();
MainApp.bus().register(this);
} }
@Override @Override
public String getFragmentClass() { public boolean specialEnableCondition() {
return ObjectivesFragment.class.getName(); PumpInterface pump = ConfigBuilderPlugin.getActivePump();
return pump == null || pump.getPumpDescription().isTempBasalCapable;
} }
@Override public class Objective {
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 {
Integer num; Integer num;
String objective; String objective;
String gate; String gate;
@ -131,6 +82,18 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface {
this.durationInDays = durationInDays; this.durationInDays = durationInDays;
this.accomplished = accomplished; 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 // Objective 0
@ -158,37 +121,41 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface {
RequirementResult requirementsMet(Integer objNum) { RequirementResult requirementsMet(Integer objNum) {
switch (objNum) { switch (objNum) {
case 0: case 0:
boolean isVirtualPump = VirtualPumpPlugin.getPlugin().isEnabled(PluginBase.PUMP); boolean isVirtualPump = VirtualPumpPlugin.getPlugin().isEnabled(PluginType.PUMP);
boolean vpUploadEnabled = SP.getBoolean("virtualpump_uploadstatus", false); boolean vpUploadEnabled = SP.getBoolean("virtualpump_uploadstatus", false);
boolean vpUploadNeeded = !isVirtualPump || vpUploadEnabled; boolean vpUploadNeeded = !isVirtualPump || vpUploadEnabled;
boolean hasBGData = DatabaseHelper.lastBg() != null; boolean hasBGData = DatabaseHelper.lastBg() != null;
boolean apsEnabled = false; boolean apsEnabled = false;
APSInterface usedAPS = ConfigBuilderPlugin.getActiveAPS(); APSInterface usedAPS = ConfigBuilderPlugin.getActiveAPS();
if (usedAPS != null && ((PluginBase) usedAPS).isEnabled(PluginBase.APS)) if (usedAPS != null && ((PluginBase) usedAPS).isEnabled(PluginType.APS))
apsEnabled = true; apsEnabled = true;
return new RequirementResult(hasBGData && bgIsAvailableInNS && pumpStatusIsAvailableInNS && NSClientInternalPlugin.getPlugin().hasWritePermission() && LoopPlugin.getPlugin().isEnabled(PluginBase.LOOP) && apsEnabled && vpUploadNeeded, boolean profileSwitchExists = TreatmentsPlugin.getPlugin().getProfileSwitchFromHistory(DateUtil.now()) != null;
MainApp.sResources.getString(R.string.objectives_bgavailableinns) + ": " + yesOrNo(bgIsAvailableInNS)
+ "\n" + MainApp.sResources.getString(R.string.nsclienthaswritepermission) + ": " + yesOrNo(NSClientInternalPlugin.getPlugin().hasWritePermission()) return new RequirementResult(hasBGData && bgIsAvailableInNS && pumpStatusIsAvailableInNS && NSClientPlugin.getPlugin().hasWritePermission() && LoopPlugin.getPlugin().isEnabled(PluginType.LOOP) && apsEnabled && vpUploadNeeded && profileSwitchExists,
+ (isVirtualPump ? "\n" + MainApp.sResources.getString(R.string.virtualpump_uploadstatus_title) + ": " + yesOrNo(vpUploadEnabled) : "") MainApp.gs(R.string.objectives_bgavailableinns) + ": " + yesOrNo(bgIsAvailableInNS)
+ "\n" + MainApp.sResources.getString(R.string.objectives_pumpstatusavailableinns) + ": " + yesOrNo(pumpStatusIsAvailableInNS) + "\n" + MainApp.gs(R.string.nsclienthaswritepermission) + ": " + yesOrNo(NSClientPlugin.getPlugin().hasWritePermission())
+ "\n" + MainApp.sResources.getString(R.string.hasbgdata) + ": " + yesOrNo(hasBGData) + (isVirtualPump ? "\n" + MainApp.gs(R.string.virtualpump_uploadstatus_title) + ": " + yesOrNo(vpUploadEnabled) : "")
+ "\n" + MainApp.sResources.getString(R.string.loopenabled) + ": " + yesOrNo(LoopPlugin.getPlugin().isEnabled(PluginBase.LOOP)) + "\n" + MainApp.gs(R.string.objectives_pumpstatusavailableinns) + ": " + yesOrNo(pumpStatusIsAvailableInNS)
+ "\n" + MainApp.sResources.getString(R.string.apsselected) + ": " + yesOrNo(apsEnabled) + "\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: case 1:
return new RequirementResult(manualEnacts >= manualEnactsNeeded, return new RequirementResult(manualEnacts >= manualEnactsNeeded,
MainApp.sResources.getString(R.string.objectives_manualenacts) + ": " + manualEnacts + "/" + manualEnactsNeeded); MainApp.gs(R.string.objectives_manualenacts) + ": " + manualEnacts + "/" + manualEnactsNeeded);
case 2: case 2:
return new RequirementResult(true, ""); return new RequirementResult(true, "");
case 3: case 3:
boolean closedModeEnabled = SafetyPlugin.getPlugin().isClosedModeEnabled(); Constraint<Boolean> closedLoopEnabled = new Constraint<>(true);
return new RequirementResult(closedModeEnabled, MainApp.sResources.getString(R.string.closedmodeenabled) + ": " + yesOrNo(closedModeEnabled)); SafetyPlugin.getPlugin().isClosedLoopAllowed(closedLoopEnabled);
return new RequirementResult(closedLoopEnabled.value(), MainApp.gs(R.string.closedmodeenabled) + ": " + yesOrNo(closedLoopEnabled.value()));
case 4: case 4:
double maxIOB = MainApp.getConfigBuilder().applyMaxIOBConstraints(1000d); double maxIOB = MainApp.getConstraintChecker().getMaxIOBAllowed().value();
boolean maxIobSet = maxIOB > 0; 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: default:
return new RequirementResult(true, ""); return new RequirementResult(true, "");
} }
@ -202,49 +169,49 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface {
objectives = new ArrayList<>(); objectives = new ArrayList<>();
objectives.add(new Objective(0, objectives.add(new Objective(0,
MainApp.sResources.getString(R.string.objectives_0_objective), MainApp.gs(R.string.objectives_0_objective),
MainApp.sResources.getString(R.string.objectives_0_gate), MainApp.gs(R.string.objectives_0_gate),
new Date(0), new Date(0),
0, // 0 day 0, // 0 day
new Date(0))); new Date(0)));
objectives.add(new Objective(1, objectives.add(new Objective(1,
MainApp.sResources.getString(R.string.objectives_1_objective), MainApp.gs(R.string.objectives_1_objective),
MainApp.sResources.getString(R.string.objectives_1_gate), MainApp.gs(R.string.objectives_1_gate),
new Date(0), new Date(0),
7, // 7 days 7, // 7 days
new Date(0))); new Date(0)));
objectives.add(new Objective(2, objectives.add(new Objective(2,
MainApp.sResources.getString(R.string.objectives_2_objective), MainApp.gs(R.string.objectives_2_objective),
MainApp.sResources.getString(R.string.objectives_2_gate), MainApp.gs(R.string.objectives_2_gate),
new Date(0), new Date(0),
0, // 0 days 0, // 0 days
new Date(0))); new Date(0)));
objectives.add(new Objective(3, objectives.add(new Objective(3,
MainApp.sResources.getString(R.string.objectives_3_objective), MainApp.gs(R.string.objectives_3_objective),
MainApp.sResources.getString(R.string.objectives_3_gate), MainApp.gs(R.string.objectives_3_gate),
new Date(0), new Date(0),
5, // 5 days 5, // 5 days
new Date(0))); new Date(0)));
objectives.add(new Objective(4, objectives.add(new Objective(4,
MainApp.sResources.getString(R.string.objectives_4_objective), MainApp.gs(R.string.objectives_4_objective),
MainApp.sResources.getString(R.string.objectives_4_gate), MainApp.gs(R.string.objectives_4_gate),
new Date(0), new Date(0),
1, 1,
new Date(0))); new Date(0)));
objectives.add(new Objective(5, objectives.add(new Objective(5,
MainApp.sResources.getString(R.string.objectives_5_objective), MainApp.gs(R.string.objectives_5_objective),
MainApp.sResources.getString(R.string.objectives_5_gate), MainApp.gs(R.string.objectives_5_gate),
new Date(0), new Date(0),
7, 7,
new Date(0))); new Date(0)));
objectives.add(new Objective(6, objectives.add(new Objective(6,
MainApp.sResources.getString(R.string.objectives_6_objective), MainApp.gs(R.string.objectives_6_objective),
"", "",
new Date(0), new Date(0),
28, 28,
new Date(0))); new Date(0)));
objectives.add(new Objective(7, objectives.add(new Objective(7,
MainApp.sResources.getString(R.string.objectives_7_objective), MainApp.gs(R.string.objectives_7_objective),
"", "",
new Date(0), new Date(0),
28, 28,
@ -294,60 +261,45 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface {
* Constraints interface * Constraints interface
**/ **/
@Override @Override
public boolean isLoopEnabled() { public Constraint<Boolean> isLoopInvokationAllowed(Constraint<Boolean> value) {
return objectives.get(0).started.getTime() > 0; if (!objectives.get(0).isStarted())
value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), 1), this);
return value;
} }
@Override @Override
public boolean isClosedModeEnabled() { public Constraint<Boolean> isClosedLoopAllowed(Constraint<Boolean> value) {
return objectives.get(3).started.getTime() > 0; if (!objectives.get(3).isStarted())
value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), 4), this);
return value;
} }
@Override @Override
public boolean isAutosensModeEnabled() { public Constraint<Boolean> isAutosensModeEnabled(Constraint<Boolean> value) {
return objectives.get(5).started.getTime() > 0; if (!objectives.get(5).isStarted())
value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), 6), this);
return value;
} }
@Override @Override
public boolean isAMAModeEnabled() { public Constraint<Boolean> isAMAModeEnabled(Constraint<Boolean> value) {
return objectives.get(6).started.getTime() > 0; if (!objectives.get(6).isStarted())
value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), 7), this);
return value;
} }
@Override @Override
public boolean isSMBModeEnabled() { public Constraint<Boolean> isSMBModeEnabled(Constraint<Boolean> value) {
return objectives.get(7).started.getTime() > 0; if (!objectives.get(7).isStarted())
value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), 8), this);
return value;
} }
@Override @Override
public Double applyMaxIOBConstraints(Double maxIob) { public Constraint<Double> applyMaxIOBConstraints(Constraint<Double> maxIob) {
if (objectives.get(3).started.getTime() > 0 && objectives.get(3).accomplished.getTime() == 0) { if (objectives.get(3).isStarted() && !objectives.get(3).isFinished())
if (Config.logConstraintsChanges) maxIob.set(0d, String.format(MainApp.gs(R.string.objectivenotfinished), 4), this);
log.debug("Limiting maxIOB " + maxIob + " to " + 0 + "U");
return 0d;
} else {
return maxIob; 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;
}
} }

View file

@ -1,19 +1,22 @@
package info.nightscout.androidaps.plugins.ConstraintsSafety; 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.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.ConstraintChecker;
import info.nightscout.androidaps.data.Profile; 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.ConstraintsInterface;
import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConfigBuilder.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.HardLimits;
import info.nightscout.utils.Round; import info.nightscout.utils.Round;
import info.nightscout.utils.SP; import info.nightscout.utils.SP;
@ -21,8 +24,7 @@ import info.nightscout.utils.SP;
/** /**
* Created by mike on 05.08.2016. * Created by mike on 05.08.2016.
*/ */
public class SafetyPlugin implements PluginBase, ConstraintsInterface { public class SafetyPlugin extends PluginBase implements ConstraintsInterface {
private static Logger log = LoggerFactory.getLogger(SafetyPlugin.class);
static SafetyPlugin plugin = null; static SafetyPlugin plugin = null;
@ -32,201 +34,154 @@ public class SafetyPlugin implements PluginBase, ConstraintsInterface {
return plugin; return plugin;
} }
@Override public SafetyPlugin() {
public String getFragmentClass() { super(new PluginDescription()
return null; .mainType(PluginType.CONSTRAINTS)
} .neverVisible(true)
.alwaysEnabled(true)
@Override .showInList(false)
public int getType() { .pluginName(R.string.safety)
return PluginBase.CONSTRAINTS; .preferencesId(R.xml.pref_safety)
} );
@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;
} }
/** /**
* Constraints interface * Constraints interface
**/ **/
@Override @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"); 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 @Override
public boolean isAutosensModeEnabled() { public Constraint<Boolean> isAutosensModeEnabled(Constraint<Boolean> value) {
return true; boolean enabled = SP.getBoolean(R.string.key_openapsama_useautosens, false);
if (!enabled)
value.set(false, MainApp.gs(R.string.autosensdisabledinpreferences), this);
return value;
} }
@Override @Override
public boolean isAMAModeEnabled() { public Constraint<Boolean> isSMBModeEnabled(Constraint<Boolean> value) {
return true; 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 @Override
public boolean isSMBModeEnabled() { public Constraint<Boolean> isAdvancedFilteringEnabled(Constraint<Boolean> value) {
return true; BgSourceInterface bgSource = MainApp.getConfigBuilder().getActiveBgSource();
if (bgSource != null) {
if (!bgSource.advancedFilteringSupported())
value.set(false, MainApp.gs(R.string.smbalwaysdisabled), this);
}
return value;
} }
@Override @Override
public Double applyBasalConstraints(Double absoluteRate) { public Constraint<Double> applyBasalConstraints(Constraint<Double> absoluteRate, Profile profile) {
Double origAbsoluteRate = absoluteRate;
Double maxBasal = SP.getDouble("openapsma_max_basal", 1d);
Profile profile = MainApp.getConfigBuilder().getProfile(); absoluteRate.setIfGreater(0d, String.format(MainApp.gs(R.string.limitingbasalratio), 0d, MainApp.gs(R.string.itmustbepositivevalue)), this);
if (profile == null) return absoluteRate;
if (absoluteRate < 0) absoluteRate = 0d; 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);
Double maxBasalMult = SP.getDouble("openapsama_current_basal_safety_multiplier", 4d);
Integer maxBasalFromDaily = SP.getInt("openapsama_max_daily_safety_multiplier", 3);
// Check percentRate but absolute rate too, because we know real current basal in pump // Check percentRate but absolute rate too, because we know real current basal in pump
Double origRate = absoluteRate; Double maxBasalMult = SP.getDouble(R.string.key_openapsama_current_basal_safety_multiplier, 4d);
if (absoluteRate > maxBasal) { double maxFromBasalMult = Math.floor(maxBasalMult * profile.getBasal() * 100) / 100;
absoluteRate = maxBasal; absoluteRate.setIfSmaller(maxFromBasalMult, String.format(MainApp.gs(R.string.limitingbasalratio), maxFromBasalMult, MainApp.gs(R.string.maxbasalmultiplier)), this);
if (Config.logConstraintsChanges && origAbsoluteRate != Constants.basalAbsoluteOnlyForCheckLimit)
log.debug("Limiting rate " + origRate + " by maxBasal preference to " + absoluteRate + "U/h"); Double maxBasalFromDaily = SP.getDouble(R.string.key_openapsama_max_daily_safety_multiplier, 3d);
} double maxFromDaily = Math.floor(profile.getMaxDailyBasal() * maxBasalFromDaily * 100) / 100;
if (absoluteRate > maxBasalMult * profile.getBasal()) { absoluteRate.setIfSmaller(maxFromDaily, String.format(MainApp.gs(R.string.limitingbasalratio), maxFromDaily, MainApp.gs(R.string.maxdailybasalmultiplier)), this);
absoluteRate = Math.floor(maxBasalMult * profile.getBasal() * 100) / 100;
if (Config.logConstraintsChanges && origAbsoluteRate != Constants.basalAbsoluteOnlyForCheckLimit) absoluteRate.setIfSmaller(HardLimits.maxBasal(), String.format(MainApp.gs(R.string.limitingbasalratio), HardLimits.maxBasal(), MainApp.gs(R.string.hardlimit)), this);
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");
}
return absoluteRate; return absoluteRate;
} }
@Override @Override
public Integer applyBasalConstraints(Integer percentRate) { public Constraint<Integer> applyBasalPercentConstraints(Constraint<Integer> percentRate, Profile profile) {
Integer origPercentRate = percentRate;
Double maxBasal = SP.getDouble("openapsma_max_basal", 1d);
Profile profile = MainApp.getConfigBuilder().getProfile();
if (profile == null) return percentRate;
Double currentBasal = profile.getBasal(); 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) Constraint<Double> absoluteConstraint = new Constraint<>(absoluteRate);
log.debug("Percent rate " + percentRate + "% recalculated to " + absoluteRate + "U/h with current basal " + currentBasal + "U/h"); applyBasalConstraints(absoluteConstraint, profile);
percentRate.copyReasons(absoluteConstraint);
if (absoluteRate < 0) absoluteRate = 0d; Integer percentRateAfterConst = Double.valueOf(absoluteConstraint.value() / currentBasal * 100).intValue();
Double maxBasalMult = SP.getDouble("openapsama_current_basal_safety_multiplier", 4d);
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();
if (percentRateAfterConst < 100) if (percentRateAfterConst < 100)
percentRateAfterConst = Round.ceilTo((double) percentRateAfterConst, 10d).intValue(); percentRateAfterConst = Round.ceilTo((double) percentRateAfterConst, 10d).intValue();
else percentRateAfterConst = Round.floorTo((double) percentRateAfterConst, 10d).intValue(); else percentRateAfterConst = Round.floorTo((double) percentRateAfterConst, 10d).intValue();
if (Config.logConstraintsChanges && !Objects.equals(origPercentRate, Constants.basalPercentOnlyForCheckLimit)) percentRate.set(percentRateAfterConst, String.format(MainApp.gs(R.string.limitingpercentrate), percentRateAfterConst, MainApp.gs(R.string.pumplimit)), this);
log.debug("Recalculated percent rate " + percentRate + "% to " + percentRateAfterConst + "%");
return percentRateAfterConst; return percentRate;
} }
@Override @Override
public Double applyBolusConstraints(Double insulin) { public Constraint<Double> applyBolusConstraints(Constraint<Double> insulin) {
try { insulin.setIfGreater(0d, String.format(MainApp.gs(R.string.limitingbolus), 0d, MainApp.gs(R.string.itmustbepositivevalue)), this);
Double maxBolus = SP.getDouble("treatmentssafety_maxbolus", 3d);
if (insulin < 0) insulin = 0d; Double maxBolus = SP.getDouble(R.string.key_treatmentssafety_maxbolus, 3d);
if (insulin > maxBolus) insulin = maxBolus; insulin.setIfSmaller(maxBolus, String.format(MainApp.gs(R.string.limitingbolus), maxBolus, MainApp.gs(R.string.maxvalueinpreferences)), this);
} catch (Exception e) {
insulin = 0d; insulin.setIfSmaller(HardLimits.maxBolus(), String.format(MainApp.gs(R.string.limitingbolus), HardLimits.maxBolus(), MainApp.gs(R.string.hardlimit)), this);
}
if (insulin > HardLimits.maxBolus()) insulin = HardLimits.maxBolus();
return insulin; return insulin;
} }
@Override @Override
public Integer applyCarbsConstraints(Integer carbs) { public Constraint<Integer> applyCarbsConstraints(Constraint<Integer> carbs) {
try { carbs.setIfGreater(0, String.format(MainApp.gs(R.string.limitingcarbs), 0, MainApp.gs(R.string.itmustbepositivevalue)), this);
Integer maxCarbs = SP.getInt("treatmentssafety_maxcarbs", 48);
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; return carbs;
} }
@Override @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; return maxIob;
} }

View file

@ -5,8 +5,6 @@ import com.j256.ormlite.table.DatabaseTable;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Objects; import java.util.Objects;
@ -18,9 +16,7 @@ import info.nightscout.utils.JsonHelper;
@DatabaseTable(tableName = Food.TABLE_FOODS) @DatabaseTable(tableName = Food.TABLE_FOODS)
public class Food { public class Food {
private static Logger log = LoggerFactory.getLogger(Food.class); static final String TABLE_FOODS = "Foods";
public static final String TABLE_FOODS = "Foods";
@DatabaseField(id = true) @DatabaseField(id = true)
public long key; public long key;
@ -65,7 +61,7 @@ public class Food {
@DatabaseField @DatabaseField
public int gi; // not used yet public int gi; // not used yet
public Food() { private Food() {
key = System.currentTimeMillis(); key = System.currentTimeMillis();
} }

View file

@ -1,90 +1,33 @@
package info.nightscout.androidaps.plugins.Food; package info.nightscout.androidaps.plugins.Food;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.interfaces.PluginBase; 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. * Created by mike on 05.08.2016.
*/ */
public class FoodPlugin implements PluginBase { public class FoodPlugin extends PluginBase {
private boolean fragmentEnabled = true;
private boolean fragmentVisible = false;
private static FoodPlugin plugin = null; private static FoodPlugin plugin = null;
private FoodService service;
private FoodPlugin() {
this.service = new FoodService();
}
public static FoodPlugin getPlugin() { public static FoodPlugin getPlugin() {
if (plugin == null) if (plugin == null)
plugin = new FoodPlugin(); plugin = new FoodPlugin();
return plugin; return plugin;
} }
@Override private FoodService service;
public String getFragmentClass() {
return FoodFragment.class.getName();
}
@Override private FoodPlugin() {
public int getType() { super(new PluginDescription()
return PluginBase.GENERAL; .mainType(PluginType.GENERAL)
} .fragmentClass(FoodFragment.class.getName())
.pluginName(R.string.food)
@Override .shortName(R.string.food_short)
public String getName() { );
return MainApp.instance().getString(R.string.food); this.service = new FoodService();
}
@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;
} }
public FoodService getService() { public FoodService getService() {

View file

@ -347,6 +347,7 @@ public class FoodService extends OrmLiteBaseService<DatabaseHelper> {
* @param _id * @param _id
* @return * @return
*/ */
@Nullable
public Food findByNSId(String _id) { public Food findByNSId(String _id) {
try { try {
List<Food> list = this.getDao().queryForEq("_id", _id); List<Food> list = this.getDao().queryForEq("_id", _id);

View file

@ -12,7 +12,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import info.nightscout.androidaps.data.Iob; 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.InsulinInterface;
/** /**

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -5,45 +5,31 @@ import com.squareup.otto.Bus;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Iob; 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.InsulinInterface;
import info.nightscout.androidaps.interfaces.PluginBase; 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.events.EventNewNotification;
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
/** /**
* Created by adrian on 13.08.2017. * 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; public static double MIN_DIA = 5;
long lastWarned = 0; long lastWarned = 0;
@Override public InsulinOrefBasePlugin() {
public int getType() { super(new PluginDescription()
return INSULIN; .mainType(PluginType.INSULIN)
} .fragmentClass(InsulinFragment.class.getName())
.pluginName(R.string.fastactinginsulin)
@Override .shortName(R.string.insulin_shortname)
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 Bus getBus() { public Bus getBus() {

View file

@ -10,9 +10,6 @@ import info.nightscout.utils.SP;
public class InsulinOrefFreePeakPlugin extends InsulinOrefBasePlugin { public class InsulinOrefFreePeakPlugin extends InsulinOrefBasePlugin {
private boolean fragmentEnabled = false;
private boolean fragmentVisible = false;
private static InsulinOrefFreePeakPlugin plugin = null; private static InsulinOrefFreePeakPlugin plugin = null;
public static InsulinOrefFreePeakPlugin getPlugin() { public static InsulinOrefFreePeakPlugin getPlugin() {
@ -21,24 +18,20 @@ public class InsulinOrefFreePeakPlugin extends InsulinOrefBasePlugin {
return plugin; 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 @Override
public int getId() { public int getId() {
return OREF_FREE_PEAK; 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() { public String getFriendlyName() {
return MainApp.sResources.getString(R.string.free_peak_oref); return MainApp.sResources.getString(R.string.free_peak_oref);
} }
@ -48,31 +41,6 @@ public class InsulinOrefFreePeakPlugin extends InsulinOrefBasePlugin {
return MainApp.sResources.getString(R.string.insulin_peak_time) + ": " + getPeak(); 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;
}
@Override @Override
int getPeak() { int getPeak() {
return SP.getInt(R.string.key_insulin_oref_peak, DEFAULT_PEAK); return SP.getInt(R.string.key_insulin_oref_peak, DEFAULT_PEAK);

View file

@ -9,9 +9,6 @@ import info.nightscout.androidaps.R;
public class InsulinOrefRapidActingPlugin extends InsulinOrefBasePlugin { public class InsulinOrefRapidActingPlugin extends InsulinOrefBasePlugin {
private boolean fragmentEnabled = false;
private boolean fragmentVisible = false;
private static InsulinOrefRapidActingPlugin plugin = null; private static InsulinOrefRapidActingPlugin plugin = null;
public static InsulinOrefRapidActingPlugin getPlugin() { public static InsulinOrefRapidActingPlugin getPlugin() {
@ -20,23 +17,19 @@ public class InsulinOrefRapidActingPlugin extends InsulinOrefBasePlugin {
return plugin; 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 @Override
public int getId() { public int getId() {
return OREF_RAPID_ACTING; 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 @Override
public String getFriendlyName() { public String getFriendlyName() {
return MainApp.sResources.getString(R.string.rapid_acting_oref); return MainApp.sResources.getString(R.string.rapid_acting_oref);
@ -47,31 +40,6 @@ public class InsulinOrefRapidActingPlugin extends InsulinOrefBasePlugin {
return MainApp.sResources.getString(R.string.fastactinginsulincomment); 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;
}
@Override @Override
int getPeak() { int getPeak() {
return PEAK; return PEAK;

View file

@ -9,9 +9,6 @@ import info.nightscout.androidaps.R;
public class InsulinOrefUltraRapidActingPlugin extends InsulinOrefBasePlugin { public class InsulinOrefUltraRapidActingPlugin extends InsulinOrefBasePlugin {
private boolean fragmentEnabled = false;
private boolean fragmentVisible = false;
private static InsulinOrefUltraRapidActingPlugin plugin = null; private static InsulinOrefUltraRapidActingPlugin plugin = null;
public static InsulinOrefUltraRapidActingPlugin getPlugin() { public static InsulinOrefUltraRapidActingPlugin getPlugin() {
@ -20,7 +17,13 @@ public class InsulinOrefUltraRapidActingPlugin extends InsulinOrefBasePlugin {
return plugin; return plugin;
} }
public static final int PEAK = 55; private static final int PEAK = 55;
private InsulinOrefUltraRapidActingPlugin() {
super();
pluginDescription
.pluginName(R.string.ultrarapid_oref);
}
@Override @Override
public int getId() { public int getId() {
@ -32,11 +35,6 @@ public class InsulinOrefUltraRapidActingPlugin extends InsulinOrefBasePlugin {
return MainApp.sResources.getString(R.string.ultrarapid_oref); return MainApp.sResources.getString(R.string.ultrarapid_oref);
} }
@Override
public String getFragmentClass() {
return InsulinFragment.class.getName();
}
@Override @Override
public String getFriendlyName() { public String getFriendlyName() {
return MainApp.sResources.getString(R.string.ultrarapid_oref); return MainApp.sResources.getString(R.string.ultrarapid_oref);
@ -47,31 +45,6 @@ public class InsulinOrefUltraRapidActingPlugin extends InsulinOrefBasePlugin {
return MainApp.sResources.getString(R.string.ultrafastactinginsulincomment); 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;
}
@Override @Override
int getPeak() { int getPeak() {
return PEAK; return PEAK;

View file

@ -7,22 +7,31 @@ import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.interfaces.PluginBase; 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.SensitivityAAPS.SensitivityAAPSPlugin;
import info.nightscout.androidaps.plugins.SensitivityWeightedAverage.SensitivityWeightedAveragePlugin; import info.nightscout.androidaps.plugins.SensitivityWeightedAverage.SensitivityWeightedAveragePlugin;
import info.nightscout.androidaps.plugins.Treatments.Treatment;
import info.nightscout.utils.SP; import info.nightscout.utils.SP;
/** /**
* Created by mike on 25.04.2017. * Created by mike on 25.04.2017.
*/ */
public class AutosensData { public class AutosensData implements DataPointWithLabelInterface {
private static Logger log = LoggerFactory.getLogger(AutosensData.class); private static Logger log = LoggerFactory.getLogger(AutosensData.class);
public void setChartTime(long chartTime) {
this.chartTime = chartTime;
}
static class CarbsInPast { static class CarbsInPast {
long time = 0L; long time = 0L;
double carbs = 0d; double carbs = 0d;
@ -33,20 +42,21 @@ public class AutosensData {
time = t.date; time = t.date;
carbs = t.carbs; carbs = t.carbs;
remaining = t.carbs; remaining = t.carbs;
if (SensitivityAAPSPlugin.getPlugin().isEnabled(PluginBase.SENSITIVITY) || SensitivityWeightedAveragePlugin.getPlugin().isEnabled(PluginBase.SENSITIVITY)) { if (SensitivityAAPSPlugin.getPlugin().isEnabled(PluginType.SENSITIVITY) || SensitivityWeightedAveragePlugin.getPlugin().isEnabled(PluginType.SENSITIVITY)) {
double maxAbsorptionHours = SP.getDouble(R.string.key_absorption_maxtime, 4d); double maxAbsorptionHours = SP.getDouble(R.string.key_absorption_maxtime, Constants.DEFAULT_MAX_ABSORPTION_TIME);
Profile profile = MainApp.getConfigBuilder().getProfile(t.date); Profile profile = MainApp.getConfigBuilder().getProfile(t.date);
double sens = Profile.toMgdl(profile.getIsf(t.date), profile.getUnits()); double sens = Profile.toMgdl(profile.getIsf(t.date), profile.getUnits());
double ic = profile.getIc(t.date); double ic = profile.getIc(t.date);
min5minCarbImpact = t.carbs / (maxAbsorptionHours * 60 / 5) * sens / ic; 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); 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 { } 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; public long time = 0L;
long chartTime;
public String pastSensitivity = ""; public String pastSensitivity = "";
public double deviation = 0d; public double deviation = 0d;
boolean nonCarbsDeviation = false; boolean nonCarbsDeviation = false;
@ -63,8 +73,11 @@ public class AutosensData {
public double autosensRatio = 1d; public double autosensRatio = 1d;
public double slopeFromMaxDeviation = 0; public double slopeFromMaxDeviation = 0;
public double slopeFromMinDeviation = 999; public double slopeFromMinDeviation = 999;
public double usedMinCarbsImpact = 0d;
public boolean failoverToMinAbsorbtionRate = false;
public String log(long time) { @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; 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;
} }
@ -72,15 +85,21 @@ public class AutosensData {
return (int) ((System.currentTimeMillis() - time) / 1000 / 60); return (int) ((System.currentTimeMillis() - time) / 1000 / 60);
} }
// remove carbs older than 4h // remove carbs older than timeframe
public void removeOldCarbs(long toTime) { 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++) { for (int i = 0; i < activeCarbsList.size(); i++) {
CarbsInPast c = activeCarbsList.get(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--); activeCarbsList.remove(i--);
if (c.remaining > 0) if (c.remaining > 0)
cob -= c.remaining; 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());
} }
} }
} }
@ -97,4 +116,57 @@ 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);
}
@Override
public int getSecondColor() {
return 0;
}
} }

View file

@ -0,0 +1,15 @@
package info.nightscout.androidaps.plugins.IobCobCalculator;
import android.support.annotation.Nullable;
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;
}
}

View file

@ -29,17 +29,31 @@ import info.nightscout.androidaps.events.EventNewBG;
import info.nightscout.androidaps.events.EventNewBasalProfile; import info.nightscout.androidaps.events.EventNewBasalProfile;
import info.nightscout.androidaps.events.EventPreferenceChange; import info.nightscout.androidaps.events.EventPreferenceChange;
import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventNewHistoryData; import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventNewHistoryData;
import info.nightscout.androidaps.plugins.OpenAPSSMB.OpenAPSSMBPlugin; 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 info.nightscout.utils.DateUtil;
import static info.nightscout.utils.DateUtil.now;
/** /**
* Created by mike on 24.04.2017. * Created by mike on 24.04.2017.
*/ */
public class IobCobCalculatorPlugin implements PluginBase { public class IobCobCalculatorPlugin extends PluginBase {
private static Logger log = LoggerFactory.getLogger(IobCobCalculatorPlugin.class); private Logger log = LoggerFactory.getLogger(IobCobCalculatorPlugin.class);
private static IobCobCalculatorPlugin plugin = null;
public static IobCobCalculatorPlugin getPlugin() {
if (plugin == null)
plugin = new IobCobCalculatorPlugin();
return plugin;
}
private LongSparseArray<IobTotal> iobTable = new LongSparseArray<>(); // oldest at index 0 private LongSparseArray<IobTotal> iobTable = new LongSparseArray<>(); // oldest at index 0
private LongSparseArray<AutosensData> autosensDataTable = new LongSparseArray<>(); // oldest at index 0 private LongSparseArray<AutosensData> autosensDataTable = new LongSparseArray<>(); // oldest at index 0
@ -55,12 +69,26 @@ public class IobCobCalculatorPlugin implements PluginBase {
boolean stopCalculationTrigger = false; boolean stopCalculationTrigger = false;
private IobCobThread thread = null; private IobCobThread thread = null;
private static IobCobCalculatorPlugin plugin = null; public IobCobCalculatorPlugin() {
super(new PluginDescription()
.mainType(PluginType.GENERAL)
.pluginName(R.string.iobcobcalculator)
.showInList(false)
.neverVisible(true)
.alwaysEnabled(true)
);
}
public static IobCobCalculatorPlugin getPlugin() { @Override
if (plugin == null) protected void onStart() {
plugin = new IobCobCalculatorPlugin(); MainApp.bus().register(this);
return plugin; super.onStart();
}
@Override
protected void onStop() {
super.onStop();
MainApp.bus().unregister(this);
} }
public LongSparseArray<AutosensData> getAutosensDataTable() { public LongSparseArray<AutosensData> getAutosensDataTable() {
@ -71,70 +99,6 @@ public class IobCobCalculatorPlugin implements PluginBase {
return bucketed_data; 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;
}
public IobCobCalculatorPlugin() {
MainApp.bus().register(this);
}
@Nullable @Nullable
public List<BgReading> getBucketedData(long fromTime) { public List<BgReading> getBucketedData(long fromTime) {
//log.debug("Locking getBucketedData"); //log.debug("Locking getBucketedData");
@ -323,22 +287,22 @@ public class IobCobCalculatorPlugin implements PluginBase {
log.debug("Bucketed data created. Size: " + bucketed_data.size()); log.debug("Bucketed data created. Size: " + bucketed_data.size());
} }
public static long oldestDataAvailable() { public long oldestDataAvailable() {
long now = System.currentTimeMillis(); 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()))); 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()); log.debug("Limiting data to oldest available temps: " + new Date(oldestDataAvailable).toString());
return getBGDataFrom; return getBGDataFrom;
} }
public IobTotal calculateFromTreatmentsAndTempsSynchronized(long time) { public IobTotal calculateFromTreatmentsAndTempsSynchronized(long time, Profile profile) {
synchronized (dataLock) { synchronized (dataLock) {
return calculateFromTreatmentsAndTemps(time); return calculateFromTreatmentsAndTemps(time, profile);
} }
} }
public IobTotal calculateFromTreatmentsAndTemps(long time) { public IobTotal calculateFromTreatmentsAndTemps(long time, Profile profile) {
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
time = roundUpTime(time); time = roundUpTime(time);
if (time < now && iobTable.get(time) != null) { if (time < now && iobTable.get(time) != null) {
@ -347,18 +311,17 @@ public class IobCobCalculatorPlugin implements PluginBase {
} else { } else {
//log.debug(">>> calculateFromTreatmentsAndTemps Cache miss " + new Date(time).toLocaleString()); //log.debug(">>> calculateFromTreatmentsAndTemps Cache miss " + new Date(time).toLocaleString());
} }
IobTotal bolusIob = MainApp.getConfigBuilder().getCalculationToTimeTreatments(time).round(); IobTotal bolusIob = TreatmentsPlugin.getPlugin().getCalculationToTimeTreatments(time).round();
IobTotal basalIob = MainApp.getConfigBuilder().getCalculationToTimeTempBasals(time).round(); IobTotal basalIob = TreatmentsPlugin.getPlugin().getCalculationToTimeTempBasals(time, profile, true, now).round();
if (OpenAPSSMBPlugin.getPlugin().isEnabled(PluginBase.APS)) { if (OpenAPSSMBPlugin.getPlugin().isEnabled(PluginType.APS)) {
// Add expected zere temp basal for next 240 mins // Add expected zero temp basal for next 240 mins
IobTotal basalIobWithZeroTemp = basalIob.clone(); IobTotal basalIobWithZeroTemp = basalIob.copy();
TemporaryBasal t = new TemporaryBasal(); TemporaryBasal t = new TemporaryBasal()
t.date = now + 60 * 1000L; .date(now + 60 * 1000L)
t.durationInMinutes = 240; .duration(240)
t.isAbsolute = true; .absolute(0);
t.absoluteRate = 0;
if (t.date < time) { if (t.date < time) {
IobTotal calc = t.iobCalc(time); IobTotal calc = t.iobCalc(time, profile);
basalIobWithZeroTemp.plus(calc); basalIobWithZeroTemp.plus(calc);
} }
@ -389,11 +352,12 @@ public class IobCobCalculatorPlugin implements PluginBase {
BasalData retval = basalDataTable.get(time); BasalData retval = basalDataTable.get(time);
if (retval == null) { if (retval == null) {
retval = new BasalData(); retval = new BasalData();
TemporaryBasal tb = MainApp.getConfigBuilder().getTempBasalFromHistory(time); Profile profile = MainApp.getConfigBuilder().getProfile(time);
retval.basal = MainApp.getConfigBuilder().getProfile(time).getBasal(time); TemporaryBasal tb = TreatmentsPlugin.getPlugin().getTempBasalFromHistory(time);
retval.basal = profile.getBasal(time);
if (tb != null) { if (tb != null) {
retval.isTempBasalRunning = true; retval.isTempBasalRunning = true;
retval.tempBasalAbsolute = tb.tempBasalConvertedToAbsolute(time); retval.tempBasalAbsolute = tb.tempBasalConvertedToAbsolute(time, profile);
} else { } else {
retval.isTempBasalRunning = false; retval.isTempBasalRunning = false;
retval.tempBasalAbsolute = retval.basal; retval.tempBasalAbsolute = retval.basal;
@ -440,6 +404,29 @@ public class IobCobCalculatorPlugin implements PluginBase {
} }
} }
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 (IobCobCalculatorPlugin.roundUpTime(treatment.date) > IobCobCalculatorPlugin.roundUpTime(autosensData.time)
&& treatment.date <= now && treatment.carbs > 0) {
displayCob += treatment.carbs;
}
}
}
for (Treatment treatment : treatments) {
if (treatment.date > now && treatment.carbs > 0) {
futureCarbs += treatment.carbs;
}
}
return new CobInfo(displayCob, futureCarbs);
}
@Nullable @Nullable
public AutosensData getLastAutosensData(String reason) { public AutosensData getLastAutosensData(String reason) {
@ -447,7 +434,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
log.debug("AUTOSENSDATA null: autosensDataTable empty (" + reason + ")"); log.debug("AUTOSENSDATA null: autosensDataTable empty (" + reason + ")");
return null; return null;
} }
AutosensData data = null; AutosensData data;
try { try {
data = autosensDataTable.valueAt(autosensDataTable.size() - 1); data = autosensDataTable.valueAt(autosensDataTable.size() - 1);
} catch (Exception e) { } catch (Exception e) {
@ -461,14 +448,11 @@ public class IobCobCalculatorPlugin implements PluginBase {
log.debug("AUTOSENSDATA null: data is old (" + reason + ") size()=" + autosensDataTable.size() + " lastdata=" + DateUtil.dateAndTimeString(data.time)); log.debug("AUTOSENSDATA null: data is old (" + reason + ") size()=" + autosensDataTable.size() + " lastdata=" + DateUtil.dateAndTimeString(data.time));
return null; return null;
} else { } else {
if (data == null)
log.debug("AUTOSENSDATA null: data == null (" + " " + reason + ") size()=" + autosensDataTable.size() + " lastdata=" + DateUtil.dateAndTimeString(data.time));
return data; return data;
} }
} }
public IobTotal[] calculateIobArrayInDia() { public IobTotal[] calculateIobArrayInDia(Profile profile) {
Profile profile = MainApp.getConfigBuilder().getProfile();
// predict IOB out to DIA plus 30m // predict IOB out to DIA plus 30m
long time = System.currentTimeMillis(); long time = System.currentTimeMillis();
time = roundUpTime(time); time = roundUpTime(time);
@ -477,15 +461,14 @@ public class IobCobCalculatorPlugin implements PluginBase {
int pos = 0; int pos = 0;
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
long t = time + i * 5 * 60000; long t = time + i * 5 * 60000;
IobTotal iob = calculateFromTreatmentsAndTempsSynchronized(t); IobTotal iob = calculateFromTreatmentsAndTempsSynchronized(t, profile);
array[pos] = iob; array[pos] = iob;
pos++; pos++;
} }
return array; return array;
} }
public IobTotal[] calculateIobArrayForSMB() { public IobTotal[] calculateIobArrayForSMB(Profile profile) {
Profile profile = MainApp.getConfigBuilder().getProfile();
// predict IOB out to DIA plus 30m // predict IOB out to DIA plus 30m
long time = System.currentTimeMillis(); long time = System.currentTimeMillis();
time = roundUpTime(time); time = roundUpTime(time);
@ -494,7 +477,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
int pos = 0; int pos = 0;
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
long t = time + i * 5 * 60000; long t = time + i * 5 * 60000;
IobTotal iob = calculateFromTreatmentsAndTempsSynchronized(t); IobTotal iob = calculateFromTreatmentsAndTempsSynchronized(t, profile);
array[pos] = iob; array[pos] = iob;
pos++; pos++;
} }
@ -520,6 +503,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
} }
@Subscribe @Subscribe
@SuppressWarnings("unused")
public void onEventAppInitialized(EventAppInitialized ev) { public void onEventAppInitialized(EventAppInitialized ev) {
if (this != getPlugin()) { if (this != getPlugin()) {
log.debug("Ignoring event for non default instance"); log.debug("Ignoring event for non default instance");
@ -529,6 +513,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
} }
@Subscribe @Subscribe
@SuppressWarnings("unused")
public void onEventNewBG(EventNewBG ev) { public void onEventNewBG(EventNewBG ev) {
if (this != getPlugin()) { if (this != getPlugin()) {
log.debug("Ignoring event for non default instance"); log.debug("Ignoring event for non default instance");
@ -589,7 +574,9 @@ public class IobCobCalculatorPlugin implements PluginBase {
} }
if (ev.isChanged(R.string.key_openapsama_autosens_period) || if (ev.isChanged(R.string.key_openapsama_autosens_period) ||
ev.isChanged(R.string.key_age) || 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"); stopCalculation("onEventPreferenceChange");
synchronized (dataLock) { synchronized (dataLock) {

View file

@ -4,6 +4,8 @@ import android.content.Context;
import android.os.PowerManager; import android.os.PowerManager;
import android.support.v4.util.LongSparseArray; import android.support.v4.util.LongSparseArray;
import com.crashlytics.android.answers.CustomEvent;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -11,24 +13,35 @@ import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import info.nightscout.androidaps.BuildConfig;
import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.events.Event; import info.nightscout.androidaps.events.Event;
import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventAutosensCalculationFinished; 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.DateUtil;
import info.nightscout.utils.FabricPrivacy;
import info.nightscout.utils.SP;
import static info.nightscout.utils.DateUtil.now;
/** /**
* Created by mike on 23.01.2018. * Created by mike on 23.01.2018.
*/ */
public class IobCobThread extends Thread { 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 final Event cause;
private IobCobCalculatorPlugin iobCobCalculatorPlugin; private IobCobCalculatorPlugin iobCobCalculatorPlugin;
@ -59,34 +72,34 @@ public class IobCobThread extends Thread {
log.debug("Aborting calculation thread (ConfigBuilder not ready): " + from); log.debug("Aborting calculation thread (ConfigBuilder not ready): " + from);
return; // app still initializing return; // app still initializing
} }
if (MainApp.getConfigBuilder().getProfile() == null) { if (!MainApp.getConfigBuilder().isProfileValid("IobCobThread")) {
log.debug("Aborting calculation thread (No profile): " + from); log.debug("Aborting calculation thread (No profile): " + from);
return; // app still initializing return; // app still initializing
} }
//log.debug("Locking calculateSensitivityData"); //log.debug("Locking calculateSensitivityData");
Object dataLock = iobCobCalculatorPlugin.dataLock;
long oldestTimeWithData = iobCobCalculatorPlugin.oldestDataAvailable(); long oldestTimeWithData = iobCobCalculatorPlugin.oldestDataAvailable();
synchronized (dataLock) { synchronized (iobCobCalculatorPlugin.dataLock) {
if (bgDataReload) { if (bgDataReload) {
iobCobCalculatorPlugin.loadBgData(start); iobCobCalculatorPlugin.loadBgData(start);
iobCobCalculatorPlugin.createBucketedData(); iobCobCalculatorPlugin.createBucketedData();
} }
List<BgReading> bucketed_data = iobCobCalculatorPlugin.getBucketedData(); List<BgReading> bucketed_data = iobCobCalculatorPlugin.getBucketedData();
LongSparseArray<AutosensData> autosensDataTable = iobCobCalculatorPlugin.getAutosensDataTable(); LongSparseArray<AutosensData> autosensDataTable = IobCobCalculatorPlugin.getPlugin().getAutosensDataTable();
if (bucketed_data == null || bucketed_data.size() < 3) { if (bucketed_data == null || bucketed_data.size() < 3) {
log.debug("Aborting calculation thread (No bucketed data available): " + from); log.debug("Aborting calculation thread (No bucketed data available): " + from);
return; return;
} }
long prevDataTime = iobCobCalculatorPlugin.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()); log.debug("Prev data time: " + new Date(prevDataTime).toLocaleString());
AutosensData previous = autosensDataTable.get(prevDataTime); AutosensData previous = autosensDataTable.get(prevDataTime);
// start from oldest to be able sub cob // start from oldest to be able sub cob
for (int i = bucketed_data.size() - 4; i >= 0; i--) { for (int i = bucketed_data.size() - 4; i >= 0; i--) {
MainApp.bus().post(new EventIobCalculationProgress(i + "/" + bucketed_data.size()));
if (iobCobCalculatorPlugin.stopCalculationTrigger) { if (iobCobCalculatorPlugin.stopCalculationTrigger) {
iobCobCalculatorPlugin.stopCalculationTrigger = false; iobCobCalculatorPlugin.stopCalculationTrigger = false;
log.debug("Aborting calculation thread (trigger): " + from); log.debug("Aborting calculation thread (trigger): " + from);
@ -94,10 +107,9 @@ public class IobCobThread extends Thread {
} }
// check if data already exists // check if data already exists
long bgTime = bucketed_data.get(i).date; long bgTime = bucketed_data.get(i).date;
bgTime = iobCobCalculatorPlugin.roundUpTime(bgTime); bgTime = IobCobCalculatorPlugin.roundUpTime(bgTime);
if (bgTime > System.currentTimeMillis()) if (bgTime > IobCobCalculatorPlugin.roundUpTime(now()))
continue; continue;
Profile profile = MainApp.getConfigBuilder().getProfile(bgTime);
AutosensData existing; AutosensData existing;
if ((existing = autosensDataTable.get(bgTime)) != null) { if ((existing = autosensDataTable.get(bgTime)) != null) {
@ -105,16 +117,12 @@ public class IobCobThread extends Thread {
continue; continue;
} }
Profile profile = MainApp.getConfigBuilder().getProfile(bgTime);
if (profile == null) { if (profile == null) {
log.debug("Aborting calculation thread (no profile): " + from); log.debug("Aborting calculation thread (no profile): " + from);
return; // profile not set yet 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) if (Config.logAutosensData)
log.debug("Processing calculation thread: " + from + " (" + i + "/" + bucketed_data.size() + ")"); log.debug("Processing calculation thread: " + from + " (" + i + "/" + bucketed_data.size() + ")");
@ -139,13 +147,12 @@ public class IobCobThread extends Thread {
delta = (bg - bucketed_data.get(i + 1).value); delta = (bg - bucketed_data.get(i + 1).value);
avgDelta = (bg - bucketed_data.get(i + 3).value) / 3; 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 bgi = -iob.activity * sens * 5;
double deviation = delta - bgi; double deviation = delta - bgi;
double avgDeviation = Math.round((avgDelta - bgi) * 1000) / 1000; double avgDeviation = Math.round((avgDelta - bgi) * 1000) / 1000;
double currentDeviation;
double slopeFromMaxDeviation = 0; double slopeFromMaxDeviation = 0;
double slopeFromMinDeviation = 999; double slopeFromMinDeviation = 999;
double maxDeviation = 0; double maxDeviation = 0;
@ -154,30 +161,43 @@ public class IobCobThread extends Thread {
// https://github.com/openaps/oref0/blob/master/lib/determine-basal/cob-autosens.js#L169 // 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 if (i < bucketed_data.size() - 16) { // we need 1h of data to calculate minDeviationSlope
long hourago = bgTime + 10 * 1000 - 60 * 60 * 1000L; long hourago = bgTime + 10 * 1000 - 60 * 60 * 1000L;
AutosensData hourAgoData = iobCobCalculatorPlugin.getAutosensData(hourago); AutosensData hourAgoData = IobCobCalculatorPlugin.getPlugin().getAutosensData(hourago);
if (hourAgoData != null) { if (hourAgoData != null) {
currentDeviation = hourAgoData.avgDeviation;
int initialIndex = autosensDataTable.indexOfKey(hourAgoData.time); int initialIndex = autosensDataTable.indexOfKey(hourAgoData.time);
if (Config.logAutosensData)
for (int past = 1; past < 12; past++) { 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); AutosensData ad = autosensDataTable.valueAt(initialIndex + past);
double deviationSlope = (ad.avgDeviation - currentDeviation) / (ad.time - bgTime) * 1000 * 60 * 5; double deviationSlope = (ad.avgDeviation - avgDeviation) / (ad.time - bgTime) * 1000 * 60 * 5;
if (ad.avgDeviation > maxDeviation) { if (ad.avgDeviation > maxDeviation) {
slopeFromMaxDeviation = Math.min(0, deviationSlope); slopeFromMaxDeviation = Math.min(0, deviationSlope);
maxDeviation = ad.avgDeviation; maxDeviation = ad.avgDeviation;
} }
if (avgDeviation < minDeviation) { if (ad.avgDeviation < minDeviation) {
slopeFromMinDeviation = Math.max(0, deviationSlope); slopeFromMinDeviation = Math.max(0, deviationSlope);
minDeviation = avgDeviation; minDeviation = ad.avgDeviation;
} }
//if (Config.logAutosensData) //if (Config.logAutosensData)
// log.debug("Deviations: " + new Date(bgTime) + new Date(ad.time) + " avgDeviation=" + avgDeviation + " deviationSlope=" + deviationSlope + " slopeFromMaxDeviation=" + slopeFromMaxDeviation + " slopeFromMinDeviation=" + slopeFromMinDeviation); // 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 = MainApp.getConfigBuilder().getTreatments5MinBackFromHistory(bgTime); List<Treatment> recentTreatments = TreatmentsPlugin.getPlugin().getTreatments5MinBackFromHistory(bgTime);
for (int ir = 0; ir < recentTreatments.size(); ir++) { for (int ir = 0; ir < recentTreatments.size(); ir++) {
autosensData.carbsFromBolus += recentTreatments.get(ir).carbs; autosensData.carbsFromBolus += recentTreatments.get(ir).carbs;
autosensData.activeCarbsList.add(new AutosensData.CarbsInPast(recentTreatments.get(ir))); autosensData.activeCarbsList.add(new AutosensData.CarbsInPast(recentTreatments.get(ir)));
@ -188,18 +208,27 @@ public class IobCobThread extends Thread {
if (previous != null && previous.cob > 0) { if (previous != null && previous.cob > 0) {
// calculate sum of min carb impact from all active treatments // calculate sum of min carb impact from all active treatments
double totalMinCarbsImpact = 0d; double totalMinCarbsImpact = 0d;
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) { for (int ii = 0; ii < autosensData.activeCarbsList.size(); ++ii) {
AutosensData.CarbsInPast c = autosensData.activeCarbsList.get(ii); AutosensData.CarbsInPast c = autosensData.activeCarbsList.get(ii);
totalMinCarbsImpact += c.min5minCarbImpact; 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 // figure out how many carbs that represents
// but always assume at least 3mg/dL/5m (default) absorption per active treatment // but always assume at least 3mg/dL/5m (default) absorption per active treatment
double ci = Math.max(deviation, totalMinCarbsImpact); double ci = Math.max(deviation, totalMinCarbsImpact);
if (ci != deviation)
autosensData.failoverToMinAbsorbtionRate = true;
autosensData.absorbed = ci * profile.getIc(bgTime) / sens; autosensData.absorbed = ci * profile.getIc(bgTime) / sens;
// and add that to the running total carbsAbsorbed // and add that to the running total carbsAbsorbed
autosensData.cob = Math.max(previous.cob - autosensData.absorbed, 0d); autosensData.cob = Math.max(previous.cob - autosensData.absorbed, 0d);
autosensData.substractAbosorbedCarbs(); autosensData.substractAbosorbedCarbs();
autosensData.usedMinCarbsImpact = totalMinCarbsImpact;
} }
autosensData.removeOldCarbs(bgTime); autosensData.removeOldCarbs(bgTime);
autosensData.cob += autosensData.carbsFromBolus; autosensData.cob += autosensData.carbsFromBolus;
@ -232,16 +261,18 @@ public class IobCobThread extends Thread {
previous = autosensData; previous = autosensData;
autosensDataTable.put(bgTime, autosensData); autosensDataTable.put(bgTime, autosensData);
if (Config.logAutosensData)
log.debug("Running detectSensitivity from: " + DateUtil.dateAndTimeString(oldestTimeWithData) + " to: " + DateUtil.dateAndTimeString(bgTime)); log.debug("Running detectSensitivity from: " + DateUtil.dateAndTimeString(oldestTimeWithData) + " to: " + DateUtil.dateAndTimeString(bgTime));
autosensData.autosensRatio = iobCobCalculatorPlugin.detectSensitivity(oldestTimeWithData, bgTime).ratio; autosensData.autosensRatio = iobCobCalculatorPlugin.detectSensitivity(oldestTimeWithData, bgTime).ratio;
if (Config.logAutosensData) if (Config.logAutosensData)
log.debug(autosensData.log(bgTime)); log.debug(autosensData.toString());
} }
} }
MainApp.bus().post(new EventAutosensCalculationFinished(cause)); MainApp.bus().post(new EventAutosensCalculationFinished(cause));
log.debug("Finishing calculation thread: " + from); log.debug("Finishing calculation thread: " + from);
} finally { } finally {
mWakeLock.release(); mWakeLock.release();
MainApp.bus().post(new EventIobCalculationProgress(""));
} }
} }

View file

@ -0,0 +1,11 @@
package info.nightscout.androidaps.plugins.IobCobCalculator.events;
import info.nightscout.androidaps.events.Event;
public class EventIobCalculationProgress extends Event {
public String progress;
public EventIobCalculationProgress(String progress) {
this.progress = progress;
}
}

View file

@ -17,6 +17,7 @@ import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.DecimalFormatter;
@ -31,7 +32,7 @@ public class APSResult {
public String reason; public String reason;
public double rate; public double rate;
public int duration; public int duration;
public boolean tempBasalReqested = false; public boolean tempBasalRequested = false;
public boolean bolusRequested = false; public boolean bolusRequested = false;
public IobTotal iob; public IobTotal iob;
public JSONObject json = new JSONObject(); public JSONObject json = new JSONObject();
@ -39,6 +40,11 @@ public class APSResult {
public double smb = 0d; // super micro bolus in units public double smb = 0d; // super micro bolus in units
public long deliverAt = 0; public long deliverAt = 0;
public Constraint<Double> inputConstraints;
public Constraint<Double> rateConstraint;
public Constraint<Double> smbConstraint;
@Override @Override
public String toString() { public String toString() {
final PumpInterface pump = ConfigBuilderPlugin.getActivePump(); final PumpInterface pump = ConfigBuilderPlugin.getActivePump();
@ -56,7 +62,7 @@ public class APSResult {
// smb // smb
if (smb != 0) if (smb != 0)
ret += ("SMB: " + DecimalFormatter.to2Decimal(smb) + " U\n"); ret += ("SMB: " + DecimalFormatter.toPumpSupportedBolus(smb) + " U\n");
// reason // reason
ret += MainApp.sResources.getString(R.string.reason) + ": " + reason; ret += MainApp.sResources.getString(R.string.reason) + ": " + reason;
@ -81,7 +87,7 @@ public class APSResult {
// smb // smb
if (smb != 0) if (smb != 0)
ret += ("<b>" + "SMB" + "</b>: " + DecimalFormatter.to2Decimal(smb) + " U<br>"); ret += ("<b>" + "SMB" + "</b>: " + DecimalFormatter.toPumpSupportedBolus(smb) + " U<br>");
// reason // reason
ret += "<b>" + MainApp.sResources.getString(R.string.reason) + "</b>: " + reason.replace("<", "&lt;").replace(">", "&gt;"); ret += "<b>" + MainApp.sResources.getString(R.string.reason) + "</b>: " + reason.replace("<", "&lt;").replace(">", "&gt;");
@ -98,9 +104,15 @@ public class APSResult {
newResult.reason = reason; newResult.reason = reason;
newResult.rate = rate; newResult.rate = rate;
newResult.duration = duration; newResult.duration = duration;
newResult.tempBasalReqested = tempBasalReqested; newResult.tempBasalRequested = tempBasalRequested;
newResult.bolusRequested = bolusRequested; newResult.bolusRequested = bolusRequested;
newResult.iob = iob; newResult.iob = iob;
newResult.json = json;
newResult.hasPredictions = hasPredictions;
newResult.smb = smb;
newResult.deliverAt = deliverAt;
newResult.rateConstraint = rateConstraint;
newResult.smbConstraint = smbConstraint;
return newResult; return newResult;
} }
@ -216,6 +228,6 @@ public class APSResult {
} }
public boolean isChangeRequested() { public boolean isChangeRequested() {
return tempBasalReqested || bolusRequested; return tempBasalRequested || bolusRequested;
} }
} }

View file

@ -3,6 +3,7 @@ package info.nightscout.androidaps.plugins.Loop;
import android.app.Activity; import android.app.Activity;
import android.os.Bundle; import android.os.Bundle;
import android.text.Html;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@ -15,23 +16,38 @@ import com.squareup.otto.Subscribe;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.plugins.Common.SubscriberFragment; import info.nightscout.androidaps.plugins.Common.SubscriberFragment;
import info.nightscout.androidaps.plugins.Loop.events.EventLoopSetLastRunGui; import info.nightscout.androidaps.plugins.Loop.events.EventLoopSetLastRunGui;
import info.nightscout.androidaps.plugins.Loop.events.EventLoopUpdateGui; import info.nightscout.androidaps.plugins.Loop.events.EventLoopUpdateGui;
import info.nightscout.utils.FabricPrivacy; import info.nightscout.utils.FabricPrivacy;
public class LoopFragment extends SubscriberFragment implements View.OnClickListener { public class LoopFragment extends SubscriberFragment {
private static Logger log = LoggerFactory.getLogger(LoopFragment.class); private static Logger log = LoggerFactory.getLogger(LoopFragment.class);
@BindView(R.id.loop_run)
Button runNowButton; Button runNowButton;
@BindView(R.id.loop_lastrun)
TextView lastRunView; TextView lastRunView;
@BindView(R.id.loop_lastenact)
TextView lastEnactView; TextView lastEnactView;
@BindView(R.id.loop_source)
TextView sourceView; TextView sourceView;
@BindView(R.id.loop_request)
TextView requestView; TextView requestView;
@BindView(R.id.loop_constraintsprocessed)
TextView constraintsProcessedView; TextView constraintsProcessedView;
TextView setByPumpView; @BindView(R.id.loop_constraints)
TextView constraintsView;
@BindView(R.id.loop_tbrsetbypump)
TextView tbrSetByPumpView;
@BindView(R.id.loop_smbsetbypump)
TextView smbSetByPumpView;
@Override @Override
@ -39,41 +55,19 @@ public class LoopFragment extends SubscriberFragment implements View.OnClickList
Bundle savedInstanceState) { Bundle savedInstanceState) {
try { try {
View view = inflater.inflate(R.layout.loop_fragment, container, false); View view = inflater.inflate(R.layout.loop_fragment, container, false);
unbinder = ButterKnife.bind(this, view);
lastRunView = (TextView) view.findViewById(R.id.loop_lastrun);
lastEnactView = (TextView) view.findViewById(R.id.loop_lastenact);
sourceView = (TextView) view.findViewById(R.id.loop_source);
requestView = (TextView) view.findViewById(R.id.loop_request);
constraintsProcessedView = (TextView) view.findViewById(R.id.loop_constraintsprocessed);
setByPumpView = (TextView) view.findViewById(R.id.loop_setbypump);
runNowButton = (Button) view.findViewById(R.id.loop_run);
runNowButton.setOnClickListener(this);
updateGUI();
return view; return view;
} catch (Exception e) { } catch (Exception e) {
FabricPrivacy.logException(e); FabricPrivacy.logException(e);
} }
return null; return null;
} }
@Override @OnClick(R.id.loop_run)
public void onClick(View view) { void onRunClick() {
switch (view.getId()) {
case R.id.loop_run:
lastRunView.setText(MainApp.sResources.getString(R.string.executing)); lastRunView.setText(MainApp.sResources.getString(R.string.executing));
Thread thread = new Thread(new Runnable() { new Thread(() -> LoopPlugin.getPlugin().invoke("Loop button", true)).start();
@Override
public void run() {
LoopPlugin.getPlugin().invoke("Loop button", true);
}
});
thread.start();
FabricPrivacy.getInstance().logCustom(new CustomEvent("Loop_Run")); FabricPrivacy.getInstance().logCustom(new CustomEvent("Loop_Run"));
break;
}
} }
@Subscribe @Subscribe
@ -86,12 +80,7 @@ public class LoopFragment extends SubscriberFragment implements View.OnClickList
clearGUI(); clearGUI();
final Activity activity = getActivity(); final Activity activity = getActivity();
if (activity != null) if (activity != null)
activity.runOnUiThread(new Runnable() { activity.runOnUiThread(() -> lastRunView.setText(ev.text));
@Override
public void run() {
lastRunView.setText(ev.text);
}
});
} }
@ -99,17 +88,27 @@ public class LoopFragment extends SubscriberFragment implements View.OnClickList
protected void updateGUI() { protected void updateGUI() {
Activity activity = getActivity(); Activity activity = getActivity();
if (activity != null) if (activity != null)
activity.runOnUiThread(new Runnable() { activity.runOnUiThread(() -> {
@Override LoopPlugin.LastRun lastRun = LoopPlugin.lastRun;
public void run() { if (lastRun != null) {
if (LoopPlugin.lastRun != null) { requestView.setText(lastRun.request != null ? lastRun.request.toSpanned() : "");
requestView.setText(LoopPlugin.lastRun.request != null ? LoopPlugin.lastRun.request.toSpanned() : ""); constraintsProcessedView.setText(lastRun.constraintsProcessed != null ? lastRun.constraintsProcessed.toSpanned() : "");
constraintsProcessedView.setText(LoopPlugin.lastRun.constraintsProcessed != null ? LoopPlugin.lastRun.constraintsProcessed.toSpanned() : ""); sourceView.setText(lastRun.source != null ? lastRun.source : "");
setByPumpView.setText(LoopPlugin.lastRun.setByPump != null ? LoopPlugin.lastRun.setByPump.toSpanned() : ""); lastRunView.setText(lastRun.lastAPSRun != null && lastRun.lastAPSRun.getTime() != 0 ? lastRun.lastAPSRun.toLocaleString() : "");
sourceView.setText(LoopPlugin.lastRun.source != null ? LoopPlugin.lastRun.source : ""); lastEnactView.setText(lastRun.lastEnact != null && lastRun.lastEnact.getTime() != 0 ? lastRun.lastEnact.toLocaleString() : "");
lastRunView.setText(LoopPlugin.lastRun.lastAPSRun != null && LoopPlugin.lastRun.lastAPSRun.getTime() != 0 ? LoopPlugin.lastRun.lastAPSRun.toLocaleString() : ""); tbrSetByPumpView.setText(lastRun.tbrSetByPump != null ? Html.fromHtml(lastRun.tbrSetByPump.toHtml()) : "");
lastEnactView.setText(LoopPlugin.lastRun.lastEnact != null && LoopPlugin.lastRun.lastEnact.getTime() != 0 ? LoopPlugin.lastRun.lastEnact.toLocaleString() : ""); smbSetByPumpView.setText(lastRun.smbSetByPump != null ? Html.fromHtml(lastRun.smbSetByPump.toHtml()) : "");
String constraints = "";
if (lastRun.constraintsProcessed != null) {
Constraint<Double> allConstraints = new Constraint<>(0d);
if (lastRun.constraintsProcessed.rateConstraint != null)
allConstraints.copyReasons(lastRun.constraintsProcessed.rateConstraint);
if (lastRun.constraintsProcessed.smbConstraint != null)
allConstraints.copyReasons(lastRun.constraintsProcessed.smbConstraint);
constraints = allConstraints.getMostLimitedReasons();
} }
constraintsView.setText(constraints);
} }
}); });
} }
@ -117,16 +116,14 @@ public class LoopFragment extends SubscriberFragment implements View.OnClickList
void clearGUI() { void clearGUI() {
Activity activity = getActivity(); Activity activity = getActivity();
if (activity != null) if (activity != null)
activity.runOnUiThread(new Runnable() { activity.runOnUiThread(() -> {
@Override
public void run() {
requestView.setText(""); requestView.setText("");
constraintsProcessedView.setText(""); constraintsProcessedView.setText("");
setByPumpView.setText("");
sourceView.setText(""); sourceView.setText("");
lastRunView.setText(""); lastRunView.setText("");
lastEnactView.setText(""); lastEnactView.setText("");
} tbrSetByPumpView.setText("");
smbSetByPumpView.setText("");
}); });
} }
} }

View file

@ -1,11 +1,16 @@
package info.nightscout.androidaps.plugins.Loop; package info.nightscout.androidaps.plugins.Loop;
import android.annotation.SuppressLint;
import android.app.Notification; import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.app.TaskStackBuilder; import android.app.TaskStackBuilder;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Build;
import android.os.SystemClock;
import android.support.annotation.NonNull;
import android.support.v4.app.NotificationCompat; import android.support.v4.app.NotificationCompat;
import com.crashlytics.android.answers.CustomEvent; import com.crashlytics.android.answers.CustomEvent;
@ -21,16 +26,21 @@ import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainActivity; import info.nightscout.androidaps.MainActivity;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.db.DatabaseHelper;
import info.nightscout.androidaps.events.Event;
import info.nightscout.androidaps.events.EventNewBG; import info.nightscout.androidaps.events.EventNewBG;
import info.nightscout.androidaps.events.EventTreatmentChange; import info.nightscout.androidaps.events.EventTreatmentChange;
import info.nightscout.androidaps.interfaces.APSInterface; import info.nightscout.androidaps.interfaces.APSInterface;
import info.nightscout.androidaps.interfaces.ConstraintsInterface; import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventAutosensCalculationFinished; import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventAutosensCalculationFinished;
import info.nightscout.androidaps.plugins.Loop.events.EventLoopResult;
import info.nightscout.androidaps.plugins.Loop.events.EventLoopSetLastRunGui; import info.nightscout.androidaps.plugins.Loop.events.EventLoopSetLastRunGui;
import info.nightscout.androidaps.plugins.Loop.events.EventLoopUpdateGui; import info.nightscout.androidaps.plugins.Loop.events.EventLoopUpdateGui;
import info.nightscout.androidaps.plugins.Loop.events.EventNewOpenLoopNotification; import info.nightscout.androidaps.plugins.Loop.events.EventNewOpenLoopNotification;
@ -43,11 +53,16 @@ import info.nightscout.utils.SP;
/** /**
* Created by mike on 05.08.2016. * Created by mike on 05.08.2016.
*/ */
public class LoopPlugin implements PluginBase { public class LoopPlugin extends PluginBase {
private static Logger log = LoggerFactory.getLogger(LoopPlugin.class); private static Logger log = LoggerFactory.getLogger(LoopPlugin.class);
private static LoopPlugin loopPlugin; public static final String CHANNEL_ID = "AndroidAPS-Openloop";
long lastBgTriggeredRun = 0;
protected static LoopPlugin loopPlugin;
@NonNull
public static LoopPlugin getPlugin() { public static LoopPlugin getPlugin() {
if (loopPlugin == null) { if (loopPlugin == null) {
loopPlugin = new LoopPlugin(); loopPlugin = new LoopPlugin();
@ -55,9 +70,6 @@ public class LoopPlugin implements PluginBase {
return loopPlugin; return loopPlugin;
} }
private boolean fragmentEnabled = false;
private boolean fragmentVisible = false;
private long loopSuspendedTill = 0L; // end of manual loop suspend private long loopSuspendedTill = 0L; // end of manual loop suspend
private boolean isSuperBolus = false; private boolean isSuperBolus = false;
private boolean isDisconnected = false; private boolean isDisconnected = false;
@ -65,7 +77,8 @@ public class LoopPlugin implements PluginBase {
public class LastRun { public class LastRun {
public APSResult request = null; public APSResult request = null;
public APSResult constraintsProcessed = null; public APSResult constraintsProcessed = null;
public PumpEnactResult setByPump = null; public PumpEnactResult tbrSetByPump = null;
public PumpEnactResult smbSetByPump = null;
public String source = null; public String source = null;
public Date lastAPSRun = null; public Date lastAPSRun = null;
public Date lastEnact = null; public Date lastEnact = null;
@ -75,92 +88,76 @@ public class LoopPlugin implements PluginBase {
static public LastRun lastRun = null; static public LastRun lastRun = null;
public LoopPlugin() { public LoopPlugin() {
MainApp.bus().register(this); super(new PluginDescription()
.mainType(PluginType.LOOP)
.fragmentClass(LoopFragment.class.getName())
.pluginName(R.string.loop)
.shortName(R.string.loop_shortname)
.preferencesId(R.xml.pref_closedmode)
);
loopSuspendedTill = SP.getLong("loopSuspendedTill", 0L); loopSuspendedTill = SP.getLong("loopSuspendedTill", 0L);
isSuperBolus = SP.getBoolean("isSuperBolus", false); isSuperBolus = SP.getBoolean("isSuperBolus", false);
isDisconnected = SP.getBoolean("isDisconnected", false); isDisconnected = SP.getBoolean("isDisconnected", false);
} }
@Override @Override
public String getFragmentClass() { protected void onStart() {
return LoopFragment.class.getName(); MainApp.bus().register(this);
createNotificationChannel();
super.onStart();
}
private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationManager mNotificationManager =
(NotificationManager) MainApp.instance().getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
@SuppressLint("WrongConstant") NotificationChannel channel = new NotificationChannel(CHANNEL_ID,
CHANNEL_ID,
NotificationManager.IMPORTANCE_HIGH);
mNotificationManager.createNotificationChannel(channel);
}
} }
@Override @Override
public int getType() { protected void onStop() {
return PluginBase.LOOP; super.onStop();
MainApp.bus().unregister(this);
} }
@Override @Override
public String getName() { public boolean specialEnableCondition() {
return MainApp.instance().getString(R.string.loop); PumpInterface pump = ConfigBuilderPlugin.getActivePump();
} return pump == null || pump.getPumpDescription().isTempBasalCapable;
@Override
public String getNameShort() {
String name = MainApp.sResources.getString(R.string.loop_shortname);
if (!name.trim().isEmpty()) {
//only if translation exists
return name;
}
// use long name as fallback
return getName();
}
@Override
public boolean isEnabled(int type) {
boolean pumpCapable = ConfigBuilderPlugin.getActivePump() == null || ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable;
return type == LOOP && fragmentEnabled && pumpCapable;
}
@Override
public boolean isVisibleInTabs(int type) {
boolean pumpCapable = ConfigBuilderPlugin.getActivePump() == null || ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable;
return type == LOOP && fragmentVisible && pumpCapable;
}
@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 == LOOP) this.fragmentEnabled = fragmentEnabled;
}
@Override
public void setFragmentVisible(int type, boolean fragmentVisible) {
if (type == LOOP) this.fragmentVisible = fragmentVisible;
}
@Override
public int getPreferencesId() {
return R.xml.pref_closedmode;
}
@Subscribe
public void onStatusEvent(final EventTreatmentChange ev) {
if (ev.treatment == null || !ev.treatment.isSMB){
invoke("EventTreatmentChange", true);
}
} }
/**
* This method is triggered once autosens calculation has completed, so the LoopPlugin
* has current data to work with. However, autosens calculation can be triggered by multiple
* sources and currently only a new BG should trigger a loop run. Hence we return early if
* the event causing the calculation is not EventNewBg.
*
* Callers of {@link info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin#runCalculation(String, long, boolean, Event)}
* are sources triggering a calculation which triggers this method upon completion.
*/
@Subscribe @Subscribe
public void onStatusEvent(final EventAutosensCalculationFinished ev) { public void onStatusEvent(final EventAutosensCalculationFinished ev) {
if (ev.cause instanceof EventNewBG) { if (!(ev.cause instanceof EventNewBG)) {
invoke(ev.getClass().getSimpleName() + "(" + ev.cause.getClass().getSimpleName() + ")", true); // Autosens calculation not triggered by a new BG
return;
} }
BgReading bgReading = DatabaseHelper.actualBg();
if (bgReading == null) {
// BG outdated
return;
}
if (bgReading.date <= lastBgTriggeredRun) {
// already looped with that value
return;
}
lastBgTriggeredRun = bgReading.date;
invoke("AutosenseCalculation for " + bgReading, true);
} }
public long suspendedTo() { public long suspendedTo() {
@ -250,23 +247,31 @@ public class LoopPlugin implements PluginBase {
return isDisconnected; return isDisconnected;
} }
public void invoke(String initiator, boolean allowNotification) { public synchronized void invoke(String initiator, boolean allowNotification){
invoke(initiator, allowNotification, false);
}
public synchronized void invoke(String initiator, boolean allowNotification, boolean tempBasalFallback) {
try { try {
if (Config.logFunctionCalls) if (Config.logFunctionCalls)
log.debug("invoke from " + initiator); log.debug("invoke from " + initiator);
ConstraintsInterface constraintsInterface = MainApp.getConfigBuilder(); Constraint<Boolean> loopEnabled = MainApp.getConstraintChecker().isLoopInvokationAllowed();
if (!constraintsInterface.isLoopEnabled()) {
log.debug(MainApp.sResources.getString(R.string.loopdisabled)); if (!loopEnabled.value()) {
MainApp.bus().post(new EventLoopSetLastRunGui(MainApp.sResources.getString(R.string.loopdisabled))); String message = MainApp.sResources.getString(R.string.loopdisabled) + "\n" + loopEnabled.getReasons();
log.debug(message);
MainApp.bus().post(new EventLoopSetLastRunGui(message));
return; return;
} }
final PumpInterface pump = ConfigBuilderPlugin.getActivePump(); final PumpInterface pump = ConfigBuilderPlugin.getActivePump();
APSResult result = null; APSResult result = null;
if (!isEnabled(PluginBase.LOOP)) if (!isEnabled(PluginType.LOOP))
return; return;
if (MainApp.getConfigBuilder().getProfile() == null) { Profile profile = MainApp.getConfigBuilder().getProfile();
if (!MainApp.getConfigBuilder().isProfileValid("Loop")) {
log.debug(MainApp.sResources.getString(R.string.noprofileselected)); log.debug(MainApp.sResources.getString(R.string.noprofileselected));
MainApp.bus().post(new EventLoopSetLastRunGui(MainApp.sResources.getString(R.string.noprofileselected))); MainApp.bus().post(new EventLoopSetLastRunGui(MainApp.sResources.getString(R.string.noprofileselected)));
return; return;
@ -276,8 +281,8 @@ public class LoopPlugin implements PluginBase {
if (pump.getBaseBasalRate() < 0.01d) return; if (pump.getBaseBasalRate() < 0.01d) return;
APSInterface usedAPS = ConfigBuilderPlugin.getActiveAPS(); APSInterface usedAPS = ConfigBuilderPlugin.getActiveAPS();
if (usedAPS != null && ((PluginBase) usedAPS).isEnabled(PluginBase.APS)) { if (usedAPS != null && ((PluginBase) usedAPS).isEnabled(PluginType.APS)) {
usedAPS.invoke(initiator); usedAPS.invoke(initiator, tempBasalFallback);
result = usedAPS.getLastAPSResult(); result = usedAPS.getLastAPSResult();
} }
@ -289,8 +294,10 @@ public class LoopPlugin implements PluginBase {
// check rate for constrais // check rate for constrais
final APSResult resultAfterConstraints = result.clone(); final APSResult resultAfterConstraints = result.clone();
resultAfterConstraints.rate = constraintsInterface.applyBasalConstraints(resultAfterConstraints.rate); resultAfterConstraints.rateConstraint = new Constraint<>(resultAfterConstraints.rate);
resultAfterConstraints.smb = constraintsInterface.applyBolusConstraints(resultAfterConstraints.smb); resultAfterConstraints.rate = MainApp.getConstraintChecker().applyBasalConstraints(resultAfterConstraints.rateConstraint, profile).value();
resultAfterConstraints.smbConstraint = new Constraint<>(resultAfterConstraints.smb);
resultAfterConstraints.smb = MainApp.getConstraintChecker().applyBolusConstraints(resultAfterConstraints.smbConstraint).value();
// safety check for multiple SMBs // safety check for multiple SMBs
long lastBolusTime = TreatmentsPlugin.getPlugin().getLastBolusTime(); long lastBolusTime = TreatmentsPlugin.getPlugin().getLastBolusTime();
@ -304,7 +311,8 @@ public class LoopPlugin implements PluginBase {
lastRun.constraintsProcessed = resultAfterConstraints; lastRun.constraintsProcessed = resultAfterConstraints;
lastRun.lastAPSRun = new Date(); lastRun.lastAPSRun = new Date();
lastRun.source = ((PluginBase) usedAPS).getName(); lastRun.source = ((PluginBase) usedAPS).getName();
lastRun.setByPump = null; lastRun.tbrSetByPump = null;
lastRun.smbSetByPump = null;
NSUpload.uploadDeviceStatus(); NSUpload.uploadDeviceStatus();
@ -320,36 +328,53 @@ public class LoopPlugin implements PluginBase {
return; return;
} }
MainApp.bus().post(new EventLoopResult(resultAfterConstraints)); Constraint<Boolean> closedLoopEnabled = MainApp.getConstraintChecker().isClosedLoopAllowed();
if (constraintsInterface.isClosedModeEnabled()) { if (closedLoopEnabled.value()) {
if (result.isChangeRequested()) { if (result.isChangeRequested()) {
final PumpEnactResult waiting = new PumpEnactResult(); final PumpEnactResult waiting = new PumpEnactResult();
final PumpEnactResult previousResult = lastRun.setByPump;
waiting.queued = true; waiting.queued = true;
lastRun.setByPump = waiting; if (resultAfterConstraints.tempBasalRequested)
lastRun.tbrSetByPump = waiting;
if (resultAfterConstraints.bolusRequested)
lastRun.smbSetByPump = waiting;
MainApp.bus().post(new EventLoopUpdateGui()); MainApp.bus().post(new EventLoopUpdateGui());
MainApp.getConfigBuilder().applyAPSRequest(resultAfterConstraints, new Callback() { FabricPrivacy.getInstance().logCustom(new CustomEvent("APSRequest"));
MainApp.getConfigBuilder().applyTBRRequest(resultAfterConstraints, profile, new Callback() {
@Override @Override
public void run() { public void run() {
FabricPrivacy.getInstance().logCustom(new CustomEvent("APSRequest"));
if (result.enacted || result.success) { if (result.enacted || result.success) {
lastRun.setByPump = result; lastRun.tbrSetByPump = result;
lastRun.lastEnact = lastRun.lastAPSRun;
MainApp.getConfigBuilder().applySMBRequest(resultAfterConstraints, new Callback() {
@Override
public void run() {
//Callback is only called if a bolus was acutally requested
if (result.enacted || result.success) {
lastRun.smbSetByPump = result;
lastRun.lastEnact = lastRun.lastAPSRun; lastRun.lastEnact = lastRun.lastAPSRun;
} else { } else {
lastRun.setByPump = previousResult; new Thread(() -> {
SystemClock.sleep(1000);
LoopPlugin.getPlugin().invoke("tempBasalFallback", allowNotification, true);
}).start();
FabricPrivacy.getInstance().logCustom(new CustomEvent("Loop_Run_TempBasalFallback"));
}
MainApp.bus().post(new EventLoopUpdateGui());
}
});
} }
MainApp.bus().post(new EventLoopUpdateGui()); MainApp.bus().post(new EventLoopUpdateGui());
} }
}); });
} else { } else {
lastRun.setByPump = null; lastRun.tbrSetByPump = null;
lastRun.source = null; lastRun.smbSetByPump = null;
} }
} else { } else {
if (result.isChangeRequested() && allowNotification) { if (result.isChangeRequested() && allowNotification) {
NotificationCompat.Builder builder = NotificationCompat.Builder builder =
new NotificationCompat.Builder(MainApp.instance().getApplicationContext()); new NotificationCompat.Builder(MainApp.instance().getApplicationContext(), CHANNEL_ID);
builder.setSmallIcon(R.drawable.notif_icon) builder.setSmallIcon(R.drawable.notif_icon)
.setContentTitle(MainApp.sResources.getString(R.string.openloop_newsuggestion)) .setContentTitle(MainApp.sResources.getString(R.string.openloop_newsuggestion))
.setContentText(resultAfterConstraints.toString()) .setContentText(resultAfterConstraints.toString())

View file

@ -1,12 +0,0 @@
package info.nightscout.androidaps.plugins.Loop.events;
import info.nightscout.androidaps.plugins.Loop.APSResult;
public class EventLoopResult {
public final APSResult apsResult;
public EventLoopResult(APSResult apsResult) {
this.apsResult = apsResult;
}
}

View file

@ -7,7 +7,6 @@ import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.graphics.Paint; import android.graphics.Paint;
import android.os.Bundle; import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.text.Html; import android.text.Html;
import android.text.Spanned; import android.text.Spanned;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@ -34,8 +33,8 @@ import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientU
import info.nightscout.utils.FabricPrivacy; import info.nightscout.utils.FabricPrivacy;
import info.nightscout.utils.SP; import info.nightscout.utils.SP;
public class NSClientInternalFragment extends SubscriberFragment implements View.OnClickListener, CompoundButton.OnCheckedChangeListener { public class NSClientFragment extends SubscriberFragment implements View.OnClickListener, CompoundButton.OnCheckedChangeListener {
private static Logger log = LoggerFactory.getLogger(NSClientInternalFragment.class); private static Logger log = LoggerFactory.getLogger(NSClientFragment.class);
private TextView logTextView; private TextView logTextView;
private TextView queueTextView; private TextView queueTextView;
@ -58,10 +57,10 @@ public class NSClientInternalFragment extends SubscriberFragment implements View
logScrollview = (ScrollView) view.findViewById(R.id.nsclientinternal_logscrollview); logScrollview = (ScrollView) view.findViewById(R.id.nsclientinternal_logscrollview);
autoscrollCheckbox = (CheckBox) view.findViewById(R.id.nsclientinternal_autoscroll); autoscrollCheckbox = (CheckBox) view.findViewById(R.id.nsclientinternal_autoscroll);
autoscrollCheckbox.setChecked(NSClientInternalPlugin.getPlugin().autoscroll); autoscrollCheckbox.setChecked(NSClientPlugin.getPlugin().autoscroll);
autoscrollCheckbox.setOnCheckedChangeListener(this); autoscrollCheckbox.setOnCheckedChangeListener(this);
pausedCheckbox = (CheckBox) view.findViewById(R.id.nsclientinternal_paused); pausedCheckbox = (CheckBox) view.findViewById(R.id.nsclientinternal_paused);
pausedCheckbox.setChecked(NSClientInternalPlugin.getPlugin().paused); pausedCheckbox.setChecked(NSClientPlugin.getPlugin().paused);
pausedCheckbox.setOnCheckedChangeListener(this); pausedCheckbox.setOnCheckedChangeListener(this);
logTextView = (TextView) view.findViewById(R.id.nsclientinternal_log); logTextView = (TextView) view.findViewById(R.id.nsclientinternal_log);
queueTextView = (TextView) view.findViewById(R.id.nsclientinternal_queue); queueTextView = (TextView) view.findViewById(R.id.nsclientinternal_queue);
@ -101,11 +100,11 @@ public class NSClientInternalFragment extends SubscriberFragment implements View
FabricPrivacy.getInstance().logCustom(new CustomEvent("NSClientRestart")); FabricPrivacy.getInstance().logCustom(new CustomEvent("NSClientRestart"));
break; break;
case R.id.nsclientinternal_delivernow: case R.id.nsclientinternal_delivernow:
NSClientInternalPlugin.getPlugin().resend("GUI"); NSClientPlugin.getPlugin().resend("GUI");
FabricPrivacy.getInstance().logCustom(new CustomEvent("NSClientDeliverNow")); FabricPrivacy.getInstance().logCustom(new CustomEvent("NSClientDeliverNow"));
break; break;
case R.id.nsclientinternal_clearlog: case R.id.nsclientinternal_clearlog:
NSClientInternalPlugin.getPlugin().clearLog(); NSClientPlugin.getPlugin().clearLog();
break; break;
case R.id.nsclientinternal_clearqueue: case R.id.nsclientinternal_clearqueue:
final Context context = getContext(); final Context context = getContext();
@ -124,7 +123,7 @@ public class NSClientInternalFragment extends SubscriberFragment implements View
builder.show(); builder.show();
break; break;
case R.id.nsclientinternal_showqueue: case R.id.nsclientinternal_showqueue:
MainApp.bus().post(new EventNSClientNewLog("QUEUE", NSClientInternalPlugin.getPlugin().queue().textList())); MainApp.bus().post(new EventNSClientNewLog("QUEUE", NSClientPlugin.getPlugin().queue().textList()));
FabricPrivacy.getInstance().logCustom(new CustomEvent("NSClientShowQueue")); FabricPrivacy.getInstance().logCustom(new CustomEvent("NSClientShowQueue"));
break; break;
} }
@ -135,14 +134,14 @@ public class NSClientInternalFragment extends SubscriberFragment implements View
switch (buttonView.getId()) { switch (buttonView.getId()) {
case R.id.nsclientinternal_paused: case R.id.nsclientinternal_paused:
SP.putBoolean(R.string.key_nsclientinternal_paused, isChecked); SP.putBoolean(R.string.key_nsclientinternal_paused, isChecked);
NSClientInternalPlugin.getPlugin().paused = isChecked; NSClientPlugin.getPlugin().paused = isChecked;
MainApp.bus().post(new EventPreferenceChange(R.string.key_nsclientinternal_paused)); MainApp.bus().post(new EventPreferenceChange(R.string.key_nsclientinternal_paused));
updateGUI(); updateGUI();
FabricPrivacy.getInstance().logCustom(new CustomEvent("NSClientPause")); FabricPrivacy.getInstance().logCustom(new CustomEvent("NSClientPause"));
break; break;
case R.id.nsclientinternal_autoscroll: case R.id.nsclientinternal_autoscroll:
SP.putBoolean(R.string.key_nsclientinternal_autoscroll, isChecked); SP.putBoolean(R.string.key_nsclientinternal_autoscroll, isChecked);
NSClientInternalPlugin.getPlugin().autoscroll = isChecked; NSClientPlugin.getPlugin().autoscroll = isChecked;
updateGUI(); updateGUI();
break; break;
} }
@ -160,15 +159,15 @@ public class NSClientInternalFragment extends SubscriberFragment implements View
activity.runOnUiThread(new Runnable() { activity.runOnUiThread(new Runnable() {
@Override @Override
public void run() { public void run() {
NSClientInternalPlugin.updateLog(); NSClientPlugin.getPlugin().updateLog();
logTextView.setText(NSClientInternalPlugin.textLog); logTextView.setText(NSClientPlugin.getPlugin().textLog);
if (NSClientInternalPlugin.getPlugin().autoscroll) { if (NSClientPlugin.getPlugin().autoscroll) {
logScrollview.fullScroll(ScrollView.FOCUS_DOWN); logScrollview.fullScroll(ScrollView.FOCUS_DOWN);
} }
urlTextView.setText(NSClientInternalPlugin.getPlugin().url()); urlTextView.setText(NSClientPlugin.getPlugin().url());
Spanned queuetext = Html.fromHtml(MainApp.sResources.getString(R.string.queue) + " <b>" + UploadQueue.size() + "</b>"); Spanned queuetext = Html.fromHtml(MainApp.sResources.getString(R.string.queue) + " <b>" + UploadQueue.size() + "</b>");
queueTextView.setText(queuetext); queueTextView.setText(queuetext);
statusTextView.setText(NSClientInternalPlugin.getPlugin().status); statusTextView.setText(NSClientPlugin.getPlugin().status);
} }
}); });
} }

View file

@ -18,126 +18,90 @@ import org.slf4j.LoggerFactory;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import info.nightscout.androidaps.BuildConfig;
import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.events.EventAppExit; import info.nightscout.androidaps.events.EventAppExit;
import info.nightscout.androidaps.events.EventNetworkChange;
import info.nightscout.androidaps.events.EventPreferenceChange;
import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientNewLog; import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientNewLog;
import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientStatus; import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientStatus;
import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientUpdateGUI; import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientUpdateGUI;
import info.nightscout.androidaps.plugins.NSClientInternal.services.NSClientService; import info.nightscout.androidaps.plugins.NSClientInternal.services.NSClientService;
import info.nightscout.androidaps.receivers.NetworkChangeReceiver;
import info.nightscout.utils.SP; import info.nightscout.utils.SP;
import info.nightscout.utils.ToastUtils; import info.nightscout.utils.ToastUtils;
public class NSClientInternalPlugin implements PluginBase { public class NSClientPlugin extends PluginBase {
private static Logger log = LoggerFactory.getLogger(NSClientInternalPlugin.class); private static Logger log = LoggerFactory.getLogger(NSClientPlugin.class);
static NSClientInternalPlugin nsClientInternalPlugin; static NSClientPlugin nsClientPlugin;
static public NSClientInternalPlugin getPlugin() { static public NSClientPlugin getPlugin() {
if (nsClientInternalPlugin == null) { if (nsClientPlugin == null) {
nsClientInternalPlugin = new NSClientInternalPlugin(); nsClientPlugin = new NSClientPlugin();
} }
return nsClientInternalPlugin; return nsClientPlugin;
} }
private boolean fragmentEnabled = true; public Handler handler;
private boolean fragmentVisible = true;
static public Handler handler; private final List<EventNSClientNewLog> listLog = new ArrayList<>();
Spanned textLog = Html.fromHtml("");
private static List<EventNSClientNewLog> listLog = new ArrayList<>();
static Spanned textLog = Html.fromHtml("");
public boolean paused = false; public boolean paused = false;
public boolean allowed = true;
boolean autoscroll = true; boolean autoscroll = true;
public String status = ""; public String status = "";
public NSClientService nsClientService = null; public NSClientService nsClientService = null;
NSClientInternalPlugin() { private NSClientPlugin() {
MainApp.bus().register(this); super(new PluginDescription()
.mainType(PluginType.GENERAL)
.fragmentClass(NSClientFragment.class.getName())
.pluginName(R.string.nsclientinternal)
.shortName(R.string.nsclientinternal_shortname)
.preferencesId(R.xml.pref_nsclientinternal)
);
if (Config.NSCLIENT || Config.G5UPLOADER) {
pluginDescription.alwaysEnabled(true).visibleByDefault(true);
}
paused = SP.getBoolean(R.string.key_nsclientinternal_paused, false); paused = SP.getBoolean(R.string.key_nsclientinternal_paused, false);
autoscroll = SP.getBoolean(R.string.key_nsclientinternal_autoscroll, true); autoscroll = SP.getBoolean(R.string.key_nsclientinternal_autoscroll, true);
if (handler == null) { if (handler == null) {
HandlerThread handlerThread = new HandlerThread(NSClientInternalPlugin.class.getSimpleName() + "Handler"); HandlerThread handlerThread = new HandlerThread(NSClientPlugin.class.getSimpleName() + "Handler");
handlerThread.start(); handlerThread.start();
handler = new Handler(handlerThread.getLooper()); handler = new Handler(handlerThread.getLooper());
} }
}
@Override
protected void onStart() {
MainApp.bus().register(this);
Context context = MainApp.instance().getApplicationContext(); Context context = MainApp.instance().getApplicationContext();
Intent intent = new Intent(context, NSClientService.class); Intent intent = new Intent(context, NSClientService.class);
context.bindService(intent, mConnection, Context.BIND_AUTO_CREATE); context.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
super.onStart();
EventNetworkChange event = NetworkChangeReceiver.grabNetworkStatus();
if (event != null)
MainApp.bus().post(event);
} }
@Override @Override
public int getType() { protected void onStop() {
return PluginBase.GENERAL; MainApp.bus().unregister(this);
} Context context = MainApp.instance().getApplicationContext();
context.unbindService(mConnection);
@Override
public String getFragmentClass() {
return NSClientInternalFragment.class.getName();
}
@Override
public String getName() {
return MainApp.sResources.getString(R.string.nsclientinternal);
}
@Override
public String getNameShort() {
String name = MainApp.sResources.getString(R.string.nsclientinternal_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_nsclientinternal;
} }
private ServiceConnection mConnection = new ServiceConnection() { private ServiceConnection mConnection = new ServiceConnection() {
@ -150,13 +114,44 @@ public class NSClientInternalPlugin implements PluginBase {
public void onServiceConnected(ComponentName name, IBinder service) { public void onServiceConnected(ComponentName name, IBinder service) {
log.debug("Service is connected"); log.debug("Service is connected");
NSClientService.LocalBinder mLocalBinder = (NSClientService.LocalBinder) service; NSClientService.LocalBinder mLocalBinder = (NSClientService.LocalBinder) service;
if (mLocalBinder != null) // is null when running in roboelectric
nsClientService = mLocalBinder.getServiceInstance(); nsClientService = mLocalBinder.getServiceInstance();
} }
}; };
@SuppressWarnings("UnusedParameters")
@Subscribe @Subscribe
public void onStatusEvent(final EventAppExit e) { public void onStatusEvent(EventPreferenceChange ev) {
if (ev.isChanged(R.string.key_ns_wifionly) ||
ev.isChanged(R.string.key_ns_wifi_ssids) ||
ev.isChanged(R.string.key_ns_allowroaming)
) {
EventNetworkChange event = NetworkChangeReceiver.grabNetworkStatus();
if (event != null)
MainApp.bus().post(event);
}
}
@Subscribe
public void onStatusEvent(final EventNetworkChange ev) {
boolean wifiOnly = SP.getBoolean(R.string.key_ns_wifionly, false);
String allowedSSIDs = SP.getString(R.string.key_ns_wifi_ssids, "");
boolean allowRoaming = SP.getBoolean(R.string.key_ns_allowroaming, true) && !wifiOnly;
boolean newAllowedState = true;
if (!ev.wifiConnected && wifiOnly) newAllowedState = false;
if (ev.wifiConnected && !allowedSSIDs.isEmpty() && !allowedSSIDs.contains(ev.ssid))
newAllowedState = false;
if (!allowRoaming && ev.roaming) newAllowedState = false;
if (newAllowedState != allowed) {
allowed = newAllowedState;
MainApp.bus().post(new EventPreferenceChange(R.string.key_nsclientinternal_paused));
}
}
@Subscribe
public void onStatusEvent(final EventAppExit ignored) {
if (nsClientService != null) if (nsClientService != null)
MainApp.instance().getApplicationContext().unbindService(mConnection); MainApp.instance().getApplicationContext().unbindService(mConnection);
} }
@ -177,7 +172,9 @@ public class NSClientInternalPlugin implements PluginBase {
handler.post(new Runnable() { handler.post(new Runnable() {
@Override @Override
public void run() { public void run() {
listLog = new ArrayList<>(); synchronized (listLog) {
listLog.clear();
}
MainApp.bus().post(new EventNSClientUpdateGUI()); MainApp.bus().post(new EventNSClientUpdateGUI());
} }
}); });
@ -187,23 +184,26 @@ public class NSClientInternalPlugin implements PluginBase {
handler.post(new Runnable() { handler.post(new Runnable() {
@Override @Override
public void run() { public void run() {
synchronized (listLog) {
listLog.add(ev); listLog.add(ev);
// remove the first line if log is too large // remove the first line if log is too large
if (listLog.size() >= Constants.MAX_LOG_LINES) { if (listLog.size() >= Constants.MAX_LOG_LINES) {
listLog.remove(0); listLog.remove(0);
} }
}
MainApp.bus().post(new EventNSClientUpdateGUI()); MainApp.bus().post(new EventNSClientUpdateGUI());
} }
}); });
} }
static synchronized void updateLog() { synchronized void updateLog() {
try { try {
StringBuilder newTextLog = new StringBuilder(); StringBuilder newTextLog = new StringBuilder();
List<EventNSClientNewLog> temporaryList = new ArrayList<>(listLog); synchronized (listLog) {
for (EventNSClientNewLog log : temporaryList) { for (EventNSClientNewLog log : listLog) {
newTextLog.append(log.toPreparedHtml()); newTextLog.append(log.toPreparedHtml());
} }
}
textLog = Html.fromHtml(newTextLog.toString()); textLog = Html.fromHtml(newTextLog.toString());
} catch (OutOfMemoryError e) { } catch (OutOfMemoryError e) {
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), "Out of memory!\nStop using this phone !!!", R.raw.error); ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), "Out of memory!\nStop using this phone !!!", R.raw.error);

View file

@ -48,7 +48,7 @@ public class UploadQueue {
public void run() { public void run() {
log.debug("QUEUE adding: " + dbr.data); log.debug("QUEUE adding: " + dbr.data);
MainApp.getDbHelper().create(dbr); MainApp.getDbHelper().create(dbr);
NSClientInternalPlugin plugin = MainApp.getSpecificPlugin(NSClientInternalPlugin.class); NSClientPlugin plugin = NSClientPlugin.getPlugin();
if (plugin != null) { if (plugin != null) {
plugin.resend("newdata"); plugin.resend("newdata");
} }

View file

@ -170,6 +170,19 @@ public class NSSettingsStatus {
} }
// valid property is "warn" or "urgent"
// plugings "iage" "sage" "cage" "pbage"
public double getExtendedWarnValue(String plugin, String property, double defaultvalue) {
JSONObject extendedSettings = this.getExtendedSettings();
if (extendedSettings == null)
return defaultvalue;
JSONObject pluginJson = extendedSettings.optJSONObject(plugin);
if (pluginJson == null)
return defaultvalue;
return pluginJson.optDouble(property, defaultvalue);
}
public String getActiveProfile() { public String getActiveProfile() {
return getStringOrNull("activeProfile"); return getStringOrNull("activeProfile");
} }

View file

@ -6,19 +6,14 @@ import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.os.PowerManager; import android.os.PowerManager;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.Date;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.db.DbRequest;
import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.plugins.NSClientInternal.NSClientInternalPlugin; import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.plugins.NSClientInternal.UploadQueue; import info.nightscout.androidaps.plugins.NSClientInternal.NSClientPlugin;
import info.nightscout.androidaps.plugins.NSClientInternal.data.AlarmAck; import info.nightscout.androidaps.plugins.NSClientInternal.data.AlarmAck;
import info.nightscout.androidaps.plugins.NSClientInternal.services.NSClientService; import info.nightscout.androidaps.plugins.NSClientInternal.services.NSClientService;
import info.nightscout.utils.SP; import info.nightscout.utils.SP;
@ -32,8 +27,8 @@ public class AckAlarmReceiver extends BroadcastReceiver {
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
AckAlarmReceiver.class.getSimpleName()); AckAlarmReceiver.class.getSimpleName());
NSClientInternalPlugin nsClientInternalPlugin = MainApp.getSpecificPlugin(NSClientInternalPlugin.class); NSClientPlugin nsClientPlugin = MainApp.getSpecificPlugin(NSClientPlugin.class);
if (!nsClientInternalPlugin.isEnabled(PluginBase.GENERAL)) { if (!nsClientPlugin.isEnabled(PluginType.GENERAL)) {
return; return;
} }
if (SP.getBoolean(R.string.key_ns_noupload, false)) { if (SP.getBoolean(R.string.key_ns_noupload, false)) {
@ -53,7 +48,7 @@ public class AckAlarmReceiver extends BroadcastReceiver {
ack.group = bundles.getString("group"); ack.group = bundles.getString("group");
ack.silenceTime = bundles.getLong("silenceTime"); ack.silenceTime = bundles.getLong("silenceTime");
NSClientService nsClientService = nsClientInternalPlugin.nsClientService; NSClientService nsClientService = nsClientPlugin.nsClientService;
if (nsClientService != null) if (nsClientService != null)
nsClientService.sendAlarmAck(ack); nsClientService.sendAlarmAck(ack);

View file

@ -14,8 +14,8 @@ import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.db.DbRequest; import info.nightscout.androidaps.db.DbRequest;
import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.plugins.NSClientInternal.NSClientInternalPlugin; import info.nightscout.androidaps.plugins.NSClientInternal.NSClientPlugin;
import info.nightscout.androidaps.plugins.NSClientInternal.UploadQueue; import info.nightscout.androidaps.plugins.NSClientInternal.UploadQueue;
import info.nightscout.androidaps.plugins.NSClientInternal.broadcasts.BroadcastTreatment; import info.nightscout.androidaps.plugins.NSClientInternal.broadcasts.BroadcastTreatment;
import info.nightscout.utils.DateUtil; import info.nightscout.utils.DateUtil;
@ -94,7 +94,7 @@ public class DBAccessReceiver extends BroadcastReceiver {
UploadQueue.add(dbr); UploadQueue.add(dbr);
} }
if (collection.equals("treatments")) { if (collection.equals("treatments")) {
genereateTreatmentOfflineBroadcast(dbr); generateTreatmentOfflineBroadcast(dbr);
} }
} }
@ -105,11 +105,11 @@ public class DBAccessReceiver extends BroadcastReceiver {
} }
public boolean shouldUpload() { public boolean shouldUpload() {
NSClientInternalPlugin nsClientInternalPlugin = MainApp.getSpecificPlugin(NSClientInternalPlugin.class); NSClientPlugin nsClientPlugin = MainApp.getSpecificPlugin(NSClientPlugin.class);
return nsClientInternalPlugin.isEnabled(PluginBase.GENERAL) && !SP.getBoolean(R.string.key_ns_noupload, false); return nsClientPlugin.isEnabled(PluginType.GENERAL) && !SP.getBoolean(R.string.key_ns_noupload, false);
} }
public void genereateTreatmentOfflineBroadcast(DbRequest request) { public void generateTreatmentOfflineBroadcast(DbRequest request) {
if (request.action.equals("dbAdd")) { if (request.action.equals("dbAdd")) {
try { try {
JSONObject data = new JSONObject(request.data); JSONObject data = new JSONObject(request.data);

View file

@ -34,7 +34,8 @@ import info.nightscout.androidaps.events.EventAppExit;
import info.nightscout.androidaps.events.EventConfigBuilderChange; import info.nightscout.androidaps.events.EventConfigBuilderChange;
import info.nightscout.androidaps.events.EventPreferenceChange; import info.nightscout.androidaps.events.EventPreferenceChange;
import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.plugins.NSClientInternal.NSClientInternalPlugin; import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.plugins.NSClientInternal.NSClientPlugin;
import info.nightscout.androidaps.plugins.NSClientInternal.UploadQueue; import info.nightscout.androidaps.plugins.NSClientInternal.UploadQueue;
import info.nightscout.androidaps.plugins.NSClientInternal.acks.NSAddAck; import info.nightscout.androidaps.plugins.NSClientInternal.acks.NSAddAck;
import info.nightscout.androidaps.plugins.NSClientInternal.acks.NSAuthAck; import info.nightscout.androidaps.plugins.NSClientInternal.acks.NSAuthAck;
@ -180,7 +181,7 @@ public class NSClientService extends Service {
@Subscribe @Subscribe
public void onStatusEvent(EventConfigBuilderChange ev) { public void onStatusEvent(EventConfigBuilderChange ev) {
if (nsEnabled != MainApp.getSpecificPlugin(NSClientInternalPlugin.class).isEnabled(PluginBase.GENERAL)) { if (nsEnabled != MainApp.getSpecificPlugin(NSClientPlugin.class).isEnabled(PluginType.GENERAL)) {
latestDateInReceivedData = 0; latestDateInReceivedData = 0;
destroy(); destroy();
initialize(); initialize();
@ -202,7 +203,10 @@ public class NSClientService extends Service {
nsAPIhashCode = Hashing.sha1().hashString(nsAPISecret, Charsets.UTF_8).toString(); nsAPIhashCode = Hashing.sha1().hashString(nsAPISecret, Charsets.UTF_8).toString();
MainApp.bus().post(new EventNSClientStatus("Initializing")); MainApp.bus().post(new EventNSClientStatus("Initializing"));
if (MainApp.getSpecificPlugin(NSClientInternalPlugin.class).paused) { if (!MainApp.getSpecificPlugin(NSClientPlugin.class).allowed) {
MainApp.bus().post(new EventNSClientNewLog("NSCLIENT", "not allowed"));
MainApp.bus().post(new EventNSClientStatus("Not allowed"));
} else if (MainApp.getSpecificPlugin(NSClientPlugin.class).paused) {
MainApp.bus().post(new EventNSClientNewLog("NSCLIENT", "paused")); MainApp.bus().post(new EventNSClientNewLog("NSCLIENT", "paused"));
MainApp.bus().post(new EventNSClientStatus("Paused")); MainApp.bus().post(new EventNSClientStatus("Paused"));
} else if (!nsEnabled) { } else if (!nsEnabled) {
@ -313,7 +317,7 @@ public class NSClientService extends Service {
} }
public void readPreferences() { public void readPreferences() {
nsEnabled = MainApp.getSpecificPlugin(NSClientInternalPlugin.class).isEnabled(PluginBase.GENERAL); nsEnabled = MainApp.getSpecificPlugin(NSClientPlugin.class).isEnabled(PluginType.GENERAL);
nsURL = SP.getString(R.string.key_nsclientinternal_url, ""); nsURL = SP.getString(R.string.key_nsclientinternal_url, "");
nsAPISecret = SP.getString(R.string.key_nsclientinternal_api_secret, ""); nsAPISecret = SP.getString(R.string.key_nsclientinternal_api_secret, "");
nsDevice = SP.getString("careportal_enteredby", ""); nsDevice = SP.getString("careportal_enteredby", "");

View file

@ -21,6 +21,7 @@ import java.lang.reflect.InvocationTargetException;
import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.GlucoseStatus; import info.nightscout.androidaps.data.GlucoseStatus;
import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.data.MealData; import info.nightscout.androidaps.data.MealData;
@ -30,6 +31,7 @@ import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugi
import info.nightscout.androidaps.plugins.Loop.ScriptReader; import info.nightscout.androidaps.plugins.Loop.ScriptReader;
import info.nightscout.androidaps.plugins.OpenAPSMA.LoggerCallback; import info.nightscout.androidaps.plugins.OpenAPSMA.LoggerCallback;
import info.nightscout.androidaps.plugins.OpenAPSSMB.SMBDefaults; import info.nightscout.androidaps.plugins.OpenAPSSMB.SMBDefaults;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.utils.SP; import info.nightscout.utils.SP;
public class DetermineBasalAdapterAMAJS { public class DetermineBasalAdapterAMAJS {
@ -204,28 +206,34 @@ public class DetermineBasalAdapterAMAJS {
mProfile.put("max_bg", maxBg); mProfile.put("max_bg", maxBg);
mProfile.put("target_bg", targetBg); mProfile.put("target_bg", targetBg);
mProfile.put("carb_ratio", profile.getIc()); mProfile.put("carb_ratio", profile.getIc());
mProfile.put("sens", Profile.toMgdl(profile.getIsf().doubleValue(), units)); mProfile.put("sens", Profile.toMgdl(profile.getIsf(), units));
mProfile.put("max_daily_safety_multiplier", SP.getInt("openapsama_max_daily_safety_multiplier", 3)); mProfile.put("max_daily_safety_multiplier", SP.getInt(R.string.key_openapsama_max_daily_safety_multiplier, 3));
mProfile.put("current_basal_safety_multiplier", SP.getDouble("openapsama_current_basal_safety_multiplier", 4d)); mProfile.put("current_basal_safety_multiplier", SP.getDouble(R.string.key_openapsama_current_basal_safety_multiplier, 4d));
mProfile.put("skip_neutral_temps", true); mProfile.put("skip_neutral_temps", true);
mProfile.put("current_basal", basalrate); mProfile.put("current_basal", basalrate);
mProfile.put("temptargetSet", tempTargetSet); mProfile.put("temptargetSet", tempTargetSet);
mProfile.put("autosens_adjust_targets", SP.getBoolean("openapsama_autosens_adjusttargets", true)); mProfile.put("autosens_adjust_targets", SP.getBoolean(R.string.key_openapsama_autosens_adjusttargets, true));
//TODO: align with max-absorption model in AMA sensitivity //align with max-absorption model in AMA sensitivity
mProfile.put("min_5m_carbimpact", SP.getDouble("openapsama_min_5m_carbimpact", SMBDefaults.min_5m_carbimpact)); if(mealData.usedMinCarbsImpact > 0){
mProfile.put("min_5m_carbimpact", mealData.usedMinCarbsImpact);
} else {
mProfile.put("min_5m_carbimpact", SP.getDouble(R.string.key_openapsama_min_5m_carbimpact, SMBDefaults.min_5m_carbimpact));
}
if (units.equals(Constants.MMOL)) { if (units.equals(Constants.MMOL)) {
mProfile.put("out_units", "mmol/L"); mProfile.put("out_units", "mmol/L");
} }
long now = System.currentTimeMillis();
TemporaryBasal tb = TreatmentsPlugin.getPlugin().getTempBasalFromHistory(now);
mCurrentTemp = new JSONObject(); mCurrentTemp = new JSONObject();
mCurrentTemp.put("temp", "absolute"); mCurrentTemp.put("temp", "absolute");
mCurrentTemp.put("duration", MainApp.getConfigBuilder().getTempBasalRemainingMinutesFromHistory()); mCurrentTemp.put("duration", tb != null ? tb.getPlannedRemainingMinutes() : 0);
mCurrentTemp.put("rate", MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory()); mCurrentTemp.put("rate", tb != null ? tb.tempBasalConvertedToAbsolute(now, profile) : 0d);
// as we have non default temps longer than 30 mintues // as we have non default temps longer than 30 mintues
TemporaryBasal tempBasal = MainApp.getConfigBuilder().getTempBasalFromHistory(System.currentTimeMillis()); TemporaryBasal tempBasal = TreatmentsPlugin.getPlugin().getTempBasalFromHistory(System.currentTimeMillis());
if (tempBasal != null) { if (tempBasal != null) {
mCurrentTemp.put("minutesrunning", tempBasal.getRealDuration()); mCurrentTemp.put("minutesrunning", tempBasal.getRealDuration());
} }
@ -235,7 +243,7 @@ public class DetermineBasalAdapterAMAJS {
mGlucoseStatus = new JSONObject(); mGlucoseStatus = new JSONObject();
mGlucoseStatus.put("glucose", glucoseStatus.glucose); mGlucoseStatus.put("glucose", glucoseStatus.glucose);
if (SP.getBoolean("always_use_shortavg", false)) { if (SP.getBoolean(R.string.key_always_use_shortavg, false)) {
mGlucoseStatus.put("delta", glucoseStatus.short_avgdelta); mGlucoseStatus.put("delta", glucoseStatus.short_avgdelta);
} else { } else {
mGlucoseStatus.put("delta", glucoseStatus.delta); mGlucoseStatus.put("delta", glucoseStatus.delta);
@ -248,7 +256,7 @@ public class DetermineBasalAdapterAMAJS {
mMealData.put("boluses", mealData.boluses); mMealData.put("boluses", mealData.boluses);
mMealData.put("mealCOB", mealData.mealCOB); mMealData.put("mealCOB", mealData.mealCOB);
if (MainApp.getConfigBuilder().isAMAModeEnabled()) { if (MainApp.getConstraintChecker().isAutosensModeEnabled().value()) {
mAutosensData = new JSONObject(); mAutosensData = new JSONObject();
mAutosensData.put("ratio", autosensDataRatio); mAutosensData.put("ratio", autosensDataRatio);
} else { } else {

View file

@ -22,7 +22,7 @@ public class DetermineBasalResultAMA extends APSResult {
json = j; json = j;
if (result.containsKey("error")) { if (result.containsKey("error")) {
reason = result.get("error").toString(); reason = result.get("error").toString();
tempBasalReqested = false; tempBasalRequested = false;
rate = -1; rate = -1;
duration = -1; duration = -1;
} else { } else {
@ -32,17 +32,17 @@ public class DetermineBasalResultAMA extends APSResult {
if (result.containsKey("rate")) { if (result.containsKey("rate")) {
rate = (Double) result.get("rate"); rate = (Double) result.get("rate");
if (rate < 0d) rate = 0d; if (rate < 0d) rate = 0d;
tempBasalReqested = true; tempBasalRequested = true;
} else { } else {
rate = -1; rate = -1;
tempBasalReqested = false; tempBasalRequested = false;
} }
if (result.containsKey("duration")) { if (result.containsKey("duration")) {
duration = ((Double) result.get("duration")).intValue(); duration = ((Double) result.get("duration")).intValue();
//changeRequested as above //changeRequested as above
} else { } else {
duration = -1; duration = -1;
tempBasalReqested = false; tempBasalRequested = false;
} }
} }
bolusRequested = false; bolusRequested = false;
@ -58,7 +58,7 @@ public class DetermineBasalResultAMA extends APSResult {
newResult.reason = reason; newResult.reason = reason;
newResult.rate = rate; newResult.rate = rate;
newResult.duration = duration; newResult.duration = duration;
newResult.tempBasalReqested = tempBasalReqested; newResult.tempBasalRequested = tempBasalRequested;
newResult.rate = rate; newResult.rate = rate;
newResult.duration = duration; newResult.duration = duration;

View file

@ -72,7 +72,7 @@ public class OpenAPSAMAFragment extends SubscriberFragment implements View.OnCli
public void onClick(View view) { public void onClick(View view) {
switch (view.getId()) { switch (view.getId()) {
case R.id.openapsma_run: case R.id.openapsma_run:
OpenAPSAMAPlugin.getPlugin().invoke("OpenAPSAMA button"); OpenAPSAMAPlugin.getPlugin().invoke("OpenAPSAMA button", false);
FabricPrivacy.getInstance().logCustom(new CustomEvent("OpenAPS_AMA_Run")); FabricPrivacy.getInstance().logCustom(new CustomEvent("OpenAPS_AMA_Run"));
break; break;
} }

View file

@ -15,8 +15,11 @@ import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.data.MealData; import info.nightscout.androidaps.data.MealData;
import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.db.TempTarget; import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.interfaces.APSInterface; import info.nightscout.androidaps.interfaces.APSInterface;
import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensResult; import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensResult;
@ -25,16 +28,16 @@ import info.nightscout.androidaps.plugins.Loop.APSResult;
import info.nightscout.androidaps.plugins.Loop.ScriptReader; import info.nightscout.androidaps.plugins.Loop.ScriptReader;
import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateGui; import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateGui;
import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateResultGui; import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateResultGui;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.utils.DateUtil; import info.nightscout.utils.DateUtil;
import info.nightscout.utils.HardLimits; import info.nightscout.utils.HardLimits;
import info.nightscout.utils.Profiler; import info.nightscout.utils.Profiler;
import info.nightscout.utils.Round; import info.nightscout.utils.Round;
import info.nightscout.utils.SP;
/** /**
* Created by mike on 05.08.2016. * Created by mike on 05.08.2016.
*/ */
public class OpenAPSAMAPlugin implements PluginBase, APSInterface { public class OpenAPSAMAPlugin extends PluginBase implements APSInterface {
private static Logger log = LoggerFactory.getLogger(OpenAPSAMAPlugin.class); private static Logger log = LoggerFactory.getLogger(OpenAPSAMAPlugin.class);
private static OpenAPSAMAPlugin openAPSAMAPlugin; private static OpenAPSAMAPlugin openAPSAMAPlugin;
@ -52,75 +55,26 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface {
DetermineBasalResultAMA lastAPSResult = null; DetermineBasalResultAMA lastAPSResult = null;
AutosensResult lastAutosensResult = null; AutosensResult lastAutosensResult = null;
private boolean fragmentEnabled = false; public OpenAPSAMAPlugin() {
private boolean fragmentVisible = false; super(new PluginDescription()
.mainType(PluginType.APS)
@Override .fragmentClass(OpenAPSAMAFragment.class.getName())
public String getName() { .pluginName(R.string.openapsama)
return MainApp.instance().getString(R.string.openapsama); .shortName(R.string.oaps_shortname)
.preferencesId(R.xml.pref_openapsama)
);
} }
@Override @Override
public String getNameShort() { public boolean specialEnableCondition() {
String name = MainApp.sResources.getString(R.string.oaps_shortname); PumpInterface pump = ConfigBuilderPlugin.getActivePump();
if (!name.trim().isEmpty()) { return pump == null || pump.getPumpDescription().isTempBasalCapable;
//only if translation exists
return name;
}
// use long name as fallback
return getName();
} }
@Override @Override
public boolean isEnabled(int type) { public boolean specialShowInListCondition() {
boolean pumpCapable = ConfigBuilderPlugin.getActivePump() == null || ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable; PumpInterface pump = ConfigBuilderPlugin.getActivePump();
return type == APS && fragmentEnabled && pumpCapable; return pump == null || pump.getPumpDescription().isTempBasalCapable;
}
@Override
public boolean isVisibleInTabs(int type) {
boolean pumpCapable = ConfigBuilderPlugin.getActivePump() == null || ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable;
return type == APS && fragmentVisible && pumpCapable;
}
@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 setFragmentVisible(int type, boolean fragmentVisible) {
if (type == APS) this.fragmentVisible = fragmentVisible;
}
@Override
public int getPreferencesId() {
return R.xml.pref_openapsama;
}
@Override
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
if (type == APS) this.fragmentEnabled = fragmentEnabled;
}
@Override
public int getType() {
return PluginBase.APS;
}
@Override
public String getFragmentClass() {
return OpenAPSAMAFragment.class.getName();
} }
@Override @Override
@ -134,8 +88,8 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface {
} }
@Override @Override
public void invoke(String initiator) { public void invoke(String initiator, boolean tempBasalFallback) {
log.debug("invoke from " + initiator); log.debug("invoke from " + initiator + " tempBasalFallback: " + tempBasalFallback);
lastAPSResult = null; lastAPSResult = null;
DetermineBasalAdapterAMAJS determineBasalAdapterAMAJS; DetermineBasalAdapterAMAJS determineBasalAdapterAMAJS;
try { try {
@ -156,7 +110,7 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface {
return; return;
} }
if (!isEnabled(PluginBase.APS)) { if (!isEnabled(PluginType.APS)) {
MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.instance().getString(R.string.openapsma_disabled))); MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.instance().getString(R.string.openapsma_disabled)));
if (Config.logAPSResult) if (Config.logAPSResult)
log.debug(MainApp.instance().getString(R.string.openapsma_disabled)); log.debug(MainApp.instance().getString(R.string.openapsma_disabled));
@ -172,8 +126,7 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface {
String units = profile.getUnits(); String units = profile.getUnits();
double maxIob = SP.getDouble("openapsma_max_iob", 1.5d); double maxBasal = MainApp.getConstraintChecker().getMaxBasalAllowed(profile).value();
double maxBasal = SP.getDouble("openapsma_max_basal", 1d);
double minBg = Profile.toMgdl(profile.getTargetLow(), units); double minBg = Profile.toMgdl(profile.getTargetLow(), units);
double maxBg = Profile.toMgdl(profile.getTargetHigh(), units); double maxBg = Profile.toMgdl(profile.getTargetHigh(), units);
double targetBg = Profile.toMgdl(profile.getTarget(), units); double targetBg = Profile.toMgdl(profile.getTarget(), units);
@ -183,21 +136,21 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface {
Date start = new Date(); Date start = new Date();
Date startPart = new Date(); Date startPart = new Date();
IobTotal[] iobArray = IobCobCalculatorPlugin.getPlugin().calculateIobArrayInDia(); IobTotal[] iobArray = IobCobCalculatorPlugin.getPlugin().calculateIobArrayInDia(profile);
Profiler.log(log, "calculateIobArrayInDia()", startPart); Profiler.log(log, "calculateIobArrayInDia()", startPart);
startPart = new Date(); startPart = new Date();
MealData mealData = MainApp.getConfigBuilder().getMealData(); MealData mealData = TreatmentsPlugin.getPlugin().getMealData();
Profiler.log(log, "getMealData()", startPart); Profiler.log(log, "getMealData()", startPart);
maxIob = MainApp.getConfigBuilder().applyMaxIOBConstraints(maxIob); double maxIob = MainApp.getConstraintChecker().getMaxIOBAllowed().value();
minBg = HardLimits.verifyHardLimits(minBg, "minBg", HardLimits.VERY_HARD_LIMIT_MIN_BG[0], HardLimits.VERY_HARD_LIMIT_MIN_BG[1]); minBg = HardLimits.verifyHardLimits(minBg, "minBg", HardLimits.VERY_HARD_LIMIT_MIN_BG[0], HardLimits.VERY_HARD_LIMIT_MIN_BG[1]);
maxBg = HardLimits.verifyHardLimits(maxBg, "maxBg", HardLimits.VERY_HARD_LIMIT_MAX_BG[0], HardLimits.VERY_HARD_LIMIT_MAX_BG[1]); maxBg = HardLimits.verifyHardLimits(maxBg, "maxBg", HardLimits.VERY_HARD_LIMIT_MAX_BG[0], HardLimits.VERY_HARD_LIMIT_MAX_BG[1]);
targetBg = HardLimits.verifyHardLimits(targetBg, "targetBg", HardLimits.VERY_HARD_LIMIT_TARGET_BG[0], HardLimits.VERY_HARD_LIMIT_TARGET_BG[1]); targetBg = HardLimits.verifyHardLimits(targetBg, "targetBg", HardLimits.VERY_HARD_LIMIT_TARGET_BG[0], HardLimits.VERY_HARD_LIMIT_TARGET_BG[1]);
boolean isTempTarget = false; boolean isTempTarget = false;
TempTarget tempTarget = MainApp.getConfigBuilder().getTempTargetFromHistory(System.currentTimeMillis()); TempTarget tempTarget = TreatmentsPlugin.getPlugin().getTempTargetFromHistory(System.currentTimeMillis());
if (tempTarget != null) { if (tempTarget != null) {
isTempTarget = true; isTempTarget = true;
minBg = HardLimits.verifyHardLimits(tempTarget.low, "minBg", HardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[0], HardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[1]); minBg = HardLimits.verifyHardLimits(tempTarget.low, "minBg", HardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[0], HardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[1]);
@ -206,14 +159,11 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface {
} }
maxIob = HardLimits.verifyHardLimits(maxIob, "maxIob", 0, HardLimits.maxIobAMA());
maxBasal = HardLimits.verifyHardLimits(maxBasal, "max_basal", 0.1, HardLimits.maxBasal());
if (!HardLimits.checkOnlyHardLimits(profile.getDia(), "dia", HardLimits.MINDIA, HardLimits.MAXDIA)) if (!HardLimits.checkOnlyHardLimits(profile.getDia(), "dia", HardLimits.MINDIA, HardLimits.MAXDIA))
return; return;
if (!HardLimits.checkOnlyHardLimits(profile.getIc(profile.secondsFromMidnight()), "carbratio", HardLimits.MINIC, HardLimits.MAXIC)) if (!HardLimits.checkOnlyHardLimits(profile.getIcTimeFromMidnight(profile.secondsFromMidnight()), "carbratio", HardLimits.MINIC, HardLimits.MAXIC))
return; return;
if (!HardLimits.checkOnlyHardLimits(Profile.toMgdl(profile.getIsf().doubleValue(), units), "sens", HardLimits.MINISF, HardLimits.MAXISF)) if (!HardLimits.checkOnlyHardLimits(Profile.toMgdl(profile.getIsf(), units), "sens", HardLimits.MINISF, HardLimits.MAXISF))
return; return;
if (!HardLimits.checkOnlyHardLimits(profile.getMaxDailyBasal(), "max_daily_basal", 0.05, HardLimits.maxBasal())) if (!HardLimits.checkOnlyHardLimits(profile.getMaxDailyBasal(), "max_daily_basal", 0.05, HardLimits.maxBasal()))
return; return;
@ -221,8 +171,8 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface {
return; return;
startPart = new Date(); startPart = new Date();
if (MainApp.getConfigBuilder().isAMAModeEnabled()) { if (MainApp.getConstraintChecker().isAutosensModeEnabled().value()) {
lastAutosensResult = IobCobCalculatorPlugin.getPlugin().detectSensitivityWithLock(IobCobCalculatorPlugin.oldestDataAvailable(), System.currentTimeMillis()); lastAutosensResult = IobCobCalculatorPlugin.getPlugin().detectSensitivityWithLock(IobCobCalculatorPlugin.getPlugin().oldestDataAvailable(), System.currentTimeMillis());
} else { } else {
lastAutosensResult = new AutosensResult(); lastAutosensResult = new AutosensResult();
} }
@ -244,16 +194,18 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface {
DetermineBasalResultAMA determineBasalResultAMA = determineBasalAdapterAMAJS.invoke(); DetermineBasalResultAMA determineBasalResultAMA = determineBasalAdapterAMAJS.invoke();
Profiler.log(log, "AMA calculation", start); Profiler.log(log, "AMA calculation", start);
// Fix bug determine basal // Fix bug determine basal
if (determineBasalResultAMA.rate == 0d && determineBasalResultAMA.duration == 0 && !MainApp.getConfigBuilder().isTempBasalInProgress()) if (determineBasalResultAMA.rate == 0d && determineBasalResultAMA.duration == 0 && !TreatmentsPlugin.getPlugin().isTempBasalInProgress())
determineBasalResultAMA.tempBasalReqested = false; determineBasalResultAMA.tempBasalRequested = false;
// limit requests on openloop mode // limit requests on openloop mode
if (!MainApp.getConfigBuilder().isClosedModeEnabled()) { if (!MainApp.getConstraintChecker().isClosedLoopAllowed().value()) {
if (MainApp.getConfigBuilder().isTempBasalInProgress() && determineBasalResultAMA.rate == 0 && determineBasalResultAMA.duration == 0) { long now = System.currentTimeMillis();
TemporaryBasal activeTemp = TreatmentsPlugin.getPlugin().getTempBasalFromHistory(now);
if (activeTemp != null && determineBasalResultAMA.rate == 0 && determineBasalResultAMA.duration == 0) {
// going to cancel // going to cancel
} else if (MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultAMA.rate - MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory()) < 0.1) { } else if (activeTemp != null && Math.abs(determineBasalResultAMA.rate - activeTemp.tempBasalConvertedToAbsolute(now, profile)) < 0.1) {
determineBasalResultAMA.tempBasalReqested = false; determineBasalResultAMA.tempBasalRequested = false;
} else if (!MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultAMA.rate - ConfigBuilderPlugin.getActivePump().getBaseBasalRate()) < 0.1) } else if (activeTemp == null && Math.abs(determineBasalResultAMA.rate - ConfigBuilderPlugin.getActivePump().getBaseBasalRate()) < 0.1)
determineBasalResultAMA.tempBasalReqested = false; determineBasalResultAMA.tempBasalRequested = false;
} }
determineBasalResultAMA.iob = iobArray[0]; determineBasalResultAMA.iob = iobArray[0];

View file

@ -18,12 +18,14 @@ import java.lang.reflect.InvocationTargetException;
import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.GlucoseStatus; import info.nightscout.androidaps.data.GlucoseStatus;
import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.data.MealData; import info.nightscout.androidaps.data.MealData;
import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.plugins.Loop.ScriptReader; import info.nightscout.androidaps.plugins.Loop.ScriptReader;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.utils.SP; import info.nightscout.utils.SP;
public class DetermineBasalAdapterMAJS { public class DetermineBasalAdapterMAJS {
@ -171,7 +173,7 @@ public class DetermineBasalAdapterMAJS {
mProfile.put("max_bg", maxBg); mProfile.put("max_bg", maxBg);
mProfile.put("target_bg", targetBg); mProfile.put("target_bg", targetBg);
mProfile.put("carb_ratio", profile.getIc()); mProfile.put("carb_ratio", profile.getIc());
mProfile.put("sens", Profile.toMgdl(profile.getIsf().doubleValue(), units)); mProfile.put("sens", Profile.toMgdl(profile.getIsf(), units));
mProfile.put("current_basal", basalRate); mProfile.put("current_basal", basalRate);
@ -179,9 +181,12 @@ public class DetermineBasalAdapterMAJS {
mProfile.put("out_units", "mmol/L"); mProfile.put("out_units", "mmol/L");
} }
long now = System.currentTimeMillis();
TemporaryBasal tb = TreatmentsPlugin.getPlugin().getTempBasalFromHistory(now);
mCurrentTemp = new JSONObject(); mCurrentTemp = new JSONObject();
mCurrentTemp.put("duration", MainApp.getConfigBuilder().getTempBasalRemainingMinutesFromHistory()); mCurrentTemp.put("duration", tb != null ? tb.getPlannedRemainingMinutes() : 0);
mCurrentTemp.put("rate", MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory()); mCurrentTemp.put("rate", tb != null ? tb.tempBasalConvertedToAbsolute(now, profile) : 0d);
mIobData = new JSONObject(); mIobData = new JSONObject();
mIobData.put("iob", iobData.iob); //netIob mIobData.put("iob", iobData.iob); //netIob
@ -193,7 +198,7 @@ public class DetermineBasalAdapterMAJS {
mGlucoseStatus = new JSONObject(); mGlucoseStatus = new JSONObject();
mGlucoseStatus.put("glucose", glucoseStatus.glucose); mGlucoseStatus.put("glucose", glucoseStatus.glucose);
if (SP.getBoolean("always_use_shortavg", false)) { if (SP.getBoolean(R.string.key_always_use_shortavg, false)) {
mGlucoseStatus.put("delta", glucoseStatus.short_avgdelta); mGlucoseStatus.put("delta", glucoseStatus.short_avgdelta);
} else { } else {
mGlucoseStatus.put("delta", glucoseStatus.delta); mGlucoseStatus.put("delta", glucoseStatus.delta);

View file

@ -20,7 +20,7 @@ public class DetermineBasalResultMA extends APSResult {
json = j; json = j;
if (result.containsKey("error")) { if (result.containsKey("error")) {
reason = (String) result.get("error"); reason = (String) result.get("error");
tempBasalReqested = false; tempBasalRequested = false;
rate = -1; rate = -1;
duration = -1; duration = -1;
mealAssist = ""; mealAssist = "";
@ -31,17 +31,17 @@ public class DetermineBasalResultMA extends APSResult {
if (result.containsKey("rate")) { if (result.containsKey("rate")) {
rate = (Double) result.get("rate"); rate = (Double) result.get("rate");
if (rate < 0d) rate = 0d; if (rate < 0d) rate = 0d;
tempBasalReqested = true; tempBasalRequested = true;
} else { } else {
rate = -1; rate = -1;
tempBasalReqested = false; tempBasalRequested = false;
} }
if (result.containsKey("duration")) { if (result.containsKey("duration")) {
duration = ((Double) result.get("duration")).intValue(); duration = ((Double) result.get("duration")).intValue();
//changeRequested as above //changeRequested as above
} else { } else {
duration = -1; duration = -1;
tempBasalReqested = false; tempBasalRequested = false;
} }
if (result.containsKey("mealAssist")) { if (result.containsKey("mealAssist")) {
mealAssist = result.get("mealAssist").toString(); mealAssist = result.get("mealAssist").toString();
@ -58,10 +58,10 @@ public class DetermineBasalResultMA extends APSResult {
newResult.reason = new String(reason); newResult.reason = new String(reason);
newResult.rate = rate; newResult.rate = rate;
newResult.duration = duration; newResult.duration = duration;
newResult.tempBasalReqested = isChangeRequested(); newResult.tempBasalRequested = isChangeRequested();
newResult.rate = rate; newResult.rate = rate;
newResult.duration = duration; newResult.duration = duration;
newResult.tempBasalReqested = isChangeRequested(); newResult.tempBasalRequested = isChangeRequested();
try { try {
newResult.json = new JSONObject(json.toString()); newResult.json = new JSONObject(json.toString());

Some files were not shown because too many files have changed in this diff Show more