247 lines
12 KiB
Kotlin
247 lines
12 KiB
Kotlin
package com.helible.pilot
|
|
|
|
import android.os.Bundle
|
|
import android.util.Log
|
|
import android.widget.Toast
|
|
import androidx.activity.ComponentActivity
|
|
import androidx.activity.compose.BackHandler
|
|
import androidx.activity.compose.setContent
|
|
import androidx.compose.material3.MaterialTheme
|
|
import androidx.compose.material3.Surface
|
|
import androidx.compose.runtime.LaunchedEffect
|
|
import androidx.compose.runtime.collectAsState
|
|
import androidx.compose.runtime.getValue
|
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
|
import androidx.navigation.compose.NavHost
|
|
import androidx.navigation.compose.composable
|
|
import androidx.navigation.compose.rememberNavController
|
|
import com.helible.pilot.components.CalibrationPage
|
|
import com.helible.pilot.components.NotImplementedPage
|
|
import com.helible.pilot.components.RotorsTestPage
|
|
import com.helible.pilot.components.console.ConsolePage
|
|
import com.helible.pilot.components.deviceScreen.DeviceControlScreen
|
|
import com.helible.pilot.components.deviceScreen.defaultDeviceActionsList
|
|
import com.helible.pilot.components.PidSettingsPage
|
|
import com.helible.pilot.components.scannerScreen.ScannerScreen
|
|
import com.helible.pilot.permissions.PermissionsLauncher
|
|
import com.helible.pilot.permissions.PermissionsRequest
|
|
import com.helible.pilot.permissions.RequestHardwareFeatures
|
|
import com.helible.pilot.ui.theme.TestblueTheme
|
|
import com.helible.pilot.viewmodels.AppPreferences
|
|
import com.helible.pilot.viewmodels.BluetoothViewModel
|
|
import com.helible.pilot.viewmodels.BluetoothViewModelFactory
|
|
import com.helible.pilot.viewmodels.PermissionDialogViewModel
|
|
import com.helible.pilot.viewmodels.PreferencesViewModel
|
|
import com.helible.pilot.viewmodels.SavedPreferencesImpl
|
|
|
|
|
|
class MainActivity : ComponentActivity() {
|
|
// TODO: move text strings to resources
|
|
|
|
private val preferences by lazy {
|
|
SavedPreferencesImpl(getSharedPreferences(packageName, MODE_PRIVATE))
|
|
}
|
|
private val preferencesViewModel by lazy {
|
|
PreferencesViewModel(preferences)
|
|
}
|
|
|
|
@ExperimentalStdlibApi
|
|
override fun onCreate(savedInstanceState: Bundle?) {
|
|
super.onCreate(savedInstanceState)
|
|
setContent {
|
|
val bluetoothViewModel =
|
|
viewModel<BluetoothViewModel>(factory = BluetoothViewModelFactory(applicationContext))
|
|
|
|
val permissionsViewModel = viewModel<PermissionDialogViewModel>()
|
|
val permissionLauncher = PermissionsLauncher()
|
|
permissionLauncher.setup(
|
|
onPermissionResult = { perm, isGranted ->
|
|
permissionsViewModel.onPermissionResult(perm, isGranted)
|
|
},
|
|
onGranted = { bluetoothViewModel.startScan() }
|
|
)
|
|
|
|
val bluetoothState by bluetoothViewModel.state.collectAsState()
|
|
val selectedDevice by bluetoothViewModel.selectedDevice.collectAsState()
|
|
val rotorsDuty by bluetoothViewModel.rotorsDuty.collectAsState()
|
|
|
|
LaunchedEffect(key1 = null) {
|
|
permissionLauncher.launch()
|
|
}
|
|
|
|
val navController = rememberNavController()
|
|
|
|
LaunchedEffect(key1 = bluetoothState.errorMessage) {
|
|
bluetoothState.errorMessage?.let { message ->
|
|
Toast.makeText(applicationContext, "Ошибка: $message", Toast.LENGTH_LONG).show()
|
|
}
|
|
}
|
|
|
|
TestblueTheme {
|
|
Surface(color = MaterialTheme.colorScheme.background) {
|
|
PermissionsRequest(
|
|
dismissCurrentDialog = { permissionsViewModel.dismissDialog() },
|
|
visiblePermissionDialogQueue = permissionsViewModel.visiblePermissionDialogQueue,
|
|
activity = this,
|
|
permissionLaunch = { perms -> permissionLauncher.launch(perms) }
|
|
)
|
|
|
|
RequestHardwareFeatures(
|
|
activity = this,
|
|
bluetoothUiState = bluetoothState
|
|
)
|
|
|
|
NavHost(
|
|
navController = navController,
|
|
startDestination = "device"
|
|
) {
|
|
composable("scanner") {
|
|
ScannerScreen(
|
|
bluetoothState = bluetoothState,
|
|
selectedDevice = selectedDevice,
|
|
startScan = { bluetoothViewModel.startScan() },
|
|
cancelScan = { bluetoothViewModel.cancelScan() },
|
|
choiceDevice = { device -> bluetoothViewModel.selectDevice(device) },
|
|
onScreenChanged = {
|
|
bluetoothViewModel.cancelScan()
|
|
val device = selectedDevice
|
|
if (device == null) {
|
|
preferencesViewModel.clearPreferences()
|
|
} else {
|
|
preferencesViewModel.savePreferences(
|
|
AppPreferences(
|
|
deviceName = device.name,
|
|
deviceAddress = device.macAddress
|
|
)
|
|
)
|
|
}
|
|
navController.navigate("device")
|
|
Log.i(
|
|
"ScanActivity",
|
|
"Preferences: ${preferencesViewModel.preferences}"
|
|
)
|
|
}
|
|
)
|
|
}
|
|
composable("device")
|
|
{
|
|
DeviceControlScreen(
|
|
bluetoothUiState = bluetoothState,
|
|
getPreferences = { preferencesViewModel.preferences },
|
|
navigateToPage = { page -> navController.navigate(page) },
|
|
connectToDevice = { device ->
|
|
bluetoothViewModel.connectToDevice(
|
|
device
|
|
)
|
|
},
|
|
disconnectFromDevice = {
|
|
preferencesViewModel.clearPreferences()
|
|
bluetoothViewModel.disconnectFromDevice()
|
|
},
|
|
deviceActionsList = defaultDeviceActionsList()
|
|
)
|
|
if (preferencesViewModel.preferences != null) BackHandler {}
|
|
}
|
|
composable("console/{title}")
|
|
{ _ ->
|
|
ConsolePage(
|
|
startTakeoff = { bluetoothViewModel.startTakeoff() },
|
|
startOnboarding = { bluetoothViewModel.startOnboarding() },
|
|
stop = { bluetoothViewModel.stopRotors() },
|
|
changeStick1Position = {
|
|
_: Int, heightVelocity: Int ->
|
|
bluetoothViewModel.changeHeightStickPosition(heightVelocity)
|
|
},
|
|
changeStick2Position = {
|
|
x: Int, y: Int ->
|
|
bluetoothViewModel.changePitchStickPosition(y)
|
|
bluetoothViewModel.changeYawStickPosition(x)
|
|
},
|
|
bluetoothUiState = bluetoothState,
|
|
reconnect = {
|
|
val preferences = preferences.getPreferences()
|
|
if(preferences != null) {
|
|
bluetoothViewModel.connectToDevice(
|
|
preferences.deviceAddress
|
|
)
|
|
} else {
|
|
navController.navigate("scanner")
|
|
}
|
|
},
|
|
navigateBack = {
|
|
navController.popBackStack()
|
|
}
|
|
)
|
|
BackHandler {
|
|
navController.popBackStack()
|
|
}
|
|
}
|
|
composable("codeblocks/{title}")
|
|
{ backStackEntry ->
|
|
NotImplementedPage(
|
|
title = backStackEntry.arguments?.getString("title") ?: "null",
|
|
navigateBack = { navController.popBackStack() }
|
|
)
|
|
}
|
|
composable("imu_calibration/{title}")
|
|
{ backStackEntry ->
|
|
CalibrationPage(
|
|
deviceStatus = bluetoothState.deviceState?.status,
|
|
startCalibration = { bluetoothViewModel.startImuCalibration() },
|
|
title = backStackEntry.arguments?.getString("title") ?: "null",
|
|
navigateBack = { navController.popBackStack() }
|
|
)
|
|
}
|
|
composable("motor_test/{title}")
|
|
{ backStackEntry ->
|
|
RotorsTestPage(
|
|
title = backStackEntry.arguments?.getString("title") ?: "null",
|
|
rotorsDuty = rotorsDuty,
|
|
setRotorsDuty = { bluetoothViewModel.setRotorsDuty(it) },
|
|
startTelemetrySending = { bluetoothViewModel.startRotorsConfigurationTelemetry() },
|
|
stopRotors = { bluetoothViewModel.stopRotors() },
|
|
navigateBack = {
|
|
navController.popBackStack()
|
|
bluetoothViewModel.stopRotorsConfigurationTelemetry()
|
|
bluetoothViewModel.stopRotors()
|
|
}
|
|
)
|
|
BackHandler {
|
|
navController.popBackStack()
|
|
bluetoothViewModel.stopRotorsConfigurationTelemetry()
|
|
bluetoothViewModel.stopRotors()
|
|
}
|
|
}
|
|
composable("pid_settings/{title}")
|
|
{ backStackEntry ->
|
|
PidSettingsPage(
|
|
title = backStackEntry.arguments?.getString("title") ?: "null",
|
|
navigateBack = {
|
|
navController.popBackStack()
|
|
bluetoothViewModel.clearPidSettings()
|
|
},
|
|
requestPidSettings = { bluetoothViewModel.requestPidSettings() },
|
|
setPidSettings = {settings -> bluetoothViewModel.applyPidSettings(settings)},
|
|
deviceState = bluetoothState.deviceState
|
|
)
|
|
BackHandler {
|
|
navController.popBackStack()
|
|
bluetoothViewModel.clearPidSettings()
|
|
}
|
|
}
|
|
composable("reports/{title}")
|
|
{ backStackEntry ->
|
|
NotImplementedPage(
|
|
title = backStackEntry.arguments?.getString("title") ?: "null",
|
|
navigateBack = { navController.popBackStack() }
|
|
)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|