From fb94393c1c53ea72ff3c8286bcefebd1d16bd637 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Wed, 9 Aug 2023 22:40:29 +0200 Subject: [PATCH] NSCv1,v3: improve sync --- .../rx/events/EventDeviceStatusChange.kt | 3 + .../interfaces/sync/DataSyncSelector.kt | 29 +- .../interfaces/sync/DataSyncSelectorV1.kt | 46 - .../interfaces/sync/DataSyncSelectorV3.kt | 3 - .../database/entities/DeviceStatus.kt | 5 +- .../nightscout/database/impl/AppRepository.kt | 9 +- .../implementation/db/CompatDBHelper.kt | 6 + .../nightscout/plugins/sync/di/SyncModule.kt | 15 +- .../plugins/sync/nsShared/NSClientFragment.kt | 6 +- .../sync/nsclient/DataSyncSelectorV1.kt | 807 ++++++++++++++++++ .../sync/nsclient/DataSyncSelectorV1Impl.kt | 737 ---------------- .../plugins/sync/nsclient/NSClientPlugin.kt | 2 - .../sync/nsclient/services/NSClientService.kt | 25 +- .../nsclient/workers/NSClientAddAckWorker.kt | 57 +- .../workers/NSClientUpdateRemoveAckWorker.kt | 52 +- ...electorV3Impl.kt => DataSyncSelectorV3.kt} | 98 +-- .../sync/nsclientV3/NSClientV3Plugin.kt | 16 +- .../sync/nsclientV3/workers/DataSyncWorker.kt | 2 +- .../sync/nsclientV3/NSClientV3PluginTest.kt | 2 +- .../nsclientV3/workers/DataSyncWorkerTest.kt | 4 +- .../nsclientV3/workers/LoadBgWorkerTest.kt | 2 +- 21 files changed, 969 insertions(+), 957 deletions(-) create mode 100644 app-wear-shared/shared/src/main/java/info/nightscout/rx/events/EventDeviceStatusChange.kt delete mode 100644 core/interfaces/src/main/java/info/nightscout/interfaces/sync/DataSyncSelectorV1.kt delete mode 100644 core/interfaces/src/main/java/info/nightscout/interfaces/sync/DataSyncSelectorV3.kt create mode 100644 plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclient/DataSyncSelectorV1.kt delete mode 100644 plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclient/DataSyncSelectorV1Impl.kt rename plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclientV3/{DataSyncSelectorV3Impl.kt => DataSyncSelectorV3.kt} (92%) diff --git a/app-wear-shared/shared/src/main/java/info/nightscout/rx/events/EventDeviceStatusChange.kt b/app-wear-shared/shared/src/main/java/info/nightscout/rx/events/EventDeviceStatusChange.kt new file mode 100644 index 0000000000..9bfe37b1b0 --- /dev/null +++ b/app-wear-shared/shared/src/main/java/info/nightscout/rx/events/EventDeviceStatusChange.kt @@ -0,0 +1,3 @@ +package info.nightscout.rx.events + +class EventDeviceStatusChange : Event() \ No newline at end of file diff --git a/core/interfaces/src/main/java/info/nightscout/interfaces/sync/DataSyncSelector.kt b/core/interfaces/src/main/java/info/nightscout/interfaces/sync/DataSyncSelector.kt index 9de3739d17..9a434d2ea6 100644 --- a/core/interfaces/src/main/java/info/nightscout/interfaces/sync/DataSyncSelector.kt +++ b/core/interfaces/src/main/java/info/nightscout/interfaces/sync/DataSyncSelector.kt @@ -21,22 +21,23 @@ interface DataSyncSelector { val value: Any val id: Long + var confirmed: Boolean } - data class PairTemporaryTarget(override val value: TemporaryTarget, override val id: Long) : DataPair - data class PairGlucoseValue(override val value: GlucoseValue, override val id: Long) : DataPair - data class PairTherapyEvent(override val value: TherapyEvent, override val id: Long) : DataPair - data class PairFood(override val value: Food, override val id: Long) : DataPair - data class PairBolus(override val value: Bolus, override val id: Long) : DataPair - data class PairCarbs(override val value: Carbs, override val id: Long) : DataPair - data class PairBolusCalculatorResult(override val value: BolusCalculatorResult, override val id: Long) : DataPair - data class PairTemporaryBasal(override val value: TemporaryBasal, override val id: Long) : DataPair - data class PairExtendedBolus(override val value: ExtendedBolus, override val id: Long) : DataPair - data class PairProfileSwitch(override val value: ProfileSwitch, override val id: Long) : DataPair - data class PairEffectiveProfileSwitch(override val value: EffectiveProfileSwitch, override val id: Long) : DataPair - data class PairOfflineEvent(override val value: OfflineEvent, override val id: Long) : DataPair - data class PairProfileStore(override val value: JSONObject, override val id: Long) : DataPair - data class PairDeviceStatus(override val value: DeviceStatus, override val id: Long) : DataPair + data class PairTemporaryTarget(override val value: TemporaryTarget, override val id: Long, override var confirmed: Boolean = false) : DataPair + data class PairGlucoseValue(override val value: GlucoseValue, override val id: Long, override var confirmed: Boolean = false) : DataPair + data class PairTherapyEvent(override val value: TherapyEvent, override val id: Long, override var confirmed: Boolean = false) : DataPair + data class PairFood(override val value: Food, override val id: Long, override var confirmed: Boolean = false) : DataPair + data class PairBolus(override val value: Bolus, override val id: Long, override var confirmed: Boolean = false) : DataPair + data class PairCarbs(override val value: Carbs, override val id: Long, override var confirmed: Boolean = false) : DataPair + data class PairBolusCalculatorResult(override val value: BolusCalculatorResult, override val id: Long, override var confirmed: Boolean = false) : DataPair + data class PairTemporaryBasal(override val value: TemporaryBasal, override val id: Long, override var confirmed: Boolean = false) : DataPair + data class PairExtendedBolus(override val value: ExtendedBolus, override val id: Long, override var confirmed: Boolean = false) : DataPair + data class PairProfileSwitch(override val value: ProfileSwitch, override val id: Long, override var confirmed: Boolean = false) : DataPair + data class PairEffectiveProfileSwitch(override val value: EffectiveProfileSwitch, override val id: Long, override var confirmed: Boolean = false) : DataPair + data class PairOfflineEvent(override val value: OfflineEvent, override val id: Long, override var confirmed: Boolean = false) : DataPair + data class PairProfileStore(override val value: JSONObject, override val id: Long, override var confirmed: Boolean = false) : DataPair + data class PairDeviceStatus(override val value: DeviceStatus, override val id: Long, override var confirmed: Boolean = false) : DataPair fun queueSize(): Long diff --git a/core/interfaces/src/main/java/info/nightscout/interfaces/sync/DataSyncSelectorV1.kt b/core/interfaces/src/main/java/info/nightscout/interfaces/sync/DataSyncSelectorV1.kt deleted file mode 100644 index f70d0a6aa3..0000000000 --- a/core/interfaces/src/main/java/info/nightscout/interfaces/sync/DataSyncSelectorV1.kt +++ /dev/null @@ -1,46 +0,0 @@ -package info.nightscout.interfaces.sync - -interface DataSyncSelectorV1 : DataSyncSelector { - - fun confirmLastBolusIdIfGreater(lastSynced: Long) - suspend fun processChangedBoluses() - - fun confirmLastCarbsIdIfGreater(lastSynced: Long) - suspend fun processChangedCarbs() - - fun confirmLastBolusCalculatorResultsIdIfGreater(lastSynced: Long) - suspend fun processChangedBolusCalculatorResults() - - fun confirmLastTempTargetsIdIfGreater(lastSynced: Long) - suspend fun processChangedTempTargets() - - fun confirmLastGlucoseValueIdIfGreater(lastSynced: Long) - suspend fun processChangedGlucoseValues() - - fun confirmLastTherapyEventIdIfGreater(lastSynced: Long) - suspend fun processChangedTherapyEvents() - - fun confirmLastFoodIdIfGreater(lastSynced: Long) - suspend fun processChangedFoods() - - fun confirmLastDeviceStatusIdIfGreater(lastSynced: Long) - suspend fun processChangedDeviceStatuses() - - fun confirmLastTemporaryBasalIdIfGreater(lastSynced: Long) - suspend fun processChangedTemporaryBasals() - - fun confirmLastExtendedBolusIdIfGreater(lastSynced: Long) - suspend fun processChangedExtendedBoluses() - - fun confirmLastProfileSwitchIdIfGreater(lastSynced: Long) - suspend fun processChangedProfileSwitches() - - fun confirmLastEffectiveProfileSwitchIdIfGreater(lastSynced: Long) - suspend fun processChangedEffectiveProfileSwitches() - - fun confirmLastOfflineEventIdIfGreater(lastSynced: Long) - suspend fun processChangedOfflineEvents() - - fun confirmLastProfileStore(lastSynced: Long) - suspend fun processChangedProfileStore() -} \ No newline at end of file diff --git a/core/interfaces/src/main/java/info/nightscout/interfaces/sync/DataSyncSelectorV3.kt b/core/interfaces/src/main/java/info/nightscout/interfaces/sync/DataSyncSelectorV3.kt deleted file mode 100644 index 90e9c77044..0000000000 --- a/core/interfaces/src/main/java/info/nightscout/interfaces/sync/DataSyncSelectorV3.kt +++ /dev/null @@ -1,3 +0,0 @@ -package info.nightscout.interfaces.sync - -interface DataSyncSelectorV3 : DataSyncSelector diff --git a/database/entities/src/main/java/info/nightscout/database/entities/DeviceStatus.kt b/database/entities/src/main/java/info/nightscout/database/entities/DeviceStatus.kt index bfe4520d7b..e48dbf322b 100644 --- a/database/entities/src/main/java/info/nightscout/database/entities/DeviceStatus.kt +++ b/database/entities/src/main/java/info/nightscout/database/entities/DeviceStatus.kt @@ -5,6 +5,7 @@ import androidx.room.Entity import androidx.room.Index import androidx.room.PrimaryKey import info.nightscout.database.entities.embedments.InterfaceIDs +import info.nightscout.database.entities.interfaces.DBEntry import info.nightscout.database.entities.interfaces.DBEntryWithTime import java.util.TimeZone @@ -17,7 +18,7 @@ import java.util.TimeZone ]) data class DeviceStatus( @PrimaryKey(autoGenerate = true) - var id: Long = 0, + override var id: Long = 0, @Embedded var interfaceIDs_backing: InterfaceIDs? = null, override var timestamp: Long, @@ -31,7 +32,7 @@ data class DeviceStatus( var isCharging: Boolean?, var configuration: String? = null -) : DBEntryWithTime { +) : DBEntry, DBEntryWithTime { var interfaceIDs: InterfaceIDs get() { diff --git a/database/impl/src/main/java/info/nightscout/database/impl/AppRepository.kt b/database/impl/src/main/java/info/nightscout/database/impl/AppRepository.kt index 12e1c629cc..46f872ad75 100644 --- a/database/impl/src/main/java/info/nightscout/database/impl/AppRepository.kt +++ b/database/impl/src/main/java/info/nightscout/database/impl/AppRepository.kt @@ -254,6 +254,7 @@ import kotlin.math.roundToInt fun insert(word: UserEntry) { database.userEntryDao.insert(word) + changeSubject.onNext(mutableListOf(word)) // Not TraceableDao } // PROFILE SWITCH @@ -712,8 +713,10 @@ import kotlin.math.roundToInt database.bolusCalculatorResultDao.getLastId() // DEVICE STATUS - fun insert(deviceStatus: DeviceStatus): Long = + fun insert(deviceStatus: DeviceStatus) { database.deviceStatusDao.insert(deviceStatus) + changeSubject.onNext(mutableListOf(deviceStatus)) // Not TraceableDao + } /* * returns a Pair of the next entity to sync and the ID of the "update". @@ -727,10 +730,6 @@ import kotlin.math.roundToInt database.deviceStatusDao.getNextModifiedOrNewAfter(id) .subscribeOn(Schedulers.io()) - fun getModifiedDeviceStatusDataFromId(lastId: Long): Single> = - database.deviceStatusDao.getModifiedFrom(lastId) - .subscribeOn(Schedulers.io()) - fun getLastDeviceStatusId(): Long? = database.deviceStatusDao.getLastId() diff --git a/implementation/src/main/java/info/nightscout/implementation/db/CompatDBHelper.kt b/implementation/src/main/java/info/nightscout/implementation/db/CompatDBHelper.kt index 3c0866c536..22751eca68 100644 --- a/implementation/src/main/java/info/nightscout/implementation/db/CompatDBHelper.kt +++ b/implementation/src/main/java/info/nightscout/implementation/db/CompatDBHelper.kt @@ -3,6 +3,7 @@ package info.nightscout.implementation.db import android.content.Context import info.nightscout.database.entities.Bolus import info.nightscout.database.entities.Carbs +import info.nightscout.database.entities.DeviceStatus import info.nightscout.database.entities.EffectiveProfileSwitch import info.nightscout.database.entities.ExtendedBolus import info.nightscout.database.entities.Food @@ -15,6 +16,7 @@ import info.nightscout.database.entities.TherapyEvent import info.nightscout.database.impl.AppRepository import info.nightscout.interfaces.ui.UiInteraction import info.nightscout.rx.bus.RxBus +import info.nightscout.rx.events.EventDeviceStatusChange import info.nightscout.rx.events.EventEffectiveProfileSwitchChanged import info.nightscout.rx.events.EventExtendedBolusChange import info.nightscout.rx.events.EventFoodDatabaseChanged @@ -109,5 +111,9 @@ class CompatDBHelper @Inject constructor( aapsLogger.debug(LTag.DATABASE, "Firing EventOfflineChange $oe") rxBus.send(EventOfflineChange()) } + it.filterIsInstance().firstOrNull()?.let { ds -> + aapsLogger.debug(LTag.DATABASE, "Firing EventDeviceStatusChange $ds") + rxBus.send(EventDeviceStatusChange()) + } } } \ No newline at end of file diff --git a/plugins/sync/src/main/java/info/nightscout/plugins/sync/di/SyncModule.kt b/plugins/sync/src/main/java/info/nightscout/plugins/sync/di/SyncModule.kt index 0b4f4188ff..8d775773bb 100644 --- a/plugins/sync/src/main/java/info/nightscout/plugins/sync/di/SyncModule.kt +++ b/plugins/sync/src/main/java/info/nightscout/plugins/sync/di/SyncModule.kt @@ -11,12 +11,9 @@ import info.nightscout.interfaces.XDripBroadcast import info.nightscout.interfaces.nsclient.NSSettingsStatus import info.nightscout.interfaces.nsclient.ProcessedDeviceStatusData import info.nightscout.interfaces.nsclient.StoreDataForDb -import info.nightscout.interfaces.sync.DataSyncSelectorV1 -import info.nightscout.interfaces.sync.DataSyncSelectorV3 import info.nightscout.interfaces.sync.DataSyncSelectorXdrip import info.nightscout.plugins.sync.nsShared.NSClientFragment import info.nightscout.plugins.sync.nsShared.StoreDataForDbImpl -import info.nightscout.plugins.sync.nsclient.DataSyncSelectorV1Impl import info.nightscout.plugins.sync.nsclient.data.NSSettingsStatusImpl import info.nightscout.plugins.sync.nsclient.data.ProcessedDeviceStatusDataImpl import info.nightscout.plugins.sync.nsclient.services.NSClientService @@ -24,8 +21,14 @@ import info.nightscout.plugins.sync.nsclient.workers.NSClientAddAckWorker import info.nightscout.plugins.sync.nsclient.workers.NSClientAddUpdateWorker import info.nightscout.plugins.sync.nsclient.workers.NSClientMbgWorker import info.nightscout.plugins.sync.nsclient.workers.NSClientUpdateRemoveAckWorker -import info.nightscout.plugins.sync.nsclientV3.DataSyncSelectorV3Impl -import info.nightscout.plugins.sync.nsclientV3.workers.* +import info.nightscout.plugins.sync.nsclientV3.workers.DataSyncWorker +import info.nightscout.plugins.sync.nsclientV3.workers.LoadBgWorker +import info.nightscout.plugins.sync.nsclientV3.workers.LoadDeviceStatusWorker +import info.nightscout.plugins.sync.nsclientV3.workers.LoadFoodsWorker +import info.nightscout.plugins.sync.nsclientV3.workers.LoadLastModificationWorker +import info.nightscout.plugins.sync.nsclientV3.workers.LoadProfileStoreWorker +import info.nightscout.plugins.sync.nsclientV3.workers.LoadStatusWorker +import info.nightscout.plugins.sync.nsclientV3.workers.LoadTreatmentsWorker import info.nightscout.plugins.sync.tidepool.TidepoolFragment import info.nightscout.plugins.sync.xdrip.DataSyncSelectorXdripImpl import info.nightscout.plugins.sync.xdrip.XdripFragment @@ -75,8 +78,6 @@ abstract class SyncModule { @Binds fun bindProcessedDeviceStatusData(processedDeviceStatusDataImpl: ProcessedDeviceStatusDataImpl): ProcessedDeviceStatusData @Binds fun bindNSSettingsStatus(nsSettingsStatusImpl: NSSettingsStatusImpl): NSSettingsStatus - @Binds fun bindDataSyncSelectorV1Interface(dataSyncSelectorV1Impl: DataSyncSelectorV1Impl): DataSyncSelectorV1 - @Binds fun bindDataSyncSelectorV3Interface(dataSyncSelectorV3Impl: DataSyncSelectorV3Impl): DataSyncSelectorV3 @Binds fun bindDataSyncSelectorXdripInterface(dataSyncSelectorXdripImpl: DataSyncSelectorXdripImpl): DataSyncSelectorXdrip @Binds fun bindStoreDataForDb(storeDataForDbImpl: StoreDataForDbImpl): StoreDataForDb @Binds fun bindXDripBroadcastInterface(xDripBroadcastImpl: XdripPlugin): XDripBroadcast diff --git a/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsShared/NSClientFragment.kt b/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsShared/NSClientFragment.kt index 1960ffb2b8..98081b80a6 100644 --- a/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsShared/NSClientFragment.kt +++ b/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsShared/NSClientFragment.kt @@ -123,7 +123,7 @@ class NSClientFragment : DaggerFragment(), MenuProvider, PluginFragment { nsClientPlugin?.listLog?.let { synchronized(it) { it.clear() - _binding?.recyclerview?.swapAdapter(RecyclerViewAdapter(it), true) + updateLog() } } true @@ -211,6 +211,7 @@ class NSClientFragment : DaggerFragment(), MenuProvider, PluginFragment { .subscribe({ updateStatus() }, fabricPrivacy::logException) updateStatus() updateQueue() + updateLog() } @Synchronized @@ -231,6 +232,9 @@ class NSClientFragment : DaggerFragment(), MenuProvider, PluginFragment { binding.status.text = nsClientPlugin?.status } + private fun updateLog() { + _binding?.recyclerview?.swapAdapter(RecyclerViewAdapter(nsClientPlugin?.listLog ?: arrayListOf()), true) + } private inner class RecyclerViewAdapter(private var logList: List) : RecyclerView.Adapter() { override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): NsClientLogViewHolder = diff --git a/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclient/DataSyncSelectorV1.kt b/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclient/DataSyncSelectorV1.kt new file mode 100644 index 0000000000..75cefbf012 --- /dev/null +++ b/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclient/DataSyncSelectorV1.kt @@ -0,0 +1,807 @@ +package info.nightscout.plugins.sync.nsclient + +import info.nightscout.core.utils.waitMillis +import info.nightscout.database.impl.AppRepository +import info.nightscout.interfaces.plugin.ActivePlugin +import info.nightscout.interfaces.profile.ProfileFunction +import info.nightscout.interfaces.sync.DataSyncSelector +import info.nightscout.interfaces.utils.JsonHelper +import info.nightscout.plugins.sync.R +import info.nightscout.plugins.sync.nsShared.events.EventNSClientUpdateGuiQueue +import info.nightscout.plugins.sync.nsShared.events.EventNSClientUpdateGuiStatus +import info.nightscout.rx.bus.RxBus +import info.nightscout.rx.events.EventNSClientNewLog +import info.nightscout.rx.logging.AAPSLogger +import info.nightscout.rx.logging.LTag +import info.nightscout.shared.sharedPreferences.SP +import info.nightscout.shared.utils.DateUtil +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.async +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class DataSyncSelectorV1 @Inject constructor( + private val sp: SP, + private val aapsLogger: AAPSLogger, + private val dateUtil: DateUtil, + private val profileFunction: ProfileFunction, + private val activePlugin: ActivePlugin, + private val appRepository: AppRepository, + private val rxBus: RxBus +) : DataSyncSelector { + + private var scope = CoroutineScope(Dispatchers.IO + SupervisorJob()) + + class QueueCounter( + var bolusesRemaining: Long = -1L, + var carbsRemaining: Long = -1L, + var bcrRemaining: Long = -1L, + var ttsRemaining: Long = -1L, + var foodsRemaining: Long = -1L, + var gvsRemaining: Long = -1L, + var tesRemaining: Long = -1L, + var dssRemaining: Long = -1L, + var tbrsRemaining: Long = -1L, + var ebsRemaining: Long = -1L, + var pssRemaining: Long = -1L, + var epssRemaining: Long = -1L, + var oesRemaining: Long = -1L + ) { + + fun size(): Long = + bolusesRemaining + + carbsRemaining + + bcrRemaining + + ttsRemaining + + foodsRemaining + + gvsRemaining + + tesRemaining + + dssRemaining + + tbrsRemaining + + ebsRemaining + + pssRemaining + + epssRemaining + + oesRemaining + } + + private val queueCounter = QueueCounter() + private val isPaused get() = sp.getBoolean(R.string.key_ns_paused, false) + + override fun queueSize(): Long = queueCounter.size() + + private var running = false + private val sync = Any() + override suspend fun doUpload() { + synchronized(sync) { + if (running) { + rxBus.send(EventNSClientNewLog("● RUN", "Already running")) + return + } + running = true + } + rxBus.send(EventNSClientUpdateGuiStatus()) + if (sp.getBoolean(R.string.key_ns_upload, true) && !isPaused) { + queueCounter.bolusesRemaining = (appRepository.getLastBolusId() ?: 0L) - sp.getLong(R.string.key_ns_bolus_last_synced_id, 0) + queueCounter.carbsRemaining = (appRepository.getLastCarbsId() ?: 0L) - sp.getLong(R.string.key_ns_carbs_last_synced_id, 0) + queueCounter.bcrRemaining = (appRepository.getLastBolusCalculatorResultId() ?: 0L) - sp.getLong(R.string.key_ns_bolus_calculator_result_last_synced_id, 0) + queueCounter.ttsRemaining = (appRepository.getLastTempTargetId() ?: 0L) - sp.getLong(R.string.key_ns_temporary_target_last_synced_id, 0) + queueCounter.foodsRemaining = (appRepository.getLastFoodId() ?: 0L) - sp.getLong(R.string.key_ns_food_last_synced_id, 0) + queueCounter.gvsRemaining = (appRepository.getLastGlucoseValueId() ?: 0L) - sp.getLong(R.string.key_ns_glucose_value_last_synced_id, 0) + queueCounter.tesRemaining = (appRepository.getLastTherapyEventId() ?: 0L) - sp.getLong(R.string.key_ns_therapy_event_last_synced_id, 0) + queueCounter.dssRemaining = (appRepository.getLastDeviceStatusId() ?: 0L) - sp.getLong(R.string.key_ns_device_status_last_synced_id, 0) + queueCounter.tbrsRemaining = (appRepository.getLastTemporaryBasalId() ?: 0L) - sp.getLong(R.string.key_ns_temporary_basal_last_synced_id, 0) + queueCounter.ebsRemaining = (appRepository.getLastExtendedBolusId() ?: 0L) - sp.getLong(R.string.key_ns_extended_bolus_last_synced_id, 0) + queueCounter.pssRemaining = (appRepository.getLastProfileSwitchId() ?: 0L) - sp.getLong(R.string.key_ns_profile_switch_last_synced_id, 0) + queueCounter.epssRemaining = (appRepository.getLastEffectiveProfileSwitchId() ?: 0L) - sp.getLong(R.string.key_ns_effective_profile_switch_last_synced_id, 0) + queueCounter.oesRemaining = (appRepository.getLastOfflineEventId() ?: 0L) - sp.getLong(R.string.key_ns_offline_event_last_synced_id, 0) + rxBus.send(EventNSClientUpdateGuiQueue()) + val boluses = scope.async { processChangedBoluses() } + val carbs = scope.async { processChangedCarbs() } + val bcs = scope.async { processChangedBolusCalculatorResults() } + val tbs = scope.async { processChangedTemporaryBasals() } + val ebs = scope.async { processChangedExtendedBoluses() } + val pss = scope.async { processChangedProfileSwitches() } + val epss = scope.async { processChangedEffectiveProfileSwitches() } + val gvs = scope.async { processChangedGlucoseValues() } + val tts = scope.async { processChangedTempTargets() } + val foods = scope.async { processChangedFoods() } + val tes = scope.async { processChangedTherapyEvents() } + val dss = scope.async { processChangedDeviceStatuses() } + val oes = scope.async { processChangedOfflineEvents() } + val ps = scope.async { processChangedProfileStore() } + + boluses.await() + carbs.await() + bcs.await() + tbs.await() + ebs.await() + pss.await() + epss.await() + gvs.await() + tts.await() + foods.await() + tes.await() + dss.await() + oes.await() + ps.await() + } + rxBus.send(EventNSClientUpdateGuiStatus()) + running = false + } + + override fun resetToNextFullSync() { + sp.remove(R.string.key_ns_glucose_value_last_synced_id) + sp.remove(R.string.key_ns_temporary_basal_last_synced_id) + sp.remove(R.string.key_ns_temporary_target_last_synced_id) + sp.remove(R.string.key_ns_extended_bolus_last_synced_id) + sp.remove(R.string.key_ns_food_last_synced_id) + sp.remove(R.string.key_ns_bolus_last_synced_id) + sp.remove(R.string.key_ns_carbs_last_synced_id) + sp.remove(R.string.key_ns_bolus_calculator_result_last_synced_id) + sp.remove(R.string.key_ns_therapy_event_last_synced_id) + sp.remove(R.string.key_ns_profile_switch_last_synced_id) + sp.remove(R.string.key_ns_effective_profile_switch_last_synced_id) + sp.remove(R.string.key_ns_offline_event_last_synced_id) + sp.remove(R.string.key_ns_profile_store_last_synced_timestamp) + + val lastDeviceStatusDbId = appRepository.getLastDeviceStatusId() + if (lastDeviceStatusDbId != null) sp.putLong(R.string.key_ns_device_status_last_synced_id, lastDeviceStatusDbId) + else sp.remove(R.string.key_ns_device_status_last_synced_id) + } + + private fun confirmLastBolusIdIfGreater(lastSynced: Long) { + if (lastSynced > sp.getLong(R.string.key_ns_bolus_last_synced_id, 0)) { + //aapsLogger.debug(LTag.NSCLIENT, "Setting Bolus data sync from $lastSynced") + sp.putLong(R.string.key_ns_bolus_last_synced_id, lastSynced) + } + } + + private suspend fun processChangedBoluses() { + var cont = true + while (cont) { + if (isPaused) return + val lastDbId = appRepository.getLastBolusId() ?: 0L + var startId = sp.getLong(R.string.key_ns_bolus_last_synced_id, 0) + if (startId > lastDbId) { + sp.putLong(R.string.key_ns_bolus_last_synced_id, 0) + startId = 0 + } + queueCounter.bolusesRemaining = lastDbId - startId + rxBus.send(EventNSClientUpdateGuiQueue()) + appRepository.getNextSyncElementBolus(startId).blockingGet()?.let { bolus -> + aapsLogger.info(LTag.NSCLIENT, "Loading Bolus data Start: $startId ${bolus.first} forID: ${bolus.second.id} ") + val dataPair = DataSyncSelector.PairBolus(bolus.first, bolus.second.id) + when { + // new record with existing NS id => must be coming from NS => ignore + bolus.first.id == bolus.second.id && bolus.first.interfaceIDs.nightscoutId != null -> + aapsLogger.info(LTag.NSCLIENT, "Ignoring Bolus. Loaded from NS: ${bolus.second.id} ") + // only NsId changed, no need to upload + bolus.first.onlyNsIdAdded(bolus.second) -> + aapsLogger.info(LTag.NSCLIENT, "Ignoring Bolus. Only NS id changed: ${bolus.second.id} ") + // without nsId = create new + bolus.first.interfaceIDs.nightscoutId == null -> { + activePlugin.activeNsClient?.nsAdd("treatments", dataPair, " $startId/$lastDbId") + synchronized(dataPair) { dataPair.waitMillis(60000) } + cont = dataPair.confirmed + } + // with nsId = update if it's modified record + bolus.first.interfaceIDs.nightscoutId != null && bolus.first.id != bolus.second.id -> { + activePlugin.activeNsClient?.nsUpdate("treatments", dataPair, "$startId/$lastDbId") + synchronized(dataPair) { dataPair.waitMillis(60000) } + cont = dataPair.confirmed + } + } + if (cont) confirmLastBolusIdIfGreater(bolus.second.id) + } ?: run { + cont = false + } + } + } + + private fun confirmLastCarbsIdIfGreater(lastSynced: Long) { + if (lastSynced > sp.getLong(R.string.key_ns_carbs_last_synced_id, 0)) { + //aapsLogger.debug(LTag.NSCLIENT, "Setting Carbs data sync from $lastSynced") + sp.putLong(R.string.key_ns_carbs_last_synced_id, lastSynced) + } + } + + private suspend fun processChangedCarbs() { + var cont = true + while (cont) { + if (isPaused) return + val lastDbId = appRepository.getLastCarbsId() ?: 0L + var startId = sp.getLong(R.string.key_ns_carbs_last_synced_id, 0) + if (startId > lastDbId) { + sp.putLong(R.string.key_ns_carbs_last_synced_id, 0) + startId = 0 + } + queueCounter.carbsRemaining = lastDbId - startId + rxBus.send(EventNSClientUpdateGuiQueue()) + appRepository.getNextSyncElementCarbs(startId).blockingGet()?.let { carb -> + aapsLogger.info(LTag.NSCLIENT, "Loading Carbs data Start: $startId ${carb.first} forID: ${carb.second.id} ") + val dataPair = DataSyncSelector.PairCarbs(carb.first, carb.second.id) + when { + // new record with existing NS id => must be coming from NS => ignore + carb.first.id == carb.second.id && carb.first.interfaceIDs.nightscoutId != null -> + aapsLogger.info(LTag.NSCLIENT, "Ignoring Carbs. Loaded from NS: ${carb.second.id} ") + // only NsId changed, no need to upload + carb.first.onlyNsIdAdded(carb.second) -> + aapsLogger.info(LTag.NSCLIENT, "Ignoring Carbs. Only NS id changed ID: ${carb.second.id} ") + // without nsId = create new + carb.first.interfaceIDs.nightscoutId == null -> { + activePlugin.activeNsClient?.nsAdd("treatments", dataPair, "$startId/$lastDbId") + synchronized(dataPair) { dataPair.waitMillis(60000) } + cont = dataPair.confirmed + } + // with nsId = update if it's modified record + carb.first.interfaceIDs.nightscoutId != null && carb.first.id != carb.second.id -> { + activePlugin.activeNsClient?.nsUpdate("treatments", dataPair, "$startId/$lastDbId") + synchronized(dataPair) { dataPair.waitMillis(60000) } + cont = dataPair.confirmed + } + } + if (cont) confirmLastCarbsIdIfGreater(carb.second.id) + } ?: run { + cont = false + } + } + } + + private fun confirmLastBolusCalculatorResultsIdIfGreater(lastSynced: Long) { + if (lastSynced > sp.getLong(R.string.key_ns_bolus_calculator_result_last_synced_id, 0)) { + //aapsLogger.debug(LTag.NSCLIENT, "Setting BolusCalculatorResult data sync from $lastSynced") + sp.putLong(R.string.key_ns_bolus_calculator_result_last_synced_id, lastSynced) + } + } + + private suspend fun processChangedBolusCalculatorResults() { + var cont = true + while (cont) { + if (isPaused) return + val lastDbId = appRepository.getLastBolusCalculatorResultId() ?: 0L + var startId = sp.getLong(R.string.key_ns_bolus_calculator_result_last_synced_id, 0) + if (startId > lastDbId) { + sp.putLong(R.string.key_ns_bolus_calculator_result_last_synced_id, 0) + startId = 0 + } + queueCounter.bcrRemaining = lastDbId - startId + rxBus.send(EventNSClientUpdateGuiQueue()) + appRepository.getNextSyncElementBolusCalculatorResult(startId).blockingGet()?.let { bolusCalculatorResult -> + aapsLogger.info(LTag.NSCLIENT, "Loading BolusCalculatorResult data Start: $startId ${bolusCalculatorResult.first} forID: ${bolusCalculatorResult.second.id} ") + val dataPair = DataSyncSelector.PairBolusCalculatorResult(bolusCalculatorResult.first, bolusCalculatorResult.second.id) + when { + // new record with existing NS id => must be coming from NS => ignore + bolusCalculatorResult.first.id == bolusCalculatorResult.second.id && bolusCalculatorResult.first.interfaceIDs.nightscoutId != null -> + aapsLogger.info(LTag.NSCLIENT, "Ignoring BolusCalculatorResult. Loaded from NS: ${bolusCalculatorResult.second.id} ") + // only NsId changed, no need to upload + bolusCalculatorResult.first.onlyNsIdAdded(bolusCalculatorResult.second) -> + aapsLogger.info(LTag.NSCLIENT, "Ignoring BolusCalculatorResult. Only NS id changed ID: ${bolusCalculatorResult.second.id} ") + // without nsId = create new + bolusCalculatorResult.first.interfaceIDs.nightscoutId == null -> { + activePlugin.activeNsClient?.nsAdd("treatments", dataPair, "$startId/$lastDbId") + synchronized(dataPair) { dataPair.waitMillis(60000) } + cont = dataPair.confirmed + } + // with nsId = update if it's modified record + bolusCalculatorResult.first.interfaceIDs.nightscoutId != null && bolusCalculatorResult.first.id != bolusCalculatorResult.second.id -> { + activePlugin.activeNsClient?.nsUpdate("treatments", dataPair, "$startId/$lastDbId") + synchronized(dataPair) { dataPair.waitMillis(60000) } + cont = dataPair.confirmed + } + } + if (cont) confirmLastBolusCalculatorResultsIdIfGreater(bolusCalculatorResult.second.id) + } ?: run { + cont = false + } + } + } + + private fun confirmLastTempTargetsIdIfGreater(lastSynced: Long) { + if (lastSynced > sp.getLong(R.string.key_ns_temporary_target_last_synced_id, 0)) { + //aapsLogger.debug(LTag.NSCLIENT, "Setting TemporaryTarget data sync from $lastSynced") + sp.putLong(R.string.key_ns_temporary_target_last_synced_id, lastSynced) + } + } + + private suspend fun processChangedTempTargets() { + var cont = true + while (cont) { + if (isPaused) return + val lastDbId = appRepository.getLastTempTargetId() ?: 0L + var startId = sp.getLong(R.string.key_ns_temporary_target_last_synced_id, 0) + if (startId > lastDbId) { + sp.putLong(R.string.key_ns_temporary_target_last_synced_id, 0) + startId = 0 + } + queueCounter.ttsRemaining = lastDbId - startId + rxBus.send(EventNSClientUpdateGuiQueue()) + appRepository.getNextSyncElementTemporaryTarget(startId).blockingGet()?.let { tt -> + aapsLogger.info(LTag.NSCLIENT, "Loading TemporaryTarget data Start: $startId ${tt.first} forID: ${tt.second.id} ") + val dataPair = DataSyncSelector.PairTemporaryTarget(tt.first, tt.second.id) + when { + // new record with existing NS id => must be coming from NS => ignore + tt.first.id == tt.second.id && tt.first.interfaceIDs.nightscoutId != null -> + aapsLogger.info(LTag.NSCLIENT, "Ignoring TemporaryTarget. Loaded from NS: ${tt.second.id} ") + // only NsId changed, no need to upload + tt.first.onlyNsIdAdded(tt.second) -> + aapsLogger.info(LTag.NSCLIENT, "Ignoring TemporaryTarget. Only NS id changed ID: ${tt.second.id} ") + // without nsId = create new + tt.first.interfaceIDs.nightscoutId == null -> { + activePlugin.activeNsClient?.nsAdd("treatments", dataPair, "$startId/$lastDbId") + synchronized(dataPair) { dataPair.waitMillis(60000) } + cont = dataPair.confirmed + } + // existing with nsId = update + tt.first.interfaceIDs.nightscoutId != null -> { + activePlugin.activeNsClient?.nsUpdate("treatments", dataPair, "$startId/$lastDbId") + synchronized(dataPair) { dataPair.waitMillis(60000) } + cont = dataPair.confirmed + } + } + if (cont) confirmLastTempTargetsIdIfGreater(tt.second.id) + } ?: run { + cont = false + } + } + } + + private fun confirmLastFoodIdIfGreater(lastSynced: Long) { + if (lastSynced > sp.getLong(R.string.key_ns_food_last_synced_id, 0)) { + //aapsLogger.debug(LTag.NSCLIENT, "Setting Food data sync from $lastSynced") + sp.putLong(R.string.key_ns_food_last_synced_id, lastSynced) + } + } + + private suspend fun processChangedFoods() { + var cont = true + while (cont) { + if (isPaused) return + val lastDbId = appRepository.getLastFoodId() ?: 0L + var startId = sp.getLong(R.string.key_ns_food_last_synced_id, 0) + if (startId > lastDbId) { + sp.putLong(R.string.key_ns_food_last_synced_id, 0) + startId = 0 + } + queueCounter.foodsRemaining = lastDbId - startId + rxBus.send(EventNSClientUpdateGuiQueue()) + appRepository.getNextSyncElementFood(startId).blockingGet()?.let { food -> + aapsLogger.info(LTag.NSCLIENT, "Loading Food data Start: $startId ${food.first} forID: ${food.second.id} ") + val dataPair = DataSyncSelector.PairFood(food.first, food.second.id) + when { + // new record with existing NS id => must be coming from NS => ignore + food.first.id == food.second.id && food.first.interfaceIDs.nightscoutId != null -> + aapsLogger.info(LTag.NSCLIENT, "Ignoring Food. Loaded from NS: ${food.second.id} ") + // only NsId changed, no need to upload + food.first.onlyNsIdAdded(food.second) -> + aapsLogger.info(LTag.NSCLIENT, "Ignoring Food. Only NS id changed ID: ${food.second.id} ") + // without nsId = create new + food.first.interfaceIDs.nightscoutId == null -> { + activePlugin.activeNsClient?.nsAdd("food", dataPair, "$startId/$lastDbId") + synchronized(dataPair) { dataPair.waitMillis(60000) } + cont = dataPair.confirmed + } + // with nsId = update + food.first.interfaceIDs.nightscoutId != null -> { + activePlugin.activeNsClient?.nsUpdate("food", dataPair, "$startId/$lastDbId") + synchronized(dataPair) { dataPair.waitMillis(60000) } + cont = dataPair.confirmed + } + } + if (cont) confirmLastFoodIdIfGreater(food.second.id) + } ?: run { + cont = false + } + } + } + + private fun confirmLastGlucoseValueIdIfGreater(lastSynced: Long) { + if (lastSynced > sp.getLong(R.string.key_ns_glucose_value_last_synced_id, 0)) { + //aapsLogger.debug(LTag.NSCLIENT, "Setting GlucoseValue data sync from $lastSynced") + sp.putLong(R.string.key_ns_glucose_value_last_synced_id, lastSynced) + } + } + + private suspend fun processChangedGlucoseValues() { + var cont = true + while (cont) { + if (isPaused) return + val lastDbId = appRepository.getLastGlucoseValueId() ?: 0L + var startId = sp.getLong(R.string.key_ns_glucose_value_last_synced_id, 0) + if (startId > lastDbId) { + sp.putLong(R.string.key_ns_glucose_value_last_synced_id, 0) + startId = 0 + } + queueCounter.gvsRemaining = lastDbId - startId + rxBus.send(EventNSClientUpdateGuiQueue()) + appRepository.getNextSyncElementGlucoseValue(startId).blockingGet()?.let { gv -> + aapsLogger.info(LTag.NSCLIENT, "Loading GlucoseValue data Start: $startId ${gv.first} forID: ${gv.second.id} ") + val dataPair = DataSyncSelector.PairGlucoseValue(gv.first, gv.second.id) + if (activePlugin.activeBgSource.shouldUploadToNs(gv.first)) { + when { + // new record with existing NS id => must be coming from NS => ignore + gv.first.id == gv.second.id && gv.first.interfaceIDs.nightscoutId != null -> + aapsLogger.info(LTag.NSCLIENT, "Ignoring GlucoseValue. Loaded from NS: ${gv.second.id} ") + // only NsId changed, no need to upload + gv.first.onlyNsIdAdded(gv.second) -> + aapsLogger.info(LTag.NSCLIENT, "Ignoring GlucoseValue. Only NS id changed ID: ${gv.second.id} ") + // without nsId = create new + gv.first.interfaceIDs.nightscoutId == null -> { + activePlugin.activeNsClient?.nsAdd("entries", dataPair, "$startId/$lastDbId") + synchronized(dataPair) { dataPair.waitMillis(60000) } + cont = dataPair.confirmed + } + // with nsId = update + else -> {// gv.first.interfaceIDs.nightscoutId != null + activePlugin.activeNsClient?.nsUpdate("entries", dataPair, "$startId/$lastDbId") + synchronized(dataPair) { dataPair.waitMillis(60000) } + cont = dataPair.confirmed + } + } + } + if (cont) confirmLastGlucoseValueIdIfGreater(gv.second.id) + } ?: run { + cont = false + } + } + } + + private fun confirmLastTherapyEventIdIfGreater(lastSynced: Long) { + if (lastSynced > sp.getLong(R.string.key_ns_therapy_event_last_synced_id, 0)) { + //aapsLogger.debug(LTag.NSCLIENT, "Setting TherapyEvents data sync from $lastSynced") + sp.putLong(R.string.key_ns_therapy_event_last_synced_id, lastSynced) + } + } + + private suspend fun processChangedTherapyEvents() { + var cont = true + while (cont) { + if (isPaused) return + val lastDbId = appRepository.getLastTherapyEventId() ?: 0L + var startId = sp.getLong(R.string.key_ns_therapy_event_last_synced_id, 0) + if (startId > lastDbId) { + sp.putLong(R.string.key_ns_therapy_event_last_synced_id, 0) + startId = 0 + } + queueCounter.tesRemaining = lastDbId - startId + rxBus.send(EventNSClientUpdateGuiQueue()) + appRepository.getNextSyncElementTherapyEvent(startId).blockingGet()?.let { te -> + aapsLogger.info(LTag.NSCLIENT, "Loading TherapyEvents data Start: $startId ${te.first} forID: ${te.second.id} ") + val dataPair = DataSyncSelector.PairTherapyEvent(te.first, te.second.id) + when { + // new record with existing NS id => must be coming from NS => ignore + te.first.id == te.second.id && te.first.interfaceIDs.nightscoutId != null -> + aapsLogger.info(LTag.NSCLIENT, "Ignoring TherapyEvent. Loaded from NS: ${te.second.id} ") + // only NsId changed, no need to upload + te.first.onlyNsIdAdded(te.second) -> + aapsLogger.info(LTag.NSCLIENT, "Ignoring TherapyEvent. Only NS id changed ID: ${te.second.id} ") + // without nsId = create new + te.first.interfaceIDs.nightscoutId == null -> { + activePlugin.activeNsClient?.nsAdd("treatments", dataPair, "$startId/$lastDbId") + synchronized(dataPair) { dataPair.waitMillis(60000) } + cont = dataPair.confirmed + } + // nsId = update + te.first.interfaceIDs.nightscoutId != null -> { + activePlugin.activeNsClient?.nsUpdate("treatments", dataPair, "$startId/$lastDbId") + synchronized(dataPair) { dataPair.waitMillis(60000) } + cont = dataPair.confirmed + } + } + if (cont) confirmLastTherapyEventIdIfGreater(te.second.id) + } ?: run { + cont = false + } + } + } + + private fun confirmLastDeviceStatusIdIfGreater(lastSynced: Long) { + if (lastSynced > sp.getLong(R.string.key_ns_device_status_last_synced_id, 0)) { + //aapsLogger.debug(LTag.NSCLIENT, "Setting DeviceStatus data sync from $lastSynced") + sp.putLong(R.string.key_ns_device_status_last_synced_id, lastSynced) + } + } + + private suspend fun processChangedDeviceStatuses() { + var cont = true + while (cont) { + if (isPaused) return + val lastDbId = appRepository.getLastDeviceStatusId() ?: 0L + var startId = sp.getLong(R.string.key_ns_device_status_last_synced_id, 0) + if (startId > lastDbId) { + sp.putLong(R.string.key_ns_device_status_last_synced_id, 0) + startId = 0 + } + queueCounter.dssRemaining = lastDbId - startId + rxBus.send(EventNSClientUpdateGuiQueue()) + appRepository.getNextSyncElementDeviceStatus(startId).blockingGet()?.let { deviceStatus -> + aapsLogger.info(LTag.NSCLIENT, "Loading DeviceStatus data Start: $startId $deviceStatus") + val dataPair = DataSyncSelector.PairDeviceStatus(deviceStatus, lastDbId) + activePlugin.activeNsClient?.nsAdd("devicestatus", dataPair, "$startId/$lastDbId") + synchronized(dataPair) { dataPair.waitMillis(60000) } + cont = dataPair.confirmed + if (cont) confirmLastDeviceStatusIdIfGreater(deviceStatus.id) + } ?: run { + cont = false + } + } + } + + private fun confirmLastTemporaryBasalIdIfGreater(lastSynced: Long) { + if (lastSynced > sp.getLong(R.string.key_ns_temporary_basal_last_synced_id, 0)) { + //aapsLogger.debug(LTag.NSCLIENT, "Setting TemporaryBasal data sync from $lastSynced") + sp.putLong(R.string.key_ns_temporary_basal_last_synced_id, lastSynced) + } + } + + private suspend fun processChangedTemporaryBasals() { + var cont = true + while (cont) { + if (isPaused) return + val lastDbId = appRepository.getLastTemporaryBasalId() ?: 0L + var startId = sp.getLong(R.string.key_ns_temporary_basal_last_synced_id, 0) + if (startId > lastDbId) { + sp.putLong(R.string.key_ns_temporary_basal_last_synced_id, 0) + startId = 0 + } + queueCounter.tbrsRemaining = lastDbId - startId + rxBus.send(EventNSClientUpdateGuiQueue()) + appRepository.getNextSyncElementTemporaryBasal(startId).blockingGet()?.let { tb -> + aapsLogger.info(LTag.NSCLIENT, "Loading TemporaryBasal data Start: $startId ${tb.first} forID: ${tb.second.id} ") + val dataPair = DataSyncSelector.PairTemporaryBasal(tb.first, tb.second.id) + val profile = profileFunction.getProfile(tb.first.timestamp) + if (profile != null) { + when { + // new record with existing NS id => must be coming from NS => ignore + tb.first.id == tb.second.id && tb.first.interfaceIDs.nightscoutId != null -> + aapsLogger.info(LTag.NSCLIENT, "Ignoring TemporaryBasal. Loaded from NS: ${tb.second.id} ") + // only NsId changed, no need to upload + tb.first.onlyNsIdAdded(tb.second) -> + aapsLogger.info(LTag.NSCLIENT, "Ignoring TemporaryBasal. Only NS id changed ID: ${tb.second.id} ") + // without nsId = create new + tb.first.interfaceIDs.nightscoutId == null -> { + activePlugin.activeNsClient?.nsAdd("treatments", dataPair, "$startId/$lastDbId", profile) + synchronized(dataPair) { dataPair.waitMillis(60000) } + cont = dataPair.confirmed + } + // with nsId = update + tb.first.interfaceIDs.nightscoutId != null -> { + activePlugin.activeNsClient?.nsUpdate("treatments", dataPair, "$startId/$lastDbId", profile) + synchronized(dataPair) { dataPair.waitMillis(60000) } + cont = dataPair.confirmed + } + } + } else aapsLogger.info(LTag.NSCLIENT, "Ignoring TemporaryBasal. No profile: ${tb.second.id} ") + if (cont) confirmLastTemporaryBasalIdIfGreater(tb.second.id) + } ?: run { + cont = false + } + } + } + + private fun confirmLastExtendedBolusIdIfGreater(lastSynced: Long) { + if (lastSynced > sp.getLong(R.string.key_ns_extended_bolus_last_synced_id, 0)) { + //aapsLogger.debug(LTag.NSCLIENT, "Setting ExtendedBolus data sync from $lastSynced") + sp.putLong(R.string.key_ns_extended_bolus_last_synced_id, lastSynced) + } + } + + private suspend fun processChangedExtendedBoluses() { + var cont = true + while (cont) { + if (isPaused) return + val lastDbId = appRepository.getLastExtendedBolusId() ?: 0L + var startId = sp.getLong(R.string.key_ns_extended_bolus_last_synced_id, 0) + if (startId > lastDbId) { + sp.putLong(R.string.key_ns_extended_bolus_last_synced_id, 0) + startId = 0 + } + queueCounter.ebsRemaining = lastDbId - startId + rxBus.send(EventNSClientUpdateGuiQueue()) + appRepository.getNextSyncElementExtendedBolus(startId).blockingGet()?.let { eb -> + aapsLogger.info(LTag.NSCLIENT, "Loading ExtendedBolus data Start: $startId ${eb.first} forID: ${eb.second.id} ") + val dataPair = DataSyncSelector.PairExtendedBolus(eb.first, eb.second.id) + val profile = profileFunction.getProfile(eb.first.timestamp) + if (profile != null) { + when { + // new record with existing NS id => must be coming from NS => ignore + eb.first.id == eb.second.id && eb.first.interfaceIDs.nightscoutId != null -> + aapsLogger.info(LTag.NSCLIENT, "Ignoring ExtendedBolus. Loaded from NS: ${eb.second.id} ") + // only NsId changed, no need to upload + eb.first.onlyNsIdAdded(eb.second) -> + aapsLogger.info(LTag.NSCLIENT, "Ignoring ExtendedBolus. Only NS id changed ID: ${eb.second.id} ") + // without nsId = create new + eb.first.interfaceIDs.nightscoutId == null -> { + activePlugin.activeNsClient?.nsAdd("treatments", dataPair, "$startId/$lastDbId", profile) + synchronized(dataPair) { dataPair.waitMillis(60000) } + cont = dataPair.confirmed + } + // with nsId = update + eb.first.interfaceIDs.nightscoutId != null -> { + activePlugin.activeNsClient?.nsUpdate("treatments", dataPair, "$startId/$lastDbId", profile) + synchronized(dataPair) { dataPair.waitMillis(60000) } + cont = dataPair.confirmed + } + } + } else aapsLogger.info(LTag.NSCLIENT, "Ignoring ExtendedBolus. No profile: ${eb.second.id} ") + if (cont) confirmLastExtendedBolusIdIfGreater(eb.second.id) + } ?: run { + cont = false + } + } + } + + private fun confirmLastProfileSwitchIdIfGreater(lastSynced: Long) { + if (lastSynced > sp.getLong(R.string.key_ns_profile_switch_last_synced_id, 0)) { + //aapsLogger.debug(LTag.NSCLIENT, "Setting ProfileSwitch data sync from $lastSynced") + sp.putLong(R.string.key_ns_profile_switch_last_synced_id, lastSynced) + } + } + + private suspend fun processChangedProfileSwitches() { + var cont = true + while (cont) { + if (isPaused) return + val lastDbId = appRepository.getLastProfileSwitchId() ?: 0L + var startId = sp.getLong(R.string.key_ns_profile_switch_last_synced_id, 0) + if (startId > lastDbId) { + sp.putLong(R.string.key_ns_profile_switch_last_synced_id, 0) + startId = 0 + } + queueCounter.pssRemaining = lastDbId - startId + rxBus.send(EventNSClientUpdateGuiQueue()) + appRepository.getNextSyncElementProfileSwitch(startId).blockingGet()?.let { ps -> + aapsLogger.info(LTag.NSCLIENT, "Loading ProfileSwitch data Start: $startId ${ps.first} forID: ${ps.second.id} ") + val dataPair = DataSyncSelector.PairProfileSwitch(ps.first, ps.second.id) + when { + // new record with existing NS id => must be coming from NS => ignore + ps.first.id == ps.second.id && ps.first.interfaceIDs.nightscoutId != null -> + aapsLogger.info(LTag.NSCLIENT, "Ignoring ProfileSwitch. Loaded from NS: ${ps.second.id} ") + // only NsId changed, no need to upload + ps.first.onlyNsIdAdded(ps.second) -> + aapsLogger.info(LTag.NSCLIENT, "Ignoring ProfileSwitch. Only NS id changed ID: ${ps.second.id} ") + // without nsId = create new + ps.first.interfaceIDs.nightscoutId == null -> { + activePlugin.activeNsClient?.nsAdd("treatments", dataPair, "$startId/$lastDbId") + synchronized(dataPair) { dataPair.waitMillis(60000) } + cont = dataPair.confirmed + } + // with nsId = update + ps.first.interfaceIDs.nightscoutId != null -> { + activePlugin.activeNsClient?.nsUpdate("treatments", dataPair, "$startId/$lastDbId") + synchronized(dataPair) { dataPair.waitMillis(60000) } + cont = dataPair.confirmed + } + } + if (cont) confirmLastProfileSwitchIdIfGreater(ps.second.id) + } ?: run { + cont = false + } + } + } + + private fun confirmLastEffectiveProfileSwitchIdIfGreater(lastSynced: Long) { + if (lastSynced > sp.getLong(R.string.key_ns_effective_profile_switch_last_synced_id, 0)) { + //aapsLogger.debug(LTag.NSCLIENT, "Setting EffectiveProfileSwitch data sync from $lastSynced") + sp.putLong(R.string.key_ns_effective_profile_switch_last_synced_id, lastSynced) + } + } + + private suspend fun processChangedEffectiveProfileSwitches() { + var cont = true + while (cont) { + if (isPaused) return + val lastDbId = appRepository.getLastEffectiveProfileSwitchId() ?: 0L + var startId = sp.getLong(R.string.key_ns_effective_profile_switch_last_synced_id, 0) + if (startId > lastDbId) { + sp.putLong(R.string.key_ns_effective_profile_switch_last_synced_id, 0) + startId = 0 + } + queueCounter.epssRemaining = lastDbId - startId + rxBus.send(EventNSClientUpdateGuiQueue()) + appRepository.getNextSyncElementEffectiveProfileSwitch(startId).blockingGet()?.let { ps -> + aapsLogger.info(LTag.NSCLIENT, "Loading EffectiveProfileSwitch data Start: $startId ${ps.first} forID: ${ps.second.id} ") + val dataPair = DataSyncSelector.PairEffectiveProfileSwitch(ps.first, ps.second.id) + when { + // new record with existing NS id => must be coming from NS => ignore + ps.first.id == ps.second.id && ps.first.interfaceIDs.nightscoutId != null -> + aapsLogger.info(LTag.NSCLIENT, "Ignoring EffectiveProfileSwitch. Loaded from NS: ${ps.second.id} ") + // only NsId changed, no need to upload + ps.first.onlyNsIdAdded(ps.second) -> + aapsLogger.info(LTag.NSCLIENT, "Ignoring EffectiveProfileSwitch. Only NS id changed ID: ${ps.second.id} ") + // without nsId = create new + ps.first.interfaceIDs.nightscoutId == null -> { + activePlugin.activeNsClient?.nsAdd("treatments", dataPair, "$startId/$lastDbId") + synchronized(dataPair) { dataPair.waitMillis(60000) } + cont = dataPair.confirmed + } + // with nsId = update + ps.first.interfaceIDs.nightscoutId != null -> { + activePlugin.activeNsClient?.nsUpdate("treatments", dataPair, "$startId/$lastDbId") + synchronized(dataPair) { dataPair.waitMillis(60000) } + cont = dataPair.confirmed + } + } + if (cont) confirmLastEffectiveProfileSwitchIdIfGreater(ps.second.id) + } ?: run { + cont = false + } + } + } + + private fun confirmLastOfflineEventIdIfGreater(lastSynced: Long) { + if (lastSynced > sp.getLong(R.string.key_ns_offline_event_last_synced_id, 0)) { + //aapsLogger.debug(LTag.NSCLIENT, "Setting OfflineEvent data sync from $lastSynced") + sp.putLong(R.string.key_ns_offline_event_last_synced_id, lastSynced) + } + } + + private suspend fun processChangedOfflineEvents() { + var cont = true + while (cont) { + if (isPaused) return + val lastDbId = appRepository.getLastOfflineEventId() ?: 0L + var startId = sp.getLong(R.string.key_ns_offline_event_last_synced_id, 0) + if (startId > lastDbId) { + sp.putLong(R.string.key_ns_offline_event_last_synced_id, 0) + startId = 0 + } + queueCounter.oesRemaining = lastDbId - startId + rxBus.send(EventNSClientUpdateGuiQueue()) + appRepository.getNextSyncElementOfflineEvent(startId).blockingGet()?.let { oe -> + aapsLogger.info(LTag.NSCLIENT, "Loading OfflineEvent data Start: $startId ${oe.first} forID: ${oe.second.id} ") + val dataPair = DataSyncSelector.PairOfflineEvent(oe.first, oe.second.id) + when { + // new record with existing NS id => must be coming from NS => ignore + oe.first.id == oe.second.id && oe.first.interfaceIDs.nightscoutId != null -> + aapsLogger.info(LTag.NSCLIENT, "Ignoring OfflineEvent. Loaded from NS: ${oe.second.id} ") + // only NsId changed, no need to upload + oe.first.onlyNsIdAdded(oe.second) -> + aapsLogger.info(LTag.NSCLIENT, "Ignoring OfflineEvent. Only NS id changed ID: ${oe.second.id} ") + // without nsId = create new + oe.first.interfaceIDs.nightscoutId == null -> { + activePlugin.activeNsClient?.nsAdd("treatments", dataPair, "$startId/$lastDbId") + synchronized(dataPair) { dataPair.waitMillis(60000) } + cont = dataPair.confirmed + } + // existing with nsId = update + oe.first.interfaceIDs.nightscoutId != null -> { + activePlugin.activeNsClient?.nsUpdate("treatments", dataPair, "$startId/$lastDbId") + synchronized(dataPair) { dataPair.waitMillis(60000) } + cont = dataPair.confirmed + } + } + if (cont) confirmLastOfflineEventIdIfGreater(oe.second.id) + } ?: run { + cont = false + } + } + } + + private fun confirmLastProfileStore(lastSynced: Long) { + sp.putLong(R.string.key_ns_profile_store_last_synced_timestamp, lastSynced) + } + + private suspend fun processChangedProfileStore() { + if (isPaused) return + val lastSync = sp.getLong(R.string.key_ns_profile_store_last_synced_timestamp, 0) + val lastChange = sp.getLong(info.nightscout.core.utils.R.string.key_local_profile_last_change, 0) + if (lastChange == 0L) return + if (lastChange > lastSync) { + if (activePlugin.activeProfileSource.profile?.allProfilesValid != true) return + val profileStore = activePlugin.activeProfileSource.profile + val profileJson = profileStore?.data ?: return + // add for v3 + if (JsonHelper.safeGetLongAllowNull(profileJson, "date") == null) + profileJson.put("date", profileStore.getStartDate()) + val dataPair = DataSyncSelector.PairProfileStore(profileJson, dateUtil.now()) + activePlugin.activeNsClient?.nsAdd("profile", dataPair, "") + synchronized(dataPair) { dataPair.waitMillis(60000) } + val now = dateUtil.now() + val cont = dataPair.confirmed + if (cont) confirmLastProfileStore(now) + } + } +} \ No newline at end of file diff --git a/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclient/DataSyncSelectorV1Impl.kt b/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclient/DataSyncSelectorV1Impl.kt deleted file mode 100644 index 04a9328493..0000000000 --- a/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclient/DataSyncSelectorV1Impl.kt +++ /dev/null @@ -1,737 +0,0 @@ -package info.nightscout.plugins.sync.nsclient - -import info.nightscout.database.impl.AppRepository -import info.nightscout.interfaces.plugin.ActivePlugin -import info.nightscout.interfaces.profile.ProfileFunction -import info.nightscout.interfaces.sync.DataSyncSelector -import info.nightscout.interfaces.sync.DataSyncSelectorV1 -import info.nightscout.interfaces.utils.JsonHelper -import info.nightscout.plugins.sync.R -import info.nightscout.plugins.sync.nsShared.events.EventNSClientUpdateGuiQueue -import info.nightscout.plugins.sync.nsShared.events.EventNSClientUpdateGuiStatus -import info.nightscout.rx.bus.RxBus -import info.nightscout.rx.logging.AAPSLogger -import info.nightscout.rx.logging.LTag -import info.nightscout.shared.sharedPreferences.SP -import info.nightscout.shared.utils.DateUtil -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class DataSyncSelectorV1Impl @Inject constructor( - private val sp: SP, - private val aapsLogger: AAPSLogger, - private val dateUtil: DateUtil, - private val profileFunction: ProfileFunction, - private val activePlugin: ActivePlugin, - private val appRepository: AppRepository, - private val rxBus: RxBus -) : DataSyncSelectorV1 { - - class QueueCounter( - var bolusesRemaining: Long = -1L, - var carbsRemaining: Long = -1L, - var bcrRemaining: Long = -1L, - var ttsRemaining: Long = -1L, - var foodsRemaining: Long = -1L, - var gvsRemaining: Long = -1L, - var tesRemaining: Long = -1L, - var dssRemaining: Long = -1L, - var tbrsRemaining: Long = -1L, - var ebsRemaining: Long = -1L, - var pssRemaining: Long = -1L, - var epssRemaining: Long = -1L, - var oesRemaining: Long = -1L - ) { - - fun size(): Long = - bolusesRemaining + - carbsRemaining + - bcrRemaining + - ttsRemaining + - foodsRemaining + - gvsRemaining + - tesRemaining + - dssRemaining + - tbrsRemaining + - ebsRemaining + - pssRemaining + - epssRemaining + - oesRemaining - } - - private val queueCounter = QueueCounter() - private val isPaused get() = sp.getBoolean(R.string.key_ns_paused, false) - - override fun queueSize(): Long = queueCounter.size() - - override suspend fun doUpload() { - rxBus.send(EventNSClientUpdateGuiStatus()) - if (sp.getBoolean(R.string.key_ns_upload, true) && !isPaused) { - queueCounter.bolusesRemaining = (appRepository.getLastBolusId() ?: 0L) - sp.getLong(R.string.key_ns_bolus_last_synced_id, 0) - queueCounter.carbsRemaining = (appRepository.getLastCarbsId() ?: 0L) - sp.getLong(R.string.key_ns_carbs_last_synced_id, 0) - queueCounter.bcrRemaining = (appRepository.getLastBolusCalculatorResultId() ?: 0L) - sp.getLong(R.string.key_ns_bolus_calculator_result_last_synced_id, 0) - queueCounter.ttsRemaining = (appRepository.getLastTempTargetId() ?: 0L) - sp.getLong(R.string.key_ns_temporary_target_last_synced_id, 0) - queueCounter.foodsRemaining = (appRepository.getLastFoodId() ?: 0L) - sp.getLong(R.string.key_ns_food_last_synced_id, 0) - queueCounter.gvsRemaining = (appRepository.getLastGlucoseValueId() ?: 0L) - sp.getLong(R.string.key_ns_glucose_value_last_synced_id, 0) - queueCounter.tesRemaining = (appRepository.getLastTherapyEventId() ?: 0L) - sp.getLong(R.string.key_ns_therapy_event_last_synced_id, 0) - queueCounter.dssRemaining = (appRepository.getLastDeviceStatusId() ?: 0L) - sp.getLong(R.string.key_ns_device_status_last_synced_id, 0) - queueCounter.tbrsRemaining = (appRepository.getLastTemporaryBasalId() ?: 0L) - sp.getLong(R.string.key_ns_temporary_basal_last_synced_id, 0) - queueCounter.ebsRemaining = (appRepository.getLastExtendedBolusId() ?: 0L) - sp.getLong(R.string.key_ns_extended_bolus_last_synced_id, 0) - queueCounter.pssRemaining = (appRepository.getLastProfileSwitchId() ?: 0L) - sp.getLong(R.string.key_ns_profile_switch_last_synced_id, 0) - queueCounter.epssRemaining = (appRepository.getLastEffectiveProfileSwitchId() ?: 0L) - sp.getLong(R.string.key_ns_effective_profile_switch_last_synced_id, 0) - queueCounter.oesRemaining = (appRepository.getLastOfflineEventId() ?: 0L) - sp.getLong(R.string.key_ns_offline_event_last_synced_id, 0) - rxBus.send(EventNSClientUpdateGuiQueue()) - processChangedBoluses() - processChangedCarbs() - processChangedBolusCalculatorResults() - processChangedTemporaryBasals() - processChangedExtendedBoluses() - processChangedProfileSwitches() - processChangedEffectiveProfileSwitches() - processChangedGlucoseValues() - processChangedTempTargets() - processChangedFoods() - processChangedTherapyEvents() - processChangedDeviceStatuses() - processChangedOfflineEvents() - processChangedProfileStore() - } - rxBus.send(EventNSClientUpdateGuiStatus()) - } - - override fun resetToNextFullSync() { - sp.remove(R.string.key_ns_glucose_value_last_synced_id) - sp.remove(R.string.key_ns_temporary_basal_last_synced_id) - sp.remove(R.string.key_ns_temporary_target_last_synced_id) - sp.remove(R.string.key_ns_extended_bolus_last_synced_id) - sp.remove(R.string.key_ns_food_last_synced_id) - sp.remove(R.string.key_ns_bolus_last_synced_id) - sp.remove(R.string.key_ns_carbs_last_synced_id) - sp.remove(R.string.key_ns_bolus_calculator_result_last_synced_id) - sp.remove(R.string.key_ns_therapy_event_last_synced_id) - sp.remove(R.string.key_ns_profile_switch_last_synced_id) - sp.remove(R.string.key_ns_effective_profile_switch_last_synced_id) - sp.remove(R.string.key_ns_offline_event_last_synced_id) - sp.remove(R.string.key_ns_profile_store_last_synced_timestamp) - - val lastDeviceStatusDbId = appRepository.getLastDeviceStatusId() - if (lastDeviceStatusDbId != null) sp.putLong(R.string.key_ns_device_status_last_synced_id, lastDeviceStatusDbId) - else sp.remove(R.string.key_ns_device_status_last_synced_id) - } - - override fun confirmLastBolusIdIfGreater(lastSynced: Long) { - if (lastSynced > sp.getLong(R.string.key_ns_bolus_last_synced_id, 0)) { - //aapsLogger.debug(LTag.NSCLIENT, "Setting Bolus data sync from $lastSynced") - sp.putLong(R.string.key_ns_bolus_last_synced_id, lastSynced) - } - } - - override tailrec suspend fun processChangedBoluses() { - if (isPaused) return - val lastDbId = appRepository.getLastBolusId() ?: 0L - var startId = sp.getLong(R.string.key_ns_bolus_last_synced_id, 0) - if (startId > lastDbId) { - sp.putLong(R.string.key_ns_bolus_last_synced_id, 0) - startId = 0 - } - queueCounter.bolusesRemaining = lastDbId - startId - rxBus.send(EventNSClientUpdateGuiQueue()) - appRepository.getNextSyncElementBolus(startId).blockingGet()?.let { bolus -> - aapsLogger.info(LTag.NSCLIENT, "Loading Bolus data Start: $startId ${bolus.first} forID: ${bolus.second.id} ") - when { - // new record with existing NS id => must be coming from NS => ignore - bolus.first.id == bolus.second.id && bolus.first.interfaceIDs.nightscoutId != null -> { - aapsLogger.info(LTag.NSCLIENT, "Ignoring Bolus. Loaded from NS: ${bolus.second.id} ") - confirmLastBolusIdIfGreater(bolus.second.id) - processChangedBoluses() - return - } - // only NsId changed, no need to upload - bolus.first.onlyNsIdAdded(bolus.second) -> { - aapsLogger.info(LTag.NSCLIENT, "Ignoring Bolus. Only NS id changed: ${bolus.second.id} ") - confirmLastBolusIdIfGreater(bolus.second.id) - processChangedBoluses() - return - } - // without nsId = create new - bolus.first.interfaceIDs.nightscoutId == null -> - activePlugin.activeNsClient?.nsAdd("treatments", DataSyncSelector.PairBolus(bolus.first, bolus.second.id), " $startId/$lastDbId") - // with nsId = update if it's modified record - bolus.first.interfaceIDs.nightscoutId != null && bolus.first.id != bolus.second.id -> - activePlugin.activeNsClient?.nsUpdate("treatments", DataSyncSelector.PairBolus(bolus.first, bolus.second.id), "$startId/$lastDbId") - } - return - } - } - - override fun confirmLastCarbsIdIfGreater(lastSynced: Long) { - if (lastSynced > sp.getLong(R.string.key_ns_carbs_last_synced_id, 0)) { - //aapsLogger.debug(LTag.NSCLIENT, "Setting Carbs data sync from $lastSynced") - sp.putLong(R.string.key_ns_carbs_last_synced_id, lastSynced) - } - } - - override tailrec suspend fun processChangedCarbs() { - if (isPaused) return - val lastDbId = appRepository.getLastCarbsId() ?: 0L - var startId = sp.getLong(R.string.key_ns_carbs_last_synced_id, 0) - if (startId > lastDbId) { - sp.putLong(R.string.key_ns_carbs_last_synced_id, 0) - startId = 0 - } - queueCounter.carbsRemaining = lastDbId - startId - rxBus.send(EventNSClientUpdateGuiQueue()) - appRepository.getNextSyncElementCarbs(startId).blockingGet()?.let { carb -> - aapsLogger.info(LTag.NSCLIENT, "Loading Carbs data Start: $startId ${carb.first} forID: ${carb.second.id} ") - when { - // new record with existing NS id => must be coming from NS => ignore - carb.first.id == carb.second.id && carb.first.interfaceIDs.nightscoutId != null -> { - aapsLogger.info(LTag.NSCLIENT, "Ignoring Carbs. Loaded from NS: ${carb.second.id} ") - confirmLastCarbsIdIfGreater(carb.second.id) - processChangedCarbs() - return - } - // only NsId changed, no need to upload - carb.first.onlyNsIdAdded(carb.second) -> { - aapsLogger.info(LTag.NSCLIENT, "Ignoring Carbs. Only NS id changed ID: ${carb.second.id} ") - confirmLastCarbsIdIfGreater(carb.second.id) - processChangedCarbs() - return - } - // without nsId = create new - carb.first.interfaceIDs.nightscoutId == null -> - activePlugin.activeNsClient?.nsAdd("treatments", DataSyncSelector.PairCarbs(carb.first, carb.second.id), "$startId/$lastDbId") - // with nsId = update if it's modified record - carb.first.interfaceIDs.nightscoutId != null && carb.first.id != carb.second.id -> - activePlugin.activeNsClient?.nsUpdate( - "treatments", - DataSyncSelector.PairCarbs(carb.first, carb.second.id), - "$startId/$lastDbId" - ) - } - return - } - } - - override fun confirmLastBolusCalculatorResultsIdIfGreater(lastSynced: Long) { - if (lastSynced > sp.getLong(R.string.key_ns_bolus_calculator_result_last_synced_id, 0)) { - //aapsLogger.debug(LTag.NSCLIENT, "Setting BolusCalculatorResult data sync from $lastSynced") - sp.putLong(R.string.key_ns_bolus_calculator_result_last_synced_id, lastSynced) - } - } - - override tailrec suspend fun processChangedBolusCalculatorResults() { - if (isPaused) return - val lastDbId = appRepository.getLastBolusCalculatorResultId() ?: 0L - var startId = sp.getLong(R.string.key_ns_bolus_calculator_result_last_synced_id, 0) - if (startId > lastDbId) { - sp.putLong(R.string.key_ns_bolus_calculator_result_last_synced_id, 0) - startId = 0 - } - queueCounter.bcrRemaining = lastDbId - startId - rxBus.send(EventNSClientUpdateGuiQueue()) - appRepository.getNextSyncElementBolusCalculatorResult(startId).blockingGet()?.let { bolusCalculatorResult -> - aapsLogger.info(LTag.NSCLIENT, "Loading BolusCalculatorResult data Start: $startId ${bolusCalculatorResult.first} forID: ${bolusCalculatorResult.second.id} ") - when { - // new record with existing NS id => must be coming from NS => ignore - bolusCalculatorResult.first.id == bolusCalculatorResult.second.id && bolusCalculatorResult.first.interfaceIDs.nightscoutId != null -> { - aapsLogger.info(LTag.NSCLIENT, "Ignoring BolusCalculatorResult. Loaded from NS: ${bolusCalculatorResult.second.id} ") - confirmLastBolusCalculatorResultsIdIfGreater(bolusCalculatorResult.second.id) - processChangedBolusCalculatorResults() - return - } - // only NsId changed, no need to upload - bolusCalculatorResult.first.onlyNsIdAdded(bolusCalculatorResult.second) -> { - aapsLogger.info(LTag.NSCLIENT, "Ignoring BolusCalculatorResult. Only NS id changed ID: ${bolusCalculatorResult.second.id} ") - confirmLastBolusCalculatorResultsIdIfGreater(bolusCalculatorResult.second.id) - processChangedBolusCalculatorResults() - return - } - // without nsId = create new - bolusCalculatorResult.first.interfaceIDs.nightscoutId == null -> - activePlugin.activeNsClient?.nsAdd("treatments", DataSyncSelector.PairBolusCalculatorResult(bolusCalculatorResult.first, bolusCalculatorResult.second.id), "$startId/$lastDbId") - // with nsId = update if it's modified record - bolusCalculatorResult.first.interfaceIDs.nightscoutId != null && bolusCalculatorResult.first.id != bolusCalculatorResult.second.id -> - activePlugin.activeNsClient?.nsUpdate("treatments", DataSyncSelector.PairBolusCalculatorResult(bolusCalculatorResult.first, bolusCalculatorResult.second.id), "$startId/$lastDbId") - } - return - } - } - - override fun confirmLastTempTargetsIdIfGreater(lastSynced: Long) { - if (lastSynced > sp.getLong(R.string.key_ns_temporary_target_last_synced_id, 0)) { - //aapsLogger.debug(LTag.NSCLIENT, "Setting TemporaryTarget data sync from $lastSynced") - sp.putLong(R.string.key_ns_temporary_target_last_synced_id, lastSynced) - } - } - - override tailrec suspend fun processChangedTempTargets() { - if (isPaused) return - val lastDbId = appRepository.getLastTempTargetId() ?: 0L - var startId = sp.getLong(R.string.key_ns_temporary_target_last_synced_id, 0) - if (startId > lastDbId) { - sp.putLong(R.string.key_ns_temporary_target_last_synced_id, 0) - startId = 0 - } - queueCounter.ttsRemaining = lastDbId - startId - rxBus.send(EventNSClientUpdateGuiQueue()) - appRepository.getNextSyncElementTemporaryTarget(startId).blockingGet()?.let { tt -> - aapsLogger.info(LTag.NSCLIENT, "Loading TemporaryTarget data Start: $startId ${tt.first} forID: ${tt.second.id} ") - when { - // new record with existing NS id => must be coming from NS => ignore - tt.first.id == tt.second.id && tt.first.interfaceIDs.nightscoutId != null -> { - aapsLogger.info(LTag.NSCLIENT, "Ignoring TemporaryTarget. Loaded from NS: ${tt.second.id} ") - confirmLastTempTargetsIdIfGreater(tt.second.id) - processChangedTempTargets() - return - } - // only NsId changed, no need to upload - tt.first.onlyNsIdAdded(tt.second) -> { - aapsLogger.info(LTag.NSCLIENT, "Ignoring TemporaryTarget. Only NS id changed ID: ${tt.second.id} ") - confirmLastTempTargetsIdIfGreater(tt.second.id) - processChangedTempTargets() - return - } - // without nsId = create new - tt.first.interfaceIDs.nightscoutId == null -> - activePlugin.activeNsClient?.nsAdd("treatments", DataSyncSelector.PairTemporaryTarget(tt.first, tt.second.id), "$startId/$lastDbId") - // existing with nsId = update - tt.first.interfaceIDs.nightscoutId != null -> - activePlugin.activeNsClient?.nsUpdate("treatments", DataSyncSelector.PairTemporaryTarget(tt.first, tt.second.id), "$startId/$lastDbId") - } - return - } - } - - override fun confirmLastFoodIdIfGreater(lastSynced: Long) { - if (lastSynced > sp.getLong(R.string.key_ns_food_last_synced_id, 0)) { - //aapsLogger.debug(LTag.NSCLIENT, "Setting Food data sync from $lastSynced") - sp.putLong(R.string.key_ns_food_last_synced_id, lastSynced) - } - } - - override tailrec suspend fun processChangedFoods() { - if (isPaused) return - val lastDbId = appRepository.getLastFoodId() ?: 0L - var startId = sp.getLong(R.string.key_ns_food_last_synced_id, 0) - if (startId > lastDbId) { - sp.putLong(R.string.key_ns_food_last_synced_id, 0) - startId = 0 - } - queueCounter.foodsRemaining = lastDbId - startId - rxBus.send(EventNSClientUpdateGuiQueue()) - appRepository.getNextSyncElementFood(startId).blockingGet()?.let { food -> - aapsLogger.info(LTag.NSCLIENT, "Loading Food data Start: $startId ${food.first} forID: ${food.second.id} ") - when { - // new record with existing NS id => must be coming from NS => ignore - food.first.id == food.second.id && food.first.interfaceIDs.nightscoutId != null -> { - aapsLogger.info(LTag.NSCLIENT, "Ignoring Food. Loaded from NS: ${food.second.id} ") - confirmLastFoodIdIfGreater(food.second.id) - processChangedFoods() - return - } - // only NsId changed, no need to upload - food.first.onlyNsIdAdded(food.second) -> { - aapsLogger.info(LTag.NSCLIENT, "Ignoring Food. Only NS id changed ID: ${food.second.id} ") - confirmLastFoodIdIfGreater(food.second.id) - processChangedFoods() - return - } - // without nsId = create new - food.first.interfaceIDs.nightscoutId == null -> - activePlugin.activeNsClient?.nsAdd("food", DataSyncSelector.PairFood(food.first, food.second.id), "$startId/$lastDbId") - // with nsId = update - food.first.interfaceIDs.nightscoutId != null -> - activePlugin.activeNsClient?.nsUpdate("food", DataSyncSelector.PairFood(food.first, food.second.id), "$startId/$lastDbId") - } - return - } - } - - override fun confirmLastGlucoseValueIdIfGreater(lastSynced: Long) { - if (lastSynced > sp.getLong(R.string.key_ns_glucose_value_last_synced_id, 0)) { - //aapsLogger.debug(LTag.NSCLIENT, "Setting GlucoseValue data sync from $lastSynced") - sp.putLong(R.string.key_ns_glucose_value_last_synced_id, lastSynced) - } - } - - override tailrec suspend fun processChangedGlucoseValues() { - if (isPaused) return - val lastDbId = appRepository.getLastGlucoseValueId() ?: 0L - var startId = sp.getLong(R.string.key_ns_glucose_value_last_synced_id, 0) - if (startId > lastDbId) { - sp.putLong(R.string.key_ns_glucose_value_last_synced_id, 0) - startId = 0 - } - queueCounter.gvsRemaining = lastDbId - startId - rxBus.send(EventNSClientUpdateGuiQueue()) - appRepository.getNextSyncElementGlucoseValue(startId).blockingGet()?.let { gv -> - aapsLogger.info(LTag.NSCLIENT, "Loading GlucoseValue data Start: $startId ${gv.first} forID: ${gv.second.id} ") - if (activePlugin.activeBgSource.shouldUploadToNs(gv.first)) { - when { - // new record with existing NS id => must be coming from NS => ignore - gv.first.id == gv.second.id && gv.first.interfaceIDs.nightscoutId != null -> { - aapsLogger.info(LTag.NSCLIENT, "Ignoring GlucoseValue. Loaded from NS: ${gv.second.id} ") - confirmLastGlucoseValueIdIfGreater(gv.second.id) - processChangedGlucoseValues() - return - } - // only NsId changed, no need to upload - gv.first.onlyNsIdAdded(gv.second) -> { - aapsLogger.info(LTag.NSCLIENT, "Ignoring GlucoseValue. Only NS id changed ID: ${gv.second.id} ") - confirmLastGlucoseValueIdIfGreater(gv.second.id) - processChangedGlucoseValues() - return - } - // without nsId = create new - gv.first.interfaceIDs.nightscoutId == null -> - activePlugin.activeNsClient?.nsAdd("entries", DataSyncSelector.PairGlucoseValue(gv.first, gv.second.id), "$startId/$lastDbId") - // with nsId = update - else -> // gv.first.interfaceIDs.nightscoutId != null - activePlugin.activeNsClient?.nsUpdate("entries", DataSyncSelector.PairGlucoseValue(gv.first, gv.second.id), "$startId/$lastDbId") - } - } else { - confirmLastGlucoseValueIdIfGreater(gv.second.id) - processChangedGlucoseValues() - return - } - } - } - - override fun confirmLastTherapyEventIdIfGreater(lastSynced: Long) { - if (lastSynced > sp.getLong(R.string.key_ns_therapy_event_last_synced_id, 0)) { - //aapsLogger.debug(LTag.NSCLIENT, "Setting TherapyEvents data sync from $lastSynced") - sp.putLong(R.string.key_ns_therapy_event_last_synced_id, lastSynced) - } - } - - override tailrec suspend fun processChangedTherapyEvents() { - if (isPaused) return - val lastDbId = appRepository.getLastTherapyEventId() ?: 0L - var startId = sp.getLong(R.string.key_ns_therapy_event_last_synced_id, 0) - if (startId > lastDbId) { - sp.putLong(R.string.key_ns_therapy_event_last_synced_id, 0) - startId = 0 - } - queueCounter.tesRemaining = lastDbId - startId - rxBus.send(EventNSClientUpdateGuiQueue()) - appRepository.getNextSyncElementTherapyEvent(startId).blockingGet()?.let { te -> - aapsLogger.info(LTag.NSCLIENT, "Loading TherapyEvents data Start: $startId ${te.first} forID: ${te.second.id} ") - when { - // new record with existing NS id => must be coming from NS => ignore - te.first.id == te.second.id && te.first.interfaceIDs.nightscoutId != null -> { - aapsLogger.info(LTag.NSCLIENT, "Ignoring TherapyEvent. Loaded from NS: ${te.second.id} ") - confirmLastTherapyEventIdIfGreater(te.second.id) - processChangedTherapyEvents() - return - } - // only NsId changed, no need to upload - te.first.onlyNsIdAdded(te.second) -> { - aapsLogger.info(LTag.NSCLIENT, "Ignoring TherapyEvent. Only NS id changed ID: ${te.second.id} ") - confirmLastTherapyEventIdIfGreater(te.second.id) - processChangedTherapyEvents() - return - } - // without nsId = create new - te.first.interfaceIDs.nightscoutId == null -> - activePlugin.activeNsClient?.nsAdd("treatments", DataSyncSelector.PairTherapyEvent(te.first, te.second.id), "$startId/$lastDbId") - // nsId = update - te.first.interfaceIDs.nightscoutId != null -> - activePlugin.activeNsClient?.nsUpdate("treatments", DataSyncSelector.PairTherapyEvent(te.first, te.second.id), "$startId/$lastDbId") - } - return - } - } - - override fun confirmLastDeviceStatusIdIfGreater(lastSynced: Long) { - if (lastSynced > sp.getLong(R.string.key_ns_device_status_last_synced_id, 0)) { - //aapsLogger.debug(LTag.NSCLIENT, "Setting DeviceStatus data sync from $lastSynced") - sp.putLong(R.string.key_ns_device_status_last_synced_id, lastSynced) - } - } - - override suspend fun processChangedDeviceStatuses() { - if (isPaused) return - val lastDbId = appRepository.getLastDeviceStatusId() ?: 0L - var startId = sp.getLong(R.string.key_ns_device_status_last_synced_id, 0) - if (startId > lastDbId) { - sp.putLong(R.string.key_ns_device_status_last_synced_id, 0) - startId = 0 - } - queueCounter.dssRemaining = lastDbId - startId - rxBus.send(EventNSClientUpdateGuiQueue()) - appRepository.getNextSyncElementDeviceStatus(startId).blockingGet()?.let { deviceStatus -> - aapsLogger.info(LTag.NSCLIENT, "Loading DeviceStatus data Start: $startId $deviceStatus") - when { - // without nsId = create new - deviceStatus.interfaceIDs.nightscoutId == null -> - activePlugin.activeNsClient?.nsAdd("devicestatus", DataSyncSelector.PairDeviceStatus(deviceStatus, lastDbId), "$startId/$lastDbId") - // with nsId = ignore - deviceStatus.interfaceIDs.nightscoutId != null -> Any() - } - return - } - } - - override fun confirmLastTemporaryBasalIdIfGreater(lastSynced: Long) { - if (lastSynced > sp.getLong(R.string.key_ns_temporary_basal_last_synced_id, 0)) { - //aapsLogger.debug(LTag.NSCLIENT, "Setting TemporaryBasal data sync from $lastSynced") - sp.putLong(R.string.key_ns_temporary_basal_last_synced_id, lastSynced) - } - } - - override tailrec suspend fun processChangedTemporaryBasals() { - if (isPaused) return - val lastDbId = appRepository.getLastTemporaryBasalId() ?: 0L - var startId = sp.getLong(R.string.key_ns_temporary_basal_last_synced_id, 0) - if (startId > lastDbId) { - sp.putLong(R.string.key_ns_temporary_basal_last_synced_id, 0) - startId = 0 - } - queueCounter.tbrsRemaining = lastDbId - startId - rxBus.send(EventNSClientUpdateGuiQueue()) - appRepository.getNextSyncElementTemporaryBasal(startId).blockingGet()?.let { tb -> - aapsLogger.info(LTag.NSCLIENT, "Loading TemporaryBasal data Start: $startId ${tb.first} forID: ${tb.second.id} ") - val profile = profileFunction.getProfile(tb.first.timestamp) - if (profile != null) { - when { - // new record with existing NS id => must be coming from NS => ignore - tb.first.id == tb.second.id && tb.first.interfaceIDs.nightscoutId != null -> { - aapsLogger.info(LTag.NSCLIENT, "Ignoring TemporaryBasal. Loaded from NS: ${tb.second.id} ") - confirmLastTemporaryBasalIdIfGreater(tb.second.id) - processChangedTemporaryBasals() - return - } - // only NsId changed, no need to upload - tb.first.onlyNsIdAdded(tb.second) -> { - aapsLogger.info(LTag.NSCLIENT, "Ignoring TemporaryBasal. Only NS id changed ID: ${tb.second.id} ") - confirmLastTemporaryBasalIdIfGreater(tb.second.id) - processChangedTemporaryBasals() - return - } - // without nsId = create new - tb.first.interfaceIDs.nightscoutId == null -> - activePlugin.activeNsClient?.nsAdd("treatments", DataSyncSelector.PairTemporaryBasal(tb.first, tb.second.id), "$startId/$lastDbId", profile) - // with nsId = update - tb.first.interfaceIDs.nightscoutId != null -> - activePlugin.activeNsClient?.nsUpdate("treatments", DataSyncSelector.PairTemporaryBasal(tb.first, tb.second.id), "$startId/$lastDbId", profile) - } - return - } else { - aapsLogger.info(LTag.NSCLIENT, "Ignoring TemporaryBasal. No profile: ${tb.second.id} ") - confirmLastTemporaryBasalIdIfGreater(tb.second.id) - processChangedTemporaryBasals() - return - } - } - } - - override fun confirmLastExtendedBolusIdIfGreater(lastSynced: Long) { - if (lastSynced > sp.getLong(R.string.key_ns_extended_bolus_last_synced_id, 0)) { - //aapsLogger.debug(LTag.NSCLIENT, "Setting ExtendedBolus data sync from $lastSynced") - sp.putLong(R.string.key_ns_extended_bolus_last_synced_id, lastSynced) - } - } - - override tailrec suspend fun processChangedExtendedBoluses() { - if (isPaused) return - val lastDbId = appRepository.getLastExtendedBolusId() ?: 0L - var startId = sp.getLong(R.string.key_ns_extended_bolus_last_synced_id, 0) - if (startId > lastDbId) { - sp.putLong(R.string.key_ns_extended_bolus_last_synced_id, 0) - startId = 0 - } - queueCounter.ebsRemaining = lastDbId - startId - rxBus.send(EventNSClientUpdateGuiQueue()) - appRepository.getNextSyncElementExtendedBolus(startId).blockingGet()?.let { eb -> - aapsLogger.info(LTag.NSCLIENT, "Loading ExtendedBolus data Start: $startId ${eb.first} forID: ${eb.second.id} ") - val profile = profileFunction.getProfile(eb.first.timestamp) - if (profile != null) { - when { - // new record with existing NS id => must be coming from NS => ignore - eb.first.id == eb.second.id && eb.first.interfaceIDs.nightscoutId != null -> { - aapsLogger.info(LTag.NSCLIENT, "Ignoring ExtendedBolus. Loaded from NS: ${eb.second.id} ") - confirmLastExtendedBolusIdIfGreater(eb.second.id) - processChangedExtendedBoluses() - return - } - // only NsId changed, no need to upload - eb.first.onlyNsIdAdded(eb.second) -> { - aapsLogger.info(LTag.NSCLIENT, "Ignoring ExtendedBolus. Only NS id changed ID: ${eb.second.id} ") - confirmLastExtendedBolusIdIfGreater(eb.second.id) - processChangedExtendedBoluses() - return - } - // without nsId = create new - eb.first.interfaceIDs.nightscoutId == null -> - activePlugin.activeNsClient?.nsAdd("treatments", DataSyncSelector.PairExtendedBolus(eb.first, eb.second.id), "$startId/$lastDbId", profile) - // with nsId = update - eb.first.interfaceIDs.nightscoutId != null -> - activePlugin.activeNsClient?.nsUpdate("treatments", DataSyncSelector.PairExtendedBolus(eb.first, eb.second.id), "$startId/$lastDbId", profile) - } - return - } else { - aapsLogger.info(LTag.NSCLIENT, "Ignoring ExtendedBolus. No profile: ${eb.second.id} ") - confirmLastExtendedBolusIdIfGreater(eb.second.id) - processChangedExtendedBoluses() - return - } - } - } - - override fun confirmLastProfileSwitchIdIfGreater(lastSynced: Long) { - if (lastSynced > sp.getLong(R.string.key_ns_profile_switch_last_synced_id, 0)) { - //aapsLogger.debug(LTag.NSCLIENT, "Setting ProfileSwitch data sync from $lastSynced") - sp.putLong(R.string.key_ns_profile_switch_last_synced_id, lastSynced) - } - } - - override tailrec suspend fun processChangedProfileSwitches() { - if (isPaused) return - val lastDbId = appRepository.getLastProfileSwitchId() ?: 0L - var startId = sp.getLong(R.string.key_ns_profile_switch_last_synced_id, 0) - if (startId > lastDbId) { - sp.putLong(R.string.key_ns_profile_switch_last_synced_id, 0) - startId = 0 - } - queueCounter.pssRemaining = lastDbId - startId - rxBus.send(EventNSClientUpdateGuiQueue()) - appRepository.getNextSyncElementProfileSwitch(startId).blockingGet()?.let { ps -> - aapsLogger.info(LTag.NSCLIENT, "Loading ProfileSwitch data Start: $startId ${ps.first} forID: ${ps.second.id} ") - when { - // new record with existing NS id => must be coming from NS => ignore - ps.first.id == ps.second.id && ps.first.interfaceIDs.nightscoutId != null -> { - aapsLogger.info(LTag.NSCLIENT, "Ignoring ProfileSwitch. Loaded from NS: ${ps.second.id} ") - confirmLastProfileSwitchIdIfGreater(ps.second.id) - processChangedProfileSwitches() - return - } - // only NsId changed, no need to upload - ps.first.onlyNsIdAdded(ps.second) -> { - aapsLogger.info(LTag.NSCLIENT, "Ignoring ProfileSwitch. Only NS id changed ID: ${ps.second.id} ") - confirmLastProfileSwitchIdIfGreater(ps.second.id) - processChangedProfileSwitches() - return - } - // without nsId = create new - ps.first.interfaceIDs.nightscoutId == null -> - activePlugin.activeNsClient?.nsAdd("treatments", DataSyncSelector.PairProfileSwitch(ps.first, ps.second.id), "$startId/$lastDbId") - // with nsId = update - ps.first.interfaceIDs.nightscoutId != null -> - activePlugin.activeNsClient?.nsUpdate("treatments", DataSyncSelector.PairProfileSwitch(ps.first, ps.second.id), "$startId/$lastDbId") - } - return - } - } - - override fun confirmLastEffectiveProfileSwitchIdIfGreater(lastSynced: Long) { - if (lastSynced > sp.getLong(R.string.key_ns_effective_profile_switch_last_synced_id, 0)) { - //aapsLogger.debug(LTag.NSCLIENT, "Setting EffectiveProfileSwitch data sync from $lastSynced") - sp.putLong(R.string.key_ns_effective_profile_switch_last_synced_id, lastSynced) - } - } - - override tailrec suspend fun processChangedEffectiveProfileSwitches() { - if (isPaused) return - val lastDbId = appRepository.getLastEffectiveProfileSwitchId() ?: 0L - var startId = sp.getLong(R.string.key_ns_effective_profile_switch_last_synced_id, 0) - if (startId > lastDbId) { - sp.putLong(R.string.key_ns_effective_profile_switch_last_synced_id, 0) - startId = 0 - } - queueCounter.epssRemaining = lastDbId - startId - rxBus.send(EventNSClientUpdateGuiQueue()) - appRepository.getNextSyncElementEffectiveProfileSwitch(startId).blockingGet()?.let { ps -> - aapsLogger.info(LTag.NSCLIENT, "Loading EffectiveProfileSwitch data Start: $startId ${ps.first} forID: ${ps.second.id} ") - when { - // new record with existing NS id => must be coming from NS => ignore - ps.first.id == ps.second.id && ps.first.interfaceIDs.nightscoutId != null -> { - aapsLogger.info(LTag.NSCLIENT, "Ignoring EffectiveProfileSwitch. Loaded from NS: ${ps.second.id} ") - confirmLastEffectiveProfileSwitchIdIfGreater(ps.second.id) - processChangedEffectiveProfileSwitches() - return - } - // only NsId changed, no need to upload - ps.first.onlyNsIdAdded(ps.second) -> { - aapsLogger.info(LTag.NSCLIENT, "Ignoring EffectiveProfileSwitch. Only NS id changed ID: ${ps.second.id} ") - confirmLastEffectiveProfileSwitchIdIfGreater(ps.second.id) - processChangedEffectiveProfileSwitches() - return - } - // without nsId = create new - ps.first.interfaceIDs.nightscoutId == null -> - activePlugin.activeNsClient?.nsAdd("treatments", DataSyncSelector.PairEffectiveProfileSwitch(ps.first, ps.second.id), "$startId/$lastDbId") - // with nsId = update - ps.first.interfaceIDs.nightscoutId != null -> - activePlugin.activeNsClient?.nsUpdate("treatments", DataSyncSelector.PairEffectiveProfileSwitch(ps.first, ps.second.id), "$startId/$lastDbId") - } - return - } - } - - override fun confirmLastOfflineEventIdIfGreater(lastSynced: Long) { - if (lastSynced > sp.getLong(R.string.key_ns_offline_event_last_synced_id, 0)) { - //aapsLogger.debug(LTag.NSCLIENT, "Setting OfflineEvent data sync from $lastSynced") - sp.putLong(R.string.key_ns_offline_event_last_synced_id, lastSynced) - } - } - - override tailrec suspend fun processChangedOfflineEvents() { - if (isPaused) return - val lastDbId = appRepository.getLastOfflineEventId() ?: 0L - var startId = sp.getLong(R.string.key_ns_offline_event_last_synced_id, 0) - if (startId > lastDbId) { - sp.putLong(R.string.key_ns_offline_event_last_synced_id, 0) - startId = 0 - } - queueCounter.oesRemaining = lastDbId - startId - rxBus.send(EventNSClientUpdateGuiQueue()) - appRepository.getNextSyncElementOfflineEvent(startId).blockingGet()?.let { oe -> - aapsLogger.info(LTag.NSCLIENT, "Loading OfflineEvent data Start: $startId ${oe.first} forID: ${oe.second.id} ") - when { - // new record with existing NS id => must be coming from NS => ignore - oe.first.id == oe.second.id && oe.first.interfaceIDs.nightscoutId != null -> { - aapsLogger.info(LTag.NSCLIENT, "Ignoring OfflineEvent. Loaded from NS: ${oe.second.id} ") - confirmLastOfflineEventIdIfGreater(oe.second.id) - processChangedOfflineEvents() - return - } - // only NsId changed, no need to upload - oe.first.onlyNsIdAdded(oe.second) -> { - aapsLogger.info(LTag.NSCLIENT, "Ignoring OfflineEvent. Only NS id changed ID: ${oe.second.id} ") - confirmLastOfflineEventIdIfGreater(oe.second.id) - processChangedOfflineEvents() - return - } - // without nsId = create new - oe.first.interfaceIDs.nightscoutId == null -> - activePlugin.activeNsClient?.nsAdd("treatments", DataSyncSelector.PairOfflineEvent(oe.first, oe.second.id), "$startId/$lastDbId") - // existing with nsId = update - oe.first.interfaceIDs.nightscoutId != null -> - activePlugin.activeNsClient?.nsUpdate("treatments", DataSyncSelector.PairOfflineEvent(oe.first, oe.second.id), "$startId/$lastDbId") - } - return - } - } - - override fun confirmLastProfileStore(lastSynced: Long) { - sp.putLong(R.string.key_ns_profile_store_last_synced_timestamp, lastSynced) - } - - override suspend fun processChangedProfileStore() { - if (isPaused) return - val lastSync = sp.getLong(R.string.key_ns_profile_store_last_synced_timestamp, 0) - val lastChange = sp.getLong(info.nightscout.core.utils.R.string.key_local_profile_last_change, 0) - if (lastChange == 0L) return - if (lastChange > lastSync) { - if (activePlugin.activeProfileSource.profile?.allProfilesValid != true) return - val profileStore = activePlugin.activeProfileSource.profile - val profileJson = profileStore?.data ?: return - // add for v3 - if (JsonHelper.safeGetLongAllowNull(profileJson, "date") == null) - profileJson.put("date", profileStore.getStartDate()) - activePlugin.activeNsClient?.nsAdd("profile", DataSyncSelector.PairProfileStore(profileJson, dateUtil.now()), "") - } - } -} \ No newline at end of file diff --git a/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclient/NSClientPlugin.kt b/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclient/NSClientPlugin.kt index c02b6b51f2..711106bedd 100644 --- a/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclient/NSClientPlugin.kt +++ b/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclient/NSClientPlugin.kt @@ -5,7 +5,6 @@ import android.content.Context import android.content.Intent import android.content.ServiceConnection import android.os.IBinder -import android.provider.ContactsContract import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceScreen import androidx.preference.SwitchPreference @@ -24,7 +23,6 @@ import info.nightscout.interfaces.profile.Profile import info.nightscout.interfaces.profile.ProfileFunction import info.nightscout.interfaces.source.DoingOwnUploadSource import info.nightscout.interfaces.sync.DataSyncSelector -import info.nightscout.interfaces.sync.DataSyncSelectorV1 import info.nightscout.interfaces.sync.NsClient import info.nightscout.interfaces.sync.Sync import info.nightscout.plugins.sync.R diff --git a/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclient/services/NSClientService.kt b/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclient/services/NSClientService.kt index d68215364a..c8f4bf44f9 100644 --- a/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclient/services/NSClientService.kt +++ b/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclient/services/NSClientService.kt @@ -25,7 +25,6 @@ import info.nightscout.interfaces.notifications.Notification import info.nightscout.interfaces.nsclient.NSAlarm import info.nightscout.interfaces.nsclient.NSSettingsStatus import info.nightscout.interfaces.nsclient.StoreDataForDb -import info.nightscout.interfaces.sync.DataSyncSelectorV1 import info.nightscout.interfaces.ui.UiInteraction import info.nightscout.interfaces.utils.JsonHelper.safeGetString import info.nightscout.interfaces.utils.JsonHelper.safeGetStringAllowNull @@ -34,6 +33,7 @@ import info.nightscout.plugins.sync.nsShared.NsIncomingDataProcessor import info.nightscout.plugins.sync.nsShared.events.EventConnectivityOptionChanged import info.nightscout.plugins.sync.nsShared.events.EventNSClientStatus import info.nightscout.plugins.sync.nsShared.events.EventNSClientUpdateGuiStatus +import info.nightscout.plugins.sync.nsclient.DataSyncSelectorV1 import info.nightscout.plugins.sync.nsclient.NSClientPlugin import info.nightscout.plugins.sync.nsclient.acks.NSAddAck import info.nightscout.plugins.sync.nsclient.acks.NSAuthAck @@ -179,6 +179,18 @@ import javax.inject.Inject .toObservable(EventNewHistoryData::class.java) .observeOn(aapsSchedulers.io) .subscribe({ resend("NEW_DATA") }, fabricPrivacy::logException) + disposable += rxBus + .toObservable(EventDeviceStatusChange::class.java) + .observeOn(aapsSchedulers.io) + .subscribe({ resend("EventDeviceStatusChange") }, fabricPrivacy::logException) + disposable += rxBus + .toObservable(EventTherapyEventChange::class.java) + .observeOn(aapsSchedulers.io) + .subscribe({ resend("EventTherapyEventChange") }, fabricPrivacy::logException) + disposable += rxBus + .toObservable(EventOfflineChange::class.java) + .observeOn(aapsSchedulers.io) + .subscribe({ resend("EventOfflineChange") }, fabricPrivacy::logException) } override fun onDestroy() { @@ -541,6 +553,7 @@ import javax.inject.Inject } } rxBus.send(EventNSClientNewLog("◄ LAST", dateUtil.dateAndTimeString(latestDateInReceivedData))) + resend("LAST") } catch (e: JSONException) { aapsLogger.error("Unhandled exception", e) } @@ -551,7 +564,7 @@ import javax.inject.Inject } } - fun dbUpdate(collection: String, _id: String?, data: JSONObject?, originalObject: Any, progress: String) { + fun dbUpdate(collection: String, @Suppress("LocalVariableName") _id: String?, data: JSONObject?, originalObject: Any, progress: String) { try { if (_id == null) return if (!isConnected || !hasWriteAuth) return @@ -595,10 +608,10 @@ import javax.inject.Inject if (!isConnected || !hasWriteAuth) return@runBlocking scope.async { if (socket?.connected() != true) return@async - if (lastAckTime > System.currentTimeMillis() - 10 * 1000L) { - aapsLogger.debug(LTag.NSCLIENT, "Skipping resend by lastAckTime: " + (System.currentTimeMillis() - lastAckTime) / 1000L + " sec") - return@async - } + // if (lastAckTime > System.currentTimeMillis() - 10 * 1000L) { + // aapsLogger.debug(LTag.NSCLIENT, "Skipping resend by lastAckTime: " + (System.currentTimeMillis() - lastAckTime) / 1000L + " sec") + // return@async + // } rxBus.send(EventNSClientNewLog("● QUEUE", "Resend started: $reason")) dataSyncSelectorV1.doUpload() rxBus.send(EventNSClientNewLog("● QUEUE", "Resend ended: $reason")) diff --git a/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclient/workers/NSClientAddAckWorker.kt b/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclient/workers/NSClientAddAckWorker.kt index 5575b25e66..947d996ad3 100644 --- a/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclient/workers/NSClientAddAckWorker.kt +++ b/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclient/workers/NSClientAddAckWorker.kt @@ -4,6 +4,7 @@ import android.content.Context import android.os.SystemClock import androidx.work.WorkerParameters import androidx.work.workDataOf +import info.nightscout.core.utils.notify import info.nightscout.core.utils.receivers.DataWorkerStorage import info.nightscout.core.utils.worker.LoggingWorker import info.nightscout.database.impl.AppRepository @@ -22,7 +23,6 @@ import info.nightscout.interfaces.sync.DataSyncSelector.PairProfileSwitch import info.nightscout.interfaces.sync.DataSyncSelector.PairTemporaryBasal import info.nightscout.interfaces.sync.DataSyncSelector.PairTemporaryTarget import info.nightscout.interfaces.sync.DataSyncSelector.PairTherapyEvent -import info.nightscout.interfaces.sync.DataSyncSelectorV1 import info.nightscout.plugins.sync.R import info.nightscout.plugins.sync.nsclient.acks.NSAddAck import info.nightscout.rx.AapsSchedulers @@ -40,7 +40,6 @@ class NSClientAddAckWorker( @Inject lateinit var dataWorkerStorage: DataWorkerStorage @Inject lateinit var repository: AppRepository @Inject lateinit var rxBus: RxBus - @Inject lateinit var dataSyncSelectorV1: DataSyncSelectorV1 @Inject lateinit var aapsSchedulers: AapsSchedulers @Inject lateinit var sp: SP @Inject lateinit var storeDataForDb: StoreDataForDb @@ -60,152 +59,128 @@ class NSClientAddAckWorker( is PairTemporaryTarget -> { val pair = ack.originalObject pair.value.interfaceIDs.nightscoutId = ack.id + pair.confirmed = true storeDataForDb.nsIdTemporaryTargets.add(pair.value) - dataSyncSelectorV1.confirmLastTempTargetsIdIfGreater(pair.id) storeDataForDb.scheduleNsIdUpdate() rxBus.send(EventNSClientNewLog("◄ DBADD", "Acked TemporaryTarget " + pair.value.interfaceIDs.nightscoutId)) - // Send new if waiting - dataSyncSelectorV1.processChangedTempTargets() } is PairGlucoseValue -> { val pair = ack.originalObject pair.value.interfaceIDs.nightscoutId = ack.id + pair.confirmed = true storeDataForDb.nsIdGlucoseValues.add(pair.value) - dataSyncSelectorV1.confirmLastGlucoseValueIdIfGreater(pair.id) storeDataForDb.scheduleNsIdUpdate() rxBus.send(EventNSClientNewLog("◄ DBADD", "Acked GlucoseValue " + pair.value.interfaceIDs.nightscoutId)) - // Send new if waiting - dataSyncSelectorV1.processChangedGlucoseValues() } is PairFood -> { val pair = ack.originalObject pair.value.interfaceIDs.nightscoutId = ack.id + pair.confirmed = true storeDataForDb.nsIdFoods.add(pair.value) - dataSyncSelectorV1.confirmLastFoodIdIfGreater(pair.id) storeDataForDb.scheduleNsIdUpdate() rxBus.send(EventNSClientNewLog("◄ DBADD", "Acked Food " + pair.value.interfaceIDs.nightscoutId)) // Send new if waiting - dataSyncSelectorV1.processChangedFoods() } is PairTherapyEvent -> { val pair = ack.originalObject pair.value.interfaceIDs.nightscoutId = ack.id + pair.confirmed = true storeDataForDb.nsIdTherapyEvents.add(pair.value) - dataSyncSelectorV1.confirmLastTherapyEventIdIfGreater(pair.id) storeDataForDb.scheduleNsIdUpdate() rxBus.send(EventNSClientNewLog("◄ DBADD", "Acked TherapyEvent " + pair.value.interfaceIDs.nightscoutId)) - // Send new if waiting - dataSyncSelectorV1.processChangedTherapyEvents() } is PairBolus -> { val pair = ack.originalObject pair.value.interfaceIDs.nightscoutId = ack.id + pair.confirmed = true storeDataForDb.nsIdBoluses.add(pair.value) - dataSyncSelectorV1.confirmLastBolusIdIfGreater(pair.id) storeDataForDb.scheduleNsIdUpdate() rxBus.send(EventNSClientNewLog("◄ DBADD", "Acked Bolus " + pair.value.interfaceIDs.nightscoutId)) - // Send new if waiting - dataSyncSelectorV1.processChangedBoluses() } is PairCarbs -> { val pair = ack.originalObject pair.value.interfaceIDs.nightscoutId = ack.id + pair.confirmed = true storeDataForDb.nsIdCarbs.add(pair.value) - dataSyncSelectorV1.confirmLastCarbsIdIfGreater(pair.id) storeDataForDb.scheduleNsIdUpdate() rxBus.send(EventNSClientNewLog("◄ DBADD", "Acked Carbs " + pair.value.interfaceIDs.nightscoutId)) - // Send new if waiting - dataSyncSelectorV1.processChangedCarbs() } is PairBolusCalculatorResult -> { val pair = ack.originalObject pair.value.interfaceIDs.nightscoutId = ack.id storeDataForDb.nsIdBolusCalculatorResults.add(pair.value) - dataSyncSelectorV1.confirmLastBolusCalculatorResultsIdIfGreater(pair.id) storeDataForDb.scheduleNsIdUpdate() rxBus.send(EventNSClientNewLog("◄ DBADD", "Acked BolusCalculatorResult " + pair.value.interfaceIDs.nightscoutId)) - // Send new if waiting - dataSyncSelectorV1.processChangedBolusCalculatorResults() } is PairTemporaryBasal -> { val pair = ack.originalObject pair.value.interfaceIDs.nightscoutId = ack.id + pair.confirmed = true storeDataForDb.nsIdTemporaryBasals.add(pair.value) - dataSyncSelectorV1.confirmLastTemporaryBasalIdIfGreater(pair.id) storeDataForDb.scheduleNsIdUpdate() rxBus.send(EventNSClientNewLog("◄ DBADD", "Acked TemporaryBasal " + pair.value.interfaceIDs.nightscoutId)) - // Send new if waiting - dataSyncSelectorV1.processChangedTemporaryBasals() } is PairExtendedBolus -> { val pair = ack.originalObject pair.value.interfaceIDs.nightscoutId = ack.id + pair.confirmed = true storeDataForDb.nsIdExtendedBoluses.add(pair.value) - dataSyncSelectorV1.confirmLastExtendedBolusIdIfGreater(pair.id) storeDataForDb.scheduleNsIdUpdate() rxBus.send(EventNSClientNewLog("◄ DBADD", "Acked ExtendedBolus " + pair.value.interfaceIDs.nightscoutId)) - // Send new if waiting - dataSyncSelectorV1.processChangedExtendedBoluses() } is PairProfileSwitch -> { val pair = ack.originalObject pair.value.interfaceIDs.nightscoutId = ack.id + pair.confirmed = true storeDataForDb.nsIdProfileSwitches.add(pair.value) - dataSyncSelectorV1.confirmLastProfileSwitchIdIfGreater(pair.id) storeDataForDb.scheduleNsIdUpdate() rxBus.send(EventNSClientNewLog("◄ DBADD", "Acked ProfileSwitch " + pair.value.interfaceIDs.nightscoutId)) - // Send new if waiting - dataSyncSelectorV1.processChangedProfileSwitches() } is PairEffectiveProfileSwitch -> { val pair = ack.originalObject pair.value.interfaceIDs.nightscoutId = ack.id + pair.confirmed = true storeDataForDb.nsIdEffectiveProfileSwitches.add(pair.value) - dataSyncSelectorV1.confirmLastEffectiveProfileSwitchIdIfGreater(pair.id) storeDataForDb.scheduleNsIdUpdate() rxBus.send(EventNSClientNewLog("◄ DBADD", "Acked EffectiveProfileSwitch " + pair.value.interfaceIDs.nightscoutId)) - // Send new if waiting - dataSyncSelectorV1.processChangedEffectiveProfileSwitches() } is DataSyncSelector.PairDeviceStatus -> { val pair = ack.originalObject pair.value.interfaceIDs.nightscoutId = ack.id + pair.confirmed = true storeDataForDb.nsIdDeviceStatuses.add(pair.value) - dataSyncSelectorV1.confirmLastDeviceStatusIdIfGreater(pair.value.id) storeDataForDb.scheduleNsIdUpdate() rxBus.send(EventNSClientNewLog("◄ DBADD", "Acked DeviceStatus " + pair.value.interfaceIDs.nightscoutId)) - // Send new if waiting - dataSyncSelectorV1.processChangedDeviceStatuses() } is PairProfileStore -> { - dataSyncSelectorV1.confirmLastProfileStore(ack.originalObject.id) + val pair = ack.originalObject + pair.confirmed = true rxBus.send(EventNSClientNewLog("◄ DBADD", "Acked ProfileStore " + ack.id)) } is PairOfflineEvent -> { val pair = ack.originalObject pair.value.interfaceIDs.nightscoutId = ack.id + pair.confirmed = true storeDataForDb.nsIdOfflineEvents.add(pair.value) - dataSyncSelectorV1.confirmLastOfflineEventIdIfGreater(pair.id) storeDataForDb.scheduleNsIdUpdate() rxBus.send(EventNSClientNewLog("◄ DBADD", "Acked OfflineEvent " + pair.value.interfaceIDs.nightscoutId)) - // Send new if waiting - dataSyncSelectorV1.processChangedOfflineEvents() } } + ack.originalObject?.let { synchronized(it) { it.notify() } } return ret } } \ No newline at end of file diff --git a/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclient/workers/NSClientUpdateRemoveAckWorker.kt b/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclient/workers/NSClientUpdateRemoveAckWorker.kt index 157b597d31..49d135cafa 100644 --- a/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclient/workers/NSClientUpdateRemoveAckWorker.kt +++ b/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclient/workers/NSClientUpdateRemoveAckWorker.kt @@ -3,6 +3,7 @@ package info.nightscout.plugins.sync.nsclient.workers import android.content.Context import androidx.work.WorkerParameters import androidx.work.workDataOf +import info.nightscout.core.utils.notify import info.nightscout.core.utils.receivers.DataWorkerStorage import info.nightscout.core.utils.worker.LoggingWorker import info.nightscout.database.impl.AppRepository @@ -18,7 +19,6 @@ import info.nightscout.interfaces.sync.DataSyncSelector.PairProfileSwitch import info.nightscout.interfaces.sync.DataSyncSelector.PairTemporaryBasal import info.nightscout.interfaces.sync.DataSyncSelector.PairTemporaryTarget import info.nightscout.interfaces.sync.DataSyncSelector.PairTherapyEvent -import info.nightscout.interfaces.sync.DataSyncSelectorV1 import info.nightscout.plugins.sync.nsclient.acks.NSUpdateAck import info.nightscout.rx.AapsSchedulers import info.nightscout.rx.bus.RxBus @@ -34,7 +34,6 @@ class NSClientUpdateRemoveAckWorker( @Inject lateinit var dataWorkerStorage: DataWorkerStorage @Inject lateinit var repository: AppRepository @Inject lateinit var rxBus: RxBus - @Inject lateinit var dataSyncSelectorV1: DataSyncSelectorV1 @Inject lateinit var aapsSchedulers: AapsSchedulers override suspend fun doWorkAndLog(): Result { @@ -47,112 +46,89 @@ class NSClientUpdateRemoveAckWorker( when (ack.originalObject) { is PairTemporaryTarget -> { val pair = ack.originalObject - dataSyncSelectorV1.confirmLastTempTargetsIdIfGreater(pair.id) + pair.confirmed = true rxBus.send(EventNSClientNewLog("◄ DBUPDATE", "Acked TemporaryTarget" + ack._id)) - // Send new if waiting - dataSyncSelectorV1.processChangedTempTargets() ret = Result.success(workDataOf("ProcessedData" to pair.toString())) } is PairGlucoseValue -> { val pair = ack.originalObject - dataSyncSelectorV1.confirmLastGlucoseValueIdIfGreater(pair.id) + pair.confirmed = true rxBus.send(EventNSClientNewLog("◄ DBUPDATE", "Acked GlucoseValue " + ack._id)) - // Send new if waiting - dataSyncSelectorV1.processChangedGlucoseValues() ret = Result.success(workDataOf("ProcessedData" to pair.toString())) } is PairFood -> { val pair = ack.originalObject - dataSyncSelectorV1.confirmLastFoodIdIfGreater(pair.id) + pair.confirmed = true rxBus.send(EventNSClientNewLog("◄ DBUPDATE", "Acked Food " + ack._id)) - // Send new if waiting - dataSyncSelectorV1.processChangedFoods() ret = Result.success(workDataOf("ProcessedData" to pair.toString())) } is PairTherapyEvent -> { val pair = ack.originalObject - dataSyncSelectorV1.confirmLastTherapyEventIdIfGreater(pair.id) + pair.confirmed = true rxBus.send(EventNSClientNewLog("◄ DBUPDATE", "Acked TherapyEvent " + ack._id)) - // Send new if waiting - dataSyncSelectorV1.processChangedTherapyEvents() ret = Result.success(workDataOf("ProcessedData" to pair.toString())) } is PairBolus -> { val pair = ack.originalObject - dataSyncSelectorV1.confirmLastBolusIdIfGreater(pair.id) + pair.confirmed = true rxBus.send(EventNSClientNewLog("◄ DBUPDATE", "Acked Bolus " + ack._id)) - // Send new if waiting - dataSyncSelectorV1.processChangedBoluses() ret = Result.success(workDataOf("ProcessedData" to pair.toString())) } is PairCarbs -> { val pair = ack.originalObject - dataSyncSelectorV1.confirmLastCarbsIdIfGreater(pair.id) + pair.confirmed = true rxBus.send(EventNSClientNewLog("◄ DBUPDATE", "Acked Carbs " + ack._id)) - // Send new if waiting - dataSyncSelectorV1.processChangedCarbs() ret = Result.success(workDataOf("ProcessedData" to pair.toString())) } is PairBolusCalculatorResult -> { val pair = ack.originalObject - dataSyncSelectorV1.confirmLastBolusCalculatorResultsIdIfGreater(pair.id) + pair.confirmed = true rxBus.send(EventNSClientNewLog("◄ DBUPDATE", "Acked BolusCalculatorResult " + ack._id)) - // Send new if waiting - dataSyncSelectorV1.processChangedBolusCalculatorResults() ret = Result.success(workDataOf("ProcessedData" to pair.toString())) } is PairTemporaryBasal -> { val pair = ack.originalObject - dataSyncSelectorV1.confirmLastTemporaryBasalIdIfGreater(pair.id) + pair.confirmed = true rxBus.send(EventNSClientNewLog("◄ DBUPDATE", "Acked TemporaryBasal " + ack._id)) - // Send new if waiting - dataSyncSelectorV1.processChangedTemporaryBasals() ret = Result.success(workDataOf("ProcessedData" to pair.toString())) } is PairExtendedBolus -> { val pair = ack.originalObject - dataSyncSelectorV1.confirmLastExtendedBolusIdIfGreater(pair.id) + pair.confirmed = true rxBus.send(EventNSClientNewLog("◄ DBUPDATE", "Acked ExtendedBolus " + ack._id)) - // Send new if waiting - dataSyncSelectorV1.processChangedExtendedBoluses() ret = Result.success(workDataOf("ProcessedData" to pair.toString())) } is PairProfileSwitch -> { val pair = ack.originalObject - dataSyncSelectorV1.confirmLastProfileSwitchIdIfGreater(pair.id) + pair.confirmed = true rxBus.send(EventNSClientNewLog("◄ DBUPDATE", "Acked ProfileSwitch " + ack._id)) - // Send new if waiting - dataSyncSelectorV1.processChangedProfileSwitches() ret = Result.success(workDataOf("ProcessedData" to pair.toString())) } is PairEffectiveProfileSwitch -> { val pair = ack.originalObject - dataSyncSelectorV1.confirmLastEffectiveProfileSwitchIdIfGreater(pair.id) + pair.confirmed = true rxBus.send(EventNSClientNewLog("◄ DBUPDATE", "Acked EffectiveProfileSwitch " + ack._id)) - // Send new if waiting - dataSyncSelectorV1.processChangedEffectiveProfileSwitches() ret = Result.success(workDataOf("ProcessedData" to pair.toString())) } is PairOfflineEvent -> { val pair = ack.originalObject - dataSyncSelectorV1.confirmLastOfflineEventIdIfGreater(pair.id) + pair.confirmed = true rxBus.send(EventNSClientNewLog("◄ DBUPDATE", "Acked OfflineEvent" + ack._id)) - // Send new if waiting - dataSyncSelectorV1.processChangedOfflineEvents() ret = Result.success(workDataOf("ProcessedData" to pair.toString())) } } + ack.originalObject?.let { synchronized(it) { it.notify() } } return ret } } \ No newline at end of file diff --git a/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclientV3/DataSyncSelectorV3Impl.kt b/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclientV3/DataSyncSelectorV3.kt similarity index 92% rename from plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclientV3/DataSyncSelectorV3Impl.kt rename to plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclientV3/DataSyncSelectorV3.kt index 7a3d88d400..3c5ea4b316 100644 --- a/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclientV3/DataSyncSelectorV3Impl.kt +++ b/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclientV3/DataSyncSelectorV3.kt @@ -7,7 +7,6 @@ import info.nightscout.interfaces.nsclient.StoreDataForDb import info.nightscout.interfaces.plugin.ActivePlugin import info.nightscout.interfaces.profile.ProfileFunction import info.nightscout.interfaces.sync.DataSyncSelector -import info.nightscout.interfaces.sync.DataSyncSelectorV3 import info.nightscout.interfaces.utils.JsonHelper import info.nightscout.plugins.sync.R import info.nightscout.plugins.sync.nsShared.events.EventNSClientUpdateGuiQueue @@ -22,7 +21,7 @@ import javax.inject.Singleton @OpenForTesting @Singleton -class DataSyncSelectorV3Impl @Inject constructor( +class DataSyncSelectorV3 @Inject constructor( private val sp: SP, private val aapsLogger: AAPSLogger, private val dateUtil: DateUtil, @@ -32,7 +31,7 @@ class DataSyncSelectorV3Impl @Inject constructor( private val rxBus: RxBus, private val storeDataForDb: StoreDataForDb, private val config: Config -) : DataSyncSelectorV3 { +) : DataSyncSelector { class QueueCounter( var bolusesRemaining: Long = -1L, @@ -127,14 +126,14 @@ class DataSyncSelectorV3Impl @Inject constructor( else sp.remove(R.string.key_ns_device_status_last_synced_id) } - fun confirmLastBolusIdIfGreater(lastSynced: Long) { + private fun confirmLastBolusIdIfGreater(lastSynced: Long) { if (lastSynced > sp.getLong(R.string.key_ns_bolus_last_synced_id, 0)) { //aapsLogger.debug(LTag.NSCLIENT, "Setting Bolus data sync from $lastSynced") sp.putLong(R.string.key_ns_bolus_last_synced_id, lastSynced) } } - suspend fun processChangedBoluses() { + private suspend fun processChangedBoluses() { var cont = true while (cont) { if (isPaused) return @@ -170,14 +169,14 @@ class DataSyncSelectorV3Impl @Inject constructor( } } - fun confirmLastCarbsIdIfGreater(lastSynced: Long) { + private fun confirmLastCarbsIdIfGreater(lastSynced: Long) { if (lastSynced > sp.getLong(R.string.key_ns_carbs_last_synced_id, 0)) { //aapsLogger.debug(LTag.NSCLIENT, "Setting Carbs data sync from $lastSynced") sp.putLong(R.string.key_ns_carbs_last_synced_id, lastSynced) } } - suspend fun processChangedCarbs() { + private suspend fun processChangedCarbs() { var cont = true while (cont) { if (isPaused) return @@ -213,14 +212,14 @@ class DataSyncSelectorV3Impl @Inject constructor( } } - fun confirmLastBolusCalculatorResultsIdIfGreater(lastSynced: Long) { + private fun confirmLastBolusCalculatorResultsIdIfGreater(lastSynced: Long) { if (lastSynced > sp.getLong(R.string.key_ns_bolus_calculator_result_last_synced_id, 0)) { //aapsLogger.debug(LTag.NSCLIENT, "Setting BolusCalculatorResult data sync from $lastSynced") sp.putLong(R.string.key_ns_bolus_calculator_result_last_synced_id, lastSynced) } } - suspend fun processChangedBolusCalculatorResults() { + private suspend fun processChangedBolusCalculatorResults() { var cont = true while (cont) { if (isPaused) return @@ -264,14 +263,14 @@ class DataSyncSelectorV3Impl @Inject constructor( } } - fun confirmLastTempTargetsIdIfGreater(lastSynced: Long) { + private fun confirmLastTempTargetsIdIfGreater(lastSynced: Long) { if (lastSynced > sp.getLong(R.string.key_ns_temporary_target_last_synced_id, 0)) { //aapsLogger.debug(LTag.NSCLIENT, "Setting TemporaryTarget data sync from $lastSynced") sp.putLong(R.string.key_ns_temporary_target_last_synced_id, lastSynced) } } - suspend fun processChangedTempTargets() { + private suspend fun processChangedTempTargets() { var cont = true while (cont) { if (isPaused) return @@ -307,14 +306,14 @@ class DataSyncSelectorV3Impl @Inject constructor( } } - fun confirmLastFoodIdIfGreater(lastSynced: Long) { + private fun confirmLastFoodIdIfGreater(lastSynced: Long) { if (lastSynced > sp.getLong(R.string.key_ns_food_last_synced_id, 0)) { //aapsLogger.debug(LTag.NSCLIENT, "Setting Food data sync from $lastSynced") sp.putLong(R.string.key_ns_food_last_synced_id, lastSynced) } } - suspend fun processChangedFoods() { + private suspend fun processChangedFoods() { var cont = true while (cont) { if (isPaused) return @@ -350,14 +349,14 @@ class DataSyncSelectorV3Impl @Inject constructor( } } - fun confirmLastGlucoseValueIdIfGreater(lastSynced: Long) { + private fun confirmLastGlucoseValueIdIfGreater(lastSynced: Long) { if (lastSynced > sp.getLong(R.string.key_ns_glucose_value_last_synced_id, 0)) { //aapsLogger.debug(LTag.NSCLIENT, "Setting GlucoseValue data sync from $lastSynced") sp.putLong(R.string.key_ns_glucose_value_last_synced_id, lastSynced) } } - suspend fun processChangedGlucoseValues() { + private suspend fun processChangedGlucoseValues() { var cont = true while (cont) { if (isPaused) return @@ -395,14 +394,14 @@ class DataSyncSelectorV3Impl @Inject constructor( } } - fun confirmLastTherapyEventIdIfGreater(lastSynced: Long) { + private fun confirmLastTherapyEventIdIfGreater(lastSynced: Long) { if (lastSynced > sp.getLong(R.string.key_ns_therapy_event_last_synced_id, 0)) { //aapsLogger.debug(LTag.NSCLIENT, "Setting TherapyEvents data sync from $lastSynced") sp.putLong(R.string.key_ns_therapy_event_last_synced_id, lastSynced) } } - suspend fun processChangedTherapyEvents() { + private suspend fun processChangedTherapyEvents() { var cont = true while (cont) { if (isPaused) return @@ -438,44 +437,45 @@ class DataSyncSelectorV3Impl @Inject constructor( } } - fun confirmLastDeviceStatusIdIfGreater(lastSynced: Long) { + private fun confirmLastDeviceStatusIdIfGreater(lastSynced: Long) { if (lastSynced > sp.getLong(R.string.key_ns_device_status_last_synced_id, 0)) { //aapsLogger.debug(LTag.NSCLIENT, "Setting DeviceStatus data sync from $lastSynced") sp.putLong(R.string.key_ns_device_status_last_synced_id, lastSynced) } } - suspend fun processChangedDeviceStatuses() { - if (isPaused) return - val lastDbId = appRepository.getLastDeviceStatusId() ?: 0L - var startId = sp.getLong(R.string.key_ns_device_status_last_synced_id, 0) - if (startId > lastDbId) { - aapsLogger.info(LTag.NSCLIENT, "Resetting startId: $startId lastDbId: $lastDbId") - sp.putLong(R.string.key_ns_device_status_last_synced_id, 0) - startId = 0 - } - queueCounter.dssRemaining = lastDbId - startId - rxBus.send(EventNSClientUpdateGuiQueue()) - appRepository.getNextSyncElementDeviceStatus(startId).blockingGet()?.let { deviceStatus -> - //aapsLogger.info(LTag.NSCLIENT, "Loading DeviceStatus data Start: $startId $deviceStatus") - // without nsId = create new - if (deviceStatus.interfaceIDs.nightscoutId == null) { - if (activePlugin.activeNsClient?.nsAdd("devicestatus", DataSyncSelector.PairDeviceStatus(deviceStatus, lastDbId), "$startId/$lastDbId") == true) - confirmLastDeviceStatusIdIfGreater(lastDbId) + private suspend fun processChangedDeviceStatuses() { + var cont = true + while (cont) { + if (isPaused) return + val lastDbId = appRepository.getLastDeviceStatusId() ?: 0L + var startId = sp.getLong(R.string.key_ns_device_status_last_synced_id, 0) + if (startId > lastDbId) { + aapsLogger.info(LTag.NSCLIENT, "Resetting startId: $startId lastDbId: $lastDbId") + sp.putLong(R.string.key_ns_device_status_last_synced_id, 0) + startId = 0 + } + queueCounter.dssRemaining = lastDbId - startId + rxBus.send(EventNSClientUpdateGuiQueue()) + appRepository.getNextSyncElementDeviceStatus(startId).blockingGet()?.let { deviceStatus -> + //aapsLogger.info(LTag.NSCLIENT, "Loading DeviceStatus data Start: $startId $deviceStatus") + cont = activePlugin.activeNsClient?.nsAdd("devicestatus", DataSyncSelector.PairDeviceStatus(deviceStatus, lastDbId), "$startId/$lastDbId") ?: false + if (cont) confirmLastDeviceStatusIdIfGreater(deviceStatus.id) + // with nsId = ignore + } ?: run { + cont = false } - // with nsId = ignore } - queueCounter.dssRemaining = 0 } - fun confirmLastTemporaryBasalIdIfGreater(lastSynced: Long) { + private fun confirmLastTemporaryBasalIdIfGreater(lastSynced: Long) { if (lastSynced > sp.getLong(R.string.key_ns_temporary_basal_last_synced_id, 0)) { //aapsLogger.debug(LTag.NSCLIENT, "Setting TemporaryBasal data sync from $lastSynced") sp.putLong(R.string.key_ns_temporary_basal_last_synced_id, lastSynced) } } - suspend fun processChangedTemporaryBasals() { + private suspend fun processChangedTemporaryBasals() { var cont = true while (cont) { if (isPaused) return @@ -512,14 +512,14 @@ class DataSyncSelectorV3Impl @Inject constructor( } } - fun confirmLastExtendedBolusIdIfGreater(lastSynced: Long) { + private fun confirmLastExtendedBolusIdIfGreater(lastSynced: Long) { if (lastSynced > sp.getLong(R.string.key_ns_extended_bolus_last_synced_id, 0)) { //aapsLogger.debug(LTag.NSCLIENT, "Setting ExtendedBolus data sync from $lastSynced") sp.putLong(R.string.key_ns_extended_bolus_last_synced_id, lastSynced) } } - suspend fun processChangedExtendedBoluses() { + private suspend fun processChangedExtendedBoluses() { var cont = true while (cont) { if (isPaused) return @@ -558,14 +558,14 @@ class DataSyncSelectorV3Impl @Inject constructor( } } - fun confirmLastProfileSwitchIdIfGreater(lastSynced: Long) { + private fun confirmLastProfileSwitchIdIfGreater(lastSynced: Long) { if (lastSynced > sp.getLong(R.string.key_ns_profile_switch_last_synced_id, 0)) { //aapsLogger.debug(LTag.NSCLIENT, "Setting ProfileSwitch data sync from $lastSynced") sp.putLong(R.string.key_ns_profile_switch_last_synced_id, lastSynced) } } - suspend fun processChangedProfileSwitches() { + private suspend fun processChangedProfileSwitches() { var cont = true while (cont) { if (isPaused) return @@ -601,14 +601,14 @@ class DataSyncSelectorV3Impl @Inject constructor( } } - fun confirmLastEffectiveProfileSwitchIdIfGreater(lastSynced: Long) { + private fun confirmLastEffectiveProfileSwitchIdIfGreater(lastSynced: Long) { if (lastSynced > sp.getLong(R.string.key_ns_effective_profile_switch_last_synced_id, 0)) { //aapsLogger.debug(LTag.NSCLIENT, "Setting EffectiveProfileSwitch data sync from $lastSynced") sp.putLong(R.string.key_ns_effective_profile_switch_last_synced_id, lastSynced) } } - suspend fun processChangedEffectiveProfileSwitches() { + private suspend fun processChangedEffectiveProfileSwitches() { var cont = true while (cont) { if (isPaused) return @@ -644,14 +644,14 @@ class DataSyncSelectorV3Impl @Inject constructor( } } - fun confirmLastOfflineEventIdIfGreater(lastSynced: Long) { + private fun confirmLastOfflineEventIdIfGreater(lastSynced: Long) { if (lastSynced > sp.getLong(R.string.key_ns_offline_event_last_synced_id, 0)) { //aapsLogger.debug(LTag.NSCLIENT, "Setting OfflineEvent data sync from $lastSynced") sp.putLong(R.string.key_ns_offline_event_last_synced_id, lastSynced) } } - suspend fun processChangedOfflineEvents() { + private suspend fun processChangedOfflineEvents() { var cont = true while (cont) { if (isPaused) return @@ -687,11 +687,11 @@ class DataSyncSelectorV3Impl @Inject constructor( } } - fun confirmLastProfileStore(lastSynced: Long) { + private fun confirmLastProfileStore(lastSynced: Long) { sp.putLong(R.string.key_ns_profile_store_last_synced_timestamp, lastSynced) } - suspend fun processChangedProfileStore() { + private suspend fun processChangedProfileStore() { if (isPaused) return val lastSync = sp.getLong(R.string.key_ns_profile_store_last_synced_timestamp, 0) val lastChange = sp.getLong(info.nightscout.core.utils.R.string.key_local_profile_last_change, 0) diff --git a/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclientV3/NSClientV3Plugin.kt b/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclientV3/NSClientV3Plugin.kt index c8dee2f68f..74b773b427 100644 --- a/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclientV3/NSClientV3Plugin.kt +++ b/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclientV3/NSClientV3Plugin.kt @@ -30,7 +30,6 @@ import info.nightscout.interfaces.plugin.PluginType import info.nightscout.interfaces.profile.Profile import info.nightscout.interfaces.source.NSClientSource import info.nightscout.interfaces.sync.DataSyncSelector -import info.nightscout.interfaces.sync.DataSyncSelectorV3 import info.nightscout.interfaces.sync.NsClient import info.nightscout.interfaces.sync.Sync import info.nightscout.interfaces.ui.UiInteraction @@ -66,11 +65,14 @@ import info.nightscout.plugins.sync.nsclientV3.workers.LoadTreatmentsWorker import info.nightscout.rx.AapsSchedulers import info.nightscout.rx.bus.RxBus import info.nightscout.rx.events.EventAppExit +import info.nightscout.rx.events.EventDeviceStatusChange import info.nightscout.rx.events.EventDismissNotification import info.nightscout.rx.events.EventNSClientNewLog import info.nightscout.rx.events.EventNewHistoryData +import info.nightscout.rx.events.EventOfflineChange import info.nightscout.rx.events.EventPreferenceChange import info.nightscout.rx.events.EventSWSyncStatus +import info.nightscout.rx.events.EventTherapyEventChange import info.nightscout.rx.logging.AAPSLogger import info.nightscout.rx.logging.LTag import info.nightscout.sdk.NSAndroidClientImpl @@ -224,6 +226,18 @@ class NSClientV3Plugin @Inject constructor( .toObservable(EventNewHistoryData::class.java) .observeOn(aapsSchedulers.io) .subscribe({ executeUpload("NEW_DATA", forceNew = false) }, fabricPrivacy::logException) + disposable += rxBus + .toObservable(EventDeviceStatusChange::class.java) + .observeOn(aapsSchedulers.io) + .subscribe({ executeUpload("EventDeviceStatusChange", forceNew = false) }, fabricPrivacy::logException) + disposable += rxBus + .toObservable(EventTherapyEventChange::class.java) + .observeOn(aapsSchedulers.io) + .subscribe({ executeUpload("EventTherapyEventChange", forceNew = false) }, fabricPrivacy::logException) + disposable += rxBus + .toObservable(EventOfflineChange::class.java) + .observeOn(aapsSchedulers.io) + .subscribe({ executeUpload("EventOfflineChange", forceNew = false) }, fabricPrivacy::logException) runLoop = Runnable { var refreshInterval = T.mins(5).msecs() diff --git a/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclientV3/workers/DataSyncWorker.kt b/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclientV3/workers/DataSyncWorker.kt index 7b8442fc46..0ef6e9da02 100644 --- a/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclientV3/workers/DataSyncWorker.kt +++ b/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclientV3/workers/DataSyncWorker.kt @@ -5,7 +5,7 @@ import androidx.work.WorkerParameters import info.nightscout.androidaps.annotations.OpenForTesting import info.nightscout.core.utils.worker.LoggingWorker import info.nightscout.interfaces.plugin.ActivePlugin -import info.nightscout.interfaces.sync.DataSyncSelectorV3 +import info.nightscout.plugins.sync.nsclientV3.DataSyncSelectorV3 import info.nightscout.plugins.sync.nsclientV3.NSClientV3Plugin import info.nightscout.rx.bus.RxBus import info.nightscout.rx.events.EventNSClientNewLog diff --git a/plugins/sync/src/test/java/info/nightscout/plugins/sync/nsclientV3/NSClientV3PluginTest.kt b/plugins/sync/src/test/java/info/nightscout/plugins/sync/nsclientV3/NSClientV3PluginTest.kt index 2dd14bbffa..9bc1151029 100644 --- a/plugins/sync/src/test/java/info/nightscout/plugins/sync/nsclientV3/NSClientV3PluginTest.kt +++ b/plugins/sync/src/test/java/info/nightscout/plugins/sync/nsclientV3/NSClientV3PluginTest.kt @@ -45,7 +45,7 @@ internal class NSClientV3PluginTest : TestBaseWithProfile() { @Mock lateinit var receiverDelegate: ReceiverDelegate @Mock lateinit var uiInteraction: UiInteraction - @Mock lateinit var dataSyncSelectorV3: DataSyncSelectorV3Impl + @Mock lateinit var dataSyncSelectorV3: DataSyncSelectorV3 @Mock lateinit var nsAndroidClient: NSAndroidClient @Mock lateinit var uel: UserEntryLogger @Mock lateinit var nsClientSource: NSClientSource diff --git a/plugins/sync/src/test/java/info/nightscout/plugins/sync/nsclientV3/workers/DataSyncWorkerTest.kt b/plugins/sync/src/test/java/info/nightscout/plugins/sync/nsclientV3/workers/DataSyncWorkerTest.kt index a966eb66ab..bcb9dcd5f8 100644 --- a/plugins/sync/src/test/java/info/nightscout/plugins/sync/nsclientV3/workers/DataSyncWorkerTest.kt +++ b/plugins/sync/src/test/java/info/nightscout/plugins/sync/nsclientV3/workers/DataSyncWorkerTest.kt @@ -8,7 +8,7 @@ import info.nightscout.androidaps.TestBase import info.nightscout.core.utils.fabric.FabricPrivacy import info.nightscout.interfaces.plugin.ActivePlugin import info.nightscout.interfaces.sync.NsClient -import info.nightscout.plugins.sync.nsclientV3.DataSyncSelectorV3Impl +import info.nightscout.plugins.sync.nsclientV3.DataSyncSelectorV3 import info.nightscout.plugins.sync.nsclientV3.NSClientV3Plugin import info.nightscout.rx.bus.RxBus import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -24,7 +24,7 @@ import org.mockito.Mockito.`when` internal class DataSyncWorkerTest : TestBase() { @Mock lateinit var fabricPrivacy: FabricPrivacy - @Mock lateinit var dataSyncSelectorV3: DataSyncSelectorV3Impl + @Mock lateinit var dataSyncSelectorV3: DataSyncSelectorV3 @Mock lateinit var activePlugin: ActivePlugin @Mock lateinit var nsClient: NsClient @Mock lateinit var rxBus: RxBus diff --git a/plugins/sync/src/test/java/info/nightscout/plugins/sync/nsclientV3/workers/LoadBgWorkerTest.kt b/plugins/sync/src/test/java/info/nightscout/plugins/sync/nsclientV3/workers/LoadBgWorkerTest.kt index f2f3c4372c..67c1314bf2 100644 --- a/plugins/sync/src/test/java/info/nightscout/plugins/sync/nsclientV3/workers/LoadBgWorkerTest.kt +++ b/plugins/sync/src/test/java/info/nightscout/plugins/sync/nsclientV3/workers/LoadBgWorkerTest.kt @@ -17,11 +17,11 @@ import info.nightscout.interfaces.Config import info.nightscout.interfaces.nsclient.StoreDataForDb import info.nightscout.interfaces.receivers.ReceiverStatusStore import info.nightscout.interfaces.source.NSClientSource -import info.nightscout.interfaces.sync.DataSyncSelectorV3 import info.nightscout.interfaces.ui.UiInteraction import info.nightscout.plugins.sync.nsShared.NsIncomingDataProcessor import info.nightscout.plugins.sync.nsclient.ReceiverDelegate import info.nightscout.plugins.sync.nsclient.data.NSDeviceStatusHandler +import info.nightscout.plugins.sync.nsclientV3.DataSyncSelectorV3 import info.nightscout.plugins.sync.nsclientV3.NSClientV3Plugin import info.nightscout.plugins.sync.nsclientV3.extensions.toNSSvgV3 import info.nightscout.rx.bus.RxBus