Files
VesiscanClinicalAndroid/app/src/main/java/com/example/medilightv2android/services/AdcCsvLogger.kt
T
dw.jang f563b20659 feat: ADC 데이터 일별 CSV 저장 (Downloads/VesiScan_ADC/)
AdcCsvLogger: 측정마다 6채널 ADC를 CSV에 append
- 파일: Downloads/VesiScan_ADC/YYYY-MM-DD.csv
- 행: scan_id × 6채널 (1회 측정 = 6행)
- 열: scan_id, timestamp, volume_ml, lr_ratio, channel, s0~s99
- BV 성공/실패 모두 ADC 저장 (volume_ml 빈칸이면 실패)
- Python: pd.read_csv() → df[df.scan_id==1] 으로 1회 측정 추출

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-27 10:47:33 +09:00

85 lines
2.7 KiB
Kotlin
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package com.example.medilightv2android.services
import android.os.Environment
import java.io.File
import java.text.SimpleDateFormat
import java.util.*
/**
* ADC 데이터를 일별 CSV 파일로 저장.
*
* 파일 위치: Downloads/VesiScan_ADC/YYYY-MM-DD.csv
* 행: scan_id × 6채널 (측정 1회 = 6행)
* 열: scan_id, timestamp, volume_ml, lr_ratio, channel, sample_0~sample_99
*/
object AdcCsvLogger {
private val dayFmt = SimpleDateFormat("yyyy-MM-dd", Locale.US)
private val timeFmt = SimpleDateFormat("HH:mm:ss.SSS", Locale.US)
private var scanCounter = 0
private fun getDir(): File {
val dir = File(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),
"VesiScan_ADC"
)
if (!dir.exists()) dir.mkdirs()
return dir
}
private fun getTodayFile(): File {
return File(getDir(), "${dayFmt.format(Date())}.csv")
}
/**
* 6채널 ADC 데이터를 CSV에 append.
*
* @param channels 6채널 ADC 버퍼 (List<List<UShort>>)
* @param volumeMl BV 추정 결과 (null이면 측정 실패)
* @param lrRatio lr_ratio 값
*/
fun log(
channels: List<List<UShort>>,
volumeMl: Double? = null,
lrRatio: Double = 1.0
) {
try {
val file = getTodayFile()
val isNew = !file.exists() || file.length() == 0L
scanCounter++
val timestamp = timeFmt.format(Date())
val volStr = volumeMl?.let { "%.1f".format(it) } ?: ""
val lrStr = "%.2f".format(lrRatio)
java.io.FileWriter(file, !isNew).buffered().use { writer ->
if (isNew) {
val header = buildString {
append("scan_id,timestamp,volume_ml,lr_ratio,channel")
for (i in 0 until 100) append(",s$i")
}
writer.write(header)
writer.newLine()
}
for ((chIdx, buffer) in channels.withIndex()) {
val row = buildString {
append("$scanCounter,$timestamp,$volStr,$lrStr,CH$chIdx")
for (sample in buffer) {
append(",${sample.toInt()}")
}
// 100개 미만이면 빈 칸으로 채움
for (i in buffer.size until 100) {
append(",")
}
}
writer.write(row)
writer.newLine()
}
}
} catch (_: Exception) {
// 로깅 실패는 앱 crash 방지
}
}
}