From b54a0106140d1b9c4a56f78f353348c6400b76b6 Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Sat, 17 Mar 2018 22:07:00 +0100 Subject: [PATCH] CarbsButton: replace suspend option with 'hypo tt'. --- .../info/nightscout/androidaps/Constants.java | 7 +- .../Overview/Dialogs/NewCarbsDialog.java | 260 +++++++++++------- .../res/layout/overview_newcarbs_dialog.xml | 40 +-- .../res/layout/overview_newinsulin_dialog.xml | 28 +- app/src/main/res/values/strings.xml | 6 + app/src/main/res/xml/pref_others.xml | 10 + 6 files changed, 230 insertions(+), 121 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/Constants.java b/app/src/main/java/info/nightscout/androidaps/Constants.java index d933018790..d96f432415 100644 --- a/app/src/main/java/info/nightscout/androidaps/Constants.java +++ b/app/src/main/java/info/nightscout/androidaps/Constants.java @@ -41,10 +41,13 @@ public class Constants { // Temp targets public static final int defaultActivityTTDuration = 90; // min public static final double defaultActivityTTmgdl = 90d; - public static final double defaultActivityTTmmol = 5d; + public static final double defaultActivityTTmmol = 8d; public static final int defaultEatingSoonTTDuration = 45; // min public static final double defaultEatingSoonTTmgdl = 140d; - public static final double defaultEatingSoonTTmmol = 8d; + public static final double defaultEatingSoonTTmmol = 5d; + public static final int defaultHypoTTDuration = 30; // min + public static final double defaultHypoTTmgdl = 120d; + public static final double defaultHypoTTmmol = 6.5d; //NSClientInternal public static final int MAX_LOG_LINES = 100; 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 7dfc3c6c65..3c068b79d7 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 @@ -17,7 +17,8 @@ import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager; import android.widget.Button; -import android.widget.CheckBox; +import android.widget.CompoundButton; +import android.widget.RadioButton; import android.widget.TextView; import com.google.common.base.Joiner; @@ -25,7 +26,6 @@ import com.wdullaer.materialdatetimepicker.date.DatePickerDialog; import com.wdullaer.materialdatetimepicker.time.RadialPickerLayout; import com.wdullaer.materialdatetimepicker.time.TimePickerDialog; -import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -44,7 +44,6 @@ import info.nightscout.androidaps.db.CareportalEvent; import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.TempTarget; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.Loop.LoopPlugin; import info.nightscout.androidaps.queue.Callback; import info.nightscout.utils.DateUtil; import info.nightscout.utils.DecimalFormatter; @@ -53,7 +52,7 @@ import info.nightscout.utils.SP; import info.nightscout.utils.SafeParse; import info.nightscout.utils.ToastUtils; -public class NewCarbsDialog extends DialogFragment implements OnClickListener, DatePickerDialog.OnDateSetListener, TimePickerDialog.OnTimeSetListener { +public class NewCarbsDialog extends DialogFragment implements OnClickListener, DatePickerDialog.OnDateSetListener, TimePickerDialog.OnTimeSetListener, CompoundButton.OnCheckedChangeListener { private static Logger log = LoggerFactory.getLogger(NewCarbsDialog.class); private NumberPicker editCarbs; @@ -71,9 +70,10 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, D private static final int FAV1_DEFAULT = 5; private static final int FAV2_DEFAULT = 10; private static final int FAV3_DEFAULT = 20; - private CheckBox suspendLoopCheckbox; - private CheckBox startActivityTTCheckbox; - private CheckBox startEatingSoonTTCheckbox; + private RadioButton startActivityTTCheckbox; + private RadioButton startEatingSoonTTCheckbox; + private RadioButton startHypoTTCheckbox; + private boolean togglingTT; private Integer maxCarbs; @@ -127,7 +127,11 @@ 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); + startActivityTTCheckbox.setOnCheckedChangeListener(this); + startEatingSoonTTCheckbox = view.findViewById(R.id.newcarbs_eating_soon_tt); + startEatingSoonTTCheckbox.setOnCheckedChangeListener(this); + startHypoTTCheckbox = view.findViewById(R.id.newcarbs_hypo_tt); + startHypoTTCheckbox.setOnCheckedChangeListener(this); dateButton = view.findViewById(R.id.newcarbs_eventdate); timeButton = view.findViewById(R.id.newcarb_eventtime); @@ -139,10 +143,6 @@ 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); - fav1Button = view.findViewById(R.id.newcarbs_plus1); fav1Button.setOnClickListener(this); fav1Button.setText(toSignedString(SP.getInt(R.string.key_carbs_button_increment_1, FAV1_DEFAULT))); @@ -155,8 +155,6 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, D fav3Button.setOnClickListener(this); fav3Button.setText(toSignedString(SP.getInt(R.string.key_carbs_button_increment_3, FAV3_DEFAULT))); - suspendLoopCheckbox = view.findViewById(R.id.newcarbs_suspend_loop); - setCancelable(true); getDialog().setCanceledOnTouchOutside(false); return view; @@ -215,12 +213,84 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, D validateInputs(); break; case R.id.newcarbs_activity_tt: - startEatingSoonTTCheckbox.setChecked(false); - break; - case R.id.carbs_eating_soon_tt: + if (togglingTT) { + togglingTT = false; + break; + } + startActivityTTCheckbox.setOnClickListener(null); + startActivityTTCheckbox.setOnCheckedChangeListener(null); startActivityTTCheckbox.setChecked(false); + startActivityTTCheckbox.setOnCheckedChangeListener(this); break; + case R.id.newcarbs_eating_soon_tt: + if (togglingTT) { + togglingTT = false; + break; + } + startEatingSoonTTCheckbox.setOnClickListener(null); + startEatingSoonTTCheckbox.setOnCheckedChangeListener(null); + startEatingSoonTTCheckbox.setChecked(false); + startEatingSoonTTCheckbox.setOnCheckedChangeListener(this); + break; + case R.id.newcarbs_hypo_tt: + if (togglingTT) { + togglingTT = false; + break; + } + startHypoTTCheckbox.setOnClickListener(null); + startHypoTTCheckbox.setOnCheckedChangeListener(null); + startHypoTTCheckbox.setChecked(false); + startHypoTTCheckbox.setOnCheckedChangeListener(this); + break; + } + } + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + // Logic to disable a selected radio when pressed. When a checked radio + // is pressed, no CheckChanged event is trigger, so register a Click event + // when checking a radio. Since Click events come after CheckChanged events, + // the Click event is triggered immediately after this. Thus, set toggingTT + // var to true, so that the first Click event fired after this is ignored. + // Radios remove themselves from Click events once unchecked. + // Since radios are not in a group, manually update their state. + switch (buttonView.getId()) { + case R.id.newcarbs_activity_tt: + togglingTT = true; + startActivityTTCheckbox.setOnClickListener(this); + + startEatingSoonTTCheckbox.setOnCheckedChangeListener(null); + startEatingSoonTTCheckbox.setChecked(false); + startEatingSoonTTCheckbox.setOnCheckedChangeListener(this); + + startHypoTTCheckbox.setOnCheckedChangeListener(null); + startHypoTTCheckbox.setChecked(false); + startHypoTTCheckbox.setOnCheckedChangeListener(this); + break; + case R.id.newcarbs_eating_soon_tt: + togglingTT = true; + startEatingSoonTTCheckbox.setOnClickListener(this); + + startActivityTTCheckbox.setOnCheckedChangeListener(null); + startActivityTTCheckbox.setChecked(false); + startActivityTTCheckbox.setOnCheckedChangeListener(this); + + startHypoTTCheckbox.setOnCheckedChangeListener(null); + startHypoTTCheckbox.setChecked(false); + startHypoTTCheckbox.setOnCheckedChangeListener(this); + break; + case R.id.newcarbs_hypo_tt: + togglingTT = true; + startHypoTTCheckbox.setOnClickListener(this); + + startActivityTTCheckbox.setOnCheckedChangeListener(null); + startActivityTTCheckbox.setChecked(false); + startActivityTTCheckbox.setOnCheckedChangeListener(this); + + startEatingSoonTTCheckbox.setOnCheckedChangeListener(null); + startEatingSoonTTCheckbox.setChecked(false); + startEatingSoonTTCheckbox.setOnCheckedChangeListener(this); + break; } } @@ -240,9 +310,6 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, D actions.add(MainApp.gs(R.string.carbs) + ": " + "" + carbsAfterConstraints + "g" + ""); if (!carbsAfterConstraints.equals(carbs)) actions.add("" + MainApp.gs(R.string.carbsconstraintapplied) + ""); - if (suspendLoopCheckbox.isChecked()) { - actions.add(MainApp.gs(R.string.loop) + ": " + "" + MainApp.gs(R.string.suspendloopfor30min) + ""); - } final Profile currentProfile = MainApp.getConfigBuilder().getProfile(); if (currentProfile == null) @@ -258,6 +325,11 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, D double eatingSoonTT = SP.getDouble(R.string.key_eatingsoon_target, currentProfile.getUnits().equals(Constants.MMOL) ? Constants.defaultEatingSoonTTmmol : Constants.defaultEatingSoonTTmgdl); eatingSoonTT = eatingSoonTT > 0 ? eatingSoonTT : currentProfile.getUnits().equals(Constants.MMOL) ? Constants.defaultEatingSoonTTmmol : Constants.defaultEatingSoonTTmgdl; + int hypoTTDuration = SP.getInt(R.string.key_hypo_duration, Constants.defaultHypoTTDuration); + hypoTTDuration = hypoTTDuration > 0 ? hypoTTDuration : Constants.defaultHypoTTDuration; + double hypoTT = SP.getDouble(R.string.key_hypo_target, currentProfile.getUnits().equals(Constants.MMOL) ? Constants.defaultHypoTTmmol : Constants.defaultHypoTTmgdl); + hypoTT = hypoTT > 0 ? hypoTT : currentProfile.getUnits().equals(Constants.MMOL) ? Constants.defaultHypoTTmmol : Constants.defaultHypoTTmgdl; + if (startActivityTTCheckbox.isChecked()) { if (currentProfile.getUnits().equals(Constants.MMOL)) { actions.add(MainApp.gs(R.string.temptargetshort) + ": " + "" + DecimalFormatter.to1Decimal(activityTT) + " mmol/l (" + activityTTDuration + " min)"); @@ -265,107 +337,109 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, D actions.add(MainApp.gs(R.string.temptargetshort) + ": " + "" + DecimalFormatter.to0Decimal(activityTT) + " mg/dl (" + activityTTDuration + " min)"); } - if (startEatingSoonTTCheckbox.isChecked() && !startActivityTTCheckbox.isChecked()) { + if (startEatingSoonTTCheckbox.isChecked()) { if (currentProfile.getUnits().equals(Constants.MMOL)) { actions.add(MainApp.gs(R.string.temptargetshort) + ": " + "" + DecimalFormatter.to1Decimal(eatingSoonTT) + " mmol/l (" + eatingSoonTTDuration + " min)"); } else actions.add(MainApp.gs(R.string.temptargetshort) + ": " + "" + DecimalFormatter.to0Decimal(eatingSoonTT) + " mg/dl (" + eatingSoonTTDuration + " min)"); - } + if (startHypoTTCheckbox.isChecked()) { + if (currentProfile.getUnits().equals(Constants.MMOL)) { + actions.add(MainApp.gs(R.string.temptargetshort) + ": " + "" + DecimalFormatter.to1Decimal(hypoTT) + " mmol/l (" + hypoTTDuration + " min)"); + } else + actions.add(MainApp.gs(R.string.temptargetshort) + ": " + "" + DecimalFormatter.to0Decimal(hypoTT) + " mg/dl (" + hypoTTDuration + " min)"); + } + final double finalActivityTT = activityTT; - final double finalEatigSoonTT = eatingSoonTT; final int finalActivityTTDuration = activityTTDuration; + final double finalEatigSoonTT = eatingSoonTT; final int finalEatingSoonTTDuration = eatingSoonTTDuration; + final double finalHypoTT = hypoTT; + final int finalHypoTTDuration = hypoTTDuration; if (!initialEventTime.equals(eventTime)) { actions.add("Time: " + DateUtil.dateAndTimeString(eventTime)); } + 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(MainApp.gs(R.string.confirmation)); + builder.setMessage(actions.isEmpty() + ? MainApp.gs(R.string.no_action_selected) + : Html.fromHtml(Joiner.on("
").join(actions))); + builder.setPositiveButton(MainApp.gs(R.string.ok), actions.isEmpty() ? null : (dialog, id) -> { + synchronized (builder) { + if (accepted) { + log.debug("guarding: already accepted"); + return; + } + accepted = true; - builder.setTitle(MainApp.gs(R.string.confirmation)); - builder.setMessage(actions.isEmpty() - ? MainApp.gs(R.string.no_action_selected) - : Html.fromHtml(Joiner.on("
").join(actions))); - builder.setPositiveButton(MainApp.gs(R.string.ok), actions.isEmpty() ? null : (dialog, id) -> { - synchronized (builder) { - if (accepted) { - log.debug("guarding: already accepted"); - return; - } - accepted = true; + 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); + } else if (startHypoTTCheckbox.isChecked()) { + TempTarget tempTarget = new TempTarget(); + tempTarget.date = System.currentTimeMillis(); + tempTarget.durationInMinutes = finalHypoTTDuration; + tempTarget.reason = MainApp.gs(R.string.hypo); + tempTarget.source = Source.USER; + tempTarget.low = Profile.toMgdl(finalHypoTT, currentProfile.getUnits()); + tempTarget.high = Profile.toMgdl(finalHypoTT, currentProfile.getUnits()); + MainApp.getDbHelper().createOrUpdate(tempTarget); + } - if (suspendLoopCheckbox.isChecked()) { - final LoopPlugin activeloop = ConfigBuilderPlugin.getActiveLoop(); - activeloop.suspendTo(System.currentTimeMillis() + 30L * 60 * 1000); - ConfigBuilderPlugin.getCommandQueue().cancelTempBasal(true, new Callback() { + if (finalCarbsAfterConstraints > 0) { + DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); + detailedBolusInfo.date = eventTime.getTime(); + detailedBolusInfo.eventType = CareportalEvent.CARBCORRECTION; + detailedBolusInfo.carbs = finalCarbsAfterConstraints; + detailedBolusInfo.context = context; + detailedBolusInfo.source = Source.USER; + if (ConfigBuilderPlugin.getActivePump().getPumpDescription().storesCarbInfo) { + ConfigBuilderPlugin.getCommandQueue().bolus(detailedBolusInfo, new Callback() { @Override public void run() { if (!result.success) { - ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.tempbasaldeliveryerror)); + Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class); + i.putExtra("soundid", R.raw.boluserror); + i.putExtra("status", result.comment); + i.putExtra("title", MainApp.gs(R.string.treatmentdeliveryerror)); + i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + MainApp.instance().startActivity(i); } } }); - } - - 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) { - DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); - detailedBolusInfo.date = eventTime.getTime(); - detailedBolusInfo.eventType = CareportalEvent.CARBCORRECTION; - detailedBolusInfo.carbs = finalCarbsAfterConstraints; - detailedBolusInfo.context = context; - detailedBolusInfo.source = Source.USER; - if (ConfigBuilderPlugin.getActivePump().getPumpDescription().storesCarbInfo) { - ConfigBuilderPlugin.getCommandQueue().bolus(detailedBolusInfo, new Callback() { - @Override - public void run() { - if (!result.success) { - Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class); - i.putExtra("soundid", R.raw.boluserror); - i.putExtra("status", result.comment); - i.putExtra("title", MainApp.gs(R.string.treatmentdeliveryerror)); - i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - MainApp.instance().startActivity(i); - } - } - }); - } else { - MainApp.getConfigBuilder().addToHistoryTreatment(detailedBolusInfo); - } + } else { + MainApp.getConfigBuilder().addToHistoryTreatment(detailedBolusInfo); } } - }); - builder.setNegativeButton(MainApp.gs(R.string.cancel), null); - builder.show(); - dismiss(); + } + }); + builder.setNegativeButton(MainApp.gs(R.string.cancel), null); + builder.show(); + dismiss(); } catch (Exception e) { log.error("Unhandled exception", e); } - } @Override diff --git a/app/src/main/res/layout/overview_newcarbs_dialog.xml b/app/src/main/res/layout/overview_newcarbs_dialog.xml index 64ed498e2e..25ca0d75d2 100644 --- a/app/src/main/res/layout/overview_newcarbs_dialog.xml +++ b/app/src/main/res/layout/overview_newcarbs_dialog.xml @@ -32,25 +32,33 @@ android:padding="5dp" android:src="@drawable/icon_cp_bolus_carbs" /> - + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:orientation="vertical"> - + - + + + + + - + android:layout_height="wrap_content" + android:orientation="vertical" + android:layout_gravity="center_horizontal"> - + + + + + Use AMA autosens feature Refresh events from NS Eating Soon + Hypo Activity Remove record: DanaR Stats @@ -743,10 +744,14 @@ eatingsoon target activity duration activity target + hypo duration + hypo target eatingsoon_duration eatingsoon_target activity_duration activity_target + hypo_duration + hypo_target Prime Getting extended bolus status Getting bolus status @@ -988,5 +993,6 @@ Insulin On Board Basals No action selected, nothing will happen + Start Hypo TT diff --git a/app/src/main/res/xml/pref_others.xml b/app/src/main/res/xml/pref_others.xml index ba16f09c2f..9ecf31aca3 100644 --- a/app/src/main/res/xml/pref_others.xml +++ b/app/src/main/res/xml/pref_others.xml @@ -25,6 +25,16 @@ android:inputType="numberDecimal" android:key="@string/key_activity_target" android:title="@string/activity_target"> + +