fix: prevent BLE freeze on NIRS streaming stop

Clear mcj callback immediately on stop to prevent stale responses from
triggering new polling chains. Delay battery polling resume by 500ms to
avoid command collision with in-flight mcj response. Add sendNirsPowerOff
for future use.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-16 11:33:57 +09:00
parent 254381dbaa
commit 3c8de65dab
2 changed files with 22 additions and 5 deletions
@@ -287,6 +287,10 @@ class BleManager private constructor(private val context: Context) {
sendRaw(CRC16.buildCommand("mta", intArrayOf(1)))
}
fun sendNirsPowerOff() {
sendRaw(CRC16.buildCommand("mta", intArrayOf(0)))
}
fun sendMqqQuery() {
sendRaw(CRC16.buildCommand("mqq"))
}
@@ -108,19 +108,29 @@ fun VivamyoMonitoringView(appState: AppState) {
handler.postDelayed(initialRetry, 2000)
}
fun stopNirsStream() {
// 1. Stop polling chain & clear callback first
nirsManager.stopStreaming()
cancelMcjRetry()
bleManager.onNirsMcjReceived = null
// 2. Resume battery polling after in-flight mcj response has time to arrive
handler.postDelayed({
bleManager.startBatteryPolling()
}, 500)
}
fun toggleStreaming() {
if (isToggling) return
isToggling = true
if (isStreaming) {
nirsManager.stopStreaming()
cancelMcjRetry()
bleManager.startBatteryPolling() // Resume battery polling
stopNirsStream()
} else {
bleManager.stopBatteryPolling() // Pause battery polling during streaming
nirsManager.startStreaming()
startNirsStream()
}
handler.postDelayed({ isToggling = false }, 500)
handler.postDelayed({ isToggling = false }, 1000)
}
LaunchedEffect(Unit) {
@@ -130,7 +140,10 @@ fun VivamyoMonitoringView(appState: AppState) {
}
}
DisposableEffect(Unit) { onDispose { nirsManager.stopStreaming(); cancelMcjRetry() } }
DisposableEffect(Unit) { onDispose {
if (nirsManager.isStreaming.value) stopNirsStream()
else { cancelMcjRetry(); bleManager.onNirsMcjReceived = null }
} }
// Clear confirm dialog
if (showClearConfirm) {