diff --git a/app/src/main/java/no/nordicsemi/android/nrftoolbox/viewmodel/HomeViewModel.kt b/app/src/main/java/no/nordicsemi/android/nrftoolbox/viewmodel/HomeViewModel.kt index 10a6c463..14654d12 100644 --- a/app/src/main/java/no/nordicsemi/android/nrftoolbox/viewmodel/HomeViewModel.kt +++ b/app/src/main/java/no/nordicsemi/android/nrftoolbox/viewmodel/HomeViewModel.kt @@ -10,6 +10,7 @@ import kotlinx.coroutines.flow.onEach import no.nordicsemi.android.cgms.data.CGMRepository import no.nordicsemi.android.csc.data.CSCRepository import no.nordicsemi.android.hrs.data.HRSRepository +import no.nordicsemi.android.hts.data.HTSRepository import no.nordicsemi.android.navigation.NavigationManager import no.nordicsemi.android.nrftoolbox.ProfileDestination import no.nordicsemi.android.nrftoolbox.view.HomeViewState @@ -20,7 +21,8 @@ class HomeViewModel @Inject constructor( private val navigationManager: NavigationManager, cgmRepository: CGMRepository, cscRepository: CSCRepository, - hrsRepository: HRSRepository + hrsRepository: HRSRepository, + htsRepository: HTSRepository ) : ViewModel() { private val _state = MutableStateFlow(HomeViewState()) @@ -38,6 +40,10 @@ class HomeViewModel @Inject constructor( hrsRepository.isRunning.onEach { _state.value = _state.value.copy(isHRSModuleRunning = it) }.launchIn(viewModelScope) + + htsRepository.isRunning.onEach { + _state.value = _state.value.copy(isHTSModuleRunning = it) + }.launchIn(viewModelScope) } fun openProfile(destination: ProfileDestination) { diff --git a/profile_hrs/src/main/java/no/nordicsemi/android/hrs/service/HRSManager.kt b/profile_hrs/src/main/java/no/nordicsemi/android/hrs/service/HRSManager.kt index 0f15a10f..de7b7244 100644 --- a/profile_hrs/src/main/java/no/nordicsemi/android/hrs/service/HRSManager.kt +++ b/profile_hrs/src/main/java/no/nordicsemi/android/hrs/service/HRSManager.kt @@ -120,6 +120,7 @@ internal class HRSManager( override fun onServicesInvalidated() { bodySensorLocationCharacteristic = null heartRateCharacteristic = null + batteryLevelCharacteristic = null } } } diff --git a/profile_hts/src/main/java/no/nordicsemi/android/hts/data/HTSData.kt b/profile_hts/src/main/java/no/nordicsemi/android/hts/data/HTSData.kt index a9f5b81f..6523de27 100644 --- a/profile_hts/src/main/java/no/nordicsemi/android/hts/data/HTSData.kt +++ b/profile_hts/src/main/java/no/nordicsemi/android/hts/data/HTSData.kt @@ -1,56 +1,6 @@ package no.nordicsemi.android.hts.data -import no.nordicsemi.android.material.you.RadioButtonItem -import no.nordicsemi.android.material.you.RadioGroupViewEntity - -private const val DISPLAY_FAHRENHEIT = "°F" -private const val DISPLAY_CELSIUS = "°C" -private const val DISPLAY_KELVIN = "°K" - internal data class HTSData( val temperatureValue: Float = 0f, - val temperatureUnit: TemperatureUnit = TemperatureUnit.CELSIUS, val batteryLevel: Int = 0, -) { - - fun displayTemperature(): String { - return when (temperatureUnit) { - TemperatureUnit.CELSIUS -> String.format("%.1f °C", temperatureValue) - TemperatureUnit.FAHRENHEIT -> String.format("%.1f °F", temperatureValue * 1.8f + 32f) - TemperatureUnit.KELVIN -> String.format("%.1f °K", temperatureValue + 273.15f) - } - } - - fun getTemperatureUnit(label: String): TemperatureUnit { - return when (label) { - DISPLAY_CELSIUS -> TemperatureUnit.CELSIUS - DISPLAY_FAHRENHEIT -> TemperatureUnit.FAHRENHEIT - DISPLAY_KELVIN -> TemperatureUnit.KELVIN - else -> throw IllegalArgumentException("Can't create TemperatureUnit from this label: $label") - } - } - - fun temperatureSettingsItems(): RadioGroupViewEntity { - return RadioGroupViewEntity( - TemperatureUnit.values().map { createRadioButtonItem(it) } - ) - } - - private fun createRadioButtonItem(unit: TemperatureUnit): RadioButtonItem { - return RadioButtonItem(displayTemperature(unit), unit == temperatureUnit) - } - - private fun displayTemperature(unit: TemperatureUnit): String { - return when (unit) { - TemperatureUnit.CELSIUS -> DISPLAY_CELSIUS - TemperatureUnit.FAHRENHEIT -> DISPLAY_FAHRENHEIT - TemperatureUnit.KELVIN -> DISPLAY_KELVIN - } - } -} - -internal enum class TemperatureUnit { - CELSIUS, - FAHRENHEIT, - KELVIN -} +) diff --git a/profile_hts/src/main/java/no/nordicsemi/android/hts/data/HTSRepository.kt b/profile_hts/src/main/java/no/nordicsemi/android/hts/data/HTSRepository.kt index d5b726ee..af24c5f6 100644 --- a/profile_hts/src/main/java/no/nordicsemi/android/hts/data/HTSRepository.kt +++ b/profile_hts/src/main/java/no/nordicsemi/android/hts/data/HTSRepository.kt @@ -1,49 +1,70 @@ package no.nordicsemi.android.hts.data -import kotlinx.coroutines.channels.BufferOverflow -import kotlinx.coroutines.flow.* -import no.nordicsemi.android.service.BleManagerStatus +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.launch +import no.nordicsemi.android.ble.ktx.suspend +import no.nordicsemi.android.hts.repository.HTSManager +import no.nordicsemi.android.hts.repository.HTSService +import no.nordicsemi.android.service.BleManagerResult +import no.nordicsemi.android.service.ConnectingResult +import no.nordicsemi.android.service.ServiceManager import javax.inject.Inject import javax.inject.Singleton @Singleton -internal class HTSRepository @Inject constructor() { +class HTSRepository @Inject constructor( + @ApplicationContext + private val context: Context, + private val serviceManager: ServiceManager, +) { + private var manager: HTSManager? = null - private val _data = MutableStateFlow(HTSData()) - val data: StateFlow = _data + private val _data = MutableStateFlow>(ConnectingResult()) + internal val data = _data.asStateFlow() - private val _command = MutableSharedFlow(extraBufferCapacity = 1, onBufferOverflow = BufferOverflow.DROP_LATEST) - val command = _command.asSharedFlow() + private val _isRunning = MutableStateFlow(false) + val isRunning = _isRunning.asStateFlow() - private val _status = MutableStateFlow(BleManagerStatus.CONNECTING) - val status = _status.asStateFlow() - - fun setNewTemperature(temperature: Float) { - _data.tryEmit(_data.value.copy(temperatureValue = temperature)) + fun launch(device: BluetoothDevice) { + serviceManager.startService(HTSService::class.java, device) } - fun setBatteryLevel(batteryLevel: Int) { - _data.tryEmit(_data.value.copy(batteryLevel = batteryLevel)) - } + fun start(device: BluetoothDevice, scope: CoroutineScope) { + val manager = HTSManager(context, scope) + this.manager = manager - fun setTemperatureUnit(unit: TemperatureUnit) { - _data.tryEmit(_data.value.copy(temperatureUnit = unit)) - } + manager.dataHolder.status.onEach { + _data.value = it + }.launchIn(scope) - fun sendDisconnectCommand() { - if (_command.subscriptionCount.value > 0) { - _command.tryEmit(DisconnectCommand) - } else { - _status.tryEmit(BleManagerStatus.DISCONNECTED) + scope.launch { + manager.start(device) } } - fun setNewStatus(status: BleManagerStatus) { - _status.value = status + private suspend fun HTSManager.start(device: BluetoothDevice) { + try { + connect(device) + .useAutoConnect(false) + .retry(3, 100) + .suspend() + _isRunning.value = true + } catch (e: Exception) { + e.printStackTrace() + } } - fun clear() { - _status.value = BleManagerStatus.CONNECTING - _data.tryEmit(HTSData()) + fun release() { + serviceManager.stopService(HTSService::class.java) + manager?.disconnect()?.enqueue() + manager = null + _isRunning.value = false } } diff --git a/profile_hts/src/main/java/no/nordicsemi/android/hts/repository/HTSManager.kt b/profile_hts/src/main/java/no/nordicsemi/android/hts/repository/HTSManager.kt index 90fd7cef..f848c979 100644 --- a/profile_hts/src/main/java/no/nordicsemi/android/hts/repository/HTSManager.kt +++ b/profile_hts/src/main/java/no/nordicsemi/android/hts/repository/HTSManager.kt @@ -24,70 +24,77 @@ package no.nordicsemi.android.hts.repository import android.bluetooth.BluetoothGatt import android.bluetooth.BluetoothGattCharacteristic import android.content.Context -import android.util.Log -import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach -import kotlinx.coroutines.launch +import no.nordicsemi.android.ble.BleManager +import no.nordicsemi.android.ble.common.callback.battery.BatteryLevelResponse import no.nordicsemi.android.ble.common.callback.ht.TemperatureMeasurementResponse import no.nordicsemi.android.ble.ktx.asValidResponseFlow -import no.nordicsemi.android.ble.ktx.suspend -import no.nordicsemi.android.hts.data.HTSRepository -import no.nordicsemi.android.service.BatteryManager +import no.nordicsemi.android.hts.data.HTSData +import no.nordicsemi.android.service.ConnectionObserverAdapter import java.util.* val HTS_SERVICE_UUID: UUID = UUID.fromString("00001809-0000-1000-8000-00805f9b34fb") private val HT_MEASUREMENT_CHARACTERISTIC_UUID = UUID.fromString("00002A1C-0000-1000-8000-00805f9b34fb") +private val BATTERY_SERVICE_UUID = UUID.fromString("0000180F-0000-1000-8000-00805f9b34fb") +private val BATTERY_LEVEL_CHARACTERISTIC_UUID = UUID.fromString("00002A19-0000-1000-8000-00805f9b34fb") + internal class HTSManager internal constructor( context: Context, - scope: CoroutineScope, - private val dataHolder: HTSRepository -) : BatteryManager(context, scope) { + private val scope: CoroutineScope, +) : BleManager(context) { + private var batteryLevelCharacteristic: BluetoothGattCharacteristic? = null private var htCharacteristic: BluetoothGattCharacteristic? = null - private val exceptionHandler = CoroutineExceptionHandler { _, t-> - Log.e("COROUTINE-EXCEPTION", "Uncaught exception", t) + private val data = MutableStateFlow(HTSData()) + val dataHolder = ConnectionObserverAdapter() + + init { + setConnectionObserver(dataHolder) + + data.onEach { + dataHolder.setValue(it) + }.launchIn(scope) } - override fun onBatteryLevelChanged(batteryLevel: Int) { - dataHolder.setBatteryLevel(batteryLevel) - } - - override fun getGattCallback(): BatteryManagerGattCallback { + override fun getGattCallback(): BleManagerGattCallback { return HTManagerGattCallback() } - private inner class HTManagerGattCallback : BatteryManagerGattCallback() { + private inner class HTManagerGattCallback : BleManagerGattCallback() { override fun initialize() { super.initialize() setIndicationCallback(htCharacteristic) .asValidResponseFlow() .onEach { - dataHolder.setNewTemperature(it.temperature) + data.tryEmit(data.value.copy(temperatureValue = it.temperature)) }.launchIn(scope) + enableIndications(htCharacteristic).enqueue() - scope.launch(exceptionHandler) { - enableIndications(htCharacteristic).suspend() - } + setNotificationCallback(batteryLevelCharacteristic).asValidResponseFlow().onEach { + data.value = data.value.copy(batteryLevel = it.batteryLevel) + }.launchIn(scope) + enableNotifications(batteryLevelCharacteristic).enqueue() } override fun isRequiredServiceSupported(gatt: BluetoothGatt): Boolean { - val service = gatt.getService(HTS_SERVICE_UUID) - if (service != null) { - htCharacteristic = service.getCharacteristic(HT_MEASUREMENT_CHARACTERISTIC_UUID) + gatt.getService(HTS_SERVICE_UUID)?.run { + htCharacteristic = getCharacteristic(HT_MEASUREMENT_CHARACTERISTIC_UUID) + } + gatt.getService(BATTERY_SERVICE_UUID)?.run { + batteryLevelCharacteristic = getCharacteristic(BATTERY_LEVEL_CHARACTERISTIC_UUID) } return htCharacteristic != null } - override fun onDeviceDisconnected() { - super.onDeviceDisconnected() + override fun onServicesInvalidated() { htCharacteristic = null + batteryLevelCharacteristic = null } - - override fun onServicesInvalidated() {} } } diff --git a/profile_hts/src/main/java/no/nordicsemi/android/hts/repository/HTSService.kt b/profile_hts/src/main/java/no/nordicsemi/android/hts/repository/HTSService.kt index 6e01a750..a921a0f1 100644 --- a/profile_hts/src/main/java/no/nordicsemi/android/hts/repository/HTSService.kt +++ b/profile_hts/src/main/java/no/nordicsemi/android/hts/repository/HTSService.kt @@ -1,25 +1,27 @@ package no.nordicsemi.android.hts.repository +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.hts.data.HTSRepository -import no.nordicsemi.android.service.ForegroundBleService +import no.nordicsemi.android.service.DEVICE_DATA +import no.nordicsemi.android.service.NotificationService import javax.inject.Inject @AndroidEntryPoint -internal class HTSService : ForegroundBleService() { +internal class HTSService : NotificationService() { @Inject lateinit var repository: HTSRepository - override val manager: HTSManager by lazy { HTSManager(this, scope, repository) } + override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { + super.onStartCommand(intent, flags, startId) - override fun onCreate() { - super.onCreate() + val device = intent!!.getParcelableExtra(DEVICE_DATA)!! - repository.command.onEach { - stopSelf() - }.launchIn(scope) + repository.start(device, lifecycleScope) + + return START_REDELIVER_INTENT } } diff --git a/profile_hts/src/main/java/no/nordicsemi/android/hts/view/HTSContentView.kt b/profile_hts/src/main/java/no/nordicsemi/android/hts/view/HTSContentView.kt index ee650d4b..969ba126 100644 --- a/profile_hts/src/main/java/no/nordicsemi/android/hts/view/HTSContentView.kt +++ b/profile_hts/src/main/java/no/nordicsemi/android/hts/view/HTSContentView.kt @@ -18,7 +18,7 @@ import no.nordicsemi.android.theme.view.ScreenSection import no.nordicsemi.android.theme.view.SectionTitle @Composable -internal fun HTSContentView(state: HTSData, onEvent: (HTSScreenViewEvent) -> Unit) { +internal fun HTSContentView(state: HTSData, temperatureUnit: TemperatureUnit, onEvent: (HTSScreenViewEvent) -> Unit) { Column( modifier = Modifier .fillMaxSize() @@ -30,21 +30,21 @@ internal fun HTSContentView(state: HTSData, onEvent: (HTSScreenViewEvent) -> Uni Spacer(modifier = Modifier.height(16.dp)) - RadioButtonGroup(viewEntity = state.temperatureSettingsItems()) { - onEvent(OnTemperatureUnitSelected(state.getTemperatureUnit(it.label))) + RadioButtonGroup(viewEntity = temperatureUnit.temperatureSettingsItems()) { + onEvent(OnTemperatureUnitSelected(it.label.toTemperatureUnit())) } } Spacer(modifier = Modifier.height(16.dp)) ScreenSection { - SectionTitle(resId = R.drawable.ic_records, title = "Records") + SectionTitle(resId = R.drawable.ic_records, title = stringResource(id = R.string.hts_records_section)) Spacer(modifier = Modifier.height(16.dp)) KeyValueField( stringResource(id = R.string.hts_temperature), - state.displayTemperature() + displayTemperature(state.temperatureValue, temperatureUnit) ) } @@ -65,5 +65,5 @@ internal fun HTSContentView(state: HTSData, onEvent: (HTSScreenViewEvent) -> Uni @Preview @Composable private fun Preview() { - HTSContentView(state = HTSData()) { } + HTSContentView(state = HTSData(), TemperatureUnit.CELSIUS) { } } diff --git a/profile_hts/src/main/java/no/nordicsemi/android/hts/view/HTSMapper.kt b/profile_hts/src/main/java/no/nordicsemi/android/hts/view/HTSMapper.kt new file mode 100644 index 00000000..9b3cf45b --- /dev/null +++ b/profile_hts/src/main/java/no/nordicsemi/android/hts/view/HTSMapper.kt @@ -0,0 +1,43 @@ +package no.nordicsemi.android.hts.view + +import no.nordicsemi.android.material.you.RadioButtonItem +import no.nordicsemi.android.material.you.RadioGroupViewEntity + +private const val DISPLAY_FAHRENHEIT = "°F" +private const val DISPLAY_CELSIUS = "°C" +private const val DISPLAY_KELVIN = "°K" + +internal fun displayTemperature(value: Float, temperatureUnit: TemperatureUnit): String { + return when (temperatureUnit) { + TemperatureUnit.CELSIUS -> String.format("%.1f °C", value) + TemperatureUnit.FAHRENHEIT -> String.format("%.1f °F", value * 1.8f + 32f) + TemperatureUnit.KELVIN -> String.format("%.1f °K", value + 273.15f) + } +} + +internal fun String.toTemperatureUnit(): TemperatureUnit { + return when (this) { + DISPLAY_CELSIUS -> TemperatureUnit.CELSIUS + DISPLAY_FAHRENHEIT -> TemperatureUnit.FAHRENHEIT + DISPLAY_KELVIN -> TemperatureUnit.KELVIN + else -> throw IllegalArgumentException("Can't create TemperatureUnit from this label: $this") + } +} + +internal fun TemperatureUnit.temperatureSettingsItems(): RadioGroupViewEntity { + return RadioGroupViewEntity( + TemperatureUnit.values().map { createRadioButtonItem(it, this) } + ) +} + +private fun createRadioButtonItem(unit: TemperatureUnit, selectedTemperatureUnit: TemperatureUnit): RadioButtonItem { + return RadioButtonItem(displayTemperature(unit), unit == selectedTemperatureUnit) +} + +private fun displayTemperature(unit: TemperatureUnit): String { + return when (unit) { + TemperatureUnit.CELSIUS -> DISPLAY_CELSIUS + TemperatureUnit.FAHRENHEIT -> DISPLAY_FAHRENHEIT + TemperatureUnit.KELVIN -> DISPLAY_KELVIN + } +} diff --git a/profile_hts/src/main/java/no/nordicsemi/android/hts/view/HTSScreen.kt b/profile_hts/src/main/java/no/nordicsemi/android/hts/view/HTSScreen.kt index 876aa523..b6ff8cef 100644 --- a/profile_hts/src/main/java/no/nordicsemi/android/hts/view/HTSScreen.kt +++ b/profile_hts/src/main/java/no/nordicsemi/android/hts/view/HTSScreen.kt @@ -10,7 +10,13 @@ import androidx.compose.ui.res.stringResource import androidx.hilt.navigation.compose.hiltViewModel import no.nordicsemi.android.hts.R import no.nordicsemi.android.hts.viewmodel.HTSViewModel +import no.nordicsemi.android.service.* import no.nordicsemi.android.theme.view.BackIconAppBar +import no.nordicsemi.android.theme.view.scanner.DeviceConnectingView +import no.nordicsemi.android.theme.view.scanner.DeviceDisconnectedView +import no.nordicsemi.android.theme.view.scanner.NoDeviceView +import no.nordicsemi.android.theme.view.scanner.Reason +import no.nordicsemi.android.utils.exhaustive @Composable fun HTSScreen() { @@ -18,15 +24,22 @@ fun HTSScreen() { val state = viewModel.state.collectAsState().value Column { - BackIconAppBar(stringResource(id = R.string.hts_title)) { - viewModel.onEvent(DisconnectEvent) - } + val navigateUp = { viewModel.onEvent(NavigateUp) } + + BackIconAppBar(stringResource(id = R.string.hts_title), navigateUp) Column(modifier = Modifier.verticalScroll(rememberScrollState())) { -// when (state) { -// is DisplayDataState -> HTSContentView(state.data) { viewModel.onEvent(it) } -// LoadingState -> DeviceConnectingView() -// }.exhaustive + when (state.htsManagerState) { + NoDeviceState -> NoDeviceView() + is WorkingState -> when (state.htsManagerState.result) { + is ConnectingResult, + is ReadyResult -> 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 SuccessResult -> HTSContentView(state.htsManagerState.result.data, state.temperatureUnit) { viewModel.onEvent(it) } + } + }.exhaustive } } } diff --git a/profile_hts/src/main/java/no/nordicsemi/android/hts/view/HTSScreenViewEvent.kt b/profile_hts/src/main/java/no/nordicsemi/android/hts/view/HTSScreenViewEvent.kt index 886df9b6..a2578ce0 100644 --- a/profile_hts/src/main/java/no/nordicsemi/android/hts/view/HTSScreenViewEvent.kt +++ b/profile_hts/src/main/java/no/nordicsemi/android/hts/view/HTSScreenViewEvent.kt @@ -1,9 +1,9 @@ package no.nordicsemi.android.hts.view -import no.nordicsemi.android.hts.data.TemperatureUnit - internal sealed class HTSScreenViewEvent internal data class OnTemperatureUnitSelected(val value: TemperatureUnit) : HTSScreenViewEvent() internal object DisconnectEvent : HTSScreenViewEvent() + +internal object NavigateUp : HTSScreenViewEvent() diff --git a/profile_hts/src/main/java/no/nordicsemi/android/hts/view/HTSState.kt b/profile_hts/src/main/java/no/nordicsemi/android/hts/view/HTSState.kt index 36e8c6dc..268b7950 100644 --- a/profile_hts/src/main/java/no/nordicsemi/android/hts/view/HTSState.kt +++ b/profile_hts/src/main/java/no/nordicsemi/android/hts/view/HTSState.kt @@ -1,9 +1,15 @@ package no.nordicsemi.android.hts.view import no.nordicsemi.android.hts.data.HTSData +import no.nordicsemi.android.service.BleManagerResult -internal sealed class HTSViewState +internal data class HTSViewState( + val temperatureUnit: TemperatureUnit = TemperatureUnit.CELSIUS, + val htsManagerState: HTSManagerState = NoDeviceState +) -internal object LoadingState : HTSViewState() +internal sealed class HTSManagerState -internal data class DisplayDataState(val data: HTSData) : HTSViewState() +internal data class WorkingState(val result: BleManagerResult) : HTSManagerState() + +internal object NoDeviceState : HTSManagerState() diff --git a/profile_hts/src/main/java/no/nordicsemi/android/hts/view/TemperatureUnit.kt b/profile_hts/src/main/java/no/nordicsemi/android/hts/view/TemperatureUnit.kt new file mode 100644 index 00000000..8da3a7ba --- /dev/null +++ b/profile_hts/src/main/java/no/nordicsemi/android/hts/view/TemperatureUnit.kt @@ -0,0 +1,7 @@ +package no.nordicsemi.android.hts.view + +internal enum class TemperatureUnit { + CELSIUS, + FAHRENHEIT, + KELVIN +} diff --git a/profile_hts/src/main/java/no/nordicsemi/android/hts/viewmodel/HTSViewModel.kt b/profile_hts/src/main/java/no/nordicsemi/android/hts/viewmodel/HTSViewModel.kt index 68a67dac..b49780ea 100644 --- a/profile_hts/src/main/java/no/nordicsemi/android/hts/viewmodel/HTSViewModel.kt +++ b/profile_hts/src/main/java/no/nordicsemi/android/hts/viewmodel/HTSViewModel.kt @@ -9,7 +9,6 @@ import no.nordicsemi.android.hts.repository.HTSService import no.nordicsemi.android.hts.repository.HTS_SERVICE_UUID import no.nordicsemi.android.hts.view.* import no.nordicsemi.android.navigation.* -import no.nordicsemi.android.service.BleManagerStatus import no.nordicsemi.android.service.ServiceManager import no.nordicsemi.android.utils.exhaustive import no.nordicsemi.android.utils.getDevice @@ -23,15 +22,20 @@ internal class HTSViewModel @Inject constructor( private val navigationManager: NavigationManager ) : ViewModel() { - val state = repository.data.combine(repository.status) { data, status -> -// when (status) { -// BleManagerStatus.CONNECTING -> LoadingState -// BleManagerStatus.OK, -// BleManagerStatus.DISCONNECTED -> DisplayDataState(data) -// } - }.stateIn(viewModelScope, SharingStarted.Lazily, LoadingState) + private val _state = MutableStateFlow(HTSViewState()) + val state = _state.asStateFlow() init { + if (!repository.isRunning.value) { + requestBluetoothDevice() + } + + repository.data.onEach { + _state.value = _state.value.copy(htsManagerState = WorkingState(it)) + }.launchIn(viewModelScope) + } + + private fun requestBluetoothDevice() { navigationManager.navigateTo(ScannerDestinationId, UUIDArgument(HTS_SERVICE_UUID)) navigationManager.recentResult.onEach { @@ -39,39 +43,29 @@ internal class HTSViewModel @Inject constructor( handleArgs(it) } }.launchIn(viewModelScope) - - repository.status.onEach { - if (it == BleManagerStatus.DISCONNECTED) { - navigationManager.navigateUp() - } - }.launchIn(viewModelScope) } private fun handleArgs(args: DestinationResult) { when (args) { is CancelDestinationResult -> navigationManager.navigateUp() - is SuccessDestinationResult -> serviceManager.startService(HTSService::class.java, args.getDevice()) + is SuccessDestinationResult -> repository.launch(args.getDevice().device) }.exhaustive } fun onEvent(event: HTSScreenViewEvent) { when (event) { - DisconnectEvent -> onDisconnectButtonClick() + DisconnectEvent -> disconnect() is OnTemperatureUnitSelected -> onTemperatureUnitSelected(event) + NavigateUp -> navigationManager.navigateUp() }.exhaustive } - private fun onDisconnectButtonClick() { - repository.sendDisconnectCommand() - repository.clear() + private fun disconnect() { + repository.release() + navigationManager.navigateUp() } private fun onTemperatureUnitSelected(event: OnTemperatureUnitSelected) { - repository.setTemperatureUnit(event.value) - } - - override fun onCleared() { - super.onCleared() - repository.clear() + _state.value = _state.value.copy(temperatureUnit = event.value) } } diff --git a/profile_hts/src/main/res/values/strings.xml b/profile_hts/src/main/res/values/strings.xml index 5c8ad9a6..4c3ebe91 100644 --- a/profile_hts/src/main/res/values/strings.xml +++ b/profile_hts/src/main/res/values/strings.xml @@ -7,4 +7,5 @@ %.1f °K Temperature + Records