Add accelerometer

This commit is contained in:
Vineyro 2023-06-05 17:00:20 +07:00
parent e8853d8cda
commit 1270f48422
46 changed files with 844 additions and 101 deletions

View File

@ -7,6 +7,7 @@
<option name="testRunner" value="GRADLE" /> <option name="testRunner" value="GRADLE" />
<option name="distributionType" value="DEFAULT_WRAPPED" /> <option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" /> <option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleJvm" value="jbr-17" />
<option name="modules"> <option name="modules">
<set> <set>
<option value="$PROJECT_DIR$" /> <option value="$PROJECT_DIR$" />

View File

@ -1,6 +1,6 @@
<project version="4"> <project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" /> <component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="temurin-11" project-jdk-type="JavaSDK"> <component name="ProjectRootManager" version="2" languageLevel="JDK_17" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" /> <output url="file://$PROJECT_DIR$/build/classes" />
</component> </component>
<component name="ProjectType"> <component name="ProjectType">

View File

@ -29,11 +29,11 @@ android {
} }
} }
compileOptions { compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8 sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_17
} }
kotlinOptions { kotlinOptions {
jvmTarget = '1.8' jvmTarget = '17'
} }
buildFeatures { buildFeatures {
compose true compose true
@ -50,23 +50,23 @@ android {
dependencies { dependencies {
implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.core:core-ktx:1.10.1'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.6.1' implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.6.1'
implementation 'androidx.activity:activity-compose:1.7.0' implementation 'androidx.activity:activity-compose:1.7.2'
implementation "androidx.compose.ui:ui:1.5.0-alpha01" implementation "androidx.compose.ui:ui:1.5.0-beta01"
implementation "androidx.compose.ui:ui-tooling-preview:1.5.0-alpha01" implementation "androidx.compose.ui:ui-tooling-preview:1.5.0-beta01"
implementation 'androidx.compose.material3:material3:1.1.0-beta01' implementation 'androidx.compose.material3:material3:1.2.0-alpha02'
implementation 'androidx.compose.material:material:1.5.0-alpha01' implementation 'androidx.compose.material:material:1.5.0-beta01'
testImplementation 'junit:junit:4.13.2' testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5' androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
androidTestImplementation "androidx.compose.ui:ui-test-junit4:1.5.0-alpha01" androidTestImplementation "androidx.compose.ui:ui-test-junit4:1.5.0-beta01"
debugImplementation "androidx.compose.ui:ui-tooling:1.5.0-alpha01" debugImplementation "androidx.compose.ui:ui-tooling:1.5.0-beta01"
debugImplementation "androidx.compose.ui:ui-test-manifest:1.5.0-alpha01" debugImplementation "androidx.compose.ui:ui-test-manifest:1.5.0-beta01"
implementation "androidx.compose.material:material-icons-extended:1.5.0-alpha01" implementation "androidx.compose.material:material-icons-extended:1.5.0-beta01"
implementation 'androidx.core:core-splashscreen:1.0.0' implementation 'androidx.core:core-splashscreen:1.0.1'
implementation 'androidx.navigation:navigation-compose:2.5.3' implementation 'androidx.navigation:navigation-compose:2.5.3'
implementation("androidx.hilt:hilt-navigation-compose:1.1.0-alpha01") implementation("androidx.hilt:hilt-navigation-compose:1.1.0-alpha01")
@ -76,8 +76,8 @@ dependencies {
implementation "com.google.accompanist:accompanist-permissions:0.26.3-beta" implementation "com.google.accompanist:accompanist-permissions:0.26.3-beta"
implementation "com.patrykandpatrick.vico:core:1.6.4" implementation "com.patrykandpatrick.vico:core:1.6.6"
implementation "com.patrykandpatrick.vico:compose:1.6.4" implementation "com.patrykandpatrick.vico:compose:1.6.6"
implementation "com.patrykandpatrick.vico:compose-m3:1.6.4" implementation "com.patrykandpatrick.vico:compose-m3:1.6.6"
} }

View File

@ -29,7 +29,7 @@ class BottomState @OptIn(ExperimentalMaterialApi::class) constructor(
) )
class BottomDialogState @OptIn(ExperimentalMaterialApi::class) constructor( class BottomDialogState @OptIn(ExperimentalMaterialApi::class) constructor(
private val sheetState: ModalBottomSheetState?, val sheetState: ModalBottomSheetState?,
val setContent: (@Composable () -> Unit) -> Unit, val setContent: (@Composable () -> Unit) -> Unit,
) { ) {

View File

@ -31,6 +31,12 @@ class BleMapper @Inject constructor(
) )
) )
} }
is Ble.Accelerometer -> {
BleView.Accelerometer(
info = input.info,
)
}
} }
} }

View File

@ -31,6 +31,12 @@ class BleViewMapper @Inject constructor(
) )
) )
} }
is BleView.Accelerometer -> {
Ble.Accelerometer(
info = input.info
)
}
} }
} }

View File

