diff --git a/app/src/main/java/com/example/medilightv2android/managers/PiezoBVEstimator.kt b/app/src/main/java/com/example/medilightv2android/managers/PiezoBVEstimator.kt index 3ed2972..cb31c49 100644 --- a/app/src/main/java/com/example/medilightv2android/managers/PiezoBVEstimator.kt +++ b/app/src/main/java/com/example/medilightv2android/managers/PiezoBVEstimator.kt @@ -35,15 +35,20 @@ object PiezoHW { var activePreset: DevicePreset = DevicePreset.V0 fun autoDetectPreset(deviceName: String) { - if (deviceName.startsWith("VBT2604") && deviceName.length >= 10) { - when (deviceName[8]) { - '0' -> activePreset = DevicePreset.V0 - '2' -> activePreset = DevicePreset.V1 - '3' -> activePreset = DevicePreset.V2 + if (deviceName.startsWith("VBT") && deviceName.length >= 4) { + // VBT...n0x → 뒤에서 3번째 글자(n)가 각도 타입 + // n=0 → V0, n=2 → V1, n=3 → V2 + val n = deviceName[deviceName.length - 3] + activePreset = when (n) { + '0' -> DevicePreset.V0 + '2' -> DevicePreset.V1 + '3' -> DevicePreset.V2 + else -> DevicePreset.V1 // 알 수 없으면 V1 기본 } } else if (deviceName.startsWith("2025MEDIP")) { activePreset = DevicePreset.LEGACY_5CH } + android.util.Log.d("PiezoHW", "autoDetectPreset: '$deviceName' → ${activePreset.name}") } val centerCh = intArrayOf(0, 1, 2, 3) diff --git a/app/src/main/java/com/example/medilightv2android/ui/views/monitoring/PiezoMonitoringView.kt b/app/src/main/java/com/example/medilightv2android/ui/views/monitoring/PiezoMonitoringView.kt index 6e967a3..ed2e994 100644 --- a/app/src/main/java/com/example/medilightv2android/ui/views/monitoring/PiezoMonitoringView.kt +++ b/app/src/main/java/com/example/medilightv2android/ui/views/monitoring/PiezoMonitoringView.kt @@ -761,9 +761,13 @@ fun PiezoMonitoringView(appState: AppState) { // Donut chart with Bladdy val donutSize = if (isCompact) 220.dp else 280.dp + // maxVolume 기준 비율 (0.0~1.0, 부드러운 연속값) + val maxVolumeForDonut = appState.piezoSettings.maxVolume.toDouble() + val donutProgress = if (maxVolumeForDonut > 0 && maxVolumeMl > 0) + (maxVolumeMl / maxVolumeForDonut).coerceIn(0.0, 1.0) else 0.0 Box(contentAlignment = Alignment.Center) { DonutChartView( - progress = appState.bladderLevel.progress, + progress = donutProgress, urgency = urgency, lineWidth = if (isCompact) 22.dp else 30.dp, size = donutSize diff --git a/app/src/main/java/com/example/medilightv2android/ui/views/monitoring/PlacementGuideView.kt b/app/src/main/java/com/example/medilightv2android/ui/views/monitoring/PlacementGuideView.kt index 4ae7a6c..54e0c50 100644 --- a/app/src/main/java/com/example/medilightv2android/ui/views/monitoring/PlacementGuideView.kt +++ b/app/src/main/java/com/example/medilightv2android/ui/views/monitoring/PlacementGuideView.kt @@ -96,6 +96,7 @@ fun PlacementGuideView(appState: AppState) { // SWEEP 추가 state var sweepLastDetected by remember { mutableIntStateOf(0) } var sweepEverSawAll by remember { mutableStateOf(false) } + var almostThereCount by remember { mutableIntStateOf(0) } // 화면 진입 시 상태 리셋 LaunchedEffect(Unit) { @@ -110,7 +111,7 @@ fun PlacementGuideView(appState: AppState) { rTracker.reset() currentRMm = null; bestRMm = 0.0 sagittalArgMaxCh = null; lateralOffsetMm = null - sweepLastDetected = 0; sweepEverSawAll = false + sweepLastDetected = 0; sweepEverSawAll = false; almostThereCount = 0 } // 화면 벗어날 때 LED OFF @@ -656,10 +657,25 @@ fun PlacementGuideView(appState: AppState) { lastHintChangeMs = now } - if (guideResult.isPass) { + // "Almost there" 연속 3회 → 자동 GREEN 통과 + val isAlmostThere = guideResult.hint.contains("Almost there") + if (isAlmostThere) almostThereCount++ else almostThereCount = 0 + val autoPass = guideResult.isPass || almostThereCount >= 3 + + if (autoPass) { isLocked = true + almostThereCount = 0 if (lastLedMode != 6) { bleManager.sendLedMode(6); lastLedMode = 6 } - bleManager.debugLogger.info("PLACEMENT_GREEN cv=${"%.3f".format(guideResult.cv)} lr_dev=${"%.3f".format(guideResult.lrDev)} score=${guideResult.score} otsu=${"%.0f".format(analyzer.lastOtsuThreshold)}") + if (guideResult.isPass) { + bleManager.debugLogger.info("PLACEMENT_GREEN cv=${"%.3f".format(guideResult.cv)} lr_dev=${"%.3f".format(guideResult.lrDev)} score=${guideResult.score} otsu=${"%.0f".format(analyzer.lastOtsuThreshold)}") + } else { + // Auto-pass: 위치 OK인데 CV 노이즈로 3회 연속 미달 + directionHint = "Green! Position locked" + directionIcon = "checkmark.circle" + placementScore = 70 + placementPhase = PlacementPhase.GREEN + bleManager.debugLogger.info("PLACEMENT_GREEN_AUTO cv=${"%.3f".format(guideResult.cv)} almostThereCount=3") + } } else { isLocked = false if (lastLedMode != 5) { bleManager.sendLedMode(5); lastLedMode = 5 }