NSCv3: more work on sync

This commit is contained in:
Milos Kozak 2022-12-14 21:49:08 +01:00
parent bd84d3a2f7
commit 09e61772ab
16 changed files with 181 additions and 112 deletions

View file

@ -16,7 +16,31 @@ interface NsClient : Sync {
fun textLog(): Spanned
fun clearLog()
enum class Collection { ENTRIES, TREATMENTS}
/**
* NSC v3 does first load of all data
* next loads are using srvModified property for sync
* not used for NSCv1
*
* @return true if inside first load of NSCv3, true for NSCv1
*/
fun isFirstLoad(collection: Collection): Boolean = true
/**
* Update newest loaded timestamp for entries collection (first load or NSCv1)
* Update newest srvModified (sync loads)
*
* @param latestReceived timestamp
*
*/
fun updateLatestBgReceivedIfNewer(latestReceived: Long)
/**
* Update newest loaded timestamp for treatments collection (first load or NSCv1)
* Update newest srvModified (sync loads)
*
* @param latestReceived timestamp
*
*/
fun updateLatestTreatmentReceivedIfNewer(latestReceived: Long)
fun handleClearAlarm(originalAlarm: NSAlarm, silenceTimeInMilliseconds: Long)

View file

@ -4,7 +4,7 @@ import android.content.Context
import info.nightscout.sdk.exceptions.DateHeaderOutOfToleranceException
import info.nightscout.sdk.exceptions.InvalidAccessTokenException
import info.nightscout.sdk.exceptions.InvalidFormatNightscoutException
import info.nightscout.sdk.exceptions.TodoNightscoutException
import info.nightscout.sdk.exceptions.UnsuccessfullNightscoutException
import info.nightscout.sdk.exceptions.UnknownResponseNightscoutException
import info.nightscout.sdk.interfaces.NSAndroidClient
import info.nightscout.sdk.localmodel.Status
@ -101,9 +101,9 @@ class NSAndroidClientImpl(
val response = api.lastModified()
if (response.isSuccessful) {
return@callWrapper response.body()?.result ?: throw TodoNightscoutException()
return@callWrapper response.body()?.result ?: throw UnsuccessfullNightscoutException()
} else {
throw TodoNightscoutException() // TODO: react to response errors (offline, ...)
throw UnsuccessfullNightscoutException()
}
}
@ -114,17 +114,19 @@ class NSAndroidClientImpl(
if (response.isSuccessful) {
return@callWrapper response.body()?.result?.map(RemoteEntry::toSgv).toNotNull()
} else {
throw TodoNightscoutException() // TODO: react to response errors (offline, ...)
throw UnsuccessfullNightscoutException()
}
}
override suspend fun getSgvsModifiedSince(from: Long): List<NSSgvV3> = callWrapper(dispatcher) {
override suspend fun getSgvsModifiedSince(from: Long, limit: Long): NSAndroidClient.ReadResponse<List<NSSgvV3>> = callWrapper(dispatcher) {
val response = api.getSgvsModifiedSince(from)
val response = api.getSgvsModifiedSince(from, limit)
val eTagString = response.headers()["ETag"]
val eTag = eTagString?.substring(3, eTagString.length - 1)?.toLong() ?: throw UnsuccessfullNightscoutException()
if (response.isSuccessful) {
return@callWrapper response.body()?.result?.map(RemoteEntry::toSgv).toNotNull()
return@callWrapper NSAndroidClient.ReadResponse(eTag, response.body()?.result?.map(RemoteEntry::toSgv).toNotNull())
} else {
throw TodoNightscoutException() // TODO: react to response errors (offline, ...)
throw UnsuccessfullNightscoutException()
}
}
@ -134,7 +136,17 @@ class NSAndroidClientImpl(
if (response.isSuccessful) {
return@callWrapper response.body()?.result?.map(RemoteEntry::toSgv).toNotNull()
} else {
throw TodoNightscoutException() // TODO: react to response errors (offline, ...)
throw UnsuccessfullNightscoutException()
}
}
override suspend fun getTreatmentsNewerThan(from: Long, limit: Long): List<NSTreatment> = callWrapper(dispatcher) {
val response = api.getTreatmentsNewerThan(from, limit)
if (response.isSuccessful) {
return@callWrapper response.body()?.result?.map(RemoteTreatment::toTreatment).toNotNull()
} else {
throw UnsuccessfullNightscoutException()
}
}
@ -142,11 +154,11 @@ class NSAndroidClientImpl(
val response = api.getTreatmentsModifiedSince(from, limit)
val eTagString = response.headers()["ETag"]
val eTag = eTagString?.substring(3, eTagString.length - 1)?.toLong() ?: throw TodoNightscoutException()
val eTag = eTagString?.substring(3, eTagString.length - 1)?.toLong() ?: throw UnsuccessfullNightscoutException()
if (response.isSuccessful) {
return@callWrapper NSAndroidClient.ReadResponse(eTag, response.body()?.result?.map(RemoteTreatment::toTreatment).toNotNull())
} else {
throw TodoNightscoutException() // TODO: react to response errors (offline, ...)
throw UnsuccessfullNightscoutException()
}
}
@ -156,7 +168,7 @@ class NSAndroidClientImpl(
if (response.isSuccessful) {
return@callWrapper response.body()?.result.toNotNull()
} else {
throw TodoNightscoutException() // TODO: react to response errors (offline, ...)
throw UnsuccessfullNightscoutException()
}
}
@ -174,7 +186,7 @@ class NSAndroidClientImpl(
lastModified = response.body()?.result?.lastModified
)
} else {
throw TodoNightscoutException() // TODO: react to response errors (offline, ...)
throw UnsuccessfullNightscoutException()
}
}
@ -191,7 +203,7 @@ class NSAndroidClientImpl(
lastModified = response.body()?.result?.lastModified
)
} else {
throw TodoNightscoutException() // TODO: react to response errors (offline, ...)
throw UnsuccessfullNightscoutException()
}
}