@ -9,6 +9,10 @@ sealed class BleView(
val info: BleInfo val info: BleInfo
) { ) {
class Accelerometer(
info: BleInfo
) : BleView(info)
class Beacon( class Beacon(
info: BleInfo, info: BleInfo,
val state: BleState val state: BleState

View File

@ -35,6 +35,7 @@ fun BleInfoView(
imageVector = when(bleInfo.type){ imageVector = when(bleInfo.type){
BleInfo.Type.BEACON -> Icons.Rounded.Nfc BleInfo.Type.BEACON -> Icons.Rounded.Nfc
BleInfo.Type.THERMOMETER -> Icons.Rounded.Thermostat BleInfo.Type.THERMOMETER -> Icons.Rounded.Thermostat
BleInfo.Type.ACCELEROMETER -> Icons.Rounded.Speed
}, },
contentDescription = null contentDescription = null
) )
@ -43,6 +44,7 @@ fun BleInfoView(
subtitle = when(bleInfo.type){ subtitle = when(bleInfo.type){
BleInfo.Type.BEACON -> "Маяк" BleInfo.Type.BEACON -> "Маяк"
BleInfo.Type.THERMOMETER -> "Термодатчик" BleInfo.Type.THERMOMETER -> "Термодатчик"
BleInfo.Type.ACCELEROMETER -> "Акселерометр"
} }
) )

View File

@ -240,6 +240,7 @@ private fun BleItem(
imageVector = when(ble.type){ imageVector = when(ble.type){
BleInfo.Type.BEACON -> Icons.Rounded.Nfc BleInfo.Type.BEACON -> Icons.Rounded.Nfc
BleInfo.Type.THERMOMETER -> Icons.Rounded.Thermostat BleInfo.Type.THERMOMETER -> Icons.Rounded.Thermostat
BleInfo.Type.ACCELEROMETER -> Icons.Rounded.Speed
}, },
contentDescription = null contentDescription = null
) )

View File

@ -38,7 +38,8 @@ class BleListViewModel @Inject constructor(
} }
override fun setInitialState(): BleListContract.State = BleListContract.State(emptyList(), emptyList(), BleListContract.State.Filter()) override fun setInitialState(): BleListContract.State =
BleListContract.State(emptyList(), emptyList(), BleListContract.State.Filter())
override fun handleEvents(event: BleListContract.Event) { override fun handleEvents(event: BleListContract.Event) {
when(event){ when(event){

View File

@ -43,6 +43,7 @@ private val BleInfo.Type?.localized: String
return when(this){ return when(this){
BleInfo.Type.BEACON -> "Маяк" BleInfo.Type.BEACON -> "Маяк"
BleInfo.Type.THERMOMETER -> "Термодатчик" BleInfo.Type.THERMOMETER -> "Термодатчик"
BleInfo.Type.ACCELEROMETER -> "Акселерометр"
null -> "Все" null -> "Все"
} }
} }

View File

@ -4,8 +4,8 @@ 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.beacon.BeaconContract import llc.arma.ble.app.ui.screen.inspection.beacon.BeaconContract
import llc.arma.ble.app.ui.screen.thermometer.ThermometerContract import llc.arma.ble.app.ui.screen.inspection.thermometer.ThermometerContract
import llc.arma.ble.domain.common.BleException import llc.arma.ble.domain.common.BleException
import llc.arma.ble.domain.model.Ble import llc.arma.ble.domain.model.Ble
import llc.arma.ble.domain.usecase.GetBleBySerial import llc.arma.ble.domain.usecase.GetBleBySerial

View File

@ -20,10 +20,11 @@ import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import llc.arma.ble.app.ui.model.BleView import llc.arma.ble.app.ui.model.BleView
import llc.arma.ble.app.ui.screen.BleInfoView import llc.arma.ble.app.ui.screen.BleInfoView
import llc.arma.ble.app.ui.screen.beacon.BeaconScreen import llc.arma.ble.app.ui.screen.inspection.accelerometer.AccelerometerScreen
import llc.arma.ble.app.ui.screen.inspection.beacon.BeaconScreen
import llc.arma.ble.app.ui.screen.password.ChangePasswordContract import llc.arma.ble.app.ui.screen.password.ChangePasswordContract
import llc.arma.ble.app.ui.screen.thermometer.ThermometerContract import llc.arma.ble.app.ui.screen.inspection.thermometer.ThermometerContract
import llc.arma.ble.app.ui.screen.thermometer.ThermometerScreen import llc.arma.ble.app.ui.screen.inspection.thermometer.ThermometerScreen
import llc.arma.ble.domain.model.Ble import llc.arma.ble.domain.model.Ble
import llc.arma.ble.domain.usecase.GetBleBySerial import llc.arma.ble.domain.usecase.GetBleBySerial
@ -114,6 +115,10 @@ fun ConnectionScreen(
} }
} }
is Ble.Accelerometer -> {
AccelerometerScreen(ble = state.ble)
}
} }
} }

View File

@ -10,8 +10,8 @@ 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.beacon.BeaconContract import llc.arma.ble.app.ui.screen.inspection.beacon.BeaconContract
import llc.arma.ble.app.ui.screen.thermometer.ThermometerContract 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.GetBleBySerial import llc.arma.ble.domain.usecase.GetBleBySerial
import llc.arma.ble.domain.usecase.WriteBle import llc.arma.ble.domain.usecase.WriteBle

View File

@ -0,0 +1,41 @@
package llc.arma.ble.app.ui.screen.inspection.accelerometer
import llc.arma.ble.app.ui.common.ViewEvent
import llc.arma.ble.app.ui.common.ViewSideEffect
import llc.arma.ble.app.ui.common.ViewState
import llc.arma.ble.app.ui.model.BleView
import llc.arma.ble.app.ui.screen.inspection.thermometer.ThermometerContract
import llc.arma.ble.domain.model.Ble
class AccelerometerContract {
sealed class Event : ViewEvent {
object OnShowAccelerometerMeasure : Event()
object OnHideAccelerometerMeasure : Event()
data class OnBleChanged(
val ble: Ble.Accelerometer,
): Event()
}
sealed class State : ViewState {
object Loading : State()
data class Display(
val origin: Ble.Accelerometer,
val accelerometer: BleView.Accelerometer,
) : State()
}
sealed class Effect : ViewSideEffect {
object ShowAccelerometerMeasure : Effect()
}
}

