1- package dev.bpavuk.touche.input
1+ package dev.bpavuk.touche.connectivity
22
33import android.util.Log
44import androidx.lifecycle.ViewModel
55import androidx.lifecycle.viewModelScope
6- import dev.bpavuk.touche.input.types.ToucheInput
7- import dev.bpavuk.touche.input.types.ToucheScreenSize
8- import dev.bpavuk.touche.usb.UsbConnection
9- import kotlinx.coroutines.Dispatchers
6+ import dev.bpavuk.touche.connectivity.usb.UsbConnection
7+ import dev.bpavuk.touche.types.Opcode
8+ import dev.bpavuk.touche.types.ToucheInput
9+ import dev.bpavuk.touche.types.ToucheScreenSize
10+ import kotlinx.coroutines.currentCoroutineContext
1011import kotlinx.coroutines.flow.MutableStateFlow
1112import kotlinx.coroutines.flow.combine
1213import kotlinx.coroutines.flow.flow
13- import kotlinx.coroutines.flow.flowOn
14+ import kotlinx.coroutines.isActive
1415import kotlinx.coroutines.launch
16+ import java.io.IOException
1517
1618class WatcherViewModel (private val connection : UsbConnection ) : ViewModel() {
1719 private val stateFlow = MutableStateFlow (WatcherState .initial)
1820 private val opcodeFlow = flow {
19- while (true ) emit(Opcode (connection.read()))
20- }.flowOn(Dispatchers .IO )
21+ try {
22+ while (currentCoroutineContext().isActive) {
23+ emit(Opcode (connection.read()))
24+ }
25+ } catch (e: IOException ) {
26+ Log .d(" Watcher" , " I/O exception. Details:\n $e " )
27+ }
28+ }
2129
2230 private val dataFlow = combine(opcodeFlow, stateFlow) { it1, it2 -> it1 to it2 }
2331
2432 fun watch () {
2533 viewModelScope.launch {
2634 dataFlow.collect { (opcode, state) ->
27- Log .d(" Watcher" , " data flow collected" )
28- if (opcode.consumed || state.consumed || state == WatcherState .initial) {
35+ if (state.consumed || state == WatcherState .initial) {
2936 return @collect
3037 }
3138
3239 val encodedState = state.encode(opcode) ? : return @collect
3340 connection.write(encodedState)
34- opcode.consume()
3541 }
3642 }
3743 }
@@ -70,7 +76,7 @@ private data class WatcherState(
7076 }
7177
7278 2 -> {
73- screen.encode()
79+ screen.encode().encodeToByteArray()
7480 }
7581
7682 else -> throw InvalidOpcodeException (opcode)
@@ -80,17 +86,14 @@ private data class WatcherState(
8086 fun consume () {
8187 consumed = true
8288 }
83- }
8489
85- private fun List<ToucheInput>.encode (): ByteArray? =
86- map { it.encode() }.reduceOrNull { acc, toucheInput ->
87- acc + " \n " .encodeToByteArray() + toucheInput
90+ private fun List<ToucheInput>.encode (): ByteArray? {
91+ val data1 = map {
92+ it.encode()
93+ }
94+ if (data1.isEmpty()) return null
95+ val data = data1.joinToString(" \n " )
96+ return data.encodeToByteArray()
8897 }
98+ }
8999
90- data class Opcode (
91- val value : Int , var consumed : Boolean = false
92- ) {
93- fun consume () {
94- consumed = true
95- }
96- }
0 commit comments