From c71fc275a544bd3ae477549e8786e4188a69fe70 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Tue, 17 Jan 2023 13:58:07 +0100 Subject: [PATCH] move more plugins to Synchronization group --- .../activities/MyPreferenceFragment.kt | 4 +- .../androidaps/di/PluginsListModule.kt | 48 +++--- .../androidaps/receivers/DataReceiver.kt | 4 +- .../implementation/wizard/BolusWizardTest.kt | 2 - plugins/main/src/main/res/values/strings.xml | 12 -- .../src/main/res/xml/pref_xdripstatus.xml | 24 --- .../openhumans/OpenHumansUploaderPlugin.kt | 2 +- .../{XdripPlugin.kt => XdripSourcePlugin.kt} | 12 +- .../info/nightscout/source/di/SourceModule.kt | 6 +- ...PluginTest.kt => XdripSourcePluginTest.kt} | 8 +- .../dataBroadcaster/DataBroadcastPlugin.kt | 19 ++- .../plugins/sync/xdrip/XdripPlugin.kt} | 70 ++++---- plugins/sync/src/main/res/values/strings.xml | 21 +++ plugins/sync/src/main/res/xml/pref_xdrip.xml | 37 ++++ .../nightscout/androidaps}/BundleMock.java | 15 +- .../androidaps/TestBaseWithProfile.kt | 6 +- .../nightscout/androidaps/TestPumpPlugin.kt | 74 ++++++++ .../DataBroadcastPluginTest.kt | 159 ++++++++++++++++++ 18 files changed, 382 insertions(+), 141 deletions(-) delete mode 100644 plugins/main/src/main/res/xml/pref_xdripstatus.xml rename plugins/source/src/main/java/info/nightscout/source/{XdripPlugin.kt => XdripSourcePlugin.kt} (91%) rename plugins/source/src/test/java/info/nightscout/source/{XdripPluginTest.kt => XdripSourcePluginTest.kt} (61%) rename plugins/{main/src/main/java/info/nightscout/plugins/general => sync/src/main/java/info/nightscout/plugins/sync}/dataBroadcaster/DataBroadcastPlugin.kt (96%) rename plugins/{main/src/main/java/info/nightscout/plugins/general/xdripStatusline/StatusLinePlugin.kt => sync/src/main/java/info/nightscout/plugins/sync/xdrip/XdripPlugin.kt} (73%) create mode 100644 plugins/sync/src/main/res/xml/pref_xdrip.xml rename {wear/src/test/java/info/nightscout/androidaps/testing/mocks => plugins/sync/src/test/java/info/nightscout/androidaps}/BundleMock.java (95%) create mode 100644 plugins/sync/src/test/java/info/nightscout/androidaps/TestPumpPlugin.kt create mode 100644 plugins/sync/src/test/java/info/nightscout/plugins/sync/dataBroadcaster/DataBroadcastPluginTest.kt diff --git a/app/src/main/java/info/nightscout/androidaps/activities/MyPreferenceFragment.kt b/app/src/main/java/info/nightscout/androidaps/activities/MyPreferenceFragment.kt index f39bf3f569..27b1cd28a2 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/MyPreferenceFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/activities/MyPreferenceFragment.kt @@ -47,10 +47,10 @@ import info.nightscout.plugins.constraints.safety.SafetyPlugin import info.nightscout.plugins.general.autotune.AutotunePlugin import info.nightscout.plugins.general.smsCommunicator.SmsCommunicatorPlugin import info.nightscout.plugins.general.wear.WearPlugin -import info.nightscout.plugins.general.xdripStatusline.StatusLinePlugin import info.nightscout.plugins.sync.nsclient.NSClientPlugin import info.nightscout.plugins.sync.nsclientV3.NSClientV3Plugin import info.nightscout.plugins.sync.tidepool.TidepoolPlugin +import info.nightscout.plugins.sync.xdrip.XdripPlugin import info.nightscout.pump.combo.ComboPlugin import info.nightscout.pump.combov2.ComboV2Plugin import info.nightscout.pump.diaconn.DiaconnG8Plugin @@ -116,7 +116,7 @@ class MyPreferenceFragment : PreferenceFragmentCompat(), OnSharedPreferenceChang @Inject lateinit var intelligoPlugin: IntelligoPlugin @Inject lateinit var aidexPlugin: AidexPlugin @Inject lateinit var smsCommunicatorPlugin: SmsCommunicatorPlugin - @Inject lateinit var statusLinePlugin: StatusLinePlugin + @Inject lateinit var statusLinePlugin: XdripPlugin @Inject lateinit var tidepoolPlugin: TidepoolPlugin @Inject lateinit var virtualPumpPlugin: VirtualPumpPlugin @Inject lateinit var wearPlugin: WearPlugin diff --git a/app/src/main/java/info/nightscout/androidaps/di/PluginsListModule.kt b/app/src/main/java/info/nightscout/androidaps/di/PluginsListModule.kt index 8ae822b1c6..7e1b89f547 100644 --- a/app/src/main/java/info/nightscout/androidaps/di/PluginsListModule.kt +++ b/app/src/main/java/info/nightscout/androidaps/di/PluginsListModule.kt @@ -31,19 +31,19 @@ import info.nightscout.plugins.constraints.safety.SafetyPlugin import info.nightscout.plugins.constraints.signatureVerifier.SignatureVerifierPlugin import info.nightscout.plugins.general.actions.ActionsPlugin import info.nightscout.plugins.general.autotune.AutotunePlugin -import info.nightscout.plugins.general.dataBroadcaster.DataBroadcastPlugin import info.nightscout.plugins.general.food.FoodPlugin import info.nightscout.plugins.general.overview.OverviewPlugin import info.nightscout.plugins.general.persistentNotification.PersistentNotificationPlugin import info.nightscout.plugins.general.smsCommunicator.SmsCommunicatorPlugin import info.nightscout.plugins.general.themes.ThemeSwitcherPlugin import info.nightscout.plugins.general.wear.WearPlugin -import info.nightscout.plugins.general.xdripStatusline.StatusLinePlugin import info.nightscout.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin import info.nightscout.plugins.profile.ProfilePlugin +import info.nightscout.plugins.sync.dataBroadcaster.DataBroadcastPlugin import info.nightscout.plugins.sync.nsclient.NSClientPlugin import info.nightscout.plugins.sync.nsclientV3.NSClientV3Plugin import info.nightscout.plugins.sync.tidepool.TidepoolPlugin +import info.nightscout.plugins.sync.xdrip.XdripPlugin import info.nightscout.pump.combo.ComboPlugin import info.nightscout.pump.combov2.ComboV2Plugin import info.nightscout.pump.diaconn.DiaconnG8Plugin @@ -51,8 +51,8 @@ import info.nightscout.pump.virtual.VirtualPumpPlugin import info.nightscout.sensitivity.SensitivityAAPSPlugin import info.nightscout.sensitivity.SensitivityOref1Plugin import info.nightscout.sensitivity.SensitivityWeightedAveragePlugin -import info.nightscout.smoothing.ExponentialSmoothingPlugin import info.nightscout.smoothing.AvgSmoothingPlugin +import info.nightscout.smoothing.ExponentialSmoothingPlugin import info.nightscout.smoothing.NoSmoothingPlugin import info.nightscout.source.AidexPlugin import info.nightscout.source.DexcomPlugin @@ -64,7 +64,7 @@ import info.nightscout.source.NSClientSourcePlugin import info.nightscout.source.PoctechPlugin import info.nightscout.source.RandomBgPlugin import info.nightscout.source.TomatoPlugin -import info.nightscout.source.XdripPlugin +import info.nightscout.source.XdripSourcePlugin import javax.inject.Qualifier @Suppress("unused") @@ -308,26 +308,38 @@ abstract class PluginsListModule { @Binds @AllConfigs @IntoMap - @IntKey(340) - abstract fun bindStatusLinePlugin(plugin: StatusLinePlugin): PluginBase + @IntKey(350) + abstract fun bindNSClientPlugin(plugin: NSClientPlugin): PluginBase @Binds @AllConfigs @IntoMap - @IntKey(360) - abstract fun bindNSClientPlugin(plugin: NSClientPlugin): PluginBase + @IntKey(355) + abstract fun bindNSClientV3Plugin(plugin: NSClientV3Plugin): PluginBase @Binds @Unfinished @IntoMap - @IntKey(368) + @IntKey(360) abstract fun bindTidepoolPlugin(plugin: TidepoolPlugin): PluginBase @Binds @AllConfigs @IntoMap - @IntKey(362) - abstract fun bindNSClientV3Plugin(plugin: NSClientV3Plugin): PluginBase + @IntKey(364) + abstract fun bindXdripPlugin(plugin: XdripPlugin): PluginBase + + @Binds + @AllConfigs + @IntoMap + @IntKey(366) + abstract fun bindDataBroadcastPlugin(plugin: DataBroadcastPlugin): PluginBase + + @Binds + @NotNSClient + @IntoMap + @IntKey(368) + abstract fun bindsOpenHumansPlugin(plugin: OpenHumansUploaderPlugin): PluginBase @Binds @AllConfigs @@ -347,17 +359,11 @@ abstract class PluginsListModule { @IntKey(381) abstract fun bindBgQualityCheckPlugin(plugin: BgQualityCheckPlugin): PluginBase - @Binds - @AllConfigs - @IntoMap - @IntKey(390) - abstract fun bindDataBroadcastPlugin(plugin: DataBroadcastPlugin): PluginBase - @Binds @AllConfigs @IntoMap @IntKey(400) - abstract fun bindXdripPlugin(plugin: XdripPlugin): PluginBase + abstract fun bindXdripSourcePlugin(plugin: XdripSourcePlugin): PluginBase @Binds @AllConfigs @@ -419,12 +425,6 @@ abstract class PluginsListModule { @IntKey(475) abstract fun bindRandomBgPlugin(plugin: RandomBgPlugin): PluginBase - @Binds - @NotNSClient - @IntoMap - @IntKey(480) - abstract fun bindsOpenHumansPlugin(plugin: OpenHumansUploaderPlugin): PluginBase - @Binds @AllConfigs @IntoMap diff --git a/app/src/main/java/info/nightscout/androidaps/receivers/DataReceiver.kt b/app/src/main/java/info/nightscout/androidaps/receivers/DataReceiver.kt index 1c681f7330..09c93b9195 100644 --- a/app/src/main/java/info/nightscout/androidaps/receivers/DataReceiver.kt +++ b/app/src/main/java/info/nightscout/androidaps/receivers/DataReceiver.kt @@ -22,7 +22,7 @@ import info.nightscout.source.GlimpPlugin import info.nightscout.source.MM640gPlugin import info.nightscout.source.PoctechPlugin import info.nightscout.source.TomatoPlugin -import info.nightscout.source.XdripPlugin +import info.nightscout.source.XdripSourcePlugin import javax.inject.Inject open class DataReceiver : DaggerBroadcastReceiver() { @@ -37,7 +37,7 @@ open class DataReceiver : DaggerBroadcastReceiver() { when (intent.action) { Intents.ACTION_NEW_BG_ESTIMATE -> - OneTimeWorkRequest.Builder(XdripPlugin.XdripWorker::class.java) + OneTimeWorkRequest.Builder(XdripSourcePlugin.XdripSourceWorker::class.java) .setInputData(dataWorkerStorage.storeInputData(bundle, intent.action)).build() Intents.POCTECH_BG -> OneTimeWorkRequest.Builder(PoctechPlugin.PoctechWorker::class.java) diff --git a/implementation/src/test/java/info/nightscout/implementation/wizard/BolusWizardTest.kt b/implementation/src/test/java/info/nightscout/implementation/wizard/BolusWizardTest.kt index caa826177d..163c8e36c0 100644 --- a/implementation/src/test/java/info/nightscout/implementation/wizard/BolusWizardTest.kt +++ b/implementation/src/test/java/info/nightscout/implementation/wizard/BolusWizardTest.kt @@ -1,6 +1,5 @@ package info.nightscout.implementation.wizard -import android.content.Context import dagger.android.AndroidInjector import dagger.android.HasAndroidInjector import info.nightscout.androidaps.TestBase @@ -35,7 +34,6 @@ class BolusWizardTest : TestBase() { @Mock lateinit var rh: ResourceHelper @Mock lateinit var profileFunction: ProfileFunction @Mock lateinit var constraintChecker: Constraints - @Mock lateinit var context: Context @Mock lateinit var activePlugin: ActivePlugin @Mock lateinit var commandQueue: CommandQueue @Mock lateinit var loop: Loop diff --git a/plugins/main/src/main/res/values/strings.xml b/plugins/main/src/main/res/values/strings.xml index 380d3be372..4d277aea40 100644 --- a/plugins/main/src/main/res/values/strings.xml +++ b/plugins/main/src/main/res/values/strings.xml @@ -112,21 +112,11 @@ TBR duration must be a multiple of %1$d minutes and greater than 0. QR Code for setup one time password - - xdripstatus_detailediob - xdripstatus_showbgi - xdripstatus_settings - - - xDrip+ Statusline (watch) - xds - Show information about your loop on your xDrip+ watchface. Show detailed IOB Break down IOB into bolus and basal IOB on the watchface Loop Disabled Show BGI Add BGI to status line - xDrip+ Status (watch) Food @@ -331,8 +321,6 @@ Large display Skin - - Data Broadcaster usage: diff --git a/plugins/main/src/main/res/xml/pref_xdripstatus.xml b/plugins/main/src/main/res/xml/pref_xdripstatus.xml deleted file mode 100644 index 4fd92a2faf..0000000000 --- a/plugins/main/src/main/res/xml/pref_xdripstatus.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/plugins/openhumans/src/main/java/info/nightscout/androidaps/plugin/general/openhumans/OpenHumansUploaderPlugin.kt b/plugins/openhumans/src/main/java/info/nightscout/androidaps/plugin/general/openhumans/OpenHumansUploaderPlugin.kt index 77411d5e73..31cf978d58 100644 --- a/plugins/openhumans/src/main/java/info/nightscout/androidaps/plugin/general/openhumans/OpenHumansUploaderPlugin.kt +++ b/plugins/openhumans/src/main/java/info/nightscout/androidaps/plugin/general/openhumans/OpenHumansUploaderPlugin.kt @@ -69,7 +69,7 @@ class OpenHumansUploaderPlugin @Inject internal constructor( private val rxBus: RxBus ) : PluginBase( PluginDescription() - .mainType(PluginType.GENERAL) + .mainType(PluginType.SYNC) .pluginIcon(R.drawable.open_humans_white) .pluginName(R.string.open_humans) .shortName(R.string.open_humans_short) diff --git a/plugins/source/src/main/java/info/nightscout/source/XdripPlugin.kt b/plugins/source/src/main/java/info/nightscout/source/XdripSourcePlugin.kt similarity index 91% rename from plugins/source/src/main/java/info/nightscout/source/XdripPlugin.kt rename to plugins/source/src/main/java/info/nightscout/source/XdripSourcePlugin.kt index af711ebfd3..78c9084dab 100644 --- a/plugins/source/src/main/java/info/nightscout/source/XdripPlugin.kt +++ b/plugins/source/src/main/java/info/nightscout/source/XdripSourcePlugin.kt @@ -25,7 +25,7 @@ import javax.inject.Inject import javax.inject.Singleton @Singleton -class XdripPlugin @Inject constructor( +class XdripSourcePlugin @Inject constructor( injector: HasAndroidInjector, rh: ResourceHelper, aapsLogger: AAPSLogger @@ -58,19 +58,19 @@ class XdripPlugin @Inject constructor( } // cannot be inner class because of needed injection - class XdripWorker( + class XdripSourceWorker( context: Context, params: WorkerParameters ) : LoggingWorker(context, params, Dispatchers.IO) { - @Inject lateinit var xdripPlugin: XdripPlugin + @Inject lateinit var xdripSourcePlugin: XdripSourcePlugin @Inject lateinit var repository: AppRepository @Inject lateinit var dataWorkerStorage: DataWorkerStorage override suspend fun doWorkAndLog(): Result { var ret = Result.success() - if (!xdripPlugin.isEnabled()) return Result.success(workDataOf("Result" to "Plugin not enabled")) + if (!xdripSourcePlugin.isEnabled()) return Result.success(workDataOf("Result" to "Plugin not enabled")) val bundle = dataWorkerStorage.pickupBundle(inputData.getLong(DataWorkerStorage.STORE_KEY, -1)) ?: return Result.failure(workDataOf("Error" to "missing input data")) @@ -93,11 +93,11 @@ class XdripPlugin @Inject constructor( .blockingGet() .also { savedValues -> savedValues.all().forEach { - xdripPlugin.detectSource(it) + xdripSourcePlugin.detectSource(it) aapsLogger.debug(LTag.DATABASE, "Inserted bg $it") } } - xdripPlugin.sensorBatteryLevel = bundle.getInt(Intents.EXTRA_SENSOR_BATTERY, -1) + xdripSourcePlugin.sensorBatteryLevel = bundle.getInt(Intents.EXTRA_SENSOR_BATTERY, -1) return ret } } diff --git a/plugins/source/src/main/java/info/nightscout/source/di/SourceModule.kt b/plugins/source/src/main/java/info/nightscout/source/di/SourceModule.kt index 2aec6c6d5a..08d5e3e57b 100644 --- a/plugins/source/src/main/java/info/nightscout/source/di/SourceModule.kt +++ b/plugins/source/src/main/java/info/nightscout/source/di/SourceModule.kt @@ -15,7 +15,7 @@ import info.nightscout.source.MM640gPlugin import info.nightscout.source.NSClientSourcePlugin import info.nightscout.source.PoctechPlugin import info.nightscout.source.TomatoPlugin -import info.nightscout.source.XdripPlugin +import info.nightscout.source.XdripSourcePlugin import info.nightscout.source.activities.RequestDexcomPermissionActivity @Module( @@ -30,7 +30,7 @@ abstract class SourceModule { @ContributesAndroidInjector abstract fun contributesBGSourceFragment(): BGSourceFragment @ContributesAndroidInjector abstract fun contributesNSClientSourceWorker(): NSClientSourcePlugin.NSClientSourceWorker - @ContributesAndroidInjector abstract fun contributesXdripWorker(): XdripPlugin.XdripWorker + @ContributesAndroidInjector abstract fun contributesXdripWorker(): XdripSourcePlugin.XdripSourceWorker @ContributesAndroidInjector abstract fun contributesDexcomWorker(): DexcomPlugin.DexcomWorker @ContributesAndroidInjector abstract fun contributesMM640gWorker(): MM640gPlugin.MM640gWorker @ContributesAndroidInjector abstract fun contributesGlimpWorker(): GlimpPlugin.GlimpWorker @@ -46,6 +46,6 @@ abstract class SourceModule { @Binds fun bindNSClientSource(nsClientSourcePlugin: NSClientSourcePlugin): NSClientSource @Binds fun bindDexcomBoyda(dexcomPlugin: DexcomPlugin): DexcomBoyda - @Binds fun bindXDrip(xdripPlugin: XdripPlugin): XDrip + @Binds fun bindXDrip(xdripSourcePlugin: XdripSourcePlugin): XDrip } } \ No newline at end of file diff --git a/plugins/source/src/test/java/info/nightscout/source/XdripPluginTest.kt b/plugins/source/src/test/java/info/nightscout/source/XdripSourcePluginTest.kt similarity index 61% rename from plugins/source/src/test/java/info/nightscout/source/XdripPluginTest.kt rename to plugins/source/src/test/java/info/nightscout/source/XdripSourcePluginTest.kt index 2524a18db6..18626e048d 100644 --- a/plugins/source/src/test/java/info/nightscout/source/XdripPluginTest.kt +++ b/plugins/source/src/test/java/info/nightscout/source/XdripSourcePluginTest.kt @@ -8,18 +8,18 @@ import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.mockito.Mock -class XdripPluginTest : TestBase() { +class XdripSourcePluginTest : TestBase() { - private lateinit var xdripPlugin: XdripPlugin + private lateinit var xdripSourcePlugin: XdripSourcePlugin @Mock lateinit var rh: ResourceHelper @BeforeEach fun setup() { - xdripPlugin = XdripPlugin({ AndroidInjector { } }, rh, aapsLogger) + xdripSourcePlugin = XdripSourcePlugin({ AndroidInjector { } }, rh, aapsLogger) } @Test fun advancedFilteringSupported() { - Assertions.assertEquals(false, xdripPlugin.advancedFilteringSupported()) + Assertions.assertEquals(false, xdripSourcePlugin.advancedFilteringSupported()) } } \ No newline at end of file diff --git a/plugins/main/src/main/java/info/nightscout/plugins/general/dataBroadcaster/DataBroadcastPlugin.kt b/plugins/sync/src/main/java/info/nightscout/plugins/sync/dataBroadcaster/DataBroadcastPlugin.kt similarity index 96% rename from plugins/main/src/main/java/info/nightscout/plugins/general/dataBroadcaster/DataBroadcastPlugin.kt rename to plugins/sync/src/main/java/info/nightscout/plugins/sync/dataBroadcaster/DataBroadcastPlugin.kt index 96bedc370d..ba6cf0b364 100644 --- a/plugins/main/src/main/java/info/nightscout/plugins/general/dataBroadcaster/DataBroadcastPlugin.kt +++ b/plugins/sync/src/main/java/info/nightscout/plugins/sync/dataBroadcaster/DataBroadcastPlugin.kt @@ -1,4 +1,4 @@ -package info.nightscout.plugins.general.dataBroadcaster +package info.nightscout.plugins.sync.dataBroadcaster import android.content.Context import android.content.Intent @@ -22,7 +22,7 @@ import info.nightscout.interfaces.profile.DefaultValueHelper import info.nightscout.interfaces.profile.ProfileFunction import info.nightscout.interfaces.receivers.Intents import info.nightscout.interfaces.receivers.ReceiverStatusStore -import info.nightscout.plugins.R +import info.nightscout.plugins.sync.R import info.nightscout.rx.AapsSchedulers import info.nightscout.rx.bus.RxBus import info.nightscout.rx.events.Event @@ -60,7 +60,7 @@ class DataBroadcastPlugin @Inject constructor( private val glucoseStatusProvider: GlucoseStatusProvider ) : PluginBase( PluginDescription() - .mainType(PluginType.GENERAL) + .mainType(PluginType.SYNC) .pluginName(R.string.data_broadcaster) .alwaysEnabled(true) .neverVisible(true) @@ -90,8 +90,7 @@ class DataBroadcastPlugin @Inject constructor( super.onStop() } - private fun sendData(event: Event) { - val bundle = Bundle() + internal fun prepareData(event: Event, bundle: Bundle) { bgStatus(bundle) iobCob(bundle) loopStatus(bundle) @@ -102,6 +101,11 @@ class DataBroadcastPlugin @Inject constructor( bundle.putInt("progressPercent", event.percent) bundle.putString("progressStatus", event.status) } + } + + private fun sendData(event: Event) { + val bundle = Bundle() + prepareData(event, bundle) //aapsLogger.debug("Prepared bundle:\n" + BundleLogger.log(bundle)) sendBroadcast( @@ -147,10 +151,7 @@ class DataBroadcastPlugin @Inject constructor( bundle.putLong("suggestedTimeStamp", loop.lastRun?.lastAPSRun ?: -1L) bundle.putString("suggested", loop.lastRun?.request?.json().toString()) if (loop.lastRun?.tbrSetByPump != null && loop.lastRun?.tbrSetByPump?.enacted == true) { - bundle.putLong( - "enactedTimeStamp", loop.lastRun?.lastTBREnact - ?: -1L - ) + bundle.putLong("enactedTimeStamp", loop.lastRun?.lastTBREnact ?: -1L) bundle.putString("enacted", loop.lastRun?.request?.json().toString()) } } else { //NSClient or remote diff --git a/plugins/main/src/main/java/info/nightscout/plugins/general/xdripStatusline/StatusLinePlugin.kt b/plugins/sync/src/main/java/info/nightscout/plugins/sync/xdrip/XdripPlugin.kt similarity index 73% rename from plugins/main/src/main/java/info/nightscout/plugins/general/xdripStatusline/StatusLinePlugin.kt rename to plugins/sync/src/main/java/info/nightscout/plugins/sync/xdrip/XdripPlugin.kt index 592e8e9727..785cde4be5 100644 --- a/plugins/main/src/main/java/info/nightscout/plugins/general/xdripStatusline/StatusLinePlugin.kt +++ b/plugins/sync/src/main/java/info/nightscout/plugins/sync/xdrip/XdripPlugin.kt @@ -1,4 +1,4 @@ -package info.nightscout.plugins.general.xdripStatusline +package info.nightscout.plugins.sync.xdrip import android.content.Context import android.content.Intent @@ -16,7 +16,7 @@ import info.nightscout.interfaces.plugin.PluginType import info.nightscout.interfaces.profile.Profile import info.nightscout.interfaces.profile.ProfileFunction import info.nightscout.interfaces.utils.DecimalFormatter -import info.nightscout.plugins.R +import info.nightscout.plugins.sync.R import info.nightscout.rx.AapsSchedulers import info.nightscout.rx.bus.RxBus import info.nightscout.rx.events.EventAppInitialized @@ -36,7 +36,7 @@ import javax.inject.Inject import javax.inject.Singleton @Singleton -class StatusLinePlugin @Inject constructor( +class XdripPlugin @Inject constructor( injector: HasAndroidInjector, private val sp: SP, private val profileFunction: ProfileFunction, @@ -50,13 +50,13 @@ class StatusLinePlugin @Inject constructor( aapsLogger: AAPSLogger ) : PluginBase( PluginDescription() - .mainType(PluginType.GENERAL) + .mainType(PluginType.SYNC) .pluginIcon((info.nightscout.core.main.R.drawable.ic_blooddrop_48)) - .pluginName(R.string.xdrip_status) - .shortName(R.string.xdrip_status_shortname) + .pluginName(R.string.xdrip) + .shortName(R.string.xdrip_shortname) .neverVisible(true) - .preferencesId(R.xml.pref_xdripstatus) - .description(R.string.description_xdrip_status_line), + .preferencesId(R.xml.pref_xdrip) + .description(R.string.description_xdrip), aapsLogger, rh, injector ) { @@ -111,47 +111,47 @@ class StatusLinePlugin @Inject constructor( } private fun sendStatus() { - var status = "" // sent once on disable - val profile = profileFunction.getProfile() - if (isEnabled() && profile != null) { - status = buildStatusString(profile) + if (sp.getBoolean(R.string.key_xdrip_send_status, false)) { + val status = profileFunction.getProfile()?.let { buildStatusLine(it) } ?: "" + context.sendBroadcast( + Intent(ACTION_NEW_EXTERNAL_STATUSLINE).also { + it.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES) + it.putExtras(Bundle().apply { putString(EXTRA_STATUSLINE, status) }) + } + ) } - //sendData - val bundle = Bundle() - bundle.putString(EXTRA_STATUSLINE, status) - val intent = Intent(ACTION_NEW_EXTERNAL_STATUSLINE) - intent.putExtras(bundle) - intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES) - context.sendBroadcast(intent, null) } - private fun buildStatusString(profile: Profile): String { - var status = "" - if (!(loop as PluginBase).isEnabled()) { - status += rh.gs(R.string.disabled_loop) + "\n" + private fun buildStatusLine(profile: Profile): String { + val status = StringBuilder() + @Suppress("LiftReturnOrAssignment") + if (!loop.isEnabled()) { + status.append(rh.gs(R.string.disabled_loop)).append("\n") lastLoopStatus = false } else lastLoopStatus = true //Temp basal - val activeTemp = iobCobCalculator.getTempBasalIncludingConvertedExtended(System.currentTimeMillis()) - if (activeTemp != null) { - status += activeTemp.toStringShort() + " " + iobCobCalculator.getTempBasalIncludingConvertedExtended(System.currentTimeMillis())?.let { + status.append(it.toStringShort()).append(" ") } //IOB val bolusIob = iobCobCalculator.calculateIobFromBolus().round() val basalIob = iobCobCalculator.calculateIobFromTempBasalsIncludingConvertedExtended().round() - status += DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U" - if (sp.getBoolean(R.string.key_xdrip_status_detailed_iob, true)) { - status += ("(" - + DecimalFormatter.to2Decimal(bolusIob.iob) + "|" - + DecimalFormatter.to2Decimal(basalIob.basaliob) + ")") - } + status.append(DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob)).append(rh.gs(info.nightscout.core.ui.R.string.insulin_unit_shortname)) + if (sp.getBoolean(R.string.key_xdrip_status_detailed_iob, true)) + status.append("(") + .append(DecimalFormatter.to2Decimal(bolusIob.iob)) + .append("|") + .append(DecimalFormatter.to2Decimal(basalIob.basaliob)) + .append(")") if (sp.getBoolean(R.string.key_xdrip_status_show_bgi, true)) { val bgi = -(bolusIob.activity + basalIob.activity) * 5 * Profile.fromMgdlToUnits(profile.getIsfMgdl(), profileFunction.getUnits()) - status += " " + (if (bgi >= 0) "+" else "") + DecimalFormatter.to2Decimal(bgi) + status.append(" ") + .append(if (bgi >= 0) "+" else "") + .append(DecimalFormatter.to2Decimal(bgi)) } // COB - status += " " + iobCobCalculator.getCobInfo("StatusLinePlugin").generateCOBString() - return status + status.append(" ").append(iobCobCalculator.getCobInfo("StatusLinePlugin").generateCOBString()) + return status.toString() } } \ No newline at end of file diff --git a/plugins/sync/src/main/res/values/strings.xml b/plugins/sync/src/main/res/values/strings.xml index 9d6bdef502..fbd606f210 100644 --- a/plugins/sync/src/main/res/values/strings.xml +++ b/plugins/sync/src/main/res/values/strings.xml @@ -147,4 +147,25 @@ Read only Working + + xdripstatus_detailediob + xdripstatus_showbgi + xdripstatus_settings + xdrip_send_status + + + xDrip+ + XD + Send data to xDrip+ + Show detailed IOB + Break down IOB into bolus and basal IOB on the watchface + Show BGI + Add BGI to status line + xDrip+ Status (watch) + Loop Disabled + Send status line to xDrip+ + + + Data Broadcaster + \ No newline at end of file diff --git a/plugins/sync/src/main/res/xml/pref_xdrip.xml b/plugins/sync/src/main/res/xml/pref_xdrip.xml new file mode 100644 index 0000000000..5f73ee232e --- /dev/null +++ b/plugins/sync/src/main/res/xml/pref_xdrip.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/wear/src/test/java/info/nightscout/androidaps/testing/mocks/BundleMock.java b/plugins/sync/src/test/java/info/nightscout/androidaps/BundleMock.java similarity index 95% rename from wear/src/test/java/info/nightscout/androidaps/testing/mocks/BundleMock.java rename to plugins/sync/src/test/java/info/nightscout/androidaps/BundleMock.java index 0f04d47276..940f882bf1 100644 --- a/wear/src/test/java/info/nightscout/androidaps/testing/mocks/BundleMock.java +++ b/plugins/sync/src/test/java/info/nightscout/androidaps/BundleMock.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.testing.mocks; +package info.nightscout.androidaps; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; @@ -17,8 +17,6 @@ import android.os.Bundle; import android.os.Parcelable; import android.util.SparseArray; -import com.google.android.gms.wearable.DataMap; - import org.mockito.Mockito; import org.mockito.stubbing.Answer; @@ -28,19 +26,11 @@ import java.util.HashMap; @SuppressWarnings({"unused", "rawtypes", "SuspiciousMethodCalls", "unchecked"}) public final class BundleMock { -/* + public static Bundle mock() { return mock(new HashMap<>()); } - public static Bundle mock(DataMap dataMap) { - HashMap hm = new HashMap<>(); - for (String key : dataMap.keySet()) { - hm.put(key, dataMap.get(key)); - } - return mock(hm); - } - public static Bundle mock(final HashMap map) { Answer unsupported = invocation -> { @@ -180,5 +170,4 @@ public final class BundleMock { return bundle; } - */ } \ No newline at end of file diff --git a/plugins/sync/src/test/java/info/nightscout/androidaps/TestBaseWithProfile.kt b/plugins/sync/src/test/java/info/nightscout/androidaps/TestBaseWithProfile.kt index bcef7a1640..cf5946aea0 100644 --- a/plugins/sync/src/test/java/info/nightscout/androidaps/TestBaseWithProfile.kt +++ b/plugins/sync/src/test/java/info/nightscout/androidaps/TestBaseWithProfile.kt @@ -8,14 +8,12 @@ import info.nightscout.core.utils.fabric.FabricPrivacy import info.nightscout.database.entities.EffectiveProfileSwitch import info.nightscout.database.entities.embedments.InsulinConfiguration import info.nightscout.database.impl.AppRepository -import info.nightscout.implementation.profile.ProfileFunctionImpl import info.nightscout.implementation.profile.ProfileStoreObject import info.nightscout.interfaces.Config import info.nightscout.interfaces.insulin.Insulin import info.nightscout.interfaces.iob.IobCobCalculator import info.nightscout.interfaces.nsclient.ProcessedDeviceStatusData import info.nightscout.interfaces.plugin.ActivePlugin -import info.nightscout.interfaces.profile.ProfileFunction import info.nightscout.interfaces.profile.ProfileStore import info.nightscout.interfaces.utils.HardLimits import info.nightscout.rx.bus.RxBus @@ -46,7 +44,7 @@ open class TestBaseWithProfile : TestBase() { @Mock lateinit var processedDeviceStatusData: ProcessedDeviceStatusData @Mock lateinit var insulin: Insulin - open lateinit var profileFunction: ProfileFunction + //open lateinit var profileFunction: ProfileFunction lateinit var dateUtil: DateUtil var insulinConfiguration: InsulinConfiguration = InsulinConfiguration("Insulin", 360 * 60 * 1000, 60 * 60 * 1000) val rxBus = RxBus(aapsSchedulers, aapsLogger) @@ -68,7 +66,7 @@ open class TestBaseWithProfile : TestBase() { `when`(dateUtil.now()).thenReturn(1656358822000) `when`(insulin.insulinConfiguration).thenReturn(insulinConfiguration) `when`(activePlugin.activeInsulin).thenReturn(insulin) - profileFunction = ProfileFunctionImpl(aapsLogger, sp, rxBus, rh, activePlugin, repository, dateUtil, config, hardLimits, aapsSchedulers, fabricPrivacy, processedDeviceStatusData) + //profileFunction = ProfileFunctionImpl(aapsLogger, sp, rxBus, rh, activePlugin, repository, dateUtil, config, hardLimits, aapsSchedulers, fabricPrivacy, processedDeviceStatusData) validProfile = ProfileSealed.Pure(pureProfileFromJson(JSONObject(validProfileJSON), dateUtil)!!) effectiveProfileSwitch = EffectiveProfileSwitch( timestamp = dateUtil.now(), diff --git a/plugins/sync/src/test/java/info/nightscout/androidaps/TestPumpPlugin.kt b/plugins/sync/src/test/java/info/nightscout/androidaps/TestPumpPlugin.kt new file mode 100644 index 0000000000..9c4cae2277 --- /dev/null +++ b/plugins/sync/src/test/java/info/nightscout/androidaps/TestPumpPlugin.kt @@ -0,0 +1,74 @@ +package info.nightscout.androidaps + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.annotations.OpenForTesting +import info.nightscout.interfaces.profile.Profile +import info.nightscout.interfaces.pump.DetailedBolusInfo +import info.nightscout.interfaces.pump.Pump +import info.nightscout.interfaces.pump.PumpEnactResult +import info.nightscout.interfaces.pump.PumpSync +import info.nightscout.interfaces.pump.defs.ManufacturerType +import info.nightscout.interfaces.pump.defs.PumpDescription +import info.nightscout.interfaces.pump.defs.PumpType +import info.nightscout.interfaces.utils.TimeChangeType +import org.json.JSONObject + +@Suppress("MemberVisibilityCanBePrivate") +@OpenForTesting +class TestPumpPlugin(val injector: HasAndroidInjector) : Pump { + + var connected = false + var isProfileSet = true + + override fun isConnected() = connected + override fun isConnecting() = false + override fun isHandshakeInProgress() = false + val lastData = 0L + + val baseBasal = 0.0 + override var pumpDescription = PumpDescription() + + override fun isInitialized(): Boolean = true + override fun isSuspended(): Boolean = false + override fun isBusy(): Boolean = false + override fun connect(reason: String) { + connected = true + } + + override fun disconnect(reason: String) { + connected = false + } + + override fun stopConnecting() { + connected = false + } + + override fun waitForDisconnectionInSeconds(): Int = 0 + override fun getPumpStatus(reason: String) {} + override fun setNewBasalProfile(profile: Profile): PumpEnactResult = PumpEnactResult(injector) + override fun isThisProfileSet(profile: Profile): Boolean = isProfileSet + override fun lastDataTime(): Long = lastData + override val baseBasalRate: Double = baseBasal + override val reservoirLevel: Double = 0.0 + override val batteryLevel: Int = 0 + override fun deliverTreatment(detailedBolusInfo: DetailedBolusInfo): PumpEnactResult = PumpEnactResult(injector).success(true) + override fun stopBolusDelivering() {} + override fun setTempBasalAbsolute(absoluteRate: Double, durationInMinutes: Int, profile: Profile, enforceNew: Boolean, tbrType: PumpSync.TemporaryBasalType): PumpEnactResult = + PumpEnactResult(injector).success(true) + + override fun setTempBasalPercent(percent: Int, durationInMinutes: Int, profile: Profile, enforceNew: Boolean, tbrType: PumpSync.TemporaryBasalType): PumpEnactResult = + PumpEnactResult(injector).success(true) + + override fun setExtendedBolus(insulin: Double, durationInMinutes: Int): PumpEnactResult = PumpEnactResult(injector).success(true) + override fun cancelTempBasal(enforceNew: Boolean): PumpEnactResult = PumpEnactResult(injector).success(true) + override fun cancelExtendedBolus(): PumpEnactResult = PumpEnactResult(injector).success(true) + override fun getJSONStatus(profile: Profile, profileName: String, version: String): JSONObject = JSONObject() + override fun manufacturer(): ManufacturerType = ManufacturerType.AAPS + override fun model(): PumpType = PumpType.GENERIC_AAPS + override fun serialNumber(): String = "1" + override fun shortStatus(veryShort: Boolean): String = "" + override val isFakingTempsByExtendedBoluses: Boolean = false + override fun loadTDDs(): PumpEnactResult = PumpEnactResult(injector).success(true) + override fun canHandleDST(): Boolean = true + override fun timezoneOrDSTChanged(timeChangeType: TimeChangeType) {} +} \ No newline at end of file diff --git a/plugins/sync/src/test/java/info/nightscout/plugins/sync/dataBroadcaster/DataBroadcastPluginTest.kt b/plugins/sync/src/test/java/info/nightscout/plugins/sync/dataBroadcaster/DataBroadcastPluginTest.kt new file mode 100644 index 0000000000..60490b1ed4 --- /dev/null +++ b/plugins/sync/src/test/java/info/nightscout/plugins/sync/dataBroadcaster/DataBroadcastPluginTest.kt @@ -0,0 +1,159 @@ +package info.nightscout.plugins.sync.dataBroadcaster + +import dagger.android.AndroidInjector +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.BundleMock +import info.nightscout.androidaps.TestBaseWithProfile +import info.nightscout.androidaps.TestPumpPlugin +import info.nightscout.database.entities.TemporaryBasal +import info.nightscout.interfaces.GlucoseUnit +import info.nightscout.interfaces.aps.AutosensDataStore +import info.nightscout.interfaces.aps.Loop +import info.nightscout.interfaces.iob.CobInfo +import info.nightscout.interfaces.iob.GlucoseStatus +import info.nightscout.interfaces.iob.GlucoseStatusProvider +import info.nightscout.interfaces.iob.InMemoryGlucoseValue +import info.nightscout.interfaces.iob.IobTotal +import info.nightscout.interfaces.nsclient.ProcessedDeviceStatusData +import info.nightscout.interfaces.profile.DefaultValueHelper +import info.nightscout.interfaces.profile.ProfileFunction +import info.nightscout.interfaces.pump.PumpEnactResult +import info.nightscout.interfaces.receivers.ReceiverStatusStore +import info.nightscout.rx.events.EventOverviewBolusProgress +import org.json.JSONObject +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.mockito.ArgumentMatchers.anyLong +import org.mockito.Mock +import org.mockito.Mockito + +internal class DataBroadcastPluginTest : TestBaseWithProfile() { + + @Mock lateinit var defaultValueHelper: DefaultValueHelper + @Mock lateinit var loop: Loop + @Mock lateinit var receiverStatusStore: ReceiverStatusStore + @Mock lateinit var glucoseStatusProvider: GlucoseStatusProvider + @Mock lateinit var profileFunction: ProfileFunction + @Mock lateinit var autosensDataStore: AutosensDataStore + + private lateinit var sut: DataBroadcastPlugin + + private val injector = HasAndroidInjector { AndroidInjector { } } + private val testPumpPlugin = TestPumpPlugin(injector) + + @BeforeEach + fun setUp() { + sut = DataBroadcastPlugin( + injector, aapsLogger, rh, aapsSchedulers, context, dateUtil, fabricPrivacy, rxBus, iobCobCalculator, profileFunction, defaultValueHelper, processedDeviceStatusData, + loop, activePlugin, receiverStatusStore, config, glucoseStatusProvider + ) + Mockito.`when`(iobCobCalculator.ads).thenReturn(autosensDataStore) + Mockito.`when`(autosensDataStore.lastBg()).thenReturn(InMemoryGlucoseValue(1000, 100.0)) + Mockito.`when`(profileFunction.getProfile()).thenReturn(validProfile) + Mockito.`when`(profileFunction.getUnits()).thenReturn(GlucoseUnit.MGDL) + Mockito.`when`(profileFunction.getProfileName()).thenReturn("TestProfile") + Mockito.`when`(iobCobCalculator.calculateIobFromBolus()).thenReturn(IobTotal(System.currentTimeMillis())) + Mockito.`when`(iobCobCalculator.getCobInfo("broadcast")).thenReturn(CobInfo(1000, 100.0, 10.0)) + Mockito.`when`(iobCobCalculator.calculateIobFromTempBasalsIncludingConvertedExtended()).thenReturn(IobTotal(System.currentTimeMillis())) + Mockito.`when`(iobCobCalculator.getTempBasalIncludingConvertedExtended(anyLong())).thenReturn(TemporaryBasal(timestamp = 1000, duration = 60000, isAbsolute = true, rate = 1.0, type = TemporaryBasal.Type.NORMAL)) + Mockito.`when`(processedDeviceStatusData.uploaderStatus).thenReturn("100%") + Mockito.`when`(loop.lastRun).thenReturn(Loop.LastRun().also { + it.lastTBREnact = 1000 + it.tbrSetByPump = PumpEnactResult(injector).success(true).enacted(true) + } + ) + Mockito.`when`(activePlugin.activePump).thenReturn(testPumpPlugin) + Mockito.`when`(glucoseStatusProvider.glucoseStatusData).thenReturn(GlucoseStatus(100.0)) + Mockito.`when`(processedDeviceStatusData.openAPSData).thenReturn(ProcessedDeviceStatusData.OpenAPSData().also { + it.clockSuggested = 1000L + it.suggested = JSONObject() + it.clockEnacted = 1000L + it.enacted = JSONObject() + }) + } + + @Test + fun prepareDataTestAPS() { + Mockito.`when`(config.APS).thenReturn(true) + val event = EventOverviewBolusProgress.also { + it.status = "Some status" + it.percent = 100 + } + val bundle = BundleMock.mock() + sut.prepareData(event, bundle) + Assertions.assertTrue(bundle.containsKey("progressPercent")) + Assertions.assertTrue(bundle.containsKey("progressStatus")) + Assertions.assertTrue(bundle.containsKey("glucoseMgdl")) + Assertions.assertTrue(bundle.containsKey("glucoseTimeStamp")) + Assertions.assertTrue(bundle.containsKey("units")) + Assertions.assertTrue(bundle.containsKey("slopeArrow")) + Assertions.assertTrue(bundle.containsKey("deltaMgdl")) + Assertions.assertTrue(bundle.containsKey("avgDeltaMgdl")) + Assertions.assertTrue(bundle.containsKey("high")) + Assertions.assertTrue(bundle.containsKey("low")) + Assertions.assertTrue(bundle.containsKey("bolusIob")) + Assertions.assertTrue(bundle.containsKey("basalIob")) + Assertions.assertTrue(bundle.containsKey("iob")) + Assertions.assertTrue(bundle.containsKey("cob")) + Assertions.assertTrue(bundle.containsKey("futureCarbs")) + Assertions.assertTrue(bundle.containsKey("phoneBattery")) + Assertions.assertTrue(bundle.containsKey("rigBattery")) + Assertions.assertTrue(bundle.containsKey("suggestedTimeStamp")) + Assertions.assertTrue(bundle.containsKey("suggested")) + Assertions.assertTrue(bundle.containsKey("enactedTimeStamp")) + Assertions.assertTrue(bundle.containsKey("enacted")) + Assertions.assertTrue(bundle.containsKey("basalTimeStamp")) + Assertions.assertTrue(bundle.containsKey("baseBasal")) + Assertions.assertTrue(bundle.containsKey("profile")) + Assertions.assertTrue(bundle.containsKey("tempBasalStart")) + Assertions.assertTrue(bundle.containsKey("tempBasalDurationInMinutes")) + Assertions.assertTrue(bundle.containsKey("tempBasalString")) + Assertions.assertTrue(bundle.containsKey("pumpTimeStamp")) + Assertions.assertTrue(bundle.containsKey("pumpBattery")) + Assertions.assertTrue(bundle.containsKey("pumpReservoir")) + Assertions.assertTrue(bundle.containsKey("pumpStatus")) + } + + @Test + fun prepareDataTestAAPSClient() { + Mockito.`when`(config.APS).thenReturn(false) + val event = EventOverviewBolusProgress.also { + it.status = "Some status" + it.percent = 100 + } + val bundle = BundleMock.mock() + sut.prepareData(event, bundle) + Assertions.assertTrue(bundle.containsKey("progressPercent")) + Assertions.assertTrue(bundle.containsKey("progressStatus")) + Assertions.assertTrue(bundle.containsKey("glucoseMgdl")) + Assertions.assertTrue(bundle.containsKey("glucoseTimeStamp")) + Assertions.assertTrue(bundle.containsKey("units")) + Assertions.assertTrue(bundle.containsKey("slopeArrow")) + Assertions.assertTrue(bundle.containsKey("deltaMgdl")) + Assertions.assertTrue(bundle.containsKey("avgDeltaMgdl")) + Assertions.assertTrue(bundle.containsKey("high")) + Assertions.assertTrue(bundle.containsKey("low")) + Assertions.assertTrue(bundle.containsKey("bolusIob")) + Assertions.assertTrue(bundle.containsKey("basalIob")) + Assertions.assertTrue(bundle.containsKey("iob")) + Assertions.assertTrue(bundle.containsKey("cob")) + Assertions.assertTrue(bundle.containsKey("futureCarbs")) + Assertions.assertTrue(bundle.containsKey("phoneBattery")) + Assertions.assertTrue(bundle.containsKey("rigBattery")) + Assertions.assertTrue(bundle.containsKey("suggestedTimeStamp")) + Assertions.assertTrue(bundle.containsKey("suggested")) + Assertions.assertTrue(bundle.containsKey("enactedTimeStamp")) + Assertions.assertTrue(bundle.containsKey("enacted")) + Assertions.assertTrue(bundle.containsKey("basalTimeStamp")) + Assertions.assertTrue(bundle.containsKey("baseBasal")) + Assertions.assertTrue(bundle.containsKey("profile")) + Assertions.assertTrue(bundle.containsKey("tempBasalStart")) + Assertions.assertTrue(bundle.containsKey("tempBasalDurationInMinutes")) + Assertions.assertTrue(bundle.containsKey("tempBasalString")) + Assertions.assertTrue(bundle.containsKey("pumpTimeStamp")) + Assertions.assertTrue(bundle.containsKey("pumpBattery")) + Assertions.assertTrue(bundle.containsKey("pumpReservoir")) + Assertions.assertTrue(bundle.containsKey("pumpStatus")) + } +} \ No newline at end of file