View File

@ -0,0 +1,92 @@
package llc.arma.ble.app.ui.screen.inspection.accelerometer
import androidx.compose.foundation.layout.Column
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.ModalBottomSheetValue
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.hilt.navigation.compose.hiltViewModel
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import llc.arma.ble.app.ui.common.rememberBottomDialogState
import llc.arma.ble.app.ui.screen.inspection.accelerometer.view.AccelerometerMeasure
import llc.arma.ble.app.ui.screen.inspection.accelerometer.view.DisplayState
import llc.arma.ble.app.ui.screen.inspection.accelerometer.view.LoadingState
import llc.arma.ble.domain.model.Ble
enum class SheetPage {
MEASURE_HISTORY
}
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun AccelerometerScreen(
ble: Ble.Accelerometer,
) {
val viewModel = hiltViewModel<AccelerometerViewModel>()
val state = viewModel.viewState.value
val bottomDialog = rememberBottomDialogState()
LaunchedEffect(ble){
viewModel.setEvent(AccelerometerContract.Event.OnBleChanged(ble))
}
var sheetPage by rememberSaveable {
mutableStateOf<SheetPage?>(null)
}
LaunchedEffect(sheetPage) {
when (sheetPage) {
SheetPage.MEASURE_HISTORY -> launch {
val currentState = viewModel.viewState.value
if (currentState is AccelerometerContract.State.Display) {
bottomDialog.show {
AccelerometerMeasure(ble = currentState.accelerometer.info)
}
}
}
null -> {
bottomDialog.hide()
}
}
}
LaunchedEffect("effect"){
viewModel.effect.onEach {
when(it){
AccelerometerContract.Effect.ShowAccelerometerMeasure -> {
sheetPage = null
delay(100)
sheetPage = SheetPage.MEASURE_HISTORY
}
}
}.launchIn(this)
}
Column {
when(state){
is AccelerometerContract.State.Display -> {
DisplayState(
origin = state.origin,
ble = state.accelerometer,
onEvent = {
viewModel.setEvent(it)
}
)
}
is AccelerometerContract.State.Loading -> LoadingState()
}
}
}

View File

@ -0,0 +1,70 @@
package llc.arma.ble.app.ui.screen.inspection.accelerometer
import dagger.hilt.android.lifecycle.HiltViewModel
import llc.arma.ble.app.ui.common.BaseViewModel
import llc.arma.ble.app.ui.mapper.BleMapper
import llc.arma.ble.app.ui.model.BleView
import llc.arma.ble.app.ui.screen.inspection.thermometer.ThermometerContract
import llc.arma.ble.domain.model.Ble
import javax.inject.Inject
@HiltViewModel
class AccelerometerViewModel @Inject constructor(
private val bleMapper: BleMapper
) : BaseViewModel<AccelerometerContract.State, AccelerometerContract.Event, AccelerometerContract.Effect>() {
override fun setInitialState() = AccelerometerContract.State.Loading
override fun handleEvents(event: AccelerometerContract.Event) {
when(event){
is AccelerometerContract.Event.OnBleChanged -> reduce(viewState.value, event)
is AccelerometerContract.Event.OnHideAccelerometerMeasure -> reduce(viewState.value, event)
is AccelerometerContract.Event.OnShowAccelerometerMeasure -> reduce(viewState.value, event)
}
}
private fun reduce(
state: AccelerometerContract.State,
event: AccelerometerContract.Event.OnHideAccelerometerMeasure
) {
}
private fun reduce(
state: AccelerometerContract.State,
event: AccelerometerContract.Event.OnShowAccelerometerMeasure
) {
setEffect {
AccelerometerContract.Effect.ShowAccelerometerMeasure
}
}
private fun reduce(
state: AccelerometerContract.State,
event: AccelerometerContract.Event.OnBleChanged
) {
when (state) {
is AccelerometerContract.State.Display -> setState {
state.copy(
origin = Ble.Accelerometer(
info = event.ble.info
)
)
}
is AccelerometerContract.State.Loading -> setState {
AccelerometerContract.State.Display(
origin = event.ble,
accelerometer = bleMapper.map(event.ble) as BleView.Accelerometer
)
}
}
}
}

View File

