From 7763a96d6a097b7ad05b363a0d6228787e2cc605 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Sat, 6 Feb 2021 00:30:27 +0100 Subject: [PATCH 1/8] migrate BG code --- .../info/nightscout/androidaps/MainApp.java | 19 +- .../androidaps/db/CompatDBHelper.kt | 43 +++ .../androidaps/db/DatabaseHelper.java | 152 +------- .../androidaps/db/DatabaseHelperProvider.java | 4 - .../dependencyInjection/AppComponent.kt | 2 + .../androidaps/dialogs/WizardDialog.kt | 5 +- .../androidaps/events/EventNewBG.kt | 4 +- .../IobCobCalculatorPluginHistory.kt | 6 +- .../plugins/aps/loop/LoopPlugin.java | 12 +- .../dataBroadcaster/DataBroadcastPlugin.kt | 7 +- .../maintenance/MaintenanceFragment.kt | 8 +- .../general/openhumans/OpenHumansUploader.kt | 18 +- .../general/overview/OverviewFragment.kt | 14 +- .../general/overview/graphData/GraphData.kt | 17 +- .../PersistentNotificationPlugin.kt | 5 +- .../smsCommunicator/SmsCommunicatorPlugin.kt | 6 +- .../general/tidepool/TidepoolPlugin.kt | 8 +- .../general/tidepool/comm/UploadChunk.kt | 17 +- .../tidepool/elements/SensorGlucoseElement.kt | 4 +- .../general/wear/ActionStringHandler.kt | 6 +- .../wearintegration/WatchUpdaterService.java | 38 +- .../iob/iobCobCalculator/GlucoseStatus.java | 27 +- .../iobCobCalculator/InMemoryGlucoseValue.kt | 6 +- .../IobCobCalculatorPlugin.java | 95 ++--- .../plugins/source/BGSourceFragment.kt | 122 +++---- .../androidaps/plugins/source/DexcomPlugin.kt | 146 ++++---- .../plugins/source/EversensePlugin.kt | 48 ++- .../androidaps/plugins/source/GlimpPlugin.kt | 45 ++- .../androidaps/plugins/source/MM640gPlugin.kt | 53 ++- .../plugins/source/NSClientSourcePlugin.kt | 77 ++-- .../plugins/source/PoctechPlugin.kt | 49 ++- .../plugins/source/RandomBgPlugin.kt | 45 ++- .../androidaps/plugins/source/TomatoPlugin.kt | 46 ++- .../androidaps/plugins/source/XdripPlugin.kt | 50 ++- .../androidaps/utils/GlucoseValueUtils.kt | 18 + .../androidaps/utils/LocalAlertUtils.kt | 5 +- .../androidaps/utils/XDripBroadcast.kt | 60 ++++ .../androidaps/utils/stats/TirCalculator.kt | 12 +- .../utils/wizard/QuickWizardEntry.kt | 7 +- core/build.gradle | 4 + core/core_dependencies.gradle | 4 +- .../nightscout/androidaps/db/BgReading.java | 334 ------------------ .../nightscout/androidaps/db/BgReading.kt | 171 +++++++++ .../interfaces/DatabaseHelperInterface.kt | 1 - .../plugins/aps/loop/APSResult.java | 48 +-- .../plugins/general/nsclient/NSUpload.java | 48 +-- .../utils/extensions/TrendArrowIcon.kt | 18 + .../activities/DanaUserOptionsActivity.kt | 2 +- .../androidaps/database/AppRepository.kt | 4 +- 49 files changed, 978 insertions(+), 962 deletions(-) create mode 100644 app/src/main/java/info/nightscout/androidaps/db/CompatDBHelper.kt create mode 100644 app/src/main/java/info/nightscout/androidaps/utils/GlucoseValueUtils.kt create mode 100644 app/src/main/java/info/nightscout/androidaps/utils/XDripBroadcast.kt delete mode 100644 core/src/main/java/info/nightscout/androidaps/db/BgReading.java create mode 100644 core/src/main/java/info/nightscout/androidaps/db/BgReading.kt create mode 100644 core/src/main/java/info/nightscout/androidaps/utils/extensions/TrendArrowIcon.kt diff --git a/app/src/main/java/info/nightscout/androidaps/MainApp.java b/app/src/main/java/info/nightscout/androidaps/MainApp.java index d03fd25c8f..5deb4acd2d 100644 --- a/app/src/main/java/info/nightscout/androidaps/MainApp.java +++ b/app/src/main/java/info/nightscout/androidaps/MainApp.java @@ -18,6 +18,9 @@ import javax.inject.Inject; import dagger.android.AndroidInjector; import dagger.android.DaggerApplication; +import info.nightscout.androidaps.database.AppRepository; +import info.nightscout.androidaps.database.transactions.VersionChangeTransaction; +import info.nightscout.androidaps.db.CompatDBHelper; import info.nightscout.androidaps.db.DatabaseHelper; import info.nightscout.androidaps.db.StaticInjector; import info.nightscout.androidaps.dependencyInjection.DaggerAppComponent; @@ -38,11 +41,14 @@ import info.nightscout.androidaps.services.Intents; import info.nightscout.androidaps.utils.ActivityMonitor; import info.nightscout.androidaps.utils.locale.LocaleHelper; import info.nightscout.androidaps.utils.sharedPreferences.SP; +import io.reactivex.disposables.CompositeDisposable; public class MainApp extends DaggerApplication { static DatabaseHelper sDatabaseHelper = null; + private final CompositeDisposable disposable = new CompositeDisposable(); + @Inject PluginStore pluginStore; @Inject AAPSLogger aapsLogger; @Inject ActivityMonitor activityMonitor; @@ -54,6 +60,8 @@ public class MainApp extends DaggerApplication { @Inject ConfigBuilderPlugin configBuilderPlugin; @Inject KeepAliveReceiver.KeepAliveManager keepAliveManager; @Inject List plugins; + @Inject CompatDBHelper compatDBHelper; + @Inject AppRepository repository; @Inject StaticInjector staticInjector; // TODO avoid , here fake only to initialize @@ -73,6 +81,15 @@ public class MainApp extends DaggerApplication { aapsLogger.error("Uncaught exception crashing app", ex); }); */ + String gitRemote = BuildConfig.REMOTE; + String commitHash = BuildConfig.HEAD; + if (gitRemote.contains("NoGitSystemAvailable")) { + gitRemote = null; + commitHash = null; + } + disposable.add(repository.runTransaction(new VersionChangeTransaction(BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE, gitRemote, commitHash)).subscribe()); + disposable.add(compatDBHelper.dbChangeDisposable()); + registerActivityLifecycleCallbacks(activityMonitor); JodaTimeAndroid.init(this); @@ -120,7 +137,7 @@ public class MainApp extends DaggerApplication { filter.addAction(Intents.ACTION_NEW_TREATMENT); filter.addAction(Intents.ACTION_CHANGED_TREATMENT); filter.addAction(Intents.ACTION_REMOVED_TREATMENT); - filter.addAction(Intents.ACTION_NEW_SGV); + //filter.addAction(Intents.ACTION_NEW_SGV); filter.addAction(Intents.ACTION_NEW_PROFILE); filter.addAction(Intents.ACTION_NEW_MBG); filter.addAction(Intents.ACTION_NEW_CAL); diff --git a/app/src/main/java/info/nightscout/androidaps/db/CompatDBHelper.kt b/app/src/main/java/info/nightscout/androidaps/db/CompatDBHelper.kt new file mode 100644 index 0000000000..7aa4667ac1 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/db/CompatDBHelper.kt @@ -0,0 +1,43 @@ +package info.nightscout.androidaps.db + +import info.nightscout.androidaps.database.AppRepository +import info.nightscout.androidaps.database.entities.GlucoseValue +import info.nightscout.androidaps.database.entities.TemporaryTarget +import info.nightscout.androidaps.database.interfaces.TraceableDBEntry +import info.nightscout.androidaps.events.EventNewBG +import info.nightscout.androidaps.events.EventTempTargetChange +import info.nightscout.androidaps.logging.AAPSLogger +import info.nightscout.androidaps.logging.LTag +import info.nightscout.androidaps.plugins.bus.RxBusWrapper +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventNewHistoryData +import io.reactivex.disposables.Disposable +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class CompatDBHelper @Inject constructor( + val aapsLogger: AAPSLogger, + val repository: AppRepository, + val rxBus: RxBusWrapper +) { + + fun dbChangeDisposable(): Disposable = repository + .changeObservable() + .doOnSubscribe { + rxBus.send(EventNewBG(null)) + } + .subscribe { + it.filterIsInstance().firstOrNull()?.let { + aapsLogger.debug(LTag.DATABASE, "Firing EventNewHistoryData") + rxBus.send(EventNewHistoryData(it.timestamp)) + } + it.filterIsInstance().lastOrNull()?.let { + aapsLogger.debug(LTag.DATABASE, "Firing EventNewBg") + rxBus.send(EventNewBG(it)) + } + it.filterIsInstance().firstOrNull()?.let { + aapsLogger.debug(LTag.DATABASE, "Firing EventTempTargetChange") + rxBus.send(EventTempTargetChange()) + } + } +} \ No newline at end of file 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 679e119b21..2589e7eb87 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java +++ b/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java @@ -33,13 +33,11 @@ import java.util.concurrent.TimeUnit; import javax.inject.Inject; import info.nightscout.androidaps.Constants; -import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.dana.comm.RecordTypes; import info.nightscout.androidaps.data.NonOverlappingIntervals; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.events.EventCareportalEventChange; import info.nightscout.androidaps.events.EventExtendedBolusChange; -import info.nightscout.androidaps.events.EventNewBG; import info.nightscout.androidaps.events.EventProfileNeedsUpdate; import info.nightscout.androidaps.events.EventRefreshOverview; import info.nightscout.androidaps.events.EventReloadProfileSwitchData; @@ -54,9 +52,7 @@ import info.nightscout.androidaps.logging.AAPSLogger; import info.nightscout.androidaps.logging.LTag; import info.nightscout.androidaps.plugins.bus.RxBusWrapper; import info.nightscout.androidaps.plugins.general.nsclient.NSUpload; -import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventNewHistoryBgData; import info.nightscout.androidaps.plugins.general.openhumans.OpenHumansUploader; -import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin; import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventNewHistoryData; import info.nightscout.androidaps.plugins.pump.insight.database.InsightBolusID; import info.nightscout.androidaps.plugins.pump.insight.database.InsightHistoryOffset; @@ -64,7 +60,6 @@ import info.nightscout.androidaps.plugins.pump.insight.database.InsightPumpID; import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin; import info.nightscout.androidaps.utils.JsonHelper; import info.nightscout.androidaps.utils.PercentageSplitter; -import info.nightscout.androidaps.utils.T; /** * This Helper contains all resource to provide a central DB management functionality. Only methods handling @@ -81,7 +76,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { @Inject OpenHumansUploader openHumansUploader; public static final String DATABASE_NAME = "AndroidAPSDb"; - public static final String DATABASE_BGREADINGS = "BgReadings"; public static final String DATABASE_TEMPORARYBASALS = "TemporaryBasals"; public static final String DATABASE_EXTENDEDBOLUSES = "ExtendedBoluses"; public static final String DATABASE_TEMPTARGETS = "TempTargets"; @@ -101,10 +95,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { private static final ScheduledExecutorService bgWorker = Executors.newSingleThreadScheduledExecutor(); private static ScheduledFuture scheduledBgPost = null; - private static final ScheduledExecutorService bgHistoryWorker = Executors.newSingleThreadScheduledExecutor(); - private static ScheduledFuture scheduledBgHistoryPost = null; - private static long oldestBgHistoryChange = 0; - private static final ScheduledExecutorService tempBasalsWorker = Executors.newSingleThreadScheduledExecutor(); private static ScheduledFuture scheduledTemBasalsPost = null; @@ -135,7 +125,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { try { aapsLogger.info(LTag.DATABASE, "onCreate"); TableUtils.createTableIfNotExists(connectionSource, TempTarget.class); - TableUtils.createTableIfNotExists(connectionSource, BgReading.class); + //TableUtils.createTableIfNotExists(connectionSource, BgReading.class); TableUtils.createTableIfNotExists(connectionSource, DanaRHistoryRecord.class); TableUtils.createTableIfNotExists(connectionSource, DbRequest.class); TableUtils.createTableIfNotExists(connectionSource, TemporaryBasal.class); @@ -167,7 +157,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { if (oldVersion < 7) { aapsLogger.info(LTag.DATABASE, "onUpgrade"); TableUtils.dropTable(connectionSource, TempTarget.class, true); - TableUtils.dropTable(connectionSource, BgReading.class, true); + //TableUtils.dropTable(connectionSource, BgReading.class, true); TableUtils.dropTable(connectionSource, DanaRHistoryRecord.class, true); TableUtils.dropTable(connectionSource, DbRequest.class, true); TableUtils.dropTable(connectionSource, TemporaryBasal.class, true); @@ -217,7 +207,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { public void resetDatabases() { try { TableUtils.dropTable(connectionSource, TempTarget.class, true); - TableUtils.dropTable(connectionSource, BgReading.class, true); + //TableUtils.dropTable(connectionSource, BgReading.class, true); TableUtils.dropTable(connectionSource, DanaRHistoryRecord.class, true); TableUtils.dropTable(connectionSource, DbRequest.class, true); TableUtils.dropTable(connectionSource, TemporaryBasal.class, true); @@ -241,7 +231,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { aapsLogger.error("Unhandled exception", e); } virtualPumpPlugin.setFakingStatus(true); - scheduleBgChange(null); // trigger refresh scheduleTemporaryBasalChange(); scheduleExtendedBolusChange(); scheduleTemporaryTargetChange(); @@ -384,136 +373,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { aapsLogger.debug(LTag.DATABASE, "Rounding " + date + " to " + rounded); return rounded; } - // ------------------- BgReading handling ----------------------- - - public boolean createIfNotExists(BgReading bgReading, String from) { - try { - bgReading.date = roundDateToSec(bgReading.date); - BgReading old = getDaoBgReadings().queryForId(bgReading.date); - if (old == null) { - getDaoBgReadings().create(bgReading); - openHumansUploader.enqueueBGReading(bgReading); - aapsLogger.debug(LTag.DATABASE, "BG: New record from: " + from + " " + bgReading.toString()); - scheduleBgChange(bgReading); - return true; - } - if (!old.isEqual(bgReading)) { - aapsLogger.debug(LTag.DATABASE, "BG: Similiar found: " + old.toString()); - old.copyFrom(bgReading); - getDaoBgReadings().update(old); - openHumansUploader.enqueueBGReading(old); - aapsLogger.debug(LTag.DATABASE, "BG: Updating record from: " + from + " New data: " + old.toString()); - scheduleBgHistoryChange(old.date); // trigger cache invalidation - return false; - } - } catch (SQLException e) { - aapsLogger.error("Unhandled exception", e); - } - return false; - } - - public void update(BgReading bgReading) { - bgReading.date = roundDateToSec(bgReading.date); - try { - getDaoBgReadings().update(bgReading); - openHumansUploader.enqueueBGReading(bgReading); - aapsLogger.debug(LTag.DATABASE, "BG: Updating record from: "+ bgReading.toString()); - scheduleBgHistoryChange(bgReading.date); // trigger cache invalidation - } catch (SQLException e) { - aapsLogger.error("Unhandled exception", e); - } - } - - private void scheduleBgChange(@Nullable final BgReading bgReading) { - class PostRunnable implements Runnable { - public void run() { - aapsLogger.debug(LTag.DATABASE, "Firing EventNewBg"); - rxBus.send(new EventNewBG(bgReading)); - scheduledBgPost = null; - } - } - // prepare task for execution in 1 sec - // cancel waiting task to prevent sending multiple posts - if (scheduledBgPost != null) - scheduledBgPost.cancel(false); - Runnable task = new PostRunnable(); - final int sec = 1; - scheduledBgPost = bgWorker.schedule(task, sec, TimeUnit.SECONDS); - - } - - private void scheduleBgHistoryChange(@Nullable final long timestamp) { - class PostRunnable implements Runnable { - public void run() { - aapsLogger.debug(LTag.DATABASE, "Firing EventNewBg"); - rxBus.send(new EventNewHistoryBgData(oldestBgHistoryChange)); - scheduledBgHistoryPost = null; - oldestBgHistoryChange = 0; - } - } - // prepare task for execution in 1 sec - // cancel waiting task to prevent sending multiple posts - if (scheduledBgHistoryPost != null) - scheduledBgHistoryPost.cancel(false); - Runnable task = new PostRunnable(); - final int sec = 3; - if (oldestBgHistoryChange == 0 || oldestBgHistoryChange > timestamp) - oldestBgHistoryChange = timestamp; - scheduledBgHistoryPost = bgHistoryWorker.schedule(task, sec, TimeUnit.SECONDS); - - } - - public List getBgreadingsDataFromTime(long mills, boolean ascending) { - try { - Dao daoBgreadings = getDaoBgReadings(); - List bgReadings; - QueryBuilder queryBuilder = daoBgreadings.queryBuilder(); - queryBuilder.orderBy("date", ascending); - Where where = queryBuilder.where(); - where.ge("date", mills).and().ge("value", 39).and().eq("isValid", true); - PreparedQuery preparedQuery = queryBuilder.prepare(); - bgReadings = daoBgreadings.query(preparedQuery); - return bgReadings; - } catch (SQLException e) { - aapsLogger.error("Unhandled exception", e); - } - return new ArrayList<>(); - } - - public List getBgreadingsDataFromTime(long start, long end, boolean ascending) { - try { - Dao daoBgreadings = getDaoBgReadings(); - List bgReadings; - QueryBuilder queryBuilder = daoBgreadings.queryBuilder(); - queryBuilder.orderBy("date", ascending); - Where where = queryBuilder.where(); - where.between("date", start, end).and().ge("value", 39).and().eq("isValid", true); - PreparedQuery preparedQuery = queryBuilder.prepare(); - bgReadings = daoBgreadings.query(preparedQuery); - return bgReadings; - } catch (SQLException e) { - aapsLogger.error("Unhandled exception", e); - } - return new ArrayList<>(); - } - - public List getAllBgreadingsDataFromTime(long mills, boolean ascending) { - try { - Dao daoBgreadings = getDaoBgReadings(); - List bgReadings; - QueryBuilder queryBuilder = daoBgreadings.queryBuilder(); - queryBuilder.orderBy("date", ascending); - Where where = queryBuilder.where(); - where.ge("date", mills); - PreparedQuery preparedQuery = queryBuilder.prepare(); - bgReadings = daoBgreadings.query(preparedQuery); - return bgReadings; - } catch (SQLException e) { - aapsLogger.error("Unhandled exception", e); - } - return new ArrayList(); - } - public List getAllBgReadings() { try { return getDaoBgReadings().queryForAll(); @@ -2010,7 +1869,8 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { return null; } - // Copied from xDrip+ +/* + TODO implement again for database branch // Copied from xDrip+ String calculateDirection(BgReading bgReading) { // Rework to get bgreaings from internal DB and calculate on that base @@ -2056,7 +1916,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { // aapsLogger.error(LTag.GLUCOSE, "Direction set to: " + arrow); return arrow; } - +*/ // ---------------- Open Humans Queue handling --------------- public void clearOpenHumansQueue() { diff --git a/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelperProvider.java b/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelperProvider.java index ae3e52180c..41f7cabdd9 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelperProvider.java +++ b/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelperProvider.java @@ -20,10 +20,6 @@ public class DatabaseHelperProvider implements DatabaseHelperInterface { @Inject DatabaseHelperProvider() { } - @NotNull @Override public List getAllBgreadingsDataFromTime(long mills, boolean ascending) { - return MainApp.getDbHelper().getAllBgreadingsDataFromTime(mills, ascending); - } - @Override public void createOrUpdate(@NotNull CareportalEvent careportalEvent) { MainApp.getDbHelper().createOrUpdate(careportalEvent); } diff --git a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/AppComponent.kt b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/AppComponent.kt index 5e36be6be2..1ec7d8b22a 100644 --- a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/AppComponent.kt +++ b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/AppComponent.kt @@ -9,6 +9,7 @@ import info.nightscout.androidaps.core.di.CoreModule import info.nightscout.androidaps.dana.di.DanaModule import info.nightscout.androidaps.danar.di.DanaRModule import info.nightscout.androidaps.danars.di.DanaRSModule +import info.nightscout.androidaps.database.DatabaseModule import info.nightscout.androidaps.plugins.pump.common.dagger.RileyLinkModule import info.nightscout.androidaps.plugins.pump.omnipod.dagger.OmnipodModule import javax.inject.Singleton @@ -17,6 +18,7 @@ import javax.inject.Singleton @Component( modules = [ AndroidInjectionModule::class, + DatabaseModule::class, PluginsModule::class, SkinsModule::class, ActivitiesModule::class, diff --git a/app/src/main/java/info/nightscout/androidaps/dialogs/WizardDialog.kt b/app/src/main/java/info/nightscout/androidaps/dialogs/WizardDialog.kt index dc3d1d47e5..81413ab08f 100644 --- a/app/src/main/java/info/nightscout/androidaps/dialogs/WizardDialog.kt +++ b/app/src/main/java/info/nightscout/androidaps/dialogs/WizardDialog.kt @@ -13,6 +13,7 @@ import android.widget.AdapterView.OnItemSelectedListener import android.widget.ArrayAdapter import android.widget.CompoundButton import androidx.fragment.app.FragmentManager +import dagger.android.HasAndroidInjector import dagger.android.support.DaggerDialogFragment import info.nightscout.androidaps.Constants import info.nightscout.androidaps.MainApp @@ -38,6 +39,7 @@ import info.nightscout.androidaps.utils.extensions.toVisibility import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.sharedPreferences.SP +import info.nightscout.androidaps.utils.valueToUnits import info.nightscout.androidaps.utils.wizard.BolusWizard import io.reactivex.disposables.CompositeDisposable import java.text.DecimalFormat @@ -47,6 +49,7 @@ import kotlin.math.abs class WizardDialog : DaggerDialogFragment() { + @Inject lateinit var injector: HasAndroidInjector @Inject lateinit var aapsLogger: AAPSLogger @Inject lateinit var aapsSchedulers: AapsSchedulers @Inject lateinit var constraintChecker: ConstraintChecker @@ -332,7 +335,7 @@ class WizardDialog : DaggerDialogFragment() { binding.notes.text.toString(), carbTime) wizard?.let { wizard -> - binding.bg.text = String.format(resourceHelper.gs(R.string.format_bg_isf), BgReading().value(Profile.toMgdl(bg, profileFunction.getUnits())).valueToUnitsToString(profileFunction.getUnits()), wizard.sens) + binding.bg.text = String.format(resourceHelper.gs(R.string.format_bg_isf), BgReading(injector).value(Profile.toMgdl(bg, profileFunction.getUnits())).valueToUnitsToString(profileFunction.getUnits()), wizard.sens) binding.bginsulin.text = resourceHelper.gs(R.string.formatinsulinunits, wizard.insulinFromBG) binding.carbs.text = String.format(resourceHelper.gs(R.string.format_carbs_ic), carbs.toDouble(), wizard.ic) diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventNewBG.kt b/app/src/main/java/info/nightscout/androidaps/events/EventNewBG.kt index 08c05407c9..4f05f83018 100644 --- a/app/src/main/java/info/nightscout/androidaps/events/EventNewBG.kt +++ b/app/src/main/java/info/nightscout/androidaps/events/EventNewBG.kt @@ -1,5 +1,5 @@ package info.nightscout.androidaps.events -import info.nightscout.androidaps.db.BgReading +import info.nightscout.androidaps.database.entities.GlucoseValue -class EventNewBG(val bgReading: BgReading?) : EventLoop() \ No newline at end of file +class EventNewBG(val glucoseValue: GlucoseValue?) : EventLoop() \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/historyBrowser/IobCobCalculatorPluginHistory.kt b/app/src/main/java/info/nightscout/androidaps/historyBrowser/IobCobCalculatorPluginHistory.kt index 14d2da5ac1..8dc1ebfb32 100644 --- a/app/src/main/java/info/nightscout/androidaps/historyBrowser/IobCobCalculatorPluginHistory.kt +++ b/app/src/main/java/info/nightscout/androidaps/historyBrowser/IobCobCalculatorPluginHistory.kt @@ -1,6 +1,7 @@ package info.nightscout.androidaps.historyBrowser import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.logging.AAPSLogger @@ -32,9 +33,10 @@ class IobCobCalculatorPluginHistory @Inject constructor( sensitivityAAPSPlugin: SensitivityAAPSPlugin, sensitivityWeightedAveragePlugin: SensitivityWeightedAveragePlugin, fabricPrivacy: FabricPrivacy, - dateUtil: DateUtil + dateUtil: DateUtil, + repository: AppRepository ) : IobCobCalculatorPlugin(injector, aapsLogger, aapsSchedulers, rxBus, sp, resourceHelper, profileFunction, - activePlugin, treatmentsPluginHistory, sensitivityOref1Plugin, sensitivityAAPSPlugin, sensitivityWeightedAveragePlugin, fabricPrivacy, dateUtil) { + activePlugin, treatmentsPluginHistory, sensitivityOref1Plugin, sensitivityAAPSPlugin, sensitivityWeightedAveragePlugin, fabricPrivacy, dateUtil, repository) { override fun onStart() { // do not attach to rxbus } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.java index 5cd3ded85e..4604c31db6 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.java @@ -30,7 +30,7 @@ import info.nightscout.androidaps.activities.ErrorHelperActivity; import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.PumpEnactResult; -import info.nightscout.androidaps.db.BgReading; +import info.nightscout.androidaps.database.entities.GlucoseValue; import info.nightscout.androidaps.db.CareportalEvent; import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.TemporaryBasal; @@ -201,14 +201,14 @@ public class LoopPlugin extends PluginBase implements LoopInterface { // Autosens calculation not triggered by a new BG if (!(event.getCause() instanceof EventNewBG)) return; - BgReading bgReading = iobCobCalculatorPlugin.actualBg(); + GlucoseValue glucoseValue = iobCobCalculatorPlugin.actualBg(); // BG outdated - if (bgReading == null) return; + if (glucoseValue == null) return; // already looped with that value - if (bgReading.date <= lastBgTriggeredRun) return; + if (glucoseValue.getTimestamp() <= lastBgTriggeredRun) return; - lastBgTriggeredRun = bgReading.date; - invoke("AutosenseCalculation for " + bgReading, true); + lastBgTriggeredRun = glucoseValue.getTimestamp(); + invoke("AutosenseCalculation for " + glucoseValue, true); }, fabricPrivacy::logException) ); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/dataBroadcaster/DataBroadcastPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/dataBroadcaster/DataBroadcastPlugin.kt index ac2a5f2392..c6b15b432f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/dataBroadcaster/DataBroadcastPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/dataBroadcaster/DataBroadcastPlugin.kt @@ -8,7 +8,6 @@ import dagger.android.HasAndroidInjector import info.nightscout.androidaps.Config import info.nightscout.androidaps.R import info.nightscout.androidaps.data.IobTotal -import info.nightscout.androidaps.db.BgReading import info.nightscout.androidaps.events.Event import info.nightscout.androidaps.events.EventExtendedBolusChange import info.nightscout.androidaps.events.EventNewBasalProfile @@ -123,13 +122,13 @@ class DataBroadcastPlugin @Inject constructor( } private fun bgStatus(bundle: Bundle) { - val lastBG: BgReading = iobCobCalculatorPlugin.lastBg() ?: return + val lastBG = iobCobCalculatorPlugin.lastBg() ?: return val glucoseStatus = GlucoseStatus(injector).glucoseStatusData ?: return bundle.putDouble("glucoseMgdl", lastBG.value) // last BG in mgdl - bundle.putLong("glucoseTimeStamp", lastBG.date) // timestamp + bundle.putLong("glucoseTimeStamp", lastBG.timestamp) // timestamp bundle.putString("units", profileFunction.getUnits()) // units used in AAPS "mg/dl" or "mmol" - bundle.putString("slopeArrow", lastBG.directionToSymbol(databaseHelper)) // direction arrow as string + bundle.putString("slopeArrow", lastBG.trendArrow.text) // direction arrow as string bundle.putDouble("deltaMgdl", glucoseStatus.delta) // bg delta in mgdl bundle.putDouble("avgDeltaMgdl", glucoseStatus.avgdelta) // average bg delta bundle.putDouble("high", defaultValueHelper.determineHighLine()) // predefined top value of in range (green area) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/MaintenanceFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/MaintenanceFragment.kt index d6cbf22770..708792f836 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/MaintenanceFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/MaintenanceFragment.kt @@ -8,8 +8,11 @@ import android.view.ViewGroup import dagger.android.support.DaggerFragment import info.nightscout.androidaps.MainApp import info.nightscout.androidaps.R +import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.databinding.MaintenanceFragmentBinding +import info.nightscout.androidaps.events.EventNewBG import info.nightscout.androidaps.interfaces.ImportExportPrefsInterface +import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.general.food.FoodPlugin import info.nightscout.androidaps.plugins.general.maintenance.activities.LogSettingActivity import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin @@ -20,11 +23,12 @@ import javax.inject.Inject class MaintenanceFragment : DaggerFragment() { @Inject lateinit var maintenancePlugin: MaintenancePlugin - @Inject lateinit var mainApp: MainApp + @Inject lateinit var rxBus: RxBusWrapper @Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var treatmentsPlugin: TreatmentsPlugin @Inject lateinit var foodPlugin: FoodPlugin @Inject lateinit var importExportPrefs: ImportExportPrefsInterface + @Inject lateinit var repository: AppRepository private var _binding: MaintenanceFragmentBinding? = null @@ -49,6 +53,8 @@ class MaintenanceFragment : DaggerFragment() { // additional service interface and plugin registry foodPlugin.service?.resetFood() treatmentsPlugin.service.resetTreatments() + Thread { repository.clearDatabases() } .start() + rxBus.send(EventNewBG(null)) }) } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/openhumans/OpenHumansUploader.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/openhumans/OpenHumansUploader.kt index 373d3fb327..9a7ee965ab 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/openhumans/OpenHumansUploader.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/openhumans/OpenHumansUploader.kt @@ -16,6 +16,7 @@ import dagger.android.HasAndroidInjector import info.nightscout.androidaps.BuildConfig import info.nightscout.androidaps.MainApp import info.nightscout.androidaps.R +import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.db.* import info.nightscout.androidaps.events.EventPreferenceChange import info.nightscout.androidaps.interfaces.PluginBase @@ -56,7 +57,8 @@ class OpenHumansUploader @Inject constructor( private val sp: SP, private val rxBus: RxBusWrapper, private val context: Context, - private val treatmentsPlugin: TreatmentsPlugin + private val treatmentsPlugin: TreatmentsPlugin, + val repository: AppRepository ) : PluginBase( PluginDescription() .mainType(PluginType.GENERAL) @@ -163,13 +165,13 @@ class OpenHumansUploader @Inject constructor( fun enqueueBGReading(bgReading: BgReading?) = bgReading?.let { insertQueueItem("BgReadings") { - put("date", bgReading.date) - put("isValid", bgReading.isValid) - put("value", bgReading.value) - put("direction", bgReading.direction) - put("raw", bgReading.raw) - put("source", bgReading.source) - put("nsId", bgReading._id) + put("date", bgReading.data.dateCreated) + put("isValid", bgReading.data.isValid) + put("value", bgReading.data.value) + put("direction", bgReading.data.trendArrow) + put("raw", bgReading.data.raw) + put("source", bgReading.data.sourceSensor) + put("nsId", bgReading.data.interfaceIDs.nightscoutId) } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.kt index a9d1c0348a..1c6a8e088a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.kt @@ -56,6 +56,7 @@ import info.nightscout.androidaps.skins.SkinProvider import info.nightscout.androidaps.utils.* import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.buildHelper.BuildHelper +import info.nightscout.androidaps.utils.extensions.directionToIcon import info.nightscout.androidaps.utils.extensions.toVisibility import info.nightscout.androidaps.utils.protection.ProtectionCheck import info.nightscout.androidaps.utils.resources.ResourceHelper @@ -94,6 +95,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList @Inject lateinit var treatmentsPlugin: TreatmentsPlugin @Inject lateinit var iobCobCalculatorPlugin: IobCobCalculatorPlugin @Inject lateinit var dexcomPlugin: DexcomPlugin + @Inject lateinit var dexcomMediator: DexcomPlugin.DexcomMediator @Inject lateinit var xdripPlugin: XdripPlugin @Inject lateinit var notificationStore: NotificationStore @Inject lateinit var actionStringHandler: ActionStringHandler @@ -308,7 +310,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList if (xdripPlugin.isEnabled(PluginType.BGSOURCE)) openCgmApp("com.eveningoutpost.dexdrip") else if (dexcomPlugin.isEnabled(PluginType.BGSOURCE)) { - dexcomPlugin.findDexcomPackageName()?.let { + dexcomMediator.findDexcomPackageName()?.let { openCgmApp(it) } ?: ToastUtils.showToastInUiThread(activity, resourceHelper.gs(R.string.dexcom_app_not_installed)) @@ -320,7 +322,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList CalibrationDialog().show(childFragmentManager, "CalibrationDialog") } else if (dexcomPlugin.isEnabled(PluginType.BGSOURCE)) { try { - dexcomPlugin.findDexcomPackageName()?.let { + dexcomMediator.findDexcomPackageName()?.let { startActivity(Intent("com.dexcom.cgm.activities.MeterEntryActivity").setPackage(it)) } ?: ToastUtils.showToastInUiThread(activity, resourceHelper.gs(R.string.dexcom_app_not_installed)) @@ -575,9 +577,9 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList else -> resourceHelper.gc(R.color.inrange) } - binding.infoLayout.bg.text = lastBG.valueToUnitsToString(units) + binding.infoLayout.bg.text = lastBG.valueToUnitsString(units) binding.infoLayout.bg.setTextColor(color) - binding.infoLayout.arrow.setImageResource(lastBG.directionToIcon(databaseHelper)) + binding.infoLayout.arrow.setImageResource(lastBG.trendArrow.directionToIcon()) binding.infoLayout.arrow.setColorFilter(color) val glucoseStatus = GlucoseStatus(injector).glucoseStatusData @@ -601,8 +603,8 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList } else flag and Paint.STRIKE_THRU_TEXT_FLAG.inv() overview_bg.paintFlags = flag } - binding.infoLayout.timeAgo.text = DateUtil.minAgo(resourceHelper, lastBG.date) - binding.infoLayout.timeAgoShort.text = "(" + DateUtil.minAgoShort(lastBG.date) + ")" + binding.infoLayout.timeAgo.text = DateUtil.minAgo(resourceHelper, lastBG.timestamp) + binding.infoLayout.timeAgoShort.text = "(" + DateUtil.minAgoShort(lastBG.timestamp) + ")" } val closedLoopEnabled = constraintChecker.isClosedLoopAllowed() diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/graphData/GraphData.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/graphData/GraphData.kt index e5d0ff4fab..4ad6118c61 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/graphData/GraphData.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/graphData/GraphData.kt @@ -27,6 +27,7 @@ import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin import info.nightscout.androidaps.utils.DecimalFormatter import info.nightscout.androidaps.utils.Round +import info.nightscout.androidaps.utils.convertToBGReadings import info.nightscout.androidaps.utils.resources.ResourceHelper import java.util.* import javax.inject.Inject @@ -35,7 +36,7 @@ import kotlin.math.max import kotlin.math.min class GraphData( - injector: HasAndroidInjector, + private val injector: HasAndroidInjector, private val graph: GraphView, private val iobCobCalculatorPlugin: IobCobCalculatorPlugin, private val treatmentsPlugin: TreatmentsInterface @@ -62,7 +63,7 @@ class GraphData( @Suppress("UNUSED_PARAMETER") fun addBgReadings(fromTime: Long, toTime: Long, lowLine: Double, highLine: Double, predictions: MutableList?) { var maxBgValue = Double.MIN_VALUE - bgReadingsArray = iobCobCalculatorPlugin.bgReadings + bgReadingsArray = iobCobCalculatorPlugin.bgReadings?.convertToBGReadings(injector) if (bgReadingsArray?.isEmpty() != false) { aapsLogger.debug("No BG data.") maxY = 10.0 @@ -71,13 +72,13 @@ class GraphData( } val bgListArray: MutableList = ArrayList() for (bg in bgReadingsArray!!) { - if (bg.date < fromTime || bg.date > toTime) continue - if (bg.value > maxBgValue) maxBgValue = bg.value + if (bg.data.timestamp < fromTime || bg.data.timestamp > toTime) continue + if (bg.data.value > maxBgValue) maxBgValue = bg.data.value bgListArray.add(bg) } if (predictions != null) { predictions.sortWith(Comparator { o1: BgReading, o2: BgReading -> o1.x.compareTo(o2.x) }) - for (prediction in predictions) if (prediction.value >= 40) bgListArray.add(prediction) + for (prediction in predictions) if (prediction.data.value >= 40) bgListArray.add(prediction) } maxBgValue = Profile.fromMgdlToUnits(maxBgValue, units) maxBgValue = addUpperChartMargin(maxBgValue) @@ -282,10 +283,10 @@ class GraphData( bgReadingsArray?.let { bgReadingsArray -> for (r in bgReadingsArray.indices) { val reading = bgReadingsArray[r] - if (reading.date > date) continue - return Profile.fromMgdlToUnits(reading.value, units) + if (reading.data.timestamp > date) continue + return Profile.fromMgdlToUnits(reading.data.value, units) } - return if (bgReadingsArray.isNotEmpty()) Profile.fromMgdlToUnits(bgReadingsArray[0].value, units) else Profile.fromMgdlToUnits(100.0, units) + return if (bgReadingsArray.isNotEmpty()) Profile.fromMgdlToUnits(bgReadingsArray[0].data.value, units) else Profile.fromMgdlToUnits(100.0, units) } ?: return Profile.fromMgdlToUnits(100.0, units) } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/persistentNotification/PersistentNotificationPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/persistentNotification/PersistentNotificationPlugin.kt index 96fbefbc65..af7813dba8 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/persistentNotification/PersistentNotificationPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/persistentNotification/PersistentNotificationPlugin.kt @@ -25,6 +25,7 @@ import info.nightscout.androidaps.utils.androidNotification.openAppIntent import info.nightscout.androidaps.utils.resources.IconsProvider import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.rx.AapsSchedulers +import info.nightscout.androidaps.utils.valueToUnitsString import io.reactivex.disposables.CompositeDisposable import javax.inject.Inject import javax.inject.Singleton @@ -135,12 +136,12 @@ class PersistentNotificationPlugin @Inject constructor( val lastBG = iobCobCalculatorPlugin.lastBg() val glucoseStatus = GlucoseStatus(injector).glucoseStatusData if (lastBG != null) { - line1aa = lastBG.valueToUnitsToString(units) + line1aa = lastBG.valueToUnitsString(units) line1 = line1aa if (glucoseStatus != null) { line1 += (" Δ" + Profile.toSignedUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units) + " avgΔ" + Profile.toSignedUnitsString(glucoseStatus.avgdelta, glucoseStatus.avgdelta * Constants.MGDL_TO_MMOLL, units)) - line1aa += " " + lastBG.directionToSymbol(databaseHelper) + line1aa += " " + lastBG.trendArrow.symbol } else { line1 += " " + resourceHelper.gs(R.string.old_data) + diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPlugin.kt index 7bf5fb22c5..b752c7ceab 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPlugin.kt @@ -305,11 +305,11 @@ class SmsCommunicatorPlugin @Inject constructor( var reply = "" val units = profileFunction.getUnits() if (actualBG != null) { - reply = resourceHelper.gs(R.string.sms_actualbg) + " " + actualBG.valueToUnitsToString(units) + ", " + reply = resourceHelper.gs(R.string.sms_actualbg) + " " + actualBG.valueToUnitsString(units) + ", " } else if (lastBG != null) { - val agoMsec = System.currentTimeMillis() - lastBG.date + val agoMsec = System.currentTimeMillis() - lastBG.timestamp val agoMin = (agoMsec / 60.0 / 1000.0).toInt() - reply = resourceHelper.gs(R.string.sms_lastbg) + " " + lastBG.valueToUnitsToString(units) + " " + String.format(resourceHelper.gs(R.string.sms_minago), agoMin) + ", " + reply = resourceHelper.gs(R.string.sms_lastbg) + " " + lastBG.valueToUnitsString(units) + " " + String.format(resourceHelper.gs(R.string.sms_minago), agoMin) + ", " } val glucoseStatus = GlucoseStatus(injector).glucoseStatusData if (glucoseStatus != null) reply += resourceHelper.gs(R.string.sms_delta) + " " + Profile.toUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units) + " " + units + ", " diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/TidepoolPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/TidepoolPlugin.kt index 5492f801a5..c3b6573060 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/TidepoolPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/TidepoolPlugin.kt @@ -93,11 +93,11 @@ class TidepoolPlugin @Inject constructor( disposable += rxBus .toObservable(EventNewBG::class.java) .observeOn(aapsSchedulers.io) - .filter { it.bgReading != null } // better would be optional in API level >24 - .map { it.bgReading } + .filter { it.glucoseValue != null } // better would be optional in API level >24 + .map { it.glucoseValue } .subscribe({ bgReading -> - if (bgReading!!.date < uploadChunk.getLastEnd()) - uploadChunk.setLastEnd(bgReading.date) + if (bgReading!!.timestamp < uploadChunk.getLastEnd()) + uploadChunk.setLastEnd(bgReading.timestamp ) if (isEnabled(PluginType.GENERAL) && (!sp.getBoolean(R.string.key_tidepool_only_while_charging, false) || receiverStatusStore.isCharging) && (!sp.getBoolean(R.string.key_tidepool_only_while_unmetered, false) || receiverStatusStore.isWifiConnected) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/comm/UploadChunk.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/comm/UploadChunk.kt index 4062f27bd0..0df39ad822 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/comm/UploadChunk.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/comm/UploadChunk.kt @@ -1,8 +1,10 @@ package info.nightscout.androidaps.plugins.general.tidepool.comm +import dagger.android.HasAndroidInjector import info.nightscout.androidaps.MainApp import info.nightscout.androidaps.R import info.nightscout.androidaps.data.Intervals +import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.db.ProfileSwitch import info.nightscout.androidaps.db.TemporaryBasal import info.nightscout.androidaps.interfaces.ActivePluginProvider @@ -16,6 +18,7 @@ import info.nightscout.androidaps.plugins.general.tidepool.utils.GsonInstance import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.T +import info.nightscout.androidaps.utils.convertToBGReadings import info.nightscout.androidaps.utils.sharedPreferences.SP import java.util.* import javax.inject.Inject @@ -24,12 +27,14 @@ import kotlin.math.max @Singleton class UploadChunk @Inject constructor( + private val injector: HasAndroidInjector, private val sp: SP, private val rxBus: RxBusWrapper, private val aapsLogger: AAPSLogger, private val profileFunction: ProfileFunction, private val treatmentsPlugin: TreatmentsPlugin, private val activePlugin: ActivePluginProvider, + private val repository: AppRepository, private val dateUtil: DateUtil ) { @@ -102,9 +107,11 @@ class UploadChunk @Inject constructor( val start: Long = 0 val end = DateUtil.now() - val bgReadingList = MainApp.getDbHelper().getBgreadingsDataFromTime(start, end, true) - return if (bgReadingList.size > 0) - bgReadingList[0].date + val bgReadingList = repository.compatGetBgReadingsDataFromTime(start, end, true) + .blockingGet() + .convertToBGReadings(injector) + return if (bgReadingList.isNotEmpty()) + bgReadingList[0].data.timestamp else -1 } @@ -131,7 +138,9 @@ class UploadChunk @Inject constructor( } private fun getBgReadings(start: Long, end: Long): List { - val readings = MainApp.getDbHelper().getBgreadingsDataFromTime(start, end, true) + val readings = repository.compatGetBgReadingsDataFromTime(start, end, true) + .blockingGet() + .convertToBGReadings(injector) val selection = SensorGlucoseElement.fromBgReadings(readings) if (selection.isNotEmpty()) rxBus.send(EventTidepoolStatus("${selection.size} CGMs selected for upload")) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/elements/SensorGlucoseElement.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/elements/SensorGlucoseElement.kt index ca2aceca1c..7573db1a82 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/elements/SensorGlucoseElement.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/elements/SensorGlucoseElement.kt @@ -5,7 +5,7 @@ import info.nightscout.androidaps.db.BgReading import java.util.* class SensorGlucoseElement(bgReading: BgReading) - : BaseElement(bgReading.date, UUID.nameUUIDFromBytes(("AAPS-cgm" + bgReading.date).toByteArray()).toString()) { + : BaseElement(bgReading.data.timestamp, UUID.nameUUIDFromBytes(("AAPS-cgm" + bgReading.data.timestamp).toByteArray()).toString()) { @Expose internal var units: String = "mg/dL" @@ -14,7 +14,7 @@ class SensorGlucoseElement(bgReading: BgReading) init { this.type = "cbg" - value = bgReading.value.toInt() + value = bgReading.data.value.toInt() } companion object { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/ActionStringHandler.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/ActionStringHandler.kt index 53a9cd8e85..667541c99b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/ActionStringHandler.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/ActionStringHandler.kt @@ -31,11 +31,7 @@ import info.nightscout.androidaps.danaRv2.DanaRv2Plugin import info.nightscout.androidaps.plugins.pump.insight.LocalInsightPlugin import info.nightscout.androidaps.plugins.treatments.CarbsGenerator import info.nightscout.androidaps.queue.Callback -import info.nightscout.androidaps.utils.DateUtil -import info.nightscout.androidaps.utils.DecimalFormatter -import info.nightscout.androidaps.utils.HardLimits -import info.nightscout.androidaps.utils.SafeParse -import info.nightscout.androidaps.utils.ToastUtils +import info.nightscout.androidaps.utils.* import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.wizard.BolusWizard diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/wearintegration/WatchUpdaterService.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/wearintegration/WatchUpdaterService.java index e85952c4fc..5b06f122d4 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/wearintegration/WatchUpdaterService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/wearintegration/WatchUpdaterService.java @@ -31,32 +31,33 @@ import dagger.android.AndroidInjection; import dagger.android.HasAndroidInjector; 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.IobTotal; import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.database.AppRepository; +import info.nightscout.androidaps.database.entities.GlucoseValue; import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.db.TemporaryBasal; +import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.interfaces.ActivePluginProvider; import info.nightscout.androidaps.interfaces.PluginType; +import info.nightscout.androidaps.interfaces.ProfileFunction; import info.nightscout.androidaps.logging.AAPSLogger; import info.nightscout.androidaps.logging.LTag; import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin; -import info.nightscout.androidaps.interfaces.ProfileFunction; import info.nightscout.androidaps.plugins.general.nsclient.data.NSDeviceStatus; import info.nightscout.androidaps.plugins.general.wear.ActionStringHandler; import info.nightscout.androidaps.plugins.general.wear.WearPlugin; import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus; import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin; -import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; import info.nightscout.androidaps.receivers.ReceiverStatusStore; import info.nightscout.androidaps.utils.DecimalFormatter; import info.nightscout.androidaps.utils.DefaultValueHelper; +import info.nightscout.androidaps.utils.GlucoseValueUtilsKt; import info.nightscout.androidaps.utils.ToastUtils; import info.nightscout.androidaps.utils.resources.ResourceHelper; import info.nightscout.androidaps.utils.sharedPreferences.SP; -import kotlin.Suppress; public class WatchUpdaterService extends WearableListenerService implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener { @Inject public HasAndroidInjector injector; @@ -72,6 +73,7 @@ public class WatchUpdaterService extends WearableListenerService implements Goog @Inject public IobCobCalculatorPlugin iobCobCalculatorPlugin; @Inject public TreatmentsPlugin treatmentsPlugin; @Inject public ActionStringHandler actionStringHandler; + @Inject public AppRepository repository; @Inject ReceiverStatusStore receiverStatusStore; @Inject Config config; @@ -275,7 +277,7 @@ public class WatchUpdaterService extends WearableListenerService implements Goog private void sendData() { - BgReading lastBG = iobCobCalculatorPlugin.lastBg(); + GlucoseValue lastBG = iobCobCalculatorPlugin.lastBg(); // Log.d(TAG, logPrefix + "LastBg=" + lastBG); if (lastBG != null) { GlucoseStatus glucoseStatus = new GlucoseStatus(injector).getGlucoseStatusData(); @@ -297,25 +299,25 @@ public class WatchUpdaterService extends WearableListenerService implements Goog } - private DataMap dataMapSingleBG(BgReading lastBG, GlucoseStatus glucoseStatus) { + private DataMap dataMapSingleBG(GlucoseValue lastBG, GlucoseStatus glucoseStatus) { String units = profileFunction.getUnits(); double convert2MGDL = 1.0; if (units.equals(Constants.MMOL)) convert2MGDL = Constants.MMOLL_TO_MGDL; - double lowLine = defaultValueHelper.determineLowLine()*convert2MGDL; - double highLine = defaultValueHelper.determineHighLine()*convert2MGDL; + double lowLine = defaultValueHelper.determineLowLine() * convert2MGDL; + double highLine = defaultValueHelper.determineHighLine() * convert2MGDL; long sgvLevel = 0L; - if (lastBG.value > highLine) { + if (lastBG.getValue() > highLine) { sgvLevel = 1; - } else if (lastBG.value < lowLine) { + } else if (lastBG.getValue() < lowLine) { sgvLevel = -1; } DataMap dataMap = new DataMap(); - dataMap.putString("sgvString", lastBG.valueToUnitsToString(units)); + dataMap.putString("sgvString", GlucoseValueUtilsKt.valueToUnitsString(lastBG, units)); dataMap.putString("glucoseUnits", units); - dataMap.putLong("timestamp", lastBG.date); + dataMap.putLong("timestamp", lastBG.getTimestamp()); if (glucoseStatus == null) { dataMap.putString("slopeArrow", ""); dataMap.putString("delta", "--"); @@ -326,7 +328,7 @@ public class WatchUpdaterService extends WearableListenerService implements Goog dataMap.putString("avgDelta", deltastring(glucoseStatus.avgdelta, glucoseStatus.avgdelta * Constants.MGDL_TO_MMOLL, units)); } dataMap.putLong("sgvLevel", sgvLevel); - dataMap.putDouble("sgvDouble", lastBG.value); + dataMap.putDouble("sgvDouble", lastBG.getValue()); dataMap.putDouble("high", highLine); dataMap.putDouble("low", lowLine); return dataMap; @@ -381,11 +383,11 @@ public class WatchUpdaterService extends WearableListenerService implements Goog googleApiConnect(); } long startTime = System.currentTimeMillis() - (long) (60000 * 60 * 5.5); - BgReading last_bg = iobCobCalculatorPlugin.lastBg(); + GlucoseValue last_bg = iobCobCalculatorPlugin.lastBg(); if (last_bg == null) return; - List graph_bgs = MainApp.getDbHelper().getBgreadingsDataFromTime(startTime, true); + List graph_bgs = repository.compatGetBgReadingsDataFromTime(startTime, true).blockingGet(); GlucoseStatus glucoseStatus = new GlucoseStatus(injector).getGlucoseStatusData(true); if (!graph_bgs.isEmpty()) { @@ -395,7 +397,7 @@ public class WatchUpdaterService extends WearableListenerService implements Goog return; } final ArrayList dataMaps = new ArrayList<>(graph_bgs.size()); - for (BgReading bg : graph_bgs) { + for (GlucoseValue bg : graph_bgs) { DataMap dataMap = dataMapSingleBG(bg, glucoseStatus); if (dataMap != null) { dataMaps.add(dataMap); @@ -541,8 +543,8 @@ public class WatchUpdaterService extends WearableListenerService implements Goog if (!predArray.isEmpty()) { final String units = profileFunction.getUnits(); for (BgReading bg : predArray) { - if (bg.value < 40) continue; - predictions.add(predictionMap(bg.date, bg.value, bg.getPredectionColor())); + if (bg.getValue() < 40) continue; + predictions.add(predictionMap(bg.getDate(), bg.getValue(), bg.getPredictionColor())); } } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/GlucoseStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/GlucoseStatus.java index 1e84ad3c66..22420fc0ce 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/GlucoseStatus.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/GlucoseStatus.java @@ -8,6 +8,7 @@ import java.util.List; import javax.inject.Inject; import dagger.android.HasAndroidInjector; +import info.nightscout.androidaps.database.entities.GlucoseValue; import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.logging.AAPSLogger; import info.nightscout.androidaps.logging.LTag; @@ -71,7 +72,7 @@ public class GlucoseStatus { synchronized (iobCobCalculatorPlugin.getDataLock()) { - List data = iobCobCalculatorPlugin.getBgReadings(); + List data = iobCobCalculatorPlugin.getBgReadings(); if (data == null) { aapsLogger.debug(LTag.GLUCOSE, "data=null"); @@ -84,18 +85,18 @@ public class GlucoseStatus { return null; } - if (data.get(0).date < DateUtil.now() - 7 * 60 * 1000L && !allowOldData) { + if (data.get(0).getTimestamp() < DateUtil.now() - 7 * 60 * 1000L && !allowOldData) { aapsLogger.debug(LTag.GLUCOSE, "olddata"); return null; } - BgReading now = data.get(0); - long now_date = now.date; + GlucoseValue now = data.get(0); + long now_date = now.getTimestamp(); double change; if (sizeRecords == 1) { GlucoseStatus status = new GlucoseStatus(injector); - status.glucose = now.value; + status.glucose = now.getValue(); status.noise = 0d; status.short_avgdelta = 0d; status.delta = 0d; @@ -112,18 +113,18 @@ public class GlucoseStatus { ArrayList long_deltas = new ArrayList<>(); // Use the latest sgv value in the now calculations - now_value_list.add(now.value); + now_value_list.add(now.getValue()); for (int i = 1; i < sizeRecords; i++) { - if (data.get(i).value > 38) { - BgReading then = data.get(i); - long then_date = then.date; + if (data.get(i).getValue() > 38) { + GlucoseValue then = data.get(i); + long then_date = then.getTimestamp(); double avgdelta; long minutesago; minutesago = Math.round((now_date - then_date) / (1000d * 60)); // multiply by 5 to get the same units as delta, i.e. mg/dL/5m - change = now.value - then.value; + change = now.getValue() - then.getValue(); avgdelta = change / minutesago * 5; aapsLogger.debug(LTag.GLUCOSE, then.toString() + " minutesago=" + minutesago + " avgdelta=" + avgdelta); @@ -131,8 +132,8 @@ public class GlucoseStatus { // use the average of all data points in the last 2.5m for all further "now" calculations if (0 < minutesago && minutesago < 2.5) { // Keep and average all values within the last 2.5 minutes - now_value_list.add(then.value); - now.value = average(now_value_list); + now_value_list.add(then.getValue()); + now.setValue(average(now_value_list)); // short_deltas are calculated from everything ~5-15 minutes ago } else if (2.5 < minutesago && minutesago < 17.5) { //console.error(minutesago, avgdelta); @@ -152,7 +153,7 @@ public class GlucoseStatus { } GlucoseStatus status = new GlucoseStatus(injector); - status.glucose = now.value; + status.glucose = now.getValue(); status.date = now_date; status.noise = 0d; //for now set to nothing as not all CGMs report noise diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/InMemoryGlucoseValue.kt b/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/InMemoryGlucoseValue.kt index 497117764e..52cd403f54 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/InMemoryGlucoseValue.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/InMemoryGlucoseValue.kt @@ -1,9 +1,9 @@ package info.nightscout.androidaps.plugins.iob.iobCobCalculator -import info.nightscout.androidaps.db.BgReading +import info.nightscout.androidaps.database.entities.GlucoseValue -class InMemoryGlucoseValue @JvmOverloads constructor(var timestamp: Long = 0L, var value: Double = 0.0, var interpolated : Boolean = false) { +class InMemoryGlucoseValue @JvmOverloads constructor(var timestamp: Long = 0L, var value: Double = 0.0, var interpolated: Boolean = false) { - constructor(gv: BgReading) : this(gv.date, gv.value) + constructor(gv: GlucoseValue) : this(gv.timestamp, gv.value) // var generated : value doesn't correspond to real value with timestamp close to real BG } \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/IobCobCalculatorPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/IobCobCalculatorPlugin.java index e8f4ab6249..430147e9ed 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/IobCobCalculatorPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/IobCobCalculatorPlugin.java @@ -10,6 +10,7 @@ import org.json.JSONArray; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.TimeUnit; import javax.inject.Inject; import javax.inject.Singleton; @@ -21,6 +22,8 @@ import info.nightscout.androidaps.R; import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.MealData; import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.database.AppRepository; +import info.nightscout.androidaps.database.entities.GlucoseValue; import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.db.Treatment; @@ -72,6 +75,7 @@ public class IobCobCalculatorPlugin extends PluginBase implements IobCobCalculat private final SensitivityWeightedAveragePlugin sensitivityWeightedAveragePlugin; private final FabricPrivacy fabricPrivacy; private final DateUtil dateUtil; + private final AppRepository repository; private final CompositeDisposable disposable = new CompositeDisposable(); @@ -80,14 +84,14 @@ public class IobCobCalculatorPlugin extends PluginBase implements IobCobCalculat private LongSparseArray autosensDataTable = new LongSparseArray<>(); // oldest at index 0 private LongSparseArray basalDataTable = new LongSparseArray<>(); // oldest at index 0 + private volatile List bgReadings = null; // newest at index 0 + private volatile List bucketed_data = null; + // we need to make sure that bucketed_data will always have the same timestamp for correct use of cached values // once referenceTime != null all bucketed data should be (x * 5min) from referenceTime Long referenceTime = null; private Boolean lastUsed5minCalculation = null; // true if used 5min bucketed data - private volatile List bgReadings = null; // newest at index 0 - private volatile List bucketed_data = null; - private final Object dataLock = new Object(); boolean stopCalculationTrigger = false; @@ -108,7 +112,8 @@ public class IobCobCalculatorPlugin extends PluginBase implements IobCobCalculat SensitivityAAPSPlugin sensitivityAAPSPlugin, SensitivityWeightedAveragePlugin sensitivityWeightedAveragePlugin, FabricPrivacy fabricPrivacy, - DateUtil dateUtil + DateUtil dateUtil, + AppRepository repository ) { super(new PluginDescription() .mainType(PluginType.GENERAL) @@ -131,6 +136,7 @@ public class IobCobCalculatorPlugin extends PluginBase implements IobCobCalculat this.sensitivityWeightedAveragePlugin = sensitivityWeightedAveragePlugin; this.fabricPrivacy = fabricPrivacy; this.dateUtil = dateUtil; + this.repository = repository; } @Override @@ -169,6 +175,7 @@ public class IobCobCalculatorPlugin extends PluginBase implements IobCobCalculat disposable.add(rxBus .toObservable(EventNewBG.class) .observeOn(aapsSchedulers.getIo()) + .debounce(1L, TimeUnit.SECONDS) .subscribe(event -> { stopCalculation("onEventNewBG"); runCalculation("onEventNewBG", System.currentTimeMillis(), true, true, event); @@ -227,11 +234,11 @@ public class IobCobCalculatorPlugin extends PluginBase implements IobCobCalculat return autosensDataTable; } - public List getBgReadings() { + public List getBgReadings() { return bgReadings; } - public void setBgReadings(List bgReadings) { + public void setBgReadings(List bgReadings) { this.bgReadings = bgReadings; } @@ -272,10 +279,10 @@ public class IobCobCalculatorPlugin extends PluginBase implements IobCobCalculat if (DateUtil.isCloseToNow(to)) { // if close to now expect there can be some readings with time in close future (caused by wrong time setting) // so read all records - bgReadings = MainApp.getDbHelper().getBgreadingsDataFromTime(start, false); + bgReadings = repository.compatGetBgReadingsDataFromTime(start, false).blockingGet(); getAapsLogger().debug(LTag.AUTOSENS, "BG data loaded. Size: " + bgReadings.size() + " Start date: " + dateUtil.dateAndTimeString(start)); } else { - bgReadings = MainApp.getDbHelper().getBgreadingsDataFromTime(start, to, false); + bgReadings = repository.compatGetBgReadingsDataFromTime(start, to, false).blockingGet(); getAapsLogger().debug(LTag.AUTOSENS, "BG data loaded. Size: " + bgReadings.size() + " Start date: " + dateUtil.dateAndTimeString(start) + " End date: " + dateUtil.dateAndTimeString(to)); } } @@ -287,8 +294,8 @@ public class IobCobCalculatorPlugin extends PluginBase implements IobCobCalculat } long totalDiff = 0; for (int i = 1; i < bgReadings.size(); ++i) { - long bgTime = bgReadings.get(i).date; - long lastbgTime = bgReadings.get(i - 1).date; + long bgTime = bgReadings.get(i).getTimestamp(); + long lastbgTime = bgReadings.get(i - 1).getTimestamp(); long diff = lastbgTime - bgTime; diff %= T.mins(5).msecs(); if (diff > T.mins(2).plus(T.secs(30)).msecs()) @@ -331,27 +338,27 @@ public class IobCobCalculatorPlugin extends PluginBase implements IobCobCalculat } @Nullable - public BgReading findNewer(long time) { - BgReading lastFound = bgReadings.get(0); - if (lastFound.date < time) return null; + public GlucoseValue findNewer(long time) { + GlucoseValue lastFound = bgReadings.get(0); + if (lastFound.getTimestamp() < time) return null; for (int i = 1; i < bgReadings.size(); ++i) { - if (bgReadings.get(i).date == time) return bgReadings.get(i); - if (bgReadings.get(i).date > time) continue; + if (bgReadings.get(i).getTimestamp() == time) return bgReadings.get(i); + if (bgReadings.get(i).getTimestamp() > time) continue; lastFound = bgReadings.get(i - 1); - if (bgReadings.get(i).date < time) break; + if (bgReadings.get(i).getTimestamp() < time) break; } return lastFound; } @Nullable - public BgReading findOlder(long time) { - BgReading lastFound = bgReadings.get(bgReadings.size() - 1); - if (lastFound.date > time) return null; + public GlucoseValue findOlder(long time) { + GlucoseValue lastFound = bgReadings.get(bgReadings.size() - 1); + if (lastFound.getTimestamp() > time) return null; for (int i = bgReadings.size() - 2; i >= 0; --i) { - if (bgReadings.get(i).date == time) return bgReadings.get(i); - if (bgReadings.get(i).date < time) continue; + if (bgReadings.get(i).getTimestamp() == time) return bgReadings.get(i); + if (bgReadings.get(i).getTimestamp() < time) continue; lastFound = bgReadings.get(i + 1); - if (bgReadings.get(i).date > time) break; + if (bgReadings.get(i).getTimestamp() > time) break; } return lastFound; } @@ -363,25 +370,25 @@ public class IobCobCalculatorPlugin extends PluginBase implements IobCobCalculat } bucketed_data = new ArrayList<>(); - long currentTime = bgReadings.get(0).date - bgReadings.get(0).date % T.mins(5).msecs(); + long currentTime = bgReadings.get(0).getTimestamp() - bgReadings.get(0).getTimestamp() % T.mins(5).msecs(); currentTime = adjustToReferenceTime(currentTime); getAapsLogger().debug("Adjusted time " + dateUtil.dateAndTimeAndSecondsString(currentTime)); //log.debug("First reading: " + new Date(currentTime).toLocaleString()); while (true) { // test if current value is older than current time - BgReading newer = findNewer(currentTime); - BgReading older = findOlder(currentTime); + GlucoseValue newer = findNewer(currentTime); + GlucoseValue older = findOlder(currentTime); if (newer == null || older == null) break; - if (older.date == newer.date) { // direct hit + if (older.getTimestamp() == newer.getTimestamp()) { // direct hit bucketed_data.add(new InMemoryGlucoseValue(newer)); } else { - double bgDelta = newer.value - older.value; - long timeDiffToNew = newer.date - currentTime; + double bgDelta = newer.getTimestamp() - older.getTimestamp(); + long timeDiffToNew = newer.getTimestamp() - currentTime; - double currentBg = newer.value - (double) timeDiffToNew / (newer.date - older.date) * bgDelta; + double currentBg = newer.getValue() - (double) timeDiffToNew / (newer.getTimestamp() - older.getTimestamp()) * bgDelta; InMemoryGlucoseValue newBgreading = new InMemoryGlucoseValue(currentTime, Math.round(currentBg), true); bucketed_data.add(newBgreading); //log.debug("BG: " + newBgreading.value + " (" + new Date(newBgreading.date).toLocaleString() + ") Prev: " + older.value + " (" + new Date(older.date).toLocaleString() + ") Newer: " + newer.value + " (" + new Date(newer.date).toLocaleString() + ")"); @@ -400,27 +407,27 @@ public class IobCobCalculatorPlugin extends PluginBase implements IobCobCalculat bucketed_data = new ArrayList<>(); bucketed_data.add(new InMemoryGlucoseValue(bgReadings.get(0))); - getAapsLogger().debug(LTag.AUTOSENS, "Adding. bgTime: " + DateUtil.toISOString(bgReadings.get(0).date) + " lastbgTime: " + "none-first-value" + " " + bgReadings.get(0).toString()); + getAapsLogger().debug(LTag.AUTOSENS, "Adding. bgTime: " + DateUtil.toISOString(bgReadings.get(0).getTimestamp()) + " lastbgTime: " + "none-first-value" + " " + bgReadings.get(0).toString()); int j = 0; for (int i = 1; i < bgReadings.size(); ++i) { - long bgTime = bgReadings.get(i).date; - long lastbgTime = bgReadings.get(i - 1).date; + long bgTime = bgReadings.get(i).getTimestamp(); + long lastbgTime = bgReadings.get(i - 1).getTimestamp(); //log.error("Processing " + i + ": " + new Date(bgTime).toString() + " " + bgReadings.get(i).value + " Previous: " + new Date(lastbgTime).toString() + " " + bgReadings.get(i - 1).value); - if (bgReadings.get(i).value < 39 || bgReadings.get(i - 1).value < 39) { + if (bgReadings.get(i).getValue() < 39 || bgReadings.get(i - 1).getValue() < 39) { throw new IllegalStateException("<39"); } long elapsed_minutes = (bgTime - lastbgTime) / (60 * 1000); if (Math.abs(elapsed_minutes) > 8) { // interpolate missing data points - double lastbg = bgReadings.get(i - 1).value; + double lastbg = bgReadings.get(i - 1).getValue(); elapsed_minutes = Math.abs(elapsed_minutes); //console.error(elapsed_minutes); long nextbgTime; while (elapsed_minutes > 5) { nextbgTime = lastbgTime - 5 * 60 * 1000; j++; - double gapDelta = bgReadings.get(i).value - lastbg; + double gapDelta = bgReadings.get(i).getValue() - lastbg; //console.error(gapDelta, lastbg, elapsed_minutes); double nextbg = lastbg + (5d / elapsed_minutes * gapDelta); InMemoryGlucoseValue newBgreading = new InMemoryGlucoseValue(nextbgTime, Math.round(nextbg), true); @@ -433,16 +440,16 @@ public class IobCobCalculatorPlugin extends PluginBase implements IobCobCalculat lastbgTime = nextbgTime; } j++; - InMemoryGlucoseValue newBgreading = new InMemoryGlucoseValue(bgTime, bgReadings.get(i).value); + InMemoryGlucoseValue newBgreading = new InMemoryGlucoseValue(bgTime, bgReadings.get(i).getValue()); bucketed_data.add(newBgreading); getAapsLogger().debug(LTag.AUTOSENS, "Adding. bgTime: " + DateUtil.toISOString(bgTime) + " lastbgTime: " + DateUtil.toISOString(lastbgTime) + " " + newBgreading.toString()); } else if (Math.abs(elapsed_minutes) > 2) { j++; - InMemoryGlucoseValue newBgreading = new InMemoryGlucoseValue(bgTime, bgReadings.get(i).value); + InMemoryGlucoseValue newBgreading = new InMemoryGlucoseValue(bgTime, bgReadings.get(i).getValue()); bucketed_data.add(newBgreading); getAapsLogger().debug(LTag.AUTOSENS, "Adding. bgTime: " + DateUtil.toISOString(bgTime) + " lastbgTime: " + DateUtil.toISOString(lastbgTime) + " " + newBgreading.toString()); } else { - bucketed_data.get(j).setValue((bucketed_data.get(j).getValue() + bgReadings.get(i).value) / 2); + bucketed_data.get(j).setValue((bucketed_data.get(j).getValue() + bgReadings.get(i).getValue()) / 2); //log.error("***** Average"); } } @@ -914,14 +921,14 @@ public class IobCobCalculatorPlugin extends PluginBase implements IobCobCalculat * Return last BgReading from database or null if db is empty */ @Nullable - public BgReading lastBg() { - List bgList = getBgReadings(); + public GlucoseValue lastBg() { + List bgList = getBgReadings(); if (bgList == null) return null; for (int i = 0; i < bgList.size(); i++) - if (bgList.get(i).value >= 39) + if (bgList.get(i).getValue() >= 39) return bgList.get(i); return null; } @@ -931,13 +938,13 @@ public class IobCobCalculatorPlugin extends PluginBase implements IobCobCalculat * or null if older */ @Nullable - public BgReading actualBg() { - BgReading lastBg = lastBg(); + public GlucoseValue actualBg() { + GlucoseValue lastBg = lastBg(); if (lastBg == null) return null; - if (lastBg.date > System.currentTimeMillis() - 9 * 60 * 1000) + if (lastBg.getTimestamp() > System.currentTimeMillis() - 9 * 60 * 1000) return lastBg; return null; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/BGSourceFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/BGSourceFragment.kt index 3c9f8ffef7..0c3193a45d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/BGSourceFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/BGSourceFragment.kt @@ -5,32 +5,28 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import dagger.android.support.DaggerFragment -import info.nightscout.androidaps.MainApp import info.nightscout.androidaps.R +import info.nightscout.androidaps.database.AppRepository +import info.nightscout.androidaps.database.entities.GlucoseValue +import info.nightscout.androidaps.database.transactions.InvalidateGlucoseValueTransaction import info.nightscout.androidaps.databinding.BgsourceFragmentBinding import info.nightscout.androidaps.databinding.BgsourceItemBinding -import info.nightscout.androidaps.db.BgReading import info.nightscout.androidaps.events.EventNewBG import info.nightscout.androidaps.interfaces.DatabaseHelperInterface import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.plugins.bus.RxBusWrapper -import info.nightscout.androidaps.plugins.general.nsclient.NSUpload -import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventNewHistoryBgData -import info.nightscout.androidaps.plugins.source.BGSourceFragment.RecyclerViewAdapter.BgReadingsViewHolder -import info.nightscout.androidaps.utils.DateUtil -import info.nightscout.androidaps.utils.FabricPrivacy -import info.nightscout.androidaps.utils.ListDiffCallback -import info.nightscout.androidaps.utils.ListUpdateCallbackHelper -import info.nightscout.androidaps.utils.T +import info.nightscout.androidaps.utils.* import info.nightscout.androidaps.utils.alertDialogs.OKDialog +import info.nightscout.androidaps.utils.extensions.directionToIcon import info.nightscout.androidaps.utils.extensions.toVisibility import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.rx.AapsSchedulers import io.reactivex.disposables.CompositeDisposable +import io.reactivex.rxkotlin.plusAssign +import java.util.concurrent.TimeUnit import javax.inject.Inject class BGSourceFragment : DaggerFragment() { @@ -41,6 +37,7 @@ class BGSourceFragment : DaggerFragment() { @Inject lateinit var profileFunction: ProfileFunction @Inject lateinit var dateUtil: DateUtil @Inject lateinit var databaseHelper: DatabaseHelperInterface + @Inject lateinit var repository: AppRepository @Inject lateinit var aapsSchedulers: AapsSchedulers private val disposable = CompositeDisposable() @@ -60,24 +57,27 @@ class BGSourceFragment : DaggerFragment() { binding.recyclerview.setHasFixedSize(true) binding.recyclerview.layoutManager = LinearLayoutManager(view.context) - val now = System.currentTimeMillis() - binding.recyclerview.adapter = RecyclerViewAdapter(getBgData(now)) } @Synchronized override fun onResume() { super.onResume() - disposable.add(rxBus + val now = System.currentTimeMillis() + disposable += repository + .compatGetBgReadingsDataFromTime(now - millsToThePast, false) + .observeOn(aapsSchedulers.main) + .subscribe { list -> binding.recyclerview.adapter = RecyclerViewAdapter(list) } + + disposable += rxBus .toObservable(EventNewBG::class.java) - .observeOn(aapsSchedulers.main) - .subscribe({ updateGUI() }, fabricPrivacy::logException) - ) - disposable.add(rxBus - .toObservable(EventNewHistoryBgData::class.java) - .observeOn(aapsSchedulers.main) - .subscribe({ updateGUI() }, fabricPrivacy::logException) - ) - updateGUI() + .observeOn(aapsSchedulers.io) + .debounce(1L, TimeUnit.SECONDS) + .subscribe({ + disposable += repository + .compatGetBgReadingsDataFromTime(now - millsToThePast, false) + .observeOn(aapsSchedulers.main) + .subscribe { list -> binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true) } + }, fabricPrivacy::logException) } @Synchronized @@ -93,83 +93,41 @@ class BGSourceFragment : DaggerFragment() { binding.recyclerview.adapter = null // avoid leaks } - private fun updateGUI() { - if (_binding == null) return - val now = System.currentTimeMillis() - (binding.recyclerview.adapter as? RecyclerViewAdapter)?.setData(getBgData(now)) - } + inner class RecyclerViewAdapter internal constructor(private var glucoseValues: List) : RecyclerView.Adapter() { - private fun getBgData(now: Long) = MainApp.getDbHelper() - .getAllBgreadingsDataFromTime(now - millsToThePast, false) - - inner class RecyclerViewAdapter internal constructor(bgReadings: List) : RecyclerView.Adapter() { - - private var callbackHelper = ListUpdateCallbackHelper(this) { binding.recyclerview.smoothScrollToPosition(0) } - - private val currentData: MutableList = mutableListOf().also { it.addAll(bgReadings) } - - fun setData(newList: List) { - val diffResult = DiffUtil.calculateDiff(getListDiffCallback(ArrayList(newList), ArrayList(currentData))) - currentData.clear() - currentData.addAll(newList) - diffResult.dispatchUpdatesTo(callbackHelper) - } - - private fun getListDiffCallback(newItems: List, oldItems: List): ListDiffCallback = - object : ListDiffCallback(newItems, oldItems) { - override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { - val new = newItems[newItemPosition] - val old = oldItems[oldItemPosition] - return new.hasValidNS == old.hasValidNS && - new.isValid == old.isValid && - new.date == old.date && - new.value == old.value - } - - override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean = - newItems[newItemPosition].date == oldItems[oldItemPosition].date - } - - override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): BgReadingsViewHolder { + override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): GlucoseValuesViewHolder { val v = LayoutInflater.from(viewGroup.context).inflate(R.layout.bgsource_item, viewGroup, false) - return BgReadingsViewHolder(v) + return GlucoseValuesViewHolder(v) } - override fun onBindViewHolder(holder: BgReadingsViewHolder, position: Int) { - val bgReading = currentData[position] - holder.binding.ns.visibility = (NSUpload.isIdValid(bgReading._id)).toVisibility() - holder.binding.invalid.visibility = bgReading.isValid.not().toVisibility() - holder.binding.date.text = dateUtil.dateAndTimeString(bgReading.date) - holder.binding.value.text = bgReading.valueToUnitsToString(profileFunction.getUnits()) - holder.binding.direction.setImageResource(bgReading.directionToIcon(databaseHelper)) - holder.binding.remove.tag = bgReading - holder.binding.remove.visibility = bgReading.isValid.toVisibility() + override fun onBindViewHolder(holder: GlucoseValuesViewHolder, position: Int) { + val glucoseValue = glucoseValues[position] + holder.binding.ns.visibility = (glucoseValue.interfaceIDs.nightscoutId != null).toVisibility() + holder.binding.invalid.visibility = (!glucoseValue.isValid).toVisibility() + holder.binding.date.text = dateUtil.dateAndTimeString(glucoseValue.timestamp) + holder.binding.value.text = glucoseValue.valueToUnitsString(profileFunction.getUnits()) + holder.binding.direction.setImageResource(glucoseValue.trendArrow.directionToIcon()) + holder.binding.remove.tag = glucoseValue } - override fun getItemCount(): Int { - return currentData.size - } + override fun getItemCount(): Int = glucoseValues.size - inner class BgReadingsViewHolder(view: View) : RecyclerView.ViewHolder(view) { + inner class GlucoseValuesViewHolder(view: View) : RecyclerView.ViewHolder(view) { val binding = BgsourceItemBinding.bind(view) init { + binding.remove.paintFlags = binding.remove.paintFlags or Paint.UNDERLINE_TEXT_FLAG binding.remove.setOnClickListener { v: View -> - val bgReading = v.tag as BgReading + val glucoseValue = v.tag as GlucoseValue activity?.let { activity -> - val text = dateUtil.dateAndTimeString(bgReading.date) + "\n" + bgReading.valueToUnitsToString(profileFunction.getUnits()) + val text = dateUtil.dateAndTimeString(glucoseValue.timestamp) + "\n" + glucoseValue.valueToUnitsString(profileFunction.getUnits()) OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.removerecord), text, Runnable { - bgReading.isValid = false - MainApp.getDbHelper().update(bgReading) + disposable += repository.runTransaction(InvalidateGlucoseValueTransaction(glucoseValue.id)).subscribe() }) } } - binding.remove.paintFlags = binding.remove.paintFlags or Paint.UNDERLINE_TEXT_FLAG } } } } - -val BgReading.hasValidNS - get() = NSUpload.isIdValid(this._id) \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/DexcomPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/DexcomPlugin.kt index a8b3fcce65..811fd3a353 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/DexcomPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/DexcomPlugin.kt @@ -8,34 +8,36 @@ import androidx.work.Worker import androidx.work.WorkerParameters import dagger.android.HasAndroidInjector import info.nightscout.androidaps.Config -import info.nightscout.androidaps.Constants -import info.nightscout.androidaps.MainApp import info.nightscout.androidaps.R import info.nightscout.androidaps.activities.RequestDexcomPermissionActivity +import info.nightscout.androidaps.database.AppRepository +import info.nightscout.androidaps.database.entities.GlucoseValue +import info.nightscout.androidaps.database.transactions.CgmSourceTransaction import info.nightscout.androidaps.db.BgReading -import info.nightscout.androidaps.db.CareportalEvent -import info.nightscout.androidaps.db.Source import info.nightscout.androidaps.interfaces.BgSourceInterface import info.nightscout.androidaps.interfaces.PluginBase import info.nightscout.androidaps.interfaces.PluginDescription import info.nightscout.androidaps.interfaces.PluginType import info.nightscout.androidaps.logging.AAPSLogger +import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.plugins.general.nsclient.NSUpload import info.nightscout.androidaps.receivers.BundleStore import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.T +import info.nightscout.androidaps.utils.XDripBroadcast import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.sharedPreferences.SP -import org.json.JSONObject +import io.reactivex.disposables.CompositeDisposable +import io.reactivex.rxkotlin.plusAssign import javax.inject.Inject import javax.inject.Singleton @Singleton class DexcomPlugin @Inject constructor( injector: HasAndroidInjector, - private val mainApp: MainApp, resourceHelper: ResourceHelper, aapsLogger: AAPSLogger, + private val dexcomMediator: DexcomMediator, config: Config ) : PluginBase(PluginDescription() .mainType(PluginType.BGSOURCE) @@ -48,6 +50,8 @@ class DexcomPlugin @Inject constructor( aapsLogger, resourceHelper, injector ), BgSourceInterface { + private val disposable = CompositeDisposable() + init { if (!config.NSCLIENT) { pluginDescription.setDefault() @@ -60,19 +64,12 @@ class DexcomPlugin @Inject constructor( override fun onStart() { super.onStart() - if (ContextCompat.checkSelfPermission(mainApp, PERMISSION) != PackageManager.PERMISSION_GRANTED) { - val intent = Intent(mainApp, RequestDexcomPermissionActivity::class.java) - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - mainApp.startActivity(intent) - } + dexcomMediator.requestPermissionIfNeeded() } - fun findDexcomPackageName(): String? { - val packageManager = mainApp.packageManager - for (packageInfo in packageManager.getInstalledPackages(0)) { - if (PACKAGE_NAMES.contains(packageInfo.packageName)) return packageInfo.packageName - } - return null + override fun onStop() { + disposable.clear() + super.onStop() } // cannot be inner class because of needed injection @@ -87,6 +84,8 @@ class DexcomPlugin @Inject constructor( @Inject lateinit var nsUpload: NSUpload @Inject lateinit var sp: SP @Inject lateinit var bundleStore: BundleStore + @Inject lateinit var broadcastToXDrip: XDripBroadcast + @Inject lateinit var repository: AppRepository init { (context.applicationContext as HasAndroidInjector).androidInjector().inject(this) @@ -97,72 +96,52 @@ class DexcomPlugin @Inject constructor( val bundle = bundleStore.pickup(inputData.getLong("storeKey", -1)) ?: return Result.failure() try { - val sensorType = bundle.getString("sensorType") ?: "" - val glucoseValues = bundle.getBundle("glucoseValues") ?: return Result.failure() - for (i in 0 until glucoseValues.size()) { - glucoseValues.getBundle(i.toString())?.let { glucoseValue -> - val bgReading = BgReading() - bgReading.value = glucoseValue.getInt("glucoseValue").toDouble() - bgReading.direction = glucoseValue.getString("trendArrow") - bgReading.date = glucoseValue.getLong("timestamp") * 1000 - bgReading.raw = 0.0 - if (MainApp.getDbHelper().createIfNotExists(bgReading, "Dexcom$sensorType")) { - if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false)) { - nsUpload.uploadBg(bgReading, "AndroidAPS-Dexcom$sensorType") - } - if (sp.getBoolean(R.string.key_dexcomg5_xdripupload, false)) { - nsUpload.sendToXdrip(bgReading) - } - } - } + val sourceSensor = when (bundle.getString("sensorType") ?: "") { + "G6" -> GlucoseValue.SourceSensor.DEXCOM_G6_NATIVE + "G5" -> GlucoseValue.SourceSensor.DEXCOM_G5_NATIVE + else -> GlucoseValue.SourceSensor.DEXCOM_NATIVE_UNKNOWN } + val glucoseValuesBundle = bundle.getBundle("glucoseValues") + ?: return Result.failure() + val glucoseValues = mutableListOf() + for (i in 0 until glucoseValuesBundle.size()) { + val glucoseValueBundle = glucoseValuesBundle.getBundle(i.toString())!! + glucoseValues += CgmSourceTransaction.TransactionGlucoseValue( + timestamp = glucoseValueBundle.getLong("timestamp") * 1000, + value = glucoseValueBundle.getInt("glucoseValue").toDouble(), + noise = null, + raw = null, + trendArrow = GlucoseValue.TrendArrow.fromString(glucoseValueBundle.getString("trendArrow")!!), + sourceSensor = sourceSensor + ) + } + val calibrations = mutableListOf() bundle.getBundle("meters")?.let { meters -> for (i in 0 until meters.size()) { - val meter = meters.getBundle(i.toString()) - meter?.let { + meters.getBundle(i.toString())?.let { val timestamp = it.getLong("timestamp") * 1000 val now = DateUtil.now() - if (timestamp > now - T.months(1).msecs() && timestamp < now) - if (MainApp.getDbHelper().getCareportalEventFromTimestamp(timestamp) == null) { - val jsonObject = JSONObject() - jsonObject.put("enteredBy", "AndroidAPS-Dexcom$sensorType") - jsonObject.put("created_at", DateUtil.toISOString(timestamp)) - jsonObject.put("eventType", CareportalEvent.BGCHECK) - jsonObject.put("glucoseType", "Finger") - jsonObject.put("glucose", meter.getInt("meterValue")) - jsonObject.put("units", Constants.MGDL) - - val careportalEvent = CareportalEvent(injector) - careportalEvent.date = timestamp - careportalEvent.source = Source.USER - careportalEvent.eventType = CareportalEvent.BGCHECK - careportalEvent.json = jsonObject.toString() - MainApp.getDbHelper().createOrUpdate(careportalEvent) - nsUpload.uploadCareportalEntryToNS(jsonObject) - } + if (timestamp > now - T.months(1).msecs() && timestamp < now) { + calibrations.add(CgmSourceTransaction.Calibration(it.getLong("timestamp") * 1000, + it.getInt("meterValue").toDouble())) + } } } } - if (sp.getBoolean(R.string.key_dexcom_lognssensorchange, false) && bundle.containsKey("sensorInsertionTime")) { - bundle.let { - val sensorInsertionTime = it.getLong("sensorInsertionTime") * 1000 - val now = DateUtil.now() - if (sensorInsertionTime > now - T.months(1).msecs() && sensorInsertionTime < now) - if (MainApp.getDbHelper().getCareportalEventFromTimestamp(sensorInsertionTime) == null) { - val jsonObject = JSONObject() - jsonObject.put("enteredBy", "AndroidAPS-Dexcom$sensorType") - jsonObject.put("created_at", DateUtil.toISOString(sensorInsertionTime)) - jsonObject.put("eventType", CareportalEvent.SENSORCHANGE) - val careportalEvent = CareportalEvent(injector) - careportalEvent.date = sensorInsertionTime - careportalEvent.source = Source.USER - careportalEvent.eventType = CareportalEvent.SENSORCHANGE - careportalEvent.json = jsonObject.toString() - MainApp.getDbHelper().createOrUpdate(careportalEvent) - nsUpload.uploadCareportalEntryToNS(jsonObject) - } - } + val sensorStartTime = if (sp.getBoolean(R.string.key_dexcom_lognssensorchange, false) && bundle.containsKey("sensorInsertionTime")) { + bundle.getLong("sensorInsertionTime", 0) * 1000 + } else { + null } + dexcomPlugin.disposable += repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, calibrations, sensorStartTime)).subscribe({ savedValues -> + savedValues.forEach { + broadcastToXDrip(it) + if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false)) + nsUpload.uploadBg(BgReading(injector, it), sourceSensor.text) + } + }, { + aapsLogger.error(LTag.BGSOURCE, "Error while saving values from Dexcom App", it) + }) } catch (e: Exception) { aapsLogger.error("Error while processing intent from Dexcom App", e) } @@ -178,4 +157,23 @@ class DexcomPlugin @Inject constructor( "com.dexcom.g6.region3.mgdl", "com.dexcom.g6.region3.mmol") const val PERMISSION = "com.dexcom.cgm.EXTERNAL_PERMISSION" } + + class DexcomMediator @Inject constructor(val context: Context) { + + fun requestPermissionIfNeeded() { + if (ContextCompat.checkSelfPermission(context, PERMISSION) != PackageManager.PERMISSION_GRANTED) { + val intent = Intent(context, RequestDexcomPermissionActivity::class.java) + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + context.startActivity(intent) + } + } + + fun findDexcomPackageName(): String? { + val packageManager = context.packageManager + for (packageInfo in packageManager.getInstalledPackages(0)) { + if (PACKAGE_NAMES.contains(packageInfo.packageName)) return packageInfo.packageName + } + return null + } + } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/EversensePlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/EversensePlugin.kt index 8106a66b48..bf13f16916 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/EversensePlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/EversensePlugin.kt @@ -7,6 +7,9 @@ import dagger.android.HasAndroidInjector import info.nightscout.androidaps.Constants import info.nightscout.androidaps.MainApp import info.nightscout.androidaps.R +import info.nightscout.androidaps.database.AppRepository +import info.nightscout.androidaps.database.entities.GlucoseValue +import info.nightscout.androidaps.database.transactions.CgmSourceTransaction import info.nightscout.androidaps.db.BgReading import info.nightscout.androidaps.db.CareportalEvent import info.nightscout.androidaps.interfaces.BgSourceInterface @@ -18,8 +21,11 @@ import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.plugins.general.nsclient.NSUpload import info.nightscout.androidaps.receivers.BundleStore import info.nightscout.androidaps.utils.DateUtil +import info.nightscout.androidaps.utils.XDripBroadcast import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.sharedPreferences.SP +import io.reactivex.disposables.CompositeDisposable +import io.reactivex.rxkotlin.plusAssign import org.json.JSONException import org.json.JSONObject import java.util.* @@ -44,18 +50,28 @@ class EversensePlugin @Inject constructor( override var sensorBatteryLevel = -1 + private val disposable = CompositeDisposable() + + override fun onStop() { + disposable.clear() + super.onStop() + } + // cannot be inner class because of needed injection class EversenseWorker( context: Context, params: WorkerParameters ) : Worker(context, params) { + @Inject lateinit var injector: HasAndroidInjector @Inject lateinit var eversensePlugin: EversensePlugin @Inject lateinit var aapsLogger: AAPSLogger @Inject lateinit var sp: SP @Inject lateinit var nsUpload: NSUpload @Inject lateinit var dateUtil: DateUtil @Inject lateinit var bundleStore: BundleStore + @Inject lateinit var repository: AppRepository + @Inject lateinit var broadcastToXDrip: XDripBroadcast init { (context.applicationContext as HasAndroidInjector).androidInjector().inject(this) @@ -73,7 +89,7 @@ class EversensePlugin @Inject constructor( if (bundle.containsKey("batteryLevel")) { aapsLogger.debug(LTag.BGSOURCE, "batteryLevel: " + bundle.getString("batteryLevel")) //sensorBatteryLevel = bundle.getString("batteryLevel").toInt() - // TODO: Philoul: Line to check I don't have eversense so I don't know what kind of information is sent... + // TODO: Line to check I don't have eversense so I don't know what kind of information is sent... } if (bundle.containsKey("signalStrength")) aapsLogger.debug(LTag.BGSOURCE, "signalStrength: " + bundle.getString("signalStrength")) if (bundle.containsKey("transmitterVersionNumber")) aapsLogger.debug(LTag.BGSOURCE, "transmitterVersionNumber: " + bundle.getString("transmitterVersionNumber")) @@ -85,6 +101,7 @@ class EversensePlugin @Inject constructor( if (bundle.containsKey("transmitterVersionNumber")) aapsLogger.debug(LTag.BGSOURCE, "transmitterVersionNumber: " + bundle.getString("transmitterVersionNumber")) if (bundle.containsKey("transmitterConnectionState")) aapsLogger.debug(LTag.BGSOURCE, "transmitterConnectionState: " + bundle.getString("transmitterConnectionState")) if (bundle.containsKey("glucoseLevels")) { + val glucoseValues = mutableListOf() val glucoseLevels = bundle.getIntArray("glucoseLevels") val glucoseRecordNumbers = bundle.getIntArray("glucoseRecordNumbers") val glucoseTimestamps = bundle.getLongArray("glucoseTimestamps") @@ -92,19 +109,24 @@ class EversensePlugin @Inject constructor( aapsLogger.debug(LTag.BGSOURCE, "glucoseLevels" + Arrays.toString(glucoseLevels)) aapsLogger.debug(LTag.BGSOURCE, "glucoseRecordNumbers" + Arrays.toString(glucoseRecordNumbers)) aapsLogger.debug(LTag.BGSOURCE, "glucoseTimestamps" + Arrays.toString(glucoseTimestamps)) - for (i in glucoseLevels.indices) { - val bgReading = BgReading() - bgReading.value = glucoseLevels[i].toDouble() - bgReading.date = glucoseTimestamps[i] - bgReading.raw = 0.0 - val isNew = MainApp.getDbHelper().createIfNotExists(bgReading, "Eversense") - if (isNew && sp.getBoolean(R.string.key_dexcomg5_nsupload, false)) { - nsUpload.uploadBg(bgReading, "AndroidAPS-Eversense") + for (i in glucoseLevels.indices) + glucoseValues += CgmSourceTransaction.TransactionGlucoseValue( + timestamp = glucoseTimestamps[i], + value = glucoseLevels[i].toDouble(), + raw = glucoseLevels[i].toDouble(), + noise = null, + trendArrow = GlucoseValue.TrendArrow.NONE, + sourceSensor = GlucoseValue.SourceSensor.EVERSENSE + ) + eversensePlugin.disposable += repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null)).subscribe({ savedValues -> + savedValues.forEach { + broadcastToXDrip(it) + if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false)) + nsUpload.uploadBg(BgReading(injector, it), GlucoseValue.SourceSensor.EVERSENSE.text) } - if (isNew && sp.getBoolean(R.string.key_dexcomg5_xdripupload, false)) { - nsUpload.sendToXdrip(bgReading) - } - } + }, { + aapsLogger.error(LTag.BGSOURCE, "Error while saving values from Eversense App", it) + }) } } if (bundle.containsKey("calibrationGlucoseLevels")) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/GlimpPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/GlimpPlugin.kt index 42ff746173..1fed35428b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/GlimpPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/GlimpPlugin.kt @@ -4,8 +4,10 @@ import android.content.Context import androidx.work.Worker import androidx.work.WorkerParameters import dagger.android.HasAndroidInjector -import info.nightscout.androidaps.MainApp import info.nightscout.androidaps.R +import info.nightscout.androidaps.database.AppRepository +import info.nightscout.androidaps.database.entities.GlucoseValue +import info.nightscout.androidaps.database.transactions.CgmSourceTransaction import info.nightscout.androidaps.db.BgReading import info.nightscout.androidaps.interfaces.BgSourceInterface import info.nightscout.androidaps.interfaces.PluginBase @@ -13,7 +15,12 @@ import info.nightscout.androidaps.interfaces.PluginDescription import info.nightscout.androidaps.interfaces.PluginType import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag +import info.nightscout.androidaps.plugins.general.nsclient.NSUpload +import info.nightscout.androidaps.utils.XDripBroadcast import info.nightscout.androidaps.utils.resources.ResourceHelper +import info.nightscout.androidaps.utils.sharedPreferences.SP +import io.reactivex.disposables.CompositeDisposable +import io.reactivex.rxkotlin.plusAssign import javax.inject.Inject import javax.inject.Singleton @@ -32,14 +39,26 @@ class GlimpPlugin @Inject constructor( aapsLogger, resourceHelper, injector ), BgSourceInterface { + private val disposable = CompositeDisposable() + + override fun onStop() { + disposable.clear() + super.onStop() + } + // cannot be inner class because of needed injection class GlimpWorker( context: Context, params: WorkerParameters ) : Worker(context, params) { + @Inject lateinit var injector: HasAndroidInjector @Inject lateinit var glimpPlugin: GlimpPlugin @Inject lateinit var aapsLogger: AAPSLogger + @Inject lateinit var repository: AppRepository + @Inject lateinit var broadcastToXDrip: XDripBroadcast + @Inject lateinit var sp: SP + @Inject lateinit var nsUpload: NSUpload init { (context.applicationContext as HasAndroidInjector).androidInjector().inject(this) @@ -48,12 +67,24 @@ class GlimpPlugin @Inject constructor( override fun doWork(): Result { if (!glimpPlugin.isEnabled(PluginType.BGSOURCE)) return Result.failure() aapsLogger.debug(LTag.BGSOURCE, "Received Glimp Data: $inputData}") - val bgReading = BgReading() - bgReading.value = inputData.getDouble("mySGV", 0.0) - bgReading.direction = inputData.getString("myTrend") - bgReading.date = inputData.getLong("myTimestamp", 0) - bgReading.raw = 0.0 - MainApp.getDbHelper().createIfNotExists(bgReading, "GLIMP") + val glucoseValues = mutableListOf() + glucoseValues += CgmSourceTransaction.TransactionGlucoseValue( + timestamp = inputData.getLong("myTimestamp", 0), + value = inputData.getDouble("mySGV", 0.0), + raw = inputData.getDouble("mySGV", 0.0), + noise = null, + trendArrow = GlucoseValue.TrendArrow.fromString(inputData.getString("myTrend")), + sourceSensor = GlucoseValue.SourceSensor.GLIMP + ) + glimpPlugin.disposable += repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null)).subscribe({ savedValues -> + savedValues.forEach { + broadcastToXDrip(it) + if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false)) + nsUpload.uploadBg(BgReading(injector, it), GlucoseValue.SourceSensor.GLIMP.text) + } + }, { + aapsLogger.error(LTag.BGSOURCE, "Error while saving values from Glimp App", it) + }) return Result.success() } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/MM640gPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/MM640gPlugin.kt index 5a886120d5..6d5b7a8c4d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/MM640gPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/MM640gPlugin.kt @@ -4,8 +4,10 @@ import android.content.Context import androidx.work.Worker import androidx.work.WorkerParameters import dagger.android.HasAndroidInjector -import info.nightscout.androidaps.MainApp import info.nightscout.androidaps.R +import info.nightscout.androidaps.database.AppRepository +import info.nightscout.androidaps.database.entities.GlucoseValue +import info.nightscout.androidaps.database.transactions.CgmSourceTransaction import info.nightscout.androidaps.db.BgReading import info.nightscout.androidaps.interfaces.BgSourceInterface import info.nightscout.androidaps.interfaces.PluginBase @@ -13,7 +15,14 @@ import info.nightscout.androidaps.interfaces.PluginDescription import info.nightscout.androidaps.interfaces.PluginType import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag +import info.nightscout.androidaps.plugins.general.nsclient.NSUpload +import info.nightscout.androidaps.receivers.BundleStore +import info.nightscout.androidaps.utils.DateUtil +import info.nightscout.androidaps.utils.XDripBroadcast import info.nightscout.androidaps.utils.resources.ResourceHelper +import info.nightscout.androidaps.utils.sharedPreferences.SP +import io.reactivex.disposables.CompositeDisposable +import io.reactivex.rxkotlin.plusAssign import org.json.JSONArray import org.json.JSONException import javax.inject.Inject @@ -33,6 +42,13 @@ class MM640gPlugin @Inject constructor( aapsLogger, resourceHelper, injector ), BgSourceInterface { + private val disposable = CompositeDisposable() + + override fun onStop() { + disposable.clear() + super.onStop() + } + // cannot be inner class because of needed injection class MM640gWorker( context: Context, @@ -40,7 +56,14 @@ class MM640gPlugin @Inject constructor( ) : Worker(context, params) { @Inject lateinit var mM640gPlugin: MM640gPlugin + @Inject lateinit var injector: HasAndroidInjector @Inject lateinit var aapsLogger: AAPSLogger + @Inject lateinit var sp: SP + @Inject lateinit var nsUpload: NSUpload + @Inject lateinit var dateUtil: DateUtil + @Inject lateinit var bundleStore: BundleStore + @Inject lateinit var repository: AppRepository + @Inject lateinit var broadcastToXDrip: XDripBroadcast init { (context.applicationContext as HasAndroidInjector).androidInjector().inject(this) @@ -54,22 +77,32 @@ class MM640gPlugin @Inject constructor( aapsLogger.debug(LTag.BGSOURCE, "Received MM640g Data: $data") if (data != null && data.isNotEmpty()) { try { + val glucoseValues = mutableListOf() val jsonArray = JSONArray(data) for (i in 0 until jsonArray.length()) { val jsonObject = jsonArray.getJSONObject(i) when (val type = jsonObject.getString("type")) { - "sgv" -> { - val bgReading = BgReading() - bgReading.value = jsonObject.getDouble("sgv") - bgReading.direction = jsonObject.getString("direction") - bgReading.date = jsonObject.getLong("date") - bgReading.raw = jsonObject.getDouble("sgv") - MainApp.getDbHelper().createIfNotExists(bgReading, "MM640g") - } - + "sgv" -> + glucoseValues += CgmSourceTransaction.TransactionGlucoseValue( + timestamp = jsonObject.getLong("sgv"), + value = jsonObject.getDouble("sgv"), + raw = jsonObject.getDouble("sgv"), + noise = null, + trendArrow = GlucoseValue.TrendArrow.fromString(jsonObject.getString("direction")), + sourceSensor = GlucoseValue.SourceSensor.MM_600_SERIES + ) else -> aapsLogger.debug(LTag.BGSOURCE, "Unknown entries type: $type") } } + mM640gPlugin.disposable += repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null)).subscribe({ savedValues -> + savedValues.forEach { + broadcastToXDrip(it) + if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false)) + nsUpload.uploadBg(BgReading(injector, it), GlucoseValue.SourceSensor.MM_600_SERIES.text) + } + }, { + aapsLogger.error(LTag.BGSOURCE, "Error while saving values from Eversense App", it) + }) } catch (e: JSONException) { aapsLogger.error("Exception: ", e) } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/NSClientSourcePlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/NSClientSourcePlugin.kt index e6ed68b96f..82dd4aa08e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/NSClientSourcePlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/NSClientSourcePlugin.kt @@ -5,20 +5,25 @@ import androidx.work.Worker import androidx.work.WorkerParameters import dagger.android.HasAndroidInjector import info.nightscout.androidaps.Config -import info.nightscout.androidaps.MainApp import info.nightscout.androidaps.R -import info.nightscout.androidaps.db.BgReading +import info.nightscout.androidaps.database.AppRepository +import info.nightscout.androidaps.database.entities.GlucoseValue +import info.nightscout.androidaps.database.transactions.CgmSourceTransaction import info.nightscout.androidaps.interfaces.BgSourceInterface import info.nightscout.androidaps.interfaces.PluginBase import info.nightscout.androidaps.interfaces.PluginDescription import info.nightscout.androidaps.interfaces.PluginType import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag +import info.nightscout.androidaps.plugins.general.nsclient.NSUpload import info.nightscout.androidaps.plugins.general.nsclient.data.NSSgv -import info.nightscout.androidaps.utils.JsonHelper.safeGetLong -import info.nightscout.androidaps.utils.JsonHelper.safeGetString +import info.nightscout.androidaps.receivers.BundleStore +import info.nightscout.androidaps.utils.DateUtil +import info.nightscout.androidaps.utils.XDripBroadcast import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.sharedPreferences.SP +import io.reactivex.disposables.CompositeDisposable +import io.reactivex.rxkotlin.plusAssign import org.json.JSONArray import org.json.JSONObject import javax.inject.Inject @@ -50,21 +55,27 @@ class NSClientSourcePlugin @Inject constructor( } } + private val disposable = CompositeDisposable() + + override fun onStop() { + disposable.clear() + super.onStop() + } + override fun advancedFilteringSupported(): Boolean { return isAdvancedFilteringEnabled } - private fun storeSgv(sgvJson: JSONObject) { - val nsSgv = NSSgv(sgvJson) - val bgReading = BgReading(injector, nsSgv) - MainApp.getDbHelper().createIfNotExists(bgReading, "NS") - detectSource(safeGetString(sgvJson, "device", "none"), safeGetLong(sgvJson, "mills")) - } - - private fun detectSource(source: String, timeStamp: Long) { - if (timeStamp > lastBGTimeStamp) { - isAdvancedFilteringEnabled = source.contains("G5 Native") || source.contains("G6 Native") || source.contains("AndroidAPS-DexcomG5") || source.contains("AndroidAPS-DexcomG6") - lastBGTimeStamp = timeStamp + private fun detectSource(glucoseValue: GlucoseValue) { + if (glucoseValue.timestamp > lastBGTimeStamp) { + isAdvancedFilteringEnabled = arrayOf( + GlucoseValue.SourceSensor.DEXCOM_NATIVE_UNKNOWN, + GlucoseValue.SourceSensor.DEXCOM_G6_NATIVE, + GlucoseValue.SourceSensor.DEXCOM_G5_NATIVE, + GlucoseValue.SourceSensor.DEXCOM_G6_NATIVE_XDRIP, + GlucoseValue.SourceSensor.DEXCOM_G5_NATIVE_XDRIP + ).any { it == glucoseValue.sourceSensor } + lastBGTimeStamp = glucoseValue.timestamp } } @@ -75,29 +86,53 @@ class NSClientSourcePlugin @Inject constructor( ) : Worker(context, params) { @Inject lateinit var nsClientSourcePlugin: NSClientSourcePlugin + @Inject lateinit var injector: HasAndroidInjector @Inject lateinit var aapsLogger: AAPSLogger @Inject lateinit var sp: SP + @Inject lateinit var nsUpload: NSUpload + @Inject lateinit var dateUtil: DateUtil + @Inject lateinit var bundleStore: BundleStore + @Inject lateinit var repository: AppRepository + @Inject lateinit var broadcastToXDrip: XDripBroadcast init { (context.applicationContext as HasAndroidInjector).androidInjector().inject(this) } + fun toGv(jsonObject: JSONObject): CgmSourceTransaction.TransactionGlucoseValue { + val sgv = NSSgv(jsonObject) + return CgmSourceTransaction.TransactionGlucoseValue( + timestamp = sgv.mills, + value = sgv.mgdl.toDouble(), + noise = null, + raw = if (sgv.filtered != null) sgv.filtered.toDouble() else sgv.mgdl.toDouble(), + trendArrow = GlucoseValue.TrendArrow.fromString(sgv.direction), + sourceSensor = GlucoseValue.SourceSensor.fromString(sgv.device) + ) + } + override fun doWork(): Result { if (!nsClientSourcePlugin.isEnabled(PluginType.BGSOURCE) && !sp.getBoolean(R.string.key_ns_autobackfill, true)) return Result.failure() try { + val glucoseValues = mutableListOf() inputData.getString("sgv")?.let { sgvString -> aapsLogger.debug(LTag.BGSOURCE, "Received NS Data: $sgvString") - val sgvJson = JSONObject(sgvString) - nsClientSourcePlugin.storeSgv(sgvJson) + glucoseValues += toGv(JSONObject(sgvString)) } inputData.getString("sgvs")?.let { sgvString -> aapsLogger.debug(LTag.BGSOURCE, "Received NS Data: $sgvString") val jsonArray = JSONArray(sgvString) - for (i in 0 until jsonArray.length()) { - val sgvJson = jsonArray.getJSONObject(i) - nsClientSourcePlugin.storeSgv(sgvJson) - } + for (i in 0 until jsonArray.length()) + glucoseValues += toGv(jsonArray.getJSONObject(i)) } + nsClientSourcePlugin.disposable += repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null)).subscribe({ savedValues -> + savedValues.forEach { + broadcastToXDrip(it) + nsClientSourcePlugin.detectSource(it) + } + }, { + aapsLogger.error(LTag.BGSOURCE, "Error while saving values from Eversense App", it) + }) } catch (e: Exception) { aapsLogger.error("Unhandled exception", e) return Result.failure() diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/PoctechPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/PoctechPlugin.kt index 5d6861ca37..67c8232fdc 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/PoctechPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/PoctechPlugin.kt @@ -5,8 +5,10 @@ import androidx.work.Worker import androidx.work.WorkerParameters import dagger.android.HasAndroidInjector import info.nightscout.androidaps.Constants -import info.nightscout.androidaps.MainApp import info.nightscout.androidaps.R +import info.nightscout.androidaps.database.AppRepository +import info.nightscout.androidaps.database.entities.GlucoseValue +import info.nightscout.androidaps.database.transactions.CgmSourceTransaction import info.nightscout.androidaps.db.BgReading import info.nightscout.androidaps.interfaces.BgSourceInterface import info.nightscout.androidaps.interfaces.PluginBase @@ -16,8 +18,11 @@ import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.plugins.general.nsclient.NSUpload import info.nightscout.androidaps.utils.JsonHelper.safeGetString +import info.nightscout.androidaps.utils.XDripBroadcast import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.sharedPreferences.SP +import io.reactivex.disposables.CompositeDisposable +import io.reactivex.rxkotlin.plusAssign import org.json.JSONArray import org.json.JSONException import javax.inject.Inject @@ -38,16 +43,26 @@ class PoctechPlugin @Inject constructor( aapsLogger, resourceHelper, injector ), BgSourceInterface { + private val disposable = CompositeDisposable() + + override fun onStop() { + disposable.clear() + super.onStop() + } + // cannot be inner class because of needed injection class PoctechWorker( context: Context, params: WorkerParameters ) : Worker(context, params) { + @Inject lateinit var injector: HasAndroidInjector @Inject lateinit var poctechPlugin: PoctechPlugin @Inject lateinit var aapsLogger: AAPSLogger @Inject lateinit var sp: SP @Inject lateinit var nsUpload: NSUpload + @Inject lateinit var repository: AppRepository + @Inject lateinit var broadcastToXDrip: XDripBroadcast init { (context.applicationContext as HasAndroidInjector).androidInjector().inject(this) @@ -57,24 +72,30 @@ class PoctechPlugin @Inject constructor( if (!poctechPlugin.isEnabled(PluginType.BGSOURCE)) return Result.failure() aapsLogger.debug(LTag.BGSOURCE, "Received Poctech Data $inputData") try { + val glucoseValues = mutableListOf() val jsonArray = JSONArray(inputData.getString("data")) aapsLogger.debug(LTag.BGSOURCE, "Received Poctech Data size:" + jsonArray.length()) for (i in 0 until jsonArray.length()) { val json = jsonArray.getJSONObject(i) - val bgReading = BgReading() - bgReading.value = json.getDouble("current") - bgReading.direction = json.getString("direction") - bgReading.date = json.getLong("date") - bgReading.raw = json.getDouble("raw") - if (safeGetString(json, "units", Constants.MGDL) == "mmol/L") bgReading.value = bgReading.value * Constants.MMOLL_TO_MGDL - val isNew = MainApp.getDbHelper().createIfNotExists(bgReading, "Poctech") - if (isNew && sp.getBoolean(R.string.key_dexcomg5_nsupload, false)) { - nsUpload.uploadBg(bgReading, "AndroidAPS-Poctech") - } - if (isNew && sp.getBoolean(R.string.key_dexcomg5_xdripupload, false)) { - nsUpload.sendToXdrip(bgReading) - } + glucoseValues += CgmSourceTransaction.TransactionGlucoseValue( + timestamp = json.getLong("date"), + value = if (safeGetString(json, "units", Constants.MGDL) == "mmol/L") json.getDouble("current") + else json.getDouble("current") * Constants.MMOLL_TO_MGDL, + raw = json.getDouble("raw"), + noise = null, + trendArrow = GlucoseValue.TrendArrow.fromString(json.getString("direction")), + sourceSensor = GlucoseValue.SourceSensor.POCTECH_NATIVE + ) } + poctechPlugin.disposable += repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null)).subscribe({ savedValues -> + savedValues.forEach { + broadcastToXDrip(it) + if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false)) + nsUpload.uploadBg(BgReading(injector, it), GlucoseValue.SourceSensor.POCTECH_NATIVE.text) + } + }, { + aapsLogger.error(LTag.BGSOURCE, "Error while saving values from Poctech App", it) + }) } catch (e: JSONException) { aapsLogger.error("Exception: ", e) return Result.failure() diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/RandomBgPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/RandomBgPlugin.kt index 5083854976..c208b27a51 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/RandomBgPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/RandomBgPlugin.kt @@ -3,8 +3,10 @@ package info.nightscout.androidaps.plugins.source import android.os.Handler import android.os.HandlerThread import dagger.android.HasAndroidInjector -import info.nightscout.androidaps.MainApp import info.nightscout.androidaps.R +import info.nightscout.androidaps.database.AppRepository +import info.nightscout.androidaps.database.entities.GlucoseValue +import info.nightscout.androidaps.database.transactions.CgmSourceTransaction import info.nightscout.androidaps.db.BgReading import info.nightscout.androidaps.interfaces.BgSourceInterface import info.nightscout.androidaps.interfaces.PluginBase @@ -16,10 +18,13 @@ import info.nightscout.androidaps.plugins.general.nsclient.NSUpload import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.T +import info.nightscout.androidaps.utils.XDripBroadcast import info.nightscout.androidaps.utils.buildHelper.BuildHelper import info.nightscout.androidaps.utils.extensions.isRunningTest import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.sharedPreferences.SP +import io.reactivex.disposables.CompositeDisposable +import io.reactivex.rxkotlin.plusAssign import java.util.* import javax.inject.Inject import javax.inject.Singleton @@ -34,7 +39,10 @@ class RandomBgPlugin @Inject constructor( private val virtualPumpPlugin: VirtualPumpPlugin, private val buildHelper: BuildHelper, private val sp: SP, - private val nsUpload: NSUpload + private val nsUpload: NSUpload, + private val dateUtil: DateUtil, + private val repository: AppRepository, + private val xDripBroadcast: XDripBroadcast ) : PluginBase(PluginDescription() .mainType(PluginType.BGSOURCE) .fragmentClass(BGSourceFragment::class.java.name) @@ -61,6 +69,8 @@ class RandomBgPlugin @Inject constructor( } } + private val disposable = CompositeDisposable() + override fun advancedFilteringSupported(): Boolean { return true } @@ -68,6 +78,7 @@ class RandomBgPlugin @Inject constructor( override fun onStart() { super.onStart() loopHandler.postDelayed(refreshLoop, T.mins(interval).msecs()) + disposable.clear() } override fun onStop() { @@ -88,16 +99,24 @@ class RandomBgPlugin @Inject constructor( val currentMinute = cal.get(Calendar.MINUTE) + (cal.get(Calendar.HOUR_OF_DAY) % 2) * 60 val bgMgdl = min + ((max - min) + (max - min) * sin(currentMinute / 120.0 * 2 * PI)) / 2 - val bgReading = BgReading() - bgReading.value = bgMgdl - bgReading.date = DateUtil.now() - bgReading.raw = bgMgdl - if (MainApp.getDbHelper().createIfNotExists(bgReading, "RandomBG")) { - if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false)) - nsUpload.uploadBg(bgReading, "AndroidAPS-RandomBG") - if (sp.getBoolean(R.string.key_dexcomg5_xdripupload, false)) - nsUpload.sendToXdrip(bgReading) - } - aapsLogger.debug(LTag.BGSOURCE, "Generated BG: $bgReading") + val glucoseValues = mutableListOf() + glucoseValues += CgmSourceTransaction.TransactionGlucoseValue( + timestamp = dateUtil._now(), + value = bgMgdl, + raw = 0.0, + noise = null, + trendArrow = GlucoseValue.TrendArrow.NONE, + sourceSensor = GlucoseValue.SourceSensor.RANDOM + ) + disposable += repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null)).subscribe({ savedValues -> + savedValues.forEach { + xDripBroadcast(it) + if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false)) + nsUpload.uploadBg(BgReading(injector, it), GlucoseValue.SourceSensor.RANDOM.text) + } + }, { + aapsLogger.error(LTag.BGSOURCE, "Error while saving values from Random plugin", it) + }) + aapsLogger.debug(LTag.BGSOURCE, "Generated BG: $bgMgdl ${Date()}") } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/TomatoPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/TomatoPlugin.kt index 0b7bd539c2..95a9d192ae 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/TomatoPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/TomatoPlugin.kt @@ -4,8 +4,10 @@ import android.content.Context import androidx.work.Worker import androidx.work.WorkerParameters import dagger.android.HasAndroidInjector -import info.nightscout.androidaps.MainApp import info.nightscout.androidaps.R +import info.nightscout.androidaps.database.AppRepository +import info.nightscout.androidaps.database.entities.GlucoseValue +import info.nightscout.androidaps.database.transactions.CgmSourceTransaction import info.nightscout.androidaps.db.BgReading import info.nightscout.androidaps.interfaces.BgSourceInterface import info.nightscout.androidaps.interfaces.PluginBase @@ -14,8 +16,11 @@ import info.nightscout.androidaps.interfaces.PluginType import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.plugins.general.nsclient.NSUpload +import info.nightscout.androidaps.utils.XDripBroadcast import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.sharedPreferences.SP +import io.reactivex.disposables.CompositeDisposable +import io.reactivex.rxkotlin.plusAssign import javax.inject.Inject import javax.inject.Singleton @@ -35,16 +40,26 @@ class TomatoPlugin @Inject constructor( aapsLogger, resourceHelper, injector ), BgSourceInterface { + private val disposable = CompositeDisposable() + + override fun onStop() { + disposable.clear() + super.onStop() + } + // cannot be inner class because of needed injection class TomatoWorker( context: Context, params: WorkerParameters ) : Worker(context, params) { + @Inject lateinit var injector: HasAndroidInjector @Inject lateinit var tomatoPlugin: TomatoPlugin @Inject lateinit var aapsLogger: AAPSLogger @Inject lateinit var sp: SP @Inject lateinit var nsUpload: NSUpload + @Inject lateinit var repository: AppRepository + @Inject lateinit var broadcastToXDrip: XDripBroadcast init { (context.applicationContext as HasAndroidInjector).androidInjector().inject(this) @@ -52,17 +67,24 @@ class TomatoPlugin @Inject constructor( override fun doWork(): Result { if (!tomatoPlugin.isEnabled(PluginType.BGSOURCE)) return Result.failure() - val bgReading = BgReading() - aapsLogger.debug(LTag.BGSOURCE, "Received Tomato Data") - bgReading.value = inputData.getDouble("com.fanqies.tomatofn.Extras.BgEstimate", 0.0) - bgReading.date = inputData.getLong("com.fanqies.tomatofn.Extras.Time", 0) - val isNew = MainApp.getDbHelper().createIfNotExists(bgReading, "Tomato") - if (isNew && sp.getBoolean(R.string.key_dexcomg5_nsupload, false)) { - nsUpload.uploadBg(bgReading, "AndroidAPS-Tomato") - } - if (isNew && sp.getBoolean(R.string.key_dexcomg5_xdripupload, false)) { - nsUpload.sendToXdrip(bgReading) - } + val glucoseValues = mutableListOf() + glucoseValues += CgmSourceTransaction.TransactionGlucoseValue( + timestamp = inputData.getLong("com.fanqies.tomatofn.Extras.Time", 0), + value = inputData.getDouble("com.fanqies.tomatofn.Extras.BgEstimate", 0.0), + raw = 0.0, + noise = null, + trendArrow = GlucoseValue.TrendArrow.NONE, + sourceSensor = GlucoseValue.SourceSensor.LIBRE_1_TOMATO + ) + tomatoPlugin.disposable += repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null)).subscribe({ savedValues -> + savedValues.forEach { + broadcastToXDrip(it) + if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false)) + nsUpload.uploadBg(BgReading(injector, it), GlucoseValue.SourceSensor.LIBRE_1_TOMATO.text) + } + }, { + aapsLogger.error(LTag.BGSOURCE, "Error while saving values from Tomato App", it) + }) return Result.success() } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/XdripPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/XdripPlugin.kt index e8fcf3bdc8..57fb9f98bb 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/XdripPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/XdripPlugin.kt @@ -4,9 +4,10 @@ import android.content.Context import androidx.work.Worker import androidx.work.WorkerParameters import dagger.android.HasAndroidInjector -import info.nightscout.androidaps.MainApp import info.nightscout.androidaps.R -import info.nightscout.androidaps.db.BgReading +import info.nightscout.androidaps.database.AppRepository +import info.nightscout.androidaps.database.entities.GlucoseValue +import info.nightscout.androidaps.database.transactions.CgmSourceTransaction import info.nightscout.androidaps.interfaces.BgSourceInterface import info.nightscout.androidaps.interfaces.PluginBase import info.nightscout.androidaps.interfaces.PluginDescription @@ -15,6 +16,8 @@ import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.services.Intents import info.nightscout.androidaps.utils.resources.ResourceHelper +import io.reactivex.disposables.CompositeDisposable +import io.reactivex.rxkotlin.plusAssign import javax.inject.Inject import javax.inject.Singleton @@ -39,8 +42,21 @@ class XdripPlugin @Inject constructor( return advancedFiltering } - private fun setSource(source: String) { - advancedFiltering = source.contains("G5 Native") || source.contains("G6 Native") + private fun detectSource(glucoseValue: GlucoseValue) { + advancedFiltering = arrayOf( + GlucoseValue.SourceSensor.DEXCOM_NATIVE_UNKNOWN, + GlucoseValue.SourceSensor.DEXCOM_G6_NATIVE, + GlucoseValue.SourceSensor.DEXCOM_G5_NATIVE, + GlucoseValue.SourceSensor.DEXCOM_G6_NATIVE_XDRIP, + GlucoseValue.SourceSensor.DEXCOM_G5_NATIVE_XDRIP + ).any { it == glucoseValue.sourceSensor } + } + + private val disposable = CompositeDisposable() + + override fun onStop() { + disposable.clear() + super.onStop() } // cannot be inner class because of needed injection @@ -50,6 +66,7 @@ class XdripPlugin @Inject constructor( ) : Worker(context, params) { @Inject lateinit var xdripPlugin: XdripPlugin + @Inject lateinit var repository: AppRepository init { (context.applicationContext as HasAndroidInjector).androidInjector().inject(this) @@ -58,15 +75,24 @@ class XdripPlugin @Inject constructor( override fun doWork(): Result { if (!xdripPlugin.isEnabled(PluginType.BGSOURCE)) return Result.failure() xdripPlugin.aapsLogger.debug(LTag.BGSOURCE, "Received xDrip data: $inputData") - val bgReading = BgReading() - bgReading.value = inputData.getDouble(Intents.EXTRA_BG_ESTIMATE, 0.0) - bgReading.direction = inputData.getString(Intents.EXTRA_BG_SLOPE_NAME) - bgReading.date = inputData.getLong(Intents.EXTRA_TIMESTAMP, 0) - bgReading.raw = inputData.getDouble(Intents.EXTRA_RAW, 0.0) + val glucoseValues = mutableListOf() + glucoseValues += CgmSourceTransaction.TransactionGlucoseValue( + timestamp = inputData.getLong(Intents.EXTRA_TIMESTAMP, 0), + value = inputData.getDouble(Intents.EXTRA_BG_ESTIMATE, 0.0), + raw = inputData.getDouble(Intents.EXTRA_RAW, 0.0), + noise = null, + trendArrow = GlucoseValue.TrendArrow.fromString(inputData.getString(Intents.EXTRA_BG_SLOPE_NAME)), + sourceSensor = GlucoseValue.SourceSensor.fromString(inputData.getString(Intents.XDRIP_DATA_SOURCE_DESCRIPTION) + ?: "") + ) + xdripPlugin.disposable += repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null)).subscribe({ savedValues -> + savedValues.forEach { + xdripPlugin.detectSource(it) + } + }, { + xdripPlugin.aapsLogger.error(LTag.BGSOURCE, "Error while saving values from Eversense App", it) + }) xdripPlugin.sensorBatteryLevel = inputData.getInt(Intents.EXTRA_SENSOR_BATTERY, -1) - val source = inputData.getString(Intents.XDRIP_DATA_SOURCE_DESCRIPTION) ?: "" - xdripPlugin.setSource(source) - MainApp.getDbHelper().createIfNotExists(bgReading, "XDRIP") return Result.success() } } diff --git a/app/src/main/java/info/nightscout/androidaps/utils/GlucoseValueUtils.kt b/app/src/main/java/info/nightscout/androidaps/utils/GlucoseValueUtils.kt new file mode 100644 index 0000000000..cfbba98958 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/utils/GlucoseValueUtils.kt @@ -0,0 +1,18 @@ +package info.nightscout.androidaps.utils + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.Constants +import info.nightscout.androidaps.database.entities.GlucoseValue +import info.nightscout.androidaps.db.BgReading + +fun GlucoseValue.valueToUnits(units: String): Double = + if (units == Constants.MGDL) value + else value * Constants.MGDL_TO_MMOLL + +fun GlucoseValue.valueToUnitsString(units: String): String = + if (units == Constants.MGDL) DecimalFormatter.to0Decimal(value) + else DecimalFormatter.to1Decimal(value * Constants.MGDL_TO_MMOLL) + +fun GlucoseValue.convertToBGReading(injector: HasAndroidInjector): BgReading = BgReading(injector, this) + +fun List.convertToBGReadings(injector: HasAndroidInjector): List = map { it.convertToBGReading(injector) } diff --git a/app/src/main/java/info/nightscout/androidaps/utils/LocalAlertUtils.kt b/app/src/main/java/info/nightscout/androidaps/utils/LocalAlertUtils.kt index e9f4f5fb64..908f759f41 100644 --- a/app/src/main/java/info/nightscout/androidaps/utils/LocalAlertUtils.kt +++ b/app/src/main/java/info/nightscout/androidaps/utils/LocalAlertUtils.kt @@ -3,7 +3,6 @@ package info.nightscout.androidaps.utils import info.nightscout.androidaps.Config import info.nightscout.androidaps.Constants import info.nightscout.androidaps.R -import info.nightscout.androidaps.db.BgReading import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.logging.AAPSLogger @@ -106,9 +105,9 @@ class LocalAlertUtils @Inject constructor( } fun checkStaleBGAlert() { - val bgReading: BgReading? = iobCobCalculatorPlugin.lastBg() + val bgReading = iobCobCalculatorPlugin.lastBg() if (sp.getBoolean(R.string.key_enable_missed_bg_readings_alert, false) - && bgReading != null && bgReading.date + missedReadingsThreshold() < System.currentTimeMillis() && sp.getLong("nextMissedReadingsAlarm", 0L) < System.currentTimeMillis()) { + && bgReading != null && bgReading.timestamp + missedReadingsThreshold() < System.currentTimeMillis() && sp.getLong("nextMissedReadingsAlarm", 0L) < System.currentTimeMillis()) { val n = Notification(Notification.BG_READINGS_MISSED, resourceHelper.gs(R.string.missed_bg_readings), Notification.URGENT) n.soundId = R.raw.alarm sp.putLong("nextMissedReadingsAlarm", System.currentTimeMillis() + missedReadingsThreshold()) diff --git a/app/src/main/java/info/nightscout/androidaps/utils/XDripBroadcast.kt b/app/src/main/java/info/nightscout/androidaps/utils/XDripBroadcast.kt new file mode 100644 index 0000000000..e814e95422 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/utils/XDripBroadcast.kt @@ -0,0 +1,60 @@ +package info.nightscout.androidaps.utils + +import android.content.Context +import android.content.Intent +import android.os.Bundle +import info.nightscout.androidaps.R +import info.nightscout.androidaps.database.entities.GlucoseValue +import info.nightscout.androidaps.logging.AAPSLogger +import info.nightscout.androidaps.logging.LTag +import info.nightscout.androidaps.utils.sharedPreferences.SP +import org.json.JSONArray +import org.json.JSONException +import org.json.JSONObject +import java.text.SimpleDateFormat +import java.util.* +import javax.inject.Inject + +class XDripBroadcast @Inject constructor( + private val context: Context, + private val aapsLogger: AAPSLogger, + private val sp: SP +) { + + operator fun invoke(glucoseValue: GlucoseValue) { + if (sp.getBoolean(R.string.key_dexcomg5_xdripupload, false)) { + val format = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.US) + try { + val entriesBody = JSONArray() + val json = JSONObject() + json.put("sgv", glucoseValue.value) + json.put("direction", glucoseValue.trendArrow.text) + json.put("device", "G5") + json.put("type", "sgv") + json.put("date", glucoseValue.timestamp) + json.put("dateString", format.format(glucoseValue.timestamp)) + entriesBody.put(json) + val bundle = Bundle() + bundle.putString("action", "add") + bundle.putString("collection", "entries") + bundle.putString("data", entriesBody.toString()) + val intent = Intent(XDRIP_PLUS_NS_EMULATOR) + intent.putExtras(bundle).addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES) + context.sendBroadcast(intent) + val receivers = context.packageManager.queryBroadcastReceivers(intent, 0) + if (receivers.size < 1) { + //NSUpload.log.debug("No xDrip receivers found. ") + aapsLogger.debug(LTag.BGSOURCE, "No xDrip receivers found.") + } else { + aapsLogger.debug(LTag.BGSOURCE, "${receivers.size} xDrip receivers") + } + } catch (e: JSONException) { + aapsLogger.error(LTag.BGSOURCE, "Unhandled exception", e) + } + } + } + + companion object { + const val XDRIP_PLUS_NS_EMULATOR = "com.eveningoutpost.dexdrip.NS_EMULATOR" + } +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/utils/stats/TirCalculator.kt b/app/src/main/java/info/nightscout/androidaps/utils/stats/TirCalculator.kt index 2d65ddbdf2..d1f7c74bf1 100644 --- a/app/src/main/java/info/nightscout/androidaps/utils/stats/TirCalculator.kt +++ b/app/src/main/java/info/nightscout/androidaps/utils/stats/TirCalculator.kt @@ -3,9 +3,9 @@ package info.nightscout.androidaps.utils.stats import android.text.Spanned import android.util.LongSparseArray 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.database.AppRepository import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.HtmlHelper @@ -19,18 +19,20 @@ import javax.inject.Singleton class TirCalculator @Inject constructor( private val resourceHelper: ResourceHelper, private val profileFunction: ProfileFunction, - private val dateUtil: DateUtil -){ + private val dateUtil: DateUtil, + private val repository: AppRepository +) { + fun calculate(days: Long, lowMgdl: Double, highMgdl: Double): LongSparseArray { if (lowMgdl < 39) throw RuntimeException("Low below 39") if (lowMgdl > highMgdl) throw RuntimeException("Low > High") val startTime = MidnightTime.calc(DateUtil.now() - T.days(days).msecs()) val endTime = MidnightTime.calc(DateUtil.now()) - val bgReadings = MainApp.getDbHelper().getBgreadingsDataFromTime(startTime, endTime, true) + val bgReadings = repository.compatGetBgReadingsDataFromTime(startTime, endTime, true).blockingGet() val result = LongSparseArray() for (bg in bgReadings) { - val midnight = MidnightTime.calc(bg.date) + val midnight = MidnightTime.calc(bg.timestamp) var tir = result[midnight] if (tir == null) { tir = TIR(midnight, lowMgdl, highMgdl) diff --git a/app/src/main/java/info/nightscout/androidaps/utils/wizard/QuickWizardEntry.kt b/app/src/main/java/info/nightscout/androidaps/utils/wizard/QuickWizardEntry.kt index 44fb0cf8db..abfe8b4bd9 100644 --- a/app/src/main/java/info/nightscout/androidaps/utils/wizard/QuickWizardEntry.kt +++ b/app/src/main/java/info/nightscout/androidaps/utils/wizard/QuickWizardEntry.kt @@ -3,10 +3,10 @@ package info.nightscout.androidaps.utils.wizard import dagger.android.HasAndroidInjector import info.nightscout.androidaps.R import info.nightscout.androidaps.data.Profile -import info.nightscout.androidaps.db.BgReading +import info.nightscout.androidaps.database.entities.GlucoseValue +import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin -import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin @@ -14,6 +14,7 @@ import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.JsonHelper.safeGetInt import info.nightscout.androidaps.utils.JsonHelper.safeGetString import info.nightscout.androidaps.utils.sharedPreferences.SP +import info.nightscout.androidaps.utils.valueToUnits import org.json.JSONException import org.json.JSONObject import java.util.* @@ -71,7 +72,7 @@ class QuickWizardEntry @Inject constructor(private val injector: HasAndroidInjec fun isActive(): Boolean = Profile.secondsFromMidnight() >= validFrom() && Profile.secondsFromMidnight() <= validTo() - fun doCalc(profile: Profile, profileName: String, lastBG: BgReading, _synchronized: Boolean): BolusWizard { + fun doCalc(profile: Profile, profileName: String, lastBG: GlucoseValue, _synchronized: Boolean): BolusWizard { val tempTarget = treatmentsPlugin.tempTargetFromHistory //BG var bg = 0.0 diff --git a/core/build.gradle b/core/build.gradle index e0c69ddb78..9d71b4cec7 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -42,4 +42,8 @@ android { } +dependencies { + implementation project(':database') +} + apply from: 'core_dependencies.gradle' \ No newline at end of file diff --git a/core/core_dependencies.gradle b/core/core_dependencies.gradle index 93beb08a79..e2a48f1d88 100644 --- a/core/core_dependencies.gradle +++ b/core/core_dependencies.gradle @@ -42,7 +42,9 @@ dependencies { api 'com.google.firebase:firebase-database-ktx' //RxBus - api "io.reactivex.rxjava2:rxandroid:${rxandroid_version}" + api "io.reactivex.rxjava2:rxjava:$rxjava_version" + api "io.reactivex.rxjava2:rxkotlin:$rxkotlin_version" + api "io.reactivex.rxjava2:rxandroid:$rxandroid_version" api "org.apache.commons:commons-lang3:$commonslang3_version" //CryptoUtil diff --git a/core/src/main/java/info/nightscout/androidaps/db/BgReading.java b/core/src/main/java/info/nightscout/androidaps/db/BgReading.java deleted file mode 100644 index 5046aed701..0000000000 --- a/core/src/main/java/info/nightscout/androidaps/db/BgReading.java +++ /dev/null @@ -1,334 +0,0 @@ -package info.nightscout.androidaps.db; - -import androidx.annotation.NonNull; - -import com.j256.ormlite.field.DatabaseField; -import com.j256.ormlite.table.DatabaseTable; - -import java.util.Date; -import java.util.List; -import java.util.Objects; - -import javax.inject.Inject; - -import dagger.android.HasAndroidInjector; -import info.nightscout.androidaps.Constants; -import info.nightscout.androidaps.core.R; -import info.nightscout.androidaps.interfaces.DatabaseHelperInterface; -import info.nightscout.androidaps.logging.AAPSLogger; -import info.nightscout.androidaps.logging.LTag; -import info.nightscout.androidaps.interfaces.ProfileFunction; -import info.nightscout.androidaps.plugins.general.nsclient.data.NSSgv; -import info.nightscout.androidaps.plugins.general.overview.graphExtensions.DataPointWithLabelInterface; -import info.nightscout.androidaps.plugins.general.overview.graphExtensions.PointsWithLabelGraphSeries; -import info.nightscout.androidaps.utils.DateUtil; -import info.nightscout.androidaps.utils.DecimalFormatter; -import info.nightscout.androidaps.utils.DefaultValueHelper; -import info.nightscout.androidaps.utils.T; -import info.nightscout.androidaps.utils.resources.ResourceHelper; - -@DatabaseTable(tableName = "BgReadings") -public class BgReading implements DataPointWithLabelInterface { - @Inject public AAPSLogger aapsLogger; - @Inject public DefaultValueHelper defaultValueHelper; - @Inject public ProfileFunction profileFunction; - @Inject public ResourceHelper resourceHelper; - @Inject public DateUtil dateUtil; - - @DatabaseField(id = true) - public long date; - - @DatabaseField - public boolean isValid = true; - - @DatabaseField - public double value; - @DatabaseField - public String direction; - @DatabaseField - public double raw; - - @DatabaseField - public int source = Source.NONE; - @DatabaseField - public String _id = null; // NS _id - - public boolean isCOBPrediction = false; // true when drawing predictions as bg points (COB) - public boolean isaCOBPrediction = false; // true when drawing predictions as bg points (aCOB) - public boolean isIOBPrediction = false; // true when drawing predictions as bg points (IOB) - public boolean isUAMPrediction = false; // true when drawing predictions as bg points (UAM) - public boolean isZTPrediction = false; // true when drawing predictions as bg points (ZT) - - public BgReading() { - StaticInjector.Companion.getInstance().androidInjector().inject(this); - } - - public BgReading(HasAndroidInjector injector) { - injector.androidInjector().inject(this); - } - - public BgReading(HasAndroidInjector injector, NSSgv sgv) { - injector.androidInjector().inject(this); - date = sgv.getMills(); - value = sgv.getMgdl(); - raw = sgv.getFiltered() != null ? sgv.getFiltered() : value; - direction = sgv.getDirection(); - _id = sgv.getId(); - } - - public Double valueToUnits(String units) { - if (units.equals(Constants.MGDL)) - return value; - else - return value * Constants.MGDL_TO_MMOLL; - } - - public String valueToUnitsToString(String units) { - if (units.equals(Constants.MGDL)) return DecimalFormatter.to0Decimal(value); - else return DecimalFormatter.to1Decimal(value * Constants.MGDL_TO_MMOLL); - } - - public String directionToSymbol(DatabaseHelperInterface databaseHelper) { - String symbol = ""; - if (direction == null) - direction = calculateDirection(databaseHelper); - - if (direction.compareTo("DoubleDown") == 0) { - symbol = "\u21ca"; - } else if (direction.compareTo("SingleDown") == 0) { - symbol = "\u2193"; - } else if (direction.compareTo("FortyFiveDown") == 0) { - symbol = "\u2198"; - } else if (direction.compareTo("Flat") == 0) { - symbol = "\u2192"; - } else if (direction.compareTo("FortyFiveUp") == 0) { - symbol = "\u2197"; - } else if (direction.compareTo("SingleUp") == 0) { - symbol = "\u2191"; - } else if (direction.compareTo("DoubleUp") == 0) { - symbol = "\u21c8"; - } else if (isSlopeNameInvalid(direction)) { - symbol = "??"; - } - return symbol; - } - - - public int directionToIcon(DatabaseHelperInterface databaseHelper) { - int symbol = 0; - if (direction == null) - direction = calculateDirection(databaseHelper); - - if (direction.compareTo("DoubleDown") == 0) { - symbol = R.drawable.ic_doubledown; - } else if (direction.compareTo("SingleDown") == 0) { - symbol = R.drawable.ic_singledown; - } else if (direction.compareTo("FortyFiveDown") == 0) { - symbol = R.drawable.ic_fortyfivedown;; - } else if (direction.compareTo("Flat") == 0) { - symbol = R.drawable.ic_flat;; - } else if (direction.compareTo("FortyFiveUp") == 0) { - symbol = R.drawable.ic_fortyfiveup; - } else if (direction.compareTo("SingleUp") == 0) { - symbol = R.drawable.ic_singleup; - } else if (direction.compareTo("DoubleUp") == 0) { - symbol = R.drawable.ic_doubleup; - } else if (isSlopeNameInvalid(direction)) { - symbol = R.drawable.ic_invalid; - } - return symbol; - } - - private static boolean isSlopeNameInvalid(String direction) { - return direction.compareTo("NOT_COMPUTABLE") == 0 || - direction.compareTo("NOT COMPUTABLE") == 0 || - direction.compareTo("OUT_OF_RANGE") == 0 || - direction.compareTo("OUT OF RANGE") == 0 || - direction.compareTo("NONE") == 0 || - direction.compareTo("NotComputable") == 0; - } - - - @NonNull @Override - public String toString() { - return "BgReading{" + - "date=" + date + - ", date=" + dateUtil.dateAndTimeString(date) + - ", value=" + value + - ", direction=" + direction + - ", raw=" + raw + - '}'; - } - - public boolean isDataChanging(BgReading other) { - if (date != other.date) { - aapsLogger.debug(LTag.GLUCOSE, "Comparing different"); - return false; - } - if (value != other.value) - return true; - return false; - } - - public boolean isEqual(BgReading other) { - if (date != other.date) { - aapsLogger.debug(LTag.GLUCOSE, "Comparing different"); - return false; - } - if (value != other.value) - return false; - if (raw != other.raw) - return false; - if (!Objects.equals(direction, other.direction)) - return false; - if (!Objects.equals(_id, other._id)) - return false; - return true; - } - - public void copyFrom(BgReading other) { - if (date != other.date) { - aapsLogger.error(LTag.GLUCOSE, "Copying different"); - return; - } - value = other.value; - raw = other.raw; - direction = other.direction; - _id = other._id; - } - - public BgReading date(long date) { - this.date = date; - return this; - } - - public BgReading date(Date date) { - this.date = date.getTime(); - return this; - } - - public BgReading value(double value) { - this.value = value; - return this; - } - - // ------------------ DataPointWithLabelInterface ------------------ - @Override - public double getX() { - return date; - } - - @Override - public double getY() { - return valueToUnits(profileFunction.getUnits()); - } - - @Override - public void setY(double y) { - - } - - @Override - public String getLabel() { - return null; - } - - @Override - public long getDuration() { - return 0; - } - - @Override - public PointsWithLabelGraphSeries.Shape getShape() { - if (isPrediction()) - return PointsWithLabelGraphSeries.Shape.PREDICTION; - else - return PointsWithLabelGraphSeries.Shape.BG; - } - - @Override - public float getSize() { - return 1; - } - - @Override - public int getColor() { - String units = profileFunction.getUnits(); - Double lowLine = defaultValueHelper.determineLowLine(); - Double highLine = defaultValueHelper.determineHighLine(); - int color = resourceHelper.gc(R.color.inrange); - if (isPrediction()) - return getPredectionColor(); - else if (valueToUnits(units) < lowLine) - color = resourceHelper.gc(R.color.low); - else if (valueToUnits(units) > highLine) - color = resourceHelper.gc(R.color.high); - return color; - } - - public int getPredectionColor() { - if (isIOBPrediction) - return resourceHelper.gc(R.color.iob); - if (isCOBPrediction) - return resourceHelper.gc(R.color.cob); - if (isaCOBPrediction) - return 0x80FFFFFF & resourceHelper.gc(R.color.cob); - if (isUAMPrediction) - return resourceHelper.gc(R.color.uam); - if (isZTPrediction) - return resourceHelper.gc(R.color.zt); - return R.color.white; - } - - private boolean isPrediction() { - return isaCOBPrediction || isCOBPrediction || isIOBPrediction || isUAMPrediction || isZTPrediction; - } - - - // Copied from xDrip+ - String calculateDirection(DatabaseHelperInterface databasehelper) { - // Rework to get bgreaings from internal DB and calculate on that base - - List bgReadingsList = databasehelper.getAllBgreadingsDataFromTime(this.date - T.mins(10).msecs(), false); - if (bgReadingsList == null || bgReadingsList.size() < 2) - return "NONE"; - BgReading current = bgReadingsList.get(1); - BgReading previous = bgReadingsList.get(0); - - if (bgReadingsList.get(1).date < bgReadingsList.get(0).date) { - current = bgReadingsList.get(0); - previous = bgReadingsList.get(1); - } - - double slope; - - // Avoid division by 0 - if (current.date == previous.date) - slope = 0; - else - slope = (previous.value - current.value) / (previous.date - current.date); - - aapsLogger.error(LTag.GLUCOSE, "Slope is :" + slope + " delta " + (previous.value - current.value) + " date difference " + (current.date - previous.date)); - - double slope_by_minute = slope * 60000; - String arrow = "NONE"; - - if (slope_by_minute <= (-3.5)) { - arrow = "DoubleDown"; - } else if (slope_by_minute <= (-2)) { - arrow = "SingleDown"; - } else if (slope_by_minute <= (-1)) { - arrow = "FortyFiveDown"; - } else if (slope_by_minute <= (1)) { - arrow = "Flat"; - } else if (slope_by_minute <= (2)) { - arrow = "FortyFiveUp"; - } else if (slope_by_minute <= (3.5)) { - arrow = "SingleUp"; - } else if (slope_by_minute <= (40)) { - arrow = "DoubleUp"; - } - aapsLogger.error(LTag.GLUCOSE, "Direction set to: " + arrow); - return arrow; - } -} diff --git a/core/src/main/java/info/nightscout/androidaps/db/BgReading.kt b/core/src/main/java/info/nightscout/androidaps/db/BgReading.kt new file mode 100644 index 0000000000..dc233425a2 --- /dev/null +++ b/core/src/main/java/info/nightscout/androidaps/db/BgReading.kt @@ -0,0 +1,171 @@ +package info.nightscout.androidaps.db + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.Constants +import info.nightscout.androidaps.core.R +import info.nightscout.androidaps.database.AppRepository +import info.nightscout.androidaps.database.entities.GlucoseValue +import info.nightscout.androidaps.interfaces.ProfileFunction +import info.nightscout.androidaps.logging.AAPSLogger +import info.nightscout.androidaps.logging.LTag +import info.nightscout.androidaps.plugins.general.overview.graphExtensions.DataPointWithLabelInterface +import info.nightscout.androidaps.plugins.general.overview.graphExtensions.PointsWithLabelGraphSeries +import info.nightscout.androidaps.utils.DecimalFormatter +import info.nightscout.androidaps.utils.DefaultValueHelper +import info.nightscout.androidaps.utils.T +import info.nightscout.androidaps.utils.resources.ResourceHelper +import javax.inject.Inject + +class BgReading : DataPointWithLabelInterface { + @Inject lateinit var aapsLogger: AAPSLogger + @Inject lateinit var defaultValueHelper: DefaultValueHelper + @Inject lateinit var profileFunction: ProfileFunction + @Inject lateinit var resourceHelper: ResourceHelper + @Inject lateinit var repository: AppRepository + + var data: GlucoseValue + + // Compatibility functions + fun setDate(timeStamp: Long) { + data.timestamp = timeStamp + } + + fun getDate(): Long = data.timestamp + fun getValue(): Double = data.value + fun setValue(value: Double) { + data.value = value + } + + var isCOBPrediction = false // true when drawing predictions as bg points (COB) + var isaCOBPrediction = false // true when drawing predictions as bg points (aCOB) + var isIOBPrediction = false // true when drawing predictions as bg points (IOB) + var isUAMPrediction = false // true when drawing predictions as bg points (UAM) + var isZTPrediction = false // true when drawing predictions as bg points (ZT) + + @Deprecated("Create only with data") + constructor(injector: HasAndroidInjector) { + injector.androidInjector().inject(this) + data = GlucoseValue( + timestamp = 0, + utcOffset = 0, + raw = null, + value = 0.0, + trendArrow = GlucoseValue.TrendArrow.NONE, + noise = null, + sourceSensor = GlucoseValue.SourceSensor.UNKNOWN + ) + } + + constructor(injector: HasAndroidInjector, glucoseValue: GlucoseValue) { + injector.androidInjector().inject(this) + data = glucoseValue + } + + fun valueToUnits(units: String): Double = + if (units == Constants.MGDL) data.value else data.value * Constants.MGDL_TO_MMOLL + + fun valueToUnitsToString(units: String): String = + if (units == Constants.MGDL) DecimalFormatter.to0Decimal(data.value) + else DecimalFormatter.to1Decimal(data.value * Constants.MGDL_TO_MMOLL) + + fun directionToSymbol(): String = + if (data.trendArrow == GlucoseValue.TrendArrow.NONE) calculateDirection().symbol + else data.trendArrow.symbol + + fun date(date: Long): BgReading { + data.timestamp = date + return this + } + + fun value(value: Double): BgReading { + data.value = value + return this + } + + // ------------------ DataPointWithLabelInterface ------------------ + override fun getX(): Double { + return data.timestamp.toDouble() + } + + override fun getY(): Double { + return valueToUnits(profileFunction.getUnits()) + } + + override fun setY(y: Double) {} + override fun getLabel(): String? = null + override fun getDuration(): Long = 0 + override fun getShape(): PointsWithLabelGraphSeries.Shape = + if (isPrediction) PointsWithLabelGraphSeries.Shape.PREDICTION + else PointsWithLabelGraphSeries.Shape.BG + + override fun getSize(): Float = 1f + + override fun getColor(): Int { + val units = profileFunction.getUnits() + val lowLine = defaultValueHelper.determineLowLine() + val highLine = defaultValueHelper.determineHighLine() + return when { + isPrediction -> predictionColor + valueToUnits(units) < lowLine -> resourceHelper.gc(R.color.low) + valueToUnits(units) > highLine -> resourceHelper.gc(R.color.high) + else -> resourceHelper.gc(R.color.inrange) + } + } + + val predictionColor: Int + get() { + return when { + isIOBPrediction -> resourceHelper.gc(R.color.iob) + isCOBPrediction -> resourceHelper.gc(R.color.cob) + isaCOBPrediction -> -0x7f000001 and resourceHelper.gc(R.color.cob) + isUAMPrediction -> resourceHelper.gc(R.color.uam) + isZTPrediction -> resourceHelper.gc(R.color.zt) + else -> R.color.white + } + } + + private val isPrediction: Boolean + get() = isaCOBPrediction || isCOBPrediction || isIOBPrediction || isUAMPrediction || isZTPrediction + + // Copied from xDrip+ + fun calculateDirection(): GlucoseValue.TrendArrow { + // Rework to get bgreaings from internal DB and calculate on that base + val bgReadingsList = repository.compatGetBgReadingsDataFromTime(data.timestamp - T.mins(10).msecs(), false) + .blockingGet() + if (bgReadingsList == null || bgReadingsList.size < 2) return GlucoseValue.TrendArrow.NONE + var current = bgReadingsList[1] + var previous = bgReadingsList[0] + if (bgReadingsList[1].timestamp < bgReadingsList[0].timestamp) { + current = bgReadingsList[0] + previous = bgReadingsList[1] + } + val slope: Double + + // Avoid division by 0 + slope = if (current.timestamp == previous.timestamp) 0.0 else (previous.value - current.value) / (previous.timestamp - current.timestamp) + aapsLogger.error(LTag.GLUCOSE, "Slope is :" + slope + " delta " + (previous.value - current.value) + " date difference " + (current.timestamp - previous.timestamp)) + val slope_by_minute = slope * 60000 + var arrow = GlucoseValue.TrendArrow.NONE + if (slope_by_minute <= -3.5) { + arrow = GlucoseValue.TrendArrow.DOUBLE_DOWN + } else if (slope_by_minute <= -2) { + arrow = GlucoseValue.TrendArrow.SINGLE_DOWN + } else if (slope_by_minute <= -1) { + arrow = GlucoseValue.TrendArrow.FORTY_FIVE_DOWN + } else if (slope_by_minute <= 1) { + arrow = GlucoseValue.TrendArrow.FLAT + } else if (slope_by_minute <= 2) { + arrow = GlucoseValue.TrendArrow.FORTY_FIVE_UP + } else if (slope_by_minute <= 3.5) { + arrow = GlucoseValue.TrendArrow.SINGLE_UP + } else if (slope_by_minute <= 40) { + arrow = GlucoseValue.TrendArrow.DOUBLE_UP + } + aapsLogger.error(LTag.GLUCOSE, "Direction set to: $arrow") + return arrow + } + + private fun isSlopeNameInvalid(direction: String?): Boolean { + return direction!!.compareTo("NOT_COMPUTABLE") == 0 || direction.compareTo("NOT COMPUTABLE") == 0 || direction.compareTo("OUT_OF_RANGE") == 0 || direction.compareTo("OUT OF RANGE") == 0 || direction.compareTo("NONE") == 0 || direction.compareTo("NotComputable") == 0 + } +} \ No newline at end of file diff --git a/core/src/main/java/info/nightscout/androidaps/interfaces/DatabaseHelperInterface.kt b/core/src/main/java/info/nightscout/androidaps/interfaces/DatabaseHelperInterface.kt index aea3be7fee..d3edb553bb 100644 --- a/core/src/main/java/info/nightscout/androidaps/interfaces/DatabaseHelperInterface.kt +++ b/core/src/main/java/info/nightscout/androidaps/interfaces/DatabaseHelperInterface.kt @@ -5,7 +5,6 @@ import info.nightscout.androidaps.db.* interface DatabaseHelperInterface { - fun getAllBgreadingsDataFromTime(mills: Long, ascending: Boolean): List fun createOrUpdate(careportalEvent: CareportalEvent) fun createOrUpdate(record: DanaRHistoryRecord) fun createOrUpdate(record: OmnipodHistoryRecord) diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/aps/loop/APSResult.java b/core/src/main/java/info/nightscout/androidaps/plugins/aps/loop/APSResult.java index d02fa4d550..6d3f7edf87 100644 --- a/core/src/main/java/info/nightscout/androidaps/plugins/aps/loop/APSResult.java +++ b/core/src/main/java/info/nightscout/androidaps/plugins/aps/loop/APSResult.java @@ -2,6 +2,8 @@ package info.nightscout.androidaps.plugins.aps.loop; import android.text.Spanned; +import androidx.annotation.NonNull; + import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -107,7 +109,7 @@ public class APSResult { return String.format(resourceHelper.gs(R.string.carbsreq), carbsReq, carbsReqWithin); } - @Override + @NonNull @Override public String toString() { final PumpInterface pump = activePlugin.getActivePump(); if (isChangeRequested()) { @@ -131,7 +133,7 @@ public class APSResult { ret += ("SMB: " + DecimalFormatter.toPumpSupportedBolus(smb, activePlugin.getActivePump(), resourceHelper) + "\n"); if (isCarbsRequired()) { - ret += getCarbsRequiredText()+"\n"; + ret += getCarbsRequiredText() + "\n"; } // reason @@ -169,7 +171,7 @@ public class APSResult { ret += ("" + "SMB" + ": " + DecimalFormatter.toPumpSupportedBolus(smb, activePlugin.getActivePump(), resourceHelper) + "
"); if (isCarbsRequired()) { - ret += getCarbsRequiredText()+"
"; + ret += getCarbsRequiredText() + "
"; } // reason @@ -239,50 +241,50 @@ public class APSResult { if (predBGs.has("IOB")) { JSONArray iob = predBGs.getJSONArray("IOB"); for (int i = 1; i < iob.length(); i++) { - BgReading bg = new BgReading(); - bg.value = iob.getInt(i); - bg.date = startTime + i * 5 * 60 * 1000L; - bg.isIOBPrediction = true; + BgReading bg = new BgReading(injector); + bg.setValue(iob.getInt(i)); + bg.setDate(startTime + i * 5 * 60 * 1000L); + bg.setIOBPrediction(true); array.add(bg); } } if (predBGs.has("aCOB")) { JSONArray iob = predBGs.getJSONArray("aCOB"); for (int i = 1; i < iob.length(); i++) { - BgReading bg = new BgReading(); - bg.value = iob.getInt(i); - bg.date = startTime + i * 5 * 60 * 1000L; - bg.isaCOBPrediction = true; + BgReading bg = new BgReading(injector); + bg.setValue(iob.getInt(i)); + bg.setDate(startTime + i * 5 * 60 * 1000L); + bg.setIsaCOBPrediction(true); array.add(bg); } } if (predBGs.has("COB")) { JSONArray iob = predBGs.getJSONArray("COB"); for (int i = 1; i < iob.length(); i++) { - BgReading bg = new BgReading(); - bg.value = iob.getInt(i); - bg.date = startTime + i * 5 * 60 * 1000L; - bg.isCOBPrediction = true; + BgReading bg = new BgReading(injector); + bg.setValue(iob.getInt(i)); + bg.setDate(startTime + i * 5 * 60 * 1000L); + bg.setCOBPrediction(true); array.add(bg); } } if (predBGs.has("UAM")) { JSONArray iob = predBGs.getJSONArray("UAM"); for (int i = 1; i < iob.length(); i++) { - BgReading bg = new BgReading(); - bg.value = iob.getInt(i); - bg.date = startTime + i * 5 * 60 * 1000L; - bg.isUAMPrediction = true; + BgReading bg = new BgReading(injector); + bg.setValue(iob.getInt(i)); + bg.setDate(startTime + i * 5 * 60 * 1000L); + bg.setUAMPrediction(true); array.add(bg); } } if (predBGs.has("ZT")) { JSONArray iob = predBGs.getJSONArray("ZT"); for (int i = 1; i < iob.length(); i++) { - BgReading bg = new BgReading(); - bg.value = iob.getInt(i); - bg.date = startTime + i * 5 * 60 * 1000L; - bg.isZTPrediction = true; + BgReading bg = new BgReading(injector); + bg.setValue(iob.getInt(i)); + bg.setDate(startTime + i * 5 * 60 * 1000L); + bg.setZTPrediction(true); array.add(bg); } } diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSUpload.java b/core/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSUpload.java index 2f7ba95612..62039d9423 100644 --- a/core/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSUpload.java +++ b/core/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSUpload.java @@ -406,10 +406,10 @@ public class NSUpload { JSONObject data = new JSONObject(); try { data.put("device", source); - data.put("date", reading.date); - data.put("dateString", DateUtil.toISOString(reading.date)); - data.put("sgv", reading.value); - data.put("direction", reading.direction); + data.put("date", reading.getDate()); + data.put("dateString", DateUtil.toISOString(reading.getDate())); + data.put("sgv", reading.getValue()); + data.put("direction", reading.getData().getTrendArrow().getText()); data.put("type", "sgv"); } catch (JSONException e) { aapsLogger.error("Unhandled exception", e); @@ -461,46 +461,6 @@ public class NSUpload { } - public void sendToXdrip(BgReading bgReading) { - final String XDRIP_PLUS_NS_EMULATOR = "com.eveningoutpost.dexdrip.NS_EMULATOR"; - SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.US); - - try { - final JSONArray entriesBody = new JSONArray(); - JSONObject json = new JSONObject(); - json.put("sgv", bgReading.value); - if (bgReading.direction == null) { - json.put("direction", "NONE"); - } else { - json.put("direction", bgReading.direction); - } - json.put("device", "G5"); - json.put("type", "sgv"); - json.put("date", bgReading.date); - json.put("dateString", format.format(bgReading.date)); - entriesBody.put(json); - - final Bundle bundle = new Bundle(); - bundle.putString("action", "add"); - bundle.putString("collection", "entries"); - bundle.putString("data", entriesBody.toString()); - final Intent intent = new Intent(XDRIP_PLUS_NS_EMULATOR); - intent.putExtras(bundle).addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); - context.sendBroadcast(intent); - List receivers = context.getPackageManager().queryBroadcastReceivers(intent, 0); - if (receivers.size() < 1) { - aapsLogger.debug("No xDrip receivers found. "); - } else { - aapsLogger.debug(receivers.size() + " xDrip receivers"); - } - - - } catch (JSONException e) { - aapsLogger.error("Unhandled exception", e); - } - - } - public void createNSTreatment(JSONObject data, ProfileStore profileStore, ProfileFunction profileFunction, long eventTime) { if (JsonHelper.safeGetString(data, "eventType", "").equals(CareportalEvent.PROFILESWITCH)) { ProfileSwitch profileSwitch = profileFunction.prepareProfileSwitch( diff --git a/core/src/main/java/info/nightscout/androidaps/utils/extensions/TrendArrowIcon.kt b/core/src/main/java/info/nightscout/androidaps/utils/extensions/TrendArrowIcon.kt new file mode 100644 index 0000000000..51bc4e869f --- /dev/null +++ b/core/src/main/java/info/nightscout/androidaps/utils/extensions/TrendArrowIcon.kt @@ -0,0 +1,18 @@ +package info.nightscout.androidaps.utils.extensions + +import info.nightscout.androidaps.core.R +import info.nightscout.androidaps.database.entities.GlucoseValue + +fun GlucoseValue.TrendArrow.directionToIcon(): Int { + return when { + this == GlucoseValue.TrendArrow.DOUBLE_DOWN -> R.drawable.ic_doubledown + this == GlucoseValue.TrendArrow.SINGLE_DOWN -> R.drawable.ic_singledown + this == GlucoseValue.TrendArrow.FORTY_FIVE_DOWN -> R.drawable.ic_fortyfivedown + this == GlucoseValue.TrendArrow.FLAT -> R.drawable.ic_flat + this == GlucoseValue.TrendArrow.FORTY_FIVE_UP -> R.drawable.ic_fortyfiveup + this == GlucoseValue.TrendArrow.SINGLE_UP -> R.drawable.ic_singleup + this == GlucoseValue.TrendArrow.DOUBLE_UP -> R.drawable.ic_doubleup + this == GlucoseValue.TrendArrow.NONE -> R.drawable.ic_invalid + else -> R.drawable.ic_invalid + } +} diff --git a/dana/src/main/java/info/nightscout/androidaps/dana/activities/DanaUserOptionsActivity.kt b/dana/src/main/java/info/nightscout/androidaps/dana/activities/DanaUserOptionsActivity.kt index 0bf692cf40..fd1ee31fbf 100644 --- a/dana/src/main/java/info/nightscout/androidaps/dana/activities/DanaUserOptionsActivity.kt +++ b/dana/src/main/java/info/nightscout/androidaps/dana/activities/DanaUserOptionsActivity.kt @@ -18,7 +18,7 @@ import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.pump.common.defs.PumpType import info.nightscout.androidaps.queue.Callback import info.nightscout.androidaps.utils.FabricPrivacy -import info.nightscout.androidaps.utils.extensions.plusAssign +import io.reactivex.rxkotlin.plusAssign import info.nightscout.androidaps.utils.rx.AapsSchedulers import io.reactivex.disposables.CompositeDisposable import java.text.DecimalFormat diff --git a/database/src/main/java/info/nightscout/androidaps/database/AppRepository.kt b/database/src/main/java/info/nightscout/androidaps/database/AppRepository.kt index 0a13455b06..8bd48a5b54 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/AppRepository.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/AppRepository.kt @@ -106,8 +106,8 @@ class AppRepository @Inject internal constructor( database.temporaryTargetDao.getLastHistoryRecord(lastId) } - -inline fun Maybe.toWrappedSingle(): Single> = +@Suppress("USELESS_CAST") +inline fun Maybe.toWrappedSingle(): Single> = this.map { ValueWrapper.Existing(it) as ValueWrapper } .switchIfEmpty(Maybe.just(ValueWrapper.Absent())) .toSingle() From d93865997c5c3441029e989296b0c7dbb5323ad0 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Sun, 7 Feb 2021 11:14:32 +0100 Subject: [PATCH 2/8] update NS values from patched Dexcom app smoothing --- .../info/nightscout/androidaps/MainApp.java | 2 +- .../androidaps/plugins/source/DexcomPlugin.kt | 8 ++++++-- .../plugins/source/NSClientSourcePlugin.kt | 1 + .../plugins/general/nsclient/NSUpload.java | 18 ++++++++++++++++++ .../database/entities/GlucoseValue.kt | 18 ++++++++++-------- 5 files changed, 36 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/MainApp.java b/app/src/main/java/info/nightscout/androidaps/MainApp.java index 5deb4acd2d..56c8b99a0a 100644 --- a/app/src/main/java/info/nightscout/androidaps/MainApp.java +++ b/app/src/main/java/info/nightscout/androidaps/MainApp.java @@ -137,7 +137,7 @@ public class MainApp extends DaggerApplication { filter.addAction(Intents.ACTION_NEW_TREATMENT); filter.addAction(Intents.ACTION_CHANGED_TREATMENT); filter.addAction(Intents.ACTION_REMOVED_TREATMENT); - //filter.addAction(Intents.ACTION_NEW_SGV); + filter.addAction(Intents.ACTION_NEW_SGV); filter.addAction(Intents.ACTION_NEW_PROFILE); filter.addAction(Intents.ACTION_NEW_MBG); filter.addAction(Intents.ACTION_NEW_CAL); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/DexcomPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/DexcomPlugin.kt index 811fd3a353..28d4190415 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/DexcomPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/DexcomPlugin.kt @@ -136,8 +136,12 @@ class DexcomPlugin @Inject constructor( dexcomPlugin.disposable += repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, calibrations, sensorStartTime)).subscribe({ savedValues -> savedValues.forEach { broadcastToXDrip(it) - if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false)) - nsUpload.uploadBg(BgReading(injector, it), sourceSensor.text) + if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false)) { + if (it.interfaceIDs.nightscoutId != null) + nsUpload.updateBg(BgReading(injector, it), sourceSensor.text) + else + nsUpload.uploadBg(BgReading(injector, it), sourceSensor.text) + } } }, { aapsLogger.error(LTag.BGSOURCE, "Error while saving values from Dexcom App", it) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/NSClientSourcePlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/NSClientSourcePlugin.kt index 82dd4aa08e..635a615784 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/NSClientSourcePlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/NSClientSourcePlugin.kt @@ -107,6 +107,7 @@ class NSClientSourcePlugin @Inject constructor( noise = null, raw = if (sgv.filtered != null) sgv.filtered.toDouble() else sgv.mgdl.toDouble(), trendArrow = GlucoseValue.TrendArrow.fromString(sgv.direction), + nightscoutId = sgv.id, sourceSensor = GlucoseValue.SourceSensor.fromString(sgv.device) ) } diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSUpload.java b/core/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSUpload.java index 62039d9423..778ab361d3 100644 --- a/core/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSUpload.java +++ b/core/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSUpload.java @@ -417,6 +417,24 @@ public class NSUpload { uploadQueue.add(new DbRequest("dbAdd", "entries", data)); } + public void updateBg(BgReading reading, String source) { + JSONObject data = new JSONObject(); + try { + data.put("device", source); + data.put("date", reading.getDate()); + data.put("dateString", DateUtil.toISOString(reading.getDate())); + data.put("sgv", reading.getValue()); + data.put("direction", reading.getData().getTrendArrow().getText()); + data.put("type", "sgv"); + if (reading.getData().getInterfaceIDs_backing() != null) + if (reading.getData().getInterfaceIDs_backing().getNightscoutId() != null) { + uploadQueue.add(new DbRequest("dbUpdate", "entries", reading.getData().getInterfaceIDs_backing().getNightscoutId(), data)); + } + } catch (JSONException e) { + aapsLogger.error("Unhandled exception", e); + } + } + public void uploadAppStart() { if (sp.getBoolean(R.string.key_ns_logappstartedevent, true)) { JSONObject data = new JSONObject(); diff --git a/database/src/main/java/info/nightscout/androidaps/database/entities/GlucoseValue.kt b/database/src/main/java/info/nightscout/androidaps/database/entities/GlucoseValue.kt index 55716ba4ac..74ad9b5ceb 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/entities/GlucoseValue.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/entities/GlucoseValue.kt @@ -34,13 +34,14 @@ data class GlucoseValue( fun contentEqualsTo(other: GlucoseValue): Boolean = timestamp == other.timestamp && - utcOffset == other.utcOffset && - raw == other.raw && - value == other.value && - trendArrow == other.trendArrow && - noise == other.noise && - sourceSensor == other.sourceSensor && - isValid == other.isValid + utcOffset == other.utcOffset && + raw == other.raw && + value == other.value && + trendArrow == other.trendArrow && + noise == other.noise && + sourceSensor == other.sourceSensor && + isValid == other.isValid && + interfaceIDs?.nightscoutId == other.interfaceIDs?.nightscoutId fun isRecordDeleted(other: GlucoseValue): Boolean = isValid && !other.isValid @@ -94,7 +95,8 @@ data class GlucoseValue( ; companion object { - fun fromString(source : String?) = values().firstOrNull {it.text == source} ?: UNKNOWN + + fun fromString(source: String?) = values().firstOrNull { it.text == source } ?: UNKNOWN } } } \ No newline at end of file From 887819edf4166bb2c0de9fc890f406d3215df985 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Mon, 8 Feb 2021 10:05:21 +0100 Subject: [PATCH 3/8] eliminate BgReading::class in favor of GlucoseValue::class --- app/jacoco.exec | Bin 161640 -> 312383 bytes .../androidaps/db/DatabaseHelper.java | 18 +- .../dependencyInjection/DataClassesModule.kt | 6 +- .../androidaps/dialogs/WizardDialog.kt | 10 +- .../plugins/aps/loop/LoopPlugin.java | 58 +-- .../openAPSAMA/DetermineBasalResultAMA.java | 77 --- .../aps/openAPSAMA/DetermineBasalResultAMA.kt | 67 +++ .../aps/openAPSAMA/OpenAPSAMAPlugin.java | 16 +- .../openAPSSMB/DetermineBasalResultSMB.java | 97 ---- .../aps/openAPSSMB/DetermineBasalResultSMB.kt | 80 ++++ .../aps/openAPSSMB/OpenAPSSMBPlugin.java | 18 +- .../general/nsclient/data/NSDeviceStatus.java | 6 +- .../general/openhumans/OpenHumansUploader.kt | 19 +- .../general/overview/graphData/GraphData.kt | 27 +- .../general/tidepool/comm/UploadChunk.kt | 7 +- .../tidepool/elements/SensorGlucoseElement.kt | 12 +- .../wearintegration/WatchUpdaterService.java | 12 +- .../iob/iobCobCalculator/GlucoseStatus.java | 1 - .../IobCobCalculatorPlugin.java | 4 +- .../iobCobCalculator/IobCobOref1Thread.java | 6 +- .../iob/iobCobCalculator/IobCobThread.java | 6 +- .../androidaps/plugins/source/DexcomPlugin.kt | 5 +- .../plugins/source/EversensePlugin.kt | 3 +- .../androidaps/plugins/source/GlimpPlugin.kt | 3 +- .../androidaps/plugins/source/MM640gPlugin.kt | 3 +- .../plugins/source/NSClientSourcePlugin.kt | 5 +- .../plugins/source/PoctechPlugin.kt | 3 +- .../plugins/source/RandomBgPlugin.kt | 3 +- .../androidaps/plugins/source/TomatoPlugin.kt | 3 +- .../androidaps/utils/GlucoseValueUtils.kt | 6 - .../nightscout/androidaps/db/BgReadingTest.kt | 185 -------- .../plugins/aps/loop/APSResultTest.kt | 2 +- .../automation/triggers/TriggerBgTest.kt | 16 +- .../automation/triggers/TriggerDeltaTest.kt | 23 +- .../automation/triggers/TriggerTestBase.kt | 7 +- .../SmsCommunicatorPluginTest.kt | 24 +- .../iob/iobCobCalculator/GlucoseStatusTest.kt | 99 ++-- .../IobCobCalculatorPluginTest.kt | 367 ++++++--------- .../core/di/CoreDataClassesModule.kt | 3 +- .../androidaps/data/GlucoseValueDataPoint.kt | 78 ++++ .../nightscout/androidaps/db/BgReading.kt | 171 ------- .../plugins/aps/loop/APSResult.java | 438 ------------------ .../androidaps/plugins/aps/loop/APSResult.kt | 399 ++++++++++++++++ .../plugins/general/nsclient/NSUpload.java | 39 +- .../database/entities/GlucoseValue.kt | 10 +- 45 files changed, 967 insertions(+), 1475 deletions(-) delete mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/DetermineBasalResultAMA.java create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/DetermineBasalResultAMA.kt delete mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/DetermineBasalResultSMB.java create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/DetermineBasalResultSMB.kt delete mode 100644 app/src/test/java/info/nightscout/androidaps/db/BgReadingTest.kt create mode 100644 core/src/main/java/info/nightscout/androidaps/data/GlucoseValueDataPoint.kt delete mode 100644 core/src/main/java/info/nightscout/androidaps/db/BgReading.kt delete mode 100644 core/src/main/java/info/nightscout/androidaps/plugins/aps/loop/APSResult.java create mode 100644 core/src/main/java/info/nightscout/androidaps/plugins/aps/loop/APSResult.kt diff --git a/app/jacoco.exec b/app/jacoco.exec index 97d8cc2389170a0c67c5b221bb980367f2a03daa..de458659e8a6aa56fe658f1aa2eca08a4b9e0487 100644 GIT binary patch delta 11914 zcmeHN3sh5Qwmy3&BoHGZsI@*2oZ4DDK9WEP$U9L~1VRu|L6Ap4tF>a)Y9A_k+ws+k zc(fZ|XtlS~ajIgq#>!PuM@JnMYFo9nR#2z*wiRh@t1W2mKIfovZ|AOcA2VysOg*l3 zLSoiA=l{OFzrFYO=Zi+a{R=ykz63jQ!pujYrY1leAha88?q>;iTin)Svmn6CIa#i? z@@tM}4Y_`V3d))dPI70$3$*4mM3Lz-s8x4vH`CM2kVNsLpqNf2LLqH@1LlzTGH5j| z20{4Z76nA&FnVK7WQ}TAqb=3Ll7r$vh7n^!weAPVvKFtY_?1&;cF% z0-mFimEgu%Ui!uhc1oBE11ah?7>&DUlXEj9Qoxtsw{jjnDW)d+J**d^1wNu%yiwBY z-6Njj6Vc|=?7i;wq4y zuYC=J#b4bROjU@lVgnMS!f?tw4`V5RAVh*dxAVb8!Ad3b{Qjh>YvNMl~BjNBgS4fGUAb48)hj8iSe! zFM%|A#s#T#@&>~^vl!l_C!;anH>q;*x|Fvk4-xkVO{JjmFxvNKb;idfx=SE#Ulb(P z_x7dQ8Q6*b{X6JFxfl8Ajz=@RjpO;|Arvd>-A?g&mqBc}90L*5xC2Jh{ujWPHqO8d zD!K__#smVIh$ZLojwdBY26!8raNj}^~13&?{D3e@`A->FZUAHKi`SA zMMH&HGfz#weiMqw>_8VSdlPokdwWKV(=+VVTjl?|JrNW|^^k;5s^0eRwp>3*Ky{vJYr z{Lb^2l2aj)PN^`%Ghqun2AW$vJ~?xKm*{*vf%-hl)HZH~Wn$wW{i%K!>ZxKIWVG`J z8~<_u`a`MbWEFgdV$;F^y1oN$(A*3dD!!vn=`QI)VT8HR8d@Bwgu%0aRKj4}eyW?q zsVi|#X^9Xk>w>n7A??nTz5WI)fluY^7pIPj7W3BlkUfiuWvuelv(E1_(6Sgv7yH<@ zQep{|Qcygn%JL*gpkL=gE~OJ#DI^ws{92ey>ClS@x^|+c&p{3k>Mbxub!(r2oU37zpCG&^2v_lnKfSNUFmapcOC$EO1f&)~ zgc#qsvy!_fG@L$L*TNWD77MXpqRB2sa=8xA5Pr`Y%~3Q0ytI8i*u{|kI;xxi8I)cR zGsXQ~&Gb_}r%<2);#6L5FztIC@~QJA77b^6j26?DbdaHp3=0dl7P`X~C`VQ+P##@D zV`jsj6ac;Qv7bK6gaVq<%$maD>ZaavVK6o9;s*+}o<8bSWFsJ)g}3BT(&Fme!<~AY1gF zwaOHTm(H2#s~C*zpl9G~LS_7wQ?!O$skoW)9dJ#eV1rn)LqobxCm|YR zkx~vZJnyGq7{xB-VEH*8p^;(vkyf{@HMFlNe4Ly>2jVeOiE5UCEQyCd(pw+!8jO)R z)OXtAj|X&fYQGf^_ytqdhoBR8hXl}#Xl6%_@vpByv|1Sn^XqQCO#wMz@*^qR4PlZ&Q5O+hD+3I4p6`pgPjZ4Vyli$eaPZ4*TL_a)^?Ud zoaUZkjbf#(ybE=L9NceDg`Ya-@vZIxe0L>HrQqo~9NGbGtAG?V2;};h+mH1_aFA-j z3j$5u!^tKi8KA;`I8~>#22G7HgVH{Q_H>#RrWF*UCV6?mLeJSzqItMnp~Y+EfuS#} z7A{=q3w-Y;>C}4E+-`%UQ1|__-FANV{T9!mnX{YE_aMCwzALF!1r6B86+srMDc|yw zq!&Rf-U2FdffK*>(g7C?yvtG&-CoZMl~NCj$Xv%YT9zoLWh=))=|&hu-z|msd)$Ou z!wL%`@(UDhrp=IFa|fLy(=r$-`rG~J(bMpr+~BpB0@BY%i1rnPw_01g!5?yQUSGW0R(BG!-8!!A7cM7I&_s^@ z{tduUByQJ7iN7mS#NS-tE{+I`U^SKcYo|^Dc+xRSsAh4Jh4cMMtQ03qG-(T@O0joR zg=5-O*!Na*r=WI1tnZQO!DpS54Clmo=WJrti;trhXv#unV8f^2Lzl{#_r*~#M=EZ< zaX;)lU>g}aRRTSRN?!xL_(Fdpy*rv~i#d%?ccyUR%j$wdNhXo|^fWod;0|pQVVv0G zv{p%`wcRjQl_wx2*Kk)gZW?MNJi@6s4rUYU!a{0}hsj(HL*!PXeGiPIQz>ZUPR2~L zzXWTbpk}z`BU;h6LlUdYq_*5aPj^JSY7#fsJvOp*ctPxWBSGDPzbyt|NulQ&z$q8e z0<+a*4UJGlJICCt;P}c%3XW1*(h)1iz~-LZnS4D8tGN-%)CF@NA5r91@Xe!2wbswme0S1d0 zsRR2VRyDW9Kpf{Ih#`s=$6eFVfvX%r5#5bhert*_Da)q(%eZ4tiN}}p3;d{KN-(C~#aQECMC2I?jN(b|Vlm_0oX+Xe?1CZU!M?Fn zeir6S`DmB2 zu$^0}(TRg-9e^K6tE1z2IEQ|Gj5$B?E_Y$qn!V(|i=(?;0mg{6hc&F9+@P;G46zBG^q~41+5x4askAVe}7EA%ez{sL_0HaI`%{w^Cxh4jy{Fm0Otl% z{Q~a920V>U_1@dw7ihLWI-H@_AH*G zygc-k*)&H+6q?P&3Y)q8KT+5`R@sKlu*WzUna$@_3%n|&6Z=Cx+SNBzf-h~zWDMAW zaM1ML40Yu${_9R}9ELY<(y+%dQ>srqlpJAxm|7<-ccUHoG6S-}?&;kJA5p;}8r~Nd z(XuDer=y++Pzm-E(uu1Y(-J_}`r>7Zb>d)8Z9j}axJkYyzVe#A9NMLMYEmtd$A)$a zjCYeHo|c~EbU9(hWA~6DMrIJ@gyKb|4V8N$^jF3M24-km|D~wN5*ljFZ`HL6om-(f z*`^ugg~w2BIInAWGcWU4U?^w&kpOlD z?%OXst2!ld-%35d;0fd48K{-|Q6+qnzl8qu`CyFhpc0ydn$0bH_}Vy&dUG?`pr`C|Mn2r!OQ(=iny#!D@SKoku9{y9M;;Grc75TXoylu z%XKH7k_t+zOYnLo-mUNAWs& z6tYWWP>kxvoE}u3#P7Ofa0yuxhzpE0To?6{2PYpacC_~yzH#3@9HZPhCCDu;E*P(H z#nNKGt16>pC?ZVZ1)(O3S%x5Y%^?Mft2tB>!9nr(C>DIfL%2;bOk^nf9)Tf}%YY|; z=sDwwgY5_`(34EVa3g)%1^fXi|6xwqiz@IzuN<$#8JO3*U?R6at_$4FasoNfdxL)J zCDAVVDIBdf>eG=cBrCCloPL-p+bh&387q{@)tk(MD2cB$daxnHrPR^J)k?|0@Q0+X zLoaYKZ4sE;)o>BJ?N zXF;kN!aV?!n9SX7tm0TMIz5)#T?V&Y@;JDUr}$@a1zw#^O^5h8^Z&p;uS~n7N%!k32f=H!zYzaL z-D7SkPoOSLXj@*(-P~ZAvba%I=>0Q?oy;tE5H7iA@(GgYp#kIZm{d(aQj{q0Nq(&4 z<1k$9Rek5BHOJvqcwP?0*24EHEmq+mxy9LWg4M+GG`f6$7KuURKZQ}eRp^-)5 z#SvB+*p)#q%C8maSr5!;9{K-wW^`zAAs0Gxu>xh6u?mzkvfK2V56sWMqWS4AuoM=B zS(JU070o;fvJX_T`lkox=ih<(Y0Gy<7Mm?HCo8_Ws&I4EPm+~*$&uqd@VfikT;x9x ze1B%b@mySA&O0#dyd~0z(Xj6BIQDPchS#_CNo9-ecvo)et3=3^4YqIZK)JI2mA07& zF==-jd_~x9`JWnR*B_DHX$Sj3t-gS4DL%DDv9V<{X+$vl-T%SbDNs; zz~lJadK_*`v6W|gMe69(VugY$GydU?Vw=^PZw&u<?_u+3*)PH}vP{PWRor)R&U9lX?=${vT$MTm_45 zHg{N&Tan<3Yv0LAwR%AHFVJSTgq!liLqiqcY*oK`3KXGx+Uy5C*xmbw+1-nb2rIUR rx)t4D)u~cpGt$$B&0p;9UU7lh6c&*$L$b getDaoBgReadings() throws SQLException { - return getDao(BgReading.class); - } - private Dao getDaoDanaRHistory() throws SQLException { return getDao(DanaRHistoryRecord.class); } @@ -373,14 +369,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { aapsLogger.debug(LTag.DATABASE, "Rounding " + date + " to " + rounded); return rounded; } - public List getAllBgReadings() { - try { - return getDaoBgReadings().queryForAll(); - } catch (SQLException e) { - aapsLogger.error("Unhandled exception", e); - } - return Collections.emptyList(); - } // ------------------- TDD handling ----------------------- public void createOrUpdateTDD(TDD tdd) { @@ -1531,6 +1519,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { } return Collections.emptyList(); } + @Nullable private ProfileSwitch getLastProfileSwitchWithoutDuration() { try { @@ -1969,8 +1958,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { public long getCountOfAllRows() { try { - return getDaoBgReadings().countOf() - + getDaoCareportalEvents().countOf() + return getDaoCareportalEvents().countOf() + getDaoExtendedBolus().countOf() + getDaoCareportalEvents().countOf() + getDaoProfileSwitch().countOf() diff --git a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/DataClassesModule.kt b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/DataClassesModule.kt index c63e70ace8..98f15e668c 100644 --- a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/DataClassesModule.kt +++ b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/DataClassesModule.kt @@ -2,11 +2,9 @@ package info.nightscout.androidaps.dependencyInjection import dagger.Module import dagger.android.ContributesAndroidInjector -import info.nightscout.androidaps.data.Profile -import info.nightscout.androidaps.db.* -import info.nightscout.androidaps.interfaces.ProfileStore -import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus +import info.nightscout.androidaps.db.DatabaseHelper import info.nightscout.androidaps.plugins.general.food.FoodService +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus import info.nightscout.androidaps.plugins.treatments.TreatmentService import info.nightscout.androidaps.utils.wizard.BolusWizard import info.nightscout.androidaps.utils.wizard.QuickWizardEntry diff --git a/app/src/main/java/info/nightscout/androidaps/dialogs/WizardDialog.kt b/app/src/main/java/info/nightscout/androidaps/dialogs/WizardDialog.kt index 81413ab08f..543e38ddcb 100644 --- a/app/src/main/java/info/nightscout/androidaps/dialogs/WizardDialog.kt +++ b/app/src/main/java/info/nightscout/androidaps/dialogs/WizardDialog.kt @@ -20,7 +20,6 @@ import info.nightscout.androidaps.MainApp import info.nightscout.androidaps.R import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.databinding.DialogWizardBinding -import info.nightscout.androidaps.db.BgReading import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.Constraint import info.nightscout.androidaps.interfaces.ProfileFunction @@ -236,6 +235,10 @@ class WizardDialog : DaggerDialogFragment() { binding.cobcheckbox.isChecked = sp.getBoolean(R.string.key_wizard_include_cob, false) } + private fun valueToUnitsToString(value: Double, units: String): String = + if (units == Constants.MGDL) DecimalFormatter.to0Decimal(value) + else DecimalFormatter.to1Decimal(value * Constants.MGDL_TO_MMOLL) + private fun initDialog() { val profile = profileFunction.getProfile() val profileStore = activePlugin.activeProfileInterface.profile @@ -246,8 +249,7 @@ class WizardDialog : DaggerDialogFragment() { return } - val profileList: ArrayList - profileList = profileStore.getProfileList() + val profileList: ArrayList = profileStore.getProfileList() profileList.add(0, resourceHelper.gs(R.string.active)) context?.let { context -> val adapter = ArrayAdapter(context, R.layout.spinner_centered, profileList) @@ -335,7 +337,7 @@ class WizardDialog : DaggerDialogFragment() { binding.notes.text.toString(), carbTime) wizard?.let { wizard -> - binding.bg.text = String.format(resourceHelper.gs(R.string.format_bg_isf), BgReading(injector).value(Profile.toMgdl(bg, profileFunction.getUnits())).valueToUnitsToString(profileFunction.getUnits()), wizard.sens) + binding.bg.text = String.format(resourceHelper.gs(R.string.format_bg_isf), valueToUnitsToString(Profile.toMgdl(bg, profileFunction.getUnits()), profileFunction.getUnits()), wizard.sens) binding.bginsulin.text = resourceHelper.gs(R.string.formatinsulinunits, wizard.insulinFromBG) binding.carbs.text = String.format(resourceHelper.gs(R.string.format_carbs_ic), carbs.toDouble(), wizard.ic) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.java index 4604c31db6..ffb93ecc9f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.java @@ -392,30 +392,30 @@ public class LoopPlugin extends PluginBase implements LoopInterface { // Prepare for pumps using % basals if (pump.getPumpDescription().tempBasalStyle == PumpDescription.PERCENT && allowPercentage()) { - result.usePercent = true; + result.setUsePercent(true); } - result.percent = (int) (result.rate / profile.getBasal() * 100); + result.setPercent((int) (result.getRate() / profile.getBasal() * 100)); // check rate for constraints final APSResult resultAfterConstraints = result.newAndClone(injector); - resultAfterConstraints.rateConstraint = new Constraint<>(resultAfterConstraints.rate); - resultAfterConstraints.rate = constraintChecker.applyBasalConstraints(resultAfterConstraints.rateConstraint, profile).value(); + resultAfterConstraints.setRateConstraint(new Constraint<>(resultAfterConstraints.getRate())); + resultAfterConstraints.setRate(constraintChecker.applyBasalConstraints(resultAfterConstraints.getRateConstraint(), profile).value()); - resultAfterConstraints.percentConstraint = new Constraint<>(resultAfterConstraints.percent); - resultAfterConstraints.percent = constraintChecker.applyBasalPercentConstraints(resultAfterConstraints.percentConstraint, profile).value(); + resultAfterConstraints.setPercentConstraint(new Constraint<>(resultAfterConstraints.getPercent())); + resultAfterConstraints.setPercent(constraintChecker.applyBasalPercentConstraints(resultAfterConstraints.getPercentConstraint(), profile).value()); - resultAfterConstraints.smbConstraint = new Constraint<>(resultAfterConstraints.smb); - resultAfterConstraints.smb = constraintChecker.applyBolusConstraints(resultAfterConstraints.smbConstraint).value(); + resultAfterConstraints.setSmbConstraint(new Constraint<>(resultAfterConstraints.getSmb())); + resultAfterConstraints.setSmb(constraintChecker.applyBolusConstraints(resultAfterConstraints.getSmbConstraint()).value()); // safety check for multiple SMBs long lastBolusTime = treatmentsPlugin.getLastBolusTime(); if (lastBolusTime != 0 && lastBolusTime + T.mins(3).msecs() > System.currentTimeMillis()) { getAapsLogger().debug(LTag.APS, "SMB requested but still in 3 min interval"); - resultAfterConstraints.smb = 0; + resultAfterConstraints.setSmb(0); } if (lastRun != null && lastRun.getConstraintsProcessed() != null) { - prevCarbsreq = lastRun.getConstraintsProcessed().carbsReq; + prevCarbsreq = lastRun.getConstraintsProcessed().getCarbsReq(); } if (lastRun == null) lastRun = new LastRun(); @@ -449,7 +449,7 @@ public class LoopPlugin extends PluginBase implements LoopInterface { if (closedLoopEnabled.value()) { if (allowNotification) { if (resultAfterConstraints.isCarbsRequired() - && resultAfterConstraints.carbsReq >= sp.getInt(R.string.key_smb_enable_carbs_suggestions_threshold, 0) + && resultAfterConstraints.getCarbsReq() >= sp.getInt(R.string.key_smb_enable_carbs_suggestions_threshold, 0) && carbsSuggestionsSuspendedUntil < System.currentTimeMillis() && !treatmentTimethreshold(-15)) { if (sp.getBoolean(R.string.key_enable_carbs_required_alert_local, true) && !sp.getBoolean(R.string.key_raise_notifications_as_android_notifications, true)) { @@ -519,9 +519,9 @@ public class LoopPlugin extends PluginBase implements LoopInterface { && !commandQueue.isRunning(Command.CommandType.BOLUS)) { final PumpEnactResult waiting = new PumpEnactResult(getInjector()); waiting.queued = true; - if (resultAfterConstraints.tempBasalRequested) + if (resultAfterConstraints.getTempBasalRequested()) lastRun.setTbrSetByPump(waiting); - if (resultAfterConstraints.bolusRequested) + if (resultAfterConstraints.getBolusRequested()) lastRun.setSmbSetByPump(waiting); rxBus.send(new EventLoopUpdateGui()); fabricPrivacy.logCustom("APSRequest"); @@ -653,7 +653,7 @@ public class LoopPlugin extends PluginBase implements LoopInterface { private void applyTBRRequest(APSResult request, Profile profile, Callback callback) { - if (!request.tempBasalRequested) { + if (!request.getTempBasalRequested()) { if (callback != null) { callback.result(new PumpEnactResult(getInjector()).enacted(false).success(true).comment(resourceHelper.gs(R.string.nochangerequested))).run(); } @@ -682,48 +682,48 @@ public class LoopPlugin extends PluginBase implements LoopInterface { long now = System.currentTimeMillis(); TemporaryBasal activeTemp = treatmentsPlugin.getTempBasalFromHistory(now); - if (request.usePercent && allowPercentage()) { - if (request.percent == 100 && request.duration == 0) { + if (request.getUsePercent() && allowPercentage()) { + if (request.getPercent() == 100 && request.getDuration() == 0) { if (activeTemp != null) { getAapsLogger().debug(LTag.APS, "applyAPSRequest: cancelTempBasal()"); commandQueue.cancelTempBasal(false, callback); } else { getAapsLogger().debug(LTag.APS, "applyAPSRequest: Basal set correctly"); if (callback != null) { - callback.result(new PumpEnactResult(getInjector()).percent(request.percent).duration(0) + callback.result(new PumpEnactResult(getInjector()).percent(request.getPercent()).duration(0) .enacted(false).success(true).comment(resourceHelper.gs(R.string.basal_set_correctly))).run(); } } } else if (activeTemp != null && activeTemp.getPlannedRemainingMinutes() > 5 - && request.duration - activeTemp.getPlannedRemainingMinutes() < 30 - && request.percent == activeTemp.percentRate) { + && request.getDuration() - activeTemp.getPlannedRemainingMinutes() < 30 + && request.getPercent() == activeTemp.percentRate) { getAapsLogger().debug(LTag.APS, "applyAPSRequest: Temp basal set correctly"); if (callback != null) { - callback.result(new PumpEnactResult(getInjector()).percent(request.percent) + callback.result(new PumpEnactResult(getInjector()).percent(request.getPercent()) .enacted(false).success(true).duration(activeTemp.getPlannedRemainingMinutes()) .comment(resourceHelper.gs(R.string.let_temp_basal_run))).run(); } } else { getAapsLogger().debug(LTag.APS, "applyAPSRequest: tempBasalPercent()"); - commandQueue.tempBasalPercent(request.percent, request.duration, false, profile, callback); + commandQueue.tempBasalPercent(request.getPercent(), request.getDuration(), false, profile, callback); } } else { - if ((request.rate == 0 && request.duration == 0) || Math.abs(request.rate - pump.getBaseBasalRate()) < pump.getPumpDescription().basalStep) { + if ((request.getRate() == 0 && request.getDuration() == 0) || Math.abs(request.getRate() - pump.getBaseBasalRate()) < pump.getPumpDescription().basalStep) { if (activeTemp != null) { getAapsLogger().debug(LTag.APS, "applyAPSRequest: cancelTempBasal()"); commandQueue.cancelTempBasal(false, callback); } else { getAapsLogger().debug(LTag.APS, "applyAPSRequest: Basal set correctly"); if (callback != null) { - callback.result(new PumpEnactResult(getInjector()).absolute(request.rate).duration(0) + callback.result(new PumpEnactResult(getInjector()).absolute(request.getRate()).duration(0) .enacted(false).success(true).comment(resourceHelper.gs(R.string.basal_set_correctly))).run(); } } } else if (activeTemp != null && activeTemp.getPlannedRemainingMinutes() > 5 - && request.duration - activeTemp.getPlannedRemainingMinutes() < 30 - && Math.abs(request.rate - activeTemp.tempBasalConvertedToAbsolute(now, profile)) < pump.getPumpDescription().basalStep) { + && request.getDuration() - activeTemp.getPlannedRemainingMinutes() < 30 + && Math.abs(request.getRate() - activeTemp.tempBasalConvertedToAbsolute(now, profile)) < pump.getPumpDescription().basalStep) { getAapsLogger().debug(LTag.APS, "applyAPSRequest: Temp basal set correctly"); if (callback != null) { callback.result(new PumpEnactResult(getInjector()).absolute(activeTemp.tempBasalConvertedToAbsolute(now, profile)) @@ -732,13 +732,13 @@ public class LoopPlugin extends PluginBase implements LoopInterface { } } else { getAapsLogger().debug(LTag.APS, "applyAPSRequest: setTempBasalAbsolute()"); - commandQueue.tempBasalAbsolute(request.rate, request.duration, false, profile, callback); + commandQueue.tempBasalAbsolute(request.getRate(), request.getDuration(), false, profile, callback); } } } private void applySMBRequest(APSResult request, Callback callback) { - if (!request.bolusRequested) { + if (!request.getBolusRequested()) { return; } @@ -777,10 +777,10 @@ public class LoopPlugin extends PluginBase implements LoopInterface { DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); detailedBolusInfo.lastKnownBolusTime = treatmentsPlugin.getLastBolusTime(); detailedBolusInfo.eventType = CareportalEvent.CORRECTIONBOLUS; - detailedBolusInfo.insulin = request.smb; + detailedBolusInfo.insulin = request.getSmb(); detailedBolusInfo.isSMB = true; detailedBolusInfo.source = Source.USER; - detailedBolusInfo.deliverAt = request.deliverAt; + detailedBolusInfo.deliverAt = request.getDeliverAt(); getAapsLogger().debug(LTag.APS, "applyAPSRequest: bolus()"); commandQueue.bolus(detailedBolusInfo, callback); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/DetermineBasalResultAMA.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/DetermineBasalResultAMA.java deleted file mode 100644 index 0bf4839f84..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/DetermineBasalResultAMA.java +++ /dev/null @@ -1,77 +0,0 @@ -package info.nightscout.androidaps.plugins.aps.openAPSAMA; - -import org.json.JSONException; -import org.json.JSONObject; -import org.mozilla.javascript.NativeObject; - -import dagger.android.HasAndroidInjector; -import info.nightscout.androidaps.logging.AAPSLogger; -import info.nightscout.androidaps.logging.LTag; -import info.nightscout.androidaps.plugins.aps.loop.APSResult; -import info.nightscout.androidaps.utils.DateUtil; - -public class DetermineBasalResultAMA extends APSResult { - private AAPSLogger aapsLogger; - - private double eventualBG; - private double snoozeBG; - - DetermineBasalResultAMA(HasAndroidInjector injector, NativeObject result, JSONObject j) { - this(injector); - date = DateUtil.now(); - json = j; - if (result.containsKey("error")) { - reason = result.get("error").toString(); - tempBasalRequested = false; - rate = -1; - duration = -1; - } else { - reason = result.get("reason").toString(); - if (result.containsKey("eventualBG")) eventualBG = (Double) result.get("eventualBG"); - if (result.containsKey("snoozeBG")) snoozeBG = (Double) result.get("snoozeBG"); - if (result.containsKey("rate")) { - rate = (Double) result.get("rate"); - if (rate < 0d) rate = 0d; - tempBasalRequested = true; - } else { - rate = -1; - tempBasalRequested = false; - } - if (result.containsKey("duration")) { - duration = ((Double) result.get("duration")).intValue(); - //changeRequested as above - } else { - duration = -1; - tempBasalRequested = false; - } - } - bolusRequested = false; - } - - private DetermineBasalResultAMA(HasAndroidInjector injector) { - super(injector); - hasPredictions = true; - } - - @Override - public DetermineBasalResultAMA newAndClone(HasAndroidInjector injector) { - DetermineBasalResultAMA newResult = new DetermineBasalResultAMA(injector); - doClone(newResult); - - newResult.eventualBG = eventualBG; - newResult.snoozeBG = snoozeBG; - return newResult; - } - - @Override - public JSONObject json() { - try { - JSONObject ret = new JSONObject(this.json.toString()); - return ret; - } catch (JSONException e) { - aapsLogger.error(LTag.APS, "Unhandled exception", e); - } - return null; - } - -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/DetermineBasalResultAMA.kt b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/DetermineBasalResultAMA.kt new file mode 100644 index 0000000000..8f462b2f19 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/DetermineBasalResultAMA.kt @@ -0,0 +1,67 @@ +package info.nightscout.androidaps.plugins.aps.openAPSAMA + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.logging.LTag +import info.nightscout.androidaps.plugins.aps.loop.APSResult +import info.nightscout.androidaps.utils.DateUtil +import org.json.JSONException +import org.json.JSONObject +import org.mozilla.javascript.NativeObject + +class DetermineBasalResultAMA private constructor(injector: HasAndroidInjector) : APSResult(injector) { + + private var eventualBG = 0.0 + private var snoozeBG = 0.0 + + internal constructor(injector: HasAndroidInjector, result: NativeObject, j: JSONObject) : this(injector) { + date = DateUtil.now() + json = j + if (result.containsKey("error")) { + reason = result["error"].toString() + tempBasalRequested = false + rate = (-1).toDouble() + duration = -1 + } else { + reason = result["reason"].toString() + if (result.containsKey("eventualBG")) eventualBG = result["eventualBG"] as Double + if (result.containsKey("snoozeBG")) snoozeBG = result["snoozeBG"] as Double + if (result.containsKey("rate")) { + rate = result["rate"] as Double + if (rate < 0.0) rate = 0.0 + tempBasalRequested = true + } else { + rate = (-1).toDouble() + tempBasalRequested = false + } + if (result.containsKey("duration")) { + duration = (result["duration"] as Double).toInt() + //changeRequested as above + } else { + duration = -1 + tempBasalRequested = false + } + } + bolusRequested = false + } + + override fun newAndClone(injector: HasAndroidInjector): DetermineBasalResultAMA { + val newResult = DetermineBasalResultAMA(injector) + doClone(newResult) + newResult.eventualBG = eventualBG + newResult.snoozeBG = snoozeBG + return newResult + } + + override fun json(): JSONObject? { + try { + return JSONObject(json.toString()) + } catch (e: JSONException) { + aapsLogger.error(LTag.APS, "Unhandled exception", e) + } + return null + } + + init { + hasPredictions = true + } +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/OpenAPSAMAPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/OpenAPSAMAPlugin.java index 7d132db4d3..76e546b88d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/OpenAPSAMAPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/OpenAPSAMAPlugin.java @@ -18,20 +18,20 @@ import info.nightscout.androidaps.interfaces.ActivePluginProvider; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginDescription; import info.nightscout.androidaps.interfaces.PluginType; +import info.nightscout.androidaps.interfaces.ProfileFunction; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.logging.AAPSLogger; import info.nightscout.androidaps.logging.LTag; -import info.nightscout.androidaps.plugins.aps.loop.APSResult; -import info.nightscout.androidaps.plugins.aps.loop.ScriptReader; import info.nightscout.androidaps.plugins.aps.events.EventOpenAPSUpdateGui; import info.nightscout.androidaps.plugins.aps.events.EventOpenAPSUpdateResultGui; +import info.nightscout.androidaps.plugins.aps.loop.APSResult; +import info.nightscout.androidaps.plugins.aps.loop.ScriptReader; import info.nightscout.androidaps.plugins.bus.RxBusWrapper; import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker; -import info.nightscout.androidaps.interfaces.ProfileFunction; -import info.nightscout.androidaps.plugins.iob.iobCobCalculator.data.AutosensData; import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult; import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus; import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.data.AutosensData; import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; import info.nightscout.androidaps.utils.DateUtil; import info.nightscout.androidaps.utils.FabricPrivacy; @@ -238,15 +238,15 @@ public class OpenAPSAMAPlugin extends PluginBase implements APSInterface { lastAPSResult = null; lastAPSRun = 0; } else { - if (determineBasalResultAMA.rate == 0d && determineBasalResultAMA.duration == 0 && !treatmentsPlugin.isTempBasalInProgress()) - determineBasalResultAMA.tempBasalRequested = false; + if (determineBasalResultAMA.getRate() == 0d && determineBasalResultAMA.getDuration() == 0 && !treatmentsPlugin.isTempBasalInProgress()) + determineBasalResultAMA.setTempBasalRequested(false); - determineBasalResultAMA.iob = iobArray[0]; + determineBasalResultAMA.setIob(iobArray[0]); long now = System.currentTimeMillis(); try { - determineBasalResultAMA.json.put("timestamp", DateUtil.toISOString(now)); + determineBasalResultAMA.getJson().put("timestamp", DateUtil.toISOString(now)); } catch (JSONException e) { aapsLogger.error(LTag.APS, "Unhandled exception", e); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/DetermineBasalResultSMB.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/DetermineBasalResultSMB.java deleted file mode 100644 index 640d1b1585..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/DetermineBasalResultSMB.java +++ /dev/null @@ -1,97 +0,0 @@ -package info.nightscout.androidaps.plugins.aps.openAPSSMB; - -import org.json.JSONException; -import org.json.JSONObject; - -import javax.inject.Inject; - -import dagger.android.HasAndroidInjector; -import info.nightscout.androidaps.logging.LTag; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.plugins.aps.loop.APSResult; -import info.nightscout.androidaps.utils.DateUtil; -import info.nightscout.androidaps.utils.sharedPreferences.SP; - -public class DetermineBasalResultSMB extends APSResult { - @Inject SP sp; - - private double eventualBG; - private double snoozeBG; - - private DetermineBasalResultSMB(HasAndroidInjector injector) { - super(injector); - hasPredictions = true; - } - - DetermineBasalResultSMB(HasAndroidInjector injector, JSONObject result) { - this(injector); - date = DateUtil.now(); - json = result; - try { - if (result.has("error")) { - reason = result.getString("error"); - return; - } - - reason = result.getString("reason"); - if (result.has("eventualBG")) eventualBG = result.getDouble("eventualBG"); - if (result.has("snoozeBG")) snoozeBG = result.getDouble("snoozeBG"); - //if (result.has("insulinReq")) insulinReq = result.getDouble("insulinReq"); - - if (result.has("carbsReq")) carbsReq = result.getInt("carbsReq"); - if (result.has("carbsReqWithin")) carbsReqWithin = result.getInt("carbsReqWithin"); - - - if (result.has("rate") && result.has("duration")) { - tempBasalRequested = true; - rate = result.getDouble("rate"); - if (rate < 0d) rate = 0d; - duration = result.getInt("duration"); - } else { - rate = -1; - duration = -1; - } - - if (result.has("units")) { - bolusRequested = true; - smb = result.getDouble("units"); - } else { - smb = 0d; - } - if (result.has("targetBG")) { - targetBG = result.getDouble("targetBG"); - } - - if (result.has("deliverAt")) { - String date = result.getString("deliverAt"); - try { - deliverAt = DateUtil.fromISODateString(date).getTime(); - } catch (Exception e) { - aapsLogger.error(LTag.APS, "Error parsing 'deliverAt' date: " + date, e); - } - } - } catch (JSONException e) { - aapsLogger.error(LTag.APS, "Error parsing determine-basal result JSON", e); - } - } - - @Override - public DetermineBasalResultSMB newAndClone(HasAndroidInjector injector) { - DetermineBasalResultSMB newResult = new DetermineBasalResultSMB(injector); - doClone(newResult); - - newResult.eventualBG = eventualBG; - newResult.snoozeBG = snoozeBG; - return newResult; - } - - @Override - public JSONObject json() { - try { - return new JSONObject(this.json.toString()); - } catch (JSONException e) { - aapsLogger.error(LTag.APS, "Error converting determine-basal result to JSON", e); - } - return null; - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/DetermineBasalResultSMB.kt b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/DetermineBasalResultSMB.kt new file mode 100644 index 0000000000..46b68bbd0a --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/DetermineBasalResultSMB.kt @@ -0,0 +1,80 @@ +package info.nightscout.androidaps.plugins.aps.openAPSSMB + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.logging.LTag +import info.nightscout.androidaps.plugins.aps.loop.APSResult +import info.nightscout.androidaps.utils.DateUtil +import org.json.JSONException +import org.json.JSONObject + +class DetermineBasalResultSMB private constructor(injector: HasAndroidInjector) : APSResult(injector) { + + private var eventualBG = 0.0 + private var snoozeBG = 0.0 + + internal constructor(injector: HasAndroidInjector, result: JSONObject) : this(injector) { + date = DateUtil.now() + json = result + try { + if (result.has("error")) { + reason = result.getString("error") + return + } + reason = result.getString("reason") + if (result.has("eventualBG")) eventualBG = result.getDouble("eventualBG") + if (result.has("snoozeBG")) snoozeBG = result.getDouble("snoozeBG") + //if (result.has("insulinReq")) insulinReq = result.getDouble("insulinReq"); + if (result.has("carbsReq")) carbsReq = result.getInt("carbsReq") + if (result.has("carbsReqWithin")) carbsReqWithin = result.getInt("carbsReqWithin") + if (result.has("rate") && result.has("duration")) { + tempBasalRequested = true + rate = result.getDouble("rate") + if (rate < 0.0) rate = 0.0 + duration = result.getInt("duration") + } else { + rate = (-1).toDouble() + duration = -1 + } + if (result.has("units")) { + bolusRequested = true + smb = result.getDouble("units") + } else { + smb = 0.0 + } + if (result.has("targetBG")) { + targetBG = result.getDouble("targetBG") + } + if (result.has("deliverAt")) { + val date = result.getString("deliverAt") + try { + deliverAt = DateUtil.fromISODateString(date).time + } catch (e: Exception) { + aapsLogger.error(LTag.APS, "Error parsing 'deliverAt' date: $date", e) + } + } + } catch (e: JSONException) { + aapsLogger.error(LTag.APS, "Error parsing determine-basal result JSON", e) + } + } + + override fun newAndClone(injector: HasAndroidInjector): DetermineBasalResultSMB { + val newResult = DetermineBasalResultSMB(injector) + doClone(newResult) + newResult.eventualBG = eventualBG + newResult.snoozeBG = snoozeBG + return newResult + } + + override fun json(): JSONObject? { + try { + return JSONObject(json.toString()) + } catch (e: JSONException) { + aapsLogger.error(LTag.APS, "Error converting determine-basal result to JSON", e) + } + return null + } + + init { + hasPredictions = true + } +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/OpenAPSSMBPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/OpenAPSSMBPlugin.java index 4a6ec60b7d..4ddbcdca76 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/OpenAPSSMBPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/OpenAPSSMBPlugin.java @@ -24,20 +24,20 @@ import info.nightscout.androidaps.interfaces.ConstraintsInterface; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginDescription; import info.nightscout.androidaps.interfaces.PluginType; +import info.nightscout.androidaps.interfaces.ProfileFunction; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.logging.AAPSLogger; import info.nightscout.androidaps.logging.LTag; -import info.nightscout.androidaps.plugins.aps.loop.APSResult; -import info.nightscout.androidaps.plugins.aps.loop.ScriptReader; import info.nightscout.androidaps.plugins.aps.events.EventOpenAPSUpdateGui; import info.nightscout.androidaps.plugins.aps.events.EventOpenAPSUpdateResultGui; +import info.nightscout.androidaps.plugins.aps.loop.APSResult; +import info.nightscout.androidaps.plugins.aps.loop.ScriptReader; import info.nightscout.androidaps.plugins.bus.RxBusWrapper; import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker; -import info.nightscout.androidaps.interfaces.ProfileFunction; -import info.nightscout.androidaps.plugins.iob.iobCobCalculator.data.AutosensData; import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult; import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus; import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.data.AutosensData; import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; import info.nightscout.androidaps.utils.DateUtil; import info.nightscout.androidaps.utils.FabricPrivacy; @@ -291,18 +291,18 @@ public class OpenAPSSMBPlugin extends PluginBase implements APSInterface, Constr } else { // TODO still needed with oref1? // Fix bug determine basal - if (determineBasalResultSMB.rate == 0d && determineBasalResultSMB.duration == 0 && !treatmentsPlugin.isTempBasalInProgress()) - determineBasalResultSMB.tempBasalRequested = false; + if (determineBasalResultSMB.getRate() == 0d && determineBasalResultSMB.getDuration() == 0 && !treatmentsPlugin.isTempBasalInProgress()) + determineBasalResultSMB.setTempBasalRequested(false); - determineBasalResultSMB.iob = iobArray[0]; + determineBasalResultSMB.setIob(iobArray[0]); try { - determineBasalResultSMB.json.put("timestamp", DateUtil.toISOString(now)); + determineBasalResultSMB.getJson().put("timestamp", DateUtil.toISOString(now)); } catch (JSONException e) { getAapsLogger().error(LTag.APS, "Unhandled exception", e); } - determineBasalResultSMB.inputConstraints = inputConstraints; + determineBasalResultSMB.setInputConstraints(inputConstraints); lastDetermineBasalAdapterSMBJS = determineBasalAdapterSMBJS; lastAPSResult = determineBasalResultSMB; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/data/NSDeviceStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/data/NSDeviceStatus.java index 9efda8bf1f..6d50c67e3a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/data/NSDeviceStatus.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/data/NSDeviceStatus.java @@ -1,6 +1,5 @@ package info.nightscout.androidaps.plugins.general.nsclient.data; -import android.text.Html; import android.text.Spanned; import org.json.JSONArray; @@ -15,7 +14,6 @@ import javax.inject.Inject; import javax.inject.Singleton; import dagger.android.HasAndroidInjector; -import info.nightscout.androidaps.Config; import info.nightscout.androidaps.R; import info.nightscout.androidaps.interfaces.ConfigInterface; import info.nightscout.androidaps.logging.AAPSLogger; @@ -475,8 +473,8 @@ public class NSDeviceStatus { public static APSResult getAPSResult(HasAndroidInjector injector) { APSResult result = new APSResult(injector); - result.json = deviceStatusOpenAPSData.suggested; - result.date = deviceStatusOpenAPSData.clockSuggested; + result.setJson(deviceStatusOpenAPSData.suggested); + result.setDate(deviceStatusOpenAPSData.clockSuggested); return result; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/openhumans/OpenHumansUploader.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/openhumans/OpenHumansUploader.kt index 9a7ee965ab..81c8c9c23e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/openhumans/OpenHumansUploader.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/openhumans/OpenHumansUploader.kt @@ -17,6 +17,7 @@ import info.nightscout.androidaps.BuildConfig import info.nightscout.androidaps.MainApp import info.nightscout.androidaps.R import info.nightscout.androidaps.database.AppRepository +import info.nightscout.androidaps.database.entities.GlucoseValue import info.nightscout.androidaps.db.* import info.nightscout.androidaps.events.EventPreferenceChange import info.nightscout.androidaps.interfaces.PluginBase @@ -163,15 +164,15 @@ class OpenHumansUploader @Inject constructor( super.onStop() } - fun enqueueBGReading(bgReading: BgReading?) = bgReading?.let { + fun enqueueBGReading(glucoseValue: GlucoseValue?) = glucoseValue?.let { insertQueueItem("BgReadings") { - put("date", bgReading.data.dateCreated) - put("isValid", bgReading.data.isValid) - put("value", bgReading.data.value) - put("direction", bgReading.data.trendArrow) - put("raw", bgReading.data.raw) - put("source", bgReading.data.sourceSensor) - put("nsId", bgReading.data.interfaceIDs.nightscoutId) + put("date", glucoseValue.timestamp) + put("isValid", glucoseValue.isValid) + put("value", glucoseValue.value) + put("direction", glucoseValue.trendArrow) + put("raw", glucoseValue.raw) + put("source", glucoseValue.sourceSensor) + put("nsId", glucoseValue.interfaceIDs.nightscoutId) } } @@ -365,7 +366,7 @@ class OpenHumansUploader @Inject constructor( .flatMapObservable { Observable.defer { Observable.fromIterable(treatmentsPlugin.service.treatmentData) } } .map { enqueueTreatment(it); increaseCounter() } .ignoreElements() - .andThen(Observable.defer { Observable.fromIterable(MainApp.getDbHelper().allBgReadings) }) + .andThen(Observable.defer { Observable.fromIterable(repository.compatGetBgReadingsDataFromTime(0, true).blockingGet()) }) .map { enqueueBGReading(it); increaseCounter() } .ignoreElements() .andThen(Observable.defer { Observable.fromIterable(MainApp.getDbHelper().allCareportalEvents) }) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/graphData/GraphData.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/graphData/GraphData.kt index 4ad6118c61..5b18eb80d5 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/graphData/GraphData.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/graphData/GraphData.kt @@ -12,9 +12,10 @@ import dagger.android.HasAndroidInjector import info.nightscout.androidaps.Constants import info.nightscout.androidaps.MainApp import info.nightscout.androidaps.R +import info.nightscout.androidaps.data.GlucoseValueDataPoint import info.nightscout.androidaps.data.IobTotal import info.nightscout.androidaps.data.Profile -import info.nightscout.androidaps.db.BgReading +import info.nightscout.androidaps.database.entities.GlucoseValue import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.LoopInterface import info.nightscout.androidaps.interfaces.ProfileFunction @@ -27,7 +28,6 @@ import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin import info.nightscout.androidaps.utils.DecimalFormatter import info.nightscout.androidaps.utils.Round -import info.nightscout.androidaps.utils.convertToBGReadings import info.nightscout.androidaps.utils.resources.ResourceHelper import java.util.* import javax.inject.Inject @@ -51,7 +51,7 @@ class GraphData( var maxY = Double.MIN_VALUE private var minY = Double.MAX_VALUE - private var bgReadingsArray: List? = null + private var bgReadingsArray: List? = null private val units: String private val series: MutableList> = ArrayList() @@ -61,9 +61,9 @@ class GraphData( } @Suppress("UNUSED_PARAMETER") - fun addBgReadings(fromTime: Long, toTime: Long, lowLine: Double, highLine: Double, predictions: MutableList?) { + fun addBgReadings(fromTime: Long, toTime: Long, lowLine: Double, highLine: Double, predictions: MutableList?) { var maxBgValue = Double.MIN_VALUE - bgReadingsArray = iobCobCalculatorPlugin.bgReadings?.convertToBGReadings(injector) + bgReadingsArray = iobCobCalculatorPlugin.bgReadings if (bgReadingsArray?.isEmpty() != false) { aapsLogger.debug("No BG data.") maxY = 10.0 @@ -72,12 +72,12 @@ class GraphData( } val bgListArray: MutableList = ArrayList() for (bg in bgReadingsArray!!) { - if (bg.data.timestamp < fromTime || bg.data.timestamp > toTime) continue - if (bg.data.value > maxBgValue) maxBgValue = bg.data.value - bgListArray.add(bg) + if (bg.timestamp < fromTime || bg.timestamp > toTime) continue + if (bg.value > maxBgValue) maxBgValue = bg.value + bgListArray.add(GlucoseValueDataPoint(injector, bg)) } if (predictions != null) { - predictions.sortWith(Comparator { o1: BgReading, o2: BgReading -> o1.x.compareTo(o2.x) }) + predictions.sortWith(Comparator { o1: GlucoseValueDataPoint, o2: GlucoseValueDataPoint -> o1.x.compareTo(o2.x) }) for (prediction in predictions) if (prediction.data.value >= 40) bgListArray.add(prediction) } maxBgValue = Profile.fromMgdlToUnits(maxBgValue, units) @@ -213,8 +213,7 @@ class GraphData( var time = fromTime while (time < toTime) { val tt = treatmentsPlugin.getTempTargetFromHistory(time) - var value: Double - value = if (tt == null) { + val value: Double = if (tt == null) { Profile.fromMgdlToUnits((profile.getTargetLowMgdl(time) + profile.getTargetHighMgdl(time)) / 2, units) } else { Profile.fromMgdlToUnits(tt.target(), units) @@ -283,10 +282,10 @@ class GraphData( bgReadingsArray?.let { bgReadingsArray -> for (r in bgReadingsArray.indices) { val reading = bgReadingsArray[r] - if (reading.data.timestamp > date) continue - return Profile.fromMgdlToUnits(reading.data.value, units) + if (reading.timestamp > date) continue + return Profile.fromMgdlToUnits(reading.value, units) } - return if (bgReadingsArray.isNotEmpty()) Profile.fromMgdlToUnits(bgReadingsArray[0].data.value, units) else Profile.fromMgdlToUnits(100.0, units) + return if (bgReadingsArray.isNotEmpty()) Profile.fromMgdlToUnits(bgReadingsArray[0].value, units) else Profile.fromMgdlToUnits(100.0, units) } ?: return Profile.fromMgdlToUnits(100.0, units) } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/comm/UploadChunk.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/comm/UploadChunk.kt index 0df39ad822..9a8c09e4dd 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/comm/UploadChunk.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/comm/UploadChunk.kt @@ -8,17 +8,16 @@ import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.db.ProfileSwitch import info.nightscout.androidaps.db.TemporaryBasal import info.nightscout.androidaps.interfaces.ActivePluginProvider +import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.plugins.bus.RxBusWrapper -import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.plugins.general.tidepool.elements.* import info.nightscout.androidaps.plugins.general.tidepool.events.EventTidepoolStatus import info.nightscout.androidaps.plugins.general.tidepool.utils.GsonInstance import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.T -import info.nightscout.androidaps.utils.convertToBGReadings import info.nightscout.androidaps.utils.sharedPreferences.SP import java.util.* import javax.inject.Inject @@ -109,9 +108,8 @@ class UploadChunk @Inject constructor( val bgReadingList = repository.compatGetBgReadingsDataFromTime(start, end, true) .blockingGet() - .convertToBGReadings(injector) return if (bgReadingList.isNotEmpty()) - bgReadingList[0].data.timestamp + bgReadingList[0].timestamp else -1 } @@ -140,7 +138,6 @@ class UploadChunk @Inject constructor( private fun getBgReadings(start: Long, end: Long): List { val readings = repository.compatGetBgReadingsDataFromTime(start, end, true) .blockingGet() - .convertToBGReadings(injector) val selection = SensorGlucoseElement.fromBgReadings(readings) if (selection.isNotEmpty()) rxBus.send(EventTidepoolStatus("${selection.size} CGMs selected for upload")) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/elements/SensorGlucoseElement.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/elements/SensorGlucoseElement.kt index 7573db1a82..da769f902e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/elements/SensorGlucoseElement.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/tidepool/elements/SensorGlucoseElement.kt @@ -1,24 +1,26 @@ package info.nightscout.androidaps.plugins.general.tidepool.elements import com.google.gson.annotations.Expose -import info.nightscout.androidaps.db.BgReading +import info.nightscout.androidaps.database.entities.GlucoseValue import java.util.* -class SensorGlucoseElement(bgReading: BgReading) - : BaseElement(bgReading.data.timestamp, UUID.nameUUIDFromBytes(("AAPS-cgm" + bgReading.data.timestamp).toByteArray()).toString()) { +class SensorGlucoseElement(bgReading: GlucoseValue) + : BaseElement(bgReading.timestamp, UUID.nameUUIDFromBytes(("AAPS-cgm" + bgReading.timestamp).toByteArray()).toString()) { @Expose internal var units: String = "mg/dL" + @Expose internal var value: Int = 0 init { this.type = "cbg" - value = bgReading.data.value.toInt() + value = bgReading.value.toInt() } companion object { - internal fun fromBgReadings(bgReadingList: List): List { + + internal fun fromBgReadings(bgReadingList: List): List { val results = LinkedList() for (bgReading in bgReadingList) { results.add(SensorGlucoseElement(bgReading)) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/wearintegration/WatchUpdaterService.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/wearintegration/WatchUpdaterService.java index 5b06f122d4..ae00054fe7 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/wearintegration/WatchUpdaterService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/wearintegration/WatchUpdaterService.java @@ -32,11 +32,11 @@ import dagger.android.HasAndroidInjector; import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.data.GlucoseValueDataPoint; import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.database.AppRepository; import info.nightscout.androidaps.database.entities.GlucoseValue; -import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.interfaces.ActivePluginProvider; @@ -537,14 +537,14 @@ public class WatchUpdaterService extends WearableListenerService implements Goog } final LoopPlugin.LastRun finalLastRun = loopPlugin.getLastRun(); - if (sp.getBoolean("wear_predictions", true) && finalLastRun != null && finalLastRun.getRequest().hasPredictions && finalLastRun.getConstraintsProcessed() != null) { - List predArray = finalLastRun.getConstraintsProcessed().getPredictions(); + if (sp.getBoolean("wear_predictions", true) && finalLastRun != null && finalLastRun.getRequest().getHasPredictions() && finalLastRun.getConstraintsProcessed() != null) { + List predArray = finalLastRun.getConstraintsProcessed().getPredictions(); if (!predArray.isEmpty()) { final String units = profileFunction.getUnits(); - for (BgReading bg : predArray) { - if (bg.getValue() < 40) continue; - predictions.add(predictionMap(bg.getDate(), bg.getValue(), bg.getPredictionColor())); + for (GlucoseValueDataPoint bg : predArray) { + if (bg.getData().getValue() < 40) continue; + predictions.add(predictionMap(bg.getData().getTimestamp(), bg.getData().getValue(), bg.getPredictionColor())); } } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/GlucoseStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/GlucoseStatus.java index 22420fc0ce..268f09eaa9 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/GlucoseStatus.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/GlucoseStatus.java @@ -9,7 +9,6 @@ import javax.inject.Inject; import dagger.android.HasAndroidInjector; import info.nightscout.androidaps.database.entities.GlucoseValue; -import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.logging.AAPSLogger; import info.nightscout.androidaps.logging.LTag; import info.nightscout.androidaps.utils.DateUtil; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/IobCobCalculatorPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/IobCobCalculatorPlugin.java index 430147e9ed..59fdd1ccff 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/IobCobCalculatorPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/IobCobCalculatorPlugin.java @@ -17,14 +17,12 @@ import javax.inject.Singleton; import dagger.android.HasAndroidInjector; import info.nightscout.androidaps.Constants; -import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.MealData; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.database.AppRepository; import info.nightscout.androidaps.database.entities.GlucoseValue; -import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.events.Event; @@ -385,7 +383,7 @@ public class IobCobCalculatorPlugin extends PluginBase implements IobCobCalculat if (older.getTimestamp() == newer.getTimestamp()) { // direct hit bucketed_data.add(new InMemoryGlucoseValue(newer)); } else { - double bgDelta = newer.getTimestamp() - older.getTimestamp(); + double bgDelta = newer.getValue() - older.getValue(); long timeDiffToNew = newer.getTimestamp() - currentTime; double currentBg = newer.getValue() - (double) timeDiffToNew / (newer.getTimestamp() - older.getTimestamp()) * bgDelta; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/IobCobOref1Thread.java b/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/IobCobOref1Thread.java index 9452087c62..ad68c3acc6 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/IobCobOref1Thread.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/IobCobOref1Thread.java @@ -18,15 +18,14 @@ import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.R; import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.Profile; -import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.db.TempTarget; +import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.events.Event; -import info.nightscout.androidaps.interfaces.ActivePluginProvider; +import info.nightscout.androidaps.interfaces.ProfileFunction; import info.nightscout.androidaps.logging.AAPSLogger; import info.nightscout.androidaps.logging.LTag; import info.nightscout.androidaps.plugins.aps.openAPSSMB.SMBDefaults; import info.nightscout.androidaps.plugins.bus.RxBusWrapper; -import info.nightscout.androidaps.interfaces.ProfileFunction; import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; import info.nightscout.androidaps.plugins.iob.iobCobCalculator.data.AutosensData; @@ -35,7 +34,6 @@ import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutos import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventIobCalculationProgress; import info.nightscout.androidaps.plugins.sensitivity.SensitivityAAPSPlugin; import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAveragePlugin; -import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; import info.nightscout.androidaps.utils.DateUtil; import info.nightscout.androidaps.utils.DecimalFormatter; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/IobCobThread.java b/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/IobCobThread.java index 40c657280f..0c7a9444d0 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/IobCobThread.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/IobCobThread.java @@ -16,15 +16,14 @@ import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.R; 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.events.Event; -import info.nightscout.androidaps.interfaces.ActivePluginProvider; import info.nightscout.androidaps.interfaces.PluginType; +import info.nightscout.androidaps.interfaces.ProfileFunction; import info.nightscout.androidaps.logging.AAPSLogger; import info.nightscout.androidaps.logging.LTag; import info.nightscout.androidaps.plugins.aps.openAPSSMB.SMBDefaults; import info.nightscout.androidaps.plugins.bus.RxBusWrapper; -import info.nightscout.androidaps.interfaces.ProfileFunction; import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; import info.nightscout.androidaps.plugins.iob.iobCobCalculator.data.AutosensData; @@ -33,7 +32,6 @@ import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutos import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventIobCalculationProgress; import info.nightscout.androidaps.plugins.sensitivity.SensitivityAAPSPlugin; import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAveragePlugin; -import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; import info.nightscout.androidaps.utils.DateUtil; import info.nightscout.androidaps.utils.DecimalFormatter; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/DexcomPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/DexcomPlugin.kt index 28d4190415..4065d78f92 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/DexcomPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/DexcomPlugin.kt @@ -13,7 +13,6 @@ import info.nightscout.androidaps.activities.RequestDexcomPermissionActivity import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.entities.GlucoseValue import info.nightscout.androidaps.database.transactions.CgmSourceTransaction -import info.nightscout.androidaps.db.BgReading import info.nightscout.androidaps.interfaces.BgSourceInterface import info.nightscout.androidaps.interfaces.PluginBase import info.nightscout.androidaps.interfaces.PluginDescription @@ -138,9 +137,9 @@ class DexcomPlugin @Inject constructor( broadcastToXDrip(it) if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false)) { if (it.interfaceIDs.nightscoutId != null) - nsUpload.updateBg(BgReading(injector, it), sourceSensor.text) + nsUpload.updateBg(it, sourceSensor.text) else - nsUpload.uploadBg(BgReading(injector, it), sourceSensor.text) + nsUpload.uploadBg(it, sourceSensor.text) } } }, { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/EversensePlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/EversensePlugin.kt index bf13f16916..e34550fc94 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/EversensePlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/EversensePlugin.kt @@ -10,7 +10,6 @@ import info.nightscout.androidaps.R import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.entities.GlucoseValue import info.nightscout.androidaps.database.transactions.CgmSourceTransaction -import info.nightscout.androidaps.db.BgReading import info.nightscout.androidaps.db.CareportalEvent import info.nightscout.androidaps.interfaces.BgSourceInterface import info.nightscout.androidaps.interfaces.PluginBase @@ -122,7 +121,7 @@ class EversensePlugin @Inject constructor( savedValues.forEach { broadcastToXDrip(it) if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false)) - nsUpload.uploadBg(BgReading(injector, it), GlucoseValue.SourceSensor.EVERSENSE.text) + nsUpload.uploadBg(it, GlucoseValue.SourceSensor.EVERSENSE.text) } }, { aapsLogger.error(LTag.BGSOURCE, "Error while saving values from Eversense App", it) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/GlimpPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/GlimpPlugin.kt index 1fed35428b..be297ec32a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/GlimpPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/GlimpPlugin.kt @@ -8,7 +8,6 @@ import info.nightscout.androidaps.R import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.entities.GlucoseValue import info.nightscout.androidaps.database.transactions.CgmSourceTransaction -import info.nightscout.androidaps.db.BgReading import info.nightscout.androidaps.interfaces.BgSourceInterface import info.nightscout.androidaps.interfaces.PluginBase import info.nightscout.androidaps.interfaces.PluginDescription @@ -80,7 +79,7 @@ class GlimpPlugin @Inject constructor( savedValues.forEach { broadcastToXDrip(it) if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false)) - nsUpload.uploadBg(BgReading(injector, it), GlucoseValue.SourceSensor.GLIMP.text) + nsUpload.uploadBg(it, GlucoseValue.SourceSensor.GLIMP.text) } }, { aapsLogger.error(LTag.BGSOURCE, "Error while saving values from Glimp App", it) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/MM640gPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/MM640gPlugin.kt index 6d5b7a8c4d..91df585df7 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/MM640gPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/MM640gPlugin.kt @@ -8,7 +8,6 @@ import info.nightscout.androidaps.R import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.entities.GlucoseValue import info.nightscout.androidaps.database.transactions.CgmSourceTransaction -import info.nightscout.androidaps.db.BgReading import info.nightscout.androidaps.interfaces.BgSourceInterface import info.nightscout.androidaps.interfaces.PluginBase import info.nightscout.androidaps.interfaces.PluginDescription @@ -98,7 +97,7 @@ class MM640gPlugin @Inject constructor( savedValues.forEach { broadcastToXDrip(it) if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false)) - nsUpload.uploadBg(BgReading(injector, it), GlucoseValue.SourceSensor.MM_600_SERIES.text) + nsUpload.uploadBg(it, GlucoseValue.SourceSensor.MM_600_SERIES.text) } }, { aapsLogger.error(LTag.BGSOURCE, "Error while saving values from Eversense App", it) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/NSClientSourcePlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/NSClientSourcePlugin.kt index 635a615784..e587fbe285 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/NSClientSourcePlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/NSClientSourcePlugin.kt @@ -94,12 +94,13 @@ class NSClientSourcePlugin @Inject constructor( @Inject lateinit var bundleStore: BundleStore @Inject lateinit var repository: AppRepository @Inject lateinit var broadcastToXDrip: XDripBroadcast + @Inject lateinit var dexcomPlugin: DexcomPlugin init { (context.applicationContext as HasAndroidInjector).androidInjector().inject(this) } - fun toGv(jsonObject: JSONObject): CgmSourceTransaction.TransactionGlucoseValue { + private fun toGv(jsonObject: JSONObject): CgmSourceTransaction.TransactionGlucoseValue { val sgv = NSSgv(jsonObject) return CgmSourceTransaction.TransactionGlucoseValue( timestamp = sgv.mills, @@ -113,7 +114,7 @@ class NSClientSourcePlugin @Inject constructor( } override fun doWork(): Result { - if (!nsClientSourcePlugin.isEnabled(PluginType.BGSOURCE) && !sp.getBoolean(R.string.key_ns_autobackfill, true)) return Result.failure() + if (!nsClientSourcePlugin.isEnabled() && !sp.getBoolean(R.string.key_ns_autobackfill, true) && !dexcomPlugin.isEnabled()) return Result.failure() try { val glucoseValues = mutableListOf() inputData.getString("sgv")?.let { sgvString -> diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/PoctechPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/PoctechPlugin.kt index 67c8232fdc..5bbc9ff953 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/PoctechPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/PoctechPlugin.kt @@ -9,7 +9,6 @@ import info.nightscout.androidaps.R import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.entities.GlucoseValue import info.nightscout.androidaps.database.transactions.CgmSourceTransaction -import info.nightscout.androidaps.db.BgReading import info.nightscout.androidaps.interfaces.BgSourceInterface import info.nightscout.androidaps.interfaces.PluginBase import info.nightscout.androidaps.interfaces.PluginDescription @@ -91,7 +90,7 @@ class PoctechPlugin @Inject constructor( savedValues.forEach { broadcastToXDrip(it) if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false)) - nsUpload.uploadBg(BgReading(injector, it), GlucoseValue.SourceSensor.POCTECH_NATIVE.text) + nsUpload.uploadBg(it, GlucoseValue.SourceSensor.POCTECH_NATIVE.text) } }, { aapsLogger.error(LTag.BGSOURCE, "Error while saving values from Poctech App", it) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/RandomBgPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/RandomBgPlugin.kt index c208b27a51..8ea04bde91 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/RandomBgPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/RandomBgPlugin.kt @@ -7,7 +7,6 @@ import info.nightscout.androidaps.R import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.entities.GlucoseValue import info.nightscout.androidaps.database.transactions.CgmSourceTransaction -import info.nightscout.androidaps.db.BgReading import info.nightscout.androidaps.interfaces.BgSourceInterface import info.nightscout.androidaps.interfaces.PluginBase import info.nightscout.androidaps.interfaces.PluginDescription @@ -112,7 +111,7 @@ class RandomBgPlugin @Inject constructor( savedValues.forEach { xDripBroadcast(it) if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false)) - nsUpload.uploadBg(BgReading(injector, it), GlucoseValue.SourceSensor.RANDOM.text) + nsUpload.uploadBg(it, GlucoseValue.SourceSensor.RANDOM.text) } }, { aapsLogger.error(LTag.BGSOURCE, "Error while saving values from Random plugin", it) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/TomatoPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/TomatoPlugin.kt index 95a9d192ae..bbbfc3aaf9 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/TomatoPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/TomatoPlugin.kt @@ -8,7 +8,6 @@ import info.nightscout.androidaps.R import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.entities.GlucoseValue import info.nightscout.androidaps.database.transactions.CgmSourceTransaction -import info.nightscout.androidaps.db.BgReading import info.nightscout.androidaps.interfaces.BgSourceInterface import info.nightscout.androidaps.interfaces.PluginBase import info.nightscout.androidaps.interfaces.PluginDescription @@ -80,7 +79,7 @@ class TomatoPlugin @Inject constructor( savedValues.forEach { broadcastToXDrip(it) if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false)) - nsUpload.uploadBg(BgReading(injector, it), GlucoseValue.SourceSensor.LIBRE_1_TOMATO.text) + nsUpload.uploadBg(it, GlucoseValue.SourceSensor.LIBRE_1_TOMATO.text) } }, { aapsLogger.error(LTag.BGSOURCE, "Error while saving values from Tomato App", it) diff --git a/app/src/main/java/info/nightscout/androidaps/utils/GlucoseValueUtils.kt b/app/src/main/java/info/nightscout/androidaps/utils/GlucoseValueUtils.kt index cfbba98958..10ebf54797 100644 --- a/app/src/main/java/info/nightscout/androidaps/utils/GlucoseValueUtils.kt +++ b/app/src/main/java/info/nightscout/androidaps/utils/GlucoseValueUtils.kt @@ -1,9 +1,7 @@ package info.nightscout.androidaps.utils -import dagger.android.HasAndroidInjector import info.nightscout.androidaps.Constants import info.nightscout.androidaps.database.entities.GlucoseValue -import info.nightscout.androidaps.db.BgReading fun GlucoseValue.valueToUnits(units: String): Double = if (units == Constants.MGDL) value @@ -12,7 +10,3 @@ fun GlucoseValue.valueToUnits(units: String): Double = fun GlucoseValue.valueToUnitsString(units: String): String = if (units == Constants.MGDL) DecimalFormatter.to0Decimal(value) else DecimalFormatter.to1Decimal(value * Constants.MGDL_TO_MMOLL) - -fun GlucoseValue.convertToBGReading(injector: HasAndroidInjector): BgReading = BgReading(injector, this) - -fun List.convertToBGReadings(injector: HasAndroidInjector): List = map { it.convertToBGReading(injector) } diff --git a/app/src/test/java/info/nightscout/androidaps/db/BgReadingTest.kt b/app/src/test/java/info/nightscout/androidaps/db/BgReadingTest.kt deleted file mode 100644 index 47417786de..0000000000 --- a/app/src/test/java/info/nightscout/androidaps/db/BgReadingTest.kt +++ /dev/null @@ -1,185 +0,0 @@ -package info.nightscout.androidaps.db - -import android.content.Context -import dagger.android.AndroidInjector -import dagger.android.HasAndroidInjector -import info.nightscout.androidaps.TestBase -import info.nightscout.androidaps.Constants -import info.nightscout.androidaps.MainApp -import info.nightscout.androidaps.interfaces.DatabaseHelperInterface -import info.nightscout.androidaps.logging.L -import info.nightscout.androidaps.interfaces.ProfileFunction -import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus -import info.nightscout.androidaps.core.R -import info.nightscout.androidaps.utils.DateUtil -import info.nightscout.androidaps.utils.DefaultValueHelper -import info.nightscout.androidaps.utils.resources.ResourceHelper -import org.junit.Assert -import org.junit.Before -import org.junit.Test -import org.junit.runner.RunWith -import org.mockito.ArgumentMatchers -import org.mockito.Mock -import org.mockito.Mockito -import org.mockito.Mockito.`when` -import org.powermock.api.mockito.PowerMockito -import org.powermock.core.classloader.annotations.PrepareForTest -import org.powermock.modules.junit4.PowerMockRunner -import java.util.* -import java.util.logging.Logger - -@RunWith(PowerMockRunner::class) -@PrepareForTest(MainApp::class, Logger::class, L::class, GlucoseStatus::class) -class BgReadingTest : TestBase() { - - @Mock lateinit var defaultValueHelper: DefaultValueHelper - @Mock lateinit var profileFunction: ProfileFunction - @Mock lateinit var resourceHelper: ResourceHelper - @Mock lateinit var databaseHelper: DatabaseHelperInterface - - var injector: HasAndroidInjector = HasAndroidInjector { - AndroidInjector { - if (it is BgReading) { - it.aapsLogger = aapsLogger - it.resourceHelper = resourceHelper - it.defaultValueHelper = defaultValueHelper - it.profileFunction = profileFunction - } - } - } - - @Test - fun valueToUnits() { - val bgReading = BgReading(injector) - bgReading.value = 18.0 - Assert.assertEquals(18.0, bgReading.valueToUnits(Constants.MGDL) * 1, 0.01) - Assert.assertEquals(1.0, bgReading.valueToUnits(Constants.MMOL) * 1, 0.01) - } - - @Test - fun directionToSymbol() { - val bgReading = BgReading(injector) - bgReading.direction = "DoubleDown" - Assert.assertEquals("\u21ca", bgReading.directionToSymbol(databaseHelper)) - bgReading.direction = "SingleDown" - Assert.assertEquals("\u2193", bgReading.directionToSymbol(databaseHelper)) - bgReading.direction = "FortyFiveDown" - Assert.assertEquals("\u2198", bgReading.directionToSymbol(databaseHelper)) - bgReading.direction = "Flat" - Assert.assertEquals("\u2192", bgReading.directionToSymbol(databaseHelper)) - bgReading.direction = "FortyFiveUp" - Assert.assertEquals("\u2197", bgReading.directionToSymbol(databaseHelper)) - bgReading.direction = "SingleUp" - Assert.assertEquals("\u2191", bgReading.directionToSymbol(databaseHelper)) - bgReading.direction = "DoubleUp" - Assert.assertEquals("\u21c8", bgReading.directionToSymbol(databaseHelper)) - bgReading.direction = "OUT OF RANGE" - Assert.assertEquals("??", bgReading.directionToSymbol(databaseHelper)) - } - - @Test - fun directionToIcon() { - val bgReading = BgReading(injector) - bgReading.direction = "DoubleDown" - Assert.assertEquals(R.drawable.ic_doubledown, bgReading.directionToIcon(databaseHelper)) - bgReading.direction = "SingleDown" - Assert.assertEquals(R.drawable.ic_singledown, bgReading.directionToIcon(databaseHelper)) - bgReading.direction = "FortyFiveDown" - Assert.assertEquals(R.drawable.ic_fortyfivedown, bgReading.directionToIcon(databaseHelper)) - bgReading.direction = "Flat" - Assert.assertEquals(R.drawable.ic_flat, bgReading.directionToIcon(databaseHelper)) - bgReading.direction = "FortyFiveUp" - Assert.assertEquals(R.drawable.ic_fortyfiveup, bgReading.directionToIcon(databaseHelper)) - bgReading.direction = "SingleUp" - Assert.assertEquals(R.drawable.ic_singleup, bgReading.directionToIcon(databaseHelper)) - bgReading.direction = "DoubleUp" - Assert.assertEquals(R.drawable.ic_doubleup, bgReading.directionToIcon(databaseHelper)) - bgReading.direction = "OUT OF RANGE" - Assert.assertEquals(R.drawable.ic_invalid, bgReading.directionToIcon(databaseHelper)) - } - - - @Test fun dateTest() { - val bgReading = BgReading(injector) - val now = System.currentTimeMillis() - bgReading.date = now - val nowDate = Date(now) - Assert.assertEquals(now, bgReading.date(now).date) - Assert.assertEquals(now, bgReading.date(nowDate).date) - } - - @Test fun valueTest() { - val bgReading = BgReading(injector) - val valueToSet = 81.0 // 4.5 mmol - Assert.assertEquals(81.0, bgReading.value(valueToSet).value, 0.01) - } - - @Test fun copyFromTest() { -// val databaseHelper = Mockito.mock(DatabaseHelper::class.java) -// `when`(MainApp.getDbHelper()).thenReturn(databaseHelper) - setReadings(72, 0) - val bgReading = BgReading(injector) - val copy = BgReading(injector) - bgReading.value = 81.0 - val now = System.currentTimeMillis() - bgReading.date = now - copy.date = now - copy.copyFrom(bgReading) - Assert.assertEquals(81.0, copy.value, 0.1) - Assert.assertEquals(now, copy.date) - Assert.assertEquals(bgReading.directionToSymbol(databaseHelper), copy.directionToSymbol(databaseHelper)) - } - - @Test - fun isEqualTest() { - val bgReading = BgReading(injector) - val copy = BgReading(injector) - bgReading.value = 81.0 - val now = System.currentTimeMillis() - bgReading.date = now - copy.date = now - copy.copyFrom(bgReading) - Assert.assertTrue(copy.isEqual(bgReading)) - Assert.assertFalse(copy.isEqual(BgReading(injector))) - } - - @Test fun calculateDirection() { - val bgReading = BgReading(injector) - val bgReadingsList: List? = null -// val databaseHelper = Mockito.mock(DatabaseHelper::class.java) -// `when`(MainApp.getDbHelper()).thenReturn(databaseHelper) - `when`(databaseHelper.getAllBgreadingsDataFromTime(ArgumentMatchers.anyLong(), ArgumentMatchers.anyBoolean())).thenReturn(bgReadingsList) - Assert.assertEquals("NONE", bgReading.calculateDirection(databaseHelper)) - setReadings(72, 0) - Assert.assertEquals("DoubleUp", bgReading.calculateDirection(databaseHelper)) - setReadings(76, 60) - Assert.assertEquals("SingleUp", bgReading.calculateDirection(databaseHelper)) - setReadings(74, 65) - Assert.assertEquals("FortyFiveUp", bgReading.calculateDirection(databaseHelper)) - setReadings(72, 72) - Assert.assertEquals("Flat", bgReading.calculateDirection(databaseHelper)) - setReadings(0, 72) - Assert.assertEquals("DoubleDown", bgReading.calculateDirection(databaseHelper)) - setReadings(60, 76) - Assert.assertEquals("SingleDown", bgReading.calculateDirection(databaseHelper)) - setReadings(65, 74) - Assert.assertEquals("FortyFiveDown", bgReading.calculateDirection(databaseHelper)) - } - - @Before - fun prepareMock() { - } - - fun setReadings(current_value: Int, previous_value: Int) { - val now = BgReading(injector) - now.value = current_value.toDouble() - now.date = System.currentTimeMillis() - val previous = BgReading(injector) - previous.value = previous_value.toDouble() - previous.date = System.currentTimeMillis() - 6 * 60 * 1000L - val bgReadings: MutableList = mutableListOf() - bgReadings.add(now) - bgReadings.add(previous) - `when`(databaseHelper.getAllBgreadingsDataFromTime(ArgumentMatchers.anyLong(), ArgumentMatchers.anyBoolean())).thenReturn(bgReadings) - } -} \ No newline at end of file diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/aps/loop/APSResultTest.kt b/app/src/test/java/info/nightscout/androidaps/plugins/aps/loop/APSResultTest.kt index b2acc8ae66..3c7b148760 100644 --- a/app/src/test/java/info/nightscout/androidaps/plugins/aps/loop/APSResultTest.kt +++ b/app/src/test/java/info/nightscout/androidaps/plugins/aps/loop/APSResultTest.kt @@ -188,7 +188,7 @@ class APSResultTest : TestBaseWithProfile() { apsResult.rate(20.0).tempBasalRequested(true) Assert.assertEquals(20.0, safeGetDouble(apsResult.json(), "rate"), 0.0) apsResult.rate(20.0).tempBasalRequested(false) - Assert.assertEquals(false, apsResult.json().has("rate")) + Assert.assertEquals(false, apsResult.json()?.has("rate")) } @Before diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerBgTest.kt b/app/src/test/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerBgTest.kt index 4d8e2b5442..430568c484 100644 --- a/app/src/test/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerBgTest.kt +++ b/app/src/test/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerBgTest.kt @@ -3,10 +3,9 @@ package info.nightscout.androidaps.plugins.general.automation.triggers import com.google.common.base.Optional import info.nightscout.androidaps.Constants import info.nightscout.androidaps.R -import info.nightscout.androidaps.db.BgReading +import info.nightscout.androidaps.database.entities.GlucoseValue import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.plugins.general.automation.elements.Comparator -import info.nightscout.androidaps.plugins.general.nsclient.data.NSSgv import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin import info.nightscout.androidaps.utils.DateUtil import org.json.JSONObject @@ -93,9 +92,16 @@ class TriggerBgTest : TriggerTestBase() { Assert.assertEquals(Optional.of(R.drawable.ic_cp_bgcheck), TriggerBg(injector).icon()) } - private fun generateOneCurrentRecordBgData(): List { - val list: MutableList = ArrayList() - list.add(BgReading(injector, NSSgv(JSONObject("{\"mgdl\":214,\"mills\":" + (now - 1) + ",\"direction\":\"Flat\"}")))) + private fun generateOneCurrentRecordBgData(): List { + val list: MutableList = ArrayList() + list.add(GlucoseValue( + raw = 0.0, + noise = 0.0, + value = 214.0, + timestamp = now - 1, + sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, + trendArrow = GlucoseValue.TrendArrow.FLAT + )) return list } } \ No newline at end of file diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerDeltaTest.kt b/app/src/test/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerDeltaTest.kt index acbc3bb5dd..977b740320 100644 --- a/app/src/test/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerDeltaTest.kt +++ b/app/src/test/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerDeltaTest.kt @@ -3,11 +3,10 @@ package info.nightscout.androidaps.plugins.general.automation.triggers import com.google.common.base.Optional import info.nightscout.androidaps.Constants import info.nightscout.androidaps.R -import info.nightscout.androidaps.db.BgReading +import info.nightscout.androidaps.database.entities.GlucoseValue import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.plugins.general.automation.elements.Comparator import info.nightscout.androidaps.plugins.general.automation.elements.InputDelta.DeltaType -import info.nightscout.androidaps.plugins.general.nsclient.data.NSSgv import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin import info.nightscout.androidaps.utils.DateUtil import org.json.JSONObject @@ -101,16 +100,16 @@ class TriggerDeltaTest : TriggerTestBase() { Assert.assertTrue(t.units == Constants.MGDL) } - private fun generateValidBgData(): List { - val list: MutableList = ArrayList() - list.add(BgReading(injector, NSSgv(JSONObject("{\"mgdl\":214,\"mills\":1514766900000,\"direction\":\"Flat\"}")))) - list.add(BgReading(injector, NSSgv(JSONObject("{\"mgdl\":216,\"mills\":1514766600000,\"direction\":\"Flat\"}")))) // +2 - list.add(BgReading(injector, NSSgv(JSONObject("{\"mgdl\":219,\"mills\":1514766300000,\"direction\":\"Flat\"}")))) // +3 - list.add(BgReading(injector, NSSgv(JSONObject("{\"mgdl\":223,\"mills\":1514766000000,\"direction\":\"Flat\"}")))) // +4 - list.add(BgReading(injector, NSSgv(JSONObject("{\"mgdl\":222,\"mills\":1514765700000,\"direction\":\"Flat\"}")))) - list.add(BgReading(injector, NSSgv(JSONObject("{\"mgdl\":224,\"mills\":1514765400000,\"direction\":\"Flat\"}")))) - list.add(BgReading(injector, NSSgv(JSONObject("{\"mgdl\":226,\"mills\":1514765100000,\"direction\":\"Flat\"}")))) - list.add(BgReading(injector, NSSgv(JSONObject("{\"mgdl\":228,\"mills\":1514764800000,\"direction\":\"Flat\"}")))) + private fun generateValidBgData(): List { + val list: MutableList = ArrayList() + list.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 214.0, timestamp = 1514766900000, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + list.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 216.0, timestamp = 1514766600000, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + list.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 219.0, timestamp = 1514766300000, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + list.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 223.0, timestamp = 1514766000000, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + list.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 222.0, timestamp = 1514765700000, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + list.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 224.0, timestamp = 1514765400000, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + list.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 226.0, timestamp = 1514765100000, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + list.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 228.0, timestamp = 1514764800000, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) return list } } \ No newline at end of file diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerTestBase.kt b/app/src/test/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerTestBase.kt index b610dd3188..df948f28c5 100644 --- a/app/src/test/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerTestBase.kt +++ b/app/src/test/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerTestBase.kt @@ -4,9 +4,7 @@ import android.content.Context import dagger.android.AndroidInjector import dagger.android.HasAndroidInjector import info.nightscout.androidaps.TestBaseWithProfile -import info.nightscout.androidaps.db.BgReading import info.nightscout.androidaps.interfaces.ActivePluginProvider -import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.general.automation.AutomationPlugin import info.nightscout.androidaps.plugins.general.automation.elements.InputBg @@ -73,7 +71,7 @@ open class TriggerTestBase : TestBaseWithProfile() { if (it is InputBg) { it.profileFunction = profileFunction } - if (it is InputTempTarget) { + if (it is InputTempTarget) { it.profileFunction = profileFunction } if (it is GlucoseStatus) { @@ -83,9 +81,6 @@ open class TriggerTestBase : TestBaseWithProfile() { if (it is StaticLabel) { it.resourceHelper = resourceHelper } - if (it is BgReading) { - it.dateUtil = dateUtil - } } } diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPluginTest.kt b/app/src/test/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPluginTest.kt index 5c5c79f016..dc72598590 100644 --- a/app/src/test/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPluginTest.kt +++ b/app/src/test/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPluginTest.kt @@ -10,7 +10,7 @@ import info.nightscout.androidaps.R import info.nightscout.androidaps.TestBaseWithProfile import info.nightscout.androidaps.data.IobTotal import info.nightscout.androidaps.data.PumpEnactResult -import info.nightscout.androidaps.db.BgReading +import info.nightscout.androidaps.database.entities.GlucoseValue import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.CommandQueueProvider import info.nightscout.androidaps.interfaces.Constraint @@ -39,9 +39,6 @@ import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.ArgumentMatchers -import org.mockito.ArgumentMatchers.any -import org.mockito.ArgumentMatchers.anyString -import org.mockito.ArgumentMatchers.eq import org.mockito.Mock import org.mockito.Mockito import org.mockito.Mockito.`when` @@ -75,12 +72,6 @@ class SmsCommunicatorPluginTest : TestBaseWithProfile() { it.aapsLogger = aapsLogger it.resourceHelper = resourceHelper } - if (it is BgReading) { - it.aapsLogger = aapsLogger - it.defaultValueHelper = defaultValueHelper - it.resourceHelper = resourceHelper - it.profileFunction = profileFunction - } if (it is AuthRequest) { it.aapsLogger = aapsLogger it.smsCommunicatorPlugin = smsCommunicatorPlugin @@ -98,9 +89,8 @@ class SmsCommunicatorPluginTest : TestBaseWithProfile() { private var hasBeenRun = false @Before fun prepareTests() { - val reading = BgReading(injector) - reading.value = 100.0 - val bgList: MutableList = ArrayList() + val reading = GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = 1514766900000, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT) + val bgList: MutableList = ArrayList() bgList.add(reading) `when`(iobCobCalculatorPlugin.dataLock).thenReturn(Unit) @@ -176,7 +166,7 @@ class SmsCommunicatorPluginTest : TestBaseWithProfile() { `when`(profileFunction.getUnits()).thenReturn(Constants.MGDL) `when`(otp.name()).thenReturn("User") - `when`(otp.checkOTP(anyString())).thenReturn(OneTimePasswordValidationResult.OK) + `when`(otp.checkOTP(ArgumentMatchers.anyString())).thenReturn(OneTimePasswordValidationResult.OK) `when`(resourceHelper.gs(R.string.smscommunicator_remotecommandnotallowed)).thenReturn("Remote command is not allowed") `when`(resourceHelper.gs(R.string.sms_wrongcode)).thenReturn("Wrong code. Command cancelled.") @@ -195,7 +185,7 @@ class SmsCommunicatorPluginTest : TestBaseWithProfile() { `when`(resourceHelper.gs(R.string.smscommunicator_loopisdisabled)).thenReturn("Loop is disabled") `when`(resourceHelper.gs(R.string.smscommunicator_loopisenabled)).thenReturn("Loop is enabled") `when`(resourceHelper.gs(R.string.wrongformat)).thenReturn("Wrong format") - `when`(resourceHelper.gs(eq(R.string.wrongTbrDuration), any())).thenAnswer({ i: InvocationOnMock -> "TBR duration must be a multiple of " + i.getArguments()[1] + " minutes and greater than 0."}) + `when`(resourceHelper.gs(ArgumentMatchers.eq(R.string.wrongTbrDuration), ArgumentMatchers.any())).thenAnswer({ i: InvocationOnMock -> "TBR duration must be a multiple of " + i.getArguments()[1] + " minutes and greater than 0." }) `when`(resourceHelper.gs(R.string.smscommunicator_loophasbeendisabled)).thenReturn("Loop has been disabled") `when`(resourceHelper.gs(R.string.smscommunicator_loophasbeenenabled)).thenReturn("Loop has been enabled") `when`(resourceHelper.gs(R.string.smscommunicator_tempbasalcanceled)).thenReturn("Temp basal canceled") @@ -450,9 +440,9 @@ class SmsCommunicatorPluginTest : TestBaseWithProfile() { passCode = smsCommunicatorPlugin.messageToConfirm?.confirmCode!! // ignore from other number smsCommunicatorPlugin.processSms(Sms("5678", passCode)) - `when`(otp.checkOTP(anyString())).thenReturn(OneTimePasswordValidationResult.ERROR_WRONG_OTP) + `when`(otp.checkOTP(ArgumentMatchers.anyString())).thenReturn(OneTimePasswordValidationResult.ERROR_WRONG_OTP) smsCommunicatorPlugin.processSms(Sms("1234", "XXXX")) - `when`(otp.checkOTP(anyString())).thenReturn(OneTimePasswordValidationResult.OK) + `when`(otp.checkOTP(ArgumentMatchers.anyString())).thenReturn(OneTimePasswordValidationResult.OK) Assert.assertEquals("XXXX", smsCommunicatorPlugin.messages[3].text) Assert.assertEquals("Wrong code. Command cancelled.", smsCommunicatorPlugin.messages[4].text) //then correct code should not work diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/GlucoseStatusTest.kt b/app/src/test/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/GlucoseStatusTest.kt index 1f96b86b83..49230292e7 100644 --- a/app/src/test/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/GlucoseStatusTest.kt +++ b/app/src/test/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/GlucoseStatusTest.kt @@ -3,12 +3,9 @@ package info.nightscout.androidaps.plugins.iob.iobCobCalculator import dagger.android.AndroidInjector import dagger.android.HasAndroidInjector import info.nightscout.androidaps.TestBase -import info.nightscout.androidaps.db.BgReading -import info.nightscout.androidaps.plugins.general.nsclient.data.NSSgv +import info.nightscout.androidaps.database.entities.GlucoseValue import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.T -import org.json.JSONException -import org.json.JSONObject import org.junit.Assert import org.junit.Before import org.junit.Test @@ -36,9 +33,6 @@ class GlucoseStatusTest : TestBase() { it.aapsLogger = aapsLogger it.iobCobCalculatorPlugin = iobCobCalculatorPlugin } - if (it is BgReading) { - it.dateUtil = dateUtil - } } } @@ -127,78 +121,57 @@ class GlucoseStatusTest : TestBase() { } // [{"mgdl":214,"mills":1521895773113,"device":"xDrip-DexcomG5","direction":"Flat","filtered":191040,"unfiltered":205024,"noise":1,"rssi":100},{"mgdl":219,"mills":1521896073352,"device":"xDrip-DexcomG5","direction":"Flat","filtered":200160,"unfiltered":209760,"noise":1,"rssi":100},{"mgdl":222,"mills":1521896372890,"device":"xDrip-DexcomG5","direction":"Flat","filtered":207360,"unfiltered":212512,"noise":1,"rssi":100},{"mgdl":220,"mills":1521896673062,"device":"xDrip-DexcomG5","direction":"Flat","filtered":211488,"unfiltered":210688,"noise":1,"rssi":100},{"mgdl":193,"mills":1521896972933,"device":"xDrip-DexcomG5","direction":"Flat","filtered":212384,"unfiltered":208960,"noise":1,"rssi":100},{"mgdl":181,"mills":1521897273336,"device":"xDrip-DexcomG5","direction":"SingleDown","filtered":210592,"unfiltered":204320,"noise":1,"rssi":100},{"mgdl":176,"mills":1521897572875,"device":"xDrip-DexcomG5","direction":"FortyFiveDown","filtered":206720,"unfiltered":197440,"noise":1,"rssi":100},{"mgdl":168,"mills":1521897872929,"device":"xDrip-DexcomG5","direction":"FortyFiveDown","filtered":201024,"unfiltered":187904,"noise":1,"rssi":100},{"mgdl":161,"mills":1521898172814,"device":"xDrip-DexcomG5","direction":"FortyFiveDown","filtered":193376,"unfiltered":178144,"noise":1,"rssi":100},{"mgdl":148,"mills":1521898472879,"device":"xDrip-DexcomG5","direction":"SingleDown","filtered":183264,"unfiltered":161216,"noise":1,"rssi":100},{"mgdl":139,"mills":1521898772862,"device":"xDrip-DexcomG5","direction":"FortyFiveDown","filtered":170784,"unfiltered":148928,"noise":1,"rssi":100},{"mgdl":132,"mills":1521899072896,"device":"xDrip-DexcomG5","direction":"FortyFiveDown","filtered":157248,"unfiltered":139552,"noise":1,"rssi":100},{"mgdl":125,"mills":1521899372834,"device":"xDrip-DexcomG5","direction":"FortyFiveDown","filtered":144416,"unfiltered":129616.00000000001,"noise":1,"rssi":100},{"mgdl":128,"mills":1521899973456,"device":"xDrip-DexcomG5","direction":"Flat","filtered":130240.00000000001,"unfiltered":133536,"noise":1,"rssi":100},{"mgdl":132,"mills":1521900573287,"device":"xDrip-DexcomG5","direction":"Flat","filtered":133504,"unfiltered":138720,"noise":1,"rssi":100},{"mgdl":127,"mills":1521900873711,"device":"xDrip-DexcomG5","direction":"Flat","filtered":136480,"unfiltered":132992,"noise":1,"rssi":100},{"mgdl":127,"mills":1521901180151,"device":"xDrip-DexcomG5","direction":"Flat","filtered":136896,"unfiltered":132128,"noise":1,"rssi":100},{"mgdl":125,"mills":1521901473582,"device":"xDrip-DexcomG5","direction":"Flat","filtered":134624,"unfiltered":129696,"noise":1,"rssi":100},{"mgdl":120,"mills":1521901773597,"device":"xDrip-DexcomG5","direction":"Flat","filtered":130704.00000000001,"unfiltered":123376,"noise":1,"rssi":100},{"mgdl":116,"mills":1521902075855,"device":"xDrip-DexcomG5","direction":"Flat","filtered":126272,"unfiltered":118448,"noise":1,"rssi":100}] - private fun generateValidBgData(): List { - val list: MutableList = ArrayList() - try { - list.add(BgReading(injector, NSSgv(JSONObject("{\"mgdl\":214,\"mills\":1514766900000,\"direction\":\"Flat\"}")))) - list.add(BgReading(injector, NSSgv(JSONObject("{\"mgdl\":216,\"mills\":1514766600000,\"direction\":\"Flat\"}")))) // +2 - list.add(BgReading(injector, NSSgv(JSONObject("{\"mgdl\":219,\"mills\":1514766300000,\"direction\":\"Flat\"}")))) // +3 - list.add(BgReading(injector, NSSgv(JSONObject("{\"mgdl\":223,\"mills\":1514766000000,\"direction\":\"Flat\"}")))) // +4 - list.add(BgReading(injector, NSSgv(JSONObject("{\"mgdl\":222,\"mills\":1514765700000,\"direction\":\"Flat\"}")))) - list.add(BgReading(injector, NSSgv(JSONObject("{\"mgdl\":224,\"mills\":1514765400000,\"direction\":\"Flat\"}")))) - list.add(BgReading(injector, NSSgv(JSONObject("{\"mgdl\":226,\"mills\":1514765100000,\"direction\":\"Flat\"}")))) - list.add(BgReading(injector, NSSgv(JSONObject("{\"mgdl\":228,\"mills\":1514764800000,\"direction\":\"Flat\"}")))) - } catch (e: JSONException) { - throw RuntimeException(e) - } + private fun generateValidBgData(): List { + val list: MutableList = ArrayList() + list.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 214.0, timestamp = 1514766900000, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + list.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 216.0, timestamp = 1514766600000, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + list.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 219.0, timestamp = 1514766300000, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + list.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 223.0, timestamp = 1514766000000, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + list.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 222.0, timestamp = 1514765700000, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + list.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 224.0, timestamp = 1514765400000, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + list.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 226.0, timestamp = 1514765100000, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + list.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 228.0, timestamp = 1514764800000, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) return list } - private fun generateMostRecentBgData(): List { - val list: MutableList = ArrayList() - try { - list.add(BgReading(injector, NSSgv(JSONObject("{\"mgdl\":214,\"mills\":1514766900000,\"direction\":\"Flat\"}")))) - list.add(BgReading(injector, NSSgv(JSONObject("{\"mgdl\":216,\"mills\":1514766800000,\"direction\":\"Flat\"}")))) // +2 - list.add(BgReading(injector, NSSgv(JSONObject("{\"mgdl\":216,\"mills\":1514766600000,\"direction\":\"Flat\"}")))) - } catch (e: JSONException) { - throw RuntimeException(e) - } + private fun generateMostRecentBgData(): List { + val list: MutableList = ArrayList() + list.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 214.0, timestamp = 1514766900000, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + list.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 216.0, timestamp = 1514766800000, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + list.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 216.0, timestamp = 1514766600000, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) return list } - private fun generateInsufficientBgData(): List { + private fun generateInsufficientBgData(): List { return ArrayList() } - private fun generateOldBgData(): List { - val list: MutableList = ArrayList() - try { - list.add(BgReading(injector, NSSgv(JSONObject("{\"mgdl\":228,\"mills\":1514764800000,\"direction\":\"Flat\"}")))) - } catch (e: JSONException) { - throw RuntimeException(e) - } + private fun generateOldBgData(): List { + val list: MutableList = ArrayList() + list.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 228.0, timestamp = 1514764800000, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) return list } - private fun generateOneCurrentRecordBgData(): List { - val list: MutableList = ArrayList() - try { - list.add(BgReading(injector, NSSgv(JSONObject("{\"mgdl\":214,\"mills\":1514766900000,\"direction\":\"Flat\"}")))) - } catch (e: JSONException) { - throw RuntimeException(e) - } + private fun generateOneCurrentRecordBgData(): List { + val list: MutableList = ArrayList() + list.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 214.0, timestamp = 1514766900000, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) return list } - private fun generateLibreTestData(): List { - val list: MutableList = ArrayList() - try { - val endTime = 1514766900000L - val latestReading = 100.0 - // Now - list.add(BgReading(injector, NSSgv(JSONObject("{\"mgdl\":$latestReading,\"mills\":$endTime,\"direction\":\"Flat\"}")))) - // One minute ago - list.add(BgReading(injector, NSSgv(JSONObject("{\"mgdl\":" + latestReading + ",\"mills\":" + (endTime - 1000 * 60 * 1) + ",\"direction\":\"Flat\"}")))) - // Two minutes ago - list.add(BgReading(injector, NSSgv(JSONObject("{\"mgdl\":" + latestReading + ",\"mills\":" + (endTime - 1000 * 60 * 2) + ",\"direction\":\"Flat\"}")))) + private fun generateLibreTestData(): List { + val list: MutableList = ArrayList() + val endTime = 1514766900000L + val latestReading = 100.0 + // Now + list.add(GlucoseValue(raw = 0.0, noise = 0.0, value = latestReading, timestamp = endTime, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + // One minute ago + list.add(GlucoseValue(raw = 0.0, noise = 0.0, value = latestReading, timestamp = endTime - 1000 * 60 * 1, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + // Two minutes ago + list.add(GlucoseValue(raw = 0.0, noise = 0.0, value = latestReading, timestamp = endTime - 1000 * 60 * 2, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) - // Three minutes and beyond at constant rate - for (i in 3..49) { - list.add(BgReading(injector, NSSgv(JSONObject("{\"mgdl\":" + (latestReading + i * 2) + ",\"mills\":" + (endTime - 1000 * 60 * i) + ",\"direction\":\"Flat\"}")))) - } - } catch (e: JSONException) { - throw RuntimeException(e) - } + // Three minutes and beyond at constant rate + for (i in 3..49) + list.add(GlucoseValue(raw = 0.0, noise = 0.0, value = latestReading + i * 2, timestamp = endTime - 1000 * 60 * i, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) return list } } \ No newline at end of file diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/IobCobCalculatorPluginTest.kt b/app/src/test/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/IobCobCalculatorPluginTest.kt index 1c13d8acfa..6c1f9ec991 100644 --- a/app/src/test/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/IobCobCalculatorPluginTest.kt +++ b/app/src/test/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/IobCobCalculatorPluginTest.kt @@ -3,10 +3,11 @@ package info.nightscout.androidaps.plugins.iob.iobCobCalculator import dagger.android.AndroidInjector import dagger.android.HasAndroidInjector import info.nightscout.androidaps.TestBase -import info.nightscout.androidaps.db.BgReading +import info.nightscout.androidaps.database.AppRepository +import info.nightscout.androidaps.database.entities.GlucoseValue import info.nightscout.androidaps.interfaces.ActivePluginProvider -import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.interfaces.ProfileFunction +import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.sensitivity.SensitivityAAPSPlugin import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAveragePlugin @@ -27,7 +28,7 @@ import org.powermock.modules.junit4.PowerMockRunner import java.util.* @RunWith(PowerMockRunner::class) -@PrepareForTest(FabricPrivacy::class) +@PrepareForTest(FabricPrivacy::class, AppRepository::class) class IobCobCalculatorPluginTest : TestBase() { @Mock lateinit var sp: SP @@ -42,129 +43,123 @@ class IobCobCalculatorPluginTest : TestBase() { @Mock lateinit var defaultValueHelper: DefaultValueHelper @Mock lateinit var fabricPrivacy: FabricPrivacy @Mock lateinit var dateUtil: DateUtil + @Mock lateinit var repository: AppRepository lateinit var iobCobCalculatorPlugin: IobCobCalculatorPlugin val injector = HasAndroidInjector { AndroidInjector { - if (it is BgReading) { - it.aapsLogger = aapsLogger - it.defaultValueHelper = defaultValueHelper - it.resourceHelper = resourceHelper - it.profileFunction = profileFunction - it.dateUtil = dateUtil - } } } @Before fun mock() { - iobCobCalculatorPlugin = IobCobCalculatorPlugin(injector, aapsLogger, aapsSchedulers, rxBus, sp, resourceHelper, profileFunction, activePlugin, treatmentsPlugin, sensitivityOref1Plugin, sensitivityAAPSPlugin, sensitivityWeightedAveragePlugin, fabricPrivacy, dateUtil) + iobCobCalculatorPlugin = IobCobCalculatorPlugin(injector, aapsLogger, aapsSchedulers, rxBus, sp, resourceHelper, profileFunction, activePlugin, treatmentsPlugin, sensitivityOref1Plugin, sensitivityAAPSPlugin, sensitivityWeightedAveragePlugin, fabricPrivacy, dateUtil, repository) } @Test fun isAbout5minDataTest() { - val bgReadingList: MutableList = ArrayList() + val bgReadingList: MutableList = ArrayList() // Super data should not be touched bgReadingList.clear() - bgReadingList.add(BgReading(injector).date(T.mins(20).msecs()).value(100.0)) - bgReadingList.add(BgReading(injector).date(T.mins(15).msecs()).value(100.0)) - bgReadingList.add(BgReading(injector).date(T.mins(10).msecs()).value(100.0)) - bgReadingList.add(BgReading(injector).date(T.mins(5).msecs()).value(100.0)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(20).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(15).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(10).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(5).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) iobCobCalculatorPlugin.bgReadings = bgReadingList Assert.assertEquals(true, iobCobCalculatorPlugin.isAbout5minData) // too much shifted data should return false bgReadingList.clear() - bgReadingList.add(BgReading(injector).date(T.mins(20).msecs()).value(100.0)) - bgReadingList.add(BgReading(injector).date(T.mins(15).msecs()).value(100.0)) - bgReadingList.add(BgReading(injector).date(T.mins(9).msecs()).value(100.0)) - bgReadingList.add(BgReading(injector).date(T.mins(5).msecs()).value(100.0)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(20).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(15).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(9).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(5).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) iobCobCalculatorPlugin.bgReadings = bgReadingList Assert.assertEquals(false, iobCobCalculatorPlugin.isAbout5minData) // too much shifted and missing data should return false bgReadingList.clear() - bgReadingList.add(BgReading(injector).date(T.mins(20).msecs()).value(100.0)) - bgReadingList.add(BgReading(injector).date(T.mins(9).msecs()).value(100.0)) - bgReadingList.add(BgReading(injector).date(T.mins(5).msecs()).value(100.0)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(20).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(9).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(5).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) iobCobCalculatorPlugin.bgReadings = bgReadingList Assert.assertEquals(false, iobCobCalculatorPlugin.isAbout5minData) // too much shifted and missing data should return false bgReadingList.clear() - bgReadingList.add(BgReading(injector).date(T.mins(83).plus(T.secs(40)).msecs()).value(100.0)) - bgReadingList.add(BgReading(injector).date(T.mins(78).plus(T.secs(40)).msecs()).value(100.0)) - bgReadingList.add(BgReading(injector).date(T.mins(73).plus(T.secs(40)).msecs()).value(100.0)) - bgReadingList.add(BgReading(injector).date(T.mins(68).plus(T.secs(40)).msecs()).value(100.0)) - bgReadingList.add(BgReading(injector).date(T.mins(63).plus(T.secs(40)).msecs()).value(100.0)) - bgReadingList.add(BgReading(injector).date(T.mins(58).plus(T.secs(40)).msecs()).value(100.0)) - bgReadingList.add(BgReading(injector).date(T.mins(53).plus(T.secs(40)).msecs()).value(100.0)) - bgReadingList.add(BgReading(injector).date(T.mins(48).plus(T.secs(40)).msecs()).value(100.0)) - bgReadingList.add(BgReading(injector).date(T.mins(43).plus(T.secs(40)).msecs()).value(100.0)) - bgReadingList.add(BgReading(injector).date(T.mins(38).plus(T.secs(33)).msecs()).value(100.0)) - bgReadingList.add(BgReading(injector).date(T.mins(33).plus(T.secs(1)).msecs()).value(100.0)) - bgReadingList.add(BgReading(injector).date(T.mins(28).plus(T.secs(0)).msecs()).value(100.0)) - bgReadingList.add(BgReading(injector).date(T.mins(23).plus(T.secs(0)).msecs()).value(100.0)) - bgReadingList.add(BgReading(injector).date(T.mins(16).plus(T.secs(36)).msecs()).value(100.0)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(83).plus(T.secs(40)).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(78).plus(T.secs(40)).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(73).plus(T.secs(40)).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(68).plus(T.secs(40)).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(63).plus(T.secs(40)).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(58).plus(T.secs(40)).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(53).plus(T.secs(40)).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(48).plus(T.secs(40)).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(43).plus(T.secs(40)).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(38).plus(T.secs(40)).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(33).plus(T.secs(1)).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(28).plus(T.secs(0)).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(23).plus(T.secs(0)).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(16).plus(T.secs(36)).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) iobCobCalculatorPlugin.bgReadings = bgReadingList Assert.assertEquals(false, iobCobCalculatorPlugin.isAbout5minData) // slightly shifted data should return true bgReadingList.clear() - bgReadingList.add(BgReading(injector).date(T.mins(20).msecs()).value(100.0)) - bgReadingList.add(BgReading(injector).date(T.mins(15).msecs()).value(100.0)) - bgReadingList.add(BgReading(injector).date(T.mins(10).msecs() - T.secs(10).msecs()).value(100.0)) - bgReadingList.add(BgReading(injector).date(T.mins(5).msecs()).value(100.0)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(20).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(15).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(10).plus(T.secs(10)).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(5).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) iobCobCalculatorPlugin.bgReadings = bgReadingList Assert.assertEquals(true, iobCobCalculatorPlugin.isAbout5minData) // slightly shifted and missing data should return true bgReadingList.clear() - bgReadingList.add(BgReading(injector).date(T.mins(20).msecs()).value(100.0)) - bgReadingList.add(BgReading(injector).date(T.mins(10).msecs() - T.secs(10).msecs()).value(100.0)) - bgReadingList.add(BgReading(injector).date(T.mins(5).msecs()).value(100.0)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(20).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(10).plus(T.secs(10)).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(5).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) iobCobCalculatorPlugin.bgReadings = bgReadingList Assert.assertEquals(true, iobCobCalculatorPlugin.isAbout5minData) } @Test fun createBucketedData5minTest() { - val bgReadingList: MutableList = ArrayList() + val bgReadingList: MutableList = ArrayList() // Super data should not be touched bgReadingList.clear() - bgReadingList.add(BgReading(injector).date(T.mins(20).msecs()).value(100.0)) - bgReadingList.add(BgReading(injector).date(T.mins(15).msecs()).value(100.0)) - bgReadingList.add(BgReading(injector).date(T.mins(10).msecs()).value(100.0)) - bgReadingList.add(BgReading(injector).date(T.mins(5).msecs()).value(100.0)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(20).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(15).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(10).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(5).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) iobCobCalculatorPlugin.bgReadings = bgReadingList Assert.assertEquals(true, iobCobCalculatorPlugin.isAbout5minData) iobCobCalculatorPlugin.createBucketedData() - Assert.assertEquals(bgReadingList[0].date, iobCobCalculatorPlugin.bucketedData[0].timestamp) - Assert.assertEquals(bgReadingList[3].date, iobCobCalculatorPlugin.bucketedData[3].timestamp) + Assert.assertEquals(bgReadingList[0].timestamp, iobCobCalculatorPlugin.bucketedData[0].timestamp) + Assert.assertEquals(bgReadingList[3].timestamp, iobCobCalculatorPlugin.bucketedData[3].timestamp) Assert.assertEquals(bgReadingList.size.toLong(), iobCobCalculatorPlugin.bucketedData.size.toLong()) // Missing value should be replaced bgReadingList.clear() - bgReadingList.add(BgReading(injector).date(T.mins(20).msecs()).value(100.0)) - bgReadingList.add(BgReading(injector).date(T.mins(10).msecs()).value(100.0)) - bgReadingList.add(BgReading(injector).date(T.mins(5).msecs()).value(100.0)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(20).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(10).plus(T.secs(10)).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(5).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) iobCobCalculatorPlugin.bgReadings = bgReadingList Assert.assertEquals(true, iobCobCalculatorPlugin.isAbout5minData) iobCobCalculatorPlugin.createBucketedData() - Assert.assertEquals(bgReadingList[0].date, iobCobCalculatorPlugin.bucketedData[0].timestamp) - Assert.assertEquals(bgReadingList[2].date, iobCobCalculatorPlugin.bucketedData[3].timestamp) + Assert.assertEquals(bgReadingList[0].timestamp, iobCobCalculatorPlugin.bucketedData[0].timestamp) + Assert.assertEquals(bgReadingList[2].timestamp, iobCobCalculatorPlugin.bucketedData[3].timestamp) Assert.assertEquals(bgReadingList.size + 1.toLong(), iobCobCalculatorPlugin.bucketedData.size.toLong()) // drift should be cleared bgReadingList.clear() - bgReadingList.add(BgReading(injector).date(T.mins(20).msecs()).value(100.0)) - bgReadingList.add(BgReading(injector).date(T.mins(15).msecs() + T.secs(10).msecs()).value(100.0)) - bgReadingList.add(BgReading(injector).date(T.mins(10).msecs() + T.secs(10).msecs()).value(100.0)) - bgReadingList.add(BgReading(injector).date(T.mins(5).msecs() - T.secs(10).msecs()).value(100.0)) - bgReadingList.add(BgReading(injector).date(T.mins(0).msecs()).value(100.0)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(20).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(15).msecs() + T.secs(10).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(10).msecs() + T.secs(10).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(5).msecs() + T.secs(10).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(0).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) iobCobCalculatorPlugin.bgReadings = bgReadingList Assert.assertEquals(true, iobCobCalculatorPlugin.isAbout5minData) iobCobCalculatorPlugin.createBucketedData() @@ -176,8 +171,8 @@ class IobCobCalculatorPluginTest : TestBase() { // bucketed data should return null if not enough bg data bgReadingList.clear() - bgReadingList.add(BgReading(injector).date(T.mins(30).msecs()).value(100.0)) - bgReadingList.add(BgReading(injector).date(T.mins(5).msecs()).value(100.0)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(30).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(5).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) iobCobCalculatorPlugin.bgReadings = bgReadingList Assert.assertEquals(true, iobCobCalculatorPlugin.isAbout5minData) iobCobCalculatorPlugin.createBucketedData() @@ -185,9 +180,9 @@ class IobCobCalculatorPluginTest : TestBase() { // data should be reconstructed bgReadingList.clear() - bgReadingList.add(BgReading(injector).date(T.mins(50).msecs()).value(100.0)) - bgReadingList.add(BgReading(injector).date(T.mins(45).msecs()).value(90.0)) - bgReadingList.add(BgReading(injector).date(T.mins(20).msecs()).value(40.0)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(50).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 90.0, timestamp = T.mins(45).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 40.0, timestamp = T.mins(20).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) iobCobCalculatorPlugin.bgReadings = bgReadingList Assert.assertEquals(true, iobCobCalculatorPlugin.isAbout5minData) iobCobCalculatorPlugin.createBucketedData() @@ -201,9 +196,9 @@ class IobCobCalculatorPluginTest : TestBase() { // non 5min data should be reconstructed bgReadingList.clear() - bgReadingList.add(BgReading(injector).date(T.mins(50).msecs()).value(100.0)) - bgReadingList.add(BgReading(injector).date(T.mins(48).msecs()).value(96.0)) - bgReadingList.add(BgReading(injector).date(T.mins(20).msecs()).value(40.0)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(50).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 96.0, timestamp = T.mins(48).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 40.0, timestamp = T.mins(20).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) iobCobCalculatorPlugin.bgReadings = bgReadingList Assert.assertEquals(false, iobCobCalculatorPlugin.isAbout5minData) iobCobCalculatorPlugin.createBucketedData() @@ -222,122 +217,34 @@ class IobCobCalculatorPluginTest : TestBase() { // real data gap test bgReadingList.clear() - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T13:34:55Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T13:14:55Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T13:09:55Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T13:04:55Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T12:59:55Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T12:54:55Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T12:49:55Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T12:44:55Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T12:39:55Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T12:34:55Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T12:29:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T12:24:55Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T12:19:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T12:14:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T12:09:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T12:04:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T11:59:55Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T11:54:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T11:49:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T11:44:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T11:39:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T11:34:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T11:29:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T11:24:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T11:19:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T11:14:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T11:09:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T11:04:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T10:59:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T10:54:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T10:49:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T10:44:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T10:39:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T10:34:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T10:29:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T10:24:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T10:19:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T10:14:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T10:09:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T10:04:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T09:59:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T09:54:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T09:49:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T09:44:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T09:39:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T09:35:05Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T09:30:17Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T09:24:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T09:19:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T09:14:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T09:09:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T09:04:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T08:59:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T08:54:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T08:49:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T08:44:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T08:40:02Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T08:34:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T08:29:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T08:24:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T08:19:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T08:14:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T08:09:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T08:04:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T07:59:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T07:54:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T07:49:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T07:44:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T07:39:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T07:34:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T07:30:03Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T07:25:17Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T07:19:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T07:14:58Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T07:09:58Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T07:04:58Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T06:59:58Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T06:54:58Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T06:49:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T06:44:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T06:39:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T06:34:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T06:29:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T06:24:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T06:19:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T06:14:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T06:10:03Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T06:04:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T05:59:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T05:54:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T05:49:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T05:44:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T05:39:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T05:34:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T05:29:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T05:24:57Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T05:19:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T05:14:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T05:09:57Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T05:04:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T04:59:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T04:54:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T04:50:03Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T04:44:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T04:39:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T04:34:57Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T04:29:57Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T04:24:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T04:19:57Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T04:14:57Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T04:10:03Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T04:04:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T03:59:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T03:54:56Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T03:50:03Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-09-05T03:44:57Z")).value(100.0)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = DateUtil.fromISODateString("2018-09-05T13:34:55Z").time, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = DateUtil.fromISODateString("2018-09-05T13:14:55Z").time, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = DateUtil.fromISODateString("2018-09-05T13:09:55Z").time, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = DateUtil.fromISODateString("2018-09-05T13:04:55Z").time, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = DateUtil.fromISODateString("2018-09-05T12:59:55Z").time, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = DateUtil.fromISODateString("2018-09-05T12:54:55Z").time, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = DateUtil.fromISODateString("2018-09-05T12:49:55Z").time, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = DateUtil.fromISODateString("2018-09-05T12:44:55Z").time, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = DateUtil.fromISODateString("2018-09-05T12:39:55Z").time, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = DateUtil.fromISODateString("2018-09-05T12:34:55Z").time, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = DateUtil.fromISODateString("2018-09-05T12:29:56Z").time, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = DateUtil.fromISODateString("2018-09-05T12:24:55Z").time, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = DateUtil.fromISODateString("2018-09-05T12:19:56Z").time, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = DateUtil.fromISODateString("2018-09-05T12:14:56Z").time, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = DateUtil.fromISODateString("2018-09-05T12:09:56Z").time, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = DateUtil.fromISODateString("2018-09-05T12:04:56Z").time, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = DateUtil.fromISODateString("2018-09-05T11:59:55Z").time, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = DateUtil.fromISODateString("2018-09-05T04:29:57Z").time, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = DateUtil.fromISODateString("2018-09-05T04:24:56Z").time, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = DateUtil.fromISODateString("2018-09-05T04:19:57Z").time, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = DateUtil.fromISODateString("2018-09-05T04:14:57Z").time, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = DateUtil.fromISODateString("2018-09-05T04:10:03Z").time, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = DateUtil.fromISODateString("2018-09-05T04:04:56Z").time, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = DateUtil.fromISODateString("2018-09-05T03:59:56Z").time, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = DateUtil.fromISODateString("2018-09-05T03:54:56Z").time, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = DateUtil.fromISODateString("2018-09-05T03:50:03Z").time, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = DateUtil.fromISODateString("2018-09-05T03:44:57Z").time, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) iobCobCalculatorPlugin.bgReadings = bgReadingList iobCobCalculatorPlugin.referenceTime = null Assert.assertEquals(true, iobCobCalculatorPlugin.isAbout5minData) @@ -347,34 +254,34 @@ class IobCobCalculatorPluginTest : TestBase() { // 5min 4sec data bgReadingList.clear() - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-10-05T06:33:40Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-10-05T06:28:36Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-10-05T06:23:32Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-10-05T06:18:28Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-10-05T06:13:24Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-10-05T06:08:19Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-10-05T06:03:16Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-10-05T05:58:11Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-10-05T05:53:07Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-10-05T05:48:03Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-10-05T05:42:58Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-10-05T05:37:54Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-10-05T05:32:51Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-10-05T05:27:46Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-10-05T05:22:42Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-10-05T05:17:38Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-10-05T05:12:33Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-10-05T05:07:29Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-10-05T05:02:26Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-10-05T04:57:21Z")).value(100.0)) - bgReadingList.add(BgReading(injector).date(DateUtil.fromISODateString("2018-10-05T04:52:17Z")).value(100.0)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = DateUtil.fromISODateString("2018-10-05T06:33:40Z").time, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = DateUtil.fromISODateString("2018-10-05T06:28:36Z").time, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = DateUtil.fromISODateString("2018-10-05T06:23:32Z").time, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = DateUtil.fromISODateString("2018-10-05T06:18:28Z").time, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = DateUtil.fromISODateString("2018-10-05T06:13:24Z").time, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = DateUtil.fromISODateString("2018-10-05T06:08:19Z").time, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = DateUtil.fromISODateString("2018-10-05T06:03:16Z").time, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = DateUtil.fromISODateString("2018-10-05T05:58:11Z").time, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = DateUtil.fromISODateString("2018-10-05T05:53:07Z").time, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = DateUtil.fromISODateString("2018-10-05T05:48:03Z").time, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = DateUtil.fromISODateString("2018-10-05T05:42:58Z").time, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = DateUtil.fromISODateString("2018-10-05T05:37:54Z").time, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = DateUtil.fromISODateString("2018-10-05T05:32:51Z").time, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = DateUtil.fromISODateString("2018-10-05T05:27:46Z").time, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = DateUtil.fromISODateString("2018-10-05T05:22:42Z").time, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = DateUtil.fromISODateString("2018-10-05T05:17:38Z").time, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = DateUtil.fromISODateString("2018-10-05T05:12:33Z").time, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = DateUtil.fromISODateString("2018-10-05T05:07:29Z").time, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = DateUtil.fromISODateString("2018-10-05T05:02:26Z").time, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = DateUtil.fromISODateString("2018-10-05T04:57:21Z").time, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = DateUtil.fromISODateString("2018-10-05T04:52:17Z").time, sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) iobCobCalculatorPlugin.bgReadings = bgReadingList Assert.assertEquals(false, iobCobCalculatorPlugin.isAbout5minData) } @Test fun bgReadingsTest() { - val bgReadingList: List = ArrayList() + val bgReadingList: List = ArrayList() iobCobCalculatorPlugin.bgReadings = bgReadingList Assert.assertEquals(bgReadingList, iobCobCalculatorPlugin.bgReadings) } @@ -386,47 +293,47 @@ class IobCobCalculatorPluginTest : TestBase() { @Test fun findNewerTest() { - val bgReadingList: MutableList = ArrayList() - bgReadingList.add(BgReading(injector).date(T.mins(20).msecs()).value(100.0)) - bgReadingList.add(BgReading(injector).date(T.mins(15).msecs()).value(100.0)) - bgReadingList.add(BgReading(injector).date(T.mins(10).msecs()).value(100.0)) - bgReadingList.add(BgReading(injector).date(T.mins(5).msecs()).value(100.0)) + val bgReadingList: MutableList = ArrayList() + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(20).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(15).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(10).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(5).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) iobCobCalculatorPlugin.bgReadings = bgReadingList - Assert.assertEquals(T.mins(10).msecs(), iobCobCalculatorPlugin.findNewer(T.mins(8).msecs())!!.date) - Assert.assertEquals(T.mins(5).msecs(), iobCobCalculatorPlugin.findNewer(T.mins(5).msecs())!!.date) - Assert.assertEquals(T.mins(10).msecs(), iobCobCalculatorPlugin.findNewer(T.mins(10).msecs())!!.date) - Assert.assertEquals(T.mins(20).msecs(), iobCobCalculatorPlugin.findNewer(T.mins(20).msecs())!!.date) + Assert.assertEquals(T.mins(10).msecs(), iobCobCalculatorPlugin.findNewer(T.mins(8).msecs())!!.timestamp) + Assert.assertEquals(T.mins(5).msecs(), iobCobCalculatorPlugin.findNewer(T.mins(5).msecs())!!.timestamp) + Assert.assertEquals(T.mins(10).msecs(), iobCobCalculatorPlugin.findNewer(T.mins(10).msecs())!!.timestamp) + Assert.assertEquals(T.mins(20).msecs(), iobCobCalculatorPlugin.findNewer(T.mins(20).msecs())!!.timestamp) Assert.assertEquals(null, iobCobCalculatorPlugin.findNewer(T.mins(22).msecs())) } @Test fun findOlderTest() { - val bgReadingList: MutableList = ArrayList() - bgReadingList.add(BgReading(injector).date(T.mins(20).msecs()).value(100.0)) - bgReadingList.add(BgReading(injector).date(T.mins(15).msecs()).value(100.0)) - bgReadingList.add(BgReading(injector).date(T.mins(10).msecs()).value(100.0)) - bgReadingList.add(BgReading(injector).date(T.mins(5).msecs()).value(100.0)) + val bgReadingList: MutableList = ArrayList() + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(20).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(15).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(10).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(5).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) iobCobCalculatorPlugin.bgReadings = bgReadingList - Assert.assertEquals(T.mins(5).msecs(), iobCobCalculatorPlugin.findOlder(T.mins(8).msecs())!!.date) - Assert.assertEquals(T.mins(5).msecs(), iobCobCalculatorPlugin.findOlder(T.mins(5).msecs())!!.date) - Assert.assertEquals(T.mins(10).msecs(), iobCobCalculatorPlugin.findOlder(T.mins(10).msecs())!!.date) - Assert.assertEquals(T.mins(20).msecs(), iobCobCalculatorPlugin.findOlder(T.mins(20).msecs())!!.date) + Assert.assertEquals(T.mins(5).msecs(), iobCobCalculatorPlugin.findOlder(T.mins(8).msecs())!!.timestamp) + Assert.assertEquals(T.mins(5).msecs(), iobCobCalculatorPlugin.findOlder(T.mins(5).msecs())!!.timestamp) + Assert.assertEquals(T.mins(10).msecs(), iobCobCalculatorPlugin.findOlder(T.mins(10).msecs())!!.timestamp) + Assert.assertEquals(T.mins(20).msecs(), iobCobCalculatorPlugin.findOlder(T.mins(20).msecs())!!.timestamp) Assert.assertEquals(null, iobCobCalculatorPlugin.findOlder(T.mins(4).msecs())) } @Test fun findPreviousTimeFromBucketedDataTest() { - val bgReadingList: MutableList = ArrayList() + val bgReadingList: MutableList = ArrayList() iobCobCalculatorPlugin.bgReadings = bgReadingList iobCobCalculatorPlugin.createBucketedData() Assert.assertEquals(null, iobCobCalculatorPlugin.findPreviousTimeFromBucketedData(1000)) // Super data should not be touched bgReadingList.clear() - bgReadingList.add(BgReading(injector).date(T.mins(20).msecs()).value(100.0)) - bgReadingList.add(BgReading(injector).date(T.mins(15).msecs()).value(100.0)) - bgReadingList.add(BgReading(injector).date(T.mins(10).msecs()).value(100.0)) - bgReadingList.add(BgReading(injector).date(T.mins(5).msecs()).value(100.0)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(20).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(15).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(10).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) + bgReadingList.add(GlucoseValue(raw = 0.0, noise = 0.0, value = 100.0, timestamp = T.mins(5).msecs(), sourceSensor = GlucoseValue.SourceSensor.UNKNOWN, trendArrow = GlucoseValue.TrendArrow.FLAT)) iobCobCalculatorPlugin.bgReadings = bgReadingList iobCobCalculatorPlugin.createBucketedData() Assert.assertEquals(null, iobCobCalculatorPlugin.findPreviousTimeFromBucketedData(T.mins(4).msecs())) diff --git a/core/src/main/java/info/nightscout/androidaps/core/di/CoreDataClassesModule.kt b/core/src/main/java/info/nightscout/androidaps/core/di/CoreDataClassesModule.kt index d17e1d0168..8696623a7c 100644 --- a/core/src/main/java/info/nightscout/androidaps/core/di/CoreDataClassesModule.kt +++ b/core/src/main/java/info/nightscout/androidaps/core/di/CoreDataClassesModule.kt @@ -2,6 +2,7 @@ package info.nightscout.androidaps.core.di import dagger.Module import dagger.android.ContributesAndroidInjector +import info.nightscout.androidaps.data.GlucoseValueDataPoint import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.data.PumpEnactResult import info.nightscout.androidaps.db.* @@ -19,7 +20,7 @@ abstract class CoreDataClassesModule { @ContributesAndroidInjector abstract fun profileInjector(): Profile @ContributesAndroidInjector abstract fun profileStoreInjector(): ProfileStore - @ContributesAndroidInjector abstract fun bgReadingInjector(): BgReading + @ContributesAndroidInjector abstract fun glucoseValueDataPointInjector(): GlucoseValueDataPoint @ContributesAndroidInjector abstract fun treatmentInjector(): Treatment @ContributesAndroidInjector abstract fun profileSwitchInjector(): ProfileSwitch @ContributesAndroidInjector abstract fun temporaryBasalInjector(): TemporaryBasal diff --git a/core/src/main/java/info/nightscout/androidaps/data/GlucoseValueDataPoint.kt b/core/src/main/java/info/nightscout/androidaps/data/GlucoseValueDataPoint.kt new file mode 100644 index 0000000000..9c884b5315 --- /dev/null +++ b/core/src/main/java/info/nightscout/androidaps/data/GlucoseValueDataPoint.kt @@ -0,0 +1,78 @@ +package info.nightscout.androidaps.data + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.Constants +import info.nightscout.androidaps.core.R +import info.nightscout.androidaps.database.entities.GlucoseValue +import info.nightscout.androidaps.interfaces.ProfileFunction +import info.nightscout.androidaps.plugins.general.overview.graphExtensions.DataPointWithLabelInterface +import info.nightscout.androidaps.plugins.general.overview.graphExtensions.PointsWithLabelGraphSeries +import info.nightscout.androidaps.utils.DefaultValueHelper +import info.nightscout.androidaps.utils.resources.ResourceHelper +import javax.inject.Inject + +class GlucoseValueDataPoint @Inject constructor( + val injector: HasAndroidInjector, + val data: GlucoseValue +) : DataPointWithLabelInterface { + + @Inject lateinit var defaultValueHelper: DefaultValueHelper + @Inject lateinit var profileFunction: ProfileFunction + @Inject lateinit var resourceHelper: ResourceHelper + + init { + injector.androidInjector().inject(this) + } + + fun valueToUnits(units: String): Double = + if (units == Constants.MGDL) data.value else data.value * Constants.MGDL_TO_MMOLL + + override fun getX(): Double { + return data.timestamp.toDouble() + } + + override fun getY(): Double { + return valueToUnits(profileFunction.getUnits()) + } + + override fun setY(y: Double) {} + override fun getLabel(): String? = null + override fun getDuration(): Long = 0 + override fun getShape(): PointsWithLabelGraphSeries.Shape = + if (isPrediction) PointsWithLabelGraphSeries.Shape.PREDICTION + else PointsWithLabelGraphSeries.Shape.BG + + override fun getSize(): Float = 1f + + override fun getColor(): Int { + val units = profileFunction.getUnits() + val lowLine = defaultValueHelper.determineLowLine() + val highLine = defaultValueHelper.determineHighLine() + return when { + isPrediction -> predictionColor + valueToUnits(units) < lowLine -> resourceHelper.gc(R.color.low) + valueToUnits(units) > highLine -> resourceHelper.gc(R.color.high) + else -> resourceHelper.gc(R.color.inrange) + } + } + + val predictionColor: Int + get() { + return when (data.sourceSensor) { + GlucoseValue.SourceSensor.IOB_PREDICTION -> resourceHelper.gc(R.color.iob) + GlucoseValue.SourceSensor.COB_PREDICTION -> resourceHelper.gc(R.color.cob) + GlucoseValue.SourceSensor.aCOB_PREDICTION -> -0x7f000001 and resourceHelper.gc(R.color.cob) + GlucoseValue.SourceSensor.UAM_PREDICTION -> resourceHelper.gc(R.color.uam) + GlucoseValue.SourceSensor.ZT_PREDICTION -> resourceHelper.gc(R.color.zt) + else -> R.color.white + } + } + + private val isPrediction: Boolean + get() = data.sourceSensor == GlucoseValue.SourceSensor.IOB_PREDICTION || + data.sourceSensor == GlucoseValue.SourceSensor.COB_PREDICTION || + data.sourceSensor == GlucoseValue.SourceSensor.aCOB_PREDICTION || + data.sourceSensor == GlucoseValue.SourceSensor.UAM_PREDICTION || + data.sourceSensor == GlucoseValue.SourceSensor.ZT_PREDICTION + +} \ No newline at end of file diff --git a/core/src/main/java/info/nightscout/androidaps/db/BgReading.kt b/core/src/main/java/info/nightscout/androidaps/db/BgReading.kt deleted file mode 100644 index dc233425a2..0000000000 --- a/core/src/main/java/info/nightscout/androidaps/db/BgReading.kt +++ /dev/null @@ -1,171 +0,0 @@ -package info.nightscout.androidaps.db - -import dagger.android.HasAndroidInjector -import info.nightscout.androidaps.Constants -import info.nightscout.androidaps.core.R -import info.nightscout.androidaps.database.AppRepository -import info.nightscout.androidaps.database.entities.GlucoseValue -import info.nightscout.androidaps.interfaces.ProfileFunction -import info.nightscout.androidaps.logging.AAPSLogger -import info.nightscout.androidaps.logging.LTag -import info.nightscout.androidaps.plugins.general.overview.graphExtensions.DataPointWithLabelInterface -import info.nightscout.androidaps.plugins.general.overview.graphExtensions.PointsWithLabelGraphSeries -import info.nightscout.androidaps.utils.DecimalFormatter -import info.nightscout.androidaps.utils.DefaultValueHelper -import info.nightscout.androidaps.utils.T -import info.nightscout.androidaps.utils.resources.ResourceHelper -import javax.inject.Inject - -class BgReading : DataPointWithLabelInterface { - @Inject lateinit var aapsLogger: AAPSLogger - @Inject lateinit var defaultValueHelper: DefaultValueHelper - @Inject lateinit var profileFunction: ProfileFunction - @Inject lateinit var resourceHelper: ResourceHelper - @Inject lateinit var repository: AppRepository - - var data: GlucoseValue - - // Compatibility functions - fun setDate(timeStamp: Long) { - data.timestamp = timeStamp - } - - fun getDate(): Long = data.timestamp - fun getValue(): Double = data.value - fun setValue(value: Double) { - data.value = value - } - - var isCOBPrediction = false // true when drawing predictions as bg points (COB) - var isaCOBPrediction = false // true when drawing predictions as bg points (aCOB) - var isIOBPrediction = false // true when drawing predictions as bg points (IOB) - var isUAMPrediction = false // true when drawing predictions as bg points (UAM) - var isZTPrediction = false // true when drawing predictions as bg points (ZT) - - @Deprecated("Create only with data") - constructor(injector: HasAndroidInjector) { - injector.androidInjector().inject(this) - data = GlucoseValue( - timestamp = 0, - utcOffset = 0, - raw = null, - value = 0.0, - trendArrow = GlucoseValue.TrendArrow.NONE, - noise = null, - sourceSensor = GlucoseValue.SourceSensor.UNKNOWN - ) - } - - constructor(injector: HasAndroidInjector, glucoseValue: GlucoseValue) { - injector.androidInjector().inject(this) - data = glucoseValue - } - - fun valueToUnits(units: String): Double = - if (units == Constants.MGDL) data.value else data.value * Constants.MGDL_TO_MMOLL - - fun valueToUnitsToString(units: String): String = - if (units == Constants.MGDL) DecimalFormatter.to0Decimal(data.value) - else DecimalFormatter.to1Decimal(data.value * Constants.MGDL_TO_MMOLL) - - fun directionToSymbol(): String = - if (data.trendArrow == GlucoseValue.TrendArrow.NONE) calculateDirection().symbol - else data.trendArrow.symbol - - fun date(date: Long): BgReading { - data.timestamp = date - return this - } - - fun value(value: Double): BgReading { - data.value = value - return this - } - - // ------------------ DataPointWithLabelInterface ------------------ - override fun getX(): Double { - return data.timestamp.toDouble() - } - - override fun getY(): Double { - return valueToUnits(profileFunction.getUnits()) - } - - override fun setY(y: Double) {} - override fun getLabel(): String? = null - override fun getDuration(): Long = 0 - override fun getShape(): PointsWithLabelGraphSeries.Shape = - if (isPrediction) PointsWithLabelGraphSeries.Shape.PREDICTION - else PointsWithLabelGraphSeries.Shape.BG - - override fun getSize(): Float = 1f - - override fun getColor(): Int { - val units = profileFunction.getUnits() - val lowLine = defaultValueHelper.determineLowLine() - val highLine = defaultValueHelper.determineHighLine() - return when { - isPrediction -> predictionColor - valueToUnits(units) < lowLine -> resourceHelper.gc(R.color.low) - valueToUnits(units) > highLine -> resourceHelper.gc(R.color.high) - else -> resourceHelper.gc(R.color.inrange) - } - } - - val predictionColor: Int - get() { - return when { - isIOBPrediction -> resourceHelper.gc(R.color.iob) - isCOBPrediction -> resourceHelper.gc(R.color.cob) - isaCOBPrediction -> -0x7f000001 and resourceHelper.gc(R.color.cob) - isUAMPrediction -> resourceHelper.gc(R.color.uam) - isZTPrediction -> resourceHelper.gc(R.color.zt) - else -> R.color.white - } - } - - private val isPrediction: Boolean - get() = isaCOBPrediction || isCOBPrediction || isIOBPrediction || isUAMPrediction || isZTPrediction - - // Copied from xDrip+ - fun calculateDirection(): GlucoseValue.TrendArrow { - // Rework to get bgreaings from internal DB and calculate on that base - val bgReadingsList = repository.compatGetBgReadingsDataFromTime(data.timestamp - T.mins(10).msecs(), false) - .blockingGet() - if (bgReadingsList == null || bgReadingsList.size < 2) return GlucoseValue.TrendArrow.NONE - var current = bgReadingsList[1] - var previous = bgReadingsList[0] - if (bgReadingsList[1].timestamp < bgReadingsList[0].timestamp) { - current = bgReadingsList[0] - previous = bgReadingsList[1] - } - val slope: Double - - // Avoid division by 0 - slope = if (current.timestamp == previous.timestamp) 0.0 else (previous.value - current.value) / (previous.timestamp - current.timestamp) - aapsLogger.error(LTag.GLUCOSE, "Slope is :" + slope + " delta " + (previous.value - current.value) + " date difference " + (current.timestamp - previous.timestamp)) - val slope_by_minute = slope * 60000 - var arrow = GlucoseValue.TrendArrow.NONE - if (slope_by_minute <= -3.5) { - arrow = GlucoseValue.TrendArrow.DOUBLE_DOWN - } else if (slope_by_minute <= -2) { - arrow = GlucoseValue.TrendArrow.SINGLE_DOWN - } else if (slope_by_minute <= -1) { - arrow = GlucoseValue.TrendArrow.FORTY_FIVE_DOWN - } else if (slope_by_minute <= 1) { - arrow = GlucoseValue.TrendArrow.FLAT - } else if (slope_by_minute <= 2) { - arrow = GlucoseValue.TrendArrow.FORTY_FIVE_UP - } else if (slope_by_minute <= 3.5) { - arrow = GlucoseValue.TrendArrow.SINGLE_UP - } else if (slope_by_minute <= 40) { - arrow = GlucoseValue.TrendArrow.DOUBLE_UP - } - aapsLogger.error(LTag.GLUCOSE, "Direction set to: $arrow") - return arrow - } - - private fun isSlopeNameInvalid(direction: String?): Boolean { - return direction!!.compareTo("NOT_COMPUTABLE") == 0 || direction.compareTo("NOT COMPUTABLE") == 0 || direction.compareTo("OUT_OF_RANGE") == 0 || direction.compareTo("OUT OF RANGE") == 0 || direction.compareTo("NONE") == 0 || direction.compareTo("NotComputable") == 0 - } -} \ No newline at end of file diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/aps/loop/APSResult.java b/core/src/main/java/info/nightscout/androidaps/plugins/aps/loop/APSResult.java deleted file mode 100644 index 6d3f7edf87..0000000000 --- a/core/src/main/java/info/nightscout/androidaps/plugins/aps/loop/APSResult.java +++ /dev/null @@ -1,438 +0,0 @@ -package info.nightscout.androidaps.plugins.aps.loop; - -import android.text.Spanned; - -import androidx.annotation.NonNull; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - -import java.util.ArrayList; -import java.util.List; - -import javax.inject.Inject; - -import dagger.android.HasAndroidInjector; -import info.nightscout.androidaps.core.R; -import info.nightscout.androidaps.data.IobTotal; -import info.nightscout.androidaps.data.Profile; -import info.nightscout.androidaps.db.BgReading; -import info.nightscout.androidaps.db.TemporaryBasal; -import info.nightscout.androidaps.interfaces.ActivePluginProvider; -import info.nightscout.androidaps.interfaces.Constraint; -import info.nightscout.androidaps.interfaces.ProfileFunction; -import info.nightscout.androidaps.interfaces.PumpDescription; -import info.nightscout.androidaps.interfaces.PumpInterface; -import info.nightscout.androidaps.interfaces.TreatmentsInterface; -import info.nightscout.androidaps.logging.AAPSLogger; -import info.nightscout.androidaps.logging.LTag; -import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker; -import info.nightscout.androidaps.utils.DecimalFormatter; -import info.nightscout.androidaps.utils.HtmlHelper; -import info.nightscout.androidaps.utils.resources.ResourceHelper; -import info.nightscout.androidaps.utils.sharedPreferences.SP; - -/** - * Created by mike on 09.06.2016. - */ -public class APSResult { - @Inject HasAndroidInjector injector; - @Inject public AAPSLogger aapsLogger; - @Inject ConstraintChecker constraintChecker; - @Inject SP sp; - @Inject ActivePluginProvider activePlugin; - @Inject TreatmentsInterface treatmentsPlugin; - @Inject ProfileFunction profileFunction; - @Inject ResourceHelper resourceHelper; - - @Inject - public APSResult(HasAndroidInjector injector) { - injector.androidInjector().inject(this); - } - - public long date = 0; - public String reason; - public double rate; - public int percent; - public boolean usePercent = false; - public int duration; - public boolean tempBasalRequested = false; - public boolean bolusRequested = false; - public IobTotal iob; - public JSONObject json = new JSONObject(); - public boolean hasPredictions = false; - public double smb = 0d; // super micro bolus in units - public long deliverAt = 0; - public double targetBG = 0d; - - public int carbsReq = 0; - public int carbsReqWithin = 0; - - public Constraint inputConstraints; - - public Constraint rateConstraint; - public Constraint percentConstraint; - public Constraint smbConstraint; - - public APSResult rate(double rate) { - this.rate = rate; - return this; - } - - public APSResult duration(int duration) { - this.duration = duration; - return this; - } - - public APSResult percent(int percent) { - this.percent = percent; - return this; - } - - public APSResult tempBasalRequested(boolean tempBasalRequested) { - this.tempBasalRequested = tempBasalRequested; - return this; - } - - public APSResult usePercent(boolean usePercent) { - this.usePercent = usePercent; - return this; - } - - public APSResult json(JSONObject json) { - this.json = json; - return this; - } - - public String getCarbsRequiredText() { - return String.format(resourceHelper.gs(R.string.carbsreq), carbsReq, carbsReqWithin); - } - - @NonNull @Override - public String toString() { - final PumpInterface pump = activePlugin.getActivePump(); - if (isChangeRequested()) { - String ret; - // rate - if (rate == 0 && duration == 0) - ret = resourceHelper.gs(R.string.canceltemp) + "\n"; - else if (rate == -1) - ret = resourceHelper.gs(R.string.let_temp_basal_run) + "\n"; - else if (usePercent) - ret = resourceHelper.gs(R.string.rate) + ": " + DecimalFormatter.to2Decimal(percent) + "% " + - "(" + DecimalFormatter.to2Decimal(percent * pump.getBaseBasalRate() / 100d) + " U/h)\n" + - resourceHelper.gs(R.string.duration) + ": " + DecimalFormatter.to2Decimal(duration) + " min\n"; - else - ret = resourceHelper.gs(R.string.rate) + ": " + DecimalFormatter.to2Decimal(rate) + " U/h " + - "(" + DecimalFormatter.to2Decimal(rate / pump.getBaseBasalRate() * 100) + "%) \n" + - resourceHelper.gs(R.string.duration) + ": " + DecimalFormatter.to2Decimal(duration) + " min\n"; - - // smb - if (smb != 0) - ret += ("SMB: " + DecimalFormatter.toPumpSupportedBolus(smb, activePlugin.getActivePump(), resourceHelper) + "\n"); - - if (isCarbsRequired()) { - ret += getCarbsRequiredText() + "\n"; - } - - // reason - ret += resourceHelper.gs(R.string.reason) + ": " + reason; - return ret; - } - - if (isCarbsRequired()) { - return getCarbsRequiredText(); - } - - return resourceHelper.gs(R.string.nochangerequested); - } - - public Spanned toSpanned() { - final PumpInterface pump = activePlugin.getActivePump(); - if (isChangeRequested()) { - String ret; - // rate - if (rate == 0 && duration == 0) - ret = resourceHelper.gs(R.string.canceltemp) + "
"; - else if (rate == -1) - ret = resourceHelper.gs(R.string.let_temp_basal_run) + "
"; - else if (usePercent) - ret = "" + resourceHelper.gs(R.string.rate) + ": " + DecimalFormatter.to2Decimal(percent) + "% " + - "(" + DecimalFormatter.to2Decimal(percent * pump.getBaseBasalRate() / 100d) + " U/h)
" + - "" + resourceHelper.gs(R.string.duration) + ": " + DecimalFormatter.to2Decimal(duration) + " min
"; - else - ret = "" + resourceHelper.gs(R.string.rate) + ": " + DecimalFormatter.to2Decimal(rate) + " U/h " + - "(" + DecimalFormatter.to2Decimal(rate / pump.getBaseBasalRate() * 100d) + "%)
" + - "" + resourceHelper.gs(R.string.duration) + ": " + DecimalFormatter.to2Decimal(duration) + " min
"; - - // smb - if (smb != 0) - ret += ("" + "SMB" + ": " + DecimalFormatter.toPumpSupportedBolus(smb, activePlugin.getActivePump(), resourceHelper) + "
"); - - if (isCarbsRequired()) { - ret += getCarbsRequiredText() + "
"; - } - - // reason - ret += "" + resourceHelper.gs(R.string.reason) + ": " + reason.replace("<", "<").replace(">", ">"); - return HtmlHelper.INSTANCE.fromHtml(ret); - } - - if (isCarbsRequired()) { - return HtmlHelper.INSTANCE.fromHtml(getCarbsRequiredText()); - } - - return HtmlHelper.INSTANCE.fromHtml(resourceHelper.gs(R.string.nochangerequested)); - } - - public APSResult newAndClone(HasAndroidInjector injector) { - APSResult newResult = new APSResult(injector); - doClone(newResult); - return newResult; - } - - protected void doClone(APSResult newResult) { - newResult.date = date; - newResult.reason = reason != null ? reason : null; - newResult.rate = rate; - newResult.duration = duration; - newResult.tempBasalRequested = tempBasalRequested; - newResult.bolusRequested = bolusRequested; - newResult.iob = iob; - try { - newResult.json = new JSONObject(json.toString()); - } catch (JSONException e) { - aapsLogger.error("Unhandled exception", e); - } - newResult.hasPredictions = hasPredictions; - newResult.smb = smb; - newResult.deliverAt = deliverAt; - newResult.rateConstraint = rateConstraint; - newResult.smbConstraint = smbConstraint; - newResult.percent = percent; - newResult.usePercent = usePercent; - newResult.carbsReq = carbsReq; - newResult.carbsReqWithin = carbsReqWithin; - newResult.targetBG = targetBG; - } - - - public JSONObject json() { - JSONObject json = new JSONObject(); - try { - if (isChangeRequested()) { - json.put("rate", rate); - json.put("duration", duration); - json.put("reason", reason); - } - } catch (JSONException e) { - aapsLogger.error("Unhandled exception", e); - } - return json; - } - - public List getPredictions() { - List array = new ArrayList<>(); - try { - long startTime = date; - if (json != null && json.has("predBGs")) { - JSONObject predBGs = json.getJSONObject("predBGs"); - if (predBGs.has("IOB")) { - JSONArray iob = predBGs.getJSONArray("IOB"); - for (int i = 1; i < iob.length(); i++) { - BgReading bg = new BgReading(injector); - bg.setValue(iob.getInt(i)); - bg.setDate(startTime + i * 5 * 60 * 1000L); - bg.setIOBPrediction(true); - array.add(bg); - } - } - if (predBGs.has("aCOB")) { - JSONArray iob = predBGs.getJSONArray("aCOB"); - for (int i = 1; i < iob.length(); i++) { - BgReading bg = new BgReading(injector); - bg.setValue(iob.getInt(i)); - bg.setDate(startTime + i * 5 * 60 * 1000L); - bg.setIsaCOBPrediction(true); - array.add(bg); - } - } - if (predBGs.has("COB")) { - JSONArray iob = predBGs.getJSONArray("COB"); - for (int i = 1; i < iob.length(); i++) { - BgReading bg = new BgReading(injector); - bg.setValue(iob.getInt(i)); - bg.setDate(startTime + i * 5 * 60 * 1000L); - bg.setCOBPrediction(true); - array.add(bg); - } - } - if (predBGs.has("UAM")) { - JSONArray iob = predBGs.getJSONArray("UAM"); - for (int i = 1; i < iob.length(); i++) { - BgReading bg = new BgReading(injector); - bg.setValue(iob.getInt(i)); - bg.setDate(startTime + i * 5 * 60 * 1000L); - bg.setUAMPrediction(true); - array.add(bg); - } - } - if (predBGs.has("ZT")) { - JSONArray iob = predBGs.getJSONArray("ZT"); - for (int i = 1; i < iob.length(); i++) { - BgReading bg = new BgReading(injector); - bg.setValue(iob.getInt(i)); - bg.setDate(startTime + i * 5 * 60 * 1000L); - bg.setZTPrediction(true); - array.add(bg); - } - } - } - } catch (JSONException e) { - aapsLogger.error("Unhandled exception", e); - } - return array; - } - - public long getLatestPredictionsTime() { - long latest = 0; - try { - long startTime = date; - if (json != null && json.has("predBGs")) { - JSONObject predBGs = json.getJSONObject("predBGs"); - if (predBGs.has("IOB")) { - JSONArray iob = predBGs.getJSONArray("IOB"); - latest = Math.max(latest, startTime + (iob.length() - 1) * 5 * 60 * 1000L); - } - if (predBGs.has("aCOB")) { - JSONArray iob = predBGs.getJSONArray("aCOB"); - latest = Math.max(latest, startTime + (iob.length() - 1) * 5 * 60 * 1000L); - } - if (predBGs.has("COB")) { - JSONArray iob = predBGs.getJSONArray("COB"); - latest = Math.max(latest, startTime + (iob.length() - 1) * 5 * 60 * 1000L); - } - if (predBGs.has("UAM")) { - JSONArray iob = predBGs.getJSONArray("UAM"); - latest = Math.max(latest, startTime + (iob.length() - 1) * 5 * 60 * 1000L); - } - if (predBGs.has("ZT")) { - JSONArray iob = predBGs.getJSONArray("ZT"); - latest = Math.max(latest, startTime + (iob.length() - 1) * 5 * 60 * 1000L); - } - } - } catch (JSONException e) { - aapsLogger.error("Unhandled exception", e); - } - - return latest; - } - - public boolean isCarbsRequired() { - return carbsReq > 0; - } - - public boolean isChangeRequested() { - Constraint closedLoopEnabled = constraintChecker.isClosedLoopAllowed(); - // closed loop mode: handle change at driver level - if (closedLoopEnabled.value()) { - aapsLogger.debug(LTag.APS, "DEFAULT: Closed mode"); - return tempBasalRequested || bolusRequested; - } - - // open loop mode: try to limit request - if (!tempBasalRequested && !bolusRequested) { - aapsLogger.debug(LTag.APS, "FALSE: No request"); - return false; - } - - long now = System.currentTimeMillis(); - TemporaryBasal activeTemp = treatmentsPlugin.getTempBasalFromHistory(now); - PumpInterface pump = activePlugin.getActivePump(); - Profile profile = profileFunction.getProfile(); - - if (profile == null) { - aapsLogger.error("FALSE: No Profile"); - return false; - } - - if (usePercent) { - if (activeTemp == null && percent == 100) { - aapsLogger.debug(LTag.APS, "FALSE: No temp running, asking cancel temp"); - return false; - } - if (activeTemp != null && Math.abs(percent - activeTemp.tempBasalConvertedToPercent(now, profile)) < pump.getPumpDescription().basalStep) { - aapsLogger.debug(LTag.APS, "FALSE: Temp equal"); - return false; - } - // always report zerotemp - if (percent == 0) { - aapsLogger.debug(LTag.APS, "TRUE: Zero temp"); - return true; - } - // always report hightemp - if (pump.getPumpDescription().tempBasalStyle == PumpDescription.PERCENT) { - double pumpLimit = pump.getPumpDescription().pumpType.getTbrSettings().getMaxDose(); - if (percent == pumpLimit) { - aapsLogger.debug(LTag.APS, "TRUE: Pump limit"); - return true; - } - } - // report change bigger than 30% - double percentMinChangeChange = sp.getDouble(R.string.key_loop_openmode_min_change, 30d); - percentMinChangeChange /= 100d; - double lowThreshold = 1 - percentMinChangeChange; - double highThreshold = 1 + percentMinChangeChange; - double change = percent / 100d; - if (activeTemp != null) - change = percent / (double) activeTemp.tempBasalConvertedToPercent(now, profile); - - if (change < lowThreshold || change > highThreshold) { - aapsLogger.debug(LTag.APS, "TRUE: Outside allowed range " + (change * 100d) + "%"); - return true; - } else { - aapsLogger.debug(LTag.APS, "TRUE: Inside allowed range " + (change * 100d) + "%"); - return false; - } - } else { - if (activeTemp == null && rate == pump.getBaseBasalRate()) { - aapsLogger.debug(LTag.APS, "FALSE: No temp running, asking cancel temp"); - return false; - } - if (activeTemp != null && Math.abs(rate - activeTemp.tempBasalConvertedToAbsolute(now, profile)) < pump.getPumpDescription().basalStep) { - aapsLogger.debug(LTag.APS, "FALSE: Temp equal"); - return false; - } - // always report zerotemp - if (rate == 0) { - aapsLogger.debug(LTag.APS, "TRUE: Zero temp"); - return true; - } - // always report hightemp - if (pump.getPumpDescription().tempBasalStyle == PumpDescription.ABSOLUTE) { - double pumpLimit = pump.getPumpDescription().pumpType.getTbrSettings().getMaxDose(); - if (rate == pumpLimit) { - aapsLogger.debug(LTag.APS, "TRUE: Pump limit"); - return true; - } - } - // report change bigger than 30% - double percentMinChangeChange = sp.getDouble(R.string.key_loop_openmode_min_change, 30d); - percentMinChangeChange /= 100d; - double lowThreshold = 1 - percentMinChangeChange; - double highThreshold = 1 + percentMinChangeChange; - double change = rate / profile.getBasal(); - if (activeTemp != null) - change = rate / activeTemp.tempBasalConvertedToAbsolute(now, profile); - - if (change < lowThreshold || change > highThreshold) { - aapsLogger.debug(LTag.APS, "TRUE: Outside allowed range " + (change * 100d) + "%"); - return true; - } else { - aapsLogger.debug(LTag.APS, "TRUE: Inside allowed range " + (change * 100d) + "%"); - return false; - } - } - } -} diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/aps/loop/APSResult.kt b/core/src/main/java/info/nightscout/androidaps/plugins/aps/loop/APSResult.kt new file mode 100644 index 0000000000..b7f1048464 --- /dev/null +++ b/core/src/main/java/info/nightscout/androidaps/plugins/aps/loop/APSResult.kt @@ -0,0 +1,399 @@ +package info.nightscout.androidaps.plugins.aps.loop + +import android.text.Spanned +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.core.R +import info.nightscout.androidaps.data.GlucoseValueDataPoint +import info.nightscout.androidaps.data.IobTotal +import info.nightscout.androidaps.database.entities.GlucoseValue +import info.nightscout.androidaps.interfaces.ActivePluginProvider +import info.nightscout.androidaps.interfaces.Constraint +import info.nightscout.androidaps.interfaces.ProfileFunction +import info.nightscout.androidaps.interfaces.PumpDescription +import info.nightscout.androidaps.interfaces.TreatmentsInterface +import info.nightscout.androidaps.logging.AAPSLogger +import info.nightscout.androidaps.logging.LTag +import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker +import info.nightscout.androidaps.utils.DecimalFormatter +import info.nightscout.androidaps.utils.HtmlHelper.fromHtml +import info.nightscout.androidaps.utils.resources.ResourceHelper +import info.nightscout.androidaps.utils.sharedPreferences.SP +import org.json.JSONException +import org.json.JSONObject +import java.util.* +import javax.inject.Inject +import kotlin.math.abs +import kotlin.math.max + +/** + * Created by mike on 09.06.2016. + */ +open class APSResult @Inject constructor(val injector: HasAndroidInjector) { + + @Inject lateinit var aapsLogger: AAPSLogger + @Inject lateinit var constraintChecker: ConstraintChecker + @Inject lateinit var sp: SP + @Inject lateinit var activePlugin: ActivePluginProvider + @Inject lateinit var treatmentsPlugin: TreatmentsInterface + @Inject lateinit var profileFunction: ProfileFunction + @Inject lateinit var resourceHelper: ResourceHelper + + var date: Long = 0 + var reason: String? = null + var rate = 0.0 + var percent = 0 + var usePercent = false + var duration = 0 + var tempBasalRequested = false + var bolusRequested = false + var iob: IobTotal? = null + var json: JSONObject? = JSONObject() + var hasPredictions = false + var smb = 0.0 // super micro bolus in units + var deliverAt: Long = 0 + var targetBG = 0.0 + var carbsReq = 0 + var carbsReqWithin = 0 + var inputConstraints: Constraint? = null + var rateConstraint: Constraint? = null + var percentConstraint: Constraint? = null + var smbConstraint: Constraint? = null + + init { + injector.androidInjector().inject(this) + } + + fun rate(rate: Double): APSResult { + this.rate = rate + return this + } + + fun duration(duration: Int): APSResult { + this.duration = duration + return this + } + + fun percent(percent: Int): APSResult { + this.percent = percent + return this + } + + fun tempBasalRequested(tempBasalRequested: Boolean): APSResult { + this.tempBasalRequested = tempBasalRequested + return this + } + + fun usePercent(usePercent: Boolean): APSResult { + this.usePercent = usePercent + return this + } + + fun json(json: JSONObject?): APSResult { + this.json = json + return this + } + + val carbsRequiredText: String + get() = String.format(resourceHelper.gs(R.string.carbsreq), carbsReq, carbsReqWithin) + + override fun toString(): String { + val pump = activePlugin.activePump + if (isChangeRequested) { + // rate + var ret: String = if (rate == 0.0 && duration == 0) "${resourceHelper.gs(R.string.canceltemp)}\n" + else if (rate == -1.0) "${resourceHelper.gs(R.string.let_temp_basal_run)}\n" + else if (usePercent) "${resourceHelper.gs(R.string.rate)}: ${DecimalFormatter.to2Decimal(percent.toDouble())}% (${DecimalFormatter.to2Decimal(percent * pump.baseBasalRate / 100.0)} U/h)\n" + + "${resourceHelper.gs(R.string.duration)}: ${DecimalFormatter.to2Decimal(duration.toDouble())} min\n" + else "${resourceHelper.gs(R.string.rate)}: ${DecimalFormatter.to2Decimal(rate)} U/h (${DecimalFormatter.to2Decimal(rate / pump.baseBasalRate * 100)}%)" + + "${resourceHelper.gs(R.string.duration)}: ${DecimalFormatter.to2Decimal(duration.toDouble())} min\n" + // smb + if (smb != 0.0) ret += "SMB: ${DecimalFormatter.toPumpSupportedBolus(smb, activePlugin.activePump, resourceHelper)}\n" + if (isCarbsRequired) { + ret += "$carbsRequiredText\n" + } + + // reason + ret += resourceHelper.gs(R.string.reason) + ": " + reason + return ret + } + return if (isCarbsRequired) { + carbsRequiredText + } else resourceHelper.gs(R.string.nochangerequested) + } + + fun toSpanned(): Spanned { + val pump = activePlugin.activePump + if (isChangeRequested) { + // rate + var ret: String = if (rate == 0.0 && duration == 0) resourceHelper.gs(R.string.canceltemp) + "
" else if (rate == -1.0) resourceHelper.gs(R.string.let_temp_basal_run) + "
" else if (usePercent) "" + resourceHelper.gs(R.string.rate) + ": " + DecimalFormatter.to2Decimal(percent.toDouble()) + "% " + + "(" + DecimalFormatter.to2Decimal(percent * pump.baseBasalRate / 100.0) + " U/h)
" + + "" + resourceHelper.gs(R.string.duration) + ": " + DecimalFormatter.to2Decimal(duration.toDouble()) + " min
" else "" + resourceHelper.gs(R.string.rate) + ": " + DecimalFormatter.to2Decimal(rate) + " U/h " + + "(" + DecimalFormatter.to2Decimal(rate / pump.baseBasalRate * 100.0) + "%)
" + + "" + resourceHelper.gs(R.string.duration) + ": " + DecimalFormatter.to2Decimal(duration.toDouble()) + " min
" + + // smb + if (smb != 0.0) ret += "" + "SMB" + ": " + DecimalFormatter.toPumpSupportedBolus(smb, activePlugin.activePump, resourceHelper) + "
" + if (isCarbsRequired) { + ret += "$carbsRequiredText
" + } + + // reason + ret += "" + resourceHelper.gs(R.string.reason) + ": " + reason!!.replace("<", "<").replace(">", ">") + return fromHtml(ret) + } + return if (isCarbsRequired) { + fromHtml(carbsRequiredText) + } else fromHtml(resourceHelper.gs(R.string.nochangerequested)) + } + + open fun newAndClone(injector: HasAndroidInjector): APSResult { + val newResult = APSResult(injector) + doClone(newResult) + return newResult + } + + protected fun doClone(newResult: APSResult) { + newResult.date = date + newResult.reason = if (reason != null) reason else null + newResult.rate = rate + newResult.duration = duration + newResult.tempBasalRequested = tempBasalRequested + newResult.bolusRequested = bolusRequested + newResult.iob = iob + newResult.json = JSONObject(json.toString()) + newResult.hasPredictions = hasPredictions + newResult.smb = smb + newResult.deliverAt = deliverAt + newResult.rateConstraint = rateConstraint + newResult.smbConstraint = smbConstraint + newResult.percent = percent + newResult.usePercent = usePercent + newResult.carbsReq = carbsReq + newResult.carbsReqWithin = carbsReqWithin + newResult.targetBG = targetBG + } + + open fun json(): JSONObject? { + val json = JSONObject() + if (isChangeRequested) { + json.put("rate", rate) + json.put("duration", duration) + json.put("reason", reason) + } + return json + } + + val predictions: MutableList + get() { + val array: MutableList = ArrayList() + val startTime = date + json?.let { json -> + if (json.has("predBGs")) { + val predBGs = json.getJSONObject("predBGs") + if (predBGs.has("IOB")) { + val iob = predBGs.getJSONArray("IOB") + for (i in 1 until iob.length()) { + val gv = GlucoseValue( + raw = 0.0, + noise = 0.0, + value = iob.getInt(i).toDouble(), + timestamp = startTime + i * 5 * 60 * 1000L, + sourceSensor = GlucoseValue.SourceSensor.IOB_PREDICTION, + trendArrow = GlucoseValue.TrendArrow.NONE + ) + array.add(GlucoseValueDataPoint(injector, gv)) + } + } + if (predBGs.has("aCOB")) { + val iob = predBGs.getJSONArray("aCOB") + for (i in 1 until iob.length()) { + val gv = GlucoseValue( + raw = 0.0, + noise = 0.0, + value = iob.getInt(i).toDouble(), + timestamp = startTime + i * 5 * 60 * 1000L, + sourceSensor = GlucoseValue.SourceSensor.aCOB_PREDICTION, + trendArrow = GlucoseValue.TrendArrow.NONE + ) + array.add(GlucoseValueDataPoint(injector, gv)) + } + } + if (predBGs.has("COB")) { + val iob = predBGs.getJSONArray("COB") + for (i in 1 until iob.length()) { + val gv = GlucoseValue( + raw = 0.0, + noise = 0.0, + value = iob.getInt(i).toDouble(), + timestamp = startTime + i * 5 * 60 * 1000L, + sourceSensor = GlucoseValue.SourceSensor.COB_PREDICTION, + trendArrow = GlucoseValue.TrendArrow.NONE + ) + array.add(GlucoseValueDataPoint(injector, gv)) + } + } + if (predBGs.has("UAM")) { + val iob = predBGs.getJSONArray("UAM") + for (i in 1 until iob.length()) { + val gv = GlucoseValue( + raw = 0.0, + noise = 0.0, + value = iob.getInt(i).toDouble(), + timestamp = startTime + i * 5 * 60 * 1000L, + sourceSensor = GlucoseValue.SourceSensor.UAM_PREDICTION, + trendArrow = GlucoseValue.TrendArrow.NONE + ) + array.add(GlucoseValueDataPoint(injector, gv)) + } + } + if (predBGs.has("ZT")) { + val iob = predBGs.getJSONArray("ZT") + for (i in 1 until iob.length()) { + val gv = GlucoseValue( + raw = 0.0, + noise = 0.0, + value = iob.getInt(i).toDouble(), + timestamp = startTime + i * 5 * 60 * 1000L, + sourceSensor = GlucoseValue.SourceSensor.ZT_PREDICTION, + trendArrow = GlucoseValue.TrendArrow.NONE + ) + array.add(GlucoseValueDataPoint(injector, gv)) + } + } + } + } + return array + } + val latestPredictionsTime: Long + get() { + var latest: Long = 0 + try { + val startTime = date + if (json != null && json!!.has("predBGs")) { + val predBGs = json!!.getJSONObject("predBGs") + if (predBGs.has("IOB")) { + val iob = predBGs.getJSONArray("IOB") + latest = max(latest, startTime + (iob.length() - 1) * 5 * 60 * 1000L) + } + if (predBGs.has("aCOB")) { + val iob = predBGs.getJSONArray("aCOB") + latest = max(latest, startTime + (iob.length() - 1) * 5 * 60 * 1000L) + } + if (predBGs.has("COB")) { + val iob = predBGs.getJSONArray("COB") + latest = max(latest, startTime + (iob.length() - 1) * 5 * 60 * 1000L) + } + if (predBGs.has("UAM")) { + val iob = predBGs.getJSONArray("UAM") + latest = max(latest, startTime + (iob.length() - 1) * 5 * 60 * 1000L) + } + if (predBGs.has("ZT")) { + val iob = predBGs.getJSONArray("ZT") + latest = max(latest, startTime + (iob.length() - 1) * 5 * 60 * 1000L) + } + } + } catch (e: JSONException) { + aapsLogger.error("Unhandled exception", e) + } + return latest + } + val isCarbsRequired: Boolean + get() = carbsReq > 0 + + val isChangeRequested: Boolean + get() { + val closedLoopEnabled = constraintChecker.isClosedLoopAllowed() + // closed loop mode: handle change at driver level + if (closedLoopEnabled.value()) { + aapsLogger.debug(LTag.APS, "DEFAULT: Closed mode") + return tempBasalRequested || bolusRequested + } + + // open loop mode: try to limit request + if (!tempBasalRequested && !bolusRequested) { + aapsLogger.debug(LTag.APS, "FALSE: No request") + return false + } + val now = System.currentTimeMillis() + val activeTemp = treatmentsPlugin.getTempBasalFromHistory(now) + val pump = activePlugin.activePump + val profile = profileFunction.getProfile() + if (profile == null) { + aapsLogger.error("FALSE: No Profile") + return false + } + return if (usePercent) { + if (activeTemp == null && percent == 100) { + aapsLogger.debug(LTag.APS, "FALSE: No temp running, asking cancel temp") + return false + } + if (activeTemp != null && abs(percent - activeTemp.tempBasalConvertedToPercent(now, profile)) < pump.pumpDescription.basalStep) { + aapsLogger.debug(LTag.APS, "FALSE: Temp equal") + return false + } + // always report zerotemp + if (percent == 0) { + aapsLogger.debug(LTag.APS, "TRUE: Zero temp") + return true + } + // always report hightemp + if (pump.pumpDescription.tempBasalStyle == PumpDescription.PERCENT) { + val pumpLimit = pump.pumpDescription.pumpType.tbrSettings.maxDose + if (percent.toDouble() == pumpLimit) { + aapsLogger.debug(LTag.APS, "TRUE: Pump limit") + return true + } + } + // report change bigger than 30% + var percentMinChangeChange = sp.getDouble(R.string.key_loop_openmode_min_change, 30.0) + percentMinChangeChange /= 100.0 + val lowThreshold = 1 - percentMinChangeChange + val highThreshold = 1 + percentMinChangeChange + var change = percent / 100.0 + if (activeTemp != null) change = percent / activeTemp.tempBasalConvertedToPercent(now, profile).toDouble() + if (change < lowThreshold || change > highThreshold) { + aapsLogger.debug(LTag.APS, "TRUE: Outside allowed range " + change * 100.0 + "%") + true + } else { + aapsLogger.debug(LTag.APS, "TRUE: Inside allowed range " + change * 100.0 + "%") + false + } + } else { + if (activeTemp == null && rate == pump.baseBasalRate) { + aapsLogger.debug(LTag.APS, "FALSE: No temp running, asking cancel temp") + return false + } + if (activeTemp != null && abs(rate - activeTemp.tempBasalConvertedToAbsolute(now, profile)) < pump.pumpDescription.basalStep) { + aapsLogger.debug(LTag.APS, "FALSE: Temp equal") + return false + } + // always report zerotemp + if (rate == 0.0) { + aapsLogger.debug(LTag.APS, "TRUE: Zero temp") + return true + } + // always report hightemp + if (pump.pumpDescription.tempBasalStyle == PumpDescription.ABSOLUTE) { + val pumpLimit = pump.pumpDescription.pumpType.tbrSettings.maxDose + if (rate == pumpLimit) { + aapsLogger.debug(LTag.APS, "TRUE: Pump limit") + return true + } + } + // report change bigger than 30% + var percentMinChangeChange = sp.getDouble(R.string.key_loop_openmode_min_change, 30.0) + percentMinChangeChange /= 100.0 + val lowThreshold = 1 - percentMinChangeChange + val highThreshold = 1 + percentMinChangeChange + var change = rate / profile.basal + if (activeTemp != null) change = rate / activeTemp.tempBasalConvertedToAbsolute(now, profile) + if (change < lowThreshold || change > highThreshold) { + aapsLogger.debug(LTag.APS, "TRUE: Outside allowed range " + change * 100.0 + "%") + true + } else { + aapsLogger.debug(LTag.APS, "TRUE: Inside allowed range " + change * 100.0 + "%") + false + } + } + } +} \ No newline at end of file diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSUpload.java b/core/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSUpload.java index 778ab361d3..571befb159 100644 --- a/core/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSUpload.java +++ b/core/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSUpload.java @@ -1,22 +1,15 @@ package info.nightscout.androidaps.plugins.general.nsclient; import android.content.Context; -import android.content.Intent; -import android.content.pm.ResolveInfo; import android.os.Build; -import android.os.Bundle; import androidx.annotation.Nullable; import org.apache.commons.lang3.StringUtils; -import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; -import java.text.SimpleDateFormat; import java.util.Date; -import java.util.List; -import java.util.Locale; import javax.inject.Inject; import javax.inject.Singleton; @@ -26,7 +19,7 @@ import info.nightscout.androidaps.core.R; import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.Profile; -import info.nightscout.androidaps.db.BgReading; +import info.nightscout.androidaps.database.entities.GlucoseValue; import info.nightscout.androidaps.db.CareportalEvent; import info.nightscout.androidaps.db.DbRequest; import info.nightscout.androidaps.db.ExtendedBolus; @@ -211,7 +204,7 @@ public class NSUpload { apsResult.json().put("timestamp", DateUtil.toISOString(lastRun.getLastAPSRun())); deviceStatus.suggested = apsResult.json(); - deviceStatus.iob = lastRun.getRequest().iob.json(); + deviceStatus.iob = lastRun.getRequest().getIob().json(); deviceStatus.iob.put("time", DateUtil.toISOString(lastRun.getLastAPSRun())); JSONObject requested = new JSONObject(); @@ -221,8 +214,8 @@ public class NSUpload { deviceStatus.enacted.put("rate", lastRun.getTbrSetByPump().json(profile).get("rate")); deviceStatus.enacted.put("duration", lastRun.getTbrSetByPump().json(profile).get("duration")); deviceStatus.enacted.put("recieved", true); - requested.put("duration", lastRun.getRequest().duration); - requested.put("rate", lastRun.getRequest().rate); + requested.put("duration", lastRun.getRequest().getDuration()); + requested.put("rate", lastRun.getRequest().getRate()); requested.put("temp", "absolute"); deviceStatus.enacted.put("requested", requested); } @@ -231,7 +224,7 @@ public class NSUpload { deviceStatus.enacted = lastRun.getRequest().json(); } deviceStatus.enacted.put("smb", lastRun.getTbrSetByPump().bolusDelivered); - requested.put("smb", lastRun.getRequest().smb); + requested.put("smb", lastRun.getRequest().getSmb()); deviceStatus.enacted.put("requested", requested); } } else { @@ -402,14 +395,14 @@ public class NSUpload { uploadQueue.add(new DbRequest("dbAdd", "treatments", data)); } - public void uploadBg(BgReading reading, String source) { + public void uploadBg(GlucoseValue reading, String source) { JSONObject data = new JSONObject(); try { data.put("device", source); - data.put("date", reading.getDate()); - data.put("dateString", DateUtil.toISOString(reading.getDate())); + data.put("date", reading.getTimestamp()); + data.put("dateString", DateUtil.toISOString(reading.getTimestamp())); data.put("sgv", reading.getValue()); - data.put("direction", reading.getData().getTrendArrow().getText()); + data.put("direction", reading.getTrendArrow().getText()); data.put("type", "sgv"); } catch (JSONException e) { aapsLogger.error("Unhandled exception", e); @@ -417,18 +410,18 @@ public class NSUpload { uploadQueue.add(new DbRequest("dbAdd", "entries", data)); } - public void updateBg(BgReading reading, String source) { + public void updateBg(GlucoseValue reading, String source) { JSONObject data = new JSONObject(); try { data.put("device", source); - data.put("date", reading.getDate()); - data.put("dateString", DateUtil.toISOString(reading.getDate())); + data.put("date", reading.getTimestamp()); + data.put("dateString", DateUtil.toISOString(reading.getTimestamp())); data.put("sgv", reading.getValue()); - data.put("direction", reading.getData().getTrendArrow().getText()); + data.put("direction", reading.getTrendArrow().getText()); data.put("type", "sgv"); - if (reading.getData().getInterfaceIDs_backing() != null) - if (reading.getData().getInterfaceIDs_backing().getNightscoutId() != null) { - uploadQueue.add(new DbRequest("dbUpdate", "entries", reading.getData().getInterfaceIDs_backing().getNightscoutId(), data)); + if (reading.getInterfaceIDs() != null) + if (reading.getInterfaceIDs().getNightscoutId() != null) { + uploadQueue.add(new DbRequest("dbUpdate", "entries", reading.getInterfaceIDs().getNightscoutId(), data)); } } catch (JSONException e) { aapsLogger.error("Unhandled exception", e); diff --git a/database/src/main/java/info/nightscout/androidaps/database/entities/GlucoseValue.kt b/database/src/main/java/info/nightscout/androidaps/database/entities/GlucoseValue.kt index 74ad9b5ceb..32e8036558 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/entities/GlucoseValue.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/entities/GlucoseValue.kt @@ -41,7 +41,7 @@ data class GlucoseValue( noise == other.noise && sourceSensor == other.sourceSensor && isValid == other.isValid && - interfaceIDs?.nightscoutId == other.interfaceIDs?.nightscoutId + interfaceIDs.nightscoutId == other.interfaceIDs.nightscoutId fun isRecordDeleted(other: GlucoseValue): Boolean = isValid && !other.isValid @@ -91,7 +91,13 @@ data class GlucoseValue( @SerializedName("MM600Series") MM_600_SERIES("MM600Series"), @SerializedName("Eversense") EVERSENSE("Eversense"), @SerializedName("Random") RANDOM("Random"), - @SerializedName("Unknown") UNKNOWN("Unknown") + @SerializedName("Unknown") UNKNOWN("Unknown"), + + @SerializedName("IOBPrediction") IOB_PREDICTION("IOBPrediction"), + @SerializedName("aCOBPrediction") aCOB_PREDICTION("aCOBPrediction"), + @SerializedName("COBPrediction") COB_PREDICTION("COBPrediction"), + @SerializedName("UAMPrediction") UAM_PREDICTION("UAMPrediction"), + @SerializedName("ZTPrediction") ZT_PREDICTION("ZTPrediction") ; companion object { From 145765e611229c269e9020a10112df93b0ea15d7 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Mon, 8 Feb 2021 13:40:09 +0100 Subject: [PATCH 4/8] improve BG sync --- .../plugins/source/BGSourceFragment.kt | 7 ++- .../androidaps/plugins/source/DexcomPlugin.kt | 17 ++++--- .../plugins/source/EversensePlugin.kt | 2 +- .../androidaps/plugins/source/GlimpPlugin.kt | 2 +- .../androidaps/plugins/source/MM640gPlugin.kt | 2 +- .../plugins/source/NSClientSourcePlugin.kt | 12 +++-- .../plugins/source/PoctechPlugin.kt | 2 +- .../plugins/source/RandomBgPlugin.kt | 2 +- .../androidaps/plugins/source/TomatoPlugin.kt | 2 +- .../androidaps/plugins/source/XdripPlugin.kt | 2 +- .../database/entities/GlucoseValue.kt | 3 +- .../transactions/CgmSourceTransaction.kt | 44 +++++++++++++++---- 12 files changed, 68 insertions(+), 29 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/BGSourceFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/BGSourceFragment.kt index 0c3193a45d..84999eb388 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/BGSourceFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/BGSourceFragment.kt @@ -18,12 +18,15 @@ import info.nightscout.androidaps.events.EventNewBG import info.nightscout.androidaps.interfaces.DatabaseHelperInterface import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.plugins.bus.RxBusWrapper -import info.nightscout.androidaps.utils.* +import info.nightscout.androidaps.utils.DateUtil +import info.nightscout.androidaps.utils.FabricPrivacy +import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.extensions.directionToIcon import info.nightscout.androidaps.utils.extensions.toVisibility import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.rx.AapsSchedulers +import info.nightscout.androidaps.utils.valueToUnitsString import io.reactivex.disposables.CompositeDisposable import io.reactivex.rxkotlin.plusAssign import java.util.concurrent.TimeUnit @@ -89,8 +92,8 @@ class BGSourceFragment : DaggerFragment() { @Synchronized override fun onDestroyView() { super.onDestroyView() - _binding = null binding.recyclerview.adapter = null // avoid leaks + _binding = null } inner class RecyclerViewAdapter internal constructor(private var glucoseValues: List) : RecyclerView.Adapter() { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/DexcomPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/DexcomPlugin.kt index 4065d78f92..6c7212ea86 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/DexcomPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/DexcomPlugin.kt @@ -132,14 +132,19 @@ class DexcomPlugin @Inject constructor( } else { null } - dexcomPlugin.disposable += repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, calibrations, sensorStartTime)).subscribe({ savedValues -> - savedValues.forEach { + dexcomPlugin.disposable += repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, calibrations, sensorStartTime)).subscribe({ result -> + result.inserted.forEach { broadcastToXDrip(it) if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false)) { - if (it.interfaceIDs.nightscoutId != null) - nsUpload.updateBg(it, sourceSensor.text) - else - nsUpload.uploadBg(it, sourceSensor.text) + nsUpload.uploadBg(it, sourceSensor.text) + //aapsLogger.debug("XXXXX: dbAdd $it") + } + } + result.updated.forEach { + broadcastToXDrip(it) + if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false)) { + nsUpload.updateBg(it, sourceSensor.text) + //aapsLogger.debug("XXXXX: dpUpdate $it") } } }, { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/EversensePlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/EversensePlugin.kt index e34550fc94..853e222cb9 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/EversensePlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/EversensePlugin.kt @@ -118,7 +118,7 @@ class EversensePlugin @Inject constructor( sourceSensor = GlucoseValue.SourceSensor.EVERSENSE ) eversensePlugin.disposable += repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null)).subscribe({ savedValues -> - savedValues.forEach { + savedValues.inserted.forEach { broadcastToXDrip(it) if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false)) nsUpload.uploadBg(it, GlucoseValue.SourceSensor.EVERSENSE.text) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/GlimpPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/GlimpPlugin.kt index be297ec32a..114b3af260 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/GlimpPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/GlimpPlugin.kt @@ -76,7 +76,7 @@ class GlimpPlugin @Inject constructor( sourceSensor = GlucoseValue.SourceSensor.GLIMP ) glimpPlugin.disposable += repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null)).subscribe({ savedValues -> - savedValues.forEach { + savedValues.inserted.forEach { broadcastToXDrip(it) if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false)) nsUpload.uploadBg(it, GlucoseValue.SourceSensor.GLIMP.text) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/MM640gPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/MM640gPlugin.kt index 91df585df7..88e14ee25a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/MM640gPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/MM640gPlugin.kt @@ -94,7 +94,7 @@ class MM640gPlugin @Inject constructor( } } mM640gPlugin.disposable += repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null)).subscribe({ savedValues -> - savedValues.forEach { + savedValues.all().forEach { broadcastToXDrip(it) if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false)) nsUpload.uploadBg(it, GlucoseValue.SourceSensor.MM_600_SERIES.text) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/NSClientSourcePlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/NSClientSourcePlugin.kt index e587fbe285..4a2658f55f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/NSClientSourcePlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/NSClientSourcePlugin.kt @@ -127,13 +127,19 @@ class NSClientSourcePlugin @Inject constructor( for (i in 0 until jsonArray.length()) glucoseValues += toGv(jsonArray.getJSONObject(i)) } - nsClientSourcePlugin.disposable += repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null)).subscribe({ savedValues -> - savedValues.forEach { + nsClientSourcePlugin.disposable += repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null, !nsClientSourcePlugin.isEnabled())).subscribe({ result -> + result.updated.forEach { + //aapsLogger.debug("XXXXX: Updated $it") + broadcastToXDrip(it) + nsClientSourcePlugin.detectSource(it) + } + result.inserted.forEach { + //aapsLogger.debug("XXXXX: Inserted $it") broadcastToXDrip(it) nsClientSourcePlugin.detectSource(it) } }, { - aapsLogger.error(LTag.BGSOURCE, "Error while saving values from Eversense App", it) + aapsLogger.error(LTag.BGSOURCE, "Error while saving values from NSClient App", it) }) } catch (e: Exception) { aapsLogger.error("Unhandled exception", e) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/PoctechPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/PoctechPlugin.kt index 5bbc9ff953..3ab79d7b70 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/PoctechPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/PoctechPlugin.kt @@ -87,7 +87,7 @@ class PoctechPlugin @Inject constructor( ) } poctechPlugin.disposable += repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null)).subscribe({ savedValues -> - savedValues.forEach { + savedValues.inserted.forEach { broadcastToXDrip(it) if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false)) nsUpload.uploadBg(it, GlucoseValue.SourceSensor.POCTECH_NATIVE.text) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/RandomBgPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/RandomBgPlugin.kt index 8ea04bde91..f0d78816a9 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/RandomBgPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/RandomBgPlugin.kt @@ -108,7 +108,7 @@ class RandomBgPlugin @Inject constructor( sourceSensor = GlucoseValue.SourceSensor.RANDOM ) disposable += repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null)).subscribe({ savedValues -> - savedValues.forEach { + savedValues.inserted.forEach { xDripBroadcast(it) if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false)) nsUpload.uploadBg(it, GlucoseValue.SourceSensor.RANDOM.text) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/TomatoPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/TomatoPlugin.kt index bbbfc3aaf9..15aec2b55e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/TomatoPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/TomatoPlugin.kt @@ -76,7 +76,7 @@ class TomatoPlugin @Inject constructor( sourceSensor = GlucoseValue.SourceSensor.LIBRE_1_TOMATO ) tomatoPlugin.disposable += repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null)).subscribe({ savedValues -> - savedValues.forEach { + savedValues.inserted.forEach { broadcastToXDrip(it) if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false)) nsUpload.uploadBg(it, GlucoseValue.SourceSensor.LIBRE_1_TOMATO.text) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/XdripPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/XdripPlugin.kt index 57fb9f98bb..73e6be3319 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/XdripPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/XdripPlugin.kt @@ -86,7 +86,7 @@ class XdripPlugin @Inject constructor( ?: "") ) xdripPlugin.disposable += repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null)).subscribe({ savedValues -> - savedValues.forEach { + savedValues.all().forEach { xdripPlugin.detectSource(it) } }, { diff --git a/database/src/main/java/info/nightscout/androidaps/database/entities/GlucoseValue.kt b/database/src/main/java/info/nightscout/androidaps/database/entities/GlucoseValue.kt index 32e8036558..7faae5fbaf 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/entities/GlucoseValue.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/entities/GlucoseValue.kt @@ -40,8 +40,7 @@ data class GlucoseValue( trendArrow == other.trendArrow && noise == other.noise && sourceSensor == other.sourceSensor && - isValid == other.isValid && - interfaceIDs.nightscoutId == other.interfaceIDs.nightscoutId + isValid == other.isValid fun isRecordDeleted(other: GlucoseValue): Boolean = isValid && !other.isValid diff --git a/database/src/main/java/info/nightscout/androidaps/database/transactions/CgmSourceTransaction.kt b/database/src/main/java/info/nightscout/androidaps/database/transactions/CgmSourceTransaction.kt index 7a9a5a2dda..26c5347603 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/transactions/CgmSourceTransaction.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/transactions/CgmSourceTransaction.kt @@ -9,11 +9,14 @@ import info.nightscout.androidaps.database.entities.TherapyEvent class CgmSourceTransaction( private val glucoseValues: List, private val calibrations: List, - private val sensorInsertionTime: Long? -) : Transaction>() { + private val sensorInsertionTime: Long?, + private val syncer: Boolean = false // caller is not native source ie. NS + // syncer is allowed create records + // update synchronization ID +) : Transaction() { - override fun run(): List { - val insertedGlucoseValues = mutableListOf() + override fun run(): TransactionResult { + val result = TransactionResult() glucoseValues.forEach { val current = database.glucoseValueDao.findByTimestampAndSensor(it.timestamp, it.sourceSensor) val glucoseValue = GlucoseValue( @@ -25,15 +28,26 @@ class CgmSourceTransaction( sourceSensor = it.sourceSensor ) glucoseValue.interfaceIDs.nightscoutId = it.nightscoutId + // if nsId is not provided in new record, copy from current if exists + if (glucoseValue.interfaceIDs.nightscoutId == null) + current?.let { existing -> glucoseValue.interfaceIDs.nightscoutId = existing.interfaceIDs.nightscoutId } when { - current == null -> { + // new record, create new + current == null -> { database.glucoseValueDao.insertNewEntry(glucoseValue) - insertedGlucoseValues.add(glucoseValue) + result.inserted.add(glucoseValue) } - - !current.contentEqualsTo(glucoseValue) -> { + // different record, update + !current.contentEqualsTo(glucoseValue) && !syncer -> { glucoseValue.id = current.id database.glucoseValueDao.updateExistingEntry(glucoseValue) + result.updated.add(glucoseValue) + } + // update NS id if didn't exist and now provided + current.interfaceIDs.nightscoutId == null && it.nightscoutId != null && syncer -> { + glucoseValue.id = current.id + database.glucoseValueDao.updateExistingEntry(glucoseValue) + result.updated.add(glucoseValue) } } } @@ -54,7 +68,7 @@ class CgmSourceTransaction( )) } } - return insertedGlucoseValues + return result } data class TransactionGlucoseValue( @@ -71,4 +85,16 @@ class CgmSourceTransaction( val timestamp: Long, val value: Double ) + + class TransactionResult { + + val inserted = mutableListOf() + val updated = mutableListOf() + + fun all(): MutableList = + mutableListOf().also { result -> + result.addAll(inserted) + result.addAll(updated) + } + } } \ No newline at end of file From cdac8d9d994cb146cabcdd4faa8bfbc555944c41 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Mon, 8 Feb 2021 14:51:57 +0100 Subject: [PATCH 5/8] reset databases in thread --- .../general/maintenance/MaintenanceFragment.kt | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/MaintenanceFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/MaintenanceFragment.kt index 708792f836..94e19ba0cb 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/MaintenanceFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/MaintenanceFragment.kt @@ -49,12 +49,14 @@ class MaintenanceFragment : DaggerFragment() { activity?.let { activity -> OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.maintenance), resourceHelper.gs(R.string.reset_db_confirm), Runnable { MainApp.getDbHelper().resetDatabases() - // should be handled by Plugin-Interface and - // additional service interface and plugin registry - foodPlugin.service?.resetFood() - treatmentsPlugin.service.resetTreatments() - Thread { repository.clearDatabases() } .start() - rxBus.send(EventNewBG(null)) + Thread { + // should be handled by Plugin-Interface and + // additional service interface and plugin registry + foodPlugin.service?.resetFood() + treatmentsPlugin.service.resetTreatments() + repository.clearDatabases() + rxBus.send(EventNewBG(null)) + } .start() }) } } From 4cbc30171c909a6ecfc0cc8006353a22ba734d3f Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Mon, 8 Feb 2021 14:56:23 +0100 Subject: [PATCH 6/8] explicitly specify return type in AppRepository --- .../androidaps/database/AppRepository.kt | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/database/src/main/java/info/nightscout/androidaps/database/AppRepository.kt b/database/src/main/java/info/nightscout/androidaps/database/AppRepository.kt index 8bd48a5b54..c074386d30 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/AppRepository.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/AppRepository.kt @@ -60,12 +60,12 @@ class AppRepository @Inject internal constructor( fun clearDatabases() = database.clearAllTables() //BG READINGS -- only valid records - fun compatGetBgReadingsDataFromTime(timestamp: Long, ascending: Boolean) = + fun compatGetBgReadingsDataFromTime(timestamp: Long, ascending: Boolean): Single> = database.glucoseValueDao.compatGetBgReadingsDataFromTime(timestamp) .map { if (!ascending) it.reversed() else it } .subscribeOn(Schedulers.io()) - fun compatGetBgReadingsDataFromTime(start: Long, end: Long, ascending: Boolean) = + fun compatGetBgReadingsDataFromTime(start: Long, end: Long, ascending: Boolean): Single> = database.glucoseValueDao.compatGetBgReadingsDataFromTime(start, end) .map { if (!ascending) it.reversed() else it } .subscribeOn(Schedulers.io()) @@ -74,23 +74,23 @@ class AppRepository @Inject internal constructor( fun findBgReadingByNSIdSingle(nsId: String): Single> = database.glucoseValueDao.findByNSIdMaybe(nsId).toWrappedSingle() - fun getModifiedBgReadingsDataFromId(lastId: Long) = + fun getModifiedBgReadingsDataFromId(lastId: Long): Single> = database.glucoseValueDao.getModifiedFrom(lastId) .subscribeOn(Schedulers.io()) - fun getBgReadingsCorrespondingLastHistoryRecord(lastId: Long) = + fun getBgReadingsCorrespondingLastHistoryRecord(lastId: Long): GlucoseValue? = database.glucoseValueDao.getLastHistoryRecord(lastId) @Suppress("unused") // debug purpose only - fun getAllBgReadingsStartingFrom(lastId: Long) = + fun getAllBgReadingsStartingFrom(lastId: Long): Single> = database.glucoseValueDao.getAllStartingFrom(lastId) .subscribeOn(Schedulers.io()) // TEMP TARGETS - fun compatGetTemporaryTargetData() = + fun compatGetTemporaryTargetData(): List = database.temporaryTargetDao.compatGetTemporaryTargetData() - fun compatGetTemporaryTargetDataFromTime(timestamp: Long, ascending: Boolean) = + fun compatGetTemporaryTargetDataFromTime(timestamp: Long, ascending: Boolean): Single> = database.temporaryTargetDao.compatGetTemporaryTargetDataFromTime(timestamp) .map { if (!ascending) it.reversed() else it } .subscribeOn(Schedulers.io()) @@ -98,11 +98,11 @@ class AppRepository @Inject internal constructor( fun findTemporaryTargetByNSIdSingle(nsId: String): Single> = database.temporaryTargetDao.findByNSIdMaybe(nsId).toWrappedSingle() - fun getModifiedTemporaryTargetsDataFromId(lastId: Long) = + fun getModifiedTemporaryTargetsDataFromId(lastId: Long): Single> = database.temporaryTargetDao.getModifiedFrom(lastId) .subscribeOn(Schedulers.io()) - fun getTemporaryTargetsCorrespondingLastHistoryRecord(lastId: Long) = + fun getTemporaryTargetsCorrespondingLastHistoryRecord(lastId: Long): TemporaryTarget? = database.temporaryTargetDao.getLastHistoryRecord(lastId) } From 420c5584cd7da57412c4de3a04cabb5a651f7195 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Mon, 8 Feb 2021 15:15:42 +0100 Subject: [PATCH 7/8] reset databases in CompositeDisposable --- .../maintenance/MaintenanceFragment.kt | 35 ++++++++++++++----- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/MaintenanceFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/MaintenanceFragment.kt index 94e19ba0cb..e6015b8b65 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/MaintenanceFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/MaintenanceFragment.kt @@ -12,24 +12,33 @@ import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.databinding.MaintenanceFragmentBinding import info.nightscout.androidaps.events.EventNewBG import info.nightscout.androidaps.interfaces.ImportExportPrefsInterface +import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.general.food.FoodPlugin import info.nightscout.androidaps.plugins.general.maintenance.activities.LogSettingActivity import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.resources.ResourceHelper +import info.nightscout.androidaps.utils.rx.AapsSchedulers +import io.reactivex.Completable.fromAction +import io.reactivex.disposables.CompositeDisposable +import io.reactivex.rxkotlin.subscribeBy import javax.inject.Inject class MaintenanceFragment : DaggerFragment() { + @Inject lateinit var aapsLogger: AAPSLogger @Inject lateinit var maintenancePlugin: MaintenancePlugin @Inject lateinit var rxBus: RxBusWrapper @Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var treatmentsPlugin: TreatmentsPlugin @Inject lateinit var foodPlugin: FoodPlugin @Inject lateinit var importExportPrefs: ImportExportPrefsInterface + @Inject lateinit var aapsSchedulers: AapsSchedulers @Inject lateinit var repository: AppRepository + private val compositeDisposable = CompositeDisposable() + private var _binding: MaintenanceFragmentBinding? = null // This property is only valid between onCreateView and @@ -48,15 +57,22 @@ class MaintenanceFragment : DaggerFragment() { binding.navResetdb.setOnClickListener { activity?.let { activity -> OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.maintenance), resourceHelper.gs(R.string.reset_db_confirm), Runnable { - MainApp.getDbHelper().resetDatabases() - Thread { - // should be handled by Plugin-Interface and - // additional service interface and plugin registry - foodPlugin.service?.resetFood() - treatmentsPlugin.service.resetTreatments() - repository.clearDatabases() - rxBus.send(EventNewBG(null)) - } .start() + compositeDisposable.add( + fromAction { + MainApp.getDbHelper().resetDatabases() + // should be handled by Plugin-Interface and + // additional service interface and plugin registry + foodPlugin.service?.resetFood() + treatmentsPlugin.service.resetTreatments() + repository.clearDatabases() + } + .subscribeOn(aapsSchedulers.io) + .observeOn(aapsSchedulers.main) + .subscribeBy( + onError = { aapsLogger.error("Error clearing databases", it) }, + onComplete = { rxBus.send(EventNewBG(null)) } + ) + ) }) } } @@ -78,6 +94,7 @@ class MaintenanceFragment : DaggerFragment() { @Synchronized override fun onDestroyView() { super.onDestroyView() + compositeDisposable.clear() _binding = null } } \ No newline at end of file From 290ff23ddc49d833b0fd3ebb5d1147086d0bad61 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Mon, 8 Feb 2021 15:29:13 +0100 Subject: [PATCH 8/8] add logging --- .../plugins/general/maintenance/MaintenanceFragment.kt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/MaintenanceFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/MaintenanceFragment.kt index e6015b8b65..e2c20aa0e6 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/MaintenanceFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/MaintenanceFragment.kt @@ -53,10 +53,14 @@ class MaintenanceFragment : DaggerFragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) binding.logSend.setOnClickListener { maintenancePlugin.sendLogs() } - binding.logDelete.setOnClickListener { maintenancePlugin.deleteLogs() } + binding.logDelete.setOnClickListener { + aapsLogger.debug("USER ENTRY: DELETE LOGS") + maintenancePlugin.deleteLogs() + } binding.navResetdb.setOnClickListener { activity?.let { activity -> OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.maintenance), resourceHelper.gs(R.string.reset_db_confirm), Runnable { + aapsLogger.debug("USER ENTRY: RESET DATABASES") compositeDisposable.add( fromAction { MainApp.getDbHelper().resetDatabases() @@ -77,12 +81,14 @@ class MaintenanceFragment : DaggerFragment() { } } binding.navExport.setOnClickListener { + aapsLogger.debug("USER ENTRY: EXPORT SETTINGS") // start activity for checking permissions... importExportPrefs.verifyStoragePermissions(this) { importExportPrefs.exportSharedPreferences(this) } } binding.navImport.setOnClickListener { + aapsLogger.debug("USER ENTRY: IMPORT SETTINGS") // start activity for checking permissions... importExportPrefs.verifyStoragePermissions(this) { importExportPrefs.importSharedPreferences(this)