xlsx export
This commit is contained in:
parent
eca21cb3bf
commit
5293604ee4
|
|
@ -17,8 +17,8 @@ android {
|
|||
applicationId "llc.arma.ble"
|
||||
minSdk 26
|
||||
targetSdk 34
|
||||
versionCode 35
|
||||
versionName "1.4.4"
|
||||
versionCode 39
|
||||
versionName "1.4.9"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
vectorDrawables {
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import androidx.compose.material.ContentAlpha
|
|||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.rounded.ArrowBack
|
||||
import androidx.compose.material.icons.rounded.Refresh
|
||||
import androidx.compose.material.icons.rounded.Save
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.FilterChip
|
||||
|
|
@ -38,10 +39,12 @@ import androidx.compose.material3.Text
|
|||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.material3.VerticalDivider
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.StrokeCap
|
||||
import androidx.compose.ui.graphics.toArgb
|
||||
import androidx.compose.ui.platform.LocalConfiguration
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
|
@ -75,6 +78,7 @@ 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.BleName
|
||||
import llc.arma.ble.domain.usecase.ExportToXlsx
|
||||
import llc.arma.ble.domain.usecase.GetBleBySerial
|
||||
import llc.arma.ble.domain.usecase.GetBleNamesFlow
|
||||
import llc.arma.ble.domain.usecase.GetHostHistoryBySerial
|
||||
|
|
@ -148,6 +152,21 @@ fun HostHistory(
|
|||
},
|
||||
actions = {
|
||||
|
||||
IconButton(
|
||||
onClick = {
|
||||
viewModel.setEvent(HostHistoryContract.Event.OnExportHistory(ble.serial))
|
||||
},
|
||||
enabled = when(state){
|
||||
is HostHistoryContract.State.Display -> state.loadingHistoryState is ProgressState.Finished
|
||||
HostHistoryContract.State.Exception -> true
|
||||
}
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Rounded.Save,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
|
||||
IconButton(
|
||||
onClick = {
|
||||
viewModel.setEvent(HostHistoryContract.Event.OnRefreshHistory(ble.name, ble.serial))
|
||||
|
|
@ -183,11 +202,10 @@ val dateFormatter = SimpleDateFormat("dd.MM", Locale.getDefault())
|
|||
val timeFormatter = SimpleDateFormat("HH:mm", Locale.getDefault())
|
||||
|
||||
val colorsStack = listOf(
|
||||
-0x63d850, -0x98c549, -0xc0ae4b, -0xde690d,
|
||||
-0xfc560c, -0xff432c, -0xff6978, -0xb350b0,
|
||||
-0x743cb6, -0x3223c7, -0x14c5, -0x3ef9,
|
||||
-0x6800, -0xa8de, -0x86aab8, -0x616162,
|
||||
-0x9f8275, -0xcccccd, -0xbbcca
|
||||
Color(0xffffd700), Color(0xff2f4f4f), Color(0xff7f0000), Color(0xFFFF0000),
|
||||
Color(0xffa9a9a9), Color(0xff00fa9a), Color(0xff00ffff), Color(0xfff0e68c),
|
||||
Color(0xff00bfff), Color(0xff0000ff), Color(0xfff08080), Color(0xffadff2f),
|
||||
Color(0xffff00ff), Color(0xff4169e1), Color(0xffff1493), Color(0xffee82ee),
|
||||
)
|
||||
|
||||
val axisValueFormatter =
|
||||
|
|
@ -246,8 +264,8 @@ fun Display(
|
|||
}.toMap()
|
||||
}
|
||||
|
||||
var selectedSerials by remember {
|
||||
mutableStateOf(allSerials)
|
||||
var selectedSerials by rememberSaveable {
|
||||
mutableStateOf(allSerials.take(1))
|
||||
}
|
||||
|
||||
val serials = remember(selectedSerials) { allSerials.filter { selectedSerials.contains(it) } }
|
||||
|
|
@ -274,7 +292,7 @@ fun Display(
|
|||
|
||||
val chart = columnChart(
|
||||
innerSpacing = 2.dp,
|
||||
columns = serials.map { LineComponent(color = colors[it]!!, thicknessDp = 7f, shape= pillShape) },
|
||||
columns = serials.map { LineComponent(color = colors[it]!!.toArgb(), thicknessDp = 7f, shape= pillShape) },
|
||||
spacing = 8.dp,
|
||||
)
|
||||
|
||||
|
|
@ -297,7 +315,7 @@ fun Display(
|
|||
leadingIcon = {
|
||||
Surface(
|
||||
shape = CircleShape,
|
||||
color = Color(colors[s]!!),
|
||||
color = colors[s]!!,
|
||||
modifier = Modifier.size(28.dp)
|
||||
) {}
|
||||
},
|
||||
|
|
@ -464,7 +482,7 @@ class HostHistoryContract {
|
|||
|
||||
sealed class Event : ViewEvent {
|
||||
|
||||
object StopMeasure : Event()
|
||||
data object StopMeasure : Event()
|
||||
|
||||
data class OnStart(
|
||||
val bleName: String,
|
||||
|
|
@ -476,6 +494,10 @@ class HostHistoryContract {
|
|||
val serial: String,
|
||||
) : Event()
|
||||
|
||||
data class OnExportHistory(
|
||||
val serial: String,
|
||||
) : Event()
|
||||
|
||||
}
|
||||
|
||||
sealed class State : ViewState {
|
||||
|
|
@ -502,7 +524,8 @@ class HostHistoryContract {
|
|||
class HostHistoryViewModel @Inject constructor(
|
||||
private val getHostHistoryBySerial: GetHostHistoryBySerial,
|
||||
private val getBleBySerial: GetBleBySerial,
|
||||
private val getBleNamesFlow: GetBleNamesFlow
|
||||
private val getBleNamesFlow: GetBleNamesFlow,
|
||||
private val exportToXlsx: ExportToXlsx
|
||||
) : BaseViewModel<HostHistoryContract.State, HostHistoryContract.Event, HostHistoryContract.Effect>() {
|
||||
|
||||
var measureJob: Job? = null
|
||||
|
|
@ -520,9 +543,27 @@ class HostHistoryViewModel @Inject constructor(
|
|||
is HostHistoryContract.Event.OnStart -> reduce(viewState.value, event)
|
||||
is HostHistoryContract.Event.OnRefreshHistory -> reduce(viewState.value, event)
|
||||
is HostHistoryContract.Event.StopMeasure -> reduce(viewState.value, event)
|
||||
is HostHistoryContract.Event.OnExportHistory -> reduce(viewState.value, event)
|
||||
}
|
||||
}
|
||||
|
||||
private fun reduce(
|
||||
state: HostHistoryContract.State,
|
||||
event: HostHistoryContract.Event.OnExportHistory
|
||||
) {
|
||||
|
||||
if(state is HostHistoryContract.State.Display) {
|
||||
|
||||
if(state.loadingHistoryState is ProgressState.Finished) {
|
||||
|
||||
exportToXlsx.invoke(event.serial, state.loadingHistoryState.data)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun reduce(
|
||||
state: HostHistoryContract.State,
|
||||
event: HostHistoryContract.Event.StopMeasure
|
||||
|
|
|
|||
|
|
@ -126,10 +126,6 @@ fun readHostHistory(
|
|||
|
||||
fun getInnerIndex(byte: Byte): Int{
|
||||
|
||||
if(byte != 0.toByte()){
|
||||
println(byte)
|
||||
}
|
||||
|
||||
var bits = BitSet.valueOf(byteArrayOf(byte))
|
||||
bits.clear(0, 4)
|
||||
bits = bits.get(4, 8)
|
||||
|
|
@ -146,7 +142,7 @@ fun readHostHistory(
|
|||
fun getDevType(byte: Byte): Int{
|
||||
|
||||
var bits = BitSet.valueOf(byteArrayOf(byte))
|
||||
bits.clear(5, 8)
|
||||
bits.clear(5, 9)
|
||||
val arr = bits.toByteArray()
|
||||
|
||||
if(arr.isEmpty()){
|
||||
|
|
@ -161,7 +157,7 @@ fun readHostHistory(
|
|||
|
||||
var bits = BitSet.valueOf(byteArrayOf(byte))
|
||||
bits.clear(0, 5)
|
||||
bits = bits.get(4, 8)
|
||||
bits = bits.get(5, 8)
|
||||
val arr = bits.toByteArray()
|
||||
|
||||
if(arr.isEmpty()){
|
||||
|
|
@ -204,8 +200,10 @@ fun readHostHistory(
|
|||
println("table serial $serial")
|
||||
|
||||
val devType = getDevType(devTypeByte)
|
||||
println("devType $devType")
|
||||
val devDataSize = getDevDataSize(devTypeByte)
|
||||
|
||||
println("payload $devDataSize")
|
||||
bleTableOffset += 2
|
||||
|
||||
if (devDataSize != 0) {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,13 @@ package llc.arma.ble.data.repository
|
|||
import android.app.Application
|
||||
import android.icu.text.SimpleDateFormat
|
||||
import android.os.Environment
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import com.patrykandpatrick.vico.core.entry.ChartEntryModelProducer
|
||||
import llc.arma.ble.R
|
||||
import llc.arma.ble.app.ui.screen.inspection.host.view.HostEntry
|
||||
import llc.arma.ble.app.ui.screen.inspection.host.view.colorsStack
|
||||
import llc.arma.ble.domain.model.Ble
|
||||
import llc.arma.ble.domain.repository.XlsxRepository
|
||||
import org.apache.poi.ss.usermodel.WorkbookFactory
|
||||
|
|
@ -20,13 +26,13 @@ class XlsxRepositoryImpl @Inject constructor(
|
|||
private val application: Application
|
||||
) : XlsxRepository {
|
||||
|
||||
override fun exportToXls(
|
||||
override fun exportAccelDataToXls(
|
||||
bleName: String,
|
||||
data: List<Ble.Accelerometer.HistoryPoint>
|
||||
): File {
|
||||
|
||||
val fileNameDateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm")
|
||||
val fileName = "${fileNameDateFormat.format(Date(System.currentTimeMillis()))}.xlsx".replace(' ', '_')
|
||||
val fileNameDateFormat = SimpleDateFormat("yyyy-MM-dd_HH-mm")
|
||||
val fileName = "${fileNameDateFormat.format(Date(System.currentTimeMillis()))}.xlsx"
|
||||
|
||||
val formatter = SimpleDateFormat("dd.MM.yyyy HH:mm")
|
||||
|
||||
|
|
@ -105,4 +111,64 @@ class XlsxRepositoryImpl @Inject constructor(
|
|||
return mailFile
|
||||
}
|
||||
|
||||
override fun exportHostDataToXls(bleName: String, data: List<Ble.Host.HistoryPoint>): File {
|
||||
val fileNameDateFormat = SimpleDateFormat("yyyy-MM-dd_HH-mm")
|
||||
val fileName = "${fileNameDateFormat.format(Date(System.currentTimeMillis()))}.xlsx"
|
||||
|
||||
val formatter = SimpleDateFormat("dd.MM.yyyy HH:mm")
|
||||
|
||||
File(application.filesDir.absolutePath).mkdirs()
|
||||
val mailFile = File(application.filesDir, fileName)
|
||||
|
||||
mailFile.createNewFile()
|
||||
|
||||
IOUtils.copy(application.resources.openRawResource(R.raw.host_history), FileOutputStream(mailFile))
|
||||
|
||||
val fileIn = FileInputStream(mailFile)
|
||||
val workbook = WorkbookFactory.create(fileIn)
|
||||
val worksheet = workbook.getSheetAt(0) as XSSFSheet
|
||||
|
||||
val row = worksheet.createRow(0)
|
||||
row.createCell(0).setCellValue("Date")
|
||||
|
||||
data.forEachIndexed { index, historyPoint ->
|
||||
|
||||
row.createCell(index).setCellValue(formatter.format(Date(historyPoint.date)))
|
||||
|
||||
}
|
||||
|
||||
data.flatMap { it.value }.distinct().forEachIndexed { rowIndex, serial ->
|
||||
|
||||
val row = worksheet.createRow(rowIndex + 1)
|
||||
row.createCell(0).setCellValue(serial)
|
||||
|
||||
data.forEachIndexed { index, historyPoint ->
|
||||
|
||||
row.createCell(index + 1)
|
||||
.setCellValue(
|
||||
if(historyPoint.value.contains(serial)) 1.0 else 0.0
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fileIn.close()
|
||||
val saveFos = FileOutputStream(mailFile)
|
||||
workbook.write(saveFos)
|
||||
saveFos.close()
|
||||
|
||||
println(fileName)
|
||||
|
||||
val sharedFile = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), fileName)
|
||||
sharedFile.createNewFile()
|
||||
|
||||
val sharedSaveFos = FileOutputStream(sharedFile)
|
||||
workbook.write(sharedSaveFos)
|
||||
sharedSaveFos.close()
|
||||
|
||||
workbook.close()
|
||||
|
||||
return mailFile
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -5,9 +5,14 @@ import java.io.File
|
|||
|
||||
interface XlsxRepository {
|
||||
|
||||
fun exportToXls(
|
||||
fun exportAccelDataToXls(
|
||||
bleName: String,
|
||||
data: List<Ble.Accelerometer.HistoryPoint>
|
||||
): File
|
||||
|
||||
fun exportHostDataToXls(
|
||||
bleName: String,
|
||||
data: List<Ble.Host.HistoryPoint>
|
||||
): File
|
||||
|
||||
}
|
||||
|
|
@ -15,7 +15,18 @@ class ExportToXlsx @Inject constructor(
|
|||
data: List<Ble.Accelerometer.HistoryPoint>
|
||||
){
|
||||
|
||||
val file = xlsxRepository.exportToXls(bleName, data)
|
||||
val file = xlsxRepository.exportAccelDataToXls(bleName, data)
|
||||
emailRepository.sendFile(file)
|
||||
|
||||
}
|
||||
|
||||
@JvmName("invokeHost")
|
||||
operator fun invoke(
|
||||
bleName: String,
|
||||
data: List<Ble.Host.HistoryPoint>
|
||||
){
|
||||
|
||||
val file = xlsxRepository.exportHostDataToXls(bleName, data)
|
||||
emailRepository.sendFile(file)
|
||||
|
||||
}
|
||||
|
|
|
|||
Binary file not shown.
Loading…
Reference in New Issue