@ -0,0 +1,301 @@
package llc.arma.ble.app.ui.screen.inspection.accelerometer.view
import androidx.compose.animation.core.tween
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.viewModelScope
import com.patrykandpatrick.vico.compose.axis.vertical.startAxis
import com.patrykandpatrick.vico.compose.chart.Chart
import com.patrykandpatrick.vico.core.entry.ChartEntryModelProducer
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
import llc.arma.ble.app.ui.common.BaseViewModel
import llc.arma.ble.app.ui.common.ViewEvent
import llc.arma.ble.app.ui.common.ViewSideEffect
import llc.arma.ble.app.ui.common.ViewState
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.text.style.TextAlign
import com.patrykandpatrick.vico.compose.axis.horizontal.bottomAxis
import com.patrykandpatrick.vico.compose.chart.column.columnChart
import com.patrykandpatrick.vico.compose.chart.scroll.rememberChartScrollSpec
import com.patrykandpatrick.vico.core.chart.scale.AutoScaleUp
import com.patrykandpatrick.vico.core.entry.FloatEntry
import com.patrykandpatrick.vico.core.scroll.AutoScrollCondition
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.domain.usecase.GetAccelerometerMeasureBySerialFlow
@Composable
fun AccelerometerMeasure(
ble: BleInfo
) {
val viewModel = hiltViewModel<AccelerometerHistoryViewModel>()
val state = viewModel.viewState.value
LaunchedEffect(ble.serial) {
viewModel.setEvent(AccelerometerMeasureContract.Event.OnStart(ble.serial))
}
DisposableEffect(key1 = ble.serial, effect = {
onDispose {
viewModel.setEvent(AccelerometerMeasureContract.Event.StopMeasure)
}
})
Column(
modifier = Modifier.fillMaxHeight(0.9f)
) {
Row(
modifier = Modifier.padding(horizontal = 12.dp),
verticalAlignment = Alignment.CenterVertically
) {
val title = when(state){
is AccelerometerMeasureContract.State.Display -> {
"История измерений"
}
AccelerometerMeasureContract.State.Exception -> "История измерений"
}
Text(
modifier = Modifier.weight(1f),
text = title,
style = MaterialTheme.typography.titleLarge
)
IconButton(
onClick = {
viewModel.setEvent(AccelerometerMeasureContract.Event.OnRefreshHistory(ble.serial))
},
enabled = true
) {
Icon(
imageVector = Icons.Rounded.Refresh,
contentDescription = null
)
}
}
Spacer(modifier = Modifier.height(16.dp))
Box(modifier = Modifier) {
when (state) {
is AccelerometerMeasureContract.State.Display -> Display(state = state)
AccelerometerMeasureContract.State.Exception -> Exception()
}
}
}
}
@Composable
fun Display(
state: AccelerometerMeasureContract.State.Display
) {
Box(modifier = Modifier
.padding(8.dp)
.fillMaxSize()
) {
if (state.measureHistory.isEmpty()) {
Text(
modifier = Modifier.align(Alignment.Center),
text = "Нет данных"
)
} else {
val producer = remember {
ChartEntryModelProducer(listOf<FloatEntry>())
}
producer.setEntries(state.measureHistory.mapIndexed { index, measurePoint ->
FloatEntry(index.toFloat(), measurePoint)
})
val lineChart = columnChart()
Chart(
chart = lineChart,
chartModelProducer = producer,
startAxis = startAxis(),
bottomAxis = bottomAxis(),
modifier = Modifier.fillMaxSize(),
autoScaleUp = AutoScaleUp.None,
diffAnimationSpec = tween(0),
chartScrollSpec = rememberChartScrollSpec(
initialScroll = InitialScroll.End,
autoScrollCondition = AutoScrollCondition.OnModelSizeIncreased
)
)
}
}
}
@Composable
fun Exception(
) {
Box(
modifier = Modifier
.padding(8.dp)
.fillMaxWidth()
.aspectRatio(2f),
){
Text(
textAlign = TextAlign.Center,
text = "Во время загрузки произошла ошибка",
modifier = Modifier.align(Alignment.Center)
)
}
}
class AccelerometerMeasureContract {
sealed class Event : ViewEvent {
object StopMeasure : Event()
data class OnStart(
val serial: String
) : Event()
data class OnRefreshHistory(
val serial: String
) : Event()
}
sealed class State : ViewState {
data class Display(
val measureHistory : List<Float>
) : State()
object Exception : State()
}
sealed class Effect : ViewSideEffect {
}
}
@HiltViewModel
class AccelerometerHistoryViewModel @Inject constructor(
private val getAccelerometerMeasureBySerialFlow: GetAccelerometerMeasureBySerialFlow,
) : BaseViewModel<AccelerometerMeasureContract.State, AccelerometerMeasureContract.Event, AccelerometerMeasureContract.Effect>() {
var measureJob: Job? = null
private var lastSerial: String? = null
override fun setInitialState() = AccelerometerMeasureContract.State.Display(
emptyList()
)
override fun handleEvents(event: AccelerometerMeasureContract.Event) {
when(event){
is AccelerometerMeasureContract.Event.OnStart -> reduce(viewState.value, event)
is AccelerometerMeasureContract.Event.OnRefreshHistory -> reduce(viewState.value, event)
is AccelerometerMeasureContract.Event.StopMeasure -> reduce(viewState.value, event)
}
}
private fun reduce(
state: AccelerometerMeasureContract.State,
event: AccelerometerMeasureContract.Event.StopMeasure
) {
measureJob?.cancel()
setState {
AccelerometerMeasureContract.State.Display(emptyList())
}
}
private fun reduce(
state: AccelerometerMeasureContract.State,
event: AccelerometerMeasureContract.Event.OnStart
) {
startReadMeasure(event.serial, false)
}
private fun reduce(
state: AccelerometerMeasureContract.State,
event: AccelerometerMeasureContract.Event.OnRefreshHistory
) {
startReadMeasure(event.serial, true)
}
private fun startReadMeasure(serial: String, restartJob: Boolean){
if(restartJob || measureJob == null) {
measureJob = viewModelScope.launch {
setState {
AccelerometerMeasureContract.State.Display(emptyList())
}
getAccelerometerMeasureBySerialFlow(serial).onEach {
it.fold(
onSuccess = {
setState {
when (this) {
is AccelerometerMeasureContract.State.Display -> {
val dataList = this.measureHistory.toMutableList().apply {
add(it)
}
AccelerometerMeasureContract.State.Display(dataList)
}
AccelerometerMeasureContract.State.Exception -> {
AccelerometerMeasureContract.State.Display(listOf(it))
}
}
}
},
onFailure = {
setState {
AccelerometerMeasureContract.State.Exception
}
}
)
}.launchIn(this)
}
}
}
}

View File

