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 b4b7115..d96607b 100644 --- a/app/src/main/java/com/example/medilightv2android/ble/BleManager.kt +++ b/app/src/main/java/com/example/medilightv2android/ble/BleManager.kt @@ -418,8 +418,11 @@ class BleManager private constructor(private val context: Context) { handler.postDelayed(timer, delay) } + private var reconnectScanCallback: ScanCallback? = null + private fun attemptAutoReconnect() { - val address = lastConnectedAddress ?: return + val targetAddress = lastConnectedAddress ?: return + val targetName = debugLogger.deviceName if (bluetoothAdapter?.isEnabled != true) { onReconnectionFailed?.invoke() isReconnecting.value = false @@ -427,15 +430,69 @@ class BleManager private constructor(private val context: Context) { } reconnectAttempt++ - logd { "Attempting auto-reconnect #$reconnectAttempt to $address" } + logd { "Auto-reconnect #$reconnectAttempt: scanning for $targetName ($targetAddress)" } + debugLogger.info("RECONNECT_SCAN #$reconnectAttempt scanning for $targetName") bluetoothGatt?.let { gatt -> try { gatt.close() } catch (_: Exception) {} bluetoothGatt = null } - val device = bluetoothAdapter.getRemoteDevice(address) - bluetoothGatt = device.connectGatt(context, true, gattCallback, BluetoothDevice.TRANSPORT_LE) + // Fresh scan to find the device again + val scanner = bluetoothAdapter.bluetoothLeScanner + if (scanner == null) { + scheduleAutoReconnect() + return + } + + // Stop any previous reconnect scan + reconnectScanCallback?.let { + try { scanner.stopScan(it) } catch (_: Exception) {} + } + + val callback = object : ScanCallback() { + override fun onScanResult(callbackType: Int, result: ScanResult) { + val name = try { result.device.name ?: "" } catch (_: Exception) { "" } + val address = result.device.address + + if (address == targetAddress || (targetName.isNotEmpty() && name == targetName)) { + logd { "Reconnect scan found: $name ($address)" } + debugLogger.info("RECONNECT_FOUND $name ($address) RSSI=${result.rssi}") + + try { scanner.stopScan(this) } catch (_: Exception) {} + reconnectScanCallback = null + + // Connect directly (autoConnect=false for fast connection) + bluetoothGatt = result.device.connectGatt( + context, false, gattCallback, BluetoothDevice.TRANSPORT_LE + ) + } + } + } + reconnectScanCallback = callback + + try { + scanner.startScan(callback) + } catch (e: Exception) { + debugLogger.error("RECONNECT_SCAN_FAIL ${e.message}") + scheduleAutoReconnect() + return + } + + // Stop scan after 8 seconds → retry next attempt + handler.postDelayed({ + try { scanner.stopScan(callback) } catch (_: Exception) {} + reconnectScanCallback = null + + if (!isConnected.value && reconnectAttempt < maxReconnectAttempts) { + debugLogger.warn("RECONNECT_SCAN_TIMEOUT #$reconnectAttempt — device not found") + scheduleAutoReconnect() + } else if (!isConnected.value) { + debugLogger.reconnectFailed() + isReconnecting.value = false + onReconnectionFailed?.invoke() + } + }, 8000) } private fun cancelReconnectTimer() {