실측 로그 (2026-07-08 11:18~11:19) 분석: mtb 응답 stream (reb×6 + raa
+ rim, 총 8개 패킷) 중간에 msn (battery) / mim (IMU) 이 TX 로 끼어들면
firmware GATT queue 가 꼬여 응답 실종 → 이어지는 mls mode 0 명령에서
완전 freeze (BLE 광고까지 중단, 재연결 10회 모두 실패).
핵심 원인:
- BleManager 의 batteryTimer / mim polling 이 시간 간격 기반이라 mtb
응답 진행 중에도 무조건 TX 발사.
- 특히 sendImuFifoQuery 는 imuCollector.reset() 을 먼저 호출 → mtb 의
rim (IMU) 이 파괴됨.
Layer 1 — BleManager gating
- isMtbBusy 프로퍼티 추가 (piezoCollector.isMultiChannel && !isComplete)
- batteryTimer / batteryRetryTimer: sendBatteryQuery 앞에 isMtbBusy skip
- Watchdog silence heartbeat: sendImuQuery (msp) → sendImuFifoQuery
(mim) 로 교체 + isMtbBusy skip
- sendImuQuery 함수 자체 삭제 — msp 명령 코드에서 완전 제거
(rsp 파서는 legacy 응답용 유지)
Layer 2 — PiezoMonitoringView mim polling gating
- LaunchedEffect while 루프의 sendImuFifoQuery 앞에 isMtbBusy skip
Layer 3 — mtb 3초 timeout + UI 안내
- sendMtb: 3초 timeout runnable, raa 응답 오면 취소
- lastMtbTimeoutAt / consecutiveMtbTimeouts state 노출
- PlacementGuideView 가 관찰 → 1~2회: "기기 응답 지연" 안내
3회 연속: "재연결" 안내 + forceDisconnectAndReconnect 자동 호출
- forceDisconnectAndReconnect 를 public 으로 승격
부가:
- disconnect 3곳 (GATT_ERROR / STATE_DISCONNECTED / watchdog forced)
에서 mtbTimeoutRunnable 도 함께 정리.
Firmware VBTFW0121 의 mls mode 0 handler 취약점은 별도로 펌웨어 팀에
리포트 필요 (본 fix 는 큐 혼잡 방지로 근본적으로 회피).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
PiezoMonitoringView 도넛차트 상단 posture chip 문구.
NON_LYING 표시 텍스트를 이전에 사용하던 '일어남' 으로 복원.
영문 (Upright) 은 그대로 유지.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
증상:
1. Sensor Alignment 완료 GREEN 진입 후 일정 시간 (약 7초 hold 종료 +
추가 몇 초) 지나면 UI 가 갑자기 "단계 0/3 / 정렬 시작" 으로
초기화되어 처음부터 재시작해야 하는 불쾌한 UX.
2. GREEN 문구 "제 위치입니다!" 가 다소 어색.
원인:
PlacementGuideView V1 로직 (line 1098) 의 3-strike 규칙 —
`greenHeld` (7초 hold) 종료 후 `guideResult.isPass=false` 가 **3회
연속** 나오면 전체 리셋 (isLocked=false, waitingForStart=true,
scanCount=0, phase=VERTICAL, rTracker.reset() ...). 그런데 사용자가
GREEN 상태에서 버튼 안 누르고 그대로 기다리면 자연스러운 미세 자세
흔들림 (1~2초) 만으로 3회 실패 성립 → 완전 리셋.
수정:
1. `placement_in_position` "제 위치입니다!" → "최적의 위치입니다!"
(영문: "In position!" → "Optimal position!").
2. 3-strike → 10-strike 완화. 10회 연속 실패 (약 5초+) 는 되어야
진짜 이탈로 간주. 그 사이는 GREEN 유지 + "최적의 위치입니다" 표시.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
인체 데이터 (data123/) 분석 결과 CH3 (-13.66° down-tilt) 검출률이
Phantom 95.2% → Human 31.8% 로 급락하며 YYNNYY flick 패턴 관측.
기존 "3연속 hit" 진입 조건이 무한 대기에 빠져 사용자에게
"↑ 위로 조금씩" 문구만 반복 노출되는 문제를 해결.
- VERTICAL_CLIMB 진입: 3연속 → 최근 6프레임 중 3회 (majority)
- CH3_STABILIZE / CENTER_OPTIMIZE lost 판정: 4프레임 중 3회 (majority)
- Stuck detection (20프레임 ≈ 5초 대기 시): 상단 3채널 relaxed mode
진입 → CH3 없이도 정렬 완료 진행
- Soft hint (12프레임 ≈ 3초 후): "CH3 확인 중 · 위치 유지/미세 조정"
으로 문구 완화 (사용자 답답함 완화)
- AdvisorState.relaxedMode 플래그 추가 (후속 저장 로직 대비)
Python replay (VBT26050202_0CM 22프레임) 로 검증:
- LEGACY: VERTICAL 무한 대기 → 정렬 실패
- NEW: soft-hint → threshold 도달 시 relaxed → 3프레임 만에 LR_BAL 도달
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
이전 sweep 에서 누락됐던 두번째 '기기 연결' 화면 풀 한글화.
추가 strings: 25 신규 (각 언어)
- '기기 연결' 제목, 검색/탭 안내
- 페어링 필요 알림 (다이얼로그 + 에러 메시지)
- Bluetooth off / 권한 필요 경고
- 검색 중 / 기기 없음 / 트러블슈팅 4단계
- 저장된 기기 / 새 기기 섹션
- 권한 허용 / 검색 시작·중지 버튼
- 최근, 페어링 삭제, 신호 좋음/보통/약함
설계:
- signalLabel(rssi) → 영어 — dev/log 용 유지
- signalLabelRes(rssi) 신규 — UI 용 Locale-aware 라벨
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
이전 Phase 2 에서 'already English-only' 라며 skip 했던 화면들 — 노인 사용자에게는 영어로
보이면 안 됨. 전체 다시 훑어 모든 user-visible 영어 hardcoded text 를 strings.xml 로 추출.
11 파일 수정:
- MainActivity (Exit dialog)
- HomeView (Smart Bladder Monitoring / Start / Connected / Clinical Mode / dev toast)
- OnboardingView (Welcome, Get Started 등)
- CalibrationView (모든 status + Retry/Skip/Continue)
- SensorSelectView (title, descriptions)
- ShuffledKeypad (Delete contentDescription)
- MeasurementHistoryView (title, tabs, empty state, Today/Yesterday)
- VivamyoMonitoringView (전체 status)
- PiezoMonitoringView (사용자 영역 — Auto/Single Scan, Voiding/Catheterization, 측정 카드, dialog 등)
- PlacementGuideView (V1 hints, Step indicator, Start/Skip/Complete Alignment, In position/Position lost)
추출 strings: ~170 (각 언어). strings.xml 194 → 365 라인.
skip 유지:
- ClinicalHomeView / ClinicalLiveView (R&D dev mode)
- PiezoMonitoring dev panel sliders (3-tap 활성화 dev 도구)
- PlacementGuide dev settings overlay + Echo Waveforms (isDevMode gated)
- BLE Debug Log / Scan Log dialog (dev 전용)
- 브랜드명 (VesiScan-Basic, Vivamyo, Bladdy)
- DEMO 배지, IMU debug 문자열, Log.d / debugLogger 출력
Korean coverage: ~95% (일반 사용자가 절대 보지 않는 dev surface 만 영어 유지).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
자산:
- drawable/arrow_transparent.png 신규 (132×112 RGBA, 우향 thin arrow)
코드:
- drawLine 3개로 구성하던 화살표 → drawImage(arrowBitmap) 한 번으로 교체
- 4방향은 rotate(degrees, pivot) 로 처리:
right=0° / down=90° / left=180° / up=-90°
- ColorFilter.tint(#E64A19 × arrowAlpha) — 일러스트 톤 매칭 + blink 유지
- arrowDrawW=90f, 높이는 icon aspect(132:112)로 비례
- center 위치는 bladder oval edge + sensorHalfH + gap + arrowSize/2
기존 blink 로직(scanCount % 2 → animateFloatAsState 180ms)은 그대로 동작 —
tint color 의 alpha 에 arrowAlpha 를 곱하므로 PNG 도 매 refresh 깜빡임.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
자산:
- drawable-xxhdpi/body_silhouette.png 신규 (finalstomachillust.png, 2240×1888 ≈ 7:6)
feature/tab-navigation 의 일러스트와 동일 — bezier 토르소를 PNG로 교체
UI:
- Top bar: Box overlay 구조로 ← + "Sensor Alignment" 화면 절대 가운데 (26sp ExtraBold)
- 본문 큰 타이틀(36sp) 제거 — top bar 와 중복
- Body 영역: bezier silhouette → Image(painter=body_silhouette) + 얇은 Canvas overlay
Canvas 는 oval(방광) + sensor PNG + 방향 화살표만 담당
- 비율 .aspectRatio(2240f / 1888f) 고정 → 화면비 무관 portrait 유지
화살표 refresh blink (사용자 요청):
- scanCount % 2 토글 → animateFloatAsState(1f ↔ 0.35f, tween 180ms)
- 매 cycle 마다 화살표 alpha 가 깜빡임 → "업데이트 됐는지" 시각화
- 색감 #FF5722 → #E64A19 (deep orange 700, 일러스트 톤 매칭)
- StrokeCap.Round + 굵기 9→10 (가독성)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- 앱 아이콘: 방광이.png로 교체 (webp→png, adaptive-icon 제거)
- Placement: "Centering" → "Checking", "LR balanced. Final check" → "Final check"
- 모든 방향 힌트에 화살표(↑↓←→) 추가 — phaseProtected 시 아이콘 추론 보장
- 디바운스 중에도 directionIcon은 최신 guideResult로 갱신 (화살표 누락 수정)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Cross-channel urine length outlier: median의 1.35x 초과 또는 0.5x 미만 → 제거
(CH3 바닥반사 urine=50 vs 정상 ~35 → 480ml↔223ml 편차 해결)
- Placement CV: V0=0.07, V1/V2=0.10 (기기별 분기)
- Placement 기준 강화: LR dev 0.20, gradient 0.3, lenVariation 0.35
- "방향OK→무조건GREEN" 제거, CV 미달시 "Fine-tune position"
- GREEN CV가이드/Hold steady 제거, ch별 len 분석 방향 안내
- 가이드 텍스트 상자 항상 표시
- 센서 이미지 topview 교체 (240×150dp)
- 앱 버전 VBTAND0101
- Plot/Log allWalls 통일 (선택 Method 기준)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
이미지:
- 센서 사진(vesiscanbasicimage.png) 오버레이 (200×125dp)
- 전체 영역 500dp로 확대
- 타원 높이 절반 + 위쪽 경계 고정
- 센서 위치 미세 조정 (x+5dp)
화살표:
- 타원 바깥 경계에 부착 (gap=12)
- 두께 5→7, 머리 18→20, 색상 #FF5722
- 상하좌우 타원 경계 기준 위치
텍스트:
- 전체 영어화 (Gradually raise/lower, Move right/left 등)
- "Sensor Placement" → "Sensor Alignment"
- "Placement Complete" → "Alignment Complete"
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Placement:
- Canvas 실루엣 → 하복부 일러스트 PNG 배경 (투명 배경 처리)
- 방광+센서+화살표는 Canvas 오버레이 유지
- GREEN 진입/이탈 즉시 반영 (디바운스 무시)
- 좌측 라벨(가슴/배꼽/치골) 제거
Spot 측정:
- 3회 측정 중 화면 깜빡임 방지 (이전 값 유지, 최종 median만 표시)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace hardcoded Korean UI strings in Piezo, CatheterizeSheet,
VoidingDiary, and UrineCameraScreen with stringResource() calls.
Add values/strings.xml (English) and values-ko/strings.xml (Korean).
System language setting now controls app language.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Force light theme only, block Samsung Force Dark Mode via forceDarkAllowed=false,
and add explicit text colors to prevent invisible text on light backgrounds.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Port of MedilightV2 iOS app to Android with Kotlin + Jetpack Compose.
Includes BLE connectivity, NIRS/Piezo sensor modes, Rive animations,
interactive measurement history charts, and foldable device support.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>