@ -0,0 +1,121 @@
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.material.icons.rounded.KeyboardArrowRight
import androidx.compose.material.icons.rounded.Refresh
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
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.model.BleView
import llc.arma.ble.app.ui.screen.BleInfoView
import llc.arma.ble.app.ui.screen.inspection.accelerometer.AccelerometerContract
import llc.arma.ble.app.ui.screen.inspection.thermometer.ThermometerContract
import llc.arma.ble.domain.model.Ble
@Composable
fun DisplayState(
onEvent: (AccelerometerContract.Event) -> Unit,
origin: Ble.Accelerometer,
ble: BleView.Accelerometer
) {
Column() {
Column(
modifier = Modifier
.verticalScroll(rememberScrollState())
.weight(1f)
) {
Box(
modifier = Modifier.padding(
vertical = 8.dp,
horizontal = 8.dp
)
) {
BleInfoView(bleInfo = origin.info)
}
Column(
modifier = Modifier,
content = {
Box(
modifier = Modifier.padding(
vertical = 8.dp,
horizontal = 8.dp
)
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.clip(RoundedCornerShape(16.dp))
.clickable {
onEvent(AccelerometerContract.Event.OnShowAccelerometerMeasure)
}
.padding(8.dp)
) {
Column(
modifier = Modifier.weight(1f)
) {
Text(
text = "График измерений"
)
}
Icon(
imageVector = Icons.Rounded.KeyboardArrowRight,
contentDescription = null
)
}
}
}
)
}
Surface(
modifier = Modifier
.fillMaxWidth()
.padding(8.dp)
.height(50.dp),
shape = CircleShape,
color = MaterialTheme.colorScheme.primaryContainer,
onClick = {
}
) {
Box(modifier = Modifier.fillMaxSize()) {
Text(
modifier = Modifier.align(Alignment.Center),
color = MaterialTheme.colorScheme.background,
style = MaterialTheme.typography.labelLarge,
text = "Сохранить"
)
}
}
}
}

View File

@ -0,0 +1,19 @@
package llc.arma.ble.app.ui.screen.inspection.accelerometer.view
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@Composable
fun LoadingState(){
Box(modifier = Modifier.fillMaxSize()) {
CircularProgressIndicator(modifier = Modifier.align(Alignment.Center))
}
}

View File

