Поправки по графикам
This commit is contained in:
parent
4528a7cd9a
commit
d974df953d
|
|
@ -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"
|
||||
|
||||
}
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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<AxisPosition.Horizontal.Bottom> { 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)
|
||||
}
|
||||
}*/
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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<Float> = 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
|
||||
)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue