diff --git a/app/src/main/java/info/nightscout/androidaps/MainApp.java b/app/src/main/java/info/nightscout/androidaps/MainApp.java index 2b169cc7de..efb822c253 100644 --- a/app/src/main/java/info/nightscout/androidaps/MainApp.java +++ b/app/src/main/java/info/nightscout/androidaps/MainApp.java @@ -31,6 +31,7 @@ import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConstraintsObjectives.ObjectivesPlugin; import info.nightscout.androidaps.plugins.ConstraintsSafety.SafetyPlugin; +import info.nightscout.androidaps.plugins.Food.FoodPlugin; import info.nightscout.androidaps.plugins.Insulin.InsulinFastactingPlugin; import info.nightscout.androidaps.plugins.Insulin.InsulinFastactingProlongedPlugin; import info.nightscout.androidaps.plugins.Insulin.InsulinOrefFreePeakPlugin; @@ -151,6 +152,7 @@ public class MainApp extends Application { if (!Config.NSCLIENT) pluginsList.add(SourceGlimpPlugin.getPlugin()); if (Config.SMSCOMMUNICATORENABLED) pluginsList.add(SmsCommunicatorPlugin.getPlugin()); + pluginsList.add(FoodPlugin.getPlugin()); pluginsList.add(WearFragment.getPlugin(this)); pluginsList.add(StatuslinePlugin.getPlugin(this)); @@ -188,6 +190,9 @@ public class MainApp extends Application { lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_TREATMENT)); lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_CHANGED_TREATMENT)); lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_REMOVED_TREATMENT)); + lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_FOOD)); + lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_CHANGED_FOOD)); + lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_REMOVED_FOOD)); lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_SGV)); lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_PROFILE)); lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_STATUS)); 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 dc52107c26..5c152e8060 100644 --- a/app/src/main/java/info/nightscout/androidaps/Services/DataService.java +++ b/app/src/main/java/info/nightscout/androidaps/Services/DataService.java @@ -116,6 +116,9 @@ public class DataService extends IntentService { Intents.ACTION_REMOVED_TREATMENT.equals(action) || Intents.ACTION_NEW_STATUS.equals(action) || Intents.ACTION_NEW_DEVICESTATUS.equals(action) || + Intents.ACTION_NEW_FOOD.equals(action) || + Intents.ACTION_CHANGED_FOOD.equals(action) || + Intents.ACTION_REMOVED_FOOD.equals(action) || Intents.ACTION_NEW_CAL.equals(action) || Intents.ACTION_NEW_MBG.equals(action)) ) { @@ -413,6 +416,56 @@ public class DataService extends IntentService { log.error("Unhandled exception", e); } } + + if (intent.getAction().equals(Intents.ACTION_NEW_FOOD) || intent.getAction().equals(Intents.ACTION_CHANGED_FOOD)) { + try { + if (bundles.containsKey("food")) { + String trstring = bundles.getString("food"); + handleAddChangeFoodRecord(new JSONObject(trstring)); + } + if (bundles.containsKey("foods")) { + String trstring = bundles.getString("foods"); + JSONArray jsonArray = new JSONArray(trstring); + for (int i = 0; i < jsonArray.length(); i++) { + JSONObject trJson = jsonArray.getJSONObject(i); + handleAddChangeFoodRecord(trJson); + } + } + } catch (Exception e) { + log.error("Unhandled exception", e); + } + } + + if (intent.getAction().equals(Intents.ACTION_REMOVED_FOOD)) { + try { + if (bundles.containsKey("food")) { + String trstring = bundles.getString("food"); + JSONObject trJson = new JSONObject(trstring); + String _id = trJson.getString("_id"); + handleRemovedFoodRecord(_id); + } + + if (bundles.containsKey("foods")) { + String trstring = bundles.getString("foods"); + JSONArray jsonArray = new JSONArray(trstring); + for (int i = 0; i < jsonArray.length(); i++) { + JSONObject trJson = jsonArray.getJSONObject(i); + String _id = trJson.getString("_id"); + handleRemovedFoodRecord(_id); + } + } + } catch (Exception e) { + log.error("Unhandled exception", e); + } + } + } + + private void handleRemovedFoodRecord(String _id) { + MainApp.getDbHelper().foodHelper.deleteFoodById(_id); + } + + public void handleAddChangeFoodRecord(JSONObject trJson) throws JSONException { + MainApp.getDbHelper().foodHelper.createFoodFromJsonIfNotExists(trJson); } private void handleRemovedRecordFromNS(String _id) { diff --git a/app/src/main/java/info/nightscout/androidaps/data/DetailedBolusInfo.java b/app/src/main/java/info/nightscout/androidaps/data/DetailedBolusInfo.java index 2d928a5541..7720b03d3e 100644 --- a/app/src/main/java/info/nightscout/androidaps/data/DetailedBolusInfo.java +++ b/app/src/main/java/info/nightscout/androidaps/data/DetailedBolusInfo.java @@ -29,4 +29,14 @@ public class DetailedBolusInfo { public Context context = null; // context for progress dialog public long pumpId = 0; // id of record if comming from pump history (not a newly created treatment) public boolean isSMB = false; // is a Super-MicroBolus + + @Override + public String toString() { + return new Date(date).toLocaleString() + + " insulin: " + insulin + + " carbs: " + carbs + + " isValid: " + isValid + + " carbTime: " + carbTime + + " isSMB: " + isSMB; + } } diff --git a/app/src/main/java/info/nightscout/androidaps/db/FoodHelper.java b/app/src/main/java/info/nightscout/androidaps/db/FoodHelper.java index fd5406f974..992e328532 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/FoodHelper.java +++ b/app/src/main/java/info/nightscout/androidaps/db/FoodHelper.java @@ -87,6 +87,8 @@ public class FoodHelper { log.debug("FOOD: Updating record by _id: " + old.toString()); scheduleFoodChange(); return true; + } else { + return false; } } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/DetailedBolusInfoStorage.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/DetailedBolusInfoStorage.java index d6352cdb18..abe3c75c73 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/DetailedBolusInfoStorage.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/DetailedBolusInfoStorage.java @@ -20,7 +20,7 @@ public class DetailedBolusInfoStorage { private static List store = new ArrayList<>(); public static void add(DetailedBolusInfo detailedBolusInfo) { - log.debug("Bolus info stored: " + new Date(detailedBolusInfo.date).toLocaleString()); + log.debug("Stored bolus info: " + detailedBolusInfo); store.add(detailedBolusInfo); } @@ -29,7 +29,7 @@ public class DetailedBolusInfoStorage { DetailedBolusInfo found = null; for (int i = 0; i < store.size(); i++) { long infoTime = store.get(i).date; - log.debug("Existing info: " + new Date(infoTime).toLocaleString()); + log.debug("Existing bolus info: " + store.get(i)); if (bolustime > infoTime - 60 * 1000 && bolustime < infoTime + 60 * 1000) { found = store.get(i); break; @@ -42,7 +42,7 @@ public class DetailedBolusInfoStorage { for (int i = 0; i < store.size(); i++) { long infoTime = store.get(i).date; if (bolustime > infoTime - 60 * 1000 && bolustime < infoTime + 60 * 1000) { - log.debug("Removing info: " + new Date(infoTime).toLocaleString()); + log.debug("Removing bolus info: " + store.get(i)); store.remove(i); break; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Food/FoodFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Food/FoodFragment.java new file mode 100644 index 0000000000..558cf0d02f --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Food/FoodFragment.java @@ -0,0 +1,315 @@ +package info.nightscout.androidaps.plugins.Food; + +import android.app.Activity; +import android.content.DialogInterface; +import android.graphics.Paint; +import android.os.Bundle; +import android.support.v7.app.AlertDialog; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.TextView; + +import com.crashlytics.android.Crashlytics; +import com.squareup.otto.Subscribe; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.db.Food; +import info.nightscout.androidaps.events.EventFoodDatabaseChanged; +import info.nightscout.androidaps.plugins.Common.SubscriberFragment; +import info.nightscout.utils.NSUpload; +import info.nightscout.utils.SpinnerHelper; + +/** + * Created by mike on 16.10.2017. + */ + +public class FoodFragment extends SubscriberFragment { + private static Logger log = LoggerFactory.getLogger(FoodFragment.class); + + EditText filter; + ImageView clearFilter; + SpinnerHelper category; + SpinnerHelper subcategory; + RecyclerView recyclerView; + + List unfiltered; + List filtered; + ArrayList categories; + ArrayList subcategories; + + final String EMPTY = MainApp.sResources.getString(R.string.none); + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + try { + View view = inflater.inflate(R.layout.food_fragment, container, false); + + filter = (EditText) view.findViewById(R.id.food_filter); + clearFilter = (ImageView) view.findViewById(R.id.food_clearfilter); + category = new SpinnerHelper(view.findViewById(R.id.food_category)); + subcategory = new SpinnerHelper(view.findViewById(R.id.food_subcategory)); + recyclerView = (RecyclerView) view.findViewById(R.id.food_recyclerview); + recyclerView.setHasFixedSize(true); + LinearLayoutManager llm = new LinearLayoutManager(view.getContext()); + recyclerView.setLayoutManager(llm); + + clearFilter.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + filter.setText(""); + category.setSelection(0); + subcategory.setSelection(0); + filterData(); + } + }); + + category.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView parent, View view, int position, long id) { + fillSubcategories(); + filterData(); + } + + @Override + public void onNothingSelected(AdapterView parent) { + fillSubcategories(); + filterData(); + } + }); + + subcategory.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView parent, View view, int position, long id) { + filterData(); + } + + @Override + public void onNothingSelected(AdapterView parent) { + filterData(); + } + }); + + filter.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + filterData(); + } + + @Override + public void afterTextChanged(Editable s) { + } + }); + + RecyclerViewAdapter adapter = new RecyclerViewAdapter(MainApp.getDbHelper().foodHelper.getFoodData()); + recyclerView.setAdapter(adapter); + + loadData(); + fillCategories(); + fillSubcategories(); + filterData(); + return view; + } catch (Exception e) { + Crashlytics.logException(e); + } + + return null; + } + + @Subscribe + @SuppressWarnings("unused") + public void onStatusEvent(final EventFoodDatabaseChanged ev) { + loadData(); + filterData(); + } + + void loadData() { + unfiltered = MainApp.getDbHelper().foodHelper.getFoodData(); + } + + void fillCategories() { + categories = new ArrayList<>(); + + for (Food f : unfiltered) { + if (f.category != null && !f.category.equals("")) + categories.add(f.category); + } + + // make it unique + categories = new ArrayList<>(new HashSet<>(categories)); + + categories.add(0, MainApp.sResources.getString(R.string.none)); + + ArrayAdapter adapterCategories = new ArrayAdapter<>(getContext(), + R.layout.spinner_centered, categories); + category.setAdapter(adapterCategories); + } + + void fillSubcategories() { + String categoryFilter = category.getSelectedItem().toString(); + subcategories = new ArrayList<>(); + + if (!categoryFilter.equals(EMPTY)) { + for (Food f : unfiltered) { + if (f.category != null && f.category.equals(categoryFilter)) + if (f.subcategory != null && !f.subcategory.equals("")) + subcategories.add(f.subcategory); + } + } + + // make it unique + subcategories = new ArrayList<>(new HashSet<>(subcategories)); + + subcategories.add(0, MainApp.sResources.getString(R.string.none)); + + ArrayAdapter adapterSubcategories = new ArrayAdapter<>(getContext(), + R.layout.spinner_centered, subcategories); + subcategory.setAdapter(adapterSubcategories); + } + + void filterData() { + String textFilter = filter.getText().toString(); + String categoryFilter = category.getSelectedItem().toString(); + String subcategoryFilter = subcategory.getSelectedItem().toString(); + + filtered = new ArrayList<>(); + + for (Food f : unfiltered) { + if (f.name == null || f.category == null || f.subcategory == null) + continue; + + if (!subcategoryFilter.equals(EMPTY) && !f.subcategory.equals(subcategoryFilter)) + continue; + if (!categoryFilter.equals(EMPTY) && !f.category.equals(categoryFilter)) + continue; + if (!textFilter.equals("") && !f.name.toLowerCase().contains(textFilter.toLowerCase())) + continue; + filtered.add(f); + } + + updateGUI(); + } + + @Override + protected void updateGUI() { + Activity activity = getActivity(); + if (activity != null) + activity.runOnUiThread(new Runnable() { + @Override + public void run() { + recyclerView.swapAdapter(new FoodFragment.RecyclerViewAdapter(filtered), true); + } + }); + } + + public class RecyclerViewAdapter extends RecyclerView.Adapter { + + List foodList; + + RecyclerViewAdapter(List foodList) { + this.foodList = foodList; + } + + @Override + public FoodsViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { + View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.food_item, viewGroup, false); + return new FoodsViewHolder(v); + } + + @Override + public void onBindViewHolder(FoodsViewHolder holder, int position) { + Food food = foodList.get(position); + holder.ns.setVisibility(food._id != null ? View.VISIBLE : View.GONE); + holder.name.setText(food.name); + holder.portion.setText(food.portion + food.units); + holder.carbs.setText(food.carbs + MainApp.sResources.getString(R.string.shortgramm)); + holder.fat.setText(MainApp.sResources.getString(R.string.shortfat) + ": " + food.fat + MainApp.sResources.getString(R.string.shortgramm)); + if (food.fat == 0) + holder.fat.setVisibility(View.INVISIBLE); + holder.protein.setText(MainApp.sResources.getString(R.string.shortprotein) + ": " + food.protein + MainApp.sResources.getString(R.string.shortgramm)); + if (food.protein == 0) + holder.protein.setVisibility(View.INVISIBLE); + holder.energy.setText(MainApp.sResources.getString(R.string.shortenergy) + ": " + food.energy + MainApp.sResources.getString(R.string.shortkilojoul)); + if (food.energy == 0) + holder.energy.setVisibility(View.INVISIBLE); + holder.remove.setTag(food); + } + + @Override + public int getItemCount() { + return foodList.size(); + } + + class FoodsViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { + TextView name; + TextView portion; + TextView carbs; + TextView fat; + TextView protein; + TextView energy; + TextView ns; + TextView remove; + + FoodsViewHolder(View itemView) { + super(itemView); + name = (TextView) itemView.findViewById(R.id.food_name); + portion = (TextView) itemView.findViewById(R.id.food_portion); + carbs = (TextView) itemView.findViewById(R.id.food_carbs); + fat = (TextView) itemView.findViewById(R.id.food_fat); + protein = (TextView) itemView.findViewById(R.id.food_protein); + energy = (TextView) itemView.findViewById(R.id.food_energy); + ns = (TextView) itemView.findViewById(R.id.ns_sign); + remove = (TextView) itemView.findViewById(R.id.food_remove); + remove.setOnClickListener(this); + remove.setPaintFlags(remove.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG); + } + + @Override + public void onClick(View v) { + final Food food = (Food) v.getTag(); + switch (v.getId()) { + + case R.id.food_remove: + AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); + builder.setTitle(MainApp.sResources.getString(R.string.confirmation)); + builder.setMessage(MainApp.sResources.getString(R.string.removerecord) + "\n" + food.name); + builder.setPositiveButton(MainApp.sResources.getString(R.string.ok), new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + final String _id = food._id; + if (_id != null && !_id.equals("")) { + NSUpload.removeFoodFromNS(_id); + } + MainApp.getDbHelper().foodHelper.delete(food); + } + }); + builder.setNegativeButton(MainApp.sResources.getString(R.string.cancel), null); + builder.show(); + break; + + } + } + } + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Food/FoodPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Food/FoodPlugin.java new file mode 100644 index 0000000000..dbd1549c11 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Food/FoodPlugin.java @@ -0,0 +1,80 @@ +package info.nightscout.androidaps.plugins.Food; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.interfaces.PluginBase; + +/** + * Created by mike on 05.08.2016. + */ +public class FoodPlugin implements PluginBase { + private boolean fragmentEnabled = true; + private boolean fragmentVisible = false; + + private static FoodPlugin plugin = null; + + public static FoodPlugin getPlugin() { + if (plugin == null) + plugin = new FoodPlugin(); + return plugin; + } + + @Override + public String getFragmentClass() { + return FoodFragment.class.getName(); + } + + @Override + public int getType() { + return PluginBase.GENERAL; + } + + @Override + public String getName() { + return MainApp.instance().getString(R.string.food); + } + + @Override + public String getNameShort() { + // use long name as fallback (not visible in tabs) + return getName(); + } + + + @Override + public boolean isEnabled(int type) { + return type == GENERAL && fragmentEnabled; + } + + @Override + public boolean isVisibleInTabs(int type) { + return type == GENERAL && fragmentVisible; + } + + @Override + public boolean canBeHidden(int type) { + return true; + } + + @Override + public boolean hasFragment() { + return true; + } + + @Override + public boolean showInList(int type) { + return true; + } + + @Override + public void setFragmentEnabled(int type, boolean fragmentEnabled) { + if (type == GENERAL) this.fragmentEnabled = fragmentEnabled; + } + + @Override + public void setFragmentVisible(int type, boolean fragmentVisible) { + if (type == GENERAL) this.fragmentVisible = fragmentVisible; + } + + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobCalculatorPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobCalculatorPlugin.java index 7be4f3b929..927126941b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobCalculatorPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobCalculatorPlugin.java @@ -367,6 +367,9 @@ public class IobCobCalculatorPlugin implements PluginBase { continue; } + if (profile.getIsf(bgTime) == null) + return; // profile not set yet + double sens = Profile.toMgdl(profile.getIsf(bgTime), profile.getUnits()); AutosensData autosensData = new AutosensData(); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastTreatment.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastTreatment.java index 9dd63a83fe..c6158be296 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastTreatment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastTreatment.java @@ -183,7 +183,7 @@ public class BroadcastTreatment { ret.add(newarr); } newarr = new JSONArray(); - count = 50; + count = 20; } newarr.put(array.get(i)); --count; 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 5f4cd211a8..bed4aadba9 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 @@ -37,9 +37,7 @@ import com.crashlytics.android.Crashlytics; import com.crashlytics.android.answers.Answers; import com.crashlytics.android.answers.CustomEvent; import com.jjoe64.graphview.GraphView; -import com.jjoe64.graphview.LabelFormatter; import com.jjoe64.graphview.ValueDependentColor; -import com.jjoe64.graphview.Viewport; import com.jjoe64.graphview.series.BarGraphSeries; import com.jjoe64.graphview.series.DataPoint; import com.jjoe64.graphview.series.LineGraphSeries; @@ -55,7 +53,6 @@ import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; -import java.util.Iterator; import java.util.List; import java.util.Objects; import java.util.concurrent.Executors; @@ -77,11 +74,9 @@ import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.db.CareportalEvent; import info.nightscout.androidaps.db.DatabaseHelper; import info.nightscout.androidaps.db.ExtendedBolus; -import info.nightscout.androidaps.db.ProfileSwitch; import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.TempTarget; import info.nightscout.androidaps.db.TemporaryBasal; -import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.events.EventCareportalEventChange; import info.nightscout.androidaps.events.EventExtendedBolusChange; import info.nightscout.androidaps.events.EventInitializationChanged; @@ -100,23 +95,20 @@ import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConstraintsObjectives.ObjectivesPlugin; import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData; import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin; -import info.nightscout.androidaps.plugins.IobCobCalculator.events.BasalData; import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventAutosensCalculationFinished; import info.nightscout.androidaps.plugins.Loop.LoopPlugin; import info.nightscout.androidaps.plugins.Loop.events.EventNewOpenLoopNotification; import info.nightscout.androidaps.plugins.NSClientInternal.broadcasts.BroadcastAckAlarm; import info.nightscout.androidaps.plugins.NSClientInternal.data.NSDeviceStatus; +import info.nightscout.androidaps.plugins.OpenAPSAMA.DetermineBasalResultAMA; import info.nightscout.androidaps.plugins.Overview.Dialogs.CalibrationDialog; import info.nightscout.androidaps.plugins.Overview.Dialogs.NewTreatmentDialog; import info.nightscout.androidaps.plugins.Overview.Dialogs.WizardDialog; import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.Overview.events.EventSetWakeLock; -import info.nightscout.androidaps.plugins.Overview.graphExtensions.AreaGraphSeries; -import info.nightscout.androidaps.plugins.Overview.graphExtensions.DataPointWithLabelInterface; -import info.nightscout.androidaps.plugins.Overview.graphExtensions.DoubleDataPoint; +import info.nightscout.androidaps.plugins.Overview.graphData.GraphData; import info.nightscout.androidaps.plugins.Overview.graphExtensions.FixedLineGraphSeries; -import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLabelGraphSeries; import info.nightscout.androidaps.plugins.Overview.graphExtensions.TimeAsXAxisLabelFormatter; import info.nightscout.androidaps.plugins.SourceXdrip.SourceXdripPlugin; import info.nightscout.androidaps.plugins.Treatments.fragments.ProfileViewerDialog; @@ -126,7 +118,6 @@ import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.NSUpload; import info.nightscout.utils.OKDialog; import info.nightscout.utils.Profiler; -import info.nightscout.utils.Round; import info.nightscout.utils.SP; import info.nightscout.utils.ToastUtils; @@ -937,8 +928,8 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, return; } - Double lowLine = SP.getDouble("low_mark", 0d); - Double highLine = SP.getDouble("high_mark", 0d); + double lowLine = SP.getDouble("low_mark", 0d); + double highLine = SP.getDouble("high_mark", 0d); //Start with updating the BG as it is unaffected by loop. // **** BG value **** @@ -1249,7 +1240,6 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, } // ****** GRAPH ******* - //log.debug("updateGUI checkpoint 1"); // allign to hours Calendar calendar = Calendar.getInstance(); @@ -1278,466 +1268,83 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, endTime = toTime; } - LineGraphSeries basalsLineSeries = null; - LineGraphSeries absoluteBasalsLineSeries = null; - LineGraphSeries baseBasalsSeries = null; - LineGraphSeries tempBasalsSeries = null; - AreaGraphSeries areaSeries; - LineGraphSeries seriesNow, seriesNow2; - - // **** TEMP BASALS graph **** - Double maxBasalValueFound = 0d; long now = System.currentTimeMillis(); - if (pump.getPumpDescription().isTempBasalCapable && showBasalsView.isChecked()) { - List baseBasalArray = new ArrayList<>(); - List tempBasalArray = new ArrayList<>(); - List basalLineArray = new ArrayList<>(); - List absoluteBasalLineArray = new ArrayList<>(); - double lastLineBasal = 0; - double lastAbsoluteLineBasal = 0; - double lastBaseBasal = 0; - double lastTempBasal = 0; - for (long time = fromTime; time < now; time += 60 * 1000L) { - BasalData basalData = IobCobCalculatorPlugin.getBasalData(time); - double baseBasalValue = basalData.basal; - double absoluteLineValue = baseBasalValue; - double tempBasalValue = 0; - double basal = 0d; - if (basalData.isTempBasalRunning) { - absoluteLineValue = tempBasalValue = basalData.tempBasalAbsolute; - if (tempBasalValue != lastTempBasal) { - tempBasalArray.add(new DataPoint(time, lastTempBasal)); - tempBasalArray.add(new DataPoint(time, basal = tempBasalValue)); - } - if (lastBaseBasal != 0d) { - baseBasalArray.add(new DataPoint(time, lastBaseBasal)); - baseBasalArray.add(new DataPoint(time, 0d)); - lastBaseBasal = 0d; - } - } else { - if (baseBasalValue != lastBaseBasal) { - baseBasalArray.add(new DataPoint(time, lastBaseBasal)); - baseBasalArray.add(new DataPoint(time, basal = baseBasalValue)); - lastBaseBasal = baseBasalValue; - } - if (lastTempBasal != 0) { - tempBasalArray.add(new DataPoint(time, lastTempBasal)); - tempBasalArray.add(new DataPoint(time, 0d)); - } - } - if (baseBasalValue != lastLineBasal) { - basalLineArray.add(new DataPoint(time, lastLineBasal)); - basalLineArray.add(new DataPoint(time, baseBasalValue)); - } - if (absoluteLineValue != lastAbsoluteLineBasal) { - absoluteBasalLineArray.add(new DataPoint(time, lastAbsoluteLineBasal)); - absoluteBasalLineArray.add(new DataPoint(time, basal)); - } + // 2nd graph + // remove old data + iobGraph.getSeries().clear(); - lastAbsoluteLineBasal = absoluteLineValue; - lastLineBasal = baseBasalValue; - lastTempBasal = tempBasalValue; - maxBasalValueFound = Math.max(maxBasalValueFound, basal); - } - basalLineArray.add(new DataPoint(now, lastLineBasal)); - baseBasalArray.add(new DataPoint(now, lastBaseBasal)); - tempBasalArray.add(new DataPoint(now, lastTempBasal)); - absoluteBasalLineArray.add(new DataPoint(now, lastAbsoluteLineBasal)); + GraphData secondGraphData = new GraphData(); - DataPoint[] baseBasal = new DataPoint[baseBasalArray.size()]; - baseBasal = baseBasalArray.toArray(baseBasal); - baseBasalsSeries = new LineGraphSeries<>(baseBasal); - baseBasalsSeries.setDrawBackground(true); - baseBasalsSeries.setBackgroundColor(MainApp.sResources.getColor(R.color.basebasal)); - baseBasalsSeries.setThickness(0); + boolean useIobForScale = false; + boolean useCobForScale = false; + boolean useDevForScale = false; + boolean useRatioForScale = false; - DataPoint[] tempBasal = new DataPoint[tempBasalArray.size()]; - tempBasal = tempBasalArray.toArray(tempBasal); - tempBasalsSeries = new LineGraphSeries<>(tempBasal); - tempBasalsSeries.setDrawBackground(true); - tempBasalsSeries.setBackgroundColor(MainApp.sResources.getColor(R.color.tempbasal)); - tempBasalsSeries.setThickness(0); - - DataPoint[] basalLine = new DataPoint[basalLineArray.size()]; - basalLine = basalLineArray.toArray(basalLine); - basalsLineSeries = new LineGraphSeries<>(basalLine); - Paint paint = new Paint(); - paint.setStyle(Paint.Style.STROKE); - paint.setStrokeWidth(2); - paint.setPathEffect(new DashPathEffect(new float[]{2, 4}, 0)); - paint.setColor(MainApp.sResources.getColor(R.color.basal)); - basalsLineSeries.setCustomPaint(paint); - - DataPoint[] absoluteBasalLine = new DataPoint[absoluteBasalLineArray.size()]; - absoluteBasalLine = absoluteBasalLineArray.toArray(absoluteBasalLine); - absoluteBasalsLineSeries = new LineGraphSeries<>(absoluteBasalLine); - Paint absolutePaint = new Paint(); - absolutePaint.setStyle(Paint.Style.STROKE); - absolutePaint.setStrokeWidth(4); - absolutePaint.setColor(MainApp.sResources.getColor(R.color.basal)); - absoluteBasalsLineSeries.setCustomPaint(absolutePaint); + if (showIobView.isChecked()) { + useIobForScale = true; + } else if (showCobView.isChecked()) { + useCobForScale = true; + } else if (showDeviationsView.isChecked()) { + useDevForScale = true; + } else if (showRatiosView.isChecked()) { + useRatioForScale = true; } - //log.debug("updateGUI checkpoint 2"); - - // **** IOB COB DEV graph **** - class DeviationDataPoint extends DataPoint { - public int color; - - public DeviationDataPoint(double x, double y, int color) { - super(x, y); - this.color = color; - } - } - FixedLineGraphSeries iobSeries; - FixedLineGraphSeries cobSeries; - BarGraphSeries devSeries; - LineGraphSeries ratioSeries; - Double maxIobValueFound = 0d; - Double maxCobValueFound = 0d; - Double maxDevValueFound = 0d; - Double maxRatioValueFound = 0d; + if (showIobView.isChecked()) + secondGraphData.addIob(iobGraph, fromTime, now, useIobForScale, 1d); + if (showCobView.isChecked()) + secondGraphData.addCob(iobGraph, fromTime, now, useCobForScale, useCobForScale ? 1d : 0.5d); + if (showDeviationsView.isChecked()) + secondGraphData.addDeviations(iobGraph, fromTime, now, useDevForScale, 1d); + if (showRatiosView.isChecked()) + secondGraphData.addRatio(iobGraph, fromTime, now, useRatioForScale, 1d); if (showIobView.isChecked() || showCobView.isChecked() || showDeviationsView.isChecked() || showRatiosView.isChecked()) { - //Date start = new Date(); - List iobArray = new ArrayList<>(); - List cobArray = new ArrayList<>(); - List devArray = new ArrayList<>(); - List ratioArray = new ArrayList<>(); - double lastIob = 0; - int lastCob = 0; - for (long time = fromTime; time <= now; time += 5 * 60 * 1000L) { - if (showIobView.isChecked()) { - double iob = IobCobCalculatorPlugin.calculateFromTreatmentsAndTempsSynchronized(time).iob; - if (Math.abs(lastIob - iob) > 0.02) { - if (Math.abs(lastIob - iob) > 0.2) - iobArray.add(new DataPoint(time, lastIob)); - iobArray.add(new DataPoint(time, iob)); - maxIobValueFound = Math.max(maxIobValueFound, Math.abs(iob)); - lastIob = iob; - } - } - if (showCobView.isChecked() || showDeviationsView.isChecked() || showRatiosView.isChecked()) { - AutosensData autosensData = IobCobCalculatorPlugin.getAutosensData(time); - if (autosensData != null && showCobView.isChecked()) { - int cob = (int) autosensData.cob; - if (cob != lastCob) { - if (autosensData.carbsFromBolus > 0) - cobArray.add(new DataPoint(time, lastCob)); - cobArray.add(new DataPoint(time, cob)); - maxCobValueFound = Math.max(maxCobValueFound, cob); - lastCob = cob; - } - } - if (autosensData != null && showDeviationsView.isChecked()) { - int color = Color.BLACK; // "=" - if (autosensData.pastSensitivity.equals("C")) color = Color.GRAY; - if (autosensData.pastSensitivity.equals("+")) color = Color.GREEN; - if (autosensData.pastSensitivity.equals("-")) color = Color.RED; - devArray.add(new DeviationDataPoint(time, autosensData.deviation, color)); - maxDevValueFound = Math.max(maxDevValueFound, Math.abs(autosensData.deviation)); - } - if (autosensData != null && showRatiosView.isChecked()) { - ratioArray.add(new DataPoint(time, autosensData.autosensRatio)); - maxRatioValueFound = Math.max(maxRatioValueFound, Math.abs(autosensData.autosensRatio)); - } - } - } - //Profiler.log(log, "IOB processed", start); - DataPoint[] iobData = new DataPoint[iobArray.size()]; - iobData = iobArray.toArray(iobData); - iobSeries = new FixedLineGraphSeries<>(iobData); - iobSeries.setDrawBackground(true); - iobSeries.setBackgroundColor(0x80FFFFFF & MainApp.sResources.getColor(R.color.iob)); //50% - iobSeries.setColor(MainApp.sResources.getColor(R.color.iob)); - iobSeries.setThickness(3); - - - Double maxByScale = null; - int graphsToShow = 0; - if (showIobView.isChecked()) { - if (maxByScale == null) maxByScale = maxIobValueFound; - graphsToShow++; - } - if (showCobView.isChecked()) { - if (maxByScale == null) maxByScale = maxCobValueFound; - graphsToShow++; - } - if (showDeviationsView.isChecked()) { - if (maxByScale == null) maxByScale = maxDevValueFound; - graphsToShow++; - } - if (showRatiosView.isChecked()) { - if (maxByScale == null) maxByScale = maxRatioValueFound; - graphsToShow++; - } - - if (graphsToShow > 1) { - if (!maxByScale.equals(maxCobValueFound)) { - List cobArrayRescaled = new ArrayList<>(); - for (int ci = 0; ci < cobArray.size(); ci++) { - cobArrayRescaled.add(new DataPoint(cobArray.get(ci).getX(), cobArray.get(ci).getY() * maxByScale / maxCobValueFound / 2)); - } - cobArray = cobArrayRescaled; - } - if (!maxByScale.equals(maxDevValueFound)) { - List devArrayRescaled = new ArrayList<>(); - for (int ci = 0; ci < devArray.size(); ci++) { - devArrayRescaled.add(new DeviationDataPoint(devArray.get(ci).getX(), devArray.get(ci).getY() * maxByScale / maxDevValueFound, devArray.get(ci).color)); - } - devArray = devArrayRescaled; - } - if (!maxByScale.equals(maxRatioValueFound)) { - List ratioArrayRescaled = new ArrayList<>(); - for (int ci = 0; ci < ratioArray.size(); ci++) { - ratioArrayRescaled.add(new DataPoint(ratioArray.get(ci).getX(), (ratioArray.get(ci).getY() - 1) * maxByScale / maxRatioValueFound)); - } - ratioArray = ratioArrayRescaled; - } - } - - // COB - DataPoint[] cobData = new DataPoint[cobArray.size()]; - cobData = cobArray.toArray(cobData); - cobSeries = new FixedLineGraphSeries<>(cobData); - cobSeries.setDrawBackground(true); - cobSeries.setBackgroundColor(0xB0FFFFFF & MainApp.sResources.getColor(R.color.cob)); //50% - cobSeries.setColor(MainApp.sResources.getColor(R.color.cob)); - cobSeries.setThickness(3); - - // DEVIATIONS - DeviationDataPoint[] devData = new DeviationDataPoint[devArray.size()]; - devData = devArray.toArray(devData); - devSeries = new BarGraphSeries<>(devData); - devSeries.setValueDependentColor(new ValueDependentColor() { - @Override - public int get(DeviationDataPoint data) { - return data.color; - } - }); - - // RATIOS - DataPoint[] ratioData = new DataPoint[ratioArray.size()]; - ratioData = ratioArray.toArray(ratioData); - ratioSeries = new LineGraphSeries<>(ratioData); - ratioSeries.setColor(MainApp.sResources.getColor(R.color.ratio)); - ratioSeries.setThickness(3); - - iobGraph.getSeries().clear(); - - if (showIobView.isChecked() && iobData.length > 0) { - addSeriesWithoutInvalidate(iobSeries, iobGraph); - } - if (showCobView.isChecked() && cobData.length > 0) { - addSeriesWithoutInvalidate(cobSeries, iobGraph); - } - if (showDeviationsView.isChecked() && devData.length > 0) { - addSeriesWithoutInvalidate(devSeries, iobGraph); - } - if (showRatiosView.isChecked() && ratioData.length > 0) { - addSeriesWithoutInvalidate(ratioSeries, iobGraph); - } iobGraph.setVisibility(View.VISIBLE); } else { iobGraph.setVisibility(View.GONE); } - //log.debug("updateGUI checkpoint 3"); // remove old data from graph - bgGraph.getSecondScale().getSeries().clear(); bgGraph.getSeries().clear(); - //log.debug("updateGUI checkpoint 4"); - // **** Area **** - DoubleDataPoint[] areaDataPoints = new DoubleDataPoint[]{ - new DoubleDataPoint(fromTime, lowLine, highLine), - new DoubleDataPoint(endTime, lowLine, highLine) - }; - areaSeries = new AreaGraphSeries<>(areaDataPoints); - addSeriesWithoutInvalidate(areaSeries, bgGraph); - areaSeries.setColor(0); - areaSeries.setDrawBackground(true); - areaSeries.setBackgroundColor(MainApp.sResources.getColor(R.color.inrangebackground)); + GraphData graphData = new GraphData(); + + + // **** In range Area **** + graphData.addInRangeArea(bgGraph, fromTime, endTime, lowLine, highLine); + + // **** BG **** + if (showPrediction) + graphData.addBgReadings(bgGraph, fromTime, toTime, lowLine, highLine, (DetermineBasalResultAMA) finalLastRun.constraintsProcessed); + else + graphData.addBgReadings(bgGraph, fromTime, toTime, lowLine, highLine, null); // set manual x bounds to have nice steps - bgGraph.getViewport().setMaxX(endTime); - bgGraph.getViewport().setMinX(fromTime); - bgGraph.getViewport().setXAxisBoundsManual(true); - bgGraph.getGridLabelRenderer().setLabelFormatter(new TimeAsXAxisLabelFormatter(getActivity(), "HH")); - bgGraph.getGridLabelRenderer().setNumHorizontalLabels(7); // only 7 because of the space - iobGraph.getViewport().setMaxX(endTime); - iobGraph.getViewport().setMinX(fromTime); - iobGraph.getViewport().setXAxisBoundsManual(true); - iobGraph.getGridLabelRenderer().setLabelFormatter(new TimeAsXAxisLabelFormatter(getActivity(), "HH")); - iobGraph.getGridLabelRenderer().setNumHorizontalLabels(7); // only 7 because of the space + graphData.formatAxis(bgGraph, fromTime, endTime); + secondGraphData.formatAxis(iobGraph, fromTime, endTime); - //log.debug("updateGUI checkpoint 5"); - // **** BG graph **** - List bgReadingsArray = MainApp.getDbHelper().getBgreadingsDataFromTime(fromTime, true); - List bgListArray = new ArrayList<>(); - - if (bgReadingsArray.size() == 0) { - return; - } - - Iterator it = bgReadingsArray.iterator(); - Double maxBgValue = 0d; - while (it.hasNext()) { - BgReading bg = it.next(); - if (bg.value > maxBgValue) maxBgValue = bg.value; - bgListArray.add(bg); - } - if (showPrediction) { - List predArray = finalLastRun.constraintsProcessed.getPredictions(); - bgListArray.addAll(predArray); - } - - maxBgValue = Profile.fromMgdlToUnits(maxBgValue, units); - maxBgValue = units.equals(Constants.MGDL) ? Round.roundTo(maxBgValue, 40d) + 80 : Round.roundTo(maxBgValue, 2d) + 4; - if (highLine > maxBgValue) maxBgValue = highLine; - Integer numOfVertLines = units.equals(Constants.MGDL) ? (int) (maxBgValue / 40 + 1) : (int) (maxBgValue / 2 + 1); - - DataPointWithLabelInterface[] bg = new DataPointWithLabelInterface[bgListArray.size()]; - bg = bgListArray.toArray(bg); - - if (bg.length > 0) { - addSeriesWithoutInvalidate(new PointsWithLabelGraphSeries<>(bg), bgGraph); - } - - //log.debug("updateGUI checkpoint 6"); // Treatments - List filteredTreatments = new ArrayList<>(); + graphData.addTreatments(bgGraph, fromTime, endTime); - List treatments = MainApp.getConfigBuilder().getTreatmentsFromHistory(); - - for (int tx = 0; tx < treatments.size(); tx++) { - Treatment t = treatments.get(tx); - if (t.getX() < fromTime || t.getX() > endTime) continue; - if (t.isSMB) - t.setY(lowLine); - else - t.setY(getNearestBg((long) t.getX(), bgReadingsArray)); - filteredTreatments.add(t); - } - - //log.debug("updateGUI checkpoint 7"); - // ProfileSwitch - List profileSwitches = MainApp.getConfigBuilder().getProfileSwitchesFromHistory().getList(); - - for (int tx = 0; tx < profileSwitches.size(); tx++) { - DataPointWithLabelInterface t = profileSwitches.get(tx); - if (t.getX() < fromTime || t.getX() > endTime) continue; - filteredTreatments.add(t); - } - - //log.debug("updateGUI checkpoint 8"); - // Extended bolus - if (!pump.isFakingTempsByExtendedBoluses()) { - List extendedBoluses = MainApp.getConfigBuilder().getExtendedBolusesFromHistory().getList(); - - for (int tx = 0; tx < extendedBoluses.size(); tx++) { - DataPointWithLabelInterface t = extendedBoluses.get(tx); - if (t.getX() + t.getDuration() < fromTime || t.getX() > endTime) continue; - if (t.getDuration() == 0) continue; - t.setY(getNearestBg((long) t.getX(), bgReadingsArray)); - filteredTreatments.add(t); - } - } - - //log.debug("updateGUI checkpoint 9"); - // Careportal - List careportalEvents = MainApp.getDbHelper().getCareportalEventsFromTime(fromTime, true); - - for (int tx = 0; tx < careportalEvents.size(); tx++) { - DataPointWithLabelInterface t = careportalEvents.get(tx); - if (t.getX() + t.getDuration() < fromTime || t.getX() > endTime) continue; - t.setY(getNearestBg((long) t.getX(), bgReadingsArray)); - filteredTreatments.add(t); - } - - DataPointWithLabelInterface[] treatmentsArray = new DataPointWithLabelInterface[filteredTreatments.size()]; - treatmentsArray = filteredTreatments.toArray(treatmentsArray); - if (treatmentsArray.length > 0) { - addSeriesWithoutInvalidate(new PointsWithLabelGraphSeries<>(treatmentsArray), bgGraph); - } - //log.debug("updateGUI checkpoint 10"); - - // set manual y bounds to have nice steps - bgGraph.getViewport().setMaxY(maxBgValue); - bgGraph.getViewport().setMinY(0); - bgGraph.getViewport().setYAxisBoundsManual(true); - bgGraph.getGridLabelRenderer().setNumVerticalLabels(numOfVertLines); - - // set second scale + // add basal data if (pump.getPumpDescription().isTempBasalCapable && showBasalsView.isChecked()) { - bgGraph.getSecondScale().setMinY(0); - bgGraph.getSecondScale().setMaxY(maxBgValue / lowLine * maxBasalValueFound * 1.2d); - bgGraph.getSecondScale().addSeries(baseBasalsSeries); - bgGraph.getSecondScale().addSeries(tempBasalsSeries); - bgGraph.getSecondScale().addSeries(basalsLineSeries); - bgGraph.getSecondScale().addSeries(absoluteBasalsLineSeries); + graphData.addBasals(bgGraph, fromTime, now, lowLine / graphData.maxY / 1.2d); } - bgGraph.getSecondScale().setLabelFormatter(new LabelFormatter() { - @Override - public String formatLabel(double value, boolean isValueX) { - return ""; - } - @Override - public void setViewport(Viewport viewport) { - - } - }); - - //log.debug("updateGUI checkpoint 11"); // **** NOW line **** - DataPoint[] nowPoints = new DataPoint[]{ - new DataPoint(now, 0), - new DataPoint(now, maxBgValue) - }; - addSeriesWithoutInvalidate(seriesNow = new LineGraphSeries<>(nowPoints), bgGraph); - seriesNow.setDrawDataPoints(false); - DataPoint[] nowPoints2 = new DataPoint[]{ - new DataPoint(now, 0), - new DataPoint(now, maxIobValueFound) - }; - addSeriesWithoutInvalidate(seriesNow2 = new LineGraphSeries<>(nowPoints2), iobGraph); - seriesNow2.setDrawDataPoints(false); - //seriesNow.setThickness(1); - // custom paint to make a dotted line - Paint paint = new Paint(); - paint.setStyle(Paint.Style.STROKE); - paint.setStrokeWidth(2); - paint.setPathEffect(new DashPathEffect(new float[]{10, 20}, 0)); - paint.setColor(Color.WHITE); - seriesNow.setCustomPaint(paint); - seriesNow2.setCustomPaint(paint); + graphData.addNowLine(bgGraph, now); + secondGraphData.addNowLine(iobGraph, now); + + // finaly enforce drawing of graphs bgGraph.onDataChanged(false, false); iobGraph.onDataChanged(false, false); Profiler.log(log, from, updateGUIStart); } - public double getNearestBg(long date, List bgReadingsArray) { - double bg = 0; - String units = MainApp.getConfigBuilder().getProfileUnits(); - for (int r = bgReadingsArray.size() - 1; r >= 0; r--) { - BgReading reading = bgReadingsArray.get(r); - if (reading.date > date) continue; - bg = Profile.fromMgdlToUnits(reading.value, units); - break; - } - return bg; - } - - void addSeriesWithoutInvalidate(Series s, GraphView graph) { - s.onGraphViewAttached(graph); - graph.getSeries().add(s); - } - - //Notifications static class RecyclerViewAdapter extends RecyclerView.Adapter { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphData/GraphData.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphData/GraphData.java new file mode 100644 index 0000000000..f4be1fd351 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphData/GraphData.java @@ -0,0 +1,467 @@ +package info.nightscout.androidaps.plugins.Overview.graphData; + +import android.graphics.Color; +import android.graphics.DashPathEffect; +import android.graphics.Paint; + +import com.jjoe64.graphview.GraphView; +import com.jjoe64.graphview.ValueDependentColor; +import com.jjoe64.graphview.series.BarGraphSeries; +import com.jjoe64.graphview.series.DataPoint; +import com.jjoe64.graphview.series.LineGraphSeries; +import com.jjoe64.graphview.series.Series; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import info.nightscout.androidaps.Constants; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.db.BgReading; +import info.nightscout.androidaps.db.CareportalEvent; +import info.nightscout.androidaps.db.ExtendedBolus; +import info.nightscout.androidaps.db.ProfileSwitch; +import info.nightscout.androidaps.db.Treatment; +import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData; +import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin; +import info.nightscout.androidaps.plugins.IobCobCalculator.events.BasalData; +import info.nightscout.androidaps.plugins.OpenAPSAMA.DetermineBasalResultAMA; +import info.nightscout.androidaps.plugins.Overview.graphExtensions.AreaGraphSeries; +import info.nightscout.androidaps.plugins.Overview.graphExtensions.DataPointWithLabelInterface; +import info.nightscout.androidaps.plugins.Overview.graphExtensions.DoubleDataPoint; +import info.nightscout.androidaps.plugins.Overview.graphExtensions.FixedLineGraphSeries; +import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLabelGraphSeries; +import info.nightscout.androidaps.plugins.Overview.graphExtensions.Scale; +import info.nightscout.androidaps.plugins.Overview.graphExtensions.ScaledDataPoint; +import info.nightscout.androidaps.plugins.Overview.graphExtensions.TimeAsXAxisLabelFormatter; +import info.nightscout.utils.Round; + +/** + * Created by mike on 18.10.2017. + */ + +public class GraphData { + + public GraphData() { + units = MainApp.getConfigBuilder().getProfileUnits(); + } + + public double maxY = 0; + private List bgReadingsArray; + private String units; + + public void addBgReadings(GraphView bgGraph, long fromTime, long toTime, double lowLine, double highLine, DetermineBasalResultAMA amaResult) { + double maxBgValue = 0d; + bgReadingsArray = MainApp.getDbHelper().getBgreadingsDataFromTime(fromTime, true); + List bgListArray = new ArrayList<>(); + + if (bgReadingsArray.size() == 0) { + return; + } + + Iterator it = bgReadingsArray.iterator(); + while (it.hasNext()) { + BgReading bg = it.next(); + if (bg.value > maxBgValue) maxBgValue = bg.value; + bgListArray.add(bg); + } + if (amaResult != null) { + List predArray = amaResult.getPredictions(); + bgListArray.addAll(predArray); + } + + maxBgValue = Profile.fromMgdlToUnits(maxBgValue, units); + maxBgValue = units.equals(Constants.MGDL) ? Round.roundTo(maxBgValue, 40d) + 80 : Round.roundTo(maxBgValue, 2d) + 4; + if (highLine > maxBgValue) maxBgValue = highLine; + int numOfVertLines = units.equals(Constants.MGDL) ? (int) (maxBgValue / 40 + 1) : (int) (maxBgValue / 2 + 1); + + DataPointWithLabelInterface[] bg = new DataPointWithLabelInterface[bgListArray.size()]; + bg = bgListArray.toArray(bg); + + if (bg.length > 0) { + addSeriesWithoutInvalidate(bgGraph, new PointsWithLabelGraphSeries<>(bg)); + } + + maxY = maxBgValue; + // set manual y bounds to have nice steps + bgGraph.getViewport().setMaxY(maxY); + bgGraph.getViewport().setMinY(0); + bgGraph.getViewport().setYAxisBoundsManual(true); + bgGraph.getGridLabelRenderer().setNumVerticalLabels(numOfVertLines); + + } + + public void addInRangeArea(GraphView bgGraph, long fromTime, long toTime, double lowLine, double highLine) { + AreaGraphSeries inRangeAreaSeries; + + DoubleDataPoint[] inRangeAreaDataPoints = new DoubleDataPoint[]{ + new DoubleDataPoint(fromTime, lowLine, highLine), + new DoubleDataPoint(toTime, lowLine, highLine) + }; + inRangeAreaSeries = new AreaGraphSeries<>(inRangeAreaDataPoints); + addSeriesWithoutInvalidate(bgGraph, inRangeAreaSeries); + inRangeAreaSeries.setColor(0); + inRangeAreaSeries.setDrawBackground(true); + inRangeAreaSeries.setBackgroundColor(MainApp.sResources.getColor(R.color.inrangebackground)); + } + + // scale in % of vertical size (like 0.3) + public void addBasals(GraphView bgGraph, long fromTime, long toTime, double scale) { + LineGraphSeries basalsLineSeries; + LineGraphSeries absoluteBasalsLineSeries; + LineGraphSeries baseBasalsSeries; + LineGraphSeries tempBasalsSeries; + + double maxBasalValueFound = 0d; + Scale basalScale = new Scale(); + + List baseBasalArray = new ArrayList<>(); + List tempBasalArray = new ArrayList<>(); + List basalLineArray = new ArrayList<>(); + List absoluteBasalLineArray = new ArrayList<>(); + double lastLineBasal = 0; + double lastAbsoluteLineBasal = 0; + double lastBaseBasal = 0; + double lastTempBasal = 0; + for (long time = fromTime; time < toTime; time += 60 * 1000L) { + BasalData basalData = IobCobCalculatorPlugin.getBasalData(time); + double baseBasalValue = basalData.basal; + double absoluteLineValue = baseBasalValue; + double tempBasalValue = 0; + double basal = 0d; + if (basalData.isTempBasalRunning) { + absoluteLineValue = tempBasalValue = basalData.tempBasalAbsolute; + if (tempBasalValue != lastTempBasal) { + tempBasalArray.add(new ScaledDataPoint(time, lastTempBasal, basalScale)); + tempBasalArray.add(new ScaledDataPoint(time, basal = tempBasalValue, basalScale)); + } + if (lastBaseBasal != 0d) { + baseBasalArray.add(new ScaledDataPoint(time, lastBaseBasal, basalScale)); + baseBasalArray.add(new ScaledDataPoint(time, 0d, basalScale)); + lastBaseBasal = 0d; + } + } else { + if (baseBasalValue != lastBaseBasal) { + baseBasalArray.add(new ScaledDataPoint(time, lastBaseBasal, basalScale)); + baseBasalArray.add(new ScaledDataPoint(time, basal = baseBasalValue, basalScale)); + lastBaseBasal = baseBasalValue; + } + if (lastTempBasal != 0) { + tempBasalArray.add(new ScaledDataPoint(time, lastTempBasal, basalScale)); + tempBasalArray.add(new ScaledDataPoint(time, 0d, basalScale)); + } + } + + if (baseBasalValue != lastLineBasal) { + basalLineArray.add(new ScaledDataPoint(time, lastLineBasal, basalScale)); + basalLineArray.add(new ScaledDataPoint(time, baseBasalValue, basalScale)); + } + if (absoluteLineValue != lastAbsoluteLineBasal) { + absoluteBasalLineArray.add(new ScaledDataPoint(time, lastAbsoluteLineBasal, basalScale)); + absoluteBasalLineArray.add(new ScaledDataPoint(time, basal, basalScale)); + } + + lastAbsoluteLineBasal = absoluteLineValue; + lastLineBasal = baseBasalValue; + lastTempBasal = tempBasalValue; + maxBasalValueFound = Math.max(maxBasalValueFound, basal); + } + + basalLineArray.add(new ScaledDataPoint(toTime, lastLineBasal, basalScale)); + baseBasalArray.add(new ScaledDataPoint(toTime, lastBaseBasal, basalScale)); + tempBasalArray.add(new ScaledDataPoint(toTime, lastTempBasal, basalScale)); + absoluteBasalLineArray.add(new ScaledDataPoint(toTime, lastAbsoluteLineBasal, basalScale)); + + ScaledDataPoint[] baseBasal = new ScaledDataPoint[baseBasalArray.size()]; + baseBasal = baseBasalArray.toArray(baseBasal); + baseBasalsSeries = new LineGraphSeries<>(baseBasal); + baseBasalsSeries.setDrawBackground(true); + baseBasalsSeries.setBackgroundColor(MainApp.sResources.getColor(R.color.basebasal)); + baseBasalsSeries.setThickness(0); + + ScaledDataPoint[] tempBasal = new ScaledDataPoint[tempBasalArray.size()]; + tempBasal = tempBasalArray.toArray(tempBasal); + tempBasalsSeries = new LineGraphSeries<>(tempBasal); + tempBasalsSeries.setDrawBackground(true); + tempBasalsSeries.setBackgroundColor(MainApp.sResources.getColor(R.color.tempbasal)); + tempBasalsSeries.setThickness(0); + + ScaledDataPoint[] basalLine = new ScaledDataPoint[basalLineArray.size()]; + basalLine = basalLineArray.toArray(basalLine); + basalsLineSeries = new LineGraphSeries<>(basalLine); + Paint paint = new Paint(); + paint.setStyle(Paint.Style.STROKE); + paint.setStrokeWidth(2); + paint.setPathEffect(new DashPathEffect(new float[]{2, 4}, 0)); + paint.setColor(MainApp.sResources.getColor(R.color.basal)); + basalsLineSeries.setCustomPaint(paint); + + ScaledDataPoint[] absoluteBasalLine = new ScaledDataPoint[absoluteBasalLineArray.size()]; + absoluteBasalLine = absoluteBasalLineArray.toArray(absoluteBasalLine); + absoluteBasalsLineSeries = new LineGraphSeries<>(absoluteBasalLine); + Paint absolutePaint = new Paint(); + absolutePaint.setStyle(Paint.Style.STROKE); + absolutePaint.setStrokeWidth(4); + absolutePaint.setColor(MainApp.sResources.getColor(R.color.basal)); + absoluteBasalsLineSeries.setCustomPaint(absolutePaint); + + basalScale.setMultiplier(maxY * scale / maxBasalValueFound); + + addSeriesWithoutInvalidate(bgGraph, baseBasalsSeries); + addSeriesWithoutInvalidate(bgGraph, tempBasalsSeries); + addSeriesWithoutInvalidate(bgGraph, basalsLineSeries); + addSeriesWithoutInvalidate(bgGraph, absoluteBasalsLineSeries); + } + + public void addTreatments(GraphView bgGraph, long fromTime, long endTime) { + List filteredTreatments = new ArrayList<>(); + + List treatments = MainApp.getConfigBuilder().getTreatmentsFromHistory(); + + for (int tx = 0; tx < treatments.size(); tx++) { + Treatment t = treatments.get(tx); + if (t.getX() < fromTime || t.getX() > endTime) continue; + t.setY(getNearestBg((long) t.getX())); + filteredTreatments.add(t); + } + + // ProfileSwitch + List profileSwitches = MainApp.getConfigBuilder().getProfileSwitchesFromHistory().getList(); + + for (int tx = 0; tx < profileSwitches.size(); tx++) { + DataPointWithLabelInterface t = profileSwitches.get(tx); + if (t.getX() < fromTime || t.getX() > endTime) continue; + filteredTreatments.add(t); + } + + // Extended bolus + if (!MainApp.getConfigBuilder().isFakingTempsByExtendedBoluses()) { + List extendedBoluses = MainApp.getConfigBuilder().getExtendedBolusesFromHistory().getList(); + + for (int tx = 0; tx < extendedBoluses.size(); tx++) { + DataPointWithLabelInterface t = extendedBoluses.get(tx); + if (t.getX() + t.getDuration() < fromTime || t.getX() > endTime) continue; + if (t.getDuration() == 0) continue; + t.setY(getNearestBg((long) t.getX())); + filteredTreatments.add(t); + } + } + + // Careportal + List careportalEvents = MainApp.getDbHelper().getCareportalEventsFromTime(fromTime, true); + + for (int tx = 0; tx < careportalEvents.size(); tx++) { + DataPointWithLabelInterface t = careportalEvents.get(tx); + if (t.getX() + t.getDuration() < fromTime || t.getX() > endTime) continue; + t.setY(getNearestBg((long) t.getX())); + filteredTreatments.add(t); + } + + DataPointWithLabelInterface[] treatmentsArray = new DataPointWithLabelInterface[filteredTreatments.size()]; + treatmentsArray = filteredTreatments.toArray(treatmentsArray); + if (treatmentsArray.length > 0) { + addSeriesWithoutInvalidate(bgGraph, new PointsWithLabelGraphSeries<>(treatmentsArray)); + } + } + + double getNearestBg(long date) { + double bg = 0; + for (int r = bgReadingsArray.size() - 1; r >= 0; r--) { + BgReading reading = bgReadingsArray.get(r); + if (reading.date > date) continue; + bg = Profile.fromMgdlToUnits(reading.value, units); + break; + } + return bg; + } + + // scale in % of vertical size (like 0.3) + public void addIob(GraphView graph, long fromTime, long toTime, boolean useForScale, double scale) { + FixedLineGraphSeries iobSeries; + List iobArray = new ArrayList<>(); + Double maxIobValueFound = 0d; + double lastIob = 0; + Scale iobScale = new Scale(); + + for (long time = fromTime; time <= toTime; time += 5 * 60 * 1000L) { + double iob = IobCobCalculatorPlugin.calculateFromTreatmentsAndTempsSynchronized(time).iob; + if (Math.abs(lastIob - iob) > 0.02) { + if (Math.abs(lastIob - iob) > 0.2) + iobArray.add(new ScaledDataPoint(time, lastIob, iobScale)); + iobArray.add(new ScaledDataPoint(time, iob, iobScale)); + maxIobValueFound = Math.max(maxIobValueFound, Math.abs(iob)); + lastIob = iob; + } + } + + ScaledDataPoint[] iobData = new ScaledDataPoint[iobArray.size()]; + iobData = iobArray.toArray(iobData); + iobSeries = new FixedLineGraphSeries<>(iobData); + iobSeries.setDrawBackground(true); + iobSeries.setBackgroundColor(0x80FFFFFF & MainApp.sResources.getColor(R.color.iob)); //50% + iobSeries.setColor(MainApp.sResources.getColor(R.color.iob)); + iobSeries.setThickness(3); + + if (useForScale) + maxY = maxIobValueFound; + + iobScale.setMultiplier(maxY * scale / maxIobValueFound); + + addSeriesWithoutInvalidate(graph, iobSeries); + } + + // scale in % of vertical size (like 0.3) + public void addCob(GraphView graph, long fromTime, long toTime, boolean useForScale, double scale) { + FixedLineGraphSeries cobSeries; + List cobArray = new ArrayList<>(); + Double maxCobValueFound = 0d; + int lastCob = 0; + Scale cobScale = new Scale(); + + for (long time = fromTime; time <= toTime; time += 5 * 60 * 1000L) { + AutosensData autosensData = IobCobCalculatorPlugin.getAutosensData(time); + if (autosensData != null) { + int cob = (int) autosensData.cob; + if (cob != lastCob) { + if (autosensData.carbsFromBolus > 0) + cobArray.add(new ScaledDataPoint(time, lastCob, cobScale)); + cobArray.add(new ScaledDataPoint(time, cob, cobScale)); + maxCobValueFound = Math.max(maxCobValueFound, cob); + lastCob = cob; + } + } + } + + // COB + ScaledDataPoint[] cobData = new ScaledDataPoint[cobArray.size()]; + cobData = cobArray.toArray(cobData); + cobSeries = new FixedLineGraphSeries<>(cobData); + cobSeries.setDrawBackground(true); + cobSeries.setBackgroundColor(0xB0FFFFFF & MainApp.sResources.getColor(R.color.cob)); //50% + cobSeries.setColor(MainApp.sResources.getColor(R.color.cob)); + cobSeries.setThickness(3); + + if (useForScale) + maxY = maxCobValueFound; + + cobScale.setMultiplier(maxY * scale / maxCobValueFound); + + addSeriesWithoutInvalidate(graph, cobSeries); + } + + // scale in % of vertical size (like 0.3) + public void addDeviations(GraphView graph, long fromTime, long toTime, boolean useForScale, double scale) { + class DeviationDataPoint extends ScaledDataPoint { + public int color; + + public DeviationDataPoint(double x, double y, int color, Scale scale) { + super(x, y, scale); + this.color = color; + } + } + + BarGraphSeries devSeries; + List devArray = new ArrayList<>(); + Double maxDevValueFound = 0d; + Scale devScale = new Scale(); + + for (long time = fromTime; time <= toTime; time += 5 * 60 * 1000L) { + AutosensData autosensData = IobCobCalculatorPlugin.getAutosensData(time); + if (autosensData != null) { + int color = Color.BLACK; // "=" + if (autosensData.pastSensitivity.equals("C")) color = Color.GRAY; + if (autosensData.pastSensitivity.equals("+")) color = Color.GREEN; + if (autosensData.pastSensitivity.equals("-")) color = Color.RED; + devArray.add(new DeviationDataPoint(time, autosensData.deviation, color, devScale)); + maxDevValueFound = Math.max(maxDevValueFound, Math.abs(autosensData.deviation)); + } + } + + // DEVIATIONS + DeviationDataPoint[] devData = new DeviationDataPoint[devArray.size()]; + devData = devArray.toArray(devData); + devSeries = new BarGraphSeries<>(devData); + devSeries.setValueDependentColor(new ValueDependentColor() { + @Override + public int get(DeviationDataPoint data) { + return data.color; + } + }); + + if (useForScale) + maxY = maxDevValueFound; + + devScale.setMultiplier(maxY * scale / maxDevValueFound); + + addSeriesWithoutInvalidate(graph, devSeries); + } + + // scale in % of vertical size (like 0.3) + public void addRatio(GraphView graph, long fromTime, long toTime, boolean useForScale, double scale) { + LineGraphSeries ratioSeries; + List ratioArray = new ArrayList<>(); + Double maxRatioValueFound = 0d; + Scale ratioScale = new Scale(-1d); + + for (long time = fromTime; time <= toTime; time += 5 * 60 * 1000L) { + AutosensData autosensData = IobCobCalculatorPlugin.getAutosensData(time); + if (autosensData != null) { + ratioArray.add(new DataPoint(time, autosensData.autosensRatio)); + maxRatioValueFound = Math.max(maxRatioValueFound, Math.abs(autosensData.autosensRatio)); + } + } + + // RATIOS + DataPoint[] ratioData = new DataPoint[ratioArray.size()]; + ratioData = ratioArray.toArray(ratioData); + ratioSeries = new LineGraphSeries<>(ratioData); + ratioSeries.setColor(MainApp.sResources.getColor(R.color.ratio)); + ratioSeries.setThickness(3); + + if (useForScale) + maxY = maxRatioValueFound; + + ratioScale.setMultiplier(maxY * scale / maxRatioValueFound); + + addSeriesWithoutInvalidate(graph, ratioSeries); + } + + // scale in % of vertical size (like 0.3) + public void addNowLine(GraphView graph, long now) { + LineGraphSeries seriesNow; + DataPoint[] nowPoints = new DataPoint[]{ + new DataPoint(now, 0), + new DataPoint(now, maxY) + }; + + seriesNow = new LineGraphSeries<>(nowPoints); + seriesNow.setDrawDataPoints(false); + // custom paint to make a dotted line + Paint paint = new Paint(); + paint.setStyle(Paint.Style.STROKE); + paint.setStrokeWidth(2); + paint.setPathEffect(new DashPathEffect(new float[]{10, 20}, 0)); + paint.setColor(Color.WHITE); + seriesNow.setCustomPaint(paint); + + addSeriesWithoutInvalidate(graph, seriesNow); + } + + public void formatAxis(GraphView graph, long fromTime, long endTime) { + graph.getViewport().setMaxX(endTime); + graph.getViewport().setMinX(fromTime); + graph.getViewport().setXAxisBoundsManual(true); + graph.getGridLabelRenderer().setLabelFormatter(new TimeAsXAxisLabelFormatter("HH")); + graph.getGridLabelRenderer().setNumHorizontalLabels(7); // only 7 because of the space + } + + private void addSeriesWithoutInvalidate(GraphView bgGraph, Series s) { + if (!s.isEmpty()) { + s.onGraphViewAttached(bgGraph); + bgGraph.getSeries().add(s); + } + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/Scale.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/Scale.java new file mode 100644 index 0000000000..4aa1271679 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/Scale.java @@ -0,0 +1,30 @@ +package info.nightscout.androidaps.plugins.Overview.graphExtensions; + +/** + * Created by mike on 18.10.2017. + */ + +public class Scale { + private double multiplier; + private double shift; + + public Scale() { + shift = 0; + } + + public Scale(double shift) { + this.shift = shift; + } + + public void setMultiplier(double value) { + this.multiplier = value; + } + + public double transform(double original) { + return original * multiplier + shift; + } + + public double getShift() { + return shift; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/ScaledDataPoint.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/ScaledDataPoint.java new file mode 100644 index 0000000000..61f4102a30 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/ScaledDataPoint.java @@ -0,0 +1,46 @@ +package info.nightscout.androidaps.plugins.Overview.graphExtensions; + +import com.jjoe64.graphview.series.DataPointInterface; + +import java.io.Serializable; +import java.util.Date; + +/** + * Created by mike on 18.10.2017. + */ + +public class ScaledDataPoint implements DataPointInterface, Serializable { + private static final long serialVersionUID=1428263342645L; + + private double x; + private double y; + + private Scale scale; + + public ScaledDataPoint(double x, double y, Scale scale) { + this.x=x; + this.y=y; + this.scale = scale; + } + + public ScaledDataPoint(Date x, double y, Scale scale) { + this.x = x.getTime(); + this.y = y; + this.scale = scale; + } + + @Override + public double getX() { + return x; + } + + @Override + public double getY() { + return scale.transform(y); + } + + @Override + public String toString() { + return "["+x+"/"+y+"]"; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/TimeAsXAxisLabelFormatter.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/TimeAsXAxisLabelFormatter.java index 881e472a1d..323751e4c8 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/TimeAsXAxisLabelFormatter.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/TimeAsXAxisLabelFormatter.java @@ -15,7 +15,7 @@ public class TimeAsXAxisLabelFormatter extends DefaultLabelFormatter { protected final String mFormat; - public TimeAsXAxisLabelFormatter(Context context, String format) { + public TimeAsXAxisLabelFormatter(String format) { mFormat = format; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/SerialIOThread.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/SerialIOThread.java index af3b852aa6..b6a54f4ec1 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/SerialIOThread.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/SerialIOThread.java @@ -187,12 +187,12 @@ public class SerialIOThread extends Thread { scheduledDisconnection = null; } } - // prepare task for execution in 5 sec + // prepare task for execution in 10 sec // cancel waiting task to prevent sending multiple disconnections if (scheduledDisconnection != null) scheduledDisconnection.cancel(false); Runnable task = new DisconnectRunnable(); - final int sec = 5; + final int sec = 10; scheduledDisconnection = worker.schedule(task, sec, TimeUnit.SECONDS); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/DanaRExecutionService.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/DanaRExecutionService.java index 9d94634094..1ef5349f25 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/DanaRExecutionService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/DanaRExecutionService.java @@ -34,6 +34,7 @@ import info.nightscout.androidaps.events.EventPreferenceChange; import info.nightscout.androidaps.events.EventPumpStatusChanged; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; import info.nightscout.androidaps.plugins.PumpDanaR.SerialIOThread; @@ -410,12 +411,12 @@ public class DanaRExecutionService extends Service { public boolean bolus(double amount, int carbs, Treatment t) { bolusingTreatment = t; - int speed = SP.getInt(R.string.key_danars_bolusspeed, 0); + int preferencesSpeed = SP.getInt(R.string.key_danars_bolusspeed, 0); MessageBase start; - if (speed == 0) + if (preferencesSpeed == 0) start = new MsgBolusStart(amount); else - start = new MsgBolusStartWithSpeed(amount, speed); + start = new MsgBolusStartWithSpeed(amount, preferencesSpeed); MsgBolusStop stop = new MsgBolusStop(amount, t); connect("bolus"); @@ -426,7 +427,7 @@ public class DanaRExecutionService extends Service { } MsgBolusProgress progress = new MsgBolusProgress(amount, t); // initialize static variables - long startTime = System.currentTimeMillis(); + long bolusStart = System.currentTimeMillis(); if (!stop.stopped) { mSerialIOThread.sendMessage(start); @@ -436,23 +437,47 @@ public class DanaRExecutionService extends Service { } while (!stop.stopped && !start.failed) { waitMsec(100); - if ((System.currentTimeMillis() - progress.lastReceive) > 5 * 1000L) { // if i didn't receive status for more than 5 sec expecting broken comm + if ((System.currentTimeMillis() - progress.lastReceive) > 15 * 1000L) { // if i didn't receive status for more than 5 sec expecting broken comm stop.stopped = true; stop.forced = true; log.debug("Communication stopped"); } } waitMsec(300); + + EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance(); + bolusingEvent.t = t; + bolusingEvent.percent = 99; + bolusingTreatment = null; + + int speed = 12; + switch (preferencesSpeed) { + case 0: + speed = 12; + break; + case 1: + speed = 30; + break; + case 2: + speed = 60; + break; + } // try to find real amount if bolusing was interrupted or comm failed if (t.insulin != amount) { disconnect("bolusingInterrupted"); - long now = System.currentTimeMillis(); - long estimatedBolusEnd = (long) (startTime + amount / 5d * 60 * 1000); // std delivery rate 5 U/min - waitMsec(Math.max(5000, estimatedBolusEnd - now + 3000)); + long bolusDurationInMSec = (long) (amount * speed * 1000); + long expectedEnd = bolusStart + bolusDurationInMSec + 3000; + + while (System.currentTimeMillis() < expectedEnd) { + long waitTime = expectedEnd - System.currentTimeMillis(); + bolusingEvent.status = String.format(MainApp.sResources.getString(R.string.waitingforestimatedbolusend), waitTime / 1000); + MainApp.bus().post(bolusingEvent); + SystemClock.sleep(1000); + } connect("bolusingInterrupted"); getPumpStatus(); - if (danaRPump.lastBolusTime.getTime() > now - 60 * 1000L) { // last bolus max 1 min old + if (danaRPump.lastBolusTime.getTime() > System.currentTimeMillis() - 60 * 1000L) { // last bolus max 1 min old t.insulin = danaRPump.lastBolusAmount; log.debug("Used bolus amount from history: " + danaRPump.lastBolusAmount); } else { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/DanaRSPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/DanaRSPlugin.java index f26bdb6fad..468626fe26 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/DanaRSPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/DanaRSPlugin.java @@ -265,7 +265,9 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface, @Override public boolean loadHistory(byte type) { connectIfNotConnected("loadHistory"); - return danaRSService.loadHistory(type); + danaRSService.loadHistory(type); + disconnect("LoadHistory"); + return true; } // Constraints interface @@ -393,10 +395,12 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface, if (!danaRSService.updateBasalsInPump(profile)) { Notification notification = new Notification(Notification.FAILED_UDPATE_PROFILE, MainApp.sResources.getString(R.string.failedupdatebasalprofile), Notification.URGENT); MainApp.bus().post(new EventNewNotification(notification)); + disconnect("SetNewBasalProfile"); return FAILED; } else { MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED)); MainApp.bus().post(new EventDismissNotification(Notification.FAILED_UDPATE_PROFILE)); + disconnect("SetNewBasalProfile"); return SUCCESS; } } @@ -431,6 +435,7 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface, log.debug("Refreshing data from pump"); if (!isConnected() && !isConnecting()) { connect(reason); + disconnect("RefreshDataFromPump"); } else log.debug("Already connecting ..."); } @@ -445,7 +450,6 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface, ConfigBuilderPlugin configBuilderPlugin = MainApp.getConfigBuilder(); detailedBolusInfo.insulin = configBuilderPlugin.applyBolusConstraints(detailedBolusInfo.insulin); if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) { - DetailedBolusInfoStorage.add(detailedBolusInfo); // will be picked up on reading history int preferencesSpeed = SP.getInt(R.string.key_danars_bolusspeed, 0); int speed = 12; switch (preferencesSpeed) { @@ -460,8 +464,8 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface, break; } // v2 stores end time for bolus, we need to adjust time - // default delivery speed is 12 U/min - detailedBolusInfo.date += detailedBolusInfo.insulin / speed * 60d * 1000; + // default delivery speed is 12 sec/U + detailedBolusInfo.date += detailedBolusInfo.insulin * speed * 1000; // clean carbs to prevent counting them as twice because they will picked up as another record // I don't think it's necessary to copy DetailedBolusInfo right now for carbs records double carbs = detailedBolusInfo.carbs; @@ -469,6 +473,8 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface, int carbTime = detailedBolusInfo.carbTime; detailedBolusInfo.carbTime = 0; + DetailedBolusInfoStorage.add(detailedBolusInfo); // will be picked up on reading history + Treatment t = new Treatment(); boolean connectionOK = false; connectIfNotConnected("bolus"); @@ -481,7 +487,7 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface, result.comment = MainApp.instance().getString(R.string.virtualpump_resultok); if (Config.logPumpActions) log.debug("deliverTreatment: OK. Asked: " + detailedBolusInfo.insulin + " Delivered: " + result.bolusDelivered); - // remove carbs because it's get from history seprately + disconnect("DeliverTreatment"); return result; } else { PumpEnactResult result = new PumpEnactResult(); @@ -624,6 +630,7 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface, result.isPercent = true; if (Config.logPumpActions) log.debug("setTempBasalPercent: OK"); + disconnect("setTempBasalPercent"); return result; } result.enacted = false; @@ -647,6 +654,7 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface, result.isPercent = true; if (Config.logPumpActions) log.debug("setHighTempBasalPercent: OK"); + disconnect("setHighTempBasalPercent"); return result; } result.enacted = false; @@ -690,6 +698,7 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface, result.isPercent = false; if (Config.logPumpActions) log.debug("setExtendedBolus: OK"); + disconnect("setExtendedBolus"); return result; } result.enacted = false; @@ -708,6 +717,7 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface, danaRSService.tempBasalStop(); result.enacted = true; result.isTempCancel = true; + disconnect("cancelTempBasal"); } if (!pump.isTempBasalInProgress) { result.success = true; @@ -734,6 +744,7 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface, danaRSService.extendedBolusStop(); result.enacted = true; result.isTempCancel = true; + disconnect("extendedBolusStop"); } if (!pump.isExtendedInProgress) { result.success = true; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_APS_History_Events.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_APS_History_Events.java index fe010eb72f..8e58dc2cb5 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_APS_History_Events.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_APS_History_Events.java @@ -10,15 +10,14 @@ import java.util.Date; import java.util.GregorianCalendar; import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; import info.nightscout.androidaps.data.DetailedBolusInfo; -import info.nightscout.androidaps.db.DanaRHistoryRecord; import info.nightscout.androidaps.db.ExtendedBolus; import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.TemporaryBasal; +import info.nightscout.androidaps.events.EventPumpStatusChanged; import info.nightscout.androidaps.plugins.ConfigBuilder.DetailedBolusInfoStorage; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes; -import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRSyncStatus; import info.nightscout.utils.DateUtil; public class DanaRS_Packet_APS_History_Events extends DanaRS_Packet { @@ -32,11 +31,11 @@ public class DanaRS_Packet_APS_History_Events extends DanaRS_Packet { private int sec = 0; public boolean done; - public int totalCount; + private int totalCount; public static long lastEventTimeLoaded = 0; - public DanaRS_Packet_APS_History_Events() { + DanaRS_Packet_APS_History_Events() { super(); opCode = BleCommandUtil.DANAR_PACKET__OPCODE__APS_HISTORY_EVENTS; done = false; @@ -97,70 +96,87 @@ public class DanaRS_Packet_APS_History_Events extends DanaRS_Packet { DetailedBolusInfo detailedBolusInfo = DetailedBolusInfoStorage.findDetailedBolusInfo(datetime.getTime()); if (detailedBolusInfo == null) { - log.debug("DetailedBolusInfo not found for " + datetime.toLocaleString()); + log.debug("Detailed bolus info not found for " + datetime.toLocaleString()); detailedBolusInfo = new DetailedBolusInfo(); + } else { + log.debug("Detailed bolus info found: " + detailedBolusInfo); } detailedBolusInfo.date = datetime.getTime(); detailedBolusInfo.source = Source.PUMP; detailedBolusInfo.pumpId = datetime.getTime(); + String status; + switch (recordCode) { case DanaRPump.TEMPSTART: log.debug("EVENT TEMPSTART (" + recordCode + ") " + datetime.toLocaleString() + " Ratio: " + param1 + "% Duration: " + param2 + "min"); temporaryBasal.percentRate = param1; temporaryBasal.durationInMinutes = param2; MainApp.getConfigBuilder().addToHistoryTempBasal(temporaryBasal); + status = "TEMPSTART " + DateUtil.timeString(datetime); break; case DanaRPump.TEMPSTOP: log.debug("EVENT TEMPSTOP (" + recordCode + ") " + datetime.toLocaleString()); MainApp.getConfigBuilder().addToHistoryTempBasal(temporaryBasal); + status = "TEMPSTOP " + DateUtil.timeString(datetime); break; case DanaRPump.EXTENDEDSTART: log.debug("EVENT EXTENDEDSTART (" + recordCode + ") " + datetime.toLocaleString() + " Amount: " + (param1 / 100d) + "U Duration: " + param2 + "min"); extendedBolus.insulin = param1 / 100d; extendedBolus.durationInMinutes = param2; MainApp.getConfigBuilder().addToHistoryExtendedBolus(extendedBolus); + status = "EXTENDEDSTART " + DateUtil.timeString(datetime); break; case DanaRPump.EXTENDEDSTOP: log.debug("EVENT EXTENDEDSTOP (" + recordCode + ") " + datetime.toLocaleString() + " Delivered: " + (param1 / 100d) + "U RealDuration: " + param2 + "min"); MainApp.getConfigBuilder().addToHistoryExtendedBolus(extendedBolus); + status = "EXTENDEDSTOP " + DateUtil.timeString(datetime); break; case DanaRPump.BOLUS: detailedBolusInfo.insulin = param1 / 100d; boolean newRecord = MainApp.getConfigBuilder().addToHistoryTreatment(detailedBolusInfo); log.debug((newRecord ? "**NEW** " : "") + "EVENT BOLUS (" + recordCode + ") " + datetime.toLocaleString() + " Bolus: " + (param1 / 100d) + "U Duration: " + param2 + "min"); DetailedBolusInfoStorage.remove(detailedBolusInfo.date); + status = "BOLUS " + DateUtil.timeString(datetime); break; case DanaRPump.DUALBOLUS: detailedBolusInfo.insulin = param1 / 100d; newRecord = MainApp.getConfigBuilder().addToHistoryTreatment(detailedBolusInfo); log.debug((newRecord ? "**NEW** " : "") + "EVENT DUALBOLUS (" + recordCode + ") " + datetime.toLocaleString() + " Bolus: " + (param1 / 100d) + "U Duration: " + param2 + "min"); DetailedBolusInfoStorage.remove(detailedBolusInfo.date); + status = "DUALBOLUS " + DateUtil.timeString(datetime); break; case DanaRPump.DUALEXTENDEDSTART: log.debug("EVENT DUALEXTENDEDSTART (" + recordCode + ") " + datetime.toLocaleString() + " Amount: " + (param1 / 100d) + "U Duration: " + param2 + "min"); extendedBolus.insulin = param1 / 100d; extendedBolus.durationInMinutes = param2; MainApp.getConfigBuilder().addToHistoryExtendedBolus(extendedBolus); + status = "DUALEXTENDEDSTART " + DateUtil.timeString(datetime); break; case DanaRPump.DUALEXTENDEDSTOP: log.debug("EVENT DUALEXTENDEDSTOP (" + recordCode + ") " + datetime.toLocaleString() + " Delivered: " + (param1 / 100d) + "U RealDuration: " + param2 + "min"); MainApp.getConfigBuilder().addToHistoryExtendedBolus(extendedBolus); + status = "DUALEXTENDEDSTOP " + DateUtil.timeString(datetime); break; case DanaRPump.SUSPENDON: log.debug("EVENT SUSPENDON (" + recordCode + ") " + datetime.toLocaleString()); + status = "SUSPENDON " + DateUtil.timeString(datetime); break; case DanaRPump.SUSPENDOFF: log.debug("EVENT SUSPENDOFF (" + recordCode + ") " + datetime.toLocaleString()); + status = "SUSPENDOFF " + DateUtil.timeString(datetime); break; case DanaRPump.REFILL: log.debug("EVENT REFILL (" + recordCode + ") " + datetime.toLocaleString() + " Amount: " + param1 / 100d + "U"); + status = "REFILL " + DateUtil.timeString(datetime); break; case DanaRPump.PRIME: log.debug("EVENT PRIME (" + recordCode + ") " + datetime.toLocaleString() + " Amount: " + param1 / 100d + "U"); + status = "PRIME " + DateUtil.timeString(datetime); break; case DanaRPump.PROFILECHANGE: log.debug("EVENT PROFILECHANGE (" + recordCode + ") " + datetime.toLocaleString() + " No: " + param1 + " CurrentRate: " + (param2 / 100d) + "U/h"); + status = "PROFILECHANGE " + DateUtil.timeString(datetime); break; case DanaRPump.CARBS: DetailedBolusInfo emptyCarbsInfo = new DetailedBolusInfo(); @@ -170,17 +186,22 @@ public class DanaRS_Packet_APS_History_Events extends DanaRS_Packet { emptyCarbsInfo.pumpId = datetime.getTime(); newRecord = MainApp.getConfigBuilder().addToHistoryTreatment(emptyCarbsInfo); log.debug((newRecord ? "**NEW** " : "") + "EVENT CARBS (" + recordCode + ") " + datetime.toLocaleString() + " Carbs: " + param1 + "g"); + status = "CARBS " + DateUtil.timeString(datetime); break; case DanaRPump.PRIMECANNULA: - log.debug("EVENT PRIME CANNULA(" + recordCode + ") " + datetime.toLocaleString() + " Amount: " + param1 / 100d + "U"); + log.debug("EVENT PRIMECANNULA(" + recordCode + ") " + datetime.toLocaleString() + " Amount: " + param1 / 100d + "U"); + status = "PRIMECANNULA " + DateUtil.timeString(datetime); break; default: log.debug("Event: " + recordCode + " " + datetime.toLocaleString() + " Param1: " + param1 + " Param2: " + param2); + status = "UNKNOWN " + DateUtil.timeString(datetime); break; } if (datetime.getTime() > lastEventTimeLoaded) lastEventTimeLoaded = datetime.getTime(); + + MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.processinghistory) + ": " + status)); } @Override diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Basal_Rate.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Basal_Rate.java index 6f56464c51..a64da24bf3 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Basal_Rate.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Basal_Rate.java @@ -4,13 +4,13 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; + import com.cozmo.danar.util.BleCommandUtil; public class DanaRS_Packet_Basal_Set_Basal_Rate extends DanaRS_Packet { private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_Basal_Set_Basal_Rate.class); private double[] profileBasalRate; - public int error; public DanaRS_Packet_Basal_Set_Basal_Rate() { super(); @@ -38,11 +38,12 @@ public class DanaRS_Packet_Basal_Set_Basal_Rate extends DanaRS_Packet { @Override public void handleMessage(byte[] data) { - int dataIndex = DATA_START; - int dataSize = 1; - error = byteArrayToInt(getBytes(data, dataIndex, dataSize)); + int result = intFromBuff(data, 0, 1); if (Config.logDanaMessageDetail) { - log.debug("Result: " + error); + if (result == 0) + log.debug("Result OK"); + else + log.error("Result Error: " + result); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Cancel_Temporary_Basal.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Cancel_Temporary_Basal.java index 70a8b02826..538750a45b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Cancel_Temporary_Basal.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Cancel_Temporary_Basal.java @@ -10,8 +10,6 @@ import com.cozmo.danar.util.BleCommandUtil; public class DanaRS_Packet_Basal_Set_Cancel_Temporary_Basal extends DanaRS_Packet { private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_Basal_Set_Cancel_Temporary_Basal.class); - public int error; - public DanaRS_Packet_Basal_Set_Cancel_Temporary_Basal() { super(); opCode = BleCommandUtil.DANAR_PACKET__OPCODE_BASAL__CANCEL_TEMPORARY_BASAL; @@ -22,9 +20,12 @@ public class DanaRS_Packet_Basal_Set_Cancel_Temporary_Basal extends DanaRS_Packe @Override public void handleMessage(byte[] data) { - error = byteArrayToInt(getBytes(data, DATA_START, 1)); + int result = intFromBuff(data, 0, 1); if (Config.logDanaMessageDetail) { - log.debug("Result " + error); + if (result == 0) + log.debug("Result OK"); + else + log.error("Result Error: " + result); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Profile_Basal_Rate.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Profile_Basal_Rate.java index 82a63f0ca7..66d0e7b4bb 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Profile_Basal_Rate.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Profile_Basal_Rate.java @@ -11,7 +11,6 @@ public class DanaRS_Packet_Basal_Set_Profile_Basal_Rate extends DanaRS_Packet { private int profileNumber; // 0 - 4 private double[] profileBasalRate; - public int error; public DanaRS_Packet_Basal_Set_Profile_Basal_Rate() { super(); @@ -41,11 +40,12 @@ public class DanaRS_Packet_Basal_Set_Profile_Basal_Rate extends DanaRS_Packet { @Override public void handleMessage(byte[] data) { - int dataIndex = DATA_START; - int dataSize = 1; - error = byteArrayToInt(getBytes(data, dataIndex, dataSize)); + int result = intFromBuff(data, 0, 1); if (Config.logDanaMessageDetail) { - log.debug("Result: " + error); + if (result == 0) + log.debug("Result OK"); + else + log.error("Result Error: " + result); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Profile_Number.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Profile_Number.java index fe47f89dfc..69f7eae8dd 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Profile_Number.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Profile_Number.java @@ -10,7 +10,6 @@ import com.cozmo.danar.util.BleCommandUtil; public class DanaRS_Packet_Basal_Set_Profile_Number extends DanaRS_Packet { private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_Basal_Set_Profile_Number.class); private int profileNumber; - public int error; public DanaRS_Packet_Basal_Set_Profile_Number() { super(); @@ -33,11 +32,12 @@ public class DanaRS_Packet_Basal_Set_Profile_Number extends DanaRS_Packet { @Override public void handleMessage(byte[] data) { - int dataIndex = DATA_START; - int dataSize = 1; - error = byteArrayToInt(getBytes(data, dataIndex, dataSize)); + int result = intFromBuff(data, 0, 1); if (Config.logDanaMessageDetail) { - log.debug("Result: " + error); + if (result == 0) + log.debug("Result OK"); + else + log.error("Result Error: " + result); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Suspend_Off.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Suspend_Off.java index 1b9444c2d3..4c78038162 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Suspend_Off.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Suspend_Off.java @@ -8,7 +8,6 @@ import com.cozmo.danar.util.BleCommandUtil; public class DanaRS_Packet_Basal_Set_Suspend_Off extends DanaRS_Packet { private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_Basal_Set_Suspend_Off.class); - public int error; public DanaRS_Packet_Basal_Set_Suspend_Off() { super(); @@ -20,11 +19,12 @@ public class DanaRS_Packet_Basal_Set_Suspend_Off extends DanaRS_Packet { @Override public void handleMessage(byte[] data) { - int dataIndex = DATA_START; - int dataSize = 1; - error = byteArrayToInt(getBytes(data, dataIndex, dataSize)); + int result = intFromBuff(data, 0, 1); if (Config.logDanaMessageDetail) { - log.debug("Result: " + error); + if (result == 0) + log.debug("Result OK"); + else + log.error("Result Error: " + result); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Suspend_On.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Suspend_On.java index 01e90e026c..75a2a5fada 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Suspend_On.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Suspend_On.java @@ -8,7 +8,6 @@ import com.cozmo.danar.util.BleCommandUtil; public class DanaRS_Packet_Basal_Set_Suspend_On extends DanaRS_Packet { private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_Basal_Set_Suspend_On.class); - public int error; public DanaRS_Packet_Basal_Set_Suspend_On() { super(); @@ -20,11 +19,12 @@ public class DanaRS_Packet_Basal_Set_Suspend_On extends DanaRS_Packet { @Override public void handleMessage(byte[] data) { - int dataIndex = DATA_START; - int dataSize = 1; - error = byteArrayToInt(getBytes(data, dataIndex, dataSize)); + int result = intFromBuff(data, 0, 1); if (Config.logDanaMessageDetail) { - log.debug("Result: " + error); + if (result == 0) + log.debug("Result OK"); + else + log.error("Result Error: " + result); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Temporary_Basal.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Temporary_Basal.java index a81d85f016..d2f68ff864 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Temporary_Basal.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Temporary_Basal.java @@ -11,7 +11,6 @@ public class DanaRS_Packet_Basal_Set_Temporary_Basal extends DanaRS_Packet { private int temporaryBasalRatio; private int temporaryBasalDuration; - public int error; public DanaRS_Packet_Basal_Set_Temporary_Basal() { super(); @@ -37,11 +36,12 @@ public class DanaRS_Packet_Basal_Set_Temporary_Basal extends DanaRS_Packet { @Override public void handleMessage(byte[] data) { - int dataIndex = DATA_START; - int dataSize = 1; - error = byteArrayToInt(getBytes(data, dataIndex, dataSize)); + int result = intFromBuff(data, 0, 1); if (Config.logDanaMessageDetail) { - log.debug("Result: " + error); + if (result == 0) + log.debug("Result OK"); + else + log.error("Result Error: " + result); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Bolus_Option.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Bolus_Option.java index e20baeaee6..103bac3ecf 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Bolus_Option.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Bolus_Option.java @@ -111,12 +111,12 @@ public class DanaRS_Packet_Bolus_Set_Bolus_Option extends DanaRS_Packet { @Override public void handleMessage(byte[] data) { - int dataIndex = DATA_START; - int dataSize = 1; - int status = byteArrayToInt(getBytes(data, dataIndex, dataSize)); - + int result = intFromBuff(data, 0, 1); if (Config.logDanaMessageDetail) { - log.debug("Result: " + status); + if (result == 0) + log.debug("Result OK"); + else + log.error("Result Error: " + result); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_CIR_CF_Array.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_CIR_CF_Array.java index cf6a459d83..062ae00712 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_CIR_CF_Array.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_CIR_CF_Array.java @@ -83,12 +83,12 @@ public class DanaRS_Packet_Bolus_Set_CIR_CF_Array extends DanaRS_Packet { @Override public void handleMessage(byte[] data) { - int dataIndex = DATA_START; - int dataSize = 1; - int status = byteArrayToInt(getBytes(data, dataIndex, dataSize)); - + int result = intFromBuff(data, 0, 1); if (Config.logDanaMessageDetail) { - log.debug("Result: " + status); + if (result == 0) + log.debug("Result OK"); + else + log.error("Result Error: " + result); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Dual_Bolus.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Dual_Bolus.java index 31c80a702a..e769bea195 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Dual_Bolus.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Dual_Bolus.java @@ -44,12 +44,12 @@ public class DanaRS_Packet_Bolus_Set_Dual_Bolus extends DanaRS_Packet { @Override public void handleMessage(byte[] data) { - int dataIndex = DATA_START; - int dataSize = 1; - int status = byteArrayToInt(getBytes(data, dataIndex, dataSize)); - + int result = intFromBuff(data, 0, 1); if (Config.logDanaMessageDetail) { - log.debug("Result: " + status); + if (result == 0) + log.debug("Result OK"); + else + log.error("Result Error: " + result); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Extended_Bolus.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Extended_Bolus.java index d5f61c0946..887a9d852a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Extended_Bolus.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Extended_Bolus.java @@ -40,12 +40,12 @@ public class DanaRS_Packet_Bolus_Set_Extended_Bolus extends DanaRS_Packet { @Override public void handleMessage(byte[] data) { - int dataIndex = DATA_START; - int dataSize = 1; - int status = byteArrayToInt(getBytes(data, dataIndex, dataSize)); - + int result = intFromBuff(data, 0, 1); if (Config.logDanaMessageDetail) { - log.debug("Result: " + status); + if (result == 0) + log.debug("Result OK"); + else + log.error("Result Error: " + result); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Extended_Bolus_Cancel.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Extended_Bolus_Cancel.java index 10aa5f4979..132de649cf 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Extended_Bolus_Cancel.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Extended_Bolus_Cancel.java @@ -19,12 +19,12 @@ public class DanaRS_Packet_Bolus_Set_Extended_Bolus_Cancel extends DanaRS_Packet @Override public void handleMessage(byte[] data) { - int dataIndex = DATA_START; - int dataSize = 1; - int status = byteArrayToInt(getBytes(data, dataIndex, dataSize)); - + int result = intFromBuff(data, 0, 1); if (Config.logDanaMessageDetail) { - log.debug("Result: " + status); + if (result == 0) + log.debug("Result OK"); + else + log.error("Result Error: " + result); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Initial_Bolus.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Initial_Bolus.java index a475e7675d..a174d39b53 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Initial_Bolus.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Initial_Bolus.java @@ -44,12 +44,12 @@ public class DanaRS_Packet_Bolus_Set_Initial_Bolus extends DanaRS_Packet { @Override public void handleMessage(byte[] data) { - int dataIndex = DATA_START; - int dataSize = 1; - int status = byteArrayToInt(getBytes(data, dataIndex, dataSize)); - + int result = intFromBuff(data, 0, 1); if (Config.logDanaMessageDetail) { - log.debug("Result: " + status); + if (result == 0) + log.debug("Result OK"); + else + log.error("Result Error: " + result); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Step_Bolus_Start.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Step_Bolus_Start.java index 1263aeb629..4c5cc23ef3 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Step_Bolus_Start.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Step_Bolus_Start.java @@ -48,14 +48,12 @@ public class DanaRS_Packet_Bolus_Set_Step_Bolus_Start extends DanaRS_Packet { } @Override public void handleMessage(byte[] data) { - int dataIndex = DATA_START; - int dataSize = 1; - int status = byteArrayToInt(getBytes(data, dataIndex, dataSize)); - - failed = status != 0x00; - + int result = intFromBuff(data, 0, 1); if (Config.logDanaMessageDetail) { - log.debug("Result: " + status); + if (result == 0) + log.debug("Result OK"); + else + log.error("Result Error: " + result); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Step_Bolus_Stop.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Step_Bolus_Stop.java index 61ddd05c9b..5383fca413 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Step_Bolus_Stop.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Step_Bolus_Stop.java @@ -35,13 +35,14 @@ public class DanaRS_Packet_Bolus_Set_Step_Bolus_Stop extends DanaRS_Packet { @Override public void handleMessage(byte[] data) { - int dataIndex = DATA_START; - int dataSize = 1; - int status = byteArrayToInt(getBytes(data, dataIndex, dataSize)); - + int result = intFromBuff(data, 0, 1); if (Config.logDanaMessageDetail) { - log.debug("Result: " + status); + if (result == 0) + log.debug("Result OK"); + else + log.error("Result Error: " + result); } + EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance(); stopped = true; if (!forced) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Set_History_Upload_Mode.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Set_History_Upload_Mode.java index 7d9ec07ff1..878cfd64dd 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Set_History_Upload_Mode.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Set_History_Upload_Mode.java @@ -31,12 +31,12 @@ public class DanaRS_Packet_General_Set_History_Upload_Mode extends DanaRS_Packet @Override public void handleMessage(byte[] data) { - int dataIndex = DATA_START; - int dataSize = 1; - int status = byteArrayToInt(getBytes(data, dataIndex, dataSize)); - + int result = intFromBuff(data, 0, 1); if (Config.logDanaMessageDetail) { - log.debug("Result: " + status); + if (result == 0) + log.debug("Result OK"); + else + log.error("Result Error: " + result); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Set_User_Time_Change_Flag_Clear.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Set_User_Time_Change_Flag_Clear.java index 9cc6b7b2e0..3917f31050 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Set_User_Time_Change_Flag_Clear.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Set_User_Time_Change_Flag_Clear.java @@ -17,12 +17,12 @@ public class DanaRS_Packet_General_Set_User_Time_Change_Flag_Clear extends DanaR @Override public void handleMessage(byte[] data) { - int dataIndex = DATA_START; - int dataSize = 1; - int status = byteArrayToInt(getBytes(data, dataIndex, dataSize)); - + int result = intFromBuff(data, 0, 1); if (Config.logDanaMessageDetail) { - log.debug("Result: " + status); + if (result == 0) + log.debug("Result OK"); + else + log.error("Result Error: " + result); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Option_Set_Pump_Time.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Option_Set_Pump_Time.java index e93e18796d..007623afca 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Option_Set_Pump_Time.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Option_Set_Pump_Time.java @@ -45,7 +45,10 @@ public class DanaRS_Packet_Option_Set_Pump_Time extends DanaRS_Packet { int dataSize = 1; error = byteArrayToInt(getBytes(data, dataIndex, dataSize)); if (Config.logDanaMessageDetail) { - log.debug("Result: " + error); + if (error == 0) + log.debug("Result OK"); + else + log.error("Result Error: " + error); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Option_Set_User_Option.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Option_Set_User_Option.java index 49c6d35708..e5d9374f32 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Option_Set_User_Option.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Option_Set_User_Option.java @@ -47,7 +47,10 @@ public class DanaRS_Packet_Option_Set_User_Option extends DanaRS_Packet { int dataSize = 1; error = byteArrayToInt(getBytes(data, dataIndex, dataSize)); if (Config.logDanaMessageDetail) { - log.debug("Result: " + error); + if (error == 0) + log.debug("Result OK"); + else + log.error("Result Error: " + error); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/BLEComm.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/BLEComm.java index dde50a93e1..42f077887d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/BLEComm.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/BLEComm.java @@ -165,19 +165,6 @@ public class BLEComm { MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.CONNECTING)); isConnecting = true; - // Following should be removed later because we close Gatt on disconnect and this should never happen - if ((mBluetoothDeviceAddress != null) && (address.equals(mBluetoothDeviceAddress)) && (mBluetoothGatt != null)) { - log.debug("Trying to use an existing mBluetoothGatt for connection."); - sHandler.post(updateProgress); - if (mBluetoothGatt.connect()) { - setCharacteristicNotification(getUARTReadBTGattChar(), true); - return true; - } - sHandler.removeCallbacks(updateProgress); - return false; - } - // end - BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address); if (device == null) { log.debug("Device not found. Unable to connect."); @@ -201,12 +188,19 @@ public class BLEComm { public void disconnect(String from) { log.debug("disconnect from: " + from); + + // cancel previous scheduled disconnection to prevent closing upcomming connection + if (scheduledDisconnection != null) + scheduledDisconnection.cancel(false); + scheduledDisconnection = null; + if ((mBluetoothAdapter == null) || (mBluetoothGatt == null)) { return; } setCharacteristicNotification(getUARTReadBTGattChar(), false); mBluetoothGatt.disconnect(); isConnected = false; + SystemClock.sleep(2000); } public void close() { @@ -214,6 +208,7 @@ public class BLEComm { if (mBluetoothGatt == null) { return; } + mBluetoothGatt.close(); mBluetoothGatt = null; } @@ -687,18 +682,19 @@ public class BLEComm { } public void scheduleDisconnection() { + class DisconnectRunnable implements Runnable { public void run() { disconnect("scheduleDisconnection"); scheduledDisconnection = null; } } - // prepare task for execution in 5 sec + // prepare task for execution in 30 sec // cancel waiting task to prevent sending multiple disconnections if (scheduledDisconnection != null) scheduledDisconnection.cancel(false); Runnable task = new DisconnectRunnable(); - final int sec = 5; + final int sec = 30; scheduledDisconnection = worker.schedule(task, sec, TimeUnit.SECONDS); log.debug("Disconnection scheduled"); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/DanaRSService.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/DanaRSService.java index 6b39788342..e3baf10870 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/DanaRSService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/DanaRSService.java @@ -26,6 +26,7 @@ import info.nightscout.androidaps.events.EventInitializationChanged; import info.nightscout.androidaps.events.EventPumpStatusChanged; import info.nightscout.androidaps.plugins.Overview.Notification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes; import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRNewStatus; @@ -188,16 +189,16 @@ public class DanaRSService extends Service { while (!msg.done && bleComm.isConnected()) { SystemClock.sleep(100); } - SystemClock.sleep(200); lastHistoryFetched = DanaRS_Packet_APS_History_Events.lastEventTimeLoaded; return true; } - public boolean bolus(double insulin, int carbs, long carbtime, Treatment t) { + public boolean bolus(final double insulin, int carbs, long carbtime, Treatment t) { + MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.startingbolus))); bolusingTreatment = t; - int speed = SP.getInt(R.string.key_danars_bolusspeed, 0); - DanaRS_Packet_Bolus_Set_Step_Bolus_Start start = new DanaRS_Packet_Bolus_Set_Step_Bolus_Start(insulin, speed); + final int preferencesSpeed = SP.getInt(R.string.key_danars_bolusspeed, 0); + DanaRS_Packet_Bolus_Set_Step_Bolus_Start start = new DanaRS_Packet_Bolus_Set_Step_Bolus_Start(insulin, preferencesSpeed); DanaRS_Packet_Bolus_Set_Step_Bolus_Stop stop = new DanaRS_Packet_Bolus_Set_Step_Bolus_Stop(insulin, t); // initialize static variables DanaRS_Packet_Notify_Delivery_Complete complete = new DanaRS_Packet_Notify_Delivery_Complete(insulin, t); // initialize static variables @@ -210,28 +211,57 @@ public class DanaRSService extends Service { bleComm.sendMessage(msgSetHistoryEntry_v2); lastHistoryFetched = carbtime - 60000; } - if (insulin > 0) { - DanaRS_Packet_Notify_Delivery_Rate_Display progress = new DanaRS_Packet_Notify_Delivery_Rate_Display(insulin, t); // initialize static variables + final long bolusStart = System.currentTimeMillis(); + if (insulin > 0) { if (!stop.stopped) { bleComm.sendMessage(start); } else { t.insulin = 0d; return false; } + DanaRS_Packet_Notify_Delivery_Rate_Display progress = new DanaRS_Packet_Notify_Delivery_Rate_Display(insulin, t); // initialize static variables + while (!stop.stopped && !start.failed && !complete.done) { SystemClock.sleep(100); - if ((System.currentTimeMillis() - progress.lastReceive) > 5 * 1000L) { // if i didn't receive status for more than 5 sec expecting broken comm + if ((System.currentTimeMillis() - progress.lastReceive) > 15 * 1000L) { // if i didn't receive status for more than 20 sec expecting broken comm stop.stopped = true; stop.forced = true; log.debug("Communication stopped"); } } } - SystemClock.sleep(3000); + + EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance(); + bolusingEvent.t = t; + bolusingEvent.percent = 99; + bolusingTreatment = null; - DanaRSPlugin.connectIfNotConnected("ReadHistoryAfterBolus"); + int speed = 12; + switch (preferencesSpeed) { + case 0: + speed = 12; + break; + case 1: + speed = 30; + break; + case 2: + speed = 60; + break; + } + long bolusDurationInMSec = (long) (insulin * speed * 1000); + long expectedEnd = bolusStart + bolusDurationInMSec + 2000; + while (System.currentTimeMillis() < expectedEnd) { + long waitTime = expectedEnd - System.currentTimeMillis(); + bolusingEvent.status = String.format(MainApp.sResources.getString(R.string.waitingforestimatedbolusend), waitTime / 1000); + MainApp.bus().post(bolusingEvent); + SystemClock.sleep(1000); + } + if (!(isConnected())) + DanaRSPlugin.getPlugin().connect("loadEvents"); loadEvents(); + bolusingEvent.percent = 100; + MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.disconnecting))); return true; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/DanaRv2Plugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/DanaRv2Plugin.java index ea174e4608..4a224bd57b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/DanaRv2Plugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/DanaRv2Plugin.java @@ -293,9 +293,8 @@ public class DanaRv2Plugin implements PluginBase, PumpInterface, DanaRInterface, ConfigBuilderPlugin configBuilderPlugin = MainApp.getConfigBuilder(); detailedBolusInfo.insulin = configBuilderPlugin.applyBolusConstraints(detailedBolusInfo.insulin); if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) { - DetailedBolusInfoStorage.add(detailedBolusInfo); // will be picked up on reading history // v2 stores end time for bolus, we need to adjust time - // default delivery speed is 12 U/min + // default delivery speed is 12 sec/U int preferencesSpeed = SP.getInt(R.string.key_danars_bolusspeed, 0); int speed = 12; switch (preferencesSpeed) { @@ -309,7 +308,7 @@ public class DanaRv2Plugin implements PluginBase, PumpInterface, DanaRInterface, speed = 60; break; } - detailedBolusInfo.date += detailedBolusInfo.insulin / speed * 60d * 1000; + detailedBolusInfo.date += speed * detailedBolusInfo.insulin * 1000; // clean carbs to prevent counting them as twice because they will picked up as another record // I don't think it's necessary to copy DetailedBolusInfo right now for carbs records double carbs = detailedBolusInfo.carbs; @@ -317,6 +316,8 @@ public class DanaRv2Plugin implements PluginBase, PumpInterface, DanaRInterface, int carbTime = detailedBolusInfo.carbTime; detailedBolusInfo.carbTime = 0; + DetailedBolusInfoStorage.add(detailedBolusInfo); // will be picked up on reading history + Treatment t = new Treatment(); boolean connectionOK = false; if (detailedBolusInfo.insulin > 0 || carbs > 0) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/SerialIOThread.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/SerialIOThread.java index 244014f3d0..da9e44f925 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/SerialIOThread.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/SerialIOThread.java @@ -188,12 +188,12 @@ public class SerialIOThread extends Thread { scheduledDisconnection = null; } } - // prepare task for execution in 5 sec + // prepare task for execution in 10 sec // cancel waiting task to prevent sending multiple disconnections if (scheduledDisconnection != null) scheduledDisconnection.cancel(false); Runnable task = new DisconnectRunnable(); - final int sec = 5; + final int sec = 10; scheduledDisconnection = worker.schedule(task, sec, TimeUnit.SECONDS); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgHistoryEvents_v2.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgHistoryEvents_v2.java index f04218ac61..922047e5cb 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgHistoryEvents_v2.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgHistoryEvents_v2.java @@ -7,13 +7,16 @@ import java.util.Date; import java.util.GregorianCalendar; import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.db.ExtendedBolus; import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.TemporaryBasal; +import info.nightscout.androidaps.events.EventPumpStatusChanged; import info.nightscout.androidaps.plugins.ConfigBuilder.DetailedBolusInfoStorage; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; +import info.nightscout.utils.DateUtil; public class MsgHistoryEvents_v2 extends MessageBase { private static Logger log = LoggerFactory.getLogger(MsgHistoryEvents_v2.class); @@ -65,70 +68,87 @@ public class MsgHistoryEvents_v2 extends MessageBase { DetailedBolusInfo detailedBolusInfo = DetailedBolusInfoStorage.findDetailedBolusInfo(datetime.getTime()); if (detailedBolusInfo == null) { - log.debug("DetailedBolusInfo not found for " + datetime.toLocaleString()); + log.debug("Detailed bolus info not found for " + datetime.toLocaleString()); detailedBolusInfo = new DetailedBolusInfo(); + } else { + log.debug("Detailed bolus info found: " + detailedBolusInfo); } detailedBolusInfo.date = datetime.getTime(); detailedBolusInfo.source = Source.PUMP; detailedBolusInfo.pumpId = datetime.getTime(); + String status = ""; + switch (recordCode) { case DanaRPump.TEMPSTART: log.debug("EVENT TEMPSTART (" + recordCode + ") " + datetime.toLocaleString() + " Ratio: " + param1 + "% Duration: " + param2 + "min"); temporaryBasal.percentRate = param1; temporaryBasal.durationInMinutes = param2; MainApp.getConfigBuilder().addToHistoryTempBasal(temporaryBasal); + status = "TEMPSTART " + DateUtil.timeString(datetime); break; case DanaRPump.TEMPSTOP: log.debug("EVENT TEMPSTOP (" + recordCode + ") " + datetime.toLocaleString()); MainApp.getConfigBuilder().addToHistoryTempBasal(temporaryBasal); + status = "TEMPSTOP " + DateUtil.timeString(datetime); break; case DanaRPump.EXTENDEDSTART: log.debug("EVENT EXTENDEDSTART (" + recordCode + ") " + datetime.toLocaleString() + " Amount: " + (param1 / 100d) + "U Duration: " + param2 + "min"); extendedBolus.insulin = param1 / 100d; extendedBolus.durationInMinutes = param2; MainApp.getConfigBuilder().addToHistoryExtendedBolus(extendedBolus); + status = "EXTENDEDSTART " + DateUtil.timeString(datetime); break; case DanaRPump.EXTENDEDSTOP: log.debug("EVENT EXTENDEDSTOP (" + recordCode + ") " + datetime.toLocaleString() + " Delivered: " + (param1 / 100d) + "U RealDuration: " + param2 + "min"); MainApp.getConfigBuilder().addToHistoryExtendedBolus(extendedBolus); + status = "EXTENDEDSTOP " + DateUtil.timeString(datetime); break; case DanaRPump.BOLUS: detailedBolusInfo.insulin = param1 / 100d; boolean newRecord = MainApp.getConfigBuilder().addToHistoryTreatment(detailedBolusInfo); log.debug((newRecord ? "**NEW** " : "") + "EVENT BOLUS (" + recordCode + ") " + datetime.toLocaleString() + " Bolus: " + (param1 / 100d) + "U Duration: " + param2 + "min"); DetailedBolusInfoStorage.remove(detailedBolusInfo.date); + status = "BOLUS " + DateUtil.timeString(datetime); break; case DanaRPump.DUALBOLUS: detailedBolusInfo.insulin = param1 / 100d; newRecord = MainApp.getConfigBuilder().addToHistoryTreatment(detailedBolusInfo); log.debug((newRecord ? "**NEW** " : "") + "EVENT DUALBOLUS (" + recordCode + ") " + datetime.toLocaleString() + " Bolus: " + (param1 / 100d) + "U Duration: " + param2 + "min"); DetailedBolusInfoStorage.remove(detailedBolusInfo.date); + status = "DUALBOLUS " + DateUtil.timeString(datetime); break; case DanaRPump.DUALEXTENDEDSTART: log.debug("EVENT DUALEXTENDEDSTART (" + recordCode + ") " + datetime.toLocaleString() + " Amount: " + (param1 / 100d) + "U Duration: " + param2 + "min"); extendedBolus.insulin = param1 / 100d; extendedBolus.durationInMinutes = param2; MainApp.getConfigBuilder().addToHistoryExtendedBolus(extendedBolus); + status = "DUALEXTENDEDSTART " + DateUtil.timeString(datetime); break; case DanaRPump.DUALEXTENDEDSTOP: log.debug("EVENT DUALEXTENDEDSTOP (" + recordCode + ") " + datetime.toLocaleString() + " Delivered: " + (param1 / 100d) + "U RealDuration: " + param2 + "min"); MainApp.getConfigBuilder().addToHistoryExtendedBolus(extendedBolus); + status = "DUALEXTENDEDSTOP " + DateUtil.timeString(datetime); break; case DanaRPump.SUSPENDON: log.debug("EVENT SUSPENDON (" + recordCode + ") " + datetime.toLocaleString()); + status = "SUSPENDON " + DateUtil.timeString(datetime); break; case DanaRPump.SUSPENDOFF: log.debug("EVENT SUSPENDOFF (" + recordCode + ") " + datetime.toLocaleString()); + status = "SUSPENDOFF " + DateUtil.timeString(datetime); break; case DanaRPump.REFILL: log.debug("EVENT REFILL (" + recordCode + ") " + datetime.toLocaleString() + " Amount: " + param1 / 100d + "U"); + status = "REFILL " + DateUtil.timeString(datetime); break; case DanaRPump.PRIME: log.debug("EVENT PRIME (" + recordCode + ") " + datetime.toLocaleString() + " Amount: " + param1 / 100d + "U"); + status = "PRIME " + DateUtil.timeString(datetime); break; case DanaRPump.PROFILECHANGE: log.debug("EVENT PROFILECHANGE (" + recordCode + ") " + datetime.toLocaleString() + " No: " + param1 + " CurrentRate: " + (param2 / 100d) + "U/h"); + status = "PROFILECHANGE " + DateUtil.timeString(datetime); break; case DanaRPump.CARBS: DetailedBolusInfo emptyCarbsInfo = new DetailedBolusInfo(); @@ -138,14 +158,17 @@ public class MsgHistoryEvents_v2 extends MessageBase { emptyCarbsInfo.pumpId = datetime.getTime(); newRecord = MainApp.getConfigBuilder().addToHistoryTreatment(emptyCarbsInfo); log.debug((newRecord ? "**NEW** " : "") + "EVENT CARBS (" + recordCode + ") " + datetime.toLocaleString() + " Carbs: " + param1 + "g"); + status = "CARBS " + DateUtil.timeString(datetime); break; default: log.debug("Event: " + recordCode + " " + datetime.toLocaleString() + " Param1: " + param1 + " Param2: " + param2); + status = "UNKNOWN " + DateUtil.timeString(datetime); break; } if (datetime.getTime() > lastEventTimeLoaded) lastEventTimeLoaded = datetime.getTime(); + MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.processinghistory) + ": " + status)); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/services/DanaRv2ExecutionService.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/services/DanaRv2ExecutionService.java index fc3df19296..75f9893bc9 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/services/DanaRv2ExecutionService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/services/DanaRv2ExecutionService.java @@ -36,6 +36,7 @@ import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.plugins.Overview.Notification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; import info.nightscout.androidaps.plugins.PumpDanaR.comm.*; import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRNewStatus; @@ -400,14 +401,15 @@ public class DanaRv2ExecutionService extends Service { return true; } - public boolean bolus(double amount, int carbs, long carbtime, Treatment t) { + public boolean bolus(final double amount, int carbs, long carbtime, Treatment t) { + MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.startingbolus))); bolusingTreatment = t; - int speed = SP.getInt(R.string.key_danars_bolusspeed, 0); + final int preferencesSpeed = SP.getInt(R.string.key_danars_bolusspeed, 0); MessageBase start; - if (speed == 0) + if (preferencesSpeed == 0) start = new MsgBolusStart(amount); else - start = new MsgBolusStartWithSpeed(amount, speed); + start = new MsgBolusStartWithSpeed(amount, preferencesSpeed); MsgBolusStop stop = new MsgBolusStop(amount, t); connect("bolus"); @@ -420,6 +422,8 @@ public class DanaRv2ExecutionService extends Service { mSerialIOThread.sendMessage(msgSetHistoryEntry_v2); lastHistoryFetched = carbtime - 60000; } + + final long bolusStart = System.currentTimeMillis(); if (amount > 0) { MsgBolusProgress progress = new MsgBolusProgress(amount, t); // initialize static variables @@ -431,26 +435,46 @@ public class DanaRv2ExecutionService extends Service { } while (!stop.stopped && !start.failed) { waitMsec(100); - if ((System.currentTimeMillis() - progress.lastReceive) > 5 * 1000L) { // if i didn't receive status for more than 5 sec expecting broken comm + if ((System.currentTimeMillis() - progress.lastReceive) > 15 * 1000L) { // if i didn't receive status for more than 5 sec expecting broken comm stop.stopped = true; stop.forced = true; log.debug("Communication stopped"); } } } + + EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance(); + bolusingEvent.t = t; + bolusingEvent.percent = 99; + bolusingTreatment = null; - // run loading history in separate thread and allow bolus dialog to be closed - new Thread(new Runnable() { - @Override - public void run() { - waitMsec(4000); - if (!(isConnected())) - connect("loadEvents"); - loadEvents(); - } - }).start(); + int speed = 12; + switch (preferencesSpeed) { + case 0: + speed = 12; + break; + case 1: + speed = 30; + break; + case 2: + speed = 60; + break; + } + long bolusDurationInMSec = (long) (amount * speed * 1000); + long expectedEnd = bolusStart + bolusDurationInMSec + 2000; + while (System.currentTimeMillis() < expectedEnd) { + long waitTime = expectedEnd - System.currentTimeMillis(); + bolusingEvent.status = String.format(MainApp.sResources.getString(R.string.waitingforestimatedbolusend), waitTime / 1000); + MainApp.bus().post(bolusingEvent); + SystemClock.sleep(1000); + } + if (!(isConnected())) + connect("loadEvents"); + loadEvents(); + bolusingEvent.percent = 100; + MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.disconnecting))); return true; - } +} public void bolusStop() { if (Config.logDanaBTComm) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityWeightedAverage/SensitivityWeightedAveragePlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityWeightedAverage/SensitivityWeightedAveragePlugin.java index 258ea09b33..68537cf47c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityWeightedAverage/SensitivityWeightedAveragePlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityWeightedAverage/SensitivityWeightedAveragePlugin.java @@ -5,11 +5,9 @@ import android.support.v4.util.LongSparseArray; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.ArrayList; -import java.util.Arrays; import java.util.Date; -import java.util.List; +import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.data.Profile; @@ -32,7 +30,7 @@ public class SensitivityWeightedAveragePlugin implements PluginBase, Sensitivity private boolean fragmentEnabled = true; private boolean fragmentVisible = false; - static SensitivityWeightedAveragePlugin plugin = null; + private static SensitivityWeightedAveragePlugin plugin = null; public static SensitivityWeightedAveragePlugin getPlugin() { if (plugin == null) @@ -108,13 +106,15 @@ public class SensitivityWeightedAveragePlugin implements PluginBase, Sensitivity int hoursForDetection = SP.getInt(R.string.key_openapsama_autosens_period, defaultHours); if (autosensDataTable == null || autosensDataTable.size() < 4) { - log.debug("No autosens data available"); + if (Config.logAutosensData) + log.debug("No autosens data available"); return new AutosensResult(); } AutosensData current = IobCobCalculatorPlugin.getAutosensData(toTime); if (current == null) { - log.debug("No autosens data available"); + if (Config.logAutosensData) + log.debug("No autosens data available"); return new AutosensResult(); } @@ -181,9 +181,10 @@ public class SensitivityWeightedAveragePlugin implements PluginBase, Sensitivity double sens = profile.getIsf(); String ratioLimit = ""; - String sensResult = ""; + String sensResult; - log.debug("Records: " + index + " " + pastSensitivity); + if (Config.logAutosensData) + log.debug("Records: " + index + " " + pastSensitivity); double average = weightedsum / weights; double basalOff = average * (60 / 5) / Profile.toMgdl(sens, profile.getUnits()); @@ -197,7 +198,8 @@ public class SensitivityWeightedAveragePlugin implements PluginBase, Sensitivity sensResult = "Sensitivity normal"; } - log.debug(sensResult); + if (Config.logAutosensData) + log.debug(sensResult); double rawRatio = ratio; ratio = Math.max(ratio, SafeParse.stringToDouble(SP.getString("openapsama_autosens_min", "0.7"))); @@ -205,10 +207,12 @@ public class SensitivityWeightedAveragePlugin implements PluginBase, Sensitivity if (ratio != rawRatio) { ratioLimit = "Ratio limited from " + rawRatio + " to " + ratio; - log.debug(ratioLimit); + if (Config.logAutosensData) + log.debug(ratioLimit); } - log.debug("Sensitivity to: " + new Date(toTime).toLocaleString() + " weightedaverage: " + average + " ratio: " + ratio); + if (Config.logAutosensData) + log.debug("Sensitivity to: " + new Date(toTime).toLocaleString() + " weightedaverage: " + average + " ratio: " + ratio); AutosensResult output = new AutosensResult(); output.ratio = Round.roundTo(ratio, 0.01); diff --git a/app/src/main/java/info/nightscout/utils/NSUpload.java b/app/src/main/java/info/nightscout/utils/NSUpload.java index 08b59a3871..fbb723f3e3 100644 --- a/app/src/main/java/info/nightscout/utils/NSUpload.java +++ b/app/src/main/java/info/nightscout/utils/NSUpload.java @@ -395,4 +395,23 @@ public class NSUpload { DbLogger.dbAdd(intent, data.toString()); } } + + public static void removeFoodFromNS(String _id) { + try { + Context context = MainApp.instance().getApplicationContext(); + Bundle bundle = new Bundle(); + bundle.putString("action", "dbRemove"); + bundle.putString("collection", "food"); + bundle.putString("_id", _id); + Intent intent = new Intent(Intents.ACTION_DATABASE); + intent.putExtras(bundle); + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + context.sendBroadcast(intent); + DbLogger.dbRemove(intent, _id); + } catch (Exception e) { + log.error("Unhandled exception", e); + } + + } + } diff --git a/app/src/main/res/layout/food_fragment.xml b/app/src/main/res/layout/food_fragment.xml new file mode 100644 index 0000000000..7b42eff11f --- /dev/null +++ b/app/src/main/res/layout/food_fragment.xml @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/food_item.xml b/app/src/main/res/layout/food_item.xml new file mode 100644 index 0000000000..d4efc403a3 --- /dev/null +++ b/app/src/main/res/layout/food_item.xml @@ -0,0 +1,100 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/values-bg/strings.xml b/app/src/main/res/values-bg/strings.xml index ab3a2bb64f..03266a5b4a 100644 --- a/app/src/main/res/values-bg/strings.xml +++ b/app/src/main/res/values-bg/strings.xml @@ -650,7 +650,7 @@ време за физ. активност Целева КЗ при физ. активност Скорост на болус - % на изменение + % от профила Време на отместване Все още устройството не е намерено DanaRS @@ -668,7 +668,7 @@ Сдвоени Времето за сдвояване изтече Сдвояване с нова помпа - опитва отново + отново Избрана помпа Сериен номер ЛЕЧ diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index efa2d31c4d..c8bdc47ec9 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -49,9 +49,9 @@ - 12s 1U - 30s 1U - 60s 1U + 12 s/U + 30 s/U + 60 s/U 0 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 13e684b3f0..9e91f96e8a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -70,7 +70,7 @@ No pump available No change requested Request - Rate + Rate Duration Reason Glucose @@ -685,10 +685,10 @@ Pass the Overview Notifications through as wear confirmation messages. Enable broadcasts to other apps (like xDrip). Enable local Broadcasts. - ACTIVITY & FEEDBACK - CARBS & BOLUS - CGM & OPENAPS - PUMP + ACTIVITY & FEEDBACK + CARBS & BOLUS + CGM & OPENAPS + PUMP Basal value [U/h] Duration [min] OpenAPS SMB @@ -754,6 +754,16 @@ Controls from Watch Set Temp-Targets and enter Treatments from the watch. Connection timed out + Food + g + ]]> + kJ + En + Pr + Fat ]]> + Waiting for estimated bolus end. Remaining %d sec. + Processing event + Starting bolus delivery