diff --git a/.travis.yml b/.travis.yml index 1d620e70b2..5c6309f817 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,7 +18,17 @@ before_install: script: # Unit Test - - ./gradlew -Pcoverage test jacocoTestReport + - ./gradlew -Pcoverage testFullDebugUnitTest jacocoTestFullDebugUnitTestReport after_success: - - bash <(curl -s https://codecov.io/bash) \ No newline at end of file + - bash <(curl -s https://codecov.io/bash) + +before_cache: + - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock + - rm -fr $HOME/.gradle/caches/*/plugin-resolution/ + +cache: + directories: + - $HOME/.gradle/caches/ + - $HOME/.gradle/wrapper/ + - $HOME/.android/build-cache \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 080422af46..15015ca255 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -15,8 +15,7 @@ apply plugin: "jacoco-android" apply plugin: 'com.jakewharton.butterknife' ext { - supportLibraryVersion = "27.0.2" - sdkBuildVersion = "27.0.3" + supportLibraryVersion = "27.1.0" ormLiteVersion = "4.46" powermockVersion = "1.7.3" dexmakerVersion = "1.2" @@ -57,15 +56,14 @@ tasks.matching {it instanceof Test}.all { android { compileSdkVersion 27 - buildToolsVersion "${sdkBuildVersion}" defaultConfig { applicationId "info.nightscout.androidaps" minSdkVersion 21 - targetSdkVersion 27 + targetSdkVersion 25 multiDexEnabled true versionCode 1500 - version "1.60c-dev" + version "1.60d-dev" buildConfigField "String", "VERSION", '"' + version + '"' buildConfigField "String", "BUILDVERSION", generateGitBuild() testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" @@ -78,7 +76,7 @@ android { // TODO remove once wear dependency com.google.android.gms:play-services-wearable:7.3.0 // has been upgraded (requiring significant code changes), which currently fails release // build with a deprecation warning - // abortOnError false + abortOnError false // (disabled entirely to avoid reports on the error, which would still be displayed // and it's easy to overlook that it's ignored) checkReleaseBuilds false @@ -183,7 +181,7 @@ dependencies { implementation("com.crashlytics.sdk.android:answers:1.3.12@aar") { transitive = true; } - libs 'MilosKozak:danars-support-lib:master@zip' + libs "MilosKozak:danars-support-lib:master@zip" implementation "com.android.support:appcompat-v7:${supportLibraryVersion}" implementation "com.android.support:support-v4:${supportLibraryVersion}" diff --git a/app/libs/sightparser-release.aar b/app/libs/sightparser-release.aar index 20de889426..4e474e608e 100644 Binary files a/app/libs/sightparser-release.aar and b/app/libs/sightparser-release.aar differ diff --git a/app/src/main/java/info/nightscout/androidaps/Config.java b/app/src/main/java/info/nightscout/androidaps/Config.java index babaccb2b1..ff7b935355 100644 --- a/app/src/main/java/info/nightscout/androidaps/Config.java +++ b/app/src/main/java/info/nightscout/androidaps/Config.java @@ -32,7 +32,6 @@ public class Config { public static final boolean logPumpComm = true; public static final boolean logPrefsChange = true; public static final boolean logConfigBuilder = true; - public static final boolean logConstraintsChanges = true; public static final boolean logNSUpload = true; public static final boolean logPumpActions = true; public static final boolean logCongigBuilderActions = true; @@ -43,6 +42,4 @@ public class Config { public static final boolean logDanaBTComm = true; public static boolean logDanaMessageDetail = true; public static final boolean logDanaSerialEngine = true; - - public static final boolean enableComboBetaFeatures = false; } diff --git a/app/src/main/java/info/nightscout/androidaps/Constants.java b/app/src/main/java/info/nightscout/androidaps/Constants.java index cd645abd9a..aeb4977584 100644 --- a/app/src/main/java/info/nightscout/androidaps/Constants.java +++ b/app/src/main/java/info/nightscout/androidaps/Constants.java @@ -41,10 +41,10 @@ public class Constants { // Temp targets public static final int defaultActivityTTDuration = 90; // min - public static final double defaultActivityTTmgdl = 90d; + public static final double defaultActivityTTmgdl = 140d; public static final double defaultActivityTTmmol = 8d; public static final int defaultEatingSoonTTDuration = 45; // min - public static final double defaultEatingSoonTTmgdl = 140d; + public static final double defaultEatingSoonTTmgdl = 90d; public static final double defaultEatingSoonTTmmol = 5d; public static final int defaultHypoTTDuration = 30; // min public static final double defaultHypoTTmgdl = 120d; diff --git a/app/src/main/java/info/nightscout/androidaps/MainActivity.java b/app/src/main/java/info/nightscout/androidaps/MainActivity.java index 0ae1e48775..440024f853 100644 --- a/app/src/main/java/info/nightscout/androidaps/MainActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/MainActivity.java @@ -48,6 +48,7 @@ import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.Food.FoodPlugin; import info.nightscout.androidaps.plugins.Overview.events.EventSetWakeLock; +import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; import info.nightscout.androidaps.tabs.SlidingTabLayout; import info.nightscout.androidaps.tabs.TabPageAdapter; import info.nightscout.utils.ImportExportPrefs; @@ -378,7 +379,8 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe MainApp.getDbHelper().resetDatabases(); // should be handled by Plugin-Interface and // additional service interface and plugin registry - MainApp.getSpecificPlugin(FoodPlugin.class).getService().resetFood(); + FoodPlugin.getPlugin().getService().resetFood(); + TreatmentsPlugin.getPlugin().getService().resetTreatments(); } }) .create() @@ -403,7 +405,8 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe else builder.setIcon(R.mipmap.blueowl); String message = "Build: " + BuildConfig.BUILDVERSION + "\n"; - message += MainApp.sResources.getString(R.string.configbuilder_nightscoutversion_label) + " " + ConfigBuilderPlugin.nightscoutVersionName; + message += "Flavor: " + BuildConfig.FLAVOR + BuildConfig.BUILD_TYPE + "\n"; + message += getString(R.string.configbuilder_nightscoutversion_label) + " " + ConfigBuilderPlugin.nightscoutVersionName; if (MainApp.engineeringMode) message += "\n" + MainApp.gs(R.string.engineering_mode_enabled); message += getString(R.string.about_link_urls); diff --git a/app/src/main/java/info/nightscout/androidaps/MainApp.java b/app/src/main/java/info/nightscout/androidaps/MainApp.java index d925330484..b5a1878160 100644 --- a/app/src/main/java/info/nightscout/androidaps/MainApp.java +++ b/app/src/main/java/info/nightscout/androidaps/MainApp.java @@ -212,11 +212,6 @@ public class MainApp extends Application { startKeepAliveService(); }).start(); } - - if (!isEngineeringModeOrRelease()) { - Notification n = new Notification(Notification.TOAST_ALARM, gs(R.string.closed_loop_disabled_on_dev_branch), Notification.NORMAL); - bus().post(new EventNewNotification(n)); - } } private void registerLocalBroadcastReceiver() { 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 7a0193d65c..6a771fc4a1 100644 --- a/app/src/main/java/info/nightscout/androidaps/Services/DataService.java +++ b/app/src/main/java/info/nightscout/androidaps/Services/DataService.java @@ -19,6 +19,7 @@ import info.nightscout.androidaps.data.ProfileStore; import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.db.CareportalEvent; import info.nightscout.androidaps.events.EventNsFood; +import info.nightscout.androidaps.events.EventNsTreatment; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConstraintsObjectives.ObjectivesPlugin; import info.nightscout.androidaps.plugins.NSClientInternal.data.NSDeviceStatus; @@ -40,6 +41,7 @@ import info.nightscout.androidaps.plugins.Source.SourceNSClientPlugin; import info.nightscout.androidaps.plugins.Source.SourceXdripPlugin; import info.nightscout.androidaps.receivers.DataReceiver; import info.nightscout.utils.BundleLogger; +import info.nightscout.utils.JsonHelper; import info.nightscout.utils.NSUpload; import info.nightscout.utils.SP; @@ -382,19 +384,18 @@ public class DataService extends IntentService { if (intent.getAction().equals(Intents.ACTION_NEW_TREATMENT) || intent.getAction().equals(Intents.ACTION_CHANGED_TREATMENT)) { try { if (bundles.containsKey("treatment")) { - String trstring = bundles.getString("treatment"); - handleAddChangeDataFromNS(trstring); + JSONObject json = new JSONObject(bundles.getString("treatment")); + handleTreatmentFromNS(json, intent); } if (bundles.containsKey("treatments")) { String trstring = bundles.getString("treatments"); JSONArray jsonArray = new JSONArray(trstring); for (int i = 0; i < jsonArray.length(); i++) { - JSONObject trJson = jsonArray.getJSONObject(i); - String trstr = trJson.toString(); - handleAddChangeDataFromNS(trstr); + JSONObject json = jsonArray.getJSONObject(i); + handleTreatmentFromNS(json, intent); } } - } catch (Exception e) { + } catch (JSONException e) { log.error("Unhandled exception", e); } } @@ -403,21 +404,19 @@ public class DataService extends IntentService { try { if (bundles.containsKey("treatment")) { String trstring = bundles.getString("treatment"); - JSONObject trJson = new JSONObject(trstring); - String _id = trJson.getString("_id"); - handleRemovedRecordFromNS(_id); + JSONObject json = new JSONObject(trstring); + handleTreatmentFromNS(json); } if (bundles.containsKey("treatments")) { String trstring = bundles.getString("treatments"); JSONArray jsonArray = new JSONArray(trstring); for (int i = 0; i < jsonArray.length(); i++) { - JSONObject trJson = jsonArray.getJSONObject(i); - String _id = trJson.getString("_id"); - handleRemovedRecordFromNS(_id); + JSONObject json = jsonArray.getJSONObject(i); + handleTreatmentFromNS(json); } } - } catch (Exception e) { + } catch (JSONException e) { log.error("Unhandled exception", e); } } @@ -489,8 +488,12 @@ public class DataService extends IntentService { } } - private void handleRemovedRecordFromNS(String _id) { - MainApp.getDbHelper().deleteTreatmentById(_id); + private void handleTreatmentFromNS(JSONObject json) { + // new DB model + EventNsTreatment evtTreatment = new EventNsTreatment(EventNsTreatment.REMOVE, json); + MainApp.bus().post(evtTreatment); + // old DB model + String _id = JsonHelper.safeGetString(json, "_id"); MainApp.getDbHelper().deleteTempTargetById(_id); MainApp.getDbHelper().deleteTempBasalById(_id); MainApp.getDbHelper().deleteExtendedBolusById(_id); @@ -498,86 +501,53 @@ public class DataService extends IntentService { MainApp.getDbHelper().deleteProfileSwitchById(_id); } - private void handleAddChangeDataFromNS(String trstring) throws JSONException { - JSONObject trJson = new JSONObject(trstring); - handleDanaRHistoryRecords(trJson); // update record _id in history - handleAddChangeTempTargetRecord(trJson); - handleAddChangeTempBasalRecord(trJson); - handleAddChangeExtendedBolusRecord(trJson); - handleAddChangeCareportalEventRecord(trJson); - handleAddChangeTreatmentRecord(trJson); - handleAddChangeProfileSwitchRecord(trJson); - } - - public void handleDanaRHistoryRecords(JSONObject trJson) { - if (trJson.has(DanaRNSHistorySync.DANARSIGNATURE)) { - MainApp.getDbHelper().updateDanaRHistoryRecordId(trJson); - } - } - - public void handleAddChangeTreatmentRecord(JSONObject trJson) throws JSONException { - if (trJson.has("insulin") || trJson.has("carbs")) { - MainApp.getDbHelper().createTreatmentFromJsonIfNotExists(trJson); - return; - } - } - - public void handleAddChangeTempTargetRecord(JSONObject trJson) throws JSONException { - if (trJson.has("eventType") && trJson.getString("eventType").equals(CareportalEvent.TEMPORARYTARGET)) { - MainApp.getDbHelper().createTemptargetFromJsonIfNotExists(trJson); - } - } - - public void handleAddChangeTempBasalRecord(JSONObject trJson) throws JSONException { - if (trJson.has("eventType") && trJson.getString("eventType").equals(CareportalEvent.TEMPBASAL)) { - MainApp.getDbHelper().createTempBasalFromJsonIfNotExists(trJson); - } - } - - public void handleAddChangeExtendedBolusRecord(JSONObject trJson) throws JSONException { - if (trJson.has("eventType") && trJson.getString("eventType").equals(CareportalEvent.COMBOBOLUS)) { - MainApp.getDbHelper().createExtendedBolusFromJsonIfNotExists(trJson); - } - } - - public void handleAddChangeCareportalEventRecord(JSONObject trJson) throws JSONException { - if (trJson.has("insulin") && trJson.getDouble("insulin") > 0) - return; - if (trJson.has("carbs") && trJson.getDouble("carbs") > 0) - return; - if (trJson.has("eventType") && ( - trJson.getString("eventType").equals(CareportalEvent.SITECHANGE) || - trJson.getString("eventType").equals(CareportalEvent.INSULINCHANGE) || - trJson.getString("eventType").equals(CareportalEvent.SENSORCHANGE) || - trJson.getString("eventType").equals(CareportalEvent.BGCHECK) || - trJson.getString("eventType").equals(CareportalEvent.NOTE) || - trJson.getString("eventType").equals(CareportalEvent.NONE) || - trJson.getString("eventType").equals(CareportalEvent.ANNOUNCEMENT) || - trJson.getString("eventType").equals(CareportalEvent.QUESTION) || - trJson.getString("eventType").equals(CareportalEvent.EXERCISE) || - trJson.getString("eventType").equals(CareportalEvent.OPENAPSOFFLINE) || - trJson.getString("eventType").equals(CareportalEvent.PUMPBATTERYCHANGE) - )) { - MainApp.getDbHelper().createCareportalEventFromJsonIfNotExists(trJson); + private void handleTreatmentFromNS(JSONObject json, Intent intent) throws JSONException { + // new DB model + int mode = Intents.ACTION_NEW_TREATMENT.equals(intent.getAction()) ? EventNsTreatment.ADD : EventNsTreatment.UPDATE; + double insulin = JsonHelper.safeGetDouble(json, "insulin"); + double carbs = JsonHelper.safeGetDouble(json, "carbs"); + String eventType = JsonHelper.safeGetString(json, "eventType"); + if (insulin > 0 || carbs > 0) { + EventNsTreatment evtTreatment = new EventNsTreatment(mode, json); + MainApp.bus().post(evtTreatment); + } else if (json.has(DanaRNSHistorySync.DANARSIGNATURE)) { + // old DB model + MainApp.getDbHelper().updateDanaRHistoryRecordId(json); + } else if (eventType.equals(CareportalEvent.TEMPORARYTARGET)) { + MainApp.getDbHelper().createTemptargetFromJsonIfNotExists(json); + } else if (eventType.equals(CareportalEvent.TEMPBASAL)) { + MainApp.getDbHelper().createTempBasalFromJsonIfNotExists(json); + } else if (eventType.equals(CareportalEvent.COMBOBOLUS)) { + MainApp.getDbHelper().createExtendedBolusFromJsonIfNotExists(json); + } else if (eventType.equals(CareportalEvent.PROFILESWITCH)) { + MainApp.getDbHelper().createProfileSwitchFromJsonIfNotExists(json); + } else if (eventType.equals(CareportalEvent.SITECHANGE) || + eventType.equals(CareportalEvent.INSULINCHANGE) || + eventType.equals(CareportalEvent.SENSORCHANGE) || + eventType.equals(CareportalEvent.BGCHECK) || + eventType.equals(CareportalEvent.NOTE) || + eventType.equals(CareportalEvent.NONE) || + eventType.equals(CareportalEvent.ANNOUNCEMENT) || + eventType.equals(CareportalEvent.QUESTION) || + eventType.equals(CareportalEvent.EXERCISE) || + eventType.equals(CareportalEvent.OPENAPSOFFLINE) || + eventType.equals(CareportalEvent.PUMPBATTERYCHANGE)) { + MainApp.getDbHelper().createCareportalEventFromJsonIfNotExists(json); } - if (trJson.has("eventType") && trJson.getString("eventType").equals(CareportalEvent.ANNOUNCEMENT)) { - long date = trJson.getLong("mills"); + if (eventType.equals(CareportalEvent.ANNOUNCEMENT)) { + long date = JsonHelper.safeGetLong(json,"mills"); long now = System.currentTimeMillis(); - if (date > now - 15 * 60 * 1000L && trJson.has("notes") - && !(trJson.has("enteredBy") && trJson.getString("enteredBy").equals(SP.getString("careportal_enteredby", "AndroidAPS")))) { - Notification announcement = new Notification(Notification.NSANNOUNCEMENT, trJson.getString("notes"), Notification.ANNOUNCEMENT, 60); + String enteredBy = JsonHelper.safeGetString(json, "enteredBy", ""); + String notes = JsonHelper.safeGetString(json, "notes", ""); + if (date > now - 15 * 60 * 1000L && !notes.isEmpty() + && !enteredBy.equals(SP.getString("careportal_enteredby", "AndroidAPS"))) { + Notification announcement = new Notification(Notification.NSANNOUNCEMENT, notes, Notification.ANNOUNCEMENT, 60); MainApp.bus().post(new EventNewNotification(announcement)); } } } - public void handleAddChangeProfileSwitchRecord(JSONObject trJson) throws JSONException { - if (trJson.has("eventType") && trJson.getString("eventType").equals(CareportalEvent.PROFILESWITCH)) { - MainApp.getDbHelper().createProfileSwitchFromJsonIfNotExists(trJson); - } - } - private void handleNewSMS(Intent intent) { Bundle bundle = intent.getExtras(); if (bundle == null) return; diff --git a/app/src/main/java/info/nightscout/androidaps/TDDStatsActivity.java b/app/src/main/java/info/nightscout/androidaps/TDDStatsActivity.java index 48955ad149..369b2f42b5 100644 --- a/app/src/main/java/info/nightscout/androidaps/TDDStatsActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/TDDStatsActivity.java @@ -129,6 +129,9 @@ public class TDDStatsActivity extends Activity { } totalBaseBasal.setText(TBB); + if (!ConfigBuilderPlugin.getActivePump().getPumpDescription().needsManualTDDLoad) + reloadButton.setVisibility(View.GONE); + // stats table tl = (TableLayout) findViewById(R.id.main_table); TableRow tr_head = new TableRow(this); @@ -436,7 +439,7 @@ public class TDDStatsActivity extends Activity { TableLayout.LayoutParams.WRAP_CONTENT)); } - if (isOldData(historyList)) { + if (isOldData(historyList) && ConfigBuilderPlugin.getActivePump().getPumpDescription().needsManualTDDLoad) { statsMessage.setVisibility(View.VISIBLE); statsMessage.setText(getString(R.string.danar_stats_olddata_Message)); diff --git a/app/src/main/java/info/nightscout/androidaps/data/IobTotal.java b/app/src/main/java/info/nightscout/androidaps/data/IobTotal.java index 889d842ccf..a87b77be07 100644 --- a/app/src/main/java/info/nightscout/androidaps/data/IobTotal.java +++ b/app/src/main/java/info/nightscout/androidaps/data/IobTotal.java @@ -24,9 +24,6 @@ public class IobTotal { // oref1 public long lastBolusTime; - public long lastTempDate; - public int lastTempDuration; - public double lastTempRate; public IobTotal iobWithZeroTemp; public double netInsulin = 0d; // for calculations from temp basals only @@ -76,9 +73,6 @@ public class IobTotal { result.netInsulin = basalIob.netInsulin + bolusIOB.netInsulin; result.extendedBolusInsulin = basalIob.extendedBolusInsulin + bolusIOB.extendedBolusInsulin; result.lastBolusTime = bolusIOB.lastBolusTime; - result.lastTempDate = basalIob.lastTempDate; - result.lastTempRate = basalIob.lastTempRate; - result.lastTempDuration = basalIob.lastTempDuration; result.iobWithZeroTemp = basalIob.iobWithZeroTemp; return result; } diff --git a/app/src/main/java/info/nightscout/androidaps/data/QuickWizard.java b/app/src/main/java/info/nightscout/androidaps/data/QuickWizard.java index 587d7f86a2..25c768cdda 100644 --- a/app/src/main/java/info/nightscout/androidaps/data/QuickWizard.java +++ b/app/src/main/java/info/nightscout/androidaps/data/QuickWizard.java @@ -10,6 +10,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.MainApp; +import info.nightscout.utils.SP; /** * Created by mike on 12.10.2016. @@ -25,10 +26,7 @@ public class QuickWizard { } public void save() { - SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext()); - SharedPreferences.Editor editor = preferences.edit(); - editor.putString("QuickWizard", storage.toString()); - editor.apply(); + SP.putString("QuickWizard", storage.toString()); } public int size() { 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 e2e4e6d639..b0f69144c5 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/CareportalEvent.java +++ b/app/src/main/java/info/nightscout/androidaps/db/CareportalEvent.java @@ -98,6 +98,14 @@ public class CareportalEvent implements DataPointWithLabelInterface { return diff.get(TimeUnit.DAYS) + " " + MainApp.sResources.getString(R.string.days) + " " + diff.get(TimeUnit.HOURS) + " " + MainApp.sResources.getString(R.string.hours); } + public boolean isOlderThan(double hours) { + Map diff = computeDiff(date, System.currentTimeMillis()); + if(diff.get(TimeUnit.DAYS)*24 + diff.get(TimeUnit.HOURS) > hours) + return true; + else + return false; + } + public String log() { return "CareportalEvent{" + "date= " + date + @@ -259,4 +267,5 @@ public class CareportalEvent implements DataPointWithLabelInterface { public int getSecondColor() { return 0; } + } 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 b1349e1761..75e830e654 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java +++ b/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java @@ -28,9 +28,7 @@ import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; import info.nightscout.androidaps.Config; -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.data.ProfileStore; import info.nightscout.androidaps.events.EventCareportalEventChange; @@ -43,15 +41,10 @@ import info.nightscout.androidaps.events.EventReloadTempBasalData; import info.nightscout.androidaps.events.EventReloadTreatmentData; import info.nightscout.androidaps.events.EventTempBasalChange; import info.nightscout.androidaps.events.EventTempTargetChange; -import info.nightscout.androidaps.events.EventTreatmentChange; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventNewHistoryData; -import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; -import info.nightscout.androidaps.plugins.Overview.notifications.Notification; import info.nightscout.androidaps.plugins.PumpDanaR.activities.DanaRNSHistorySync; import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes; import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin; -import info.nightscout.utils.DateUtil; import info.nightscout.utils.NSUpload; import info.nightscout.utils.PercentageSplitter; import info.nightscout.utils.ToastUtils; @@ -72,7 +65,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { public static final String DATABASE_TEMPORARYBASALS = "TemporaryBasals"; public static final String DATABASE_EXTENDEDBOLUSES = "ExtendedBoluses"; public static final String DATABASE_TEMPTARGETS = "TempTargets"; - public static final String DATABASE_TREATMENTS = "Treatments"; public static final String DATABASE_DANARHISTORY = "DanaRHistory"; public static final String DATABASE_DBREQUESTS = "DBRequests"; public static final String DATABASE_CAREPORTALEVENTS = "CareportalEvents"; @@ -81,14 +73,11 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { private static final int DATABASE_VERSION = 8; - private static Long earliestDataChange = null; + public static Long earliestDataChange = null; private static final ScheduledExecutorService bgWorker = Executors.newSingleThreadScheduledExecutor(); private static ScheduledFuture scheduledBgPost = null; - private static final ScheduledExecutorService treatmentsWorker = Executors.newSingleThreadScheduledExecutor(); - private static ScheduledFuture scheduledTratmentPost = null; - private static final ScheduledExecutorService tempBasalsWorker = Executors.newSingleThreadScheduledExecutor(); private static ScheduledFuture scheduledTemBasalsPost = null; @@ -118,7 +107,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { try { log.info("onCreate"); TableUtils.createTableIfNotExists(connectionSource, TempTarget.class); - TableUtils.createTableIfNotExists(connectionSource, Treatment.class); TableUtils.createTableIfNotExists(connectionSource, BgReading.class); TableUtils.createTableIfNotExists(connectionSource, DanaRHistoryRecord.class); TableUtils.createTableIfNotExists(connectionSource, DbRequest.class); @@ -141,12 +129,9 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { if (oldVersion == 7 && newVersion == 8) { log.debug("Upgrading database from v7 to v8"); - TableUtils.dropTable(connectionSource, Treatment.class, true); - TableUtils.createTableIfNotExists(connectionSource, Treatment.class); } else { log.info(DatabaseHelper.class.getName(), "onUpgrade"); TableUtils.dropTable(connectionSource, TempTarget.class, true); - TableUtils.dropTable(connectionSource, Treatment.class, true); TableUtils.dropTable(connectionSource, BgReading.class, true); TableUtils.dropTable(connectionSource, DanaRHistoryRecord.class, true); TableUtils.dropTable(connectionSource, DbRequest.class, true); @@ -178,40 +163,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { super.close(); } - public void cleanUpDatabases() { - // TODO: call it somewhere - log.debug("Before BgReadings size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_BGREADINGS)); - getWritableDatabase().delete(DATABASE_BGREADINGS, "date" + " < '" + (System.currentTimeMillis() - Constants.hoursToKeepInDatabase * 60 * 60 * 1000L) + "'", null); - log.debug("After BgReadings size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_BGREADINGS)); - - log.debug("Before TempTargets size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_TEMPTARGETS)); - getWritableDatabase().delete(DATABASE_TEMPTARGETS, "date" + " < '" + (System.currentTimeMillis() - Constants.hoursToKeepInDatabase * 60 * 60 * 1000L) + "'", null); - log.debug("After TempTargets size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_TEMPTARGETS)); - - log.debug("Before Treatments size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_TREATMENTS)); - getWritableDatabase().delete(DATABASE_TREATMENTS, "date" + " < '" + (System.currentTimeMillis() - Constants.hoursToKeepInDatabase * 60 * 60 * 1000L) + "'", null); - log.debug("After Treatments size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_TREATMENTS)); - - log.debug("Before History size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_DANARHISTORY)); - getWritableDatabase().delete(DATABASE_DANARHISTORY, "recordDate" + " < '" + (System.currentTimeMillis() - Constants.daysToKeepHistoryInDatabase * 24 * 60 * 60 * 1000L) + "'", null); - log.debug("After History size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_DANARHISTORY)); - - log.debug("Before TemporaryBasals size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_TEMPORARYBASALS)); - getWritableDatabase().delete(DATABASE_TEMPORARYBASALS, "recordDate" + " < '" + (System.currentTimeMillis() - Constants.daysToKeepHistoryInDatabase * 24 * 60 * 60 * 1000L) + "'", null); - log.debug("After TemporaryBasals size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_TEMPORARYBASALS)); - - log.debug("Before ExtendedBoluses size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_EXTENDEDBOLUSES)); - getWritableDatabase().delete(DATABASE_EXTENDEDBOLUSES, "recordDate" + " < '" + (System.currentTimeMillis() - Constants.daysToKeepHistoryInDatabase * 24 * 60 * 60 * 1000L) + "'", null); - log.debug("After ExtendedBoluses size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_EXTENDEDBOLUSES)); - - log.debug("Before CareportalEvent size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_CAREPORTALEVENTS)); - getWritableDatabase().delete(DATABASE_CAREPORTALEVENTS, "recordDate" + " < '" + (System.currentTimeMillis() - Constants.daysToKeepHistoryInDatabase * 24 * 60 * 60 * 1000L) + "'", null); - log.debug("After CareportalEvent size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_CAREPORTALEVENTS)); - - log.debug("Before ProfileSwitch size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_PROFILESWITCHES)); - getWritableDatabase().delete(DATABASE_PROFILESWITCHES, "recordDate" + " < '" + (System.currentTimeMillis() - Constants.daysToKeepHistoryInDatabase * 24 * 60 * 60 * 1000L) + "'", null); - log.debug("After ProfileSwitch size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_PROFILESWITCHES)); - } public long size(String database) { return DatabaseUtils.queryNumEntries(getReadableDatabase(), database); @@ -222,7 +173,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { public void resetDatabases() { try { TableUtils.dropTable(connectionSource, TempTarget.class, true); - TableUtils.dropTable(connectionSource, Treatment.class, true); TableUtils.dropTable(connectionSource, BgReading.class, true); TableUtils.dropTable(connectionSource, DanaRHistoryRecord.class, true); TableUtils.dropTable(connectionSource, DbRequest.class, true); @@ -232,7 +182,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { TableUtils.dropTable(connectionSource, ProfileSwitch.class, true); TableUtils.dropTable(connectionSource, TDD.class, true); TableUtils.createTableIfNotExists(connectionSource, TempTarget.class); - TableUtils.createTableIfNotExists(connectionSource, Treatment.class); TableUtils.createTableIfNotExists(connectionSource, BgReading.class); TableUtils.createTableIfNotExists(connectionSource, DanaRHistoryRecord.class); TableUtils.createTableIfNotExists(connectionSource, DbRequest.class); @@ -248,7 +197,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { VirtualPumpPlugin.setFakingStatus(true); scheduleBgChange(null); // trigger refresh scheduleTemporaryBasalChange(); - scheduleTreatmentChange(null); scheduleExtendedBolusChange(); scheduleTemporaryTargetChange(); scheduleCareportalEventChange(); @@ -264,17 +212,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { ); } - public void resetTreatments() { - try { - TableUtils.dropTable(connectionSource, Treatment.class, true); - TableUtils.createTableIfNotExists(connectionSource, Treatment.class); - updateEarliestDataChange(0); - } catch (SQLException e) { - log.error("Unhandled exception", e); - } - scheduleTreatmentChange(null); - } - public void resetTempTargets() { try { TableUtils.dropTable(connectionSource, TempTarget.class, true); @@ -343,10 +280,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { return getDao(TempTarget.class); } - private Dao getDaoTreatments() throws SQLException { - return getDao(Treatment.class); - } - private Dao getDaoBgReadings() throws SQLException { return getDao(BgReading.class); } @@ -379,7 +312,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { return getDao(ProfileSwitch.class); } - public long roundDateToSec(long date) { + public static long roundDateToSec(long date) { return date - date % 1000; } // ------------------- BgReading handling ----------------------- @@ -413,7 +346,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { try { getDaoBgReadings().update(bgReading); } catch (SQLException e) { - e.printStackTrace(); + log.error("Unhandled exception", e); } } @@ -436,8 +369,8 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { } /* - * Return last BgReading from database or null if db is empty - */ + * Return last BgReading from database or null if db is empty + */ @Nullable public static BgReading lastBg() { List bgList = null; @@ -461,9 +394,9 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { } /* - * Return bg reading if not old ( <9 min ) - * or null if older - */ + * Return bg reading if not old ( <9 min ) + * or null if older + */ @Nullable public static BgReading actualBg() { BgReading lastBg = lastBg(); @@ -513,7 +446,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { } // ------------------- TDD handling ----------------------- - public void createOrUpdateTDD(TDD tdd){ + public void createOrUpdateTDD(TDD tdd) { try { Dao dao = getDaoTDD(); dao.createOrUpdate(tdd); @@ -539,7 +472,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { } - // ------------- DbRequests handling ------------------- public void create(DbRequest dbr) { @@ -576,7 +508,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { queryBuilder.limit(10L); PreparedQuery preparedQuery = queryBuilder.prepare(); List dbList = getDaoDbRequest().query(preparedQuery); - log.error("deleteDbRequestbyMongoId query size: " + dbList.size()); for (DbRequest r : dbList) { delete(r); } @@ -604,147 +535,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { // -------------------- TREATMENT HANDLING ------------------- - // return true if new record is created - public boolean createOrUpdate(Treatment treatment) { - try { - Treatment old; - treatment.date = roundDateToSec(treatment.date); - - if (treatment.source == Source.PUMP) { - // check for changed from pump change in NS - QueryBuilder queryBuilder = getDaoTreatments().queryBuilder(); - Where where = queryBuilder.where(); - where.eq("pumpId", treatment.pumpId); - PreparedQuery preparedQuery = queryBuilder.prepare(); - List trList = getDaoTreatments().query(preparedQuery); - if (trList.size() > 0) { - // do nothing, pump history record cannot be changed - log.debug("TREATMENT: Pump record already found in database: " + treatment.toString()); - return false; - } - getDaoTreatments().create(treatment); - log.debug("TREATMENT: New record from: " + Source.getString(treatment.source) + " " + treatment.toString()); - updateEarliestDataChange(treatment.date); - scheduleTreatmentChange(treatment); - return true; - } - if (treatment.source == Source.NIGHTSCOUT) { - old = getDaoTreatments().queryForId(treatment.date); - if (old != null) { - if (!old.isEqual(treatment)) { - boolean historyChange = old.isDataChanging(treatment); - long oldDate = old.date; - getDaoTreatments().delete(old); // need to delete/create because date may change too - old.copyFrom(treatment); - getDaoTreatments().create(old); - log.debug("TREATMENT: Updating record by date from: " + Source.getString(treatment.source) + " " + old.toString()); - if (historyChange) { - updateEarliestDataChange(oldDate); - updateEarliestDataChange(old.date); - } - scheduleTreatmentChange(treatment); - return true; - } - return false; - } - // find by NS _id - if (treatment._id != null) { - QueryBuilder queryBuilder = getDaoTreatments().queryBuilder(); - Where where = queryBuilder.where(); - where.eq("_id", treatment._id); - PreparedQuery preparedQuery = queryBuilder.prepare(); - List trList = getDaoTreatments().query(preparedQuery); - if (trList.size() > 0) { - old = trList.get(0); - if (!old.isEqual(treatment)) { - boolean historyChange = old.isDataChanging(treatment); - long oldDate = old.date; - getDaoTreatments().delete(old); // need to delete/create because date may change too - old.copyFrom(treatment); - getDaoTreatments().create(old); - log.debug("TREATMENT: Updating record by _id from: " + Source.getString(treatment.source) + " " + old.toString()); - if (historyChange) { - updateEarliestDataChange(oldDate); - updateEarliestDataChange(old.date); - } - scheduleTreatmentChange(treatment); - return true; - } - } - } - getDaoTreatments().create(treatment); - log.debug("TREATMENT: New record from: " + Source.getString(treatment.source) + " " + treatment.toString()); - updateEarliestDataChange(treatment.date); - scheduleTreatmentChange(treatment); - return true; - } - if (treatment.source == Source.USER) { - getDaoTreatments().create(treatment); - log.debug("TREATMENT: New record from: " + Source.getString(treatment.source) + " " + treatment.toString()); - updateEarliestDataChange(treatment.date); - scheduleTreatmentChange(treatment); - return true; - } - } catch (SQLException e) { - log.error("Unhandled exception", e); - } - return false; - } - - public void delete(Treatment treatment) { - try { - getDaoTreatments().delete(treatment); - updateEarliestDataChange(treatment.date); - } catch (SQLException e) { - log.error("Unhandled exception", e); - } - scheduleTreatmentChange(treatment); - } - - public void update(Treatment treatment) { - try { - getDaoTreatments().update(treatment); - updateEarliestDataChange(treatment.date); - } catch (SQLException e) { - log.error("Unhandled exception", e); - } - scheduleTreatmentChange(treatment); - } - - public void deleteTreatmentById(String _id) { - Treatment stored = findTreatmentById(_id); - if (stored != null) { - log.debug("TREATMENT: Removing Treatment record from database: " + stored.toString()); - delete(stored); - updateEarliestDataChange(stored.date); - scheduleTreatmentChange(null); - } - } - - @Nullable - private Treatment findTreatmentById(String _id) { - try { - Dao daoTreatments = getDaoTreatments(); - QueryBuilder queryBuilder = daoTreatments.queryBuilder(); - Where where = queryBuilder.where(); - where.eq("_id", _id); - queryBuilder.limit(10L); - PreparedQuery preparedQuery = queryBuilder.prepare(); - List trList = daoTreatments.query(preparedQuery); - if (trList.size() != 1) { - //log.debug("Treatment findTreatmentById query size: " + trList.size()); - return null; - } else { - //log.debug("Treatment findTreatmentById found: " + trList.get(0).log()); - return trList.get(0); - } - } catch (SQLException e) { - log.error("Unhandled exception", e); - } - return null; - } - - private void updateEarliestDataChange(long newDate) { + public static void updateEarliestDataChange(long newDate) { if (earliestDataChange == null) { earliestDataChange = newDate; return; @@ -754,73 +545,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { } } - private static void scheduleTreatmentChange(@Nullable final Treatment treatment) { - class PostRunnable implements Runnable { - public void run() { - log.debug("Firing EventTreatmentChange"); - MainApp.bus().post(new EventReloadTreatmentData(new EventTreatmentChange(treatment))); - if (earliestDataChange != null) - MainApp.bus().post(new EventNewHistoryData(earliestDataChange)); - earliestDataChange = null; - scheduledTratmentPost = null; - } - } - // prepare task for execution in 1 sec - // cancel waiting task to prevent sending multiple posts - if (scheduledTratmentPost != null) - scheduledTratmentPost.cancel(false); - Runnable task = new PostRunnable(); - final int sec = 1; - scheduledTratmentPost = treatmentsWorker.schedule(task, sec, TimeUnit.SECONDS); - - } - - public List getTreatmentDataFromTime(long mills, boolean ascending) { - try { - Dao daoTreatments = getDaoTreatments(); - List treatments; - QueryBuilder queryBuilder = daoTreatments.queryBuilder(); - queryBuilder.orderBy("date", ascending); - Where where = queryBuilder.where(); - where.ge("date", mills); - PreparedQuery preparedQuery = queryBuilder.prepare(); - treatments = daoTreatments.query(preparedQuery); - return treatments; - } catch (SQLException e) { - log.error("Unhandled exception", e); - } - return new ArrayList(); - } - - public void createTreatmentFromJsonIfNotExists(JSONObject trJson) { - try { - Treatment treatment = new Treatment(); - treatment.source = Source.NIGHTSCOUT; - treatment.date = roundDateToSec(trJson.getLong("mills")); - treatment.carbs = trJson.has("carbs") ? trJson.getDouble("carbs") : 0; - treatment.insulin = trJson.has("insulin") ? trJson.getDouble("insulin") : 0d; - treatment.pumpId = trJson.has("pumpId") ? trJson.getLong("pumpId") : 0; - treatment._id = trJson.getString("_id"); - if (trJson.has("isSMB")) - treatment.isSMB = trJson.getBoolean("isSMB"); - if (trJson.has("eventType")) { - treatment.mealBolus = !trJson.get("eventType").equals("Correction Bolus"); - double carbs = treatment.carbs; - if (trJson.has("boluscalc")) { - JSONObject boluscalc = trJson.getJSONObject("boluscalc"); - if (boluscalc.has("carbs")) { - carbs = Math.max(boluscalc.getDouble("carbs"), carbs); - } - } - if (carbs <= 0) - treatment.mealBolus = false; - } - createOrUpdate(treatment); - } catch (JSONException e) { - log.error("Unhandled exception", e); - } - } - // ---------------- TempTargets handling --------------- public List getTemptargetsDataFromTime(long mills, boolean ascending) { @@ -988,7 +712,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { getDaoDanaRHistory().createOrUpdate(record); //If it is a TDD, store it for stats also. - if(record.recordCode == RecordTypes.RECORD_TYPE_DAILY){ + if (record.recordCode == RecordTypes.RECORD_TYPE_DAILY) { createOrUpdateTDD(new TDD(record.recordDate, record.recordDailyBolus, record.recordDailyBasal, 0)); } @@ -1428,37 +1152,10 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { } */ - public void createExtendedBolusFromJsonIfNotExists(JSONObject trJson) { - try { - QueryBuilder queryBuilder = null; - queryBuilder = getDaoExtendedBolus().queryBuilder(); - Where where = queryBuilder.where(); - where.eq("_id", trJson.getString("_id")).or().eq("date", trJson.getLong("mills")); - PreparedQuery preparedQuery = queryBuilder.prepare(); - List list = getDaoExtendedBolus().query(preparedQuery); - ExtendedBolus extendedBolus; - if (list.size() == 0) { - extendedBolus = new ExtendedBolus(); - extendedBolus.source = Source.NIGHTSCOUT; - if (Config.logIncommingData) - log.debug("Adding ExtendedBolus record to database: " + trJson.toString()); - // Record does not exists. add - } else if (list.size() == 1) { - extendedBolus = list.get(0); - if (Config.logIncommingData) - log.debug("Updating ExtendedBolus record in database: " + trJson.toString()); - } else { - log.error("Something went wrong"); - return; - } - extendedBolus.date = trJson.getLong("mills"); - extendedBolus.durationInMinutes = trJson.has("duration") ? trJson.getInt("duration") : 0; - extendedBolus.insulin = trJson.getDouble("relative"); - extendedBolus._id = trJson.getString("_id"); + public void createExtendedBolusFromJsonIfNotExists(JSONObject json) { + ExtendedBolus extendedBolus = ExtendedBolus.createFromJson(json); + if (extendedBolus != null) createOrUpdate(extendedBolus); - } catch (SQLException | JSONException e) { - log.error("Unhandled exception", e); - } } private static void scheduleExtendedBolusChange() { @@ -1504,6 +1201,15 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { scheduleCareportalEventChange(); } + public CareportalEvent getCareportalEventFromTimestamp(long timestamp) { + try { + return getDaoCareportalEvents().queryForId(timestamp); + } catch (SQLException e) { + log.error("Unhandled exception", e); + } + return null; + } + @Nullable public CareportalEvent getLastCareportalEvent(String event) { try { @@ -1557,7 +1263,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { public void deleteCareportalEventById(String _id) { try { - QueryBuilder queryBuilder = null; + QueryBuilder queryBuilder; queryBuilder = getDaoCareportalEvents().queryBuilder(); Where where = queryBuilder.where(); where.eq("_id", _id); @@ -1580,7 +1286,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { public void createCareportalEventFromJsonIfNotExists(JSONObject trJson) { try { - QueryBuilder queryBuilder = null; + QueryBuilder queryBuilder; queryBuilder = getDaoCareportalEvents().queryBuilder(); Where where = queryBuilder.where(); where.eq("_id", trJson.getString("_id")).or().eq("date", trJson.getLong("mills")); diff --git a/app/src/main/java/info/nightscout/androidaps/db/ExtendedBolus.java b/app/src/main/java/info/nightscout/androidaps/db/ExtendedBolus.java index 7bd60fe496..418de86c6c 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/ExtendedBolus.java +++ b/app/src/main/java/info/nightscout/androidaps/db/ExtendedBolus.java @@ -9,24 +9,25 @@ import android.graphics.Color; import com.j256.ormlite.field.DatabaseField; import com.j256.ormlite.table.DatabaseTable; +import org.json.JSONException; +import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.Date; import java.util.Objects; import info.nightscout.androidaps.Constants; -import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.data.Iob; import info.nightscout.androidaps.data.IobTotal; -import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.interfaces.InsulinInterface; import info.nightscout.androidaps.interfaces.Interval; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.Overview.graphExtensions.DataPointWithLabelInterface; import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLabelGraphSeries; +import info.nightscout.androidaps.plugins.Treatments.Treatment; import info.nightscout.utils.DateUtil; import info.nightscout.utils.DecimalFormatter; +import info.nightscout.utils.JsonHelper; import info.nightscout.utils.Round; /** @@ -91,6 +92,16 @@ public class ExtendedBolus implements Interval, DataPointWithLabelInterface { pumpId = t.pumpId; } + public static ExtendedBolus createFromJson(JSONObject json) { + ExtendedBolus extendedBolus = new ExtendedBolus(); + extendedBolus.source = Source.NIGHTSCOUT; + extendedBolus.date = JsonHelper.safeGetLong(json, "mills"); + extendedBolus.durationInMinutes = JsonHelper.safeGetInt(json, "duration"); + extendedBolus.insulin = JsonHelper.safeGetDouble(json, "relative") / 60 * extendedBolus.durationInMinutes; + extendedBolus._id = JsonHelper.safeGetString(json, "_id"); + extendedBolus.pumpId = JsonHelper.safeGetLong(json, "pumpId"); + return extendedBolus; + } // -------- Interval interface --------- Long cuttedEnd = null; diff --git a/app/src/main/java/info/nightscout/androidaps/db/TemporaryBasal.java b/app/src/main/java/info/nightscout/androidaps/db/TemporaryBasal.java index e2303bac53..733027b188 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/TemporaryBasal.java +++ b/app/src/main/java/info/nightscout/androidaps/db/TemporaryBasal.java @@ -6,7 +6,6 @@ import com.j256.ormlite.table.DatabaseTable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.Date; import java.util.Objects; import info.nightscout.androidaps.MainApp; @@ -17,6 +16,7 @@ import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.interfaces.InsulinInterface; import info.nightscout.androidaps.interfaces.Interval; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.Treatments.Treatment; import info.nightscout.utils.DateUtil; import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.SP; @@ -217,7 +217,7 @@ public class TemporaryBasal implements Interval { // -------- Interval interface end --------- - public IobTotal iobCalc(long time) { + public IobTotal iobCalc(long time, Profile profile) { if(isFakeExtended){ log.error("iobCalc should only be called on Extended boluses separately"); @@ -225,7 +225,6 @@ public class TemporaryBasal implements Interval { } IobTotal result = new IobTotal(time); - Profile profile = MainApp.getConfigBuilder().getProfile(time); InsulinInterface insulinInterface = ConfigBuilderPlugin.getActiveInsulin(); int realDuration = getDurationToTime(time); diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventNsTreatment.java b/app/src/main/java/info/nightscout/androidaps/events/EventNsTreatment.java new file mode 100644 index 0000000000..2c5ba6c9c0 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/events/EventNsTreatment.java @@ -0,0 +1,36 @@ +package info.nightscout.androidaps.events; + +import org.json.JSONObject; + + +/** + * Event which is published with data fetched from NightScout specific for the + * Treatment-class. + *

