mirror of
https://github.com/aljazceru/Android-nRF-Toolbox.git
synced 2026-01-08 01:04:20 +01:00
Change UART service
This commit is contained in:
@@ -4,6 +4,5 @@ import no.nordicsemi.android.utils.EMPTY
|
||||
|
||||
internal data class UARTData(
|
||||
val text: String = String.EMPTY,
|
||||
val macros: List<UARTMacro> = emptyList(),
|
||||
val batteryLevel: Int = 0
|
||||
)
|
||||
|
||||
@@ -1,58 +1,74 @@
|
||||
package no.nordicsemi.android.uart.data
|
||||
|
||||
import kotlinx.coroutines.channels.BufferOverflow
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
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.asSharedFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import no.nordicsemi.android.service.BleManagerStatus
|
||||
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.service.BleManagerResult
|
||||
import no.nordicsemi.android.service.ConnectingResult
|
||||
import no.nordicsemi.android.service.ServiceManager
|
||||
import no.nordicsemi.android.uart.repository.UARTManager
|
||||
import no.nordicsemi.android.uart.repository.UARTService
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
internal class UARTRepository @Inject constructor() {
|
||||
class UARTRepository @Inject constructor(
|
||||
@ApplicationContext
|
||||
private val context: Context,
|
||||
private val serviceManager: ServiceManager,
|
||||
) {
|
||||
private var manager: UARTManager? = null
|
||||
|
||||
private val _data = MutableStateFlow(UARTData())
|
||||
val data = _data.asStateFlow()
|
||||
private val _data = MutableStateFlow<BleManagerResult<UARTData>>(ConnectingResult())
|
||||
internal val data = _data.asStateFlow()
|
||||
|
||||
private val _command = MutableSharedFlow<UARTServiceCommand>(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 addNewMacro(macro: UARTMacro) {
|
||||
_data.tryEmit(_data.value.copy(macros = _data.value.macros + macro))
|
||||
fun launch(device: BluetoothDevice) {
|
||||
serviceManager.startService(UARTService::class.java, device)
|
||||
}
|
||||
|
||||
fun deleteMacro(macro: UARTMacro) {
|
||||
val macros = _data.value.macros.toMutableList().apply {
|
||||
remove(macro)
|
||||
}
|
||||
_data.tryEmit(_data.value.copy(macros = macros))
|
||||
}
|
||||
fun start(device: BluetoothDevice, scope: CoroutineScope) {
|
||||
val manager = UARTManager(context, scope)
|
||||
this.manager = manager
|
||||
|
||||
fun emitNewMessage(message: String) {
|
||||
_data.tryEmit(_data.value.copy(text = message))
|
||||
}
|
||||
manager.dataHolder.status.onEach {
|
||||
_data.value = it
|
||||
}.launchIn(scope)
|
||||
|
||||
fun emitNewBatteryLevel(batteryLevel: Int) {
|
||||
_data.tryEmit(_data.value.copy(batteryLevel = batteryLevel))
|
||||
}
|
||||
|
||||
fun sendNewCommand(command: UARTServiceCommand) {
|
||||
if (_command.subscriptionCount.value > 0) {
|
||||
_command.tryEmit(command)
|
||||
} else {
|
||||
_status.tryEmit(BleManagerStatus.DISCONNECTED)
|
||||
scope.launch {
|
||||
manager.start(device)
|
||||
}
|
||||
}
|
||||
|
||||
fun setNewStatus(status: BleManagerStatus) {
|
||||
_status.value = status
|
||||
fun runMacro(macro: UARTMacro) {
|
||||
manager?.send(macro.command)
|
||||
}
|
||||
|
||||
fun clear() {
|
||||
_status.value = BleManagerStatus.CONNECTING
|
||||
private suspend fun UARTManager.start(device: BluetoothDevice) {
|
||||
try {
|
||||
connect(device)
|
||||
.useAutoConnect(false)
|
||||
.retry(3, 100)
|
||||
.suspend()
|
||||
_isRunning.value = true
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
fun release() {
|
||||
serviceManager.stopService(UARTService::class.java)
|
||||
manager?.disconnect()?.enqueue()
|
||||
manager = null
|
||||
_isRunning.value = false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,53 +26,66 @@ import android.bluetooth.BluetoothGattCharacteristic
|
||||
import android.bluetooth.BluetoothGattService
|
||||
import android.content.Context
|
||||
import android.text.TextUtils
|
||||
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.WriteRequest
|
||||
import no.nordicsemi.android.ble.common.callback.battery.BatteryLevelResponse
|
||||
import no.nordicsemi.android.ble.ktx.asFlow
|
||||
import no.nordicsemi.android.ble.ktx.suspend
|
||||
import no.nordicsemi.android.service.BatteryManager
|
||||
import no.nordicsemi.android.uart.data.UARTRepository
|
||||
import no.nordicsemi.android.ble.ktx.asValidResponseFlow
|
||||
import no.nordicsemi.android.service.ConnectionObserverAdapter
|
||||
import no.nordicsemi.android.uart.data.UARTData
|
||||
import no.nordicsemi.android.utils.EMPTY
|
||||
import no.nordicsemi.android.utils.launchWithCatch
|
||||
import java.util.*
|
||||
|
||||
val UART_SERVICE_UUID = UUID.fromString("6E400001-B5A3-F393-E0A9-E50E24DCCA9E")
|
||||
private val UART_RX_CHARACTERISTIC_UUID = UUID.fromString("6E400002-B5A3-F393-E0A9-E50E24DCCA9E")
|
||||
private val UART_TX_CHARACTERISTIC_UUID = UUID.fromString("6E400003-B5A3-F393-E0A9-E50E24DCCA9E")
|
||||
|
||||
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 UARTManager(
|
||||
context: Context,
|
||||
scope: CoroutineScope,
|
||||
private val dataHolder: UARTRepository
|
||||
) : BatteryManager(context, scope) {
|
||||
private val scope: CoroutineScope,
|
||||
) : BleManager(context) {
|
||||
|
||||
private var batteryLevelCharacteristic: BluetoothGattCharacteristic? = null
|
||||
|
||||
private var rxCharacteristic: BluetoothGattCharacteristic? = null
|
||||
private var txCharacteristic: BluetoothGattCharacteristic? = null
|
||||
|
||||
private val exceptionHandler = CoroutineExceptionHandler { _, t->
|
||||
Log.e("COROUTINE-EXCEPTION", "Uncaught exception", t)
|
||||
}
|
||||
|
||||
private var useLongWrite = true
|
||||
|
||||
private inner class UARTManagerGattCallback : BatteryManagerGattCallback() {
|
||||
private val data = MutableStateFlow(UARTData())
|
||||
val dataHolder = ConnectionObserverAdapter<UARTData>()
|
||||
|
||||
init {
|
||||
setConnectionObserver(dataHolder)
|
||||
|
||||
data.onEach {
|
||||
dataHolder.setValue(it)
|
||||
}.launchIn(scope)
|
||||
}
|
||||
|
||||
private inner class UARTManagerGattCallback : BleManagerGattCallback() {
|
||||
|
||||
override fun initialize() {
|
||||
setNotificationCallback(txCharacteristic).asFlow().onEach {
|
||||
val text: String = it.getStringValue(0) ?: String.EMPTY
|
||||
dataHolder.emitNewMessage(text)
|
||||
data.tryEmit(data.value.copy(text = text))
|
||||
}
|
||||
|
||||
scope.launch(exceptionHandler) {
|
||||
requestMtu(260).suspend()
|
||||
}
|
||||
requestMtu(260).enqueue()
|
||||
enableNotifications(txCharacteristic).enqueue()
|
||||
|
||||
scope.launch(exceptionHandler) {
|
||||
enableNotifications(txCharacteristic).suspend()
|
||||
}
|
||||
setNotificationCallback(batteryLevelCharacteristic).asValidResponseFlow<BatteryLevelResponse>().onEach {
|
||||
data.value = data.value.copy(batteryLevel = it.batteryLevel)
|
||||
}.launchIn(scope)
|
||||
enableNotifications(batteryLevelCharacteristic).enqueue()
|
||||
}
|
||||
|
||||
override fun isRequiredServiceSupported(gatt: BluetoothGatt): Boolean {
|
||||
@@ -100,24 +113,24 @@ internal class UARTManager(
|
||||
useLongWrite = false
|
||||
}
|
||||
}
|
||||
return rxCharacteristic != null && txCharacteristic != null && (writeRequest || writeCommand)
|
||||
}
|
||||
|
||||
override fun onDeviceDisconnected() {
|
||||
rxCharacteristic = null
|
||||
txCharacteristic = null
|
||||
useLongWrite = true
|
||||
gatt.getService(BATTERY_SERVICE_UUID)?.run {
|
||||
batteryLevelCharacteristic = getCharacteristic(BATTERY_LEVEL_CHARACTERISTIC_UUID)
|
||||
}
|
||||
return rxCharacteristic != null && txCharacteristic != null && batteryLevelCharacteristic != null && (writeRequest || writeCommand)
|
||||
}
|
||||
|
||||
override fun onServicesInvalidated() {
|
||||
|
||||
batteryLevelCharacteristic = null
|
||||
rxCharacteristic = null
|
||||
txCharacteristic = null
|
||||
useLongWrite = true
|
||||
}
|
||||
}
|
||||
|
||||
fun send(text: String) {
|
||||
if (rxCharacteristic == null) return
|
||||
if (!TextUtils.isEmpty(text)) {
|
||||
scope.launch(exceptionHandler) {
|
||||
scope.launchWithCatch {
|
||||
val request: WriteRequest = writeCharacteristic(rxCharacteristic, text.toByteArray(), BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT)
|
||||
if (!useLongWrite) {
|
||||
request.split()
|
||||
@@ -127,11 +140,7 @@ internal class UARTManager(
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBatteryLevelChanged(batteryLevel: Int) {
|
||||
dataHolder.emitNewBatteryLevel(batteryLevel)
|
||||
}
|
||||
|
||||
override fun getGattCallback(): BatteryManagerGattCallback {
|
||||
override fun getGattCallback(): BleManagerGattCallback {
|
||||
return UARTManagerGattCallback()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,37 +1,27 @@
|
||||
package no.nordicsemi.android.uart.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.service.ForegroundBleService
|
||||
import no.nordicsemi.android.uart.data.DisconnectCommand
|
||||
import no.nordicsemi.android.uart.data.SendTextCommand
|
||||
import no.nordicsemi.android.service.DEVICE_DATA
|
||||
import no.nordicsemi.android.service.NotificationService
|
||||
import no.nordicsemi.android.uart.data.UARTRepository
|
||||
import no.nordicsemi.android.utils.exhaustive
|
||||
import javax.inject.Inject
|
||||
|
||||
@AndroidEntryPoint
|
||||
internal class UARTService : ForegroundBleService() {
|
||||
internal class UARTService : NotificationService() {
|
||||
|
||||
@Inject
|
||||
lateinit var repository: UARTRepository
|
||||
|
||||
override val manager: UARTManager by lazy { UARTManager(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<BluetoothDevice>(DEVICE_DATA)!!
|
||||
|
||||
// status.onEach {
|
||||
// val status = it.mapToSimpleManagerStatus()
|
||||
// repository.setNewStatus(status)
|
||||
// stopIfDisconnected(status)
|
||||
// }.launchIn(scope)
|
||||
repository.start(device, lifecycleScope)
|
||||
|
||||
repository.command.onEach {
|
||||
when (it) {
|
||||
DisconnectCommand -> stopSelf()
|
||||
is SendTextCommand -> manager.send(it.command)
|
||||
}.exhaustive
|
||||
}.launchIn(scope)
|
||||
return START_REDELIVER_INTENT
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,19 +18,26 @@ import no.nordicsemi.android.theme.view.ScreenSection
|
||||
import no.nordicsemi.android.theme.view.SectionTitle
|
||||
import no.nordicsemi.android.uart.R
|
||||
import no.nordicsemi.android.uart.data.UARTData
|
||||
import no.nordicsemi.android.uart.data.UARTMacro
|
||||
|
||||
@Composable
|
||||
internal fun UARTContentView(state: UARTData, onEvent: (UARTViewEvent) -> Unit) {
|
||||
internal fun UARTContentView(state: UARTData, macros: List<UARTMacro>, onEvent: (UARTViewEvent) -> Unit) {
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
modifier = Modifier.padding(16.dp)
|
||||
) {
|
||||
InputSection(state, onEvent)
|
||||
InputSection(macros, onEvent)
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
if (state.text.isNotEmpty()) {
|
||||
OutputSection(state.text)
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
}
|
||||
|
||||
Button(
|
||||
onClick = { onEvent(OnDisconnectButtonClick) }
|
||||
onClick = { onEvent(DisconnectEvent) }
|
||||
) {
|
||||
Text(text = stringResource(id = R.string.disconnect))
|
||||
}
|
||||
@@ -38,7 +45,7 @@ internal fun UARTContentView(state: UARTData, onEvent: (UARTViewEvent) -> Unit)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun InputSection(state: UARTData, onEvent: (UARTViewEvent) -> Unit) {
|
||||
private fun InputSection(macros: List<UARTMacro>, onEvent: (UARTViewEvent) -> Unit) {
|
||||
val showSearchDialog = remember { mutableStateOf(false) }
|
||||
|
||||
if (showSearchDialog.value) {
|
||||
@@ -53,13 +60,13 @@ private fun InputSection(state: UARTData, onEvent: (UARTViewEvent) -> Unit) {
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
state.macros.forEach {
|
||||
macros.forEach {
|
||||
MacroItem(macro = it, onEvent = onEvent)
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
}
|
||||
|
||||
if (state.macros.isEmpty()) {
|
||||
if (macros.isEmpty()) {
|
||||
Text(
|
||||
text = stringResource(id = R.string.uart_no_macros_info),
|
||||
style = MaterialTheme.typography.bodyMedium
|
||||
@@ -78,7 +85,7 @@ private fun InputSection(state: UARTData, onEvent: (UARTViewEvent) -> Unit) {
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun OutputSection(state: UARTData, onEvent: (UARTViewEvent) -> Unit) {
|
||||
private fun OutputSection(text: String) {
|
||||
ScreenSection {
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
@@ -87,7 +94,7 @@ private fun OutputSection(state: UARTData, onEvent: (UARTViewEvent) -> Unit) {
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
|
||||
Text(text = text)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,9 +8,15 @@ import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
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.uart.R
|
||||
import no.nordicsemi.android.uart.viewmodel.UARTViewModel
|
||||
import no.nordicsemi.android.utils.exhaustive
|
||||
|
||||
@Composable
|
||||
fun UARTScreen() {
|
||||
@@ -18,15 +24,25 @@ fun UARTScreen() {
|
||||
val state = viewModel.state.collectAsState().value
|
||||
|
||||
Column {
|
||||
val navigateUp = { viewModel.onEvent(NavigateUp) }
|
||||
|
||||
BackIconAppBar(stringResource(id = R.string.uart_title)) {
|
||||
viewModel.onEvent(OnDisconnectButtonClick)
|
||||
viewModel.onEvent(DisconnectEvent)
|
||||
}
|
||||
|
||||
Column(modifier = Modifier.verticalScroll(rememberScrollState())) {
|
||||
// when (state) {
|
||||
// is DisplayDataState -> UARTContentView(state.data) { viewModel.onEvent(it) }
|
||||
// LoadingState -> DeviceConnectingView()
|
||||
// }.exhaustive
|
||||
when (state.uartManagerState) {
|
||||
NoDeviceState -> NoDeviceView()
|
||||
is WorkingState -> when (state.uartManagerState.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 -> UARTContentView(state.uartManagerState.result.data, state.macros) { viewModel.onEvent(it) }
|
||||
}
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
package no.nordicsemi.android.uart.view
|
||||
|
||||
import no.nordicsemi.android.service.BleManagerResult
|
||||
import no.nordicsemi.android.uart.data.UARTData
|
||||
import no.nordicsemi.android.uart.data.UARTMacro
|
||||
|
||||
internal sealed class UARTViewState
|
||||
internal data class UARTViewState(
|
||||
val macros: List<UARTMacro> = emptyList(),
|
||||
val uartManagerState: HTSManagerState = NoDeviceState
|
||||
)
|
||||
|
||||
internal object LoadingState : UARTViewState()
|
||||
internal sealed class HTSManagerState
|
||||
|
||||
internal data class DisplayDataState(val data: UARTData) : UARTViewState()
|
||||
internal data class WorkingState(val result: BleManagerResult<UARTData>) : HTSManagerState()
|
||||
|
||||
internal object NoDeviceState : HTSManagerState()
|
||||
|
||||
@@ -9,4 +9,6 @@ internal data class OnDeleteMacro(val macro: UARTMacro) : UARTViewEvent()
|
||||
|
||||
internal data class OnRunMacro(val macro: UARTMacro) : UARTViewEvent()
|
||||
|
||||
internal object OnDisconnectButtonClick : UARTViewEvent()
|
||||
internal object DisconnectEvent : UARTViewEvent()
|
||||
|
||||
internal object NavigateUp : UARTViewEvent()
|
||||
|
||||
@@ -3,14 +3,13 @@ package no.nordicsemi.android.uart.viewmodel
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import no.nordicsemi.android.navigation.*
|
||||
import no.nordicsemi.android.service.BleManagerStatus
|
||||
import no.nordicsemi.android.service.ServiceManager
|
||||
import no.nordicsemi.android.uart.data.DisconnectCommand
|
||||
import no.nordicsemi.android.uart.data.SendTextCommand
|
||||
import no.nordicsemi.android.uart.data.UARTMacro
|
||||
import no.nordicsemi.android.uart.data.UARTRepository
|
||||
import no.nordicsemi.android.uart.repository.UARTService
|
||||
import no.nordicsemi.android.uart.repository.UART_SERVICE_UUID
|
||||
import no.nordicsemi.android.uart.view.*
|
||||
import no.nordicsemi.android.utils.exhaustive
|
||||
@@ -21,19 +20,23 @@ import javax.inject.Inject
|
||||
@HiltViewModel
|
||||
internal class UARTViewModel @Inject constructor(
|
||||
private val repository: UARTRepository,
|
||||
private val serviceManager: ServiceManager,
|
||||
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(UARTViewState())
|
||||
val state = _state.asStateFlow()
|
||||
|
||||
init {
|
||||
if (!repository.isRunning.value) {
|
||||
requestBluetoothDevice()
|
||||
}
|
||||
|
||||
repository.data.onEach {
|
||||
_state.value = _state.value.copy(uartManagerState = WorkingState(it))
|
||||
}.launchIn(viewModelScope)
|
||||
}
|
||||
|
||||
private fun requestBluetoothDevice() {
|
||||
navigationManager.navigateTo(ScannerDestinationId, UUIDArgument(UART_SERVICE_UUID))
|
||||
|
||||
navigationManager.recentResult.onEach {
|
||||
@@ -41,32 +44,38 @@ internal class UARTViewModel @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(UARTService::class.java, args.getDevice())
|
||||
is SuccessDestinationResult -> repository.launch(args.getDevice().device)
|
||||
}.exhaustive
|
||||
}
|
||||
|
||||
fun onEvent(event: UARTViewEvent) {
|
||||
when (event) {
|
||||
is OnCreateMacro -> repository.addNewMacro(event.macro)
|
||||
is OnDeleteMacro -> repository.deleteMacro(event.macro)
|
||||
OnDisconnectButtonClick -> repository.sendNewCommand(DisconnectCommand)
|
||||
is OnRunMacro -> repository.sendNewCommand(SendTextCommand(event.macro.command))
|
||||
is OnCreateMacro -> addNewMacro(event.macro)
|
||||
is OnDeleteMacro -> deleteMacro(event.macro)
|
||||
DisconnectEvent -> disconnect()
|
||||
is OnRunMacro -> repository.runMacro(event.macro)
|
||||
NavigateUp -> navigationManager.navigateUp()
|
||||
}.exhaustive
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
super.onCleared()
|
||||
repository.clear()
|
||||
private fun addNewMacro(macro: UARTMacro) {
|
||||
_state.tryEmit(_state.value.copy(macros = _state.value.macros + macro))
|
||||
}
|
||||
|
||||
private fun deleteMacro(macro: UARTMacro) {
|
||||
val macros = _state.value.macros.toMutableList().apply {
|
||||
remove(macro)
|
||||
}
|
||||
_state.tryEmit(_state.value.copy(macros = macros))
|
||||
}
|
||||
|
||||
private fun disconnect() {
|
||||
repository.release()
|
||||
navigationManager.navigateUp()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user