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()