improve BG sync
This commit is contained in:
parent
887819edf4
commit
145765e611
12 changed files with 68 additions and 29 deletions
|
@ -18,12 +18,15 @@ import info.nightscout.androidaps.events.EventNewBG
|
||||||
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface
|
import info.nightscout.androidaps.interfaces.DatabaseHelperInterface
|
||||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
||||||
import info.nightscout.androidaps.utils.*
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
|
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||||
|
import info.nightscout.androidaps.utils.T
|
||||||
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
||||||
import info.nightscout.androidaps.utils.extensions.directionToIcon
|
import info.nightscout.androidaps.utils.extensions.directionToIcon
|
||||||
import info.nightscout.androidaps.utils.extensions.toVisibility
|
import info.nightscout.androidaps.utils.extensions.toVisibility
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||||
|
import info.nightscout.androidaps.utils.valueToUnitsString
|
||||||
import io.reactivex.disposables.CompositeDisposable
|
import io.reactivex.disposables.CompositeDisposable
|
||||||
import io.reactivex.rxkotlin.plusAssign
|
import io.reactivex.rxkotlin.plusAssign
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
@ -89,8 +92,8 @@ class BGSourceFragment : DaggerFragment() {
|
||||||
@Synchronized
|
@Synchronized
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
_binding = null
|
|
||||||
binding.recyclerview.adapter = null // avoid leaks
|
binding.recyclerview.adapter = null // avoid leaks
|
||||||
|
_binding = null
|
||||||
}
|
}
|
||||||
|
|
||||||
inner class RecyclerViewAdapter internal constructor(private var glucoseValues: List<GlucoseValue>) : RecyclerView.Adapter<RecyclerViewAdapter.GlucoseValuesViewHolder>() {
|
inner class RecyclerViewAdapter internal constructor(private var glucoseValues: List<GlucoseValue>) : RecyclerView.Adapter<RecyclerViewAdapter.GlucoseValuesViewHolder>() {
|
||||||
|
|
|
@ -132,14 +132,19 @@ class DexcomPlugin @Inject constructor(
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
dexcomPlugin.disposable += repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, calibrations, sensorStartTime)).subscribe({ savedValues ->
|
dexcomPlugin.disposable += repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, calibrations, sensorStartTime)).subscribe({ result ->
|
||||||
savedValues.forEach {
|
result.inserted.forEach {
|
||||||
broadcastToXDrip(it)
|
broadcastToXDrip(it)
|
||||||
if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false)) {
|
if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false)) {
|
||||||
if (it.interfaceIDs.nightscoutId != null)
|
|
||||||
nsUpload.updateBg(it, sourceSensor.text)
|
|
||||||
else
|
|
||||||
nsUpload.uploadBg(it, sourceSensor.text)
|
nsUpload.uploadBg(it, sourceSensor.text)
|
||||||
|
//aapsLogger.debug("XXXXX: dbAdd $it")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result.updated.forEach {
|
||||||
|
broadcastToXDrip(it)
|
||||||
|
if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false)) {
|
||||||
|
nsUpload.updateBg(it, sourceSensor.text)
|
||||||
|
//aapsLogger.debug("XXXXX: dpUpdate $it")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
|
|
|
@ -118,7 +118,7 @@ class EversensePlugin @Inject constructor(
|
||||||
sourceSensor = GlucoseValue.SourceSensor.EVERSENSE
|
sourceSensor = GlucoseValue.SourceSensor.EVERSENSE
|
||||||
)
|
)
|
||||||
eversensePlugin.disposable += repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null)).subscribe({ savedValues ->
|
eversensePlugin.disposable += repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null)).subscribe({ savedValues ->
|
||||||
savedValues.forEach {
|
savedValues.inserted.forEach {
|
||||||
broadcastToXDrip(it)
|
broadcastToXDrip(it)
|
||||||
if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false))
|
if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false))
|
||||||
nsUpload.uploadBg(it, GlucoseValue.SourceSensor.EVERSENSE.text)
|
nsUpload.uploadBg(it, GlucoseValue.SourceSensor.EVERSENSE.text)
|
||||||
|
|
|
@ -76,7 +76,7 @@ class GlimpPlugin @Inject constructor(
|
||||||
sourceSensor = GlucoseValue.SourceSensor.GLIMP
|
sourceSensor = GlucoseValue.SourceSensor.GLIMP
|
||||||
)
|
)
|
||||||
glimpPlugin.disposable += repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null)).subscribe({ savedValues ->
|
glimpPlugin.disposable += repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null)).subscribe({ savedValues ->
|
||||||
savedValues.forEach {
|
savedValues.inserted.forEach {
|
||||||
broadcastToXDrip(it)
|
broadcastToXDrip(it)
|
||||||
if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false))
|
if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false))
|
||||||
nsUpload.uploadBg(it, GlucoseValue.SourceSensor.GLIMP.text)
|
nsUpload.uploadBg(it, GlucoseValue.SourceSensor.GLIMP.text)
|
||||||
|
|
|
@ -94,7 +94,7 @@ class MM640gPlugin @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mM640gPlugin.disposable += repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null)).subscribe({ savedValues ->
|
mM640gPlugin.disposable += repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null)).subscribe({ savedValues ->
|
||||||
savedValues.forEach {
|
savedValues.all().forEach {
|
||||||
broadcastToXDrip(it)
|
broadcastToXDrip(it)
|
||||||
if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false))
|
if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false))
|
||||||
nsUpload.uploadBg(it, GlucoseValue.SourceSensor.MM_600_SERIES.text)
|
nsUpload.uploadBg(it, GlucoseValue.SourceSensor.MM_600_SERIES.text)
|
||||||
|
|
|
@ -127,13 +127,19 @@ class NSClientSourcePlugin @Inject constructor(
|
||||||
for (i in 0 until jsonArray.length())
|
for (i in 0 until jsonArray.length())
|
||||||
glucoseValues += toGv(jsonArray.getJSONObject(i))
|
glucoseValues += toGv(jsonArray.getJSONObject(i))
|
||||||
}
|
}
|
||||||
nsClientSourcePlugin.disposable += repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null)).subscribe({ savedValues ->
|
nsClientSourcePlugin.disposable += repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null, !nsClientSourcePlugin.isEnabled())).subscribe({ result ->
|
||||||
savedValues.forEach {
|
result.updated.forEach {
|
||||||
|
//aapsLogger.debug("XXXXX: Updated $it")
|
||||||
|
broadcastToXDrip(it)
|
||||||
|
nsClientSourcePlugin.detectSource(it)
|
||||||
|
}
|
||||||
|
result.inserted.forEach {
|
||||||
|
//aapsLogger.debug("XXXXX: Inserted $it")
|
||||||
broadcastToXDrip(it)
|
broadcastToXDrip(it)
|
||||||
nsClientSourcePlugin.detectSource(it)
|
nsClientSourcePlugin.detectSource(it)
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
aapsLogger.error(LTag.BGSOURCE, "Error while saving values from Eversense App", it)
|
aapsLogger.error(LTag.BGSOURCE, "Error while saving values from NSClient App", it)
|
||||||
})
|
})
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
aapsLogger.error("Unhandled exception", e)
|
aapsLogger.error("Unhandled exception", e)
|
||||||
|
|
|
@ -87,7 +87,7 @@ class PoctechPlugin @Inject constructor(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
poctechPlugin.disposable += repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null)).subscribe({ savedValues ->
|
poctechPlugin.disposable += repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null)).subscribe({ savedValues ->
|
||||||
savedValues.forEach {
|
savedValues.inserted.forEach {
|
||||||
broadcastToXDrip(it)
|
broadcastToXDrip(it)
|
||||||
if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false))
|
if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false))
|
||||||
nsUpload.uploadBg(it, GlucoseValue.SourceSensor.POCTECH_NATIVE.text)
|
nsUpload.uploadBg(it, GlucoseValue.SourceSensor.POCTECH_NATIVE.text)
|
||||||
|
|
|
@ -108,7 +108,7 @@ class RandomBgPlugin @Inject constructor(
|
||||||
sourceSensor = GlucoseValue.SourceSensor.RANDOM
|
sourceSensor = GlucoseValue.SourceSensor.RANDOM
|
||||||
)
|
)
|
||||||
disposable += repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null)).subscribe({ savedValues ->
|
disposable += repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null)).subscribe({ savedValues ->
|
||||||
savedValues.forEach {
|
savedValues.inserted.forEach {
|
||||||
xDripBroadcast(it)
|
xDripBroadcast(it)
|
||||||
if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false))
|
if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false))
|
||||||
nsUpload.uploadBg(it, GlucoseValue.SourceSensor.RANDOM.text)
|
nsUpload.uploadBg(it, GlucoseValue.SourceSensor.RANDOM.text)
|
||||||
|
|
|
@ -76,7 +76,7 @@ class TomatoPlugin @Inject constructor(
|
||||||
sourceSensor = GlucoseValue.SourceSensor.LIBRE_1_TOMATO
|
sourceSensor = GlucoseValue.SourceSensor.LIBRE_1_TOMATO
|
||||||
)
|
)
|
||||||
tomatoPlugin.disposable += repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null)).subscribe({ savedValues ->
|
tomatoPlugin.disposable += repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null)).subscribe({ savedValues ->
|
||||||
savedValues.forEach {
|
savedValues.inserted.forEach {
|
||||||
broadcastToXDrip(it)
|
broadcastToXDrip(it)
|
||||||
if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false))
|
if (sp.getBoolean(R.string.key_dexcomg5_nsupload, false))
|
||||||
nsUpload.uploadBg(it, GlucoseValue.SourceSensor.LIBRE_1_TOMATO.text)
|
nsUpload.uploadBg(it, GlucoseValue.SourceSensor.LIBRE_1_TOMATO.text)
|
||||||
|
|
|
@ -86,7 +86,7 @@ class XdripPlugin @Inject constructor(
|
||||||
?: "")
|
?: "")
|
||||||
)
|
)
|
||||||
xdripPlugin.disposable += repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null)).subscribe({ savedValues ->
|
xdripPlugin.disposable += repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null)).subscribe({ savedValues ->
|
||||||
savedValues.forEach {
|
savedValues.all().forEach {
|
||||||
xdripPlugin.detectSource(it)
|
xdripPlugin.detectSource(it)
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
|
|
|
@ -40,8 +40,7 @@ data class GlucoseValue(
|
||||||
trendArrow == other.trendArrow &&
|
trendArrow == other.trendArrow &&
|
||||||
noise == other.noise &&
|
noise == other.noise &&
|
||||||
sourceSensor == other.sourceSensor &&
|
sourceSensor == other.sourceSensor &&
|
||||||
isValid == other.isValid &&
|
isValid == other.isValid
|
||||||
interfaceIDs.nightscoutId == other.interfaceIDs.nightscoutId
|
|
||||||
|
|
||||||
fun isRecordDeleted(other: GlucoseValue): Boolean =
|
fun isRecordDeleted(other: GlucoseValue): Boolean =
|
||||||
isValid && !other.isValid
|
isValid && !other.isValid
|
||||||
|
|
|
@ -9,11 +9,14 @@ import info.nightscout.androidaps.database.entities.TherapyEvent
|
||||||
class CgmSourceTransaction(
|
class CgmSourceTransaction(
|
||||||
private val glucoseValues: List<TransactionGlucoseValue>,
|
private val glucoseValues: List<TransactionGlucoseValue>,
|
||||||
private val calibrations: List<Calibration>,
|
private val calibrations: List<Calibration>,
|
||||||
private val sensorInsertionTime: Long?
|
private val sensorInsertionTime: Long?,
|
||||||
) : Transaction<List<GlucoseValue>>() {
|
private val syncer: Boolean = false // caller is not native source ie. NS
|
||||||
|
// syncer is allowed create records
|
||||||
|
// update synchronization ID
|
||||||
|
) : Transaction<CgmSourceTransaction.TransactionResult>() {
|
||||||
|
|
||||||
override fun run(): List<GlucoseValue> {
|
override fun run(): TransactionResult {
|
||||||
val insertedGlucoseValues = mutableListOf<GlucoseValue>()
|
val result = TransactionResult()
|
||||||
glucoseValues.forEach {
|
glucoseValues.forEach {
|
||||||
val current = database.glucoseValueDao.findByTimestampAndSensor(it.timestamp, it.sourceSensor)
|
val current = database.glucoseValueDao.findByTimestampAndSensor(it.timestamp, it.sourceSensor)
|
||||||
val glucoseValue = GlucoseValue(
|
val glucoseValue = GlucoseValue(
|
||||||
|
@ -25,15 +28,26 @@ class CgmSourceTransaction(
|
||||||
sourceSensor = it.sourceSensor
|
sourceSensor = it.sourceSensor
|
||||||
)
|
)
|
||||||
glucoseValue.interfaceIDs.nightscoutId = it.nightscoutId
|
glucoseValue.interfaceIDs.nightscoutId = it.nightscoutId
|
||||||
|
// if nsId is not provided in new record, copy from current if exists
|
||||||
|
if (glucoseValue.interfaceIDs.nightscoutId == null)
|
||||||
|
current?.let { existing -> glucoseValue.interfaceIDs.nightscoutId = existing.interfaceIDs.nightscoutId }
|
||||||
when {
|
when {
|
||||||
|
// new record, create new
|
||||||
current == null -> {
|
current == null -> {
|
||||||
database.glucoseValueDao.insertNewEntry(glucoseValue)
|
database.glucoseValueDao.insertNewEntry(glucoseValue)
|
||||||
insertedGlucoseValues.add(glucoseValue)
|
result.inserted.add(glucoseValue)
|
||||||
}
|
}
|
||||||
|
// different record, update
|
||||||
!current.contentEqualsTo(glucoseValue) -> {
|
!current.contentEqualsTo(glucoseValue) && !syncer -> {
|
||||||
glucoseValue.id = current.id
|
glucoseValue.id = current.id
|
||||||
database.glucoseValueDao.updateExistingEntry(glucoseValue)
|
database.glucoseValueDao.updateExistingEntry(glucoseValue)
|
||||||
|
result.updated.add(glucoseValue)
|
||||||
|
}
|
||||||
|
// update NS id if didn't exist and now provided
|
||||||
|
current.interfaceIDs.nightscoutId == null && it.nightscoutId != null && syncer -> {
|
||||||
|
glucoseValue.id = current.id
|
||||||
|
database.glucoseValueDao.updateExistingEntry(glucoseValue)
|
||||||
|
result.updated.add(glucoseValue)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,7 +68,7 @@ class CgmSourceTransaction(
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return insertedGlucoseValues
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
data class TransactionGlucoseValue(
|
data class TransactionGlucoseValue(
|
||||||
|
@ -71,4 +85,16 @@ class CgmSourceTransaction(
|
||||||
val timestamp: Long,
|
val timestamp: Long,
|
||||||
val value: Double
|
val value: Double
|
||||||
)
|
)
|
||||||
|
|
||||||
|
class TransactionResult {
|
||||||
|
|
||||||
|
val inserted = mutableListOf<GlucoseValue>()
|
||||||
|
val updated = mutableListOf<GlucoseValue>()
|
||||||
|
|
||||||
|
fun all(): MutableList<GlucoseValue> =
|
||||||
|
mutableListOf<GlucoseValue>().also { result ->
|
||||||
|
result.addAll(inserted)
|
||||||
|
result.addAll(updated)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in a new issue