mirror of
https://github.com/aljazceru/Android-nRF-Toolbox.git
synced 2026-01-28 11:04:27 +01:00
Fix manager in progress indicator
This commit is contained in:
@@ -4,10 +4,7 @@ import android.bluetooth.BluetoothDevice
|
||||
import android.content.Context
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.launch
|
||||
import no.nordicsemi.android.ble.ktx.suspend
|
||||
import no.nordicsemi.android.cgms.repository.CGMManager
|
||||
@@ -30,8 +27,8 @@ class CGMRepository @Inject constructor(
|
||||
private val _data = MutableStateFlow<BleManagerResult<CGMData>>(ConnectingResult())
|
||||
internal val data = _data.asStateFlow()
|
||||
|
||||
private val _isRunning = MutableStateFlow(false)
|
||||
val isRunning = _isRunning.asStateFlow()
|
||||
val isRunning = data.map { it.isRunning() }
|
||||
val hasBeenDisconnected = data.map { it.hasBeenDisconnected() }
|
||||
|
||||
fun launch(device: BluetoothDevice) {
|
||||
serviceManager.startService(CGMService::class.java, device)
|
||||
@@ -56,7 +53,6 @@ class CGMRepository @Inject constructor(
|
||||
.useAutoConnect(false)
|
||||
.retry(3, 100)
|
||||
.suspend()
|
||||
_isRunning.value = true
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
@@ -75,9 +71,7 @@ class CGMRepository @Inject constructor(
|
||||
}
|
||||
|
||||
fun release() {
|
||||
serviceManager.stopService(CGMService::class.java)
|
||||
manager?.disconnect()?.enqueue()
|
||||
manager = null
|
||||
_isRunning.value = false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ import android.bluetooth.BluetoothGattCharacteristic
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import android.util.SparseArray
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
@@ -48,6 +48,7 @@ import no.nordicsemi.android.cgms.data.CGMData
|
||||
import no.nordicsemi.android.cgms.data.CGMRecord
|
||||
import no.nordicsemi.android.cgms.data.RequestStatus
|
||||
import no.nordicsemi.android.service.ConnectionObserverAdapter
|
||||
import no.nordicsemi.android.utils.launchWithCatch
|
||||
import java.util.*
|
||||
|
||||
val CGMS_SERVICE_UUID: UUID = UUID.fromString("0000181F-0000-1000-8000-00805f9b34fb")
|
||||
@@ -80,10 +81,6 @@ internal class CGMManager(
|
||||
|
||||
private var sessionStartTime: Long = 0
|
||||
|
||||
private val exceptionHandler = CoroutineExceptionHandler { _, t ->
|
||||
Log.e("COROUTINE-EXCEPTION", "Uncaught exception", t)
|
||||
}
|
||||
|
||||
private val data = MutableStateFlow(CGMData())
|
||||
val dataHolder = ConnectionObserverAdapter<CGMData>()
|
||||
|
||||
@@ -101,32 +98,17 @@ internal class CGMManager(
|
||||
|
||||
override fun log(priority: Int, message: String) {
|
||||
super.log(priority, message)
|
||||
Log.d("COROUTINE-EXCEPTION", message)
|
||||
Log.d("CGM-PROFILE", message)
|
||||
}
|
||||
|
||||
private inner class CGMManagerGattCallback : BleManagerGattCallback() {
|
||||
override fun initialize() {
|
||||
super.initialize()
|
||||
|
||||
scope.launch(exceptionHandler) {
|
||||
val response =
|
||||
readCharacteristic(cgmFeatureCharacteristic).suspendForValidResponse<CGMFeatureResponse>()
|
||||
this@CGMManager.secured = response.features.e2eCrcSupported
|
||||
}
|
||||
|
||||
scope.launch(exceptionHandler) {
|
||||
val response =
|
||||
readCharacteristic(cgmFeatureCharacteristic).suspendForValidResponse<CGMFeatureResponse>()
|
||||
this@CGMManager.secured = response.features.e2eCrcSupported
|
||||
}
|
||||
|
||||
scope.launch(exceptionHandler) {
|
||||
val response =
|
||||
readCharacteristic(cgmStatusCharacteristic).suspendForValidResponse<CGMStatusResponse>()
|
||||
if (response.status?.sessionStopped == false) {
|
||||
sessionStartTime = System.currentTimeMillis() - response.timeOffset * 60000L
|
||||
}
|
||||
}
|
||||
enableNotifications(cgmMeasurementCharacteristic).enqueue()
|
||||
enableIndications(cgmSpecificOpsControlPointCharacteristic).enqueue()
|
||||
enableIndications(recordAccessControlPointCharacteristic).enqueue()
|
||||
enableNotifications(batteryLevelCharacteristic).enqueue()
|
||||
|
||||
setNotificationCallback(cgmMeasurementCharacteristic).asValidResponseFlow<ContinuousGlucoseMeasurementResponse>()
|
||||
.onEach {
|
||||
@@ -164,7 +146,7 @@ internal class CGMManager(
|
||||
|
||||
setIndicationCallback(recordAccessControlPointCharacteristic).asValidResponseFlow<RecordAccessControlPointResponse>()
|
||||
.onEach {
|
||||
if (it.isOperationCompleted && !it.wereRecordsFound() && it.numberOfRecords > 0) {
|
||||
if (it.isOperationCompleted && it.wereRecordsFound() && it.numberOfRecords > 0) {
|
||||
onRecordsReceived(it)
|
||||
} else if (it.isOperationCompleted && !it.wereRecordsFound()) {
|
||||
onNoRecordsFound()
|
||||
@@ -180,13 +162,16 @@ internal class CGMManager(
|
||||
data.value = data.value.copy(batteryLevel = it.batteryLevel)
|
||||
}.launchIn(scope)
|
||||
|
||||
enableNotifications(cgmMeasurementCharacteristic).enqueue()
|
||||
enableIndications(cgmSpecificOpsControlPointCharacteristic).enqueue()
|
||||
enableIndications(recordAccessControlPointCharacteristic).enqueue()
|
||||
enableNotifications(batteryLevelCharacteristic).enqueue()
|
||||
scope.launchWithCatch {
|
||||
val cgmResponse = readCharacteristic(cgmFeatureCharacteristic).suspendForValidResponse<CGMFeatureResponse>()
|
||||
this@CGMManager.secured = cgmResponse.features.e2eCrcSupported
|
||||
|
||||
if (sessionStartTime == 0L) {
|
||||
scope.launch(exceptionHandler) {
|
||||
val response = readCharacteristic(cgmStatusCharacteristic).suspendForValidResponse<CGMStatusResponse>()
|
||||
if (response.status?.sessionStopped == false) {
|
||||
sessionStartTime = System.currentTimeMillis() - response.timeOffset * 60000L
|
||||
}
|
||||
|
||||
if (sessionStartTime == 0L) {
|
||||
writeCharacteristic(
|
||||
cgmSpecificOpsControlPointCharacteristic,
|
||||
CGMSpecificOpsControlPointData.startSession(secured),
|
||||
@@ -282,7 +267,7 @@ internal class CGMManager(
|
||||
clear()
|
||||
data.value = data.value.copy(requestStatus = RequestStatus.PENDING)
|
||||
recordAccessRequestInProgress = true
|
||||
scope.launch(exceptionHandler) {
|
||||
scope.launchWithCatch {
|
||||
writeCharacteristic(
|
||||
recordAccessControlPointCharacteristic,
|
||||
RecordAccessControlPointData.reportLastStoredRecord(),
|
||||
@@ -296,7 +281,7 @@ internal class CGMManager(
|
||||
clear()
|
||||
data.value = data.value.copy(requestStatus = RequestStatus.PENDING)
|
||||
recordAccessRequestInProgress = true
|
||||
scope.launch(exceptionHandler) {
|
||||
scope.launchWithCatch {
|
||||
writeCharacteristic(
|
||||
recordAccessControlPointCharacteristic,
|
||||
RecordAccessControlPointData.reportFirstStoredRecord(),
|
||||
@@ -310,7 +295,7 @@ internal class CGMManager(
|
||||
clear()
|
||||
data.value = data.value.copy(requestStatus = RequestStatus.PENDING)
|
||||
recordAccessRequestInProgress = true
|
||||
scope.launch(exceptionHandler) {
|
||||
scope.launchWithCatch {
|
||||
writeCharacteristic(
|
||||
recordAccessControlPointCharacteristic,
|
||||
RecordAccessControlPointData.reportNumberOfAllStoredRecords(),
|
||||
|
||||
@@ -4,6 +4,8 @@ import android.bluetooth.BluetoothDevice
|
||||
import android.content.Intent
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import no.nordicsemi.android.cgms.data.CGMRepository
|
||||
import no.nordicsemi.android.service.DEVICE_DATA
|
||||
import no.nordicsemi.android.service.NotificationService
|
||||
@@ -22,6 +24,10 @@ internal class CGMService : NotificationService() {
|
||||
|
||||
repository.start(device, lifecycleScope)
|
||||
|
||||
repository.hasBeenDisconnected.onEach {
|
||||
if (it) stopSelf()
|
||||
}.launchIn(lifecycleScope)
|
||||
|
||||
return START_REDELIVER_INTENT
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,11 +32,11 @@ fun CGMScreen() {
|
||||
when (state) {
|
||||
NoDeviceState -> NoDeviceView()
|
||||
is WorkingState -> when (state.result) {
|
||||
is ConnectingResult,
|
||||
is ReadyResult -> DeviceConnectingView { viewModel.onEvent(DisconnectEvent) }
|
||||
is ConnectingResult -> DeviceConnectingView { viewModel.onEvent(DisconnectEvent) }
|
||||
is DisconnectedResult -> DeviceDisconnectedView(Reason.USER, navigateUp)
|
||||
is LinkLossResult -> DeviceDisconnectedView(Reason.LINK_LOSS, navigateUp)
|
||||
is MissingServiceResult -> DeviceDisconnectedView(Reason.MISSING_SERVICE, navigateUp)
|
||||
is UnknownErrorResult -> DeviceDisconnectedView(Reason.UNKNOWN, navigateUp)
|
||||
is SuccessResult -> CGMContentView(state.result.data) { viewModel.onEvent(it) }
|
||||
}
|
||||
}.exhaustive
|
||||
|
||||
@@ -3,10 +3,8 @@ package no.nordicsemi.android.cgms.viewmodel
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.launch
|
||||
import no.nordicsemi.android.cgms.data.CGMRepository
|
||||
import no.nordicsemi.android.cgms.data.CGMServiceCommand
|
||||
import no.nordicsemi.android.cgms.repository.CGMS_SERVICE_UUID
|
||||
@@ -27,8 +25,10 @@ internal class CGMScreenViewModel @Inject constructor(
|
||||
val state = _state.asStateFlow()
|
||||
|
||||
init {
|
||||
if (!repository.isRunning.value) {
|
||||
requestBluetoothDevice()
|
||||
viewModelScope.launch {
|
||||
if (repository.isRunning.firstOrNull() == false) {
|
||||
requestBluetoothDevice()
|
||||
}
|
||||
}
|
||||
|
||||
repository.data.onEach {
|
||||
|
||||
Reference in New Issue
Block a user