Merge pull request #3092 from Jackenmen/handle_sensor_start_time_in_xdrip_broadcast
Add support for SensorStartedAt extra in xDrip+ BG source
This commit is contained in:
commit
c972b7ed02
|
@ -25,6 +25,7 @@ interface Intents {
|
||||||
const val EXTRA_BG_SLOPE = "com.eveningoutpost.dexdrip.Extras.BgSlope"
|
const val EXTRA_BG_SLOPE = "com.eveningoutpost.dexdrip.Extras.BgSlope"
|
||||||
const val EXTRA_BG_SLOPE_NAME = "com.eveningoutpost.dexdrip.Extras.BgSlopeName"
|
const val EXTRA_BG_SLOPE_NAME = "com.eveningoutpost.dexdrip.Extras.BgSlopeName"
|
||||||
const val EXTRA_SENSOR_BATTERY = "com.eveningoutpost.dexdrip.Extras.SensorBattery"
|
const val EXTRA_SENSOR_BATTERY = "com.eveningoutpost.dexdrip.Extras.SensorBattery"
|
||||||
|
const val EXTRA_SENSOR_STARTED_AT = "com.eveningoutpost.dexdrip.Extras.SensorStartedAt"
|
||||||
const val EXTRA_TIMESTAMP = "com.eveningoutpost.dexdrip.Extras.Time"
|
const val EXTRA_TIMESTAMP = "com.eveningoutpost.dexdrip.Extras.Time"
|
||||||
const val EXTRA_RAW = "com.eveningoutpost.dexdrip.Extras.Raw"
|
const val EXTRA_RAW = "com.eveningoutpost.dexdrip.Extras.Raw"
|
||||||
const val XDRIP_DATA_SOURCE_DESCRIPTION = "com.eveningoutpost.dexdrip.Extras.SourceDesc"
|
const val XDRIP_DATA_SOURCE_DESCRIPTION = "com.eveningoutpost.dexdrip.Extras.SourceDesc"
|
||||||
|
|
|
@ -22,6 +22,8 @@ dependencies {
|
||||||
implementation(project(":core:ui"))
|
implementation(project(":core:ui"))
|
||||||
implementation(project(":core:utils"))
|
implementation(project(":core:utils"))
|
||||||
|
|
||||||
|
testImplementation(Libs.AndroidX.Work.testing)
|
||||||
|
|
||||||
testImplementation(project(":shared:tests"))
|
testImplementation(project(":shared:tests"))
|
||||||
|
|
||||||
kapt(Libs.Dagger.compiler)
|
kapt(Libs.Dagger.compiler)
|
||||||
|
|
|
@ -1,20 +1,28 @@
|
||||||
package app.aaps.plugins.source
|
package app.aaps.plugins.source
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.os.Bundle
|
||||||
import androidx.work.WorkerParameters
|
import androidx.work.WorkerParameters
|
||||||
import androidx.work.workDataOf
|
import androidx.work.workDataOf
|
||||||
import app.aaps.core.interfaces.logging.AAPSLogger
|
import app.aaps.core.interfaces.logging.AAPSLogger
|
||||||
import app.aaps.core.interfaces.logging.LTag
|
import app.aaps.core.interfaces.logging.LTag
|
||||||
|
import app.aaps.core.interfaces.logging.UserEntryLogger
|
||||||
import app.aaps.core.interfaces.plugin.PluginBase
|
import app.aaps.core.interfaces.plugin.PluginBase
|
||||||
import app.aaps.core.interfaces.plugin.PluginDescription
|
import app.aaps.core.interfaces.plugin.PluginDescription
|
||||||
import app.aaps.core.interfaces.plugin.PluginType
|
import app.aaps.core.interfaces.plugin.PluginType
|
||||||
import app.aaps.core.interfaces.receivers.Intents
|
import app.aaps.core.interfaces.receivers.Intents
|
||||||
import app.aaps.core.interfaces.resources.ResourceHelper
|
import app.aaps.core.interfaces.resources.ResourceHelper
|
||||||
|
import app.aaps.core.interfaces.sharedPreferences.SP
|
||||||
import app.aaps.core.interfaces.source.BgSource
|
import app.aaps.core.interfaces.source.BgSource
|
||||||
import app.aaps.core.interfaces.source.XDripSource
|
import app.aaps.core.interfaces.source.XDripSource
|
||||||
|
import app.aaps.core.interfaces.utils.DateUtil
|
||||||
|
import app.aaps.core.interfaces.utils.T
|
||||||
import app.aaps.core.main.utils.worker.LoggingWorker
|
import app.aaps.core.main.utils.worker.LoggingWorker
|
||||||
import app.aaps.core.utils.receivers.DataWorkerStorage
|
import app.aaps.core.utils.receivers.DataWorkerStorage
|
||||||
import app.aaps.database.entities.GlucoseValue
|
import app.aaps.database.entities.GlucoseValue
|
||||||
|
import app.aaps.database.entities.UserEntry.Action
|
||||||
|
import app.aaps.database.entities.UserEntry.Sources
|
||||||
|
import app.aaps.database.entities.ValueWithUnit
|
||||||
import app.aaps.database.impl.AppRepository
|
import app.aaps.database.impl.AppRepository
|
||||||
import app.aaps.database.impl.transactions.CgmSourceTransaction
|
import app.aaps.database.impl.transactions.CgmSourceTransaction
|
||||||
import app.aaps.database.transactions.TransactionGlucoseValue
|
import app.aaps.database.transactions.TransactionGlucoseValue
|
||||||
|
@ -22,6 +30,7 @@ import dagger.android.HasAndroidInjector
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
import kotlin.math.abs
|
||||||
import kotlin.math.round
|
import kotlin.math.round
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
|
@ -34,7 +43,7 @@ class XdripSourcePlugin @Inject constructor(
|
||||||
.mainType(PluginType.BGSOURCE)
|
.mainType(PluginType.BGSOURCE)
|
||||||
.fragmentClass(BGSourceFragment::class.java.name)
|
.fragmentClass(BGSourceFragment::class.java.name)
|
||||||
.pluginIcon((app.aaps.core.main.R.drawable.ic_blooddrop_48))
|
.pluginIcon((app.aaps.core.main.R.drawable.ic_blooddrop_48))
|
||||||
.preferencesId(R.xml.pref_bgsource)
|
.preferencesId(R.xml.pref_dexcom)
|
||||||
.pluginName(R.string.source_xdrip)
|
.pluginName(R.string.source_xdrip)
|
||||||
.description(R.string.description_source_xdrip),
|
.description(R.string.description_source_xdrip),
|
||||||
aapsLogger, rh, injector
|
aapsLogger, rh, injector
|
||||||
|
@ -63,8 +72,25 @@ class XdripSourcePlugin @Inject constructor(
|
||||||
) : LoggingWorker(context, params, Dispatchers.IO) {
|
) : LoggingWorker(context, params, Dispatchers.IO) {
|
||||||
|
|
||||||
@Inject lateinit var xdripSourcePlugin: XdripSourcePlugin
|
@Inject lateinit var xdripSourcePlugin: XdripSourcePlugin
|
||||||
|
@Inject lateinit var sp: SP
|
||||||
|
@Inject lateinit var dateUtil: DateUtil
|
||||||
@Inject lateinit var repository: AppRepository
|
@Inject lateinit var repository: AppRepository
|
||||||
@Inject lateinit var dataWorkerStorage: DataWorkerStorage
|
@Inject lateinit var dataWorkerStorage: DataWorkerStorage
|
||||||
|
@Inject lateinit var uel: UserEntryLogger
|
||||||
|
|
||||||
|
fun getSensorStartTime(bundle: Bundle): Long? {
|
||||||
|
val now = dateUtil.now()
|
||||||
|
var sensorStartTime: Long? = if (sp.getBoolean(R.string.key_dexcom_log_ns_sensor_change, false)) {
|
||||||
|
bundle.getLong(Intents.EXTRA_SENSOR_STARTED_AT, 0)
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
// check start time validity
|
||||||
|
sensorStartTime?.let {
|
||||||
|
if (abs(it - now) > T.months(1).msecs() || it > now) sensorStartTime = null
|
||||||
|
}
|
||||||
|
return sensorStartTime
|
||||||
|
}
|
||||||
|
|
||||||
override suspend fun doWorkAndLog(): Result {
|
override suspend fun doWorkAndLog(): Result {
|
||||||
var ret = Result.success()
|
var ret = Result.success()
|
||||||
|
@ -86,17 +112,27 @@ class XdripSourcePlugin @Inject constructor(
|
||||||
?: ""
|
?: ""
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null))
|
val sensorStartTime = getSensorStartTime(bundle)
|
||||||
|
repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), sensorStartTime))
|
||||||
.doOnError {
|
.doOnError {
|
||||||
aapsLogger.error(LTag.DATABASE, "Error while saving values from Xdrip", it)
|
aapsLogger.error(LTag.DATABASE, "Error while saving values from Xdrip", it)
|
||||||
ret = Result.failure(workDataOf("Error" to it.toString()))
|
ret = Result.failure(workDataOf("Error" to it.toString()))
|
||||||
}
|
}
|
||||||
.blockingGet()
|
.blockingGet()
|
||||||
.also { savedValues ->
|
.also { result ->
|
||||||
savedValues.all().forEach {
|
result.all().forEach {
|
||||||
xdripSourcePlugin.detectSource(it)
|
xdripSourcePlugin.detectSource(it)
|
||||||
aapsLogger.debug(LTag.DATABASE, "Inserted bg $it")
|
aapsLogger.debug(LTag.DATABASE, "Inserted bg $it")
|
||||||
}
|
}
|
||||||
|
result.sensorInsertionsInserted.forEach {
|
||||||
|
uel.log(
|
||||||
|
Action.CAREPORTAL,
|
||||||
|
Sources.Xdrip,
|
||||||
|
ValueWithUnit.Timestamp(it.timestamp),
|
||||||
|
ValueWithUnit.TherapyEventType(it.type)
|
||||||
|
)
|
||||||
|
aapsLogger.debug(LTag.DATABASE, "Inserted sensor insertion $it")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
xdripSourcePlugin.sensorBatteryLevel = bundle.getInt(Intents.EXTRA_SENSOR_BATTERY, -1)
|
xdripSourcePlugin.sensorBatteryLevel = bundle.getInt(Intents.EXTRA_SENSOR_BATTERY, -1)
|
||||||
return ret
|
return ret
|
||||||
|
|
|
@ -1,25 +1,115 @@
|
||||||
package app.aaps.plugins.source
|
package app.aaps.plugins.source
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.work.WorkerFactory
|
||||||
|
import androidx.work.WorkerParameters
|
||||||
|
import androidx.work.testing.TestListenableWorkerBuilder
|
||||||
|
import app.aaps.core.interfaces.receivers.Intents
|
||||||
import app.aaps.core.interfaces.resources.ResourceHelper
|
import app.aaps.core.interfaces.resources.ResourceHelper
|
||||||
|
import app.aaps.core.interfaces.utils.DateUtil
|
||||||
|
import app.aaps.core.interfaces.utils.T
|
||||||
|
import app.aaps.core.interfaces.sharedPreferences.SP
|
||||||
|
import app.aaps.core.utils.receivers.DataWorkerStorage
|
||||||
|
import app.aaps.shared.impl.utils.DateUtilImpl
|
||||||
|
import app.aaps.shared.tests.BundleMock
|
||||||
import app.aaps.shared.tests.TestBase
|
import app.aaps.shared.tests.TestBase
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
import dagger.android.AndroidInjector
|
import dagger.android.AndroidInjector
|
||||||
|
import dagger.android.HasAndroidInjector
|
||||||
import org.junit.jupiter.api.BeforeEach
|
import org.junit.jupiter.api.BeforeEach
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import org.mockito.Mock
|
import org.mockito.Mock
|
||||||
|
import org.mockito.Mockito.`when`
|
||||||
|
|
||||||
class XdripSourcePluginTest : TestBase() {
|
class XdripSourcePluginTest : TestBase() {
|
||||||
|
|
||||||
private lateinit var xdripSourcePlugin: XdripSourcePlugin
|
abstract class ContextWithInjector : Context(), HasAndroidInjector
|
||||||
|
|
||||||
|
private lateinit var xdripSourcePlugin: XdripSourcePlugin
|
||||||
|
private lateinit var dateUtil: DateUtil
|
||||||
|
private lateinit var dataWorkerStorage: DataWorkerStorage
|
||||||
|
|
||||||
|
private val injector = HasAndroidInjector {
|
||||||
|
AndroidInjector {
|
||||||
|
if (it is XdripSourcePlugin.XdripSourceWorker) {
|
||||||
|
it.dataWorkerStorage = dataWorkerStorage
|
||||||
|
it.dateUtil = dateUtil
|
||||||
|
it.sp = sp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Mock lateinit var sp: SP
|
||||||
@Mock lateinit var rh: ResourceHelper
|
@Mock lateinit var rh: ResourceHelper
|
||||||
|
@Mock lateinit var context: ContextWithInjector
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
fun setup() {
|
fun setup() {
|
||||||
xdripSourcePlugin = XdripSourcePlugin({ AndroidInjector { } }, rh, aapsLogger)
|
`when`(context.applicationContext).thenReturn(context)
|
||||||
|
`when`(context.androidInjector()).thenReturn(injector.androidInjector())
|
||||||
|
xdripSourcePlugin = XdripSourcePlugin(injector, rh, aapsLogger)
|
||||||
|
dateUtil = DateUtilImpl(context)
|
||||||
|
dataWorkerStorage = DataWorkerStorage(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun prepareWorker(
|
||||||
|
sensorStartTime: Long? = dateUtil.now(),
|
||||||
|
logNsSensorChange: Boolean = true,
|
||||||
|
): Pair<Bundle, XdripSourcePlugin.XdripSourceWorker> {
|
||||||
|
val bundle = BundleMock.mock()
|
||||||
|
sensorStartTime?.let { bundle.putLong(Intents.EXTRA_SENSOR_STARTED_AT, sensorStartTime) }
|
||||||
|
`when`(sp.getBoolean(R.string.key_dexcom_log_ns_sensor_change, false)).thenReturn(logNsSensorChange)
|
||||||
|
|
||||||
|
lateinit var worker: XdripSourcePlugin.XdripSourceWorker
|
||||||
|
TestListenableWorkerBuilder<XdripSourcePlugin.XdripSourceWorker>(context)
|
||||||
|
.setWorkerFactory(object: WorkerFactory() {
|
||||||
|
override fun createWorker(appContext: Context, workerClassName: String, workerParameters: WorkerParameters): XdripSourcePlugin.XdripSourceWorker {
|
||||||
|
worker = XdripSourcePlugin.XdripSourceWorker(context, workerParameters)
|
||||||
|
return worker
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.setInputData(dataWorkerStorage.storeInputData(bundle, Intents.ACTION_NEW_BG_ESTIMATE)).build()
|
||||||
|
|
||||||
|
return Pair(bundle, worker)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test fun advancedFilteringSupported() {
|
@Test fun advancedFilteringSupported() {
|
||||||
assertThat(xdripSourcePlugin.advancedFilteringSupported()).isFalse()
|
assertThat(xdripSourcePlugin.advancedFilteringSupported()).isFalse()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test fun getSensorStartTime_withoutValue_returnsNull() {
|
||||||
|
val (bundle, worker) = prepareWorker(sensorStartTime = null)
|
||||||
|
|
||||||
|
val result = worker.getSensorStartTime(bundle)
|
||||||
|
|
||||||
|
assertThat(result).isNull()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test fun getSensorStartTime_withSettingDisabled_returnsNull() {
|
||||||
|
val sensorStartTime = dateUtil.now()
|
||||||
|
val (bundle, worker) = prepareWorker(sensorStartTime = sensorStartTime, logNsSensorChange = false)
|
||||||
|
|
||||||
|
val result = worker.getSensorStartTime(bundle)
|
||||||
|
|
||||||
|
assertThat(result).isNull()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test fun getSensorStartTime_withRecentValue_returnsStartTime() {
|
||||||
|
val sensorStartTime = dateUtil.now()
|
||||||
|
val (bundle, worker) = prepareWorker(sensorStartTime = sensorStartTime)
|
||||||
|
|
||||||
|
val result = worker.getSensorStartTime(bundle)
|
||||||
|
|
||||||
|
assertThat(result).isEqualTo(sensorStartTime)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test fun getSensorStartTime_withOldValue_returnsNull() {
|
||||||
|
val sensorStartTime = dateUtil.now() - T.months(2).msecs()
|
||||||
|
val (bundle, worker) = prepareWorker(sensorStartTime = sensorStartTime)
|
||||||
|
|
||||||
|
val result = worker.getSensorStartTime(bundle)
|
||||||
|
|
||||||
|
assertThat(result).isNull()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue