Merge branch 'dev' into dev
This commit is contained in:
commit
bc2f749ef3
174 changed files with 8777 additions and 5006 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -7,3 +7,4 @@
|
||||||
*.apk
|
*.apk
|
||||||
build/
|
build/
|
||||||
.idea/
|
.idea/
|
||||||
|
app/src/main/jniLibs
|
||||||
|
|
|
@ -7,12 +7,15 @@ android:
|
||||||
components:
|
components:
|
||||||
- platform-tools
|
- platform-tools
|
||||||
- tools
|
- tools
|
||||||
- build-tools-26.0.2
|
- build-tools-27.0.2
|
||||||
- android-23
|
- android-23
|
||||||
- extra-google-m2repository
|
- extra-google-m2repository
|
||||||
- extra-android-m2repository
|
- extra-android-m2repository
|
||||||
- extra-google-google_play_services
|
- extra-google-google_play_services
|
||||||
|
|
||||||
|
before_install:
|
||||||
|
- yes | sdkmanager "platforms;android-27"
|
||||||
|
|
||||||
script:
|
script:
|
||||||
# Unit Test
|
# Unit Test
|
||||||
- ./gradlew test jacocoTestReport
|
- ./gradlew test jacocoTestReport
|
||||||
|
|
10
ISSUE_TEMPLATE.md
Normal file
10
ISSUE_TEMPLATE.md
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
Reporting bugs
|
||||||
|
--------------
|
||||||
|
- Note the precise time the problem occurred and describe the circumstances and steps that caused
|
||||||
|
the problem
|
||||||
|
- Note the Build version (found in the About dialog in the app, when pressing the three dots in the
|
||||||
|
upper-right corner).
|
||||||
|
- Obtain the app's log files, which can be found on the phone in
|
||||||
|
_/storage/emulated/0/Android/data/info.nightscout.androidaps/_
|
||||||
|
See https://github.com/MilosKozak/AndroidAPS/wiki/Accessing-logfiles
|
||||||
|
- Open an issue at https://github.com/MilosKozak/AndroidAPS/issues/new
|
|
@ -12,9 +12,10 @@ buildscript {
|
||||||
apply plugin: "com.android.application"
|
apply plugin: "com.android.application"
|
||||||
apply plugin: "io.fabric"
|
apply plugin: "io.fabric"
|
||||||
apply plugin: "jacoco-android"
|
apply plugin: "jacoco-android"
|
||||||
|
apply plugin: 'com.jakewharton.butterknife'
|
||||||
|
|
||||||
ext {
|
ext {
|
||||||
supportLibraryVersion = "23.4.0"
|
supportLibraryVersion = "27.0.2"
|
||||||
ormLiteVersion = "4.46"
|
ormLiteVersion = "4.46"
|
||||||
powermockVersion = "1.7.3"
|
powermockVersion = "1.7.3"
|
||||||
dexmakerVersion = "1.2"
|
dexmakerVersion = "1.2"
|
||||||
|
@ -47,8 +48,8 @@ def generateGitBuild = { ->
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 23
|
compileSdkVersion 27
|
||||||
buildToolsVersion "26.0.2"
|
buildToolsVersion "${supportLibraryVersion}"
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "info.nightscout.androidaps"
|
applicationId "info.nightscout.androidaps"
|
||||||
|
@ -56,7 +57,7 @@ android {
|
||||||
targetSdkVersion 23
|
targetSdkVersion 23
|
||||||
multiDexEnabled true
|
multiDexEnabled true
|
||||||
versionCode 1500
|
versionCode 1500
|
||||||
version "1.57-dev"
|
version "1.59-dev"
|
||||||
buildConfigField "String", "VERSION", '"' + version + '"'
|
buildConfigField "String", "VERSION", '"' + version + '"'
|
||||||
buildConfigField "String", "BUILDVERSION", generateGitBuild()
|
buildConfigField "String", "BUILDVERSION", generateGitBuild()
|
||||||
|
|
||||||
|
@ -65,6 +66,13 @@ android {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lintOptions {
|
lintOptions {
|
||||||
|
// TODO remove once wear dependency com.google.android.gms:play-services-wearable:7.3.0
|
||||||
|
// has been upgraded (requiring significant code changes), which currently fails release
|
||||||
|
// build with a deprecation warning
|
||||||
|
//abortOnError false
|
||||||
|
// (disabled entirely to avoid reports on the error, which would still be displayed
|
||||||
|
// and it's easy to overlook that it's ignored)
|
||||||
|
checkReleaseBuilds false
|
||||||
disable 'MissingTranslation'
|
disable 'MissingTranslation'
|
||||||
disable 'ExtraTranslation'
|
disable 'ExtraTranslation'
|
||||||
}
|
}
|
||||||
|
@ -171,6 +179,7 @@ dependencies {
|
||||||
compile("com.crashlytics.sdk.android:answers:1.3.12@aar") {
|
compile("com.crashlytics.sdk.android:answers:1.3.12@aar") {
|
||||||
transitive = true;
|
transitive = true;
|
||||||
}
|
}
|
||||||
|
compile 'MilosKozak:danars-support-lib:master@zip'
|
||||||
|
|
||||||
compile "com.android.support:appcompat-v7:${supportLibraryVersion}"
|
compile "com.android.support:appcompat-v7:${supportLibraryVersion}"
|
||||||
compile "com.android.support:support-v4:${supportLibraryVersion}"
|
compile "com.android.support:support-v4:${supportLibraryVersion}"
|
||||||
|
@ -180,6 +189,7 @@ dependencies {
|
||||||
compile "com.android.support:design:${supportLibraryVersion}"
|
compile "com.android.support:design:${supportLibraryVersion}"
|
||||||
compile "com.android.support:percent:${supportLibraryVersion}"
|
compile "com.android.support:percent:${supportLibraryVersion}"
|
||||||
compile "com.wdullaer:materialdatetimepicker:2.3.0"
|
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.squareup:otto:1.3.7"
|
||||||
compile "com.j256.ormlite:ormlite-core:${ormLiteVersion}"
|
compile "com.j256.ormlite:ormlite-core:${ormLiteVersion}"
|
||||||
compile "com.j256.ormlite:ormlite-android:${ormLiteVersion}"
|
compile "com.j256.ormlite:ormlite-android:${ormLiteVersion}"
|
||||||
|
@ -206,6 +216,11 @@ dependencies {
|
||||||
|
|
||||||
compile "net.danlew:android.joda:2.9.9.1"
|
compile "net.danlew:android.joda:2.9.9.1"
|
||||||
|
|
||||||
|
compile 'org.mozilla:rhino:1.7.7.2'
|
||||||
|
|
||||||
|
api "com.jakewharton:butterknife:8.8.1"
|
||||||
|
annotationProcessor "com.jakewharton:butterknife-compiler:8.8.1"
|
||||||
|
|
||||||
testCompile "junit:junit:4.12"
|
testCompile "junit:junit:4.12"
|
||||||
testCompile "org.json:json:20140107"
|
testCompile "org.json:json:20140107"
|
||||||
testCompile "org.mockito:mockito-core:2.7.22"
|
testCompile "org.mockito:mockito-core:2.7.22"
|
||||||
|
@ -220,3 +235,27 @@ dependencies {
|
||||||
androidTestCompile "com.google.dexmaker:dexmaker:${dexmakerVersion}"
|
androidTestCompile "com.google.dexmaker:dexmaker:${dexmakerVersion}"
|
||||||
androidTestCompile "com.google.dexmaker:dexmaker-mockito:${dexmakerVersion}"
|
androidTestCompile "com.google.dexmaker:dexmaker-mockito:${dexmakerVersion}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
task unzip(type: Copy) {
|
||||||
|
def zipPath = configurations.compile.find {it.name.startsWith("danars") }
|
||||||
|
def zipFile = file(zipPath)
|
||||||
|
def outputDir = file("${buildDir}/unpacked/dist")
|
||||||
|
|
||||||
|
from zipTree(zipFile)
|
||||||
|
into outputDir
|
||||||
|
}
|
||||||
|
|
||||||
|
task copyLibs(dependsOn: unzip, type: Copy) {
|
||||||
|
def src = file("${buildDir}/unpacked/dist/danars-support-lib-master")
|
||||||
|
def target = file("src/main/jniLibs/")
|
||||||
|
|
||||||
|
from src
|
||||||
|
into target
|
||||||
|
}
|
||||||
|
|
||||||
|
task full_clean(type: Delete) {
|
||||||
|
delete file("src/main/jniLibs")
|
||||||
|
}
|
||||||
|
|
||||||
|
clean.dependsOn full_clean
|
||||||
|
preBuild.dependsOn copyLibs
|
Binary file not shown.
|
@ -61,6 +61,7 @@
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<activity android:name=".plugins.PumpDanaRS.activities.PairingHelperActivity" />
|
<activity android:name=".plugins.PumpDanaRS.activities.PairingHelperActivity" />
|
||||||
|
<activity android:name=".HistoryBrowseActivity" />
|
||||||
|
|
||||||
<receiver
|
<receiver
|
||||||
android:name=".receivers.DataReceiver"
|
android:name=".receivers.DataReceiver"
|
||||||
|
|
61
app/src/main/assets/OpenAPSSMB/basal-set-temp.js
Normal file
61
app/src/main/assets/OpenAPSSMB/basal-set-temp.js
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
function reason(rT, msg) {
|
||||||
|
rT.reason = (rT.reason ? rT.reason + '. ' : '') + msg;
|
||||||
|
console.error(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
var tempBasalFunctions = {};
|
||||||
|
|
||||||
|
tempBasalFunctions.getMaxSafeBasal = function getMaxSafeBasal(profile) {
|
||||||
|
|
||||||
|
var max_daily_safety_multiplier = (isNaN(profile.max_daily_safety_multiplier) || profile.max_daily_safety_multiplier == null) ? 3 : profile.max_daily_safety_multiplier;
|
||||||
|
var current_basal_safety_multiplier = (isNaN(profile.current_basal_safety_multiplier) || profile.current_basal_safety_multiplier == null) ? 4 : profile.current_basal_safety_multiplier;
|
||||||
|
|
||||||
|
return Math.min(profile.max_basal, max_daily_safety_multiplier * profile.max_daily_basal, current_basal_safety_multiplier * profile.current_basal);
|
||||||
|
};
|
||||||
|
|
||||||
|
tempBasalFunctions.setTempBasal = function setTempBasal(rate, duration, profile, rT, currenttemp) {
|
||||||
|
//var maxSafeBasal = Math.min(profile.max_basal, 3 * profile.max_daily_basal, 4 * profile.current_basal);
|
||||||
|
|
||||||
|
var maxSafeBasal = tempBasalFunctions.getMaxSafeBasal(profile);
|
||||||
|
var round_basal = require('./round-basal');
|
||||||
|
|
||||||
|
if (rate < 0) {
|
||||||
|
rate = 0;
|
||||||
|
} // if >30m @ 0 required, zero temp will be extended to 30m instead
|
||||||
|
else if (rate > maxSafeBasal) {
|
||||||
|
rate = maxSafeBasal;
|
||||||
|
}
|
||||||
|
|
||||||
|
var suggestedRate = round_basal(rate, profile);
|
||||||
|
if (typeof(currenttemp) !== 'undefined' && typeof(currenttemp.duration) !== 'undefined' && typeof(currenttemp.rate) !== 'undefined' && currenttemp.duration > (duration-10) && currenttemp.duration <= 120 && suggestedRate <= currenttemp.rate * 1.2 && suggestedRate >= currenttemp.rate * 0.8) {
|
||||||
|
rT.reason += " "+currenttemp.duration+"m left and " + currenttemp.rate + " ~ req " + suggestedRate + "U/hr: no temp required";
|
||||||
|
return rT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (suggestedRate === profile.current_basal) {
|
||||||
|
if (profile.skip_neutral_temps) {
|
||||||
|
if (typeof(currenttemp) !== 'undefined' && typeof(currenttemp.duration) !== 'undefined' && currenttemp.duration > 0) {
|
||||||
|
reason(rT, 'Suggested rate is same as profile rate, a temp basal is active, canceling current temp');
|
||||||
|
rT.duration = 0;
|
||||||
|
rT.rate = 0;
|
||||||
|
return rT;
|
||||||
|
} else {
|
||||||
|
reason(rT, 'Suggested rate is same as profile rate, no temp basal is active, doing nothing');
|
||||||
|
return rT;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
reason(rT, 'Setting neutral temp basal of ' + profile.current_basal + 'U/hr');
|
||||||
|
rT.duration = duration;
|
||||||
|
rT.rate = suggestedRate;
|
||||||
|
return rT;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rT.duration = duration;
|
||||||
|
rT.rate = suggestedRate;
|
||||||
|
return rT;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = tempBasalFunctions;
|
1146
app/src/main/assets/OpenAPSSMB/determine-basal.js
Normal file
1146
app/src/main/assets/OpenAPSSMB/determine-basal.js
Normal file
File diff suppressed because it is too large
Load diff
|
@ -24,6 +24,8 @@ public class Config {
|
||||||
public static final boolean SMSCOMMUNICATORENABLED = !BuildConfig.NSCLIENTOLNY && !BuildConfig.G5UPLOADER;
|
public static final boolean SMSCOMMUNICATORENABLED = !BuildConfig.NSCLIENTOLNY && !BuildConfig.G5UPLOADER;
|
||||||
|
|
||||||
|
|
||||||
|
public static final boolean displayDeviationSlope = false;
|
||||||
|
|
||||||
public static final boolean detailedLog = true;
|
public static final boolean detailedLog = true;
|
||||||
public static final boolean logFunctionCalls = true;
|
public static final boolean logFunctionCalls = true;
|
||||||
public static final boolean logIncommingData = true;
|
public static final boolean logIncommingData = true;
|
||||||
|
|
|
@ -35,17 +35,6 @@ public class Constants {
|
||||||
public static final int CPP_MIN_TIMESHIFT = -6;
|
public static final int CPP_MIN_TIMESHIFT = -6;
|
||||||
public static final int CPP_MAX_TIMESHIFT = 23;
|
public static final int CPP_MAX_TIMESHIFT = 23;
|
||||||
|
|
||||||
// Very Hard Limits Ranges
|
|
||||||
// First value is the Lowest and second value is the Highest a Limit can define
|
|
||||||
public static final int[] VERY_HARD_LIMIT_MIN_BG = {72,180};
|
|
||||||
public static final int[] VERY_HARD_LIMIT_MAX_BG = {90,270};
|
|
||||||
public static final int[] VERY_HARD_LIMIT_TARGET_BG = {80,200};
|
|
||||||
|
|
||||||
// Very Hard Limits Ranges for Temp Targets
|
|
||||||
public static final int[] VERY_HARD_LIMIT_TEMP_MIN_BG = {72,180};
|
|
||||||
public static final int[] VERY_HARD_LIMIT_TEMP_MAX_BG = {72,270};
|
|
||||||
public static final int[] VERY_HARD_LIMIT_TEMP_TARGET_BG = {72,200};
|
|
||||||
|
|
||||||
//DanaR
|
//DanaR
|
||||||
public static final double dailyLimitWarning = 0.95d;
|
public static final double dailyLimitWarning = 0.95d;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,300 @@
|
||||||
|
package info.nightscout.androidaps;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v7.app.AppCompatActivity;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.CheckBox;
|
||||||
|
import android.widget.SeekBar;
|
||||||
|
|
||||||
|
import com.jjoe64.graphview.GraphView;
|
||||||
|
import com.squareup.otto.Subscribe;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.Calendar;
|
||||||
|
|
||||||
|
import butterknife.BindView;
|
||||||
|
import butterknife.ButterKnife;
|
||||||
|
import butterknife.OnClick;
|
||||||
|
import butterknife.OnLongClick;
|
||||||
|
import info.nightscout.androidaps.data.Profile;
|
||||||
|
import info.nightscout.androidaps.events.EventCustomCalculationFinished;
|
||||||
|
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||||
|
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||||
|
import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin;
|
||||||
|
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventAutosensCalculationFinished;
|
||||||
|
import info.nightscout.androidaps.plugins.Overview.OverviewPlugin;
|
||||||
|
import info.nightscout.androidaps.plugins.Overview.graphData.GraphData;
|
||||||
|
import info.nightscout.utils.DateUtil;
|
||||||
|
import info.nightscout.utils.SP;
|
||||||
|
|
||||||
|
public class HistoryBrowseActivity extends AppCompatActivity {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(HistoryBrowseActivity.class);
|
||||||
|
|
||||||
|
@BindView(R.id.historybrowse_date)
|
||||||
|
Button buttonDate;
|
||||||
|
@BindView(R.id.historybrowse_zoom)
|
||||||
|
Button buttonZoom;
|
||||||
|
@BindView(R.id.historyybrowse_bggraph)
|
||||||
|
GraphView bgGraph;
|
||||||
|
@BindView(R.id.historybrowse_iobgraph)
|
||||||
|
GraphView iobGraph;
|
||||||
|
@BindView(R.id.historybrowse_seekBar)
|
||||||
|
SeekBar seekBar;
|
||||||
|
|
||||||
|
@BindView(R.id.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;
|
||||||
|
|
||||||
|
private int rangeToDisplay = 24; // for graph
|
||||||
|
private long start;
|
||||||
|
|
||||||
|
IobCobCalculatorPlugin iobCobCalculatorPlugin;
|
||||||
|
|
||||||
|
EventCustomCalculationFinished eventCustomCalculationFinished = new EventCustomCalculationFinished();
|
||||||
|
|
||||||
|
public HistoryBrowseActivity() {
|
||||||
|
iobCobCalculatorPlugin = new IobCobCalculatorPlugin();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.activity_historybrowse);
|
||||||
|
|
||||||
|
ButterKnife.bind(this);
|
||||||
|
|
||||||
|
bgGraph.getGridLabelRenderer().setGridColor(MainApp.sResources.getColor(R.color.graphgrid));
|
||||||
|
bgGraph.getGridLabelRenderer().reloadStyles();
|
||||||
|
iobGraph.getGridLabelRenderer().setGridColor(MainApp.sResources.getColor(R.color.graphgrid));
|
||||||
|
iobGraph.getGridLabelRenderer().reloadStyles();
|
||||||
|
iobGraph.getGridLabelRenderer().setHorizontalLabelsVisible(false);
|
||||||
|
bgGraph.getGridLabelRenderer().setLabelVerticalWidth(50);
|
||||||
|
iobGraph.getGridLabelRenderer().setLabelVerticalWidth(50);
|
||||||
|
iobGraph.getGridLabelRenderer().setNumVerticalLabels(5);
|
||||||
|
|
||||||
|
// set start of current day
|
||||||
|
Calendar calendar = Calendar.getInstance();
|
||||||
|
calendar.setTimeInMillis(System.currentTimeMillis());
|
||||||
|
calendar.set(Calendar.MILLISECOND, 0);
|
||||||
|
calendar.set(Calendar.SECOND, 0);
|
||||||
|
calendar.set(Calendar.MINUTE, 0);
|
||||||
|
calendar.set(Calendar.HOUR_OF_DAY, 0);
|
||||||
|
start = calendar.getTimeInMillis();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
updateGUI("onResume");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@OnClick(R.id.historybrowse_start)
|
||||||
|
void onClickStart() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnClick(R.id.historybrowse_left)
|
||||||
|
void onClickLeft() {
|
||||||
|
start -= rangeToDisplay * 60 * 60 * 1000L;
|
||||||
|
updateGUI("left");
|
||||||
|
iobCobCalculatorPlugin.clearCache();
|
||||||
|
iobCobCalculatorPlugin.runCalculation("onClickLeft", start, true, eventCustomCalculationFinished);
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnClick(R.id.historybrowse_right)
|
||||||
|
void onClickRight() {
|
||||||
|
start += rangeToDisplay * 60 * 60 * 1000L;
|
||||||
|
updateGUI("right");
|
||||||
|
iobCobCalculatorPlugin.clearCache();
|
||||||
|
iobCobCalculatorPlugin.runCalculation("onClickRight", start, true, eventCustomCalculationFinished);
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnClick(R.id.historybrowse_end)
|
||||||
|
void onClickEnd() {
|
||||||
|
Calendar calendar = Calendar.getInstance();
|
||||||
|
calendar.setTimeInMillis(System.currentTimeMillis());
|
||||||
|
calendar.set(Calendar.MILLISECOND, 0);
|
||||||
|
calendar.set(Calendar.SECOND, 0);
|
||||||
|
calendar.set(Calendar.MINUTE, 0);
|
||||||
|
calendar.set(Calendar.HOUR_OF_DAY, 0);
|
||||||
|
start = calendar.getTimeInMillis();
|
||||||
|
updateGUI("resetToMidnight");
|
||||||
|
iobCobCalculatorPlugin.clearCache();
|
||||||
|
iobCobCalculatorPlugin.runCalculation("onClickEnd", start, true, eventCustomCalculationFinished);
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnClick(R.id.historybrowse_zoom)
|
||||||
|
void onClickZoom() {
|
||||||
|
rangeToDisplay += 6;
|
||||||
|
rangeToDisplay = rangeToDisplay > 24 ? 6 : rangeToDisplay;
|
||||||
|
updateGUI("rangeChange");
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnLongClick(R.id.historybrowse_zoom)
|
||||||
|
boolean onLongClickZoom() {
|
||||||
|
Calendar calendar = Calendar.getInstance();
|
||||||
|
calendar.setTimeInMillis(start);
|
||||||
|
calendar.set(Calendar.MILLISECOND, 0);
|
||||||
|
calendar.set(Calendar.SECOND, 0);
|
||||||
|
calendar.set(Calendar.MINUTE, 0);
|
||||||
|
calendar.set(Calendar.HOUR_OF_DAY, 0);
|
||||||
|
start = calendar.getTimeInMillis();
|
||||||
|
updateGUI("resetToMidnight");
|
||||||
|
iobCobCalculatorPlugin.clearCache();
|
||||||
|
iobCobCalculatorPlugin.runCalculation("onLongClickZoom", start, true, eventCustomCalculationFinished);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnClick(R.id.historybrowse_date)
|
||||||
|
void onClickDate() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@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;
|
||||||
|
if (activity != null && e.cause == eventCustomCalculationFinished) {
|
||||||
|
log.debug("EventAutosensCalculationFinished");
|
||||||
|
activity.runOnUiThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
updateGUI("EventAutosensCalculationFinished");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateGUI(String from) {
|
||||||
|
final PumpInterface pump = ConfigBuilderPlugin.getActivePump();
|
||||||
|
final Profile profile = MainApp.getConfigBuilder().getProfile();
|
||||||
|
final String units = profile.getUnits();
|
||||||
|
|
||||||
|
double lowLineSetting = SP.getDouble("low_mark", Profile.fromMgdlToUnits(OverviewPlugin.bgTargetLow, units));
|
||||||
|
double highLineSetting = SP.getDouble("high_mark", Profile.fromMgdlToUnits(OverviewPlugin.bgTargetHigh, units));
|
||||||
|
|
||||||
|
if (lowLineSetting < 1)
|
||||||
|
lowLineSetting = Profile.fromMgdlToUnits(76d, units);
|
||||||
|
if (highLineSetting < 1)
|
||||||
|
highLineSetting = Profile.fromMgdlToUnits(180d, units);
|
||||||
|
|
||||||
|
final double lowLine = lowLineSetting;
|
||||||
|
final double highLine = highLineSetting;
|
||||||
|
|
||||||
|
final boolean showPrediction = false;
|
||||||
|
|
||||||
|
int hoursToFetch;
|
||||||
|
final long toTime;
|
||||||
|
final long fromTime;
|
||||||
|
//if (showPrediction) {
|
||||||
|
//int predHours = (int) (Math.ceil(((DetermineBasalResultAMA) finalLastRun.constraintsProcessed).getLatestPredictionsTime() - System.currentTimeMillis()) / (60 * 60 * 1000));
|
||||||
|
//predHours = Math.min(2, predHours);
|
||||||
|
//predHours = Math.max(0, predHours);
|
||||||
|
//hoursToFetch = rangeToDisplay - predHours;
|
||||||
|
//toTime = calendar.getTimeInMillis() + 100000; // little bit more to avoid wrong rounding - Graphview specific
|
||||||
|
//fromTime = toTime - hoursToFetch * 60 * 60 * 1000L;
|
||||||
|
//endTime = toTime + predHours * 60 * 60 * 1000L;
|
||||||
|
//} else {
|
||||||
|
fromTime = start + 100000;
|
||||||
|
toTime = start + rangeToDisplay * 60 * 60 * 1000L;
|
||||||
|
//}
|
||||||
|
|
||||||
|
buttonDate.setText(DateUtil.dateAndTimeString(start));
|
||||||
|
buttonZoom.setText(String.valueOf(rangeToDisplay));
|
||||||
|
|
||||||
|
log.debug("Period: " + DateUtil.dateAndTimeString(fromTime) + " - " + DateUtil.dateAndTimeString(toTime));
|
||||||
|
|
||||||
|
final long pointer = System.currentTimeMillis();
|
||||||
|
|
||||||
|
// ------------------ 1st graph
|
||||||
|
|
||||||
|
final GraphData graphData = new GraphData(bgGraph, IobCobCalculatorPlugin.getPlugin());
|
||||||
|
|
||||||
|
// **** In range Area ****
|
||||||
|
graphData.addInRangeArea(fromTime, toTime, lowLine, highLine);
|
||||||
|
|
||||||
|
// **** BG ****
|
||||||
|
if (showPrediction)
|
||||||
|
//graphData.addBgReadings(fromTime, toTime, lowLine, highLine, (DetermineBasalResultAMA) finalLastRun.constraintsProcessed);
|
||||||
|
;
|
||||||
|
else
|
||||||
|
graphData.addBgReadings(fromTime, toTime, lowLine, highLine, null);
|
||||||
|
|
||||||
|
// set manual x bounds to have nice steps
|
||||||
|
graphData.formatAxis(fromTime, toTime);
|
||||||
|
|
||||||
|
// Treatments
|
||||||
|
graphData.addTreatments(fromTime, toTime);
|
||||||
|
|
||||||
|
// add basal data
|
||||||
|
if (pump.getPumpDescription().isTempBasalCapable && showBasalsCheckbox.isChecked()) {
|
||||||
|
graphData.addBasals(fromTime, toTime, lowLine / graphData.maxY / 1.2d);
|
||||||
|
}
|
||||||
|
|
||||||
|
// **** NOW line ****
|
||||||
|
graphData.addNowLine(pointer);
|
||||||
|
|
||||||
|
// ------------------ 2nd graph
|
||||||
|
|
||||||
|
final GraphData secondGraphData = new GraphData(iobGraph, iobCobCalculatorPlugin);
|
||||||
|
|
||||||
|
boolean useIobForScale = false;
|
||||||
|
boolean useCobForScale = false;
|
||||||
|
boolean useDevForScale = false;
|
||||||
|
boolean useRatioForScale = false;
|
||||||
|
|
||||||
|
if (showIobCheckbox.isChecked()) {
|
||||||
|
useIobForScale = true;
|
||||||
|
} else if (showCobCheckbox.isChecked()) {
|
||||||
|
useCobForScale = true;
|
||||||
|
} else if (showDeviationsCheckbox.isChecked()) {
|
||||||
|
useDevForScale = true;
|
||||||
|
} else if (showRatiosCheckbox.isChecked()) {
|
||||||
|
useRatioForScale = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (showIobCheckbox.isChecked())
|
||||||
|
secondGraphData.addIob(fromTime, toTime, useIobForScale, 1d);
|
||||||
|
if (showCobCheckbox.isChecked())
|
||||||
|
secondGraphData.addCob(fromTime, toTime, useCobForScale, useCobForScale ? 1d : 0.5d);
|
||||||
|
if (showDeviationsCheckbox.isChecked())
|
||||||
|
secondGraphData.addDeviations(fromTime, toTime, useDevForScale, 1d);
|
||||||
|
if (showRatiosCheckbox.isChecked())
|
||||||
|
secondGraphData.addRatio(fromTime, toTime, useRatioForScale, 1d);
|
||||||
|
|
||||||
|
// **** NOW line ****
|
||||||
|
// set manual x bounds to have nice steps
|
||||||
|
secondGraphData.formatAxis(fromTime, toTime);
|
||||||
|
secondGraphData.addNowLine(pointer);
|
||||||
|
|
||||||
|
// do GUI update
|
||||||
|
if (showIobCheckbox.isChecked() || showCobCheckbox.isChecked() || showDeviationsCheckbox.isChecked() || showRatiosCheckbox.isChecked()) {
|
||||||
|
iobGraph.setVisibility(View.VISIBLE);
|
||||||
|
} else {
|
||||||
|
iobGraph.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
// finally enforce drawing of graphs
|
||||||
|
graphData.performUpdate();
|
||||||
|
secondGraphData.performUpdate();
|
||||||
|
}
|
||||||
|
}
|
|
@ -82,7 +82,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
|
||||||
Manifest.permission.WRITE_EXTERNAL_STORAGE}, CASE_STORAGE);
|
Manifest.permission.WRITE_EXTERNAL_STORAGE}, CASE_STORAGE);
|
||||||
}
|
}
|
||||||
askForBatteryOptimizationPermission();
|
askForBatteryOptimizationPermission();
|
||||||
checkUpgradeToProfileTarget();
|
doMigrations();
|
||||||
if (Config.logFunctionCalls)
|
if (Config.logFunctionCalls)
|
||||||
log.debug("onCreate");
|
log.debug("onCreate");
|
||||||
|
|
||||||
|
@ -163,6 +163,19 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void doMigrations() {
|
||||||
|
|
||||||
|
checkUpgradeToProfileTarget();
|
||||||
|
|
||||||
|
// guarantee that the unreachable threshold is at least 30 and of type String
|
||||||
|
// Added in 1.57 at 21.01.2018
|
||||||
|
Integer unreachable_threshold = SP.getInt(R.string.key_pump_unreachable_threshold, 30);
|
||||||
|
SP.remove(R.string.key_pump_unreachable_threshold);
|
||||||
|
if (unreachable_threshold < 30) unreachable_threshold = 30;
|
||||||
|
SP.putString(R.string.key_pump_unreachable_threshold, unreachable_threshold.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void checkUpgradeToProfileTarget() { // TODO: can be removed in the future
|
private void checkUpgradeToProfileTarget() { // TODO: can be removed in the future
|
||||||
boolean oldKeyExists = SP.contains("openapsma_min_bg");
|
boolean oldKeyExists = SP.contains("openapsma_min_bg");
|
||||||
if (oldKeyExists) {
|
if (oldKeyExists) {
|
||||||
|
@ -346,6 +359,9 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
|
||||||
}
|
}
|
||||||
}, null);
|
}, null);
|
||||||
break;
|
break;
|
||||||
|
case R.id.nav_historybrowser:
|
||||||
|
startActivity(new Intent(v.getContext(), HistoryBrowseActivity.class));
|
||||||
|
break;
|
||||||
case R.id.nav_resetdb:
|
case R.id.nav_resetdb:
|
||||||
new AlertDialog.Builder(v.getContext())
|
new AlertDialog.Builder(v.getContext())
|
||||||
.setTitle(R.string.nav_resetdb)
|
.setTitle(R.string.nav_resetdb)
|
||||||
|
|
|
@ -44,9 +44,9 @@ import info.nightscout.androidaps.plugins.NSClientInternal.NSClientInternalPlugi
|
||||||
import info.nightscout.androidaps.plugins.NSClientInternal.receivers.AckAlarmReceiver;
|
import info.nightscout.androidaps.plugins.NSClientInternal.receivers.AckAlarmReceiver;
|
||||||
import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin;
|
import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin;
|
||||||
import info.nightscout.androidaps.plugins.OpenAPSMA.OpenAPSMAPlugin;
|
import info.nightscout.androidaps.plugins.OpenAPSMA.OpenAPSMAPlugin;
|
||||||
|
import info.nightscout.androidaps.plugins.OpenAPSSMB.OpenAPSSMBPlugin;
|
||||||
import info.nightscout.androidaps.plugins.Overview.OverviewPlugin;
|
import info.nightscout.androidaps.plugins.Overview.OverviewPlugin;
|
||||||
import info.nightscout.androidaps.plugins.Persistentnotification.PersistentNotificationPlugin;
|
import info.nightscout.androidaps.plugins.Persistentnotification.PersistentNotificationPlugin;
|
||||||
import info.nightscout.androidaps.plugins.ProfileCircadianPercentage.CircadianPercentageProfileFragment;
|
|
||||||
import info.nightscout.androidaps.plugins.ProfileLocal.LocalProfilePlugin;
|
import info.nightscout.androidaps.plugins.ProfileLocal.LocalProfilePlugin;
|
||||||
import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin;
|
import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin;
|
||||||
import info.nightscout.androidaps.plugins.ProfileSimple.SimpleProfilePlugin;
|
import info.nightscout.androidaps.plugins.ProfileSimple.SimpleProfilePlugin;
|
||||||
|
@ -136,11 +136,10 @@ public class MainApp extends Application {
|
||||||
if (Config.APS) pluginsList.add(LoopPlugin.getPlugin());
|
if (Config.APS) pluginsList.add(LoopPlugin.getPlugin());
|
||||||
if (Config.APS) pluginsList.add(OpenAPSMAPlugin.getPlugin());
|
if (Config.APS) pluginsList.add(OpenAPSMAPlugin.getPlugin());
|
||||||
if (Config.APS) pluginsList.add(OpenAPSAMAPlugin.getPlugin());
|
if (Config.APS) pluginsList.add(OpenAPSAMAPlugin.getPlugin());
|
||||||
|
if (Config.APS) pluginsList.add(OpenAPSSMBPlugin.getPlugin());
|
||||||
pluginsList.add(NSProfilePlugin.getPlugin());
|
pluginsList.add(NSProfilePlugin.getPlugin());
|
||||||
if (Config.OTHERPROFILES) pluginsList.add(SimpleProfilePlugin.getPlugin());
|
if (Config.OTHERPROFILES) pluginsList.add(SimpleProfilePlugin.getPlugin());
|
||||||
if (Config.OTHERPROFILES) pluginsList.add(LocalProfilePlugin.getPlugin());
|
if (Config.OTHERPROFILES) pluginsList.add(LocalProfilePlugin.getPlugin());
|
||||||
if (Config.OTHERPROFILES)
|
|
||||||
pluginsList.add(CircadianPercentageProfileFragment.getPlugin());
|
|
||||||
pluginsList.add(TreatmentsPlugin.getPlugin());
|
pluginsList.add(TreatmentsPlugin.getPlugin());
|
||||||
if (Config.SAFETY) pluginsList.add(SafetyPlugin.getPlugin());
|
if (Config.SAFETY) pluginsList.add(SafetyPlugin.getPlugin());
|
||||||
if (Config.APS) pluginsList.add(ObjectivesPlugin.getPlugin());
|
if (Config.APS) pluginsList.add(ObjectivesPlugin.getPlugin());
|
||||||
|
@ -235,6 +234,10 @@ public class MainApp extends Application {
|
||||||
return sResources.getString(id);
|
return sResources.getString(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String gs(int id, Object... args) {
|
||||||
|
return sResources.getString(id, args);
|
||||||
|
}
|
||||||
|
|
||||||
public static MainApp instance() {
|
public static MainApp instance() {
|
||||||
return sInstance;
|
return sInstance;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ import android.text.TextUtils;
|
||||||
import info.nightscout.androidaps.events.EventPreferenceChange;
|
import info.nightscout.androidaps.events.EventPreferenceChange;
|
||||||
import info.nightscout.androidaps.events.EventRefreshGui;
|
import info.nightscout.androidaps.events.EventRefreshGui;
|
||||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||||
|
import info.nightscout.androidaps.plugins.OpenAPSSMB.OpenAPSSMBPlugin;
|
||||||
import info.nightscout.androidaps.plugins.Careportal.CareportalPlugin;
|
import info.nightscout.androidaps.plugins.Careportal.CareportalPlugin;
|
||||||
import info.nightscout.androidaps.plugins.ConstraintsSafety.SafetyPlugin;
|
import info.nightscout.androidaps.plugins.ConstraintsSafety.SafetyPlugin;
|
||||||
import info.nightscout.androidaps.plugins.Insulin.InsulinOrefFreePeakPlugin;
|
import info.nightscout.androidaps.plugins.Insulin.InsulinOrefFreePeakPlugin;
|
||||||
|
@ -145,6 +146,7 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
|
||||||
addPreferencesFromResourceIfEnabled(LoopPlugin.getPlugin(), PluginBase.LOOP);
|
addPreferencesFromResourceIfEnabled(LoopPlugin.getPlugin(), PluginBase.LOOP);
|
||||||
addPreferencesFromResourceIfEnabled(OpenAPSMAPlugin.getPlugin(), PluginBase.APS);
|
addPreferencesFromResourceIfEnabled(OpenAPSMAPlugin.getPlugin(), PluginBase.APS);
|
||||||
addPreferencesFromResourceIfEnabled(OpenAPSAMAPlugin.getPlugin(), PluginBase.APS);
|
addPreferencesFromResourceIfEnabled(OpenAPSAMAPlugin.getPlugin(), PluginBase.APS);
|
||||||
|
addPreferencesFromResourceIfEnabled(OpenAPSSMBPlugin.getPlugin(), PluginBase.APS);
|
||||||
}
|
}
|
||||||
|
|
||||||
addPreferencesFromResourceIfEnabled(SensitivityAAPSPlugin.getPlugin(), PluginBase.SENSITIVITY);
|
addPreferencesFromResourceIfEnabled(SensitivityAAPSPlugin.getPlugin(), PluginBase.SENSITIVITY);
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
package info.nightscout.androidaps.Services;
|
package info.nightscout.androidaps.Services;
|
||||||
|
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.res.AssetFileDescriptor;
|
import android.content.res.AssetFileDescriptor;
|
||||||
|
import android.media.AudioManager;
|
||||||
import android.media.MediaPlayer;
|
import android.media.MediaPlayer;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
|
|
||||||
|
@ -53,7 +55,10 @@ public class AlarmSoundService extends Service {
|
||||||
log.error("Unhandled exception", e);
|
log.error("Unhandled exception", e);
|
||||||
}
|
}
|
||||||
player.setLooping(true); // Set looping
|
player.setLooping(true); // Set looping
|
||||||
|
AudioManager manager = (AudioManager)this.getSystemService(Context.AUDIO_SERVICE);
|
||||||
|
if (manager == null || !manager.isMusicActive()) {
|
||||||
player.setVolume(100, 100);
|
player.setVolume(100, 100);
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
player.prepare();
|
player.prepare();
|
||||||
|
|
|
@ -15,20 +15,22 @@ import org.slf4j.LoggerFactory;
|
||||||
import info.nightscout.androidaps.Config;
|
import info.nightscout.androidaps.Config;
|
||||||
import info.nightscout.androidaps.MainApp;
|
import info.nightscout.androidaps.MainApp;
|
||||||
import info.nightscout.androidaps.R;
|
import info.nightscout.androidaps.R;
|
||||||
|
import info.nightscout.androidaps.data.ProfileStore;
|
||||||
import info.nightscout.androidaps.db.BgReading;
|
import info.nightscout.androidaps.db.BgReading;
|
||||||
import info.nightscout.androidaps.db.CareportalEvent;
|
import info.nightscout.androidaps.db.CareportalEvent;
|
||||||
import info.nightscout.androidaps.events.EventNewBasalProfile;
|
import info.nightscout.androidaps.events.EventNewBasalProfile;
|
||||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||||
import info.nightscout.androidaps.plugins.ConstraintsObjectives.ObjectivesPlugin;
|
import info.nightscout.androidaps.plugins.ConstraintsObjectives.ObjectivesPlugin;
|
||||||
|
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSDeviceStatus;
|
||||||
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSMbg;
|
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSMbg;
|
||||||
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSgv;
|
|
||||||
import info.nightscout.androidaps.data.ProfileStore;
|
|
||||||
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSettingsStatus;
|
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSettingsStatus;
|
||||||
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
|
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSgv;
|
||||||
import info.nightscout.androidaps.plugins.Overview.OverviewPlugin;
|
import info.nightscout.androidaps.plugins.Overview.OverviewPlugin;
|
||||||
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
|
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
|
||||||
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
|
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
|
||||||
|
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
|
||||||
import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin;
|
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.PumpDanaR.activities.DanaRNSHistorySync;
|
||||||
import info.nightscout.androidaps.plugins.SmsCommunicator.events.EventNewSMS;
|
import info.nightscout.androidaps.plugins.SmsCommunicator.events.EventNewSMS;
|
||||||
import info.nightscout.androidaps.plugins.SourceDexcomG5.SourceDexcomG5Plugin;
|
import info.nightscout.androidaps.plugins.SourceDexcomG5.SourceDexcomG5Plugin;
|
||||||
|
@ -37,7 +39,6 @@ import info.nightscout.androidaps.plugins.SourceMM640g.SourceMM640gPlugin;
|
||||||
import info.nightscout.androidaps.plugins.SourceNSClient.SourceNSClientPlugin;
|
import info.nightscout.androidaps.plugins.SourceNSClient.SourceNSClientPlugin;
|
||||||
import info.nightscout.androidaps.plugins.SourceXdrip.SourceXdripPlugin;
|
import info.nightscout.androidaps.plugins.SourceXdrip.SourceXdripPlugin;
|
||||||
import info.nightscout.androidaps.receivers.DataReceiver;
|
import info.nightscout.androidaps.receivers.DataReceiver;
|
||||||
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSDeviceStatus;
|
|
||||||
import info.nightscout.utils.BundleLogger;
|
import info.nightscout.utils.BundleLogger;
|
||||||
import info.nightscout.utils.NSUpload;
|
import info.nightscout.utils.NSUpload;
|
||||||
import info.nightscout.utils.SP;
|
import info.nightscout.utils.SP;
|
||||||
|
@ -365,8 +366,10 @@ public class DataService extends IntentService {
|
||||||
String profile = bundles.getString("profile");
|
String profile = bundles.getString("profile");
|
||||||
ProfileStore profileStore = new ProfileStore(new JSONObject(profile));
|
ProfileStore profileStore = new ProfileStore(new JSONObject(profile));
|
||||||
NSProfilePlugin.storeNewProfile(profileStore);
|
NSProfilePlugin.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());
|
MainApp.bus().post(new EventNewBasalProfile());
|
||||||
|
|
||||||
if (Config.logIncommingData)
|
if (Config.logIncommingData)
|
||||||
log.debug("Received profileStore: " + activeProfile + " " + profile);
|
log.debug("Received profileStore: " + activeProfile + " " + profile);
|
||||||
} catch (JSONException e) {
|
} catch (JSONException e) {
|
||||||
|
@ -597,7 +600,8 @@ public class DataService extends IntentService {
|
||||||
if (trJson.has("eventType") && trJson.getString("eventType").equals(CareportalEvent.ANNOUNCEMENT)) {
|
if (trJson.has("eventType") && trJson.getString("eventType").equals(CareportalEvent.ANNOUNCEMENT)) {
|
||||||
long date = trJson.getLong("mills");
|
long date = trJson.getLong("mills");
|
||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
if (date > now - 15 * 60 * 1000L && trJson.has("notes")) {
|
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);
|
Notification announcement = new Notification(Notification.NSANNOUNCEMENT, trJson.getString("notes"), Notification.ANNOUNCEMENT, 60);
|
||||||
MainApp.bus().post(new EventNewNotification(announcement));
|
MainApp.bus().post(new EventNewNotification(announcement));
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ public class DetailedBolusInfo {
|
||||||
public Context context = null; // context for progress dialog
|
public Context context = null; // context for progress dialog
|
||||||
public long pumpId = 0; // id of record if comming from pump history (not a newly created treatment)
|
public long pumpId = 0; // id of record if comming from pump history (not a newly created treatment)
|
||||||
public boolean isSMB = false; // is a Super-MicroBolus
|
public boolean isSMB = false; // is a Super-MicroBolus
|
||||||
|
public long deliverAt = 0; // SMB should be delivered within 1 min from this time
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
|
@ -37,6 +38,7 @@ public class DetailedBolusInfo {
|
||||||
" carbs: " + carbs +
|
" carbs: " + carbs +
|
||||||
" isValid: " + isValid +
|
" isValid: " + isValid +
|
||||||
" carbTime: " + carbTime +
|
" carbTime: " + carbTime +
|
||||||
" isSMB: " + isSMB;
|
" isSMB: " + isSMB +
|
||||||
|
" deliverAt: " + new Date(deliverAt).toLocaleString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ public class GlucoseStatus {
|
||||||
public double avgdelta = 0d;
|
public double avgdelta = 0d;
|
||||||
public double short_avgdelta = 0d;
|
public double short_avgdelta = 0d;
|
||||||
public double long_avgdelta = 0d;
|
public double long_avgdelta = 0d;
|
||||||
|
public long date = 0L;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -133,6 +134,7 @@ public class GlucoseStatus {
|
||||||
|
|
||||||
GlucoseStatus status = new GlucoseStatus();
|
GlucoseStatus status = new GlucoseStatus();
|
||||||
status.glucose = now.value;
|
status.glucose = now.value;
|
||||||
|
status.date = now_date;
|
||||||
|
|
||||||
status.short_avgdelta = average(short_deltas);
|
status.short_avgdelta = average(short_deltas);
|
||||||
|
|
||||||
|
|
|
@ -12,4 +12,26 @@ public class Iob {
|
||||||
activityContrib += iob.activityContrib;
|
activityContrib += iob.activityContrib;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
|
||||||
|
Iob iob = (Iob) o;
|
||||||
|
|
||||||
|
if (Double.compare(iob.iobContrib, iobContrib) != 0) return false;
|
||||||
|
return Double.compare(iob.activityContrib, activityContrib) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int result;
|
||||||
|
long temp;
|
||||||
|
temp = Double.doubleToLongBits(iobContrib);
|
||||||
|
result = (int) (temp ^ (temp >>> 32));
|
||||||
|
temp = Double.doubleToLongBits(activityContrib);
|
||||||
|
result = 31 * result + (int) (temp ^ (temp >>> 32));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,8 +21,11 @@ public class IobTotal {
|
||||||
public double hightempinsulin;
|
public double hightempinsulin;
|
||||||
|
|
||||||
// oref1
|
// oref1
|
||||||
public double microBolusInsulin;
|
public long lastBolusTime;
|
||||||
public double microBolusIOB;
|
public long lastTempDate;
|
||||||
|
public int lastTempDuration;
|
||||||
|
public double lastTempRate;
|
||||||
|
public IobTotal iobWithZeroTemp;
|
||||||
|
|
||||||
public double netInsulin = 0d; // for calculations from temp basals only
|
public double netInsulin = 0d; // for calculations from temp basals only
|
||||||
public double netRatio = 0d; // net ratio at start of temp basal
|
public double netRatio = 0d; // net ratio at start of temp basal
|
||||||
|
@ -31,6 +34,23 @@ public class IobTotal {
|
||||||
|
|
||||||
long time;
|
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(long time) {
|
public IobTotal(long time) {
|
||||||
this.iob = 0d;
|
this.iob = 0d;
|
||||||
this.activity = 0d;
|
this.activity = 0d;
|
||||||
|
@ -38,8 +58,7 @@ public class IobTotal {
|
||||||
this.basaliob = 0d;
|
this.basaliob = 0d;
|
||||||
this.netbasalinsulin = 0d;
|
this.netbasalinsulin = 0d;
|
||||||
this.hightempinsulin = 0d;
|
this.hightempinsulin = 0d;
|
||||||
this.microBolusInsulin = 0d;
|
this.lastBolusTime = 0;
|
||||||
this.microBolusIOB = 0d;
|
|
||||||
this.time = time;
|
this.time = time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,8 +71,6 @@ public class IobTotal {
|
||||||
hightempinsulin += other.hightempinsulin;
|
hightempinsulin += other.hightempinsulin;
|
||||||
netInsulin += other.netInsulin;
|
netInsulin += other.netInsulin;
|
||||||
extendedBolusInsulin += other.extendedBolusInsulin;
|
extendedBolusInsulin += other.extendedBolusInsulin;
|
||||||
microBolusInsulin += other.microBolusInsulin;
|
|
||||||
microBolusIOB += other.microBolusIOB;
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,11 +79,14 @@ public class IobTotal {
|
||||||
result.iob = bolusIOB.iob + basalIob.basaliob;
|
result.iob = bolusIOB.iob + basalIob.basaliob;
|
||||||
result.activity = bolusIOB.activity + basalIob.activity;
|
result.activity = bolusIOB.activity + basalIob.activity;
|
||||||
result.bolussnooze = bolusIOB.bolussnooze;
|
result.bolussnooze = bolusIOB.bolussnooze;
|
||||||
result.basaliob = basalIob.basaliob;
|
result.basaliob = bolusIOB.basaliob + basalIob.basaliob;
|
||||||
result.netbasalinsulin = basalIob.netbasalinsulin;
|
result.netbasalinsulin = bolusIOB.netbasalinsulin + basalIob.netbasalinsulin;
|
||||||
result.hightempinsulin = basalIob.hightempinsulin;
|
result.hightempinsulin = basalIob.hightempinsulin + bolusIOB.hightempinsulin;
|
||||||
result.microBolusInsulin = bolusIOB.microBolusInsulin + basalIob.microBolusInsulin;
|
result.lastBolusTime = bolusIOB.lastBolusTime;
|
||||||
result.microBolusIOB = bolusIOB.microBolusIOB + basalIob.microBolusIOB;
|
result.lastTempDate = basalIob.lastTempDate;
|
||||||
|
result.lastTempRate = basalIob.lastTempRate;
|
||||||
|
result.lastTempDuration = basalIob.lastTempDuration;
|
||||||
|
result.iobWithZeroTemp = basalIob.iobWithZeroTemp;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,8 +97,6 @@ public class IobTotal {
|
||||||
this.basaliob = Round.roundTo(this.basaliob, 0.001);
|
this.basaliob = Round.roundTo(this.basaliob, 0.001);
|
||||||
this.netbasalinsulin = Round.roundTo(this.netbasalinsulin, 0.001);
|
this.netbasalinsulin = Round.roundTo(this.netbasalinsulin, 0.001);
|
||||||
this.hightempinsulin = Round.roundTo(this.hightempinsulin, 0.001);
|
this.hightempinsulin = Round.roundTo(this.hightempinsulin, 0.001);
|
||||||
this.microBolusInsulin = Round.roundTo(this.microBolusInsulin, 0.001);
|
|
||||||
this.microBolusIOB = Round.roundTo(this.microBolusIOB, 0.001);
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,7 +120,24 @@ public class IobTotal {
|
||||||
json.put("basaliob", basaliob);
|
json.put("basaliob", basaliob);
|
||||||
json.put("bolussnooze", bolussnooze);
|
json.put("bolussnooze", bolussnooze);
|
||||||
json.put("activity", activity);
|
json.put("activity", activity);
|
||||||
|
json.put("lastBolusTime", lastBolusTime);
|
||||||
json.put("time", DateUtil.toISOString(new Date(time)));
|
json.put("time", DateUtil.toISOString(new Date(time)));
|
||||||
|
/*
|
||||||
|
|
||||||
|
This is requested by SMB determine_basal but by based on Scott's info
|
||||||
|
it's MDT specific safety check only
|
||||||
|
It's causing rounding issues in determine_basal
|
||||||
|
|
||||||
|
JSONObject lastTemp = new JSONObject();
|
||||||
|
lastTemp.put("date", lastTempDate);
|
||||||
|
lastTemp.put("rate", lastTempRate);
|
||||||
|
lastTemp.put("duration", lastTempDuration);
|
||||||
|
json.put("lastTemp", lastTemp);
|
||||||
|
*/
|
||||||
|
if (iobWithZeroTemp != null) {
|
||||||
|
JSONObject iwzt = iobWithZeroTemp.determineBasalJson();
|
||||||
|
json.put("iobWithZeroTemp", iwzt);
|
||||||
|
}
|
||||||
} catch (JSONException e) {
|
} catch (JSONException e) {
|
||||||
log.error("Unhandled exception", e);
|
log.error("Unhandled exception", e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,4 +7,8 @@ public class MealData {
|
||||||
public double boluses = 0d;
|
public double boluses = 0d;
|
||||||
public double carbs = 0d;
|
public double carbs = 0d;
|
||||||
public double mealCOB = 0.0d;
|
public double mealCOB = 0.0d;
|
||||||
|
public double slopeFromMaxDeviation = 0;
|
||||||
|
public double slopeFromMinDeviation = 999;
|
||||||
|
public long lastBolusTime;
|
||||||
|
public long lastCarbTime = 0L;
|
||||||
}
|
}
|
||||||
|
|
|
@ -239,6 +239,7 @@ public class Profile {
|
||||||
// if pump not available (at start)
|
// if pump not available (at start)
|
||||||
// do not store converted array
|
// do not store converted array
|
||||||
basal_v = null;
|
basal_v = null;
|
||||||
|
isValidated = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -412,6 +413,8 @@ public class Profile {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getBasalList() {
|
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");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,6 +57,10 @@ public class PumpEnactResult extends Object {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PumpEnactResult percent(Integer percent) {
|
||||||
|
this.percent = percent;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
public PumpEnactResult isPercent(boolean isPercent) {
|
public PumpEnactResult isPercent(boolean isPercent) {
|
||||||
this.isPercent = isPercent;
|
this.isPercent = isPercent;
|
||||||
return this;
|
return this;
|
||||||
|
@ -111,7 +115,7 @@ public class PumpEnactResult extends Object {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Spanned toSpanned() {
|
public Spanned toSpanned() {
|
||||||
String ret = MainApp.sResources.getString(R.string.success) + ": " + success;
|
String ret = "<b>" + MainApp.sResources.getString(R.string.success) + "</b>: " + success;
|
||||||
if (queued) {
|
if (queued) {
|
||||||
ret = MainApp.sResources.getString(R.string.waitingforpumpresult);
|
ret = MainApp.sResources.getString(R.string.waitingforpumpresult);
|
||||||
} else if (enacted) {
|
} else if (enacted) {
|
||||||
|
@ -119,17 +123,20 @@ public class PumpEnactResult extends Object {
|
||||||
ret += "<br><b>" + MainApp.sResources.getString(R.string.enacted) + "</b>: " + enacted;
|
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.comment) + "</b>: " + comment +
|
||||||
"<br>" + MainApp.sResources.getString(R.string.canceltemp);
|
"<br>" + MainApp.sResources.getString(R.string.canceltemp);
|
||||||
} else if (isPercent) {
|
} else if (isPercent && percent != -1) {
|
||||||
ret += "<br><b>" + MainApp.sResources.getString(R.string.enacted) + "</b>: " + enacted;
|
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.comment) + "</b>: " + comment;
|
||||||
ret += "<br><b>" + MainApp.sResources.getString(R.string.duration) + "</b>: " + duration + " min";
|
ret += "<br><b>" + MainApp.sResources.getString(R.string.duration) + "</b>: " + duration + " min";
|
||||||
ret += "<br><b>" + MainApp.sResources.getString(R.string.percent) + "</b>: " + percent + "%";
|
ret += "<br><b>" + MainApp.sResources.getString(R.string.percent) + "</b>: " + percent + "%";
|
||||||
} else {
|
} else if (absolute != -1) {
|
||||||
ret += "<br><b>" + MainApp.sResources.getString(R.string.enacted) + "</b>: " + enacted;
|
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.comment) + "</b>: " + comment;
|
||||||
ret += "<br><b>" + MainApp.sResources.getString(R.string.duration) + "</b>: " + duration + " min";
|
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";
|
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";
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ret += "<br><b>" + MainApp.sResources.getString(R.string.comment) + "</b>: " + comment;
|
ret += "<br><b>" + MainApp.sResources.getString(R.string.comment) + "</b>: " + comment;
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,9 +82,9 @@ public class QuickWizardEntry {
|
||||||
double cob = 0d;
|
double cob = 0d;
|
||||||
AutosensData autosensData;
|
AutosensData autosensData;
|
||||||
if (_synchronized)
|
if (_synchronized)
|
||||||
autosensData = IobCobCalculatorPlugin.getLastAutosensDataSynchronized("QuickWizard COB");
|
autosensData = IobCobCalculatorPlugin.getPlugin().getLastAutosensDataSynchronized("QuickWizard COB");
|
||||||
else
|
else
|
||||||
autosensData = IobCobCalculatorPlugin.getLastAutosensData("QuickWizard COB");
|
autosensData = IobCobCalculatorPlugin.getPlugin().getLastAutosensData("QuickWizard COB");
|
||||||
|
|
||||||
if (autosensData != null && useCOB() == YES) {
|
if (autosensData != null && useCOB() == YES) {
|
||||||
cob = autosensData.cob;
|
cob = autosensData.cob;
|
||||||
|
|
|
@ -17,7 +17,6 @@ import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSgv;
|
||||||
import info.nightscout.androidaps.plugins.Overview.OverviewPlugin;
|
import info.nightscout.androidaps.plugins.Overview.OverviewPlugin;
|
||||||
import info.nightscout.androidaps.plugins.Overview.graphExtensions.DataPointWithLabelInterface;
|
import info.nightscout.androidaps.plugins.Overview.graphExtensions.DataPointWithLabelInterface;
|
||||||
import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLabelGraphSeries;
|
import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLabelGraphSeries;
|
||||||
import info.nightscout.utils.DateUtil;
|
|
||||||
import info.nightscout.utils.DecimalFormatter;
|
import info.nightscout.utils.DecimalFormatter;
|
||||||
import info.nightscout.utils.SP;
|
import info.nightscout.utils.SP;
|
||||||
|
|
||||||
|
@ -43,7 +42,11 @@ public class BgReading implements DataPointWithLabelInterface {
|
||||||
@DatabaseField
|
@DatabaseField
|
||||||
public String _id = null; // NS _id
|
public String _id = null; // NS _id
|
||||||
|
|
||||||
public boolean isPrediction = false; // true when drawing predictions as bg points
|
public boolean isCOBPrediction = false; // true when drawing predictions as bg points (COB)
|
||||||
|
public boolean isaCOBPrediction = false; // true when drawing predictions as bg points (aCOB)
|
||||||
|
public boolean isIOBPrediction = false; // true when drawing predictions as bg points (IOB)
|
||||||
|
public boolean isUAMPrediction = false; // true when drawing predictions as bg points (UAM)
|
||||||
|
public boolean isZTPrediction = false; // true when drawing predictions as bg points (ZT)
|
||||||
|
|
||||||
public BgReading() {
|
public BgReading() {
|
||||||
}
|
}
|
||||||
|
@ -184,7 +187,10 @@ public class BgReading implements DataPointWithLabelInterface {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PointsWithLabelGraphSeries.Shape getShape() {
|
public PointsWithLabelGraphSeries.Shape getShape() {
|
||||||
return PointsWithLabelGraphSeries.Shape.POINT;
|
if (isPrediction())
|
||||||
|
return PointsWithLabelGraphSeries.Shape.PREDICTION;
|
||||||
|
else
|
||||||
|
return PointsWithLabelGraphSeries.Shape.BG;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -205,7 +211,7 @@ public class BgReading implements DataPointWithLabelInterface {
|
||||||
highLine = Profile.fromMgdlToUnits(OverviewPlugin.bgTargetHigh, units);
|
highLine = Profile.fromMgdlToUnits(OverviewPlugin.bgTargetHigh, units);
|
||||||
}
|
}
|
||||||
int color = MainApp.sResources.getColor(R.color.inrange);
|
int color = MainApp.sResources.getColor(R.color.inrange);
|
||||||
if (isPrediction)
|
if (isPrediction())
|
||||||
color = MainApp.sResources.getColor(R.color.prediction);
|
color = MainApp.sResources.getColor(R.color.prediction);
|
||||||
else if (valueToUnits(units) < lowLine)
|
else if (valueToUnits(units) < lowLine)
|
||||||
color = MainApp.sResources.getColor(R.color.low);
|
color = MainApp.sResources.getColor(R.color.low);
|
||||||
|
@ -214,4 +220,23 @@ public class BgReading implements DataPointWithLabelInterface {
|
||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSecondColor() {
|
||||||
|
if (isIOBPrediction)
|
||||||
|
return MainApp.sResources.getColor(R.color.iob);
|
||||||
|
if (isCOBPrediction)
|
||||||
|
return MainApp.sResources.getColor(R.color.cob);
|
||||||
|
if (isaCOBPrediction)
|
||||||
|
return 0x80FFFFFF & MainApp.sResources.getColor(R.color.cob);
|
||||||
|
if (isUAMPrediction)
|
||||||
|
return MainApp.sResources.getColor(R.color.uam);
|
||||||
|
if (isZTPrediction)
|
||||||
|
return MainApp.sResources.getColor(R.color.zt);
|
||||||
|
return R.color.mdtp_white;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isPrediction() {
|
||||||
|
return isaCOBPrediction || isCOBPrediction || isIOBPrediction || isUAMPrediction || isZTPrediction;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import android.graphics.Color;
|
||||||
import com.j256.ormlite.field.DatabaseField;
|
import com.j256.ormlite.field.DatabaseField;
|
||||||
import com.j256.ormlite.table.DatabaseTable;
|
import com.j256.ormlite.table.DatabaseTable;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -184,13 +185,24 @@ public class CareportalEvent implements DataPointWithLabelInterface {
|
||||||
try {
|
try {
|
||||||
JSONObject object = new JSONObject(json);
|
JSONObject object = new JSONObject(json);
|
||||||
if (object.has("notes"))
|
if (object.has("notes"))
|
||||||
return object.getString("notes");
|
return StringUtils.abbreviate(object.getString("notes"), 40);
|
||||||
} catch (JSONException e) {
|
} catch (JSONException e) {
|
||||||
log.error("Unhandled exception", e);
|
log.error("Unhandled exception", e);
|
||||||
}
|
}
|
||||||
return Translator.translate(eventType);
|
return Translator.translate(eventType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getNotes() {
|
||||||
|
try {
|
||||||
|
JSONObject object = new JSONObject(json);
|
||||||
|
if (object.has("notes"))
|
||||||
|
return object.getString("notes");
|
||||||
|
} catch (JSONException e) {
|
||||||
|
log.error("Unhandled exception", e);
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getDuration() {
|
public long getDuration() {
|
||||||
try {
|
try {
|
||||||
|
@ -242,4 +254,9 @@ public class CareportalEvent implements DataPointWithLabelInterface {
|
||||||
return Color.GRAY;
|
return Color.GRAY;
|
||||||
return Color.GRAY;
|
return Color.GRAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSecondColor() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -225,9 +225,9 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
log.error("Unhandled exception", e);
|
log.error("Unhandled exception", e);
|
||||||
}
|
}
|
||||||
VirtualPumpPlugin.setFakingStatus(true);
|
VirtualPumpPlugin.setFakingStatus(true);
|
||||||
scheduleBgChange(); // trigger refresh
|
scheduleBgChange(null); // trigger refresh
|
||||||
scheduleTemporaryBasalChange();
|
scheduleTemporaryBasalChange();
|
||||||
scheduleTreatmentChange();
|
scheduleTreatmentChange(null);
|
||||||
scheduleExtendedBolusChange();
|
scheduleExtendedBolusChange();
|
||||||
scheduleTemporaryTargetChange();
|
scheduleTemporaryTargetChange();
|
||||||
scheduleCareportalEventChange();
|
scheduleCareportalEventChange();
|
||||||
|
@ -252,7 +252,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
log.error("Unhandled exception", e);
|
log.error("Unhandled exception", e);
|
||||||
}
|
}
|
||||||
scheduleTreatmentChange();
|
scheduleTreatmentChange(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void resetTempTargets() {
|
public void resetTempTargets() {
|
||||||
|
@ -358,7 +358,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
if (old == null) {
|
if (old == null) {
|
||||||
getDaoBgReadings().create(bgReading);
|
getDaoBgReadings().create(bgReading);
|
||||||
log.debug("BG: New record from: " + from + " " + bgReading.toString());
|
log.debug("BG: New record from: " + from + " " + bgReading.toString());
|
||||||
scheduleBgChange();
|
scheduleBgChange(bgReading);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (!old.isEqual(bgReading)) {
|
if (!old.isEqual(bgReading)) {
|
||||||
|
@ -366,7 +366,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
old.copyFrom(bgReading);
|
old.copyFrom(bgReading);
|
||||||
getDaoBgReadings().update(old);
|
getDaoBgReadings().update(old);
|
||||||
log.debug("BG: Updating record from: " + from + " New data: " + old.toString());
|
log.debug("BG: Updating record from: " + from + " New data: " + old.toString());
|
||||||
scheduleBgChange();
|
scheduleBgChange(bgReading);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
|
@ -384,11 +384,11 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void scheduleBgChange() {
|
private static void scheduleBgChange(@Nullable final BgReading bgReading) {
|
||||||
class PostRunnable implements Runnable {
|
class PostRunnable implements Runnable {
|
||||||
public void run() {
|
public void run() {
|
||||||
log.debug("Firing EventNewBg");
|
log.debug("Firing EventNewBg");
|
||||||
MainApp.bus().post(new EventNewBG());
|
MainApp.bus().post(new EventNewBG(bgReading));
|
||||||
scheduledBgPost = null;
|
scheduledBgPost = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -507,7 +507,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int deleteDbRequestbyMongoId(String action, String id) {
|
public void deleteDbRequestbyMongoId(String action, String id) {
|
||||||
try {
|
try {
|
||||||
QueryBuilder<DbRequest, String> queryBuilder = getDaoDbRequest().queryBuilder();
|
QueryBuilder<DbRequest, String> queryBuilder = getDaoDbRequest().queryBuilder();
|
||||||
Where where = queryBuilder.where();
|
Where where = queryBuilder.where();
|
||||||
|
@ -515,16 +515,13 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
queryBuilder.limit(10L);
|
queryBuilder.limit(10L);
|
||||||
PreparedQuery<DbRequest> preparedQuery = queryBuilder.prepare();
|
PreparedQuery<DbRequest> preparedQuery = queryBuilder.prepare();
|
||||||
List<DbRequest> dbList = getDaoDbRequest().query(preparedQuery);
|
List<DbRequest> dbList = getDaoDbRequest().query(preparedQuery);
|
||||||
if (dbList.size() != 1) {
|
|
||||||
log.error("deleteDbRequestbyMongoId query size: " + dbList.size());
|
log.error("deleteDbRequestbyMongoId query size: " + dbList.size());
|
||||||
} else {
|
for (DbRequest r : dbList) {
|
||||||
//log.debug("Treatment findTreatmentById found: " + trList.get(0).log());
|
delete(r);
|
||||||
return delete(dbList.get(0));
|
|
||||||
}
|
}
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
log.error("Unhandled exception", e);
|
log.error("Unhandled exception", e);
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deleteAllDbRequests() {
|
public void deleteAllDbRequests() {
|
||||||
|
@ -566,7 +563,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
getDaoTreatments().create(treatment);
|
getDaoTreatments().create(treatment);
|
||||||
log.debug("TREATMENT: New record from: " + Source.getString(treatment.source) + " " + treatment.toString());
|
log.debug("TREATMENT: New record from: " + Source.getString(treatment.source) + " " + treatment.toString());
|
||||||
updateEarliestDataChange(treatment.date);
|
updateEarliestDataChange(treatment.date);
|
||||||
scheduleTreatmentChange();
|
scheduleTreatmentChange(treatment);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (treatment.source == Source.NIGHTSCOUT) {
|
if (treatment.source == Source.NIGHTSCOUT) {
|
||||||
|
@ -583,7 +580,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
updateEarliestDataChange(oldDate);
|
updateEarliestDataChange(oldDate);
|
||||||
updateEarliestDataChange(old.date);
|
updateEarliestDataChange(old.date);
|
||||||
}
|
}
|
||||||
scheduleTreatmentChange();
|
scheduleTreatmentChange(treatment);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -608,7 +605,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
updateEarliestDataChange(oldDate);
|
updateEarliestDataChange(oldDate);
|
||||||
updateEarliestDataChange(old.date);
|
updateEarliestDataChange(old.date);
|
||||||
}
|
}
|
||||||
scheduleTreatmentChange();
|
scheduleTreatmentChange(treatment);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -616,14 +613,14 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
getDaoTreatments().create(treatment);
|
getDaoTreatments().create(treatment);
|
||||||
log.debug("TREATMENT: New record from: " + Source.getString(treatment.source) + " " + treatment.toString());
|
log.debug("TREATMENT: New record from: " + Source.getString(treatment.source) + " " + treatment.toString());
|
||||||
updateEarliestDataChange(treatment.date);
|
updateEarliestDataChange(treatment.date);
|
||||||
scheduleTreatmentChange();
|
scheduleTreatmentChange(treatment);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (treatment.source == Source.USER) {
|
if (treatment.source == Source.USER) {
|
||||||
getDaoTreatments().create(treatment);
|
getDaoTreatments().create(treatment);
|
||||||
log.debug("TREATMENT: New record from: " + Source.getString(treatment.source) + " " + treatment.toString());
|
log.debug("TREATMENT: New record from: " + Source.getString(treatment.source) + " " + treatment.toString());
|
||||||
updateEarliestDataChange(treatment.date);
|
updateEarliestDataChange(treatment.date);
|
||||||
scheduleTreatmentChange();
|
scheduleTreatmentChange(treatment);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
|
@ -639,7 +636,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
log.error("Unhandled exception", e);
|
log.error("Unhandled exception", e);
|
||||||
}
|
}
|
||||||
scheduleTreatmentChange();
|
scheduleTreatmentChange(treatment);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update(Treatment treatment) {
|
public void update(Treatment treatment) {
|
||||||
|
@ -649,7 +646,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
log.error("Unhandled exception", e);
|
log.error("Unhandled exception", e);
|
||||||
}
|
}
|
||||||
scheduleTreatmentChange();
|
scheduleTreatmentChange(treatment);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deleteTreatmentById(String _id) {
|
public void deleteTreatmentById(String _id) {
|
||||||
|
@ -658,12 +655,12 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
log.debug("TREATMENT: Removing Treatment record from database: " + stored.toString());
|
log.debug("TREATMENT: Removing Treatment record from database: " + stored.toString());
|
||||||
delete(stored);
|
delete(stored);
|
||||||
updateEarliestDataChange(stored.date);
|
updateEarliestDataChange(stored.date);
|
||||||
scheduleTreatmentChange();
|
scheduleTreatmentChange(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public Treatment findTreatmentById(String _id) {
|
private Treatment findTreatmentById(String _id) {
|
||||||
try {
|
try {
|
||||||
Dao<Treatment, Long> daoTreatments = getDaoTreatments();
|
Dao<Treatment, Long> daoTreatments = getDaoTreatments();
|
||||||
QueryBuilder<Treatment, Long> queryBuilder = daoTreatments.queryBuilder();
|
QueryBuilder<Treatment, Long> queryBuilder = daoTreatments.queryBuilder();
|
||||||
|
@ -695,11 +692,11 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void scheduleTreatmentChange() {
|
private static void scheduleTreatmentChange(@Nullable final Treatment treatment) {
|
||||||
class PostRunnable implements Runnable {
|
class PostRunnable implements Runnable {
|
||||||
public void run() {
|
public void run() {
|
||||||
log.debug("Firing EventTreatmentChange");
|
log.debug("Firing EventTreatmentChange");
|
||||||
MainApp.bus().post(new EventReloadTreatmentData(new EventTreatmentChange()));
|
MainApp.bus().post(new EventReloadTreatmentData(new EventTreatmentChange(treatment)));
|
||||||
if (earliestDataChange != null)
|
if (earliestDataChange != null)
|
||||||
MainApp.bus().post(new EventNewHistoryData(earliestDataChange));
|
MainApp.bus().post(new EventNewHistoryData(earliestDataChange));
|
||||||
earliestDataChange = null;
|
earliestDataChange = null;
|
||||||
|
@ -1473,7 +1470,21 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
log.error("Unhandled exception", e);
|
log.error("Unhandled exception", e);
|
||||||
}
|
}
|
||||||
return new ArrayList<CareportalEvent>();
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<CareportalEvent> getCareportalEventsFromTime(boolean ascending) {
|
||||||
|
try {
|
||||||
|
List<CareportalEvent> careportalEvents;
|
||||||
|
QueryBuilder<CareportalEvent, Long> queryBuilder = getDaoCareportalEvents().queryBuilder();
|
||||||
|
queryBuilder.orderBy("date", ascending);
|
||||||
|
PreparedQuery<CareportalEvent> preparedQuery = queryBuilder.prepare();
|
||||||
|
careportalEvents = getDaoCareportalEvents().query(preparedQuery);
|
||||||
|
return careportalEvents;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
log.error("Unhandled exception", e);
|
||||||
|
}
|
||||||
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deleteCareportalEventById(String _id) {
|
public void deleteCareportalEventById(String _id) {
|
||||||
|
|
|
@ -285,4 +285,9 @@ public class ExtendedBolus implements Interval, DataPointWithLabelInterface {
|
||||||
public int getColor() {
|
public int getColor() {
|
||||||
return Color.CYAN;
|
return Color.CYAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSecondColor() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,7 +70,7 @@ public class FoodHelper {
|
||||||
public boolean createOrUpdate(Food food) {
|
public boolean createOrUpdate(Food food) {
|
||||||
try {
|
try {
|
||||||
// find by NS _id
|
// find by NS _id
|
||||||
if (food._id != null) {
|
if (food._id != null && !food._id.equals("")) {
|
||||||
Food old;
|
Food old;
|
||||||
|
|
||||||
QueryBuilder<Food, Long> queryBuilder = getDaoFood().queryBuilder();
|
QueryBuilder<Food, Long> queryBuilder = getDaoFood().queryBuilder();
|
||||||
|
@ -90,12 +90,13 @@ public class FoodHelper {
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
}
|
|
||||||
getDaoFood().createOrUpdate(food);
|
getDaoFood().createOrUpdate(food);
|
||||||
log.debug("FOOD: New record: " + food.toString());
|
log.debug("FOOD: New record: " + food.toString());
|
||||||
scheduleFoodChange();
|
scheduleFoodChange();
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
log.error("Unhandled exception", e);
|
log.error("Unhandled exception", e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -238,6 +238,11 @@ public class ProfileSwitch implements Interval, DataPointWithLabelInterface {
|
||||||
return Color.CYAN;
|
return Color.CYAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSecondColor() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "ProfileSwitch{" +
|
return "ProfileSwitch{" +
|
||||||
"date=" + date +
|
"date=" + date +
|
||||||
|
|
|
@ -12,6 +12,7 @@ import java.util.Objects;
|
||||||
|
|
||||||
import info.nightscout.androidaps.Constants;
|
import info.nightscout.androidaps.Constants;
|
||||||
import info.nightscout.androidaps.MainApp;
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
import info.nightscout.androidaps.R;
|
||||||
import info.nightscout.androidaps.data.Iob;
|
import info.nightscout.androidaps.data.Iob;
|
||||||
import info.nightscout.androidaps.interfaces.InsulinInterface;
|
import info.nightscout.androidaps.interfaces.InsulinInterface;
|
||||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||||
|
@ -139,6 +140,9 @@ public class Treatment implements DataPointWithLabelInterface {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PointsWithLabelGraphSeries.Shape getShape() {
|
public PointsWithLabelGraphSeries.Shape getShape() {
|
||||||
|
if (isSMB)
|
||||||
|
return PointsWithLabelGraphSeries.Shape.SMB;
|
||||||
|
else
|
||||||
return PointsWithLabelGraphSeries.Shape.BOLUS;
|
return PointsWithLabelGraphSeries.Shape.BOLUS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,12 +153,19 @@ public class Treatment implements DataPointWithLabelInterface {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getColor() {
|
public int getColor() {
|
||||||
if (isValid)
|
if (isSMB)
|
||||||
|
return MainApp.sResources.getColor(R.color.tempbasal);
|
||||||
|
else if (isValid)
|
||||||
return Color.CYAN;
|
return Color.CYAN;
|
||||||
else
|
else
|
||||||
return MainApp.instance().getResources().getColor(android.R.color.holo_red_light);
|
return MainApp.instance().getResources().getColor(android.R.color.holo_red_light);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSecondColor() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setY(double y) {
|
public void setY(double y) {
|
||||||
yValue = y;
|
yValue = y;
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
package info.nightscout.androidaps.events;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 23.01.2018.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class EventAppInitialized extends Event {
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
package info.nightscout.androidaps.events;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 13.02.2018.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class EventCustomCalculationFinished extends Event {
|
||||||
|
}
|
|
@ -1,7 +1,17 @@
|
||||||
package info.nightscout.androidaps.events;
|
package info.nightscout.androidaps.events;
|
||||||
|
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.db.BgReading;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by mike on 05.06.2016.
|
* Created by mike on 05.06.2016.
|
||||||
*/
|
*/
|
||||||
public class EventNewBG extends EventLoop {
|
public class EventNewBG extends EventLoop {
|
||||||
|
@Nullable
|
||||||
|
public final BgReading bgReading;
|
||||||
|
|
||||||
|
public EventNewBG(BgReading bgReading) {
|
||||||
|
this.bgReading = bgReading;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,17 @@
|
||||||
package info.nightscout.androidaps.events;
|
package info.nightscout.androidaps.events;
|
||||||
|
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.db.Treatment;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by mike on 04.06.2016.
|
* Created by mike on 04.06.2016.
|
||||||
*/
|
*/
|
||||||
public class EventTreatmentChange extends EventLoop {
|
public class EventTreatmentChange extends EventLoop {
|
||||||
|
@Nullable
|
||||||
|
public final Treatment treatment;
|
||||||
|
|
||||||
|
public EventTreatmentChange(Treatment treatment) {
|
||||||
|
this.treatment = treatment;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,4 +4,5 @@ package info.nightscout.androidaps.interfaces;
|
||||||
* Created by mike on 20.06.2016.
|
* Created by mike on 20.06.2016.
|
||||||
*/
|
*/
|
||||||
public interface BgSourceInterface {
|
public interface BgSourceInterface {
|
||||||
|
boolean advancedFilteringSupported();
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,16 +10,16 @@ import info.nightscout.androidaps.db.Treatment;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public interface InsulinInterface {
|
public interface InsulinInterface {
|
||||||
final int FASTACTINGINSULIN = 0;
|
int FASTACTINGINSULIN = 0;
|
||||||
final int FASTACTINGINSULINPROLONGED = 1;
|
int FASTACTINGINSULINPROLONGED = 1;
|
||||||
final int OREF_RAPID_ACTING = 2;
|
int OREF_RAPID_ACTING = 2;
|
||||||
final int OREF_ULTRA_RAPID_ACTING = 3;
|
int OREF_ULTRA_RAPID_ACTING = 3;
|
||||||
final int OREF_FREE_PEAK = 4;
|
int OREF_FREE_PEAK = 4;
|
||||||
|
|
||||||
|
|
||||||
int getId();
|
int getId();
|
||||||
String getFriendlyName();
|
String getFriendlyName();
|
||||||
String getComment();
|
String getComment();
|
||||||
double getDia();
|
double getDia();
|
||||||
public Iob iobCalcForTreatment(Treatment treatment, long time, double dia);
|
Iob iobCalcForTreatment(Treatment treatment, long time, double dia);
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,4 +35,6 @@ public class PumpDescription {
|
||||||
public double basalMinimumRate = 0.04d;
|
public double basalMinimumRate = 0.04d;
|
||||||
|
|
||||||
public boolean isRefillingCapable = false;
|
public boolean isRefillingCapable = false;
|
||||||
|
|
||||||
|
public boolean storesCarbInfo = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@ public interface TreatmentsInterface {
|
||||||
|
|
||||||
List<Treatment> getTreatmentsFromHistory();
|
List<Treatment> getTreatmentsFromHistory();
|
||||||
List<Treatment> getTreatments5MinBackFromHistory(long time);
|
List<Treatment> getTreatments5MinBackFromHistory(long time);
|
||||||
|
long getLastBolusTime();
|
||||||
|
|
||||||
// real basals (not faked by extended bolus)
|
// real basals (not faked by extended bolus)
|
||||||
boolean isInHistoryRealTempBasalInProgress();
|
boolean isInHistoryRealTempBasalInProgress();
|
||||||
|
|
|
@ -137,11 +137,11 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL
|
||||||
extendedBolus.setVisibility(View.GONE);
|
extendedBolus.setVisibility(View.GONE);
|
||||||
extendedBolusCancel.setVisibility(View.GONE);
|
extendedBolusCancel.setVisibility(View.GONE);
|
||||||
} else {
|
} else {
|
||||||
if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) {
|
ExtendedBolus activeExtendedBolus = MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis());
|
||||||
|
if (activeExtendedBolus != null) {
|
||||||
extendedBolus.setVisibility(View.GONE);
|
extendedBolus.setVisibility(View.GONE);
|
||||||
extendedBolusCancel.setVisibility(View.VISIBLE);
|
extendedBolusCancel.setVisibility(View.VISIBLE);
|
||||||
ExtendedBolus running = MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis());
|
extendedBolusCancel.setText(MainApp.instance().getString(R.string.cancel) + " " + activeExtendedBolus.toString());
|
||||||
extendedBolusCancel.setText(MainApp.instance().getString(R.string.cancel) + " " + running.toString());
|
|
||||||
} else {
|
} else {
|
||||||
extendedBolus.setVisibility(View.VISIBLE);
|
extendedBolus.setVisibility(View.VISIBLE);
|
||||||
extendedBolusCancel.setVisibility(View.GONE);
|
extendedBolusCancel.setVisibility(View.GONE);
|
||||||
|
@ -153,10 +153,10 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL
|
||||||
tempBasal.setVisibility(View.GONE);
|
tempBasal.setVisibility(View.GONE);
|
||||||
tempBasalCancel.setVisibility(View.GONE);
|
tempBasalCancel.setVisibility(View.GONE);
|
||||||
} else {
|
} else {
|
||||||
if (MainApp.getConfigBuilder().isTempBasalInProgress()) {
|
final TemporaryBasal activeTemp = MainApp.getConfigBuilder().getTempBasalFromHistory(System.currentTimeMillis());
|
||||||
|
if (activeTemp != null) {
|
||||||
tempBasal.setVisibility(View.GONE);
|
tempBasal.setVisibility(View.GONE);
|
||||||
tempBasalCancel.setVisibility(View.VISIBLE);
|
tempBasalCancel.setVisibility(View.VISIBLE);
|
||||||
final TemporaryBasal activeTemp = MainApp.getConfigBuilder().getTempBasalFromHistory(System.currentTimeMillis());
|
|
||||||
tempBasalCancel.setText(MainApp.instance().getString(R.string.cancel) + " " + activeTemp.toStringShort());
|
tempBasalCancel.setText(MainApp.instance().getString(R.string.cancel) + " " + activeTemp.toStringShort());
|
||||||
} else {
|
} else {
|
||||||
tempBasal.setVisibility(View.VISIBLE);
|
tempBasal.setVisibility(View.VISIBLE);
|
||||||
|
|
|
@ -38,6 +38,7 @@ import java.text.DecimalFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import info.nightscout.androidaps.Constants;
|
import info.nightscout.androidaps.Constants;
|
||||||
import info.nightscout.androidaps.MainApp;
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
@ -45,6 +46,7 @@ import info.nightscout.androidaps.R;
|
||||||
import info.nightscout.androidaps.data.GlucoseStatus;
|
import info.nightscout.androidaps.data.GlucoseStatus;
|
||||||
import info.nightscout.androidaps.data.Profile;
|
import info.nightscout.androidaps.data.Profile;
|
||||||
import info.nightscout.androidaps.data.ProfileStore;
|
import info.nightscout.androidaps.data.ProfileStore;
|
||||||
|
import info.nightscout.androidaps.db.BgReading;
|
||||||
import info.nightscout.androidaps.db.CareportalEvent;
|
import info.nightscout.androidaps.db.CareportalEvent;
|
||||||
import info.nightscout.androidaps.db.ProfileSwitch;
|
import info.nightscout.androidaps.db.ProfileSwitch;
|
||||||
import info.nightscout.androidaps.db.Source;
|
import info.nightscout.androidaps.db.Source;
|
||||||
|
@ -407,12 +409,23 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
|
||||||
else layout.setVisibility(View.GONE);
|
else layout.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateBGforDateTime() {
|
||||||
|
long millis = eventTime.getTime() - (150 * 1000L); // 2,5 * 60 * 1000
|
||||||
|
List<BgReading> data = MainApp.getDbHelper().getBgreadingsDataFromTime(millis, true);
|
||||||
|
if ((data.size() > 0) &&
|
||||||
|
(data.get(0).date > millis - 7 * 60 * 1000L) &&
|
||||||
|
(data.get(0).date < millis + 7 * 60 * 1000L)) {
|
||||||
|
editBg.setValue(Profile.fromMgdlToUnits(data.get(0).value, profile != null ? profile.getUnits() : Constants.MGDL));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDateSet(DatePickerDialog view, int year, int monthOfYear, int dayOfMonth) {
|
public void onDateSet(DatePickerDialog view, int year, int monthOfYear, int dayOfMonth) {
|
||||||
eventTime.setYear(year - 1900);
|
eventTime.setYear(year - 1900);
|
||||||
eventTime.setMonth(monthOfYear);
|
eventTime.setMonth(monthOfYear);
|
||||||
eventTime.setDate(dayOfMonth);
|
eventTime.setDate(dayOfMonth);
|
||||||
dateButton.setText(DateUtil.dateString(eventTime));
|
dateButton.setText(DateUtil.dateString(eventTime));
|
||||||
|
updateBGforDateTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -421,6 +434,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
|
||||||
eventTime.setMinutes(minute);
|
eventTime.setMinutes(minute);
|
||||||
eventTime.setSeconds(second);
|
eventTime.setSeconds(second);
|
||||||
timeButton.setText(DateUtil.timeString(eventTime));
|
timeButton.setText(DateUtil.timeString(eventTime));
|
||||||
|
updateBGforDateTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,9 +2,12 @@ package info.nightscout.androidaps.plugins.Common;
|
||||||
|
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
|
|
||||||
|
import butterknife.Unbinder;
|
||||||
import info.nightscout.androidaps.MainApp;
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
|
||||||
abstract public class SubscriberFragment extends Fragment {
|
abstract public class SubscriberFragment extends Fragment {
|
||||||
|
protected Unbinder unbinder;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPause() {
|
public void onPause() {
|
||||||
super.onPause();
|
super.onPause();
|
||||||
|
@ -18,5 +21,12 @@ abstract public class SubscriberFragment extends Fragment {
|
||||||
updateGUI();
|
updateGUI();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override public void onDestroyView() {
|
||||||
|
super.onDestroyView();
|
||||||
|
if (unbinder != null)
|
||||||
|
unbinder.unbind();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
protected abstract void updateGUI();
|
protected abstract void updateGUI();
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,11 +23,14 @@ import info.nightscout.androidaps.data.MealData;
|
||||||
import info.nightscout.androidaps.data.Profile;
|
import info.nightscout.androidaps.data.Profile;
|
||||||
import info.nightscout.androidaps.data.ProfileIntervals;
|
import info.nightscout.androidaps.data.ProfileIntervals;
|
||||||
import info.nightscout.androidaps.data.PumpEnactResult;
|
import info.nightscout.androidaps.data.PumpEnactResult;
|
||||||
|
import info.nightscout.androidaps.db.CareportalEvent;
|
||||||
import info.nightscout.androidaps.db.ExtendedBolus;
|
import info.nightscout.androidaps.db.ExtendedBolus;
|
||||||
import info.nightscout.androidaps.db.ProfileSwitch;
|
import info.nightscout.androidaps.db.ProfileSwitch;
|
||||||
|
import info.nightscout.androidaps.db.Source;
|
||||||
import info.nightscout.androidaps.db.TempTarget;
|
import info.nightscout.androidaps.db.TempTarget;
|
||||||
import info.nightscout.androidaps.db.TemporaryBasal;
|
import info.nightscout.androidaps.db.TemporaryBasal;
|
||||||
import info.nightscout.androidaps.db.Treatment;
|
import info.nightscout.androidaps.db.Treatment;
|
||||||
|
import info.nightscout.androidaps.events.EventAppInitialized;
|
||||||
import info.nightscout.androidaps.interfaces.APSInterface;
|
import info.nightscout.androidaps.interfaces.APSInterface;
|
||||||
import info.nightscout.androidaps.interfaces.BgSourceInterface;
|
import info.nightscout.androidaps.interfaces.BgSourceInterface;
|
||||||
import info.nightscout.androidaps.interfaces.ConstraintsInterface;
|
import info.nightscout.androidaps.interfaces.ConstraintsInterface;
|
||||||
|
@ -144,6 +147,7 @@ public class ConfigBuilderPlugin implements PluginBase, ConstraintsInterface, Tr
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
pluginList = MainApp.getPluginsList();
|
pluginList = MainApp.getPluginsList();
|
||||||
loadSettings();
|
loadSettings();
|
||||||
|
MainApp.bus().post(new EventAppInitialized());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void storeSettings() {
|
public void storeSettings() {
|
||||||
|
@ -240,96 +244,90 @@ public class ConfigBuilderPlugin implements PluginBase, ConstraintsInterface, Tr
|
||||||
ArrayList<PluginBase> pluginsInCategory;
|
ArrayList<PluginBase> pluginsInCategory;
|
||||||
|
|
||||||
// PluginBase.APS
|
// PluginBase.APS
|
||||||
pluginsInCategory = MainApp.getSpecificPluginsListByInterface(APSInterface.class);
|
activeAPS = this.determineActivePlugin(APSInterface.class, PluginBase.APS);
|
||||||
activeAPS = (APSInterface) getTheOneEnabledInArray(pluginsInCategory, PluginBase.APS);
|
|
||||||
if (activeAPS != null) {
|
|
||||||
if (Config.logConfigBuilder)
|
|
||||||
log.debug("Selected APS interface: " + ((PluginBase) activeAPS).getName());
|
|
||||||
for (PluginBase p : pluginsInCategory) {
|
|
||||||
if (!p.getName().equals(((PluginBase) activeAPS).getName())) {
|
|
||||||
p.setFragmentVisible(PluginBase.APS, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// PluginBase.INSULIN
|
// PluginBase.INSULIN
|
||||||
pluginsInCategory = MainApp.getSpecificPluginsListByInterface(InsulinInterface.class);
|
activeInsulin = this.determineActivePlugin(InsulinInterface.class, PluginBase.INSULIN);
|
||||||
activeInsulin = (InsulinInterface) getTheOneEnabledInArray(pluginsInCategory, PluginBase.INSULIN);
|
|
||||||
if (Config.logConfigBuilder)
|
|
||||||
log.debug("Selected insulin interface: " + ((PluginBase) activeInsulin).getName());
|
|
||||||
for (PluginBase p : pluginsInCategory) {
|
|
||||||
if (!p.getName().equals(((PluginBase) activeInsulin).getName())) {
|
|
||||||
p.setFragmentVisible(PluginBase.INSULIN, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// PluginBase.SENSITIVITY
|
// PluginBase.SENSITIVITY
|
||||||
pluginsInCategory = MainApp.getSpecificPluginsListByInterface(SensitivityInterface.class);
|
activeSensitivity = this.determineActivePlugin(SensitivityInterface.class, PluginBase.SENSITIVITY);
|
||||||
activeSensitivity = (SensitivityInterface) getTheOneEnabledInArray(pluginsInCategory, PluginBase.SENSITIVITY);
|
|
||||||
if (Config.logConfigBuilder)
|
|
||||||
log.debug("Selected sensitivity interface: " + ((PluginBase) activeSensitivity).getName());
|
|
||||||
for (PluginBase p : pluginsInCategory) {
|
|
||||||
if (!p.getName().equals(((PluginBase) activeSensitivity).getName())) {
|
|
||||||
p.setFragmentVisible(PluginBase.SENSITIVITY, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// PluginBase.PROFILE
|
// PluginBase.PROFILE
|
||||||
pluginsInCategory = MainApp.getSpecificPluginsListByInterface(ProfileInterface.class);
|
activeProfile = this.determineActivePlugin(ProfileInterface.class, PluginBase.PROFILE);
|
||||||
activeProfile = (ProfileInterface) getTheOneEnabledInArray(pluginsInCategory, PluginBase.PROFILE);
|
|
||||||
if (Config.logConfigBuilder)
|
|
||||||
log.debug("Selected profile interface: " + ((PluginBase) activeProfile).getName());
|
|
||||||
for (PluginBase p : pluginsInCategory) {
|
|
||||||
if (!p.getName().equals(((PluginBase) activeProfile).getName())) {
|
|
||||||
p.setFragmentVisible(PluginBase.PROFILE, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// PluginBase.BGSOURCE
|
// PluginBase.BGSOURCE
|
||||||
pluginsInCategory = MainApp.getSpecificPluginsListByInterface(BgSourceInterface.class);
|
activeBgSource = this.determineActivePlugin(BgSourceInterface.class, PluginBase.BGSOURCE);
|
||||||
activeBgSource = (BgSourceInterface) getTheOneEnabledInArray(pluginsInCategory, PluginBase.BGSOURCE);
|
|
||||||
if (Config.logConfigBuilder)
|
|
||||||
log.debug("Selected bgSource interface: " + ((PluginBase) activeBgSource).getName());
|
|
||||||
for (PluginBase p : pluginsInCategory) {
|
|
||||||
if (!p.getName().equals(((PluginBase) activeBgSource).getName())) {
|
|
||||||
p.setFragmentVisible(PluginBase.BGSOURCE, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// PluginBase.PUMP
|
// PluginBase.PUMP
|
||||||
pluginsInCategory = MainApp.getSpecificPluginsList(PluginBase.PUMP);
|
pluginsInCategory = MainApp.getSpecificPluginsList(PluginBase.PUMP);
|
||||||
activePump = (PumpInterface) getTheOneEnabledInArray(pluginsInCategory, PluginBase.PUMP);
|
activePump = (PumpInterface) getTheOneEnabledInArray(pluginsInCategory, PluginBase.PUMP);
|
||||||
if (activePump == null)
|
if (activePump == null)
|
||||||
activePump = VirtualPumpPlugin.getPlugin(); // for NSClient build
|
activePump = VirtualPumpPlugin.getPlugin(); // for NSClient build
|
||||||
if (Config.logConfigBuilder)
|
this.setFragmentVisiblities(((PluginBase)activePump).getName(), pluginsInCategory, PluginBase.PUMP);
|
||||||
log.debug("Selected pump interface: " + ((PluginBase) activePump).getName());
|
|
||||||
for (PluginBase p : pluginsInCategory) {
|
|
||||||
if (!p.getName().equals(((PluginBase) activePump).getName())) {
|
|
||||||
p.setFragmentVisible(PluginBase.PUMP, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// PluginBase.LOOP
|
// PluginBase.LOOP
|
||||||
pluginsInCategory = MainApp.getSpecificPluginsList(PluginBase.LOOP);
|
activeLoop = this.determineActivePlugin(PluginBase.LOOP);
|
||||||
activeLoop = (LoopPlugin) getTheOneEnabledInArray(pluginsInCategory, PluginBase.LOOP);
|
|
||||||
if (activeLoop != null) {
|
|
||||||
if (Config.logConfigBuilder)
|
|
||||||
log.debug("Selected loop interface: " + activeLoop.getName());
|
|
||||||
for (PluginBase p : pluginsInCategory) {
|
|
||||||
if (!p.getName().equals(activeLoop.getName())) {
|
|
||||||
p.setFragmentVisible(PluginBase.LOOP, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// PluginBase.TREATMENT
|
// PluginBase.TREATMENT
|
||||||
pluginsInCategory = MainApp.getSpecificPluginsList(PluginBase.TREATMENT);
|
activeTreatments = this.determineActivePlugin(PluginBase.TREATMENT);
|
||||||
activeTreatments = (TreatmentsInterface) getTheOneEnabledInArray(pluginsInCategory, PluginBase.TREATMENT);
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* disables the visibility for all fragments of Plugins with the given PluginType
|
||||||
|
* which are not equally named to the Plugin implementing the given Plugin Interface.
|
||||||
|
*
|
||||||
|
* @param pluginInterface
|
||||||
|
* @param pluginType
|
||||||
|
* @param <T>
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private <T> T determineActivePlugin(Class<T> pluginInterface, int pluginType) {
|
||||||
|
ArrayList<PluginBase> pluginsInCategory;
|
||||||
|
pluginsInCategory = MainApp.getSpecificPluginsListByInterface(pluginInterface);
|
||||||
|
|
||||||
|
return this.determineActivePlugin(pluginsInCategory, pluginType);
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> T determineActivePlugin(int pluginType) {
|
||||||
|
ArrayList<PluginBase> pluginsInCategory;
|
||||||
|
pluginsInCategory = MainApp.getSpecificPluginsList(pluginType);
|
||||||
|
|
||||||
|
return this.determineActivePlugin(pluginsInCategory, pluginType);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* disables the visibility for all fragments of Plugins in the given pluginsInCategory
|
||||||
|
* with the given PluginType which are not equally named to the Plugin implementing the
|
||||||
|
* given Plugin Interface.
|
||||||
|
*
|
||||||
|
* TODO we are casting an interface to PluginBase, which seems to be rather odd, since
|
||||||
|
* TODO the interface is not implementing PluginBase (this is just avoiding errors through
|
||||||
|
* TODO conventions.
|
||||||
|
*
|
||||||
|
* @param pluginsInCategory
|
||||||
|
* @param pluginType
|
||||||
|
* @param <T>
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private <T> T determineActivePlugin(ArrayList<PluginBase> pluginsInCategory,
|
||||||
|
int pluginType) {
|
||||||
|
T activePlugin = (T) getTheOneEnabledInArray(pluginsInCategory, pluginType);
|
||||||
|
|
||||||
|
if (activePlugin != null) {
|
||||||
|
this.setFragmentVisiblities(((PluginBase)activePlugin).getName(),
|
||||||
|
pluginsInCategory, pluginType);
|
||||||
|
}
|
||||||
|
|
||||||
|
return activePlugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setFragmentVisiblities(String activePluginName, ArrayList<PluginBase> pluginsInCategory,
|
||||||
|
int pluginType) {
|
||||||
if (Config.logConfigBuilder)
|
if (Config.logConfigBuilder)
|
||||||
log.debug("Selected treatment interface: " + ((PluginBase) activeTreatments).getName());
|
log.debug("Selected interface: " + activePluginName);
|
||||||
for (PluginBase p : pluginsInCategory) {
|
for (PluginBase p : pluginsInCategory) {
|
||||||
if (!p.getName().equals(((PluginBase) activeTreatments).getName())) {
|
if (!p.getName().equals(activePluginName)) {
|
||||||
p.setFragmentVisible(PluginBase.TREATMENT, false);
|
p.setFragmentVisible(pluginType, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -351,33 +349,19 @@ public class ConfigBuilderPlugin implements PluginBase, ConstraintsInterface, Tr
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Ex Pump interface
|
|
||||||
*
|
|
||||||
* Config builder return itself as a pump and check constraints before it passes command to pump driver
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* expect absolute request and allow both absolute and percent response based on pump capabilities
|
* expect absolute request and allow both absolute and percent response based on pump capabilities
|
||||||
*
|
|
||||||
* @param request
|
|
||||||
* @return
|
|
||||||
* true if command is going to be executed
|
|
||||||
* false if error
|
|
||||||
*/
|
*/
|
||||||
|
public void applyAPSRequest(APSResult request, Callback callback) {
|
||||||
public boolean applyAPSRequest(APSResult request, Callback callback) {
|
|
||||||
PumpInterface pump = getActivePump();
|
PumpInterface pump = getActivePump();
|
||||||
request.rate = applyBasalConstraints(request.rate);
|
request.rate = applyBasalConstraints(request.rate);
|
||||||
PumpEnactResult result;
|
|
||||||
|
|
||||||
if (!pump.isInitialized()) {
|
if (!pump.isInitialized()) {
|
||||||
log.debug("applyAPSRequest: " + MainApp.sResources.getString(R.string.pumpNotInitialized));
|
log.debug("applyAPSRequest: " + MainApp.sResources.getString(R.string.pumpNotInitialized));
|
||||||
if (callback != null) {
|
if (callback != null) {
|
||||||
callback.result(new PumpEnactResult().comment(MainApp.sResources.getString(R.string.pumpNotInitialized)).enacted(false).success(false)).run();
|
callback.result(new PumpEnactResult().comment(MainApp.sResources.getString(R.string.pumpNotInitialized)).enacted(false).success(false)).run();
|
||||||
}
|
}
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pump.isSuspended()) {
|
if (pump.isSuspended()) {
|
||||||
|
@ -385,24 +369,24 @@ public class ConfigBuilderPlugin implements PluginBase, ConstraintsInterface, Tr
|
||||||
if (callback != null) {
|
if (callback != null) {
|
||||||
callback.result(new PumpEnactResult().comment(MainApp.sResources.getString(R.string.pumpsuspended)).enacted(false).success(false)).run();
|
callback.result(new PumpEnactResult().comment(MainApp.sResources.getString(R.string.pumpsuspended)).enacted(false).success(false)).run();
|
||||||
}
|
}
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Config.logCongigBuilderActions)
|
if (Config.logCongigBuilderActions)
|
||||||
log.debug("applyAPSRequest: " + request.toString());
|
log.debug("applyAPSRequest: " + request.toString());
|
||||||
|
|
||||||
|
if (request.tempBasalReqested) {
|
||||||
if ((request.rate == 0 && request.duration == 0) || Math.abs(request.rate - pump.getBaseBasalRate()) < pump.getPumpDescription().basalStep) {
|
if ((request.rate == 0 && request.duration == 0) || Math.abs(request.rate - pump.getBaseBasalRate()) < pump.getPumpDescription().basalStep) {
|
||||||
if (isTempBasalInProgress()) {
|
if (isTempBasalInProgress()) {
|
||||||
if (Config.logCongigBuilderActions)
|
if (Config.logCongigBuilderActions)
|
||||||
log.debug("applyAPSRequest: cancelTempBasal()");
|
log.debug("applyAPSRequest: cancelTempBasal()");
|
||||||
getCommandQueue().cancelTempBasal(false, callback);
|
getCommandQueue().cancelTempBasal(false, callback);
|
||||||
return true;
|
|
||||||
} else {
|
} else {
|
||||||
if (Config.logCongigBuilderActions)
|
if (Config.logCongigBuilderActions)
|
||||||
log.debug("applyAPSRequest: Basal set correctly");
|
log.debug("applyAPSRequest: Basal set correctly");
|
||||||
if (callback != null) {
|
if (callback != null) {
|
||||||
callback.result(new PumpEnactResult().absolute(request.rate).duration(0).enacted(false).success(true).comment("Basal set correctly")).run();
|
callback.result(new PumpEnactResult().absolute(request.rate).duration(0).enacted(false).success(true).comment("Basal set correctly")).run();
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
} else if (isTempBasalInProgress()
|
} else if (isTempBasalInProgress()
|
||||||
&& getTempBasalRemainingMinutesFromHistory() > 5
|
&& getTempBasalRemainingMinutesFromHistory() > 5
|
||||||
|
@ -412,15 +396,28 @@ public class ConfigBuilderPlugin implements PluginBase, ConstraintsInterface, Tr
|
||||||
if (callback != null) {
|
if (callback != null) {
|
||||||
callback.result(new PumpEnactResult().absolute(getTempBasalAbsoluteRateHistory()).duration(getTempBasalFromHistory(System.currentTimeMillis()).getPlannedRemainingMinutes()).enacted(false).success(true).comment("Temp basal set correctly")).run();
|
callback.result(new PumpEnactResult().absolute(getTempBasalAbsoluteRateHistory()).duration(getTempBasalFromHistory(System.currentTimeMillis()).getPlannedRemainingMinutes()).enacted(false).success(true).comment("Temp basal set correctly")).run();
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
} else {
|
} else {
|
||||||
if (Config.logCongigBuilderActions)
|
if (Config.logCongigBuilderActions)
|
||||||
log.debug("applyAPSRequest: setTempBasalAbsolute()");
|
log.debug("applyAPSRequest: setTempBasalAbsolute()");
|
||||||
getCommandQueue().tempBasalAbsolute(request.rate, request.duration, false, callback);
|
getCommandQueue().tempBasalAbsolute(request.rate, request.duration, false, callback);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (request.bolusRequested) {
|
||||||
|
long lastBolusTime = getLastBolusTime();
|
||||||
|
if (lastBolusTime != 0 && lastBolusTime + 3 * 60 * 1000 > System.currentTimeMillis()) {
|
||||||
|
log.debug("SMB requsted but still in 3 min interval");
|
||||||
|
} else {
|
||||||
|
DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo();
|
||||||
|
detailedBolusInfo.eventType = CareportalEvent.CORRECTIONBOLUS;
|
||||||
|
detailedBolusInfo.insulin = request.smb;
|
||||||
|
detailedBolusInfo.isSMB = true;
|
||||||
|
detailedBolusInfo.source = Source.USER;
|
||||||
|
detailedBolusInfo.deliverAt = request.deliverAt;
|
||||||
|
getCommandQueue().bolus(detailedBolusInfo, callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constraints interface
|
* Constraints interface
|
||||||
|
@ -596,6 +593,11 @@ public class ConfigBuilderPlugin implements PluginBase, ConstraintsInterface, Tr
|
||||||
return activeTreatments.getTreatments5MinBackFromHistory(time);
|
return activeTreatments.getTreatments5MinBackFromHistory(time);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getLastBolusTime() {
|
||||||
|
return activeTreatments.getLastBolusTime();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isInHistoryRealTempBasalInProgress() {
|
public boolean isInHistoryRealTempBasalInProgress() {
|
||||||
return activeTreatments.isInHistoryRealTempBasalInProgress();
|
return activeTreatments.isInHistoryRealTempBasalInProgress();
|
||||||
|
@ -786,10 +788,10 @@ public class ConfigBuilderPlugin implements PluginBase, ConstraintsInterface, Tr
|
||||||
return profile;
|
return profile;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Unable to determine profile, failover to default
|
// Unable to determine profile, failover to default
|
||||||
if (activeProfile.getProfile() == null)
|
if (activeProfile.getProfile() == null)
|
||||||
return null; //app not initialized
|
return null; //app not initialized
|
||||||
}
|
|
||||||
Profile defaultProfile = activeProfile.getProfile().getDefaultProfile();
|
Profile defaultProfile = activeProfile.getProfile().getDefaultProfile();
|
||||||
if (defaultProfile != null)
|
if (defaultProfile != null)
|
||||||
return defaultProfile;
|
return defaultProfile;
|
||||||
|
|
|
@ -61,7 +61,6 @@ public class FoodFragment extends SubscriberFragment {
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
try {
|
try {
|
||||||
View view = inflater.inflate(R.layout.food_fragment, container, false);
|
View view = inflater.inflate(R.layout.food_fragment, container, false);
|
||||||
|
|
||||||
filter = (EditText) view.findViewById(R.id.food_filter);
|
filter = (EditText) view.findViewById(R.id.food_filter);
|
||||||
clearFilter = (ImageView) view.findViewById(R.id.food_clearfilter);
|
clearFilter = (ImageView) view.findViewById(R.id.food_clearfilter);
|
||||||
category = new SpinnerHelper(view.findViewById(R.id.food_category));
|
category = new SpinnerHelper(view.findViewById(R.id.food_category));
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package info.nightscout.androidaps.plugins.Insulin;
|
package info.nightscout.androidaps.plugins.Insulin;
|
||||||
|
|
||||||
|
import com.squareup.otto.Bus;
|
||||||
|
|
||||||
import info.nightscout.androidaps.MainApp;
|
import info.nightscout.androidaps.MainApp;
|
||||||
import info.nightscout.androidaps.R;
|
import info.nightscout.androidaps.R;
|
||||||
import info.nightscout.androidaps.data.Iob;
|
import info.nightscout.androidaps.data.Iob;
|
||||||
|
@ -44,38 +46,53 @@ public abstract class InsulinOrefBasePlugin implements PluginBase, InsulinInterf
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Bus getBus() {
|
||||||
|
return MainApp.bus();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public double getDia() {
|
public double getDia() {
|
||||||
double dia = getUserDefinedDia();
|
double dia = getUserDefinedDia();
|
||||||
if(dia >= MIN_DIA){
|
if(dia >= MIN_DIA){
|
||||||
return dia;
|
return dia;
|
||||||
} else {
|
} else {
|
||||||
if((System.currentTimeMillis() - lastWarned) > 60*1000) {
|
sendShortDiaNotification(dia);
|
||||||
lastWarned = System.currentTimeMillis();
|
|
||||||
Notification notification = new Notification(Notification.SHORT_DIA, String.format(MainApp.sResources.getString(R.string.dia_too_short), dia, MIN_DIA), Notification.URGENT);
|
|
||||||
MainApp.bus().post(new EventNewNotification(notification));
|
|
||||||
}
|
|
||||||
return MIN_DIA;
|
return MIN_DIA;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sendShortDiaNotification(double dia) {
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNotificationPattern() {
|
||||||
|
return MainApp.sResources.getString(R.string.dia_too_short);
|
||||||
|
}
|
||||||
|
|
||||||
public double getUserDefinedDia() {
|
public double getUserDefinedDia() {
|
||||||
return MainApp.getConfigBuilder().getProfile() != null ? MainApp.getConfigBuilder().getProfile().getDia() : MIN_DIA;
|
return MainApp.getConfigBuilder().getProfile() != null ? MainApp.getConfigBuilder().getProfile().getDia() : MIN_DIA;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Iob iobCalcForTreatment(Treatment treatment, long time) {
|
||||||
|
return this.iobCalcForTreatment(treatment, time, 0d);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Iob iobCalcForTreatment(Treatment treatment, long time, double dia) {
|
public Iob iobCalcForTreatment(Treatment treatment, long time, double dia) {
|
||||||
Iob result = new Iob();
|
Iob result = new Iob();
|
||||||
|
|
||||||
int peak = getPeak();
|
int peak = getPeak();
|
||||||
|
|
||||||
|
|
||||||
if (treatment.insulin != 0d) {
|
if (treatment.insulin != 0d) {
|
||||||
|
|
||||||
long bolusTime = treatment.date;
|
long bolusTime = treatment.date;
|
||||||
double t = (time - bolusTime) / 1000d / 60d;
|
double t = (time - bolusTime) / 1000d / 60d;
|
||||||
|
|
||||||
double td = getDia()*60; //getDIA() always > 5
|
double td = getDia()*60; //getDIA() always >= MIN_DIA
|
||||||
double tp = peak;
|
double tp = peak;
|
||||||
|
|
||||||
// force the IOB to 0 if over DIA hours have passed
|
// force the IOB to 0 if over DIA hours have passed
|
||||||
|
|
|
@ -57,11 +57,15 @@ public class AutosensData {
|
||||||
public double cob = 0;
|
public double cob = 0;
|
||||||
public double bgi = 0d;
|
public double bgi = 0d;
|
||||||
public double delta = 0d;
|
public double delta = 0d;
|
||||||
|
public double avgDelta = 0d;
|
||||||
|
public double avgDeviation = 0d;
|
||||||
|
|
||||||
public double autosensRatio = 1d;
|
public double autosensRatio = 1d;
|
||||||
|
public double slopeFromMaxDeviation = 0;
|
||||||
|
public double slopeFromMinDeviation = 999;
|
||||||
|
|
||||||
public String log(long time) {
|
public String log(long time) {
|
||||||
return "AutosensData: " + new Date(time).toLocaleString() + " " + pastSensitivity + " Delta=" + delta + " Bgi=" + bgi + " Deviation=" + deviation + " Absorbed=" + absorbed + " CarbsFromBolus=" + carbsFromBolus + " COB=" + cob + " autosensRatio=" + autosensRatio;
|
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() {
|
public int minOld() {
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
package info.nightscout.androidaps.plugins.IobCobCalculator;
|
package info.nightscout.androidaps.plugins.IobCobCalculator;
|
||||||
|
|
||||||
import android.os.Handler;
|
import android.os.SystemClock;
|
||||||
import android.os.HandlerThread;
|
|
||||||
import android.os.Process;
|
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v4.util.LongSparseArray;
|
import android.support.v4.util.LongSparseArray;
|
||||||
|
|
||||||
|
@ -24,15 +22,17 @@ import info.nightscout.androidaps.data.IobTotal;
|
||||||
import info.nightscout.androidaps.data.Profile;
|
import info.nightscout.androidaps.data.Profile;
|
||||||
import info.nightscout.androidaps.db.BgReading;
|
import info.nightscout.androidaps.db.BgReading;
|
||||||
import info.nightscout.androidaps.db.TemporaryBasal;
|
import info.nightscout.androidaps.db.TemporaryBasal;
|
||||||
import info.nightscout.androidaps.db.Treatment;
|
import info.nightscout.androidaps.events.Event;
|
||||||
|
import info.nightscout.androidaps.events.EventAppInitialized;
|
||||||
import info.nightscout.androidaps.events.EventConfigBuilderChange;
|
import info.nightscout.androidaps.events.EventConfigBuilderChange;
|
||||||
import info.nightscout.androidaps.events.EventNewBG;
|
import info.nightscout.androidaps.events.EventNewBG;
|
||||||
import info.nightscout.androidaps.events.EventNewBasalProfile;
|
import info.nightscout.androidaps.events.EventNewBasalProfile;
|
||||||
import info.nightscout.androidaps.events.EventPreferenceChange;
|
import info.nightscout.androidaps.events.EventPreferenceChange;
|
||||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||||
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventAutosensCalculationFinished;
|
|
||||||
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventNewHistoryData;
|
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventNewHistoryData;
|
||||||
|
import info.nightscout.androidaps.plugins.OpenAPSSMB.OpenAPSSMBPlugin;
|
||||||
|
import info.nightscout.utils.DateUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by mike on 24.04.2017.
|
* Created by mike on 24.04.2017.
|
||||||
|
@ -41,19 +41,19 @@ import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventNewHistor
|
||||||
public class IobCobCalculatorPlugin implements PluginBase {
|
public class IobCobCalculatorPlugin implements PluginBase {
|
||||||
private static Logger log = LoggerFactory.getLogger(IobCobCalculatorPlugin.class);
|
private static Logger log = LoggerFactory.getLogger(IobCobCalculatorPlugin.class);
|
||||||
|
|
||||||
private static LongSparseArray<IobTotal> iobTable = new LongSparseArray<>(); // oldest at index 0
|
private LongSparseArray<IobTotal> iobTable = new LongSparseArray<>(); // oldest at index 0
|
||||||
private static LongSparseArray<AutosensData> autosensDataTable = new LongSparseArray<>(); // oldest at index 0
|
private LongSparseArray<AutosensData> autosensDataTable = new LongSparseArray<>(); // oldest at index 0
|
||||||
private static LongSparseArray<BasalData> basalDataTable = new LongSparseArray<>(); // oldest at index 0
|
private LongSparseArray<BasalData> basalDataTable = new LongSparseArray<>(); // oldest at index 0
|
||||||
|
|
||||||
private static volatile List<BgReading> bgReadings = null; // newest at index 0
|
private volatile List<BgReading> bgReadings = null; // newest at index 0
|
||||||
private static volatile List<BgReading> bucketed_data = null;
|
private volatile List<BgReading> bucketed_data = null;
|
||||||
|
|
||||||
private static double dia = Constants.defaultDIA;
|
private double dia = Constants.defaultDIA;
|
||||||
|
|
||||||
private static Handler sHandler = null;
|
final Object dataLock = new Object();
|
||||||
private static HandlerThread sHandlerThread = null;
|
|
||||||
|
|
||||||
private static final Object dataLock = new Object();
|
boolean stopCalculationTrigger = false;
|
||||||
|
private IobCobThread thread = null;
|
||||||
|
|
||||||
private static IobCobCalculatorPlugin plugin = null;
|
private static IobCobCalculatorPlugin plugin = null;
|
||||||
|
|
||||||
|
@ -63,11 +63,11 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
||||||
return plugin;
|
return plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static LongSparseArray<AutosensData> getAutosensDataTable() {
|
public LongSparseArray<AutosensData> getAutosensDataTable() {
|
||||||
return autosensDataTable;
|
return autosensDataTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<BgReading> getBucketedData() {
|
public List<BgReading> getBucketedData() {
|
||||||
return bucketed_data;
|
return bucketed_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,18 +131,12 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
IobCobCalculatorPlugin() {
|
public IobCobCalculatorPlugin() {
|
||||||
MainApp.bus().register(this);
|
MainApp.bus().register(this);
|
||||||
if (sHandlerThread == null) {
|
|
||||||
sHandlerThread = new HandlerThread(IobCobCalculatorPlugin.class.getSimpleName(), Process.THREAD_PRIORITY_LOWEST);
|
|
||||||
sHandlerThread.start();
|
|
||||||
sHandler = new Handler(sHandlerThread.getLooper());
|
|
||||||
}
|
|
||||||
onNewBg(new EventNewBG());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static List<BgReading> getBucketedData(long fromTime) {
|
public List<BgReading> getBucketedData(long fromTime) {
|
||||||
//log.debug("Locking getBucketedData");
|
//log.debug("Locking getBucketedData");
|
||||||
synchronized (dataLock) {
|
synchronized (dataLock) {
|
||||||
if (bucketed_data == null) {
|
if (bucketed_data == null) {
|
||||||
|
@ -160,7 +154,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int indexNewerThan(long time) {
|
private int indexNewerThan(long time) {
|
||||||
for (int index = 0; index < bucketed_data.size(); index++) {
|
for (int index = 0; index < bucketed_data.size(); index++) {
|
||||||
if (bucketed_data.get(index).date < time)
|
if (bucketed_data.get(index).date < time)
|
||||||
return index - 1;
|
return index - 1;
|
||||||
|
@ -175,14 +169,9 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
||||||
return rouded;
|
return rouded;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadBgData() {
|
void loadBgData(long start) {
|
||||||
//log.debug("Locking loadBgData");
|
bgReadings = MainApp.getDbHelper().getBgreadingsDataFromTime((long) (start - 60 * 60 * 1000L * (24 + dia)), false);
|
||||||
synchronized (dataLock) {
|
log.debug("BG data loaded. Size: " + bgReadings.size() + " Start date: " + DateUtil.dateAndTimeString(start));
|
||||||
onNewProfile(null);
|
|
||||||
bgReadings = MainApp.getDbHelper().getBgreadingsDataFromTime((long) (System.currentTimeMillis() - 60 * 60 * 1000L * (24 + dia)), false);
|
|
||||||
log.debug("BG data loaded. Size: " + bgReadings.size());
|
|
||||||
}
|
|
||||||
//log.debug("Releasing loadBgData");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isAbout5minData() {
|
private boolean isAbout5minData() {
|
||||||
|
@ -209,7 +198,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createBucketedData() {
|
void createBucketedData() {
|
||||||
if (isAbout5minData())
|
if (isAbout5minData())
|
||||||
createBucketedData5min();
|
createBucketedData5min();
|
||||||
else
|
else
|
||||||
|
@ -241,7 +230,6 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createBucketedDataRecalculated() {
|
private void createBucketedDataRecalculated() {
|
||||||
synchronized (dataLock) {
|
|
||||||
if (bgReadings == null || bgReadings.size() < 3) {
|
if (bgReadings == null || bgReadings.size() < 3) {
|
||||||
bucketed_data = null;
|
bucketed_data = null;
|
||||||
return;
|
return;
|
||||||
|
@ -271,12 +259,9 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void createBucketedData5min() {
|
private void createBucketedData5min() {
|
||||||
//log.debug("Locking createBucketedData");
|
|
||||||
synchronized (dataLock) {
|
|
||||||
if (bgReadings == null || bgReadings.size() < 3) {
|
if (bgReadings == null || bgReadings.size() < 3) {
|
||||||
bucketed_data = null;
|
bucketed_data = null;
|
||||||
return;
|
return;
|
||||||
|
@ -337,128 +322,6 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
||||||
}
|
}
|
||||||
log.debug("Bucketed data created. Size: " + bucketed_data.size());
|
log.debug("Bucketed data created. Size: " + bucketed_data.size());
|
||||||
}
|
}
|
||||||
//log.debug("Releasing createBucketedData");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void calculateSensitivityData() {
|
|
||||||
if (MainApp.getConfigBuilder() == null)
|
|
||||||
return; // app still initializing
|
|
||||||
if (MainApp.getConfigBuilder().getProfile() == null)
|
|
||||||
return; // app still initializing
|
|
||||||
//log.debug("Locking calculateSensitivityData");
|
|
||||||
long oldestTimeWithData = oldestDataAvailable();
|
|
||||||
|
|
||||||
synchronized (dataLock) {
|
|
||||||
|
|
||||||
if (bucketed_data == null || bucketed_data.size() < 3) {
|
|
||||||
log.debug("calculateSensitivityData: No bucketed data available");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
long prevDataTime = 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--) {
|
|
||||||
// check if data already exists
|
|
||||||
long bgTime = bucketed_data.get(i).date;
|
|
||||||
bgTime = roundUpTime(bgTime);
|
|
||||||
if (bgTime > System.currentTimeMillis())
|
|
||||||
continue;
|
|
||||||
Profile profile = MainApp.getConfigBuilder().getProfile(bgTime);
|
|
||||||
|
|
||||||
AutosensData existing;
|
|
||||||
if ((existing = autosensDataTable.get(bgTime)) != null) {
|
|
||||||
previous = existing;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (profile.getIsf(bgTime) == null)
|
|
||||||
return; // profile not set yet
|
|
||||||
|
|
||||||
double sens = Profile.toMgdl(profile.getIsf(bgTime), profile.getUnits());
|
|
||||||
|
|
||||||
AutosensData autosensData = new AutosensData();
|
|
||||||
autosensData.time = bgTime;
|
|
||||||
if (previous != null)
|
|
||||||
autosensData.activeCarbsList = new ArrayList<>(previous.activeCarbsList);
|
|
||||||
else
|
|
||||||
autosensData.activeCarbsList = new ArrayList<>();
|
|
||||||
|
|
||||||
//console.error(bgTime , bucketed_data[i].glucose);
|
|
||||||
double bg;
|
|
||||||
double avgDelta;
|
|
||||||
double delta;
|
|
||||||
bg = bucketed_data.get(i).value;
|
|
||||||
if (bg < 39 || bucketed_data.get(i + 3).value < 39) {
|
|
||||||
log.error("! value < 39");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
delta = (bg - bucketed_data.get(i + 1).value);
|
|
||||||
|
|
||||||
IobTotal iob = calculateFromTreatmentsAndTemps(bgTime);
|
|
||||||
|
|
||||||
double bgi = -iob.activity * sens * 5;
|
|
||||||
double deviation = delta - bgi;
|
|
||||||
|
|
||||||
List<Treatment> recentTreatments = MainApp.getConfigBuilder().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)));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// if we are absorbing carbs
|
|
||||||
if (previous != null && previous.cob > 0) {
|
|
||||||
// calculate sum of min carb impact from all active treatments
|
|
||||||
double totalMinCarbsImpact = 0d;
|
|
||||||
for (int ii = 0; ii < autosensData.activeCarbsList.size(); ++ii) {
|
|
||||||
AutosensData.CarbsInPast c = autosensData.activeCarbsList.get(ii);
|
|
||||||
totalMinCarbsImpact += c.min5minCarbImpact;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
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.removeOldCarbs(bgTime);
|
|
||||||
autosensData.cob += autosensData.carbsFromBolus;
|
|
||||||
autosensData.deviation = deviation;
|
|
||||||
autosensData.bgi = bgi;
|
|
||||||
autosensData.delta = delta;
|
|
||||||
|
|
||||||
// calculate autosens only without COB
|
|
||||||
if (autosensData.cob <= 0) {
|
|
||||||
if (Math.abs(deviation) < Constants.DEVIATION_TO_BE_EQUAL) {
|
|
||||||
autosensData.pastSensitivity += "=";
|
|
||||||
autosensData.nonEqualDeviation = true;
|
|
||||||
} else if (deviation > 0) {
|
|
||||||
autosensData.pastSensitivity += "+";
|
|
||||||
autosensData.nonEqualDeviation = true;
|
|
||||||
} else {
|
|
||||||
autosensData.pastSensitivity += "-";
|
|
||||||
autosensData.nonEqualDeviation = true;
|
|
||||||
}
|
|
||||||
autosensData.nonCarbsDeviation = true;
|
|
||||||
} else {
|
|
||||||
autosensData.pastSensitivity += "C";
|
|
||||||
}
|
|
||||||
//log.debug("TIME: " + new Date(bgTime).toString() + " BG: " + bg + " SENS: " + sens + " DELTA: " + delta + " AVGDELTA: " + avgDelta + " IOB: " + iob.iob + " ACTIVITY: " + iob.activity + " BGI: " + bgi + " DEVIATION: " + deviation);
|
|
||||||
|
|
||||||
previous = autosensData;
|
|
||||||
autosensDataTable.put(bgTime, autosensData);
|
|
||||||
autosensData.autosensRatio = detectSensitivity(oldestTimeWithData, bgTime).ratio;
|
|
||||||
if (Config.logAutosensData)
|
|
||||||
log.debug(autosensData.log(bgTime));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MainApp.bus().post(new EventAutosensCalculationFinished());
|
|
||||||
//log.debug("Releasing calculateSensitivityData");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static long oldestDataAvailable() {
|
public static long oldestDataAvailable() {
|
||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
|
@ -469,13 +332,13 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
||||||
return getBGDataFrom;
|
return getBGDataFrom;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IobTotal calculateFromTreatmentsAndTempsSynchronized(long time) {
|
public IobTotal calculateFromTreatmentsAndTempsSynchronized(long time) {
|
||||||
synchronized (dataLock) {
|
synchronized (dataLock) {
|
||||||
return calculateFromTreatmentsAndTemps(time);
|
return calculateFromTreatmentsAndTemps(time);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IobTotal calculateFromTreatmentsAndTemps(long time) {
|
public IobTotal calculateFromTreatmentsAndTemps(long time) {
|
||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
time = roundUpTime(time);
|
time = roundUpTime(time);
|
||||||
if (time < now && iobTable.get(time) != null) {
|
if (time < now && iobTable.get(time) != null) {
|
||||||
|
@ -486,6 +349,21 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
||||||
}
|
}
|
||||||
IobTotal bolusIob = MainApp.getConfigBuilder().getCalculationToTimeTreatments(time).round();
|
IobTotal bolusIob = MainApp.getConfigBuilder().getCalculationToTimeTreatments(time).round();
|
||||||
IobTotal basalIob = MainApp.getConfigBuilder().getCalculationToTimeTempBasals(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;
|
||||||
|
if (t.date < time) {
|
||||||
|
IobTotal calc = t.iobCalc(time);
|
||||||
|
basalIobWithZeroTemp.plus(calc);
|
||||||
|
}
|
||||||
|
|
||||||
|
basalIob.iobWithZeroTemp = basalIobWithZeroTemp;
|
||||||
|
}
|
||||||
|
|
||||||
IobTotal iobTotal = IobTotal.combine(bolusIob, basalIob).round();
|
IobTotal iobTotal = IobTotal.combine(bolusIob, basalIob).round();
|
||||||
if (time < System.currentTimeMillis()) {
|
if (time < System.currentTimeMillis()) {
|
||||||
|
@ -495,7 +373,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private static Long findPreviousTimeFromBucketedData(long time) {
|
private Long findPreviousTimeFromBucketedData(long time) {
|
||||||
if (bucketed_data == null)
|
if (bucketed_data == null)
|
||||||
return null;
|
return null;
|
||||||
for (int index = 0; index < bucketed_data.size(); index++) {
|
for (int index = 0; index < bucketed_data.size(); index++) {
|
||||||
|
@ -505,7 +383,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BasalData getBasalData(long time) {
|
public BasalData getBasalData(long time) {
|
||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
time = roundUpTime(time);
|
time = roundUpTime(time);
|
||||||
BasalData retval = basalDataTable.get(time);
|
BasalData retval = basalDataTable.get(time);
|
||||||
|
@ -531,7 +409,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static AutosensData getAutosensData(long time) {
|
public AutosensData getAutosensData(long time) {
|
||||||
synchronized (dataLock) {
|
synchronized (dataLock) {
|
||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
if (time > now)
|
if (time > now)
|
||||||
|
@ -556,7 +434,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static AutosensData getLastAutosensDataSynchronized(String reason) {
|
public AutosensData getLastAutosensDataSynchronized(String reason) {
|
||||||
synchronized (dataLock) {
|
synchronized (dataLock) {
|
||||||
return getLastAutosensData(reason);
|
return getLastAutosensData(reason);
|
||||||
}
|
}
|
||||||
|
@ -564,7 +442,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
||||||
|
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static AutosensData getLastAutosensData(String reason) {
|
public AutosensData getLastAutosensData(String reason) {
|
||||||
if (autosensDataTable.size() < 1) {
|
if (autosensDataTable.size() < 1) {
|
||||||
log.debug("AUTOSENSDATA null: autosensDataTable empty (" + reason + ")");
|
log.debug("AUTOSENSDATA null: autosensDataTable empty (" + reason + ")");
|
||||||
return null;
|
return null;
|
||||||
|
@ -580,16 +458,16 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (data.time < System.currentTimeMillis() - 11 * 60 * 1000) {
|
if (data.time < System.currentTimeMillis() - 11 * 60 * 1000) {
|
||||||
log.debug("AUTOSENSDATA null: data is old (" + reason + ")");
|
log.debug("AUTOSENSDATA null: data is old (" + reason + ") size()=" + autosensDataTable.size() + " lastdata=" + DateUtil.dateAndTimeString(data.time));
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
if (data == null)
|
if (data == null)
|
||||||
log.debug("AUTOSENSDATA null: data == null (" + " " + reason + ")");
|
log.debug("AUTOSENSDATA null: data == null (" + " " + reason + ") size()=" + autosensDataTable.size() + " lastdata=" + DateUtil.dateAndTimeString(data.time));
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IobTotal[] calculateIobArrayInDia() {
|
public IobTotal[] calculateIobArrayInDia() {
|
||||||
Profile profile = MainApp.getConfigBuilder().getProfile();
|
Profile profile = MainApp.getConfigBuilder().getProfile();
|
||||||
// predict IOB out to DIA plus 30m
|
// predict IOB out to DIA plus 30m
|
||||||
long time = System.currentTimeMillis();
|
long time = System.currentTimeMillis();
|
||||||
|
@ -606,13 +484,30 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static AutosensResult detectSensitivityWithLock(long fromTime, long toTime) {
|
public IobTotal[] calculateIobArrayForSMB() {
|
||||||
|
Profile profile = MainApp.getConfigBuilder().getProfile();
|
||||||
|
// predict IOB out to DIA plus 30m
|
||||||
|
long time = System.currentTimeMillis();
|
||||||
|
time = roundUpTime(time);
|
||||||
|
int len = (4 * 60) / 5;
|
||||||
|
IobTotal[] array = new IobTotal[len];
|
||||||
|
int pos = 0;
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
long t = time + i * 5 * 60000;
|
||||||
|
IobTotal iob = calculateFromTreatmentsAndTempsSynchronized(t);
|
||||||
|
array[pos] = iob;
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AutosensResult detectSensitivityWithLock(long fromTime, long toTime) {
|
||||||
synchronized (dataLock) {
|
synchronized (dataLock) {
|
||||||
return detectSensitivity(fromTime, toTime);
|
return detectSensitivity(fromTime, toTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static AutosensResult detectSensitivity(long fromTime, long toTime) {
|
static AutosensResult detectSensitivity(long fromTime, long toTime) {
|
||||||
return ConfigBuilderPlugin.getActiveSensitivity().detectSensitivity(fromTime, toTime);
|
return ConfigBuilderPlugin.getActiveSensitivity().detectSensitivity(fromTime, toTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -625,19 +520,49 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void onNewBg(EventNewBG ev) {
|
public void onEventAppInitialized(EventAppInitialized ev) {
|
||||||
sHandler.post(new Runnable() {
|
if (this != getPlugin()) {
|
||||||
@Override
|
log.debug("Ignoring event for non default instance");
|
||||||
public void run() {
|
return;
|
||||||
loadBgData();
|
}
|
||||||
createBucketedData();
|
runCalculation("onEventAppInitialized", System.currentTimeMillis(), true, ev);
|
||||||
calculateSensitivityData();
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onEventNewBG(EventNewBG ev) {
|
||||||
|
if (this != getPlugin()) {
|
||||||
|
log.debug("Ignoring event for non default instance");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
stopCalculation("onEventNewBG");
|
||||||
|
runCalculation("onEventNewBG", System.currentTimeMillis(), true, ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void stopCalculation(String from) {
|
||||||
|
if (thread != null && thread.getState() != Thread.State.TERMINATED) {
|
||||||
|
stopCalculationTrigger = true;
|
||||||
|
log.debug("Stopping calculation thread: " + from);
|
||||||
|
while (thread.getState() != Thread.State.TERMINATED) {
|
||||||
|
SystemClock.sleep(100);
|
||||||
|
}
|
||||||
|
log.debug("Calculation thread stopped: " + from);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void runCalculation(String from, long start, boolean bgDataReload, Event cause) {
|
||||||
|
log.debug("Starting calculation thread: " + from);
|
||||||
|
if (thread == null || thread.getState() == Thread.State.TERMINATED) {
|
||||||
|
thread = new IobCobThread(this, from, start, bgDataReload, cause);
|
||||||
|
thread.start();
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void onNewProfile(EventNewBasalProfile ev) {
|
public void onNewProfile(EventNewBasalProfile ev) {
|
||||||
|
if (this != getPlugin()) {
|
||||||
|
log.debug("Ignoring event for non default instance");
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (MainApp.getConfigBuilder() == null)
|
if (MainApp.getConfigBuilder() == null)
|
||||||
return; // app still initializing
|
return; // app still initializing
|
||||||
Profile profile = MainApp.getConfigBuilder().getProfile();
|
Profile profile = MainApp.getConfigBuilder().getProfile();
|
||||||
|
@ -647,64 +572,65 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
||||||
if (ev == null) { // on init no need of reset
|
if (ev == null) { // on init no need of reset
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
stopCalculation("onNewProfile");
|
||||||
synchronized (dataLock) {
|
synchronized (dataLock) {
|
||||||
log.debug("Invalidating cached data because of new profile. IOB: " + iobTable.size() + " Autosens: " + autosensDataTable.size() + " records");
|
log.debug("Invalidating cached data because of new profile. IOB: " + iobTable.size() + " Autosens: " + autosensDataTable.size() + " records");
|
||||||
iobTable = new LongSparseArray<>();
|
iobTable = new LongSparseArray<>();
|
||||||
autosensDataTable = new LongSparseArray<>();
|
autosensDataTable = new LongSparseArray<>();
|
||||||
}
|
}
|
||||||
sHandler.post(new Runnable() {
|
runCalculation("onNewProfile", System.currentTimeMillis(), false, ev);
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
calculateSensitivityData();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void onStatusEvent(EventPreferenceChange ev) {
|
public void onEventPreferenceChange(EventPreferenceChange ev) {
|
||||||
|
if (this != getPlugin()) {
|
||||||
|
log.debug("Ignoring event for non default instance");
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (ev.isChanged(R.string.key_openapsama_autosens_period) ||
|
if (ev.isChanged(R.string.key_openapsama_autosens_period) ||
|
||||||
ev.isChanged(R.string.key_age) ||
|
ev.isChanged(R.string.key_age) ||
|
||||||
ev.isChanged(R.string.key_absorption_maxtime)
|
ev.isChanged(R.string.key_absorption_maxtime)
|
||||||
) {
|
) {
|
||||||
|
stopCalculation("onEventPreferenceChange");
|
||||||
synchronized (dataLock) {
|
synchronized (dataLock) {
|
||||||
log.debug("Invalidating cached data because of preference change. IOB: " + iobTable.size() + " Autosens: " + autosensDataTable.size() + " records");
|
log.debug("Invalidating cached data because of preference change. IOB: " + iobTable.size() + " Autosens: " + autosensDataTable.size() + " records");
|
||||||
iobTable = new LongSparseArray<>();
|
iobTable = new LongSparseArray<>();
|
||||||
autosensDataTable = new LongSparseArray<>();
|
autosensDataTable = new LongSparseArray<>();
|
||||||
}
|
}
|
||||||
sHandler.post(new Runnable() {
|
runCalculation("onEventPreferenceChange", System.currentTimeMillis(), false, ev);
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
calculateSensitivityData();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void onStatusEvent(EventConfigBuilderChange ev) {
|
public void onEventConfigBuilderChange(EventConfigBuilderChange ev) {
|
||||||
|
if (this != getPlugin()) {
|
||||||
|
log.debug("Ignoring event for non default instance");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
stopCalculation("onEventConfigBuilderChange");
|
||||||
synchronized (dataLock) {
|
synchronized (dataLock) {
|
||||||
log.debug("Invalidating cached data because of configuration change. IOB: " + iobTable.size() + " Autosens: " + autosensDataTable.size() + " records");
|
log.debug("Invalidating cached data because of configuration change. IOB: " + iobTable.size() + " Autosens: " + autosensDataTable.size() + " records");
|
||||||
iobTable = new LongSparseArray<>();
|
iobTable = new LongSparseArray<>();
|
||||||
autosensDataTable = new LongSparseArray<>();
|
autosensDataTable = new LongSparseArray<>();
|
||||||
}
|
}
|
||||||
sHandler.post(new Runnable() {
|
runCalculation("onEventConfigBuilderChange", System.currentTimeMillis(), false, ev);
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
calculateSensitivityData();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// When historical data is changed (comming from NS etc) finished calculations after this date must be invalidated
|
// When historical data is changed (comming from NS etc) finished calculations after this date must be invalidated
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void onNewHistoryData(EventNewHistoryData ev) {
|
public void onEventNewHistoryData(EventNewHistoryData ev) {
|
||||||
|
if (this != getPlugin()) {
|
||||||
|
log.debug("Ignoring event for non default instance");
|
||||||
|
return;
|
||||||
|
}
|
||||||
//log.debug("Locking onNewHistoryData");
|
//log.debug("Locking onNewHistoryData");
|
||||||
|
stopCalculation("onEventNewHistoryData");
|
||||||
synchronized (dataLock) {
|
synchronized (dataLock) {
|
||||||
long time = ev.time;
|
// clear up 5 min back for proper COB calculation
|
||||||
|
long time = ev.time - 5 * 60 * 1000L;
|
||||||
log.debug("Invalidating cached data to: " + new Date(time).toLocaleString());
|
log.debug("Invalidating cached data to: " + new Date(time).toLocaleString());
|
||||||
for (int index = iobTable.size() - 1; index >= 0; index--) {
|
for (int index = iobTable.size() - 1; index >= 0; index--) {
|
||||||
if (iobTable.keyAt(index) > time) {
|
if (iobTable.keyAt(index) > time) {
|
||||||
if (Config.logAutosensData)
|
|
||||||
if (Config.logAutosensData)
|
if (Config.logAutosensData)
|
||||||
log.debug("Removing from iobTable: " + new Date(iobTable.keyAt(index)).toLocaleString());
|
log.debug("Removing from iobTable: " + new Date(iobTable.keyAt(index)).toLocaleString());
|
||||||
iobTable.removeAt(index);
|
iobTable.removeAt(index);
|
||||||
|
@ -731,15 +657,18 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sHandler.post(new Runnable() {
|
runCalculation("onEventNewHistoryData", System.currentTimeMillis(), false, ev);
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
calculateSensitivityData();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
//log.debug("Releasing onNewHistoryData");
|
//log.debug("Releasing onNewHistoryData");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void clearCache() {
|
||||||
|
synchronized (dataLock) {
|
||||||
|
log.debug("Clearing cached data.");
|
||||||
|
iobTable = new LongSparseArray<>();
|
||||||
|
autosensDataTable = new LongSparseArray<>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// From https://gist.github.com/IceCreamYou/6ffa1b18c4c8f6aeaad2
|
// From https://gist.github.com/IceCreamYou/6ffa1b18c4c8f6aeaad2
|
||||||
// Returns the value at a given percentile in a sorted numeric array.
|
// Returns the value at a given percentile in a sorted numeric array.
|
||||||
// "Linear interpolation between closest ranks" method
|
// "Linear interpolation between closest ranks" method
|
||||||
|
|
|
@ -0,0 +1,248 @@
|
||||||
|
package info.nightscout.androidaps.plugins.IobCobCalculator;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.PowerManager;
|
||||||
|
import android.support.v4.util.LongSparseArray;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.Config;
|
||||||
|
import info.nightscout.androidaps.Constants;
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
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.plugins.IobCobCalculator.events.EventAutosensCalculationFinished;
|
||||||
|
import info.nightscout.androidaps.queue.QueueThread;
|
||||||
|
import info.nightscout.utils.DateUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 23.01.2018.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class IobCobThread extends Thread {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(QueueThread.class);
|
||||||
|
private final Event cause;
|
||||||
|
|
||||||
|
private IobCobCalculatorPlugin iobCobCalculatorPlugin;
|
||||||
|
private boolean bgDataReload;
|
||||||
|
private String from;
|
||||||
|
private long start;
|
||||||
|
|
||||||
|
private PowerManager.WakeLock mWakeLock;
|
||||||
|
|
||||||
|
public IobCobThread(IobCobCalculatorPlugin plugin, String from, long start, boolean bgDataReload, Event cause) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.iobCobCalculatorPlugin = plugin;
|
||||||
|
this.bgDataReload = bgDataReload;
|
||||||
|
this.from = from;
|
||||||
|
this.cause = cause;
|
||||||
|
this.start = start;
|
||||||
|
|
||||||
|
PowerManager powerManager = (PowerManager) MainApp.instance().getApplicationContext().getSystemService(Context.POWER_SERVICE);
|
||||||
|
mWakeLock = powerManager.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "iobCobThread");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final void run() {
|
||||||
|
mWakeLock.acquire();
|
||||||
|
try {
|
||||||
|
if (MainApp.getConfigBuilder() == null) {
|
||||||
|
log.debug("Aborting calculation thread (ConfigBuilder not ready): " + from);
|
||||||
|
return; // app still initializing
|
||||||
|
}
|
||||||
|
if (MainApp.getConfigBuilder().getProfile() == null) {
|
||||||
|
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) {
|
||||||
|
if (bgDataReload) {
|
||||||
|
iobCobCalculatorPlugin.loadBgData(start);
|
||||||
|
iobCobCalculatorPlugin.createBucketedData();
|
||||||
|
}
|
||||||
|
List<BgReading> bucketed_data = iobCobCalculatorPlugin.getBucketedData();
|
||||||
|
LongSparseArray<AutosensData> autosensDataTable = iobCobCalculatorPlugin.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);
|
||||||
|
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--) {
|
||||||
|
if (iobCobCalculatorPlugin.stopCalculationTrigger) {
|
||||||
|
iobCobCalculatorPlugin.stopCalculationTrigger = false;
|
||||||
|
log.debug("Aborting calculation thread (trigger): " + from);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// check if data already exists
|
||||||
|
long bgTime = bucketed_data.get(i).date;
|
||||||
|
bgTime = iobCobCalculatorPlugin.roundUpTime(bgTime);
|
||||||
|
if (bgTime > System.currentTimeMillis())
|
||||||
|
continue;
|
||||||
|
Profile profile = MainApp.getConfigBuilder().getProfile(bgTime);
|
||||||
|
|
||||||
|
AutosensData existing;
|
||||||
|
if ((existing = autosensDataTable.get(bgTime)) != null) {
|
||||||
|
previous = existing;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
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() + ")");
|
||||||
|
|
||||||
|
double sens = Profile.toMgdl(profile.getIsf(bgTime), profile.getUnits());
|
||||||
|
|
||||||
|
AutosensData autosensData = new AutosensData();
|
||||||
|
autosensData.time = bgTime;
|
||||||
|
if (previous != null)
|
||||||
|
autosensData.activeCarbsList = new ArrayList<>(previous.activeCarbsList);
|
||||||
|
else
|
||||||
|
autosensData.activeCarbsList = new ArrayList<>();
|
||||||
|
|
||||||
|
//console.error(bgTime , bucketed_data[i].glucose);
|
||||||
|
double bg;
|
||||||
|
double avgDelta;
|
||||||
|
double delta;
|
||||||
|
bg = bucketed_data.get(i).value;
|
||||||
|
if (bg < 39 || bucketed_data.get(i + 3).value < 39) {
|
||||||
|
log.error("! value < 39");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
delta = (bg - bucketed_data.get(i + 1).value);
|
||||||
|
avgDelta = (bg - bucketed_data.get(i + 3).value) / 3;
|
||||||
|
|
||||||
|
IobTotal iob = iobCobCalculatorPlugin.calculateFromTreatmentsAndTemps(bgTime);
|
||||||
|
|
||||||
|
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;
|
||||||
|
double minDeviation = 999;
|
||||||
|
|
||||||
|
// https://github.com/openaps/oref0/blob/master/lib/determine-basal/cob-autosens.js#L169
|
||||||
|
if (i < bucketed_data.size() - 16) { // we need 1h of data to calculate minDeviationSlope
|
||||||
|
long hourago = bgTime + 10 * 1000 - 60 * 60 * 1000L;
|
||||||
|
AutosensData hourAgoData = iobCobCalculatorPlugin.getAutosensData(hourago);
|
||||||
|
if (hourAgoData != null) {
|
||||||
|
currentDeviation = hourAgoData.avgDeviation;
|
||||||
|
int initialIndex = autosensDataTable.indexOfKey(hourAgoData.time);
|
||||||
|
|
||||||
|
for (int past = 1; past < 12; past++) {
|
||||||
|
AutosensData ad = autosensDataTable.valueAt(initialIndex + past);
|
||||||
|
double deviationSlope = (ad.avgDeviation - currentDeviation) / (ad.time - bgTime) * 1000 * 60 * 5;
|
||||||
|
if (ad.avgDeviation > maxDeviation) {
|
||||||
|
slopeFromMaxDeviation = Math.min(0, deviationSlope);
|
||||||
|
maxDeviation = ad.avgDeviation;
|
||||||
|
}
|
||||||
|
if (avgDeviation < minDeviation) {
|
||||||
|
slopeFromMinDeviation = Math.max(0, deviationSlope);
|
||||||
|
minDeviation = avgDeviation;
|
||||||
|
}
|
||||||
|
|
||||||
|
//if (Config.logAutosensData)
|
||||||
|
// log.debug("Deviations: " + new Date(bgTime) + new Date(ad.time) + " avgDeviation=" + avgDeviation + " deviationSlope=" + deviationSlope + " slopeFromMaxDeviation=" + slopeFromMaxDeviation + " slopeFromMinDeviation=" + slopeFromMinDeviation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Treatment> recentTreatments = MainApp.getConfigBuilder().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)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// if we are absorbing carbs
|
||||||
|
if (previous != null && previous.cob > 0) {
|
||||||
|
// calculate sum of min carb impact from all active treatments
|
||||||
|
double totalMinCarbsImpact = 0d;
|
||||||
|
for (int ii = 0; ii < autosensData.activeCarbsList.size(); ++ii) {
|
||||||
|
AutosensData.CarbsInPast c = autosensData.activeCarbsList.get(ii);
|
||||||
|
totalMinCarbsImpact += c.min5minCarbImpact;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
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.removeOldCarbs(bgTime);
|
||||||
|
autosensData.cob += autosensData.carbsFromBolus;
|
||||||
|
autosensData.deviation = deviation;
|
||||||
|
autosensData.bgi = bgi;
|
||||||
|
autosensData.delta = delta;
|
||||||
|
autosensData.avgDelta = avgDelta;
|
||||||
|
autosensData.avgDeviation = avgDeviation;
|
||||||
|
autosensData.slopeFromMaxDeviation = slopeFromMaxDeviation;
|
||||||
|
autosensData.slopeFromMinDeviation = slopeFromMinDeviation;
|
||||||
|
|
||||||
|
|
||||||
|
// calculate autosens only without COB
|
||||||
|
if (autosensData.cob <= 0) {
|
||||||
|
if (Math.abs(deviation) < Constants.DEVIATION_TO_BE_EQUAL) {
|
||||||
|
autosensData.pastSensitivity += "=";
|
||||||
|
autosensData.nonEqualDeviation = true;
|
||||||
|
} else if (deviation > 0) {
|
||||||
|
autosensData.pastSensitivity += "+";
|
||||||
|
autosensData.nonEqualDeviation = true;
|
||||||
|
} else {
|
||||||
|
autosensData.pastSensitivity += "-";
|
||||||
|
autosensData.nonEqualDeviation = true;
|
||||||
|
}
|
||||||
|
autosensData.nonCarbsDeviation = true;
|
||||||
|
} else {
|
||||||
|
autosensData.pastSensitivity += "C";
|
||||||
|
}
|
||||||
|
//log.debug("TIME: " + new Date(bgTime).toString() + " BG: " + bg + " SENS: " + sens + " DELTA: " + delta + " AVGDELTA: " + avgDelta + " IOB: " + iob.iob + " ACTIVITY: " + iob.activity + " BGI: " + bgi + " DEVIATION: " + deviation);
|
||||||
|
|
||||||
|
previous = autosensData;
|
||||||
|
autosensDataTable.put(bgTime, autosensData);
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MainApp.bus().post(new EventAutosensCalculationFinished(cause));
|
||||||
|
log.debug("Finishing calculation thread: " + from);
|
||||||
|
} finally {
|
||||||
|
mWakeLock.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
package info.nightscout.androidaps.plugins.IobCobCalculator.events;
|
package info.nightscout.androidaps.plugins.IobCobCalculator.events;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.events.Event;
|
||||||
import info.nightscout.androidaps.events.EventLoop;
|
import info.nightscout.androidaps.events.EventLoop;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -7,4 +8,9 @@ import info.nightscout.androidaps.events.EventLoop;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class EventAutosensCalculationFinished extends EventLoop {
|
public class EventAutosensCalculationFinished extends EventLoop {
|
||||||
|
public Event cause;
|
||||||
|
|
||||||
|
public EventAutosensCalculationFinished(Event cause) {
|
||||||
|
this.cause = cause;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,22 @@
|
||||||
package info.nightscout.androidaps.plugins.Loop;
|
package info.nightscout.androidaps.plugins.Loop;
|
||||||
|
|
||||||
import android.os.Parcel;
|
|
||||||
import android.os.Parcelable;
|
|
||||||
import android.text.Html;
|
import android.text.Html;
|
||||||
import android.text.Spanned;
|
import android.text.Spanned;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import info.nightscout.androidaps.MainApp;
|
import info.nightscout.androidaps.MainApp;
|
||||||
import info.nightscout.androidaps.R;
|
import info.nightscout.androidaps.R;
|
||||||
|
import info.nightscout.androidaps.data.IobTotal;
|
||||||
|
import info.nightscout.androidaps.db.BgReading;
|
||||||
import info.nightscout.androidaps.interfaces.PumpInterface;
|
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||||
import info.nightscout.utils.DecimalFormatter;
|
import info.nightscout.utils.DecimalFormatter;
|
||||||
|
@ -22,36 +27,64 @@ import info.nightscout.utils.DecimalFormatter;
|
||||||
public class APSResult {
|
public class APSResult {
|
||||||
private static Logger log = LoggerFactory.getLogger(APSResult.class);
|
private static Logger log = LoggerFactory.getLogger(APSResult.class);
|
||||||
|
|
||||||
|
public Date date;
|
||||||
public String reason;
|
public String reason;
|
||||||
public double rate;
|
public double rate;
|
||||||
public int duration;
|
public int duration;
|
||||||
public boolean changeRequested = false;
|
public boolean tempBasalReqested = false;
|
||||||
|
public boolean bolusRequested = false;
|
||||||
|
public IobTotal iob;
|
||||||
|
public JSONObject json = new JSONObject();
|
||||||
|
public boolean hasPredictions = false;
|
||||||
|
public double smb = 0d; // super micro bolus in units
|
||||||
|
public long deliverAt = 0;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
final PumpInterface pump = ConfigBuilderPlugin.getActivePump();
|
final PumpInterface pump = ConfigBuilderPlugin.getActivePump();
|
||||||
if (changeRequested) {
|
if (isChangeRequested()) {
|
||||||
|
String ret;
|
||||||
|
// rate
|
||||||
if (rate == 0 && duration == 0)
|
if (rate == 0 && duration == 0)
|
||||||
return MainApp.sResources.getString(R.string.canceltemp);
|
ret = MainApp.sResources.getString(R.string.canceltemp) + "\n";
|
||||||
|
else if (rate == -1)
|
||||||
|
ret = MainApp.sResources.getString(R.string.let_temp_basal_run) + "\n";
|
||||||
else
|
else
|
||||||
return MainApp.sResources.getString(R.string.rate) + ": " + DecimalFormatter.to2Decimal(rate) + " U/h " +
|
ret = MainApp.sResources.getString(R.string.rate) + ": " + DecimalFormatter.to2Decimal(rate) + " U/h " +
|
||||||
"(" + DecimalFormatter.to2Decimal(rate / pump.getBaseBasalRate() * 100) + "%) \n" +
|
"(" + DecimalFormatter.to2Decimal(rate / pump.getBaseBasalRate() * 100) + "%) \n" +
|
||||||
MainApp.sResources.getString(R.string.duration) + ": " + DecimalFormatter.to0Decimal(duration) + " min\n" +
|
MainApp.sResources.getString(R.string.duration) + ": " + DecimalFormatter.to2Decimal(duration) + " min\n";
|
||||||
MainApp.sResources.getString(R.string.reason) + ": " + reason;
|
|
||||||
|
// smb
|
||||||
|
if (smb != 0)
|
||||||
|
ret += ("SMB: " + DecimalFormatter.to2Decimal(smb) + " U\n");
|
||||||
|
|
||||||
|
// reason
|
||||||
|
ret += MainApp.sResources.getString(R.string.reason) + ": " + reason;
|
||||||
|
return ret;
|
||||||
} else
|
} else
|
||||||
return MainApp.sResources.getString(R.string.nochangerequested);
|
return MainApp.sResources.getString(R.string.nochangerequested);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Spanned toSpanned() {
|
public Spanned toSpanned() {
|
||||||
final PumpInterface pump = ConfigBuilderPlugin.getActivePump();
|
final PumpInterface pump = ConfigBuilderPlugin.getActivePump();
|
||||||
if (changeRequested) {
|
if (isChangeRequested()) {
|
||||||
String ret = "";
|
String ret;
|
||||||
if (rate == 0 && duration == 0) ret = MainApp.sResources.getString(R.string.canceltemp);
|
// rate
|
||||||
|
if (rate == 0 && duration == 0)
|
||||||
|
ret = MainApp.sResources.getString(R.string.canceltemp) + "<br>";
|
||||||
|
else if (rate == -1)
|
||||||
|
ret = MainApp.sResources.getString(R.string.let_temp_basal_run) + "<br>";
|
||||||
else
|
else
|
||||||
ret = "<b>" + MainApp.sResources.getString(R.string.rate) + "</b>: " + DecimalFormatter.to2Decimal(rate) + " U/h " +
|
ret = "<b>" + MainApp.sResources.getString(R.string.rate) + "</b>: " + DecimalFormatter.to2Decimal(rate) + " U/h " +
|
||||||
"(" + DecimalFormatter.to2Decimal(rate / pump.getBaseBasalRate() * 100) + "%) <br>" +
|
"(" + DecimalFormatter.to2Decimal(rate / pump.getBaseBasalRate() * 100) + "%) <br>" +
|
||||||
"<b>" + MainApp.sResources.getString(R.string.duration) + "</b>: " + DecimalFormatter.to2Decimal(duration) + " min<br>" +
|
"<b>" + MainApp.sResources.getString(R.string.duration) + "</b>: " + DecimalFormatter.to2Decimal(duration) + " min<br>";
|
||||||
"<b>" + MainApp.sResources.getString(R.string.reason) + "</b>: " + reason.replace("<", "<").replace(">", ">");
|
|
||||||
|
// smb
|
||||||
|
if (smb != 0)
|
||||||
|
ret += ("<b>" + "SMB" + "</b>: " + DecimalFormatter.to2Decimal(smb) + " U<br>");
|
||||||
|
|
||||||
|
// reason
|
||||||
|
ret += "<b>" + MainApp.sResources.getString(R.string.reason) + "</b>: " + reason.replace("<", "<").replace(">", ">");
|
||||||
return Html.fromHtml(ret);
|
return Html.fromHtml(ret);
|
||||||
} else
|
} else
|
||||||
return Html.fromHtml(MainApp.sResources.getString(R.string.nochangerequested));
|
return Html.fromHtml(MainApp.sResources.getString(R.string.nochangerequested));
|
||||||
|
@ -62,17 +95,19 @@ public class APSResult {
|
||||||
|
|
||||||
public APSResult clone() {
|
public APSResult clone() {
|
||||||
APSResult newResult = new APSResult();
|
APSResult newResult = new APSResult();
|
||||||
newResult.reason = new String(reason);
|
newResult.reason = reason;
|
||||||
newResult.rate = rate;
|
newResult.rate = rate;
|
||||||
newResult.duration = duration;
|
newResult.duration = duration;
|
||||||
newResult.changeRequested = changeRequested;
|
newResult.tempBasalReqested = tempBasalReqested;
|
||||||
|
newResult.bolusRequested = bolusRequested;
|
||||||
|
newResult.iob = iob;
|
||||||
return newResult;
|
return newResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
public JSONObject json() {
|
public JSONObject json() {
|
||||||
JSONObject json = new JSONObject();
|
JSONObject json = new JSONObject();
|
||||||
try {
|
try {
|
||||||
if (changeRequested) {
|
if (isChangeRequested()) {
|
||||||
json.put("rate", rate);
|
json.put("rate", rate);
|
||||||
json.put("duration", duration);
|
json.put("duration", duration);
|
||||||
json.put("reason", reason);
|
json.put("reason", reason);
|
||||||
|
@ -82,4 +117,105 @@ public class APSResult {
|
||||||
}
|
}
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<BgReading> getPredictions() {
|
||||||
|
List<BgReading> array = new ArrayList<>();
|
||||||
|
try {
|
||||||
|
long startTime = date.getTime();
|
||||||
|
if (json.has("predBGs")) {
|
||||||
|
JSONObject predBGs = json.getJSONObject("predBGs");
|
||||||
|
if (predBGs.has("IOB")) {
|
||||||
|
JSONArray iob = predBGs.getJSONArray("IOB");
|
||||||
|
for (int i = 1; i < iob.length(); i++) {
|
||||||
|
BgReading bg = new BgReading();
|
||||||
|
bg.value = iob.getInt(i);
|
||||||
|
bg.date = startTime + i * 5 * 60 * 1000L;
|
||||||
|
bg.isIOBPrediction = true;
|
||||||
|
array.add(bg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (predBGs.has("aCOB")) {
|
||||||
|
JSONArray iob = predBGs.getJSONArray("aCOB");
|
||||||
|
for (int i = 1; i < iob.length(); i++) {
|
||||||
|
BgReading bg = new BgReading();
|
||||||
|
bg.value = iob.getInt(i);
|
||||||
|
bg.date = startTime + i * 5 * 60 * 1000L;
|
||||||
|
bg.isaCOBPrediction = true;
|
||||||
|
array.add(bg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (predBGs.has("COB")) {
|
||||||
|
JSONArray iob = predBGs.getJSONArray("COB");
|
||||||
|
for (int i = 1; i < iob.length(); i++) {
|
||||||
|
BgReading bg = new BgReading();
|
||||||
|
bg.value = iob.getInt(i);
|
||||||
|
bg.date = startTime + i * 5 * 60 * 1000L;
|
||||||
|
bg.isCOBPrediction = true;
|
||||||
|
array.add(bg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (predBGs.has("UAM")) {
|
||||||
|
JSONArray iob = predBGs.getJSONArray("UAM");
|
||||||
|
for (int i = 1; i < iob.length(); i++) {
|
||||||
|
BgReading bg = new BgReading();
|
||||||
|
bg.value = iob.getInt(i);
|
||||||
|
bg.date = startTime + i * 5 * 60 * 1000L;
|
||||||
|
bg.isUAMPrediction = true;
|
||||||
|
array.add(bg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (predBGs.has("ZT")) {
|
||||||
|
JSONArray iob = predBGs.getJSONArray("ZT");
|
||||||
|
for (int i = 1; i < iob.length(); i++) {
|
||||||
|
BgReading bg = new BgReading();
|
||||||
|
bg.value = iob.getInt(i);
|
||||||
|
bg.date = startTime + i * 5 * 60 * 1000L;
|
||||||
|
bg.isZTPrediction = true;
|
||||||
|
array.add(bg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getLatestPredictionsTime() {
|
||||||
|
long latest = 0;
|
||||||
|
try {
|
||||||
|
long startTime = date != null ? date.getTime() : 0;
|
||||||
|
if (json.has("predBGs")) {
|
||||||
|
JSONObject predBGs = json.getJSONObject("predBGs");
|
||||||
|
if (predBGs.has("IOB")) {
|
||||||
|
JSONArray iob = predBGs.getJSONArray("IOB");
|
||||||
|
latest = Math.max(latest, startTime + (iob.length() - 1) * 5 * 60 * 1000L);
|
||||||
|
}
|
||||||
|
if (predBGs.has("aCOB")) {
|
||||||
|
JSONArray iob = predBGs.getJSONArray("aCOB");
|
||||||
|
latest = Math.max(latest, startTime + (iob.length() - 1) * 5 * 60 * 1000L);
|
||||||
|
}
|
||||||
|
if (predBGs.has("COB")) {
|
||||||
|
JSONArray iob = predBGs.getJSONArray("COB");
|
||||||
|
latest = Math.max(latest, startTime + (iob.length() - 1) * 5 * 60 * 1000L);
|
||||||
|
}
|
||||||
|
if (predBGs.has("UAM")) {
|
||||||
|
JSONArray iob = predBGs.getJSONArray("UAM");
|
||||||
|
latest = Math.max(latest, startTime + (iob.length() - 1) * 5 * 60 * 1000L);
|
||||||
|
}
|
||||||
|
if (predBGs.has("ZT")) {
|
||||||
|
JSONArray iob = predBGs.getJSONArray("ZT");
|
||||||
|
latest = Math.max(latest, startTime + (iob.length() - 1) * 5 * 60 * 1000L);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return latest;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isChangeRequested() {
|
||||||
|
return tempBasalReqested || bolusRequested;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ import android.app.PendingIntent;
|
||||||
import android.app.TaskStackBuilder;
|
import android.app.TaskStackBuilder;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.support.v7.app.NotificationCompat;
|
import android.support.v4.app.NotificationCompat;
|
||||||
|
|
||||||
import com.crashlytics.android.answers.Answers;
|
import com.crashlytics.android.answers.Answers;
|
||||||
import com.crashlytics.android.answers.CustomEvent;
|
import com.crashlytics.android.answers.CustomEvent;
|
||||||
|
@ -30,9 +30,12 @@ import info.nightscout.androidaps.interfaces.ConstraintsInterface;
|
||||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||||
import info.nightscout.androidaps.interfaces.PumpInterface;
|
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||||
|
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventAutosensCalculationFinished;
|
||||||
|
import info.nightscout.androidaps.plugins.Loop.events.EventLoopResult;
|
||||||
import info.nightscout.androidaps.plugins.Loop.events.EventLoopSetLastRunGui;
|
import info.nightscout.androidaps.plugins.Loop.events.EventLoopSetLastRunGui;
|
||||||
import info.nightscout.androidaps.plugins.Loop.events.EventLoopUpdateGui;
|
import info.nightscout.androidaps.plugins.Loop.events.EventLoopUpdateGui;
|
||||||
import info.nightscout.androidaps.plugins.Loop.events.EventNewOpenLoopNotification;
|
import info.nightscout.androidaps.plugins.Loop.events.EventNewOpenLoopNotification;
|
||||||
|
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
|
||||||
import info.nightscout.androidaps.queue.Callback;
|
import info.nightscout.androidaps.queue.Callback;
|
||||||
import info.nightscout.utils.NSUpload;
|
import info.nightscout.utils.NSUpload;
|
||||||
import info.nightscout.utils.SP;
|
import info.nightscout.utils.SP;
|
||||||
|
@ -148,12 +151,16 @@ public class LoopPlugin implements PluginBase {
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void onStatusEvent(final EventTreatmentChange ev) {
|
public void onStatusEvent(final EventTreatmentChange ev) {
|
||||||
|
if (ev.treatment == null || !ev.treatment.isSMB){
|
||||||
invoke("EventTreatmentChange", true);
|
invoke("EventTreatmentChange", true);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void onStatusEvent(final EventNewBG ev) {
|
public void onStatusEvent(final EventAutosensCalculationFinished ev) {
|
||||||
invoke("EventNewBG", true);
|
if (ev.cause instanceof EventNewBG) {
|
||||||
|
invoke(ev.getClass().getSimpleName() + "(" + ev.cause.getClass().getSimpleName() + ")", true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public long suspendedTo() {
|
public long suspendedTo() {
|
||||||
|
@ -283,6 +290,14 @@ public class LoopPlugin implements PluginBase {
|
||||||
// check rate for constrais
|
// check rate for constrais
|
||||||
final APSResult resultAfterConstraints = result.clone();
|
final APSResult resultAfterConstraints = result.clone();
|
||||||
resultAfterConstraints.rate = constraintsInterface.applyBasalConstraints(resultAfterConstraints.rate);
|
resultAfterConstraints.rate = constraintsInterface.applyBasalConstraints(resultAfterConstraints.rate);
|
||||||
|
resultAfterConstraints.smb = constraintsInterface.applyBolusConstraints(resultAfterConstraints.smb);
|
||||||
|
|
||||||
|
// safety check for multiple SMBs
|
||||||
|
long lastBolusTime = TreatmentsPlugin.getPlugin().getLastBolusTime();
|
||||||
|
if (lastBolusTime != 0 && lastBolusTime + 3 * 60 * 1000 > System.currentTimeMillis()) {
|
||||||
|
log.debug("SMB requsted but still in 3 min interval");
|
||||||
|
resultAfterConstraints.smb = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (lastRun == null) lastRun = new LastRun();
|
if (lastRun == null) lastRun = new LastRun();
|
||||||
lastRun.request = result;
|
lastRun.request = result;
|
||||||
|
@ -305,8 +320,10 @@ public class LoopPlugin implements PluginBase {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MainApp.bus().post(new EventLoopResult(resultAfterConstraints));
|
||||||
|
|
||||||
if (constraintsInterface.isClosedModeEnabled()) {
|
if (constraintsInterface.isClosedModeEnabled()) {
|
||||||
if (result.changeRequested) {
|
if (result.isChangeRequested()) {
|
||||||
final PumpEnactResult waiting = new PumpEnactResult();
|
final PumpEnactResult waiting = new PumpEnactResult();
|
||||||
final PumpEnactResult previousResult = lastRun.setByPump;
|
final PumpEnactResult previousResult = lastRun.setByPump;
|
||||||
waiting.queued = true;
|
waiting.queued = true;
|
||||||
|
@ -330,7 +347,7 @@ public class LoopPlugin implements PluginBase {
|
||||||
lastRun.source = null;
|
lastRun.source = null;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (result.changeRequested && allowNotification) {
|
if (result.isChangeRequested() && allowNotification) {
|
||||||
NotificationCompat.Builder builder =
|
NotificationCompat.Builder builder =
|
||||||
new NotificationCompat.Builder(MainApp.instance().getApplicationContext());
|
new NotificationCompat.Builder(MainApp.instance().getApplicationContext());
|
||||||
builder.setSmallIcon(R.drawable.notif_icon)
|
builder.setSmallIcon(R.drawable.notif_icon)
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -124,7 +124,7 @@ public class NSDeviceStatus {
|
||||||
static DeviceStatusPumpData deviceStatusPumpData = null;
|
static DeviceStatusPumpData deviceStatusPumpData = null;
|
||||||
|
|
||||||
public Spanned getExtendedPumpStatus() {
|
public Spanned getExtendedPumpStatus() {
|
||||||
if (deviceStatusPumpData.extended != null)
|
if (deviceStatusPumpData != null && deviceStatusPumpData.extended != null)
|
||||||
return deviceStatusPumpData.extended;
|
return deviceStatusPumpData.extended;
|
||||||
return Html.fromHtml("");
|
return Html.fromHtml("");
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ import info.nightscout.androidaps.db.TemporaryBasal;
|
||||||
import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin;
|
import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin;
|
||||||
import info.nightscout.androidaps.plugins.Loop.ScriptReader;
|
import info.nightscout.androidaps.plugins.Loop.ScriptReader;
|
||||||
import info.nightscout.androidaps.plugins.OpenAPSMA.LoggerCallback;
|
import info.nightscout.androidaps.plugins.OpenAPSMA.LoggerCallback;
|
||||||
|
import info.nightscout.androidaps.plugins.OpenAPSSMB.SMBDefaults;
|
||||||
import info.nightscout.utils.SP;
|
import info.nightscout.utils.SP;
|
||||||
|
|
||||||
public class DetermineBasalAdapterAMAJS {
|
public class DetermineBasalAdapterAMAJS {
|
||||||
|
@ -189,8 +190,7 @@ public class DetermineBasalAdapterAMAJS {
|
||||||
GlucoseStatus glucoseStatus,
|
GlucoseStatus glucoseStatus,
|
||||||
MealData mealData,
|
MealData mealData,
|
||||||
double autosensDataRatio,
|
double autosensDataRatio,
|
||||||
boolean tempTargetSet,
|
boolean tempTargetSet) throws JSONException {
|
||||||
double min_5m_carbimpact) throws JSONException {
|
|
||||||
|
|
||||||
String units = profile.getUnits();
|
String units = profile.getUnits();
|
||||||
|
|
||||||
|
@ -211,7 +211,7 @@ public class DetermineBasalAdapterAMAJS {
|
||||||
mProfile.put("current_basal", basalrate);
|
mProfile.put("current_basal", basalrate);
|
||||||
mProfile.put("temptargetSet", tempTargetSet);
|
mProfile.put("temptargetSet", tempTargetSet);
|
||||||
mProfile.put("autosens_adjust_targets", SP.getBoolean("openapsama_autosens_adjusttargets", true));
|
mProfile.put("autosens_adjust_targets", SP.getBoolean("openapsama_autosens_adjusttargets", true));
|
||||||
mProfile.put("min_5m_carbimpact", SP.getDouble("openapsama_min_5m_carbimpact", 3d));
|
mProfile.put("min_5m_carbimpact", SP.getInt("openapsama_min_5m_carbimpact", SMBDefaults.min_5m_carbimpact));
|
||||||
|
|
||||||
if (units.equals(Constants.MMOL)) {
|
if (units.equals(Constants.MMOL)) {
|
||||||
mProfile.put("out_units", "mmol/L");
|
mProfile.put("out_units", "mmol/L");
|
||||||
|
|
|
@ -1,35 +1,28 @@
|
||||||
package info.nightscout.androidaps.plugins.OpenAPSAMA;
|
package info.nightscout.androidaps.plugins.OpenAPSAMA;
|
||||||
|
|
||||||
import org.json.JSONArray;
|
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.mozilla.javascript.NativeObject;
|
import org.mozilla.javascript.NativeObject;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.db.BgReading;
|
|
||||||
import info.nightscout.androidaps.plugins.Loop.APSResult;
|
import info.nightscout.androidaps.plugins.Loop.APSResult;
|
||||||
import info.nightscout.androidaps.data.IobTotal;
|
|
||||||
|
|
||||||
public class DetermineBasalResultAMA extends APSResult {
|
public class DetermineBasalResultAMA extends APSResult {
|
||||||
private static Logger log = LoggerFactory.getLogger(DetermineBasalResultAMA.class);
|
private static Logger log = LoggerFactory.getLogger(DetermineBasalResultAMA.class);
|
||||||
|
|
||||||
public Date date;
|
|
||||||
public JSONObject json = new JSONObject();
|
|
||||||
public double eventualBG;
|
public double eventualBG;
|
||||||
public double snoozeBG;
|
public double snoozeBG;
|
||||||
public IobTotal iob;
|
|
||||||
|
|
||||||
public DetermineBasalResultAMA(NativeObject result, JSONObject j) {
|
public DetermineBasalResultAMA(NativeObject result, JSONObject j) {
|
||||||
|
this();
|
||||||
date = new Date();
|
date = new Date();
|
||||||
json = j;
|
json = j;
|
||||||
if (result.containsKey("error")) {
|
if (result.containsKey("error")) {
|
||||||
reason = result.get("error").toString();
|
reason = result.get("error").toString();
|
||||||
changeRequested = false;
|
tempBasalReqested = false;
|
||||||
rate = -1;
|
rate = -1;
|
||||||
duration = -1;
|
duration = -1;
|
||||||
} else {
|
} else {
|
||||||
|
@ -39,34 +32,35 @@ public class DetermineBasalResultAMA extends APSResult {
|
||||||
if (result.containsKey("rate")) {
|
if (result.containsKey("rate")) {
|
||||||
rate = (Double) result.get("rate");
|
rate = (Double) result.get("rate");
|
||||||
if (rate < 0d) rate = 0d;
|
if (rate < 0d) rate = 0d;
|
||||||
changeRequested = true;
|
tempBasalReqested = true;
|
||||||
} else {
|
} else {
|
||||||
rate = -1;
|
rate = -1;
|
||||||
changeRequested = false;
|
tempBasalReqested = false;
|
||||||
}
|
}
|
||||||
if (result.containsKey("duration")) {
|
if (result.containsKey("duration")) {
|
||||||
duration = ((Double) result.get("duration")).intValue();
|
duration = ((Double) result.get("duration")).intValue();
|
||||||
//changeRequested as above
|
//changeRequested as above
|
||||||
} else {
|
} else {
|
||||||
duration = -1;
|
duration = -1;
|
||||||
changeRequested = false;
|
tempBasalReqested = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
bolusRequested = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DetermineBasalResultAMA() {
|
public DetermineBasalResultAMA() {
|
||||||
|
hasPredictions = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DetermineBasalResultAMA clone() {
|
public DetermineBasalResultAMA clone() {
|
||||||
DetermineBasalResultAMA newResult = new DetermineBasalResultAMA();
|
DetermineBasalResultAMA newResult = new DetermineBasalResultAMA();
|
||||||
newResult.reason = new String(reason);
|
newResult.reason = reason;
|
||||||
newResult.rate = rate;
|
newResult.rate = rate;
|
||||||
newResult.duration = duration;
|
newResult.duration = duration;
|
||||||
newResult.changeRequested = changeRequested;
|
newResult.tempBasalReqested = tempBasalReqested;
|
||||||
newResult.rate = rate;
|
newResult.rate = rate;
|
||||||
newResult.duration = duration;
|
newResult.duration = duration;
|
||||||
newResult.changeRequested = changeRequested;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
newResult.json = new JSONObject(json.toString());
|
newResult.json = new JSONObject(json.toString());
|
||||||
|
@ -90,72 +84,4 @@ public class DetermineBasalResultAMA extends APSResult {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<BgReading> getPredictions() {
|
|
||||||
List<BgReading> array = new ArrayList<>();
|
|
||||||
try {
|
|
||||||
long startTime = date.getTime();
|
|
||||||
if (json.has("predBGs")) {
|
|
||||||
JSONObject predBGs = json.getJSONObject("predBGs");
|
|
||||||
if (predBGs.has("IOB")) {
|
|
||||||
JSONArray iob = predBGs.getJSONArray("IOB");
|
|
||||||
for (int i = 1; i < iob.length(); i ++) {
|
|
||||||
BgReading bg = new BgReading();
|
|
||||||
bg.value = iob.getInt(i);
|
|
||||||
bg.date = startTime + i * 5 * 60 * 1000L;
|
|
||||||
bg.isPrediction = true;
|
|
||||||
array.add(bg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (predBGs.has("aCOB")) {
|
|
||||||
JSONArray iob = predBGs.getJSONArray("aCOB");
|
|
||||||
for (int i = 1; i < iob.length(); i ++) {
|
|
||||||
BgReading bg = new BgReading();
|
|
||||||
bg.value = iob.getInt(i);
|
|
||||||
bg.date = startTime + i * 5 * 60 * 1000L;
|
|
||||||
bg.isPrediction = true;
|
|
||||||
array.add(bg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (predBGs.has("COB")) {
|
|
||||||
JSONArray iob = predBGs.getJSONArray("COB");
|
|
||||||
for (int i = 1; i < iob.length(); i ++) {
|
|
||||||
BgReading bg = new BgReading();
|
|
||||||
bg.value = iob.getInt(i);
|
|
||||||
bg.date = startTime + i * 5 * 60 * 1000L;
|
|
||||||
bg.isPrediction = true;
|
|
||||||
array.add(bg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (JSONException e) {
|
|
||||||
log.error("Unhandled exception", e);
|
|
||||||
}
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getLatestPredictionsTime() {
|
|
||||||
long latest = 0;
|
|
||||||
try {
|
|
||||||
long startTime = date.getTime();
|
|
||||||
if (json.has("predBGs")) {
|
|
||||||
JSONObject predBGs = json.getJSONObject("predBGs");
|
|
||||||
if (predBGs.has("IOB")) {
|
|
||||||
JSONArray iob = predBGs.getJSONArray("IOB");
|
|
||||||
latest = Math.max(latest, startTime + (iob.length() - 1) * 5 * 60 * 1000L);
|
|
||||||
}
|
|
||||||
if (predBGs.has("aCOB")) {
|
|
||||||
JSONArray iob = predBGs.getJSONArray("aCOB");
|
|
||||||
latest = Math.max(latest, startTime + (iob.length() - 1) * 5 * 60 * 1000L);
|
|
||||||
}
|
|
||||||
if (predBGs.has("COB")) {
|
|
||||||
JSONArray iob = predBGs.getJSONArray("COB");
|
|
||||||
latest = Math.max(latest, startTime + (iob.length() - 1) * 5 * 60 * 1000L);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (JSONException e) {
|
|
||||||
log.error("Unhandled exception", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
return latest;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,6 @@ import java.io.IOException;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
import info.nightscout.androidaps.Config;
|
import info.nightscout.androidaps.Config;
|
||||||
import info.nightscout.androidaps.Constants;
|
|
||||||
import info.nightscout.androidaps.MainApp;
|
import info.nightscout.androidaps.MainApp;
|
||||||
import info.nightscout.androidaps.R;
|
import info.nightscout.androidaps.R;
|
||||||
import info.nightscout.androidaps.data.GlucoseStatus;
|
import info.nightscout.androidaps.data.GlucoseStatus;
|
||||||
|
@ -18,6 +17,7 @@ import info.nightscout.androidaps.data.Profile;
|
||||||
import info.nightscout.androidaps.db.TempTarget;
|
import info.nightscout.androidaps.db.TempTarget;
|
||||||
import info.nightscout.androidaps.interfaces.APSInterface;
|
import info.nightscout.androidaps.interfaces.APSInterface;
|
||||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||||
|
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||||
import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensResult;
|
import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensResult;
|
||||||
import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin;
|
import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin;
|
||||||
|
@ -26,12 +26,10 @@ import info.nightscout.androidaps.plugins.Loop.ScriptReader;
|
||||||
import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateGui;
|
import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateGui;
|
||||||
import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateResultGui;
|
import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateResultGui;
|
||||||
import info.nightscout.utils.DateUtil;
|
import info.nightscout.utils.DateUtil;
|
||||||
import info.nightscout.utils.NSUpload;
|
import info.nightscout.utils.HardLimits;
|
||||||
import info.nightscout.utils.Profiler;
|
import info.nightscout.utils.Profiler;
|
||||||
import info.nightscout.utils.Round;
|
import info.nightscout.utils.Round;
|
||||||
import info.nightscout.utils.SP;
|
import info.nightscout.utils.SP;
|
||||||
import info.nightscout.utils.SafeParse;
|
|
||||||
import info.nightscout.utils.ToastUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by mike on 05.08.2016.
|
* Created by mike on 05.08.2016.
|
||||||
|
@ -149,6 +147,7 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface {
|
||||||
|
|
||||||
GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData();
|
GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData();
|
||||||
Profile profile = MainApp.getConfigBuilder().getProfile();
|
Profile profile = MainApp.getConfigBuilder().getProfile();
|
||||||
|
PumpInterface pump = ConfigBuilderPlugin.getActivePump();
|
||||||
|
|
||||||
if (profile == null) {
|
if (profile == null) {
|
||||||
MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.instance().getString(R.string.noprofileselected)));
|
MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.instance().getString(R.string.noprofileselected)));
|
||||||
|
@ -184,7 +183,7 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface {
|
||||||
|
|
||||||
Date start = new Date();
|
Date start = new Date();
|
||||||
Date startPart = new Date();
|
Date startPart = new Date();
|
||||||
IobTotal[] iobArray = IobCobCalculatorPlugin.calculateIobArrayInDia();
|
IobTotal[] iobArray = IobCobCalculatorPlugin.getPlugin().calculateIobArrayInDia();
|
||||||
Profiler.log(log, "calculateIobArrayInDia()", startPart);
|
Profiler.log(log, "calculateIobArrayInDia()", startPart);
|
||||||
|
|
||||||
startPart = new Date();
|
startPart = new Date();
|
||||||
|
@ -193,35 +192,37 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface {
|
||||||
|
|
||||||
maxIob = MainApp.getConfigBuilder().applyMaxIOBConstraints(maxIob);
|
maxIob = MainApp.getConfigBuilder().applyMaxIOBConstraints(maxIob);
|
||||||
|
|
||||||
minBg = verifyHardLimits(minBg, "minBg", Constants.VERY_HARD_LIMIT_MIN_BG[0], Constants.VERY_HARD_LIMIT_MIN_BG[1]);
|
minBg = HardLimits.verifyHardLimits(minBg, "minBg", HardLimits.VERY_HARD_LIMIT_MIN_BG[0], HardLimits.VERY_HARD_LIMIT_MIN_BG[1]);
|
||||||
maxBg = verifyHardLimits(maxBg, "maxBg", Constants.VERY_HARD_LIMIT_MAX_BG[0], Constants.VERY_HARD_LIMIT_MAX_BG[1]);
|
maxBg = HardLimits.verifyHardLimits(maxBg, "maxBg", HardLimits.VERY_HARD_LIMIT_MAX_BG[0], HardLimits.VERY_HARD_LIMIT_MAX_BG[1]);
|
||||||
targetBg = verifyHardLimits(targetBg, "targetBg", Constants.VERY_HARD_LIMIT_TARGET_BG[0], Constants.VERY_HARD_LIMIT_TARGET_BG[1]);
|
targetBg = HardLimits.verifyHardLimits(targetBg, "targetBg", HardLimits.VERY_HARD_LIMIT_TARGET_BG[0], HardLimits.VERY_HARD_LIMIT_TARGET_BG[1]);
|
||||||
|
|
||||||
boolean isTempTarget = false;
|
boolean isTempTarget = false;
|
||||||
TempTarget tempTarget = MainApp.getConfigBuilder().getTempTargetFromHistory(System.currentTimeMillis());
|
TempTarget tempTarget = MainApp.getConfigBuilder().getTempTargetFromHistory(System.currentTimeMillis());
|
||||||
if (tempTarget != null) {
|
if (tempTarget != null) {
|
||||||
isTempTarget = true;
|
isTempTarget = true;
|
||||||
minBg = verifyHardLimits(tempTarget.low, "minBg", Constants.VERY_HARD_LIMIT_TEMP_MIN_BG[0], Constants.VERY_HARD_LIMIT_TEMP_MIN_BG[1]);
|
minBg = HardLimits.verifyHardLimits(tempTarget.low, "minBg", HardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[0], HardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[1]);
|
||||||
maxBg = verifyHardLimits(tempTarget.high, "maxBg", Constants.VERY_HARD_LIMIT_TEMP_MAX_BG[0], Constants.VERY_HARD_LIMIT_TEMP_MAX_BG[1]);
|
maxBg = HardLimits.verifyHardLimits(tempTarget.high, "maxBg", HardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[0], HardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[1]);
|
||||||
targetBg = verifyHardLimits((tempTarget.low + tempTarget.high) / 2, "targetBg", Constants.VERY_HARD_LIMIT_TEMP_TARGET_BG[0], Constants.VERY_HARD_LIMIT_TEMP_TARGET_BG[1]);
|
targetBg = HardLimits.verifyHardLimits((tempTarget.low + tempTarget.high) / 2, "targetBg", HardLimits.VERY_HARD_LIMIT_TEMP_TARGET_BG[0], HardLimits.VERY_HARD_LIMIT_TEMP_TARGET_BG[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
maxIob = verifyHardLimits(maxIob, "maxIob", 0, 7);
|
maxIob = HardLimits.verifyHardLimits(maxIob, "maxIob", 0, HardLimits.maxIobAMA());
|
||||||
maxBasal = verifyHardLimits(maxBasal, "max_basal", 0.1, 10);
|
maxBasal = HardLimits.verifyHardLimits(maxBasal, "max_basal", 0.1, HardLimits.maxBasal());
|
||||||
|
|
||||||
if (!checkOnlyHardLimits(profile.getDia(), "dia", 2, 7)) return;
|
if (!HardLimits.checkOnlyHardLimits(profile.getDia(), "dia", HardLimits.MINDIA, HardLimits.MAXDIA))
|
||||||
if (!checkOnlyHardLimits(profile.getIc(Profile.secondsFromMidnight()), "carbratio", 2, 100))
|
|
||||||
return;
|
return;
|
||||||
if (!checkOnlyHardLimits(Profile.toMgdl(profile.getIsf(), units), "sens", 2, 900))
|
if (!HardLimits.checkOnlyHardLimits(profile.getIc(profile.secondsFromMidnight()), "carbratio", HardLimits.MINIC, HardLimits.MAXIC))
|
||||||
return;
|
return;
|
||||||
if (!checkOnlyHardLimits(profile.getMaxDailyBasal(), "max_daily_basal", 0.1, 10)) return;
|
if (!HardLimits.checkOnlyHardLimits(Profile.toMgdl(profile.getIsf().doubleValue(), units), "sens", HardLimits.MINISF, HardLimits.MAXISF))
|
||||||
if (!checkOnlyHardLimits(ConfigBuilderPlugin.getActivePump().getBaseBasalRate(), "current_basal", 0.01, 5))
|
return;
|
||||||
|
if (!HardLimits.checkOnlyHardLimits(profile.getMaxDailyBasal(), "max_daily_basal", 0.1, HardLimits.maxBasal()))
|
||||||
|
return;
|
||||||
|
if (!HardLimits.checkOnlyHardLimits(pump.getBaseBasalRate(), "current_basal", 0.01, HardLimits.maxBasal()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
startPart = new Date();
|
startPart = new Date();
|
||||||
if (MainApp.getConfigBuilder().isAMAModeEnabled()) {
|
if (MainApp.getConfigBuilder().isAMAModeEnabled()) {
|
||||||
lastAutosensResult = IobCobCalculatorPlugin.detectSensitivityWithLock(IobCobCalculatorPlugin.oldestDataAvailable(), System.currentTimeMillis());
|
lastAutosensResult = IobCobCalculatorPlugin.getPlugin().detectSensitivityWithLock(IobCobCalculatorPlugin.oldestDataAvailable(), System.currentTimeMillis());
|
||||||
} else {
|
} else {
|
||||||
lastAutosensResult = new AutosensResult();
|
lastAutosensResult = new AutosensResult();
|
||||||
}
|
}
|
||||||
|
@ -233,8 +234,7 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface {
|
||||||
try {
|
try {
|
||||||
determineBasalAdapterAMAJS.setData(profile, maxIob, maxBasal, minBg, maxBg, targetBg, ConfigBuilderPlugin.getActivePump().getBaseBasalRate(), iobArray, glucoseStatus, mealData,
|
determineBasalAdapterAMAJS.setData(profile, maxIob, maxBasal, minBg, maxBg, targetBg, ConfigBuilderPlugin.getActivePump().getBaseBasalRate(), iobArray, glucoseStatus, mealData,
|
||||||
lastAutosensResult.ratio, //autosensDataRatio
|
lastAutosensResult.ratio, //autosensDataRatio
|
||||||
isTempTarget,
|
isTempTarget
|
||||||
SafeParse.stringToDouble(SP.getString("openapsama_min_5m_carbimpact", "3.0"))//min_5m_carbimpact
|
|
||||||
);
|
);
|
||||||
} catch (JSONException e) {
|
} catch (JSONException e) {
|
||||||
log.error("Unable to set data: " + e.toString());
|
log.error("Unable to set data: " + e.toString());
|
||||||
|
@ -245,15 +245,15 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface {
|
||||||
Profiler.log(log, "AMA calculation", start);
|
Profiler.log(log, "AMA calculation", start);
|
||||||
// Fix bug determine basal
|
// Fix bug determine basal
|
||||||
if (determineBasalResultAMA.rate == 0d && determineBasalResultAMA.duration == 0 && !MainApp.getConfigBuilder().isTempBasalInProgress())
|
if (determineBasalResultAMA.rate == 0d && determineBasalResultAMA.duration == 0 && !MainApp.getConfigBuilder().isTempBasalInProgress())
|
||||||
determineBasalResultAMA.changeRequested = false;
|
determineBasalResultAMA.tempBasalReqested = false;
|
||||||
// limit requests on openloop mode
|
// limit requests on openloop mode
|
||||||
if (!MainApp.getConfigBuilder().isClosedModeEnabled()) {
|
if (!MainApp.getConfigBuilder().isClosedModeEnabled()) {
|
||||||
if (MainApp.getConfigBuilder().isTempBasalInProgress() && determineBasalResultAMA.rate == 0 && determineBasalResultAMA.duration == 0) {
|
if (MainApp.getConfigBuilder().isTempBasalInProgress() && determineBasalResultAMA.rate == 0 && determineBasalResultAMA.duration == 0) {
|
||||||
// going to cancel
|
// going to cancel
|
||||||
} else if (MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultAMA.rate - MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory()) < 0.1) {
|
} else if (MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultAMA.rate - MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory()) < 0.1) {
|
||||||
determineBasalResultAMA.changeRequested = false;
|
determineBasalResultAMA.tempBasalReqested = false;
|
||||||
} else if (!MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultAMA.rate - ConfigBuilderPlugin.getActivePump().getBaseBasalRate()) < 0.1)
|
} else if (!MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultAMA.rate - ConfigBuilderPlugin.getActivePump().getBaseBasalRate()) < 0.1)
|
||||||
determineBasalResultAMA.changeRequested = false;
|
determineBasalResultAMA.tempBasalReqested = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
determineBasalResultAMA.iob = iobArray[0];
|
determineBasalResultAMA.iob = iobArray[0];
|
||||||
|
@ -274,24 +274,4 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface {
|
||||||
//deviceStatus.suggested = determineBasalResultAMA.json;
|
//deviceStatus.suggested = determineBasalResultAMA.json;
|
||||||
}
|
}
|
||||||
|
|
||||||
// safety checks
|
|
||||||
public static boolean checkOnlyHardLimits(Double value, String valueName, double lowLimit, double highLimit) {
|
|
||||||
return value.equals(verifyHardLimits(value, valueName, lowLimit, highLimit));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Double verifyHardLimits(Double value, String valueName, double lowLimit, double highLimit) {
|
|
||||||
Double newvalue = value;
|
|
||||||
if (newvalue < lowLimit || newvalue > highLimit) {
|
|
||||||
newvalue = Math.max(newvalue, lowLimit);
|
|
||||||
newvalue = Math.min(newvalue, highLimit);
|
|
||||||
String msg = String.format(MainApp.sResources.getString(R.string.openapsma_valueoutofrange), valueName);
|
|
||||||
msg += ".\n";
|
|
||||||
msg += String.format(MainApp.sResources.getString(R.string.openapsma_valuelimitedto), value, newvalue);
|
|
||||||
log.error(msg);
|
|
||||||
NSUpload.uploadError(msg);
|
|
||||||
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), msg, R.raw.error);
|
|
||||||
}
|
|
||||||
return newvalue;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@ import org.mozilla.javascript.NativeObject;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import info.nightscout.androidaps.data.IobTotal;
|
|
||||||
import info.nightscout.androidaps.plugins.Loop.APSResult;
|
import info.nightscout.androidaps.plugins.Loop.APSResult;
|
||||||
|
|
||||||
public class DetermineBasalResultMA extends APSResult {
|
public class DetermineBasalResultMA extends APSResult {
|
||||||
|
@ -16,13 +15,12 @@ public class DetermineBasalResultMA extends APSResult {
|
||||||
public double eventualBG;
|
public double eventualBG;
|
||||||
public double snoozeBG;
|
public double snoozeBG;
|
||||||
public String mealAssist;
|
public String mealAssist;
|
||||||
public IobTotal iob;
|
|
||||||
|
|
||||||
public DetermineBasalResultMA(NativeObject result, JSONObject j) {
|
public DetermineBasalResultMA(NativeObject result, JSONObject j) {
|
||||||
json = j;
|
json = j;
|
||||||
if (result.containsKey("error")) {
|
if (result.containsKey("error")) {
|
||||||
reason = (String) result.get("error");
|
reason = (String) result.get("error");
|
||||||
changeRequested = false;
|
tempBasalReqested = false;
|
||||||
rate = -1;
|
rate = -1;
|
||||||
duration = -1;
|
duration = -1;
|
||||||
mealAssist = "";
|
mealAssist = "";
|
||||||
|
@ -33,17 +31,17 @@ public class DetermineBasalResultMA extends APSResult {
|
||||||
if (result.containsKey("rate")) {
|
if (result.containsKey("rate")) {
|
||||||
rate = (Double) result.get("rate");
|
rate = (Double) result.get("rate");
|
||||||
if (rate < 0d) rate = 0d;
|
if (rate < 0d) rate = 0d;
|
||||||
changeRequested = true;
|
tempBasalReqested = true;
|
||||||
} else {
|
} else {
|
||||||
rate = -1;
|
rate = -1;
|
||||||
changeRequested = false;
|
tempBasalReqested = false;
|
||||||
}
|
}
|
||||||
if (result.containsKey("duration")) {
|
if (result.containsKey("duration")) {
|
||||||
duration = ((Double) result.get("duration")).intValue();
|
duration = ((Double) result.get("duration")).intValue();
|
||||||
//changeRequested as above
|
//changeRequested as above
|
||||||
} else {
|
} else {
|
||||||
duration = -1;
|
duration = -1;
|
||||||
changeRequested = false;
|
tempBasalReqested = false;
|
||||||
}
|
}
|
||||||
if (result.containsKey("mealAssist")) {
|
if (result.containsKey("mealAssist")) {
|
||||||
mealAssist = result.get("mealAssist").toString();
|
mealAssist = result.get("mealAssist").toString();
|
||||||
|
@ -60,10 +58,10 @@ public class DetermineBasalResultMA extends APSResult {
|
||||||
newResult.reason = new String(reason);
|
newResult.reason = new String(reason);
|
||||||
newResult.rate = rate;
|
newResult.rate = rate;
|
||||||
newResult.duration = duration;
|
newResult.duration = duration;
|
||||||
newResult.changeRequested = changeRequested;
|
newResult.tempBasalReqested = isChangeRequested();
|
||||||
newResult.rate = rate;
|
newResult.rate = rate;
|
||||||
newResult.duration = duration;
|
newResult.duration = duration;
|
||||||
newResult.changeRequested = changeRequested;
|
newResult.tempBasalReqested = isChangeRequested();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
newResult.json = new JSONObject(json.toString());
|
newResult.json = new JSONObject(json.toString());
|
||||||
|
@ -72,7 +70,7 @@ public class DetermineBasalResultMA extends APSResult {
|
||||||
}
|
}
|
||||||
newResult.eventualBG = eventualBG;
|
newResult.eventualBG = eventualBG;
|
||||||
newResult.snoozeBG = snoozeBG;
|
newResult.snoozeBG = snoozeBG;
|
||||||
newResult.mealAssist = new String(mealAssist);
|
newResult.mealAssist = mealAssist;
|
||||||
return newResult;
|
return newResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,6 @@ import java.io.IOException;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
import info.nightscout.androidaps.Config;
|
import info.nightscout.androidaps.Config;
|
||||||
import info.nightscout.androidaps.Constants;
|
|
||||||
import info.nightscout.androidaps.MainApp;
|
import info.nightscout.androidaps.MainApp;
|
||||||
import info.nightscout.androidaps.R;
|
import info.nightscout.androidaps.R;
|
||||||
import info.nightscout.androidaps.data.GlucoseStatus;
|
import info.nightscout.androidaps.data.GlucoseStatus;
|
||||||
|
@ -18,19 +17,21 @@ import info.nightscout.androidaps.data.Profile;
|
||||||
import info.nightscout.androidaps.db.TempTarget;
|
import info.nightscout.androidaps.db.TempTarget;
|
||||||
import info.nightscout.androidaps.interfaces.APSInterface;
|
import info.nightscout.androidaps.interfaces.APSInterface;
|
||||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||||
|
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||||
import info.nightscout.androidaps.plugins.Loop.APSResult;
|
import info.nightscout.androidaps.plugins.Loop.APSResult;
|
||||||
import info.nightscout.androidaps.plugins.Loop.ScriptReader;
|
import info.nightscout.androidaps.plugins.Loop.ScriptReader;
|
||||||
import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateGui;
|
import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateGui;
|
||||||
import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateResultGui;
|
import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateResultGui;
|
||||||
import info.nightscout.utils.DateUtil;
|
import info.nightscout.utils.DateUtil;
|
||||||
|
import info.nightscout.utils.HardLimits;
|
||||||
import info.nightscout.utils.Profiler;
|
import info.nightscout.utils.Profiler;
|
||||||
import info.nightscout.utils.Round;
|
import info.nightscout.utils.Round;
|
||||||
import info.nightscout.utils.SP;
|
import info.nightscout.utils.SP;
|
||||||
import info.nightscout.utils.SafeParse;
|
import info.nightscout.utils.SafeParse;
|
||||||
|
|
||||||
import static info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin.checkOnlyHardLimits;
|
import static info.nightscout.utils.HardLimits.checkOnlyHardLimits;
|
||||||
import static info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin.verifyHardLimits;
|
import static info.nightscout.utils.HardLimits.verifyHardLimits;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by mike on 05.08.2016.
|
* Created by mike on 05.08.2016.
|
||||||
|
@ -147,6 +148,7 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface {
|
||||||
|
|
||||||
GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData();
|
GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData();
|
||||||
Profile profile = MainApp.getConfigBuilder().getProfile();
|
Profile profile = MainApp.getConfigBuilder().getProfile();
|
||||||
|
PumpInterface pump = ConfigBuilderPlugin.getActivePump();
|
||||||
|
|
||||||
if (profile == null) {
|
if (profile == null) {
|
||||||
MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.instance().getString(R.string.noprofileselected)));
|
MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.instance().getString(R.string.noprofileselected)));
|
||||||
|
@ -195,26 +197,29 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface {
|
||||||
maxIob = MainApp.getConfigBuilder().applyMaxIOBConstraints(maxIob);
|
maxIob = MainApp.getConfigBuilder().applyMaxIOBConstraints(maxIob);
|
||||||
Profiler.log(log, "MA data gathering", start);
|
Profiler.log(log, "MA data gathering", start);
|
||||||
|
|
||||||
minBg = verifyHardLimits(minBg, "minBg", Constants.VERY_HARD_LIMIT_MIN_BG[0], Constants.VERY_HARD_LIMIT_MIN_BG[1]);
|
minBg = verifyHardLimits(minBg, "minBg", HardLimits.VERY_HARD_LIMIT_MIN_BG[0], HardLimits.VERY_HARD_LIMIT_MIN_BG[1]);
|
||||||
maxBg = verifyHardLimits(maxBg, "maxBg", Constants.VERY_HARD_LIMIT_MAX_BG[0], Constants.VERY_HARD_LIMIT_MAX_BG[1]);
|
maxBg = verifyHardLimits(maxBg, "maxBg", HardLimits.VERY_HARD_LIMIT_MAX_BG[0], HardLimits.VERY_HARD_LIMIT_MAX_BG[1]);
|
||||||
targetBg = verifyHardLimits(targetBg, "targetBg", Constants.VERY_HARD_LIMIT_TARGET_BG[0], Constants.VERY_HARD_LIMIT_TARGET_BG[1]);
|
targetBg = verifyHardLimits(targetBg, "targetBg", HardLimits.VERY_HARD_LIMIT_TARGET_BG[0], HardLimits.VERY_HARD_LIMIT_TARGET_BG[1]);
|
||||||
|
|
||||||
TempTarget tempTarget = MainApp.getConfigBuilder().getTempTargetFromHistory(System.currentTimeMillis());
|
TempTarget tempTarget = MainApp.getConfigBuilder().getTempTargetFromHistory(System.currentTimeMillis());
|
||||||
if (tempTarget != null) {
|
if (tempTarget != null) {
|
||||||
minBg = verifyHardLimits(tempTarget.low, "minBg", Constants.VERY_HARD_LIMIT_TEMP_MIN_BG[0], Constants.VERY_HARD_LIMIT_TEMP_MIN_BG[1]);
|
minBg = verifyHardLimits(tempTarget.low, "minBg", HardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[0], HardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[1]);
|
||||||
maxBg = verifyHardLimits(tempTarget.high, "maxBg", Constants.VERY_HARD_LIMIT_TEMP_MAX_BG[0], Constants.VERY_HARD_LIMIT_TEMP_MAX_BG[1]);
|
maxBg = verifyHardLimits(tempTarget.high, "maxBg", HardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[0], HardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[1]);
|
||||||
targetBg = verifyHardLimits((tempTarget.low + tempTarget.high) / 2, "targetBg", Constants.VERY_HARD_LIMIT_TEMP_TARGET_BG[0], Constants.VERY_HARD_LIMIT_TEMP_TARGET_BG[1]);
|
targetBg = verifyHardLimits((tempTarget.low + tempTarget.high) / 2, "targetBg", HardLimits.VERY_HARD_LIMIT_TEMP_TARGET_BG[0], HardLimits.VERY_HARD_LIMIT_TEMP_TARGET_BG[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
maxIob = verifyHardLimits(maxIob, "maxIob", 0, 7);
|
maxIob = verifyHardLimits(maxIob, "maxIob", 0, HardLimits.maxIobAMA());
|
||||||
maxBasal = verifyHardLimits(maxBasal, "max_basal", 0.1, 10);
|
maxBasal = verifyHardLimits(maxBasal, "max_basal", 0.1, HardLimits.maxBasal());
|
||||||
|
|
||||||
if (!checkOnlyHardLimits(profile.getDia(), "dia", 2, 7)) return;
|
if (!checkOnlyHardLimits(profile.getDia(), "dia", HardLimits.MINDIA, HardLimits.MAXDIA))
|
||||||
if (!checkOnlyHardLimits(profile.getIc(), "carbratio", 2, 100)) return;
|
|
||||||
if (!checkOnlyHardLimits(Profile.toMgdl(profile.getIsf(), units), "sens", 2, 900))
|
|
||||||
return;
|
return;
|
||||||
if (!checkOnlyHardLimits(profile.getMaxDailyBasal(), "max_daily_basal", 0.1, 10)) return;
|
if (!checkOnlyHardLimits(profile.getIc(profile.secondsFromMidnight()), "carbratio", HardLimits.MINIC, HardLimits.MAXIC))
|
||||||
if (!checkOnlyHardLimits(ConfigBuilderPlugin.getActivePump().getBaseBasalRate(), "current_basal", 0.01, 5))
|
return;
|
||||||
|
if (!checkOnlyHardLimits(Profile.toMgdl(profile.getIsf().doubleValue(), units), "sens", HardLimits.MINISF, HardLimits.MAXISF))
|
||||||
|
return;
|
||||||
|
if (!checkOnlyHardLimits(profile.getMaxDailyBasal(), "max_daily_basal", 0.1, HardLimits.maxBasal()))
|
||||||
|
return;
|
||||||
|
if (!checkOnlyHardLimits(pump.getBaseBasalRate(), "current_basal", 0.01, HardLimits.maxBasal()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
start = new Date();
|
start = new Date();
|
||||||
|
@ -229,15 +234,15 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface {
|
||||||
DetermineBasalResultMA determineBasalResultMA = determineBasalAdapterMAJS.invoke();
|
DetermineBasalResultMA determineBasalResultMA = determineBasalAdapterMAJS.invoke();
|
||||||
// Fix bug determinef basal
|
// Fix bug determinef basal
|
||||||
if (determineBasalResultMA.rate == 0d && determineBasalResultMA.duration == 0 && !MainApp.getConfigBuilder().isTempBasalInProgress())
|
if (determineBasalResultMA.rate == 0d && determineBasalResultMA.duration == 0 && !MainApp.getConfigBuilder().isTempBasalInProgress())
|
||||||
determineBasalResultMA.changeRequested = false;
|
determineBasalResultMA.tempBasalReqested = false;
|
||||||
// limit requests on openloop mode
|
// limit requests on openloop mode
|
||||||
if (!MainApp.getConfigBuilder().isClosedModeEnabled()) {
|
if (!MainApp.getConfigBuilder().isClosedModeEnabled()) {
|
||||||
if (MainApp.getConfigBuilder().isTempBasalInProgress() && determineBasalResultMA.rate == 0 && determineBasalResultMA.duration == 0) {
|
if (MainApp.getConfigBuilder().isTempBasalInProgress() && determineBasalResultMA.rate == 0 && determineBasalResultMA.duration == 0) {
|
||||||
// going to cancel
|
// going to cancel
|
||||||
} else if (MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultMA.rate - MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory()) < 0.1) {
|
} else if (MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultMA.rate - MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory()) < 0.1) {
|
||||||
determineBasalResultMA.changeRequested = false;
|
determineBasalResultMA.tempBasalReqested = false;
|
||||||
} else if (!MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultMA.rate - ConfigBuilderPlugin.getActivePump().getBaseBasalRate()) < 0.1)
|
} else if (!MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultMA.rate - ConfigBuilderPlugin.getActivePump().getBaseBasalRate()) < 0.1)
|
||||||
determineBasalResultMA.changeRequested = false;
|
determineBasalResultMA.tempBasalReqested = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
determineBasalResultMA.iob = iobTotal;
|
determineBasalResultMA.iob = iobTotal;
|
||||||
|
|
|
@ -0,0 +1,344 @@
|
||||||
|
package info.nightscout.androidaps.plugins.OpenAPSSMB;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
import org.mozilla.javascript.Callable;
|
||||||
|
import org.mozilla.javascript.Context;
|
||||||
|
import org.mozilla.javascript.Function;
|
||||||
|
import org.mozilla.javascript.NativeJSON;
|
||||||
|
import org.mozilla.javascript.NativeObject;
|
||||||
|
import org.mozilla.javascript.RhinoException;
|
||||||
|
import org.mozilla.javascript.Scriptable;
|
||||||
|
import org.mozilla.javascript.ScriptableObject;
|
||||||
|
import org.mozilla.javascript.Undefined;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
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.interfaces.PluginBase;
|
||||||
|
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||||
|
import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin;
|
||||||
|
import info.nightscout.androidaps.plugins.Loop.ScriptReader;
|
||||||
|
import info.nightscout.androidaps.plugins.OpenAPSMA.LoggerCallback;
|
||||||
|
import info.nightscout.androidaps.plugins.SourceDexcomG5.SourceDexcomG5Plugin;
|
||||||
|
import info.nightscout.utils.SP;
|
||||||
|
import info.nightscout.utils.SafeParse;
|
||||||
|
|
||||||
|
public class DetermineBasalAdapterSMBJS {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(DetermineBasalAdapterSMBJS.class);
|
||||||
|
|
||||||
|
|
||||||
|
private ScriptReader mScriptReader = null;
|
||||||
|
private JSONObject mProfile;
|
||||||
|
private JSONObject mGlucoseStatus;
|
||||||
|
private JSONArray mIobData;
|
||||||
|
private JSONObject mMealData;
|
||||||
|
private JSONObject mCurrentTemp;
|
||||||
|
private JSONObject mAutosensData = null;
|
||||||
|
private boolean mMicrobolusAllowed;
|
||||||
|
|
||||||
|
private String storedCurrentTemp = null;
|
||||||
|
private String storedIobData = null;
|
||||||
|
|
||||||
|
private String storedGlucoseStatus = null;
|
||||||
|
private String storedProfile = null;
|
||||||
|
private String storedMeal_data = null;
|
||||||
|
private String storedAutosens_data = null;
|
||||||
|
private String storedMicroBolusAllowed = null;
|
||||||
|
|
||||||
|
private String scriptDebug = "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main code
|
||||||
|
*/
|
||||||
|
|
||||||
|
public DetermineBasalAdapterSMBJS(ScriptReader scriptReader) throws IOException {
|
||||||
|
mScriptReader = scriptReader;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public DetermineBasalResultSMB invoke() {
|
||||||
|
|
||||||
|
|
||||||
|
log.debug(">>> Invoking detemine_basal <<<");
|
||||||
|
log.debug("Glucose status: " + (storedGlucoseStatus = mGlucoseStatus.toString()));
|
||||||
|
log.debug("IOB data: " + (storedIobData = mIobData.toString()));
|
||||||
|
log.debug("Current temp: " + (storedCurrentTemp = mCurrentTemp.toString()));
|
||||||
|
log.debug("Profile: " + (storedProfile = mProfile.toString()));
|
||||||
|
log.debug("Meal data: " + (storedMeal_data = mMealData.toString()));
|
||||||
|
if (mAutosensData != null)
|
||||||
|
log.debug("Autosens data: " + (storedAutosens_data = mAutosensData.toString()));
|
||||||
|
else
|
||||||
|
log.debug("Autosens data: " + (storedAutosens_data = "undefined"));
|
||||||
|
log.debug("Reservoir data: " + "undefined");
|
||||||
|
log.debug("MicroBolusAllowed: " + (storedMicroBolusAllowed = "" + mMicrobolusAllowed));
|
||||||
|
|
||||||
|
DetermineBasalResultSMB determineBasalResultSMB = null;
|
||||||
|
|
||||||
|
Context rhino = Context.enter();
|
||||||
|
Scriptable scope = rhino.initStandardObjects();
|
||||||
|
// Turn off optimization to make Rhino Android compatible
|
||||||
|
rhino.setOptimizationLevel(-1);
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
//register logger callback for console.log and console.error
|
||||||
|
ScriptableObject.defineClass(scope, LoggerCallback.class);
|
||||||
|
Scriptable myLogger = rhino.newObject(scope, "LoggerCallback", null);
|
||||||
|
scope.put("console2", scope, myLogger);
|
||||||
|
rhino.evaluateString(scope, readFile("OpenAPSAMA/loggerhelper.js"), "JavaScript", 0, null);
|
||||||
|
|
||||||
|
//set module parent
|
||||||
|
rhino.evaluateString(scope, "var module = {\"parent\":Boolean(1)};", "JavaScript", 0, null);
|
||||||
|
rhino.evaluateString(scope, "var round_basal = function round_basal(basal, profile) { return basal; };", "JavaScript", 0, null);
|
||||||
|
rhino.evaluateString(scope, "require = function() {return round_basal;};", "JavaScript", 0, null);
|
||||||
|
|
||||||
|
//generate functions "determine_basal" and "setTempBasal"
|
||||||
|
rhino.evaluateString(scope, readFile("OpenAPSSMB/determine-basal.js"), "JavaScript", 0, null);
|
||||||
|
rhino.evaluateString(scope, readFile("OpenAPSSMB/basal-set-temp.js"), "setTempBasal.js", 0, null);
|
||||||
|
Object determineBasalObj = scope.get("determine_basal", scope);
|
||||||
|
Object setTempBasalFunctionsObj = scope.get("tempBasalFunctions", scope);
|
||||||
|
|
||||||
|
//call determine-basal
|
||||||
|
if (determineBasalObj instanceof Function && setTempBasalFunctionsObj instanceof NativeObject) {
|
||||||
|
Function determineBasalJS = (Function) determineBasalObj;
|
||||||
|
|
||||||
|
//prepare parameters
|
||||||
|
Object[] params = new Object[]{
|
||||||
|
makeParam(mGlucoseStatus, rhino, scope),
|
||||||
|
makeParam(mCurrentTemp, rhino, scope),
|
||||||
|
makeParamArray(mIobData, rhino, scope),
|
||||||
|
makeParam(mProfile, rhino, scope),
|
||||||
|
makeParam(mAutosensData, rhino, scope),
|
||||||
|
makeParam(mMealData, rhino, scope),
|
||||||
|
setTempBasalFunctionsObj,
|
||||||
|
new Boolean(mMicrobolusAllowed),
|
||||||
|
makeParam(null, rhino, scope) // reservoir data as undefined
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
NativeObject jsResult = (NativeObject) determineBasalJS.call(rhino, scope, scope, params);
|
||||||
|
scriptDebug = LoggerCallback.getScriptDebug();
|
||||||
|
|
||||||
|
// Parse the jsResult object to a JSON-String
|
||||||
|
String result = NativeJSON.stringify(rhino, scope, jsResult, null, null).toString();
|
||||||
|
if (Config.logAPSResult)
|
||||||
|
log.debug("Result: " + result);
|
||||||
|
try {
|
||||||
|
determineBasalResultSMB = new DetermineBasalResultSMB(new JSONObject(result));
|
||||||
|
} catch (JSONException e) {
|
||||||
|
log.error("Unhandled exception", e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.debug("Problem loading JS Functions");
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.debug("IOException");
|
||||||
|
} catch (RhinoException e) {
|
||||||
|
log.error("RhinoException: (" + e.lineNumber() + "," + e.columnNumber() + ") " + e.toString());
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
log.error(e.toString());
|
||||||
|
} catch (InstantiationException e) {
|
||||||
|
log.error(e.toString());
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
log.error(e.toString());
|
||||||
|
} finally {
|
||||||
|
Context.exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
storedGlucoseStatus = mGlucoseStatus.toString();
|
||||||
|
storedIobData = mIobData.toString();
|
||||||
|
storedCurrentTemp = mCurrentTemp.toString();
|
||||||
|
storedProfile = mProfile.toString();
|
||||||
|
storedMeal_data = mMealData.toString();
|
||||||
|
|
||||||
|
return determineBasalResultSMB;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
String getGlucoseStatusParam() {
|
||||||
|
return storedGlucoseStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getCurrentTempParam() {
|
||||||
|
return storedCurrentTemp;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getIobDataParam() {
|
||||||
|
return storedIobData;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getProfileParam() {
|
||||||
|
return storedProfile;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getMealDataParam() {
|
||||||
|
return storedMeal_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getAutosensDataParam() {
|
||||||
|
return storedAutosens_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getMicroBolusAllowedParam() {
|
||||||
|
return storedMicroBolusAllowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getScriptDebug() {
|
||||||
|
return scriptDebug;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setData(Profile profile,
|
||||||
|
double maxIob,
|
||||||
|
double maxBasal,
|
||||||
|
double minBg,
|
||||||
|
double maxBg,
|
||||||
|
double targetBg,
|
||||||
|
double basalrate,
|
||||||
|
IobTotal[] iobArray,
|
||||||
|
GlucoseStatus glucoseStatus,
|
||||||
|
MealData mealData,
|
||||||
|
double autosensDataRatio,
|
||||||
|
boolean tempTargetSet,
|
||||||
|
boolean microBolusAllowed
|
||||||
|
) throws JSONException {
|
||||||
|
|
||||||
|
String units = profile.getUnits();
|
||||||
|
|
||||||
|
mProfile = new JSONObject();
|
||||||
|
|
||||||
|
mProfile.put("max_iob", maxIob);
|
||||||
|
mProfile.put("dia", profile.getDia());
|
||||||
|
mProfile.put("type", "current");
|
||||||
|
mProfile.put("max_daily_basal", profile.getMaxDailyBasal());
|
||||||
|
mProfile.put("max_basal", maxBasal);
|
||||||
|
mProfile.put("min_bg", minBg);
|
||||||
|
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.getInt("openapsama_current_basal_safety_multiplier", 4));
|
||||||
|
|
||||||
|
mProfile.put("high_temptarget_raises_sensitivity", SMBDefaults.high_temptarget_raises_sensitivity);
|
||||||
|
mProfile.put("low_temptarget_lowers_sensitivity", SMBDefaults.low_temptarget_lowers_sensitivity);
|
||||||
|
mProfile.put("sensitivity_raises_target", SMBDefaults.sensitivity_raises_target);
|
||||||
|
mProfile.put("resistance_lowers_target", SMBDefaults.resistance_lowers_target);
|
||||||
|
mProfile.put("adv_target_adjustments", SMBDefaults.adv_target_adjustments);
|
||||||
|
mProfile.put("exercise_mode", SMBDefaults.exercise_mode);
|
||||||
|
mProfile.put("half_basal_exercise_target", SMBDefaults.half_basal_exercise_target);
|
||||||
|
mProfile.put("maxCOB", SMBDefaults.maxCOB);
|
||||||
|
mProfile.put("skip_neutral_temps", SMBDefaults.skip_neutral_temps);
|
||||||
|
mProfile.put("min_5m_carbimpact", SP.getInt("openapsama_min_5m_carbimpact", SMBDefaults.min_5m_carbimpact));;
|
||||||
|
mProfile.put("remainingCarbsCap", SMBDefaults.remainingCarbsCap);
|
||||||
|
mProfile.put("enableUAM", SP.getBoolean(R.string.key_use_uam, false));
|
||||||
|
mProfile.put("A52_risk_enable", SMBDefaults.A52_risk_enable);
|
||||||
|
mProfile.put("enableSMB_with_COB", SP.getBoolean(R.string.key_use_smb, false) && SP.getBoolean(R.string.key_enableSMB_with_COB, false));
|
||||||
|
mProfile.put("enableSMB_with_temptarget", SP.getBoolean(R.string.key_use_smb, false) && SP.getBoolean(R.string.key_enableSMB_with_temptarget, false));
|
||||||
|
mProfile.put("allowSMB_with_high_temptarget", SP.getBoolean(R.string.key_use_smb, false) && SP.getBoolean(R.string.key_allowSMB_with_high_temptarget, false));
|
||||||
|
mProfile.put("enableSMB_always", SP.getBoolean(R.string.key_use_smb, false) && SP.getBoolean(R.string.key_enableSMB_always, false) && ConfigBuilderPlugin.getActiveBgSource().advancedFilteringSupported());
|
||||||
|
mProfile.put("enableSMB_after_carbs", SP.getBoolean(R.string.key_use_smb, false) && SP.getBoolean(R.string.key_enableSMB_after_carbs, false) && ConfigBuilderPlugin.getActiveBgSource().advancedFilteringSupported());
|
||||||
|
mProfile.put("maxSMBBasalMinutes", SP.getInt("key_smbmaxminutes", SMBDefaults.maxSMBBasalMinutes));
|
||||||
|
mProfile.put("carbsReqThreshold", SMBDefaults.carbsReqThreshold);
|
||||||
|
|
||||||
|
mProfile.put("current_basal", basalrate);
|
||||||
|
mProfile.put("temptargetSet", tempTargetSet);
|
||||||
|
mProfile.put("autosens_max", SafeParse.stringToDouble(SP.getString("openapsama_autosens_max", "1.2")));
|
||||||
|
|
||||||
|
if (units.equals(Constants.MMOL)) {
|
||||||
|
mProfile.put("out_units", "mmol/L");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
mCurrentTemp = new JSONObject();
|
||||||
|
mCurrentTemp.put("temp", "absolute");
|
||||||
|
mCurrentTemp.put("duration", MainApp.getConfigBuilder().getTempBasalRemainingMinutesFromHistory());
|
||||||
|
mCurrentTemp.put("rate", MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory());
|
||||||
|
|
||||||
|
// as we have non default temps longer than 30 mintues
|
||||||
|
TemporaryBasal tempBasal = MainApp.getConfigBuilder().getTempBasalFromHistory(System.currentTimeMillis());
|
||||||
|
if (tempBasal != null) {
|
||||||
|
mCurrentTemp.put("minutesrunning", tempBasal.getRealDuration());
|
||||||
|
}
|
||||||
|
|
||||||
|
mIobData = IobCobCalculatorPlugin.convertToJSONArray(iobArray);
|
||||||
|
|
||||||
|
mGlucoseStatus = new JSONObject();
|
||||||
|
mGlucoseStatus.put("glucose", glucoseStatus.glucose);
|
||||||
|
|
||||||
|
if (SP.getBoolean("always_use_shortavg", false)) {
|
||||||
|
mGlucoseStatus.put("delta", glucoseStatus.short_avgdelta);
|
||||||
|
} else {
|
||||||
|
mGlucoseStatus.put("delta", glucoseStatus.delta);
|
||||||
|
}
|
||||||
|
mGlucoseStatus.put("short_avgdelta", glucoseStatus.short_avgdelta);
|
||||||
|
mGlucoseStatus.put("long_avgdelta", glucoseStatus.long_avgdelta);
|
||||||
|
mGlucoseStatus.put("date", glucoseStatus.date);
|
||||||
|
|
||||||
|
mMealData = new JSONObject();
|
||||||
|
mMealData.put("carbs", mealData.carbs);
|
||||||
|
mMealData.put("boluses", mealData.boluses);
|
||||||
|
mMealData.put("mealCOB", mealData.mealCOB);
|
||||||
|
mMealData.put("slopeFromMaxDeviation", mealData.slopeFromMaxDeviation);
|
||||||
|
mMealData.put("slopeFromMinDeviation", mealData.slopeFromMinDeviation);
|
||||||
|
mMealData.put("lastBolusTime", mealData.lastBolusTime);
|
||||||
|
mMealData.put("lastCarbTime", mealData.lastCarbTime);
|
||||||
|
|
||||||
|
|
||||||
|
if (MainApp.getConfigBuilder().isAMAModeEnabled()) {
|
||||||
|
mAutosensData = new JSONObject();
|
||||||
|
mAutosensData.put("ratio", autosensDataRatio);
|
||||||
|
} else {
|
||||||
|
mAutosensData = new JSONObject();
|
||||||
|
mAutosensData.put("ratio", 1.0);
|
||||||
|
}
|
||||||
|
mMicrobolusAllowed = microBolusAllowed;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object makeParam(JSONObject jsonObject, Context rhino, Scriptable scope) {
|
||||||
|
|
||||||
|
if (jsonObject == null) return Undefined.instance;
|
||||||
|
|
||||||
|
Object param = NativeJSON.parse(rhino, scope, jsonObject.toString(), new Callable() {
|
||||||
|
@Override
|
||||||
|
public Object call(Context context, Scriptable scriptable, Scriptable scriptable1, Object[] objects) {
|
||||||
|
return objects[1];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return param;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object makeParamArray(JSONArray jsonArray, Context rhino, Scriptable scope) {
|
||||||
|
//Object param = NativeJSON.parse(rhino, scope, "{myarray: " + jsonArray.toString() + " }", new Callable() {
|
||||||
|
Object param = NativeJSON.parse(rhino, scope, jsonArray.toString(), new Callable() {
|
||||||
|
@Override
|
||||||
|
public Object call(Context context, Scriptable scriptable, Scriptable scriptable1, Object[] objects) {
|
||||||
|
return objects[1];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return param;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String readFile(String filename) throws IOException {
|
||||||
|
byte[] bytes = mScriptReader.readFile(filename);
|
||||||
|
String string = new String(bytes, "UTF-8");
|
||||||
|
if (string.startsWith("#!/usr/bin/env node")) {
|
||||||
|
string = string.substring(20);
|
||||||
|
}
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,104 @@
|
||||||
|
package info.nightscout.androidaps.plugins.OpenAPSSMB;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.plugins.Loop.APSResult;
|
||||||
|
import info.nightscout.utils.DateUtil;
|
||||||
|
|
||||||
|
public class DetermineBasalResultSMB extends APSResult {
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(DetermineBasalResultSMB.class);
|
||||||
|
|
||||||
|
public double eventualBG;
|
||||||
|
public double snoozeBG;
|
||||||
|
public double insulinReq;
|
||||||
|
public double carbsReq;
|
||||||
|
|
||||||
|
public DetermineBasalResultSMB(JSONObject result) {
|
||||||
|
this();
|
||||||
|
date = new Date();
|
||||||
|
json = result;
|
||||||
|
try {
|
||||||
|
if (result.has("error")) {
|
||||||
|
reason = result.getString("error");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
reason = result.getString("reason");
|
||||||
|
if (result.has("eventualBG")) eventualBG = result.getDouble("eventualBG");
|
||||||
|
if (result.has("snoozeBG")) snoozeBG = result.getDouble("snoozeBG");
|
||||||
|
if (result.has("insulinReq")) insulinReq = result.getDouble("insulinReq");
|
||||||
|
if (result.has("carbsReq")) carbsReq = result.getDouble("carbsReq");
|
||||||
|
|
||||||
|
if (result.has("rate") && result.has("duration")) {
|
||||||
|
tempBasalReqested = true;
|
||||||
|
rate = result.getDouble("rate");
|
||||||
|
if (rate < 0d) rate = 0d;
|
||||||
|
duration = result.getInt("duration");
|
||||||
|
} else {
|
||||||
|
rate = -1;
|
||||||
|
duration = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.has("units")) {
|
||||||
|
bolusRequested = true;
|
||||||
|
smb = result.getDouble("units");
|
||||||
|
} else {
|
||||||
|
smb = 0d;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.has("deliverAt")) {
|
||||||
|
String date = result.getString("deliverAt");
|
||||||
|
try {
|
||||||
|
deliverAt = DateUtil.fromISODateString(date).getTime();
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("Error parsing 'deliverAt' date: " + date, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (JSONException e) {
|
||||||
|
log.error("Error parsing determine-basal result JSON", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public DetermineBasalResultSMB() {
|
||||||
|
hasPredictions = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DetermineBasalResultSMB clone() {
|
||||||
|
DetermineBasalResultSMB newResult = new DetermineBasalResultSMB();
|
||||||
|
newResult.reason = reason;
|
||||||
|
newResult.rate = rate;
|
||||||
|
newResult.duration = duration;
|
||||||
|
newResult.tempBasalReqested = tempBasalReqested;
|
||||||
|
newResult.bolusRequested = bolusRequested;
|
||||||
|
newResult.rate = rate;
|
||||||
|
newResult.duration = duration;
|
||||||
|
newResult.smb = smb;
|
||||||
|
newResult.deliverAt = deliverAt;
|
||||||
|
|
||||||
|
try {
|
||||||
|
newResult.json = new JSONObject(json.toString());
|
||||||
|
} catch (JSONException e) {
|
||||||
|
log.error("Error clone parsing determine-basal result", e);
|
||||||
|
}
|
||||||
|
newResult.eventualBG = eventualBG;
|
||||||
|
newResult.snoozeBG = snoozeBG;
|
||||||
|
newResult.date = date;
|
||||||
|
return newResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JSONObject json() {
|
||||||
|
try {
|
||||||
|
return new JSONObject(this.json.toString());
|
||||||
|
} catch (JSONException e) {
|
||||||
|
log.error("Error converting determine-basal result to JSON", e);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,142 @@
|
||||||
|
package info.nightscout.androidaps.plugins.OpenAPSSMB;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.crashlytics.android.answers.Answers;
|
||||||
|
import com.crashlytics.android.answers.CustomEvent;
|
||||||
|
import com.squareup.otto.Subscribe;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
import info.nightscout.androidaps.R;
|
||||||
|
import info.nightscout.androidaps.plugins.Common.SubscriberFragment;
|
||||||
|
import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateGui;
|
||||||
|
import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateResultGui;
|
||||||
|
import info.nightscout.utils.JSONFormatter;
|
||||||
|
|
||||||
|
public class OpenAPSSMBFragment extends SubscriberFragment implements View.OnClickListener {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(OpenAPSSMBFragment.class);
|
||||||
|
|
||||||
|
Button run;
|
||||||
|
TextView lastRunView;
|
||||||
|
TextView glucoseStatusView;
|
||||||
|
TextView currentTempView;
|
||||||
|
TextView iobDataView;
|
||||||
|
TextView profileView;
|
||||||
|
TextView mealDataView;
|
||||||
|
TextView autosensDataView;
|
||||||
|
TextView resultView;
|
||||||
|
TextView scriptdebugView;
|
||||||
|
TextView requestView;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
|
Bundle savedInstanceState) {
|
||||||
|
View view = inflater.inflate(R.layout.openapsama_fragment, container, false);
|
||||||
|
|
||||||
|
run = (Button) view.findViewById(R.id.openapsma_run);
|
||||||
|
run.setOnClickListener(this);
|
||||||
|
lastRunView = (TextView) view.findViewById(R.id.openapsma_lastrun);
|
||||||
|
glucoseStatusView = (TextView) view.findViewById(R.id.openapsma_glucosestatus);
|
||||||
|
currentTempView = (TextView) view.findViewById(R.id.openapsma_currenttemp);
|
||||||
|
iobDataView = (TextView) view.findViewById(R.id.openapsma_iobdata);
|
||||||
|
profileView = (TextView) view.findViewById(R.id.openapsma_profile);
|
||||||
|
mealDataView = (TextView) view.findViewById(R.id.openapsma_mealdata);
|
||||||
|
autosensDataView = (TextView) view.findViewById(R.id.openapsma_autosensdata);
|
||||||
|
scriptdebugView = (TextView) view.findViewById(R.id.openapsma_scriptdebugdata);
|
||||||
|
resultView = (TextView) view.findViewById(R.id.openapsma_result);
|
||||||
|
requestView = (TextView) view.findViewById(R.id.openapsma_request);
|
||||||
|
|
||||||
|
updateGUI();
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
switch (view.getId()) {
|
||||||
|
case R.id.openapsma_run:
|
||||||
|
OpenAPSSMBPlugin.getPlugin().invoke("OpenAPSSMB button");
|
||||||
|
Answers.getInstance().logCustom(new CustomEvent("OpenAPS_SMB_Run"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onStatusEvent(final EventOpenAPSUpdateGui ev) {
|
||||||
|
updateGUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onStatusEvent(final EventOpenAPSUpdateResultGui ev) {
|
||||||
|
updateResultGUI(ev.text);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void updateGUI() {
|
||||||
|
Activity activity = getActivity();
|
||||||
|
if (activity != null)
|
||||||
|
activity.runOnUiThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
OpenAPSSMBPlugin plugin = OpenAPSSMBPlugin.getPlugin();
|
||||||
|
DetermineBasalResultSMB lastAPSResult = plugin.lastAPSResult;
|
||||||
|
if (lastAPSResult != null) {
|
||||||
|
resultView.setText(JSONFormatter.format(lastAPSResult.json));
|
||||||
|
requestView.setText(lastAPSResult.toSpanned());
|
||||||
|
}
|
||||||
|
DetermineBasalAdapterSMBJS determineBasalAdapterSMBJS = plugin.lastDetermineBasalAdapterSMBJS;
|
||||||
|
if (determineBasalAdapterSMBJS != null) {
|
||||||
|
glucoseStatusView.setText(JSONFormatter.format(determineBasalAdapterSMBJS.getGlucoseStatusParam()));
|
||||||
|
currentTempView.setText(JSONFormatter.format(determineBasalAdapterSMBJS.getCurrentTempParam()));
|
||||||
|
try {
|
||||||
|
JSONArray iobArray = new JSONArray(determineBasalAdapterSMBJS.getIobDataParam());
|
||||||
|
iobDataView.setText(String.format(MainApp.sResources.getString(R.string.array_of_elements), iobArray.length()) + "\n" + JSONFormatter.format(iobArray.getString(0)));
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
iobDataView.setText("JSONException");
|
||||||
|
}
|
||||||
|
profileView.setText(JSONFormatter.format(determineBasalAdapterSMBJS.getProfileParam()));
|
||||||
|
mealDataView.setText(JSONFormatter.format(determineBasalAdapterSMBJS.getMealDataParam()));
|
||||||
|
scriptdebugView.setText(determineBasalAdapterSMBJS.getScriptDebug());
|
||||||
|
}
|
||||||
|
if (plugin.lastAPSRun != null) {
|
||||||
|
lastRunView.setText(plugin.lastAPSRun.toLocaleString());
|
||||||
|
}
|
||||||
|
if (plugin.lastAutosensResult != null) {
|
||||||
|
autosensDataView.setText(JSONFormatter.format(plugin.lastAutosensResult.json()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateResultGUI(final String text) {
|
||||||
|
Activity activity = getActivity();
|
||||||
|
if (activity != null)
|
||||||
|
activity.runOnUiThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
resultView.setText(text);
|
||||||
|
glucoseStatusView.setText("");
|
||||||
|
currentTempView.setText("");
|
||||||
|
iobDataView.setText("");
|
||||||
|
profileView.setText("");
|
||||||
|
mealDataView.setText("");
|
||||||
|
autosensDataView.setText("");
|
||||||
|
scriptdebugView.setText("");
|
||||||
|
requestView.setText("");
|
||||||
|
lastRunView.setText("");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,301 @@
|
||||||
|
package info.nightscout.androidaps.plugins.OpenAPSSMB;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.Config;
|
||||||
|
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.TempTarget;
|
||||||
|
import info.nightscout.androidaps.interfaces.APSInterface;
|
||||||
|
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||||
|
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||||
|
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||||
|
import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensResult;
|
||||||
|
import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin;
|
||||||
|
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.utils.DateUtil;
|
||||||
|
import info.nightscout.utils.HardLimits;
|
||||||
|
import info.nightscout.utils.NSUpload;
|
||||||
|
import info.nightscout.utils.Profiler;
|
||||||
|
import info.nightscout.utils.Round;
|
||||||
|
import info.nightscout.utils.SP;
|
||||||
|
import info.nightscout.utils.ToastUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 05.08.2016.
|
||||||
|
*/
|
||||||
|
public class OpenAPSSMBPlugin implements PluginBase, APSInterface {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(OpenAPSSMBPlugin.class);
|
||||||
|
|
||||||
|
// last values
|
||||||
|
DetermineBasalAdapterSMBJS lastDetermineBasalAdapterSMBJS = null;
|
||||||
|
Date lastAPSRun = null;
|
||||||
|
DetermineBasalResultSMB lastAPSResult = null;
|
||||||
|
AutosensResult lastAutosensResult = null;
|
||||||
|
|
||||||
|
boolean fragmentEnabled = false;
|
||||||
|
boolean fragmentVisible = true;
|
||||||
|
|
||||||
|
private static OpenAPSSMBPlugin openAPSSMBPlugin;
|
||||||
|
|
||||||
|
private OpenAPSSMBPlugin() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static OpenAPSSMBPlugin getPlugin() {
|
||||||
|
if (openAPSSMBPlugin == null) {
|
||||||
|
openAPSSMBPlugin = new OpenAPSSMBPlugin();
|
||||||
|
}
|
||||||
|
return openAPSSMBPlugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return MainApp.instance().getString(R.string.openapssmb);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getNameShort() {
|
||||||
|
String name = MainApp.sResources.getString(R.string.smb_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 == 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_openapssmb;
|
||||||
|
}
|
||||||
|
|
||||||
|
@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 OpenAPSSMBFragment.class.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public APSResult getLastAPSResult() {
|
||||||
|
return lastAPSResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Date getLastAPSRun() {
|
||||||
|
return lastAPSRun;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void invoke(String initiator) {
|
||||||
|
log.debug("invoke from " + initiator);
|
||||||
|
lastAPSResult = null;
|
||||||
|
DetermineBasalAdapterSMBJS determineBasalAdapterSMBJS = null;
|
||||||
|
try {
|
||||||
|
determineBasalAdapterSMBJS = new DetermineBasalAdapterSMBJS(new ScriptReader(MainApp.instance().getBaseContext()));
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData();
|
||||||
|
Profile profile = MainApp.getConfigBuilder().getProfile();
|
||||||
|
PumpInterface pump = ConfigBuilderPlugin.getActivePump();
|
||||||
|
|
||||||
|
if (profile == null) {
|
||||||
|
MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.instance().getString(R.string.noprofileselected)));
|
||||||
|
if (Config.logAPSResult)
|
||||||
|
log.debug(MainApp.instance().getString(R.string.noprofileselected));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isEnabled(PluginBase.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));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (glucoseStatus == null) {
|
||||||
|
MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.instance().getString(R.string.openapsma_noglucosedata)));
|
||||||
|
if (Config.logAPSResult)
|
||||||
|
log.debug(MainApp.instance().getString(R.string.openapsma_noglucosedata));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String units = profile.getUnits();
|
||||||
|
|
||||||
|
double maxIob = SP.getDouble("openapsma_max_iob", 1.5d);
|
||||||
|
double maxBasal = SP.getDouble("openapsma_max_basal", 1d);
|
||||||
|
double minBg = Profile.toMgdl(profile.getTargetLow(), units);
|
||||||
|
double maxBg = Profile.toMgdl(profile.getTargetHigh(), units);
|
||||||
|
double targetBg = (minBg + maxBg) / 2;
|
||||||
|
|
||||||
|
minBg = Round.roundTo(minBg, 0.1d);
|
||||||
|
maxBg = Round.roundTo(maxBg, 0.1d);
|
||||||
|
|
||||||
|
Date start = new Date();
|
||||||
|
Date startPart = new Date();
|
||||||
|
IobTotal[] iobArray = IobCobCalculatorPlugin.getPlugin().calculateIobArrayForSMB();
|
||||||
|
Profiler.log(log, "calculateIobArrayInDia()", startPart);
|
||||||
|
|
||||||
|
startPart = new Date();
|
||||||
|
MealData mealData = MainApp.getConfigBuilder().getMealData();
|
||||||
|
Profiler.log(log, "getMealData()", startPart);
|
||||||
|
|
||||||
|
maxIob = MainApp.getConfigBuilder().applyMaxIOBConstraints(maxIob);
|
||||||
|
|
||||||
|
minBg = verifyHardLimits(minBg, "minBg", HardLimits.VERY_HARD_LIMIT_MIN_BG[0], HardLimits.VERY_HARD_LIMIT_MIN_BG[1]);
|
||||||
|
maxBg = verifyHardLimits(maxBg, "maxBg", HardLimits.VERY_HARD_LIMIT_MAX_BG[0], HardLimits.VERY_HARD_LIMIT_MAX_BG[1]);
|
||||||
|
targetBg = 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());
|
||||||
|
if (tempTarget != null) {
|
||||||
|
isTempTarget = true;
|
||||||
|
minBg = verifyHardLimits(tempTarget.low, "minBg", HardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[0], HardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[1]);
|
||||||
|
maxBg = verifyHardLimits(tempTarget.high, "maxBg", HardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[0], HardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[1]);
|
||||||
|
targetBg = verifyHardLimits((tempTarget.low + tempTarget.high) / 2, "targetBg", HardLimits.VERY_HARD_LIMIT_TEMP_TARGET_BG[0], HardLimits.VERY_HARD_LIMIT_TEMP_TARGET_BG[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
maxIob = verifyHardLimits(maxIob, "maxIob", 0, HardLimits.maxIobSMB());
|
||||||
|
maxBasal = verifyHardLimits(maxBasal, "max_basal", 0.1, HardLimits.maxBasal());
|
||||||
|
|
||||||
|
if (!checkOnlyHardLimits(profile.getDia(), "dia", HardLimits.MINDIA, HardLimits.MAXDIA)) return;
|
||||||
|
if (!checkOnlyHardLimits(profile.getIc(profile.secondsFromMidnight()), "carbratio", HardLimits.MINIC, HardLimits.MAXIC))
|
||||||
|
return;
|
||||||
|
if (!checkOnlyHardLimits(Profile.toMgdl(profile.getIsf().doubleValue(), units), "sens", HardLimits.MINISF, HardLimits.MAXISF))
|
||||||
|
return;
|
||||||
|
if (!checkOnlyHardLimits(profile.getMaxDailyBasal(), "max_daily_basal", 0.1, HardLimits.maxBasal())) return;
|
||||||
|
if (!checkOnlyHardLimits(pump.getBaseBasalRate(), "current_basal", 0.01, HardLimits.maxBasal())) return;
|
||||||
|
|
||||||
|
startPart = new Date();
|
||||||
|
if (MainApp.getConfigBuilder().isAMAModeEnabled()) {
|
||||||
|
lastAutosensResult = IobCobCalculatorPlugin.getPlugin().detectSensitivityWithLock(IobCobCalculatorPlugin.oldestDataAvailable(), System.currentTimeMillis());
|
||||||
|
} else {
|
||||||
|
lastAutosensResult = new AutosensResult();
|
||||||
|
}
|
||||||
|
Profiler.log(log, "detectSensitivityandCarbAbsorption()", startPart);
|
||||||
|
Profiler.log(log, "SMB data gathering", start);
|
||||||
|
|
||||||
|
start = new Date();
|
||||||
|
try {
|
||||||
|
determineBasalAdapterSMBJS.setData(profile, maxIob, maxBasal, minBg, maxBg, targetBg, ConfigBuilderPlugin.getActivePump().getBaseBasalRate(), iobArray, glucoseStatus, mealData,
|
||||||
|
lastAutosensResult.ratio, //autosensDataRatio
|
||||||
|
isTempTarget,
|
||||||
|
true //microBolusAllowed
|
||||||
|
);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DetermineBasalResultSMB determineBasalResultSMB = determineBasalAdapterSMBJS.invoke();
|
||||||
|
Profiler.log(log, "SMB calculation", start);
|
||||||
|
// TODO still needed with oref1?
|
||||||
|
// Fix bug determine basal
|
||||||
|
if (determineBasalResultSMB.rate == 0d && determineBasalResultSMB.duration == 0 && !MainApp.getConfigBuilder().isTempBasalInProgress())
|
||||||
|
determineBasalResultSMB.tempBasalReqested = false;
|
||||||
|
// limit requests on openloop mode
|
||||||
|
if (!MainApp.getConfigBuilder().isClosedModeEnabled()) {
|
||||||
|
if (MainApp.getConfigBuilder().isTempBasalInProgress() && determineBasalResultSMB.rate == 0 && determineBasalResultSMB.duration == 0) {
|
||||||
|
// going to cancel
|
||||||
|
} else if (MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultSMB.rate - MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory()) < 0.1) {
|
||||||
|
determineBasalResultSMB.tempBasalReqested = false;
|
||||||
|
} else if (!MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultSMB.rate - pump.getBaseBasalRate()) < 0.1) {
|
||||||
|
determineBasalResultSMB.tempBasalReqested = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
determineBasalResultSMB.iob = iobArray[0];
|
||||||
|
Date now = new Date();
|
||||||
|
|
||||||
|
try {
|
||||||
|
determineBasalResultSMB.json.put("timestamp", DateUtil.toISOString(now));
|
||||||
|
} catch (JSONException e) {
|
||||||
|
log.error("Unhandled exception", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
lastDetermineBasalAdapterSMBJS = determineBasalAdapterSMBJS;
|
||||||
|
lastAPSResult = determineBasalResultSMB;
|
||||||
|
lastAPSRun = now;
|
||||||
|
MainApp.bus().post(new EventOpenAPSUpdateGui());
|
||||||
|
|
||||||
|
//deviceStatus.suggested = determineBasalResultAMA.json;
|
||||||
|
}
|
||||||
|
|
||||||
|
// safety checks
|
||||||
|
private static boolean checkOnlyHardLimits(Double value, String valueName, double lowLimit, double highLimit) {
|
||||||
|
return value.equals(verifyHardLimits(value, valueName, lowLimit, highLimit));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Double verifyHardLimits(Double value, String valueName, double lowLimit, double highLimit) {
|
||||||
|
Double newvalue = value;
|
||||||
|
if (newvalue < lowLimit || newvalue > highLimit) {
|
||||||
|
newvalue = Math.max(newvalue, lowLimit);
|
||||||
|
newvalue = Math.min(newvalue, highLimit);
|
||||||
|
String msg = String.format(MainApp.sResources.getString(R.string.valueoutofrange), valueName);
|
||||||
|
msg += ".\n";
|
||||||
|
msg += String.format(MainApp.sResources.getString(R.string.valuelimitedto), value, newvalue);
|
||||||
|
log.error(msg);
|
||||||
|
NSUpload.uploadError(msg);
|
||||||
|
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), msg, R.raw.error);
|
||||||
|
}
|
||||||
|
return newvalue;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
package info.nightscout.androidaps.plugins.OpenAPSSMB;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 10.12.2017.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class SMBDefaults {
|
||||||
|
// CALCULATED OR FROM PREFS
|
||||||
|
|
||||||
|
// max_iob: 0 // if max_iob is not provided, will default to zero
|
||||||
|
// max_daily_safety_multiplier:3
|
||||||
|
// current_basal_safety_multiplier:4
|
||||||
|
// autosens_max:1.2
|
||||||
|
// autosens_min:0.7
|
||||||
|
|
||||||
|
// USED IN AUTOSENS
|
||||||
|
public final static boolean rewind_resets_autosens = true; // reset autosensitivity to neutral for awhile after each pump rewind
|
||||||
|
|
||||||
|
// USED IN TARGETS
|
||||||
|
// by default the higher end of the target range is used only for avoiding bolus wizard overcorrections
|
||||||
|
// use wide_bg_target_range: true to force neutral temps over a wider range of eventualBGs
|
||||||
|
public final static boolean wide_bg_target_range = false; // by default use only the low end of the pump's BG target range as OpenAPS target
|
||||||
|
|
||||||
|
// USED IN AUTOTUNE
|
||||||
|
public final static double autotune_isf_adjustmentFraction = 1.0; // keep autotune ISF closer to pump ISF via a weighted average of fullNewISF and pumpISF. 1.0 allows full adjustment, 0 is no adjustment from pump ISF.
|
||||||
|
public final static double remainingCarbsFraction = 1.0; // fraction of carbs we'll assume will absorb over 4h if we don't yet see carb absorption
|
||||||
|
|
||||||
|
// USED IN DETERMINE_BASAL
|
||||||
|
public final static boolean low_temptarget_lowers_sensitivity = false; // lower sensitivity for temptargets <= 99.
|
||||||
|
public final static boolean high_temptarget_raises_sensitivity = false; // raise sensitivity for temptargets >= 111. synonym for exercise_mode
|
||||||
|
public final static boolean sensitivity_raises_target = true; // raise BG target when autosens detects sensitivity
|
||||||
|
public final static boolean resistance_lowers_target = false; // lower BG target when autosens detects resistance
|
||||||
|
public final static boolean adv_target_adjustments = false; // lower target automatically when BG and eventualBG are high
|
||||||
|
public final static boolean exercise_mode = false; // when true, > 105 mg/dL high temp target adjusts sensitivityRatio for exercise_mode. This majorly changes the behavior of high temp targets from before. synonmym for high_temptarget_raises_sensitivity
|
||||||
|
public final static int half_basal_exercise_target = 160; // when temptarget is 160 mg/dL *and* exercise_mode=true, run 50% basal at this level (120 = 75%; 140 = 60%)
|
||||||
|
// create maxCOB and default it to 120 because that's the most a typical body can absorb over 4 hours.
|
||||||
|
// (If someone enters more carbs or stacks more; OpenAPS will just truncate dosing based on 120.
|
||||||
|
// Essentially, this just limits AMA/SMB as a safety cap against excessive COB entry)
|
||||||
|
public final static int maxCOB = 120;
|
||||||
|
public final static boolean skip_neutral_temps = true; // ***** default false in oref1 ***** if true, don't set neutral temps
|
||||||
|
// unsuspend_if_no_temp:false // if true, pump will un-suspend after a zero temp finishes
|
||||||
|
// bolussnooze_dia_divisor:2 // bolus snooze decays after 1/2 of DIA
|
||||||
|
public final static int min_5m_carbimpact = 8; // mg/dL per 5m (8 mg/dL/5m corresponds to 24g/hr at a CSF of 4 mg/dL/g (x/5*60/4))
|
||||||
|
public final static int remainingCarbsCap = 90; // max carbs we'll assume will absorb over 4h if we don't yet see carb absorption
|
||||||
|
// WARNING: use SMB with caution: it can and will automatically bolus up to max_iob worth of extra insulin
|
||||||
|
// enableUAM:true // enable detection of unannounced meal carb absorption
|
||||||
|
public final static boolean A52_risk_enable = false;
|
||||||
|
//public final static boolean enableSMB_with_COB = true; // ***** default false in oref1 ***** enable supermicrobolus while COB is positive
|
||||||
|
//public final static boolean enableSMB_with_temptarget = true; // ***** default false in oref1 ***** enable supermicrobolus for eating soon temp targets
|
||||||
|
// *** WARNING *** DO NOT USE enableSMB_always or enableSMB_after_carbs with xDrip+, Libre, or similar
|
||||||
|
// xDrip+, LimiTTer, etc. do not properly filter out high-noise SGVs
|
||||||
|
// Using SMB overnight with such data sources risks causing a dangerous overdose of insulin
|
||||||
|
// if the CGM sensor reads falsely high and doesn't come down as actual BG does
|
||||||
|
// public final static boolean enableSMB_always = false; // always enable supermicrobolus (unless disabled by high temptarget)
|
||||||
|
// *** WARNING *** DO NOT USE enableSMB_always or enableSMB_after_carbs with xDrip+, Libre, or similar
|
||||||
|
//public final static boolean enableSMB_after_carbs = false; // enable supermicrobolus for 6h after carbs, even with 0 COB
|
||||||
|
//public final static boolean allowSMB_with_high_temptarget = false; // allow supermicrobolus (if otherwise enabled) even with high temp targets
|
||||||
|
public final static int maxSMBBasalMinutes = 30; // maximum minutes of basal that can be delivered as a single SMB with uncovered COB
|
||||||
|
// curve:"rapid-acting" // Supported curves: "bilinear", "rapid-acting" (Novolog, Novorapid, Humalog, Apidra) and "ultra-rapid" (Fiasp)
|
||||||
|
// useCustomPeakTime:false // allows changing insulinPeakTime
|
||||||
|
// insulinPeakTime:75 // number of minutes after a bolus activity peaks. defaults to 55m for Fiasp if useCustomPeakTime: false
|
||||||
|
public final static int carbsReqThreshold = 1; // grams of carbsReq to trigger a pushover
|
||||||
|
// offline_hotspot:false // enabled an offline-only local wifi hotspot if no Internet available
|
||||||
|
}
|
|
@ -19,6 +19,7 @@ import info.nightscout.androidaps.Services.AlarmSoundService;
|
||||||
|
|
||||||
public class ErrorDialog extends DialogFragment implements View.OnClickListener {
|
public class ErrorDialog extends DialogFragment implements View.OnClickListener {
|
||||||
private static Logger log = LoggerFactory.getLogger(ErrorDialog.class);
|
private static Logger log = LoggerFactory.getLogger(ErrorDialog.class);
|
||||||
|
Button muteButton;
|
||||||
Button okButton;
|
Button okButton;
|
||||||
TextView statusView;
|
TextView statusView;
|
||||||
ErrorHelperActivity helperActivity;
|
ErrorHelperActivity helperActivity;
|
||||||
|
@ -52,14 +53,14 @@ public class ErrorDialog extends DialogFragment implements View.OnClickListener
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
getDialog().setTitle(title);
|
getDialog().setTitle(title);
|
||||||
View view = inflater.inflate(R.layout.overview_error_dialog, container, false);
|
View view = inflater.inflate(R.layout.overview_error_dialog, container, false);
|
||||||
|
muteButton = (Button) view.findViewById(R.id.overview_error_mute);
|
||||||
okButton = (Button) view.findViewById(R.id.overview_error_ok);
|
okButton = (Button) view.findViewById(R.id.overview_error_ok);
|
||||||
statusView = (TextView) view.findViewById(R.id.overview_error_status);
|
statusView = (TextView) view.findViewById(R.id.overview_error_status);
|
||||||
|
muteButton.setOnClickListener(this);
|
||||||
okButton.setOnClickListener(this);
|
okButton.setOnClickListener(this);
|
||||||
setCancelable(false);
|
setCancelable(false);
|
||||||
|
|
||||||
Intent alarm = new Intent(MainApp.instance().getApplicationContext(), AlarmSoundService.class);
|
startAlarm();
|
||||||
alarm.putExtra("soundid", soundId);
|
|
||||||
MainApp.instance().startService(alarm);
|
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,13 +78,16 @@ public class ErrorDialog extends DialogFragment implements View.OnClickListener
|
||||||
if (helperActivity != null) {
|
if (helperActivity != null) {
|
||||||
helperActivity.finish();
|
helperActivity.finish();
|
||||||
}
|
}
|
||||||
Intent alarm = new Intent(MainApp.instance().getApplicationContext(), AlarmSoundService.class);
|
stopAlarm();
|
||||||
MainApp.instance().stopService(alarm);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
switch (view.getId()) {
|
switch (view.getId()) {
|
||||||
|
case R.id.overview_error_mute:
|
||||||
|
log.debug("Error dialog mute button pressed");
|
||||||
|
stopAlarm();
|
||||||
|
break;
|
||||||
case R.id.overview_error_ok:
|
case R.id.overview_error_ok:
|
||||||
log.debug("Error dialog ok button pressed");
|
log.debug("Error dialog ok button pressed");
|
||||||
dismiss();
|
dismiss();
|
||||||
|
@ -91,4 +95,14 @@ public class ErrorDialog extends DialogFragment implements View.OnClickListener
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void startAlarm() {
|
||||||
|
Intent alarm = new Intent(MainApp.instance().getApplicationContext(), AlarmSoundService.class);
|
||||||
|
alarm.putExtra("soundid", soundId);
|
||||||
|
MainApp.instance().startService(alarm);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void stopAlarm() {
|
||||||
|
Intent alarm = new Intent(MainApp.instance().getApplicationContext(), AlarmSoundService.class);
|
||||||
|
MainApp.instance().stopService(alarm);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,10 @@ package info.nightscout.androidaps.plugins.Overview.Dialogs;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v7.app.AppCompatActivity;
|
import android.support.v7.app.AppCompatActivity;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.R;
|
||||||
|
import info.nightscout.utils.NSUpload;
|
||||||
|
import info.nightscout.utils.SP;
|
||||||
|
|
||||||
public class ErrorHelperActivity extends AppCompatActivity {
|
public class ErrorHelperActivity extends AppCompatActivity {
|
||||||
public ErrorHelperActivity() {
|
public ErrorHelperActivity() {
|
||||||
super();
|
super();
|
||||||
|
@ -17,5 +21,9 @@ public class ErrorHelperActivity extends AppCompatActivity {
|
||||||
errorDialog.setSound(getIntent().getIntExtra("soundid", 0));
|
errorDialog.setSound(getIntent().getIntExtra("soundid", 0));
|
||||||
errorDialog.setTitle(getIntent().getStringExtra("title"));
|
errorDialog.setTitle(getIntent().getStringExtra("title"));
|
||||||
errorDialog.show(this.getSupportFragmentManager(), "Error");
|
errorDialog.show(this.getSupportFragmentManager(), "Error");
|
||||||
|
|
||||||
|
if (SP.getBoolean(R.string.key_ns_create_announcements_from_errors, true)) {
|
||||||
|
NSUpload.uploadError(getIntent().getStringExtra("status"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -159,6 +159,7 @@ public class NewTreatmentDialog extends DialogFragment implements OnClickListene
|
||||||
detailedBolusInfo.carbs = finalCarbsAfterConstraints;
|
detailedBolusInfo.carbs = finalCarbsAfterConstraints;
|
||||||
detailedBolusInfo.context = context;
|
detailedBolusInfo.context = context;
|
||||||
detailedBolusInfo.source = Source.USER;
|
detailedBolusInfo.source = Source.USER;
|
||||||
|
if (detailedBolusInfo.insulin > 0 || ConfigBuilderPlugin.getActivePump().getPumpDescription().storesCarbInfo) {
|
||||||
ConfigBuilderPlugin.getCommandQueue().bolus(detailedBolusInfo, new Callback() {
|
ConfigBuilderPlugin.getCommandQueue().bolus(detailedBolusInfo, new Callback() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
@ -172,6 +173,9 @@ public class NewTreatmentDialog extends DialogFragment implements OnClickListene
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
MainApp.getConfigBuilder().addToHistoryTreatment(detailedBolusInfo);
|
||||||
|
}
|
||||||
Answers.getInstance().logCustom(new CustomEvent("Bolus"));
|
Answers.getInstance().logCustom(new CustomEvent("Bolus"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -365,6 +365,7 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com
|
||||||
detailedBolusInfo.carbTime = carbTime;
|
detailedBolusInfo.carbTime = carbTime;
|
||||||
detailedBolusInfo.boluscalc = boluscalcJSON;
|
detailedBolusInfo.boluscalc = boluscalcJSON;
|
||||||
detailedBolusInfo.source = Source.USER;
|
detailedBolusInfo.source = Source.USER;
|
||||||
|
if (detailedBolusInfo.insulin > 0 || ConfigBuilderPlugin.getActivePump().getPumpDescription().storesCarbInfo) {
|
||||||
ConfigBuilderPlugin.getCommandQueue().bolus(detailedBolusInfo, new Callback() {
|
ConfigBuilderPlugin.getCommandQueue().bolus(detailedBolusInfo, new Callback() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
@ -378,6 +379,9 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
MainApp.getConfigBuilder().addToHistoryTreatment(detailedBolusInfo);
|
||||||
|
}
|
||||||
Answers.getInstance().logCustom(new CustomEvent("Wizard"));
|
Answers.getInstance().logCustom(new CustomEvent("Wizard"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -472,7 +476,7 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com
|
||||||
// COB
|
// COB
|
||||||
Double c_cob = 0d;
|
Double c_cob = 0d;
|
||||||
if (cobCheckbox.isChecked()) {
|
if (cobCheckbox.isChecked()) {
|
||||||
AutosensData autosensData = IobCobCalculatorPlugin.getLastAutosensData("Wizard COB");
|
AutosensData autosensData = IobCobCalculatorPlugin.getPlugin().getLastAutosensData("Wizard COB");
|
||||||
|
|
||||||
if(autosensData != null) {
|
if(autosensData != null) {
|
||||||
c_cob = autosensData.cob;
|
c_cob = autosensData.cob;
|
||||||
|
@ -528,12 +532,12 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com
|
||||||
if (calculatedTotalInsulin > 0d || calculatedCarbs > 0d) {
|
if (calculatedTotalInsulin > 0d || calculatedCarbs > 0d) {
|
||||||
String insulinText = calculatedTotalInsulin > 0d ? (DecimalFormatter.to2Decimal(calculatedTotalInsulin) + "U") : "";
|
String insulinText = calculatedTotalInsulin > 0d ? (DecimalFormatter.to2Decimal(calculatedTotalInsulin) + "U") : "";
|
||||||
String carbsText = calculatedCarbs > 0d ? (DecimalFormatter.to0Decimal(calculatedCarbs) + "g") : "";
|
String carbsText = calculatedCarbs > 0d ? (DecimalFormatter.to0Decimal(calculatedCarbs) + "g") : "";
|
||||||
total.setText(getString(R.string.result) + ": " + insulinText + " " + carbsText);
|
total.setText(MainApp.gs(R.string.result) + ": " + insulinText + " " + carbsText);
|
||||||
okButton.setVisibility(View.VISIBLE);
|
okButton.setVisibility(View.VISIBLE);
|
||||||
} else {
|
} else {
|
||||||
// TODO this should also be run when loading the dialog as the OK button is initially visible
|
// TODO this should also be run when loading the dialog as the OK button is initially visible
|
||||||
// but does nothing if neither carbs nor insulin is > 0
|
// but does nothing if neither carbs nor insulin is > 0
|
||||||
total.setText(getString(R.string.missing) + " " + DecimalFormatter.to0Decimal(wizard.carbsEquivalent) + "g");
|
total.setText(MainApp.gs(R.string.missing) + " " + DecimalFormatter.to0Decimal(wizard.carbsEquivalent) + "g");
|
||||||
okButton.setVisibility(View.INVISIBLE);
|
okButton.setVisibility(View.INVISIBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -93,8 +93,6 @@ import info.nightscout.androidaps.plugins.Loop.LoopPlugin;
|
||||||
import info.nightscout.androidaps.plugins.Loop.events.EventNewOpenLoopNotification;
|
import info.nightscout.androidaps.plugins.Loop.events.EventNewOpenLoopNotification;
|
||||||
import info.nightscout.androidaps.plugins.NSClientInternal.broadcasts.BroadcastAckAlarm;
|
import info.nightscout.androidaps.plugins.NSClientInternal.broadcasts.BroadcastAckAlarm;
|
||||||
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSDeviceStatus;
|
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSDeviceStatus;
|
||||||
import info.nightscout.androidaps.plugins.OpenAPSAMA.DetermineBasalResultAMA;
|
|
||||||
import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin;
|
|
||||||
import info.nightscout.androidaps.plugins.Overview.Dialogs.CalibrationDialog;
|
import info.nightscout.androidaps.plugins.Overview.Dialogs.CalibrationDialog;
|
||||||
import info.nightscout.androidaps.plugins.Overview.Dialogs.ErrorHelperActivity;
|
import info.nightscout.androidaps.plugins.Overview.Dialogs.ErrorHelperActivity;
|
||||||
import info.nightscout.androidaps.plugins.Overview.Dialogs.NewTreatmentDialog;
|
import info.nightscout.androidaps.plugins.Overview.Dialogs.NewTreatmentDialog;
|
||||||
|
@ -148,12 +146,18 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
|
||||||
TextView sage;
|
TextView sage;
|
||||||
TextView pbage;
|
TextView pbage;
|
||||||
|
|
||||||
CheckBox showPredictionView;
|
TextView showPredictionLabel;
|
||||||
CheckBox showBasalsView;
|
CheckBox showPredictionCheckbox;
|
||||||
CheckBox showIobView;
|
TextView showBasalsLabel;
|
||||||
CheckBox showCobView;
|
CheckBox showBasalsCheckbox;
|
||||||
CheckBox showDeviationsView;
|
TextView showIobLabel;
|
||||||
CheckBox showRatiosView;
|
CheckBox showIobCheckbox;
|
||||||
|
TextView showCobLabel;
|
||||||
|
CheckBox showCobCheckbox;
|
||||||
|
TextView showDeviationsLabel;
|
||||||
|
CheckBox showDeviationsCheckbox;
|
||||||
|
TextView showRatiosLabel;
|
||||||
|
CheckBox showRatiosCheckbox;
|
||||||
|
|
||||||
RecyclerView notificationsView;
|
RecyclerView notificationsView;
|
||||||
LinearLayoutManager llm;
|
LinearLayoutManager llm;
|
||||||
|
@ -265,24 +269,37 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
|
||||||
|
|
||||||
acceptTempLayout = (LinearLayout) view.findViewById(R.id.overview_accepttemplayout);
|
acceptTempLayout = (LinearLayout) view.findViewById(R.id.overview_accepttemplayout);
|
||||||
|
|
||||||
showPredictionView = (CheckBox) view.findViewById(R.id.overview_showprediction);
|
showPredictionCheckbox = (CheckBox) view.findViewById(R.id.overview_showprediction);
|
||||||
showBasalsView = (CheckBox) view.findViewById(R.id.overview_showbasals);
|
showBasalsCheckbox = (CheckBox) view.findViewById(R.id.overview_showbasals);
|
||||||
showIobView = (CheckBox) view.findViewById(R.id.overview_showiob);
|
showIobCheckbox = (CheckBox) view.findViewById(R.id.overview_showiob);
|
||||||
showCobView = (CheckBox) view.findViewById(R.id.overview_showcob);
|
showCobCheckbox = (CheckBox) view.findViewById(R.id.overview_showcob);
|
||||||
showDeviationsView = (CheckBox) view.findViewById(R.id.overview_showdeviations);
|
showDeviationsCheckbox = (CheckBox) view.findViewById(R.id.overview_showdeviations);
|
||||||
showRatiosView = (CheckBox) view.findViewById(R.id.overview_showratios);
|
showRatiosCheckbox = (CheckBox) view.findViewById(R.id.overview_showratios);
|
||||||
showPredictionView.setChecked(SP.getBoolean("showprediction", false));
|
showPredictionCheckbox.setChecked(SP.getBoolean("showprediction", false));
|
||||||
showBasalsView.setChecked(SP.getBoolean("showbasals", true));
|
showBasalsCheckbox.setChecked(SP.getBoolean("showbasals", true));
|
||||||
showIobView.setChecked(SP.getBoolean("showiob", false));
|
showIobCheckbox.setChecked(SP.getBoolean("showiob", false));
|
||||||
showCobView.setChecked(SP.getBoolean("showcob", false));
|
showCobCheckbox.setChecked(SP.getBoolean("showcob", false));
|
||||||
showDeviationsView.setChecked(SP.getBoolean("showdeviations", false));
|
showDeviationsCheckbox.setChecked(SP.getBoolean("showdeviations", false));
|
||||||
showRatiosView.setChecked(SP.getBoolean("showratios", false));
|
showRatiosCheckbox.setChecked(SP.getBoolean("showratios", false));
|
||||||
showPredictionView.setOnCheckedChangeListener(this);
|
showPredictionCheckbox.setOnCheckedChangeListener(this);
|
||||||
showBasalsView.setOnCheckedChangeListener(this);
|
showBasalsCheckbox.setOnCheckedChangeListener(this);
|
||||||
showIobView.setOnCheckedChangeListener(this);
|
showIobCheckbox.setOnCheckedChangeListener(this);
|
||||||
showCobView.setOnCheckedChangeListener(this);
|
showCobCheckbox.setOnCheckedChangeListener(this);
|
||||||
showDeviationsView.setOnCheckedChangeListener(this);
|
showDeviationsCheckbox.setOnCheckedChangeListener(this);
|
||||||
showRatiosView.setOnCheckedChangeListener(this);
|
showRatiosCheckbox.setOnCheckedChangeListener(this);
|
||||||
|
|
||||||
|
showPredictionLabel = (TextView) view.findViewById(R.id.overview_showprediction_label);
|
||||||
|
showPredictionLabel.setOnClickListener(this);
|
||||||
|
showBasalsLabel = (TextView) view.findViewById(R.id.overview_showbasals_label);
|
||||||
|
showBasalsLabel.setOnClickListener(this);
|
||||||
|
showIobLabel = (TextView) view.findViewById(R.id.overview_showiob_label);
|
||||||
|
showIobLabel.setOnClickListener(this);
|
||||||
|
showCobLabel = (TextView) view.findViewById(R.id.overview_showcob_label);
|
||||||
|
showCobLabel.setOnClickListener(this);
|
||||||
|
showDeviationsLabel = (TextView) view.findViewById(R.id.overview_showdeviations_label);
|
||||||
|
showDeviationsLabel.setOnClickListener(this);
|
||||||
|
showRatiosLabel = (TextView) view.findViewById(R.id.overview_showratios_label);
|
||||||
|
showRatiosLabel.setOnClickListener(this);
|
||||||
|
|
||||||
notificationsView = (RecyclerView) view.findViewById(R.id.overview_notifications);
|
notificationsView = (RecyclerView) view.findViewById(R.id.overview_notifications);
|
||||||
notificationsView.setHasFixedSize(true);
|
notificationsView.setHasFixedSize(true);
|
||||||
|
@ -375,24 +392,24 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
|
||||||
case R.id.overview_showiob:
|
case R.id.overview_showiob:
|
||||||
break;
|
break;
|
||||||
case R.id.overview_showcob:
|
case R.id.overview_showcob:
|
||||||
showDeviationsView.setOnCheckedChangeListener(null);
|
showDeviationsCheckbox.setOnCheckedChangeListener(null);
|
||||||
showDeviationsView.setChecked(false);
|
showDeviationsCheckbox.setChecked(false);
|
||||||
showDeviationsView.setOnCheckedChangeListener(this);
|
showDeviationsCheckbox.setOnCheckedChangeListener(this);
|
||||||
break;
|
break;
|
||||||
case R.id.overview_showdeviations:
|
case R.id.overview_showdeviations:
|
||||||
showCobView.setOnCheckedChangeListener(null);
|
showCobCheckbox.setOnCheckedChangeListener(null);
|
||||||
showCobView.setChecked(false);
|
showCobCheckbox.setChecked(false);
|
||||||
showCobView.setOnCheckedChangeListener(this);
|
showCobCheckbox.setOnCheckedChangeListener(this);
|
||||||
break;
|
break;
|
||||||
case R.id.overview_showratios:
|
case R.id.overview_showratios:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
SP.putBoolean("showiob", showIobView.isChecked());
|
SP.putBoolean("showiob", showIobCheckbox.isChecked());
|
||||||
SP.putBoolean("showprediction", showPredictionView.isChecked());
|
SP.putBoolean("showprediction", showPredictionCheckbox.isChecked());
|
||||||
SP.putBoolean("showbasals", showBasalsView.isChecked());
|
SP.putBoolean("showbasals", showBasalsCheckbox.isChecked());
|
||||||
SP.putBoolean("showcob", showCobView.isChecked());
|
SP.putBoolean("showcob", showCobCheckbox.isChecked());
|
||||||
SP.putBoolean("showdeviations", showDeviationsView.isChecked());
|
SP.putBoolean("showdeviations", showDeviationsCheckbox.isChecked());
|
||||||
SP.putBoolean("showratios", showRatiosView.isChecked());
|
SP.putBoolean("showratios", showRatiosCheckbox.isChecked());
|
||||||
scheduleUpdateGUI("onGraphCheckboxesCheckedChanged");
|
scheduleUpdateGUI("onGraphCheckboxesCheckedChanged");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -619,6 +636,24 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
|
||||||
if (ConfigBuilderPlugin.getActivePump().isSuspended() || !ConfigBuilderPlugin.getActivePump().isInitialized())
|
if (ConfigBuilderPlugin.getActivePump().isSuspended() || !ConfigBuilderPlugin.getActivePump().isInitialized())
|
||||||
ConfigBuilderPlugin.getCommandQueue().readStatus("RefreshClicked", null);
|
ConfigBuilderPlugin.getCommandQueue().readStatus("RefreshClicked", null);
|
||||||
break;
|
break;
|
||||||
|
case R.id.overview_showprediction_label:
|
||||||
|
showPredictionCheckbox.toggle();
|
||||||
|
break;
|
||||||
|
case R.id.overview_showbasals_label:
|
||||||
|
showBasalsCheckbox.toggle();
|
||||||
|
break;
|
||||||
|
case R.id.overview_showiob_label:
|
||||||
|
showIobCheckbox.toggle();
|
||||||
|
break;
|
||||||
|
case R.id.overview_showcob_label:
|
||||||
|
showCobCheckbox.toggle();
|
||||||
|
break;
|
||||||
|
case R.id.overview_showdeviations_label:
|
||||||
|
showDeviationsCheckbox.toggle();
|
||||||
|
break;
|
||||||
|
case R.id.overview_showratios_label:
|
||||||
|
showRatiosCheckbox.toggle();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -638,7 +673,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
|
||||||
if (ConfigBuilderPlugin.getActiveLoop() != null) {
|
if (ConfigBuilderPlugin.getActiveLoop() != null) {
|
||||||
ConfigBuilderPlugin.getActiveLoop().invoke("Accept temp button", false);
|
ConfigBuilderPlugin.getActiveLoop().invoke("Accept temp button", false);
|
||||||
final LoopPlugin.LastRun finalLastRun = LoopPlugin.lastRun;
|
final LoopPlugin.LastRun finalLastRun = LoopPlugin.lastRun;
|
||||||
if (finalLastRun != null && finalLastRun.lastAPSRun != null && finalLastRun.constraintsProcessed.changeRequested) {
|
if (finalLastRun != null && finalLastRun.lastAPSRun != null && finalLastRun.constraintsProcessed.isChangeRequested()) {
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
|
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
|
||||||
builder.setTitle(getContext().getString(R.string.confirmation));
|
builder.setTitle(getContext().getString(R.string.confirmation));
|
||||||
builder.setMessage(getContext().getString(R.string.setbasalquestion) + "\n" + finalLastRun.constraintsProcessed);
|
builder.setMessage(getContext().getString(R.string.setbasalquestion) + "\n" + finalLastRun.constraintsProcessed);
|
||||||
|
@ -1069,7 +1104,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
|
||||||
boolean showAcceptButton = !MainApp.getConfigBuilder().isClosedModeEnabled(); // Open mode needed
|
boolean showAcceptButton = !MainApp.getConfigBuilder().isClosedModeEnabled(); // Open mode needed
|
||||||
showAcceptButton = showAcceptButton && finalLastRun != null && finalLastRun.lastAPSRun != null; // aps result must exist
|
showAcceptButton = showAcceptButton && finalLastRun != null && finalLastRun.lastAPSRun != null; // aps result must exist
|
||||||
showAcceptButton = showAcceptButton && (finalLastRun.lastOpenModeAccept == null || finalLastRun.lastOpenModeAccept.getTime() < finalLastRun.lastAPSRun.getTime()); // never accepted or before last result
|
showAcceptButton = showAcceptButton && (finalLastRun.lastOpenModeAccept == null || finalLastRun.lastOpenModeAccept.getTime() < finalLastRun.lastAPSRun.getTime()); // never accepted or before last result
|
||||||
showAcceptButton = showAcceptButton && finalLastRun.constraintsProcessed.changeRequested; // change is requested
|
showAcceptButton = showAcceptButton && finalLastRun.constraintsProcessed.isChangeRequested(); // change is requested
|
||||||
|
|
||||||
if (showAcceptButton && pump.isInitialized() && !pump.isSuspended() && ConfigBuilderPlugin.getActiveLoop() != null) {
|
if (showAcceptButton && pump.isInitialized() && !pump.isSuspended() && ConfigBuilderPlugin.getActiveLoop() != null) {
|
||||||
acceptTempLayout.setVisibility(View.VISIBLE);
|
acceptTempLayout.setVisibility(View.VISIBLE);
|
||||||
|
@ -1241,19 +1276,19 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
|
||||||
// cob
|
// cob
|
||||||
if (cobView != null) { // view must not exists
|
if (cobView != null) { // view must not exists
|
||||||
String cobText = "";
|
String cobText = "";
|
||||||
AutosensData autosensData = IobCobCalculatorPlugin.getLastAutosensData("Overview COB");
|
AutosensData autosensData = IobCobCalculatorPlugin.getPlugin().getLastAutosensData("Overview COB");
|
||||||
if (autosensData != null)
|
if (autosensData != null)
|
||||||
cobText = (int) autosensData.cob + " g";
|
cobText = (int) autosensData.cob + " g";
|
||||||
cobView.setText(cobText);
|
cobView.setText(cobText);
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean showPrediction = showPredictionView.isChecked() && finalLastRun != null && finalLastRun.constraintsProcessed.getClass().equals(DetermineBasalResultAMA.class);
|
final boolean predictionsAvailable = finalLastRun != null && finalLastRun.request.hasPredictions;
|
||||||
if (MainApp.getSpecificPlugin(OpenAPSAMAPlugin.class) != null && MainApp.getSpecificPlugin(OpenAPSAMAPlugin.class).isEnabled(PluginBase.APS)) {
|
if (predictionsAvailable) {
|
||||||
showPredictionView.setVisibility(View.VISIBLE);
|
showPredictionCheckbox.setVisibility(View.VISIBLE);
|
||||||
getActivity().findViewById(R.id.overview_showprediction_label).setVisibility(View.VISIBLE);
|
showPredictionLabel.setVisibility(View.VISIBLE);
|
||||||
} else {
|
} else {
|
||||||
showPredictionView.setVisibility(View.GONE);
|
showPredictionCheckbox.setVisibility(View.GONE);
|
||||||
getActivity().findViewById(R.id.overview_showprediction_label).setVisibility(View.GONE);
|
showPredictionLabel.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// pump status from ns
|
// pump status from ns
|
||||||
|
@ -1306,8 +1341,8 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
|
||||||
final long toTime;
|
final long toTime;
|
||||||
final long fromTime;
|
final long fromTime;
|
||||||
final long endTime;
|
final long endTime;
|
||||||
if (showPrediction) {
|
if (predictionsAvailable && showPredictionCheckbox.isChecked()) {
|
||||||
int predHours = (int) (Math.ceil(((DetermineBasalResultAMA) finalLastRun.constraintsProcessed).getLatestPredictionsTime() - System.currentTimeMillis()) / (60 * 60 * 1000));
|
int predHours = (int) (Math.ceil(finalLastRun.constraintsProcessed.getLatestPredictionsTime() - System.currentTimeMillis()) / (60 * 60 * 1000));
|
||||||
predHours = Math.min(2, predHours);
|
predHours = Math.min(2, predHours);
|
||||||
predHours = Math.max(0, predHours);
|
predHours = Math.max(0, predHours);
|
||||||
hoursToFetch = rangeToDisplay - predHours;
|
hoursToFetch = rangeToDisplay - predHours;
|
||||||
|
@ -1327,14 +1362,14 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
|
||||||
// ------------------ 1st graph
|
// ------------------ 1st graph
|
||||||
Profiler.log(log, from + " - 1st graph - START", updateGUIStart);
|
Profiler.log(log, from + " - 1st graph - START", updateGUIStart);
|
||||||
|
|
||||||
final GraphData graphData = new GraphData(bgGraph);
|
final GraphData graphData = new GraphData(bgGraph, IobCobCalculatorPlugin.getPlugin());
|
||||||
|
|
||||||
// **** In range Area ****
|
// **** In range Area ****
|
||||||
graphData.addInRangeArea(fromTime, endTime, lowLine, highLine);
|
graphData.addInRangeArea(fromTime, endTime, lowLine, highLine);
|
||||||
|
|
||||||
// **** BG ****
|
// **** BG ****
|
||||||
if (showPrediction)
|
if (predictionsAvailable && showPredictionCheckbox.isChecked())
|
||||||
graphData.addBgReadings(fromTime, toTime, lowLine, highLine, (DetermineBasalResultAMA) finalLastRun.constraintsProcessed);
|
graphData.addBgReadings(fromTime, toTime, lowLine, highLine, finalLastRun.constraintsProcessed);
|
||||||
else
|
else
|
||||||
graphData.addBgReadings(fromTime, toTime, lowLine, highLine, null);
|
graphData.addBgReadings(fromTime, toTime, lowLine, highLine, null);
|
||||||
|
|
||||||
|
@ -1345,41 +1380,49 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
|
||||||
graphData.addTreatments(fromTime, endTime);
|
graphData.addTreatments(fromTime, endTime);
|
||||||
|
|
||||||
// add basal data
|
// add basal data
|
||||||
if (pump.getPumpDescription().isTempBasalCapable && showBasalsView.isChecked()) {
|
if (pump.getPumpDescription().isTempBasalCapable && showBasalsCheckbox.isChecked()) {
|
||||||
graphData.addBasals(fromTime, now, lowLine / graphData.maxY / 1.2d);
|
graphData.addBasals(fromTime, now, lowLine / graphData.maxY / 1.2d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add target line
|
||||||
|
graphData.addTargetLine(fromTime, toTime);
|
||||||
|
|
||||||
// **** NOW line ****
|
// **** NOW line ****
|
||||||
graphData.addNowLine(now);
|
graphData.addNowLine(now);
|
||||||
|
|
||||||
// ------------------ 2nd graph
|
// ------------------ 2nd graph
|
||||||
Profiler.log(log, from + " - 2nd graph - START", updateGUIStart);
|
Profiler.log(log, from + " - 2nd graph - START", updateGUIStart);
|
||||||
|
|
||||||
final GraphData secondGraphData = new GraphData(iobGraph);
|
final GraphData secondGraphData = new GraphData(iobGraph, IobCobCalculatorPlugin.getPlugin());
|
||||||
|
|
||||||
boolean useIobForScale = false;
|
boolean useIobForScale = false;
|
||||||
boolean useCobForScale = false;
|
boolean useCobForScale = false;
|
||||||
boolean useDevForScale = false;
|
boolean useDevForScale = false;
|
||||||
boolean useRatioForScale = false;
|
boolean useRatioForScale = false;
|
||||||
|
boolean useDSForScale = false;
|
||||||
|
|
||||||
if (showIobView.isChecked()) {
|
if (showIobCheckbox.isChecked()) {
|
||||||
useIobForScale = true;
|
useIobForScale = true;
|
||||||
} else if (showCobView.isChecked()) {
|
} else if (showCobCheckbox.isChecked()) {
|
||||||
useCobForScale = true;
|
useCobForScale = true;
|
||||||
} else if (showDeviationsView.isChecked()) {
|
} else if (showDeviationsCheckbox.isChecked()) {
|
||||||
useDevForScale = true;
|
useDevForScale = true;
|
||||||
} else if (showRatiosView.isChecked()) {
|
} else if (showRatiosCheckbox.isChecked()) {
|
||||||
useRatioForScale = true;
|
useRatioForScale = true;
|
||||||
|
} else if (Config.displayDeviationSlope) {
|
||||||
|
useDSForScale = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (showIobView.isChecked())
|
if (showIobCheckbox.isChecked())
|
||||||
secondGraphData.addIob(fromTime, now, useIobForScale, 1d);
|
secondGraphData.addIob(fromTime, now, useIobForScale, 1d);
|
||||||
if (showCobView.isChecked())
|
if (showCobCheckbox.isChecked())
|
||||||
secondGraphData.addCob(fromTime, now, useCobForScale, useCobForScale ? 1d : 0.5d);
|
secondGraphData.addCob(fromTime, now, useCobForScale, useCobForScale ? 1d : 0.5d);
|
||||||
if (showDeviationsView.isChecked())
|
if (showDeviationsCheckbox.isChecked())
|
||||||
secondGraphData.addDeviations(fromTime, now, useDevForScale, 1d);
|
secondGraphData.addDeviations(fromTime, now, useDevForScale, 1d);
|
||||||
if (showRatiosView.isChecked())
|
if (showRatiosCheckbox.isChecked())
|
||||||
secondGraphData.addRatio(fromTime, now, useRatioForScale, 1d);
|
secondGraphData.addRatio(fromTime, now, useRatioForScale, 1d);
|
||||||
|
if (Config.displayDeviationSlope)
|
||||||
|
secondGraphData.addDeviationSlope(fromTime, now, useDSForScale, 1d);
|
||||||
|
|
||||||
// **** NOW line ****
|
// **** NOW line ****
|
||||||
// set manual x bounds to have nice steps
|
// set manual x bounds to have nice steps
|
||||||
|
@ -1392,7 +1435,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
|
||||||
activity.runOnUiThread(new Runnable() {
|
activity.runOnUiThread(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (showIobView.isChecked() || showCobView.isChecked() || showDeviationsView.isChecked() || showRatiosView.isChecked()) {
|
if (showIobCheckbox.isChecked() || showCobCheckbox.isChecked() || showDeviationsCheckbox.isChecked() || showRatiosCheckbox.isChecked() || Config.displayDeviationSlope) {
|
||||||
iobGraph.setVisibility(View.VISIBLE);
|
iobGraph.setVisibility(View.VISIBLE);
|
||||||
} else {
|
} else {
|
||||||
iobGraph.setVisibility(View.GONE);
|
iobGraph.setVisibility(View.GONE);
|
||||||
|
|
|
@ -16,6 +16,10 @@ public class EventOverviewBolusProgress extends Event {
|
||||||
public EventOverviewBolusProgress() {
|
public EventOverviewBolusProgress() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isSMB(){
|
||||||
|
return (t != null) && t.isSMB;
|
||||||
|
}
|
||||||
|
|
||||||
public static EventOverviewBolusProgress getInstance() {
|
public static EventOverviewBolusProgress getInstance() {
|
||||||
if(eventOverviewBolusProgress == null) {
|
if(eventOverviewBolusProgress == null) {
|
||||||
eventOverviewBolusProgress = new EventOverviewBolusProgress();
|
eventOverviewBolusProgress = new EventOverviewBolusProgress();
|
||||||
|
|
|
@ -12,7 +12,6 @@ import com.jjoe64.graphview.series.LineGraphSeries;
|
||||||
import com.jjoe64.graphview.series.Series;
|
import com.jjoe64.graphview.series.Series;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import info.nightscout.androidaps.Constants;
|
import info.nightscout.androidaps.Constants;
|
||||||
|
@ -23,12 +22,14 @@ import info.nightscout.androidaps.db.BgReading;
|
||||||
import info.nightscout.androidaps.db.CareportalEvent;
|
import info.nightscout.androidaps.db.CareportalEvent;
|
||||||
import info.nightscout.androidaps.db.ExtendedBolus;
|
import info.nightscout.androidaps.db.ExtendedBolus;
|
||||||
import info.nightscout.androidaps.db.ProfileSwitch;
|
import info.nightscout.androidaps.db.ProfileSwitch;
|
||||||
|
import info.nightscout.androidaps.db.TempTarget;
|
||||||
import info.nightscout.androidaps.db.Treatment;
|
import info.nightscout.androidaps.db.Treatment;
|
||||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||||
import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData;
|
import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData;
|
||||||
import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin;
|
import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin;
|
||||||
import info.nightscout.androidaps.plugins.IobCobCalculator.BasalData;
|
import info.nightscout.androidaps.plugins.IobCobCalculator.BasalData;
|
||||||
import info.nightscout.androidaps.plugins.OpenAPSAMA.DetermineBasalResultAMA;
|
import info.nightscout.androidaps.plugins.Loop.APSResult;
|
||||||
|
import info.nightscout.androidaps.plugins.Loop.LoopPlugin;
|
||||||
import info.nightscout.androidaps.plugins.Overview.graphExtensions.AreaGraphSeries;
|
import info.nightscout.androidaps.plugins.Overview.graphExtensions.AreaGraphSeries;
|
||||||
import info.nightscout.androidaps.plugins.Overview.graphExtensions.DataPointWithLabelInterface;
|
import info.nightscout.androidaps.plugins.Overview.graphExtensions.DataPointWithLabelInterface;
|
||||||
import info.nightscout.androidaps.plugins.Overview.graphExtensions.DoubleDataPoint;
|
import info.nightscout.androidaps.plugins.Overview.graphExtensions.DoubleDataPoint;
|
||||||
|
@ -37,6 +38,7 @@ import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLab
|
||||||
import info.nightscout.androidaps.plugins.Overview.graphExtensions.Scale;
|
import info.nightscout.androidaps.plugins.Overview.graphExtensions.Scale;
|
||||||
import info.nightscout.androidaps.plugins.Overview.graphExtensions.ScaledDataPoint;
|
import info.nightscout.androidaps.plugins.Overview.graphExtensions.ScaledDataPoint;
|
||||||
import info.nightscout.androidaps.plugins.Overview.graphExtensions.TimeAsXAxisLabelFormatter;
|
import info.nightscout.androidaps.plugins.Overview.graphExtensions.TimeAsXAxisLabelFormatter;
|
||||||
|
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
|
||||||
import info.nightscout.utils.Round;
|
import info.nightscout.utils.Round;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -51,12 +53,15 @@ public class GraphData {
|
||||||
private String units;
|
private String units;
|
||||||
private List<Series> series = new ArrayList<>();
|
private List<Series> series = new ArrayList<>();
|
||||||
|
|
||||||
public GraphData(GraphView graph) {
|
private IobCobCalculatorPlugin iobCobCalculatorPlugin;
|
||||||
|
|
||||||
|
public GraphData(GraphView graph, IobCobCalculatorPlugin iobCobCalculatorPlugin) {
|
||||||
units = MainApp.getConfigBuilder().getProfileUnits();
|
units = MainApp.getConfigBuilder().getProfileUnits();
|
||||||
this.graph = graph;
|
this.graph = graph;
|
||||||
|
this.iobCobCalculatorPlugin = iobCobCalculatorPlugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addBgReadings(long fromTime, long toTime, double lowLine, double highLine, DetermineBasalResultAMA amaResult) {
|
public void addBgReadings(long fromTime, long toTime, double lowLine, double highLine, APSResult apsResult) {
|
||||||
double maxBgValue = 0d;
|
double maxBgValue = 0d;
|
||||||
bgReadingsArray = MainApp.getDbHelper().getBgreadingsDataFromTime(fromTime, true);
|
bgReadingsArray = MainApp.getDbHelper().getBgreadingsDataFromTime(fromTime, true);
|
||||||
List<DataPointWithLabelInterface> bgListArray = new ArrayList<>();
|
List<DataPointWithLabelInterface> bgListArray = new ArrayList<>();
|
||||||
|
@ -65,14 +70,12 @@ public class GraphData {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator<BgReading> it = bgReadingsArray.iterator();
|
for (BgReading bg : bgReadingsArray) {
|
||||||
while (it.hasNext()) {
|
|
||||||
BgReading bg = it.next();
|
|
||||||
if (bg.value > maxBgValue) maxBgValue = bg.value;
|
if (bg.value > maxBgValue) maxBgValue = bg.value;
|
||||||
bgListArray.add(bg);
|
bgListArray.add(bg);
|
||||||
}
|
}
|
||||||
if (amaResult != null) {
|
if (apsResult != null) {
|
||||||
List<BgReading> predArray = amaResult.getPredictions();
|
List<BgReading> predArray = apsResult.getPredictions();
|
||||||
bgListArray.addAll(predArray);
|
bgListArray.addAll(predArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,11 +128,11 @@ public class GraphData {
|
||||||
List<ScaledDataPoint> basalLineArray = new ArrayList<>();
|
List<ScaledDataPoint> basalLineArray = new ArrayList<>();
|
||||||
List<ScaledDataPoint> absoluteBasalLineArray = new ArrayList<>();
|
List<ScaledDataPoint> absoluteBasalLineArray = new ArrayList<>();
|
||||||
double lastLineBasal = 0;
|
double lastLineBasal = 0;
|
||||||
double lastAbsoluteLineBasal = 0;
|
double lastAbsoluteLineBasal = -1;
|
||||||
double lastBaseBasal = 0;
|
double lastBaseBasal = 0;
|
||||||
double lastTempBasal = 0;
|
double lastTempBasal = 0;
|
||||||
for (long time = fromTime; time < toTime; time += 60 * 1000L) {
|
for (long time = fromTime; time < toTime; time += 60 * 1000L) {
|
||||||
BasalData basalData = IobCobCalculatorPlugin.getBasalData(time);
|
BasalData basalData = IobCobCalculatorPlugin.getPlugin().getBasalData(time);
|
||||||
double baseBasalValue = basalData.basal;
|
double baseBasalValue = basalData.basal;
|
||||||
double absoluteLineValue = baseBasalValue;
|
double absoluteLineValue = baseBasalValue;
|
||||||
double tempBasalValue = 0;
|
double tempBasalValue = 0;
|
||||||
|
@ -218,6 +221,54 @@ public class GraphData {
|
||||||
addSeries(absoluteBasalsLineSeries);
|
addSeries(absoluteBasalsLineSeries);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addTargetLine(long fromTime, long toTime) {
|
||||||
|
Profile profile = MainApp.getConfigBuilder().getProfile();
|
||||||
|
if (profile == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LineGraphSeries<DataPoint> targetsSeries;
|
||||||
|
|
||||||
|
Scale targetsScale = new Scale();
|
||||||
|
targetsScale.setMultiplier(1);
|
||||||
|
|
||||||
|
List<DataPoint> targetsSeriesArray = new ArrayList<>();
|
||||||
|
double lastTarget = 0;
|
||||||
|
|
||||||
|
if (LoopPlugin.lastRun != null && LoopPlugin.lastRun.constraintsProcessed != null) {
|
||||||
|
APSResult apsResult = LoopPlugin.lastRun.constraintsProcessed;
|
||||||
|
long latestPredictionsTime = apsResult.getLatestPredictionsTime();
|
||||||
|
if (latestPredictionsTime > toTime) {
|
||||||
|
toTime = latestPredictionsTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (long time = fromTime; time < toTime; time += 60 * 1000L) {
|
||||||
|
TempTarget tt = TreatmentsPlugin.getPlugin().getTempTargetFromHistory(time);
|
||||||
|
double value;
|
||||||
|
if (tt == null) {
|
||||||
|
value = (profile.getTargetLow(time) + profile.getTargetHigh(time)) / 2;
|
||||||
|
} else {
|
||||||
|
value = (tt.low + tt.high) / 2;
|
||||||
|
}
|
||||||
|
if (lastTarget > 0 && lastTarget != value) {
|
||||||
|
targetsSeriesArray.add(new DataPoint(time, lastTarget));
|
||||||
|
}
|
||||||
|
lastTarget = value;
|
||||||
|
|
||||||
|
targetsSeriesArray.add(new DataPoint(time, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
DataPoint[] targets = new DataPoint[targetsSeriesArray.size()];
|
||||||
|
targets = targetsSeriesArray.toArray(targets);
|
||||||
|
targetsSeries = new LineGraphSeries<>(targets);
|
||||||
|
targetsSeries.setDrawBackground(false);
|
||||||
|
targetsSeries.setColor(MainApp.sResources.getColor(R.color.tempTargetBackground));
|
||||||
|
targetsSeries.setThickness(2);
|
||||||
|
|
||||||
|
addSeries(targetsSeries);
|
||||||
|
}
|
||||||
|
|
||||||
public void addTreatments(long fromTime, long endTime) {
|
public void addTreatments(long fromTime, long endTime) {
|
||||||
List<DataPointWithLabelInterface> filteredTreatments = new ArrayList<>();
|
List<DataPointWithLabelInterface> filteredTreatments = new ArrayList<>();
|
||||||
|
|
||||||
|
@ -253,7 +304,7 @@ public class GraphData {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Careportal
|
// Careportal
|
||||||
List<CareportalEvent> careportalEvents = MainApp.getDbHelper().getCareportalEventsFromTime(fromTime, true);
|
List<CareportalEvent> careportalEvents = MainApp.getDbHelper().getCareportalEventsFromTime(fromTime - 6 * 60 * 60 * 1000, true);
|
||||||
|
|
||||||
for (int tx = 0; tx < careportalEvents.size(); tx++) {
|
for (int tx = 0; tx < careportalEvents.size(); tx++) {
|
||||||
DataPointWithLabelInterface t = careportalEvents.get(tx);
|
DataPointWithLabelInterface t = careportalEvents.get(tx);
|
||||||
|
@ -267,7 +318,7 @@ public class GraphData {
|
||||||
addSeries(new PointsWithLabelGraphSeries<>(treatmentsArray));
|
addSeries(new PointsWithLabelGraphSeries<>(treatmentsArray));
|
||||||
}
|
}
|
||||||
|
|
||||||
double getNearestBg(long date) {
|
private double getNearestBg(long date) {
|
||||||
double bg = 0;
|
double bg = 0;
|
||||||
for (int r = bgReadingsArray.size() - 1; r >= 0; r--) {
|
for (int r = bgReadingsArray.size() - 1; r >= 0; r--) {
|
||||||
BgReading reading = bgReadingsArray.get(r);
|
BgReading reading = bgReadingsArray.get(r);
|
||||||
|
@ -287,7 +338,7 @@ public class GraphData {
|
||||||
Scale iobScale = new Scale();
|
Scale iobScale = new Scale();
|
||||||
|
|
||||||
for (long time = fromTime; time <= toTime; time += 5 * 60 * 1000L) {
|
for (long time = fromTime; time <= toTime; time += 5 * 60 * 1000L) {
|
||||||
double iob = IobCobCalculatorPlugin.calculateFromTreatmentsAndTempsSynchronized(time).iob;
|
double iob = IobCobCalculatorPlugin.getPlugin().calculateFromTreatmentsAndTempsSynchronized(time).iob;
|
||||||
if (Math.abs(lastIob - iob) > 0.02) {
|
if (Math.abs(lastIob - iob) > 0.02) {
|
||||||
if (Math.abs(lastIob - iob) > 0.2)
|
if (Math.abs(lastIob - iob) > 0.2)
|
||||||
iobArray.add(new ScaledDataPoint(time, lastIob, iobScale));
|
iobArray.add(new ScaledDataPoint(time, lastIob, iobScale));
|
||||||
|
@ -322,7 +373,7 @@ public class GraphData {
|
||||||
Scale cobScale = new Scale();
|
Scale cobScale = new Scale();
|
||||||
|
|
||||||
for (long time = fromTime; time <= toTime; time += 5 * 60 * 1000L) {
|
for (long time = fromTime; time <= toTime; time += 5 * 60 * 1000L) {
|
||||||
AutosensData autosensData = IobCobCalculatorPlugin.getAutosensData(time);
|
AutosensData autosensData = IobCobCalculatorPlugin.getPlugin().getAutosensData(time);
|
||||||
if (autosensData != null) {
|
if (autosensData != null) {
|
||||||
int cob = (int) autosensData.cob;
|
int cob = (int) autosensData.cob;
|
||||||
if (cob != lastCob) {
|
if (cob != lastCob) {
|
||||||
|
@ -369,7 +420,7 @@ public class GraphData {
|
||||||
Scale devScale = new Scale();
|
Scale devScale = new Scale();
|
||||||
|
|
||||||
for (long time = fromTime; time <= toTime; time += 5 * 60 * 1000L) {
|
for (long time = fromTime; time <= toTime; time += 5 * 60 * 1000L) {
|
||||||
AutosensData autosensData = IobCobCalculatorPlugin.getAutosensData(time);
|
AutosensData autosensData = IobCobCalculatorPlugin.getPlugin().getAutosensData(time);
|
||||||
if (autosensData != null) {
|
if (autosensData != null) {
|
||||||
int color = Color.BLACK; // "="
|
int color = Color.BLACK; // "="
|
||||||
if (autosensData.pastSensitivity.equals("C")) color = Color.GRAY;
|
if (autosensData.pastSensitivity.equals("C")) color = Color.GRAY;
|
||||||
|
@ -401,21 +452,21 @@ public class GraphData {
|
||||||
|
|
||||||
// scale in % of vertical size (like 0.3)
|
// scale in % of vertical size (like 0.3)
|
||||||
public void addRatio(long fromTime, long toTime, boolean useForScale, double scale) {
|
public void addRatio(long fromTime, long toTime, boolean useForScale, double scale) {
|
||||||
LineGraphSeries<DataPoint> ratioSeries;
|
LineGraphSeries<ScaledDataPoint> ratioSeries;
|
||||||
List<DataPoint> ratioArray = new ArrayList<>();
|
List<ScaledDataPoint> ratioArray = new ArrayList<>();
|
||||||
Double maxRatioValueFound = 0d;
|
Double maxRatioValueFound = 0d;
|
||||||
Scale ratioScale = new Scale(-1d);
|
Scale ratioScale = new Scale(-1d);
|
||||||
|
|
||||||
for (long time = fromTime; time <= toTime; time += 5 * 60 * 1000L) {
|
for (long time = fromTime; time <= toTime; time += 5 * 60 * 1000L) {
|
||||||
AutosensData autosensData = IobCobCalculatorPlugin.getAutosensData(time);
|
AutosensData autosensData = IobCobCalculatorPlugin.getPlugin().getAutosensData(time);
|
||||||
if (autosensData != null) {
|
if (autosensData != null) {
|
||||||
ratioArray.add(new DataPoint(time, autosensData.autosensRatio));
|
ratioArray.add(new ScaledDataPoint(time, autosensData.autosensRatio, ratioScale));
|
||||||
maxRatioValueFound = Math.max(maxRatioValueFound, Math.abs(autosensData.autosensRatio));
|
maxRatioValueFound = Math.max(maxRatioValueFound, Math.abs(autosensData.autosensRatio));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// RATIOS
|
// RATIOS
|
||||||
DataPoint[] ratioData = new DataPoint[ratioArray.size()];
|
ScaledDataPoint[] ratioData = new ScaledDataPoint[ratioArray.size()];
|
||||||
ratioData = ratioArray.toArray(ratioData);
|
ratioData = ratioArray.toArray(ratioData);
|
||||||
ratioSeries = new LineGraphSeries<>(ratioData);
|
ratioSeries = new LineGraphSeries<>(ratioData);
|
||||||
ratioSeries.setColor(MainApp.sResources.getColor(R.color.ratio));
|
ratioSeries.setColor(MainApp.sResources.getColor(R.color.ratio));
|
||||||
|
@ -429,6 +480,50 @@ public class GraphData {
|
||||||
addSeries(ratioSeries);
|
addSeries(ratioSeries);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// scale in % of vertical size (like 0.3)
|
||||||
|
public void addDeviationSlope(long fromTime, long toTime, boolean useForScale, double scale) {
|
||||||
|
LineGraphSeries<ScaledDataPoint> dsMaxSeries;
|
||||||
|
LineGraphSeries<ScaledDataPoint> dsMinSeries;
|
||||||
|
List<ScaledDataPoint> dsMaxArray = new ArrayList<>();
|
||||||
|
List<ScaledDataPoint> dsMinArray = new ArrayList<>();
|
||||||
|
Double maxFromMaxValueFound = 0d;
|
||||||
|
Double maxFromMinValueFound = 0d;
|
||||||
|
Scale dsMaxScale = new Scale();
|
||||||
|
Scale dsMinScale = new Scale();
|
||||||
|
|
||||||
|
for (long time = fromTime; time <= toTime; time += 5 * 60 * 1000L) {
|
||||||
|
AutosensData autosensData = IobCobCalculatorPlugin.getPlugin().getAutosensData(time);
|
||||||
|
if (autosensData != null) {
|
||||||
|
dsMaxArray.add(new ScaledDataPoint(time, autosensData.slopeFromMaxDeviation, dsMaxScale));
|
||||||
|
dsMinArray.add(new ScaledDataPoint(time, autosensData.slopeFromMinDeviation, dsMinScale));
|
||||||
|
maxFromMaxValueFound = Math.max(maxFromMaxValueFound, Math.abs(autosensData.slopeFromMaxDeviation));
|
||||||
|
maxFromMinValueFound = Math.max(maxFromMinValueFound, Math.abs(autosensData.slopeFromMinDeviation));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Slopes
|
||||||
|
ScaledDataPoint[] ratioMaxData = new ScaledDataPoint[dsMaxArray.size()];
|
||||||
|
ratioMaxData = dsMaxArray.toArray(ratioMaxData);
|
||||||
|
dsMaxSeries = new LineGraphSeries<>(ratioMaxData);
|
||||||
|
dsMaxSeries.setColor(Color.MAGENTA);
|
||||||
|
dsMaxSeries.setThickness(3);
|
||||||
|
|
||||||
|
ScaledDataPoint[] ratioMinData = new ScaledDataPoint[dsMinArray.size()];
|
||||||
|
ratioMinData = dsMinArray.toArray(ratioMinData);
|
||||||
|
dsMinSeries = new LineGraphSeries<>(ratioMinData);
|
||||||
|
dsMinSeries.setColor(Color.YELLOW);
|
||||||
|
dsMinSeries.setThickness(3);
|
||||||
|
|
||||||
|
if (useForScale)
|
||||||
|
maxY = Math.max(maxFromMaxValueFound, maxFromMinValueFound);
|
||||||
|
|
||||||
|
dsMaxScale.setMultiplier(maxY * scale / maxFromMaxValueFound);
|
||||||
|
dsMinScale.setMultiplier(maxY * scale / maxFromMinValueFound);
|
||||||
|
|
||||||
|
addSeries(dsMaxSeries);
|
||||||
|
addSeries(dsMinSeries);
|
||||||
|
}
|
||||||
|
|
||||||
// scale in % of vertical size (like 0.3)
|
// scale in % of vertical size (like 0.3)
|
||||||
public void addNowLine(long now) {
|
public void addNowLine(long now) {
|
||||||
LineGraphSeries<DataPoint> seriesNow;
|
LineGraphSeries<DataPoint> seriesNow;
|
||||||
|
|
|
@ -55,4 +55,5 @@ public interface DataPointWithLabelInterface extends DataPointInterface{
|
||||||
PointsWithLabelGraphSeries.Shape getShape();
|
PointsWithLabelGraphSeries.Shape getShape();
|
||||||
float getSize();
|
float getSize();
|
||||||
int getColor();
|
int getColor();
|
||||||
|
int getSecondColor();
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,17 +60,12 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
|
||||||
* You can also render a custom drawing via {@link com.jjoe64.graphview.series.PointsGraphSeries.CustomShape}
|
* You can also render a custom drawing via {@link com.jjoe64.graphview.series.PointsGraphSeries.CustomShape}
|
||||||
*/
|
*/
|
||||||
public enum Shape {
|
public enum Shape {
|
||||||
/**
|
BG,
|
||||||
* draws a point / circle
|
PREDICTION,
|
||||||
*/
|
|
||||||
POINT,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* draws a triangle
|
|
||||||
*/
|
|
||||||
TRIANGLE,
|
TRIANGLE,
|
||||||
RECTANGLE,
|
RECTANGLE,
|
||||||
BOLUS,
|
BOLUS,
|
||||||
|
SMB,
|
||||||
EXTENDEDBOLUS,
|
EXTENDEDBOLUS,
|
||||||
PROFILE,
|
PROFILE,
|
||||||
MBG,
|
MBG,
|
||||||
|
@ -141,9 +136,6 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
|
||||||
Iterator<E> values = getValues(minX, maxX);
|
Iterator<E> values = getValues(minX, maxX);
|
||||||
|
|
||||||
// draw background
|
// draw background
|
||||||
double lastEndY = 0;
|
|
||||||
double lastEndX = 0;
|
|
||||||
|
|
||||||
// draw data
|
// draw data
|
||||||
|
|
||||||
double diffY = maxY - minY;
|
double diffY = maxY - minY;
|
||||||
|
@ -154,9 +146,8 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
|
||||||
float graphLeft = graphView.getGraphContentLeft();
|
float graphLeft = graphView.getGraphContentLeft();
|
||||||
float graphTop = graphView.getGraphContentTop();
|
float graphTop = graphView.getGraphContentTop();
|
||||||
|
|
||||||
lastEndY = 0;
|
float scaleX = (float) (graphWidth / diffX);
|
||||||
lastEndX = 0;
|
|
||||||
float firstX = 0;
|
|
||||||
int i=0;
|
int i=0;
|
||||||
while (values.hasNext()) {
|
while (values.hasNext()) {
|
||||||
E value = values.next();
|
E value = values.next();
|
||||||
|
@ -171,9 +162,6 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
|
||||||
double ratX = valX / diffX;
|
double ratX = valX / diffX;
|
||||||
double x = graphWidth * ratX;
|
double x = graphWidth * ratX;
|
||||||
|
|
||||||
double orgX = x;
|
|
||||||
double orgY = y;
|
|
||||||
|
|
||||||
// overdraw
|
// overdraw
|
||||||
boolean overdraw = false;
|
boolean overdraw = false;
|
||||||
if (x > graphWidth) { // end right
|
if (x > graphWidth) { // end right
|
||||||
|
@ -185,6 +173,14 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
|
||||||
if (y > graphHeight) { // end top
|
if (y > graphHeight) { // end top
|
||||||
overdraw = true;
|
overdraw = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
long duration = value.getDuration();
|
||||||
|
float endWithDuration = (float) (x + duration * scaleX + graphLeft + 1);
|
||||||
|
// cut off to graph start if needed
|
||||||
|
if (x < 0 && endWithDuration > 0) {
|
||||||
|
x = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Fix a bug that continue to show the DOT after Y axis */
|
/* Fix a bug that continue to show the DOT after Y axis */
|
||||||
if(x < 0) {
|
if(x < 0) {
|
||||||
overdraw = true;
|
overdraw = true;
|
||||||
|
@ -195,15 +191,25 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
|
||||||
registerDataPoint(endX, endY, value);
|
registerDataPoint(endX, endY, value);
|
||||||
|
|
||||||
float xpluslength = 0;
|
float xpluslength = 0;
|
||||||
if (value.getDuration() > 0) {
|
if (duration > 0) {
|
||||||
xpluslength = endX + Math.min((float) (value.getDuration() * graphWidth / diffX), graphLeft + graphWidth);
|
xpluslength = Math.min(endWithDuration, graphLeft + graphWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
// draw data point
|
// draw data point
|
||||||
if (!overdraw) {
|
if (!overdraw) {
|
||||||
if (value.getShape() == Shape.POINT) {
|
if (value.getShape() == Shape.BG) {
|
||||||
|
mPaint.setStyle(Paint.Style.FILL);
|
||||||
mPaint.setStrokeWidth(0);
|
mPaint.setStrokeWidth(0);
|
||||||
canvas.drawCircle(endX, endY, scaledPxSize, mPaint);
|
canvas.drawCircle(endX, endY, scaledPxSize, mPaint);
|
||||||
|
} else if (value.getShape() == Shape.PREDICTION) {
|
||||||
|
mPaint.setColor(value.getColor());
|
||||||
|
mPaint.setStyle(Paint.Style.FILL);
|
||||||
|
mPaint.setStrokeWidth(0);
|
||||||
|
canvas.drawCircle(endX, endY, scaledPxSize, mPaint);
|
||||||
|
mPaint.setColor(value.getSecondColor());
|
||||||
|
mPaint.setStyle(Paint.Style.FILL);
|
||||||
|
mPaint.setStrokeWidth(0);
|
||||||
|
canvas.drawCircle(endX, endY, scaledPxSize / 3, mPaint);
|
||||||
} else if (value.getShape() == Shape.RECTANGLE) {
|
} else if (value.getShape() == Shape.RECTANGLE) {
|
||||||
canvas.drawRect(endX-scaledPxSize, endY-scaledPxSize, endX+scaledPxSize, endY+scaledPxSize, mPaint);
|
canvas.drawRect(endX-scaledPxSize, endY-scaledPxSize, endX+scaledPxSize, endY+scaledPxSize, mPaint);
|
||||||
} else if (value.getShape() == Shape.TRIANGLE) {
|
} else if (value.getShape() == Shape.TRIANGLE) {
|
||||||
|
@ -224,6 +230,14 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
|
||||||
if (value.getLabel() != null) {
|
if (value.getLabel() != null) {
|
||||||
drawLabel45(endX, endY, value, canvas);
|
drawLabel45(endX, endY, value, canvas);
|
||||||
}
|
}
|
||||||
|
} else if (value.getShape() == Shape.SMB) {
|
||||||
|
mPaint.setStrokeWidth(2);
|
||||||
|
Point[] points = new Point[3];
|
||||||
|
points[0] = new Point((int)endX, (int)(endY-value.getSize()));
|
||||||
|
points[1] = new Point((int)(endX+value.getSize()), (int)(endY+value.getSize()*0.67));
|
||||||
|
points[2] = new Point((int)(endX-value.getSize()), (int)(endY+value.getSize()*0.67));
|
||||||
|
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
|
||||||
|
drawArrows(points, canvas, mPaint);
|
||||||
} else if (value.getShape() == Shape.EXTENDEDBOLUS) {
|
} else if (value.getShape() == Shape.EXTENDEDBOLUS) {
|
||||||
mPaint.setStrokeWidth(0);
|
mPaint.setStrokeWidth(0);
|
||||||
if (value.getLabel() != null) {
|
if (value.getLabel() != null) {
|
||||||
|
|
|
@ -21,8 +21,6 @@ import java.util.List;
|
||||||
import info.nightscout.androidaps.MainApp;
|
import info.nightscout.androidaps.MainApp;
|
||||||
import info.nightscout.androidaps.R;
|
import info.nightscout.androidaps.R;
|
||||||
import info.nightscout.androidaps.Services.AlarmSoundService;
|
import info.nightscout.androidaps.Services.AlarmSoundService;
|
||||||
import info.nightscout.androidaps.plugins.Wear.WearPlugin;
|
|
||||||
//Added by Rumen for snooze time
|
|
||||||
import info.nightscout.utils.SP;
|
import info.nightscout.utils.SP;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -44,16 +42,12 @@ public class NotificationStore {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Notification get(int index) {
|
public synchronized void add(Notification n) {
|
||||||
return store.get(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void add(Notification n) {
|
|
||||||
log.info("Notification received: " + n.text);
|
log.info("Notification received: " + n.text);
|
||||||
for (int i = 0; i < store.size(); i++) {
|
for (Notification storeNotification : store) {
|
||||||
if (get(i).id == n.id) {
|
if (storeNotification.id == n.id) {
|
||||||
get(i).date = n.date;
|
storeNotification.date = n.date;
|
||||||
get(i).validTo = n.validTo;
|
storeNotification.validTo = n.validTo;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,6 +66,44 @@ public class NotificationStore {
|
||||||
Collections.sort(store, new NotificationComparator());
|
Collections.sort(store, new NotificationComparator());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public synchronized boolean remove(int id) {
|
||||||
|
for (int i = 0; i < store.size(); i++) {
|
||||||
|
if (store.get(i).id == id) {
|
||||||
|
if (store.get(i).soundId != null) {
|
||||||
|
Intent alarm = new Intent(MainApp.instance().getApplicationContext(), AlarmSoundService.class);
|
||||||
|
MainApp.instance().stopService(alarm);
|
||||||
|
}
|
||||||
|
store.remove(i);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void removeExpired() {
|
||||||
|
for (int i = 0; i < store.size(); i++) {
|
||||||
|
Notification n = store.get(i);
|
||||||
|
if (n.validTo.getTime() != 0 && n.validTo.getTime() < System.currentTimeMillis()) {
|
||||||
|
store.remove(i);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void snoozeTo(long timeToSnooze) {
|
||||||
|
log.debug("Snoozing alarm until: " + timeToSnooze);
|
||||||
|
SP.putLong("snoozedTo", timeToSnooze);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void unSnooze() {
|
||||||
|
if (Notification.isAlarmForStaleData()) {
|
||||||
|
Notification notification = new Notification(Notification.NSALARM, MainApp.sResources.getString(R.string.nsalarm_staledata), Notification.URGENT);
|
||||||
|
SP.putLong("snoozedTo", System.currentTimeMillis());
|
||||||
|
add(notification);
|
||||||
|
log.debug("Snoozed to current time and added back notification!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void raiseSystemNotification(Notification n) {
|
private void raiseSystemNotification(Notification n) {
|
||||||
Context context = MainApp.instance().getApplicationContext();
|
Context context = MainApp.instance().getApplicationContext();
|
||||||
NotificationManager mgr = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
NotificationManager mgr = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
|
@ -95,42 +127,4 @@ public class NotificationStore {
|
||||||
}
|
}
|
||||||
mgr.notify(n.id, notificationBuilder.build());
|
mgr.notify(n.id, notificationBuilder.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean remove(int id) {
|
|
||||||
for (int i = 0; i < store.size(); i++) {
|
|
||||||
if (get(i).id == id) {
|
|
||||||
if (get(i).soundId != null) {
|
|
||||||
Intent alarm = new Intent(MainApp.instance().getApplicationContext(), AlarmSoundService.class);
|
|
||||||
MainApp.instance().stopService(alarm);
|
|
||||||
}
|
|
||||||
store.remove(i);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeExpired() {
|
|
||||||
for (int i = 0; i < store.size(); i++) {
|
|
||||||
Notification n = get(i);
|
|
||||||
if (n.validTo.getTime() != 0 && n.validTo.getTime() < System.currentTimeMillis()) {
|
|
||||||
store.remove(i);
|
|
||||||
i--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void snoozeTo(long timeToSnooze) {
|
|
||||||
log.debug("Snoozing alarm until: " + timeToSnooze);
|
|
||||||
SP.putLong("snoozedTo", timeToSnooze);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void unSnooze() {
|
|
||||||
if (Notification.isAlarmForStaleData()) {
|
|
||||||
Notification notification = new Notification(Notification.NSALARM, MainApp.sResources.getString(R.string.nsalarm_staledata), Notification.URGENT);
|
|
||||||
SP.putLong("snoozedTo", System.currentTimeMillis());
|
|
||||||
add(notification);
|
|
||||||
log.debug("Snoozed to current time and added back notification!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ import android.content.Intent;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.BitmapFactory;
|
import android.graphics.BitmapFactory;
|
||||||
import android.support.v4.app.TaskStackBuilder;
|
import android.support.v4.app.TaskStackBuilder;
|
||||||
import android.support.v7.app.NotificationCompat;
|
import android.support.v4.app.NotificationCompat;
|
||||||
|
|
||||||
import com.squareup.otto.Subscribe;
|
import com.squareup.otto.Subscribe;
|
||||||
|
|
||||||
|
|
|
@ -1,546 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.ProfileCircadianPercentage;
|
|
||||||
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.app.AlertDialog;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.support.design.widget.Snackbar;
|
|
||||||
import android.support.v4.app.DialogFragment;
|
|
||||||
import android.support.v4.content.ContextCompat;
|
|
||||||
import android.text.Editable;
|
|
||||||
import android.text.Html;
|
|
||||||
import android.text.TextWatcher;
|
|
||||||
import android.view.Gravity;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.view.inputmethod.InputMethodManager;
|
|
||||||
import android.widget.Button;
|
|
||||||
import android.widget.EditText;
|
|
||||||
import android.widget.FrameLayout;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
import android.widget.RadioButton;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import com.andreabaccega.widget.FormEditText;
|
|
||||||
import com.squareup.otto.Subscribe;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.MainApp;
|
|
||||||
import info.nightscout.androidaps.R;
|
|
||||||
import info.nightscout.androidaps.events.EventInitializationChanged;
|
|
||||||
import info.nightscout.androidaps.events.EventProfileSwitchChange;
|
|
||||||
import info.nightscout.androidaps.plugins.Careportal.CareportalFragment;
|
|
||||||
import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog;
|
|
||||||
import info.nightscout.androidaps.plugins.Careportal.OptionsToShow;
|
|
||||||
import info.nightscout.androidaps.plugins.Common.SubscriberFragment;
|
|
||||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
|
||||||
import info.nightscout.utils.DecimalFormatter;
|
|
||||||
import info.nightscout.utils.SafeParse;
|
|
||||||
|
|
||||||
public class CircadianPercentageProfileFragment extends SubscriberFragment {
|
|
||||||
private static Logger log = LoggerFactory.getLogger(CircadianPercentageProfileFragment.class);
|
|
||||||
|
|
||||||
private static CircadianPercentageProfilePlugin circadianPercentageProfilePlugin = new CircadianPercentageProfilePlugin();
|
|
||||||
private Object snackbarCaller;
|
|
||||||
|
|
||||||
public static CircadianPercentageProfilePlugin getPlugin() {
|
|
||||||
return circadianPercentageProfilePlugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
FormEditText diaView;
|
|
||||||
RadioButton mgdlView;
|
|
||||||
RadioButton mmolView;
|
|
||||||
FormEditText targetlowView;
|
|
||||||
FormEditText targethighView;
|
|
||||||
FormEditText percentageView;
|
|
||||||
FormEditText timeshiftView;
|
|
||||||
TextView profileView;
|
|
||||||
TextView baseprofileIC;
|
|
||||||
TextView baseprofileBasal;
|
|
||||||
LinearLayout baseprofileBasalLayout;
|
|
||||||
TextView baseprofileISF;
|
|
||||||
Button profileswitchButton;
|
|
||||||
ImageView percentageIcon;
|
|
||||||
ImageView timeIcon;
|
|
||||||
ImageView basaleditIcon;
|
|
||||||
ImageView iceditIcon;
|
|
||||||
ImageView isfeditIcon;
|
|
||||||
BasalEditDialog basalEditDialog;
|
|
||||||
FrameLayout fl;
|
|
||||||
Snackbar mSnackBar;
|
|
||||||
|
|
||||||
static Boolean percentageViewHint = true;
|
|
||||||
static Boolean timeshiftViewHint = true;
|
|
||||||
|
|
||||||
TextWatcher textWatch = new TextWatcher() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void afterTextChanged(Editable s) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void beforeTextChanged(CharSequence s, int start,
|
|
||||||
int count, int after) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onTextChanged(CharSequence s, int start,
|
|
||||||
int before, int count) {
|
|
||||||
|
|
||||||
if (percentageView.testValidity()) {
|
|
||||||
if (SafeParse.stringToInt(percentageView.getText().toString()) == 0) {
|
|
||||||
circadianPercentageProfilePlugin.percentage = 100;
|
|
||||||
} else {
|
|
||||||
circadianPercentageProfilePlugin.percentage = SafeParse.stringToInt(percentageView.getText().toString());
|
|
||||||
}
|
|
||||||
updateProfileInfo();
|
|
||||||
}
|
|
||||||
if (timeshiftView.testValidity()) {
|
|
||||||
circadianPercentageProfilePlugin.timeshift = SafeParse.stringToInt(timeshiftView.getText().toString());
|
|
||||||
updateProfileInfo();
|
|
||||||
}
|
|
||||||
if (diaView.testValidity()) {
|
|
||||||
circadianPercentageProfilePlugin.dia = SafeParse.stringToDouble(diaView.getText().toString());
|
|
||||||
updateProfileInfo();
|
|
||||||
}
|
|
||||||
if (targethighView.testValidity()) {
|
|
||||||
circadianPercentageProfilePlugin.targetLow = SafeParse.stringToDouble(targetlowView.getText().toString());
|
|
||||||
updateProfileInfo();
|
|
||||||
}
|
|
||||||
if (targetlowView.testValidity()) {
|
|
||||||
circadianPercentageProfilePlugin.targetHigh = SafeParse.stringToDouble(targethighView.getText().toString());
|
|
||||||
updateProfileInfo();
|
|
||||||
}
|
|
||||||
circadianPercentageProfilePlugin.storeSettings();
|
|
||||||
updateProfileInfo();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
|
||||||
Bundle savedInstanceState) {
|
|
||||||
|
|
||||||
showDeprecatedDialog();
|
|
||||||
|
|
||||||
View layout = inflater.inflate(R.layout.circadianpercentageprofile_fragment, container, false);
|
|
||||||
fl = (FrameLayout) layout.findViewById(R.id.circadianpercentageprofile_framelayout);
|
|
||||||
fl.requestFocusFromTouch();
|
|
||||||
diaView = (FormEditText) layout.findViewById(R.id.circadianpercentageprofile_dia);
|
|
||||||
mgdlView = (RadioButton) layout.findViewById(R.id.circadianpercentageprofile_mgdl);
|
|
||||||
mmolView = (RadioButton) layout.findViewById(R.id.circadianpercentageprofile_mmol);
|
|
||||||
targetlowView = (FormEditText) layout.findViewById(R.id.circadianpercentageprofile_targetlow);
|
|
||||||
targethighView = (FormEditText) layout.findViewById(R.id.circadianpercentageprofile_targethigh);
|
|
||||||
percentageView = (FormEditText) layout.findViewById(R.id.circadianpercentageprofile_percentage);
|
|
||||||
timeshiftView = (FormEditText) layout.findViewById(R.id.circadianpercentageprofile_timeshift);
|
|
||||||
profileView = (TextView) layout.findViewById(R.id.circadianpercentageprofile_profileview);
|
|
||||||
baseprofileBasal = (TextView) layout.findViewById(R.id.circadianpercentageprofile_baseprofilebasal);
|
|
||||||
baseprofileBasalLayout = (LinearLayout) layout.findViewById(R.id.circadianpercentageprofile_baseprofilebasal_layout);
|
|
||||||
baseprofileIC = (TextView) layout.findViewById(R.id.circadianpercentageprofile_baseprofileic);
|
|
||||||
baseprofileISF = (TextView) layout.findViewById(R.id.circadianpercentageprofile_baseprofileisf);
|
|
||||||
percentageIcon = (ImageView) layout.findViewById(R.id.circadianpercentageprofile_percentageicon);
|
|
||||||
timeIcon = (ImageView) layout.findViewById(R.id.circadianpercentageprofile_timeicon);
|
|
||||||
profileswitchButton = (Button) layout.findViewById(R.id.circadianpercentageprofile_profileswitch);
|
|
||||||
|
|
||||||
basaleditIcon = (ImageView) layout.findViewById(R.id.circadianpercentageprofile_basaledit);
|
|
||||||
iceditIcon = (ImageView) layout.findViewById(R.id.circadianpercentageprofile_icedit);
|
|
||||||
isfeditIcon = (ImageView) layout.findViewById(R.id.circadianpercentageprofile_isfedit);
|
|
||||||
|
|
||||||
if (!ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable) {
|
|
||||||
layout.findViewById(R.id.circadianpercentageprofile_baseprofilebasal_layout).setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
mgdlView.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
circadianPercentageProfilePlugin.mgdl = mgdlView.isChecked();
|
|
||||||
circadianPercentageProfilePlugin.mmol = !circadianPercentageProfilePlugin.mgdl;
|
|
||||||
mmolView.setChecked(circadianPercentageProfilePlugin.mmol);
|
|
||||||
circadianPercentageProfilePlugin.storeSettings();
|
|
||||||
updateProfileInfo();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
mmolView.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
circadianPercentageProfilePlugin.mmol = mmolView.isChecked();
|
|
||||||
circadianPercentageProfilePlugin.mgdl = !circadianPercentageProfilePlugin.mmol;
|
|
||||||
mgdlView.setChecked(circadianPercentageProfilePlugin.mgdl);
|
|
||||||
circadianPercentageProfilePlugin.storeSettings();
|
|
||||||
updateProfileInfo();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
profileswitchButton.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View view) {
|
|
||||||
NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog();
|
|
||||||
final OptionsToShow profileswitch = CareportalFragment.PROFILESWITCHDIRECT;
|
|
||||||
profileswitch.executeProfileSwitch = true;
|
|
||||||
newDialog.setOptions(profileswitch, R.string.careportal_profileswitch);
|
|
||||||
newDialog.show(getFragmentManager(), "NewNSTreatmentDialog");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
timeIcon.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View view) {
|
|
||||||
timeshiftView.requestFocusFromTouch();
|
|
||||||
timeshiftView.setSelection(timeshiftView.getText().length());
|
|
||||||
((InputMethodManager) getContext()
|
|
||||||
.getSystemService(Context.INPUT_METHOD_SERVICE)).showSoftInput(timeshiftView, InputMethodManager.SHOW_IMPLICIT);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
percentageIcon.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View view) {
|
|
||||||
percentageView.requestFocusFromTouch();
|
|
||||||
percentageView.setSelection(percentageView.getText().length());
|
|
||||||
((InputMethodManager) getContext()
|
|
||||||
.getSystemService(Context.INPUT_METHOD_SERVICE)).showSoftInput(percentageView, InputMethodManager.SHOW_IMPLICIT);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
basaleditIcon.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View view) {
|
|
||||||
basalEditDialog = new BasalEditDialog();
|
|
||||||
basalEditDialog.setup(getPlugin().basebasal, getString(R.string.edit_base_basal), CircadianPercentageProfileFragment.this);
|
|
||||||
basalEditDialog.show(getFragmentManager(), getString(R.string.edit_base_basal));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
isfeditIcon.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View view) {
|
|
||||||
basalEditDialog = new BasalEditDialog();
|
|
||||||
basalEditDialog.setup(getPlugin().baseisf, getString(R.string.edit_base_isf), CircadianPercentageProfileFragment.this);
|
|
||||||
basalEditDialog.show(getFragmentManager(), getString(R.string.edit_base_isf));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
iceditIcon.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View view) {
|
|
||||||
basalEditDialog = new BasalEditDialog();
|
|
||||||
basalEditDialog.setup(getPlugin().baseic, getString(R.string.edit_base_ic), CircadianPercentageProfileFragment.this);
|
|
||||||
basalEditDialog.show(getFragmentManager(), getString(R.string.edit_base_ic));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
/*timeshiftView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFocusChange(View view, boolean hasFocus) {
|
|
||||||
if (!hasFocus) {
|
|
||||||
if(mSnackBar!=null && snackbarCaller == timeshiftView){
|
|
||||||
mSnackBar.dismiss();
|
|
||||||
}
|
|
||||||
timeshiftView.clearFocus();
|
|
||||||
fl.requestFocusFromTouch();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (timeshiftViewHint) {
|
|
||||||
customSnackbar(view, getString(R.string.timeshift_hint), timeshiftView);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
percentageView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFocusChange(View view, boolean hasFocus) {
|
|
||||||
if (!hasFocus) {
|
|
||||||
if(mSnackBar!=null && snackbarCaller == percentageView){
|
|
||||||
mSnackBar.dismiss();
|
|
||||||
}
|
|
||||||
percentageView.clearFocus();
|
|
||||||
fl.requestFocusFromTouch();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (percentageViewHint) {
|
|
||||||
customSnackbar(view, getString(R.string.percentagefactor_hint), percentageView);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});*/
|
|
||||||
|
|
||||||
diaView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFocusChange(View view, boolean hasFocus) {
|
|
||||||
if (!hasFocus) {
|
|
||||||
diaView.clearFocus();
|
|
||||||
fl.requestFocusFromTouch();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
targethighView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFocusChange(View view, boolean hasFocus) {
|
|
||||||
if (!hasFocus) {
|
|
||||||
targethighView.clearFocus();
|
|
||||||
fl.requestFocusFromTouch();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
targetlowView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFocusChange(View view, boolean hasFocus) {
|
|
||||||
if (!hasFocus) {
|
|
||||||
targetlowView.clearFocus();
|
|
||||||
fl.requestFocusFromTouch();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
diaView.addTextChangedListener(textWatch);
|
|
||||||
targetlowView.addTextChangedListener(textWatch);
|
|
||||||
targethighView.addTextChangedListener(textWatch);
|
|
||||||
percentageView.addTextChangedListener(textWatch);
|
|
||||||
timeshiftView.addTextChangedListener(textWatch);
|
|
||||||
|
|
||||||
updateGUI();
|
|
||||||
|
|
||||||
onStatusEvent(new EventInitializationChanged());
|
|
||||||
|
|
||||||
return layout;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void showDeprecatedDialog() {
|
|
||||||
AlertDialog.Builder adb = new AlertDialog.Builder(getContext());
|
|
||||||
adb.setTitle("DEPRECATED! Please migrate!");
|
|
||||||
adb.setMessage("CircadianPercentageProfile has been deprecated. " +
|
|
||||||
"It is recommended to migrate to LocalProfile.\n\n" +
|
|
||||||
"Good news: You won't lose any functionality! Percentage and Timeshift have been ported to the ProfileSwitch :) \n\n " +
|
|
||||||
"How to migrate:\n" +
|
|
||||||
"1) Press MIGRATE, the system will automatically fill the LocalProfile for you.\n" +
|
|
||||||
"2) Switch to LocalProfile in the ConfigBuilder\n" +
|
|
||||||
"3) CHECK that all settings are correct in the LocalProfile!!!");
|
|
||||||
adb.setIcon(android.R.drawable.ic_dialog_alert);
|
|
||||||
adb.setPositiveButton("MIGRATE", new DialogInterface.OnClickListener() {
|
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
|
||||||
CircadianPercentageProfilePlugin.migrateToLP();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
adb.setNegativeButton("Cancel", null);
|
|
||||||
adb.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateGUI() {
|
|
||||||
updateProfileInfo();
|
|
||||||
|
|
||||||
diaView.removeTextChangedListener(textWatch);
|
|
||||||
targetlowView.removeTextChangedListener(textWatch);
|
|
||||||
targethighView.removeTextChangedListener(textWatch);
|
|
||||||
percentageView.removeTextChangedListener(textWatch);
|
|
||||||
timeshiftView.removeTextChangedListener(textWatch);
|
|
||||||
|
|
||||||
mgdlView.setChecked(circadianPercentageProfilePlugin.mgdl);
|
|
||||||
mmolView.setChecked(circadianPercentageProfilePlugin.mmol);
|
|
||||||
diaView.setText(circadianPercentageProfilePlugin.dia.toString());
|
|
||||||
targetlowView.setText(circadianPercentageProfilePlugin.targetLow.toString());
|
|
||||||
targethighView.setText(circadianPercentageProfilePlugin.targetHigh.toString());
|
|
||||||
percentageView.setText("" + circadianPercentageProfilePlugin.percentage);
|
|
||||||
timeshiftView.setText("" + circadianPercentageProfilePlugin.timeshift);
|
|
||||||
|
|
||||||
|
|
||||||
diaView.addTextChangedListener(textWatch);
|
|
||||||
targetlowView.addTextChangedListener(textWatch);
|
|
||||||
targethighView.addTextChangedListener(textWatch);
|
|
||||||
percentageView.addTextChangedListener(textWatch);
|
|
||||||
timeshiftView.addTextChangedListener(textWatch);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void customSnackbar(View view, final String Msg, Object snackbarCaller) {
|
|
||||||
if (mSnackBar != null) mSnackBar.dismiss();
|
|
||||||
|
|
||||||
this.snackbarCaller = snackbarCaller;
|
|
||||||
if (timeshiftViewHint || percentageViewHint) {
|
|
||||||
//noinspection WrongConstant
|
|
||||||
mSnackBar = Snackbar.make(view, Msg, 7000)
|
|
||||||
.setActionTextColor(ContextCompat.getColor(MainApp.instance(), R.color.notificationInfo))
|
|
||||||
.setAction(getString(R.string.dont_show_again), new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
if (Msg.equals(getString(R.string.percentagefactor_hint))) {
|
|
||||||
percentageViewHint = false;
|
|
||||||
} else if (Msg.equals(getString(R.string.timeshift_hint))) {
|
|
||||||
timeshiftViewHint = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
view = mSnackBar.getView();
|
|
||||||
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) view.getLayoutParams();
|
|
||||||
params.gravity = Gravity.CENTER_HORIZONTAL | Gravity.TOP;
|
|
||||||
view.setLayoutParams(params);
|
|
||||||
view.setBackgroundColor(ContextCompat.getColor(MainApp.instance(), R.color.cardview_dark_background));
|
|
||||||
TextView mainTextView = (TextView) (view).findViewById(android.support.design.R.id.snackbar_text);
|
|
||||||
mainTextView.setTextColor(ContextCompat.getColor(MainApp.instance(), R.color.mdtp_white));
|
|
||||||
mSnackBar.show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateProfileInfo() {
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
sb.append("<h3>");
|
|
||||||
sb.append(getString(R.string.nsprofileview_activeprofile_label));
|
|
||||||
sb.append("</h3>");
|
|
||||||
sb.append("<h4>");
|
|
||||||
sb.append(getString(R.string.nsprofileview_basal_label));
|
|
||||||
sb.append(" ( ∑");
|
|
||||||
sb.append(DecimalFormatter.to2Decimal(circadianPercentageProfilePlugin.percentageBasalSum()));
|
|
||||||
sb.append("U )");
|
|
||||||
sb.append("</h4> " + circadianPercentageProfilePlugin.basalString());
|
|
||||||
sb.append("<h4>");
|
|
||||||
sb.append(getString(R.string.nsprofileview_ic_label));
|
|
||||||
sb.append("</h4> " + circadianPercentageProfilePlugin.icString());
|
|
||||||
sb.append("<h4>");
|
|
||||||
sb.append(getString(R.string.nsprofileview_isf_label));
|
|
||||||
sb.append("</h4> " + circadianPercentageProfilePlugin.isfString());
|
|
||||||
profileView.setText(Html.fromHtml(sb.toString()));
|
|
||||||
|
|
||||||
baseprofileBasal.setText(Html.fromHtml("<h3>" + getString(R.string.base_profile_label) + " ( ∑" + DecimalFormatter.to2Decimal(circadianPercentageProfilePlugin.baseBasalSum()) + "U )</h3>" +
|
|
||||||
"<h4>" + getString(R.string.nsprofileview_basal_label) + "</h4>" + circadianPercentageProfilePlugin.baseBasalString()));
|
|
||||||
baseprofileIC.setText(Html.fromHtml("<h4>" + getString(R.string.nsprofileview_ic_label) + "</h4>" + circadianPercentageProfilePlugin.baseIcString()));
|
|
||||||
baseprofileISF.setText(Html.fromHtml("<h4>" + getString(R.string.nsprofileview_isf_label) + "</h4>" + circadianPercentageProfilePlugin.baseIsfString()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onStop() {
|
|
||||||
super.onStop();
|
|
||||||
if (basalEditDialog != null && basalEditDialog.isVisible()) {
|
|
||||||
basalEditDialog.dismiss();
|
|
||||||
}
|
|
||||||
basalEditDialog = null;
|
|
||||||
fl.requestFocusFromTouch();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class BasalEditDialog extends DialogFragment {
|
|
||||||
|
|
||||||
private double[] values;
|
|
||||||
private String title;
|
|
||||||
private CircadianPercentageProfileFragment fragment;
|
|
||||||
|
|
||||||
public void setup(double[] values, String title, CircadianPercentageProfileFragment fragment) {
|
|
||||||
this.values = values;
|
|
||||||
this.title = title;
|
|
||||||
this.fragment = fragment;
|
|
||||||
}
|
|
||||||
|
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
|
||||||
Bundle savedInstanceState) {
|
|
||||||
getDialog().setTitle(title);
|
|
||||||
View view = inflater.inflate(R.layout.circadianpercentageprofile_editbasal_dialog, container, false);
|
|
||||||
LinearLayout list = (LinearLayout) view.findViewById(R.id.circadianpp_editbasal_listlayout);
|
|
||||||
final EditText[] editTexts = new EditText[24];
|
|
||||||
for (int i = 0; i < 24; i++) {
|
|
||||||
View childview = inflater.inflate(R.layout.circadianpercentageprofile_listelement, container, false);
|
|
||||||
((TextView) childview.findViewById(R.id.basal_time_elem)).setText((i < 10 ? "0" : "") + i + ":00: ");
|
|
||||||
|
|
||||||
ImageView copyprevbutton = (ImageView) childview.findViewById(R.id.basal_copyprev_elem);
|
|
||||||
|
|
||||||
if (i == 0) {
|
|
||||||
copyprevbutton.setVisibility(View.INVISIBLE);
|
|
||||||
} else {
|
|
||||||
final int j = i; //needs to be final to be passed to inner class.
|
|
||||||
copyprevbutton.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View view) {
|
|
||||||
editTexts[j].setText(editTexts[j - 1].getText());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
editTexts[i] = ((EditText) childview.findViewById(R.id.basal_edittext_elem));
|
|
||||||
editTexts[i].setText(DecimalFormatter.to2Decimal(values[i]));
|
|
||||||
list.addView(childview);
|
|
||||||
}
|
|
||||||
getDialog().setCancelable(true);
|
|
||||||
|
|
||||||
view.findViewById(R.id.ok_button).setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View view) {
|
|
||||||
for (int i = 0; i < 24; i++) {
|
|
||||||
if (editTexts[i].getText().length() != 0) {
|
|
||||||
values[i] = SafeParse.stringToDouble(editTexts[i].getText().toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fragment.updateProfileInfo();
|
|
||||||
getPlugin().storeSettings();
|
|
||||||
dismiss();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
view.findViewById(R.id.cancel_action).setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View view) {
|
|
||||||
dismiss();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return view;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPause() {
|
|
||||||
super.onPause();
|
|
||||||
|
|
||||||
if (basalEditDialog != null && basalEditDialog.isVisible()) {
|
|
||||||
basalEditDialog.dismiss();
|
|
||||||
}
|
|
||||||
basalEditDialog = null;
|
|
||||||
|
|
||||||
fl.requestFocusFromTouch();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onResume() {
|
|
||||||
super.onResume();
|
|
||||||
onStatusEvent(new EventInitializationChanged());
|
|
||||||
fl.requestFocusFromTouch();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Subscribe
|
|
||||||
public void onStatusEvent(final EventInitializationChanged e) {
|
|
||||||
Activity activity = getActivity();
|
|
||||||
if (activity != null)
|
|
||||||
activity.runOnUiThread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
if (!ConfigBuilderPlugin.getActivePump().isInitialized() || ConfigBuilderPlugin.getActivePump().isSuspended()) {
|
|
||||||
profileswitchButton.setVisibility(View.GONE);
|
|
||||||
} else {
|
|
||||||
profileswitchButton.setVisibility(View.VISIBLE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Subscribe
|
|
||||||
public void onStatusEvent(final EventProfileSwitchChange e) {
|
|
||||||
Activity activity = getActivity();
|
|
||||||
if (activity != null)
|
|
||||||
activity.runOnUiThread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
updateGUI();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,455 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.ProfileCircadianPercentage;
|
|
||||||
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.preference.PreferenceManager;
|
|
||||||
|
|
||||||
import org.json.JSONArray;
|
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.text.DecimalFormat;
|
|
||||||
|
|
||||||
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.interfaces.PluginBase;
|
|
||||||
import info.nightscout.androidaps.interfaces.ProfileInterface;
|
|
||||||
import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog;
|
|
||||||
import info.nightscout.androidaps.plugins.ProfileLocal.LocalProfilePlugin;
|
|
||||||
import info.nightscout.utils.DecimalFormatter;
|
|
||||||
import info.nightscout.utils.NSUpload;
|
|
||||||
import info.nightscout.utils.SP;
|
|
||||||
import info.nightscout.utils.SafeParse;
|
|
||||||
import info.nightscout.utils.ToastUtils;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Adrian on 12.11.2016.
|
|
||||||
* Based on SimpleProfile created by mike on 05.08.2016.
|
|
||||||
*/
|
|
||||||
public class CircadianPercentageProfilePlugin implements PluginBase, ProfileInterface {
|
|
||||||
public static final String SETTINGS_PREFIX = "CircadianPercentageProfile";
|
|
||||||
private static Logger log = LoggerFactory.getLogger(CircadianPercentageProfilePlugin.class);
|
|
||||||
|
|
||||||
private boolean fragmentEnabled = false;
|
|
||||||
private boolean fragmentVisible = false;
|
|
||||||
|
|
||||||
private static ProfileStore convertedProfile = null;
|
|
||||||
private static String convertedProfileName = null;
|
|
||||||
|
|
||||||
boolean mgdl;
|
|
||||||
boolean mmol;
|
|
||||||
Double dia;
|
|
||||||
Double targetLow;
|
|
||||||
Double targetHigh;
|
|
||||||
public int percentage;
|
|
||||||
public int timeshift;
|
|
||||||
double[] basebasal = new double[]{1d, 1d, 1d, 1d, 1d, 1d, 1d, 1d, 1d, 1d, 1d, 1d, 1d, 1d, 1d, 1d, 1d, 1d, 1d, 1d, 1d, 1d, 1d, 1d};
|
|
||||||
double[] baseisf = new double[]{35d, 35d, 35d, 35d, 35d, 35d, 35d, 35d, 35d, 35d, 35d, 35d, 35d, 35d, 35d, 35d, 35d, 35d, 35d, 35d, 35d, 35d, 35d, 35d};
|
|
||||||
double[] baseic = new double[]{4d, 4d, 4d, 4d, 4d, 4d, 4d, 4d, 4d, 4d, 4d, 4d, 4d, 4d, 4d, 4d, 4d, 4d, 4d, 4d, 4d, 4d, 4d, 4d};
|
|
||||||
|
|
||||||
public CircadianPercentageProfilePlugin() {
|
|
||||||
loadSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getFragmentClass() {
|
|
||||||
return CircadianPercentageProfileFragment.class.getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getType() {
|
|
||||||
return PluginBase.PROFILE;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return MainApp.instance().getString(R.string.circadian_percentage_profile);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getNameShort() {
|
|
||||||
String name = MainApp.sResources.getString(R.string.circadian_percentage_profile_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 == PROFILE && fragmentEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isVisibleInTabs(int type) {
|
|
||||||
return type == PROFILE && 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 == PROFILE) this.fragmentEnabled = fragmentEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setFragmentVisible(int type, boolean fragmentVisible) {
|
|
||||||
if (type == PROFILE) this.fragmentVisible = fragmentVisible;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getPreferencesId() {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void storeSettings() {
|
|
||||||
if (Config.logPrefsChange)
|
|
||||||
log.debug("Storing settings");
|
|
||||||
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
|
|
||||||
SharedPreferences.Editor editor = settings.edit();
|
|
||||||
editor.putBoolean(SETTINGS_PREFIX + "mmol", mmol);
|
|
||||||
editor.putBoolean(SETTINGS_PREFIX + "mgdl", mgdl);
|
|
||||||
editor.putString(SETTINGS_PREFIX + "dia", dia.toString());
|
|
||||||
editor.putString(SETTINGS_PREFIX + "targetlow", targetLow.toString());
|
|
||||||
editor.putString(SETTINGS_PREFIX + "targethigh", targetHigh.toString());
|
|
||||||
editor.putString(SETTINGS_PREFIX + "timeshift", timeshift + "");
|
|
||||||
editor.putString(SETTINGS_PREFIX + "percentage", percentage + "");
|
|
||||||
|
|
||||||
|
|
||||||
for (int i = 0; i < 24; i++) {
|
|
||||||
editor.putString(SETTINGS_PREFIX + "basebasal" + i, DecimalFormatter.to2Decimal(basebasal[i]));
|
|
||||||
editor.putString(SETTINGS_PREFIX + "baseisf" + i, DecimalFormatter.to2Decimal(baseisf[i]));
|
|
||||||
editor.putString(SETTINGS_PREFIX + "baseic" + i, DecimalFormatter.to2Decimal(baseic[i]));
|
|
||||||
}
|
|
||||||
editor.commit();
|
|
||||||
createConvertedProfile();
|
|
||||||
}
|
|
||||||
|
|
||||||
void loadSettings() {
|
|
||||||
if (Config.logPrefsChange)
|
|
||||||
log.debug("Loading stored settings");
|
|
||||||
|
|
||||||
mgdl = SP.getBoolean(SETTINGS_PREFIX + "mgdl", true);
|
|
||||||
mmol = SP.getBoolean(SETTINGS_PREFIX + "mmol", false);
|
|
||||||
dia = SP.getDouble(SETTINGS_PREFIX + "dia", Constants.defaultDIA);
|
|
||||||
targetLow = SP.getDouble(SETTINGS_PREFIX + "targetlow", 80d);
|
|
||||||
targetHigh = SP.getDouble(SETTINGS_PREFIX + "targethigh", 120d);
|
|
||||||
percentage = SP.getInt(SETTINGS_PREFIX + "percentage", 100);
|
|
||||||
timeshift = SP.getInt(SETTINGS_PREFIX + "timeshift", 0);
|
|
||||||
|
|
||||||
for (int i = 0; i < 24; i++) {
|
|
||||||
basebasal[i] = SP.getDouble(SETTINGS_PREFIX + "basebasal" + i, basebasal[i]);
|
|
||||||
baseic[i] = SP.getDouble(SETTINGS_PREFIX + "baseic" + i, baseic[i]);
|
|
||||||
baseisf[i] = SP.getDouble(SETTINGS_PREFIX + "baseisf" + i, baseisf[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public String externallySetParameters(int timeshift, int percentage) {
|
|
||||||
|
|
||||||
String msg = "";
|
|
||||||
|
|
||||||
if (!fragmentEnabled) {
|
|
||||||
msg += "NO CPP!" + "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
//check for validity
|
|
||||||
if (percentage < Constants.CPP_MIN_PERCENTAGE || percentage > Constants.CPP_MAX_PERCENTAGE) {
|
|
||||||
msg += String.format(MainApp.sResources.getString(R.string.openapsma_valueoutofrange), "Profile-Percentage") + "\n";
|
|
||||||
}
|
|
||||||
if (timeshift < 0 || timeshift > 23) {
|
|
||||||
msg += String.format(MainApp.sResources.getString(R.string.openapsma_valueoutofrange), "Profile-Timeshift") + "\n";
|
|
||||||
}
|
|
||||||
final Profile profile = MainApp.getConfigBuilder().getProfile();
|
|
||||||
|
|
||||||
if (profile == null || profile.getBasal() == null) {
|
|
||||||
msg += MainApp.sResources.getString(R.string.cpp_notloadedplugins) + "\n";
|
|
||||||
}
|
|
||||||
if (!"".equals(msg)) {
|
|
||||||
msg += MainApp.sResources.getString(R.string.cpp_valuesnotstored);
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
//store profile
|
|
||||||
this.timeshift = timeshift;
|
|
||||||
this.percentage = percentage;
|
|
||||||
storeSettings();
|
|
||||||
|
|
||||||
|
|
||||||
//send profile to pumpe
|
|
||||||
new NewNSTreatmentDialog(); //init
|
|
||||||
NewNSTreatmentDialog.doProfileSwitch(this.getProfile(), this.getProfileName(), 0, percentage, timeshift);
|
|
||||||
|
|
||||||
//return formatted string
|
|
||||||
/*msg += "%: " + this.percentage + " h: +" + this.timeshift;
|
|
||||||
msg += "\n";
|
|
||||||
msg += "\nBasal:\n" + basalString() + "\n";
|
|
||||||
msg += "\nISF:\n" + isfString() + "\n";
|
|
||||||
msg += "\nIC:\n" + isfString() + "\n";*/
|
|
||||||
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void migrateToLP() {
|
|
||||||
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
|
|
||||||
SharedPreferences.Editor editor = settings.edit();
|
|
||||||
editor.putBoolean("LocalProfile" + "mmol", SP.getBoolean(SETTINGS_PREFIX + "mmol", false));
|
|
||||||
editor.putBoolean("LocalProfile" + "mgdl", SP.getBoolean(SETTINGS_PREFIX + "mgdl", true));
|
|
||||||
editor.putString("LocalProfile" + "dia", "" + SP.getDouble(SETTINGS_PREFIX + "dia", Constants.defaultDIA));
|
|
||||||
editor.putString("LocalProfile" + "ic", getLPic());
|
|
||||||
editor.putString("LocalProfile" + "isf", getLPisf());
|
|
||||||
editor.putString("LocalProfile" + "basal", getLPbasal());
|
|
||||||
try {
|
|
||||||
JSONArray targetLow = new JSONArray().put(new JSONObject().put("time", "00:00").put("timeAsSeconds", 0).put("value", SP.getDouble(SETTINGS_PREFIX + "targetlow", 120d)));
|
|
||||||
JSONArray targetHigh = new JSONArray().put(new JSONObject().put("time", "00:00").put("timeAsSeconds", 0).put("value", SP.getDouble(SETTINGS_PREFIX + "targethigh", 120d)));
|
|
||||||
editor.putString("LocalProfile" + "targetlow", targetLow.toString());
|
|
||||||
editor.putString("LocalProfile" + "targethigh", targetHigh.toString());
|
|
||||||
} catch (JSONException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
editor.commit();
|
|
||||||
LocalProfilePlugin lp = MainApp.getSpecificPlugin(LocalProfilePlugin.class);
|
|
||||||
lp.loadSettings();
|
|
||||||
|
|
||||||
/* TODO: remove Settings and switch to LP later on
|
|
||||||
* For now only nag the user every time (s)he opens the CPP fragment and offer to migrate.
|
|
||||||
* Keep settings for now in order to allow the user to check that the migration went well.
|
|
||||||
*/
|
|
||||||
//removeSettings();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getLPisf() {
|
|
||||||
return getLPConversion("baseisf", 35d);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getLPic() {
|
|
||||||
return getLPConversion("baseic", 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getLPbasal() {
|
|
||||||
return getLPConversion("basebasal", 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getLPConversion(String type, double defaultValue) {
|
|
||||||
try {
|
|
||||||
JSONArray jsonArray = new JSONArray();
|
|
||||||
double last = -1d;
|
|
||||||
|
|
||||||
for (int i = 0; i < 24; i++) {
|
|
||||||
double value = SP.getDouble(SETTINGS_PREFIX + type + i, defaultValue);
|
|
||||||
String time;
|
|
||||||
DecimalFormat df = new DecimalFormat("00");
|
|
||||||
time = df.format(i) + ":00";
|
|
||||||
if (last != value) {
|
|
||||||
jsonArray.put(new JSONObject().put("time", time).put("timeAsSeconds", i * 60 * 60).put("value", value));
|
|
||||||
}
|
|
||||||
last = value;
|
|
||||||
}
|
|
||||||
return jsonArray.toString();
|
|
||||||
} catch (JSONException e) {
|
|
||||||
log.error("Unhandled exception", e);
|
|
||||||
}
|
|
||||||
return LocalProfilePlugin.DEFAULTARRAY;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void removeSettings() {
|
|
||||||
if (Config.logPrefsChange)
|
|
||||||
log.debug("Removing settings");
|
|
||||||
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
|
|
||||||
SharedPreferences.Editor editor = settings.edit();
|
|
||||||
editor.remove(SETTINGS_PREFIX + "mmol");
|
|
||||||
editor.remove(SETTINGS_PREFIX + "mgdl");
|
|
||||||
editor.remove(SETTINGS_PREFIX + "dia");
|
|
||||||
editor.remove(SETTINGS_PREFIX + "targetlow");
|
|
||||||
editor.remove(SETTINGS_PREFIX + "targethigh");
|
|
||||||
editor.remove(SETTINGS_PREFIX + "timeshift");
|
|
||||||
editor.remove(SETTINGS_PREFIX + "percentage");
|
|
||||||
|
|
||||||
|
|
||||||
for (int i = 0; i < 24; i++) {
|
|
||||||
editor.remove(SETTINGS_PREFIX + "basebasal");
|
|
||||||
editor.remove(SETTINGS_PREFIX + "baseisf" + i);
|
|
||||||
editor.remove(SETTINGS_PREFIX + "baseic" + i);
|
|
||||||
}
|
|
||||||
editor.commit();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void createConvertedProfile() {
|
|
||||||
JSONObject json = new JSONObject();
|
|
||||||
JSONObject store = new JSONObject();
|
|
||||||
JSONObject profile = new JSONObject();
|
|
||||||
|
|
||||||
StringBuilder stringBuilder = new StringBuilder();
|
|
||||||
stringBuilder.append(DecimalFormatter.to2Decimal(sum(basebasal)));
|
|
||||||
stringBuilder.append("U@");
|
|
||||||
stringBuilder.append(percentage);
|
|
||||||
stringBuilder.append("%>");
|
|
||||||
stringBuilder.append(timeshift);
|
|
||||||
stringBuilder.append("h");
|
|
||||||
String profileName = stringBuilder.toString();
|
|
||||||
|
|
||||||
try {
|
|
||||||
json.put("defaultProfile", profileName);
|
|
||||||
json.put("store", store);
|
|
||||||
profile.put("dia", dia);
|
|
||||||
|
|
||||||
int offset = -(timeshift % 24) + 24;
|
|
||||||
|
|
||||||
JSONArray icArray = new JSONArray();
|
|
||||||
JSONArray isfArray = new JSONArray();
|
|
||||||
JSONArray basalArray = new JSONArray();
|
|
||||||
for (int i = 0; i < 24; i++) {
|
|
||||||
String time;
|
|
||||||
DecimalFormat df = new DecimalFormat("00");
|
|
||||||
time = df.format(i) + ":00";
|
|
||||||
icArray.put(new JSONObject().put("time", time).put("timeAsSeconds", i * 60 * 60).put("value", baseic[(offset + i) % 24] * 100d / percentage));
|
|
||||||
isfArray.put(new JSONObject().put("time", time).put("timeAsSeconds", i * 60 * 60).put("value", baseisf[(offset + i) % 24] * 100d / percentage));
|
|
||||||
basalArray.put(new JSONObject().put("time", time).put("timeAsSeconds", i * 60 * 60).put("value", basebasal[(offset + i) % 24] * percentage / 100d));
|
|
||||||
}
|
|
||||||
profile.put("carbratio", icArray);
|
|
||||||
profile.put("sens", isfArray);
|
|
||||||
profile.put("basal", basalArray);
|
|
||||||
|
|
||||||
|
|
||||||
profile.put("target_low", new JSONArray().put(new JSONObject().put("time", "00:00").put("timeAsSeconds", 0).put("value", targetLow)));
|
|
||||||
profile.put("target_high", new JSONArray().put(new JSONObject().put("time", "00:00").put("timeAsSeconds", 0).put("value", targetHigh)));
|
|
||||||
profile.put("units", mgdl ? Constants.MGDL : Constants.MMOL);
|
|
||||||
store.put(profileName, profile);
|
|
||||||
} catch (JSONException e) {
|
|
||||||
log.error("Unhandled exception", e);
|
|
||||||
}
|
|
||||||
convertedProfile = new ProfileStore(json);
|
|
||||||
convertedProfileName = profileName;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ProfileStore getProfile() {
|
|
||||||
if (convertedProfile == null)
|
|
||||||
createConvertedProfile();
|
|
||||||
|
|
||||||
performLimitCheck();
|
|
||||||
return convertedProfile;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getUnits() {
|
|
||||||
return mgdl ? Constants.MGDL : Constants.MMOL;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getProfileName() {
|
|
||||||
if (convertedProfile == null)
|
|
||||||
createConvertedProfile();
|
|
||||||
|
|
||||||
performLimitCheck();
|
|
||||||
return convertedProfileName;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void performLimitCheck() {
|
|
||||||
if (percentage < Constants.CPP_MIN_PERCENTAGE || percentage > Constants.CPP_MAX_PERCENTAGE) {
|
|
||||||
String msg = String.format(MainApp.sResources.getString(R.string.openapsma_valueoutofrange), "Profile-Percentage");
|
|
||||||
log.error(msg);
|
|
||||||
NSUpload.uploadError(msg);
|
|
||||||
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), msg, R.raw.error);
|
|
||||||
percentage = Math.max(percentage, Constants.CPP_MIN_PERCENTAGE);
|
|
||||||
percentage = Math.min(percentage, Constants.CPP_MAX_PERCENTAGE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String basalString() {
|
|
||||||
return profileString(basebasal, timeshift, percentage, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
String icString() {
|
|
||||||
return profileString(baseic, timeshift, percentage, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
String isfString() {
|
|
||||||
return profileString(baseisf, timeshift, percentage, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
String baseIcString() {
|
|
||||||
return profileString(baseic, 0, 100, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
String baseIsfString() {
|
|
||||||
return profileString(baseisf, 0, 100, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
String baseBasalString() {
|
|
||||||
return profileString(basebasal, 0, 100, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public double baseBasalSum() {
|
|
||||||
return sum(basebasal);
|
|
||||||
}
|
|
||||||
|
|
||||||
public double percentageBasalSum() {
|
|
||||||
double result = 0;
|
|
||||||
for (int i = 0; i < basebasal.length; i++) {
|
|
||||||
result += SafeParse.stringToDouble(DecimalFormatter.to2Decimal(basebasal[i] * percentage / 100d));
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static double sum(double values[]) {
|
|
||||||
double result = 0;
|
|
||||||
for (int i = 0; i < values.length; i++) {
|
|
||||||
result += values[i];
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private static String profileString(double[] values, int timeshift, int percentage, boolean inc) {
|
|
||||||
timeshift = -(timeshift % 24) + 24;
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
sb.append("<b>");
|
|
||||||
sb.append(0);
|
|
||||||
sb.append("h: ");
|
|
||||||
sb.append("</b>");
|
|
||||||
sb.append(DecimalFormatter.to2Decimal(values[(timeshift + 0) % 24] * (inc ? percentage / 100d : 100d / percentage)));
|
|
||||||
double prevVal = values[(timeshift + 0) % 24];
|
|
||||||
for (int i = 1; i < 24; i++) {
|
|
||||||
if (prevVal != values[(timeshift + i) % 24]) {
|
|
||||||
sb.append(", ");
|
|
||||||
sb.append("<b>");
|
|
||||||
sb.append(i);
|
|
||||||
sb.append("h: ");
|
|
||||||
sb.append("</b>");
|
|
||||||
sb.append(DecimalFormatter.to2Decimal(values[(timeshift + i) % 24] * (inc ? percentage / 100d : 100d / percentage)));
|
|
||||||
prevVal = values[(timeshift + i) % 24];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getPercentage() {
|
|
||||||
return percentage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getTimeshift() {
|
|
||||||
return timeshift;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,560 @@
|
||||||
|
package info.nightscout.androidaps.plugins.PumpDanaR;
|
||||||
|
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
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.Profile;
|
||||||
|
import info.nightscout.androidaps.data.ProfileStore;
|
||||||
|
import info.nightscout.androidaps.data.PumpEnactResult;
|
||||||
|
import info.nightscout.androidaps.db.ExtendedBolus;
|
||||||
|
import info.nightscout.androidaps.db.TemporaryBasal;
|
||||||
|
import info.nightscout.androidaps.interfaces.ConstraintsInterface;
|
||||||
|
import info.nightscout.androidaps.interfaces.DanaRInterface;
|
||||||
|
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||||
|
import info.nightscout.androidaps.interfaces.ProfileInterface;
|
||||||
|
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.androidaps.plugins.ProfileNS.NSProfilePlugin;
|
||||||
|
import info.nightscout.androidaps.plugins.PumpDanaR.services.AbstractDanaRExecutionService;
|
||||||
|
import info.nightscout.utils.DateUtil;
|
||||||
|
import info.nightscout.utils.DecimalFormatter;
|
||||||
|
import info.nightscout.utils.Round;
|
||||||
|
import info.nightscout.utils.SP;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 28.01.2018.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public abstract class AbstractDanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, ConstraintsInterface, ProfileInterface {
|
||||||
|
protected Logger log;
|
||||||
|
|
||||||
|
protected boolean mPluginPumpEnabled = false;
|
||||||
|
protected boolean mPluginProfileEnabled = false;
|
||||||
|
protected boolean mFragmentPumpVisible = true;
|
||||||
|
|
||||||
|
protected AbstractDanaRExecutionService sExecutionService;
|
||||||
|
|
||||||
|
protected DanaRPump pump = DanaRPump.getInstance();
|
||||||
|
protected boolean useExtendedBoluses = false;
|
||||||
|
|
||||||
|
public PumpDescription pumpDescription = new PumpDescription();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getFragmentClass() {
|
||||||
|
return DanaRFragment.class.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Plugin base interface
|
||||||
|
@Override
|
||||||
|
public int getType() {
|
||||||
|
return PluginBase.PUMP;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getNameShort() {
|
||||||
|
String name = MainApp.sResources.getString(R.string.danarpump_shortname);
|
||||||
|
if (!name.trim().isEmpty()) {
|
||||||
|
//only if translation exists
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
// use long name as fallback
|
||||||
|
return getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEnabled(int type) {
|
||||||
|
if (type == PluginBase.PROFILE) return mPluginProfileEnabled && mPluginPumpEnabled;
|
||||||
|
else if (type == PluginBase.PUMP) return mPluginPumpEnabled;
|
||||||
|
else if (type == PluginBase.CONSTRAINTS) return mPluginPumpEnabled;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isVisibleInTabs(int type) {
|
||||||
|
if (type == PluginBase.PROFILE || type == PluginBase.CONSTRAINTS) return false;
|
||||||
|
else if (type == PluginBase.PUMP) return mFragmentPumpVisible;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canBeHidden(int type) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasFragment() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean showInList(int type) {
|
||||||
|
return type == PUMP;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
|
||||||
|
if (type == PluginBase.PROFILE)
|
||||||
|
mPluginProfileEnabled = fragmentEnabled;
|
||||||
|
else if (type == PluginBase.PUMP)
|
||||||
|
mPluginPumpEnabled = fragmentEnabled;
|
||||||
|
// if pump profile was enabled need to switch to another too
|
||||||
|
if (type == PluginBase.PUMP && !fragmentEnabled && mPluginProfileEnabled) {
|
||||||
|
setFragmentEnabled(PluginBase.PROFILE, false);
|
||||||
|
setFragmentVisible(PluginBase.PROFILE, false);
|
||||||
|
NSProfilePlugin.getPlugin().setFragmentEnabled(PluginBase.PROFILE, true);
|
||||||
|
NSProfilePlugin.getPlugin().setFragmentVisible(PluginBase.PROFILE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFragmentVisible(int type, boolean fragmentVisible) {
|
||||||
|
if (type == PluginBase.PUMP)
|
||||||
|
mFragmentPumpVisible = fragmentVisible;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSuspended() {
|
||||||
|
return pump.pumpSuspended;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isBusy() {
|
||||||
|
if (sExecutionService == null) return false;
|
||||||
|
return sExecutionService.isConnected() || sExecutionService.isConnecting();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pump interface
|
||||||
|
@Override
|
||||||
|
public PumpEnactResult setNewBasalProfile(Profile profile) {
|
||||||
|
PumpEnactResult result = new PumpEnactResult();
|
||||||
|
|
||||||
|
if (sExecutionService == null) {
|
||||||
|
log.error("setNewBasalProfile sExecutionService is null");
|
||||||
|
result.comment = "setNewBasalProfile sExecutionService is null";
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if (!isInitialized()) {
|
||||||
|
log.error("setNewBasalProfile not initialized");
|
||||||
|
Notification notification = new Notification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED, MainApp.sResources.getString(R.string.pumpNotInitializedProfileNotSet), Notification.URGENT);
|
||||||
|
MainApp.bus().post(new EventNewNotification(notification));
|
||||||
|
result.comment = MainApp.sResources.getString(R.string.pumpNotInitializedProfileNotSet);
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED));
|
||||||
|
}
|
||||||
|
if (!sExecutionService.updateBasalsInPump(profile)) {
|
||||||
|
Notification notification = new Notification(Notification.FAILED_UDPATE_PROFILE, MainApp.sResources.getString(R.string.failedupdatebasalprofile), Notification.URGENT);
|
||||||
|
MainApp.bus().post(new EventNewNotification(notification));
|
||||||
|
result.comment = MainApp.sResources.getString(R.string.failedupdatebasalprofile);
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED));
|
||||||
|
MainApp.bus().post(new EventDismissNotification(Notification.FAILED_UDPATE_PROFILE));
|
||||||
|
Notification notification = new Notification(Notification.PROFILE_SET_OK, MainApp.sResources.getString(R.string.profile_set_ok), Notification.INFO, 60);
|
||||||
|
MainApp.bus().post(new EventNewNotification(notification));
|
||||||
|
result.success = true;
|
||||||
|
result.enacted = true;
|
||||||
|
result.comment = "OK";
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isThisProfileSet(Profile profile) {
|
||||||
|
if (!isInitialized())
|
||||||
|
return true; // TODO: not sure what's better. so far TRUE to prevent too many SMS
|
||||||
|
if (pump.pumpProfiles == null)
|
||||||
|
return true; // TODO: not sure what's better. so far TRUE to prevent too many SMS
|
||||||
|
int basalValues = pump.basal48Enable ? 48 : 24;
|
||||||
|
int basalIncrement = pump.basal48Enable ? 30 * 60 : 60 * 60;
|
||||||
|
for (int h = 0; h < basalValues; h++) {
|
||||||
|
Double pumpValue = pump.pumpProfiles[pump.activeProfile][h];
|
||||||
|
Double profileValue = profile.getBasal((Integer) (h * basalIncrement));
|
||||||
|
if (profileValue == null) return true;
|
||||||
|
if (Math.abs(pumpValue - profileValue) > getPumpDescription().basalStep) {
|
||||||
|
log.debug("Diff found. Hour: " + h + " Pump: " + pumpValue + " Profile: " + profileValue);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Date lastDataTime() {
|
||||||
|
return new Date(pump.lastConnection);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getBaseBasalRate() {
|
||||||
|
return pump.currentBasal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stopBolusDelivering() {
|
||||||
|
if (sExecutionService == null) {
|
||||||
|
log.error("stopBolusDelivering sExecutionService is null");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sExecutionService.bolusStop();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, boolean enforceNew) {
|
||||||
|
PumpEnactResult result = new PumpEnactResult();
|
||||||
|
ConfigBuilderPlugin configBuilderPlugin = MainApp.getConfigBuilder();
|
||||||
|
percent = configBuilderPlugin.applyBasalConstraints(percent);
|
||||||
|
if (percent < 0) {
|
||||||
|
result.isTempCancel = false;
|
||||||
|
result.enacted = false;
|
||||||
|
result.success = false;
|
||||||
|
result.comment = MainApp.instance().getString(R.string.danar_invalidinput);
|
||||||
|
log.error("setTempBasalPercent: Invalid input");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if (percent > getPumpDescription().maxTempPercent)
|
||||||
|
percent = getPumpDescription().maxTempPercent;
|
||||||
|
TemporaryBasal runningTB = MainApp.getConfigBuilder().getRealTempBasalFromHistory(System.currentTimeMillis());
|
||||||
|
if (runningTB != null && runningTB.percentRate == percent && !enforceNew) {
|
||||||
|
result.enacted = false;
|
||||||
|
result.success = true;
|
||||||
|
result.isTempCancel = false;
|
||||||
|
result.comment = MainApp.instance().getString(R.string.virtualpump_resultok);
|
||||||
|
result.duration = pump.tempBasalRemainingMin;
|
||||||
|
result.percent = pump.tempBasalPercent;
|
||||||
|
result.absolute = MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory();
|
||||||
|
result.isPercent = true;
|
||||||
|
if (Config.logPumpActions)
|
||||||
|
log.debug("setTempBasalPercent: Correct value already set");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
int durationInHours = Math.max(durationInMinutes / 60, 1);
|
||||||
|
boolean connectionOK = sExecutionService.tempBasal(percent, durationInHours);
|
||||||
|
if (connectionOK && pump.isTempBasalInProgress && pump.tempBasalPercent == percent) {
|
||||||
|
result.enacted = true;
|
||||||
|
result.success = true;
|
||||||
|
result.comment = MainApp.instance().getString(R.string.virtualpump_resultok);
|
||||||
|
result.isTempCancel = false;
|
||||||
|
result.duration = pump.tempBasalRemainingMin;
|
||||||
|
result.percent = pump.tempBasalPercent;
|
||||||
|
result.absolute = MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory();
|
||||||
|
result.isPercent = true;
|
||||||
|
if (Config.logPumpActions)
|
||||||
|
log.debug("setTempBasalPercent: OK");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
result.enacted = false;
|
||||||
|
result.success = false;
|
||||||
|
result.comment = MainApp.instance().getString(R.string.tempbasaldeliveryerror);
|
||||||
|
log.error("setTempBasalPercent: Failed to set temp basal");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes) {
|
||||||
|
ConfigBuilderPlugin configBuilderPlugin = MainApp.getConfigBuilder();
|
||||||
|
insulin = configBuilderPlugin.applyBolusConstraints(insulin);
|
||||||
|
// needs to be rounded
|
||||||
|
int durationInHalfHours = Math.max(durationInMinutes / 30, 1);
|
||||||
|
insulin = Round.roundTo(insulin, getPumpDescription().extendedBolusStep);
|
||||||
|
|
||||||
|
PumpEnactResult result = new PumpEnactResult();
|
||||||
|
ExtendedBolus runningEB = MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis());
|
||||||
|
if (runningEB != null && Math.abs(runningEB.insulin - insulin) < getPumpDescription().extendedBolusStep) {
|
||||||
|
result.enacted = false;
|
||||||
|
result.success = true;
|
||||||
|
result.comment = MainApp.instance().getString(R.string.virtualpump_resultok);
|
||||||
|
result.duration = pump.extendedBolusRemainingMinutes;
|
||||||
|
result.absolute = pump.extendedBolusAbsoluteRate;
|
||||||
|
result.isPercent = false;
|
||||||
|
result.isTempCancel = false;
|
||||||
|
if (Config.logPumpActions)
|
||||||
|
log.debug("setExtendedBolus: Correct extended bolus already set. Current: " + pump.extendedBolusAmount + " Asked: " + insulin);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
boolean connectionOK = sExecutionService.extendedBolus(insulin, durationInHalfHours);
|
||||||
|
if (connectionOK && pump.isExtendedInProgress && Math.abs(pump.extendedBolusAmount - insulin) < getPumpDescription().extendedBolusStep) {
|
||||||
|
result.enacted = true;
|
||||||
|
result.success = true;
|
||||||
|
result.comment = MainApp.instance().getString(R.string.virtualpump_resultok);
|
||||||
|
result.isTempCancel = false;
|
||||||
|
result.duration = pump.extendedBolusRemainingMinutes;
|
||||||
|
result.absolute = pump.extendedBolusAbsoluteRate;
|
||||||
|
if (! SP.getBoolean("danar_useextended", false)) result.bolusDelivered = pump.extendedBolusAmount;
|
||||||
|
result.isPercent = false;
|
||||||
|
if (Config.logPumpActions)
|
||||||
|
log.debug("setExtendedBolus: OK");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
result.enacted = false;
|
||||||
|
result.success = false;
|
||||||
|
result.comment = MainApp.instance().getString(R.string.danar_valuenotsetproperly);
|
||||||
|
log.error("setExtendedBolus: Failed to extended bolus");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PumpEnactResult cancelExtendedBolus() {
|
||||||
|
PumpEnactResult result = new PumpEnactResult();
|
||||||
|
ExtendedBolus runningEB = MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis());
|
||||||
|
if (runningEB != null) {
|
||||||
|
sExecutionService.extendedBolusStop();
|
||||||
|
result.enacted = true;
|
||||||
|
result.isTempCancel = true;
|
||||||
|
}
|
||||||
|
if (!pump.isExtendedInProgress) {
|
||||||
|
result.success = true;
|
||||||
|
result.comment = MainApp.instance().getString(R.string.virtualpump_resultok);
|
||||||
|
if (Config.logPumpActions)
|
||||||
|
log.debug("cancelExtendedBolus: OK");
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
result.success = false;
|
||||||
|
result.comment = MainApp.instance().getString(R.string.danar_valuenotsetproperly);
|
||||||
|
log.error("cancelExtendedBolus: Failed to cancel extended bolus");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void connect(String from) {
|
||||||
|
if (sExecutionService != null) {
|
||||||
|
sExecutionService.connect();
|
||||||
|
pumpDescription.basalStep = pump.basalStep;
|
||||||
|
pumpDescription.bolusStep = pump.bolusStep;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isConnected() {
|
||||||
|
return sExecutionService != null && sExecutionService.isConnected();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isConnecting() {
|
||||||
|
return sExecutionService != null && sExecutionService.isConnecting();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void disconnect(String from) {
|
||||||
|
if (sExecutionService != null) sExecutionService.disconnect(from);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stopConnecting() {
|
||||||
|
if (sExecutionService != null) sExecutionService.stopConnecting();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void getPumpStatus() {
|
||||||
|
if (sExecutionService != null) sExecutionService.getPumpStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JSONObject getJSONStatus() {
|
||||||
|
if (pump.lastConnection + 5 * 60 * 1000L < System.currentTimeMillis()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
JSONObject pumpjson = new JSONObject();
|
||||||
|
JSONObject battery = new JSONObject();
|
||||||
|
JSONObject status = new JSONObject();
|
||||||
|
JSONObject extended = new JSONObject();
|
||||||
|
try {
|
||||||
|
battery.put("percent", pump.batteryRemaining);
|
||||||
|
status.put("status", pump.pumpSuspended ? "suspended" : "normal");
|
||||||
|
status.put("timestamp", DateUtil.toISOString(pump.lastConnection));
|
||||||
|
extended.put("Version", BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION);
|
||||||
|
extended.put("PumpIOB", pump.iob);
|
||||||
|
if (pump.lastBolusTime.getTime() != 0) {
|
||||||
|
extended.put("LastBolus", pump.lastBolusTime.toLocaleString());
|
||||||
|
extended.put("LastBolusAmount", pump.lastBolusAmount);
|
||||||
|
}
|
||||||
|
TemporaryBasal tb = MainApp.getConfigBuilder().getRealTempBasalFromHistory(System.currentTimeMillis());
|
||||||
|
if (tb != null) {
|
||||||
|
extended.put("TempBasalAbsoluteRate", tb.tempBasalConvertedToAbsolute(System.currentTimeMillis()));
|
||||||
|
extended.put("TempBasalStart", DateUtil.dateAndTimeString(tb.date));
|
||||||
|
extended.put("TempBasalRemaining", tb.getPlannedRemainingMinutes());
|
||||||
|
}
|
||||||
|
ExtendedBolus eb = MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis());
|
||||||
|
if (eb != null) {
|
||||||
|
extended.put("ExtendedBolusAbsoluteRate", eb.absoluteRate());
|
||||||
|
extended.put("ExtendedBolusStart", DateUtil.dateAndTimeString(eb.date));
|
||||||
|
extended.put("ExtendedBolusRemaining", eb.getPlannedRemainingMinutes());
|
||||||
|
}
|
||||||
|
extended.put("BaseBasalRate", getBaseBasalRate());
|
||||||
|
try {
|
||||||
|
extended.put("ActiveProfile", MainApp.getConfigBuilder().getProfileName());
|
||||||
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
pumpjson.put("battery", battery);
|
||||||
|
pumpjson.put("status", status);
|
||||||
|
pumpjson.put("extended", extended);
|
||||||
|
pumpjson.put("reservoir", (int) pump.reservoirRemainingUnits);
|
||||||
|
pumpjson.put("clock", DateUtil.toISOString(new Date()));
|
||||||
|
} catch (JSONException e) {
|
||||||
|
log.error("Unhandled exception", e);
|
||||||
|
}
|
||||||
|
return pumpjson;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String deviceID() {
|
||||||
|
return pump.serialNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PumpDescription getPumpDescription() {
|
||||||
|
return pumpDescription;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DanaR interface
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PumpEnactResult loadHistory(byte type) {
|
||||||
|
return sExecutionService.loadHistory(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constraint interface
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isLoopEnabled() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isClosedModeEnabled() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAutosensModeEnabled() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAMAModeEnabled() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSMBModeEnabled() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("PointlessBooleanExpression")
|
||||||
|
@Override
|
||||||
|
public Double applyBasalConstraints(Double absoluteRate) {
|
||||||
|
double origAbsoluteRate = absoluteRate;
|
||||||
|
if (pump != null) {
|
||||||
|
if (absoluteRate > pump.maxBasal) {
|
||||||
|
absoluteRate = pump.maxBasal;
|
||||||
|
if (Config.logConstraintsChanges && origAbsoluteRate != Constants.basalAbsoluteOnlyForCheckLimit)
|
||||||
|
log.debug("Limiting rate " + origAbsoluteRate + "U/h by pump constraint to " + absoluteRate + "U/h");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return absoluteRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("PointlessBooleanExpression")
|
||||||
|
@Override
|
||||||
|
public Integer applyBasalConstraints(Integer percentRate) {
|
||||||
|
Integer origPercentRate = percentRate;
|
||||||
|
if (percentRate < 0) percentRate = 0;
|
||||||
|
if (percentRate > getPumpDescription().maxTempPercent)
|
||||||
|
percentRate = getPumpDescription().maxTempPercent;
|
||||||
|
if (!Objects.equals(percentRate, origPercentRate) && Config.logConstraintsChanges && !Objects.equals(origPercentRate, Constants.basalPercentOnlyForCheckLimit))
|
||||||
|
log.debug("Limiting percent rate " + origPercentRate + "% to " + percentRate + "%");
|
||||||
|
return percentRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("PointlessBooleanExpression")
|
||||||
|
@Override
|
||||||
|
public Double applyBolusConstraints(Double insulin) {
|
||||||
|
double origInsulin = insulin;
|
||||||
|
if (pump != null) {
|
||||||
|
if (insulin > pump.maxBolus) {
|
||||||
|
insulin = pump.maxBolus;
|
||||||
|
if (Config.logConstraintsChanges && origInsulin != Constants.bolusOnlyForCheckLimit)
|
||||||
|
log.debug("Limiting bolus " + origInsulin + "U by pump constraint to " + insulin + "U");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return insulin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer applyCarbsConstraints(Integer carbs) {
|
||||||
|
return carbs;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Double applyMaxIOBConstraints(Double maxIob) {
|
||||||
|
return maxIob;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public ProfileStore getProfile() {
|
||||||
|
if (pump.lastSettingsRead == 0)
|
||||||
|
return null; // no info now
|
||||||
|
return pump.createConvertedProfile();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUnits() {
|
||||||
|
return pump.getUnits();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getProfileName() {
|
||||||
|
return pump.createConvertedProfileName();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reply for sms communicator
|
||||||
|
public String shortStatus(boolean veryShort) {
|
||||||
|
String ret = "";
|
||||||
|
if (pump.lastConnection != 0) {
|
||||||
|
Long agoMsec = System.currentTimeMillis() - pump.lastConnection;
|
||||||
|
int agoMin = (int) (agoMsec / 60d / 1000d);
|
||||||
|
ret += "LastConn: " + agoMin + " minago\n";
|
||||||
|
}
|
||||||
|
if (pump.lastBolusTime.getTime() != 0) {
|
||||||
|
ret += "LastBolus: " + DecimalFormatter.to2Decimal(pump.lastBolusAmount) + "U @" + android.text.format.DateFormat.format("HH:mm", pump.lastBolusTime) + "\n";
|
||||||
|
}
|
||||||
|
TemporaryBasal activeTemp = MainApp.getConfigBuilder().getRealTempBasalFromHistory(System.currentTimeMillis());
|
||||||
|
if (activeTemp != null) {
|
||||||
|
ret += "Temp: " + activeTemp.toStringFull() + "\n";
|
||||||
|
}
|
||||||
|
ExtendedBolus activeExtendedBolus = MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis());
|
||||||
|
if (activeExtendedBolus != null) {
|
||||||
|
ret += "Extended: " + activeExtendedBolus.toString() + "\n";
|
||||||
|
}
|
||||||
|
if (!veryShort) {
|
||||||
|
ret += "TDD: " + DecimalFormatter.to0Decimal(pump.dailyTotalUnits) + " / " + pump.maxDailyTotalUnits + " U\n";
|
||||||
|
}
|
||||||
|
ret += "IOB: " + pump.iob + "U\n";
|
||||||
|
ret += "Reserv: " + DecimalFormatter.to0Decimal(pump.reservoirRemainingUnits) + "U\n";
|
||||||
|
ret += "Batt: " + pump.batteryRemaining + "\n";
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
// TODO: daily total constraint
|
||||||
|
|
||||||
|
}
|
|
@ -6,6 +6,7 @@ import android.preference.ListPreference;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.Vector;
|
||||||
|
|
||||||
public class BluetoothDevicePreference extends ListPreference {
|
public class BluetoothDevicePreference extends ListPreference {
|
||||||
|
|
||||||
|
@ -13,21 +14,18 @@ public class BluetoothDevicePreference extends ListPreference {
|
||||||
super(context, attrs);
|
super(context, attrs);
|
||||||
|
|
||||||
BluetoothAdapter bta = BluetoothAdapter.getDefaultAdapter();
|
BluetoothAdapter bta = BluetoothAdapter.getDefaultAdapter();
|
||||||
Integer size = 0;
|
Vector<CharSequence> entries = new Vector<CharSequence>();
|
||||||
if (bta != null) {
|
|
||||||
size += bta.getBondedDevices().size();
|
|
||||||
}
|
|
||||||
CharSequence[] entries = new CharSequence[size];
|
|
||||||
int i = 0;
|
|
||||||
if (bta != null) {
|
if (bta != null) {
|
||||||
Set<BluetoothDevice> pairedDevices = bta.getBondedDevices();
|
Set<BluetoothDevice> pairedDevices = bta.getBondedDevices();
|
||||||
for (BluetoothDevice dev : pairedDevices) {
|
for (BluetoothDevice dev : pairedDevices) {
|
||||||
entries[i] = dev.getName();
|
String name = dev.getName();
|
||||||
i++;
|
if(name != null) {
|
||||||
|
entries.add(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setEntries(entries);
|
}
|
||||||
setEntryValues(entries);
|
setEntries(entries.toArray(new CharSequence[0]));
|
||||||
|
setEntryValues(entries.toArray(new CharSequence[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
public BluetoothDevicePreference(Context context) {
|
public BluetoothDevicePreference(Context context) {
|
||||||
|
|
|
@ -21,8 +21,15 @@ import com.squareup.otto.Subscribe;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import butterknife.BindView;
|
||||||
|
import butterknife.ButterKnife;
|
||||||
|
import butterknife.OnClick;
|
||||||
|
import butterknife.Unbinder;
|
||||||
import info.nightscout.androidaps.MainApp;
|
import info.nightscout.androidaps.MainApp;
|
||||||
import info.nightscout.androidaps.R;
|
import info.nightscout.androidaps.R;
|
||||||
|
import info.nightscout.androidaps.db.ExtendedBolus;
|
||||||
import info.nightscout.androidaps.events.EventExtendedBolusChange;
|
import info.nightscout.androidaps.events.EventExtendedBolusChange;
|
||||||
import info.nightscout.androidaps.events.EventPumpStatusChanged;
|
import info.nightscout.androidaps.events.EventPumpStatusChanged;
|
||||||
import info.nightscout.androidaps.events.EventTempBasalChange;
|
import info.nightscout.androidaps.events.EventTempBasalChange;
|
||||||
|
@ -49,27 +56,24 @@ public class DanaRFragment extends SubscriberFragment {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
TextView lastConnectionView;
|
@BindView(R.id.danar_lastconnection) TextView lastConnectionView;
|
||||||
TextView btConnectionView;
|
@BindView(R.id.danar_btconnection) TextView btConnectionView;
|
||||||
TextView lastBolusView;
|
@BindView(R.id.danar_lastbolus) TextView lastBolusView;
|
||||||
TextView dailyUnitsView;
|
@BindView(R.id.danar_dailyunits) TextView dailyUnitsView;
|
||||||
TextView basaBasalRateView;
|
@BindView(R.id.danar_basabasalrate) TextView basaBasalRateView;
|
||||||
TextView tempBasalView;
|
@BindView(R.id.danar_tempbasal) TextView tempBasalView;
|
||||||
TextView extendedBolusView;
|
@BindView(R.id.danar_extendedbolus) TextView extendedBolusView;
|
||||||
TextView batteryView;
|
@BindView(R.id.danar_battery) TextView batteryView;
|
||||||
TextView reservoirView;
|
@BindView(R.id.danar_reservoir) TextView reservoirView;
|
||||||
TextView iobView;
|
@BindView(R.id.danar_iob) TextView iobView;
|
||||||
TextView firmwareView;
|
@BindView(R.id.danar_firmware) TextView firmwareView;
|
||||||
TextView basalStepView;
|
@BindView(R.id.danar_basalstep) TextView basalStepView;
|
||||||
TextView bolusStepView;
|
@BindView(R.id.danar_bolusstep) TextView bolusStepView;
|
||||||
TextView serialNumberView;
|
@BindView(R.id.danar_serialnumber) TextView serialNumberView;
|
||||||
TextView queueView;
|
@BindView(R.id.danar_queue) TextView queueView;
|
||||||
Button viewProfileButton;
|
|
||||||
Button historyButton;
|
|
||||||
Button statsButton;
|
|
||||||
|
|
||||||
LinearLayout pumpStatusLayout;
|
@BindView(R.id.overview_pumpstatuslayout) LinearLayout pumpStatusLayout;
|
||||||
TextView pumpStatusView;
|
@BindView(R.id.overview_pumpstatus) TextView pumpStatusView;
|
||||||
|
|
||||||
public DanaRFragment() {
|
public DanaRFragment() {
|
||||||
}
|
}
|
||||||
|
@ -91,61 +95,10 @@ public class DanaRFragment extends SubscriberFragment {
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
try {
|
try {
|
||||||
View view = inflater.inflate(R.layout.danar_fragment, container, false);
|
View view = inflater.inflate(R.layout.danar_fragment, container, false);
|
||||||
btConnectionView = (TextView) view.findViewById(R.id.danar_btconnection);
|
unbinder = ButterKnife.bind(this, view);
|
||||||
lastConnectionView = (TextView) view.findViewById(R.id.danar_lastconnection);
|
|
||||||
lastBolusView = (TextView) view.findViewById(R.id.danar_lastbolus);
|
|
||||||
dailyUnitsView = (TextView) view.findViewById(R.id.danar_dailyunits);
|
|
||||||
basaBasalRateView = (TextView) view.findViewById(R.id.danar_basabasalrate);
|
|
||||||
tempBasalView = (TextView) view.findViewById(R.id.danar_tempbasal);
|
|
||||||
extendedBolusView = (TextView) view.findViewById(R.id.danar_extendedbolus);
|
|
||||||
batteryView = (TextView) view.findViewById(R.id.danar_battery);
|
|
||||||
reservoirView = (TextView) view.findViewById(R.id.danar_reservoir);
|
|
||||||
iobView = (TextView) view.findViewById(R.id.danar_iob);
|
|
||||||
firmwareView = (TextView) view.findViewById(R.id.danar_firmware);
|
|
||||||
viewProfileButton = (Button) view.findViewById(R.id.danar_viewprofile);
|
|
||||||
historyButton = (Button) view.findViewById(R.id.danar_history);
|
|
||||||
statsButton = (Button) view.findViewById(R.id.danar_stats);
|
|
||||||
basalStepView = (TextView) view.findViewById(R.id.danar_basalstep);
|
|
||||||
bolusStepView = (TextView) view.findViewById(R.id.danar_bolusstep);
|
|
||||||
serialNumberView = (TextView) view.findViewById(R.id.danar_serialnumber);
|
|
||||||
queueView = (TextView) view.findViewById(R.id.danar_queue);
|
|
||||||
|
|
||||||
pumpStatusView = (TextView) view.findViewById(R.id.overview_pumpstatus);
|
|
||||||
pumpStatusView.setBackgroundColor(MainApp.sResources.getColor(R.color.colorInitializingBorder));
|
pumpStatusView.setBackgroundColor(MainApp.sResources.getColor(R.color.colorInitializingBorder));
|
||||||
pumpStatusLayout = (LinearLayout) view.findViewById(R.id.overview_pumpstatuslayout);
|
|
||||||
|
|
||||||
viewProfileButton.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
FragmentManager manager = getFragmentManager();
|
|
||||||
ProfileViewDialog profileViewDialog = new ProfileViewDialog();
|
|
||||||
profileViewDialog.show(manager, "ProfileViewDialog");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
historyButton.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
startActivity(new Intent(getContext(), DanaRHistoryActivity.class));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
statsButton.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
startActivity(new Intent(getContext(), DanaRStatsActivity.class));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
btConnectionView.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
log.debug("Clicked connect to pump");
|
|
||||||
ConfigBuilderPlugin.getCommandQueue().readStatus("Clicked connect to pump", null);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
updateGUI();
|
|
||||||
return view;
|
return view;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Crashlytics.logException(e);
|
Crashlytics.logException(e);
|
||||||
|
@ -154,6 +107,26 @@ public class DanaRFragment extends SubscriberFragment {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OnClick(R.id.danar_history) void onHistoryClick() {
|
||||||
|
startActivity(new Intent(getContext(), DanaRHistoryActivity.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnClick(R.id.danar_viewprofile) void onViewProfileClick() {
|
||||||
|
FragmentManager manager = getFragmentManager();
|
||||||
|
ProfileViewDialog profileViewDialog = new ProfileViewDialog();
|
||||||
|
profileViewDialog.show(manager, "ProfileViewDialog");
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnClick(R.id.danar_stats) void onStatsClick() {
|
||||||
|
startActivity(new Intent(getContext(), DanaRStatsActivity.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnClick(R.id.danar_btconnection) void onBtConnectionClick() {
|
||||||
|
log.debug("Clicked connect to pump");
|
||||||
|
DanaRPump.getInstance().lastConnection = 0;
|
||||||
|
ConfigBuilderPlugin.getCommandQueue().readStatus("Clicked connect to pump", null);
|
||||||
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void onStatusEvent(final EventPumpStatusChanged c) {
|
public void onStatusEvent(final EventPumpStatusChanged c) {
|
||||||
Activity activity = getActivity();
|
Activity activity = getActivity();
|
||||||
|
@ -212,8 +185,8 @@ public class DanaRFragment extends SubscriberFragment {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
DanaRPump pump = DanaRPump.getInstance();
|
DanaRPump pump = DanaRPump.getInstance();
|
||||||
if (pump.lastConnection.getTime() != 0) {
|
if (pump.lastConnection != 0) {
|
||||||
Long agoMsec = System.currentTimeMillis() - pump.lastConnection.getTime();
|
Long agoMsec = System.currentTimeMillis() - pump.lastConnection;
|
||||||
int agoMin = (int) (agoMsec / 60d / 1000d);
|
int agoMin = (int) (agoMsec / 60d / 1000d);
|
||||||
lastConnectionView.setText(DateUtil.timeString(pump.lastConnection) + " (" + String.format(MainApp.sResources.getString(R.string.minago), agoMin) + ")");
|
lastConnectionView.setText(DateUtil.timeString(pump.lastConnection) + " (" + String.format(MainApp.sResources.getString(R.string.minago), agoMin) + ")");
|
||||||
SetWarnColor.setColor(lastConnectionView, agoMin, 16d, 31d);
|
SetWarnColor.setColor(lastConnectionView, agoMin, 16d, 31d);
|
||||||
|
@ -244,8 +217,9 @@ public class DanaRFragment extends SubscriberFragment {
|
||||||
tempBasalView.setText("");
|
tempBasalView.setText("");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) {
|
ExtendedBolus activeExtendedBolus = MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis());
|
||||||
extendedBolusView.setText(MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis()).toString());
|
if (activeExtendedBolus != null) {
|
||||||
|
extendedBolusView.setText(activeExtendedBolus.toString());
|
||||||
} else {
|
} else {
|
||||||
extendedBolusView.setText("");
|
extendedBolusView.setText("");
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,69 +5,30 @@ import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.ServiceConnection;
|
import android.content.ServiceConnection;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
|
|
||||||
import com.squareup.otto.Subscribe;
|
import com.squareup.otto.Subscribe;
|
||||||
|
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.BuildConfig;
|
|
||||||
import info.nightscout.androidaps.Config;
|
import info.nightscout.androidaps.Config;
|
||||||
import info.nightscout.androidaps.Constants;
|
|
||||||
import info.nightscout.androidaps.MainApp;
|
import info.nightscout.androidaps.MainApp;
|
||||||
import info.nightscout.androidaps.R;
|
import info.nightscout.androidaps.R;
|
||||||
import info.nightscout.androidaps.data.DetailedBolusInfo;
|
import info.nightscout.androidaps.data.DetailedBolusInfo;
|
||||||
import info.nightscout.androidaps.data.PumpEnactResult;
|
import info.nightscout.androidaps.data.PumpEnactResult;
|
||||||
import info.nightscout.androidaps.db.ExtendedBolus;
|
|
||||||
import info.nightscout.androidaps.db.TemporaryBasal;
|
import info.nightscout.androidaps.db.TemporaryBasal;
|
||||||
import info.nightscout.androidaps.db.Treatment;
|
import info.nightscout.androidaps.db.Treatment;
|
||||||
import info.nightscout.androidaps.events.EventAppExit;
|
import info.nightscout.androidaps.events.EventAppExit;
|
||||||
import info.nightscout.androidaps.events.EventPreferenceChange;
|
import info.nightscout.androidaps.events.EventPreferenceChange;
|
||||||
import info.nightscout.androidaps.interfaces.ConstraintsInterface;
|
|
||||||
import info.nightscout.androidaps.interfaces.DanaRInterface;
|
|
||||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
|
||||||
import info.nightscout.androidaps.interfaces.ProfileInterface;
|
|
||||||
import info.nightscout.androidaps.interfaces.PumpDescription;
|
import info.nightscout.androidaps.interfaces.PumpDescription;
|
||||||
import info.nightscout.androidaps.interfaces.PumpInterface;
|
|
||||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||||
import info.nightscout.androidaps.data.Profile;
|
|
||||||
import info.nightscout.androidaps.data.ProfileStore;
|
|
||||||
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
|
|
||||||
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
|
|
||||||
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
|
|
||||||
import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin;
|
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.services.DanaRExecutionService;
|
import info.nightscout.androidaps.plugins.PumpDanaR.services.DanaRExecutionService;
|
||||||
import info.nightscout.utils.DateUtil;
|
|
||||||
import info.nightscout.utils.DecimalFormatter;
|
|
||||||
import info.nightscout.utils.Round;
|
import info.nightscout.utils.Round;
|
||||||
import info.nightscout.utils.SP;
|
import info.nightscout.utils.SP;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by mike on 05.08.2016.
|
* Created by mike on 05.08.2016.
|
||||||
*/
|
*/
|
||||||
public class DanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, ConstraintsInterface, ProfileInterface {
|
public class DanaRPlugin extends AbstractDanaRPlugin {
|
||||||
private static Logger log = LoggerFactory.getLogger(DanaRPlugin.class);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getFragmentClass() {
|
|
||||||
return DanaRFragment.class.getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean fragmentPumpEnabled = false;
|
|
||||||
private static boolean fragmentProfileEnabled = false;
|
|
||||||
private static boolean fragmentPumpVisible = true;
|
|
||||||
|
|
||||||
private static DanaRExecutionService sExecutionService;
|
|
||||||
|
|
||||||
|
|
||||||
private static DanaRPump pump = DanaRPump.getInstance();
|
|
||||||
private static boolean useExtendedBoluses = false;
|
|
||||||
|
|
||||||
private static DanaRPlugin plugin = null;
|
private static DanaRPlugin plugin = null;
|
||||||
|
|
||||||
|
@ -77,9 +38,8 @@ public class DanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, C
|
||||||
return plugin;
|
return plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PumpDescription pumpDescription = new PumpDescription();
|
|
||||||
|
|
||||||
public DanaRPlugin() {
|
public DanaRPlugin() {
|
||||||
|
log = LoggerFactory.getLogger(DanaRPlugin.class);
|
||||||
useExtendedBoluses = SP.getBoolean("danar_useextended", false);
|
useExtendedBoluses = SP.getBoolean("danar_useextended", false);
|
||||||
|
|
||||||
Context context = MainApp.instance().getApplicationContext();
|
Context context = MainApp.instance().getApplicationContext();
|
||||||
|
@ -110,6 +70,8 @@ public class DanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, C
|
||||||
pumpDescription.basalMinimumRate = 0.04d;
|
pumpDescription.basalMinimumRate = 0.04d;
|
||||||
|
|
||||||
pumpDescription.isRefillingCapable = true;
|
pumpDescription.isRefillingCapable = true;
|
||||||
|
|
||||||
|
pumpDescription.storesCarbInfo = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ServiceConnection mConnection = new ServiceConnection() {
|
private ServiceConnection mConnection = new ServiceConnection() {
|
||||||
|
@ -145,83 +107,17 @@ public class DanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, C
|
||||||
}
|
}
|
||||||
|
|
||||||
// Plugin base interface
|
// Plugin base interface
|
||||||
@Override
|
|
||||||
public int getType() {
|
|
||||||
return PluginBase.PUMP;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return MainApp.instance().getString(R.string.danarpump);
|
return MainApp.instance().getString(R.string.danarpump);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getNameShort() {
|
|
||||||
String name = MainApp.sResources.getString(R.string.danarpump_shortname);
|
|
||||||
if (!name.trim().isEmpty()) {
|
|
||||||
//only if translation exists
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
// use long name as fallback
|
|
||||||
return getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isEnabled(int type) {
|
|
||||||
if (type == PluginBase.PROFILE) return fragmentProfileEnabled && fragmentPumpEnabled;
|
|
||||||
else if (type == PluginBase.PUMP) return fragmentPumpEnabled;
|
|
||||||
else if (type == PluginBase.CONSTRAINTS) return fragmentPumpEnabled;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isVisibleInTabs(int type) {
|
|
||||||
if (type == PluginBase.PROFILE || type == PluginBase.CONSTRAINTS) return false;
|
|
||||||
else if (type == PluginBase.PUMP) return fragmentPumpVisible;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean canBeHidden(int type) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasFragment() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean showInList(int type) {
|
|
||||||
return type == PUMP;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
|
|
||||||
if (type == PluginBase.PROFILE)
|
|
||||||
fragmentProfileEnabled = fragmentEnabled;
|
|
||||||
else if (type == PluginBase.PUMP)
|
|
||||||
fragmentPumpEnabled = fragmentEnabled;
|
|
||||||
// if pump profile was enabled need to switch to another too
|
|
||||||
if (type == PluginBase.PUMP && !fragmentEnabled && fragmentProfileEnabled) {
|
|
||||||
setFragmentEnabled(PluginBase.PROFILE, false);
|
|
||||||
setFragmentVisible(PluginBase.PROFILE, false);
|
|
||||||
NSProfilePlugin.getPlugin().setFragmentEnabled(PluginBase.PROFILE, true);
|
|
||||||
NSProfilePlugin.getPlugin().setFragmentVisible(PluginBase.PROFILE, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setFragmentVisible(int type, boolean fragmentVisible) {
|
|
||||||
if (type == PluginBase.PUMP)
|
|
||||||
fragmentPumpVisible = fragmentVisible;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getPreferencesId() {
|
public int getPreferencesId() {
|
||||||
return R.xml.pref_danar;
|
return R.xml.pref_danar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Pump interface
|
||||||
@Override
|
@Override
|
||||||
public boolean isFakingTempsByExtendedBoluses() {
|
public boolean isFakingTempsByExtendedBoluses() {
|
||||||
return useExtendedBoluses;
|
return useExtendedBoluses;
|
||||||
|
@ -229,82 +125,7 @@ public class DanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, C
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isInitialized() {
|
public boolean isInitialized() {
|
||||||
return pump.lastConnection.getTime() > 0 && pump.isExtendedBolusEnabled && pump.maxBasal > 0;
|
return pump.lastConnection > 0 && pump.isExtendedBolusEnabled && pump.maxBasal > 0;
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSuspended() {
|
|
||||||
return pump.pumpSuspended;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isBusy() {
|
|
||||||
if (sExecutionService == null) return false;
|
|
||||||
return sExecutionService.isConnected() || sExecutionService.isConnecting();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pump interface
|
|
||||||
@Override
|
|
||||||
public PumpEnactResult setNewBasalProfile(Profile profile) {
|
|
||||||
PumpEnactResult result = new PumpEnactResult();
|
|
||||||
|
|
||||||
if (sExecutionService == null) {
|
|
||||||
log.error("setNewBasalProfile sExecutionService is null");
|
|
||||||
result.comment = "setNewBasalProfile sExecutionService is null";
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
if (!isInitialized()) {
|
|
||||||
log.error("setNewBasalProfile not initialized");
|
|
||||||
Notification notification = new Notification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED, MainApp.sResources.getString(R.string.pumpNotInitializedProfileNotSet), Notification.URGENT);
|
|
||||||
MainApp.bus().post(new EventNewNotification(notification));
|
|
||||||
result.comment = MainApp.sResources.getString(R.string.pumpNotInitializedProfileNotSet);
|
|
||||||
return result;
|
|
||||||
} else {
|
|
||||||
MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED));
|
|
||||||
}
|
|
||||||
if (!sExecutionService.updateBasalsInPump(profile)) {
|
|
||||||
Notification notification = new Notification(Notification.FAILED_UDPATE_PROFILE, MainApp.sResources.getString(R.string.failedupdatebasalprofile), Notification.URGENT);
|
|
||||||
MainApp.bus().post(new EventNewNotification(notification));
|
|
||||||
result.comment = MainApp.sResources.getString(R.string.failedupdatebasalprofile);
|
|
||||||
return result;
|
|
||||||
} else {
|
|
||||||
MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED));
|
|
||||||
MainApp.bus().post(new EventDismissNotification(Notification.FAILED_UDPATE_PROFILE));
|
|
||||||
result.success = true;
|
|
||||||
result.enacted = true;
|
|
||||||
result.comment = "OK";
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isThisProfileSet(Profile profile) {
|
|
||||||
if (!isInitialized())
|
|
||||||
return true; // TODO: not sure what's better. so far TRUE to prevent too many SMS
|
|
||||||
if (pump.pumpProfiles == null)
|
|
||||||
return true; // TODO: not sure what's better. so far TRUE to prevent too many SMS
|
|
||||||
int basalValues = pump.basal48Enable ? 48 : 24;
|
|
||||||
int basalIncrement = pump.basal48Enable ? 30 * 60 : 60 * 60;
|
|
||||||
for (int h = 0; h < basalValues; h++) {
|
|
||||||
Double pumpValue = pump.pumpProfiles[pump.activeProfile][h];
|
|
||||||
Double profileValue = profile.getBasal((Integer) (h * basalIncrement));
|
|
||||||
if (profileValue == null) return true;
|
|
||||||
if (Math.abs(pumpValue - profileValue) > getPumpDescription().basalStep) {
|
|
||||||
log.debug("Diff found. Hour: " + h + " Pump: " + pumpValue + " Profile: " + profileValue);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Date lastDataTime() {
|
|
||||||
return pump.lastConnection;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public double getBaseBasalRate() {
|
|
||||||
return pump.currentBasal;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -313,8 +134,9 @@ public class DanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, C
|
||||||
detailedBolusInfo.insulin = configBuilderPlugin.applyBolusConstraints(detailedBolusInfo.insulin);
|
detailedBolusInfo.insulin = configBuilderPlugin.applyBolusConstraints(detailedBolusInfo.insulin);
|
||||||
if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) {
|
if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) {
|
||||||
Treatment t = new Treatment();
|
Treatment t = new Treatment();
|
||||||
|
t.isSMB = detailedBolusInfo.isSMB;
|
||||||
boolean connectionOK = false;
|
boolean connectionOK = false;
|
||||||
if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) connectionOK = sExecutionService.bolus(detailedBolusInfo.insulin, (int) detailedBolusInfo.carbs, t);
|
if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) connectionOK = sExecutionService.bolus(detailedBolusInfo.insulin, (int) detailedBolusInfo.carbs, detailedBolusInfo.carbTime, t);
|
||||||
PumpEnactResult result = new PumpEnactResult();
|
PumpEnactResult result = new PumpEnactResult();
|
||||||
result.success = connectionOK;
|
result.success = connectionOK;
|
||||||
result.bolusDelivered = t.insulin;
|
result.bolusDelivered = t.insulin;
|
||||||
|
@ -337,15 +159,6 @@ public class DanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, C
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void stopBolusDelivering() {
|
|
||||||
if (sExecutionService == null) {
|
|
||||||
log.error("stopBolusDelivering sExecutionService is null");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
sExecutionService.bolusStop();
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is called from APS
|
// This is called from APS
|
||||||
@Override
|
@Override
|
||||||
public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean enforceNew) {
|
public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean enforceNew) {
|
||||||
|
@ -498,107 +311,12 @@ public class DanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, C
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, boolean enforceNew) {
|
|
||||||
PumpEnactResult result = new PumpEnactResult();
|
|
||||||
ConfigBuilderPlugin configBuilderPlugin = MainApp.getConfigBuilder();
|
|
||||||
percent = configBuilderPlugin.applyBasalConstraints(percent);
|
|
||||||
if (percent < 0) {
|
|
||||||
result.isTempCancel = false;
|
|
||||||
result.enacted = false;
|
|
||||||
result.success = false;
|
|
||||||
result.comment = MainApp.instance().getString(R.string.danar_invalidinput);
|
|
||||||
log.error("setTempBasalPercent: Invalid input");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
if (percent > getPumpDescription().maxTempPercent)
|
|
||||||
percent = getPumpDescription().maxTempPercent;
|
|
||||||
TemporaryBasal runningTB = MainApp.getConfigBuilder().getRealTempBasalFromHistory(System.currentTimeMillis());
|
|
||||||
if (runningTB != null && runningTB.percentRate == percent && !enforceNew) {
|
|
||||||
result.enacted = false;
|
|
||||||
result.success = true;
|
|
||||||
result.isTempCancel = false;
|
|
||||||
result.comment = MainApp.instance().getString(R.string.virtualpump_resultok);
|
|
||||||
result.duration = pump.tempBasalRemainingMin;
|
|
||||||
result.percent = pump.tempBasalPercent;
|
|
||||||
result.absolute = MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory();
|
|
||||||
result.isPercent = true;
|
|
||||||
if (Config.logPumpActions)
|
|
||||||
log.debug("setTempBasalPercent: Correct value already set");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
int durationInHours = Math.max(durationInMinutes / 60, 1);
|
|
||||||
boolean connectionOK = sExecutionService.tempBasal(percent, durationInHours);
|
|
||||||
if (connectionOK && pump.isTempBasalInProgress && pump.tempBasalPercent == percent) {
|
|
||||||
result.enacted = true;
|
|
||||||
result.success = true;
|
|
||||||
result.comment = MainApp.instance().getString(R.string.virtualpump_resultok);
|
|
||||||
result.isTempCancel = false;
|
|
||||||
result.duration = pump.tempBasalRemainingMin;
|
|
||||||
result.percent = pump.tempBasalPercent;
|
|
||||||
result.absolute = MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory();
|
|
||||||
result.isPercent = true;
|
|
||||||
if (Config.logPumpActions)
|
|
||||||
log.debug("setTempBasalPercent: OK");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
result.enacted = false;
|
|
||||||
result.success = false;
|
|
||||||
result.comment = MainApp.instance().getString(R.string.tempbasaldeliveryerror);
|
|
||||||
log.error("setTempBasalPercent: Failed to set temp basal");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes) {
|
|
||||||
ConfigBuilderPlugin configBuilderPlugin = MainApp.getConfigBuilder();
|
|
||||||
insulin = configBuilderPlugin.applyBolusConstraints(insulin);
|
|
||||||
// needs to be rounded
|
|
||||||
int durationInHalfHours = Math.max(durationInMinutes / 30, 1);
|
|
||||||
insulin = Round.roundTo(insulin, getPumpDescription().extendedBolusStep);
|
|
||||||
|
|
||||||
PumpEnactResult result = new PumpEnactResult();
|
|
||||||
ExtendedBolus runningEB = MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis());
|
|
||||||
if (runningEB != null && Math.abs(runningEB.insulin - insulin) < getPumpDescription().extendedBolusStep) {
|
|
||||||
result.enacted = false;
|
|
||||||
result.success = true;
|
|
||||||
result.comment = MainApp.instance().getString(R.string.virtualpump_resultok);
|
|
||||||
result.duration = pump.extendedBolusRemainingMinutes;
|
|
||||||
result.absolute = pump.extendedBolusAbsoluteRate;
|
|
||||||
result.isPercent = false;
|
|
||||||
result.isTempCancel = false;
|
|
||||||
if (Config.logPumpActions)
|
|
||||||
log.debug("setExtendedBolus: Correct extended bolus already set. Current: " + pump.extendedBolusAmount + " Asked: " + insulin);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
boolean connectionOK = sExecutionService.extendedBolus(insulin, durationInHalfHours);
|
|
||||||
if (connectionOK && pump.isExtendedInProgress && Math.abs(pump.extendedBolusAmount - insulin) < getPumpDescription().extendedBolusStep) {
|
|
||||||
result.enacted = true;
|
|
||||||
result.success = true;
|
|
||||||
result.comment = MainApp.instance().getString(R.string.virtualpump_resultok);
|
|
||||||
result.isTempCancel = false;
|
|
||||||
result.duration = pump.extendedBolusRemainingMinutes;
|
|
||||||
result.absolute = pump.extendedBolusAbsoluteRate;
|
|
||||||
result.bolusDelivered = pump.extendedBolusAmount;
|
|
||||||
result.isPercent = false;
|
|
||||||
if (Config.logPumpActions)
|
|
||||||
log.debug("setExtendedBolus: OK");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
result.enacted = false;
|
|
||||||
result.success = false;
|
|
||||||
result.comment = MainApp.instance().getString(R.string.danar_valuenotsetproperly);
|
|
||||||
log.error("setExtendedBolus: Failed to extended bolus");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PumpEnactResult cancelTempBasal(boolean force) {
|
public PumpEnactResult cancelTempBasal(boolean force) {
|
||||||
if (MainApp.getConfigBuilder().isInHistoryRealTempBasalInProgress())
|
if (MainApp.getConfigBuilder().isInHistoryRealTempBasalInProgress())
|
||||||
return cancelRealTempBasal();
|
return cancelRealTempBasal();
|
||||||
if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress() && useExtendedBoluses) {
|
if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress() && useExtendedBoluses) {
|
||||||
PumpEnactResult cancelEx = cancelExtendedBolus();
|
return cancelExtendedBolus();
|
||||||
return cancelEx;
|
|
||||||
}
|
}
|
||||||
PumpEnactResult result = new PumpEnactResult();
|
PumpEnactResult result = new PumpEnactResult();
|
||||||
result.success = true;
|
result.success = true;
|
||||||
|
@ -632,257 +350,8 @@ public class DanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, C
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public PumpEnactResult cancelExtendedBolus() {
|
|
||||||
PumpEnactResult result = new PumpEnactResult();
|
|
||||||
ExtendedBolus runningEB = MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis());
|
|
||||||
if (runningEB != null) {
|
|
||||||
sExecutionService.extendedBolusStop();
|
|
||||||
result.enacted = true;
|
|
||||||
result.isTempCancel = true;
|
|
||||||
}
|
|
||||||
if (!pump.isExtendedInProgress) {
|
|
||||||
result.success = true;
|
|
||||||
result.comment = MainApp.instance().getString(R.string.virtualpump_resultok);
|
|
||||||
if (Config.logPumpActions)
|
|
||||||
log.debug("cancelExtendedBolus: OK");
|
|
||||||
return result;
|
|
||||||
} else {
|
|
||||||
result.success = false;
|
|
||||||
result.comment = MainApp.instance().getString(R.string.danar_valuenotsetproperly);
|
|
||||||
log.error("cancelExtendedBolus: Failed to cancel extended bolus");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void connect(String from) {
|
|
||||||
if (sExecutionService != null) {
|
|
||||||
sExecutionService.connect(from);
|
|
||||||
pumpDescription.basalStep = pump.basalStep;
|
|
||||||
pumpDescription.bolusStep = pump.bolusStep;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isConnected() {
|
|
||||||
return sExecutionService != null && sExecutionService.isConnected();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isConnecting() {
|
|
||||||
return sExecutionService != null && sExecutionService.isConnecting();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void disconnect(String from) {
|
|
||||||
if (sExecutionService != null) sExecutionService.disconnect(from);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void stopConnecting() {
|
|
||||||
if (sExecutionService != null) sExecutionService.stopConnecting();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void getPumpStatus() {
|
|
||||||
if (sExecutionService != null) sExecutionService.getPumpStatus();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public JSONObject getJSONStatus() {
|
|
||||||
if (pump.lastConnection.getTime() + 5 * 60 * 1000L < System.currentTimeMillis()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
JSONObject pumpjson = new JSONObject();
|
|
||||||
JSONObject battery = new JSONObject();
|
|
||||||
JSONObject status = new JSONObject();
|
|
||||||
JSONObject extended = new JSONObject();
|
|
||||||
try {
|
|
||||||
battery.put("percent", pump.batteryRemaining);
|
|
||||||
status.put("status", pump.pumpSuspended ? "suspended" : "normal");
|
|
||||||
status.put("timestamp", DateUtil.toISOString(pump.lastConnection));
|
|
||||||
extended.put("Version", BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION);
|
|
||||||
extended.put("PumpIOB", pump.iob);
|
|
||||||
if (pump.lastBolusTime.getTime() != 0) {
|
|
||||||
extended.put("LastBolus", pump.lastBolusTime.toLocaleString());
|
|
||||||
extended.put("LastBolusAmount", pump.lastBolusAmount);
|
|
||||||
}
|
|
||||||
TemporaryBasal tb = MainApp.getConfigBuilder().getRealTempBasalFromHistory(System.currentTimeMillis());
|
|
||||||
if (tb != null) {
|
|
||||||
extended.put("TempBasalAbsoluteRate", tb.tempBasalConvertedToAbsolute(System.currentTimeMillis()));
|
|
||||||
extended.put("TempBasalStart", DateUtil.dateAndTimeString(tb.date));
|
|
||||||
extended.put("TempBasalRemaining", tb.getPlannedRemainingMinutes());
|
|
||||||
}
|
|
||||||
ExtendedBolus eb = MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis());
|
|
||||||
if (eb != null) {
|
|
||||||
extended.put("ExtendedBolusAbsoluteRate", eb.absoluteRate());
|
|
||||||
extended.put("ExtendedBolusStart", DateUtil.dateAndTimeString(eb.date));
|
|
||||||
extended.put("ExtendedBolusRemaining", eb.getPlannedRemainingMinutes());
|
|
||||||
}
|
|
||||||
extended.put("BaseBasalRate", getBaseBasalRate());
|
|
||||||
try {
|
|
||||||
extended.put("ActiveProfile", MainApp.getConfigBuilder().getProfileName());
|
|
||||||
} catch (Exception e) {
|
|
||||||
}
|
|
||||||
|
|
||||||
pumpjson.put("battery", battery);
|
|
||||||
pumpjson.put("status", status);
|
|
||||||
pumpjson.put("extended", extended);
|
|
||||||
pumpjson.put("reservoir", (int) pump.reservoirRemainingUnits);
|
|
||||||
pumpjson.put("clock", DateUtil.toISOString(new Date()));
|
|
||||||
} catch (JSONException e) {
|
|
||||||
log.error("Unhandled exception", e);
|
|
||||||
}
|
|
||||||
return pumpjson;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String deviceID() {
|
|
||||||
return pump.serialNumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PumpDescription getPumpDescription() {
|
|
||||||
return pumpDescription;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DanaR interface
|
|
||||||
*/
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PumpEnactResult loadHistory(byte type) {
|
|
||||||
return sExecutionService.loadHistory(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PumpEnactResult loadEvents() {
|
public PumpEnactResult loadEvents() {
|
||||||
return null; // no history, not needed
|
return null; // no history, not needed
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Constraint interface
|
|
||||||
*/
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isLoopEnabled() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isClosedModeEnabled() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isAutosensModeEnabled() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isAMAModeEnabled() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSMBModeEnabled() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("PointlessBooleanExpression")
|
|
||||||
@Override
|
|
||||||
public Double applyBasalConstraints(Double absoluteRate) {
|
|
||||||
double origAbsoluteRate = absoluteRate;
|
|
||||||
if (pump != null) {
|
|
||||||
if (absoluteRate > pump.maxBasal) {
|
|
||||||
absoluteRate = pump.maxBasal;
|
|
||||||
if (Config.logConstraintsChanges && origAbsoluteRate != Constants.basalAbsoluteOnlyForCheckLimit)
|
|
||||||
log.debug("Limiting rate " + origAbsoluteRate + "U/h by pump constraint to " + absoluteRate + "U/h");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return absoluteRate;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("PointlessBooleanExpression")
|
|
||||||
@Override
|
|
||||||
public Integer applyBasalConstraints(Integer percentRate) {
|
|
||||||
Integer origPercentRate = percentRate;
|
|
||||||
if (percentRate < 0) percentRate = 0;
|
|
||||||
if (percentRate > getPumpDescription().maxTempPercent)
|
|
||||||
percentRate = getPumpDescription().maxTempPercent;
|
|
||||||
if (!Objects.equals(percentRate, origPercentRate) && Config.logConstraintsChanges && !Objects.equals(origPercentRate, Constants.basalPercentOnlyForCheckLimit))
|
|
||||||
log.debug("Limiting percent rate " + origPercentRate + "% to " + percentRate + "%");
|
|
||||||
return percentRate;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("PointlessBooleanExpression")
|
|
||||||
@Override
|
|
||||||
public Double applyBolusConstraints(Double insulin) {
|
|
||||||
double origInsulin = insulin;
|
|
||||||
if (pump != null) {
|
|
||||||
if (insulin > pump.maxBolus) {
|
|
||||||
insulin = pump.maxBolus;
|
|
||||||
if (Config.logConstraintsChanges && origInsulin != Constants.bolusOnlyForCheckLimit)
|
|
||||||
log.debug("Limiting bolus " + origInsulin + "U by pump constraint to " + insulin + "U");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return insulin;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Integer applyCarbsConstraints(Integer carbs) {
|
|
||||||
return carbs;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Double applyMaxIOBConstraints(Double maxIob) {
|
|
||||||
return maxIob;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public ProfileStore getProfile() {
|
|
||||||
if (pump.lastSettingsRead.getTime() == 0)
|
|
||||||
return null; // no info now
|
|
||||||
return pump.createConvertedProfile();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getUnits() {
|
|
||||||
return pump.getUnits();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getProfileName() {
|
|
||||||
return pump.createConvertedProfileName();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reply for sms communicator
|
|
||||||
public String shortStatus(boolean veryShort) {
|
|
||||||
String ret = "";
|
|
||||||
if (pump.lastConnection.getTime() != 0) {
|
|
||||||
Long agoMsec = System.currentTimeMillis() - pump.lastConnection.getTime();
|
|
||||||
int agoMin = (int) (agoMsec / 60d / 1000d);
|
|
||||||
ret += "LastConn: " + agoMin + " minago\n";
|
|
||||||
}
|
|
||||||
if (pump.lastBolusTime.getTime() != 0) {
|
|
||||||
ret += "LastBolus: " + DecimalFormatter.to2Decimal(pump.lastBolusAmount) + "U @" + android.text.format.DateFormat.format("HH:mm", pump.lastBolusTime) + "\n";
|
|
||||||
}
|
|
||||||
if (MainApp.getConfigBuilder().isInHistoryRealTempBasalInProgress()) {
|
|
||||||
ret += "Temp: " + MainApp.getConfigBuilder().getRealTempBasalFromHistory(System.currentTimeMillis()).toStringFull() + "\n";
|
|
||||||
}
|
|
||||||
if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) {
|
|
||||||
ret += "Extended: " + MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis()).toString() + "\n";
|
|
||||||
}
|
|
||||||
if (!veryShort) {
|
|
||||||
ret += "TDD: " + DecimalFormatter.to0Decimal(pump.dailyTotalUnits) + " / " + pump.maxDailyTotalUnits + " U\n";
|
|
||||||
}
|
|
||||||
ret += "IOB: " + pump.iob + "U\n";
|
|
||||||
ret += "Reserv: " + DecimalFormatter.to0Decimal(pump.reservoirRemainingUnits) + "U\n";
|
|
||||||
ret += "Batt: " + pump.batteryRemaining + "\n";
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
// TODO: daily total constraint
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,8 +56,8 @@ public class DanaRPump {
|
||||||
public static final int CARBS = 14;
|
public static final int CARBS = 14;
|
||||||
public static final int PRIMECANNULA = 15;
|
public static final int PRIMECANNULA = 15;
|
||||||
|
|
||||||
public Date lastConnection = new Date(0);
|
public long lastConnection = 0;
|
||||||
public Date lastSettingsRead = new Date(0);
|
public long lastSettingsRead =0;
|
||||||
|
|
||||||
// Info
|
// Info
|
||||||
public String serialNumber = "";
|
public String serialNumber = "";
|
||||||
|
|
|
@ -13,12 +13,13 @@ import java.io.OutputStream;
|
||||||
import info.nightscout.androidaps.Config;
|
import info.nightscout.androidaps.Config;
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase;
|
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase;
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageHashTable;
|
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageHashTable;
|
||||||
|
import info.nightscout.androidaps.plugins.PumpDanaR.services.AbstractSerialIOThread;
|
||||||
import info.nightscout.utils.CRC;
|
import info.nightscout.utils.CRC;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by mike on 17.07.2016.
|
* Created by mike on 17.07.2016.
|
||||||
*/
|
*/
|
||||||
public class SerialIOThread extends Thread {
|
public class SerialIOThread extends AbstractSerialIOThread {
|
||||||
private static Logger log = LoggerFactory.getLogger(SerialIOThread.class);
|
private static Logger log = LoggerFactory.getLogger(SerialIOThread.class);
|
||||||
|
|
||||||
private InputStream mInputStream = null;
|
private InputStream mInputStream = null;
|
||||||
|
@ -28,10 +29,10 @@ public class SerialIOThread extends Thread {
|
||||||
private boolean mKeepRunning = true;
|
private boolean mKeepRunning = true;
|
||||||
private byte[] mReadBuff = new byte[0];
|
private byte[] mReadBuff = new byte[0];
|
||||||
|
|
||||||
MessageBase processedMessage;
|
private MessageBase processedMessage;
|
||||||
|
|
||||||
public SerialIOThread(BluetoothSocket rfcommSocket) {
|
public SerialIOThread(BluetoothSocket rfcommSocket) {
|
||||||
super(SerialIOThread.class.toString());
|
super();
|
||||||
|
|
||||||
mRfCommSocket = rfcommSocket;
|
mRfCommSocket = rfcommSocket;
|
||||||
try {
|
try {
|
||||||
|
@ -137,6 +138,7 @@ public class SerialIOThread extends Thread {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public synchronized void sendMessage(MessageBase message) {
|
public synchronized void sendMessage(MessageBase message) {
|
||||||
if (!mRfCommSocket.isConnected()) {
|
if (!mRfCommSocket.isConnected()) {
|
||||||
log.error("Socket not connected on sendMessage");
|
log.error("Socket not connected on sendMessage");
|
||||||
|
@ -172,6 +174,7 @@ public class SerialIOThread extends Thread {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void disconnect(String reason) {
|
public void disconnect(String reason) {
|
||||||
mKeepRunning = false;
|
mKeepRunning = false;
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -35,8 +35,8 @@ public class MsgInitConnStatusTime extends MessageBase {
|
||||||
MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).setFragmentVisible(PluginBase.PUMP, true);
|
MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).setFragmentVisible(PluginBase.PUMP, true);
|
||||||
MainApp.getSpecificPlugin(DanaRPlugin.class).setFragmentEnabled(PluginBase.PUMP, false);
|
MainApp.getSpecificPlugin(DanaRPlugin.class).setFragmentEnabled(PluginBase.PUMP, false);
|
||||||
MainApp.getSpecificPlugin(DanaRPlugin.class).setFragmentVisible(PluginBase.PUMP, false);
|
MainApp.getSpecificPlugin(DanaRPlugin.class).setFragmentVisible(PluginBase.PUMP, false);
|
||||||
DanaRPump.getInstance().lastConnection = new Date(0); // mark not initialized
|
|
||||||
|
|
||||||
|
DanaRPump.getInstance().lastConnection = 0; // mark not initialized
|
||||||
//If profile coming from pump, switch it as well
|
//If profile coming from pump, switch it as well
|
||||||
if(MainApp.getSpecificPlugin(DanaRPlugin.class).isEnabled(PluginBase.PROFILE)){
|
if(MainApp.getSpecificPlugin(DanaRPlugin.class).isEnabled(PluginBase.PROFILE)){
|
||||||
(MainApp.getSpecificPlugin(DanaRPlugin.class)).setFragmentEnabled(PluginBase.PROFILE, false);
|
(MainApp.getSpecificPlugin(DanaRPlugin.class)).setFragmentEnabled(PluginBase.PROFILE, false);
|
||||||
|
|
|
@ -23,7 +23,7 @@ public class MsgSettingBasal extends MessageBase {
|
||||||
pump.pumpProfiles[pump.activeProfile] = new double[24];
|
pump.pumpProfiles[pump.activeProfile] = new double[24];
|
||||||
for (int index = 0; index < 24; index++) {
|
for (int index = 0; index < 24; index++) {
|
||||||
int basal = intFromBuff(bytes, 2 * index, 2);
|
int basal = intFromBuff(bytes, 2 * index, 2);
|
||||||
if (basal < DanaRPlugin.pumpDescription.basalMinimumRate) basal = 0;
|
if (basal < DanaRPlugin.getPlugin().pumpDescription.basalMinimumRate) basal = 0;
|
||||||
pump.pumpProfiles[pump.activeProfile][index] = basal / 100d;
|
pump.pumpProfiles[pump.activeProfile][index] = basal / 100d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,10 +6,12 @@ import org.slf4j.LoggerFactory;
|
||||||
import info.nightscout.androidaps.Config;
|
import info.nightscout.androidaps.Config;
|
||||||
import info.nightscout.androidaps.MainApp;
|
import info.nightscout.androidaps.MainApp;
|
||||||
import info.nightscout.androidaps.R;
|
import info.nightscout.androidaps.R;
|
||||||
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
|
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||||
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
|
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
|
||||||
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
|
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
|
||||||
|
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump;
|
import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump;
|
||||||
|
import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by mike on 13.12.2016.
|
* Created by mike on 13.12.2016.
|
||||||
|
@ -40,6 +42,11 @@ public class MsgSettingMeal extends MessageBase {
|
||||||
log.debug("Is Config U/d: " + pump.isConfigUD);
|
log.debug("Is Config U/d: " + pump.isConfigUD);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DanaRKorean is not possible to set to 0.01 but it works when controlled from AAPS
|
||||||
|
if (DanaRKoreanPlugin.getPlugin().isEnabled(PluginBase.PUMP)) {
|
||||||
|
pump.basalStep = 0.01d;
|
||||||
|
}
|
||||||
|
|
||||||
if (pump.basalStep != 0.01d) {
|
if (pump.basalStep != 0.01d) {
|
||||||
Notification notification = new Notification(Notification.WRONGBASALSTEP, MainApp.sResources.getString(R.string.danar_setbasalstep001), Notification.URGENT);
|
Notification notification = new Notification(Notification.WRONGBASALSTEP, MainApp.sResources.getString(R.string.danar_setbasalstep001), Notification.URGENT);
|
||||||
MainApp.bus().post(new EventNewNotification(notification));
|
MainApp.bus().post(new EventNewNotification(notification));
|
||||||
|
|
|
@ -69,8 +69,8 @@ public class MsgStatusBolusExtended extends MessageBase {
|
||||||
DanaRPump pump = DanaRPump.getInstance();
|
DanaRPump pump = DanaRPump.getInstance();
|
||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
|
|
||||||
if (treatmentsInterface.isInHistoryExtendedBoluslInProgress()) {
|
|
||||||
ExtendedBolus extendedBolus = treatmentsInterface.getExtendedBolusFromHistory(System.currentTimeMillis());
|
ExtendedBolus extendedBolus = treatmentsInterface.getExtendedBolusFromHistory(System.currentTimeMillis());
|
||||||
|
if (extendedBolus != null) {
|
||||||
if (pump.isExtendedInProgress) {
|
if (pump.isExtendedInProgress) {
|
||||||
if (extendedBolus.absoluteRate() != pump.extendedBolusAbsoluteRate) {
|
if (extendedBolus.absoluteRate() != pump.extendedBolusAbsoluteRate) {
|
||||||
// Close current extended
|
// Close current extended
|
||||||
|
|
|
@ -0,0 +1,225 @@
|
||||||
|
package info.nightscout.androidaps.plugins.PumpDanaR.services;
|
||||||
|
|
||||||
|
import android.app.Service;
|
||||||
|
import android.bluetooth.BluetoothAdapter;
|
||||||
|
import android.bluetooth.BluetoothDevice;
|
||||||
|
import android.bluetooth.BluetoothSocket;
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.IBinder;
|
||||||
|
import android.os.SystemClock;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.Config;
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
import info.nightscout.androidaps.R;
|
||||||
|
import info.nightscout.androidaps.data.Profile;
|
||||||
|
import info.nightscout.androidaps.data.PumpEnactResult;
|
||||||
|
import info.nightscout.androidaps.db.Treatment;
|
||||||
|
import info.nightscout.androidaps.events.EventPumpStatusChanged;
|
||||||
|
import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump;
|
||||||
|
import info.nightscout.androidaps.plugins.PumpDanaR.SerialIOThread;
|
||||||
|
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase;
|
||||||
|
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusStop;
|
||||||
|
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryAlarm;
|
||||||
|
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryBasalHour;
|
||||||
|
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryBolus;
|
||||||
|
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryCarbo;
|
||||||
|
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryDailyInsulin;
|
||||||
|
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryDone;
|
||||||
|
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryError;
|
||||||
|
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryGlucose;
|
||||||
|
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryRefill;
|
||||||
|
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistorySuspend;
|
||||||
|
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgPCCommStart;
|
||||||
|
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgPCCommStop;
|
||||||
|
import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes;
|
||||||
|
import info.nightscout.utils.SP;
|
||||||
|
import info.nightscout.utils.ToastUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 28.01.2018.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public abstract class AbstractDanaRExecutionService extends Service {
|
||||||
|
protected Logger log;
|
||||||
|
|
||||||
|
protected String mDevName;
|
||||||
|
|
||||||
|
protected BluetoothSocket mRfcommSocket;
|
||||||
|
protected BluetoothDevice mBTDevice;
|
||||||
|
|
||||||
|
protected DanaRPump mDanaRPump = DanaRPump.getInstance();
|
||||||
|
protected Treatment mBolusingTreatment = null;
|
||||||
|
|
||||||
|
protected Boolean mConnectionInProgress = false;
|
||||||
|
|
||||||
|
protected AbstractSerialIOThread mSerialIOThread;
|
||||||
|
|
||||||
|
protected IBinder mBinder;
|
||||||
|
|
||||||
|
protected final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");
|
||||||
|
|
||||||
|
public abstract boolean updateBasalsInPump(final Profile profile);
|
||||||
|
|
||||||
|
public abstract void connect();
|
||||||
|
|
||||||
|
public abstract void getPumpStatus();
|
||||||
|
|
||||||
|
public abstract PumpEnactResult loadEvents();
|
||||||
|
|
||||||
|
public abstract boolean bolus(double amount, int carbs, long carbtime, final Treatment t);
|
||||||
|
|
||||||
|
public abstract boolean highTempBasal(int percent); // Rv2 only
|
||||||
|
|
||||||
|
public abstract boolean tempBasal(int percent, int durationInHours);
|
||||||
|
|
||||||
|
public abstract boolean tempBasalStop();
|
||||||
|
|
||||||
|
public abstract boolean extendedBolus(double insulin, int durationInHalfHours);
|
||||||
|
|
||||||
|
public abstract boolean extendedBolusStop();
|
||||||
|
|
||||||
|
|
||||||
|
protected BroadcastReceiver receiver = new BroadcastReceiver() {
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
|
||||||
|
String action = intent.getAction();
|
||||||
|
if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) {
|
||||||
|
log.debug("Device was disconnected " + device.getName());//Device was disconnected
|
||||||
|
if (mBTDevice != null && mBTDevice.getName() != null && mBTDevice.getName().equals(device.getName())) {
|
||||||
|
if (mSerialIOThread != null) {
|
||||||
|
mSerialIOThread.disconnect("BT disconnection broadcast");
|
||||||
|
}
|
||||||
|
MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTED));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBinder onBind(Intent intent) {
|
||||||
|
return mBinder;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||||
|
return START_STICKY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isConnected() {
|
||||||
|
return mRfcommSocket != null && mRfcommSocket.isConnected();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isConnecting() {
|
||||||
|
return mConnectionInProgress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void disconnect(String from) {
|
||||||
|
if (mSerialIOThread != null)
|
||||||
|
mSerialIOThread.disconnect(from);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stopConnecting() {
|
||||||
|
if (mSerialIOThread != null)
|
||||||
|
mSerialIOThread.disconnect("stopConnecting");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void getBTSocketForSelectedPump() {
|
||||||
|
mDevName = SP.getString(MainApp.sResources.getString(R.string.key_danar_bt_name), "");
|
||||||
|
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
|
||||||
|
|
||||||
|
if (bluetoothAdapter != null) {
|
||||||
|
Set<BluetoothDevice> bondedDevices = bluetoothAdapter.getBondedDevices();
|
||||||
|
|
||||||
|
for (BluetoothDevice device : bondedDevices) {
|
||||||
|
if (mDevName.equals(device.getName())) {
|
||||||
|
mBTDevice = device;
|
||||||
|
try {
|
||||||
|
mRfcommSocket = mBTDevice.createRfcommSocketToServiceRecord(SPP_UUID);
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("Error creating socket: ", e);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.nobtadapter));
|
||||||
|
}
|
||||||
|
if (mBTDevice == null) {
|
||||||
|
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.devicenotfound));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void bolusStop() {
|
||||||
|
if (Config.logDanaBTComm)
|
||||||
|
log.debug("bolusStop >>>>> @ " + (mBolusingTreatment == null ? "" : mBolusingTreatment.insulin));
|
||||||
|
MsgBolusStop stop = new MsgBolusStop();
|
||||||
|
stop.forced = true;
|
||||||
|
if (isConnected()) {
|
||||||
|
mSerialIOThread.sendMessage(stop);
|
||||||
|
while (!stop.stopped) {
|
||||||
|
mSerialIOThread.sendMessage(stop);
|
||||||
|
SystemClock.sleep(200);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
stop.stopped = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public PumpEnactResult loadHistory(byte type) {
|
||||||
|
PumpEnactResult result = new PumpEnactResult();
|
||||||
|
if (!isConnected()) return result;
|
||||||
|
MessageBase msg = null;
|
||||||
|
switch (type) {
|
||||||
|
case RecordTypes.RECORD_TYPE_ALARM:
|
||||||
|
msg = new MsgHistoryAlarm();
|
||||||
|
break;
|
||||||
|
case RecordTypes.RECORD_TYPE_BASALHOUR:
|
||||||
|
msg = new MsgHistoryBasalHour();
|
||||||
|
break;
|
||||||
|
case RecordTypes.RECORD_TYPE_BOLUS:
|
||||||
|
msg = new MsgHistoryBolus();
|
||||||
|
break;
|
||||||
|
case RecordTypes.RECORD_TYPE_CARBO:
|
||||||
|
msg = new MsgHistoryCarbo();
|
||||||
|
break;
|
||||||
|
case RecordTypes.RECORD_TYPE_DAILY:
|
||||||
|
msg = new MsgHistoryDailyInsulin();
|
||||||
|
break;
|
||||||
|
case RecordTypes.RECORD_TYPE_ERROR:
|
||||||
|
msg = new MsgHistoryError();
|
||||||
|
break;
|
||||||
|
case RecordTypes.RECORD_TYPE_GLUCOSE:
|
||||||
|
msg = new MsgHistoryGlucose();
|
||||||
|
break;
|
||||||
|
case RecordTypes.RECORD_TYPE_REFILL:
|
||||||
|
msg = new MsgHistoryRefill();
|
||||||
|
break;
|
||||||
|
case RecordTypes.RECORD_TYPE_SUSPEND:
|
||||||
|
msg = new MsgHistorySuspend();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
MsgHistoryDone done = new MsgHistoryDone();
|
||||||
|
mSerialIOThread.sendMessage(new MsgPCCommStart());
|
||||||
|
SystemClock.sleep(400);
|
||||||
|
mSerialIOThread.sendMessage(msg);
|
||||||
|
while (!done.received && mRfcommSocket.isConnected()) {
|
||||||
|
SystemClock.sleep(100);
|
||||||
|
}
|
||||||
|
SystemClock.sleep(200);
|
||||||
|
mSerialIOThread.sendMessage(new MsgPCCommStop());
|
||||||
|
result.success = true;
|
||||||
|
result.comment = "OK";
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
package info.nightscout.androidaps.plugins.PumpDanaR.services;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 28.01.2018.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public abstract class AbstractSerialIOThread extends Thread {
|
||||||
|
|
||||||
|
public abstract void sendMessage(MessageBase message);
|
||||||
|
public abstract void disconnect(String reason);
|
||||||
|
}
|
|
@ -1,41 +1,33 @@
|
||||||
package info.nightscout.androidaps.plugins.PumpDanaR.services;
|
package info.nightscout.androidaps.plugins.PumpDanaR.services;
|
||||||
|
|
||||||
import android.app.Service;
|
|
||||||
import android.bluetooth.BluetoothAdapter;
|
|
||||||
import android.bluetooth.BluetoothDevice;
|
import android.bluetooth.BluetoothDevice;
|
||||||
import android.bluetooth.BluetoothSocket;
|
|
||||||
import android.content.BroadcastReceiver;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.IBinder;
|
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
|
|
||||||
import com.squareup.otto.Subscribe;
|
import com.squareup.otto.Subscribe;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.Config;
|
import info.nightscout.androidaps.Config;
|
||||||
import info.nightscout.androidaps.Constants;
|
import info.nightscout.androidaps.Constants;
|
||||||
import info.nightscout.androidaps.MainApp;
|
import info.nightscout.androidaps.MainApp;
|
||||||
import info.nightscout.androidaps.R;
|
import info.nightscout.androidaps.R;
|
||||||
|
import info.nightscout.androidaps.data.Profile;
|
||||||
import info.nightscout.androidaps.data.PumpEnactResult;
|
import info.nightscout.androidaps.data.PumpEnactResult;
|
||||||
import info.nightscout.androidaps.db.Treatment;
|
import info.nightscout.androidaps.db.Treatment;
|
||||||
import info.nightscout.androidaps.events.EventAppExit;
|
import info.nightscout.androidaps.events.EventAppExit;
|
||||||
import info.nightscout.androidaps.events.EventInitializationChanged;
|
import info.nightscout.androidaps.events.EventInitializationChanged;
|
||||||
import info.nightscout.androidaps.events.EventPreferenceChange;
|
import info.nightscout.androidaps.events.EventPreferenceChange;
|
||||||
import info.nightscout.androidaps.events.EventPumpStatusChanged;
|
import info.nightscout.androidaps.events.EventPumpStatusChanged;
|
||||||
import info.nightscout.androidaps.data.Profile;
|
|
||||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||||
import info.nightscout.androidaps.plugins.Overview.Dialogs.BolusProgressDialog;
|
import info.nightscout.androidaps.plugins.Overview.Dialogs.BolusProgressDialog;
|
||||||
|
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
|
||||||
import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress;
|
import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress;
|
||||||
|
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin;
|
import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin;
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump;
|
import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump;
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.SerialIOThread;
|
import info.nightscout.androidaps.plugins.PumpDanaR.SerialIOThread;
|
||||||
|
@ -45,18 +37,6 @@ import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusStart;
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusStartWithSpeed;
|
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusStartWithSpeed;
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusStop;
|
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusStop;
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgCheckValue;
|
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgCheckValue;
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryAlarm;
|
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryBasalHour;
|
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryBolus;
|
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryCarbo;
|
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryDailyInsulin;
|
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryDone;
|
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryError;
|
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryGlucose;
|
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryRefill;
|
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistorySuspend;
|
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgPCCommStart;
|
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgPCCommStop;
|
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetActivateBasalProfile;
|
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetActivateBasalProfile;
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetBasalProfile;
|
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetBasalProfile;
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetCarbsEntry;
|
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetCarbsEntry;
|
||||||
|
@ -67,9 +47,9 @@ import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetTempBasalStop;
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetTime;
|
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetTime;
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingActiveProfile;
|
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingActiveProfile;
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingBasal;
|
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingBasal;
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingMeal;
|
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingGlucose;
|
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingGlucose;
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingMaxValues;
|
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingMaxValues;
|
||||||
|
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingMeal;
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingProfileRatios;
|
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingProfileRatios;
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingProfileRatiosAll;
|
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingProfileRatiosAll;
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingPumpTime;
|
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingPumpTime;
|
||||||
|
@ -78,51 +58,18 @@ import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgStatus;
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgStatusBasic;
|
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgStatusBasic;
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgStatusBolusExtended;
|
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgStatusBolusExtended;
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgStatusTempBasal;
|
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgStatusTempBasal;
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes;
|
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRNewStatus;
|
import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRNewStatus;
|
||||||
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
|
|
||||||
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
|
|
||||||
import info.nightscout.androidaps.queue.Callback;
|
import info.nightscout.androidaps.queue.Callback;
|
||||||
import info.nightscout.utils.NSUpload;
|
import info.nightscout.utils.NSUpload;
|
||||||
import info.nightscout.utils.SP;
|
import info.nightscout.utils.SP;
|
||||||
import info.nightscout.utils.ToastUtils;
|
import info.nightscout.utils.ToastUtils;
|
||||||
|
|
||||||
public class DanaRExecutionService extends Service {
|
public class DanaRExecutionService extends AbstractDanaRExecutionService{
|
||||||
private static Logger log = LoggerFactory.getLogger(DanaRExecutionService.class);
|
|
||||||
|
|
||||||
private String devName;
|
|
||||||
|
|
||||||
private SerialIOThread mSerialIOThread;
|
|
||||||
private BluetoothSocket mRfcommSocket;
|
|
||||||
private BluetoothDevice mBTDevice;
|
|
||||||
|
|
||||||
private IBinder mBinder = new LocalBinder();
|
|
||||||
|
|
||||||
private DanaRPump danaRPump = DanaRPump.getInstance();
|
|
||||||
private Treatment bolusingTreatment = null;
|
|
||||||
|
|
||||||
private static Boolean connectionInProgress = false;
|
|
||||||
|
|
||||||
private static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");
|
|
||||||
|
|
||||||
private BroadcastReceiver receiver = new BroadcastReceiver() {
|
|
||||||
@Override
|
|
||||||
public void onReceive(Context context, Intent intent) {
|
|
||||||
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
|
|
||||||
String action = intent.getAction();
|
|
||||||
if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) {
|
|
||||||
log.debug("Device was disconnected " + device.getName());//Device was disconnected
|
|
||||||
if (mBTDevice != null && mBTDevice.getName() != null && mBTDevice.getName().equals(device.getName())) {
|
|
||||||
if (mSerialIOThread != null) {
|
|
||||||
mSerialIOThread.disconnect("BT disconnection broadcast");
|
|
||||||
}
|
|
||||||
MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTED));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public DanaRExecutionService() {
|
public DanaRExecutionService() {
|
||||||
|
log = LoggerFactory.getLogger(DanaRExecutionService.class);
|
||||||
|
mBinder = new LocalBinder();
|
||||||
|
|
||||||
registerBus();
|
registerBus();
|
||||||
MainApp.instance().getApplicationContext().registerReceiver(receiver, new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED));
|
MainApp.instance().getApplicationContext().registerReceiver(receiver, new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED));
|
||||||
}
|
}
|
||||||
|
@ -133,17 +80,6 @@ public class DanaRExecutionService extends Service {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public IBinder onBind(Intent intent) {
|
|
||||||
return mBinder;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
|
||||||
|
|
||||||
return START_STICKY;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void registerBus() {
|
private void registerBus() {
|
||||||
try {
|
try {
|
||||||
MainApp.bus().unregister(this);
|
MainApp.bus().unregister(this);
|
||||||
|
@ -154,49 +90,27 @@ public class DanaRExecutionService extends Service {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void onStatusEvent(EventAppExit event) {
|
public void onStatusEvent(final EventPreferenceChange pch) {
|
||||||
if (Config.logFunctionCalls)
|
|
||||||
log.debug("EventAppExit received");
|
|
||||||
|
|
||||||
if (mSerialIOThread != null)
|
if (mSerialIOThread != null)
|
||||||
mSerialIOThread.disconnect("Application exit");
|
mSerialIOThread.disconnect("EventPreferenceChange");
|
||||||
|
|
||||||
MainApp.instance().getApplicationContext().unregisterReceiver(receiver);
|
|
||||||
|
|
||||||
stopSelf();
|
|
||||||
if (Config.logFunctionCalls)
|
|
||||||
log.debug("EventAppExit finished");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isConnected() {
|
public void connect() {
|
||||||
return mRfcommSocket != null && mRfcommSocket.isConnected();
|
if (mDanaRPump.password != -1 && mDanaRPump.password != SP.getInt(R.string.key_danar_password, -1)) {
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isConnecting() {
|
|
||||||
return connectionInProgress;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void disconnect(String from) {
|
|
||||||
if (mSerialIOThread != null)
|
|
||||||
mSerialIOThread.disconnect(from);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void connect(String from) {
|
|
||||||
if (danaRPump.password != -1 && danaRPump.password != SP.getInt(R.string.key_danar_password, -1)) {
|
|
||||||
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.wrongpumppassword), R.raw.error);
|
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.wrongpumppassword), R.raw.error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connectionInProgress)
|
if (mConnectionInProgress)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
new Thread(new Runnable() {
|
new Thread(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
connectionInProgress = true;
|
mConnectionInProgress = true;
|
||||||
getBTSocketForSelectedPump();
|
getBTSocketForSelectedPump();
|
||||||
if (mRfcommSocket == null || mBTDevice == null) {
|
if (mRfcommSocket == null || mBTDevice == null) {
|
||||||
connectionInProgress = false;
|
mConnectionInProgress = false;
|
||||||
return; // Device not found
|
return; // Device not found
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,48 +131,11 @@ public class DanaRExecutionService extends Service {
|
||||||
MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.CONNECTED, 0));
|
MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.CONNECTED, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
connectionInProgress = false;
|
mConnectionInProgress = false;
|
||||||
}
|
}
|
||||||
}).start();
|
}).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void stopConnecting() {
|
|
||||||
if (mSerialIOThread != null)
|
|
||||||
mSerialIOThread.disconnect("stopConnecting");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void getBTSocketForSelectedPump() {
|
|
||||||
devName = SP.getString(MainApp.sResources.getString(R.string.key_danar_bt_name), "");
|
|
||||||
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
|
|
||||||
|
|
||||||
if (bluetoothAdapter != null) {
|
|
||||||
Set<BluetoothDevice> bondedDevices = bluetoothAdapter.getBondedDevices();
|
|
||||||
|
|
||||||
for (BluetoothDevice device : bondedDevices) {
|
|
||||||
if (devName.equals(device.getName())) {
|
|
||||||
mBTDevice = device;
|
|
||||||
try {
|
|
||||||
mRfcommSocket = mBTDevice.createRfcommSocketToServiceRecord(SPP_UUID);
|
|
||||||
} catch (IOException e) {
|
|
||||||
log.error("Error creating socket: ", e);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.nobtadapter));
|
|
||||||
}
|
|
||||||
if (mBTDevice == null) {
|
|
||||||
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.devicenotfound));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Subscribe
|
|
||||||
public void onStatusEvent(final EventPreferenceChange pch) {
|
|
||||||
if (mSerialIOThread != null)
|
|
||||||
mSerialIOThread.disconnect("EventPreferenceChange");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void getPumpStatus() {
|
public void getPumpStatus() {
|
||||||
try {
|
try {
|
||||||
MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingpumpstatus)));
|
MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingpumpstatus)));
|
||||||
|
@ -268,7 +145,7 @@ public class DanaRExecutionService extends Service {
|
||||||
MsgStatusBolusExtended exStatusMsg = new MsgStatusBolusExtended();
|
MsgStatusBolusExtended exStatusMsg = new MsgStatusBolusExtended();
|
||||||
MsgCheckValue checkValue = new MsgCheckValue();
|
MsgCheckValue checkValue = new MsgCheckValue();
|
||||||
|
|
||||||
if (danaRPump.isNewPump) {
|
if (mDanaRPump.isNewPump) {
|
||||||
mSerialIOThread.sendMessage(checkValue);
|
mSerialIOThread.sendMessage(checkValue);
|
||||||
if (!checkValue.received) {
|
if (!checkValue.received) {
|
||||||
return;
|
return;
|
||||||
|
@ -283,8 +160,8 @@ public class DanaRExecutionService extends Service {
|
||||||
mSerialIOThread.sendMessage(exStatusMsg);
|
mSerialIOThread.sendMessage(exStatusMsg);
|
||||||
MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingbolusstatus)));
|
MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingbolusstatus)));
|
||||||
|
|
||||||
Date now = new Date();
|
long now = System.currentTimeMillis();
|
||||||
if (danaRPump.lastSettingsRead.getTime() + 60 * 60 * 1000L < now.getTime() || !MainApp.getSpecificPlugin(DanaRPlugin.class).isInitialized()) {
|
if (mDanaRPump.lastSettingsRead + 60 * 60 * 1000L < now || !MainApp.getSpecificPlugin(DanaRPlugin.class).isInitialized()) {
|
||||||
MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingpumpsettings)));
|
MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingpumpsettings)));
|
||||||
mSerialIOThread.sendMessage(new MsgSettingShippingInfo());
|
mSerialIOThread.sendMessage(new MsgSettingShippingInfo());
|
||||||
mSerialIOThread.sendMessage(new MsgSettingActiveProfile());
|
mSerialIOThread.sendMessage(new MsgSettingActiveProfile());
|
||||||
|
@ -298,26 +175,26 @@ public class DanaRExecutionService extends Service {
|
||||||
mSerialIOThread.sendMessage(new MsgSettingProfileRatiosAll());
|
mSerialIOThread.sendMessage(new MsgSettingProfileRatiosAll());
|
||||||
MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingpumptime)));
|
MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingpumptime)));
|
||||||
mSerialIOThread.sendMessage(new MsgSettingPumpTime());
|
mSerialIOThread.sendMessage(new MsgSettingPumpTime());
|
||||||
long timeDiff = (danaRPump.pumpTime.getTime() - System.currentTimeMillis()) / 1000L;
|
long timeDiff = (mDanaRPump.pumpTime.getTime() - System.currentTimeMillis()) / 1000L;
|
||||||
log.debug("Pump time difference: " + timeDiff + " seconds");
|
log.debug("Pump time difference: " + timeDiff + " seconds");
|
||||||
if (Math.abs(timeDiff) > 10) {
|
if (Math.abs(timeDiff) > 10) {
|
||||||
mSerialIOThread.sendMessage(new MsgSetTime(new Date()));
|
mSerialIOThread.sendMessage(new MsgSetTime(new Date()));
|
||||||
mSerialIOThread.sendMessage(new MsgSettingPumpTime());
|
mSerialIOThread.sendMessage(new MsgSettingPumpTime());
|
||||||
timeDiff = (danaRPump.pumpTime.getTime() - System.currentTimeMillis()) / 1000L;
|
timeDiff = (mDanaRPump.pumpTime.getTime() - System.currentTimeMillis()) / 1000L;
|
||||||
log.debug("Pump time difference: " + timeDiff + " seconds");
|
log.debug("Pump time difference: " + timeDiff + " seconds");
|
||||||
}
|
}
|
||||||
danaRPump.lastSettingsRead = now;
|
mDanaRPump.lastSettingsRead = now;
|
||||||
}
|
}
|
||||||
|
|
||||||
danaRPump.lastConnection = now;
|
mDanaRPump.lastConnection = now;
|
||||||
MainApp.bus().post(new EventDanaRNewStatus());
|
MainApp.bus().post(new EventDanaRNewStatus());
|
||||||
MainApp.bus().post(new EventInitializationChanged());
|
MainApp.bus().post(new EventInitializationChanged());
|
||||||
NSUpload.uploadDeviceStatus();
|
NSUpload.uploadDeviceStatus();
|
||||||
if (danaRPump.dailyTotalUnits > danaRPump.maxDailyTotalUnits * Constants.dailyLimitWarning) {
|
if (mDanaRPump.dailyTotalUnits > mDanaRPump.maxDailyTotalUnits * Constants.dailyLimitWarning) {
|
||||||
log.debug("Approaching daily limit: " + danaRPump.dailyTotalUnits + "/" + danaRPump.maxDailyTotalUnits);
|
log.debug("Approaching daily limit: " + mDanaRPump.dailyTotalUnits + "/" + mDanaRPump.maxDailyTotalUnits);
|
||||||
Notification reportFail = new Notification(Notification.APPROACHING_DAILY_LIMIT, MainApp.sResources.getString(R.string.approachingdailylimit), Notification.URGENT);
|
Notification reportFail = new Notification(Notification.APPROACHING_DAILY_LIMIT, MainApp.sResources.getString(R.string.approachingdailylimit), Notification.URGENT);
|
||||||
MainApp.bus().post(new EventNewNotification(reportFail));
|
MainApp.bus().post(new EventNewNotification(reportFail));
|
||||||
NSUpload.uploadError(MainApp.sResources.getString(R.string.approachingdailylimit) + ": " + danaRPump.dailyTotalUnits + "/" + danaRPump.maxDailyTotalUnits + "U");
|
NSUpload.uploadError(MainApp.sResources.getString(R.string.approachingdailylimit) + ": " + mDanaRPump.dailyTotalUnits + "/" + mDanaRPump.maxDailyTotalUnits + "U");
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("Unhandled exception", e);
|
log.error("Unhandled exception", e);
|
||||||
|
@ -326,10 +203,10 @@ public class DanaRExecutionService extends Service {
|
||||||
|
|
||||||
public boolean tempBasal(int percent, int durationInHours) {
|
public boolean tempBasal(int percent, int durationInHours) {
|
||||||
if (!isConnected()) return false;
|
if (!isConnected()) return false;
|
||||||
if (danaRPump.isTempBasalInProgress) {
|
if (mDanaRPump.isTempBasalInProgress) {
|
||||||
MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.stoppingtempbasal)));
|
MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.stoppingtempbasal)));
|
||||||
mSerialIOThread.sendMessage(new MsgSetTempBasalStop());
|
mSerialIOThread.sendMessage(new MsgSetTempBasalStop());
|
||||||
waitMsec(500);
|
SystemClock.sleep(500);
|
||||||
}
|
}
|
||||||
MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.settingtempbasal)));
|
MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.settingtempbasal)));
|
||||||
mSerialIOThread.sendMessage(new MsgSetTempBasalStart(percent, durationInHours));
|
mSerialIOThread.sendMessage(new MsgSetTempBasalStart(percent, durationInHours));
|
||||||
|
@ -365,11 +242,16 @@ public class DanaRExecutionService extends Service {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean bolus(double amount, int carbs, final Treatment t) {
|
@Override
|
||||||
|
public PumpEnactResult loadEvents() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean bolus(double amount, int carbs, long carbtime, final Treatment t) {
|
||||||
if (!isConnected()) return false;
|
if (!isConnected()) return false;
|
||||||
if (BolusProgressDialog.stopPressed) return false;
|
if (BolusProgressDialog.stopPressed) return false;
|
||||||
|
|
||||||
bolusingTreatment = t;
|
mBolusingTreatment = t;
|
||||||
int preferencesSpeed = SP.getInt(R.string.key_danars_bolusspeed, 0);
|
int preferencesSpeed = SP.getInt(R.string.key_danars_bolusspeed, 0);
|
||||||
MessageBase start;
|
MessageBase start;
|
||||||
if (preferencesSpeed == 0)
|
if (preferencesSpeed == 0)
|
||||||
|
@ -379,7 +261,7 @@ public class DanaRExecutionService extends Service {
|
||||||
MsgBolusStop stop = new MsgBolusStop(amount, t);
|
MsgBolusStop stop = new MsgBolusStop(amount, t);
|
||||||
|
|
||||||
if (carbs > 0) {
|
if (carbs > 0) {
|
||||||
mSerialIOThread.sendMessage(new MsgSetCarbsEntry(System.currentTimeMillis(), carbs));
|
mSerialIOThread.sendMessage(new MsgSetCarbsEntry(carbtime, carbs));
|
||||||
}
|
}
|
||||||
|
|
||||||
MsgBolusProgress progress = new MsgBolusProgress(amount, t); // initialize static variables
|
MsgBolusProgress progress = new MsgBolusProgress(amount, t); // initialize static variables
|
||||||
|
@ -392,20 +274,20 @@ public class DanaRExecutionService extends Service {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
while (!stop.stopped && !start.failed) {
|
while (!stop.stopped && !start.failed) {
|
||||||
waitMsec(100);
|
SystemClock.sleep(100);
|
||||||
if ((System.currentTimeMillis() - progress.lastReceive) > 15 * 1000L) { // if i didn't receive status for more than 15 sec expecting broken comm
|
if ((System.currentTimeMillis() - progress.lastReceive) > 15 * 1000L) { // if i didn't receive status for more than 15 sec expecting broken comm
|
||||||
stop.stopped = true;
|
stop.stopped = true;
|
||||||
stop.forced = true;
|
stop.forced = true;
|
||||||
log.debug("Communication stopped");
|
log.debug("Communication stopped");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
waitMsec(300);
|
SystemClock.sleep(300);
|
||||||
|
|
||||||
EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance();
|
EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance();
|
||||||
bolusingEvent.t = t;
|
bolusingEvent.t = t;
|
||||||
bolusingEvent.percent = 99;
|
bolusingEvent.percent = 99;
|
||||||
|
|
||||||
bolusingTreatment = null;
|
mBolusingTreatment = null;
|
||||||
|
|
||||||
int speed = 12;
|
int speed = 12;
|
||||||
switch (preferencesSpeed) {
|
switch (preferencesSpeed) {
|
||||||
|
@ -437,11 +319,11 @@ public class DanaRExecutionService extends Service {
|
||||||
ConfigBuilderPlugin.getCommandQueue().independentConnect("bolusingInterrupted", new Callback() {
|
ConfigBuilderPlugin.getCommandQueue().independentConnect("bolusingInterrupted", new Callback() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (danaRPump.lastBolusTime.getTime() > System.currentTimeMillis() - 60 * 1000L) { // last bolus max 1 min old
|
if (mDanaRPump.lastBolusTime.getTime() > System.currentTimeMillis() - 60 * 1000L) { // last bolus max 1 min old
|
||||||
t.insulin = danaRPump.lastBolusAmount;
|
t.insulin = mDanaRPump.lastBolusAmount;
|
||||||
log.debug("Used bolus amount from history: " + danaRPump.lastBolusAmount);
|
log.debug("Used bolus amount from history: " + mDanaRPump.lastBolusAmount);
|
||||||
} else {
|
} else {
|
||||||
log.debug("Bolus amount in history too old: " + danaRPump.lastBolusTime.toLocaleString());
|
log.debug("Bolus amount in history too old: " + mDanaRPump.lastBolusTime.toLocaleString());
|
||||||
}
|
}
|
||||||
synchronized (o) {
|
synchronized (o) {
|
||||||
o.notify();
|
o.notify();
|
||||||
|
@ -460,22 +342,6 @@ public class DanaRExecutionService extends Service {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void bolusStop() {
|
|
||||||
if (Config.logDanaBTComm)
|
|
||||||
log.debug("bolusStop >>>>> @ " + (bolusingTreatment == null ? "" : bolusingTreatment.insulin));
|
|
||||||
MsgBolusStop stop = new MsgBolusStop();
|
|
||||||
stop.forced = true;
|
|
||||||
if (isConnected()) {
|
|
||||||
mSerialIOThread.sendMessage(stop);
|
|
||||||
while (!stop.stopped) {
|
|
||||||
mSerialIOThread.sendMessage(stop);
|
|
||||||
waitMsec(200);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
stop.stopped = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean carbsEntry(int amount) {
|
public boolean carbsEntry(int amount) {
|
||||||
if (!isConnected()) return false;
|
if (!isConnected()) return false;
|
||||||
MsgSetCarbsEntry msg = new MsgSetCarbsEntry(System.currentTimeMillis(), amount);
|
MsgSetCarbsEntry msg = new MsgSetCarbsEntry(System.currentTimeMillis(), amount);
|
||||||
|
@ -483,51 +349,9 @@ public class DanaRExecutionService extends Service {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PumpEnactResult loadHistory(byte type) {
|
@Override
|
||||||
PumpEnactResult result = new PumpEnactResult();
|
public boolean highTempBasal(int percent) {
|
||||||
if (!isConnected()) return result;
|
return false;
|
||||||
MessageBase msg = null;
|
|
||||||
switch (type) {
|
|
||||||
case RecordTypes.RECORD_TYPE_ALARM:
|
|
||||||
msg = new MsgHistoryAlarm();
|
|
||||||
break;
|
|
||||||
case RecordTypes.RECORD_TYPE_BASALHOUR:
|
|
||||||
msg = new MsgHistoryBasalHour();
|
|
||||||
break;
|
|
||||||
case RecordTypes.RECORD_TYPE_BOLUS:
|
|
||||||
msg = new MsgHistoryBolus();
|
|
||||||
break;
|
|
||||||
case RecordTypes.RECORD_TYPE_CARBO:
|
|
||||||
msg = new MsgHistoryCarbo();
|
|
||||||
break;
|
|
||||||
case RecordTypes.RECORD_TYPE_DAILY:
|
|
||||||
msg = new MsgHistoryDailyInsulin();
|
|
||||||
break;
|
|
||||||
case RecordTypes.RECORD_TYPE_ERROR:
|
|
||||||
msg = new MsgHistoryError();
|
|
||||||
break;
|
|
||||||
case RecordTypes.RECORD_TYPE_GLUCOSE:
|
|
||||||
msg = new MsgHistoryGlucose();
|
|
||||||
break;
|
|
||||||
case RecordTypes.RECORD_TYPE_REFILL:
|
|
||||||
msg = new MsgHistoryRefill();
|
|
||||||
break;
|
|
||||||
case RecordTypes.RECORD_TYPE_SUSPEND:
|
|
||||||
msg = new MsgHistorySuspend();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
MsgHistoryDone done = new MsgHistoryDone();
|
|
||||||
mSerialIOThread.sendMessage(new MsgPCCommStart());
|
|
||||||
waitMsec(400);
|
|
||||||
mSerialIOThread.sendMessage(msg);
|
|
||||||
while (!done.received && mRfcommSocket.isConnected()) {
|
|
||||||
waitMsec(100);
|
|
||||||
}
|
|
||||||
waitMsec(200);
|
|
||||||
mSerialIOThread.sendMessage(new MsgPCCommStop());
|
|
||||||
result.success = true;
|
|
||||||
result.comment = "OK";
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean updateBasalsInPump(final Profile profile) {
|
public boolean updateBasalsInPump(final Profile profile) {
|
||||||
|
@ -538,13 +362,25 @@ public class DanaRExecutionService extends Service {
|
||||||
mSerialIOThread.sendMessage(msgSet);
|
mSerialIOThread.sendMessage(msgSet);
|
||||||
MsgSetActivateBasalProfile msgActivate = new MsgSetActivateBasalProfile((byte) 0);
|
MsgSetActivateBasalProfile msgActivate = new MsgSetActivateBasalProfile((byte) 0);
|
||||||
mSerialIOThread.sendMessage(msgActivate);
|
mSerialIOThread.sendMessage(msgActivate);
|
||||||
danaRPump.lastSettingsRead = new Date(0); // force read full settings
|
mDanaRPump.lastSettingsRead = 0; // force read full settings
|
||||||
getPumpStatus();
|
getPumpStatus();
|
||||||
MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING));
|
MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void waitMsec(long msecs) {
|
@Subscribe
|
||||||
SystemClock.sleep(msecs);
|
public void onStatusEvent(EventAppExit event) {
|
||||||
|
if (Config.logFunctionCalls)
|
||||||
|
log.debug("EventAppExit received");
|
||||||
|
|
||||||
|
if (mSerialIOThread != null)
|
||||||
|
mSerialIOThread.disconnect("Application exit");
|
||||||
|
|
||||||
|
MainApp.instance().getApplicationContext().unregisterReceiver(receiver);
|
||||||
|
|
||||||
|
stopSelf();
|
||||||
|
if (Config.logFunctionCalls)
|
||||||
|
log.debug("EventAppExit finished");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,71 +5,31 @@ import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.ServiceConnection;
|
import android.content.ServiceConnection;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
|
|
||||||
import com.squareup.otto.Subscribe;
|
import com.squareup.otto.Subscribe;
|
||||||
|
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.BuildConfig;
|
|
||||||
import info.nightscout.androidaps.Config;
|
import info.nightscout.androidaps.Config;
|
||||||
import info.nightscout.androidaps.Constants;
|
|
||||||
import info.nightscout.androidaps.MainApp;
|
import info.nightscout.androidaps.MainApp;
|
||||||
import info.nightscout.androidaps.R;
|
import info.nightscout.androidaps.R;
|
||||||
import info.nightscout.androidaps.data.DetailedBolusInfo;
|
import info.nightscout.androidaps.data.DetailedBolusInfo;
|
||||||
import info.nightscout.androidaps.data.Profile;
|
|
||||||
import info.nightscout.androidaps.data.ProfileStore;
|
|
||||||
import info.nightscout.androidaps.data.PumpEnactResult;
|
import info.nightscout.androidaps.data.PumpEnactResult;
|
||||||
import info.nightscout.androidaps.db.ExtendedBolus;
|
|
||||||
import info.nightscout.androidaps.db.TemporaryBasal;
|
import info.nightscout.androidaps.db.TemporaryBasal;
|
||||||
import info.nightscout.androidaps.db.Treatment;
|
import info.nightscout.androidaps.db.Treatment;
|
||||||
import info.nightscout.androidaps.events.EventAppExit;
|
import info.nightscout.androidaps.events.EventAppExit;
|
||||||
import info.nightscout.androidaps.events.EventPreferenceChange;
|
import info.nightscout.androidaps.events.EventPreferenceChange;
|
||||||
import info.nightscout.androidaps.interfaces.ConstraintsInterface;
|
|
||||||
import info.nightscout.androidaps.interfaces.DanaRInterface;
|
|
||||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
|
||||||
import info.nightscout.androidaps.interfaces.ProfileInterface;
|
|
||||||
import info.nightscout.androidaps.interfaces.PumpDescription;
|
import info.nightscout.androidaps.interfaces.PumpDescription;
|
||||||
import info.nightscout.androidaps.interfaces.PumpInterface;
|
|
||||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||||
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
|
import info.nightscout.androidaps.plugins.PumpDanaR.AbstractDanaRPlugin;
|
||||||
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
|
|
||||||
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
|
|
||||||
import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin;
|
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.DanaRFragment;
|
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump;
|
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaRKorean.services.DanaRKoreanExecutionService;
|
import info.nightscout.androidaps.plugins.PumpDanaRKorean.services.DanaRKoreanExecutionService;
|
||||||
import info.nightscout.utils.DateUtil;
|
|
||||||
import info.nightscout.utils.DecimalFormatter;
|
|
||||||
import info.nightscout.utils.Round;
|
import info.nightscout.utils.Round;
|
||||||
import info.nightscout.utils.SP;
|
import info.nightscout.utils.SP;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by mike on 05.08.2016.
|
* Created by mike on 05.08.2016.
|
||||||
*/
|
*/
|
||||||
public class DanaRKoreanPlugin implements PluginBase, PumpInterface, DanaRInterface, ConstraintsInterface, ProfileInterface {
|
public class DanaRKoreanPlugin extends AbstractDanaRPlugin {
|
||||||
private static Logger log = LoggerFactory.getLogger(DanaRKoreanPlugin.class);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getFragmentClass() {
|
|
||||||
return DanaRFragment.class.getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean fragmentPumpEnabled = false;
|
|
||||||
private static boolean fragmentProfileEnabled = false;
|
|
||||||
private static boolean fragmentPumpVisible = true;
|
|
||||||
|
|
||||||
private static DanaRKoreanExecutionService sExecutionService;
|
|
||||||
|
|
||||||
|
|
||||||
private static DanaRPump pump = DanaRPump.getInstance();
|
|
||||||
private boolean useExtendedBoluses = false;
|
|
||||||
|
|
||||||
private static DanaRKoreanPlugin plugin = null;
|
private static DanaRKoreanPlugin plugin = null;
|
||||||
|
|
||||||
|
@ -79,9 +39,8 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, DanaRInterf
|
||||||
return plugin;
|
return plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PumpDescription pumpDescription = new PumpDescription();
|
|
||||||
|
|
||||||
public DanaRKoreanPlugin() {
|
public DanaRKoreanPlugin() {
|
||||||
|
log = LoggerFactory.getLogger(DanaRKoreanPlugin.class);
|
||||||
useExtendedBoluses = SP.getBoolean("danar_useextended", false);
|
useExtendedBoluses = SP.getBoolean("danar_useextended", false);
|
||||||
|
|
||||||
Context context = MainApp.instance().getApplicationContext();
|
Context context = MainApp.instance().getApplicationContext();
|
||||||
|
@ -112,6 +71,8 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, DanaRInterf
|
||||||
pumpDescription.basalMinimumRate = 0.1d;
|
pumpDescription.basalMinimumRate = 0.1d;
|
||||||
|
|
||||||
pumpDescription.isRefillingCapable = true;
|
pumpDescription.isRefillingCapable = true;
|
||||||
|
|
||||||
|
pumpDescription.storesCarbInfo = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ServiceConnection mConnection = new ServiceConnection() {
|
private ServiceConnection mConnection = new ServiceConnection() {
|
||||||
|
@ -147,83 +108,17 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, DanaRInterf
|
||||||
}
|
}
|
||||||
|
|
||||||
// Plugin base interface
|
// Plugin base interface
|
||||||
@Override
|
|
||||||
public int getType() {
|
|
||||||
return PluginBase.PUMP;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return MainApp.instance().getString(R.string.danarkoreanpump);
|
return MainApp.instance().getString(R.string.danarkoreanpump);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getNameShort() {
|
|
||||||
String name = MainApp.sResources.getString(R.string.danarpump_shortname);
|
|
||||||
if (!name.trim().isEmpty()) {
|
|
||||||
//only if translation exists
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
// use long name as fallback
|
|
||||||
return getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isEnabled(int type) {
|
|
||||||
if (type == PluginBase.PROFILE) return fragmentProfileEnabled && fragmentPumpEnabled;
|
|
||||||
else if (type == PluginBase.PUMP) return fragmentPumpEnabled;
|
|
||||||
else if (type == PluginBase.CONSTRAINTS) return fragmentPumpEnabled;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isVisibleInTabs(int type) {
|
|
||||||
if (type == PluginBase.PROFILE || type == PluginBase.CONSTRAINTS) return false;
|
|
||||||
else if (type == PluginBase.PUMP) return fragmentPumpVisible;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean canBeHidden(int type) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasFragment() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean showInList(int type) {
|
|
||||||
return type == PUMP;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
|
|
||||||
if (type == PluginBase.PROFILE)
|
|
||||||
fragmentProfileEnabled = fragmentEnabled;
|
|
||||||
else if (type == PluginBase.PUMP)
|
|
||||||
fragmentPumpEnabled = fragmentEnabled;
|
|
||||||
// if pump profile was enabled need to switch to another too
|
|
||||||
if (type == PluginBase.PUMP && !fragmentEnabled && fragmentProfileEnabled) {
|
|
||||||
setFragmentEnabled(PluginBase.PROFILE, false);
|
|
||||||
setFragmentVisible(PluginBase.PROFILE, false);
|
|
||||||
NSProfilePlugin.getPlugin().setFragmentEnabled(PluginBase.PROFILE, true);
|
|
||||||
NSProfilePlugin.getPlugin().setFragmentVisible(PluginBase.PROFILE, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setFragmentVisible(int type, boolean fragmentVisible) {
|
|
||||||
if (type == PluginBase.PUMP)
|
|
||||||
fragmentPumpVisible = fragmentVisible;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getPreferencesId() {
|
public int getPreferencesId() {
|
||||||
return R.xml.pref_danarkorean;
|
return R.xml.pref_danarkorean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Pump interface
|
||||||
@Override
|
@Override
|
||||||
public boolean isFakingTempsByExtendedBoluses() {
|
public boolean isFakingTempsByExtendedBoluses() {
|
||||||
return useExtendedBoluses;
|
return useExtendedBoluses;
|
||||||
|
@ -231,82 +126,7 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, DanaRInterf
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isInitialized() {
|
public boolean isInitialized() {
|
||||||
return pump.lastConnection.getTime() > 0 && pump.maxBasal > 0 && !pump.isConfigUD && !pump.isEasyModeEnabled && pump.isExtendedBolusEnabled;
|
return pump.lastConnection > 0 && pump.maxBasal > 0 && !pump.isConfigUD && !pump.isEasyModeEnabled && pump.isExtendedBolusEnabled;
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSuspended() {
|
|
||||||
return pump.pumpSuspended;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isBusy() {
|
|
||||||
if (sExecutionService == null) return false;
|
|
||||||
return sExecutionService.isConnected() || sExecutionService.isConnecting();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pump interface
|
|
||||||
@Override
|
|
||||||
public PumpEnactResult setNewBasalProfile(Profile profile) {
|
|
||||||
PumpEnactResult result = new PumpEnactResult();
|
|
||||||
|
|
||||||
if (sExecutionService == null) {
|
|
||||||
log.error("setNewBasalProfile sExecutionService is null");
|
|
||||||
result.comment = "setNewBasalProfile sExecutionService is null";
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
if (!isInitialized()) {
|
|
||||||
log.error("setNewBasalProfile not initialized");
|
|
||||||
Notification notification = new Notification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED, MainApp.sResources.getString(R.string.pumpNotInitializedProfileNotSet), Notification.URGENT);
|
|
||||||
MainApp.bus().post(new EventNewNotification(notification));
|
|
||||||
result.comment = MainApp.sResources.getString(R.string.pumpNotInitializedProfileNotSet);
|
|
||||||
return result;
|
|
||||||
} else {
|
|
||||||
MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED));
|
|
||||||
}
|
|
||||||
if (!sExecutionService.updateBasalsInPump(profile)) {
|
|
||||||
Notification notification = new Notification(Notification.FAILED_UDPATE_PROFILE, MainApp.sResources.getString(R.string.failedupdatebasalprofile), Notification.URGENT);
|
|
||||||
MainApp.bus().post(new EventNewNotification(notification));
|
|
||||||
result.comment = MainApp.sResources.getString(R.string.failedupdatebasalprofile);
|
|
||||||
return result;
|
|
||||||
} else {
|
|
||||||
MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED));
|
|
||||||
MainApp.bus().post(new EventDismissNotification(Notification.FAILED_UDPATE_PROFILE));
|
|
||||||
result.success = true;
|
|
||||||
result.enacted = true;
|
|
||||||
result.comment = "OK";
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isThisProfileSet(Profile profile) {
|
|
||||||
if (!isInitialized())
|
|
||||||
return true; // TODO: not sure what's better. so far TRUE to prevent too many SMS
|
|
||||||
if (pump.pumpProfiles == null)
|
|
||||||
return true; // TODO: not sure what's better. so far TRUE to prevent too many SMS
|
|
||||||
int basalValues = pump.basal48Enable ? 48 : 24;
|
|
||||||
int basalIncrement = pump.basal48Enable ? 30 * 60 : 60 * 60;
|
|
||||||
for (int h = 0; h < basalValues; h++) {
|
|
||||||
Double pumpValue = pump.pumpProfiles[pump.activeProfile][h];
|
|
||||||
Double profileValue = profile.getBasal((Integer) (h * basalIncrement));
|
|
||||||
if (profileValue == null) return true;
|
|
||||||
if (Math.abs(pumpValue - profileValue) > getPumpDescription().basalStep) {
|
|
||||||
log.debug("Diff found. Hour: " + h + " Pump: " + pumpValue + " Profile: " + profileValue);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Date lastDataTime() {
|
|
||||||
return pump.lastConnection;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public double getBaseBasalRate() {
|
|
||||||
return pump.currentBasal;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -315,8 +135,9 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, DanaRInterf
|
||||||
detailedBolusInfo.insulin = configBuilderPlugin.applyBolusConstraints(detailedBolusInfo.insulin);
|
detailedBolusInfo.insulin = configBuilderPlugin.applyBolusConstraints(detailedBolusInfo.insulin);
|
||||||
if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) {
|
if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) {
|
||||||
Treatment t = new Treatment();
|
Treatment t = new Treatment();
|
||||||
|
t.isSMB = detailedBolusInfo.isSMB;
|
||||||
boolean connectionOK = false;
|
boolean connectionOK = false;
|
||||||
if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) connectionOK = sExecutionService.bolus(detailedBolusInfo.insulin, (int) detailedBolusInfo.carbs, t);
|
if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) connectionOK = sExecutionService.bolus(detailedBolusInfo.insulin, (int) detailedBolusInfo.carbs, detailedBolusInfo.carbTime, t);
|
||||||
PumpEnactResult result = new PumpEnactResult();
|
PumpEnactResult result = new PumpEnactResult();
|
||||||
result.success = connectionOK;
|
result.success = connectionOK;
|
||||||
result.bolusDelivered = t.insulin;
|
result.bolusDelivered = t.insulin;
|
||||||
|
@ -339,15 +160,6 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, DanaRInterf
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void stopBolusDelivering() {
|
|
||||||
if (sExecutionService == null) {
|
|
||||||
log.error("stopBolusDelivering sExecutionService is null");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
sExecutionService.bolusStop();
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is called from APS
|
// This is called from APS
|
||||||
@Override
|
@Override
|
||||||
public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean enforceNew) {
|
public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean enforceNew) {
|
||||||
|
@ -500,107 +312,12 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, DanaRInterf
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, boolean enforceNew) {
|
|
||||||
PumpEnactResult result = new PumpEnactResult();
|
|
||||||
ConfigBuilderPlugin configBuilderPlugin = MainApp.getConfigBuilder();
|
|
||||||
percent = configBuilderPlugin.applyBasalConstraints(percent);
|
|
||||||
if (percent < 0) {
|
|
||||||
result.isTempCancel = false;
|
|
||||||
result.enacted = false;
|
|
||||||
result.success = false;
|
|
||||||
result.comment = MainApp.instance().getString(R.string.danar_invalidinput);
|
|
||||||
log.error("setTempBasalPercent: Invalid input");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
if (percent > getPumpDescription().maxTempPercent)
|
|
||||||
percent = getPumpDescription().maxTempPercent;
|
|
||||||
TemporaryBasal runningTB = MainApp.getConfigBuilder().getRealTempBasalFromHistory(System.currentTimeMillis());
|
|
||||||
if (runningTB != null && runningTB.percentRate == percent && enforceNew) {
|
|
||||||
result.enacted = false;
|
|
||||||
result.success = true;
|
|
||||||
result.isTempCancel = false;
|
|
||||||
result.comment = MainApp.instance().getString(R.string.virtualpump_resultok);
|
|
||||||
result.duration = pump.tempBasalRemainingMin;
|
|
||||||
result.percent = pump.tempBasalPercent;
|
|
||||||
result.absolute = MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory();
|
|
||||||
result.isPercent = true;
|
|
||||||
if (Config.logPumpActions)
|
|
||||||
log.debug("setTempBasalPercent: Correct value already set");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
int durationInHours = Math.max(durationInMinutes / 60, 1);
|
|
||||||
boolean connectionOK = sExecutionService.tempBasal(percent, durationInHours);
|
|
||||||
if (connectionOK && pump.isTempBasalInProgress && pump.tempBasalPercent == percent) {
|
|
||||||
result.enacted = true;
|
|
||||||
result.success = true;
|
|
||||||
result.comment = MainApp.instance().getString(R.string.virtualpump_resultok);
|
|
||||||
result.isTempCancel = false;
|
|
||||||
result.duration = pump.tempBasalRemainingMin;
|
|
||||||
result.percent = pump.tempBasalPercent;
|
|
||||||
result.absolute = MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory();
|
|
||||||
result.isPercent = true;
|
|
||||||
if (Config.logPumpActions)
|
|
||||||
log.debug("setTempBasalPercent: OK");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
result.enacted = false;
|
|
||||||
result.success = false;
|
|
||||||
result.comment = MainApp.instance().getString(R.string.danar_valuenotsetproperly);
|
|
||||||
log.error("setTempBasalPercent: Failed to set temp basal");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes) {
|
|
||||||
ConfigBuilderPlugin configBuilderPlugin = MainApp.getConfigBuilder();
|
|
||||||
insulin = configBuilderPlugin.applyBolusConstraints(insulin);
|
|
||||||
// needs to be rounded
|
|
||||||
int durationInHalfHours = Math.max(durationInMinutes / 30, 1);
|
|
||||||
insulin = Round.roundTo(insulin, getPumpDescription().extendedBolusStep);
|
|
||||||
|
|
||||||
PumpEnactResult result = new PumpEnactResult();
|
|
||||||
ExtendedBolus runningEB = MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis());
|
|
||||||
if (runningEB != null && Math.abs(runningEB.insulin - insulin) < getPumpDescription().extendedBolusStep) {
|
|
||||||
result.enacted = false;
|
|
||||||
result.success = true;
|
|
||||||
result.comment = MainApp.instance().getString(R.string.virtualpump_resultok);
|
|
||||||
result.duration = pump.extendedBolusRemainingMinutes;
|
|
||||||
result.absolute = pump.extendedBolusAbsoluteRate;
|
|
||||||
result.isPercent = false;
|
|
||||||
result.isTempCancel = false;
|
|
||||||
if (Config.logPumpActions)
|
|
||||||
log.debug("setExtendedBolus: Correct extended bolus already set. Current: " + pump.extendedBolusAmount + " Asked: " + insulin);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
boolean connectionOK = sExecutionService.extendedBolus(insulin, durationInHalfHours);
|
|
||||||
if (connectionOK && pump.isExtendedInProgress && Math.abs(pump.extendedBolusAmount - insulin) < getPumpDescription().extendedBolusStep) {
|
|
||||||
result.enacted = true;
|
|
||||||
result.success = true;
|
|
||||||
result.comment = MainApp.instance().getString(R.string.virtualpump_resultok);
|
|
||||||
result.isTempCancel = false;
|
|
||||||
result.duration = pump.extendedBolusRemainingMinutes;
|
|
||||||
result.absolute = pump.extendedBolusAbsoluteRate;
|
|
||||||
result.bolusDelivered = pump.extendedBolusAmount;
|
|
||||||
result.isPercent = false;
|
|
||||||
if (Config.logPumpActions)
|
|
||||||
log.debug("setExtendedBolus: OK");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
result.enacted = false;
|
|
||||||
result.success = false;
|
|
||||||
result.comment = MainApp.instance().getString(R.string.danar_valuenotsetproperly);
|
|
||||||
log.error("setExtendedBolus: Failed to extended bolus");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PumpEnactResult cancelTempBasal(boolean force) {
|
public PumpEnactResult cancelTempBasal(boolean force) {
|
||||||
if (MainApp.getConfigBuilder().isInHistoryRealTempBasalInProgress())
|
if (MainApp.getConfigBuilder().isInHistoryRealTempBasalInProgress())
|
||||||
return cancelRealTempBasal();
|
return cancelRealTempBasal();
|
||||||
if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress() && useExtendedBoluses) {
|
if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress() && useExtendedBoluses) {
|
||||||
PumpEnactResult cancelEx = cancelExtendedBolus();
|
return cancelExtendedBolus();
|
||||||
return cancelEx;
|
|
||||||
}
|
}
|
||||||
PumpEnactResult result = new PumpEnactResult();
|
PumpEnactResult result = new PumpEnactResult();
|
||||||
result.success = true;
|
result.success = true;
|
||||||
|
@ -634,257 +351,8 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, DanaRInterf
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public PumpEnactResult cancelExtendedBolus() {
|
|
||||||
PumpEnactResult result = new PumpEnactResult();
|
|
||||||
ExtendedBolus runningEB = MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis());
|
|
||||||
if (runningEB != null) {
|
|
||||||
sExecutionService.extendedBolusStop();
|
|
||||||
result.enacted = true;
|
|
||||||
result.isTempCancel = true;
|
|
||||||
}
|
|
||||||
if (!pump.isExtendedInProgress) {
|
|
||||||
result.success = true;
|
|
||||||
result.comment = MainApp.instance().getString(R.string.virtualpump_resultok);
|
|
||||||
if (Config.logPumpActions)
|
|
||||||
log.debug("cancelExtendedBolus: OK");
|
|
||||||
return result;
|
|
||||||
} else {
|
|
||||||
result.success = false;
|
|
||||||
result.comment = MainApp.instance().getString(R.string.danar_valuenotsetproperly);
|
|
||||||
log.error("cancelExtendedBolus: Failed to cancel extended bolus");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void connect(String from) {
|
|
||||||
if (sExecutionService != null) {
|
|
||||||
sExecutionService.connect(from);
|
|
||||||
pumpDescription.basalStep = pump.basalStep;
|
|
||||||
pumpDescription.bolusStep = pump.bolusStep;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isConnected() {
|
|
||||||
return sExecutionService != null && sExecutionService.isConnected();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isConnecting() {
|
|
||||||
return sExecutionService != null && sExecutionService.isConnecting();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void disconnect(String from) {
|
|
||||||
if (sExecutionService != null) sExecutionService.disconnect(from);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void stopConnecting() {
|
|
||||||
if (sExecutionService != null) sExecutionService.stopConnecting();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void getPumpStatus() {
|
|
||||||
if (sExecutionService != null) sExecutionService.getPumpStatus();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public JSONObject getJSONStatus() {
|
|
||||||
if (pump.lastConnection.getTime() + 5 * 60 * 1000L < System.currentTimeMillis()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
JSONObject pumpjson = new JSONObject();
|
|
||||||
JSONObject battery = new JSONObject();
|
|
||||||
JSONObject status = new JSONObject();
|
|
||||||
JSONObject extended = new JSONObject();
|
|
||||||
try {
|
|
||||||
battery.put("percent", pump.batteryRemaining);
|
|
||||||
status.put("status", pump.pumpSuspended ? "suspended" : "normal");
|
|
||||||
status.put("timestamp", DateUtil.toISOString(pump.lastConnection));
|
|
||||||
extended.put("Version", BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION);
|
|
||||||
extended.put("PumpIOB", pump.iob);
|
|
||||||
if (pump.lastBolusTime.getTime() != 0) {
|
|
||||||
extended.put("LastBolus", pump.lastBolusTime.toLocaleString());
|
|
||||||
extended.put("LastBolusAmount", pump.lastBolusAmount);
|
|
||||||
}
|
|
||||||
TemporaryBasal tb = MainApp.getConfigBuilder().getRealTempBasalFromHistory(System.currentTimeMillis());
|
|
||||||
if (tb != null) {
|
|
||||||
extended.put("TempBasalAbsoluteRate", tb.tempBasalConvertedToAbsolute(System.currentTimeMillis()));
|
|
||||||
extended.put("TempBasalStart", DateUtil.dateAndTimeString(tb.date));
|
|
||||||
extended.put("TempBasalRemaining", tb.getPlannedRemainingMinutes());
|
|
||||||
}
|
|
||||||
ExtendedBolus eb = MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis());
|
|
||||||
if (eb != null) {
|
|
||||||
extended.put("ExtendedBolusAbsoluteRate", eb.absoluteRate());
|
|
||||||
extended.put("ExtendedBolusStart", DateUtil.dateAndTimeString(eb.date));
|
|
||||||
extended.put("ExtendedBolusRemaining", eb.getPlannedRemainingMinutes());
|
|
||||||
}
|
|
||||||
extended.put("BaseBasalRate", getBaseBasalRate());
|
|
||||||
try {
|
|
||||||
extended.put("ActiveProfile", MainApp.getConfigBuilder().getProfileName());
|
|
||||||
} catch (Exception e) {
|
|
||||||
}
|
|
||||||
|
|
||||||
pumpjson.put("battery", battery);
|
|
||||||
pumpjson.put("status", status);
|
|
||||||
pumpjson.put("extended", extended);
|
|
||||||
pumpjson.put("reservoir", (int) pump.reservoirRemainingUnits);
|
|
||||||
pumpjson.put("clock", DateUtil.toISOString(new Date()));
|
|
||||||
} catch (JSONException e) {
|
|
||||||
log.error("Unhandled exception", e);
|
|
||||||
}
|
|
||||||
return pumpjson;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String deviceID() {
|
|
||||||
return pump.serialNumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PumpDescription getPumpDescription() {
|
|
||||||
return pumpDescription;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DanaR interface
|
|
||||||
*/
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PumpEnactResult loadHistory(byte type) {
|
|
||||||
return sExecutionService.loadHistory(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PumpEnactResult loadEvents() {
|
public PumpEnactResult loadEvents() {
|
||||||
return null; // no history, not needed
|
return null; // no history, not needed
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Constraint interface
|
|
||||||
*/
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isLoopEnabled() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isClosedModeEnabled() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isAutosensModeEnabled() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isAMAModeEnabled() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSMBModeEnabled() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("PointlessBooleanExpression")
|
|
||||||
@Override
|
|
||||||
public Double applyBasalConstraints(Double absoluteRate) {
|
|
||||||
double origAbsoluteRate = absoluteRate;
|
|
||||||
if (pump != null) {
|
|
||||||
if (absoluteRate > pump.maxBasal) {
|
|
||||||
absoluteRate = pump.maxBasal;
|
|
||||||
if (Config.logConstraintsChanges && origAbsoluteRate != Constants.basalAbsoluteOnlyForCheckLimit)
|
|
||||||
log.debug("Limiting rate " + origAbsoluteRate + "U/h by pump constraint to " + absoluteRate + "U/h");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return absoluteRate;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("PointlessBooleanExpression")
|
|
||||||
@Override
|
|
||||||
public Integer applyBasalConstraints(Integer percentRate) {
|
|
||||||
Integer origPercentRate = percentRate;
|
|
||||||
if (percentRate < 0) percentRate = 0;
|
|
||||||
if (percentRate > getPumpDescription().maxTempPercent)
|
|
||||||
percentRate = getPumpDescription().maxTempPercent;
|
|
||||||
if (!Objects.equals(percentRate, origPercentRate) && Config.logConstraintsChanges && !Objects.equals(origPercentRate, Constants.basalPercentOnlyForCheckLimit))
|
|
||||||
log.debug("Limiting percent rate " + origPercentRate + "% to " + percentRate + "%");
|
|
||||||
return percentRate;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("PointlessBooleanExpression")
|
|
||||||
@Override
|
|
||||||
public Double applyBolusConstraints(Double insulin) {
|
|
||||||
double origInsulin = insulin;
|
|
||||||
if (pump != null) {
|
|
||||||
if (insulin > pump.maxBolus) {
|
|
||||||
insulin = pump.maxBolus;
|
|
||||||
if (Config.logConstraintsChanges && origInsulin != Constants.bolusOnlyForCheckLimit)
|
|
||||||
log.debug("Limiting bolus " + origInsulin + "U by pump constraint to " + insulin + "U");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return insulin;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Integer applyCarbsConstraints(Integer carbs) {
|
|
||||||
return carbs;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Double applyMaxIOBConstraints(Double maxIob) {
|
|
||||||
return maxIob;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public ProfileStore getProfile() {
|
|
||||||
if (pump.lastSettingsRead.getTime() == 0)
|
|
||||||
return null; // no info now
|
|
||||||
return pump.createConvertedProfile();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getUnits() {
|
|
||||||
return pump.getUnits();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getProfileName() {
|
|
||||||
return pump.createConvertedProfileName();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reply for sms communicator
|
|
||||||
public String shortStatus(boolean veryShort) {
|
|
||||||
String ret = "";
|
|
||||||
if (pump.lastConnection.getTime() != 0) {
|
|
||||||
Long agoMsec = System.currentTimeMillis() - pump.lastConnection.getTime();
|
|
||||||
int agoMin = (int) (agoMsec / 60d / 1000d);
|
|
||||||
ret += "LastConn: " + agoMin + " minago\n";
|
|
||||||
}
|
|
||||||
if (pump.lastBolusTime.getTime() != 0) {
|
|
||||||
ret += "LastBolus: " + DecimalFormatter.to2Decimal(pump.lastBolusAmount) + "U @" + android.text.format.DateFormat.format("HH:mm", pump.lastBolusTime) + "\n";
|
|
||||||
}
|
|
||||||
if (MainApp.getConfigBuilder().isInHistoryRealTempBasalInProgress()) {
|
|
||||||
ret += "Temp: " + MainApp.getConfigBuilder().getRealTempBasalFromHistory(System.currentTimeMillis()).toStringFull() + "\n";
|
|
||||||
}
|
|
||||||
if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) {
|
|
||||||
ret += "Extended: " + MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis()).toString() + "\n";
|
|
||||||
}
|
|
||||||
if (!veryShort) {
|
|
||||||
ret += "TDD: " + DecimalFormatter.to0Decimal(pump.dailyTotalUnits) + " / " + pump.maxDailyTotalUnits + " U\n";
|
|
||||||
}
|
|
||||||
ret += "IOB: " + pump.iob + "U\n";
|
|
||||||
ret += "Reserv: " + DecimalFormatter.to0Decimal(pump.reservoirRemainingUnits) + "U\n";
|
|
||||||
ret += "Batt: " + pump.batteryRemaining + "\n";
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
// TODO: daily total constraint
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,13 +13,14 @@ import java.io.OutputStream;
|
||||||
import info.nightscout.androidaps.Config;
|
import info.nightscout.androidaps.Config;
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump;
|
import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump;
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase;
|
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase;
|
||||||
|
import info.nightscout.androidaps.plugins.PumpDanaR.services.AbstractSerialIOThread;
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaRKorean.comm.MessageHashTable_k;
|
import info.nightscout.androidaps.plugins.PumpDanaRKorean.comm.MessageHashTable_k;
|
||||||
import info.nightscout.utils.CRC;
|
import info.nightscout.utils.CRC;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by mike on 17.07.2016.
|
* Created by mike on 17.07.2016.
|
||||||
*/
|
*/
|
||||||
public class SerialIOThread extends Thread {
|
public class SerialIOThread extends AbstractSerialIOThread {
|
||||||
private static Logger log = LoggerFactory.getLogger(SerialIOThread.class);
|
private static Logger log = LoggerFactory.getLogger(SerialIOThread.class);
|
||||||
|
|
||||||
private InputStream mInputStream = null;
|
private InputStream mInputStream = null;
|
||||||
|
@ -29,10 +30,10 @@ public class SerialIOThread extends Thread {
|
||||||
private boolean mKeepRunning = true;
|
private boolean mKeepRunning = true;
|
||||||
private byte[] mReadBuff = new byte[0];
|
private byte[] mReadBuff = new byte[0];
|
||||||
|
|
||||||
MessageBase processedMessage;
|
private MessageBase processedMessage;
|
||||||
|
|
||||||
public SerialIOThread(BluetoothSocket rfcommSocket) {
|
public SerialIOThread(BluetoothSocket rfcommSocket) {
|
||||||
super(SerialIOThread.class.toString());
|
super();
|
||||||
|
|
||||||
mRfCommSocket = rfcommSocket;
|
mRfCommSocket = rfcommSocket;
|
||||||
try {
|
try {
|
||||||
|
@ -138,6 +139,7 @@ public class SerialIOThread extends Thread {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public synchronized void sendMessage(MessageBase message) {
|
public synchronized void sendMessage(MessageBase message) {
|
||||||
if (!mRfCommSocket.isConnected()) {
|
if (!mRfCommSocket.isConnected()) {
|
||||||
log.error("Socket not connected on sendMessage");
|
log.error("Socket not connected on sendMessage");
|
||||||
|
@ -173,6 +175,7 @@ public class SerialIOThread extends Thread {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void disconnect(String reason) {
|
public void disconnect(String reason) {
|
||||||
mKeepRunning = false;
|
mKeepRunning = false;
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -37,7 +37,7 @@ public class MsgInitConnStatusTime_k extends MessageBase {
|
||||||
MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).setFragmentVisible(PluginBase.PUMP, false);
|
MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).setFragmentVisible(PluginBase.PUMP, false);
|
||||||
MainApp.getSpecificPlugin(DanaRPlugin.class).setFragmentEnabled(PluginBase.PUMP, true);
|
MainApp.getSpecificPlugin(DanaRPlugin.class).setFragmentEnabled(PluginBase.PUMP, true);
|
||||||
MainApp.getSpecificPlugin(DanaRPlugin.class).setFragmentVisible(PluginBase.PUMP, true);
|
MainApp.getSpecificPlugin(DanaRPlugin.class).setFragmentVisible(PluginBase.PUMP, true);
|
||||||
DanaRPump.getInstance().lastConnection = new Date(0); // mark not initialized
|
DanaRPump.getInstance().lastConnection = 0; // mark not initialized
|
||||||
|
|
||||||
//If profile coming from pump, switch it as well
|
//If profile coming from pump, switch it as well
|
||||||
if (MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).isEnabled(PluginBase.PROFILE)) {
|
if (MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).isEnabled(PluginBase.PROFILE)) {
|
||||||
|
|
|
@ -24,7 +24,7 @@ public class MsgSettingBasal_k extends MessageBase {
|
||||||
pump.pumpProfiles[pump.activeProfile] = new double[24];
|
pump.pumpProfiles[pump.activeProfile] = new double[24];
|
||||||
for (int index = 0; index < 24; index++) {
|
for (int index = 0; index < 24; index++) {
|
||||||
int basal = intFromBuff(bytes, 2 * index, 2);
|
int basal = intFromBuff(bytes, 2 * index, 2);
|
||||||
if (basal < DanaRKoreanPlugin.pumpDescription.basalMinimumRate) basal = 0;
|
if (basal < DanaRKoreanPlugin.getPlugin().pumpDescription.basalMinimumRate) basal = 0;
|
||||||
pump.pumpProfiles[pump.activeProfile][index] = basal / 100d;
|
pump.pumpProfiles[pump.activeProfile][index] = basal / 100d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,58 +1,36 @@
|
||||||
package info.nightscout.androidaps.plugins.PumpDanaRKorean.services;
|
package info.nightscout.androidaps.plugins.PumpDanaRKorean.services;
|
||||||
|
|
||||||
import android.app.Service;
|
|
||||||
import android.bluetooth.BluetoothAdapter;
|
|
||||||
import android.bluetooth.BluetoothDevice;
|
import android.bluetooth.BluetoothDevice;
|
||||||
import android.bluetooth.BluetoothSocket;
|
|
||||||
import android.content.BroadcastReceiver;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.IBinder;
|
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
|
|
||||||
import com.squareup.otto.Subscribe;
|
import com.squareup.otto.Subscribe;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.Config;
|
import info.nightscout.androidaps.Config;
|
||||||
import info.nightscout.androidaps.Constants;
|
import info.nightscout.androidaps.Constants;
|
||||||
import info.nightscout.androidaps.MainApp;
|
import info.nightscout.androidaps.MainApp;
|
||||||
import info.nightscout.androidaps.R;
|
import info.nightscout.androidaps.R;
|
||||||
|
import info.nightscout.androidaps.data.Profile;
|
||||||
import info.nightscout.androidaps.data.PumpEnactResult;
|
import info.nightscout.androidaps.data.PumpEnactResult;
|
||||||
import info.nightscout.androidaps.db.Treatment;
|
import info.nightscout.androidaps.db.Treatment;
|
||||||
import info.nightscout.androidaps.events.EventAppExit;
|
import info.nightscout.androidaps.events.EventAppExit;
|
||||||
import info.nightscout.androidaps.events.EventInitializationChanged;
|
import info.nightscout.androidaps.events.EventInitializationChanged;
|
||||||
import info.nightscout.androidaps.events.EventPreferenceChange;
|
import info.nightscout.androidaps.events.EventPreferenceChange;
|
||||||
import info.nightscout.androidaps.events.EventPumpStatusChanged;
|
import info.nightscout.androidaps.events.EventPumpStatusChanged;
|
||||||
import info.nightscout.androidaps.data.Profile;
|
|
||||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||||
import info.nightscout.androidaps.plugins.Overview.Dialogs.BolusProgressDialog;
|
import info.nightscout.androidaps.plugins.Overview.Dialogs.BolusProgressDialog;
|
||||||
import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress;
|
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
|
||||||
|
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump;
|
import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump;
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase;
|
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusProgress;
|
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusProgress;
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusStart;
|
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusStart;
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusStop;
|
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusStop;
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryAlarm;
|
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryBasalHour;
|
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryBolus;
|
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryCarbo;
|
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryDailyInsulin;
|
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryDone;
|
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryError;
|
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryGlucose;
|
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryRefill;
|
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistorySuspend;
|
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgPCCommStart;
|
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgPCCommStop;
|
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetCarbsEntry;
|
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetCarbsEntry;
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetExtendedBolusStart;
|
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetExtendedBolusStart;
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetExtendedBolusStop;
|
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetExtendedBolusStop;
|
||||||
|
@ -68,56 +46,23 @@ import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingPumpTime;
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingShippingInfo;
|
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingShippingInfo;
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgStatusBolusExtended;
|
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgStatusBolusExtended;
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgStatusTempBasal;
|
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgStatusTempBasal;
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes;
|
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRNewStatus;
|
import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRNewStatus;
|
||||||
|
import info.nightscout.androidaps.plugins.PumpDanaR.services.AbstractDanaRExecutionService;
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin;
|
import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin;
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaRKorean.SerialIOThread;
|
import info.nightscout.androidaps.plugins.PumpDanaRKorean.SerialIOThread;
|
||||||
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
|
|
||||||
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
|
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaRKorean.comm.MsgCheckValue_k;
|
import info.nightscout.androidaps.plugins.PumpDanaRKorean.comm.MsgCheckValue_k;
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaRKorean.comm.MsgSettingBasal_k;
|
import info.nightscout.androidaps.plugins.PumpDanaRKorean.comm.MsgSettingBasal_k;
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaRKorean.comm.MsgStatusBasic_k;
|
import info.nightscout.androidaps.plugins.PumpDanaRKorean.comm.MsgStatusBasic_k;
|
||||||
import info.nightscout.androidaps.queue.Callback;
|
|
||||||
import info.nightscout.utils.NSUpload;
|
import info.nightscout.utils.NSUpload;
|
||||||
import info.nightscout.utils.SP;
|
import info.nightscout.utils.SP;
|
||||||
import info.nightscout.utils.ToastUtils;
|
import info.nightscout.utils.ToastUtils;
|
||||||
|
|
||||||
public class DanaRKoreanExecutionService extends Service {
|
public class DanaRKoreanExecutionService extends AbstractDanaRExecutionService {
|
||||||
private static Logger log = LoggerFactory.getLogger(DanaRKoreanExecutionService.class);
|
|
||||||
|
|
||||||
private String devName;
|
|
||||||
|
|
||||||
private SerialIOThread mSerialIOThread;
|
|
||||||
private BluetoothSocket mRfcommSocket;
|
|
||||||
private BluetoothDevice mBTDevice;
|
|
||||||
|
|
||||||
private IBinder mBinder = new LocalBinder();
|
|
||||||
|
|
||||||
private DanaRPump danaRPump = DanaRPump.getInstance();
|
|
||||||
private Treatment bolusingTreatment = null;
|
|
||||||
|
|
||||||
private static Boolean connectionInProgress = false;
|
|
||||||
|
|
||||||
private static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");
|
|
||||||
|
|
||||||
private BroadcastReceiver receiver = new BroadcastReceiver() {
|
|
||||||
@Override
|
|
||||||
public void onReceive(Context context, Intent intent) {
|
|
||||||
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
|
|
||||||
String action = intent.getAction();
|
|
||||||
if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) {
|
|
||||||
log.debug("Device was disconnected " + device.getName());//Device was disconnected
|
|
||||||
if (mBTDevice != null && mBTDevice.getName() != null && mBTDevice.getName().equals(device.getName())) {
|
|
||||||
if (mSerialIOThread != null) {
|
|
||||||
mSerialIOThread.disconnect("BT disconnection broadcast");
|
|
||||||
}
|
|
||||||
MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTED));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public DanaRKoreanExecutionService() {
|
public DanaRKoreanExecutionService() {
|
||||||
|
log = LoggerFactory.getLogger(DanaRKoreanExecutionService.class);
|
||||||
|
mBinder = new LocalBinder();
|
||||||
|
|
||||||
registerBus();
|
registerBus();
|
||||||
MainApp.instance().getApplicationContext().registerReceiver(receiver, new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED));
|
MainApp.instance().getApplicationContext().registerReceiver(receiver, new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED));
|
||||||
}
|
}
|
||||||
|
@ -128,17 +73,6 @@ public class DanaRKoreanExecutionService extends Service {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public IBinder onBind(Intent intent) {
|
|
||||||
return mBinder;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
|
||||||
|
|
||||||
return START_STICKY;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void registerBus() {
|
private void registerBus() {
|
||||||
try {
|
try {
|
||||||
MainApp.bus().unregister(this);
|
MainApp.bus().unregister(this);
|
||||||
|
@ -163,35 +97,28 @@ public class DanaRKoreanExecutionService extends Service {
|
||||||
log.debug("EventAppExit finished");
|
log.debug("EventAppExit finished");
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isConnected() {
|
@Subscribe
|
||||||
return mRfcommSocket != null && mRfcommSocket.isConnected();
|
public void onStatusEvent(final EventPreferenceChange pch) {
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isConnecting() {
|
|
||||||
return connectionInProgress;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void disconnect(String from) {
|
|
||||||
if (mSerialIOThread != null)
|
if (mSerialIOThread != null)
|
||||||
mSerialIOThread.disconnect(from);
|
mSerialIOThread.disconnect("EventPreferenceChange");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void connect(String from) {
|
public void connect() {
|
||||||
if (danaRPump.password != -1 && danaRPump.password != SP.getInt(R.string.key_danar_password, -1)) {
|
if (mDanaRPump.password != -1 && mDanaRPump.password != SP.getInt(R.string.key_danar_password, -1)) {
|
||||||
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.wrongpumppassword), R.raw.error);
|
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.wrongpumppassword), R.raw.error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connectionInProgress)
|
if (mConnectionInProgress)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
new Thread(new Runnable() {
|
new Thread(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
connectionInProgress = true;
|
mConnectionInProgress = true;
|
||||||
getBTSocketForSelectedPump();
|
getBTSocketForSelectedPump();
|
||||||
if (mRfcommSocket == null || mBTDevice == null) {
|
if (mRfcommSocket == null || mBTDevice == null) {
|
||||||
connectionInProgress = false;
|
mConnectionInProgress = false;
|
||||||
return; // Device not found
|
return; // Device not found
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,48 +139,11 @@ public class DanaRKoreanExecutionService extends Service {
|
||||||
MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.CONNECTED, 0));
|
MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.CONNECTED, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
connectionInProgress = false;
|
mConnectionInProgress = false;
|
||||||
}
|
}
|
||||||
}).start();
|
}).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void stopConnecting() {
|
|
||||||
if (mSerialIOThread != null)
|
|
||||||
mSerialIOThread.disconnect("stopConnecting");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void getBTSocketForSelectedPump() {
|
|
||||||
devName = SP.getString(MainApp.sResources.getString(R.string.key_danar_bt_name), "");
|
|
||||||
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
|
|
||||||
|
|
||||||
if (bluetoothAdapter != null) {
|
|
||||||
Set<BluetoothDevice> bondedDevices = bluetoothAdapter.getBondedDevices();
|
|
||||||
|
|
||||||
for (BluetoothDevice device : bondedDevices) {
|
|
||||||
if (devName.equals(device.getName())) {
|
|
||||||
mBTDevice = device;
|
|
||||||
try {
|
|
||||||
mRfcommSocket = mBTDevice.createRfcommSocketToServiceRecord(SPP_UUID);
|
|
||||||
} catch (IOException e) {
|
|
||||||
log.error("Error creating socket: ", e);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.nobtadapter));
|
|
||||||
}
|
|
||||||
if (mBTDevice == null) {
|
|
||||||
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.devicenotfound));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Subscribe
|
|
||||||
public void onStatusEvent(final EventPreferenceChange pch) {
|
|
||||||
if (mSerialIOThread != null)
|
|
||||||
mSerialIOThread.disconnect("EventPreferenceChange");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void getPumpStatus() {
|
public void getPumpStatus() {
|
||||||
try {
|
try {
|
||||||
MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingpumpstatus)));
|
MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingpumpstatus)));
|
||||||
|
@ -263,7 +153,7 @@ public class DanaRKoreanExecutionService extends Service {
|
||||||
MsgStatusBolusExtended exStatusMsg = new MsgStatusBolusExtended();
|
MsgStatusBolusExtended exStatusMsg = new MsgStatusBolusExtended();
|
||||||
MsgCheckValue_k checkValue = new MsgCheckValue_k();
|
MsgCheckValue_k checkValue = new MsgCheckValue_k();
|
||||||
|
|
||||||
if (danaRPump.isNewPump) {
|
if (mDanaRPump.isNewPump) {
|
||||||
mSerialIOThread.sendMessage(checkValue);
|
mSerialIOThread.sendMessage(checkValue);
|
||||||
if (!checkValue.received) {
|
if (!checkValue.received) {
|
||||||
return;
|
return;
|
||||||
|
@ -278,8 +168,8 @@ public class DanaRKoreanExecutionService extends Service {
|
||||||
mSerialIOThread.sendMessage(exStatusMsg);
|
mSerialIOThread.sendMessage(exStatusMsg);
|
||||||
MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingbolusstatus)));
|
MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingbolusstatus)));
|
||||||
|
|
||||||
Date now = new Date();
|
long now = System.currentTimeMillis();
|
||||||
if (danaRPump.lastSettingsRead.getTime() + 60 * 60 * 1000L < now.getTime() || !MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).isInitialized()) {
|
if (mDanaRPump.lastSettingsRead + 60 * 60 * 1000L < now || !MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).isInitialized()) {
|
||||||
MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingpumpsettings)));
|
MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingpumpsettings)));
|
||||||
mSerialIOThread.sendMessage(new MsgSettingShippingInfo());
|
mSerialIOThread.sendMessage(new MsgSettingShippingInfo());
|
||||||
mSerialIOThread.sendMessage(new MsgSettingMeal());
|
mSerialIOThread.sendMessage(new MsgSettingMeal());
|
||||||
|
@ -290,39 +180,38 @@ public class DanaRKoreanExecutionService extends Service {
|
||||||
mSerialIOThread.sendMessage(new MsgSettingProfileRatios());
|
mSerialIOThread.sendMessage(new MsgSettingProfileRatios());
|
||||||
MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingpumptime)));
|
MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingpumptime)));
|
||||||
mSerialIOThread.sendMessage(new MsgSettingPumpTime());
|
mSerialIOThread.sendMessage(new MsgSettingPumpTime());
|
||||||
long timeDiff = (danaRPump.pumpTime.getTime() - System.currentTimeMillis()) / 1000L;
|
long timeDiff = (mDanaRPump.pumpTime.getTime() - System.currentTimeMillis()) / 1000L;
|
||||||
log.debug("Pump time difference: " + timeDiff + " seconds");
|
log.debug("Pump time difference: " + timeDiff + " seconds");
|
||||||
if (Math.abs(timeDiff) > 10) {
|
if (Math.abs(timeDiff) > 10) {
|
||||||
mSerialIOThread.sendMessage(new MsgSetTime(new Date()));
|
mSerialIOThread.sendMessage(new MsgSetTime(new Date()));
|
||||||
mSerialIOThread.sendMessage(new MsgSettingPumpTime());
|
mSerialIOThread.sendMessage(new MsgSettingPumpTime());
|
||||||
timeDiff = (danaRPump.pumpTime.getTime() - System.currentTimeMillis()) / 1000L;
|
timeDiff = (mDanaRPump.pumpTime.getTime() - System.currentTimeMillis()) / 1000L;
|
||||||
log.debug("Pump time difference: " + timeDiff + " seconds");
|
log.debug("Pump time difference: " + timeDiff + " seconds");
|
||||||
}
|
}
|
||||||
danaRPump.lastSettingsRead = now;
|
mDanaRPump.lastSettingsRead = now;
|
||||||
}
|
}
|
||||||
|
|
||||||
danaRPump.lastConnection = now;
|
mDanaRPump.lastConnection = now;
|
||||||
MainApp.bus().post(new EventDanaRNewStatus());
|
MainApp.bus().post(new EventDanaRNewStatus());
|
||||||
MainApp.bus().post(new EventInitializationChanged());
|
MainApp.bus().post(new EventInitializationChanged());
|
||||||
NSUpload.uploadDeviceStatus();
|
NSUpload.uploadDeviceStatus();
|
||||||
if (danaRPump.dailyTotalUnits > danaRPump.maxDailyTotalUnits * Constants.dailyLimitWarning) {
|
if (mDanaRPump.dailyTotalUnits > mDanaRPump.maxDailyTotalUnits * Constants.dailyLimitWarning) {
|
||||||
log.debug("Approaching daily limit: " + danaRPump.dailyTotalUnits + "/" + danaRPump.maxDailyTotalUnits);
|
log.debug("Approaching daily limit: " + mDanaRPump.dailyTotalUnits + "/" + mDanaRPump.maxDailyTotalUnits);
|
||||||
Notification reportFail = new Notification(Notification.APPROACHING_DAILY_LIMIT, MainApp.sResources.getString(R.string.approachingdailylimit), Notification.URGENT);
|
Notification reportFail = new Notification(Notification.APPROACHING_DAILY_LIMIT, MainApp.sResources.getString(R.string.approachingdailylimit), Notification.URGENT);
|
||||||
MainApp.bus().post(new EventNewNotification(reportFail));
|
MainApp.bus().post(new EventNewNotification(reportFail));
|
||||||
NSUpload.uploadError(MainApp.sResources.getString(R.string.approachingdailylimit) + ": " + danaRPump.dailyTotalUnits + "/" + danaRPump.maxDailyTotalUnits + "U");
|
NSUpload.uploadError(MainApp.sResources.getString(R.string.approachingdailylimit) + ": " + mDanaRPump.dailyTotalUnits + "/" + mDanaRPump.maxDailyTotalUnits + "U");
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("Unhandled exception", e);
|
log.error("Unhandled exception", e);
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean tempBasal(int percent, int durationInHours) {
|
public boolean tempBasal(int percent, int durationInHours) {
|
||||||
if (!isConnected()) return false;
|
if (!isConnected()) return false;
|
||||||
if (danaRPump.isTempBasalInProgress) {
|
if (mDanaRPump.isTempBasalInProgress) {
|
||||||
MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.stoppingtempbasal)));
|
MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.stoppingtempbasal)));
|
||||||
mSerialIOThread.sendMessage(new MsgSetTempBasalStop());
|
mSerialIOThread.sendMessage(new MsgSetTempBasalStop());
|
||||||
waitMsec(500);
|
SystemClock.sleep(500);
|
||||||
}
|
}
|
||||||
MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.settingtempbasal)));
|
MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.settingtempbasal)));
|
||||||
mSerialIOThread.sendMessage(new MsgSetTempBasalStart(percent, durationInHours));
|
mSerialIOThread.sendMessage(new MsgSetTempBasalStart(percent, durationInHours));
|
||||||
|
@ -358,16 +247,21 @@ public class DanaRKoreanExecutionService extends Service {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean bolus(double amount, int carbs, final Treatment t) {
|
@Override
|
||||||
|
public PumpEnactResult loadEvents() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean bolus(double amount, int carbs, long carbtime, final Treatment t) {
|
||||||
if (!isConnected()) return false;
|
if (!isConnected()) return false;
|
||||||
if (BolusProgressDialog.stopPressed) return false;
|
if (BolusProgressDialog.stopPressed) return false;
|
||||||
|
|
||||||
bolusingTreatment = t;
|
mBolusingTreatment = t;
|
||||||
MsgBolusStart start = new MsgBolusStart(amount);
|
MsgBolusStart start = new MsgBolusStart(amount);
|
||||||
MsgBolusStop stop = new MsgBolusStop(amount, t);
|
MsgBolusStop stop = new MsgBolusStop(amount, t);
|
||||||
|
|
||||||
if (carbs > 0) {
|
if (carbs > 0) {
|
||||||
mSerialIOThread.sendMessage(new MsgSetCarbsEntry(System.currentTimeMillis(), carbs));
|
mSerialIOThread.sendMessage(new MsgSetCarbsEntry(carbtime, carbs));
|
||||||
}
|
}
|
||||||
|
|
||||||
MsgBolusProgress progress = new MsgBolusProgress(amount, t); // initialize static variables
|
MsgBolusProgress progress = new MsgBolusProgress(amount, t); // initialize static variables
|
||||||
|
@ -380,37 +274,21 @@ public class DanaRKoreanExecutionService extends Service {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
while (!stop.stopped && !start.failed) {
|
while (!stop.stopped && !start.failed) {
|
||||||
waitMsec(100);
|
SystemClock.sleep(100);
|
||||||
if ((System.currentTimeMillis() - progress.lastReceive) > 15 * 1000L) { // if i didn't receive status for more than 15 sec expecting broken comm
|
if ((System.currentTimeMillis() - progress.lastReceive) > 15 * 1000L) { // if i didn't receive status for more than 15 sec expecting broken comm
|
||||||
stop.stopped = true;
|
stop.stopped = true;
|
||||||
stop.forced = true;
|
stop.forced = true;
|
||||||
log.debug("Communication stopped");
|
log.debug("Communication stopped");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
waitMsec(300);
|
SystemClock.sleep(300);
|
||||||
|
|
||||||
bolusingTreatment = null;
|
mBolusingTreatment = null;
|
||||||
ConfigBuilderPlugin.getCommandQueue().readStatus("bolusOK", null);
|
ConfigBuilderPlugin.getCommandQueue().readStatus("bolusOK", null);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void bolusStop() {
|
|
||||||
if (Config.logDanaBTComm)
|
|
||||||
log.debug("bolusStop >>>>> @ " + (bolusingTreatment == null ? "" : bolusingTreatment.insulin));
|
|
||||||
MsgBolusStop stop = new MsgBolusStop();
|
|
||||||
stop.forced = true;
|
|
||||||
if (isConnected()) {
|
|
||||||
mSerialIOThread.sendMessage(stop);
|
|
||||||
while (!stop.stopped) {
|
|
||||||
mSerialIOThread.sendMessage(stop);
|
|
||||||
waitMsec(200);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
stop.stopped = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean carbsEntry(int amount) {
|
public boolean carbsEntry(int amount) {
|
||||||
if (!isConnected()) return false;
|
if (!isConnected()) return false;
|
||||||
MsgSetCarbsEntry msg = new MsgSetCarbsEntry(System.currentTimeMillis(), amount);
|
MsgSetCarbsEntry msg = new MsgSetCarbsEntry(System.currentTimeMillis(), amount);
|
||||||
|
@ -418,51 +296,9 @@ public class DanaRKoreanExecutionService extends Service {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PumpEnactResult loadHistory(byte type) {
|
@Override
|
||||||
PumpEnactResult result = new PumpEnactResult();
|
public boolean highTempBasal(int percent) {
|
||||||
if (!isConnected()) return result;
|
return false;
|
||||||
MessageBase msg = null;
|
|
||||||
switch (type) {
|
|
||||||
case RecordTypes.RECORD_TYPE_ALARM:
|
|
||||||
msg = new MsgHistoryAlarm();
|
|
||||||
break;
|
|
||||||
case RecordTypes.RECORD_TYPE_BASALHOUR:
|
|
||||||
msg = new MsgHistoryBasalHour();
|
|
||||||
break;
|
|
||||||
case RecordTypes.RECORD_TYPE_BOLUS:
|
|
||||||
msg = new MsgHistoryBolus();
|
|
||||||
break;
|
|
||||||
case RecordTypes.RECORD_TYPE_CARBO:
|
|
||||||
msg = new MsgHistoryCarbo();
|
|
||||||
break;
|
|
||||||
case RecordTypes.RECORD_TYPE_DAILY:
|
|
||||||
msg = new MsgHistoryDailyInsulin();
|
|
||||||
break;
|
|
||||||
case RecordTypes.RECORD_TYPE_ERROR:
|
|
||||||
msg = new MsgHistoryError();
|
|
||||||
break;
|
|
||||||
case RecordTypes.RECORD_TYPE_GLUCOSE:
|
|
||||||
msg = new MsgHistoryGlucose();
|
|
||||||
break;
|
|
||||||
case RecordTypes.RECORD_TYPE_REFILL:
|
|
||||||
msg = new MsgHistoryRefill();
|
|
||||||
break;
|
|
||||||
case RecordTypes.RECORD_TYPE_SUSPEND:
|
|
||||||
msg = new MsgHistorySuspend();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
MsgHistoryDone done = new MsgHistoryDone();
|
|
||||||
mSerialIOThread.sendMessage(new MsgPCCommStart());
|
|
||||||
waitMsec(400);
|
|
||||||
mSerialIOThread.sendMessage(msg);
|
|
||||||
while (!done.received && mRfcommSocket.isConnected()) {
|
|
||||||
waitMsec(100);
|
|
||||||
}
|
|
||||||
waitMsec(200);
|
|
||||||
mSerialIOThread.sendMessage(new MsgPCCommStop());
|
|
||||||
result.success = true;
|
|
||||||
result.comment = "OK";
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean updateBasalsInPump(final Profile profile) {
|
public boolean updateBasalsInPump(final Profile profile) {
|
||||||
|
@ -471,13 +307,10 @@ public class DanaRKoreanExecutionService extends Service {
|
||||||
double[] basal = DanaRPump.buildDanaRProfileRecord(profile);
|
double[] basal = DanaRPump.buildDanaRProfileRecord(profile);
|
||||||
MsgSetSingleBasalProfile msgSet = new MsgSetSingleBasalProfile(basal);
|
MsgSetSingleBasalProfile msgSet = new MsgSetSingleBasalProfile(basal);
|
||||||
mSerialIOThread.sendMessage(msgSet);
|
mSerialIOThread.sendMessage(msgSet);
|
||||||
danaRPump.lastSettingsRead = new Date(0); // force read full settings
|
mDanaRPump.lastSettingsRead = 0; // force read full settings
|
||||||
getPumpStatus();
|
getPumpStatus();
|
||||||
MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING));
|
MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void waitMsec(long msecs) {
|
|
||||||
SystemClock.sleep(msecs);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -189,6 +189,8 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface,
|
||||||
pumpDescription.basalMinimumRate = 0.04d;
|
pumpDescription.basalMinimumRate = 0.04d;
|
||||||
|
|
||||||
pumpDescription.isRefillingCapable = true;
|
pumpDescription.isRefillingCapable = true;
|
||||||
|
|
||||||
|
pumpDescription.storesCarbInfo = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ServiceConnection mConnection = new ServiceConnection() {
|
private ServiceConnection mConnection = new ServiceConnection() {
|
||||||
|
@ -346,7 +348,7 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface,
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public ProfileStore getProfile() {
|
public ProfileStore getProfile() {
|
||||||
if (pump.lastSettingsRead.getTime() == 0)
|
if (pump.lastSettingsRead == 0)
|
||||||
return null; // no info now
|
return null; // no info now
|
||||||
return pump.createConvertedProfile();
|
return pump.createConvertedProfile();
|
||||||
}
|
}
|
||||||
|
@ -365,7 +367,7 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface,
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isInitialized() {
|
public boolean isInitialized() {
|
||||||
return pump.lastConnection.getTime() > 0 && pump.maxBasal > 0;
|
return pump.lastConnection > 0 && pump.maxBasal > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -436,7 +438,7 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface,
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Date lastDataTime() {
|
public Date lastDataTime() {
|
||||||
return pump.lastConnection;
|
return new Date(pump.lastConnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -475,9 +477,10 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface,
|
||||||
DetailedBolusInfoStorage.add(detailedBolusInfo); // will be picked up on reading history
|
DetailedBolusInfoStorage.add(detailedBolusInfo); // will be picked up on reading history
|
||||||
|
|
||||||
Treatment t = new Treatment();
|
Treatment t = new Treatment();
|
||||||
|
t.isSMB = detailedBolusInfo.isSMB;
|
||||||
boolean connectionOK = false;
|
boolean connectionOK = false;
|
||||||
if (detailedBolusInfo.insulin > 0 || carbs > 0)
|
if (detailedBolusInfo.insulin > 0 || carbs > 0)
|
||||||
connectionOK = danaRSService.bolus(detailedBolusInfo.insulin, (int) carbs, System.currentTimeMillis() + carbTime * 60 * 1000 + 1000, t); // +1000 to make the record different
|
connectionOK = danaRSService.bolus(detailedBolusInfo.insulin, (int) carbs, System.currentTimeMillis() + carbTime * 60 * 1000, t);
|
||||||
PumpEnactResult result = new PumpEnactResult();
|
PumpEnactResult result = new PumpEnactResult();
|
||||||
result.success = connectionOK;
|
result.success = connectionOK;
|
||||||
result.bolusDelivered = t.insulin;
|
result.bolusDelivered = t.insulin;
|
||||||
|
@ -751,7 +754,7 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface,
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JSONObject getJSONStatus() {
|
public JSONObject getJSONStatus() {
|
||||||
if (pump.lastConnection.getTime() + 5 * 60 * 1000L < System.currentTimeMillis()) {
|
if (pump.lastConnection + 5 * 60 * 1000L < System.currentTimeMillis()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
JSONObject pumpjson = new JSONObject();
|
JSONObject pumpjson = new JSONObject();
|
||||||
|
@ -810,19 +813,21 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface,
|
||||||
@Override
|
@Override
|
||||||
public String shortStatus(boolean veryShort) {
|
public String shortStatus(boolean veryShort) {
|
||||||
String ret = "";
|
String ret = "";
|
||||||
if (pump.lastConnection.getTime() != 0) {
|
if (pump.lastConnection != 0) {
|
||||||
Long agoMsec = System.currentTimeMillis() - pump.lastConnection.getTime();
|
Long agoMsec = System.currentTimeMillis() - pump.lastConnection;
|
||||||
int agoMin = (int) (agoMsec / 60d / 1000d);
|
int agoMin = (int) (agoMsec / 60d / 1000d);
|
||||||
ret += "LastConn: " + agoMin + " minago\n";
|
ret += "LastConn: " + agoMin + " minago\n";
|
||||||
}
|
}
|
||||||
if (pump.lastBolusTime.getTime() != 0) {
|
if (pump.lastBolusTime.getTime() != 0) {
|
||||||
ret += "LastBolus: " + DecimalFormatter.to2Decimal(pump.lastBolusAmount) + "U @" + android.text.format.DateFormat.format("HH:mm", pump.lastBolusTime) + "\n";
|
ret += "LastBolus: " + DecimalFormatter.to2Decimal(pump.lastBolusAmount) + "U @" + android.text.format.DateFormat.format("HH:mm", pump.lastBolusTime) + "\n";
|
||||||
}
|
}
|
||||||
if (MainApp.getConfigBuilder().isInHistoryRealTempBasalInProgress()) {
|
TemporaryBasal activeTemp = MainApp.getConfigBuilder().getRealTempBasalFromHistory(System.currentTimeMillis());
|
||||||
ret += "Temp: " + MainApp.getConfigBuilder().getRealTempBasalFromHistory(System.currentTimeMillis()).toStringFull() + "\n";
|
if (activeTemp != null) {
|
||||||
|
ret += "Temp: " + activeTemp.toStringFull() + "\n";
|
||||||
}
|
}
|
||||||
if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) {
|
ExtendedBolus activeExtendedBolus = MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis());
|
||||||
ret += "Extended: " + MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis()).toString() + "\n";
|
if (activeExtendedBolus != null) {
|
||||||
|
ret += "Extended: " + activeExtendedBolus.toString() + "\n";
|
||||||
}
|
}
|
||||||
if (!veryShort) {
|
if (!veryShort) {
|
||||||
ret += "TDD: " + DecimalFormatter.to0Decimal(pump.dailyTotalUnits) + " / " + pump.maxDailyTotalUnits + " U\n";
|
ret += "TDD: " + DecimalFormatter.to0Decimal(pump.dailyTotalUnits) + " / " + pump.maxDailyTotalUnits + " U\n";
|
||||||
|
|
|
@ -9,6 +9,7 @@ import java.util.Calendar;
|
||||||
import java.util.GregorianCalendar;
|
import java.util.GregorianCalendar;
|
||||||
|
|
||||||
import info.nightscout.androidaps.Config;
|
import info.nightscout.androidaps.Config;
|
||||||
|
import info.nightscout.utils.DateUtil;
|
||||||
|
|
||||||
public class DanaRS_Packet_APS_Set_Event_History extends DanaRS_Packet {
|
public class DanaRS_Packet_APS_Set_Event_History extends DanaRS_Packet {
|
||||||
private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_APS_Set_Event_History.class);
|
private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_APS_Set_Event_History.class);
|
||||||
|
@ -30,6 +31,8 @@ public class DanaRS_Packet_APS_Set_Event_History extends DanaRS_Packet {
|
||||||
this.time = time;
|
this.time = time;
|
||||||
this.param1 = param1;
|
this.param1 = param1;
|
||||||
this.param2 = param2;
|
this.param2 = param2;
|
||||||
|
if (Config.logDanaMessageDetail)
|
||||||
|
log.debug("Set history entry: " + DateUtil.dateAndTimeString(time) + " type: " + type + " param1: " + param1 + " param2: " + param2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -164,6 +164,8 @@ public class BLEComm {
|
||||||
scheduledDisconnection = null;
|
scheduledDisconnection = null;
|
||||||
|
|
||||||
if ((mBluetoothAdapter == null) || (mBluetoothGatt == null)) {
|
if ((mBluetoothAdapter == null) || (mBluetoothGatt == null)) {
|
||||||
|
log.debug("disconnect not possible: (mBluetoothAdapter == null) " + (mBluetoothAdapter == null));
|
||||||
|
log.debug("disconnect not possible: (mBluetoothGatt == null) " + (mBluetoothGatt == null));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setCharacteristicNotification(getUARTReadBTGattChar(), false);
|
setCharacteristicNotification(getUARTReadBTGattChar(), false);
|
||||||
|
@ -257,6 +259,8 @@ public class BLEComm {
|
||||||
log.debug("setCharacteristicNotification");
|
log.debug("setCharacteristicNotification");
|
||||||
if ((mBluetoothAdapter == null) || (mBluetoothGatt == null)) {
|
if ((mBluetoothAdapter == null) || (mBluetoothGatt == null)) {
|
||||||
log.debug("BluetoothAdapter not initialized_ERROR");
|
log.debug("BluetoothAdapter not initialized_ERROR");
|
||||||
|
isConnecting = false;
|
||||||
|
isConnected = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
|
mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
|
||||||
|
@ -266,20 +270,25 @@ public class BLEComm {
|
||||||
log.debug("readCharacteristic");
|
log.debug("readCharacteristic");
|
||||||
if ((mBluetoothAdapter == null) || (mBluetoothGatt == null)) {
|
if ((mBluetoothAdapter == null) || (mBluetoothGatt == null)) {
|
||||||
log.debug("BluetoothAdapter not initialized_ERROR");
|
log.debug("BluetoothAdapter not initialized_ERROR");
|
||||||
|
isConnecting = false;
|
||||||
|
isConnected = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mBluetoothGatt.readCharacteristic(characteristic);
|
mBluetoothGatt.readCharacteristic(characteristic);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeCharacteristic_NO_RESPONSE(final BluetoothGattCharacteristic characteristic, final byte[] data) {
|
public void writeCharacteristic_NO_RESPONSE(final BluetoothGattCharacteristic characteristic, final byte[] data) {
|
||||||
if ((mBluetoothAdapter == null) || (mBluetoothGatt == null)) {
|
|
||||||
log.debug("BluetoothAdapter not initialized_ERROR");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
new Thread(new Runnable() {
|
new Thread(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
SystemClock.sleep(WRITE_DELAY_MILLIS);
|
SystemClock.sleep(WRITE_DELAY_MILLIS);
|
||||||
|
|
||||||
|
if ((mBluetoothAdapter == null) || (mBluetoothGatt == null)) {
|
||||||
|
log.debug("BluetoothAdapter not initialized_ERROR");
|
||||||
|
isConnecting = false;
|
||||||
|
isConnected = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
characteristic.setValue(data);
|
characteristic.setValue(data);
|
||||||
characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
|
characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
|
||||||
log.debug("writeCharacteristic:" + DanaRS_Packet.toHexString(data));
|
log.debug("writeCharacteristic:" + DanaRS_Packet.toHexString(data));
|
||||||
|
@ -306,6 +315,8 @@ public class BLEComm {
|
||||||
log.debug("getSupportedGattServices");
|
log.debug("getSupportedGattServices");
|
||||||
if ((mBluetoothAdapter == null) || (mBluetoothGatt == null)) {
|
if ((mBluetoothAdapter == null) || (mBluetoothGatt == null)) {
|
||||||
log.debug("BluetoothAdapter not initialized_ERROR");
|
log.debug("BluetoothAdapter not initialized_ERROR");
|
||||||
|
isConnecting = false;
|
||||||
|
isConnected = false;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -131,8 +131,8 @@ public class DanaRSService extends Service {
|
||||||
MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingtempbasalstatus)));
|
MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingtempbasalstatus)));
|
||||||
bleComm.sendMessage(new DanaRS_Packet_Basal_Get_Temporary_Basal_State());
|
bleComm.sendMessage(new DanaRS_Packet_Basal_Get_Temporary_Basal_State());
|
||||||
|
|
||||||
Date now = new Date();
|
long now = System.currentTimeMillis();
|
||||||
if (danaRPump.lastSettingsRead.getTime() + 60 * 60 * 1000L < now.getTime() || !MainApp.getSpecificPlugin(DanaRSPlugin.class).isInitialized()) {
|
if (danaRPump.lastSettingsRead + 60 * 60 * 1000L < now || !MainApp.getSpecificPlugin(DanaRSPlugin.class).isInitialized()) {
|
||||||
MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingpumpsettings)));
|
MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingpumpsettings)));
|
||||||
bleComm.sendMessage(new DanaRS_Packet_General_Get_Shipping_Information()); // serial no
|
bleComm.sendMessage(new DanaRS_Packet_General_Get_Shipping_Information()); // serial no
|
||||||
bleComm.sendMessage(new DanaRS_Packet_General_Get_Pump_Check()); // firmware
|
bleComm.sendMessage(new DanaRS_Packet_General_Get_Pump_Check()); // firmware
|
||||||
|
@ -156,7 +156,6 @@ public class DanaRSService extends Service {
|
||||||
|
|
||||||
loadEvents();
|
loadEvents();
|
||||||
|
|
||||||
danaRPump.lastConnection = now;
|
|
||||||
MainApp.bus().post(new EventDanaRNewStatus());
|
MainApp.bus().post(new EventDanaRNewStatus());
|
||||||
MainApp.bus().post(new EventInitializationChanged());
|
MainApp.bus().post(new EventInitializationChanged());
|
||||||
NSUpload.uploadDeviceStatus();
|
NSUpload.uploadDeviceStatus();
|
||||||
|
@ -190,6 +189,7 @@ public class DanaRSService extends Service {
|
||||||
else
|
else
|
||||||
lastHistoryFetched = 0;
|
lastHistoryFetched = 0;
|
||||||
log.debug("Events loaded");
|
log.debug("Events loaded");
|
||||||
|
danaRPump.lastConnection = System.currentTimeMillis();
|
||||||
return new PumpEnactResult().success(true);
|
return new PumpEnactResult().success(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -357,7 +357,7 @@ public class DanaRSService extends Service {
|
||||||
bleComm.sendMessage(msgSet);
|
bleComm.sendMessage(msgSet);
|
||||||
DanaRS_Packet_Basal_Set_Profile_Number msgActivate = new DanaRS_Packet_Basal_Set_Profile_Number(0);
|
DanaRS_Packet_Basal_Set_Profile_Number msgActivate = new DanaRS_Packet_Basal_Set_Profile_Number(0);
|
||||||
bleComm.sendMessage(msgActivate);
|
bleComm.sendMessage(msgActivate);
|
||||||
danaRPump.lastSettingsRead = new Date(0); // force read full settings
|
danaRPump.lastSettingsRead = 0; // force read full settings
|
||||||
getPumpStatus();
|
getPumpStatus();
|
||||||
MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING));
|
MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING));
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -5,68 +5,31 @@ import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.ServiceConnection;
|
import android.content.ServiceConnection;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
|
|
||||||
import com.squareup.otto.Subscribe;
|
import com.squareup.otto.Subscribe;
|
||||||
|
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.BuildConfig;
|
|
||||||
import info.nightscout.androidaps.Config;
|
import info.nightscout.androidaps.Config;
|
||||||
import info.nightscout.androidaps.Constants;
|
|
||||||
import info.nightscout.androidaps.MainApp;
|
import info.nightscout.androidaps.MainApp;
|
||||||
import info.nightscout.androidaps.R;
|
import info.nightscout.androidaps.R;
|
||||||
import info.nightscout.androidaps.data.DetailedBolusInfo;
|
import info.nightscout.androidaps.data.DetailedBolusInfo;
|
||||||
import info.nightscout.androidaps.data.Profile;
|
|
||||||
import info.nightscout.androidaps.data.ProfileStore;
|
|
||||||
import info.nightscout.androidaps.data.PumpEnactResult;
|
import info.nightscout.androidaps.data.PumpEnactResult;
|
||||||
import info.nightscout.androidaps.db.ExtendedBolus;
|
|
||||||
import info.nightscout.androidaps.db.TemporaryBasal;
|
import info.nightscout.androidaps.db.TemporaryBasal;
|
||||||
import info.nightscout.androidaps.db.Treatment;
|
import info.nightscout.androidaps.db.Treatment;
|
||||||
import info.nightscout.androidaps.events.EventAppExit;
|
import info.nightscout.androidaps.events.EventAppExit;
|
||||||
import info.nightscout.androidaps.interfaces.ConstraintsInterface;
|
|
||||||
import info.nightscout.androidaps.interfaces.DanaRInterface;
|
|
||||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
|
||||||
import info.nightscout.androidaps.interfaces.ProfileInterface;
|
|
||||||
import info.nightscout.androidaps.interfaces.PumpDescription;
|
import info.nightscout.androidaps.interfaces.PumpDescription;
|
||||||
import info.nightscout.androidaps.interfaces.PumpInterface;
|
|
||||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||||
import info.nightscout.androidaps.plugins.ConfigBuilder.DetailedBolusInfoStorage;
|
import info.nightscout.androidaps.plugins.ConfigBuilder.DetailedBolusInfoStorage;
|
||||||
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
|
import info.nightscout.androidaps.plugins.PumpDanaR.AbstractDanaRPlugin;
|
||||||
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
|
|
||||||
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
|
|
||||||
import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin;
|
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.DanaRFragment;
|
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump;
|
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaRv2.services.DanaRv2ExecutionService;
|
import info.nightscout.androidaps.plugins.PumpDanaRv2.services.DanaRv2ExecutionService;
|
||||||
import info.nightscout.utils.DateUtil;
|
|
||||||
import info.nightscout.utils.DecimalFormatter;
|
|
||||||
import info.nightscout.utils.Round;
|
import info.nightscout.utils.Round;
|
||||||
import info.nightscout.utils.SP;
|
import info.nightscout.utils.SP;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by mike on 05.08.2016.
|
* Created by mike on 05.08.2016.
|
||||||
*/
|
*/
|
||||||
public class DanaRv2Plugin implements PluginBase, PumpInterface, DanaRInterface, ConstraintsInterface, ProfileInterface {
|
public class DanaRv2Plugin extends AbstractDanaRPlugin {
|
||||||
private static Logger log = LoggerFactory.getLogger(DanaRv2Plugin.class);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getFragmentClass() {
|
|
||||||
return DanaRFragment.class.getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean fragmentPumpEnabled = false;
|
|
||||||
private static boolean fragmentProfileEnabled = false;
|
|
||||||
private static boolean fragmentPumpVisible = true;
|
|
||||||
|
|
||||||
private static DanaRv2ExecutionService sExecutionService;
|
|
||||||
|
|
||||||
|
|
||||||
private static DanaRv2Plugin plugin = null;
|
private static DanaRv2Plugin plugin = null;
|
||||||
|
|
||||||
|
@ -76,11 +39,10 @@ public class DanaRv2Plugin implements PluginBase, PumpInterface, DanaRInterface,
|
||||||
return plugin;
|
return plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static DanaRPump pump = DanaRPump.getInstance();
|
|
||||||
|
|
||||||
private static PumpDescription pumpDescription = new PumpDescription();
|
|
||||||
|
|
||||||
private DanaRv2Plugin() {
|
private DanaRv2Plugin() {
|
||||||
|
log = LoggerFactory.getLogger(DanaRv2Plugin.class);
|
||||||
|
useExtendedBoluses = false;
|
||||||
|
|
||||||
Context context = MainApp.instance().getApplicationContext();
|
Context context = MainApp.instance().getApplicationContext();
|
||||||
Intent intent = new Intent(context, DanaRv2ExecutionService.class);
|
Intent intent = new Intent(context, DanaRv2ExecutionService.class);
|
||||||
context.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
|
context.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
|
||||||
|
@ -109,6 +71,8 @@ public class DanaRv2Plugin implements PluginBase, PumpInterface, DanaRInterface,
|
||||||
pumpDescription.basalMinimumRate = 0.04d;
|
pumpDescription.basalMinimumRate = 0.04d;
|
||||||
|
|
||||||
pumpDescription.isRefillingCapable = true;
|
pumpDescription.isRefillingCapable = true;
|
||||||
|
|
||||||
|
pumpDescription.storesCarbInfo = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ServiceConnection mConnection = new ServiceConnection() {
|
private ServiceConnection mConnection = new ServiceConnection() {
|
||||||
|
@ -132,78 +96,11 @@ public class DanaRv2Plugin implements PluginBase, PumpInterface, DanaRInterface,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Plugin base interface
|
// Plugin base interface
|
||||||
@Override
|
|
||||||
public int getType() {
|
|
||||||
return PluginBase.PUMP;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return MainApp.instance().getString(R.string.danarv2pump);
|
return MainApp.instance().getString(R.string.danarv2pump);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getNameShort() {
|
|
||||||
String name = MainApp.sResources.getString(R.string.danarpump_shortname);
|
|
||||||
if (!name.trim().isEmpty()) {
|
|
||||||
//only if translation exists
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
// use long name as fallback
|
|
||||||
return getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isEnabled(int type) {
|
|
||||||
if (type == PluginBase.PROFILE) return fragmentProfileEnabled && fragmentPumpEnabled;
|
|
||||||
else if (type == PluginBase.PUMP) return fragmentPumpEnabled;
|
|
||||||
else if (type == PluginBase.CONSTRAINTS) return fragmentPumpEnabled;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isVisibleInTabs(int type) {
|
|
||||||
if (type == PluginBase.PROFILE || type == PluginBase.CONSTRAINTS) return false;
|
|
||||||
else if (type == PluginBase.PUMP) return fragmentPumpVisible;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean canBeHidden(int type) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasFragment() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean showInList(int type) {
|
|
||||||
return type == PUMP;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
|
|
||||||
if (type == PluginBase.PROFILE)
|
|
||||||
fragmentProfileEnabled = fragmentEnabled;
|
|
||||||
else if (type == PluginBase.PUMP)
|
|
||||||
fragmentPumpEnabled = fragmentEnabled;
|
|
||||||
// if pump profile was enabled need to switch to another too
|
|
||||||
if (type == PluginBase.PUMP && !fragmentEnabled && fragmentProfileEnabled) {
|
|
||||||
setFragmentEnabled(PluginBase.PROFILE, false);
|
|
||||||
setFragmentVisible(PluginBase.PROFILE, false);
|
|
||||||
NSProfilePlugin.getPlugin().setFragmentEnabled(PluginBase.PROFILE, true);
|
|
||||||
NSProfilePlugin.getPlugin().setFragmentVisible(PluginBase.PROFILE, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setFragmentVisible(int type, boolean fragmentVisible) {
|
|
||||||
if (type == PluginBase.PUMP)
|
|
||||||
fragmentPumpVisible = fragmentVisible;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getPreferencesId() {
|
public int getPreferencesId() {
|
||||||
return R.xml.pref_danarv2;
|
return R.xml.pref_danarv2;
|
||||||
|
@ -216,86 +113,10 @@ public class DanaRv2Plugin implements PluginBase, PumpInterface, DanaRInterface,
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isInitialized() {
|
public boolean isInitialized() {
|
||||||
return pump.lastConnection.getTime() > 0 && pump.maxBasal > 0;
|
return pump.lastConnection > 0 && pump.maxBasal > 0;
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSuspended() {
|
|
||||||
return pump.pumpSuspended;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isBusy() {
|
|
||||||
if (sExecutionService == null) return false;
|
|
||||||
return sExecutionService.isConnected() || sExecutionService.isConnecting();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pump interface
|
// Pump interface
|
||||||
@Override
|
|
||||||
public PumpEnactResult setNewBasalProfile(Profile profile) {
|
|
||||||
PumpEnactResult result = new PumpEnactResult();
|
|
||||||
|
|
||||||
if (sExecutionService == null) {
|
|
||||||
log.error("setNewBasalProfile sExecutionService is null");
|
|
||||||
result.comment = "setNewBasalProfile sExecutionService is null";
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
if (!isInitialized()) {
|
|
||||||
log.error("setNewBasalProfile not initialized");
|
|
||||||
Notification notification = new Notification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED, MainApp.sResources.getString(R.string.pumpNotInitializedProfileNotSet), Notification.URGENT);
|
|
||||||
MainApp.bus().post(new EventNewNotification(notification));
|
|
||||||
result.comment = MainApp.sResources.getString(R.string.pumpNotInitializedProfileNotSet);
|
|
||||||
return result;
|
|
||||||
} else {
|
|
||||||
MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED));
|
|
||||||
}
|
|
||||||
if (!sExecutionService.updateBasalsInPump(profile)) {
|
|
||||||
Notification notification = new Notification(Notification.FAILED_UDPATE_PROFILE, MainApp.sResources.getString(R.string.failedupdatebasalprofile), Notification.URGENT);
|
|
||||||
MainApp.bus().post(new EventNewNotification(notification));
|
|
||||||
result.comment = MainApp.sResources.getString(R.string.failedupdatebasalprofile);
|
|
||||||
return result;
|
|
||||||
} else {
|
|
||||||
MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED));
|
|
||||||
MainApp.bus().post(new EventDismissNotification(Notification.FAILED_UDPATE_PROFILE));
|
|
||||||
Notification notification = new Notification(Notification.PROFILE_SET_OK, MainApp.sResources.getString(R.string.profile_set_ok), Notification.INFO, 60);
|
|
||||||
MainApp.bus().post(new EventNewNotification(notification));
|
|
||||||
result.success = true;
|
|
||||||
result.enacted = true;
|
|
||||||
result.comment = "OK";
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isThisProfileSet(Profile profile) {
|
|
||||||
if (!isInitialized())
|
|
||||||
return true; // TODO: not sure what's better. so far TRUE to prevent too many SMS
|
|
||||||
if (pump.pumpProfiles == null)
|
|
||||||
return true; // TODO: not sure what's better. so far TRUE to prevent too many SMS
|
|
||||||
int basalValues = pump.basal48Enable ? 48 : 24;
|
|
||||||
int basalIncrement = pump.basal48Enable ? 30 * 60 : 60 * 60;
|
|
||||||
for (int h = 0; h < basalValues; h++) {
|
|
||||||
Double pumpValue = pump.pumpProfiles[pump.activeProfile][h];
|
|
||||||
Double profileValue = profile.getBasal((Integer) (h * basalIncrement));
|
|
||||||
if (profileValue == null) return true;
|
|
||||||
if (Math.abs(pumpValue - profileValue) > getPumpDescription().basalStep) {
|
|
||||||
log.debug("Diff found. Hour: " + h + " Pump: " + pumpValue + " Profile: " + profileValue);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Date lastDataTime() {
|
|
||||||
return pump.lastConnection;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public double getBaseBasalRate() {
|
|
||||||
return pump.currentBasal;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo) {
|
public PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo) {
|
||||||
ConfigBuilderPlugin configBuilderPlugin = MainApp.getConfigBuilder();
|
ConfigBuilderPlugin configBuilderPlugin = MainApp.getConfigBuilder();
|
||||||
|
@ -327,9 +148,10 @@ public class DanaRv2Plugin implements PluginBase, PumpInterface, DanaRInterface,
|
||||||
DetailedBolusInfoStorage.add(detailedBolusInfo); // will be picked up on reading history
|
DetailedBolusInfoStorage.add(detailedBolusInfo); // will be picked up on reading history
|
||||||
|
|
||||||
Treatment t = new Treatment();
|
Treatment t = new Treatment();
|
||||||
|
t.isSMB = detailedBolusInfo.isSMB;
|
||||||
boolean connectionOK = false;
|
boolean connectionOK = false;
|
||||||
if (detailedBolusInfo.insulin > 0 || carbs > 0)
|
if (detailedBolusInfo.insulin > 0 || carbs > 0)
|
||||||
connectionOK = sExecutionService.bolus(detailedBolusInfo.insulin, (int) carbs, System.currentTimeMillis() + carbTime * 60 * 1000 + 1000, t); // +1000 to make the record different
|
connectionOK = sExecutionService.bolus(detailedBolusInfo.insulin, (int) carbs, System.currentTimeMillis() + carbTime * 60 * 1000, t);
|
||||||
PumpEnactResult result = new PumpEnactResult();
|
PumpEnactResult result = new PumpEnactResult();
|
||||||
result.success = connectionOK;
|
result.success = connectionOK;
|
||||||
result.bolusDelivered = t.insulin;
|
result.bolusDelivered = t.insulin;
|
||||||
|
@ -511,49 +333,6 @@ public class DanaRv2Plugin implements PluginBase, PumpInterface, DanaRInterface,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes) {
|
|
||||||
ConfigBuilderPlugin configBuilderPlugin = MainApp.getConfigBuilder();
|
|
||||||
insulin = configBuilderPlugin.applyBolusConstraints(insulin);
|
|
||||||
// needs to be rounded
|
|
||||||
int durationInHalfHours = Math.max(durationInMinutes / 30, 1);
|
|
||||||
insulin = Round.roundTo(insulin, getPumpDescription().extendedBolusStep);
|
|
||||||
|
|
||||||
PumpEnactResult result = new PumpEnactResult();
|
|
||||||
ExtendedBolus runningEB = MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis());
|
|
||||||
if (runningEB != null && Math.abs(runningEB.insulin - insulin) < getPumpDescription().extendedBolusStep) {
|
|
||||||
result.enacted = false;
|
|
||||||
result.success = true;
|
|
||||||
result.comment = MainApp.instance().getString(R.string.virtualpump_resultok);
|
|
||||||
result.duration = pump.extendedBolusRemainingMinutes;
|
|
||||||
result.absolute = pump.extendedBolusAbsoluteRate;
|
|
||||||
result.isPercent = false;
|
|
||||||
result.isTempCancel = false;
|
|
||||||
if (Config.logPumpActions)
|
|
||||||
log.debug("setExtendedBolus: Correct extended bolus already set. Current: " + pump.extendedBolusAmount + " Asked: " + insulin);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
boolean connectionOK = sExecutionService.extendedBolus(insulin, durationInHalfHours);
|
|
||||||
if (connectionOK && pump.isExtendedInProgress && Math.abs(pump.extendedBolusAmount - insulin) < getPumpDescription().extendedBolusStep) {
|
|
||||||
result.enacted = true;
|
|
||||||
result.success = true;
|
|
||||||
result.comment = MainApp.instance().getString(R.string.virtualpump_resultok);
|
|
||||||
result.isTempCancel = false;
|
|
||||||
result.duration = pump.extendedBolusRemainingMinutes;
|
|
||||||
result.absolute = pump.extendedBolusAbsoluteRate;
|
|
||||||
result.bolusDelivered = pump.extendedBolusAmount;
|
|
||||||
result.isPercent = false;
|
|
||||||
if (Config.logPumpActions)
|
|
||||||
log.debug("setExtendedBolus: OK");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
result.enacted = false;
|
|
||||||
result.success = false;
|
|
||||||
result.comment = MainApp.instance().getString(R.string.danar_valuenotsetproperly);
|
|
||||||
log.error("setExtendedBolus: Failed to extended bolus");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PumpEnactResult cancelTempBasal(boolean force) {
|
public PumpEnactResult cancelTempBasal(boolean force) {
|
||||||
PumpEnactResult result = new PumpEnactResult();
|
PumpEnactResult result = new PumpEnactResult();
|
||||||
|
@ -579,257 +358,8 @@ public class DanaRv2Plugin implements PluginBase, PumpInterface, DanaRInterface,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public PumpEnactResult cancelExtendedBolus() {
|
|
||||||
PumpEnactResult result = new PumpEnactResult();
|
|
||||||
ExtendedBolus runningEB = MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis());
|
|
||||||
if (runningEB != null) {
|
|
||||||
sExecutionService.extendedBolusStop();
|
|
||||||
result.enacted = true;
|
|
||||||
result.isTempCancel = true;
|
|
||||||
}
|
|
||||||
if (!pump.isExtendedInProgress) {
|
|
||||||
result.success = true;
|
|
||||||
result.comment = MainApp.instance().getString(R.string.virtualpump_resultok);
|
|
||||||
if (Config.logPumpActions)
|
|
||||||
log.debug("cancelExtendedBolus: OK");
|
|
||||||
return result;
|
|
||||||
} else {
|
|
||||||
result.success = false;
|
|
||||||
result.comment = MainApp.instance().getString(R.string.danar_valuenotsetproperly);
|
|
||||||
log.error("cancelExtendedBolus: Failed to cancel extended bolus");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void connect(String from) {
|
|
||||||
if (sExecutionService != null) {
|
|
||||||
sExecutionService.connect(from);
|
|
||||||
pumpDescription.basalStep = pump.basalStep;
|
|
||||||
pumpDescription.bolusStep = pump.bolusStep;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isConnected() {
|
|
||||||
return sExecutionService != null && sExecutionService.isConnected();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isConnecting() {
|
|
||||||
return sExecutionService != null && sExecutionService.isConnecting();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void disconnect(String from) {
|
|
||||||
if (sExecutionService != null) sExecutionService.disconnect(from);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void stopConnecting() {
|
|
||||||
if (sExecutionService != null) sExecutionService.stopConnecting();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void getPumpStatus() {
|
|
||||||
if (sExecutionService != null) sExecutionService.getPumpStatus();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public JSONObject getJSONStatus() {
|
|
||||||
if (pump.lastConnection.getTime() + 5 * 60 * 1000L < System.currentTimeMillis()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
JSONObject pumpjson = new JSONObject();
|
|
||||||
JSONObject battery = new JSONObject();
|
|
||||||
JSONObject status = new JSONObject();
|
|
||||||
JSONObject extended = new JSONObject();
|
|
||||||
try {
|
|
||||||
battery.put("percent", pump.batteryRemaining);
|
|
||||||
status.put("status", pump.pumpSuspended ? "suspended" : "normal");
|
|
||||||
status.put("timestamp", DateUtil.toISOString(pump.lastConnection));
|
|
||||||
extended.put("Version", BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION);
|
|
||||||
extended.put("PumpIOB", pump.iob);
|
|
||||||
if (pump.lastBolusTime.getTime() != 0) {
|
|
||||||
extended.put("LastBolus", pump.lastBolusTime.toLocaleString());
|
|
||||||
extended.put("LastBolusAmount", pump.lastBolusAmount);
|
|
||||||
}
|
|
||||||
TemporaryBasal tb = MainApp.getConfigBuilder().getTempBasalFromHistory(System.currentTimeMillis());
|
|
||||||
if (tb != null) {
|
|
||||||
extended.put("TempBasalAbsoluteRate", tb.tempBasalConvertedToAbsolute(System.currentTimeMillis()));
|
|
||||||
extended.put("TempBasalStart", DateUtil.dateAndTimeString(tb.date));
|
|
||||||
extended.put("TempBasalRemaining", tb.getPlannedRemainingMinutes());
|
|
||||||
}
|
|
||||||
ExtendedBolus eb = MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis());
|
|
||||||
if (eb != null) {
|
|
||||||
extended.put("ExtendedBolusAbsoluteRate", eb.absoluteRate());
|
|
||||||
extended.put("ExtendedBolusStart", DateUtil.dateAndTimeString(eb.date));
|
|
||||||
extended.put("ExtendedBolusRemaining", eb.getPlannedRemainingMinutes());
|
|
||||||
}
|
|
||||||
extended.put("BaseBasalRate", getBaseBasalRate());
|
|
||||||
try {
|
|
||||||
extended.put("ActiveProfile", MainApp.getConfigBuilder().getProfileName());
|
|
||||||
} catch (Exception e) {
|
|
||||||
}
|
|
||||||
|
|
||||||
pumpjson.put("battery", battery);
|
|
||||||
pumpjson.put("status", status);
|
|
||||||
pumpjson.put("extended", extended);
|
|
||||||
pumpjson.put("reservoir", (int) pump.reservoirRemainingUnits);
|
|
||||||
pumpjson.put("clock", DateUtil.toISOString(new Date()));
|
|
||||||
} catch (JSONException e) {
|
|
||||||
log.error("Unhandled exception", e);
|
|
||||||
}
|
|
||||||
return pumpjson;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String deviceID() {
|
|
||||||
return pump.serialNumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PumpDescription getPumpDescription() {
|
|
||||||
return pumpDescription;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DanaR interface
|
|
||||||
*/
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PumpEnactResult loadHistory(byte type) {
|
|
||||||
return sExecutionService.loadHistory(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PumpEnactResult loadEvents() {
|
public PumpEnactResult loadEvents() {
|
||||||
return sExecutionService.loadEvents();
|
return sExecutionService.loadEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Constraint interface
|
|
||||||
*/
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isLoopEnabled() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isClosedModeEnabled() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isAutosensModeEnabled() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isAMAModeEnabled() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSMBModeEnabled() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("PointlessBooleanExpression")
|
|
||||||
@Override
|
|
||||||
public Double applyBasalConstraints(Double absoluteRate) {
|
|
||||||
double origAbsoluteRate = absoluteRate;
|
|
||||||
if (pump != null) {
|
|
||||||
if (absoluteRate > pump.maxBasal) {
|
|
||||||
absoluteRate = pump.maxBasal;
|
|
||||||
if (Config.logConstraintsChanges && origAbsoluteRate != Constants.basalAbsoluteOnlyForCheckLimit)
|
|
||||||
log.debug("Limiting rate " + origAbsoluteRate + "U/h by pump constraint to " + absoluteRate + "U/h");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return absoluteRate;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("PointlessBooleanExpression")
|
|
||||||
@Override
|
|
||||||
public Integer applyBasalConstraints(Integer percentRate) {
|
|
||||||
Integer origPercentRate = percentRate;
|
|
||||||
if (percentRate < 0) percentRate = 0;
|
|
||||||
if (percentRate > getPumpDescription().maxTempPercent)
|
|
||||||
percentRate = getPumpDescription().maxTempPercent;
|
|
||||||
if (!Objects.equals(percentRate, origPercentRate) && Config.logConstraintsChanges && !Objects.equals(origPercentRate, Constants.basalPercentOnlyForCheckLimit))
|
|
||||||
log.debug("Limiting percent rate " + origPercentRate + "% to " + percentRate + "%");
|
|
||||||
return percentRate;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("PointlessBooleanExpression")
|
|
||||||
@Override
|
|
||||||
public Double applyBolusConstraints(Double insulin) {
|
|
||||||
double origInsulin = insulin;
|
|
||||||
if (pump != null) {
|
|
||||||
if (insulin > pump.maxBolus) {
|
|
||||||
insulin = pump.maxBolus;
|
|
||||||
if (Config.logConstraintsChanges && origInsulin != Constants.bolusOnlyForCheckLimit)
|
|
||||||
log.debug("Limiting bolus " + origInsulin + "U by pump constraint to " + insulin + "U");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return insulin;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Integer applyCarbsConstraints(Integer carbs) {
|
|
||||||
return carbs;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Double applyMaxIOBConstraints(Double maxIob) {
|
|
||||||
return maxIob;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public ProfileStore getProfile() {
|
|
||||||
if (pump.lastSettingsRead.getTime() == 0)
|
|
||||||
return null; // no info now
|
|
||||||
return pump.createConvertedProfile();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getUnits() {
|
|
||||||
return pump.getUnits();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getProfileName() {
|
|
||||||
return pump.createConvertedProfileName();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reply for sms communicator
|
|
||||||
public String shortStatus(boolean veryShort) {
|
|
||||||
String ret = "";
|
|
||||||
if (pump.lastConnection.getTime() != 0) {
|
|
||||||
Long agoMsec = System.currentTimeMillis() - pump.lastConnection.getTime();
|
|
||||||
int agoMin = (int) (agoMsec / 60d / 1000d);
|
|
||||||
ret += "LastConn: " + agoMin + " minago\n";
|
|
||||||
}
|
|
||||||
if (pump.lastBolusTime.getTime() != 0) {
|
|
||||||
ret += "LastBolus: " + DecimalFormatter.to2Decimal(pump.lastBolusAmount) + "U @" + android.text.format.DateFormat.format("HH:mm", pump.lastBolusTime) + "\n";
|
|
||||||
}
|
|
||||||
if (MainApp.getConfigBuilder().isInHistoryRealTempBasalInProgress()) {
|
|
||||||
ret += "Temp: " + MainApp.getConfigBuilder().getTempBasalFromHistory(System.currentTimeMillis()).toStringFull() + "\n";
|
|
||||||
}
|
|
||||||
if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) {
|
|
||||||
ret += "Extended: " + MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis()).toString() + "\n";
|
|
||||||
}
|
|
||||||
if (!veryShort) {
|
|
||||||
ret += "TDD: " + DecimalFormatter.to0Decimal(pump.dailyTotalUnits) + " / " + pump.maxDailyTotalUnits + " U\n";
|
|
||||||
}
|
|
||||||
ret += "IOB: " + pump.iob + "U\n";
|
|
||||||
ret += "Reserv: " + DecimalFormatter.to0Decimal(pump.reservoirRemainingUnits) + "U\n";
|
|
||||||
ret += "Batt: " + pump.batteryRemaining + "\n";
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
// TODO: daily total constraint
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,13 +13,14 @@ import java.io.OutputStream;
|
||||||
import info.nightscout.androidaps.Config;
|
import info.nightscout.androidaps.Config;
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump;
|
import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump;
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase;
|
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase;
|
||||||
|
import info.nightscout.androidaps.plugins.PumpDanaR.services.AbstractSerialIOThread;
|
||||||
import info.nightscout.androidaps.plugins.PumpDanaRv2.comm.MessageHashTable_v2;
|
import info.nightscout.androidaps.plugins.PumpDanaRv2.comm.MessageHashTable_v2;
|
||||||
import info.nightscout.utils.CRC;
|
import info.nightscout.utils.CRC;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by mike on 17.07.2016.
|
* Created by mike on 17.07.2016.
|
||||||
*/
|
*/
|
||||||
public class SerialIOThread extends Thread {
|
public class SerialIOThread extends AbstractSerialIOThread {
|
||||||
private static Logger log = LoggerFactory.getLogger(SerialIOThread.class);
|
private static Logger log = LoggerFactory.getLogger(SerialIOThread.class);
|
||||||
|
|
||||||
private InputStream mInputStream = null;
|
private InputStream mInputStream = null;
|
||||||
|
@ -29,10 +30,10 @@ public class SerialIOThread extends Thread {
|
||||||
private boolean mKeepRunning = true;
|
private boolean mKeepRunning = true;
|
||||||
private byte[] mReadBuff = new byte[0];
|
private byte[] mReadBuff = new byte[0];
|
||||||
|
|
||||||
MessageBase processedMessage;
|
private MessageBase processedMessage;
|
||||||
|
|
||||||
public SerialIOThread(BluetoothSocket rfcommSocket) {
|
public SerialIOThread(BluetoothSocket rfcommSocket) {
|
||||||
super(SerialIOThread.class.toString());
|
super();
|
||||||
|
|
||||||
mRfCommSocket = rfcommSocket;
|
mRfCommSocket = rfcommSocket;
|
||||||
try {
|
try {
|
||||||
|
@ -138,6 +139,7 @@ public class SerialIOThread extends Thread {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public synchronized void sendMessage(MessageBase message) {
|
public synchronized void sendMessage(MessageBase message) {
|
||||||
if (!mRfCommSocket.isConnected()) {
|
if (!mRfCommSocket.isConnected()) {
|
||||||
log.error("Socket not connected on sendMessage");
|
log.error("Socket not connected on sendMessage");
|
||||||
|
@ -173,6 +175,7 @@ public class SerialIOThread extends Thread {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void disconnect(String reason) {
|
public void disconnect(String reason) {
|
||||||
mKeepRunning = false;
|
mKeepRunning = false;
|
||||||
try {
|
try {
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue