From 742e02ef3cebf6321a62800d0b7cfe3ed0f349da Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Fri, 9 Dec 2022 23:26:15 +0100 Subject: [PATCH] NSCv3: reading is working --- .../nightscout/sdk/NSAndroidClientImpl.kt | 4 +- .../sdk/interfaces/NSAndroidClient.kt | 1 + .../sdk/localmodel/ApiPermissions.kt | 5 +- .../nightscout/source/BGSourceFragment.kt | 2 +- .../sync/nsclient/services/NSClientService.kt | 2 +- .../sync/nsclientV3/NSClientV3Plugin.kt | 93 +++++++++++++------ .../sync/nsclientV3/workers/LoadBgWorker.kt | 1 + plugins/sync/src/main/res/values/strings.xml | 4 + 8 files changed, 81 insertions(+), 31 deletions(-) diff --git a/core/ns-sdk/src/main/java/info/nightscout/sdk/NSAndroidClientImpl.kt b/core/ns-sdk/src/main/java/info/nightscout/sdk/NSAndroidClientImpl.kt index 4a5b3ffa10..019c16a914 100644 --- a/core/ns-sdk/src/main/java/info/nightscout/sdk/NSAndroidClientImpl.kt +++ b/core/ns-sdk/src/main/java/info/nightscout/sdk/NSAndroidClientImpl.kt @@ -58,6 +58,8 @@ class NSAndroidClientImpl( accessToken = accessToken, logging = logging ) + override var lastStatus: Status? = null + private set /* * TODO: how should our result look like? @@ -81,7 +83,7 @@ class NSAndroidClientImpl( } override suspend fun getStatus(): Status = callWrapper(dispatcher) { - api.statusSimple().result!!.toLocal() + api.statusSimple().result!!.toLocal().also { lastStatus = it } } // TODO: return something better than a String diff --git a/core/ns-sdk/src/main/java/info/nightscout/sdk/interfaces/NSAndroidClient.kt b/core/ns-sdk/src/main/java/info/nightscout/sdk/interfaces/NSAndroidClient.kt index 918f4e8538..e57144a74f 100644 --- a/core/ns-sdk/src/main/java/info/nightscout/sdk/interfaces/NSAndroidClient.kt +++ b/core/ns-sdk/src/main/java/info/nightscout/sdk/interfaces/NSAndroidClient.kt @@ -8,6 +8,7 @@ import info.nightscout.sdk.remotemodel.RemoteDeviceStatus interface NSAndroidClient { + val lastStatus: Status? suspend fun getVersion(): String suspend fun getStatus(): Status suspend fun getEntries(): String diff --git a/core/ns-sdk/src/main/java/info/nightscout/sdk/localmodel/ApiPermissions.kt b/core/ns-sdk/src/main/java/info/nightscout/sdk/localmodel/ApiPermissions.kt index d78861667a..5eaa012fde 100644 --- a/core/ns-sdk/src/main/java/info/nightscout/sdk/localmodel/ApiPermissions.kt +++ b/core/ns-sdk/src/main/java/info/nightscout/sdk/localmodel/ApiPermissions.kt @@ -7,4 +7,7 @@ data class ApiPermissions( val profile: ApiPermission, val settings: ApiPermission, val treatments: ApiPermission -) +) { + fun isFull() = deviceStatus.full && entries.full && food.full && profile.full && settings.full && treatments.full + fun isRead() = deviceStatus.read && entries.read && food.read && profile.read && settings.read && treatments.read +} diff --git a/plugins/source/src/main/java/info/nightscout/source/BGSourceFragment.kt b/plugins/source/src/main/java/info/nightscout/source/BGSourceFragment.kt index 29808634f9..a308813c4e 100644 --- a/plugins/source/src/main/java/info/nightscout/source/BGSourceFragment.kt +++ b/plugins/source/src/main/java/info/nightscout/source/BGSourceFragment.kt @@ -140,7 +140,7 @@ class BGSourceFragment : DaggerFragment(), MenuProvider { val newDay = position == 0 || !dateUtil.isSameDay(glucoseValue.timestamp, glucoseValues[position - 1].timestamp) holder.binding.date.visibility = newDay.toVisibility() holder.binding.date.text = if (newDay) dateUtil.dateStringRelative(glucoseValue.timestamp, rh) else "" - holder.binding.time.text = dateUtil.timeString(glucoseValue.timestamp) + holder.binding.time.text = dateUtil.timeStringWithSeconds(glucoseValue.timestamp) holder.binding.value.text = glucoseValue.valueToUnitsString(profileFunction.getUnits()) holder.binding.direction.setImageResource(glucoseValue.trendArrow.directionToIcon()) if (position > 0) { diff --git a/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclient/services/NSClientService.kt b/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclient/services/NSClientService.kt index 69f3fdd187..a8cc99ca1b 100644 --- a/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclient/services/NSClientService.kt +++ b/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclient/services/NSClientService.kt @@ -251,7 +251,7 @@ class NSClientService : DaggerService(), NsClient.NSClientService { } else if (!nsEnabled) { rxBus.send(EventNSClientNewLog("NSCLIENT", "disabled")) rxBus.send(EventNSClientStatus("Disabled")) - } else if (nsURL != "" && (config.isEngineeringMode() || nsURL.lowercase(Locale.getDefault()).startsWith("https://"))) { + } else if (nsURL != "" && (nsURL.lowercase(Locale.getDefault()).startsWith("https://"))) { try { rxBus.send(EventNSClientStatus("Connecting ...")) val opt = IO.Options() diff --git a/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclientV3/NSClientV3Plugin.kt b/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclientV3/NSClientV3Plugin.kt index b7486c1bda..73f36a5d97 100644 --- a/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclientV3/NSClientV3Plugin.kt +++ b/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclientV3/NSClientV3Plugin.kt @@ -26,7 +26,6 @@ import info.nightscout.interfaces.utils.HtmlHelper import info.nightscout.plugins.sync.R import info.nightscout.plugins.sync.nsShared.NSClientFragment import info.nightscout.plugins.sync.nsShared.events.EventNSClientResend -import info.nightscout.plugins.sync.nsShared.events.EventNSClientStatus import info.nightscout.plugins.sync.nsShared.events.EventNSClientUpdateGUI import info.nightscout.plugins.sync.nsclient.NsClientReceiverDelegate import info.nightscout.plugins.sync.nsclient.data.AlarmAck @@ -87,21 +86,31 @@ class NSClientV3Plugin @Inject constructor( companion object { val JOB_NAME: String = this::class.java.simpleName + val REFRESH_INTERVAL = T.mins(5).msecs() } private val disposable = CompositeDisposable() + private lateinit var runLoop: Runnable private val handler = Handler(HandlerThread(this::class.simpleName + "Handler").also { it.start() }.looper) private val listLog: MutableList = ArrayList() - override var status = "" + override val status + get() = + when { + sp.getBoolean(R.string.key_ns_client_paused, false) -> rh.gs(info.nightscout.core.ui.R.string.paused) + isAllowed.not() -> blockingReason + nsAndroidClient.lastStatus == null -> rh.gs(R.string.not_connected) + 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?.isRead() == true -> rh.gs(R.string.read_only) + else -> rh.gs(info.nightscout.core.ui.R.string.unknown) + } override val nsClientService: NSClientService? = null // service not needed internal lateinit var nsAndroidClient: NSAndroidClient // private lateinit var nsAndroidRxClient: NSAndroidRxClient - val isAllowed: Boolean - get() = nsClientReceiverDelegate.allowed - val blockingReason: String - get() = nsClientReceiverDelegate.blockingReason + val isAllowed get() = nsClientReceiverDelegate.allowed + val blockingReason get() = nsClientReceiverDelegate.blockingReason private val maxAge = T.days(77).msecs() internal var lastModified: LastModified? = null // timestamp of last modification for every collection @@ -133,31 +142,24 @@ class NSClientV3Plugin @Inject constructor( lastFetched.collections.profile = max(dateUtil.now() - maxAge, lastFetched.collections.profile) lastFetched.collections.devicestatus = max(dateUtil.now() - maxAge, lastFetched.collections.devicestatus) - nsAndroidClient = NSAndroidClientImpl( - baseUrl = sp.getString(info.nightscout.core.utils.R.string.key_nsclientinternal_url, "").lowercase().replace("https://", ""), - accessToken = sp.getString(R.string.key_ns_client_token, ""), - context = context, - logging = true - ) + setClient() nsClientReceiverDelegate.grabReceiversState() - disposable += rxBus - .toObservable(EventNSClientStatus::class.java) - .observeOn(aapsSchedulers.io) - .subscribe({ event -> - status = event.getStatus(context) - rxBus.send(EventNSClientUpdateGUI()) - // Pass to setup wizard - rxBus.send(EventSWSyncStatus(event.getStatus(context))) - }, fabricPrivacy::logException) disposable += rxBus .toObservable(EventNetworkChange::class.java) .observeOn(aapsSchedulers.io) - .subscribe({ ev -> nsClientReceiverDelegate.onStatusEvent(ev) }, fabricPrivacy::logException) + .subscribe({ ev -> + nsClientReceiverDelegate.onStatusEvent(ev) + setClient() + }, fabricPrivacy::logException) disposable += rxBus .toObservable(EventPreferenceChange::class.java) .observeOn(aapsSchedulers.io) - .subscribe({ ev -> nsClientReceiverDelegate.onStatusEvent(ev) }, fabricPrivacy::logException) + .subscribe({ ev -> + nsClientReceiverDelegate.onStatusEvent(ev) + 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) @@ -177,10 +179,18 @@ class NSClientV3Plugin @Inject constructor( .toObservable(EventNSClientResend::class.java) .observeOn(aapsSchedulers.io) .subscribe({ event -> resend(event.reason) }, fabricPrivacy::logException) + + runLoop = Runnable { + executeLoop() + handler.postDelayed(runLoop, REFRESH_INTERVAL) + } + handler.postDelayed(runLoop, REFRESH_INTERVAL) + executeLoop() } override fun onStop() { // context.applicationContext.unbindService(mConnection) + handler.removeCallbacksAndMessages(null) disposable.clear() super.onStop() } @@ -196,8 +206,8 @@ class NSClientV3Plugin @Inject constructor( preferenceFragment.findPreference(rh.gs(R.string.key_ns_receive_tbr_eb))?.isVisible = config.isEngineeringMode() } - override val hasWritePermission: Boolean get() = nsClientService?.hasWriteAuth ?: false - override val connected: Boolean get() = nsClientService?.isConnected ?: false + override val hasWritePermission: Boolean get() = nsAndroidClient.lastStatus?.apiPermissions?.isFull() ?: false + override val connected: Boolean get() = nsAndroidClient.lastStatus != null override fun clearLog() { handler.post { @@ -206,6 +216,16 @@ class NSClientV3Plugin @Inject constructor( } } + private fun setClient() { + nsAndroidClient = NSAndroidClientImpl( + baseUrl = sp.getString(info.nightscout.core.utils.R.string.key_nsclientinternal_url, "").lowercase().replace("https://", ""), + accessToken = sp.getString(R.string.key_ns_client_token, ""), + context = context, + logging = true + ) + rxBus.send(EventSWSyncStatus(status)) + } + private fun addToLog(ev: EventNSClientNewLog) { synchronized(listLog) { listLog.add(ev) @@ -239,8 +259,7 @@ class NSClientV3Plugin @Inject constructor( rxBus.send(EventPreferenceChange(rh.gs(R.string.key_ns_client_paused))) } - override val version: NsClient.Version - get() = NsClient.Version.V3 + override val version: NsClient.Version get() = NsClient.Version.V3 override val address: String get() = sp.getString(info.nightscout.core.utils.R.string.key_nsclientinternal_url, "") @@ -287,6 +306,26 @@ class NSClientV3Plugin @Inject constructor( } fun test() { + executeLoop() + } + + fun scheduleNewExecution() { + val toTime = lastFetched.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))) + } + } + + private fun executeLoop() { + if (sp.getBoolean(R.string.key_ns_client_paused, false)) { + rxBus.send(EventNSClientNewLog("NSCLIENT", "paused")) + return + } + if (!isAllowed) { + rxBus.send(EventNSClientNewLog("NSCLIENT", blockingReason)) + return + } if (workIsRunning(arrayOf(JOB_NAME))) rxBus.send(EventNSClientNewLog("RUN", "Already running")) else { diff --git a/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclientV3/workers/LoadBgWorker.kt b/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclientV3/workers/LoadBgWorker.kt index 8bccefe53f..99b9cbed8c 100644 --- a/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclientV3/workers/LoadBgWorker.kt +++ b/plugins/sync/src/main/java/info/nightscout/plugins/sync/nsclientV3/workers/LoadBgWorker.kt @@ -76,6 +76,7 @@ class LoadBgWorker( } else { rxBus.send(EventNSClientNewLog("END", "No new SGVs from ${dateUtil.dateAndTimeAndSecondsString(nsClientV3Plugin.lastFetched.collections.entries)}")) + nsClientV3Plugin.scheduleNewExecution() // Idea is to run after 5 min after last BG WorkManager.getInstance(context) .beginUniqueWork( NSClientV3Plugin.JOB_NAME, diff --git a/plugins/sync/src/main/res/values/strings.xml b/plugins/sync/src/main/res/values/strings.xml index 666d569463..9d6bdef502 100644 --- a/plugins/sync/src/main/res/values/strings.xml +++ b/plugins/sync/src/main/res/values/strings.xml @@ -143,4 +143,8 @@ Reset start Upload now + Not connected + Read only + Working + \ No newline at end of file