diff --git a/app/libs/sightparser-release.aar b/app/libs/sightparser-release.aar index fdf02e2abb..20de889426 100644 Binary files a/app/libs/sightparser-release.aar and b/app/libs/sightparser-release.aar differ diff --git a/app/src/main/java/info/nightscout/androidaps/Constants.java b/app/src/main/java/info/nightscout/androidaps/Constants.java index e0549ab9bb..d933018790 100644 --- a/app/src/main/java/info/nightscout/androidaps/Constants.java +++ b/app/src/main/java/info/nightscout/androidaps/Constants.java @@ -38,6 +38,14 @@ public class Constants { //DanaR public static final double dailyLimitWarning = 0.95d; + // Temp targets + public static final int defaultActivityTTDuration = 90; // min + public static final double defaultActivityTTmgdl = 90d; + public static final double defaultActivityTTmmol = 5d; + public static final int defaultEatingSoonTTDuration = 45; // min + public static final double defaultEatingSoonTTmgdl = 140d; + public static final double defaultEatingSoonTTmmol = 8d; + //NSClientInternal public static final int MAX_LOG_LINES = 100; diff --git a/app/src/main/java/info/nightscout/androidaps/MainApp.java b/app/src/main/java/info/nightscout/androidaps/MainApp.java index 412383c6e1..2069ea557b 100644 --- a/app/src/main/java/info/nightscout/androidaps/MainApp.java +++ b/app/src/main/java/info/nightscout/androidaps/MainApp.java @@ -247,6 +247,10 @@ public class MainApp extends Application { return sResources.getString(id, args); } + public static int gc(int id) { + return sResources.getColor(id); + } + public static MainApp instance() { return sInstance; } diff --git a/app/src/main/java/info/nightscout/androidaps/data/Profile.java b/app/src/main/java/info/nightscout/androidaps/data/Profile.java index f461c84b2e..cb17802777 100644 --- a/app/src/main/java/info/nightscout/androidaps/data/Profile.java +++ b/app/src/main/java/info/nightscout/androidaps/data/Profile.java @@ -442,6 +442,14 @@ public class Profile { return ret; } + public double getTarget(){ + return getTarget(secondsFromMidnight(System.currentTimeMillis())); + } + + private double getTarget(Integer time) { + return (getTargetLow(time) + getTargetHigh(time))/2; + } + public Double getTargetLow() { return getTargetLow(secondsFromMidnight(System.currentTimeMillis())); } diff --git a/app/src/main/java/info/nightscout/androidaps/db/TempTarget.java b/app/src/main/java/info/nightscout/androidaps/db/TempTarget.java index c6d0ed18c4..980ce1c03c 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/TempTarget.java +++ b/app/src/main/java/info/nightscout/androidaps/db/TempTarget.java @@ -41,6 +41,10 @@ public class TempTarget implements Interval { @DatabaseField public int durationInMinutes; + public double target() { + return (low + high) / 2; + } + public boolean isEqual(TempTarget other) { if (date != other.date) { return false; diff --git a/app/src/main/java/info/nightscout/androidaps/db/TemporaryBasal.java b/app/src/main/java/info/nightscout/androidaps/db/TemporaryBasal.java index 3feb9c4ad2..806f65704a 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/TemporaryBasal.java +++ b/app/src/main/java/info/nightscout/androidaps/db/TemporaryBasal.java @@ -325,13 +325,13 @@ public class TemporaryBasal implements Interval { if(profile != null) { double basal = profile.getBasal(); if(basal != 0){ - return Math.round(rate*100d/basal) + "% "; + return Math.round(rate*100d/basal) + "%"; } } } - return DecimalFormatter.to2Decimal(rate) + "U/h "; + return DecimalFormatter.to2Decimal(rate) + "U/h"; } else { // percent - return percentRate + "% "; + return percentRate + "%"; } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/DetermineBasalAdapterAMAJS.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/DetermineBasalAdapterAMAJS.java index b9a67f0f4e..7f6df8466d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/DetermineBasalAdapterAMAJS.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/DetermineBasalAdapterAMAJS.java @@ -211,7 +211,8 @@ public class DetermineBasalAdapterAMAJS { mProfile.put("current_basal", basalrate); mProfile.put("temptargetSet", tempTargetSet); mProfile.put("autosens_adjust_targets", SP.getBoolean("openapsama_autosens_adjusttargets", true)); - mProfile.put("min_5m_carbimpact", SP.getInt("openapsama_min_5m_carbimpact", SMBDefaults.min_5m_carbimpact)); + //TODO: align with max-absorption model in AMA sensitivity + mProfile.put("min_5m_carbimpact", SP.getDouble("openapsama_min_5m_carbimpact", SMBDefaults.min_5m_carbimpact)); if (units.equals(Constants.MMOL)) { mProfile.put("out_units", "mmol/L"); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/OpenAPSAMAPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/OpenAPSAMAPlugin.java index bfe4fedf1f..9d537b5b2f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/OpenAPSAMAPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/OpenAPSAMAPlugin.java @@ -176,7 +176,7 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface { double maxBasal = SP.getDouble("openapsma_max_basal", 1d); double minBg = Profile.toMgdl(profile.getTargetLow(), units); double maxBg = Profile.toMgdl(profile.getTargetHigh(), units); - double targetBg = (minBg + maxBg) / 2; + double targetBg = Profile.toMgdl(profile.getTarget(), units); minBg = Round.roundTo(minBg, 0.1d); maxBg = Round.roundTo(maxBg, 0.1d); @@ -202,7 +202,7 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface { isTempTarget = true; minBg = HardLimits.verifyHardLimits(tempTarget.low, "minBg", HardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[0], HardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[1]); maxBg = HardLimits.verifyHardLimits(tempTarget.high, "maxBg", HardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[0], HardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[1]); - targetBg = HardLimits.verifyHardLimits((tempTarget.low + tempTarget.high) / 2, "targetBg", HardLimits.VERY_HARD_LIMIT_TEMP_TARGET_BG[0], HardLimits.VERY_HARD_LIMIT_TEMP_TARGET_BG[1]); + targetBg = HardLimits.verifyHardLimits(tempTarget.target(), "targetBg", HardLimits.VERY_HARD_LIMIT_TEMP_TARGET_BG[0], HardLimits.VERY_HARD_LIMIT_TEMP_TARGET_BG[1]); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/OpenAPSMAPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/OpenAPSMAPlugin.java index adb18491a4..9f071c75a2 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/OpenAPSMAPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/OpenAPSMAPlugin.java @@ -179,7 +179,7 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface { double maxBasal = SafeParse.stringToDouble(SP.getString("openapsma_max_basal", "1")); double minBg = Profile.toMgdl(profile.getTargetLow(), units); double maxBg = Profile.toMgdl(profile.getTargetHigh(), units); - double targetBg = (minBg + maxBg) / 2; + double targetBg = Profile.toMgdl(profile.getTarget(), units); minBg = Round.roundTo(minBg, 0.1d); maxBg = Round.roundTo(maxBg, 0.1d); @@ -205,7 +205,7 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface { if (tempTarget != null) { minBg = verifyHardLimits(tempTarget.low, "minBg", HardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[0], HardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[1]); maxBg = verifyHardLimits(tempTarget.high, "maxBg", HardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[0], HardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[1]); - targetBg = verifyHardLimits((tempTarget.low + tempTarget.high) / 2, "targetBg", HardLimits.VERY_HARD_LIMIT_TEMP_TARGET_BG[0], HardLimits.VERY_HARD_LIMIT_TEMP_TARGET_BG[1]); + targetBg = verifyHardLimits(tempTarget.target(), "targetBg", HardLimits.VERY_HARD_LIMIT_TEMP_TARGET_BG[0], HardLimits.VERY_HARD_LIMIT_TEMP_TARGET_BG[1]); } maxIob = verifyHardLimits(maxIob, "maxIob", 0, HardLimits.maxIobAMA()); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/DetermineBasalAdapterSMBJS.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/DetermineBasalAdapterSMBJS.java index b019dbe1cf..5ec19adfe8 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/DetermineBasalAdapterSMBJS.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/DetermineBasalAdapterSMBJS.java @@ -241,7 +241,8 @@ public class DetermineBasalAdapterSMBJS { 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));; + //TODO: align with max-absorption model in AMA sensitivity + mProfile.put("min_5m_carbimpact", SP.getDouble("openapsama_min_5m_carbimpact", SMBDefaults.min_5m_carbimpact));; mProfile.put("remainingCarbsCap", SMBDefaults.remainingCarbsCap); mProfile.put("enableUAM", SP.getBoolean(R.string.key_use_uam, false)); mProfile.put("A52_risk_enable", SMBDefaults.A52_risk_enable); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/OpenAPSSMBPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/OpenAPSSMBPlugin.java index c992f0e739..325951929a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/OpenAPSSMBPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/OpenAPSSMBPlugin.java @@ -181,7 +181,7 @@ public class OpenAPSSMBPlugin implements PluginBase, APSInterface { double maxBasal = SP.getDouble("openapsma_max_basal", 1d); double minBg = Profile.toMgdl(profile.getTargetLow(), units); double maxBg = Profile.toMgdl(profile.getTargetHigh(), units); - double targetBg = (minBg + maxBg) / 2; + double targetBg = Profile.toMgdl(profile.getTarget(), units); minBg = Round.roundTo(minBg, 0.1d); maxBg = Round.roundTo(maxBg, 0.1d); @@ -207,7 +207,7 @@ public class OpenAPSSMBPlugin implements PluginBase, APSInterface { isTempTarget = true; minBg = verifyHardLimits(tempTarget.low, "minBg", HardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[0], HardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[1]); maxBg = verifyHardLimits(tempTarget.high, "maxBg", HardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[0], HardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[1]); - targetBg = verifyHardLimits((tempTarget.low + tempTarget.high) / 2, "targetBg", HardLimits.VERY_HARD_LIMIT_TEMP_TARGET_BG[0], HardLimits.VERY_HARD_LIMIT_TEMP_TARGET_BG[1]); + targetBg = verifyHardLimits(tempTarget.target(), "targetBg", HardLimits.VERY_HARD_LIMIT_TEMP_TARGET_BG[0], HardLimits.VERY_HARD_LIMIT_TEMP_TARGET_BG[1]); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/SMBDefaults.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/SMBDefaults.java index a7e690ce79..0ce8d2bb94 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/SMBDefaults.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/SMBDefaults.java @@ -40,7 +40,7 @@ public class SMBDefaults { 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 double min_5m_carbimpact = 8d; // mg/dL per 5m (8 mg/dL/5m corresponds to 24g/hr at a CSF of 4 mg/dL/g (x/5*60/4)) public final static int remainingCarbsCap = 90; // max carbs we'll assume will absorb over 4h if we don't yet see carb absorption // WARNING: use SMB with caution: it can and will automatically bolus up to max_iob worth of extra insulin // enableUAM:true // enable detection of unannounced meal carb absorption diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java index 15e93816bd..6f46a5db8a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java @@ -36,15 +36,15 @@ import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.data.DetailedBolusInfo; +import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.db.CareportalEvent; import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.TempTarget; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.Loop.APSResult; import info.nightscout.androidaps.plugins.Loop.LoopPlugin; -import info.nightscout.androidaps.plugins.OpenAPSSMB.DetermineBasalResultSMB; import info.nightscout.androidaps.queue.Callback; import info.nightscout.utils.DateUtil; +import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.NumberPicker; import info.nightscout.utils.SP; import info.nightscout.utils.SafeParse; @@ -69,9 +69,9 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, D private static final double FAV1_DEFAULT = 5; private static final double FAV2_DEFAULT = 10; private static final double FAV3_DEFAULT = 20; - private CheckBox suspendLoopCheckbox; private CheckBox startActivityTTCheckbox; + private CheckBox startEatingSoonTTCheckbox; private Integer maxCarbs; @@ -103,7 +103,7 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, D Integer carbs = SafeParse.stringToInt(editCarbs.getText()); if (carbs > maxCarbs) { editCarbs.setValue(0d); - ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), getString(R.string.carbsconstraintapplied)); + ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.carbsconstraintapplied)); } } @@ -127,6 +127,7 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, D editCarbs.setParams(0d, 0d, (double) maxCarbs, 1d, new DecimalFormat("0"), false, textWatcher); startActivityTTCheckbox = view.findViewById(R.id.newcarbs_activity_tt); + startEatingSoonTTCheckbox = view.findViewById(R.id.carbs_eating_soon_tt); dateButton = view.findViewById(R.id.newcarbs_eventdate); timeButton = view.findViewById(R.id.newcarb_eventtime); @@ -138,6 +139,10 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, D dateButton.setOnClickListener(this); timeButton.setOnClickListener(this); + //To be able to select only one TT at a time + startEatingSoonTTCheckbox.setOnClickListener(this); + startActivityTTCheckbox.setOnClickListener(this); + // TODO prefilling carbs, maybe // TODO maybe update suggested carbs to target TT when checked // APSResult lastAPSResult = ConfigBuilderPlugin.getActiveAPS().getLastAPSResult(); @@ -147,13 +152,13 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, D fav1Button = view.findViewById(R.id.newcarbs_plus1); fav1Button.setOnClickListener(this); - fav1Button.setText("+" + SP.getString(MainApp.gs(R.string.key_carbs_button_increment_1), String.valueOf(FAV1_DEFAULT))); + fav1Button.setText("+" + SP.getString(R.string.key_carbs_button_increment_1, String.valueOf(FAV1_DEFAULT))); fav2Button = view.findViewById(R.id.newcarbs_plus2); fav2Button.setOnClickListener(this); - fav2Button.setText("+" + SP.getString(MainApp.gs(R.string.key_carbs_button_increment_2), String.valueOf(FAV2_DEFAULT))); + fav2Button.setText("+" + SP.getString(R.string.key_carbs_button_increment_2, String.valueOf(FAV2_DEFAULT))); fav3Button = view.findViewById(R.id.newcarbs_plus3); fav3Button.setOnClickListener(this); - fav3Button.setText("+" + SP.getString(MainApp.gs(R.string.key_carbs_button_increment_3), String.valueOf(FAV3_DEFAULT))); + fav3Button.setText("+" + SP.getString(R.string.key_carbs_button_increment_3, String.valueOf(FAV3_DEFAULT))); suspendLoopCheckbox = view.findViewById(R.id.newcarbs_suspend_loop); @@ -197,19 +202,26 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, D break; case R.id.newcarbs_plus1: editCarbs.setValue(editCarbs.getValue() - + SP.getDouble(MainApp.gs(R.string.key_carbs_button_increment_1), FAV1_DEFAULT)); + + SP.getDouble(R.string.key_carbs_button_increment_1, FAV1_DEFAULT)); validateInputs(); break; case R.id.newcarbs_plus2: editCarbs.setValue(editCarbs.getValue() - + SP.getDouble(MainApp.gs(R.string.key_carbs_button_increment_2), FAV2_DEFAULT)); + + SP.getDouble(R.string.key_carbs_button_increment_2, FAV2_DEFAULT)); validateInputs(); break; case R.id.newcarbs_plus3: editCarbs.setValue(editCarbs.getValue() - + SP.getDouble(MainApp.gs(R.string.key_carbs_button_increment_3), FAV3_DEFAULT)); + + SP.getDouble(R.string.key_carbs_button_increment_3, FAV3_DEFAULT)); validateInputs(); break; + case R.id.newcarbs_activity_tt: + startEatingSoonTTCheckbox.setChecked(false); + break; + case R.id.carbs_eating_soon_tt: + startActivityTTCheckbox.setChecked(false); + break; + } } @@ -227,20 +239,46 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, D String confirmMessage = ""; if (carbs > 0) - confirmMessage += getString(R.string.carbs) + ": " + "" + carbsAfterConstraints + "g" + ""; + confirmMessage += MainApp.gs(R.string.carbs) + ": " + "" + carbsAfterConstraints + "g" + ""; if (!carbsAfterConstraints.equals(carbs)) - confirmMessage += "
" + getString(R.string.carbsconstraintapplied) + ""; + confirmMessage += "
" + MainApp.gs(R.string.carbsconstraintapplied) + ""; if (suspendLoopCheckbox.isChecked()) { - confirmMessage += "
" + "Loop: " + "" + "Suspend for 30 min"; + confirmMessage += "
" + MainApp.gs(R.string.loop) + ": " + "" + MainApp.gs(R.string.suspendloopfor30min) + ""; } - double prefTTDuration = SP.getDouble(R.string.key_activity_duration, 90d); - double ttDuration = prefTTDuration > 0 ? prefTTDuration : 90d; - double prefTT = SP.getDouble(R.string.key_activity_target, 140d); - double tt = prefTT > 0 ? prefTT : 140d; + final Profile currentProfile = MainApp.getConfigBuilder().getProfile(); + if (currentProfile == null) + return; + + int activityTTDuration = SP.getInt(R.string.key_activity_duration, Constants.defaultActivityTTDuration); + activityTTDuration = activityTTDuration > 0 ? activityTTDuration : Constants.defaultActivityTTDuration; + double activityTT = SP.getDouble(R.string.key_activity_target, currentProfile.getUnits().equals(Constants.MMOL) ? Constants.defaultActivityTTmmol : Constants.defaultActivityTTmgdl); + activityTT = activityTT > 0 ? activityTT : currentProfile.getUnits().equals(Constants.MMOL) ? Constants.defaultActivityTTmmol : Constants.defaultActivityTTmgdl; + + int eatingSoonTTDuration = SP.getInt(R.string.key_eatingsoon_duration, Constants.defaultEatingSoonTTDuration); + eatingSoonTTDuration = eatingSoonTTDuration > 0 ? eatingSoonTTDuration : Constants.defaultEatingSoonTTDuration; + double eatingSoonTT = SP.getDouble(R.string.key_eatingsoon_target, currentProfile.getUnits().equals(Constants.MMOL) ? Constants.defaultEatingSoonTTmmol : Constants.defaultEatingSoonTTmgdl); + eatingSoonTT = eatingSoonTT > 0 ? Profile.toMgdl(eatingSoonTT, currentProfile.getUnits()) : currentProfile.getUnits().equals(Constants.MMOL) ? Constants.defaultEatingSoonTTmmol : Constants.defaultEatingSoonTTmgdl; + + if (startActivityTTCheckbox.isChecked()) { - confirmMessage += "
" + "TT: " + "" + ((int) tt) + "mg/dl for " + ((int) ttDuration) + " min "; + if (currentProfile.getUnits().equals(Constants.MMOL)) { + confirmMessage += "
" + MainApp.gs(R.string.temptargetshort) + ": " + "" + DecimalFormatter.to1Decimal(activityTT) + " mmol/l (" + ((int) activityTTDuration) + " min)"; + } else + confirmMessage += "
" + MainApp.gs(R.string.temptargetshort) + ": " + "" + DecimalFormatter.to0Decimal(activityTT) + " mg/dl (" + ((int) activityTTDuration) + " min)"; + } + if (startEatingSoonTTCheckbox.isChecked() && !startActivityTTCheckbox.isChecked()) { + if (currentProfile.getUnits().equals(Constants.MMOL)) { + confirmMessage += "
" + MainApp.gs(R.string.temptargetshort) + ": " + "" + DecimalFormatter.to1Decimal(eatingSoonTT) + " mmol/l (" + eatingSoonTTDuration + " min)"; + } else + confirmMessage += "
" + MainApp.gs(R.string.temptargetshort) + ": " + "" + DecimalFormatter.to0Decimal(eatingSoonTT) + " mg/dl (" + eatingSoonTTDuration + " min)"; + + } + final double finalActivityTT = activityTT; + final double finalEatigSoonTT = eatingSoonTT; + final int finalActivityTTDuration = activityTTDuration; + final int finalEatingSoonTTDuration = eatingSoonTTDuration; if (StringUtils.isNoneEmpty(food)) { confirmMessage += "
" + "Food: " + food; @@ -249,66 +287,80 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, D if (!initialEventTime.equals(eventTime)) { confirmMessage += "
Time: " + DateUtil.dateAndTimeString(eventTime); } + if (confirmMessage.length() > 0) { - final int finalCarbsAfterConstraints = carbsAfterConstraints; + final int finalCarbsAfterConstraints = carbsAfterConstraints; - final Context context = getContext(); - final AlertDialog.Builder builder = new AlertDialog.Builder(context); + final Context context = getContext(); + final AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setTitle(this.getContext().getString(R.string.confirmation)); - if (confirmMessage.startsWith("
")) - confirmMessage = confirmMessage.substring("
".length()); - builder.setMessage(Html.fromHtml(confirmMessage)); - builder.setPositiveButton(getString(R.string.ok), (dialog, id) -> { - synchronized (builder) { - if (accepted) { - log.debug("guarding: already accepted"); - return; - } - accepted = true; + builder.setTitle(MainApp.gs(R.string.confirmation)); + if (confirmMessage.startsWith("
")) + confirmMessage = confirmMessage.substring("
".length()); - if (suspendLoopCheckbox.isChecked()) { - final LoopPlugin activeloop = ConfigBuilderPlugin.getActiveLoop(); - activeloop.suspendTo(System.currentTimeMillis() + 30L * 60 * 1000); - ConfigBuilderPlugin.getCommandQueue().cancelTempBasal(true, new Callback() { - @Override - public void run() { - if (!result.success) { - ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.tempbasaldeliveryerror)); + builder.setMessage(Html.fromHtml(confirmMessage)); + builder.setPositiveButton(MainApp.gs(R.string.ok), (dialog, id) -> { + synchronized (builder) { + if (accepted) { + log.debug("guarding: already accepted"); + return; + } + accepted = true; + + if (suspendLoopCheckbox.isChecked()) { + final LoopPlugin activeloop = ConfigBuilderPlugin.getActiveLoop(); + activeloop.suspendTo(System.currentTimeMillis() + 30L * 60 * 1000); + ConfigBuilderPlugin.getCommandQueue().cancelTempBasal(true, new Callback() { + @Override + public void run() { + if (!result.success) { + ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.tempbasaldeliveryerror)); + } } - } - }); - } + }); + } - if (startActivityTTCheckbox.isChecked()) { - TempTarget tempTarget = new TempTarget(); - tempTarget.date = System.currentTimeMillis(); - tempTarget.durationInMinutes = (int) ttDuration; - tempTarget.reason = "Activity"; - tempTarget.source = Source.USER; - tempTarget.low = (int) tt; - tempTarget.high = (int) tt; - MainApp.getDbHelper().createOrUpdate(tempTarget); - } + if (startActivityTTCheckbox.isChecked()) { + TempTarget tempTarget = new TempTarget(); + tempTarget.date = System.currentTimeMillis(); + tempTarget.durationInMinutes = finalActivityTTDuration; + tempTarget.reason = MainApp.gs(R.string.activity); + tempTarget.source = Source.USER; + tempTarget.low = Profile.toMgdl(finalActivityTT, currentProfile.getUnits()); + tempTarget.high = Profile.toMgdl(finalActivityTT, currentProfile.getUnits()); + MainApp.getDbHelper().createOrUpdate(tempTarget); + } else if (startEatingSoonTTCheckbox.isChecked()) { + TempTarget tempTarget = new TempTarget(); + tempTarget.date = System.currentTimeMillis(); + tempTarget.durationInMinutes = finalEatingSoonTTDuration; + tempTarget.reason = MainApp.gs(R.string.eatingsoon); + tempTarget.source = Source.USER; + tempTarget.low = Profile.toMgdl(finalEatigSoonTT, currentProfile.getUnits()); + tempTarget.high = Profile.toMgdl(finalEatigSoonTT, currentProfile.getUnits()); + MainApp.getDbHelper().createOrUpdate(tempTarget); + } - if (finalCarbsAfterConstraints > 0 || food != null) { - DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); - detailedBolusInfo.date = eventTime.getTime(); - detailedBolusInfo.eventType = CareportalEvent.CARBCORRECTION; - detailedBolusInfo.carbs = finalCarbsAfterConstraints; + if (finalCarbsAfterConstraints > 0 || food != null) { + DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); + detailedBolusInfo.date = eventTime.getTime(); + detailedBolusInfo.eventType = CareportalEvent.CARBCORRECTION; + detailedBolusInfo.carbs = finalCarbsAfterConstraints; // detailedBolusInfo.food = food; - detailedBolusInfo.context = context; - detailedBolusInfo.source = Source.USER; - MainApp.getConfigBuilder().addToHistoryTreatment(detailedBolusInfo); + detailedBolusInfo.context = context; + detailedBolusInfo.source = Source.USER; + MainApp.getConfigBuilder().addToHistoryTreatment(detailedBolusInfo); + } } - } - }); - builder.setNegativeButton(getString(R.string.cancel), null); - builder.show(); - dismiss(); + }); + builder.setNegativeButton(MainApp.gs(R.string.cancel), null); + builder.show(); + dismiss(); + } else + dismiss(); } catch (Exception e) { log.error("Unhandled exception", e); } + } @Override @@ -326,4 +378,4 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, D eventTime.setSeconds(second); timeButton.setText(DateUtil.timeString(eventTime)); } -} \ No newline at end of file +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewInsulinDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewInsulinDialog.java index 7c86cde764..0b8b263262 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewInsulinDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewInsulinDialog.java @@ -246,8 +246,19 @@ public class NewInsulinDialog extends DialogFragment implements OnClickListener, double ttDuration = prefTTDuration > 0 ? prefTTDuration : 45d; double prefTT = SP.getDouble(R.string.key_eatingsoon_target, 80d); double tt = prefTT > 0 ? prefTT : 80d; + Profile currentProfile = MainApp.getConfigBuilder().getProfile(); + if(currentProfile == null) + return; + if(currentProfile.getUnits().equals(Constants.MMOL)) + tt = prefTT > 0 ? Profile.toMgdl(prefTT, Constants.MMOL) : 80d; + else + tt = prefTT > 0 ? prefTT : 80d; + final double finalTT = tt; if (startESMCheckbox.isChecked()) { - confirmMessage += "
" + "TT: " + "" + ((int) tt) + "mg/dl for " + ((int) ttDuration) + " min "; + if(currentProfile.getUnits().equals("mmol")){ + confirmMessage += "
" + "TT: " + "" + Profile.toMmol(tt, Constants.MGDL) + " mmol for " + ((int) ttDuration) + " min "; + } else + confirmMessage += "
" + "TT: " + "" + ((int) tt) + "mg/dl for " + ((int) ttDuration) + " min "; } if (!initialEventTime.equals(eventTime)) { @@ -277,8 +288,8 @@ public class NewInsulinDialog extends DialogFragment implements OnClickListener, tempTarget.durationInMinutes = (int) ttDuration; tempTarget.reason = "Eating soon"; tempTarget.source = Source.USER; - tempTarget.low = (int) tt; - tempTarget.high = (int) tt; + tempTarget.low = (int) finalTT; + tempTarget.high = (int) finalTT; MainApp.getDbHelper().createOrUpdate(tempTarget); } @@ -339,4 +350,4 @@ public class NewInsulinDialog extends DialogFragment implements OnClickListener, eventTime.setSeconds(second); timeButton.setText(DateUtil.timeString(eventTime)); } -} \ No newline at end of file +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphData/GraphData.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphData/GraphData.java index 02bb1a7b3d..b13ab19219 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphData/GraphData.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphData/GraphData.java @@ -249,7 +249,7 @@ public class GraphData { if (tt == null) { value = (profile.getTargetLow(time) + profile.getTargetHigh(time)) / 2; } else { - value = (tt.low + tt.high) / 2; + value = tt.target(); } if (lastTarget > 0 && lastTarget != value) { targetsSeriesArray.add(new DataPoint(time, lastTarget)); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/InsightPumpPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/InsightPumpPlugin.java index fe5f84d66f..ba5fa0fa11 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/InsightPumpPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/InsightPumpPlugin.java @@ -27,13 +27,15 @@ import info.nightscout.androidaps.interfaces.ConstraintsInterface; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.interfaces.PumpInterface; +import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress; import info.nightscout.androidaps.plugins.Overview.notifications.Notification; -import info.nightscout.androidaps.plugins.PumpInsight.connector.AbsoluteTBRTaskRunner; import info.nightscout.androidaps.plugins.PumpInsight.connector.CancelBolusTaskRunner; import info.nightscout.androidaps.plugins.PumpInsight.connector.Connector; +import info.nightscout.androidaps.plugins.PumpInsight.connector.ReadBasalProfileTaskRunner; import info.nightscout.androidaps.plugins.PumpInsight.connector.SetTBRTaskRunner; +import info.nightscout.androidaps.plugins.PumpInsight.connector.WriteBasalProfileTaskRunner; import info.nightscout.androidaps.plugins.PumpInsight.events.EventInsightPumpCallback; import info.nightscout.androidaps.plugins.PumpInsight.events.EventInsightPumpUpdateGui; import info.nightscout.androidaps.plugins.PumpInsight.history.HistoryReceiver; @@ -46,6 +48,7 @@ import info.nightscout.utils.SP; import sugar.free.sightparser.applayer.descriptors.ActiveBolus; import sugar.free.sightparser.applayer.descriptors.ActiveBolusType; import sugar.free.sightparser.applayer.descriptors.PumpStatus; +import sugar.free.sightparser.applayer.descriptors.configuration_blocks.BRProfileBlock; import sugar.free.sightparser.applayer.messages.AppLayerMessage; import sugar.free.sightparser.applayer.messages.remote_control.BolusMessage; import sugar.free.sightparser.applayer.messages.remote_control.CancelTBRMessage; @@ -56,7 +59,6 @@ import sugar.free.sightparser.handling.TaskRunner; import sugar.free.sightparser.handling.taskrunners.StatusTaskRunner; import static info.nightscout.androidaps.plugins.PumpInsight.history.PumpIdCache.getRecordUniqueID; -import static info.nightscout.androidaps.plugins.PumpInsight.utils.Helpers.roundDouble; /** @@ -93,6 +95,7 @@ public class InsightPumpPlugin implements PluginBase, PumpInterface, Constraints private double basalRate = 0; private Connector connector; private volatile boolean connector_enabled = false; + private List profileBlocks; private final TaskRunner.ResultCallback statusResultHandler = new TaskRunner.ResultCallback() { @Override @@ -110,13 +113,17 @@ public class InsightPumpPlugin implements PluginBase, PumpInterface, Constraints @Override public synchronized void onResult(Object result) { - log("GOT STATUS RESULT!!!"); - statusResult = (StatusTaskRunner.StatusResult) result; - statusResultTime = Helpers.tsl(); - processStatusResult(); - updateGui(); - connector.requestHistoryReSync(); - connector.requestHistorySync(); + if (result instanceof StatusTaskRunner.StatusResult) { + log("GOT STATUS RESULT!!!"); + statusResult = (StatusTaskRunner.StatusResult) result; + statusResultTime = Helpers.tsl(); + processStatusResult(); + updateGui(); + connector.requestHistoryReSync(); + connector.requestHistorySync(); + } else if (result instanceof List) { + profileBlocks = (List) result; + } } }; @@ -142,7 +149,7 @@ public class InsightPumpPlugin implements PluginBase, PumpInterface, Constraints pumpDescription.tempDurationStep30mAllowed = true; pumpDescription.tempMaxDuration = 24 * 60; - pumpDescription.isSetBasalProfileCapable = false; // leave this for now + pumpDescription.isSetBasalProfileCapable = true; // leave this for now pumpDescription.basalStep = 0.01d; pumpDescription.basalMinimumRate = 0.02d; @@ -378,6 +385,7 @@ public class InsightPumpPlugin implements PluginBase, PumpInterface, Constraints public void run() { taskRunner = new StatusTaskRunner(connector.getServiceConnector()); taskRunner.fetch(statusResultHandler); + new ReadBasalProfileTaskRunner(connector.getServiceConnector()).fetch(statusResultHandler); } } , 1000); @@ -386,21 +394,59 @@ public class InsightPumpPlugin implements PluginBase, PumpInterface, Constraints } } - // TODO implement + + @Override public PumpEnactResult setNewBasalProfile(Profile profile) { - lastDataTime = new Date(); - // Do nothing here. we are using MainApp.getConfigBuilder().getActiveProfile().getProfile(); PumpEnactResult result = new PumpEnactResult(); - result.enacted = false; - result.success = false; - Notification notification = new Notification(Notification.PROFILE_SET_OK, MainApp.sResources.getString(R.string.profile_set_ok), Notification.INFO, 60); - MainApp.bus().post(new EventNewNotification(notification)); + if (!isInitialized()) { + log.error("setNewBasalProfile not initialized"); + Notification notification = new Notification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED, MainApp.sResources.getString(R.string.pumpNotInitializedProfileNotSet), Notification.URGENT); + MainApp.bus().post(new EventNewNotification(notification)); + result.comment = MainApp.sResources.getString(R.string.pumpNotInitializedProfileNotSet); + return result; + } else { + MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED)); + } + List profileBlocks = new ArrayList<>(); + for (int i = 0; i < profile.getBasalValues().length; i++) { + Profile.BasalValue basalValue = profile.getBasalValues()[i]; + Profile.BasalValue nextValue = null; + if (profile.getBasalValues().length > i + 1) nextValue = profile.getBasalValues()[i + 1]; + profileBlocks.add(new BRProfileBlock.ProfileBlock((((nextValue != null ? nextValue.timeAsSeconds : 24 * 60 * 60) - basalValue.timeAsSeconds) / 60), basalValue.value)); + } + final UUID uuid = aSyncTaskRunner(new WriteBasalProfileTaskRunner(connector.getServiceConnector(), profileBlocks), "Write basal profile"); + final Mstatus ms = async.busyWaitForCommandResult(uuid, BUSY_WAIT_TIME); + if (ms.success()) { + MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED)); + MainApp.bus().post(new EventDismissNotification(Notification.FAILED_UDPATE_PROFILE)); + Notification notification = new Notification(Notification.PROFILE_SET_OK, MainApp.sResources.getString(R.string.profile_set_ok), Notification.INFO, 60); + MainApp.bus().post(new EventNewNotification(notification)); + result.success = true; + result.enacted = true; + result.comment = "OK"; + } else { + Notification notification = new Notification(Notification.FAILED_UDPATE_PROFILE, MainApp.sResources.getString(R.string.failedupdatebasalprofile), Notification.URGENT); + MainApp.bus().post(new EventNewNotification(notification)); + result.comment = MainApp.sResources.getString(R.string.failedupdatebasalprofile); + } return result; } @Override public boolean isThisProfileSet(Profile profile) { + if (!isInitialized() || profileBlocks == null) return true; + if (profile.getBasalValues().length != profileBlocks.size()) return false; + for (int i = 0; i < profileBlocks.size(); i++) { + BRProfileBlock.ProfileBlock profileBlock = profileBlocks.get(i); + Profile.BasalValue basalValue = profile.getBasalValues()[i]; + Profile.BasalValue nextValue = null; + if (profile.getBasalValues().length > i + 1) nextValue = profile.getBasalValues()[i + 1]; + if (profileBlock == null || basalValue == null) return false; + if (profileBlock.getDuration() * 60 != (nextValue != null ? nextValue.timeAsSeconds : 24 * 60 * 60) - basalValue.timeAsSeconds) return false; + //Allow a little imprecision due to rounding errors + if (Math.abs(profileBlock.getAmount() - basalValue.value) > 0.2D) return false; + } return true; } @@ -431,7 +477,7 @@ public class InsightPumpPlugin implements PluginBase, PumpInterface, Constraints // is there an insulin component to the treatment? if (detailedBolusInfo.insulin > 0) { - final UUID cmd = deliverBolus((float) detailedBolusInfo.insulin); // actually request delivery + final UUID cmd = deliverBolus(detailedBolusInfo.insulin); // actually request delivery if (cmd == null) { return pumpEnactFailure(); } @@ -545,51 +591,6 @@ public class InsightPumpPlugin implements PluginBase, PumpInterface, Constraints return pumpEnactResult; } - //@Override - public PumpEnactResult setTempBasalAbsoluteOld(Double absoluteRate, Integer durationInMinutes, boolean enforceNew) { - absoluteRate = Helpers.roundDouble(absoluteRate, 3); - log("Set TBR absolute: " + absoluteRate); - - final AbsoluteTBRTaskRunner task = new AbsoluteTBRTaskRunner(connector.getServiceConnector(), absoluteRate, durationInMinutes); - final UUID cmd = aSyncTaskRunner(task, "Set TBR abs: " + absoluteRate + " " + durationInMinutes + "m"); - - if (cmd == null) { - return pumpEnactFailure(); - } - - Mstatus ms = async.busyWaitForCommandResult(cmd, BUSY_WAIT_TIME); - log("Got command status: " + ms); - - PumpEnactResult pumpEnactResult = new PumpEnactResult().enacted(true).isPercent(false).duration(durationInMinutes); - pumpEnactResult.absolute = absoluteRate; // TODO get converted value? - pumpEnactResult.success = ms.success(); - pumpEnactResult.isTempCancel = false; // do we test this here? - pumpEnactResult.comment = ms.getCommandComment(); - - if (pumpEnactResult.success) { - // create log entry - final TemporaryBasal tempBasal = new TemporaryBasal(); - tempBasal.date = System.currentTimeMillis(); - tempBasal.isAbsolute = true; - tempBasal.absoluteRate = task.getCalculatedAbsolute(); // is this the correct figure to use? - tempBasal.durationInMinutes = durationInMinutes; - tempBasal.source = Source.USER; - MainApp.getConfigBuilder().addToHistoryTempBasal(tempBasal); - } - - if (Config.logPumpComm) - log.debug("Setting temp basal absolute: " + pumpEnactResult.success); - - lastDataTime = new Date(); - - updateGui(); - - connector.requestHistorySync(5000); - connector.tryToGetPumpStatusAgain(); - - return pumpEnactResult; - } - @Override public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, boolean enforceNew) { @@ -686,8 +687,8 @@ public class InsightPumpPlugin implements PluginBase, PumpInterface, Constraints public PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes) { log("Set Extended bolus " + insulin + " " + durationInMinutes); ExtendedBolusMessage extendedBolusMessage = new ExtendedBolusMessage(); - extendedBolusMessage.setAmount((float) ((double) insulin)); - extendedBolusMessage.setDuration((short) ((int) durationInMinutes)); + extendedBolusMessage.setAmount(insulin); + extendedBolusMessage.setDuration(durationInMinutes); final UUID cmd = aSyncSingleCommand(extendedBolusMessage, "Extended bolus U" + insulin + " mins:" + durationInMinutes); if (cmd == null) { return pumpEnactFailure(); @@ -755,7 +756,7 @@ public class InsightPumpPlugin implements PluginBase, PumpInterface, Constraints } - private synchronized UUID deliverBolus(float bolusValue) { + private synchronized UUID deliverBolus(double bolusValue) { log("DeliverBolus: " + bolusValue); if (bolusValue == 0) return null; @@ -838,7 +839,7 @@ public class InsightPumpPlugin implements PluginBase, PumpInterface, Constraints if (statusResult != null) { batteryPercent = statusResult.getBatteryAmountMessage().getBatteryAmount(); reservoirInUnits = (int) statusResult.getCartridgeAmountMessage().getCartridgeAmount(); - basalRate = roundDouble(statusResult.getCurrentBasalMessage().getCurrentBasalAmount(), 2); + basalRate = statusResult.getCurrentBasalMessage().getCurrentBasalAmount(); initialized = true; // basic communication test } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/connector/AbsoluteTBRTaskRunner.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/connector/AbsoluteTBRTaskRunner.java deleted file mode 100644 index 923ed84dc8..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/connector/AbsoluteTBRTaskRunner.java +++ /dev/null @@ -1,60 +0,0 @@ -package info.nightscout.androidaps.plugins.PumpInsight.connector; - -import info.nightscout.androidaps.plugins.PumpInsight.utils.Helpers; -import sugar.free.sightparser.applayer.messages.AppLayerMessage; -import sugar.free.sightparser.applayer.messages.remote_control.ChangeTBRMessage; -import sugar.free.sightparser.applayer.messages.remote_control.SetTBRMessage; -import sugar.free.sightparser.applayer.messages.status.CurrentBasalMessage; -import sugar.free.sightparser.applayer.messages.status.CurrentTBRMessage; -import sugar.free.sightparser.handling.SightServiceConnector; -import sugar.free.sightparser.handling.TaskRunner; - -// by Tebbe Ubben - -public class AbsoluteTBRTaskRunner extends TaskRunner { - - private double absolute; - private int amount; - private int duration; - private int calculated_percentage; - private double calculated_absolute; - - public AbsoluteTBRTaskRunner(SightServiceConnector serviceConnector, double absolute, int duration) { - super(serviceConnector); - if (absolute < 0) absolute = 0; - this.absolute = absolute; - this.duration = duration; - } - - public int getCalculatedPercentage() { - return calculated_percentage; - } - - public double getCalculatedAbsolute() { - return calculated_absolute; - } - - @Override - protected AppLayerMessage run(AppLayerMessage message) throws Exception { - if (message == null) return new CurrentBasalMessage(); - else if (message instanceof CurrentBasalMessage) { - float currentBasal = ((CurrentBasalMessage) message).getCurrentBasalAmount(); - amount = (int) (100d / currentBasal * absolute); - amount = ((int) amount / 10) * 10; - if (amount > 250) amount = 250; - calculated_percentage = amount; - calculated_absolute = Helpers.roundDouble(calculated_percentage * (double) currentBasal / 100d, 3); - Connector.log("Asked: " + absolute + " current: " + currentBasal + " calculated as: " + amount + "%" + " = " + calculated_absolute); - return new CurrentTBRMessage(); - } else if (message instanceof CurrentTBRMessage) { - SetTBRMessage setTBRMessage; - if (((CurrentTBRMessage) message).getPercentage() == 100) - setTBRMessage = new SetTBRMessage(); - else setTBRMessage = new ChangeTBRMessage(); - setTBRMessage.setAmount((short) amount); - setTBRMessage.setDuration((short) duration); - return setTBRMessage; - } else if (message instanceof SetTBRMessage) finish(amount); - return null; - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/connector/ReadBasalProfileTaskRunner.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/connector/ReadBasalProfileTaskRunner.java new file mode 100644 index 0000000000..f201d20dfe --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/connector/ReadBasalProfileTaskRunner.java @@ -0,0 +1,65 @@ +package info.nightscout.androidaps.plugins.PumpInsight.connector; + +import android.util.Log; + +import sugar.free.sightparser.applayer.descriptors.configuration_blocks.ActiveProfileBlock; +import sugar.free.sightparser.applayer.descriptors.configuration_blocks.BRProfile1Block; +import sugar.free.sightparser.applayer.descriptors.configuration_blocks.BRProfile2Block; +import sugar.free.sightparser.applayer.descriptors.configuration_blocks.BRProfile3Block; +import sugar.free.sightparser.applayer.descriptors.configuration_blocks.BRProfile4Block; +import sugar.free.sightparser.applayer.descriptors.configuration_blocks.BRProfile5Block; +import sugar.free.sightparser.applayer.descriptors.configuration_blocks.BRProfileBlock; +import sugar.free.sightparser.applayer.descriptors.configuration_blocks.ConfigurationBlock; +import sugar.free.sightparser.applayer.messages.AppLayerMessage; +import sugar.free.sightparser.applayer.messages.configuration.ReadConfigurationBlockMessage; +import sugar.free.sightparser.handling.SightServiceConnector; +import sugar.free.sightparser.handling.TaskRunner; + +/** + * Created by Tebbe Ubben on 10.03.2018. + */ + +public class ReadBasalProfileTaskRunner extends TaskRunner { + + public ReadBasalProfileTaskRunner(SightServiceConnector serviceConnector) { + super(serviceConnector); + } + + @Override + protected AppLayerMessage run(AppLayerMessage message) throws Exception { + if (message == null) { + ReadConfigurationBlockMessage readMessage = new ReadConfigurationBlockMessage(); + readMessage.setConfigurationBlockID(ActiveProfileBlock.ID); + return readMessage; + } else if (message instanceof ReadConfigurationBlockMessage) { + ConfigurationBlock configurationBlock = ((ReadConfigurationBlockMessage) message).getConfigurationBlock(); + if (configurationBlock instanceof ActiveProfileBlock) { + ActiveProfileBlock activeProfileBlock = (ActiveProfileBlock) configurationBlock; + ReadConfigurationBlockMessage readMessage = new ReadConfigurationBlockMessage(); + switch (activeProfileBlock.getActiveProfile()) { + case BR_PROFILE_1: + readMessage.setConfigurationBlockID(BRProfile1Block.ID); + break; + case BR_PROFILE_2: + readMessage.setConfigurationBlockID(BRProfile2Block.ID); + break; + case BR_PROFILE_3: + readMessage.setConfigurationBlockID(BRProfile3Block.ID); + break; + case BR_PROFILE_4: + readMessage.setConfigurationBlockID(BRProfile4Block.ID); + break; + case BR_PROFILE_5: + readMessage.setConfigurationBlockID(BRProfile5Block.ID); + break; + } + ReadConfigurationBlockMessage test = new ReadConfigurationBlockMessage(); + test.setConfigurationBlockID(BRProfile1Block.ID); + return test; + } else if (configurationBlock instanceof BRProfileBlock) { + finish(((BRProfileBlock) configurationBlock).getProfileBlocks()); + } + } + return null; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/connector/SetTBRTaskRunner.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/connector/SetTBRTaskRunner.java index 5d22feba8f..1506ecb4a9 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/connector/SetTBRTaskRunner.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/connector/SetTBRTaskRunner.java @@ -28,20 +28,20 @@ public class SetTBRTaskRunner extends TaskRunner { if (amount == 100) finish(amount); else { SetTBRMessage setTBRMessage = new SetTBRMessage(); - setTBRMessage.setDuration((short) duration); - setTBRMessage.setAmount((short) amount); + setTBRMessage.setDuration(duration); + setTBRMessage.setAmount(amount); return setTBRMessage; } } else { if (amount == 100) { ChangeTBRMessage changeTBRMessage = new ChangeTBRMessage(); - changeTBRMessage.setDuration((short) 1); - changeTBRMessage.setAmount((short) 90); + changeTBRMessage.setDuration(1); + changeTBRMessage.setAmount(90); return changeTBRMessage; } else { ChangeTBRMessage changeTBRMessage = new ChangeTBRMessage(); - changeTBRMessage.setDuration((short) duration); - changeTBRMessage.setAmount((short) amount); + changeTBRMessage.setDuration(duration); + changeTBRMessage.setAmount(amount); return changeTBRMessage; } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/connector/WriteBasalProfileTaskRunner.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/connector/WriteBasalProfileTaskRunner.java new file mode 100644 index 0000000000..7012d200e7 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/connector/WriteBasalProfileTaskRunner.java @@ -0,0 +1,72 @@ +package info.nightscout.androidaps.plugins.PumpInsight.connector; + +import java.util.List; + +import sugar.free.sightparser.applayer.descriptors.configuration_blocks.ActiveProfileBlock; +import sugar.free.sightparser.applayer.descriptors.configuration_blocks.BRProfile1Block; +import sugar.free.sightparser.applayer.descriptors.configuration_blocks.BRProfile2Block; +import sugar.free.sightparser.applayer.descriptors.configuration_blocks.BRProfile3Block; +import sugar.free.sightparser.applayer.descriptors.configuration_blocks.BRProfile4Block; +import sugar.free.sightparser.applayer.descriptors.configuration_blocks.BRProfile5Block; +import sugar.free.sightparser.applayer.descriptors.configuration_blocks.BRProfileBlock; +import sugar.free.sightparser.applayer.descriptors.configuration_blocks.ConfigurationBlock; +import sugar.free.sightparser.applayer.messages.AppLayerMessage; +import sugar.free.sightparser.applayer.messages.configuration.CloseWriteSessionMessage; +import sugar.free.sightparser.applayer.messages.configuration.OpenWriteSessionMessage; +import sugar.free.sightparser.applayer.messages.configuration.ReadConfigurationBlockMessage; +import sugar.free.sightparser.applayer.messages.configuration.WriteConfigurationBlockMessage; +import sugar.free.sightparser.handling.SightServiceConnector; +import sugar.free.sightparser.handling.TaskRunner; + +/** + * Created by Tebbe Ubben on 10.03.2018. + */ + +public class WriteBasalProfileTaskRunner extends TaskRunner { + + private List profileBlocks; + private BRProfileBlock profileBlock; + + public WriteBasalProfileTaskRunner(SightServiceConnector serviceConnector, List profileBlocks) { + super(serviceConnector); + this.profileBlocks = profileBlocks; + } + + @Override + protected AppLayerMessage run(AppLayerMessage message) throws Exception { + if (message == null) { + ReadConfigurationBlockMessage readMessage = new ReadConfigurationBlockMessage(); + readMessage.setConfigurationBlockID(ActiveProfileBlock.ID); + return readMessage; + } else if (message instanceof ReadConfigurationBlockMessage) { + ConfigurationBlock configurationBlock = ((ReadConfigurationBlockMessage) message).getConfigurationBlock(); + ActiveProfileBlock activeProfileBlock = (ActiveProfileBlock) configurationBlock; + switch (activeProfileBlock.getActiveProfile()) { + case BR_PROFILE_1: + profileBlock = new BRProfile1Block(); + break; + case BR_PROFILE_2: + profileBlock = new BRProfile2Block(); + break; + case BR_PROFILE_3: + profileBlock = new BRProfile3Block(); + break; + case BR_PROFILE_4: + profileBlock = new BRProfile4Block(); + break; + case BR_PROFILE_5: + profileBlock = new BRProfile5Block(); + break; + } + profileBlock.setProfileBlocks(profileBlocks); + return new OpenWriteSessionMessage(); + } else if (message instanceof OpenWriteSessionMessage) { + WriteConfigurationBlockMessage writeMessage = new WriteConfigurationBlockMessage(); + writeMessage.setConfigurationBlock(profileBlock); + return writeMessage; + } else if (message instanceof WriteConfigurationBlockMessage) { + return new CloseWriteSessionMessage(); + } else if (message instanceof CloseWriteSessionMessage) finish(null); + return null; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/history/HistoryIntentAdapter.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/history/HistoryIntentAdapter.java index b4618ae3b5..4295fadccb 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/history/HistoryIntentAdapter.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/history/HistoryIntentAdapter.java @@ -71,8 +71,8 @@ class HistoryIntentAdapter { final long pump_serial_number = Long.parseLong(intent.getStringExtra(HistoryBroadcast.EXTRA_PUMP_SERIAL_NUMBER)); final Date event_time = getDateExtra(intent, HistoryBroadcast.EXTRA_EVENT_TIME); final Date start_time = getDateExtra(intent, HistoryBroadcast.EXTRA_START_TIME); - final float immediate_amount = intent.getFloatExtra(HistoryBroadcast.EXTRA_IMMEDIATE_AMOUNT, -1); - final float extended_insulin = intent.getFloatExtra(HistoryBroadcast.EXTRA_EXTENDED_AMOUNT, -1); + final double immediate_amount = intent.getDoubleExtra(HistoryBroadcast.EXTRA_IMMEDIATE_AMOUNT, -1); + final double extended_insulin = intent.getDoubleExtra(HistoryBroadcast.EXTRA_EXTENDED_AMOUNT, -1); final int extended_minutes = intent.getIntExtra(HistoryBroadcast.EXTRA_DURATION, -1); final long record_unique_id = getRecordUniqueID(pump_serial_number, bolus_id > -1 ? bolus_id : pump_record_id); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Wear/ActionStringHandler.java b/app/src/main/java/info/nightscout/androidaps/plugins/Wear/ActionStringHandler.java index 636a935787..270051fbb6 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Wear/ActionStringHandler.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Wear/ActionStringHandler.java @@ -481,7 +481,7 @@ public class ActionStringHandler { ret += "DEFAULT RANGE: "; ret += profile.getTargetLow() + " - " + profile.getTargetHigh(); - ret += " target: " + (profile.getTargetLow() + profile.getTargetHigh()) / 2; + ret += " target: " + profile.getTarget(); return ret; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Wear/WearPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Wear/WearPlugin.java index b72a767278..3c1e827fe6 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Wear/WearPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Wear/WearPlugin.java @@ -10,6 +10,7 @@ import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.events.EventBolusRequested; import info.nightscout.androidaps.events.EventExtendedBolusChange; +import info.nightscout.androidaps.events.EventLoop; import info.nightscout.androidaps.events.EventNewBG; import info.nightscout.androidaps.events.EventNewBasalProfile; import info.nightscout.androidaps.events.EventPreferenceChange; @@ -18,6 +19,7 @@ import info.nightscout.androidaps.events.EventTempBasalChange; import info.nightscout.androidaps.events.EventTreatmentChange; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.plugins.Loop.LoopPlugin; +import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateGui; import info.nightscout.androidaps.plugins.Overview.events.EventDismissBolusprogressIfRunning; import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress; import info.nightscout.androidaps.plugins.Wear.wearintegration.WatchUpdaterService; @@ -168,6 +170,11 @@ public class WearPlugin implements PluginBase { sendDataToWatch(true, true, false); } + @Subscribe + public void onStatusEvent(final EventOpenAPSUpdateGui ev){ + sendDataToWatch(true, true, false); + } + @Subscribe public void onStatusEvent(final EventExtendedBolusChange ev) { sendDataToWatch(true, true, false); @@ -197,7 +204,7 @@ public class WearPlugin implements PluginBase { @Subscribe public void onStatusEvent(final EventOverviewBolusProgress ev) { - if(!ev.isSMB()||SP.getBoolean("wear_notifySMB", false)) { + if(!ev.isSMB()||SP.getBoolean("wear_notifySMB", true)) { Intent intent = new Intent(ctx, WatchUpdaterService.class).setAction(WatchUpdaterService.ACTION_SEND_BOLUSPROGRESS); intent.putExtra("progresspercent", ev.percent); intent.putExtra("progressstatus", ev.status); @@ -251,11 +258,4 @@ public class WearPlugin implements PluginBase { public static void unRegisterWatchUpdaterService() { watchUS = null; } - - public void overviewNotification(int id, String message) { - if(SP.getBoolean("wear_overview_notification", false)){ - ActionStringHandler.expectNotificationAction(message, id); - } - } - } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Wear/wearintegration/WatchUpdaterService.java b/app/src/main/java/info/nightscout/androidaps/plugins/Wear/wearintegration/WatchUpdaterService.java index 74423fe7ac..a254221a3e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Wear/wearintegration/WatchUpdaterService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Wear/wearintegration/WatchUpdaterService.java @@ -6,6 +6,8 @@ import android.content.IntentFilter; import android.content.SharedPreferences; import android.os.BatteryManager; import android.os.Bundle; +import android.os.Handler; +import android.os.HandlerThread; import android.preference.PreferenceManager; import android.support.annotation.NonNull; import android.util.Log; @@ -19,11 +21,15 @@ import com.google.android.gms.wearable.PutDataRequest; import com.google.android.gms.wearable.Wearable; import com.google.android.gms.wearable.WearableListenerService; +import org.mozilla.javascript.tools.jsc.Main; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; import java.util.List; +import java.util.stream.Collectors; import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Constants; @@ -35,6 +41,7 @@ import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.db.DatabaseHelper; import info.nightscout.androidaps.db.TemporaryBasal; +import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.TreatmentsInterface; import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData; @@ -82,6 +89,7 @@ public class WatchUpdaterService extends WearableListenerService implements private static Logger log = LoggerFactory.getLogger(WatchUpdaterService.class); + private Handler handler; @Override public void onCreate() { @@ -91,6 +99,11 @@ public class WatchUpdaterService extends WearableListenerService implements if (wear_integration) { googleApiConnect(); } + if (handler == null) { + HandlerThread handlerThread = new HandlerThread(this.getClass().getSimpleName() + "Handler"); + handlerThread.start(); + handler = new Handler(handlerThread.getLooper()); + } } public void listenForChangeInSettings() { @@ -123,34 +136,33 @@ public class WatchUpdaterService extends WearableListenerService implements @Override public int onStartCommand(Intent intent, int flags, int startId) { - String action = null; - if (intent != null) { - action = intent.getAction(); - } + String action = intent != null ? intent.getAction() : null; if (wear_integration) { - if (googleApiClient.isConnected()) { - if (ACTION_RESEND.equals(action)) { - resendData(); - } else if (ACTION_OPEN_SETTINGS.equals(action)) { - sendNotification(); - } else if (ACTION_SEND_STATUS.equals(action)) { - sendStatus(); - } else if (ACTION_SEND_BASALS.equals(action)) { - sendBasals(); - } else if (ACTION_SEND_BOLUSPROGRESS.equals(action)) { - sendBolusProgress(intent.getIntExtra("progresspercent", 0), intent.hasExtra("progressstatus") ? intent.getStringExtra("progressstatus") : ""); - } else if (ACTION_SEND_ACTIONCONFIRMATIONREQUEST.equals(action)) { - String title = intent.getStringExtra("title"); - String message = intent.getStringExtra("message"); - String actionstring = intent.getStringExtra("actionstring"); - sendActionConfirmationRequest(title, message, actionstring); + handler.post(() -> { + if (googleApiClient.isConnected()) { + if (ACTION_RESEND.equals(action)) { + resendData(); + } else if (ACTION_OPEN_SETTINGS.equals(action)) { + sendNotification(); + } else if (ACTION_SEND_STATUS.equals(action)) { + sendStatus(); + } else if (ACTION_SEND_BASALS.equals(action)) { + sendBasals(); + } else if (ACTION_SEND_BOLUSPROGRESS.equals(action)) { + sendBolusProgress(intent.getIntExtra("progresspercent", 0), intent.hasExtra("progressstatus") ? intent.getStringExtra("progressstatus") : ""); + } else if (ACTION_SEND_ACTIONCONFIRMATIONREQUEST.equals(action)) { + String title = intent.getStringExtra("title"); + String message = intent.getStringExtra("message"); + String actionstring = intent.getStringExtra("actionstring"); + sendActionConfirmationRequest(title, message, actionstring); + } else { + sendData(); + } } else { - sendData(); + googleApiClient.connect(); } - } else { - googleApiClient.connect(); - } + }); } return START_STICKY; @@ -345,11 +357,15 @@ public class WatchUpdaterService extends WearableListenerService implements } long now = System.currentTimeMillis(); - long startTimeWindow = now - (long) (60000 * 60 * 5.5); + final long startTimeWindow = now - (long) (60000 * 60 * 5.5); ArrayList basals = new ArrayList<>(); ArrayList temps = new ArrayList<>(); + ArrayList boluses = new ArrayList<>(); + ArrayList predictions = new ArrayList<>(); + + Profile profile = MainApp.getConfigBuilder().getProfile(); @@ -447,9 +463,31 @@ public class WatchUpdaterService extends WearableListenerService implements } } + List treatments = MainApp.getConfigBuilder().getTreatmentsFromHistory(); + for (Treatment treatment:treatments) { + if(treatment.date > startTimeWindow){ + boluses.add(treatmentMap(treatment.date, treatment.insulin, treatment.carbs, treatment.isSMB, treatment.isValid)); + } + + } + + final LoopPlugin.LastRun finalLastRun = LoopPlugin.lastRun; + if(SP.getBoolean("wear_predictions", true) && finalLastRun != null && finalLastRun.request.hasPredictions && finalLastRun.constraintsProcessed != null){ + List predArray = finalLastRun.constraintsProcessed.getPredictions(); + + if (!predArray.isEmpty()) { + for (BgReading bg : predArray) { + predictions.add(predictionMap(bg.date, bg.value)); + } + } + } + + DataMap dm = new DataMap(); dm.putDataMapArrayList("basals", basals); dm.putDataMapArrayList("temps", temps); + dm.putDataMapArrayList("boluses", boluses); + dm.putDataMapArrayList("predictions", predictions); new SendToDataLayerThread(BASAL_DATA_PATH, googleApiClient).execute(dm); } @@ -472,6 +510,23 @@ public class WatchUpdaterService extends WearableListenerService implements return dm; } + private DataMap treatmentMap(long date, double bolus, double carbs, boolean isSMB, boolean isValid) { + DataMap dm = new DataMap(); + dm.putLong("date", date); + dm.putDouble("bolus", bolus); + dm.putDouble("carbs", carbs); + dm.putBoolean("isSMB", isSMB); + dm.putBoolean("isValid", isValid); + return dm; + } + + private DataMap predictionMap(long timestamp, double sgv) { + DataMap dm = new DataMap(); + dm.putLong("timestamp", timestamp); + dm.putDouble("sgv", sgv); + return dm; + } + private void sendNotification() { if (googleApiClient.isConnected()) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/XDripStatusline/StatuslinePlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/XDripStatusline/StatuslinePlugin.java index 5fb902c2eb..7e9619dfb3 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/XDripStatusline/StatuslinePlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/XDripStatusline/StatuslinePlugin.java @@ -184,7 +184,7 @@ public class StatuslinePlugin implements PluginBase { TemporaryBasal activeTemp = treatmentsInterface.getTempBasalFromHistory(System.currentTimeMillis()); if (activeTemp != null) { - status += activeTemp.toStringShort(); + status += activeTemp.toStringShort() + " "; } //IOB diff --git a/app/src/main/res/layout/overview_fragment_smallheight.xml b/app/src/main/res/layout/overview_fragment_smallheight.xml index 604687de82..0e15d66681 100644 --- a/app/src/main/res/layout/overview_fragment_smallheight.xml +++ b/app/src/main/res/layout/overview_fragment_smallheight.xml @@ -394,7 +394,9 @@ android:paddingRight="0dp" android:text="@string/overview_treatment_label" android:textColor="@color/colorTreatmentButton" - android:textSize="10sp" /> + android:textSize="10sp" + android:visibility="gone"/> + + android:textSize="10sp" + android:visibility="gone"/> + android:textSize="10sp" + android:visibility="gone"/> + + + android:text="@string/start_eating_soon_tt" /> + android:text="@string/suspendloopfor30min" /> + android:layout_gravity="center_horizontal" + android:padding="5dp"> + android:visibility="gone" /> + android:layout_marginBottom="5dp" + android:orientation="horizontal">