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/
.idea/
app/src/main/jniLibs
full/
debug/
release/

View file

@ -2,7 +2,7 @@ language: android
jdk: oraclejdk8
env:
matrix:
- ANDROID_TARGET=android-23 ANDROID_ABI=x86
- ANDROID_TARGET=android-23 ANDROID_ABI=x86 org.gradle.jvmargs=-XX:-OmitStackTraceInFastThrow
android:
components:
- platform-tools
@ -18,7 +18,17 @@ before_install:
script:
# Unit Test
- ./gradlew test jacocoTestReport
- ./gradlew -Pcoverage testFullDebugUnitTest jacocoTestFullDebugUnitTestReport
after_success:
- bash <(curl -s https://codecov.io/bash)
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'
ext {
supportLibraryVersion = "27.0.2"
supportLibraryVersion = "27.1.0"
ormLiteVersion = "4.46"
powermockVersion = "1.7.3"
dexmakerVersion = "1.2"
butterknifeVersion = "8.8.1"
}
repositories {
maven { url 'https://maven.fabric.io/public' }
jcenter { url "https://jcenter.bintray.com/" }
}
def generateGitBuild = { ->
@ -47,19 +49,24 @@ def generateGitBuild = { ->
return stringBuilder.toString()
}
tasks.matching {it instanceof Test}.all {
testLogging.events = ["failed", "skipped", "started"]
testLogging.exceptionFormat = "full"
}
android {
compileSdkVersion 27
buildToolsVersion "${supportLibraryVersion}"
defaultConfig {
applicationId "info.nightscout.androidaps"
minSdkVersion 21
targetSdkVersion 23
targetSdkVersion 25
multiDexEnabled true
versionCode 1500
version "1.59-dev"
version "1.60e-dev"
buildConfigField "String", "VERSION", '"' + version + '"'
buildConfigField "String", "BUILDVERSION", generateGitBuild()
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
ndk {
moduleName "BleCommandUtil"
@ -69,7 +76,7 @@ android {
// TODO remove once wear dependency com.google.android.gms:play-services-wearable:7.3.0
// has been upgraded (requiring significant code changes), which currently fails release
// build with a deprecation warning
//abortOnError false
abortOnError false
// (disabled entirely to avoid reports on the error, which would still be displayed
// and it's easy to overlook that it's ignored)
checkReleaseBuilds false
@ -82,7 +89,7 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
testCoverageEnabled true
testCoverageEnabled (project.hasProperty('coverage') ? true : false)
}
}
productFlavors {
@ -97,21 +104,6 @@ android {
buildConfigField "boolean", "APS", "true"
buildConfigField "boolean", "PUMPDRIVERS", "true"
buildConfigField "boolean", "NSCLIENTOLNY", "false"
buildConfigField "boolean", "CLOSEDLOOP", "true"
buildConfigField "boolean", "G5UPLOADER", "false"
buildConfigField "boolean", "PUMPCONTROL", "false"
}
openloop {
dimension "standard"
resValue "string", "app_name", "AndroidAPS"
versionName version
manifestPlaceholders = [
appIcon: "@mipmap/blueowl"
]
buildConfigField "boolean", "APS", "true"
buildConfigField "boolean", "PUMPDRIVERS", "true"
buildConfigField "boolean", "NSCLIENTOLNY", "false"
buildConfigField "boolean", "CLOSEDLOOP", "false"
buildConfigField "boolean", "G5UPLOADER", "false"
buildConfigField "boolean", "PUMPCONTROL", "false"
}
@ -125,7 +117,6 @@ android {
buildConfigField "boolean", "APS", "false"
buildConfigField "boolean", "PUMPDRIVERS", "true"
buildConfigField "boolean", "NSCLIENTOLNY", "false"
buildConfigField "boolean", "CLOSEDLOOP", "false"
buildConfigField "boolean", "G5UPLOADER", "false"
buildConfigField "boolean", "PUMPCONTROL", "true"
}
@ -139,7 +130,6 @@ android {
buildConfigField "boolean", "APS", "false"
buildConfigField "boolean", "PUMPDRIVERS", "false"
buildConfigField "boolean", "NSCLIENTOLNY", "true"
buildConfigField "boolean", "CLOSEDLOOP", "false"
buildConfigField "boolean", "G5UPLOADER", "false"
buildConfigField "boolean", "PUMPCONTROL", "false"
}
@ -153,7 +143,6 @@ android {
buildConfigField "boolean", "APS", "false"
buildConfigField "boolean", "PUMPDRIVERS", "false"
buildConfigField "boolean", "NSCLIENTOLNY", "false"
buildConfigField "boolean", "CLOSEDLOOP", "false"
buildConfigField "boolean", "G5UPLOADER", "true"
buildConfigField "boolean", "PUMPCONTROL", "false"
}
@ -165,8 +154,9 @@ android {
testOptions {
unitTests.returnDefaultValues = true
unitTests.includeAndroidResources = true
}
}
}
allprojects {
repositories {
@ -177,75 +167,82 @@ allprojects {
}
}
configurations {
libs
}
dependencies {
wearApp project(':wear')
compile fileTree(include: ['*.jar'], dir: 'libs')
compile("com.crashlytics.sdk.android:crashlytics:2.6.7@aar") {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation("com.crashlytics.sdk.android:crashlytics:2.6.7@aar") {
transitive = true;
}
compile("com.crashlytics.sdk.android:answers:1.3.12@aar") {
implementation("com.crashlytics.sdk.android:answers:1.3.12@aar") {
transitive = true;
}
compile 'MilosKozak:danars-support-lib:master@zip'
libs "MilosKozak:danars-support-lib:master@zip"
compile "com.android.support:appcompat-v7:${supportLibraryVersion}"
compile "com.android.support:support-v4:${supportLibraryVersion}"
compile "com.android.support:cardview-v7:${supportLibraryVersion}"
compile "com.android.support:recyclerview-v7:${supportLibraryVersion}"
compile "com.android.support:gridlayout-v7:${supportLibraryVersion}"
compile "com.android.support:design:${supportLibraryVersion}"
compile "com.android.support:percent:${supportLibraryVersion}"
compile "com.wdullaer:materialdatetimepicker:2.3.0"
compile 'com.android.support.constraint:constraint-layout:1.0.2'
compile "com.squareup:otto:1.3.7"
compile "com.j256.ormlite:ormlite-core:${ormLiteVersion}"
compile "com.j256.ormlite:ormlite-android:${ormLiteVersion}"
compile("com.github.tony19:logback-android-classic:1.1.1-6") {
implementation "com.android.support:appcompat-v7:${supportLibraryVersion}"
implementation "com.android.support:support-v4:${supportLibraryVersion}"
implementation "com.android.support:cardview-v7:${supportLibraryVersion}"
implementation "com.android.support:recyclerview-v7:${supportLibraryVersion}"
implementation "com.android.support:gridlayout-v7:${supportLibraryVersion}"
implementation "com.android.support:design:${supportLibraryVersion}"
implementation "com.android.support:percent:${supportLibraryVersion}"
implementation "com.wdullaer:materialdatetimepicker:2.3.0"
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
implementation "com.squareup:otto:1.3.7"
implementation "com.j256.ormlite:ormlite-core:${ormLiteVersion}"
implementation "com.j256.ormlite:ormlite-android:${ormLiteVersion}"
implementation("com.github.tony19:logback-android-classic:1.1.1-6") {
exclude group: "com.google.android", module: "android"
}
compile "org.apache.commons:commons-lang3:3.6"
compile "org.slf4j:slf4j-api:1.7.12"
compile "com.jjoe64:graphview:4.0.1"
compile "com.joanzapata.iconify:android-iconify-fontawesome:2.1.1"
compile "com.google.android.gms:play-services-wearable:7.5.0"
compile(name: "android-edittext-validator-v1.3.4-mod", ext: "aar")
compile(name: "sightparser-release", ext: "aar")
implementation "org.apache.commons:commons-lang3:3.6"
implementation "org.slf4j:slf4j-api:1.7.12"
implementation "com.jjoe64:graphview:4.0.1"
implementation "com.joanzapata.iconify:android-iconify-fontawesome:2.1.1"
implementation "com.google.android.gms:play-services-wearable:7.5.0"
implementation(name: "android-edittext-validator-v1.3.4-mod", ext: "aar")
implementation(name: "sightparser-release", ext: "aar")
compile("com.google.android:flexbox:0.3.0") {
implementation("com.google.android:flexbox:0.3.0") {
exclude group: "com.android.support"
}
compile("io.socket:socket.io-client:0.8.3") {
implementation("io.socket:socket.io-client:0.8.3") {
// excluding org.json which is provided by Android
exclude group: "org.json", module: "json"
}
compile "com.google.code.gson:gson:2.7"
compile "com.google.guava:guava:20.0"
implementation "com.google.code.gson:gson:2.7"
implementation "com.google.guava:guava:20.0"
compile "net.danlew:android.joda:2.9.9.1"
implementation "net.danlew:android.joda:2.9.9.1"
implementation "uk.com.robust-it:cloning:1.9.9"
compile 'org.mozilla:rhino:1.7.7.2'
implementation 'org.mozilla:rhino:1.7.7.2'
api "com.jakewharton:butterknife:8.8.1"
annotationProcessor "com.jakewharton:butterknife-compiler:8.8.1"
implementation "com.jakewharton:butterknife:${butterknifeVersion}"
annotationProcessor "com.jakewharton:butterknife-compiler:${butterknifeVersion}"
testCompile "junit:junit:4.12"
testCompile "org.json:json:20140107"
testCompile "org.mockito:mockito-core:2.7.22"
testCompile "org.powermock:powermock-api-mockito2:${powermockVersion}"
testCompile "org.powermock:powermock-module-junit4-rule-agent:${powermockVersion}"
testCompile "org.powermock:powermock-module-junit4-rule:${powermockVersion}"
testCompile "org.powermock:powermock-module-junit4:${powermockVersion}"
testCompile "joda-time:joda-time:2.9.4.2"
testCompile "com.google.truth:truth:0.39"
testImplementation "junit:junit:4.12"
testImplementation "org.json:json:20140107"
testImplementation "org.mockito:mockito-core:2.7.22"
testImplementation "org.powermock:powermock-api-mockito2:${powermockVersion}"
testImplementation "org.powermock:powermock-module-junit4-rule-agent:${powermockVersion}"
testImplementation "org.powermock:powermock-module-junit4-rule:${powermockVersion}"
testImplementation "org.powermock:powermock-module-junit4:${powermockVersion}"
testImplementation "joda-time:joda-time:2.9.4.2"
testImplementation "com.google.truth:truth:0.39"
testImplementation 'org.robolectric:robolectric:3.8'
testImplementation "org.skyscreamer:jsonassert:1.5.0"
androidTestCompile "org.mockito:mockito-core:2.7.22"
androidTestCompile "com.google.dexmaker:dexmaker:${dexmakerVersion}"
androidTestCompile "com.google.dexmaker:dexmaker-mockito:${dexmakerVersion}"
androidTestImplementation "org.mockito:mockito-core:2.7.22"
androidTestImplementation "com.google.dexmaker:dexmaker:${dexmakerVersion}"
androidTestImplementation "com.google.dexmaker:dexmaker-mockito:${dexmakerVersion}"
}
task unzip(type: Copy) {
def zipPath = configurations.compile.find {it.name.startsWith("danars") }
def zipPath = configurations.libs.find {it.name.startsWith("danars") }
def zipFile = file(zipPath)
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.VIBRATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="com.google.android.permission.PROVIDE_BACKGROUND" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="sugar.free.sightremote.HISTORY_BROADCASTS" />
<uses-permission-sdk-23 android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
@ -47,7 +49,7 @@
android:theme="@style/Theme.AppCompat.Translucent" />
<activity android:name=".AgreementActivity" />
<activity android:name=".plugins.PumpDanaR.activities.DanaRHistoryActivity" />
<activity android:name=".plugins.PumpDanaR.activities.DanaRStatsActivity" />
<activity android:name=".TDDStatsActivity" />
<activity android:name=".plugins.Overview.activities.QuickWizardListActivity">
<intent-filter>
<action android:name="info.nightscout.androidaps.plugins.Overview.activities.QuickWizardListActivity" />
@ -111,6 +113,14 @@
</intent-filter>
</receiver>
<!-- Network change local receiver -->
<receiver android:name=".receivers.NetworkChangeReceiver">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
<action android:name="android.net.wifi.WIFI_STATE_CHANGED" />
</intent-filter>
</receiver>
<!-- Service processing incomming data -->
<service
android:name=".Services.DataService"

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>
<!-- Create a file appender for a log in the application's data directory -->
<property name="EXT_FILES_DIR" value="${EXT_DIR:-/sdcard}/Android/data/${PACKAGE_NAME}/files"/>
<property scope="context" name="EXT_FILES_DIR" value="${EXT_DIR:-/sdcard}/Android/data/${PACKAGE_NAME}/files"/>
<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${EXT_FILES_DIR}/AndroidAPS.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">

View file

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

View file

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

View file

@ -2,11 +2,18 @@ package info.nightscout.androidaps;
import android.app.Activity;
import android.os.Bundle;
import android.support.v4.content.res.ResourcesCompat;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.PopupMenu;
import android.text.SpannableString;
import android.text.style.ForegroundColorSpan;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.ImageButton;
import android.widget.SeekBar;
import android.widget.TextView;
import com.jjoe64.graphview.GraphView;
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.IobCobCalculator.IobCobCalculatorPlugin;
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventAutosensCalculationFinished;
import info.nightscout.androidaps.plugins.Overview.OverviewFragment;
import info.nightscout.androidaps.plugins.Overview.OverviewPlugin;
import info.nightscout.androidaps.plugins.Overview.graphData.GraphData;
import info.nightscout.utils.DateUtil;
@ -34,6 +42,13 @@ import info.nightscout.utils.SP;
public class HistoryBrowseActivity extends AppCompatActivity {
private static Logger log = LoggerFactory.getLogger(HistoryBrowseActivity.class);
ImageButton chartButton;
boolean showBasal = true;
boolean showIob, showCob, showDev, showRat, showDevslope;
@BindView(R.id.historybrowse_date)
Button buttonDate;
@BindView(R.id.historybrowse_zoom)
@ -44,19 +59,8 @@ public class HistoryBrowseActivity extends AppCompatActivity {
GraphView iobGraph;
@BindView(R.id.historybrowse_seekBar)
SeekBar seekBar;
@BindView(R.id.overview_showprediction)
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;
@BindView(R.id.historybrowse_noprofile)
TextView noProfile;
private int rangeToDisplay = 24; // for graph
private long start;
@ -85,6 +89,8 @@ public class HistoryBrowseActivity extends AppCompatActivity {
iobGraph.getGridLabelRenderer().setLabelVerticalWidth(50);
iobGraph.getGridLabelRenderer().setNumVerticalLabels(5);
setupChartMenu();
// set start of current day
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
@ -162,15 +168,6 @@ public class HistoryBrowseActivity extends AppCompatActivity {
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
public void onStatusEvent(final EventAutosensCalculationFinished e) {
Activity activity = this;
@ -188,6 +185,14 @@ public class HistoryBrowseActivity extends AppCompatActivity {
void updateGUI(String from) {
final PumpInterface pump = ConfigBuilderPlugin.getActivePump();
final Profile profile = MainApp.getConfigBuilder().getProfile();
if (profile == null) {
noProfile.setVisibility(View.VISIBLE);
return;
} else {
noProfile.setVisibility(View.GONE);
}
final String units = profile.getUnits();
double lowLineSetting = SP.getDouble("low_mark", Profile.fromMgdlToUnits(OverviewPlugin.bgTargetLow, units));
@ -247,7 +252,7 @@ public class HistoryBrowseActivity extends AppCompatActivity {
graphData.addTreatments(fromTime, toTime);
// add basal data
if (pump.getPumpDescription().isTempBasalCapable && showBasalsCheckbox.isChecked()) {
if (pump.getPumpDescription().isTempBasalCapable && showBasal) {
graphData.addBasals(fromTime, toTime, lowLine / graphData.maxY / 1.2d);
}
@ -262,25 +267,30 @@ public class HistoryBrowseActivity extends AppCompatActivity {
boolean useCobForScale = false;
boolean useDevForScale = false;
boolean useRatioForScale = false;
boolean useDevSlopeForScale = false;
if (showIobCheckbox.isChecked()) {
if (showIob) {
useIobForScale = true;
} else if (showCobCheckbox.isChecked()) {
} else if (showCob) {
useCobForScale = true;
} else if (showDeviationsCheckbox.isChecked()) {
} else if (showDev) {
useDevForScale = true;
} else if (showRatiosCheckbox.isChecked()) {
} else if (showRat) {
useRatioForScale = true;
} else if (showDevslope) {
useDevSlopeForScale = true;
}
if (showIobCheckbox.isChecked())
if (showIob)
secondGraphData.addIob(fromTime, toTime, useIobForScale, 1d);
if (showCobCheckbox.isChecked())
if (showCob)
secondGraphData.addCob(fromTime, toTime, useCobForScale, useCobForScale ? 1d : 0.5d);
if (showDeviationsCheckbox.isChecked())
if (showDev)
secondGraphData.addDeviations(fromTime, toTime, useDevForScale, 1d);
if (showRatiosCheckbox.isChecked())
if (showRat)
secondGraphData.addRatio(fromTime, toTime, useRatioForScale, 1d);
if (showDevslope)
secondGraphData.addDeviationSlope(fromTime, toTime, useDevSlopeForScale, 1d);
// **** NOW line ****
// set manual x bounds to have nice steps
@ -288,7 +298,7 @@ public class HistoryBrowseActivity extends AppCompatActivity {
secondGraphData.addNowLine(pointer);
// do GUI update
if (showIobCheckbox.isChecked() || showCobCheckbox.isChecked() || showDeviationsCheckbox.isChecked() || showRatiosCheckbox.isChecked()) {
if (showIob || showCob || showDev || showRat || showDevslope) {
iobGraph.setVisibility(View.VISIBLE);
} else {
iobGraph.setVisibility(View.GONE);
@ -297,4 +307,98 @@ public class HistoryBrowseActivity extends AppCompatActivity {
graphData.performUpdate();
secondGraphData.performUpdate();
}
private void setupChartMenu() {
chartButton = (ImageButton) findViewById(R.id.overview_chartMenuButton);
chartButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MenuItem item;
CharSequence title;
SpannableString s;
PopupMenu popup = new PopupMenu(v.getContext(), v);
item = popup.getMenu().add(Menu.NONE, OverviewFragment.CHARTTYPE.BAS.ordinal(), Menu.NONE, MainApp.gs(R.string.overview_show_basals));
title = item.getTitle();
s = new SpannableString(title);
s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.basal, null)), 0, s.length(), 0);
item.setTitle(s);
item.setCheckable(true);
item.setChecked(showBasal);
item = popup.getMenu().add(Menu.NONE, OverviewFragment.CHARTTYPE.IOB.ordinal(), Menu.NONE, MainApp.gs(R.string.overview_show_iob));
title = item.getTitle();
s = new SpannableString(title);
s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.iob, null)), 0, s.length(), 0);
item.setTitle(s);
item.setCheckable(true);
item.setChecked(showIob);
item = popup.getMenu().add(Menu.NONE, OverviewFragment.CHARTTYPE.COB.ordinal(), Menu.NONE, MainApp.gs(R.string.overview_show_cob));
title = item.getTitle();
s = new SpannableString(title);
s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.cob, null)), 0, s.length(), 0);
item.setTitle(s);
item.setCheckable(true);
item.setChecked(showCob);
item = popup.getMenu().add(Menu.NONE, OverviewFragment.CHARTTYPE.DEV.ordinal(), Menu.NONE, MainApp.gs(R.string.overview_show_deviations));
title = item.getTitle();
s = new SpannableString(title);
s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.deviations, null)), 0, s.length(), 0);
item.setTitle(s);
item.setCheckable(true);
item.setChecked(showDev);
item = popup.getMenu().add(Menu.NONE, OverviewFragment.CHARTTYPE.SEN.ordinal(), Menu.NONE, MainApp.gs(R.string.overview_show_sensitivity));
title = item.getTitle();
s = new SpannableString(title);
s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.ratio, null)), 0, s.length(), 0);
item.setTitle(s);
item.setCheckable(true);
item.setChecked(showRat);
if (MainApp.devBranch) {
item = popup.getMenu().add(Menu.NONE, OverviewFragment.CHARTTYPE.DEVSLOPE.ordinal(), Menu.NONE, "Deviation slope");
title = item.getTitle();
s = new SpannableString(title);
s.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(getResources(), R.color.devslopepos, null)), 0, s.length(), 0);
item.setTitle(s);
item.setCheckable(true);
item.setChecked(showDevslope);
}
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
if (item.getItemId() == OverviewFragment.CHARTTYPE.BAS.ordinal()) {
showBasal = !item.isChecked();
} else if (item.getItemId() == OverviewFragment.CHARTTYPE.IOB.ordinal()) {
showIob = !item.isChecked();
} else if (item.getItemId() == OverviewFragment.CHARTTYPE.COB.ordinal()) {
showCob = !item.isChecked();
} else if (item.getItemId() == OverviewFragment.CHARTTYPE.DEV.ordinal()) {
showDev = !item.isChecked();
} else if (item.getItemId() == OverviewFragment.CHARTTYPE.SEN.ordinal()) {
showRat = !item.isChecked();
} else if (item.getItemId() == OverviewFragment.CHARTTYPE.DEVSLOPE.ordinal()) {
showDevslope = !item.isChecked();
}
updateGUI("onGraphCheckboxesCheckedChanged");
return true;
}
});
chartButton.setImageResource(R.drawable.ic_arrow_drop_up_white_24dp);
popup.setOnDismissListener(new PopupMenu.OnDismissListener() {
@Override
public void onDismiss(PopupMenu menu) {
chartButton.setImageResource(R.drawable.ic_arrow_drop_down_white_24dp);
}
});
popup.show();
}
});
}
}

View file

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

View file

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

View file

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

View file

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

View file

@ -37,6 +37,8 @@ public interface Intents {
String EXTRA_SENSOR_BATTERY = "com.eveningoutpost.dexdrip.Extras.SensorBattery";
String EXTRA_TIMESTAMP = "com.eveningoutpost.dexdrip.Extras.Time";
String EXTRA_RAW = "com.eveningoutpost.dexdrip.Extras.Raw";
String XDRIP_DATA_SOURCE_DESCRIPTION = "com.eveningoutpost.dexdrip.Extras.SourceDesc";
String ACTION_NEW_BG_ESTIMATE_NO_DATA = "com.eveningoutpost.dexdrip.BgEstimateNoData";

View file

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

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 com.rits.cloning.Cloner;
import org.json.JSONObject;
import java.util.Date;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.db.Source;
import info.nightscout.androidaps.interfaces.InsulinInterface;
/**
* Created by mike on 29.05.2017.
@ -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 boolean isSMB = false; // is a Super-MicroBolus
public long deliverAt = 0; // SMB should be delivered within 1 min from this time
public String notes = null;
public DetailedBolusInfo copy() {
DetailedBolusInfo n = new DetailedBolusInfo();
n.date = date;
n.eventType = eventType;
n.insulin = insulin;
n.carbs = carbs;
n.source = source;
n.isValid = isValid;
n.glucose = glucose;
n.glucoseType = glucoseType;
n.carbTime = carbTime;
n.boluscalc = boluscalc;
n.context = context;
n.pumpId = pumpId;
n.isSMB = isSMB;
n.deliverAt = deliverAt;
n.notes = notes;
return n;
}
@Override
public String toString() {

View file

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

View file

@ -16,7 +16,11 @@ import info.nightscout.androidaps.interfaces.Interval;
public abstract class Intervals<T extends Interval> {
LongSparseArray<T> rawData = new LongSparseArray<T>(); // oldest at index 0
LongSparseArray<T> rawData; // oldest at index 0
public Intervals() {
rawData = new LongSparseArray<T>();
}
public synchronized Intervals reset() {
rawData = new LongSparseArray<T>();
@ -27,8 +31,7 @@ public abstract class Intervals<T extends Interval> {
/**
* The List must be sorted by `T.start()` in ascending order
*
* */
*/
public synchronized void add(List<T> list) {
for (T interval : list) {
rawData.put(interval.start(), interval);
@ -36,6 +39,10 @@ public abstract class Intervals<T extends Interval> {
merge();
}
public synchronized void add(T interval) {
rawData.put(interval.start(), interval);
merge();
}
public synchronized List<T> getList() {
@ -47,7 +54,7 @@ public abstract class Intervals<T extends Interval> {
public synchronized List<T> getReversedList() {
List<T> list = new ArrayList<>();
for (int i = rawData.size() -1; i>=0; i--)
for (int i = rawData.size() - 1; i >= 0; i--)
list.add(rawData.valueAt(i));
return list;
}
@ -86,5 +93,4 @@ public abstract class Intervals<T extends Interval> {
}
}

View file

@ -7,6 +7,16 @@ public class Iob {
public double iobContrib = 0d;
public double activityContrib = 0d;
public Iob iobContrib(double iobContrib) {
this.iobContrib = iobContrib;
return this;
}
public Iob activityContrib(double activityContrib) {
this.activityContrib = activityContrib;
return this;
}
public Iob plus(Iob iob) {
iobContrib += iob.iobContrib;
activityContrib += iob.activityContrib;

View file

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

View file

@ -11,4 +11,5 @@ public class MealData {
public double slopeFromMinDeviation = 999;
public long lastBolusTime;
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.v4.util.LongSparseArray;
import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.interfaces.Interval;
/**
@ -11,6 +13,14 @@ import info.nightscout.androidaps.interfaces.Interval;
public class NonOverlappingIntervals<T extends Interval> extends Intervals<T> {
public NonOverlappingIntervals() {
super();
}
public NonOverlappingIntervals (Intervals<T> other) {
rawData = other.rawData.clone();
}
protected synchronized void merge() {
for (int index = 0; index < rawData.size() - 1; index++) {
Interval i = rawData.valueAt(index);
@ -27,4 +37,5 @@ public class NonOverlappingIntervals<T extends Interval> extends Intervals<T> {
if (index >= 0) return rawData.valueAt(index);
return null;
}
}

View file

@ -11,18 +11,26 @@ import info.nightscout.androidaps.interfaces.Interval;
public class OverlappingIntervals<T extends Interval> extends Intervals<T> {
public OverlappingIntervals() {
super();
}
public OverlappingIntervals(Intervals<T> other) {
rawData = other.rawData.clone();
}
protected synchronized void merge() {
boolean needToCut = false;
long cutTime = 0;
for (int index = rawData.size()-1; index >= 0; index--) { //begin with newest
for (int index = rawData.size() - 1; index >= 0; index--) { //begin with newest
Interval cur = rawData.valueAt(index);
if (cur.isEndingEvent()){
if (cur.isEndingEvent()) {
needToCut = true;
cutTime = cur.start();
} else {
//event that is no EndingEvent might need to be stopped by an ending event
if(needToCut&&cur.end() > cutTime){
if (needToCut && cur.end() > cutTime) {
cur.cutEndTo(cutTime);
}
}
@ -31,9 +39,9 @@ public class OverlappingIntervals<T extends Interval> extends Intervals<T> {
@Nullable
public synchronized T getValueByInterval(long time) {
for (int index = rawData.size()-1; index >= 0; index--) { //begin with newest
for (int index = rawData.size() - 1; index >= 0; index--) { //begin with newest
T cur = rawData.valueAt(index);
if (cur.match(time)){
if (cur.match(time)) {
return cur;
}
}

View file

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

View file

@ -3,10 +3,14 @@ package info.nightscout.androidaps.data;
import android.support.annotation.Nullable;
import android.support.v4.util.LongSparseArray;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
import info.nightscout.androidaps.interfaces.Interval;
import info.nightscout.utils.DateUtil;
/**
* Created by mike on 09.05.2017.
@ -16,8 +20,17 @@ import info.nightscout.androidaps.interfaces.Interval;
// When no interval match the lastest record without duration is used
public class ProfileIntervals<T extends Interval> {
private static Logger log = LoggerFactory.getLogger(ProfileIntervals.class);
private LongSparseArray<T> rawData = new LongSparseArray<>(); // oldest at index 0
private LongSparseArray<T> rawData; // oldest at index 0
public ProfileIntervals () {
rawData = new LongSparseArray<>();
}
public ProfileIntervals (ProfileIntervals<T> other) {
rawData = other.rawData.clone();
}
public synchronized ProfileIntervals reset() {
rawData = new LongSparseArray<>();
@ -25,9 +38,11 @@ public class ProfileIntervals<T extends Interval> {
}
public synchronized void add(T newInterval) {
if (newInterval.isValid()) {
rawData.put(newInterval.start(), newInterval);
merge();
}
}
public synchronized void add(List<T> list) {
for (T interval : list) {
@ -51,6 +66,13 @@ public class ProfileIntervals<T extends Interval> {
public synchronized Interval getValueToTime(long time) {
int index = binarySearch(time);
if (index >= 0) return rawData.valueAt(index);
// if we request data older than first record, use oldest with zero duration instead
for (index = 0; index < rawData.size(); index++) {
if (rawData.valueAt(index).durationInMsec() == 0) {
//log.debug("Requested profile for time: " + DateUtil.dateAndTimeString(time) + ". Providing oldest record: " + rawData.valueAt(0).toString());
return rawData.valueAt(index);
}
}
return null;
}
@ -107,4 +129,9 @@ public class ProfileIntervals<T extends Interval> {
public synchronized T getReversed(int index) {
return rawData.valueAt(size() - 1 - index);
}
@Override
public String toString() {
return rawData.toString();
}
}

View file

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

View file

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

View file

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

View file

@ -195,8 +195,7 @@ public class BgReading implements DataPointWithLabelInterface {
@Override
public float getSize() {
boolean isTablet = MainApp.sResources.getBoolean(R.bool.isTablet);
return isTablet ? 8 : 5;
return 1;
}
@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);
}
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() {
return "CareportalEvent{" +
"date= " + date +
@ -259,4 +267,5 @@ public class CareportalEvent implements DataPointWithLabelInterface {
public int getSecondColor() {
return 0;
}
}

View file

@ -8,7 +8,6 @@ import android.support.annotation.Nullable;
import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper;
import com.j256.ormlite.dao.CloseableIterator;
import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.dao.DaoManager;
import com.j256.ormlite.stmt.PreparedQuery;
import com.j256.ormlite.stmt.QueryBuilder;
import com.j256.ormlite.stmt.Where;
@ -31,7 +30,6 @@ import java.util.concurrent.TimeUnit;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.ProfileStore;
import info.nightscout.androidaps.events.EventCareportalEventChange;
@ -44,21 +42,19 @@ import info.nightscout.androidaps.events.EventReloadTempBasalData;
import info.nightscout.androidaps.events.EventReloadTreatmentData;
import info.nightscout.androidaps.events.EventTempBasalChange;
import info.nightscout.androidaps.events.EventTempTargetChange;
import info.nightscout.androidaps.events.EventTreatmentChange;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventNewHistoryData;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
import info.nightscout.androidaps.plugins.PumpDanaR.activities.DanaRNSHistorySync;
import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes;
import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.JsonHelper;
import info.nightscout.utils.NSUpload;
import info.nightscout.utils.PercentageSplitter;
import info.nightscout.utils.ToastUtils;
/**
* This Helper contains all resource to provide a central DB management functionality. Only methods handling
* data-structure (and not the DB content) should be contained in here (meaning DDL and not SQL).
*
* <p>
* This class can safely be called from Services, but should not call Services to avoid circular dependencies.
* One major issue with this (right now) are the scheduled events, which are put into the service. Therefor all
* direct calls to the corresponding methods (eg. resetDatabases) should be done by a central service.
@ -71,22 +67,19 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
public static final String DATABASE_TEMPORARYBASALS = "TemporaryBasals";
public static final String DATABASE_EXTENDEDBOLUSES = "ExtendedBoluses";
public static final String DATABASE_TEMPTARGETS = "TempTargets";
public static final String DATABASE_TREATMENTS = "Treatments";
public static final String DATABASE_DANARHISTORY = "DanaRHistory";
public static final String DATABASE_DBREQUESTS = "DBRequests";
public static final String DATABASE_CAREPORTALEVENTS = "CareportalEvents";
public static final String DATABASE_PROFILESWITCHES = "ProfileSwitches";
public static final String DATABASE_TDDS = "TDDs";
private static final int DATABASE_VERSION = 8;
private static Long earliestDataChange = null;
public static Long earliestDataChange = null;
private static final ScheduledExecutorService bgWorker = Executors.newSingleThreadScheduledExecutor();
private static ScheduledFuture<?> scheduledBgPost = null;
private static final ScheduledExecutorService treatmentsWorker = Executors.newSingleThreadScheduledExecutor();
private static ScheduledFuture<?> scheduledTratmentPost = null;
private static final ScheduledExecutorService tempBasalsWorker = Executors.newSingleThreadScheduledExecutor();
private static ScheduledFuture<?> scheduledTemBasalsPost = null;
@ -116,7 +109,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
try {
log.info("onCreate");
TableUtils.createTableIfNotExists(connectionSource, TempTarget.class);
TableUtils.createTableIfNotExists(connectionSource, Treatment.class);
TableUtils.createTableIfNotExists(connectionSource, BgReading.class);
TableUtils.createTableIfNotExists(connectionSource, DanaRHistoryRecord.class);
TableUtils.createTableIfNotExists(connectionSource, DbRequest.class);
@ -124,6 +116,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
TableUtils.createTableIfNotExists(connectionSource, ExtendedBolus.class);
TableUtils.createTableIfNotExists(connectionSource, CareportalEvent.class);
TableUtils.createTableIfNotExists(connectionSource, ProfileSwitch.class);
TableUtils.createTableIfNotExists(connectionSource, TDD.class);
} catch (SQLException e) {
log.error("Can't create database", e);
throw new RuntimeException(e);
@ -138,12 +131,9 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
if (oldVersion == 7 && newVersion == 8) {
log.debug("Upgrading database from v7 to v8");
TableUtils.dropTable(connectionSource, Treatment.class, true);
TableUtils.createTableIfNotExists(connectionSource, Treatment.class);
} else {
log.info(DatabaseHelper.class.getName(), "onUpgrade");
TableUtils.dropTable(connectionSource, TempTarget.class, true);
TableUtils.dropTable(connectionSource, Treatment.class, true);
TableUtils.dropTable(connectionSource, BgReading.class, true);
TableUtils.dropTable(connectionSource, DanaRHistoryRecord.class, true);
TableUtils.dropTable(connectionSource, DbRequest.class, true);
@ -175,40 +165,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
super.close();
}
public void cleanUpDatabases() {
// TODO: call it somewhere
log.debug("Before BgReadings size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_BGREADINGS));
getWritableDatabase().delete(DATABASE_BGREADINGS, "date" + " < '" + (System.currentTimeMillis() - Constants.hoursToKeepInDatabase * 60 * 60 * 1000L) + "'", null);
log.debug("After BgReadings size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_BGREADINGS));
log.debug("Before TempTargets size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_TEMPTARGETS));
getWritableDatabase().delete(DATABASE_TEMPTARGETS, "date" + " < '" + (System.currentTimeMillis() - Constants.hoursToKeepInDatabase * 60 * 60 * 1000L) + "'", null);
log.debug("After TempTargets size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_TEMPTARGETS));
log.debug("Before Treatments size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_TREATMENTS));
getWritableDatabase().delete(DATABASE_TREATMENTS, "date" + " < '" + (System.currentTimeMillis() - Constants.hoursToKeepInDatabase * 60 * 60 * 1000L) + "'", null);
log.debug("After Treatments size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_TREATMENTS));
log.debug("Before History size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_DANARHISTORY));
getWritableDatabase().delete(DATABASE_DANARHISTORY, "recordDate" + " < '" + (System.currentTimeMillis() - Constants.daysToKeepHistoryInDatabase * 24 * 60 * 60 * 1000L) + "'", null);
log.debug("After History size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_DANARHISTORY));
log.debug("Before TemporaryBasals size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_TEMPORARYBASALS));
getWritableDatabase().delete(DATABASE_TEMPORARYBASALS, "recordDate" + " < '" + (System.currentTimeMillis() - Constants.daysToKeepHistoryInDatabase * 24 * 60 * 60 * 1000L) + "'", null);
log.debug("After TemporaryBasals size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_TEMPORARYBASALS));
log.debug("Before ExtendedBoluses size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_EXTENDEDBOLUSES));
getWritableDatabase().delete(DATABASE_EXTENDEDBOLUSES, "recordDate" + " < '" + (System.currentTimeMillis() - Constants.daysToKeepHistoryInDatabase * 24 * 60 * 60 * 1000L) + "'", null);
log.debug("After ExtendedBoluses size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_EXTENDEDBOLUSES));
log.debug("Before CareportalEvent size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_CAREPORTALEVENTS));
getWritableDatabase().delete(DATABASE_CAREPORTALEVENTS, "recordDate" + " < '" + (System.currentTimeMillis() - Constants.daysToKeepHistoryInDatabase * 24 * 60 * 60 * 1000L) + "'", null);
log.debug("After CareportalEvent size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_CAREPORTALEVENTS));
log.debug("Before ProfileSwitch size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_PROFILESWITCHES));
getWritableDatabase().delete(DATABASE_PROFILESWITCHES, "recordDate" + " < '" + (System.currentTimeMillis() - Constants.daysToKeepHistoryInDatabase * 24 * 60 * 60 * 1000L) + "'", null);
log.debug("After ProfileSwitch size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_PROFILESWITCHES));
}
public long size(String database) {
return DatabaseUtils.queryNumEntries(getReadableDatabase(), database);
@ -219,7 +175,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
public void resetDatabases() {
try {
TableUtils.dropTable(connectionSource, TempTarget.class, true);
TableUtils.dropTable(connectionSource, Treatment.class, true);
TableUtils.dropTable(connectionSource, BgReading.class, true);
TableUtils.dropTable(connectionSource, DanaRHistoryRecord.class, true);
TableUtils.dropTable(connectionSource, DbRequest.class, true);
@ -227,8 +182,8 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
TableUtils.dropTable(connectionSource, ExtendedBolus.class, true);
TableUtils.dropTable(connectionSource, CareportalEvent.class, true);
TableUtils.dropTable(connectionSource, ProfileSwitch.class, true);
TableUtils.dropTable(connectionSource, TDD.class, true);
TableUtils.createTableIfNotExists(connectionSource, TempTarget.class);
TableUtils.createTableIfNotExists(connectionSource, Treatment.class);
TableUtils.createTableIfNotExists(connectionSource, BgReading.class);
TableUtils.createTableIfNotExists(connectionSource, DanaRHistoryRecord.class);
TableUtils.createTableIfNotExists(connectionSource, DbRequest.class);
@ -236,6 +191,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
TableUtils.createTableIfNotExists(connectionSource, ExtendedBolus.class);
TableUtils.createTableIfNotExists(connectionSource, CareportalEvent.class);
TableUtils.createTableIfNotExists(connectionSource, ProfileSwitch.class);
TableUtils.createTableIfNotExists(connectionSource, TDD.class);
updateEarliestDataChange(0);
} catch (SQLException e) {
log.error("Unhandled exception", e);
@ -243,7 +199,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
VirtualPumpPlugin.setFakingStatus(true);
scheduleBgChange(null); // trigger refresh
scheduleTemporaryBasalChange();
scheduleTreatmentChange(null);
scheduleExtendedBolusChange();
scheduleTemporaryTargetChange();
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() {
try {
TableUtils.dropTable(connectionSource, TempTarget.class, true);
@ -323,6 +267,14 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
scheduleProfileSwitchChange();
}
public void resetTDDs() {
try {
TableUtils.dropTable(connectionSource, TDD.class, true);
TableUtils.createTableIfNotExists(connectionSource, TDD.class);
} catch (SQLException e) {
log.error("Unhandled exception", e);
}
}
// ------------------ getDao -------------------------------------------
@ -330,10 +282,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
return getDao(TempTarget.class);
}
private Dao<Treatment, Long> getDaoTreatments() throws SQLException {
return getDao(Treatment.class);
}
private Dao<BgReading, Long> getDaoBgReadings() throws SQLException {
return getDao(BgReading.class);
}
@ -342,6 +290,10 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
return getDao(DanaRHistoryRecord.class);
}
private Dao<TDD, String> getDaoTDD() throws SQLException {
return getDao(TDD.class);
}
private Dao<DbRequest, String> getDaoDbRequest() throws SQLException {
return getDao(DbRequest.class);
}
@ -362,7 +314,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
return getDao(ProfileSwitch.class);
}
public long roundDateToSec(long date) {
public static long roundDateToSec(long date) {
return date - date % 1000;
}
// ------------------- BgReading handling -----------------------
@ -396,7 +348,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
try {
getDaoBgReadings().update(bgReading);
} catch (SQLException e) {
e.printStackTrace();
log.error("Unhandled exception", e);
}
}
@ -495,6 +447,33 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
return new ArrayList<BgReading>();
}
// ------------------- TDD handling -----------------------
public void createOrUpdateTDD(TDD tdd) {
try {
Dao<TDD, String> dao = getDaoTDD();
dao.createOrUpdate(tdd);
} catch (SQLException e) {
ToastUtils.showToastInUiThread(MainApp.instance(), "createOrUpdate-Exception");
log.error("Unhandled exception", e);
}
}
public List<TDD> getTDDs() {
List<TDD> tddList;
try {
QueryBuilder<TDD, String> queryBuilder = getDaoTDD().queryBuilder();
queryBuilder.orderBy("date", false);
queryBuilder.limit(10L);
PreparedQuery<TDD> preparedQuery = queryBuilder.prepare();
tddList = getDaoTDD().query(preparedQuery);
} catch (SQLException e) {
log.error("Unhandled exception", e);
tddList = new ArrayList<>();
}
return tddList;
}
// ------------- DbRequests handling -------------------
public void create(DbRequest dbr) {
@ -531,7 +510,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
queryBuilder.limit(10L);
PreparedQuery<DbRequest> preparedQuery = queryBuilder.prepare();
List<DbRequest> dbList = getDaoDbRequest().query(preparedQuery);
log.error("deleteDbRequestbyMongoId query size: " + dbList.size());
for (DbRequest r : dbList) {
delete(r);
}
@ -559,146 +537,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
// -------------------- TREATMENT HANDLING -------------------
// return true if new record is created
public boolean createOrUpdate(Treatment treatment) {
try {
Treatment old;
treatment.date = roundDateToSec(treatment.date);
if (treatment.source == Source.PUMP) {
// check for changed from pump change in NS
QueryBuilder<Treatment, Long> queryBuilder = getDaoTreatments().queryBuilder();
Where where = queryBuilder.where();
where.eq("pumpId", treatment.pumpId);
PreparedQuery<Treatment> preparedQuery = queryBuilder.prepare();
List<Treatment> trList = getDaoTreatments().query(preparedQuery);
if (trList.size() > 0) {
// do nothing, pump history record cannot be changed
return false;
}
getDaoTreatments().create(treatment);
log.debug("TREATMENT: New record from: " + Source.getString(treatment.source) + " " + treatment.toString());
updateEarliestDataChange(treatment.date);
scheduleTreatmentChange(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) {
public static void updateEarliestDataChange(long newDate) {
if (earliestDataChange == null) {
earliestDataChange = newDate;
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 ---------------
public List<TempTarget> getTemptargetsDataFromTime(long mills, boolean ascending) {
@ -892,15 +664,15 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
public void createTemptargetFromJsonIfNotExists(JSONObject trJson) {
try {
String units = MainApp.getConfigBuilder().getProfileUnits();
TempTarget tempTarget = new TempTarget();
tempTarget.date = trJson.getLong("mills");
tempTarget.durationInMinutes = trJson.getInt("duration");
tempTarget.low = Profile.toMgdl(trJson.getDouble("targetBottom"), units);
tempTarget.high = Profile.toMgdl(trJson.getDouble("targetTop"), units);
tempTarget.reason = trJson.getString("reason");
tempTarget._id = trJson.getString("_id");
tempTarget.source = Source.NIGHTSCOUT;
String units = JsonHelper.safeGetString(trJson, "units", MainApp.getConfigBuilder().getProfileUnits());
TempTarget tempTarget = new TempTarget()
.date(trJson.getLong("mills"))
.duration(trJson.getInt("duration"))
.low(Profile.toMgdl(trJson.getDouble("targetBottom"), units))
.high(Profile.toMgdl(trJson.getDouble("targetTop"), units))
.reason(trJson.getString("reason"))
._id(trJson.getString("_id"))
.source(Source.NIGHTSCOUT);
createOrUpdate(tempTarget);
} catch (JSONException e) {
log.error("Unhandled exception", e);
@ -940,6 +712,12 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
public void createOrUpdate(DanaRHistoryRecord record) {
try {
getDaoDanaRHistory().createOrUpdate(record);
//If it is a TDD, store it for stats also.
if (record.recordCode == RecordTypes.RECORD_TYPE_DAILY) {
createOrUpdateTDD(new TDD(record.recordDate, record.recordDailyBolus, record.recordDailyBasal, 0));
}
} catch (SQLException e) {
log.error("Unhandled exception", e);
}
@ -1169,10 +947,10 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
}
createOrUpdate(extendedBolus);
} else {
TemporaryBasal tempBasal = new TemporaryBasal();
tempBasal.date = trJson.getLong("mills");
tempBasal.source = Source.NIGHTSCOUT;
tempBasal.pumpId = trJson.has("pumpId") ? trJson.getLong("pumpId") : 0;
TemporaryBasal tempBasal = new TemporaryBasal()
.date(trJson.getLong("mills"))
.source(Source.NIGHTSCOUT)
.pumpId(trJson.has("pumpId") ? trJson.getLong("pumpId") : 0);
if (trJson.has("duration")) {
tempBasal.durationInMinutes = trJson.getInt("duration");
}
@ -1376,37 +1154,10 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
}
*/
public void createExtendedBolusFromJsonIfNotExists(JSONObject trJson) {
try {
QueryBuilder<ExtendedBolus, Long> queryBuilder = null;
queryBuilder = getDaoExtendedBolus().queryBuilder();
Where where = queryBuilder.where();
where.eq("_id", trJson.getString("_id")).or().eq("date", trJson.getLong("mills"));
PreparedQuery<ExtendedBolus> preparedQuery = queryBuilder.prepare();
List<ExtendedBolus> list = getDaoExtendedBolus().query(preparedQuery);
ExtendedBolus extendedBolus;
if (list.size() == 0) {
extendedBolus = new ExtendedBolus();
extendedBolus.source = Source.NIGHTSCOUT;
if (Config.logIncommingData)
log.debug("Adding ExtendedBolus record to database: " + trJson.toString());
// Record does not exists. add
} else if (list.size() == 1) {
extendedBolus = list.get(0);
if (Config.logIncommingData)
log.debug("Updating ExtendedBolus record in database: " + trJson.toString());
} else {
log.error("Something went wrong");
return;
}
extendedBolus.date = trJson.getLong("mills");
extendedBolus.durationInMinutes = trJson.has("duration") ? trJson.getInt("duration") : 0;
extendedBolus.insulin = trJson.getDouble("relative");
extendedBolus._id = trJson.getString("_id");
public void createExtendedBolusFromJsonIfNotExists(JSONObject json) {
ExtendedBolus extendedBolus = ExtendedBolus.createFromJson(json);
if (extendedBolus != null)
createOrUpdate(extendedBolus);
} catch (SQLException | JSONException e) {
log.error("Unhandled exception", e);
}
}
private static void scheduleExtendedBolusChange() {
@ -1452,6 +1203,15 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
scheduleCareportalEventChange();
}
public CareportalEvent getCareportalEventFromTimestamp(long timestamp) {
try {
return getDaoCareportalEvents().queryForId(timestamp);
} catch (SQLException e) {
log.error("Unhandled exception", e);
}
return null;
}
@Nullable
public CareportalEvent getLastCareportalEvent(String event) {
try {
@ -1505,7 +1265,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
public void deleteCareportalEventById(String _id) {
try {
QueryBuilder<CareportalEvent, Long> queryBuilder = null;
QueryBuilder<CareportalEvent, Long> queryBuilder;
queryBuilder = getDaoCareportalEvents().queryBuilder();
Where where = queryBuilder.where();
where.eq("_id", _id);
@ -1528,7 +1288,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
public void createCareportalEventFromJsonIfNotExists(JSONObject trJson) {
try {
QueryBuilder<CareportalEvent, Long> queryBuilder = null;
QueryBuilder<CareportalEvent, Long> queryBuilder;
queryBuilder = getDaoCareportalEvents().queryBuilder();
Where where = queryBuilder.where();
where.eq("_id", trJson.getString("_id")).or().eq("date", trJson.getLong("mills"));
@ -1585,14 +1345,14 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
List<ProfileSwitch> profileSwitches;
QueryBuilder<ProfileSwitch, Long> queryBuilder = daoProfileSwitch.queryBuilder();
queryBuilder.orderBy("date", ascending);
queryBuilder.limit(20L);
queryBuilder.limit(100L);
PreparedQuery<ProfileSwitch> preparedQuery = queryBuilder.prepare();
profileSwitches = daoProfileSwitch.query(preparedQuery);
return profileSwitches;
} catch (SQLException e) {
log.error("Unhandled exception", e);
}
return new ArrayList<ProfileSwitch>();
return new ArrayList<>();
}
public boolean createOrUpdate(ProfileSwitch profileSwitch) {
@ -1709,7 +1469,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
if (trJson.has("profileJson"))
profileSwitch.profileJson = trJson.getString("profileJson");
else {
ProfileStore store = ConfigBuilderPlugin.getActiveProfileInterface().getProfile();
ProfileStore store = MainApp.getConfigBuilder().getActiveProfileInterface().getProfile();
Profile profile = store.getSpecificProfile(profileSwitch.profileName);
if (profile != null) {
profileSwitch.profileJson = profile.getData().toString();

View file

@ -9,24 +9,25 @@ import android.graphics.Color;
import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Date;
import java.util.Objects;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.data.Iob;
import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.interfaces.InsulinInterface;
import info.nightscout.androidaps.interfaces.Interval;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Overview.graphExtensions.DataPointWithLabelInterface;
import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLabelGraphSeries;
import info.nightscout.androidaps.plugins.Treatments.Treatment;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.JsonHelper;
import info.nightscout.utils.Round;
/**
@ -91,6 +92,16 @@ public class ExtendedBolus implements Interval, DataPointWithLabelInterface {
pumpId = t.pumpId;
}
public static ExtendedBolus createFromJson(JSONObject json) {
ExtendedBolus extendedBolus = new ExtendedBolus();
extendedBolus.source = Source.NIGHTSCOUT;
extendedBolus.date = JsonHelper.safeGetLong(json, "mills");
extendedBolus.durationInMinutes = JsonHelper.safeGetInt(json, "duration");
extendedBolus.insulin = JsonHelper.safeGetDouble(json, "relative") / 60 * extendedBolus.durationInMinutes;
extendedBolus._id = JsonHelper.safeGetString(json, "_id");
extendedBolus.pumpId = JsonHelper.safeGetLong(json, "pumpId");
return extendedBolus;
}
// -------- Interval interface ---------
Long cuttedEnd = null;

View file

@ -61,6 +61,31 @@ public class ProfileSwitch implements Interval, DataPointWithLabelInterface {
private Profile profile = null;
public ProfileSwitch date(long date) {
this.date = date;
return this;
}
public ProfileSwitch profileName(String profileName) {
this.profileName = profileName;
return this;
}
public ProfileSwitch profile(Profile profile) {
this.profile = profile;
return this;
}
public ProfileSwitch source(int source) {
this.source = source;
return this;
}
public ProfileSwitch duration(int duration) {
this.durationInMinutes = duration;
return this;
}
@Nullable
public Profile getProfileObject() {
if (profile == null)

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;
}
public TempTarget date(long date) {
this.date = date;
return this;
}
public TempTarget low(double low) {
this.low = low;
return this;
}
public TempTarget high(double high) {
this.high = high;
return this;
}
public TempTarget duration(int duration) {
this.durationInMinutes = duration;
return this;
}
public TempTarget reason(String reason) {
this.reason = reason;
return this;
}
public TempTarget _id(String _id) {
this._id = _id;
return this;
}
public TempTarget source(int source) {
this.source = source;
return this;
}
// -------- Interval interface ---------
Long cuttedEnd = null;

View file

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

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 info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.plugins.Treatments.Treatment;
/**
* Created by mike on 04.06.2016.

View file

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

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;
import info.nightscout.androidaps.plugins.Loop.APSResult;
import info.nightscout.androidaps.data.Profile;
/**
* Created by mike on 15.06.2016.
*/
public interface ConstraintsInterface {
boolean isLoopEnabled();
default Constraint<Boolean> isLoopInvokationAllowed(Constraint<Boolean> value) {
return value;
}
boolean isClosedModeEnabled();
default Constraint<Boolean> isClosedLoopAllowed(Constraint<Boolean> value) {
return value;
}
boolean isAutosensModeEnabled();
default Constraint<Boolean> isAutosensModeEnabled(Constraint<Boolean> value) {
return value;
}
boolean isAMAModeEnabled();
default Constraint<Boolean> isAMAModeEnabled(Constraint<Boolean> value) {
return value;
}
boolean isSMBModeEnabled();
default Constraint<Boolean> isSMBModeEnabled(Constraint<Boolean> value) {
return value;
}
Double applyBasalConstraints(Double absoluteRate);
default Constraint<Boolean> isAdvancedFilteringEnabled(Constraint<Boolean> value) {
return value;
}
Integer applyBasalConstraints(Integer percentRate);
default Constraint<Double> applyBasalConstraints(Constraint<Double> absoluteRate, Profile profile) {
return absoluteRate;
}
Double applyBolusConstraints(Double insulin);
default Constraint<Integer> applyBasalPercentConstraints(Constraint<Integer> percentRate, Profile profile) {
return percentRate;
}
Integer applyCarbsConstraints(Integer carbs);
default Constraint<Double> applyBolusConstraints(Constraint<Double> insulin) {
return insulin;
}
Double applyMaxIOBConstraints(Double maxIob);
default Constraint<Integer> applyCarbsConstraints(Constraint<Integer> carbs) {
return carbs;
}
default Constraint<Double> applyMaxIOBConstraints(Constraint<Double> maxIob) {
return maxIob;
};
}

View file

@ -1,9 +1,7 @@
package info.nightscout.androidaps.interfaces;
import java.util.Date;
import info.nightscout.androidaps.data.Iob;
import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.plugins.Treatments.Treatment;
/**
* Created by mike on 17.04.2017.

View file

@ -1,34 +1,165 @@
package info.nightscout.androidaps.interfaces;
import java.util.Date;
import android.os.SystemClock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
/**
* Created by mike on 09.06.2016.
*/
public interface PluginBase {
int GENERAL = 1;
int TREATMENT = 2;
int SENSITIVITY = 3;
int PROFILE = 4;
int APS = 5;
int PUMP = 6;
int CONSTRAINTS = 7;
int LOOP = 8;
int BGSOURCE = 9;
int INSULIN = 10;
int LAST = 11; // keep always highest number
public abstract class PluginBase {
private static Logger log = LoggerFactory.getLogger(PluginBase.class);
int getType();
String getFragmentClass();
public enum State {
NOT_INITIALIZED,
ENABLED,
DISABLED
}
String getName();
String getNameShort();
boolean isEnabled(int type);
boolean isVisibleInTabs(int type);
boolean canBeHidden(int type);
boolean hasFragment();
boolean showInList(int type);
void setFragmentEnabled(int type, boolean fragmentEnabled);
void setFragmentVisible(int type, boolean fragmentVisible);
int getPreferencesId();
private State state = State.NOT_INITIALIZED;
private boolean isFragmentVisible = false;
public PluginDescription pluginDescription;
// Specific plugin with more Interfaces
protected boolean isProfileInterfaceEnabled = false;
public PluginBase(PluginDescription pluginDescription) {
this.pluginDescription = pluginDescription;
}
// public PluginType getType() {
// return mainType;
// }
// public String getFragmentClass() {
// return fragmentClass;
// }
public String getName() {
if (pluginDescription.pluginName == -1)
return "UKNOWN";
else
return MainApp.gs(pluginDescription.pluginName);
}
public String getNameShort() {
if (pluginDescription.shortName == -1)
return getName();
String name = MainApp.gs(pluginDescription.shortName);
if (!name.trim().isEmpty()) //only if translation exists
return name;
// use long name as fallback
return getName();
}
public PluginType getType() {
return pluginDescription.mainType;
}
public int getPreferencesId() {
return pluginDescription.preferencesId;
}
public int getAdvancedPreferencesId() {
return pluginDescription.advancedPreferencesId;
}
public boolean isEnabled(PluginType type) {
if (pluginDescription.alwaysEnabled && type == pluginDescription.mainType)
return true;
if (pluginDescription.mainType == PluginType.CONSTRAINTS && type == PluginType.CONSTRAINTS)
return true;
if (type == pluginDescription.mainType)
return state == State.ENABLED && specialEnableCondition();
if (type == PluginType.CONSTRAINTS && pluginDescription.mainType == PluginType.PUMP && isEnabled(PluginType.PUMP))
return true;
if (type == PluginType.PROFILE && pluginDescription.mainType == PluginType.PUMP)
return isProfileInterfaceEnabled;
return false;
}
public boolean hasFragment() {
return pluginDescription.fragmentClass != null;
}
/**
* So far plugin can have it's main type + ConstraintInterface + ProfileInterface
* ConstraintInterface is enabled if main plugin is enabled
* ProfileInterface can be enabled only if main iterface is enable
*/
public void setPluginEnabled(PluginType type, boolean newState) {
if (type == pluginDescription.mainType) {
if (newState == true) { // enabling plugin
if (state != State.ENABLED) {
onStateChange(type, state, State.ENABLED);
state = State.ENABLED;
log.debug("Starting: " + getName());
onStart();
}
} else { // disabling plugin
if (state == State.ENABLED) {
onStateChange(type, state, State.ENABLED);
state = State.DISABLED;
onStop();
log.debug("Stopping: " + getName());
}
}
} else if (type == PluginType.PROFILE) {
isProfileInterfaceEnabled = newState;
}
}
public void setFragmentVisible(PluginType type, boolean fragmentVisible) {
if (type == pluginDescription.mainType) {
isFragmentVisible = fragmentVisible && specialEnableCondition();
}
}
public boolean isFragmentVisible() {
if (pluginDescription.alwayVisible)
return true;
if (pluginDescription.neverVisible)
return false;
return isFragmentVisible;
}
public boolean showInList(PluginType type) {
if (pluginDescription.mainType == type)
return pluginDescription.showInList && specialShowInListCondition();
if (type == PluginType.PROFILE && pluginDescription.mainType == PluginType.PUMP)
return isEnabled(PluginType.PUMP);
return false;
}
public boolean specialEnableCondition() {
return true;
}
public boolean specialShowInListCondition() {
return true;
}
protected void onStart() {
if (getType() == PluginType.PUMP) {
new Thread(() -> {
SystemClock.sleep(3000);
ConfigBuilderPlugin.getCommandQueue().readStatus("Pump driver changed.", null);
}).start();
}
}
protected void onStop() {
}
protected void onStateChange(PluginType type, State oldState, State newState) {
}
}

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

View file

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

View file

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

View file

@ -1,82 +1,22 @@
package info.nightscout.androidaps.plugins.Actions;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType;
/**
* Created by mike on 05.11.2016.
*/
public class ActionsPlugin implements PluginBase {
public class ActionsPlugin extends PluginBase {
private boolean fragmentEnabled = true;
private boolean fragmentVisible = true;
@Override
public int getType() {
return PluginBase.GENERAL;
public ActionsPlugin() {
super(new PluginDescription()
.mainType(PluginType.GENERAL)
.fragmentClass(ActionsFragment.class.getName())
.pluginName(R.string.actions)
.shortName(R.string.actions_shortname)
);
}
@Override
public String getFragmentClass() {
return ActionsFragment.class.getName();
}
@Override
public String getName() {
return MainApp.sResources.getString(R.string.actions);
}
@Override
public String getNameShort() {
String name = MainApp.sResources.getString(R.string.actions_shortname);
if (!name.trim().isEmpty()){
//only if translation exists
return name;
}
// use long name as fallback
return getName();
}
@Override
public boolean isEnabled(int type) {
return type == GENERAL && fragmentEnabled;
}
@Override
public boolean isVisibleInTabs(int type) {
return type == GENERAL && fragmentVisible;
}
@Override
public boolean canBeHidden(int type) {
return true;
}
@Override
public boolean hasFragment() {
return true;
}
@Override
public boolean showInList(int type) {
return true;
}
@Override
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
if (type == GENERAL) this.fragmentEnabled = fragmentEnabled;
}
@Override
public void setFragmentVisible(int type, boolean fragmentVisible) {
if (type == GENERAL) this.fragmentVisible = fragmentVisible;
}
@Override
public int getPreferencesId() {
return -1;
}
}

View file

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

View file

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

View file

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

View file

@ -2,6 +2,7 @@ package info.nightscout.androidaps.plugins.Careportal;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import android.view.LayoutInflater;
@ -12,7 +13,9 @@ import android.widget.TextView;
import com.squareup.otto.Subscribe;
import info.nightscout.androidaps.BuildConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
@ -21,11 +24,12 @@ import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.events.EventCareportalEventChange;
import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog;
import info.nightscout.androidaps.plugins.Common.SubscriberFragment;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSettingsStatus;
import info.nightscout.androidaps.plugins.Overview.OverviewFragment;
import info.nightscout.utils.FabricPrivacy;
public class CareportalFragment extends SubscriberFragment implements View.OnClickListener {
private static Logger log = LoggerFactory.getLogger(CareportalFragment.class);
TextView iage;
TextView cage;
@ -96,7 +100,7 @@ public class CareportalFragment extends SubscriberFragment implements View.OnCli
noProfileView = view.findViewById(R.id.profileview_noprofile);
butonsLayout = (LinearLayout) view.findViewById(R.id.careportal_buttons);
ProfileStore profileStore = ConfigBuilderPlugin.getActiveProfileInterface().getProfile();
ProfileStore profileStore = MainApp.getConfigBuilder().getActiveProfileInterface().getProfile();
if (profileStore == null) {
noProfileView.setVisibility(View.VISIBLE);
butonsLayout.setVisibility(View.GONE);
@ -208,26 +212,54 @@ public class CareportalFragment extends SubscriberFragment implements View.OnCli
public static void updateAge(Activity activity, final TextView sage, final TextView iage, final TextView cage, final TextView pbage) {
if (activity != null) {
activity.runOnUiThread(
new Runnable() {
@Override
public void run() {
() -> {
CareportalEvent careportalEvent;
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);
if (sage != null) {
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) {
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) {
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) {
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;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType;
public class CareportalPlugin implements PluginBase {
private boolean fragmentEnabled = true;
private boolean fragmentVisible = true;
public class CareportalPlugin extends PluginBase {
static CareportalPlugin careportalPlugin;
@ -19,70 +17,13 @@ public class CareportalPlugin implements PluginBase {
return careportalPlugin;
}
@Override
public int getType() {
return PluginBase.GENERAL;
}
@Override
public String getFragmentClass() {
return CareportalFragment.class.getName();
}
@Override
public String getName() {
return MainApp.sResources.getString(R.string.careportal);
}
@Override
public String getNameShort() {
String name = MainApp.sResources.getString(R.string.careportal_shortname);
if (!name.trim().isEmpty()){
//only if translation exists
return name;
}
// use long name as fallback
return getName();
}
@Override
public boolean isEnabled(int type) {
return type == GENERAL && fragmentEnabled;
}
@Override
public boolean isVisibleInTabs(int type) {
return type == GENERAL && fragmentVisible;
}
@Override
public boolean canBeHidden(int type) {
return true;
}
@Override
public boolean hasFragment() {
return true;
}
@Override
public boolean showInList(int type) {
return !Config.NSCLIENT && !Config.G5UPLOADER;
}
@Override
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
if (type == GENERAL) this.fragmentEnabled = fragmentEnabled;
}
@Override
public void setFragmentVisible(int type, boolean fragmentVisible) {
if (type == GENERAL) this.fragmentVisible = fragmentVisible;
}
@Override
public int getPreferencesId() {
return R.xml.pref_careportal;
public CareportalPlugin() {
super(new PluginDescription()
.mainType(PluginType.GENERAL)
.fragmentClass(CareportalFragment.class.getName())
.pluginName(R.string.careportal)
.shortName(R.string.careportal_shortname)
);
}
}

View file

@ -2,8 +2,6 @@ package info.nightscout.androidaps.plugins.Careportal.Dialogs;
import android.app.Activity;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog;
@ -16,7 +14,6 @@ import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.RadioButton;
@ -24,6 +21,7 @@ import android.widget.Spinner;
import android.widget.TextView;
import com.crashlytics.android.answers.CustomEvent;
import com.google.common.collect.Lists;
import com.wdullaer.materialdatetimepicker.date.DatePickerDialog;
import com.wdullaer.materialdatetimepicker.time.RadialPickerLayout;
import com.wdullaer.materialdatetimepicker.time.TimePickerDialog;
@ -50,13 +48,13 @@ import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.db.ProfileSwitch;
import info.nightscout.androidaps.db.Source;
import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.events.EventNewBasalProfile;
import info.nightscout.androidaps.plugins.Careportal.OptionsToShow;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Overview.Dialogs.ErrorHelperActivity;
import info.nightscout.androidaps.queue.Callback;
import info.nightscout.utils.FabricPrivacy;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.DefaultValueHelper;
import info.nightscout.utils.FabricPrivacy;
import info.nightscout.utils.HardLimits;
import info.nightscout.utils.JsonHelper;
import info.nightscout.utils.NSUpload;
import info.nightscout.utils.NumberPicker;
import info.nightscout.utils.SP;
@ -72,8 +70,8 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
private static String event;
Profile profile;
ProfileStore profileStore;
String units;
public ProfileStore profileStore;
String units = Constants.MGDL;
TextView eventTypeText;
LinearLayout layoutPercent;
@ -107,13 +105,19 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
Date eventTime;
private static Integer seconds = null;
public void setOptions(OptionsToShow options, int event) {
this.options = options;
this.event = MainApp.sResources.getString(event);
this.event = MainApp.gs(event);
}
public NewNSTreatmentDialog() {
super();
if (seconds == null) {
seconds = Double.valueOf(Math.random() * 59).intValue();
}
}
@Override
@ -132,7 +136,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (options == null) return null;
getDialog().setTitle(getString(options.eventName));
getDialog().setTitle(MainApp.gs(options.eventName));
setStyle(DialogFragment.STYLE_NORMAL, getTheme());
View view = inflater.inflate(R.layout.careportal_newnstreatment_dialog, container, false);
@ -168,11 +172,16 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
// profile
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;
units = profile != null ? profile.getUnits() : Constants.MGDL;
profileList = profileStore.getProfileList();
ArrayAdapter<CharSequence> adapter = new ArrayAdapter<CharSequence>(getContext(),
ArrayAdapter<CharSequence> adapter = new ArrayAdapter<>(getContext(),
R.layout.spinner_centered, profileList);
profileSpinner.setAdapter(adapter);
// 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)))
profileSpinner.setSelection(p);
}
final Double bg = Profile.fromMgdlToUnits(GlucoseStatus.getGlucoseStatusData() != null ? GlucoseStatus.getGlucoseStatusData().glucose : 0d, profile != null ? profile.getUnits() : Constants.MGDL);
}
final Double bg = Profile.fromMgdlToUnits(GlucoseStatus.getGlucoseStatusData() != null ? GlucoseStatus.getGlucoseStatusData().glucose : 0d, units);
// temp target
final ArrayList<CharSequence> reasonList = new ArrayList<CharSequence>();
reasonList.add(MainApp.sResources.getString(R.string.manual));
reasonList.add(MainApp.sResources.getString(R.string.eatingsoon));
reasonList.add(MainApp.sResources.getString(R.string.activity));
ArrayAdapter<CharSequence> adapterReason = new ArrayAdapter<CharSequence>(getContext(),
final List<String> reasonList = Lists.newArrayList(
MainApp.gs(R.string.manual),
MainApp.gs(R.string.eatingsoon),
MainApp.gs(R.string.activity),
MainApp.gs(R.string.hypo));
ArrayAdapter<String> adapterReason = new ArrayAdapter<>(getContext(),
R.layout.spinner_centered, reasonList);
reasonSpinner.setAdapter(adapterReason);
reasonSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
double defaultDuration = 0;
double defaultDuration;
double defaultTarget = 0;
if (profile != null) {
defaultTarget = bg.doubleValue();
defaultTarget = bg;
}
boolean erase = false;
if (MainApp.sResources.getString(R.string.eatingsoon).equals(reasonList.get(position))) {
defaultDuration = SP.getDouble(R.string.key_eatingsoon_duration, 0d);
defaultTarget = SP.getDouble(R.string.key_eatingsoon_target, 0d);
;
} else if (MainApp.sResources.getString(R.string.activity).equals(reasonList.get(position))) {
defaultDuration = SP.getDouble(R.string.key_activity_duration, 0d);
;
defaultTarget = SP.getDouble(R.string.key_activity_target, 0d);
;
String units = MainApp.getConfigBuilder().getProfileUnits();
DefaultValueHelper helper = new DefaultValueHelper();
if (MainApp.gs(R.string.eatingsoon).equals(reasonList.get(position))) {
defaultDuration = helper.determineEatingSoonTTDuration();
defaultTarget = helper.determineEatingSoonTT(units);
} else if (MainApp.gs(R.string.activity).equals(reasonList.get(position))) {
defaultDuration = helper.determineActivityTTDuration();
defaultTarget = helper.determineActivityTT(units);
} else if (MainApp.gs(R.string.hypo).equals(reasonList.get(position))) {
defaultDuration = helper.determineHypoTTDuration();
defaultTarget = helper.determineHypoTT(units);
} else {
defaultDuration = 0;
erase = true;
}
if (defaultTarget != 0 || erase) {
editTemptarget.setValue(defaultTarget);
}
@ -258,19 +271,16 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
editBg.setParams(bg, 0d, 500d, 1d, new DecimalFormat("0"), false, bgTextWatcher);
editTemptarget.setParams(bg, 0d, 500d, 1d, new DecimalFormat("0"), false);
}
sensorRadioButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
Double bg = Profile.fromMgdlToUnits(GlucoseStatus.getGlucoseStatusData() != null ? GlucoseStatus.getGlucoseStatusData().glucose : 0d, profile.getUnits());
editBg.setValue(bg);
}
sensorRadioButton.setOnCheckedChangeListener((buttonView, isChecked) -> {
Double bg1 = Profile.fromMgdlToUnits(GlucoseStatus.getGlucoseStatusData() != null ? GlucoseStatus.getGlucoseStatusData().glucose : 0d, profile.getUnits());
editBg.setValue(bg1);
});
Integer maxCarbs = MainApp.getConfigBuilder().applyCarbsConstraints(Constants.carbsOnlyForCheckLimit);
Integer maxCarbs = MainApp.getConstraintChecker().getMaxCarbsAllowed().value();
editCarbs = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_carbsinput);
editCarbs.setParams(0d, 0d, (double) maxCarbs, 1d, new DecimalFormat("0"), false);
Double maxInsulin = MainApp.getConfigBuilder().applyBolusConstraints(Constants.bolusOnlyForCheckLimit);
Double maxInsulin = MainApp.getConstraintChecker().getMaxBolusAllowed().value();
editInsulin = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_insulininput);
editInsulin.setParams(0d, 0d, maxInsulin, 0.05d, new DecimalFormat("0.00"), false);
@ -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.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.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.setParams(0d, (double) Constants.CPP_MIN_TIMESHIFT, (double) Constants.CPP_MAX_TIMESHIFT, 1d, new DecimalFormat("0"), false);
ProfileSwitch ps = MainApp.getConfigBuilder().getProfileSwitchFromHistory(System.currentTimeMillis());
ProfileSwitch ps = TreatmentsPlugin.getPlugin().getProfileSwitchFromHistory(DateUtil.now());
if (ps != null && ps.isCPP) {
final int percentage = ps.percentage;
final int timeshift = ps.timeshift;
reuseButton.setText(reuseButton.getText() + " " + percentage + "% " + timeshift + "h");
reuseButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
reuseButton.setOnClickListener(v -> {
editPercentage.setValue((double) percentage);
editTimeshift.setValue((double) timeshift);
}
});
}
if (ps == null) {
options.duration = false;
}
showOrHide((ViewGroup) view.findViewById(R.id.careportal_newnstreatment_eventtime_layout), options.date);
showOrHide((ViewGroup) view.findViewById(R.id.careportal_newnstreatment_bg_layout), options.bg);
@ -395,7 +409,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
tpd.show(context.getFragmentManager(), "Timepickerdialog");
break;
case R.id.ok:
createNSTreatment();
confirmNSTreatmentCreation();
dismiss();
break;
case R.id.cancel:
@ -432,7 +446,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
public void onTimeSet(RadialPickerLayout view, int hourOfDay, int minute, int second) {
eventTime.setHours(hourOfDay);
eventTime.setMinutes(minute);
eventTime.setSeconds(second);
eventTime.setSeconds(this.seconds++); // randomize seconds to prevent creating record of the same time, if user choose time manually
timeButton.setText(DateUtil.timeString(eventTime));
updateBGforDateTime();
}
@ -559,160 +573,152 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
String buildConfirmText(JSONObject data) {
String ret = "";
try {
if (data.has("eventType")) {
ret += getString(R.string.careportal_newnstreatment_eventtype);
ret += MainApp.gs(R.string.careportal_newnstreatment_eventtype);
ret += ": ";
ret += Translator.translate(data.getString("eventType"));
ret += Translator.translate(JsonHelper.safeGetString(data, "eventType", ""));
ret += "\n";
}
if (data.has("glucose")) {
ret += getString(R.string.treatments_wizard_bg_label);
ret += MainApp.gs(R.string.treatments_wizard_bg_label);
ret += ": ";
ret += data.get("glucose");
ret += JsonHelper.safeGetObject(data, "glucose", "");
ret += " " + units + "\n";
}
if (data.has("glucoseType")) {
ret += getString(R.string.careportal_newnstreatment_glucosetype);
ret += MainApp.gs(R.string.careportal_newnstreatment_glucosetype);
ret += ": ";
ret += Translator.translate(data.getString("glucoseType"));
ret += Translator.translate(JsonHelper.safeGetString(data, "glucoseType", ""));
ret += "\n";
}
if (data.has("carbs")) {
ret += getString(R.string.careportal_newnstreatment_carbs_label);
ret += MainApp.gs(R.string.careportal_newnstreatment_carbs_label);
ret += ": ";
ret += data.get("carbs");
ret += JsonHelper.safeGetObject(data, "carbs", "");
ret += " g\n";
}
if (data.has("insulin")) {
ret += getString(R.string.careportal_newnstreatment_insulin_label);
ret += MainApp.gs(R.string.careportal_newnstreatment_insulin_label);
ret += ": ";
ret += data.get("insulin");
ret += JsonHelper.safeGetObject(data, "insulin", "");
ret += " U\n";
}
if (data.has("duration")) {
ret += getString(R.string.careportal_newnstreatment_duration_label);
ret += MainApp.gs(R.string.careportal_newnstreatment_duration_label);
ret += ": ";
ret += data.get("duration");
ret += JsonHelper.safeGetObject(data, "duration", "");
ret += " min\n";
}
if (data.has("percent")) {
ret += getString(R.string.careportal_newnstreatment_percent_label);
ret += MainApp.gs(R.string.careportal_newnstreatment_percent_label);
ret += ": ";
ret += data.get("percent");
ret += JsonHelper.safeGetObject(data, "percent", "");
ret += " %\n";
}
if (data.has("absolute")) {
ret += getString(R.string.careportal_newnstreatment_absolute_label);
ret += MainApp.gs(R.string.careportal_newnstreatment_absolute_label);
ret += ": ";
ret += data.get("absolute");
ret += JsonHelper.safeGetObject(data, "absolute", "");
ret += " U/h\n";
}
if (data.has("preBolus")) {
ret += getString(R.string.careportal_newnstreatment_carbtime_label);
ret += MainApp.gs(R.string.careportal_newnstreatment_carbtime_label);
ret += ": ";
ret += data.get("preBolus");
ret += JsonHelper.safeGetObject(data, "preBolus", "");
ret += " min\n";
}
if (data.has("notes")) {
ret += getString(R.string.careportal_newnstreatment_notes_label);
ret += MainApp.gs(R.string.careportal_newnstreatment_notes_label);
ret += ": ";
ret += data.get("notes");
ret += JsonHelper.safeGetObject(data, "notes", "");
ret += "\n";
}
if (data.has("profile")) {
ret += getString(R.string.careportal_newnstreatment_profile_label);
ret += MainApp.gs(R.string.careportal_newnstreatment_profile_label);
ret += ": ";
ret += data.get("profile");
ret += JsonHelper.safeGetObject(data, "profile", "");
ret += "\n";
}
if (data.has("percentage")) {
ret += getString(R.string.careportal_newnstreatment_percentage_label);
ret += MainApp.gs(R.string.careportal_newnstreatment_percentage_label);
ret += ": ";
ret += data.get("percentage");
ret += JsonHelper.safeGetObject(data, "percentage", "");
ret += " %\n";
}
if (data.has("timeshift")) {
ret += getString(R.string.careportal_newnstreatment_timeshift_label);
ret += MainApp.gs(R.string.careportal_newnstreatment_timeshift_label);
ret += ": ";
ret += data.get("timeshift");
ret += JsonHelper.safeGetObject(data, "timeshift", "");
ret += " h\n";
}
if (data.has("targetBottom") && data.has("targetTop")) {
ret += getString(R.string.target_range);
ret += MainApp.gs(R.string.target_range);
ret += " ";
ret += data.get("targetBottom");
ret += JsonHelper.safeGetObject(data, "targetBottom", "");
ret += " - ";
ret += data.get("targetTop");
ret += JsonHelper.safeGetObject(data, "targetTop", "");
ret += "\n";
}
if (data.has("created_at")) {
ret += getString(R.string.careportal_newnstreatment_eventtime_label);
ret += MainApp.gs(R.string.careportal_newnstreatment_eventtime_label);
ret += ": ";
ret += eventTime.toLocaleString();
ret += "\n";
}
if (data.has("enteredBy")) {
ret += getString(R.string.careportal_newnstreatment_enteredby_title);
ret += MainApp.gs(R.string.careportal_newnstreatment_enteredby_title);
ret += ": ";
ret += data.get("enteredBy");
ret += JsonHelper.safeGetObject(data, "enteredBy", "");
ret += "\n";
}
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
return ret;
}
void createNSTreatment() {
void confirmNSTreatmentCreation() {
if (context != null) {
final JSONObject data = gatherData();
String confirmText = buildConfirmText(data);
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setTitle(getContext().getString(R.string.confirmation));
final String confirmText = buildConfirmText(data);
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(MainApp.gs(R.string.confirmation));
builder.setMessage(confirmText);
builder.setPositiveButton(getContext().getString(R.string.ok), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
builder.setPositiveButton(MainApp.gs(R.string.ok), (dialog, id) -> createNSTreatment(data));
builder.setNegativeButton(MainApp.gs(R.string.cancel), null);
builder.show();
}
}
public void createNSTreatment(JSONObject data) {
if (options.executeProfileSwitch) {
if (data.has("profile")) {
try {
doProfileSwitch(profileStore, data.getString("profile"), data.getInt("duration"), data.getInt("percentage"), data.getInt("timeshift"));
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
doProfileSwitch(profileStore, JsonHelper.safeGetString(data, "profile"), JsonHelper.safeGetInt(data, "duration"), JsonHelper.safeGetInt(data, "percentage"), JsonHelper.safeGetInt(data, "timeshift"));
}
} else if (options.executeTempTarget) {
try {
if ((data.has("targetBottom") && data.has("targetTop")) || (data.has("duration") && data.getInt("duration") == 0)) {
TempTarget tempTarget = new TempTarget();
tempTarget.date = eventTime.getTime();
tempTarget.durationInMinutes = data.getInt("duration");
tempTarget.reason = data.getString("reason");
tempTarget.source = Source.USER;
final int duration = JsonHelper.safeGetInt(data, "duration");
final double targetBottom = JsonHelper.safeGetDouble(data, "targetBottom");
final double targetTop = JsonHelper.safeGetDouble(data, "targetTop");
final String reason = JsonHelper.safeGetString(data, "reason", "");
if ((targetBottom != 0d && targetTop != 0d) || duration == 0) {
TempTarget tempTarget = new TempTarget()
.date(eventTime.getTime())
.duration(duration)
.reason(reason)
.source(Source.USER);
if (tempTarget.durationInMinutes != 0) {
tempTarget.low = Profile.toMgdl(data.getDouble("targetBottom"), profile.getUnits());
tempTarget.high = Profile.toMgdl(data.getDouble("targetTop"), profile.getUnits());
tempTarget.low(Profile.toMgdl(targetBottom, profile.getUnits()))
.high(Profile.toMgdl(targetTop, profile.getUnits()));
} else {
tempTarget.low = 0;
tempTarget.high = 0;
tempTarget.low(0).high(0);
}
log.debug("Creating new TempTarget db record: " + tempTarget.toString());
MainApp.getDbHelper().createOrUpdate(tempTarget);
NSUpload.uploadCareportalEntryToNS(data);
TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget);
FabricPrivacy.getInstance().logCustom(new CustomEvent("TempTarget"));
}
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
} else {
NSUpload.uploadCareportalEntryToNS(data);
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) {
ProfileSwitch profileSwitch = new ProfileSwitch();
@ -720,59 +726,29 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
profileSwitch.source = Source.USER;
profileSwitch.profileName = profileName;
profileSwitch.profileJson = profileStore.getSpecificProfile(profileName).getData().toString();
profileSwitch.profilePlugin = ConfigBuilderPlugin.getActiveProfileInterface().getClass().getName();
profileSwitch.profilePlugin = MainApp.getConfigBuilder().getActiveProfileInterface().getClass().getName();
profileSwitch.durationInMinutes = duration;
profileSwitch.isCPP = percentage != 100 || timeshift != 0;
profileSwitch.timeshift = timeshift;
profileSwitch.percentage = percentage;
MainApp.getConfigBuilder().addToHistoryProfileSwitch(profileSwitch);
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());
}
});
TreatmentsPlugin.getPlugin().addToHistoryProfileSwitch(profileSwitch);
FabricPrivacy.getInstance().logCustom(new CustomEvent("ProfileSwitch"));
}
public static void doProfileSwitch(final int duration, final int percentage, final int timeshift) {
ProfileSwitch profileSwitch = MainApp.getConfigBuilder().getProfileSwitchFromHistory(System.currentTimeMillis());
ProfileSwitch profileSwitch = TreatmentsPlugin.getPlugin().getProfileSwitchFromHistory(System.currentTimeMillis());
if (profileSwitch != null) {
profileSwitch = new ProfileSwitch();
profileSwitch.date = System.currentTimeMillis();
profileSwitch.source = Source.USER;
profileSwitch.profileName = MainApp.getConfigBuilder().getProfileName(System.currentTimeMillis(), false);
profileSwitch.profileJson = MainApp.getConfigBuilder().getProfile().getData().toString();
profileSwitch.profilePlugin = ConfigBuilderPlugin.getActiveProfileInterface().getClass().getName();
profileSwitch.profilePlugin = MainApp.getConfigBuilder().getActiveProfileInterface().getClass().getName();
profileSwitch.durationInMinutes = duration;
profileSwitch.isCPP = percentage != 100 || timeshift != 0;
profileSwitch.timeshift = timeshift;
profileSwitch.percentage = percentage;
MainApp.getConfigBuilder().addToHistoryProfileSwitch(profileSwitch);
ConfigBuilderPlugin.getCommandQueue().setProfile(profileSwitch.getProfileObject(), new Callback() {
@Override
public void run() {
if (!result.success) {
Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class);
i.putExtra("soundid", R.raw.boluserror);
i.putExtra("status", result.comment);
i.putExtra("title", MainApp.sResources.getString(R.string.failedupdatebasalprofile));
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
MainApp.instance().startActivity(i);
}
MainApp.bus().post(new EventNewBasalProfile());
}
});
TreatmentsPlugin.getPlugin().addToHistoryProfileSwitch(profileSwitch);
FabricPrivacy.getInstance().logCustom(new CustomEvent("ProfileSwitch"));
} else {
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.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.annotation.NonNull;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@ -17,11 +17,14 @@ import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView;
import com.crashlytics.android.answers.CustomEvent;
import java.util.ArrayList;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.PreferencesActivity;
import info.nightscout.androidaps.R;
@ -32,10 +35,12 @@ import info.nightscout.androidaps.interfaces.BgSourceInterface;
import info.nightscout.androidaps.interfaces.ConstraintsInterface;
import info.nightscout.androidaps.interfaces.InsulinInterface;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.interfaces.ProfileInterface;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.interfaces.SensitivityInterface;
import info.nightscout.androidaps.plugins.Insulin.InsulinFastactingPlugin;
import info.nightscout.androidaps.plugins.Common.SubscriberFragment;
import info.nightscout.androidaps.plugins.Insulin.InsulinOrefRapidActingPlugin;
import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin;
import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin;
import info.nightscout.androidaps.plugins.SensitivityOref0.SensitivityOref0Plugin;
@ -43,33 +48,46 @@ import info.nightscout.utils.FabricPrivacy;
import info.nightscout.utils.PasswordProtection;
public class ConfigBuilderFragment extends Fragment {
static ConfigBuilderPlugin configBuilderPlugin = new ConfigBuilderPlugin();
static public ConfigBuilderPlugin getPlugin() {
return configBuilderPlugin;
}
public class ConfigBuilderFragment extends SubscriberFragment {
@BindView(R.id.configbuilder_insulinlistview)
ListView insulinListView;
@BindView(R.id.configbuilder_sensitivitylistview)
ListView sensitivityListView;
@BindView(R.id.configbuilder_bgsourcelistview)
ListView bgsourceListView;
@BindView(R.id.configbuilder_bgsourcelabel)
TextView bgsourceLabel;
@BindView(R.id.configbuilder_pumplistview)
ListView pumpListView;
@BindView(R.id.configbuilder_pumplabel)
TextView pumpLabel;
@BindView(R.id.configbuilder_looplistview)
ListView loopListView;
@BindView(R.id.configbuilder_looplabel)
TextView loopLabel;
@BindView(R.id.configbuilder_treatmentslistview)
ListView treatmentsListView;
@BindView(R.id.configbuilder_treatmentslabel)
TextView treatmentsLabel;
@BindView(R.id.configbuilder_profilelistview)
ListView profileListView;
@BindView(R.id.configbuilder_profilelabel)
TextView profileLabel;
@BindView(R.id.configbuilder_apslistview)
ListView apsListView;
@BindView(R.id.configbuilder_apslabel)
TextView apsLabel;
@BindView(R.id.configbuilder_constraintslistview)
ListView constraintsListView;
@BindView(R.id.configbuilder_constraintslabel)
TextView constraintsLabel;
@BindView(R.id.configbuilder_generallistview)
ListView generalListView;
@BindView(R.id.configbuilder_mainlayout)
LinearLayout mainLayout;
@BindView(R.id.configbuilder_unlock)
Button unlock;
PluginCustomAdapter insulinDataAdapter = null;
@ -84,51 +102,17 @@ public class ConfigBuilderFragment extends Fragment {
PluginCustomAdapter generalDataAdapter = null;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
try {
View view = inflater.inflate(R.layout.configbuilder_fragment, container, false);
insulinListView = (ListView) view.findViewById(R.id.configbuilder_insulinlistview);
sensitivityListView = (ListView) view.findViewById(R.id.configbuilder_sensitivitylistview);
bgsourceListView = (ListView) view.findViewById(R.id.configbuilder_bgsourcelistview);
bgsourceLabel = (TextView) view.findViewById(R.id.configbuilder_bgsourcelabel);
pumpListView = (ListView) view.findViewById(R.id.configbuilder_pumplistview);
pumpLabel = (TextView) view.findViewById(R.id.configbuilder_pumplabel);
loopListView = (ListView) view.findViewById(R.id.configbuilder_looplistview);
loopLabel = (TextView) view.findViewById(R.id.configbuilder_looplabel);
treatmentsListView = (ListView) view.findViewById(R.id.configbuilder_treatmentslistview);
treatmentsLabel = (TextView) view.findViewById(R.id.configbuilder_treatmentslabel);
profileListView = (ListView) view.findViewById(R.id.configbuilder_profilelistview);
profileLabel = (TextView) view.findViewById(R.id.configbuilder_profilelabel);
apsListView = (ListView) view.findViewById(R.id.configbuilder_apslistview);
apsLabel = (TextView) view.findViewById(R.id.configbuilder_apslabel);
constraintsListView = (ListView) view.findViewById(R.id.configbuilder_constraintslistview);
constraintsLabel = (TextView) view.findViewById(R.id.configbuilder_constraintslabel);
generalListView = (ListView) view.findViewById(R.id.configbuilder_generallistview);
unbinder = ButterKnife.bind(this, view);
mainLayout = (LinearLayout) view.findViewById(R.id.configbuilder_mainlayout);
unlock = (Button) view.findViewById(R.id.configbuilder_unlock);
setViews();
if (PasswordProtection.isLocked("settings_password")) {
if (PasswordProtection.isLocked("settings_password"))
mainLayout.setVisibility(View.GONE);
unlock.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
PasswordProtection.QueryPassword(getContext(), R.string.settings_password, "settings_password", new Runnable() {
@Override
public void run() {
mainLayout.setVisibility(View.VISIBLE);
else
unlock.setVisibility(View.GONE);
}
}, null);
}
});
} else {
unlock.setVisibility(View.GONE);
}
return view;
} catch (Exception e) {
FabricPrivacy.logException(e);
@ -137,52 +121,64 @@ public class ConfigBuilderFragment extends Fragment {
return null;
}
void setViews() {
insulinDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInListByInterface(InsulinInterface.class, PluginBase.INSULIN), PluginBase.INSULIN);
@OnClick(R.id.configbuilder_unlock)
public void onClickUnlock() {
PasswordProtection.QueryPassword(getContext(), R.string.settings_password, "settings_password", () -> {
mainLayout.setVisibility(View.VISIBLE);
unlock.setVisibility(View.GONE);
}, null);
}
@Override
protected void updateGUI() {
insulinDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInListByInterface(InsulinInterface.class, PluginType.INSULIN), PluginType.INSULIN);
insulinListView.setAdapter(insulinDataAdapter);
setListViewHeightBasedOnChildren(insulinListView);
bgsourceDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInListByInterface(BgSourceInterface.class, PluginBase.BGSOURCE), PluginBase.BGSOURCE);
bgsourceDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInListByInterface(BgSourceInterface.class, PluginType.BGSOURCE), PluginType.BGSOURCE);
bgsourceListView.setAdapter(bgsourceDataAdapter);
if (MainApp.getSpecificPluginsVisibleInList(PluginBase.BGSOURCE).size() == 0)
if (MainApp.getSpecificPluginsVisibleInList(PluginType.BGSOURCE).size() == 0)
bgsourceLabel.setVisibility(View.GONE);
setListViewHeightBasedOnChildren(bgsourceListView);
pumpDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInList(PluginBase.PUMP), PluginBase.PUMP);
pumpDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInList(PluginType.PUMP), PluginType.PUMP);
pumpListView.setAdapter(pumpDataAdapter);
if (MainApp.getSpecificPluginsVisibleInList(PluginBase.PUMP).size() == 0)
if (MainApp.getSpecificPluginsVisibleInList(PluginType.PUMP).size() == 0 || Config.NSCLIENT || Config.G5UPLOADER) {
pumpLabel.setVisibility(View.GONE);
pumpListView.setVisibility(View.GONE);
}
setListViewHeightBasedOnChildren(pumpListView);
loopDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInList(PluginBase.LOOP), PluginBase.LOOP);
loopDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInList(PluginType.LOOP), PluginType.LOOP);
loopListView.setAdapter(loopDataAdapter);
setListViewHeightBasedOnChildren(loopListView);
if (MainApp.getSpecificPluginsVisibleInList(PluginBase.LOOP).size() == 0)
if (MainApp.getSpecificPluginsVisibleInList(PluginType.LOOP).size() == 0)
loopLabel.setVisibility(View.GONE);
treatmentDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInList(PluginBase.TREATMENT), PluginBase.TREATMENT);
treatmentDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInList(PluginType.TREATMENT), PluginType.TREATMENT);
treatmentsListView.setAdapter(treatmentDataAdapter);
setListViewHeightBasedOnChildren(treatmentsListView);
if (MainApp.getSpecificPluginsVisibleInList(PluginBase.TREATMENT).size() == 0)
if (MainApp.getSpecificPluginsVisibleInList(PluginType.TREATMENT).size() == 0)
treatmentsLabel.setVisibility(View.GONE);
profileDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInListByInterface(ProfileInterface.class, PluginBase.PROFILE), PluginBase.PROFILE);
profileDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInListByInterface(ProfileInterface.class, PluginType.PROFILE), PluginType.PROFILE);
profileListView.setAdapter(profileDataAdapter);
if (MainApp.getSpecificPluginsVisibleInList(PluginBase.PROFILE).size() == 0)
if (MainApp.getSpecificPluginsVisibleInList(PluginType.PROFILE).size() == 0)
profileLabel.setVisibility(View.GONE);
setListViewHeightBasedOnChildren(profileListView);
apsDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInList(PluginBase.APS), PluginBase.APS);
apsDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInList(PluginType.APS), PluginType.APS);
apsListView.setAdapter(apsDataAdapter);
setListViewHeightBasedOnChildren(apsListView);
if (MainApp.getSpecificPluginsVisibleInList(PluginBase.APS).size() == 0)
if (MainApp.getSpecificPluginsVisibleInList(PluginType.APS).size() == 0)
apsLabel.setVisibility(View.GONE);
sensivityDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInListByInterface(SensitivityInterface.class, PluginBase.SENSITIVITY), PluginBase.SENSITIVITY);
sensivityDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInListByInterface(SensitivityInterface.class, PluginType.SENSITIVITY), PluginType.SENSITIVITY);
sensitivityListView.setAdapter(sensivityDataAdapter);
setListViewHeightBasedOnChildren(sensitivityListView);
constraintsDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInListByInterface(ConstraintsInterface.class, PluginBase.CONSTRAINTS), PluginBase.CONSTRAINTS);
constraintsDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInListByInterface(ConstraintsInterface.class, PluginType.CONSTRAINTS), PluginType.CONSTRAINTS);
constraintsListView.setAdapter(constraintsDataAdapter);
setListViewHeightBasedOnChildren(constraintsListView);
if (MainApp.getSpecificPluginsVisibleInList(PluginBase.CONSTRAINTS).size() == 0)
if (MainApp.getSpecificPluginsVisibleInList(PluginType.CONSTRAINTS).size() == 0)
constraintsLabel.setVisibility(View.GONE);
generalDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInList(PluginBase.GENERAL), PluginBase.GENERAL);
generalDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInList(PluginType.GENERAL), PluginType.GENERAL);
generalListView.setAdapter(generalDataAdapter);
setListViewHeightBasedOnChildren(generalListView);
}
/*
@ -192,10 +188,10 @@ public class ConfigBuilderFragment extends Fragment {
private class PluginCustomAdapter extends ArrayAdapter<PluginBase> {
private ArrayList<PluginBase> pluginList;
final private int type;
final private PluginType type;
public PluginCustomAdapter(Context context, int textViewResourceId,
ArrayList<PluginBase> pluginList, int type) {
PluginCustomAdapter(Context context, int textViewResourceId,
ArrayList<PluginBase> pluginList, PluginType type) {
super(context, textViewResourceId, pluginList);
this.pluginList = new ArrayList<>();
this.pluginList.addAll(pluginList);
@ -209,10 +205,11 @@ public class ConfigBuilderFragment extends Fragment {
ImageView settings;
}
@NonNull
@Override
public View getView(int position, View view, ViewGroup parent) {
public View getView(int position, View view, @NonNull ViewGroup parent) {
PluginViewHolder holder = null;
PluginViewHolder holder;
PluginBase plugin = pluginList.get(position);
if (view == null) {
@ -231,60 +228,45 @@ public class ConfigBuilderFragment extends Fragment {
view.setTag(holder);
holder.checkboxEnabled.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
holder.checkboxEnabled.setOnClickListener(v -> {
CheckBox cb = (CheckBox) v;
PluginBase plugin = (PluginBase) cb.getTag();
plugin.setFragmentEnabled(type, cb.isChecked());
plugin.setFragmentVisible(type, cb.isChecked());
onEnabledCategoryChanged(plugin, type);
configBuilderPlugin.storeSettings();
PluginBase plugin1 = (PluginBase) cb.getTag();
plugin1.setPluginEnabled(type, cb.isChecked());
plugin1.setFragmentVisible(type, cb.isChecked());
onEnabledCategoryChanged(plugin1, type);
ConfigBuilderPlugin.getPlugin().storeSettings("CheckedCheckboxEnabled");
MainApp.bus().post(new EventRefreshGui());
MainApp.bus().post(new EventConfigBuilderChange());
getPlugin().logPluginStatus();
ConfigBuilderPlugin.getPlugin().logPluginStatus();
FabricPrivacy.getInstance().logCustom(new CustomEvent("ConfigurationChange"));
}
});
holder.checkboxVisible.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
holder.checkboxVisible.setOnClickListener(v -> {
CheckBox cb = (CheckBox) v;
PluginBase plugin = (PluginBase) cb.getTag();
plugin.setFragmentVisible(type, cb.isChecked());
configBuilderPlugin.storeSettings();
PluginBase plugin12 = (PluginBase) cb.getTag();
plugin12.setFragmentVisible(type, cb.isChecked());
ConfigBuilderPlugin.getPlugin().storeSettings("CheckedCheckboxVisible");
MainApp.bus().post(new EventRefreshGui());
getPlugin().logPluginStatus();
}
ConfigBuilderPlugin.getPlugin().logPluginStatus();
});
holder.settings.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
final PluginBase plugin = (PluginBase) v.getTag();
PasswordProtection.QueryPassword(getContext(), R.string.settings_password, "settings_password", new Runnable() {
@Override
public void run() {
holder.settings.setOnClickListener(v -> {
final PluginBase plugin13 = (PluginBase) v.getTag();
PasswordProtection.QueryPassword(getContext(), R.string.settings_password, "settings_password", () -> {
Intent i = new Intent(getContext(), PreferencesActivity.class);
i.putExtra("id", plugin.getPreferencesId());
i.putExtra("id", plugin13.getPreferencesId());
startActivity(i);
}
}, null);
}
});
holder.name.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
final PluginBase plugin = (PluginBase) v.getTag();
PasswordProtection.QueryPassword(getContext(), R.string.settings_password, "settings_password", new Runnable() {
@Override
public void run() {
holder.name.setOnLongClickListener(v -> {
final PluginBase plugin14 = (PluginBase) v.getTag();
PasswordProtection.QueryPassword(getContext(), R.string.settings_password, "settings_password", () -> {
Intent i = new Intent(getContext(), PreferencesActivity.class);
i.putExtra("id", plugin.getPreferencesId());
i.putExtra("id", plugin14.getPreferencesId());
startActivity(i);
}
}, null);
return false;
}
});
} else {
@ -293,15 +275,18 @@ public class ConfigBuilderFragment extends Fragment {
holder.name.setText(plugin.getName());
holder.checkboxEnabled.setChecked(plugin.isEnabled(type));
holder.checkboxVisible.setChecked(plugin.isVisibleInTabs(type));
holder.checkboxVisible.setChecked(plugin.isFragmentVisible());
holder.name.setTag(plugin);
holder.checkboxEnabled.setTag(plugin);
holder.checkboxVisible.setTag(plugin);
holder.settings.setTag(plugin);
if (!plugin.canBeHidden(type)) {
if (plugin.pluginDescription.alwaysEnabled) {
holder.checkboxEnabled.setEnabled(false);
}
if (plugin.pluginDescription.alwayVisible) {
holder.checkboxEnabled.setEnabled(false);
holder.checkboxVisible.setEnabled(false);
}
if (!plugin.isEnabled(type)) {
@ -313,19 +298,19 @@ public class ConfigBuilderFragment extends Fragment {
}
// Hide enabled control and force enabled plugin if there is only one plugin available
if (type == PluginBase.INSULIN || type == PluginBase.PUMP || type == PluginBase.TREATMENT || type == PluginBase.PROFILE || type == PluginBase.SENSITIVITY)
if (type == PluginType.INSULIN || type == PluginType.PUMP || type == PluginType.SENSITIVITY)
if (pluginList.size() < 2) {
holder.checkboxEnabled.setEnabled(false);
plugin.setFragmentEnabled(type, true);
getPlugin().storeSettings();
plugin.setPluginEnabled(type, true);
ConfigBuilderPlugin.getPlugin().storeSettings("ForceEnable");
}
// Constraints cannot be disabled
if (type == PluginBase.CONSTRAINTS)
if (type == PluginType.CONSTRAINTS)
holder.checkboxEnabled.setEnabled(false);
// Hide disabled profiles by default
if (type == PluginBase.PROFILE) {
if (type == PluginType.PROFILE) {
if (!plugin.isEnabled(type)) {
holder.checkboxVisible.setEnabled(false);
holder.checkboxVisible.setChecked(false);
@ -335,9 +320,9 @@ public class ConfigBuilderFragment extends Fragment {
}
// Disable profile control for pump profiles if pump is not enabled
if (type == PluginBase.PROFILE) {
if (type == PluginType.PROFILE) {
if (PumpInterface.class.isAssignableFrom(plugin.getClass())) {
if (!plugin.isEnabled(PluginBase.PUMP)) {
if (!plugin.isEnabled(PluginType.PUMP)) {
holder.checkboxEnabled.setEnabled(false);
holder.checkboxEnabled.setChecked(false);
}
@ -354,32 +339,32 @@ public class ConfigBuilderFragment extends Fragment {
}
void onEnabledCategoryChanged(PluginBase changedPlugin, int type) {
void onEnabledCategoryChanged(PluginBase changedPlugin, PluginType type) {
ArrayList<PluginBase> pluginsInCategory = null;
switch (type) {
// Multiple selection allowed
case PluginBase.GENERAL:
case PluginBase.CONSTRAINTS:
case PluginBase.LOOP:
case GENERAL:
case CONSTRAINTS:
case LOOP:
break;
// Single selection allowed
case PluginBase.INSULIN:
case INSULIN:
pluginsInCategory = MainApp.getSpecificPluginsListByInterface(InsulinInterface.class);
break;
case PluginBase.SENSITIVITY:
case SENSITIVITY:
pluginsInCategory = MainApp.getSpecificPluginsListByInterface(SensitivityInterface.class);
break;
case PluginBase.APS:
case APS:
pluginsInCategory = MainApp.getSpecificPluginsListByInterface(APSInterface.class);
break;
case PluginBase.PROFILE:
case PROFILE:
pluginsInCategory = MainApp.getSpecificPluginsListByInterface(ProfileInterface.class);
break;
case PluginBase.BGSOURCE:
case BGSOURCE:
pluginsInCategory = MainApp.getSpecificPluginsListByInterface(BgSourceInterface.class);
break;
case PluginBase.TREATMENT:
case PluginBase.PUMP:
case TREATMENT:
case PUMP:
pluginsInCategory = MainApp.getSpecificPluginsListByInterface(PumpInterface.class);
break;
}
@ -390,23 +375,23 @@ public class ConfigBuilderFragment extends Fragment {
if (p.getName().equals(changedPlugin.getName())) {
// this is new selected
} else {
p.setFragmentEnabled(type, false);
p.setPluginEnabled(type, false);
p.setFragmentVisible(type, false);
}
}
} else { // enable first plugin in list
if (type == PluginBase.PUMP)
MainApp.getSpecificPlugin(VirtualPumpPlugin.class).setFragmentEnabled(type, true);
else if (type == PluginBase.INSULIN)
MainApp.getSpecificPlugin(InsulinFastactingPlugin.class).setFragmentEnabled(type, true);
else if (type == PluginBase.SENSITIVITY)
MainApp.getSpecificPlugin(SensitivityOref0Plugin.class).setFragmentEnabled(type, true);
else if (type == PluginBase.PROFILE)
MainApp.getSpecificPlugin(NSProfilePlugin.class).setFragmentEnabled(type, true);
if (type == PluginType.PUMP)
VirtualPumpPlugin.getPlugin().setPluginEnabled(type, true);
else if (type == PluginType.INSULIN)
InsulinOrefRapidActingPlugin.getPlugin().setPluginEnabled(type, true);
else if (type == PluginType.SENSITIVITY)
SensitivityOref0Plugin.getPlugin().setPluginEnabled(type, true);
else if (type == PluginType.PROFILE)
NSProfilePlugin.getPlugin().setPluginEnabled(type, true);
else
pluginsInCategory.get(0).setFragmentEnabled(type, true);
pluginsInCategory.get(0).setPluginEnabled(type, true);
}
setViews();
updateGUI();
}
}

View file

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

View file

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

View file

@ -1,19 +1,22 @@
package info.nightscout.androidaps.plugins.ConstraintsSafety;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Objects;
import info.nightscout.androidaps.BuildConfig;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.ConstraintChecker;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.interfaces.BgSourceInterface;
import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.interfaces.ConstraintsInterface;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin;
import info.nightscout.androidaps.plugins.OpenAPSMA.OpenAPSMAPlugin;
import info.nightscout.androidaps.plugins.OpenAPSSMB.OpenAPSSMBPlugin;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.HardLimits;
import info.nightscout.utils.Round;
import info.nightscout.utils.SP;
@ -21,8 +24,7 @@ import info.nightscout.utils.SP;
/**
* Created by mike on 05.08.2016.
*/
public class SafetyPlugin implements PluginBase, ConstraintsInterface {
private static Logger log = LoggerFactory.getLogger(SafetyPlugin.class);
public class SafetyPlugin extends PluginBase implements ConstraintsInterface {
static SafetyPlugin plugin = null;
@ -32,201 +34,154 @@ public class SafetyPlugin implements PluginBase, ConstraintsInterface {
return plugin;
}
@Override
public String getFragmentClass() {
return null;
}
@Override
public int getType() {
return PluginBase.CONSTRAINTS;
}
@Override
public String getName() {
return MainApp.instance().getString(R.string.safety);
}
@Override
public String getNameShort() {
// use long name as fallback (no tabs)
return getName();
}
@Override
public boolean isEnabled(int type) {
return type == CONSTRAINTS;
}
@Override
public boolean isVisibleInTabs(int type) {
return false;
}
@Override
public boolean canBeHidden(int type) {
return true;
}
@Override
public boolean hasFragment() {
return false;
}
@Override
public boolean showInList(int type) {
return false;
}
@Override
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
}
@Override
public void setFragmentVisible(int type, boolean fragmentVisible) {
}
@Override
public int getPreferencesId() {
return R.xml.pref_safety;
}
@Override
public boolean isLoopEnabled() {
return ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable;
public SafetyPlugin() {
super(new PluginDescription()
.mainType(PluginType.CONSTRAINTS)
.neverVisible(true)
.alwaysEnabled(true)
.showInList(false)
.pluginName(R.string.safety)
.preferencesId(R.xml.pref_safety)
);
}
/**
* Constraints interface
**/
@Override
public boolean isClosedModeEnabled() {
public Constraint<Boolean> isLoopInvokationAllowed(Constraint<Boolean> value) {
if (!ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable)
value.set(false, MainApp.gs(R.string.pumpisnottempbasalcapable), this);
return value;
}
@Override
public Constraint<Boolean> isClosedLoopAllowed(Constraint<Boolean> value) {
String mode = SP.getString("aps_mode", "open");
return mode.equals("closed") && BuildConfig.CLOSEDLOOP;
if (!mode.equals("closed"))
value.set(false, MainApp.gs(R.string.closedmodedisabledinpreferences), this);
if (!MainApp.isEngineeringModeOrRelease()) {
if (value.value()) {
Notification n = new Notification(Notification.TOAST_ALARM, MainApp.gs(R.string.closed_loop_disabled_on_dev_branch), Notification.NORMAL);
MainApp.bus().post(new EventNewNotification(n));
}
value.set(false, MainApp.gs(R.string.closed_loop_disabled_on_dev_branch), this);
}
return value;
}
@Override
public boolean isAutosensModeEnabled() {
return true;
public Constraint<Boolean> isAutosensModeEnabled(Constraint<Boolean> value) {
boolean enabled = SP.getBoolean(R.string.key_openapsama_useautosens, false);
if (!enabled)
value.set(false, MainApp.gs(R.string.autosensdisabledinpreferences), this);
return value;
}
@Override
public boolean isAMAModeEnabled() {
return true;
public Constraint<Boolean> isSMBModeEnabled(Constraint<Boolean> value) {
boolean enabled = SP.getBoolean(R.string.key_use_smb, false);
if (!enabled)
value.set(false, MainApp.gs(R.string.smbdisabledinpreferences), this);
ConstraintChecker constraintChecker = MainApp.getConstraintChecker();
Constraint<Boolean> closedLoop = constraintChecker.isClosedLoopAllowed();
if (!closedLoop.value())
value.set(false, MainApp.gs(R.string.smbnotallowedinopenloopmode), this);
return value;
}
@Override
public boolean isSMBModeEnabled() {
return true;
public Constraint<Boolean> isAdvancedFilteringEnabled(Constraint<Boolean> value) {
BgSourceInterface bgSource = MainApp.getConfigBuilder().getActiveBgSource();
if (bgSource != null) {
if (!bgSource.advancedFilteringSupported())
value.set(false, MainApp.gs(R.string.smbalwaysdisabled), this);
}
return value;
}
@Override
public Double applyBasalConstraints(Double absoluteRate) {
Double origAbsoluteRate = absoluteRate;
Double maxBasal = SP.getDouble("openapsma_max_basal", 1d);
public Constraint<Double> applyBasalConstraints(Constraint<Double> absoluteRate, Profile profile) {
Profile profile = MainApp.getConfigBuilder().getProfile();
if (profile == null) return absoluteRate;
if (absoluteRate < 0) absoluteRate = 0d;
absoluteRate.setIfGreater(0d, String.format(MainApp.gs(R.string.limitingbasalratio), 0d, MainApp.gs(R.string.itmustbepositivevalue)), this);
double maxBasal = SP.getDouble(R.string.key_openapsma_max_basal, 1d);
absoluteRate.setIfSmaller(maxBasal, String.format(MainApp.gs(R.string.limitingbasalratio), maxBasal, MainApp.gs(R.string.maxvalueinpreferences)), this);
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 && origAbsoluteRate != Constants.basalAbsoluteOnlyForCheckLimit)
log.debug("Limiting rate " + origRate + " by maxBasal preference to " + absoluteRate + "U/h");
}
if (absoluteRate > maxBasalMult * profile.getBasal()) {
absoluteRate = Math.floor(maxBasalMult * profile.getBasal() * 100) / 100;
if (Config.logConstraintsChanges && origAbsoluteRate != Constants.basalAbsoluteOnlyForCheckLimit)
log.debug("Limiting rate " + origRate + " by maxBasalMult to " + absoluteRate + "U/h");
}
if (absoluteRate > profile.getMaxDailyBasal() * maxBasalFromDaily) {
absoluteRate = profile.getMaxDailyBasal() * maxBasalFromDaily;
if (Config.logConstraintsChanges && origAbsoluteRate != Constants.basalAbsoluteOnlyForCheckLimit)
log.debug("Limiting rate " + origRate + " by 3 * maxDailyBasal to " + absoluteRate + "U/h");
}
Double maxBasalMult = SP.getDouble(R.string.key_openapsama_current_basal_safety_multiplier, 4d);
double maxFromBasalMult = Math.floor(maxBasalMult * profile.getBasal() * 100) / 100;
absoluteRate.setIfSmaller(maxFromBasalMult, String.format(MainApp.gs(R.string.limitingbasalratio), maxFromBasalMult, MainApp.gs(R.string.maxbasalmultiplier)), this);
Double maxBasalFromDaily = SP.getDouble(R.string.key_openapsama_max_daily_safety_multiplier, 3d);
double maxFromDaily = Math.floor(profile.getMaxDailyBasal() * maxBasalFromDaily * 100) / 100;
absoluteRate.setIfSmaller(maxFromDaily, String.format(MainApp.gs(R.string.limitingbasalratio), maxFromDaily, MainApp.gs(R.string.maxdailybasalmultiplier)), this);
absoluteRate.setIfSmaller(HardLimits.maxBasal(), String.format(MainApp.gs(R.string.limitingbasalratio), HardLimits.maxBasal(), MainApp.gs(R.string.hardlimit)), this);
return absoluteRate;
}
@Override
public Integer applyBasalConstraints(Integer percentRate) {
Integer origPercentRate = percentRate;
Double maxBasal = SP.getDouble("openapsma_max_basal", 1d);
public Constraint<Integer> applyBasalPercentConstraints(Constraint<Integer> percentRate, Profile profile) {
Profile profile = MainApp.getConfigBuilder().getProfile();
if (profile == null) return percentRate;
Double currentBasal = profile.getBasal();
Double absoluteRate = currentBasal * ((double) percentRate.originalValue() / 100);
Double absoluteRate = currentBasal * ((double) percentRate / 100);
percentRate.addReason("Percent rate " + percentRate.originalValue() + "% recalculated to " + DecimalFormatter.to2Decimal(absoluteRate) + " U/h with current basal " + DecimalFormatter.to2Decimal(currentBasal) + " U/h", this);
if (Config.logConstraintsChanges)
log.debug("Percent rate " + percentRate + "% recalculated to " + absoluteRate + "U/h with current basal " + currentBasal + "U/h");
Constraint<Double> absoluteConstraint = new Constraint<>(absoluteRate);
applyBasalConstraints(absoluteConstraint, profile);
percentRate.copyReasons(absoluteConstraint);
if (absoluteRate < 0) absoluteRate = 0d;
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();
Integer percentRateAfterConst = Double.valueOf(absoluteConstraint.value() / currentBasal * 100).intValue();
if (percentRateAfterConst < 100)
percentRateAfterConst = Round.ceilTo((double) percentRateAfterConst, 10d).intValue();
else percentRateAfterConst = Round.floorTo((double) percentRateAfterConst, 10d).intValue();
if (Config.logConstraintsChanges && !Objects.equals(origPercentRate, Constants.basalPercentOnlyForCheckLimit))
log.debug("Recalculated percent rate " + percentRate + "% to " + percentRateAfterConst + "%");
return percentRateAfterConst;
percentRate.set(percentRateAfterConst, String.format(MainApp.gs(R.string.limitingpercentrate), percentRateAfterConst, MainApp.gs(R.string.pumplimit)), this);
return percentRate;
}
@Override
public Double applyBolusConstraints(Double insulin) {
try {
Double maxBolus = SP.getDouble("treatmentssafety_maxbolus", 3d);
public Constraint<Double> applyBolusConstraints(Constraint<Double> insulin) {
insulin.setIfGreater(0d, String.format(MainApp.gs(R.string.limitingbolus), 0d, MainApp.gs(R.string.itmustbepositivevalue)), this);
if (insulin < 0) insulin = 0d;
if (insulin > maxBolus) insulin = maxBolus;
} catch (Exception e) {
insulin = 0d;
}
if (insulin > HardLimits.maxBolus()) insulin = HardLimits.maxBolus();
Double maxBolus = SP.getDouble(R.string.key_treatmentssafety_maxbolus, 3d);
insulin.setIfSmaller(maxBolus, String.format(MainApp.gs(R.string.limitingbolus), maxBolus, MainApp.gs(R.string.maxvalueinpreferences)), this);
insulin.setIfSmaller(HardLimits.maxBolus(), String.format(MainApp.gs(R.string.limitingbolus), HardLimits.maxBolus(), MainApp.gs(R.string.hardlimit)), this);
return insulin;
}
@Override
public Integer applyCarbsConstraints(Integer carbs) {
try {
Integer maxCarbs = SP.getInt("treatmentssafety_maxcarbs", 48);
public Constraint<Integer> applyCarbsConstraints(Constraint<Integer> carbs) {
carbs.setIfGreater(0, String.format(MainApp.gs(R.string.limitingcarbs), 0, MainApp.gs(R.string.itmustbepositivevalue)), this);
Integer maxCarbs = SP.getInt(R.string.key_treatmentssafety_maxcarbs, 48);
carbs.setIfSmaller(maxCarbs, String.format(MainApp.gs(R.string.limitingcarbs), maxCarbs, MainApp.gs(R.string.maxvalueinpreferences)), this);
if (carbs < 0) carbs = 0;
if (carbs > maxCarbs) carbs = maxCarbs;
} catch (Exception e) {
carbs = 0;
}
return carbs;
}
@Override
public Double applyMaxIOBConstraints(Double maxIob) {
public Constraint<Double> applyMaxIOBConstraints(Constraint<Double> maxIob) {
double maxIobPref;
if (OpenAPSSMBPlugin.getPlugin().isEnabled(PluginType.APS))
maxIobPref = SP.getDouble(R.string.key_openapssmb_max_iob, 3d);
else
maxIobPref = SP.getDouble(R.string.key_openapsma_max_iob, 1.5d);
maxIob.setIfSmaller(maxIobPref, String.format(MainApp.gs(R.string.limitingiob), maxIobPref, MainApp.gs(R.string.maxvalueinpreferences)), this);
if (OpenAPSMAPlugin.getPlugin().isEnabled(PluginType.APS))
maxIob.setIfSmaller(HardLimits.maxIobAMA(), String.format(MainApp.gs(R.string.limitingiob), HardLimits.maxIobAMA(), MainApp.gs(R.string.hardlimit)), this);
if (OpenAPSAMAPlugin.getPlugin().isEnabled(PluginType.APS))
maxIob.setIfSmaller(HardLimits.maxIobAMA(), String.format(MainApp.gs(R.string.limitingiob), HardLimits.maxIobAMA(), MainApp.gs(R.string.hardlimit)), this);
if (OpenAPSSMBPlugin.getPlugin().isEnabled(PluginType.APS))
maxIob.setIfSmaller(HardLimits.maxIobSMB(), String.format(MainApp.gs(R.string.limitingiob), HardLimits.maxIobSMB(), MainApp.gs(R.string.hardlimit)), this);
return maxIob;
}

View file

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

View file

@ -1,90 +1,33 @@
package info.nightscout.androidaps.plugins.Food;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType;
/**
* Created by mike on 05.08.2016.
*/
public class FoodPlugin implements PluginBase {
private boolean fragmentEnabled = true;
private boolean fragmentVisible = false;
public class FoodPlugin extends PluginBase {
private static FoodPlugin plugin = null;
private FoodService service;
private FoodPlugin() {
this.service = new FoodService();
}
public static FoodPlugin getPlugin() {
if (plugin == null)
plugin = new FoodPlugin();
return plugin;
}
@Override
public String getFragmentClass() {
return FoodFragment.class.getName();
}
private FoodService service;
@Override
public int getType() {
return PluginBase.GENERAL;
}
@Override
public String getName() {
return MainApp.instance().getString(R.string.food);
}
@Override
public String getNameShort() {
// use long name as fallback (not visible in tabs)
return getName();
}
@Override
public boolean isEnabled(int type) {
return type == GENERAL && fragmentEnabled;
}
@Override
public boolean isVisibleInTabs(int type) {
return type == GENERAL && fragmentVisible;
}
@Override
public boolean canBeHidden(int type) {
return true;
}
@Override
public boolean hasFragment() {
return true;
}
@Override
public boolean showInList(int type) {
return true;
}
@Override
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
if (type == GENERAL) this.fragmentEnabled = fragmentEnabled;
}
@Override
public void setFragmentVisible(int type, boolean fragmentVisible) {
if (type == GENERAL) this.fragmentVisible = fragmentVisible;
}
@Override
public int getPreferencesId() {
return -1;
private FoodPlugin() {
super(new PluginDescription()
.mainType(PluginType.GENERAL)
.fragmentClass(FoodFragment.class.getName())
.pluginName(R.string.food)
.shortName(R.string.food_short)
);
this.service = new FoodService();
}
public FoodService getService() {

View file

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

View file

@ -12,7 +12,7 @@ import java.util.ArrayList;
import java.util.List;
import info.nightscout.androidaps.data.Iob;
import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.plugins.Treatments.Treatment;
import info.nightscout.androidaps.interfaces.InsulinInterface;
/**

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.R;
import info.nightscout.androidaps.data.Iob;
import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.plugins.Treatments.Treatment;
import info.nightscout.androidaps.interfaces.InsulinInterface;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
/**
* Created by adrian on 13.08.2017.
*/
public abstract class InsulinOrefBasePlugin implements PluginBase, InsulinInterface {
public abstract class InsulinOrefBasePlugin extends PluginBase implements InsulinInterface {
public static double MIN_DIA = 5;
long lastWarned = 0;
@Override
public int getType() {
return INSULIN;
}
@Override
public String getNameShort() {
return MainApp.sResources.getString(R.string.insulin_shortname);
}
@Override
public boolean canBeHidden(int type) {
return true;
}
@Override
public boolean hasFragment() {
return true;
}
@Override
public boolean showInList(int type) {
return true;
public InsulinOrefBasePlugin() {
super(new PluginDescription()
.mainType(PluginType.INSULIN)
.fragmentClass(InsulinFragment.class.getName())
.pluginName(R.string.fastactinginsulin)
.shortName(R.string.insulin_shortname)
);
}
public Bus getBus() {
@ -53,7 +39,7 @@ public abstract class InsulinOrefBasePlugin implements PluginBase, InsulinInterf
@Override
public double getDia() {
double dia = getUserDefinedDia();
if(dia >= MIN_DIA){
if (dia >= MIN_DIA) {
return dia;
} else {
sendShortDiaNotification(dia);
@ -62,7 +48,7 @@ public abstract class InsulinOrefBasePlugin implements PluginBase, InsulinInterf
}
void sendShortDiaNotification(double dia) {
if((System.currentTimeMillis() - lastWarned) > 60*1000) {
if ((System.currentTimeMillis() - lastWarned) > 60 * 1000) {
lastWarned = System.currentTimeMillis();
Notification notification = new Notification(Notification.SHORT_DIA, String.format(this.getNotificationPattern(), dia, MIN_DIA), Notification.URGENT);
this.getBus().post(new EventNewNotification(notification));
@ -92,7 +78,7 @@ public abstract class InsulinOrefBasePlugin implements PluginBase, InsulinInterf
long bolusTime = treatment.date;
double t = (time - bolusTime) / 1000d / 60d;
double td = getDia()*60; //getDIA() always >= MIN_DIA
double td = getDia() * 60; //getDIA() always >= MIN_DIA
double tp = peak;
// force the IOB to 0 if over DIA hours have passed
@ -111,7 +97,7 @@ public abstract class InsulinOrefBasePlugin implements PluginBase, InsulinInterf
public String getComment() {
String comment = commentStandardText();
double userDia = getUserDefinedDia();
if(userDia < MIN_DIA){
if (userDia < MIN_DIA) {
comment += "\n" + String.format(MainApp.sResources.getString(R.string.dia_too_short), userDia, MIN_DIA);
}
return comment;

View file

@ -10,9 +10,6 @@ import info.nightscout.utils.SP;
public class InsulinOrefFreePeakPlugin extends InsulinOrefBasePlugin {
private boolean fragmentEnabled = false;
private boolean fragmentVisible = false;
private static InsulinOrefFreePeakPlugin plugin = null;
public static InsulinOrefFreePeakPlugin getPlugin() {
@ -21,24 +18,20 @@ public class InsulinOrefFreePeakPlugin extends InsulinOrefBasePlugin {
return plugin;
}
public static final int DEFAULT_PEAK = 75;
private static final int DEFAULT_PEAK = 75;
private InsulinOrefFreePeakPlugin() {
super();
pluginDescription
.pluginName(R.string.free_peak_oref)
.preferencesId(R.xml.pref_insulinoreffreepeak);
}
@Override
public int getId() {
return OREF_FREE_PEAK;
}
@Override
public String getName() {
return MainApp.sResources.getString(R.string.free_peak_oref);
}
@Override
public String getFragmentClass() {
return InsulinFragment.class.getName();
}
@Override
public String getFriendlyName() {
return MainApp.sResources.getString(R.string.free_peak_oref);
}
@ -48,31 +41,6 @@ public class InsulinOrefFreePeakPlugin extends InsulinOrefBasePlugin {
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
int getPeak() {
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 {
private boolean fragmentEnabled = false;
private boolean fragmentVisible = false;
private static InsulinOrefRapidActingPlugin plugin = null;
public static InsulinOrefRapidActingPlugin getPlugin() {
@ -20,23 +17,19 @@ public class InsulinOrefRapidActingPlugin extends InsulinOrefBasePlugin {
return plugin;
}
public static final int PEAK = 75;
private static final int PEAK = 75;
private InsulinOrefRapidActingPlugin() {
super();
pluginDescription
.pluginName(R.string.rapid_acting_oref);
}
@Override
public int getId() {
return OREF_RAPID_ACTING;
}
@Override
public String getName() {
return MainApp.sResources.getString(R.string.rapid_acting_oref);
}
@Override
public String getFragmentClass() {
return InsulinFragment.class.getName();
}
@Override
public String getFriendlyName() {
return MainApp.sResources.getString(R.string.rapid_acting_oref);
@ -47,31 +40,6 @@ public class InsulinOrefRapidActingPlugin extends InsulinOrefBasePlugin {
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
int getPeak() {
return PEAK;

View file

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

View file

@ -7,22 +7,31 @@ import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.plugins.OpenAPSSMB.SMBDefaults;
import info.nightscout.androidaps.plugins.Overview.graphExtensions.DataPointWithLabelInterface;
import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLabelGraphSeries;
import info.nightscout.androidaps.plugins.Overview.graphExtensions.Scale;
import info.nightscout.androidaps.plugins.SensitivityAAPS.SensitivityAAPSPlugin;
import info.nightscout.androidaps.plugins.SensitivityWeightedAverage.SensitivityWeightedAveragePlugin;
import info.nightscout.androidaps.plugins.Treatments.Treatment;
import info.nightscout.utils.SP;
/**
* Created by mike on 25.04.2017.
*/
public class AutosensData {
public class AutosensData implements DataPointWithLabelInterface {
private static Logger log = LoggerFactory.getLogger(AutosensData.class);
public void setChartTime(long chartTime) {
this.chartTime = chartTime;
}
static class CarbsInPast {
long time = 0L;
double carbs = 0d;
@ -33,20 +42,21 @@ public class AutosensData {
time = t.date;
carbs = t.carbs;
remaining = t.carbs;
if (SensitivityAAPSPlugin.getPlugin().isEnabled(PluginBase.SENSITIVITY) || SensitivityWeightedAveragePlugin.getPlugin().isEnabled(PluginBase.SENSITIVITY)) {
double maxAbsorptionHours = SP.getDouble(R.string.key_absorption_maxtime, 4d);
if (SensitivityAAPSPlugin.getPlugin().isEnabled(PluginType.SENSITIVITY) || SensitivityWeightedAveragePlugin.getPlugin().isEnabled(PluginType.SENSITIVITY)) {
double maxAbsorptionHours = SP.getDouble(R.string.key_absorption_maxtime, Constants.DEFAULT_MAX_ABSORPTION_TIME);
Profile profile = MainApp.getConfigBuilder().getProfile(t.date);
double sens = Profile.toMgdl(profile.getIsf(t.date), profile.getUnits());
double ic = profile.getIc(t.date);
min5minCarbImpact = t.carbs / (maxAbsorptionHours * 60 / 5) * sens / ic;
log.debug("Min 5m carbs impact for " + carbs + "g @" + new Date(t.date).toLocaleString() + " for " + maxAbsorptionHours + "h calculated to " + min5minCarbImpact + " ISF: " + sens + " IC: " + ic);
} else {
min5minCarbImpact = SP.getDouble("openapsama_min_5m_carbimpact", 3.0);
min5minCarbImpact = SP.getDouble(R.string.key_openapsama_min_5m_carbimpact, SMBDefaults.min_5m_carbimpact);
}
}
}
public long time = 0L;
long chartTime;
public String pastSensitivity = "";
public double deviation = 0d;
boolean nonCarbsDeviation = false;
@ -63,24 +73,33 @@ public class AutosensData {
public double autosensRatio = 1d;
public double slopeFromMaxDeviation = 0;
public double slopeFromMinDeviation = 999;
public double usedMinCarbsImpact = 0d;
public boolean failoverToMinAbsorbtionRate = false;
public String log(long time) {
return "AutosensData: " + new Date(time).toLocaleString() + " " + pastSensitivity + " Delta=" + delta + " avgDelta=" + avgDelta + " Bgi=" + bgi + " Deviation=" + deviation + " avgDeviation=" + avgDeviation + " Absorbed=" + absorbed + " CarbsFromBolus=" + carbsFromBolus + " COB=" + cob + " autosensRatio=" + autosensRatio + " slopeFromMaxDeviation=" + slopeFromMaxDeviation + " slopeFromMinDeviation =" + slopeFromMinDeviation ;
@Override
public String toString() {
return "AutosensData: " + new Date(time).toLocaleString() + " " + pastSensitivity + " Delta=" + delta + " avgDelta=" + avgDelta + " Bgi=" + bgi + " Deviation=" + deviation + " avgDeviation=" + avgDeviation + " Absorbed=" + absorbed + " CarbsFromBolus=" + carbsFromBolus + " COB=" + cob + " autosensRatio=" + autosensRatio + " slopeFromMaxDeviation=" + slopeFromMaxDeviation + " slopeFromMinDeviation =" + slopeFromMinDeviation;
}
public int minOld() {
return (int) ((System.currentTimeMillis() - time) / 1000 / 60);
}
// remove carbs older than 4h
// remove carbs older than timeframe
public void removeOldCarbs(long toTime) {
double maxAbsorptionHours = Constants.DEFAULT_MAX_ABSORPTION_TIME;
if (SensitivityAAPSPlugin.getPlugin().isEnabled(PluginType.SENSITIVITY) || SensitivityWeightedAveragePlugin.getPlugin().isEnabled(PluginType.SENSITIVITY)) {
maxAbsorptionHours = SP.getDouble(R.string.key_absorption_maxtime, Constants.DEFAULT_MAX_ABSORPTION_TIME);
} else {
maxAbsorptionHours = SP.getDouble(R.string.key_absorption_cutoff, Constants.DEFAULT_MAX_ABSORPTION_TIME);
}
for (int i = 0; i < activeCarbsList.size(); i++) {
CarbsInPast c = activeCarbsList.get(i);
if (c.time + 4 * 60 * 60 * 1000L < toTime) {
if (c.time + maxAbsorptionHours * 60 * 60 * 1000L < toTime) {
activeCarbsList.remove(i--);
if (c.remaining > 0)
cob -= c.remaining;
log.debug("Removing carbs at "+ new Date(toTime).toLocaleString() + " + after 4h :" + new Date(c.time).toLocaleString());
log.debug("Removing carbs at " + new Date(toTime).toLocaleString() + " + after " + maxAbsorptionHours + "h :" + new Date(c.time).toLocaleString());
}
}
}
@ -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.EventPreferenceChange;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventNewHistoryData;
import info.nightscout.androidaps.plugins.OpenAPSSMB.OpenAPSSMBPlugin;
import info.nightscout.androidaps.plugins.Treatments.Treatment;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.utils.DateUtil;
import static info.nightscout.utils.DateUtil.now;
/**
* Created by mike on 24.04.2017.
*/
public class IobCobCalculatorPlugin implements PluginBase {
private static Logger log = LoggerFactory.getLogger(IobCobCalculatorPlugin.class);
public class IobCobCalculatorPlugin extends PluginBase {
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<AutosensData> autosensDataTable = new LongSparseArray<>(); // oldest at index 0
@ -55,12 +69,26 @@ public class IobCobCalculatorPlugin implements PluginBase {
boolean stopCalculationTrigger = false;
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() {
if (plugin == null)
plugin = new IobCobCalculatorPlugin();
return plugin;
@Override
protected void onStart() {
MainApp.bus().register(this);
super.onStart();
}
@Override
protected void onStop() {
super.onStop();
MainApp.bus().unregister(this);
}
public LongSparseArray<AutosensData> getAutosensDataTable() {
@ -71,70 +99,6 @@ public class IobCobCalculatorPlugin implements PluginBase {
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
public List<BgReading> getBucketedData(long fromTime) {
//log.debug("Locking getBucketedData");
@ -323,22 +287,22 @@ public class IobCobCalculatorPlugin implements PluginBase {
log.debug("Bucketed data created. Size: " + bucketed_data.size());
}
public static long oldestDataAvailable() {
public long oldestDataAvailable() {
long now = System.currentTimeMillis();
long oldestDataAvailable = MainApp.getConfigBuilder().oldestDataAvailable();
long oldestDataAvailable = TreatmentsPlugin.getPlugin().oldestDataAvailable();
long getBGDataFrom = Math.max(oldestDataAvailable, (long) (now - 60 * 60 * 1000L * (24 + MainApp.getConfigBuilder().getProfile().getDia())));
log.debug("Limiting data to oldest available temps: " + new Date(oldestDataAvailable).toString());
return getBGDataFrom;
}
public IobTotal calculateFromTreatmentsAndTempsSynchronized(long time) {
public IobTotal calculateFromTreatmentsAndTempsSynchronized(long time, Profile profile) {
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();
time = roundUpTime(time);
if (time < now && iobTable.get(time) != null) {
@ -347,18 +311,17 @@ public class IobCobCalculatorPlugin implements PluginBase {
} else {
//log.debug(">>> calculateFromTreatmentsAndTemps Cache miss " + new Date(time).toLocaleString());
}
IobTotal bolusIob = MainApp.getConfigBuilder().getCalculationToTimeTreatments(time).round();
IobTotal basalIob = MainApp.getConfigBuilder().getCalculationToTimeTempBasals(time).round();
if (OpenAPSSMBPlugin.getPlugin().isEnabled(PluginBase.APS)) {
// Add expected zere temp basal for next 240 mins
IobTotal basalIobWithZeroTemp = basalIob.clone();
TemporaryBasal t = new TemporaryBasal();
t.date = now + 60 * 1000L;
t.durationInMinutes = 240;
t.isAbsolute = true;
t.absoluteRate = 0;
IobTotal bolusIob = TreatmentsPlugin.getPlugin().getCalculationToTimeTreatments(time).round();
IobTotal basalIob = TreatmentsPlugin.getPlugin().getCalculationToTimeTempBasals(time, profile, true, now).round();
if (OpenAPSSMBPlugin.getPlugin().isEnabled(PluginType.APS)) {
// Add expected zero temp basal for next 240 mins
IobTotal basalIobWithZeroTemp = basalIob.copy();
TemporaryBasal t = new TemporaryBasal()
.date(now + 60 * 1000L)
.duration(240)
.absolute(0);
if (t.date < time) {
IobTotal calc = t.iobCalc(time);
IobTotal calc = t.iobCalc(time, profile);
basalIobWithZeroTemp.plus(calc);
}
@ -389,11 +352,12 @@ public class IobCobCalculatorPlugin implements PluginBase {
BasalData retval = basalDataTable.get(time);
if (retval == null) {
retval = new BasalData();
TemporaryBasal tb = MainApp.getConfigBuilder().getTempBasalFromHistory(time);
retval.basal = MainApp.getConfigBuilder().getProfile(time).getBasal(time);
Profile profile = MainApp.getConfigBuilder().getProfile(time);
TemporaryBasal tb = TreatmentsPlugin.getPlugin().getTempBasalFromHistory(time);
retval.basal = profile.getBasal(time);
if (tb != null) {
retval.isTempBasalRunning = true;
retval.tempBasalAbsolute = tb.tempBasalConvertedToAbsolute(time);
retval.tempBasalAbsolute = tb.tempBasalConvertedToAbsolute(time, profile);
} else {
retval.isTempBasalRunning = false;
retval.tempBasalAbsolute = retval.basal;
@ -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
public AutosensData getLastAutosensData(String reason) {
@ -447,7 +434,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
log.debug("AUTOSENSDATA null: autosensDataTable empty (" + reason + ")");
return null;
}
AutosensData data = null;
AutosensData data;
try {
data = autosensDataTable.valueAt(autosensDataTable.size() - 1);
} 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));
return null;
} else {
if (data == null)
log.debug("AUTOSENSDATA null: data == null (" + " " + reason + ") size()=" + autosensDataTable.size() + " lastdata=" + DateUtil.dateAndTimeString(data.time));
return data;
}
}
public IobTotal[] calculateIobArrayInDia() {
Profile profile = MainApp.getConfigBuilder().getProfile();
public IobTotal[] calculateIobArrayInDia(Profile profile) {
// predict IOB out to DIA plus 30m
long time = System.currentTimeMillis();
time = roundUpTime(time);
@ -477,15 +461,14 @@ public class IobCobCalculatorPlugin implements PluginBase {
int pos = 0;
for (int i = 0; i < len; i++) {
long t = time + i * 5 * 60000;
IobTotal iob = calculateFromTreatmentsAndTempsSynchronized(t);
IobTotal iob = calculateFromTreatmentsAndTempsSynchronized(t, profile);
array[pos] = iob;
pos++;
}
return array;
}
public IobTotal[] calculateIobArrayForSMB() {
Profile profile = MainApp.getConfigBuilder().getProfile();
public IobTotal[] calculateIobArrayForSMB(Profile profile) {
// predict IOB out to DIA plus 30m
long time = System.currentTimeMillis();
time = roundUpTime(time);
@ -494,7 +477,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
int pos = 0;
for (int i = 0; i < len; i++) {
long t = time + i * 5 * 60000;
IobTotal iob = calculateFromTreatmentsAndTempsSynchronized(t);
IobTotal iob = calculateFromTreatmentsAndTempsSynchronized(t, profile);
array[pos] = iob;
pos++;
}
@ -520,6 +503,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
}
@Subscribe
@SuppressWarnings("unused")
public void onEventAppInitialized(EventAppInitialized ev) {
if (this != getPlugin()) {
log.debug("Ignoring event for non default instance");
@ -529,6 +513,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
}
@Subscribe
@SuppressWarnings("unused")
public void onEventNewBG(EventNewBG ev) {
if (this != getPlugin()) {
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) ||
ev.isChanged(R.string.key_age) ||
ev.isChanged(R.string.key_absorption_maxtime)
ev.isChanged(R.string.key_absorption_maxtime) ||
ev.isChanged(R.string.key_openapsama_min_5m_carbimpact) ||
ev.isChanged(R.string.key_absorption_cutoff)
) {
stopCalculation("onEventPreferenceChange");
synchronized (dataLock) {

View file

@ -4,6 +4,8 @@ import android.content.Context;
import android.os.PowerManager;
import android.support.v4.util.LongSparseArray;
import com.crashlytics.android.answers.CustomEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -11,24 +13,35 @@ import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import info.nightscout.androidaps.BuildConfig;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.events.Event;
import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventAutosensCalculationFinished;
import info.nightscout.androidaps.queue.QueueThread;
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventIobCalculationProgress;
import info.nightscout.androidaps.plugins.OpenAPSSMB.SMBDefaults;
import info.nightscout.androidaps.plugins.SensitivityAAPS.SensitivityAAPSPlugin;
import info.nightscout.androidaps.plugins.SensitivityWeightedAverage.SensitivityWeightedAveragePlugin;
import info.nightscout.androidaps.plugins.Treatments.Treatment;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.FabricPrivacy;
import info.nightscout.utils.SP;
import static info.nightscout.utils.DateUtil.now;
/**
* Created by mike on 23.01.2018.
*/
public class IobCobThread extends Thread {
private static Logger log = LoggerFactory.getLogger(QueueThread.class);
private static Logger log = LoggerFactory.getLogger(IobCobThread.class);
private final Event cause;
private IobCobCalculatorPlugin iobCobCalculatorPlugin;
@ -59,34 +72,34 @@ public class IobCobThread extends Thread {
log.debug("Aborting calculation thread (ConfigBuilder not ready): " + from);
return; // app still initializing
}
if (MainApp.getConfigBuilder().getProfile() == null) {
if (!MainApp.getConfigBuilder().isProfileValid("IobCobThread")) {
log.debug("Aborting calculation thread (No profile): " + from);
return; // app still initializing
}
//log.debug("Locking calculateSensitivityData");
Object dataLock = iobCobCalculatorPlugin.dataLock;
long oldestTimeWithData = iobCobCalculatorPlugin.oldestDataAvailable();
synchronized (dataLock) {
synchronized (iobCobCalculatorPlugin.dataLock) {
if (bgDataReload) {
iobCobCalculatorPlugin.loadBgData(start);
iobCobCalculatorPlugin.createBucketedData();
}
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) {
log.debug("Aborting calculation thread (No bucketed data available): " + from);
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());
AutosensData previous = autosensDataTable.get(prevDataTime);
// start from oldest to be able sub cob
for (int i = bucketed_data.size() - 4; i >= 0; i--) {
MainApp.bus().post(new EventIobCalculationProgress(i + "/" + bucketed_data.size()));
if (iobCobCalculatorPlugin.stopCalculationTrigger) {
iobCobCalculatorPlugin.stopCalculationTrigger = false;
log.debug("Aborting calculation thread (trigger): " + from);
@ -94,10 +107,9 @@ public class IobCobThread extends Thread {
}
// check if data already exists
long bgTime = bucketed_data.get(i).date;
bgTime = iobCobCalculatorPlugin.roundUpTime(bgTime);
if (bgTime > System.currentTimeMillis())
bgTime = IobCobCalculatorPlugin.roundUpTime(bgTime);
if (bgTime > IobCobCalculatorPlugin.roundUpTime(now()))
continue;
Profile profile = MainApp.getConfigBuilder().getProfile(bgTime);
AutosensData existing;
if ((existing = autosensDataTable.get(bgTime)) != null) {
@ -105,16 +117,12 @@ public class IobCobThread extends Thread {
continue;
}
Profile profile = MainApp.getConfigBuilder().getProfile(bgTime);
if (profile == null) {
log.debug("Aborting calculation thread (no profile): " + from);
return; // profile not set yet
}
if (profile.getIsf(bgTime) == null) {
log.debug("Aborting calculation thread (no ISF): " + from);
return; // profile not set yet
}
if (Config.logAutosensData)
log.debug("Processing calculation thread: " + from + " (" + i + "/" + bucketed_data.size() + ")");
@ -139,13 +147,12 @@ public class IobCobThread extends Thread {
delta = (bg - bucketed_data.get(i + 1).value);
avgDelta = (bg - bucketed_data.get(i + 3).value) / 3;
IobTotal iob = iobCobCalculatorPlugin.calculateFromTreatmentsAndTemps(bgTime);
IobTotal iob = iobCobCalculatorPlugin.calculateFromTreatmentsAndTemps(bgTime, profile);
double bgi = -iob.activity * sens * 5;
double deviation = delta - bgi;
double avgDeviation = Math.round((avgDelta - bgi) * 1000) / 1000;
double currentDeviation;
double slopeFromMaxDeviation = 0;
double slopeFromMinDeviation = 999;
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
if (i < bucketed_data.size() - 16) { // we need 1h of data to calculate minDeviationSlope
long hourago = bgTime + 10 * 1000 - 60 * 60 * 1000L;
AutosensData hourAgoData = iobCobCalculatorPlugin.getAutosensData(hourago);
AutosensData hourAgoData = IobCobCalculatorPlugin.getPlugin().getAutosensData(hourago);
if (hourAgoData != null) {
currentDeviation = hourAgoData.avgDeviation;
int initialIndex = autosensDataTable.indexOfKey(hourAgoData.time);
for (int past = 1; past < 12; past++) {
if (Config.logAutosensData)
log.debug(">>>>> bucketed_data.size()=" + bucketed_data.size() + " i=" + i + "hourAgoData=" + hourAgoData.toString());
int past = 1;
try {
for (; past < 12; past++) {
AutosensData ad = autosensDataTable.valueAt(initialIndex + past);
double deviationSlope = (ad.avgDeviation - currentDeviation) / (ad.time - bgTime) * 1000 * 60 * 5;
double deviationSlope = (ad.avgDeviation - avgDeviation) / (ad.time - bgTime) * 1000 * 60 * 5;
if (ad.avgDeviation > maxDeviation) {
slopeFromMaxDeviation = Math.min(0, deviationSlope);
maxDeviation = ad.avgDeviation;
}
if (avgDeviation < minDeviation) {
if (ad.avgDeviation < minDeviation) {
slopeFromMinDeviation = Math.max(0, deviationSlope);
minDeviation = avgDeviation;
minDeviation = ad.avgDeviation;
}
//if (Config.logAutosensData)
// log.debug("Deviations: " + new Date(bgTime) + new Date(ad.time) + " avgDeviation=" + avgDeviation + " deviationSlope=" + deviationSlope + " slopeFromMaxDeviation=" + slopeFromMaxDeviation + " slopeFromMinDeviation=" + slopeFromMinDeviation);
}
} catch (Exception e) {
log.error("Unhandled exception", e);
FabricPrivacy.logException(e);
FabricPrivacy.getInstance().logCustom(new CustomEvent("CatchedError")
.putCustomAttribute("buildversion", BuildConfig.BUILDVERSION)
.putCustomAttribute("version", BuildConfig.VERSION)
.putCustomAttribute("autosensDataTable", iobCobCalculatorPlugin.getAutosensDataTable().toString())
.putCustomAttribute("for_data", ">>>>> bucketed_data.size()=" + bucketed_data.size() + " i=" + i + "hourAgoData=" + hourAgoData.toString())
.putCustomAttribute("past", past)
);
}
}
}
List<Treatment> recentTreatments = MainApp.getConfigBuilder().getTreatments5MinBackFromHistory(bgTime);
List<Treatment> recentTreatments = TreatmentsPlugin.getPlugin().getTreatments5MinBackFromHistory(bgTime);
for (int ir = 0; ir < recentTreatments.size(); ir++) {
autosensData.carbsFromBolus += recentTreatments.get(ir).carbs;
autosensData.activeCarbsList.add(new AutosensData.CarbsInPast(recentTreatments.get(ir)));
@ -188,18 +208,27 @@ public class IobCobThread extends Thread {
if (previous != null && previous.cob > 0) {
// calculate sum of min carb impact from all active treatments
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) {
AutosensData.CarbsInPast c = autosensData.activeCarbsList.get(ii);
totalMinCarbsImpact += c.min5minCarbImpact;
}
} else {
//Oref sensitivity
totalMinCarbsImpact = SP.getDouble(R.string.key_openapsama_min_5m_carbimpact, SMBDefaults.min_5m_carbimpact);
}
// figure out how many carbs that represents
// but always assume at least 3mg/dL/5m (default) absorption per active treatment
double ci = Math.max(deviation, totalMinCarbsImpact);
if (ci != deviation)
autosensData.failoverToMinAbsorbtionRate = true;
autosensData.absorbed = ci * profile.getIc(bgTime) / sens;
// and add that to the running total carbsAbsorbed
autosensData.cob = Math.max(previous.cob - autosensData.absorbed, 0d);
autosensData.substractAbosorbedCarbs();
autosensData.usedMinCarbsImpact = totalMinCarbsImpact;
}
autosensData.removeOldCarbs(bgTime);
autosensData.cob += autosensData.carbsFromBolus;
@ -232,16 +261,18 @@ public class IobCobThread extends Thread {
previous = autosensData;
autosensDataTable.put(bgTime, autosensData);
if (Config.logAutosensData)
log.debug("Running detectSensitivity from: " + DateUtil.dateAndTimeString(oldestTimeWithData) + " to: " + DateUtil.dateAndTimeString(bgTime));
autosensData.autosensRatio = iobCobCalculatorPlugin.detectSensitivity(oldestTimeWithData, bgTime).ratio;
if (Config.logAutosensData)
log.debug(autosensData.log(bgTime));
log.debug(autosensData.toString());
}
}
MainApp.bus().post(new EventAutosensCalculationFinished(cause));
log.debug("Finishing calculation thread: " + from);
} finally {
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.data.IobTotal;
import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.utils.DecimalFormatter;
@ -31,7 +32,7 @@ public class APSResult {
public String reason;
public double rate;
public int duration;
public boolean tempBasalReqested = false;
public boolean tempBasalRequested = false;
public boolean bolusRequested = false;
public IobTotal iob;
public JSONObject json = new JSONObject();
@ -39,6 +40,11 @@ public class APSResult {
public double smb = 0d; // super micro bolus in units
public long deliverAt = 0;
public Constraint<Double> inputConstraints;
public Constraint<Double> rateConstraint;
public Constraint<Double> smbConstraint;
@Override
public String toString() {
final PumpInterface pump = ConfigBuilderPlugin.getActivePump();
@ -56,7 +62,7 @@ public class APSResult {
// smb
if (smb != 0)
ret += ("SMB: " + DecimalFormatter.to2Decimal(smb) + " U\n");
ret += ("SMB: " + DecimalFormatter.toPumpSupportedBolus(smb) + " U\n");
// reason
ret += MainApp.sResources.getString(R.string.reason) + ": " + reason;
@ -81,7 +87,7 @@ public class APSResult {
// smb
if (smb != 0)
ret += ("<b>" + "SMB" + "</b>: " + DecimalFormatter.to2Decimal(smb) + " U<br>");
ret += ("<b>" + "SMB" + "</b>: " + DecimalFormatter.toPumpSupportedBolus(smb) + " U<br>");
// reason
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.rate = rate;
newResult.duration = duration;
newResult.tempBasalReqested = tempBasalReqested;
newResult.tempBasalRequested = tempBasalRequested;
newResult.bolusRequested = bolusRequested;
newResult.iob = iob;
newResult.json = json;
newResult.hasPredictions = hasPredictions;
newResult.smb = smb;
newResult.deliverAt = deliverAt;
newResult.rateConstraint = rateConstraint;
newResult.smbConstraint = smbConstraint;
return newResult;
}
@ -216,6 +228,6 @@ public class APSResult {
}
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.os.Bundle;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@ -15,23 +16,38 @@ import com.squareup.otto.Subscribe;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.plugins.Common.SubscriberFragment;
import info.nightscout.androidaps.plugins.Loop.events.EventLoopSetLastRunGui;
import info.nightscout.androidaps.plugins.Loop.events.EventLoopUpdateGui;
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);
@BindView(R.id.loop_run)
Button runNowButton;
@BindView(R.id.loop_lastrun)
TextView lastRunView;
@BindView(R.id.loop_lastenact)
TextView lastEnactView;
@BindView(R.id.loop_source)
TextView sourceView;
@BindView(R.id.loop_request)
TextView requestView;
@BindView(R.id.loop_constraintsprocessed)
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
@ -39,41 +55,19 @@ public class LoopFragment extends SubscriberFragment implements View.OnClickList
Bundle savedInstanceState) {
try {
View view = inflater.inflate(R.layout.loop_fragment, container, false);
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();
unbinder = ButterKnife.bind(this, view);
return view;
} catch (Exception e) {
FabricPrivacy.logException(e);
}
return null;
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.loop_run:
@OnClick(R.id.loop_run)
void onRunClick() {
lastRunView.setText(MainApp.sResources.getString(R.string.executing));
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
LoopPlugin.getPlugin().invoke("Loop button", true);
}
});
thread.start();
new Thread(() -> LoopPlugin.getPlugin().invoke("Loop button", true)).start();
FabricPrivacy.getInstance().logCustom(new CustomEvent("Loop_Run"));
break;
}
}
@Subscribe
@ -86,12 +80,7 @@ public class LoopFragment extends SubscriberFragment implements View.OnClickList
clearGUI();
final Activity activity = getActivity();
if (activity != null)
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
lastRunView.setText(ev.text);
}
});
activity.runOnUiThread(() -> lastRunView.setText(ev.text));
}
@ -99,17 +88,27 @@ public class LoopFragment extends SubscriberFragment implements View.OnClickList
protected void updateGUI() {
Activity activity = getActivity();
if (activity != null)
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
if (LoopPlugin.lastRun != null) {
requestView.setText(LoopPlugin.lastRun.request != null ? LoopPlugin.lastRun.request.toSpanned() : "");
constraintsProcessedView.setText(LoopPlugin.lastRun.constraintsProcessed != null ? LoopPlugin.lastRun.constraintsProcessed.toSpanned() : "");
setByPumpView.setText(LoopPlugin.lastRun.setByPump != null ? LoopPlugin.lastRun.setByPump.toSpanned() : "");
sourceView.setText(LoopPlugin.lastRun.source != null ? LoopPlugin.lastRun.source : "");
lastRunView.setText(LoopPlugin.lastRun.lastAPSRun != null && LoopPlugin.lastRun.lastAPSRun.getTime() != 0 ? LoopPlugin.lastRun.lastAPSRun.toLocaleString() : "");
lastEnactView.setText(LoopPlugin.lastRun.lastEnact != null && LoopPlugin.lastRun.lastEnact.getTime() != 0 ? LoopPlugin.lastRun.lastEnact.toLocaleString() : "");
activity.runOnUiThread(() -> {
LoopPlugin.LastRun lastRun = LoopPlugin.lastRun;
if (lastRun != null) {
requestView.setText(lastRun.request != null ? lastRun.request.toSpanned() : "");
constraintsProcessedView.setText(lastRun.constraintsProcessed != null ? lastRun.constraintsProcessed.toSpanned() : "");
sourceView.setText(lastRun.source != null ? lastRun.source : "");
lastRunView.setText(lastRun.lastAPSRun != null && lastRun.lastAPSRun.getTime() != 0 ? lastRun.lastAPSRun.toLocaleString() : "");
lastEnactView.setText(lastRun.lastEnact != null && lastRun.lastEnact.getTime() != 0 ? lastRun.lastEnact.toLocaleString() : "");
tbrSetByPumpView.setText(lastRun.tbrSetByPump != null ? Html.fromHtml(lastRun.tbrSetByPump.toHtml()) : "");
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() {
Activity activity = getActivity();
if (activity != null)
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
activity.runOnUiThread(() -> {
requestView.setText("");
constraintsProcessedView.setText("");
setByPumpView.setText("");
sourceView.setText("");
lastRunView.setText("");
lastEnactView.setText("");
}
tbrSetByPumpView.setText("");
smbSetByPumpView.setText("");
});
}
}

View file

@ -1,11 +1,16 @@
package info.nightscout.androidaps.plugins.Loop;
import android.annotation.SuppressLint;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.TaskStackBuilder;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.SystemClock;
import android.support.annotation.NonNull;
import android.support.v4.app.NotificationCompat;
import com.crashlytics.android.answers.CustomEvent;
@ -21,16 +26,21 @@ import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainActivity;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Profile;
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.EventTreatmentChange;
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.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.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.EventLoopUpdateGui;
import info.nightscout.androidaps.plugins.Loop.events.EventNewOpenLoopNotification;
@ -43,11 +53,16 @@ import info.nightscout.utils.SP;
/**
* 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 LoopPlugin loopPlugin;
public static final String CHANNEL_ID = "AndroidAPS-Openloop";
long lastBgTriggeredRun = 0;
protected static LoopPlugin loopPlugin;
@NonNull
public static LoopPlugin getPlugin() {
if (loopPlugin == null) {
loopPlugin = new LoopPlugin();
@ -55,9 +70,6 @@ public class LoopPlugin implements PluginBase {
return loopPlugin;
}
private boolean fragmentEnabled = false;
private boolean fragmentVisible = false;
private long loopSuspendedTill = 0L; // end of manual loop suspend
private boolean isSuperBolus = false;
private boolean isDisconnected = false;
@ -65,7 +77,8 @@ public class LoopPlugin implements PluginBase {
public class LastRun {
public APSResult request = null;
public APSResult constraintsProcessed = null;
public PumpEnactResult setByPump = null;
public PumpEnactResult tbrSetByPump = null;
public PumpEnactResult smbSetByPump = null;
public String source = null;
public Date lastAPSRun = null;
public Date lastEnact = null;
@ -75,92 +88,76 @@ public class LoopPlugin implements PluginBase {
static public LastRun lastRun = null;
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);
isSuperBolus = SP.getBoolean("isSuperBolus", false);
isDisconnected = SP.getBoolean("isDisconnected", false);
}
@Override
public String getFragmentClass() {
return LoopFragment.class.getName();
protected void onStart() {
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
public int getType() {
return PluginBase.LOOP;
protected void onStop() {
super.onStop();
MainApp.bus().unregister(this);
}
@Override
public String getName() {
return MainApp.instance().getString(R.string.loop);
}
@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);
}
public boolean specialEnableCondition() {
PumpInterface pump = ConfigBuilderPlugin.getActivePump();
return pump == null || pump.getPumpDescription().isTempBasalCapable;
}
/**
* 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
public void onStatusEvent(final EventAutosensCalculationFinished ev) {
if (ev.cause instanceof EventNewBG) {
invoke(ev.getClass().getSimpleName() + "(" + ev.cause.getClass().getSimpleName() + ")", true);
if (!(ev.cause instanceof EventNewBG)) {
// 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() {
@ -250,23 +247,31 @@ public class LoopPlugin implements PluginBase {
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 {
if (Config.logFunctionCalls)
log.debug("invoke from " + initiator);
ConstraintsInterface constraintsInterface = MainApp.getConfigBuilder();
if (!constraintsInterface.isLoopEnabled()) {
log.debug(MainApp.sResources.getString(R.string.loopdisabled));
MainApp.bus().post(new EventLoopSetLastRunGui(MainApp.sResources.getString(R.string.loopdisabled)));
Constraint<Boolean> loopEnabled = MainApp.getConstraintChecker().isLoopInvokationAllowed();
if (!loopEnabled.value()) {
String message = MainApp.sResources.getString(R.string.loopdisabled) + "\n" + loopEnabled.getReasons();
log.debug(message);
MainApp.bus().post(new EventLoopSetLastRunGui(message));
return;
}
final PumpInterface pump = ConfigBuilderPlugin.getActivePump();
APSResult result = null;
if (!isEnabled(PluginBase.LOOP))
if (!isEnabled(PluginType.LOOP))
return;
if (MainApp.getConfigBuilder().getProfile() == null) {
Profile profile = MainApp.getConfigBuilder().getProfile();
if (!MainApp.getConfigBuilder().isProfileValid("Loop")) {
log.debug(MainApp.sResources.getString(R.string.noprofileselected));
MainApp.bus().post(new EventLoopSetLastRunGui(MainApp.sResources.getString(R.string.noprofileselected)));
return;
@ -276,8 +281,8 @@ public class LoopPlugin implements PluginBase {
if (pump.getBaseBasalRate() < 0.01d) return;
APSInterface usedAPS = ConfigBuilderPlugin.getActiveAPS();
if (usedAPS != null && ((PluginBase) usedAPS).isEnabled(PluginBase.APS)) {
usedAPS.invoke(initiator);
if (usedAPS != null && ((PluginBase) usedAPS).isEnabled(PluginType.APS)) {
usedAPS.invoke(initiator, tempBasalFallback);
result = usedAPS.getLastAPSResult();
}
@ -289,8 +294,10 @@ public class LoopPlugin implements PluginBase {
// check rate for constrais
final APSResult resultAfterConstraints = result.clone();
resultAfterConstraints.rate = constraintsInterface.applyBasalConstraints(resultAfterConstraints.rate);
resultAfterConstraints.smb = constraintsInterface.applyBolusConstraints(resultAfterConstraints.smb);
resultAfterConstraints.rateConstraint = new Constraint<>(resultAfterConstraints.rate);
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
long lastBolusTime = TreatmentsPlugin.getPlugin().getLastBolusTime();
@ -304,7 +311,8 @@ public class LoopPlugin implements PluginBase {
lastRun.constraintsProcessed = resultAfterConstraints;
lastRun.lastAPSRun = new Date();
lastRun.source = ((PluginBase) usedAPS).getName();
lastRun.setByPump = null;
lastRun.tbrSetByPump = null;
lastRun.smbSetByPump = null;
NSUpload.uploadDeviceStatus();
@ -320,36 +328,53 @@ public class LoopPlugin implements PluginBase {
return;
}
MainApp.bus().post(new EventLoopResult(resultAfterConstraints));
Constraint<Boolean> closedLoopEnabled = MainApp.getConstraintChecker().isClosedLoopAllowed();
if (constraintsInterface.isClosedModeEnabled()) {
if (closedLoopEnabled.value()) {
if (result.isChangeRequested()) {
final PumpEnactResult waiting = new PumpEnactResult();
final PumpEnactResult previousResult = lastRun.setByPump;
waiting.queued = true;
lastRun.setByPump = waiting;
if (resultAfterConstraints.tempBasalRequested)
lastRun.tbrSetByPump = waiting;
if (resultAfterConstraints.bolusRequested)
lastRun.smbSetByPump = waiting;
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
public void run() {
FabricPrivacy.getInstance().logCustom(new CustomEvent("APSRequest"));
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;
} 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());
}
});
} else {
lastRun.setByPump = null;
lastRun.source = null;
lastRun.tbrSetByPump = null;
lastRun.smbSetByPump = null;
}
} else {
if (result.isChangeRequested() && allowNotification) {
NotificationCompat.Builder builder =
new NotificationCompat.Builder(MainApp.instance().getApplicationContext());
new NotificationCompat.Builder(MainApp.instance().getApplicationContext(), CHANNEL_ID);
builder.setSmallIcon(R.drawable.notif_icon)
.setContentTitle(MainApp.sResources.getString(R.string.openloop_newsuggestion))
.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.graphics.Paint;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.text.Html;
import android.text.Spanned;
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.SP;
public class NSClientInternalFragment extends SubscriberFragment implements View.OnClickListener, CompoundButton.OnCheckedChangeListener {
private static Logger log = LoggerFactory.getLogger(NSClientInternalFragment.class);
public class NSClientFragment extends SubscriberFragment implements View.OnClickListener, CompoundButton.OnCheckedChangeListener {
private static Logger log = LoggerFactory.getLogger(NSClientFragment.class);
private TextView logTextView;
private TextView queueTextView;
@ -58,10 +57,10 @@ public class NSClientInternalFragment extends SubscriberFragment implements View
logScrollview = (ScrollView) view.findViewById(R.id.nsclientinternal_logscrollview);
autoscrollCheckbox = (CheckBox) view.findViewById(R.id.nsclientinternal_autoscroll);
autoscrollCheckbox.setChecked(NSClientInternalPlugin.getPlugin().autoscroll);
autoscrollCheckbox.setChecked(NSClientPlugin.getPlugin().autoscroll);
autoscrollCheckbox.setOnCheckedChangeListener(this);
pausedCheckbox = (CheckBox) view.findViewById(R.id.nsclientinternal_paused);
pausedCheckbox.setChecked(NSClientInternalPlugin.getPlugin().paused);
pausedCheckbox.setChecked(NSClientPlugin.getPlugin().paused);
pausedCheckbox.setOnCheckedChangeListener(this);
logTextView = (TextView) view.findViewById(R.id.nsclientinternal_log);
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"));
break;
case R.id.nsclientinternal_delivernow:
NSClientInternalPlugin.getPlugin().resend("GUI");
NSClientPlugin.getPlugin().resend("GUI");
FabricPrivacy.getInstance().logCustom(new CustomEvent("NSClientDeliverNow"));
break;
case R.id.nsclientinternal_clearlog:
NSClientInternalPlugin.getPlugin().clearLog();
NSClientPlugin.getPlugin().clearLog();
break;
case R.id.nsclientinternal_clearqueue:
final Context context = getContext();
@ -124,7 +123,7 @@ public class NSClientInternalFragment extends SubscriberFragment implements View
builder.show();
break;
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"));
break;
}
@ -135,14 +134,14 @@ public class NSClientInternalFragment extends SubscriberFragment implements View
switch (buttonView.getId()) {
case R.id.nsclientinternal_paused:
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));
updateGUI();
FabricPrivacy.getInstance().logCustom(new CustomEvent("NSClientPause"));
break;
case R.id.nsclientinternal_autoscroll:
SP.putBoolean(R.string.key_nsclientinternal_autoscroll, isChecked);
NSClientInternalPlugin.getPlugin().autoscroll = isChecked;
NSClientPlugin.getPlugin().autoscroll = isChecked;
updateGUI();
break;
}
@ -160,15 +159,15 @@ public class NSClientInternalFragment extends SubscriberFragment implements View
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
NSClientInternalPlugin.updateLog();
logTextView.setText(NSClientInternalPlugin.textLog);
if (NSClientInternalPlugin.getPlugin().autoscroll) {
NSClientPlugin.getPlugin().updateLog();
logTextView.setText(NSClientPlugin.getPlugin().textLog);
if (NSClientPlugin.getPlugin().autoscroll) {
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>");
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.List;
import info.nightscout.androidaps.BuildConfig;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.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.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientNewLog;
import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientStatus;
import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientUpdateGUI;
import info.nightscout.androidaps.plugins.NSClientInternal.services.NSClientService;
import info.nightscout.androidaps.receivers.NetworkChangeReceiver;
import info.nightscout.utils.SP;
import info.nightscout.utils.ToastUtils;
public class NSClientInternalPlugin implements PluginBase {
private static Logger log = LoggerFactory.getLogger(NSClientInternalPlugin.class);
public class NSClientPlugin extends PluginBase {
private static Logger log = LoggerFactory.getLogger(NSClientPlugin.class);
static NSClientInternalPlugin nsClientInternalPlugin;
static NSClientPlugin nsClientPlugin;
static public NSClientInternalPlugin getPlugin() {
if (nsClientInternalPlugin == null) {
nsClientInternalPlugin = new NSClientInternalPlugin();
static public NSClientPlugin getPlugin() {
if (nsClientPlugin == null) {
nsClientPlugin = new NSClientPlugin();
}
return nsClientInternalPlugin;
return nsClientPlugin;
}
private boolean fragmentEnabled = true;
private boolean fragmentVisible = true;
public Handler handler;
static public Handler handler;
private static List<EventNSClientNewLog> listLog = new ArrayList<>();
static Spanned textLog = Html.fromHtml("");
private final List<EventNSClientNewLog> listLog = new ArrayList<>();
Spanned textLog = Html.fromHtml("");
public boolean paused = false;
public boolean allowed = true;
boolean autoscroll = true;
public String status = "";
public NSClientService nsClientService = null;
NSClientInternalPlugin() {
MainApp.bus().register(this);
private NSClientPlugin() {
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);
autoscroll = SP.getBoolean(R.string.key_nsclientinternal_autoscroll, true);
if (handler == null) {
HandlerThread handlerThread = new HandlerThread(NSClientInternalPlugin.class.getSimpleName() + "Handler");
HandlerThread handlerThread = new HandlerThread(NSClientPlugin.class.getSimpleName() + "Handler");
handlerThread.start();
handler = new Handler(handlerThread.getLooper());
}
}
@Override
protected void onStart() {
MainApp.bus().register(this);
Context context = MainApp.instance().getApplicationContext();
Intent intent = new Intent(context, NSClientService.class);
context.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
super.onStart();
EventNetworkChange event = NetworkChangeReceiver.grabNetworkStatus();
if (event != null)
MainApp.bus().post(event);
}
@Override
public int getType() {
return PluginBase.GENERAL;
}
@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;
protected void onStop() {
MainApp.bus().unregister(this);
Context context = MainApp.instance().getApplicationContext();
context.unbindService(mConnection);
}
private ServiceConnection mConnection = new ServiceConnection() {
@ -150,13 +114,44 @@ public class NSClientInternalPlugin implements PluginBase {
public void onServiceConnected(ComponentName name, IBinder service) {
log.debug("Service is connected");
NSClientService.LocalBinder mLocalBinder = (NSClientService.LocalBinder) service;
if (mLocalBinder != null) // is null when running in roboelectric
nsClientService = mLocalBinder.getServiceInstance();
}
};
@SuppressWarnings("UnusedParameters")
@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)
MainApp.instance().getApplicationContext().unbindService(mConnection);
}
@ -177,7 +172,9 @@ public class NSClientInternalPlugin implements PluginBase {
handler.post(new Runnable() {
@Override
public void run() {
listLog = new ArrayList<>();
synchronized (listLog) {
listLog.clear();
}
MainApp.bus().post(new EventNSClientUpdateGUI());
}
});
@ -187,23 +184,26 @@ public class NSClientInternalPlugin implements PluginBase {
handler.post(new Runnable() {
@Override
public void run() {
synchronized (listLog) {
listLog.add(ev);
// remove the first line if log is too large
if (listLog.size() >= Constants.MAX_LOG_LINES) {
listLog.remove(0);
}
}
MainApp.bus().post(new EventNSClientUpdateGUI());
}
});
}
static synchronized void updateLog() {
synchronized void updateLog() {
try {
StringBuilder newTextLog = new StringBuilder();
List<EventNSClientNewLog> temporaryList = new ArrayList<>(listLog);
for (EventNSClientNewLog log : temporaryList) {
synchronized (listLog) {
for (EventNSClientNewLog log : listLog) {
newTextLog.append(log.toPreparedHtml());
}
}
textLog = Html.fromHtml(newTextLog.toString());
} catch (OutOfMemoryError e) {
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() {
log.debug("QUEUE adding: " + dbr.data);
MainApp.getDbHelper().create(dbr);
NSClientInternalPlugin plugin = MainApp.getSpecificPlugin(NSClientInternalPlugin.class);
NSClientPlugin plugin = NSClientPlugin.getPlugin();
if (plugin != null) {
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() {
return getStringOrNull("activeProfile");
}
@ -193,7 +206,7 @@ public class NSSettingsStatus {
return result;
}
}
if (settingsO.has("alarmTimeagoWarnMins") && Objects.equals(what, "alarmTimeagoWarnMins")){
if (settingsO.has("alarmTimeagoWarnMins") && Objects.equals(what, "alarmTimeagoWarnMins")) {
Double result = settingsO.getDouble(what);
return result;
}
@ -206,7 +219,7 @@ public class NSSettingsStatus {
private String getStringOrNull(String key) {
String ret = null;
if(data == null) return null;
if (data == null) return null;
if (data.has(key)) {
try {
ret = data.getString(key);
@ -315,7 +328,7 @@ public class NSSettingsStatus {
public JSONObject extentendedPumpSettings() {
try {
JSONObject extended = getExtendedSettings();
if(extended == null) return null;
if (extended == null) return null;
if (extended.has("pump")) {
JSONObject pump = extended.getJSONObject("pump");
return pump;

View file

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

View file

@ -14,8 +14,8 @@ import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.db.DbRequest;
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.broadcasts.BroadcastTreatment;
import info.nightscout.utils.DateUtil;
@ -94,7 +94,7 @@ public class DBAccessReceiver extends BroadcastReceiver {
UploadQueue.add(dbr);
}
if (collection.equals("treatments")) {
genereateTreatmentOfflineBroadcast(dbr);
generateTreatmentOfflineBroadcast(dbr);
}
}
@ -105,11 +105,11 @@ public class DBAccessReceiver extends BroadcastReceiver {
}
public boolean shouldUpload() {
NSClientInternalPlugin nsClientInternalPlugin = MainApp.getSpecificPlugin(NSClientInternalPlugin.class);
return nsClientInternalPlugin.isEnabled(PluginBase.GENERAL) && !SP.getBoolean(R.string.key_ns_noupload, false);
NSClientPlugin nsClientPlugin = MainApp.getSpecificPlugin(NSClientPlugin.class);
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")) {
try {
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.EventPreferenceChange;
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.acks.NSAddAck;
import info.nightscout.androidaps.plugins.NSClientInternal.acks.NSAuthAck;
@ -180,7 +181,7 @@ public class NSClientService extends Service {
@Subscribe
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;
destroy();
initialize();
@ -202,7 +203,10 @@ public class NSClientService extends Service {
nsAPIhashCode = Hashing.sha1().hashString(nsAPISecret, Charsets.UTF_8).toString();
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 EventNSClientStatus("Paused"));
} else if (!nsEnabled) {
@ -313,7 +317,7 @@ public class NSClientService extends Service {
}
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, "");
nsAPISecret = SP.getString(R.string.key_nsclientinternal_api_secret, "");
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.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.GlucoseStatus;
import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.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.OpenAPSMA.LoggerCallback;
import info.nightscout.androidaps.plugins.OpenAPSSMB.SMBDefaults;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.utils.SP;
public class DetermineBasalAdapterAMAJS {
@ -204,28 +206,34 @@ public class DetermineBasalAdapterAMAJS {
mProfile.put("max_bg", maxBg);
mProfile.put("target_bg", targetBg);
mProfile.put("carb_ratio", profile.getIc());
mProfile.put("sens", Profile.toMgdl(profile.getIsf().doubleValue(), units));
mProfile.put("max_daily_safety_multiplier", SP.getInt("openapsama_max_daily_safety_multiplier", 3));
mProfile.put("current_basal_safety_multiplier", SP.getDouble("openapsama_current_basal_safety_multiplier", 4d));
mProfile.put("sens", Profile.toMgdl(profile.getIsf(), units));
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(R.string.key_openapsama_current_basal_safety_multiplier, 4d));
mProfile.put("skip_neutral_temps", true);
mProfile.put("current_basal", basalrate);
mProfile.put("temptargetSet", tempTargetSet);
mProfile.put("autosens_adjust_targets", SP.getBoolean("openapsama_autosens_adjusttargets", true));
//TODO: align with max-absorption model in AMA sensitivity
mProfile.put("min_5m_carbimpact", SP.getDouble("openapsama_min_5m_carbimpact", SMBDefaults.min_5m_carbimpact));
mProfile.put("autosens_adjust_targets", SP.getBoolean(R.string.key_openapsama_autosens_adjusttargets, true));
//align with max-absorption model in AMA sensitivity
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)) {
mProfile.put("out_units", "mmol/L");
}
long now = System.currentTimeMillis();
TemporaryBasal tb = TreatmentsPlugin.getPlugin().getTempBasalFromHistory(now);
mCurrentTemp = new JSONObject();
mCurrentTemp.put("temp", "absolute");
mCurrentTemp.put("duration", MainApp.getConfigBuilder().getTempBasalRemainingMinutesFromHistory());
mCurrentTemp.put("rate", MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory());
mCurrentTemp.put("duration", tb != null ? tb.getPlannedRemainingMinutes() : 0);
mCurrentTemp.put("rate", tb != null ? tb.tempBasalConvertedToAbsolute(now, profile) : 0d);
// 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) {
mCurrentTemp.put("minutesrunning", tempBasal.getRealDuration());
}
@ -235,7 +243,7 @@ public class DetermineBasalAdapterAMAJS {
mGlucoseStatus = new JSONObject();
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);
} else {
mGlucoseStatus.put("delta", glucoseStatus.delta);
@ -248,7 +256,7 @@ public class DetermineBasalAdapterAMAJS {
mMealData.put("boluses", mealData.boluses);
mMealData.put("mealCOB", mealData.mealCOB);
if (MainApp.getConfigBuilder().isAMAModeEnabled()) {
if (MainApp.getConstraintChecker().isAutosensModeEnabled().value()) {
mAutosensData = new JSONObject();
mAutosensData.put("ratio", autosensDataRatio);
} else {
@ -259,7 +267,7 @@ public class DetermineBasalAdapterAMAJS {
public Object makeParam(JSONObject jsonObject, Context rhino, Scriptable scope) {
if(jsonObject == null) return Undefined.instance;
if (jsonObject == null) return Undefined.instance;
Object param = NativeJSON.parse(rhino, scope, jsonObject.toString(), new Callable() {
@Override

View file

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

View file

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

View file

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

View file

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

View file

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

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