labapart / gattlib

Library to access GATT information from BLE (Bluetooth Low Energy) devices
http://labapart.com/
460 stars 161 forks source link

Call to gattlib_discover hangs randomly #36

Open DannyVlasenko opened 7 years ago

DannyVlasenko commented 7 years ago

I try to connect to device and to discover its characteristics. I use following code (c++11):

  connection = gattlib_connect(nullptr, netAddress.c_str(), BDADDR_LE_RANDOM, BT_SEC_LOW, 0, 0);

        //gattlib_context_t* context = connection->context; 

        if(connection == nullptr) {

            log->warn("[%s: %s] Connection is null after gattlib_connect", "BleDevice", __FUNCTION__);

            return;

        }

        gattlib_characteristic_t* characteristics;

        int characteristics_count;

        int ret;

        ret = gattlib_discover_char(connection, &characteristics, &characteristics_count);

        if (ret){

            log->error("[%s: %s] Failed discover services", "BleDevice", __FUNCTION__);

            return 2; // Fail to discover characteristics

         }

about 50% of calls to gattlib_discover_char blocks forever. I've found that check for user_data.discovered in gattlib_discover_char_range in while loop is always fails in this situation. I've also understood that gattlib_connect also calls gattlib_discover_char and stores result in gattlib_context_t structure. I use the same function for discovering as gattlib_connect and call to gattlib_connect is always succeed but following guttlib_discover_char in my code hangs. Or maybe I do something wrong and there is a way to get characteristics from connection context (gattlib_context_t type is not accessible via gattlib.h)?

os is ubuntu 16.04.1

mweal-ed commented 7 years ago

I think this is related to Issue #2. I have been looking into the connect failures (without a lot of success). One of the common connect failures is the call to gattlib_discover_char() in io_connect_cb(). However my experience differs from yours in that if the connection is successful, I have not been getting failures when calling gattlib_discover_char_range() afterwords. Note: I call gattlib_discover_primary() before the call to gattlib_discover_char_range() so I don't know if this is resolving the problem.

Out of curiosity, do you have the same problem if you wait for bluetooth to properly disconnect after the previous run of your program (wait 60 seconds or until "hcitool con" indicates there are no connections remaining)?

OS is Ubuntu 16.04.2 LTS

DannyVlasenko commented 7 years ago

It looks like 60s waiting doesn't help. user_data.discovered stays false in a half of calls to discover_char(). Moreover, discover_char() sometimes hangs on first call after starting my program first time on just loaded os.

Note: I call gattlib_discover_primary() before the call to gattlib_discover_char_range() so I don't know if this is resolving the problem.

Yep, I call it too, just removed from my post to make it shorter.

Is it important to call all of these functions from main program thread? I've just understood, that i call them in separate thread

mweal-ed commented 7 years ago

I have a pending pull request #33 that might help this. It is also available at mweal-ed/gattlib on the "iteration" branch. if you are using _async functions you will have to uncomment the #define USE_THREADS in gattlib_internal.h.

Also are you using threads/semaphores/mutexes/notifications/ _async/callbacks in your code?

mweal-ed commented 7 years ago

Is it important to call all of these functions from main program thread? I've just understood, that i call them in separate thread.

I have been having some problems with threads and gattlib. I don't know if it is something I am doing or something to do with gattlib/gatttool/bluez or the bluetooth kernel drivers. The gattlib code itself uses a thread to handle the glib event loop, and I am unable get mutexes or semaphores to work properly for watching the event completion flags for various functions. So I suspect there may be something in gattlib or its underlying libraries that is not thread safe.