fix: GATT 에러로 끊길 때도 자동 reconnect 시작 (핵심 버그 수정)

근본 원인: Android BLE가 disconnect 시 STATUS_DISCONNECTED가 아닌
GATT 에러(status≠0)로 콜백을 보냄. 기존 에러 경로에서는
reconnectAttempt>0일 때만 재연결 → 첫 끊김 시 재연결 안 됨.

수정:
- wasConnected 체크: 이전에 연결됨 + 사용자 disconnect 아님 → 자동 reconnect
- GATT_ERROR 로그 + DISCONNECTED(gatt_error) 로그 기록
- stopBatteryPolling/stopWatchdog 호출 추가
- watchdog: connected=false 감지 시 무한 루프 대신 break

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-23 15:13:11 +09:00
parent d3006d91dc
commit a474935e3c
@@ -376,9 +376,14 @@ class BleManager private constructor(private val context: Context) {
}
val silenceMs = System.currentTimeMillis() - lastRxTimestamp
debugLogger.info("WATCHDOG_CHECK silence=${silenceMs}ms connected=${isConnected.value}")
val connected = isConnected.value
debugLogger.info("WATCHDOG_CHECK silence=${silenceMs}ms connected=$connected")
if (!isConnected.value) continue
// connected=false면 정상 경로에서 이미 처리됨 → watchdog 종료
if (!connected) {
debugLogger.info("WATCHDOG_STOP — already disconnected (handled by GATT callback)")
break
}
if (silenceMs > watchdogTimeoutMs) {
// 직접 로그 기록 (handler 블로킹 무관)
@@ -551,7 +556,12 @@ class BleManager private constructor(private val context: Context) {
connectionTimer = null
if (status != BluetoothGatt.GATT_SUCCESS && newState != BluetoothProfile.STATE_CONNECTED) {
loge { "GATT connection failed with status: $status" }
val wasConnected = isConnected.value
loge { "GATT error: status=$status newState=$newState wasConnected=$wasConnected" }
debugLogger.error("GATT_ERROR status=$status newState=$newState wasConnected=$wasConnected")
stopBatteryPolling()
stopWatchdog()
bluetoothGatt = null
txCharacteristic = null
rxCharacteristic = null
@@ -563,7 +573,11 @@ class BleManager private constructor(private val context: Context) {
gatt.close()
if (reconnectAttempt > 0 && lastConnectedAddress != null) {
if (wasConnected && lastConnectedAddress != null && !isUserDisconnect) {
debugLogger.disconnected("gatt_error", status)
onUnexpectedDisconnect?.invoke()
scheduleAutoReconnect()
} else if (reconnectAttempt > 0 && lastConnectedAddress != null) {
scheduleAutoReconnect()
} else {
isReconnecting.value = false