diff --git a/app/src/main/java/info/nightscout/androidaps/MainActivity.java b/app/src/main/java/info/nightscout/androidaps/MainActivity.java index b702897ba4..e77be36ba6 100644 --- a/app/src/main/java/info/nightscout/androidaps/MainActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/MainActivity.java @@ -82,7 +82,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe Manifest.permission.WRITE_EXTERNAL_STORAGE}, CASE_STORAGE); } askForBatteryOptimizationPermission(); - checkUpgradeToProfileTarget(); + doMigrations(); if (Config.logFunctionCalls) log.debug("onCreate"); @@ -163,6 +163,19 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe } } + private void doMigrations() { + + checkUpgradeToProfileTarget(); + + // guarantee that the unreachable threshold is at least 30 and of type String + // Added in 1.57 at 21.01.2018 + Integer unreachable_threshold = SP.getInt(R.string.key_pump_unreachable_threshold, 30); + SP.remove(R.string.key_pump_unreachable_threshold); + if(unreachable_threshold < 30) unreachable_threshold = 30; + SP.putString(R.string.key_pump_unreachable_threshold, unreachable_threshold.toString()); + } + + private void checkUpgradeToProfileTarget() { // TODO: can be removed in the future boolean oldKeyExists = SP.contains("openapsma_min_bg"); if (oldKeyExists) { 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 e4d65eadc0..b242c4c099 100644 --- a/app/src/main/java/info/nightscout/androidaps/Services/DataService.java +++ b/app/src/main/java/info/nightscout/androidaps/Services/DataService.java @@ -15,20 +15,22 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.data.ProfileStore; import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.db.CareportalEvent; import info.nightscout.androidaps.events.EventNewBasalProfile; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConstraintsObjectives.ObjectivesPlugin; +import info.nightscout.androidaps.plugins.NSClientInternal.data.NSDeviceStatus; import info.nightscout.androidaps.plugins.NSClientInternal.data.NSMbg; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSgv; -import info.nightscout.androidaps.data.ProfileStore; import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSettingsStatus; -import info.nightscout.androidaps.plugins.Overview.notifications.Notification; +import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSgv; import info.nightscout.androidaps.plugins.Overview.OverviewPlugin; import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.Overview.notifications.Notification; import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin; +import info.nightscout.androidaps.plugins.ProfileNS.events.EventNSProfileUpdateGUI; import info.nightscout.androidaps.plugins.PumpDanaR.activities.DanaRNSHistorySync; import info.nightscout.androidaps.plugins.SmsCommunicator.events.EventNewSMS; import info.nightscout.androidaps.plugins.SourceDexcomG5.SourceDexcomG5Plugin; @@ -37,7 +39,6 @@ import info.nightscout.androidaps.plugins.SourceMM640g.SourceMM640gPlugin; import info.nightscout.androidaps.plugins.SourceNSClient.SourceNSClientPlugin; import info.nightscout.androidaps.plugins.SourceXdrip.SourceXdripPlugin; import info.nightscout.androidaps.receivers.DataReceiver; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSDeviceStatus; import info.nightscout.utils.BundleLogger; import info.nightscout.utils.NSUpload; import info.nightscout.utils.SP; @@ -365,8 +366,10 @@ public class DataService extends IntentService { String profile = bundles.getString("profile"); ProfileStore profileStore = new ProfileStore(new JSONObject(profile)); NSProfilePlugin.storeNewProfile(profileStore); - MainApp.bus().post(new EventNewBasalProfile()); - + MainApp.bus().post(new EventNSProfileUpdateGUI()); + // if there are no profile switches this should lead to profile update + if (MainApp.getConfigBuilder().getProfileSwitchesFromHistory().size() == 0) + MainApp.bus().post(new EventNewBasalProfile()); if (Config.logIncommingData) log.debug("Received profileStore: " + activeProfile + " " + profile); } catch (JSONException e) { diff --git a/app/src/main/java/info/nightscout/androidaps/data/Profile.java b/app/src/main/java/info/nightscout/androidaps/data/Profile.java index 5235545362..7bb693ef23 100644 --- a/app/src/main/java/info/nightscout/androidaps/data/Profile.java +++ b/app/src/main/java/info/nightscout/androidaps/data/Profile.java @@ -239,6 +239,7 @@ public class Profile { // if pump not available (at start) // do not store converted array basal_v = null; + isValidated = false; } } diff --git a/app/src/main/java/info/nightscout/androidaps/db/CareportalEvent.java b/app/src/main/java/info/nightscout/androidaps/db/CareportalEvent.java index b80f4f932e..8c55034c9f 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/CareportalEvent.java +++ b/app/src/main/java/info/nightscout/androidaps/db/CareportalEvent.java @@ -191,6 +191,17 @@ public class CareportalEvent implements DataPointWithLabelInterface { return Translator.translate(eventType); } + public String getNotes() { + try { + JSONObject object = new JSONObject(json); + if (object.has("notes")) + return object.getString("notes"); + } catch (JSONException e) { + log.error("Unhandled exception", e); + } + return ""; + } + @Override public long getDuration() { try { diff --git a/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java b/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java index c74233bd9c..3986a8b98d 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java +++ b/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java @@ -507,7 +507,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { return 0; } - public int deleteDbRequestbyMongoId(String action, String id) { + public void deleteDbRequestbyMongoId(String action, String id) { try { QueryBuilder queryBuilder = getDaoDbRequest().queryBuilder(); Where where = queryBuilder.where(); @@ -515,16 +515,13 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { queryBuilder.limit(10L); PreparedQuery preparedQuery = queryBuilder.prepare(); List dbList = getDaoDbRequest().query(preparedQuery); - if (dbList.size() != 1) { - log.error("deleteDbRequestbyMongoId query size: " + dbList.size()); - } else { - //log.debug("Treatment findTreatmentById found: " + trList.get(0).log()); - return delete(dbList.get(0)); + log.error("deleteDbRequestbyMongoId query size: " + dbList.size()); + for (DbRequest r : dbList) { + delete(r); } } catch (SQLException e) { log.error("Unhandled exception", e); } - return 0; } public void deleteAllDbRequests() { @@ -1508,7 +1505,21 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { } catch (SQLException e) { log.error("Unhandled exception", e); } - return new ArrayList(); + return new ArrayList<>(); + } + + public List getCareportalEventsFromTime(boolean ascending) { + try { + List careportalEvents; + QueryBuilder queryBuilder = getDaoCareportalEvents().queryBuilder(); + queryBuilder.orderBy("date", ascending); + PreparedQuery preparedQuery = queryBuilder.prepare(); + careportalEvents = getDaoCareportalEvents().query(preparedQuery); + return careportalEvents; + } catch (SQLException e) { + log.error("Unhandled exception", e); + } + return new ArrayList<>(); } public void deleteCareportalEventById(String _id) { 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 992e328532..a933c2166e 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/FoodHelper.java +++ b/app/src/main/java/info/nightscout/androidaps/db/FoodHelper.java @@ -70,7 +70,7 @@ public class FoodHelper { public boolean createOrUpdate(Food food) { try { // find by NS _id - if (food._id != null) { + if (food._id != null && !food._id.equals("")) { Food old; QueryBuilder queryBuilder = getDaoFood().queryBuilder(); @@ -90,12 +90,13 @@ public class FoodHelper { } else { return false; } + } else { + getDaoFood().createOrUpdate(food); + log.debug("FOOD: New record: " + food.toString()); + scheduleFoodChange(); + return true; } } - getDaoFood().createOrUpdate(food); - log.debug("FOOD: New record: " + food.toString()); - scheduleFoodChange(); - return true; } catch (SQLException e) { log.error("Unhandled exception", e); } diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventAppInitialized.java b/app/src/main/java/info/nightscout/androidaps/events/EventAppInitialized.java new file mode 100644 index 0000000000..17262cfb85 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/events/EventAppInitialized.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.events; + +/** + * Created by mike on 23.01.2018. + */ + +public class EventAppInitialized extends Event { +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderPlugin.java index 99ff546eac..e63924d80a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderPlugin.java @@ -28,6 +28,7 @@ import info.nightscout.androidaps.db.ProfileSwitch; import info.nightscout.androidaps.db.TempTarget; import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.db.Treatment; +import info.nightscout.androidaps.events.EventAppInitialized; import info.nightscout.androidaps.interfaces.APSInterface; import info.nightscout.androidaps.interfaces.BgSourceInterface; import info.nightscout.androidaps.interfaces.ConstraintsInterface; @@ -144,6 +145,7 @@ public class ConfigBuilderPlugin implements PluginBase, ConstraintsInterface, Tr public void initialize() { pluginList = MainApp.getPluginsList(); loadSettings(); + MainApp.bus().post(new EventAppInitialized()); } public void storeSettings() { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesFragment.java index f633c1b5ac..e4eef9ff2f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesFragment.java @@ -197,6 +197,7 @@ public class ObjectivesFragment extends Fragment { ObjectivesPlugin.objectives.get(4).objective = MainApp.sResources.getString(R.string.objectives_4_objective); ObjectivesPlugin.objectives.get(5).objective = MainApp.sResources.getString(R.string.objectives_5_objective); ObjectivesPlugin.objectives.get(6).objective = MainApp.sResources.getString(R.string.objectives_6_objective); + ObjectivesPlugin.objectives.get(7).objective = MainApp.sResources.getString(R.string.objectives_7_objective); ObjectivesPlugin.objectives.get(0).gate = MainApp.sResources.getString(R.string.objectives_0_gate); ObjectivesPlugin.objectives.get(1).gate = MainApp.sResources.getString(R.string.objectives_1_gate); ObjectivesPlugin.objectives.get(2).gate = MainApp.sResources.getString(R.string.objectives_2_gate); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesPlugin.java index 794f66ef60..3b0891680d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesPlugin.java @@ -161,14 +161,14 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface { boolean isVirtualPump = VirtualPumpPlugin.getPlugin().isEnabled(PluginBase.PUMP); boolean vpUploadEnabled = SP.getBoolean("virtualpump_uploadstatus", false); boolean vpUploadNeeded = !isVirtualPump || vpUploadEnabled; - boolean hasBGData = DatabaseHelper.lastBg()!=null; + boolean hasBGData = DatabaseHelper.lastBg() != null; boolean apsEnabled = false; APSInterface usedAPS = ConfigBuilderPlugin.getActiveAPS(); if (usedAPS != null && ((PluginBase) usedAPS).isEnabled(PluginBase.APS)) apsEnabled = true; - return new RequirementResult(hasBGData&&bgIsAvailableInNS && pumpStatusIsAvailableInNS && NSClientInternalPlugin.getPlugin().hasWritePermission() && LoopPlugin.getPlugin().isEnabled(PluginBase.LOOP) && apsEnabled && vpUploadNeeded, + return new RequirementResult(hasBGData && bgIsAvailableInNS && pumpStatusIsAvailableInNS && NSClientInternalPlugin.getPlugin().hasWritePermission() && LoopPlugin.getPlugin().isEnabled(PluginBase.LOOP) && apsEnabled && vpUploadNeeded, MainApp.sResources.getString(R.string.objectives_bgavailableinns) + ": " + yesOrNo(bgIsAvailableInNS) + "\n" + MainApp.sResources.getString(R.string.nsclienthaswritepermission) + ": " + yesOrNo(NSClientInternalPlugin.getPlugin().hasWritePermission()) + (isVirtualPump ? "\n" + MainApp.sResources.getString(R.string.virtualpump_uploadstatus_title) + ": " + yesOrNo(vpUploadEnabled) : "") @@ -187,7 +187,7 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface { return new RequirementResult(closedModeEnabled, MainApp.sResources.getString(R.string.closedmodeenabled) + ": " + yesOrNo(closedModeEnabled)); case 4: double maxIOB = MainApp.getConfigBuilder().applyMaxIOBConstraints(1000d); - boolean maxIobSet = maxIOB > 0; + boolean maxIobSet = maxIOB > 0; return new RequirementResult(maxIobSet, MainApp.sResources.getString(R.string.maxiobset) + ": " + yesOrNo(maxIobSet)); default: return new RequirementResult(true, ""); @@ -320,12 +320,12 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface { @Override public Double applyMaxIOBConstraints(Double maxIob) { - if (objectives.get(4).started.getTime() > 0 || objectives.get(2).accomplished.getTime() == 0) - return maxIob; - else { + if (objectives.get(3).started.getTime() > 0 && objectives.get(3).accomplished.getTime() == 0) { if (Config.logConstraintsChanges) log.debug("Limiting maxIOB " + maxIob + " to " + 0 + "U"); return 0d; + } else { + return maxIob; } } 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 index 558cf0d02f..a5c00aab7f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Food/FoodFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Food/FoodFragment.java @@ -61,7 +61,6 @@ public class FoodFragment extends SubscriberFragment { 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)); 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 fbbbe43ccc..504c676c8d 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 @@ -1,8 +1,6 @@ package info.nightscout.androidaps.plugins.IobCobCalculator; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.Process; +import android.os.SystemClock; import android.support.annotation.Nullable; import android.support.v4.util.LongSparseArray; @@ -24,15 +22,15 @@ import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.db.TemporaryBasal; -import info.nightscout.androidaps.db.Treatment; +import info.nightscout.androidaps.events.EventAppInitialized; import info.nightscout.androidaps.events.EventConfigBuilderChange; import info.nightscout.androidaps.events.EventNewBG; import info.nightscout.androidaps.events.EventNewBasalProfile; import info.nightscout.androidaps.events.EventPreferenceChange; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventAutosensCalculationFinished; import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventNewHistoryData; +import info.nightscout.utils.DateUtil; /** * Created by mike on 24.04.2017. @@ -50,10 +48,10 @@ public class IobCobCalculatorPlugin implements PluginBase { private static double dia = Constants.defaultDIA; - private static Handler sHandler = null; - private static HandlerThread sHandlerThread = null; + static final Object dataLock = new Object(); - private static final Object dataLock = new Object(); + boolean stopCalculationTrigger = false; + IobCobThread thread = null; private static IobCobCalculatorPlugin plugin = null; @@ -133,12 +131,6 @@ public class IobCobCalculatorPlugin implements PluginBase { IobCobCalculatorPlugin() { MainApp.bus().register(this); - if (sHandlerThread == null) { - sHandlerThread = new HandlerThread(IobCobCalculatorPlugin.class.getSimpleName(), Process.THREAD_PRIORITY_LOWEST); - sHandlerThread.start(); - sHandler = new Handler(sHandlerThread.getLooper()); - } - onNewBg(new EventNewBG()); } @Nullable @@ -175,14 +167,9 @@ public class IobCobCalculatorPlugin implements PluginBase { return rouded; } - private void loadBgData() { - //log.debug("Locking loadBgData"); - synchronized (dataLock) { - onNewProfile(null); - bgReadings = MainApp.getDbHelper().getBgreadingsDataFromTime((long) (System.currentTimeMillis() - 60 * 60 * 1000L * (24 + dia)), false); - log.debug("BG data loaded. Size: " + bgReadings.size()); - } - //log.debug("Releasing loadBgData"); + void loadBgData() { + bgReadings = MainApp.getDbHelper().getBgreadingsDataFromTime((long) (System.currentTimeMillis() - 60 * 60 * 1000L * (24 + dia)), false); + log.debug("BG data loaded. Size: " + bgReadings.size()); } private boolean isAbout5minData() { @@ -209,7 +196,7 @@ public class IobCobCalculatorPlugin implements PluginBase { } } - private void createBucketedData() { + void createBucketedData() { if (isAbout5minData()) createBucketedData5min(); else @@ -241,223 +228,97 @@ public class IobCobCalculatorPlugin implements PluginBase { } private void createBucketedDataRecalculated() { - synchronized (dataLock) { - if (bgReadings == null || bgReadings.size() < 3) { - bucketed_data = null; - return; - } + if (bgReadings == null || bgReadings.size() < 3) { + bucketed_data = null; + return; + } - bucketed_data = new ArrayList<>(); - long currentTime = bgReadings.get(0).date + 5 * 60 * 1000 - bgReadings.get(0).date % (5 * 60 * 1000) - 5 * 60 * 1000L; - //log.debug("First reading: " + new Date(currentTime).toLocaleString()); + bucketed_data = new ArrayList<>(); + long currentTime = bgReadings.get(0).date + 5 * 60 * 1000 - bgReadings.get(0).date % (5 * 60 * 1000) - 5 * 60 * 1000L; + //log.debug("First reading: " + new Date(currentTime).toLocaleString()); - while (true) { - // test if current value is older than current time - BgReading newer = findNewer(currentTime); - BgReading older = findOlder(currentTime); - if (newer == null || older == null) - break; + while (true) { + // test if current value is older than current time + BgReading newer = findNewer(currentTime); + BgReading older = findOlder(currentTime); + if (newer == null || older == null) + break; - double bgDelta = newer.value - older.value; - long timeDiffToNew = newer.date - currentTime; + double bgDelta = newer.value - older.value; + long timeDiffToNew = newer.date - currentTime; - double currentBg = newer.value - (double) timeDiffToNew / (newer.date - older.date) * bgDelta; - BgReading newBgreading = new BgReading(); - newBgreading.date = currentTime; - newBgreading.value = Math.round(currentBg); - bucketed_data.add(newBgreading); - //log.debug("BG: " + newBgreading.value + " (" + new Date(newBgreading.date).toLocaleString() + ") Prev: " + older.value + " (" + new Date(older.date).toLocaleString() + ") Newer: " + newer.value + " (" + new Date(newer.date).toLocaleString() + ")"); - currentTime -= 5 * 60 * 1000L; + double currentBg = newer.value - (double) timeDiffToNew / (newer.date - older.date) * bgDelta; + BgReading newBgreading = new BgReading(); + newBgreading.date = currentTime; + newBgreading.value = Math.round(currentBg); + bucketed_data.add(newBgreading); + //log.debug("BG: " + newBgreading.value + " (" + new Date(newBgreading.date).toLocaleString() + ") Prev: " + older.value + " (" + new Date(older.date).toLocaleString() + ") Newer: " + newer.value + " (" + new Date(newer.date).toLocaleString() + ")"); + currentTime -= 5 * 60 * 1000L; - } } } public void createBucketedData5min() { - //log.debug("Locking createBucketedData"); - synchronized (dataLock) { - if (bgReadings == null || bgReadings.size() < 3) { - bucketed_data = null; - return; + if (bgReadings == null || bgReadings.size() < 3) { + bucketed_data = null; + return; + } + + bucketed_data = new ArrayList<>(); + bucketed_data.add(bgReadings.get(0)); + int j = 0; + for (int i = 1; i < bgReadings.size(); ++i) { + long bgTime = bgReadings.get(i).date; + long lastbgTime = bgReadings.get(i - 1).date; + //log.error("Processing " + i + ": " + new Date(bgTime).toString() + " " + bgReadings.get(i).value + " Previous: " + new Date(lastbgTime).toString() + " " + bgReadings.get(i - 1).value); + if (bgReadings.get(i).value < 39 || bgReadings.get(i - 1).value < 39) { + continue; } - bucketed_data = new ArrayList<>(); - bucketed_data.add(bgReadings.get(0)); - int j = 0; - for (int i = 1; i < bgReadings.size(); ++i) { - long bgTime = bgReadings.get(i).date; - long lastbgTime = bgReadings.get(i - 1).date; - //log.error("Processing " + i + ": " + new Date(bgTime).toString() + " " + bgReadings.get(i).value + " Previous: " + new Date(lastbgTime).toString() + " " + bgReadings.get(i - 1).value); - if (bgReadings.get(i).value < 39 || bgReadings.get(i - 1).value < 39) { - continue; - } - - long elapsed_minutes = (bgTime - lastbgTime) / (60 * 1000); - if (Math.abs(elapsed_minutes) > 8) { - // interpolate missing data points - double lastbg = bgReadings.get(i - 1).value; - elapsed_minutes = Math.abs(elapsed_minutes); - //console.error(elapsed_minutes); - long nextbgTime; - while (elapsed_minutes > 5) { - nextbgTime = lastbgTime - 5 * 60 * 1000; - j++; - BgReading newBgreading = new BgReading(); - newBgreading.date = nextbgTime; - double gapDelta = bgReadings.get(i).value - lastbg; - //console.error(gapDelta, lastbg, elapsed_minutes); - double nextbg = lastbg + (5d / elapsed_minutes * gapDelta); - newBgreading.value = Math.round(nextbg); - //console.error("Interpolated", bucketed_data[j]); - bucketed_data.add(newBgreading); - //log.error("******************************************************************************************************* Adding:" + new Date(newBgreading.date).toString() + " " + newBgreading.value); - - elapsed_minutes = elapsed_minutes - 5; - lastbg = nextbg; - lastbgTime = nextbgTime; - } + long elapsed_minutes = (bgTime - lastbgTime) / (60 * 1000); + if (Math.abs(elapsed_minutes) > 8) { + // interpolate missing data points + double lastbg = bgReadings.get(i - 1).value; + elapsed_minutes = Math.abs(elapsed_minutes); + //console.error(elapsed_minutes); + long nextbgTime; + while (elapsed_minutes > 5) { + nextbgTime = lastbgTime - 5 * 60 * 1000; j++; BgReading newBgreading = new BgReading(); - newBgreading.value = bgReadings.get(i).value; - newBgreading.date = bgTime; + newBgreading.date = nextbgTime; + double gapDelta = bgReadings.get(i).value - lastbg; + //console.error(gapDelta, lastbg, elapsed_minutes); + double nextbg = lastbg + (5d / elapsed_minutes * gapDelta); + newBgreading.value = Math.round(nextbg); + //console.error("Interpolated", bucketed_data[j]); bucketed_data.add(newBgreading); - //log.error("******************************************************************************************************* Copying:" + new Date(newBgreading.date).toString() + " " + newBgreading.value); - } else if (Math.abs(elapsed_minutes) > 2) { - j++; - BgReading newBgreading = new BgReading(); - newBgreading.value = bgReadings.get(i).value; - newBgreading.date = bgTime; - bucketed_data.add(newBgreading); - //log.error("******************************************************************************************************* Copying:" + new Date(newBgreading.date).toString() + " " + newBgreading.value); - } else { - bucketed_data.get(j).value = (bucketed_data.get(j).value + bgReadings.get(i).value) / 2; - //log.error("***** Average"); + //log.error("******************************************************************************************************* Adding:" + new Date(newBgreading.date).toString() + " " + newBgreading.value); + + elapsed_minutes = elapsed_minutes - 5; + lastbg = nextbg; + lastbgTime = nextbgTime; } - } - log.debug("Bucketed data created. Size: " + bucketed_data.size()); - } - //log.debug("Releasing createBucketedData"); - } - - private void calculateSensitivityData() { - if (MainApp.getConfigBuilder() == null) - return; // app still initializing - if (MainApp.getConfigBuilder().getProfile() == null) - return; // app still initializing - //log.debug("Locking calculateSensitivityData"); - long oldestTimeWithData = oldestDataAvailable(); - - synchronized (dataLock) { - - if (bucketed_data == null || bucketed_data.size() < 3) { - log.debug("calculateSensitivityData: No bucketed data available"); - return; - } - - long prevDataTime = roundUpTime(bucketed_data.get(bucketed_data.size() - 3).date); - log.debug("Prev data time: " + new Date(prevDataTime).toLocaleString()); - AutosensData previous = autosensDataTable.get(prevDataTime); - // start from oldest to be able sub cob - for (int i = bucketed_data.size() - 4; i >= 0; i--) { - // check if data already exists - long bgTime = bucketed_data.get(i).date; - bgTime = roundUpTime(bgTime); - if (bgTime > System.currentTimeMillis()) - continue; - Profile profile = MainApp.getConfigBuilder().getProfile(bgTime); - - AutosensData existing; - if ((existing = autosensDataTable.get(bgTime)) != null) { - previous = existing; - continue; - } - - if (profile.getIsf(bgTime) == null) - return; // profile not set yet - - double sens = Profile.toMgdl(profile.getIsf(bgTime), profile.getUnits()); - - AutosensData autosensData = new AutosensData(); - autosensData.time = bgTime; - if (previous != null) - autosensData.activeCarbsList = new ArrayList<>(previous.activeCarbsList); - else - autosensData.activeCarbsList = new ArrayList<>(); - - //console.error(bgTime , bucketed_data[i].glucose); - double bg; - double avgDelta; - double delta; - bg = bucketed_data.get(i).value; - if (bg < 39 || bucketed_data.get(i + 3).value < 39) { - log.error("! value < 39"); - continue; - } - delta = (bg - bucketed_data.get(i + 1).value); - - IobTotal iob = calculateFromTreatmentsAndTemps(bgTime); - - double bgi = -iob.activity * sens * 5; - double deviation = delta - bgi; - - List recentTreatments = MainApp.getConfigBuilder().getTreatments5MinBackFromHistory(bgTime); - for (int ir = 0; ir < recentTreatments.size(); ir++) { - autosensData.carbsFromBolus += recentTreatments.get(ir).carbs; - autosensData.activeCarbsList.add(new AutosensData.CarbsInPast(recentTreatments.get(ir))); - } - - - // if we are absorbing carbs - if (previous != null && previous.cob > 0) { - // calculate sum of min carb impact from all active treatments - double totalMinCarbsImpact = 0d; - for (int ii = 0; ii < autosensData.activeCarbsList.size(); ++ii) { - AutosensData.CarbsInPast c = autosensData.activeCarbsList.get(ii); - totalMinCarbsImpact += c.min5minCarbImpact; - } - - // figure out how many carbs that represents - // but always assume at least 3mg/dL/5m (default) absorption per active treatment - double ci = Math.max(deviation, totalMinCarbsImpact); - autosensData.absorbed = ci * profile.getIc(bgTime) / sens; - // and add that to the running total carbsAbsorbed - autosensData.cob = Math.max(previous.cob - autosensData.absorbed, 0d); - autosensData.substractAbosorbedCarbs(); - } - autosensData.removeOldCarbs(bgTime); - autosensData.cob += autosensData.carbsFromBolus; - autosensData.deviation = deviation; - autosensData.bgi = bgi; - autosensData.delta = delta; - - // calculate autosens only without COB - if (autosensData.cob <= 0) { - if (Math.abs(deviation) < Constants.DEVIATION_TO_BE_EQUAL) { - autosensData.pastSensitivity += "="; - autosensData.nonEqualDeviation = true; - } else if (deviation > 0) { - autosensData.pastSensitivity += "+"; - autosensData.nonEqualDeviation = true; - } else { - autosensData.pastSensitivity += "-"; - autosensData.nonEqualDeviation = true; - } - autosensData.nonCarbsDeviation = true; - } else { - autosensData.pastSensitivity += "C"; - } - //log.debug("TIME: " + new Date(bgTime).toString() + " BG: " + bg + " SENS: " + sens + " DELTA: " + delta + " AVGDELTA: " + avgDelta + " IOB: " + iob.iob + " ACTIVITY: " + iob.activity + " BGI: " + bgi + " DEVIATION: " + deviation); - - previous = autosensData; - autosensDataTable.put(bgTime, autosensData); - autosensData.autosensRatio = detectSensitivity(oldestTimeWithData, bgTime).ratio; - if (Config.logAutosensData) - log.debug(autosensData.log(bgTime)); + j++; + BgReading newBgreading = new BgReading(); + newBgreading.value = bgReadings.get(i).value; + newBgreading.date = bgTime; + bucketed_data.add(newBgreading); + //log.error("******************************************************************************************************* Copying:" + new Date(newBgreading.date).toString() + " " + newBgreading.value); + } else if (Math.abs(elapsed_minutes) > 2) { + j++; + BgReading newBgreading = new BgReading(); + newBgreading.value = bgReadings.get(i).value; + newBgreading.date = bgTime; + bucketed_data.add(newBgreading); + //log.error("******************************************************************************************************* Copying:" + new Date(newBgreading.date).toString() + " " + newBgreading.value); + } else { + bucketed_data.get(j).value = (bucketed_data.get(j).value + bgReadings.get(i).value) / 2; + //log.error("***** Average"); } } - MainApp.bus().post(new EventAutosensCalculationFinished()); - //log.debug("Releasing calculateSensitivityData"); + log.debug("Bucketed data created. Size: " + bucketed_data.size()); } public static long oldestDataAvailable() { @@ -580,11 +441,11 @@ public class IobCobCalculatorPlugin implements PluginBase { return null; } if (data.time < System.currentTimeMillis() - 11 * 60 * 1000) { - log.debug("AUTOSENSDATA null: data is old (" + reason + ")"); + log.debug("AUTOSENSDATA null: data is old (" + reason + ") size()=" + autosensDataTable.size() + " lastdata=" + DateUtil.dateAndTimeString(data.time)); return null; } else { if (data == null) - log.debug("AUTOSENSDATA null: data == null (" + " " + reason + ")"); + log.debug("AUTOSENSDATA null: data == null (" + " " + reason + ") size()=" + autosensDataTable.size() + " lastdata=" + DateUtil.dateAndTimeString(data.time)); return data; } } @@ -612,7 +473,7 @@ public class IobCobCalculatorPlugin implements PluginBase { } } - private static AutosensResult detectSensitivity(long fromTime, long toTime) { + static AutosensResult detectSensitivity(long fromTime, long toTime) { return ConfigBuilderPlugin.getActiveSensitivity().detectSensitivity(fromTime, toTime); } @@ -625,15 +486,33 @@ public class IobCobCalculatorPlugin implements PluginBase { } @Subscribe - public void onNewBg(EventNewBG ev) { - sHandler.post(new Runnable() { - @Override - public void run() { - loadBgData(); - createBucketedData(); - calculateSensitivityData(); + public void onEventAppInitialized(EventAppInitialized ev) { + runCalculation("onEventAppInitialized", true); + } + + @Subscribe + public void onEventNewBG(EventNewBG ev) { + stopCalculation("onEventNewBG"); + runCalculation("onEventNewBG", true); + } + + private void stopCalculation(String from) { + if (thread != null && thread.getState() != Thread.State.TERMINATED) { + stopCalculationTrigger = true; + log.debug("Stopping calculation thread: " + from); + while (thread.getState() != Thread.State.TERMINATED) { + SystemClock.sleep(100); } - }); + log.debug("Calculation thread stopped: " + from); + } + } + + private void runCalculation(String from, boolean bgDataReload) { + log.debug("Starting calculation thread: " + from); + if (thread == null || thread.getState() == Thread.State.TERMINATED) { + thread = new IobCobThread(this, from, bgDataReload); + thread.start(); + } } @Subscribe @@ -647,66 +526,55 @@ public class IobCobCalculatorPlugin implements PluginBase { if (ev == null) { // on init no need of reset return; } + stopCalculation("onNewProfile"); synchronized (dataLock) { log.debug("Invalidating cached data because of new profile. IOB: " + iobTable.size() + " Autosens: " + autosensDataTable.size() + " records"); iobTable = new LongSparseArray<>(); autosensDataTable = new LongSparseArray<>(); } - sHandler.post(new Runnable() { - @Override - public void run() { - calculateSensitivityData(); - } - }); + runCalculation("onNewProfile", false); } @Subscribe - public void onStatusEvent(EventPreferenceChange ev) { + public void onEventPreferenceChange(EventPreferenceChange ev) { if (ev.isChanged(R.string.key_openapsama_autosens_period) || ev.isChanged(R.string.key_age) || ev.isChanged(R.string.key_absorption_maxtime) ) { + stopCalculation("onEventPreferenceChange"); synchronized (dataLock) { log.debug("Invalidating cached data because of preference change. IOB: " + iobTable.size() + " Autosens: " + autosensDataTable.size() + " records"); iobTable = new LongSparseArray<>(); autosensDataTable = new LongSparseArray<>(); } - sHandler.post(new Runnable() { - @Override - public void run() { - calculateSensitivityData(); - } - }); + runCalculation("onEventPreferenceChange", false); } } @Subscribe - public void onStatusEvent(EventConfigBuilderChange ev) { + public void onEventConfigBuilderChange(EventConfigBuilderChange ev) { + stopCalculation("onEventConfigBuilderChange"); synchronized (dataLock) { log.debug("Invalidating cached data because of configuration change. IOB: " + iobTable.size() + " Autosens: " + autosensDataTable.size() + " records"); iobTable = new LongSparseArray<>(); autosensDataTable = new LongSparseArray<>(); } - sHandler.post(new Runnable() { - @Override - public void run() { - calculateSensitivityData(); - } - }); + runCalculation("onEventConfigBuilderChange", false); } // When historical data is changed (comming from NS etc) finished calculations after this date must be invalidated @Subscribe - public void onNewHistoryData(EventNewHistoryData ev) { + public void onEventNewHistoryData(EventNewHistoryData ev) { //log.debug("Locking onNewHistoryData"); + stopCalculation("onEventNewHistoryData"); synchronized (dataLock) { - long time = ev.time; + // clear up 5 min back for proper COB calculation + long time = ev.time - 5 * 60 * 1000L; log.debug("Invalidating cached data to: " + new Date(time).toLocaleString()); for (int index = iobTable.size() - 1; index >= 0; index--) { if (iobTable.keyAt(index) > time) { if (Config.logAutosensData) - if (Config.logAutosensData) - log.debug("Removing from iobTable: " + new Date(iobTable.keyAt(index)).toLocaleString()); + log.debug("Removing from iobTable: " + new Date(iobTable.keyAt(index)).toLocaleString()); iobTable.removeAt(index); } else { break; @@ -731,12 +599,7 @@ public class IobCobCalculatorPlugin implements PluginBase { } } } - sHandler.post(new Runnable() { - @Override - public void run() { - calculateSensitivityData(); - } - }); + runCalculation("onEventNewHistoryData", false); //log.debug("Releasing onNewHistoryData"); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobThread.java b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobThread.java new file mode 100644 index 0000000000..947e6ba03f --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobThread.java @@ -0,0 +1,206 @@ +package info.nightscout.androidaps.plugins.IobCobCalculator; + +import android.content.Context; +import android.os.PowerManager; +import android.support.v4.util.LongSparseArray; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import info.nightscout.androidaps.Config; +import info.nightscout.androidaps.Constants; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.data.IobTotal; +import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.db.BgReading; +import info.nightscout.androidaps.db.Treatment; +import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventAutosensCalculationFinished; +import info.nightscout.androidaps.queue.QueueThread; + +import static info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin.getBucketedData; +import static info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin.oldestDataAvailable; +import static info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin.roundUpTime; + +/** + * Created by mike on 23.01.2018. + */ + +public class IobCobThread extends Thread { + private static Logger log = LoggerFactory.getLogger(QueueThread.class); + + private IobCobCalculatorPlugin iobCobCalculatorPlugin; + private boolean bgDataReload; + private String from; + + private PowerManager.WakeLock mWakeLock; + + public IobCobThread(IobCobCalculatorPlugin plugin, String from, boolean bgDataReload) { + super(); + + this.iobCobCalculatorPlugin = plugin; + this.bgDataReload = bgDataReload; + this.from = from; + + PowerManager powerManager = (PowerManager) MainApp.instance().getApplicationContext().getSystemService(Context.POWER_SERVICE); + mWakeLock = powerManager.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "iobCobThread"); + } + + @Override + public final void run() { + mWakeLock.acquire(); + try { + if (MainApp.getConfigBuilder() == null) { + log.debug("Aborting calculation thread (ConfigBuilder not ready): " + from); + return; // app still initializing + } + if (MainApp.getConfigBuilder().getProfile() == null) { + log.debug("Aborting calculation thread (No profile): " + from); + return; // app still initializing + } + //log.debug("Locking calculateSensitivityData"); + + Object dataLock = iobCobCalculatorPlugin.dataLock; + + long oldestTimeWithData = oldestDataAvailable(); + + synchronized (dataLock) { + if (bgDataReload) { + iobCobCalculatorPlugin.loadBgData(); + iobCobCalculatorPlugin.createBucketedData(); + } + List bucketed_data = getBucketedData(); + LongSparseArray autosensDataTable = iobCobCalculatorPlugin.getAutosensDataTable(); + + if (bucketed_data == null || bucketed_data.size() < 3) { + log.debug("Aborting calculation thread (No bucketed data available): " + from); + return; + } + + long prevDataTime = roundUpTime(bucketed_data.get(bucketed_data.size() - 3).date); + log.debug("Prev data time: " + new Date(prevDataTime).toLocaleString()); + AutosensData previous = autosensDataTable.get(prevDataTime); + // start from oldest to be able sub cob + for (int i = bucketed_data.size() - 4; i >= 0; i--) { + if (iobCobCalculatorPlugin.stopCalculationTrigger) { + iobCobCalculatorPlugin.stopCalculationTrigger = false; + log.debug("Aborting calculation thread (trigger): " + from); + return; + } + // check if data already exists + long bgTime = bucketed_data.get(i).date; + bgTime = roundUpTime(bgTime); + if (bgTime > System.currentTimeMillis()) + continue; + Profile profile = MainApp.getConfigBuilder().getProfile(bgTime); + + AutosensData existing; + if ((existing = autosensDataTable.get(bgTime)) != null) { + previous = existing; + continue; + } + + if (profile == null) { + log.debug("Aborting calculation thread (no profile): " + from); + return; // profile not set yet + } + + if (profile.getIsf(bgTime) == null) { + log.debug("Aborting calculation thread (no ISF): " + from); + return; // profile not set yet + } + + if (Config.logAutosensData) + log.debug("Processing calculation thread: " + from + " (" + i + "/" + bucketed_data.size() + ")"); + + double sens = Profile.toMgdl(profile.getIsf(bgTime), profile.getUnits()); + + AutosensData autosensData = new AutosensData(); + autosensData.time = bgTime; + if (previous != null) + autosensData.activeCarbsList = new ArrayList<>(previous.activeCarbsList); + else + autosensData.activeCarbsList = new ArrayList<>(); + + //console.error(bgTime , bucketed_data[i].glucose); + double bg; + double avgDelta; + double delta; + bg = bucketed_data.get(i).value; + if (bg < 39 || bucketed_data.get(i + 3).value < 39) { + log.error("! value < 39"); + continue; + } + delta = (bg - bucketed_data.get(i + 1).value); + + IobTotal iob = iobCobCalculatorPlugin.calculateFromTreatmentsAndTemps(bgTime); + + double bgi = -iob.activity * sens * 5; + double deviation = delta - bgi; + + List recentTreatments = MainApp.getConfigBuilder().getTreatments5MinBackFromHistory(bgTime); + for (int ir = 0; ir < recentTreatments.size(); ir++) { + autosensData.carbsFromBolus += recentTreatments.get(ir).carbs; + autosensData.activeCarbsList.add(new AutosensData.CarbsInPast(recentTreatments.get(ir))); + } + + + // if we are absorbing carbs + if (previous != null && previous.cob > 0) { + // calculate sum of min carb impact from all active treatments + double totalMinCarbsImpact = 0d; + for (int ii = 0; ii < autosensData.activeCarbsList.size(); ++ii) { + AutosensData.CarbsInPast c = autosensData.activeCarbsList.get(ii); + totalMinCarbsImpact += c.min5minCarbImpact; + } + + // figure out how many carbs that represents + // but always assume at least 3mg/dL/5m (default) absorption per active treatment + double ci = Math.max(deviation, totalMinCarbsImpact); + autosensData.absorbed = ci * profile.getIc(bgTime) / sens; + // and add that to the running total carbsAbsorbed + autosensData.cob = Math.max(previous.cob - autosensData.absorbed, 0d); + autosensData.substractAbosorbedCarbs(); + } + autosensData.removeOldCarbs(bgTime); + autosensData.cob += autosensData.carbsFromBolus; + autosensData.deviation = deviation; + autosensData.bgi = bgi; + autosensData.delta = delta; + + // calculate autosens only without COB + if (autosensData.cob <= 0) { + if (Math.abs(deviation) < Constants.DEVIATION_TO_BE_EQUAL) { + autosensData.pastSensitivity += "="; + autosensData.nonEqualDeviation = true; + } else if (deviation > 0) { + autosensData.pastSensitivity += "+"; + autosensData.nonEqualDeviation = true; + } else { + autosensData.pastSensitivity += "-"; + autosensData.nonEqualDeviation = true; + } + autosensData.nonCarbsDeviation = true; + } else { + autosensData.pastSensitivity += "C"; + } + //log.debug("TIME: " + new Date(bgTime).toString() + " BG: " + bg + " SENS: " + sens + " DELTA: " + delta + " AVGDELTA: " + avgDelta + " IOB: " + iob.iob + " ACTIVITY: " + iob.activity + " BGI: " + bgi + " DEVIATION: " + deviation); + + previous = autosensData; + autosensDataTable.put(bgTime, autosensData); + autosensData.autosensRatio = iobCobCalculatorPlugin.detectSensitivity(oldestTimeWithData, bgTime).ratio; + if (Config.logAutosensData) + log.debug(autosensData.log(bgTime)); + } + } + MainApp.bus().post(new EventAutosensCalculationFinished()); + log.debug("Finishing calculation thread: " + from); + } finally { + mWakeLock.release(); + } + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialog.java index fd720e9499..530843836d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialog.java @@ -528,12 +528,12 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com if (calculatedTotalInsulin > 0d || calculatedCarbs > 0d) { String insulinText = calculatedTotalInsulin > 0d ? (DecimalFormatter.to2Decimal(calculatedTotalInsulin) + "U") : ""; String carbsText = calculatedCarbs > 0d ? (DecimalFormatter.to0Decimal(calculatedCarbs) + "g") : ""; - total.setText(getString(R.string.result) + ": " + insulinText + " " + carbsText); + total.setText(MainApp.gs(R.string.result) + ": " + insulinText + " " + carbsText); okButton.setVisibility(View.VISIBLE); } else { // TODO this should also be run when loading the dialog as the OK button is initially visible // but does nothing if neither carbs nor insulin is > 0 - total.setText(getString(R.string.missing) + " " + DecimalFormatter.to0Decimal(wizard.carbsEquivalent) + "g"); + total.setText(MainApp.gs(R.string.missing) + " " + DecimalFormatter.to0Decimal(wizard.carbsEquivalent) + "g"); okButton.setVisibility(View.INVISIBLE); } 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 380e8f5d87..9b44af6477 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 @@ -149,12 +149,18 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, TextView sage; TextView pbage; - CheckBox showPredictionView; - CheckBox showBasalsView; - CheckBox showIobView; - CheckBox showCobView; - CheckBox showDeviationsView; - CheckBox showRatiosView; + TextView showPredictionLabel; + CheckBox showPredictionCheckbox; + TextView showBasalsLabel; + CheckBox showBasalsCheckbox; + TextView showIobLabel; + CheckBox showIobCheckbox; + TextView showCobLabel; + CheckBox showCobCheckbox; + TextView showDeviationsLabel; + CheckBox showDeviationsCheckbox; + TextView showRatiosLabel; + CheckBox showRatiosCheckbox; RecyclerView notificationsView; LinearLayoutManager llm; @@ -266,24 +272,37 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, acceptTempLayout = (LinearLayout) view.findViewById(R.id.overview_accepttemplayout); - showPredictionView = (CheckBox) view.findViewById(R.id.overview_showprediction); - showBasalsView = (CheckBox) view.findViewById(R.id.overview_showbasals); - showIobView = (CheckBox) view.findViewById(R.id.overview_showiob); - showCobView = (CheckBox) view.findViewById(R.id.overview_showcob); - showDeviationsView = (CheckBox) view.findViewById(R.id.overview_showdeviations); - showRatiosView = (CheckBox) view.findViewById(R.id.overview_showratios); - showPredictionView.setChecked(SP.getBoolean("showprediction", false)); - showBasalsView.setChecked(SP.getBoolean("showbasals", true)); - showIobView.setChecked(SP.getBoolean("showiob", false)); - showCobView.setChecked(SP.getBoolean("showcob", false)); - showDeviationsView.setChecked(SP.getBoolean("showdeviations", false)); - showRatiosView.setChecked(SP.getBoolean("showratios", false)); - showPredictionView.setOnCheckedChangeListener(this); - showBasalsView.setOnCheckedChangeListener(this); - showIobView.setOnCheckedChangeListener(this); - showCobView.setOnCheckedChangeListener(this); - showDeviationsView.setOnCheckedChangeListener(this); - showRatiosView.setOnCheckedChangeListener(this); + showPredictionCheckbox = (CheckBox) view.findViewById(R.id.overview_showprediction); + showBasalsCheckbox = (CheckBox) view.findViewById(R.id.overview_showbasals); + showIobCheckbox = (CheckBox) view.findViewById(R.id.overview_showiob); + showCobCheckbox = (CheckBox) view.findViewById(R.id.overview_showcob); + showDeviationsCheckbox = (CheckBox) view.findViewById(R.id.overview_showdeviations); + showRatiosCheckbox = (CheckBox) view.findViewById(R.id.overview_showratios); + showPredictionCheckbox.setChecked(SP.getBoolean("showprediction", false)); + showBasalsCheckbox.setChecked(SP.getBoolean("showbasals", true)); + showIobCheckbox.setChecked(SP.getBoolean("showiob", false)); + showCobCheckbox.setChecked(SP.getBoolean("showcob", false)); + showDeviationsCheckbox.setChecked(SP.getBoolean("showdeviations", false)); + showRatiosCheckbox.setChecked(SP.getBoolean("showratios", false)); + showPredictionCheckbox.setOnCheckedChangeListener(this); + showBasalsCheckbox.setOnCheckedChangeListener(this); + showIobCheckbox.setOnCheckedChangeListener(this); + showCobCheckbox.setOnCheckedChangeListener(this); + showDeviationsCheckbox.setOnCheckedChangeListener(this); + showRatiosCheckbox.setOnCheckedChangeListener(this); + + showPredictionLabel = (TextView) view.findViewById(R.id.overview_showprediction_label); + showPredictionLabel.setOnClickListener(this); + showBasalsLabel = (TextView) view.findViewById(R.id.overview_showbasals_label); + showBasalsLabel.setOnClickListener(this); + showIobLabel = (TextView) view.findViewById(R.id.overview_showiob_label); + showIobLabel.setOnClickListener(this); + showCobLabel = (TextView) view.findViewById(R.id.overview_showcob_label); + showCobLabel.setOnClickListener(this); + showDeviationsLabel = (TextView) view.findViewById(R.id.overview_showdeviations_label); + showDeviationsLabel.setOnClickListener(this); + showRatiosLabel = (TextView) view.findViewById(R.id.overview_showratios_label); + showRatiosLabel.setOnClickListener(this); notificationsView = (RecyclerView) view.findViewById(R.id.overview_notifications); notificationsView.setHasFixedSize(true); @@ -376,24 +395,24 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, case R.id.overview_showiob: break; case R.id.overview_showcob: - showDeviationsView.setOnCheckedChangeListener(null); - showDeviationsView.setChecked(false); - showDeviationsView.setOnCheckedChangeListener(this); + showDeviationsCheckbox.setOnCheckedChangeListener(null); + showDeviationsCheckbox.setChecked(false); + showDeviationsCheckbox.setOnCheckedChangeListener(this); break; case R.id.overview_showdeviations: - showCobView.setOnCheckedChangeListener(null); - showCobView.setChecked(false); - showCobView.setOnCheckedChangeListener(this); + showCobCheckbox.setOnCheckedChangeListener(null); + showCobCheckbox.setChecked(false); + showCobCheckbox.setOnCheckedChangeListener(this); break; case R.id.overview_showratios: break; } - SP.putBoolean("showiob", showIobView.isChecked()); - SP.putBoolean("showprediction", showPredictionView.isChecked()); - SP.putBoolean("showbasals", showBasalsView.isChecked()); - SP.putBoolean("showcob", showCobView.isChecked()); - SP.putBoolean("showdeviations", showDeviationsView.isChecked()); - SP.putBoolean("showratios", showRatiosView.isChecked()); + SP.putBoolean("showiob", showIobCheckbox.isChecked()); + SP.putBoolean("showprediction", showPredictionCheckbox.isChecked()); + SP.putBoolean("showbasals", showBasalsCheckbox.isChecked()); + SP.putBoolean("showcob", showCobCheckbox.isChecked()); + SP.putBoolean("showdeviations", showDeviationsCheckbox.isChecked()); + SP.putBoolean("showratios", showRatiosCheckbox.isChecked()); scheduleUpdateGUI("onGraphCheckboxesCheckedChanged"); } @@ -498,6 +517,16 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, } } }); + if (MainApp.getConfigBuilder().getActivePump().getPumpDescription().isExtendedBolusCapable && MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) { + ConfigBuilderPlugin.getCommandQueue().cancelExtended( new Callback() { + @Override + public void run() { + if (!result.success) { + ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.extendedbolusdeliveryerror)); + } + } + }); + } NSUpload.uploadOpenAPSOffline(30); return true; } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.disconnectpumpfor1h))) { @@ -511,6 +540,16 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, } } }); + if (MainApp.getConfigBuilder().getActivePump().getPumpDescription().isExtendedBolusCapable && MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) { + ConfigBuilderPlugin.getCommandQueue().cancelExtended( new Callback() { + @Override + public void run() { + if (!result.success) { + ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.extendedbolusdeliveryerror)); + } + } + }); + } NSUpload.uploadOpenAPSOffline(60); return true; } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.disconnectpumpfor2h))) { @@ -524,6 +563,16 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, } } }); + if (MainApp.getConfigBuilder().getActivePump().getPumpDescription().isExtendedBolusCapable && MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) { + ConfigBuilderPlugin.getCommandQueue().cancelExtended( new Callback() { + @Override + public void run() { + if (!result.success) { + ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.extendedbolusdeliveryerror)); + } + } + }); + } NSUpload.uploadOpenAPSOffline(120); return true; } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.disconnectpumpfor3h))) { @@ -537,6 +586,16 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, } } }); + if (MainApp.getConfigBuilder().getActivePump().getPumpDescription().isExtendedBolusCapable && MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) { + ConfigBuilderPlugin.getCommandQueue().cancelExtended( new Callback() { + @Override + public void run() { + if (!result.success) { + ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.extendedbolusdeliveryerror)); + } + } + }); + } NSUpload.uploadOpenAPSOffline(180); return true; } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.careportal_profileswitch))) { @@ -580,6 +639,24 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, if (ConfigBuilderPlugin.getActivePump().isSuspended() || !ConfigBuilderPlugin.getActivePump().isInitialized()) ConfigBuilderPlugin.getCommandQueue().readStatus("RefreshClicked", null); break; + case R.id.overview_showprediction_label: + showPredictionCheckbox.toggle(); + break; + case R.id.overview_showbasals_label: + showBasalsCheckbox.toggle(); + break; + case R.id.overview_showiob_label: + showIobCheckbox.toggle(); + break; + case R.id.overview_showcob_label: + showCobCheckbox.toggle(); + break; + case R.id.overview_showdeviations_label: + showDeviationsCheckbox.toggle(); + break; + case R.id.overview_showratios_label: + showRatiosCheckbox.toggle(); + break; } } @@ -1206,13 +1283,13 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, cobView.setText(cobText); } - final boolean showPrediction = showPredictionView.isChecked() && finalLastRun != null && finalLastRun.constraintsProcessed.getClass().equals(DetermineBasalResultAMA.class); + final boolean showPrediction = showPredictionCheckbox.isChecked() && finalLastRun != null && finalLastRun.constraintsProcessed.getClass().equals(DetermineBasalResultAMA.class); if (MainApp.getSpecificPlugin(OpenAPSAMAPlugin.class) != null && MainApp.getSpecificPlugin(OpenAPSAMAPlugin.class).isEnabled(PluginBase.APS)) { - showPredictionView.setVisibility(View.VISIBLE); - getActivity().findViewById(R.id.overview_showprediction_label).setVisibility(View.VISIBLE); + showPredictionCheckbox.setVisibility(View.VISIBLE); + showPredictionLabel.setVisibility(View.VISIBLE); } else { - showPredictionView.setVisibility(View.GONE); - getActivity().findViewById(R.id.overview_showprediction_label).setVisibility(View.GONE); + showPredictionCheckbox.setVisibility(View.GONE); + showPredictionLabel.setVisibility(View.GONE); } // pump status from ns @@ -1304,7 +1381,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, graphData.addTreatments(fromTime, endTime); // add basal data - if (pump.getPumpDescription().isTempBasalCapable && showBasalsView.isChecked()) { + if (pump.getPumpDescription().isTempBasalCapable && showBasalsCheckbox.isChecked()) { graphData.addBasals(fromTime, now, lowLine / graphData.maxY / 1.2d); } @@ -1321,23 +1398,23 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, boolean useDevForScale = false; boolean useRatioForScale = false; - if (showIobView.isChecked()) { + if (showIobCheckbox.isChecked()) { useIobForScale = true; - } else if (showCobView.isChecked()) { + } else if (showCobCheckbox.isChecked()) { useCobForScale = true; - } else if (showDeviationsView.isChecked()) { + } else if (showDeviationsCheckbox.isChecked()) { useDevForScale = true; - } else if (showRatiosView.isChecked()) { + } else if (showRatiosCheckbox.isChecked()) { useRatioForScale = true; } - if (showIobView.isChecked()) + if (showIobCheckbox.isChecked()) secondGraphData.addIob(fromTime, now, useIobForScale, 1d); - if (showCobView.isChecked()) + if (showCobCheckbox.isChecked()) secondGraphData.addCob(fromTime, now, useCobForScale, useCobForScale ? 1d : 0.5d); - if (showDeviationsView.isChecked()) + if (showDeviationsCheckbox.isChecked()) secondGraphData.addDeviations(fromTime, now, useDevForScale, 1d); - if (showRatiosView.isChecked()) + if (showRatiosCheckbox.isChecked()) secondGraphData.addRatio(fromTime, now, useRatioForScale, 1d); // **** NOW line **** @@ -1351,7 +1428,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, activity.runOnUiThread(new Runnable() { @Override public void run() { - if (showIobView.isChecked() || showCobView.isChecked() || showDeviationsView.isChecked() || showRatiosView.isChecked()) { + if (showIobCheckbox.isChecked() || showCobCheckbox.isChecked() || showDeviationsCheckbox.isChecked() || showRatiosCheckbox.isChecked()) { iobGraph.setVisibility(View.VISIBLE); } else { iobGraph.setVisibility(View.GONE); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphData/GraphData.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphData/GraphData.java index e76714c5b2..5d5a0832d5 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphData/GraphData.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphData/GraphData.java @@ -253,7 +253,7 @@ public class GraphData { } // Careportal - List careportalEvents = MainApp.getDbHelper().getCareportalEventsFromTime(fromTime, true); + List careportalEvents = MainApp.getDbHelper().getCareportalEventsFromTime(fromTime - 6 * 60 * 60 * 1000, true); for (int tx = 0; tx < careportalEvents.size(); tx++) { DataPointWithLabelInterface t = careportalEvents.get(tx); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/PointsWithLabelGraphSeries.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/PointsWithLabelGraphSeries.java index 7606a71f17..26892372d5 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/PointsWithLabelGraphSeries.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/PointsWithLabelGraphSeries.java @@ -141,9 +141,6 @@ public class PointsWithLabelGraphSeries e Iterator values = getValues(minX, maxX); // draw background - double lastEndY = 0; - double lastEndX = 0; - // draw data double diffY = maxY - minY; @@ -154,9 +151,8 @@ public class PointsWithLabelGraphSeries e float graphLeft = graphView.getGraphContentLeft(); float graphTop = graphView.getGraphContentTop(); - lastEndY = 0; - lastEndX = 0; - float firstX = 0; + float scaleX = (float) (graphWidth / diffX); + int i=0; while (values.hasNext()) { E value = values.next(); @@ -171,9 +167,6 @@ public class PointsWithLabelGraphSeries e double ratX = valX / diffX; double x = graphWidth * ratX; - double orgX = x; - double orgY = y; - // overdraw boolean overdraw = false; if (x > graphWidth) { // end right @@ -185,6 +178,14 @@ public class PointsWithLabelGraphSeries e if (y > graphHeight) { // end top overdraw = true; } + + long duration = value.getDuration(); + float endWithDuration = (float) (x + duration * scaleX + graphLeft + 1); + // cut off to graph start if needed + if (x < 0 && endWithDuration > 0) { + x = 0; + } + /* Fix a bug that continue to show the DOT after Y axis */ if(x < 0) { overdraw = true; @@ -195,8 +196,8 @@ public class PointsWithLabelGraphSeries e registerDataPoint(endX, endY, value); float xpluslength = 0; - if (value.getDuration() > 0) { - xpluslength = endX + Math.min((float) (value.getDuration() * graphWidth / diffX), graphLeft + graphWidth); + if (duration > 0) { + xpluslength = Math.min(endWithDuration, graphLeft + graphWidth); } // draw data point diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboFragment.java index 8419478725..7baea350b0 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboFragment.java @@ -6,7 +6,6 @@ import android.app.AlertDialog; import android.graphics.Color; import android.graphics.Typeface; import android.os.Bundle; -import android.text.Spanned; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -30,6 +29,7 @@ public class ComboFragment extends SubscriberFragment implements View.OnClickLis private TextView batteryView; private TextView reservoirView; private TextView lastConnectionView; + private TextView baseBasalRate; private TextView tempBasalText; private Button refreshButton; private Button alertsButton; @@ -46,6 +46,7 @@ public class ComboFragment extends SubscriberFragment implements View.OnClickLis batteryView = (TextView) view.findViewById(R.id.combo_pumpstate_battery); reservoirView = (TextView) view.findViewById(R.id.combo_insulinstate); lastConnectionView = (TextView) view.findViewById(R.id.combo_lastconnection); + baseBasalRate = (TextView) view.findViewById(R.id.combo_base_basal_rate); tempBasalText = (TextView) view.findViewById(R.id.combo_temp_basal); refreshButton = (Button) view.findViewById(R.id.combo_refresh_button); @@ -197,6 +198,9 @@ public class ComboFragment extends SubscriberFragment implements View.OnClickLis lastConnectionView.setTextColor(Color.WHITE); } + // base basal rate + baseBasalRate.setText(MainApp.sResources.getString(R.string.pump_basebasalrate, plugin.getBaseBasalRate())); + // TBR String tbrStr = ""; if (ps.tbrPercent != -1 && ps.tbrPercent != 100) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPlugin.java index bc27a3ebbc..32a91a7a73 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPlugin.java @@ -3,6 +3,9 @@ package info.nightscout.androidaps.plugins.PumpCombo; import android.os.SystemClock; import android.support.annotation.NonNull; +import com.crashlytics.android.answers.Answers; +import com.crashlytics.android.answers.CustomEvent; + import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -344,6 +347,8 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf } private synchronized void initializePump() { + Answers.getInstance().logCustom(new CustomEvent("ComboInit") + .putCustomAttribute("buildversion", BuildConfig.BUILDVERSION)); long maxWait = System.currentTimeMillis() + 15 * 1000; while (!ruffyScripter.isPumpAvailable()) { log.debug("Waiting for ruffy service to come up ..."); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_APS_Set_Event_History.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_APS_Set_Event_History.java index 4e559a77df..84ead83665 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_APS_Set_Event_History.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_APS_Set_Event_History.java @@ -9,6 +9,7 @@ import java.util.Calendar; import java.util.GregorianCalendar; import info.nightscout.androidaps.Config; +import info.nightscout.utils.DateUtil; public class DanaRS_Packet_APS_Set_Event_History extends DanaRS_Packet { private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_APS_Set_Event_History.class); @@ -30,6 +31,8 @@ public class DanaRS_Packet_APS_Set_Event_History extends DanaRS_Packet { this.time = time; this.param1 = param1; this.param2 = param2; + if (Config.logDanaMessageDetail) + log.debug("Set history entry: " + DateUtil.dateAndTimeString(time) + " type: " + type + " param1: " + param1 + " param2: " + param2); } @Override 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 f8d18a4d22..a892404929 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 @@ -164,6 +164,8 @@ public class BLEComm { scheduledDisconnection = null; if ((mBluetoothAdapter == null) || (mBluetoothGatt == null)) { + log.debug("disconnect not possible: (mBluetoothAdapter == null) " + (mBluetoothAdapter == null)); + log.debug("disconnect not possible: (mBluetoothGatt == null) " + (mBluetoothGatt == null)); return; } setCharacteristicNotification(getUARTReadBTGattChar(), false); @@ -257,6 +259,8 @@ public class BLEComm { log.debug("setCharacteristicNotification"); if ((mBluetoothAdapter == null) || (mBluetoothGatt == null)) { log.debug("BluetoothAdapter not initialized_ERROR"); + isConnecting = false; + isConnected = false; return; } mBluetoothGatt.setCharacteristicNotification(characteristic, enabled); @@ -266,6 +270,8 @@ public class BLEComm { log.debug("readCharacteristic"); if ((mBluetoothAdapter == null) || (mBluetoothGatt == null)) { log.debug("BluetoothAdapter not initialized_ERROR"); + isConnecting = false; + isConnected = false; return; } mBluetoothGatt.readCharacteristic(characteristic); @@ -274,6 +280,8 @@ public class BLEComm { public void writeCharacteristic_NO_RESPONSE(final BluetoothGattCharacteristic characteristic, final byte[] data) { if ((mBluetoothAdapter == null) || (mBluetoothGatt == null)) { log.debug("BluetoothAdapter not initialized_ERROR"); + isConnecting = false; + isConnected = false; return; } @@ -306,6 +314,8 @@ public class BLEComm { log.debug("getSupportedGattServices"); if ((mBluetoothAdapter == null) || (mBluetoothGatt == null)) { log.debug("BluetoothAdapter not initialized_ERROR"); + isConnecting = false; + isConnected = false; return null; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityAAPS/SensitivityAAPSPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityAAPS/SensitivityAAPSPlugin.java index f02cdd9371..f45d6cec40 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityAAPS/SensitivityAAPSPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityAAPS/SensitivityAAPSPlugin.java @@ -11,6 +11,7 @@ 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; @@ -191,8 +192,10 @@ public class SensitivityAAPSPlugin implements PluginBase, SensitivityInterface{ log.debug(ratioLimit); } - log.debug("Sensitivity to: " + new Date(toTime).toLocaleString() + " percentile: " + percentile + " ratio: " + ratio); - log.debug("Sensitivity to: deviations " + Arrays.toString(deviations)); + if (Config.logAutosensData) { + log.debug("Sensitivity to: " + new Date(toTime).toLocaleString() + " percentile: " + percentile + " ratio: " + ratio + " mealCOB: " + current.cob); + log.debug("Sensitivity to: deviations " + Arrays.toString(deviations)); + } AutosensResult output = new AutosensResult(); output.ratio = Round.roundTo(ratio, 0.01); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityOref0/SensitivityOref0Plugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityOref0/SensitivityOref0Plugin.java index 9aedf22d44..bf7d6ce8f5 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityOref0/SensitivityOref0Plugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityOref0/SensitivityOref0Plugin.java @@ -7,8 +7,10 @@ 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; @@ -118,7 +120,7 @@ public class SensitivityOref0Plugin implements PluginBase, SensitivityInterface return new AutosensResult(); } - AutosensData current = IobCobCalculatorPlugin.getLastAutosensData("SensitivityOref0"); // this is running inside lock already + AutosensData current = IobCobCalculatorPlugin.getAutosensData(toTime); // this is running inside lock already if (current == null) { log.debug("No current autosens data available"); return new AutosensResult(); @@ -199,10 +201,8 @@ public class SensitivityOref0Plugin implements PluginBase, SensitivityInterface log.debug(ratioLimit); } - double newisf = Math.round(Profile.toMgdl(sens, profile.getUnits()) / ratio); - if (ratio != 1) { - log.debug("ISF adjusted from " + Profile.toMgdl(sens, profile.getUnits()) + " to " + newisf); - } + if (Config.logAutosensData) + log.debug("Sensitivity to: " + new Date(toTime).toLocaleString() + " ratio: " + ratio + " mealCOB: " + current.cob); AutosensResult output = new AutosensResult(); output.ratio = Round.roundTo(ratio, 0.01); 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 046cd056fa..5f9e996a8a 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 @@ -217,7 +217,7 @@ public class SensitivityWeightedAveragePlugin implements PluginBase, Sensitivity } if (Config.logAutosensData) - log.debug("Sensitivity to: " + new Date(toTime).toLocaleString() + " weightedaverage: " + average + " ratio: " + ratio); + log.debug("Sensitivity to: " + new Date(toTime).toLocaleString() + " weightedaverage: " + average + " ratio: " + ratio + " mealCOB: " + current.cob); AutosensResult output = new AutosensResult(); output.ratio = Round.roundTo(ratio, 0.01); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsFragment.java index 6fcbcfe951..b10ad96697 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsFragment.java @@ -20,6 +20,7 @@ import info.nightscout.androidaps.events.EventExtendedBolusChange; import info.nightscout.androidaps.plugins.Common.SubscriberFragment; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.Treatments.fragments.TreatmentsBolusFragment; +import info.nightscout.androidaps.plugins.Treatments.fragments.TreatmentsCareportalFragment; import info.nightscout.androidaps.plugins.Treatments.fragments.TreatmentsExtendedBolusesFragment; import info.nightscout.androidaps.plugins.Treatments.fragments.TreatmentsProfileSwitchFragment; import info.nightscout.androidaps.plugins.Treatments.fragments.TreatmentsTempTargetFragment; @@ -33,6 +34,7 @@ public class TreatmentsFragment extends SubscriberFragment implements View.OnCli TextView tempBasalsTab; TextView tempTargetTab; TextView profileSwitchTab; + TextView careportalTab; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, @@ -45,11 +47,13 @@ public class TreatmentsFragment extends SubscriberFragment implements View.OnCli tempBasalsTab = (TextView) view.findViewById(R.id.treatments_tempbasals); tempTargetTab = (TextView) view.findViewById(R.id.treatments_temptargets); profileSwitchTab = (TextView) view.findViewById(R.id.treatments_profileswitches); + careportalTab = (TextView) view.findViewById(R.id.treatments_careportal); treatmentsTab.setOnClickListener(this); extendedBolusesTab.setOnClickListener(this); tempBasalsTab.setOnClickListener(this); tempTargetTab.setOnClickListener(this); profileSwitchTab.setOnClickListener(this); + careportalTab.setOnClickListener(this); setFragment(new TreatmentsBolusFragment()); setBackgroundColorOnSelected(treatmentsTab); @@ -87,6 +91,10 @@ public class TreatmentsFragment extends SubscriberFragment implements View.OnCli setFragment(new TreatmentsProfileSwitchFragment()); setBackgroundColorOnSelected(profileSwitchTab); break; + case R.id.treatments_careportal: + setFragment(new TreatmentsCareportalFragment()); + setBackgroundColorOnSelected(careportalTab); + break; } } @@ -104,6 +112,7 @@ public class TreatmentsFragment extends SubscriberFragment implements View.OnCli tempBasalsTab.setBackgroundColor(MainApp.sResources.getColor(R.color.defaultbackground)); tempTargetTab.setBackgroundColor(MainApp.sResources.getColor(R.color.defaultbackground)); profileSwitchTab.setBackgroundColor(MainApp.sResources.getColor(R.color.defaultbackground)); + careportalTab.setBackgroundColor(MainApp.sResources.getColor(R.color.defaultbackground)); selected.setBackgroundColor(MainApp.sResources.getColor(R.color.tabBgColorSelected)); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsCareportalFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsCareportalFragment.java new file mode 100644 index 0000000000..7218198b43 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsCareportalFragment.java @@ -0,0 +1,192 @@ +package info.nightscout.androidaps.plugins.Treatments.fragments; + +import android.app.Activity; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.graphics.Paint; +import android.os.Bundle; +import android.support.v7.app.AlertDialog; +import android.support.v7.widget.CardView; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.TextView; + +import com.squareup.otto.Subscribe; + +import java.util.List; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.Services.Intents; +import info.nightscout.androidaps.db.CareportalEvent; +import info.nightscout.androidaps.events.EventCareportalEventChange; +import info.nightscout.androidaps.plugins.Common.SubscriberFragment; +import info.nightscout.androidaps.plugins.NSClientInternal.UploadQueue; +import info.nightscout.utils.DateUtil; +import info.nightscout.utils.NSUpload; +import info.nightscout.utils.SP; +import info.nightscout.utils.Translator; + +/** + * Created by mike on 13/01/17. + */ + +public class TreatmentsCareportalFragment extends SubscriberFragment implements View.OnClickListener { + + RecyclerView recyclerView; + LinearLayoutManager llm; + Button refreshFromNS; + + Context context; + + public class RecyclerViewAdapter extends RecyclerView.Adapter { + + List careportalEventList; + + RecyclerViewAdapter(List careportalEventList) { + this.careportalEventList = careportalEventList; + } + + @Override + public CareportalEventsViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { + View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.treatments_careportal_item, viewGroup, false); + CareportalEventsViewHolder CareportalEventsViewHolder = new CareportalEventsViewHolder(v); + return CareportalEventsViewHolder; + } + + @Override + public void onBindViewHolder(CareportalEventsViewHolder holder, int position) { + CareportalEvent careportalEvent = careportalEventList.get(position); + holder.ns.setVisibility(NSUpload.isIdValid(careportalEvent._id) ? View.VISIBLE : View.GONE); + holder.date.setText(DateUtil.dateAndTimeString(careportalEvent.date)); + holder.note.setText(careportalEvent.getNotes()); + holder.type.setText(Translator.translate(careportalEvent.eventType)); + holder.remove.setTag(careportalEvent); + } + + @Override + public int getItemCount() { + return careportalEventList.size(); + } + + @Override + public void onAttachedToRecyclerView(RecyclerView recyclerView) { + super.onAttachedToRecyclerView(recyclerView); + } + + public class CareportalEventsViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { + CardView cv; + TextView date; + TextView type; + TextView note; + TextView remove; + TextView ns; + + CareportalEventsViewHolder(View itemView) { + super(itemView); + cv = (CardView) itemView.findViewById(R.id.careportal_cardview); + date = (TextView) itemView.findViewById(R.id.careportal_date); + type = (TextView) itemView.findViewById(R.id.careportal_type); + note = (TextView) itemView.findViewById(R.id.careportal_note); + ns = (TextView) itemView.findViewById(R.id.ns_sign); + remove = (TextView) itemView.findViewById(R.id.careportal_remove); + remove.setOnClickListener(this); + remove.setPaintFlags(remove.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG); + } + + @Override + public void onClick(View v) { + final CareportalEvent careportalEvent = (CareportalEvent) v.getTag(); + switch (v.getId()) { + case R.id.careportal_remove: + AlertDialog.Builder builder = new AlertDialog.Builder(context); + builder.setTitle(MainApp.sResources.getString(R.string.confirmation)); + builder.setMessage(MainApp.sResources.getString(R.string.removerecord) + "\n" + DateUtil.dateAndTimeString(careportalEvent.date)); + builder.setPositiveButton(MainApp.sResources.getString(R.string.ok), new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + final String _id = careportalEvent._id; + if (NSUpload.isIdValid(_id)) { + NSUpload.removeCareportalEntryFromNS(_id); + } else { + UploadQueue.removeID("dbAdd", _id); + } + MainApp.getDbHelper().delete(careportalEvent); + } + }); + builder.setNegativeButton(MainApp.sResources.getString(R.string.cancel), null); + builder.show(); + break; + } + } + } + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.treatments_careportal_fragment, container, false); + + recyclerView = (RecyclerView) view.findViewById(R.id.careportal_recyclerview); + recyclerView.setHasFixedSize(true); + llm = new LinearLayoutManager(view.getContext()); + recyclerView.setLayoutManager(llm); + + RecyclerViewAdapter adapter = new RecyclerViewAdapter(MainApp.getDbHelper().getCareportalEventsFromTime(false)); + recyclerView.setAdapter(adapter); + + refreshFromNS = (Button) view.findViewById(R.id.careportal_refreshfromnightscout); + refreshFromNS.setOnClickListener(this); + + context = getContext(); + + boolean nsUploadOnly = SP.getBoolean(R.string.key_ns_upload_only, false); + if (nsUploadOnly) + refreshFromNS.setVisibility(View.GONE); + + updateGUI(); + return view; + } + + @Override + public void onClick(View view) { + switch (view.getId()) { + case R.id.careportal_refreshfromnightscout: + AlertDialog.Builder builder = new AlertDialog.Builder(this.getContext()); + builder.setTitle(this.getContext().getString(R.string.confirmation)); + builder.setMessage(this.getContext().getString(R.string.refresheventsfromnightscout) + " ?"); + builder.setPositiveButton(this.getContext().getString(R.string.ok), new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + MainApp.getDbHelper().resetCareportalEvents(); + Intent restartNSClient = new Intent(Intents.ACTION_RESTART); + MainApp.instance().getApplicationContext().sendBroadcast(restartNSClient); + } + }); + builder.setNegativeButton(this.getContext().getString(R.string.cancel), null); + builder.show(); + break; + } + + } + + @Subscribe + public void onStatusEvent(final EventCareportalEventChange ev) { + updateGUI(); + } + + @Override + protected void updateGUI() { + Activity activity = getActivity(); + if (activity != null) + activity.runOnUiThread(new Runnable() { + @Override + public void run() { + recyclerView.swapAdapter(new RecyclerViewAdapter(MainApp.getDbHelper().getCareportalEventsFromTime(false)), false); + } + }); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Wear/wearintegration/WatchUpdaterService.java b/app/src/main/java/info/nightscout/androidaps/plugins/Wear/wearintegration/WatchUpdaterService.java index 65b5a2557d..d7bda4781b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Wear/wearintegration/WatchUpdaterService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Wear/wearintegration/WatchUpdaterService.java @@ -637,6 +637,11 @@ public class WatchUpdaterService extends WearableListenerService implements private String generateBasalString(TreatmentsInterface treatmentsInterface) { String basalStringResult; + + Profile profile = MainApp.getConfigBuilder().getProfile(); + if (profile == null) + return ""; + TemporaryBasal activeTemp = treatmentsInterface.getTempBasalFromHistory(System.currentTimeMillis()); if (activeTemp != null) { basalStringResult = activeTemp.toStringShort(); @@ -644,7 +649,7 @@ public class WatchUpdaterService extends WearableListenerService implements if (SP.getBoolean(R.string.key_danar_visualizeextendedaspercentage, false)) { basalStringResult = "100%"; } else { - basalStringResult = DecimalFormatter.to2Decimal(MainApp.getConfigBuilder().getProfile().getBasal()) + "U/h"; + basalStringResult = DecimalFormatter.to2Decimal(profile.getBasal()) + "U/h"; } } return basalStringResult; diff --git a/app/src/main/java/info/nightscout/androidaps/queue/CommandQueue.java b/app/src/main/java/info/nightscout/androidaps/queue/CommandQueue.java index a8b122f1ab..d7d8457a27 100644 --- a/app/src/main/java/info/nightscout/androidaps/queue/CommandQueue.java +++ b/app/src/main/java/info/nightscout/androidaps/queue/CommandQueue.java @@ -147,8 +147,6 @@ public class CommandQueue { public static void independentConnect(String reason, Callback callback) { CommandQueue tempCommandQueue = new CommandQueue(); tempCommandQueue.readStatus(reason, callback); - QueueThread tempThread = new QueueThread(tempCommandQueue); - tempThread.start(); } // returns true if command is queued diff --git a/app/src/main/java/info/nightscout/androidaps/queue/QueueThread.java b/app/src/main/java/info/nightscout/androidaps/queue/QueueThread.java index 17828645ad..b098ec6a98 100644 --- a/app/src/main/java/info/nightscout/androidaps/queue/QueueThread.java +++ b/app/src/main/java/info/nightscout/androidaps/queue/QueueThread.java @@ -16,6 +16,8 @@ import info.nightscout.androidaps.events.EventPumpStatusChanged; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.Overview.events.EventDismissBolusprogressIfRunning; +import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.Overview.notifications.Notification; import info.nightscout.androidaps.queue.events.EventQueueChanged; import info.nightscout.utils.SP; @@ -34,7 +36,7 @@ public class QueueThread extends Thread { private PowerManager.WakeLock mWakeLock; public QueueThread(CommandQueue queue) { - super(QueueThread.class.toString()); + super(); this.queue = queue; PowerManager powerManager = (PowerManager) MainApp.instance().getApplicationContext().getSystemService(Context.POWER_SERVICE); @@ -51,12 +53,6 @@ public class QueueThread extends Thread { while (true) { PumpInterface pump = ConfigBuilderPlugin.getActivePump(); long secondsElapsed = (System.currentTimeMillis() - connectionStartTime) / 1000; - if (pump.isConnecting()) { - log.debug("QUEUE: connecting " + secondsElapsed); - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.CONNECTING, (int) secondsElapsed)); - SystemClock.sleep(1000); - continue; - } if (!pump.isConnected() && secondsElapsed > Constants.PUMP_MAX_CONNECTION_TIME_IN_SECONDS) { MainApp.bus().post(new EventDismissBolusprogressIfRunning(null)); @@ -73,19 +69,37 @@ public class QueueThread extends Thread { //write time SP.putLong(R.string.key_btwatchdog_lastbark, System.currentTimeMillis()); //toggle BT + pump.stopConnecting(); + pump.disconnect("watchdog"); + SystemClock.sleep(1000); BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); mBluetoothAdapter.disable(); SystemClock.sleep(1000); mBluetoothAdapter.enable(); SystemClock.sleep(1000); //start over again once after watchdog barked + //Notification notification = new Notification(Notification.OLD_NSCLIENT, "Watchdog", Notification.URGENT); + //MainApp.bus().post(new EventNewNotification(notification)); connectionStartTime = lastCommandTime = System.currentTimeMillis(); + pump.connect("watchdog"); } else { queue.clear(); + log.debug("QUEUE: no connection possible"); + MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING)); + pump.disconnect("Queue empty"); + MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTED)); return; } } + if (pump.isConnecting()) { + log.debug("QUEUE: connecting " + secondsElapsed); + MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.CONNECTING, (int) secondsElapsed)); + SystemClock.sleep(1000); + continue; + } + + if (!pump.isConnected()) { log.debug("QUEUE: connect"); MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.CONNECTING, (int) secondsElapsed)); diff --git a/app/src/main/res/layout/combopump_fragment.xml b/app/src/main/res/layout/combopump_fragment.xml index 7fb016bb83..54e3e2f3d1 100644 --- a/app/src/main/res/layout/combopump_fragment.xml +++ b/app/src/main/res/layout/combopump_fragment.xml @@ -283,6 +283,51 @@ --> + + + + + + + + + + + + - + android:buttonTint="@color/prediction" /> + android:buttonTint="@color/basal" /> + android:buttonTint="@color/iob" /> + android:buttonTint="@color/cob" /> + android:buttonTint="@color/deviations" /> + android:buttonTint="@color/prediction" /> + android:buttonTint="@color/basal" /> + android:buttonTint="@color/iob" /> + android:buttonTint="@color/cob" /> + android:buttonTint="@color/deviations" /> + android:buttonTint="@color/prediction" /> + android:buttonTint="@color/basal" /> + android:buttonTint="@color/iob" /> + android:buttonTint="@color/cob" /> + android:buttonTint="@color/deviations" /> + + + +