From a175540291fa3294b542c43764dd78d80893544f Mon Sep 17 00:00:00 2001 From: jjangddu Date: Tue, 23 Jun 2026 17:39:46 +0900 Subject: [PATCH] =?UTF-8?q?fix(posture):=20pitch=20=EB=B6=84=EB=A5=98=20in?= =?UTF-8?q?vert=20+=20PiezoMonitoring=20=EC=84=A4=EC=A0=95=EC=97=90?= =?UTF-8?q?=EB=8F=84=20=EA=B8=B0=EC=83=81=20=EC=95=8C=EB=9E=8C=20=ED=86=A0?= =?UTF-8?q?=EA=B8=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 증상 1: 디바이스 평평하게 둠 → "Upright" / 세움 → "Lying" (또는 기존 빌드의 "Sitting") 으로 사용자 직관과 반대. 진단: 사용자 raw 데이터 분석 - 평평 (AZ dominant, AZ ≈ 1g): pitch ≈ 0° → 코드가 NON_LYING (Upright) 반환 - 세움 (AX dominant, AX ≈ 1g): pitch ≈ 80~90° → 코드가 LYING 반환 사용자 직관: 평평=Lying, 세움=Upright → 코드 inversion. 수정 1: ImuPostureClassifier 의 분류 조건 invert - 기존: |pitch| > threshold → LYING - 신규: |pitch| ≤ threshold → LYING (작은 pitch = AZ 가 중력 = 센서 평평) - dev slider hint 도 "|pitch|≤N°→Lying" 으로 동기화 수정 2: PiezoMonitoring 의 dev settings overlay 에도 기상 알람 토글 추가 - 기존: PiezoPersonalizationView 에만 존재 - 신규: dev settings panel (Pitch Threshold slider 아래) 에 동일 토글 - 두 위치 모두 같은 WakeupAlarmPrefs 사용 — sync 됨 - 사용자가 monitoring 페이지에서 바로 켜고 끌 수 있음 Co-Authored-By: Claude Opus 4.7 --- .../managers/ImuPostureClassifier.kt | 5 +++- .../views/monitoring/PiezoMonitoringView.kt | 25 ++++++++++++++++++- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/example/medilightv2android/managers/ImuPostureClassifier.kt b/app/src/main/java/com/example/medilightv2android/managers/ImuPostureClassifier.kt index a7b7f31..cbf40e4 100644 --- a/app/src/main/java/com/example/medilightv2android/managers/ImuPostureClassifier.kt +++ b/app/src/main/java/com/example/medilightv2android/managers/ImuPostureClassifier.kt @@ -69,7 +69,10 @@ object ImuPostureClassifier { val absPitch = abs(pitch) val thr = GreenZoneConstants.pitchLyingThreshold - val posture = if (absPitch > thr) Posture.LYING else Posture.NON_LYING + // Pitch 의미: AX 가 중력과 일치할수록 큰 값 (≈90°), AZ 가 중력과 일치하면 작은 값 (≈0°). + // 사용자 직관: 센서 평평하게 둠 (AZ up) = LYING, 세움 (AX up) = NON_LYING (upright). + // → 작은 pitch → LYING, 큰 pitch → NON_LYING + val posture = if (absPitch <= thr) Posture.LYING else Posture.NON_LYING return Result(posture, pitch, accMag, gyroMag, "ok") } } 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 c937c49..a9eb0a3 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 @@ -1791,7 +1791,7 @@ fun PiezoMonitoringView(appState: AppState) { Spacer(modifier = Modifier.width(8.dp)) Text("${pitchThrVal.toInt()}°", fontSize = 13.sp, fontWeight = FontWeight.Bold, color = MlPrimary) Spacer(modifier = Modifier.weight(1f)) - Text("|pitch|>${pitchThrVal.toInt()}°→Lying", fontSize = 11.sp, color = MlSecondaryText) + Text("|pitch|≤${pitchThrVal.toInt()}°→Lying", fontSize = 11.sp, color = MlSecondaryText) } Slider( value = pitchThrVal, @@ -1800,6 +1800,29 @@ fun PiezoMonitoringView(appState: AppState) { steps = 11, colors = SliderDefaults.colors(thumbColor = MlPrimary, activeTrackColor = MlPrimary) ) + + HorizontalDivider(modifier = Modifier.padding(vertical = dividerPadding)) + + // Wakeup Alarm toggle (Personalization 페이지 와 동일 prefs) + var wakeupEnabled by remember { + mutableStateOf(com.example.medilightv2android.services.WakeupAlarmPrefs.isEnabled(context)) + } + Row(verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.fillMaxWidth()) { + Column(modifier = Modifier.weight(1f)) { + Text("기상 알람", fontSize = labelSize, fontWeight = FontWeight.SemiBold) + Text("일어남 감지 시 빨간 팝업", + fontSize = 11.sp, color = MlSecondaryText) + } + Switch( + checked = wakeupEnabled, + onCheckedChange = { + wakeupEnabled = it + com.example.medilightv2android.services.WakeupAlarmPrefs.setEnabled(context, it) + }, + colors = SwitchDefaults.colors(checkedTrackColor = Color(0xFFD32F2F)) + ) + } } HorizontalDivider(modifier = Modifier.padding(vertical = dividerPadding))