From 464bbfff0665499245add82b1f183319cb50fbc4 Mon Sep 17 00:00:00 2001 From: jjangddu Date: Thu, 13 Aug 2026 11:41:53 +0900 Subject: [PATCH] =?UTF-8?q?feat(dev):=20=EC=95=B1=20=EC=A2=85=EB=A3=8C=20?= =?UTF-8?q?=EC=8B=9C=20=EC=9E=90=EB=8F=99=20=ED=8E=98=EC=96=B4=EB=A7=81=20?= =?UTF-8?q?=ED=95=B4=EC=A0=9C=20(=EB=8B=A4=EC=A4=91=20=ED=8F=B0=C3=97?= =?UTF-8?q?=EA=B8=B0=EA=B8=B0=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20workflow=20?= =?UTF-8?q?=EC=9E=90=EB=8F=99=ED=99=94)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 배경 (사용자 관찰): · 폰 A ↔ 기기 A 페어링 후 앱 종료 · 폰 B 로 기기 A 접근 시 실패. · 폰 B 에서 "저장된 기기" 삭제해도 기기 A 는 폰 A bond 만 신뢰 · 물리 리셋 필요. · 매번 수동으로 Settings > "페어링 해제" 누르기 번거로움 · 잊기 쉬움. 수정: 1. GreenZoneConstants.autoUnbondOnAppExit: Boolean = false (신규) dev-mode 용 flag · 앱 종료 시 자동 unbond 여부. 2. MainActivity.onDestroy() 훅 flag ON + 연결된 기기 있으면 → BleManager.disconnectAndUnbond() 자동 실행. 기기측 msr(unbond+reboot) + 폰측 removeBond · fresh state 유지. 3. PiezoMonitoringView Settings (dev-mode 조건부) "Delete Pairing" 버튼 아래에 토글 카드: "앱 종료 시 자동 페어링 해제" 설명: "[dev] 다중 폰×기기 테스트용 · 종료 시 unbond" 효과: · 폰 A 앱 종료 → 자동 unbond msr 전송 → 기기 A clean · 폰 B 접근 시 fresh pairing 즉시 성공 · 매뉴얼 clean 도 여전히 Delete Pairing 버튼으로 즉시 실행 가능 (기존) 주의: · default OFF (일반 사용자 flow 는 bond 유지가 UX 이점) · onDestroy 는 앱 강제종료 시 스킵 가능 · 정상 종료 (뒤로가기/스와이프) 는 커버 · try/catch silent · 종료 시점 실패는 UC-05 (필수기능 아님) 빌드: BUILD SUCCESSFUL 1m 15s. --- .../com/medithings/vesiscan/MainActivity.kt | 22 +++++++++++++ .../vesiscan/managers/GreenZoneConstants.kt | 14 +++++++++ .../views/monitoring/PiezoMonitoringView.kt | 31 +++++++++++++++++++ 3 files changed, 67 insertions(+) diff --git a/app/src/main/java/com/medithings/vesiscan/MainActivity.kt b/app/src/main/java/com/medithings/vesiscan/MainActivity.kt index 0fda484..f6ff681 100644 --- a/app/src/main/java/com/medithings/vesiscan/MainActivity.kt +++ b/app/src/main/java/com/medithings/vesiscan/MainActivity.kt @@ -82,6 +82,28 @@ class MainActivity : ComponentActivity() { } } } + + /** + * 2026-08-12: 테스트 세션 종료 시 자동 페어링 해제 (dev-mode 용). + * + * `GreenZoneConstants.autoUnbondOnAppExit` ON 이고 · 연결된 기기가 있으면 + * `disconnectAndUnbond()` 실행 → 기기측 msr(unbond+reboot) + 폰측 removeBond. + * 다음 실행 (다른 폰) 에서 fresh pairing 가능하도록 clean state 유지. + * + * onDestroy 는 앱 강제종료 시 스킵될 수 있으나 · 정상 종료 (뒤로가기 · 홈 스와이프 + * 후 recent 앱에서 swipe away) 는 커버. dev-mode 테스트 workflow 는 대부분 정상 종료. + */ + override fun onDestroy() { + try { + if (com.medithings.vesiscan.managers.GreenZoneConstants.autoUnbondOnAppExit) { + val ble = com.medithings.vesiscan.ble.BleManager.getInstance(applicationContext) + if (ble.isConnected.value) { + ble.disconnectAndUnbond() + } + } + } catch (_: Exception) { /* silent · 종료 시점 · UC-05 */ } + super.onDestroy() + } } @Composable diff --git a/app/src/main/java/com/medithings/vesiscan/managers/GreenZoneConstants.kt b/app/src/main/java/com/medithings/vesiscan/managers/GreenZoneConstants.kt index e9aac09..9ed449e 100644 --- a/app/src/main/java/com/medithings/vesiscan/managers/GreenZoneConstants.kt +++ b/app/src/main/java/com/medithings/vesiscan/managers/GreenZoneConstants.kt @@ -71,6 +71,20 @@ object GreenZoneConstants { @Volatile var placementGuideMode: PlacementGuideMode = PlacementGuideMode.SIMPLE @Volatile var alignmentAlgo: AlignmentAlgo = AlignmentAlgo.V1 // default V1 (일반 사용자). V2 (Method D) 는 clinical alignment session 전용. + /** + * 2026-08-12: 테스트 세션 종료 시 자동 페어링 해제 (dev-mode 용). + * + * ON 시 · MainActivity.onDestroy() 에서 연결된 기기가 있으면 자동으로 + * disconnectAndUnbond() 호출. 여러 폰 × 여러 기기 테스트 환경에서 매번 수동으로 + * 페어링 해제할 필요 없이 앱 종료만 하면 기기 clean state 유지. + * + * 시나리오: 폰 A 로 기기 A 테스트 → 앱 종료 → 자동 unbond msr 전송 → + * 기기 A 는 폰 A bond 삭제 → 다음에 폰 B 가 기기 A 와 fresh pairing 성공. + * + * default OFF (일반 사용자 flow 는 bond 유지가 UX 이점 · 잘못 켜지면 매번 재페어링). + */ + @Volatile var autoUnbondOnAppExit: Boolean = false + /** Posture pitch 임계값 (deg). |pitch| > 이 값 → LYING, ≤ 이 값 → NON_LYING. dev 모드에서 조정 가능. */ @Volatile var pitchLyingThreshold: Float = 25f diff --git a/app/src/main/java/com/medithings/vesiscan/ui/views/monitoring/PiezoMonitoringView.kt b/app/src/main/java/com/medithings/vesiscan/ui/views/monitoring/PiezoMonitoringView.kt index ab8cc79..3b2b698 100644 --- a/app/src/main/java/com/medithings/vesiscan/ui/views/monitoring/PiezoMonitoringView.kt +++ b/app/src/main/java/com/medithings/vesiscan/ui/views/monitoring/PiezoMonitoringView.kt @@ -2403,6 +2403,37 @@ fun PiezoMonitoringView(appState: AppState) { ) } + // 2026-08-12: 다중 폰 × 다중 기기 테스트 workflow 자동화 (dev-mode 전용). + // ON 시 · MainActivity.onDestroy() 에서 자동으로 disconnectAndUnbond(). + // 다음 실행 (다른 폰) 에서 fresh pairing 성공 · 매번 수동 unbond 불필요. + if (appState.isDevMode) { + Spacer(modifier = Modifier.height(6.dp)) + var autoUnbond by remember { + mutableStateOf(com.medithings.vesiscan.managers.GreenZoneConstants.autoUnbondOnAppExit) + } + Row( + modifier = Modifier.fillMaxWidth() + .background(MlPrimary.copy(alpha = 0.05f), RoundedCornerShape(10.dp)) + .padding(horizontal = 12.dp, vertical = 6.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + Column(modifier = Modifier.weight(1f)) { + Text("앱 종료 시 자동 페어링 해제", + fontSize = 13.sp, fontWeight = FontWeight.SemiBold) + Text("[dev] 다중 폰×기기 테스트용 · 종료 시 unbond", + fontSize = 10.sp, color = MlSecondaryText) + } + Switch( + checked = autoUnbond, + onCheckedChange = { + autoUnbond = it + com.medithings.vesiscan.managers.GreenZoneConstants.autoUnbondOnAppExit = it + }, + colors = SwitchDefaults.colors(checkedTrackColor = MlPrimary), + ) + } + } + Spacer(modifier = Modifier.height(8.dp)) HorizontalDivider(modifier = Modifier.padding(vertical = dividerPadding)) Spacer(modifier = Modifier.height(8.dp))