view model and object
This commit is contained in:
1 parent
b1d89fbd08
commit
025f754504
16 files changed
+2605
-85
No files matched your search
Generated
+3
@@ -0,0 +1,3 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
Generated
+6
@@ -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>
|
||||||
Generated
+2410
File diff suppressed because it is too large.
Load diff
Generated
+12
@@ -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>
|
||||||
Generated
+10
@@ -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>
|
||||||
Generated
+10
@@ -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>
|
||||||
Generated
+17
@@ -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>
|
||||||
Generated
+6
@@ -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>
|
||||||
@@ -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")
|
||||||
}
|
}
|
||||||
@@ -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", "Cannot request permissions: Context is not an Activity!")
|
Log.d("ESP32_BLE", "Alle Bluetooth-Berechtigungen sind bereits erteilt!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
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,6 +62,10 @@ 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)
|
||||||
@@ -51,22 +73,23 @@ fun ConnectScreen(bleManager: BleManager) {
|
|||||||
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,8 +54,11 @@ 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()
|
||||||
|
|||||||
Reference in new issue
Block a user