view model and object

This commit is contained in:
lash404 committed 2026-10-30 15:00:46 +01:00
1 parent b1d89fbd08
commit 025f754504
16 files changed
+2609 -89

No files matched your search

+3
View File
@@ -0,0 +1,3 @@
# Default ignored files
/shelf/
/workspace.xml
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AndroidProjectSystem">
<option name="providerId" value="com.android.tools.idea.GradleProjectSystem" />
</component>
</project>
File diff suppressed because it is too large. Load diff
+12
View File
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="testRunner" value="CHOOSE_PER_TEST" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleJvm" value="#GRADLE_LOCAL_JAVA_HOME" />
</GradleProjectSettings>
</option>
</component>
</project>
+10
View File
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectMigrations">
<option name="MigrateToGradleLocalJavaHome">
<set>
<option value="$PROJECT_DIR$" />
</set>
</option>
</component>
</project>
+10
View File
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>
+17
View File
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="com.intellij.execution.junit.AbstractAllInDirectoryConfigurationProducer" />
<option value="com.intellij.execution.junit.AllInPackageConfigurationProducer" />
<option value="com.intellij.execution.junit.PatternConfigurationProducer" />
<option value="com.intellij.execution.junit.TestInClassConfigurationProducer" />
<option value="com.intellij.execution.junit.UniqueIdConfigurationProducer" />
<option value="com.intellij.execution.junit.testDiscovery.JUnitTestDiscoveryConfigurationProducer" />
<option value="org.jetbrains.kotlin.idea.junit.KotlinJUnitRunConfigurationProducer" />
<option value="org.jetbrains.kotlin.idea.junit.KotlinPatternConfigurationProducer" />
</set>
</option>
</component>
</project>
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
</component>
</project>
+1
View File
@@ -54,5 +54,6 @@ dependencies {
debugImplementation(libs.androidx.compose.ui.test.manifest) debugImplementation(libs.androidx.compose.ui.test.manifest)
debugImplementation(libs.androidx.compose.ui.tooling) debugImplementation(libs.androidx.compose.ui.tooling)
implementation("androidx.activity:activity-ktx:1.13.0")
implementation("androidx.navigation:navigation-compose:2.10.2") implementation("androidx.navigation:navigation-compose:2.10.2")
} }
+1 -2
View File
@@ -3,7 +3,7 @@
xmlns:tools="http://schemas.android.com/tools"> xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" /> <uses-permission android:name="android.permission.BLUETOOTH_SCAN"/>
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /> <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:maxSdkVersion="30" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE"/> <uses-permission android:name="android.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE"/>
@@ -19,7 +19,6 @@
android:theme="@style/Theme.SmartWatchAndroid"> android:theme="@style/Theme.SmartWatchAndroid">
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
android:screenOrientation="portrait"
android:exported="true" android:exported="true"
android:theme="@style/Theme.SmartWatchAndroid" android:theme="@style/Theme.SmartWatchAndroid"
android:windowSoftInputMode="adjustResize"> android:windowSoftInputMode="adjustResize">
@@ -9,16 +9,22 @@ import android.bluetooth.BluetoothGattCharacteristic
import android.bluetooth.BluetoothManager import android.bluetooth.BluetoothManager
import android.bluetooth.BluetoothProfile import android.bluetooth.BluetoothProfile
import android.content.Context import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.os.Build import android.os.Build
import android.util.Log import android.util.Log
import android.widget.Toast
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
import androidx.annotation.RequiresPermission import androidx.annotation.RequiresPermission
import androidx.compose.runtime.mutableStateOf import androidx.compose.ui.platform.LocalContext
import androidx.core.app.ActivityCompat import androidx.core.app.ActivityCompat
import com.example.smart_watch_android.MainViewModel
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.time.LocalDate import java.time.LocalDate
import java.time.LocalTime import java.time.LocalTime
@@ -26,18 +32,15 @@ import java.time.format.DateTimeFormatter
import java.util.UUID import java.util.UUID
import kotlin.time.Duration.Companion.milliseconds import kotlin.time.Duration.Companion.milliseconds
class BleManager(private val context: Context) { object BLEManager{
//var deviceAddress = "10:BD:A3:8F:01:0E"
var devices = mutableListOf<Devices>() var devices = mutableListOf<Devices>()
var isConnected = mutableStateOf(false) private val _isConnected = MutableStateFlow(false)
val isConnected: StateFlow<Boolean> = _isConnected.asStateFlow()
val currentDate: LocalDate? = LocalDate.now() val currentDate: LocalDate? = LocalDate.now()
private val deviceUUIDs = DeviceUUIDs private val deviceUUIDs = DeviceUUIDs
private var bluetoothGatt: BluetoothGatt? = null private var bluetoothGatt: BluetoothGatt? = null
private var bluetoothManager: BluetoothManager? = null private lateinit var bluetoothManager: BluetoothManager
private var bluetoothAdapter: BluetoothAdapter? = null private lateinit var bluetoothAdapter: BluetoothAdapter
var deviceAddress: String = ""
val gattCallback = object : BluetoothGattCallback() { val gattCallback = object : BluetoothGattCallback() {
@RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT) @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) { override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) {
@@ -46,7 +49,7 @@ class BleManager(private val context: Context) {
Log.d("ESP32_BLE", "Connected! Start discoverServices()...") Log.d("ESP32_BLE", "Connected! Start discoverServices()...")
gatt.discoverServices() gatt.discoverServices()
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) { } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
isConnected.value = false updateConnectionStatus(false)
gatt.close() gatt.close()
bluetoothGatt = null bluetoothGatt = null
@@ -54,14 +57,14 @@ class BleManager(private val context: Context) {
} }
} else { } else {
Log.d("ESP32_BLE", "error in onConnectionStateChange! Status-Code: $status") Log.d("ESP32_BLE", "error in onConnectionStateChange! Status-Code: $status")
isConnected.value = false updateConnectionStatus(false)
} }
} }
override fun onServicesDiscovered(gatt: BluetoothGatt, status: Int) { override fun onServicesDiscovered(gatt: BluetoothGatt, status: Int) {
if (status == BluetoothGatt.GATT_SUCCESS) { if (status == BluetoothGatt.GATT_SUCCESS) {
Log.d("ESP32_BLE", "connected successfully.") Log.d("ESP32_BLE", "connected successfully.")
isConnected.value = true updateConnectionStatus(true)
} }
} }
} }
@@ -69,28 +72,31 @@ class BleManager(private val context: Context) {
val deviceName: String, val deviceName: String,
val deviceMac: String val deviceMac: String
) )
@RequiresApi(Build.VERSION_CODES.S) @RequiresApi(Build.VERSION_CODES.S)
@RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT) @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
fun init() { fun init(context: Context, activity: Activity) {
checkAndRequestBluetoothPermissions() checkAndRequestBluetoothPermissions(
activity = activity
)
bluetoothManager = context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager bluetoothManager = context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
bluetoothAdapter = bluetoothManager?.adapter bluetoothAdapter = bluetoothManager.adapter
devices = getDeviceList() as MutableList<Devices> devices = getDeviceList() as MutableList<Devices>
} }
fun updateConnectionStatus(status: Boolean) {
_isConnected.value = status
}
@RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT) @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
fun getDeviceList(): List<Devices>{ fun getDeviceList(): List<Devices>{
bluetoothAdapter?.bondedDevices?.forEach { device -> devices.clear()
bluetoothAdapter.bondedDevices?.forEach { device ->
devices.add(Devices(deviceName = device.name, deviceMac = device.address)) devices.add(Devices(deviceName = device.name, deviceMac = device.address))
} }
Log.d("devices","$devices") Log.d("devices","$devices")
return devices return devices
} }
@RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT) @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
@RequiresApi(Build.VERSION_CODES.S) @RequiresApi(Build.VERSION_CODES.S)
fun checkAndRequestBluetoothPermissions() { fun checkAndRequestBluetoothPermissions(activity: Activity) {
val permissions = arrayOf( val permissions = arrayOf(
Manifest.permission.BLUETOOTH_CONNECT, Manifest.permission.BLUETOOTH_CONNECT,
Manifest.permission.BLUETOOTH_SCAN, Manifest.permission.BLUETOOTH_SCAN,
@@ -98,27 +104,20 @@ class BleManager(private val context: Context) {
) )
val missingPermissions = permissions.filter { val missingPermissions = permissions.filter {
ActivityCompat.checkSelfPermission(context, it) != PackageManager.PERMISSION_GRANTED ActivityCompat.checkSelfPermission(activity, it) != PackageManager.PERMISSION_GRANTED
} }
if (missingPermissions.isNotEmpty()) { if (missingPermissions.isNotEmpty()) {
val activity = context as? Activity // Berechtigungen anfordern
if (activity != null) { ActivityCompat.requestPermissions(activity, missingPermissions.toTypedArray(), 101)
ActivityCompat.requestPermissions(activity, missingPermissions.toTypedArray(), 101) } else {
} else { Log.d("ESP32_BLE", "Alle Bluetooth-Berechtigungen sind bereits erteilt!")
Log.d("ESP32_BLE", "Cannot request permissions: Context is not an Activity!")
}
} }
} }
fun connectToEsp32(context: Context, deviceAddress: String) {
fun connectToEsp32() {
Log.d("ESP32_BLE", "connectToEsp32 started with address: $deviceAddress") Log.d("ESP32_BLE", "connectToEsp32 started with address: $deviceAddress")
if (bluetoothAdapter == null) {
Log.d("ESP32_BLE", "error: Bluetooth is not supported!")
return
}
try { try {
val device = bluetoothAdapter!!.getRemoteDevice(deviceAddress) val device = bluetoothAdapter.getRemoteDevice(deviceAddress)
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_GRANTED) { if (ActivityCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_GRANTED) {
bluetoothGatt = device.connectGatt(context, false, gattCallback) bluetoothGatt = device.connectGatt(context, false, gattCallback)
@@ -131,7 +130,7 @@ class BleManager(private val context: Context) {
} }
} }
@RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT) @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
fun disconnectEsp32() { fun disconnectEsp32(context: Context) {
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_GRANTED) { if (ActivityCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_GRANTED) {
bluetoothGatt?.disconnect() bluetoothGatt?.disconnect()
Log.d("ESP32_BLE","disconnectEsp32") Log.d("ESP32_BLE","disconnectEsp32")
@@ -140,8 +139,7 @@ class BleManager(private val context: Context) {
Log.d("BLE_DEBUG", "Permission BLUETOOTH_CONNECT error!") Log.d("BLE_DEBUG", "Permission BLUETOOTH_CONNECT error!")
} }
} }
fun writeToEsp32(context: Context, dataString: String, SERVICE_UUID: UUID?, CHARACTERISTIC_UUID: UUID?) {
fun writeToEsp32(dataString: String, SERVICE_UUID: UUID?, CHARACTERISTIC_UUID: UUID?) {
val gatt = bluetoothGatt val gatt = bluetoothGatt
if (gatt == null) { if (gatt == null) {
Log.d("ESP32_BLE", "error: no GATT-Objekt existing (not connected).") Log.d("ESP32_BLE", "error: no GATT-Objekt existing (not connected).")
@@ -170,7 +168,7 @@ class BleManager(private val context: Context) {
Log.d("ESP32_BLE", "started writing: $success") Log.d("ESP32_BLE", "started writing: $success")
} }
} }
fun syncTime() { fun syncTime(context: Context) {
val currentTime = LocalTime.now() val currentTime = LocalTime.now()
val formatterTime = DateTimeFormatter.ofPattern("HH mm ss") val formatterTime = DateTimeFormatter.ofPattern("HH mm ss")
val formattedTime = currentTime.format(formatterTime) val formattedTime = currentTime.format(formatterTime)
@@ -181,11 +179,19 @@ class BleManager(private val context: Context) {
Log.d("Time/Date","$formattedDate $formattedTime") Log.d("Time/Date","$formattedDate $formattedTime")
CoroutineScope(Dispatchers.IO).launch { CoroutineScope(Dispatchers.IO).launch {
writeToEsp32(formattedTime, deviceUUIDs.SERVICE_UUID, deviceUUIDs.CHAR_TIME_UUID) writeToEsp32(
context = context,
dataString = formattedTime,
SERVICE_UUID = deviceUUIDs.SERVICE_UUID,
CHARACTERISTIC_UUID = deviceUUIDs.CHAR_TIME_UUID)
delay(150.milliseconds) delay(150.milliseconds)
writeToEsp32("$formattedDate", deviceUUIDs.SERVICE_UUID, deviceUUIDs.CHAR_DATE_UUID) writeToEsp32(
context = context,
dataString ="$formattedDate",
SERVICE_UUID = deviceUUIDs.SERVICE_UUID,
CHARACTERISTIC_UUID = deviceUUIDs.CHAR_DATE_UUID)
} }
} }
} }
@@ -1,7 +1,6 @@
package com.example.smart_watch_android package com.example.smart_watch_android
import android.Manifest import android.Manifest
import android.content.Intent
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
@@ -13,20 +12,17 @@ import androidx.annotation.RequiresPermission
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import com.example.smart_watch_android.BLE.BleManager import com.example.smart_watch_android.BLE.BLEManager
import com.example.smart_watch_android.Screens.AppNavigation import com.example.smart_watch_android.Screens.AppNavigation
class MainActivity : ComponentActivity() { class MainActivity : ComponentActivity() {
lateinit var bleManager: BleManager private val viewModel: MainViewModel by viewModels()
@RequiresApi(Build.VERSION_CODES.S) @RequiresApi(Build.VERSION_CODES.S)
@RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT) @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
override fun onCreate(savedInstanceState: Bundle?,) { override fun onCreate(savedInstanceState: Bundle?,) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
bleManager = BleManager(this) BLEManager.init(context = applicationContext, activity = this)
bleManager.init()
enableEdgeToEdge() enableEdgeToEdge()
setContent { setContent {
MaterialTheme { MaterialTheme {
@@ -34,16 +30,9 @@ class MainActivity : ComponentActivity() {
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background color = MaterialTheme.colorScheme.background
) { ) {
AppNavigation(bleManager = bleManager) AppNavigation(viewModel)
} }
} }
} }
} }
@RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
override fun onDestroy() {
super.onDestroy()
bleManager.disconnectEsp32()
}
} }
@@ -0,0 +1,17 @@
package com.example.smart_watch_android
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
class MainViewModel : ViewModel() {
var selectedDevice by mutableStateOf("device")
fun updateSelectedDevice(newName: String) {
selectedDevice = newName
}
var selectedDeviceAddress = ""
fun updateSelectedDeviceAddress(address: String) {
selectedDeviceAddress = address
}
}
@@ -4,17 +4,23 @@ import android.Manifest
import androidx.annotation.RequiresPermission import androidx.annotation.RequiresPermission
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.platform.LocalContext
import androidx.navigation.compose.NavHost import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController import androidx.navigation.compose.rememberNavController
import com.example.smart_watch_android.BLE.BleManager import com.example.smart_watch_android.BLE.BLEManager
import com.example.smart_watch_android.MainViewModel
@RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT) @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
@Composable @Composable
fun AppNavigation(bleManager: BleManager) { fun AppNavigation(viewModel: MainViewModel) {
val context = LocalContext.current
val isConnected by BLEManager.isConnected.collectAsState()
val navController = rememberNavController() val navController = rememberNavController()
LaunchedEffect(bleManager.isConnected) { LaunchedEffect(BLEManager.isConnected) {
if (bleManager.isConnected.value) { if (isConnected) {
navController.navigate("control_panel") { navController.navigate("control_panel") {
popUpTo("connect") { inclusive = true } popUpTo("connect") { inclusive = true }
} }
@@ -24,7 +30,7 @@ fun AppNavigation(bleManager: BleManager) {
} }
} }
} }
val startDestination = if (bleManager.isConnected.value) { val startDestination = if (isConnected) {
"control_panel" "control_panel"
} else { } else {
"connect" "connect"
@@ -36,17 +42,15 @@ fun AppNavigation(bleManager: BleManager) {
) { ) {
// Connect Screen // Connect Screen
composable("connect") { composable("connect") {
ConnectScreen( ConnectScreen(viewModel)
bleManager = bleManager
)
} }
composable("control_panel") { composable("control_panel") {
ControlPanelScreen( ControlPanelScreen(
bleManager = bleManager, viewModel,
onDisconnectClicked = { onDisconnectClicked = {
bleManager.disconnectEsp32() BLEManager.disconnectEsp32(context = context)
} },
) )
} }
} }
@@ -1,13 +1,17 @@
package com.example.smart_watch_android.Screens package com.example.smart_watch_android.Screens
import android.Manifest import android.Manifest
import android.content.res.Configuration
import android.util.Log import android.util.Log
import androidx.annotation.RequiresPermission import androidx.annotation.RequiresPermission
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
@@ -27,15 +31,29 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import com.example.smart_watch_android.BLE.BleManager import com.example.smart_watch_android.BLE.BLEManager
import com.example.smart_watch_android.MainViewModel
@RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT) @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
@Composable @Composable
fun ConnectScreen(bleManager: BleManager) { fun ConnectScreen(viewModel: MainViewModel) {
val context = LocalContext.current
var expanded by remember { mutableStateOf(false) } var expanded by remember { mutableStateOf(false) }
var selectedDevice by remember { mutableStateOf("device") } val configuration = LocalConfiguration.current
val isLandscape = configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
val fraction = 0.7f
val dynamicModifier = if (isLandscape) {
Modifier
.fillMaxHeight(fraction)
.aspectRatio(1f)
} else {
Modifier
.fillMaxWidth(fraction)
.aspectRatio(1f)
}
Column( Column(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
@@ -44,29 +62,34 @@ fun ConnectScreen(bleManager: BleManager) {
horizontalAlignment = Alignment.CenterHorizontally horizontalAlignment = Alignment.CenterHorizontally
) )
{ {
Box(
){
Text("if the list is empty ensure you have bluetooth enabled!")
}
Box( Box(
modifier = Modifier modifier = Modifier
.padding(16.dp) .padding(16.dp)
) { ) {
Button( Button(
onClick = { expanded = !expanded }, onClick = { expanded = !expanded},
shape = RoundedCornerShape(4.dp), shape = RoundedCornerShape(4.dp),
modifier = Modifier.width(400.dp) modifier = Modifier.fillMaxWidth(fraction),
colors = ButtonDefaults.buttonColors(Color(0xFF5E18BE))
) { ) {
Text(selectedDevice) Text(viewModel.selectedDevice)
} }
DropdownMenu( DropdownMenu(
expanded = expanded, expanded = expanded,
onDismissRequest = { expanded = false }, onDismissRequest = { expanded = false },
modifier = Modifier modifier = Modifier
.width(400.dp) .fillMaxWidth(0.6f)
) { ) {
bleManager.devices.forEach { item -> BLEManager.devices.forEach { item ->
DropdownMenuItem( DropdownMenuItem(
text = { Text(item.deviceName) }, text = { Text(item.deviceName) },
onClick = { onClick = {
selectedDevice = item.deviceName viewModel.updateSelectedDevice(item.deviceName)
bleManager.deviceAddress = item.deviceMac viewModel.updateSelectedDeviceAddress(item.deviceMac)
Log.d("ConnectScreen", item.deviceMac) Log.d("ConnectScreen", item.deviceMac)
expanded = false expanded = false
} }
@@ -75,13 +98,11 @@ fun ConnectScreen(bleManager: BleManager) {
} }
} }
Spacer(modifier = Modifier.height(64.dp)) Spacer(modifier = Modifier.height(64.dp))
Button( Button(
modifier = Modifier.size(400.dp), modifier = dynamicModifier,
onClick = {bleManager.connectToEsp32() }, onClick = {BLEManager.connectToEsp32(context, viewModel.selectedDeviceAddress) },
shape = CircleShape, shape = CircleShape,
colors = ButtonDefaults.buttonColors(containerColor = Color(0xFF5E18BE)) colors = ButtonDefaults.buttonColors(containerColor = Color(0xFF5E18BE))
) { ) {
@@ -12,6 +12,7 @@ import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
@@ -19,15 +20,18 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.example.smart_watch_android.BLE.BleManager import com.example.smart_watch_android.BLE.BLEManager
import com.example.smart_watch_android.BLE.DeviceUUIDs import com.example.smart_watch_android.BLE.DeviceUUIDs
import com.example.smart_watch_android.MainViewModel
@Composable @Composable
fun ControlPanelScreen( fun ControlPanelScreen(
bleManager: BleManager, viewModel: MainViewModel,
onDisconnectClicked: () -> Unit onDisconnectClicked: () -> Unit
) { ) {
val context = LocalContext.current
var textInput by remember { mutableStateOf("") } var textInput by remember { mutableStateOf("") }
Column( Column(
@@ -50,9 +54,12 @@ fun ControlPanelScreen(
Button( Button(
onClick = { onClick = {
if (textInput.isNotEmpty()) { if (textInput.isNotEmpty()) {
bleManager.writeToEsp32( BLEManager.writeToEsp32(
textInput, DeviceUUIDs.SERVICE_UUID, DeviceUUIDs.CHAR_MESSAGE_UUID context = context,
) dataString = textInput,
SERVICE_UUID = DeviceUUIDs.SERVICE_UUID,
CHARACTERISTIC_UUID = DeviceUUIDs.CHAR_MESSAGE_UUID,
)
textInput = "" textInput = ""
} }
}, },
@@ -67,7 +74,9 @@ fun ControlPanelScreen(
Button( Button(
onClick = { onClick = {
bleManager.syncTime() BLEManager.syncTime(
context
)
}, },
colors = ButtonDefaults.buttonColors(containerColor = Color(0xFF50128F)), colors = ButtonDefaults.buttonColors(containerColor = Color(0xFF50128F)),
modifier = Modifier.fillMaxWidth() modifier = Modifier.fillMaxWidth()