move more plugins to Synchronization group

This commit is contained in:
Milos Kozak 2023-01-17 13:58:07 +01:00
parent 6fc3b35c4c
commit c71fc275a5
18 changed files with 382 additions and 141 deletions

View file

@ -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

View file

@ -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

View file

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

View file

@ -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

View file

@ -112,21 +112,11 @@
<string name="sms_wrong_tbr_duration">TBR duration must be a multiple of %1$d minutes and greater than 0.</string>
<string name="a11y_otp_qr_code">QR Code for setup one time password</string>
<!-- xDrip status line -->
<string name="key_xdrip_status_detailed_iob" translatable="false">xdripstatus_detailediob</string>
<string name="key_xdrip_status_show_bgi" translatable="false">xdripstatus_showbgi</string>
<string name="key_xdrip_status_settings" translatable="false">xdripstatus_settings</string>
<!-- StatusLine -->
<string name="xdrip_status">xDrip+ Statusline (watch)</string>
<string name="xdrip_status_shortname">xds</string>
<string name="description_xdrip_status_line">Show information about your loop on your xDrip+ watchface.</string>
<string name="xdrip_status_detailed_iob_title">Show detailed IOB</string>
<string name="xdrip_status_detailed_iob_summary">Break down IOB into bolus and basal IOB on the watchface</string>
<string name="disabled_loop">Loop Disabled</string>
<string name="xdrip_status_show_bgi_title">Show BGI</string>
<string name="xdrip_status_show_bgi_summary">Add BGI to status line</string>
<string name="xdrip_status_settings">xDrip+ Status (watch)</string>
<!-- Food-->
<string name="food_short">Food</string>
@ -331,8 +321,6 @@
<string name="largedisplay_description">Large display</string>
<string name="skin">Skin</string>
<!-- DataBroadcast-->
<string name="data_broadcaster" translatable="false">Data Broadcaster</string>
<string name="cannula_usage">usage:</string>
<!-- Iob-->

View file

@ -1,24 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<PreferenceCategory
android:key="@string/key_xdrip_status_settings"
android:title="@string/xdrip_status_settings"
app:initialExpandedChildrenCount="0">
<SwitchPreference
android:defaultValue="true"
android:key="@string/key_xdrip_status_detailed_iob"
android:summary="@string/xdrip_status_detailed_iob_summary"
android:title="@string/xdrip_status_detailed_iob_title" />
<SwitchPreference
android:defaultValue="false"
android:key="@string/key_xdrip_status_show_bgi"
android:summary="@string/xdrip_status_show_bgi_summary"
android:title="@string/xdrip_status_show_bgi_title" />
</PreferenceCategory>
</androidx.preference.PreferenceScreen>

View file

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

View file

@ -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
}
}

View file

@ -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
}
}

View file

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

View file

@ -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

View file

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

View file

@ -147,4 +147,25 @@
<string name="read_only">Read only</string>
<string name="working">Working</string>
<!-- xDrip status line -->
<string name="key_xdrip_status_detailed_iob" translatable="false">xdripstatus_detailediob</string>
<string name="key_xdrip_status_show_bgi" translatable="false">xdripstatus_showbgi</string>
<string name="key_xdrip_status_settings" translatable="false">xdripstatus_settings</string>
<string name="key_xdrip_send_status">xdrip_send_status</string>
<!-- Xdrip StatusLine -->
<string name="xdrip">xDrip+</string>
<string name="xdrip_shortname">XD</string>
<string name="description_xdrip">Send data to xDrip+</string>
<string name="xdrip_status_detailed_iob_title">Show detailed IOB</string>
<string name="xdrip_status_detailed_iob_summary">Break down IOB into bolus and basal IOB on the watchface</string>
<string name="xdrip_status_show_bgi_title">Show BGI</string>
<string name="xdrip_status_show_bgi_summary">Add BGI to status line</string>
<string name="xdrip_status_settings">xDrip+ Status (watch)</string>
<string name="disabled_loop">Loop Disabled</string>
<string name="xdrip_send_status_title">Send status line to xDrip+</string>
<!-- DataBroadcast-->
<string name="data_broadcaster" translatable="false">Data Broadcaster</string>
</resources>

View file

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<PreferenceCategory
android:key="xdrip_category"
android:title="@string/xdrip"
app:initialExpandedChildrenCount="0">
<SwitchPreference
android:defaultValue="false"
android:key="@string/key_xdrip_send_status"
android:title="@string/xdrip_send_status_title" />
<PereferenceScreen
android:key="@string/key_xdrip_status_settings"
android:dependency="@string/key_xdrip_send_status"
android:title="@string/xdrip_status_settings"
app:initialExpandedChildrenCount="0">
<SwitchPreference
android:defaultValue="true"
android:key="@string/key_xdrip_status_detailed_iob"
android:summary="@string/xdrip_status_detailed_iob_summary"
android:title="@string/xdrip_status_detailed_iob_title" />
<SwitchPreference
android:defaultValue="false"
android:key="@string/key_xdrip_status_show_bgi"
android:summary="@string/xdrip_status_show_bgi_summary"
android:title="@string/xdrip_status_show_bgi_title" />
</PereferenceScreen>
</PreferenceCategory>
</androidx.preference.PreferenceScreen>

View file

@ -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<String, Object> hm = new HashMap<>();
for (String key : dataMap.keySet()) {
hm.put(key, dataMap.get(key));
}
return mock(hm);
}
public static Bundle mock(final HashMap<String, Object> map) {
Answer unsupported = invocation -> {
@ -180,5 +170,4 @@ public final class BundleMock {
return bundle;
}
*/
}

View file

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

View file

@ -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) {}
}

View file

@ -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"))
}
}