View file

@ -9,13 +9,14 @@ import info.nightscout.sdk.remotemodel.LastModified
import info.nightscout.sdk.remotemodel.RemoteDeviceStatus
import io.reactivex.rxjava3.core.Single
import kotlinx.coroutines.rx3.rxSingle
import retrofit2.http.Query
class NSAndroidRxClientImpl(private val client: NSAndroidClient) : NSAndroidRxClient {
override fun getVersion(): Single<String> = rxSingle { client.getVersion() }
override fun getStatus(): Single<Status> = rxSingle { client.getStatus() }
override fun getLastModified(): Single<LastModified> = rxSingle { client.getLastModified() }
override fun getSgvsModifiedSince(from: Long): Single<List<NSSgvV3>> = rxSingle { client.getSgvsModifiedSince(from) }
override fun getSgvsModifiedSince(from: Long, limit: Long): Single<NSAndroidClient.ReadResponse<List<NSSgvV3>>> = rxSingle { client.getSgvsModifiedSince(from, limit) }
override fun getTreatmentsModifiedSince(from: Long, limit: Long): Single<NSAndroidClient.ReadResponse<List<NSTreatment>>> =
rxSingle { client.getTreatmentsModifiedSince(from, limit) }
override fun getDeviceStatusModifiedSince(from: Long): Single<List<RemoteDeviceStatus>> =

View file

@ -1,3 +0,0 @@
package info.nightscout.sdk.exceptions
class TodoNightscoutException : NightscoutException()

View file

@ -0,0 +1,3 @@
package info.nightscout.sdk.exceptions
class UnsuccessfullNightscoutException : NightscoutException()

View file

@ -21,8 +21,9 @@ interface NSAndroidClient {
suspend fun getLastModified(): LastModified
suspend fun getSgvs(): List<NSSgvV3>
suspend fun getSgvsModifiedSince(from: Long): List<NSSgvV3>
suspend fun getSgvsModifiedSince(from: Long, limit: Long): ReadResponse<List<NSSgvV3>>
suspend fun getSgvsNewerThan(from: Long, limit: Long): List<NSSgvV3>
suspend fun getTreatmentsNewerThan(from: Long, limit: Long): List<NSTreatment>
suspend fun getTreatmentsModifiedSince(from: Long, limit: Long): ReadResponse<List<NSTreatment>>
suspend fun getDeviceStatusModifiedSince(from: Long): List<RemoteDeviceStatus>
suspend fun createTreatment(nsTreatment: NSTreatment): CreateUpdateResponse

View file

@ -12,7 +12,7 @@ interface NSAndroidRxClient {
fun getVersion(): Single<String>
fun getStatus(): Single<Status>
fun getLastModified(): Single<LastModified>
fun getSgvsModifiedSince(from: Long): Single<List<NSSgvV3>>
fun getSgvsModifiedSince(from: Long, limit: Long): Single<NSAndroidClient.ReadResponse<List<NSSgvV3>>>
fun getTreatmentsModifiedSince(from: Long, limit: Long): Single<NSAndroidClient.ReadResponse<List<NSTreatment>>>
fun getDeviceStatusModifiedSince(from: Long): Single<List<RemoteDeviceStatus>>
}

View file

@ -45,7 +45,10 @@ internal interface NightscoutRemoteService {
suspend fun getSgvsNewerThan(@Query(value = "date\$gt", encoded = true) date: Long, @Query("limit") limit: Long): Response<NSResponse<List<RemoteEntry>>>
@GET("v3/entries/history/{from}")
suspend fun getSgvsModifiedSince(@Path("from") from: Long): Response<NSResponse<List<RemoteEntry>>>
suspend fun getSgvsModifiedSince(@Path("from") from: Long, @Query("limit") limit: Long): Response<NSResponse<List<RemoteEntry>>>
@GET("v3/treatments")
suspend fun getTreatmentsNewerThan(@Query(value = "date\$gt", encoded = true) date: Long, @Query("limit") limit: Long): Response<NSResponse<List<RemoteTreatment>>>
@GET("v3/treatments/history/{from}")
suspend fun getTreatmentsModifiedSince(@Path("from") from: Long, @Query("limit") limit: Long): Response<NSResponse<List<RemoteTreatment>>>

View file

@ -15,9 +15,9 @@ data class LastModified(
@Serializable
data class Collections(
@SerializedName("devicestatus") var devicestatus: Long, // devicestatus collection
@SerializedName("entries") var entries: Long, // entries collection
@SerializedName("profile") var profile: Long, // profile collection
@SerializedName("treatments") var treatments: Long // treatments collection
@SerializedName("devicestatus") var devicestatus: Long = 0, // devicestatus collection
@SerializedName("entries") var entries: Long = 0, // entries collection
@SerializedName("profile") var profile: Long = 0, // profile collection
@SerializedName("treatments") var treatments: Long = 0 // treatments collection
)
}

View file

@ -54,6 +54,7 @@ import info.nightscout.interfaces.nsclient.StoreDataForDb
import info.nightscout.interfaces.pump.VirtualPump
import info.nightscout.interfaces.source.NSClientSource
import info.nightscout.interfaces.ui.UiInteraction
import info.nightscout.plugins.sync.nsclientV3.NSClientV3Plugin
import info.nightscout.rx.bus.RxBus
import info.nightscout.rx.events.EventNSClientNewLog
import info.nightscout.rx.logging.AAPSLogger

View file

@ -39,6 +39,7 @@ import info.nightscout.plugins.sync.nsclientV3.workers.LoadLastModificationWorke
import info.nightscout.plugins.sync.nsclientV3.workers.LoadStatusWorker
import info.nightscout.rx.AapsSchedulers
import info.nightscout.rx.bus.RxBus
import info.nightscout.rx.events.EventAppExit
import info.nightscout.rx.events.EventChargingState
import info.nightscout.rx.events.EventNSClientNewLog
import info.nightscout.rx.events.EventNetworkChange
@ -60,7 +61,6 @@ import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import javax.inject.Inject
import javax.inject.Singleton
import kotlin.math.max
@Singleton
class NSClientV3Plugin @Inject constructor(
@ -113,22 +113,14 @@ class NSClientV3Plugin @Inject constructor(
}
internal lateinit var nsAndroidClient: NSAndroidClient
// private lateinit var nsAndroidRxClient: NSAndroidRxClient
val isAllowed get() = nsClientReceiverDelegate.allowed
val blockingReason get() = nsClientReceiverDelegate.blockingReason
private val isAllowed get() = nsClientReceiverDelegate.allowed
private val blockingReason get() = nsClientReceiverDelegate.blockingReason
private val maxAge = T.days(77).msecs()
internal var newestDataOnServer: LastModified? = null // timestamp of last modification for every collection
internal var lastLoadedSrvModified =
LastModified(
LastModified.Collections(
dateUtil.now() - maxAge,
dateUtil.now() - maxAge,
dateUtil.now() - maxAge,
dateUtil.now() - maxAge
)
) // timestamp of last fetched data for every collection
val maxAge = T.days(77).msecs()
internal var newestDataOnServer: LastModified? = null // timestamp of last modification for every collection provided by server
internal var lastLoadedSrvModified = LastModified(LastModified.Collections()) // max srvLastModified timestamp of last fetched data for every collection
internal var firstLoadContinueTimestamp = LastModified(LastModified.Collections()) // timestamp of last fetched data for every collection during initial load
override fun onStart() {
// context.bindService(Intent(context, NSClientService::class.java), mConnection, Context.BIND_AUTO_CREATE)
@ -137,16 +129,9 @@ class NSClientV3Plugin @Inject constructor(
lastLoadedSrvModified = Json.decodeFromString(
sp.getString(
R.string.key_ns_client_v3_last_modified,
Json.encodeToString(
LastModified.serializer(),
LastModified(LastModified.Collections(dateUtil.now() - maxAge, dateUtil.now() - maxAge, dateUtil.now() - maxAge, dateUtil.now() - maxAge))
Json.encodeToString(LastModified.serializer(), LastModified(LastModified.Collections()))
)
)
)
lastLoadedSrvModified.collections.entries = max(dateUtil.now() - maxAge, lastLoadedSrvModified.collections.entries)
lastLoadedSrvModified.collections.treatments = max(dateUtil.now() - maxAge, lastLoadedSrvModified.collections.treatments)
lastLoadedSrvModified.collections.profile = max(dateUtil.now() - maxAge, lastLoadedSrvModified.collections.profile)
lastLoadedSrvModified.collections.devicestatus = max(dateUtil.now() - maxAge, lastLoadedSrvModified.collections.devicestatus)
setClient()
@ -166,10 +151,10 @@ class NSClientV3Plugin @Inject constructor(
if (ev.isChanged(rh.gs(R.string.key_ns_client_token)) || ev.isChanged(rh.gs(info.nightscout.core.utils.R.string.key_nsclientinternal_url)))
setClient()
}, fabricPrivacy::logException)
// disposable += rxBus
// .toObservable(EventAppExit::class.java)
// .observeOn(aapsSchedulers.io)
// .subscribe({ if (nsClientService != null) context.unbindService(mConnection) }, fabricPrivacy::logException)
disposable += rxBus
.toObservable(EventAppExit::class.java)
.observeOn(aapsSchedulers.io)
.subscribe({ WorkManager.getInstance(context).cancelUniqueWork(JOB_NAME) }, fabricPrivacy::logException)
disposable += rxBus
.toObservable(EventNSClientNewLog::class.java)
.observeOn(aapsSchedulers.io)
@ -187,8 +172,8 @@ class NSClientV3Plugin @Inject constructor(
.subscribe({ event -> resend(event.reason) }, fabricPrivacy::logException)
runLoop = Runnable {
executeLoop()
handler.postDelayed(runLoop, REFRESH_INTERVAL)
executeLoop()
}
handler.postDelayed(runLoop, REFRESH_INTERVAL)
executeLoop()
@ -214,7 +199,6 @@ class NSClientV3Plugin @Inject constructor(
override val hasWritePermission: Boolean get() = nsAndroidClient.lastStatus?.apiPermissions?.isFull() ?: false
override val connected: Boolean get() = nsAndroidClient.lastStatus != null
override fun clearLog() {
handler.post {
synchronized(listLog) { listLog.clear() }
@ -283,27 +267,23 @@ class NSClientV3Plugin @Inject constructor(
// })
}
override fun updateLatestBgReceivedIfNewer(latestReceived: Long) {
if (latestReceived > lastLoadedSrvModified.collections.entries) {
lastLoadedSrvModified.collections.entries = latestReceived
storeLastFetched()
override fun isFirstLoad(collection: NsClient.Collection) =
when (collection) {
NsClient.Collection.ENTRIES -> lastLoadedSrvModified.collections.entries == 0L
NsClient.Collection.TREATMENTS -> lastLoadedSrvModified.collections.treatments == 0L
}
override fun updateLatestBgReceivedIfNewer(latestReceived: Long) {
if (isFirstLoad(NsClient.Collection.ENTRIES)) firstLoadContinueTimestamp.collections.entries = latestReceived
}
override fun updateLatestTreatmentReceivedIfNewer(latestReceived: Long) {
lastLoadedSrvModified.collections.treatments = latestReceived
storeLastFetched()
if (isFirstLoad(NsClient.Collection.TREATMENTS)) firstLoadContinueTimestamp.collections.treatments = latestReceived
}
override fun resetToFullSync() {
lastLoadedSrvModified = LastModified(
LastModified.Collections(
dateUtil.now() - maxAge,
dateUtil.now() - maxAge,
dateUtil.now() - maxAge,
dateUtil.now() - maxAge
)
)
firstLoadContinueTimestamp = LastModified(LastModified.Collections())
lastLoadedSrvModified = LastModified(LastModified.Collections())
storeLastFetched()
}
@ -316,9 +296,10 @@ class NSClientV3Plugin @Inject constructor(
}
enum class Operation { CREATE, UPDATE }
private val gson: Gson = GsonBuilder().create()
private fun dbOperation(collection: String, dataPair: DataSyncSelector.DataPair, progress: String, operation: Operation) {
val call = when(operation) {
val call = when (operation) {
Operation.CREATE -> nsAndroidClient::createTreatment
Operation.UPDATE -> nsAndroidClient::updateTreatment
}
@ -343,11 +324,11 @@ class NSClientV3Plugin @Inject constructor(
val id = if (dataPair.value is TraceableDBEntry) (dataPair.value as TraceableDBEntry).interfaceIDs.nightscoutId else ""
rxBus.send(
EventNSClientNewLog(
when(operation) {
when (operation) {
Operation.CREATE -> "ADD $collection"
Operation.UPDATE -> "UPDATE $collection"
},
when(operation) {
when (operation) {
Operation.CREATE -> "Sent ${dataPair.javaClass.simpleName} ${gson.toJson(data)} $progress"
Operation.UPDATE -> "Sent ${dataPair.javaClass.simpleName} $id ${gson.toJson(data)} $progress"
}
@ -382,7 +363,8 @@ class NSClientV3Plugin @Inject constructor(
}
}
}
private fun storeLastFetched() {
fun storeLastFetched() {
sp.putString(R.string.key_ns_client_v3_last_modified, Json.encodeToString(LastModified.serializer(), lastLoadedSrvModified))
}
@ -391,20 +373,19 @@ class NSClientV3Plugin @Inject constructor(
}
fun scheduleNewExecution() {
val toTime = lastLoadedSrvModified.collections.entries + T.mins(6).plus(T.secs(0)).msecs()
if (toTime > dateUtil.now()) {
var toTime = lastLoadedSrvModified.collections.entries + T.mins(6).plus(T.secs(0)).msecs()
if (toTime < dateUtil.now()) toTime = dateUtil.now() + T.mins(1).plus(T.secs(0)).msecs()
handler.postDelayed({ executeLoop() }, toTime - dateUtil.now())
rxBus.send(EventNSClientNewLog("NEXT", dateUtil.dateAndTimeAndSecondsString(toTime)))
}
}
private fun executeLoop() {
if (sp.getBoolean(R.string.key_ns_client_paused, false)) {
rxBus.send(EventNSClientNewLog("NSCLIENT", "paused"))
rxBus.send(EventNSClientNewLog("RUN", "paused"))
return
}
if (!isAllowed) {
rxBus.send(EventNSClientNewLog("NSCLIENT", blockingReason))
rxBus.send(EventNSClientNewLog("RUN", blockingReason))
return
}
if (workIsRunning(arrayOf(JOB_NAME)))

View file

@ -8,15 +8,19 @@ import androidx.work.WorkerParameters
import androidx.work.workDataOf
import info.nightscout.core.utils.receivers.DataWorkerStorage
import info.nightscout.core.utils.worker.LoggingWorker
import info.nightscout.interfaces.sync.NsClient
import info.nightscout.interfaces.workflow.WorkerClasses
import info.nightscout.plugins.sync.nsShared.StoreDataForDbImpl
import info.nightscout.plugins.sync.nsclientV3.NSClientV3Plugin
import info.nightscout.rx.bus.RxBus
import info.nightscout.rx.events.EventNSClientNewLog
import info.nightscout.sdk.interfaces.NSAndroidClient
import info.nightscout.sdk.localmodel.entry.NSSgvV3
import info.nightscout.shared.sharedPreferences.SP
import info.nightscout.shared.utils.DateUtil
import kotlinx.coroutines.runBlocking
import javax.inject.Inject
import kotlin.math.max
class LoadBgWorker(
context: Context, params: WorkerParameters
@ -37,20 +41,26 @@ class LoadBgWorker(
override fun doWorkAndLog(): Result {
var ret = Result.success()
val isFirstLoad = nsClientV3Plugin.isFirstLoad(NsClient.Collection.ENTRIES)
val lastLoaded =
if (isFirstLoad) max(nsClientV3Plugin.firstLoadContinueTimestamp.collections.entries, dateUtil.now() - nsClientV3Plugin.maxAge)
else max(nsClientV3Plugin.lastLoadedSrvModified.collections.entries, dateUtil.now() - nsClientV3Plugin.maxAge)
runBlocking {
if ((nsClientV3Plugin.newestDataOnServer?.collections?.entries ?: Long.MAX_VALUE) > nsClientV3Plugin.lastLoadedSrvModified.collections.entries)
if ((nsClientV3Plugin.newestDataOnServer?.collections?.entries ?: Long.MAX_VALUE) > lastLoaded)
try {
//val sgvs = nsClientV3Plugin.nsAndroidClient.getSgvsModifiedSince(nsClientV3Plugin.lastFetched.collections.entries)
val sgvs = nsClientV3Plugin.nsAndroidClient.getSgvsNewerThan(nsClientV3Plugin.lastLoadedSrvModified.collections.entries, 500)
val sgvs: List<NSSgvV3>
val response: NSAndroidClient.ReadResponse<List<NSSgvV3>>?
if (isFirstLoad) sgvs = nsClientV3Plugin.nsAndroidClient.getSgvsNewerThan(lastLoaded, 500)
else {
response = nsClientV3Plugin.nsAndroidClient.getSgvsModifiedSince(lastLoaded, 500)
sgvs = response.values
nsClientV3Plugin.lastLoadedSrvModified.collections.entries = response.lastServerModified
nsClientV3Plugin.storeLastFetched()
}
aapsLogger.debug("SGVS: $sgvs")
if (sgvs.isNotEmpty()) {
rxBus.send(
EventNSClientNewLog(
"RCV",
"${sgvs.size} SVGs from ${dateUtil.dateAndTimeAndSecondsString(nsClientV3Plugin.lastLoadedSrvModified.collections.entries)}"
)
)
val action = if (isFirstLoad) "RCV-FIRST" else "RCV"
rxBus.send(EventNSClientNewLog(action, "${sgvs.size} SVGs from ${dateUtil.dateAndTimeAndSecondsString(lastLoaded)}"))
// Objective0
sp.putBoolean(info.nightscout.core.utils.R.string.key_objectives_bg_is_available_in_ns, true)
// Schedule processing of fetched data and continue of loading
@ -60,7 +70,13 @@ class LoadBgWorker(
OneTimeWorkRequest.Builder(workerClasses.nsClientSourceWorker).setInputData(dataWorkerStorage.storeInputData(sgvs)).build()
).then(OneTimeWorkRequest.Builder(LoadBgWorker::class.java).build()).enqueue()
} else {
rxBus.send(EventNSClientNewLog("END", "No SGVs from ${dateUtil.dateAndTimeAndSecondsString(nsClientV3Plugin.lastLoadedSrvModified.collections.entries)}"))
// End first load
if (isFirstLoad) {
nsClientV3Plugin.lastLoadedSrvModified.collections.entries = lastLoaded
nsClientV3Plugin.storeLastFetched()
}
rxBus.send(EventNSClientNewLog("RCV END", "No SGVs from ${dateUtil
.dateAndTimeAndSecondsString(lastLoaded)}"))
WorkManager.getInstance(context)
.beginUniqueWork(
NSClientV3Plugin.JOB_NAME,
@ -75,7 +91,13 @@ class LoadBgWorker(
ret = Result.failure(workDataOf("Error" to error.toString()))
}
else {
rxBus.send(EventNSClientNewLog("END", "No new SGVs from ${dateUtil.dateAndTimeAndSecondsString(nsClientV3Plugin.lastLoadedSrvModified.collections.entries)}"))
// End first load
if (isFirstLoad) {
nsClientV3Plugin.lastLoadedSrvModified.collections.entries = lastLoaded
nsClientV3Plugin.storeLastFetched()
}
rxBus.send(EventNSClientNewLog("RCV END", "No new SGVs from ${dateUtil
.dateAndTimeAndSecondsString(lastLoaded)}"))
nsClientV3Plugin.scheduleNewExecution() // Idea is to run after 5 min after last BG
WorkManager.getInstance(context)
.beginUniqueWork(

View file

@ -40,8 +40,9 @@ class LoadDeviceStatusWorker(
if (deviceStatuses.isNotEmpty()) {
rxBus.send(EventNSClientNewLog("RCV", "${deviceStatuses.size} DSs from ${dateUtil.dateAndTimeAndSecondsString(from)}"))
nsDeviceStatusHandler.handleNewData(deviceStatuses.toTypedArray())
rxBus.send(EventNSClientNewLog("DONE DS", ""))
} else {
rxBus.send(EventNSClientNewLog("END", "No DSs from ${dateUtil.dateAndTimeAndSecondsString(from)}"))
rxBus.send(EventNSClientNewLog("RCV END", "No DSs from ${dateUtil.dateAndTimeAndSecondsString(from)}"))
}
WorkManager.getInstance(context)
.enqueueUniqueWork(

View file

@ -9,12 +9,16 @@ import androidx.work.workDataOf
import info.nightscout.core.utils.receivers.DataWorkerStorage
import info.nightscout.core.utils.worker.LoggingWorker
import info.nightscout.interfaces.nsclient.StoreDataForDb
import info.nightscout.interfaces.sync.NsClient
import info.nightscout.plugins.sync.nsclientV3.NSClientV3Plugin
import info.nightscout.rx.bus.RxBus
import info.nightscout.rx.events.EventNSClientNewLog
import info.nightscout.sdk.interfaces.NSAndroidClient
import info.nightscout.sdk.localmodel.treatment.NSTreatment
import info.nightscout.shared.utils.DateUtil
import kotlinx.coroutines.runBlocking
import javax.inject.Inject
import kotlin.math.max
class LoadTreatmentsWorker(
context: Context,
@ -31,34 +35,47 @@ class LoadTreatmentsWorker(
override fun doWorkAndLog(): Result {
var ret = Result.success()
val isFirstLoad = nsClientV3Plugin.isFirstLoad(NsClient.Collection.TREATMENTS)
val lastLoaded =
if (isFirstLoad) max(nsClientV3Plugin.firstLoadContinueTimestamp.collections.treatments, dateUtil.now() - nsClientV3Plugin.maxAge)
else max(nsClientV3Plugin.lastLoadedSrvModified.collections.treatments, dateUtil.now() - nsClientV3Plugin.maxAge)
runBlocking {
if ((nsClientV3Plugin.newestDataOnServer?.collections?.treatments ?: Long.MAX_VALUE) > nsClientV3Plugin.lastLoadedSrvModified.collections.treatments)
if ((nsClientV3Plugin.newestDataOnServer?.collections?.treatments ?: Long.MAX_VALUE) > lastLoaded)
try {
val treatments = nsClientV3Plugin.nsAndroidClient.getTreatmentsModifiedSince(nsClientV3Plugin.lastLoadedSrvModified.collections.treatments, 500)
val treatments: List<NSTreatment>
val response: NSAndroidClient.ReadResponse<List<NSTreatment>>?
if (isFirstLoad) {
treatments = nsClientV3Plugin.nsAndroidClient.getTreatmentsNewerThan(lastLoaded, 500)
response = NSAndroidClient.ReadResponse(0, treatments)
}
else {
response = nsClientV3Plugin.nsAndroidClient.getTreatmentsModifiedSince(lastLoaded, 500)
treatments = response.values
nsClientV3Plugin.lastLoadedSrvModified.collections.treatments = response.lastServerModified
nsClientV3Plugin.storeLastFetched()
}
aapsLogger.debug("TREATMENTS: $treatments")
if (treatments.values.isNotEmpty()) {
rxBus.send(
EventNSClientNewLog(
"RCV",
"${treatments.values.size} TRs from ${dateUtil.dateAndTimeAndSecondsString(nsClientV3Plugin.lastLoadedSrvModified.collections.treatments)}"
)
)
if (treatments.isNotEmpty()) {
val action = if (isFirstLoad) "RCV-FIRST" else "RCV"
rxBus.send(EventNSClientNewLog(action, "${treatments.size} TRs from ${dateUtil.dateAndTimeAndSecondsString(lastLoaded)}"))
// Schedule processing of fetched data and continue of loading
WorkManager.getInstance(context)
.beginUniqueWork(
NSClientV3Plugin.JOB_NAME,
ExistingWorkPolicy.APPEND_OR_REPLACE,
OneTimeWorkRequest.Builder(ProcessTreatmentsWorker::class.java)
.setInputData(dataWorkerStorage.storeInputData(treatments))
.setInputData(dataWorkerStorage.storeInputData(response))
.build()
).then(OneTimeWorkRequest.Builder(LoadTreatmentsWorker::class.java).build())
.enqueue()
} else {
rxBus.send(
EventNSClientNewLog(
"END", "No TRs from ${dateUtil.dateAndTimeAndSecondsString(nsClientV3Plugin.lastLoadedSrvModified.collections.treatments)}"
)
)
// End first load
if (isFirstLoad) {
nsClientV3Plugin.lastLoadedSrvModified.collections.treatments = lastLoaded
nsClientV3Plugin.storeLastFetched()
}
rxBus.send(EventNSClientNewLog("RCV END", "No TRs from ${dateUtil
.dateAndTimeAndSecondsString(lastLoaded)}"))
storeDataForDb.storeTreatmentsToDb()
WorkManager.getInstance(context)
.enqueueUniqueWork(
@ -72,7 +89,13 @@ class LoadTreatmentsWorker(
ret = Result.failure(workDataOf("Error" to error.toString()))
}
else {
rxBus.send(EventNSClientNewLog("END", "No new TRs from ${dateUtil.dateAndTimeAndSecondsString(nsClientV3Plugin.lastLoadedSrvModified.collections.treatments)}"))
// End first load
if (isFirstLoad) {
nsClientV3Plugin.lastLoadedSrvModified.collections.treatments = lastLoaded
nsClientV3Plugin.storeLastFetched()
}
rxBus.send(EventNSClientNewLog("RCV END", "No new TRs from ${dateUtil
.dateAndTimeAndSecondsString(lastLoaded)}"))
storeDataForDb.storeTreatmentsToDb()
WorkManager.getInstance(context)
.enqueueUniqueWork(

View file

@ -62,12 +62,12 @@ class ProcessTreatmentsWorker(
val treatments = dataWorkerStorage.pickupObject(inputData.getLong(DataWorkerStorage.STORE_KEY, -1)) as NSAndroidClient.ReadResponse<List<NSTreatment>>?
?: return Result.failure(workDataOf("Error" to "missing input data"))
var latestDateInReceivedData: Long = 0
val ret = Result.success()
for (treatment in treatments.values) {
aapsLogger.debug(LTag.DATABASE, "Received NS treatment: $treatment")
if (treatment.date > latestDateInReceivedData) latestDateInReceivedData = treatment.date
//Find latest date in treatment
val mills = treatment.date
when (treatment) {
is NSBolus ->
if (sp.getBoolean(info.nightscout.core.utils.R.string.key_ns_receive_insulin, false) || config.NSCLIENT)
@ -136,7 +136,7 @@ class ProcessTreatmentsWorker(
}
}
}
activePlugin.activeNsClient?.updateLatestTreatmentReceivedIfNewer(treatments.lastServerModified)
activePlugin.activeNsClient?.updateLatestTreatmentReceivedIfNewer(latestDateInReceivedData)
// xDripBroadcast.sendTreatments(treatments)
return ret
}

View file

@ -151,7 +151,7 @@
android:title="@string/connection_settings_title">
<SwitchPreference
android:defaultValue="false"
android:defaultValue="true"
android:key="@string/key_ns_cellular"
android:title="@string/ns_cellular" />