feat(firmware): 이미 연결된 기기 있으면 스캔 생략 · 바로 재연결 (cloud-mvp 19a1c12 이식)
이전 fix (47317b3) 는 진입 시 disconnect 만 했지만 사용자가 여전히
Scan → Connect 를 수동으로 눌러야 했음. UX 낭비.
이제:
1. 진입 → 이미 연결된 기기 체크 (BleManager.isConnected)
2. BluetoothDevice + name 캡처
3. 메인 앱 disconnect (프로브 광고 재개)
4. 1.5s 대기 (BLE stack 정리)
5. DfuManager.connectDirectly(device, name) — 스캔 생략
6. 사용자는 CONNECTED 상태에서 "Start DFU" 만 누르면 됨
BleManager.kt (demo-final path): currentBluetoothDevice getter 추가
DfuManager.kt: connectDirectly(device, name)
FirmwareUpdateView.kt: LaunchedEffect 개편 — 조건 분기 · delay · auto-connect
연결 없이 진입하면 기존 스캔 flow 유지.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -114,6 +114,13 @@ class BleManager private constructor(private val context: Context) {
|
|||||||
val batteryLevel = mutableStateOf(0)
|
val batteryLevel = mutableStateOf(0)
|
||||||
val bluetoothEnabled = mutableStateOf(bluetoothAdapter?.isEnabled == true)
|
val bluetoothEnabled = mutableStateOf(bluetoothAdapter?.isEnabled == true)
|
||||||
val isServiceReady = mutableStateOf(false)
|
val isServiceReady = mutableStateOf(false)
|
||||||
|
|
||||||
|
/** 현재 GATT 연결된 BluetoothDevice · 없으면 null. Firmware DFU 진입 시
|
||||||
|
* 스캔 생략하고 바로 이 기기로 재연결하는 경로에서 사용. */
|
||||||
|
val currentBluetoothDevice: android.bluetooth.BluetoothDevice?
|
||||||
|
@android.annotation.SuppressLint("MissingPermission")
|
||||||
|
get() = bluetoothGatt?.device
|
||||||
|
|
||||||
val isBonded: Boolean
|
val isBonded: Boolean
|
||||||
@android.annotation.SuppressLint("MissingPermission")
|
@android.annotation.SuppressLint("MissingPermission")
|
||||||
get() = bluetoothGatt?.device?.bondState == android.bluetooth.BluetoothDevice.BOND_BONDED
|
get() = bluetoothGatt?.device?.bondState == android.bluetooth.BluetoothDevice.BOND_BONDED
|
||||||
|
|||||||
@@ -195,6 +195,16 @@ class DfuManager(context: Context) {
|
|||||||
).also { it.connect(device.device) }
|
).also { it.connect(device.device) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 스캔 생략 · 이미 알고 있는 기기에 바로 연결 (2026-08-03).
|
||||||
|
* 메인 앱이 이미 프로브에 연결됐던 상태에서 FirmwareUpdate 진입할 때 사용.
|
||||||
|
*/
|
||||||
|
fun connectDirectly(device: BluetoothDevice, name: String) {
|
||||||
|
val scanned = ScannedDevice(device = device, name = name, rssi = 0, inDfuMode = false)
|
||||||
|
log("skip scan — using previously connected device: $name")
|
||||||
|
connect(scanned)
|
||||||
|
}
|
||||||
|
|
||||||
fun disconnect() {
|
fun disconnect() {
|
||||||
closeNus()
|
closeNus()
|
||||||
if (phase.value == DfuPhase.CONNECTED || phase.value == DfuPhase.CONNECTING) {
|
if (phase.value == DfuPhase.CONNECTED || phase.value == DfuPhase.CONNECTING) {
|
||||||
|
|||||||
@@ -91,13 +91,25 @@ fun FirmwareUpdateScreen(onBack: () -> Unit, modifier: Modifier = Modifier) {
|
|||||||
) { result -> granted = result.values.all { it } }
|
) { result -> granted = result.values.all { it } }
|
||||||
|
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
// 진입 시 메인 앱 BLE 연결 해제 — 프로브가 연결 중이면 광고 중단되어
|
|
||||||
// DfuManager 스캔에서 안 보이는 문제 해결 (2026-08-03).
|
|
||||||
runCatching {
|
|
||||||
com.medithings.vesiscan.ble.BleManager.getInstance(context).disconnect()
|
|
||||||
}
|
|
||||||
manager.loadFirmware()
|
manager.loadFirmware()
|
||||||
if (!granted) launcher.launch(perms)
|
if (!granted) {
|
||||||
|
launcher.launch(perms)
|
||||||
|
return@LaunchedEffect
|
||||||
|
}
|
||||||
|
|
||||||
|
// 이미 메인 앱이 연결된 기기가 있으면 스캔 생략 · 자동 재연결로 UX 단축 (2026-08-03).
|
||||||
|
val bleManager = com.medithings.vesiscan.ble.BleManager.getInstance(context)
|
||||||
|
val preConnectedDevice = if (bleManager.isConnected.value) bleManager.currentBluetoothDevice else null
|
||||||
|
val preConnectedName = bleManager.connectedDeviceName.value
|
||||||
|
|
||||||
|
// 메인 앱 BLE 연결 해제 — 프로브가 연결 중이면 광고 중단되어 스캔 안 보임.
|
||||||
|
runCatching { bleManager.disconnect() }
|
||||||
|
|
||||||
|
// 이미 알던 기기가 있으면 스캔 없이 바로 재연결 시도.
|
||||||
|
if (preConnectedDevice != null && preConnectedName.isNotEmpty()) {
|
||||||
|
kotlinx.coroutines.delay(1500) // BLE stack 정리 · 재광고 대기
|
||||||
|
manager.connectDirectly(preConnectedDevice, preConnectedName)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
DisposableEffect(Unit) { onDispose { manager.shutdown() } }
|
DisposableEffect(Unit) { onDispose { manager.shutdown() } }
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user