@@ -95,6 +95,8 @@ abstract class Peripheral<ID: Any, EX: Peripheral.Executor<ID>>(
9595 *
9696 * This is not-null when the device is connected or was connected using auto connect,
9797 * that is when any GATT event for the device, including connection state change, is expected.
98+ *
99+ * It's set to `null` when the peripheral is closed.
98100 */
99101 private var gattEventCollector: Job ? = null
100102
@@ -200,7 +202,9 @@ abstract class Peripheral<ID: Any, EX: Peripheral.Executor<ID>>(
200202 * Returns `true` if the peripheral is disconnected of getting disconnected.
201203 */
202204 val isDisconnected: Boolean
203- get() = state.value is ConnectionState .Disconnected || state.value is ConnectionState .Disconnecting
205+ get() = state.value is ConnectionState .Disconnected ||
206+ state.value is ConnectionState .Disconnecting ||
207+ state.value is ConnectionState .Closed
204208
205209 /* *
206210 * Waits until the given condition is met.
@@ -266,6 +270,7 @@ abstract class Peripheral<ID: Any, EX: Peripheral.Executor<ID>>(
266270 impl.close()
267271 _state .update { ConnectionState .Closed }
268272 }
273+ gattEventCollector = null
269274 }
270275
271276 /* *
@@ -476,36 +481,47 @@ abstract class Peripheral<ID: Any, EX: Peripheral.Executor<ID>>(
476481 * @throws SecurityException If BLUETOOTH_CONNECT permission is denied.
477482 */
478483 suspend fun disconnect () {
479- // Check if the peripheral isn't already disconnected or has a pending disconnection.
480- state.value.let { currentState ->
481- if (currentState is ConnectionState .Disconnected ) {
482- // Make sure the AutoConnect also gets cancelled if the peripheral is currently disconnected.
483- close()
484+ // Depending on the state...
485+ when (state.value) {
486+ is ConnectionState .Closed -> {
487+ // Do nothing when already closed.
484488 return
485489 }
486- if (currentState is ConnectionState .Disconnecting ) {
487- waitUntil { it is ConnectionState .Disconnected }
490+ is ConnectionState .Disconnected -> {
491+ // Make sure auto-connection is closed.
492+ close()
488493 return
489494 }
495+ is ConnectionState .Disconnecting -> {
496+ // Skip..
497+ }
498+ is ConnectionState .Connecting -> {
499+ // Cancel the connection attempt.
500+ logger.trace(" Cancelling connection to {}" , this )
501+ _state .update { ConnectionState .Disconnecting }
502+ impl.disconnect()
503+ }
504+ is ConnectionState .Connected -> {
505+ // Disconnect from the peripheral.
506+ logger.trace(" Disconnecting from {}" , this )
507+ _state .update { ConnectionState .Disconnecting }
508+ impl.disconnect()
509+ }
490510 }
491511
492- // Disconnect from the peripheral.
493- logger.trace(" Disconnecting from {}" , this )
494- _state .update { ConnectionState .Disconnecting }
495- if (impl.disconnect()) {
496- try {
497- waitUntil(500 .milliseconds) { it is ConnectionState .Disconnected }
498- } catch (e: TimeoutCancellationException ) {
499- logger.warn(" Disconnection takes longer than expected, closing" )
512+ // If the peripheral is disconnecting, wait until it is disconnected and close.
513+ try {
514+ if (! impl.isClosed) {
515+ waitUntil(500 .milliseconds) { it.isDisconnected }
500516 }
501- } else {
502- // Update the state if disconnect() returned false.
503- _state .update {
504- ConnectionState .Disconnected (ConnectionState .Disconnected .Reason .Success )
517+ } catch (e: TimeoutCancellationException ) {
518+ if (! isDisconnected) {
519+ logger.warn(" Disconnection takes longer than expected, closing" )
505520 }
521+ } finally {
522+ close()
523+ logger.info(" Disconnected from {}" , this )
506524 }
507- close()
508- logger.info(" Disconnected from {}" , this )
509525 }
510526
511527 // Other
0 commit comments