diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000000..f7b3a44868 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000000..3b312839bf --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 5d19981032..fbb68289f4 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -37,7 +37,7 @@ - + diff --git a/app/src/main/java/info/nightscout/androidaps/Config.java b/app/src/main/java/info/nightscout/androidaps/Config.java index 20dd4a77bf..d81a8cd4a0 100644 --- a/app/src/main/java/info/nightscout/androidaps/Config.java +++ b/app/src/main/java/info/nightscout/androidaps/Config.java @@ -19,8 +19,9 @@ public class Config { public static final boolean logPumpComm = true; public static final boolean logPrefsChange = true; public static final boolean logConfigBuilder = true; - public static final boolean logConstrainsChnages = true; + public static final boolean logConstraintsChanges = true; // Developing mode only - never turn on + // TODO: remove fakeGlucoseData public static final boolean fakeGlucoseData = true; } diff --git a/app/src/main/java/info/nightscout/androidaps/Services/DataService.java b/app/src/main/java/info/nightscout/androidaps/Services/DataService.java index 421775f78f..2d1a088299 100644 --- a/app/src/main/java/info/nightscout/androidaps/Services/DataService.java +++ b/app/src/main/java/info/nightscout/androidaps/Services/DataService.java @@ -334,7 +334,6 @@ public class DataService extends IntentService { @Nullable public static Treatment findById(String _id) { try { - QueryBuilder qb = null; Dao daoTreatments = MainApp.getDbHelper().getDaoTreatments(); QueryBuilder queryBuilder = daoTreatments.queryBuilder(); Where where = queryBuilder.where(); diff --git a/app/src/main/java/info/nightscout/androidaps/data/Result.java b/app/src/main/java/info/nightscout/androidaps/data/Result.java index 28661890fa..a079db7d52 100644 --- a/app/src/main/java/info/nightscout/androidaps/data/Result.java +++ b/app/src/main/java/info/nightscout/androidaps/data/Result.java @@ -4,23 +4,31 @@ import android.os.Parcel; import android.os.Parcelable; public class Result extends Object implements Parcelable{ - public boolean success = false; - public boolean enacted = false; + public boolean success = false; // request was processed successfully (but possible no change was needed) + public boolean enacted = false; // request was processed successfully and change has been made public String comment = ""; - public Integer duration = -1; - public Double absolute = -1d; - public Integer percent = -1; - public Double bolusDelivered = 0d; + // Result of basal change + public Integer duration = -1; // duration set [minutes] + public Double absolute = -1d; // absolute rate [U/h] , isPercent = false + public Integer percent = -1; // percent of current basal [%] (100% = current basal), isPercent = true + public boolean isPercent = false; // if true percent is used, otherwise absolute + // Result of treatment delivery + public Double bolusDelivered = 0d; // real value of delivered insulin + public Integer carbsDelivered = 0; // real value of delivered carbs public String log() { - return "Success: " + success + " Enacted: " + enacted + " Comment: " + comment + " Duration: " + duration + " Absolute: " + absolute + " Percent: " + percent; + return "Success: " + success + " Enacted: " + enacted + " Comment: " + comment + " Duration: " + duration + " Absolute: " + absolute + " Percent: " + percent + " IsPercent: " + isPercent; } public String toString() { String ret = "Success: " + success; if (enacted) { - ret += "\nEnacted: " + enacted + "\nComment: " + comment + "\nDuration: " + duration + " min\nAbsolute: " + absolute + " U/h"; + if (isPercent) { + ret += "\nEnacted: " + enacted + "\nComment: " + comment + "\nDuration: " + duration + " min\nPercent: " + percent + "%"; + } else { + ret += "\nEnacted: " + enacted + "\nComment: " + comment + "\nDuration: " + duration + " min\nAbsolute: " + absolute + " U/h"; + } } else { ret += "\nComment: " + comment; } @@ -36,6 +44,7 @@ public class Result extends Object implements Parcelable{ public void writeToParcel(Parcel dest, int flags) { dest.writeInt(success ? 1 : 0); dest.writeInt(enacted ? 1 : 0); + dest.writeInt(isPercent ? 1 : 0); dest.writeString(comment); dest.writeInt(duration); dest.writeDouble(absolute); @@ -55,6 +64,7 @@ public class Result extends Object implements Parcelable{ protected Result(Parcel in) { success = in.readInt() == 1 ? true : false; enacted = in.readInt() == 1 ? true : false; + isPercent = in.readInt() == 1 ? true : false; duration = in.readInt(); comment = in.readString(); absolute = in.readDouble(); diff --git a/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java b/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java index a5ef1bef47..47d230bb02 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java +++ b/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java @@ -29,6 +29,7 @@ import info.nightscout.androidaps.R; import info.nightscout.androidaps.events.EventNewBG; import info.nightscout.androidaps.events.EventTempBasalChange; import info.nightscout.androidaps.events.EventTreatmentChange; +import info.nightscout.utils.Round; public class DatabaseHelper extends OrmLiteSqliteOpenHelper { private static Logger log = LoggerFactory.getLogger(DatabaseHelper.class); @@ -227,6 +228,13 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { 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); + return this; + } } @Nullable @@ -284,6 +292,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { e.printStackTrace(); return null; } + result.round(); return result; } } diff --git a/app/src/main/java/info/nightscout/androidaps/db/TempBasal.java b/app/src/main/java/info/nightscout/androidaps/db/TempBasal.java index fd1426149a..852d74bf0a 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/TempBasal.java +++ b/app/src/main/java/info/nightscout/androidaps/db/TempBasal.java @@ -110,49 +110,6 @@ public class TempBasal { return result; } - /* - public Iob calcIob() { - Iob iob = new Iob(); - - long msAgo = getMillisecondsFromStart(); - Calendar startAdjusted = Calendar.getInstance(TimeZone.getTimeZone("UTC")); - startAdjusted.setTime(this.timeStart); - int minutes = startAdjusted.get(Calendar.MINUTE); - minutes = minutes % 4; - if (startAdjusted.get(Calendar.SECOND) > 0 && minutes == 0) { - minutes += 4; - } - startAdjusted.add(Calendar.MINUTE, minutes); - startAdjusted.set(Calendar.SECOND, 0); - - IobCalc iobCalc = new IobCalc(); - iobCalc.setTime(new Date()); - iobCalc.setAmount(-1.0d * (baseRatio - tempRatio) / 15.0d / 100.0d); - - long timeStartTime = startAdjusted.getTimeInMillis(); - Date currentTimeEnd = timeEnd; - if (currentTimeEnd == null) { - currentTimeEnd = new Date(); - if (getPlannedTimeEnd().getTime() < currentTimeEnd.getTime()) { - currentTimeEnd = getPlannedTimeEnd(); - } - } - for (long time = timeStartTime; time < currentTimeEnd.getTime(); time += 4 * 60_000) { - Date start = new Date(time); - - iobCalc.setTimeStart(start); - iob.plus(iobCalc.invoke()); - } - - if (Settings.logTempIOBCalculation) { - log.debug("TempIOB start: " + this.timeStart + " end: " + this.timeEnd + " Percent: " + this.percent + " Duration: " + this.duration + " CalcDurat: " + (int) ((currentTimeEnd.getTime() - this.timeStart.getTime()) / 1000 / 60) - + "min minAgo: " + (int) (msAgo / 1000 / 60) + " IOB: " + iob.iobContrib + " Activity: " + iob.activityContrib + " Impact: " + (-0.01d * (baseRatio - tempRatio) * ((currentTimeEnd.getTime() - this.timeStart.getTime()) / 1000 / 60) / 60) - ); - } - - return iob; - } - */ // Determine end of basal public Date getTimeEnd() { Date tempBasalTimePlannedEnd = getPlannedTimeEnd(); @@ -181,8 +138,9 @@ public class TempBasal { return new Date().getTime() - timeStart.getTime(); } - public int getRemainingMinutes() { - long remainingMin = (getTimeEnd().getTime() - new Date().getTime()) / 1000 / 60; + public int getPlannedRemainingMinutes() { + if (timeEnd != null) return 0; + long remainingMin = (getPlannedTimeEnd().getTime() - new Date().getTime()) / 1000 / 60; return (remainingMin < 0) ? 0 : (int) remainingMin; } diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/ConstrainsInterface.java b/app/src/main/java/info/nightscout/androidaps/interfaces/ConstrainsInterface.java deleted file mode 100644 index 5e429a7872..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/interfaces/ConstrainsInterface.java +++ /dev/null @@ -1,13 +0,0 @@ -package info.nightscout.androidaps.interfaces; - -import info.nightscout.androidaps.plugins.APSResult; - -/** - * Created by mike on 15.06.2016. - */ -public interface ConstrainsInterface { - - boolean isAutomaticProcessingEnabled(); - boolean manualConfirmationNeeded(); - APSResult applyBasalConstrains(APSResult result); -} diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/ConstraintsInterface.java b/app/src/main/java/info/nightscout/androidaps/interfaces/ConstraintsInterface.java new file mode 100644 index 0000000000..105f79e7c9 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/ConstraintsInterface.java @@ -0,0 +1,18 @@ +package info.nightscout.androidaps.interfaces; + +import info.nightscout.androidaps.plugins.APSResult; + +/** + * Created by mike on 15.06.2016. + */ +public interface ConstraintsInterface { + + boolean isAutomaticProcessingEnabled(); + boolean manualConfirmationNeeded(); + APSResult applyBasalConstraints(APSResult request); + Double applyBasalConstraints(Double absoluteRate); + Integer applyBasalConstraints(Integer percentRate); + + Double applyBolusConstraints(Double insulin); + Integer applyCarbsConstraints(Integer carbs); +} diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/PluginBase.java b/app/src/main/java/info/nightscout/androidaps/interfaces/PluginBase.java index e4f3b10dcc..b4233df298 100644 --- a/app/src/main/java/info/nightscout/androidaps/interfaces/PluginBase.java +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/PluginBase.java @@ -12,7 +12,7 @@ public interface PluginBase { int PROFILE = 4; int APS = 5; int PUMP = 6; - int CONSTRAINS = 7; + int CONSTRAINTS = 7; int LOOP = 8; public int getType(); diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/PumpInterface.java b/app/src/main/java/info/nightscout/androidaps/interfaces/PumpInterface.java index e64241a1cb..0f2a55fb5b 100644 --- a/app/src/main/java/info/nightscout/androidaps/interfaces/PumpInterface.java +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/PumpInterface.java @@ -26,7 +26,7 @@ public interface PumpInterface { double getTempBasalRemainingMinutes(); TempBasal getTempBasal(); - Result deliverTreatment(Double insulin, Double carbs); + Result deliverTreatment(Double insulin, Integer carbs); Result setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes); Result setTempBasalPercent(Integer percent, Integer durationInMinutes); Result setExtendedBolus(Double insulin, Integer durationInMinutes); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderFragment.java index f3de63c552..332aec9280 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderFragment.java @@ -12,13 +12,11 @@ import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.CheckBox; import android.widget.ListAdapter; import android.widget.ListView; import android.widget.TextView; -import android.widget.Toast; import org.json.JSONException; import org.json.JSONObject; @@ -39,21 +37,19 @@ import info.nightscout.androidaps.data.Result; import info.nightscout.androidaps.db.TempBasal; import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.events.EventRefreshGui; +import info.nightscout.androidaps.events.EventTempBasalChange; import info.nightscout.androidaps.events.EventTreatmentChange; -import info.nightscout.androidaps.interfaces.APSInterface; -import info.nightscout.androidaps.interfaces.ConstrainsInterface; +import info.nightscout.androidaps.interfaces.ConstraintsInterface; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.ProfileInterface; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.interfaces.TempBasalsInterface; import info.nightscout.androidaps.interfaces.TreatmentsInterface; import info.nightscout.androidaps.plugins.APSResult; -import info.nightscout.androidaps.plugins.TempBasals.TempBasalsFragment; -import info.nightscout.androidaps.plugins.Treatments.TreatmentsFragment; import info.nightscout.client.data.NSProfile; import info.nightscout.utils.DateUtil; -public class ConfigBuilderFragment extends Fragment implements PluginBase, PumpInterface, ConstrainsInterface { +public class ConfigBuilderFragment extends Fragment implements PluginBase, PumpInterface, ConstraintsInterface { private static Logger log = LoggerFactory.getLogger(ConfigBuilderFragment.class); private static final String PREFS_NAME = "Settings"; @@ -64,7 +60,7 @@ public class ConfigBuilderFragment extends Fragment implements PluginBase, PumpI ListView tempsListView; ListView profileListView; ListView apsListView; - ListView constrainsListView; + ListView constraintsListView; ListView generalListView; PluginCustomAdapter pumpDataAdapter = null; @@ -73,7 +69,7 @@ public class ConfigBuilderFragment extends Fragment implements PluginBase, PumpI PluginCustomAdapter tempsDataAdapter = null; PluginCustomAdapter profileDataAdapter = null; PluginCustomAdapter apsDataAdapter = null; - PluginCustomAdapter constrainsDataAdapter = null; + PluginCustomAdapter constraintsDataAdapter = null; PluginCustomAdapter generalDataAdapter = null; @@ -118,7 +114,7 @@ public class ConfigBuilderFragment extends Fragment implements PluginBase, PumpI tempsListView = (ListView) view.findViewById(R.id.configbuilder_tempslistview); profileListView = (ListView) view.findViewById(R.id.configbuilder_profilelistview); apsListView = (ListView) view.findViewById(R.id.configbuilder_apslistview); - constrainsListView = (ListView) view.findViewById(R.id.configbuilder_constrainslistview); + constraintsListView = (ListView) view.findViewById(R.id.configbuilder_constraintslistview); generalListView = (ListView) view.findViewById(R.id.configbuilder_generallistview); setViews(); @@ -144,9 +140,9 @@ public class ConfigBuilderFragment extends Fragment implements PluginBase, PumpI apsDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainActivity.getSpecificPluginsList(PluginBase.APS)); apsListView.setAdapter(apsDataAdapter); setListViewHeightBasedOnChildren(apsListView); - constrainsDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainActivity.getSpecificPluginsList(PluginBase.CONSTRAINS)); - constrainsListView.setAdapter(constrainsDataAdapter); - setListViewHeightBasedOnChildren(constrainsListView); + constraintsDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainActivity.getSpecificPluginsList(PluginBase.CONSTRAINTS)); + constraintsListView.setAdapter(constraintsDataAdapter); + setListViewHeightBasedOnChildren(constraintsListView); generalDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainActivity.getSpecificPluginsList(PluginBase.GENERAL)); generalListView.setAdapter(generalDataAdapter); setListViewHeightBasedOnChildren(generalListView); @@ -200,7 +196,7 @@ public class ConfigBuilderFragment extends Fragment implements PluginBase, PumpI /* * Pump interface * - * Config builder return itself as a pump and check constrains before it passes command to pump driver + * Config builder return itself as a pump and check constraints before it passes command to pump driver */ @Nullable public PumpInterface getActivePump() { @@ -253,23 +249,16 @@ public class ConfigBuilderFragment extends Fragment implements PluginBase, PumpI } @Override - public Result deliverTreatment(Double insulin, Double carbs) { - SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext()); - Double maxbolus = Double.parseDouble(SP.getString("treatmentssafety_maxbolus", "3")); - Double maxcarbs = Double.parseDouble(SP.getString("treatmentssafety_maxcarbs", "48")); + public Result deliverTreatment(Double insulin, Integer carbs) { + insulin = applyBolusConstraints(insulin); + carbs = applyCarbsConstraints(carbs); - if (insulin > maxbolus || carbs > maxcarbs) { - Result failResult = new Result(); - failResult.success = false; - failResult.comment = MainApp.instance().getString(R.string.constrains_violation); - return failResult; - } Result result = activePump.deliverTreatment(insulin, carbs); if (result.success) { Treatment t = new Treatment(); t.insulin = result.bolusDelivered; - t.carbs = carbs; + t.carbs = (double) result.carbsDelivered; t.created_at = new Date(); try { MainApp.instance().getDbHelper().getDaoTreatments().create(t); @@ -283,29 +272,55 @@ public class ConfigBuilderFragment extends Fragment implements PluginBase, PumpI return result; } + /** + * apply constraints, set temp based on absolute valus and expecting absolute result + * + * @param absoluteRate + * @param durationInMinutes + * @return + */ @Override public Result setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes) { - // TODO: constrains here - return activePump.setTempBasalAbsolute(absoluteRate, durationInMinutes); + Double rateAfterConstraints = applyBasalConstraints(absoluteRate); + Result result = activePump.setTempBasalAbsolute(rateAfterConstraints, durationInMinutes); + if (result.enacted) { + uploadTempBasalStartAbsolute(result.absolute, result.duration); + MainApp.bus().post(new EventTempBasalChange()); + } + return result; } + /** + * apply constraints, set temp based on percent and expecting result in percent + * + * @param percent 0 ... 100 ... + * @param durationInMinutes + * @return result + */ @Override public Result setTempBasalPercent(Integer percent, Integer durationInMinutes) { - // TODO: constrains here - return activePump.setTempBasalPercent(percent, durationInMinutes); + Integer percentAfterConstraints = applyBasalConstraints(percent); + Result result = activePump.setTempBasalPercent(percentAfterConstraints, durationInMinutes); + if (result.enacted) { + uploadTempBasalStartPercent(result.percent, result.duration); + MainApp.bus().post(new EventTempBasalChange()); + } + return result; } @Override public Result setExtendedBolus(Double insulin, Integer durationInMinutes) { - // TODO: constrains here + // TODO: constraints here return activePump.setExtendedBolus(insulin, durationInMinutes); } @Override public Result cancelTempBasal() { Result result = activePump.cancelTempBasal(); - if (result.enacted) + if (result.enacted) { uploadTempBasalEnd(); + MainApp.bus().post(new EventTempBasalChange()); + } return result; } @@ -314,11 +329,32 @@ public class ConfigBuilderFragment extends Fragment implements PluginBase, PumpI return activePump.cancelExtendedBolus(); } + /** + * expect absolute request and allow both absolute and percent response based on pump capabilities + * @param request + * @return + */ @Override public Result applyAPSRequest(APSResult request) { - Result result = activePump.applyAPSRequest(request); - if (result.enacted) - uploadTempBasalStart(result.absolute, result.duration); + Double rateAfterConstraints = applyBasalConstraints(request.rate); + request.rate = rateAfterConstraints; + Result result = activePump.applyAPSRequest(request); + if (result.enacted) { + if (result.isPercent) { + if (result.percent == 0) { + uploadTempBasalEnd(); + } else { + uploadTempBasalStartPercent(result.percent, result.duration); + } + } else { + if (result.absolute == 0d) { + uploadTempBasalEnd(); + } else { + uploadTempBasalStartAbsolute(result.absolute, result.duration); + } + } + MainApp.bus().post(new EventTempBasalChange()); + } return result; } @@ -405,8 +441,8 @@ public class ConfigBuilderFragment extends Fragment implements PluginBase, PumpI if (pluginList.size() < 2) holder.checkboxEnabled.setEnabled(false); - // Constrains cannot be disabled - if (type == PluginBase.CONSTRAINS) + // Constraints cannot be disabled + if (type == PluginBase.CONSTRAINTS) holder.checkboxEnabled.setEnabled(false); // Hide disabled profiles by default @@ -446,7 +482,7 @@ public class ConfigBuilderFragment extends Fragment implements PluginBase, PumpI // Multiple selection allowed case PluginBase.APS: case PluginBase.GENERAL: - case PluginBase.CONSTRAINS: + case PluginBase.CONSTRAINTS: break; // Single selection allowed case PluginBase.PROFILE: @@ -478,7 +514,7 @@ public class ConfigBuilderFragment extends Fragment implements PluginBase, PumpI // Multiple selection allowed case PluginBase.APS: case PluginBase.GENERAL: - case PluginBase.CONSTRAINS: + case PluginBase.CONSTRAINTS: break; // Single selection allowed case PluginBase.PROFILE: @@ -607,15 +643,15 @@ public class ConfigBuilderFragment extends Fragment implements PluginBase, PumpI } /** - * Constrains interface + * Constraints interface **/ @Override public boolean isAutomaticProcessingEnabled() { boolean result = true; - ArrayList constrainsPlugins = MainActivity.getSpecificPluginsList(PluginBase.CONSTRAINS); - for (PluginBase p : constrainsPlugins) { - ConstrainsInterface constrain = (ConstrainsInterface) p; + ArrayList constraintsPlugins = MainActivity.getSpecificPluginsList(PluginBase.CONSTRAINTS); + for (PluginBase p : constraintsPlugins) { + ConstraintsInterface constrain = (ConstraintsInterface) p; if (!p.isEnabled()) continue; result = result && constrain.isAutomaticProcessingEnabled(); } @@ -626,9 +662,9 @@ public class ConfigBuilderFragment extends Fragment implements PluginBase, PumpI public boolean manualConfirmationNeeded() { boolean result = false; - ArrayList constrainsPlugins = MainActivity.getSpecificPluginsList(PluginBase.CONSTRAINS); - for (PluginBase p : constrainsPlugins) { - ConstrainsInterface constrain = (ConstrainsInterface) p; + ArrayList constraintsPlugins = MainActivity.getSpecificPluginsList(PluginBase.CONSTRAINTS); + for (PluginBase p : constraintsPlugins) { + ConstraintsInterface constrain = (ConstraintsInterface) p; if (!p.isEnabled()) continue; result = result || constrain.manualConfirmationNeeded(); } @@ -636,29 +672,96 @@ public class ConfigBuilderFragment extends Fragment implements PluginBase, PumpI } @Override - public APSResult applyBasalConstrains(APSResult result) { - ArrayList constrainsPlugins = MainActivity.getSpecificPluginsList(PluginBase.CONSTRAINS); - for (PluginBase p : constrainsPlugins) { - ConstrainsInterface constrain = (ConstrainsInterface) p; + public APSResult applyBasalConstraints(APSResult result) { + ArrayList constraintsPlugins = MainActivity.getSpecificPluginsList(PluginBase.CONSTRAINTS); + for (PluginBase p : constraintsPlugins) { + ConstraintsInterface constrain = (ConstraintsInterface) p; if (!p.isEnabled()) continue; - constrain.applyBasalConstrains(result); + constrain.applyBasalConstraints(result); } return result; } - public static void uploadTempBasalStart(Double absolute, double durationInMinutes) { - try { - //SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext()); - //boolean useAbsoluteForUpload = sp.getBoolean("ns_sync_use_absolute", false); + @Override + public Double applyBasalConstraints(Double absoluteRate) { + Double rateAfterConstrain = absoluteRate; + ArrayList constraintsPlugins = MainActivity.getSpecificPluginsList(PluginBase.CONSTRAINTS); + for (PluginBase p : constraintsPlugins) { + ConstraintsInterface constrain = (ConstraintsInterface) p; + if (!p.isEnabled()) continue; + rateAfterConstrain = constrain.applyBasalConstraints(rateAfterConstrain); + } + return rateAfterConstrain; + } + @Override + public Integer applyBasalConstraints(Integer percentRate) { + Integer rateAfterConstrain = percentRate; + ArrayList constraintsPlugins = MainActivity.getSpecificPluginsList(PluginBase.CONSTRAINTS); + for (PluginBase p : constraintsPlugins) { + ConstraintsInterface constrain = (ConstraintsInterface) p; + if (!p.isEnabled()) continue; + rateAfterConstrain = constrain.applyBasalConstraints(rateAfterConstrain); + } + return rateAfterConstrain; + } + + @Override + public Double applyBolusConstraints(Double insulin) { + Double insulinAfterConstrain = insulin; + ArrayList constraintsPlugins = MainActivity.getSpecificPluginsList(PluginBase.CONSTRAINTS); + for (PluginBase p : constraintsPlugins) { + ConstraintsInterface constrain = (ConstraintsInterface) p; + if (!p.isEnabled()) continue; + insulinAfterConstrain = constrain.applyBolusConstraints(insulinAfterConstrain); + } + return insulinAfterConstrain; + } + + @Override + public Integer applyCarbsConstraints(Integer carbs) { + Integer carbsAfterConstrain = carbs; + ArrayList constraintsPlugins = MainActivity.getSpecificPluginsList(PluginBase.CONSTRAINTS); + for (PluginBase p : constraintsPlugins) { + ConstraintsInterface constrain = (ConstraintsInterface) p; + if (!p.isEnabled()) continue; + carbsAfterConstrain = constrain.applyCarbsConstraints(carbsAfterConstrain); + } + return carbsAfterConstrain; + } + + public static void uploadTempBasalStartAbsolute(Double absolute, double durationInMinutes) { + try { Context context = MainApp.instance().getApplicationContext(); JSONObject data = new JSONObject(); data.put("eventType", "Temp Basal"); data.put("duration", durationInMinutes); - //if (useAbsoluteForUpload && absolute != null) - data.put("absolute", absolute); - //else - // data.put("percent", percent - 100); + data.put("absolute", absolute); + data.put("created_at", DateUtil.toISOString(new Date())); + data.put("enteredBy", MainApp.instance().getString(R.string.app_name)); + Bundle bundle = new Bundle(); + bundle.putString("action", "dbAdd"); + bundle.putString("collection", "treatments"); + bundle.putString("data", data.toString()); + Intent intent = new Intent(Intents.ACTION_DATABASE); + intent.putExtras(bundle); + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + context.sendBroadcast(intent); + List q = context.getPackageManager().queryBroadcastReceivers(intent, 0); + if (q.size() < 1) { + log.error("DBADD No receivers"); + } else log.debug("DBADD dbAdd " + q.size() + " receivers " + data.toString()); + } catch (JSONException e) { + } + } + + public static void uploadTempBasalStartPercent(Integer percent, double durationInMinutes) { + try { + Context context = MainApp.instance().getApplicationContext(); + JSONObject data = new JSONObject(); + data.put("eventType", "Temp Basal"); + data.put("duration", durationInMinutes); + data.put("percent", percent - 100); data.put("created_at", DateUtil.toISOString(new Date())); data.put("enteredBy", MainApp.instance().getString(R.string.app_name)); Bundle bundle = new Bundle(); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopFragment.java index 5ab9eb5501..4774884322 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopFragment.java @@ -2,7 +2,6 @@ package info.nightscout.androidaps.plugins.Loop; import android.app.Activity; -import android.content.DialogInterface; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; @@ -10,7 +9,6 @@ import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.view.WindowManager; import android.widget.Button; import android.widget.TextView; @@ -29,7 +27,7 @@ import info.nightscout.androidaps.data.Result; import info.nightscout.androidaps.events.EventNewBG; import info.nightscout.androidaps.events.EventTreatmentChange; import info.nightscout.androidaps.interfaces.APSInterface; -import info.nightscout.androidaps.interfaces.ConstrainsInterface; +import info.nightscout.androidaps.interfaces.ConstraintsInterface; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.APSResult; @@ -42,14 +40,14 @@ public class LoopFragment extends Fragment implements View.OnClickListener, Plug TextView lastEnactView; TextView sourceView; TextView requestView; - TextView constrainsProcessedView; + TextView constraintsProcessedView; TextView setByPumpView; boolean confirmed; class LastRun implements Parcelable { public APSResult request = null; - public APSResult constrainsProcessed = null; + public APSResult constraintsProcessed = null; public Result setByPump = null; public String source = null; public Date lastAPSRun = null; @@ -63,11 +61,11 @@ public class LoopFragment extends Fragment implements View.OnClickListener, Plug @Override public void writeToParcel(Parcel dest, int flags) { dest.writeParcelable(request, 0); - dest.writeParcelable(constrainsProcessed, 0); + dest.writeParcelable(constraintsProcessed, 0); dest.writeParcelable(setByPump, 0); dest.writeString(source); dest.writeLong(lastAPSRun.getTime()); - dest.writeLong(lastEnact.getTime()); + dest.writeLong(lastEnact!= null ? lastEnact.getTime(): 0l); } public final Parcelable.Creator CREATOR = new Parcelable.Creator() { @@ -82,7 +80,7 @@ public class LoopFragment extends Fragment implements View.OnClickListener, Plug private LastRun(Parcel in) { request = in.readParcelable(APSResult.class.getClassLoader()); - constrainsProcessed = in.readParcelable(APSResult.class.getClassLoader()); + constraintsProcessed = in.readParcelable(APSResult.class.getClassLoader()); setByPump = in.readParcelable(Result.class.getClassLoader()); source = in.readString(); lastAPSRun = new Date(in.readLong()); @@ -157,7 +155,7 @@ public class LoopFragment extends Fragment implements View.OnClickListener, Plug lastEnactView = (TextView) view.findViewById(R.id.loop_lastenact); sourceView = (TextView) view.findViewById(R.id.loop_source); requestView = (TextView) view.findViewById(R.id.loop_request); - constrainsProcessedView = (TextView) view.findViewById(R.id.loop_constrainsprocessed); + constraintsProcessedView = (TextView) view.findViewById(R.id.loop_constraintsprocessed); setByPumpView = (TextView) view.findViewById(R.id.loop_setbypump); runNowButton = (Button) view.findViewById(R.id.loop_run); runNowButton.setOnClickListener(this); @@ -210,19 +208,19 @@ public class LoopFragment extends Fragment implements View.OnClickListener, Plug @Subscribe public void onStatusEvent(final EventNewBG ev) { - ConstrainsInterface constrainsInterface = MainActivity.getConfigBuilder(); - if (constrainsInterface.isAutomaticProcessingEnabled()) { + ConstraintsInterface constraintsInterface = MainActivity.getConfigBuilder(); + if (constraintsInterface.isAutomaticProcessingEnabled()) { invoke(); updateGUI(); } } private void invoke() { - ConstrainsInterface constrainsInterface = MainActivity.getConfigBuilder(); + ConstraintsInterface constraintsInterface = MainActivity.getConfigBuilder(); PumpInterface pumpInterface = MainActivity.getConfigBuilder().getActivePump(); APSResult result = null; - if (constrainsInterface == null || pumpInterface == null || !isEnabled()) + if (constraintsInterface == null || pumpInterface == null || !isEnabled()) return; APSInterface usedAPS = null; @@ -255,7 +253,7 @@ public class LoopFragment extends Fragment implements View.OnClickListener, Plug } confirmed = false; - if (constrainsInterface.manualConfirmationNeeded()) { + if (constraintsInterface.manualConfirmationNeeded()) { // TODO: user notification here confirmed = true; } else { @@ -263,15 +261,15 @@ public class LoopFragment extends Fragment implements View.OnClickListener, Plug } // check rate for constrais - APSResult resultAfterConstrains = result.clone(); + APSResult resultAfterConstraints = result.clone(); if (result.changeRequested) { - constrainsInterface.applyBasalConstrains(resultAfterConstrains); - Result applyResult = pumpInterface.applyAPSRequest(resultAfterConstrains); + constraintsInterface.applyBasalConstraints(resultAfterConstraints); + Result applyResult = pumpInterface.applyAPSRequest(resultAfterConstraints); Date lastEnact = lastRun != null ? lastRun.lastEnact : new Date(0, 0, 0); lastRun = new LastRun(); lastRun.request = result; - lastRun.constrainsProcessed = resultAfterConstrains; + lastRun.constraintsProcessed = resultAfterConstraints; lastRun.setByPump = applyResult; lastRun.source = ((PluginBase) usedAPS).getName(); lastRun.lastAPSRun = new Date(); @@ -282,7 +280,7 @@ public class LoopFragment extends Fragment implements View.OnClickListener, Plug } else { if (lastRun == null) lastRun = new LastRun(); lastRun.request = result; - lastRun.constrainsProcessed = resultAfterConstrains; + lastRun.constraintsProcessed = resultAfterConstraints; lastRun.setByPump = null; lastRun.source = null; lastRun.lastAPSRun = new Date(); @@ -298,7 +296,7 @@ public class LoopFragment extends Fragment implements View.OnClickListener, Plug public void run() { if (lastRun != null) { requestView.setText(lastRun.request != null ? lastRun.request.toString() : ""); - constrainsProcessedView.setText(lastRun.constrainsProcessed != null ? lastRun.constrainsProcessed.toString() : ""); + constraintsProcessedView.setText(lastRun.constraintsProcessed != null ? lastRun.constraintsProcessed.toString() : ""); setByPumpView.setText(lastRun.setByPump != null ? lastRun.setByPump.toString() : ""); sourceView.setText(lastRun.source != null ? lastRun.source.toString() : ""); lastRunView.setText(lastRun.lastAPSRun != null && lastRun.lastAPSRun.getTime() != 0 ? lastRun.lastAPSRun.toLocaleString() : ""); @@ -315,7 +313,7 @@ public class LoopFragment extends Fragment implements View.OnClickListener, Plug @Override public void run() { requestView.setText(""); - constrainsProcessedView.setText(""); + constraintsProcessedView.setText(""); setByPumpView.setText(""); sourceView.setText(""); lastRunView.setText(""); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Objectives/ObjectivesFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Objectives/ObjectivesFragment.java index bfc301dab8..aff370699b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Objectives/ObjectivesFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Objectives/ObjectivesFragment.java @@ -25,11 +25,11 @@ import java.util.List; import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.interfaces.ConstrainsInterface; +import info.nightscout.androidaps.interfaces.ConstraintsInterface; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.plugins.APSResult; -public class ObjectivesFragment extends Fragment implements View.OnClickListener, PluginBase, ConstrainsInterface { +public class ObjectivesFragment extends Fragment implements View.OnClickListener, PluginBase, ConstraintsInterface { private static Logger log = LoggerFactory.getLogger(ObjectivesFragment.class); RecyclerView recyclerView; @@ -42,7 +42,7 @@ public class ObjectivesFragment extends Fragment implements View.OnClickListener @Override public int getType() { - return PluginBase.CONSTRAINS; + return PluginBase.CONSTRAINTS; } @Override @@ -314,7 +314,7 @@ public class ObjectivesFragment extends Fragment implements View.OnClickListener } /** - * Constrains interface + * Constraints interface **/ @Override public boolean isAutomaticProcessingEnabled() { @@ -327,8 +327,28 @@ public class ObjectivesFragment extends Fragment implements View.OnClickListener } @Override - public APSResult applyBasalConstrains(APSResult result) { + public APSResult applyBasalConstraints(APSResult result) { return result; } + @Override + public Double applyBasalConstraints(Double absoluteRate) { + return absoluteRate; + } + + @Override + public Integer applyBasalConstraints(Integer percentRate) { + return percentRate; + } + + @Override + public Double applyBolusConstraints(Double insulin) { + return insulin; + } + + @Override + public Integer applyCarbsConstraints(Integer carbs) { + return carbs; + } + } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/DetermineBasalAdapterJS.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/DetermineBasalAdapterJS.java index de09782ddd..c25200ceb5 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/DetermineBasalAdapterJS.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/DetermineBasalAdapterJS.java @@ -132,8 +132,8 @@ public class DetermineBasalAdapterJS implements Parcelable { mV8rt.add(PARAM_iobData, mIobData); // Glucose status mGlucoseStatus = new V8Object(mV8rt); - mGlucoseStatus.add("delta", 0); mGlucoseStatus.add("glucose", 0); + mGlucoseStatus.add("delta", 0); mGlucoseStatus.add("avgdelta", 0); mV8rt.add(PARAM_glucoseStatus, mGlucoseStatus); // Meal data diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/DetermineBasalResult.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/DetermineBasalResult.java index c023bad6b5..cd955d32ca 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/DetermineBasalResult.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/DetermineBasalResult.java @@ -32,7 +32,7 @@ public class DetermineBasalResult extends APSResult { } if (result.contains("duration")) { duration = result.getInteger("duration"); - changeRequested = changeRequested & true; + changeRequested = changeRequested; } else { duration = -1; changeRequested = false; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/IobTotal.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/IobTotal.java index 0b167b8a94..77e3786313 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/IobTotal.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/IobTotal.java @@ -6,6 +6,7 @@ import org.json.JSONObject; import java.util.Date; import info.nightscout.utils.DateUtil; +import info.nightscout.utils.Round; public class IobTotal { public Double iob; @@ -50,6 +51,16 @@ public class IobTotal { return result; } + public IobTotal round() { + this.iob = Round.roundTo(this.iob, 0.001); + this.activity = Round.roundTo(this.activity, 0.0001); + this.bolussnooze = Round.roundTo(this.bolussnooze, 0.0001); + this.basaliob = Round.roundTo(this.basaliob, 0.001); + this.netbasalinsulin = Round.roundTo(this.netbasalinsulin, 0.001); + this.hightempinsulin = Round.roundTo(this.hightempinsulin, 0.001); + return this; + } + public JSONObject json() { JSONObject json = new JSONObject(); try { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/OpenAPSMAFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/OpenAPSMAFragment.java index bdae0f057c..3fb86d4ee7 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/OpenAPSMAFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/OpenAPSMAFragment.java @@ -36,6 +36,7 @@ import info.nightscout.androidaps.plugins.ScriptReader; import info.nightscout.androidaps.plugins.Treatments.TreatmentsFragment; import info.nightscout.client.data.NSProfile; import info.nightscout.utils.DateUtil; +import info.nightscout.utils.Round; public class OpenAPSMAFragment extends Fragment implements View.OnClickListener, PluginBase, APSInterface { private static Logger log = LoggerFactory.getLogger(OpenAPSMAFragment.class); @@ -262,6 +263,8 @@ public class OpenAPSMAFragment extends Fragment implements View.OnClickListener, double maxBasal = Double.parseDouble(SP.getString("openapsma_max_basal", "1").replace(",", ".")); double minBg = NSProfile.toMgdl(Double.parseDouble(SP.getString("openapsma_min_bg", minBgDefault).replace(",", ".")), units); double maxBg = NSProfile.toMgdl(Double.parseDouble(SP.getString("openapsma_max_bg", maxBgDefault).replace(",", ".")), units); + minBg = Round.roundTo(minBg, 1d); + maxBg = Round.roundTo(maxBg, 1d); TreatmentsInterface treatments = MainActivity.getConfigBuilder().getActiveTreatments(); TempBasalsInterface tempBasals = MainActivity.getConfigBuilder().getActiveTempBasals(); @@ -270,7 +273,7 @@ public class OpenAPSMAFragment extends Fragment implements View.OnClickListener, IobTotal bolusIob = treatments.getLastCalculation(); IobTotal basalIob = tempBasals.getLastCalculation(); - IobTotal iobTotal = IobTotal.combine(bolusIob, basalIob); + IobTotal iobTotal = IobTotal.combine(bolusIob, basalIob).round(); TreatmentsFragment.MealData mealData = treatments.getMealData(); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewExtendedBolusDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewExtendedBolusDialog.java new file mode 100644 index 0000000000..8bb831f780 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewExtendedBolusDialog.java @@ -0,0 +1,96 @@ +package info.nightscout.androidaps.plugins.Overview.Dialogs; + +import android.content.DialogInterface; +import android.os.Bundle; +import android.support.v4.app.DialogFragment; +import android.support.v7.app.AlertDialog; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.EditText; +import android.widget.RadioButton; + +import info.nightscout.androidaps.MainActivity; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.data.Result; +import info.nightscout.androidaps.interfaces.PumpInterface; + +public class NewExtendedBolusDialog extends DialogFragment implements View.OnClickListener { + + Button okButton; + EditText insulinEdit; + RadioButton h05Radio; + RadioButton h10Radio; + RadioButton h20Radio; + RadioButton h30Radio; + RadioButton h40Radio; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.overview_newextendedbolus_fragment, container, false); + okButton = (Button) view.findViewById(R.id.overview_newextendedbolus_okbutton); + insulinEdit = (EditText) view.findViewById(R.id.overview_newextendedbolus_insulin); + h05Radio = (RadioButton) view.findViewById(R.id.overview_newextendedbolus_05h); + h10Radio = (RadioButton) view.findViewById(R.id.overview_newextendedbolus_1h); + h20Radio = (RadioButton) view.findViewById(R.id.overview_newextendedbolus_2h); + h30Radio = (RadioButton) view.findViewById(R.id.overview_newextendedbolus_3h); + h40Radio = (RadioButton) view.findViewById(R.id.overview_newextendedbolus_4h); + + okButton.setOnClickListener(this); + return view; + } + + @Override + public void onClick(View view) { + switch (view.getId()) { + case R.id.overview_newextendedbolus_okbutton: + try { + int basalPercent = 100; + String insulinText = insulinEdit.getText().toString().replace(",", "."); + Double insulin = Double.parseDouble(!insulinText.equals("") ? insulinText : "0"); + int durationInMinutes = 30; + if (h10Radio.isChecked()) durationInMinutes = 60; + if (h20Radio.isChecked()) durationInMinutes = 120; + if (h30Radio.isChecked()) durationInMinutes = 180; + if (h40Radio.isChecked()) durationInMinutes = 240; + + String confirmMessage = getString(R.string.setextendedbolusquestion); + + Double insulinAfterConstraint = MainActivity.getConfigBuilder().applyBolusConstraints(insulin); + confirmMessage += " " + insulinAfterConstraint + " U "; + confirmMessage += getString(R.string.duration) + " " + durationInMinutes + "min ?"; + if (insulinAfterConstraint != insulin) + confirmMessage += "\n" + getString(R.string.constraintapllied); + insulin = insulinAfterConstraint; + + final Double finalInsulin = insulin; + final int finalDurationInMinutes = durationInMinutes; + + AlertDialog.Builder builder = new AlertDialog.Builder(this.getContext()); + builder.setTitle(this.getContext().getString(R.string.confirmation)); + builder.setMessage(confirmMessage); + builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + PumpInterface pump = MainActivity.getConfigBuilder().getActivePump(); + Result result = pump.setExtendedBolus(finalInsulin, finalDurationInMinutes); + if (!result.success) { + AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); + builder.setTitle(getContext().getString(R.string.treatmentdeliveryerror)); + builder.setMessage(result.comment); + builder.setPositiveButton(getContext().getString(R.string.ok), null); + builder.show(); + } + } + }); + builder.setNegativeButton(getString(R.string.cancel), null); + builder.show(); + dismiss(); + + } catch (Exception e) { + e.printStackTrace(); + } + } + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewTempBasalDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewTempBasalDialog.java new file mode 100644 index 0000000000..55f955054d --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewTempBasalDialog.java @@ -0,0 +1,114 @@ +package info.nightscout.androidaps.plugins.Overview.Dialogs; + +import android.content.DialogInterface; +import android.os.Bundle; +import android.support.v4.app.DialogFragment; +import android.support.v7.app.AlertDialog; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.EditText; +import android.widget.RadioButton; + +import info.nightscout.androidaps.MainActivity; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.data.Result; +import info.nightscout.androidaps.interfaces.PumpInterface; + +public class NewTempBasalDialog extends DialogFragment implements View.OnClickListener { + + Button okButton; + EditText basalEdit; + RadioButton percentRadio; + RadioButton absoluteRadio; + RadioButton h05Radio; + RadioButton h10Radio; + RadioButton h20Radio; + RadioButton h30Radio; + RadioButton h40Radio; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.overview_newtempbasal_fragment, container, false); + okButton = (Button) view.findViewById(R.id.overview_newtempbasal_okbutton); + basalEdit = (EditText) view.findViewById(R.id.overview_newtempbasal_basal); + percentRadio = (RadioButton) view.findViewById(R.id.overview_newtempbasal_percent); + absoluteRadio = (RadioButton) view.findViewById(R.id.overview_newtempbasal_absolute); + h05Radio = (RadioButton) view.findViewById(R.id.overview_newtempbasal_05h); + h10Radio = (RadioButton) view.findViewById(R.id.overview_newtempbasal_1h); + h20Radio = (RadioButton) view.findViewById(R.id.overview_newtempbasal_2h); + h30Radio = (RadioButton) view.findViewById(R.id.overview_newtempbasal_3h); + h40Radio = (RadioButton) view.findViewById(R.id.overview_newtempbasal_4h); + + okButton.setOnClickListener(this); + return view; + } + + @Override + public void onClick(View view) { + switch (view.getId()) { + case R.id.overview_newtempbasal_okbutton: + try { + int basalPercent = 100; + String basalText = basalEdit.getText().toString().replace(",", "."); + Double basal = Double.parseDouble(!basalText.equals("") ? basalText : "0"); + final boolean setAsPercent = percentRadio.isChecked(); + int durationInMinutes = 30; + if (h10Radio.isChecked()) durationInMinutes = 60; + if (h20Radio.isChecked()) durationInMinutes = 120; + if (h30Radio.isChecked()) durationInMinutes = 180; + if (h40Radio.isChecked()) durationInMinutes = 240; + + String confirmMessage = getString(R.string.setbasalquestion); + if (setAsPercent) { + basalPercent = MainActivity.getConfigBuilder().applyBasalConstraints(basal.intValue()); + confirmMessage += "\n " + basalPercent + "% "; + confirmMessage += getString(R.string.duration) + " " + durationInMinutes + "min ?"; + if (basalPercent != basal.intValue()) + confirmMessage += "\n" + getString(R.string.constraintapllied); + } else { + Double basalAfterConstraint = MainActivity.getConfigBuilder().applyBasalConstraints(basal); + confirmMessage += "\n " + basalAfterConstraint + " U/h "; + confirmMessage += getString(R.string.duration) + " " + durationInMinutes + "min ?"; + if (basalAfterConstraint != basal) + confirmMessage += "\n" + getString(R.string.constraintapllied); + basal = basalAfterConstraint; + } + + final int finalBasalPercent = basalPercent; + final Double finalBasal = basal; + final int finalDurationInMinutes = durationInMinutes; + + AlertDialog.Builder builder = new AlertDialog.Builder(this.getContext()); + builder.setTitle(this.getContext().getString(R.string.confirmation)); + builder.setMessage(confirmMessage); + builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + PumpInterface pump = MainActivity.getConfigBuilder().getActivePump(); + Result result; + if (setAsPercent) { + result = pump.setTempBasalPercent(finalBasalPercent, finalDurationInMinutes); + } else { + result = pump.setTempBasalAbsolute(finalBasal, finalDurationInMinutes); + } + if (!result.success) { + AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); + builder.setTitle(getContext().getString(R.string.treatmentdeliveryerror)); + builder.setMessage(result.comment); + builder.setPositiveButton(getContext().getString(R.string.ok), null); + builder.show(); + } + } + }); + builder.setNegativeButton(getString(R.string.cancel), null); + builder.show(); + dismiss(); + + } catch (Exception e) { + e.printStackTrace(); + } + } + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewTreatmentDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewTreatmentDialog.java new file mode 100644 index 0000000000..5f49018f95 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewTreatmentDialog.java @@ -0,0 +1,96 @@ +package info.nightscout.androidaps.plugins.Overview.Dialogs; + +import android.content.DialogInterface; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.preference.PreferenceManager; +import android.support.v4.app.DialogFragment; +import android.support.v7.app.AlertDialog; +import android.view.*; +import android.view.View.OnClickListener; +import android.view.animation.Interpolator; +import android.widget.Button; +import android.widget.TextView; + +import info.nightscout.androidaps.MainActivity; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.data.Result; +import info.nightscout.androidaps.interfaces.PumpInterface; + +public class NewTreatmentDialog extends DialogFragment implements OnClickListener { + + Button deliverButton; + TextView insulin; + TextView carbs; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.overview_newtreatment_fragment, null, false); + + deliverButton = (Button) view.findViewById(R.id.treatments_newtreatment_deliverbutton); + + deliverButton.setOnClickListener(this); + getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE); + getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE); + insulin = (TextView) view.findViewById(R.id.treatments_newtreatment_insulinamount); + carbs = (TextView) view.findViewById(R.id.treatments_newtreatment_carbsamount); + + return view; + } + + @Override + public void onClick(View view) { + switch (view.getId()) { + case R.id.treatments_newtreatment_deliverbutton: + + try { + String insulinText = this.insulin.getText().toString().replace(",", "."); + String carbsText = this.carbs.getText().toString().replace(",", "."); + Double insulin = Double.parseDouble(!insulinText.equals("") ? insulinText : "0"); + Integer carbs = Integer.parseInt(!carbsText.equals("") ? carbsText : "0"); + + String confirmMessage = getString(R.string.entertreatmentquestion); + + Double insulinAfterConstraints = MainActivity.getConfigBuilder().applyBolusConstraints(insulin); + Integer carbsAfterConstraints = MainActivity.getConfigBuilder().applyCarbsConstraints(carbs); + + confirmMessage += getString(R.string.bolus) + ": " + insulinAfterConstraints + "U"; + confirmMessage += "\n" + getString(R.string.carbs) + ": " + carbsAfterConstraints + "g"; + if (insulinAfterConstraints != insulin || carbsAfterConstraints != carbs) + confirmMessage += "\n" + getString(R.string.constraintapllied); + + final Double finalInsulinAfterConstraints = insulinAfterConstraints; + final Integer finalCarbsAfterConstraints = carbsAfterConstraints; + + AlertDialog.Builder builder = new AlertDialog.Builder(this.getContext()); + builder.setTitle(this.getContext().getString(R.string.confirmation)); + builder.setMessage(confirmMessage); + builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + if (finalInsulinAfterConstraints > 0 || finalCarbsAfterConstraints > 0) { + PumpInterface pump = MainActivity.getConfigBuilder().getActivePump(); + Result result = pump.deliverTreatment(finalInsulinAfterConstraints, finalCarbsAfterConstraints); + if (!result.success) { + AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); + builder.setTitle(getContext().getString(R.string.treatmentdeliveryerror)); + builder.setMessage(result.comment); + builder.setPositiveButton(getContext().getString(R.string.ok), null); + builder.show(); + } + } + } + }); + builder.setNegativeButton(getString(R.string.cancel), null); + builder.show(); + dismiss(); + } catch (Exception e) { + e.printStackTrace(); + } + break; + } + + } + +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewTreatmentDialogFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewTreatmentDialogFragment.java deleted file mode 100644 index 23439b4c42..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewTreatmentDialogFragment.java +++ /dev/null @@ -1,77 +0,0 @@ -package info.nightscout.androidaps.plugins.Overview.Dialogs; - -import android.content.DialogInterface; -import android.content.Intent; -import android.content.SharedPreferences; -import android.os.Bundle; -import android.preference.PreferenceManager; -import android.support.v4.app.DialogFragment; -import android.support.v7.app.AlertDialog; -import android.view.*; -import android.view.View.OnClickListener; -import android.widget.Button; -import android.widget.TextView; - -import info.nightscout.androidaps.MainActivity; -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.Services.Intents; -import info.nightscout.androidaps.data.Result; - -public class NewTreatmentDialogFragment extends DialogFragment implements OnClickListener { - - Button deliverButton; - TextView insulin; - TextView carbs; - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.treatments_newtreatment_fragment, null, false); - - deliverButton = (Button) view.findViewById(R.id.treatments_newtreatment_deliverbutton); - - deliverButton.setOnClickListener(this); - getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE); - getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE); - insulin = (TextView) view.findViewById(R.id.treatments_newtreatment_insulinamount); - carbs = (TextView) view.findViewById(R.id.treatments_newtreatment_carbsamount); - - return view; - } - - @Override - public void onClick(View view) { - switch (view.getId()) { - case R.id.treatments_newtreatment_deliverbutton: - SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext()); - Double maxbolus = Double.parseDouble(SP.getString("treatmentssafety_maxbolus", "3")); - Double maxcarbs = Double.parseDouble(SP.getString("treatmentssafety_maxcarbs", "48")); - - - String insulinText = this.insulin.getText().toString().replace(",", "."); - String carbsText = this.carbs.getText().toString().replace(",", "."); - Double insulin = Double.parseDouble(!insulinText.equals("") ? this.insulin.getText().toString() : "0"); - Double carbs = Double.parseDouble(!carbsText.equals("") ? this.carbs.getText().toString() : "0"); - if (insulin > maxbolus) { - this.insulin.setText(""); - } else if (carbs > maxcarbs) { - this.carbs.setText(""); - } else if (insulin > 0d || carbs > 0d) { - dismiss(); - Result result = MainActivity.getConfigBuilder().getActivePump().deliverTreatment(insulin, carbs); - if (!result.success) { - AlertDialog.Builder builder = new AlertDialog.Builder(this.getContext()); - builder.setTitle(this.getContext().getString(R.string.bolusdeliveryerror)); - builder.setMessage(result.comment); - builder.setPositiveButton(this.getContext().getString(R.string.ok), null); - builder.show(); - - } - } - break; - } - - } - -} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialogFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialog.java similarity index 73% rename from app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialogFragment.java rename to app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialog.java index 6188808545..d6e3e735de 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialogFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialog.java @@ -1,9 +1,11 @@ package info.nightscout.androidaps.plugins.Overview.Dialogs; +import android.content.DialogInterface; import android.content.SharedPreferences; import android.os.Bundle; import android.preference.PreferenceManager; import android.support.v4.app.DialogFragment; +import android.support.v7.app.AlertDialog; import android.text.Editable; import android.text.TextWatcher; import android.view.*; @@ -15,18 +17,19 @@ import android.widget.TextView; import java.text.DecimalFormat; -import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainActivity; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.data.Result; import info.nightscout.androidaps.db.BgReading; +import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.interfaces.TempBasalsInterface; import info.nightscout.androidaps.interfaces.TreatmentsInterface; import info.nightscout.androidaps.plugins.OpenAPSMA.IobTotal; import info.nightscout.client.data.NSProfile; import info.nightscout.utils.*; -public class WizardDialogFragment extends DialogFragment implements OnClickListener { +public class WizardDialog extends DialogFragment implements OnClickListener { Button wizardDialogDeliverButton; TextView correctionInput; @@ -43,7 +46,7 @@ public class WizardDialogFragment extends DialogFragment implements OnClickListe public static final DecimalFormat numberFormat = new DecimalFormat("0.00"); public static final DecimalFormat intFormat = new DecimalFormat("0"); - Double calculatedCarbs = 0d; + Integer calculatedCarbs = 0; Double calculatedTotalInsulin = 0d; final private TextWatcher textWatcher = new TextWatcher() { @@ -69,7 +72,7 @@ public class WizardDialogFragment extends DialogFragment implements OnClickListe @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.treatments_wizard_fragment, null, false); + View view = inflater.inflate(R.layout.overview_wizard_fragment, null, false); wizardDialogDeliverButton = (Button) view.findViewById(R.id.treatments_wizard_deliverButton); wizardDialogDeliverButton.setOnClickListener(this); @@ -109,8 +112,48 @@ public class WizardDialogFragment extends DialogFragment implements OnClickListe switch (view.getId()) { case R.id.treatments_wizard_deliverButton: if (calculatedTotalInsulin > 0d || calculatedCarbs > 0d){ + DecimalFormat formatNumber2decimalplaces = new DecimalFormat("0.00"); + String confirmMessage = getString(R.string.entertreatmentquestion); + + Double insulinAfterConstraints = MainActivity.getConfigBuilder().applyBolusConstraints(calculatedTotalInsulin); + Integer carbsAfterConstraints = MainActivity.getConfigBuilder().applyCarbsConstraints(calculatedCarbs); + + confirmMessage += "\n" + getString(R.string.bolus) + ": " + formatNumber2decimalplaces.format(insulinAfterConstraints) + "U"; + confirmMessage += "\n" + getString(R.string.carbs) + ": " + carbsAfterConstraints + "g"; + + if (insulinAfterConstraints != calculatedTotalInsulin || carbsAfterConstraints != calculatedCarbs) { + AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); + builder.setTitle(getContext().getString(R.string.treatmentdeliveryerror)); + builder.setMessage(getString(R.string.constraints_violation) + "\n" + getString(R.string.changeyourinput)); + builder.setPositiveButton(getContext().getString(R.string.ok), null); + builder.show(); + return; + } + + final Double finalInsulinAfterConstraints = insulinAfterConstraints; + final Integer finalCarbsAfterConstraints = carbsAfterConstraints; + + AlertDialog.Builder builder = new AlertDialog.Builder(this.getContext()); + builder.setTitle(this.getContext().getString(R.string.confirmation)); + builder.setMessage(confirmMessage); + builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + if (finalInsulinAfterConstraints > 0 || finalCarbsAfterConstraints > 0) { + PumpInterface pump = MainActivity.getConfigBuilder().getActivePump(); + Result result = pump.deliverTreatment(finalInsulinAfterConstraints, finalCarbsAfterConstraints); + if (!result.success) { + AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); + builder.setTitle(getContext().getString(R.string.treatmentdeliveryerror)); + builder.setMessage(result.comment); + builder.setPositiveButton(getContext().getString(R.string.ok), null); + builder.show(); + } + } + } + }); + builder.setNegativeButton(getString(R.string.cancel), null); + builder.show(); dismiss(); - MainActivity.getConfigBuilder().getActivePump().deliverTreatment(calculatedTotalInsulin, calculatedCarbs); } break; } @@ -170,10 +213,6 @@ public class WizardDialogFragment extends DialogFragment implements OnClickListe } private void calculateInsulin() { - SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext()); - Double maxbolus = Double.parseDouble(SP.getString("treatmentssafety_maxbolus", "3")); - Double maxcarbs = Double.parseDouble(SP.getString("treatmentssafety_maxcarbs", "48")); - NSProfile profile = MainActivity.getConfigBuilder().getActiveProfile().getProfile(); // Entered values @@ -182,17 +221,17 @@ public class WizardDialogFragment extends DialogFragment implements OnClickListe String i_correction = this.correctionInput.getText().toString().replace(",", "."); Double c_bg = 0d; try { c_bg = Double.parseDouble(i_bg.equals("") ? "0" : i_bg); } catch (Exception e) {} - Double c_carbs = 0d; - try { c_carbs = Double.parseDouble(i_carbs.equals("") ? "0" : i_carbs); } catch (Exception e) {} - c_carbs = ((Long)Math.round(c_carbs)).doubleValue(); + Integer c_carbs = 0; + try { c_carbs = Integer.parseInt(i_carbs.equals("") ? "0" : i_carbs); } catch (Exception e) {} + c_carbs = (Integer) Math.round(c_carbs); Double c_correction = 0d; try { c_correction = Double.parseDouble(i_correction.equals("") ? "0" : i_correction); } catch (Exception e) {} - if(c_correction > maxbolus) { + if(c_correction != MainActivity.getConfigBuilder().applyBolusConstraints(c_correction)) { this.correctionInput.setText(""); wizardDialogDeliverButton.setVisibility(Button.GONE); return; } - if(c_carbs > maxcarbs) { + if(c_carbs != MainActivity.getConfigBuilder().applyCarbsConstraints(c_carbs)) { this.carbsInput.setText(""); wizardDialogDeliverButton.setVisibility(Button.GONE); return; @@ -244,7 +283,7 @@ public class WizardDialogFragment extends DialogFragment implements OnClickListe calculatedTotalInsulin = 0d; totalInsulin.setText(""); } else { - calculatedTotalInsulin = roundTo(calculatedTotalInsulin, 0.05d); + calculatedTotalInsulin = Round.roundTo(calculatedTotalInsulin, 0.05d); total.setText(""); totalInsulin.setText(numberFormat.format(calculatedTotalInsulin) + "U"); } @@ -260,11 +299,4 @@ public class WizardDialogFragment extends DialogFragment implements OnClickListe wizardDialogDeliverButton.setVisibility(Button.GONE); } } - - private Double roundTo(Double x, Double step) { - if (x != 0d) { - return Math.round(x / step) * step; - } - return 0d; - } } \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java index b090788f0d..44eb66bd23 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java @@ -38,10 +38,13 @@ import info.nightscout.androidaps.db.DatabaseHelper; import info.nightscout.androidaps.db.TempBasal; import info.nightscout.androidaps.events.EventNewBG; import info.nightscout.androidaps.events.EventTempBasalChange; +import info.nightscout.androidaps.events.EventTreatmentChange; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PumpInterface; -import info.nightscout.androidaps.plugins.Overview.Dialogs.NewTreatmentDialogFragment; -import info.nightscout.androidaps.plugins.Overview.Dialogs.WizardDialogFragment; +import info.nightscout.androidaps.plugins.Overview.Dialogs.NewExtendedBolusDialog; +import info.nightscout.androidaps.plugins.Overview.Dialogs.NewTempBasalDialog; +import info.nightscout.androidaps.plugins.Overview.Dialogs.NewTreatmentDialog; +import info.nightscout.androidaps.plugins.Overview.Dialogs.WizardDialog; import info.nightscout.client.data.NSProfile; @@ -53,9 +56,13 @@ public class OverviewFragment extends Fragment implements PluginBase { TextView deltaView; GraphView bgGraph; + LinearLayout cancelTempLayout; + LinearLayout setTempLayout; Button cancelTempButton; Button treatmentButton; Button wizardButton; + Button setTempButton; + Button setExtenedButton; boolean visibleNow = false; Handler loopHandler = new Handler(); @@ -141,12 +148,17 @@ public class OverviewFragment extends Fragment implements PluginBase { cancelTempButton = (Button) view.findViewById(R.id.overview_canceltemp); treatmentButton = (Button) view.findViewById(R.id.overview_treatment); wizardButton = (Button) view.findViewById(R.id.overview_wizard); + setExtenedButton = (Button) view.findViewById(R.id.overview_extendedbolus); + setTempButton = (Button) view.findViewById(R.id.overview_settempbasal); + cancelTempButton = (Button) view.findViewById(R.id.overview_canceltemp); + setTempLayout = (LinearLayout) view.findViewById(R.id.overview_settemplayout); + cancelTempLayout = (LinearLayout) view.findViewById(R.id.overview_canceltemplayout); treatmentButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { FragmentManager manager = getFragmentManager(); - NewTreatmentDialogFragment treatmentDialogFragment = new NewTreatmentDialogFragment(); + NewTreatmentDialog treatmentDialogFragment = new NewTreatmentDialog(); treatmentDialogFragment.show(manager, "TreatmentDialog"); } }); @@ -155,8 +167,8 @@ public class OverviewFragment extends Fragment implements PluginBase { @Override public void onClick(View view) { FragmentManager manager = getFragmentManager(); - WizardDialogFragment wizardDialogFragment = new WizardDialogFragment(); - wizardDialogFragment.show(manager, "WizardDialog"); + WizardDialog wizardDialog = new WizardDialog(); + wizardDialog.show(manager, "WizardDialog"); } }); @@ -170,6 +182,25 @@ public class OverviewFragment extends Fragment implements PluginBase { } } }); + + setTempButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + FragmentManager manager = getFragmentManager(); + NewTempBasalDialog newTempDialog = new NewTempBasalDialog(); + newTempDialog.show(manager, "NewTempDialog"); + } + }); + + setExtenedButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + FragmentManager manager = getFragmentManager(); + NewExtendedBolusDialog newExtendedDialog = new NewExtendedBolusDialog(); + newExtendedDialog.show(manager, "NewExtendedDialog"); + } + }); + updateGUI(); return view; } @@ -183,6 +214,20 @@ public class OverviewFragment extends Fragment implements PluginBase { MainApp.bus().register(this); } + @Subscribe + public void onStatusEvent(final EventTreatmentChange ev) { + Activity activity = getActivity(); + if (activity != null) + activity.runOnUiThread(new Runnable() { + @Override + public void run() { + updateGUI(); + } + }); + else + log.debug("EventTreatmentChange: Activity is null"); + } + @Subscribe public void onStatusEvent(final EventTempBasalChange ev) { Activity activity = getActivity(); @@ -243,10 +288,12 @@ public class OverviewFragment extends Fragment implements PluginBase { if (pump.isTempBasalInProgress()) { TempBasal activeTemp = pump.getTempBasal(); - cancelTempButton.setVisibility(View.VISIBLE); + cancelTempLayout.setVisibility(View.VISIBLE); + setTempLayout.setVisibility(View.GONE); cancelTempButton.setText(MainApp.instance().getString(R.string.cancel) + ": " + activeTemp.toString()); } else { - cancelTempButton.setVisibility(View.INVISIBLE); + cancelTempLayout.setVisibility(View.GONE); + setTempLayout.setVisibility(View.VISIBLE); } // **** BG value **** diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SafetyFragment/SafetyFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/SafetyFragment/SafetyFragment.java index 70ec045682..9fb5466f34 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SafetyFragment/SafetyFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/SafetyFragment/SafetyFragment.java @@ -2,17 +2,8 @@ package info.nightscout.androidaps.plugins.SafetyFragment; import android.content.SharedPreferences; -import android.os.Bundle; -import android.preference.PreferenceFragment; import android.preference.PreferenceManager; import android.support.v4.app.Fragment; -import android.text.Editable; -import android.text.TextWatcher; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.EditText; -import android.widget.TextView; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -21,19 +12,19 @@ import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainActivity; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.interfaces.ConstrainsInterface; +import info.nightscout.androidaps.interfaces.ConstraintsInterface; import info.nightscout.androidaps.interfaces.PluginBase; -import info.nightscout.androidaps.interfaces.ProfileInterface; import info.nightscout.androidaps.plugins.APSResult; import info.nightscout.client.data.NSProfile; +import info.nightscout.utils.Round; -public class SafetyFragment extends Fragment implements PluginBase, ConstrainsInterface { +public class SafetyFragment extends Fragment implements PluginBase, ConstraintsInterface { private static Logger log = LoggerFactory.getLogger(SafetyFragment.class); @Override public int getType() { - return PluginBase.CONSTRAINS; + return PluginBase.CONSTRAINTS; } @Override @@ -71,7 +62,7 @@ public class SafetyFragment extends Fragment implements PluginBase, ConstrainsIn } /** - * Constrains interface + * Constraints interface **/ @Override public boolean isAutomaticProcessingEnabled() { @@ -84,33 +75,111 @@ public class SafetyFragment extends Fragment implements PluginBase, ConstrainsIn } @Override - public APSResult applyBasalConstrains(APSResult result) { + public APSResult applyBasalConstraints(APSResult result) { + result.rate = applyBasalConstraints(result.rate); + return result; + } + + @Override + public Double applyBasalConstraints(Double absoluteRate) { SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext()); Double maxBasal = Double.parseDouble(SP.getString("openapsma_max_basal", "1").replace(",", ".")); NSProfile profile = MainActivity.getConfigBuilder().getActiveProfile().getProfile(); - if (result.rate < 0) result.rate = 0; + if (absoluteRate < 0) absoluteRate = 0d; Integer maxBasalMult = 4; Integer maxBasalFromDaily = 3; // Check percentRate but absolute rate too, because we know real current basal in pump - Double origRate = result.rate; - if (result.rate > maxBasal) { - result.rate = maxBasal; - if (Config.logConstrainsChnages) - log.debug("Limiting rate " + origRate + " by maxBasal preference to " + result.rate + "U/h"); + Double origRate = absoluteRate; + if (absoluteRate > maxBasal) { + absoluteRate = maxBasal; + if (Config.logConstraintsChanges) + log.debug("Limiting rate " + origRate + " by maxBasal preference to " + absoluteRate + "U/h"); } - if (result.rate > maxBasalMult * profile.getBasal(NSProfile.secondsFromMidnight())) { - result.rate = Math.floor(maxBasalMult * profile.getBasal(NSProfile.secondsFromMidnight()) * 100) / 100; - if (Config.logConstrainsChnages) - log.debug("Limiting rate " + origRate + " by maxBasalMult to " + result.rate + "U/h"); + if (absoluteRate > maxBasalMult * profile.getBasal(NSProfile.secondsFromMidnight())) { + absoluteRate = Math.floor(maxBasalMult * profile.getBasal(NSProfile.secondsFromMidnight()) * 100) / 100; + if (Config.logConstraintsChanges) + log.debug("Limiting rate " + origRate + " by maxBasalMult to " + absoluteRate + "U/h"); } - if (result.rate > profile.getMaxDailyBasal() * maxBasalFromDaily) { - result.rate = profile.getMaxDailyBasal() * maxBasalFromDaily; - if (Config.logConstrainsChnages) - log.debug("Limiting rate " + origRate + " by 3 * maxDailyBasal to " + result.rate + "U/h"); + if (absoluteRate > profile.getMaxDailyBasal() * maxBasalFromDaily) { + absoluteRate = profile.getMaxDailyBasal() * maxBasalFromDaily; + if (Config.logConstraintsChanges) + log.debug("Limiting rate " + origRate + " by 3 * maxDailyBasal to " + absoluteRate + "U/h"); } - return result; + return absoluteRate; + } + + @Override + public Integer applyBasalConstraints(Integer percentRate) { + SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext()); + Double maxBasal = Double.parseDouble(SP.getString("openapsma_max_basal", "1").replace(",", ".")); + + NSProfile profile = MainActivity.getConfigBuilder().getActiveProfile().getProfile(); + Double currentBasal = profile.getBasal(profile.secondsFromMidnight()); + + Double absoluteRate = currentBasal * ((double) percentRate / 100); + + if (Config.logConstraintsChanges) + log.debug("Percent rate " + percentRate + "% recalculated to " + absoluteRate + "U/h with current basal " + currentBasal + "U/h"); + + if (absoluteRate < 0) absoluteRate = 0d; + + Integer maxBasalMult = 4; + Integer maxBasalFromDaily = 3; + // Check percentRate but absolute rate too, because we know real current basal in pump + Double origRate = absoluteRate; + if (absoluteRate > maxBasal) { + absoluteRate = maxBasal; + if (Config.logConstraintsChanges) + log.debug("Limiting rate " + origRate + " by maxBasal preference to " + absoluteRate + "U/h"); + } + if (absoluteRate > maxBasalMult * profile.getBasal(NSProfile.secondsFromMidnight())) { + absoluteRate = Math.floor(maxBasalMult * profile.getBasal(NSProfile.secondsFromMidnight()) * 100) / 100; + if (Config.logConstraintsChanges) + log.debug("Limiting rate " + origRate + " by maxBasalMult to " + absoluteRate + "U/h"); + } + if (absoluteRate > profile.getMaxDailyBasal() * maxBasalFromDaily) { + absoluteRate = profile.getMaxDailyBasal() * maxBasalFromDaily; + if (Config.logConstraintsChanges) + log.debug("Limiting rate " + origRate + " by 3 * maxDailyBasal to " + absoluteRate + "U/h"); + } + + Integer percentRateAfterConst = new Double(absoluteRate / currentBasal * 100).intValue(); + if (percentRateAfterConst < 100) Round.ceilTo(absoluteRate, 10d).intValue(); + else Round.floorTo(absoluteRate, 10d).intValue(); + + if (Config.logConstraintsChanges) + log.debug("Recalculated percent rate " + percentRate + "% to " + percentRateAfterConst + "%"); + return percentRateAfterConst; + } + + @Override + public Double applyBolusConstraints(Double insulin) { + SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext()); + try { + Double maxBolus = Double.parseDouble(SP.getString("treatmentssafety_maxbolus", "3")); + + if (insulin < 0) insulin = 0d; + if (insulin > maxBolus) insulin = maxBolus; + } catch (Exception e) { + insulin = 0d; + } + return insulin; + } + + @Override + public Integer applyCarbsConstraints(Integer carbs) { + SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext()); + try { + Integer maxCarbs = Integer.parseInt(SP.getString("treatmentssafety_maxcarbs", "48")); + + if (carbs < 0) carbs = 0; + if (carbs > maxCarbs) carbs = maxCarbs; + } catch (Exception e) { + carbs = 0; + } + return carbs; } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/TempBasals/TempBasalsFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/TempBasals/TempBasalsFragment.java index ad37cd3ed4..274a18e986 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/TempBasals/TempBasalsFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/TempBasals/TempBasalsFragment.java @@ -14,6 +14,7 @@ import android.widget.TextView; import com.j256.ormlite.dao.Dao; import com.j256.ormlite.stmt.PreparedQuery; import com.j256.ormlite.stmt.QueryBuilder; +import com.j256.ormlite.stmt.Where; import com.squareup.otto.Subscribe; import org.slf4j.Logger; @@ -110,6 +111,8 @@ public class TempBasalsFragment extends Fragment implements PluginBase, TempBasa */ QueryBuilder queryBuilder = dao.queryBuilder(); queryBuilder.orderBy("timeIndex", false); + Where where = queryBuilder.where(); + where.eq("isExtended", false); queryBuilder.limit(30l); PreparedQuery preparedQuery = queryBuilder.prepare(); tempBasals = dao.query(preparedQuery); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/VirtualPump/VirtualPumpFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/VirtualPump/VirtualPumpFragment.java index 04e8dc0dc8..f0612bbde1 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/VirtualPump/VirtualPumpFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/VirtualPump/VirtualPumpFragment.java @@ -17,9 +17,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.sql.SQLException; -import java.text.DateFormat; -import java.text.DecimalFormat; -import java.text.SimpleDateFormat; import java.util.Date; import info.nightscout.androidaps.Config; @@ -30,7 +27,6 @@ import info.nightscout.androidaps.events.EventTreatmentChange; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.data.Result; import info.nightscout.androidaps.db.TempBasal; -import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.plugins.APSResult; import info.nightscout.client.data.NSProfile; @@ -220,14 +216,15 @@ public class VirtualPumpFragment extends Fragment implements PluginBase, PumpInt public double getTempBasalRemainingMinutes() { if (!isTempBasalInProgress()) return 0; - return tempBasal.getRemainingMinutes(); + return tempBasal.getPlannedRemainingMinutes(); } @Override - public Result deliverTreatment(Double insulin, Double carbs) { + public Result deliverTreatment(Double insulin, Integer carbs) { Result result = new Result(); result.success = true; result.bolusDelivered = insulin; + result.carbsDelivered = carbs; result.comment = getString(R.string.virtualpump_resultok); if (Config.logPumpComm) @@ -282,6 +279,7 @@ public class VirtualPumpFragment extends Fragment implements PluginBase, PumpInt result.success = true; result.enacted = true; result.percent = percent; + result.isPercent = true; result.duration = durationInMinutes; result.comment = getString(R.string.virtualpump_resultok); try { @@ -308,6 +306,7 @@ public class VirtualPumpFragment extends Fragment implements PluginBase, PumpInt extendedBolus.isExtended = true; extendedBolus.absolute = insulin * 60d / durationInMinutes; extendedBolus.duration = durationInMinutes; + extendedBolus.isAbsolute = true; result.success = true; result.enacted = true; result.comment = getString(R.string.virtualpump_resultok); @@ -378,6 +377,8 @@ public class VirtualPumpFragment extends Fragment implements PluginBase, PumpInt if (isTempBasalInProgress()) { if (request.rate == getTempBasalAbsoluteRate()) { Result noChange = new Result(); + noChange.absolute = request.rate; + noChange.duration = tempBasal.getPlannedRemainingMinutes(); noChange.enacted = false; noChange.comment = "Temp basal set correctly"; noChange.success = true; @@ -388,6 +389,8 @@ public class VirtualPumpFragment extends Fragment implements PluginBase, PumpInt } if (request.rate == getBaseBasalRate()) { Result noChange = new Result(); + noChange.absolute = request.rate; + noChange.duration = 0; noChange.enacted = false; noChange.comment = "Basal set correctly"; noChange.success = true; @@ -410,7 +413,7 @@ public class VirtualPumpFragment extends Fragment implements PluginBase, PumpInt if (isTempBasalInProgress()) { status.put("tempbasalpct", tempBasal.percent); status.put("tempbasalstart", DateUtil.toISOString(tempBasal.timeStart)); - status.put("tempbasalremainmin", tempBasal.getRemainingMinutes()); + status.put("tempbasalremainmin", tempBasal.getPlannedRemainingMinutes()); } status.put("timestamp", DateUtil.toISOString(new Date())); diff --git a/app/src/main/java/info/nightscout/utils/Round.java b/app/src/main/java/info/nightscout/utils/Round.java new file mode 100644 index 0000000000..f1fe3e0df6 --- /dev/null +++ b/app/src/main/java/info/nightscout/utils/Round.java @@ -0,0 +1,25 @@ +package info.nightscout.utils; + +/** + * Created by mike on 20.06.2016. + */ +public class Round { + public static Double roundTo(Double x, Double step) { + if (x != 0d) { + return Math.round(x / step) * step; + } + return 0d; + } + public static Double floorTo(Double x, Double step) { + if (x != 0d) { + return Math.floor(x / step) * step; + } + return 0d; + } + public static Double ceilTo(Double x, Double step) { + if (x != 0d) { + return Math.ceil(x / step) * step; + } + return 0d; + } +} diff --git a/app/src/main/res/layout/configbuilder_fragment.xml b/app/src/main/res/layout/configbuilder_fragment.xml index e40cd070e0..4c3140ddf3 100644 --- a/app/src/main/res/layout/configbuilder_fragment.xml +++ b/app/src/main/res/layout/configbuilder_fragment.xml @@ -116,12 +116,12 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="5dp" - android:text="@string/configbuilder_constrains" + android:text="@string/configbuilder_constraints" android:textAppearance="?android:attr/textAppearanceMedium" android:textStyle="bold" /> + android:layout_height="match_parent" + android:orientation="vertical"> + android:layout_height="wrap_content" + android:orientation="horizontal"> + android:textSize="80dp" + android:textStyle="bold" /> + android:layout_marginTop="10dp" + android:orientation="vertical"> - - + + + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginLeft="10dp" + android:textAppearance="?android:attr/textAppearanceMedium" /> @@ -52,44 +53,72 @@ android:layout_height="200dip" /> + android:layout_height="wrap_content" + android:orientation="horizontal">