Merge branch 'smb060' into dev
This commit is contained in:
commit
6312b81e10
61
app/src/main/assets/OpenAPSSMB/basal-set-temp.js
Normal file
61
app/src/main/assets/OpenAPSSMB/basal-set-temp.js
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
function reason(rT, msg) {
|
||||||
|
rT.reason = (rT.reason ? rT.reason + '. ' : '') + msg;
|
||||||
|
console.error(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
var tempBasalFunctions = {};
|
||||||
|
|
||||||
|
tempBasalFunctions.getMaxSafeBasal = function getMaxSafeBasal(profile) {
|
||||||
|
|
||||||
|
var max_daily_safety_multiplier = (isNaN(profile.max_daily_safety_multiplier) || profile.max_daily_safety_multiplier == null) ? 3 : profile.max_daily_safety_multiplier;
|
||||||
|
var current_basal_safety_multiplier = (isNaN(profile.current_basal_safety_multiplier) || profile.current_basal_safety_multiplier == null) ? 4 : profile.current_basal_safety_multiplier;
|
||||||
|
|
||||||
|
return Math.min(profile.max_basal, max_daily_safety_multiplier * profile.max_daily_basal, current_basal_safety_multiplier * profile.current_basal);
|
||||||
|
};
|
||||||
|
|
||||||
|
tempBasalFunctions.setTempBasal = function setTempBasal(rate, duration, profile, rT, currenttemp) {
|
||||||
|
//var maxSafeBasal = Math.min(profile.max_basal, 3 * profile.max_daily_basal, 4 * profile.current_basal);
|
||||||
|
|
||||||
|
var maxSafeBasal = tempBasalFunctions.getMaxSafeBasal(profile);
|
||||||
|
var round_basal = require('./round-basal');
|
||||||
|
|
||||||
|
if (rate < 0) {
|
||||||
|
rate = 0;
|
||||||
|
} // if >30m @ 0 required, zero temp will be extended to 30m instead
|
||||||
|
else if (rate > maxSafeBasal) {
|
||||||
|
rate = maxSafeBasal;
|
||||||
|
}
|
||||||
|
|
||||||
|
var suggestedRate = round_basal(rate, profile);
|
||||||
|
if (typeof(currenttemp) !== 'undefined' && typeof(currenttemp.duration) !== 'undefined' && typeof(currenttemp.rate) !== 'undefined' && currenttemp.duration > (duration-10) && currenttemp.duration <= 120 && suggestedRate <= currenttemp.rate * 1.2 && suggestedRate >= currenttemp.rate * 0.8) {
|
||||||
|
rT.reason += " "+currenttemp.duration+"m left and " + currenttemp.rate + " ~ req " + suggestedRate + "U/hr: no temp required";
|
||||||
|
return rT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (suggestedRate === profile.current_basal) {
|
||||||
|
if (profile.skip_neutral_temps) {
|
||||||
|
if (typeof(currenttemp) !== 'undefined' && typeof(currenttemp.duration) !== 'undefined' && currenttemp.duration > 0) {
|
||||||
|
reason(rT, 'Suggested rate is same as profile rate, a temp basal is active, canceling current temp');
|
||||||
|
rT.duration = 0;
|
||||||
|
rT.rate = 0;
|
||||||
|
return rT;
|
||||||
|
} else {
|
||||||
|
reason(rT, 'Suggested rate is same as profile rate, no temp basal is active, doing nothing');
|
||||||
|
return rT;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
reason(rT, 'Setting neutral temp basal of ' + profile.current_basal + 'U/hr');
|
||||||
|
rT.duration = duration;
|
||||||
|
rT.rate = suggestedRate;
|
||||||
|
return rT;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rT.duration = duration;
|
||||||
|
rT.rate = suggestedRate;
|
||||||
|
return rT;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = tempBasalFunctions;
|
1146
app/src/main/assets/OpenAPSSMB/determine-basal.js
Normal file
1146
app/src/main/assets/OpenAPSSMB/determine-basal.js
Normal file
File diff suppressed because it is too large
Load diff
|
@ -24,6 +24,8 @@ public class Config {
|
||||||
public static final boolean SMSCOMMUNICATORENABLED = !BuildConfig.NSCLIENTOLNY && !BuildConfig.G5UPLOADER;
|
public static final boolean SMSCOMMUNICATORENABLED = !BuildConfig.NSCLIENTOLNY && !BuildConfig.G5UPLOADER;
|
||||||
|
|
||||||
|
|
||||||
|
public static final boolean displayDeviationSlope = true;
|
||||||
|
|
||||||
public static final boolean detailedLog = true;
|
public static final boolean detailedLog = true;
|
||||||
public static final boolean logFunctionCalls = true;
|
public static final boolean logFunctionCalls = true;
|
||||||
public static final boolean logIncommingData = true;
|
public static final boolean logIncommingData = true;
|
||||||
|
|
|
@ -44,6 +44,7 @@ import info.nightscout.androidaps.plugins.NSClientInternal.NSClientInternalPlugi
|
||||||
import info.nightscout.androidaps.plugins.NSClientInternal.receivers.AckAlarmReceiver;
|
import info.nightscout.androidaps.plugins.NSClientInternal.receivers.AckAlarmReceiver;
|
||||||
import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin;
|
import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin;
|
||||||
import info.nightscout.androidaps.plugins.OpenAPSMA.OpenAPSMAPlugin;
|
import info.nightscout.androidaps.plugins.OpenAPSMA.OpenAPSMAPlugin;
|
||||||
|
import info.nightscout.androidaps.plugins.OpenAPSSMB.OpenAPSSMBPlugin;
|
||||||
import info.nightscout.androidaps.plugins.Overview.OverviewPlugin;
|
import info.nightscout.androidaps.plugins.Overview.OverviewPlugin;
|
||||||
import info.nightscout.androidaps.plugins.Persistentnotification.PersistentNotificationPlugin;
|
import info.nightscout.androidaps.plugins.Persistentnotification.PersistentNotificationPlugin;
|
||||||
import info.nightscout.androidaps.plugins.ProfileCircadianPercentage.CircadianPercentageProfileFragment;
|
import info.nightscout.androidaps.plugins.ProfileCircadianPercentage.CircadianPercentageProfileFragment;
|
||||||
|
@ -136,6 +137,7 @@ public class MainApp extends Application {
|
||||||
if (Config.APS) pluginsList.add(LoopPlugin.getPlugin());
|
if (Config.APS) pluginsList.add(LoopPlugin.getPlugin());
|
||||||
if (Config.APS) pluginsList.add(OpenAPSMAPlugin.getPlugin());
|
if (Config.APS) pluginsList.add(OpenAPSMAPlugin.getPlugin());
|
||||||
if (Config.APS) pluginsList.add(OpenAPSAMAPlugin.getPlugin());
|
if (Config.APS) pluginsList.add(OpenAPSAMAPlugin.getPlugin());
|
||||||
|
if (Config.APS) pluginsList.add(OpenAPSSMBPlugin.getPlugin());
|
||||||
pluginsList.add(NSProfilePlugin.getPlugin());
|
pluginsList.add(NSProfilePlugin.getPlugin());
|
||||||
if (Config.OTHERPROFILES) pluginsList.add(SimpleProfilePlugin.getPlugin());
|
if (Config.OTHERPROFILES) pluginsList.add(SimpleProfilePlugin.getPlugin());
|
||||||
if (Config.OTHERPROFILES) pluginsList.add(LocalProfilePlugin.getPlugin());
|
if (Config.OTHERPROFILES) pluginsList.add(LocalProfilePlugin.getPlugin());
|
||||||
|
|
|
@ -16,6 +16,7 @@ import android.text.TextUtils;
|
||||||
import info.nightscout.androidaps.events.EventPreferenceChange;
|
import info.nightscout.androidaps.events.EventPreferenceChange;
|
||||||
import info.nightscout.androidaps.events.EventRefreshGui;
|
import info.nightscout.androidaps.events.EventRefreshGui;
|
||||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||||
|
import info.nightscout.androidaps.plugins.OpenAPSSMB.OpenAPSSMBPlugin;
|
||||||
import info.nightscout.androidaps.plugins.Careportal.CareportalPlugin;
|
import info.nightscout.androidaps.plugins.Careportal.CareportalPlugin;
|
||||||
import info.nightscout.androidaps.plugins.ConstraintsSafety.SafetyPlugin;
|
import info.nightscout.androidaps.plugins.ConstraintsSafety.SafetyPlugin;
|
||||||
import info.nightscout.androidaps.plugins.Insulin.InsulinOrefFreePeakPlugin;
|
import info.nightscout.androidaps.plugins.Insulin.InsulinOrefFreePeakPlugin;
|
||||||
|
@ -145,6 +146,7 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
|
||||||
addPreferencesFromResourceIfEnabled(LoopPlugin.getPlugin(), PluginBase.LOOP);
|
addPreferencesFromResourceIfEnabled(LoopPlugin.getPlugin(), PluginBase.LOOP);
|
||||||
addPreferencesFromResourceIfEnabled(OpenAPSMAPlugin.getPlugin(), PluginBase.APS);
|
addPreferencesFromResourceIfEnabled(OpenAPSMAPlugin.getPlugin(), PluginBase.APS);
|
||||||
addPreferencesFromResourceIfEnabled(OpenAPSAMAPlugin.getPlugin(), PluginBase.APS);
|
addPreferencesFromResourceIfEnabled(OpenAPSAMAPlugin.getPlugin(), PluginBase.APS);
|
||||||
|
addPreferencesFromResourceIfEnabled(OpenAPSSMBPlugin.getPlugin(), PluginBase.APS);
|
||||||
}
|
}
|
||||||
|
|
||||||
addPreferencesFromResourceIfEnabled(SensitivityAAPSPlugin.getPlugin(), PluginBase.SENSITIVITY);
|
addPreferencesFromResourceIfEnabled(SensitivityAAPSPlugin.getPlugin(), PluginBase.SENSITIVITY);
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
package info.nightscout.androidaps.Services;
|
package info.nightscout.androidaps.Services;
|
||||||
|
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.res.AssetFileDescriptor;
|
import android.content.res.AssetFileDescriptor;
|
||||||
|
import android.media.AudioManager;
|
||||||
import android.media.MediaPlayer;
|
import android.media.MediaPlayer;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
|
|
||||||
|
@ -53,7 +55,10 @@ public class AlarmSoundService extends Service {
|
||||||
log.error("Unhandled exception", e);
|
log.error("Unhandled exception", e);
|
||||||
}
|
}
|
||||||
player.setLooping(true); // Set looping
|
player.setLooping(true); // Set looping
|
||||||
player.setVolume(100, 100);
|
AudioManager manager = (AudioManager)this.getSystemService(Context.AUDIO_SERVICE);
|
||||||
|
if (manager == null || !manager.isMusicActive()) {
|
||||||
|
player.setVolume(100, 100);
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
player.prepare();
|
player.prepare();
|
||||||
|
|
|
@ -29,6 +29,7 @@ public class DetailedBolusInfo {
|
||||||
public Context context = null; // context for progress dialog
|
public Context context = null; // context for progress dialog
|
||||||
public long pumpId = 0; // id of record if comming from pump history (not a newly created treatment)
|
public long pumpId = 0; // id of record if comming from pump history (not a newly created treatment)
|
||||||
public boolean isSMB = false; // is a Super-MicroBolus
|
public boolean isSMB = false; // is a Super-MicroBolus
|
||||||
|
public long deliverAt = 0; // SMB should be delivered within 1 min from this time
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
|
@ -37,6 +38,7 @@ public class DetailedBolusInfo {
|
||||||
" carbs: " + carbs +
|
" carbs: " + carbs +
|
||||||
" isValid: " + isValid +
|
" isValid: " + isValid +
|
||||||
" carbTime: " + carbTime +
|
" carbTime: " + carbTime +
|
||||||
" isSMB: " + isSMB;
|
" isSMB: " + isSMB +
|
||||||
|
" deliverAt: " + new Date(deliverAt).toLocaleString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ public class GlucoseStatus {
|
||||||
public double avgdelta = 0d;
|
public double avgdelta = 0d;
|
||||||
public double short_avgdelta = 0d;
|
public double short_avgdelta = 0d;
|
||||||
public double long_avgdelta = 0d;
|
public double long_avgdelta = 0d;
|
||||||
|
public long date = 0L;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -133,6 +134,7 @@ public class GlucoseStatus {
|
||||||
|
|
||||||
GlucoseStatus status = new GlucoseStatus();
|
GlucoseStatus status = new GlucoseStatus();
|
||||||
status.glucose = now.value;
|
status.glucose = now.value;
|
||||||
|
status.date = now_date;
|
||||||
|
|
||||||
status.short_avgdelta = average(short_deltas);
|
status.short_avgdelta = average(short_deltas);
|
||||||
|
|
||||||
|
|
|
@ -21,8 +21,11 @@ public class IobTotal {
|
||||||
public double hightempinsulin;
|
public double hightempinsulin;
|
||||||
|
|
||||||
// oref1
|
// oref1
|
||||||
public double microBolusInsulin;
|
public long lastBolusTime;
|
||||||
public double microBolusIOB;
|
public long lastTempDate;
|
||||||
|
public int lastTempDuration;
|
||||||
|
public double lastTempRate;
|
||||||
|
public IobTotal iobWithZeroTemp;
|
||||||
|
|
||||||
public double netInsulin = 0d; // for calculations from temp basals only
|
public double netInsulin = 0d; // for calculations from temp basals only
|
||||||
public double netRatio = 0d; // net ratio at start of temp basal
|
public double netRatio = 0d; // net ratio at start of temp basal
|
||||||
|
@ -31,6 +34,23 @@ public class IobTotal {
|
||||||
|
|
||||||
long time;
|
long time;
|
||||||
|
|
||||||
|
|
||||||
|
public IobTotal clone() {
|
||||||
|
IobTotal copy = new IobTotal(time);
|
||||||
|
copy.iob = iob;
|
||||||
|
copy.activity = activity;
|
||||||
|
copy.bolussnooze = bolussnooze;
|
||||||
|
copy.basaliob = basaliob;
|
||||||
|
copy.netbasalinsulin = netbasalinsulin;
|
||||||
|
copy.hightempinsulin = hightempinsulin;
|
||||||
|
copy.lastBolusTime = lastBolusTime;
|
||||||
|
copy.lastTempDate = lastTempDate;
|
||||||
|
copy.lastTempDuration = lastTempDuration;
|
||||||
|
copy.lastTempRate = lastTempRate;
|
||||||
|
copy.iobWithZeroTemp = iobWithZeroTemp;
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
public IobTotal(long time) {
|
public IobTotal(long time) {
|
||||||
this.iob = 0d;
|
this.iob = 0d;
|
||||||
this.activity = 0d;
|
this.activity = 0d;
|
||||||
|
@ -38,8 +58,7 @@ public class IobTotal {
|
||||||
this.basaliob = 0d;
|
this.basaliob = 0d;
|
||||||
this.netbasalinsulin = 0d;
|
this.netbasalinsulin = 0d;
|
||||||
this.hightempinsulin = 0d;
|
this.hightempinsulin = 0d;
|
||||||
this.microBolusInsulin = 0d;
|
this.lastBolusTime = 0;
|
||||||
this.microBolusIOB = 0d;
|
|
||||||
this.time = time;
|
this.time = time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,8 +71,6 @@ public class IobTotal {
|
||||||
hightempinsulin += other.hightempinsulin;
|
hightempinsulin += other.hightempinsulin;
|
||||||
netInsulin += other.netInsulin;
|
netInsulin += other.netInsulin;
|
||||||
extendedBolusInsulin += other.extendedBolusInsulin;
|
extendedBolusInsulin += other.extendedBolusInsulin;
|
||||||
microBolusInsulin += other.microBolusInsulin;
|
|
||||||
microBolusIOB += other.microBolusIOB;
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,11 +79,14 @@ public class IobTotal {
|
||||||
result.iob = bolusIOB.iob + basalIob.basaliob;
|
result.iob = bolusIOB.iob + basalIob.basaliob;
|
||||||
result.activity = bolusIOB.activity + basalIob.activity;
|
result.activity = bolusIOB.activity + basalIob.activity;
|
||||||
result.bolussnooze = bolusIOB.bolussnooze;
|
result.bolussnooze = bolusIOB.bolussnooze;
|
||||||
result.basaliob = basalIob.basaliob;
|
result.basaliob = bolusIOB.basaliob + basalIob.basaliob;
|
||||||
result.netbasalinsulin = basalIob.netbasalinsulin;
|
result.netbasalinsulin = bolusIOB.netbasalinsulin + basalIob.netbasalinsulin;
|
||||||
result.hightempinsulin = basalIob.hightempinsulin;
|
result.hightempinsulin = basalIob.hightempinsulin + bolusIOB.hightempinsulin;
|
||||||
result.microBolusInsulin = bolusIOB.microBolusInsulin + basalIob.microBolusInsulin;
|
result.lastBolusTime = bolusIOB.lastBolusTime;
|
||||||
result.microBolusIOB = bolusIOB.microBolusIOB + basalIob.microBolusIOB;
|
result.lastTempDate = basalIob.lastTempDate;
|
||||||
|
result.lastTempRate = basalIob.lastTempRate;
|
||||||
|
result.lastTempDuration = basalIob.lastTempDuration;
|
||||||
|
result.iobWithZeroTemp = basalIob.iobWithZeroTemp;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,8 +97,6 @@ public class IobTotal {
|
||||||
this.basaliob = Round.roundTo(this.basaliob, 0.001);
|
this.basaliob = Round.roundTo(this.basaliob, 0.001);
|
||||||
this.netbasalinsulin = Round.roundTo(this.netbasalinsulin, 0.001);
|
this.netbasalinsulin = Round.roundTo(this.netbasalinsulin, 0.001);
|
||||||
this.hightempinsulin = Round.roundTo(this.hightempinsulin, 0.001);
|
this.hightempinsulin = Round.roundTo(this.hightempinsulin, 0.001);
|
||||||
this.microBolusInsulin = Round.roundTo(this.microBolusInsulin, 0.001);
|
|
||||||
this.microBolusIOB = Round.roundTo(this.microBolusIOB, 0.001);
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,7 +120,24 @@ public class IobTotal {
|
||||||
json.put("basaliob", basaliob);
|
json.put("basaliob", basaliob);
|
||||||
json.put("bolussnooze", bolussnooze);
|
json.put("bolussnooze", bolussnooze);
|
||||||
json.put("activity", activity);
|
json.put("activity", activity);
|
||||||
|
json.put("lastBolusTime", lastBolusTime);
|
||||||
json.put("time", DateUtil.toISOString(new Date(time)));
|
json.put("time", DateUtil.toISOString(new Date(time)));
|
||||||
|
/*
|
||||||
|
|
||||||
|
This is requested by SMB determine_basal but by based on Scott's info
|
||||||
|
it's MDT specific safety check only
|
||||||
|
It's causing rounding issues in determine_basal
|
||||||
|
|
||||||
|
JSONObject lastTemp = new JSONObject();
|
||||||
|
lastTemp.put("date", lastTempDate);
|
||||||
|
lastTemp.put("rate", lastTempRate);
|
||||||
|
lastTemp.put("duration", lastTempDuration);
|
||||||
|
json.put("lastTemp", lastTemp);
|
||||||
|
*/
|
||||||
|
if (iobWithZeroTemp != null) {
|
||||||
|
JSONObject iwzt = iobWithZeroTemp.determineBasalJson();
|
||||||
|
json.put("iobWithZeroTemp", iwzt);
|
||||||
|
}
|
||||||
} catch (JSONException e) {
|
} catch (JSONException e) {
|
||||||
log.error("Unhandled exception", e);
|
log.error("Unhandled exception", e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,4 +7,8 @@ public class MealData {
|
||||||
public double boluses = 0d;
|
public double boluses = 0d;
|
||||||
public double carbs = 0d;
|
public double carbs = 0d;
|
||||||
public double mealCOB = 0.0d;
|
public double mealCOB = 0.0d;
|
||||||
|
public double slopeFromMaxDeviation = 0;
|
||||||
|
public double slopeFromMinDeviation = 999;
|
||||||
|
public long lastBolusTime;
|
||||||
|
public long lastCarbTime = 0L;
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,6 +57,10 @@ public class PumpEnactResult extends Object {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PumpEnactResult percent(Integer percent) {
|
||||||
|
this.percent = percent;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
public PumpEnactResult isPercent(boolean isPercent) {
|
public PumpEnactResult isPercent(boolean isPercent) {
|
||||||
this.isPercent = isPercent;
|
this.isPercent = isPercent;
|
||||||
return this;
|
return this;
|
||||||
|
@ -111,7 +115,7 @@ public class PumpEnactResult extends Object {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Spanned toSpanned() {
|
public Spanned toSpanned() {
|
||||||
String ret = MainApp.sResources.getString(R.string.success) + ": " + success;
|
String ret = "<b>" + MainApp.sResources.getString(R.string.success) + "</b>: " + success;
|
||||||
if (queued) {
|
if (queued) {
|
||||||
ret = MainApp.sResources.getString(R.string.waitingforpumpresult);
|
ret = MainApp.sResources.getString(R.string.waitingforpumpresult);
|
||||||
} else if (enacted) {
|
} else if (enacted) {
|
||||||
|
@ -119,17 +123,20 @@ public class PumpEnactResult extends Object {
|
||||||
ret += "<br><b>" + MainApp.sResources.getString(R.string.enacted) + "</b>: " + enacted;
|
ret += "<br><b>" + MainApp.sResources.getString(R.string.enacted) + "</b>: " + enacted;
|
||||||
ret += "<br><b>" + MainApp.sResources.getString(R.string.comment) + "</b>: " + comment +
|
ret += "<br><b>" + MainApp.sResources.getString(R.string.comment) + "</b>: " + comment +
|
||||||
"<br>" + MainApp.sResources.getString(R.string.canceltemp);
|
"<br>" + MainApp.sResources.getString(R.string.canceltemp);
|
||||||
} else if (isPercent) {
|
} else if (isPercent && percent != -1) {
|
||||||
ret += "<br><b>" + MainApp.sResources.getString(R.string.enacted) + "</b>: " + enacted;
|
ret += "<br><b>" + MainApp.sResources.getString(R.string.enacted) + "</b>: " + enacted;
|
||||||
ret += "<br><b>" + MainApp.sResources.getString(R.string.comment) + "</b>: " + comment;
|
ret += "<br><b>" + MainApp.sResources.getString(R.string.comment) + "</b>: " + comment;
|
||||||
ret += "<br><b>" + MainApp.sResources.getString(R.string.duration) + "</b>: " + duration + " min";
|
ret += "<br><b>" + MainApp.sResources.getString(R.string.duration) + "</b>: " + duration + " min";
|
||||||
ret += "<br><b>" + MainApp.sResources.getString(R.string.percent) + "</b>: " + percent + "%";
|
ret += "<br><b>" + MainApp.sResources.getString(R.string.percent) + "</b>: " + percent + "%";
|
||||||
} else {
|
} else if (absolute != -1) {
|
||||||
ret += "<br><b>" + MainApp.sResources.getString(R.string.enacted) + "</b>: " + enacted;
|
ret += "<br><b>" + MainApp.sResources.getString(R.string.enacted) + "</b>: " + enacted;
|
||||||
ret += "<br><b>" + MainApp.sResources.getString(R.string.comment) + "</b>: " + comment;
|
ret += "<br><b>" + MainApp.sResources.getString(R.string.comment) + "</b>: " + comment;
|
||||||
ret += "<br><b>" + MainApp.sResources.getString(R.string.duration) + "</b>: " + duration + " min";
|
ret += "<br><b>" + MainApp.sResources.getString(R.string.duration) + "</b>: " + duration + " min";
|
||||||
ret += "<br><b>" + MainApp.sResources.getString(R.string.absolute) + "</b>: " + DecimalFormatter.to2Decimal(absolute) + " U/h";
|
ret += "<br><b>" + MainApp.sResources.getString(R.string.absolute) + "</b>: " + DecimalFormatter.to2Decimal(absolute) + " U/h";
|
||||||
}
|
}
|
||||||
|
if (bolusDelivered > 0) {
|
||||||
|
ret += "<br><b>" + MainApp.sResources.getString(R.string.bolus) + "</b>: " + DecimalFormatter.to2Decimal(bolusDelivered) + " U";
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ret += "<br><b>" + MainApp.sResources.getString(R.string.comment) + "</b>: " + comment;
|
ret += "<br><b>" + MainApp.sResources.getString(R.string.comment) + "</b>: " + comment;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,6 @@ import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSgv;
|
||||||
import info.nightscout.androidaps.plugins.Overview.OverviewPlugin;
|
import info.nightscout.androidaps.plugins.Overview.OverviewPlugin;
|
||||||
import info.nightscout.androidaps.plugins.Overview.graphExtensions.DataPointWithLabelInterface;
|
import info.nightscout.androidaps.plugins.Overview.graphExtensions.DataPointWithLabelInterface;
|
||||||
import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLabelGraphSeries;
|
import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLabelGraphSeries;
|
||||||
import info.nightscout.utils.DateUtil;
|
|
||||||
import info.nightscout.utils.DecimalFormatter;
|
import info.nightscout.utils.DecimalFormatter;
|
||||||
import info.nightscout.utils.SP;
|
import info.nightscout.utils.SP;
|
||||||
|
|
||||||
|
@ -43,7 +42,11 @@ public class BgReading implements DataPointWithLabelInterface {
|
||||||
@DatabaseField
|
@DatabaseField
|
||||||
public String _id = null; // NS _id
|
public String _id = null; // NS _id
|
||||||
|
|
||||||
public boolean isPrediction = false; // true when drawing predictions as bg points
|
public boolean isCOBPrediction = false; // true when drawing predictions as bg points (COB)
|
||||||
|
public boolean isaCOBPrediction = false; // true when drawing predictions as bg points (aCOB)
|
||||||
|
public boolean isIOBPrediction = false; // true when drawing predictions as bg points (IOB)
|
||||||
|
public boolean isUAMPrediction = false; // true when drawing predictions as bg points (UAM)
|
||||||
|
public boolean isZTPrediction = false; // true when drawing predictions as bg points (ZT)
|
||||||
|
|
||||||
public BgReading() {
|
public BgReading() {
|
||||||
}
|
}
|
||||||
|
@ -184,7 +187,10 @@ public class BgReading implements DataPointWithLabelInterface {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PointsWithLabelGraphSeries.Shape getShape() {
|
public PointsWithLabelGraphSeries.Shape getShape() {
|
||||||
return PointsWithLabelGraphSeries.Shape.POINT;
|
if (isPrediction())
|
||||||
|
return PointsWithLabelGraphSeries.Shape.PREDICTION;
|
||||||
|
else
|
||||||
|
return PointsWithLabelGraphSeries.Shape.BG;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -205,7 +211,7 @@ public class BgReading implements DataPointWithLabelInterface {
|
||||||
highLine = Profile.fromMgdlToUnits(OverviewPlugin.bgTargetHigh, units);
|
highLine = Profile.fromMgdlToUnits(OverviewPlugin.bgTargetHigh, units);
|
||||||
}
|
}
|
||||||
int color = MainApp.sResources.getColor(R.color.inrange);
|
int color = MainApp.sResources.getColor(R.color.inrange);
|
||||||
if (isPrediction)
|
if (isPrediction())
|
||||||
color = MainApp.sResources.getColor(R.color.prediction);
|
color = MainApp.sResources.getColor(R.color.prediction);
|
||||||
else if (valueToUnits(units) < lowLine)
|
else if (valueToUnits(units) < lowLine)
|
||||||
color = MainApp.sResources.getColor(R.color.low);
|
color = MainApp.sResources.getColor(R.color.low);
|
||||||
|
@ -214,4 +220,23 @@ public class BgReading implements DataPointWithLabelInterface {
|
||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSecondColor() {
|
||||||
|
if (isIOBPrediction)
|
||||||
|
return MainApp.sResources.getColor(R.color.iob);
|
||||||
|
if (isCOBPrediction)
|
||||||
|
return MainApp.sResources.getColor(R.color.cob);
|
||||||
|
if (isaCOBPrediction)
|
||||||
|
return 0x80FFFFFF & MainApp.sResources.getColor(R.color.cob);
|
||||||
|
if (isUAMPrediction)
|
||||||
|
return MainApp.sResources.getColor(R.color.uam);
|
||||||
|
if (isZTPrediction)
|
||||||
|
return MainApp.sResources.getColor(R.color.zt);
|
||||||
|
return R.color.mdtp_white;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isPrediction() {
|
||||||
|
return isaCOBPrediction || isCOBPrediction || isIOBPrediction || isUAMPrediction || isZTPrediction;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -253,4 +253,9 @@ public class CareportalEvent implements DataPointWithLabelInterface {
|
||||||
return Color.GRAY;
|
return Color.GRAY;
|
||||||
return Color.GRAY;
|
return Color.GRAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSecondColor() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -285,4 +285,9 @@ public class ExtendedBolus implements Interval, DataPointWithLabelInterface {
|
||||||
public int getColor() {
|
public int getColor() {
|
||||||
return Color.CYAN;
|
return Color.CYAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSecondColor() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -238,6 +238,11 @@ public class ProfileSwitch implements Interval, DataPointWithLabelInterface {
|
||||||
return Color.CYAN;
|
return Color.CYAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSecondColor() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "ProfileSwitch{" +
|
return "ProfileSwitch{" +
|
||||||
"date=" + date +
|
"date=" + date +
|
||||||
|
|
|
@ -12,6 +12,7 @@ import java.util.Objects;
|
||||||
|
|
||||||
import info.nightscout.androidaps.Constants;
|
import info.nightscout.androidaps.Constants;
|
||||||
import info.nightscout.androidaps.MainApp;
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
import info.nightscout.androidaps.R;
|
||||||
import info.nightscout.androidaps.data.Iob;
|
import info.nightscout.androidaps.data.Iob;
|
||||||
import info.nightscout.androidaps.interfaces.InsulinInterface;
|
import info.nightscout.androidaps.interfaces.InsulinInterface;
|
||||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||||
|
@ -139,7 +140,10 @@ public class Treatment implements DataPointWithLabelInterface {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PointsWithLabelGraphSeries.Shape getShape() {
|
public PointsWithLabelGraphSeries.Shape getShape() {
|
||||||
return PointsWithLabelGraphSeries.Shape.BOLUS;
|
if (isSMB)
|
||||||
|
return PointsWithLabelGraphSeries.Shape.SMB;
|
||||||
|
else
|
||||||
|
return PointsWithLabelGraphSeries.Shape.BOLUS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -149,12 +153,19 @@ public class Treatment implements DataPointWithLabelInterface {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getColor() {
|
public int getColor() {
|
||||||
if (isValid)
|
if (isSMB)
|
||||||
|
return MainApp.sResources.getColor(R.color.tempbasal);
|
||||||
|
else if (isValid)
|
||||||
return Color.CYAN;
|
return Color.CYAN;
|
||||||
else
|
else
|
||||||
return MainApp.instance().getResources().getColor(android.R.color.holo_red_light);
|
return MainApp.instance().getResources().getColor(android.R.color.holo_red_light);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSecondColor() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setY(double y) {
|
public void setY(double y) {
|
||||||
yValue = y;
|
yValue = y;
|
||||||
|
|
|
@ -4,4 +4,5 @@ package info.nightscout.androidaps.interfaces;
|
||||||
* Created by mike on 20.06.2016.
|
* Created by mike on 20.06.2016.
|
||||||
*/
|
*/
|
||||||
public interface BgSourceInterface {
|
public interface BgSourceInterface {
|
||||||
|
boolean advancedFilteringSupported();
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,16 +10,16 @@ import info.nightscout.androidaps.db.Treatment;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public interface InsulinInterface {
|
public interface InsulinInterface {
|
||||||
final int FASTACTINGINSULIN = 0;
|
int FASTACTINGINSULIN = 0;
|
||||||
final int FASTACTINGINSULINPROLONGED = 1;
|
int FASTACTINGINSULINPROLONGED = 1;
|
||||||
final int OREF_RAPID_ACTING = 2;
|
int OREF_RAPID_ACTING = 2;
|
||||||
final int OREF_ULTRA_RAPID_ACTING = 3;
|
int OREF_ULTRA_RAPID_ACTING = 3;
|
||||||
final int OREF_FREE_PEAK = 4;
|
int OREF_FREE_PEAK = 4;
|
||||||
|
|
||||||
|
|
||||||
int getId();
|
int getId();
|
||||||
String getFriendlyName();
|
String getFriendlyName();
|
||||||
String getComment();
|
String getComment();
|
||||||
double getDia();
|
double getDia();
|
||||||
public Iob iobCalcForTreatment(Treatment treatment, long time, double dia);
|
Iob iobCalcForTreatment(Treatment treatment, long time, double dia);
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@ public interface TreatmentsInterface {
|
||||||
|
|
||||||
List<Treatment> getTreatmentsFromHistory();
|
List<Treatment> getTreatmentsFromHistory();
|
||||||
List<Treatment> getTreatments5MinBackFromHistory(long time);
|
List<Treatment> getTreatments5MinBackFromHistory(long time);
|
||||||
|
long getLastBolusTime();
|
||||||
|
|
||||||
// real basals (not faked by extended bolus)
|
// real basals (not faked by extended bolus)
|
||||||
boolean isInHistoryRealTempBasalInProgress();
|
boolean isInHistoryRealTempBasalInProgress();
|
||||||
|
|
|
@ -23,8 +23,10 @@ import info.nightscout.androidaps.data.MealData;
|
||||||
import info.nightscout.androidaps.data.Profile;
|
import info.nightscout.androidaps.data.Profile;
|
||||||
import info.nightscout.androidaps.data.ProfileIntervals;
|
import info.nightscout.androidaps.data.ProfileIntervals;
|
||||||
import info.nightscout.androidaps.data.PumpEnactResult;
|
import info.nightscout.androidaps.data.PumpEnactResult;
|
||||||
|
import info.nightscout.androidaps.db.CareportalEvent;
|
||||||
import info.nightscout.androidaps.db.ExtendedBolus;
|
import info.nightscout.androidaps.db.ExtendedBolus;
|
||||||
import info.nightscout.androidaps.db.ProfileSwitch;
|
import info.nightscout.androidaps.db.ProfileSwitch;
|
||||||
|
import info.nightscout.androidaps.db.Source;
|
||||||
import info.nightscout.androidaps.db.TempTarget;
|
import info.nightscout.androidaps.db.TempTarget;
|
||||||
import info.nightscout.androidaps.db.TemporaryBasal;
|
import info.nightscout.androidaps.db.TemporaryBasal;
|
||||||
import info.nightscout.androidaps.db.Treatment;
|
import info.nightscout.androidaps.db.Treatment;
|
||||||
|
@ -353,33 +355,19 @@ public class ConfigBuilderPlugin implements PluginBase, ConstraintsInterface, Tr
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Ex Pump interface
|
|
||||||
*
|
|
||||||
* Config builder return itself as a pump and check constraints before it passes command to pump driver
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* expect absolute request and allow both absolute and percent response based on pump capabilities
|
* expect absolute request and allow both absolute and percent response based on pump capabilities
|
||||||
*
|
|
||||||
* @param request
|
|
||||||
* @return
|
|
||||||
* true if command is going to be executed
|
|
||||||
* false if error
|
|
||||||
*/
|
*/
|
||||||
|
public void applyAPSRequest(APSResult request, Callback callback) {
|
||||||
public boolean applyAPSRequest(APSResult request, Callback callback) {
|
|
||||||
PumpInterface pump = getActivePump();
|
PumpInterface pump = getActivePump();
|
||||||
request.rate = applyBasalConstraints(request.rate);
|
request.rate = applyBasalConstraints(request.rate);
|
||||||
PumpEnactResult result;
|
|
||||||
|
|
||||||
if (!pump.isInitialized()) {
|
if (!pump.isInitialized()) {
|
||||||
log.debug("applyAPSRequest: " + MainApp.sResources.getString(R.string.pumpNotInitialized));
|
log.debug("applyAPSRequest: " + MainApp.sResources.getString(R.string.pumpNotInitialized));
|
||||||
if (callback != null) {
|
if (callback != null) {
|
||||||
callback.result(new PumpEnactResult().comment(MainApp.sResources.getString(R.string.pumpNotInitialized)).enacted(false).success(false)).run();
|
callback.result(new PumpEnactResult().comment(MainApp.sResources.getString(R.string.pumpNotInitialized)).enacted(false).success(false)).run();
|
||||||
}
|
}
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pump.isSuspended()) {
|
if (pump.isSuspended()) {
|
||||||
|
@ -387,43 +375,56 @@ public class ConfigBuilderPlugin implements PluginBase, ConstraintsInterface, Tr
|
||||||
if (callback != null) {
|
if (callback != null) {
|
||||||
callback.result(new PumpEnactResult().comment(MainApp.sResources.getString(R.string.pumpsuspended)).enacted(false).success(false)).run();
|
callback.result(new PumpEnactResult().comment(MainApp.sResources.getString(R.string.pumpsuspended)).enacted(false).success(false)).run();
|
||||||
}
|
}
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Config.logCongigBuilderActions)
|
if (Config.logCongigBuilderActions)
|
||||||
log.debug("applyAPSRequest: " + request.toString());
|
log.debug("applyAPSRequest: " + request.toString());
|
||||||
if ((request.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)
|
if (Config.logCongigBuilderActions)
|
||||||
log.debug("applyAPSRequest: cancelTempBasal()");
|
log.debug("applyAPSRequest: Temp basal set correctly");
|
||||||
getCommandQueue().cancelTempBasal(false, callback);
|
if (callback != null) {
|
||||||
return true;
|
callback.result(new PumpEnactResult().absolute(getTempBasalAbsoluteRateHistory()).duration(getTempBasalFromHistory(System.currentTimeMillis()).getPlannedRemainingMinutes()).enacted(false).success(true).comment("Temp basal set correctly")).run();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (Config.logCongigBuilderActions)
|
if (Config.logCongigBuilderActions)
|
||||||
log.debug("applyAPSRequest: Basal set correctly");
|
log.debug("applyAPSRequest: setTempBasalAbsolute()");
|
||||||
if (callback != null) {
|
getCommandQueue().tempBasalAbsolute(request.rate, request.duration, false, callback);
|
||||||
callback.result(new PumpEnactResult().absolute(request.rate).duration(0).enacted(false).success(true).comment("Basal set correctly")).run();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
} else if (isTempBasalInProgress()
|
}
|
||||||
&& getTempBasalRemainingMinutesFromHistory() > 5
|
|
||||||
&& Math.abs(request.rate - getTempBasalAbsoluteRateHistory()) < pump.getPumpDescription().basalStep) {
|
if (request.bolusRequested) {
|
||||||
if (Config.logCongigBuilderActions)
|
long lastBolusTime = getLastBolusTime();
|
||||||
log.debug("applyAPSRequest: Temp basal set correctly");
|
if (lastBolusTime != 0 && lastBolusTime + 3 * 60 * 1000 > System.currentTimeMillis()) {
|
||||||
if (callback != null) {
|
log.debug("SMB requsted but still in 3 min interval");
|
||||||
callback.result(new PumpEnactResult().absolute(getTempBasalAbsoluteRateHistory()).duration(getTempBasalFromHistory(System.currentTimeMillis()).getPlannedRemainingMinutes()).enacted(false).success(true).comment("Temp basal set correctly")).run();
|
} 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
|
* Constraints interface
|
||||||
**/
|
**/
|
||||||
|
@ -598,6 +599,11 @@ public class ConfigBuilderPlugin implements PluginBase, ConstraintsInterface, Tr
|
||||||
return activeTreatments.getTreatments5MinBackFromHistory(time);
|
return activeTreatments.getTreatments5MinBackFromHistory(time);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getLastBolusTime() {
|
||||||
|
return activeTreatments.getLastBolusTime();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isInHistoryRealTempBasalInProgress() {
|
public boolean isInHistoryRealTempBasalInProgress() {
|
||||||
return activeTreatments.isInHistoryRealTempBasalInProgress();
|
return activeTreatments.isInHistoryRealTempBasalInProgress();
|
||||||
|
|
|
@ -57,11 +57,15 @@ public class AutosensData {
|
||||||
public double cob = 0;
|
public double cob = 0;
|
||||||
public double bgi = 0d;
|
public double bgi = 0d;
|
||||||
public double delta = 0d;
|
public double delta = 0d;
|
||||||
|
public double avgDelta = 0d;
|
||||||
|
public double avgDeviation = 0d;
|
||||||
|
|
||||||
public double autosensRatio = 1d;
|
public double autosensRatio = 1d;
|
||||||
|
public double slopeFromMaxDeviation = 0;
|
||||||
|
public double slopeFromMinDeviation = 999;
|
||||||
|
|
||||||
public String log(long time) {
|
public String log(long time) {
|
||||||
return "AutosensData: " + new Date(time).toLocaleString() + " " + pastSensitivity + " Delta=" + delta + " Bgi=" + bgi + " Deviation=" + deviation + " Absorbed=" + absorbed + " CarbsFromBolus=" + carbsFromBolus + " COB=" + cob + " autosensRatio=" + autosensRatio;
|
return "AutosensData: " + new Date(time).toLocaleString() + " " + pastSensitivity + " Delta=" + delta + " avgDelta=" + avgDelta + " Bgi=" + bgi + " Deviation=" + deviation + " avgDeviation=" + avgDeviation + " Absorbed=" + absorbed + " CarbsFromBolus=" + carbsFromBolus + " COB=" + cob + " autosensRatio=" + autosensRatio + " slopeFromMaxDeviation=" + slopeFromMaxDeviation + " slopeFromMinDeviation =" + slopeFromMinDeviation ;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int minOld() {
|
public int minOld() {
|
||||||
|
|
|
@ -22,6 +22,7 @@ import info.nightscout.androidaps.data.IobTotal;
|
||||||
import info.nightscout.androidaps.data.Profile;
|
import info.nightscout.androidaps.data.Profile;
|
||||||
import info.nightscout.androidaps.db.BgReading;
|
import info.nightscout.androidaps.db.BgReading;
|
||||||
import info.nightscout.androidaps.db.TemporaryBasal;
|
import info.nightscout.androidaps.db.TemporaryBasal;
|
||||||
|
import info.nightscout.androidaps.events.Event;
|
||||||
import info.nightscout.androidaps.events.EventAppInitialized;
|
import info.nightscout.androidaps.events.EventAppInitialized;
|
||||||
import info.nightscout.androidaps.events.EventConfigBuilderChange;
|
import info.nightscout.androidaps.events.EventConfigBuilderChange;
|
||||||
import info.nightscout.androidaps.events.EventNewBG;
|
import info.nightscout.androidaps.events.EventNewBG;
|
||||||
|
@ -30,6 +31,7 @@ import info.nightscout.androidaps.events.EventPreferenceChange;
|
||||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||||
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventNewHistoryData;
|
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventNewHistoryData;
|
||||||
|
import info.nightscout.androidaps.plugins.OpenAPSSMB.OpenAPSSMBPlugin;
|
||||||
import info.nightscout.utils.DateUtil;
|
import info.nightscout.utils.DateUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -129,7 +131,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
IobCobCalculatorPlugin() {
|
private IobCobCalculatorPlugin() {
|
||||||
MainApp.bus().register(this);
|
MainApp.bus().register(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,7 +261,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void createBucketedData5min() {
|
private void createBucketedData5min() {
|
||||||
if (bgReadings == null || bgReadings.size() < 3) {
|
if (bgReadings == null || bgReadings.size() < 3) {
|
||||||
bucketed_data = null;
|
bucketed_data = null;
|
||||||
return;
|
return;
|
||||||
|
@ -347,6 +349,21 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
||||||
}
|
}
|
||||||
IobTotal bolusIob = MainApp.getConfigBuilder().getCalculationToTimeTreatments(time).round();
|
IobTotal bolusIob = MainApp.getConfigBuilder().getCalculationToTimeTreatments(time).round();
|
||||||
IobTotal basalIob = MainApp.getConfigBuilder().getCalculationToTimeTempBasals(time).round();
|
IobTotal basalIob = MainApp.getConfigBuilder().getCalculationToTimeTempBasals(time).round();
|
||||||
|
if (OpenAPSSMBPlugin.getPlugin().isEnabled(PluginBase.APS)) {
|
||||||
|
// Add expected zere temp basal for next 240 mins
|
||||||
|
IobTotal basalIobWithZeroTemp = basalIob.clone();
|
||||||
|
TemporaryBasal t = new TemporaryBasal();
|
||||||
|
t.date = now + 60 * 1000L;
|
||||||
|
t.durationInMinutes = 240;
|
||||||
|
t.isAbsolute = true;
|
||||||
|
t.absoluteRate = 0;
|
||||||
|
if (t.date < time) {
|
||||||
|
IobTotal calc = t.iobCalc(time);
|
||||||
|
basalIobWithZeroTemp.plus(calc);
|
||||||
|
}
|
||||||
|
|
||||||
|
basalIob.iobWithZeroTemp = basalIobWithZeroTemp;
|
||||||
|
}
|
||||||
|
|
||||||
IobTotal iobTotal = IobTotal.combine(bolusIob, basalIob).round();
|
IobTotal iobTotal = IobTotal.combine(bolusIob, basalIob).round();
|
||||||
if (time < System.currentTimeMillis()) {
|
if (time < System.currentTimeMillis()) {
|
||||||
|
@ -467,6 +484,23 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static 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 static AutosensResult detectSensitivityWithLock(long fromTime, long toTime) {
|
public static AutosensResult detectSensitivityWithLock(long fromTime, long toTime) {
|
||||||
synchronized (dataLock) {
|
synchronized (dataLock) {
|
||||||
return detectSensitivity(fromTime, toTime);
|
return detectSensitivity(fromTime, toTime);
|
||||||
|
@ -487,13 +521,13 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void onEventAppInitialized(EventAppInitialized ev) {
|
public void onEventAppInitialized(EventAppInitialized ev) {
|
||||||
runCalculation("onEventAppInitialized", true);
|
runCalculation("onEventAppInitialized", true, ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void onEventNewBG(EventNewBG ev) {
|
public void onEventNewBG(EventNewBG ev) {
|
||||||
stopCalculation("onEventNewBG");
|
stopCalculation("onEventNewBG");
|
||||||
runCalculation("onEventNewBG", true);
|
runCalculation("onEventNewBG", true, ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void stopCalculation(String from) {
|
private void stopCalculation(String from) {
|
||||||
|
@ -507,10 +541,10 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void runCalculation(String from, boolean bgDataReload) {
|
private void runCalculation(String from, boolean bgDataReload, Event cause) {
|
||||||
log.debug("Starting calculation thread: " + from);
|
log.debug("Starting calculation thread: " + from);
|
||||||
if (thread == null || thread.getState() == Thread.State.TERMINATED) {
|
if (thread == null || thread.getState() == Thread.State.TERMINATED) {
|
||||||
thread = new IobCobThread(this, from, bgDataReload);
|
thread = new IobCobThread(this, from, bgDataReload, cause);
|
||||||
thread.start();
|
thread.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -532,7 +566,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
||||||
iobTable = new LongSparseArray<>();
|
iobTable = new LongSparseArray<>();
|
||||||
autosensDataTable = new LongSparseArray<>();
|
autosensDataTable = new LongSparseArray<>();
|
||||||
}
|
}
|
||||||
runCalculation("onNewProfile", false);
|
runCalculation("onNewProfile", false, ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
|
@ -547,7 +581,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
||||||
iobTable = new LongSparseArray<>();
|
iobTable = new LongSparseArray<>();
|
||||||
autosensDataTable = new LongSparseArray<>();
|
autosensDataTable = new LongSparseArray<>();
|
||||||
}
|
}
|
||||||
runCalculation("onEventPreferenceChange", false);
|
runCalculation("onEventPreferenceChange", false, ev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -559,7 +593,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
||||||
iobTable = new LongSparseArray<>();
|
iobTable = new LongSparseArray<>();
|
||||||
autosensDataTable = new LongSparseArray<>();
|
autosensDataTable = new LongSparseArray<>();
|
||||||
}
|
}
|
||||||
runCalculation("onEventConfigBuilderChange", false);
|
runCalculation("onEventConfigBuilderChange", false, ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
// When historical data is changed (comming from NS etc) finished calculations after this date must be invalidated
|
// When historical data is changed (comming from NS etc) finished calculations after this date must be invalidated
|
||||||
|
@ -599,7 +633,7 @@ public class IobCobCalculatorPlugin implements PluginBase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
runCalculation("onEventNewHistoryData", false);
|
runCalculation("onEventNewHistoryData", false, ev);
|
||||||
//log.debug("Releasing onNewHistoryData");
|
//log.debug("Releasing onNewHistoryData");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ import info.nightscout.androidaps.data.IobTotal;
|
||||||
import info.nightscout.androidaps.data.Profile;
|
import info.nightscout.androidaps.data.Profile;
|
||||||
import info.nightscout.androidaps.db.BgReading;
|
import info.nightscout.androidaps.db.BgReading;
|
||||||
import info.nightscout.androidaps.db.Treatment;
|
import info.nightscout.androidaps.db.Treatment;
|
||||||
|
import info.nightscout.androidaps.events.Event;
|
||||||
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventAutosensCalculationFinished;
|
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventAutosensCalculationFinished;
|
||||||
import info.nightscout.androidaps.queue.QueueThread;
|
import info.nightscout.androidaps.queue.QueueThread;
|
||||||
|
|
||||||
|
@ -31,6 +32,7 @@ import static info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculat
|
||||||
|
|
||||||
public class IobCobThread extends Thread {
|
public class IobCobThread extends Thread {
|
||||||
private static Logger log = LoggerFactory.getLogger(QueueThread.class);
|
private static Logger log = LoggerFactory.getLogger(QueueThread.class);
|
||||||
|
private final Event cause;
|
||||||
|
|
||||||
private IobCobCalculatorPlugin iobCobCalculatorPlugin;
|
private IobCobCalculatorPlugin iobCobCalculatorPlugin;
|
||||||
private boolean bgDataReload;
|
private boolean bgDataReload;
|
||||||
|
@ -38,12 +40,13 @@ public class IobCobThread extends Thread {
|
||||||
|
|
||||||
private PowerManager.WakeLock mWakeLock;
|
private PowerManager.WakeLock mWakeLock;
|
||||||
|
|
||||||
public IobCobThread(IobCobCalculatorPlugin plugin, String from, boolean bgDataReload) {
|
public IobCobThread(IobCobCalculatorPlugin plugin, String from, boolean bgDataReload, Event cause) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.iobCobCalculatorPlugin = plugin;
|
this.iobCobCalculatorPlugin = plugin;
|
||||||
this.bgDataReload = bgDataReload;
|
this.bgDataReload = bgDataReload;
|
||||||
this.from = from;
|
this.from = from;
|
||||||
|
this.cause = cause;
|
||||||
|
|
||||||
PowerManager powerManager = (PowerManager) MainApp.instance().getApplicationContext().getSystemService(Context.POWER_SERVICE);
|
PowerManager powerManager = (PowerManager) MainApp.instance().getApplicationContext().getSystemService(Context.POWER_SERVICE);
|
||||||
mWakeLock = powerManager.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "iobCobThread");
|
mWakeLock = powerManager.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "iobCobThread");
|
||||||
|
@ -135,11 +138,45 @@ public class IobCobThread extends Thread {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
delta = (bg - bucketed_data.get(i + 1).value);
|
delta = (bg - bucketed_data.get(i + 1).value);
|
||||||
|
avgDelta = (bg - bucketed_data.get(i + 3).value) / 3;
|
||||||
|
|
||||||
IobTotal iob = iobCobCalculatorPlugin.calculateFromTreatmentsAndTemps(bgTime);
|
IobTotal iob = iobCobCalculatorPlugin.calculateFromTreatmentsAndTemps(bgTime);
|
||||||
|
|
||||||
double bgi = -iob.activity * sens * 5;
|
double bgi = -iob.activity * sens * 5;
|
||||||
double deviation = delta - bgi;
|
double deviation = delta - bgi;
|
||||||
|
double avgDeviation = Math.round((avgDelta - bgi) * 1000) / 1000;
|
||||||
|
|
||||||
|
double currentDeviation;
|
||||||
|
double slopeFromMaxDeviation = 0;
|
||||||
|
double slopeFromMinDeviation = 999;
|
||||||
|
double maxDeviation = 0;
|
||||||
|
double minDeviation = 999;
|
||||||
|
|
||||||
|
// https://github.com/openaps/oref0/blob/master/lib/determine-basal/cob-autosens.js#L169
|
||||||
|
if (i < bucketed_data.size() - 16) { // we need 1h of data to calculate minDeviationSlope
|
||||||
|
long hourago = bgTime + 10 * 1000 - 60 * 60 * 1000L;
|
||||||
|
AutosensData hourAgoData = iobCobCalculatorPlugin.getAutosensData(hourago);
|
||||||
|
if (hourAgoData != null) {
|
||||||
|
currentDeviation = hourAgoData.avgDeviation;
|
||||||
|
int initialIndex = autosensDataTable.indexOfKey(hourAgoData.time);
|
||||||
|
|
||||||
|
for (int past = 1; past < 12; past++) {
|
||||||
|
AutosensData ad = autosensDataTable.valueAt(initialIndex + past);
|
||||||
|
double deviationSlope = (ad.avgDeviation - currentDeviation) / (ad.time - bgTime) * 1000 * 60 * 5;
|
||||||
|
if (ad.avgDeviation > maxDeviation) {
|
||||||
|
slopeFromMaxDeviation = Math.min(0, deviationSlope);
|
||||||
|
maxDeviation = ad.avgDeviation;
|
||||||
|
}
|
||||||
|
if (avgDeviation < minDeviation) {
|
||||||
|
slopeFromMinDeviation = Math.max(0, deviationSlope);
|
||||||
|
minDeviation = avgDeviation;
|
||||||
|
}
|
||||||
|
|
||||||
|
//if (Config.logAutosensData)
|
||||||
|
// log.debug("Deviations: " + new Date(bgTime) + new Date(ad.time) + " avgDeviation=" + avgDeviation + " deviationSlope=" + deviationSlope + " slopeFromMaxDeviation=" + slopeFromMaxDeviation + " slopeFromMinDeviation=" + slopeFromMinDeviation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
List<Treatment> recentTreatments = MainApp.getConfigBuilder().getTreatments5MinBackFromHistory(bgTime);
|
List<Treatment> recentTreatments = MainApp.getConfigBuilder().getTreatments5MinBackFromHistory(bgTime);
|
||||||
for (int ir = 0; ir < recentTreatments.size(); ir++) {
|
for (int ir = 0; ir < recentTreatments.size(); ir++) {
|
||||||
|
@ -170,6 +207,11 @@ public class IobCobThread extends Thread {
|
||||||
autosensData.deviation = deviation;
|
autosensData.deviation = deviation;
|
||||||
autosensData.bgi = bgi;
|
autosensData.bgi = bgi;
|
||||||
autosensData.delta = delta;
|
autosensData.delta = delta;
|
||||||
|
autosensData.avgDelta = avgDelta;
|
||||||
|
autosensData.avgDeviation = avgDeviation;
|
||||||
|
autosensData.slopeFromMaxDeviation = slopeFromMaxDeviation;
|
||||||
|
autosensData.slopeFromMinDeviation = slopeFromMinDeviation;
|
||||||
|
|
||||||
|
|
||||||
// calculate autosens only without COB
|
// calculate autosens only without COB
|
||||||
if (autosensData.cob <= 0) {
|
if (autosensData.cob <= 0) {
|
||||||
|
@ -196,7 +238,7 @@ public class IobCobThread extends Thread {
|
||||||
log.debug(autosensData.log(bgTime));
|
log.debug(autosensData.log(bgTime));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MainApp.bus().post(new EventAutosensCalculationFinished());
|
MainApp.bus().post(new EventAutosensCalculationFinished(cause));
|
||||||
log.debug("Finishing calculation thread: " + from);
|
log.debug("Finishing calculation thread: " + from);
|
||||||
} finally {
|
} finally {
|
||||||
mWakeLock.release();
|
mWakeLock.release();
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package info.nightscout.androidaps.plugins.IobCobCalculator.events;
|
package info.nightscout.androidaps.plugins.IobCobCalculator.events;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.events.Event;
|
||||||
import info.nightscout.androidaps.events.EventLoop;
|
import info.nightscout.androidaps.events.EventLoop;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -7,4 +8,9 @@ import info.nightscout.androidaps.events.EventLoop;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class EventAutosensCalculationFinished extends EventLoop {
|
public class EventAutosensCalculationFinished extends EventLoop {
|
||||||
|
public Event cause;
|
||||||
|
|
||||||
|
public EventAutosensCalculationFinished(Event cause) {
|
||||||
|
this.cause = cause;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,22 @@
|
||||||
package info.nightscout.androidaps.plugins.Loop;
|
package info.nightscout.androidaps.plugins.Loop;
|
||||||
|
|
||||||
import android.os.Parcel;
|
|
||||||
import android.os.Parcelable;
|
|
||||||
import android.text.Html;
|
import android.text.Html;
|
||||||
import android.text.Spanned;
|
import android.text.Spanned;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import info.nightscout.androidaps.MainApp;
|
import info.nightscout.androidaps.MainApp;
|
||||||
import info.nightscout.androidaps.R;
|
import info.nightscout.androidaps.R;
|
||||||
|
import info.nightscout.androidaps.data.IobTotal;
|
||||||
|
import info.nightscout.androidaps.db.BgReading;
|
||||||
import info.nightscout.androidaps.interfaces.PumpInterface;
|
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||||
import info.nightscout.utils.DecimalFormatter;
|
import info.nightscout.utils.DecimalFormatter;
|
||||||
|
@ -22,36 +27,64 @@ import info.nightscout.utils.DecimalFormatter;
|
||||||
public class APSResult {
|
public class APSResult {
|
||||||
private static Logger log = LoggerFactory.getLogger(APSResult.class);
|
private static Logger log = LoggerFactory.getLogger(APSResult.class);
|
||||||
|
|
||||||
|
public Date date;
|
||||||
public String reason;
|
public String reason;
|
||||||
public double rate;
|
public double rate;
|
||||||
public int duration;
|
public int duration;
|
||||||
public boolean changeRequested = false;
|
public boolean tempBasalReqested = false;
|
||||||
|
public boolean bolusRequested = false;
|
||||||
|
public IobTotal iob;
|
||||||
|
public JSONObject json = new JSONObject();
|
||||||
|
public boolean hasPredictions = false;
|
||||||
|
public double smb = 0d; // super micro bolus in units
|
||||||
|
public long deliverAt = 0;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
final PumpInterface pump = ConfigBuilderPlugin.getActivePump();
|
final PumpInterface pump = ConfigBuilderPlugin.getActivePump();
|
||||||
if (changeRequested) {
|
if (isChangeRequested()) {
|
||||||
|
String ret;
|
||||||
|
// rate
|
||||||
if (rate == 0 && duration == 0)
|
if (rate == 0 && duration == 0)
|
||||||
return MainApp.sResources.getString(R.string.canceltemp);
|
ret = MainApp.sResources.getString(R.string.canceltemp) + "\n";
|
||||||
|
else if (rate == -1)
|
||||||
|
ret = MainApp.sResources.getString(R.string.let_temp_basal_run) + "\n";
|
||||||
else
|
else
|
||||||
return MainApp.sResources.getString(R.string.rate) + ": " + DecimalFormatter.to2Decimal(rate) + " U/h " +
|
ret = MainApp.sResources.getString(R.string.rate) + ": " + DecimalFormatter.to2Decimal(rate) + " U/h " +
|
||||||
"(" + DecimalFormatter.to2Decimal(rate / pump.getBaseBasalRate() * 100) + "%)\n" +
|
"(" + DecimalFormatter.to2Decimal(rate / pump.getBaseBasalRate() * 100) + "%) \n" +
|
||||||
MainApp.sResources.getString(R.string.duration) + ": " + DecimalFormatter.to0Decimal(duration) + " min\n" +
|
MainApp.sResources.getString(R.string.duration) + ": " + DecimalFormatter.to2Decimal(duration) + " min\n";
|
||||||
MainApp.sResources.getString(R.string.reason) + ": " + reason;
|
|
||||||
|
// smb
|
||||||
|
if (smb != 0)
|
||||||
|
ret += ("SMB: " + DecimalFormatter.to2Decimal(smb) + " U\n");
|
||||||
|
|
||||||
|
// reason
|
||||||
|
ret += MainApp.sResources.getString(R.string.reason) + ": " + reason;
|
||||||
|
return ret;
|
||||||
} else
|
} else
|
||||||
return MainApp.sResources.getString(R.string.nochangerequested);
|
return MainApp.sResources.getString(R.string.nochangerequested);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Spanned toSpanned() {
|
public Spanned toSpanned() {
|
||||||
final PumpInterface pump = ConfigBuilderPlugin.getActivePump();
|
final PumpInterface pump = ConfigBuilderPlugin.getActivePump();
|
||||||
if (changeRequested) {
|
if (isChangeRequested()) {
|
||||||
String ret = "";
|
String ret;
|
||||||
if (rate == 0 && duration == 0) ret = MainApp.sResources.getString(R.string.canceltemp);
|
// rate
|
||||||
|
if (rate == 0 && duration == 0)
|
||||||
|
ret = MainApp.sResources.getString(R.string.canceltemp) + "<br>";
|
||||||
|
else if (rate == -1)
|
||||||
|
ret = MainApp.sResources.getString(R.string.let_temp_basal_run) + "<br>";
|
||||||
else
|
else
|
||||||
ret = "<b>" + MainApp.sResources.getString(R.string.rate) + "</b>: " + DecimalFormatter.to2Decimal(rate) + " U/h " +
|
ret = "<b>" + MainApp.sResources.getString(R.string.rate) + "</b>: " + DecimalFormatter.to2Decimal(rate) + " U/h " +
|
||||||
"(" + DecimalFormatter.to2Decimal(rate / pump.getBaseBasalRate() * 100) + "%) <br>" +
|
"(" + DecimalFormatter.to2Decimal(rate / pump.getBaseBasalRate() * 100) + "%) <br>" +
|
||||||
"<b>" + MainApp.sResources.getString(R.string.duration) + "</b>: " + DecimalFormatter.to2Decimal(duration) + " min<br>" +
|
"<b>" + MainApp.sResources.getString(R.string.duration) + "</b>: " + DecimalFormatter.to2Decimal(duration) + " min<br>";
|
||||||
"<b>" + MainApp.sResources.getString(R.string.reason) + "</b>: " + reason.replace("<", "<").replace(">", ">");
|
|
||||||
|
// smb
|
||||||
|
if (smb != 0)
|
||||||
|
ret += ("<b>" + "SMB" + "</b>: " + DecimalFormatter.to2Decimal(smb) + " U<br>");
|
||||||
|
|
||||||
|
// reason
|
||||||
|
ret += "<b>" + MainApp.sResources.getString(R.string.reason) + "</b>: " + reason.replace("<", "<").replace(">", ">");
|
||||||
return Html.fromHtml(ret);
|
return Html.fromHtml(ret);
|
||||||
} else
|
} else
|
||||||
return Html.fromHtml(MainApp.sResources.getString(R.string.nochangerequested));
|
return Html.fromHtml(MainApp.sResources.getString(R.string.nochangerequested));
|
||||||
|
@ -62,17 +95,19 @@ public class APSResult {
|
||||||
|
|
||||||
public APSResult clone() {
|
public APSResult clone() {
|
||||||
APSResult newResult = new APSResult();
|
APSResult newResult = new APSResult();
|
||||||
newResult.reason = new String(reason);
|
newResult.reason = reason;
|
||||||
newResult.rate = rate;
|
newResult.rate = rate;
|
||||||
newResult.duration = duration;
|
newResult.duration = duration;
|
||||||
newResult.changeRequested = changeRequested;
|
newResult.tempBasalReqested = tempBasalReqested;
|
||||||
|
newResult.bolusRequested = bolusRequested;
|
||||||
|
newResult.iob = iob;
|
||||||
return newResult;
|
return newResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
public JSONObject json() {
|
public JSONObject json() {
|
||||||
JSONObject json = new JSONObject();
|
JSONObject json = new JSONObject();
|
||||||
try {
|
try {
|
||||||
if (changeRequested) {
|
if (isChangeRequested()) {
|
||||||
json.put("rate", rate);
|
json.put("rate", rate);
|
||||||
json.put("duration", duration);
|
json.put("duration", duration);
|
||||||
json.put("reason", reason);
|
json.put("reason", reason);
|
||||||
|
@ -82,4 +117,105 @@ public class APSResult {
|
||||||
}
|
}
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<BgReading> getPredictions() {
|
||||||
|
List<BgReading> array = new ArrayList<>();
|
||||||
|
try {
|
||||||
|
long startTime = date.getTime();
|
||||||
|
if (json.has("predBGs")) {
|
||||||
|
JSONObject predBGs = json.getJSONObject("predBGs");
|
||||||
|
if (predBGs.has("IOB")) {
|
||||||
|
JSONArray iob = predBGs.getJSONArray("IOB");
|
||||||
|
for (int i = 1; i < iob.length(); i++) {
|
||||||
|
BgReading bg = new BgReading();
|
||||||
|
bg.value = iob.getInt(i);
|
||||||
|
bg.date = startTime + i * 5 * 60 * 1000L;
|
||||||
|
bg.isIOBPrediction = true;
|
||||||
|
array.add(bg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (predBGs.has("aCOB")) {
|
||||||
|
JSONArray iob = predBGs.getJSONArray("aCOB");
|
||||||
|
for (int i = 1; i < iob.length(); i++) {
|
||||||
|
BgReading bg = new BgReading();
|
||||||
|
bg.value = iob.getInt(i);
|
||||||
|
bg.date = startTime + i * 5 * 60 * 1000L;
|
||||||
|
bg.isaCOBPrediction = true;
|
||||||
|
array.add(bg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (predBGs.has("COB")) {
|
||||||
|
JSONArray iob = predBGs.getJSONArray("COB");
|
||||||
|
for (int i = 1; i < iob.length(); i++) {
|
||||||
|
BgReading bg = new BgReading();
|
||||||
|
bg.value = iob.getInt(i);
|
||||||
|
bg.date = startTime + i * 5 * 60 * 1000L;
|
||||||
|
bg.isCOBPrediction = true;
|
||||||
|
array.add(bg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (predBGs.has("UAM")) {
|
||||||
|
JSONArray iob = predBGs.getJSONArray("UAM");
|
||||||
|
for (int i = 1; i < iob.length(); i++) {
|
||||||
|
BgReading bg = new BgReading();
|
||||||
|
bg.value = iob.getInt(i);
|
||||||
|
bg.date = startTime + i * 5 * 60 * 1000L;
|
||||||
|
bg.isUAMPrediction = true;
|
||||||
|
array.add(bg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (predBGs.has("ZT")) {
|
||||||
|
JSONArray iob = predBGs.getJSONArray("ZT");
|
||||||
|
for (int i = 1; i < iob.length(); i++) {
|
||||||
|
BgReading bg = new BgReading();
|
||||||
|
bg.value = iob.getInt(i);
|
||||||
|
bg.date = startTime + i * 5 * 60 * 1000L;
|
||||||
|
bg.isZTPrediction = true;
|
||||||
|
array.add(bg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getLatestPredictionsTime() {
|
||||||
|
long latest = 0;
|
||||||
|
try {
|
||||||
|
long startTime = date.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);
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,9 +30,12 @@ import info.nightscout.androidaps.interfaces.ConstraintsInterface;
|
||||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||||
import info.nightscout.androidaps.interfaces.PumpInterface;
|
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||||
|
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventAutosensCalculationFinished;
|
||||||
|
import info.nightscout.androidaps.plugins.Loop.events.EventLoopResult;
|
||||||
import info.nightscout.androidaps.plugins.Loop.events.EventLoopSetLastRunGui;
|
import info.nightscout.androidaps.plugins.Loop.events.EventLoopSetLastRunGui;
|
||||||
import info.nightscout.androidaps.plugins.Loop.events.EventLoopUpdateGui;
|
import info.nightscout.androidaps.plugins.Loop.events.EventLoopUpdateGui;
|
||||||
import info.nightscout.androidaps.plugins.Loop.events.EventNewOpenLoopNotification;
|
import info.nightscout.androidaps.plugins.Loop.events.EventNewOpenLoopNotification;
|
||||||
|
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
|
||||||
import info.nightscout.androidaps.queue.Callback;
|
import info.nightscout.androidaps.queue.Callback;
|
||||||
import info.nightscout.utils.NSUpload;
|
import info.nightscout.utils.NSUpload;
|
||||||
import info.nightscout.utils.SP;
|
import info.nightscout.utils.SP;
|
||||||
|
@ -152,8 +155,10 @@ public class LoopPlugin implements PluginBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void onStatusEvent(final EventNewBG ev) {
|
public void onStatusEvent(final EventAutosensCalculationFinished ev) {
|
||||||
invoke("EventNewBG", true);
|
if (ev.cause instanceof EventNewBG) {
|
||||||
|
invoke(ev.getClass().getSimpleName() + "(" + ev.cause.getClass().getSimpleName() + ")", true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public long suspendedTo() {
|
public long suspendedTo() {
|
||||||
|
@ -283,6 +288,14 @@ public class LoopPlugin implements PluginBase {
|
||||||
// check rate for constrais
|
// check rate for constrais
|
||||||
final APSResult resultAfterConstraints = result.clone();
|
final APSResult resultAfterConstraints = result.clone();
|
||||||
resultAfterConstraints.rate = constraintsInterface.applyBasalConstraints(resultAfterConstraints.rate);
|
resultAfterConstraints.rate = constraintsInterface.applyBasalConstraints(resultAfterConstraints.rate);
|
||||||
|
resultAfterConstraints.smb = constraintsInterface.applyBolusConstraints(resultAfterConstraints.smb);
|
||||||
|
|
||||||
|
// safety check for multiple SMBs
|
||||||
|
long lastBolusTime = TreatmentsPlugin.getPlugin().getLastBolusTime();
|
||||||
|
if (lastBolusTime != 0 && lastBolusTime + 3 * 60 * 1000 > System.currentTimeMillis()) {
|
||||||
|
log.debug("SMB requsted but still in 3 min interval");
|
||||||
|
resultAfterConstraints.smb = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (lastRun == null) lastRun = new LastRun();
|
if (lastRun == null) lastRun = new LastRun();
|
||||||
lastRun.request = result;
|
lastRun.request = result;
|
||||||
|
@ -305,8 +318,10 @@ public class LoopPlugin implements PluginBase {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MainApp.bus().post(new EventLoopResult(resultAfterConstraints));
|
||||||
|
|
||||||
if (constraintsInterface.isClosedModeEnabled()) {
|
if (constraintsInterface.isClosedModeEnabled()) {
|
||||||
if (result.changeRequested) {
|
if (result.isChangeRequested()) {
|
||||||
final PumpEnactResult waiting = new PumpEnactResult();
|
final PumpEnactResult waiting = new PumpEnactResult();
|
||||||
final PumpEnactResult previousResult = lastRun.setByPump;
|
final PumpEnactResult previousResult = lastRun.setByPump;
|
||||||
waiting.queued = true;
|
waiting.queued = true;
|
||||||
|
@ -330,7 +345,7 @@ public class LoopPlugin implements PluginBase {
|
||||||
lastRun.source = null;
|
lastRun.source = null;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (result.changeRequested && allowNotification) {
|
if (result.isChangeRequested() && allowNotification) {
|
||||||
NotificationCompat.Builder builder =
|
NotificationCompat.Builder builder =
|
||||||
new NotificationCompat.Builder(MainApp.instance().getApplicationContext());
|
new NotificationCompat.Builder(MainApp.instance().getApplicationContext());
|
||||||
builder.setSmallIcon(R.drawable.notif_icon)
|
builder.setSmallIcon(R.drawable.notif_icon)
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
package info.nightscout.androidaps.plugins.Loop.events;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.plugins.Loop.APSResult;
|
||||||
|
|
||||||
|
public class EventLoopResult {
|
||||||
|
public final APSResult apsResult;
|
||||||
|
|
||||||
|
public EventLoopResult(APSResult apsResult) {
|
||||||
|
this.apsResult = apsResult;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ import info.nightscout.androidaps.db.TemporaryBasal;
|
||||||
import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin;
|
import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin;
|
||||||
import info.nightscout.androidaps.plugins.Loop.ScriptReader;
|
import info.nightscout.androidaps.plugins.Loop.ScriptReader;
|
||||||
import info.nightscout.androidaps.plugins.OpenAPSMA.LoggerCallback;
|
import info.nightscout.androidaps.plugins.OpenAPSMA.LoggerCallback;
|
||||||
|
import info.nightscout.androidaps.plugins.OpenAPSSMB.SMBDefaults;
|
||||||
import info.nightscout.utils.SP;
|
import info.nightscout.utils.SP;
|
||||||
|
|
||||||
public class DetermineBasalAdapterAMAJS {
|
public class DetermineBasalAdapterAMAJS {
|
||||||
|
@ -189,8 +190,7 @@ public class DetermineBasalAdapterAMAJS {
|
||||||
GlucoseStatus glucoseStatus,
|
GlucoseStatus glucoseStatus,
|
||||||
MealData mealData,
|
MealData mealData,
|
||||||
double autosensDataRatio,
|
double autosensDataRatio,
|
||||||
boolean tempTargetSet,
|
boolean tempTargetSet) throws JSONException {
|
||||||
double min_5m_carbimpact) throws JSONException {
|
|
||||||
|
|
||||||
String units = profile.getUnits();
|
String units = profile.getUnits();
|
||||||
|
|
||||||
|
@ -211,7 +211,7 @@ public class DetermineBasalAdapterAMAJS {
|
||||||
mProfile.put("current_basal", basalrate);
|
mProfile.put("current_basal", basalrate);
|
||||||
mProfile.put("temptargetSet", tempTargetSet);
|
mProfile.put("temptargetSet", tempTargetSet);
|
||||||
mProfile.put("autosens_adjust_targets", SP.getBoolean("openapsama_autosens_adjusttargets", true));
|
mProfile.put("autosens_adjust_targets", SP.getBoolean("openapsama_autosens_adjusttargets", true));
|
||||||
mProfile.put("min_5m_carbimpact", SP.getDouble("openapsama_min_5m_carbimpact", 3d));
|
mProfile.put("min_5m_carbimpact", SP.getInt("openapsama_min_5m_carbimpact", SMBDefaults.min_5m_carbimpact));
|
||||||
|
|
||||||
if (units.equals(Constants.MMOL)) {
|
if (units.equals(Constants.MMOL)) {
|
||||||
mProfile.put("out_units", "mmol/L");
|
mProfile.put("out_units", "mmol/L");
|
||||||
|
|
|
@ -1,35 +1,28 @@
|
||||||
package info.nightscout.androidaps.plugins.OpenAPSAMA;
|
package info.nightscout.androidaps.plugins.OpenAPSAMA;
|
||||||
|
|
||||||
import org.json.JSONArray;
|
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.mozilla.javascript.NativeObject;
|
import org.mozilla.javascript.NativeObject;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.db.BgReading;
|
|
||||||
import info.nightscout.androidaps.plugins.Loop.APSResult;
|
import info.nightscout.androidaps.plugins.Loop.APSResult;
|
||||||
import info.nightscout.androidaps.data.IobTotal;
|
|
||||||
|
|
||||||
public class DetermineBasalResultAMA extends APSResult {
|
public class DetermineBasalResultAMA extends APSResult {
|
||||||
private static Logger log = LoggerFactory.getLogger(DetermineBasalResultAMA.class);
|
private static Logger log = LoggerFactory.getLogger(DetermineBasalResultAMA.class);
|
||||||
|
|
||||||
public Date date;
|
|
||||||
public JSONObject json = new JSONObject();
|
|
||||||
public double eventualBG;
|
public double eventualBG;
|
||||||
public double snoozeBG;
|
public double snoozeBG;
|
||||||
public IobTotal iob;
|
|
||||||
|
|
||||||
public DetermineBasalResultAMA(NativeObject result, JSONObject j) {
|
public DetermineBasalResultAMA(NativeObject result, JSONObject j) {
|
||||||
|
this();
|
||||||
date = new Date();
|
date = new Date();
|
||||||
json = j;
|
json = j;
|
||||||
if (result.containsKey("error")) {
|
if (result.containsKey("error")) {
|
||||||
reason = result.get("error").toString();
|
reason = result.get("error").toString();
|
||||||
changeRequested = false;
|
tempBasalReqested = false;
|
||||||
rate = -1;
|
rate = -1;
|
||||||
duration = -1;
|
duration = -1;
|
||||||
} else {
|
} else {
|
||||||
|
@ -37,36 +30,37 @@ public class DetermineBasalResultAMA extends APSResult {
|
||||||
if (result.containsKey("eventualBG")) eventualBG = (Double) result.get("eventualBG");
|
if (result.containsKey("eventualBG")) eventualBG = (Double) result.get("eventualBG");
|
||||||
if (result.containsKey("snoozeBG")) snoozeBG = (Double) result.get("snoozeBG");
|
if (result.containsKey("snoozeBG")) snoozeBG = (Double) result.get("snoozeBG");
|
||||||
if (result.containsKey("rate")) {
|
if (result.containsKey("rate")) {
|
||||||
rate = (Double) result.get("rate");
|
rate = (Double) result.get("rate");
|
||||||
if (rate < 0d) rate = 0d;
|
if (rate < 0d) rate = 0d;
|
||||||
changeRequested = true;
|
tempBasalReqested = true;
|
||||||
} else {
|
} else {
|
||||||
rate = -1;
|
rate = -1;
|
||||||
changeRequested = false;
|
tempBasalReqested = false;
|
||||||
}
|
}
|
||||||
if (result.containsKey("duration")) {
|
if (result.containsKey("duration")) {
|
||||||
duration = ((Double)result.get("duration")).intValue();
|
duration = ((Double) result.get("duration")).intValue();
|
||||||
//changeRequested as above
|
//changeRequested as above
|
||||||
} else {
|
} else {
|
||||||
duration = -1;
|
duration = -1;
|
||||||
changeRequested = false;
|
tempBasalReqested = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
bolusRequested = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DetermineBasalResultAMA() {
|
public DetermineBasalResultAMA() {
|
||||||
|
hasPredictions = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DetermineBasalResultAMA clone() {
|
public DetermineBasalResultAMA clone() {
|
||||||
DetermineBasalResultAMA newResult = new DetermineBasalResultAMA();
|
DetermineBasalResultAMA newResult = new DetermineBasalResultAMA();
|
||||||
newResult.reason = new String(reason);
|
newResult.reason = reason;
|
||||||
newResult.rate = rate;
|
newResult.rate = rate;
|
||||||
newResult.duration = duration;
|
newResult.duration = duration;
|
||||||
newResult.changeRequested = changeRequested;
|
newResult.tempBasalReqested = tempBasalReqested;
|
||||||
newResult.rate = rate;
|
newResult.rate = rate;
|
||||||
newResult.duration = duration;
|
newResult.duration = duration;
|
||||||
newResult.changeRequested = changeRequested;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
newResult.json = new JSONObject(json.toString());
|
newResult.json = new JSONObject(json.toString());
|
||||||
|
@ -90,72 +84,4 @@ public class DetermineBasalResultAMA extends APSResult {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<BgReading> getPredictions() {
|
|
||||||
List<BgReading> array = new ArrayList<>();
|
|
||||||
try {
|
|
||||||
long startTime = date.getTime();
|
|
||||||
if (json.has("predBGs")) {
|
|
||||||
JSONObject predBGs = json.getJSONObject("predBGs");
|
|
||||||
if (predBGs.has("IOB")) {
|
|
||||||
JSONArray iob = predBGs.getJSONArray("IOB");
|
|
||||||
for (int i = 1; i < iob.length(); i ++) {
|
|
||||||
BgReading bg = new BgReading();
|
|
||||||
bg.value = iob.getInt(i);
|
|
||||||
bg.date = startTime + i * 5 * 60 * 1000L;
|
|
||||||
bg.isPrediction = true;
|
|
||||||
array.add(bg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (predBGs.has("aCOB")) {
|
|
||||||
JSONArray iob = predBGs.getJSONArray("aCOB");
|
|
||||||
for (int i = 1; i < iob.length(); i ++) {
|
|
||||||
BgReading bg = new BgReading();
|
|
||||||
bg.value = iob.getInt(i);
|
|
||||||
bg.date = startTime + i * 5 * 60 * 1000L;
|
|
||||||
bg.isPrediction = true;
|
|
||||||
array.add(bg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (predBGs.has("COB")) {
|
|
||||||
JSONArray iob = predBGs.getJSONArray("COB");
|
|
||||||
for (int i = 1; i < iob.length(); i ++) {
|
|
||||||
BgReading bg = new BgReading();
|
|
||||||
bg.value = iob.getInt(i);
|
|
||||||
bg.date = startTime + i * 5 * 60 * 1000L;
|
|
||||||
bg.isPrediction = true;
|
|
||||||
array.add(bg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (JSONException e) {
|
|
||||||
log.error("Unhandled exception", e);
|
|
||||||
}
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getLatestPredictionsTime() {
|
|
||||||
long latest = 0;
|
|
||||||
try {
|
|
||||||
long startTime = date.getTime();
|
|
||||||
if (json.has("predBGs")) {
|
|
||||||
JSONObject predBGs = json.getJSONObject("predBGs");
|
|
||||||
if (predBGs.has("IOB")) {
|
|
||||||
JSONArray iob = predBGs.getJSONArray("IOB");
|
|
||||||
latest = Math.max(latest, startTime + (iob.length() - 1) * 5 * 60 * 1000L);
|
|
||||||
}
|
|
||||||
if (predBGs.has("aCOB")) {
|
|
||||||
JSONArray iob = predBGs.getJSONArray("aCOB");
|
|
||||||
latest = Math.max(latest, startTime + (iob.length() - 1) * 5 * 60 * 1000L);
|
|
||||||
}
|
|
||||||
if (predBGs.has("COB")) {
|
|
||||||
JSONArray iob = predBGs.getJSONArray("COB");
|
|
||||||
latest = Math.max(latest, startTime + (iob.length() - 1) * 5 * 60 * 1000L);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (JSONException e) {
|
|
||||||
log.error("Unhandled exception", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
return latest;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,6 @@ import info.nightscout.utils.NSUpload;
|
||||||
import info.nightscout.utils.Profiler;
|
import info.nightscout.utils.Profiler;
|
||||||
import info.nightscout.utils.Round;
|
import info.nightscout.utils.Round;
|
||||||
import info.nightscout.utils.SP;
|
import info.nightscout.utils.SP;
|
||||||
import info.nightscout.utils.SafeParse;
|
|
||||||
import info.nightscout.utils.ToastUtils;
|
import info.nightscout.utils.ToastUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -233,8 +232,7 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface {
|
||||||
try {
|
try {
|
||||||
determineBasalAdapterAMAJS.setData(profile, maxIob, maxBasal, minBg, maxBg, targetBg, ConfigBuilderPlugin.getActivePump().getBaseBasalRate(), iobArray, glucoseStatus, mealData,
|
determineBasalAdapterAMAJS.setData(profile, maxIob, maxBasal, minBg, maxBg, targetBg, ConfigBuilderPlugin.getActivePump().getBaseBasalRate(), iobArray, glucoseStatus, mealData,
|
||||||
lastAutosensResult.ratio, //autosensDataRatio
|
lastAutosensResult.ratio, //autosensDataRatio
|
||||||
isTempTarget,
|
isTempTarget
|
||||||
SafeParse.stringToDouble(SP.getString("openapsama_min_5m_carbimpact", "3.0"))//min_5m_carbimpact
|
|
||||||
);
|
);
|
||||||
} catch (JSONException e) {
|
} catch (JSONException e) {
|
||||||
log.error("Unable to set data: " + e.toString());
|
log.error("Unable to set data: " + e.toString());
|
||||||
|
@ -245,15 +243,15 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface {
|
||||||
Profiler.log(log, "AMA calculation", start);
|
Profiler.log(log, "AMA calculation", start);
|
||||||
// Fix bug determine basal
|
// Fix bug determine basal
|
||||||
if (determineBasalResultAMA.rate == 0d && determineBasalResultAMA.duration == 0 && !MainApp.getConfigBuilder().isTempBasalInProgress())
|
if (determineBasalResultAMA.rate == 0d && determineBasalResultAMA.duration == 0 && !MainApp.getConfigBuilder().isTempBasalInProgress())
|
||||||
determineBasalResultAMA.changeRequested = false;
|
determineBasalResultAMA.tempBasalReqested = false;
|
||||||
// limit requests on openloop mode
|
// limit requests on openloop mode
|
||||||
if (!MainApp.getConfigBuilder().isClosedModeEnabled()) {
|
if (!MainApp.getConfigBuilder().isClosedModeEnabled()) {
|
||||||
if (MainApp.getConfigBuilder().isTempBasalInProgress() && determineBasalResultAMA.rate == 0 && determineBasalResultAMA.duration == 0) {
|
if (MainApp.getConfigBuilder().isTempBasalInProgress() && determineBasalResultAMA.rate == 0 && determineBasalResultAMA.duration == 0) {
|
||||||
// going to cancel
|
// going to cancel
|
||||||
} else if (MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultAMA.rate - MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory()) < 0.1) {
|
} else if (MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultAMA.rate - MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory()) < 0.1) {
|
||||||
determineBasalResultAMA.changeRequested = false;
|
determineBasalResultAMA.tempBasalReqested = false;
|
||||||
} else if (!MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultAMA.rate - ConfigBuilderPlugin.getActivePump().getBaseBasalRate()) < 0.1)
|
} else if (!MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultAMA.rate - ConfigBuilderPlugin.getActivePump().getBaseBasalRate()) < 0.1)
|
||||||
determineBasalResultAMA.changeRequested = false;
|
determineBasalResultAMA.tempBasalReqested = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
determineBasalResultAMA.iob = iobArray[0];
|
determineBasalResultAMA.iob = iobArray[0];
|
||||||
|
|
|
@ -6,7 +6,6 @@ import org.mozilla.javascript.NativeObject;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import info.nightscout.androidaps.data.IobTotal;
|
|
||||||
import info.nightscout.androidaps.plugins.Loop.APSResult;
|
import info.nightscout.androidaps.plugins.Loop.APSResult;
|
||||||
|
|
||||||
public class DetermineBasalResultMA extends APSResult {
|
public class DetermineBasalResultMA extends APSResult {
|
||||||
|
@ -16,13 +15,12 @@ public class DetermineBasalResultMA extends APSResult {
|
||||||
public double eventualBG;
|
public double eventualBG;
|
||||||
public double snoozeBG;
|
public double snoozeBG;
|
||||||
public String mealAssist;
|
public String mealAssist;
|
||||||
public IobTotal iob;
|
|
||||||
|
|
||||||
public DetermineBasalResultMA(NativeObject result, JSONObject j) {
|
public DetermineBasalResultMA(NativeObject result, JSONObject j) {
|
||||||
json = j;
|
json = j;
|
||||||
if (result.containsKey("error")) {
|
if (result.containsKey("error")) {
|
||||||
reason = (String) result.get("error");
|
reason = (String) result.get("error");
|
||||||
changeRequested = false;
|
tempBasalReqested = false;
|
||||||
rate = -1;
|
rate = -1;
|
||||||
duration = -1;
|
duration = -1;
|
||||||
mealAssist = "";
|
mealAssist = "";
|
||||||
|
@ -33,17 +31,17 @@ public class DetermineBasalResultMA extends APSResult {
|
||||||
if (result.containsKey("rate")) {
|
if (result.containsKey("rate")) {
|
||||||
rate = (Double) result.get("rate");
|
rate = (Double) result.get("rate");
|
||||||
if (rate < 0d) rate = 0d;
|
if (rate < 0d) rate = 0d;
|
||||||
changeRequested = true;
|
tempBasalReqested = true;
|
||||||
} else {
|
} else {
|
||||||
rate = -1;
|
rate = -1;
|
||||||
changeRequested = false;
|
tempBasalReqested = false;
|
||||||
}
|
}
|
||||||
if (result.containsKey("duration")) {
|
if (result.containsKey("duration")) {
|
||||||
duration = ((Double) result.get("duration")).intValue();
|
duration = ((Double) result.get("duration")).intValue();
|
||||||
//changeRequested as above
|
//changeRequested as above
|
||||||
} else {
|
} else {
|
||||||
duration = -1;
|
duration = -1;
|
||||||
changeRequested = false;
|
tempBasalReqested = false;
|
||||||
}
|
}
|
||||||
if (result.containsKey("mealAssist")) {
|
if (result.containsKey("mealAssist")) {
|
||||||
mealAssist = result.get("mealAssist").toString();
|
mealAssist = result.get("mealAssist").toString();
|
||||||
|
@ -60,10 +58,10 @@ public class DetermineBasalResultMA extends APSResult {
|
||||||
newResult.reason = new String(reason);
|
newResult.reason = new String(reason);
|
||||||
newResult.rate = rate;
|
newResult.rate = rate;
|
||||||
newResult.duration = duration;
|
newResult.duration = duration;
|
||||||
newResult.changeRequested = changeRequested;
|
newResult.tempBasalReqested = isChangeRequested();
|
||||||
newResult.rate = rate;
|
newResult.rate = rate;
|
||||||
newResult.duration = duration;
|
newResult.duration = duration;
|
||||||
newResult.changeRequested = changeRequested;
|
newResult.tempBasalReqested = isChangeRequested();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
newResult.json = new JSONObject(json.toString());
|
newResult.json = new JSONObject(json.toString());
|
||||||
|
@ -72,7 +70,7 @@ public class DetermineBasalResultMA extends APSResult {
|
||||||
}
|
}
|
||||||
newResult.eventualBG = eventualBG;
|
newResult.eventualBG = eventualBG;
|
||||||
newResult.snoozeBG = snoozeBG;
|
newResult.snoozeBG = snoozeBG;
|
||||||
newResult.mealAssist = new String(mealAssist);
|
newResult.mealAssist = mealAssist;
|
||||||
return newResult;
|
return newResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -229,15 +229,15 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface {
|
||||||
DetermineBasalResultMA determineBasalResultMA = determineBasalAdapterMAJS.invoke();
|
DetermineBasalResultMA determineBasalResultMA = determineBasalAdapterMAJS.invoke();
|
||||||
// Fix bug determinef basal
|
// Fix bug determinef basal
|
||||||
if (determineBasalResultMA.rate == 0d && determineBasalResultMA.duration == 0 && !MainApp.getConfigBuilder().isTempBasalInProgress())
|
if (determineBasalResultMA.rate == 0d && determineBasalResultMA.duration == 0 && !MainApp.getConfigBuilder().isTempBasalInProgress())
|
||||||
determineBasalResultMA.changeRequested = false;
|
determineBasalResultMA.tempBasalReqested = false;
|
||||||
// limit requests on openloop mode
|
// limit requests on openloop mode
|
||||||
if (!MainApp.getConfigBuilder().isClosedModeEnabled()) {
|
if (!MainApp.getConfigBuilder().isClosedModeEnabled()) {
|
||||||
if (MainApp.getConfigBuilder().isTempBasalInProgress() && determineBasalResultMA.rate == 0 && determineBasalResultMA.duration == 0) {
|
if (MainApp.getConfigBuilder().isTempBasalInProgress() && determineBasalResultMA.rate == 0 && determineBasalResultMA.duration == 0) {
|
||||||
// going to cancel
|
// going to cancel
|
||||||
} else if (MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultMA.rate - MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory()) < 0.1) {
|
} else if (MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultMA.rate - MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory()) < 0.1) {
|
||||||
determineBasalResultMA.changeRequested = false;
|
determineBasalResultMA.tempBasalReqested = false;
|
||||||
} else if (!MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultMA.rate - ConfigBuilderPlugin.getActivePump().getBaseBasalRate()) < 0.1)
|
} else if (!MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultMA.rate - ConfigBuilderPlugin.getActivePump().getBaseBasalRate()) < 0.1)
|
||||||
determineBasalResultMA.changeRequested = false;
|
determineBasalResultMA.tempBasalReqested = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
determineBasalResultMA.iob = iobTotal;
|
determineBasalResultMA.iob = iobTotal;
|
||||||
|
|
|
@ -0,0 +1,344 @@
|
||||||
|
package info.nightscout.androidaps.plugins.OpenAPSSMB;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
import org.mozilla.javascript.Callable;
|
||||||
|
import org.mozilla.javascript.Context;
|
||||||
|
import org.mozilla.javascript.Function;
|
||||||
|
import org.mozilla.javascript.NativeJSON;
|
||||||
|
import org.mozilla.javascript.NativeObject;
|
||||||
|
import org.mozilla.javascript.RhinoException;
|
||||||
|
import org.mozilla.javascript.Scriptable;
|
||||||
|
import org.mozilla.javascript.ScriptableObject;
|
||||||
|
import org.mozilla.javascript.Undefined;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.Config;
|
||||||
|
import info.nightscout.androidaps.Constants;
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
import info.nightscout.androidaps.R;
|
||||||
|
import info.nightscout.androidaps.data.GlucoseStatus;
|
||||||
|
import info.nightscout.androidaps.data.IobTotal;
|
||||||
|
import info.nightscout.androidaps.data.MealData;
|
||||||
|
import info.nightscout.androidaps.data.Profile;
|
||||||
|
import info.nightscout.androidaps.db.TemporaryBasal;
|
||||||
|
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||||
|
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||||
|
import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin;
|
||||||
|
import info.nightscout.androidaps.plugins.Loop.ScriptReader;
|
||||||
|
import info.nightscout.androidaps.plugins.OpenAPSMA.LoggerCallback;
|
||||||
|
import info.nightscout.androidaps.plugins.SourceDexcomG5.SourceDexcomG5Plugin;
|
||||||
|
import info.nightscout.utils.SP;
|
||||||
|
import info.nightscout.utils.SafeParse;
|
||||||
|
|
||||||
|
public class DetermineBasalAdapterSMBJS {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(DetermineBasalAdapterSMBJS.class);
|
||||||
|
|
||||||
|
|
||||||
|
private ScriptReader mScriptReader = null;
|
||||||
|
private JSONObject mProfile;
|
||||||
|
private JSONObject mGlucoseStatus;
|
||||||
|
private JSONArray mIobData;
|
||||||
|
private JSONObject mMealData;
|
||||||
|
private JSONObject mCurrentTemp;
|
||||||
|
private JSONObject mAutosensData = null;
|
||||||
|
private boolean mMicrobolusAllowed;
|
||||||
|
|
||||||
|
private String storedCurrentTemp = null;
|
||||||
|
private String storedIobData = null;
|
||||||
|
|
||||||
|
private String storedGlucoseStatus = null;
|
||||||
|
private String storedProfile = null;
|
||||||
|
private String storedMeal_data = null;
|
||||||
|
private String storedAutosens_data = null;
|
||||||
|
private String storedMicroBolusAllowed = null;
|
||||||
|
|
||||||
|
private String scriptDebug = "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main code
|
||||||
|
*/
|
||||||
|
|
||||||
|
public DetermineBasalAdapterSMBJS(ScriptReader scriptReader) throws IOException {
|
||||||
|
mScriptReader = scriptReader;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public DetermineBasalResultSMB invoke() {
|
||||||
|
|
||||||
|
|
||||||
|
log.debug(">>> Invoking detemine_basal <<<");
|
||||||
|
log.debug("Glucose status: " + (storedGlucoseStatus = mGlucoseStatus.toString()));
|
||||||
|
log.debug("IOB data: " + (storedIobData = mIobData.toString()));
|
||||||
|
log.debug("Current temp: " + (storedCurrentTemp = mCurrentTemp.toString()));
|
||||||
|
log.debug("Profile: " + (storedProfile = mProfile.toString()));
|
||||||
|
log.debug("Meal data: " + (storedMeal_data = mMealData.toString()));
|
||||||
|
if (mAutosensData != null)
|
||||||
|
log.debug("Autosens data: " + (storedAutosens_data = mAutosensData.toString()));
|
||||||
|
else
|
||||||
|
log.debug("Autosens data: " + (storedAutosens_data = "undefined"));
|
||||||
|
log.debug("Reservoir data: " + "undefined");
|
||||||
|
log.debug("MicroBolusAllowed: " + (storedMicroBolusAllowed = "" + mMicrobolusAllowed));
|
||||||
|
|
||||||
|
DetermineBasalResultSMB determineBasalResultSMB = null;
|
||||||
|
|
||||||
|
Context rhino = Context.enter();
|
||||||
|
Scriptable scope = rhino.initStandardObjects();
|
||||||
|
// Turn off optimization to make Rhino Android compatible
|
||||||
|
rhino.setOptimizationLevel(-1);
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
//register logger callback for console.log and console.error
|
||||||
|
ScriptableObject.defineClass(scope, LoggerCallback.class);
|
||||||
|
Scriptable myLogger = rhino.newObject(scope, "LoggerCallback", null);
|
||||||
|
scope.put("console2", scope, myLogger);
|
||||||
|
rhino.evaluateString(scope, readFile("OpenAPSAMA/loggerhelper.js"), "JavaScript", 0, null);
|
||||||
|
|
||||||
|
//set module parent
|
||||||
|
rhino.evaluateString(scope, "var module = {\"parent\":Boolean(1)};", "JavaScript", 0, null);
|
||||||
|
rhino.evaluateString(scope, "var round_basal = function round_basal(basal, profile) { return basal; };", "JavaScript", 0, null);
|
||||||
|
rhino.evaluateString(scope, "require = function() {return round_basal;};", "JavaScript", 0, null);
|
||||||
|
|
||||||
|
//generate functions "determine_basal" and "setTempBasal"
|
||||||
|
rhino.evaluateString(scope, readFile("OpenAPSSMB/determine-basal.js"), "JavaScript", 0, null);
|
||||||
|
rhino.evaluateString(scope, readFile("OpenAPSSMB/basal-set-temp.js"), "setTempBasal.js", 0, null);
|
||||||
|
Object determineBasalObj = scope.get("determine_basal", scope);
|
||||||
|
Object setTempBasalFunctionsObj = scope.get("tempBasalFunctions", scope);
|
||||||
|
|
||||||
|
//call determine-basal
|
||||||
|
if (determineBasalObj instanceof Function && setTempBasalFunctionsObj instanceof NativeObject) {
|
||||||
|
Function determineBasalJS = (Function) determineBasalObj;
|
||||||
|
|
||||||
|
//prepare parameters
|
||||||
|
Object[] params = new Object[]{
|
||||||
|
makeParam(mGlucoseStatus, rhino, scope),
|
||||||
|
makeParam(mCurrentTemp, rhino, scope),
|
||||||
|
makeParamArray(mIobData, rhino, scope),
|
||||||
|
makeParam(mProfile, rhino, scope),
|
||||||
|
makeParam(mAutosensData, rhino, scope),
|
||||||
|
makeParam(mMealData, rhino, scope),
|
||||||
|
setTempBasalFunctionsObj,
|
||||||
|
new Boolean(mMicrobolusAllowed),
|
||||||
|
makeParam(null, rhino, scope) // reservoir data as undefined
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
NativeObject jsResult = (NativeObject) determineBasalJS.call(rhino, scope, scope, params);
|
||||||
|
scriptDebug = LoggerCallback.getScriptDebug();
|
||||||
|
|
||||||
|
// Parse the jsResult object to a JSON-String
|
||||||
|
String result = NativeJSON.stringify(rhino, scope, jsResult, null, null).toString();
|
||||||
|
if (Config.logAPSResult)
|
||||||
|
log.debug("Result: " + result);
|
||||||
|
try {
|
||||||
|
determineBasalResultSMB = new DetermineBasalResultSMB(new JSONObject(result));
|
||||||
|
} catch (JSONException e) {
|
||||||
|
log.error("Unhandled exception", e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.debug("Problem loading JS Functions");
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.debug("IOException");
|
||||||
|
} catch (RhinoException e) {
|
||||||
|
log.error("RhinoException: (" + e.lineNumber() + "," + e.columnNumber() + ") " + e.toString());
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
log.error(e.toString());
|
||||||
|
} catch (InstantiationException e) {
|
||||||
|
log.error(e.toString());
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
log.error(e.toString());
|
||||||
|
} finally {
|
||||||
|
Context.exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
storedGlucoseStatus = mGlucoseStatus.toString();
|
||||||
|
storedIobData = mIobData.toString();
|
||||||
|
storedCurrentTemp = mCurrentTemp.toString();
|
||||||
|
storedProfile = mProfile.toString();
|
||||||
|
storedMeal_data = mMealData.toString();
|
||||||
|
|
||||||
|
return determineBasalResultSMB;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
String getGlucoseStatusParam() {
|
||||||
|
return storedGlucoseStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getCurrentTempParam() {
|
||||||
|
return storedCurrentTemp;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getIobDataParam() {
|
||||||
|
return storedIobData;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getProfileParam() {
|
||||||
|
return storedProfile;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getMealDataParam() {
|
||||||
|
return storedMeal_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getAutosensDataParam() {
|
||||||
|
return storedAutosens_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getMicroBolusAllowedParam() {
|
||||||
|
return storedMicroBolusAllowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getScriptDebug() {
|
||||||
|
return scriptDebug;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setData(Profile profile,
|
||||||
|
double maxIob,
|
||||||
|
double maxBasal,
|
||||||
|
double minBg,
|
||||||
|
double maxBg,
|
||||||
|
double targetBg,
|
||||||
|
double basalrate,
|
||||||
|
IobTotal[] iobArray,
|
||||||
|
GlucoseStatus glucoseStatus,
|
||||||
|
MealData mealData,
|
||||||
|
double autosensDataRatio,
|
||||||
|
boolean tempTargetSet,
|
||||||
|
boolean microBolusAllowed
|
||||||
|
) throws JSONException {
|
||||||
|
|
||||||
|
String units = profile.getUnits();
|
||||||
|
|
||||||
|
mProfile = new JSONObject();
|
||||||
|
|
||||||
|
mProfile.put("max_iob", maxIob);
|
||||||
|
mProfile.put("dia", profile.getDia());
|
||||||
|
mProfile.put("type", "current");
|
||||||
|
mProfile.put("max_daily_basal", profile.getMaxDailyBasal());
|
||||||
|
mProfile.put("max_basal", maxBasal);
|
||||||
|
mProfile.put("min_bg", minBg);
|
||||||
|
mProfile.put("max_bg", maxBg);
|
||||||
|
mProfile.put("target_bg", targetBg);
|
||||||
|
mProfile.put("carb_ratio", profile.getIc());
|
||||||
|
mProfile.put("sens", Profile.toMgdl(profile.getIsf().doubleValue(), units));
|
||||||
|
mProfile.put("max_daily_safety_multiplier", SP.getInt("openapsama_max_daily_safety_multiplier", 3));
|
||||||
|
mProfile.put("current_basal_safety_multiplier", SP.getInt("openapsama_current_basal_safety_multiplier", 4));
|
||||||
|
|
||||||
|
mProfile.put("high_temptarget_raises_sensitivity", SMBDefaults.high_temptarget_raises_sensitivity);
|
||||||
|
mProfile.put("low_temptarget_lowers_sensitivity", SMBDefaults.low_temptarget_lowers_sensitivity);
|
||||||
|
mProfile.put("sensitivity_raises_target", SMBDefaults.sensitivity_raises_target);
|
||||||
|
mProfile.put("resistance_lowers_target", SMBDefaults.resistance_lowers_target);
|
||||||
|
mProfile.put("adv_target_adjustments", SMBDefaults.adv_target_adjustments);
|
||||||
|
mProfile.put("exercise_mode", SMBDefaults.exercise_mode);
|
||||||
|
mProfile.put("half_basal_exercise_target", SMBDefaults.half_basal_exercise_target);
|
||||||
|
mProfile.put("maxCOB", SMBDefaults.maxCOB);
|
||||||
|
mProfile.put("skip_neutral_temps", SMBDefaults.skip_neutral_temps);
|
||||||
|
mProfile.put("min_5m_carbimpact", SP.getInt("openapsama_min_5m_carbimpact", SMBDefaults.min_5m_carbimpact));
|
||||||
|
mProfile.put("remainingCarbsCap", SMBDefaults.remainingCarbsCap);
|
||||||
|
mProfile.put("enableUAM", SP.getBoolean(R.string.key_use_uam, false));
|
||||||
|
mProfile.put("A52_risk_enable", SMBDefaults.A52_risk_enable);
|
||||||
|
mProfile.put("enableSMB_with_COB", SP.getBoolean(R.string.key_use_smb, false) && SP.getBoolean(R.string.key_enableSMB_with_COB, false));
|
||||||
|
mProfile.put("enableSMB_with_temptarget", SP.getBoolean(R.string.key_use_smb, false) && SP.getBoolean(R.string.key_enableSMB_with_temptarget, false));
|
||||||
|
mProfile.put("allowSMB_with_high_temptarget", SP.getBoolean(R.string.key_use_smb, false) && SP.getBoolean(R.string.key_allowSMB_with_high_temptarget, false));
|
||||||
|
mProfile.put("enableSMB_always", SP.getBoolean(R.string.key_use_smb, false) && SP.getBoolean(R.string.key_enableSMB_always, false) && ConfigBuilderPlugin.getActiveBgSource().advancedFilteringSupported());
|
||||||
|
mProfile.put("enableSMB_after_carbs", SP.getBoolean(R.string.key_use_smb, false) && SP.getBoolean(R.string.key_enableSMB_after_carbs, false) && ConfigBuilderPlugin.getActiveBgSource().advancedFilteringSupported());
|
||||||
|
mProfile.put("maxSMBBasalMinutes", SP.getInt("key_smbmaxminutes", SMBDefaults.maxSMBBasalMinutes));
|
||||||
|
mProfile.put("carbsReqThreshold", SMBDefaults.carbsReqThreshold);
|
||||||
|
|
||||||
|
mProfile.put("current_basal", basalrate);
|
||||||
|
mProfile.put("temptargetSet", tempTargetSet);
|
||||||
|
mProfile.put("autosens_max", SafeParse.stringToDouble(SP.getString("openapsama_autosens_max", "1.2")));
|
||||||
|
|
||||||
|
if (units.equals(Constants.MMOL)) {
|
||||||
|
mProfile.put("out_units", "mmol/L");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
mCurrentTemp = new JSONObject();
|
||||||
|
mCurrentTemp.put("temp", "absolute");
|
||||||
|
mCurrentTemp.put("duration", MainApp.getConfigBuilder().getTempBasalRemainingMinutesFromHistory());
|
||||||
|
mCurrentTemp.put("rate", MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory());
|
||||||
|
|
||||||
|
// as we have non default temps longer than 30 mintues
|
||||||
|
TemporaryBasal tempBasal = MainApp.getConfigBuilder().getTempBasalFromHistory(System.currentTimeMillis());
|
||||||
|
if (tempBasal != null) {
|
||||||
|
mCurrentTemp.put("minutesrunning", tempBasal.getRealDuration());
|
||||||
|
}
|
||||||
|
|
||||||
|
mIobData = IobCobCalculatorPlugin.convertToJSONArray(iobArray);
|
||||||
|
|
||||||
|
mGlucoseStatus = new JSONObject();
|
||||||
|
mGlucoseStatus.put("glucose", glucoseStatus.glucose);
|
||||||
|
|
||||||
|
if (SP.getBoolean("always_use_shortavg", false)) {
|
||||||
|
mGlucoseStatus.put("delta", glucoseStatus.short_avgdelta);
|
||||||
|
} else {
|
||||||
|
mGlucoseStatus.put("delta", glucoseStatus.delta);
|
||||||
|
}
|
||||||
|
mGlucoseStatus.put("short_avgdelta", glucoseStatus.short_avgdelta);
|
||||||
|
mGlucoseStatus.put("long_avgdelta", glucoseStatus.long_avgdelta);
|
||||||
|
mGlucoseStatus.put("date", glucoseStatus.date);
|
||||||
|
|
||||||
|
mMealData = new JSONObject();
|
||||||
|
mMealData.put("carbs", mealData.carbs);
|
||||||
|
mMealData.put("boluses", mealData.boluses);
|
||||||
|
mMealData.put("mealCOB", mealData.mealCOB);
|
||||||
|
mMealData.put("slopeFromMaxDeviation", mealData.slopeFromMaxDeviation);
|
||||||
|
mMealData.put("slopeFromMinDeviation", mealData.slopeFromMinDeviation);
|
||||||
|
mMealData.put("lastBolusTime", mealData.lastBolusTime);
|
||||||
|
mMealData.put("lastCarbTime", mealData.lastCarbTime);
|
||||||
|
|
||||||
|
|
||||||
|
if (MainApp.getConfigBuilder().isAMAModeEnabled()) {
|
||||||
|
mAutosensData = new JSONObject();
|
||||||
|
;
|
||||||
|
mAutosensData.put("ratio", autosensDataRatio);
|
||||||
|
} else {
|
||||||
|
mAutosensData = null;
|
||||||
|
}
|
||||||
|
mMicrobolusAllowed = microBolusAllowed;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object makeParam(JSONObject jsonObject, Context rhino, Scriptable scope) {
|
||||||
|
|
||||||
|
if (jsonObject == null) return Undefined.instance;
|
||||||
|
|
||||||
|
Object param = NativeJSON.parse(rhino, scope, jsonObject.toString(), new Callable() {
|
||||||
|
@Override
|
||||||
|
public Object call(Context context, Scriptable scriptable, Scriptable scriptable1, Object[] objects) {
|
||||||
|
return objects[1];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return param;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object makeParamArray(JSONArray jsonArray, Context rhino, Scriptable scope) {
|
||||||
|
//Object param = NativeJSON.parse(rhino, scope, "{myarray: " + jsonArray.toString() + " }", new Callable() {
|
||||||
|
Object param = NativeJSON.parse(rhino, scope, jsonArray.toString(), new Callable() {
|
||||||
|
@Override
|
||||||
|
public Object call(Context context, Scriptable scriptable, Scriptable scriptable1, Object[] objects) {
|
||||||
|
return objects[1];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return param;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String readFile(String filename) throws IOException {
|
||||||
|
byte[] bytes = mScriptReader.readFile(filename);
|
||||||
|
String string = new String(bytes, "UTF-8");
|
||||||
|
if (string.startsWith("#!/usr/bin/env node")) {
|
||||||
|
string = string.substring(20);
|
||||||
|
}
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,104 @@
|
||||||
|
package info.nightscout.androidaps.plugins.OpenAPSSMB;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.plugins.Loop.APSResult;
|
||||||
|
import info.nightscout.utils.DateUtil;
|
||||||
|
|
||||||
|
public class DetermineBasalResultSMB extends APSResult {
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(DetermineBasalResultSMB.class);
|
||||||
|
|
||||||
|
public double eventualBG;
|
||||||
|
public double snoozeBG;
|
||||||
|
public double insulinReq;
|
||||||
|
public double carbsReq;
|
||||||
|
|
||||||
|
public DetermineBasalResultSMB(JSONObject result) {
|
||||||
|
this();
|
||||||
|
date = new Date();
|
||||||
|
json = result;
|
||||||
|
try {
|
||||||
|
if (result.has("error")) {
|
||||||
|
reason = result.getString("error");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
reason = result.getString("reason");
|
||||||
|
if (result.has("eventualBG")) eventualBG = result.getDouble("eventualBG");
|
||||||
|
if (result.has("snoozeBG")) snoozeBG = result.getDouble("snoozeBG");
|
||||||
|
if (result.has("insulinReq")) insulinReq = result.getDouble("insulinReq");
|
||||||
|
if (result.has("carbsReq")) carbsReq = result.getDouble("carbsReq");
|
||||||
|
|
||||||
|
if (result.has("rate") && result.has("duration")) {
|
||||||
|
tempBasalReqested = true;
|
||||||
|
rate = result.getDouble("rate");
|
||||||
|
if (rate < 0d) rate = 0d;
|
||||||
|
duration = result.getInt("duration");
|
||||||
|
} else {
|
||||||
|
rate = -1;
|
||||||
|
duration = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.has("units")) {
|
||||||
|
bolusRequested = true;
|
||||||
|
smb = result.getDouble("units");
|
||||||
|
} else {
|
||||||
|
smb = 0d;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.has("deliverAt")) {
|
||||||
|
String date = result.getString("deliverAt");
|
||||||
|
try {
|
||||||
|
deliverAt = DateUtil.fromISODateString(date).getTime();
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("Error parsing 'deliverAt' date: " + date, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (JSONException e) {
|
||||||
|
log.error("Error parsing determine-basal result JSON", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public DetermineBasalResultSMB() {
|
||||||
|
hasPredictions = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DetermineBasalResultSMB clone() {
|
||||||
|
DetermineBasalResultSMB newResult = new DetermineBasalResultSMB();
|
||||||
|
newResult.reason = reason;
|
||||||
|
newResult.rate = rate;
|
||||||
|
newResult.duration = duration;
|
||||||
|
newResult.tempBasalReqested = tempBasalReqested;
|
||||||
|
newResult.bolusRequested = bolusRequested;
|
||||||
|
newResult.rate = rate;
|
||||||
|
newResult.duration = duration;
|
||||||
|
newResult.smb = smb;
|
||||||
|
newResult.deliverAt = deliverAt;
|
||||||
|
|
||||||
|
try {
|
||||||
|
newResult.json = new JSONObject(json.toString());
|
||||||
|
} catch (JSONException e) {
|
||||||
|
log.error("Error clone parsing determine-basal result", e);
|
||||||
|
}
|
||||||
|
newResult.eventualBG = eventualBG;
|
||||||
|
newResult.snoozeBG = snoozeBG;
|
||||||
|
newResult.date = date;
|
||||||
|
return newResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JSONObject json() {
|
||||||
|
try {
|
||||||
|
return new JSONObject(this.json.toString());
|
||||||
|
} catch (JSONException e) {
|
||||||
|
log.error("Error converting determine-basal result to JSON", e);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,142 @@
|
||||||
|
package info.nightscout.androidaps.plugins.OpenAPSSMB;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.crashlytics.android.answers.Answers;
|
||||||
|
import com.crashlytics.android.answers.CustomEvent;
|
||||||
|
import com.squareup.otto.Subscribe;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
import info.nightscout.androidaps.R;
|
||||||
|
import info.nightscout.androidaps.plugins.Common.SubscriberFragment;
|
||||||
|
import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateGui;
|
||||||
|
import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateResultGui;
|
||||||
|
import info.nightscout.utils.JSONFormatter;
|
||||||
|
|
||||||
|
public class OpenAPSSMBFragment extends SubscriberFragment implements View.OnClickListener {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(OpenAPSSMBFragment.class);
|
||||||
|
|
||||||
|
Button run;
|
||||||
|
TextView lastRunView;
|
||||||
|
TextView glucoseStatusView;
|
||||||
|
TextView currentTempView;
|
||||||
|
TextView iobDataView;
|
||||||
|
TextView profileView;
|
||||||
|
TextView mealDataView;
|
||||||
|
TextView autosensDataView;
|
||||||
|
TextView resultView;
|
||||||
|
TextView scriptdebugView;
|
||||||
|
TextView requestView;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
|
Bundle savedInstanceState) {
|
||||||
|
View view = inflater.inflate(R.layout.openapsama_fragment, container, false);
|
||||||
|
|
||||||
|
run = (Button) view.findViewById(R.id.openapsma_run);
|
||||||
|
run.setOnClickListener(this);
|
||||||
|
lastRunView = (TextView) view.findViewById(R.id.openapsma_lastrun);
|
||||||
|
glucoseStatusView = (TextView) view.findViewById(R.id.openapsma_glucosestatus);
|
||||||
|
currentTempView = (TextView) view.findViewById(R.id.openapsma_currenttemp);
|
||||||
|
iobDataView = (TextView) view.findViewById(R.id.openapsma_iobdata);
|
||||||
|
profileView = (TextView) view.findViewById(R.id.openapsma_profile);
|
||||||
|
mealDataView = (TextView) view.findViewById(R.id.openapsma_mealdata);
|
||||||
|
autosensDataView = (TextView) view.findViewById(R.id.openapsma_autosensdata);
|
||||||
|
scriptdebugView = (TextView) view.findViewById(R.id.openapsma_scriptdebugdata);
|
||||||
|
resultView = (TextView) view.findViewById(R.id.openapsma_result);
|
||||||
|
requestView = (TextView) view.findViewById(R.id.openapsma_request);
|
||||||
|
|
||||||
|
updateGUI();
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
switch (view.getId()) {
|
||||||
|
case R.id.openapsma_run:
|
||||||
|
OpenAPSSMBPlugin.getPlugin().invoke("OpenAPSSMB button");
|
||||||
|
Answers.getInstance().logCustom(new CustomEvent("OpenAPS_SMB_Run"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onStatusEvent(final EventOpenAPSUpdateGui ev) {
|
||||||
|
updateGUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onStatusEvent(final EventOpenAPSUpdateResultGui ev) {
|
||||||
|
updateResultGUI(ev.text);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void updateGUI() {
|
||||||
|
Activity activity = getActivity();
|
||||||
|
if (activity != null)
|
||||||
|
activity.runOnUiThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
OpenAPSSMBPlugin plugin = OpenAPSSMBPlugin.getPlugin();
|
||||||
|
DetermineBasalResultSMB lastAPSResult = plugin.lastAPSResult;
|
||||||
|
if (lastAPSResult != null) {
|
||||||
|
resultView.setText(JSONFormatter.format(lastAPSResult.json));
|
||||||
|
requestView.setText(lastAPSResult.toSpanned());
|
||||||
|
}
|
||||||
|
DetermineBasalAdapterSMBJS determineBasalAdapterSMBJS = plugin.lastDetermineBasalAdapterSMBJS;
|
||||||
|
if (determineBasalAdapterSMBJS != null) {
|
||||||
|
glucoseStatusView.setText(JSONFormatter.format(determineBasalAdapterSMBJS.getGlucoseStatusParam()));
|
||||||
|
currentTempView.setText(JSONFormatter.format(determineBasalAdapterSMBJS.getCurrentTempParam()));
|
||||||
|
try {
|
||||||
|
JSONArray iobArray = new JSONArray(determineBasalAdapterSMBJS.getIobDataParam());
|
||||||
|
iobDataView.setText(String.format(MainApp.sResources.getString(R.string.array_of_elements), iobArray.length()) + "\n" + JSONFormatter.format(iobArray.getString(0)));
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
iobDataView.setText("JSONException");
|
||||||
|
}
|
||||||
|
profileView.setText(JSONFormatter.format(determineBasalAdapterSMBJS.getProfileParam()));
|
||||||
|
mealDataView.setText(JSONFormatter.format(determineBasalAdapterSMBJS.getMealDataParam()));
|
||||||
|
scriptdebugView.setText(determineBasalAdapterSMBJS.getScriptDebug());
|
||||||
|
}
|
||||||
|
if (plugin.lastAPSRun != null) {
|
||||||
|
lastRunView.setText(plugin.lastAPSRun.toLocaleString());
|
||||||
|
}
|
||||||
|
if (plugin.lastAutosensResult != null) {
|
||||||
|
autosensDataView.setText(JSONFormatter.format(plugin.lastAutosensResult.json()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateResultGUI(final String text) {
|
||||||
|
Activity activity = getActivity();
|
||||||
|
if (activity != null)
|
||||||
|
activity.runOnUiThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
resultView.setText(text);
|
||||||
|
glucoseStatusView.setText("");
|
||||||
|
currentTempView.setText("");
|
||||||
|
iobDataView.setText("");
|
||||||
|
profileView.setText("");
|
||||||
|
mealDataView.setText("");
|
||||||
|
autosensDataView.setText("");
|
||||||
|
scriptdebugView.setText("");
|
||||||
|
requestView.setText("");
|
||||||
|
lastRunView.setText("");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,301 @@
|
||||||
|
package info.nightscout.androidaps.plugins.OpenAPSSMB;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.Config;
|
||||||
|
import info.nightscout.androidaps.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.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.NSUpload;
|
||||||
|
import info.nightscout.utils.Profiler;
|
||||||
|
import info.nightscout.utils.Round;
|
||||||
|
import info.nightscout.utils.SP;
|
||||||
|
import info.nightscout.utils.ToastUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 05.08.2016.
|
||||||
|
*/
|
||||||
|
public class OpenAPSSMBPlugin implements PluginBase, APSInterface {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(OpenAPSSMBPlugin.class);
|
||||||
|
|
||||||
|
// last values
|
||||||
|
DetermineBasalAdapterSMBJS lastDetermineBasalAdapterSMBJS = null;
|
||||||
|
Date lastAPSRun = null;
|
||||||
|
DetermineBasalResultSMB lastAPSResult = null;
|
||||||
|
AutosensResult lastAutosensResult = null;
|
||||||
|
|
||||||
|
boolean fragmentEnabled = false;
|
||||||
|
boolean fragmentVisible = true;
|
||||||
|
|
||||||
|
private static OpenAPSSMBPlugin openAPSSMBPlugin;
|
||||||
|
|
||||||
|
private OpenAPSSMBPlugin() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static OpenAPSSMBPlugin getPlugin() {
|
||||||
|
if (openAPSSMBPlugin == null) {
|
||||||
|
openAPSSMBPlugin = new OpenAPSSMBPlugin();
|
||||||
|
}
|
||||||
|
return openAPSSMBPlugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return MainApp.instance().getString(R.string.openapssmb);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getNameShort() {
|
||||||
|
String name = MainApp.sResources.getString(R.string.smb_shortname);
|
||||||
|
if (!name.trim().isEmpty()) {
|
||||||
|
//only if translation exists
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
// use long name as fallback
|
||||||
|
return getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEnabled(int type) {
|
||||||
|
boolean pumpCapable = ConfigBuilderPlugin.getActivePump() == null || ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable;
|
||||||
|
return type == APS && fragmentEnabled && pumpCapable;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isVisibleInTabs(int type) {
|
||||||
|
boolean pumpCapable = ConfigBuilderPlugin.getActivePump() == null || ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable;
|
||||||
|
return type == APS && fragmentVisible && pumpCapable;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canBeHidden(int type) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasFragment() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean showInList(int type) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFragmentVisible(int type, boolean fragmentVisible) {
|
||||||
|
if (type == APS) this.fragmentVisible = fragmentVisible;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getPreferencesId() {
|
||||||
|
return R.xml.pref_openapssmb;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFragmentEnabled(int type, boolean fragmentEnabled) {
|
||||||
|
if (type == APS) this.fragmentEnabled = fragmentEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getType() {
|
||||||
|
return PluginBase.APS;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getFragmentClass() {
|
||||||
|
return OpenAPSSMBFragment.class.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public APSResult getLastAPSResult() {
|
||||||
|
return lastAPSResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Date getLastAPSRun() {
|
||||||
|
return lastAPSRun;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void invoke(String initiator) {
|
||||||
|
log.debug("invoke from " + initiator);
|
||||||
|
lastAPSResult = null;
|
||||||
|
DetermineBasalAdapterSMBJS determineBasalAdapterSMBJS = null;
|
||||||
|
try {
|
||||||
|
determineBasalAdapterSMBJS = new DetermineBasalAdapterSMBJS(new ScriptReader(MainApp.instance().getBaseContext()));
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData();
|
||||||
|
Profile profile = MainApp.getConfigBuilder().getProfile();
|
||||||
|
PumpInterface pump = ConfigBuilderPlugin.getActivePump();
|
||||||
|
|
||||||
|
if (profile == null) {
|
||||||
|
MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.instance().getString(R.string.noprofileselected)));
|
||||||
|
if (Config.logAPSResult)
|
||||||
|
log.debug(MainApp.instance().getString(R.string.noprofileselected));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isEnabled(PluginBase.APS)) {
|
||||||
|
MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.instance().getString(R.string.openapsma_disabled)));
|
||||||
|
if (Config.logAPSResult)
|
||||||
|
log.debug(MainApp.instance().getString(R.string.openapsma_disabled));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (glucoseStatus == null) {
|
||||||
|
MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.instance().getString(R.string.openapsma_noglucosedata)));
|
||||||
|
if (Config.logAPSResult)
|
||||||
|
log.debug(MainApp.instance().getString(R.string.openapsma_noglucosedata));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String units = profile.getUnits();
|
||||||
|
|
||||||
|
double maxIob = SP.getDouble("openapsma_max_iob", 1.5d);
|
||||||
|
double maxBasal = SP.getDouble("openapsma_max_basal", 1d);
|
||||||
|
double minBg = Profile.toMgdl(profile.getTargetLow(), units);
|
||||||
|
double maxBg = Profile.toMgdl(profile.getTargetHigh(), units);
|
||||||
|
double targetBg = (minBg + maxBg) / 2;
|
||||||
|
|
||||||
|
minBg = Round.roundTo(minBg, 0.1d);
|
||||||
|
maxBg = Round.roundTo(maxBg, 0.1d);
|
||||||
|
|
||||||
|
Date start = new Date();
|
||||||
|
Date startPart = new Date();
|
||||||
|
IobTotal[] iobArray = IobCobCalculatorPlugin.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", 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]);
|
||||||
|
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
maxIob = verifyHardLimits(maxIob, "maxIob", 0, 7);
|
||||||
|
maxBasal = verifyHardLimits(maxBasal, "max_basal", 0.1, 10);
|
||||||
|
|
||||||
|
if (!checkOnlyHardLimits(profile.getDia(), "dia", 2, 7)) return;
|
||||||
|
if (!checkOnlyHardLimits(profile.getIc(profile.secondsFromMidnight()), "carbratio", 2, 100))
|
||||||
|
return;
|
||||||
|
if (!checkOnlyHardLimits(Profile.toMgdl(profile.getIsf().doubleValue(), units), "sens", 2, 900))
|
||||||
|
return;
|
||||||
|
if (!checkOnlyHardLimits(profile.getMaxDailyBasal(), "max_daily_basal", 0.1, 10)) return;
|
||||||
|
if (!checkOnlyHardLimits(pump.getBaseBasalRate(), "current_basal", 0.01, 5)) return;
|
||||||
|
|
||||||
|
startPart = new Date();
|
||||||
|
if (MainApp.getConfigBuilder().isAMAModeEnabled()) {
|
||||||
|
lastAutosensResult = IobCobCalculatorPlugin.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.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
package info.nightscout.androidaps.plugins.OpenAPSSMB;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 10.12.2017.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class SMBDefaults {
|
||||||
|
// CALCULATED OR FROM PREFS
|
||||||
|
|
||||||
|
// max_iob: 0 // if max_iob is not provided, will default to zero
|
||||||
|
// max_daily_safety_multiplier:3
|
||||||
|
// current_basal_safety_multiplier:4
|
||||||
|
// autosens_max:1.2
|
||||||
|
// autosens_min:0.7
|
||||||
|
|
||||||
|
// USED IN AUTOSENS
|
||||||
|
public final static boolean rewind_resets_autosens = true; // reset autosensitivity to neutral for awhile after each pump rewind
|
||||||
|
|
||||||
|
// USED IN TARGETS
|
||||||
|
// by default the higher end of the target range is used only for avoiding bolus wizard overcorrections
|
||||||
|
// use wide_bg_target_range: true to force neutral temps over a wider range of eventualBGs
|
||||||
|
public final static boolean wide_bg_target_range = false; // by default use only the low end of the pump's BG target range as OpenAPS target
|
||||||
|
|
||||||
|
// USED IN AUTOTUNE
|
||||||
|
public final static double autotune_isf_adjustmentFraction = 1.0; // keep autotune ISF closer to pump ISF via a weighted average of fullNewISF and pumpISF. 1.0 allows full adjustment, 0 is no adjustment from pump ISF.
|
||||||
|
public final static double remainingCarbsFraction = 1.0; // fraction of carbs we'll assume will absorb over 4h if we don't yet see carb absorption
|
||||||
|
|
||||||
|
// USED IN DETERMINE_BASAL
|
||||||
|
public final static boolean low_temptarget_lowers_sensitivity = false; // lower sensitivity for temptargets <= 99.
|
||||||
|
public final static boolean high_temptarget_raises_sensitivity = false; // raise sensitivity for temptargets >= 111. synonym for exercise_mode
|
||||||
|
public final static boolean sensitivity_raises_target = true; // raise BG target when autosens detects sensitivity
|
||||||
|
public final static boolean resistance_lowers_target = false; // lower BG target when autosens detects resistance
|
||||||
|
public final static boolean adv_target_adjustments = false; // lower target automatically when BG and eventualBG are high
|
||||||
|
public final static boolean exercise_mode = false; // when true, > 105 mg/dL high temp target adjusts sensitivityRatio for exercise_mode. This majorly changes the behavior of high temp targets from before. synonmym for high_temptarget_raises_sensitivity
|
||||||
|
public final static int half_basal_exercise_target = 160; // when temptarget is 160 mg/dL *and* exercise_mode=true, run 50% basal at this level (120 = 75%; 140 = 60%)
|
||||||
|
// create maxCOB and default it to 120 because that's the most a typical body can absorb over 4 hours.
|
||||||
|
// (If someone enters more carbs or stacks more; OpenAPS will just truncate dosing based on 120.
|
||||||
|
// Essentially, this just limits AMA/SMB as a safety cap against excessive COB entry)
|
||||||
|
public final static int maxCOB = 120;
|
||||||
|
public final static boolean skip_neutral_temps = true; // ***** default false in oref1 ***** if true, don't set neutral temps
|
||||||
|
// unsuspend_if_no_temp:false // if true, pump will un-suspend after a zero temp finishes
|
||||||
|
// bolussnooze_dia_divisor:2 // bolus snooze decays after 1/2 of DIA
|
||||||
|
public final static int min_5m_carbimpact = 8; // mg/dL per 5m (8 mg/dL/5m corresponds to 24g/hr at a CSF of 4 mg/dL/g (x/5*60/4))
|
||||||
|
public final static int remainingCarbsCap = 90; // max carbs we'll assume will absorb over 4h if we don't yet see carb absorption
|
||||||
|
// WARNING: use SMB with caution: it can and will automatically bolus up to max_iob worth of extra insulin
|
||||||
|
// enableUAM:true // enable detection of unannounced meal carb absorption
|
||||||
|
public final static boolean A52_risk_enable = false;
|
||||||
|
//public final static boolean enableSMB_with_COB = true; // ***** default false in oref1 ***** enable supermicrobolus while COB is positive
|
||||||
|
//public final static boolean enableSMB_with_temptarget = true; // ***** default false in oref1 ***** enable supermicrobolus for eating soon temp targets
|
||||||
|
// *** WARNING *** DO NOT USE enableSMB_always or enableSMB_after_carbs with xDrip+, Libre, or similar
|
||||||
|
// xDrip+, LimiTTer, etc. do not properly filter out high-noise SGVs
|
||||||
|
// Using SMB overnight with such data sources risks causing a dangerous overdose of insulin
|
||||||
|
// if the CGM sensor reads falsely high and doesn't come down as actual BG does
|
||||||
|
// public final static boolean enableSMB_always = false; // always enable supermicrobolus (unless disabled by high temptarget)
|
||||||
|
// *** WARNING *** DO NOT USE enableSMB_always or enableSMB_after_carbs with xDrip+, Libre, or similar
|
||||||
|
//public final static boolean enableSMB_after_carbs = false; // enable supermicrobolus for 6h after carbs, even with 0 COB
|
||||||
|
//public final static boolean allowSMB_with_high_temptarget = false; // allow supermicrobolus (if otherwise enabled) even with high temp targets
|
||||||
|
public final static int maxSMBBasalMinutes = 30; // maximum minutes of basal that can be delivered as a single SMB with uncovered COB
|
||||||
|
// curve:"rapid-acting" // Supported curves: "bilinear", "rapid-acting" (Novolog, Novorapid, Humalog, Apidra) and "ultra-rapid" (Fiasp)
|
||||||
|
// useCustomPeakTime:false // allows changing insulinPeakTime
|
||||||
|
// insulinPeakTime:75 // number of minutes after a bolus activity peaks. defaults to 55m for Fiasp if useCustomPeakTime: false
|
||||||
|
public final static int carbsReqThreshold = 1; // grams of carbsReq to trigger a pushover
|
||||||
|
// offline_hotspot:false // enabled an offline-only local wifi hotspot if no Internet available
|
||||||
|
}
|
|
@ -93,8 +93,6 @@ import info.nightscout.androidaps.plugins.Loop.LoopPlugin;
|
||||||
import info.nightscout.androidaps.plugins.Loop.events.EventNewOpenLoopNotification;
|
import info.nightscout.androidaps.plugins.Loop.events.EventNewOpenLoopNotification;
|
||||||
import info.nightscout.androidaps.plugins.NSClientInternal.broadcasts.BroadcastAckAlarm;
|
import info.nightscout.androidaps.plugins.NSClientInternal.broadcasts.BroadcastAckAlarm;
|
||||||
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSDeviceStatus;
|
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSDeviceStatus;
|
||||||
import info.nightscout.androidaps.plugins.OpenAPSAMA.DetermineBasalResultAMA;
|
|
||||||
import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin;
|
|
||||||
import info.nightscout.androidaps.plugins.Overview.Dialogs.CalibrationDialog;
|
import info.nightscout.androidaps.plugins.Overview.Dialogs.CalibrationDialog;
|
||||||
import info.nightscout.androidaps.plugins.Overview.Dialogs.ErrorHelperActivity;
|
import info.nightscout.androidaps.plugins.Overview.Dialogs.ErrorHelperActivity;
|
||||||
import info.nightscout.androidaps.plugins.Overview.Dialogs.NewTreatmentDialog;
|
import info.nightscout.androidaps.plugins.Overview.Dialogs.NewTreatmentDialog;
|
||||||
|
@ -675,7 +673,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
|
||||||
if (ConfigBuilderPlugin.getActiveLoop() != null) {
|
if (ConfigBuilderPlugin.getActiveLoop() != null) {
|
||||||
ConfigBuilderPlugin.getActiveLoop().invoke("Accept temp button", false);
|
ConfigBuilderPlugin.getActiveLoop().invoke("Accept temp button", false);
|
||||||
final LoopPlugin.LastRun finalLastRun = LoopPlugin.lastRun;
|
final LoopPlugin.LastRun finalLastRun = LoopPlugin.lastRun;
|
||||||
if (finalLastRun != null && finalLastRun.lastAPSRun != null && finalLastRun.constraintsProcessed.changeRequested) {
|
if (finalLastRun != null && finalLastRun.lastAPSRun != null && finalLastRun.constraintsProcessed.isChangeRequested()) {
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
|
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
|
||||||
builder.setTitle(getContext().getString(R.string.confirmation));
|
builder.setTitle(getContext().getString(R.string.confirmation));
|
||||||
builder.setMessage(getContext().getString(R.string.setbasalquestion) + "\n" + finalLastRun.constraintsProcessed);
|
builder.setMessage(getContext().getString(R.string.setbasalquestion) + "\n" + finalLastRun.constraintsProcessed);
|
||||||
|
@ -1106,7 +1104,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
|
||||||
boolean showAcceptButton = !MainApp.getConfigBuilder().isClosedModeEnabled(); // Open mode needed
|
boolean showAcceptButton = !MainApp.getConfigBuilder().isClosedModeEnabled(); // Open mode needed
|
||||||
showAcceptButton = showAcceptButton && finalLastRun != null && finalLastRun.lastAPSRun != null; // aps result must exist
|
showAcceptButton = showAcceptButton && finalLastRun != null && finalLastRun.lastAPSRun != null; // aps result must exist
|
||||||
showAcceptButton = showAcceptButton && (finalLastRun.lastOpenModeAccept == null || finalLastRun.lastOpenModeAccept.getTime() < finalLastRun.lastAPSRun.getTime()); // never accepted or before last result
|
showAcceptButton = showAcceptButton && (finalLastRun.lastOpenModeAccept == null || finalLastRun.lastOpenModeAccept.getTime() < finalLastRun.lastAPSRun.getTime()); // never accepted or before last result
|
||||||
showAcceptButton = showAcceptButton && finalLastRun.constraintsProcessed.changeRequested; // change is requested
|
showAcceptButton = showAcceptButton && finalLastRun.constraintsProcessed.isChangeRequested(); // change is requested
|
||||||
|
|
||||||
if (showAcceptButton && pump.isInitialized() && !pump.isSuspended() && ConfigBuilderPlugin.getActiveLoop() != null) {
|
if (showAcceptButton && pump.isInitialized() && !pump.isSuspended() && ConfigBuilderPlugin.getActiveLoop() != null) {
|
||||||
acceptTempLayout.setVisibility(View.VISIBLE);
|
acceptTempLayout.setVisibility(View.VISIBLE);
|
||||||
|
@ -1284,8 +1282,8 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
|
||||||
cobView.setText(cobText);
|
cobView.setText(cobText);
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean showPrediction = showPredictionCheckbox.isChecked() && finalLastRun != null && finalLastRun.constraintsProcessed.getClass().equals(DetermineBasalResultAMA.class);
|
final boolean predictionsAvailable = finalLastRun != null && finalLastRun.request.hasPredictions;
|
||||||
if (MainApp.getSpecificPlugin(OpenAPSAMAPlugin.class) != null && MainApp.getSpecificPlugin(OpenAPSAMAPlugin.class).isEnabled(PluginBase.APS)) {
|
if (predictionsAvailable) {
|
||||||
showPredictionCheckbox.setVisibility(View.VISIBLE);
|
showPredictionCheckbox.setVisibility(View.VISIBLE);
|
||||||
showPredictionLabel.setVisibility(View.VISIBLE);
|
showPredictionLabel.setVisibility(View.VISIBLE);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1343,8 +1341,8 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
|
||||||
final long toTime;
|
final long toTime;
|
||||||
final long fromTime;
|
final long fromTime;
|
||||||
final long endTime;
|
final long endTime;
|
||||||
if (showPrediction) {
|
if (predictionsAvailable && showPredictionCheckbox.isChecked()) {
|
||||||
int predHours = (int) (Math.ceil(((DetermineBasalResultAMA) finalLastRun.constraintsProcessed).getLatestPredictionsTime() - System.currentTimeMillis()) / (60 * 60 * 1000));
|
int predHours = (int) (Math.ceil(finalLastRun.constraintsProcessed.getLatestPredictionsTime() - System.currentTimeMillis()) / (60 * 60 * 1000));
|
||||||
predHours = Math.min(2, predHours);
|
predHours = Math.min(2, predHours);
|
||||||
predHours = Math.max(0, predHours);
|
predHours = Math.max(0, predHours);
|
||||||
hoursToFetch = rangeToDisplay - predHours;
|
hoursToFetch = rangeToDisplay - predHours;
|
||||||
|
@ -1370,8 +1368,8 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
|
||||||
graphData.addInRangeArea(fromTime, endTime, lowLine, highLine);
|
graphData.addInRangeArea(fromTime, endTime, lowLine, highLine);
|
||||||
|
|
||||||
// **** BG ****
|
// **** BG ****
|
||||||
if (showPrediction)
|
if (predictionsAvailable && showPredictionCheckbox.isChecked())
|
||||||
graphData.addBgReadings(fromTime, toTime, lowLine, highLine, (DetermineBasalResultAMA) finalLastRun.constraintsProcessed);
|
graphData.addBgReadings(fromTime, toTime, lowLine, highLine, finalLastRun.constraintsProcessed);
|
||||||
else
|
else
|
||||||
graphData.addBgReadings(fromTime, toTime, lowLine, highLine, null);
|
graphData.addBgReadings(fromTime, toTime, lowLine, highLine, null);
|
||||||
|
|
||||||
|
@ -1398,6 +1396,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
|
||||||
boolean useCobForScale = false;
|
boolean useCobForScale = false;
|
||||||
boolean useDevForScale = false;
|
boolean useDevForScale = false;
|
||||||
boolean useRatioForScale = false;
|
boolean useRatioForScale = false;
|
||||||
|
boolean useDSForScale = false;
|
||||||
|
|
||||||
if (showIobCheckbox.isChecked()) {
|
if (showIobCheckbox.isChecked()) {
|
||||||
useIobForScale = true;
|
useIobForScale = true;
|
||||||
|
@ -1407,6 +1406,8 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
|
||||||
useDevForScale = true;
|
useDevForScale = true;
|
||||||
} else if (showRatiosCheckbox.isChecked()) {
|
} else if (showRatiosCheckbox.isChecked()) {
|
||||||
useRatioForScale = true;
|
useRatioForScale = true;
|
||||||
|
} else if (Config.displayDeviationSlope) {
|
||||||
|
useDSForScale = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (showIobCheckbox.isChecked())
|
if (showIobCheckbox.isChecked())
|
||||||
|
@ -1417,6 +1418,8 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
|
||||||
secondGraphData.addDeviations(fromTime, now, useDevForScale, 1d);
|
secondGraphData.addDeviations(fromTime, now, useDevForScale, 1d);
|
||||||
if (showRatiosCheckbox.isChecked())
|
if (showRatiosCheckbox.isChecked())
|
||||||
secondGraphData.addRatio(fromTime, now, useRatioForScale, 1d);
|
secondGraphData.addRatio(fromTime, now, useRatioForScale, 1d);
|
||||||
|
if (Config.displayDeviationSlope)
|
||||||
|
secondGraphData.addDeviationSlope(fromTime, now, useDSForScale, 1d);
|
||||||
|
|
||||||
// **** NOW line ****
|
// **** NOW line ****
|
||||||
// set manual x bounds to have nice steps
|
// set manual x bounds to have nice steps
|
||||||
|
@ -1429,7 +1432,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
|
||||||
activity.runOnUiThread(new Runnable() {
|
activity.runOnUiThread(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (showIobCheckbox.isChecked() || showCobCheckbox.isChecked() || showDeviationsCheckbox.isChecked() || showRatiosCheckbox.isChecked()) {
|
if (showIobCheckbox.isChecked() || showCobCheckbox.isChecked() || showDeviationsCheckbox.isChecked() || showRatiosCheckbox.isChecked() || Config.displayDeviationSlope) {
|
||||||
iobGraph.setVisibility(View.VISIBLE);
|
iobGraph.setVisibility(View.VISIBLE);
|
||||||
} else {
|
} else {
|
||||||
iobGraph.setVisibility(View.GONE);
|
iobGraph.setVisibility(View.GONE);
|
||||||
|
|
|
@ -12,7 +12,6 @@ import com.jjoe64.graphview.series.LineGraphSeries;
|
||||||
import com.jjoe64.graphview.series.Series;
|
import com.jjoe64.graphview.series.Series;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import info.nightscout.androidaps.Constants;
|
import info.nightscout.androidaps.Constants;
|
||||||
|
@ -28,7 +27,7 @@ import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||||
import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData;
|
import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData;
|
||||||
import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin;
|
import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin;
|
||||||
import info.nightscout.androidaps.plugins.IobCobCalculator.BasalData;
|
import info.nightscout.androidaps.plugins.IobCobCalculator.BasalData;
|
||||||
import info.nightscout.androidaps.plugins.OpenAPSAMA.DetermineBasalResultAMA;
|
import info.nightscout.androidaps.plugins.Loop.APSResult;
|
||||||
import info.nightscout.androidaps.plugins.Overview.graphExtensions.AreaGraphSeries;
|
import info.nightscout.androidaps.plugins.Overview.graphExtensions.AreaGraphSeries;
|
||||||
import info.nightscout.androidaps.plugins.Overview.graphExtensions.DataPointWithLabelInterface;
|
import info.nightscout.androidaps.plugins.Overview.graphExtensions.DataPointWithLabelInterface;
|
||||||
import info.nightscout.androidaps.plugins.Overview.graphExtensions.DoubleDataPoint;
|
import info.nightscout.androidaps.plugins.Overview.graphExtensions.DoubleDataPoint;
|
||||||
|
@ -56,7 +55,7 @@ public class GraphData {
|
||||||
this.graph = graph;
|
this.graph = graph;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addBgReadings(long fromTime, long toTime, double lowLine, double highLine, DetermineBasalResultAMA amaResult) {
|
public void addBgReadings(long fromTime, long toTime, double lowLine, double highLine, APSResult apsResult) {
|
||||||
double maxBgValue = 0d;
|
double maxBgValue = 0d;
|
||||||
bgReadingsArray = MainApp.getDbHelper().getBgreadingsDataFromTime(fromTime, true);
|
bgReadingsArray = MainApp.getDbHelper().getBgreadingsDataFromTime(fromTime, true);
|
||||||
List<DataPointWithLabelInterface> bgListArray = new ArrayList<>();
|
List<DataPointWithLabelInterface> bgListArray = new ArrayList<>();
|
||||||
|
@ -65,14 +64,12 @@ public class GraphData {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator<BgReading> it = bgReadingsArray.iterator();
|
for (BgReading bg : bgReadingsArray) {
|
||||||
while (it.hasNext()) {
|
|
||||||
BgReading bg = it.next();
|
|
||||||
if (bg.value > maxBgValue) maxBgValue = bg.value;
|
if (bg.value > maxBgValue) maxBgValue = bg.value;
|
||||||
bgListArray.add(bg);
|
bgListArray.add(bg);
|
||||||
}
|
}
|
||||||
if (amaResult != null) {
|
if (apsResult != null) {
|
||||||
List<BgReading> predArray = amaResult.getPredictions();
|
List<BgReading> predArray = apsResult.getPredictions();
|
||||||
bgListArray.addAll(predArray);
|
bgListArray.addAll(predArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,7 +264,7 @@ public class GraphData {
|
||||||
addSeries(new PointsWithLabelGraphSeries<>(treatmentsArray));
|
addSeries(new PointsWithLabelGraphSeries<>(treatmentsArray));
|
||||||
}
|
}
|
||||||
|
|
||||||
double getNearestBg(long date) {
|
private double getNearestBg(long date) {
|
||||||
double bg = 0;
|
double bg = 0;
|
||||||
for (int r = bgReadingsArray.size() - 1; r >= 0; r--) {
|
for (int r = bgReadingsArray.size() - 1; r >= 0; r--) {
|
||||||
BgReading reading = bgReadingsArray.get(r);
|
BgReading reading = bgReadingsArray.get(r);
|
||||||
|
@ -401,21 +398,21 @@ public class GraphData {
|
||||||
|
|
||||||
// scale in % of vertical size (like 0.3)
|
// scale in % of vertical size (like 0.3)
|
||||||
public void addRatio(long fromTime, long toTime, boolean useForScale, double scale) {
|
public void addRatio(long fromTime, long toTime, boolean useForScale, double scale) {
|
||||||
LineGraphSeries<DataPoint> ratioSeries;
|
LineGraphSeries<ScaledDataPoint> ratioSeries;
|
||||||
List<DataPoint> ratioArray = new ArrayList<>();
|
List<ScaledDataPoint> ratioArray = new ArrayList<>();
|
||||||
Double maxRatioValueFound = 0d;
|
Double maxRatioValueFound = 0d;
|
||||||
Scale ratioScale = new Scale(-1d);
|
Scale ratioScale = new Scale(-1d);
|
||||||
|
|
||||||
for (long time = fromTime; time <= toTime; time += 5 * 60 * 1000L) {
|
for (long time = fromTime; time <= toTime; time += 5 * 60 * 1000L) {
|
||||||
AutosensData autosensData = IobCobCalculatorPlugin.getAutosensData(time);
|
AutosensData autosensData = IobCobCalculatorPlugin.getAutosensData(time);
|
||||||
if (autosensData != null) {
|
if (autosensData != null) {
|
||||||
ratioArray.add(new DataPoint(time, autosensData.autosensRatio));
|
ratioArray.add(new ScaledDataPoint(time, autosensData.autosensRatio, ratioScale));
|
||||||
maxRatioValueFound = Math.max(maxRatioValueFound, Math.abs(autosensData.autosensRatio));
|
maxRatioValueFound = Math.max(maxRatioValueFound, Math.abs(autosensData.autosensRatio));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// RATIOS
|
// RATIOS
|
||||||
DataPoint[] ratioData = new DataPoint[ratioArray.size()];
|
ScaledDataPoint[] ratioData = new ScaledDataPoint[ratioArray.size()];
|
||||||
ratioData = ratioArray.toArray(ratioData);
|
ratioData = ratioArray.toArray(ratioData);
|
||||||
ratioSeries = new LineGraphSeries<>(ratioData);
|
ratioSeries = new LineGraphSeries<>(ratioData);
|
||||||
ratioSeries.setColor(MainApp.sResources.getColor(R.color.ratio));
|
ratioSeries.setColor(MainApp.sResources.getColor(R.color.ratio));
|
||||||
|
@ -429,6 +426,50 @@ public class GraphData {
|
||||||
addSeries(ratioSeries);
|
addSeries(ratioSeries);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// scale in % of vertical size (like 0.3)
|
||||||
|
public void addDeviationSlope(long fromTime, long toTime, boolean useForScale, double scale) {
|
||||||
|
LineGraphSeries<ScaledDataPoint> dsMaxSeries;
|
||||||
|
LineGraphSeries<ScaledDataPoint> dsMinSeries;
|
||||||
|
List<ScaledDataPoint> dsMaxArray = new ArrayList<>();
|
||||||
|
List<ScaledDataPoint> dsMinArray = new ArrayList<>();
|
||||||
|
Double maxFromMaxValueFound = 0d;
|
||||||
|
Double maxFromMinValueFound = 0d;
|
||||||
|
Scale dsMaxScale = new Scale();
|
||||||
|
Scale dsMinScale = new Scale();
|
||||||
|
|
||||||
|
for (long time = fromTime; time <= toTime; time += 5 * 60 * 1000L) {
|
||||||
|
AutosensData autosensData = IobCobCalculatorPlugin.getAutosensData(time);
|
||||||
|
if (autosensData != null) {
|
||||||
|
dsMaxArray.add(new ScaledDataPoint(time, autosensData.slopeFromMaxDeviation, dsMaxScale));
|
||||||
|
dsMinArray.add(new ScaledDataPoint(time, autosensData.slopeFromMinDeviation, dsMinScale));
|
||||||
|
maxFromMaxValueFound = Math.max(maxFromMaxValueFound, Math.abs(autosensData.slopeFromMaxDeviation));
|
||||||
|
maxFromMinValueFound = Math.max(maxFromMinValueFound, Math.abs(autosensData.slopeFromMinDeviation));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Slopes
|
||||||
|
ScaledDataPoint[] ratioMaxData = new ScaledDataPoint[dsMaxArray.size()];
|
||||||
|
ratioMaxData = dsMaxArray.toArray(ratioMaxData);
|
||||||
|
dsMaxSeries = new LineGraphSeries<>(ratioMaxData);
|
||||||
|
dsMaxSeries.setColor(Color.MAGENTA);
|
||||||
|
dsMaxSeries.setThickness(3);
|
||||||
|
|
||||||
|
ScaledDataPoint[] ratioMinData = new ScaledDataPoint[dsMinArray.size()];
|
||||||
|
ratioMinData = dsMinArray.toArray(ratioMinData);
|
||||||
|
dsMinSeries = new LineGraphSeries<>(ratioMinData);
|
||||||
|
dsMinSeries.setColor(Color.YELLOW);
|
||||||
|
dsMinSeries.setThickness(3);
|
||||||
|
|
||||||
|
if (useForScale)
|
||||||
|
maxY = Math.max(maxFromMaxValueFound, maxFromMinValueFound);
|
||||||
|
|
||||||
|
dsMaxScale.setMultiplier(maxY * scale / maxFromMaxValueFound);
|
||||||
|
dsMinScale.setMultiplier(maxY * scale / maxFromMinValueFound);
|
||||||
|
|
||||||
|
addSeries(dsMaxSeries);
|
||||||
|
addSeries(dsMinSeries);
|
||||||
|
}
|
||||||
|
|
||||||
// scale in % of vertical size (like 0.3)
|
// scale in % of vertical size (like 0.3)
|
||||||
public void addNowLine(long now) {
|
public void addNowLine(long now) {
|
||||||
LineGraphSeries<DataPoint> seriesNow;
|
LineGraphSeries<DataPoint> seriesNow;
|
||||||
|
|
|
@ -55,4 +55,5 @@ public interface DataPointWithLabelInterface extends DataPointInterface{
|
||||||
PointsWithLabelGraphSeries.Shape getShape();
|
PointsWithLabelGraphSeries.Shape getShape();
|
||||||
float getSize();
|
float getSize();
|
||||||
int getColor();
|
int getColor();
|
||||||
|
int getSecondColor();
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,17 +60,12 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
|
||||||
* You can also render a custom drawing via {@link com.jjoe64.graphview.series.PointsGraphSeries.CustomShape}
|
* You can also render a custom drawing via {@link com.jjoe64.graphview.series.PointsGraphSeries.CustomShape}
|
||||||
*/
|
*/
|
||||||
public enum Shape {
|
public enum Shape {
|
||||||
/**
|
BG,
|
||||||
* draws a point / circle
|
PREDICTION,
|
||||||
*/
|
|
||||||
POINT,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* draws a triangle
|
|
||||||
*/
|
|
||||||
TRIANGLE,
|
TRIANGLE,
|
||||||
RECTANGLE,
|
RECTANGLE,
|
||||||
BOLUS,
|
BOLUS,
|
||||||
|
SMB,
|
||||||
EXTENDEDBOLUS,
|
EXTENDEDBOLUS,
|
||||||
PROFILE,
|
PROFILE,
|
||||||
MBG,
|
MBG,
|
||||||
|
@ -202,9 +197,19 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
|
||||||
|
|
||||||
// draw data point
|
// draw data point
|
||||||
if (!overdraw) {
|
if (!overdraw) {
|
||||||
if (value.getShape() == Shape.POINT) {
|
if (value.getShape() == Shape.BG) {
|
||||||
|
mPaint.setStyle(Paint.Style.FILL);
|
||||||
mPaint.setStrokeWidth(0);
|
mPaint.setStrokeWidth(0);
|
||||||
canvas.drawCircle(endX, endY, scaledPxSize, mPaint);
|
canvas.drawCircle(endX, endY, scaledPxSize, mPaint);
|
||||||
|
} else if (value.getShape() == Shape.PREDICTION) {
|
||||||
|
mPaint.setColor(value.getColor());
|
||||||
|
mPaint.setStyle(Paint.Style.FILL);
|
||||||
|
mPaint.setStrokeWidth(0);
|
||||||
|
canvas.drawCircle(endX, endY, scaledPxSize, mPaint);
|
||||||
|
mPaint.setColor(value.getSecondColor());
|
||||||
|
mPaint.setStyle(Paint.Style.FILL);
|
||||||
|
mPaint.setStrokeWidth(0);
|
||||||
|
canvas.drawCircle(endX, endY, scaledPxSize / 3, mPaint);
|
||||||
} else if (value.getShape() == Shape.RECTANGLE) {
|
} else if (value.getShape() == Shape.RECTANGLE) {
|
||||||
canvas.drawRect(endX-scaledPxSize, endY-scaledPxSize, endX+scaledPxSize, endY+scaledPxSize, mPaint);
|
canvas.drawRect(endX-scaledPxSize, endY-scaledPxSize, endX+scaledPxSize, endY+scaledPxSize, mPaint);
|
||||||
} else if (value.getShape() == Shape.TRIANGLE) {
|
} else if (value.getShape() == Shape.TRIANGLE) {
|
||||||
|
@ -225,6 +230,14 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
|
||||||
if (value.getLabel() != null) {
|
if (value.getLabel() != null) {
|
||||||
drawLabel45(endX, endY, value, canvas);
|
drawLabel45(endX, endY, value, canvas);
|
||||||
}
|
}
|
||||||
|
} else if (value.getShape() == Shape.SMB) {
|
||||||
|
mPaint.setStrokeWidth(2);
|
||||||
|
Point[] points = new Point[3];
|
||||||
|
points[0] = new Point((int)endX, (int)(endY-value.getSize()));
|
||||||
|
points[1] = new Point((int)(endX+value.getSize()), (int)(endY+value.getSize()*0.67));
|
||||||
|
points[2] = new Point((int)(endX-value.getSize()), (int)(endY+value.getSize()*0.67));
|
||||||
|
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
|
||||||
|
drawArrows(points, canvas, mPaint);
|
||||||
} else if (value.getShape() == Shape.EXTENDEDBOLUS) {
|
} else if (value.getShape() == Shape.EXTENDEDBOLUS) {
|
||||||
mPaint.setStrokeWidth(0);
|
mPaint.setStrokeWidth(0);
|
||||||
if (value.getLabel() != null) {
|
if (value.getLabel() != null) {
|
||||||
|
|
|
@ -82,4 +82,9 @@ public class SourceDexcomG5Plugin implements PluginBase, BgSourceInterface {
|
||||||
public int getPreferencesId() {
|
public int getPreferencesId() {
|
||||||
return R.xml.pref_dexcomg5;
|
return R.xml.pref_dexcomg5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean advancedFilteringSupported() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,4 +83,8 @@ public class SourceGlimpPlugin implements PluginBase, BgSourceInterface {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean advancedFilteringSupported() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,4 +83,8 @@ public class SourceMM640gPlugin implements PluginBase, BgSourceInterface {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean advancedFilteringSupported() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,4 +85,8 @@ public class SourceNSClientPlugin implements PluginBase, BgSourceInterface {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean advancedFilteringSupported() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,4 +84,8 @@ public class SourceXdripPlugin implements PluginBase, BgSourceInterface {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean advancedFilteringSupported() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import info.nightscout.androidaps.Config;
|
import info.nightscout.androidaps.Config;
|
||||||
|
@ -197,6 +198,8 @@ public class TreatmentsPlugin implements PluginBase, TreatmentsInterface {
|
||||||
Iob tIOB = t.iobCalc(time, dia);
|
Iob tIOB = t.iobCalc(time, dia);
|
||||||
total.iob += tIOB.iobContrib;
|
total.iob += tIOB.iobContrib;
|
||||||
total.activity += tIOB.activityContrib;
|
total.activity += tIOB.activityContrib;
|
||||||
|
if (t.date > total.lastBolusTime)
|
||||||
|
total.lastBolusTime = t.date;
|
||||||
if (!t.isSMB) {
|
if (!t.isSMB) {
|
||||||
// instead of dividing the DIA that only worked on the bilinear curves,
|
// instead of dividing the DIA that only worked on the bilinear curves,
|
||||||
// multiply the time the treatment is seen active.
|
// multiply the time the treatment is seen active.
|
||||||
|
@ -204,9 +207,6 @@ public class TreatmentsPlugin implements PluginBase, TreatmentsInterface {
|
||||||
long snoozeTime = t.date + (long) (timeSinceTreatment * SP.getDouble("openapsama_bolussnooze_dia_divisor", 2.0));
|
long snoozeTime = t.date + (long) (timeSinceTreatment * SP.getDouble("openapsama_bolussnooze_dia_divisor", 2.0));
|
||||||
Iob bIOB = t.iobCalc(snoozeTime, dia);
|
Iob bIOB = t.iobCalc(snoozeTime, dia);
|
||||||
total.bolussnooze += bIOB.iobContrib;
|
total.bolussnooze += bIOB.iobContrib;
|
||||||
} else {
|
|
||||||
total.basaliob += t.insulin;
|
|
||||||
total.microBolusIOB += tIOB.iobContrib;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,6 +244,7 @@ public class TreatmentsPlugin implements PluginBase, TreatmentsInterface {
|
||||||
if (t > dia_ago && t <= now) {
|
if (t > dia_ago && t <= now) {
|
||||||
if (treatment.carbs >= 1) {
|
if (treatment.carbs >= 1) {
|
||||||
result.carbs += treatment.carbs;
|
result.carbs += treatment.carbs;
|
||||||
|
result.lastCarbTime = t;
|
||||||
}
|
}
|
||||||
if (treatment.insulin > 0 && treatment.mealBolus) {
|
if (treatment.insulin > 0 && treatment.mealBolus) {
|
||||||
result.boluses += treatment.insulin;
|
result.boluses += treatment.insulin;
|
||||||
|
@ -254,7 +255,10 @@ public class TreatmentsPlugin implements PluginBase, TreatmentsInterface {
|
||||||
AutosensData autosensData = IobCobCalculatorPlugin.getLastAutosensDataSynchronized("getMealData()");
|
AutosensData autosensData = IobCobCalculatorPlugin.getLastAutosensDataSynchronized("getMealData()");
|
||||||
if (autosensData != null) {
|
if (autosensData != null) {
|
||||||
result.mealCOB = autosensData.cob;
|
result.mealCOB = autosensData.cob;
|
||||||
|
result.slopeFromMinDeviation = autosensData.slopeFromMinDeviation;
|
||||||
|
result.slopeFromMaxDeviation = autosensData.slopeFromMaxDeviation;
|
||||||
}
|
}
|
||||||
|
result.lastBolusTime = getLastBolusTime();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -276,6 +280,18 @@ public class TreatmentsPlugin implements PluginBase, TreatmentsInterface {
|
||||||
return in5minback;
|
return in5minback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getLastBolusTime() {
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
long last = 0;
|
||||||
|
for (Treatment t : treatments) {
|
||||||
|
if (t.date > last && t.insulin > 0 && t.isValid && t.date <= now)
|
||||||
|
last = t.date;
|
||||||
|
}
|
||||||
|
log.debug("Last bolus time: " + new Date(last).toLocaleString());
|
||||||
|
return last;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isInHistoryRealTempBasalInProgress() {
|
public boolean isInHistoryRealTempBasalInProgress() {
|
||||||
return getRealTempBasalFromHistory(System.currentTimeMillis()) != null;
|
return getRealTempBasalFromHistory(System.currentTimeMillis()) != null;
|
||||||
|
@ -327,6 +343,12 @@ public class TreatmentsPlugin implements PluginBase, TreatmentsInterface {
|
||||||
IobTotal calc = t.iobCalc(time);
|
IobTotal calc = t.iobCalc(time);
|
||||||
//log.debug("BasalIOB " + new Date(time) + " >>> " + calc.basaliob);
|
//log.debug("BasalIOB " + new Date(time) + " >>> " + calc.basaliob);
|
||||||
total.plus(calc);
|
total.plus(calc);
|
||||||
|
if (!t.isEndingEvent()) {
|
||||||
|
total.lastTempDate = t.date;
|
||||||
|
total.lastTempDuration = t.durationInMinutes;
|
||||||
|
total.lastTempRate = t.tempBasalConvertedToAbsolute(t.date);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ConfigBuilderPlugin.getActivePump().isFakingTempsByExtendedBoluses()) {
|
if (ConfigBuilderPlugin.getActivePump().isFakingTempsByExtendedBoluses()) {
|
||||||
|
@ -337,6 +359,12 @@ public class TreatmentsPlugin implements PluginBase, TreatmentsInterface {
|
||||||
if (e.date > time) continue;
|
if (e.date > time) continue;
|
||||||
IobTotal calc = e.iobCalc(time);
|
IobTotal calc = e.iobCalc(time);
|
||||||
totalExt.plus(calc);
|
totalExt.plus(calc);
|
||||||
|
TemporaryBasal t = new TemporaryBasal(e);
|
||||||
|
if (!t.isEndingEvent() && t.date > total.lastTempDate) {
|
||||||
|
total.lastTempDate = t.date;
|
||||||
|
total.lastTempDuration = t.durationInMinutes;
|
||||||
|
total.lastTempRate = t.tempBasalConvertedToAbsolute(t.date);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Convert to basal iob
|
// Convert to basal iob
|
||||||
|
|
|
@ -81,7 +81,7 @@ public class TreatmentsBolusFragment extends SubscriberFragment implements View.
|
||||||
Iob iob = t.iobCalc(System.currentTimeMillis(), profile.getDia());
|
Iob iob = t.iobCalc(System.currentTimeMillis(), profile.getDia());
|
||||||
holder.iob.setText(DecimalFormatter.to2Decimal(iob.iobContrib) + " U");
|
holder.iob.setText(DecimalFormatter.to2Decimal(iob.iobContrib) + " U");
|
||||||
holder.activity.setText(DecimalFormatter.to3Decimal(iob.activityContrib) + " U");
|
holder.activity.setText(DecimalFormatter.to3Decimal(iob.activityContrib) + " U");
|
||||||
holder.mealOrCorrection.setText(t.mealBolus ? MainApp.sResources.getString(R.string.mealbolus) : MainApp.sResources.getString(R.string.correctionbous));
|
holder.mealOrCorrection.setText(t.isSMB ? "SMB" : t.mealBolus ? MainApp.sResources.getString(R.string.mealbolus) : MainApp.sResources.getString(R.string.correctionbous));
|
||||||
holder.ph.setVisibility(t.source == Source.PUMP ? View.VISIBLE : View.GONE);
|
holder.ph.setVisibility(t.source == Source.PUMP ? View.VISIBLE : View.GONE);
|
||||||
holder.ns.setVisibility(NSUpload.isIdValid(t._id) ? View.VISIBLE : View.GONE);
|
holder.ns.setVisibility(NSUpload.isIdValid(t._id) ? View.VISIBLE : View.GONE);
|
||||||
holder.invalid.setVisibility(t.isValid ? View.GONE : View.VISIBLE);
|
holder.invalid.setVisibility(t.isValid ? View.GONE : View.VISIBLE);
|
||||||
|
|
|
@ -503,7 +503,7 @@ public class ActionStringHandler {
|
||||||
return "Last result not available!";
|
return "Last result not available!";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!result.changeRequested) {
|
if (!result.isChangeRequested()) {
|
||||||
ret += MainApp.sResources.getString(R.string.nochangerequested) + "\n";
|
ret += MainApp.sResources.getString(R.string.nochangerequested) + "\n";
|
||||||
} else if (result.rate == 0 && result.duration == 0) {
|
} else if (result.rate == 0 && result.duration == 0) {
|
||||||
ret += MainApp.sResources.getString(R.string.canceltemp) + "\n";
|
ret += MainApp.sResources.getString(R.string.canceltemp) + "\n";
|
||||||
|
|
|
@ -32,6 +32,7 @@ import info.nightscout.androidaps.queue.commands.CommandExtendedBolus;
|
||||||
import info.nightscout.androidaps.queue.commands.CommandLoadEvents;
|
import info.nightscout.androidaps.queue.commands.CommandLoadEvents;
|
||||||
import info.nightscout.androidaps.queue.commands.CommandLoadHistory;
|
import info.nightscout.androidaps.queue.commands.CommandLoadHistory;
|
||||||
import info.nightscout.androidaps.queue.commands.CommandReadStatus;
|
import info.nightscout.androidaps.queue.commands.CommandReadStatus;
|
||||||
|
import info.nightscout.androidaps.queue.commands.CommandSMBBolus;
|
||||||
import info.nightscout.androidaps.queue.commands.CommandSetProfile;
|
import info.nightscout.androidaps.queue.commands.CommandSetProfile;
|
||||||
import info.nightscout.androidaps.queue.commands.CommandTempBasalAbsolute;
|
import info.nightscout.androidaps.queue.commands.CommandTempBasalAbsolute;
|
||||||
import info.nightscout.androidaps.queue.commands.CommandTempBasalPercent;
|
import info.nightscout.androidaps.queue.commands.CommandTempBasalPercent;
|
||||||
|
@ -151,30 +152,35 @@ public class CommandQueue {
|
||||||
|
|
||||||
// returns true if command is queued
|
// returns true if command is queued
|
||||||
public boolean bolus(DetailedBolusInfo detailedBolusInfo, Callback callback) {
|
public boolean bolus(DetailedBolusInfo detailedBolusInfo, Callback callback) {
|
||||||
if (isRunning(Command.CommandType.BOLUS)) {
|
Command.CommandType type = detailedBolusInfo.isSMB ? Command.CommandType.SMB_BOLUS : Command.CommandType.BOLUS;
|
||||||
|
|
||||||
|
if (isRunning(type)) {
|
||||||
if (callback != null)
|
if (callback != null)
|
||||||
callback.result(executingNowError()).run();
|
callback.result(executingNowError()).run();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove all unfinished boluses
|
// remove all unfinished boluses
|
||||||
removeAll(Command.CommandType.BOLUS);
|
removeAll(type);
|
||||||
|
|
||||||
// apply constraints
|
// apply constraints
|
||||||
detailedBolusInfo.insulin = MainApp.getConfigBuilder().applyBolusConstraints(detailedBolusInfo.insulin);
|
detailedBolusInfo.insulin = MainApp.getConfigBuilder().applyBolusConstraints(detailedBolusInfo.insulin);
|
||||||
detailedBolusInfo.carbs = MainApp.getConfigBuilder().applyCarbsConstraints((int) detailedBolusInfo.carbs);
|
detailedBolusInfo.carbs = MainApp.getConfigBuilder().applyCarbsConstraints((int) detailedBolusInfo.carbs);
|
||||||
|
|
||||||
// add new command to queue
|
// add new command to queue
|
||||||
add(new CommandBolus(detailedBolusInfo, callback));
|
if (detailedBolusInfo.isSMB) {
|
||||||
|
add(new CommandSMBBolus(detailedBolusInfo, callback));
|
||||||
|
} else {
|
||||||
|
add(new CommandBolus(detailedBolusInfo, callback));
|
||||||
|
// Bring up bolus progress dialog (start here, so the dialog is shown when the bolus is requested,
|
||||||
|
// not when the Bolus command is starting. The command closes the dialog upon completion).
|
||||||
|
showBolusProgressDialog(detailedBolusInfo.insulin, detailedBolusInfo.context);
|
||||||
|
// Notify Wear about upcoming bolus
|
||||||
|
MainApp.bus().post(new EventBolusRequested(detailedBolusInfo.insulin));
|
||||||
|
}
|
||||||
|
|
||||||
notifyAboutNewCommand();
|
notifyAboutNewCommand();
|
||||||
|
|
||||||
// Notify Wear about upcoming bolus
|
|
||||||
MainApp.bus().post(new EventBolusRequested(detailedBolusInfo.insulin));
|
|
||||||
|
|
||||||
// Bring up bolus progress dialog
|
|
||||||
showBolusProgressDialog(detailedBolusInfo.insulin, detailedBolusInfo.context);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ import info.nightscout.androidaps.queue.Callback;
|
||||||
public abstract class Command {
|
public abstract class Command {
|
||||||
public enum CommandType {
|
public enum CommandType {
|
||||||
BOLUS,
|
BOLUS,
|
||||||
|
SMB_BOLUS,
|
||||||
TEMPBASAL,
|
TEMPBASAL,
|
||||||
EXTENDEDBOLUS,
|
EXTENDEDBOLUS,
|
||||||
BASALPROFILE,
|
BASALPROFILE,
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
package info.nightscout.androidaps.queue.commands;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.MainApp;
|
||||||
|
import info.nightscout.androidaps.data.DetailedBolusInfo;
|
||||||
|
import info.nightscout.androidaps.data.PumpEnactResult;
|
||||||
|
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||||
|
import info.nightscout.androidaps.plugins.Overview.Dialogs.BolusProgressDialog;
|
||||||
|
import info.nightscout.androidaps.plugins.Overview.events.EventDismissBolusprogressIfRunning;
|
||||||
|
import info.nightscout.androidaps.queue.Callback;
|
||||||
|
import info.nightscout.utils.DecimalFormatter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 09.11.2017.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class CommandSMBBolus extends Command {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(CommandSMBBolus.class);
|
||||||
|
DetailedBolusInfo detailedBolusInfo;
|
||||||
|
|
||||||
|
public CommandSMBBolus(DetailedBolusInfo detailedBolusInfo, Callback callback) {
|
||||||
|
commandType = CommandType.SMB_BOLUS;
|
||||||
|
this.detailedBolusInfo = detailedBolusInfo;
|
||||||
|
this.callback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute() {
|
||||||
|
PumpEnactResult r;
|
||||||
|
if (detailedBolusInfo.deliverAt != 0 && detailedBolusInfo.deliverAt + 60 * 1000L > System.currentTimeMillis())
|
||||||
|
r = ConfigBuilderPlugin.getActivePump().deliverTreatment(detailedBolusInfo);
|
||||||
|
else {
|
||||||
|
r = new PumpEnactResult().enacted(false).success(false).comment("SMB request too old");
|
||||||
|
log.debug("SMB bolus canceled. delivetAt=" + detailedBolusInfo.deliverAt + " now=" + System.currentTimeMillis());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (callback != null)
|
||||||
|
callback.result(r).run();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String status() {
|
||||||
|
return "SMBBOLUS " + DecimalFormatter.to1Decimal(detailedBolusInfo.insulin) + "U";
|
||||||
|
}
|
||||||
|
}
|
|
@ -199,17 +199,8 @@ public class NSUpload {
|
||||||
apsResult.json().put("timestamp", DateUtil.toISOString(lastRun.lastAPSRun));
|
apsResult.json().put("timestamp", DateUtil.toISOString(lastRun.lastAPSRun));
|
||||||
deviceStatus.suggested = apsResult.json();
|
deviceStatus.suggested = apsResult.json();
|
||||||
|
|
||||||
if (lastRun.request instanceof DetermineBasalResultMA) {
|
deviceStatus.iob = lastRun.request.iob.json();
|
||||||
DetermineBasalResultMA result = (DetermineBasalResultMA) lastRun.request;
|
deviceStatus.iob.put("time", DateUtil.toISOString(lastRun.lastAPSRun));
|
||||||
deviceStatus.iob = result.iob.json();
|
|
||||||
deviceStatus.iob.put("time", DateUtil.toISOString(lastRun.lastAPSRun));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lastRun.request instanceof DetermineBasalResultAMA) {
|
|
||||||
DetermineBasalResultAMA result = (DetermineBasalResultAMA) lastRun.request;
|
|
||||||
deviceStatus.iob = result.iob.json();
|
|
||||||
deviceStatus.iob.put("time", DateUtil.toISOString(lastRun.lastAPSRun));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lastRun.setByPump != null && lastRun.setByPump.enacted) { // enacted
|
if (lastRun.setByPump != null && lastRun.setByPump.enacted) { // enacted
|
||||||
deviceStatus.enacted = lastRun.request.json();
|
deviceStatus.enacted = lastRun.request.json();
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
<color name="iob">#FFFB8C00</color>
|
<color name="iob">#FFFB8C00</color>
|
||||||
<color name="bolus">#FFFFCC03</color>
|
<color name="bolus">#FFFFCC03</color>
|
||||||
<color name="cob">#8BC34A</color>
|
<color name="cob">#8BC34A</color>
|
||||||
|
<color name="uam">#ffea00</color>
|
||||||
|
<color name="zt">#ff9500</color>
|
||||||
<color name="ratio">#FFFFFF</color>
|
<color name="ratio">#FFFFFF</color>
|
||||||
<color name="inrange">#00FF00</color>
|
<color name="inrange">#00FF00</color>
|
||||||
<color name="low">#FF0000</color>
|
<color name="low">#FF0000</color>
|
||||||
|
|
|
@ -692,6 +692,14 @@
|
||||||
<string name="careportal_pump_label">PUMP</string>
|
<string name="careportal_pump_label">PUMP</string>
|
||||||
<string name="overview_newtempbasal_basalabsolute">Basal value [U/h]</string>
|
<string name="overview_newtempbasal_basalabsolute">Basal value [U/h]</string>
|
||||||
<string name="careportal_newnstreatment_duration_min_label">Duration [min]</string>
|
<string name="careportal_newnstreatment_duration_min_label">Duration [min]</string>
|
||||||
|
<string name="openapssmb">OpenAPS SMB</string>
|
||||||
|
<string name="smb_shortname">SMB</string>
|
||||||
|
<string name="key_use_smb">use_smb</string>
|
||||||
|
<string name="key_use_uam">use_uam</string>
|
||||||
|
<string name="enableuam">Enable UAM</string>
|
||||||
|
<string name="enablesmb">Enable SMB</string>
|
||||||
|
<string name="enablesmb_summary">Use Super Micro Boluses instead of temp basal for faster action</string>
|
||||||
|
<string name="enableuam_summary">Detection of Unannounced meals</string>
|
||||||
<string name="key_insulin_oref_peak" translatable="false">insulin_oref_peak</string>
|
<string name="key_insulin_oref_peak" translatable="false">insulin_oref_peak</string>
|
||||||
<string name="insulin_oref_peak">IOB Curve Peak Time</string>
|
<string name="insulin_oref_peak">IOB Curve Peak Time</string>
|
||||||
<string name="insulin_peak_time">Peak Time [min]</string>
|
<string name="insulin_peak_time">Peak Time [min]</string>
|
||||||
|
@ -786,6 +794,9 @@
|
||||||
<string name="customapp">Customized APK for download</string>
|
<string name="customapp">Customized APK for download</string>
|
||||||
<string name="wear_detailed_delta_title">Show detailed delta</string>
|
<string name="wear_detailed_delta_title">Show detailed delta</string>
|
||||||
<string name="wear_detailed_delta_summary">Show delta with one more decimal place</string>
|
<string name="wear_detailed_delta_summary">Show delta with one more decimal place</string>
|
||||||
|
<string name="smbmaxminutes">45 60 75 90 105 120</string>
|
||||||
|
<string name="smbmaxminutes_summary">Max minutes of basal to limit SMB to</string>
|
||||||
|
<string name="key_smbmaxminutes" translatable="false">smbmaxminutes</string>
|
||||||
<string name="unsupportedfirmware">Unsupported pump firmware</string>
|
<string name="unsupportedfirmware">Unsupported pump firmware</string>
|
||||||
<string name="dexcomg5_xdripupload_title">Send BG data to xDrip+</string>
|
<string name="dexcomg5_xdripupload_title">Send BG data to xDrip+</string>
|
||||||
<string name="key_dexcomg5_xdripupload" translatable="false">dexcomg5_xdripupload</string>
|
<string name="key_dexcomg5_xdripupload" translatable="false">dexcomg5_xdripupload</string>
|
||||||
|
@ -901,5 +912,21 @@
|
||||||
<string name="day">day</string>
|
<string name="day">day</string>
|
||||||
<string name="week">week</string>
|
<string name="week">week</string>
|
||||||
<string name="time_plural">s</string>
|
<string name="time_plural">s</string>
|
||||||
|
<string name="key_enableSMB_always" translatable="false">enableSMB_always</string>
|
||||||
|
<string name="key_enableSMB_with_COB" translatable="false">enableSMB_with_COB</string>
|
||||||
|
<string name="key_enableSMB_with_temptarget" translatable="false">enableSMB_with_temptarget</string>
|
||||||
|
<string name="key_enableSMB_after_carbs" translatable="false">enableSMB_after_carbs</string>
|
||||||
|
<string name="key_allowSMB_with_high_temptarget" translatable="false">enableSMB_with_high_temptarget</string>
|
||||||
|
<string name="enablesmbalways">Enable SMB always</string>
|
||||||
|
<string name="enablesmbalways_summary">Enable SMB always independently to boluses. Possible only with BG source with nice filtering of data like G5</string>
|
||||||
|
<string name="enablesmbaftercarbs">Enable SMB after carbs</string>
|
||||||
|
<string name="enablesmbaftercarbs_summary">Enable SMB for 6h after carbs, even with 0 COB. Possible only with BG source with nice filtering of data like G5</string>
|
||||||
|
<string name="enablesmbwithcob">Enable SMB with COB</string>
|
||||||
|
<string name="enablesmbwithcob_summary">Enable SMB when there is COB active.</string>
|
||||||
|
<string name="enablesmbwithtemptarget">Enable SMB with temp targets</string>
|
||||||
|
<string name="enablesmbwithtemptarget_summary">Enable SMB when there is temp target active (eating soon, exercise)</string>
|
||||||
|
<string name="enablesmbwithhightemptarget">Enable SMB with high temp targets</string>
|
||||||
|
<string name="enablesmbwithhightemptarget_summary">Enable SMB when there is high temp target active (exercise)</string>
|
||||||
|
<string name="let_temp_basal_run">Let current temp basal run</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
||||||
|
|
|
@ -4,125 +4,113 @@
|
||||||
<PreferenceCategory
|
<PreferenceCategory
|
||||||
android:key="advanced"
|
android:key="advanced"
|
||||||
android:title="@string/advancedsettings_title">
|
android:title="@string/advancedsettings_title">
|
||||||
<PreferenceScreen
|
<PreferenceScreen android:title="@string/advancedsettings_title">
|
||||||
android:title="@string/advancedsettings_title">
|
<PreferenceCategory android:title="@string/nightscout">
|
||||||
<PreferenceCategory
|
|
||||||
android:title="@string/nightscout">
|
|
||||||
<SwitchPreference
|
<SwitchPreference
|
||||||
android:defaultValue="false"
|
android:defaultValue="false"
|
||||||
android:key="@string/key_ns_upload_only"
|
android:key="@string/key_ns_upload_only"
|
||||||
android:title="@string/ns_upload_only"
|
android:summary="@string/ns_upload_only_summary"
|
||||||
android:summary="@string/ns_upload_only_summary"/>
|
android:title="@string/ns_upload_only" />
|
||||||
<SwitchPreference
|
<SwitchPreference
|
||||||
android:defaultValue="false"
|
android:defaultValue="false"
|
||||||
android:key="@string/key_ns_noupload"
|
android:key="@string/key_ns_noupload"
|
||||||
android:title="@string/ns_noupload"
|
android:summary="@string/ns_noupload_summary"
|
||||||
android:summary="@string/ns_noupload_summary"/>
|
android:title="@string/ns_noupload" />
|
||||||
<SwitchPreference
|
<SwitchPreference
|
||||||
android:defaultValue="false"
|
android:defaultValue="false"
|
||||||
android:key="ns_sync_use_absolute"
|
android:key="ns_sync_use_absolute"
|
||||||
android:title="@string/ns_sync_use_absolute_title" />
|
android:title="@string/ns_sync_use_absolute_title" />
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
<PreferenceCategory
|
<PreferenceCategory android:title="@string/superbolus">
|
||||||
android:title="@string/superbolus">
|
|
||||||
<SwitchPreference
|
<SwitchPreference
|
||||||
android:defaultValue="false"
|
android:defaultValue="false"
|
||||||
android:key="@string/key_usesuperbolus"
|
android:key="@string/key_usesuperbolus"
|
||||||
android:title="@string/enablesuperbolus"
|
android:summary="@string/enablesuperbolus_summary"
|
||||||
android:summary="@string/enablesuperbolus_summary"/>
|
android:title="@string/enablesuperbolus" />
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
<PreferenceCategory
|
<PreferenceCategory android:title="@string/openapsma">
|
||||||
android:title="@string/openapsma">
|
|
||||||
<SwitchPreference
|
<SwitchPreference
|
||||||
android:defaultValue="false"
|
android:defaultValue="false"
|
||||||
android:key="always_use_shortavg"
|
android:key="always_use_shortavg"
|
||||||
android:title="@string/always_use_shortavg"
|
android:summary="@string/always_use_shortavg_summary"
|
||||||
android:summary="@string/always_use_shortavg_summary"/>
|
android:title="@string/always_use_shortavg" />
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
<PreferenceCategory
|
<PreferenceCategory android:title="OpenAPS preferences.json">
|
||||||
android:title="OpenAPS preferences.json">
|
<Preference android:summary="@string/openapsama_link_to_preferncejson_doc_txt">
|
||||||
<Preference
|
|
||||||
android:summary="@string/openapsama_link_to_preferncejson_doc_txt" >
|
|
||||||
<intent
|
<intent
|
||||||
android:action="android.intent.action.VIEW"
|
android:action="android.intent.action.VIEW"
|
||||||
android:data="@string/openapsama_link_to_preferncejson_doc" />
|
android:data="@string/openapsama_link_to_preferncejson_doc" />
|
||||||
</Preference>
|
</Preference>
|
||||||
<com.andreabaccega.widget.ValidatingEditTextPreference
|
<com.andreabaccega.widget.ValidatingEditTextPreference
|
||||||
validate:testType="numericRange"
|
|
||||||
validate:minNumber="1"
|
|
||||||
validate:maxNumber="10"
|
|
||||||
android:digits="0123456789.,"
|
|
||||||
android:defaultValue="3"
|
android:defaultValue="3"
|
||||||
android:selectAllOnFocus="true"
|
|
||||||
android:inputType="number"
|
|
||||||
android:maxLines="20"
|
|
||||||
android:title="@string/openapsama_max_daily_safety_multiplier"
|
|
||||||
android:dialogMessage="@string/openapsama_max_daily_safety_multiplier_summary"
|
android:dialogMessage="@string/openapsama_max_daily_safety_multiplier_summary"
|
||||||
android:key="openapsama_max_daily_safety_multiplier" />
|
|
||||||
<com.andreabaccega.widget.ValidatingEditTextPreference
|
|
||||||
validate:testType="numericRange"
|
|
||||||
validate:minNumber="1"
|
|
||||||
validate:maxNumber="10"
|
|
||||||
android:digits="0123456789.,"
|
android:digits="0123456789.,"
|
||||||
android:defaultValue="4"
|
|
||||||
android:selectAllOnFocus="true"
|
|
||||||
android:singleLine="true"
|
|
||||||
android:inputType="number"
|
android:inputType="number"
|
||||||
|
android:key="openapsama_max_daily_safety_multiplier"
|
||||||
android:maxLines="20"
|
android:maxLines="20"
|
||||||
android:title="@string/openapsama_current_basal_safety_multiplier"
|
|
||||||
android:dialogMessage="@string/openapsama_current_basal_safety_multiplier_summary"
|
|
||||||
android:key="openapsama_current_basal_safety_multiplier" />
|
|
||||||
<com.andreabaccega.widget.ValidatingEditTextPreference
|
|
||||||
validate:testType="floatNumericRange"
|
|
||||||
validate:floatminNumber="0.5"
|
|
||||||
validate:floatmaxNumber="3"
|
|
||||||
android:digits="0123456789.,"
|
|
||||||
android:defaultValue="1.2"
|
|
||||||
android:selectAllOnFocus="true"
|
android:selectAllOnFocus="true"
|
||||||
android:singleLine="true"
|
android:title="@string/openapsama_max_daily_safety_multiplier"
|
||||||
android:inputType="numberDecimal"
|
|
||||||
android:maxLines="20"
|
|
||||||
android:title="@string/openapsama_autosens_max"
|
|
||||||
android:dialogMessage="@string/openapsama_autosens_max_summary"
|
|
||||||
android:key="openapsama_autosens_max" />
|
|
||||||
<com.andreabaccega.widget.ValidatingEditTextPreference
|
|
||||||
validate:testType="floatNumericRange"
|
|
||||||
validate:floatminNumber="0.1"
|
|
||||||
validate:floatmaxNumber="1.0"
|
|
||||||
android:defaultValue="0.7"
|
|
||||||
android:selectAllOnFocus="true"
|
|
||||||
android:singleLine="true"
|
|
||||||
android:inputType="numberDecimal"
|
|
||||||
android:maxLines="20"
|
|
||||||
android:title="@string/openapsama_autosens_min"
|
|
||||||
android:dialogMessage="@string/openapsama_autosens_min_summary"
|
|
||||||
android:key="openapsama_autosens_min" />
|
|
||||||
<SwitchPreference
|
|
||||||
android:defaultValue="true"
|
|
||||||
android:key="openapsama_autosens_adjusttargets"
|
|
||||||
android:title="@string/openapsama_autosens_adjusttargets"
|
|
||||||
android:summary="@string/openapsama_autosens_adjusttargets_summary"/>
|
|
||||||
<com.andreabaccega.widget.ValidatingEditTextPreference
|
|
||||||
validate:testType="floatNumericRange"
|
|
||||||
validate:minNumber="1"
|
|
||||||
validate:maxNumber="10"
|
validate:maxNumber="10"
|
||||||
|
validate:minNumber="1"
|
||||||
|
validate:testType="numericRange" />
|
||||||
|
<com.andreabaccega.widget.ValidatingEditTextPreference
|
||||||
|
android:defaultValue="4"
|
||||||
|
android:dialogMessage="@string/openapsama_current_basal_safety_multiplier_summary"
|
||||||
android:digits="0123456789.,"
|
android:digits="0123456789.,"
|
||||||
android:defaultValue="2"
|
android:inputType="number"
|
||||||
|
android:key="openapsama_current_basal_safety_multiplier"
|
||||||
|
android:maxLines="20"
|
||||||
android:selectAllOnFocus="true"
|
android:selectAllOnFocus="true"
|
||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
|
android:title="@string/openapsama_current_basal_safety_multiplier"
|
||||||
|
validate:maxNumber="10"
|
||||||
|
validate:minNumber="1"
|
||||||
|
validate:testType="numericRange" />
|
||||||
|
<com.andreabaccega.widget.ValidatingEditTextPreference
|
||||||
|
android:defaultValue="1.2"
|
||||||
|
android:dialogMessage="@string/openapsama_autosens_max_summary"
|
||||||
|
android:digits="0123456789.,"
|
||||||
android:inputType="numberDecimal"
|
android:inputType="numberDecimal"
|
||||||
|
android:key="openapsama_autosens_max"
|
||||||
android:maxLines="20"
|
android:maxLines="20"
|
||||||
android:title="@string/openapsama_bolussnooze_dia_divisor"
|
android:selectAllOnFocus="true"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:title="@string/openapsama_autosens_max"
|
||||||
|
validate:floatmaxNumber="3"
|
||||||
|
validate:floatminNumber="0.5"
|
||||||
|
validate:testType="floatNumericRange" />
|
||||||
|
<com.andreabaccega.widget.ValidatingEditTextPreference
|
||||||
|
android:defaultValue="0.7"
|
||||||
|
android:dialogMessage="@string/openapsama_autosens_min_summary"
|
||||||
|
android:inputType="numberDecimal"
|
||||||
|
android:key="openapsama_autosens_min"
|
||||||
|
android:maxLines="20"
|
||||||
|
android:selectAllOnFocus="true"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:title="@string/openapsama_autosens_min"
|
||||||
|
validate:floatmaxNumber="1.0"
|
||||||
|
validate:floatminNumber="0.1"
|
||||||
|
validate:testType="floatNumericRange" />
|
||||||
|
<com.andreabaccega.widget.ValidatingEditTextPreference
|
||||||
|
android:defaultValue="2"
|
||||||
android:dialogMessage="@string/openapsama_bolussnooze_dia_divisor_summary"
|
android:dialogMessage="@string/openapsama_bolussnooze_dia_divisor_summary"
|
||||||
android:key="openapsama_bolussnooze_dia_divisor" />
|
android:digits="0123456789.,"
|
||||||
|
android:inputType="numberDecimal"
|
||||||
|
android:key="openapsama_bolussnooze_dia_divisor"
|
||||||
|
android:maxLines="20"
|
||||||
|
android:selectAllOnFocus="true"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:title="@string/openapsama_bolussnooze_dia_divisor"
|
||||||
|
validate:maxNumber="10"
|
||||||
|
validate:minNumber="1"
|
||||||
|
validate:testType="floatNumericRange" />
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
<PreferenceCategory
|
<PreferenceCategory android:title="@string/profile">
|
||||||
android:title="@string/profile">
|
|
||||||
<SwitchPreference
|
<SwitchPreference
|
||||||
android:defaultValue="false"
|
android:defaultValue="false"
|
||||||
android:key="@string/key_do_not_track_profile_switch"
|
android:key="@string/key_do_not_track_profile_switch"
|
||||||
android:title="@string/do_not_track_profile_switch"
|
android:summary="@string/do_not_track_profile_switch_summary"
|
||||||
android:summary="@string/do_not_track_profile_switch_summary"/>
|
android:title="@string/do_not_track_profile_switch" />
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
<PreferenceCategory
|
<PreferenceCategory
|
||||||
|
|
|
@ -21,6 +21,11 @@
|
||||||
android:defaultValue="false"
|
android:defaultValue="false"
|
||||||
android:key="openapsama_useautosens"
|
android:key="openapsama_useautosens"
|
||||||
android:title="@string/openapsama_useautosens" />
|
android:title="@string/openapsama_useautosens" />
|
||||||
|
<SwitchPreference
|
||||||
|
android:defaultValue="true"
|
||||||
|
android:key="openapsama_autosens_adjusttargets"
|
||||||
|
android:summary="@string/openapsama_autosens_adjusttargets_summary"
|
||||||
|
android:title="@string/openapsama_autosens_adjusttargets" />
|
||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
|
|
79
app/src/main/res/xml/pref_openapssmb.xml
Normal file
79
app/src/main/res/xml/pref_openapssmb.xml
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:validate="http://schemas.android.com/apk/res-auto">
|
||||||
|
<PreferenceCategory
|
||||||
|
android:key="openapssmb"
|
||||||
|
android:title="@string/openapssmb">
|
||||||
|
<EditTextPreference
|
||||||
|
android:defaultValue="1"
|
||||||
|
android:key="openapsma_max_basal"
|
||||||
|
android:numeric="decimal"
|
||||||
|
android:dialogMessage="@string/openapsma_maxbasal_summary"
|
||||||
|
android:title="@string/openapsma_maxbasal_title" />
|
||||||
|
<EditTextPreference
|
||||||
|
android:defaultValue="1.5"
|
||||||
|
android:key="openapsma_max_iob"
|
||||||
|
android:numeric="decimal"
|
||||||
|
android:dialogMessage="@string/openapsma_maxiob_summary"
|
||||||
|
android:title="@string/openapsma_maxiob_title" />
|
||||||
|
<SwitchPreference
|
||||||
|
android:defaultValue="false"
|
||||||
|
android:key="openapsama_useautosens"
|
||||||
|
android:title="@string/openapsama_useautosens" />
|
||||||
|
<SwitchPreference
|
||||||
|
android:defaultValue="false"
|
||||||
|
android:key="@string/key_use_smb"
|
||||||
|
android:summary="@string/enablesmb_summary"
|
||||||
|
android:title="@string/enablesmb" />
|
||||||
|
<SwitchPreference
|
||||||
|
android:defaultValue="false"
|
||||||
|
android:key="@string/key_enableSMB_with_COB"
|
||||||
|
android:summary="@string/enablesmbwithcob_summary"
|
||||||
|
android:title="@string/enablesmbwithcob"
|
||||||
|
android:dependency="@string/key_use_smb"/>
|
||||||
|
<SwitchPreference
|
||||||
|
android:defaultValue="false"
|
||||||
|
android:key="@string/key_enableSMB_with_temptarget"
|
||||||
|
android:summary="@string/enablesmbwithtemptarget_summary"
|
||||||
|
android:title="@string/enablesmbwithtemptarget"
|
||||||
|
android:dependency="@string/key_use_smb"/>
|
||||||
|
<SwitchPreference
|
||||||
|
android:defaultValue="false"
|
||||||
|
android:key="@string/key_allowSMB_with_high_temptarget"
|
||||||
|
android:summary="@string/enablesmbwithhightemptarget_summary"
|
||||||
|
android:title="@string/enablesmbwithhightemptarget"
|
||||||
|
android:dependency="@string/key_use_smb"/>
|
||||||
|
<SwitchPreference
|
||||||
|
android:defaultValue="false"
|
||||||
|
android:key="@string/key_enableSMB_always"
|
||||||
|
android:summary="@string/enablesmbalways_summary"
|
||||||
|
android:title="@string/enablesmbalways"
|
||||||
|
android:dependency="@string/key_use_smb"/>
|
||||||
|
<SwitchPreference
|
||||||
|
android:defaultValue="false"
|
||||||
|
android:key="@string/key_enableSMB_after_carbs"
|
||||||
|
android:summary="@string/enablesmbaftercarbs_summary"
|
||||||
|
android:title="@string/enablesmbaftercarbs"
|
||||||
|
android:dependency="@string/key_use_smb"/>
|
||||||
|
<com.andreabaccega.widget.ValidatingEditTextPreference
|
||||||
|
android:defaultValue="30"
|
||||||
|
android:dialogMessage="@string/smbmaxminutes"
|
||||||
|
android:digits="0123456789"
|
||||||
|
android:inputType="number"
|
||||||
|
android:key="key_smbmaxminutes"
|
||||||
|
android:maxLines="20"
|
||||||
|
android:selectAllOnFocus="true"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:title="@string/smbmaxminutes_summary"
|
||||||
|
validate:maxNumber="120"
|
||||||
|
validate:minNumber="15"
|
||||||
|
validate:testType="numericRange" />
|
||||||
|
<SwitchPreference
|
||||||
|
android:defaultValue="false"
|
||||||
|
android:key="@string/key_use_uam"
|
||||||
|
android:summary="@string/enableuam_summary"
|
||||||
|
android:title="@string/enableuam" />
|
||||||
|
</PreferenceCategory>
|
||||||
|
|
||||||
|
|
||||||
|
</PreferenceScreen>
|
Loading…
Reference in a new issue