feat: 임상 Live 6채널 시각화 화면 (ClinicalLiveView)

vesiscan_test Section 2 프로토콜 패턴을 안드로이드 앱 안에서 직접 구현.
실제 몸에 센서 붙인 채 6채널 실시간 그래프 보면서 측정 + 저장 가능.

신규 화면 ClinicalLiveView:
- 600ms 간격 mtb? 자동 송신 (Piezo 6ch + IMU 동시)
- 2×3 grid 라이브 차트 (raw ADC waveform, CH0~CH5 색상별)
  · y축 0~4095 (12-bit ADC) 고정 + 가로 grid 4분할
  · 각 채널 peak 값 표시
- IMU 카드 — ImuAnalysis 기반 자세 + tilt + shake (흔들림 시 빨강 경고)
- 상단: 세션 라벨 + S=Subject TV=TrueVol Ab=Abdomen 한 줄 + #cycle ✓captured
- 컨트롤: Pause/Resume · Capture (수동 저장) · Auto Capture 토글 · End Session

ClinicalSession 모델 확장:
- subjectId / trueVolumeMl / abdomenThicknessMm 필드 추가
- folderName 에 subjectId prefix (예: "S001_VBT26050202_SUPINE_ALIGN_0CM_...")
- meta.json 에 subject_id / true_volume_ml / abdomen_thickness_mm 자동 기록

ClinicalSessionStore:
- lastSubjectId / lastTrueVolumeMl / lastAbdomenThicknessMm 기억 (다음 측정 자동 채움)

ClinicalHomeView 입력 폼 확장:
- Subject ID 텍스트필드
- True Volume (mL) + Abdomen (mm) 2-컬럼 숫자 입력
- Start Live Measurement 버튼 → CLINICAL_LIVE 화면으로 직행
  (이전: alignment/BV step에 따라 PlacementGuide/PiezoMonitoring 분기)

AppState/MainActivity:
- AppScreen.CLINICAL_LIVE 추가
- MainActivity Back: LIVE 시 endMeasurement + ClinicalHome 복귀

데이터 흐름:
  Start Live → ClinicalLiveView 진입 → mtb? 600ms loop
    → piezoCollector → 6채널 buffer (자동 또는 수동 capture)
    → AdcCsvLogger.log → adc.csv 누적
    → imuCollector → 15 IMU samples
    → ImuCsvLogger.log → imu.csv 누적
  End/Back → endMeasurement → meta.json finalize → ClinicalHome 복귀

장점:
- 검사자가 실제 시연 중 6채널 신호 품질 즉시 확인
- Auto Capture로 매 사이클 자동 저장 (Pause로 일시 멈춤)
- subject_id 기반 폴더명으로 피험자별 grouping 자연스럽게

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-01 11:17:55 +09:00
parent ec3be6fa5d
commit 38fa93c8b2
6 changed files with 430 additions and 9 deletions
@@ -40,6 +40,7 @@ import com.example.medilightv2android.ui.views.consent.ConsentView
import com.example.medilightv2android.ui.views.reminder.ReminderSettingsView
import com.example.medilightv2android.ui.views.sensorselect.SensorSelectView
import com.example.medilightv2android.ui.views.clinical.ClinicalHomeView
import com.example.medilightv2android.ui.views.clinical.ClinicalLiveView
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
@@ -117,6 +118,11 @@ fun MedilightApp(modifier: Modifier = Modifier) {
com.example.medilightv2android.services.ClinicalSessionStore.inClinicalFlow = false
appState.currentScreen = AppScreen.HOME
}
AppScreen.CLINICAL_LIVE -> {
// 측정 폴더 finalize 후 ClinicalHome 복귀
com.example.medilightv2android.services.ClinicalSessionStore.endMeasurement(context)
appState.currentScreen = AppScreen.CLINICAL_HOME
}
// 모니터링 하위 화면 → 모니터링
AppScreen.MEASUREMENT_HISTORY -> appState.currentScreen = AppScreen.PIEZO_MONITORING
AppScreen.VOIDING_DIARY -> appState.currentScreen = AppScreen.PIEZO_MONITORING
@@ -164,6 +170,7 @@ fun MedilightApp(modifier: Modifier = Modifier) {
onBack = { appState.backToMonitoring() }
)
AppScreen.CLINICAL_HOME -> ClinicalHomeView(appState)
AppScreen.CLINICAL_LIVE -> ClinicalLiveView(appState)
}
}
}