минуты
This commit is contained in:
parent
54fb528400
commit
12df287193
|
|
@ -13,8 +13,8 @@ android {
|
|||
applicationId "llc.arma.ble"
|
||||
minSdk 24
|
||||
targetSdk 33
|
||||
versionCode 8
|
||||
versionName "1.2.8"
|
||||
versionCode 9
|
||||
versionName "1.2.9"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
vectorDrawables {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package llc.arma.ble.app.ui.screen.inspection.accelerometer.view
|
|||
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
|
|
@ -22,7 +23,10 @@ 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.draw.rotate
|
||||
import androidx.compose.ui.graphics.StrokeCap
|
||||
import androidx.compose.ui.graphics.TransformOrigin
|
||||
import androidx.compose.ui.graphics.graphicsLayer
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import com.patrykandpatrick.vico.compose.axis.horizontal.bottomAxis
|
||||
import com.patrykandpatrick.vico.compose.chart.line.lineChart
|
||||
|
|
@ -132,7 +136,6 @@ fun Display(
|
|||
} else {
|
||||
|
||||
|
||||
|
||||
val xProducer = remember {
|
||||
ChartEntryModelProducer(listOf<FloatEntry>())
|
||||
}
|
||||
|
|
@ -151,6 +154,9 @@ fun Display(
|
|||
FloatEntry(index.toFloat(), measurePoint.x )
|
||||
}
|
||||
is MeasureData.Vibration -> FloatEntry(index.toFloat(), measurePoint.value)
|
||||
is MeasureData.Angle -> {
|
||||
FloatEntry(index.toFloat(), measurePoint.xAngle )
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
|
@ -160,6 +166,9 @@ fun Display(
|
|||
FloatEntry(index.toFloat(), measurePoint.y )
|
||||
}
|
||||
is MeasureData.Vibration -> FloatEntry(index.toFloat(), measurePoint.value)
|
||||
is MeasureData.Angle -> {
|
||||
FloatEntry(index.toFloat(), measurePoint.yAngle )
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
|
@ -169,6 +178,9 @@ fun Display(
|
|||
FloatEntry(index.toFloat(), measurePoint.z )
|
||||
}
|
||||
is MeasureData.Vibration -> FloatEntry(index.toFloat(), measurePoint.value)
|
||||
is MeasureData.Angle -> {
|
||||
FloatEntry(index.toFloat(), measurePoint.zAngle )
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
|
@ -180,64 +192,127 @@ fun Display(
|
|||
)
|
||||
)
|
||||
|
||||
if(state.measureHistory.lastOrNull() is MeasureData.Accelerate) {
|
||||
val lastMeasure = state.measureHistory.lastOrNull()
|
||||
|
||||
Column() {
|
||||
if(lastMeasure is MeasureData.Accelerate) {
|
||||
|
||||
Text(text = "Ось X:")
|
||||
if(state.mode == AccelViewMode.ANGLE){
|
||||
|
||||
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)
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(16.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
|
||||
Column(
|
||||
modifier = Modifier.weight(1f),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
|
||||
Text(text = "Ось X: ${lastMeasure.x}")
|
||||
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
|
||||
Angle(
|
||||
angle = lastMeasure.x,
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
Column(
|
||||
modifier = Modifier.weight(1f),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
|
||||
Text(text = "Ось Y: ${lastMeasure.y}")
|
||||
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
|
||||
Angle(
|
||||
modifier = Modifier.weight(1f),
|
||||
angle = lastMeasure.y
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
Column(
|
||||
modifier = Modifier.weight(1f),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
|
||||
Text(text = "Ось Z: ${lastMeasure.z}")
|
||||
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
|
||||
Angle(
|
||||
modifier = Modifier.weight(1f),
|
||||
angle = lastMeasure.z
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
Column() {
|
||||
|
||||
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)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -274,6 +349,75 @@ fun Display(
|
|||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun Angle(
|
||||
modifier: Modifier = Modifier,
|
||||
angle: Float
|
||||
) {
|
||||
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
shape = CircleShape,
|
||||
color = MaterialTheme.colorScheme.primaryContainer
|
||||
) {
|
||||
|
||||
Column(
|
||||
modifier = modifier.padding(4.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
|
||||
Text(text = "0°C")
|
||||
|
||||
Row(
|
||||
modifier.weight(1f),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
|
||||
Text(text = "-90°C")
|
||||
|
||||
Surface(
|
||||
modifier = Modifier
|
||||
.aspectRatio(1f)
|
||||
.fillMaxHeight()
|
||||
.padding(8.dp),
|
||||
color = MaterialTheme.colorScheme.secondary,
|
||||
shape = CircleShape
|
||||
) {
|
||||
|
||||
Box(
|
||||
modifier = Modifier,
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.rotate(-90f + angle),
|
||||
horizontalArrangement = Arrangement.End
|
||||
) {
|
||||
|
||||
Box(modifier = Modifier.weight(1f))
|
||||
|
||||
Divider(modifier = Modifier.weight(1f))
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Text(text = "90°C")
|
||||
|
||||
}
|
||||
|
||||
Text(text = "±180°C")
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun Exception(
|
||||
|
||||
|
|
@ -324,6 +468,7 @@ class AccelerometerAccelContract {
|
|||
sealed class State : ViewState {
|
||||
|
||||
data class Display(
|
||||
val mode: AccelViewMode,
|
||||
val measureHistory : List<MeasureData>
|
||||
) : State()
|
||||
|
||||
|
|
@ -349,7 +494,8 @@ class AccelerometerAccelViewModel @Inject constructor(
|
|||
private var lastSerial: String? = null
|
||||
|
||||
override fun setInitialState() = AccelerometerAccelContract.State.Display(
|
||||
emptyList()
|
||||
mode = AccelViewMode.ACCELERATION,
|
||||
measureHistory = emptyList()
|
||||
)
|
||||
|
||||
override fun handleEvents(event: AccelerometerAccelContract.Event) {
|
||||
|
|
@ -365,12 +511,14 @@ class AccelerometerAccelViewModel @Inject constructor(
|
|||
event: AccelerometerAccelContract.Event.StopMeasure
|
||||
) {
|
||||
|
||||
|
||||
measureJob?.cancel()
|
||||
measureJob = null
|
||||
|
||||
setState {
|
||||
AccelerometerAccelContract.State.Display(emptyList())
|
||||
AccelerometerAccelContract.State.Display(
|
||||
mode = AccelViewMode.ACCELERATION,
|
||||
measureHistory = emptyList()
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -407,7 +555,10 @@ class AccelerometerAccelViewModel @Inject constructor(
|
|||
measureJob = viewModelScope.launch {
|
||||
|
||||
setState {
|
||||
AccelerometerAccelContract.State.Display(emptyList())
|
||||
AccelerometerAccelContract.State.Display(
|
||||
mode = AccelViewMode.ACCELERATION,
|
||||
measureHistory = emptyList()
|
||||
)
|
||||
}
|
||||
|
||||
getAccelerometerMeasureBySerialFlow(serial, accelScale, accelMode, fftAxis, fftMode, frequency).onEach {
|
||||
|
|
@ -422,11 +573,11 @@ class AccelerometerAccelViewModel @Inject constructor(
|
|||
if(accelMode != AccelViewMode.ANGLE) {
|
||||
dataList = dataList.takeLast(10).toMutableList()
|
||||
}
|
||||
AccelerometerAccelContract.State.Display(dataList)
|
||||
AccelerometerAccelContract.State.Display(accelMode, dataList)
|
||||
}
|
||||
|
||||
AccelerometerAccelContract.State.Exception -> {
|
||||
AccelerometerAccelContract.State.Display(listOf(it))
|
||||
AccelerometerAccelContract.State.Display(accelMode, listOf(it))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,21 +25,23 @@ fun IntervalEdit(
|
|||
mutableStateOf((state.accelerometerState.historyInterval / 1000 / 60 / 60).toInt())
|
||||
}
|
||||
|
||||
val maxInterval = 240
|
||||
val maxInterval = 10 * 24 * 60 * 60 * 1000
|
||||
|
||||
if(value > maxInterval){
|
||||
value = maxInterval
|
||||
}
|
||||
|
||||
if(value < 1){
|
||||
value = 1
|
||||
value = 1 * 60 * 1000
|
||||
}
|
||||
|
||||
val maxHours = maxInterval
|
||||
val maxDays = maxInterval / 24
|
||||
val maxMinutes = maxInterval / millisInMinute
|
||||
val maxHours = maxInterval / millisInHour
|
||||
val maxDays = maxInterval / millisInDay
|
||||
|
||||
val dayValue = value / 24
|
||||
val hourValue = value - (24 * dayValue)
|
||||
val dayValue = value / millisInDay
|
||||
val hourValue = (value - (dayValue * millisInDay)) / millisInHour
|
||||
val minutesValue = (value - (dayValue * millisInDay) - (hourValue * millisInHour)) / millisInMinute
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
|
|
@ -62,7 +64,9 @@ fun IntervalEdit(
|
|||
NumberPicker(
|
||||
range = -1..maxDays,
|
||||
value = dayValue,
|
||||
onValueChanged = { value = (it * 24) + hourValue }
|
||||
onValueChanged = {
|
||||
value = (it * millisInDay) + (hourValue * millisInHour) + (minutesValue * millisInMinute)
|
||||
}
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
|
|
@ -75,7 +79,7 @@ fun IntervalEdit(
|
|||
range = -1..maxHours,
|
||||
value = hourValue,
|
||||
onValueChanged = {
|
||||
value = it + (dayValue * 24)
|
||||
value = (it * millisInHour) + (dayValue * millisInDay) + (minutesValue * millisInMinute)
|
||||
}
|
||||
)
|
||||
|
||||
|
|
@ -83,6 +87,20 @@ fun IntervalEdit(
|
|||
|
||||
Text(text = "Часы")
|
||||
|
||||
Spacer(modifier = Modifier.width(16.dp))
|
||||
|
||||
NumberPicker(
|
||||
range = -1..maxMinutes,
|
||||
value = minutesValue,
|
||||
onValueChanged = {
|
||||
value = (it * millisInMinute) + (dayValue * millisInDay) + (hourValue * millisInHour)
|
||||
}
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
|
||||
Text(text = "Минуты")
|
||||
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
|
@ -97,7 +115,7 @@ fun IntervalEdit(
|
|||
onClick = {
|
||||
onEvent(
|
||||
AccelerometerContract.Event.OnSaveIntervalChanged(
|
||||
value.toLong() * 1000 * 60 * 60
|
||||
value.toLong()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
@ -120,6 +138,11 @@ fun IntervalEdit(
|
|||
|
||||
}
|
||||
|
||||
const val millisInMinute = 1000 * 60
|
||||
const val millisInHour = millisInMinute * 60
|
||||
const val millisInDay = millisInHour * 24
|
||||
|
||||
|
||||
@Composable
|
||||
fun NumberPicker(
|
||||
modifier: Modifier = Modifier,
|
||||
|
|
|
|||
|
|
@ -35,6 +35,15 @@ enum class AccelScale(val k: Int) {
|
|||
|
||||
sealed class MeasureData {
|
||||
|
||||
data class Angle(
|
||||
val xAngle: Float,
|
||||
val yAngle: Float,
|
||||
val zAngle: Float,
|
||||
val xAccelerate: Float,
|
||||
val yAccelerate: Float,
|
||||
val zAccelerate: Float,
|
||||
) : MeasureData()
|
||||
|
||||
data class Accelerate(
|
||||
val x: Float,
|
||||
val y: Float,
|
||||
|
|
|
|||
Loading…
Reference in New Issue