This commit is contained in:
Vineyro 2023-10-06 17:00:23 +07:00
parent 0133326481
commit 54fb528400
15 changed files with 238 additions and 108 deletions

View File

@ -13,8 +13,8 @@ android {
applicationId "llc.arma.ble"
minSdk 24
targetSdk 33
versionCode 7
versionName "1.2.7"
versionCode 8
versionName "1.2.8"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {

View File

@ -40,7 +40,7 @@ class BleMapper @Inject constructor(
),
accelerometerState = BleView.Accelerometer.AccelerometerState(
saveHistory = input.accelerometerState.saveHistory,
historyInterval = input.accelerometerState.historyInterval,
historyInterval = input.accelerometerState.historyInterval
)
)
}

View File

@ -20,9 +20,8 @@ sealed class BleView(
class AccelerometerState(
saveHistory: Ble.Accelerometer.History,
historyInterval: Long
historyInterval: Long,
) {
var saveHistory by mutableStateOf(saveHistory)
var historyInterval by mutableStateOf(historyInterval)

View File

@ -114,7 +114,7 @@ class AccelerometerContract {
val accelScale: AccelScale,
val fftViewMode: FftViewMode,
val fftAxis: FftAxis,
val fftFrequency: FftFrequency
val fftFrequency: FftFrequency,
) : State() {
sealed class WriteState {

View File

@ -85,7 +85,8 @@ class AccelerometerViewModel @Inject constructor(
if(saveHistory is Ble.Accelerometer.History.Enabled){
saveHistory = Ble.Accelerometer.History.Enabled(
mode = event.mode,
scale = saveHistory.scale
scale = saveHistory.scale,
detailed = saveHistory.detailed
)
}
@ -200,7 +201,8 @@ class AccelerometerViewModel @Inject constructor(
state.accelerometer.accelerometerState.saveHistory = Ble.Accelerometer.History.Enabled(
scale = AccelScale.S_2,
mode = AccelViewMode.ACCELERATION
mode = AccelViewMode.ACCELERATION,
detailed = true
)
setEffect {

View File

@ -23,6 +23,7 @@ val AccelViewMode.localized: String
ACCELERATION -> "Ускорение"
PEAK_ACCELERATION -> "Пиковое ускорение"
RMS -> "Среднеквадратичное ускорение"
VIBRATION -> "Вибрация"
ANGLE -> "Угол"
}
}

View File

@ -37,7 +37,7 @@ import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import llc.arma.ble.domain.usecase.AccelScale
import llc.arma.ble.domain.usecase.AccelViewMode
import llc.arma.ble.domain.usecase.Accelerate
import llc.arma.ble.domain.usecase.MeasureData
import llc.arma.ble.domain.usecase.FftAxis
import llc.arma.ble.domain.usecase.FftFrequency
import llc.arma.ble.domain.usecase.FftViewMode
@ -131,6 +131,8 @@ fun Display(
} else {
val xProducer = remember {
ChartEntryModelProducer(listOf<FloatEntry>())
}
@ -144,15 +146,30 @@ fun Display(
}
xProducer.setEntries(state.measureHistory.mapIndexed { index, measurePoint ->
FloatEntry(index.toFloat(), measurePoint.x )
when(measurePoint){
is MeasureData.Accelerate -> {
FloatEntry(index.toFloat(), measurePoint.x )
}
is MeasureData.Vibration -> FloatEntry(index.toFloat(), measurePoint.value)
}
})
yProducer.setEntries(state.measureHistory.mapIndexed { index, measurePoint ->
FloatEntry(index.toFloat(), measurePoint.y)
when(measurePoint){
is MeasureData.Accelerate -> {
FloatEntry(index.toFloat(), measurePoint.y )
}
is MeasureData.Vibration -> FloatEntry(index.toFloat(), measurePoint.value)
}
})
zProducer.setEntries(state.measureHistory.mapIndexed { index, measurePoint ->
FloatEntry(index.toFloat(), measurePoint.z)
when(measurePoint){
is MeasureData.Accelerate -> {
FloatEntry(index.toFloat(), measurePoint.z )
}
is MeasureData.Vibration -> FloatEntry(index.toFloat(), measurePoint.value)
}
})
val lineChart = lineChart(
@ -163,62 +180,91 @@ fun Display(
)
)
Column() {
if(state.measureHistory.lastOrNull() is MeasureData.Accelerate) {
Text(text = "Ось X:")
Column() {
Chart(
chart = lineChart,
chartModelProducer = xProducer,
startAxis = startAxis(),
bottomAxis = bottomAxis(),
modifier = Modifier
.fillMaxWidth()
.weight(1f),
autoScaleUp = AutoScaleUp.None,
diffAnimationSpec = tween(0),
chartScrollSpec = rememberChartScrollSpec(
initialScroll = InitialScroll.End,
autoScrollCondition = AutoScrollCondition.OnModelSizeIncreased,
autoScrollAnimationSpec = tween(0)
Text(text = "Ось X:")
Chart(
chart = lineChart,
chartModelProducer = xProducer,
startAxis = startAxis(),
bottomAxis = bottomAxis(),
modifier = Modifier
.fillMaxWidth()
.weight(1f),
autoScaleUp = AutoScaleUp.None,
diffAnimationSpec = tween(0),
chartScrollSpec = rememberChartScrollSpec(
initialScroll = InitialScroll.End,
autoScrollCondition = AutoScrollCondition.OnModelSizeIncreased,
autoScrollAnimationSpec = tween(0)
)
)
)
Text(text = "Ось Y:")
Chart(
chart = lineChart,
chartModelProducer = yProducer,
startAxis = startAxis(),
bottomAxis = bottomAxis(),
modifier = Modifier
.fillMaxWidth()
.weight(1f),
autoScaleUp = AutoScaleUp.None,
diffAnimationSpec = tween(0),
chartScrollSpec = rememberChartScrollSpec(
initialScroll = InitialScroll.End,
autoScrollCondition = AutoScrollCondition.OnModelSizeIncreased,
autoScrollAnimationSpec = tween(0)
Text(text = "Ось Y:")
Chart(
chart = lineChart,
chartModelProducer = yProducer,
startAxis = startAxis(),
bottomAxis = bottomAxis(),
modifier = Modifier
.fillMaxWidth()
.weight(1f),
autoScaleUp = AutoScaleUp.None,
diffAnimationSpec = tween(0),
chartScrollSpec = rememberChartScrollSpec(
initialScroll = InitialScroll.End,
autoScrollCondition = AutoScrollCondition.OnModelSizeIncreased,
autoScrollAnimationSpec = tween(0)
)
)
)
Text(text = "Ось Z:")
Chart(
chart = lineChart,
chartModelProducer = zProducer,
startAxis = startAxis(),
bottomAxis = bottomAxis(),
modifier = Modifier
.fillMaxWidth()
.weight(1f),
autoScaleUp = AutoScaleUp.None,
diffAnimationSpec = tween(0),
chartScrollSpec = rememberChartScrollSpec(
initialScroll = InitialScroll.End,
autoScrollCondition = AutoScrollCondition.OnModelSizeIncreased,
autoScrollAnimationSpec = tween(0)
Text(text = "Ось Z:")
Chart(
chart = lineChart,
chartModelProducer = zProducer,
startAxis = startAxis(),
bottomAxis = bottomAxis(),
modifier = Modifier
.fillMaxWidth()
.weight(1f),
autoScaleUp = AutoScaleUp.None,
diffAnimationSpec = tween(0),
chartScrollSpec = rememberChartScrollSpec(
initialScroll = InitialScroll.End,
autoScrollCondition = AutoScrollCondition.OnModelSizeIncreased,
autoScrollAnimationSpec = tween(0)
)
)
)
}
} else {
Column {
Text(text = "Вибрация:")
Chart(
chart = lineChart,
chartModelProducer = xProducer,
startAxis = startAxis(),
bottomAxis = bottomAxis(),
modifier = Modifier
.fillMaxWidth()
.weight(1f),
autoScaleUp = AutoScaleUp.None,
diffAnimationSpec = tween(0),
chartScrollSpec = rememberChartScrollSpec(
initialScroll = InitialScroll.End,
autoScrollCondition = AutoScrollCondition.OnModelSizeIncreased,
autoScrollAnimationSpec = tween(0)
)
)
}
}
@ -278,7 +324,7 @@ class AccelerometerAccelContract {
sealed class State : ViewState {
data class Display(
val measureHistory : List<Accelerate>
val measureHistory : List<MeasureData>
) : State()
object Exception : State()
@ -370,18 +416,12 @@ class AccelerometerAccelViewModel @Inject constructor(
setState {
when (this) {
is AccelerometerAccelContract.State.Display -> {
val dataList = this.measureHistory.toMutableList().apply {
add(
Accelerate(
//x = ((9806.65f / (Short.MAX_VALUE / 2)) * it.x) * (accelScale.k / 2),
//y = ((9806.65f / (Short.MAX_VALUE / 2)) * it.y) * (accelScale.k / 2),
//z = ((9806.65f / (Short.MAX_VALUE / 2)) * it.z) * (accelScale.k / 2)
x = it.x,
y = it.y,
z = it.z
)
)
}.takeLast(10)
var dataList = this.measureHistory.toMutableList().apply {
add(it)
}
if(accelMode != AccelViewMode.ANGLE) {
dataList = dataList.takeLast(10).toMutableList()
}
AccelerometerAccelContract.State.Display(dataList)
}

View File

@ -3,7 +3,6 @@ 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.scrollBy
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
@ -30,11 +29,8 @@ import androidx.compose.ui.text.style.TextAlign
import com.patrykandpatrick.vico.compose.axis.horizontal.bottomAxis
import com.patrykandpatrick.vico.compose.chart.line.lineChart
import com.patrykandpatrick.vico.compose.chart.scroll.rememberChartScrollSpec
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.chart.decoration.ThresholdLine
import com.patrykandpatrick.vico.core.chart.scale.AutoScaleUp
import com.patrykandpatrick.vico.core.entry.ChartEntry
import com.patrykandpatrick.vico.core.entry.FloatEntry
import com.patrykandpatrick.vico.core.scroll.AutoScrollCondition
@ -42,19 +38,15 @@ import com.patrykandpatrick.vico.core.scroll.InitialScroll
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import llc.arma.ble.app.ui.screen.inspection.thermometer.view.TemperatureEntry
import llc.arma.ble.app.ui.screen.inspection.thermometer.view.TemperatureHistoryContract
import llc.arma.ble.app.ui.screen.inspection.thermometer.view.formatter
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.Accelerate
import llc.arma.ble.domain.usecase.FftAxis
import llc.arma.ble.domain.usecase.FftFrequency
import llc.arma.ble.domain.usecase.FftViewMode
import llc.arma.ble.domain.usecase.GetAccelerometerHistoryBySerial
import llc.arma.ble.domain.usecase.GetAccelerometerMeasureBySerialFlow
import java.util.Date
class AccelEntry(

View File

@ -12,6 +12,7 @@ import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.RadioButton
import androidx.compose.material3.Surface
import androidx.compose.material3.Switch
import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
@ -33,6 +34,7 @@ fun HistoryEdit(
val history = state.accelerometer.accelerometerState.saveHistory
val detailed = if (history is Ble.Accelerometer.History.Enabled) history.detailed else false
val accelMode = if (history is Ble.Accelerometer.History.Enabled) history.mode else state.accelViewMode
val accelScale = if (history is Ble.Accelerometer.History.Enabled) history.scale else state.accelScale

View File

@ -25,7 +25,7 @@ import llc.arma.ble.domain.model.ConnectedBleInfo
import llc.arma.ble.domain.repository.BleRepository
import llc.arma.ble.domain.usecase.AccelScale
import llc.arma.ble.domain.usecase.AccelViewMode
import llc.arma.ble.domain.usecase.Accelerate
import llc.arma.ble.domain.usecase.MeasureData
import llc.arma.ble.domain.usecase.FftAxis
import llc.arma.ble.domain.usecase.FftFrequency
import llc.arma.ble.domain.usecase.FftViewMode
@ -77,7 +77,8 @@ val AccelViewMode.sendData: Byte
AccelViewMode.ACCELERATION -> 0
AccelViewMode.PEAK_ACCELERATION -> 1
AccelViewMode.RMS -> 2
AccelViewMode.ANGLE -> 3
AccelViewMode.VIBRATION -> 3
AccelViewMode.ANGLE -> 0
}
}
@ -557,14 +558,15 @@ class BleRepositoryImpl @Inject constructor(
0 -> AccelViewMode.ACCELERATION
1 -> AccelViewMode.PEAK_ACCELERATION
2 -> AccelViewMode.RMS
3 -> AccelViewMode.ANGLE
3 -> AccelViewMode.VIBRATION
else -> {
return Result.failure(BleException.UnexpectedResponse)
}
}
Ble.Accelerometer.History.Enabled(
scale = scale,
mode = mode
mode = mode,
detailed = false //TODO
)
},
onFailure = {
@ -949,7 +951,7 @@ class BleRepositoryImpl @Inject constructor(
fftAxis: FftAxis,
fftMode: FftViewMode,
frequency: FftFrequency,
): Flow<Result<Accelerate, BleException>> {
): Flow<Result<MeasureData, BleException>> {
return callbackFlow {

View File

@ -14,11 +14,15 @@ import llc.arma.ble.domain.Result
import llc.arma.ble.domain.common.BleException
import llc.arma.ble.domain.usecase.AccelScale
import llc.arma.ble.domain.usecase.AccelViewMode
import llc.arma.ble.domain.usecase.Accelerate
import llc.arma.ble.domain.usecase.MeasureData
import llc.arma.ble.domain.usecase.FftAxis
import llc.arma.ble.domain.usecase.FftFrequency
import llc.arma.ble.domain.usecase.FftViewMode
import java.util.UUID
import kotlin.math.PI
import kotlin.math.atan
import kotlin.math.pow
import kotlin.math.sqrt
class ReadAccelerometerCallback(
@ -28,7 +32,7 @@ class ReadAccelerometerCallback(
private val fftAxis: FftAxis,
private val fftMode: FftViewMode,
private val frequency: FftFrequency,
private val onResult: (Result<Accelerate, BleException>) -> Unit
private val onResult: (Result<MeasureData, BleException>) -> Unit
) : BluetoothGattCallback() {
override fun onConnectionStateChange(
@ -162,21 +166,49 @@ class ReadAccelerometerCallback(
value: ByteArray,
){
val data = value.toList().chunked(2).map {
it.toByteArray().get2byteShortAt()
val result = if(accelMode == AccelViewMode.VIBRATION){
MeasureData.Vibration((value.get2byteShortAt().toFloat() * accelScale.k) / Short.MAX_VALUE)
} else {
val data = value.toList().chunked(2).map {
it.toByteArray().get2byteShortAt()
}
Log.d("accel", "x: ${data[0]} y: ${data[1]} z: ${data[2]} bytes: ${value.joinToString { it.toString() }}")
val x: Float
val y: Float
val z: Float
if (accelMode == AccelViewMode.ANGLE) {
x = calculateZAngle(data[2].toFloat(), data[1].toFloat()) * 180f / Math.PI.toFloat()
y = calculateZAngle(data[2].toFloat(), data[0].toFloat()) * 180f / Math.PI.toFloat()
z = calculateZAngle(data[0].toFloat(), data[1].toFloat()) * 180f / Math.PI.toFloat()
} else {
x = (data[0].toFloat() * accelScale.k) / Short.MAX_VALUE
y = (data[1].toFloat() * accelScale.k) / Short.MAX_VALUE
z = (data[2].toFloat() * accelScale.k) / Short.MAX_VALUE
}
val state = MeasureData.Accelerate(
x = x,
y = y,
z = z
)
state
}
Log.d("accel", "${Short.MAX_VALUE} ${data[0].toFloat() * accelScale.k} ${(data[0].toFloat() * accelScale.k) / Short.MAX_VALUE} ${data[0].toFloat()} ${data[1].toFloat()} ${data[2].toFloat()}")
val state = Accelerate(
x = (data[0].toFloat() * accelScale.k) / Short.MAX_VALUE,
y = (data[1].toFloat() * accelScale.k) / Short.MAX_VALUE,
z = (data[2].toFloat() * accelScale.k) / Short.MAX_VALUE
)
Log.d("accel", state.x.toString())
onResult(Result.success(state))
onResult(Result.success(result))
}
@ -218,3 +250,48 @@ class ReadAccelerometerCallback(
}
}
fun calculateAngle(
targetAxis: Float,
firstAxis: Float,
secondAxis: Float
): Float {
return atan(targetAxis.div(sqrt(firstAxis.pow(2) + secondAxis.pow(2))))
}
fun calculateZAngle(
x: Float,
y: Float
): Float {
var x = x
if(x == 0f && y == 0f){
x = 0.0001f
}
if(x > 0){
return atan(y/x)
}
if(x < 0 && y >= 0){
return atan(y/x) + PI.toFloat()
}
if(x < 0 && y < 0){
return atan(y/x) - PI.toFloat()
}
if(x == 0f && y > 0){
return PI.toFloat() / 2f
}
if(x == 0f && y < 0){
return -PI.toFloat() / 2f
}
return 0f
}

View File

@ -320,7 +320,7 @@ class ReadAccelerometerSpectreCallback(
ProgressState.Finished(
resultAccelerometerPackage.withIndex().map {
Ble.Accelerometer.MeasurePoint(
frequency = ((frequencyInterval!! * it.index + initialValue!!) * accelScale.k) / Short.MAX_VALUE,
frequency = frequencyInterval!! * it.index + initialValue!!,
value = (it.value * accelScale.k) / Short.MAX_VALUE
)
}

View File

@ -17,7 +17,8 @@ sealed class Ble(
data class Enabled(
val scale: AccelScale,
val mode: AccelViewMode
val mode: AccelViewMode,
val detailed: Boolean
) : History()
object Disabled : History()

View File

@ -9,7 +9,7 @@ import llc.arma.ble.domain.model.BleInfo
import llc.arma.ble.domain.model.ConnectedBleInfo
import llc.arma.ble.domain.usecase.AccelScale
import llc.arma.ble.domain.usecase.AccelViewMode
import llc.arma.ble.domain.usecase.Accelerate
import llc.arma.ble.domain.usecase.MeasureData
import llc.arma.ble.domain.usecase.FftAxis
import llc.arma.ble.domain.usecase.FftFrequency
import llc.arma.ble.domain.usecase.FftViewMode
@ -39,7 +39,7 @@ interface BleRepository {
fftAxis: FftAxis,
fftMode: FftViewMode,
frequency: FftFrequency
): Flow<Result<Accelerate, BleException>>
): Flow<Result<MeasureData, BleException>>
suspend fun getAccelerometerSpectreBySerial(
serial: String,

View File

@ -17,7 +17,7 @@ class GetAccelerometerMeasureBySerialFlow @Inject constructor(
fftAxis: FftAxis,
fftMode: FftViewMode,
frequency: FftFrequency
): Flow<Result<Accelerate, BleException>> {
): Flow<Result<MeasureData, BleException>> {
return bleRepository.getAccelerometerMeasureBySerialFlow(serial, accelScale, accelMode, fftAxis, fftMode, frequency)
@ -26,13 +26,27 @@ class GetAccelerometerMeasureBySerialFlow @Inject constructor(
}
enum class AccelViewMode {
ACCELERATION, PEAK_ACCELERATION, RMS, ANGLE
ACCELERATION, PEAK_ACCELERATION, RMS, VIBRATION, ANGLE
}
enum class AccelScale(val k: Int) {
S_2(2_000), S_4(4_000), S_8(8_000), S_16(16_000)
}
sealed class MeasureData {
data class Accelerate(
val x: Float,
val y: Float,
val z: Float,
) : MeasureData()
data class Vibration(
val value: Float
) : MeasureData()
}
data class Accelerate(
val x: Float,
val y: Float,