diff --git a/app/build.gradle b/app/build.gradle
index 62ab741..77d72f2 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -11,10 +11,10 @@ android {
defaultConfig {
applicationId "llc.arma.ble"
- minSdk 24
+ minSdk 26
targetSdk 33
- versionCode 9
- versionName "1.2.9"
+ versionCode 10
+ versionName "1.2.10"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
@@ -87,4 +87,6 @@ dependencies {
implementation "com.patrykandpatrick.vico:compose:1.7.1"
implementation "com.patrykandpatrick.vico:compose-m3:1.7.1"
+ implementation files('libs/poishadow-all.jar')
+
}
\ No newline at end of file
diff --git a/app/libs/poishadow-all.jar b/app/libs/poishadow-all.jar
new file mode 100644
index 0000000..177eba8
Binary files /dev/null and b/app/libs/poishadow-all.jar differ
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 8d50d78..2469251 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -29,6 +29,18 @@
tools:targetApi="31"
android:name=".app.framework.App">
+
+
+
+
+
+
() {
init {
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 16e13ea..7de1d1c 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
@@ -226,6 +226,7 @@ fun Display(
producer.setEntries(
data.mapIndexed { index, measurePoint ->
AccelerometerEntry(measurePoint.frequency, index.toFloat(), measurePoint.value)
+
}
)
}
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 ad72a1e..e05195c 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
@@ -345,12 +345,11 @@ fun Display(
}
-
}
}
@Composable
-private fun Angle(
+public fun Angle(
modifier: Modifier = Modifier,
angle: Float
) {
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 220af9f..a31c832 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
@@ -23,6 +23,7 @@ import llc.arma.ble.app.ui.common.ViewState
import llc.arma.ble.domain.model.BleInfo
import javax.inject.Inject
import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.rounded.CloudUpload
import androidx.compose.material.icons.rounded.Refresh
import androidx.compose.ui.graphics.StrokeCap
import androidx.compose.ui.text.style.TextAlign
@@ -31,6 +32,8 @@ import com.patrykandpatrick.vico.compose.chart.line.lineChart
import com.patrykandpatrick.vico.compose.chart.scroll.rememberChartScrollSpec
import com.patrykandpatrick.vico.core.axis.AxisPosition
import com.patrykandpatrick.vico.core.axis.formatter.AxisValueFormatter
+import com.patrykandpatrick.vico.core.chart.decoration.ThresholdLine
+import com.patrykandpatrick.vico.core.chart.scale.AutoScaleUp
import com.patrykandpatrick.vico.core.entry.ChartEntry
import com.patrykandpatrick.vico.core.entry.FloatEntry
import com.patrykandpatrick.vico.core.scroll.AutoScrollCondition
@@ -43,10 +46,12 @@ import llc.arma.ble.domain.common.ProgressState
import llc.arma.ble.domain.model.Ble
import llc.arma.ble.domain.usecase.AccelScale
import llc.arma.ble.domain.usecase.AccelViewMode
+import llc.arma.ble.domain.usecase.ExportToXlsx
import llc.arma.ble.domain.usecase.FftAxis
import llc.arma.ble.domain.usecase.FftFrequency
import llc.arma.ble.domain.usecase.FftViewMode
import llc.arma.ble.domain.usecase.GetAccelerometerHistoryBySerial
+import llc.arma.ble.domain.usecase.MeasureData
import java.util.Date
class AccelEntry(
@@ -108,6 +113,21 @@ fun AccelerometerHistory(
style = MaterialTheme.typography.titleLarge
)
+ IconButton(
+ onClick = {
+ viewModel.setEvent(AccelerometerHistoryContract.Event.OnExport)
+ },
+ enabled = when(state){
+ is AccelerometerHistoryContract.State.Display -> state.loadingHistoryState is ProgressState.Finished
+ AccelerometerHistoryContract.State.Exception -> false
+ }
+ ) {
+ Icon(
+ imageVector = Icons.Rounded.CloudUpload,
+ contentDescription = null
+ )
+ }
+
IconButton(
onClick = {
viewModel.setEvent(AccelerometerHistoryContract.Event.OnRefreshHistory(ble.serial, accelScale, accelMode, fftAxis, fftMode, frequency))
@@ -164,14 +184,6 @@ fun Display(
} else {
- val producer = remember {
- ChartEntryModelProducer(listOf())
- }
-
- producer.setEntries(state.loadingHistoryState.data.mapIndexed { index, measurePoint ->
- AccelEntry(measurePoint.frequency, index.toFloat(), measurePoint.value )
- })
-
val axisValueFormatter =
AxisValueFormatter { value, chartValues ->
(chartValues.chartEntryModel.entries.firstOrNull()
@@ -181,25 +193,174 @@ fun Display(
.orEmpty()
}
- val lineChart = lineChart()
+ val xProducer = remember {
+ ChartEntryModelProducer(listOf())
+ }
- Chart(
- chart = lineChart,
- chartModelProducer = producer,
- startAxis = startAxis(),
- bottomAxis = bottomAxis(
- tickLength = 0.dp,
- valueFormatter = axisValueFormatter,
- labelRotationDegrees = -90f,
- ),
- modifier = Modifier.fillMaxSize(),
- chartScrollSpec = rememberChartScrollSpec(
- initialScroll = InitialScroll.End,
- autoScrollCondition = AutoScrollCondition.OnModelSizeIncreased,
- autoScrollAnimationSpec = tween(0)
+ val yProducer = remember {
+ ChartEntryModelProducer(listOf())
+ }
+
+ val zProducer = remember {
+ ChartEntryModelProducer(listOf())
+ }
+
+ xProducer.setEntries(state.loadingHistoryState.data.mapIndexed { index, measurePoint ->
+ when(measurePoint){
+ is Ble.Accelerometer.HistoryPoint.Accelerate -> {
+ AccelEntry(measurePoint.date, index.toFloat(), measurePoint.x )
+ }
+ is Ble.Accelerometer.HistoryPoint.Vibration -> {
+ AccelEntry(measurePoint.date, index.toFloat(), measurePoint.value)
+ }
+ is Ble.Accelerometer.HistoryPoint.Angle -> {
+ AccelEntry(measurePoint.date, index.toFloat(), measurePoint.x )
+ }
+ }
+ })
+
+ yProducer.setEntries(state.loadingHistoryState.data.mapIndexed { index, measurePoint ->
+ when(measurePoint){
+ is Ble.Accelerometer.HistoryPoint.Accelerate -> {
+ AccelEntry(measurePoint.date, index.toFloat(), measurePoint.y )
+ }
+ is Ble.Accelerometer.HistoryPoint.Vibration -> {
+ AccelEntry(measurePoint.date, index.toFloat(), measurePoint.value)
+ }
+ is Ble.Accelerometer.HistoryPoint.Angle -> {
+ AccelEntry(measurePoint.date, index.toFloat(), measurePoint.y )
+ }
+ }
+ })
+
+ zProducer.setEntries(state.loadingHistoryState.data.mapIndexed { index, measurePoint ->
+ when(measurePoint){
+ is Ble.Accelerometer.HistoryPoint.Accelerate -> {
+ AccelEntry(measurePoint.date, index.toFloat(), measurePoint.z )
+ }
+ is Ble.Accelerometer.HistoryPoint.Vibration -> {
+ AccelEntry(measurePoint.date, index.toFloat(), measurePoint.value)
+ }
+ is Ble.Accelerometer.HistoryPoint.Angle -> {
+ AccelEntry(measurePoint.date, index.toFloat(), measurePoint.z )
+ }
+ }
+ })
+
+ val lineChart = lineChart(
+ decorations = listOf(
+ ThresholdLine(
+ thresholdValue = 0f
+ )
)
)
+ val lastMeasure = state.loadingHistoryState.data.lastOrNull()
+
+ if((lastMeasure is Ble.Accelerometer.HistoryPoint.Vibration).not()) {
+
+ Column() {
+
+ Text(text = "Ось X:")
+
+ 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)
+ )
+ )
+
+ Text(text = "Ось Y:")
+ Chart(
+ chart = lineChart,
+ chartModelProducer = yProducer,
+ 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)
+ )
+ )
+
+ Text(text = "Ось Z:")
+ Chart(
+ chart = lineChart,
+ chartModelProducer = zProducer,
+ 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)
+ )
+ )
+
+ }
+
+ } 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)
+ )
+ )
+
+ }
+
+ }
+
}
}
@@ -261,6 +422,8 @@ class AccelerometerHistoryContract {
object StopMeasure : Event()
+ object OnExport : Event()
+
data class OnStart(
val serial: String,
val accelScale: AccelScale,
@@ -284,7 +447,7 @@ class AccelerometerHistoryContract {
sealed class State : ViewState {
data class Display(
- val loadingHistoryState : ProgressState>
+ val loadingHistoryState : ProgressState>
) : State()
object Exception : State()
@@ -302,6 +465,7 @@ class AccelerometerHistoryContract {
@HiltViewModel
class AccelerometerHistoryViewModel @Inject constructor(
private val getAccelerometerHistoryBySerial: GetAccelerometerHistoryBySerial,
+ private val exportToXlsx: ExportToXlsx
) : BaseViewModel() {
var measureJob: Job? = null
@@ -317,15 +481,28 @@ class AccelerometerHistoryViewModel @Inject constructor(
is AccelerometerHistoryContract.Event.OnStart -> reduce(viewState.value, event)
is AccelerometerHistoryContract.Event.OnRefreshHistory -> reduce(viewState.value, event)
is AccelerometerHistoryContract.Event.StopMeasure -> reduce(viewState.value, event)
+ is AccelerometerHistoryContract.Event.OnExport -> reduce(viewState.value, event)
}
}
+ private fun reduce(
+ state: AccelerometerHistoryContract.State,
+ event: AccelerometerHistoryContract.Event.OnExport
+ ) {
+
+ if(state is AccelerometerHistoryContract.State.Display){
+ if(state.loadingHistoryState is ProgressState.Finished){
+ exportToXlsx.invoke(state.loadingHistoryState.data)
+ }
+ }
+
+ }
+
private fun reduce(
state: AccelerometerHistoryContract.State,
event: AccelerometerHistoryContract.Event.StopMeasure
) {
-
measureJob?.cancel()
measureJob = null
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 6d76677..e58a4c8 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
@@ -22,7 +22,7 @@ fun IntervalEdit(
){
var value by remember(state.accelerometerState.historyInterval) {
- mutableStateOf((state.accelerometerState.historyInterval / 1000 / 60 / 60).toInt())
+ mutableIntStateOf((state.accelerometerState.historyInterval).toInt())
}
val maxInterval = 10 * 24 * 60 * 60 * 1000
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 9687ee1..c8f88bd 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
@@ -142,13 +142,17 @@ fun Write(
modifier = Modifier.weight(1f)
) {
+ val hours = it / 1000 / 60 / 60
+ val minutes = (it - ( hours * 1000 * 60 * 60 )) / 1000 / 60
+
Text(
- text = "Интервал измерний"
+ text = "Интервал измерений"
)
+
Text(
color = MaterialTheme.colorScheme.secondary,
style = MaterialTheme.typography.bodyMedium,
- text = "${it / 1000 / 60 / 60} ч."
+ text = "$hours ч. $minutes мин."
)
}
diff --git a/app/src/main/java/llc/arma/ble/app/ui/screen/inspection/thermometer/view/Write.kt b/app/src/main/java/llc/arma/ble/app/ui/screen/inspection/thermometer/view/Write.kt
index 9f87084..fd506bf 100644
--- a/app/src/main/java/llc/arma/ble/app/ui/screen/inspection/thermometer/view/Write.kt
+++ b/app/src/main/java/llc/arma/ble/app/ui/screen/inspection/thermometer/view/Write.kt
@@ -137,13 +137,17 @@ fun Write(
modifier = Modifier.weight(1f)
) {
+ val hours = it / 1000 / 60 / 60
+ val minutes = (it - ( hours * 1000 * 60 * 60 )) / 1000 / 60
+
Text(
- text = "Интервал измерний"
+ text = "Интервал измерений"
)
+
Text(
color = MaterialTheme.colorScheme.secondary,
style = MaterialTheme.typography.bodyMedium,
- text = "${it / 1000 / 60 / 60} ч."
+ text = "$hours ч. $minutes мин."
)
}
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 dd2ce87..ffafb68 100644
--- a/app/src/main/java/llc/arma/ble/data/BleRepositoryImpl.kt
+++ b/app/src/main/java/llc/arma/ble/data/BleRepositoryImpl.kt
@@ -542,7 +542,6 @@ class BleRepositoryImpl @Inject constructor(
serviceId = serviceUUID,
characteristicId = accelerometerReadUUID,
).fold(
-
onSuccess = {
Log.d("history", it.joinToString { it.toString() })
val scale = when(it[1].toInt()){
@@ -559,6 +558,7 @@ class BleRepositoryImpl @Inject constructor(
1 -> AccelViewMode.PEAK_ACCELERATION
2 -> AccelViewMode.RMS
3 -> AccelViewMode.VIBRATION
+ 4 -> AccelViewMode.ANGLE
else -> {
return Result.failure(BleException.UnexpectedResponse)
}
@@ -572,7 +572,6 @@ class BleRepositoryImpl @Inject constructor(
onFailure = {
return Result.failure(BleException.UnexpectedResponse)
}
-
)
}
false -> Ble.Accelerometer.History.Disabled
@@ -738,17 +737,31 @@ class BleRepositoryImpl @Inject constructor(
override suspend fun getAccelerometerHistoryBySerial(
serial: String
- ): Flow>, BleException>> {
+ ): Flow>, BleException>> {
var gatt: BluetoothGatt? = null
return callbackFlow {
- deviceCache[serial]?.device?.let { device ->
+ deviceCache[serial]?.let { result ->
+
+ val device = result.device
if (checkPermission()) {
- val scale = writeCharacteristic(
+ val state = readAccelState(result).fold(
+ onSuccess = {
+
+ },
+ onFailure = {
+ null
+ }
+ )
+
+ var scale: AccelScale? = null
+ var mode: AccelViewMode? = null
+
+ writeCharacteristic(
device = device,
serviceId = serviceUUID,
characteristicId = accelerometerReadUUID,
@@ -761,13 +774,21 @@ class BleRepositoryImpl @Inject constructor(
characteristicId = accelerometerReadUUID,
).fold(
onSuccess = {
- when(it[1].toInt()){
+ scale = when(it[1].toInt()){
0 -> AccelScale.S_2
1 -> AccelScale.S_4
2 -> AccelScale.S_8
3 -> AccelScale.S_16
else -> null
}
+ mode = when(it[0].toInt()){
+ 0 -> AccelViewMode.ACCELERATION
+ 1 -> AccelViewMode.PEAK_ACCELERATION
+ 2 -> AccelViewMode.RMS
+ 3 -> AccelViewMode.VIBRATION
+ 4 -> AccelViewMode.ANGLE
+ else -> null
+ }
},
onFailure = { null }
)
@@ -777,12 +798,12 @@ class BleRepositoryImpl @Inject constructor(
}
)
- if(scale != null) {
+ if(scale != null && mode != null) {
gatt = device.connectGatt(
app,
false,
- ReadAccelerometerHistoryCallback(scale, app) {
+ ReadAccelerometerHistoryCallback(mode!!, scale!!, app) {
CoroutineScope(Dispatchers.IO).launch {
send(it)
}
diff --git a/app/src/main/java/llc/arma/ble/data/EmailRepositoryImpl.kt b/app/src/main/java/llc/arma/ble/data/EmailRepositoryImpl.kt
new file mode 100644
index 0000000..fab9f76
--- /dev/null
+++ b/app/src/main/java/llc/arma/ble/data/EmailRepositoryImpl.kt
@@ -0,0 +1,41 @@
+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(
+ private val application: Application
+) : EmailRepository {
+
+ override fun sendFile(file: File) {
+ val uri = FileProvider.getUriForFile(application, "llc.arma.ble.fileprovider", file)
+
+ val sendIntent = Intent(Intent.ACTION_SEND)
+ sendIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
+ sendIntent.type = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
+ sendIntent.putExtra(Intent.EXTRA_SUBJECT, "Measure history")
+ sendIntent.putExtra(Intent.EXTRA_STREAM, uri)
+ application.startActivity(
+ Intent.createChooser(sendIntent, "Send email...").apply {
+ flags = Intent.FLAG_ACTIVITY_NEW_TASK
+ }
+ )
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/llc/arma/ble/data/ReadAccelerometerCallback.kt b/app/src/main/java/llc/arma/ble/data/ReadAccelerometerCallback.kt
index 8d0b5e4..6b2420b 100644
--- a/app/src/main/java/llc/arma/ble/data/ReadAccelerometerCallback.kt
+++ b/app/src/main/java/llc/arma/ble/data/ReadAccelerometerCallback.kt
@@ -261,7 +261,7 @@ fun calculateAngle(
}
-fun calculateZAngle(
+public fun calculateZAngle(
x: Float,
y: Float
): Float {
diff --git a/app/src/main/java/llc/arma/ble/data/ReadAccelerometerHistoryCallback.kt b/app/src/main/java/llc/arma/ble/data/ReadAccelerometerHistoryCallback.kt
index cde8cf4..dca14e3 100644
--- a/app/src/main/java/llc/arma/ble/data/ReadAccelerometerHistoryCallback.kt
+++ b/app/src/main/java/llc/arma/ble/data/ReadAccelerometerHistoryCallback.kt
@@ -14,11 +14,13 @@ 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
class ReadAccelerometerHistoryCallback(
+ private val mode: AccelViewMode,
private val scale: AccelScale,
private val app: Application,
- private val onResult: (Result>, BleException>) -> Unit
+ private val onResult: (Result>, BleException>) -> Unit
) : BluetoothGattCallback() {
enum class Property {
@@ -218,11 +220,37 @@ class ReadAccelerometerHistoryCallback(
onResult(
Result.success(
ProgressState.Finished(
- resultTemperaturePackage.withIndex().map {
- Ble.Accelerometer.MeasurePoint(
- frequency = lastMeasureSystemTime!! - (((resultTemperaturePackage.size - 1) - it.index) * bleMeasureInterval!!),
- value = (it.value * scale.k) / Short.MAX_VALUE
- )
+ when(mode){
+ AccelViewMode.ACCELERATION,
+ AccelViewMode.PEAK_ACCELERATION,
+ AccelViewMode.RMS -> {
+ resultTemperaturePackage.chunked(3).withIndex().map {
+ Ble.Accelerometer.HistoryPoint.Angle(
+ date = lastMeasureSystemTime!! - (((resultTemperaturePackage.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
+ )
+ }
+ }
+ AccelViewMode.ANGLE -> {
+ resultTemperaturePackage.chunked(3).withIndex().map {
+ Ble.Accelerometer.HistoryPoint.Angle(
+ date = lastMeasureSystemTime!! - (((resultTemperaturePackage.size - 1) - it.index) * bleMeasureInterval!!),
+ x = calculateZAngle(it.value[2], it.value[1]) * 180f / Math.PI.toFloat(),
+ y = calculateZAngle(it.value[2], it.value[0]) * 180f / Math.PI.toFloat(),
+ z = calculateZAngle(it.value[0], it.value[1]) * 180f / Math.PI.toFloat()
+ )
+ }
+ }
+ AccelViewMode.VIBRATION -> {
+ resultTemperaturePackage.withIndex().map {
+ Ble.Accelerometer.HistoryPoint.Vibration(
+ date = lastMeasureSystemTime!! - (((resultTemperaturePackage.size - 1) - it.index) * bleMeasureInterval!!),
+ value = (it.value * scale.k) / Short.MAX_VALUE
+ )
+ }
+ }
}
)
)
@@ -261,11 +289,37 @@ class ReadAccelerometerHistoryCallback(
onResult(
Result.success(
ProgressState.Finished(
- resultTemperaturePackage.withIndex().map {
- Ble.Accelerometer.MeasurePoint(
- frequency = lastMeasureSystemTime!! - (((resultTemperaturePackage.size - 1) - it.index) * bleMeasureInterval!!),
- value = (it.value * scale.k) / Short.MAX_VALUE
- )
+ when(mode){
+ AccelViewMode.ACCELERATION,
+ AccelViewMode.PEAK_ACCELERATION,
+ AccelViewMode.RMS -> {
+ resultTemperaturePackage.chunked(3).withIndex().map {
+ Ble.Accelerometer.HistoryPoint.Angle(
+ date = lastMeasureSystemTime!! - (((resultTemperaturePackage.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
+ )
+ }
+ }
+ AccelViewMode.ANGLE -> {
+ resultTemperaturePackage.chunked(3).withIndex().map {
+ Ble.Accelerometer.HistoryPoint.Angle(
+ date = lastMeasureSystemTime!! - (((resultTemperaturePackage.size - 1) - it.index) * bleMeasureInterval!!),
+ x = calculateZAngle(it.value[2], it.value[1]) * 180f / Math.PI.toFloat(),
+ y = calculateZAngle(it.value[2], it.value[0]) * 180f / Math.PI.toFloat(),
+ z = calculateZAngle(it.value[0], it.value[1]) * 180f / Math.PI.toFloat()
+ )
+ }
+ }
+ AccelViewMode.VIBRATION -> {
+ resultTemperaturePackage.withIndex().map {
+ Ble.Accelerometer.HistoryPoint.Vibration(
+ date = lastMeasureSystemTime!! - (((resultTemperaturePackage.size - 1) - it.index) * bleMeasureInterval!!),
+ value = (it.value * scale.k) / Short.MAX_VALUE
+ )
+ }
+ }
}
)
)
diff --git a/app/src/main/java/llc/arma/ble/data/WriteAccelerometerCallback.kt b/app/src/main/java/llc/arma/ble/data/WriteAccelerometerCallback.kt
index 69815af..83253e0 100644
--- a/app/src/main/java/llc/arma/ble/data/WriteAccelerometerCallback.kt
+++ b/app/src/main/java/llc/arma/ble/data/WriteAccelerometerCallback.kt
@@ -64,36 +64,33 @@ class WriteAccelerometerCallback(
status: Int
){
- if(request.tx != null || request.saveHistory != null) {
+ Log.d("write", "${request.tx != null} ${request.saveHistory != null} ${request.historyInterval != null}")
+
+ if(request.tx != null || request.saveHistory != null || request.historyInterval != null) {
fun UInt.to4ByteArrayInLittleEndian(): ByteArray =
(3 downTo 0).map {
(this shr (it * Byte.SIZE_BITS)).toByte()
}.toByteArray()
- var uuid: Pair? = null
+ var uuid: Triple? = null
uuid = request.historyInterval?.let {
- this.request = request.copy(
- historyInterval = null
- )
-
- Pair(
+ Triple(
intervalWriteUUID,
mutableListOf(3).apply {
addAll((it).toUInt().to4ByteArrayInLittleEndian().reversed().toList())
- }.toByteArray()
+ }.toByteArray(),
+ request.copy(
+ historyInterval = null
+ )
)
}
uuid = request.saveHistory?.let {
- this.request = request.copy(
- saveHistory = null
- )
-
- Pair(
+ Triple(
saveEnabledWriteUUID,
mutableListOf(4).apply {
add(if (it is Ble.Accelerometer.History.Enabled) 1 else 0)
@@ -101,17 +98,16 @@ class WriteAccelerometerCallback(
add(it.mode.sendData)
add(it.scale.sendData)
}
- }.toByteArray()
+ }.toByteArray(),
+ request.copy(
+ saveHistory = null
+ )
)
} ?: uuid
uuid = request.tx?.let {
- this.request = request.copy(
- tx = null
- )
-
- Pair(
+ Triple(
txWriteUUID,
byteArrayOf(
when (it) {
@@ -125,6 +121,9 @@ class WriteAccelerometerCallback(
Ble.BleState.TX.PLUS_3 -> 3
Ble.BleState.TX.PLUS_4 -> 4
}
+ ),
+ request.copy(
+ tx = null
)
)
@@ -138,6 +137,8 @@ class WriteAccelerometerCallback(
gatt.writeCharacteristic(it, uuid.second)
+ request = uuid.third
+
return
}
diff --git a/app/src/main/java/llc/arma/ble/data/WriteThermometerCallback.kt b/app/src/main/java/llc/arma/ble/data/WriteThermometerCallback.kt
index 833d6b3..a9fe747 100644
--- a/app/src/main/java/llc/arma/ble/data/WriteThermometerCallback.kt
+++ b/app/src/main/java/llc/arma/ble/data/WriteThermometerCallback.kt
@@ -75,43 +75,37 @@ class WriteThermometerCallback(
(this shr (it * Byte.SIZE_BITS)).toByte()
}.toByteArray()
- var uuid: Pair? = null
+ var uuid: Triple? = null
uuid = request.historyInterval?.let {
- this.request = request.copy(
- historyInterval = null
- )
-
- Pair(
+ Triple(
intervalWriteUUID,
mutableListOf(3).apply {
addAll((it).toUInt().to4ByteArrayInLittleEndian().reversed().toList())
- }.toByteArray()
+ }.toByteArray(),
+ request.copy(
+ historyInterval = null
+ )
)
}
uuid = request.saveHistory?.let {
- this.request = request.copy(
- saveHistory = null
- )
-
- Pair(
+ Triple(
saveEnabledWriteUUID,
mutableListOf(4).apply {
add(if (it) 1 else 0)
- }.toByteArray()
+ }.toByteArray(),
+ request.copy(
+ saveHistory = null
+ )
)
} ?: uuid
uuid = request.tx?.let {
- this.request = request.copy(
- tx = null
- )
-
- Pair(
+ Triple(
txWriteUUID,
byteArrayOf(
when (it) {
@@ -125,6 +119,9 @@ class WriteThermometerCallback(
Ble.BleState.TX.PLUS_3 -> 3
Ble.BleState.TX.PLUS_4 -> 4
}
+ ),
+ request.copy(
+ tx = null
)
)
@@ -137,7 +134,7 @@ class WriteThermometerCallback(
}?.let {
gatt.writeCharacteristic(it, uuid.second)
-
+ request = uuid.third
return
}
diff --git a/app/src/main/java/llc/arma/ble/data/XlsxRepositoryImpl.kt b/app/src/main/java/llc/arma/ble/data/XlsxRepositoryImpl.kt
new file mode 100644
index 0000000..298c706
--- /dev/null
+++ b/app/src/main/java/llc/arma/ble/data/XlsxRepositoryImpl.kt
@@ -0,0 +1,88 @@
+package llc.arma.ble.data
+
+import android.app.Application
+import android.icu.text.SimpleDateFormat
+import llc.arma.ble.R
+import llc.arma.ble.domain.model.Ble
+import llc.arma.ble.domain.repository.XlsxRepository
+import org.apache.poi.ss.usermodel.WorkbookFactory
+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.Date
+import java.util.UUID
+import javax.inject.Inject
+
+class XlsxRepositoryImpl @Inject constructor(
+ private val application: Application
+) : XlsxRepository {
+
+
+
+ override fun exportToXls(data: List): File {
+
+ val formatter = SimpleDateFormat("dd.MM.yyyy HH:mm")
+
+ val file = File(application.filesDir, "${UUID.randomUUID()}.xlsx")
+ file.createNewFile()
+ when(data.firstOrNull()){
+ is Ble.Accelerometer.HistoryPoint.Vibration -> {
+ IOUtils.copy(application.resources.openRawResource(R.raw.measure_single_axis), FileOutputStream(file))
+ }
+ else -> {
+ IOUtils.copy(application.resources.openRawResource(R.raw.measure_multiple_axis), FileOutputStream(file))
+ }
+ }
+
+
+ val fileIn = FileInputStream(file)
+ val workbook = WorkbookFactory.create(fileIn)
+ val worksheet = workbook.getSheetAt(0) as XSSFSheet
+
+ data.withIndex().forEach {
+
+ val row = worksheet.createRow(it.index + 1)
+ val dateX = row.createCell(0)
+ val dateY = row.createCell(2)
+ val dateZ = row.createCell(4)
+ val x = row.createCell(1)
+ val y = row.createCell(3)
+ val z = row.createCell(5)
+
+ when(val value = it.value){
+ is Ble.Accelerometer.HistoryPoint.Angle -> {
+ dateX.setCellValue(formatter.format(Date(value.date)))
+ dateY.setCellValue(formatter.format(Date(value.date)))
+ dateZ.setCellValue(formatter.format(Date(value.date)))
+ x.setCellValue(value.x.toDouble())
+ y.setCellValue(value.y.toDouble())
+ z.setCellValue(value.z.toDouble())
+ }
+ is Ble.Accelerometer.HistoryPoint.Vibration -> {
+ dateX.setCellValue(formatter.format(Date(value.date)))
+ x.setCellValue(value.value.toDouble())
+ }
+
+ is Ble.Accelerometer.HistoryPoint.Accelerate -> {
+ dateX.setCellValue(formatter.format(Date(value.date)))
+ dateY.setCellValue(formatter.format(Date(value.date)))
+ dateZ.setCellValue(formatter.format(Date(value.date)))
+ x.setCellValue(value.x.toDouble())
+ y.setCellValue(value.y.toDouble())
+ z.setCellValue(value.z.toDouble())
+ }
+
+ }
+ }
+
+ fileIn.close()
+ val saveFos = FileOutputStream(file)
+ workbook.write(saveFos)
+ workbook.close()
+ saveFos.close()
+ return file
+ }
+
+}
\ No newline at end of file
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 5bced8e..4c82b99 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
@@ -31,18 +31,34 @@ sealed class Ble(
val historyInterval: Long?
)
+ sealed class HistoryPoint {
+
+ class Vibration (
+ val date: Long,
+ val value: Float
+ ) : HistoryPoint()
+
+ class Accelerate (
+ val date: Long,
+ val x: Float,
+ val y: Float,
+ val z: Float
+ ) : HistoryPoint()
+
+ class Angle (
+ val date: Long,
+ val x: Float,
+ val y: Float,
+ val z: Float
+ ) : HistoryPoint()
+
+ }
+
class MeasurePoint (
val frequency: Long,
val value: Float
)
- class HistoryPoint (
- val time: Long,
- val x: Float,
- val y: Float,
- val z: Float
- )
-
data class AccelerometerState(
val saveHistory: History,
val historyInterval: Long
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 550bd04..cdac918 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
@@ -50,6 +50,6 @@ interface BleRepository {
frequency: FftFrequency
): Flow>, BleException>>
- suspend fun getAccelerometerHistoryBySerial(serial: String): Flow>, BleException>>
+ suspend fun getAccelerometerHistoryBySerial(serial: String): Flow>, BleException>>
}
\ No newline at end of file
diff --git a/app/src/main/java/llc/arma/ble/domain/repository/EmailRepository.kt b/app/src/main/java/llc/arma/ble/domain/repository/EmailRepository.kt
new file mode 100644
index 0000000..fbb5170
--- /dev/null
+++ b/app/src/main/java/llc/arma/ble/domain/repository/EmailRepository.kt
@@ -0,0 +1,9 @@
+package llc.arma.ble.domain.repository
+
+import java.io.File
+
+interface EmailRepository {
+
+ fun sendFile(file: File)
+
+}
\ No newline at end of file
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
new file mode 100644
index 0000000..3d308b5
--- /dev/null
+++ b/app/src/main/java/llc/arma/ble/domain/repository/XlsxRepository.kt
@@ -0,0 +1,11 @@
+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 {
+
+ fun exportToXls(data: List): File
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/llc/arma/ble/domain/usecase/ExportToXlsx.kt b/app/src/main/java/llc/arma/ble/domain/usecase/ExportToXlsx.kt
new file mode 100644
index 0000000..1755a0d
--- /dev/null
+++ b/app/src/main/java/llc/arma/ble/domain/usecase/ExportToXlsx.kt
@@ -0,0 +1,34 @@
+package llc.arma.ble.domain.usecase
+
+import android.app.Application
+import llc.arma.ble.R
+import llc.arma.ble.domain.model.Ble
+import llc.arma.ble.domain.repository.EmailRepository
+import llc.arma.ble.domain.repository.XlsxRepository
+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.XSSFCell
+import org.apache.poi.xssf.usermodel.XSSFSheet
+import org.apache.poi.xssf.usermodel.XSSFTable
+import java.io.File
+import java.io.FileInputStream
+import java.io.FileOutputStream
+import java.util.UUID
+import javax.inject.Inject
+
+class ExportToXlsx @Inject constructor(
+ private val xlsxRepository: XlsxRepository,
+ private val emailRepository: EmailRepository
+) {
+
+ operator fun invoke(data: List){
+
+ val file = xlsxRepository.exportToXls(data)
+ emailRepository.sendFile(file)
+
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/llc/arma/ble/domain/usecase/GetAccelerometerHistoryBySerial.kt b/app/src/main/java/llc/arma/ble/domain/usecase/GetAccelerometerHistoryBySerial.kt
index e7496b2..a3b0f56 100644
--- a/app/src/main/java/llc/arma/ble/domain/usecase/GetAccelerometerHistoryBySerial.kt
+++ b/app/src/main/java/llc/arma/ble/domain/usecase/GetAccelerometerHistoryBySerial.kt
@@ -12,7 +12,7 @@ class GetAccelerometerHistoryBySerial @Inject constructor(
private val bleRepository: BleRepository
) {
- suspend operator fun invoke(serial: String): Flow>, BleException>> {
+ suspend operator fun invoke(serial: String): Flow>, BleException>> {
return bleRepository.getAccelerometerHistoryBySerial(serial)
diff --git a/app/src/main/res/raw/measure_multiple_axis.xlsx b/app/src/main/res/raw/measure_multiple_axis.xlsx
new file mode 100644
index 0000000..198220a
Binary files /dev/null and b/app/src/main/res/raw/measure_multiple_axis.xlsx differ
diff --git a/app/src/main/res/raw/measure_single_axis.xlsx b/app/src/main/res/raw/measure_single_axis.xlsx
new file mode 100644
index 0000000..370a150
Binary files /dev/null and b/app/src/main/res/raw/measure_single_axis.xlsx differ
diff --git a/app/src/main/res/xml/provider_paths.xml b/app/src/main/res/xml/provider_paths.xml
new file mode 100644
index 0000000..ef021c3
--- /dev/null
+++ b/app/src/main/res/xml/provider_paths.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file