Init
This commit is contained in:
parent
806ceb1fa8
commit
4226f18d96
|
|
@ -0,0 +1,32 @@
|
||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<profile version="1.0">
|
||||||
|
<option name="myName" value="Project Default" />
|
||||||
|
<inspection_tool class="PreviewAnnotationInFunctionWithParameters" enabled="true" level="ERROR" enabled_by_default="true">
|
||||||
|
<option name="composableFile" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="PreviewApiLevelMustBeValid" enabled="true" level="ERROR" enabled_by_default="true">
|
||||||
|
<option name="composableFile" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="PreviewDimensionRespectsLimit" enabled="true" level="WARNING" enabled_by_default="true">
|
||||||
|
<option name="composableFile" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="PreviewFontScaleMustBeGreaterThanZero" enabled="true" level="ERROR" enabled_by_default="true">
|
||||||
|
<option name="composableFile" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="PreviewMultipleParameterProviders" enabled="true" level="ERROR" enabled_by_default="true">
|
||||||
|
<option name="composableFile" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="PreviewMustBeTopLevelFunction" enabled="true" level="ERROR" enabled_by_default="true">
|
||||||
|
<option name="composableFile" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="PreviewNeedsComposableAnnotation" enabled="true" level="ERROR" enabled_by_default="true">
|
||||||
|
<option name="composableFile" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="PreviewNotSupportedInUnitTestFiles" enabled="true" level="ERROR" enabled_by_default="true">
|
||||||
|
<option name="composableFile" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="PreviewPickerAnnotation" enabled="true" level="ERROR" enabled_by_default="true">
|
||||||
|
<option name="composableFile" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
</profile>
|
||||||
|
</component>
|
||||||
|
|
@ -5,18 +5,20 @@ import llc.arma.ble.app.ui.common.ViewSideEffect
|
||||||
import llc.arma.ble.app.ui.common.ViewState
|
import llc.arma.ble.app.ui.common.ViewState
|
||||||
import llc.arma.ble.domain.model.Ble
|
import llc.arma.ble.domain.model.Ble
|
||||||
import llc.arma.ble.domain.model.BleInfo
|
import llc.arma.ble.domain.model.BleInfo
|
||||||
|
import llc.arma.ble.domain.model.ConnectedBleInfo
|
||||||
|
|
||||||
class BleListContract {
|
class BleListContract {
|
||||||
|
|
||||||
sealed class Event : ViewEvent {
|
sealed class Event : ViewEvent {
|
||||||
|
|
||||||
data class OnConnectToBle(
|
data class OnConnectToBle(
|
||||||
val ble: BleInfo
|
val bleAddress: String
|
||||||
) : Event()
|
) : Event()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
data class State(
|
data class State(
|
||||||
|
val connectedBleList: List<ConnectedBleInfo>,
|
||||||
val bleList: List<BleInfo>
|
val bleList: List<BleInfo>
|
||||||
) : ViewState
|
) : ViewState
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package llc.arma.ble.app.ui.screen.ble
|
package llc.arma.ble.app.ui.screen.ble
|
||||||
|
|
||||||
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
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.CircleShape
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.rounded.BatteryFull
|
import androidx.compose.material.icons.rounded.*
|
||||||
import androidx.compose.material.icons.rounded.NetworkCell
|
|
||||||
import androidx.compose.material.icons.rounded.Nfc
|
|
||||||
import androidx.compose.material.icons.rounded.Thermostat
|
|
||||||
import androidx.compose.material3.*
|
import androidx.compose.material3.*
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
|
@ -24,6 +22,7 @@ import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import llc.arma.ble.domain.model.BleInfo
|
import llc.arma.ble.domain.model.BleInfo
|
||||||
|
import llc.arma.ble.domain.model.ConnectedBleInfo
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
|
|
@ -53,7 +52,9 @@ fun BleListScreen(
|
||||||
if(state.bleList.isEmpty()){
|
if(state.bleList.isEmpty()){
|
||||||
LinearProgressIndicator(
|
LinearProgressIndicator(
|
||||||
strokeCap = StrokeCap.Round,
|
strokeCap = StrokeCap.Round,
|
||||||
modifier = Modifier.fillMaxWidth().height(3.dp)
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(3.dp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -62,12 +63,20 @@ fun BleListScreen(
|
||||||
modifier = Modifier.fillMaxSize()
|
modifier = Modifier.fillMaxSize()
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
items(items = state.connectedBleList){
|
||||||
|
|
||||||
|
ConnectedBleItem(ble = it) {
|
||||||
|
viewModel.setEvent(BleListContract.Event.OnConnectToBle(it.serial))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
items(items = state.bleList) {
|
items(items = state.bleList) {
|
||||||
|
|
||||||
BleItem(
|
BleItem(
|
||||||
ble = it,
|
ble = it,
|
||||||
onClick = {
|
onClick = {
|
||||||
viewModel.setEvent(BleListContract.Event.OnConnectToBle(it))
|
viewModel.setEvent(BleListContract.Event.OnConnectToBle(it.serial))
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -181,3 +190,61 @@ 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 = "Соединено"
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -8,11 +8,13 @@ import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import llc.arma.ble.app.ui.common.BaseViewModel
|
import llc.arma.ble.app.ui.common.BaseViewModel
|
||||||
import llc.arma.ble.domain.usecase.GetBleAroundFlow
|
import llc.arma.ble.domain.usecase.GetBleAroundFlow
|
||||||
|
import llc.arma.ble.domain.usecase.GetConnectedBleDevices
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
class BleListViewModel @Inject constructor(
|
class BleListViewModel @Inject constructor(
|
||||||
getBleAroundFlow: GetBleAroundFlow
|
getBleAroundFlow: GetBleAroundFlow,
|
||||||
|
getConnectedBleDevices: GetConnectedBleDevices
|
||||||
) : BaseViewModel<BleListContract.State, BleListContract.Event, BleListContract.Effect>() {
|
) : BaseViewModel<BleListContract.State, BleListContract.Event, BleListContract.Effect>() {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
|
@ -21,7 +23,10 @@ class BleListViewModel @Inject constructor(
|
||||||
it.fold(
|
it.fold(
|
||||||
onSuccess = {
|
onSuccess = {
|
||||||
setState {
|
setState {
|
||||||
BleListContract.State(it)
|
BleListContract.State(
|
||||||
|
connectedBleList = emptyList(),
|
||||||
|
bleList = it
|
||||||
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onFailure = {
|
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) {
|
override fun handleEvents(event: BleListContract.Event) {
|
||||||
when(event){
|
when(event){
|
||||||
|
|
@ -46,7 +51,7 @@ class BleListViewModel @Inject constructor(
|
||||||
event: BleListContract.Event.OnConnectToBle
|
event: BleListContract.Event.OnConnectToBle
|
||||||
) {
|
) {
|
||||||
setEffect {
|
setEffect {
|
||||||
BleListContract.Effect.Navigation.NavigateToBle(serial = event.ble.serial)
|
BleListContract.Effect.Navigation.NavigateToBle(serial = event.bleAddress)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ fun TemperatureHistory(
|
||||||
val viewModel = hiltViewModel<TemperatureHistoryViewModel>()
|
val viewModel = hiltViewModel<TemperatureHistoryViewModel>()
|
||||||
val state = viewModel.viewState.value
|
val state = viewModel.viewState.value
|
||||||
|
|
||||||
LaunchedEffect("ble.serial") {
|
LaunchedEffect(ble.serial) {
|
||||||
viewModel.setEvent(TemperatureHistoryContract.Event.OnStart(ble.serial))
|
viewModel.setEvent(TemperatureHistoryContract.Event.OnStart(ble.serial))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -138,6 +138,15 @@ fun Display(
|
||||||
|
|
||||||
is ProgressState.Finished -> {
|
is ProgressState.Finished -> {
|
||||||
|
|
||||||
|
if(state.loadingHistoryState.data.isEmpty()){
|
||||||
|
|
||||||
|
Text(
|
||||||
|
modifier = Modifier.align(Alignment.Center),
|
||||||
|
text = "Нет данных"
|
||||||
|
)
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
val producer = remember(state.loadingHistoryState.data) {
|
val producer = remember(state.loadingHistoryState.data) {
|
||||||
state.loadingHistoryState.data.mapIndexed { index, measurePoint ->
|
state.loadingHistoryState.data.mapIndexed { index, measurePoint ->
|
||||||
TemperatureEntry(measurePoint.date, index.toFloat(), measurePoint.value)
|
TemperatureEntry(measurePoint.date, index.toFloat(), measurePoint.value)
|
||||||
|
|
@ -148,8 +157,8 @@ fun Display(
|
||||||
|
|
||||||
val axisValueFormatter =
|
val axisValueFormatter =
|
||||||
AxisValueFormatter<AxisPosition.Horizontal.Bottom> { value, chartValues ->
|
AxisValueFormatter<AxisPosition.Horizontal.Bottom> { value, chartValues ->
|
||||||
(chartValues.chartEntryModel.entries.first()
|
(chartValues.chartEntryModel.entries.firstOrNull()
|
||||||
.getOrNull(value.toInt()) as? TemperatureEntry)
|
?.getOrNull(value.toInt()) as? TemperatureEntry)
|
||||||
?.localDate
|
?.localDate
|
||||||
?.let { formatter.format(Date(it)) }
|
?.let { formatter.format(Date(it)) }
|
||||||
.orEmpty()
|
.orEmpty()
|
||||||
|
|
@ -177,6 +186,8 @@ fun Display(
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
is ProgressState.Indeterminate -> {
|
is ProgressState.Indeterminate -> {
|
||||||
|
|
||||||
CircularProgressIndicator(
|
CircularProgressIndicator(
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import llc.arma.ble.domain.common.BleException
|
||||||
import llc.arma.ble.domain.common.ProgressState
|
import llc.arma.ble.domain.common.ProgressState
|
||||||
import llc.arma.ble.domain.model.Ble
|
import llc.arma.ble.domain.model.Ble
|
||||||
import llc.arma.ble.domain.model.BleInfo
|
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.repository.BleRepository
|
||||||
import llc.arma.ble.domain.usecase.GetBleBySerial
|
import llc.arma.ble.domain.usecase.GetBleBySerial
|
||||||
import java.nio.charset.Charset
|
import java.nio.charset.Charset
|
||||||
|
|
@ -84,15 +85,31 @@ class BleRepositoryImpl @Inject constructor(
|
||||||
|
|
||||||
private val deviceCache = mutableMapOf<String, ScanResult>()
|
private val deviceCache = mutableMapOf<String, ScanResult>()
|
||||||
val resultList = mutableMapOf<String, BleInfo>()
|
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>> {
|
override fun getBleAroundFlow(): Flow<Result<List<BleInfo>, BleException>> {
|
||||||
|
|
||||||
return if(
|
return if(checkPermission()){
|
||||||
Build.VERSION.SDK_INT <= Build.VERSION_CODES.P || ActivityCompat.checkSelfPermission(
|
|
||||||
app,
|
|
||||||
Manifest.permission.BLUETOOTH_SCAN
|
|
||||||
) == PackageManager.PERMISSION_GRANTED
|
|
||||||
){
|
|
||||||
|
|
||||||
callbackFlow {
|
callbackFlow {
|
||||||
|
|
||||||
|
|
@ -105,11 +122,7 @@ class BleRepositoryImpl @Inject constructor(
|
||||||
|
|
||||||
super.onScanResult(callbackType, result)
|
super.onScanResult(callbackType, result)
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P || ActivityCompat.checkSelfPermission(
|
if (checkPermission()) {
|
||||||
app,
|
|
||||||
Manifest.permission.BLUETOOTH_CONNECT
|
|
||||||
) == PackageManager.PERMISSION_GRANTED
|
|
||||||
) {
|
|
||||||
|
|
||||||
if (result.scanRecord?.deviceName?.contains("ArmA") == true) {
|
if (result.scanRecord?.deviceName?.contains("ArmA") == true) {
|
||||||
|
|
||||||
|
|
@ -177,11 +190,7 @@ class BleRepositoryImpl @Inject constructor(
|
||||||
|
|
||||||
deviceCache[serial]?.let { result ->
|
deviceCache[serial]?.let { result ->
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P || ActivityCompat.checkSelfPermission(
|
if (checkPermission()) {
|
||||||
app,
|
|
||||||
Manifest.permission.BLUETOOTH_CONNECT
|
|
||||||
) == PackageManager.PERMISSION_GRANTED
|
|
||||||
) {
|
|
||||||
|
|
||||||
if (it.isActive) {
|
if (it.isActive) {
|
||||||
|
|
||||||
|
|
@ -334,11 +343,7 @@ class BleRepositoryImpl @Inject constructor(
|
||||||
|
|
||||||
deviceCache[serial]?.device?.let {
|
deviceCache[serial]?.device?.let {
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P || ActivityCompat.checkSelfPermission(
|
if (checkPermission()) {
|
||||||
app,
|
|
||||||
Manifest.permission.BLUETOOTH_CONNECT
|
|
||||||
) == PackageManager.PERMISSION_GRANTED
|
|
||||||
) {
|
|
||||||
|
|
||||||
gatt = it.connectGatt(app, false, ReadHistoryCallback(app) {
|
gatt = it.connectGatt(app, false, ReadHistoryCallback(app) {
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
|
@ -533,8 +538,7 @@ class BleRepositoryImpl @Inject constructor(
|
||||||
characteristicId: UUID
|
characteristicId: UUID
|
||||||
): Result<ByteArray, BleException> = suspendCancellableCoroutine {
|
): Result<ByteArray, BleException> = suspendCancellableCoroutine {
|
||||||
|
|
||||||
var result: ByteArray? = null
|
var result: ByteArray?
|
||||||
var bleGatt: BluetoothGatt? = null
|
|
||||||
|
|
||||||
val callback = object : BluetoothGattCallback() {
|
val callback = object : BluetoothGattCallback() {
|
||||||
|
|
||||||
|
|
@ -550,11 +554,7 @@ class BleRepositoryImpl @Inject constructor(
|
||||||
|
|
||||||
if (newState == BluetoothProfile.STATE_CONNECTED) {
|
if (newState == BluetoothProfile.STATE_CONNECTED) {
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P || ActivityCompat.checkSelfPermission(
|
if (checkPermission()) {
|
||||||
app,
|
|
||||||
Manifest.permission.BLUETOOTH_CONNECT
|
|
||||||
) == PackageManager.PERMISSION_GRANTED
|
|
||||||
) {
|
|
||||||
|
|
||||||
gatt.discoverServices()
|
gatt.discoverServices()
|
||||||
|
|
||||||
|
|
@ -590,11 +590,7 @@ class BleRepositoryImpl @Inject constructor(
|
||||||
characteristic.uuid == characteristicId
|
characteristic.uuid == characteristicId
|
||||||
}?.let { char ->
|
}?.let { char ->
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P || ActivityCompat.checkSelfPermission(
|
if (checkPermission()) {
|
||||||
app,
|
|
||||||
Manifest.permission.BLUETOOTH_CONNECT
|
|
||||||
) == PackageManager.PERMISSION_GRANTED
|
|
||||||
) {
|
|
||||||
|
|
||||||
gatt.readCharacteristic(char)
|
gatt.readCharacteristic(char)
|
||||||
|
|
||||||
|
|
@ -616,24 +612,17 @@ class BleRepositoryImpl @Inject constructor(
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated("Deprecated in Java")
|
|
||||||
override fun onCharacteristicRead(
|
override fun onCharacteristicRead(
|
||||||
gatt: BluetoothGatt,
|
gatt: BluetoothGatt,
|
||||||
characteristic: BluetoothGattCharacteristic,
|
characteristic: BluetoothGattCharacteristic,
|
||||||
status: Int
|
status: Int
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
|
||||||
super.onCharacteristicRead(gatt, characteristic, status)
|
super.onCharacteristicRead(gatt, characteristic, status)
|
||||||
|
onCommonCharacteristicRead(gatt, characteristic, characteristic.value, status)
|
||||||
result = characteristic.value
|
|
||||||
if (result != null) {
|
|
||||||
it.resume(Result.success(result!!))
|
|
||||||
} else {
|
|
||||||
bleGatt?.close()
|
|
||||||
it.resume(Result.failure(BleException.UnexpectedResponse))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gatt.close()
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCharacteristicRead(
|
override fun onCharacteristicRead(
|
||||||
|
|
@ -643,16 +632,21 @@ class BleRepositoryImpl @Inject constructor(
|
||||||
status: Int
|
status: Int
|
||||||
) {
|
) {
|
||||||
super.onCharacteristicRead(gatt, characteristic, value, status)
|
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")
|
Log.d("read", "onCharacteristicRead $status")
|
||||||
|
|
||||||
if(status == BluetoothGatt.GATT_SUCCESS) {
|
if(status == BluetoothGatt.GATT_SUCCESS) {
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P || ActivityCompat.checkSelfPermission(
|
if (checkPermission()) {
|
||||||
app,
|
|
||||||
Manifest.permission.BLUETOOTH_CONNECT
|
|
||||||
) == PackageManager.PERMISSION_GRANTED
|
|
||||||
) {
|
|
||||||
|
|
||||||
gatt.close()
|
gatt.close()
|
||||||
result = value
|
result = value
|
||||||
|
|
@ -673,11 +667,8 @@ class BleRepositoryImpl @Inject constructor(
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P || ActivityCompat.checkSelfPermission(
|
if (checkPermission()) {
|
||||||
app,
|
device.connectGatt(app, false, callback)
|
||||||
Manifest.permission.BLUETOOTH_CONNECT
|
|
||||||
) == PackageManager.PERMISSION_GRANTED) {
|
|
||||||
bleGatt = device.connectGatt(app, false, callback)
|
|
||||||
} else {
|
} else {
|
||||||
it.resume(Result.failure(BleException.PermissionDenied))
|
it.resume(Result.failure(BleException.PermissionDenied))
|
||||||
}
|
}
|
||||||
|
|
@ -707,11 +698,7 @@ class BleRepositoryImpl @Inject constructor(
|
||||||
|
|
||||||
if (newState == BluetoothProfile.STATE_CONNECTED) {
|
if (newState == BluetoothProfile.STATE_CONNECTED) {
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P || ActivityCompat.checkSelfPermission(
|
if (checkPermission()) {
|
||||||
app,
|
|
||||||
Manifest.permission.BLUETOOTH_CONNECT
|
|
||||||
) == PackageManager.PERMISSION_GRANTED
|
|
||||||
) {
|
|
||||||
gatt.discoverServices()
|
gatt.discoverServices()
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
|
@ -751,11 +738,7 @@ class BleRepositoryImpl @Inject constructor(
|
||||||
characteristic.uuid == characteristicId
|
characteristic.uuid == characteristicId
|
||||||
}?.let { char ->
|
}?.let { char ->
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P || ActivityCompat.checkSelfPermission(
|
if (checkPermission()) {
|
||||||
app,
|
|
||||||
Manifest.permission.BLUETOOTH_CONNECT
|
|
||||||
) == PackageManager.PERMISSION_GRANTED
|
|
||||||
) {
|
|
||||||
|
|
||||||
gatt.writeCharacteristic(char, writeData)
|
gatt.writeCharacteristic(char, writeData)
|
||||||
|
|
||||||
|
|
@ -788,11 +771,7 @@ class BleRepositoryImpl @Inject constructor(
|
||||||
|
|
||||||
Log.d("write", "onCharacteristicWrite $status")
|
Log.d("write", "onCharacteristicWrite $status")
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P || ActivityCompat.checkSelfPermission(
|
if (checkPermission()) {
|
||||||
app,
|
|
||||||
Manifest.permission.BLUETOOTH_CONNECT
|
|
||||||
) == PackageManager.PERMISSION_GRANTED
|
|
||||||
) {
|
|
||||||
|
|
||||||
gatt.close()
|
gatt.close()
|
||||||
|
|
||||||
|
|
@ -816,10 +795,7 @@ class BleRepositoryImpl @Inject constructor(
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P || ActivityCompat.checkSelfPermission(
|
if (checkPermission()) {
|
||||||
app,
|
|
||||||
Manifest.permission.BLUETOOTH_CONNECT
|
|
||||||
) == PackageManager.PERMISSION_GRANTED) {
|
|
||||||
|
|
||||||
bleGatt = device.connectGatt(app, false, callback)
|
bleGatt = device.connectGatt(app, false, callback)
|
||||||
|
|
||||||
|
|
@ -831,12 +807,27 @@ class BleRepositoryImpl @Inject constructor(
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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(
|
fun BluetoothGatt.writeCharacteristic(
|
||||||
characteristic: BluetoothGattCharacteristic,
|
characteristic: BluetoothGattCharacteristic,
|
||||||
data: ByteArray
|
data: ByteArray
|
||||||
){
|
): Result<Unit, BleException>{
|
||||||
|
|
||||||
|
return if(checkPermission()){
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
writeCharacteristic(characteristic, data, BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT)
|
writeCharacteristic(characteristic, data, BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT)
|
||||||
|
|
@ -845,4 +836,12 @@ fun BluetoothGatt.writeCharacteristic(
|
||||||
writeCharacteristic(characteristic)
|
writeCharacteristic(characteristic)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result.success(Unit)
|
||||||
|
|
||||||
|
} else {
|
||||||
|
Result.failure(BleException.PermissionDenied)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -47,11 +47,7 @@ class ReadHistoryCallback(
|
||||||
|
|
||||||
if(newState == BluetoothGatt.STATE_CONNECTED){
|
if(newState == BluetoothGatt.STATE_CONNECTED){
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P || ActivityCompat.checkSelfPermission(
|
if (checkPermission()) {
|
||||||
app,
|
|
||||||
Manifest.permission.BLUETOOTH_CONNECT
|
|
||||||
) == PackageManager.PERMISSION_GRANTED
|
|
||||||
) {
|
|
||||||
gatt.discoverServices()
|
gatt.discoverServices()
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -77,11 +73,7 @@ class ReadHistoryCallback(
|
||||||
if(status == BluetoothGatt.GATT_SUCCESS){
|
if(status == BluetoothGatt.GATT_SUCCESS){
|
||||||
gatt.getService(serviceUUID)?.getCharacteristic(temperatureHistoryReadUUID)?.let {
|
gatt.getService(serviceUUID)?.getCharacteristic(temperatureHistoryReadUUID)?.let {
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P || ActivityCompat.checkSelfPermission(
|
if (checkPermission()) {
|
||||||
app,
|
|
||||||
Manifest.permission.BLUETOOTH_CONNECT
|
|
||||||
) == PackageManager.PERMISSION_GRANTED
|
|
||||||
) {
|
|
||||||
|
|
||||||
readProperty = Property.DATA_SIZE
|
readProperty = Property.DATA_SIZE
|
||||||
gatt.writeCharacteristic(it, byteArrayOf(2))
|
gatt.writeCharacteristic(it, byteArrayOf(2))
|
||||||
|
|
@ -114,9 +106,11 @@ class ReadHistoryCallback(
|
||||||
characteristic: BluetoothGattCharacteristic,
|
characteristic: BluetoothGattCharacteristic,
|
||||||
status: Int
|
status: Int
|
||||||
) {
|
) {
|
||||||
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
|
||||||
super.onCharacteristicRead(gatt, characteristic, status)
|
super.onCharacteristicRead(gatt, characteristic, status)
|
||||||
onCommonCharacteristicRead(gatt, characteristic, characteristic.value, status)
|
onCommonCharacteristicRead(gatt, characteristic, characteristic.value, status)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCharacteristicRead(
|
override fun onCharacteristicRead(
|
||||||
gatt: BluetoothGatt,
|
gatt: BluetoothGatt,
|
||||||
|
|
@ -125,7 +119,7 @@ class ReadHistoryCallback(
|
||||||
status: Int
|
status: Int
|
||||||
) {
|
) {
|
||||||
super.onCharacteristicRead(gatt, characteristic, value, status)
|
super.onCharacteristicRead(gatt, characteristic, value, status)
|
||||||
//onCommonCharacteristicRead(gatt, characteristic, value, status)
|
onCommonCharacteristicRead(gatt, characteristic, value, status)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onCommonCharacteristicRead(
|
private fun onCommonCharacteristicRead(
|
||||||
|
|
@ -137,6 +131,19 @@ class ReadHistoryCallback(
|
||||||
if(status == BluetoothGatt.GATT_SUCCESS){
|
if(status == BluetoothGatt.GATT_SUCCESS){
|
||||||
when(readProperty){
|
when(readProperty){
|
||||||
Property.DATA_SIZE -> {
|
Property.DATA_SIZE -> {
|
||||||
|
|
||||||
|
if(value.contentEquals(byteArrayOf(0, 0))) {
|
||||||
|
onResult(
|
||||||
|
Result.success(
|
||||||
|
ProgressState.Finished(
|
||||||
|
emptyList()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
gatt.close()
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
val writeData = mutableListOf(
|
val writeData = mutableListOf(
|
||||||
1.toByte(),
|
1.toByte(),
|
||||||
0.toByte(),
|
0.toByte(),
|
||||||
|
|
@ -147,6 +154,8 @@ class ReadHistoryCallback(
|
||||||
|
|
||||||
readProperty = Property.PACKAGE
|
readProperty = Property.PACKAGE
|
||||||
gatt.writeCharacteristic(characteristic, writeData)
|
gatt.writeCharacteristic(characteristic, writeData)
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Property.PACKAGE -> {
|
Property.PACKAGE -> {
|
||||||
|
|
||||||
|
|
@ -177,11 +186,7 @@ class ReadHistoryCallback(
|
||||||
if(nextPackageDataCount != 0.toUByte()){
|
if(nextPackageDataCount != 0.toUByte()){
|
||||||
|
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P || ActivityCompat.checkSelfPermission(
|
if (checkPermission()) {
|
||||||
app,
|
|
||||||
Manifest.permission.BLUETOOTH_CONNECT
|
|
||||||
) == PackageManager.PERMISSION_GRANTED
|
|
||||||
) {
|
|
||||||
|
|
||||||
gatt.writeCharacteristic(characteristic, byteArrayOf(5))
|
gatt.writeCharacteristic(characteristic, byteArrayOf(5))
|
||||||
gatt.readCharacteristic(characteristic)
|
gatt.readCharacteristic(characteristic)
|
||||||
|
|
@ -209,7 +214,7 @@ class ReadHistoryCallback(
|
||||||
gatt.close()
|
gatt.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} else {
|
||||||
|
|
||||||
if (value[0] == 251.toByte()) {
|
if (value[0] == 251.toByte()) {
|
||||||
|
|
||||||
|
|
@ -246,6 +251,11 @@ class ReadHistoryCallback(
|
||||||
)
|
)
|
||||||
gatt.close()
|
gatt.close()
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
onResult(Result.failure(BleException.UnexpectedResponse))
|
||||||
|
gatt.close()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
|
|
@ -267,11 +277,7 @@ class ReadHistoryCallback(
|
||||||
super.onCharacteristicWrite(gatt, characteristic, status)
|
super.onCharacteristicWrite(gatt, characteristic, status)
|
||||||
if(status == BluetoothGatt.GATT_SUCCESS){
|
if(status == BluetoothGatt.GATT_SUCCESS){
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P || ActivityCompat.checkSelfPermission(
|
if (checkPermission()) {
|
||||||
app,
|
|
||||||
Manifest.permission.BLUETOOTH_CONNECT
|
|
||||||
) == PackageManager.PERMISSION_GRANTED
|
|
||||||
) {
|
|
||||||
|
|
||||||
gatt.readCharacteristic(characteristic)
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
package llc.arma.ble.domain.model
|
||||||
|
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
|
class ConnectedBleInfo(
|
||||||
|
val name: String,
|
||||||
|
val serial: String,
|
||||||
|
)
|
||||||
|
|
@ -6,10 +6,13 @@ import llc.arma.ble.domain.common.BleException
|
||||||
import llc.arma.ble.domain.common.ProgressState
|
import llc.arma.ble.domain.common.ProgressState
|
||||||
import llc.arma.ble.domain.model.Ble
|
import llc.arma.ble.domain.model.Ble
|
||||||
import llc.arma.ble.domain.model.BleInfo
|
import llc.arma.ble.domain.model.BleInfo
|
||||||
|
import llc.arma.ble.domain.model.ConnectedBleInfo
|
||||||
import llc.arma.ble.domain.usecase.GetBleBySerial
|
import llc.arma.ble.domain.usecase.GetBleBySerial
|
||||||
|
|
||||||
interface BleRepository {
|
interface BleRepository {
|
||||||
|
|
||||||
|
fun getConnectedBle(): List<ConnectedBleInfo>
|
||||||
|
|
||||||
fun getBleAroundFlow(): Flow<Result<List<BleInfo>, BleException>>
|
fun getBleAroundFlow(): Flow<Result<List<BleInfo>, BleException>>
|
||||||
|
|
||||||
suspend fun getBleBySerial(serial: String): Result<Ble, GetBleBySerial.GetBleException>
|
suspend fun getBleBySerial(serial: String): Result<Ble, GetBleBySerial.GetBleException>
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue