Поправки по графикам

This commit is contained in:
Vineyro 2023-07-28 16:57:05 +07:00
parent 62205d27a0
commit bd10b5b6b6
10 changed files with 399 additions and 264 deletions

View File

@ -1,4 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">

View File

@ -13,8 +13,8 @@ android {
applicationId "llc.arma.ble"
minSdk 24
targetSdk 33
versionCode 4
versionName "1.2.1"
versionCode 5
versionName "1.2.2"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {

View File

@ -1,6 +1,8 @@
package llc.arma.ble.app.ui.screen.inspection.accelerometer
import androidx.compose.foundation.layout.Column
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.ModalBottomSheetValue
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
@ -32,6 +34,7 @@ enum class SheetPage {
MEASURE, POWER, WRITE, HISTORY, ACCEL_MODE_EDIT, SPECTRE_MODE_EDIT, SPECTRE_EDIT, FREQUENCY_EDIT, AXIS_EDIT, FFT_MODE_EDIT
}
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun AccelerometerScreen(
ble: Ble.Accelerometer,
@ -42,6 +45,7 @@ fun AccelerometerScreen(
val bottomDialog = rememberBottomDialogState()
LaunchedEffect(ble){
viewModel.setEvent(AccelerometerContract.Event.OnBleChanged(ble))
}
@ -50,6 +54,15 @@ fun AccelerometerScreen(
mutableStateOf<SheetPage?>(null)
}
LaunchedEffect(
key1 = bottomDialog.sheetState?.currentValue,
block = {
if(bottomDialog.sheetState?.currentValue == ModalBottomSheetValue.Hidden) {
sheetPage = null
}
}
)
val scope = rememberCoroutineScope()
LaunchedEffect(sheetPage) {

View File

@ -86,47 +86,6 @@ fun AccelSpectreEdit(
modifier = Modifier
) {
Box(
modifier = Modifier.padding(
vertical = 8.dp,
horizontal = 8.dp
)
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.clip(RoundedCornerShape(16.dp))
.clickable {
onEvent(AccelerometerContract.Event.OnAccelViewModeEdit(next = AccelerometerContract.Event.OnAccelViewModeEdit.Next.SPECTRE))
}
.padding(8.dp)
) {
Column(
modifier = Modifier.weight(1f)
) {
Text(
text = "Accel view mode"
)
Text(
color = MaterialTheme.colorScheme.secondary,
style = MaterialTheme.typography.bodyMedium,
text = accelMode.localized
)
}
Icon(
imageVector = Icons.Rounded.KeyboardArrowDown,
contentDescription = null
)
}
}
Box(
modifier = Modifier.padding(
vertical = 8.dp,

View File

@ -33,6 +33,9 @@ import com.patrykandpatrick.vico.compose.chart.scroll.rememberChartScrollState
import com.patrykandpatrick.vico.core.axis.AxisPosition
import com.patrykandpatrick.vico.core.axis.formatter.AxisValueFormatter
import com.patrykandpatrick.vico.core.entry.ChartEntry
import com.patrykandpatrick.vico.core.entry.FloatEntry
import com.patrykandpatrick.vico.core.extension.sumByFloat
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import llc.arma.ble.domain.common.ProgressState
@ -82,23 +85,67 @@ fun AccelerometerHistory(
val title = when(state){
is AccelerometerHistoryContract.State.Display -> {
when (state.loadingHistoryState) {
is ProgressState.Finished -> "${fftMode.localized} (${state.loadingHistoryState.data.size})"
else -> fftMode.localized
if (state.previousHistory !== null) {
"${fftMode.localized} (${state.previousHistory.size})"
}else {
fftMode.localized
}
}
AccelerometerHistoryContract.State.Exception -> fftMode.localized
}
Text(
Row(
modifier = Modifier.weight(1f),
text = title,
style = MaterialTheme.typography.titleLarge
)
verticalAlignment = Alignment.CenterVertically
) {
Text(
modifier = Modifier.padding(end = 16.dp),
text = title,
style = MaterialTheme.typography.titleLarge
)
if(state is AccelerometerHistoryContract.State.Display) {
when (state.loadingHistoryState) {
is ProgressState.Indeterminate -> {
CircularProgressIndicator(
modifier = Modifier.size(16.dp),
strokeWidth = 2.dp,
strokeCap = StrokeCap.Round,
)
}
is ProgressState.Progress -> {
val progressAnimDuration = 1500
val progressAnimation by animateFloatAsState(
targetValue = state.loadingHistoryState.value,
animationSpec = tween(
durationMillis = progressAnimDuration,
easing = FastOutSlowInEasing
)
)
CircularProgressIndicator(
modifier = Modifier.size(16.dp),
strokeWidth = 2.dp,
strokeCap = StrokeCap.Round,
progress = progressAnimation,
)
}
else -> {}
}
}
}
IconButton(
onClick = {
viewModel.setEvent(AccelerometerHistoryContract.Event.OnRefreshHistory(ble.serial, accelMode, fftAxis, fftMode, frequency, accelScale))
viewModel.setEvent(AccelerometerHistoryContract.Event.OnStart(ble.serial, accelMode, fftAxis, fftMode, frequency, accelScale))
},
enabled = when(state){
is AccelerometerHistoryContract.State.Display -> state.loadingHistoryState is ProgressState.Finished
@ -127,7 +174,14 @@ fun AccelerometerHistory(
}
}
val axisValueFormatter = AxisValueFormatter<AxisPosition.Horizontal.Bottom> { value, chartValues ->
(chartValues.chartEntryModel.entries.firstOrNull()
?.getOrNull(value.toInt()) as? AccelerometerEntry)
?.frequency?.let { String.format("%.1f", (it.toFloat() / 256f)) }
.orEmpty()
}
@Composable
fun Display(
@ -139,100 +193,89 @@ fun Display(
.fillMaxSize()
) {
when (state.loadingHistoryState) {
val data = if(state.loadingHistoryState is ProgressState.Finished){
state.loadingHistoryState.data
} else {
state.previousHistory
}
is ProgressState.Finished -> {
val producer = remember {
ChartEntryModelProducer(listOf<FloatEntry>())
}
if(state.loadingHistoryState.data.isEmpty()){
if(data != null){
Text(
modifier = Modifier.align(Alignment.Center),
text = "Нет данных"
)
if(data.isEmpty()){
} else {
Text(
modifier = Modifier.align(Alignment.Center),
text = "Нет данных"
)
val producer = remember(state.loadingHistoryState.data) {
state.loadingHistoryState.data.mapIndexed { index, measurePoint ->
} else {
LaunchedEffect(data){
producer.setEntries(
data.mapIndexed { index, measurePoint ->
AccelerometerEntry(measurePoint.frequency, index.toFloat(), measurePoint.value)
}.let {
ChartEntryModelProducer(it)
}
}
val axisValueFormatter =
AxisValueFormatter<AxisPosition.Horizontal.Bottom> { value, chartValues ->
(chartValues.chartEntryModel.entries.firstOrNull()
?.getOrNull(value.toInt()) as? AccelerometerEntry)
?.frequency?.let { String.format("%.1f", (it.toFloat() / 256f)) }
.orEmpty()
}
val lineChart = columnChart(
spacing = 1.5.dp
)
LaunchedEffect(state.loadingHistoryState.data){
lineChart.bounds
lineChart.setBounds(
left = lineChart.bounds.left / 20,
top = lineChart.bounds.top,
right = lineChart.bounds.right / 20,
bottom = lineChart.bounds.bottom,
)
}
val scrollState = rememberChartScrollState()
Chart(
isZoomEnabled = true,
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)
}*/
}
}
is ProgressState.Indeterminate -> {
CircularProgressIndicator(
strokeCap = StrokeCap.Round,
modifier = Modifier.align(Alignment.Center)
val lineChart = columnChart(
spacing = 1.5.dp
)
}
is ProgressState.Progress -> {
val scrollState = rememberChartScrollState()
val progressAnimDuration = 1500
val progressAnimation by animateFloatAsState(
targetValue = state.loadingHistoryState.value,
animationSpec = tween(
durationMillis = progressAnimDuration,
easing = FastOutSlowInEasing
Chart(
diffAnimationSpec = tween(0),
isZoomEnabled = true,
chartScrollState = scrollState,
chart = lineChart,
chartModelProducer = producer,
startAxis = startAxis(),
bottomAxis = bottomAxis(
tickLength = 0.dp,
valueFormatter = axisValueFormatter,
labelRotationDegrees = -90f,
),
modifier = Modifier.fillMaxSize()
)
}
} else {
when (state.loadingHistoryState) {
is ProgressState.Indeterminate -> {
CircularProgressIndicator(
strokeCap = StrokeCap.Round,
modifier = Modifier.align(Alignment.Center)
)
)
CircularProgressIndicator(
strokeCap = StrokeCap.Round,
progress = progressAnimation,
modifier = Modifier.align(Alignment.Center)
)
}
is ProgressState.Progress -> {
val progressAnimDuration = 1500
val progressAnimation by animateFloatAsState(
targetValue = state.loadingHistoryState.value,
animationSpec = tween(
durationMillis = progressAnimDuration,
easing = FastOutSlowInEasing
)
)
CircularProgressIndicator(
strokeCap = StrokeCap.Round,
progress = progressAnimation,
modifier = Modifier.align(Alignment.Center)
)
}
else -> {}
}
}
}
@ -286,6 +329,7 @@ class AccelerometerHistoryContract {
sealed class State : ViewState {
data class Display(
val previousHistory : List<Ble.Accelerometer.MeasurePoint>?,
val loadingHistoryState : ProgressState<List<Ble.Accelerometer.MeasurePoint>>
) : State()
@ -306,10 +350,12 @@ class AccelerometerHistoryViewModel @Inject constructor(
private val getAccelerometerSpectreBySerial: GetAccelerometerSpectreBySerial
) : BaseViewModel<AccelerometerHistoryContract.State, AccelerometerHistoryContract.Event, AccelerometerHistoryContract.Effect>() {
private var job: Job? = null
private var lastSerial: String? = null
override fun setInitialState() = AccelerometerHistoryContract.State.Display(
ProgressState.Indeterminate
loadingHistoryState = ProgressState.Indeterminate,
previousHistory = null
)
override fun handleEvents(event: AccelerometerHistoryContract.Event) {
@ -323,44 +369,81 @@ class AccelerometerHistoryViewModel @Inject constructor(
state: AccelerometerHistoryContract.State,
event: AccelerometerHistoryContract.Event.OnStart
) {
viewModelScope.launch {
if(state is AccelerometerHistoryContract.State.Display) {
//if(lastSerial != event.serial) {
lastSerial = event.serial
lastSerial = event.serial
setState {
AccelerometerHistoryContract.State.Display(ProgressState.Indeterminate)
}
setState {
AccelerometerHistoryContract.State.Display(
loadingHistoryState = ProgressState.Indeterminate,
previousHistory = when(state.loadingHistoryState){
is ProgressState.Finished -> state.loadingHistoryState.data
is ProgressState.Indeterminate -> null
is ProgressState.Progress -> null
}
)
}
getAccelerometerSpectreBySerial(
serial = event.serial,
accelMode = event.accelMode,
fftAxis = event.fftAxis,
fftMode = event.fftMode,
frequency = event.frequency,
accelScale = event.accelScale
).onEach {
it.fold(
onSuccess = {
setState {
AccelerometerHistoryContract.State.Display(it)
}
},
onFailure = {
setState {
AccelerometerHistoryContract.State.Exception
}
}
)
}.launchIn(this)
//}
} else {
setState {
AccelerometerHistoryContract.State.Display(
loadingHistoryState = ProgressState.Indeterminate,
previousHistory = null
)
}
}
job?.cancel()
job = getAccelerometerSpectreBySerial(
serial = event.serial,
accelMode = event.accelMode,
fftAxis = event.fftAxis,
fftMode = event.fftMode,
frequency = event.frequency,
accelScale = event.accelScale
).onEach {
val currentState = viewState.value
Log.d("currentState", currentState.toString())
if(currentState is AccelerometerHistoryContract.State.Display) {
it.fold(
onSuccess = {
setState {
AccelerometerHistoryContract.State.Display(
loadingHistoryState = it,
previousHistory = when (it) {
is ProgressState.Finished -> {
it.data
}
is ProgressState.Indeterminate -> currentState.previousHistory
is ProgressState.Progress -> currentState.previousHistory
}
)
}
},
onFailure = {
setState {
AccelerometerHistoryContract.State.Exception
}
}
)
}
}.launchIn(this)
}
}
@ -369,7 +452,7 @@ class AccelerometerHistoryViewModel @Inject constructor(
state: AccelerometerHistoryContract.State,
event: AccelerometerHistoryContract.Event.OnRefreshHistory
) {
viewModelScope.launch {
/*viewModelScope.launch {
setState {
AccelerometerHistoryContract.State.Display(ProgressState.Indeterminate)
@ -397,7 +480,7 @@ class AccelerometerHistoryViewModel @Inject constructor(
)
}.launchIn(this)
}
}*/
}
}

View File

@ -381,7 +381,7 @@ class AccelerometerMeasureViewModel @Inject constructor(
z = ((9806.65f / (Short.MAX_VALUE / 2)) * it.z) * (accelScale.k / 2)
)
)
}
}.takeLast(10)
AccelerometerMeasureContract.State.Display(dataList)
}

View File

@ -579,63 +579,9 @@ class BleRepositoryImpl @Inject constructor(
if (checkPermission()) {
writeCharacteristic(
device = it,
serviceId = serviceUUID,
characteristicId = accelerometerReadUUID,
writeData = byteArrayOf(
4,
accelMode.sendData,
accelScale.sendData,
fftMode.sendData,
fftAxis.sendData,
frequency.sendData,
1
)
).onFailure {
CoroutineScope(Dispatchers.IO).launch {
send(Result.failure(BleException.PermissionDenied))
}
}
var result = false
while (result.not()){
writeCharacteristic(
device = it,
serviceId = serviceUUID,
characteristicId = accelerometerReadUUID,
writeData = byteArrayOf(4, 0)
).onFailure {
CoroutineScope(Dispatchers.IO).launch {
send(Result.failure(BleException.PermissionDenied))
}
}
readCharacteristic(
device = it,
serviceId = serviceUUID,
characteristicId = accelerometerReadUUID
).fold(
onSuccess = { readData ->
Log.d("read", readData.joinToString(", "))
if(readData.isNotEmpty() && readData.first() == (0).toByte()){
result = true
} else {
delay(200)
}
},
onFailure = {
CoroutineScope(Dispatchers.IO).launch {
send(Result.failure(BleException.PermissionDenied))
}
}
)
}
gatt = it.connectGatt(app, false, ReadAccelerometerSpectreCallback(app) {
gatt = it.connectGatt(app, false, ReadAccelerometerSpectreCallback(
app, accelScale, accelMode, fftAxis, fftMode, frequency
) {
CoroutineScope(Dispatchers.IO).launch {
send(it)
}
@ -919,8 +865,6 @@ class BleRepositoryImpl @Inject constructor(
) {
super.onServicesDiscovered(gatt, status)
Log.d("read", "onServicesDiscovered $status")
if (status == BluetoothGatt.GATT_SUCCESS) {
gatt.services?.firstOrNull { service ->
@ -1068,8 +1012,6 @@ class BleRepositoryImpl @Inject constructor(
) {
super.onServicesDiscovered(gatt, status)
Log.d("write", "onServicesDiscovered $status")
if (status == BluetoothGatt.GATT_SUCCESS) {
gatt.services?.firstOrNull { service ->
@ -1114,8 +1056,6 @@ class BleRepositoryImpl @Inject constructor(
) {
super.onCharacteristicWrite(gatt, characteristic, status)
Log.d("write", "onCharacteristicWrite $status")
if (checkPermission()) {
gatt.close()

View File

@ -67,6 +67,8 @@ class ReadAccelerometerCallback(
) {
super.onServicesDiscovered(gatt, status)
Log.d("accel", "onServicesDiscovered")
if(status == BluetoothGatt.GATT_SUCCESS){
gatt.getService(serviceUUID)?.getCharacteristic(accelerometerReadUUID)?.let {
@ -80,11 +82,9 @@ class ReadAccelerometerCallback(
fftMode.sendData,
fftAxis.sendData,
frequency.sendData,
2
1
)
Log.d("payload", payload.joinToString(" - "))
gatt.writeCharacteristic(it, payload)
} else {
@ -107,14 +107,14 @@ class ReadAccelerometerCallback(
) {
super.onCharacteristicWrite(gatt, characteristic, status)
Log.d("accel", "request written")
if(status == BluetoothGatt.GATT_SUCCESS){
gatt.getService(serviceUUID)?.getCharacteristic(accelerometerReadUUID)?.let {
if (checkPermission()) {
Log.d("write", "enable notifications")
gatt.setCharacteristicNotification(it, true)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
@ -162,6 +162,8 @@ class ReadAccelerometerCallback(
value: ByteArray,
){
Log.d("accel", "notification")
val data = value.toList().chunked(2).map {
it.toByteArray().get2byteShortAt(0)
}

View File

@ -5,6 +5,7 @@ import android.app.Application
import android.bluetooth.BluetoothGatt
import android.bluetooth.BluetoothGattCallback
import android.bluetooth.BluetoothGattCharacteristic
import android.bluetooth.BluetoothGattDescriptor
import android.content.pm.PackageManager
import android.os.Build
import android.util.Log
@ -13,8 +14,14 @@ import llc.arma.ble.domain.Result
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.usecase.AccelScale
import llc.arma.ble.domain.usecase.AccelViewMode
import llc.arma.ble.domain.usecase.FftAxis
import llc.arma.ble.domain.usecase.FftFrequency
import llc.arma.ble.domain.usecase.FftViewMode
import java.nio.ByteBuffer
import java.nio.ByteOrder.LITTLE_ENDIAN
import java.util.UUID
fun ByteArray.get2byteShortAt(idx: Int): Int {
val shorts = ShortArray(1)
@ -22,11 +29,21 @@ fun ByteArray.get2byteShortAt(idx: Int): Int {
return shorts[0].toInt()//(this[0].toInt() + (this[1].toInt() shl 8)).toShort()
}
class ReadAccelerometerSpectreCallback(
private val app: Application,
private val accelScale: AccelScale,
private val accelMode: AccelViewMode,
private val fftAxis: FftAxis,
private val fftMode: FftViewMode,
private val frequency: FftFrequency,
private val onResult: (Result<ProgressState<List<Ble.Accelerometer.MeasurePoint>>, BleException>) -> Unit
) : BluetoothGattCallback() {
enum class Property {
DATA_SIZE, PACKAGE
}
private fun ByteArray.get4byteUIntAt(idx: Int) =
((this[idx + 3].toUInt() and 0xFFu) shl 24) or
((this[idx + 2].toUInt() and 0xFFu) shl 16) or
@ -50,13 +67,17 @@ class ReadAccelerometerSpectreCallback(
) {
super.onConnectionStateChange(gatt, status, newState)
Log.d("spectre", "onConnectionStateChange")
if(status == BluetoothGatt.GATT_SUCCESS){
if(newState == BluetoothGatt.STATE_CONNECTED){
if (checkPermission()) {
gatt.discoverServices()
} else {
onResult(Result.failure(BleException.UnexpectedResponse))
gatt.close()
@ -77,38 +98,52 @@ class ReadAccelerometerSpectreCallback(
status: Int
) {
super.onServicesDiscovered(gatt, status)
Log.d("read", "discover ${status}")
Log.d("spectre", "onServicesDiscovered")
if(status == BluetoothGatt.GATT_SUCCESS){
gatt.getService(serviceUUID)?.getCharacteristic(accelerometerHistoryReadUUID)?.let {
if (checkPermission()) {
Log.d("read", "discovered")
readProperty = Property.DATA_SIZE
gatt.writeCharacteristic(it, byteArrayOf(2))
} else {
onResult(Result.failure(BleException.PermissionDenied))
gatt.close()
}
return
}
onResult(Result.failure(BleException.UnexpectedResponse))
enableNotifications(gatt)
}
}
//private var lastMeasureSystemTime: Long? = null
private fun enableNotifications(
gatt: BluetoothGatt
){
gatt.getService(serviceUUID)?.getCharacteristic(accelerometerReadUUID)?.let {
if (checkPermission()) {
gatt.setCharacteristicNotification(it, true)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
gatt.writeDescriptor(it.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb")),
BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE)
} else {
val descriptor = it.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"))
descriptor.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE
gatt.writeDescriptor(descriptor)
}
Log.d("spectre", "enable notification")
onResult(Result.success(ProgressState.Indeterminate))
resultAccelerometerPackage.clear()
} else {
onResult(Result.failure(BleException.PermissionDenied))
gatt.close()
}
return
}
onResult(Result.failure(BleException.UnexpectedResponse))
}
private var initialValue: Long? = null
//private var bleRealTime: Long? = null
private var frequencyInterval: Long? = null
private val resultAccelerometerPackage: MutableList<Float> = mutableListOf()
@ -127,6 +162,42 @@ class ReadAccelerometerSpectreCallback(
}
}
@Deprecated("Deprecated in Java")
override fun onCharacteristicChanged(
gatt: BluetoothGatt,
characteristic: BluetoothGattCharacteristic
) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
super.onCharacteristicChanged(gatt, characteristic)
onCommonCharacteristicChanged(gatt, characteristic, characteristic.value)
}
}
override fun onCharacteristicChanged(
gatt: BluetoothGatt,
characteristic: BluetoothGattCharacteristic,
value: ByteArray
) {
super.onCharacteristicChanged(gatt, characteristic, value)
onCommonCharacteristicChanged(gatt, characteristic, value)
}
private fun onCommonCharacteristicChanged(
gatt: BluetoothGatt,
characteristic: BluetoothGattCharacteristic,
value: ByteArray,
){
if(characteristic.uuid == accelerometerReadUUID) {
Log.d("spectre", "changed")
readProperty = Property.DATA_SIZE
gatt.getService(serviceUUID).getCharacteristic(accelerometerHistoryReadUUID)?.let {
gatt.writeCharacteristic(it, byteArrayOf(2))
}
}
}
override fun onCharacteristicRead(
gatt: BluetoothGatt,
characteristic: BluetoothGattCharacteristic,
@ -144,6 +215,8 @@ class ReadAccelerometerSpectreCallback(
status: Int
){
Log.d("spectre", "onCharacteristicRead")
if(status == BluetoothGatt.GATT_SUCCESS){
when(readProperty){
Property.DATA_SIZE -> {
@ -209,6 +282,7 @@ class ReadAccelerometerSpectreCallback(
}
} else {
onResult(
Result.success(
ProgressState.Finished(
@ -221,7 +295,9 @@ class ReadAccelerometerSpectreCallback(
)
)
)
gatt.close()
start(gatt)
}
} else {
@ -247,6 +323,7 @@ class ReadAccelerometerSpectreCallback(
gatt.readCharacteristic(characteristic)
} else {
onResult(
Result.success(
ProgressState.Finished(
@ -259,7 +336,9 @@ class ReadAccelerometerSpectreCallback(
)
)
)
gatt.close()
start(gatt)
}
} else {
onResult(Result.failure(BleException.UnexpectedResponse))
@ -285,11 +364,73 @@ class ReadAccelerometerSpectreCallback(
status: Int
) {
super.onCharacteristicWrite(gatt, characteristic, status)
if(status == BluetoothGatt.GATT_SUCCESS){
Log.d("spectre", "request written $readProperty")
if(readProperty !== null) {
if (status == BluetoothGatt.GATT_SUCCESS) {
if (checkPermission()) {
gatt.readCharacteristic(characteristic)
} else {
onResult(Result.failure(BleException.PermissionDenied))
gatt.close()
}
} else {
onResult(Result.failure(BleException.UnexpectedResponse))
gatt.close()
}
}
}
override fun onMtuChanged(gatt: BluetoothGatt?, mtu: Int, status: Int) {
super.onMtuChanged(gatt, mtu, status)
Log.d("spectre", "mtu $mtu")
}
override fun onDescriptorWrite(
gatt: BluetoothGatt,
descriptor: BluetoothGattDescriptor,
status: Int
) {
Log.d("spectre", "descriptor written")
super.onDescriptorWrite(gatt, descriptor, status)
start(gatt)
}
private fun start(
gatt: BluetoothGatt,
){
Log.d("spectre", "start")
gatt.getService(serviceUUID)?.getCharacteristic(accelerometerReadUUID)?.let {
if (checkPermission()) {
gatt.readCharacteristic(characteristic)
val payload = byteArrayOf(
4,
accelMode.sendData,
accelScale.sendData,
fftMode.sendData,
fftAxis.sendData,
frequency.sendData,
2
)
readProperty = null
gatt.writeCharacteristic(it, payload)
onResult(Result.success(ProgressState.Indeterminate))
resultAccelerometerPackage.clear()
} else {
@ -298,14 +439,13 @@ class ReadAccelerometerSpectreCallback(
}
} else {
onResult(Result.failure(BleException.UnexpectedResponse))
gatt.close()
return
}
}
fun checkPermission(): Boolean {
private fun checkPermission(): Boolean {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
ActivityCompat.checkSelfPermission(app, Manifest.permission.BLUETOOTH_CONNECT) ==
@ -320,7 +460,7 @@ class ReadAccelerometerSpectreCallback(
}
}
fun BluetoothGatt.writeCharacteristic(
private fun BluetoothGatt.writeCharacteristic(
characteristic: BluetoothGattCharacteristic,
data: ByteArray
): Result<Unit, BleException>{

View File

@ -133,7 +133,6 @@ class ReadHistoryCallback(
value: ByteArray,
status: Int
){
Log.d("read", value[0].toString())
if(status == BluetoothGatt.GATT_SUCCESS){
when(readProperty){