most new AMA code added
This commit is contained in:
parent
26102848f5
commit
25a3b678e9
|
@ -6,7 +6,7 @@ import com.j256.ormlite.stmt.query.In;
|
|||
* Created by mike on 07.06.2016.
|
||||
*/
|
||||
public class Constants {
|
||||
public static final String MGDL = "mg/dl"; // This is Nightscout representation
|
||||
public static final String MGDL = "mg/dl"; // This is Nightscout's representation
|
||||
public static final String MMOL = "mmol";
|
||||
|
||||
public static final double MMOLL_TO_MGDL = 18; // 18.0182;
|
||||
|
@ -24,5 +24,17 @@ public class Constants {
|
|||
|
||||
public static final long keepAliveMsecs = 5 * 60 * 1000L;
|
||||
|
||||
// SMS COMMUNICATOR
|
||||
|
||||
public static final long remoteBolusMinDistance = 15 * 60 * 1000L;
|
||||
|
||||
// AMA
|
||||
public static final int MAX_DAILY_SAFETY_MULTIPLIER = 3;
|
||||
public static final int CURRENT_BASAL_SAFETY_MULTIPLIER = 4;
|
||||
|
||||
public static final int BOLUSSNOOZE_DIA_ADVISOR = 2;
|
||||
public static final double AUTOSENS_MAX = 1.2d;
|
||||
public static final double AUTOSENS_MIN = 0.7d;
|
||||
public static final double MIN_5M_CARBIMPACT = 3d;
|
||||
|
||||
}
|
||||
|
|
|
@ -1,11 +1,21 @@
|
|||
package info.nightscout.androidaps.data;
|
||||
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.Html;
|
||||
import android.text.Spanned;
|
||||
|
||||
import com.j256.ormlite.dao.Dao;
|
||||
import com.j256.ormlite.stmt.PreparedQuery;
|
||||
import com.j256.ormlite.stmt.QueryBuilder;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.db.DatabaseHelper;
|
||||
import info.nightscout.androidaps.db.BgReading;
|
||||
import info.nightscout.utils.DecimalFormatter;
|
||||
import info.nightscout.utils.Round;
|
||||
|
||||
|
@ -17,35 +27,105 @@ public class GlucoseStatus {
|
|||
public double glucose = 0d;
|
||||
public double delta = 0d;
|
||||
public double avgdelta = 0d;
|
||||
public double short_avgdelta = 0d; // TODO: add calculation for AMA
|
||||
public double long_avgdelta = 0d; // TODO: add calculation for AMA
|
||||
public double short_avgdelta = 0d;
|
||||
public double long_avgdelta = 0d;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return MainApp.sResources.getString(R.string.glucose) + " " + DecimalFormatter.to0Decimal(glucose) + " mg/dl\n" +
|
||||
MainApp.sResources.getString(R.string.delta) + " " + DecimalFormatter.to0Decimal(delta) + " mg/dl\n" +
|
||||
MainApp.sResources.getString(R.string.avgdelta) + " " + DecimalFormatter.to2Decimal(avgdelta) + " mg/dl";
|
||||
MainApp.sResources.getString(R.string.short_avgdelta) + " " + DecimalFormatter.to2Decimal(short_avgdelta) + " mg/dl\n" +
|
||||
MainApp.sResources.getString(R.string.long_avgdelta) + " " + DecimalFormatter.to2Decimal(long_avgdelta) + " mg/dl";
|
||||
}
|
||||
|
||||
public Spanned toSpanned() {
|
||||
return Html.fromHtml("<b>" + MainApp.sResources.getString(R.string.glucose) + "</b>: " + DecimalFormatter.to0Decimal(glucose) + " mg/dl<br>" +
|
||||
"<b>" + MainApp.sResources.getString(R.string.delta) + "</b>: " + DecimalFormatter.to0Decimal(delta) + " mg/dl<br>" +
|
||||
"<b>" + MainApp.sResources.getString(R.string.avgdelta) + "</b>: " + DecimalFormatter.to2Decimal(avgdelta) + " mg/dl");
|
||||
"<b>" + MainApp.sResources.getString(R.string.short_avgdelta) + "</b>: " + DecimalFormatter.to2Decimal(short_avgdelta) + " mg/dl<br>" +
|
||||
"<b>" + MainApp.sResources.getString(R.string.long_avgdelta) + "</b>: " + DecimalFormatter.to2Decimal(long_avgdelta) + " mg/dl");
|
||||
}
|
||||
|
||||
public GlucoseStatus() {
|
||||
}
|
||||
|
||||
public GlucoseStatus(Double glucose, Double delta, Double avgdelta) {
|
||||
this.glucose = glucose;
|
||||
this.delta = delta;
|
||||
this.avgdelta = avgdelta;
|
||||
}
|
||||
|
||||
public GlucoseStatus round() {
|
||||
this.glucose = Round.roundTo(this.glucose, 0.1);
|
||||
this.delta = Round.roundTo(this.delta, 0.01);
|
||||
this.avgdelta = Round.roundTo(this.avgdelta, 0.01);
|
||||
this.short_avgdelta = Round.roundTo(this.short_avgdelta, 0.01);
|
||||
this.long_avgdelta = Round.roundTo(this.long_avgdelta, 0.01);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static GlucoseStatus getGlucoseStatusData() {
|
||||
// load 45min
|
||||
long fromtime = (long) (new Date().getTime() - 60 * 1000L * 45);
|
||||
List<BgReading> data = MainApp.getDbHelper().getDataFromTime(fromtime, false);
|
||||
|
||||
int sizeRecords = data.size();
|
||||
if (sizeRecords < 4 || data.get(0).timeIndex < new Date().getTime() - 7 * 60 * 1000L) {
|
||||
return null;
|
||||
}
|
||||
|
||||
BgReading now = data.get(0);
|
||||
long now_date = now.timeIndex;
|
||||
double change;
|
||||
|
||||
ArrayList<Double> last_deltas = new ArrayList<Double>();
|
||||
ArrayList<Double> short_deltas = new ArrayList<Double>();
|
||||
ArrayList<Double> long_deltas = new ArrayList<Double>();
|
||||
|
||||
for (int i = 1; i < data.size(); i++) {
|
||||
if (data.get(i).value > 38) {
|
||||
BgReading then = data.get(i);
|
||||
long then_date = then.timeIndex;
|
||||
double avgdelta = 0;
|
||||
int minutesago;
|
||||
|
||||
minutesago = Math.round((now_date - then_date) / (1000 * 60));
|
||||
// multiply by 5 to get the same units as delta, i.e. mg/dL/5m
|
||||
change = now.value - then.value;
|
||||
avgdelta = change / minutesago * 5;
|
||||
|
||||
// use the average of all data points in the last 2.5m for all further "now" calculations
|
||||
if (0 < minutesago && minutesago < 2.5) {
|
||||
now.value = (now.value + then.value) / 2;
|
||||
now_date = (now_date + then_date) / 2;
|
||||
// short_deltas are calculated from everything ~5-15 minutes ago
|
||||
} else if (2.5 < minutesago && minutesago < 17.5) {
|
||||
//console.error(minutesago, avgdelta);
|
||||
short_deltas.add(avgdelta);
|
||||
// last_deltas are calculated from everything ~5 minutes ago
|
||||
if (2.5 < minutesago && minutesago < 7.5) {
|
||||
last_deltas.add(avgdelta);
|
||||
}
|
||||
// long_deltas are calculated from everything ~20-40 minutes ago
|
||||
} else if (17.5 < minutesago && minutesago < 42.5) {
|
||||
long_deltas.add(avgdelta);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GlucoseStatus status = new GlucoseStatus();
|
||||
status.glucose = now.value;
|
||||
status.delta = average(last_deltas);
|
||||
status.short_avgdelta = average(short_deltas);
|
||||
status.long_avgdelta = average(long_deltas);
|
||||
status.avgdelta = status.short_avgdelta; // for OpenAPS MA
|
||||
|
||||
return status.round();
|
||||
}
|
||||
|
||||
public static double average(ArrayList<Double> array) {
|
||||
double sum = 0d;
|
||||
|
||||
if (array.size() == 0)
|
||||
return 0d;
|
||||
|
||||
for (Double value : array) {
|
||||
sum += value;
|
||||
}
|
||||
return sum / array.size();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
package info.nightscout.androidaps.data;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.client.data.NSProfile;
|
||||
import info.nightscout.utils.DateUtil;
|
||||
import info.nightscout.utils.Round;
|
||||
|
||||
|
@ -73,4 +77,62 @@ public class IobTotal {
|
|||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
public JSONObject determineBasalJson() {
|
||||
JSONObject json = new JSONObject();
|
||||
try {
|
||||
json.put("iob", iob);
|
||||
json.put("basaliob", basaliob);
|
||||
json.put("bolussnooze", bolussnooze);
|
||||
json.put("activity", activity);
|
||||
json.put("time", DateUtil.toISOString(new Date()));
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
public static IobTotal calulateFromTreatmentsAndTemps() {
|
||||
ConfigBuilderPlugin.getActiveTreatments().updateTotalIOB();
|
||||
IobTotal bolusIob = ConfigBuilderPlugin.getActiveTreatments().getLastCalculation().round();
|
||||
if (bolusIob == null) bolusIob = new IobTotal();
|
||||
ConfigBuilderPlugin.getActiveTempBasals().updateTotalIOB();
|
||||
IobTotal basalIob = ConfigBuilderPlugin.getActiveTempBasals().getLastCalculation().round();
|
||||
if (basalIob == null) basalIob = new IobTotal();
|
||||
IobTotal iobTotal = IobTotal.combine(bolusIob, basalIob).round();
|
||||
return iobTotal;
|
||||
}
|
||||
|
||||
public static IobTotal calulateFromTreatmentsAndTemps(long time) {
|
||||
IobTotal bolusIob = ConfigBuilderPlugin.getActiveTreatments().getCalculationToTime(time).round();
|
||||
if (bolusIob == null) bolusIob = new IobTotal();
|
||||
IobTotal basalIob = ConfigBuilderPlugin.getActiveTempBasals().getCalculationToTime(time).round();
|
||||
if (basalIob == null) basalIob = new IobTotal();
|
||||
IobTotal iobTotal = IobTotal.combine(bolusIob, basalIob).round();
|
||||
return iobTotal;
|
||||
}
|
||||
|
||||
public static IobTotal[] calculateIobArrayInDia() {
|
||||
NSProfile profile = ConfigBuilderPlugin.getActiveProfile().getProfile();
|
||||
// predict IOB out to DIA plus 30m
|
||||
long time = new Date().getTime();
|
||||
int len = (int) ((profile.getDia() *60 + 30) / 5);
|
||||
IobTotal[] array = new IobTotal[len];
|
||||
int pos = 0;
|
||||
for (int i = 0; i < len; i++){
|
||||
long t = time + i * 5 * 60000;
|
||||
IobTotal iob = calulateFromTreatmentsAndTemps(t);
|
||||
array[pos] = iob;
|
||||
pos++;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
public static JSONArray convertToJSONArray(IobTotal[] iobArray) {
|
||||
JSONArray array = new JSONArray();
|
||||
for (int i = 0; i < iobArray.length; i ++) {
|
||||
array.put(iobArray[i].determineBasalJson());
|
||||
}
|
||||
return array;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
package info.nightscout.androidaps.data;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.db.BgReading;
|
||||
import info.nightscout.androidaps.db.Treatment;
|
||||
import info.nightscout.androidaps.plugins.OpenAPSAMA.Autosens;
|
||||
import info.nightscout.androidaps.plugins.OpenAPSAMA.AutosensResult;
|
||||
import info.nightscout.client.data.NSProfile;
|
||||
|
||||
/**
|
||||
|
@ -14,16 +18,24 @@ public class MealData {
|
|||
public double carbs = 0d;
|
||||
public double mealCOB = 0.0d; // TODO: add calculation for AMA
|
||||
|
||||
|
||||
public void addTreatment(Treatment treatment) {
|
||||
NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile();
|
||||
if (profile == null) return;
|
||||
|
||||
// TODO: not sure how much data do i need for AMA
|
||||
List<BgReading> bgReadings = MainApp.getDbHelper().getDataFromTime((long) (new Date().getTime() - 60 * 60 * 1000L * profile.getDia() * 2), false);
|
||||
|
||||
long now = new Date().getTime();
|
||||
long dia_ago = now - (new Double(profile.getDia() * 60 * 60 * 1000l)).longValue();
|
||||
long t = treatment.created_at.getTime();
|
||||
if (t > dia_ago && t <= now) {
|
||||
if (treatment.carbs >= 1) {
|
||||
carbs += treatment.carbs;
|
||||
AutosensResult result = Autosens.detectSensitivityandCarbAbsorption(bgReadings, t);
|
||||
double myCarbsAbsorbed = result.carbsAbsorbed;
|
||||
double myMealCOB = Math.max(0, carbs - myCarbsAbsorbed);
|
||||
mealCOB = Math.max(mealCOB, myMealCOB);
|
||||
}
|
||||
if (treatment.insulin > 0 && treatment.mealBolus) {
|
||||
boluses += treatment.insulin;
|
||||
|
|
|
@ -183,12 +183,12 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
return null;
|
||||
}
|
||||
|
||||
public List<BgReading> getDataFromTime(long mills) {
|
||||
public List<BgReading> getDataFromTime(long mills, boolean ascending) {
|
||||
try {
|
||||
Dao<BgReading, Long> daoBgreadings = getDaoBgReadings();
|
||||
List<BgReading> bgReadings;
|
||||
QueryBuilder<BgReading, Long> queryBuilder = daoBgreadings.queryBuilder();
|
||||
queryBuilder.orderBy("timeIndex", true);
|
||||
queryBuilder.orderBy("timeIndex", ascending);
|
||||
Where where = queryBuilder.where();
|
||||
where.ge("timeIndex", mills).and().gt("value", 38);
|
||||
PreparedQuery<BgReading> preparedQuery = queryBuilder.prepare();
|
||||
|
@ -200,63 +200,4 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
return new ArrayList<BgReading>();
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns glucose_status for openAPS or null if no actual data available
|
||||
*/
|
||||
@Nullable
|
||||
public GlucoseStatus getGlucoseStatusData() {
|
||||
GlucoseStatus result = new GlucoseStatus();
|
||||
try {
|
||||
|
||||
Dao<BgReading, Long> daoBgreadings = null;
|
||||
daoBgreadings = getDaoBgReadings();
|
||||
List<BgReading> bgReadings;
|
||||
QueryBuilder<BgReading, Long> queryBuilder = daoBgreadings.queryBuilder();
|
||||
queryBuilder.orderBy("timeIndex", false);
|
||||
queryBuilder.where().gt("value", 38);
|
||||
queryBuilder.limit(4l);
|
||||
PreparedQuery<BgReading> preparedQuery = queryBuilder.prepare();
|
||||
bgReadings = daoBgreadings.query(preparedQuery);
|
||||
|
||||
int sizeRecords = bgReadings.size();
|
||||
|
||||
if (sizeRecords < 4 || bgReadings.get(sizeRecords - 4).timeIndex < new Date().getTime() - 7 * 60 * 1000L) {
|
||||
return null;
|
||||
}
|
||||
|
||||
double minutes = 5;
|
||||
double change;
|
||||
double avg;
|
||||
|
||||
if (bgReadings.size() > 3) {
|
||||
BgReading now = bgReadings.get(sizeRecords - 4);
|
||||
BgReading last = bgReadings.get(sizeRecords - 3);
|
||||
BgReading last1 = bgReadings.get(sizeRecords - 2);
|
||||
BgReading last2 = bgReadings.get(sizeRecords - 1);
|
||||
if (last2.value > 38) {
|
||||
minutes = (now.timeIndex - last2.timeIndex)/(60d*1000);
|
||||
change = now.value - last2.value;
|
||||
} else if (last1.value > 38) {
|
||||
minutes = (now.timeIndex - last1.timeIndex)/(60d*1000);;
|
||||
change = now.value - last1.value;
|
||||
} else if (last.value > 38) {
|
||||
minutes = (now.timeIndex - last.timeIndex)/(60d*1000);
|
||||
change = now.value - last.value;
|
||||
} else {
|
||||
change = 0;
|
||||
}
|
||||
//multiply by 5 to get the same unit as delta, i.e. mg/dL/5m
|
||||
avg = change / minutes * 5;
|
||||
|
||||
result.glucose = now.value;
|
||||
result.delta = (now.value - last.value)*5*60*1000/(now.getTimeIndex() - last.getTimeIndex());
|
||||
result.avgdelta = avg;
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
result.round();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import info.nightscout.androidaps.data.IobTotal;
|
|||
public interface TempBasalsInterface {
|
||||
void updateTotalIOB();
|
||||
IobTotal getLastCalculation();
|
||||
IobTotal getCalculationToTime(long time);
|
||||
|
||||
TempBasal getTempBasal (Date time);
|
||||
TempBasal getExtendedBolus (Date time);
|
||||
|
|
|
@ -13,6 +13,7 @@ public interface TreatmentsInterface {
|
|||
|
||||
void updateTotalIOB();
|
||||
IobTotal getLastCalculation();
|
||||
IobTotal getCalculationToTime(long time);
|
||||
MealData getMealData();
|
||||
List<Treatment> getTreatments();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,225 @@
|
|||
package info.nightscout.androidaps.plugins.OpenAPSAMA;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import info.nightscout.androidaps.Constants;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.data.IobTotal;
|
||||
import info.nightscout.androidaps.db.BgReading;
|
||||
import info.nightscout.client.data.NSProfile;
|
||||
import info.nightscout.utils.Round;
|
||||
|
||||
|
||||
public class Autosens {
|
||||
private static Logger log = LoggerFactory.getLogger(Autosens.class);
|
||||
|
||||
public static AutosensResult detectSensitivityandCarbAbsorption(List<BgReading> glucose_data, long mealTime) {
|
||||
|
||||
NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile();
|
||||
|
||||
//console.error(mealTime);
|
||||
|
||||
double deviationSum = 0;
|
||||
double carbsAbsorbed = 0;
|
||||
|
||||
List<BgReading> bucketed_data = new ArrayList<>();
|
||||
bucketed_data.add(glucose_data.get(0));
|
||||
int j = 0;
|
||||
for (int i = 1; i < glucose_data.size(); ++i) {
|
||||
long bgTime = glucose_data.get(i).getTimeIndex();
|
||||
long lastbgTime = glucose_data.get(i - 1).getTimeIndex();
|
||||
if (glucose_data.get(i).value < 39 || glucose_data.get(i - 1).value < 39) {
|
||||
continue;
|
||||
}
|
||||
|
||||
long elapsed_minutes = (bgTime - lastbgTime) / (60 * 1000);
|
||||
if (Math.abs(elapsed_minutes) > 8) {
|
||||
// interpolate missing data points
|
||||
double lastbg = glucose_data.get(i - 1).value;
|
||||
elapsed_minutes = Math.abs(elapsed_minutes);
|
||||
//console.error(elapsed_minutes);
|
||||
long nextbgTime;
|
||||
while (elapsed_minutes > 5) {
|
||||
nextbgTime = lastbgTime + 5 * 60 * 1000;
|
||||
j++;
|
||||
BgReading newBgreading = new BgReading();
|
||||
newBgreading.timeIndex = nextbgTime;
|
||||
double gapDelta = glucose_data.get(i).value - lastbg;
|
||||
//console.error(gapDelta, lastbg, elapsed_minutes);
|
||||
double nextbg = lastbg + (5 / elapsed_minutes * gapDelta);
|
||||
newBgreading.value = Math.round(nextbg);
|
||||
//console.error("Interpolated", bucketed_data[j]);
|
||||
bucketed_data.add(newBgreading);
|
||||
|
||||
elapsed_minutes = elapsed_minutes - 5;
|
||||
lastbg = nextbg;
|
||||
lastbgTime = nextbgTime;
|
||||
}
|
||||
} else if (Math.abs(elapsed_minutes) > 2) {
|
||||
j++;
|
||||
BgReading newBgreading = new BgReading();
|
||||
newBgreading.value = glucose_data.get(i).value;
|
||||
newBgreading.timeIndex = bgTime;
|
||||
bucketed_data.add(newBgreading);
|
||||
} else {
|
||||
bucketed_data.get(j).value = (bucketed_data.get(j).value + glucose_data.get(i).value) / 2;
|
||||
}
|
||||
}
|
||||
//console.error(bucketed_data);
|
||||
double[] avgDeltas = new double[bucketed_data.size() - 2];
|
||||
double[] bgis = new double[bucketed_data.size() - 2];
|
||||
double[] deviations = new double[bucketed_data.size() - 2];
|
||||
|
||||
String debugString = "";
|
||||
for (int i = 0; i < bucketed_data.size() - 3; ++i) {
|
||||
long bgTime = bucketed_data.get(i).timeIndex;
|
||||
int secondsFromMidnight = NSProfile.secondsFromMidnight(new Date(bgTime));
|
||||
|
||||
double sens = profile.getIsf(secondsFromMidnight);
|
||||
|
||||
//console.error(bgTime , bucketed_data[i].glucose);
|
||||
double bg;
|
||||
double avgDelta;
|
||||
double delta;
|
||||
bg = bucketed_data.get(i).value;
|
||||
if (bg < 40 || bucketed_data.get(i + 3).value < 40) {
|
||||
log.error("! value < 40");
|
||||
continue;
|
||||
}
|
||||
avgDelta = (bg - bucketed_data.get(i + 3).value) / 3;
|
||||
delta = (bg - bucketed_data.get(i + 1).value);
|
||||
|
||||
// avgDelta = avgDelta.toFixed(2);
|
||||
IobTotal iob = IobTotal.calulateFromTreatmentsAndTemps(bgTime);
|
||||
|
||||
double bgi = Math.round((-iob.activity * sens * 5) * 100) / 100;
|
||||
// bgi = bgi.toFixed(2);
|
||||
//console.error(delta);
|
||||
double deviation = delta - bgi;
|
||||
// deviation = deviation.toFixed(2);
|
||||
//if (deviation < 0 && deviation > -2) { console.error("BG: "+bg+", avgDelta: "+avgDelta+", BGI: "+bgi+", deviation: "+deviation); }
|
||||
|
||||
// Exclude large positive deviations (carb absorption) from autosens
|
||||
if (avgDelta - bgi < 6) {
|
||||
if (deviation > 0) {
|
||||
debugString += "+";
|
||||
} else if (deviation == 0) {
|
||||
debugString += "=";
|
||||
} else {
|
||||
debugString += "-";
|
||||
}
|
||||
avgDeltas[i] = avgDelta;
|
||||
bgis[i] = bgi;
|
||||
deviations[i] = deviation;
|
||||
deviationSum += deviation;
|
||||
} else {
|
||||
debugString += ">";
|
||||
//console.error(bgTime);
|
||||
}
|
||||
|
||||
// if bgTime is more recent than mealTime
|
||||
if (bgTime > mealTime) {
|
||||
// figure out how many carbs that represents
|
||||
// but always assume at least 3mg/dL/5m (default) absorption
|
||||
double ci = Math.max(deviation, Constants.MIN_5M_CARBIMPACT);
|
||||
double absorbed = ci * profile.getIc(secondsFromMidnight) / sens;
|
||||
// and add that to the running total carbsAbsorbed
|
||||
carbsAbsorbed += absorbed;
|
||||
}
|
||||
}
|
||||
//console.error("");
|
||||
log.debug(debugString);
|
||||
//console.log(JSON.stringify(avgDeltas));
|
||||
//console.log(JSON.stringify(bgis));
|
||||
Arrays.sort(avgDeltas);
|
||||
Arrays.sort(bgis);
|
||||
Arrays.sort(deviations);
|
||||
|
||||
for (double i = 0.9; i > 0.1; i = i - 0.02) {
|
||||
//console.error("p="+i.toFixed(2)+": "+percentile(avgDeltas, i).toFixed(2)+", "+percentile(bgis, i).toFixed(2)+", "+percentile(deviations, i).toFixed(2));
|
||||
if (percentile(deviations, (i + 0.02)) >= 0 && percentile(deviations, i) < 0) {
|
||||
//console.error("p="+i.toFixed(2)+": "+percentile(avgDeltas, i).toFixed(2)+", "+percentile(bgis, i).toFixed(2)+", "+percentile(deviations, i).toFixed(2));
|
||||
log.debug(Math.round(100 * i) + "% of non-meal deviations negative (target 45%-50%)");
|
||||
}
|
||||
}
|
||||
double pSensitive = percentile(deviations, 0.50);
|
||||
double pResistant = percentile(deviations, 0.45);
|
||||
//p30 = percentile(deviations, 0.3);
|
||||
|
||||
// average = deviationSum / deviations.length;
|
||||
|
||||
//console.error("Mean deviation: "+average.toFixed(2));
|
||||
double basalOff = 0;
|
||||
|
||||
if (pSensitive < 0) { // sensitive
|
||||
basalOff = pSensitive * (60 / 5) / profile.getIsf(NSProfile.secondsFromMidnight());
|
||||
log.debug("Excess insulin sensitivity detected: ");
|
||||
} else if (pResistant > 0) { // resistant
|
||||
basalOff = pResistant * (60 / 5) / profile.getIsf(NSProfile.secondsFromMidnight());
|
||||
log.debug("Excess insulin resistance detected: ");
|
||||
} else {
|
||||
log.debug("Sensitivity normal.");
|
||||
}
|
||||
double ratio = 1 + (basalOff / profile.getMaxDailyBasal());
|
||||
|
||||
// don't adjust more than 1.5x
|
||||
double rawRatio = ratio;
|
||||
ratio = Math.max(ratio, Constants.AUTOSENS_MIN);
|
||||
ratio = Math.min(ratio, Constants.AUTOSENS_MAX);
|
||||
|
||||
if (ratio != rawRatio) {
|
||||
log.debug("Ratio limited from " + rawRatio + " to " + ratio);
|
||||
}
|
||||
|
||||
double newisf = Math.round(profile.getIsf(NSProfile.secondsFromMidnight()) / ratio);
|
||||
if (ratio != 1) {
|
||||
log.debug("ISF adjusted from " + profile.getIsf(NSProfile.secondsFromMidnight()) + " to " + newisf);
|
||||
}
|
||||
//console.error("Basal adjustment "+basalOff.toFixed(2)+"U/hr");
|
||||
//console.error("Ratio: "+ratio*100+"%: new ISF: "+newisf.toFixed(1)+"mg/dL/U");
|
||||
|
||||
AutosensResult output = new AutosensResult();
|
||||
output.ratio = Round.roundTo(ratio, 0.01);
|
||||
output.carbsAbsorbed = Round.roundTo(carbsAbsorbed, 0.01);
|
||||
return output;
|
||||
}
|
||||
|
||||
// From https://gist.github.com/IceCreamYou/6ffa1b18c4c8f6aeaad2
|
||||
// Returns the value at a given percentile in a sorted numeric array.
|
||||
// "Linear interpolation between closest ranks" method
|
||||
public static double percentile(double[] arr, double p) {
|
||||
if (arr.length == 0) return 0;
|
||||
if (p <= 0) return arr[0];
|
||||
if (p >= 1) return arr[arr.length - 1];
|
||||
|
||||
double index = arr.length * p,
|
||||
lower = Math.floor(index),
|
||||
upper = lower + 1,
|
||||
weight = index % 1;
|
||||
|
||||
if (upper >= arr.length) return arr[(int) lower];
|
||||
return arr[(int) lower] * (1 - weight) + arr[(int) upper] * weight;
|
||||
}
|
||||
|
||||
// Returns the percentile of the given value in a sorted numeric array.
|
||||
public static double percentRank(double[] arr, double v) {
|
||||
for (int i = 0, l = arr.length; i < l; i++) {
|
||||
if (v <= arr[i]) {
|
||||
while (i < l && v == arr[i]) i++;
|
||||
if (i == 0) return 0;
|
||||
if (v != arr[i - 1]) {
|
||||
i += (v - arr[i - 1]) / (arr[i] - arr[i - 1]);
|
||||
}
|
||||
return i / l;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package info.nightscout.androidaps.plugins.OpenAPSAMA;
|
||||
|
||||
/**
|
||||
* Created by mike on 06.01.2017.
|
||||
*/
|
||||
public class AutosensResult {
|
||||
public double ratio;
|
||||
public double carbsAbsorbed;
|
||||
}
|
|
@ -13,9 +13,13 @@ import org.slf4j.LoggerFactory;
|
|||
import java.io.IOException;
|
||||
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.Constants;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.data.GlucoseStatus;
|
||||
import info.nightscout.androidaps.data.MealData;
|
||||
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.Loop.ScriptReader;
|
||||
import info.nightscout.androidaps.data.IobTotal;
|
||||
import info.nightscout.client.data.NSProfile;
|
||||
|
@ -28,10 +32,10 @@ public class DetermineBasalAdapterAMAJS {
|
|||
V8 mV8rt;
|
||||
private V8Object mProfile;
|
||||
private V8Object mGlucoseStatus;
|
||||
private V8Object mIobData;
|
||||
private V8Array mIobData;
|
||||
private V8Object mMealData;
|
||||
private V8Object mCurrentTemp;
|
||||
private V8Object mAutosensData = null;
|
||||
private V8Object mAutosensData;
|
||||
|
||||
private final String PARAM_currentTemp = "currentTemp";
|
||||
private final String PARAM_iobData = "iobData";
|
||||
|
@ -73,8 +77,14 @@ public class DetermineBasalAdapterAMAJS {
|
|||
mProfile.add("max_basal", 0);
|
||||
mProfile.add("max_bg", 0);
|
||||
mProfile.add("min_bg", 0);
|
||||
mProfile.add("carbratio", 0);
|
||||
mProfile.add("carb_ratio", 0);
|
||||
mProfile.add("sens", 0);
|
||||
mProfile.add("max_daily_safety_multiplier", Constants.MAX_DAILY_SAFETY_MULTIPLIER);
|
||||
mProfile.add("current_basal_safety_multiplier", Constants.CURRENT_BASAL_SAFETY_MULTIPLIER);
|
||||
mProfile.add("skip_neutral_temps", true);
|
||||
mProfile.add("temptargetSet", false);
|
||||
mProfile.add("autosens_adjust_targets", false);
|
||||
mProfile.add("min_5m_carbimpact", 0);
|
||||
mProfile.add("current_basal", 0);
|
||||
mV8rt.add(PARAM_profile, mProfile);
|
||||
// Current temp
|
||||
|
@ -84,14 +94,8 @@ public class DetermineBasalAdapterAMAJS {
|
|||
mCurrentTemp.add("rate", 0);
|
||||
mV8rt.add(PARAM_currentTemp, mCurrentTemp);
|
||||
// IOB data
|
||||
mIobData = new V8Object(mV8rt);
|
||||
mIobData.add("iob", 0); //netIob
|
||||
mIobData.add("activity", 0); //netActivity
|
||||
mIobData.add("bolussnooze", 0); //bolusIob
|
||||
mIobData.add("basaliob", 0);
|
||||
mIobData.add("netbasalinsulin", 0);
|
||||
mIobData.add("hightempinsulin", 0);
|
||||
mV8rt.add(PARAM_iobData, mIobData);
|
||||
// mIobData = new V8Array(mV8rt);
|
||||
// mV8rt.add(PARAM_iobData, mIobData);
|
||||
// Glucose status
|
||||
mGlucoseStatus = new V8Object(mV8rt);
|
||||
mGlucoseStatus.add("glucose", 0);
|
||||
|
@ -105,7 +109,9 @@ public class DetermineBasalAdapterAMAJS {
|
|||
mMealData.add("mealCOB", 0.0d);
|
||||
mV8rt.add(PARAM_meal_data, mMealData);
|
||||
// Autosens data
|
||||
mV8rt.executeVoidScript("autosens_data = undefined");
|
||||
mAutosensData = new V8Object(mV8rt);
|
||||
mMealData.add("ratio", 0.0d);
|
||||
mV8rt.add(PARAM_autosens_data, mAutosensData);
|
||||
}
|
||||
|
||||
public DetermineBasalResultAMA invoke() {
|
||||
|
@ -149,8 +155,7 @@ public class DetermineBasalAdapterAMAJS {
|
|||
storedCurrentTemp = mV8rt.executeStringScript("JSON.stringify(" + PARAM_currentTemp + ");");
|
||||
storedProfile = mV8rt.executeStringScript("JSON.stringify(" + PARAM_profile + ");");
|
||||
storedMeal_data = mV8rt.executeStringScript("JSON.stringify(" + PARAM_meal_data + ");");
|
||||
if (mAutosensData != null)
|
||||
storedAutosens_data = mV8rt.executeStringScript("JSON.stringify(" + PARAM_autosens_data + ");");
|
||||
storedAutosens_data = mV8rt.executeStringScript("JSON.stringify(" + PARAM_autosens_data + ");");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -225,11 +230,15 @@ public class DetermineBasalAdapterAMAJS {
|
|||
JavaVoidCallback callbackLog = new JavaVoidCallback() {
|
||||
@Override
|
||||
public void invoke(V8Object arg0, V8Array parameters) {
|
||||
if (parameters.length() > 0) {
|
||||
Object arg1 = parameters.get(0);
|
||||
if (Config.logAPSResult)
|
||||
log.debug("Input params: " + arg1);
|
||||
int i = 0;
|
||||
String s = "";
|
||||
while (i < parameters.length()) {
|
||||
Object arg = parameters.get(i);
|
||||
s += arg + " ";
|
||||
i++;
|
||||
}
|
||||
if (!s.equals("") && Config.logAPSResult)
|
||||
log.debug("Script debug: " + s);
|
||||
}
|
||||
};
|
||||
mV8rt.registerJavaMethod(callbackLog, "log");
|
||||
|
@ -244,10 +253,12 @@ public class DetermineBasalAdapterAMAJS {
|
|||
double maxBg,
|
||||
double targetBg,
|
||||
PumpInterface pump,
|
||||
IobTotal iobData,
|
||||
IobTotal[] iobArray,
|
||||
GlucoseStatus glucoseStatus,
|
||||
MealData mealData,
|
||||
JSONObject autosensData) {
|
||||
double autosensDataRatio,
|
||||
boolean tempTargetSet,
|
||||
double min_5m_carbimpact) {
|
||||
|
||||
String units = profile.getUnits();
|
||||
|
||||
|
@ -260,23 +271,21 @@ public class DetermineBasalAdapterAMAJS {
|
|||
mProfile.add("min_bg", minBg);
|
||||
mProfile.add("max_bg", maxBg);
|
||||
mProfile.add("target_bg", targetBg);
|
||||
mProfile.add("carbratio", profile.getIc(profile.secondsFromMidnight()));
|
||||
mProfile.add("carb_ratio", profile.getIc(profile.secondsFromMidnight()));
|
||||
mProfile.add("sens", NSProfile.toMgdl(profile.getIsf(NSProfile.secondsFromMidnight()).doubleValue(), units));
|
||||
|
||||
mProfile.add("current_basal", pump.getBaseBasalRate());
|
||||
mProfile.add("temptargetSet", tempTargetSet);
|
||||
mProfile.add("autosens_adjust_targets", MainApp.getConfigBuilder().isAMAModeEnabled());
|
||||
mProfile.add("min_5m_carbimpact", min_5m_carbimpact);
|
||||
|
||||
mCurrentTemp.add("duration", pump.getTempBasalRemainingMinutes());
|
||||
mCurrentTemp.add("rate", pump.getTempBasalAbsoluteRate());
|
||||
|
||||
mIobData.add("iob", iobData.iob); //netIob
|
||||
mIobData.add("activity", iobData.activity); //netActivity
|
||||
mIobData.add("bolussnooze", iobData.bolussnooze); //bolusIob
|
||||
mIobData.add("basaliob", iobData.basaliob);
|
||||
mIobData.add("netbasalinsulin", iobData.netbasalinsulin);
|
||||
mIobData.add("hightempinsulin", iobData.hightempinsulin);
|
||||
mIobData = mV8rt.executeArrayScript(IobTotal.convertToJSONArray(iobArray).toString());
|
||||
mV8rt.add(PARAM_iobData, mIobData);
|
||||
|
||||
mGlucoseStatus.add("glucose", glucoseStatus.glucose);
|
||||
mGlucoseStatus.add("delta", glucoseStatus.delta);
|
||||
mGlucoseStatus.add("avgdelta", glucoseStatus.avgdelta);
|
||||
mGlucoseStatus.add("short_avgdelta", glucoseStatus.short_avgdelta);
|
||||
mGlucoseStatus.add("long_avgdelta", glucoseStatus.long_avgdelta);
|
||||
|
||||
|
@ -284,12 +293,7 @@ public class DetermineBasalAdapterAMAJS {
|
|||
mMealData.add("boluses", mealData.boluses);
|
||||
mMealData.add("mealCOB", mealData.mealCOB);
|
||||
|
||||
if (autosensData != null) {
|
||||
mAutosensData = new V8Object(mV8rt);
|
||||
// TODO: add autosens data here for AMA
|
||||
} else {
|
||||
mV8rt.executeVoidScript("autosens_data = undefined");
|
||||
}
|
||||
mAutosensData.add("ratio", autosensDataRatio);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -11,6 +11,8 @@ import android.widget.TextView;
|
|||
|
||||
import com.squareup.otto.Subscribe;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -110,7 +112,13 @@ public class OpenAPSAMAFragment extends Fragment implements View.OnClickListener
|
|||
if (determineBasalAdapterAMAJS != null) {
|
||||
glucoseStatusView.setText(JSONFormatter.format(determineBasalAdapterAMAJS.getGlucoseStatusParam()));
|
||||
currentTempView.setText(JSONFormatter.format(determineBasalAdapterAMAJS.getCurrentTempParam()));
|
||||
iobDataView.setText(JSONFormatter.format(determineBasalAdapterAMAJS.getIobDataParam()));
|
||||
try {
|
||||
JSONArray iobArray = new JSONArray(determineBasalAdapterAMAJS.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(determineBasalAdapterAMAJS.getProfileParam()));
|
||||
mealDataView.setText(JSONFormatter.format(determineBasalAdapterAMAJS.getMealDataParam()));
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import org.slf4j.LoggerFactory;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.Constants;
|
||||
|
@ -16,6 +17,7 @@ import info.nightscout.androidaps.MainApp;
|
|||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.data.GlucoseStatus;
|
||||
import info.nightscout.androidaps.data.MealData;
|
||||
import info.nightscout.androidaps.db.BgReading;
|
||||
import info.nightscout.androidaps.interfaces.APSInterface;
|
||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||
|
@ -107,7 +109,7 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface {
|
|||
return;
|
||||
}
|
||||
|
||||
GlucoseStatus glucoseStatus = MainApp.getDbHelper().getGlucoseStatusData();
|
||||
GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData();
|
||||
NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile();
|
||||
PumpInterface pump = MainApp.getConfigBuilder();
|
||||
|
||||
|
@ -162,16 +164,9 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface {
|
|||
minBg = Round.roundTo(minBg, 0.1d);
|
||||
maxBg = Round.roundTo(maxBg, 0.1d);
|
||||
|
||||
TreatmentsInterface treatments = MainApp.getConfigBuilder().getActiveTreatments();
|
||||
TempBasalsInterface tempBasals = MainApp.getConfigBuilder().getActiveTempBasals();
|
||||
treatments.updateTotalIOB();
|
||||
tempBasals.updateTotalIOB();
|
||||
IobTotal bolusIob = treatments.getLastCalculation();
|
||||
IobTotal basalIob = tempBasals.getLastCalculation();
|
||||
IobTotal[] iobArray = IobTotal.calculateIobArrayInDia();
|
||||
|
||||
IobTotal iobTotal = IobTotal.combine(bolusIob, basalIob).round();
|
||||
|
||||
MealData mealData = treatments.getMealData();
|
||||
MealData mealData = MainApp.getConfigBuilder().getActiveTreatments().getMealData();
|
||||
|
||||
maxIob = MainApp.getConfigBuilder().applyMaxIOBConstraints(maxIob);
|
||||
|
||||
|
@ -188,7 +183,14 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface {
|
|||
if (!checkOnlyHardLimits(profile.getMaxDailyBasal(), "max_daily_basal", 0.1, 10)) return;
|
||||
if (!checkOnlyHardLimits(pump.getBaseBasalRate(), "current_basal", 0.01, 5)) return;
|
||||
|
||||
determineBasalAdapterAMAJS.setData(profile, maxIob, maxBasal, minBg, maxBg, targetBg, pump, iobTotal, glucoseStatus, mealData, null);
|
||||
List<BgReading> bgReadings = MainApp.getDbHelper().getDataFromTime((long) (new Date().getTime() - 60 * 60 * 1000L * (24 + profile.getDia())), false);
|
||||
AutosensResult autosensResult = Autosens.detectSensitivityandCarbAbsorption(bgReadings, new Date().getTime());
|
||||
|
||||
determineBasalAdapterAMAJS.setData(profile, maxIob, maxBasal, minBg, maxBg, targetBg, pump, iobArray, glucoseStatus, mealData,
|
||||
autosensResult.ratio, //autosensDataRatio
|
||||
false, // isTempTargetSet TODO: add when we start handling temp targets
|
||||
Constants.MIN_5M_CARBIMPACT //min_5m_carbimpact
|
||||
);
|
||||
|
||||
|
||||
DetermineBasalResultAMA determineBasalResultAMA = determineBasalAdapterAMAJS.invoke();
|
||||
|
@ -203,7 +205,7 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface {
|
|||
determineBasalResultAMA.changeRequested = false;
|
||||
}
|
||||
|
||||
determineBasalResultAMA.iob = iobTotal;
|
||||
determineBasalResultAMA.iob = iobArray[0];
|
||||
|
||||
determineBasalAdapterAMAJS.release();
|
||||
|
||||
|
|
|
@ -107,7 +107,7 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface {
|
|||
return;
|
||||
}
|
||||
|
||||
GlucoseStatus glucoseStatus = MainApp.getDbHelper().getGlucoseStatusData();
|
||||
GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData();
|
||||
NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile();
|
||||
PumpInterface pump = MainApp.getConfigBuilder();
|
||||
|
||||
|
|
|
@ -513,8 +513,8 @@ public class OverviewFragment extends Fragment {
|
|||
acceptTempLayout.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
TempBasal activeTemp = pump.getTempBasal();
|
||||
if (pump.isTempBasalInProgress()) {
|
||||
TempBasal activeTemp = pump.getTempBasal();
|
||||
cancelTempLayout.setVisibility(View.VISIBLE);
|
||||
cancelTempButton.setText(MainApp.instance().getString(R.string.cancel) + ": " + activeTemp.toString());
|
||||
runningTempView.setVisibility(View.VISIBLE);
|
||||
|
@ -578,7 +578,7 @@ public class OverviewFragment extends Fragment {
|
|||
if (lastBG != null && bgView != null) {
|
||||
bgView.setText(lastBG.valueToUnitsToString(profile.getUnits()));
|
||||
arrowView.setText(lastBG.directionToSymbol());
|
||||
GlucoseStatus glucoseStatus = MainApp.getDbHelper().getGlucoseStatusData();
|
||||
GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData();
|
||||
if (glucoseStatus != null){
|
||||
deltaView.setText("Δ " + NSProfile.toUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units) + " " + units);
|
||||
avgdeltaView.setText("øΔ " + NSProfile.toUnitsString(glucoseStatus.avgdelta, glucoseStatus.avgdelta * Constants.MGDL_TO_MMOLL, units) + " " + units);
|
||||
|
@ -708,7 +708,7 @@ public class OverviewFragment extends Fragment {
|
|||
bgGraph.getGridLabelRenderer().setNumHorizontalLabels(7); // only 7 because of the space
|
||||
|
||||
// **** BG graph ****
|
||||
List<BgReading> bgReadingsArray = MainApp.getDbHelper().getDataFromTime(fromTime);
|
||||
List<BgReading> bgReadingsArray = MainApp.getDbHelper().getDataFromTime(fromTime, true);
|
||||
List<BgReading> inRangeArray = new ArrayList<BgReading>();
|
||||
List<BgReading> outOfRangeArray = new ArrayList<BgReading>();
|
||||
|
||||
|
|
|
@ -97,8 +97,8 @@ public class SafetyPlugin implements PluginBase, ConstraintsInterface {
|
|||
if (profile == null) return absoluteRate;
|
||||
if (absoluteRate < 0) absoluteRate = 0d;
|
||||
|
||||
Integer maxBasalMult = 4;
|
||||
Integer maxBasalFromDaily = 3;
|
||||
Integer maxBasalMult = Constants.CURRENT_BASAL_SAFETY_MULTIPLIER;
|
||||
Integer maxBasalFromDaily = Constants.MAX_DAILY_SAFETY_MULTIPLIER;
|
||||
// Check percentRate but absolute rate too, because we know real current basal in pump
|
||||
Double origRate = absoluteRate;
|
||||
if (absoluteRate > maxBasal) {
|
||||
|
@ -136,8 +136,8 @@ public class SafetyPlugin implements PluginBase, ConstraintsInterface {
|
|||
|
||||
if (absoluteRate < 0) absoluteRate = 0d;
|
||||
|
||||
Integer maxBasalMult = 4;
|
||||
Integer maxBasalFromDaily = 3;
|
||||
Integer maxBasalMult = Constants.CURRENT_BASAL_SAFETY_MULTIPLIER;
|
||||
Integer maxBasalFromDaily = Constants.MAX_DAILY_SAFETY_MULTIPLIER;
|
||||
// Check percentRate but absolute rate too, because we know real current basal in pump
|
||||
Double origRate = absoluteRate;
|
||||
if (absoluteRate > maxBasal) {
|
||||
|
|
|
@ -213,7 +213,7 @@ public class SmsCommunicatorPlugin implements PluginBase {
|
|||
} else if (lastBG != null) {
|
||||
reply = MainApp.sResources.getString(R.string.sms_lastbg) + " " + lastBG.valueToUnitsToString(units) + " " + String.format(MainApp.sResources.getString(R.string.sms_minago), agoMin) + ", ";
|
||||
}
|
||||
GlucoseStatus glucoseStatus = MainApp.getDbHelper().getGlucoseStatusData();
|
||||
GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData();
|
||||
if (glucoseStatus != null)
|
||||
reply += MainApp.sResources.getString(R.string.sms_delta) + " " + NSProfile.toUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units) + " " + units + ", ";
|
||||
|
||||
|
|
|
@ -197,10 +197,10 @@ public class TempBasalsPlugin implements PluginBase, TempBasalsInterface {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void updateTotalIOB() {
|
||||
public IobTotal getCalculationToTime(long time) {
|
||||
checkForExpired(tempBasals);
|
||||
checkForExpired(extendedBoluses);
|
||||
Date now = new Date();
|
||||
Date now = new Date(time);
|
||||
IobTotal total = new IobTotal();
|
||||
for (Integer pos = 0; pos < tempBasals.size(); pos++) {
|
||||
TempBasal t = tempBasals.get(pos);
|
||||
|
@ -214,6 +214,13 @@ public class TempBasalsPlugin implements PluginBase, TempBasalsInterface {
|
|||
total.plus(calc);
|
||||
}
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTotalIOB() {
|
||||
IobTotal total = getCalculationToTime(new Date().getTime());
|
||||
|
||||
lastCalculationTimestamp = new Date().getTime();
|
||||
lastCalculation = total;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import java.util.ArrayList;
|
|||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import info.nightscout.androidaps.Constants;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.data.Iob;
|
||||
|
@ -22,6 +23,7 @@ import info.nightscout.androidaps.events.EventTreatmentChange;
|
|||
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||
import info.nightscout.androidaps.interfaces.TreatmentsInterface;
|
||||
import info.nightscout.androidaps.data.IobTotal;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.client.data.NSProfile;
|
||||
|
||||
/**
|
||||
|
@ -112,28 +114,32 @@ public class TreatmentsPlugin implements PluginBase, TreatmentsInterface {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void updateTotalIOB() {
|
||||
public IobTotal getCalculationToTime(long time) {
|
||||
IobTotal total = new IobTotal();
|
||||
|
||||
if (MainApp.getConfigBuilder() == null || MainApp.getConfigBuilder().getActiveProfile() == null) // app not initialized yet
|
||||
return;
|
||||
NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile();
|
||||
if (profile == null) {
|
||||
lastCalculation = total;
|
||||
return;
|
||||
}
|
||||
if (MainApp.getConfigBuilder() == null || ConfigBuilderPlugin.getActiveProfile() == null) // app not initialized yet
|
||||
return total;
|
||||
NSProfile profile = ConfigBuilderPlugin.getActiveProfile().getProfile();
|
||||
if (profile == null)
|
||||
return total;
|
||||
|
||||
Double dia = profile.getDia();
|
||||
|
||||
Date now = new Date();
|
||||
Date now = new Date(time);
|
||||
for (Integer pos = 0; pos < treatments.size(); pos++) {
|
||||
Treatment t = treatments.get(pos);
|
||||
Iob tIOB = t.iobCalc(now, dia);
|
||||
total.iob += tIOB.iobContrib;
|
||||
total.activity += tIOB.activityContrib;
|
||||
Iob bIOB = t.iobCalc(now, dia / 2);
|
||||
Iob bIOB = t.iobCalc(now, dia / Constants.BOLUSSNOOZE_DIA_ADVISOR);
|
||||
total.bolussnooze += bIOB.iobContrib;
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTotalIOB() {
|
||||
IobTotal total = getCalculationToTime(new Date().getTime());
|
||||
|
||||
lastCalculationTimestamp = new Date().getTime();
|
||||
lastCalculation = total;
|
||||
|
|
|
@ -144,7 +144,7 @@ public class WatchUpdaterService extends WearableListenerService implements
|
|||
|
||||
BgReading lastBG = MainApp.getDbHelper().lastBg();
|
||||
if (lastBG != null) {
|
||||
GlucoseStatus glucoseStatus = MainApp.getDbHelper().getGlucoseStatusData();
|
||||
GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData();
|
||||
|
||||
if(googleApiClient != null && !googleApiClient.isConnected() && !googleApiClient.isConnecting()) { googleApiConnect(); }
|
||||
if (wear_integration) {
|
||||
|
@ -254,8 +254,8 @@ public class WatchUpdaterService extends WearableListenerService implements
|
|||
|
||||
if (last_bg == null) return;
|
||||
|
||||
List<BgReading> graph_bgs = MainApp.getDbHelper().getDataFromTime(startTime);
|
||||
GlucoseStatus glucoseStatus = MainApp.getDbHelper().getGlucoseStatusData();
|
||||
List<BgReading> graph_bgs = MainApp.getDbHelper().getDataFromTime(startTime, true);
|
||||
GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData();
|
||||
|
||||
if (!graph_bgs.isEmpty()) {
|
||||
DataMap entries = dataMapSingleBG(last_bg, glucoseStatus);
|
||||
|
|
|
@ -102,7 +102,7 @@ public class PersistentNotificationPlugin implements PluginBase{
|
|||
|
||||
|
||||
BgReading lastBG = MainApp.getDbHelper().lastBg();
|
||||
GlucoseStatus glucoseStatus = MainApp.getDbHelper().getGlucoseStatusData();
|
||||
GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData();
|
||||
|
||||
if(profile != null && lastBG != null) {
|
||||
line1 = lastBG.valueToUnitsToString(profile.getUnits());
|
||||
|
|
|
@ -17,7 +17,10 @@ public class JSONFormatter {
|
|||
public static Spanned format(final String jsonString) {
|
||||
final JsonVisitor visitor = new JsonVisitor(4, ' ');
|
||||
try {
|
||||
return Html.fromHtml(visitor.visit(new JSONObject(jsonString), 0));
|
||||
if (jsonString.getBytes()[0] == '[')
|
||||
return Html.fromHtml(visitor.visit(new JSONArray(jsonString), 0));
|
||||
else
|
||||
return Html.fromHtml(visitor.visit(new JSONObject(jsonString), 0));
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
return Html.fromHtml("");
|
||||
|
|
|
@ -398,4 +398,7 @@
|
|||
<string name="sms_minago">%dmin ago</string>
|
||||
<string name="localprofile">Local Profile</string>
|
||||
<string name="openapsama">OpenAPS AMA</string>
|
||||
<string name="short_avgdelta">Short avg. delta</string>
|
||||
<string name="long_avgdelta">Long avg. delta</string>
|
||||
<string name="array_of_elements">Array of %d elements.\nActual value:</string>
|
||||
</resources>
|
||||
|
|
Loading…
Reference in a new issue