diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..103e00c --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,32 @@ + + + + \ No newline at end of file diff --git a/app/src/main/java/llc/arma/ble/app/ui/screen/ble/BleListContract.kt b/app/src/main/java/llc/arma/ble/app/ui/screen/ble/BleListContract.kt index 26827f4..bc942a0 100644 --- a/app/src/main/java/llc/arma/ble/app/ui/screen/ble/BleListContract.kt +++ b/app/src/main/java/llc/arma/ble/app/ui/screen/ble/BleListContract.kt @@ -5,18 +5,20 @@ import llc.arma.ble.app.ui.common.ViewSideEffect import llc.arma.ble.app.ui.common.ViewState import llc.arma.ble.domain.model.Ble import llc.arma.ble.domain.model.BleInfo +import llc.arma.ble.domain.model.ConnectedBleInfo class BleListContract { sealed class Event : ViewEvent { data class OnConnectToBle( - val ble: BleInfo + val bleAddress: String ) : Event() } data class State( + val connectedBleList: List, val bleList: List ) : ViewState diff --git a/app/src/main/java/llc/arma/ble/app/ui/screen/ble/BleListScreen.kt b/app/src/main/java/llc/arma/ble/app/ui/screen/ble/BleListScreen.kt index 404422f..e6e2462 100644 --- a/app/src/main/java/llc/arma/ble/app/ui/screen/ble/BleListScreen.kt +++ b/app/src/main/java/llc/arma/ble/app/ui/screen/ble/BleListScreen.kt @@ -1,5 +1,6 @@ package llc.arma.ble.app.ui.screen.ble +import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn @@ -7,10 +8,7 @@ import androidx.compose.foundation.lazy.items import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.rounded.BatteryFull -import androidx.compose.material.icons.rounded.NetworkCell -import androidx.compose.material.icons.rounded.Nfc -import androidx.compose.material.icons.rounded.Thermostat +import androidx.compose.material.icons.rounded.* import androidx.compose.material3.* import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect @@ -24,6 +22,7 @@ import androidx.hilt.navigation.compose.hiltViewModel import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import llc.arma.ble.domain.model.BleInfo +import llc.arma.ble.domain.model.ConnectedBleInfo @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -53,7 +52,9 @@ fun BleListScreen( if(state.bleList.isEmpty()){ LinearProgressIndicator( strokeCap = StrokeCap.Round, - modifier = Modifier.fillMaxWidth().height(3.dp) + modifier = Modifier + .fillMaxWidth() + .height(3.dp) ) } @@ -62,12 +63,20 @@ fun BleListScreen( modifier = Modifier.fillMaxSize() ) { + items(items = state.connectedBleList){ + + ConnectedBleItem(ble = it) { + viewModel.setEvent(BleListContract.Event.OnConnectToBle(it.serial)) + } + + } + items(items = state.bleList) { BleItem( ble = it, onClick = { - viewModel.setEvent(BleListContract.Event.OnConnectToBle(it)) + viewModel.setEvent(BleListContract.Event.OnConnectToBle(it.serial)) } ) @@ -180,4 +189,62 @@ private fun BleItem( } +} + +@Composable +private fun ConnectedBleItem( + ble: ConnectedBleInfo, + onClick: () -> Unit +){ + + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(12.dp), + modifier = Modifier + .fillMaxWidth() + .clip(RoundedCornerShape(16.dp)) + .clickable { onClick() } + .background(MaterialTheme.colorScheme.tertiaryContainer.copy(alpha = .99f)) + .padding(vertical = 8.dp, horizontal = 16.dp) + + ) { + + ItemIcon { + Icon( + modifier = Modifier.align(Alignment.Center), + imageVector = Icons.Rounded.Link, + contentDescription = null + ) + } + + Column { + + Text(text = ble.name) + + Text( + style = MaterialTheme.typography.bodyMedium, + text = ble.serial + ) + + Row( + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.alpha(0.7f) + ) { + + Text( + style = MaterialTheme.typography.bodyMedium, + text = "Соединено" + ) + + } + } + + } + + } + } \ No newline at end of file diff --git a/app/src/main/java/llc/arma/ble/app/ui/screen/ble/BleListViewModel.kt b/app/src/main/java/llc/arma/ble/app/ui/screen/ble/BleListViewModel.kt index 61b7b53..5332fd7 100644 --- a/app/src/main/java/llc/arma/ble/app/ui/screen/ble/BleListViewModel.kt +++ b/app/src/main/java/llc/arma/ble/app/ui/screen/ble/BleListViewModel.kt @@ -8,11 +8,13 @@ import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch import llc.arma.ble.app.ui.common.BaseViewModel import llc.arma.ble.domain.usecase.GetBleAroundFlow +import llc.arma.ble.domain.usecase.GetConnectedBleDevices import javax.inject.Inject @HiltViewModel class BleListViewModel @Inject constructor( - getBleAroundFlow: GetBleAroundFlow + getBleAroundFlow: GetBleAroundFlow, + getConnectedBleDevices: GetConnectedBleDevices ) : BaseViewModel() { init { @@ -21,7 +23,10 @@ class BleListViewModel @Inject constructor( it.fold( onSuccess = { setState { - BleListContract.State(it) + BleListContract.State( + connectedBleList = emptyList(), + bleList = it + ) } }, onFailure = { @@ -33,7 +38,7 @@ class BleListViewModel @Inject constructor( } - override fun setInitialState(): BleListContract.State = BleListContract.State(emptyList()) + override fun setInitialState(): BleListContract.State = BleListContract.State(emptyList(), emptyList()) override fun handleEvents(event: BleListContract.Event) { when(event){ @@ -46,7 +51,7 @@ class BleListViewModel @Inject constructor( event: BleListContract.Event.OnConnectToBle ) { setEffect { - BleListContract.Effect.Navigation.NavigateToBle(serial = event.ble.serial) + BleListContract.Effect.Navigation.NavigateToBle(serial = event.bleAddress) } } diff --git a/app/src/main/java/llc/arma/ble/app/ui/screen/thermometer/view/TemperatureHistory.kt b/app/src/main/java/llc/arma/ble/app/ui/screen/thermometer/view/TemperatureHistory.kt index 263e297..8f281de 100644 --- a/app/src/main/java/llc/arma/ble/app/ui/screen/thermometer/view/TemperatureHistory.kt +++ b/app/src/main/java/llc/arma/ble/app/ui/screen/thermometer/view/TemperatureHistory.kt @@ -61,7 +61,7 @@ fun TemperatureHistory( val viewModel = hiltViewModel() val state = viewModel.viewState.value - LaunchedEffect("ble.serial") { + LaunchedEffect(ble.serial) { viewModel.setEvent(TemperatureHistoryContract.Event.OnStart(ble.serial)) } @@ -138,42 +138,53 @@ fun Display( is ProgressState.Finished -> { - val producer = remember(state.loadingHistoryState.data) { - state.loadingHistoryState.data.mapIndexed { index, measurePoint -> - TemperatureEntry(measurePoint.date, index.toFloat(), measurePoint.value) - }.let { - ChartEntryModelProducer(it) - } - } + if(state.loadingHistoryState.data.isEmpty()){ - val axisValueFormatter = - AxisValueFormatter { value, chartValues -> - (chartValues.chartEntryModel.entries.first() - .getOrNull(value.toInt()) as? TemperatureEntry) - ?.localDate - ?.let { formatter.format(Date(it)) } - .orEmpty() + Text( + modifier = Modifier.align(Alignment.Center), + text = "Нет данных" + ) + + } else { + + val producer = remember(state.loadingHistoryState.data) { + state.loadingHistoryState.data.mapIndexed { index, measurePoint -> + TemperatureEntry(measurePoint.date, index.toFloat(), measurePoint.value) + }.let { + ChartEntryModelProducer(it) + } } - val lineChart = lineChart() + val axisValueFormatter = + AxisValueFormatter { value, chartValues -> + (chartValues.chartEntryModel.entries.firstOrNull() + ?.getOrNull(value.toInt()) as? TemperatureEntry) + ?.localDate + ?.let { formatter.format(Date(it)) } + .orEmpty() + } - val scrollState = rememberChartScrollState() + val lineChart = lineChart() - Chart( - chartScrollState = scrollState, - chart = lineChart, - chartModelProducer = producer, - startAxis = startAxis(), - bottomAxis = bottomAxis( - tickLength = 0.dp, - valueFormatter = axisValueFormatter, - labelRotationDegrees = -90f, - ), - modifier = Modifier.fillMaxSize(), - ) + val scrollState = rememberChartScrollState() + + Chart( + chartScrollState = scrollState, + chart = lineChart, + chartModelProducer = producer, + startAxis = startAxis(), + bottomAxis = bottomAxis( + tickLength = 0.dp, + valueFormatter = axisValueFormatter, + labelRotationDegrees = -90f, + ), + modifier = Modifier.fillMaxSize(), + ) + + LaunchedEffect(scrollState.maxValue) { + scrollState.scrollBy(scrollState.maxValue) + } - LaunchedEffect(scrollState.maxValue) { - scrollState.scrollBy(scrollState.maxValue) } } diff --git a/app/src/main/java/llc/arma/ble/data/BleRepositoryImpl.kt b/app/src/main/java/llc/arma/ble/data/BleRepositoryImpl.kt index 71340fd..bc7955d 100644 --- a/app/src/main/java/llc/arma/ble/data/BleRepositoryImpl.kt +++ b/app/src/main/java/llc/arma/ble/data/BleRepositoryImpl.kt @@ -21,6 +21,7 @@ import llc.arma.ble.domain.common.BleException import llc.arma.ble.domain.common.ProgressState import llc.arma.ble.domain.model.Ble import llc.arma.ble.domain.model.BleInfo +import llc.arma.ble.domain.model.ConnectedBleInfo import llc.arma.ble.domain.repository.BleRepository import llc.arma.ble.domain.usecase.GetBleBySerial import java.nio.charset.Charset @@ -84,15 +85,31 @@ class BleRepositoryImpl @Inject constructor( private val deviceCache = mutableMapOf() val resultList = mutableMapOf() + override fun getConnectedBle(): List { + + if(checkPermission()) { + + return app.getSystemService(BluetoothManager::class.java) + .getConnectedDevices(BluetoothProfile.GATT) + .filter { + it.name.contains("arma", true) + } + .map { + ConnectedBleInfo( + name = it.name, + serial = it.address + ) + } + + }else{ + return emptyList() + } + + } override fun getBleAroundFlow(): Flow, BleException>> { - return if( - Build.VERSION.SDK_INT <= Build.VERSION_CODES.P || ActivityCompat.checkSelfPermission( - app, - Manifest.permission.BLUETOOTH_SCAN - ) == PackageManager.PERMISSION_GRANTED - ){ + return if(checkPermission()){ callbackFlow { @@ -105,11 +122,7 @@ class BleRepositoryImpl @Inject constructor( super.onScanResult(callbackType, result) - if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P || ActivityCompat.checkSelfPermission( - app, - Manifest.permission.BLUETOOTH_CONNECT - ) == PackageManager.PERMISSION_GRANTED - ) { + if (checkPermission()) { if (result.scanRecord?.deviceName?.contains("ArmA") == true) { @@ -177,11 +190,7 @@ class BleRepositoryImpl @Inject constructor( deviceCache[serial]?.let { result -> - if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P || ActivityCompat.checkSelfPermission( - app, - Manifest.permission.BLUETOOTH_CONNECT - ) == PackageManager.PERMISSION_GRANTED - ) { + if (checkPermission()) { if (it.isActive) { @@ -334,11 +343,7 @@ class BleRepositoryImpl @Inject constructor( deviceCache[serial]?.device?.let { - if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P || ActivityCompat.checkSelfPermission( - app, - Manifest.permission.BLUETOOTH_CONNECT - ) == PackageManager.PERMISSION_GRANTED - ) { + if (checkPermission()) { gatt = it.connectGatt(app, false, ReadHistoryCallback(app) { CoroutineScope(Dispatchers.IO).launch { @@ -533,8 +538,7 @@ class BleRepositoryImpl @Inject constructor( characteristicId: UUID ): Result = suspendCancellableCoroutine { - var result: ByteArray? = null - var bleGatt: BluetoothGatt? = null + var result: ByteArray? val callback = object : BluetoothGattCallback() { @@ -550,11 +554,7 @@ class BleRepositoryImpl @Inject constructor( if (newState == BluetoothProfile.STATE_CONNECTED) { - if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P || ActivityCompat.checkSelfPermission( - app, - Manifest.permission.BLUETOOTH_CONNECT - ) == PackageManager.PERMISSION_GRANTED - ) { + if (checkPermission()) { gatt.discoverServices() @@ -590,11 +590,7 @@ class BleRepositoryImpl @Inject constructor( characteristic.uuid == characteristicId }?.let { char -> - if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P || ActivityCompat.checkSelfPermission( - app, - Manifest.permission.BLUETOOTH_CONNECT - ) == PackageManager.PERMISSION_GRANTED - ) { + if (checkPermission()) { gatt.readCharacteristic(char) @@ -616,24 +612,17 @@ class BleRepositoryImpl @Inject constructor( } - @Deprecated("Deprecated in Java") override fun onCharacteristicRead( gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, status: Int ) { - super.onCharacteristicRead(gatt, characteristic, status) - result = characteristic.value - if (result != null) { - it.resume(Result.success(result!!)) - } else { - bleGatt?.close() - it.resume(Result.failure(BleException.UnexpectedResponse)) + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) { + super.onCharacteristicRead(gatt, characteristic, status) + onCommonCharacteristicRead(gatt, characteristic, characteristic.value, status) } - gatt.close() - } override fun onCharacteristicRead( @@ -643,16 +632,21 @@ class BleRepositoryImpl @Inject constructor( status: Int ) { super.onCharacteristicRead(gatt, characteristic, value, status) + onCommonCharacteristicRead(gatt, characteristic, value, status) + } + + fun onCommonCharacteristicRead( + gatt: BluetoothGatt, + characteristic: BluetoothGattCharacteristic, + value: ByteArray, + status: Int + ) { Log.d("read", "onCharacteristicRead $status") if(status == BluetoothGatt.GATT_SUCCESS) { - if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P || ActivityCompat.checkSelfPermission( - app, - Manifest.permission.BLUETOOTH_CONNECT - ) == PackageManager.PERMISSION_GRANTED - ) { + if (checkPermission()) { gatt.close() result = value @@ -673,11 +667,8 @@ class BleRepositoryImpl @Inject constructor( } - if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P || ActivityCompat.checkSelfPermission( - app, - Manifest.permission.BLUETOOTH_CONNECT - ) == PackageManager.PERMISSION_GRANTED) { - bleGatt = device.connectGatt(app, false, callback) + if (checkPermission()) { + device.connectGatt(app, false, callback) } else { it.resume(Result.failure(BleException.PermissionDenied)) } @@ -707,11 +698,7 @@ class BleRepositoryImpl @Inject constructor( if (newState == BluetoothProfile.STATE_CONNECTED) { - if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P || ActivityCompat.checkSelfPermission( - app, - Manifest.permission.BLUETOOTH_CONNECT - ) == PackageManager.PERMISSION_GRANTED - ) { + if (checkPermission()) { gatt.discoverServices() } else { @@ -751,11 +738,7 @@ class BleRepositoryImpl @Inject constructor( characteristic.uuid == characteristicId }?.let { char -> - if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P || ActivityCompat.checkSelfPermission( - app, - Manifest.permission.BLUETOOTH_CONNECT - ) == PackageManager.PERMISSION_GRANTED - ) { + if (checkPermission()) { gatt.writeCharacteristic(char, writeData) @@ -788,11 +771,7 @@ class BleRepositoryImpl @Inject constructor( Log.d("write", "onCharacteristicWrite $status") - if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P || ActivityCompat.checkSelfPermission( - app, - Manifest.permission.BLUETOOTH_CONNECT - ) == PackageManager.PERMISSION_GRANTED - ) { + if (checkPermission()) { gatt.close() @@ -816,10 +795,7 @@ class BleRepositoryImpl @Inject constructor( } - if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P || ActivityCompat.checkSelfPermission( - app, - Manifest.permission.BLUETOOTH_CONNECT - ) == PackageManager.PERMISSION_GRANTED) { + if (checkPermission()) { bleGatt = device.connectGatt(app, false, callback) @@ -831,18 +807,41 @@ class BleRepositoryImpl @Inject constructor( } -} + fun checkPermission(): Boolean { -fun BluetoothGatt.writeCharacteristic( - characteristic: BluetoothGattCharacteristic, - data: ByteArray -){ + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + ActivityCompat.checkSelfPermission(app, Manifest.permission.BLUETOOTH_CONNECT) == + PackageManager.PERMISSION_GRANTED && + ActivityCompat.checkSelfPermission(app, Manifest.permission.BLUETOOTH_SCAN) == + PackageManager.PERMISSION_GRANTED + } else { + return ActivityCompat.checkSelfPermission(app, Manifest.permission.ACCESS_FINE_LOCATION) == + PackageManager.PERMISSION_GRANTED && + ActivityCompat.checkSelfPermission(app, Manifest.permission.ACCESS_COARSE_LOCATION) == + PackageManager.PERMISSION_GRANTED + } + } + + fun BluetoothGatt.writeCharacteristic( + characteristic: BluetoothGattCharacteristic, + data: ByteArray + ): Result{ + + return if(checkPermission()){ + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + writeCharacteristic(characteristic, data, BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT) + }else{ + characteristic.value = data + writeCharacteristic(characteristic) + } + + Result.success(Unit) + + } else { + Result.failure(BleException.PermissionDenied) + } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - writeCharacteristic(characteristic, data, BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT) - }else{ - characteristic.value = data - writeCharacteristic(characteristic) } } \ No newline at end of file diff --git a/app/src/main/java/llc/arma/ble/data/ReadHistoryCallback.kt b/app/src/main/java/llc/arma/ble/data/ReadHistoryCallback.kt index ed10025..660f4a4 100644 --- a/app/src/main/java/llc/arma/ble/data/ReadHistoryCallback.kt +++ b/app/src/main/java/llc/arma/ble/data/ReadHistoryCallback.kt @@ -47,11 +47,7 @@ class ReadHistoryCallback( if(newState == BluetoothGatt.STATE_CONNECTED){ - if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P || ActivityCompat.checkSelfPermission( - app, - Manifest.permission.BLUETOOTH_CONNECT - ) == PackageManager.PERMISSION_GRANTED - ) { + if (checkPermission()) { gatt.discoverServices() } else { @@ -77,11 +73,7 @@ class ReadHistoryCallback( if(status == BluetoothGatt.GATT_SUCCESS){ gatt.getService(serviceUUID)?.getCharacteristic(temperatureHistoryReadUUID)?.let { - if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P || ActivityCompat.checkSelfPermission( - app, - Manifest.permission.BLUETOOTH_CONNECT - ) == PackageManager.PERMISSION_GRANTED - ) { + if (checkPermission()) { readProperty = Property.DATA_SIZE gatt.writeCharacteristic(it, byteArrayOf(2)) @@ -114,8 +106,10 @@ class ReadHistoryCallback( characteristic: BluetoothGattCharacteristic, status: Int ) { - super.onCharacteristicRead(gatt, characteristic, status) - onCommonCharacteristicRead(gatt, characteristic, characteristic.value, status) + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) { + super.onCharacteristicRead(gatt, characteristic, status) + onCommonCharacteristicRead(gatt, characteristic, characteristic.value, status) + } } override fun onCharacteristicRead( @@ -125,7 +119,7 @@ class ReadHistoryCallback( status: Int ) { super.onCharacteristicRead(gatt, characteristic, value, status) - //onCommonCharacteristicRead(gatt, characteristic, value, status) + onCommonCharacteristicRead(gatt, characteristic, value, status) } private fun onCommonCharacteristicRead( @@ -137,16 +131,31 @@ class ReadHistoryCallback( if(status == BluetoothGatt.GATT_SUCCESS){ when(readProperty){ Property.DATA_SIZE -> { - val writeData = mutableListOf( - 1.toByte(), - 0.toByte(), - 0.toByte() - ).apply { - addAll(value.toList()) - }.toByteArray() - readProperty = Property.PACKAGE - gatt.writeCharacteristic(characteristic, writeData) + if(value.contentEquals(byteArrayOf(0, 0))) { + onResult( + Result.success( + ProgressState.Finished( + emptyList() + ) + ) + ) + gatt.close() + + } else { + + val writeData = mutableListOf( + 1.toByte(), + 0.toByte(), + 0.toByte() + ).apply { + addAll(value.toList()) + }.toByteArray() + + readProperty = Property.PACKAGE + gatt.writeCharacteristic(characteristic, writeData) + + } } Property.PACKAGE -> { @@ -177,11 +186,7 @@ class ReadHistoryCallback( if(nextPackageDataCount != 0.toUByte()){ - if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P || ActivityCompat.checkSelfPermission( - app, - Manifest.permission.BLUETOOTH_CONNECT - ) == PackageManager.PERMISSION_GRANTED - ) { + if (checkPermission()) { gatt.writeCharacteristic(characteristic, byteArrayOf(5)) gatt.readCharacteristic(characteristic) @@ -209,43 +214,48 @@ class ReadHistoryCallback( gatt.close() } - } + } else { - if(value[0] == 251.toByte()) { + if (value[0] == 251.toByte()) { - val nextPackageDataCount = value[1].toUByte() - val temperatureDataArray = value.toList().subList(2, value.size) + val nextPackageDataCount = value[1].toUByte() + val temperatureDataArray = value.toList().subList(2, value.size) - resultTemperaturePackage.addAll( - temperatureDataArray.chunked(2).map { - (it[0] + it[1] * 256).toFloat() / 100f - } - ) + resultTemperaturePackage.addAll( + temperatureDataArray.chunked(2).map { + (it[0] + it[1] * 256).toFloat() / 100f + } + ) - onResult(Result.success(ProgressState.Progress(expectedDataSize!!.toFloat() / resultTemperaturePackage.size.toFloat()))) + onResult(Result.success(ProgressState.Progress(expectedDataSize!!.toFloat() / resultTemperaturePackage.size.toFloat()))) - if(nextPackageDataCount != 0.toUByte()){ + if (nextPackageDataCount != 0.toUByte()) { - val writeData = byteArrayOf(5) + val writeData = byteArrayOf(5) - gatt.writeCharacteristic(characteristic, writeData) - gatt.readCharacteristic(characteristic) + gatt.writeCharacteristic(characteristic, writeData) + gatt.readCharacteristic(characteristic) - } else { - onResult( - Result.success( - ProgressState.Finished( - resultTemperaturePackage.withIndex().map { - Ble.Thermometer.MeasurePoint( - date = lastMeasureSystemTime!! - (((resultTemperaturePackage.size - 1) - it.index) * bleMeasureInterval!!), - value = it.value - ) - } + } else { + onResult( + Result.success( + ProgressState.Finished( + resultTemperaturePackage.withIndex().map { + Ble.Thermometer.MeasurePoint( + date = lastMeasureSystemTime!! - (((resultTemperaturePackage.size - 1) - it.index) * bleMeasureInterval!!), + value = it.value + ) + } + ) ) ) - ) + gatt.close() + } + } else { + onResult(Result.failure(BleException.UnexpectedResponse)) gatt.close() } + } } else -> { @@ -267,11 +277,7 @@ class ReadHistoryCallback( super.onCharacteristicWrite(gatt, characteristic, status) if(status == BluetoothGatt.GATT_SUCCESS){ - if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P || ActivityCompat.checkSelfPermission( - app, - Manifest.permission.BLUETOOTH_CONNECT - ) == PackageManager.PERMISSION_GRANTED - ) { + if (checkPermission()) { gatt.readCharacteristic(characteristic) @@ -289,4 +295,41 @@ class ReadHistoryCallback( } + fun checkPermission(): Boolean { + + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + ActivityCompat.checkSelfPermission(app, Manifest.permission.BLUETOOTH_CONNECT) == + PackageManager.PERMISSION_GRANTED && + ActivityCompat.checkSelfPermission(app, Manifest.permission.BLUETOOTH_SCAN) == + PackageManager.PERMISSION_GRANTED + } else { + return ActivityCompat.checkSelfPermission(app, Manifest.permission.ACCESS_FINE_LOCATION) == + PackageManager.PERMISSION_GRANTED && + ActivityCompat.checkSelfPermission(app, Manifest.permission.ACCESS_COARSE_LOCATION) == + PackageManager.PERMISSION_GRANTED + } + } + + fun BluetoothGatt.writeCharacteristic( + characteristic: BluetoothGattCharacteristic, + data: ByteArray + ): Result{ + + return if(checkPermission()){ + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + writeCharacteristic(characteristic, data, BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT) + }else{ + characteristic.value = data + writeCharacteristic(characteristic) + } + + Result.success(Unit) + + } else { + Result.failure(BleException.PermissionDenied) + } + + } + } \ No newline at end of file diff --git a/app/src/main/java/llc/arma/ble/domain/model/ConnectedBleInfo.kt b/app/src/main/java/llc/arma/ble/domain/model/ConnectedBleInfo.kt new file mode 100644 index 0000000..374ba0f --- /dev/null +++ b/app/src/main/java/llc/arma/ble/domain/model/ConnectedBleInfo.kt @@ -0,0 +1,8 @@ +package llc.arma.ble.domain.model + +import java.util.UUID + +class ConnectedBleInfo( + val name: String, + val serial: String, +) \ No newline at end of file diff --git a/app/src/main/java/llc/arma/ble/domain/repository/BleRepository.kt b/app/src/main/java/llc/arma/ble/domain/repository/BleRepository.kt index 38b5ffc..537ecd4 100644 --- a/app/src/main/java/llc/arma/ble/domain/repository/BleRepository.kt +++ b/app/src/main/java/llc/arma/ble/domain/repository/BleRepository.kt @@ -6,10 +6,13 @@ import llc.arma.ble.domain.common.BleException import llc.arma.ble.domain.common.ProgressState import llc.arma.ble.domain.model.Ble import llc.arma.ble.domain.model.BleInfo +import llc.arma.ble.domain.model.ConnectedBleInfo import llc.arma.ble.domain.usecase.GetBleBySerial interface BleRepository { + fun getConnectedBle(): List + fun getBleAroundFlow(): Flow, BleException>> suspend fun getBleBySerial(serial: String): Result diff --git a/app/src/main/java/llc/arma/ble/domain/usecase/GetConnectedBleDevices.kt b/app/src/main/java/llc/arma/ble/domain/usecase/GetConnectedBleDevices.kt new file mode 100644 index 0000000..d331a54 --- /dev/null +++ b/app/src/main/java/llc/arma/ble/domain/usecase/GetConnectedBleDevices.kt @@ -0,0 +1,15 @@ +package llc.arma.ble.domain.usecase + +import llc.arma.ble.domain.model.ConnectedBleInfo +import llc.arma.ble.domain.repository.BleRepository +import javax.inject.Inject + +class GetConnectedBleDevices @Inject constructor( + private val bleRepository: BleRepository +) { + + operator fun invoke(): List{ + return bleRepository.getConnectedBle() + } + +} \ No newline at end of file