This commit is contained in:
Vineyro 2023-04-04 09:10:12 +07:00
commit 5e309d001c
9 changed files with 334 additions and 181 deletions

View File

@ -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<ConnectedBleInfo>,
val bleList: List<BleInfo>
) : ViewState

View File

@ -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 = "Соединено"
)
}
}
}
}
}

View File

@ -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<BleListContract.State, BleListContract.Event, BleListContract.Effect>() {
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)
}
}

View File

@ -61,7 +61,7 @@ fun TemperatureHistory(
val viewModel = hiltViewModel<TemperatureHistoryViewModel>()
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<AxisPosition.Horizontal.Bottom> { 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<AxisPosition.Horizontal.Bottom> { 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)
}
}

View File

@ -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<String, ScanResult>()
val resultList = mutableMapOf<String, BleInfo>()
override fun getConnectedBle(): List<ConnectedBleInfo> {
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<Result<List<BleInfo>, 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<ByteArray, BleException> = 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<Unit, BleException>{
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)
}
}

View File

@ -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<Unit, BleException>{
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)
}
}
}

View File

@ -0,0 +1,8 @@
package llc.arma.ble.domain.model
import java.util.UUID
class ConnectedBleInfo(
val name: String,
val serial: String,
)

View File

@ -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<ConnectedBleInfo>
fun getBleAroundFlow(): Flow<Result<List<BleInfo>, BleException>>
suspend fun getBleBySerial(serial: String): Result<Ble, GetBleBySerial.GetBleException>

View File

@ -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<ConnectedBleInfo>{
return bleRepository.getConnectedBle()
}
}