Масштаб графиков

This commit is contained in:
Vineyro 2023-09-13 15:54:56 +07:00
parent c59c929f35
commit f97811ed9e
23 changed files with 1072 additions and 112 deletions

View File

@ -14,7 +14,7 @@ android {
minSdk 24 minSdk 24
targetSdk 33 targetSdk 33
versionCode 5 versionCode 5
versionName "1.2.3" versionName "1.2.5"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables { vectorDrawables {
@ -24,7 +24,7 @@ android {
buildTypes { buildTypes {
release { release {
minifyEnabled false minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
} }
} }
@ -47,8 +47,8 @@ android {
} }
} }
applicationVariants.all { variant -> applicationVariants.configureEach { variant ->
variant.outputs.all { variant.outputs.configureEach {
outputFileName = "Arma BLE v${defaultConfig.versionName}.apk" outputFileName = "Arma BLE v${defaultConfig.versionName}.apk"
} }
} }

View File

@ -1,7 +1,6 @@
package llc.arma.ble.app.ui package llc.arma.ble.app.ui
import android.Manifest import android.Manifest
import android.annotation.SuppressLint
import android.content.BroadcastReceiver import android.content.BroadcastReceiver
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent

View File

@ -3,7 +3,10 @@ package llc.arma.ble.app.ui.model
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import llc.arma.ble.domain.model.Ble
import llc.arma.ble.domain.model.BleInfo import llc.arma.ble.domain.model.BleInfo
import llc.arma.ble.domain.usecase.AccelScale
import llc.arma.ble.domain.usecase.AccelViewMode
sealed class BleView( sealed class BleView(
val info: BleInfo val info: BleInfo
@ -16,7 +19,7 @@ sealed class BleView(
) : BleView(info) { ) : BleView(info) {
class AccelerometerState( class AccelerometerState(
saveHistory: Boolean, saveHistory: Ble.Accelerometer.History,
historyInterval: Long historyInterval: Long
) { ) {

View File

@ -4,7 +4,6 @@ import llc.arma.ble.app.ui.common.ViewEvent
import llc.arma.ble.app.ui.common.ViewSideEffect import llc.arma.ble.app.ui.common.ViewSideEffect
import llc.arma.ble.app.ui.common.ViewState import llc.arma.ble.app.ui.common.ViewState
import llc.arma.ble.app.ui.model.BleView import llc.arma.ble.app.ui.model.BleView
import llc.arma.ble.app.ui.screen.inspection.beacon.BeaconContract
import llc.arma.ble.domain.model.Ble import llc.arma.ble.domain.model.Ble
import llc.arma.ble.domain.usecase.AccelScale import llc.arma.ble.domain.usecase.AccelScale
import llc.arma.ble.domain.usecase.AccelViewMode import llc.arma.ble.domain.usecase.AccelViewMode
@ -27,16 +26,21 @@ class AccelerometerContract {
data class OnAccelViewModeEdit( data class OnAccelViewModeEdit(
val next: Next val next: Next
) : Event(){ ) : Event()
enum class Next { enum class Next {
ACCEL, SPECTRE ACCEL, SPECTRE, HISTORY
} }
} data class OnAccelScaleEdit(
val next: Next
) : Event()
object OnAccelEdit : Event()
object OnSpectreEdit : Event() object OnSpectreEdit : Event()
object OnHistoryEdit : Event()
object OnFftFrequencyEdit : Event() object OnFftFrequencyEdit : Event()
object OnFftAxisEdit : Event() object OnFftAxisEdit : Event()
object OnFftModeEdit : Event() object OnFftModeEdit : Event()
@ -50,6 +54,7 @@ class AccelerometerContract {
object OnChangePassword : Event() object OnChangePassword : Event()
object OnSaveIntervalEdit : Event() object OnSaveIntervalEdit : Event()
object OnHideHistoryEdit : Event()
data class OnBleChanged( data class OnBleChanged(
val ble: Ble.Accelerometer, val ble: Ble.Accelerometer,
@ -63,6 +68,10 @@ class AccelerometerContract {
val mode: AccelViewMode val mode: AccelViewMode
) : Event() ) : Event()
data class OnHistoryViewModeChanged(
val mode: AccelViewMode
) : Event()
data class OnFftFrequencyChanged( data class OnFftFrequencyChanged(
val frequency: FftFrequency val frequency: FftFrequency
) : Event() ) : Event()
@ -75,6 +84,14 @@ class AccelerometerContract {
val mode: FftViewMode val mode: FftViewMode
) : Event() ) : Event()
data class OnAccelScaleChanged(
val scale: AccelScale
) : Event()
data class OnHistoryScaleChanged(
val scale: AccelScale
) : Event()
data class OnSaveHistoryChanged( data class OnSaveHistoryChanged(
val save: Boolean val save: Boolean
) : Event() ) : Event()
@ -132,18 +149,28 @@ class AccelerometerContract {
object ShowWriteBle : Effect() object ShowWriteBle : Effect()
object HideWriteBle : Effect() object HideWriteBle : Effect()
data class ShowAccelEdit( object HideHistoryEdit : Effect()
val next: Event.OnAccelViewModeEdit.Next
data class ShowAccelViewEdit(
val next: Event.Next
) : Effect() ) : Effect()
data class ShowAccelScaleEdit(
val next: Event.Next
) : Effect()
object ShowAccelEdit : Effect()
object ShowSpectreEdit : Effect() object ShowSpectreEdit : Effect()
object ShowFftFrequencyEdit : Effect() object ShowFftFrequencyEdit : Effect()
object ShowFftAxisEdit : Effect() object ShowFftAxisEdit : Effect()
object ShowFftModeEdit : Effect() object ShowFftModeEdit : Effect()
object HideIntervalPicker : Effect() object HideIntervalPicker : Effect()
object ShowIntervalPicker : Effect() object ShowIntervalPicker : Effect()
object ShowHistoryEdit : Effect()
sealed class Navigation : Effect() { sealed class Navigation : Effect() {
object NavigateToChangePassword : Navigation() object NavigateToChangePassword : Navigation()

View File

@ -17,15 +17,18 @@ import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import llc.arma.ble.app.ui.common.rememberBottomDialogState import llc.arma.ble.app.ui.common.rememberBottomDialogState
import llc.arma.ble.app.ui.screen.inspection.accelerometer.view.AccelEdit
import llc.arma.ble.app.ui.screen.inspection.accelerometer.view.AccelFftAxisEdit import llc.arma.ble.app.ui.screen.inspection.accelerometer.view.AccelFftAxisEdit
import llc.arma.ble.app.ui.screen.inspection.accelerometer.view.AccelFftModeEdit import llc.arma.ble.app.ui.screen.inspection.accelerometer.view.AccelFftModeEdit
import llc.arma.ble.app.ui.screen.inspection.accelerometer.view.AccelFrequencyEdit import llc.arma.ble.app.ui.screen.inspection.accelerometer.view.AccelFrequencyEdit
import llc.arma.ble.app.ui.screen.inspection.accelerometer.view.AccelScaleEdit
import llc.arma.ble.app.ui.screen.inspection.accelerometer.view.AccelSpectreEdit import llc.arma.ble.app.ui.screen.inspection.accelerometer.view.AccelSpectreEdit
import llc.arma.ble.app.ui.screen.inspection.accelerometer.view.AccelViewEdit import llc.arma.ble.app.ui.screen.inspection.accelerometer.view.AccelViewEdit
import llc.arma.ble.app.ui.screen.inspection.accelerometer.view.AccelerometerSpectre import llc.arma.ble.app.ui.screen.inspection.accelerometer.view.AccelerometerSpectre
import llc.arma.ble.app.ui.screen.inspection.accelerometer.view.AccelerometerAccel import llc.arma.ble.app.ui.screen.inspection.accelerometer.view.AccelerometerAccel
import llc.arma.ble.app.ui.screen.inspection.accelerometer.view.AccelerometerHistory import llc.arma.ble.app.ui.screen.inspection.accelerometer.view.AccelerometerHistory
import llc.arma.ble.app.ui.screen.inspection.accelerometer.view.DisplayState import llc.arma.ble.app.ui.screen.inspection.accelerometer.view.DisplayState
import llc.arma.ble.app.ui.screen.inspection.accelerometer.view.HistoryEdit
import llc.arma.ble.app.ui.screen.inspection.accelerometer.view.IntervalEdit import llc.arma.ble.app.ui.screen.inspection.accelerometer.view.IntervalEdit
import llc.arma.ble.app.ui.screen.inspection.accelerometer.view.LoadingState import llc.arma.ble.app.ui.screen.inspection.accelerometer.view.LoadingState
import llc.arma.ble.app.ui.screen.inspection.accelerometer.view.PowerEdit import llc.arma.ble.app.ui.screen.inspection.accelerometer.view.PowerEdit
@ -33,7 +36,7 @@ import llc.arma.ble.app.ui.screen.inspection.accelerometer.view.Write
import llc.arma.ble.domain.model.Ble import llc.arma.ble.domain.model.Ble
enum class SheetPage { enum class SheetPage {
HISTORY, ACCEL, POWER, WRITE, SPECTRE, ACCEL_MODE_EDIT, SPECTRE_MODE_EDIT, SPECTRE_EDIT, FREQUENCY_EDIT, AXIS_EDIT, FFT_MODE_EDIT, INTERVAL_EDIT HISTORY, ACCEL_SCALE, SPECTRE_SCALE, HISTORY_MODE_EDIT, HISTORY_SCALE, HISTORY_EDIT, ACCEL_EDIT, ACCEL, POWER, WRITE, SPECTRE, ACCEL_MODE_EDIT, SPECTRE_MODE_EDIT, SPECTRE_EDIT, FREQUENCY_EDIT, AXIS_EDIT, FFT_MODE_EDIT, INTERVAL_EDIT
} }
@OptIn(ExperimentalMaterialApi::class) @OptIn(ExperimentalMaterialApi::class)
@ -157,7 +160,7 @@ fun AccelerometerScreen(
if(currentState is AccelerometerContract.State.Display) { if(currentState is AccelerometerContract.State.Display) {
AccelViewEdit( AccelViewEdit(
next = AccelerometerContract.Event.OnAccelViewModeEdit.Next.ACCEL, next = AccelerometerContract.Event.Next.ACCEL,
state = currentState, state = currentState,
onEvent = { onEvent = {
viewModel.setEvent(it) viewModel.setEvent(it)
@ -172,7 +175,22 @@ fun AccelerometerScreen(
if(currentState is AccelerometerContract.State.Display) { if(currentState is AccelerometerContract.State.Display) {
AccelViewEdit( AccelViewEdit(
next = AccelerometerContract.Event.OnAccelViewModeEdit.Next.SPECTRE, next = AccelerometerContract.Event.Next.SPECTRE,
state = currentState,
onEvent = {
viewModel.setEvent(it)
}
)
}
}
SheetPage.HISTORY_MODE_EDIT -> bottomDialog.show {
val currentState = viewModel.viewState.value
if(currentState is AccelerometerContract.State.Display) {
AccelViewEdit(
next = AccelerometerContract.Event.Next.HISTORY,
state = currentState, state = currentState,
onEvent = { onEvent = {
viewModel.setEvent(it) viewModel.setEvent(it)
@ -237,7 +255,6 @@ fun AccelerometerScreen(
} }
} }
SheetPage.INTERVAL_EDIT -> bottomDialog.show { SheetPage.INTERVAL_EDIT -> bottomDialog.show {
val currentState = viewModel.viewState.value val currentState = viewModel.viewState.value
@ -252,12 +269,82 @@ fun AccelerometerScreen(
} }
} }
SheetPage.ACCEL_SCALE -> bottomDialog.show {
val currentState = viewModel.viewState.value
if(currentState is AccelerometerContract.State.Display) {
AccelScaleEdit(
next = AccelerometerContract.Event.Next.ACCEL,
state = currentState,
onEvent = {
viewModel.setEvent(it)
}
)
}
}
SheetPage.SPECTRE_SCALE -> bottomDialog.show {
val currentState = viewModel.viewState.value
if(currentState is AccelerometerContract.State.Display) {
AccelScaleEdit(
next = AccelerometerContract.Event.Next.SPECTRE,
state = currentState,
onEvent = {
viewModel.setEvent(it)
}
)
}
}
SheetPage.HISTORY_SCALE -> bottomDialog.show {
val currentState = viewModel.viewState.value
if(currentState is AccelerometerContract.State.Display) {
AccelScaleEdit(
next = AccelerometerContract.Event.Next.HISTORY,
state = currentState,
onEvent = {
viewModel.setEvent(it)
}
)
}
}
SheetPage.ACCEL_EDIT -> bottomDialog.show {
val currentState = viewModel.viewState.value
if(currentState is AccelerometerContract.State.Display) {
AccelEdit(
state = currentState,
onEvent = {
viewModel.setEvent(it)
}
)
}
}
SheetPage.HISTORY_EDIT -> bottomDialog.show {
val currentState = viewModel.viewState.value
if(currentState is AccelerometerContract.State.Display) {
HistoryEdit(
state = currentState,
onEvent = {
viewModel.setEvent(it)
}
)
}
}
null -> { null -> {
bottomDialog.hide() bottomDialog.hide()
} }
} }
} }
@ -300,12 +387,13 @@ fun AccelerometerScreen(
delay(100) delay(100)
sheetPage = SheetPage.SPECTRE sheetPage = SheetPage.SPECTRE
} }
is AccelerometerContract.Effect.ShowAccelEdit -> launch { is AccelerometerContract.Effect.ShowAccelViewEdit -> launch {
sheetPage = null sheetPage = null
delay(100) delay(100)
sheetPage = when(it.next){ sheetPage = when(it.next){
AccelerometerContract.Event.OnAccelViewModeEdit.Next.ACCEL -> SheetPage.ACCEL_MODE_EDIT AccelerometerContract.Event.Next.ACCEL -> SheetPage.ACCEL_MODE_EDIT
AccelerometerContract.Event.OnAccelViewModeEdit.Next.SPECTRE -> SheetPage.SPECTRE_MODE_EDIT AccelerometerContract.Event.Next.SPECTRE -> SheetPage.SPECTRE_MODE_EDIT
AccelerometerContract.Event.Next.HISTORY -> SheetPage.HISTORY_MODE_EDIT
} }
} }
is AccelerometerContract.Effect.ShowSpectreEdit -> launch { is AccelerometerContract.Effect.ShowSpectreEdit -> launch {
@ -328,25 +416,46 @@ fun AccelerometerScreen(
delay(100) delay(100)
sheetPage = SheetPage.FFT_MODE_EDIT sheetPage = SheetPage.FFT_MODE_EDIT
} }
is AccelerometerContract.Effect.ShowAccelerometerHistory -> launch {
AccelerometerContract.Effect.ShowAccelerometerHistory -> launch {
sheetPage = null sheetPage = null
delay(100) delay(100)
sheetPage = SheetPage.HISTORY sheetPage = SheetPage.HISTORY
} }
is AccelerometerContract.Effect.HideIntervalPicker -> {
AccelerometerContract.Effect.HideIntervalPicker -> {
sheetPage = null sheetPage = null
delay(100) delay(100)
} }
AccelerometerContract.Effect.ShowIntervalPicker -> { is AccelerometerContract.Effect.ShowIntervalPicker -> {
sheetPage = null sheetPage = null
delay(100) delay(100)
sheetPage = SheetPage.INTERVAL_EDIT sheetPage = SheetPage.INTERVAL_EDIT
} }
is AccelerometerContract.Effect.ShowAccelScaleEdit -> {
sheetPage = null
delay(100)
sheetPage = when(it.next){
AccelerometerContract.Event.Next.ACCEL -> SheetPage.ACCEL_SCALE
AccelerometerContract.Event.Next.SPECTRE -> SheetPage.SPECTRE_SCALE
AccelerometerContract.Event.Next.HISTORY -> SheetPage.HISTORY_SCALE
}
}
is AccelerometerContract.Effect.ShowAccelEdit -> {
sheetPage = null
delay(100)
sheetPage = SheetPage.ACCEL_EDIT
}
is AccelerometerContract.Effect.Navigation -> { is AccelerometerContract.Effect.Navigation -> {
onEvent(it) onEvent(it)
} }
is AccelerometerContract.Effect.ShowHistoryEdit -> {
sheetPage = null
delay(100)
sheetPage = SheetPage.HISTORY_EDIT
}
is AccelerometerContract.Effect.HideHistoryEdit -> {
sheetPage = null
delay(100)
}
} }
}.launchIn(this) }.launchIn(this)
} }

View File

@ -7,8 +7,6 @@ import llc.arma.ble.app.ui.common.BaseViewModel
import llc.arma.ble.app.ui.mapper.BleMapper import llc.arma.ble.app.ui.mapper.BleMapper
import llc.arma.ble.app.ui.mapper.BleViewMapper import llc.arma.ble.app.ui.mapper.BleViewMapper
import llc.arma.ble.app.ui.model.BleView import llc.arma.ble.app.ui.model.BleView
import llc.arma.ble.app.ui.screen.inspection.beacon.BeaconContract
import llc.arma.ble.app.ui.screen.inspection.thermometer.ThermometerContract
import llc.arma.ble.domain.model.Ble import llc.arma.ble.domain.model.Ble
import llc.arma.ble.domain.usecase.AccelScale import llc.arma.ble.domain.usecase.AccelScale
import llc.arma.ble.domain.usecase.AccelViewMode import llc.arma.ble.domain.usecase.AccelViewMode
@ -54,6 +52,106 @@ class AccelerometerViewModel @Inject constructor(
is AccelerometerContract.Event.OnChangePassword -> reduce(viewState.value, event) is AccelerometerContract.Event.OnChangePassword -> reduce(viewState.value, event)
is AccelerometerContract.Event.OnSaveIntervalChanged -> reduce(viewState.value, event) is AccelerometerContract.Event.OnSaveIntervalChanged -> reduce(viewState.value, event)
is AccelerometerContract.Event.OnSaveIntervalEdit -> reduce(viewState.value, event) is AccelerometerContract.Event.OnSaveIntervalEdit -> reduce(viewState.value, event)
is AccelerometerContract.Event.OnAccelScaleChanged -> reduce(viewState.value, event)
is AccelerometerContract.Event.OnAccelScaleEdit -> reduce(viewState.value, event)
is AccelerometerContract.Event.OnAccelEdit -> reduce(viewState.value, event)
is AccelerometerContract.Event.OnHistoryEdit -> reduce(viewState.value, event)
is AccelerometerContract.Event.OnHistoryScaleChanged -> reduce(viewState.value, event)
is AccelerometerContract.Event.OnHistoryViewModeChanged -> reduce(viewState.value, event)
is AccelerometerContract.Event.OnHideHistoryEdit -> reduce(viewState.value, event)
}
}
private fun reduce(
state: AccelerometerContract.State,
event: AccelerometerContract.Event.OnHideHistoryEdit
) {
setEffect {
AccelerometerContract.Effect.HideHistoryEdit
}
}
private fun reduce(
state: AccelerometerContract.State,
event: AccelerometerContract.Event.OnHistoryViewModeChanged
) {
if(state is AccelerometerContract.State.Display){
var saveHistory = state.accelerometer.accelerometerState.saveHistory
if(saveHistory is Ble.Accelerometer.History.Enabled){
saveHistory = Ble.Accelerometer.History.Enabled(
mode = event.mode,
scale = saveHistory.scale
)
}
state.accelerometer.accelerometerState.saveHistory = saveHistory
}
}
private fun reduce(
state: AccelerometerContract.State,
event: AccelerometerContract.Event.OnHistoryScaleChanged
) {
if(state is AccelerometerContract.State.Display){
var saveHistory = state.accelerometer.accelerometerState.saveHistory
if(saveHistory is Ble.Accelerometer.History.Enabled){
saveHistory = saveHistory.copy(scale = event.scale)
}
state.accelerometer.accelerometerState.saveHistory = saveHistory
}
}
private fun reduce(
state: AccelerometerContract.State,
event: AccelerometerContract.Event.OnHistoryEdit
) {
setEffect {
AccelerometerContract.Effect.ShowHistoryEdit
}
}
private fun reduce(
state: AccelerometerContract.State,
event: AccelerometerContract.Event.OnAccelScaleChanged
) {
if(state is AccelerometerContract.State.Display){
setState {
state.copy(
accelScale = event.scale
)
}
}
}
private fun reduce(
state: AccelerometerContract.State,
event: AccelerometerContract.Event.OnAccelScaleEdit
) {
setEffect {
AccelerometerContract.Effect.ShowAccelScaleEdit(
event.next
)
} }
} }
@ -98,7 +196,22 @@ class AccelerometerViewModel @Inject constructor(
if(state is AccelerometerContract.State.Display) { if(state is AccelerometerContract.State.Display) {
state.accelerometer.accelerometerState.saveHistory = event.save if(event.save){
state.accelerometer.accelerometerState.saveHistory = Ble.Accelerometer.History.Enabled(
scale = AccelScale.S_2,
mode = AccelViewMode.ACCELERATION
)
setEffect {
AccelerometerContract.Effect.ShowHistoryEdit
}
} else {
state.accelerometer.accelerometerState.saveHistory = Ble.Accelerometer.History.Disabled
}
} }
@ -188,6 +301,17 @@ class AccelerometerViewModel @Inject constructor(
} }
private fun reduce(
state: AccelerometerContract.State,
event: AccelerometerContract.Event.OnAccelEdit
) {
setEffect {
AccelerometerContract.Effect.ShowAccelEdit
}
}
private fun reduce( private fun reduce(
state: AccelerometerContract.State, state: AccelerometerContract.State,
event: AccelerometerContract.Event.OnSpectreEdit event: AccelerometerContract.Event.OnSpectreEdit
@ -343,7 +467,7 @@ class AccelerometerViewModel @Inject constructor(
event: AccelerometerContract.Event.OnAccelViewModeEdit event: AccelerometerContract.Event.OnAccelViewModeEdit
) { ) {
setEffect { setEffect {
AccelerometerContract.Effect.ShowAccelEdit(event.next) AccelerometerContract.Effect.ShowAccelViewEdit(event.next)
} }
} }

View File

@ -0,0 +1,172 @@
package llc.arma.ble.app.ui.screen.inspection.accelerometer.view
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.KeyboardArrowDown
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.RadioButton
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.unit.dp
import llc.arma.ble.app.ui.screen.inspection.accelerometer.AccelerometerContract
import llc.arma.ble.domain.usecase.AccelScale
import llc.arma.ble.domain.usecase.FftAxis
import llc.arma.ble.domain.usecase.FftFrequency
import llc.arma.ble.domain.usecase.FftViewMode
@Composable
fun AccelEdit(
state: AccelerometerContract.State.Display,
onEvent: (AccelerometerContract.Event) -> Unit,
){
val accelMode = state.accelViewMode
val fftMode = state.fftViewMode
val fftAxis = state.fftAxis
val fftFrequency = state.fftFrequency
val accelScale = state.accelScale
Column(
modifier = Modifier
) {
Text(
modifier = Modifier.padding(horizontal = 12.dp),
text = "Ускорение",
style = MaterialTheme.typography.titleLarge
)
Spacer(modifier = Modifier.height(16.dp))
Column(
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.Next.ACCEL
)
)
}
.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,
horizontal = 8.dp
)
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.clip(RoundedCornerShape(16.dp))
.clickable {
onEvent(AccelerometerContract.Event.OnAccelScaleEdit(next = AccelerometerContract.Event.Next.ACCEL))
}
.padding(8.dp)
) {
Column(
modifier = Modifier.weight(1f)
) {
Text(
text = "Accel scale"
)
Text(
color = MaterialTheme.colorScheme.secondary,
style = MaterialTheme.typography.bodyMedium,
text = accelScale.localized
)
}
Icon(
imageVector = Icons.Rounded.KeyboardArrowDown,
contentDescription = null
)
}
}
}
Spacer(modifier = Modifier.height(16.dp))
Surface(
modifier = Modifier
.fillMaxWidth()
.padding(8.dp)
.height(50.dp),
shape = CircleShape,
color = MaterialTheme.colorScheme.primaryContainer,
onClick = {
onEvent(AccelerometerContract.Event.OnShowAccelerometerAccel)
}
) {
Box(modifier = Modifier.fillMaxSize()) {
Text(
modifier = Modifier.align(Alignment.Center),
color = MaterialTheme.colorScheme.background,
style = MaterialTheme.typography.labelLarge,
text = "Продолжить"
)
}
}
}
}

View File

@ -0,0 +1,138 @@
package llc.arma.ble.app.ui.screen.inspection.accelerometer.view
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.KeyboardArrowDown
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.RadioButton
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.unit.dp
import llc.arma.ble.app.ui.screen.inspection.accelerometer.AccelerometerContract
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
@Composable
fun AccelScaleEdit(
next: AccelerometerContract.Event.Next,
state: AccelerometerContract.State.Display,
onEvent: (AccelerometerContract.Event) -> Unit,
){
var fftMode = when(next){
AccelerometerContract.Event.Next.ACCEL,
AccelerometerContract.Event.Next.SPECTRE ->
state.accelScale
AccelerometerContract.Event.Next.HISTORY -> {
val history = state.accelerometer.accelerometerState.saveHistory
if (history is Ble.Accelerometer.History.Enabled)
history.scale
else {
state.accelScale
}
}
}
Column(
modifier = Modifier
) {
Text(
modifier = Modifier.padding(horizontal = 12.dp),
text = "Accel scale",
style = MaterialTheme.typography.titleLarge
)
Spacer(modifier = Modifier.height(16.dp))
AccelScale.values().forEach {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.fillMaxWidth()
.clip(RoundedCornerShape(8.dp))
.clickable {
when(next){
AccelerometerContract.Event.Next.ACCEL,
AccelerometerContract.Event.Next.SPECTRE ->
onEvent(AccelerometerContract.Event.OnAccelScaleChanged(it))
AccelerometerContract.Event.Next.HISTORY ->
onEvent(AccelerometerContract.Event.OnHistoryScaleChanged(it))
}
}
.padding(4.dp)
) {
RadioButton(
selected = it == fftMode,
onClick = {
when(next){
AccelerometerContract.Event.Next.ACCEL,
AccelerometerContract.Event.Next.SPECTRE ->
onEvent(AccelerometerContract.Event.OnAccelScaleChanged(it))
AccelerometerContract.Event.Next.HISTORY ->
onEvent(AccelerometerContract.Event.OnHistoryScaleChanged(it))
}
}
)
Text(text = it.localized)
}
}
Spacer(modifier = Modifier.height(16.dp))
Surface(
modifier = Modifier
.fillMaxWidth()
.padding(8.dp)
.height(50.dp),
shape = CircleShape,
color = MaterialTheme.colorScheme.primaryContainer,
onClick = {
when(next){
AccelerometerContract.Event.Next.ACCEL ->
onEvent(AccelerometerContract.Event.OnAccelEdit)
AccelerometerContract.Event.Next.SPECTRE ->
onEvent(AccelerometerContract.Event.OnSpectreEdit)
AccelerometerContract.Event.Next.HISTORY ->
onEvent(AccelerometerContract.Event.OnHistoryEdit)
}
}
) {
Box(modifier = Modifier.fillMaxSize()) {
Text(
modifier = Modifier.align(Alignment.Center),
color = MaterialTheme.colorScheme.background,
style = MaterialTheme.typography.labelLarge,
text = "Ок"
)
}
}
}
}

View File

@ -19,6 +19,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import llc.arma.ble.app.ui.screen.inspection.accelerometer.AccelerometerContract import llc.arma.ble.app.ui.screen.inspection.accelerometer.AccelerometerContract
import llc.arma.ble.domain.usecase.AccelScale
import llc.arma.ble.domain.usecase.FftAxis import llc.arma.ble.domain.usecase.FftAxis
import llc.arma.ble.domain.usecase.FftFrequency import llc.arma.ble.domain.usecase.FftFrequency
import llc.arma.ble.domain.usecase.FftViewMode import llc.arma.ble.domain.usecase.FftViewMode
@ -59,6 +60,16 @@ val FftViewMode.localized: String
} }
} }
val AccelScale.localized: String
get() {
return when(this){
AccelScale.S_2 -> "2g"
AccelScale.S_4 -> "4g"
AccelScale.S_8 -> "8g"
AccelScale.S_16 -> "16g"
}
}
@Composable @Composable
fun AccelSpectreEdit( fun AccelSpectreEdit(
state: AccelerometerContract.State.Display, state: AccelerometerContract.State.Display,
@ -69,6 +80,7 @@ fun AccelSpectreEdit(
val fftMode = state.fftViewMode val fftMode = state.fftViewMode
val fftAxis = state.fftAxis val fftAxis = state.fftAxis
val fftFrequency = state.fftFrequency val fftFrequency = state.fftFrequency
val accelScale = state.accelScale
Column( Column(
modifier = Modifier modifier = Modifier
@ -207,6 +219,47 @@ fun AccelSpectreEdit(
} }
Box(
modifier = Modifier.padding(
vertical = 8.dp,
horizontal = 8.dp
)
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.clip(RoundedCornerShape(16.dp))
.clickable {
onEvent(AccelerometerContract.Event.OnAccelScaleEdit(next = AccelerometerContract.Event.Next.SPECTRE))
}
.padding(8.dp)
) {
Column(
modifier = Modifier.weight(1f)
) {
Text(
text = "Accel scale"
)
Text(
color = MaterialTheme.colorScheme.secondary,
style = MaterialTheme.typography.bodyMedium,
text = accelScale.localized
)
}
Icon(
imageVector = Icons.Rounded.KeyboardArrowDown,
contentDescription = null
)
}
}
} }
Spacer(modifier = Modifier.height(16.dp)) Spacer(modifier = Modifier.height(16.dp))

View File

@ -29,7 +29,7 @@ val AccelViewMode.localized: String
@Composable @Composable
fun AccelViewEdit( fun AccelViewEdit(
next: AccelerometerContract.Event.OnAccelViewModeEdit.Next, next: AccelerometerContract.Event.Next,
state: AccelerometerContract.State.Display, state: AccelerometerContract.State.Display,
onEvent: (AccelerometerContract.Event) -> Unit, onEvent: (AccelerometerContract.Event) -> Unit,
){ ){
@ -85,14 +85,21 @@ fun AccelViewEdit(
shape = CircleShape, shape = CircleShape,
color = MaterialTheme.colorScheme.primaryContainer, color = MaterialTheme.colorScheme.primaryContainer,
onClick = { onClick = {
onEvent(AccelerometerContract.Event.OnAccelViewModelChanged(value))
when(next){ when(next){
AccelerometerContract.Event.OnAccelViewModeEdit.Next.ACCEL -> { AccelerometerContract.Event.Next.ACCEL -> {
onEvent(AccelerometerContract.Event.OnShowAccelerometerAccel) onEvent(AccelerometerContract.Event.OnAccelViewModelChanged(value))
onEvent(AccelerometerContract.Event.OnAccelEdit)
} }
AccelerometerContract.Event.OnAccelViewModeEdit.Next.SPECTRE -> { AccelerometerContract.Event.Next.SPECTRE -> {
onEvent(AccelerometerContract.Event.OnAccelViewModelChanged(value))
onEvent(AccelerometerContract.Event.OnSpectreEdit) onEvent(AccelerometerContract.Event.OnSpectreEdit)
} }
AccelerometerContract.Event.Next.HISTORY -> {
onEvent(AccelerometerContract.Event.OnHistoryViewModeChanged(value))
onEvent(AccelerometerContract.Event.OnHistoryEdit)
}
} }
} }
@ -104,7 +111,7 @@ fun AccelViewEdit(
modifier = Modifier.align(Alignment.Center), modifier = Modifier.align(Alignment.Center),
color = MaterialTheme.colorScheme.background, color = MaterialTheme.colorScheme.background,
style = MaterialTheme.typography.labelLarge, style = MaterialTheme.typography.labelLarge,
text = "Продолжить" text = "Ок"
) )
} }

View File

@ -373,9 +373,12 @@ class AccelerometerAccelViewModel @Inject constructor(
val dataList = this.measureHistory.toMutableList().apply { val dataList = this.measureHistory.toMutableList().apply {
add( add(
Accelerate( Accelerate(
x = ((9806.65f / (Short.MAX_VALUE / 2)) * it.x) * (accelScale.k / 2), //x = ((9806.65f / (Short.MAX_VALUE / 2)) * it.x) * (accelScale.k / 2),
y = ((9806.65f / (Short.MAX_VALUE / 2)) * it.y) * (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) //z = ((9806.65f / (Short.MAX_VALUE / 2)) * it.z) * (accelScale.k / 2)
x = it.x,
y = it.y,
z = it.z
) )
) )
}.takeLast(10) }.takeLast(10)

View File

@ -84,11 +84,11 @@ fun AccelerometerHistory(
viewModel.setEvent(AccelerometerHistoryContract.Event.OnStart(ble.serial, accelScale, accelMode, fftAxis, fftMode, frequency)) viewModel.setEvent(AccelerometerHistoryContract.Event.OnStart(ble.serial, accelScale, accelMode, fftAxis, fftMode, frequency))
} }
DisposableEffect("ble") { /*DisposableEffect("ble") {
onDispose { onDispose {
viewModel.setEvent(AccelerometerHistoryContract.Event.StopMeasure) viewModel.setEvent(AccelerometerHistoryContract.Event.StopMeasure)
} }
} }*/
Column( Column(
modifier = Modifier.fillMaxHeight(0.9f) modifier = Modifier.fillMaxHeight(0.9f)

View File

@ -113,10 +113,27 @@ fun DisplayState(
text = "Сохранять историю измерений" text = "Сохранять историю измерений"
) )
val history = ble.accelerometerState.saveHistory
if(history is Ble.Accelerometer.History.Enabled){
Text(
color = MaterialTheme.colorScheme.secondary,
style = MaterialTheme.typography.bodyMedium,
text = "View mode ${history.mode.localized}"
)
Text(
color = MaterialTheme.colorScheme.secondary,
style = MaterialTheme.typography.bodyMedium,
text = "Scale: ${history.scale.localized}"
)
}
} }
Switch( Switch(
checked = ble.accelerometerState.saveHistory, checked = ble.accelerometerState.saveHistory is Ble.Accelerometer.History.Enabled,
onCheckedChange = { onCheckedChange = {
onEvent(AccelerometerContract.Event.OnSaveHistoryChanged(it)) onEvent(AccelerometerContract.Event.OnSaveHistoryChanged(it))
} }
@ -218,7 +235,7 @@ fun DisplayState(
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
modifier = Modifier modifier = Modifier
.clip(RoundedCornerShape(16.dp)) .clip(RoundedCornerShape(16.dp))
.clickable { onEvent(AccelerometerContract.Event.OnAccelViewModeEdit(next = AccelerometerContract.Event.OnAccelViewModeEdit.Next.ACCEL)) } .clickable { onEvent(AccelerometerContract.Event.OnAccelEdit) }
.padding(8.dp) .padding(8.dp)
) { ) {

View File

@ -0,0 +1,172 @@
package llc.arma.ble.app.ui.screen.inspection.accelerometer.view
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.KeyboardArrowDown
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.RadioButton
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.unit.dp
import llc.arma.ble.app.ui.screen.inspection.accelerometer.AccelerometerContract
import llc.arma.ble.domain.model.Ble
import llc.arma.ble.domain.usecase.AccelScale
import llc.arma.ble.domain.usecase.FftAxis
import llc.arma.ble.domain.usecase.FftFrequency
import llc.arma.ble.domain.usecase.FftViewMode
@Composable
fun HistoryEdit(
state: AccelerometerContract.State.Display,
onEvent: (AccelerometerContract.Event) -> Unit,
){
val history = state.accelerometer.accelerometerState.saveHistory
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
Column(
modifier = Modifier
) {
Text(
modifier = Modifier.padding(horizontal = 12.dp),
text = "История измерений",
style = MaterialTheme.typography.titleLarge
)
Spacer(modifier = Modifier.height(16.dp))
Column(
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.Next.HISTORY
)
)
}
.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,
horizontal = 8.dp
)
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.clip(RoundedCornerShape(16.dp))
.clickable {
onEvent(AccelerometerContract.Event.OnAccelScaleEdit(next = AccelerometerContract.Event.Next.HISTORY))
}
.padding(8.dp)
) {
Column(
modifier = Modifier.weight(1f)
) {
Text(
text = "Accel scale"
)
Text(
color = MaterialTheme.colorScheme.secondary,
style = MaterialTheme.typography.bodyMedium,
text = accelScale.localized
)
}
Icon(
imageVector = Icons.Rounded.KeyboardArrowDown,
contentDescription = null
)
}
}
}
Spacer(modifier = Modifier.height(16.dp))
Surface(
modifier = Modifier
.fillMaxWidth()
.padding(8.dp)
.height(50.dp),
shape = CircleShape,
color = MaterialTheme.colorScheme.primaryContainer,
onClick = {
onEvent(AccelerometerContract.Event.OnHideHistoryEdit)
}
) {
Box(modifier = Modifier.fillMaxSize()) {
Text(
modifier = Modifier.align(Alignment.Center),
color = MaterialTheme.colorScheme.background,
style = MaterialTheme.typography.labelLarge,
text = "Ок"
)
}
}
}
}

