-
Notifications
You must be signed in to change notification settings - Fork 46
Description
First of all, thank you for providing such an excellent library.
I currently have a use case: an Android phone acts as the central device, continuously scanning (with filtering rules, based on specific names) and connecting to peripheral devices. Once a target device is detected, it connects.
I'm encountering a problem: when a peripheral device disconnects and then reconnects, it reverts to the state it was in when disconnected.
I noticed that CentralManagerImpl uses managedPeripherals to cache peripheral devices. Even after a peripheral device is powered off and disconnected, rescanning still returns the cached device, and I can't reset the _state in the peripheral from the outside. Is there a way to clear or reset the state of the peripheral devices? What's the best way to implement this for my use case?
Here is my code example:
fun scan() {
centralManager.scan(Duration.INFINITE) {
Any {
Name(FILTER_NAME)
}
}.filter { seenDevicesAddress.add(it.peripheral.address) }
.map {
wrapDevice(it)
}
.onEach { newDevice ->
observePeripheralState(newDevice.peripheral, scope)
onPeripheralSelected(newDevice.peripheral)
}
.catch { e ->
}
.onCompletion {
}
.launchIn(scope)
}
private fun observePeripheralState(
peripheral: Peripheral,
scope: CoroutineScope
) {
observedPeripheralJobs[peripheral.address]?.cancel() observedPeripheralJobs . remove (peripheral.address)
val job = peripheral.state
.onEach {
when (it) {
is ConnectionState.Connected -> {
}
is ConnectionState.Disconnected -> {
}
else -> {
}
}
}
.onCompletion {
observedPeripheralJobs.remove(peripheral.address)
}
.launchIn(scope)
observedPeripheralJobs[peripheral.address] = job
}
fun onPeripheralSelected(peripheral: Peripheral, autoConnect: Boolean = false) {
val connectionScope = connectionScopeMap[peripheral]
connectionScope?.launch {
try {
peripheral.disconnect()
} catch (e: Exception) {
}
} ?: run {
connectionScopeMap[peripheral] = CoroutineScope(context = Dispatchers.IO)
.apply {
launch {
try {
withTimeout(CONNECT_TIMEOUT) {
connect(peripheral, autoConnect)
}
observeServices(peripheral, scope)
} catch (e: Exception) {
connectionScopeMap.remove(peripheral)?.cancel()
}
}
}
}
}