Skip to content

m_semaphoreOpenEvt semaphore is stuck waiting when a connection fails #744

Closed
@egzplicit

Description

@egzplicit

I have a class that wraps the BLE stuff in order to connect to a HM10 bluetooth device. This is the way it works:

  • creates a BLEClient
  • scans 3 seconds for HM10 BLE devices
  • if no device is found, it waits 10 seconds and restarts the scan
  • if the device is found, it connects to it using the created BLEClient from step 1
  • when the device is disconnected (due to powering off the HM10 module or other reasons), it will re-start scanning
  • if the device is found again, it reuses the BLEClient instance to reconnect

It works great but I think I found one bug: upon a disconnect (due to HM10 being turned off), a scan starts. When I turn the HM10 module on, the scan discovers it and it attempts to establish a new connection using pClient->connect(deviceAddress).

At this point sometimes the connect call fails. What is interesting is the order of the events: BLEClient::connect takes the m_semaphoreRegEvt semaphore and registers the new app using esp_ble_gattc_app_register. That works fine, then the m_semaphoreRegEvt is given back inside the handling of the ESP_GATTC_REG_EVT event. Next the m_semaphoreOpenEvt semaphore is taken and esp_ble_gattc_open is called. Ideally this should work and the m_semaphoreOpenEvt should be given back when handling ESP_GATTC_OPEN_EVT event.

However, what I found is that occasionally the ESP_GATTC_OPEN_EVT event never fires, and instead the ESP_GATTC_DISCONNECT_EVT fires. Handling the ESP_GATTC_DISCONNECT_EVT event gives back the m_semaphoreRssiCmplEvt and m_semaphoreSearchCmplEvt semaphores, but not the m_semaphoreOpenEvt one that was taken by the connect method in the BLEClient.

This means the BLEClient::connect hangs forever waiting for uint32_t rc = m_semaphoreOpenEvt.wait("connect"); - https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/BLEClient.cpp#L132

Because my call to BLEClient::connect never returns, my class that wraps everything stops working and will never re-scan or handle this.

I am looking into a fix, I think that https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/BLEClient.cpp#L178 should give the m_semaphoreOpenEvt semaphore as well.

Here are the logs when the above happens (The HM10Client is my class):

[D][BLEScan.cpp:106] handleGAPEvent(): Ignoring 63:04:e2:60:c1:8b, already seen it.
[D][BLEClient.cpp:464] handleGAPEvent(): BLEClient ... handling GAP event!
[D][BLEScan.cpp:106] handleGAPEvent(): Ignoring 63:04:e2:60:c1:8b, already seen it.
[D][BLEClient.cpp:464] handleGAPEvent(): BLEClient ... handling GAP event!
[D][BLEAdvertisedDevice.cpp:424] setRSSI(): - setRSSI(): rssi: -80
[D][BLEAdvertisedDevice.cpp:253] parseAdvertisement(): Type: 0x01 (), length: 1, data: 06
[D][BLEAdvertisedDevice.cpp:253] parseAdvertisement(): Type: 0x02 (), length: 2, data: e0ff
[D][BLEAdvertisedDevice.cpp:453] setServiceUUID(): - addServiceUUID(): serviceUUID: 0000ffe0-0000-1000-8000-00805f9b34fb
[D][HM10Client.cpp:79] onResult(): BLE Advertised Device found: Name: , Address: 00:15:83:10:54:12, serviceUUID: 0000ffe0-0000-1000-8000-00805f9b34fb
[D][HM10Client.cpp:81] onResult(): Found what looks like an HM10 device, stopping scan
[D][BLEScan.cpp:259] stop(): >> stop()
[D][BLEScan.cpp:271] stop(): << stop()
[D][HM10Client.cpp:40] connect(): Starting connection
[D][BLEClient.cpp:103] connect(): >> connect(00:15:83:10:54:12)
[I][BLEDevice.cpp:596] addPeerDevice(): add conn_id: 0, GATT role: client
[D][FreeRTOS.cpp:165] take(): Semaphore taking: name: RegEvt (0x3ffd47ac), owner: <N/A> for connect
[D][BLEClient.cpp:464] handleGAPEvent(): BLEClient ... handling GAP event!
[D][FreeRTOS.cpp:174] take(): Semaphore taken:  name: RegEvt (0x3ffd47ac), owner: connect
[D][BLEDevice.cpp:150] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... Unknown
[D][BLEClient.cpp:165] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... Unknown
[D][FreeRTOS.cpp:165] take(): Semaphore taking: name: OpenEvt (0x3ffd480c), owner: <N/A> for connect
[D][FreeRTOS.cpp:174] take(): Semaphore taken:  name: OpenEvt (0x3ffd480c), owner: connect
[D][BLEDevice.cpp:150] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... Unknown
[D][BLEClient.cpp:165] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... Unknown
[D][HM10Client.cpp:95] onDisconnect(): Disconnected
[I][BLEDevice.cpp:607] removePeerDevice(): remove: 0, GATT role client
[D][BLEDevice.cpp:150] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... Unknown
[D][BLEDevice.cpp:150] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... Unknown
[D][main.ino:50] loop(): Loop task running
[D][main.ino:50] loop(): Loop task running
[D][main.ino:50] loop(): Loop task running
[D][main.ino:50] loop(): Loop task running
[D][main.ino:50] loop(): Loop task running
[D][main.ino:50] loop(): Loop task running

You can see how scan finds the device, it stops the scan and then it attempts to connect. However, due to ::connect never returning, it blocks everything.

This failure to connect only happens occasionally, in 50% of the time with my hm10 module. I'm not sure why it can't connect but in the log you can see that ESP_GATTC_DISCONNECT_EVT event is fired because i have a callback on it that actually gets called ([D][HM10Client.cpp:95] onDisconnect(): Disconnected).

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions