Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug with connection #120

Open
MkhytarMkhoian opened this issue Feb 12, 2024 · 5 comments
Open

Bug with connection #120

MkhytarMkhoian opened this issue Feb 12, 2024 · 5 comments
Labels
bug Something isn't working

Comments

@MkhytarMkhoian
Copy link

MkhytarMkhoian commented Feb 12, 2024

In the tutorial, you say that the connect function is suspended and waits until device is in connected state, but it's not true. I've got the exception STATE_DISCONNECTED when calling discoverServices right after connect.
To solve this problem, I use callbacks instead of relying on the described behavior above.

This happened because BLE asynchronous itself under the hood. Could we fix API or make clear documentation?

    // Connect a Bluetooth LE device. This is a suspend function that waits until device is in connected state.
    val connection = blinkyDevice.connect(context) // blinkyDevice from scanner

    // Discover services on the Bluetooth LE Device. This is a suspend function which waits until device discovery is finished.
    val services = connection.discoverServices()
@philips77 philips77 added the bug Something isn't working label Feb 26, 2024
@0x7061
Copy link

0x7061 commented Mar 25, 2024

I've encountered the same problem, solved it using a suspendCancellableCoroutine() and resolving the future once the connection state changes to CONNECTED.

However, I feel a suspending connect function is not a good design, as there is no proper way to close the gatt without its reference, see #135

@philips77
Copy link
Member

Hi,
I'm refactoring the library. A lot of things will change. I'll make sure that connect behaves as in the documentation.

@duranaustin
Copy link

any update on this? tried following the documentation outlined in the README and experiencing the same exact thing. @philips77 Thanks for all your help.

@asiljan
Copy link

asiljan commented Nov 27, 2024

@0x7061 Could you maybe provide some example of how you solved this issue with connecting to the ble device using suspendCancellableCoroutine since have similar issue here with calling connect with client side timeout.

@duranaustin
Copy link

duranaustin commented Nov 27, 2024

@asiljan Others may have better solutions but here is an example of what you could do. Obviously this is specific to our needs but you can play around with it and adjust as needed.

 @SuppressLint("MissingPermission")
    fun getAdvertisementServiceImei(
        serverDevice: ServerDevice,
        onSetImei: (String?) -> Unit,
    ) {
        _bluetoothUiState.update {
            it.copy(
                getAdvertisementServiceImeiLoading = true,
            )
        }
        this.serverDevice = serverDevice
        getAdvertisementServiceImeiJob?.cancel()
        getAdvertisementServiceImeiJob = viewModelScope.launch {
            try {
                val client = ClientBleGatt.connect(
                    context = context,
                    device = serverDevice,
                    scope = this
                )
                client.connectionState.onEach { newState ->
                    when (newState) {
                        GattConnectionState.STATE_DISCONNECTED -> {
                            Log.d(tag, "getAdvertisementServiceImei - disconnected")
                            _bluetoothUiState.update {
                                it.copy(
                                    getAdvertisementServiceImeiLoading = false,
                                )
                            }
                        }

                        GattConnectionState.STATE_DISCONNECTING -> {
                            Log.d(tag, "getAdvertisementServiceImei - disconnecting")
                        }

                        GattConnectionState.STATE_CONNECTING -> {
                            Log.d(tag, "getAdvertisementServiceImei - connecting")
                        }

                        GattConnectionState.STATE_CONNECTED -> {
                            Log.d(tag, "getAdvertisementServiceImei - connected")
                            try {
                                val services = client.discoverServices()
                                val advertisementService =
                                    services.findService(BluetoothUuid.ADVERTISEMENT_UUID)
                                advertisementService?.let {
                                    val deviceName = readCharacteristicAsString(
                                        advertisementService,
                                        BluetoothUuid.ADVERTISEMENT_UUID_DEVICE_NAME
                                    )
                                    Log.d(
                                        tag,
                                        "getAdvertisementServiceImei - deviceName: $deviceName"
                                    )
                                    val firmwareVersion = readCharacteristicAsString(
                                        advertisementService,
                                        BluetoothUuid.ADVERTISEMENT_UUID_FIRMWARE_VERSION
                                    )
                                    Log.d(
                                        tag,
                                        "getAdvertisementServiceImei - firmwareVersion: $firmwareVersion"
                                    )
                                    val imei = readCharacteristicAsString(
                                        advertisementService,
                                        BluetoothUuid.ADVERTISEMENT_UUID_IMEI
                                    )
                                    onSetImei(imei)
                                    _bluetoothUiState.update {
                                        it.copy(
                                            getAdvertisementServiceImeiLoading = false,
                                        )
                                    }
                                    Log.d(tag, "getAdvertisementServiceImei - imei: $imei")
                                }
                            } catch (e: Exception) {
                                e.printStackTrace()
                            }
                        }
                    }
                }.launchIn(this)
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

5 participants