View File

@ -22,6 +22,7 @@ import llc.arma.ble.R
import llc.arma.ble.app.ui.screen.inspection.accelerometer.AccelerometerContract import llc.arma.ble.app.ui.screen.inspection.accelerometer.AccelerometerContract
import llc.arma.ble.app.ui.screen.inspection.thermometer.ThermometerContract import llc.arma.ble.app.ui.screen.inspection.thermometer.ThermometerContract
import llc.arma.ble.app.ui.screen.inspection.thermometer.localizedName import llc.arma.ble.app.ui.screen.inspection.thermometer.localizedName
import llc.arma.ble.domain.model.Ble
@Composable @Composable
fun Write( fun Write(
@ -107,7 +108,10 @@ fun Write(
Text( Text(
color = MaterialTheme.colorScheme.secondary, color = MaterialTheme.colorScheme.secondary,
style = MaterialTheme.typography.bodyMedium, style = MaterialTheme.typography.bodyMedium,
text = it.localizedName text = when(it){
Ble.Accelerometer.History.Disabled -> "Выключено"
is Ble.Accelerometer.History.Enabled -> "Включено"
}
) )
} }

View File

@ -524,9 +524,61 @@ class BleRepositoryImpl @Inject constructor(
onSuccess = { return@fold it } onSuccess = { return@fold it }
) )
val historyParams = when(record.timerEnabled){
true -> {
writeCharacteristic(
device = record.device,
serviceId = serviceUUID,
characteristicId = accelerometerReadUUID,
writeData = byteArrayOf(4)
).onFailure {
return Result.failure(BleException.UnexpectedResponse)
}
readCharacteristic(
device = record.device,
serviceId = serviceUUID,
characteristicId = accelerometerReadUUID,
).fold(
onSuccess = {
Log.d("history", it.joinToString { it.toString() })
val scale = when(it[1].toInt()){
0 -> AccelScale.S_2
1 -> AccelScale.S_4
2 -> AccelScale.S_8
3 -> AccelScale.S_16
else -> {
return Result.failure(BleException.UnexpectedResponse)
}
}
val mode = when(it[0].toInt()){
0 -> AccelViewMode.ACCELERATION
1 -> AccelViewMode.PEAK_ACCELERATION
2 -> AccelViewMode.RMS
3 -> AccelViewMode.ANGLE
else -> {
return Result.failure(BleException.UnexpectedResponse)
}
}
Ble.Accelerometer.History.Enabled(
scale = scale,
mode = mode
)
},
onFailure = {
return Result.failure(BleException.UnexpectedResponse)
}
)
}
false -> Ble.Accelerometer.History.Disabled
}
return Result.success( return Result.success(
Ble.Accelerometer.AccelerometerState( Ble.Accelerometer.AccelerometerState(
saveHistory = record.timerEnabled, saveHistory = historyParams,
historyInterval = history historyInterval = history
) )
) )
@ -690,24 +742,62 @@ class BleRepositoryImpl @Inject constructor(
return callbackFlow { return callbackFlow {
deviceCache[serial]?.device?.let { deviceCache[serial]?.device?.let { device ->
if (checkPermission()) { if (checkPermission()) {
gatt = it.connectGatt(app, false, ReadAccelerometerHistoryCallback(app) { val scale = writeCharacteristic(
device = device,
serviceId = serviceUUID,
characteristicId = accelerometerReadUUID,
writeData = byteArrayOf(4)
).fold(
onSuccess = {
readCharacteristic(
device = device,
serviceId = serviceUUID,
characteristicId = accelerometerReadUUID,
).fold(
onSuccess = {
when(it[1].toInt()){
0 -> AccelScale.S_2
1 -> AccelScale.S_4
2 -> AccelScale.S_8
3 -> AccelScale.S_16
else -> null
}
},
onFailure = { null }
)
},
onFailure = {
null
}
)
if(scale != null) {
gatt = device.connectGatt(
app,
false,
ReadAccelerometerHistoryCallback(scale, app) {
CoroutineScope(Dispatchers.IO).launch { CoroutineScope(Dispatchers.IO).launch {
send(it) send(it)
} }
}) })
} else {
CoroutineScope(Dispatchers.IO).launch {
send(Result.failure(BleException.UnexpectedResponse))
}
}
} else { } else {
CoroutineScope(Dispatchers.IO).launch { CoroutineScope(Dispatchers.IO).launch {
send(Result.failure(BleException.PermissionDenied)) send(Result.failure(BleException.PermissionDenied))
} }
return@callbackFlow
} }
} }
@ -865,6 +955,8 @@ class BleRepositoryImpl @Inject constructor(
var gatt: BluetoothGatt? = null var gatt: BluetoothGatt? = null
if(checkPermission()) {
deviceCache[serial]?.let { deviceCache[serial]?.let {
gatt = it.device.connectGatt( gatt = it.device.connectGatt(
@ -885,10 +977,19 @@ class BleRepositoryImpl @Inject constructor(
) )
} }
awaitClose { awaitClose {
gatt?.close() gatt?.close()
} }
} else {
CoroutineScope(Dispatchers.IO).launch {
send(Result.failure(BleException.PermissionDenied))
}
}
} }
@ -919,16 +1020,18 @@ class BleRepositoryImpl @Inject constructor(
gatt.discoverServices() gatt.discoverServices()
} else { } else {
it.resume(Result.failure(BleException.PermissionDenied)) it.resume(Result.failure(BleException.PermissionDenied))
gatt.disconnect()
} }
} else {
gatt.close()
} }
} else { } else {
it.resume(Result.failure(BleException.PermissionDenied)) it.resume(Result.failure(BleException.PermissionDenied))
gatt.disconnect()
} }
@ -954,6 +1057,7 @@ class BleRepositoryImpl @Inject constructor(
} else { } else {
gatt.disconnect()
it.resume(Result.failure(BleException.PermissionDenied)) it.resume(Result.failure(BleException.PermissionDenied))
} }
@ -962,10 +1066,14 @@ class BleRepositoryImpl @Inject constructor(
} }
gatt.disconnect()
it.resume(Result.failure(BleException.UnexpectedResponse)) it.resume(Result.failure(BleException.UnexpectedResponse))
} else { } else {
gatt.disconnect()
it.resume(Result.failure(BleException.UnexpectedResponse)) it.resume(Result.failure(BleException.UnexpectedResponse))
} }
} }
@ -1005,8 +1113,6 @@ class BleRepositoryImpl @Inject constructor(
if(status == BluetoothGatt.GATT_SUCCESS) { if(status == BluetoothGatt.GATT_SUCCESS) {
if (checkPermission()) { if (checkPermission()) {
gatt.close()
result = value result = value
it.resume(Result.success(result!!)) it.resume(Result.success(result!!))
@ -1014,11 +1120,11 @@ class BleRepositoryImpl @Inject constructor(
it.resume(Result.failure(BleException.PermissionDenied)) it.resume(Result.failure(BleException.PermissionDenied))
} }
gatt.disconnect()
} else { } else {
it.resume(Result.failure(BleException.UnexpectedResponse)) it.resume(Result.failure(BleException.UnexpectedResponse))
gatt.disconnect()
} }
} }
@ -1060,7 +1166,7 @@ class BleRepositoryImpl @Inject constructor(
} else { } else {
bleGatt?.close() bleGatt?.disconnect()
it.resume(Result.failure(BleException.PermissionDenied)) it.resume(Result.failure(BleException.PermissionDenied))
} }
@ -1068,13 +1174,12 @@ class BleRepositoryImpl @Inject constructor(
} else { } else {
bleGatt?.close() bleGatt?.close()
it.resume(Result.success(Unit))
} }
} else { } else {
bleGatt?.close() bleGatt?.disconnect()
it.resume(Result.failure(BleException.UnexpectedResponse)) it.resume(Result.failure(BleException.UnexpectedResponse))
} }
@ -1101,7 +1206,7 @@ class BleRepositoryImpl @Inject constructor(
} else { } else {
bleGatt?.close() bleGatt?.disconnect()
it.resume(Result.failure(BleException.PermissionDenied)) it.resume(Result.failure(BleException.PermissionDenied))
} }
@ -1112,12 +1217,12 @@ class BleRepositoryImpl @Inject constructor(
Log.d("write", "service not found") Log.d("write", "service not found")
bleGatt?.close() bleGatt?.disconnect()
it.resume(Result.failure(BleException.UnexpectedResponse)) it.resume(Result.failure(BleException.UnexpectedResponse))
} else { } else {
bleGatt?.close() bleGatt?.disconnect()
it.resume(Result.failure(BleException.UnexpectedResponse)) it.resume(Result.failure(BleException.UnexpectedResponse))
} }
@ -1133,8 +1238,6 @@ class BleRepositoryImpl @Inject constructor(
if (checkPermission()) { if (checkPermission()) {
gatt.close()
if(status == BluetoothGatt.GATT_SUCCESS) { if(status == BluetoothGatt.GATT_SUCCESS) {
it.resume(Result.success(Unit)) it.resume(Result.success(Unit))
@ -1147,11 +1250,12 @@ class BleRepositoryImpl @Inject constructor(
} else { } else {
gatt.close()
it.resume(Result.failure(BleException.PermissionDenied)) it.resume(Result.failure(BleException.PermissionDenied))
} }
gatt.disconnect()
} }
} }

