Files
VesiscanClinicalAndroid/app/src/main/java/com/medithings/vesiscan/services/ImuCsvLogger.kt
T
dw.jang bcbc7b440c refactor: 데모 브랜치 패키지 통일 com.example.medilightv2android → com.medithings.vesiscan
사용자앱 (feature/tab-navigation) 과 패키지 이름 일치. namespace + applicationId
둘 다 com.medithings.vesiscan 로 변경 (기존 데모 앱은 재설치 필요).

## 변경 범위
- Kotlin 148 파일: package + import 문 (714 occurrences)
- 디렉토리 이동: com/example/medilightv2android → com/medithings/vesiscan
  (main, test, androidTest 각각)
- app/build.gradle.kts: namespace, applicationId
- docs/FLAVOR_DEMO_STABLE.md: 참조 갱신
- V41DetectorCH4Test: BvDispatchResult.methodChosen → method (dto field name fix)

## 주의
- applicationId 가 바뀌므로 기존 데모 앱 (com.example.medilightv2android.demo) 은
  Android 관점에서 다른 앱으로 취급 — 재설치 시 PIN/설정 초기화됨.
- Fresh install 권장. 기존 앱 (com.example...) 은 별도로 uninstall 필요.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-07-02 14:30:43 +09:00

67 lines
2.6 KiB
Kotlin

package com.medithings.vesiscan.services
import com.medithings.vesiscan.ble.ImuSample
import java.io.File
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
/**
* IMU 샘플을 CSV로 저장. 임상 R&D 모드 한정.
*
* 파일 위치 (임상 모드일 때):
* Downloads/VesiScan_Sessions/{folder}/imu.csv
*
* 한 번의 mtb? 응답에서 15 샘플 → CSV 15행. scan_id로 같은 측정의 piezo adc.csv와 매칭 가능.
*
* Sensitivity:
* ax/ay/az: g (Accel ±4g, 1 LSB = 1/8192 g)
* gx/gy/gz: dps (Gyro ±500 dps, 1 LSB = 1/65.536 dps)
*
* Sample 순서: 한 응답 안에서 oldest→newest. sample_idx 컬럼으로 명시.
*/
object ImuCsvLogger {
private val timeFmt = SimpleDateFormat("HH:mm:ss.SSS", Locale.US)
/**
* 임상 모드 한정. ClinicalSessionStore.currentLogDir()가 있을 때만 저장.
* samples를 oldest→newest 순서로 그대로 기록.
*/
fun log(samples: List<ImuSample>) {
val dir = ClinicalSessionStore.currentLogDir() ?: return
if (samples.isEmpty()) return
try {
dir.mkdirs()
val file = File(dir, "imu.csv")
val isNew = !file.exists() || file.length() == 0L
val scanId = AdcCsvLogger.lastScanId // piezo adc.csv와 매칭용
val timestamp = timeFmt.format(Date())
val clinicalLabel = ClinicalSessionStore.currentLabel()
val fwVersion = com.medithings.vesiscan.ble.BleManager.current?.firmwareVersion?.value ?: ""
file.bufferedWriter().use { _ -> } // ensure exists
java.io.FileWriter(file, !isNew).buffered().use { writer ->
if (isNew) {
writer.write("scan_id,timestamp,clinical_label,firmware_version,sample_idx,ax_g,ay_g,az_g,gx_dps,gy_dps,gz_dps")
writer.newLine()
}
for ((idx, s) in samples.withIndex()) {
writer.write(buildString {
append("$scanId,$timestamp,$clinicalLabel,$fwVersion,$idx,")
append("%.4f".format(s.ax)); append(",")
append("%.4f".format(s.ay)); append(",")
append("%.4f".format(s.az)); append(",")
append("%.4f".format(s.gx)); append(",")
append("%.4f".format(s.gy)); append(",")
append("%.4f".format(s.gz))
})
writer.newLine()
}
}
} catch (_: Exception) {
// 로그는 측정 자체를 막으면 안 됨 — silent fail
}
}
}