+ * Payload is the from NS retrieved JSON-String which should be handled by all + * subscriber. + */ + +public class EventNsTreatment extends Event { + + public static final int ADD = 0; + public static final int UPDATE = 1; + public static final int REMOVE = 2; + + private final int mode; + + private final JSONObject payload; + + public EventNsTreatment(int mode, JSONObject payload) { + this.mode = mode; + this.payload = payload; + } + + public int getMode() { + return mode; + } + + public JSONObject getPayload() { + return payload; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventTreatmentChange.java b/app/src/main/java/info/nightscout/androidaps/events/EventTreatmentChange.java index 2a3581f9bf..989b24b7f9 100644 --- a/app/src/main/java/info/nightscout/androidaps/events/EventTreatmentChange.java +++ b/app/src/main/java/info/nightscout/androidaps/events/EventTreatmentChange.java @@ -2,7 +2,7 @@ package info.nightscout.androidaps.events; import android.support.annotation.Nullable; -import info.nightscout.androidaps.db.Treatment; +import info.nightscout.androidaps.plugins.Treatments.Treatment; /** * Created by mike on 04.06.2016. diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/InsulinInterface.java b/app/src/main/java/info/nightscout/androidaps/interfaces/InsulinInterface.java index f7be6883e9..a123554ae8 100644 --- a/app/src/main/java/info/nightscout/androidaps/interfaces/InsulinInterface.java +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/InsulinInterface.java @@ -1,10 +1,7 @@ package info.nightscout.androidaps.interfaces; -import java.util.Date; - import info.nightscout.androidaps.data.Iob; -import info.nightscout.androidaps.data.Profile; -import info.nightscout.androidaps.db.Treatment; +import info.nightscout.androidaps.plugins.Treatments.Treatment; /** * Created by mike on 17.04.2017. diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/PluginBase.java b/app/src/main/java/info/nightscout/androidaps/interfaces/PluginBase.java index 190a3b89f9..1173936430 100644 --- a/app/src/main/java/info/nightscout/androidaps/interfaces/PluginBase.java +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/PluginBase.java @@ -152,10 +152,7 @@ public abstract class PluginBase { if (getType() == PluginType.PUMP) { new Thread(() -> { SystemClock.sleep(3000); - try { - ConfigBuilderPlugin.getCommandQueue().readStatus("Pump driver changed.", null); - } catch (Exception ignored) { // Thread fail to start in tests - } + ConfigBuilderPlugin.getCommandQueue().readStatus("Pump driver changed.", null); }).start(); } } diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/PumpDescription.java b/app/src/main/java/info/nightscout/androidaps/interfaces/PumpDescription.java index cc7b3b3e85..ec6976a2c7 100644 --- a/app/src/main/java/info/nightscout/androidaps/interfaces/PumpDescription.java +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/PumpDescription.java @@ -41,4 +41,7 @@ public class PumpDescription { public boolean storesCarbInfo = true; public boolean is30minBasalRatesCapable = false; + + public boolean supportsTDDs = false; + public boolean needsManualTDDLoad = true; } diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/TreatmentsInterface.java b/app/src/main/java/info/nightscout/androidaps/interfaces/TreatmentsInterface.java index 129e54b50b..30610ca2f6 100644 --- a/app/src/main/java/info/nightscout/androidaps/interfaces/TreatmentsInterface.java +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/TreatmentsInterface.java @@ -5,11 +5,12 @@ import java.util.List; import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.MealData; +import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.db.ExtendedBolus; 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.plugins.Treatments.Treatment; import info.nightscout.androidaps.data.Intervals; import info.nightscout.androidaps.data.ProfileIntervals; @@ -24,7 +25,7 @@ public interface TreatmentsInterface { IobTotal getLastCalculationTreatments(); IobTotal getCalculationToTimeTreatments(long time); IobTotal getLastCalculationTempBasals(); - IobTotal getCalculationToTimeTempBasals(long time); + IobTotal getCalculationToTimeTempBasals(long time, Profile profile); MealData getMealData(); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Actions/ActionsFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Actions/ActionsFragment.java index e424943acb..cc73571b9d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Actions/ActionsFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Actions/ActionsFragment.java @@ -79,7 +79,6 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL tddStats = view.findViewById(R.id.actions_tddstats); history = view.findViewById(R.id.actions_historybrowser); - profileSwitch.setOnClickListener(this); tempTarget.setOnClickListener(this); extendedBolus.setOnClickListener(this); @@ -191,6 +190,9 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL tempTarget.setVisibility(View.GONE); else tempTarget.setVisibility(View.VISIBLE); + + if (!ConfigBuilderPlugin.getActivePump().getPumpDescription().supportsTDDs) tddStats.setVisibility(View.GONE); + else tddStats.setVisibility(View.VISIBLE); } }); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/CareportalFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/CareportalFragment.java index 2656e43a26..8a8a730bb3 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/CareportalFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/CareportalFragment.java @@ -2,6 +2,7 @@ package info.nightscout.androidaps.plugins.Careportal; import android.app.Activity; +import android.graphics.Color; import android.os.Bundle; import android.support.v4.app.FragmentManager; import android.view.LayoutInflater; @@ -12,7 +13,9 @@ import android.widget.TextView; import com.squareup.otto.Subscribe; -import info.nightscout.androidaps.BuildConfig; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; @@ -21,11 +24,12 @@ import info.nightscout.androidaps.db.CareportalEvent; import info.nightscout.androidaps.events.EventCareportalEventChange; import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog; import info.nightscout.androidaps.plugins.Common.SubscriberFragment; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSettingsStatus; import info.nightscout.androidaps.plugins.Overview.OverviewFragment; import info.nightscout.utils.FabricPrivacy; public class CareportalFragment extends SubscriberFragment implements View.OnClickListener { + private static Logger log = LoggerFactory.getLogger(CareportalFragment.class); TextView iage; TextView cage; @@ -208,26 +212,54 @@ public class CareportalFragment extends SubscriberFragment implements View.OnCli public static void updateAge(Activity activity, final TextView sage, final TextView iage, final TextView cage, final TextView pbage) { if (activity != null) { activity.runOnUiThread( - new Runnable() { - @Override - public void run() { - CareportalEvent careportalEvent; - String notavailable = OverviewFragment.shorttextmode ? "-" : MainApp.sResources.getString(R.string.notavailable); - if (sage != null) { - careportalEvent = MainApp.getDbHelper().getLastCareportalEvent(CareportalEvent.SENSORCHANGE); - sage.setText(careportalEvent != null ? careportalEvent.age() : notavailable); + () -> { + CareportalEvent careportalEvent; + NSSettingsStatus nsSettings = new NSSettingsStatus().getInstance(); + + double iageUrgent = nsSettings.getExtendedWarnValue("iage", "urgent", 72); + double iageWarn = nsSettings.getExtendedWarnValue("iage", "warn", 48); + double cageUrgent = nsSettings.getExtendedWarnValue("cage", "urgent", 72); + double cageWarn = nsSettings.getExtendedWarnValue("cage", "warn", 48); + double sageUrgent = nsSettings.getExtendedWarnValue("sage", "urgent", 166); + double sageWarn = nsSettings.getExtendedWarnValue("sage", "warn", 164); + double pbageUrgent = nsSettings.getExtendedWarnValue("pgage", "urgent", 360); + double pbageWarn = nsSettings.getExtendedWarnValue("pgage", "warn", 240); + + String notavailable = OverviewFragment.shorttextmode ? "-" : MainApp.sResources.getString(R.string.notavailable); + if (sage != null) { + careportalEvent = MainApp.getDbHelper().getLastCareportalEvent(CareportalEvent.SENSORCHANGE); + if (careportalEvent != null) { + sage.setTextColor(CareportalFragment.determineTextColor(careportalEvent, sageWarn, sageUrgent)); + sage.setText(careportalEvent.age()); + } else { + sage.setText(notavailable); } - if (iage != null) { - careportalEvent = MainApp.getDbHelper().getLastCareportalEvent(CareportalEvent.INSULINCHANGE); - iage.setText(careportalEvent != null ? careportalEvent.age() : notavailable); + } + if (iage != null) { + careportalEvent = MainApp.getDbHelper().getLastCareportalEvent(CareportalEvent.INSULINCHANGE); + if (careportalEvent != null) { + iage.setTextColor(CareportalFragment.determineTextColor(careportalEvent, iageWarn, iageUrgent)); + iage.setText(careportalEvent.age()); + } else { + iage.setText(notavailable); } - if (cage != null) { - careportalEvent = MainApp.getDbHelper().getLastCareportalEvent(CareportalEvent.SITECHANGE); - cage.setText(careportalEvent != null ? careportalEvent.age() : notavailable); + } + if (cage != null) { + careportalEvent = MainApp.getDbHelper().getLastCareportalEvent(CareportalEvent.SITECHANGE); + if (careportalEvent != null) { + cage.setTextColor(CareportalFragment.determineTextColor(careportalEvent, cageWarn, cageUrgent)); + cage.setText(careportalEvent.age()); + } else { + cage.setText(notavailable); } - if (pbage != null) { - careportalEvent = MainApp.getDbHelper().getLastCareportalEvent(CareportalEvent.PUMPBATTERYCHANGE); - pbage.setText(careportalEvent != null ? careportalEvent.age() : notavailable); + } + if (pbage != null) { + careportalEvent = MainApp.getDbHelper().getLastCareportalEvent(CareportalEvent.PUMPBATTERYCHANGE); + if (careportalEvent != null) { + pbage.setTextColor(CareportalFragment.determineTextColor(careportalEvent, pbageWarn, pbageUrgent)); + pbage.setText(careportalEvent.age()); + } else { + pbage.setText(notavailable); } } } @@ -235,4 +267,15 @@ public class CareportalFragment extends SubscriberFragment implements View.OnCli } } + public static int determineTextColor(CareportalEvent careportalEvent, double warnThreshold, double urgentThreshold) { + if (careportalEvent.isOlderThan(urgentThreshold)) { + return MainApp.sResources.getColor(R.color.low); + } else if (careportalEvent.isOlderThan(warnThreshold)) { + return MainApp.sResources.getColor(R.color.high); + } else { + return Color.WHITE; + } + + } } + diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsSafety/SafetyPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsSafety/SafetyPlugin.java index a3e27e1662..6a9613e92a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsSafety/SafetyPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsSafety/SafetyPlugin.java @@ -14,6 +14,8 @@ import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin; import info.nightscout.androidaps.plugins.OpenAPSMA.OpenAPSMAPlugin; import info.nightscout.androidaps.plugins.OpenAPSSMB.OpenAPSSMBPlugin; +import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.Overview.notifications.Notification; import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.HardLimits; import info.nightscout.utils.Round; @@ -55,12 +57,18 @@ public class SafetyPlugin extends PluginBase implements ConstraintsInterface { @Override public Constraint isClosedLoopAllowed(Constraint value) { - if (!MainApp.isEngineeringModeOrRelease()) - value.set(false, MainApp.gs(R.string.closed_loop_disabled_on_dev_branch), this); - String mode = SP.getString("aps_mode", "open"); if (!mode.equals("closed")) value.set(false, MainApp.gs(R.string.closedmodedisabledinpreferences), this); + + if (!MainApp.isEngineeringModeOrRelease()) { + if (value.value()) { + Notification n = new Notification(Notification.TOAST_ALARM, MainApp.gs(R.string.closed_loop_disabled_on_dev_branch), Notification.NORMAL); + MainApp.bus().post(new EventNewNotification(n)); + } + value.set(false, MainApp.gs(R.string.closed_loop_disabled_on_dev_branch), this); + } + return value; } @@ -161,7 +169,11 @@ public class SafetyPlugin extends PluginBase implements ConstraintsInterface { @Override public Constraint applyMaxIOBConstraints(Constraint maxIob) { - double maxIobPref = SP.getDouble(R.string.key_openapsma_max_iob, 1.5d); + double maxIobPref; + if (OpenAPSSMBPlugin.getPlugin().isEnabled(PluginType.APS)) + maxIobPref = SP.getDouble(R.string.key_openapssmb_max_iob, 3d); + else + maxIobPref = SP.getDouble(R.string.key_openapsma_max_iob, 1.5d); maxIob.setIfSmaller(maxIobPref, String.format(MainApp.gs(R.string.limitingiob), maxIobPref, MainApp.gs(R.string.maxvalueinpreferences)), this); if (OpenAPSMAPlugin.getPlugin().isEnabled(PluginType.APS)) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Food/Food.java b/app/src/main/java/info/nightscout/androidaps/plugins/Food/Food.java index 5506d32471..49da1d6ac5 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Food/Food.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Food/Food.java @@ -5,8 +5,6 @@ import com.j256.ormlite.table.DatabaseTable; import org.json.JSONException; import org.json.JSONObject; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import java.util.Objects; @@ -18,9 +16,7 @@ import info.nightscout.utils.JsonHelper; @DatabaseTable(tableName = Food.TABLE_FOODS) public class Food { - private static Logger log = LoggerFactory.getLogger(Food.class); - - public static final String TABLE_FOODS = "Foods"; + static final String TABLE_FOODS = "Foods"; @DatabaseField(id = true) public long key; @@ -65,7 +61,7 @@ public class Food { @DatabaseField public int gi; // not used yet - public Food() { + private Food() { key = System.currentTimeMillis(); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Food/FoodService.java b/app/src/main/java/info/nightscout/androidaps/plugins/Food/FoodService.java index c3028461ec..44b96850ae 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Food/FoodService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Food/FoodService.java @@ -347,6 +347,7 @@ public class FoodService extends OrmLiteBaseService { * @param _id * @return */ + @Nullable public Food findByNSId(String _id) { try { List list = this.getDao().queryForEq("_id", _id); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Insulin/ActivityGraph.java b/app/src/main/java/info/nightscout/androidaps/plugins/Insulin/ActivityGraph.java index 5a0d7fcce9..8bbd1d3e7f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Insulin/ActivityGraph.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Insulin/ActivityGraph.java @@ -12,7 +12,7 @@ import java.util.ArrayList; import java.util.List; import info.nightscout.androidaps.data.Iob; -import info.nightscout.androidaps.db.Treatment; +import info.nightscout.androidaps.plugins.Treatments.Treatment; import info.nightscout.androidaps.interfaces.InsulinInterface; /** diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Insulin/InsulinOrefBasePlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Insulin/InsulinOrefBasePlugin.java index cf56452bcc..672c5cfeb6 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Insulin/InsulinOrefBasePlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Insulin/InsulinOrefBasePlugin.java @@ -5,7 +5,7 @@ import com.squareup.otto.Bus; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.data.Iob; -import info.nightscout.androidaps.db.Treatment; +import info.nightscout.androidaps.plugins.Treatments.Treatment; import info.nightscout.androidaps.interfaces.InsulinInterface; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginDescription; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/AutosensData.java b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/AutosensData.java index 42a2b35490..397656306b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/AutosensData.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/AutosensData.java @@ -10,8 +10,7 @@ import java.util.List; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.data.Profile; -import info.nightscout.androidaps.db.Treatment; -import info.nightscout.androidaps.interfaces.PluginBase; +import info.nightscout.androidaps.plugins.Treatments.Treatment; import info.nightscout.androidaps.interfaces.PluginType; import info.nightscout.androidaps.plugins.SensitivityAAPS.SensitivityAAPSPlugin; import info.nightscout.androidaps.plugins.SensitivityWeightedAverage.SensitivityWeightedAveragePlugin; 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 f56939e504..f51c7f7a94 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 @@ -293,13 +293,13 @@ public class IobCobCalculatorPlugin extends PluginBase { return getBGDataFrom; } - public IobTotal calculateFromTreatmentsAndTempsSynchronized(long time) { + public IobTotal calculateFromTreatmentsAndTempsSynchronized(long time, Profile profile) { synchronized (dataLock) { - return calculateFromTreatmentsAndTemps(time); + return calculateFromTreatmentsAndTemps(time, profile); } } - public IobTotal calculateFromTreatmentsAndTemps(long time) { + public IobTotal calculateFromTreatmentsAndTemps(long time, Profile profile) { long now = System.currentTimeMillis(); time = roundUpTime(time); if (time < now && iobTable.get(time) != null) { @@ -309,16 +309,16 @@ public class IobCobCalculatorPlugin extends PluginBase { //log.debug(">>> calculateFromTreatmentsAndTemps Cache miss " + new Date(time).toLocaleString()); } IobTotal bolusIob = TreatmentsPlugin.getPlugin().getCalculationToTimeTreatments(time).round(); - IobTotal basalIob = TreatmentsPlugin.getPlugin().getCalculationToTimeTempBasals(time).round(); + IobTotal basalIob = TreatmentsPlugin.getPlugin().getCalculationToTimeTempBasals(time, profile).round(); if (OpenAPSSMBPlugin.getPlugin().isEnabled(PluginType.APS)) { - // Add expected zere temp basal for next 240 mins + // Add expected zero temp basal for next 240 mins IobTotal basalIobWithZeroTemp = basalIob.copy(); TemporaryBasal t = new TemporaryBasal() .date(now + 60 * 1000L) .duration(240) .absolute(0); if (t.date < time) { - IobTotal calc = t.iobCalc(time); + IobTotal calc = t.iobCalc(time, profile); basalIobWithZeroTemp.plus(calc); } @@ -426,8 +426,7 @@ public class IobCobCalculatorPlugin extends PluginBase { } } - public IobTotal[] calculateIobArrayInDia() { - Profile profile = MainApp.getConfigBuilder().getProfile(); + public IobTotal[] calculateIobArrayInDia(Profile profile) { // predict IOB out to DIA plus 30m long time = System.currentTimeMillis(); time = roundUpTime(time); @@ -436,15 +435,14 @@ public class IobCobCalculatorPlugin extends PluginBase { int pos = 0; for (int i = 0; i < len; i++) { long t = time + i * 5 * 60000; - IobTotal iob = calculateFromTreatmentsAndTempsSynchronized(t); + IobTotal iob = calculateFromTreatmentsAndTempsSynchronized(t, profile); array[pos] = iob; pos++; } return array; } - public IobTotal[] calculateIobArrayForSMB() { - Profile profile = MainApp.getConfigBuilder().getProfile(); + public IobTotal[] calculateIobArrayForSMB(Profile profile) { // predict IOB out to DIA plus 30m long time = System.currentTimeMillis(); time = roundUpTime(time); @@ -453,7 +451,7 @@ public class IobCobCalculatorPlugin extends PluginBase { int pos = 0; for (int i = 0; i < len; i++) { long t = time + i * 5 * 60000; - IobTotal iob = calculateFromTreatmentsAndTempsSynchronized(t); + IobTotal iob = calculateFromTreatmentsAndTempsSynchronized(t, profile); array[pos] = iob; pos++; } @@ -479,6 +477,7 @@ public class IobCobCalculatorPlugin extends PluginBase { } @Subscribe + @SuppressWarnings("unused") public void onEventAppInitialized(EventAppInitialized ev) { if (this != getPlugin()) { log.debug("Ignoring event for non default instance"); @@ -488,6 +487,7 @@ public class IobCobCalculatorPlugin extends PluginBase { } @Subscribe + @SuppressWarnings("unused") public void onEventNewBG(EventNewBG ev) { if (this != getPlugin()) { log.debug("Ignoring event for non default instance"); 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 index da7d0fbbbd..e3f12cbea6 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobThread.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobThread.java @@ -20,7 +20,7 @@ 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.Treatments.Treatment; import info.nightscout.androidaps.events.Event; import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventAutosensCalculationFinished; import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; @@ -138,7 +138,7 @@ public class IobCobThread extends Thread { delta = (bg - bucketed_data.get(i + 1).value); avgDelta = (bg - bucketed_data.get(i + 3).value) / 3; - IobTotal iob = iobCobCalculatorPlugin.calculateFromTreatmentsAndTemps(bgTime); + IobTotal iob = iobCobCalculatorPlugin.calculateFromTreatmentsAndTemps(bgTime, profile); double bgi = -iob.activity * sens * 5; double deviation = delta - bgi; @@ -155,7 +155,8 @@ public class IobCobThread extends Thread { AutosensData hourAgoData = iobCobCalculatorPlugin.getAutosensData(hourago); if (hourAgoData != null) { int initialIndex = autosensDataTable.indexOfKey(hourAgoData.time); - log.debug(">>>>> bucketed_data.size()=" + bucketed_data.size() + " i=" + i + "hourAgoData=" + hourAgoData.toString()); + if (Config.logAutosensData) + log.debug(">>>>> bucketed_data.size()=" + bucketed_data.size() + " i=" + i + "hourAgoData=" + hourAgoData.toString()); int past = 1; try { for (; past < 12; past++) { @@ -242,7 +243,8 @@ public class IobCobThread extends Thread { previous = autosensData; autosensDataTable.put(bgTime, autosensData); - log.debug("Running detectSensitivity from: " + DateUtil.dateAndTimeString(oldestTimeWithData) + " to: " + DateUtil.dateAndTimeString(bgTime)); + if (Config.logAutosensData) + log.debug("Running detectSensitivity from: " + DateUtil.dateAndTimeString(oldestTimeWithData) + " to: " + DateUtil.dateAndTimeString(bgTime)); autosensData.autosensRatio = iobCobCalculatorPlugin.detectSensitivity(oldestTimeWithData, bgTime).ratio; if (Config.logAutosensData) log.debug(autosensData.toString()); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopPlugin.java index fed92404e5..e29eda04dc 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopPlugin.java @@ -1,11 +1,14 @@ package info.nightscout.androidaps.plugins.Loop; +import android.annotation.SuppressLint; import android.app.Notification; +import android.app.NotificationChannel; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.TaskStackBuilder; import android.content.Context; import android.content.Intent; +import android.os.Build; import android.support.v4.app.NotificationCompat; import com.crashlytics.android.answers.CustomEvent; @@ -48,6 +51,9 @@ import info.nightscout.utils.SP; public class LoopPlugin extends PluginBase { private static Logger log = LoggerFactory.getLogger(LoopPlugin.class); + public static final String CHANNEL_ID = "AndroidAPS-Openloop"; + + protected static LoopPlugin loopPlugin; public static LoopPlugin getPlugin() { @@ -90,9 +96,22 @@ public class LoopPlugin extends PluginBase { @Override protected void onStart() { MainApp.bus().register(this); + createNotificationChannel(); super.onStart(); } + private void createNotificationChannel() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + + NotificationManager mNotificationManager = + (NotificationManager) MainApp.instance().getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE); + @SuppressLint("WrongConstant") NotificationChannel channel = new NotificationChannel(CHANNEL_ID, + CHANNEL_ID, + NotificationManager.IMPORTANCE_HIGH); + mNotificationManager.createNotificationChannel(channel); + } + } + @Override protected void onStop() { super.onStop(); @@ -322,7 +341,7 @@ public class LoopPlugin extends PluginBase { } else { if (result.isChangeRequested() && allowNotification) { NotificationCompat.Builder builder = - new NotificationCompat.Builder(MainApp.instance().getApplicationContext()); + new NotificationCompat.Builder(MainApp.instance().getApplicationContext(), CHANNEL_ID); builder.setSmallIcon(R.drawable.notif_icon) .setContentTitle(MainApp.sResources.getString(R.string.openloop_newsuggestion)) .setContentText(resultAfterConstraints.toString()) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/NSSettingsStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/NSSettingsStatus.java index 3feced94cd..8d09a05146 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/NSSettingsStatus.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/NSSettingsStatus.java @@ -170,6 +170,19 @@ public class NSSettingsStatus { } + // valid property is "warn" or "urgent" + // plugings "iage" "sage" "cage" "pbage" + + public double getExtendedWarnValue(String plugin, String property, double defaultvalue) { + JSONObject extendedSettings = this.getExtendedSettings(); + if (extendedSettings == null) + return defaultvalue; + JSONObject pluginJson = extendedSettings.optJSONObject(plugin); + if (pluginJson == null) + return defaultvalue; + return pluginJson.optDouble(property, defaultvalue); + } + public String getActiveProfile() { return getStringOrNull("activeProfile"); } @@ -193,7 +206,7 @@ public class NSSettingsStatus { return result; } } - if (settingsO.has("alarmTimeagoWarnMins") && Objects.equals(what, "alarmTimeagoWarnMins")){ + if (settingsO.has("alarmTimeagoWarnMins") && Objects.equals(what, "alarmTimeagoWarnMins")) { Double result = settingsO.getDouble(what); return result; } @@ -206,7 +219,7 @@ public class NSSettingsStatus { private String getStringOrNull(String key) { String ret = null; - if(data == null) return null; + if (data == null) return null; if (data.has(key)) { try { ret = data.getString(key); @@ -288,21 +301,21 @@ public class NSSettingsStatus { JSONObject pump = extentendedPumpSettings(); switch (setting) { case "warnClock": - return pump != null && pump.has(setting) ? pump.getDouble(setting) : 30; + return pump != null && pump.has(setting) ? pump.getDouble(setting) : 30; case "urgentClock": - return pump != null && pump.has(setting) ? pump.getDouble(setting) : 30; + return pump != null && pump.has(setting) ? pump.getDouble(setting) : 30; case "warnRes": - return pump != null && pump.has(setting) ? pump.getDouble(setting) : 30; + return pump != null && pump.has(setting) ? pump.getDouble(setting) : 30; case "urgentRes": - return pump != null && pump.has(setting) ? pump.getDouble(setting) : 30; + return pump != null && pump.has(setting) ? pump.getDouble(setting) : 30; case "warnBattV": - return pump != null && pump.has(setting) ? pump.getDouble(setting) : 30; + return pump != null && pump.has(setting) ? pump.getDouble(setting) : 30; case "urgentBattV": - return pump != null && pump.has(setting) ? pump.getDouble(setting) : 30; - case "warnBattP": - return pump != null && pump.has(setting) ? pump.getDouble(setting) : 30; + return pump != null && pump.has(setting) ? pump.getDouble(setting) : 30; + case "warnBattP": + return pump != null && pump.has(setting) ? pump.getDouble(setting) : 30; case "urgentBattP": - return pump != null && pump.has(setting) ? pump.getDouble(setting) : 30; + return pump != null && pump.has(setting) ? pump.getDouble(setting) : 30; } } catch (JSONException e) { log.error("Unhandled exception", e); @@ -310,12 +323,12 @@ public class NSSettingsStatus { return 0d; } - + @Nullable public JSONObject extentendedPumpSettings() { try { JSONObject extended = getExtendedSettings(); - if(extended == null) return null; + if (extended == null) return null; if (extended.has("pump")) { JSONObject pump = extended.getJSONObject("pump"); return pump; @@ -350,7 +363,7 @@ public class NSSettingsStatus { return ""; } - public boolean openAPSEnabledAlerts() { + public boolean openAPSEnabledAlerts() { try { JSONObject pump = extentendedPumpSettings(); if (pump != null && pump.has("openaps")) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/OpenAPSAMAPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/OpenAPSAMAPlugin.java index d9ffc67830..2789c75252 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/OpenAPSAMAPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/OpenAPSAMAPlugin.java @@ -136,7 +136,7 @@ public class OpenAPSAMAPlugin extends PluginBase implements APSInterface { Date start = new Date(); Date startPart = new Date(); - IobTotal[] iobArray = IobCobCalculatorPlugin.getPlugin().calculateIobArrayInDia(); + IobTotal[] iobArray = IobCobCalculatorPlugin.getPlugin().calculateIobArrayInDia(profile); Profiler.log(log, "calculateIobArrayInDia()", startPart); startPart = new Date(); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/OpenAPSSMBPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/OpenAPSSMBPlugin.java index f30338d024..60b516fc63 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/OpenAPSSMBPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/OpenAPSSMBPlugin.java @@ -143,7 +143,7 @@ public class OpenAPSSMBPlugin extends PluginBase implements APSInterface { Date start = new Date(); Date startPart = new Date(); - IobTotal[] iobArray = IobCobCalculatorPlugin.getPlugin().calculateIobArrayForSMB(); + IobTotal[] iobArray = IobCobCalculatorPlugin.getPlugin().calculateIobArrayForSMB(profile); Profiler.log(log, "calculateIobArrayInDia()", startPart); startPart = new Date(); 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 38498f5eaf..d6c9c70c4e 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 @@ -111,6 +111,7 @@ import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotificati import info.nightscout.androidaps.plugins.Overview.events.EventSetWakeLock; import info.nightscout.androidaps.plugins.Overview.graphData.GraphData; import info.nightscout.androidaps.plugins.Overview.notifications.Notification; +import info.nightscout.androidaps.plugins.Overview.notifications.NotificationRecyclerViewAdapter; import info.nightscout.androidaps.plugins.Overview.notifications.NotificationStore; import info.nightscout.androidaps.plugins.Source.SourceDexcomG5Plugin; import info.nightscout.androidaps.plugins.Source.SourceXdripPlugin; @@ -460,32 +461,32 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, final PumpDescription pumpDescription = ConfigBuilderPlugin.getActivePump().getPumpDescription(); if (activeloop == null || !MainApp.getConfigBuilder().isProfileValid("ContexMenuCreation")) return; - menu.setHeaderTitle(MainApp.sResources.getString(R.string.loop)); + menu.setHeaderTitle(MainApp.gs(R.string.loop)); if (activeloop.isEnabled(PluginType.LOOP)) { - menu.add(MainApp.sResources.getString(R.string.disableloop)); + menu.add(MainApp.gs(R.string.disableloop)); if (!activeloop.isSuspended()) { - menu.add(MainApp.sResources.getString(R.string.suspendloopfor1h)); - menu.add(MainApp.sResources.getString(R.string.suspendloopfor2h)); - menu.add(MainApp.sResources.getString(R.string.suspendloopfor3h)); - menu.add(MainApp.sResources.getString(R.string.suspendloopfor10h)); + menu.add(MainApp.gs(R.string.suspendloopfor1h)); + menu.add(MainApp.gs(R.string.suspendloopfor2h)); + menu.add(MainApp.gs(R.string.suspendloopfor3h)); + menu.add(MainApp.gs(R.string.suspendloopfor10h)); if (pumpDescription.tempDurationStep15mAllowed) - menu.add(MainApp.sResources.getString(R.string.disconnectpumpfor15m)); + menu.add(MainApp.gs(R.string.disconnectpumpfor15m)); if (pumpDescription.tempDurationStep30mAllowed) - menu.add(MainApp.sResources.getString(R.string.disconnectpumpfor30m)); - menu.add(MainApp.sResources.getString(R.string.disconnectpumpfor1h)); - menu.add(MainApp.sResources.getString(R.string.disconnectpumpfor2h)); - menu.add(MainApp.sResources.getString(R.string.disconnectpumpfor3h)); + menu.add(MainApp.gs(R.string.disconnectpumpfor30m)); + menu.add(MainApp.gs(R.string.disconnectpumpfor1h)); + menu.add(MainApp.gs(R.string.disconnectpumpfor2h)); + menu.add(MainApp.gs(R.string.disconnectpumpfor3h)); } else { - menu.add(MainApp.sResources.getString(R.string.resume)); + menu.add(MainApp.gs(R.string.resume)); } } if (!activeloop.isEnabled(PluginType.LOOP)) - menu.add(MainApp.sResources.getString(R.string.enableloop)); + menu.add(MainApp.gs(R.string.enableloop)); } else if (v == activeProfileView) { - menu.setHeaderTitle(MainApp.sResources.getString(R.string.profile)); - menu.add(MainApp.sResources.getString(R.string.danar_viewprofile)); + menu.setHeaderTitle(MainApp.gs(R.string.profile)); + menu.add(MainApp.gs(R.string.danar_viewprofile)); if (MainApp.getConfigBuilder().getActiveProfileInterface().getProfile() != null) { - menu.add(MainApp.sResources.getString(R.string.careportal_profileswitch)); + menu.add(MainApp.gs(R.string.careportal_profileswitch)); } } } @@ -496,7 +497,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, if (profile == null) return true; final LoopPlugin activeloop = ConfigBuilderPlugin.getActiveLoop(); - if (item.getTitle().equals(MainApp.sResources.getString(R.string.disableloop))) { + if (item.getTitle().equals(MainApp.gs(R.string.disableloop))) { activeloop.setPluginEnabled(PluginType.LOOP, false); activeloop.setFragmentVisible(PluginType.LOOP, false); MainApp.getConfigBuilder().storeSettings("DisablingLoop"); @@ -505,75 +506,75 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, @Override public void run() { if (!result.success) { - ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.tempbasaldeliveryerror)); + ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.tempbasaldeliveryerror)); } } }); NSUpload.uploadOpenAPSOffline(24 * 60); // upload 24h, we don't know real duration return true; - } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.enableloop))) { + } else if (item.getTitle().equals(MainApp.gs(R.string.enableloop))) { activeloop.setPluginEnabled(PluginType.LOOP, true); activeloop.setFragmentVisible(PluginType.LOOP, true); MainApp.getConfigBuilder().storeSettings("EnablingLoop"); updateGUI("suspendmenu"); NSUpload.uploadOpenAPSOffline(0); return true; - } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.resume))) { + } else if (item.getTitle().equals(MainApp.gs(R.string.resume))) { activeloop.suspendTo(0L); updateGUI("suspendmenu"); MainApp.getConfigBuilder().getCommandQueue().cancelTempBasal(true, new Callback() { @Override public void run() { if (!result.success) { - ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.tempbasaldeliveryerror)); + ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.tempbasaldeliveryerror)); } } }); NSUpload.uploadOpenAPSOffline(0); return true; - } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.suspendloopfor1h))) { + } else if (item.getTitle().equals(MainApp.gs(R.string.suspendloopfor1h))) { MainApp.getConfigBuilder().suspendLoop(60); updateGUI("suspendmenu"); return true; - } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.suspendloopfor2h))) { + } else if (item.getTitle().equals(MainApp.gs(R.string.suspendloopfor2h))) { MainApp.getConfigBuilder().suspendLoop(120); updateGUI("suspendmenu"); return true; - } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.suspendloopfor3h))) { + } else if (item.getTitle().equals(MainApp.gs(R.string.suspendloopfor3h))) { MainApp.getConfigBuilder().suspendLoop(180); updateGUI("suspendmenu"); return true; - } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.suspendloopfor10h))) { + } else if (item.getTitle().equals(MainApp.gs(R.string.suspendloopfor10h))) { MainApp.getConfigBuilder().suspendLoop(600); updateGUI("suspendmenu"); return true; - } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.disconnectpumpfor15m))) { + } else if (item.getTitle().equals(MainApp.gs(R.string.disconnectpumpfor15m))) { MainApp.getConfigBuilder().disconnectPump(15, profile); updateGUI("suspendmenu"); return true; - } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.disconnectpumpfor30m))) { + } else if (item.getTitle().equals(MainApp.gs(R.string.disconnectpumpfor30m))) { MainApp.getConfigBuilder().disconnectPump(30, profile); updateGUI("suspendmenu"); return true; - } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.disconnectpumpfor1h))) { + } else if (item.getTitle().equals(MainApp.gs(R.string.disconnectpumpfor1h))) { MainApp.getConfigBuilder().disconnectPump(60, profile); updateGUI("suspendmenu"); return true; - } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.disconnectpumpfor2h))) { + } else if (item.getTitle().equals(MainApp.gs(R.string.disconnectpumpfor2h))) { MainApp.getConfigBuilder().disconnectPump(120, profile); updateGUI("suspendmenu"); return true; - } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.disconnectpumpfor3h))) { + } else if (item.getTitle().equals(MainApp.gs(R.string.disconnectpumpfor3h))) { MainApp.getConfigBuilder().disconnectPump(180, profile); updateGUI("suspendmenu"); return true; - } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.careportal_profileswitch))) { + } else if (item.getTitle().equals(MainApp.gs(R.string.careportal_profileswitch))) { NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog(); final OptionsToShow profileswitch = CareportalFragment.PROFILESWITCHDIRECT; profileswitch.executeProfileSwitch = true; newDialog.setOptions(profileswitch, R.string.careportal_profileswitch); newDialog.show(getFragmentManager(), "NewNSTreatmentDialog"); - } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.danar_viewprofile))) { + } else if (item.getTitle().equals(MainApp.gs(R.string.danar_viewprofile))) { ProfileViewerDialog pvd = ProfileViewerDialog.newInstance(System.currentTimeMillis()); FragmentManager manager = getFragmentManager(); pvd.show(manager, "ProfileViewDialog"); @@ -753,9 +754,9 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, if (!insulinAfterConstraints.equals(wizard.calculatedTotalInsulin) || !carbsAfterConstraints.equals(quickWizardEntry.carbs())) { AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); - builder.setTitle(MainApp.sResources.getString(R.string.treatmentdeliveryerror)); + builder.setTitle(MainApp.gs(R.string.treatmentdeliveryerror)); builder.setMessage(getString(R.string.constraints_violation) + "\n" + getString(R.string.changeyourinput)); - builder.setPositiveButton(MainApp.sResources.getString(R.string.ok), null); + builder.setPositiveButton(MainApp.gs(R.string.ok), null); builder.show(); return; } @@ -765,7 +766,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, final Context context = getContext(); final AlertDialog.Builder builder = new AlertDialog.Builder(context); accepted = false; - builder.setTitle(MainApp.sResources.getString(R.string.confirmation)); + builder.setTitle(MainApp.gs(R.string.confirmation)); builder.setMessage(confirmMessage); builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { @@ -789,7 +790,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class); i.putExtra("soundid", R.raw.boluserror); i.putExtra("status", result.comment); - i.putExtra("title", MainApp.sResources.getString(R.string.tempbasaldeliveryerror)); + i.putExtra("title", MainApp.gs(R.string.tempbasaldeliveryerror)); i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); MainApp.instance().startActivity(i); } @@ -810,7 +811,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class); i.putExtra("soundid", R.raw.boluserror); i.putExtra("status", result.comment); - i.putExtra("title", MainApp.sResources.getString(R.string.treatmentdeliveryerror)); + i.putExtra("title", MainApp.gs(R.string.treatmentdeliveryerror)); i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); MainApp.instance().startActivity(i); } @@ -841,12 +842,9 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, public void onResume() { super.onResume(); MainApp.bus().register(this); - sRefreshLoop = new Runnable() { - @Override - public void run() { - scheduleUpdateGUI("refreshLoop"); - sLoopHandler.postDelayed(sRefreshLoop, 60 * 1000L); - } + sRefreshLoop = () -> { + scheduleUpdateGUI("refreshLoop"); + sLoopHandler.postDelayed(sRefreshLoop, 60 * 1000L); }; sLoopHandler.postDelayed(sRefreshLoop, 60 * 1000L); registerForContextMenu(apsModeView); @@ -894,23 +892,11 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, scheduleUpdateGUI("EventExtendedBolusChange"); } -// Handled by EventAutosensCalculationFinished -// @Subscribe -// public void onStatusEvent(final EventNewBG ev) { -// scheduleUpdateGUI("EventNewBG"); -// } - @Subscribe public void onStatusEvent(final EventNewOpenLoopNotification ev) { scheduleUpdateGUI("EventNewOpenLoopNotification"); } -// Handled by EventAutosensCalculationFinished -// @Subscribe -// public void onStatusEvent(final EventNewBasalProfile ev) { -// scheduleUpdateGUI("EventNewBasalProfile"); -// } - @Subscribe public void onStatusEvent(final EventTempTargetChange ev) { scheduleUpdateGUI("EventTempTargetChange"); @@ -920,12 +906,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, public void onStatusEvent(final EventPumpStatusChanged s) { Activity activity = getActivity(); if (activity != null) - activity.runOnUiThread(new Runnable() { - @Override - public void run() { - updatePumpStatus(s.textStatus()); - } - }); + activity.runOnUiThread(() -> updatePumpStatus(s.textStatus())); } private void hideTempRecommendation() { @@ -962,12 +943,9 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, public void run() { Activity activity = getActivity(); if (activity != null) - activity.runOnUiThread(new Runnable() { - @Override - public void run() { - updateGUI(from); - scheduledUpdate = null; - } + activity.runOnUiThread(() -> { + updateGUI(from); + scheduledUpdate = null; }); } } @@ -1032,7 +1010,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, avgdeltaView.setText("øΔ15m: " + Profile.toUnitsString(glucoseStatus.short_avgdelta, glucoseStatus.short_avgdelta * Constants.MGDL_TO_MMOLL, units) + " øΔ40m: " + Profile.toUnitsString(glucoseStatus.long_avgdelta, glucoseStatus.long_avgdelta * Constants.MGDL_TO_MMOLL, units)); } else { - deltaView.setText("Δ " + MainApp.sResources.getString(R.string.notavailable)); + deltaView.setText("Δ " + MainApp.gs(R.string.notavailable)); if (avgdeltaView != null) avgdeltaView.setText(""); } @@ -1049,25 +1027,29 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, final LoopPlugin activeloop = ConfigBuilderPlugin.getActiveLoop(); if (activeloop != null && activeloop.isEnabled(activeloop.getType()) && activeloop.isSuperBolus()) { apsModeView.setBackgroundColor(MainApp.sResources.getColor(R.color.looppumpsuspended)); - apsModeView.setText(String.format(MainApp.sResources.getString(R.string.loopsuperbolusfor), activeloop.minutesToEndOfSuspend())); + apsModeView.setText(String.format(MainApp.gs(R.string.loopsuperbolusfor), activeloop.minutesToEndOfSuspend())); + apsModeView.setTextColor(Color.WHITE); + } else if (activeloop != null && activeloop.isEnabled(activeloop.getType()) && activeloop.isDisconnected()) { + apsModeView.setBackgroundColor(MainApp.sResources.getColor(R.color.looppumpsuspended)); + apsModeView.setText(String.format(MainApp.gs(R.string.loopdisconnectedfor), activeloop.minutesToEndOfSuspend())); apsModeView.setTextColor(Color.WHITE); } else if (activeloop != null && activeloop.isEnabled(activeloop.getType()) && activeloop.isSuspended()) { apsModeView.setBackgroundColor(MainApp.sResources.getColor(R.color.looppumpsuspended)); - apsModeView.setText(String.format(MainApp.sResources.getString(R.string.loopsuspendedfor), activeloop.minutesToEndOfSuspend())); + apsModeView.setText(String.format(MainApp.gs(R.string.loopsuspendedfor), activeloop.minutesToEndOfSuspend())); apsModeView.setTextColor(Color.WHITE); } else if (pump.isSuspended()) { apsModeView.setBackgroundColor(MainApp.sResources.getColor(R.color.looppumpsuspended)); - apsModeView.setText(MainApp.sResources.getString(R.string.pumpsuspended)); + apsModeView.setText(MainApp.gs(R.string.pumpsuspended)); apsModeView.setTextColor(Color.WHITE); } else if (activeloop != null && activeloop.isEnabled(activeloop.getType())) { if (closedLoopEnabled.value()) { - apsModeView.setText(MainApp.sResources.getString(R.string.closedloop)); + apsModeView.setText(MainApp.gs(R.string.closedloop)); } else { - apsModeView.setText(MainApp.sResources.getString(R.string.openloop)); + apsModeView.setText(MainApp.gs(R.string.openloop)); } } else { apsModeView.setBackgroundColor(MainApp.sResources.getColor(R.color.loopdisabled)); - apsModeView.setText(MainApp.sResources.getString(R.string.disabledloop)); + apsModeView.setText(MainApp.gs(R.string.disabledloop)); apsModeView.setTextColor(Color.WHITE); } } else { @@ -1135,11 +1117,11 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, baseBasalView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - String fullText = MainApp.sResources.getString(R.string.pump_basebasalrate_label) + ": " + DecimalFormatter.to2Decimal(profile.getBasal()) + "U/h\n"; + String fullText = MainApp.gs(R.string.pump_basebasalrate_label) + ": " + DecimalFormatter.to2Decimal(profile.getBasal()) + "U/h\n"; if (activeTemp != null) { - fullText += MainApp.sResources.getString(R.string.pump_tempbasal_label) + ": " + activeTemp.toStringFull(); + fullText += MainApp.gs(R.string.pump_tempbasal_label) + ": " + activeTemp.toStringFull(); } - OKDialog.show(getActivity(), MainApp.sResources.getString(R.string.basal), fullText, null); + OKDialog.show(getActivity(), MainApp.gs(R.string.basal), fullText, null); } }); @@ -1173,7 +1155,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, extendedBolusView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - OKDialog.show(getActivity(), MainApp.sResources.getString(R.string.extendedbolus), extendedBolus.toString(), null); + OKDialog.show(getActivity(), MainApp.gs(R.string.extendedbolus), extendedBolus.toString(), null); } }); @@ -1192,17 +1174,14 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, activeProfileView.setText(MainApp.getConfigBuilder().getProfileName()); activeProfileView.setBackgroundColor(Color.GRAY); - tempTargetView.setOnLongClickListener(new View.OnLongClickListener() { - @Override - public boolean onLongClick(View view) { - view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); - NewNSTreatmentDialog newTTDialog = new NewNSTreatmentDialog(); - final OptionsToShow temptarget = CareportalFragment.TEMPTARGET; - temptarget.executeTempTarget = true; - newTTDialog.setOptions(temptarget, R.string.careportal_temporarytarget); - newTTDialog.show(getFragmentManager(), "NewNSTreatmentDialog"); - return true; - } + tempTargetView.setOnLongClickListener(view -> { + view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); + NewNSTreatmentDialog newTTDialog = new NewNSTreatmentDialog(); + final OptionsToShow temptarget = CareportalFragment.TEMPTARGET; + temptarget.executeTempTarget = true; + newTTDialog.setOptions(temptarget, R.string.careportal_temporarytarget); + newTTDialog.show(getFragmentManager(), "NewNSTreatmentDialog"); + return true; }); tempTargetView.setLongClickable(true); @@ -1276,14 +1255,11 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, if (shorttextmode) { String iobtext = DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U"; iobView.setText(iobtext); - iobView.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - String iobtext = DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U\n" - + getString(R.string.bolus) + ": " + DecimalFormatter.to2Decimal(bolusIob.iob) + "U\n" - + getString(R.string.basal) + ": " + DecimalFormatter.to2Decimal(basalIob.basaliob) + "U\n"; - OKDialog.show(getActivity(), MainApp.sResources.getString(R.string.iob), iobtext, null); - } + iobView.setOnClickListener(v -> { + String iobtext1 = DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U\n" + + getString(R.string.bolus) + ": " + DecimalFormatter.to2Decimal(bolusIob.iob) + "U\n" + + getString(R.string.basal) + ": " + DecimalFormatter.to2Decimal(basalIob.basaliob) + "U\n"; + OKDialog.show(getActivity(), MainApp.gs(R.string.iob), iobtext1, null); }); } else if (MainApp.sResources.getBoolean(R.bool.isTablet)) { String iobtext = DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U (" @@ -1310,159 +1286,138 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, // pump status from ns if (pumpDeviceStatusView != null) { pumpDeviceStatusView.setText(NSDeviceStatus.getInstance().getPumpStatus()); - pumpDeviceStatusView.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - OKDialog.show(getActivity(), MainApp.sResources.getString(R.string.pump), NSDeviceStatus.getInstance().getExtendedPumpStatus(), null); - } - }); + pumpDeviceStatusView.setOnClickListener(v -> OKDialog.show(getActivity(), MainApp.gs(R.string.pump), NSDeviceStatus.getInstance().getExtendedPumpStatus(), null)); } // OpenAPS status from ns if (openapsDeviceStatusView != null) { openapsDeviceStatusView.setText(NSDeviceStatus.getInstance().getOpenApsStatus()); - openapsDeviceStatusView.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - OKDialog.show(getActivity(), MainApp.sResources.getString(R.string.openaps), NSDeviceStatus.getInstance().getExtendedOpenApsStatus(), null); - } - }); + openapsDeviceStatusView.setOnClickListener(v -> OKDialog.show(getActivity(), MainApp.gs(R.string.openaps), NSDeviceStatus.getInstance().getExtendedOpenApsStatus(), null)); } // Uploader status from ns if (uploaderDeviceStatusView != null) { uploaderDeviceStatusView.setText(NSDeviceStatus.getInstance().getUploaderStatus()); - uploaderDeviceStatusView.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - OKDialog.show(getActivity(), MainApp.sResources.getString(R.string.uploader), NSDeviceStatus.getInstance().getExtendedUploaderStatus(), null); - } - }); + uploaderDeviceStatusView.setOnClickListener(v -> OKDialog.show(getActivity(), MainApp.gs(R.string.uploader), NSDeviceStatus.getInstance().getExtendedUploaderStatus(), null)); } // ****** GRAPH ******* - new Thread(new Runnable() { - @Override - public void run() { - // allign to hours - Calendar calendar = Calendar.getInstance(); - calendar.setTimeInMillis(System.currentTimeMillis()); - calendar.set(Calendar.MILLISECOND, 0); - calendar.set(Calendar.SECOND, 0); - calendar.set(Calendar.MINUTE, 0); - calendar.add(Calendar.HOUR, 1); + new Thread(() -> { + // allign to hours + Calendar calendar = Calendar.getInstance(); + calendar.setTimeInMillis(System.currentTimeMillis()); + calendar.set(Calendar.MILLISECOND, 0); + calendar.set(Calendar.SECOND, 0); + calendar.set(Calendar.MINUTE, 0); + calendar.add(Calendar.HOUR, 1); - int hoursToFetch; - final long toTime; - final long fromTime; - final long endTime; - if (predictionsAvailable && SP.getBoolean("showprediction", false)) { - int predHours = (int) (Math.ceil(finalLastRun.constraintsProcessed.getLatestPredictionsTime() - System.currentTimeMillis()) / (60 * 60 * 1000)); - predHours = Math.min(2, predHours); - predHours = Math.max(0, predHours); - hoursToFetch = rangeToDisplay - predHours; - toTime = calendar.getTimeInMillis() + 100000; // little bit more to avoid wrong rounding - Graphview specific - fromTime = toTime - hoursToFetch * 60 * 60 * 1000L; - endTime = toTime + predHours * 60 * 60 * 1000L; - } else { - hoursToFetch = rangeToDisplay; - toTime = calendar.getTimeInMillis() + 100000; // little bit more to avoid wrong rounding - Graphview specific - fromTime = toTime - hoursToFetch * 60 * 60 * 1000L; - endTime = toTime; - } + int hoursToFetch; + final long toTime; + final long fromTime; + final long endTime; + if (predictionsAvailable && SP.getBoolean("showprediction", false)) { + int predHours = (int) (Math.ceil(finalLastRun.constraintsProcessed.getLatestPredictionsTime() - System.currentTimeMillis()) / (60 * 60 * 1000)); + predHours = Math.min(2, predHours); + predHours = Math.max(0, predHours); + hoursToFetch = rangeToDisplay - predHours; + toTime = calendar.getTimeInMillis() + 100000; // little bit more to avoid wrong rounding - Graphview specific + fromTime = toTime - hoursToFetch * 60 * 60 * 1000L; + endTime = toTime + predHours * 60 * 60 * 1000L; + } else { + hoursToFetch = rangeToDisplay; + toTime = calendar.getTimeInMillis() + 100000; // little bit more to avoid wrong rounding - Graphview specific + fromTime = toTime - hoursToFetch * 60 * 60 * 1000L; + endTime = toTime; + } - final long now = System.currentTimeMillis(); + final long now = System.currentTimeMillis(); - // ------------------ 1st graph - Profiler.log(log, from + " - 1st graph - START", updateGUIStart); + // ------------------ 1st graph + Profiler.log(log, from + " - 1st graph - START", updateGUIStart); - final GraphData graphData = new GraphData(bgGraph, IobCobCalculatorPlugin.getPlugin()); + final GraphData graphData = new GraphData(bgGraph, IobCobCalculatorPlugin.getPlugin()); - // **** In range Area **** - graphData.addInRangeArea(fromTime, endTime, lowLine, highLine); + // **** In range Area **** + graphData.addInRangeArea(fromTime, endTime, lowLine, highLine); - // **** BG **** - if (predictionsAvailable && SP.getBoolean("showprediction", false)) - graphData.addBgReadings(fromTime, toTime, lowLine, highLine, finalLastRun.constraintsProcessed); - else - graphData.addBgReadings(fromTime, toTime, lowLine, highLine, null); + // **** BG **** + if (predictionsAvailable && SP.getBoolean("showprediction", false)) + graphData.addBgReadings(fromTime, toTime, lowLine, highLine, finalLastRun.constraintsProcessed); + else + graphData.addBgReadings(fromTime, toTime, lowLine, highLine, null); - // set manual x bounds to have nice steps - graphData.formatAxis(fromTime, endTime); + // set manual x bounds to have nice steps + graphData.formatAxis(fromTime, endTime); - // Treatments - graphData.addTreatments(fromTime, endTime); + // Treatments + graphData.addTreatments(fromTime, endTime); - // add basal data - if (pump.getPumpDescription().isTempBasalCapable && SP.getBoolean("showbasals", true)) { - graphData.addBasals(fromTime, now, lowLine / graphData.maxY / 1.2d); - } + // add basal data + if (pump.getPumpDescription().isTempBasalCapable && SP.getBoolean("showbasals", true)) { + graphData.addBasals(fromTime, now, lowLine / graphData.maxY / 1.2d); + } - // add target line - graphData.addTargetLine(fromTime, toTime, profile); + // add target line + graphData.addTargetLine(fromTime, toTime, profile); - // **** NOW line **** - graphData.addNowLine(now); + // **** NOW line **** + graphData.addNowLine(now); - // ------------------ 2nd graph - Profiler.log(log, from + " - 2nd graph - START", updateGUIStart); + // ------------------ 2nd graph + Profiler.log(log, from + " - 2nd graph - START", updateGUIStart); - final GraphData secondGraphData = new GraphData(iobGraph, IobCobCalculatorPlugin.getPlugin()); + final GraphData secondGraphData = new GraphData(iobGraph, IobCobCalculatorPlugin.getPlugin()); - boolean useIobForScale = false; - boolean useCobForScale = false; - boolean useDevForScale = false; - boolean useRatioForScale = false; - boolean useDSForScale = false; + boolean useIobForScale = false; + boolean useCobForScale = false; + boolean useDevForScale = false; + boolean useRatioForScale = false; + boolean useDSForScale = false; - if (SP.getBoolean("showiob", true)) { - useIobForScale = true; - } else if (SP.getBoolean("showcob", true)) { - useCobForScale = true; - } else if (SP.getBoolean("showdeviations", false)) { - useDevForScale = true; - } else if (SP.getBoolean("showratios", false)) { - useRatioForScale = true; - } else if (Config.displayDeviationSlope) { - useDSForScale = true; - } + if (SP.getBoolean("showiob", true)) { + useIobForScale = true; + } else if (SP.getBoolean("showcob", true)) { + useCobForScale = true; + } else if (SP.getBoolean("showdeviations", false)) { + useDevForScale = true; + } else if (SP.getBoolean("showratios", false)) { + useRatioForScale = true; + } else if (Config.displayDeviationSlope) { + useDSForScale = true; + } - if (SP.getBoolean("showiob", true)) - secondGraphData.addIob(fromTime, now, useIobForScale, 1d); - if (SP.getBoolean("showcob", true)) - secondGraphData.addCob(fromTime, now, useCobForScale, useCobForScale ? 1d : 0.5d); - if (SP.getBoolean("showdeviations", false)) - secondGraphData.addDeviations(fromTime, now, useDevForScale, 1d); - if (SP.getBoolean("showratios", false)) - secondGraphData.addRatio(fromTime, now, useRatioForScale, 1d); - if (Config.displayDeviationSlope) - secondGraphData.addDeviationSlope(fromTime, now, useDSForScale, 1d); + if (SP.getBoolean("showiob", true)) + secondGraphData.addIob(fromTime, now, useIobForScale, 1d); + if (SP.getBoolean("showcob", true)) + secondGraphData.addCob(fromTime, now, useCobForScale, useCobForScale ? 1d : 0.5d); + if (SP.getBoolean("showdeviations", false)) + secondGraphData.addDeviations(fromTime, now, useDevForScale, 1d); + if (SP.getBoolean("showratios", false)) + secondGraphData.addRatio(fromTime, now, useRatioForScale, 1d); + if (Config.displayDeviationSlope) + secondGraphData.addDeviationSlope(fromTime, now, useDSForScale, 1d); - // **** NOW line **** - // set manual x bounds to have nice steps - secondGraphData.formatAxis(fromTime, endTime); - secondGraphData.addNowLine(now); + // **** NOW line **** + // set manual x bounds to have nice steps + secondGraphData.formatAxis(fromTime, endTime); + secondGraphData.addNowLine(now); - // do GUI update - FragmentActivity activity = getActivity(); - if (activity != null) { - activity.runOnUiThread(new Runnable() { - @Override - public void run() { - if (SP.getBoolean("showiob", true) || SP.getBoolean("showcob", true) || SP.getBoolean("showdeviations", false) || SP.getBoolean("showratios", false) || Config.displayDeviationSlope) { - iobGraph.setVisibility(View.VISIBLE); - } else { - iobGraph.setVisibility(View.GONE); - } - // finally enforce drawing of graphs - graphData.performUpdate(); - secondGraphData.performUpdate(); - Profiler.log(log, from + " - onDataChanged", updateGUIStart); - } - }); - } + // do GUI update + FragmentActivity activity = getActivity(); + if (activity != null) { + activity.runOnUiThread(() -> { + if (SP.getBoolean("showiob", true) || SP.getBoolean("showcob", true) || SP.getBoolean("showdeviations", false) || SP.getBoolean("showratios", false) || Config.displayDeviationSlope) { + iobGraph.setVisibility(View.VISIBLE); + } else { + iobGraph.setVisibility(View.GONE); + } + // finally enforce drawing of graphs + graphData.performUpdate(); + secondGraphData.performUpdate(); + Profiler.log(log, from + " - onDataChanged", updateGUIStart); + }); } }).start(); @@ -1470,108 +1425,18 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, } //Notifications - static class RecyclerViewAdapter extends RecyclerView.Adapter { - - List notificationsList; - - RecyclerViewAdapter(List notificationsList) { - this.notificationsList = notificationsList; - } - - @Override - public NotificationsViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { - View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.overview_notification_item, viewGroup, false); - return new NotificationsViewHolder(v); - } - - @Override - public void onBindViewHolder(NotificationsViewHolder holder, int position) { - Notification notification = notificationsList.get(position); - holder.dismiss.setTag(notification); - if (Objects.equals(notification.text, MainApp.sResources.getString(R.string.nsalarm_staledata))) - holder.dismiss.setText("snooze"); - holder.text.setText(notification.text); - holder.time.setText(DateUtil.timeString(notification.date)); - if (notification.level == Notification.URGENT) - holder.cv.setBackgroundColor(ContextCompat.getColor(MainApp.instance(), R.color.notificationUrgent)); - else if (notification.level == Notification.NORMAL) - holder.cv.setBackgroundColor(ContextCompat.getColor(MainApp.instance(), R.color.notificationNormal)); - else if (notification.level == Notification.LOW) - holder.cv.setBackgroundColor(ContextCompat.getColor(MainApp.instance(), R.color.notificationLow)); - else if (notification.level == Notification.INFO) - holder.cv.setBackgroundColor(ContextCompat.getColor(MainApp.instance(), R.color.notificationInfo)); - else if (notification.level == Notification.ANNOUNCEMENT) - holder.cv.setBackgroundColor(ContextCompat.getColor(MainApp.instance(), R.color.notificationAnnouncement)); - } - - @Override - public int getItemCount() { - return notificationsList.size(); - } - - @Override - public void onAttachedToRecyclerView(RecyclerView recyclerView) { - super.onAttachedToRecyclerView(recyclerView); - } - - static class NotificationsViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { - CardView cv; - TextView time; - TextView text; - Button dismiss; - - NotificationsViewHolder(View itemView) { - super(itemView); - cv = (CardView) itemView.findViewById(R.id.notification_cardview); - time = (TextView) itemView.findViewById(R.id.notification_time); - text = (TextView) itemView.findViewById(R.id.notification_text); - dismiss = (Button) itemView.findViewById(R.id.notification_dismiss); - dismiss.setOnClickListener(this); - } - - @Override - public void onClick(View v) { - Notification notification = (Notification) v.getTag(); - switch (v.getId()) { - case R.id.notification_dismiss: - MainApp.bus().post(new EventDismissNotification(notification.id)); - if (notification.nsAlarm != null) { - BroadcastAckAlarm.handleClearAlarm(notification.nsAlarm, MainApp.instance().getApplicationContext(), 60 * 60 * 1000L); - } - // Adding current time to snooze if we got staleData - log.debug("Notification text is: " + notification.text); - if (notification.text.equals(MainApp.sResources.getString(R.string.nsalarm_staledata))) { - NotificationStore nstore = OverviewPlugin.getPlugin().notificationStore; - long msToSnooze = SP.getInt("nsalarm_staledatavalue", 15) * 60 * 1000L; - log.debug("snooze nsalarm_staledatavalue in minutes is " + SP.getInt("nsalarm_staledatavalue", 15) + "\n in ms is: " + msToSnooze + " currentTimeMillis is: " + System.currentTimeMillis()); - nstore.snoozeTo(System.currentTimeMillis() + (SP.getInt("nsalarm_staledatavalue", 15) * 60 * 1000L)); - } - break; - } - } - } - - } void updateNotifications() { - Activity activity = getActivity(); - if (activity != null) - activity.runOnUiThread(new Runnable() { - @Override - public void run() { - NotificationStore nstore = OverviewPlugin.getPlugin().notificationStore; - nstore.removeExpired(); - nstore.unSnooze(); - if (nstore.store.size() > 0) { - RecyclerViewAdapter adapter = new RecyclerViewAdapter(nstore.store); - notificationsView.setAdapter(adapter); - notificationsView.setVisibility(View.VISIBLE); - } else { - notificationsView.setVisibility(View.GONE); - } - } - }); + NotificationStore nstore = OverviewPlugin.getPlugin().notificationStore; + nstore.removeExpired(); + nstore.unSnooze(); + if (nstore.store.size() > 0) { + NotificationRecyclerViewAdapter adapter = new NotificationRecyclerViewAdapter(nstore.store); + notificationsView.setAdapter(adapter); + notificationsView.setVisibility(View.VISIBLE); + } else { + notificationsView.setVisibility(View.GONE); + } } - } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewPlugin.java index ff9b4f809c..67e494a76d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewPlugin.java @@ -72,8 +72,8 @@ public class OverviewPlugin extends PluginBase { @Subscribe public void onStatusEvent(final EventNewNotification n) { - notificationStore.add(n.notification); - MainApp.bus().post(new EventRefreshOverview("EventNewNotification")); + if (notificationStore.add(n.notification)) + MainApp.bus().post(new EventRefreshOverview("EventNewNotification")); } @Subscribe diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventOverviewBolusProgress.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventOverviewBolusProgress.java index 18c3ff1e27..6f9526369e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventOverviewBolusProgress.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventOverviewBolusProgress.java @@ -3,8 +3,7 @@ package info.nightscout.androidaps.plugins.Overview.events; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import info.nightscout.androidaps.data.PumpEnactResult; -import info.nightscout.androidaps.db.Treatment; +import info.nightscout.androidaps.plugins.Treatments.Treatment; import info.nightscout.androidaps.events.Event; public class EventOverviewBolusProgress extends Event { 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 7d1cd07b69..1a8816d0b3 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 @@ -23,7 +23,6 @@ import info.nightscout.androidaps.db.CareportalEvent; import info.nightscout.androidaps.db.ExtendedBolus; import info.nightscout.androidaps.db.ProfileSwitch; import info.nightscout.androidaps.db.TempTarget; -import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData; import info.nightscout.androidaps.plugins.IobCobCalculator.BasalData; @@ -38,6 +37,7 @@ import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLab 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.androidaps.plugins.Treatments.Treatment; import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; import info.nightscout.utils.Round; @@ -334,7 +334,10 @@ public class GraphData { Scale iobScale = new Scale(); for (long time = fromTime; time <= toTime; time += 5 * 60 * 1000L) { - double iob = IobCobCalculatorPlugin.getPlugin().calculateFromTreatmentsAndTempsSynchronized(time).iob; + Profile profile = MainApp.getConfigBuilder().getProfile(time); + double iob = 0d; + if (profile != null) + iob = IobCobCalculatorPlugin.getPlugin().calculateFromTreatmentsAndTempsSynchronized(time, profile).iob; if (Math.abs(lastIob - iob) > 0.02) { if (Math.abs(lastIob - iob) > 0.2) iobArray.add(new ScaledDataPoint(time, lastIob, iobScale)); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/notifications/NotificationRecyclerViewAdapter.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/notifications/NotificationRecyclerViewAdapter.java new file mode 100644 index 0000000000..6087ae0210 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/notifications/NotificationRecyclerViewAdapter.java @@ -0,0 +1,107 @@ +package info.nightscout.androidaps.plugins.Overview.notifications; + +import android.support.v4.content.ContextCompat; +import android.support.v7.widget.CardView; +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 org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; +import java.util.Objects; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.plugins.NSClientInternal.broadcasts.BroadcastAckAlarm; +import info.nightscout.androidaps.plugins.Overview.OverviewPlugin; +import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; +import info.nightscout.utils.DateUtil; +import info.nightscout.utils.SP; + +public class NotificationRecyclerViewAdapter extends RecyclerView.Adapter { + private static Logger log = LoggerFactory.getLogger(NotificationRecyclerViewAdapter.class); + + private List notificationsList; + + public NotificationRecyclerViewAdapter(List notificationsList) { + this.notificationsList = notificationsList; + } + + @Override + public NotificationsViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { + View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.overview_notification_item, viewGroup, false); + return new NotificationsViewHolder(v); + } + + @Override + public void onBindViewHolder(NotificationsViewHolder holder, int position) { + Notification notification = notificationsList.get(position); + holder.dismiss.setTag(notification); + if (Objects.equals(notification.text, MainApp.gs(R.string.nsalarm_staledata))) + holder.dismiss.setText("snooze"); + holder.text.setText(notification.text); + holder.time.setText(DateUtil.timeString(notification.date)); + if (notification.level == Notification.URGENT) + holder.cv.setBackgroundColor(ContextCompat.getColor(MainApp.instance(), R.color.notificationUrgent)); + else if (notification.level == Notification.NORMAL) + holder.cv.setBackgroundColor(ContextCompat.getColor(MainApp.instance(), R.color.notificationNormal)); + else if (notification.level == Notification.LOW) + holder.cv.setBackgroundColor(ContextCompat.getColor(MainApp.instance(), R.color.notificationLow)); + else if (notification.level == Notification.INFO) + holder.cv.setBackgroundColor(ContextCompat.getColor(MainApp.instance(), R.color.notificationInfo)); + else if (notification.level == Notification.ANNOUNCEMENT) + holder.cv.setBackgroundColor(ContextCompat.getColor(MainApp.instance(), R.color.notificationAnnouncement)); + } + + @Override + public int getItemCount() { + return notificationsList.size(); + } + + @Override + public void onAttachedToRecyclerView(RecyclerView recyclerView) { + super.onAttachedToRecyclerView(recyclerView); + } + + static class NotificationsViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { + CardView cv; + TextView time; + TextView text; + Button dismiss; + + NotificationsViewHolder(View itemView) { + super(itemView); + cv = (CardView) itemView.findViewById(R.id.notification_cardview); + time = (TextView) itemView.findViewById(R.id.notification_time); + text = (TextView) itemView.findViewById(R.id.notification_text); + dismiss = (Button) itemView.findViewById(R.id.notification_dismiss); + dismiss.setOnClickListener(this); + } + + @Override + public void onClick(View v) { + Notification notification = (Notification) v.getTag(); + switch (v.getId()) { + case R.id.notification_dismiss: + MainApp.bus().post(new EventDismissNotification(notification.id)); + if (notification.nsAlarm != null) { + BroadcastAckAlarm.handleClearAlarm(notification.nsAlarm, MainApp.instance().getApplicationContext(), 60 * 60 * 1000L); + } + // Adding current time to snooze if we got staleData + log.debug("Notification text is: " + notification.text); + if (notification.text.equals(MainApp.sResources.getString(R.string.nsalarm_staledata))) { + NotificationStore nstore = OverviewPlugin.getPlugin().notificationStore; + long msToSnooze = SP.getInt("nsalarm_staledatavalue", 15) * 60 * 1000L; + log.debug("snooze nsalarm_staledatavalue in minutes is " + SP.getInt("nsalarm_staledatavalue", 15) + "\n in ms is: " + msToSnooze + " currentTimeMillis is: " + System.currentTimeMillis()); + nstore.snoozeTo(System.currentTimeMillis() + (SP.getInt("nsalarm_staledatavalue", 15) * 60 * 1000L)); + } + break; + } + } + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/notifications/NotificationStore.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/notifications/NotificationStore.java index aa61b48097..f0bb147982 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/notifications/NotificationStore.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/notifications/NotificationStore.java @@ -1,5 +1,7 @@ package info.nightscout.androidaps.plugins.Overview.notifications; +import android.annotation.SuppressLint; +import android.app.NotificationChannel; import android.app.NotificationManager; import android.content.Context; import android.content.Intent; @@ -8,6 +10,7 @@ import android.graphics.BitmapFactory; import android.media.AudioAttributes; import android.media.RingtoneManager; import android.net.Uri; +import android.os.Build; import android.support.v4.app.NotificationCompat; import org.slf4j.Logger; @@ -28,11 +31,15 @@ import info.nightscout.utils.SP; */ public class NotificationStore { + + public static final String CHANNEL_ID = "AndroidAPS-Overview"; + private static Logger log = LoggerFactory.getLogger(NotificationStore.class); public List store = new ArrayList(); public long snoozedUntil = 0L; public NotificationStore() { + createNotificationChannel(); } public class NotificationComparator implements Comparator { @@ -42,13 +49,13 @@ public class NotificationStore { } } - public synchronized void add(Notification n) { + public synchronized boolean add(Notification n) { log.info("Notification received: " + n.text); for (Notification storeNotification : store) { if (storeNotification.id == n.id) { storeNotification.date = n.date; storeNotification.validTo = n.validTo; - return; + return false; } } store.add(n); @@ -64,6 +71,7 @@ public class NotificationStore { } Collections.sort(store, new NotificationComparator()); + return true; } public synchronized boolean remove(int id) { @@ -110,7 +118,7 @@ public class NotificationStore { Bitmap largeIcon = BitmapFactory.decodeResource(context.getResources(), R.mipmap.blueowl); Uri sound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM); NotificationCompat.Builder notificationBuilder = - new NotificationCompat.Builder(context) + new NotificationCompat.Builder(context, CHANNEL_ID) .setSmallIcon(R.drawable.ic_notification) .setLargeIcon(largeIcon) .setContentText(n.text) @@ -127,4 +135,17 @@ public class NotificationStore { } mgr.notify(n.id, notificationBuilder.build()); } + + private void createNotificationChannel() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + + NotificationManager mNotificationManager = + (NotificationManager) MainApp.instance().getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE); + @SuppressLint("WrongConstant") NotificationChannel channel = new NotificationChannel(CHANNEL_ID, + CHANNEL_ID, + NotificationManager.IMPORTANCE_HIGH); + mNotificationManager.createNotificationChannel(channel); + } + } + } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Persistentnotification/PersistentNotificationPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Persistentnotification/PersistentNotificationPlugin.java index ee04843080..789c9df143 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Persistentnotification/PersistentNotificationPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Persistentnotification/PersistentNotificationPlugin.java @@ -1,11 +1,14 @@ package info.nightscout.androidaps.plugins.Persistentnotification; +import android.annotation.SuppressLint; +import android.app.NotificationChannel; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; +import android.os.Build; import android.support.v4.app.NotificationCompat; import android.support.v4.app.TaskStackBuilder; @@ -41,6 +44,8 @@ import info.nightscout.utils.DecimalFormatter; public class PersistentNotificationPlugin extends PluginBase { + public static final String CHANNEL_ID = "AndroidAPS-Ongoing"; + private static final int ONGOING_NOTIFICATION_ID = 4711; private final Context ctx; @@ -57,10 +62,23 @@ public class PersistentNotificationPlugin extends PluginBase { @Override protected void onStart() { MainApp.bus().register(this); + createNotificationChannel(); updateNotification(); super.onStart(); } + private void createNotificationChannel() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + + NotificationManager mNotificationManager = + (NotificationManager) ctx.getSystemService(Context.NOTIFICATION_SERVICE); + @SuppressLint("WrongConstant") NotificationChannel channel = new NotificationChannel(CHANNEL_ID, + CHANNEL_ID, + NotificationManager.IMPORTANCE_HIGH); + mNotificationManager.createNotificationChannel(channel); + } + } + @Override protected void onStop() { MainApp.bus().unregister(this); @@ -118,7 +136,7 @@ public class PersistentNotificationPlugin extends PluginBase { line3 += " - " + MainApp.getConfigBuilder().getProfileName(); - NotificationCompat.Builder builder = new NotificationCompat.Builder(ctx); + NotificationCompat.Builder builder = new NotificationCompat.Builder(ctx, CHANNEL_ID); builder.setOngoing(true); builder.setCategory(NotificationCompat.CATEGORY_STATUS); builder.setSmallIcon(R.drawable.ic_notification); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfileFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfileFragment.java index fb8e2166e0..a325f08ad2 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfileFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfileFragment.java @@ -4,6 +4,7 @@ package info.nightscout.androidaps.plugins.ProfileLocal; import android.app.Activity; import android.os.Bundle; import android.support.annotation.NonNull; +import android.support.v4.app.FragmentTransaction; import android.text.Editable; import android.text.TextWatcher; import android.view.LayoutInflater; @@ -48,45 +49,43 @@ public class LocalProfileFragment extends SubscriberFragment { TimeListEdit basalView; TimeListEdit targetView; Button profileswitchButton; + Button resetButton; + Button saveButton; + TextView invalidProfile; + Runnable save = () -> { + doEdit(); + if (basalView != null) { + basalView.updateLabel(MainApp.sResources.getString(R.string.nsprofileview_basal_label) + ": " + getSumLabel()); + } + }; + + TextWatcher textWatch = new TextWatcher() { + + @Override + public void afterTextChanged(Editable s) { + } + + @Override + public void beforeTextChanged(CharSequence s, int start, + int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, + int before, int count) { + LocalProfilePlugin.getPlugin().dia = SafeParse.stringToDouble(diaView.getText().toString()); + doEdit(); + } + }; + @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { try { - Runnable save = new Runnable() { - @Override - public void run() { - LocalProfilePlugin.getPlugin().storeSettings(); - if (basalView != null) { - basalView.updateLabel(MainApp.sResources.getString(R.string.nsprofileview_basal_label) + ": " + getSumLabel()); - } - updateGUI(); - } - }; - - TextWatcher textWatch = new TextWatcher() { - - @Override - public void afterTextChanged(Editable s) { - } - - @Override - public void beforeTextChanged(CharSequence s, int start, - int count, int after) { - } - - @Override - public void onTextChanged(CharSequence s, int start, - int before, int count) { - LocalProfilePlugin.getPlugin().dia = SafeParse.stringToDouble(diaView.getText().toString()); - LocalProfilePlugin.getPlugin().storeSettings(); - updateGUI(); - } - }; PumpDescription pumpDescription = ConfigBuilderPlugin.getActivePump().getPumpDescription(); - View layout = inflater.inflate(R.layout.localprofile_fragment, container, false); diaView = (NumberPicker) layout.findViewById(R.id.localprofile_dia); diaView.setParams(LocalProfilePlugin.getPlugin().dia, 2d, 48d, 0.1d, new DecimalFormat("0.0"), false, textWatch); @@ -97,6 +96,10 @@ public class LocalProfileFragment extends SubscriberFragment { basalView = new TimeListEdit(getContext(), layout, R.id.localprofile_basal, MainApp.sResources.getString(R.string.nsprofileview_basal_label) + ": " + getSumLabel(), LocalProfilePlugin.getPlugin().basal, null, pumpDescription.basalMinimumRate, 10, 0.01d, new DecimalFormat("0.00"), save); targetView = new TimeListEdit(getContext(), layout, R.id.localprofile_target, MainApp.sResources.getString(R.string.nsprofileview_target_label) + ":", LocalProfilePlugin.getPlugin().targetLow, LocalProfilePlugin.getPlugin().targetHigh, 3d, 200, 0.1d, new DecimalFormat("0.0"), save); profileswitchButton = (Button) layout.findViewById(R.id.localprofile_profileswitch); + resetButton = (Button) layout.findViewById(R.id.localprofile_reset); + saveButton = (Button) layout.findViewById(R.id.localprofile_save); + + invalidProfile = (TextView) layout.findViewById(R.id.invalidprofile); if (!ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable) { @@ -112,7 +115,7 @@ public class LocalProfileFragment extends SubscriberFragment { LocalProfilePlugin.getPlugin().mgdl = mgdlView.isChecked(); LocalProfilePlugin.getPlugin().mmol = !LocalProfilePlugin.getPlugin().mgdl; mmolView.setChecked(LocalProfilePlugin.getPlugin().mmol); - LocalProfilePlugin.getPlugin().storeSettings(); + doEdit(); } }); mmolView.setOnClickListener(new View.OnClickListener() { @@ -121,7 +124,7 @@ public class LocalProfileFragment extends SubscriberFragment { LocalProfilePlugin.getPlugin().mmol = mmolView.isChecked(); LocalProfilePlugin.getPlugin().mgdl = !LocalProfilePlugin.getPlugin().mmol; mgdlView.setChecked(LocalProfilePlugin.getPlugin().mgdl); - LocalProfilePlugin.getPlugin().storeSettings(); + doEdit(); } }); @@ -136,6 +139,25 @@ public class LocalProfileFragment extends SubscriberFragment { } }); + resetButton.setOnClickListener(view -> { + LocalProfilePlugin.getPlugin().loadSettings(); + mgdlView.setChecked(LocalProfilePlugin.getPlugin().mgdl); + mmolView.setChecked(LocalProfilePlugin.getPlugin().mmol); + diaView.setParams(LocalProfilePlugin.getPlugin().dia, 2d, 48d, 0.1d, new DecimalFormat("0.0"), false, textWatch); + icView = new TimeListEdit(getContext(), layout, R.id.localprofile_ic, MainApp.sResources.getString(R.string.nsprofileview_ic_label) + ":", LocalProfilePlugin.getPlugin().ic, null, 0.5, 50d, 0.1d, new DecimalFormat("0.0"), save); + isfView = new TimeListEdit(getContext(), layout, R.id.localprofile_isf, MainApp.sResources.getString(R.string.nsprofileview_isf_label) + ":", LocalProfilePlugin.getPlugin().isf, null, 0.5, 500d, 0.1d, new DecimalFormat("0.0"), save); + basalView = new TimeListEdit(getContext(), layout, R.id.localprofile_basal, MainApp.sResources.getString(R.string.nsprofileview_basal_label) + ": " + getSumLabel(), LocalProfilePlugin.getPlugin().basal, null, pumpDescription.basalMinimumRate, 10, 0.01d, new DecimalFormat("0.00"), save); + targetView = new TimeListEdit(getContext(), layout, R.id.localprofile_target, MainApp.sResources.getString(R.string.nsprofileview_target_label) + ":", LocalProfilePlugin.getPlugin().targetLow, LocalProfilePlugin.getPlugin().targetHigh, 3d, 200, 0.1d, new DecimalFormat("0.0"), save); + updateGUI(); + }); + + saveButton.setOnClickListener(view -> { + if(!LocalProfilePlugin.getPlugin().isValidEditState()){ + return; //Should not happen as saveButton should not be visible if not valid + } + LocalProfilePlugin.getPlugin().storeSettings(); + updateGUI(); + }); return layout; } catch (Exception e) { @@ -146,9 +168,14 @@ public class LocalProfileFragment extends SubscriberFragment { return null; } + public void doEdit() { + LocalProfilePlugin.getPlugin().setEdited(true); + updateGUI(); + } + @NonNull public String getSumLabel() { - ProfileStore profile = LocalProfilePlugin.getPlugin().getProfile(); + ProfileStore profile = LocalProfilePlugin.getPlugin().createProfileStore(); if (profile != null) return " ∑" + DecimalFormatter.to2Decimal(profile.getDefaultProfile().baseBasalSum()) + "U"; else @@ -167,16 +194,39 @@ public class LocalProfileFragment extends SubscriberFragment { activity.runOnUiThread(new Runnable() { @Override public void run() { - boolean isValid = LocalProfilePlugin.getPlugin().getProfile() != null && LocalProfilePlugin.getPlugin().getProfile().getDefaultProfile().isValid(MainApp.gs(R.string.localprofile)); - if (!ConfigBuilderPlugin.getActivePump().isInitialized() || ConfigBuilderPlugin.getActivePump().isSuspended() || !isValid) { - profileswitchButton.setVisibility(View.GONE); + boolean isValid = LocalProfilePlugin.getPlugin().isValidEditState(); + boolean isEdited = LocalProfilePlugin.getPlugin().isEdited(); + if (isValid) { + invalidProfile.setVisibility(View.GONE); //show invalid profile + + if (isEdited || !ConfigBuilderPlugin.getActivePump().isInitialized() || ConfigBuilderPlugin.getActivePump().isSuspended()) { + //edited profile -> save first + //pump not initialized -> don't update profile yet + profileswitchButton.setVisibility(View.GONE); + } else { + profileswitchButton.setVisibility(View.VISIBLE); + } + + if(isEdited){ + saveButton.setVisibility(View.VISIBLE); + } else { + saveButton.setVisibility(View.GONE); + + } + + } else { - profileswitchButton.setVisibility(View.VISIBLE); - } - if (isValid) - invalidProfile.setVisibility(View.GONE); - else invalidProfile.setVisibility(View.VISIBLE); + profileswitchButton.setVisibility(View.GONE); + saveButton.setVisibility(View.GONE); //don't save an invalid profile + } + + //Show reset button iff data was edited + if(isEdited) { + resetButton.setVisibility(View.VISIBLE); + } else { + resetButton.setVisibility(View.GONE); + } } }); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfilePlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfilePlugin.java index 512d452289..30e0d9b064 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfilePlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfilePlugin.java @@ -2,6 +2,7 @@ package info.nightscout.androidaps.plugins.ProfileLocal; import android.content.SharedPreferences; import android.preference.PreferenceManager; +import android.support.annotation.NonNull; import org.json.JSONArray; import org.json.JSONException; @@ -40,6 +41,15 @@ public class LocalProfilePlugin extends PluginBase implements ProfileInterface { private static final String DEFAULTARRAY = "[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":0}]"; + public boolean isEdited() { + return edited; + } + + public void setEdited(boolean edited) { + this.edited = edited; + } + + boolean edited; boolean mgdl; boolean mmol; Double dia; @@ -59,7 +69,7 @@ public class LocalProfilePlugin extends PluginBase implements ProfileInterface { loadSettings(); } - public void storeSettings() { + public synchronized void storeSettings() { SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext()); SharedPreferences.Editor editor = settings.edit(); editor.putBoolean(LOCAL_PROFILE + "mmol", mmol); @@ -72,12 +82,13 @@ public class LocalProfilePlugin extends PluginBase implements ProfileInterface { editor.putString(LOCAL_PROFILE + "targethigh", targetHigh.toString()); editor.apply(); - createConvertedProfile(); + createAndStoreConvertedProfile(); + edited = false; if (Config.logPrefsChange) log.debug("Storing settings: " + getRawProfile().getData().toString()); } - public void loadSettings() { + public synchronized void loadSettings() { if (Config.logPrefsChange) log.debug("Loading stored settings"); @@ -124,6 +135,8 @@ public class LocalProfilePlugin extends PluginBase implements ProfileInterface { } catch (JSONException ignored) { } } + edited = false; + createAndStoreConvertedProfile(); } /* @@ -164,7 +177,16 @@ public class LocalProfilePlugin extends PluginBase implements ProfileInterface { "created_at": "2016-06-16T08:34:41.256Z" } */ - private void createConvertedProfile() { + private void createAndStoreConvertedProfile() { + convertedProfile = createProfileStore(); + } + + public synchronized boolean isValidEditState() { + return createProfileStore().getDefaultProfile().isValid(MainApp.gs(R.string.localprofile)); + } + + @NonNull + public ProfileStore createProfileStore() { JSONObject json = new JSONObject(); JSONObject store = new JSONObject(); JSONObject profile = new JSONObject(); @@ -183,21 +205,17 @@ public class LocalProfilePlugin extends PluginBase implements ProfileInterface { } catch (JSONException e) { log.error("Unhandled exception", e); } - convertedProfile = new ProfileStore(json); + return new ProfileStore(json); } @Override public ProfileStore getProfile() { - if (convertedProfile == null) - createConvertedProfile(); if (!convertedProfile.getDefaultProfile().isValid(MainApp.gs(R.string.localprofile))) return null; return convertedProfile; } public ProfileStore getRawProfile() { - if (convertedProfile == null) - createConvertedProfile(); return convertedProfile; } @@ -208,8 +226,6 @@ public class LocalProfilePlugin extends PluginBase implements ProfileInterface { @Override public String getProfileName() { - if (convertedProfile == null) - createConvertedProfile(); return DecimalFormatter.to2Decimal(convertedProfile.getDefaultProfile().percentageBasalSum()) + "U "; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboAlertHistoryDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboAlertHistoryDialog.java deleted file mode 100644 index 6f30b3aed9..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboAlertHistoryDialog.java +++ /dev/null @@ -1,52 +0,0 @@ -package info.nightscout.androidaps.plugins.PumpCombo; - -import android.os.Bundle; -import android.support.v4.app.DialogFragment; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; - -import java.text.DateFormat; -import java.util.List; - -import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.history.PumpAlert; -import info.nightscout.androidaps.R; - -public class ComboAlertHistoryDialog extends DialogFragment { - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View layout = inflater.inflate(R.layout.combo_alert_history_fragment, container, false); - TextView text = (TextView) layout.findViewById(R.id.combo_error_history_text); - List errors = ComboPlugin.getPlugin().getPump().errorHistory; - if (errors.isEmpty()) { - text.setText(R.string.combo_no_alert_data_note); - } else { - StringBuilder sb = new StringBuilder(); - DateFormat dateTimeFormatter = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT); - boolean first = true; - for (PumpAlert error : errors) { - if (first) { - first = false; - } else { - sb.append("\n"); - } - sb.append(dateTimeFormatter.format(error.timestamp)); - sb.append(" "); - sb.append(error.message); - if (error.warningCode != null) { - sb.append(" (W"); - sb.append(error.warningCode); - sb.append(")"); - } - if (error.errorCode != null) { - sb.append(" (E"); - sb.append(error.errorCode); - sb.append(")"); - } - } - text.setText(sb.toString()); - } - return layout; - } -} 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 9753f35ea4..14fdd3c219 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,6 +6,7 @@ import android.app.AlertDialog; import android.graphics.Color; import android.graphics.Typeface; import android.os.Bundle; +import android.support.annotation.NonNull; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -16,7 +17,6 @@ import com.squareup.otto.Subscribe; import org.apache.commons.lang3.StringUtils; -import info.nightscout.androidaps.Config; import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.PumpState; import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.history.Bolus; import info.nightscout.androidaps.MainApp; @@ -29,7 +29,7 @@ import info.nightscout.androidaps.queue.events.EventQueueChanged; import info.nightscout.utils.DateUtil; import info.nightscout.utils.SP; -public class ComboFragment extends SubscriberFragment implements View.OnClickListener, View.OnLongClickListener { +public class ComboFragment extends SubscriberFragment implements View.OnClickListener { private TextView stateView; private TextView activityView; private TextView batteryView; @@ -39,43 +39,28 @@ public class ComboFragment extends SubscriberFragment implements View.OnClickLis private TextView baseBasalRate; private TextView tempBasalText; private Button refreshButton; - private Button alertsButton; - private Button tddsButton; private TextView bolusCount; private TextView tbrCount; - private Button fullHistoryButton; @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.combopump_fragment, container, false); - stateView = (TextView) view.findViewById(R.id.combo_state); - activityView = (TextView) view.findViewById(R.id.combo_activity); - batteryView = (TextView) view.findViewById(R.id.combo_pumpstate_battery); - reservoirView = (TextView) view.findViewById(R.id.combo_insulinstate); - lastBolusView = (TextView) view.findViewById(R.id.combo_last_bolus); - 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); - bolusCount = (TextView) view.findViewById(R.id.combo_bolus_count); - tbrCount = (TextView) view.findViewById(R.id.combo_tbr_count); + stateView = view.findViewById(R.id.combo_state); + activityView = view.findViewById(R.id.combo_activity); + batteryView = view.findViewById(R.id.combo_pumpstate_battery); + reservoirView = view.findViewById(R.id.combo_insulinstate); + lastBolusView = view.findViewById(R.id.combo_last_bolus); + lastConnectionView = view.findViewById(R.id.combo_lastconnection); + baseBasalRate = view.findViewById(R.id.combo_base_basal_rate); + tempBasalText = view.findViewById(R.id.combo_temp_basal); + bolusCount = view.findViewById(R.id.combo_bolus_count); + tbrCount = view.findViewById(R.id.combo_tbr_count); - refreshButton = (Button) view.findViewById(R.id.combo_refresh_button); + refreshButton = view.findViewById(R.id.combo_refresh_button); refreshButton.setOnClickListener(this); - alertsButton = (Button) view.findViewById(R.id.combo_alerts_button); - alertsButton.setOnClickListener(this); - alertsButton.setOnLongClickListener(this); - - tddsButton = (Button) view.findViewById(R.id.combo_tdds_button); - tddsButton.setOnClickListener(this); - tddsButton.setOnLongClickListener(this); - - fullHistoryButton = (Button) view.findViewById(R.id.combo_full_history_button); - fullHistoryButton.setOnClickListener(this); - fullHistoryButton.setOnLongClickListener(this); - updateGUI(); return view; } @@ -99,75 +84,9 @@ public class ComboFragment extends SubscriberFragment implements View.OnClickLis } }); break; - case R.id.combo_alerts_button: - ComboAlertHistoryDialog ehd = new ComboAlertHistoryDialog(); - ehd.show(getFragmentManager(), ComboAlertHistoryDialog.class.getSimpleName()); - break; - case R.id.combo_tdds_button: - ComboTddHistoryDialog thd = new ComboTddHistoryDialog(); - thd.show(getFragmentManager(), ComboTddHistoryDialog.class.getSimpleName()); - break; - case R.id.combo_full_history_button: - AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); - builder.setMessage(R.string.combo_read_full_history_info); - builder.show(); - break; } } - // TODO clean up when when queuing - @Override - public boolean onLongClick(View view) { - switch (view.getId()) { - case R.id.combo_alerts_button: - alertsButton.setEnabled(false); - tddsButton.setEnabled(false); - fullHistoryButton.setEnabled(false); - new Thread(() -> ComboPlugin.getPlugin().readAlertData(new Callback() { - @Override - public void run() { - runOnUiThread(() -> { - alertsButton.setEnabled(true); - tddsButton.setEnabled(true); - fullHistoryButton.setEnabled(true); - }); - } - })).start(); - return true; - case R.id.combo_tdds_button: - alertsButton.setEnabled(false); - tddsButton.setEnabled(false); - fullHistoryButton.setEnabled(false); - new Thread(() -> ComboPlugin.getPlugin().readTddData(new Callback() { - @Override - public void run() { - runOnUiThread(() -> { - alertsButton.setEnabled(true); - tddsButton.setEnabled(true); - fullHistoryButton.setEnabled(true); - }); - } - })).start(); - return true; - case R.id.combo_full_history_button: - alertsButton.setEnabled(false); - tddsButton.setEnabled(false); - fullHistoryButton.setEnabled(false); - new Thread(() -> ComboPlugin.getPlugin().readAllPumpData(new Callback() { - @Override - public void run() { - runOnUiThread(() -> { - alertsButton.setEnabled(true); - tddsButton.setEnabled(true); - fullHistoryButton.setEnabled(true); - }); - } - })).start(); - return true; - } - return false; - } - @Subscribe public void onStatusEvent(final EventComboPumpUpdateGUI ignored) { updateGUI(); @@ -210,13 +129,6 @@ public class ComboFragment extends SubscriberFragment implements View.OnClickLis } if (plugin.isInitialized()) { - refreshButton.setVisibility(View.VISIBLE); - if (Config.enableComboBetaFeatures) { - alertsButton.setVisibility(View.VISIBLE); - tddsButton.setVisibility(View.VISIBLE); - } - fullHistoryButton.setVisibility(View.VISIBLE); - // battery batteryView.setTextSize(20); if (ps.batteryState == PumpState.EMPTY) { 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 43d855dab1..2ba3ba782a 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 @@ -28,7 +28,7 @@ import info.nightscout.androidaps.db.CareportalEvent; import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.TDD; import info.nightscout.androidaps.db.TemporaryBasal; -import info.nightscout.androidaps.db.Treatment; +import info.nightscout.androidaps.plugins.Treatments.Treatment; import info.nightscout.androidaps.events.EventInitializationChanged; import info.nightscout.androidaps.events.EventRefreshOverview; import info.nightscout.androidaps.interfaces.Constraint; @@ -68,8 +68,8 @@ import info.nightscout.utils.SP; */ public class ComboPlugin extends PluginBase implements PumpInterface, ConstraintsInterface { private static final Logger log = LoggerFactory.getLogger(ComboPlugin.class); - public static final String COMBO_TBRS_SET = "combo_tbrs_set"; - public static final String COMBO_BOLUSES_DELIVERED = "combo_boluses_delivered"; + static final String COMBO_TBRS_SET = "combo_tbrs_set"; + static final String COMBO_BOLUSES_DELIVERED = "combo_boluses_delivered"; private static ComboPlugin plugin = null; @@ -112,6 +112,9 @@ public class ComboPlugin extends PluginBase implements PumpInterface, Constraint pumpDescription.storesCarbInfo = false; pumpDescription.is30minBasalRatesCapable = false; + + pumpDescription.supportsTDDs = true; + pumpDescription.needsManualTDDLoad = true; } @NonNull @@ -1124,11 +1127,11 @@ public class ComboPlugin extends PluginBase implements PumpInterface, Constraint */ private boolean readHistory(@Nullable PumpHistoryRequest request) { CommandResult historyResult = runCommand(MainApp.gs(R.string.combo_activity_reading_pump_history), 3, () -> ruffyScripter.readHistory(request)); - if (!historyResult.success) { + PumpHistory history = historyResult.history; + if (!historyResult.success || history == null) { return false; } - PumpHistory history = historyResult.history; updateDbFromPumpHistory(history); // update local cache @@ -1171,64 +1174,6 @@ public class ComboPlugin extends PluginBase implements PumpInterface, Constraint return pumpBolus.timestamp + Math.min(secondsFromBolus, 59 * 1000); } - // TODO use queue once ready - void readTddData(Callback post) { -// ConfigBuilderPlugin.getCommandQueue().custom(new Callback() { -// @Override -// public void run() { - readHistory(new PumpHistoryRequest().tddHistory(PumpHistoryRequest.FULL)); -// } -// }, post); - if (post != null) { - post.run(); - } - CommandQueue commandQueue = ConfigBuilderPlugin.getCommandQueue(); - if (commandQueue.performing() == null && commandQueue.size() == 0) { - ruffyScripter.disconnect(); - } - } - - // TODO use queue once ready - void readAlertData(Callback post) { -// ConfigBuilderPlugin.getCommandQueue().custom(new Callback() { -// @Override -// public void run() { - readHistory(new PumpHistoryRequest().pumpErrorHistory(PumpHistoryRequest.FULL)); -// } -// }, post); - if (post != null) { - post.run(); - } - CommandQueue commandQueue = ConfigBuilderPlugin.getCommandQueue(); - if (commandQueue.performing() == null && commandQueue.size() == 0) { - ruffyScripter.disconnect(); - } - } - - // TODO use queue once ready - void readAllPumpData(Callback post) { -// ConfigBuilderPlugin.getCommandQueue().custom(new Callback() { -// @Override -// public void run() { - readHistory(new PumpHistoryRequest() - .bolusHistory(PumpHistoryRequest.FULL) - .pumpErrorHistory(PumpHistoryRequest.FULL) - .tddHistory(PumpHistoryRequest.FULL)); - CommandResult readBasalResult = runCommand(MainApp.gs(R.string.combo_actvity_reading_basal_profile), 2, ruffyScripter::readBasalProfile); - if (readBasalResult.success) { - pump.basalProfile = readBasalResult.basalProfile; - } -// } -// }, post); - if (post != null) { - post.run(); - } - CommandQueue commandQueue = ConfigBuilderPlugin.getCommandQueue(); - if (commandQueue.performing() == null && commandQueue.size() == 0) { - ruffyScripter.disconnect(); - } - } - /** * Reads QuickInfo to update reservoir level and determine if new boluses exist on the pump * and if so, queries the history for all new records. @@ -1378,7 +1323,6 @@ public class ComboPlugin extends PluginBase implements PumpInterface, Constraint @Override public PumpEnactResult loadTDDs() { - PumpEnactResult result = new PumpEnactResult(); result.success = readHistory(new PumpHistoryRequest().tddHistory(PumpHistoryRequest.FULL)); if (result.success) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboTddHistoryDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboTddHistoryDialog.java deleted file mode 100644 index 7da1c8ba30..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboTddHistoryDialog.java +++ /dev/null @@ -1,58 +0,0 @@ -package info.nightscout.androidaps.plugins.PumpCombo; - -import android.os.Bundle; -import android.support.v4.app.DialogFragment; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; - -import java.text.DateFormat; -import java.util.List; -import java.util.Locale; - -import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.history.Tdd; -import info.nightscout.androidaps.R; - -public class ComboTddHistoryDialog extends DialogFragment { - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View layout = inflater.inflate(R.layout.combo_tdd_history_fragment, container, false); - TextView text = (TextView) layout.findViewById(R.id.combo_tdd_history_text); - List tdds = ComboPlugin.getPlugin().getPump().tddHistory; - if (tdds.isEmpty()) { - text.setText(R.string.combo_no_tdd_data_note); - } else { - StringBuilder sb = new StringBuilder(); - DateFormat dateFormatter = DateFormat.getDateInstance(); - double avg = 0; - double min = 999; - double max = 0; - int count = 0; - for (Tdd tdd : tdds) { - if (tdd.total > 0) { - avg += tdd.total; - count++; - } - if (tdd.total < min) min = tdd.total; - if (tdd.total > max) max = tdd.total; - } - avg = avg / count; - sb.append(String.format(Locale.getDefault(), getString(R.string.combo_tdd_minimum), min)); - sb.append("\n"); - sb.append(String.format(Locale.getDefault(), getString(R.string.combo_tdd_average), avg)); - sb.append("\n"); - sb.append(String.format(Locale.getDefault(), getString(R.string.combo_tdd_maximum), max)); - sb.append("\n"); - for (Tdd tdd : tdds) { - sb.append("\n"); - sb.append(dateFormatter.format(tdd.timestamp)); - sb.append(" "); - sb.append(String.format(Locale.getDefault(), "%3.1f", tdd.total)); - sb.append(" U"); - } - text.setText(sb.toString()); - } - return layout; - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPlugin.java index ee0f33b281..cbcf21cd48 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPlugin.java @@ -18,7 +18,7 @@ import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.db.ExtendedBolus; import info.nightscout.androidaps.db.TemporaryBasal; -import info.nightscout.androidaps.db.Treatment; +import info.nightscout.androidaps.plugins.Treatments.Treatment; import info.nightscout.androidaps.events.EventAppExit; import info.nightscout.androidaps.events.EventPreferenceChange; import info.nightscout.androidaps.interfaces.Constraint; @@ -72,6 +72,9 @@ public class DanaRPlugin extends AbstractDanaRPlugin { pumpDescription.isRefillingCapable = true; pumpDescription.storesCarbInfo = true; + + pumpDescription.supportsTDDs = true; + pumpDescription.needsManualTDDLoad = true; } @Override diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusProgress.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusProgress.java index b200ccc5c1..79358526fa 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusProgress.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusProgress.java @@ -1,16 +1,12 @@ package info.nightscout.androidaps.plugins.PumpDanaR.comm; -import com.squareup.otto.Bus; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.Date; - import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.db.Treatment; +import info.nightscout.androidaps.plugins.Treatments.Treatment; import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress; public class MsgBolusProgress extends MessageBase { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusStop.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusStop.java index 7040b84183..6718d76194 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusStop.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusStop.java @@ -1,13 +1,11 @@ package info.nightscout.androidaps.plugins.PumpDanaR.comm; -import com.squareup.otto.Bus; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.db.Treatment; +import info.nightscout.androidaps.plugins.Treatments.Treatment; import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress; public class MsgBolusStop extends MessageBase { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/AbstractDanaRExecutionService.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/AbstractDanaRExecutionService.java index 4727e2650f..5524cf5c5c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/AbstractDanaRExecutionService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/AbstractDanaRExecutionService.java @@ -21,10 +21,9 @@ import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.PumpEnactResult; -import info.nightscout.androidaps.db.Treatment; +import info.nightscout.androidaps.plugins.Treatments.Treatment; import info.nightscout.androidaps.events.EventPumpStatusChanged; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; -import info.nightscout.androidaps.plugins.PumpDanaR.SerialIOThread; import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusStop; import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryAlarm; 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 4bf080f3fb..eabf4fc94a 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 @@ -18,7 +18,7 @@ import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.PumpEnactResult; -import info.nightscout.androidaps.db.Treatment; +import info.nightscout.androidaps.plugins.Treatments.Treatment; import info.nightscout.androidaps.events.EventAppExit; import info.nightscout.androidaps.events.EventInitializationChanged; import info.nightscout.androidaps.events.EventPreferenceChange; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/DanaRKoreanPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/DanaRKoreanPlugin.java index 212eb95dcd..a3a39a30f1 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/DanaRKoreanPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/DanaRKoreanPlugin.java @@ -18,7 +18,7 @@ import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.db.ExtendedBolus; import info.nightscout.androidaps.db.TemporaryBasal; -import info.nightscout.androidaps.db.Treatment; +import info.nightscout.androidaps.plugins.Treatments.Treatment; import info.nightscout.androidaps.events.EventAppExit; import info.nightscout.androidaps.events.EventPreferenceChange; import info.nightscout.androidaps.interfaces.Constraint; @@ -73,6 +73,9 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin { pumpDescription.isRefillingCapable = true; pumpDescription.storesCarbInfo = true; + + pumpDescription.supportsTDDs = true; + pumpDescription.needsManualTDDLoad = true; } @Override diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/services/DanaRKoreanExecutionService.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/services/DanaRKoreanExecutionService.java index 12d7590a59..c136666d5e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/services/DanaRKoreanExecutionService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/services/DanaRKoreanExecutionService.java @@ -18,7 +18,7 @@ import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.PumpEnactResult; -import info.nightscout.androidaps.db.Treatment; +import info.nightscout.androidaps.plugins.Treatments.Treatment; import info.nightscout.androidaps.events.EventAppExit; import info.nightscout.androidaps.events.EventInitializationChanged; import info.nightscout.androidaps.events.EventPreferenceChange; 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 17bc4671ce..7655c0ff46 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 @@ -26,7 +26,7 @@ import info.nightscout.androidaps.data.ProfileStore; import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.db.ExtendedBolus; import info.nightscout.androidaps.db.TemporaryBasal; -import info.nightscout.androidaps.db.Treatment; +import info.nightscout.androidaps.plugins.Treatments.Treatment; import info.nightscout.androidaps.events.EventAppExit; import info.nightscout.androidaps.interfaces.Constraint; import info.nightscout.androidaps.interfaces.ConstraintsInterface; @@ -111,6 +111,9 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte pumpDescription.isRefillingCapable = true; pumpDescription.storesCarbInfo = true; + + pumpDescription.supportsTDDs = true; + pumpDescription.needsManualTDDLoad = true; } @Override @@ -363,9 +366,9 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte speed = 60; break; } - // v2 stores end time for bolus, we need to adjust time + // RS stores end time for bolus, we need to adjust time // default delivery speed is 12 sec/U - detailedBolusInfo.date += detailedBolusInfo.insulin * speed * 1000; + detailedBolusInfo.date = DateUtil.now() + (long)(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; @@ -379,7 +382,7 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte t.isSMB = detailedBolusInfo.isSMB; boolean connectionOK = false; if (detailedBolusInfo.insulin > 0 || carbs > 0) - connectionOK = danaRSService.bolus(detailedBolusInfo.insulin, (int) carbs, System.currentTimeMillis() + carbTime * 60 * 1000, t); + connectionOK = danaRSService.bolus(detailedBolusInfo.insulin, (int) carbs, DateUtil.now() + carbTime * 60 * 1000, t); PumpEnactResult result = new PumpEnactResult(); result.success = connectionOK; result.bolusDelivered = t.insulin; 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 5383fca413..83e84e28cc 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 @@ -9,7 +9,7 @@ import info.nightscout.androidaps.R; import com.cozmo.danar.util.BleCommandUtil; -import info.nightscout.androidaps.db.Treatment; +import info.nightscout.androidaps.plugins.Treatments.Treatment; import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress; public class DanaRS_Packet_Bolus_Set_Step_Bolus_Stop extends DanaRS_Packet { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Notify_Delivery_Complete.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Notify_Delivery_Complete.java index 0139b12197..fb5793995c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Notify_Delivery_Complete.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Notify_Delivery_Complete.java @@ -9,7 +9,7 @@ import info.nightscout.androidaps.R; import com.cozmo.danar.util.BleCommandUtil; -import info.nightscout.androidaps.db.Treatment; +import info.nightscout.androidaps.plugins.Treatments.Treatment; import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress; public class DanaRS_Packet_Notify_Delivery_Complete extends DanaRS_Packet { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Notify_Delivery_Rate_Display.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Notify_Delivery_Rate_Display.java index 26c12c27af..5354836375 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Notify_Delivery_Rate_Display.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Notify_Delivery_Rate_Display.java @@ -7,7 +7,7 @@ import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import com.cozmo.danar.util.BleCommandUtil; -import info.nightscout.androidaps.db.Treatment; +import info.nightscout.androidaps.plugins.Treatments.Treatment; import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress; public class DanaRS_Packet_Notify_Delivery_Rate_Display extends DanaRS_Packet { 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 489864ebd1..384c1a3772 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 @@ -19,7 +19,7 @@ import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.PumpEnactResult; -import info.nightscout.androidaps.db.Treatment; +import info.nightscout.androidaps.plugins.Treatments.Treatment; import info.nightscout.androidaps.events.EventAppExit; import info.nightscout.androidaps.events.EventInitializationChanged; import info.nightscout.androidaps.events.EventPumpStatusChanged; @@ -71,8 +71,10 @@ import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Notify_D import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Option_Get_Pump_Time; import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Option_Set_Pump_Time; import info.nightscout.androidaps.queue.Callback; +import info.nightscout.utils.DateUtil; import info.nightscout.utils.NSUpload; import info.nightscout.utils.SP; +import info.nightscout.utils.T; public class DanaRSService extends Service { private static Logger log = LoggerFactory.getLogger(DanaRSService.class); @@ -145,8 +147,10 @@ public class DanaRSService extends Service { bleComm.sendMessage(new DanaRS_Packet_Option_Get_Pump_Time()); long timeDiff = (danaRPump.pumpTime.getTime() - System.currentTimeMillis()) / 1000L; log.debug("Pump time difference: " + timeDiff + " seconds"); - if (Math.abs(timeDiff) > 10) { - bleComm.sendMessage(new DanaRS_Packet_Option_Set_Pump_Time(new Date())); + if (Math.abs(timeDiff) > 3) { + waitForWholeMinute(); // Dana can set only whole minute + // add 10sec to be sure we are over minute (will be cutted off anyway) + bleComm.sendMessage(new DanaRS_Packet_Option_Set_Pump_Time(new Date(DateUtil.now() + T.secs(10).msecs()))); bleComm.sendMessage(new DanaRS_Packet_Option_Get_Pump_Time()); timeDiff = (danaRPump.pumpTime.getTime() - System.currentTimeMillis()) / 1000L; log.debug("Pump time difference: " + timeDiff + " seconds"); @@ -458,4 +462,14 @@ public class DanaRSService extends Service { log.debug("EventAppExit finished"); } + void waitForWholeMinute() { + while (true) { + long time = DateUtil.now(); + long timeToWholeMinute = (60000 - time % 60000); + if (timeToWholeMinute > 59800 || timeToWholeMinute < 300) + break; + MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.waitingfortimesynchronization, (int)(timeToWholeMinute / 1000)))); + SystemClock.sleep(Math.min(timeToWholeMinute, 100)); + } + } } 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 5d7eae2091..81c5d4d944 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 @@ -17,14 +17,15 @@ import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.db.TemporaryBasal; -import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.events.EventAppExit; import info.nightscout.androidaps.interfaces.Constraint; import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.plugins.ConfigBuilder.DetailedBolusInfoStorage; import info.nightscout.androidaps.plugins.PumpDanaR.AbstractDanaRPlugin; import info.nightscout.androidaps.plugins.PumpDanaRv2.services.DanaRv2ExecutionService; +import info.nightscout.androidaps.plugins.Treatments.Treatment; import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; +import info.nightscout.utils.DateUtil; import info.nightscout.utils.Round; import info.nightscout.utils.SP; @@ -72,6 +73,9 @@ public class DanaRv2Plugin extends AbstractDanaRPlugin { pumpDescription.isRefillingCapable = true; pumpDescription.storesCarbInfo = true; + + pumpDescription.supportsTDDs = true; + pumpDescription.needsManualTDDLoad = true; } @Override @@ -153,7 +157,7 @@ public class DanaRv2Plugin extends AbstractDanaRPlugin { speed = 60; break; } - detailedBolusInfo.date += speed * detailedBolusInfo.insulin * 1000; + detailedBolusInfo.date = DateUtil.now() + (long)(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; @@ -167,7 +171,7 @@ public class DanaRv2Plugin extends AbstractDanaRPlugin { t.isSMB = detailedBolusInfo.isSMB; boolean connectionOK = false; if (detailedBolusInfo.insulin > 0 || carbs > 0) - connectionOK = sExecutionService.bolus(detailedBolusInfo.insulin, (int) carbs, System.currentTimeMillis() + carbTime * 60 * 1000, t); + connectionOK = sExecutionService.bolus(detailedBolusInfo.insulin, (int) carbs, DateUtil.now() + carbTime * 60 * 1000, t); PumpEnactResult result = new PumpEnactResult(); result.success = connectionOK; result.bolusDelivered = t.insulin; @@ -380,4 +384,5 @@ public class DanaRv2Plugin extends AbstractDanaRPlugin { public PumpEnactResult loadEvents() { return sExecutionService.loadEvents(); } + } 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 1eb73a500a..551c2684c0 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 @@ -18,7 +18,7 @@ import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.PumpEnactResult; -import info.nightscout.androidaps.db.Treatment; +import info.nightscout.androidaps.plugins.Treatments.Treatment; import info.nightscout.androidaps.events.EventAppExit; import info.nightscout.androidaps.events.EventInitializationChanged; import info.nightscout.androidaps.events.EventPreferenceChange; @@ -64,8 +64,10 @@ import info.nightscout.androidaps.plugins.PumpDanaRv2.comm.MsgSetHistoryEntry_v2 import info.nightscout.androidaps.plugins.PumpDanaRv2.comm.MsgStatusBolusExtended_v2; import info.nightscout.androidaps.plugins.PumpDanaRv2.comm.MsgStatusTempBasal_v2; import info.nightscout.androidaps.queue.Callback; +import info.nightscout.utils.DateUtil; import info.nightscout.utils.NSUpload; import info.nightscout.utils.SP; +import info.nightscout.utils.T; import info.nightscout.utils.ToastUtils; public class DanaRv2ExecutionService extends AbstractDanaRExecutionService { @@ -198,8 +200,10 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService { mSerialIOThread.sendMessage(new MsgSettingPumpTime()); long timeDiff = (mDanaRPump.pumpTime.getTime() - System.currentTimeMillis()) / 1000L; log.debug("Pump time difference: " + timeDiff + " seconds"); - if (Math.abs(timeDiff) > 10) { - mSerialIOThread.sendMessage(new MsgSetTime(new Date())); + if (Math.abs(timeDiff) > 3) { + waitForWholeMinute(); // Dana can set only whole minute + // add 10sec to be sure we are over minute (will be cutted off anyway) + mSerialIOThread.sendMessage(new MsgSetTime(new Date(DateUtil.now() + T.secs(10).msecs()))); mSerialIOThread.sendMessage(new MsgSettingPumpTime()); timeDiff = (mDanaRPump.pumpTime.getTime() - System.currentTimeMillis()) / 1000L; log.debug("Pump time difference: " + timeDiff + " seconds"); @@ -450,4 +454,14 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService { return true; } + void waitForWholeMinute() { + while (true) { + long time = DateUtil.now(); + long timeToWholeMinute = (60000 - time % 60000); + if (timeToWholeMinute > 59800 || timeToWholeMinute < 3000) + break; + MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.waitingfortimesynchronization, (int)(timeToWholeMinute / 1000)))); + SystemClock.sleep(Math.min(timeToWholeMinute, 100)); + } + } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/InsightPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/InsightPlugin.java index 4ad70cfc31..c0e53ddaac 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/InsightPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/InsightPlugin.java @@ -21,7 +21,7 @@ import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.db.ExtendedBolus; import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.TemporaryBasal; -import info.nightscout.androidaps.db.Treatment; +import info.nightscout.androidaps.plugins.Treatments.Treatment; import info.nightscout.androidaps.interfaces.Constraint; import info.nightscout.androidaps.interfaces.ConstraintsInterface; import info.nightscout.androidaps.interfaces.PluginBase; @@ -142,6 +142,9 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai pumpDescription.isRefillingCapable = true; pumpDescription.storesCarbInfo = false; + + pumpDescription.supportsTDDs = true; + pumpDescription.needsManualTDDLoad = false; } @@ -193,8 +196,8 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai @Override public PumpEnactResult loadTDDs() { - //TODO: read TDDs and store to DB PumpEnactResult result = new PumpEnactResult(); + result.success = true; return result; } @@ -242,7 +245,6 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai // TODO review if (!Config.NSCLIENT && !Config.G5UPLOADER) NSUpload.uploadDeviceStatus(); - lastDataTime = new Date(); } @Override @@ -283,7 +285,6 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai public void getPumpStatus() { log("getPumpStatus"); - lastDataTime = new Date(); if (Connector.get().isPumpConnected()) { log("is connected.. requesting status"); final UUID uuid = aSyncTaskRunner(new StatusTaskRunner(connector.getServiceConnector()), "Status"); @@ -439,7 +440,6 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai updateGui(); connector.tryToGetPumpStatusAgain(); - lastDataTime = new Date(); connector.requestHistorySync(30000); if (result.success) while (true) { @@ -538,8 +538,6 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai if (Config.logPumpComm) log.debug("Setting temp basal absolute: " + pumpEnactResult.success); - lastDataTime = new Date(); - updateGui(); connector.requestHistorySync(5000); @@ -621,7 +619,6 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai TemporaryBasal tempStop = new TemporaryBasal().date(System.currentTimeMillis()).source(Source.USER); TreatmentsPlugin.getPlugin().addToHistoryTempBasal(tempStop); } - lastDataTime = new Date(); updateGui(); if (Config.logPumpComm) log.debug("Canceling temp basal: "); // TODO get more info @@ -950,6 +947,7 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai singleMessageTaskRunner.fetch(new TaskRunner.ResultCallback() { @Override public void onResult(Object o) { + lastDataTime = new Date(); log(name + " success"); event.response_object = o; if (o instanceof BolusMessage) { @@ -988,6 +986,7 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai task.fetch(new TaskRunner.ResultCallback() { @Override public void onResult(Object o) { + lastDataTime = new Date(); log(name + " success"); event.response_object = o; event.success = true; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/history/HistoryIntentAdapter.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/history/HistoryIntentAdapter.java index 4295fadccb..1ddc4fd4b7 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/history/HistoryIntentAdapter.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/history/HistoryIntentAdapter.java @@ -1,18 +1,25 @@ package info.nightscout.androidaps.plugins.PumpInsight.history; import android.content.Intent; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.db.CareportalEvent; +import info.nightscout.androidaps.db.TDD; +import info.nightscout.utils.DateUtil; +import info.nightscout.utils.NSUpload; +import info.nightscout.utils.SP; +import org.json.JSONException; +import org.json.JSONObject; +import sugar.free.sightparser.handling.HistoryBroadcast; import java.util.Date; -import sugar.free.sightparser.handling.HistoryBroadcast; - import static info.nightscout.androidaps.plugins.PumpInsight.history.PumpIdCache.updatePumpSerialNumber; /** * Created by jamorham on 27/01/2018. - * + *

* Parse inbound logbook intents - * */ class HistoryIntentAdapter { @@ -109,4 +116,88 @@ class HistoryIntentAdapter { log("ERROR, UNKNWON BOLUS TYPE: " + bolus_type); } } + + void processDailyTotalIntent(Intent intent) { + Date date = getDateExtra(intent, HistoryBroadcast.EXTRA_TOTAL_DATE); + double basal = intent.getDoubleExtra(HistoryBroadcast.EXTRA_BASAL_TOTAL, 0D); + double bolus = intent.getDoubleExtra(HistoryBroadcast.EXTRA_BOLUS_TOTAL, 0D); + TDD tdd = new TDD(date.getTime(), bolus, basal, bolus + basal); + MainApp.getDbHelper().createOrUpdateTDD(tdd); + } + + void processCannulaFilledIntent(Intent intent) { + Date date = getDateExtra(intent, HistoryBroadcast.EXTRA_EVENT_TIME); + uploadCareportalEvent(date, CareportalEvent.SITECHANGE); + } + + void processCartridgeInsertedIntent(Intent intent) { + Date date = getDateExtra(intent, HistoryBroadcast.EXTRA_EVENT_TIME); + uploadCareportalEvent(date, CareportalEvent.INSULINCHANGE); + } + + void processBatteryInsertedIntent(Intent intent) { + Date date = getDateExtra(intent, HistoryBroadcast.EXTRA_EVENT_TIME); + uploadCareportalEvent(date, CareportalEvent.PUMPBATTERYCHANGE); + } + + private void uploadCareportalEvent(Date date, String event) { + if (SP.getBoolean("insight_automatic_careportal_events", false)) { + if (MainApp.getDbHelper().getCareportalEventFromTimestamp(date.getTime()) != null) return; + try { + JSONObject data = new JSONObject(); + String enteredBy = SP.getString("careportal_enteredby", ""); + if (!enteredBy.equals("")) data.put("enteredBy", enteredBy); + data.put("created_at", DateUtil.toISOString(date)); + data.put("eventType", event); + NSUpload.uploadCareportalEntryToNS(data); + } catch (JSONException e) { + e.printStackTrace(); + } + } + } + + void processOccurenceOfAlertIntent(Intent intent) { + if (SP.getBoolean("insight_automatic_careportal_events", false)) { + Date date = getDateExtra(intent, HistoryBroadcast.EXTRA_EVENT_TIME); + String alertType = intent.getStringExtra(HistoryBroadcast.EXTRA_ALERT_TYPE); + if (MainApp.getDbHelper().getCareportalEventFromTimestamp(date.getTime()) != null) return; + try { + JSONObject data = new JSONObject(); + String enteredBy = SP.getString("careportal_enteredby", ""); + if (!enteredBy.equals("")) data.put("enteredBy", enteredBy); + data.put("created_at", DateUtil.toISOString(date)); + data.put("eventType", CareportalEvent.NOTE); + data.put("notes", MainApp.instance().getString(getAlertText(alertType))); + NSUpload.uploadCareportalEntryToNS(data); + } catch (JSONException e) { + e.printStackTrace(); + } + } + } + + private int getAlertText(String type) { + if (type.equals("Error6MechanicalError")) return R.string.alert_e6; + if (type.equals("Error7ElectronicError")) return R.string.alert_e7; + if (type.equals("Error10RewindError")) return R.string.alert_e10; + if (type.equals("Error13LanguageError")) return R.string.alert_e13; + if (type.equals("Maintenance20CartridgeNotInserted")) return R.string.alert_m20; + if (type.equals("Maintenance21CartridgeEmpty")) return R.string.alert_m21; + if (type.equals("Maintenance22BatteryEmpty")) return R.string.alert_m22; + if (type.equals("Maintenance23AutomaticOff")) return R.string.alert_m23; + if (type.equals("Maintenance24Occlusion")) return R.string.alert_m24; + if (type.equals("Maintenance25LoantimeOver")) return R.string.alert_m25; + if (type.equals("Maintenance26CartridgeChangeNotCompleted")) return R.string.alert_m26; + if (type.equals("Maintenance27DataDownloadFailed")) return R.string.alert_m27; + if (type.equals("Maintenance28PauseModeTimeout")) return R.string.alert_m28; + if (type.equals("Maintenance29BatteryTypeNotSet")) return R.string.alert_m29; + if (type.equals("Maintenance30CartridgeTypeNotSet")) return R.string.alert_m30; + if (type.equals("Warning31CartridgeLow")) return R.string.alert_w31; + if (type.equals("Warning32BatteryLow")) return R.string.alert_w32; + if (type.equals("Warning33InvalidDateTime")) return R.string.alert_w33; + if (type.equals("Warning34EndOfWarranty")) return R.string.alert_w34; + if (type.equals("Warning36TBRCancelled")) return R.string.alert_w36; + if (type.equals("Warning38BolusCancelled")) return R.string.alert_w38; + if (type.equals("Warning39LoantimeWarning")) return R.string.alert_w39; + return 0; + } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/history/HistoryReceiver.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/history/HistoryReceiver.java index cad58963b4..0e254e3341 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/history/HistoryReceiver.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/history/HistoryReceiver.java @@ -11,13 +11,7 @@ import info.nightscout.androidaps.R; import static info.nightscout.androidaps.plugins.PumpInsight.history.HistoryReceiver.Status.BUSY; import static info.nightscout.androidaps.plugins.PumpInsight.history.HistoryReceiver.Status.SYNCED; import static info.nightscout.androidaps.plugins.PumpInsight.history.HistoryReceiver.Status.SYNCING; -import static sugar.free.sightparser.handling.HistoryBroadcast.ACTION_BOLUS_DELIVERED; -import static sugar.free.sightparser.handling.HistoryBroadcast.ACTION_BOLUS_PROGRAMMED; -import static sugar.free.sightparser.handling.HistoryBroadcast.ACTION_END_OF_TBR; -import static sugar.free.sightparser.handling.HistoryBroadcast.ACTION_PUMP_STATUS_CHANGED; -import static sugar.free.sightparser.handling.HistoryBroadcast.ACTION_STILL_SYNCING; -import static sugar.free.sightparser.handling.HistoryBroadcast.ACTION_SYNC_FINISHED; -import static sugar.free.sightparser.handling.HistoryBroadcast.ACTION_SYNC_STARTED; +import static sugar.free.sightparser.handling.HistoryBroadcast.*; /** * Created by jamorham on 27/01/2018. @@ -45,9 +39,14 @@ public class HistoryReceiver { filter.addAction(ACTION_BOLUS_PROGRAMMED); filter.addAction(ACTION_BOLUS_DELIVERED); filter.addAction(ACTION_END_OF_TBR); + filter.addAction(ACTION_DAILY_TOTAL); filter.addAction(ACTION_SYNC_STARTED); filter.addAction(ACTION_STILL_SYNCING); filter.addAction(ACTION_SYNC_FINISHED); + filter.addAction(ACTION_CANNULA_FILLED); + filter.addAction(ACTION_CARTRIDGE_INSERTED); + filter.addAction(ACTION_BATTERY_INSERTED); + filter.addAction(ACTION_OCCURENCE_OF_ALERT); MainApp.instance().registerReceiver(historyReceiver, filter); } @@ -79,7 +78,6 @@ public class HistoryReceiver { } switch (action) { - case ACTION_SYNC_STARTED: status = SYNCING; break; @@ -95,6 +93,21 @@ public class HistoryReceiver { case ACTION_END_OF_TBR: intentAdapter.processTBRIntent(intent); break; + case ACTION_DAILY_TOTAL: + intentAdapter.processDailyTotalIntent(intent); + break; + case ACTION_CANNULA_FILLED: + intentAdapter.processCannulaFilledIntent(intent); + break; + case ACTION_CARTRIDGE_INSERTED: + intentAdapter.processCartridgeInsertedIntent(intent); + break; + case ACTION_BATTERY_INSERTED: + intentAdapter.processBatteryInsertedIntent(intent); + break; + case ACTION_OCCURENCE_OF_ALERT: + intentAdapter.processOccurenceOfAlertIntent(intent); + break; } } }; 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 6b072a3a17..0725823ac9 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 @@ -30,7 +30,7 @@ import info.nightscout.utils.SafeParse; * Created by mike on 24.06.2017. */ -public class SensitivityAAPSPlugin extends PluginBase implements SensitivityInterface{ +public class SensitivityAAPSPlugin extends PluginBase implements SensitivityInterface { private static Logger log = LoggerFactory.getLogger(SensitivityAAPSPlugin.class); static SensitivityAAPSPlugin plugin = null; @@ -118,7 +118,9 @@ public class SensitivityAAPSPlugin extends PluginBase implements SensitivityInte String ratioLimit = ""; String sensResult = ""; - log.debug("Records: " + index + " " + pastSensitivity); + if (Config.logAutosensData) + log.debug("Records: " + index + " " + pastSensitivity); + Arrays.sort(deviations); double percentile = IobCobCalculatorPlugin.percentile(deviations, 0.50); @@ -133,7 +135,8 @@ public class SensitivityAAPSPlugin extends PluginBase implements SensitivityInte 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"))); 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 46e00427bf..3e9cc2cf9e 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 @@ -118,12 +118,15 @@ public class SensitivityOref0Plugin extends PluginBase implements SensitivityInt String ratioLimit = ""; String sensResult = ""; - log.debug("Records: " + index + " " + pastSensitivity); + if (Config.logAutosensData) + log.debug("Records: " + index + " " + pastSensitivity); + Arrays.sort(deviations); for (double i = 0.9; i > 0.1; i = i - 0.02) { if (IobCobCalculatorPlugin.percentile(deviations, (i + 0.02)) >= 0 && IobCobCalculatorPlugin.percentile(deviations, i) < 0) { - log.debug(Math.round(100 * i) + "% of non-meal deviations negative (target 45%-50%)"); + if (Config.logAutosensData) + log.debug(Math.round(100 * i) + "% of non-meal deviations negative (target 45%-50%)"); } } double pSensitive = IobCobCalculatorPlugin.percentile(deviations, 0.50); @@ -140,7 +143,10 @@ public class SensitivityOref0Plugin extends PluginBase implements SensitivityInt } else { sensResult = "Sensitivity normal"; } - log.debug(sensResult); + + if (Config.logAutosensData) + log.debug(sensResult); + ratio = 1 + (basalOff / profile.getMaxDailyBasal()); double rawRatio = ratio; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/SmsCommunicatorPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/SmsCommunicatorPlugin.java index b6c8ebca33..8308a2eb92 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/SmsCommunicatorPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/SmsCommunicatorPlugin.java @@ -315,7 +315,7 @@ public class SmsCommunicatorPlugin extends PluginBase { switch (splited[1].toUpperCase()) { case "REFRESH": Intent restartNSClient = new Intent(Intents.ACTION_RESTART); - MainApp.getDbHelper().resetTreatments(); + TreatmentsPlugin.getPlugin().getService().resetTreatments(); MainApp.instance().getApplicationContext().sendBroadcast(restartNSClient); List q = MainApp.instance().getApplicationContext().getPackageManager().queryBroadcastReceivers(restartNSClient, 0); reply = "TERATMENTS REFRESH " + q.size() + " receivers"; diff --git a/app/src/main/java/info/nightscout/androidaps/db/Treatment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/Treatment.java similarity index 75% rename from app/src/main/java/info/nightscout/androidaps/db/Treatment.java rename to app/src/main/java/info/nightscout/androidaps/plugins/Treatments/Treatment.java index 31df191387..31d44a3e30 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/Treatment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/Treatment.java @@ -1,10 +1,12 @@ -package info.nightscout.androidaps.db; +package info.nightscout.androidaps.plugins.Treatments; import android.graphics.Color; import com.j256.ormlite.field.DatabaseField; import com.j256.ormlite.table.DatabaseTable; +import org.json.JSONException; +import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -14,6 +16,8 @@ import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.data.Iob; +import info.nightscout.androidaps.db.DatabaseHelper; +import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.interfaces.InsulinInterface; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.Overview.OverviewPlugin; @@ -21,11 +25,14 @@ import info.nightscout.androidaps.plugins.Overview.graphExtensions.DataPointWith import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLabelGraphSeries; import info.nightscout.utils.DateUtil; import info.nightscout.utils.DecimalFormatter; +import info.nightscout.utils.JsonHelper; -@DatabaseTable(tableName = DatabaseHelper.DATABASE_TREATMENTS) +@DatabaseTable(tableName = Treatment.TABLE_TREATMENTS) public class Treatment implements DataPointWithLabelInterface { private static Logger log = LoggerFactory.getLogger(Treatment.class); + public static final String TABLE_TREATMENTS = "Treatments"; + @DatabaseField(id = true) public long date; @@ -57,6 +64,32 @@ public class Treatment implements DataPointWithLabelInterface { public Treatment() { } + public static Treatment createFromJson(JSONObject json) throws JSONException { + Treatment treatment = new Treatment(); + treatment.source = Source.NIGHTSCOUT; + treatment.date = DateUtil.roundDateToSec(JsonHelper.safeGetLong(json, "mills")); + if (treatment.date == 0L) + return null; + treatment.carbs = JsonHelper.safeGetDouble(json,"carbs"); + treatment.insulin = JsonHelper.safeGetDouble(json,"insulin"); + treatment.pumpId = JsonHelper.safeGetLong(json, "pumpId"); + treatment._id = json.getString("_id"); + treatment.isSMB = JsonHelper.safeGetBoolean(json,"isSMB"); + if (json.has("eventType")) { + treatment.mealBolus = !json.get("eventType").equals("Correction Bolus"); + double carbs = treatment.carbs; + if (json.has("boluscalc")) { + JSONObject boluscalc = json.getJSONObject("boluscalc"); + if (boluscalc.has("carbs")) { + carbs = Math.max(boluscalc.getDouble("carbs"), carbs); + } + } + if (carbs <= 0) + treatment.mealBolus = false; + } + return treatment; + } + public String toString() { return "Treatment{" + "date= " + date + @@ -72,9 +105,8 @@ public class Treatment implements DataPointWithLabelInterface { } public boolean isDataChanging(Treatment other) { - if (date != other.date) { + if (date != other.date) return true; - } if (insulin != other.insulin) return true; if (carbs != other.carbs) @@ -83,9 +115,8 @@ public class Treatment implements DataPointWithLabelInterface { } public boolean isEqual(Treatment other) { - if (date != other.date) { + if (date != other.date) return false; - } if (insulin != other.insulin) return false; if (carbs != other.carbs) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentService.java b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentService.java new file mode 100644 index 0000000000..2a5b798018 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentService.java @@ -0,0 +1,426 @@ +package info.nightscout.androidaps.plugins.Treatments; + +import android.content.Intent; +import android.os.IBinder; +import android.support.annotation.Nullable; + +import com.j256.ormlite.android.apptools.OpenHelperManager; +import com.j256.ormlite.android.apptools.OrmLiteBaseService; +import com.j256.ormlite.dao.Dao; +import com.j256.ormlite.dao.DaoManager; +import com.j256.ormlite.stmt.PreparedQuery; +import com.j256.ormlite.stmt.QueryBuilder; +import com.j256.ormlite.stmt.Where; +import com.j256.ormlite.support.ConnectionSource; +import com.j256.ormlite.table.TableUtils; +import com.squareup.otto.Subscribe; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.db.DatabaseHelper; +import info.nightscout.androidaps.db.ICallback; +import info.nightscout.androidaps.db.Source; +import info.nightscout.androidaps.events.Event; +import info.nightscout.androidaps.events.EventNsTreatment; +import info.nightscout.androidaps.events.EventReloadTreatmentData; +import info.nightscout.androidaps.events.EventTreatmentChange; +import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventNewHistoryData; +import info.nightscout.utils.JsonHelper; + + +/** + * Created by mike on 24.09.2017. + */ + +public class TreatmentService extends OrmLiteBaseService { + private static Logger log = LoggerFactory.getLogger(TreatmentService.class); + + private static final ScheduledExecutorService treatmentEventWorker = Executors.newSingleThreadScheduledExecutor(); + private static ScheduledFuture scheduledTreatmentEventPost = null; + + public TreatmentService() { + onCreate(); + dbInitialize(); + MainApp.bus().register(this); + } + + /** + * This method is a simple re-implementation of the database create and up/downgrade functionality + * in SQLiteOpenHelper#getDatabaseLocked method. + *

+ * It is implemented to be able to late initialize separate plugins of the application. + */ + protected void dbInitialize() { + DatabaseHelper helper = OpenHelperManager.getHelper(this, DatabaseHelper.class); + int newVersion = helper.getNewVersion(); + int oldVersion = helper.getOldVersion(); + + if (oldVersion > newVersion) { + onDowngrade(this.getConnectionSource(), oldVersion, newVersion); + } else { + onUpgrade(this.getConnectionSource(), oldVersion, newVersion); + } + } + + public Dao getDao() { + try { + return DaoManager.createDao(this.getConnectionSource(), Treatment.class); + } catch (SQLException e) { + log.error("Cannot create Dao for Treatment.class"); + } + + return null; + } + + @Subscribe + @SuppressWarnings("unused") + public void handleNsEvent(EventNsTreatment event) { + int mode = event.getMode(); + JSONObject payload = event.getPayload(); + + if (mode == EventNsTreatment.ADD || mode == EventNsTreatment.UPDATE) { + this.createTreatmentFromJsonIfNotExists(payload); + } else { // EventNsTreatment.REMOVE + this.deleteNS(payload); + } + } + + @Override + public void onCreate() { + super.onCreate(); + try { + log.info("onCreate"); + TableUtils.createTableIfNotExists(this.getConnectionSource(), Treatment.class); + } catch (SQLException e) { + log.error("Can't create database", e); + throw new RuntimeException(e); + } + } + + public void onUpgrade(ConnectionSource connectionSource, int oldVersion, int newVersion) { + if (oldVersion == 7 && newVersion == 8) { + log.debug("Upgrading database from v7 to v8"); + try { + TableUtils.dropTable(connectionSource, Treatment.class, true); + TableUtils.createTableIfNotExists(connectionSource, Treatment.class); + } catch (SQLException e) { + log.error("Can't create database", e); + throw new RuntimeException(e); + } + } else { + log.info("onUpgrade"); +// this.resetFood(); + } + } + + public void onDowngrade(ConnectionSource connectionSource, int oldVersion, int newVersion) { + // this method is not supported right now + } + + public void resetTreatments() { + try { + TableUtils.dropTable(this.getConnectionSource(), Treatment.class, true); + TableUtils.createTableIfNotExists(this.getConnectionSource(), Treatment.class); + DatabaseHelper.updateEarliestDataChange(0); + } catch (SQLException e) { + log.error("Unhandled exception", e); + } + scheduleTreatmentChange(null); + } + + + /** + * A place to centrally register events to be posted, if any data changed. + * This should be implemented in an abstract service-class. + *

+ * We do need to make sure, that ICallback is extended to be able to handle multiple + * events, or handle a list of events. + *

+ * on some methods the earliestDataChange event is handled separatly, in that it is checked if it is + * set to null by another event already (eg. scheduleExtendedBolusChange). + * + * @param event + * @param eventWorker + * @param callback + */ + private void scheduleEvent(final Event event, ScheduledExecutorService eventWorker, + final ICallback callback) { + + class PostRunnable implements Runnable { + public void run() { + log.debug("Firing EventFoodChange"); + MainApp.bus().post(event); + if (DatabaseHelper.earliestDataChange != null) + MainApp.bus().post(new EventNewHistoryData(DatabaseHelper.earliestDataChange)); + DatabaseHelper.earliestDataChange = null; + callback.setPost(null); + } + } + // prepare task for execution in 1 sec + // cancel waiting task to prevent sending multiple posts + if (callback.getPost() != null) + callback.getPost().cancel(false); + Runnable task = new PostRunnable(); + final int sec = 1; + callback.setPost(eventWorker.schedule(task, sec, TimeUnit.SECONDS)); + } + + /** + * Schedule a foodChange Event. + */ + public void scheduleTreatmentChange(@Nullable final Treatment treatment) { + this.scheduleEvent(new EventReloadTreatmentData(new EventTreatmentChange(treatment)), treatmentEventWorker, new ICallback() { + @Override + public void setPost(ScheduledFuture post) { + scheduledTreatmentEventPost = post; + } + + @Override + public ScheduledFuture getPost() { + return scheduledTreatmentEventPost; + } + }); + } + + public List getTreatmentData() { + try { + return this.getDao().queryForAll(); + } catch (SQLException e) { + log.error("Unhandled exception", e); + } + + return new ArrayList<>(); + } + + /* + { + "_id": "551ee3ad368e06e80856e6a9", + "type": "food", + "category": "Zakladni", + "subcategory": "Napoje", + "name": "Mleko", + "portion": 250, + "carbs": 12, + "gi": 1, + "created_at": "2015-04-14T06:59:16.500Z", + "unit": "ml" + } + */ + public void createTreatmentFromJsonIfNotExists(JSONObject json) { + try { + Treatment treatment = Treatment.createFromJson(json); + if (treatment != null) + createOrUpdate(treatment); + } catch (JSONException e) { + log.error("Unhandled exception", e); + } + } + + public void createFoodFromJsonIfNotExists(JSONArray array) { + try { + for (int n = 0; n < array.length(); n++) { + JSONObject json = array.getJSONObject(n); + createTreatmentFromJsonIfNotExists(json); + } + } catch (JSONException e) { + log.error("Unhandled exception", e); + } + } + + // return true if new record is created + public boolean createOrUpdate(Treatment treatment) { + try { + Treatment old; + treatment.date = DatabaseHelper.roundDateToSec(treatment.date); + + if (treatment.source == Source.PUMP) { + // check for changed from pump change in NS + QueryBuilder queryBuilder = getDao().queryBuilder(); + Where where = queryBuilder.where(); + where.eq("pumpId", treatment.pumpId); + PreparedQuery preparedQuery = queryBuilder.prepare(); + List trList = getDao().query(preparedQuery); + if (trList.size() > 0) { + // do nothing, pump history record cannot be changed + log.debug("TREATMENT: Pump record already found in database: " + treatment.toString()); + return false; + } + getDao().create(treatment); + log.debug("TREATMENT: New record from: " + Source.getString(treatment.source) + " " + treatment.toString()); + DatabaseHelper.updateEarliestDataChange(treatment.date); + scheduleTreatmentChange(treatment); + return true; + } + if (treatment.source == Source.NIGHTSCOUT) { + old = getDao().queryForId(treatment.date); + if (old != null) { + if (!old.isEqual(treatment)) { + boolean historyChange = old.isDataChanging(treatment); + long oldDate = old.date; + getDao().delete(old); // need to delete/create because date may change too + old.copyFrom(treatment); + getDao().create(old); + log.debug("TREATMENT: Updating record by date from: " + Source.getString(treatment.source) + " " + old.toString()); + if (historyChange) { + DatabaseHelper.updateEarliestDataChange(oldDate); + DatabaseHelper.updateEarliestDataChange(old.date); + } + scheduleTreatmentChange(treatment); + return true; + } + return false; + } + // find by NS _id + if (treatment._id != null) { + old = findByNSId(treatment._id); + if (old != null) { + if (!old.isEqual(treatment)) { + boolean historyChange = old.isDataChanging(treatment); + long oldDate = old.date; + getDao().delete(old); // need to delete/create because date may change too + old.copyFrom(treatment); + getDao().create(old); + log.debug("TREATMENT: Updating record by _id from: " + Source.getString(treatment.source) + " " + old.toString()); + if (historyChange) { + DatabaseHelper.updateEarliestDataChange(oldDate); + DatabaseHelper.updateEarliestDataChange(old.date); + } + scheduleTreatmentChange(treatment); + return true; + } + } + } + getDao().create(treatment); + log.debug("TREATMENT: New record from: " + Source.getString(treatment.source) + " " + treatment.toString()); + DatabaseHelper.updateEarliestDataChange(treatment.date); + scheduleTreatmentChange(treatment); + return true; + } + if (treatment.source == Source.USER) { + getDao().create(treatment); + log.debug("TREATMENT: New record from: " + Source.getString(treatment.source) + " " + treatment.toString()); + DatabaseHelper.updateEarliestDataChange(treatment.date); + scheduleTreatmentChange(treatment); + return true; + } + } catch (SQLException e) { + log.error("Unhandled exception", e); + } + return false; + } + + public void deleteNS(JSONObject json) { + String _id = JsonHelper.safeGetString(json, "_id"); + if (_id != null && !_id.isEmpty()) + this.deleteByNSId(_id); + } + + /** + * deletes an entry by its NS Id. + *

+ * Basically a convenience method for findByNSId and delete. + * + * @param _id + */ + private void deleteByNSId(String _id) { + Treatment stored = findByNSId(_id); + if (stored != null) { + log.debug("TREATMENT: Removing Treatment record from database: " + stored.toString()); + delete(stored); + DatabaseHelper.updateEarliestDataChange(stored.date); + scheduleTreatmentChange(null); + } + } + + /** + * deletes the treatment and sends the treatmentChange Event + *

+ * should be moved ot a Service + * + * @param treatment + */ + public void delete(Treatment treatment) { + try { + getDao().delete(treatment); + DatabaseHelper.updateEarliestDataChange(treatment.date); + this.scheduleTreatmentChange(treatment); + } catch (SQLException e) { + log.error("Unhandled exception", e); + } + } + + public void update(Treatment treatment) { + try { + getDao().update(treatment); + DatabaseHelper.updateEarliestDataChange(treatment.date); + } catch (SQLException e) { + log.error("Unhandled exception", e); + } + scheduleTreatmentChange(treatment); + } + + /** + * finds treatment by its NS Id. + * + * @param _id + * @return + */ + @Nullable + public Treatment findByNSId(String _id) { + try { + Dao daoTreatments = getDao(); + QueryBuilder queryBuilder = daoTreatments.queryBuilder(); + Where where = queryBuilder.where(); + where.eq("_id", _id); + queryBuilder.limit(10L); + PreparedQuery preparedQuery = queryBuilder.prepare(); + List trList = daoTreatments.query(preparedQuery); + if (trList.size() != 1) { + //log.debug("Treatment findTreatmentById query size: " + trList.size()); + return null; + } else { + //log.debug("Treatment findTreatmentById found: " + trList.get(0).log()); + return trList.get(0); + } + } catch (SQLException e) { + log.error("Unhandled exception", e); + } + return null; + } + + public List getTreatmentDataFromTime(long mills, boolean ascending) { + try { + Dao daoTreatments = getDao(); + List treatments; + QueryBuilder queryBuilder = daoTreatments.queryBuilder(); + queryBuilder.orderBy("date", ascending); + Where where = queryBuilder.where(); + where.ge("date", mills); + PreparedQuery preparedQuery = queryBuilder.prepare(); + treatments = daoTreatments.query(preparedQuery); + return treatments; + } catch (SQLException e) { + log.error("Unhandled exception", e); + } + return new ArrayList<>(); + } + + @Nullable + @Override + public IBinder onBind(Intent intent) { + return null; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsPlugin.java index 55195928fc..36fac67834 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsPlugin.java @@ -27,7 +27,6 @@ import info.nightscout.androidaps.db.ExtendedBolus; 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.EventReloadProfileSwitchData; import info.nightscout.androidaps.events.EventReloadTempBasalData; import info.nightscout.androidaps.events.EventReloadTreatmentData; @@ -41,8 +40,10 @@ import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData; import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin; import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.Overview.notifications.Notification; +import info.nightscout.utils.DateUtil; import info.nightscout.utils.NSUpload; import info.nightscout.utils.SP; +import info.nightscout.utils.T; /** * Created by mike on 05.08.2016. @@ -58,14 +59,16 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface return treatmentsPlugin; } + private TreatmentService service; + private IobTotal lastTreatmentCalculation; private IobTotal lastTempBasalsCalculation; - private final static ArrayList treatments = new ArrayList<>(); - private final static Intervals tempBasals = new NonOverlappingIntervals<>(); - private final static Intervals extendedBoluses = new NonOverlappingIntervals<>(); - private final static Intervals tempTargets = new OverlappingIntervals<>(); - private final static ProfileIntervals profiles = new ProfileIntervals<>(); + private final ArrayList treatments = new ArrayList<>(); + private final Intervals tempBasals = new NonOverlappingIntervals<>(); + private final Intervals extendedBoluses = new NonOverlappingIntervals<>(); + private final Intervals tempTargets = new OverlappingIntervals<>(); + private final ProfileIntervals profiles = new ProfileIntervals<>(); public TreatmentsPlugin() { super(new PluginDescription() @@ -76,6 +79,7 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface .preferencesId(R.xml.pref_absorption_oref0) .alwaysEnabled(true) ); + this.service = new TreatmentService(); } @Override @@ -94,18 +98,22 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface MainApp.bus().register(this); } - private static void initializeTreatmentData() { + public TreatmentService getService() { + return this.service; + } + + private void initializeTreatmentData() { double dia = Constants.defaultDIA; if (MainApp.getConfigBuilder() != null && MainApp.getConfigBuilder().getProfile() != null) dia = MainApp.getConfigBuilder().getProfile().getDia(); long fromMills = (long) (System.currentTimeMillis() - 60 * 60 * 1000L * (24 + dia)); synchronized (treatments) { treatments.clear(); - treatments.addAll(MainApp.getDbHelper().getTreatmentDataFromTime(fromMills, false)); + treatments.addAll(getService().getTreatmentDataFromTime(fromMills, false)); } } - private static void initializeTempBasalData() { + private void initializeTempBasalData() { double dia = Constants.defaultDIA; if (MainApp.getConfigBuilder() != null && MainApp.getConfigBuilder().getProfile() != null) dia = MainApp.getConfigBuilder().getProfile().getDia(); @@ -117,7 +125,7 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface } - private static void initializeExtendedBolusData() { + private void initializeExtendedBolusData() { double dia = Constants.defaultDIA; if (MainApp.getConfigBuilder() != null && MainApp.getConfigBuilder().getProfile() != null) dia = MainApp.getConfigBuilder().getProfile().getDia(); @@ -203,7 +211,7 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface if (profile == null) return result; long now = System.currentTimeMillis(); - long dia_ago = now - (Double.valueOf(1.5d * profile.getDia() * 60 * 60 * 1000l)).longValue(); + long dia_ago = now - (Double.valueOf(1.5d * profile.getDia() * T.hours(1).msecs())).longValue(); synchronized (treatments) { for (Treatment treatment : treatments) { @@ -235,7 +243,7 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface @Override public List getTreatmentsFromHistory() { synchronized (treatments) { - return (List) treatments.clone(); + return new ArrayList<>(treatments); } } @@ -300,6 +308,7 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface } @Subscribe + @SuppressWarnings("unused") public void onStatusEvent(final EventReloadTempBasalData ev) { log.debug("EventReloadTempBasalData"); initializeTempBasalData(); @@ -312,22 +321,15 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface } @Override - public IobTotal getCalculationToTimeTempBasals(long time) { + public IobTotal getCalculationToTimeTempBasals(long time, Profile profile) { IobTotal total = new IobTotal(time); synchronized (tempBasals) { for (Integer pos = 0; pos < tempBasals.size(); pos++) { TemporaryBasal t = tempBasals.get(pos); if (t.date > time) continue; - IobTotal calc = t.iobCalc(time); + IobTotal calc = t.iobCalc(time, profile); //log.debug("BasalIOB " + new Date(time) + " >>> " + calc.basaliob); total.plus(calc); - if (!t.isEndingEvent()) { - total.lastTempDate = t.date; - total.lastTempDuration = t.durationInMinutes; - Profile profile = MainApp.getConfigBuilder().getProfile(t.date); - total.lastTempRate = t.tempBasalConvertedToAbsolute(t.date, profile); - } - } } if (ConfigBuilderPlugin.getActivePump().isFakingTempsByExtendedBoluses()) { @@ -338,13 +340,6 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface if (e.date > time) continue; IobTotal calc = e.iobCalc(time); totalExt.plus(calc); - TemporaryBasal t = new TemporaryBasal(e); - if (!t.isEndingEvent() && t.date > total.lastTempDate) { - total.lastTempDate = t.date; - total.lastTempDuration = t.durationInMinutes; - Profile profile = MainApp.getConfigBuilder().getProfile(t.date); - total.lastTempRate = t.tempBasalConvertedToAbsolute(t.date, profile); - } } } // Convert to basal iob @@ -359,7 +354,9 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface @Override public void updateTotalIOBTempBasals() { - lastTempBasalsCalculation = getCalculationToTimeTempBasals(System.currentTimeMillis()); + Profile profile = MainApp.getConfigBuilder().getProfile(); + if (profile != null) + lastTempBasalsCalculation = getCalculationToTimeTempBasals(DateUtil.now(), profile); } @Nullable @@ -442,7 +439,7 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface treatment.carbs = detailedBolusInfo.carbs; treatment.source = detailedBolusInfo.source; treatment.mealBolus = treatment.carbs > 0; - boolean newRecordCreated = MainApp.getDbHelper().createOrUpdate(treatment); + boolean newRecordCreated = getService().createOrUpdate(treatment); //log.debug("Adding new Treatment record" + treatment.toString()); if (detailedBolusInfo.carbTime != 0) { Treatment carbsTreatment = new Treatment(); @@ -451,7 +448,7 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface carbsTreatment.date = detailedBolusInfo.date + detailedBolusInfo.carbTime * 60 * 1000L + 1000L; // add 1 sec to make them different records carbsTreatment.carbs = detailedBolusInfo.carbs; carbsTreatment.source = detailedBolusInfo.source; - MainApp.getDbHelper().createOrUpdate(carbsTreatment); + getService().createOrUpdate(carbsTreatment); //log.debug("Adding new Treatment record" + carbsTreatment); } if (newRecordCreated && detailedBolusInfo.isValid) @@ -480,6 +477,7 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface // TempTargets @Subscribe + @SuppressWarnings("unused") public void onStatusEvent(final EventTempTargetChange ev) { initializeTempTargetData(); } @@ -509,6 +507,7 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface // Profile Switch @Subscribe + @SuppressWarnings("unused") public void onStatusEvent(final EventReloadProfileSwitchData ev) { initializeProfileSwitchData(); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsBolusFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsBolusFragment.java index 6831ee33f9..87626ed4cd 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsBolusFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsBolusFragment.java @@ -31,7 +31,7 @@ import info.nightscout.androidaps.Services.Intents; import info.nightscout.androidaps.data.Iob; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.db.Source; -import info.nightscout.androidaps.db.Treatment; +import info.nightscout.androidaps.plugins.Treatments.Treatment; import info.nightscout.androidaps.events.EventNewBG; import info.nightscout.androidaps.events.EventTreatmentChange; import info.nightscout.androidaps.plugins.Common.SubscriberFragment; @@ -145,14 +145,14 @@ public class TreatmentsBolusFragment extends SubscriberFragment implements View. final String _id = treatment._id; if (treatment.source == Source.PUMP) { treatment.isValid = false; - MainApp.getDbHelper().update(treatment); + TreatmentsPlugin.getPlugin().getService().update(treatment); } else { if (NSUpload.isIdValid(_id)) { NSUpload.removeCareportalEntryFromNS(_id); } else { UploadQueue.removeID("dbAdd", _id); } - MainApp.getDbHelper().delete(treatment); + TreatmentsPlugin.getPlugin().getService().delete(treatment); } updateGUI(); FabricPrivacy.getInstance().logCustom(new CustomEvent("RemoveTreatment")); @@ -204,7 +204,7 @@ public class TreatmentsBolusFragment extends SubscriberFragment implements View. 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().resetTreatments(); + TreatmentsPlugin.getPlugin().getService().resetTreatments(); Intent restartNSClient = new Intent(Intents.ACTION_RESTART); MainApp.instance().getApplicationContext().sendBroadcast(restartNSClient); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsTemporaryBasalsFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsTemporaryBasalsFragment.java index b9004e8dd5..957c5c02f1 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsTemporaryBasalsFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsTemporaryBasalsFragment.java @@ -2,9 +2,9 @@ package info.nightscout.androidaps.plugins.Treatments.fragments; import android.app.Activity; import android.content.Context; -import android.content.DialogInterface; import android.graphics.Paint; import android.os.Bundle; +import android.support.annotation.NonNull; import android.support.v4.content.ContextCompat; import android.support.v7.app.AlertDialog; import android.support.v7.widget.CardView; @@ -18,9 +18,6 @@ import android.widget.TextView; import com.crashlytics.android.answers.CustomEvent; import com.squareup.otto.Subscribe; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.data.Intervals; @@ -40,8 +37,6 @@ import info.nightscout.utils.NSUpload; public class TreatmentsTemporaryBasalsFragment extends SubscriberFragment { - private static Logger log = LoggerFactory.getLogger(TreatmentsTemporaryBasalsFragment.class); - RecyclerView recyclerView; LinearLayoutManager llm; @@ -70,7 +65,7 @@ public class TreatmentsTemporaryBasalsFragment extends SubscriberFragment { holder.ns.setVisibility(NSUpload.isIdValid(tempBasal._id) ? View.VISIBLE : View.GONE); if (tempBasal.isEndingEvent()) { holder.date.setText(DateUtil.dateAndTimeString(tempBasal.date)); - holder.duration.setText(MainApp.sResources.getString(R.string.cancel)); + holder.duration.setText(MainApp.gs(R.string.cancel)); holder.absolute.setText(""); holder.percent.setText(""); holder.realDuration.setText(""); @@ -82,14 +77,16 @@ public class TreatmentsTemporaryBasalsFragment extends SubscriberFragment { } else { if (tempBasal.isInProgress()) { holder.date.setText(DateUtil.dateAndTimeString(tempBasal.date)); + holder.date.setTextColor(ContextCompat.getColor(MainApp.instance(), R.color.colorActive)); } else { - holder.date.setText(DateUtil.dateAndTimeString(tempBasal.date) + " - " + DateUtil.timeString(tempBasal.end())); + holder.date.setText(DateUtil.dateAndTimeRangeString(tempBasal.date, tempBasal.end())); + holder.date.setTextColor(holder.netRatio.getCurrentTextColor()); } - holder.duration.setText(DecimalFormatter.to0Decimal(tempBasal.durationInMinutes) + " min"); + holder.duration.setText(DecimalFormatter.to0Decimal(tempBasal.durationInMinutes, " min")); if (tempBasal.isAbsolute) { Profile profile = MainApp.getConfigBuilder().getProfile(tempBasal.date); if (profile != null) { - holder.absolute.setText(DecimalFormatter.to0Decimal(tempBasal.tempBasalConvertedToAbsolute(tempBasal.date, profile)) + " U/h"); + holder.absolute.setText(DecimalFormatter.to0Decimal(tempBasal.tempBasalConvertedToAbsolute(tempBasal.date, profile), " U/h")); holder.percent.setText(""); } else { holder.absolute.setText(MainApp.gs(R.string.noprofile)); @@ -97,24 +94,19 @@ public class TreatmentsTemporaryBasalsFragment extends SubscriberFragment { } } else { holder.absolute.setText(""); - holder.percent.setText(DecimalFormatter.to0Decimal(tempBasal.percentRate) + "%"); + holder.percent.setText(DecimalFormatter.to0Decimal(tempBasal.percentRate, "%")); } - holder.realDuration.setText(DecimalFormatter.to0Decimal(tempBasal.getRealDuration()) + " min"); - IobTotal iob = new IobTotal(System.currentTimeMillis()); - try { // in case app loaded and still no profile selected - iob = tempBasal.iobCalc(System.currentTimeMillis()); - } catch (Exception e) { - } - holder.iob.setText(DecimalFormatter.to2Decimal(iob.basaliob) + " U"); - holder.netInsulin.setText(DecimalFormatter.to2Decimal(iob.netInsulin) + " U"); - holder.netRatio.setText(DecimalFormatter.to2Decimal(iob.netRatio) + " U/h"); - //holder.extendedFlag.setVisibility(tempBasal.isExtended ? View.VISIBLE : View.GONE); + holder.realDuration.setText(DecimalFormatter.to0Decimal(tempBasal.getRealDuration(), " min")); + long now = DateUtil.now(); + IobTotal iob = new IobTotal(now); + Profile profile = MainApp.getConfigBuilder().getProfile(now); + if (profile != null) + iob = tempBasal.iobCalc(now, profile); + holder.iob.setText(DecimalFormatter.to2Decimal(iob.basaliob, " U")); + holder.netInsulin.setText(DecimalFormatter.to2Decimal(iob.netInsulin, " U")); + holder.netRatio.setText(DecimalFormatter.to2Decimal(iob.netRatio, " U/h")); holder.extendedFlag.setVisibility(View.GONE); - if (tempBasal.isInProgress()) - holder.date.setTextColor(ContextCompat.getColor(MainApp.instance(), R.color.colorActive)); - else - holder.date.setTextColor(holder.netRatio.getCurrentTextColor()); - if (tempBasal.iobCalc(System.currentTimeMillis()).basaliob != 0) + if (iob.basaliob != 0) holder.iob.setTextColor(ContextCompat.getColor(MainApp.instance(), R.color.colorActive)); else holder.iob.setTextColor(holder.netRatio.getCurrentTextColor()); @@ -172,21 +164,19 @@ public class TreatmentsTemporaryBasalsFragment extends SubscriberFragment { switch (v.getId()) { case R.id.tempbasals_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(tempBasal.date)); - builder.setPositiveButton(MainApp.sResources.getString(R.string.ok), new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - final String _id = tempBasal._id; - if (NSUpload.isIdValid(_id)) { - NSUpload.removeCareportalEntryFromNS(_id); - } else { - UploadQueue.removeID("dbAdd", _id); - } - MainApp.getDbHelper().delete(tempBasal); - FabricPrivacy.getInstance().logCustom(new CustomEvent("RemoveTempBasal")); + builder.setTitle(MainApp.gs(R.string.confirmation)); + builder.setMessage(MainApp.gs(R.string.removerecord) + "\n" + DateUtil.dateAndTimeString(tempBasal.date)); + builder.setPositiveButton(MainApp.gs(R.string.ok), (dialog, id) -> { + final String _id = tempBasal._id; + if (NSUpload.isIdValid(_id)) { + NSUpload.removeCareportalEntryFromNS(_id); + } else { + UploadQueue.removeID("dbAdd", _id); } + MainApp.getDbHelper().delete(tempBasal); + FabricPrivacy.getInstance().logCustom(new CustomEvent("RemoveTempBasal")); }); - builder.setNegativeButton(MainApp.sResources.getString(R.string.cancel), null); + builder.setNegativeButton(MainApp.gs(R.string.cancel), null); builder.show(); break; } @@ -195,7 +185,7 @@ public class TreatmentsTemporaryBasalsFragment extends SubscriberFragment { } @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.treatments_tempbasals_fragment, container, false); @@ -216,12 +206,12 @@ public class TreatmentsTemporaryBasalsFragment extends SubscriberFragment { } @Subscribe - public void onStatusEvent(final EventTempBasalChange ev) { + public void onStatusEvent(final EventTempBasalChange ignored) { updateGUI(); } @Subscribe - public void onStatusEvent(final EventNewBG ev) { + public void onStatusEvent(final EventNewBG ignored) { updateGUI(); } @@ -229,15 +219,11 @@ public class TreatmentsTemporaryBasalsFragment extends SubscriberFragment { protected void updateGUI() { Activity activity = getActivity(); if (activity != null) - activity.runOnUiThread(new Runnable() { - @Override - public void run() { - recyclerView.swapAdapter(new RecyclerViewAdapter(TreatmentsPlugin.getPlugin().getTemporaryBasalsFromHistory()), false); - if (TreatmentsPlugin.getPlugin().getLastCalculationTempBasals() != null) { - String totalText = DecimalFormatter.to2Decimal(TreatmentsPlugin.getPlugin().getLastCalculationTempBasals().basaliob) + " U"; - tempBasalTotalView.setText(totalText); - } - } + activity.runOnUiThread(() -> { + recyclerView.swapAdapter(new RecyclerViewAdapter(TreatmentsPlugin.getPlugin().getTemporaryBasalsFromHistory()), false); + IobTotal tempBasalsCalculation = TreatmentsPlugin.getPlugin().getLastCalculationTempBasals(); + if (tempBasalsCalculation != null) + tempBasalTotalView.setText(DecimalFormatter.to2Decimal(tempBasalsCalculation.basaliob, " U")); }); } 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 90a1262a6b..bde197b45f 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 @@ -37,7 +37,7 @@ import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.db.DatabaseHelper; import info.nightscout.androidaps.db.TemporaryBasal; -import info.nightscout.androidaps.db.Treatment; +import info.nightscout.androidaps.plugins.Treatments.Treatment; import info.nightscout.androidaps.interfaces.PluginType; import info.nightscout.androidaps.interfaces.TreatmentsInterface; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; 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 141d064682..fa15ee46d2 100644 --- a/app/src/main/java/info/nightscout/androidaps/queue/CommandQueue.java +++ b/app/src/main/java/info/nightscout/androidaps/queue/CommandQueue.java @@ -299,9 +299,10 @@ public class CommandQueue { // returns true if command is queued public boolean setProfile(Profile profile, Callback callback) { - if (isRunning(Command.CommandType.BASALPROFILE)) { + if (isThisProfileSet(profile)) { + log.debug("QUEUE: Correct profile already set"); if (callback != null) - callback.result(executingNowError()).run(); + callback.result(new PumpEnactResult().success(true).enacted(false)).run(); return false; } @@ -329,13 +330,6 @@ public class CommandQueue { MainApp.bus().post(new EventDismissNotification(Notification.BASAL_VALUE_BELOW_MINIMUM)); - if (isThisProfileSet(profile)) { - log.debug("QUEUE: Correct profile already set"); - if (callback != null) - callback.result(new PumpEnactResult().success(true).enacted(false)).run(); - return false; - } - // remove all unfinished removeAll(Command.CommandType.BASALPROFILE); diff --git a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandSetProfile.java b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandSetProfile.java index 96a11dacf5..8a8bc41dfa 100644 --- a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandSetProfile.java +++ b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandSetProfile.java @@ -1,5 +1,8 @@ package info.nightscout.androidaps.queue.commands; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.data.Profile; @@ -17,6 +20,7 @@ import info.nightscout.androidaps.queue.Callback; */ public class CommandSetProfile extends Command { + private static Logger log = LoggerFactory.getLogger(CommandSetProfile.class); private Profile profile; public CommandSetProfile(Profile profile, Callback callback) { @@ -27,6 +31,13 @@ public class CommandSetProfile extends Command { @Override public void execute() { + if (ConfigBuilderPlugin.getCommandQueue().isThisProfileSet(profile)) { + log.debug("QUEUE: Correct profile already set"); + if (callback != null) + callback.result(new PumpEnactResult().success(true).enacted(false)).run(); + return; + } + PumpEnactResult r = ConfigBuilderPlugin.getActivePump().setNewBasalProfile(profile); if (callback != null) callback.result(r).run(); diff --git a/app/src/main/java/info/nightscout/utils/DateUtil.java b/app/src/main/java/info/nightscout/utils/DateUtil.java index cb0081f941..441449e8ee 100644 --- a/app/src/main/java/info/nightscout/utils/DateUtil.java +++ b/app/src/main/java/info/nightscout/utils/DateUtil.java @@ -122,6 +122,10 @@ public class DateUtil { return dateString(date) + " " + timeString(date); } + public static String dateAndTimeRangeString(long start, long end) { + return dateAndTimeString(start) + " - " + timeString(end); + } + public static String dateAndTimeString(long mills) { return dateString(mills) + " " + timeString(mills); } @@ -167,4 +171,8 @@ public class DateUtil { return System.currentTimeMillis(); } + public static long roundDateToSec(long date) { + return date - date % 1000; + } + } diff --git a/app/src/main/java/info/nightscout/utils/DecimalFormatter.java b/app/src/main/java/info/nightscout/utils/DecimalFormatter.java index d821f5ba37..6709b304d9 100644 --- a/app/src/main/java/info/nightscout/utils/DecimalFormatter.java +++ b/app/src/main/java/info/nightscout/utils/DecimalFormatter.java @@ -17,18 +17,34 @@ public class DecimalFormatter { return format0dec.format(value); } + public static String to0Decimal(double value, String unit) { + return format0dec.format(value) + unit; + } + public static String to1Decimal(double value) { return format1dec.format(value); } + public static String to1Decimal(double value, String unit) { + return format1dec.format(value) + unit; + } + public static String to2Decimal(double value) { return format2dec.format(value); } + public static String to2Decimal(double value, String unit) { + return format2dec.format(value) + unit; + } + public static String to3Decimal(double value) { return format3dec.format(value); } + public static String to3Decimal(double value, String unit) { + return format3dec.format(value) + unit; + } + public static String toPumpSupportedBolus(double value) { return ConfigBuilderPlugin.getActivePump().getPumpDescription().bolusStep <= 0.01 ? to2Decimal(value) diff --git a/app/src/main/java/info/nightscout/utils/JsonHelper.java b/app/src/main/java/info/nightscout/utils/JsonHelper.java index 3cc9a3c8a0..ead68132af 100644 --- a/app/src/main/java/info/nightscout/utils/JsonHelper.java +++ b/app/src/main/java/info/nightscout/utils/JsonHelper.java @@ -17,41 +17,79 @@ public class JsonHelper { private JsonHelper() {}; - public static String safeGetString(JSONObject json, String fieldName) throws JSONException { + public static String safeGetString(JSONObject json, String fieldName) { String result = null; if (json.has(fieldName)) { - result = json.getString(fieldName); + try { + result = json.getString(fieldName); + } catch (JSONException ignored) { + } } return result; } - public static String safeGetString(JSONObject json, String fieldName, String defaultValue) throws JSONException { + public static String safeGetString(JSONObject json, String fieldName, String defaultValue) { String result = defaultValue; if (json.has(fieldName)) { - result = json.getString(fieldName); + try { + result = json.getString(fieldName); + } catch (JSONException ignored) { + } } return result; } - public static double safeGetDouble(JSONObject json, String fieldName) throws JSONException { + public static double safeGetDouble(JSONObject json, String fieldName) { double result = 0d; if (json.has(fieldName)) { - result = json.getDouble(fieldName); + try { + result = json.getDouble(fieldName); + } catch (JSONException ignored) { + } } return result; } - public static int safeGetInt(JSONObject json, String fieldName) throws JSONException { + public static int safeGetInt(JSONObject json, String fieldName) { int result = 0; if (json.has(fieldName)) { - result = json.getInt(fieldName); + try { + result = json.getInt(fieldName); + } catch (JSONException ignored) { + } + } + + return result; + } + + public static long safeGetLong(JSONObject json, String fieldName) { + long result = 0; + + if (json.has(fieldName)) { + try { + result = json.getLong(fieldName); + } catch (JSONException e) { + } + } + + return result; + } + + public static boolean safeGetBoolean(JSONObject json, String fieldName) { + boolean result = false; + + if (json.has(fieldName)) { + try { + result = json.getBoolean(fieldName); + } catch (JSONException e) { + } } return result; diff --git a/app/src/main/java/info/nightscout/utils/NSUpload.java b/app/src/main/java/info/nightscout/utils/NSUpload.java index 96d24af4d4..9b9b940ef9 100644 --- a/app/src/main/java/info/nightscout/utils/NSUpload.java +++ b/app/src/main/java/info/nightscout/utils/NSUpload.java @@ -406,6 +406,10 @@ public class NSUpload { } public static void uploadError(String error) { + uploadError(error, new Date()); + } + + public static void uploadError(String error, Date date) { Context context = MainApp.instance().getApplicationContext(); Bundle bundle = new Bundle(); bundle.putString("action", "dbAdd"); @@ -413,7 +417,7 @@ public class NSUpload { JSONObject data = new JSONObject(); try { data.put("eventType", "Announcement"); - data.put("created_at", DateUtil.toISOString(new Date())); + data.put("created_at", DateUtil.toISOString(date)); data.put("enteredBy", SP.getString("careportal_enteredby", MainApp.gs(R.string.app_name))); data.put("notes", error); data.put("isAnnouncement", true); diff --git a/app/src/main/java/info/nightscout/utils/NumberPicker.java b/app/src/main/java/info/nightscout/utils/NumberPicker.java index 53ffd90f7b..01c7dcb336 100644 --- a/app/src/main/java/info/nightscout/utils/NumberPicker.java +++ b/app/src/main/java/info/nightscout/utils/NumberPicker.java @@ -148,6 +148,9 @@ public class NumberPicker extends LinearLayout implements View.OnKeyListener, } public void setParams(Double initValue, Double minValue, Double maxValue, Double step, NumberFormat formater, boolean allowZero, TextWatcher textWatcher) { + if(this.textWatcher != null) { + editText.removeTextChangedListener(this.textWatcher); + } setParams(initValue, minValue, maxValue, step, formater, allowZero); this.textWatcher = textWatcher; editText.addTextChangedListener(textWatcher); diff --git a/app/src/main/java/info/nightscout/utils/TimeListEdit.java b/app/src/main/java/info/nightscout/utils/TimeListEdit.java index bc41ece59d..ec03734b18 100644 --- a/app/src/main/java/info/nightscout/utils/TimeListEdit.java +++ b/app/src/main/java/info/nightscout/utils/TimeListEdit.java @@ -78,6 +78,7 @@ public class TimeListEdit { private void buildView() { layout = (LinearLayout) view.findViewById(resLayoutId); + layout.removeAllViews(); textlabel = new TextView(context); textlabel.setText(label); diff --git a/app/src/main/res/layout/combo_alert_history_fragment.xml b/app/src/main/res/layout/combo_alert_history_fragment.xml deleted file mode 100644 index f1faa9bb86..0000000000 --- a/app/src/main/res/layout/combo_alert_history_fragment.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/combo_tdd_history_fragment.xml b/app/src/main/res/layout/combo_tdd_history_fragment.xml deleted file mode 100644 index 04335526ba..0000000000 --- a/app/src/main/res/layout/combo_tdd_history_fragment.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/combopump_fragment.xml b/app/src/main/res/layout/combopump_fragment.xml index 67b135b677..5bb90090be 100644 --- a/app/src/main/res/layout/combopump_fragment.xml +++ b/app/src/main/res/layout/combopump_fragment.xml @@ -499,46 +499,6 @@ android:paddingLeft="0dp" android:paddingRight="0dp" android:text="@string/combo_refresh" /> - - - - - - - diff --git a/app/src/main/res/layout/localprofile_fragment.xml b/app/src/main/res/layout/localprofile_fragment.xml index 4b61e0235d..a08c6964e9 100644 --- a/app/src/main/res/layout/localprofile_fragment.xml +++ b/app/src/main/res/layout/localprofile_fragment.xml @@ -153,6 +153,43 @@ android:text="@string/activate_profile" android:textColor="@color/colorProfileSwitchButton" /> + +