View File

@ -162,22 +162,22 @@ class ReadAccelerometerCallback(
value: ByteArray, value: ByteArray,
){ ){
Log.d("accel", "notification")
val data = value.toList().chunked(2).map { val data = value.toList().chunked(2).map {
it.toByteArray().get2byteShortAt() it.toByteArray().get2byteShortAt()
} }
onResult( 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()}")
Result.success(
Accelerate( val state = Accelerate(
x = data[0].toFloat(), x = (data[0].toFloat() * accelScale.k) / Short.MAX_VALUE,
y = data[1].toFloat(), y = (data[1].toFloat() * accelScale.k) / Short.MAX_VALUE,
z = data[2].toFloat() z = (data[2].toFloat() * accelScale.k) / Short.MAX_VALUE
)
)
) )
Log.d("accel", state.x.toString())
onResult(Result.success(state))
} }
private fun checkPermission(): Boolean { private fun checkPermission(): Boolean {

View File

@ -13,8 +13,10 @@ import llc.arma.ble.domain.Result
import llc.arma.ble.domain.common.BleException import llc.arma.ble.domain.common.BleException
import llc.arma.ble.domain.common.ProgressState import llc.arma.ble.domain.common.ProgressState
import llc.arma.ble.domain.model.Ble import llc.arma.ble.domain.model.Ble
import llc.arma.ble.domain.usecase.AccelScale
class ReadAccelerometerHistoryCallback( class ReadAccelerometerHistoryCallback(
private val scale: AccelScale,
private val app: Application, private val app: Application,
private val onResult: (Result<ProgressState<List<Ble.Accelerometer.MeasurePoint>>, BleException>) -> Unit private val onResult: (Result<ProgressState<List<Ble.Accelerometer.MeasurePoint>>, BleException>) -> Unit
) : BluetoothGattCallback() { ) : BluetoothGattCallback() {
@ -36,6 +38,7 @@ class ReadAccelerometerHistoryCallback(
private var readProperty: Property? = null private var readProperty: Property? = null
init { init {
Log.d("history", scale.name)
onResult(Result.success(ProgressState.Indeterminate)) onResult(Result.success(ProgressState.Indeterminate))
} }
@ -172,6 +175,7 @@ class ReadAccelerometerHistoryCallback(
lastMeasureSystemTime = System.currentTimeMillis() - ((bleRealTime!! - bleLastMeasureTime!!) * 1_000) lastMeasureSystemTime = System.currentTimeMillis() - ((bleRealTime!! - bleLastMeasureTime!!) * 1_000)
val nextPackageDataCount = value.get2byteUIntAt(2)
val temperatureDataArray = value.toUByteArray().asList().subList(16, value.size) val temperatureDataArray = value.toUByteArray().asList().subList(16, value.size)
resultTemperaturePackage.addAll( resultTemperaturePackage.addAll(
@ -180,7 +184,6 @@ class ReadAccelerometerHistoryCallback(
}.toMutableList() }.toMutableList()
) )
val nextPackageDataCount = value.get2byteUIntAt(2)
expectedDataSize = nextPackageDataCount.toInt() + resultTemperaturePackage.size expectedDataSize = nextPackageDataCount.toInt() + resultTemperaturePackage.size
onResult(Result.success(ProgressState.Progress(0f / expectedDataSize!!.toFloat()))) onResult(Result.success(ProgressState.Progress(0f / expectedDataSize!!.toFloat())))
@ -207,7 +210,7 @@ class ReadAccelerometerHistoryCallback(
resultTemperaturePackage.withIndex().map { resultTemperaturePackage.withIndex().map {
Ble.Accelerometer.MeasurePoint( Ble.Accelerometer.MeasurePoint(
frequency = lastMeasureSystemTime!! - (((resultTemperaturePackage.size - 1) - it.index) * bleMeasureInterval!!), frequency = lastMeasureSystemTime!! - (((resultTemperaturePackage.size - 1) - it.index) * bleMeasureInterval!!),
value = it.value value = (it.value * scale.k) / Short.MAX_VALUE
) )
} }
) )
@ -245,7 +248,7 @@ class ReadAccelerometerHistoryCallback(
resultTemperaturePackage.withIndex().map { resultTemperaturePackage.withIndex().map {
Ble.Accelerometer.MeasurePoint( Ble.Accelerometer.MeasurePoint(
frequency = lastMeasureSystemTime!! - (((resultTemperaturePackage.size - 1) - it.index) * bleMeasureInterval!!), frequency = lastMeasureSystemTime!! - (((resultTemperaturePackage.size - 1) - it.index) * bleMeasureInterval!!),
value = it.value value = (it.value * scale.k) / Short.MAX_VALUE
) )
} }
) )

View File

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

View File

@ -96,7 +96,11 @@ class WriteAccelerometerCallback(
Pair( Pair(
saveEnabledWriteUUID, saveEnabledWriteUUID,
mutableListOf<Byte>(4).apply { mutableListOf<Byte>(4).apply {
add(if (it) 1 else 0) add(if (it is Ble.Accelerometer.History.Enabled) 1 else 0)
if(it is Ble.Accelerometer.History.Enabled) {
add(it.mode.sendData)
add(it.scale.sendData)
}
}.toByteArray() }.toByteArray()
) )
} ?: uuid } ?: uuid

View File

@ -1,5 +1,8 @@
package llc.arma.ble.domain.model package llc.arma.ble.domain.model
import llc.arma.ble.domain.usecase.AccelScale
import llc.arma.ble.domain.usecase.AccelViewMode
sealed class Ble( sealed class Ble(
val info: BleInfo val info: BleInfo
) { ) {
@ -10,9 +13,20 @@ sealed class Ble(
val accelerometerState: AccelerometerState val accelerometerState: AccelerometerState
): Ble(info) { ): Ble(info) {
sealed class History {
data class Enabled(
val scale: AccelScale,
val mode: AccelViewMode
) : History()
object Disabled : History()
}
data class WriteRequest( data class WriteRequest(
val tx: BleState.TX?, val tx: BleState.TX?,
val saveHistory: Boolean?, val saveHistory: History?,
val historyInterval: Long? val historyInterval: Long?
) )
@ -21,8 +35,15 @@ sealed class Ble(
val value: Float val value: Float
) )
class HistoryPoint (
val time: Long,
val x: Float,
val y: Float,
val z: Float
)
data class AccelerometerState( data class AccelerometerState(
val saveHistory: Boolean, val saveHistory: History,
val historyInterval: Long val historyInterval: Long
) )

View File

@ -30,7 +30,7 @@ enum class AccelViewMode {
} }
enum class AccelScale(val k: Int) { enum class AccelScale(val k: Int) {
S_2(2), S_4(4), S_8(8), S_16(16) S_2(2_000), S_4(4_000), S_8(8_000), S_16(16_000)
} }
data class Accelerate( data class Accelerate(

View File

@ -14,7 +14,7 @@ buildscript {
}// Top-level build file where you can add configuration options common to all sub-projects/modules. }// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins { plugins {
id 'com.android.application' version '8.0.2' apply false id 'com.android.application' version '8.1.1' apply false
id 'com.android.library' version '8.0.2' apply false id 'com.android.library' version '8.1.1' apply false
id 'org.jetbrains.kotlin.android' version '1.7.0' apply false id 'org.jetbrains.kotlin.android' version '1.7.0' apply false
} }