@ -1,10 +1,10 @@
package llc.arma.ble.app.ui.screen.beacon package llc.arma.ble.app.ui.screen.inspection.beacon
import llc.arma.ble.app.ui.common.ViewEvent 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.thermometer.ThermometerContract import llc.arma.ble.app.ui.screen.inspection.thermometer.ThermometerContract
import llc.arma.ble.domain.model.Ble import llc.arma.ble.domain.model.Ble
class BeaconContract { class BeaconContract {

View File

@ -1,4 +1,4 @@
package llc.arma.ble.app.ui.screen.beacon package llc.arma.ble.app.ui.screen.inspection.beacon
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.CircleShape
@ -19,10 +19,10 @@ 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.beacon.view.DisplayState import llc.arma.ble.app.ui.screen.inspection.beacon.view.DisplayState
import llc.arma.ble.app.ui.screen.beacon.view.PowerEdit import llc.arma.ble.app.ui.screen.inspection.beacon.view.PowerEdit
import llc.arma.ble.app.ui.screen.beacon.view.Write import llc.arma.ble.app.ui.screen.inspection.beacon.view.Write
import llc.arma.ble.app.ui.screen.thermometer.localizedName import llc.arma.ble.app.ui.screen.inspection.thermometer.localizedName
import llc.arma.ble.domain.model.Ble import llc.arma.ble.domain.model.Ble
enum class SheetPage { enum class SheetPage {

View File

@ -1,4 +1,4 @@
package llc.arma.ble.app.ui.screen.beacon package llc.arma.ble.app.ui.screen.inspection.beacon
import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
@ -11,7 +11,7 @@ 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.thermometer.ThermometerContract 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.model.BleInfo import llc.arma.ble.domain.model.BleInfo
import llc.arma.ble.domain.usecase.WriteBle import llc.arma.ble.domain.usecase.WriteBle

View File

@ -1,4 +1,4 @@
package llc.arma.ble.app.ui.screen.beacon.view package llc.arma.ble.app.ui.screen.inspection.beacon.view
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
@ -17,7 +17,7 @@ import androidx.compose.ui.draw.clip
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import llc.arma.ble.app.ui.model.BleView import llc.arma.ble.app.ui.model.BleView
import llc.arma.ble.app.ui.screen.BleInfoView import llc.arma.ble.app.ui.screen.BleInfoView
import llc.arma.ble.app.ui.screen.beacon.BeaconContract import llc.arma.ble.app.ui.screen.inspection.beacon.BeaconContract
import llc.arma.ble.domain.model.Ble import llc.arma.ble.domain.model.Ble
@Composable @Composable

View File

@ -1,4 +1,4 @@
package llc.arma.ble.app.ui.screen.beacon.view package llc.arma.ble.app.ui.screen.inspection.beacon.view
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
@ -14,8 +14,8 @@ 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.model.BleView import llc.arma.ble.app.ui.model.BleView
import llc.arma.ble.app.ui.screen.beacon.BeaconContract import llc.arma.ble.app.ui.screen.inspection.beacon.BeaconContract
import llc.arma.ble.app.ui.screen.thermometer.ThermometerContract import llc.arma.ble.app.ui.screen.inspection.thermometer.ThermometerContract
@Composable @Composable
fun PowerEdit( fun PowerEdit(

View File

@ -1,4 +1,4 @@
package llc.arma.ble.app.ui.screen.beacon.view package llc.arma.ble.app.ui.screen.inspection.beacon.view
import androidx.compose.animation.animateContentSize import androidx.compose.animation.animateContentSize
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
@ -17,8 +17,8 @@ import androidx.compose.ui.graphics.StrokeCap
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import llc.arma.ble.R import llc.arma.ble.R
import llc.arma.ble.app.ui.screen.beacon.BeaconContract import llc.arma.ble.app.ui.screen.inspection.beacon.BeaconContract
import llc.arma.ble.app.ui.screen.thermometer.localizedName import llc.arma.ble.app.ui.screen.inspection.thermometer.localizedName
@Composable @Composable
fun Write( fun Write(

View File

@ -1,4 +1,4 @@
package llc.arma.ble.app.ui.screen.thermometer package llc.arma.ble.app.ui.screen.inspection.thermometer
import llc.arma.ble.app.ui.common.ViewEvent import llc.arma.ble.app.ui.common.ViewEvent
import llc.arma.ble.app.ui.common.ViewSideEffect import llc.arma.ble.app.ui.common.ViewSideEffect

View File

@ -1,34 +1,26 @@
package llc.arma.ble.app.ui.screen.thermometer package llc.arma.ble.app.ui.screen.inspection.thermometer
import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.ModalBottomSheetLayout import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material.ModalBottomSheetValue import androidx.compose.runtime.Composable
import androidx.compose.material.icons.Icons import androidx.compose.runtime.LaunchedEffect
import androidx.compose.material.icons.rounded.KeyboardArrowDown import androidx.compose.runtime.getValue
import androidx.compose.material3.* import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.draw.clip
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel import androidx.hilt.navigation.compose.hiltViewModel
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.launchIn 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.R
import llc.arma.ble.app.ui.common.rememberBottomDialogState import llc.arma.ble.app.ui.common.rememberBottomDialogState
import llc.arma.ble.app.ui.screen.thermometer.view.* import llc.arma.ble.app.ui.screen.inspection.thermometer.view.DisplayState
import llc.arma.ble.app.ui.screen.inspection.thermometer.view.IntervalEdit
import llc.arma.ble.app.ui.screen.inspection.thermometer.view.LoadingState
import llc.arma.ble.app.ui.screen.inspection.thermometer.view.PowerEdit
import llc.arma.ble.app.ui.screen.inspection.thermometer.view.TemperatureHistory
import llc.arma.ble.app.ui.screen.inspection.thermometer.view.Write
import llc.arma.ble.domain.model.Ble import llc.arma.ble.domain.model.Ble
enum class SheetPage { enum class SheetPage {
@ -74,7 +66,6 @@ fun ThermometerScreen(
val viewModel = hiltViewModel<ThermometerViewModel>() val viewModel = hiltViewModel<ThermometerViewModel>()
val state = viewModel.viewState.value val state = viewModel.viewState.value
val bottomDialog = rememberBottomDialogState() val bottomDialog = rememberBottomDialogState()
LaunchedEffect(sheetPage){ LaunchedEffect(sheetPage){
@ -142,8 +133,6 @@ fun ThermometerScreen(
} }
} }
val writeSheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
LaunchedEffect("effect"){ LaunchedEffect("effect"){
viewModel.effect.onEach { viewModel.effect.onEach {
when(it){ when(it){

View File

@ -1,4 +1,4 @@
package llc.arma.ble.app.ui.screen.thermometer package llc.arma.ble.app.ui.screen.inspection.thermometer
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
@ -201,7 +201,9 @@ class ThermometerViewModel @Inject constructor(
setState { setState {
state.copy( state.copy(
writeState = ThermometerContract.State.Display.WriteState.Writing(request.writeRequest) writeState = ThermometerContract.State.Display.WriteState.Writing(
request.writeRequest
)
) )
} }

View File

@ -1,4 +1,4 @@
package llc.arma.ble.app.ui.screen.thermometer.view package llc.arma.ble.app.ui.screen.inspection.thermometer.view
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
@ -18,7 +18,8 @@ import androidx.compose.ui.draw.clip
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import llc.arma.ble.app.ui.model.BleView import llc.arma.ble.app.ui.model.BleView
import llc.arma.ble.app.ui.screen.BleInfoView import llc.arma.ble.app.ui.screen.BleInfoView
import llc.arma.ble.app.ui.screen.thermometer.ThermometerContract import llc.arma.ble.app.ui.screen.inspection.accelerometer.AccelerometerContract
import llc.arma.ble.app.ui.screen.inspection.thermometer.ThermometerContract
import llc.arma.ble.domain.model.Ble import llc.arma.ble.domain.model.Ble
@Composable @Composable

View File

@ -1,4 +1,4 @@
package llc.arma.ble.app.ui.screen.thermometer.view package llc.arma.ble.app.ui.screen.inspection.thermometer.view
import androidx.compose.animation.* import androidx.compose.animation.*
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
@ -12,7 +12,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import llc.arma.ble.app.ui.model.BleView import llc.arma.ble.app.ui.model.BleView
import llc.arma.ble.app.ui.screen.thermometer.ThermometerContract import llc.arma.ble.app.ui.screen.inspection.thermometer.ThermometerContract
@Composable @Composable
fun IntervalEdit( fun IntervalEdit(
@ -165,11 +165,11 @@ fun NumberPicker(
targetState = value, targetState = value,
transitionSpec = { transitionSpec = {
if (targetState > initialState) { if (targetState > initialState) {
slideInVertically { height -> height } + fadeIn() with (slideInVertically { height -> height } + fadeIn()).togetherWith(
slideOutVertically { height -> -height } + fadeOut() slideOutVertically { height -> -height } + fadeOut())
} else { } else {
slideInVertically { height -> -height } + fadeIn() with (slideInVertically { height -> -height } + fadeIn()).togetherWith(
slideOutVertically { height -> height } + fadeOut() slideOutVertically { height -> height } + fadeOut())
}.using( }.using(
SizeTransform(clip = false) SizeTransform(clip = false)
) )

View File

@ -1,4 +1,4 @@
package llc.arma.ble.app.ui.screen.thermometer.view package llc.arma.ble.app.ui.screen.inspection.thermometer.view
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize

View File

@ -1,4 +1,4 @@
package llc.arma.ble.app.ui.screen.thermometer.view package llc.arma.ble.app.ui.screen.inspection.thermometer.view
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
@ -14,7 +14,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.model.BleView import llc.arma.ble.app.ui.model.BleView
import llc.arma.ble.app.ui.screen.thermometer.ThermometerContract import llc.arma.ble.app.ui.screen.inspection.thermometer.ThermometerContract
@Composable @Composable
fun PowerEdit( fun PowerEdit(

View File

@ -1,4 +1,4 @@
package llc.arma.ble.app.ui.screen.thermometer.view package llc.arma.ble.app.ui.screen.inspection.thermometer.view
import androidx.compose.animation.core.FastOutSlowInEasing import androidx.compose.animation.core.FastOutSlowInEasing
import androidx.compose.animation.core.animateFloatAsState import androidx.compose.animation.core.animateFloatAsState

View File

@ -1,4 +1,4 @@
package llc.arma.ble.app.ui.screen.thermometer.view package llc.arma.ble.app.ui.screen.inspection.thermometer.view
import androidx.compose.animation.animateContentSize import androidx.compose.animation.animateContentSize
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
@ -19,8 +19,8 @@ import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import llc.arma.ble.R import llc.arma.ble.R
import llc.arma.ble.app.ui.screen.thermometer.ThermometerContract import llc.arma.ble.app.ui.screen.inspection.thermometer.ThermometerContract
import llc.arma.ble.app.ui.screen.thermometer.localizedName import llc.arma.ble.app.ui.screen.inspection.thermometer.localizedName
@Composable @Composable
fun Write( fun Write(

View File

@ -6,9 +6,9 @@ import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable import androidx.navigation.compose.composable
import androidx.navigation.compose.dialog import androidx.navigation.compose.dialog
import androidx.navigation.compose.rememberNavController import androidx.navigation.compose.rememberNavController
import llc.arma.ble.app.ui.screen.beacon.BeaconContract import llc.arma.ble.app.ui.screen.inspection.beacon.BeaconContract
import llc.arma.ble.app.ui.screen.thermometer.ThermometerScreen import llc.arma.ble.app.ui.screen.inspection.thermometer.ThermometerScreen
import llc.arma.ble.app.ui.screen.beacon.BeaconScreen import llc.arma.ble.app.ui.screen.inspection.beacon.BeaconScreen
import llc.arma.ble.app.ui.screen.ble.BleListContract import llc.arma.ble.app.ui.screen.ble.BleListContract
import llc.arma.ble.app.ui.screen.ble.BleListScreen import llc.arma.ble.app.ui.screen.ble.BleListScreen
import llc.arma.ble.app.ui.screen.connection.ConnectionContract import llc.arma.ble.app.ui.screen.connection.ConnectionContract

View File

@ -23,7 +23,7 @@ import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import llc.arma.ble.app.ui.screen.password.view.Loading import llc.arma.ble.app.ui.screen.password.view.Loading
import llc.arma.ble.app.ui.screen.password.view.Result import llc.arma.ble.app.ui.screen.password.view.Result
import llc.arma.ble.app.ui.screen.thermometer.view.LoadingState import llc.arma.ble.app.ui.screen.inspection.thermometer.view.LoadingState
@Composable @Composable
fun ChangePasswordScreen( fun ChangePasswordScreen(

View File

@ -72,7 +72,7 @@ fun BleTheme(
SideEffect { SideEffect {
currentWindow.statusBarColor = LightColorScheme.primary.copy(alpha = 0f).toArgb() currentWindow.statusBarColor = LightColorScheme.primary.copy(alpha = 0f).toArgb()
WindowCompat.getInsetsController(currentWindow, view).isAppearanceLightStatusBars = darkTheme.not() WindowCompat.getInsetsController(currentWindow, view).isAppearanceLightStatusBars = true
} }
} }

View File

@ -11,6 +11,7 @@ import android.os.Build
import android.os.SystemClock import android.os.SystemClock
import android.util.Log import android.util.Log
import androidx.core.app.ActivityCompat import androidx.core.app.ActivityCompat
import androidx.core.util.toRange
import kotlinx.coroutines.* import kotlinx.coroutines.*
import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
@ -27,6 +28,7 @@ import java.util.*
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
import kotlin.coroutines.resume import kotlin.coroutines.resume
import kotlin.random.Random
val serviceUUID: UUID = UUID.fromString("a77db03a-9bc4-11ed-a8fc-0242ac120002") val serviceUUID: UUID = UUID.fromString("a77db03a-9bc4-11ed-a8fc-0242ac120002")
@ -83,8 +85,9 @@ class BleRepositoryImpl @Inject constructor(
private val ScanResult.type: BleInfo.Type private val ScanResult.type: BleInfo.Type
get() { get() {
return when(scanRecord?.manufacturerSpecificData?.get(89)?.get(0)?.toUByte()?.toInt()){ return when(scanRecord?.manufacturerSpecificData?.get(89)?.get(0)?.toUByte()?.toInt()){
1 -> BleInfo.Type.BEACON
2 -> BleInfo.Type.THERMOMETER 2 -> BleInfo.Type.THERMOMETER
else -> BleInfo.Type.BEACON else -> BleInfo.Type.ACCELEROMETER
} }
} }
@ -135,13 +138,13 @@ class BleRepositoryImpl @Inject constructor(
if (checkPermission()) { if (checkPermission()) {
if (result.scanRecord?.deviceName?.contains("ArmA") == true) { //if (result.scanRecord?.deviceName?.contains("ArmA") == true) {
resultList[result.device.address] = result.info resultList[result.device.address] = result.info
deviceCache[result.device.address] = result deviceCache[result.device.address] = result
} //}
} else { } else {
CoroutineScope(Dispatchers.IO).launch { CoroutineScope(Dispatchers.IO).launch {
@ -227,6 +230,38 @@ class BleRepositoryImpl @Inject constructor(
deviceCache[serial]?.let { result -> deviceCache[serial]?.let { result ->
return when(result.info.type) { return when(result.info.type) {
BleInfo.Type.ACCELEROMETER -> {
Result.success(
flow {
while (true) {
deviceCache[serial]?.let { newResult ->
emit(
Ble.Accelerometer(
info = newResult.info.copy(
rssi = if((SystemClock.elapsedRealtimeNanos() - newResult.timestampNanos) > 15_000_000_000) {
null
} else {
newResult.rssi
}
)
)
)
}
delay(1_000)
}
}
)
}
BleInfo.Type.BEACON -> { BleInfo.Type.BEACON -> {
Result.success( Result.success(
flow { flow {
@ -342,6 +377,9 @@ class BleRepositoryImpl @Inject constructor(
} }
BleInfo.Type.ACCELEROMETER -> {
TODO()
}
} }
} }
@ -577,6 +615,19 @@ class BleRepositoryImpl @Inject constructor(
return Result.success(Unit) return Result.success(Unit)
} }
override fun getAccelerometerMeasureBySerialFlow(serial: String): Flow<Result<Float, BleException>> {
return flow {
while (true){
delay(1000)
emit(
Result.success(((-256)..256).random().toFloat())
)
}
}
}
private suspend fun readCharacteristic( private suspend fun readCharacteristic(
device: BluetoothDevice, device: BluetoothDevice,
serviceId: UUID, serviceId: UUID,

View File

@ -4,6 +4,12 @@ sealed class Ble(
val info: BleInfo val info: BleInfo
) { ) {
class Accelerometer(
info: BleInfo
): Ble(info){
}
class Beacon( class Beacon(
info: BleInfo, info: BleInfo,
val state: BleState val state: BleState

View File

@ -10,7 +10,7 @@ data class BleInfo(
){ ){
enum class Type { enum class Type {
BEACON, THERMOMETER BEACON, THERMOMETER, ACCELEROMETER
} }
} }

View File

@ -24,5 +24,6 @@ interface BleRepository {
suspend fun writeBle(serial: String, request: Ble.Beacon.WriteRequest): Result<Unit, BleException> suspend fun writeBle(serial: String, request: Ble.Beacon.WriteRequest): Result<Unit, BleException>
suspend fun changeBlePassword(password: String, serial: String): Result<Unit, BleException> suspend fun changeBlePassword(password: String, serial: String): Result<Unit, BleException>
fun getAccelerometerMeasureBySerialFlow(serial: String): Flow<Result<Float, BleException>>
} }

View File

@ -0,0 +1,21 @@
package llc.arma.ble.domain.usecase
import kotlinx.coroutines.flow.Flow
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 llc.arma.ble.domain.repository.BleRepository
import javax.inject.Inject
class GetAccelerometerMeasureBySerialFlow @Inject constructor(
private val bleRepository: BleRepository
) {
operator fun invoke(serial: String): Flow<Result<Float, BleException>> {
return bleRepository.getAccelerometerMeasureBySerialFlow(serial)
}
}

View File

@ -12,7 +12,7 @@
<style name="Theme.Ble" parent="android:Theme.Material.Light.NoActionBar" > <style name="Theme.Ble" parent="android:Theme.Material.Light.NoActionBar" >
<item name="android:statusBarColor">#00000000</item> <item name="android:statusBarColor">#00000000</item>
<item name="android:navigationBarColor">#ffffffff</item> <item name="android:navigationBarColor">#ffffffff</item>
<item name="android:windowLightStatusBar" >true</item> <item name="android:windowLightStatusBar">true</item>
</style> </style>
</resources> </resources>

View File

@ -6,7 +6,7 @@ buildscript {
dependencies { dependencies {
classpath('com.google.dagger:hilt-android-gradle-plugin:2.45') classpath('com.google.dagger:hilt-android-gradle-plugin:2.45')
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.10"
} }
repositories { repositories {
mavenCentral() mavenCentral()
@ -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.0' apply false id 'com.android.application' version '8.0.2' apply false
id 'com.android.library' version '8.0.0' apply false id 'com.android.library' version '8.0.2' apply false
id 'org.jetbrains.kotlin.android' version '1.7.0' apply false id 'org.jetbrains.kotlin.android' version '1.7.0' apply false
} }

View File

@ -23,3 +23,4 @@ kotlin.code.style=official
android.nonTransitiveRClass=true android.nonTransitiveRClass=true
android.defaults.buildfeatures.buildconfig=true android.defaults.buildfeatures.buildconfig=true
android.nonFinalResIds=false android.nonFinalResIds=false
org.gradle.unsafe.configuration-cache=true