diff --git a/app/src/main/java/com/example/medilightv2android/managers/GreenZoneConstants.kt b/app/src/main/java/com/example/medilightv2android/managers/GreenZoneConstants.kt index 8eabc99..f373b96 100644 --- a/app/src/main/java/com/example/medilightv2android/managers/GreenZoneConstants.kt +++ b/app/src/main/java/com/example/medilightv2android/managers/GreenZoneConstants.kt @@ -36,8 +36,13 @@ object GreenZoneConstants { /** Posture acc magnitude gate max (g). 이 값 초과면 classifier UNKNOWN. */ @Volatile var postureAccMagMax: Float = 1.2f - /** Posture polling 간격 (ms). PiezoMonitoring 에서 mtb 보내는 주기. dev 모드에서 조정 가능. */ - @Volatile var posturePollIntervalMs: Long = 1000L + /** + * Posture polling 간격 (ms). PiezoMonitoring 에서 msp 보내는 주기. + * 6/30 변경: mtb (1Hz × 15sample) → msp (5Hz × 1sample) 로 전환. piezo burst 가청음 제거. + * Walking detector 의 1.5초 window 안에 7-8 sample 확보 위해 200ms 주기. + * dev 모드에서 조정 가능. + */ + @Volatile var posturePollIntervalMs: Long = 200L // ── Walking detector 임계값 (flowchart 4-2 / 5-2) ───────────────── /** Walking 인정 최소 pitch (deg). |pitch| > 이 값 이라야 walking 후보. */ 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 a825a66..b22c0f5 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 @@ -719,10 +719,11 @@ fun PiezoMonitoringView(appState: AppState) { com.example.medilightv2android.services.PostureEventLogger.startSession(context) } - // IMU polling + 자세 분류 (Phase 1) — 10초 주기로 mtb 명령 → rim: 응답 받아 분류. - // msp 가 펌웨어에서 rsp: 응답 안 보내는 듯해 mtb (alignment) 로 우회. - // mtb 는 piezo measurement 도 트리거하므로 piezoCollector.skipNextComplete 로 - // user 의 측정 callback 가 spurious fire 되는 거 차단. + // IMU polling + 자세 분류 — msp 명령 (rsp: 응답, IMU-only). + // 6/30: 이전엔 mtb (piezo 6ch + IMU) 폴링으로 매 cycle piezo burst 가청음 발생. + // 사용자앱에서 msp 의 rsp: 응답 정상 (실측 VBTFW0120, 18B = tag+12B sample+crc) 확정 후 + // 데모도 동일 적용. WalkingDetector window (1.5초) 확보 위해 폴링 주기 1000→200ms. + // 둘 다 imuCollector.parseRsp/parseRim 가 같은 onComplete 콜백 트리거 → classifier 동일. LaunchedEffect(isConnected, isDemoMode) { Log.d("ImuDbg", "LaunchedEffect start isConnected=$isConnected isDemoMode=$isDemoMode") if (isDemoMode) { @@ -780,20 +781,16 @@ fun PiezoMonitoringView(appState: AppState) { Log.d("ImuDbg", "imuCollector log: $msg") } while (isActive) { - // Auto Scan 의 cycle 사이 idle 시간에도 polling 가능 — isAutoMeasuring 조건 제외. - // isMeasuring 은 현재 measure() 호출 중인 짧은 시간만 true → 사이 idle 에서 mtb 가능. - // isSpotInProgress 는 5회 연속 측정이라 분리 (충돌 회피). - // 이전: Auto Scan 켜두면 isAutoMeasuring=true 영원 유지 → mtb 영원 skip → posture UNKNOWN + // msp 는 piezo burst 없는 IMU-only — Auto/Single Scan 중에도 충돌 없이 가능. + // 단 isMeasuring (현재 measure() 호출 중) / isSpotInProgress 짧은 시간만 skip + // (BLE 큐 충돌 방어). + // Auto Scan 자체는 mtb 응답에 IMU 가 들어있어 자동으로 posture 갱신됨 (parseRim). if (isConnected && !isMeasuring && !isSpotInProgress) { - Log.d("ImuDbg", "→ sendMtb (posture poll)") - bleManager.piezoCollector.skipNextComplete = true - val sent = bleManager.sendMtb() - if (!sent) { - bleManager.piezoCollector.skipNextComplete = false // throttled, no response coming - Log.d("ImuDbg", "mtb throttled — skip this cycle") + if (!isAutoMeasuring) { + // idle — msp polling (무음) + bleManager.sendImuQuery() } - } else { - Log.d("ImuDbg", "skip (connected=$isConnected measuring=$isMeasuring spot=$isSpotInProgress)") + // isAutoMeasuring=true 면 mtb 의 rim: 가 알아서 posture 갱신, msp skip } kotlinx.coroutines.delay(GreenZoneConstants.posturePollIntervalMs) }