NSCv3: reading is working

This commit is contained in:
Milos Kozak 2022-12-09 23:26:15 +01:00
parent 30e7e5ed77
commit 742e02ef3c
8 changed files with 81 additions and 31 deletions

View file

@ -58,6 +58,8 @@ class NSAndroidClientImpl(
accessToken = accessToken, accessToken = accessToken,
logging = logging logging = logging
) )
override var lastStatus: Status? = null
private set
/* /*
* TODO: how should our result look like? * TODO: how should our result look like?
@ -81,7 +83,7 @@ class NSAndroidClientImpl(
} }
override suspend fun getStatus(): Status = callWrapper(dispatcher) { 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 // TODO: return something better than a String

View file

@ -8,6 +8,7 @@ import info.nightscout.sdk.remotemodel.RemoteDeviceStatus
interface NSAndroidClient { interface NSAndroidClient {
val lastStatus: Status?
suspend fun getVersion(): String suspend fun getVersion(): String
suspend fun getStatus(): Status suspend fun getStatus(): Status
suspend fun getEntries(): String suspend fun getEntries(): String

View file

@ -7,4 +7,7 @@ data class ApiPermissions(
val profile: ApiPermission, val profile: ApiPermission,
val settings: ApiPermission, val settings: ApiPermission,
val treatments: 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
}

View file

@ -140,7 +140,7 @@ class BGSourceFragment : DaggerFragment(), MenuProvider {
val newDay = position == 0 || !dateUtil.isSameDay(glucoseValue.timestamp, glucoseValues[position - 1].timestamp) val newDay = position == 0 || !dateUtil.isSameDay(glucoseValue.timestamp, glucoseValues[position - 1].timestamp)
holder.binding.date.visibility = newDay.toVisibility() holder.binding.date.visibility = newDay.toVisibility()
holder.binding.date.text = if (newDay) dateUtil.dateStringRelative(glucoseValue.timestamp, rh) else "" 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.value.text = glucoseValue.valueToUnitsString(profileFunction.getUnits())
holder.binding.direction.setImageResource(glucoseValue.trendArrow.directionToIcon()) holder.binding.direction.setImageResource(glucoseValue.trendArrow.directionToIcon())
if (position > 0) { if (position > 0) {

View file

@ -251,7 +251,7 @@ class NSClientService : DaggerService(), NsClient.NSClientService {
} else if (!nsEnabled) { } else if (!nsEnabled) {
rxBus.send(EventNSClientNewLog("NSCLIENT", "disabled")) rxBus.send(EventNSClientNewLog("NSCLIENT", "disabled"))
rxBus.send(EventNSClientStatus("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 { try {
rxBus.send(EventNSClientStatus("Connecting ...")) rxBus.send(EventNSClientStatus("Connecting ..."))
val opt = IO.Options() val opt = IO.Options()

View file

@ -26,7 +26,6 @@ import info.nightscout.interfaces.utils.HtmlHelper
import info.nightscout.plugins.sync.R import info.nightscout.plugins.sync.R
import info.nightscout.plugins.sync.nsShared.NSClientFragment import info.nightscout.plugins.sync.nsShared.NSClientFragment
import info.nightscout.plugins.sync.nsShared.events.EventNSClientResend 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.nsShared.events.EventNSClientUpdateGUI
import info.nightscout.plugins.sync.nsclient.NsClientReceiverDelegate import info.nightscout.plugins.sync.nsclient.NsClientReceiverDelegate
import info.nightscout.plugins.sync.nsclient.data.AlarmAck import info.nightscout.plugins.sync.nsclient.data.AlarmAck
@ -87,21 +86,31 @@ class NSClientV3Plugin @Inject constructor(
companion object { companion object {
val JOB_NAME: String = this::class.java.simpleName val JOB_NAME: String = this::class.java.simpleName
val REFRESH_INTERVAL = T.mins(5).msecs()
} }
private val disposable = CompositeDisposable() private val disposable = CompositeDisposable()
private lateinit var runLoop: Runnable
private val handler = Handler(HandlerThread(this::class.simpleName + "Handler").also { it.start() }.looper) private val handler = Handler(HandlerThread(this::class.simpleName + "Handler").also { it.start() }.looper)
private val listLog: MutableList<EventNSClientNewLog> = ArrayList() private val listLog: MutableList<EventNSClientNewLog> = 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 override val nsClientService: NSClientService? = null // service not needed
internal lateinit var nsAndroidClient: NSAndroidClient internal lateinit var nsAndroidClient: NSAndroidClient
// private lateinit var nsAndroidRxClient: NSAndroidRxClient // private lateinit var nsAndroidRxClient: NSAndroidRxClient
val isAllowed: Boolean val isAllowed get() = nsClientReceiverDelegate.allowed
get() = nsClientReceiverDelegate.allowed val blockingReason get() = nsClientReceiverDelegate.blockingReason
val blockingReason: String
get() = nsClientReceiverDelegate.blockingReason
private val maxAge = T.days(77).msecs() private val maxAge = T.days(77).msecs()
internal var lastModified: LastModified? = null // timestamp of last modification for every collection 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.profile = max(dateUtil.now() - maxAge, lastFetched.collections.profile)
lastFetched.collections.devicestatus = max(dateUtil.now() - maxAge, lastFetched.collections.devicestatus) lastFetched.collections.devicestatus = max(dateUtil.now() - maxAge, lastFetched.collections.devicestatus)
nsAndroidClient = NSAndroidClientImpl( setClient()
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
)
nsClientReceiverDelegate.grabReceiversState() 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 disposable += rxBus
.toObservable(EventNetworkChange::class.java) .toObservable(EventNetworkChange::class.java)
.observeOn(aapsSchedulers.io) .observeOn(aapsSchedulers.io)
.subscribe({ ev -> nsClientReceiverDelegate.onStatusEvent(ev) }, fabricPrivacy::logException) .subscribe({ ev ->
nsClientReceiverDelegate.onStatusEvent(ev)
setClient()
}, fabricPrivacy::logException)
disposable += rxBus disposable += rxBus
.toObservable(EventPreferenceChange::class.java) .toObservable(EventPreferenceChange::class.java)
.observeOn(aapsSchedulers.io) .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 // disposable += rxBus
// .toObservable(EventAppExit::class.java) // .toObservable(EventAppExit::class.java)
// .observeOn(aapsSchedulers.io) // .observeOn(aapsSchedulers.io)
@ -177,10 +179,18 @@ class NSClientV3Plugin @Inject constructor(
.toObservable(EventNSClientResend::class.java) .toObservable(EventNSClientResend::class.java)
.observeOn(aapsSchedulers.io) .observeOn(aapsSchedulers.io)
.subscribe({ event -> resend(event.reason) }, fabricPrivacy::logException) .subscribe({ event -> resend(event.reason) }, fabricPrivacy::logException)
runLoop = Runnable {
executeLoop()
handler.postDelayed(runLoop, REFRESH_INTERVAL)
}
handler.postDelayed(runLoop, REFRESH_INTERVAL)
executeLoop()
} }
override fun onStop() { override fun onStop() {
// context.applicationContext.unbindService(mConnection) // context.applicationContext.unbindService(mConnection)
handler.removeCallbacksAndMessages(null)
disposable.clear() disposable.clear()
super.onStop() super.onStop()
} }
@ -196,8 +206,8 @@ class NSClientV3Plugin @Inject constructor(
preferenceFragment.findPreference<SwitchPreference>(rh.gs(R.string.key_ns_receive_tbr_eb))?.isVisible = config.isEngineeringMode() preferenceFragment.findPreference<SwitchPreference>(rh.gs(R.string.key_ns_receive_tbr_eb))?.isVisible = config.isEngineeringMode()
} }
override val hasWritePermission: Boolean get() = nsClientService?.hasWriteAuth ?: false override val hasWritePermission: Boolean get() = nsAndroidClient.lastStatus?.apiPermissions?.isFull() ?: false
override val connected: Boolean get() = nsClientService?.isConnected ?: false override val connected: Boolean get() = nsAndroidClient.lastStatus != null
override fun clearLog() { override fun clearLog() {
handler.post { 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) { private fun addToLog(ev: EventNSClientNewLog) {
synchronized(listLog) { synchronized(listLog) {
listLog.add(ev) listLog.add(ev)
@ -239,8 +259,7 @@ class NSClientV3Plugin @Inject constructor(
rxBus.send(EventPreferenceChange(rh.gs(R.string.key_ns_client_paused))) rxBus.send(EventPreferenceChange(rh.gs(R.string.key_ns_client_paused)))
} }
override val version: NsClient.Version override val version: NsClient.Version get() = NsClient.Version.V3
get() = NsClient.Version.V3
override val address: String get() = sp.getString(info.nightscout.core.utils.R.string.key_nsclientinternal_url, "") 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() { 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))) if (workIsRunning(arrayOf(JOB_NAME)))
rxBus.send(EventNSClientNewLog("RUN", "Already running")) rxBus.send(EventNSClientNewLog("RUN", "Already running"))
else { else {

View file

@ -76,6 +76,7 @@ class LoadBgWorker(
} }
else { 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.lastFetched.collections.entries)}"))
nsClientV3Plugin.scheduleNewExecution() // Idea is to run after 5 min after last BG
WorkManager.getInstance(context) WorkManager.getInstance(context)
.beginUniqueWork( .beginUniqueWork(
NSClientV3Plugin.JOB_NAME, NSClientV3Plugin.JOB_NAME,

View file

@ -143,4 +143,8 @@
<string name="reset_start">Reset start</string> <string name="reset_start">Reset start</string>
<string name="upload_now">Upload now</string> <string name="upload_now">Upload now</string>
<string name="not_connected">Not connected</string>
<string name="read_only">Read only</string>
<string name="working">Working</string>
</resources> </resources>