Better UI layout on the device screen

This commit is contained in:
2024-01-27 23:14:26 +07:00
parent 18bd21fba1
commit 3b62743481
6 changed files with 67 additions and 58 deletions

View File

@@ -6,8 +6,10 @@ import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.BackHandler
import androidx.activity.compose.setContent
import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
@@ -139,7 +141,10 @@ class MainActivity : ComponentActivity() {
device
)
},
disconnectFromDevice = { bluetoothViewModel.disconnectFromDevice() },
disconnectFromDevice = {
preferencesViewModel.clearPreferences()
bluetoothViewModel.disconnectFromDevice()
},
deviceActionsList = defaultDeviceActionsList()
)
if (preferencesViewModel.preferences != null) BackHandler {}
@@ -150,6 +155,9 @@ class MainActivity : ComponentActivity() {
title = backStackEntry.arguments?.getString("title") ?: "null",
navigateBack = { navController.popBackStack() }
)
Button(onClick = { bluetoothViewModel.sendHelloWorld() }) {
Text("Click me!")
}
}
composable("codeblocks/{title}")
{ backStackEntry ->

View File

@@ -1,7 +1,10 @@
package com.helible.pilot.components.deviceScreen
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material3.Icon
@@ -11,6 +14,7 @@ import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
@@ -33,7 +37,7 @@ fun DeviceControlScreen(
scannerPageName: String = "scanner",
) {
LaunchedEffect(Unit) {
val preferences: AppPreferences? = getPreferences()
val preferences = getPreferences()
if (preferences == null) {
navigateToPage(scannerPageName)
} else {
@@ -85,19 +89,24 @@ fun DeviceControlScreen(
)
for (action in section.value) {
TextButton(
onClick = { navigateToPage(action.first + '/' + action.second.second) }
onClick = { navigateToPage(action.first + '/' + action.second.second) },
modifier = Modifier.fillMaxWidth()
) {
Icon(
painter = painterResource(id = action.second.first.first),
tint = action.second.first.second,
contentDescription = null,
modifier = Modifier.size(25.dp)
)
Text(
text = action.second.second,
color = MaterialTheme.colorScheme.inverseSurface,
modifier = Modifier.padding(horizontal = 5.dp)
)
Row(modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(5.dp),
verticalAlignment = Alignment.CenterVertically
) {
Icon(
painter = painterResource(id = action.second.first.first),
tint = action.second.first.second,
contentDescription = null,
modifier = Modifier.size(25.dp)
)
Text(
text = action.second.second,
color = MaterialTheme.colorScheme.inverseSurface
)
}
}
}
}

View File

@@ -14,7 +14,7 @@ import android.os.Build
import android.util.Log
import android.widget.Toast
import androidx.activity.ComponentActivity
import com.helible.pilot.BluetoothDataTransferService
import com.helible.pilot.viewmodels.BluetoothDataTransferService
import com.helible.pilot.KMessage
import com.helible.pilot.dataclasses.BluetoothDeviceDomain
import com.helible.pilot.receivers.BluetoothAdapterStateReceiver
@@ -40,7 +40,7 @@ import java.util.UUID
sealed interface ConnectionResult {
object ConnectionEstablished : ConnectionResult
data class TransferSucceded(val message: KMessage) : ConnectionResult
data class TransferSucceded(val message: String) : ConnectionResult
data class Error(val message: String) : ConnectionResult
}
@@ -219,6 +219,7 @@ class AndroidBluetoothController(private val context: Context) : BluetoothContro
return flow {}
}
return flow {
Log.i("BluetoothController", "Connecting to device...")
currentClientSocket =
bluetoothAdapter.getRemoteDevice(device).createRfcommSocketToServiceRecord(
UUID.fromString(SERVICE_UUID)
@@ -235,7 +236,9 @@ class AndroidBluetoothController(private val context: Context) : BluetoothContro
)
}
} catch (e: IOException) {
closeConnection()
socket.close()
currentClientSocket = null
Log.e("BluetoothController", e.toString())
emit(ConnectionResult.Error("Connection was interrupted"))
}
}
@@ -256,6 +259,7 @@ class AndroidBluetoothController(private val context: Context) : BluetoothContro
override fun closeConnection() {
currentClientSocket?.close()
currentClientSocket = null
Log.i("BluetoothController", "Connection closed")
}
override fun onDestroy() {

View File

@@ -0,0 +1,9 @@
package com.helible.pilot.controllers
data class DeviceState(
val isHandshakeWaiting: Boolean = true,
val isIMUCalibrating: Boolean = false,
val flightMode: Boolean = false,
val batteryCharge: Int?,
val flightHeight: Float?
)

View File

@@ -1,6 +1,9 @@
package com.helible.pilot
package com.helible.pilot.viewmodels
import android.bluetooth.BluetoothSocket
import android.util.Log
import com.helible.pilot.KMessage
import com.helible.pilot.toKMessage
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
@@ -14,7 +17,7 @@ class TransferFailedException : IOException("Reading incoming data failed")
class BluetoothDataTransferService(
private val socket: BluetoothSocket,
) {
fun listenForIncomingMessages(): Flow<KMessage> {
fun listenForIncomingMessages(): Flow<String> {
return flow {
if (!socket.isConnected)
return@flow
@@ -25,11 +28,11 @@ class BluetoothDataTransferService(
} catch (e: IOException) {
throw TransferFailedException()
}
val strData: String = buffer.decodeToString(endIndex = byteCount)
emit(
buffer.decodeToString(
endIndex = byteCount
).toKMessage()
strData
)
Log.i("BluetoothController", "Received: ${strData.dropLast(2)}")
}
}.flowOn(Dispatchers.IO)
}

View File

@@ -94,7 +94,9 @@ class BluetoothViewModel(
}
is ConnectionResult.TransferSucceded -> {
TODO("Telemetry not implemented")
_state.update { it.copy(
) }
}
is ConnectionResult.Error -> {
@@ -108,14 +110,12 @@ class BluetoothViewModel(
}
}
}
.catch { _ ->
.catch { throwable ->
bluetoothController.closeConnection()
_state.update {
it.copy(
isConnected = false,
isConnecting = false
)
}
_state.update { it.copy(
isConnected = false,
isConnecting = false
) }
}
.launchIn(viewModelScope)
}
@@ -123,7 +123,7 @@ class BluetoothViewModel(
private var deviceConnectionJob: Job? = null
fun connectToDevice(device: String) {
if (_state.value.isConnected) {
if (_state.value.isConnected and _state.value.isConnecting) {
return
}
_state.update { it.copy(isConnecting = true) }
@@ -162,36 +162,12 @@ class BluetoothViewModel(
super.onCleared()
}
fun sendRotorsDutySpeed(rotorsState: RotorsSpeedMessage) {
fun sendHelloWorld() {
viewModelScope.launch {
bluetoothController.trySendMessage(
rotorsStateMessegeAdapter.toJson(rotorsState).plus("\r").toByteArray()
"{\"p1\": {\"p\": 1.5, \"i\": 1.5, \"d\": 1.5}}\n\r".toByteArray()
//"{\"p1\": [1.5, 1.5, 1.5]}\n\r".toByteArray()
)
}
}
fun sendAlarmState(alarmStateMessage: AlarmStateMessage) {
viewModelScope.launch {
bluetoothController.trySendMessage(
alarmStateMessageAdapter.toJson(alarmStateMessage).plus("\r").toByteArray()
)
}
}
fun sendEmergStop() {
viewModelScope.launch {
bluetoothController.trySendMessage(
emergStopMessageAdapter.toJson(EmergStopMessage(true)).plus("\r").toByteArray()
)
}
}
fun sendR3Duty(r3: Int) {
viewModelScope.launch {
bluetoothController.trySendMessage(
"R3$r3\n\r".toByteArray()
)
delay(30)
}
}
}