NSCv3: upload bolus, srvLastModified for treatments

This commit is contained in:
Milos Kozak 2022-12-13 23:22:22 +01:00
parent 6937a61694
commit bd84d3a2f7
32 changed files with 224 additions and 117 deletions

View file

@ -17,21 +17,24 @@ import org.json.JSONObject
interface DataSyncSelector {
interface DataPair
data class PairTemporaryTarget(val value: TemporaryTarget, val updateRecordId: Long): DataPair
data class PairGlucoseValue(val value: GlucoseValue, val updateRecordId: Long): DataPair
data class PairTherapyEvent(val value: TherapyEvent, val updateRecordId: Long): DataPair
data class PairFood(val value: Food, val updateRecordId: Long): DataPair
data class PairBolus(val value: Bolus, val updateRecordId: Long): DataPair
data class PairCarbs(val value: Carbs, val updateRecordId: Long): DataPair
data class PairBolusCalculatorResult(val value: BolusCalculatorResult, val updateRecordId: Long): DataPair
data class PairTemporaryBasal(val value: TemporaryBasal, val updateRecordId: Long): DataPair
data class PairExtendedBolus(val value: ExtendedBolus, val updateRecordId: Long): DataPair
data class PairProfileSwitch(val value: ProfileSwitch, val updateRecordId: Long): DataPair
data class PairEffectiveProfileSwitch(val value: EffectiveProfileSwitch, val updateRecordId: Long): DataPair
data class PairOfflineEvent(val value: OfflineEvent, val updateRecordId: Long): DataPair
data class PairProfileStore(val value: JSONObject, val timestampSync: Long): DataPair
data class PairDeviceStatus(val value: DeviceStatus, val unused: Long?): DataPair
interface DataPair {
val value: Any
val id: Long
}
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
fun queueSize(): Long

View file

@ -138,11 +138,13 @@ class NSAndroidClientImpl(
}
}
override suspend fun getTreatmentsModifiedSince(from: Long, limit: Long): List<NSTreatment> = callWrapper(dispatcher) {
override suspend fun getTreatmentsModifiedSince(from: Long, limit: Long): NSAndroidClient.ReadResponse<List<NSTreatment>> = callWrapper(dispatcher) {
val response = api.getTreatmentsModifiedSince(from, limit)
val eTagString = response.headers()["ETag"]
val eTag = eTagString?.substring(3, eTagString.length - 1)?.toLong() ?: throw TodoNightscoutException()
if (response.isSuccessful) {
return@callWrapper response.body()?.result?.map(RemoteTreatment::toTreatment).toNotNull()
return@callWrapper NSAndroidClient.ReadResponse(eTag, response.body()?.result?.map(RemoteTreatment::toTreatment).toNotNull())
} else {
throw TodoNightscoutException() // TODO: react to response errors (offline, ...)
}
@ -161,9 +163,11 @@ class NSAndroidClientImpl(
override suspend fun createTreatment(nsTreatment: NSTreatment): CreateUpdateResponse = callWrapper(dispatcher) {
val remoteTreatment = nsTreatment.toRemoteTreatment() ?: throw InvalidFormatNightscoutException()
remoteTreatment.app = "AAPS"
val response = api.createTreatment(remoteTreatment)
if (response.isSuccessful) {
return@callWrapper CreateUpdateResponse(
response = response.code(),
identifier = response.body()?.result?.identifier ?: throw UnknownResponseNightscoutException(),
isDeduplication = response.body()?.result?.isDeduplication ?: false,
deduplicatedIdentifier = response.body()?.result?.deduplicatedIdentifier,
@ -180,6 +184,7 @@ class NSAndroidClientImpl(
val response = api.updateTreatment(remoteTreatment)
if (response.isSuccessful) {
return@callWrapper CreateUpdateResponse(
response = response.code(),
identifier = response.body()?.result?.identifier ?: throw UnknownResponseNightscoutException(),
isDeduplication = response.body()?.result?.isDeduplication ?: false,
deduplicatedIdentifier = response.body()?.result?.deduplicatedIdentifier,

View file

@ -16,7 +16,7 @@ class NSAndroidRxClientImpl(private val client: NSAndroidClient) : NSAndroidRxCl
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 getTreatmentsModifiedSince(from: Long, limit: Long): Single<List<NSTreatment>> =
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>> =
rxSingle { client.getDeviceStatusModifiedSince(from) }

View file

@ -9,6 +9,11 @@ import info.nightscout.sdk.remotemodel.RemoteDeviceStatus
interface NSAndroidClient {
class ReadResponse<T>(
val lastServerModified: Long,
val values: T
)
val lastStatus: Status?
suspend fun getVersion(): String
suspend fun getStatus(): Status
@ -18,7 +23,7 @@ interface NSAndroidClient {
suspend fun getSgvs(): List<NSSgvV3>
suspend fun getSgvsModifiedSince(from: Long): List<NSSgvV3>
suspend fun getSgvsNewerThan(from: Long, limit: Long): List<NSSgvV3>
suspend fun getTreatmentsModifiedSince(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
suspend fun updateTreatment(nsTreatment: NSTreatment): CreateUpdateResponse

View file

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

View file

@ -1,6 +1,7 @@
package info.nightscout.sdk.localmodel.treatment
class CreateUpdateResponse(
val response: Int,
val identifier: String?,
val isDeduplication: Boolean? = false,
val deduplicatedIdentifier: String? = null,

View file

@ -19,6 +19,7 @@ data class NSBolus(
override val endId: Long?,
override val pumpType: String?,
override val pumpSerial: String?,
override var app: String? = null,
val insulin: Double,
val type: BolusType

View file

@ -1,7 +1,6 @@
package info.nightscout.sdk.localmodel.treatment
import info.nightscout.sdk.localmodel.entry.NsUnits
import org.json.JSONObject
data class NSBolusWizard(
override val date: Long,
@ -20,6 +19,7 @@ data class NSBolusWizard(
override val endId: Long?,
override val pumpType: String?,
override val pumpSerial: String?,
override var app: String? = null,
val bolusCalculatorResult: String?,
val glucose: Double?,
) : NSTreatment

View file

@ -19,6 +19,7 @@ data class NSCarbs(
override val endId: Long?,
override val pumpType: String?,
override val pumpSerial: String?,
override var app: String? = null,
val carbs: Double,
val duration: Long
) : NSTreatment

View file

@ -20,6 +20,7 @@ data class NSEffectiveProfileSwitch(
override val endId: Long?,
override val pumpType: String?,
override val pumpSerial: String?,
override var app: String? = null,
val profileJson: JSONObject,
val originalProfileName: String,
val originalCustomizedName: String,

View file

@ -19,6 +19,7 @@ data class NSExtendedBolus(
override val endId: Long?,
override val pumpType: String?,
override val pumpSerial: String?,
override var app: String? = null,
val duration: Long,
val enteredinsulin: Double,
val isEmulatingTempBasal: Boolean?

View file

@ -19,6 +19,7 @@ data class NSOfflineEvent(
override val endId: Long?,
override val pumpType: String?,
override val pumpSerial: String?,
override var app: String? = null,
val duration: Long,
val reason: Reason
) : NSTreatment {

View file

@ -20,6 +20,7 @@ data class NSProfileSwitch(
override val endId: Long?,
override val pumpType: String?,
override val pumpSerial: String?,
override var app: String? = null,
val profileJson: JSONObject?,
val profileName: String,
val originalProfileName: String?,

View file

@ -1,7 +1,6 @@
package info.nightscout.sdk.localmodel.treatment
import info.nightscout.sdk.localmodel.entry.NsUnits
import org.json.JSONObject
data class NSTemporaryBasal(
override val date: Long,
@ -20,6 +19,7 @@ data class NSTemporaryBasal(
override val endId: Long?,
override val pumpType: String?,
override val pumpSerial: String?,
override var app: String? = null,
val duration: Long,
val rate: Double, // when sending to NS always convertedToAbsolute(timestamp, profile)
val isAbsolute: Boolean,

View file

@ -19,6 +19,7 @@ data class NSTemporaryTarget(
override val endId: Long?,
override val pumpType: String?,
override val pumpSerial: String?,
override var app: String? = null,
val duration: Long,
val targetBottom: Double,
val targetTop: Double,

View file

@ -20,6 +20,7 @@ data class NSTherapyEvent(
override val endId: Long?,
override val pumpType: String?,
override val pumpSerial: String?,
override var app: String? = null,
val duration: Long,
var enteredBy: String? = null,
var glucose: Double? = null,

View file

@ -19,6 +19,7 @@ interface NSTreatment {
val endId: Long?
val pumpType: String?
val pumpSerial: String?
var app: String?
fun Double.asMgdl() =
when (units) {

View file

@ -2,18 +2,15 @@ package info.nightscout.sdk.networking
import com.google.gson.JsonElement
import info.nightscout.sdk.remotemodel.LastModified
import info.nightscout.sdk.remotemodel.RemoteDeviceStatus
import info.nightscout.sdk.remotemodel.NSResponse
import info.nightscout.sdk.remotemodel.RemoteCreateUpdateResponse
import info.nightscout.sdk.remotemodel.RemoteDeviceStatus
import info.nightscout.sdk.remotemodel.RemoteEntry
import info.nightscout.sdk.remotemodel.RemoteStatusResponse
import info.nightscout.sdk.remotemodel.RemoteTreatment
import okhttp3.RequestBody
import retrofit2.Call
import retrofit2.Response
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.Header
import retrofit2.http.POST
import retrofit2.http.PUT
import retrofit2.http.Path
@ -57,9 +54,9 @@ internal interface NightscoutRemoteService {
suspend fun getDeviceStatusModifiedSince(@Path("from") from: Long): Response<NSResponse<List<RemoteDeviceStatus>>>
@POST("v3/treatments")
fun createTreatment(@Body remoteTreatment: RemoteTreatment): Response<NSResponse<RemoteCreateUpdateResponse>>
suspend fun createTreatment(@Body remoteTreatment: RemoteTreatment): Response<NSResponse<RemoteCreateUpdateResponse>>
@PUT("v3/treatments")
fun updateTreatment(@Body remoteTreatment: RemoteTreatment): Response<NSResponse<RemoteCreateUpdateResponse>>
suspend fun updateTreatment(@Body remoteTreatment: RemoteTreatment): Response<NSResponse<RemoteCreateUpdateResponse>>
}

View file

@ -1,11 +1,9 @@
package info.nightscout.sdk.remotemodel
import com.google.gson.Gson
import com.google.gson.annotations.SerializedName
import info.nightscout.sdk.localmodel.treatment.EventType
import org.joda.time.DateTime
import org.joda.time.format.ISODateTimeFormat
import org.json.JSONObject
/*
* Depending on the type, different other fields are present.
@ -23,7 +21,7 @@ internal data class RemoteTreatment(
@SerializedName("timestamp") val timestamp: Long? = null, // integer($int64) or string required timestamp when the record or event occurred, you can choose from three input formats Unix epoch in milliseconds (1525383610088), Unix epoch in seconds (1525383610), ISO 8601 with optional timezone ('2018-05-03T21:40:10.088Z' or '2018-05-03T23:40:10.088+02:00')
@SerializedName("created_at") val created_at: String? = null, // integer($int64) or string timestamp on previous version of api, in my examples, a lot of treatments don't have date, only created_at, some of them with string others with long...
@SerializedName("utcOffset") val utcOffset: Long? = null, // integer Local UTC offset (timezone) of the event in minutes. This field can be set either directly by the client (in the incoming document) or it is automatically parsed from the date field.
// @SerializedName("app") val app : String, // TODO required ? Application or system in which the record was entered by human or device for the first time.
@SerializedName("app") var app : String? = null, // Application or system in which the record was entered by human or device for the first time.
@SerializedName("device") val device: String? = null, // string The device from which the data originated (including serial number of the device, if it is relevant and safe).
@SerializedName("srvCreated") val srvCreated: Long? = null, // integer($int64) example: 1525383610088 The server's timestamp of document insertion into the database (Unix epoch in ms). This field appears only for documents which were inserted by API v3.
@SerializedName("subject") val subject: String? = null, // string Name of the security subject (within Nightscout scope) which has created the document. This field is automatically set by the server from the passed token or JWT.

View file

@ -7,9 +7,9 @@ import info.nightscout.interfaces.nsclient.NSSettingsStatus
import info.nightscout.interfaces.nsclient.ProcessedDeviceStatusData
import info.nightscout.interfaces.nsclient.StoreDataForDb
import info.nightscout.interfaces.sync.DataSyncSelector
import info.nightscout.plugins.sync.nsShared.DataSyncSelectorImplementation
import info.nightscout.plugins.sync.nsShared.NSClientFragment
import info.nightscout.plugins.sync.nsShared.StoreDataForDbImpl
import info.nightscout.plugins.sync.nsclient.DataSyncSelectorImplementation
import info.nightscout.plugins.sync.nsclient.data.NSSettingsStatusImpl
import info.nightscout.plugins.sync.nsclient.data.ProcessedDeviceStatusDataImpl
import info.nightscout.plugins.sync.nsclient.services.NSClientService
@ -17,6 +17,7 @@ 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.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.LoadLastModificationWorker
@ -49,6 +50,7 @@ abstract class SyncModule {
@ContributesAndroidInjector abstract fun contributesTreatmentWorker(): LoadTreatmentsWorker
@ContributesAndroidInjector abstract fun contributesProcessTreatmentsWorker(): ProcessTreatmentsWorker
@ContributesAndroidInjector abstract fun contributesLoadDeviceStatusWorker(): LoadDeviceStatusWorker
@ContributesAndroidInjector abstract fun contributesDataSyncWorker(): DataSyncWorker
@ContributesAndroidInjector abstract fun contributesTidepoolFragment(): TidepoolFragment

View file

@ -1,4 +1,4 @@
package info.nightscout.plugins.sync.nsclient
package info.nightscout.plugins.sync.nsShared
import info.nightscout.database.ValueWrapper
import info.nightscout.database.impl.AppRepository
@ -56,11 +56,12 @@ class DataSyncSelectorImplementation @Inject constructor(
}
private val queueCounter = QueueCounter()
private val isPaused get() = sp.getBoolean(R.string.key_ns_client_paused, false)
override fun queueSize(): Long = queueCounter.size()
override fun doUpload() {
if (sp.getBoolean(R.string.key_ns_upload, true)) {
if (sp.getBoolean(R.string.key_ns_upload, true) && !isPaused) {
processChangedBolusesCompat()
processChangedCarbsCompat()
processChangedBolusCalculatorResultsCompat()
@ -106,6 +107,7 @@ class DataSyncSelectorImplementation @Inject constructor(
}
override tailrec fun processChangedBolusesCompat() {
if (isPaused) return
val lastDbIdWrapped = appRepository.getLastBolusIdWrapped().blockingGet()
val lastDbId = if (lastDbIdWrapped is ValueWrapper.Existing) lastDbIdWrapped.value else 0L
var startId = sp.getLong(R.string.key_ns_bolus_last_synced_id, 0)
@ -158,6 +160,7 @@ class DataSyncSelectorImplementation @Inject constructor(
}
override tailrec fun processChangedCarbsCompat() {
if (isPaused) return
val lastDbIdWrapped = appRepository.getLastCarbsIdWrapped().blockingGet()
val lastDbId = if (lastDbIdWrapped is ValueWrapper.Existing) lastDbIdWrapped.value else 0L
var startId = sp.getLong(R.string.key_ns_carbs_last_synced_id, 0)
@ -206,6 +209,7 @@ class DataSyncSelectorImplementation @Inject constructor(
}
override tailrec fun processChangedBolusCalculatorResultsCompat() {
if (isPaused) return
val lastDbIdWrapped = appRepository.getLastBolusCalculatorResultIdWrapped().blockingGet()
val lastDbId = if (lastDbIdWrapped is ValueWrapper.Existing) lastDbIdWrapped.value else 0L
var startId = sp.getLong(R.string.key_ns_bolus_calculator_result_last_synced_id, 0)
@ -257,6 +261,7 @@ class DataSyncSelectorImplementation @Inject constructor(
}
override tailrec fun processChangedTempTargetsCompat() {
if (isPaused) return
val lastDbIdWrapped = appRepository.getLastTempTargetIdWrapped().blockingGet()
val lastDbId = if (lastDbIdWrapped is ValueWrapper.Existing) lastDbIdWrapped.value else 0L
var startId = sp.getLong(R.string.key_ns_temporary_target_last_synced_id, 0)
@ -309,6 +314,7 @@ class DataSyncSelectorImplementation @Inject constructor(
}
override tailrec fun processChangedFoodsCompat() {
if (isPaused) return
val lastDbIdWrapped = appRepository.getLastFoodIdWrapped().blockingGet()
val lastDbId = if (lastDbIdWrapped is ValueWrapper.Existing) lastDbIdWrapped.value else 0L
var startId = sp.getLong(R.string.key_ns_food_last_synced_id, 0)
@ -357,6 +363,7 @@ class DataSyncSelectorImplementation @Inject constructor(
}
override tailrec fun processChangedGlucoseValuesCompat() {
if (isPaused) return
val lastDbIdWrapped = appRepository.getLastGlucoseValueIdWrapped().blockingGet()
val lastDbId = if (lastDbIdWrapped is ValueWrapper.Existing) lastDbIdWrapped.value else 0L
var startId = sp.getLong(R.string.key_ns_glucose_value_last_synced_id, 0)
@ -369,7 +376,7 @@ class DataSyncSelectorImplementation @Inject constructor(
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
// 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)
@ -410,6 +417,7 @@ class DataSyncSelectorImplementation @Inject constructor(
}
override tailrec fun processChangedTherapyEventsCompat() {
if (isPaused) return
val lastDbIdWrapped = appRepository.getLastTherapyEventIdWrapped().blockingGet()
val lastDbId = if (lastDbIdWrapped is ValueWrapper.Existing) lastDbIdWrapped.value else 0L
var startId = sp.getLong(R.string.key_ns_therapy_event_last_synced_id, 0)
@ -458,6 +466,7 @@ class DataSyncSelectorImplementation @Inject constructor(
}
override fun processChangedDeviceStatusesCompat() {
if (isPaused) return
val lastDbIdWrapped = appRepository.getLastDeviceStatusIdWrapped().blockingGet()
val lastDbId = if (lastDbIdWrapped is ValueWrapper.Existing) lastDbIdWrapped.value else 0L
var startId = sp.getLong(R.string.key_ns_device_status_last_synced_id, 0)
@ -471,7 +480,7 @@ class DataSyncSelectorImplementation @Inject constructor(
when {
// without nsId = create new
deviceStatus.interfaceIDs.nightscoutId == null ->
activePlugin.activeNsClient?.dbAdd("devicestatus", DataSyncSelector.PairDeviceStatus(deviceStatus, null), "$startId/$lastDbId")
activePlugin.activeNsClient?.dbAdd("devicestatus", DataSyncSelector.PairDeviceStatus(deviceStatus, 0), "$startId/$lastDbId")
// with nsId = ignore
deviceStatus.interfaceIDs.nightscoutId != null -> Any()
}
@ -487,6 +496,7 @@ class DataSyncSelectorImplementation @Inject constructor(
}
override tailrec fun processChangedTemporaryBasalsCompat() {
if (isPaused) return
val lastDbIdWrapped = appRepository.getLastTemporaryBasalIdWrapped().blockingGet()
val lastDbId = if (lastDbIdWrapped is ValueWrapper.Existing) lastDbIdWrapped.value else 0L
var startId = sp.getLong(R.string.key_ns_temporary_basal_last_synced_id, 0)
@ -539,6 +549,7 @@ class DataSyncSelectorImplementation @Inject constructor(
}
override tailrec fun processChangedExtendedBolusesCompat() {
if (isPaused) return
val lastDbIdWrapped = appRepository.getLastExtendedBolusIdWrapped().blockingGet()
val lastDbId = if (lastDbIdWrapped is ValueWrapper.Existing) lastDbIdWrapped.value else 0L
var startId = sp.getLong(R.string.key_ns_extended_bolus_last_synced_id, 0)
@ -599,6 +610,7 @@ class DataSyncSelectorImplementation @Inject constructor(
}
override tailrec fun processChangedProfileSwitchesCompat() {
if (isPaused) return
val lastDbIdWrapped = appRepository.getLastProfileSwitchIdWrapped().blockingGet()
val lastDbId = if (lastDbIdWrapped is ValueWrapper.Existing) lastDbIdWrapped.value else 0L
var startId = sp.getLong(R.string.key_ns_profile_switch_last_synced_id, 0)
@ -647,6 +659,7 @@ class DataSyncSelectorImplementation @Inject constructor(
}
override tailrec fun processChangedEffectiveProfileSwitchesCompat() {
if (isPaused) return
val lastDbIdWrapped = appRepository.getLastEffectiveProfileSwitchIdWrapped().blockingGet()
val lastDbId = if (lastDbIdWrapped is ValueWrapper.Existing) lastDbIdWrapped.value else 0L
var startId = sp.getLong(R.string.key_ns_effective_profile_switch_last_synced_id, 0)
@ -699,6 +712,7 @@ class DataSyncSelectorImplementation @Inject constructor(
}
override tailrec fun processChangedOfflineEventsCompat() {
if (isPaused) return
val lastDbIdWrapped = appRepository.getLastOfflineEventIdWrapped().blockingGet()
val lastDbId = if (lastDbIdWrapped is ValueWrapper.Existing) lastDbIdWrapped.value else 0L
var startId = sp.getLong(R.string.key_ns_offline_event_last_synced_id, 0)
@ -744,6 +758,7 @@ class DataSyncSelectorImplementation @Inject constructor(
}
override 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
@ -753,4 +768,4 @@ class DataSyncSelectorImplementation @Inject constructor(
activePlugin.activeNsClient?.dbAdd("profile", DataSyncSelector.PairProfileStore(profileJson, dateUtil.now()), "")
}
}
}
}

View file

@ -26,7 +26,6 @@ import info.nightscout.interfaces.sync.NsClient
import info.nightscout.plugins.sync.R
import info.nightscout.plugins.sync.databinding.NsClientFragmentBinding
import info.nightscout.plugins.sync.nsShared.events.EventNSClientUpdateGUI
import info.nightscout.plugins.sync.nsclientV3.NSClientV3Plugin
import info.nightscout.rx.AapsSchedulers
import info.nightscout.rx.bus.RxBus
import info.nightscout.rx.events.EventNSClientRestart
@ -56,7 +55,6 @@ class NSClientFragment : DaggerFragment(), MenuProvider, PluginFragment {
const val ID_MENU_RESTART = 508
const val ID_MENU_SEND_NOW = 509
const val ID_MENU_FULL_SYNC = 510
const val ID_MENU_TEST = 601
}
override var plugin: PluginBase? = null
@ -97,8 +95,6 @@ class NSClientFragment : DaggerFragment(), MenuProvider, PluginFragment {
}
override fun onCreateMenu(menu: Menu, inflater: MenuInflater) {
if (config.isUnfinishedMode())
menu.add(Menu.FIRST, ID_MENU_TEST, 0, "Test").setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER)
menu.add(Menu.FIRST, ID_MENU_CLEAR_LOG, 0, rh.gs(R.string.clear_log)).setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER)
menu.add(Menu.FIRST, ID_MENU_RESTART, 0, rh.gs(R.string.restart)).setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER)
menu.add(Menu.FIRST, ID_MENU_SEND_NOW, 0, rh.gs(R.string.deliver_now)).setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER)
@ -133,11 +129,6 @@ class NSClientFragment : DaggerFragment(), MenuProvider, PluginFragment {
true
}
ID_MENU_TEST -> {
nsClientPlugin?.let { plugin -> if (plugin is NSClientV3Plugin) handler.post { plugin.test() } }
true
}
else -> false
}

View file

@ -580,7 +580,7 @@ class NSClientService : DaggerService() {
socket?.emit("dbUpdate", message, NSUpdateAck("dbUpdate", _id, aapsLogger, rxBus, this, dateUtil, dataWorkerStorage, originalObject))
rxBus.send(
EventNSClientNewLog(
"DBUPDATE $collection", "Sent " + originalObject.javaClass.simpleName + " " +
"UPDATE $collection", "Sent " + originalObject.javaClass.simpleName + " " +
"" + _id + " " + data + progress
)
)
@ -596,7 +596,7 @@ class NSClientService : DaggerService() {
message.put("collection", collection)
message.put("data", data)
socket?.emit("dbAdd", message, NSAddAck(aapsLogger, rxBus, this, dateUtil, dataWorkerStorage, originalObject))
rxBus.send(EventNSClientNewLog("DBADD $collection", "Sent " + originalObject.javaClass.simpleName + " " + data + " " + progress))
rxBus.send(EventNSClientNewLog("ADD $collection", "Sent " + originalObject.javaClass.simpleName + " " + data + " " + progress))
} catch (e: JSONException) {
aapsLogger.error("Unhandled exception", e)
}

View file

@ -55,7 +55,7 @@ class NSClientAddAckWorker(
val pair = ack.originalObject
pair.value.interfaceIDs.nightscoutId = ack.id
storeDataForDb.nsIdTemporaryTargets.add(pair.value)
dataSyncSelector.confirmLastTempTargetsIdIfGreater(pair.updateRecordId)
dataSyncSelector.confirmLastTempTargetsIdIfGreater(pair.id)
storeDataForDb.scheduleNsIdUpdate()
rxBus.send(EventNSClientNewLog("DBADD", "Acked TemporaryTarget " + pair.value.interfaceIDs.nightscoutId))
// Send new if waiting
@ -66,7 +66,7 @@ class NSClientAddAckWorker(
val pair = ack.originalObject
pair.value.interfaceIDs.nightscoutId = ack.id
storeDataForDb.nsIdGlucoseValues.add(pair.value)
dataSyncSelector.confirmLastGlucoseValueIdIfGreater(pair.updateRecordId)
dataSyncSelector.confirmLastGlucoseValueIdIfGreater(pair.id)
storeDataForDb.scheduleNsIdUpdate()
rxBus.send(EventNSClientNewLog("DBADD", "Acked GlucoseValue " + pair.value.interfaceIDs.nightscoutId))
// Send new if waiting
@ -77,7 +77,7 @@ class NSClientAddAckWorker(
val pair = ack.originalObject
pair.value.interfaceIDs.nightscoutId = ack.id
storeDataForDb.nsIdFoods.add(pair.value)
dataSyncSelector.confirmLastFoodIdIfGreater(pair.updateRecordId)
dataSyncSelector.confirmLastFoodIdIfGreater(pair.id)
storeDataForDb.scheduleNsIdUpdate()
rxBus.send(EventNSClientNewLog("DBADD", "Acked Food " + pair.value.interfaceIDs.nightscoutId))
// Send new if waiting
@ -88,7 +88,7 @@ class NSClientAddAckWorker(
val pair = ack.originalObject
pair.value.interfaceIDs.nightscoutId = ack.id
storeDataForDb.nsIdTherapyEvents.add(pair.value)
dataSyncSelector.confirmLastTherapyEventIdIfGreater(pair.updateRecordId)
dataSyncSelector.confirmLastTherapyEventIdIfGreater(pair.id)
storeDataForDb.scheduleNsIdUpdate()
rxBus.send(EventNSClientNewLog("DBADD", "Acked TherapyEvent " + pair.value.interfaceIDs.nightscoutId))
// Send new if waiting
@ -99,7 +99,7 @@ class NSClientAddAckWorker(
val pair = ack.originalObject
pair.value.interfaceIDs.nightscoutId = ack.id
storeDataForDb.nsIdBoluses.add(pair.value)
dataSyncSelector.confirmLastBolusIdIfGreater(pair.updateRecordId)
dataSyncSelector.confirmLastBolusIdIfGreater(pair.id)
storeDataForDb.scheduleNsIdUpdate()
rxBus.send(EventNSClientNewLog("DBADD", "Acked Bolus " + pair.value.interfaceIDs.nightscoutId))
// Send new if waiting
@ -110,7 +110,7 @@ class NSClientAddAckWorker(
val pair = ack.originalObject
pair.value.interfaceIDs.nightscoutId = ack.id
storeDataForDb.nsIdCarbs.add(pair.value)
dataSyncSelector.confirmLastCarbsIdIfGreater(pair.updateRecordId)
dataSyncSelector.confirmLastCarbsIdIfGreater(pair.id)
storeDataForDb.scheduleNsIdUpdate()
rxBus.send(EventNSClientNewLog("DBADD", "Acked Carbs " + pair.value.interfaceIDs.nightscoutId))
// Send new if waiting
@ -121,7 +121,7 @@ class NSClientAddAckWorker(
val pair = ack.originalObject
pair.value.interfaceIDs.nightscoutId = ack.id
storeDataForDb.nsIdBolusCalculatorResults.add(pair.value)
dataSyncSelector.confirmLastBolusCalculatorResultsIdIfGreater(pair.updateRecordId)
dataSyncSelector.confirmLastBolusCalculatorResultsIdIfGreater(pair.id)
storeDataForDb.scheduleNsIdUpdate()
rxBus.send(EventNSClientNewLog("DBADD", "Acked BolusCalculatorResult " + pair.value.interfaceIDs.nightscoutId))
// Send new if waiting
@ -132,7 +132,7 @@ class NSClientAddAckWorker(
val pair = ack.originalObject
pair.value.interfaceIDs.nightscoutId = ack.id
storeDataForDb.nsIdTemporaryBasals.add(pair.value)
dataSyncSelector.confirmLastTemporaryBasalIdIfGreater(pair.updateRecordId)
dataSyncSelector.confirmLastTemporaryBasalIdIfGreater(pair.id)
storeDataForDb.scheduleNsIdUpdate()
rxBus.send(EventNSClientNewLog("DBADD", "Acked TemporaryBasal " + pair.value.interfaceIDs.nightscoutId))
// Send new if waiting
@ -143,7 +143,7 @@ class NSClientAddAckWorker(
val pair = ack.originalObject
pair.value.interfaceIDs.nightscoutId = ack.id
storeDataForDb.nsIdExtendedBoluses.add(pair.value)
dataSyncSelector.confirmLastExtendedBolusIdIfGreater(pair.updateRecordId)
dataSyncSelector.confirmLastExtendedBolusIdIfGreater(pair.id)
storeDataForDb.scheduleNsIdUpdate()
rxBus.send(EventNSClientNewLog("DBADD", "Acked ExtendedBolus " + pair.value.interfaceIDs.nightscoutId))
// Send new if waiting
@ -154,7 +154,7 @@ class NSClientAddAckWorker(
val pair = ack.originalObject
pair.value.interfaceIDs.nightscoutId = ack.id
storeDataForDb.nsIdProfileSwitches.add(pair.value)
dataSyncSelector.confirmLastProfileSwitchIdIfGreater(pair.updateRecordId)
dataSyncSelector.confirmLastProfileSwitchIdIfGreater(pair.id)
storeDataForDb.scheduleNsIdUpdate()
rxBus.send(EventNSClientNewLog("DBADD", "Acked ProfileSwitch " + pair.value.interfaceIDs.nightscoutId))
// Send new if waiting
@ -165,7 +165,7 @@ class NSClientAddAckWorker(
val pair = ack.originalObject
pair.value.interfaceIDs.nightscoutId = ack.id
storeDataForDb.nsIdEffectiveProfileSwitches.add(pair.value)
dataSyncSelector.confirmLastEffectiveProfileSwitchIdIfGreater(pair.updateRecordId)
dataSyncSelector.confirmLastEffectiveProfileSwitchIdIfGreater(pair.id)
storeDataForDb.scheduleNsIdUpdate()
rxBus.send(EventNSClientNewLog("DBADD", "Acked EffectiveProfileSwitch " + pair.value.interfaceIDs.nightscoutId))
// Send new if waiting
@ -184,7 +184,7 @@ class NSClientAddAckWorker(
}
is PairProfileStore -> {
dataSyncSelector.confirmLastProfileStore(ack.originalObject.timestampSync)
dataSyncSelector.confirmLastProfileStore(ack.originalObject.id)
rxBus.send(EventNSClientNewLog("DBADD", "Acked ProfileStore " + ack.id))
}
@ -192,7 +192,7 @@ class NSClientAddAckWorker(
val pair = ack.originalObject
pair.value.interfaceIDs.nightscoutId = ack.id
storeDataForDb.nsIdOfflineEvents.add(pair.value)
dataSyncSelector.confirmLastOfflineEventIdIfGreater(pair.updateRecordId)
dataSyncSelector.confirmLastOfflineEventIdIfGreater(pair.id)
storeDataForDb.scheduleNsIdUpdate()
rxBus.send(EventNSClientNewLog("DBADD", "Acked OfflineEvent " + pair.value.interfaceIDs.nightscoutId))
// Send new if waiting

View file

@ -46,7 +46,7 @@ class NSClientUpdateRemoveAckWorker(
when (ack.originalObject) {
is PairTemporaryTarget -> {
val pair = ack.originalObject
dataSyncSelector.confirmLastTempTargetsIdIfGreater(pair.updateRecordId)
dataSyncSelector.confirmLastTempTargetsIdIfGreater(pair.id)
rxBus.send(EventNSClientNewLog("DBUPDATE", "Acked TemporaryTarget" + ack._id))
// Send new if waiting
dataSyncSelector.processChangedTempTargetsCompat()
@ -55,7 +55,7 @@ class NSClientUpdateRemoveAckWorker(
is PairGlucoseValue -> {
val pair = ack.originalObject
dataSyncSelector.confirmLastGlucoseValueIdIfGreater(pair.updateRecordId)
dataSyncSelector.confirmLastGlucoseValueIdIfGreater(pair.id)
rxBus.send(EventNSClientNewLog("DBUPDATE", "Acked GlucoseValue " + ack._id))
// Send new if waiting
dataSyncSelector.processChangedGlucoseValuesCompat()
@ -64,7 +64,7 @@ class NSClientUpdateRemoveAckWorker(
is PairFood -> {
val pair = ack.originalObject
dataSyncSelector.confirmLastFoodIdIfGreater(pair.updateRecordId)
dataSyncSelector.confirmLastFoodIdIfGreater(pair.id)
rxBus.send(EventNSClientNewLog("DBUPDATE", "Acked Food " + ack._id))
// Send new if waiting
dataSyncSelector.processChangedFoodsCompat()
@ -73,7 +73,7 @@ class NSClientUpdateRemoveAckWorker(
is PairTherapyEvent -> {
val pair = ack.originalObject
dataSyncSelector.confirmLastTherapyEventIdIfGreater(pair.updateRecordId)
dataSyncSelector.confirmLastTherapyEventIdIfGreater(pair.id)
rxBus.send(EventNSClientNewLog("DBUPDATE", "Acked TherapyEvent " + ack._id))
// Send new if waiting
dataSyncSelector.processChangedTherapyEventsCompat()
@ -82,7 +82,7 @@ class NSClientUpdateRemoveAckWorker(
is PairBolus -> {
val pair = ack.originalObject
dataSyncSelector.confirmLastBolusIdIfGreater(pair.updateRecordId)
dataSyncSelector.confirmLastBolusIdIfGreater(pair.id)
rxBus.send(EventNSClientNewLog("DBUPDATE", "Acked Bolus " + ack._id))
// Send new if waiting
dataSyncSelector.processChangedBolusesCompat()
@ -91,7 +91,7 @@ class NSClientUpdateRemoveAckWorker(
is PairCarbs -> {
val pair = ack.originalObject
dataSyncSelector.confirmLastCarbsIdIfGreater(pair.updateRecordId)
dataSyncSelector.confirmLastCarbsIdIfGreater(pair.id)
rxBus.send(EventNSClientNewLog("DBUPDATE", "Acked Carbs " + ack._id))
// Send new if waiting
dataSyncSelector.processChangedCarbsCompat()
@ -100,7 +100,7 @@ class NSClientUpdateRemoveAckWorker(
is PairBolusCalculatorResult -> {
val pair = ack.originalObject
dataSyncSelector.confirmLastBolusCalculatorResultsIdIfGreater(pair.updateRecordId)
dataSyncSelector.confirmLastBolusCalculatorResultsIdIfGreater(pair.id)
rxBus.send(EventNSClientNewLog("DBUPDATE", "Acked BolusCalculatorResult " + ack._id))
// Send new if waiting
dataSyncSelector.processChangedBolusCalculatorResultsCompat()
@ -109,7 +109,7 @@ class NSClientUpdateRemoveAckWorker(
is PairTemporaryBasal -> {
val pair = ack.originalObject
dataSyncSelector.confirmLastTemporaryBasalIdIfGreater(pair.updateRecordId)
dataSyncSelector.confirmLastTemporaryBasalIdIfGreater(pair.id)
rxBus.send(EventNSClientNewLog("DBUPDATE", "Acked TemporaryBasal " + ack._id))
// Send new if waiting
dataSyncSelector.processChangedTemporaryBasalsCompat()
@ -118,7 +118,7 @@ class NSClientUpdateRemoveAckWorker(
is PairExtendedBolus -> {
val pair = ack.originalObject
dataSyncSelector.confirmLastExtendedBolusIdIfGreater(pair.updateRecordId)
dataSyncSelector.confirmLastExtendedBolusIdIfGreater(pair.id)
rxBus.send(EventNSClientNewLog("DBUPDATE", "Acked ExtendedBolus " + ack._id))
// Send new if waiting
dataSyncSelector.processChangedExtendedBolusesCompat()
@ -127,7 +127,7 @@ class NSClientUpdateRemoveAckWorker(
is PairProfileSwitch -> {
val pair = ack.originalObject
dataSyncSelector.confirmLastProfileSwitchIdIfGreater(pair.updateRecordId)
dataSyncSelector.confirmLastProfileSwitchIdIfGreater(pair.id)
rxBus.send(EventNSClientNewLog("DBUPDATE", "Acked ProfileSwitch " + ack._id))
// Send new if waiting
dataSyncSelector.processChangedProfileSwitchesCompat()
@ -136,7 +136,7 @@ class NSClientUpdateRemoveAckWorker(
is PairEffectiveProfileSwitch -> {
val pair = ack.originalObject
dataSyncSelector.confirmLastEffectiveProfileSwitchIdIfGreater(pair.updateRecordId)
dataSyncSelector.confirmLastEffectiveProfileSwitchIdIfGreater(pair.id)
rxBus.send(EventNSClientNewLog("DBUPDATE", "Acked EffectiveProfileSwitch " + ack._id))
// Send new if waiting
dataSyncSelector.processChangedEffectiveProfileSwitchesCompat()
@ -145,7 +145,7 @@ class NSClientUpdateRemoveAckWorker(
is PairOfflineEvent -> {
val pair = ack.originalObject
dataSyncSelector.confirmLastOfflineEventIdIfGreater(pair.updateRecordId)
dataSyncSelector.confirmLastOfflineEventIdIfGreater(pair.id)
rxBus.send(EventNSClientNewLog("DBUPDATE", "Acked OfflineEvent" + ack._id))
// Send new if waiting
dataSyncSelector.processChangedOfflineEventsCompat()

View file

@ -11,11 +11,15 @@ import androidx.work.ExistingWorkPolicy
import androidx.work.OneTimeWorkRequest
import androidx.work.WorkInfo
import androidx.work.WorkManager
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import dagger.android.HasAndroidInjector
import info.nightscout.core.utils.fabric.FabricPrivacy
import info.nightscout.database.entities.interfaces.TraceableDBEntry
import info.nightscout.interfaces.Config
import info.nightscout.interfaces.Constants
import info.nightscout.interfaces.nsclient.NSAlarm
import info.nightscout.interfaces.nsclient.StoreDataForDb
import info.nightscout.interfaces.plugin.PluginBase
import info.nightscout.interfaces.plugin.PluginDescription
import info.nightscout.interfaces.plugin.PluginType
@ -71,7 +75,9 @@ class NSClientV3Plugin @Inject constructor(
private val nsClientReceiverDelegate: NsClientReceiverDelegate,
private val config: Config,
private val dateUtil: DateUtil,
private val uiInteraction: UiInteraction
private val uiInteraction: UiInteraction,
private val storeDataForDb: StoreDataForDb,
private val dataSyncSelector: DataSyncSelector
) : NsClient, Sync, PluginBase(
PluginDescription()
.mainType(PluginType.SYNC)
@ -113,8 +119,8 @@ class NSClientV3Plugin @Inject constructor(
val blockingReason get() = nsClientReceiverDelegate.blockingReason
private val maxAge = T.days(77).msecs()
internal var lastModified: LastModified? = null // timestamp of last modification for every collection
internal var lastFetched =
internal var newestDataOnServer: LastModified? = null // timestamp of last modification for every collection
internal var lastLoadedSrvModified =
LastModified(
LastModified.Collections(
dateUtil.now() - maxAge,
@ -128,7 +134,7 @@ class NSClientV3Plugin @Inject constructor(
// context.bindService(Intent(context, NSClientService::class.java), mConnection, Context.BIND_AUTO_CREATE)
super.onStart()
lastFetched = Json.decodeFromString(
lastLoadedSrvModified = Json.decodeFromString(
sp.getString(
R.string.key_ns_client_v3_last_modified,
Json.encodeToString(
@ -137,10 +143,10 @@ class NSClientV3Plugin @Inject constructor(
)
)
)
lastFetched.collections.entries = max(dateUtil.now() - maxAge, lastFetched.collections.entries)
lastFetched.collections.treatments = max(dateUtil.now() - maxAge, lastFetched.collections.treatments)
lastFetched.collections.profile = max(dateUtil.now() - maxAge, lastFetched.collections.profile)
lastFetched.collections.devicestatus = max(dateUtil.now() - maxAge, lastFetched.collections.devicestatus)
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()
@ -251,7 +257,7 @@ class NSClientV3Plugin @Inject constructor(
}
override fun resend(reason: String) {
// nsClientService?.resend(reason)
executeLoop()
}
override fun pause(newState: Boolean) {
@ -278,19 +284,19 @@ class NSClientV3Plugin @Inject constructor(
}
override fun updateLatestBgReceivedIfNewer(latestReceived: Long) {
if (latestReceived > lastFetched.collections.entries) {
lastFetched.collections.entries = latestReceived
if (latestReceived > lastLoadedSrvModified.collections.entries) {
lastLoadedSrvModified.collections.entries = latestReceived
storeLastFetched()
}
}
override fun updateLatestTreatmentReceivedIfNewer(latestReceived: Long) {
lastFetched.collections.treatments = latestReceived
lastLoadedSrvModified.collections.treatments = latestReceived
storeLastFetched()
}
override fun resetToFullSync() {
lastFetched = LastModified(
lastLoadedSrvModified = LastModified(
LastModified.Collections(
dateUtil.now() - maxAge,
dateUtil.now() - maxAge,
@ -302,6 +308,20 @@ class NSClientV3Plugin @Inject constructor(
}
override fun dbAdd(collection: String, dataPair: DataSyncSelector.DataPair, progress: String) {
dbOperation(collection, dataPair, progress, Operation.CREATE)
}
override fun dbUpdate(collection: String, dataPair: DataSyncSelector.DataPair, progress: String) {
dbOperation(collection, dataPair, progress, Operation.UPDATE)
}
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) {
Operation.CREATE -> nsAndroidClient::createTreatment
Operation.UPDATE -> nsAndroidClient::updateTreatment
}
when (dataPair) {
is DataSyncSelector.PairBolus -> dataPair.value.toNSBolus()
// is DataSyncSelector.PairCarbs -> dataPair.value.toJson(false, dateUtil)
@ -319,18 +339,51 @@ class NSClientV3Plugin @Inject constructor(
}?.let { data ->
runBlocking {
if (collection == "treatments") {
val result = nsAndroidClient.createTreatment(data)
try {
val id = if (dataPair.value is TraceableDBEntry) (dataPair.value as TraceableDBEntry).interfaceIDs.nightscoutId else ""
rxBus.send(
EventNSClientNewLog(
when(operation) {
Operation.CREATE -> "ADD $collection"
Operation.UPDATE -> "UPDATE $collection"
},
when(operation) {
Operation.CREATE -> "Sent ${dataPair.javaClass.simpleName} ${gson.toJson(data)} $progress"
Operation.UPDATE -> "Sent ${dataPair.javaClass.simpleName} $id ${gson.toJson(data)} $progress"
}
)
)
val result = call(data)
when (dataPair) {
is DataSyncSelector.PairBolus -> {
if (result.response == 201) { // created
dataPair.value.interfaceIDs.nightscoutId = result.identifier
storeDataForDb.nsIdBoluses.add(dataPair.value)
storeDataForDb.scheduleNsIdUpdate()
}
dataSyncSelector.confirmLastBolusIdIfGreater(dataPair.id)
}
// is DataSyncSelector.PairCarbs -> dataPair.value.toJson(false, dateUtil)
// is DataSyncSelector.PairBolusCalculatorResult -> dataPair.value.toJson(false, dateUtil, profileFunction)
// is DataSyncSelector.PairTemporaryTarget -> dataPair.value.toJson(false, profileFunction.getUnits(), dateUtil)
// is DataSyncSelector.PairFood -> dataPair.value.toJson(false)
// is DataSyncSelector.PairGlucoseValue -> dataPair.value.toJson(false, dateUtil)
// is DataSyncSelector.PairTherapyEvent -> dataPair.value.toJson(false, dateUtil)
// is DataSyncSelector.PairTemporaryBasal -> dataPair.value.toJson(false, profileFunction.getProfile(dataPair.value.timestamp), dateUtil)
// is DataSyncSelector.PairExtendedBolus -> dataPair.value.toJson(false, profileFunction.getProfile(dataPair.value.timestamp), dateUtil)
// is DataSyncSelector.PairProfileSwitch -> dataPair.value.toJson(false, dateUtil)
// is DataSyncSelector.PairEffectiveProfileSwitch -> dataPair.value.toJson(false, dateUtil)
// is DataSyncSelector.PairOfflineEvent -> dataPair.value.toJson(false, dateUtil)
}
} catch (e: Exception) {
aapsLogger.error(LTag.NSCLIENT, "Upload exception", e)
}
}
}
}
}
override fun dbUpdate(collection: String, dataPair: DataSyncSelector.DataPair, progress: String) {
TODO("Not yet implemented")
}
private fun storeLastFetched() {
sp.putString(R.string.key_ns_client_v3_last_modified, Json.encodeToString(LastModified.serializer(), lastFetched))
sp.putString(R.string.key_ns_client_v3_last_modified, Json.encodeToString(LastModified.serializer(), lastLoadedSrvModified))
}
fun test() {
@ -338,7 +391,7 @@ class NSClientV3Plugin @Inject constructor(
}
fun scheduleNewExecution() {
val toTime = lastFetched.collections.entries + T.mins(6).plus(T.secs(0)).msecs()
val toTime = lastLoadedSrvModified.collections.entries + T.mins(6).plus(T.secs(0)).msecs()
if (toTime > dateUtil.now()) {
handler.postDelayed({ executeLoop() }, toTime - dateUtil.now())
rxBus.send(EventNSClientNewLog("NEXT", dateUtil.dateAndTimeAndSecondsString(toTime)))
@ -366,8 +419,10 @@ class NSClientV3Plugin @Inject constructor(
)
.then(OneTimeWorkRequest.Builder(LoadLastModificationWorker::class.java).build())
.then(OneTimeWorkRequest.Builder(LoadBgWorker::class.java).build())
// LoadTreatmentsWorker is enqueued after BG finish
//.then(OneTimeWorkRequest.Builder(LoadTreatmentsWorker::class.java).build())
// Other Workers are enqueued after BG finish
// LoadTreatmentsWorker
// LoadDeviceStatusWorker
// DataSyncWorker
.enqueue()
}
}

View file

@ -0,0 +1,21 @@
package info.nightscout.plugins.sync.nsclientV3.workers
import android.content.Context
import androidx.work.WorkerParameters
import info.nightscout.core.utils.worker.LoggingWorker
import info.nightscout.interfaces.plugin.ActivePlugin
import info.nightscout.interfaces.sync.DataSyncSelector
import javax.inject.Inject
class DataSyncWorker(
context: Context, params: WorkerParameters
) : LoggingWorker(context, params) {
@Inject lateinit var dataSyncSelector: DataSyncSelector
@Inject lateinit var activePlugin: ActivePlugin
override fun doWorkAndLog(): Result {
if (activePlugin.activeNsClient?.hasWritePermission == true) dataSyncSelector.doUpload()
return Result.success()
}
}

View file

@ -39,16 +39,16 @@ class LoadBgWorker(
var ret = Result.success()
runBlocking {
if ((nsClientV3Plugin.lastModified?.collections?.entries ?: Long.MAX_VALUE) > nsClientV3Plugin.lastFetched.collections.entries)
if ((nsClientV3Plugin.newestDataOnServer?.collections?.entries ?: Long.MAX_VALUE) > nsClientV3Plugin.lastLoadedSrvModified.collections.entries)
try {
//val sgvs = nsClientV3Plugin.nsAndroidClient.getSgvsModifiedSince(nsClientV3Plugin.lastFetched.collections.entries)
val sgvs = nsClientV3Plugin.nsAndroidClient.getSgvsNewerThan(nsClientV3Plugin.lastFetched.collections.entries, 500)
val sgvs = nsClientV3Plugin.nsAndroidClient.getSgvsNewerThan(nsClientV3Plugin.lastLoadedSrvModified.collections.entries, 500)
aapsLogger.debug("SGVS: $sgvs")
if (sgvs.isNotEmpty()) {
rxBus.send(
EventNSClientNewLog(
"RCV",
"${sgvs.size} SVGs from ${dateUtil.dateAndTimeAndSecondsString(nsClientV3Plugin.lastFetched.collections.entries)}"
"${sgvs.size} SVGs from ${dateUtil.dateAndTimeAndSecondsString(nsClientV3Plugin.lastLoadedSrvModified.collections.entries)}"
)
)
// Objective0
@ -60,7 +60,7 @@ 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.lastFetched.collections.entries)}"))
rxBus.send(EventNSClientNewLog("END", "No SGVs from ${dateUtil.dateAndTimeAndSecondsString(nsClientV3Plugin.lastLoadedSrvModified.collections.entries)}"))
WorkManager.getInstance(context)
.beginUniqueWork(
NSClientV3Plugin.JOB_NAME,
@ -75,7 +75,7 @@ class LoadBgWorker(
ret = Result.failure(workDataOf("Error" to error.toString()))
}
else {
rxBus.send(EventNSClientNewLog("END", "No new SGVs from ${dateUtil.dateAndTimeAndSecondsString(nsClientV3Plugin.lastFetched.collections.entries)}"))
rxBus.send(EventNSClientNewLog("END", "No new SGVs from ${dateUtil.dateAndTimeAndSecondsString(nsClientV3Plugin.lastLoadedSrvModified.collections.entries)}"))
nsClientV3Plugin.scheduleNewExecution() // Idea is to run after 5 min after last BG
WorkManager.getInstance(context)
.beginUniqueWork(

View file

@ -1,6 +1,9 @@
package info.nightscout.plugins.sync.nsclientV3.workers
import android.content.Context
import androidx.work.ExistingWorkPolicy
import androidx.work.OneTimeWorkRequest
import androidx.work.WorkManager
import androidx.work.WorkerParameters
import androidx.work.workDataOf
import info.nightscout.core.utils.receivers.DataWorkerStorage
@ -40,6 +43,12 @@ class LoadDeviceStatusWorker(
} else {
rxBus.send(EventNSClientNewLog("END", "No DSs from ${dateUtil.dateAndTimeAndSecondsString(from)}"))
}
WorkManager.getInstance(context)
.enqueueUniqueWork(
NSClientV3Plugin.JOB_NAME,
ExistingWorkPolicy.APPEND_OR_REPLACE,
OneTimeWorkRequest.Builder(DataSyncWorker::class.java).build()
)
} catch (error: Exception) {
aapsLogger.error("Error: ", error)
ret = Result.failure(workDataOf("Error" to error.toString()))

View file

@ -20,8 +20,8 @@ class LoadLastModificationWorker(
runBlocking {
try {
val lm = nsClientV3Plugin.nsAndroidClient.getLastModified()
nsClientV3Plugin.lastModified = lm
aapsLogger.debug("LAST MODIFIED: ${nsClientV3Plugin.lastModified}")
nsClientV3Plugin.newestDataOnServer = lm
aapsLogger.debug("LAST MODIFIED: ${nsClientV3Plugin.newestDataOnServer}")
} catch (error: Exception) {
aapsLogger.error("Error: ", error)
ret = Result.failure(workDataOf("Error" to error.toString()))

View file

@ -32,15 +32,15 @@ class LoadTreatmentsWorker(
var ret = Result.success()
runBlocking {
if ((nsClientV3Plugin.lastModified?.collections?.treatments ?: Long.MAX_VALUE) > nsClientV3Plugin.lastFetched.collections.treatments)
if ((nsClientV3Plugin.newestDataOnServer?.collections?.treatments ?: Long.MAX_VALUE) > nsClientV3Plugin.lastLoadedSrvModified.collections.treatments)
try {
val treatments = nsClientV3Plugin.nsAndroidClient.getTreatmentsModifiedSince(nsClientV3Plugin.lastFetched.collections.treatments, 500)
val treatments = nsClientV3Plugin.nsAndroidClient.getTreatmentsModifiedSince(nsClientV3Plugin.lastLoadedSrvModified.collections.treatments, 500)
aapsLogger.debug("TREATMENTS: $treatments")
if (treatments.isNotEmpty()) {
if (treatments.values.isNotEmpty()) {
rxBus.send(
EventNSClientNewLog(
"RCV",
"${treatments.size} TRs from ${dateUtil.dateAndTimeAndSecondsString(nsClientV3Plugin.lastFetched.collections.treatments)}"
"${treatments.values.size} TRs from ${dateUtil.dateAndTimeAndSecondsString(nsClientV3Plugin.lastLoadedSrvModified.collections.treatments)}"
)
)
// Schedule processing of fetched data and continue of loading
@ -56,7 +56,7 @@ class LoadTreatmentsWorker(
} else {
rxBus.send(
EventNSClientNewLog(
"END", "No TRs from ${dateUtil.dateAndTimeAndSecondsString(nsClientV3Plugin.lastFetched.collections.treatments)}"
"END", "No TRs from ${dateUtil.dateAndTimeAndSecondsString(nsClientV3Plugin.lastLoadedSrvModified.collections.treatments)}"
)
)
storeDataForDb.storeTreatmentsToDb()
@ -72,7 +72,7 @@ class LoadTreatmentsWorker(
ret = Result.failure(workDataOf("Error" to error.toString()))
}
else {
rxBus.send(EventNSClientNewLog("END", "No new TRs from ${dateUtil.dateAndTimeAndSecondsString(nsClientV3Plugin.lastFetched.collections.treatments)}"))
rxBus.send(EventNSClientNewLog("END", "No new TRs from ${dateUtil.dateAndTimeAndSecondsString(nsClientV3Plugin.lastLoadedSrvModified.collections.treatments)}"))
storeDataForDb.storeTreatmentsToDb()
WorkManager.getInstance(context)
.enqueueUniqueWork(

View file

@ -25,6 +25,7 @@ import info.nightscout.plugins.sync.nsclientV3.extensions.toTemporaryTarget
import info.nightscout.plugins.sync.nsclientV3.extensions.toTherapyEvent
import info.nightscout.rx.bus.RxBus
import info.nightscout.rx.logging.LTag
import info.nightscout.sdk.interfaces.NSAndroidClient
import info.nightscout.sdk.localmodel.treatment.NSBolus
import info.nightscout.sdk.localmodel.treatment.NSBolusWizard
import info.nightscout.sdk.localmodel.treatment.NSCarbs
@ -58,20 +59,15 @@ class ProcessTreatmentsWorker(
override fun doWorkAndLog(): Result {
@Suppress("UNCHECKED_CAST")
val treatments = dataWorkerStorage.pickupObject(inputData.getLong(DataWorkerStorage.STORE_KEY, -1)) as List<NSTreatment>?
val treatments = dataWorkerStorage.pickupObject(inputData.getLong(DataWorkerStorage.STORE_KEY, -1)) as NSAndroidClient.ReadResponse<List<NSTreatment>>?
?: return Result.failure(workDataOf("Error" to "missing input data"))
val ret = Result.success()
var latestDateInReceivedData = 0L
for (treatment in treatments) {
for (treatment in treatments.values) {
aapsLogger.debug(LTag.DATABASE, "Received NS treatment: $treatment")
//Find latest date in treatment
val mills = treatment.date
if (mills != 0L && mills < dateUtil.now())
if (mills > latestDateInReceivedData) latestDateInReceivedData = mills
when (treatment) {
is NSBolus ->
if (sp.getBoolean(info.nightscout.core.utils.R.string.key_ns_receive_insulin, false) || config.NSCLIENT)
@ -140,7 +136,7 @@ class ProcessTreatmentsWorker(
}
}
}
activePlugin.activeNsClient?.updateLatestTreatmentReceivedIfNewer(latestDateInReceivedData)
activePlugin.activeNsClient?.updateLatestTreatmentReceivedIfNewer(treatments.lastServerModified)
// xDripBroadcast.sendTreatments(treatments)
return ret
}