From cac3712b8c266934782c8519ef89d4633570229e Mon Sep 17 00:00:00 2001 From: jjangddu Date: Tue, 26 May 2026 08:53:43 +0900 Subject: [PATCH] =?UTF-8?q?BLE:=20maa=20throttle=EC=9D=84=20state-based=20?= =?UTF-8?q?=EA=B2=8C=EC=9D=B4=ED=8A=B8=EB=A1=9C=20=EA=B0=95=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 이전 응답이 완료되기 전에 새 maa가 송신되면 piezoCollector.startMultiChannel(6)이 호출되며 collector가 reset → 큐에 떠다니던 reb 패킷이 폐기되어 BV_FAIL/BV_SKIP가 발생하던 문제 대응. 변경: - 시간 단독 게이트(800ms) → state + 시간 복합 게이트 - (A) piezoCollector.isMultiChannel && !isComplete 이면 차단 단 5초 넘으면 강제 통과(영영 deadlock 방지) - (B) 최소 간격 800ms → 1500ms (펌웨어 응답 시간 ~1.2~1.4s 반영) - sendAllChannels/sendChannelsOnly가 공유하는 canSendMaa() 헬퍼로 일원화 Co-Authored-By: Claude Opus 4.7 (1M context) --- .../medilightv2android/ble/BleManager.kt | 37 +++++++++++++------ 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/com/example/medilightv2android/ble/BleManager.kt b/app/src/main/java/com/example/medilightv2android/ble/BleManager.kt index cae3652..6c20636 100644 --- a/app/src/main/java/com/example/medilightv2android/ble/BleManager.kt +++ b/app/src/main/java/com/example/medilightv2android/ble/BleManager.kt @@ -400,12 +400,8 @@ class BleManager private constructor(private val context: Context) { } fun sendAllChannels(mode: Int = 0): Boolean { - val now = System.currentTimeMillis() - if (now - lastMaaSentMs < 800) { - android.util.Log.w("BleManager", "maa THROTTLED — ${now - lastMaaSentMs}ms since last") - return false - } - lastMaaSentMs = now + if (!canSendMaa("sendAllChannels")) return false + lastMaaSentMs = System.currentTimeMillis() piezoCollector.startMultiChannel(6) sendRaw(CRC16.buildCommandASCII("maa", " ")) return true @@ -457,15 +453,34 @@ class BleManager private constructor(private val context: Context) { sendRaw(CRC16.buildCommandASCII("mbb", " ")) } - /** 6채널 측정만 (maa) — 최소 800ms 간격 throttle */ + /** + * 6채널 측정 명령(maa) 송신 가능 여부: + * (A) 이전 응답이 아직 진행 중(isMultiChannel && !isComplete)이면 차단. + * 단 5초 넘게 응답이 안 오면 강제 통과(영영 deadlock 방지). + * (B) 마지막 송신으로부터 1500ms 미만이면 차단(펌웨어 burst 방어). + */ private var lastMaaSentMs = 0L - fun sendChannelsOnly(): Boolean { + private fun canSendMaa(caller: String): Boolean { val now = System.currentTimeMillis() - if (now - lastMaaSentMs < 800) { - android.util.Log.w("BleManager", "maa THROTTLED — ${now - lastMaaSentMs}ms since last") + val collectorBusy = piezoCollector.isMultiChannel && !piezoCollector.isComplete + val sinceLast = now - lastMaaSentMs + if (collectorBusy) { + if (sinceLast < 5000) { + android.util.Log.w("BleManager", "maa BUSY [$caller] — prev response in progress (${sinceLast}ms)") + return false + } + android.util.Log.w("BleManager", "maa FORCE [$caller] — prev incomplete after ${sinceLast}ms, abandoning") + } + if (sinceLast < 1500) { + android.util.Log.w("BleManager", "maa THROTTLED [$caller] — ${sinceLast}ms since last") return false } - lastMaaSentMs = now + return true + } + + fun sendChannelsOnly(): Boolean { + if (!canSendMaa("sendChannelsOnly")) return false + lastMaaSentMs = System.currentTimeMillis() piezoCollector.startMultiChannel(6) sendRaw(CRC16.buildCommandASCII("maa", " ")) return true