NSCv3: better profile processing. needs https://github.com/nightscout/cgm-remote-monitor/pull/7839
This commit is contained in:
parent
71a31f6c5b
commit
9769a01e6f
|
@ -35,6 +35,6 @@ interface ProfileSource {
|
||||||
|
|
||||||
var currentProfileIndex: Int
|
var currentProfileIndex: Int
|
||||||
fun currentProfile(): SingleProfile?
|
fun currentProfile(): SingleProfile?
|
||||||
fun storeSettings(activity: FragmentActivity? = null)
|
fun storeSettings(activity: FragmentActivity? = null, emptyCreated: Boolean = false)
|
||||||
|
|
||||||
}
|
}
|
|
@ -16,7 +16,7 @@ interface NsClient : Sync {
|
||||||
fun textLog(): Spanned
|
fun textLog(): Spanned
|
||||||
fun clearLog()
|
fun clearLog()
|
||||||
|
|
||||||
enum class Collection { ENTRIES, TREATMENTS, FOODS }
|
enum class Collection { ENTRIES, TREATMENTS, FOODS, PROFILE }
|
||||||
/**
|
/**
|
||||||
* NSC v3 does first load of all data
|
* NSC v3 does first load of all data
|
||||||
* next loads are using srvModified property for sync
|
* next loads are using srvModified property for sync
|
||||||
|
|
|
@ -456,6 +456,19 @@ class NSAndroidClientImpl(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override suspend fun getProfileModifiedSince(from: Long): NSAndroidClient.ReadResponse<List<JSONObject>> = callWrapper(dispatcher) {
|
||||||
|
|
||||||
|
val response = api.getProfileModifiedSince(from)
|
||||||
|
if (response.isSuccessful) {
|
||||||
|
val eTagString = response.headers()["ETag"]
|
||||||
|
val eTag = eTagString?.substring(3, eTagString.length - 1)?.toLong()
|
||||||
|
return@callWrapper NSAndroidClient.ReadResponse(code = response.raw().networkResponse?.code ?: response.code(), lastServerModified = eTag, values = response.body()?.result.toNotNull())
|
||||||
|
} else {
|
||||||
|
throw UnsuccessfullNightscoutException()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private suspend fun <T> callWrapper(dispatcher: CoroutineDispatcher, block: suspend () -> T): T =
|
private suspend fun <T> callWrapper(dispatcher: CoroutineDispatcher, block: suspend () -> T): T =
|
||||||
withContext(dispatcher) {
|
withContext(dispatcher) {
|
||||||
retry(
|
retry(
|
||||||
|
|
|
@ -35,6 +35,7 @@ interface NSAndroidClient {
|
||||||
suspend fun getDeviceStatusModifiedSince(from: Long): List<NSDeviceStatus>
|
suspend fun getDeviceStatusModifiedSince(from: Long): List<NSDeviceStatus>
|
||||||
|
|
||||||
suspend fun createProfileStore(remoteProfileStore: JSONObject): CreateUpdateResponse
|
suspend fun createProfileStore(remoteProfileStore: JSONObject): CreateUpdateResponse
|
||||||
|
suspend fun getProfileModifiedSince(from: Long): ReadResponse<List<JSONObject>>
|
||||||
suspend fun getLastProfileStore(): ReadResponse<List<JSONObject>>
|
suspend fun getLastProfileStore(): ReadResponse<List<JSONObject>>
|
||||||
|
|
||||||
suspend fun createTreatment(nsTreatment: NSTreatment): CreateUpdateResponse
|
suspend fun createTreatment(nsTreatment: NSTreatment): CreateUpdateResponse
|
||||||
|
|
|
@ -93,9 +93,14 @@ internal interface NightscoutRemoteService {
|
||||||
@DELETE("v3/food")
|
@DELETE("v3/food")
|
||||||
suspend fun deleteFood(@Path("identifier") identifier: String): Response<NSResponse<RemoteCreateUpdateResponse>>
|
suspend fun deleteFood(@Path("identifier") identifier: String): Response<NSResponse<RemoteCreateUpdateResponse>>
|
||||||
|
|
||||||
|
@GET("v3/profile/history/{from}")
|
||||||
|
suspend fun getProfileModifiedSince(@Path("from") from: Long, @Query("limit") limit: Long = 10): Response<NSResponse<List<JSONObject>>>
|
||||||
|
|
||||||
|
|
||||||
@GET("v3/profile?sort\$desc=date&limit=1")
|
@GET("v3/profile?sort\$desc=date&limit=1")
|
||||||
suspend fun getLastProfile(): Response<NSResponse<List<JSONObject>>>
|
suspend fun getLastProfile(): Response<NSResponse<List<JSONObject>>>
|
||||||
|
|
||||||
|
|
||||||
@POST("v3/profile")
|
@POST("v3/profile")
|
||||||
suspend fun createProfile(@Body profile: JsonObject): Response<NSResponse<RemoteCreateUpdateResponse>>
|
suspend fun createProfile(@Body profile: JsonObject): Response<NSResponse<RemoteCreateUpdateResponse>>
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ class ProfileStoreObject(val injector: HasAndroidInjector, override val data: JS
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getStartDate(): Long {
|
override fun getStartDate(): Long {
|
||||||
val iso = JsonHelper.safeGetString(data, "startDate") ?: return 0
|
val iso = JsonHelper.safeGetString(data, "created_at") ?: JsonHelper.safeGetString(data, "startDate") ?: return 0
|
||||||
return try {
|
return try {
|
||||||
dateUtil.fromISODateString(iso)
|
dateUtil.fromISODateString(iso)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
|
|
|
@ -45,7 +45,7 @@ class ProfileStoreObject(val injector: HasAndroidInjector, override val data: JS
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getStartDate(): Long {
|
override fun getStartDate(): Long {
|
||||||
val iso = JsonHelper.safeGetString(data, "startDate") ?: return 0
|
val iso = JsonHelper.safeGetString(data, "created_at") ?: JsonHelper.safeGetString(data,"startDate") ?: return 0
|
||||||
return try {
|
return try {
|
||||||
dateUtil.fromISODateString(iso)
|
dateUtil.fromISODateString(iso)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
|
|
|
@ -45,7 +45,7 @@ class ProfileStoreObject(val injector: HasAndroidInjector, override val data: JS
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getStartDate(): Long {
|
override fun getStartDate(): Long {
|
||||||
val iso = JsonHelper.safeGetString(data, "startDate") ?: return 0
|
val iso = JsonHelper.safeGetString(data, "created_at") ?: JsonHelper.safeGetString(data,"startDate") ?: return 0
|
||||||
return try {
|
return try {
|
||||||
dateUtil.fromISODateString(iso)
|
dateUtil.fromISODateString(iso)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
|
|
|
@ -175,7 +175,7 @@ class ProfilePlugin @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
override fun storeSettings(activity: FragmentActivity?) {
|
override fun storeSettings(activity: FragmentActivity?, emptyCreated: Boolean) {
|
||||||
for (i in 0 until numOfProfiles) {
|
for (i in 0 until numOfProfiles) {
|
||||||
profiles[i].run {
|
profiles[i].run {
|
||||||
val localProfileNumbered = Constants.LOCAL_PROFILE + "_" + i + "_"
|
val localProfileNumbered = Constants.LOCAL_PROFILE + "_" + i + "_"
|
||||||
|
@ -191,7 +191,7 @@ class ProfilePlugin @Inject constructor(
|
||||||
}
|
}
|
||||||
sp.putInt(Constants.LOCAL_PROFILE + "_profiles", numOfProfiles)
|
sp.putInt(Constants.LOCAL_PROFILE + "_profiles", numOfProfiles)
|
||||||
|
|
||||||
sp.putLong(info.nightscout.core.utils.R.string.key_local_profile_last_change, dateUtil.now())
|
sp.putLong(info.nightscout.core.utils.R.string.key_local_profile_last_change, if (emptyCreated) 0 else dateUtil.now())
|
||||||
createAndStoreConvertedProfile()
|
createAndStoreConvertedProfile()
|
||||||
isEdited = false
|
isEdited = false
|
||||||
aapsLogger.debug(LTag.PROFILE, "Storing settings: " + rawProfile?.data.toString())
|
aapsLogger.debug(LTag.PROFILE, "Storing settings: " + rawProfile?.data.toString())
|
||||||
|
@ -360,7 +360,7 @@ class ProfilePlugin @Inject constructor(
|
||||||
)
|
)
|
||||||
currentProfileIndex = profiles.size - 1
|
currentProfileIndex = profiles.size - 1
|
||||||
createAndStoreConvertedProfile()
|
createAndStoreConvertedProfile()
|
||||||
storeSettings()
|
storeSettings(emptyCreated = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun cloneProfile() {
|
fun cloneProfile() {
|
||||||
|
@ -412,6 +412,7 @@ class ProfilePlugin @Inject constructor(
|
||||||
if (numOfProfiles > 0) json.put("defaultProfile", currentProfile()?.name)
|
if (numOfProfiles > 0) json.put("defaultProfile", currentProfile()?.name)
|
||||||
val startDate = sp.getLong(info.nightscout.core.utils.R.string.key_local_profile_last_change, dateUtil.now())
|
val startDate = sp.getLong(info.nightscout.core.utils.R.string.key_local_profile_last_change, dateUtil.now())
|
||||||
json.put("date", startDate)
|
json.put("date", startDate)
|
||||||
|
json.put("created_at", dateUtil.toISOAsUTC(startDate))
|
||||||
json.put("startDate", dateUtil.toISOAsUTC(startDate))
|
json.put("startDate", dateUtil.toISOAsUTC(startDate))
|
||||||
json.put("store", store)
|
json.put("store", store)
|
||||||
} catch (e: JSONException) {
|
} catch (e: JSONException) {
|
||||||
|
|
|
@ -132,12 +132,14 @@ class NSClientV3Plugin @Inject constructor(
|
||||||
when {
|
when {
|
||||||
sp.getBoolean(R.string.key_ns_client_paused, false) -> rh.gs(info.nightscout.core.ui.R.string.paused)
|
sp.getBoolean(R.string.key_ns_client_paused, false) -> rh.gs(info.nightscout.core.ui.R.string.paused)
|
||||||
isAllowed.not() -> blockingReason
|
isAllowed.not() -> blockingReason
|
||||||
|
lastOperationError != null -> rh.gs(info.nightscout.core.ui.R.string.error)
|
||||||
nsAndroidClient?.lastStatus == null -> rh.gs(R.string.not_connected)
|
nsAndroidClient?.lastStatus == null -> rh.gs(R.string.not_connected)
|
||||||
workIsRunning(arrayOf(JOB_NAME)) -> rh.gs(R.string.working)
|
workIsRunning(arrayOf(JOB_NAME)) -> rh.gs(R.string.working)
|
||||||
nsAndroidClient?.lastStatus?.apiPermissions?.isFull() == true -> rh.gs(info.nightscout.shared.R.string.connected)
|
nsAndroidClient?.lastStatus?.apiPermissions?.isFull() == true -> rh.gs(info.nightscout.shared.R.string.connected)
|
||||||
nsAndroidClient?.lastStatus?.apiPermissions?.isRead() == true -> rh.gs(R.string.read_only)
|
nsAndroidClient?.lastStatus?.apiPermissions?.isRead() == true -> rh.gs(R.string.read_only)
|
||||||
else -> rh.gs(info.nightscout.core.ui.R.string.unknown)
|
else -> rh.gs(info.nightscout.core.ui.R.string.unknown)
|
||||||
}
|
}
|
||||||
|
var lastOperationError: String? = null
|
||||||
|
|
||||||
internal var nsAndroidClient: NSAndroidClient? = null
|
internal var nsAndroidClient: NSAndroidClient? = null
|
||||||
|
|
||||||
|
@ -315,6 +317,7 @@ class NSClientV3Plugin @Inject constructor(
|
||||||
NsClient.Collection.ENTRIES -> lastLoadedSrvModified.collections.entries == 0L
|
NsClient.Collection.ENTRIES -> lastLoadedSrvModified.collections.entries == 0L
|
||||||
NsClient.Collection.TREATMENTS -> lastLoadedSrvModified.collections.treatments == 0L
|
NsClient.Collection.TREATMENTS -> lastLoadedSrvModified.collections.treatments == 0L
|
||||||
NsClient.Collection.FOODS -> lastLoadedSrvModified.collections.foods == 0L
|
NsClient.Collection.FOODS -> lastLoadedSrvModified.collections.foods == 0L
|
||||||
|
NsClient.Collection.PROFILE -> lastLoadedSrvModified.collections.profile == 0L
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateLatestBgReceivedIfNewer(latestReceived: Long) {
|
override fun updateLatestBgReceivedIfNewer(latestReceived: Long) {
|
||||||
|
|
|
@ -119,9 +119,11 @@ class LoadBgWorker(
|
||||||
} catch (error: Exception) {
|
} catch (error: Exception) {
|
||||||
aapsLogger.error("Error: ", error)
|
aapsLogger.error("Error: ", error)
|
||||||
rxBus.send(EventNSClientNewLog("ERROR", error.localizedMessage))
|
rxBus.send(EventNSClientNewLog("ERROR", error.localizedMessage))
|
||||||
|
nsClientV3Plugin.lastOperationError = error.localizedMessage
|
||||||
return Result.failure(workDataOf("Error" to error.localizedMessage))
|
return Result.failure(workDataOf("Error" to error.localizedMessage))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsClientV3Plugin.lastOperationError = null
|
||||||
return Result.success()
|
return Result.success()
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -52,9 +52,11 @@ class LoadDeviceStatusWorker(
|
||||||
} catch (error: Exception) {
|
} catch (error: Exception) {
|
||||||
aapsLogger.error("Error: ", error)
|
aapsLogger.error("Error: ", error)
|
||||||
rxBus.send(EventNSClientNewLog("ERROR", error.localizedMessage))
|
rxBus.send(EventNSClientNewLog("ERROR", error.localizedMessage))
|
||||||
|
nsClientV3Plugin.lastOperationError = error.localizedMessage
|
||||||
return Result.failure(workDataOf("Error" to error.localizedMessage))
|
return Result.failure(workDataOf("Error" to error.localizedMessage))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsClientV3Plugin.lastOperationError = null
|
||||||
return Result.success()
|
return Result.success()
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -64,9 +64,11 @@ class LoadFoodsWorker(
|
||||||
} catch (error: Exception) {
|
} catch (error: Exception) {
|
||||||
aapsLogger.error("Error: ", error)
|
aapsLogger.error("Error: ", error)
|
||||||
rxBus.send(EventNSClientNewLog("ERROR", error.localizedMessage))
|
rxBus.send(EventNSClientNewLog("ERROR", error.localizedMessage))
|
||||||
|
nsClientV3Plugin.lastOperationError = error.localizedMessage
|
||||||
return Result.failure(workDataOf("Error" to error.localizedMessage))
|
return Result.failure(workDataOf("Error" to error.localizedMessage))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsClientV3Plugin.lastOperationError = null
|
||||||
return Result.success()
|
return Result.success()
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -28,8 +28,10 @@ class LoadLastModificationWorker(
|
||||||
} catch (error: Exception) {
|
} catch (error: Exception) {
|
||||||
aapsLogger.error(LTag.NSCLIENT, "Error: ", error)
|
aapsLogger.error(LTag.NSCLIENT, "Error: ", error)
|
||||||
rxBus.send(EventNSClientNewLog("ERROR", error.localizedMessage))
|
rxBus.send(EventNSClientNewLog("ERROR", error.localizedMessage))
|
||||||
|
nsClientV3Plugin.lastOperationError = error.localizedMessage
|
||||||
return Result.failure(workDataOf("Error" to error.localizedMessage))
|
return Result.failure(workDataOf("Error" to error.localizedMessage))
|
||||||
}
|
}
|
||||||
|
nsClientV3Plugin.lastOperationError = null
|
||||||
return Result.success()
|
return Result.success()
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -8,6 +8,7 @@ import androidx.work.WorkerParameters
|
||||||
import androidx.work.workDataOf
|
import androidx.work.workDataOf
|
||||||
import info.nightscout.core.utils.receivers.DataWorkerStorage
|
import info.nightscout.core.utils.receivers.DataWorkerStorage
|
||||||
import info.nightscout.core.utils.worker.LoggingWorker
|
import info.nightscout.core.utils.worker.LoggingWorker
|
||||||
|
import info.nightscout.interfaces.sync.NsClient
|
||||||
import info.nightscout.interfaces.utils.JsonHelper
|
import info.nightscout.interfaces.utils.JsonHelper
|
||||||
import info.nightscout.interfaces.workflow.WorkerClasses
|
import info.nightscout.interfaces.workflow.WorkerClasses
|
||||||
import info.nightscout.plugins.sync.nsclientV3.NSClientV3Plugin
|
import info.nightscout.plugins.sync.nsclientV3.NSClientV3Plugin
|
||||||
|
@ -37,13 +38,23 @@ class LoadProfileStoreWorker(
|
||||||
val nsAndroidClient = nsClientV3Plugin.nsAndroidClient ?: return Result.failure(workDataOf("Error" to "AndroidClient is null"))
|
val nsAndroidClient = nsClientV3Plugin.nsAndroidClient ?: return Result.failure(workDataOf("Error" to "AndroidClient is null"))
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val lastLoaded = max(nsClientV3Plugin.lastLoadedSrvModified.collections.profile, 0)
|
val isFirstLoad = nsClientV3Plugin.isFirstLoad(NsClient.Collection.PROFILE)
|
||||||
|
val lastLoaded = max(nsClientV3Plugin.lastLoadedSrvModified.collections.profile, dateUtil.now() - nsClientV3Plugin.maxAge)
|
||||||
if ((nsClientV3Plugin.newestDataOnServer?.collections?.profile ?: Long.MAX_VALUE) > lastLoaded) {
|
if ((nsClientV3Plugin.newestDataOnServer?.collections?.profile ?: Long.MAX_VALUE) > lastLoaded) {
|
||||||
val response: NSAndroidClient.ReadResponse<List<JSONObject>> = nsAndroidClient.getLastProfileStore()
|
val response: NSAndroidClient.ReadResponse<List<JSONObject>> =
|
||||||
|
if (isFirstLoad) nsAndroidClient.getLastProfileStore()
|
||||||
|
else nsAndroidClient.getProfileModifiedSince(lastLoaded)
|
||||||
val profiles = response.values
|
val profiles = response.values
|
||||||
if (profiles.size == 1) {
|
if (profiles.isNotEmpty()) {
|
||||||
val profile = profiles[0]
|
val profile = profiles[profiles.size - 1]
|
||||||
JsonHelper.safeGetLongAllowNull(profile, "srvModified")?.let { nsClientV3Plugin.lastLoadedSrvModified.collections.profile = it }
|
// if srvModified found in response
|
||||||
|
response.lastServerModified?.let { nsClientV3Plugin.lastLoadedSrvModified.collections.profile = it } ?:
|
||||||
|
// if srvModified found in record
|
||||||
|
JsonHelper.safeGetLongAllowNull(profile, "srvModified")?.let { nsClientV3Plugin.lastLoadedSrvModified.collections.profile = it } ?:
|
||||||
|
// if created_at found in record
|
||||||
|
JsonHelper.safeGetStringAllowNull(profile, "created_at", null)?.let { nsClientV3Plugin.lastLoadedSrvModified.collections.profile = dateUtil.fromISODateString(it) } ?:
|
||||||
|
// if not found reset to now
|
||||||
|
{ nsClientV3Plugin.lastLoadedSrvModified.collections.profile = dateUtil.now() }
|
||||||
nsClientV3Plugin.storeLastLoadedSrvModified()
|
nsClientV3Plugin.storeLastLoadedSrvModified()
|
||||||
aapsLogger.debug(LTag.NSCLIENT, "PROFILE: $profile")
|
aapsLogger.debug(LTag.NSCLIENT, "PROFILE: $profile")
|
||||||
rxBus.send(EventNSClientNewLog("RCV", "1 PROFILE from ${dateUtil.dateAndTimeAndSecondsString(lastLoaded)}"))
|
rxBus.send(EventNSClientNewLog("RCV", "1 PROFILE from ${dateUtil.dateAndTimeAndSecondsString(lastLoaded)}"))
|
||||||
|
|
|
@ -27,8 +27,10 @@ class LoadStatusWorker(
|
||||||
} catch (error: Exception) {
|
} catch (error: Exception) {
|
||||||
aapsLogger.error("Error: ", error)
|
aapsLogger.error("Error: ", error)
|
||||||
rxBus.send(EventNSClientNewLog("ERROR", error.localizedMessage))
|
rxBus.send(EventNSClientNewLog("ERROR", error.localizedMessage))
|
||||||
|
nsClientV3Plugin.lastOperationError = error.localizedMessage
|
||||||
return Result.failure(workDataOf("Error" to error.localizedMessage))
|
return Result.failure(workDataOf("Error" to error.localizedMessage))
|
||||||
}
|
}
|
||||||
|
nsClientV3Plugin.lastOperationError = null
|
||||||
return Result.success()
|
return Result.success()
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -104,9 +104,11 @@ class LoadTreatmentsWorker(
|
||||||
} catch (error: Exception) {
|
} catch (error: Exception) {
|
||||||
aapsLogger.error("Error: ", error)
|
aapsLogger.error("Error: ", error)
|
||||||
rxBus.send(EventNSClientNewLog("ERROR", error.localizedMessage))
|
rxBus.send(EventNSClientNewLog("ERROR", error.localizedMessage))
|
||||||
|
nsClientV3Plugin.lastOperationError = error.localizedMessage
|
||||||
return Result.failure(workDataOf("Error" to error.localizedMessage))
|
return Result.failure(workDataOf("Error" to error.localizedMessage))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsClientV3Plugin.lastOperationError = null
|
||||||
return Result.success()
|
return Result.success()
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -45,7 +45,7 @@ class ProfileStoreObject(val injector: HasAndroidInjector, override val data: JS
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getStartDate(): Long {
|
override fun getStartDate(): Long {
|
||||||
val iso = JsonHelper.safeGetString(data, "startDate") ?: return 0
|
val iso = JsonHelper.safeGetString(data, "created_at") ?: JsonHelper.safeGetString(data, "startDate") ?: return 0
|
||||||
return try {
|
return try {
|
||||||
dateUtil.fromISODateString(iso)
|
dateUtil.fromISODateString(iso)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
|
|
Loading…
Reference in a new issue