Merge commit 'origin/dev^' into combo-dev-merge

* commit 'origin/dev^': (313 commits)
  cleanup
  draw profile in dana profile viewer
  optimize imports
  draw basal in profile viewer
  BG autobackfill configurable
  travis 2nd try
  Save new profile when updating it
  Add environment variable to handle testCoverage
  do not pass DIA to SMB determine_basal
  show Dana model properly after communication error
  fix deviation slope calculations
  Read maximum basal and bolus amount from pump
  update maxIOB hard limits
  Allow bolus record only in new treatment dialog
  use safeGetString
  JsonHelper test
  food code cleanup
  Show bolus progress
  Missing import statement
  Insight: add treatment to progress event
  ...
This commit is contained in:
Johannes Mockenhaupt 2018-03-16 15:44:54 +01:00
commit db00404e43
No known key found for this signature in database
GPG key ID: 9E1EA6AF7BBBB0D1
245 changed files with 12776 additions and 3022 deletions

1
.gitignore vendored
View file

@ -7,3 +7,4 @@
*.apk
build/
.idea/
app/src/main/jniLibs

View file

@ -18,7 +18,7 @@ before_install:
script:
# Unit Test
- ./gradlew test jacocoTestReport
- ./gradlew -Pcoverage test jacocoTestReport
after_success:
- bash <(curl -s https://codecov.io/bash)

View file

@ -57,7 +57,7 @@ android {
targetSdkVersion 23
multiDexEnabled true
versionCode 1500
version "1.58-combo-phantom-fusion"
version "1.59-dev"
buildConfigField "String", "VERSION", '"' + version + '"'
buildConfigField "String", "BUILDVERSION", generateGitBuild()
@ -82,7 +82,7 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
testCoverageEnabled true
testCoverageEnabled (project.hasProperty('coverage') ? true : false)
}
}
productFlavors {
@ -187,6 +187,7 @@ dependencies {
compile("com.crashlytics.sdk.android:answers:1.3.12@aar") {
transitive = true;
}
compile 'MilosKozak:danars-support-lib:master@zip'
compile "com.android.support:appcompat-v7:${supportLibraryVersion}"
compile "com.android.support:support-v4:${supportLibraryVersion}"
@ -196,6 +197,7 @@ dependencies {
compile "com.android.support:design:${supportLibraryVersion}"
compile "com.android.support:percent:${supportLibraryVersion}"
compile "com.wdullaer:materialdatetimepicker:2.3.0"
compile 'com.android.support.constraint:constraint-layout:1.0.2'
compile "com.squareup:otto:1.3.7"
compile "com.j256.ormlite:ormlite-core:${ormLiteVersion}"
compile "com.j256.ormlite:ormlite-android:${ormLiteVersion}"
@ -208,6 +210,8 @@ dependencies {
compile "com.joanzapata.iconify:android-iconify-fontawesome:2.1.1"
compile "com.google.android.gms:play-services-wearable:7.5.0"
compile(name: "android-edittext-validator-v1.3.4-mod", ext: "aar")
compile(name: "sightparser-release", ext: "aar")
compile("com.google.android:flexbox:0.3.0") {
exclude group: "com.android.support"
}
@ -220,6 +224,8 @@ dependencies {
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"
@ -231,8 +237,33 @@ dependencies {
testCompile "org.powermock:powermock-module-junit4-rule:${powermockVersion}"
testCompile "org.powermock:powermock-module-junit4:${powermockVersion}"
testCompile "joda-time:joda-time:2.9.4.2"
testCompile "com.google.truth:truth:0.39"
androidTestCompile "org.mockito:mockito-core:2.7.22"
androidTestCompile "com.google.dexmaker:dexmaker:${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.

Binary file not shown.

View file

@ -61,6 +61,7 @@
</intent-filter>
</activity>
<activity android:name=".plugins.PumpDanaRS.activities.PairingHelperActivity" />
<activity android:name=".HistoryBrowseActivity" />
<receiver
android:name=".receivers.DataReceiver"

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

File diff suppressed because it is too large Load diff

View file

@ -25,6 +25,8 @@ public class Config {
public static final boolean SMSCOMMUNICATORENABLED = !BuildConfig.NSCLIENTOLNY && !BuildConfig.G5UPLOADER;
public static final boolean displayDeviationSlope = true;
public static final boolean detailedLog = true;
public static final boolean logFunctionCalls = true;
public static final boolean logIncommingData = true;

View file

@ -33,20 +33,17 @@ public class Constants {
public static final int CPP_MIN_TIMESHIFT = -6;
public static final int CPP_MAX_TIMESHIFT = 23;
// Very Hard Limits Ranges
// First value is the Lowest and second value is the Highest a Limit can define
public static final int[] VERY_HARD_LIMIT_MIN_BG = {72,180};
public static final int[] VERY_HARD_LIMIT_MAX_BG = {90,270};
public static final int[] VERY_HARD_LIMIT_TARGET_BG = {80,200};
// Very Hard Limits Ranges for Temp Targets
public static final int[] VERY_HARD_LIMIT_TEMP_MIN_BG = {72,180};
public static final int[] VERY_HARD_LIMIT_TEMP_MAX_BG = {72,270};
public static final int[] VERY_HARD_LIMIT_TEMP_TARGET_BG = {72,200};
//DanaR
public static final double dailyLimitWarning = 0.95d;
// Temp targets
public static final int defaultActivityTTDuration = 90; // min
public static final double defaultActivityTTmgdl = 90d;
public static final double defaultActivityTTmmol = 5d;
public static final int defaultEatingSoonTTDuration = 45; // min
public static final double defaultEatingSoonTTmgdl = 140d;
public static final double defaultEatingSoonTTmmol = 8d;
//NSClientInternal
public static final int MAX_LOG_LINES = 100;

View file

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

View file

@ -39,13 +39,14 @@ import com.squareup.otto.Subscribe;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.Services.AlarmSoundService;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.events.EventAppExit;
import info.nightscout.androidaps.events.EventFeatureRunning;
import info.nightscout.androidaps.events.EventPreferenceChange;
import info.nightscout.androidaps.events.EventRefreshGui;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Food.FoodPlugin;
import info.nightscout.androidaps.plugins.Overview.events.EventSetWakeLock;
import info.nightscout.androidaps.tabs.SlidingTabLayout;
import info.nightscout.androidaps.tabs.TabPageAdapter;
@ -116,9 +117,9 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
runOnUiThread(new Runnable() {
@Override
public void run() {
if(ev.recreate) {
if (ev.recreate) {
recreate();
}else {
} else {
try { // activity may be destroyed
setUpTabs(true);
} catch (IllegalStateException e) {
@ -175,7 +176,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
// Added in 1.57 at 21.01.2018
Integer unreachable_threshold = SP.getInt(R.string.key_pump_unreachable_threshold, 30);
SP.remove(R.string.key_pump_unreachable_threshold);
if(unreachable_threshold < 30) unreachable_threshold = 30;
if (unreachable_threshold < 30) unreachable_threshold = 30;
SP.putString(R.string.key_pump_unreachable_threshold, unreachable_threshold.toString());
}
@ -226,6 +227,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
super.onResume();
askForSMSPermissions();
askForLocationPermissions();
MainApp.bus().post(new EventFeatureRunning(EventFeatureRunning.Feature.MAIN));
}
@Override
@ -362,6 +364,9 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
}
}, null);
break;
case R.id.nav_historybrowser:
startActivity(new Intent(v.getContext(), HistoryBrowseActivity.class));
break;
case R.id.nav_resetdb:
new AlertDialog.Builder(v.getContext())
.setTitle(R.string.nav_resetdb)
@ -371,6 +376,9 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
@Override
public void onClick(DialogInterface dialog, int which) {
MainApp.getDbHelper().resetDatabases();
// should be handled by Plugin-Interface and
// additional service interface and plugin registry
MainApp.getSpecificPlugin(FoodPlugin.class).getService().resetFood();
}
})
.create()
@ -390,7 +398,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
case R.id.nav_about:
AlertDialog.Builder builder = new AlertDialog.Builder(v.getContext());
builder.setTitle(getString(R.string.app_name) + " " + BuildConfig.VERSION);
if (Config.NSCLIENT|| Config.G5UPLOADER)
if (Config.NSCLIENT || Config.G5UPLOADER)
builder.setIcon(R.mipmap.yellowowl);
else
builder.setIcon(R.mipmap.blueowl);

View file

@ -44,9 +44,9 @@ import info.nightscout.androidaps.plugins.NSClientInternal.NSClientInternalPlugi
import info.nightscout.androidaps.plugins.NSClientInternal.receivers.AckAlarmReceiver;
import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin;
import info.nightscout.androidaps.plugins.OpenAPSMA.OpenAPSMAPlugin;
import info.nightscout.androidaps.plugins.OpenAPSSMB.OpenAPSSMBPlugin;
import info.nightscout.androidaps.plugins.Overview.OverviewPlugin;
import info.nightscout.androidaps.plugins.Persistentnotification.PersistentNotificationPlugin;
import info.nightscout.androidaps.plugins.ProfileCircadianPercentage.CircadianPercentageProfileFragment;
import info.nightscout.androidaps.plugins.ProfileLocal.LocalProfilePlugin;
import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin;
import info.nightscout.androidaps.plugins.ProfileSimple.SimpleProfilePlugin;
@ -55,6 +55,7 @@ import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin;
import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin;
import info.nightscout.androidaps.plugins.PumpDanaRS.DanaRSPlugin;
import info.nightscout.androidaps.plugins.PumpDanaRv2.DanaRv2Plugin;
import info.nightscout.androidaps.plugins.PumpInsight.InsightPumpPlugin;
import info.nightscout.androidaps.plugins.PumpMDI.MDIPlugin;
import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin;
import info.nightscout.androidaps.plugins.SensitivityAAPS.SensitivityAAPSPlugin;
@ -72,6 +73,7 @@ import info.nightscout.androidaps.plugins.XDripStatusline.StatuslinePlugin;
import info.nightscout.androidaps.receivers.DataReceiver;
import info.nightscout.androidaps.receivers.KeepAliveReceiver;
import info.nightscout.androidaps.receivers.NSAlarmReceiver;
import info.nightscout.utils.FabricPrivacy;
import info.nightscout.utils.NSUpload;
import io.fabric.sdk.android.Fabric;
@ -97,18 +99,26 @@ public class MainApp extends Application {
@Override
public void onCreate() {
super.onCreate();
Fabric.with(this, new Crashlytics());
Fabric.with(this, new Answers());
sInstance = this;
sResources = getResources();
try {
if (FabricPrivacy.fabricEnabled()) {
Fabric.with(this, new Crashlytics());
Fabric.with(this, new Answers());
Crashlytics.setString("BUILDVERSION", BuildConfig.BUILDVERSION);
}
} catch (Exception e) {
android.util.Log.e("ANDROIDAPS", "Error with Fabric init! " + e);
}
JodaTimeAndroid.init(this);
Crashlytics.setString("BUILDVERSION", BuildConfig.BUILDVERSION);
log.info("Version: " + BuildConfig.VERSION_NAME);
log.info("BuildVersion: " + BuildConfig.BUILDVERSION);
sBus = Config.logEvents ? new LoggingBus(ThreadEnforcer.ANY) : new Bus(ThreadEnforcer.ANY);
sInstance = this;
sResources = getResources();
registerLocalBroadcastReceiver();
if (pluginsList == null) {
@ -131,16 +141,16 @@ public class MainApp extends Application {
if (Config.DANAR) pluginsList.add(DanaRSPlugin.getPlugin());
if (Config.COMBO) pluginsList.add(ComboPlugin.getPlugin());
pluginsList.add(CareportalPlugin.getPlugin());
// if (Config.DANAR) pluginsList.add(InsightPumpPlugin.getPlugin()); // <-- Enable Insight plugin here
if (Config.MDI) pluginsList.add(MDIPlugin.getPlugin());
if (Config.VIRTUALPUMP) pluginsList.add(VirtualPumpPlugin.getPlugin());
if (Config.APS) pluginsList.add(LoopPlugin.getPlugin());
if (Config.APS) pluginsList.add(OpenAPSMAPlugin.getPlugin());
if (Config.APS) pluginsList.add(OpenAPSAMAPlugin.getPlugin());
if (Config.APS) pluginsList.add(OpenAPSSMBPlugin.getPlugin());
pluginsList.add(NSProfilePlugin.getPlugin());
if (Config.OTHERPROFILES) pluginsList.add(SimpleProfilePlugin.getPlugin());
if (Config.OTHERPROFILES) pluginsList.add(LocalProfilePlugin.getPlugin());
if (Config.OTHERPROFILES)
pluginsList.add(CircadianPercentageProfileFragment.getPlugin());
pluginsList.add(TreatmentsPlugin.getPlugin());
if (Config.SAFETY) pluginsList.add(SafetyPlugin.getPlugin());
if (Config.APS) pluginsList.add(ObjectivesPlugin.getPlugin());
@ -168,15 +178,15 @@ public class MainApp extends Application {
}
NSUpload.uploadAppStart();
if (Config.NSCLIENT)
Answers.getInstance().logCustom(new CustomEvent("AppStart-NSClient"));
FabricPrivacy.getInstance().logCustom(new CustomEvent("AppStart-NSClient"));
else if (Config.G5UPLOADER)
Answers.getInstance().logCustom(new CustomEvent("AppStart-G5Uploader"));
FabricPrivacy.getInstance().logCustom(new CustomEvent("AppStart-G5Uploader"));
else if (Config.PUMPCONTROL)
Answers.getInstance().logCustom(new CustomEvent("AppStart-PumpControl"));
FabricPrivacy.getInstance().logCustom(new CustomEvent("AppStart-PumpControl"));
else if (MainApp.getConfigBuilder().isClosedModeEnabled())
Answers.getInstance().logCustom(new CustomEvent("AppStart-ClosedLoop"));
FabricPrivacy.getInstance().logCustom(new CustomEvent("AppStart-ClosedLoop"));
else
Answers.getInstance().logCustom(new CustomEvent("AppStart-OpenLoop"));
FabricPrivacy.getInstance().logCustom(new CustomEvent("AppStart-OpenLoop"));
new Thread(new Runnable() {
@Override
@ -239,6 +249,10 @@ public class MainApp extends Application {
return sResources.getString(id, args);
}
public static int gc(int id) {
return sResources.getColor(id);
}
public static MainApp instance() {
return sInstance;
}

View file

@ -15,6 +15,7 @@ import android.text.TextUtils;
import info.nightscout.androidaps.events.EventPreferenceChange;
import info.nightscout.androidaps.events.EventRefreshGui;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.plugins.OpenAPSSMB.OpenAPSSMBPlugin;
import info.nightscout.androidaps.plugins.Careportal.CareportalPlugin;
import info.nightscout.androidaps.plugins.ConstraintsSafety.SafetyPlugin;
import info.nightscout.androidaps.plugins.Insulin.InsulinOrefFreePeakPlugin;
@ -129,6 +130,8 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
addPreferencesFromResource(id);
addPreferencesFromResource(R.xml.pref_advanced);
} else {
addPreferencesFromResource(R.xml.pref_overview);
if (!Config.NSCLIENT && !Config.G5UPLOADER) {
addPreferencesFromResource(R.xml.pref_password);
}
@ -145,6 +148,7 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
addPreferencesFromResourceIfEnabled(LoopPlugin.getPlugin(), PluginBase.LOOP);
addPreferencesFromResourceIfEnabled(OpenAPSMAPlugin.getPlugin(), PluginBase.APS);
addPreferencesFromResourceIfEnabled(OpenAPSAMAPlugin.getPlugin(), PluginBase.APS);
addPreferencesFromResourceIfEnabled(OpenAPSSMBPlugin.getPlugin(), PluginBase.APS);
}
addPreferencesFromResourceIfEnabled(SensitivityAAPSPlugin.getPlugin(), PluginBase.SENSITIVITY);

View file

@ -1,8 +1,10 @@
package info.nightscout.androidaps.Services;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.res.AssetFileDescriptor;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.IBinder;
@ -53,7 +55,10 @@ public class AlarmSoundService extends Service {
log.error("Unhandled exception", e);
}
player.setLooping(true); // Set looping
player.setVolume(100, 100);
AudioManager manager = (AudioManager)this.getSystemService(Context.AUDIO_SERVICE);
if (manager == null || !manager.isMusicActive()) {
player.setVolume(100, 100);
}
try {
player.prepare();

View file

@ -19,6 +19,7 @@ import info.nightscout.androidaps.data.ProfileStore;
import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.events.EventNewBasalProfile;
import info.nightscout.androidaps.events.EventNsFood;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.ConstraintsObjectives.ObjectivesPlugin;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSDeviceStatus;
@ -123,8 +124,8 @@ public class DataService extends IntentService {
handleNewDataFromDexcomG5(intent);
}
} else if (Intents.ACTION_NEW_SGV.equals(action)) {
// always backfill SGV from NS
handleNewDataFromNSClient(intent);
if (nsClientEnabled || SP.getBoolean(R.string.ns_autobackfill, true))
handleNewDataFromNSClient(intent);
// Objectives 0
ObjectivesPlugin.bgIsAvailableInNS = true;
ObjectivesPlugin.saveProgress();
@ -474,57 +475,19 @@ public class DataService extends IntentService {
}
}
if (intent.getAction().equals(Intents.ACTION_NEW_FOOD) || intent.getAction().equals(Intents.ACTION_CHANGED_FOOD)) {
try {
if (bundles.containsKey("food")) {
String trstring = bundles.getString("food");
handleAddChangeFoodRecord(new JSONObject(trstring));
}
if (bundles.containsKey("foods")) {
String trstring = bundles.getString("foods");
JSONArray jsonArray = new JSONArray(trstring);
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject trJson = jsonArray.getJSONObject(i);
handleAddChangeFoodRecord(trJson);
}
}
} catch (Exception e) {
log.error("Unhandled exception", e);
}
if (intent.getAction().equals(Intents.ACTION_NEW_FOOD)
|| intent.getAction().equals(Intents.ACTION_CHANGED_FOOD)) {
int mode = Intents.ACTION_NEW_FOOD.equals(intent.getAction()) ? EventNsFood.ADD : EventNsFood.UPDATE;
EventNsFood evt = new EventNsFood(mode, bundles);
MainApp.bus().post(evt);
}
if (intent.getAction().equals(Intents.ACTION_REMOVED_FOOD)) {
try {
if (bundles.containsKey("food")) {
String trstring = bundles.getString("food");
JSONObject trJson = new JSONObject(trstring);
String _id = trJson.getString("_id");
handleRemovedFoodRecord(_id);
}
if (bundles.containsKey("foods")) {
String trstring = bundles.getString("foods");
JSONArray jsonArray = new JSONArray(trstring);
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject trJson = jsonArray.getJSONObject(i);
String _id = trJson.getString("_id");
handleRemovedFoodRecord(_id);
}
}
} catch (Exception e) {
log.error("Unhandled exception", e);
}
EventNsFood evt = new EventNsFood(EventNsFood.REMOVE, bundles);
MainApp.bus().post(evt);
}
}
private void handleRemovedFoodRecord(String _id) {
MainApp.getDbHelper().foodHelper.deleteFoodById(_id);
}
public void handleAddChangeFoodRecord(JSONObject trJson) throws JSONException {
MainApp.getDbHelper().foodHelper.createFoodFromJsonIfNotExists(trJson);
}
private void handleRemovedRecordFromNS(String _id) {
MainApp.getDbHelper().deleteTreatmentById(_id);
MainApp.getDbHelper().deleteTempTargetById(_id);

View file

@ -27,6 +27,7 @@ public class DetailedBolusInfo {
public Context context = null; // context for progress dialog
public long pumpId = 0; // id of record if comming from pump history (not a newly created treatment)
public boolean isSMB = false; // is a Super-MicroBolus
public long deliverAt = 0; // SMB should be delivered within 1 min from this time
public DetailedBolusInfo copy() {
DetailedBolusInfo copy = new DetailedBolusInfo();
@ -53,6 +54,7 @@ public class DetailedBolusInfo {
" carbs: " + carbs +
" isValid: " + isValid +
" carbTime: " + carbTime +
" isSMB: " + isSMB;
" isSMB: " + isSMB +
" deliverAt: " + new Date(deliverAt).toLocaleString();
}
}

View file

@ -35,6 +35,7 @@ public class GlucoseStatus {
public double avgdelta = 0d;
public double short_avgdelta = 0d;
public double long_avgdelta = 0d;
public long date = 0L;
@Override
@ -133,6 +134,7 @@ public class GlucoseStatus {
GlucoseStatus status = new GlucoseStatus();
status.glucose = now.value;
status.date = now_date;
status.short_avgdelta = average(short_deltas);

View file

@ -21,8 +21,11 @@ public class IobTotal {
public double hightempinsulin;
// oref1
public double microBolusInsulin;
public double microBolusIOB;
public long lastBolusTime;
public long lastTempDate;
public int lastTempDuration;
public double lastTempRate;
public IobTotal iobWithZeroTemp;
public double netInsulin = 0d; // for calculations from temp basals only
public double netRatio = 0d; // net ratio at start of temp basal
@ -31,6 +34,23 @@ public class IobTotal {
long time;
public IobTotal clone() {
IobTotal copy = new IobTotal(time);
copy.iob = iob;
copy.activity = activity;
copy.bolussnooze = bolussnooze;
copy.basaliob = basaliob;
copy.netbasalinsulin = netbasalinsulin;
copy.hightempinsulin = hightempinsulin;
copy.lastBolusTime = lastBolusTime;
copy.lastTempDate = lastTempDate;
copy.lastTempDuration = lastTempDuration;
copy.lastTempRate = lastTempRate;
copy.iobWithZeroTemp = iobWithZeroTemp;
return copy;
}
public IobTotal(long time) {
this.iob = 0d;
this.activity = 0d;
@ -38,8 +58,7 @@ public class IobTotal {
this.basaliob = 0d;
this.netbasalinsulin = 0d;
this.hightempinsulin = 0d;
this.microBolusInsulin = 0d;
this.microBolusIOB = 0d;
this.lastBolusTime = 0;
this.time = time;
}
@ -52,8 +71,6 @@ public class IobTotal {
hightempinsulin += other.hightempinsulin;
netInsulin += other.netInsulin;
extendedBolusInsulin += other.extendedBolusInsulin;
microBolusInsulin += other.microBolusInsulin;
microBolusIOB += other.microBolusIOB;
return this;
}
@ -62,11 +79,14 @@ public class IobTotal {
result.iob = bolusIOB.iob + basalIob.basaliob;
result.activity = bolusIOB.activity + basalIob.activity;
result.bolussnooze = bolusIOB.bolussnooze;
result.basaliob = basalIob.basaliob;
result.netbasalinsulin = basalIob.netbasalinsulin;
result.hightempinsulin = basalIob.hightempinsulin;
result.microBolusInsulin = bolusIOB.microBolusInsulin + basalIob.microBolusInsulin;
result.microBolusIOB = bolusIOB.microBolusIOB + basalIob.microBolusIOB;
result.basaliob = bolusIOB.basaliob + basalIob.basaliob;
result.netbasalinsulin = bolusIOB.netbasalinsulin + basalIob.netbasalinsulin;
result.hightempinsulin = basalIob.hightempinsulin + bolusIOB.hightempinsulin;
result.lastBolusTime = bolusIOB.lastBolusTime;
result.lastTempDate = basalIob.lastTempDate;
result.lastTempRate = basalIob.lastTempRate;
result.lastTempDuration = basalIob.lastTempDuration;
result.iobWithZeroTemp = basalIob.iobWithZeroTemp;
return result;
}
@ -77,8 +97,6 @@ public class IobTotal {
this.basaliob = Round.roundTo(this.basaliob, 0.001);
this.netbasalinsulin = Round.roundTo(this.netbasalinsulin, 0.001);
this.hightempinsulin = Round.roundTo(this.hightempinsulin, 0.001);
this.microBolusInsulin = Round.roundTo(this.microBolusInsulin, 0.001);
this.microBolusIOB = Round.roundTo(this.microBolusIOB, 0.001);
return this;
}
@ -102,7 +120,24 @@ public class IobTotal {
json.put("basaliob", basaliob);
json.put("bolussnooze", bolussnooze);
json.put("activity", activity);
json.put("lastBolusTime", lastBolusTime);
json.put("time", DateUtil.toISOString(new Date(time)));
/*
This is requested by SMB determine_basal but by based on Scott's info
it's MDT specific safety check only
It's causing rounding issues in determine_basal
JSONObject lastTemp = new JSONObject();
lastTemp.put("date", lastTempDate);
lastTemp.put("rate", lastTempRate);
lastTemp.put("duration", lastTempDuration);
json.put("lastTemp", lastTemp);
*/
if (iobWithZeroTemp != null) {
JSONObject iwzt = iobWithZeroTemp.determineBasalJson();
json.put("iobWithZeroTemp", iwzt);
}
} catch (JSONException e) {
log.error("Unhandled exception", e);
}

View file

@ -7,4 +7,8 @@ public class MealData {
public double boluses = 0d;
public double carbs = 0d;
public double mealCOB = 0.0d;
public double slopeFromMaxDeviation = 0;
public double slopeFromMinDeviation = 999;
public long lastBolusTime;
public long lastCarbTime = 0L;
}

View file

@ -2,7 +2,7 @@ package info.nightscout.androidaps.data;
import android.support.v4.util.LongSparseArray;
import com.crashlytics.android.Crashlytics;
import org.json.JSONArray;
import org.json.JSONException;
@ -25,6 +25,7 @@ import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.FabricPrivacy;
import info.nightscout.utils.ToastUtils;
public class Profile {
@ -57,7 +58,7 @@ public class Profile {
if (units != null)
this.units = units;
else {
Crashlytics.log("Profile failover failed too");
FabricPrivacy.log("Profile failover failed too");
this.units = Constants.MGDL;
}
}
@ -217,16 +218,18 @@ public class Profile {
if (isValid) {
// Check for hours alignment
for (int index = 0; index < basal_v.size(); index++) {
long secondsFromMidnight = basal_v.keyAt(index);
if (secondsFromMidnight % 3600 != 0) {
Notification notification = new Notification(Notification.BASAL_PROFILE_NOT_ALIGNED_TO_HOURS, String.format(MainApp.gs(R.string.basalprofilenotaligned), from), Notification.NORMAL);
MainApp.bus().post(new EventNewNotification(notification));
PumpInterface pump = MainApp.getConfigBuilder().getActivePump();
if (pump != null && !pump.getPumpDescription().is30minBasalRatesCapable) {
for (int index = 0; index < basal_v.size(); index++) {
long secondsFromMidnight = basal_v.keyAt(index);
if (secondsFromMidnight % 3600 != 0) {
Notification notification = new Notification(Notification.BASAL_PROFILE_NOT_ALIGNED_TO_HOURS, String.format(MainApp.gs(R.string.basalprofilenotaligned), from), Notification.NORMAL);
MainApp.bus().post(new EventNewNotification(notification));
}
}
}
// Check for minimal basal value
PumpInterface pump = ConfigBuilderPlugin.getActivePump();
if (pump != null) {
PumpDescription description = pump.getPumpDescription();
for (int i = 0; i < basal_v.size(); i++) {
@ -413,6 +416,8 @@ public class Profile {
}
public String getBasalList() {
if (basal_v == null)
basal_v = convertToSparseArray(basal);
return getValuesList(basal_v, null, new DecimalFormat("0.00"), "U");
}
@ -439,6 +444,14 @@ public class Profile {
return ret;
}
public double getTarget(){
return getTarget(secondsFromMidnight(System.currentTimeMillis()));
}
private double getTarget(Integer time) {
return (getTargetLow(time) + getTargetHigh(time))/2;
}
public Double getTargetLow() {
return getTargetLow(secondsFromMidnight(System.currentTimeMillis()));
}

View file

@ -116,7 +116,7 @@ public class PumpEnactResult {
}
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) {
ret = MainApp.sResources.getString(R.string.waitingforpumpresult);
} else if (enacted) {
@ -124,17 +124,20 @@ public class PumpEnactResult {
ret += "<br><b>" + MainApp.sResources.getString(R.string.enacted) + "</b>: " + enacted;
ret += "<br><b>" + MainApp.sResources.getString(R.string.comment) + "</b>: " + comment +
"<br>" + MainApp.sResources.getString(R.string.canceltemp);
} else if (isPercent) {
} else if (isPercent && percent != -1) {
ret += "<br><b>" + MainApp.sResources.getString(R.string.enacted) + "</b>: " + enacted;
ret += "<br><b>" + MainApp.sResources.getString(R.string.comment) + "</b>: " + comment;
ret += "<br><b>" + MainApp.sResources.getString(R.string.duration) + "</b>: " + duration + " min";
ret += "<br><b>" + MainApp.sResources.getString(R.string.percent) + "</b>: " + percent + "%";
} else {
} else if (absolute != -1) {
ret += "<br><b>" + MainApp.sResources.getString(R.string.enacted) + "</b>: " + enacted;
ret += "<br><b>" + MainApp.sResources.getString(R.string.comment) + "</b>: " + comment;
ret += "<br><b>" + MainApp.sResources.getString(R.string.duration) + "</b>: " + duration + " min";
ret += "<br><b>" + MainApp.sResources.getString(R.string.absolute) + "</b>: " + DecimalFormatter.to2Decimal(absolute) + " U/h";
}
if (bolusDelivered > 0) {
ret += "<br><b>" + MainApp.sResources.getString(R.string.bolus) + "</b>: " + DecimalFormatter.to2Decimal(bolusDelivered) + " U";
}
} else {
ret += "<br><b>" + MainApp.sResources.getString(R.string.comment) + "</b>: " + comment;
}

View file

@ -82,9 +82,9 @@ public class QuickWizardEntry {
double cob = 0d;
AutosensData autosensData;
if (_synchronized)
autosensData = IobCobCalculatorPlugin.getLastAutosensDataSynchronized("QuickWizard COB");
autosensData = IobCobCalculatorPlugin.getPlugin().getLastAutosensDataSynchronized("QuickWizard COB");
else
autosensData = IobCobCalculatorPlugin.getLastAutosensData("QuickWizard COB");
autosensData = IobCobCalculatorPlugin.getPlugin().getLastAutosensData("QuickWizard COB");
if (autosensData != null && useCOB() == YES) {
cob = autosensData.cob;

View file

@ -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.graphExtensions.DataPointWithLabelInterface;
import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLabelGraphSeries;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.SP;
@ -43,7 +42,11 @@ public class BgReading implements DataPointWithLabelInterface {
@DatabaseField
public String _id = null; // NS _id
public boolean isPrediction = false; // true when drawing predictions as bg points
public boolean isCOBPrediction = false; // true when drawing predictions as bg points (COB)
public boolean isaCOBPrediction = false; // true when drawing predictions as bg points (aCOB)
public boolean isIOBPrediction = false; // true when drawing predictions as bg points (IOB)
public boolean isUAMPrediction = false; // true when drawing predictions as bg points (UAM)
public boolean isZTPrediction = false; // true when drawing predictions as bg points (ZT)
public BgReading() {
}
@ -184,7 +187,10 @@ public class BgReading implements DataPointWithLabelInterface {
@Override
public PointsWithLabelGraphSeries.Shape getShape() {
return PointsWithLabelGraphSeries.Shape.POINT;
if (isPrediction())
return PointsWithLabelGraphSeries.Shape.PREDICTION;
else
return PointsWithLabelGraphSeries.Shape.BG;
}
@Override
@ -205,7 +211,7 @@ public class BgReading implements DataPointWithLabelInterface {
highLine = Profile.fromMgdlToUnits(OverviewPlugin.bgTargetHigh, units);
}
int color = MainApp.sResources.getColor(R.color.inrange);
if (isPrediction)
if (isPrediction())
color = MainApp.sResources.getColor(R.color.prediction);
else if (valueToUnits(units) < lowLine)
color = MainApp.sResources.getColor(R.color.low);
@ -214,4 +220,23 @@ public class BgReading implements DataPointWithLabelInterface {
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;
}
}

View file

@ -254,4 +254,9 @@ public class CareportalEvent implements DataPointWithLabelInterface {
return Color.GRAY;
return Color.GRAY;
}
@Override
public int getSecondColor() {
return 0;
}
}

View file

@ -8,6 +8,7 @@ import android.support.annotation.Nullable;
import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper;
import com.j256.ormlite.dao.CloseableIterator;
import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.dao.DaoManager;
import com.j256.ormlite.stmt.PreparedQuery;
import com.j256.ormlite.stmt.QueryBuilder;
import com.j256.ormlite.stmt.Where;
@ -35,7 +36,6 @@ import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.ProfileStore;
import info.nightscout.androidaps.events.EventCareportalEventChange;
import info.nightscout.androidaps.events.EventExtendedBolusChange;
import info.nightscout.androidaps.events.EventFoodDatabaseChanged;
import info.nightscout.androidaps.events.EventNewBG;
import info.nightscout.androidaps.events.EventProfileSwitchChange;
import info.nightscout.androidaps.events.EventRefreshOverview;
@ -55,6 +55,14 @@ import info.nightscout.utils.DateUtil;
import info.nightscout.utils.NSUpload;
import info.nightscout.utils.PercentageSplitter;
/**
* This Helper contains all resource to provide a central DB management functionality. Only methods handling
* data-structure (and not the DB content) should be contained in here (meaning DDL and not SQL).
*
* This class can safely be called from Services, but should not call Services to avoid circular dependencies.
* One major issue with this (right now) are the scheduled events, which are put into the service. Therefor all
* direct calls to the corresponding methods (eg. resetDatabases) should be done by a central service.
*/
public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
private static Logger log = LoggerFactory.getLogger(DatabaseHelper.class);
@ -68,7 +76,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
public static final String DATABASE_DBREQUESTS = "DBRequests";
public static final String DATABASE_CAREPORTALEVENTS = "CareportalEvents";
public static final String DATABASE_PROFILESWITCHES = "ProfileSwitches";
public static final String DATABASE_FOODS = "Foods";
private static final int DATABASE_VERSION = 8;
@ -95,7 +102,8 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
private static final ScheduledExecutorService profileSwitchEventWorker = Executors.newSingleThreadScheduledExecutor();
private static ScheduledFuture<?> scheduledProfileSwitchEventPost = null;
public FoodHelper foodHelper = new FoodHelper(this);
private int oldVersion = 0;
private int newVersion = 0;
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
@ -116,7 +124,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
TableUtils.createTableIfNotExists(connectionSource, ExtendedBolus.class);
TableUtils.createTableIfNotExists(connectionSource, CareportalEvent.class);
TableUtils.createTableIfNotExists(connectionSource, ProfileSwitch.class);
TableUtils.createTableIfNotExists(connectionSource, Food.class);
} catch (SQLException e) {
log.error("Can't create database", e);
throw new RuntimeException(e);
@ -126,6 +133,9 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
@Override
public void onUpgrade(SQLiteDatabase database, ConnectionSource connectionSource, int oldVersion, int newVersion) {
try {
this.oldVersion = oldVersion;
this.newVersion = newVersion;
if (oldVersion == 7 && newVersion == 8) {
log.debug("Upgrading database from v7 to v8");
TableUtils.dropTable(connectionSource, Treatment.class, true);
@ -141,7 +151,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
TableUtils.dropTable(connectionSource, ExtendedBolus.class, true);
TableUtils.dropTable(connectionSource, CareportalEvent.class, true);
TableUtils.dropTable(connectionSource, ProfileSwitch.class, true);
TableUtils.dropTable(connectionSource, Food.class, true);
onCreate(database, connectionSource);
}
} catch (SQLException e) {
@ -150,6 +159,14 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
}
}
public int getOldVersion() {
return oldVersion;
}
public int getNewVersion() {
return newVersion;
}
/**
* Close the database connections and clear any cached DAOs.
*/
@ -219,20 +236,18 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
TableUtils.createTableIfNotExists(connectionSource, ExtendedBolus.class);
TableUtils.createTableIfNotExists(connectionSource, CareportalEvent.class);
TableUtils.createTableIfNotExists(connectionSource, ProfileSwitch.class);
foodHelper.resetFood();
updateEarliestDataChange(0);
} catch (SQLException e) {
log.error("Unhandled exception", e);
}
VirtualPumpPlugin.setFakingStatus(true);
scheduleBgChange(); // trigger refresh
scheduleBgChange(null); // trigger refresh
scheduleTemporaryBasalChange();
scheduleTreatmentChange();
scheduleTreatmentChange(null);
scheduleExtendedBolusChange();
scheduleTemporaryTargetChange();
scheduleCareportalEventChange();
scheduleProfileSwitchChange();
foodHelper.scheduleFoodChange();
new java.util.Timer().schedule(
new java.util.TimerTask() {
@Override
@ -252,7 +267,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
} catch (SQLException e) {
log.error("Unhandled exception", e);
}
scheduleTreatmentChange();
scheduleTreatmentChange(null);
}
public void resetTempTargets() {
@ -308,6 +323,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
scheduleProfileSwitchChange();
}
// ------------------ getDao -------------------------------------------
private Dao<TempTarget, Long> getDaoTempTargets() throws SQLException {
@ -358,7 +374,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
if (old == null) {
getDaoBgReadings().create(bgReading);
log.debug("BG: New record from: " + from + " " + bgReading.toString());
scheduleBgChange();
scheduleBgChange(bgReading);
return true;
}
if (!old.isEqual(bgReading)) {
@ -366,7 +382,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
old.copyFrom(bgReading);
getDaoBgReadings().update(old);
log.debug("BG: Updating record from: " + from + " New data: " + old.toString());
scheduleBgChange();
scheduleBgChange(bgReading);
return false;
}
} catch (SQLException e) {
@ -384,11 +400,11 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
}
}
private static void scheduleBgChange() {
private static void scheduleBgChange(@Nullable final BgReading bgReading) {
class PostRunnable implements Runnable {
public void run() {
log.debug("Firing EventNewBg");
MainApp.bus().post(new EventNewBG());
MainApp.bus().post(new EventNewBG(bgReading));
scheduledBgPost = null;
}
}
@ -563,7 +579,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
getDaoTreatments().create(treatment);
log.debug("TREATMENT: New record from: " + Source.getString(treatment.source) + " " + treatment.toString());
updateEarliestDataChange(treatment.date);
scheduleTreatmentChange();
scheduleTreatmentChange(treatment);
return true;
}
if (treatment.source == Source.NIGHTSCOUT) {
@ -580,7 +596,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
updateEarliestDataChange(oldDate);
updateEarliestDataChange(old.date);
}
scheduleTreatmentChange();
scheduleTreatmentChange(treatment);
return true;
}
return false;
@ -605,7 +621,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
updateEarliestDataChange(oldDate);
updateEarliestDataChange(old.date);
}
scheduleTreatmentChange();
scheduleTreatmentChange(treatment);
return true;
}
}
@ -613,14 +629,14 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
getDaoTreatments().create(treatment);
log.debug("TREATMENT: New record from: " + Source.getString(treatment.source) + " " + treatment.toString());
updateEarliestDataChange(treatment.date);
scheduleTreatmentChange();
scheduleTreatmentChange(treatment);
return true;
}
if (treatment.source == Source.USER) {
getDaoTreatments().create(treatment);
log.debug("TREATMENT: New record from: " + Source.getString(treatment.source) + " " + treatment.toString());
updateEarliestDataChange(treatment.date);
scheduleTreatmentChange();
scheduleTreatmentChange(treatment);
return true;
}
} catch (SQLException e) {
@ -636,7 +652,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
} catch (SQLException e) {
log.error("Unhandled exception", e);
}
scheduleTreatmentChange();
scheduleTreatmentChange(treatment);
}
public void update(Treatment treatment) {
@ -646,7 +662,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
} catch (SQLException e) {
log.error("Unhandled exception", e);
}
scheduleTreatmentChange();
scheduleTreatmentChange(treatment);
}
public void deleteTreatmentById(String _id) {
@ -655,12 +671,12 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
log.debug("TREATMENT: Removing Treatment record from database: " + stored.toString());
delete(stored);
updateEarliestDataChange(stored.date);
scheduleTreatmentChange();
scheduleTreatmentChange(null);
}
}
@Nullable
public Treatment findTreatmentById(String _id) {
private Treatment findTreatmentById(String _id) {
try {
Dao<Treatment, Long> daoTreatments = getDaoTreatments();
QueryBuilder<Treatment, Long> queryBuilder = daoTreatments.queryBuilder();
@ -692,11 +708,11 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
}
}
private static void scheduleTreatmentChange() {
private static void scheduleTreatmentChange(@Nullable final Treatment treatment) {
class PostRunnable implements Runnable {
public void run() {
log.debug("Firing EventTreatmentChange");
MainApp.bus().post(new EventReloadTreatmentData(new EventTreatmentChange()));
MainApp.bus().post(new EventReloadTreatmentData(new EventTreatmentChange(treatment)));
if (earliestDataChange != null)
MainApp.bus().post(new EventNewHistoryData(earliestDataChange));
earliestDataChange = null;
@ -1742,4 +1758,4 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
}
// ---------------- Food handling ---------------
}
}

View file

@ -285,4 +285,9 @@ public class ExtendedBolus implements Interval, DataPointWithLabelInterface {
public int getColor() {
return Color.CYAN;
}
@Override
public int getSecondColor() {
return 0;
}
}

View file

@ -1,208 +0,0 @@
package info.nightscout.androidaps.db;
import com.j256.ormlite.android.AndroidConnectionSource;
import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.stmt.PreparedQuery;
import com.j256.ormlite.stmt.QueryBuilder;
import com.j256.ormlite.stmt.Where;
import com.j256.ormlite.table.TableUtils;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.events.EventFoodDatabaseChanged;
/**
* Created by mike on 24.09.2017.
*/
public class FoodHelper {
private static Logger log = LoggerFactory.getLogger(FoodHelper.class);
DatabaseHelper databaseHelper;
private static final ScheduledExecutorService foodEventWorker = Executors.newSingleThreadScheduledExecutor();
private static ScheduledFuture<?> scheduledFoodEventPost = null;
public FoodHelper(DatabaseHelper databaseHelper) {
this.databaseHelper = databaseHelper;
}
private Dao<Food, Long> getDaoFood() throws SQLException {
return databaseHelper.getDao(Food.class);
}
public void resetFood() {
try {
TableUtils.dropTable(databaseHelper.getConnectionSource(), Food.class, true);
TableUtils.createTableIfNotExists(databaseHelper.getConnectionSource(), Food.class);
} catch (SQLException e) {
log.error("Unhandled exception", e);
}
scheduleFoodChange();
}
public List<Food> getFoodData() {
try {
Dao<Food, Long> daoFood = getDaoFood();
List<Food> foods;
QueryBuilder<Food, Long> queryBuilder = daoFood.queryBuilder();
PreparedQuery<Food> preparedQuery = queryBuilder.prepare();
foods = daoFood.query(preparedQuery);
return foods;
} catch (SQLException e) {
log.error("Unhandled exception", e);
}
return new ArrayList<>();
}
public boolean createOrUpdate(Food food) {
try {
// find by NS _id
if (food._id != null && !food._id.equals("")) {
Food old;
QueryBuilder<Food, Long> queryBuilder = getDaoFood().queryBuilder();
Where where = queryBuilder.where();
where.eq("_id", food._id);
PreparedQuery<Food> preparedQuery = queryBuilder.prepare();
List<Food> found = getDaoFood().query(preparedQuery);
if (found.size() > 0) {
old = found.get(0);
if (!old.isEqual(food)) {
getDaoFood().delete(old); // need to delete/create because date may change too
old.copyFrom(food);
getDaoFood().create(old);
log.debug("FOOD: Updating record by _id: " + old.toString());
scheduleFoodChange();
return true;
} else {
return false;
}
} else {
getDaoFood().createOrUpdate(food);
log.debug("FOOD: New record: " + food.toString());
scheduleFoodChange();
return true;
}
}
} catch (SQLException e) {
log.error("Unhandled exception", e);
}
return false;
}
public void delete(Food food) {
try {
getDaoFood().delete(food);
scheduleFoodChange();
} catch (SQLException e) {
log.error("Unhandled exception", e);
}
}
public static void scheduleFoodChange() {
class PostRunnable implements Runnable {
public void run() {
log.debug("Firing EventFoodChange");
MainApp.bus().post(new EventFoodDatabaseChanged());
scheduledFoodEventPost = null;
}
}
// prepare task for execution in 1 sec
// cancel waiting task to prevent sending multiple posts
if (scheduledFoodEventPost != null)
scheduledFoodEventPost.cancel(false);
Runnable task = new PostRunnable();
final int sec = 1;
scheduledFoodEventPost = foodEventWorker.schedule(task, sec, TimeUnit.SECONDS);
}
/*
{
"_id": "551ee3ad368e06e80856e6a9",
"type": "food",
"category": "Zakladni",
"subcategory": "Napoje",
"name": "Mleko",
"portion": 250,
"carbs": 12,
"gi": 1,
"created_at": "2015-04-14T06:59:16.500Z",
"unit": "ml"
}
*/
public void createFoodFromJsonIfNotExists(JSONObject trJson) {
try {
Food food = new Food();
if (trJson.has("type") && trJson.getString("type").equals("food")) {
if (trJson.has("_id"))
food._id = trJson.getString("_id");
if (trJson.has("category"))
food.category = trJson.getString("category");
if (trJson.has("subcategory"))
food.subcategory = trJson.getString("subcategory");
if (trJson.has("name"))
food.name = trJson.getString("name");
if (trJson.has("unit"))
food.units = trJson.getString("unit");
if (trJson.has("portion"))
food.portion = trJson.getDouble("portion");
if (trJson.has("carbs"))
food.carbs = trJson.getInt("carbs");
if (trJson.has("gi"))
food.gi = trJson.getInt("gi");
if (trJson.has("energy"))
food.energy = trJson.getInt("energy");
if (trJson.has("protein"))
food.protein = trJson.getInt("protein");
if (trJson.has("fat"))
food.fat = trJson.getInt("fat");
}
createOrUpdate(food);
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
}
public void deleteFoodById(String _id) {
Food stored = findFoodById(_id);
if (stored != null) {
log.debug("FOOD: Removing Food record from database: " + stored.toString());
delete(stored);
scheduleFoodChange();
}
}
public Food findFoodById(String _id) {
try {
QueryBuilder<Food, Long> queryBuilder = getDaoFood().queryBuilder();
Where where = queryBuilder.where();
where.eq("_id", _id);
PreparedQuery<Food> preparedQuery = queryBuilder.prepare();
List<Food> list = getDaoFood().query(preparedQuery);
if (list.size() == 1) {
return list.get(0);
} else {
return null;
}
} catch (SQLException e) {
log.error("Unhandled exception", e);
}
return null;
}
}

View file

@ -0,0 +1,15 @@
package info.nightscout.androidaps.db;
import java.util.concurrent.ScheduledFuture;
/**
* Created by triplem on 05.01.18.
*/
public interface ICallback {
void setPost(ScheduledFuture<?> post);
ScheduledFuture<?> getPost();
}

View file

@ -238,6 +238,11 @@ public class ProfileSwitch implements Interval, DataPointWithLabelInterface {
return Color.CYAN;
}
@Override
public int getSecondColor() {
return 0;
}
public String toString() {
return "ProfileSwitch{" +
"date=" + date +

View file

@ -41,6 +41,10 @@ public class TempTarget implements Interval {
@DatabaseField
public int durationInMinutes;
public double target() {
return (low + high) / 2;
}
public boolean isEqual(TempTarget other) {
if (date != other.date) {
return false;

View file

@ -325,13 +325,13 @@ public class TemporaryBasal implements Interval {
if(profile != null) {
double basal = profile.getBasal();
if(basal != 0){
return Math.round(rate*100d/basal) + "% ";
return Math.round(rate*100d/basal) + "%";
}
}
}
return DecimalFormatter.to2Decimal(rate) + "U/h ";
return DecimalFormatter.to2Decimal(rate) + "U/h";
} else { // percent
return percentRate + "% ";
return percentRate + "%";
}
}

View file

@ -12,9 +12,11 @@ import java.util.Objects;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Iob;
import info.nightscout.androidaps.interfaces.InsulinInterface;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Overview.OverviewPlugin;
import info.nightscout.androidaps.plugins.Overview.graphExtensions.DataPointWithLabelInterface;
import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLabelGraphSeries;
import info.nightscout.utils.DateUtil;
@ -120,7 +122,7 @@ public class Treatment implements DataPointWithLabelInterface {
@Override
public double getY() {
return yValue;
return isSMB ? OverviewPlugin.getPlugin().determineLowLine() : yValue;
}
@Override
@ -139,7 +141,10 @@ public class Treatment implements DataPointWithLabelInterface {
@Override
public PointsWithLabelGraphSeries.Shape getShape() {
return PointsWithLabelGraphSeries.Shape.BOLUS;
if (isSMB)
return PointsWithLabelGraphSeries.Shape.SMB;
else
return PointsWithLabelGraphSeries.Shape.BOLUS;
}
@Override
@ -149,12 +154,19 @@ public class Treatment implements DataPointWithLabelInterface {
@Override
public int getColor() {
if (isValid)
if (isSMB)
return MainApp.sResources.getColor(R.color.tempbasal);
else if (isValid)
return Color.CYAN;
else
return MainApp.instance().getResources().getColor(android.R.color.holo_red_light);
}
@Override
public int getSecondColor() {
return 0;
}
@Override
public void setY(double y) {
yValue = y;

View file

@ -0,0 +1,8 @@
package info.nightscout.androidaps.events;
/**
* Created by mike on 13.02.2018.
*/
public class EventCustomCalculationFinished extends Event {
}

View file

@ -0,0 +1,36 @@
package info.nightscout.androidaps.events;
/**
* Created by jamorham on 07/02/2018.
*
* Event to indicate that an app feature is being used, for example bolus wizard being opened
*
* The purpose this has been created for is to enable opportunistic connection to the pump
* so that it is already connected before the user wishes to enact a pump function
*
*/
public class EventFeatureRunning extends Event {
private Feature feature = Feature.UNKNOWN;
public EventFeatureRunning() {
}
public EventFeatureRunning(Feature feature) {
this.feature = feature;
}
public Feature getFeature() {
return feature;
}
public enum Feature {
UNKNOWN,
MAIN,
WIZARD,
JUST_ADD_MORE_HERE
}
}

View file

@ -1,7 +1,17 @@
package info.nightscout.androidaps.events;
import android.support.annotation.Nullable;
import info.nightscout.androidaps.db.BgReading;
/**
* Created by mike on 05.06.2016.
*/
public class EventNewBG extends EventLoop {
@Nullable
public final BgReading bgReading;
public EventNewBG(BgReading bgReading) {
this.bgReading = bgReading;
}
}

View file

@ -0,0 +1,35 @@
package info.nightscout.androidaps.events;
import android.os.Bundle;
/**
* Event which is published with data fetched from NightScout specific for the
* Food-class.
*
* Payload is the from NS retrieved JSON-String which should be handled by all
* subscriber.
*/
public class EventNsFood extends Event {
public static final int ADD = 0;
public static final int UPDATE = 1;
public static final int REMOVE = 2;
private final int mode;
private final Bundle payload;
public EventNsFood(int mode, Bundle payload) {
this.mode = mode;
this.payload = payload;
}
public int getMode() {
return mode;
}
public Bundle getPayload() {
return payload;
}
}

View file

@ -1,7 +1,17 @@
package info.nightscout.androidaps.events;
import android.support.annotation.Nullable;
import info.nightscout.androidaps.db.Treatment;
/**
* Created by mike on 04.06.2016.
*/
public class EventTreatmentChange extends EventLoop {
@Nullable
public final Treatment treatment;
public EventTreatmentChange(Treatment treatment) {
this.treatment = treatment;
}
}

View file

@ -4,4 +4,5 @@ package info.nightscout.androidaps.interfaces;
* Created by mike on 20.06.2016.
*/
public interface BgSourceInterface {
boolean advancedFilteringSupported();
}

View file

@ -10,16 +10,16 @@ import info.nightscout.androidaps.db.Treatment;
*/
public interface InsulinInterface {
final int FASTACTINGINSULIN = 0;
final int FASTACTINGINSULINPROLONGED = 1;
final int OREF_RAPID_ACTING = 2;
final int OREF_ULTRA_RAPID_ACTING = 3;
final int OREF_FREE_PEAK = 4;
int FASTACTINGINSULIN = 0;
int FASTACTINGINSULINPROLONGED = 1;
int OREF_RAPID_ACTING = 2;
int OREF_ULTRA_RAPID_ACTING = 3;
int OREF_FREE_PEAK = 4;
int getId();
String getFriendlyName();
String getComment();
double getDia();
public Iob iobCalcForTreatment(Treatment treatment, long time, double dia);
Iob iobCalcForTreatment(Treatment treatment, long time, double dia);
}

View file

@ -27,6 +27,8 @@ public class PumpDescription {
public double tempAbsoluteStep = 0.05d;
public int tempDurationStep = 60;
public boolean tempDurationStep15mAllowed = false;
public boolean tempDurationStep30mAllowed = false;
public int tempMaxDuration = 12 * 60;
@ -37,4 +39,6 @@ public class PumpDescription {
public boolean isRefillingCapable = false;
public boolean storesCarbInfo = true;
public boolean is30minBasalRatesCapable = false;
}

View file

@ -30,6 +30,7 @@ public interface TreatmentsInterface {
List<Treatment> getTreatmentsFromHistory();
List<Treatment> getTreatments5MinBackFromHistory(long time);
long getLastBolusTime();
// real basals (not faked by extended bolus)
boolean isInHistoryRealTempBasalInProgress();

View file

@ -9,8 +9,7 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.crashlytics.android.Crashlytics;
import com.crashlytics.android.answers.Answers;
import com.crashlytics.android.answers.CustomEvent;
import com.squareup.otto.Subscribe;
@ -32,6 +31,7 @@ import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialo
import info.nightscout.androidaps.plugins.Careportal.OptionsToShow;
import info.nightscout.androidaps.plugins.Common.SubscriberFragment;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.utils.FabricPrivacy;
import info.nightscout.utils.SingleClickButton;
/**
@ -83,7 +83,7 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL
updateGUI();
return view;
} catch (Exception e) {
Crashlytics.logException(e);
FabricPrivacy.logException(e);
}
return null;
@ -137,11 +137,11 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL
extendedBolus.setVisibility(View.GONE);
extendedBolusCancel.setVisibility(View.GONE);
} else {
if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) {
ExtendedBolus activeExtendedBolus = MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis());
if (activeExtendedBolus != null) {
extendedBolus.setVisibility(View.GONE);
extendedBolusCancel.setVisibility(View.VISIBLE);
ExtendedBolus running = MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis());
extendedBolusCancel.setText(MainApp.instance().getString(R.string.cancel) + " " + running.toString());
extendedBolusCancel.setText(MainApp.instance().getString(R.string.cancel) + " " + activeExtendedBolus.toString());
} else {
extendedBolus.setVisibility(View.VISIBLE);
extendedBolusCancel.setVisibility(View.GONE);
@ -153,10 +153,10 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL
tempBasal.setVisibility(View.GONE);
tempBasalCancel.setVisibility(View.GONE);
} else {
if (MainApp.getConfigBuilder().isTempBasalInProgress()) {
final TemporaryBasal activeTemp = MainApp.getConfigBuilder().getTempBasalFromHistory(System.currentTimeMillis());
if (activeTemp != null) {
tempBasal.setVisibility(View.GONE);
tempBasalCancel.setVisibility(View.VISIBLE);
final TemporaryBasal activeTemp = MainApp.getConfigBuilder().getTempBasalFromHistory(System.currentTimeMillis());
tempBasalCancel.setText(MainApp.instance().getString(R.string.cancel) + " " + activeTemp.toStringShort());
} else {
tempBasal.setVisibility(View.VISIBLE);
@ -203,13 +203,13 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL
case R.id.actions_extendedbolus_cancel:
if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) {
ConfigBuilderPlugin.getCommandQueue().cancelExtended(null);
Answers.getInstance().logCustom(new CustomEvent("CancelExtended"));
FabricPrivacy.getInstance().logCustom(new CustomEvent("CancelExtended"));
}
break;
case R.id.actions_canceltempbasal:
if (MainApp.getConfigBuilder().isTempBasalInProgress()) {
ConfigBuilderPlugin.getCommandQueue().cancelTempBasal(true, null);
Answers.getInstance().logCustom(new CustomEvent("CancelTemp"));
FabricPrivacy.getInstance().logCustom(new CustomEvent("CancelTemp"));
}
break;
case R.id.actions_settempbasal:

View file

@ -14,7 +14,6 @@ import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import com.crashlytics.android.answers.Answers;
import com.crashlytics.android.answers.CustomEvent;
import org.slf4j.Logger;
@ -31,6 +30,7 @@ import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Overview.Dialogs.ErrorHelperActivity;
import info.nightscout.androidaps.queue.Callback;
import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.FabricPrivacy;
import info.nightscout.utils.NumberPicker;
import info.nightscout.utils.SP;
import info.nightscout.utils.SafeParse;
@ -171,7 +171,7 @@ public class FillDialog extends DialogFragment implements OnClickListener {
}
}
});
Answers.getInstance().logCustom(new CustomEvent("Fill"));
FabricPrivacy.getInstance().logCustom(new CustomEvent("Fill"));
}
}
});

View file

@ -10,7 +10,6 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.crashlytics.android.answers.Answers;
import com.crashlytics.android.answers.CustomEvent;
import org.slf4j.Logger;
@ -24,6 +23,7 @@ import info.nightscout.androidaps.R;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Overview.Dialogs.ErrorHelperActivity;
import info.nightscout.androidaps.queue.Callback;
import info.nightscout.utils.FabricPrivacy;
import info.nightscout.utils.NumberPicker;
import info.nightscout.utils.SafeParse;
@ -99,7 +99,7 @@ public class NewExtendedBolusDialog extends DialogFragment implements View.OnCli
}
}
});
Answers.getInstance().logCustom(new CustomEvent("ExtendedBolus"));
FabricPrivacy.getInstance().logCustom(new CustomEvent("ExtendedBolus"));
}
});
builder.setNegativeButton(getString(R.string.cancel), null);

View file

@ -1,6 +1,5 @@
package info.nightscout.androidaps.plugins.Actions.dialogs;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
@ -13,7 +12,6 @@ import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import com.crashlytics.android.answers.Answers;
import com.crashlytics.android.answers.CustomEvent;
import org.slf4j.Logger;
@ -28,6 +26,7 @@ import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Overview.Dialogs.ErrorHelperActivity;
import info.nightscout.androidaps.queue.Callback;
import info.nightscout.utils.FabricPrivacy;
import info.nightscout.utils.NumberPicker;
import info.nightscout.utils.SafeParse;
@ -162,7 +161,7 @@ public class NewTempBasalDialog extends DialogFragment implements View.OnClickLi
} else {
ConfigBuilderPlugin.getCommandQueue().tempBasalAbsolute(finalBasal, finalDurationInMinutes, true, callback);
}
Answers.getInstance().logCustom(new CustomEvent("TempBasal"));
FabricPrivacy.getInstance().logCustom(new CustomEvent("TempBasal"));
}
});
builder.setNegativeButton(getString(R.string.cancel), null);

View file

@ -10,7 +10,6 @@ import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.crashlytics.android.Crashlytics;
import com.squareup.otto.Subscribe;
import info.nightscout.androidaps.BuildConfig;
@ -24,6 +23,7 @@ import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialo
import info.nightscout.androidaps.plugins.Common.SubscriberFragment;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Overview.OverviewFragment;
import info.nightscout.utils.FabricPrivacy;
public class CareportalFragment extends SubscriberFragment implements View.OnClickListener {
@ -111,7 +111,7 @@ public class CareportalFragment extends SubscriberFragment implements View.OnCli
updateGUI();
return view;
} catch (Exception e) {
Crashlytics.logException(e);
FabricPrivacy.logException(e);
}
return null;

View file

@ -23,7 +23,6 @@ import android.widget.RadioButton;
import android.widget.Spinner;
import android.widget.TextView;
import com.crashlytics.android.answers.Answers;
import com.crashlytics.android.answers.CustomEvent;
import com.wdullaer.materialdatetimepicker.date.DatePickerDialog;
import com.wdullaer.materialdatetimepicker.time.RadialPickerLayout;
@ -38,6 +37,7 @@ import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
@ -45,6 +45,7 @@ import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.GlucoseStatus;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.ProfileStore;
import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.db.ProfileSwitch;
import info.nightscout.androidaps.db.Source;
@ -54,6 +55,7 @@ import info.nightscout.androidaps.plugins.Careportal.OptionsToShow;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Overview.Dialogs.ErrorHelperActivity;
import info.nightscout.androidaps.queue.Callback;
import info.nightscout.utils.FabricPrivacy;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.NSUpload;
import info.nightscout.utils.NumberPicker;
@ -407,12 +409,23 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
else layout.setVisibility(View.GONE);
}
private void updateBGforDateTime() {
long millis = eventTime.getTime() - (150 * 1000L); // 2,5 * 60 * 1000
List<BgReading> data = MainApp.getDbHelper().getBgreadingsDataFromTime(millis, true);
if ((data.size() > 0) &&
(data.get(0).date > millis - 7 * 60 * 1000L) &&
(data.get(0).date < millis + 7 * 60 * 1000L)) {
editBg.setValue(Profile.fromMgdlToUnits(data.get(0).value, profile != null ? profile.getUnits() : Constants.MGDL));
}
}
@Override
public void onDateSet(DatePickerDialog view, int year, int monthOfYear, int dayOfMonth) {
eventTime.setYear(year - 1900);
eventTime.setMonth(monthOfYear);
eventTime.setDate(dayOfMonth);
dateButton.setText(DateUtil.dateString(eventTime));
updateBGforDateTime();
}
@Override
@ -421,6 +434,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
eventTime.setMinutes(minute);
eventTime.setSeconds(second);
timeButton.setText(DateUtil.timeString(eventTime));
updateBGforDateTime();
}
@ -685,14 +699,14 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
log.debug("Creating new TempTarget db record: " + tempTarget.toString());
MainApp.getDbHelper().createOrUpdate(tempTarget);
NSUpload.uploadCareportalEntryToNS(data);
Answers.getInstance().logCustom(new CustomEvent("TempTarget"));
FabricPrivacy.getInstance().logCustom(new CustomEvent("TempTarget"));
}
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
} else {
NSUpload.uploadCareportalEntryToNS(data);
Answers.getInstance().logCustom(new CustomEvent("NSTreatment"));
FabricPrivacy.getInstance().logCustom(new CustomEvent("NSTreatment"));
}
}
});
@ -727,7 +741,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
MainApp.bus().post(new EventNewBasalProfile());
}
});
Answers.getInstance().logCustom(new CustomEvent("ProfileSwitch"));
FabricPrivacy.getInstance().logCustom(new CustomEvent("ProfileSwitch"));
}
public static void doProfileSwitch(final int duration, final int percentage, final int timeshift) {
@ -759,7 +773,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
MainApp.bus().post(new EventNewBasalProfile());
}
});
Answers.getInstance().logCustom(new CustomEvent("ProfileSwitch"));
FabricPrivacy.getInstance().logCustom(new CustomEvent("ProfileSwitch"));
} else {
log.error("No profile switch existing");
}

View file

@ -17,8 +17,7 @@ import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView;
import com.crashlytics.android.Crashlytics;
import com.crashlytics.android.answers.Answers;
import com.crashlytics.android.answers.CustomEvent;
import java.util.ArrayList;
@ -40,6 +39,7 @@ import info.nightscout.androidaps.plugins.Insulin.InsulinFastactingPlugin;
import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin;
import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin;
import info.nightscout.androidaps.plugins.SensitivityOref0.SensitivityOref0Plugin;
import info.nightscout.utils.FabricPrivacy;
import info.nightscout.utils.PasswordProtection;
@ -131,7 +131,7 @@ public class ConfigBuilderFragment extends Fragment {
}
return view;
} catch (Exception e) {
Crashlytics.logException(e);
FabricPrivacy.logException(e);
}
return null;
@ -242,7 +242,7 @@ public class ConfigBuilderFragment extends Fragment {
MainApp.bus().post(new EventRefreshGui());
MainApp.bus().post(new EventConfigBuilderChange());
getPlugin().logPluginStatus();
Answers.getInstance().logCustom(new CustomEvent("ConfigurationChange"));
FabricPrivacy.getInstance().logCustom(new CustomEvent("ConfigurationChange"));
}
});

View file

@ -23,8 +23,10 @@ import info.nightscout.androidaps.data.MealData;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.ProfileIntervals;
import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.db.ExtendedBolus;
import info.nightscout.androidaps.db.ProfileSwitch;
import info.nightscout.androidaps.db.Source;
import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.db.Treatment;
@ -48,6 +50,7 @@ import info.nightscout.androidaps.queue.Callback;
import info.nightscout.androidaps.queue.CommandQueue;
import info.nightscout.utils.NSUpload;
import info.nightscout.utils.SP;
import info.nightscout.utils.ToastUtils;
/**
* Created by mike on 05.08.2016.
@ -243,96 +246,90 @@ public class ConfigBuilderPlugin implements PluginBase, ConstraintsInterface, Tr
ArrayList<PluginBase> pluginsInCategory;
// PluginBase.APS
pluginsInCategory = MainApp.getSpecificPluginsListByInterface(APSInterface.class);
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);
}
}
}
activeAPS = this.determineActivePlugin(APSInterface.class, PluginBase.APS);
// PluginBase.INSULIN
pluginsInCategory = MainApp.getSpecificPluginsListByInterface(InsulinInterface.class);
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);
}
}
activeInsulin = this.determineActivePlugin(InsulinInterface.class, PluginBase.INSULIN);
// PluginBase.SENSITIVITY
pluginsInCategory = MainApp.getSpecificPluginsListByInterface(SensitivityInterface.class);
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);
}
}
activeSensitivity = this.determineActivePlugin(SensitivityInterface.class, PluginBase.SENSITIVITY);
// PluginBase.PROFILE
pluginsInCategory = MainApp.getSpecificPluginsListByInterface(ProfileInterface.class);
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);
}
}
activeProfile = this.determineActivePlugin(ProfileInterface.class, PluginBase.PROFILE);
// PluginBase.BGSOURCE
pluginsInCategory = MainApp.getSpecificPluginsListByInterface(BgSourceInterface.class);
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);
}
}
activeBgSource = this.determineActivePlugin(BgSourceInterface.class, PluginBase.BGSOURCE);
// PluginBase.PUMP
pluginsInCategory = MainApp.getSpecificPluginsList(PluginBase.PUMP);
activePump = (PumpInterface) getTheOneEnabledInArray(pluginsInCategory, PluginBase.PUMP);
if (activePump == null)
activePump = VirtualPumpPlugin.getPlugin(); // for NSClient build
if (Config.logConfigBuilder)
log.debug("Selected pump interface: " + ((PluginBase) activePump).getName());
for (PluginBase p : pluginsInCategory) {
if (!p.getName().equals(((PluginBase) activePump).getName())) {
p.setFragmentVisible(PluginBase.PUMP, false);
}
}
this.setFragmentVisiblities(((PluginBase) activePump).getName(), pluginsInCategory, PluginBase.PUMP);
// PluginBase.LOOP
pluginsInCategory = MainApp.getSpecificPluginsList(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);
}
}
}
activeLoop = this.determineActivePlugin(PluginBase.LOOP);
// PluginBase.TREATMENT
pluginsInCategory = MainApp.getSpecificPluginsList(PluginBase.TREATMENT);
activeTreatments = (TreatmentsInterface) getTheOneEnabledInArray(pluginsInCategory, PluginBase.TREATMENT);
activeTreatments = this.determineActivePlugin(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.
* <p>
* 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)
log.debug("Selected treatment interface: " + ((PluginBase) activeTreatments).getName());
log.debug("Selected interface: " + activePluginName);
for (PluginBase p : pluginsInCategory) {
if (!p.getName().equals(((PluginBase) activeTreatments).getName())) {
p.setFragmentVisible(PluginBase.TREATMENT, false);
if (!p.getName().equals(activePluginName)) {
p.setFragmentVisible(pluginType, false);
}
}
}
@ -354,33 +351,19 @@ public class ConfigBuilderPlugin implements PluginBase, ConstraintsInterface, Tr
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
*
* @param request
* @return
* true if command is going to be executed
* false if error
*/
public boolean applyAPSRequest(APSResult request, Callback callback) {
public void applyAPSRequest(APSResult request, Callback callback) {
PumpInterface pump = getActivePump();
request.rate = applyBasalConstraints(request.rate);
PumpEnactResult result;
if (!pump.isInitialized()) {
log.debug("applyAPSRequest: " + MainApp.sResources.getString(R.string.pumpNotInitialized));
if (callback != null) {
callback.result(new PumpEnactResult().comment(MainApp.sResources.getString(R.string.pumpNotInitialized)).enacted(false).success(false)).run();
}
return false;
return;
}
if (pump.isSuspended()) {
@ -388,43 +371,56 @@ public class ConfigBuilderPlugin implements PluginBase, ConstraintsInterface, Tr
if (callback != null) {
callback.result(new PumpEnactResult().comment(MainApp.sResources.getString(R.string.pumpsuspended)).enacted(false).success(false)).run();
}
return false;
return;
}
if (Config.logCongigBuilderActions)
log.debug("applyAPSRequest: " + request.toString());
if ((request.rate == 0 && request.duration == 0) || Math.abs(request.rate - pump.getBaseBasalRate()) < pump.getPumpDescription().basalStep) {
if (isTempBasalInProgress()) {
if (request.tempBasalReqested) {
if ((request.rate == 0 && request.duration == 0) || Math.abs(request.rate - pump.getBaseBasalRate()) < pump.getPumpDescription().basalStep) {
if (isTempBasalInProgress()) {
if (Config.logCongigBuilderActions)
log.debug("applyAPSRequest: cancelTempBasal()");
getCommandQueue().cancelTempBasal(false, callback);
} else {
if (Config.logCongigBuilderActions)
log.debug("applyAPSRequest: Basal set correctly");
if (callback != null) {
callback.result(new PumpEnactResult().absolute(request.rate).duration(0).enacted(false).success(true).comment("Basal set correctly")).run();
}
}
} else if (isTempBasalInProgress()
&& getTempBasalRemainingMinutesFromHistory() > 5
&& Math.abs(request.rate - getTempBasalAbsoluteRateHistory()) < pump.getPumpDescription().basalStep) {
if (Config.logCongigBuilderActions)
log.debug("applyAPSRequest: cancelTempBasal()");
getCommandQueue().cancelTempBasal(false, callback);
return true;
log.debug("applyAPSRequest: Temp basal set correctly");
if (callback != null) {
callback.result(new PumpEnactResult().absolute(getTempBasalAbsoluteRateHistory()).duration(getTempBasalFromHistory(System.currentTimeMillis()).getPlannedRemainingMinutes()).enacted(false).success(true).comment("Temp basal set correctly")).run();
}
} else {
if (Config.logCongigBuilderActions)
log.debug("applyAPSRequest: Basal set correctly");
if (callback != null) {
callback.result(new PumpEnactResult().absolute(request.rate).duration(0).enacted(false).success(true).comment("Basal set correctly")).run();
}
return false;
log.debug("applyAPSRequest: setTempBasalAbsolute()");
getCommandQueue().tempBasalAbsolute(request.rate, request.duration, false, callback);
}
} else if (isTempBasalInProgress()
&& getTempBasalRemainingMinutesFromHistory() > 5
&& Math.abs(request.rate - getTempBasalAbsoluteRateHistory()) < pump.getPumpDescription().basalStep) {
if (Config.logCongigBuilderActions)
log.debug("applyAPSRequest: Temp basal set correctly");
if (callback != null) {
callback.result(new PumpEnactResult().absolute(getTempBasalAbsoluteRateHistory()).duration(getTempBasalFromHistory(System.currentTimeMillis()).getPlannedRemainingMinutes()).enacted(false).success(true).comment("Temp basal set correctly")).run();
}
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);
}
return false;
} else {
if (Config.logCongigBuilderActions)
log.debug("applyAPSRequest: setTempBasalAbsolute()");
getCommandQueue().tempBasalAbsolute(request.rate, request.duration, false, callback);
return true;
}
}
/**
* Constraints interface
**/
@ -599,6 +595,11 @@ public class ConfigBuilderPlugin implements PluginBase, ConstraintsInterface, Tr
return activeTreatments.getTreatments5MinBackFromHistory(time);
}
@Override
public long getLastBolusTime() {
return activeTreatments.getLastBolusTime();
}
@Override
public boolean isInHistoryRealTempBasalInProgress() {
return activeTreatments.isInHistoryRealTempBasalInProgress();
@ -745,14 +746,17 @@ public class ConfigBuilderPlugin implements PluginBase, ConstraintsInterface, Tr
}
public String getProfileName(long time, boolean customized) {
ProfileSwitch profileSwitch = getProfileSwitchFromHistory(time);
if (profileSwitch != null) {
if (profileSwitch.profileJson != null) {
return customized ? profileSwitch.getCustomizedName() : profileSwitch.profileName;
} else {
Profile profile = activeProfile.getProfile().getSpecificProfile(profileSwitch.profileName);
if (profile != null)
return profileSwitch.profileName;
boolean ignoreProfileSwitchEvents = SP.getBoolean(R.string.key_do_not_track_profile_switch, false);
if (!ignoreProfileSwitchEvents) {
ProfileSwitch profileSwitch = getProfileSwitchFromHistory(time);
if (profileSwitch != null) {
if (profileSwitch.profileJson != null) {
return customized ? profileSwitch.getCustomizedName() : profileSwitch.profileName;
} else {
Profile profile = activeProfile.getProfile().getSpecificProfile(profileSwitch.profileName);
if (profile != null)
return profileSwitch.profileName;
}
}
}
// Unable to determine profile, failover to default
@ -790,10 +794,10 @@ public class ConfigBuilderPlugin implements PluginBase, ConstraintsInterface, Tr
return profile;
}
}
// Unable to determine profile, failover to default
if (activeProfile.getProfile() == null)
return null; //app not initialized
}
// Unable to determine profile, failover to default
if (activeProfile.getProfile() == null)
return null; //app not initialized
Profile defaultProfile = activeProfile.getProfile().getDefaultProfile();
if (defaultProfile != null)
return defaultProfile;
@ -813,4 +817,40 @@ public class ConfigBuilderPlugin implements PluginBase, ConstraintsInterface, Tr
}
return null;
}
public void disconnectPump(int durationInMinutes) {
getActiveLoop().disconnectTo(System.currentTimeMillis() + durationInMinutes * 60 * 1000L);
getCommandQueue().tempBasalPercent(0, durationInMinutes, true, new Callback() {
@Override
public void run() {
if (!result.success) {
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.tempbasaldeliveryerror));
}
}
});
if (getActivePump().getPumpDescription().isExtendedBolusCapable && isInHistoryExtendedBoluslInProgress()) {
getCommandQueue().cancelExtended(new Callback() {
@Override
public void run() {
if (!result.success) {
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.extendedbolusdeliveryerror));
}
}
});
}
NSUpload.uploadOpenAPSOffline(durationInMinutes);
}
public void suspendLoop(int durationInMinutes) {
getActiveLoop().suspendTo(System.currentTimeMillis() + durationInMinutes * 60 * 1000);
getCommandQueue().cancelTempBasal(true, new Callback() {
@Override
public void run() {
if (!result.success) {
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.tempbasaldeliveryerror));
}
}
});
NSUpload.uploadOpenAPSOffline(durationInMinutes);
}
}

View file

@ -15,7 +15,6 @@ import android.widget.CheckBox;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.crashlytics.android.Crashlytics;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -25,6 +24,7 @@ import java.util.List;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.utils.FabricPrivacy;
public class ObjectivesFragment extends Fragment {
private static Logger log = LoggerFactory.getLogger(ObjectivesFragment.class);
@ -208,7 +208,7 @@ public class ObjectivesFragment extends Fragment {
return view;
} catch (Exception e) {
Crashlytics.logException(e);
FabricPrivacy.logException(e);
}
return null;

View file

@ -130,7 +130,7 @@ public class SafetyPlugin implements PluginBase, ConstraintsInterface {
if (profile == null) return absoluteRate;
if (absoluteRate < 0) absoluteRate = 0d;
Integer maxBasalMult = SP.getInt("openapsama_current_basal_safety_multiplier", 4);
Double maxBasalMult = SP.getDouble("openapsama_current_basal_safety_multiplier", 4d);
Integer maxBasalFromDaily = SP.getInt("openapsama_max_daily_safety_multiplier", 3);
// Check percentRate but absolute rate too, because we know real current basal in pump
Double origRate = absoluteRate;
@ -168,7 +168,7 @@ public class SafetyPlugin implements PluginBase, ConstraintsInterface {
if (absoluteRate < 0) absoluteRate = 0d;
Integer maxBasalMult = SP.getInt("openapsama_current_basal_safety_multiplier", 4);
Double maxBasalMult = SP.getDouble("openapsama_current_basal_safety_multiplier", 4d);
Integer maxBasalFromDaily = SP.getInt("openapsama_max_daily_safety_multiplier", 3);
// Check percentRate but absolute rate too, because we know real current basal in pump
Double origRate = absoluteRate;

View file

@ -1,22 +1,27 @@
package info.nightscout.androidaps.db;
package info.nightscout.androidaps.plugins.Food;
import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Objects;
import info.nightscout.utils.JsonHelper;
/**
* Created by mike on 20.09.2017.
*/
@DatabaseTable(tableName = DatabaseHelper.DATABASE_FOODS)
@DatabaseTable(tableName = Food.TABLE_FOODS)
public class Food {
private static Logger log = LoggerFactory.getLogger(Food.class);
public static final String TABLE_FOODS = "Foods";
@DatabaseField(id = true)
public long key;
@ -64,6 +69,25 @@ public class Food {
key = System.currentTimeMillis();
}
public static Food createFromJson(JSONObject json) throws JSONException {
Food food = new Food();
if ("food".equals(JsonHelper.safeGetString(json, "type"))) {
food._id = JsonHelper.safeGetString(json, "_id");
food.category = JsonHelper.safeGetString(json, "category");
food.subcategory = JsonHelper.safeGetString(json, "subcategory");
food.name = JsonHelper.safeGetString(json, "name");
food.units = JsonHelper.safeGetString(json, "unit");
food.portion = JsonHelper.safeGetDouble(json, "portion");
food.carbs = JsonHelper.safeGetInt(json, "carbs");
food.gi = JsonHelper.safeGetInt(json, "gi");
food.energy = JsonHelper.safeGetInt(json, "energy");
food.protein = JsonHelper.safeGetInt(json, "protein");
food.fat = JsonHelper.safeGetInt(json, "fat");
}
return food;
}
public boolean isEqual(Food other) {
if (portion != other.portion)
return false;
@ -104,4 +128,22 @@ public class Food {
units = other.units;
gi = other.gi;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("_id=" + _id + ";");
sb.append("isValid=" + isValid + ";");
sb.append("name=" + name + ";");
sb.append("category=" + category + ";");
sb.append("subcategory=" + subcategory + ";");
sb.append("portion=" + portion + ";");
sb.append("carbs=" + carbs + ";");
sb.append("protein=" + protein + ";");
sb.append("energy=" + energy + ";");
sb.append("units=" + units + ";");
sb.append("gi=" + gi + ";");
return sb.toString();
}
}

View file

@ -18,7 +18,6 @@ import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import com.crashlytics.android.Crashlytics;
import com.squareup.otto.Subscribe;
import org.slf4j.Logger;
@ -27,12 +26,13 @@ import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.db.Food;
import info.nightscout.androidaps.events.EventFoodDatabaseChanged;
import info.nightscout.androidaps.plugins.Common.SubscriberFragment;
import info.nightscout.utils.FabricPrivacy;
import info.nightscout.utils.NSUpload;
import info.nightscout.utils.SpinnerHelper;
@ -121,7 +121,8 @@ public class FoodFragment extends SubscriberFragment {
}
});
RecyclerViewAdapter adapter = new RecyclerViewAdapter(MainApp.getDbHelper().foodHelper.getFoodData());
RecyclerViewAdapter adapter = new RecyclerViewAdapter(MainApp
.getSpecificPlugin(FoodPlugin.class).getService().getFoodData());
recyclerView.setAdapter(adapter);
loadData();
@ -130,7 +131,7 @@ public class FoodFragment extends SubscriberFragment {
filterData();
return view;
} catch (Exception e) {
Crashlytics.logException(e);
FabricPrivacy.logException(e);
}
return null;
@ -144,20 +145,19 @@ public class FoodFragment extends SubscriberFragment {
}
void loadData() {
unfiltered = MainApp.getDbHelper().foodHelper.getFoodData();
unfiltered = MainApp.getSpecificPlugin(FoodPlugin.class).getService().getFoodData();
}
void fillCategories() {
categories = new ArrayList<>();
Set<CharSequence> catSet = new HashSet<>();
for (Food f : unfiltered) {
if (f.category != null && !f.category.equals(""))
categories.add(f.category);
catSet.add(f.category);
}
// make it unique
categories = new ArrayList<>(new HashSet<>(categories));
categories = new ArrayList<>(catSet);
categories.add(0, MainApp.sResources.getString(R.string.none));
ArrayAdapter<CharSequence> adapterCategories = new ArrayAdapter<>(getContext(),
@ -167,19 +167,19 @@ public class FoodFragment extends SubscriberFragment {
void fillSubcategories() {
String categoryFilter = category.getSelectedItem().toString();
subcategories = new ArrayList<>();
Set<CharSequence> subCatSet = new HashSet<>();
if (!categoryFilter.equals(EMPTY)) {
for (Food f : unfiltered) {
if (f.category != null && f.category.equals(categoryFilter))
if (f.subcategory != null && !f.subcategory.equals(""))
subcategories.add(f.subcategory);
subCatSet.add(f.subcategory);
}
}
// make it unique
subcategories = new ArrayList<>(new HashSet<>(subcategories));
subcategories = new ArrayList<>(subCatSet);
subcategories.add(0, MainApp.sResources.getString(R.string.none));
ArrayAdapter<CharSequence> adapterSubcategories = new ArrayAdapter<>(getContext(),
@ -299,7 +299,7 @@ public class FoodFragment extends SubscriberFragment {
if (_id != null && !_id.equals("")) {
NSUpload.removeFoodFromNS(_id);
}
MainApp.getDbHelper().foodHelper.delete(food);
MainApp.getSpecificPlugin(FoodPlugin.class).getService().delete(food);
}
});
builder.setNegativeButton(MainApp.sResources.getString(R.string.cancel), null);

View file

@ -13,6 +13,12 @@ public class FoodPlugin implements PluginBase {
private static FoodPlugin plugin = null;
private FoodService service;
private FoodPlugin() {
this.service = new FoodService();
}
public static FoodPlugin getPlugin() {
if (plugin == null)
plugin = new FoodPlugin();
@ -81,5 +87,8 @@ public class FoodPlugin implements PluginBase {
return -1;
}
public FoodService getService() {
return this.service;
}
}

View file

@ -0,0 +1,368 @@
package info.nightscout.androidaps.plugins.Food;
import android.content.Intent;
import android.os.Bundle;
import android.os.IBinder;
import android.support.annotation.Nullable;
import com.j256.ormlite.android.apptools.OpenHelperManager;
import com.j256.ormlite.android.apptools.OrmLiteBaseService;
import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.dao.DaoManager;
import com.j256.ormlite.support.ConnectionSource;
import com.j256.ormlite.table.TableUtils;
import com.squareup.otto.Subscribe;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.db.DatabaseHelper;
import info.nightscout.androidaps.db.ICallback;
import info.nightscout.androidaps.events.Event;
import info.nightscout.androidaps.events.EventFoodDatabaseChanged;
import info.nightscout.androidaps.events.EventNsFood;
/**
* Created by mike on 24.09.2017.
*/
public class FoodService extends OrmLiteBaseService<DatabaseHelper> {
private static Logger log = LoggerFactory.getLogger(FoodService.class);
private static final ScheduledExecutorService foodEventWorker = Executors.newSingleThreadScheduledExecutor();
private static ScheduledFuture<?> scheduledFoodEventPost = null;
public FoodService() {
onCreate();
dbInitialize();
MainApp.bus().register(this);
}
/**
* This method is a simple re-implementation of the database create and up/downgrade functionality
* in SQLiteOpenHelper#getDatabaseLocked method.
* <p>
* It is implemented to be able to late initialize separate plugins of the application.
*/
protected void dbInitialize() {
DatabaseHelper helper = OpenHelperManager.getHelper(this, DatabaseHelper.class);
int newVersion = helper.getNewVersion();
int oldVersion = helper.getOldVersion();
if (oldVersion > newVersion) {
onDowngrade(this.getConnectionSource(), oldVersion, newVersion);
} else {
onUpgrade(this.getConnectionSource(), oldVersion, newVersion);
}
}
public Dao<Food, Long> getDao() {
try {
return DaoManager.createDao(this.getConnectionSource(), Food.class);
} catch (SQLException e) {
log.error("Cannot create Dao for Food.class");
}
return null;
}
@Subscribe
public void handleNsEvent(EventNsFood event) {
int mode = event.getMode();
Bundle payload = event.getPayload();
try {
if (payload.containsKey("food")) {
JSONObject json = new JSONObject(payload.getString("food"));
if (mode == EventNsFood.ADD || mode == EventNsFood.UPDATE) {
this.createFoodFromJsonIfNotExists(json);
} else {
this.deleteNS(json);
}
}
if (payload.containsKey("foods")) {
JSONArray array = new JSONArray(payload.getString("foods"));
if (mode == EventNsFood.ADD || mode == EventNsFood.UPDATE) {
this.createFoodFromJsonIfNotExists(array);
} else {
this.deleteNS(array);
}
}
} catch (JSONException e) {
log.error("Unhandled Exception", e);
}
}
@Override
public void onCreate() {
super.onCreate();
try {
log.info("onCreate");
TableUtils.createTableIfNotExists(this.getConnectionSource(), Food.class);
} catch (SQLException e) {
log.error("Can't create database", e);
throw new RuntimeException(e);
}
}
public void onUpgrade(ConnectionSource connectionSource, int oldVersion, int newVersion) {
if (oldVersion == 7 && newVersion == 8) {
log.debug("Upgrading database from v7 to v8");
} else {
log.info("onUpgrade");
// this.resetFood();
}
}
public void onDowngrade(ConnectionSource connectionSource, int oldVersion, int newVersion) {
// this method is not supported right now
}
public void resetFood() {
try {
TableUtils.dropTable(this.getConnectionSource(), Food.class, true);
TableUtils.createTableIfNotExists(this.getConnectionSource(), Food.class);
} catch (SQLException e) {
log.error("Unhandled exception", e);
}
scheduleFoodChange();
}
/**
* A place to centrally register events to be posted, if any data changed.
* This should be implemented in an abstract service-class.
* <p>
* We do need to make sure, that ICallback is extended to be able to handle multiple
* events, or handle a list of events.
* <p>
* on some methods the earliestDataChange event is handled separatly, in that it is checked if it is
* set to null by another event already (eg. scheduleExtendedBolusChange).
*
* @param event
* @param eventWorker
* @param callback
*/
private void scheduleEvent(final Event event, ScheduledExecutorService eventWorker,
final ICallback callback) {
class PostRunnable implements Runnable {
public void run() {
log.debug("Firing EventFoodChange");
MainApp.bus().post(event);
callback.setPost(null);
}
}
// prepare task for execution in 1 sec
// cancel waiting task to prevent sending multiple posts
if (callback.getPost() != null)
callback.getPost().cancel(false);
Runnable task = new PostRunnable();
final int sec = 1;
callback.setPost(eventWorker.schedule(task, sec, TimeUnit.SECONDS));
}
/**
* Schedule a foodChange Event.
*/
public void scheduleFoodChange() {
this.scheduleEvent(new EventFoodDatabaseChanged(), foodEventWorker, new ICallback() {
@Override
public void setPost(ScheduledFuture<?> post) {
scheduledFoodEventPost = post;
}
@Override
public ScheduledFuture<?> getPost() {
return scheduledFoodEventPost;
}
});
}
public List<Food> getFoodData() {
try {
return this.getDao().queryForAll();
} catch (SQLException e) {
log.error("Unhandled exception", e);
}
return new ArrayList<>();
}
/*
{
"_id": "551ee3ad368e06e80856e6a9",
"type": "food",
"category": "Zakladni",
"subcategory": "Napoje",
"name": "Mleko",
"portion": 250,
"carbs": 12,
"gi": 1,
"created_at": "2015-04-14T06:59:16.500Z",
"unit": "ml"
}
*/
public void createFoodFromJsonIfNotExists(JSONObject json) {
try {
Food food = Food.createFromJson(json);
this.createFoodFromJsonIfNotExists(food);
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
}
public void createFoodFromJsonIfNotExists(JSONArray array) {
try {
for (int n = 0; n < array.length(); n++) {
JSONObject json = array.getJSONObject(n);
Food food = Food.createFromJson(json);
this.createFoodFromJsonIfNotExists(food);
}
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
}
public void createFoodFromJsonIfNotExists(Food food) {
this.createOrUpdateByNS(food);
}
public void deleteNS(JSONObject json) {
try {
String _id = json.getString("_id");
this.deleteByNSId(_id);
} catch (JSONException | SQLException e) {
log.error("Unhandled exception", e);
}
}
public void deleteNS(JSONArray array) {
try {
for (int n = 0; n < array.length(); n++) {
JSONObject json = array.getJSONObject(n);
this.deleteNS(json);
}
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
}
/**
* deletes an entry by its NS Id.
* <p>
* Basically a convenience method for findByNSId and delete.
*
* @param _id
*/
public void deleteByNSId(String _id) throws SQLException {
Food stored = this.findByNSId(_id);
if (stored != null) {
log.debug("FOOD: Removing Food record from database: " + stored.toString());
this.delete(stored);
}
}
/**
* deletes the food and sends the foodChange Event
* <p>
* should be moved ot a Service
*
* @param food
*/
public void delete(Food food) {
try {
this.getDao().delete(food);
this.scheduleFoodChange();
} catch (SQLException e) {
log.error("Unhandled exception", e);
}
}
/**
* Create of update a food record by the NS (Nightscout) Id.
*
* @param food
* @return
*/
public boolean createOrUpdateByNS(Food food) {
// find by NS _id
if (food._id != null && !food._id.equals("")) {
Food old = this.findByNSId(food._id);
if (old != null) {
if (!old.isEqual(food)) {
this.delete(old); // need to delete/create because date may change too
old.copyFrom(food);
this.create(old);
return true;
} else {
return false;
}
} else {
this.createOrUpdate(food);
return true;
}
}
return false;
}
public void createOrUpdate(Food food) {
try {
this.getDao().createOrUpdate(food);
log.debug("FOOD: Created or Updated: " + food.toString());
} catch (SQLException e) {
log.error("Unable to createOrUpdate Food", e);
}
this.scheduleFoodChange();
}
public void create(Food food) {
try {
this.getDao().create(food);
log.debug("FOOD: New record: " + food.toString());
} catch (SQLException e) {
log.error("Unable to create Food", e);
}
this.scheduleFoodChange();
}
/**
* finds food by its NS Id.
*
* @param _id
* @return
*/
public Food findByNSId(String _id) {
try {
List<Food> list = this.getDao().queryForEq("_id", _id);
if (list.size() == 1) { // really? if there are more then one result, then we do not return anything...
return list.get(0);
}
} catch (SQLException e) {
log.error("Unhandled exception", e);
}
return null;
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
}

View file

@ -7,11 +7,11 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.crashlytics.android.Crashlytics;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.utils.FabricPrivacy;
/**
* Created by mike on 17.04.2017.
@ -37,7 +37,7 @@ public class InsulinFragment extends Fragment {
return view;
} catch (Exception e) {
Crashlytics.logException(e);
FabricPrivacy.logException(e);
}
return null;

View file

@ -57,11 +57,15 @@ public class AutosensData {
public double cob = 0;
public double bgi = 0d;
public double delta = 0d;
public double avgDelta = 0d;
public double avgDeviation = 0d;
public double autosensRatio = 1d;
public double slopeFromMaxDeviation = 0;
public double slopeFromMinDeviation = 999;
public 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() {

View file

@ -22,6 +22,7 @@ import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.events.Event;
import info.nightscout.androidaps.events.EventAppInitialized;
import info.nightscout.androidaps.events.EventConfigBuilderChange;
import info.nightscout.androidaps.events.EventNewBG;
@ -30,6 +31,7 @@ import info.nightscout.androidaps.events.EventPreferenceChange;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventNewHistoryData;
import info.nightscout.androidaps.plugins.OpenAPSSMB.OpenAPSSMBPlugin;
import info.nightscout.utils.DateUtil;
/**
@ -39,19 +41,19 @@ import info.nightscout.utils.DateUtil;
public class IobCobCalculatorPlugin implements PluginBase {
private static Logger log = LoggerFactory.getLogger(IobCobCalculatorPlugin.class);
private static LongSparseArray<IobTotal> iobTable = new LongSparseArray<>(); // oldest at index 0
private static LongSparseArray<AutosensData> autosensDataTable = new LongSparseArray<>(); // oldest at index 0
private static LongSparseArray<BasalData> basalDataTable = new LongSparseArray<>(); // oldest at index 0
private LongSparseArray<IobTotal> iobTable = new LongSparseArray<>(); // oldest at index 0
private LongSparseArray<AutosensData> autosensDataTable = new LongSparseArray<>(); // oldest at index 0
private LongSparseArray<BasalData> basalDataTable = new LongSparseArray<>(); // oldest at index 0
private static volatile List<BgReading> bgReadings = null; // newest at index 0
private static volatile List<BgReading> bucketed_data = null;
private volatile List<BgReading> bgReadings = null; // newest at index 0
private volatile List<BgReading> bucketed_data = null;
private static double dia = Constants.defaultDIA;
private double dia = Constants.defaultDIA;
static final Object dataLock = new Object();
final Object dataLock = new Object();
boolean stopCalculationTrigger = false;
IobCobThread thread = null;
private IobCobThread thread = null;
private static IobCobCalculatorPlugin plugin = null;
@ -61,11 +63,11 @@ public class IobCobCalculatorPlugin implements PluginBase {
return plugin;
}
public static LongSparseArray<AutosensData> getAutosensDataTable() {
public LongSparseArray<AutosensData> getAutosensDataTable() {
return autosensDataTable;
}
public static List<BgReading> getBucketedData() {
public List<BgReading> getBucketedData() {
return bucketed_data;
}
@ -129,12 +131,12 @@ public class IobCobCalculatorPlugin implements PluginBase {
return -1;
}
IobCobCalculatorPlugin() {
public IobCobCalculatorPlugin() {
MainApp.bus().register(this);
}
@Nullable
public static List<BgReading> getBucketedData(long fromTime) {
public List<BgReading> getBucketedData(long fromTime) {
//log.debug("Locking getBucketedData");
synchronized (dataLock) {
if (bucketed_data == null) {
@ -152,7 +154,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
return null;
}
private static int indexNewerThan(long time) {
private int indexNewerThan(long time) {
for (int index = 0; index < bucketed_data.size(); index++) {
if (bucketed_data.get(index).date < time)
return index - 1;
@ -167,9 +169,9 @@ public class IobCobCalculatorPlugin implements PluginBase {
return rouded;
}
void loadBgData() {
bgReadings = MainApp.getDbHelper().getBgreadingsDataFromTime((long) (System.currentTimeMillis() - 60 * 60 * 1000L * (24 + dia)), false);
log.debug("BG data loaded. Size: " + bgReadings.size());
void loadBgData(long start) {
bgReadings = MainApp.getDbHelper().getBgreadingsDataFromTime((long) (start - 60 * 60 * 1000L * (24 + dia)), false);
log.debug("BG data loaded. Size: " + bgReadings.size() + " Start date: " + DateUtil.dateAndTimeString(start));
}
private boolean isAbout5minData() {
@ -259,7 +261,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
}
public void createBucketedData5min() {
private void createBucketedData5min() {
if (bgReadings == null || bgReadings.size() < 3) {
bucketed_data = null;
return;
@ -330,13 +332,13 @@ public class IobCobCalculatorPlugin implements PluginBase {
return getBGDataFrom;
}
public static IobTotal calculateFromTreatmentsAndTempsSynchronized(long time) {
public IobTotal calculateFromTreatmentsAndTempsSynchronized(long time) {
synchronized (dataLock) {
return calculateFromTreatmentsAndTemps(time);
}
}
public static IobTotal calculateFromTreatmentsAndTemps(long time) {
public IobTotal calculateFromTreatmentsAndTemps(long time) {
long now = System.currentTimeMillis();
time = roundUpTime(time);
if (time < now && iobTable.get(time) != null) {
@ -347,6 +349,21 @@ public class IobCobCalculatorPlugin implements PluginBase {
}
IobTotal bolusIob = MainApp.getConfigBuilder().getCalculationToTimeTreatments(time).round();
IobTotal basalIob = MainApp.getConfigBuilder().getCalculationToTimeTempBasals(time).round();
if (OpenAPSSMBPlugin.getPlugin().isEnabled(PluginBase.APS)) {
// Add expected zere temp basal for next 240 mins
IobTotal basalIobWithZeroTemp = basalIob.clone();
TemporaryBasal t = new TemporaryBasal();
t.date = now + 60 * 1000L;
t.durationInMinutes = 240;
t.isAbsolute = true;
t.absoluteRate = 0;
if (t.date < time) {
IobTotal calc = t.iobCalc(time);
basalIobWithZeroTemp.plus(calc);
}
basalIob.iobWithZeroTemp = basalIobWithZeroTemp;
}
IobTotal iobTotal = IobTotal.combine(bolusIob, basalIob).round();
if (time < System.currentTimeMillis()) {
@ -356,7 +373,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
}
@Nullable
private static Long findPreviousTimeFromBucketedData(long time) {
private Long findPreviousTimeFromBucketedData(long time) {
if (bucketed_data == null)
return null;
for (int index = 0; index < bucketed_data.size(); index++) {
@ -366,7 +383,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
return null;
}
public static BasalData getBasalData(long time) {
public BasalData getBasalData(long time) {
long now = System.currentTimeMillis();
time = roundUpTime(time);
BasalData retval = basalDataTable.get(time);
@ -392,7 +409,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
}
@Nullable
public static AutosensData getAutosensData(long time) {
public AutosensData getAutosensData(long time) {
synchronized (dataLock) {
long now = System.currentTimeMillis();
if (time > now)
@ -417,7 +434,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
}
@Nullable
public static AutosensData getLastAutosensDataSynchronized(String reason) {
public AutosensData getLastAutosensDataSynchronized(String reason) {
synchronized (dataLock) {
return getLastAutosensData(reason);
}
@ -425,7 +442,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
@Nullable
public static AutosensData getLastAutosensData(String reason) {
public AutosensData getLastAutosensData(String reason) {
if (autosensDataTable.size() < 1) {
log.debug("AUTOSENSDATA null: autosensDataTable empty (" + reason + ")");
return null;
@ -450,7 +467,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
}
}
public static IobTotal[] calculateIobArrayInDia() {
public IobTotal[] calculateIobArrayInDia() {
Profile profile = MainApp.getConfigBuilder().getProfile();
// predict IOB out to DIA plus 30m
long time = System.currentTimeMillis();
@ -467,7 +484,24 @@ public class IobCobCalculatorPlugin implements PluginBase {
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) {
return detectSensitivity(fromTime, toTime);
}
@ -487,13 +521,21 @@ public class IobCobCalculatorPlugin implements PluginBase {
@Subscribe
public void onEventAppInitialized(EventAppInitialized ev) {
runCalculation("onEventAppInitialized", true);
if (this != getPlugin()) {
log.debug("Ignoring event for non default instance");
return;
}
runCalculation("onEventAppInitialized", System.currentTimeMillis(), true, ev);
}
@Subscribe
public void onEventNewBG(EventNewBG ev) {
if (this != getPlugin()) {
log.debug("Ignoring event for non default instance");
return;
}
stopCalculation("onEventNewBG");
runCalculation("onEventNewBG", true);
runCalculation("onEventNewBG", System.currentTimeMillis(), true, ev);
}
private void stopCalculation(String from) {
@ -507,16 +549,20 @@ public class IobCobCalculatorPlugin implements PluginBase {
}
}
private void runCalculation(String from, boolean bgDataReload) {
public void runCalculation(String from, long start, boolean bgDataReload, Event cause) {
log.debug("Starting calculation thread: " + from);
if (thread == null || thread.getState() == Thread.State.TERMINATED) {
thread = new IobCobThread(this, from, bgDataReload);
thread = new IobCobThread(this, from, start, bgDataReload, cause);
thread.start();
}
}
@Subscribe
public void onNewProfile(EventNewBasalProfile ev) {
if (this != getPlugin()) {
log.debug("Ignoring event for non default instance");
return;
}
if (MainApp.getConfigBuilder() == null)
return; // app still initializing
Profile profile = MainApp.getConfigBuilder().getProfile();
@ -532,11 +578,15 @@ public class IobCobCalculatorPlugin implements PluginBase {
iobTable = new LongSparseArray<>();
autosensDataTable = new LongSparseArray<>();
}
runCalculation("onNewProfile", false);
runCalculation("onNewProfile", System.currentTimeMillis(), false, ev);
}
@Subscribe
public void onEventPreferenceChange(EventPreferenceChange ev) {
if (this != getPlugin()) {
log.debug("Ignoring event for non default instance");
return;
}
if (ev.isChanged(R.string.key_openapsama_autosens_period) ||
ev.isChanged(R.string.key_age) ||
ev.isChanged(R.string.key_absorption_maxtime)
@ -547,24 +597,32 @@ public class IobCobCalculatorPlugin implements PluginBase {
iobTable = new LongSparseArray<>();
autosensDataTable = new LongSparseArray<>();
}
runCalculation("onEventPreferenceChange", false);
runCalculation("onEventPreferenceChange", System.currentTimeMillis(), false, ev);
}
}
@Subscribe
public void onEventConfigBuilderChange(EventConfigBuilderChange ev) {
if (this != getPlugin()) {
log.debug("Ignoring event for non default instance");
return;
}
stopCalculation("onEventConfigBuilderChange");
synchronized (dataLock) {
log.debug("Invalidating cached data because of configuration change. IOB: " + iobTable.size() + " Autosens: " + autosensDataTable.size() + " records");
iobTable = new LongSparseArray<>();
autosensDataTable = new LongSparseArray<>();
}
runCalculation("onEventConfigBuilderChange", false);
runCalculation("onEventConfigBuilderChange", System.currentTimeMillis(), false, ev);
}
// When historical data is changed (comming from NS etc) finished calculations after this date must be invalidated
@Subscribe
public void onEventNewHistoryData(EventNewHistoryData ev) {
if (this != getPlugin()) {
log.debug("Ignoring event for non default instance");
return;
}
//log.debug("Locking onNewHistoryData");
stopCalculation("onEventNewHistoryData");
synchronized (dataLock) {
@ -599,10 +657,18 @@ public class IobCobCalculatorPlugin implements PluginBase {
}
}
}
runCalculation("onEventNewHistoryData", false);
runCalculation("onEventNewHistoryData", System.currentTimeMillis(), false, ev);
//log.debug("Releasing onNewHistoryData");
}
public void clearCache() {
synchronized (dataLock) {
log.debug("Clearing cached data.");
iobTable = new LongSparseArray<>();
autosensDataTable = new LongSparseArray<>();
}
}
// From https://gist.github.com/IceCreamYou/6ffa1b18c4c8f6aeaad2
// Returns the value at a given percentile in a sorted numeric array.
// "Linear interpolation between closest ranks" method

View file

@ -18,12 +18,10 @@ 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 static info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin.getBucketedData;
import static info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin.oldestDataAvailable;
import static info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin.roundUpTime;
import info.nightscout.utils.DateUtil;
/**
* Created by mike on 23.01.2018.
@ -31,19 +29,23 @@ import static info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculat
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, boolean bgDataReload) {
public IobCobThread(IobCobCalculatorPlugin plugin, String from, long start, boolean bgDataReload, Event cause) {
super();
this.iobCobCalculatorPlugin = plugin;
this.bgDataReload = bgDataReload;
this.from = from;
this.cause = cause;
this.start = start;
PowerManager powerManager = (PowerManager) MainApp.instance().getApplicationContext().getSystemService(Context.POWER_SERVICE);
mWakeLock = powerManager.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "iobCobThread");
@ -65,14 +67,14 @@ public class IobCobThread extends Thread {
Object dataLock = iobCobCalculatorPlugin.dataLock;
long oldestTimeWithData = oldestDataAvailable();
long oldestTimeWithData = iobCobCalculatorPlugin.oldestDataAvailable();
synchronized (dataLock) {
if (bgDataReload) {
iobCobCalculatorPlugin.loadBgData();
iobCobCalculatorPlugin.loadBgData(start);
iobCobCalculatorPlugin.createBucketedData();
}
List<BgReading> bucketed_data = getBucketedData();
List<BgReading> bucketed_data = iobCobCalculatorPlugin.getBucketedData();
LongSparseArray<AutosensData> autosensDataTable = iobCobCalculatorPlugin.getAutosensDataTable();
if (bucketed_data == null || bucketed_data.size() < 3) {
@ -80,7 +82,7 @@ public class IobCobThread extends Thread {
return;
}
long prevDataTime = roundUpTime(bucketed_data.get(bucketed_data.size() - 3).date);
long prevDataTime = iobCobCalculatorPlugin.roundUpTime(bucketed_data.get(bucketed_data.size() - 3).date);
log.debug("Prev data time: " + new Date(prevDataTime).toLocaleString());
AutosensData previous = autosensDataTable.get(prevDataTime);
// start from oldest to be able sub cob
@ -92,7 +94,7 @@ public class IobCobThread extends Thread {
}
// check if data already exists
long bgTime = bucketed_data.get(i).date;
bgTime = roundUpTime(bgTime);
bgTime = iobCobCalculatorPlugin.roundUpTime(bgTime);
if (bgTime > System.currentTimeMillis())
continue;
Profile profile = MainApp.getConfigBuilder().getProfile(bgTime);
@ -135,11 +137,43 @@ public class IobCobThread extends Thread {
continue;
}
delta = (bg - bucketed_data.get(i + 1).value);
avgDelta = (bg - bucketed_data.get(i + 3).value) / 3;
IobTotal iob = iobCobCalculatorPlugin.calculateFromTreatmentsAndTemps(bgTime);
double bgi = -iob.activity * sens * 5;
double deviation = delta - bgi;
double avgDeviation = Math.round((avgDelta - bgi) * 1000) / 1000;
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) {
int initialIndex = autosensDataTable.indexOfKey(hourAgoData.time);
for (int past = 1; past < 12; past++) {
AutosensData ad = autosensDataTable.valueAt(initialIndex + past);
double deviationSlope = (ad.avgDeviation - avgDeviation) / (ad.time - bgTime) * 1000 * 60 * 5;
if (ad.avgDeviation > maxDeviation) {
slopeFromMaxDeviation = Math.min(0, deviationSlope);
maxDeviation = ad.avgDeviation;
}
if (ad.avgDeviation < minDeviation) {
slopeFromMinDeviation = Math.max(0, deviationSlope);
minDeviation = ad.avgDeviation;
}
//if (Config.logAutosensData)
// log.debug("Deviations: " + new Date(bgTime) + new Date(ad.time) + " avgDeviation=" + avgDeviation + " deviationSlope=" + deviationSlope + " slopeFromMaxDeviation=" + slopeFromMaxDeviation + " slopeFromMinDeviation=" + slopeFromMinDeviation);
}
}
}
List<Treatment> recentTreatments = MainApp.getConfigBuilder().getTreatments5MinBackFromHistory(bgTime);
for (int ir = 0; ir < recentTreatments.size(); ir++) {
@ -170,6 +204,11 @@ public class IobCobThread extends Thread {
autosensData.deviation = deviation;
autosensData.bgi = bgi;
autosensData.delta = delta;
autosensData.avgDelta = avgDelta;
autosensData.avgDeviation = avgDeviation;
autosensData.slopeFromMaxDeviation = slopeFromMaxDeviation;
autosensData.slopeFromMinDeviation = slopeFromMinDeviation;
// calculate autosens only without COB
if (autosensData.cob <= 0) {
@ -191,12 +230,13 @@ public class IobCobThread extends Thread {
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());
MainApp.bus().post(new EventAutosensCalculationFinished(cause));
log.debug("Finishing calculation thread: " + from);
} finally {
mWakeLock.release();

View file

@ -1,5 +1,6 @@
package info.nightscout.androidaps.plugins.IobCobCalculator.events;
import info.nightscout.androidaps.events.Event;
import info.nightscout.androidaps.events.EventLoop;
/**
@ -7,4 +8,9 @@ import info.nightscout.androidaps.events.EventLoop;
*/
public class EventAutosensCalculationFinished extends EventLoop {
public Event cause;
public EventAutosensCalculationFinished(Event cause) {
this.cause = cause;
}
}

View file

@ -1,17 +1,22 @@
package info.nightscout.androidaps.plugins.Loop;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.Html;
import android.text.Spanned;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.utils.DecimalFormatter;
@ -22,36 +27,64 @@ import info.nightscout.utils.DecimalFormatter;
public class APSResult {
private static Logger log = LoggerFactory.getLogger(APSResult.class);
public Date date;
public String reason;
public double rate;
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
public String toString() {
final PumpInterface pump = ConfigBuilderPlugin.getActivePump();
if (changeRequested) {
if (isChangeRequested()) {
String ret;
// rate
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
return MainApp.sResources.getString(R.string.rate) + ": " + DecimalFormatter.to2Decimal(rate) + " U/h " +
"(" + DecimalFormatter.to2Decimal(rate / pump.getBaseBasalRate() * 100) + "%)\n" +
MainApp.sResources.getString(R.string.duration) + ": " + DecimalFormatter.to0Decimal(duration) + " min\n" +
MainApp.sResources.getString(R.string.reason) + ": " + reason;
ret = MainApp.sResources.getString(R.string.rate) + ": " + DecimalFormatter.to2Decimal(rate) + " U/h " +
"(" + DecimalFormatter.to2Decimal(rate / pump.getBaseBasalRate() * 100) + "%) \n" +
MainApp.sResources.getString(R.string.duration) + ": " + DecimalFormatter.to2Decimal(duration) + " min\n";
// smb
if (smb != 0)
ret += ("SMB: " + DecimalFormatter.to2Decimal(smb) + " U\n");
// reason
ret += MainApp.sResources.getString(R.string.reason) + ": " + reason;
return ret;
} else
return MainApp.sResources.getString(R.string.nochangerequested);
}
public Spanned toSpanned() {
final PumpInterface pump = ConfigBuilderPlugin.getActivePump();
if (changeRequested) {
String ret = "";
if (rate == 0 && duration == 0) ret = MainApp.sResources.getString(R.string.canceltemp);
if (isChangeRequested()) {
String ret;
// 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
ret = "<b>" + MainApp.sResources.getString(R.string.rate) + "</b>: " + DecimalFormatter.to2Decimal(rate) + " U/h " +
"(" + 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.reason) + "</b>: " + reason.replace("<", "&lt;").replace(">", "&gt;");
"(" + DecimalFormatter.to2Decimal(rate / pump.getBaseBasalRate() * 100) + "%) <br>" +
"<b>" + MainApp.sResources.getString(R.string.duration) + "</b>: " + DecimalFormatter.to2Decimal(duration) + " min<br>";
// 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("<", "&lt;").replace(">", "&gt;");
return Html.fromHtml(ret);
} else
return Html.fromHtml(MainApp.sResources.getString(R.string.nochangerequested));
@ -62,17 +95,19 @@ public class APSResult {
public APSResult clone() {
APSResult newResult = new APSResult();
newResult.reason = new String(reason);
newResult.reason = reason;
newResult.rate = rate;
newResult.duration = duration;
newResult.changeRequested = changeRequested;
newResult.tempBasalReqested = tempBasalReqested;
newResult.bolusRequested = bolusRequested;
newResult.iob = iob;
return newResult;
}
public JSONObject json() {
JSONObject json = new JSONObject();
try {
if (changeRequested) {
if (isChangeRequested()) {
json.put("rate", rate);
json.put("duration", duration);
json.put("reason", reason);
@ -82,4 +117,105 @@ public class APSResult {
}
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;
}
}

View file

@ -9,8 +9,6 @@ import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import com.crashlytics.android.Crashlytics;
import com.crashlytics.android.answers.Answers;
import com.crashlytics.android.answers.CustomEvent;
import com.squareup.otto.Subscribe;
@ -22,6 +20,7 @@ import info.nightscout.androidaps.R;
import info.nightscout.androidaps.plugins.Common.SubscriberFragment;
import info.nightscout.androidaps.plugins.Loop.events.EventLoopSetLastRunGui;
import info.nightscout.androidaps.plugins.Loop.events.EventLoopUpdateGui;
import info.nightscout.utils.FabricPrivacy;
public class LoopFragment extends SubscriberFragment implements View.OnClickListener {
private static Logger log = LoggerFactory.getLogger(LoopFragment.class);
@ -53,7 +52,7 @@ public class LoopFragment extends SubscriberFragment implements View.OnClickList
updateGUI();
return view;
} catch (Exception e) {
Crashlytics.logException(e);
FabricPrivacy.logException(e);
}
return null;
@ -71,7 +70,7 @@ public class LoopFragment extends SubscriberFragment implements View.OnClickList
}
});
thread.start();
Answers.getInstance().logCustom(new CustomEvent("Loop_Run"));
FabricPrivacy.getInstance().logCustom(new CustomEvent("Loop_Run"));
break;
}

View file

@ -8,7 +8,6 @@ import android.content.Context;
import android.content.Intent;
import android.support.v4.app.NotificationCompat;
import com.crashlytics.android.answers.Answers;
import com.crashlytics.android.answers.CustomEvent;
import com.squareup.otto.Subscribe;
@ -30,10 +29,14 @@ import info.nightscout.androidaps.interfaces.ConstraintsInterface;
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.events.EventAutosensCalculationFinished;
import info.nightscout.androidaps.plugins.Loop.events.EventLoopResult;
import info.nightscout.androidaps.plugins.Loop.events.EventLoopSetLastRunGui;
import info.nightscout.androidaps.plugins.Loop.events.EventLoopUpdateGui;
import info.nightscout.androidaps.plugins.Loop.events.EventNewOpenLoopNotification;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.androidaps.queue.Callback;
import info.nightscout.utils.FabricPrivacy;
import info.nightscout.utils.NSUpload;
import info.nightscout.utils.SP;
@ -148,12 +151,16 @@ public class LoopPlugin implements PluginBase {
@Subscribe
public void onStatusEvent(final EventTreatmentChange ev) {
invoke("EventTreatmentChange", true);
if (ev.treatment == null || !ev.treatment.isSMB){
invoke("EventTreatmentChange", true);
}
}
@Subscribe
public void onStatusEvent(final EventNewBG ev) {
invoke("EventNewBG", true);
public void onStatusEvent(final EventAutosensCalculationFinished ev) {
if (ev.cause instanceof EventNewBG) {
invoke(ev.getClass().getSimpleName() + "(" + ev.cause.getClass().getSimpleName() + ")", true);
}
}
public long suspendedTo() {
@ -283,6 +290,14 @@ public class LoopPlugin implements PluginBase {
// check rate for constrais
final APSResult resultAfterConstraints = result.clone();
resultAfterConstraints.rate = constraintsInterface.applyBasalConstraints(resultAfterConstraints.rate);
resultAfterConstraints.smb = constraintsInterface.applyBolusConstraints(resultAfterConstraints.smb);
// 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();
lastRun.request = result;
@ -305,8 +320,10 @@ public class LoopPlugin implements PluginBase {
return;
}
MainApp.bus().post(new EventLoopResult(resultAfterConstraints));
if (constraintsInterface.isClosedModeEnabled()) {
if (result.changeRequested) {
if (result.isChangeRequested()) {
final PumpEnactResult waiting = new PumpEnactResult();
final PumpEnactResult previousResult = lastRun.setByPump;
waiting.queued = true;
@ -315,7 +332,7 @@ public class LoopPlugin implements PluginBase {
MainApp.getConfigBuilder().applyAPSRequest(resultAfterConstraints, new Callback() {
@Override
public void run() {
Answers.getInstance().logCustom(new CustomEvent("APSRequest"));
FabricPrivacy.getInstance().logCustom(new CustomEvent("APSRequest"));
if (result.enacted || result.success) {
lastRun.setByPump = result;
lastRun.lastEnact = lastRun.lastAPSRun;
@ -330,7 +347,7 @@ public class LoopPlugin implements PluginBase {
lastRun.source = null;
}
} else {
if (result.changeRequested && allowNotification) {
if (result.isChangeRequested() && allowNotification) {
NotificationCompat.Builder builder =
new NotificationCompat.Builder(MainApp.instance().getApplicationContext());
builder.setSmallIcon(R.drawable.notif_icon)

View file

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

View file

@ -18,8 +18,6 @@ import android.widget.CompoundButton;
import android.widget.ScrollView;
import android.widget.TextView;
import com.crashlytics.android.Crashlytics;
import com.crashlytics.android.answers.Answers;
import com.crashlytics.android.answers.CustomEvent;
import com.squareup.otto.Subscribe;
@ -33,6 +31,7 @@ import info.nightscout.androidaps.plugins.Common.SubscriberFragment;
import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientNewLog;
import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientRestart;
import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientUpdateGUI;
import info.nightscout.utils.FabricPrivacy;
import info.nightscout.utils.SP;
public class NSClientInternalFragment extends SubscriberFragment implements View.OnClickListener, CompoundButton.OnCheckedChangeListener {
@ -88,7 +87,7 @@ public class NSClientInternalFragment extends SubscriberFragment implements View
updateGUI();
return view;
} catch (Exception e) {
Crashlytics.logException(e);
FabricPrivacy.logException(e);
}
return null;
@ -99,11 +98,11 @@ public class NSClientInternalFragment extends SubscriberFragment implements View
switch (view.getId()) {
case R.id.nsclientinternal_restart:
MainApp.bus().post(new EventNSClientRestart());
Answers.getInstance().logCustom(new CustomEvent("NSClientRestart"));
FabricPrivacy.getInstance().logCustom(new CustomEvent("NSClientRestart"));
break;
case R.id.nsclientinternal_delivernow:
NSClientInternalPlugin.getPlugin().resend("GUI");
Answers.getInstance().logCustom(new CustomEvent("NSClientDeliverNow"));
FabricPrivacy.getInstance().logCustom(new CustomEvent("NSClientDeliverNow"));
break;
case R.id.nsclientinternal_clearlog:
NSClientInternalPlugin.getPlugin().clearLog();
@ -118,7 +117,7 @@ public class NSClientInternalFragment extends SubscriberFragment implements View
public void onClick(DialogInterface dialog, int id) {
UploadQueue.clearQueue();
updateGUI();
Answers.getInstance().logCustom(new CustomEvent("NSClientClearQueue"));
FabricPrivacy.getInstance().logCustom(new CustomEvent("NSClientClearQueue"));
}
});
builder.setNegativeButton(getString(R.string.cancel), null);
@ -126,7 +125,7 @@ public class NSClientInternalFragment extends SubscriberFragment implements View
break;
case R.id.nsclientinternal_showqueue:
MainApp.bus().post(new EventNSClientNewLog("QUEUE", NSClientInternalPlugin.getPlugin().queue().textList()));
Answers.getInstance().logCustom(new CustomEvent("NSClientShowQueue"));
FabricPrivacy.getInstance().logCustom(new CustomEvent("NSClientShowQueue"));
break;
}
}
@ -139,7 +138,7 @@ public class NSClientInternalFragment extends SubscriberFragment implements View
NSClientInternalPlugin.getPlugin().paused = isChecked;
MainApp.bus().post(new EventPreferenceChange(R.string.key_nsclientinternal_paused));
updateGUI();
Answers.getInstance().logCustom(new CustomEvent("NSClientPause"));
FabricPrivacy.getInstance().logCustom(new CustomEvent("NSClientPause"));
break;
case R.id.nsclientinternal_autoscroll:
SP.putBoolean(R.string.key_nsclientinternal_autoscroll, isChecked);

View file

@ -124,7 +124,7 @@ public class NSDeviceStatus {
static DeviceStatusPumpData deviceStatusPumpData = null;
public Spanned getExtendedPumpStatus() {
if (deviceStatusPumpData.extended != null)
if (deviceStatusPumpData != null && deviceStatusPumpData.extended != null)
return deviceStatusPumpData.extended;
return Html.fromHtml("");
}

View file

@ -9,7 +9,7 @@ import android.os.HandlerThread;
import android.os.IBinder;
import android.os.PowerManager;
import com.crashlytics.android.Crashlytics;
import com.google.common.base.Charsets;
import com.google.common.hash.Hashing;
import com.j256.ormlite.dao.CloseableIterator;
@ -62,6 +62,8 @@ import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotificati
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.FabricPrivacy;
import info.nightscout.utils.JsonHelper;
import info.nightscout.utils.SP;
import io.socket.client.IO;
import io.socket.client.Socket;
@ -123,7 +125,7 @@ public class NSClientService extends Service {
@Override
public void onDestroy() {
super.onDestroy();
mWakeLock.release();
if (mWakeLock.isHeld()) mWakeLock.release();
}
public class LocalBinder extends Binder {
@ -345,14 +347,14 @@ public class NSClientService extends Service {
try {
data = (JSONObject) args[0];
} catch (Exception e) {
Crashlytics.log("Wrong Announcement from NS: " + args[0]);
FabricPrivacy.log("Wrong Announcement from NS: " + args[0]);
return;
}
if (Config.detailedLog)
try {
MainApp.bus().post(new EventNSClientNewLog("ANNOUNCEMENT", data.has("message") ? data.getString("message") : "received"));
MainApp.bus().post(new EventNSClientNewLog("ANNOUNCEMENT", JsonHelper.safeGetString(data, "message", "received")));
} catch (Exception e) {
Crashlytics.logException(e);
FabricPrivacy.logException(e);
}
BroadcastAnnouncement.handleAnnouncement(data, getApplicationContext());
log.debug(data.toString());
@ -381,7 +383,7 @@ public class NSClientService extends Service {
try {
data = (JSONObject) args[0];
} catch (Exception e) {
Crashlytics.log("Wrong alarm from NS: " + args[0]);
FabricPrivacy.log("Wrong alarm from NS: " + args[0]);
return;
}
BroadcastAlarm.handleAlarm(data, getApplicationContext());
@ -409,7 +411,7 @@ public class NSClientService extends Service {
try {
data = (JSONObject) args[0];
} catch (Exception e) {
Crashlytics.log("Wrong Urgent alarm from NS: " + args[0]);
FabricPrivacy.log("Wrong Urgent alarm from NS: " + args[0]);
return;
}
if (Config.detailedLog)
@ -434,7 +436,7 @@ public class NSClientService extends Service {
try {
data = (JSONObject) args[0];
} catch (Exception e) {
Crashlytics.log("Wrong Urgent alarm from NS: " + args[0]);
FabricPrivacy.log("Wrong Urgent alarm from NS: " + args[0]);
return;
}
if (Config.detailedLog)
@ -572,22 +574,18 @@ public class NSClientService extends Service {
MainApp.bus().post(new EventNSClientNewLog("DATA", "received " + foods.length() + " foods"));
for (Integer index = 0; index < foods.length(); index++) {
JSONObject jsonFood = foods.getJSONObject(index);
NSTreatment treatment = new NSTreatment(jsonFood);
// remove from upload queue if Ack is failing
UploadQueue.removeID(jsonFood);
//Find latest date in treatment
if (treatment.getMills() != null && treatment.getMills() < System.currentTimeMillis())
if (treatment.getMills() > latestDateInReceivedData)
latestDateInReceivedData = treatment.getMills();
if (treatment.getAction() == null) {
String action = JsonHelper.safeGetString(jsonFood, "action");
if (action == null) {
addedFoods.put(jsonFood);
} else if (treatment.getAction().equals("update")) {
} else if (action.equals("update")) {
updatedFoods.put(jsonFood);
} else if (treatment.getAction().equals("remove")) {
if (treatment.getMills() != null && treatment.getMills() > System.currentTimeMillis() - 24 * 60 * 60 * 1000L) // handle 1 day old deletions only
removedFoods.put(jsonFood);
} else if (action.equals("remove")) {
removedFoods.put(jsonFood);
}
}
if (removedFoods.length() > 0) {
@ -600,18 +598,6 @@ public class NSClientService extends Service {
BroadcastFood.handleNewFood(addedFoods, MainApp.instance().getApplicationContext(), isDelta);
}
}
if (data.has("")) {
JSONArray foods = data.getJSONArray("food");
if (foods.length() > 0) {
MainApp.bus().post(new EventNSClientNewLog("DATA", "received " + foods.length() + " foods"));
for (Integer index = 0; index < foods.length(); index++) {
JSONObject jsonFood = foods.getJSONObject(index);
// remove from upload queue if Ack is failing
UploadQueue.removeID(jsonFood);
}
BroadcastDeviceStatus.handleNewFoods(foods, MainApp.instance().getApplicationContext(), isDelta);
}
}
if (data.has("mbgs")) {
JSONArray mbgs = data.getJSONArray("mbgs");
if (mbgs.length() > 0)
@ -665,7 +651,7 @@ public class NSClientService extends Service {
}
//MainApp.bus().post(new EventNSClientNewLog("NSCLIENT", "onDataUpdate end");
} finally {
wakeLock.release();
if (wakeLock.isHeld()) wakeLock.release();
}
}

View file

@ -29,6 +29,7 @@ import info.nightscout.androidaps.db.TemporaryBasal;
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.OpenAPSSMB.SMBDefaults;
import info.nightscout.utils.SP;
public class DetermineBasalAdapterAMAJS {
@ -189,8 +190,7 @@ public class DetermineBasalAdapterAMAJS {
GlucoseStatus glucoseStatus,
MealData mealData,
double autosensDataRatio,
boolean tempTargetSet,
double min_5m_carbimpact) throws JSONException {
boolean tempTargetSet) throws JSONException {
String units = profile.getUnits();
@ -206,12 +206,13 @@ public class DetermineBasalAdapterAMAJS {
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("current_basal_safety_multiplier", SP.getDouble("openapsama_current_basal_safety_multiplier", 4d));
mProfile.put("skip_neutral_temps", true);
mProfile.put("current_basal", basalrate);
mProfile.put("temptargetSet", tempTargetSet);
mProfile.put("autosens_adjust_targets", SP.getBoolean("openapsama_autosens_adjusttargets", true));
mProfile.put("min_5m_carbimpact", SP.getDouble("openapsama_min_5m_carbimpact", 3d));
//TODO: align with max-absorption model in AMA sensitivity
mProfile.put("min_5m_carbimpact", SP.getDouble("openapsama_min_5m_carbimpact", SMBDefaults.min_5m_carbimpact));
if (units.equals(Constants.MMOL)) {
mProfile.put("out_units", "mmol/L");

View file

@ -1,35 +1,28 @@
package info.nightscout.androidaps.plugins.OpenAPSAMA;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.mozilla.javascript.NativeObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
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.data.IobTotal;
public class DetermineBasalResultAMA extends APSResult {
private static Logger log = LoggerFactory.getLogger(DetermineBasalResultAMA.class);
public Date date;
public JSONObject json = new JSONObject();
public double eventualBG;
public double snoozeBG;
public IobTotal iob;
public DetermineBasalResultAMA(NativeObject result, JSONObject j) {
this();
date = new Date();
json = j;
if (result.containsKey("error")) {
reason = result.get("error").toString();
changeRequested = false;
tempBasalReqested = false;
rate = -1;
duration = -1;
} else {
@ -37,36 +30,37 @@ public class DetermineBasalResultAMA extends APSResult {
if (result.containsKey("eventualBG")) eventualBG = (Double) result.get("eventualBG");
if (result.containsKey("snoozeBG")) snoozeBG = (Double) result.get("snoozeBG");
if (result.containsKey("rate")) {
rate = (Double) result.get("rate");
rate = (Double) result.get("rate");
if (rate < 0d) rate = 0d;
changeRequested = true;
tempBasalReqested = true;
} else {
rate = -1;
changeRequested = false;
tempBasalReqested = false;
}
if (result.containsKey("duration")) {
duration = ((Double)result.get("duration")).intValue();
duration = ((Double) result.get("duration")).intValue();
//changeRequested as above
} else {
duration = -1;
changeRequested = false;
tempBasalReqested = false;
}
}
bolusRequested = false;
}
public DetermineBasalResultAMA() {
hasPredictions = true;
}
@Override
public DetermineBasalResultAMA clone() {
DetermineBasalResultAMA newResult = new DetermineBasalResultAMA();
newResult.reason = new String(reason);
newResult.reason = reason;
newResult.rate = rate;
newResult.duration = duration;
newResult.changeRequested = changeRequested;
newResult.tempBasalReqested = tempBasalReqested;
newResult.rate = rate;
newResult.duration = duration;
newResult.changeRequested = changeRequested;
try {
newResult.json = new JSONObject(json.toString());
@ -90,72 +84,4 @@ public class DetermineBasalResultAMA extends APSResult {
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;
}
}

View file

@ -9,8 +9,6 @@ import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import com.crashlytics.android.Crashlytics;
import com.crashlytics.android.answers.Answers;
import com.crashlytics.android.answers.CustomEvent;
import com.squareup.otto.Subscribe;
@ -24,6 +22,7 @@ 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.FabricPrivacy;
import info.nightscout.utils.JSONFormatter;
public class OpenAPSAMAFragment extends SubscriberFragment implements View.OnClickListener {
@ -63,7 +62,7 @@ public class OpenAPSAMAFragment extends SubscriberFragment implements View.OnCli
updateGUI();
return view;
} catch (Exception e) {
Crashlytics.logException(e);
FabricPrivacy.logException(e);
}
return null;
@ -74,7 +73,7 @@ public class OpenAPSAMAFragment extends SubscriberFragment implements View.OnCli
switch (view.getId()) {
case R.id.openapsma_run:
OpenAPSAMAPlugin.getPlugin().invoke("OpenAPSAMA button");
Answers.getInstance().logCustom(new CustomEvent("OpenAPS_AMA_Run"));
FabricPrivacy.getInstance().logCustom(new CustomEvent("OpenAPS_AMA_Run"));
break;
}

View file

@ -8,7 +8,6 @@ import java.io.IOException;
import java.util.Date;
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;
@ -18,6 +17,7 @@ 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;
@ -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.EventOpenAPSUpdateResultGui;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.NSUpload;
import info.nightscout.utils.HardLimits;
import info.nightscout.utils.Profiler;
import info.nightscout.utils.Round;
import info.nightscout.utils.SP;
import info.nightscout.utils.SafeParse;
import info.nightscout.utils.ToastUtils;
/**
* Created by mike on 05.08.2016.
@ -149,6 +147,7 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface {
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)));
@ -177,14 +176,14 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface {
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;
double targetBg = Profile.toMgdl(profile.getTarget(), units);
minBg = Round.roundTo(minBg, 0.1d);
maxBg = Round.roundTo(maxBg, 0.1d);
Date start = new Date();
Date startPart = new Date();
IobTotal[] iobArray = IobCobCalculatorPlugin.calculateIobArrayInDia();
IobTotal[] iobArray = IobCobCalculatorPlugin.getPlugin().calculateIobArrayInDia();
Profiler.log(log, "calculateIobArrayInDia()", startPart);
startPart = new Date();
@ -193,35 +192,37 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface {
maxIob = MainApp.getConfigBuilder().applyMaxIOBConstraints(maxIob);
minBg = verifyHardLimits(minBg, "minBg", Constants.VERY_HARD_LIMIT_MIN_BG[0], Constants.VERY_HARD_LIMIT_MIN_BG[1]);
maxBg = verifyHardLimits(maxBg, "maxBg", Constants.VERY_HARD_LIMIT_MAX_BG[0], Constants.VERY_HARD_LIMIT_MAX_BG[1]);
targetBg = verifyHardLimits(targetBg, "targetBg", Constants.VERY_HARD_LIMIT_TARGET_BG[0], Constants.VERY_HARD_LIMIT_TARGET_BG[1]);
minBg = HardLimits.verifyHardLimits(minBg, "minBg", HardLimits.VERY_HARD_LIMIT_MIN_BG[0], HardLimits.VERY_HARD_LIMIT_MIN_BG[1]);
maxBg = HardLimits.verifyHardLimits(maxBg, "maxBg", HardLimits.VERY_HARD_LIMIT_MAX_BG[0], HardLimits.VERY_HARD_LIMIT_MAX_BG[1]);
targetBg = HardLimits.verifyHardLimits(targetBg, "targetBg", HardLimits.VERY_HARD_LIMIT_TARGET_BG[0], HardLimits.VERY_HARD_LIMIT_TARGET_BG[1]);
boolean isTempTarget = false;
TempTarget tempTarget = MainApp.getConfigBuilder().getTempTargetFromHistory(System.currentTimeMillis());
if (tempTarget != null) {
isTempTarget = true;
minBg = verifyHardLimits(tempTarget.low, "minBg", Constants.VERY_HARD_LIMIT_TEMP_MIN_BG[0], Constants.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]);
targetBg = verifyHardLimits((tempTarget.low + tempTarget.high) / 2, "targetBg", Constants.VERY_HARD_LIMIT_TEMP_TARGET_BG[0], Constants.VERY_HARD_LIMIT_TEMP_TARGET_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 = HardLimits.verifyHardLimits(tempTarget.high, "maxBg", HardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[0], HardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[1]);
targetBg = HardLimits.verifyHardLimits(tempTarget.target(), "targetBg", HardLimits.VERY_HARD_LIMIT_TEMP_TARGET_BG[0], HardLimits.VERY_HARD_LIMIT_TEMP_TARGET_BG[1]);
}
maxIob = verifyHardLimits(maxIob, "maxIob", 0, 7);
maxBasal = verifyHardLimits(maxBasal, "max_basal", 0.1, 10);
maxIob = HardLimits.verifyHardLimits(maxIob, "maxIob", 0, HardLimits.maxIobAMA());
maxBasal = HardLimits.verifyHardLimits(maxBasal, "max_basal", 0.1, HardLimits.maxBasal());
if (!checkOnlyHardLimits(profile.getDia(), "dia", 2, 7)) return;
if (!checkOnlyHardLimits(profile.getIc(Profile.secondsFromMidnight()), "carbratio", 2, 100))
if (!HardLimits.checkOnlyHardLimits(profile.getDia(), "dia", HardLimits.MINDIA, HardLimits.MAXDIA))
return;
if (!checkOnlyHardLimits(Profile.toMgdl(profile.getIsf(), units), "sens", 2, 900))
if (!HardLimits.checkOnlyHardLimits(profile.getIc(profile.secondsFromMidnight()), "carbratio", HardLimits.MINIC, HardLimits.MAXIC))
return;
if (!checkOnlyHardLimits(profile.getMaxDailyBasal(), "max_daily_basal", 0.1, 10)) return;
if (!checkOnlyHardLimits(ConfigBuilderPlugin.getActivePump().getBaseBasalRate(), "current_basal", 0.01, 5))
if (!HardLimits.checkOnlyHardLimits(Profile.toMgdl(profile.getIsf().doubleValue(), units), "sens", HardLimits.MINISF, HardLimits.MAXISF))
return;
if (!HardLimits.checkOnlyHardLimits(profile.getMaxDailyBasal(), "max_daily_basal", 0.05, HardLimits.maxBasal()))
return;
if (!HardLimits.checkOnlyHardLimits(pump.getBaseBasalRate(), "current_basal", 0.01, HardLimits.maxBasal()))
return;
startPart = new Date();
if (MainApp.getConfigBuilder().isAMAModeEnabled()) {
lastAutosensResult = IobCobCalculatorPlugin.detectSensitivityWithLock(IobCobCalculatorPlugin.oldestDataAvailable(), System.currentTimeMillis());
lastAutosensResult = IobCobCalculatorPlugin.getPlugin().detectSensitivityWithLock(IobCobCalculatorPlugin.oldestDataAvailable(), System.currentTimeMillis());
} else {
lastAutosensResult = new AutosensResult();
}
@ -233,8 +234,7 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface {
try {
determineBasalAdapterAMAJS.setData(profile, maxIob, maxBasal, minBg, maxBg, targetBg, ConfigBuilderPlugin.getActivePump().getBaseBasalRate(), iobArray, glucoseStatus, mealData,
lastAutosensResult.ratio, //autosensDataRatio
isTempTarget,
SafeParse.stringToDouble(SP.getString("openapsama_min_5m_carbimpact", "3.0"))//min_5m_carbimpact
isTempTarget
);
} catch (JSONException e) {
log.error("Unable to set data: " + e.toString());
@ -245,15 +245,15 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface {
Profiler.log(log, "AMA calculation", start);
// Fix bug determine basal
if (determineBasalResultAMA.rate == 0d && determineBasalResultAMA.duration == 0 && !MainApp.getConfigBuilder().isTempBasalInProgress())
determineBasalResultAMA.changeRequested = false;
determineBasalResultAMA.tempBasalReqested = false;
// limit requests on openloop mode
if (!MainApp.getConfigBuilder().isClosedModeEnabled()) {
if (MainApp.getConfigBuilder().isTempBasalInProgress() && determineBasalResultAMA.rate == 0 && determineBasalResultAMA.duration == 0) {
// going to cancel
} 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)
determineBasalResultAMA.changeRequested = false;
determineBasalResultAMA.tempBasalReqested = false;
}
determineBasalResultAMA.iob = iobArray[0];
@ -274,24 +274,4 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface {
//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;
}
}

View file

@ -6,7 +6,6 @@ import org.mozilla.javascript.NativeObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.plugins.Loop.APSResult;
public class DetermineBasalResultMA extends APSResult {
@ -16,13 +15,12 @@ public class DetermineBasalResultMA extends APSResult {
public double eventualBG;
public double snoozeBG;
public String mealAssist;
public IobTotal iob;
public DetermineBasalResultMA(NativeObject result, JSONObject j) {
json = j;
if (result.containsKey("error")) {
reason = (String) result.get("error");
changeRequested = false;
tempBasalReqested = false;
rate = -1;
duration = -1;
mealAssist = "";
@ -33,17 +31,17 @@ public class DetermineBasalResultMA extends APSResult {
if (result.containsKey("rate")) {
rate = (Double) result.get("rate");
if (rate < 0d) rate = 0d;
changeRequested = true;
tempBasalReqested = true;
} else {
rate = -1;
changeRequested = false;
tempBasalReqested = false;
}
if (result.containsKey("duration")) {
duration = ((Double) result.get("duration")).intValue();
//changeRequested as above
} else {
duration = -1;
changeRequested = false;
tempBasalReqested = false;
}
if (result.containsKey("mealAssist")) {
mealAssist = result.get("mealAssist").toString();
@ -60,10 +58,10 @@ public class DetermineBasalResultMA extends APSResult {
newResult.reason = new String(reason);
newResult.rate = rate;
newResult.duration = duration;
newResult.changeRequested = changeRequested;
newResult.tempBasalReqested = isChangeRequested();
newResult.rate = rate;
newResult.duration = duration;
newResult.changeRequested = changeRequested;
newResult.tempBasalReqested = isChangeRequested();
try {
newResult.json = new JSONObject(json.toString());
@ -72,7 +70,7 @@ public class DetermineBasalResultMA extends APSResult {
}
newResult.eventualBG = eventualBG;
newResult.snoozeBG = snoozeBG;
newResult.mealAssist = new String(mealAssist);
newResult.mealAssist = mealAssist;
return newResult;
}

View file

@ -9,8 +9,6 @@ import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import com.crashlytics.android.Crashlytics;
import com.crashlytics.android.answers.Answers;
import com.crashlytics.android.answers.CustomEvent;
import com.squareup.otto.Subscribe;
@ -22,6 +20,7 @@ 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.FabricPrivacy;
import info.nightscout.utils.JSONFormatter;
public class OpenAPSMAFragment extends SubscriberFragment implements View.OnClickListener {
@ -57,7 +56,7 @@ public class OpenAPSMAFragment extends SubscriberFragment implements View.OnClic
updateGUI();
return view;
} catch (Exception e) {
Crashlytics.logException(e);
FabricPrivacy.logException(e);
}
return null;
@ -68,7 +67,7 @@ public class OpenAPSMAFragment extends SubscriberFragment implements View.OnClic
switch (view.getId()) {
case R.id.openapsma_run:
OpenAPSMAPlugin.getPlugin().invoke("OpenAPSMA button");
Answers.getInstance().logCustom(new CustomEvent("OpenAPS_MA_Run"));
FabricPrivacy.getInstance().logCustom(new CustomEvent("OpenAPS_MA_Run"));
break;
}

View file

@ -8,7 +8,6 @@ import java.io.IOException;
import java.util.Date;
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;
@ -18,19 +17,21 @@ 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.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.Profiler;
import info.nightscout.utils.Round;
import info.nightscout.utils.SP;
import info.nightscout.utils.SafeParse;
import static info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin.checkOnlyHardLimits;
import static info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin.verifyHardLimits;
import static info.nightscout.utils.HardLimits.checkOnlyHardLimits;
import static info.nightscout.utils.HardLimits.verifyHardLimits;
/**
* Created by mike on 05.08.2016.
@ -147,6 +148,7 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface {
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)));
@ -177,7 +179,7 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface {
double maxBasal = SafeParse.stringToDouble(SP.getString("openapsma_max_basal", "1"));
double minBg = Profile.toMgdl(profile.getTargetLow(), units);
double maxBg = Profile.toMgdl(profile.getTargetHigh(), units);
double targetBg = (minBg + maxBg) / 2;
double targetBg = Profile.toMgdl(profile.getTarget(), units);
minBg = Round.roundTo(minBg, 0.1d);
maxBg = Round.roundTo(maxBg, 0.1d);
@ -195,26 +197,29 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface {
maxIob = MainApp.getConfigBuilder().applyMaxIOBConstraints(maxIob);
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]);
maxBg = verifyHardLimits(maxBg, "maxBg", Constants.VERY_HARD_LIMIT_MAX_BG[0], Constants.VERY_HARD_LIMIT_MAX_BG[1]);
targetBg = verifyHardLimits(targetBg, "targetBg", Constants.VERY_HARD_LIMIT_TARGET_BG[0], Constants.VERY_HARD_LIMIT_TARGET_BG[1]);
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]);
TempTarget tempTarget = MainApp.getConfigBuilder().getTempTargetFromHistory(System.currentTimeMillis());
if (tempTarget != null) {
minBg = verifyHardLimits(tempTarget.low, "minBg", Constants.VERY_HARD_LIMIT_TEMP_MIN_BG[0], Constants.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]);
targetBg = verifyHardLimits((tempTarget.low + tempTarget.high) / 2, "targetBg", Constants.VERY_HARD_LIMIT_TEMP_TARGET_BG[0], Constants.VERY_HARD_LIMIT_TEMP_TARGET_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", HardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[0], HardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[1]);
targetBg = verifyHardLimits(tempTarget.target(), "targetBg", HardLimits.VERY_HARD_LIMIT_TEMP_TARGET_BG[0], HardLimits.VERY_HARD_LIMIT_TEMP_TARGET_BG[1]);
}
maxIob = verifyHardLimits(maxIob, "maxIob", 0, 7);
maxBasal = verifyHardLimits(maxBasal, "max_basal", 0.1, 10);
maxIob = verifyHardLimits(maxIob, "maxIob", 0, HardLimits.maxIobAMA());
maxBasal = verifyHardLimits(maxBasal, "max_basal", 0.1, HardLimits.maxBasal());
if (!checkOnlyHardLimits(profile.getDia(), "dia", 2, 7)) return;
if (!checkOnlyHardLimits(profile.getIc(), "carbratio", 2, 100)) return;
if (!checkOnlyHardLimits(Profile.toMgdl(profile.getIsf(), units), "sens", 2, 900))
if (!checkOnlyHardLimits(profile.getDia(), "dia", HardLimits.MINDIA, HardLimits.MAXDIA))
return;
if (!checkOnlyHardLimits(profile.getMaxDailyBasal(), "max_daily_basal", 0.1, 10)) return;
if (!checkOnlyHardLimits(ConfigBuilderPlugin.getActivePump().getBaseBasalRate(), "current_basal", 0.01, 5))
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.05, HardLimits.maxBasal()))
return;
if (!checkOnlyHardLimits(pump.getBaseBasalRate(), "current_basal", 0.01, HardLimits.maxBasal()))
return;
start = new Date();
@ -229,15 +234,15 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface {
DetermineBasalResultMA determineBasalResultMA = determineBasalAdapterMAJS.invoke();
// Fix bug determinef basal
if (determineBasalResultMA.rate == 0d && determineBasalResultMA.duration == 0 && !MainApp.getConfigBuilder().isTempBasalInProgress())
determineBasalResultMA.changeRequested = false;
determineBasalResultMA.tempBasalReqested = false;
// limit requests on openloop mode
if (!MainApp.getConfigBuilder().isClosedModeEnabled()) {
if (MainApp.getConfigBuilder().isTempBasalInProgress() && determineBasalResultMA.rate == 0 && determineBasalResultMA.duration == 0) {
// going to cancel
} 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)
determineBasalResultMA.changeRequested = false;
determineBasalResultMA.tempBasalReqested = false;
}
determineBasalResultMA.iob = iobTotal;

View file

@ -0,0 +1,345 @@
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.getDouble("openapsama_current_basal_safety_multiplier", 4d));
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);
//TODO: align with max-absorption model in AMA sensitivity
mProfile.put("min_5m_carbimpact", SP.getDouble("openapsama_min_5m_carbimpact", SMBDefaults.min_5m_carbimpact));;
mProfile.put("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;
}
}

View file

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

View file

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

View file

@ -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 = Profile.toMgdl(profile.getTarget(), units);
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.target(), "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.05, 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;
}
}

View file

@ -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 double min_5m_carbimpact = 8d; // 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
}

View file

@ -11,7 +11,6 @@ import android.view.Window;
import android.view.WindowManager;
import android.widget.TextView;
import com.crashlytics.android.answers.Answers;
import com.crashlytics.android.answers.CustomEvent;
import org.slf4j.Logger;
@ -24,6 +23,7 @@ import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.GlucoseStatus;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.utils.FabricPrivacy;
import info.nightscout.utils.NumberPicker;
import info.nightscout.utils.SafeParse;
import info.nightscout.utils.XdripCalibrations;
@ -88,7 +88,7 @@ public class CalibrationDialog extends DialogFragment implements View.OnClickLis
final Double bg = SafeParse.stringToDouble(bgNumber.getText());
XdripCalibrations.confirmAndSendCalibration(bg, context);
dismiss();
Answers.getInstance().logCustom(new CustomEvent("Calibration"));
FabricPrivacy.getInstance().logCustom(new CustomEvent("Calibration"));
break;
case R.id.cancel:
dismiss();

View file

@ -0,0 +1,380 @@
package info.nightscout.androidaps.plugins.Overview.Dialogs;
import android.content.Context;
import android.os.Bundle;
import android.os.HandlerThread;
import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog;
import android.text.Editable;
import android.text.Html;
import android.text.TextWatcher;
import android.text.format.DateFormat;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.TextView;
import com.wdullaer.materialdatetimepicker.date.DatePickerDialog;
import com.wdullaer.materialdatetimepicker.time.RadialPickerLayout;
import com.wdullaer.materialdatetimepicker.time.TimePickerDialog;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.text.DecimalFormat;
import java.util.Calendar;
import java.util.Date;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.db.Source;
import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Loop.LoopPlugin;
import info.nightscout.androidaps.queue.Callback;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.NumberPicker;
import info.nightscout.utils.SP;
import info.nightscout.utils.SafeParse;
import info.nightscout.utils.ToastUtils;
public class NewCarbsDialog extends DialogFragment implements OnClickListener, DatePickerDialog.OnDateSetListener, TimePickerDialog.OnTimeSetListener {
private static Logger log = LoggerFactory.getLogger(NewCarbsDialog.class);
private EditText foodText;
private NumberPicker editCarbs;
private TextView dateButton;
private TextView timeButton;
private Date initialEventTime;
private Date eventTime;
private Button fav1Button;
private Button fav2Button;
private Button fav3Button;
private static final double FAV1_DEFAULT = 5;
private static final double FAV2_DEFAULT = 10;
private static final double FAV3_DEFAULT = 20;
private CheckBox suspendLoopCheckbox;
private CheckBox startActivityTTCheckbox;
private CheckBox startEatingSoonTTCheckbox;
private Integer maxCarbs;
//one shot guards
private boolean accepted;
private boolean okClicked;
public NewCarbsDialog() {
HandlerThread mHandlerThread = new HandlerThread(NewCarbsDialog.class.getSimpleName());
mHandlerThread.start();
}
final private TextWatcher textWatcher = new TextWatcher() {
@Override
public void afterTextChanged(Editable s) {
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
validateInputs();
}
};
private void validateInputs() {
Integer carbs = SafeParse.stringToInt(editCarbs.getText());
if (carbs > maxCarbs) {
editCarbs.setValue(0d);
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.carbsconstraintapplied));
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.overview_newcarbs_dialog, container, false);
view.findViewById(R.id.ok).setOnClickListener(this);
view.findViewById(R.id.cancel).setOnClickListener(this);
getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
maxCarbs = MainApp.getConfigBuilder().applyCarbsConstraints(Constants.carbsOnlyForCheckLimit);
foodText = view.findViewById(R.id.newcarb_food);
editCarbs = view.findViewById(R.id.newcarb_carbsamount);
editCarbs.setParams(0d, 0d, (double) maxCarbs, 1d, new DecimalFormat("0"), false, textWatcher);
startActivityTTCheckbox = view.findViewById(R.id.newcarbs_activity_tt);
startEatingSoonTTCheckbox = view.findViewById(R.id.carbs_eating_soon_tt);
dateButton = view.findViewById(R.id.newcarbs_eventdate);
timeButton = view.findViewById(R.id.newcarb_eventtime);
initialEventTime = new Date();
eventTime = new Date(initialEventTime.getTime());
dateButton.setText(DateUtil.dateString(eventTime));
timeButton.setText(DateUtil.timeString(eventTime));
dateButton.setOnClickListener(this);
timeButton.setOnClickListener(this);
//To be able to select only one TT at a time
startEatingSoonTTCheckbox.setOnClickListener(this);
startActivityTTCheckbox.setOnClickListener(this);
// TODO prefilling carbs, maybe
// TODO maybe update suggested carbs to target TT when checked
// APSResult lastAPSResult = ConfigBuilderPlugin.getActiveAPS().getLastAPSResult();
// if (lastAPSResult != null && lastAPSResult instanceof DetermineBasalResultSMB && ((DetermineBasalResultSMB) lastAPSResult).carbsReq > 0) {
// editCarbs.setValue(((DetermineBasalResultSMB) lastAPSResult).carbsReq);
// }
fav1Button = view.findViewById(R.id.newcarbs_plus1);
fav1Button.setOnClickListener(this);
fav1Button.setText("+" + SP.getString(R.string.key_carbs_button_increment_1, String.valueOf(FAV1_DEFAULT)));
fav2Button = view.findViewById(R.id.newcarbs_plus2);
fav2Button.setOnClickListener(this);
fav2Button.setText("+" + SP.getString(R.string.key_carbs_button_increment_2, String.valueOf(FAV2_DEFAULT)));
fav3Button = view.findViewById(R.id.newcarbs_plus3);
fav3Button.setOnClickListener(this);
fav3Button.setText("+" + SP.getString(R.string.key_carbs_button_increment_3, String.valueOf(FAV3_DEFAULT)));
suspendLoopCheckbox = view.findViewById(R.id.newcarbs_suspend_loop);
setCancelable(true);
getDialog().setCanceledOnTouchOutside(false);
return view;
}
@Override
public synchronized void onClick(View view) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(eventTime);
switch (view.getId()) {
case R.id.ok:
submit();
break;
case R.id.cancel:
dismiss();
break;
case R.id.newcarbs_eventdate:
DatePickerDialog dpd = DatePickerDialog.newInstance(
this,
calendar.get(Calendar.YEAR),
calendar.get(Calendar.MONTH),
calendar.get(Calendar.DAY_OF_MONTH)
);
dpd.setThemeDark(true);
dpd.dismissOnPause(true);
dpd.show(getActivity().getFragmentManager(), "Datepickerdialog");
break;
case R.id.newcarb_eventtime:
TimePickerDialog tpd = TimePickerDialog.newInstance(
this,
calendar.get(Calendar.HOUR_OF_DAY),
calendar.get(Calendar.MINUTE),
DateFormat.is24HourFormat(getActivity())
);
tpd.setThemeDark(true);
tpd.dismissOnPause(true);
tpd.show(getActivity().getFragmentManager(), "Timepickerdialog");
break;
case R.id.newcarbs_plus1:
editCarbs.setValue(editCarbs.getValue()
+ SP.getDouble(R.string.key_carbs_button_increment_1, FAV1_DEFAULT));
validateInputs();
break;
case R.id.newcarbs_plus2:
editCarbs.setValue(editCarbs.getValue()
+ SP.getDouble(R.string.key_carbs_button_increment_2, FAV2_DEFAULT));
validateInputs();
break;
case R.id.newcarbs_plus3:
editCarbs.setValue(editCarbs.getValue()
+ SP.getDouble(R.string.key_carbs_button_increment_3, FAV3_DEFAULT));
validateInputs();
break;
case R.id.newcarbs_activity_tt:
startEatingSoonTTCheckbox.setChecked(false);
break;
case R.id.carbs_eating_soon_tt:
startActivityTTCheckbox.setChecked(false);
break;
}
}
private void submit() {
if (okClicked) {
log.debug("guarding: ok already clicked");
dismiss();
return;
}
okClicked = true;
try {
final String food = StringUtils.trimToNull(foodText.getText().toString());
final Integer carbs = SafeParse.stringToInt(editCarbs.getText());
Integer carbsAfterConstraints = MainApp.getConfigBuilder().applyCarbsConstraints(carbs);
String confirmMessage = "";
if (carbs > 0)
confirmMessage += MainApp.gs(R.string.carbs) + ": " + "<font color='" + MainApp.gc(R.color.colorCarbsButton) + "'>" + carbsAfterConstraints + "g" + "</font>";
if (!carbsAfterConstraints.equals(carbs))
confirmMessage += "<br/><font color='" + MainApp.gc(R.color.low) + "'>" + MainApp.gs(R.string.carbsconstraintapplied) + "</font>";
if (suspendLoopCheckbox.isChecked()) {
confirmMessage += "<br/>" + MainApp.gs(R.string.loop) + ": " + "<font color='" + MainApp.gc(R.color.low) + "'>" + MainApp.gs(R.string.suspendloopfor30min) + "</font>";
}
final Profile currentProfile = MainApp.getConfigBuilder().getProfile();
if (currentProfile == null)
return;
int activityTTDuration = SP.getInt(R.string.key_activity_duration, Constants.defaultActivityTTDuration);
activityTTDuration = activityTTDuration > 0 ? activityTTDuration : Constants.defaultActivityTTDuration;
double activityTT = SP.getDouble(R.string.key_activity_target, currentProfile.getUnits().equals(Constants.MMOL) ? Constants.defaultActivityTTmmol : Constants.defaultActivityTTmgdl);
activityTT = activityTT > 0 ? activityTT : currentProfile.getUnits().equals(Constants.MMOL) ? Constants.defaultActivityTTmmol : Constants.defaultActivityTTmgdl;
int eatingSoonTTDuration = SP.getInt(R.string.key_eatingsoon_duration, Constants.defaultEatingSoonTTDuration);
eatingSoonTTDuration = eatingSoonTTDuration > 0 ? eatingSoonTTDuration : Constants.defaultEatingSoonTTDuration;
double eatingSoonTT = SP.getDouble(R.string.key_eatingsoon_target, currentProfile.getUnits().equals(Constants.MMOL) ? Constants.defaultEatingSoonTTmmol : Constants.defaultEatingSoonTTmgdl);
eatingSoonTT = eatingSoonTT > 0 ? eatingSoonTT : currentProfile.getUnits().equals(Constants.MMOL) ? Constants.defaultEatingSoonTTmmol : Constants.defaultEatingSoonTTmgdl;
if (startActivityTTCheckbox.isChecked()) {
if (currentProfile.getUnits().equals(Constants.MMOL)) {
confirmMessage += "<br/>" + MainApp.gs(R.string.temptargetshort) + ": " + "<font color='" + MainApp.gc(R.color.high) + "'>" + DecimalFormatter.to1Decimal(activityTT) + " mmol/l (" + ((int) activityTTDuration) + " min)</font>";
} else
confirmMessage += "<br/>" + MainApp.gs(R.string.temptargetshort) + ": " + "<font color='" + MainApp.gc(R.color.high) + "'>" + DecimalFormatter.to0Decimal(activityTT) + " mg/dl (" + ((int) activityTTDuration) + " min)</font>";
}
if (startEatingSoonTTCheckbox.isChecked() && !startActivityTTCheckbox.isChecked()) {
if (currentProfile.getUnits().equals(Constants.MMOL)) {
confirmMessage += "<br/>" + MainApp.gs(R.string.temptargetshort) + ": " + "<font color='" + MainApp.gc(R.color.high) + "'>" + DecimalFormatter.to1Decimal(eatingSoonTT) + " mmol/l (" + eatingSoonTTDuration + " min)</font>";
} else
confirmMessage += "<br/>" + MainApp.gs(R.string.temptargetshort) + ": " + "<font color='" + MainApp.gc(R.color.high) + "'>" + DecimalFormatter.to0Decimal(eatingSoonTT) + " mg/dl (" + eatingSoonTTDuration + " min)</font>";
}
final double finalActivityTT = activityTT;
final double finalEatigSoonTT = eatingSoonTT;
final int finalActivityTTDuration = activityTTDuration;
final int finalEatingSoonTTDuration = eatingSoonTTDuration;
if (StringUtils.isNoneEmpty(food)) {
confirmMessage += "<br/>" + "Food: " + food;
}
if (!initialEventTime.equals(eventTime)) {
confirmMessage += "<br/> Time: " + DateUtil.dateAndTimeString(eventTime);
}
if (confirmMessage.length() > 0) {
final int finalCarbsAfterConstraints = carbsAfterConstraints;
final Context context = getContext();
final AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(MainApp.gs(R.string.confirmation));
if (confirmMessage.startsWith("<br/>"))
confirmMessage = confirmMessage.substring("<br/>".length());
builder.setMessage(Html.fromHtml(confirmMessage));
builder.setPositiveButton(MainApp.gs(R.string.ok), (dialog, id) -> {
synchronized (builder) {
if (accepted) {
log.debug("guarding: already accepted");
return;
}
accepted = true;
if (suspendLoopCheckbox.isChecked()) {
final LoopPlugin activeloop = ConfigBuilderPlugin.getActiveLoop();
activeloop.suspendTo(System.currentTimeMillis() + 30L * 60 * 1000);
ConfigBuilderPlugin.getCommandQueue().cancelTempBasal(true, new Callback() {
@Override
public void run() {
if (!result.success) {
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.tempbasaldeliveryerror));
}
}
});
}
if (startActivityTTCheckbox.isChecked()) {
TempTarget tempTarget = new TempTarget();
tempTarget.date = System.currentTimeMillis();
tempTarget.durationInMinutes = finalActivityTTDuration;
tempTarget.reason = MainApp.gs(R.string.activity);
tempTarget.source = Source.USER;
tempTarget.low = Profile.toMgdl(finalActivityTT, currentProfile.getUnits());
tempTarget.high = Profile.toMgdl(finalActivityTT, currentProfile.getUnits());
MainApp.getDbHelper().createOrUpdate(tempTarget);
} else if (startEatingSoonTTCheckbox.isChecked()) {
TempTarget tempTarget = new TempTarget();
tempTarget.date = System.currentTimeMillis();
tempTarget.durationInMinutes = finalEatingSoonTTDuration;
tempTarget.reason = MainApp.gs(R.string.eatingsoon);
tempTarget.source = Source.USER;
tempTarget.low = Profile.toMgdl(finalEatigSoonTT, currentProfile.getUnits());
tempTarget.high = Profile.toMgdl(finalEatigSoonTT, currentProfile.getUnits());
MainApp.getDbHelper().createOrUpdate(tempTarget);
}
if (finalCarbsAfterConstraints > 0 || food != null) {
DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo();
detailedBolusInfo.date = eventTime.getTime();
detailedBolusInfo.eventType = CareportalEvent.CARBCORRECTION;
detailedBolusInfo.carbs = finalCarbsAfterConstraints;
// detailedBolusInfo.food = food;
detailedBolusInfo.context = context;
detailedBolusInfo.source = Source.USER;
MainApp.getConfigBuilder().addToHistoryTreatment(detailedBolusInfo);
}
}
});
builder.setNegativeButton(MainApp.gs(R.string.cancel), null);
builder.show();
dismiss();
} else
dismiss();
} catch (Exception e) {
log.error("Unhandled exception", e);
}
}
@Override
public void onDateSet(DatePickerDialog view, int year, int monthOfYear, int dayOfMonth) {
eventTime.setYear(year - 1900);
eventTime.setMonth(monthOfYear);
eventTime.setDate(dayOfMonth);
dateButton.setText(DateUtil.dateString(eventTime));
}
@Override
public void onTimeSet(RadialPickerLayout view, int hourOfDay, int minute, int second) {
eventTime.setHours(hourOfDay);
eventTime.setMinutes(minute);
eventTime.setSeconds(second);
timeButton.setText(DateUtil.timeString(eventTime));
}
}

View file

@ -0,0 +1,353 @@
package info.nightscout.androidaps.plugins.Overview.Dialogs;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.HandlerThread;
import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog;
import android.text.Editable;
import android.text.Html;
import android.text.TextWatcher;
import android.text.format.DateFormat;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.TextView;
import com.crashlytics.android.answers.Answers;
import com.crashlytics.android.answers.CustomEvent;
import com.wdullaer.materialdatetimepicker.date.DatePickerDialog;
import com.wdullaer.materialdatetimepicker.time.RadialPickerLayout;
import com.wdullaer.materialdatetimepicker.time.TimePickerDialog;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.text.DecimalFormat;
import java.util.Calendar;
import java.util.Date;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.db.Source;
import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Loop.APSResult;
import info.nightscout.androidaps.plugins.OpenAPSSMB.DetermineBasalResultSMB;
import info.nightscout.androidaps.queue.Callback;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.NumberPicker;
import info.nightscout.utils.SP;
import info.nightscout.utils.SafeParse;
import info.nightscout.utils.ToastUtils;
public class NewInsulinDialog extends DialogFragment implements OnClickListener, DatePickerDialog.OnDateSetListener, TimePickerDialog.OnTimeSetListener {
private static Logger log = LoggerFactory.getLogger(NewInsulinDialog.class);
private NumberPicker editInsulin;
private TextView dateButton;
private TextView timeButton;
private Date initialEventTime;
private Date eventTime;
private Button plus1Button;
private Button plus2Button;
private Button plus3Button;
public static final double PLUS1_DEFAULT = 0.5d;
public static final double PLUS2_DEFAULT = 1d;
public static final double PLUS3_DEFAULT = 2d;
private CheckBox startESMCheckbox;
private CheckBox recordOnlyCheckbox;
private Double maxInsulin;
//one shot guards
private boolean accepted;
private boolean okClicked;
public NewInsulinDialog() {
HandlerThread mHandlerThread = new HandlerThread(NewInsulinDialog.class.getSimpleName());
mHandlerThread.start();
}
final private TextWatcher textWatcher = new TextWatcher() {
@Override
public void afterTextChanged(Editable s) {
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
validateInputs();
}
};
private void validateInputs() {
Double insulin = SafeParse.stringToDouble(editInsulin.getText());
if (insulin > maxInsulin) {
editInsulin.setValue(0d);
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.bolusconstraintapplied));
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.overview_newinsulin_dialog, container, false);
view.findViewById(R.id.ok).setOnClickListener(this);
view.findViewById(R.id.cancel).setOnClickListener(this);
getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
maxInsulin = MainApp.getConfigBuilder().applyBolusConstraints(Constants.bolusOnlyForCheckLimit);
editInsulin = (NumberPicker) view.findViewById(R.id.treatments_newinsulin_amount);
editInsulin.setParams(0d, 0d, maxInsulin, ConfigBuilderPlugin.getActivePump().getPumpDescription().bolusStep, new DecimalFormat("0.00"), false, textWatcher);
dateButton = (TextView) view.findViewById(R.id.newinsulin_eventdate);
timeButton = (TextView) view.findViewById(R.id.newinsulin_eventtime);
initialEventTime = new Date();
eventTime = new Date(initialEventTime.getTime());
dateButton.setText(DateUtil.dateString(eventTime));
timeButton.setText(DateUtil.timeString(eventTime));
dateButton.setOnClickListener(this);
timeButton.setOnClickListener(this);
/*
// This makes it to easy to just bolus insulinReq, which is almost always too much
APSResult lastAPSResult = ConfigBuilderPlugin.getActiveAPS().getLastAPSResult();
if (lastAPSResult != null && lastAPSResult instanceof DetermineBasalResultSMB && ((DetermineBasalResultSMB) lastAPSResult).insulinReq > 0) {
editInsulin.setValue(((DetermineBasalResultSMB )lastAPSResult).insulinReq);
}
*/
plus1Button = (Button) view.findViewById(R.id.newinsulin_plus05);
plus1Button.setOnClickListener(this);
plus1Button.setText("+" + SP.getString(MainApp.gs(R.string.key_insulin_button_increment_1), String.valueOf(PLUS1_DEFAULT)));
plus2Button = (Button) view.findViewById(R.id.newinsulin_plus10);
plus2Button.setOnClickListener(this);
plus2Button.setText("+" + SP.getString(MainApp.gs(R.string.key_insulin_button_increment_2), String.valueOf(PLUS2_DEFAULT)));
plus3Button = (Button) view.findViewById(R.id.newinsulin_plus20);
plus3Button.setOnClickListener(this);
plus3Button.setText("+" + SP.getString(MainApp.gs(R.string.key_insulin_button_increment_3), String.valueOf(PLUS3_DEFAULT)));
startESMCheckbox = (CheckBox) view.findViewById(R.id.newinsulin_start_eating_soon_tt);
recordOnlyCheckbox = (CheckBox) view.findViewById(R.id.newinsulin_record_only);
recordOnlyCheckbox.setOnCheckedChangeListener((buttonView, isChecked) -> {
if (dateButton != null) dateButton.setEnabled(isChecked);
if (timeButton != null) timeButton.setEnabled(isChecked);
});
setCancelable(true);
getDialog().setCanceledOnTouchOutside(false);
return view;
}
@Override
public synchronized void onClick(View view) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(eventTime);
switch (view.getId()) {
case R.id.ok:
submit();
break;
case R.id.cancel:
dismiss();
break;
case R.id.newinsulin_eventdate:
DatePickerDialog dpd = DatePickerDialog.newInstance(
this,
calendar.get(Calendar.YEAR),
calendar.get(Calendar.MONTH),
calendar.get(Calendar.DAY_OF_MONTH)
);
dpd.setThemeDark(true);
dpd.dismissOnPause(true);
dpd.show(getActivity().getFragmentManager(), "Datepickerdialog");
break;
case R.id.newinsulin_eventtime:
TimePickerDialog tpd = TimePickerDialog.newInstance(
this,
calendar.get(Calendar.HOUR_OF_DAY),
calendar.get(Calendar.MINUTE),
DateFormat.is24HourFormat(getActivity())
);
tpd.setThemeDark(true);
tpd.dismissOnPause(true);
tpd.show(getActivity().getFragmentManager(), "Timepickerdialog");
break;
case R.id.newinsulin_start_eating_soon_tt:
final Profile profile = MainApp.getConfigBuilder().getProfile();
double tt = SP.getDouble(R.string.key_eatingsoon_target, 0d);
double ttBgAdd = (tt - profile.getTargetLow()) / profile.getIsf();
editInsulin.setValue(editInsulin.getValue() + (startESMCheckbox.isChecked() ? ttBgAdd : -ttBgAdd));
break;
case R.id.newinsulin_plus05:
editInsulin.setValue(editInsulin.getValue()
+ SP.getDouble(MainApp.gs(R.string.key_insulin_button_increment_1), PLUS1_DEFAULT));
validateInputs();
break;
case R.id.newinsulin_plus10:
editInsulin.setValue(editInsulin.getValue()
+ SP.getDouble(MainApp.gs(R.string.key_insulin_button_increment_2), PLUS2_DEFAULT));
validateInputs();
break;
case R.id.newinsulin_plus20:
editInsulin.setValue(editInsulin.getValue()
+ SP.getDouble(MainApp.gs(R.string.key_insulin_button_increment_3), PLUS3_DEFAULT));
validateInputs();
break;
}
}
private void submit() {
if (okClicked){
log.debug("guarding: ok already clicked");
dismiss();
return;
}
okClicked = true;
try {
Double insulin = SafeParse.stringToDouble(editInsulin.getText());
Double insulinAfterConstraints = MainApp.getConfigBuilder().applyBolusConstraints(insulin);
String confirmMessage = "";
if (insulin > 0) {
confirmMessage += MainApp.gs(R.string.bolus) + ": " + "<font color='" + MainApp.gc(R.color.colorCarbsButton) + "'>" + insulinAfterConstraints + "U" + "</font>";
if (recordOnlyCheckbox.isChecked()) {
confirmMessage += "<br/><font color='" + MainApp.gc(R.color.low) + "'>" + MainApp.gs(R.string.bolusrecordedonly) + "</font>";
}
}
if (!insulinAfterConstraints.equals(insulin))
confirmMessage += "<br/><font color='" + MainApp.sResources.getColor(R.color.low) + "'>" + MainApp.gs(R.string.bolusconstraintapplied) + "</font>";
double prefTTDuration = SP.getDouble(R.string.key_eatingsoon_duration, 45d);
double ttDuration = prefTTDuration > 0 ? prefTTDuration : 45d;
double prefTT = SP.getDouble(R.string.key_eatingsoon_target, 80d);
double tt = prefTT > 0 ? prefTT : 80d;
Profile currentProfile = MainApp.getConfigBuilder().getProfile();
if(currentProfile == null)
return;
if(currentProfile.getUnits().equals(Constants.MMOL))
tt = prefTT > 0 ? Profile.toMgdl(prefTT, Constants.MMOL) : 80d;
else
tt = prefTT > 0 ? prefTT : 80d;
final double finalTT = tt;
if (startESMCheckbox.isChecked()) {
if(currentProfile.getUnits().equals("mmol")){
confirmMessage += "<br/>" + "TT: " + "<font color='" + MainApp.sResources.getColor(R.color.high) + "'>" + Profile.toMmol(tt, Constants.MGDL) + " mmol for " + ((int) ttDuration) + " min </font>";
} else
confirmMessage += "<br/>" + "TT: " + "<font color='" + MainApp.sResources.getColor(R.color.high) + "'>" + ((int) tt) + "mg/dl for " + ((int) ttDuration) + " min </font>";
}
if (!initialEventTime.equals(eventTime)) {
confirmMessage += "<br/>Time: " + DateUtil.dateAndTimeString(eventTime);
}
final double finalInsulinAfterConstraints = insulinAfterConstraints;
final Context context = getContext();
final AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(MainApp.gs(R.string.confirmation));
if (confirmMessage.startsWith("<br/>"))
confirmMessage = confirmMessage.substring("<br/>".length());
builder.setMessage(Html.fromHtml(confirmMessage));
builder.setPositiveButton(MainApp.gs(R.string.ok), (dialog, id) -> {
synchronized (builder) {
if (accepted) {
log.debug("guarding: already accepted");
return;
}
accepted = true;
if (startESMCheckbox.isChecked()) {
TempTarget tempTarget = new TempTarget();
tempTarget.date = System.currentTimeMillis();
tempTarget.durationInMinutes = (int) ttDuration;
tempTarget.reason = "Eating soon";
tempTarget.source = Source.USER;
tempTarget.low = (int) finalTT;
tempTarget.high = (int) finalTT;
MainApp.getDbHelper().createOrUpdate(tempTarget);
}
if (finalInsulinAfterConstraints <= 0.01) {
return;
}
if (recordOnlyCheckbox.isChecked()) {
DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo();
detailedBolusInfo.source = Source.USER;
detailedBolusInfo.date = eventTime.getTime();
detailedBolusInfo.eventType = CareportalEvent.CORRECTIONBOLUS;
detailedBolusInfo.insulin = finalInsulinAfterConstraints;
MainApp.getConfigBuilder().addToHistoryTreatment(detailedBolusInfo);
} else {
DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo();
detailedBolusInfo.eventType = CareportalEvent.CORRECTIONBOLUS;
detailedBolusInfo.insulin = finalInsulinAfterConstraints;
detailedBolusInfo.context = context;
detailedBolusInfo.source = Source.USER;
ConfigBuilderPlugin.getCommandQueue().bolus(detailedBolusInfo, new Callback() {
@Override
public void run() {
if (!result.success) {
Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class);
i.putExtra("soundid", R.raw.boluserror);
i.putExtra("status", result.comment);
i.putExtra("title", MainApp.gs(R.string.treatmentdeliveryerror));
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
MainApp.instance().startActivity(i);
}
}
});
Answers.getInstance().logCustom(new CustomEvent("Bolus"));
}
}
});
builder.setNegativeButton(MainApp.gs(R.string.cancel), null);
builder.show();
dismiss();
} catch (Exception e) {
log.error("Unhandled exception", e);
}
}
@Override
public void onDateSet(DatePickerDialog view, int year, int monthOfYear, int dayOfMonth) {
eventTime.setYear(year - 1900);
eventTime.setMonth(monthOfYear);
eventTime.setDate(dayOfMonth);
dateButton.setText(DateUtil.dateString(eventTime));
}
@Override
public void onTimeSet(RadialPickerLayout view, int hourOfDay, int minute, int second) {
eventTime.setHours(hourOfDay);
eventTime.setMinutes(minute);
eventTime.setSeconds(second);
timeButton.setText(DateUtil.timeString(eventTime));
}
}

View file

@ -15,8 +15,8 @@ import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.CheckBox;
import com.crashlytics.android.answers.Answers;
import com.crashlytics.android.answers.CustomEvent;
import org.slf4j.Logger;
@ -33,6 +33,7 @@ import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.db.Source;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.queue.Callback;
import info.nightscout.utils.FabricPrivacy;
import info.nightscout.utils.NumberPicker;
import info.nightscout.utils.SafeParse;
import info.nightscout.utils.ToastUtils;
@ -50,6 +51,8 @@ public class NewTreatmentDialog extends DialogFragment implements OnClickListene
private boolean accepted;
private boolean okClicked;
private CheckBox recordOnlyCheckbox;
public NewTreatmentDialog() {
}
@ -72,12 +75,12 @@ public class NewTreatmentDialog extends DialogFragment implements OnClickListene
Integer carbs = SafeParse.stringToInt(editCarbs.getText());
if (carbs > maxCarbs) {
editCarbs.setValue(0d);
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), getString(R.string.carbsconstraintapplied));
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.carbsconstraintapplied));
}
Double insulin = SafeParse.stringToDouble(editInsulin.getText());
if (insulin > maxInsulin) {
editInsulin.setValue(0d);
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), getString(R.string.bolusconstraintapplied));
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.bolusconstraintapplied));
}
}
@ -101,6 +104,8 @@ public class NewTreatmentDialog extends DialogFragment implements OnClickListene
editCarbs.setParams(0d, 0d, (double) maxCarbs, 1d, new DecimalFormat("0"), false, textWatcher);
editInsulin.setParams(0d, 0d, maxInsulin, ConfigBuilderPlugin.getActivePump().getPumpDescription().bolusStep, new DecimalFormat("0.00"), false, textWatcher);
recordOnlyCheckbox = (CheckBox) view.findViewById(R.id.newtreatment_record_only);
setCancelable(true);
getDialog().setCanceledOnTouchOutside(false);
return view;
@ -121,15 +126,21 @@ public class NewTreatmentDialog extends DialogFragment implements OnClickListene
Double insulin = SafeParse.stringToDouble(editInsulin.getText());
final Integer carbs = SafeParse.stringToInt(editCarbs.getText());
String confirmMessage = getString(R.string.entertreatmentquestion) + "<br/>";
String confirmMessage = MainApp.gs(R.string.entertreatmentquestion) + "<br/>";
Double insulinAfterConstraints = MainApp.getConfigBuilder().applyBolusConstraints(insulin);
Integer carbsAfterConstraints = MainApp.getConfigBuilder().applyCarbsConstraints(carbs);
confirmMessage += getString(R.string.bolus) + ": " + "<font color='" + MainApp.sResources.getColor(R.color.bolus) + "'>" + insulinAfterConstraints + "U" + "</font>";
confirmMessage += "<br/>" + getString(R.string.carbs) + ": " + carbsAfterConstraints + "g";
if (insulin > 0) {
confirmMessage += MainApp.gs(R.string.bolus) + ": " + "<font color='" + MainApp.gc(R.color.colorCarbsButton) + "'>" + insulinAfterConstraints + "U" + "</font>";
if (recordOnlyCheckbox.isChecked()) {
confirmMessage += "<br/><font color='" + MainApp.gc(R.color.low) + "'>" + MainApp.gs(R.string.bolusrecordedonly) + "</font>";
}
}
if (carbsAfterConstraints > 0)
confirmMessage += "<br/>" + MainApp.gs(R.string.carbs) + ": " + carbsAfterConstraints + "g";
if (insulinAfterConstraints - insulin != 0 || !Objects.equals(carbsAfterConstraints, carbs))
confirmMessage += "<br/>" + getString(R.string.constraintapllied);
confirmMessage += "<br/>" + MainApp.gs(R.string.constraintapllied);
final double finalInsulinAfterConstraints = insulinAfterConstraints;
@ -138,9 +149,9 @@ public class NewTreatmentDialog extends DialogFragment implements OnClickListene
final Context context = getContext();
final AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(this.getContext().getString(R.string.confirmation));
builder.setTitle(MainApp.gs(R.string.confirmation));
builder.setMessage(Html.fromHtml(confirmMessage));
builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() {
builder.setPositiveButton(MainApp.gs(R.string.ok), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
synchronized (builder) {
if (accepted) {
@ -158,7 +169,7 @@ public class NewTreatmentDialog extends DialogFragment implements OnClickListene
detailedBolusInfo.carbs = finalCarbsAfterConstraints;
detailedBolusInfo.context = context;
detailedBolusInfo.source = Source.USER;
if (detailedBolusInfo.insulin > 0 || ConfigBuilderPlugin.getActivePump().getPumpDescription().storesCarbInfo) {
if (!(recordOnlyCheckbox.isChecked() && (detailedBolusInfo.insulin > 0 || ConfigBuilderPlugin.getActivePump().getPumpDescription().storesCarbInfo))) {
ConfigBuilderPlugin.getCommandQueue().bolus(detailedBolusInfo, new Callback() {
@Override
public void run() {
@ -166,7 +177,7 @@ public class NewTreatmentDialog extends DialogFragment implements OnClickListene
Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class);
i.putExtra("soundid", R.raw.boluserror);
i.putExtra("status", result.comment);
i.putExtra("title", MainApp.sResources.getString(R.string.treatmentdeliveryerror));
i.putExtra("title", MainApp.gs(R.string.treatmentdeliveryerror));
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
MainApp.instance().startActivity(i);
}
@ -175,14 +186,12 @@ public class NewTreatmentDialog extends DialogFragment implements OnClickListene
} else {
MainApp.getConfigBuilder().addToHistoryTreatment(detailedBolusInfo);
}
Answers.getInstance().logCustom(new CustomEvent("Bolus"));
FabricPrivacy.getInstance().logCustom(new CustomEvent("Bolus"));
}
}
}
});
builder.setNegativeButton(
getString(R.string.cancel), null);
builder.setNegativeButton(MainApp.gs(R.string.cancel), null);
builder.show();
dismiss();

View file

@ -25,7 +25,6 @@ import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;
import com.crashlytics.android.answers.Answers;
import com.crashlytics.android.answers.CustomEvent;
import com.squareup.otto.Subscribe;
@ -50,6 +49,7 @@ import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.db.DatabaseHelper;
import info.nightscout.androidaps.db.Source;
import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.events.EventFeatureRunning;
import info.nightscout.androidaps.events.EventNewBG;
import info.nightscout.androidaps.events.EventRefreshOverview;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
@ -57,9 +57,8 @@ import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData;
import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin;
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventAutosensCalculationFinished;
import info.nightscout.androidaps.plugins.Loop.LoopPlugin;
import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin;
import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateGui;
import info.nightscout.androidaps.queue.Callback;
import info.nightscout.utils.FabricPrivacy;
import info.nightscout.utils.BolusWizard;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.DecimalFormatter;
@ -132,6 +131,7 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com
public void onResume() {
super.onResume();
MainApp.bus().register(this);
MainApp.bus().post(new EventFeatureRunning(EventFeatureRunning.Feature.WIZARD));
}
@Override
@ -382,7 +382,7 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com
} else {
MainApp.getConfigBuilder().addToHistoryTreatment(detailedBolusInfo);
}
Answers.getInstance().logCustom(new CustomEvent("Wizard"));
FabricPrivacy.getInstance().logCustom(new CustomEvent("Wizard"));
}
}
}
@ -476,7 +476,7 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com
// COB
Double c_cob = 0d;
if (cobCheckbox.isChecked()) {
AutosensData autosensData = IobCobCalculatorPlugin.getLastAutosensData("Wizard COB");
AutosensData autosensData = IobCobCalculatorPlugin.getPlugin().getLastAutosensData("Wizard COB");
if(autosensData != null) {
c_cob = autosensData.cob;

View file

@ -3,9 +3,11 @@ package info.nightscout.androidaps.plugins.Overview;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.NotificationManager;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
@ -32,8 +34,6 @@ import android.widget.CompoundButton;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.crashlytics.android.Crashlytics;
import com.crashlytics.android.answers.Answers;
import com.crashlytics.android.answers.CustomEvent;
import com.jjoe64.graphview.GraphView;
import com.squareup.otto.Subscribe;
@ -93,10 +93,10 @@ import info.nightscout.androidaps.plugins.Loop.LoopPlugin;
import info.nightscout.androidaps.plugins.Loop.events.EventNewOpenLoopNotification;
import info.nightscout.androidaps.plugins.NSClientInternal.broadcasts.BroadcastAckAlarm;
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.ErrorHelperActivity;
import info.nightscout.androidaps.plugins.Overview.Dialogs.NewCarbsDialog;
import info.nightscout.androidaps.plugins.Overview.Dialogs.NewInsulinDialog;
import info.nightscout.androidaps.plugins.Overview.Dialogs.NewTreatmentDialog;
import info.nightscout.androidaps.plugins.Overview.Dialogs.WizardDialog;
import info.nightscout.androidaps.plugins.Overview.activities.QuickWizardListActivity;
@ -105,12 +105,14 @@ import info.nightscout.androidaps.plugins.Overview.events.EventSetWakeLock;
import info.nightscout.androidaps.plugins.Overview.graphData.GraphData;
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
import info.nightscout.androidaps.plugins.Overview.notifications.NotificationStore;
import info.nightscout.androidaps.plugins.SourceDexcomG5.SourceDexcomG5Plugin;
import info.nightscout.androidaps.plugins.SourceXdrip.SourceXdripPlugin;
import info.nightscout.androidaps.plugins.Treatments.fragments.ProfileViewerDialog;
import info.nightscout.androidaps.queue.Callback;
import info.nightscout.utils.BolusWizard;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.FabricPrivacy;
import info.nightscout.utils.NSUpload;
import info.nightscout.utils.OKDialog;
import info.nightscout.utils.Profiler;
@ -165,10 +167,14 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
LinearLayoutManager llm;
LinearLayout acceptTempLayout;
SingleClickButton acceptTempButton;
SingleClickButton treatmentButton;
SingleClickButton wizardButton;
SingleClickButton calibrationButton;
SingleClickButton acceptTempButton;
SingleClickButton insulinButton;
SingleClickButton carbsButton;
SingleClickButton cgmButton;
SingleClickButton quickWizardButton;
CheckBox lockScreen;
@ -259,6 +265,12 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
treatmentButton.setOnClickListener(this);
wizardButton = (SingleClickButton) view.findViewById(R.id.overview_wizardbutton);
wizardButton.setOnClickListener(this);
insulinButton = (SingleClickButton) view.findViewById(R.id.overview_insulinbutton);
if (insulinButton != null)
insulinButton.setOnClickListener(this);
carbsButton = (SingleClickButton) view.findViewById(R.id.overview_carbsbutton);
if (carbsButton != null)
carbsButton.setOnClickListener(this);
acceptTempButton = (SingleClickButton) view.findViewById(R.id.overview_accepttempbutton);
if (acceptTempButton != null)
acceptTempButton.setOnClickListener(this);
@ -268,6 +280,9 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
calibrationButton = (SingleClickButton) view.findViewById(R.id.overview_calibrationbutton);
if (calibrationButton != null)
calibrationButton.setOnClickListener(this);
cgmButton = (SingleClickButton) view.findViewById(R.id.overview_cgmbutton);
if (cgmButton != null)
cgmButton.setOnClickListener(this);
acceptTempLayout = (LinearLayout) view.findViewById(R.id.overview_accepttemplayout);
@ -344,7 +359,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
return view;
} catch (Exception e) {
Crashlytics.logException(e);
FabricPrivacy.logException(e);
log.debug("Runtime Exception", e);
}
@ -368,7 +383,9 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
menu.add(MainApp.sResources.getString(R.string.suspendloopfor2h));
menu.add(MainApp.sResources.getString(R.string.suspendloopfor3h));
menu.add(MainApp.sResources.getString(R.string.suspendloopfor10h));
if (pumpDescription.tempDurationStep <= 30)
if (pumpDescription.tempDurationStep15mAllowed)
menu.add(MainApp.sResources.getString(R.string.disconnectpumpfor15m));
if (pumpDescription.tempDurationStep30mAllowed)
menu.add(MainApp.sResources.getString(R.string.disconnectpumpfor30m));
menu.add(MainApp.sResources.getString(R.string.disconnectpumpfor1h));
menu.add(MainApp.sResources.getString(R.string.disconnectpumpfor2h));
@ -423,7 +440,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
activeloop.setFragmentVisible(PluginBase.LOOP, false);
MainApp.getConfigBuilder().storeSettings();
updateGUI("suspendmenu");
ConfigBuilderPlugin.getCommandQueue().cancelTempBasal(true, new Callback() {
MainApp.getConfigBuilder().getCommandQueue().cancelTempBasal(true, new Callback() {
@Override
public void run() {
if (!result.success) {
@ -431,7 +448,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
}
}
});
NSUpload.uploadOpenAPSOffline(60); // upload 60 min, we don;t know real duration
NSUpload.uploadOpenAPSOffline(24 * 60); // upload 24h, we don't know real duration
return true;
} else if (item.getTitle().equals(MainApp.sResources.getString(R.string.enableloop))) {
activeloop.setFragmentEnabled(PluginBase.LOOP, true);
@ -443,7 +460,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
} else if (item.getTitle().equals(MainApp.sResources.getString(R.string.resume))) {
activeloop.suspendTo(0L);
updateGUI("suspendmenu");
ConfigBuilderPlugin.getCommandQueue().cancelTempBasal(true, new Callback() {
MainApp.getConfigBuilder().getCommandQueue().cancelTempBasal(true, new Callback() {
@Override
public void run() {
if (!result.success) {
@ -454,148 +471,40 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
NSUpload.uploadOpenAPSOffline(0);
return true;
} else if (item.getTitle().equals(MainApp.sResources.getString(R.string.suspendloopfor1h))) {
activeloop.suspendTo(System.currentTimeMillis() + 60L * 60 * 1000);
MainApp.getConfigBuilder().suspendLoop(60);
updateGUI("suspendmenu");
ConfigBuilderPlugin.getCommandQueue().cancelTempBasal(true, new Callback() {
@Override
public void run() {
if (!result.success) {
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.tempbasaldeliveryerror));
}
}
});
NSUpload.uploadOpenAPSOffline(60);
return true;
} else if (item.getTitle().equals(MainApp.sResources.getString(R.string.suspendloopfor2h))) {
activeloop.suspendTo(System.currentTimeMillis() + 2 * 60L * 60 * 1000);
MainApp.getConfigBuilder().suspendLoop(120);
updateGUI("suspendmenu");
ConfigBuilderPlugin.getCommandQueue().cancelTempBasal(true, new Callback() {
@Override
public void run() {
if (!result.success) {
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.tempbasaldeliveryerror));
}
}
});
NSUpload.uploadOpenAPSOffline(120);
return true;
} else if (item.getTitle().equals(MainApp.sResources.getString(R.string.suspendloopfor3h))) {
activeloop.suspendTo(System.currentTimeMillis() + 3 * 60L * 60 * 1000);
MainApp.getConfigBuilder().suspendLoop(180);
updateGUI("suspendmenu");
ConfigBuilderPlugin.getCommandQueue().cancelTempBasal(true, new Callback() {
@Override
public void run() {
if (!result.success) {
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.tempbasaldeliveryerror));
}
}
});
NSUpload.uploadOpenAPSOffline(180);
return true;
} else if (item.getTitle().equals(MainApp.sResources.getString(R.string.suspendloopfor10h))) {
activeloop.suspendTo(System.currentTimeMillis() + 10 * 60L * 60 * 1000);
MainApp.getConfigBuilder().suspendLoop(600);
updateGUI("suspendmenu");
return true;
} else if (item.getTitle().equals(MainApp.sResources.getString(R.string.disconnectpumpfor15m))) {
MainApp.getConfigBuilder().disconnectPump(15);
updateGUI("suspendmenu");
ConfigBuilderPlugin.getCommandQueue().cancelTempBasal(true, new Callback() {
@Override
public void run() {
if (!result.success) {
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.tempbasaldeliveryerror));
}
}
});
NSUpload.uploadOpenAPSOffline(600);
return true;
} else if (item.getTitle().equals(MainApp.sResources.getString(R.string.disconnectpumpfor30m))) {
activeloop.disconnectTo(System.currentTimeMillis() + 30L * 60 * 1000);
MainApp.getConfigBuilder().disconnectPump(30);
updateGUI("suspendmenu");
ConfigBuilderPlugin.getCommandQueue().tempBasalPercent(0, 30, true, new Callback() {
@Override
public void run() {
if (!result.success) {
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.tempbasaldeliveryerror));
}
}
});
if (MainApp.getConfigBuilder().getActivePump().getPumpDescription().isExtendedBolusCapable && MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) {
ConfigBuilderPlugin.getCommandQueue().cancelExtended( new Callback() {
@Override
public void run() {
if (!result.success) {
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.extendedbolusdeliveryerror));
}
}
});
}
NSUpload.uploadOpenAPSOffline(30);
return true;
} else if (item.getTitle().equals(MainApp.sResources.getString(R.string.disconnectpumpfor1h))) {
activeloop.disconnectTo(System.currentTimeMillis() + 1 * 60L * 60 * 1000);
MainApp.getConfigBuilder().disconnectPump(60);
updateGUI("suspendmenu");
ConfigBuilderPlugin.getCommandQueue().tempBasalPercent(0, 60, true, new Callback() {
@Override
public void run() {
if (!result.success) {
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.tempbasaldeliveryerror));
}
}
});
if (MainApp.getConfigBuilder().getActivePump().getPumpDescription().isExtendedBolusCapable && MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) {
ConfigBuilderPlugin.getCommandQueue().cancelExtended( new Callback() {
@Override
public void run() {
if (!result.success) {
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.extendedbolusdeliveryerror));
}
}
});
}
NSUpload.uploadOpenAPSOffline(60);
return true;
} else if (item.getTitle().equals(MainApp.sResources.getString(R.string.disconnectpumpfor2h))) {
activeloop.disconnectTo(System.currentTimeMillis() + 2 * 60L * 60 * 1000);
MainApp.getConfigBuilder().disconnectPump(120);
updateGUI("suspendmenu");
ConfigBuilderPlugin.getCommandQueue().tempBasalPercent(0, 2 * 60, true, new Callback() {
@Override
public void run() {
if (!result.success) {
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.tempbasaldeliveryerror));
}
}
});
if (MainApp.getConfigBuilder().getActivePump().getPumpDescription().isExtendedBolusCapable && MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) {
ConfigBuilderPlugin.getCommandQueue().cancelExtended( new Callback() {
@Override
public void run() {
if (!result.success) {
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.extendedbolusdeliveryerror));
}
}
});
}
NSUpload.uploadOpenAPSOffline(120);
return true;
} else if (item.getTitle().equals(MainApp.sResources.getString(R.string.disconnectpumpfor3h))) {
activeloop.disconnectTo(System.currentTimeMillis() + 3 * 60L * 60 * 1000);
MainApp.getConfigBuilder().disconnectPump(180);
updateGUI("suspendmenu");
ConfigBuilderPlugin.getCommandQueue().tempBasalPercent(0, 3 * 60, true, new Callback() {
@Override
public void run() {
if (!result.success) {
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.tempbasaldeliveryerror));
}
}
});
if (MainApp.getConfigBuilder().getActivePump().getPumpDescription().isExtendedBolusCapable && MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) {
ConfigBuilderPlugin.getCommandQueue().cancelExtended( new Callback() {
@Override
public void run() {
if (!result.success) {
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.extendedbolusdeliveryerror));
}
}
});
}
NSUpload.uploadOpenAPSOffline(180);
return true;
} else if (item.getTitle().equals(MainApp.sResources.getString(R.string.careportal_profileswitch))) {
NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog();
@ -614,6 +523,10 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
@Override
public void onClick(View v) {
boolean xdrip = MainApp.getSpecificPlugin(SourceXdripPlugin.class) != null && MainApp.getSpecificPlugin(SourceXdripPlugin.class).isEnabled(PluginBase.BGSOURCE);
boolean g5 = MainApp.getSpecificPlugin(SourceDexcomG5Plugin.class) != null && MainApp.getSpecificPlugin(SourceDexcomG5Plugin.class).isEnabled(PluginBase.BGSOURCE);
String units = MainApp.getConfigBuilder().getProfileUnits();
FragmentManager manager = getFragmentManager();
switch (v.getId()) {
case R.id.overview_accepttempbutton:
@ -627,13 +540,36 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
wizardDialog.show(manager, "WizardDialog");
break;
case R.id.overview_calibrationbutton:
CalibrationDialog calibrationDialog = new CalibrationDialog();
calibrationDialog.show(manager, "CalibrationDialog");
if (xdrip) {
CalibrationDialog calibrationDialog = new CalibrationDialog();
calibrationDialog.show(manager, "CalibrationDialog");
} else if (g5) {
try {
Intent i = new Intent("com.dexcom.cgm.activities.MeterEntryActivity");
startActivity(i);
} catch (ActivityNotFoundException e) {
ToastUtils.showToastInUiThread(getActivity(), MainApp.gs(R.string.g5appnotdetected));
}
}
break;
case R.id.overview_cgmbutton:
if (xdrip)
openCgmApp("com.eveningoutpost.dexdrip");
else if (g5 && units.equals(Constants.MGDL))
openCgmApp("com.dexcom.cgm.region5.mgdl");
else if (g5 && units.equals(Constants.MMOL))
openCgmApp("com.dexcom.cgm.region5.mmol");
break;
case R.id.overview_treatmentbutton:
NewTreatmentDialog treatmentDialogFragment = new NewTreatmentDialog();
treatmentDialogFragment.show(manager, "TreatmentDialog");
break;
case R.id.overview_insulinbutton:
new NewInsulinDialog().show(manager, "InsulinDialog");
break;
case R.id.overview_carbsbutton:
new NewCarbsDialog().show(manager, "CarbsDialog");
break;
case R.id.overview_pumpstatus:
if (ConfigBuilderPlugin.getActivePump().isSuspended() || !ConfigBuilderPlugin.getActivePump().isInitialized())
ConfigBuilderPlugin.getCommandQueue().readStatus("RefreshClicked", null);
@ -660,6 +596,25 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
}
public boolean openCgmApp(String packageName) {
PackageManager packageManager = getContext().getPackageManager();
try {
Intent intent = packageManager.getLaunchIntentForPackage(packageName);
if (intent == null) {
throw new ActivityNotFoundException();
}
intent.addCategory(Intent.CATEGORY_LAUNCHER);
getContext().startActivity(intent);
return true;
} catch (ActivityNotFoundException e) {
new AlertDialog.Builder(getContext())
.setMessage(R.string.error_starting_cgm)
.setPositiveButton("OK", null)
.show();
return false;
}
}
@Override
public boolean onLongClick(View v) {
switch (v.getId()) {
@ -675,7 +630,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
if (ConfigBuilderPlugin.getActiveLoop() != null) {
ConfigBuilderPlugin.getActiveLoop().invoke("Accept temp button", false);
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());
builder.setTitle(getContext().getString(R.string.confirmation));
builder.setMessage(getContext().getString(R.string.setbasalquestion) + "\n" + finalLastRun.constraintsProcessed);
@ -700,7 +655,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
scheduleUpdateGUI("onClickAcceptTemp");
}
});
Answers.getInstance().logCustom(new CustomEvent("AcceptTemp"));
FabricPrivacy.getInstance().logCustom(new CustomEvent("AcceptTemp"));
}
});
builder.setNegativeButton(getContext().getString(R.string.cancel), null);
@ -816,7 +771,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
}
}
});
Answers.getInstance().logCustom(new CustomEvent("QuickWizard"));
FabricPrivacy.getInstance().logCustom(new CustomEvent("QuickWizard"));
}
}
}
@ -1017,16 +972,8 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
return;
}
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 double lowLine = OverviewPlugin.getPlugin().determineLowLine(units);
final double highLine = OverviewPlugin.getPlugin().determineHighLine(units);
//Start with updating the BG as it is unaffected by loop.
// **** BG value ****
@ -1106,7 +1053,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
boolean showAcceptButton = !MainApp.getConfigBuilder().isClosedModeEnabled(); // Open mode needed
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.constraintsProcessed.changeRequested; // change is requested
showAcceptButton = showAcceptButton && finalLastRun.constraintsProcessed.isChangeRequested(); // change is requested
if (showAcceptButton && pump.isInitialized() && !pump.isSuspended() && ConfigBuilderPlugin.getActiveLoop() != null) {
acceptTempLayout.setVisibility(View.VISIBLE);
@ -1116,14 +1063,26 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
}
}
// **** Calibration button ****
// **** Calibration & CGM buttons ****
boolean xDripIsBgSource = MainApp.getSpecificPlugin(SourceXdripPlugin.class) != null && MainApp.getSpecificPlugin(SourceXdripPlugin.class).isEnabled(PluginBase.BGSOURCE);
boolean g5IsBgSource = MainApp.getSpecificPlugin(SourceDexcomG5Plugin.class) != null && MainApp.getSpecificPlugin(SourceDexcomG5Plugin.class).isEnabled(PluginBase.BGSOURCE);
boolean bgAvailable = DatabaseHelper.actualBg() != null;
if (calibrationButton != null) {
if (MainApp.getSpecificPlugin(SourceXdripPlugin.class) != null && MainApp.getSpecificPlugin(SourceXdripPlugin.class).isEnabled(PluginBase.BGSOURCE) && profile != null && DatabaseHelper.actualBg() != null) {
if ((xDripIsBgSource || g5IsBgSource) && bgAvailable && SP.getBoolean(R.string.key_show_calibration_button, true)) {
calibrationButton.setVisibility(View.VISIBLE);
} else {
calibrationButton.setVisibility(View.GONE);
}
}
if (cgmButton != null) {
if (xDripIsBgSource && SP.getBoolean(R.string.key_show_cgm_button, false)) {
cgmButton.setVisibility(View.VISIBLE);
} else if (g5IsBgSource && SP.getBoolean(R.string.key_show_cgm_button, false)) {
cgmButton.setVisibility(View.VISIBLE);
} else {
cgmButton.setVisibility(View.GONE);
}
}
final TemporaryBasal activeTemp = MainApp.getConfigBuilder().getTempBasalFromHistory(System.currentTimeMillis());
String basalText = "";
@ -1220,15 +1179,40 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
} else
quickWizardButton.setVisibility(View.GONE);
// Bolus and calc button
if (pump.isInitialized() && !pump.isSuspended()) {
wizardButton.setVisibility(View.VISIBLE);
treatmentButton.setVisibility(View.VISIBLE);
} else {
wizardButton.setVisibility(View.GONE);
treatmentButton.setVisibility(View.GONE);
// **** Various treatment buttons ****
if (carbsButton != null) {
if (SP.getBoolean(R.string.key_show_carbs_button, true)
&& !ConfigBuilderPlugin.getActivePump().getPumpDescription().storesCarbInfo ||
(pump.isInitialized() && !pump.isSuspended())) {
carbsButton.setVisibility(View.VISIBLE);
} else {
carbsButton.setVisibility(View.GONE);
}
}
if (pump.isInitialized() && !pump.isSuspended()) {
if (treatmentButton != null) {
if (SP.getBoolean(R.string.key_show_treatment_button, false)) {
treatmentButton.setVisibility(View.VISIBLE);
} else {
treatmentButton.setVisibility(View.GONE);
}
}
if (wizardButton != null) {
if (SP.getBoolean(R.string.key_show_wizard_button, true)) {
wizardButton.setVisibility(View.VISIBLE);
} else {
wizardButton.setVisibility(View.GONE);
}
}
if (insulinButton != null) {
if (SP.getBoolean(R.string.key_show_insulin_button, true)) {
insulinButton.setVisibility(View.VISIBLE);
} else {
insulinButton.setVisibility(View.GONE);
}
}
}
// **** BG value ****
if (lastBG == null) { //left this here as it seems you want to exit at this point if it is null...
@ -1276,14 +1260,14 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
// cob
if (cobView != null) { // view must not exists
String cobText = "";
AutosensData autosensData = IobCobCalculatorPlugin.getLastAutosensData("Overview COB");
AutosensData autosensData = IobCobCalculatorPlugin.getPlugin().getLastAutosensData("Overview COB");
if (autosensData != null)
cobText = (int) autosensData.cob + " g";
cobView.setText(cobText);
}
final boolean showPrediction = showPredictionCheckbox.isChecked() && finalLastRun != null && finalLastRun.constraintsProcessed.getClass().equals(DetermineBasalResultAMA.class);
if (MainApp.getSpecificPlugin(OpenAPSAMAPlugin.class) != null && MainApp.getSpecificPlugin(OpenAPSAMAPlugin.class).isEnabled(PluginBase.APS)) {
final boolean predictionsAvailable = finalLastRun != null && finalLastRun.request.hasPredictions;
if (predictionsAvailable) {
showPredictionCheckbox.setVisibility(View.VISIBLE);
showPredictionLabel.setVisibility(View.VISIBLE);
} else {
@ -1341,8 +1325,8 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
final long toTime;
final long fromTime;
final long endTime;
if (showPrediction) {
int predHours = (int) (Math.ceil(((DetermineBasalResultAMA) finalLastRun.constraintsProcessed).getLatestPredictionsTime() - System.currentTimeMillis()) / (60 * 60 * 1000));
if (predictionsAvailable && showPredictionCheckbox.isChecked()) {
int predHours = (int) (Math.ceil(finalLastRun.constraintsProcessed.getLatestPredictionsTime() - System.currentTimeMillis()) / (60 * 60 * 1000));
predHours = Math.min(2, predHours);
predHours = Math.max(0, predHours);
hoursToFetch = rangeToDisplay - predHours;
@ -1362,14 +1346,14 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
// ------------------ 1st graph
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 ****
graphData.addInRangeArea(fromTime, endTime, lowLine, highLine);
// **** BG ****
if (showPrediction)
graphData.addBgReadings(fromTime, toTime, lowLine, highLine, (DetermineBasalResultAMA) finalLastRun.constraintsProcessed);
if (predictionsAvailable && showPredictionCheckbox.isChecked())
graphData.addBgReadings(fromTime, toTime, lowLine, highLine, finalLastRun.constraintsProcessed);
else
graphData.addBgReadings(fromTime, toTime, lowLine, highLine, null);
@ -1384,18 +1368,22 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
graphData.addBasals(fromTime, now, lowLine / graphData.maxY / 1.2d);
}
// add target line
graphData.addTargetLine(fromTime, toTime);
// **** NOW line ****
graphData.addNowLine(now);
// ------------------ 2nd graph
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 useCobForScale = false;
boolean useDevForScale = false;
boolean useRatioForScale = false;
boolean useDSForScale = false;
if (showIobCheckbox.isChecked()) {
useIobForScale = true;
@ -1405,6 +1393,8 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
useDevForScale = true;
} else if (showRatiosCheckbox.isChecked()) {
useRatioForScale = true;
} else if (Config.displayDeviationSlope) {
useDSForScale = true;
}
if (showIobCheckbox.isChecked())
@ -1415,6 +1405,8 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
secondGraphData.addDeviations(fromTime, now, useDevForScale, 1d);
if (showRatiosCheckbox.isChecked())
secondGraphData.addRatio(fromTime, now, useRatioForScale, 1d);
if (Config.displayDeviationSlope)
secondGraphData.addDeviationSlope(fromTime, now, useDSForScale, 1d);
// **** NOW line ****
// set manual x bounds to have nice steps
@ -1427,7 +1419,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
if (showIobCheckbox.isChecked() || showCobCheckbox.isChecked() || showDeviationsCheckbox.isChecked() || showRatiosCheckbox.isChecked()) {
if (showIobCheckbox.isChecked() || showCobCheckbox.isChecked() || showDeviationsCheckbox.isChecked() || showRatiosCheckbox.isChecked() || Config.displayDeviationSlope) {
iobGraph.setVisibility(View.VISIBLE);
} else {
iobGraph.setVisibility(View.GONE);

View file

@ -9,6 +9,7 @@ import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.QuickWizard;
import info.nightscout.androidaps.events.EventRefreshOverview;
import info.nightscout.androidaps.interfaces.PluginBase;
@ -26,7 +27,6 @@ public class OverviewPlugin implements PluginBase {
private static OverviewPlugin overviewPlugin = new OverviewPlugin();
public static OverviewPlugin getPlugin() {
if (overviewPlugin == null)
overviewPlugin = new OverviewPlugin();
return overviewPlugin;
@ -92,7 +92,7 @@ public class OverviewPlugin implements PluginBase {
@Override
public boolean showInList(int type) {
return false;
return true;
}
@Override
@ -107,7 +107,7 @@ public class OverviewPlugin implements PluginBase {
@Override
public int getPreferencesId() {
return -1;
return R.xml.pref_overview;
}
@Override
@ -128,4 +128,34 @@ public class OverviewPlugin implements PluginBase {
MainApp.bus().post(new EventRefreshOverview("EventDismissNotification"));
}
public double determineHighLine() {
Profile profile = MainApp.getConfigBuilder().getProfile();
if (profile == null) {
return bgTargetHigh;
}
return determineHighLine(profile.getUnits());
}
public double determineHighLine(String units) {
double highLineSetting = SP.getDouble("high_mark", Profile.fromMgdlToUnits(OverviewPlugin.bgTargetHigh, units));
if (highLineSetting < 1)
highLineSetting = Profile.fromMgdlToUnits(180d, units);
return highLineSetting;
}
public double determineLowLine() {
Profile profile = MainApp.getConfigBuilder().getProfile();
if (profile == null) {
return bgTargetLow;
}
return determineLowLine(profile.getUnits());
}
public double determineLowLine(String units) {
double lowLineSetting = SP.getDouble("low_mark", Profile.fromMgdlToUnits(OverviewPlugin.bgTargetLow, units));
if (lowLineSetting < 1)
lowLineSetting = Profile.fromMgdlToUnits(76d, units);
return lowLineSetting;
}
}

View file

@ -3,6 +3,7 @@ package info.nightscout.androidaps.plugins.Overview.events;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.events.Event;
@ -11,11 +12,16 @@ public class EventOverviewBolusProgress extends Event {
public String status = "";
public Treatment t = null;
public int percent = 0;
public int bolusId;
private static EventOverviewBolusProgress eventOverviewBolusProgress = null;
public EventOverviewBolusProgress() {
}
public boolean isSMB(){
return (t != null) && t.isSMB;
}
public static EventOverviewBolusProgress getInstance() {
if(eventOverviewBolusProgress == null) {
eventOverviewBolusProgress = new EventOverviewBolusProgress();

View file

@ -12,7 +12,6 @@ import com.jjoe64.graphview.series.LineGraphSeries;
import com.jjoe64.graphview.series.Series;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
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.ExtendedBolus;
import info.nightscout.androidaps.db.ProfileSwitch;
import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData;
import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin;
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.DataPointWithLabelInterface;
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.ScaledDataPoint;
import info.nightscout.androidaps.plugins.Overview.graphExtensions.TimeAsXAxisLabelFormatter;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.utils.Round;
/**
@ -51,12 +53,15 @@ public class GraphData {
private String units;
private List<Series> series = new ArrayList<>();
public GraphData(GraphView graph) {
private IobCobCalculatorPlugin iobCobCalculatorPlugin;
public GraphData(GraphView graph, IobCobCalculatorPlugin iobCobCalculatorPlugin) {
units = MainApp.getConfigBuilder().getProfileUnits();
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;
bgReadingsArray = MainApp.getDbHelper().getBgreadingsDataFromTime(fromTime, true);
List<DataPointWithLabelInterface> bgListArray = new ArrayList<>();
@ -65,14 +70,12 @@ public class GraphData {
return;
}
Iterator<BgReading> it = bgReadingsArray.iterator();
while (it.hasNext()) {
BgReading bg = it.next();
for (BgReading bg : bgReadingsArray) {
if (bg.value > maxBgValue) maxBgValue = bg.value;
bgListArray.add(bg);
}
if (amaResult != null) {
List<BgReading> predArray = amaResult.getPredictions();
if (apsResult != null) {
List<BgReading> predArray = apsResult.getPredictions();
bgListArray.addAll(predArray);
}
@ -125,11 +128,11 @@ public class GraphData {
List<ScaledDataPoint> basalLineArray = new ArrayList<>();
List<ScaledDataPoint> absoluteBasalLineArray = new ArrayList<>();
double lastLineBasal = 0;
double lastAbsoluteLineBasal = 0;
double lastAbsoluteLineBasal = -1;
double lastBaseBasal = 0;
double lastTempBasal = 0;
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 absoluteLineValue = baseBasalValue;
double tempBasalValue = 0;
@ -218,6 +221,54 @@ public class GraphData {
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.target();
}
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) {
List<DataPointWithLabelInterface> filteredTreatments = new ArrayList<>();
@ -267,7 +318,7 @@ public class GraphData {
addSeries(new PointsWithLabelGraphSeries<>(treatmentsArray));
}
double getNearestBg(long date) {
private double getNearestBg(long date) {
double bg = 0;
for (int r = bgReadingsArray.size() - 1; r >= 0; r--) {
BgReading reading = bgReadingsArray.get(r);
@ -287,7 +338,7 @@ public class GraphData {
Scale iobScale = new Scale();
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.2)
iobArray.add(new ScaledDataPoint(time, lastIob, iobScale));
@ -322,7 +373,7 @@ public class GraphData {
Scale cobScale = new Scale();
for (long time = fromTime; time <= toTime; time += 5 * 60 * 1000L) {
AutosensData autosensData = IobCobCalculatorPlugin.getAutosensData(time);
AutosensData autosensData = IobCobCalculatorPlugin.getPlugin().getAutosensData(time);
if (autosensData != null) {
int cob = (int) autosensData.cob;
if (cob != lastCob) {
@ -369,7 +420,7 @@ public class GraphData {
Scale devScale = new Scale();
for (long time = fromTime; time <= toTime; time += 5 * 60 * 1000L) {
AutosensData autosensData = IobCobCalculatorPlugin.getAutosensData(time);
AutosensData autosensData = IobCobCalculatorPlugin.getPlugin().getAutosensData(time);
if (autosensData != null) {
int color = Color.BLACK; // "="
if (autosensData.pastSensitivity.equals("C")) color = Color.GRAY;
@ -401,21 +452,21 @@ public class GraphData {
// scale in % of vertical size (like 0.3)
public void addRatio(long fromTime, long toTime, boolean useForScale, double scale) {
LineGraphSeries<DataPoint> ratioSeries;
List<DataPoint> ratioArray = new ArrayList<>();
LineGraphSeries<ScaledDataPoint> ratioSeries;
List<ScaledDataPoint> ratioArray = new ArrayList<>();
Double maxRatioValueFound = 0d;
Scale ratioScale = new Scale(-1d);
for (long time = fromTime; time <= toTime; time += 5 * 60 * 1000L) {
AutosensData autosensData = IobCobCalculatorPlugin.getAutosensData(time);
AutosensData autosensData = IobCobCalculatorPlugin.getPlugin().getAutosensData(time);
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));
}
}
// RATIOS
DataPoint[] ratioData = new DataPoint[ratioArray.size()];
ScaledDataPoint[] ratioData = new ScaledDataPoint[ratioArray.size()];
ratioData = ratioArray.toArray(ratioData);
ratioSeries = new LineGraphSeries<>(ratioData);
ratioSeries.setColor(MainApp.sResources.getColor(R.color.ratio));
@ -429,6 +480,50 @@ public class GraphData {
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)
public void addNowLine(long now) {
LineGraphSeries<DataPoint> seriesNow;

View file

@ -55,4 +55,5 @@ public interface DataPointWithLabelInterface extends DataPointInterface{
PointsWithLabelGraphSeries.Shape getShape();
float getSize();
int getColor();
int getSecondColor();
}

View file

@ -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}
*/
public enum Shape {
/**
* draws a point / circle
*/
POINT,
/**
* draws a triangle
*/
BG,
PREDICTION,
TRIANGLE,
RECTANGLE,
BOLUS,
SMB,
EXTENDEDBOLUS,
PROFILE,
MBG,
@ -202,9 +197,19 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
// draw data point
if (!overdraw) {
if (value.getShape() == Shape.POINT) {
if (value.getShape() == Shape.BG) {
mPaint.setStyle(Paint.Style.FILL);
mPaint.setStrokeWidth(0);
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) {
canvas.drawRect(endX-scaledPxSize, endY-scaledPxSize, endX+scaledPxSize, endY+scaledPxSize, mPaint);
} else if (value.getShape() == Shape.TRIANGLE) {
@ -225,6 +230,14 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
if (value.getLabel() != null) {
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) {
mPaint.setStrokeWidth(0);
if (value.getLabel() != null) {

View file

@ -21,8 +21,6 @@ import java.util.List;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.Services.AlarmSoundService;
import info.nightscout.androidaps.plugins.Wear.WearPlugin;
//Added by Rumen for snooze time
import info.nightscout.utils.SP;
/**
@ -44,16 +42,12 @@ public class NotificationStore {
}
}
public Notification get(int index) {
return store.get(index);
}
public void add(Notification n) {
public synchronized void add(Notification n) {
log.info("Notification received: " + n.text);
for (int i = 0; i < store.size(); i++) {
if (get(i).id == n.id) {
get(i).date = n.date;
get(i).validTo = n.validTo;
for (Notification storeNotification : store) {
if (storeNotification.id == n.id) {
storeNotification.date = n.date;
storeNotification.validTo = n.validTo;
return;
}
}
@ -72,6 +66,44 @@ public class NotificationStore {
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) {
Context context = MainApp.instance().getApplicationContext();
NotificationManager mgr = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
@ -95,42 +127,4 @@ public class NotificationStore {
}
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!");
}
}
}

View file

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

View file

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

View file

@ -13,7 +13,6 @@ import android.widget.Button;
import android.widget.RadioButton;
import android.widget.TextView;
import com.crashlytics.android.Crashlytics;
import com.squareup.otto.Subscribe;
import org.slf4j.Logger;
@ -33,6 +32,7 @@ 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.FabricPrivacy;
import info.nightscout.utils.NumberPicker;
import info.nightscout.utils.SafeParse;
import info.nightscout.utils.TimeListEdit;
@ -140,7 +140,7 @@ public class LocalProfileFragment extends SubscriberFragment {
return layout;
} catch (Exception e) {
log.error("Unhandled exception: ", e);
Crashlytics.logException(e);
FabricPrivacy.logException(e);
}
return null;

View file

@ -10,7 +10,6 @@ import android.widget.ArrayAdapter;
import android.widget.Spinner;
import android.widget.TextView;
import com.crashlytics.android.Crashlytics;
import com.squareup.otto.Subscribe;
import java.util.ArrayList;
@ -22,6 +21,7 @@ import info.nightscout.androidaps.data.ProfileStore;
import info.nightscout.androidaps.plugins.Common.SubscriberFragment;
import info.nightscout.androidaps.plugins.ProfileNS.events.EventNSProfileUpdateGUI;
import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.FabricPrivacy;
public class NSProfileFragment extends SubscriberFragment implements AdapterView.OnItemSelectedListener {
@ -56,7 +56,7 @@ public class NSProfileFragment extends SubscriberFragment implements AdapterView
updateGUI();
return layout;
} catch (Exception e) {
Crashlytics.logException(e);
FabricPrivacy.logException(e);
}
return null;

View file

@ -13,7 +13,6 @@ import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.TextView;
import com.crashlytics.android.Crashlytics;
import com.squareup.otto.Subscribe;
import org.slf4j.Logger;
@ -27,6 +26,7 @@ import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialo
import info.nightscout.androidaps.plugins.Careportal.OptionsToShow;
import info.nightscout.androidaps.plugins.Common.SubscriberFragment;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.utils.FabricPrivacy;
import info.nightscout.utils.SafeParse;
public class SimpleProfileFragment extends SubscriberFragment {
@ -137,7 +137,7 @@ public class SimpleProfileFragment extends SubscriberFragment {
return layout;
} catch (Exception e) {
Crashlytics.logException(e);
FabricPrivacy.logException(e);
}
return null;

View file

@ -34,6 +34,7 @@ import info.nightscout.androidaps.plugins.PumpDanaR.services.AbstractDanaRExecut
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.
@ -293,7 +294,7 @@ public abstract class AbstractDanaRPlugin implements PluginBase, PumpInterface,
result.isTempCancel = false;
result.duration = pump.extendedBolusRemainingMinutes;
result.absolute = pump.extendedBolusAbsoluteRate;
result.bolusDelivered = pump.extendedBolusAmount;
if (! SP.getBoolean("danar_useextended", false)) result.bolusDelivered = pump.extendedBolusAmount;
result.isPercent = false;
if (Config.logPumpActions)
log.debug("setExtendedBolus: OK");
@ -538,11 +539,13 @@ public abstract class AbstractDanaRPlugin implements PluginBase, PumpInterface,
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";
TemporaryBasal activeTemp = MainApp.getConfigBuilder().getRealTempBasalFromHistory(System.currentTimeMillis());
if (activeTemp != null) {
ret += "Temp: " + activeTemp.toStringFull() + "\n";
}
if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) {
ret += "Extended: " + MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis()).toString() + "\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";

View file

@ -15,7 +15,7 @@ import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.crashlytics.android.Crashlytics;
import com.squareup.otto.Subscribe;
import org.slf4j.Logger;
@ -29,6 +29,7 @@ import butterknife.OnClick;
import butterknife.Unbinder;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.db.ExtendedBolus;
import info.nightscout.androidaps.events.EventExtendedBolusChange;
import info.nightscout.androidaps.events.EventPumpStatusChanged;
import info.nightscout.androidaps.events.EventTempBasalChange;
@ -41,6 +42,7 @@ import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRNewStatus;
import info.nightscout.androidaps.queue.events.EventQueueChanged;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.FabricPrivacy;
import info.nightscout.utils.SetWarnColor;
public class DanaRFragment extends SubscriberFragment {
@ -100,7 +102,7 @@ public class DanaRFragment extends SubscriberFragment {
return view;
} catch (Exception e) {
Crashlytics.logException(e);
FabricPrivacy.logException(e);
}
return null;
@ -216,8 +218,9 @@ public class DanaRFragment extends SubscriberFragment {
tempBasalView.setText("");
}
}
if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) {
extendedBolusView.setText(MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis()).toString());
ExtendedBolus activeExtendedBolus = MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis());
if (activeExtendedBolus != null) {
extendedBolusView.setText(activeExtendedBolus.toString());
} else {
extendedBolusView.setText("");
}
@ -226,7 +229,7 @@ public class DanaRFragment extends SubscriberFragment {
batteryView.setText("{fa-battery-" + (pump.batteryRemaining / 25) + "}");
SetWarnColor.setColorInverse(batteryView, pump.batteryRemaining, 51d, 26d);
iobView.setText(pump.iob + " U");
if (pump.isNewPump) {
if (pump.model != 0 || pump.protocol != 0 || pump.productCode != 0) {
firmwareView.setText(String.format(MainApp.sResources.getString(R.string.danar_model), pump.model, pump.protocol, pump.productCode));
} else {
firmwareView.setText("OLD");

View file

@ -134,6 +134,7 @@ public class DanaRPlugin extends AbstractDanaRPlugin {
detailedBolusInfo.insulin = configBuilderPlugin.applyBolusConstraints(detailedBolusInfo.insulin);
if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) {
Treatment t = new Treatment();
t.isSMB = detailedBolusInfo.isSMB;
boolean connectionOK = false;
if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) connectionOK = sExecutionService.bolus(detailedBolusInfo.insulin, (int) detailedBolusInfo.carbs, detailedBolusInfo.carbTime, t);
PumpEnactResult result = new PumpEnactResult();
@ -315,8 +316,7 @@ public class DanaRPlugin extends AbstractDanaRPlugin {
if (MainApp.getConfigBuilder().isInHistoryRealTempBasalInProgress())
return cancelRealTempBasal();
if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress() && useExtendedBoluses) {
PumpEnactResult cancelEx = cancelExtendedBolus();
return cancelEx;
return cancelExtendedBolus();
}
PumpEnactResult result = new PumpEnactResult();
result.success = true;

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