diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/GlunovoPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/GlunovoPlugin.kt index ed5ebc609d..cc2639e41e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/GlunovoPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/GlunovoPlugin.kt @@ -5,6 +5,7 @@ import android.net.Uri import android.os.Handler import android.os.HandlerThread import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.Constants import info.nightscout.androidaps.R import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.entities.GlucoseValue @@ -15,13 +16,16 @@ import info.nightscout.androidaps.interfaces.PluginDescription import info.nightscout.androidaps.interfaces.PluginType import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag +import info.nightscout.androidaps.utils.DateUtil +import info.nightscout.androidaps.utils.FabricPrivacy +import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.XDripBroadcast import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.sharedPreferences.SP import io.reactivex.disposables.CompositeDisposable -import java.util.* import javax.inject.Inject import javax.inject.Singleton +import kotlin.math.min @Singleton class GlunovoPlugin @Inject constructor( @@ -31,7 +35,9 @@ class GlunovoPlugin @Inject constructor( private val sp: SP, private val context: Context, private val repository: AppRepository, - private val broadcastToXDrip: XDripBroadcast + private val broadcastToXDrip: XDripBroadcast, + private val dateUtil: DateUtil, + private val fabricPrivacy: FabricPrivacy ) : PluginBase( PluginDescription() .mainType(PluginType.BGSOURCE) @@ -51,8 +57,15 @@ class GlunovoPlugin @Inject constructor( init { refreshLoop = Runnable { - loopHandler.postDelayed(refreshLoop, INTERVAL) - handleNewData() + try { + handleNewData() + } catch (e: Exception) { + fabricPrivacy.logException(e) + aapsLogger.error("Error while processing data", e) + } + val lastReadTimestamp = sp.getLong(R.string.key_last_processed_glunovo_timestamp, 0L) + val differenceToNow = min(INTERVAL, dateUtil.now() - lastReadTimestamp + INTERVAL + T.secs(10).msecs()) + loopHandler.postDelayed(refreshLoop, differenceToNow) } } @@ -60,7 +73,7 @@ class GlunovoPlugin @Inject constructor( override fun onStart() { super.onStart() - loopHandler.postDelayed(refreshLoop, INTERVAL) + loopHandler.postDelayed(refreshLoop, T.secs(30).msecs()) // do not start immediately, app may be still starting } override fun onStop() { @@ -73,42 +86,50 @@ class GlunovoPlugin @Inject constructor( if (!isEnabled()) return context.contentResolver.query(contentUri, null, null, null, null)?.let { cr -> - cr.moveToLast() - val curTime = Calendar.getInstance().timeInMillis - val time = cr.getLong(0) - val value = cr.getDouble(1) //value in mmol/l... - if (time > curTime || time == 0L) { - aapsLogger.error(LTag.BGSOURCE, "Error in received data date/time $time") - return - } - - if (value < 2 || value > 25) { - aapsLogger.error(LTag.BGSOURCE, "Error in received data value (value out of bounds) $value") - return - } - val glucoseValues = mutableListOf<CgmSourceTransaction.TransactionGlucoseValue>() - glucoseValues += CgmSourceTransaction.TransactionGlucoseValue( - timestamp = time, - value = value, - raw = 0.0, - noise = null, - trendArrow = GlucoseValue.TrendArrow.NONE, - sourceSensor = GlucoseValue.SourceSensor.GLUNOVO_NATIVE - ) - repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null)) - .doOnError { - aapsLogger.error(LTag.DATABASE, "Error while saving values from Glunovo App", it) - } - .blockingGet() - .also { savedValues -> - savedValues.inserted.forEach { - broadcastToXDrip(it) - aapsLogger.debug(LTag.DATABASE, "Inserted bg $it") - } + cr.moveToFirst() + + while (!cr.isAfterLast) { + val timestamp = cr.getLong(0) + val value = cr.getDouble(1) //value in mmol/l... + if (timestamp > dateUtil.now() || timestamp == 0L) { + aapsLogger.error(LTag.BGSOURCE, "Error in received data date/time $timestamp") + continue } + if (value < 2 || value > 25) { + aapsLogger.error(LTag.BGSOURCE, "Error in received data value (value out of bounds) $value") + continue + } + + // bypass already processed + if (timestamp < sp.getLong(R.string.key_last_processed_glunovo_timestamp, 0L)) continue + + glucoseValues += CgmSourceTransaction.TransactionGlucoseValue( + timestamp = timestamp, + value = value * Constants.MMOLL_TO_MGDL, + raw = 0.0, + noise = null, + trendArrow = GlucoseValue.TrendArrow.NONE, + sourceSensor = GlucoseValue.SourceSensor.GLUNOVO_NATIVE + ) + sp.putLong(R.string.key_last_processed_glunovo_timestamp, timestamp) + cr.moveToNext() + } cr.close() + + if (glucoseValues.isNotEmpty()) + repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null)) + .doOnError { + aapsLogger.error(LTag.DATABASE, "Error while saving values from Glunovo App", it) + } + .blockingGet() + .also { savedValues -> + savedValues.inserted.forEach { + broadcastToXDrip(it) + aapsLogger.debug(LTag.DATABASE, "Inserted bg $it") + } + } } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f776a6b2de..1beca8f6d9 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1134,5 +1134,6 @@ <string name="data_status">BG data status</string> <string name="recalculated_data_used">Recalculated data used</string> <string name="bg_too_close">BG too close:\n%1$s\n%2$s</string> + <string name="key_last_processed_glunovo_timestamp">last_processed_glunovo_timestamp</string> </resources>