diff --git a/app/build.gradle b/app/build.gradle index 5b870cc..de104bc 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -13,8 +13,8 @@ android { applicationId "llc.arma.ble" minSdk 24 targetSdk 33 - versionCode 2 - versionName "1.1" + versionCode 4 + versionName "1.2.1" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables { @@ -46,6 +46,13 @@ android { excludes += '/META-INF/{AL2.0,LGPL2.1}' } } + + applicationVariants.all { variant -> + variant.outputs.all { + outputFileName = "Arma BLE v${defaultConfig.versionName}.apk" + } + } + } dependencies { @@ -76,8 +83,8 @@ dependencies { implementation "com.google.accompanist:accompanist-permissions:0.26.3-beta" - implementation "com.patrykandpatrick.vico:core:1.6.6" - implementation "com.patrykandpatrick.vico:compose:1.6.6" - implementation "com.patrykandpatrick.vico:compose-m3:1.6.6" + implementation "com.patrykandpatrick.vico:core:1.7.1" + implementation "com.patrykandpatrick.vico:compose:1.7.1" + implementation "com.patrykandpatrick.vico:compose-m3:1.7.1" } \ No newline at end of file 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 2faaba7..34e8ab4 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 @@ -122,7 +122,14 @@ fun BleListScreen( } ) - if(state.bleList.isEmpty()){ + val filteredData = state.bleList.filter { + (it.type == state.filter.bleType || state.filter.bleType == null) && + it.name.contains(state.filter.name) && + it.serial.contains(state.filter.mac) && + state.filter.rssi.contains(it.rssi?.toFloat() ?: Float.MIN_VALUE) + } + + if(filteredData.isEmpty()){ LinearProgressIndicator( strokeCap = StrokeCap.Round, modifier = Modifier @@ -131,37 +138,44 @@ fun BleListScreen( ) } - LazyColumn( - verticalArrangement = Arrangement.spacedBy(8.dp), - modifier = Modifier.fillMaxSize() - ) { + if(filteredData.isEmpty()){ - items(items = state.connectedBleList){ + Box(modifier = Modifier.fillMaxSize()){ + Text( + modifier = Modifier.align(Alignment.Center), + style = MaterialTheme.typography.titleMedium, + text = "Метки в области не найдены" + ) + } + + } else { + LazyColumn( + verticalArrangement = Arrangement.spacedBy(8.dp), + modifier = Modifier.fillMaxSize() + ) { + + items(items = state.connectedBleList){ + + ConnectedBleItem(ble = it) { + viewModel.setEvent(BleListContract.Event.OnConnectToBle(it.serial)) + } + + } + + + + items(items = filteredData.sortedBy { it.name }.reversed()) { + + BleItem( + ble = it, + onClick = { + viewModel.setEvent(BleListContract.Event.OnConnectToBle(it.serial)) + } + ) - ConnectedBleItem(ble = it) { - viewModel.setEvent(BleListContract.Event.OnConnectToBle(it.serial)) } } - - val filteredData = state.bleList.filter { - (it.type == state.filter.bleType || state.filter.bleType == null) && - it.name.contains(state.filter.name) && - it.serial.contains(state.filter.mac) && - state.filter.rssi.contains(it.rssi?.toFloat() ?: Float.MIN_VALUE) - } - - items(items = filteredData.sortedBy { it.name }.reversed()) { - - BleItem( - ble = it, - onClick = { - viewModel.setEvent(BleListContract.Event.OnConnectToBle(it.serial)) - } - ) - - } - } } @@ -374,12 +388,6 @@ private fun BleItem( modifier = Modifier.alpha(0.7f) ) { - val color = if(ble.batteryLevel < 100){ - MaterialTheme.colorScheme.error - } else { - LocalContentColor.current - } - Icon( modifier = Modifier.size(16.dp), imageVector = Icons.Rounded.ArrowRightAlt, diff --git a/app/src/main/java/llc/arma/ble/app/ui/screen/inspection/accelerometer/view/AcceleromterHistory.kt b/app/src/main/java/llc/arma/ble/app/ui/screen/inspection/accelerometer/view/AcceleromterHistory.kt index 29644f7..b0a97a5 100644 --- a/app/src/main/java/llc/arma/ble/app/ui/screen/inspection/accelerometer/view/AcceleromterHistory.kt +++ b/app/src/main/java/llc/arma/ble/app/ui/screen/inspection/accelerometer/view/AcceleromterHistory.kt @@ -3,6 +3,7 @@ package llc.arma.ble.app.ui.screen.inspection.accelerometer.view import androidx.compose.animation.core.FastOutSlowInEasing import androidx.compose.animation.core.animateFloatAsState import androidx.compose.animation.core.tween +import androidx.compose.foundation.gestures.detectTransformGestures import androidx.compose.foundation.gestures.scrollBy import androidx.compose.foundation.layout.* import androidx.compose.material3.* @@ -27,12 +28,15 @@ import llc.arma.ble.domain.model.BleInfo import javax.inject.Inject import androidx.compose.material.icons.Icons import androidx.compose.material.icons.rounded.Refresh +import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.StrokeCap +import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.text.style.TextAlign import com.patrykandpatrick.vico.compose.chart.column.columnChart 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.component.shape.LineComponent import com.patrykandpatrick.vico.core.entry.ChartEntry import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach @@ -157,15 +161,28 @@ fun Display( AxisValueFormatter { value, chartValues -> (chartValues.chartEntryModel.entries.firstOrNull() ?.getOrNull(value.toInt()) as? AccelerometerEntry) - ?.frequency?.toString() + ?.frequency?.let { it.toFloat() / 16f }?.toString() .orEmpty() } - val lineChart = columnChart() + 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, @@ -175,12 +192,13 @@ fun Display( valueFormatter = axisValueFormatter, labelRotationDegrees = -90f, ), - modifier = Modifier.fillMaxSize(), + modifier = Modifier.fillMaxSize() ) - LaunchedEffect(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 53bc0e5..0336963 100644 --- a/app/src/main/java/llc/arma/ble/data/BleRepositoryImpl.kt +++ b/app/src/main/java/llc/arma/ble/data/BleRepositoryImpl.kt @@ -57,6 +57,10 @@ fun UByteArray.toTemperature(): Float { return result } +fun ByteArray.get2byteUIntAt(idx: Int) = + ((this[idx + 1].toUInt() and 0xFFu) shl 8) or + (this[idx].toUInt() and 0xFFu) + @Singleton class BleRepositoryImpl @Inject constructor( private val app: Application @@ -510,6 +514,54 @@ class BleRepositoryImpl @Inject constructor( if (checkPermission()) { + writeCharacteristic( + device = it, + serviceId = serviceUUID, + characteristicId = accelerometerReadUUID, + writeData = byteArrayOf(4, 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("a 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, ReadAccelerometerHistoryCallback(app) { CoroutineScope(Dispatchers.IO).launch { send(it) diff --git a/app/src/main/java/llc/arma/ble/data/ReadAcceleromterHistoryCallback.kt b/app/src/main/java/llc/arma/ble/data/ReadAcceleromterHistoryCallback.kt index 28955ec..d9acceb 100644 --- a/app/src/main/java/llc/arma/ble/data/ReadAcceleromterHistoryCallback.kt +++ b/app/src/main/java/llc/arma/ble/data/ReadAcceleromterHistoryCallback.kt @@ -13,6 +13,8 @@ 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 java.nio.ByteBuffer +import java.nio.ByteOrder.LITTLE_ENDIAN class ReadAccelerometerHistoryCallback( private val app: Application, @@ -29,6 +31,12 @@ class ReadAccelerometerHistoryCallback( ((this[idx + 1].toUInt() and 0xFFu) shl 8) or (this[idx].toUInt() and 0xFFu) + private fun ByteArray.get2byteShortAt(idx: Int): Int { + val shorts = ShortArray(1) + ByteBuffer.wrap(this).order(LITTLE_ENDIAN).asShortBuffer()[shorts] + return shorts[0].toInt()//(this[0].toInt() + (this[1].toInt() shl 8)).toShort() + } + private var readProperty: Property? = null init { @@ -97,11 +105,11 @@ class ReadAccelerometerHistoryCallback( } - private var lastMeasureSystemTime: Long? = null + //private var lastMeasureSystemTime: Long? = null - private var bleMeasureInterval: Long? = null - private var bleRealTime: Long? = null - private var bleLastMeasureTime: Long? = null + private var initialValue: Long? = null + //private var bleRealTime: Long? = null + private var frequencyInterval: Long? = null private val resultAccelerometerPackage: MutableList = mutableListOf() @@ -171,23 +179,20 @@ class ReadAccelerometerHistoryCallback( if(value[0] == 250.toByte()){ - bleMeasureInterval = value.get4byteUIntAt(4).toLong() - bleLastMeasureTime = value.get4byteUIntAt(8).toLong() - bleRealTime = value.get4byteUIntAt(12).toLong() + initialValue = value.get4byteUIntAt(8).toLong() + frequencyInterval = value.get4byteUIntAt(4).toLong() - lastMeasureSystemTime = ((bleRealTime!! - bleLastMeasureTime!!) * 1_000) - - val accelerometerDataArray = value.toUByteArray().asList().subList(16, value.size) + val accelerometerDataArray = value.asList().subList(16, value.size) resultAccelerometerPackage.addAll( accelerometerDataArray.chunked(2).map { - it.toUByteArray().toTemperature() + it.toByteArray().get2byteShortAt(0).toFloat() }.toMutableList() ) val nextPackageDataCount = value.get2byteUIntAt(2) expectedDataSize = nextPackageDataCount.toInt() + resultAccelerometerPackage.size - Log.d("read", expectedDataSize.toString()) + onResult(Result.success(ProgressState.Progress(0f / expectedDataSize!!.toFloat()))) onResult(Result.success(ProgressState.Progress(resultAccelerometerPackage.size.toFloat() / expectedDataSize!!.toFloat()))) @@ -211,7 +216,7 @@ class ReadAccelerometerHistoryCallback( ProgressState.Finished( resultAccelerometerPackage.withIndex().map { Ble.Accelerometer.MeasurePoint( - frequency = lastMeasureSystemTime!! - (((resultAccelerometerPackage.size - 1) - it.index) * bleMeasureInterval!!), + frequency = frequencyInterval!! * it.index + initialValue!!, value = it.value ) } @@ -226,11 +231,11 @@ class ReadAccelerometerHistoryCallback( if (value[0] == 251.toByte()) { val nextPackageDataCount = value.get2byteUIntAt(2) - val temperatureDataArray = value.toUByteArray().toList().subList(4, value.size) + val temperatureDataArray = value.toList().subList(4, value.size) resultAccelerometerPackage.addAll( temperatureDataArray.chunked(2).map { - it.toUByteArray().toTemperature() + it.toByteArray().get2byteShortAt(0).toFloat() } ) @@ -249,7 +254,7 @@ class ReadAccelerometerHistoryCallback( ProgressState.Finished( resultAccelerometerPackage.withIndex().map { Ble.Accelerometer.MeasurePoint( - frequency = lastMeasureSystemTime!! - (((resultAccelerometerPackage.size - 1) - it.index) * bleMeasureInterval!!), + frequency = frequencyInterval!! * it.index + initialValue!!, value = it.value ) }