From 002a99d1638cd6770bda548eaa514d7771795035 Mon Sep 17 00:00:00 2001 From: jjangddu Date: Thu, 30 Apr 2026 17:29:37 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20Placement=20LED=20=EB=8B=A8=EA=B3=84?= =?UTF-8?q?=EB=B3=84=201=ED=9A=8C=EB=A7=8C=20+=20=ED=99=94=EC=82=B4?= =?UTF-8?q?=ED=91=9C=20=ED=99=95=EB=8C=80=20+=20=EB=8F=84=EB=84=9B?= =?UTF-8?q?=EB=B7=B0=20detachment=20LED?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Placement: - LED 명령: 매 스캔 → 단계 변경 시 1회만 (lastLedMode 추적) - 5=SEARCHING, 6=COMPLETE, 화면 나갈 때 0=OFF - 화살표 크기: arrowLen 40→60, arrowHead 12→18, strokeWidth 4→5 Monitoring (도넛뷰): - 매 측정마다 DetachmentDetection.detect() 실행 - 미부착 감지 시 LED 4 (DETACH_WARNING) 전송 + 로그 Co-Authored-By: Claude Opus 4.6 (1M context) --- .../views/monitoring/PiezoMonitoringView.kt | 9 +++ .../ui/views/monitoring/PlacementGuideView.kt | 57 ++++++++++--------- 2 files changed, 38 insertions(+), 28 deletions(-) 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 934d511..1829534 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 @@ -123,6 +123,15 @@ fun PiezoMonitoringView(appState: AppState) { lastMultiChannelResult.clear() lastMultiChannelResult.addAll(channels) + // Detachment 체크 + val sortedBuffers = channels.sortedBy { it.channel }.map { it.buffer } + val detachResult = com.example.medilightv2android.managers.DetachmentDetection.detect(sortedBuffers) + if (detachResult.isDetached) { + Log.w("PiezoMonitor", "DETACHED mean=${"%.1f".format(detachResult.meanAbs)} std=${"%.1f".format(detachResult.stdVal)}") + bleManager.debugLogger.warn("DETACHED mean=${"%.1f".format(detachResult.meanAbs)} std=${"%.1f".format(detachResult.stdVal)}") + handler.post { bleManager.sendLedMode(4) } + } + var rawVolumeMl: Double? = null var rawLrRatio = 1.0 var totalWallCount = 0 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 7866793..d49082a 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 @@ -72,6 +72,7 @@ fun PlacementGuideView(appState: AppState) { var lastGuidePhase by remember { mutableStateOf(PlacementPhase.VERTICAL) } var lastHintChangeMs by remember { mutableStateOf(0L) } var showPlacementSettings by remember { mutableStateOf(false) } + var lastLedMode by remember { mutableIntStateOf(-1) } // 2단계 순차 탐색: VERTICAL → LATERAL → GREEN var placementPhase by remember { mutableStateOf(PlacementPhase.VERTICAL) } @@ -234,33 +235,33 @@ fun PlacementGuideView(appState: AppState) { // ── 방향 화살표 ── if (!greenZone) { val arrowColor = Color(0xFFFF9800) - val arrowLen = 40f - val arrowHead = 12f + val arrowLen = 60f + val arrowHead = 18f when { directionIcon.contains("up") -> { val ax = cx; val ay = sensorY - 20f - drawLine(arrowColor, Offset(ax, ay + arrowLen), Offset(ax, ay), strokeWidth = 4f) - drawLine(arrowColor, Offset(ax - arrowHead, ay + arrowHead), Offset(ax, ay), strokeWidth = 4f) - drawLine(arrowColor, Offset(ax + arrowHead, ay + arrowHead), Offset(ax, ay), strokeWidth = 4f) + drawLine(arrowColor, Offset(ax, ay + arrowLen), Offset(ax, ay), strokeWidth = 5f) + drawLine(arrowColor, Offset(ax - arrowHead, ay + arrowHead), Offset(ax, ay), strokeWidth = 5f) + drawLine(arrowColor, Offset(ax + arrowHead, ay + arrowHead), Offset(ax, ay), strokeWidth = 5f) } directionIcon.contains("down") -> { val ax = cx; val ay = sensorY + sensorH + 20f - drawLine(arrowColor, Offset(ax, ay - arrowLen), Offset(ax, ay), strokeWidth = 4f) - drawLine(arrowColor, Offset(ax - arrowHead, ay - arrowHead), Offset(ax, ay), strokeWidth = 4f) - drawLine(arrowColor, Offset(ax + arrowHead, ay - arrowHead), Offset(ax, ay), strokeWidth = 4f) + drawLine(arrowColor, Offset(ax, ay - arrowLen), Offset(ax, ay), strokeWidth = 5f) + drawLine(arrowColor, Offset(ax - arrowHead, ay - arrowHead), Offset(ax, ay), strokeWidth = 5f) + drawLine(arrowColor, Offset(ax + arrowHead, ay - arrowHead), Offset(ax, ay), strokeWidth = 5f) } directionIcon.contains("left") -> { val ax = cx - sensorW / 2 - 25f; val ay = sensorY + sensorH / 2 - drawLine(arrowColor, Offset(ax + arrowLen, ay), Offset(ax, ay), strokeWidth = 4f) - drawLine(arrowColor, Offset(ax + arrowHead, ay - arrowHead), Offset(ax, ay), strokeWidth = 4f) - drawLine(arrowColor, Offset(ax + arrowHead, ay + arrowHead), Offset(ax, ay), strokeWidth = 4f) + drawLine(arrowColor, Offset(ax + arrowLen, ay), Offset(ax, ay), strokeWidth = 5f) + drawLine(arrowColor, Offset(ax + arrowHead, ay - arrowHead), Offset(ax, ay), strokeWidth = 5f) + drawLine(arrowColor, Offset(ax + arrowHead, ay + arrowHead), Offset(ax, ay), strokeWidth = 5f) } directionIcon.contains("right") -> { val ax = cx + sensorW / 2 + 25f; val ay = sensorY + sensorH / 2 - drawLine(arrowColor, Offset(ax - arrowLen, ay), Offset(ax, ay), strokeWidth = 4f) - drawLine(arrowColor, Offset(ax - arrowHead, ay - arrowHead), Offset(ax, ay), strokeWidth = 4f) - drawLine(arrowColor, Offset(ax - arrowHead, ay + arrowHead), Offset(ax, ay), strokeWidth = 4f) + drawLine(arrowColor, Offset(ax - arrowLen, ay), Offset(ax, ay), strokeWidth = 5f) + drawLine(arrowColor, Offset(ax - arrowHead, ay - arrowHead), Offset(ax, ay), strokeWidth = 5f) + drawLine(arrowColor, Offset(ax - arrowHead, ay + arrowHead), Offset(ax, ay), strokeWidth = 5f) } } } @@ -534,11 +535,11 @@ fun PlacementGuideView(appState: AppState) { if (guideResult.isPass) { isLocked = true - bleManager.sendLedMode(6) // ALIGN_COMPLETE + 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)}") } else { isLocked = false - bleManager.sendLedMode(5) // ALIGN_SEARCHING + if (lastLedMode != 5) { bleManager.sendLedMode(5); lastLedMode = 5 } bleManager.debugLogger.info("PLACEMENT_${guideResult.phase.name} score=${guideResult.score} otsu=${"%.0f".format(analyzer.lastOtsuThreshold)} hint=${guideResult.hint}") } } @@ -798,27 +799,27 @@ private fun SensorLayoutCanvas( when { directionIcon.contains("up") -> { val ax = cx; val ay = cy - 190f - drawLine(orangeColor, Offset(ax, ay + al), Offset(ax, ay), strokeWidth = 4f) - drawLine(orangeColor, Offset(ax - 14f, ay + 14f), Offset(ax, ay), strokeWidth = 4f) - drawLine(orangeColor, Offset(ax + 14f, ay + 14f), Offset(ax, ay), strokeWidth = 4f) + drawLine(orangeColor, Offset(ax, ay + al), Offset(ax, ay), strokeWidth = 5f) + drawLine(orangeColor, Offset(ax - 14f, ay + 14f), Offset(ax, ay), strokeWidth = 5f) + drawLine(orangeColor, Offset(ax + 14f, ay + 14f), Offset(ax, ay), strokeWidth = 5f) } directionIcon.contains("down") -> { val ax = cx; val ay = cy + 190f - drawLine(orangeColor, Offset(ax, ay - al), Offset(ax, ay), strokeWidth = 4f) - drawLine(orangeColor, Offset(ax - 14f, ay - 14f), Offset(ax, ay), strokeWidth = 4f) - drawLine(orangeColor, Offset(ax + 14f, ay - 14f), Offset(ax, ay), strokeWidth = 4f) + drawLine(orangeColor, Offset(ax, ay - al), Offset(ax, ay), strokeWidth = 5f) + drawLine(orangeColor, Offset(ax - 14f, ay - 14f), Offset(ax, ay), strokeWidth = 5f) + drawLine(orangeColor, Offset(ax + 14f, ay - 14f), Offset(ax, ay), strokeWidth = 5f) } directionIcon.contains("left") -> { val ax = cx - 190f; val ay = cy - drawLine(orangeColor, Offset(ax + al, ay), Offset(ax, ay), strokeWidth = 4f) - drawLine(orangeColor, Offset(ax + 14f, ay - 14f), Offset(ax, ay), strokeWidth = 4f) - drawLine(orangeColor, Offset(ax + 14f, ay + 14f), Offset(ax, ay), strokeWidth = 4f) + drawLine(orangeColor, Offset(ax + al, ay), Offset(ax, ay), strokeWidth = 5f) + drawLine(orangeColor, Offset(ax + 14f, ay - 14f), Offset(ax, ay), strokeWidth = 5f) + drawLine(orangeColor, Offset(ax + 14f, ay + 14f), Offset(ax, ay), strokeWidth = 5f) } directionIcon.contains("right") -> { val ax = cx + 190f; val ay = cy - drawLine(orangeColor, Offset(ax - al, ay), Offset(ax, ay), strokeWidth = 4f) - drawLine(orangeColor, Offset(ax - 14f, ay - 14f), Offset(ax, ay), strokeWidth = 4f) - drawLine(orangeColor, Offset(ax - 14f, ay + 14f), Offset(ax, ay), strokeWidth = 4f) + drawLine(orangeColor, Offset(ax - al, ay), Offset(ax, ay), strokeWidth = 5f) + drawLine(orangeColor, Offset(ax - 14f, ay - 14f), Offset(ax, ay), strokeWidth = 5f) + drawLine(orangeColor, Offset(ax - 14f, ay + 14f), Offset(ax, ay), strokeWidth = 5f) } } }