diff --git a/app/build.gradle b/app/build.gradle
index 959d359..e132dfb 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -13,8 +13,8 @@ android {
applicationId "llc.arma.ble"
minSdk 26
targetSdk 34
- versionCode 18
- versionName "1.2.18"
+ versionCode 22
+ versionName "1.3.2"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
@@ -86,8 +86,8 @@ dependencies {
kapt('com.google.dagger:hilt-android-compiler:2.45')
kapt("androidx.hilt:hilt-compiler:1.0.0")
- implementation 'no.nordicsemi.android.kotlin.ble:scanner:1.0.14'
- implementation 'no.nordicsemi.android.kotlin.ble:client:1.0.14'
+ implementation 'no.nordicsemi.android.kotlin.ble:scanner:1.0.19'
+ implementation 'no.nordicsemi.android.kotlin.ble:client:1.0.19'
implementation "com.google.accompanist:accompanist-permissions:0.26.3-beta"
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index f9ed2e5..7041d30 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -7,8 +7,10 @@
-
-
+
+
-
+
+
diff --git a/app/src/main/java/llc/arma/ble/app/ui/mapper/BleMapper.kt b/app/src/main/java/llc/arma/ble/app/ui/mapper/BleMapper.kt
index aaed0c2..d1c295d 100644
--- a/app/src/main/java/llc/arma/ble/app/ui/mapper/BleMapper.kt
+++ b/app/src/main/java/llc/arma/ble/app/ui/mapper/BleMapper.kt
@@ -39,7 +39,7 @@ class BleMapper @Inject constructor(
tx = txMapper.map(input.state.tx)
),
accelerometerState = BleView.Accelerometer.AccelerometerState(
- saveHistory = input.accelerometerState.saveHistory,
+ saveHistorySettings = input.accelerometerState.saveHistorySettings,
historyInterval = input.accelerometerState.historyInterval
)
)
diff --git a/app/src/main/java/llc/arma/ble/app/ui/mapper/BleViewMapper.kt b/app/src/main/java/llc/arma/ble/app/ui/mapper/BleViewMapper.kt
index 012e920..b13ea1c 100644
--- a/app/src/main/java/llc/arma/ble/app/ui/mapper/BleViewMapper.kt
+++ b/app/src/main/java/llc/arma/ble/app/ui/mapper/BleViewMapper.kt
@@ -39,7 +39,7 @@ class BleViewMapper @Inject constructor(
tx = txMapper.map(input.state.tx)
),
accelerometerState = Ble.Accelerometer.AccelerometerState(
- saveHistory = input.accelerometerState.saveHistory,
+ saveHistorySettings = input.accelerometerState.saveHistory,
historyInterval = input.accelerometerState.historyInterval,
)
)
diff --git a/app/src/main/java/llc/arma/ble/app/ui/model/BleView.kt b/app/src/main/java/llc/arma/ble/app/ui/model/BleView.kt
index 7f134cb..747a881 100644
--- a/app/src/main/java/llc/arma/ble/app/ui/model/BleView.kt
+++ b/app/src/main/java/llc/arma/ble/app/ui/model/BleView.kt
@@ -5,8 +5,6 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import llc.arma.ble.domain.model.Ble
import llc.arma.ble.domain.model.BleInfo
-import llc.arma.ble.domain.usecase.AccelScale
-import llc.arma.ble.domain.usecase.AccelViewMode
sealed class BleView(
val info: BleInfo
@@ -19,10 +17,10 @@ sealed class BleView(
) : BleView(info) {
class AccelerometerState(
- saveHistory: Ble.Accelerometer.History,
+ saveHistorySettings: Ble.Accelerometer.HistorySettings,
historyInterval: Long,
) {
- var saveHistory by mutableStateOf(saveHistory)
+ var saveHistory by mutableStateOf(saveHistorySettings)
var historyInterval by mutableStateOf(historyInterval)
}
diff --git a/app/src/main/java/llc/arma/ble/app/ui/screen/ble/BleListViewModel.kt b/app/src/main/java/llc/arma/ble/app/ui/screen/ble/BleListViewModel.kt
index 85b5bff..d7484bd 100644
--- a/app/src/main/java/llc/arma/ble/app/ui/screen/ble/BleListViewModel.kt
+++ b/app/src/main/java/llc/arma/ble/app/ui/screen/ble/BleListViewModel.kt
@@ -24,7 +24,23 @@ class BleListViewModel @Inject constructor(
var job: Job? = null
- while (true) {
+ getBleAroundFlow().fold(
+ onSuccess = {
+ it.onEach {
+ setState {
+ copy(
+ connectedBleList = emptyList(),
+ bleList = it
+ )
+ }
+ }.launchIn(viewModelScope)
+ },
+ onFailure = {
+ throw IllegalStateException()
+ }
+ )
+
+ /*while (true) {
job?.cancel()
job = getBleAroundFlow().onEach {
@@ -46,7 +62,7 @@ class BleListViewModel @Inject constructor(
delay(30_000)
- }
+ }*/
}
diff --git a/app/src/main/java/llc/arma/ble/app/ui/screen/inspection/accelerometer/AccelerometerViewModel.kt b/app/src/main/java/llc/arma/ble/app/ui/screen/inspection/accelerometer/AccelerometerViewModel.kt
index 44c40fd..d248f72 100644
--- a/app/src/main/java/llc/arma/ble/app/ui/screen/inspection/accelerometer/AccelerometerViewModel.kt
+++ b/app/src/main/java/llc/arma/ble/app/ui/screen/inspection/accelerometer/AccelerometerViewModel.kt
@@ -82,8 +82,8 @@ class AccelerometerViewModel @Inject constructor(
var saveHistory = state.accelerometer.accelerometerState.saveHistory
- if(saveHistory is Ble.Accelerometer.History.Enabled){
- saveHistory = Ble.Accelerometer.History.Enabled(
+ if(saveHistory is Ble.Accelerometer.HistorySettings.Enabled){
+ saveHistory = Ble.Accelerometer.HistorySettings.Enabled(
mode = event.mode,
scale = saveHistory.scale,
detailed = saveHistory.detailed
@@ -105,7 +105,7 @@ class AccelerometerViewModel @Inject constructor(
var saveHistory = state.accelerometer.accelerometerState.saveHistory
- if(saveHistory is Ble.Accelerometer.History.Enabled){
+ if(saveHistory is Ble.Accelerometer.HistorySettings.Enabled){
saveHistory = saveHistory.copy(scale = event.scale)
}
@@ -199,7 +199,7 @@ class AccelerometerViewModel @Inject constructor(
if(event.save){
- state.accelerometer.accelerometerState.saveHistory = Ble.Accelerometer.History.Enabled(
+ state.accelerometer.accelerometerState.saveHistory = Ble.Accelerometer.HistorySettings.Enabled(
scale = AccelScale.S_2,
mode = AccelViewMode.ACCELERATION,
detailed = true
@@ -211,7 +211,7 @@ class AccelerometerViewModel @Inject constructor(
} else {
- state.accelerometer.accelerometerState.saveHistory = Ble.Accelerometer.History.Disabled
+ state.accelerometer.accelerometerState.saveHistory = Ble.Accelerometer.HistorySettings.Disabled
}
@@ -397,7 +397,7 @@ class AccelerometerViewModel @Inject constructor(
val writeRequest = Ble.Accelerometer.WriteRequest(
tx = if(newBle.state.tx == state.origin.state.tx) null else newBle.state.tx,
- saveHistory = if(newBle.accelerometerState.saveHistory == state.origin.accelerometerState.saveHistory) null else newBle.accelerometerState.saveHistory,
+ saveHistorySettings = if(newBle.accelerometerState.saveHistorySettings == state.origin.accelerometerState.saveHistorySettings) null else newBle.accelerometerState.saveHistorySettings,
historyInterval = if(newBle.accelerometerState.historyInterval == state.origin.accelerometerState.historyInterval) null else newBle.accelerometerState.historyInterval,
)
@@ -565,8 +565,8 @@ class AccelerometerViewModel @Inject constructor(
tx = request.writeRequest.tx ?: state.origin.state.tx
),
accelerometerState = currentState.origin.accelerometerState.copy(
- saveHistory = request.writeRequest.saveHistory
- ?: currentState.origin.accelerometerState.saveHistory
+ saveHistorySettings = request.writeRequest.saveHistorySettings
+ ?: currentState.origin.accelerometerState.saveHistorySettings
)
)
diff --git a/app/src/main/java/llc/arma/ble/app/ui/screen/inspection/accelerometer/view/AccelScaleEdit.kt b/app/src/main/java/llc/arma/ble/app/ui/screen/inspection/accelerometer/view/AccelScaleEdit.kt
index 1402fc0..8bcd84b 100644
--- a/app/src/main/java/llc/arma/ble/app/ui/screen/inspection/accelerometer/view/AccelScaleEdit.kt
+++ b/app/src/main/java/llc/arma/ble/app/ui/screen/inspection/accelerometer/view/AccelScaleEdit.kt
@@ -2,13 +2,8 @@ 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
@@ -21,10 +16,6 @@ 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(
@@ -39,7 +30,7 @@ fun AccelScaleEdit(
state.accelScale
AccelerometerContract.Event.Next.HISTORY -> {
val history = state.accelerometer.accelerometerState.saveHistory
- if (history is Ble.Accelerometer.History.Enabled)
+ if (history is Ble.Accelerometer.HistorySettings.Enabled)
history.scale
else {
state.accelScale
diff --git a/app/src/main/java/llc/arma/ble/app/ui/screen/inspection/accelerometer/view/AccelerometerSpectre.kt b/app/src/main/java/llc/arma/ble/app/ui/screen/inspection/accelerometer/view/AccelerometerSpectre.kt
index 7de1d1c..2c9821d 100644
--- a/app/src/main/java/llc/arma/ble/app/ui/screen/inspection/accelerometer/view/AccelerometerSpectre.kt
+++ b/app/src/main/java/llc/arma/ble/app/ui/screen/inspection/accelerometer/view/AccelerometerSpectre.kt
@@ -76,7 +76,6 @@ fun AccelerometerSpectre(
DisposableEffect(key1 = "ble", effect = {
onDispose {
- Log.d("history", "dispose")
viewModel.setEvent(AccelerometerSpectreContract.Event.StopMeasure)
}
@@ -340,8 +339,8 @@ class AccelerometerSpectreContract {
sealed class State : ViewState {
data class Display(
- val previousHistory : List?,
- val loadingHistoryState : ProgressState>
+ val previousHistory : List?,
+ val loadingHistoryState : ProgressState>
) : State()
object Exception : State()
diff --git a/app/src/main/java/llc/arma/ble/app/ui/screen/inspection/accelerometer/view/AcceleromterAccel.kt b/app/src/main/java/llc/arma/ble/app/ui/screen/inspection/accelerometer/view/AcceleromterAccel.kt
index f8400c2..4f7d225 100644
--- a/app/src/main/java/llc/arma/ble/app/ui/screen/inspection/accelerometer/view/AcceleromterAccel.kt
+++ b/app/src/main/java/llc/arma/ble/app/ui/screen/inspection/accelerometer/view/AcceleromterAccel.kt
@@ -25,8 +25,6 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.Refresh
import androidx.compose.ui.draw.rotate
import androidx.compose.ui.graphics.StrokeCap
-import androidx.compose.ui.graphics.TransformOrigin
-import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.text.style.TextAlign
import com.patrykandpatrick.vico.compose.axis.horizontal.bottomAxis
import com.patrykandpatrick.vico.compose.chart.line.lineChart
@@ -39,10 +37,10 @@ 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.model.Ble
import llc.arma.ble.domain.usecase.AccelScale
import llc.arma.ble.domain.usecase.AccelViewMode
import llc.arma.ble.domain.usecase.AccelViewMode.*
-import llc.arma.ble.domain.usecase.MeasureData
import llc.arma.ble.domain.usecase.FftAxis
import llc.arma.ble.domain.usecase.FftFrequency
import llc.arma.ble.domain.usecase.FftViewMode
@@ -151,37 +149,40 @@ fun Display(
xProducer.setEntries(state.measureHistory.mapIndexed { index, measurePoint ->
when(measurePoint){
- is MeasureData.Accelerate -> {
+ is Ble.Accelerometer.RealtimePoint.Common ->
FloatEntry(index.toFloat(), measurePoint.x )
- }
- is MeasureData.Vibration -> FloatEntry(index.toFloat(), measurePoint.value)
- is MeasureData.Angle -> {
- FloatEntry(index.toFloat(), measurePoint.xAngle )
- }
+ is Ble.Accelerometer.RealtimePoint.Vibration ->
+ FloatEntry(index.toFloat(), measurePoint.value)
+ is Ble.Accelerometer.RealtimePoint.Angle ->
+ FloatEntry(index.toFloat(), measurePoint.x )
+ is Ble.Accelerometer.RealtimePoint.Rotation ->
+ FloatEntry(index.toFloat(), measurePoint.angle )
}
})
yProducer.setEntries(state.measureHistory.mapIndexed { index, measurePoint ->
when(measurePoint){
- is MeasureData.Accelerate -> {
+ is Ble.Accelerometer.RealtimePoint.Common ->
FloatEntry(index.toFloat(), measurePoint.y )
- }
- is MeasureData.Vibration -> FloatEntry(index.toFloat(), measurePoint.value)
- is MeasureData.Angle -> {
- FloatEntry(index.toFloat(), measurePoint.yAngle )
- }
+ is Ble.Accelerometer.RealtimePoint.Vibration ->
+ FloatEntry(index.toFloat(), measurePoint.value)
+ is Ble.Accelerometer.RealtimePoint.Angle ->
+ FloatEntry(index.toFloat(), measurePoint.y)
+ is Ble.Accelerometer.RealtimePoint.Rotation ->
+ FloatEntry(index.toFloat(), measurePoint.tmp)
}
})
zProducer.setEntries(state.measureHistory.mapIndexed { index, measurePoint ->
when(measurePoint){
- is MeasureData.Accelerate -> {
- FloatEntry(index.toFloat(), measurePoint.z )
- }
- is MeasureData.Vibration -> FloatEntry(index.toFloat(), measurePoint.value)
- is MeasureData.Angle -> {
- FloatEntry(index.toFloat(), measurePoint.zAngle )
- }
+ is Ble.Accelerometer.RealtimePoint.Common ->
+ FloatEntry(index.toFloat(), measurePoint.z)
+ is Ble.Accelerometer.RealtimePoint.Vibration ->
+ FloatEntry(index.toFloat(), measurePoint.value)
+ is Ble.Accelerometer.RealtimePoint.Angle ->
+ FloatEntry(index.toFloat(), measurePoint.z)
+ is Ble.Accelerometer.RealtimePoint.Rotation ->
+ FloatEntry(index.toFloat(), measurePoint.turnovers.toFloat())
}
})
@@ -195,16 +196,7 @@ fun Display(
val lastMeasure = state.measureHistory.lastOrNull()
- /*when(lastMeasure){
- is MeasureData.Accelerate -> TODO()
- is MeasureData.Angle -> TODO()
- is MeasureData.Vibration -> {
-
- }
- null -> {}
- }*/
-
- if(lastMeasure is MeasureData.Accelerate) {
+ if(lastMeasure is Ble.Accelerometer.RealtimePoint.Common) {
when(state.mode){
ROTATIONS -> {
@@ -524,7 +516,7 @@ class AccelerometerAccelContract {
data class Display(
val mode: AccelViewMode,
- val measureHistory : List
+ val measureHistory : List
) : State()
object Exception : State()
diff --git a/app/src/main/java/llc/arma/ble/app/ui/screen/inspection/accelerometer/view/AcceleromterHistory.kt b/app/src/main/java/llc/arma/ble/app/ui/screen/inspection/accelerometer/view/AcceleromterHistory.kt
index 5d80831..8533c72 100644
--- a/app/src/main/java/llc/arma/ble/app/ui/screen/inspection/accelerometer/view/AcceleromterHistory.kt
+++ b/app/src/main/java/llc/arma/ble/app/ui/screen/inspection/accelerometer/view/AcceleromterHistory.kt
@@ -52,7 +52,6 @@ import llc.arma.ble.domain.usecase.FftFrequency
import llc.arma.ble.domain.usecase.FftViewMode
import llc.arma.ble.domain.usecase.GetAccelerometerHistoryBySerial
import llc.arma.ble.domain.usecase.GetBleBySerial
-import llc.arma.ble.domain.usecase.MeasureData
import java.util.Date
class AccelEntry(
@@ -208,7 +207,7 @@ fun Display(
xProducer.setEntries(state.loadingHistoryState.data.mapIndexed { index, measurePoint ->
when(measurePoint){
- is Ble.Accelerometer.HistoryPoint.Accelerate -> {
+ is Ble.Accelerometer.HistoryPoint.Acceleration -> {
AccelEntry(measurePoint.date, index.toFloat(), measurePoint.x )
}
is Ble.Accelerometer.HistoryPoint.Vibration -> {
@@ -217,12 +216,16 @@ fun Display(
is Ble.Accelerometer.HistoryPoint.Angle -> {
AccelEntry(measurePoint.date, index.toFloat(), measurePoint.x )
}
+ is Ble.Accelerometer.HistoryPoint.Rotation -> {
+ AccelEntry(measurePoint.date, index.toFloat(), measurePoint.value.toFloat() )
+ }
}
+
})
yProducer.setEntries(state.loadingHistoryState.data.mapIndexed { index, measurePoint ->
when(measurePoint){
- is Ble.Accelerometer.HistoryPoint.Accelerate -> {
+ is Ble.Accelerometer.HistoryPoint.Acceleration -> {
AccelEntry(measurePoint.date, index.toFloat(), measurePoint.y )
}
is Ble.Accelerometer.HistoryPoint.Vibration -> {
@@ -231,12 +234,15 @@ fun Display(
is Ble.Accelerometer.HistoryPoint.Angle -> {
AccelEntry(measurePoint.date, index.toFloat(), measurePoint.y )
}
+ is Ble.Accelerometer.HistoryPoint.Rotation -> {
+ AccelEntry(measurePoint.date, index.toFloat(), measurePoint.value.toFloat() )
+ }
}
})
zProducer.setEntries(state.loadingHistoryState.data.mapIndexed { index, measurePoint ->
when(measurePoint){
- is Ble.Accelerometer.HistoryPoint.Accelerate -> {
+ is Ble.Accelerometer.HistoryPoint.Acceleration -> {
AccelEntry(measurePoint.date, index.toFloat(), measurePoint.z )
}
is Ble.Accelerometer.HistoryPoint.Vibration -> {
@@ -245,6 +251,9 @@ fun Display(
is Ble.Accelerometer.HistoryPoint.Angle -> {
AccelEntry(measurePoint.date, index.toFloat(), measurePoint.z )
}
+ is Ble.Accelerometer.HistoryPoint.Rotation -> {
+ AccelEntry(measurePoint.date, index.toFloat(), measurePoint.value.toFloat() )
+ }
}
})
@@ -258,9 +267,10 @@ fun Display(
val lastMeasure = state.loadingHistoryState.data.lastOrNull()
- if((lastMeasure is Ble.Accelerometer.HistoryPoint.Vibration).not()) {
-
- Column() {
+ when(lastMeasure){
+ is Ble.Accelerometer.HistoryPoint.Acceleration,
+ is Ble.Accelerometer.HistoryPoint.Angle -> {
+ Column {
Text(text = "Ось X:")
@@ -330,36 +340,64 @@ fun Display(
)
}
-
- } else {
-
- Column {
-
- Text(text = "Вибрация:")
-
- Chart(
- chart = lineChart,
- chartModelProducer = xProducer,
- startAxis = startAxis(),
- bottomAxis = bottomAxis(
- tickLength = 0.dp,
- valueFormatter = axisValueFormatter,
- labelRotationDegrees = -90f,
- ),
- modifier = Modifier
- .fillMaxWidth()
- .weight(1f),
- autoScaleUp = AutoScaleUp.None,
- diffAnimationSpec = tween(0),
- chartScrollSpec = rememberChartScrollSpec(
- initialScroll = InitialScroll.End,
- autoScrollCondition = AutoScrollCondition.OnModelSizeIncreased,
- autoScrollAnimationSpec = tween(0)
- )
- )
-
}
+ is Ble.Accelerometer.HistoryPoint.Rotation -> {
+ Column {
+ Text(text = "Обороты:")
+
+ Chart(
+ chart = lineChart,
+ chartModelProducer = xProducer,
+ startAxis = startAxis(),
+ bottomAxis = bottomAxis(
+ tickLength = 0.dp,
+ valueFormatter = axisValueFormatter,
+ labelRotationDegrees = -90f,
+ ),
+ modifier = Modifier
+ .fillMaxWidth()
+ .weight(1f),
+ autoScaleUp = AutoScaleUp.None,
+ diffAnimationSpec = tween(0),
+ chartScrollSpec = rememberChartScrollSpec(
+ initialScroll = InitialScroll.End,
+ autoScrollCondition = AutoScrollCondition.OnModelSizeIncreased,
+ autoScrollAnimationSpec = tween(0)
+ )
+ )
+
+ }
+ }
+ is Ble.Accelerometer.HistoryPoint.Vibration -> {
+ Column {
+
+ Text(text = "Вибрация:")
+
+ Chart(
+ chart = lineChart,
+ chartModelProducer = xProducer,
+ startAxis = startAxis(),
+ bottomAxis = bottomAxis(
+ tickLength = 0.dp,
+ valueFormatter = axisValueFormatter,
+ labelRotationDegrees = -90f,
+ ),
+ modifier = Modifier
+ .fillMaxWidth()
+ .weight(1f),
+ autoScaleUp = AutoScaleUp.None,
+ diffAnimationSpec = tween(0),
+ chartScrollSpec = rememberChartScrollSpec(
+ initialScroll = InitialScroll.End,
+ autoScrollCondition = AutoScrollCondition.OnModelSizeIncreased,
+ autoScrollAnimationSpec = tween(0)
+ )
+ )
+
+ }
+ }
+ null -> {}
}
}
diff --git a/app/src/main/java/llc/arma/ble/app/ui/screen/inspection/accelerometer/view/DisplayState.kt b/app/src/main/java/llc/arma/ble/app/ui/screen/inspection/accelerometer/view/DisplayState.kt
index 5fc7039..776a7a3 100644
--- a/app/src/main/java/llc/arma/ble/app/ui/screen/inspection/accelerometer/view/DisplayState.kt
+++ b/app/src/main/java/llc/arma/ble/app/ui/screen/inspection/accelerometer/view/DisplayState.kt
@@ -18,7 +18,6 @@ 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
@@ -115,7 +114,7 @@ fun DisplayState(
val history = ble.accelerometerState.saveHistory
- if(history is Ble.Accelerometer.History.Enabled){
+ if(history is Ble.Accelerometer.HistorySettings.Enabled){
Text(
color = MaterialTheme.colorScheme.secondary,
style = MaterialTheme.typography.bodyMedium,
@@ -133,7 +132,7 @@ fun DisplayState(
}
Switch(
- checked = ble.accelerometerState.saveHistory is Ble.Accelerometer.History.Enabled,
+ checked = ble.accelerometerState.saveHistory is Ble.Accelerometer.HistorySettings.Enabled,
onCheckedChange = {
onEvent(AccelerometerContract.Event.OnSaveHistoryChanged(it))
}
@@ -168,13 +167,14 @@ fun DisplayState(
text = "Интервал измерений"
)
- val hours = ble.accelerometerState.historyInterval / 1000 / 60 / 60
- val minutes = (ble.accelerometerState.historyInterval - ( hours * 1000 * 60 * 60 )) / 1000 / 60
+ val hours = ble.accelerometerState.historyInterval / millisInHour
+ val minutes = (ble.accelerometerState.historyInterval - (hours * millisInHour)) / millisInMinute
+ val seconds = (ble.accelerometerState.historyInterval - (hours * millisInHour) - (minutes * millisInMinute)) / millisInSecond
Text(
color = MaterialTheme.colorScheme.secondary,
style = MaterialTheme.typography.bodyMedium,
- text = "$hours ч. $minutes мин."
+ text = "$hours ч. $minutes мин. $seconds сек."
)
}
diff --git a/app/src/main/java/llc/arma/ble/app/ui/screen/inspection/accelerometer/view/HistoryEdit.kt b/app/src/main/java/llc/arma/ble/app/ui/screen/inspection/accelerometer/view/HistoryEdit.kt
index 6d6aa6e..3add635 100644
--- a/app/src/main/java/llc/arma/ble/app/ui/screen/inspection/accelerometer/view/HistoryEdit.kt
+++ b/app/src/main/java/llc/arma/ble/app/ui/screen/inspection/accelerometer/view/HistoryEdit.kt
@@ -2,17 +2,13 @@ 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.Switch
import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
@@ -21,10 +17,6 @@ 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(
@@ -34,9 +26,9 @@ fun HistoryEdit(
val history = state.accelerometer.accelerometerState.saveHistory
- val detailed = if (history is Ble.Accelerometer.History.Enabled) history.detailed else false
- val accelMode = if (history is Ble.Accelerometer.History.Enabled) history.mode else state.accelViewMode
- val accelScale = if (history is Ble.Accelerometer.History.Enabled) history.scale else state.accelScale
+ val detailed = if (history is Ble.Accelerometer.HistorySettings.Enabled) history.detailed else false
+ val accelMode = if (history is Ble.Accelerometer.HistorySettings.Enabled) history.mode else state.accelViewMode
+ val accelScale = if (history is Ble.Accelerometer.HistorySettings.Enabled) history.scale else state.accelScale
Column(
modifier = Modifier
diff --git a/app/src/main/java/llc/arma/ble/app/ui/screen/inspection/accelerometer/view/IntervalEdit.kt b/app/src/main/java/llc/arma/ble/app/ui/screen/inspection/accelerometer/view/IntervalEdit.kt
index e58a4c8..20eafe7 100644
--- a/app/src/main/java/llc/arma/ble/app/ui/screen/inspection/accelerometer/view/IntervalEdit.kt
+++ b/app/src/main/java/llc/arma/ble/app/ui/screen/inspection/accelerometer/view/IntervalEdit.kt
@@ -1,5 +1,6 @@
package llc.arma.ble.app.ui.screen.inspection.accelerometer.view
+import android.util.Log
import androidx.compose.animation.*
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.CircleShape
@@ -26,15 +27,17 @@ fun IntervalEdit(
}
val maxInterval = 10 * 24 * 60 * 60 * 1000
+ val minInterval = 10_000
if(value > maxInterval){
value = maxInterval
}
- if(value < 1){
- value = 1 * 60 * 1000
+ if(value < minInterval){
+ value = minInterval
}
+ val maxSeconds = maxInterval / millisInSecond
val maxMinutes = maxInterval / millisInMinute
val maxHours = maxInterval / millisInHour
val maxDays = maxInterval / millisInDay
@@ -42,6 +45,7 @@ fun IntervalEdit(
val dayValue = value / millisInDay
val hourValue = (value - (dayValue * millisInDay)) / millisInHour
val minutesValue = (value - (dayValue * millisInDay) - (hourValue * millisInHour)) / millisInMinute
+ val secondsValue = (value - (dayValue * millisInDay) - (hourValue * millisInHour) - (minutesValue * millisInMinute)) / millisInSecond
Column(
modifier = Modifier
@@ -65,13 +69,13 @@ fun IntervalEdit(
range = -1..maxDays,
value = dayValue,
onValueChanged = {
- value = (it * millisInDay) + (hourValue * millisInHour) + (minutesValue * millisInMinute)
+ value = (it * millisInDay) + (hourValue * millisInHour) + (minutesValue * millisInMinute) + (secondsValue * millisInSecond)
}
)
Spacer(modifier = Modifier.width(8.dp))
- Text(text = "Дни")
+ Text(text = "Д.")
Spacer(modifier = Modifier.width(16.dp))
@@ -79,13 +83,13 @@ fun IntervalEdit(
range = -1..maxHours,
value = hourValue,
onValueChanged = {
- value = (it * millisInHour) + (dayValue * millisInDay) + (minutesValue * millisInMinute)
+ value = (it * millisInHour) + (dayValue * millisInDay) + (minutesValue * millisInMinute) + (secondsValue * millisInSecond)
}
)
Spacer(modifier = Modifier.width(8.dp))
- Text(text = "Часы")
+ Text(text = "Ч.")
Spacer(modifier = Modifier.width(16.dp))
@@ -93,13 +97,27 @@ fun IntervalEdit(
range = -1..maxMinutes,
value = minutesValue,
onValueChanged = {
- value = (it * millisInMinute) + (dayValue * millisInDay) + (hourValue * millisInHour)
+ value = (secondsValue * millisInSecond) + (it * millisInMinute) + (dayValue * millisInDay) + (hourValue * millisInHour)
}
)
Spacer(modifier = Modifier.width(8.dp))
- Text(text = "Минуты")
+ Text(text = "М.")
+
+ Spacer(modifier = Modifier.width(16.dp))
+
+ NumberPicker(
+ range = -1..maxSeconds,
+ value = secondsValue,
+ onValueChanged = {
+ value = (it * millisInSecond) + (minutesValue * millisInMinute) + (dayValue * millisInDay) + (hourValue * millisInHour)
+ }
+ )
+
+ Spacer(modifier = Modifier.width(8.dp))
+
+ Text(text = "С.")
}
@@ -138,7 +156,8 @@ fun IntervalEdit(
}
-const val millisInMinute = 1000 * 60
+const val millisInSecond = 1000
+const val millisInMinute = millisInSecond * 60
const val millisInHour = millisInMinute * 60
const val millisInDay = millisInHour * 24
diff --git a/app/src/main/java/llc/arma/ble/app/ui/screen/inspection/accelerometer/view/Write.kt b/app/src/main/java/llc/arma/ble/app/ui/screen/inspection/accelerometer/view/Write.kt
index c8f88bd..287f519 100644
--- a/app/src/main/java/llc/arma/ble/app/ui/screen/inspection/accelerometer/view/Write.kt
+++ b/app/src/main/java/llc/arma/ble/app/ui/screen/inspection/accelerometer/view/Write.kt
@@ -10,17 +10,14 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
-import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.StrokeCap
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
-import kotlinx.coroutines.launch
import llc.arma.ble.R
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.localizedName
import llc.arma.ble.domain.model.Ble
@@ -45,7 +42,7 @@ fun Write(
when (state) {
is AccelerometerContract.State.Display.WriteState.DisplayPreview -> {
- if(state.writeRequest.tx != null || state.writeRequest.saveHistory != null || state.writeRequest.historyInterval != null) {
+ if(state.writeRequest.tx != null || state.writeRequest.saveHistorySettings != null || state.writeRequest.historyInterval != null) {
state.writeRequest.tx?.let {
Box(
@@ -82,7 +79,7 @@ fun Write(
}
}
- state.writeRequest.saveHistory?.let {
+ state.writeRequest.saveHistorySettings?.let {
Box(
modifier = Modifier.padding(
@@ -109,8 +106,8 @@ fun Write(
color = MaterialTheme.colorScheme.secondary,
style = MaterialTheme.typography.bodyMedium,
text = when(it){
- Ble.Accelerometer.History.Disabled -> "Выключено"
- is Ble.Accelerometer.History.Enabled -> "Включено"
+ Ble.Accelerometer.HistorySettings.Disabled -> "Выключено"
+ is Ble.Accelerometer.HistorySettings.Enabled -> "Включено"
}
)
@@ -142,17 +139,18 @@ fun Write(
modifier = Modifier.weight(1f)
) {
- val hours = it / 1000 / 60 / 60
- val minutes = (it - ( hours * 1000 * 60 * 60 )) / 1000 / 60
-
Text(
text = "Интервал измерений"
)
+ val hours = it / millisInHour
+ val minutes = (it - (hours * millisInHour)) / millisInMinute
+ val seconds = (it - (hours * millisInHour) - (minutes * millisInMinute)) / millisInSecond
+
Text(
color = MaterialTheme.colorScheme.secondary,
style = MaterialTheme.typography.bodyMedium,
- text = "$hours ч. $minutes мин."
+ text = "$hours ч. $minutes мин. $seconds сек."
)
}
diff --git a/app/src/main/java/llc/arma/ble/app/ui/screen/inspection/thermometer/ThermometerScreen.kt b/app/src/main/java/llc/arma/ble/app/ui/screen/inspection/thermometer/ThermometerScreen.kt
index da5ccc7..c9a71c3 100644
--- a/app/src/main/java/llc/arma/ble/app/ui/screen/inspection/thermometer/ThermometerScreen.kt
+++ b/app/src/main/java/llc/arma/ble/app/ui/screen/inspection/thermometer/ThermometerScreen.kt
@@ -39,15 +39,15 @@ val Boolean.localizedName: String
val Ble.BleState.TX.localizedName: String
get() {
return when(this){
- Ble.BleState.TX.MINUS_40 -> -40
- Ble.BleState.TX.MINUS_20 -> -20
- Ble.BleState.TX.MINUS_16 -> -16
- Ble.BleState.TX.MINUS_12 -> -12
- Ble.BleState.TX.MINUS_8 -> -8
- Ble.BleState.TX.MINUS_4 -> -4
- Ble.BleState.TX.ZERO -> 0
- Ble.BleState.TX.PLUS_3 -> 3
- Ble.BleState.TX.PLUS_4 -> 4
+ Ble.BleState.TX.MINUS_40 -> "-40"
+ Ble.BleState.TX.MINUS_20 -> "-20"
+ Ble.BleState.TX.MINUS_16 -> "-16"
+ Ble.BleState.TX.MINUS_12 -> "-12"
+ Ble.BleState.TX.MINUS_8 -> "-8"
+ Ble.BleState.TX.MINUS_4 -> "-4"
+ Ble.BleState.TX.ZERO -> "0"
+ Ble.BleState.TX.PLUS_3 -> "3"
+ Ble.BleState.TX.PLUS_4 -> "4"
}.toString()
}
diff --git a/app/src/main/java/llc/arma/ble/app/ui/screen/inspection/thermometer/view/TemperatureHistory.kt b/app/src/main/java/llc/arma/ble/app/ui/screen/inspection/thermometer/view/TemperatureHistory.kt
index cc72e9e..1713a3a 100644
--- a/app/src/main/java/llc/arma/ble/app/ui/screen/inspection/thermometer/view/TemperatureHistory.kt
+++ b/app/src/main/java/llc/arma/ble/app/ui/screen/inspection/thermometer/view/TemperatureHistory.kt
@@ -256,7 +256,7 @@ class TemperatureHistoryContract {
sealed class State : ViewState {
data class Display(
- val loadingHistoryState : ProgressState>
+ val loadingHistoryState : ProgressState>
) : State()
object Exception : State()
diff --git a/app/src/main/java/llc/arma/ble/data/BleRepositoryImpl.kt b/app/src/main/java/llc/arma/ble/data/BleRepositoryImpl.kt
index e92e17e..444ecbc 100644
--- a/app/src/main/java/llc/arma/ble/data/BleRepositoryImpl.kt
+++ b/app/src/main/java/llc/arma/ble/data/BleRepositoryImpl.kt
@@ -1,100 +1,53 @@
package llc.arma.ble.data
import android.app.Application
-import android.bluetooth.*
-import android.bluetooth.le.ScanCallback
-import android.bluetooth.le.ScanResult
-import android.bluetooth.le.ScanSettings
import android.os.SystemClock
-import android.util.Log
-import kotlinx.coroutines.*
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow
+import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.flow
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.launch
+import llc.arma.ble.data.extensions.checkPermission
+import llc.arma.ble.data.extensions.fromByte
+import llc.arma.ble.data.extensions.get4byteUIntAt
+import llc.arma.ble.data.extensions.info
+import llc.arma.ble.data.extensions.sendData
+import llc.arma.ble.data.extensions.toTemperature
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.model.BleInfo
-import llc.arma.ble.domain.model.ConnectedBleInfo
import llc.arma.ble.domain.repository.BleRepository
import llc.arma.ble.domain.usecase.AccelScale
import llc.arma.ble.domain.usecase.AccelViewMode
-import llc.arma.ble.domain.usecase.AccelViewMode.*
-import llc.arma.ble.domain.usecase.MeasureData
import llc.arma.ble.domain.usecase.FftAxis
import llc.arma.ble.domain.usecase.FftFrequency
import llc.arma.ble.domain.usecase.FftViewMode
-import no.nordicsemi.android.common.core.DataByteArray
import no.nordicsemi.android.kotlin.ble.client.main.callback.ClientBleGatt
-import no.nordicsemi.android.kotlin.ble.core.scanner.BleScanResult
-import no.nordicsemi.android.kotlin.ble.scanner.aggregator.BleScanResultAggregator
-import java.util.*
+import no.nordicsemi.android.kotlin.ble.core.data.util.DataByteArray
+import no.nordicsemi.android.kotlin.ble.core.scanner.BleNumOfMatches
+import no.nordicsemi.android.kotlin.ble.core.scanner.BleScanMode
+import no.nordicsemi.android.kotlin.ble.core.scanner.BleScannerCallbackType
+import no.nordicsemi.android.kotlin.ble.core.scanner.BleScannerMatchMode
+import no.nordicsemi.android.kotlin.ble.core.scanner.BleScannerSettings
+import no.nordicsemi.android.kotlin.ble.scanner.BleScanner
+import java.util.Collections
+import java.util.Timer
+import java.util.TimerTask
+import java.util.UUID
import javax.inject.Inject
import javax.inject.Singleton
import kotlin.math.PI
import kotlin.math.atan
-val FftFrequency.sendData: Byte
- get() {
- return when(this){
- FftFrequency.OFF -> 0
- FftFrequency.F_1 -> 1
- FftFrequency.F_10 -> 2
- FftFrequency.F_25 -> 3
- FftFrequency.F_50 -> 4
- FftFrequency.F_100 -> 5
- FftFrequency.F_200 -> 6
- FftFrequency.F_400 -> 7
- FftFrequency.F_1620 -> 8
- FftFrequency.F_1344 -> 9
- }
- }
-
-val FftAxis.sendData: Byte
- get() {
- return when(this){
- FftAxis.AUTO -> 0
- FftAxis.X -> 1
- FftAxis.Y -> 2
- FftAxis.Z -> 3
- }
- }
-
-val FftViewMode.sendData: Byte
- get() {
- return when(this){
- FftViewMode.SPECTRE -> 0
- FftViewMode.X -> 1
- FftViewMode.Y -> 2
- FftViewMode.Z -> 3
- }
- }
-
-val AccelViewMode.sendData: Byte
- get() {
- return when(this){
- ACCELERATION -> 0
- PEAK_ACCELERATION -> 1
- RMS -> 2
- VIBRATION -> 3
- ANGLE -> 0
- ROTATIONS -> 4
- }
- }
-
-val AccelScale.sendData: Byte
- get() {
- return when(this){
- AccelScale.S_2 -> 0
- AccelScale.S_4 -> 1
- AccelScale.S_8 -> 2
- AccelScale.S_16 -> 3
- }
- }
-
val serviceUUID: UUID = UUID.fromString("a77db03a-9bc4-11ed-a8fc-0242ac120002")
val accelerometerReadUUID: UUID = UUID.fromString("00002713-0000-1000-8000-00805f9b34fb")
@@ -108,270 +61,62 @@ val passwordWriteUUID: UUID = UUID.fromString("a77db6f2-9bc4-11ed-a8fc-0242ac120
val txWriteUUID: UUID = UUID.fromString("00002a07-0000-1000-8000-00805f9b34fb")
val flashWriteUUID: UUID = UUID.fromString("a77db6f2-9bc4-11ed-a8fc-0242ac120002")
-@OptIn(ExperimentalUnsignedTypes::class)
-fun UByteArray.toTemperature(): Float {
- val uShort = (this[0] + this[1] * 256u).toUShort()
- val result = if (uShort > Short.MAX_VALUE.toUShort()) {
- ((uShort.inv() + 1u).toFloat().unaryMinus()) / 100f
- } else {
- uShort.toFloat() / 100f
- }
- return result
-}
-
-fun ByteArray.get2byteUIntAt(idx: Int) =
- ((this[idx + 1].toUInt() and 0xFFu) shl 8) or
- (this[idx].toUInt() and 0xFFu)
@Singleton
class BleRepositoryImpl @Inject constructor(
private val app: Application
) : BleRepository {
- private val ScanResult.timerEnabled: Boolean
- get() {
- return scanRecord?.manufacturerSpecificData?.get(89)?.get(2) == 1.toByte()
- }
-
- private val BleScanResult.timerEnabled: Boolean
- get() {
- return data?.scanRecord?.manufacturerSpecificData?.get(89)?.getByte(2) == 1.toByte()
- }
-
- private val BleScanResult.info: BleInfo
- get() {
- this.device.name
- return BleInfo(
- name = this.device.name ?: "",
- serial = device.address,
- batteryLevel = batteryLevel ?: 0,
- rssi = data?.rssi,
- type = type,
- scanTime = (data?.timestampNanos ?: 0) / 1_000_000,
- tx = data?.txPower ?: 0,
- recordEnabled = timerEnabled
- )
- }
-
- private val ScanResult.info: BleInfo
- get() {
- return BleInfo(
- name = scanRecord?.deviceName ?: "",
- serial = device.address,
- batteryLevel = batteryLevel ?: 0,
- rssi = rssi,
- type = type,
- scanTime = timestampNanos / 1_000_000,
- tx = scanRecord?.txPowerLevel ?: 0,
- recordEnabled = timerEnabled
- )
- }
-
- private val BleScanResult.batteryLevel: Int?
- get() {
- return data?.scanRecord?.manufacturerSpecificData?.get(89)?.getByte(1)
- ?.toUByte()?.toInt()
- }
-
- private val ScanResult.batteryLevel: Int?
- get() {
- return scanRecord?.manufacturerSpecificData?.get(89)?.get(1)
- ?.toUByte()?.toInt()
- }
-
- private val BleScanResult.type: BleInfo.Type
- get() {
- return when(data?.scanRecord?.manufacturerSpecificData?.get(89)?.getByte(0)?.toUByte()?.toInt()){
- 1 -> BleInfo.Type.BEACON
- 2 -> BleInfo.Type.THERMOMETER
- else -> BleInfo.Type.ACCELEROMETER
- }
- }
-
- private val ScanResult.type: BleInfo.Type
- get() {
- return when(scanRecord?.manufacturerSpecificData?.get(89)?.get(0)?.toUByte()?.toInt()){
- 1 -> BleInfo.Type.BEACON
- 2 -> BleInfo.Type.THERMOMETER
- else -> BleInfo.Type.ACCELEROMETER
- }
- }
-
- private fun ByteArray.getUIntAt(idx: Int) =
- ((this[idx + 3].toUInt() and 0xFFu) shl 24) or
- ((this[idx + 2].toUInt() and 0xFFu) shl 16) or
- ((this[idx + 1].toUInt() and 0xFFu) shl 8) or
- (this[idx].toUInt() and 0xFFu)
-
- private val deviceCache = mutableMapOf()
val resultList: MutableMap = Collections.synchronizedMap(mutableMapOf())
- override fun getConnectedBle(): List {
-
- if(app.checkPermission()) {
-
- return app.getSystemService(BluetoothManager::class.java)
- .getConnectedDevices(BluetoothProfile.GATT)
- .filter {
- it.name.contains("arma", true)
- }
- .map {
- ConnectedBleInfo(
- name = it.name,
- serial = it.address
- )
- }
-
- } else {
- return emptyList()
- }
-
- }
-
- private val aggregator = BleScanResultAggregator()
-
- override fun getBleAroundFlow(): Flow, BleException>> {
-
- /*return if(checkPermission()){
-
- callbackFlow {
-
- BleScanner(app).scan(
- settings = BleScannerSettings(
- includeStoredBondedDevices = false,
- scanMode = BleScanMode.SCAN_MODE_LOW_LATENCY,
- callbackType = BleScannerCallbackType.CALLBACK_TYPE_ALL_MATCHES,
- matchMode = BleScannerMatchMode.MATCH_MODE_AGGRESSIVE,
- numOfMatches = BleNumOfMatches.MATCH_NUM_ONE_ADVERTISEMENT,
- reportDelay = 0L
- ),
-
- ).filter { it.device.name?.contains("ArmA") == true }
- .onEach { aggregator.aggregateDevices(it) }
- .onEach {
- resultList[it.device.address] = it.info
- //deviceCache[it.device.address] = it
- }.launchIn(CoroutineScope(Dispatchers.IO))
-
- val timer = Timer().apply {
- schedule(object : TimerTask() {
- override fun run() {
- CoroutineScope(Dispatchers.IO).launch {
- send(Result.success(resultList.values.toList()))
- }
- }
- }, 500, 500)
- }
-
- awaitClose {
- timer.cancel()
- }
-
- }
-
- } else {
-
- flow { emit(Result.failure(BleException.PermissionDenied)) }
-
- }*/
+ override fun getBleAroundFlow(): Result>, BleException> {
return if(app.checkPermission()){
- callbackFlow {
+ Result.success(
- val bleCallback = object : ScanCallback() {
+ callbackFlow {
- override fun onScanResult(
- callbackType: Int,
- result: ScanResult
- ) {
+ val job = BleScanner(app)
+ .scan(
+ settings = BleScannerSettings(
+ includeStoredBondedDevices = false,
+ scanMode = BleScanMode.SCAN_MODE_LOW_LATENCY,
+ callbackType = BleScannerCallbackType.CALLBACK_TYPE_ALL_MATCHES,
+ matchMode = BleScannerMatchMode.MATCH_MODE_AGGRESSIVE,
+ numOfMatches = BleNumOfMatches.MATCH_NUM_ONE_ADVERTISEMENT,
+ reportDelay = 0L
+ )
+ ).filter { it.device.name?.contains("ArmA") == true }
+ .onEach {
+ resultList[it.device.address] = it.info
+ }.launchIn(CoroutineScope(Dispatchers.IO))
- super.onScanResult(callbackType, result)
-
- if (app.checkPermission()) {
-
- if (result.scanRecord?.deviceName?.contains("ArmA") == true) {
-
- resultList[result.device.address] = result.info
-
- deviceCache[result.device.address] = result
-
- }
-
- } else {
- CoroutineScope(Dispatchers.IO).launch {
- send(
- Result.failure(BleException.PermissionDenied)
- )
- }
- }
-
- }
-
- override fun onBatchScanResults(results: MutableList) {
- super.onBatchScanResults(results)
-
- if (app.checkPermission()) {
-
- results.forEach { result ->
-
- if (result.scanRecord?.deviceName?.contains("ArmA") == true) {
-
- resultList[result.device.address] = result.info
-
- deviceCache[result.device.address] = result
+ val timer = Timer().apply {
+ schedule(object : TimerTask() {
+ override fun run() {
+ CoroutineScope(Dispatchers.IO).launch {
+ send(resultList.values.toList())
}
-
}
-
- } else {
- CoroutineScope(Dispatchers.IO).launch {
- send(
- Result.failure(BleException.PermissionDenied)
- )
- }
- }
-
+ }, 500, 500)
}
+
+ awaitClose {
+ job.cancel()
+ timer.cancel()
+ }
+
}
- val bleScanner =
- app.getSystemService(BluetoothManager::class.java).adapter.bluetoothLeScanner
-
- bleScanner.startScan(
- listOf(),
- ScanSettings.Builder()
- .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
- .setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES)
- .setMatchMode(ScanSettings.MATCH_MODE_AGGRESSIVE)
- .setNumOfMatches(ScanSettings.MATCH_NUM_ONE_ADVERTISEMENT)
- .setReportDelay(0L)
- .build(),
- bleCallback)
-
- val timer = Timer().apply {
- schedule(object : TimerTask() {
- override fun run() {
- CoroutineScope(Dispatchers.IO).launch {
- send(Result.success(resultList.values.toList()))
- }
- }
- }, 500, 500)
- }
-
- awaitClose {
- bleScanner.stopScan(bleCallback)
- timer.cancel()
- }
-
- }
+ )
} else {
- flow { emit(Result.failure(BleException.PermissionDenied)) }
+ Result.failure(BleException.PermissionDenied)
}
@@ -381,12 +126,15 @@ class BleRepositoryImpl @Inject constructor(
serial: String
): Result, BleException> {
- deviceCache[serial]?.let { result ->
+ resultList[serial]?.let { result ->
- return when(result.info.type) {
+ return when(result.type) {
BleInfo.Type.ACCELEROMETER -> {
- val tState = readAccelState(result).fold(
+ val tState = readAccelState(
+ result.serial,
+ result.recordEnabled
+ ).fold(
onFailure = {
return Result.failure(it)
},
@@ -400,30 +148,21 @@ class BleRepositoryImpl @Inject constructor(
while (true) {
- deviceCache[serial]?.let { newResult ->
+ resultList[serial]?.let { newResult ->
emit(
Ble.Accelerometer(
- info = newResult.info.copy(
- rssi = if((SystemClock.elapsedRealtimeNanos() - newResult.timestampNanos) > 15_000_000_000) {
+ info = newResult.copy(
+ rssi = if((SystemClock.elapsedRealtimeNanos() - newResult.scanTime) > 15_000_000_000) {
null
} else {
newResult.rssi
}
),
state = Ble.BleState(
- tx = when (result.scanRecord?.txPowerLevel) {
- -40 -> Ble.BleState.TX.MINUS_40
- -20 -> Ble.BleState.TX.MINUS_20
- -16 -> Ble.BleState.TX.MINUS_16
- -12 -> Ble.BleState.TX.MINUS_12
- -8 -> Ble.BleState.TX.MINUS_8
- -4 -> Ble.BleState.TX.MINUS_4
- 3 -> Ble.BleState.TX.PLUS_3
- 4 -> Ble.BleState.TX.PLUS_4
- else -> Ble.BleState.TX.ZERO
- }
+ tx = Ble.BleState.TX.fromByte(result.tx.toByte())
+ ?: Ble.BleState.TX.ZERO
),
accelerometerState = tState
)
@@ -445,27 +184,18 @@ class BleRepositoryImpl @Inject constructor(
while (true) {
- deviceCache[serial]?.let { newResult ->
+ resultList[serial]?.let { newResult ->
val state = Ble.BleState(
- tx = when (result.scanRecord?.txPowerLevel) {
- -40 -> Ble.BleState.TX.MINUS_40
- -20 -> Ble.BleState.TX.MINUS_20
- -16 -> Ble.BleState.TX.MINUS_16
- -12 -> Ble.BleState.TX.MINUS_12
- -8 -> Ble.BleState.TX.MINUS_8
- -4 -> Ble.BleState.TX.MINUS_4
- 3 -> Ble.BleState.TX.PLUS_3
- 4 -> Ble.BleState.TX.PLUS_4
- else -> Ble.BleState.TX.ZERO
- }
+ tx = Ble.BleState.TX.fromByte(result.tx.toByte())
+ ?: Ble.BleState.TX.ZERO
)
emit(
Ble.Beacon(
- info = newResult.info.copy(
- rssi = if((SystemClock.elapsedRealtimeNanos() - newResult.timestampNanos) > 15_000_000_000) {
+ info = newResult.copy(
+ rssi = if((SystemClock.elapsedRealtimeNanos() - newResult.scanTime) > 15_000_000_000) {
null
} else {
newResult.rssi
@@ -488,7 +218,7 @@ class BleRepositoryImpl @Inject constructor(
}
BleInfo.Type.THERMOMETER -> {
- val tState = readThermometerState(result).fold(
+ val tState = readThermometerState(result.serial, result.recordEnabled).fold(
onFailure = {
return Result.failure(it)
},
@@ -502,27 +232,18 @@ class BleRepositoryImpl @Inject constructor(
while (true) {
- deviceCache[serial]?.let { newResult ->
+ resultList[serial]?.let { newResult ->
val state = Ble.BleState(
- tx = when (result.scanRecord?.txPowerLevel) {
- -40 -> Ble.BleState.TX.MINUS_40
- -20 -> Ble.BleState.TX.MINUS_20
- -16 -> Ble.BleState.TX.MINUS_16
- -12 -> Ble.BleState.TX.MINUS_12
- -8 -> Ble.BleState.TX.MINUS_8
- -4 -> Ble.BleState.TX.MINUS_4
- 3 -> Ble.BleState.TX.PLUS_3
- 4 -> Ble.BleState.TX.PLUS_4
- else -> Ble.BleState.TX.ZERO
- }
+ tx = Ble.BleState.TX.fromByte(result.tx.toByte())
+ ?: Ble.BleState.TX.ZERO
)
emit(
Ble.Thermometer(
- info = newResult.info.copy(
- rssi = if((SystemClock.elapsedRealtimeNanos() - newResult.timestampNanos) > 15_000_000_000) {
+ info = newResult.copy(
+ rssi = if((SystemClock.elapsedRealtimeNanos() - newResult.scanTime) > 15_000_000_000) {
null
} else {
newResult.rssi
@@ -555,15 +276,16 @@ class BleRepositoryImpl @Inject constructor(
@OptIn(ExperimentalUnsignedTypes::class)
private suspend fun readThermometerState(
- record: ScanResult
+ address: String,
+ timer: Boolean
): Result {
return if(app.checkPermission()) {
- try {
+ val connection =
+ ClientBleGatt.connect(app, address, CoroutineScope(Dispatchers.IO))
- val connection =
- ClientBleGatt.connect(app, record.device.address, CoroutineScope(Dispatchers.IO))
+ try {
val service = connection.discoverServices()
.findService(serviceUUID) ?: return Result.failure(BleException.UnexpectedResponse)
@@ -582,7 +304,7 @@ class BleRepositoryImpl @Inject constructor(
val interval = characteristic.read().value.let {
if(it.size == 4){
- it.getUIntAt(0).toLong()
+ it.get4byteUIntAt(0).toLong()
}else{
0
}
@@ -593,7 +315,7 @@ class BleRepositoryImpl @Inject constructor(
return Result.success(
Ble.Thermometer.ThermometerState(
temperature = temperature,
- saveHistory = record.timerEnabled,
+ saveHistory = timer,
historyInterval = interval
)
)
@@ -601,6 +323,10 @@ class BleRepositoryImpl @Inject constructor(
} catch (err: Throwable){
err.printStackTrace()
return Result.failure(BleException.UnexpectedResponse)
+ } finally {
+
+ connection.close()
+
}
} else {
@@ -612,15 +338,16 @@ class BleRepositoryImpl @Inject constructor(
}
private suspend fun readAccelState(
- record: ScanResult
+ address: String,
+ timer: Boolean
): Result {
return if(app.checkPermission()) {
- try {
+ val connection =
+ ClientBleGatt.connect(app, address, CoroutineScope(Dispatchers.IO))
- val connection =
- ClientBleGatt.connect(app, record.device.address, CoroutineScope(Dispatchers.IO))
+ try {
val service = connection.discoverServices()
.findService(serviceUUID) ?: return Result.failure(BleException.UnexpectedResponse)
@@ -632,13 +359,13 @@ class BleRepositoryImpl @Inject constructor(
val interval = characteristic.read().value.let {
if(it.size == 4){
- it.getUIntAt(0).toLong()
+ it.get4byteUIntAt(0).toLong()
}else{
0
}
}
- val historyParams = when(record.timerEnabled){
+ val historySettingsParams = when(timer){
true -> {
characteristic = service.findCharacteristic(accelerometerReadUUID)
@@ -649,40 +376,24 @@ class BleRepositoryImpl @Inject constructor(
val data = it.value
- val scale = when(data[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(data[0].toInt()){
- 0 -> ACCELERATION
- 1 -> PEAK_ACCELERATION
- 2 -> RMS
- 3 -> VIBRATION
- 4 -> ANGLE
- else -> {
- return Result.failure(BleException.UnexpectedResponse)
- }
- }
- Ble.Accelerometer.History.Enabled(
+ val scale = AccelScale.fromByte(data[1]) ?: return Result.failure(BleException.UnexpectedResponse)
+ val mode = AccelViewMode.fromByte(data[0]) ?: return Result.failure(BleException.UnexpectedResponse)
+
+ Ble.Accelerometer.HistorySettings.Enabled(
scale = scale,
mode = mode,
- detailed = false //TODO
+ detailed = false
)
}
}
- false -> Ble.Accelerometer.History.Disabled
+ false -> Ble.Accelerometer.HistorySettings.Disabled
}
connection.close()
return Result.success(
Ble.Accelerometer.AccelerometerState(
- saveHistory = historyParams,
+ saveHistorySettings = historySettingsParams,
historyInterval = interval
)
)
@@ -691,6 +402,10 @@ class BleRepositoryImpl @Inject constructor(
return Result.failure(BleException.UnexpectedResponse)
+ } finally {
+
+ connection.close()
+
}
} else {
@@ -708,158 +423,25 @@ class BleRepositoryImpl @Inject constructor(
fftAxis: FftAxis,
fftMode: FftViewMode,
frequency: FftFrequency
- ): Flow>, BleException>> {
+ ): Flow>, BleException>> {
- //return readAccelerometerSpectre(serial, app, accelScale, accelMode, fftAxis, fftMode, frequency)
-
- var gatt: BluetoothGatt? = null
-
- return callbackFlow {
-
- deviceCache[serial]?.device?.let {
-
- if (app.checkPermission()) {
-
- gatt = it.connectGatt(app, false, ReadAccelerometerSpectreCallback(
- app, accelScale, accelMode, fftAxis, fftMode, frequency
- ) {
- CoroutineScope(Dispatchers.IO).launch {
- send(it)
- }
- })
-
- } else {
-
- CoroutineScope(Dispatchers.IO).launch {
- send(Result.failure(BleException.PermissionDenied))
- }
-
- return@callbackFlow
-
- }
-
- }
-
- awaitClose {
- Log.d("measure", "close")
- gatt?.close()
- }
-
- }
+ return readAccelerometerSpectre(serial, app, accelScale, accelMode, fftAxis, fftMode, frequency)
}
override suspend fun getTemperatureHistoryBySerial(
serial: String
- ): Flow>, BleException>> {
+ ): Flow>, BleException>> {
return readThermometerHistory(serial, app)
- /*var gatt: BluetoothGatt? = null
-
- return callbackFlow {
-
- deviceCache[serial]?.device?.let {
-
- if (app.checkPermission()) {
-
- gatt = it.connectGatt(app, false, ReadTemperatureHistoryCallback(app) {
- CoroutineScope(Dispatchers.IO).launch {
- send(it)
- }
- })
-
- } else {
-
- CoroutineScope(Dispatchers.IO).launch {
- send(Result.failure(BleException.PermissionDenied))
- }
-
- return@callbackFlow
-
- }
-
- }
-
- awaitClose {
- gatt?.close()
- }
-
- }*/
-
}
override suspend fun getAccelerometerHistoryBySerial(
serial: String
): Flow>, BleException>> {
- return flow {
-
- if (app.checkPermission()) {
-
- try {
-
- var scale: AccelScale? = null
- var mode: AccelViewMode? = null
-
- val connection = ClientBleGatt.connect(
- app,
- serial,
- CoroutineScope(Dispatchers.Default)
- )
-
- val characteristic = connection.discoverServices()
- .findService(serviceUUID)
- ?.findCharacteristic(accelerometerReadUUID)
-
- characteristic?.write(DataByteArray.from(4))
- characteristic?.read()?.let {
- val data = it.value
- scale = when (data[1].toInt()) {
- 0 -> AccelScale.S_2
- 1 -> AccelScale.S_4
- 2 -> AccelScale.S_8
- 3 -> AccelScale.S_16
- else -> null
- }
- mode = when (data[0].toInt()) {
- 0 -> ACCELERATION
- 1 -> PEAK_ACCELERATION
- 2 -> RMS
- 3 -> VIBRATION
- 4 -> ANGLE
- else -> null
- }
- }
-
- if (scale != null && mode != null) {
-
- readAccelerometerHistory(serial, mode!!, scale!!, app).collect {
-
- emit(it)
-
- }
-
- } else {
-
- emit(Result.failure(BleException.UnexpectedResponse))
-
- }
-
- } catch (err: Throwable) {
- err.printStackTrace()
-
- emit(Result.failure(BleException.UnexpectedResponse))
-
- }
-
- } else {
-
- emit(Result.failure(BleException.PermissionDenied))
-
- }
-
- }
+ return getAccelerometerHistory(serial, app)
}
@@ -875,28 +457,17 @@ class BleRepositoryImpl @Inject constructor(
return if(app.checkPermission()) {
+ val connection =
+ ClientBleGatt.connect(app, serial, CoroutineScope(Dispatchers.Default))
+
try {
- val connection =
- ClientBleGatt.connect(app, serial, CoroutineScope(Dispatchers.Default))
val services = connection.discoverServices()
val service = services.findService(serviceUUID) ?: return Result.failure(BleException.UnexpectedResponse)
request.tx?.let {
service.findCharacteristic(txWriteUUID)!!.write(
- DataByteArray.from(
- when (it) {
- Ble.BleState.TX.MINUS_40 -> -40
- Ble.BleState.TX.MINUS_20 -> -20
- Ble.BleState.TX.MINUS_16 -> -16
- Ble.BleState.TX.MINUS_12 -> -12
- Ble.BleState.TX.MINUS_8 -> -8
- Ble.BleState.TX.MINUS_4 -> -4
- Ble.BleState.TX.ZERO -> 0
- Ble.BleState.TX.PLUS_3 -> 3
- Ble.BleState.TX.PLUS_4 -> 4
- }
- )
+ DataByteArray.from(it.sendData)
)
}
@@ -933,6 +504,10 @@ class BleRepositoryImpl @Inject constructor(
err.printStackTrace()
Result.failure(BleException.UnexpectedResponse)
+ } finally {
+
+ connection.close()
+
}
} else {
@@ -950,31 +525,19 @@ class BleRepositoryImpl @Inject constructor(
return if(app.checkPermission()) {
- try {
+ val connection = ClientBleGatt.connect(app, serial, CoroutineScope(Dispatchers.Default))
- val connect = ClientBleGatt.connect(app, serial, scope = CoroutineScope(Dispatchers.Default))
+ try {
request.tx?.let {
- connect.discoverServices().findService(serviceUUID)?.findCharacteristic(txWriteUUID)?.write(
- DataByteArray.from(
- when (it) {
- Ble.BleState.TX.MINUS_40 -> -40
- Ble.BleState.TX.MINUS_20 -> -20
- Ble.BleState.TX.MINUS_16 -> -16
- Ble.BleState.TX.MINUS_12 -> -12
- Ble.BleState.TX.MINUS_8 -> -8
- Ble.BleState.TX.MINUS_4 -> -4
- Ble.BleState.TX.ZERO -> 0
- Ble.BleState.TX.PLUS_3 -> 3
- Ble.BleState.TX.PLUS_4 -> 4
- }
- )
+ connection.discoverServices().findService(serviceUUID)?.findCharacteristic(txWriteUUID)?.write(
+ DataByteArray.from(it.sendData)
) ?: return Result.failure(BleException.UnexpectedResponse)
}
- connect.close()
+ connection.close()
Result.success(Unit)
@@ -983,6 +546,10 @@ class BleRepositoryImpl @Inject constructor(
err.printStackTrace()
Result.failure(BleException.UnexpectedResponse)
+ } finally {
+
+ connection.close()
+
}
} else {
@@ -1005,10 +572,11 @@ class BleRepositoryImpl @Inject constructor(
return if(app.checkPermission()) {
+ val connection =
+ ClientBleGatt.connect(app, serial, CoroutineScope(Dispatchers.Default))
+
try {
- val connection =
- ClientBleGatt.connect(app, serial, CoroutineScope(Dispatchers.Default))
val services = connection.discoverServices()
val service = services.findService(serviceUUID) ?: return Result.failure(
BleException.UnexpectedResponse
@@ -1016,29 +584,17 @@ class BleRepositoryImpl @Inject constructor(
request.tx?.let {
service.findCharacteristic(txWriteUUID)!!.write(
- DataByteArray.from(
- when (it) {
- Ble.BleState.TX.MINUS_40 -> -40
- Ble.BleState.TX.MINUS_20 -> -20
- Ble.BleState.TX.MINUS_16 -> -16
- Ble.BleState.TX.MINUS_12 -> -12
- Ble.BleState.TX.MINUS_8 -> -8
- Ble.BleState.TX.MINUS_4 -> -4
- Ble.BleState.TX.ZERO -> 0
- Ble.BleState.TX.PLUS_3 -> 3
- Ble.BleState.TX.PLUS_4 -> 4
- }
- )
+ DataByteArray.from(it.sendData)
)
}
- request.saveHistory?.let {
+ request.saveHistorySettings?.let {
service.findCharacteristic(saveEnabledWriteUUID)!!.write(
DataByteArray.from(
*mutableListOf(4).apply {
- add(if (it is Ble.Accelerometer.History.Enabled) 1 else 0)
- if (it is Ble.Accelerometer.History.Enabled) {
+ add(if (it is Ble.Accelerometer.HistorySettings.Enabled) 1 else 0)
+ if (it is Ble.Accelerometer.HistorySettings.Enabled) {
add(it.mode.sendData)
add(it.scale.sendData)
}
@@ -1071,6 +627,10 @@ class BleRepositoryImpl @Inject constructor(
err.printStackTrace()
Result.failure(BleException.UnexpectedResponse)
+ } finally {
+
+ connection.close()
+
}
} else {
@@ -1088,10 +648,11 @@ class BleRepositoryImpl @Inject constructor(
return if(app.checkPermission()) {
+ val connection =
+ ClientBleGatt.connect(app, serial, CoroutineScope(Dispatchers.Default))
+
try {
- val connection =
- ClientBleGatt.connect(app, serial, CoroutineScope(Dispatchers.Default))
val services = connection.discoverServices()
val service = services.findService(serviceUUID)
?: return Result.failure(BleException.UnexpectedResponse)
@@ -1113,6 +674,10 @@ class BleRepositoryImpl @Inject constructor(
err.printStackTrace()
Result.failure(BleException.UnexpectedResponse)
+ } finally {
+
+ connection.close()
+
}
} else {
@@ -1128,181 +693,34 @@ class BleRepositoryImpl @Inject constructor(
fftAxis: FftAxis,
fftMode: FftViewMode,
frequency: FftFrequency,
- ): Flow> {
-
- return if (app.checkPermission()) {
-
- flow {
-
- try {
-
- val connection =
- ClientBleGatt.connect(app, serial, CoroutineScope(Dispatchers.Default))
-
- val services = connection.discoverServices()
-
- val characteristic =
- services.findService(serviceUUID)
- ?.findCharacteristic(accelerometerReadUUID)
-
- val payload = DataByteArray.from(
- 4,
- accelMode.sendData,
- accelScale.sendData,
- fftMode.sendData,
- fftAxis.sendData,
- frequency.sendData,
- 1
- )
-
- characteristic?.write(payload)
-
- characteristic?.getNotifications()?.collect {
-
- val value = it.value
-
- val result = if (accelMode == VIBRATION) {
-
- MeasureData.Vibration(
- (value.get2byteShortAt()
- .toFloat() * accelScale.k) / Short.MAX_VALUE
- )
-
- } else {
-
- val data = value.toList().chunked(2).map {
- it.toByteArray().get2byteShortAt()
- }
-
- Log.d(
- "accel",
- "x: ${data[0]} y: ${data[1]} z: ${data[2]} bytes: ${value.toUByteArray().joinToString { it.toString(16).padStart(2, '0') }}"
- )
-
- val x: Float
- val y: Float
- val z: Float
-
- when(accelMode){
- ANGLE -> {
- x = calculateAngle(
- data[2].toFloat(),
- data[1].toFloat()
- ) * 180f / Math.PI.toFloat()
- y = calculateAngle(
- data[2].toFloat(),
- data[0].toFloat()
- ) * 180f / Math.PI.toFloat()
- z = calculateAngle(
- data[0].toFloat(),
- data[1].toFloat()
- ) * 180f / Math.PI.toFloat()
- }
- ROTATIONS -> {
- x = ((360f / 8f) * ((data[0] / 100f) + 1f)) - 45f
- y = data[1].toFloat()
- z = data[2].toFloat()
- }
- else -> {
- x = (data[0].toFloat() * accelScale.k) / Short.MAX_VALUE
- y = (data[1].toFloat() * accelScale.k) / Short.MAX_VALUE
- z = (data[2].toFloat() * accelScale.k) / Short.MAX_VALUE
- }
- }
-
- /*if (accelMode == ANGLE) {
-
- x = calculateZAngle(
- data[2].toFloat(),
- data[1].toFloat()
- ) * 180f / Math.PI.toFloat()
- y = calculateZAngle(
- data[2].toFloat(),
- data[0].toFloat()
- ) * 180f / Math.PI.toFloat()
- z = calculateZAngle(
- data[0].toFloat(),
- data[1].toFloat()
- ) * 180f / Math.PI.toFloat()
-
- } else {
-
- x = (data[0].toFloat() * accelScale.k) / Short.MAX_VALUE
- y = (data[1].toFloat() * accelScale.k) / Short.MAX_VALUE
- z = (data[2].toFloat() * accelScale.k) / Short.MAX_VALUE
-
- }*/
-
- val state = MeasureData.Accelerate(
- x = x,
- y = y,
- z = z
- )
-
- state
-
-
- }
-
- emit(Result.success(result))
-
- }
-
- connection.close()
-
- } catch (err: Exception) {
-
- err.printStackTrace()
-
- emit(Result.failure(BleException.UnexpectedResponse))
-
- }
-
- }
-
-
- } else {
-
- flow { }
-
- }
+ ): Flow> {
+ return getAccelerometerRealtimeData(app, serial, accelScale, accelMode, fftAxis, fftMode, frequency)
}
}
fun calculateAngle(
- x: Float,
- y: Float
+ first: Float,
+ second: Float
): Float {
- var x = x
+ var first = first
- if(x == 0f && y == 0f){
- x = 0.0001f
+ if(first == 0f && second == 0f){
+ first = 0.0001f
}
- if(x > 0){
- return atan(y/x)
+ val result = when {
+ first > 0 -> atan(second / first)
+ first < 0 && second >= 0 -> atan(second / first) + PI.toFloat()
+ first < 0 && second < 0 -> atan(second/first) - PI.toFloat()
+ first == 0f && second > 0 -> PI.toFloat() / 2f
+ first == 0f && second < 0 -> -PI.toFloat() / 2f
+ else -> 0f
}
- if(x < 0 && y >= 0){
- return atan(y/x) + PI.toFloat()
- }
-
- if(x < 0 && y < 0){
- return atan(y/x) - PI.toFloat()
- }
-
- if(x == 0f && y > 0){
- return PI.toFloat() / 2f
- }
-
- if(x == 0f && y < 0){
- return -PI.toFloat() / 2f
- }
-
- return 0f
+ return result * 180f / Math.PI.toFloat()
}
\ No newline at end of file
diff --git a/app/src/main/java/llc/arma/ble/data/EmailRepositoryImpl.kt b/app/src/main/java/llc/arma/ble/data/EmailRepositoryImpl.kt
index fab9f76..6da8e60 100644
--- a/app/src/main/java/llc/arma/ble/data/EmailRepositoryImpl.kt
+++ b/app/src/main/java/llc/arma/ble/data/EmailRepositoryImpl.kt
@@ -3,20 +3,8 @@ package llc.arma.ble.data
import android.app.Application
import android.content.Intent
import androidx.core.content.FileProvider
-import llc.arma.ble.R
import llc.arma.ble.domain.repository.EmailRepository
-import llc.arma.ble.domain.repository.XlsxRepository
-import llc.arma.ble.domain.usecase.MeasureData
-import org.apache.poi.ss.SpreadsheetVersion
-import org.apache.poi.ss.usermodel.WorkbookFactory
-import org.apache.poi.ss.util.AreaReference
-import org.apache.poi.ss.util.CellReference
-import org.apache.poi.util.IOUtils
-import org.apache.poi.xssf.usermodel.XSSFSheet
import java.io.File
-import java.io.FileInputStream
-import java.io.FileOutputStream
-import java.util.UUID
import javax.inject.Inject
class EmailRepositoryImpl @Inject constructor(
diff --git a/app/src/main/java/llc/arma/ble/data/ReadAccelerometerHistory.kt b/app/src/main/java/llc/arma/ble/data/GetAccelerometerHistory.kt
similarity index 69%
rename from app/src/main/java/llc/arma/ble/data/ReadAccelerometerHistory.kt
rename to app/src/main/java/llc/arma/ble/data/GetAccelerometerHistory.kt
index e7905be..33f1c25 100644
--- a/app/src/main/java/llc/arma/ble/data/ReadAccelerometerHistory.kt
+++ b/app/src/main/java/llc/arma/ble/data/GetAccelerometerHistory.kt
@@ -10,56 +10,36 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
+import llc.arma.ble.data.extensions.checkPermission
+import llc.arma.ble.data.extensions.fromByte
+import llc.arma.ble.data.extensions.get2byteShortAt
+import llc.arma.ble.data.extensions.get2byteUIntAt
+import llc.arma.ble.data.extensions.get4byteUIntAt
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.usecase.AccelScale
import llc.arma.ble.domain.usecase.AccelViewMode
-import no.nordicsemi.android.common.core.DataByteArray
import no.nordicsemi.android.kotlin.ble.client.main.callback.ClientBleGatt
+import no.nordicsemi.android.kotlin.ble.core.data.util.DataByteArray
-fun Application.checkPermission(): Boolean {
-
- return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
- ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) ==
- PackageManager.PERMISSION_GRANTED &&
- ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN) ==
- PackageManager.PERMISSION_GRANTED
- } else {
- return ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) ==
- PackageManager.PERMISSION_GRANTED &&
- ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) ==
- PackageManager.PERMISSION_GRANTED
- }
-}
-
-fun ByteArray.get4byteUIntAt(idx: Int) =
- ((this[idx + 3].toUInt() and 0xFFu) shl 24) or
- ((this[idx + 2].toUInt() and 0xFFu) shl 16) or
- ((this[idx + 1].toUInt() and 0xFFu) shl 8) or
- (this[idx].toUInt() and 0xFFu)
-
-/*fun ByteArray.get2byteUIntAt(idx: Int) =
- ((this[idx + 1].toUInt() and 0xFFu) shl 8) or
- (this[idx].toUInt() and 0xFFu)*/
@OptIn(ExperimentalUnsignedTypes::class)
-fun readAccelerometerHistory(
+fun getAccelerometerHistory(
address: String,
- mode: AccelViewMode,
- scale: AccelScale,
app: Application,
): Flow>, BleException>> {
return flow {
+
var lastMeasureSystemTime: Long? = null
var bleMeasureInterval: Long? = null
var bleRealTime: Long? = null
var bleLastMeasureTime: Long? = null
- val resultTemperaturePackage: MutableList = mutableListOf()
+ val resultPackage: MutableList = mutableListOf()
val result = mutableListOf>()
@@ -67,10 +47,21 @@ fun readAccelerometerHistory(
if(app.checkPermission()) {
+ val connection =
+ ClientBleGatt.connect(app, address, CoroutineScope(Dispatchers.Default))
+
try {
- val connection =
- ClientBleGatt.connect(app, address, CoroutineScope(Dispatchers.Default))
+ val specData = connection.discoverServices()
+ .findService(serviceUUID)
+ ?.findCharacteristic(accelerometerReadUUID)
+ ?.let {
+ it.write(DataByteArray.from(4))
+ it.read()
+ } ?: throw IllegalStateException()
+
+ val scale = AccelScale.fromByte(specData.value[1]) ?: throw IllegalStateException()
+ val mode = AccelViewMode.fromByte(specData.value[0]) ?: throw IllegalStateException()
val characteristic = connection.discoverServices()
.findService(serviceUUID)
@@ -78,7 +69,6 @@ fun readAccelerometerHistory(
if(characteristic != null) {
-
characteristic.write(DataByteArray.from(2))
var value = characteristic.read().value
@@ -89,7 +79,7 @@ fun readAccelerometerHistory(
} else {
- Log.d("expected data size", value.get2byteUIntAt(0).toString())
+ var nextPackageDataCount = value.get2byteUIntAt(0)
val writeData = mutableListOf(
1.toByte(),
@@ -101,7 +91,7 @@ fun readAccelerometerHistory(
characteristic.write(DataByteArray(writeData))
value = characteristic.read().value
- var nextPackageDataCount = value.get2byteUIntAt(2)
+
while (nextPackageDataCount.toInt() != 0) {
@@ -112,7 +102,7 @@ fun readAccelerometerHistory(
bleRealTime = value.get4byteUIntAt(12).toLong()
lastMeasureSystemTime =
- System.currentTimeMillis() - ((bleRealTime!! - bleLastMeasureTime!!) * 1_000)
+ System.currentTimeMillis() - ((bleRealTime - bleLastMeasureTime) * 1_000)
value.toUByteArray().asList().subList(16, value.size)
@@ -125,23 +115,17 @@ fun readAccelerometerHistory(
result.add(value.toUByteArray().toList())
nextPackageDataCount = value.get2byteUIntAt(2)
- resultTemperaturePackage.addAll(
+ resultPackage.addAll(
temperatureDataArray.chunked(2).map {
it.toUByteArray().toByteArray().get2byteShortAt().toFloat()
}.toMutableList()
)
- Log.d(
- "received data size",
- (temperatureDataArray.chunked(2).size).toString()
- )
- Log.d("next data size", nextPackageDataCount.toString())
-
expectedDataSize =
- nextPackageDataCount.toInt() + resultTemperaturePackage.size
+ nextPackageDataCount.toInt() + resultPackage.size
emit(Result.success(ProgressState.Progress(0f / expectedDataSize.toFloat())))
- emit(Result.success(ProgressState.Progress(resultTemperaturePackage.size.toFloat() / expectedDataSize.toFloat())))
+ emit(Result.success(ProgressState.Progress(resultPackage.size.toFloat() / expectedDataSize.toFloat())))
characteristic.write(DataByteArray.from(5))
value = characteristic.read().value
@@ -152,13 +136,20 @@ fun readAccelerometerHistory(
Result.success(
ProgressState.Finished(
when (mode) {
- AccelViewMode.ROTATIONS,
+ AccelViewMode.ROTATIONS -> {
+ resultPackage.withIndex().map {
+ Ble.Accelerometer.HistoryPoint.Rotation(
+ date = lastMeasureSystemTime!! - (((resultPackage.size - 1) - it.index) * bleMeasureInterval!!),
+ value = it.value.toLong()
+ )
+ }
+ }
AccelViewMode.ACCELERATION,
AccelViewMode.PEAK_ACCELERATION,
AccelViewMode.RMS -> {
- resultTemperaturePackage.chunked(3).withIndex().map {
+ resultPackage.chunked(3).withIndex().map {
Ble.Accelerometer.HistoryPoint.Angle(
- date = lastMeasureSystemTime!! - (((resultTemperaturePackage.size - 1) - it.index) * bleMeasureInterval!!),
+ date = lastMeasureSystemTime!! - (((resultPackage.size - 1) - it.index) * bleMeasureInterval!!),
x = (it.value[0] * scale.k) / Short.MAX_VALUE,
y = (it.value[1] * scale.k) / Short.MAX_VALUE,
z = (it.value[2] * scale.k) / Short.MAX_VALUE
@@ -167,29 +158,29 @@ fun readAccelerometerHistory(
}
AccelViewMode.ANGLE -> {
- resultTemperaturePackage.chunked(3).withIndex().map {
+ resultPackage.chunked(3).withIndex().map {
Ble.Accelerometer.HistoryPoint.Angle(
- date = lastMeasureSystemTime!! - (((resultTemperaturePackage.size - 1) - it.index) * bleMeasureInterval!!),
+ date = lastMeasureSystemTime!! - (((resultPackage.size - 1) - it.index) * bleMeasureInterval!!),
x = calculateAngle(
it.value[2],
it.value[1]
- ) * 180f / Math.PI.toFloat(),
+ ),
y = calculateAngle(
it.value[2],
it.value[0]
- ) * 180f / Math.PI.toFloat(),
+ ),
z = calculateAngle(
it.value[0],
it.value[1]
- ) * 180f / Math.PI.toFloat()
+ )
)
}
}
AccelViewMode.VIBRATION -> {
- resultTemperaturePackage.withIndex().map {
+ resultPackage.withIndex().map {
Ble.Accelerometer.HistoryPoint.Vibration(
- date = lastMeasureSystemTime!! - (((resultTemperaturePackage.size - 1) - it.index) * bleMeasureInterval!!),
+ date = lastMeasureSystemTime!! - (((resultPackage.size - 1) - it.index) * bleMeasureInterval!!),
value = (it.value * scale.k) / Short.MAX_VALUE
)
}
@@ -210,13 +201,16 @@ fun readAccelerometerHistory(
}
} catch (err: Throwable) {
-
+ err.printStackTrace()
emit(Result.failure(BleException.UnexpectedResponse))
+ } finally {
+
+ connection.close()
+
}
} else {
-
emit(Result.failure(BleException.PermissionDenied))
}
diff --git a/app/src/main/java/llc/arma/ble/data/GetAccelerometerRealtimeData.kt b/app/src/main/java/llc/arma/ble/data/GetAccelerometerRealtimeData.kt
new file mode 100644
index 0000000..e8d68b1
--- /dev/null
+++ b/app/src/main/java/llc/arma/ble/data/GetAccelerometerRealtimeData.kt
@@ -0,0 +1,136 @@
+package llc.arma.ble.data
+
+import android.app.Application
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.flow
+import llc.arma.ble.data.extensions.checkPermission
+import llc.arma.ble.data.extensions.get2byteShortAt
+import llc.arma.ble.data.extensions.sendData
+import llc.arma.ble.domain.Result
+import llc.arma.ble.domain.common.BleException
+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.AccelViewMode.*
+import llc.arma.ble.domain.usecase.FftAxis
+import llc.arma.ble.domain.usecase.FftFrequency
+import llc.arma.ble.domain.usecase.FftViewMode
+import no.nordicsemi.android.kotlin.ble.client.main.callback.ClientBleGatt
+import no.nordicsemi.android.kotlin.ble.core.data.util.DataByteArray
+
+fun getAccelerometerRealtimeData(
+ app: Application,
+ serial: String,
+ accelScale: AccelScale,
+ accelMode: AccelViewMode,
+ fftAxis: FftAxis,
+ fftMode: FftViewMode,
+ frequency: FftFrequency,
+): Flow> {
+
+ return flow {
+
+ if(app.checkPermission()) {
+
+ val connection =
+ ClientBleGatt.connect(app, serial, CoroutineScope(Dispatchers.Default))
+
+ try {
+
+ val services = connection.discoverServices()
+
+ val characteristic =
+ services.findService(serviceUUID)
+ ?.findCharacteristic(accelerometerReadUUID)
+ ?: throw IllegalStateException()
+
+ characteristic.write(
+ DataByteArray.from(
+ 4,
+ accelMode.sendData,
+ accelScale.sendData,
+ fftMode.sendData,
+ fftAxis.sendData,
+ frequency.sendData,
+ 1
+ )
+ )
+
+ characteristic.getNotifications().collect {
+
+ val value = it.value
+
+ val data = value.toList().chunked(2).map {
+ it.toByteArray().get2byteShortAt()
+ }
+
+ val result = when(accelMode){
+ VIBRATION -> {
+ Ble.Accelerometer.RealtimePoint.Vibration(
+ (value.get2byteShortAt()
+ .toFloat() * accelScale.k) / Short.MAX_VALUE
+ )
+ }
+ ANGLE -> {
+ Ble.Accelerometer.RealtimePoint.Angle(
+ x = calculateAngle(
+ data[2].toFloat(),
+ data[1].toFloat()
+ ),
+ y = calculateAngle(
+ data[2].toFloat(),
+ data[0].toFloat()
+ ),
+ z = calculateAngle(
+ data[0].toFloat(),
+ data[1].toFloat()
+ )
+ )
+ }
+ ROTATIONS -> {
+ Ble.Accelerometer.RealtimePoint.Rotation(
+ angle = ((360f / 8f) * ((data[0] / 100f) + 1f)) - 45f,
+ tmp = data[1].toFloat(),
+ turnovers = data[2]
+ )
+ }
+ ACCELERATION,
+ PEAK_ACCELERATION,
+ RMS -> {
+ Ble.Accelerometer.RealtimePoint.Common(
+ x = (data[0].toFloat() * accelScale.k) / Short.MAX_VALUE,
+ y = (data[1].toFloat() * accelScale.k) / Short.MAX_VALUE,
+ z = (data[2].toFloat() * accelScale.k) / Short.MAX_VALUE,
+ )
+ }
+ }
+
+ emit(Result.success(result))
+
+ }
+
+
+ } catch (err: Exception) {
+
+ err.printStackTrace()
+
+ emit(Result.failure(BleException.UnexpectedResponse))
+
+ } finally {
+
+ connection.disconnect()
+ connection.close()
+
+ }
+
+ } else {
+
+ emit(Result.failure(BleException.PermissionDenied))
+
+ }
+
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/llc/arma/ble/data/ReadAccelerometerSpectreCallback.kt b/app/src/main/java/llc/arma/ble/data/ReadAccelerometerSpectreCallback.kt
index 067afa7..8acc858 100644
--- a/app/src/main/java/llc/arma/ble/data/ReadAccelerometerSpectreCallback.kt
+++ b/app/src/main/java/llc/arma/ble/data/ReadAccelerometerSpectreCallback.kt
@@ -1,19 +1,21 @@
package llc.arma.ble.data
-import android.Manifest
import android.app.Application
import android.bluetooth.BluetoothGatt
import android.bluetooth.BluetoothGattCallback
import android.bluetooth.BluetoothGattCharacteristic
import android.bluetooth.BluetoothGattDescriptor
-import android.content.pm.PackageManager
import android.os.Build
import android.util.Log
-import androidx.core.app.ActivityCompat
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
+import llc.arma.ble.data.extensions.checkPermission
+import llc.arma.ble.data.extensions.get2byteShortAt
+import llc.arma.ble.data.extensions.get2byteUIntAt
+import llc.arma.ble.data.extensions.get4byteUIntAt
+import llc.arma.ble.data.extensions.sendData
import llc.arma.ble.domain.Result
import llc.arma.ble.domain.common.BleException
import llc.arma.ble.domain.common.ProgressState
@@ -23,441 +25,14 @@ 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
-import no.nordicsemi.android.common.core.DataByteArray
import no.nordicsemi.android.kotlin.ble.client.main.callback.ClientBleGatt
+import no.nordicsemi.android.kotlin.ble.core.data.util.DataByteArray
import java.nio.ByteBuffer
import java.nio.ByteOrder.LITTLE_ENDIAN
import java.util.UUID
-fun ByteArray.get2byteShortAt(): Int {
- val shorts = ShortArray(1)
- ByteBuffer.wrap(this).order(LITTLE_ENDIAN).asShortBuffer()[shorts]
- return shorts[0].toInt()
-}
-class ReadAccelerometerSpectreCallback(
- private val app: Application,
- private val accelScale: AccelScale,
- private val accelMode: AccelViewMode,
- private val fftAxis: FftAxis,
- private val fftMode: FftViewMode,
- private val frequency: FftFrequency,
- private val onResult: (Result>, BleException>) -> Unit
-) : BluetoothGattCallback() {
- enum class Property {
- DATA_SIZE, PACKAGE
- }
-
- private fun ByteArray.get4byteUIntAt(idx: Int) =
- ((this[idx + 3].toUInt() and 0xFFu) shl 24) or
- ((this[idx + 2].toUInt() and 0xFFu) shl 16) or
- ((this[idx + 1].toUInt() and 0xFFu) shl 8) or
- (this[idx].toUInt() and 0xFFu)
-
- private fun ByteArray.get2byteUIntAt(idx: Int) =
- ((this[idx + 1].toUInt() and 0xFFu) shl 8) or
- (this[idx].toUInt() and 0xFFu)
-
- private var readProperty: Property? = null
-
- init {
- onResult(Result.success(ProgressState.Indeterminate))
- }
-
- override fun onConnectionStateChange(
- gatt: BluetoothGatt,
- status: Int,
- newState: Int
- ) {
- super.onConnectionStateChange(gatt, status, newState)
-
- if(status == BluetoothGatt.GATT_SUCCESS){
-
- if(newState == BluetoothGatt.STATE_CONNECTED){
-
- if (app.checkPermission()) {
- gatt.discoverServices()
- } else {
- onResult(Result.failure(BleException.UnexpectedResponse))
- gatt.close()
- }
- }
-
- } else {
-
- onResult(Result.failure(BleException.UnexpectedResponse))
- gatt.close()
-
- }
-
- }
-
- override fun onServicesDiscovered(
- gatt: BluetoothGatt,
- status: Int
- ) {
- super.onServicesDiscovered(gatt, status)
-
- if(status == BluetoothGatt.GATT_SUCCESS){
- enableNotifications(gatt)
- }
-
- }
-
- private fun enableNotifications(
- gatt: BluetoothGatt
- ){
-
- gatt.getService(serviceUUID)?.getCharacteristic(accelerometerReadUUID)?.let {
-
- if (app.checkPermission()) {
-
- gatt.setCharacteristicNotification(it, true)
-
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
- gatt.writeDescriptor(it.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb")),
- BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE)
- } else {
- val descriptor = it.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"))
- descriptor.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE
- gatt.writeDescriptor(descriptor)
- }
-
- Log.d("spectre", "enable notification")
-
- onResult(Result.success(ProgressState.Indeterminate))
- resultAccelerometerPackage.clear()
-
- } else {
- onResult(Result.failure(BleException.PermissionDenied))
- gatt.close()
- }
-
- return
-
- }
-
- onResult(Result.failure(BleException.UnexpectedResponse))
-
- }
-
- private var initialValue: Long? = null
- private var frequencyInterval: Long? = null
-
- private val resultAccelerometerPackage: MutableList = mutableListOf()
-
- private var expectedDataSize: Int? = null
-
- @Deprecated("Deprecated in Java")
- override fun onCharacteristicRead(
- gatt: BluetoothGatt,
- characteristic: BluetoothGattCharacteristic,
- status: Int
- ) {
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
- super.onCharacteristicRead(gatt, characteristic, status)
- onCommonCharacteristicRead(gatt, characteristic, characteristic.value, status)
- }
- }
-
- @Deprecated("Deprecated in Java")
- override fun onCharacteristicChanged(
- gatt: BluetoothGatt,
- characteristic: BluetoothGattCharacteristic
- ) {
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
- super.onCharacteristicChanged(gatt, characteristic)
- onCommonCharacteristicChanged(gatt, characteristic, characteristic.value)
- }
- }
-
- override fun onCharacteristicChanged(
- gatt: BluetoothGatt,
- characteristic: BluetoothGattCharacteristic,
- value: ByteArray
- ) {
- super.onCharacteristicChanged(gatt, characteristic, value)
- onCommonCharacteristicChanged(gatt, characteristic, value)
- }
-
- private fun onCommonCharacteristicChanged(
- gatt: BluetoothGatt,
- characteristic: BluetoothGattCharacteristic,
- value: ByteArray,
- ){
-
- if(characteristic.uuid == accelerometerReadUUID) {
-
- readProperty = Property.DATA_SIZE
- gatt.getService(serviceUUID).getCharacteristic(accelerometerHistoryReadUUID)?.let {
- gatt.writeCharacteristic(it, byteArrayOf(2))
- }
-
- }
- }
-
- override fun onCharacteristicRead(
- gatt: BluetoothGatt,
- characteristic: BluetoothGattCharacteristic,
- value: ByteArray,
- status: Int
- ) {
- super.onCharacteristicRead(gatt, characteristic, value, status)
- onCommonCharacteristicRead(gatt, characteristic, value, status)
- }
-
- private fun onCommonCharacteristicRead(
- gatt: BluetoothGatt,
- characteristic: BluetoothGattCharacteristic,
- value: ByteArray,
- status: Int
- ){
-
- Log.d("value", value.joinToString(separator = ""))
-
- if(status == BluetoothGatt.GATT_SUCCESS){
- when(readProperty){
- Property.DATA_SIZE -> {
-
- if(value.contentEquals(byteArrayOf(0, 0))) {
- onResult(
- Result.success(
- ProgressState.Finished(
- emptyList()
- )
- )
- )
- gatt.close()
-
- } else {
-
- val writeData = mutableListOf(
- 1.toByte(),
- 0.toByte(),
- 0.toByte()
- ).apply {
- addAll(value.toList())
- }.toByteArray()
-
- readProperty = Property.PACKAGE
- gatt.writeCharacteristic(characteristic, writeData)
-
- }
- }
- Property.PACKAGE -> {
-
- if(value[0] == 250.toByte()){
-
- initialValue = value.get4byteUIntAt(8).toLong()
- frequencyInterval = value.get4byteUIntAt(4).toLong()
-
- val accelerometerDataArray = value.asList().subList(16, value.size)
-
- resultAccelerometerPackage.addAll(
- accelerometerDataArray.chunked(2).map {
- it.toByteArray().get2byteShortAt().toFloat()
- }.toMutableList()
- )
-
- val nextPackageDataCount = value.get2byteUIntAt(2)
- expectedDataSize = nextPackageDataCount.toInt() + resultAccelerometerPackage.size
-
- onResult(Result.success(ProgressState.Progress(0f / expectedDataSize!!.toFloat())))
- onResult(Result.success(ProgressState.Progress(resultAccelerometerPackage.size.toFloat() / expectedDataSize!!.toFloat())))
-
- if(nextPackageDataCount != 0.toUInt()){
-
- if (app.checkPermission()) {
-
- gatt.writeCharacteristic(characteristic, byteArrayOf(5))
- gatt.readCharacteristic(characteristic)
-
- } else {
-
- onResult(Result.failure(BleException.PermissionDenied))
- gatt.close()
-
- }
-
- } else {
-
- onResult(
- Result.success(
- ProgressState.Finished(
- resultAccelerometerPackage.withIndex().map {
- Ble.Accelerometer.MeasurePoint(
- frequency = frequencyInterval!! * it.index + initialValue!!,
- value = (it.value * accelScale.k) / Short.MAX_VALUE
- )
- }
- )
- )
- )
-
- start(gatt)
-
- }
-
- } else {
-
- if (value[0] == 251.toByte()) {
-
- val nextPackageDataCount = value.get2byteUIntAt(2)
- val temperatureDataArray = value.toList().subList(4, value.size)
-
- resultAccelerometerPackage.addAll(
- temperatureDataArray.chunked(2).map {
- it.toByteArray().get2byteShortAt().toFloat()
- }
- )
-
- onResult(Result.success(ProgressState.Progress(resultAccelerometerPackage.size.toFloat() / expectedDataSize!!.toFloat())))
-
- if (nextPackageDataCount != 0.toUInt()) {
-
- val writeData = byteArrayOf(5)
-
- gatt.writeCharacteristic(characteristic, writeData)
- gatt.readCharacteristic(characteristic)
-
- } else {
-
- onResult(
- Result.success(
- ProgressState.Finished(
- resultAccelerometerPackage.withIndex().map {
- Ble.Accelerometer.MeasurePoint(
- frequency = frequencyInterval!! * it.index + initialValue!!,
- value = (it.value * accelScale.k) / Short.MAX_VALUE
- )
- }
- )
- )
- )
-
- start(gatt)
-
- }
- } else {
- onResult(Result.failure(BleException.UnexpectedResponse))
- gatt.close()
- }
-
- }
- }
- else -> {
- onResult(Result.failure(BleException.UnexpectedResponse))
- gatt.close()
-
- }
-
- }
-
- }
- }
-
- override fun onCharacteristicWrite(
- gatt: BluetoothGatt,
- characteristic: BluetoothGattCharacteristic,
- status: Int
- ) {
- super.onCharacteristicWrite(gatt, characteristic, status)
-
- if(readProperty !== null) {
-
- if (status == BluetoothGatt.GATT_SUCCESS) {
-
- if (app.checkPermission()) {
-
- gatt.readCharacteristic(characteristic)
-
- } else {
-
- onResult(Result.failure(BleException.PermissionDenied))
- gatt.close()
-
- }
-
- } else {
- onResult(Result.failure(BleException.UnexpectedResponse))
- gatt.close()
- }
- }
-
- }
-
- override fun onDescriptorWrite(
- gatt: BluetoothGatt,
- descriptor: BluetoothGattDescriptor,
- status: Int
- ) {
- super.onDescriptorWrite(gatt, descriptor, status)
- start(gatt)
- }
-
- private fun start(
- gatt: BluetoothGatt,
- ){
-
- gatt.getService(serviceUUID)?.getCharacteristic(accelerometerReadUUID)?.let {
-
- if (app.checkPermission()) {
-
- val payload = byteArrayOf(
- 4,
- accelMode.sendData,
- accelScale.sendData,
- fftMode.sendData,
- fftAxis.sendData,
- frequency.sendData,
- 2
- )
- readProperty = null
- gatt.writeCharacteristic(it, payload)
-
- onResult(Result.success(ProgressState.Indeterminate))
- resultAccelerometerPackage.clear()
-
- } else {
-
- onResult(Result.failure(BleException.PermissionDenied))
- gatt.close()
-
- }
-
- return
-
- }
-
- }
-
- private fun BluetoothGatt.writeCharacteristic(
- characteristic: BluetoothGattCharacteristic,
- data: ByteArray
- ): Result{
-
- return if(app.checkPermission()){
-
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
- writeCharacteristic(characteristic, data, BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT)
- }else{
- characteristic.value = data
- writeCharacteristic(characteristic)
- }
-
- Result.success(Unit)
-
- } else {
- Result.failure(BleException.PermissionDenied)
- }
-
- }
-
-}
-
-
-@OptIn(ExperimentalUnsignedTypes::class)
fun readAccelerometerSpectre(
address: String,
app: Application,
@@ -466,72 +41,65 @@ fun readAccelerometerSpectre(
fftAxis: FftAxis,
fftMode: FftViewMode,
frequency: FftFrequency,
-): Flow>, BleException>> {
+): Flow>, BleException>> {
return flow {
- var initialValue: Long? = null
- var frequencyInterval: Long? = null
-
- val resultAccelerometerPackage: MutableList = mutableListOf()
-
- var expectedDataSize: Int? = null
-
if(app.checkPermission()) {
+ val connection =
+ ClientBleGatt.connect(app, address, CoroutineScope(Dispatchers.Default))
+
try {
- val connection =
- ClientBleGatt.connect(app, address, CoroutineScope(Dispatchers.Default))
+ val service = connection.discoverServices()
+ .findService(serviceUUID) ?: throw IllegalStateException()
- val characteristic = connection.discoverServices()
- .findService(serviceUUID)
- ?.findCharacteristic(accelerometerReadUUID)
+ val characteristic = service.findCharacteristic(accelerometerReadUUID)
?: throw IllegalStateException()
- val historyCharacteristic = connection.discoverServices()
- .findService(serviceUUID)
- ?.findCharacteristic(accelerometerHistoryReadUUID)
+ val historyCharacteristic = service.findCharacteristic(accelerometerHistoryReadUUID)
?: throw IllegalStateException()
- Log.d("notification", "-1")
+ characteristic.findDescriptor(
+ UUID.fromString("00002902-0000-1000-8000-00805f9b34fb")
+ )?.write(DataByteArray(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE))
+ ?: throw IllegalStateException()
- Log.d("notification", "0")
-
- characteristic.write(DataByteArray(byteArrayOf(
- 4,
- accelMode.sendData,
- accelScale.sendData,
- fftMode.sendData,
- fftAxis.sendData,
- frequency.sendData,
- 2
- )))
-
- Log.d("notification", "1")
+ characteristic.write(
+ DataByteArray(byteArrayOf(
+ 4,
+ accelMode.sendData,
+ accelScale.sendData,
+ fftMode.sendData,
+ fftAxis.sendData,
+ frequency.sendData,
+ 2
+ ))
+ )
val notifications = characteristic.getNotifications()
notifications.collect {
+ var initialValue: Long? = null
+ var frequencyInterval: Long? = null
+ val resultAccelerometerPackage: MutableList = mutableListOf()
- Log.d("notification", "0")
+ var expectedDataSize: Int? = null
historyCharacteristic.write(DataByteArray.from(2))
var value = historyCharacteristic.read().value
- Log.d("value", value.joinToString(separator = ""))
- Log.d("value", value.get2byteUIntAt(0).toString())
-
if (value.contentEquals(byteArrayOf(0, 0))) {
emit(Result.success(ProgressState.Finished(emptyList())))
} else {
- Log.d("expected data size", value.get2byteUIntAt(0).toString())
+ var nextPackageDataCount = value.get2byteUIntAt(0)
val writeData = mutableListOf(
1.toByte(),
@@ -543,7 +111,7 @@ fun readAccelerometerSpectre(
historyCharacteristic.write(DataByteArray(writeData))
value = historyCharacteristic.read().value
- var nextPackageDataCount = value.get2byteUIntAt(2)
+
while (nextPackageDataCount.toInt() != 0) {
@@ -569,8 +137,8 @@ fun readAccelerometerSpectre(
expectedDataSize = nextPackageDataCount.toInt() + resultAccelerometerPackage.size
- emit(Result.success(ProgressState.Progress(0f / expectedDataSize!!.toFloat())))
- emit(Result.success(ProgressState.Progress(resultAccelerometerPackage.size.toFloat() / expectedDataSize!!.toFloat())))
+ emit(Result.success(ProgressState.Progress(0f / expectedDataSize.toFloat())))
+ emit(Result.success(ProgressState.Progress(resultAccelerometerPackage.size.toFloat() / expectedDataSize.toFloat())))
historyCharacteristic.write(DataByteArray.from(5))
value = historyCharacteristic.read().value
@@ -581,7 +149,7 @@ fun readAccelerometerSpectre(
Result.success(
ProgressState.Finished(
resultAccelerometerPackage.withIndex().map {
- Ble.Accelerometer.MeasurePoint(
+ Ble.Accelerometer.SpectrePoint(
frequency = frequencyInterval!! * it.index + initialValue!!,
value = (it.value * accelScale.k) / Short.MAX_VALUE
)
@@ -611,6 +179,10 @@ fun readAccelerometerSpectre(
err.printStackTrace()
emit(Result.failure(BleException.UnexpectedResponse))
+ } finally {
+
+ connection.close()
+
}
} else {
diff --git a/app/src/main/java/llc/arma/ble/data/ReadTemperatureHistoryCallback.kt b/app/src/main/java/llc/arma/ble/data/ReadTemperatureHistoryCallback.kt
index 256554d..625b47c 100644
--- a/app/src/main/java/llc/arma/ble/data/ReadTemperatureHistoryCallback.kt
+++ b/app/src/main/java/llc/arma/ble/data/ReadTemperatureHistoryCallback.kt
@@ -1,339 +1,31 @@
package llc.arma.ble.data
-import android.Manifest
import android.app.Application
import android.bluetooth.BluetoothGatt
import android.bluetooth.BluetoothGattCallback
import android.bluetooth.BluetoothGattCharacteristic
-import android.content.pm.PackageManager
import android.os.Build
import android.util.Log
-import androidx.core.app.ActivityCompat
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
+import llc.arma.ble.data.extensions.checkPermission
+import llc.arma.ble.data.extensions.get2byteUIntAt
+import llc.arma.ble.data.extensions.get4byteUIntAt
+import llc.arma.ble.data.extensions.toTemperature
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.usecase.AccelScale
-import llc.arma.ble.domain.usecase.AccelViewMode
-import no.nordicsemi.android.common.core.DataByteArray
import no.nordicsemi.android.kotlin.ble.client.main.callback.ClientBleGatt
-
-class ReadTemperatureHistoryCallback(
- private val app: Application,
- private val onResult: (Result>, BleException>) -> Unit
-) : BluetoothGattCallback() {
-
- enum class Property {
- DATA_SIZE, PACKAGE
- }
-
- private fun ByteArray.get4byteUIntAt(idx: Int) =
- ((this[idx + 3].toUInt() and 0xFFu) shl 24) or
- ((this[idx + 2].toUInt() and 0xFFu) shl 16) or
- ((this[idx + 1].toUInt() and 0xFFu) shl 8) or
- (this[idx].toUInt() and 0xFFu)
-
- private fun ByteArray.get2byteUIntAt(idx: Int) =
- ((this[idx + 1].toUInt() and 0xFFu) shl 8) or
- (this[idx].toUInt() and 0xFFu)
-
- private var readProperty: Property? = null
-
- init {
- onResult(Result.success(ProgressState.Indeterminate))
- }
-
- override fun onConnectionStateChange(
- gatt: BluetoothGatt,
- status: Int,
- newState: Int
- ) {
- super.onConnectionStateChange(gatt, status, newState)
-
- if(status == BluetoothGatt.GATT_SUCCESS){
-
- if(newState == BluetoothGatt.STATE_CONNECTED){
-
- if (app.checkPermission()) {
- gatt.discoverServices()
-
- } else {
- onResult(Result.failure(BleException.UnexpectedResponse))
- gatt.close()
- }
- }
-
- } else {
-
- onResult(Result.failure(BleException.UnexpectedResponse))
- gatt.close()
-
- }
-
- }
-
- override fun onServicesDiscovered(
- gatt: BluetoothGatt,
- status: Int
- ) {
- super.onServicesDiscovered(gatt, status)
- if(status == BluetoothGatt.GATT_SUCCESS){
- gatt.getService(serviceUUID)?.getCharacteristic(temperatureHistoryReadUUID)?.let {
-
- if (app.checkPermission()) {
-
- readProperty = Property.DATA_SIZE
- gatt.writeCharacteristic(it, byteArrayOf(2))
-
- } else {
-
- onResult(Result.failure(BleException.PermissionDenied))
- gatt.close()
-
- }
-
- }
-
- }
-
- }
-
- private var lastMeasureSystemTime: Long? = null
-
- private var bleMeasureInterval: Long? = null
- private var bleRealTime: Long? = null
- private var bleLastMeasureTime: Long? = null
-
- private val resultTemperaturePackage: MutableList = mutableListOf()
-
- var expectedDataSize: Int? = null
-
- override fun onCharacteristicRead(
- gatt: BluetoothGatt,
- characteristic: BluetoothGattCharacteristic,
- status: Int
- ) {
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
- super.onCharacteristicRead(gatt, characteristic, status)
- onCommonCharacteristicRead(gatt, characteristic, characteristic.value, status)
- }
- }
-
- override fun onCharacteristicRead(
- gatt: BluetoothGatt,
- characteristic: BluetoothGattCharacteristic,
- value: ByteArray,
- status: Int
- ) {
- super.onCharacteristicRead(gatt, characteristic, value, status)
- onCommonCharacteristicRead(gatt, characteristic, value, status)
- }
-
- @OptIn(ExperimentalUnsignedTypes::class)
- private fun onCommonCharacteristicRead(
- gatt: BluetoothGatt,
- characteristic: BluetoothGattCharacteristic,
- value: ByteArray,
- status: Int
- ){
-
- if(status == BluetoothGatt.GATT_SUCCESS){
- when(readProperty){
- Property.DATA_SIZE -> {
-
- if(value.contentEquals(byteArrayOf(0, 0))) {
- onResult(
- Result.success(
- ProgressState.Finished(
- emptyList()
- )
- )
- )
- gatt.close()
-
- } else {
-
- val writeData = mutableListOf(
- 1.toByte(),
- 0.toByte(),
- 0.toByte()
- ).apply {
- addAll(value.toList())
- }.toByteArray()
-
- readProperty = Property.PACKAGE
- gatt.writeCharacteristic(characteristic, writeData)
-
- }
- }
- Property.PACKAGE -> {
-
- if(value[0] == 250.toByte()){
-
- bleMeasureInterval = value.get4byteUIntAt(4).toLong()
- bleLastMeasureTime = value.get4byteUIntAt(8).toLong()
- bleRealTime = value.get4byteUIntAt(12).toLong()
-
- lastMeasureSystemTime = System.currentTimeMillis() - ((bleRealTime!! - bleLastMeasureTime!!) * 1_000)
-
- val temperatureDataArray = value.toUByteArray().asList().subList(16, value.size)
-
- resultTemperaturePackage.addAll(
- temperatureDataArray.chunked(2).map {
- it.toUByteArray().toTemperature()
- }.toMutableList()
- )
-
- val nextPackageDataCount = value.get2byteUIntAt(2)
- expectedDataSize = nextPackageDataCount.toInt() + resultTemperaturePackage.size
- Log.d("read", expectedDataSize.toString())
- onResult(Result.success(ProgressState.Progress(0f / expectedDataSize!!.toFloat())))
- onResult(Result.success(ProgressState.Progress(resultTemperaturePackage.size.toFloat() / expectedDataSize!!.toFloat())))
-
- if(nextPackageDataCount != 0.toUInt()){
-
- if (app.checkPermission()) {
-
- gatt.writeCharacteristic(characteristic, byteArrayOf(5))
- gatt.readCharacteristic(characteristic)
-
- } else {
-
- onResult(Result.failure(BleException.PermissionDenied))
- gatt.close()
-
- }
-
- } else {
- onResult(
- Result.success(
- ProgressState.Finished(
- resultTemperaturePackage.withIndex().map {
- Ble.Thermometer.MeasurePoint(
- date = lastMeasureSystemTime!! - (((resultTemperaturePackage.size - 1) - it.index) * bleMeasureInterval!!),
- value = it.value
- )
- }
- )
- )
- )
- gatt.close()
- }
-
- } else {
-
- if (value[0] == 251.toByte()) {
-
- val nextPackageDataCount = value.get2byteUIntAt(2)
- val temperatureDataArray = value.toUByteArray().toList().subList(4, value.size)
-
- resultTemperaturePackage.addAll(
- temperatureDataArray.chunked(2).map {
- it.toUByteArray().toTemperature()
- }
- )
-
- onResult(Result.success(ProgressState.Progress(resultTemperaturePackage.size.toFloat() / expectedDataSize!!.toFloat())))
-
- if (nextPackageDataCount != 0.toUInt()) {
-
- val writeData = byteArrayOf(5)
-
- gatt.writeCharacteristic(characteristic, writeData)
- gatt.readCharacteristic(characteristic)
-
- } else {
- onResult(
- Result.success(
- ProgressState.Finished(
- resultTemperaturePackage.withIndex().map {
- Ble.Thermometer.MeasurePoint(
- date = lastMeasureSystemTime!! - (((resultTemperaturePackage.size - 1) - it.index) * bleMeasureInterval!!),
- value = it.value
- )
- }
- )
- )
- )
- gatt.close()
- }
- } else {
- onResult(Result.failure(BleException.UnexpectedResponse))
- gatt.close()
- }
-
- }
- }
- else -> {
- onResult(Result.failure(BleException.UnexpectedResponse))
- gatt.close()
-
- }
-
- }
-
- }
- }
-
- override fun onCharacteristicWrite(
- gatt: BluetoothGatt,
- characteristic: BluetoothGattCharacteristic,
- status: Int
- ) {
- super.onCharacteristicWrite(gatt, characteristic, status)
- if(status == BluetoothGatt.GATT_SUCCESS){
-
- if (app.checkPermission()) {
-
- gatt.readCharacteristic(characteristic)
-
- } else {
-
- onResult(Result.failure(BleException.PermissionDenied))
- gatt.close()
-
- }
-
- } else {
- onResult(Result.failure(BleException.UnexpectedResponse))
- gatt.close()
- }
-
- }
-
- fun BluetoothGatt.writeCharacteristic(
- characteristic: BluetoothGattCharacteristic,
- data: ByteArray
- ): Result{
-
- return if(app.checkPermission()){
-
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
- writeCharacteristic(characteristic, data, BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT)
- }else{
- characteristic.value = data
- writeCharacteristic(characteristic)
- }
-
- Result.success(Unit)
-
- } else {
- Result.failure(BleException.PermissionDenied)
- }
-
- }
-
-}
+import no.nordicsemi.android.kotlin.ble.core.data.util.DataByteArray
@OptIn(ExperimentalUnsignedTypes::class)
fun readThermometerHistory(
address: String,
app: Application,
-): Flow>, BleException>> {
+): Flow>, BleException>> {
return flow {
@@ -369,8 +61,6 @@ fun readThermometerHistory(
} else {
- Log.d("expected data size", value.get2byteUIntAt(0).toString())
-
val writeData = mutableListOf(
1.toByte(),
0.toByte(),
@@ -410,12 +100,6 @@ fun readThermometerHistory(
}.toMutableList()
)
- Log.d(
- "received data size",
- (temperatureDataArray.chunked(2).size).toString()
- )
- Log.d("next data size", nextPackageDataCount.toString())
-
expectedDataSize =
nextPackageDataCount.toInt() + resultTemperaturePackage.size
@@ -431,7 +115,7 @@ fun readThermometerHistory(
Result.success(
ProgressState.Finished(
resultTemperaturePackage.withIndex().map {
- Ble.Thermometer.MeasurePoint(
+ Ble.Thermometer.HistoryPoint(
date = lastMeasureSystemTime!! - (((resultTemperaturePackage.size - 1) - it.index) * bleMeasureInterval!!),
value = it.value
)
diff --git a/app/src/main/java/llc/arma/ble/data/XlsxRepositoryImpl.kt b/app/src/main/java/llc/arma/ble/data/XlsxRepositoryImpl.kt
index 453907a..616d892 100644
--- a/app/src/main/java/llc/arma/ble/data/XlsxRepositoryImpl.kt
+++ b/app/src/main/java/llc/arma/ble/data/XlsxRepositoryImpl.kt
@@ -1,10 +1,9 @@
package llc.arma.ble.data
-import android.R.attr.src
import android.app.Application
import android.icu.text.SimpleDateFormat
import android.os.Environment
-import android.os.FileUtils
+import android.util.Log
import llc.arma.ble.R
import llc.arma.ble.domain.model.Ble
import llc.arma.ble.domain.repository.XlsxRepository
@@ -15,7 +14,6 @@ import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.util.Date
-import java.util.UUID
import javax.inject.Inject
@@ -28,12 +26,14 @@ class XlsxRepositoryImpl @Inject constructor(
data: List
): File {
- val fileNameDateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS")
- val fileName = "$bleName ${fileNameDateFormat.format(Date(System.currentTimeMillis()))}.xlsx"
+ val fileNameDateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm")
+ val fileName = "${fileNameDateFormat.format(Date(System.currentTimeMillis()))}.xlsx".replace(' ', '_')
val formatter = SimpleDateFormat("dd.MM.yyyy HH:mm")
+ File(application.filesDir.absolutePath).mkdirs()
val mailFile = File(application.filesDir, fileName)
+
mailFile.createNewFile()
when(data.firstOrNull()){
@@ -73,7 +73,7 @@ class XlsxRepositoryImpl @Inject constructor(
x.setCellValue(value.value.toDouble())
}
- is Ble.Accelerometer.HistoryPoint.Accelerate -> {
+ is Ble.Accelerometer.HistoryPoint.Acceleration -> {
dateX.setCellValue(formatter.format(Date(value.date)))
dateY.setCellValue(formatter.format(Date(value.date)))
dateZ.setCellValue(formatter.format(Date(value.date)))
@@ -82,6 +82,10 @@ class XlsxRepositoryImpl @Inject constructor(
z.setCellValue(value.z.toDouble())
}
+ is Ble.Accelerometer.HistoryPoint.Rotation -> {
+ dateX.setCellValue(formatter.format(Date(value.date)))
+ x.setCellValue(value.value.toDouble())
+ }
}
}
diff --git a/app/src/main/java/llc/arma/ble/data/extensions/ApplicationExtension.kt b/app/src/main/java/llc/arma/ble/data/extensions/ApplicationExtension.kt
new file mode 100644
index 0000000..3ad29b7
--- /dev/null
+++ b/app/src/main/java/llc/arma/ble/data/extensions/ApplicationExtension.kt
@@ -0,0 +1,22 @@
+package llc.arma.ble.data.extensions
+
+import android.Manifest
+import android.app.Application
+import android.content.pm.PackageManager
+import android.os.Build
+import androidx.core.app.ActivityCompat
+
+fun Application.checkPermission(): Boolean {
+
+ return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+ ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) ==
+ PackageManager.PERMISSION_GRANTED &&
+ ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN) ==
+ PackageManager.PERMISSION_GRANTED
+ } else {
+ return ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) ==
+ PackageManager.PERMISSION_GRANTED &&
+ ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) ==
+ PackageManager.PERMISSION_GRANTED
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/llc/arma/ble/data/extensions/BleEnumExtensions.kt b/app/src/main/java/llc/arma/ble/data/extensions/BleEnumExtensions.kt
new file mode 100644
index 0000000..3c965e2
--- /dev/null
+++ b/app/src/main/java/llc/arma/ble/data/extensions/BleEnumExtensions.kt
@@ -0,0 +1,93 @@
+package llc.arma.ble.data.extensions
+
+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
+
+fun Ble.BleState.TX.Companion.fromByte(byte: Byte): Ble.BleState.TX? {
+ return Ble.BleState.TX.values().associateBy { it.sendData }[byte]
+}
+
+val Ble.BleState.TX.sendData: Byte
+ get() {
+ return when (this) {
+ Ble.BleState.TX.MINUS_40 -> -40
+ Ble.BleState.TX.MINUS_20 -> -20
+ Ble.BleState.TX.MINUS_16 -> -16
+ Ble.BleState.TX.MINUS_12 -> -12
+ Ble.BleState.TX.MINUS_8 -> -8
+ Ble.BleState.TX.MINUS_4 -> -4
+ Ble.BleState.TX.ZERO -> 0
+ Ble.BleState.TX.PLUS_3 -> 3
+ Ble.BleState.TX.PLUS_4 -> 4
+ }
+ }
+
+val FftFrequency.sendData: Byte
+ get() {
+ return when(this){
+ FftFrequency.OFF -> 0
+ FftFrequency.F_1 -> 1
+ FftFrequency.F_10 -> 2
+ FftFrequency.F_25 -> 3
+ FftFrequency.F_50 -> 4
+ FftFrequency.F_100 -> 5
+ FftFrequency.F_200 -> 6
+ FftFrequency.F_400 -> 7
+ FftFrequency.F_1620 -> 8
+ FftFrequency.F_1344 -> 9
+ }
+ }
+
+val FftAxis.sendData: Byte
+ get() {
+ return when(this){
+ FftAxis.AUTO -> 0
+ FftAxis.X -> 1
+ FftAxis.Y -> 2
+ FftAxis.Z -> 3
+ }
+ }
+
+val FftViewMode.sendData: Byte
+ get() {
+ return when(this){
+ FftViewMode.SPECTRE -> 0
+ FftViewMode.X -> 1
+ FftViewMode.Y -> 2
+ FftViewMode.Z -> 3
+ }
+ }
+
+fun AccelViewMode.Companion.fromByte(byte: Byte): AccelViewMode? {
+ return AccelViewMode.values().associateBy { it.sendData }[byte]
+}
+
+val AccelViewMode.sendData: Byte
+ get() {
+ return when(this){
+ AccelViewMode.ACCELERATION -> 0
+ AccelViewMode.PEAK_ACCELERATION -> 1
+ AccelViewMode.RMS -> 2
+ AccelViewMode.VIBRATION -> 3
+ AccelViewMode.ANGLE -> 4
+ AccelViewMode.ROTATIONS -> 5
+ }
+ }
+
+fun AccelScale.Companion.fromByte(byte: Byte): AccelScale? {
+ return AccelScale.values().associateBy { it.sendData }[byte]
+}
+
+val AccelScale.sendData: Byte
+ get() {
+ return when(this){
+ AccelScale.S_2 -> 0
+ AccelScale.S_4 -> 1
+ AccelScale.S_8 -> 2
+ AccelScale.S_16 -> 3
+ }
+ }
\ No newline at end of file
diff --git a/app/src/main/java/llc/arma/ble/data/extensions/BleScanResultExtensions.kt b/app/src/main/java/llc/arma/ble/data/extensions/BleScanResultExtensions.kt
new file mode 100644
index 0000000..5d7bdf3
--- /dev/null
+++ b/app/src/main/java/llc/arma/ble/data/extensions/BleScanResultExtensions.kt
@@ -0,0 +1,40 @@
+package llc.arma.ble.data.extensions
+
+import llc.arma.ble.domain.model.BleInfo
+import no.nordicsemi.android.kotlin.ble.core.scanner.BleScanResult
+
+val BleScanResult.timerEnabled: Boolean
+ get() {
+ return data?.scanRecord?.manufacturerSpecificData?.get(89)?.getByte(2) == 1.toByte()
+ }
+
+val BleScanResult.info: BleInfo
+ get() {
+ this.device.name
+ return BleInfo(
+ name = this.device.name ?: "",
+ serial = device.address,
+ batteryLevel = batteryLevel ?: 0,
+ rssi = data?.rssi,
+ type = type,
+ scanTime = (data?.timestampNanos ?: 0) / 1_000_000,
+ tx = data?.txPower ?: 0,
+ recordEnabled = timerEnabled
+ )
+ }
+
+val BleScanResult.batteryLevel: Int?
+ get() {
+ return data?.scanRecord?.manufacturerSpecificData?.get(89)?.getByte(1)
+ ?.toUByte()?.toInt()
+ }
+
+val BleScanResult.type: BleInfo.Type
+ get() {
+ return when(data?.scanRecord?.manufacturerSpecificData?.get(89)?.getByte(0)?.toUByte()?.toInt()){
+ 1 -> BleInfo.Type.BEACON
+ 2 -> BleInfo.Type.THERMOMETER
+ else -> BleInfo.Type.ACCELEROMETER
+ }
+ }
+
diff --git a/app/src/main/java/llc/arma/ble/data/extensions/ByteArrayExtensions.kt b/app/src/main/java/llc/arma/ble/data/extensions/ByteArrayExtensions.kt
new file mode 100644
index 0000000..a5269f4
--- /dev/null
+++ b/app/src/main/java/llc/arma/ble/data/extensions/ByteArrayExtensions.kt
@@ -0,0 +1,35 @@
+package llc.arma.ble.data.extensions
+
+import java.nio.ByteBuffer
+import java.nio.ByteOrder
+
+fun ByteArray.get2byteShortAt(): Int {
+ val shorts = ShortArray(1)
+ ByteBuffer.wrap(this).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer()[shorts]
+ return shorts[0].toInt()
+}
+
+fun ByteArray.get4byteUIntAt(idx: Int) =
+ ((this[idx + 3].toUInt() and 0xFFu) shl 24) or
+ ((this[idx + 2].toUInt() and 0xFFu) shl 16) or
+ ((this[idx + 1].toUInt() and 0xFFu) shl 8) or
+ (this[idx].toUInt() and 0xFFu)
+
+fun ByteArray.get2byteUIntAt(idx: Int) =
+ ((this[idx + 1].toUInt() and 0xFFu) shl 8) or
+ (this[idx].toUInt() and 0xFFu)
+
+@OptIn(ExperimentalUnsignedTypes::class)
+fun UByteArray.toTemperature(): Float {
+
+ val uShort = (this[0] + this[1] * 256u).toUShort()
+
+ val result = if (uShort > Short.MAX_VALUE.toUShort()) {
+ ((uShort.inv() + 1u).toFloat().unaryMinus()) / 100f
+ } else {
+ uShort.toFloat() / 100f
+ }
+
+ return result
+
+}
diff --git a/app/src/main/java/llc/arma/ble/domain/model/Ble.kt b/app/src/main/java/llc/arma/ble/domain/model/Ble.kt
index 4c82b99..abd3912 100644
--- a/app/src/main/java/llc/arma/ble/domain/model/Ble.kt
+++ b/app/src/main/java/llc/arma/ble/domain/model/Ble.kt
@@ -13,21 +13,21 @@ sealed class Ble(
val accelerometerState: AccelerometerState
): Ble(info) {
- sealed class History {
+ sealed class HistorySettings {
data class Enabled(
val scale: AccelScale,
val mode: AccelViewMode,
val detailed: Boolean
- ) : History()
+ ) : HistorySettings()
- object Disabled : History()
+ object Disabled : HistorySettings()
}
data class WriteRequest(
val tx: BleState.TX?,
- val saveHistory: History?,
+ val saveHistorySettings: HistorySettings?,
val historyInterval: Long?
)
@@ -38,7 +38,12 @@ sealed class Ble(
val value: Float
) : HistoryPoint()
- class Accelerate (
+ class Rotation (
+ val date: Long,
+ val value: Long
+ ) : HistoryPoint()
+
+ class Acceleration (
val date: Long,
val x: Float,
val y: Float,
@@ -54,13 +59,39 @@ sealed class Ble(
}
- class MeasurePoint (
+ sealed class RealtimePoint {
+
+ data class Rotation(
+ val angle: Float,
+ val tmp: Float,
+ val turnovers: Int,
+ ) : RealtimePoint()
+
+ data class Common(
+ val x: Float,
+ val y: Float,
+ val z: Float,
+ ) : RealtimePoint()
+
+ data class Angle(
+ val x: Float,
+ val y: Float,
+ val z: Float,
+ ) : RealtimePoint()
+
+ data class Vibration(
+ val value: Float
+ ) : RealtimePoint()
+
+ }
+
+ class SpectrePoint (
val frequency: Long,
val value: Float
)
data class AccelerometerState(
- val saveHistory: History,
+ val saveHistorySettings: HistorySettings,
val historyInterval: Long
)
@@ -83,7 +114,7 @@ sealed class Ble(
val thermometerState: ThermometerState
) : Ble(info) {
- class MeasurePoint(
+ class HistoryPoint(
val date: Long,
val value: Float
)
@@ -107,7 +138,9 @@ sealed class Ble(
){
enum class TX {
- MINUS_40, MINUS_20, MINUS_16, MINUS_12, MINUS_8, MINUS_4, ZERO, PLUS_3, PLUS_4
+ MINUS_40, MINUS_20, MINUS_16, MINUS_12, MINUS_8, MINUS_4, ZERO, PLUS_3, PLUS_4;
+
+ companion object
}
}
diff --git a/app/src/main/java/llc/arma/ble/domain/repository/BleRepository.kt b/app/src/main/java/llc/arma/ble/domain/repository/BleRepository.kt
index cdac918..9c3c3dd 100644
--- a/app/src/main/java/llc/arma/ble/domain/repository/BleRepository.kt
+++ b/app/src/main/java/llc/arma/ble/domain/repository/BleRepository.kt
@@ -9,20 +9,17 @@ import llc.arma.ble.domain.model.BleInfo
import llc.arma.ble.domain.model.ConnectedBleInfo
import llc.arma.ble.domain.usecase.AccelScale
import llc.arma.ble.domain.usecase.AccelViewMode
-import llc.arma.ble.domain.usecase.MeasureData
import llc.arma.ble.domain.usecase.FftAxis
import llc.arma.ble.domain.usecase.FftFrequency
import llc.arma.ble.domain.usecase.FftViewMode
interface BleRepository {
- fun getConnectedBle(): List
-
- fun getBleAroundFlow(): Flow, BleException>>
+ fun getBleAroundFlow(): Result>, BleException>
suspend fun getBleBySerial(serial: String) : Result, BleException>
- suspend fun getTemperatureHistoryBySerial(serial: String): Flow>, BleException>>
+ suspend fun getTemperatureHistoryBySerial(serial: String): Flow>, BleException>>
suspend fun writeBle(serial: String, request: Ble.Thermometer.WriteRequest): Result
@@ -39,7 +36,7 @@ interface BleRepository {
fftAxis: FftAxis,
fftMode: FftViewMode,
frequency: FftFrequency
- ): Flow>
+ ): Flow>
suspend fun getAccelerometerSpectreBySerial(
serial: String,
@@ -48,7 +45,7 @@ interface BleRepository {
fftAxis: FftAxis,
fftMode: FftViewMode,
frequency: FftFrequency
- ): Flow>, BleException>>
+ ): Flow>, BleException>>
suspend fun getAccelerometerHistoryBySerial(serial: String): Flow>, BleException>>
diff --git a/app/src/main/java/llc/arma/ble/domain/repository/XlsxRepository.kt b/app/src/main/java/llc/arma/ble/domain/repository/XlsxRepository.kt
index e839aab..5a148d7 100644
--- a/app/src/main/java/llc/arma/ble/domain/repository/XlsxRepository.kt
+++ b/app/src/main/java/llc/arma/ble/domain/repository/XlsxRepository.kt
@@ -1,7 +1,6 @@
package llc.arma.ble.domain.repository
import llc.arma.ble.domain.model.Ble
-import llc.arma.ble.domain.usecase.MeasureData
import java.io.File
interface XlsxRepository {
diff --git a/app/src/main/java/llc/arma/ble/domain/usecase/GetAccelerometerMeasureBySerialFlow.kt b/app/src/main/java/llc/arma/ble/domain/usecase/GetAccelerometerMeasureBySerialFlow.kt
index c80f6c4..4352389 100644
--- a/app/src/main/java/llc/arma/ble/domain/usecase/GetAccelerometerMeasureBySerialFlow.kt
+++ b/app/src/main/java/llc/arma/ble/domain/usecase/GetAccelerometerMeasureBySerialFlow.kt
@@ -3,6 +3,7 @@ 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.model.Ble
import llc.arma.ble.domain.repository.BleRepository
import javax.inject.Inject
@@ -17,7 +18,7 @@ class GetAccelerometerMeasureBySerialFlow @Inject constructor(
fftAxis: FftAxis,
fftMode: FftViewMode,
frequency: FftFrequency
- ): Flow> {
+ ): Flow> {
return bleRepository.getAccelerometerMeasureBySerialFlow(serial, accelScale, accelMode, fftAxis, fftMode, frequency)
@@ -26,38 +27,15 @@ class GetAccelerometerMeasureBySerialFlow @Inject constructor(
}
enum class AccelViewMode {
- ACCELERATION, PEAK_ACCELERATION, RMS, VIBRATION, ANGLE, ROTATIONS
+ ACCELERATION, PEAK_ACCELERATION, RMS, VIBRATION, ANGLE, ROTATIONS;
+
+ companion object
}
enum class AccelScale(val k: Int) {
- S_2(2_000), S_4(4_000), S_8(8_000), S_16(16_000)
-}
-sealed class MeasureData {
+ S_2(2_000), S_4(4_000), S_8(8_000), S_16(16_000);
- data class Angle(
- val xAngle: Float,
- val yAngle: Float,
- val zAngle: Float,
- val xAccelerate: Float,
- val yAccelerate: Float,
- val zAccelerate: Float,
- ) : MeasureData()
+ companion object
- data class Accelerate(
- val x: Float,
- val y: Float,
- val z: Float,
- ) : MeasureData()
-
- data class Vibration(
- val value: Float
- ) : MeasureData()
-
-}
-
-data class Accelerate(
- val x: Float,
- val y: Float,
- val z: Float,
-)
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/app/src/main/java/llc/arma/ble/domain/usecase/GetAccelerometerSpectreBySerial.kt b/app/src/main/java/llc/arma/ble/domain/usecase/GetAccelerometerSpectreBySerial.kt
index 5190ba2..d025cdc 100644
--- a/app/src/main/java/llc/arma/ble/domain/usecase/GetAccelerometerSpectreBySerial.kt
+++ b/app/src/main/java/llc/arma/ble/domain/usecase/GetAccelerometerSpectreBySerial.kt
@@ -19,7 +19,7 @@ class GetAccelerometerSpectreBySerial @Inject constructor(
fftAxis: FftAxis,
fftMode: FftViewMode,
frequency: FftFrequency
- ): Flow>, BleException>> {
+ ): Flow>, BleException>> {
return bleRepository.getAccelerometerSpectreBySerial(serial, accelScale, accelMode, fftAxis, fftMode, frequency)
@@ -28,13 +28,19 @@ class GetAccelerometerSpectreBySerial @Inject constructor(
}
enum class FftFrequency {
- OFF, F_1, F_10, F_25, F_50, F_100, F_200, F_400, F_1620, F_1344
+ OFF, F_1, F_10, F_25, F_50, F_100, F_200, F_400, F_1620, F_1344;
+
+ companion object
}
enum class FftViewMode {
- SPECTRE, X, Y, Z
+ SPECTRE, X, Y, Z;
+
+ companion object
}
enum class FftAxis {
- AUTO, X, Y, Z
+ AUTO, X, Y, Z;
+
+ companion object
}
\ No newline at end of file
diff --git a/app/src/main/java/llc/arma/ble/domain/usecase/GetBleAroundFlow.kt b/app/src/main/java/llc/arma/ble/domain/usecase/GetBleAroundFlow.kt
index a594369..60e9a32 100644
--- a/app/src/main/java/llc/arma/ble/domain/usecase/GetBleAroundFlow.kt
+++ b/app/src/main/java/llc/arma/ble/domain/usecase/GetBleAroundFlow.kt
@@ -12,6 +12,6 @@ class GetBleAroundFlow @Inject constructor(
private val bleRepository: BleRepository
) {
- operator fun invoke(): Flow, BleException>> = bleRepository.getBleAroundFlow()
+ operator fun invoke(): Result>, BleException> = bleRepository.getBleAroundFlow()
}
\ No newline at end of file
diff --git a/app/src/main/java/llc/arma/ble/domain/usecase/GetConnectedBleDevices.kt b/app/src/main/java/llc/arma/ble/domain/usecase/GetConnectedBleDevices.kt
deleted file mode 100644
index d331a54..0000000
--- a/app/src/main/java/llc/arma/ble/domain/usecase/GetConnectedBleDevices.kt
+++ /dev/null
@@ -1,15 +0,0 @@
-package llc.arma.ble.domain.usecase
-
-import llc.arma.ble.domain.model.ConnectedBleInfo
-import llc.arma.ble.domain.repository.BleRepository
-import javax.inject.Inject
-
-class GetConnectedBleDevices @Inject constructor(
- private val bleRepository: BleRepository
-) {
-
- operator fun invoke(): List{
- return bleRepository.getConnectedBle()
- }
-
-}
\ No newline at end of file
diff --git a/app/src/main/java/llc/arma/ble/domain/usecase/GetTemperatureHistoryBySerial.kt b/app/src/main/java/llc/arma/ble/domain/usecase/GetTemperatureHistoryBySerial.kt
index 8979043..1230181 100644
--- a/app/src/main/java/llc/arma/ble/domain/usecase/GetTemperatureHistoryBySerial.kt
+++ b/app/src/main/java/llc/arma/ble/domain/usecase/GetTemperatureHistoryBySerial.kt
@@ -12,7 +12,7 @@ class GetTemperatureHistoryBySerial @Inject constructor(
private val bleRepository: BleRepository
) {
- suspend operator fun invoke(serial: String): Flow>, BleException>> {
+ suspend operator fun invoke(serial: String): Flow>, BleException>> {
return bleRepository.getTemperatureHistoryBySerial(serial)