arduino-libraries / ArduinoBLE

ArduinoBLE library for Arduino
GNU Lesser General Public License v2.1
311 stars 205 forks source link

hasCharacteristic() returning false #198

Open baconcheese113 opened 3 years ago

baconcheese113 commented 3 years ago

Hey, first off thanks a ton for putting this library together and maintaining it!

I have working code for a central (Arduino IoT) to connect with a peripheral (Arduino Sense) and read sensor data from a characteristic called Volts.

I'm currently porting my peripheral code to a new microcontroller (da-14531), and trying to use the same code for the central. Everything is working the same at this point except hasCharacteristic() is returning false for my Volts characteristic even though I can see the service correctly in my nRF scanner app. I've already made sure the service/char UUIDs match

Any suggestions how to debug? I'm not sure why this would return false when I can see the characteristic in my scanner app

JamieMcQuire23 commented 3 years ago

Having a similar issue with this (Arduino BLE Sense)... BLEService not showing characteristics as a peripheral when connecting as a central and not sure why.

JamieMcQuire23 commented 3 years ago

Going to follow up from my comment yesterday because I got this working. I found that I did not call the BLEDevice.discoverAttributes() function before checking if the characteristics were readable. Additionally, I put a timing loop (terminates if my characteristic is successfully written) around the connection part of the code. It seems that sometimes the BLE sense board takes awhile to show the characteristics upon connection.

baconcheese113 commented 3 years ago

Hmm, I tried adding in a BLEDevice.discoverAttributes() call but still no luck. The weird thing for me is that it works just fine with the BLE Sense as the peripheral, it's just not returning true when I call hasCharacteristic(VOLT_CHARACTERISTIC_UUID) with the new microcontroller.

On both peripherals I get: peripheral.connect() = true peripheral.serviceCount() = 0 peripheral.appearance() = 0 peripheral.discoverService(SENSOR_SERVICE_UUID) = true peripheral.hasService(SENSOR_SERVICE_UUID) = false peripheral.discoverAttributes() = true peripheral.hasCharacteristic(VOLT_CHARACTERISTIC_UUID) = false

JamieMcQuire23 commented 3 years ago

Could you send your code across. I found that you need a timed loop wrapped around the actions that you are doing to the peripheral that repeats from the start when there is an error. It seems to me that sometimes the characteristics are not advertised immediately.

baconcheese113 commented 3 years ago

Sure, https://github.com/baconcheese113/handle-it/blob/master/src/hub/HandleHub.cpp#L320 After connecting with the peripheral (da-14531) hasService() and hasCharacteristic() both return false

I also tried wrapping the hasService in a loop with a delay between every iteration, but still false after a couple minutes

baconcheese113 commented 3 years ago

Okay, I found the reason that hasService is returning false.

I'm using a 128-bit UUID extended from a 16-bit uuid: 0000181a-0000-1000-8000-00805f9b34fb This is a BLE Assigned Number and 181a is understood to be "Environment Sensing"

The function in this library BLERemoteService::uuid() returns the 16-bit uuid 181a for my 128-bit uuid I pasted above. It then does strcasecmp(uuid, s->uuid()) == 0 and sees that they don't match. This is very confusing behavior because I'd imagine everyone who is using 128-bit uuids based off Assigned Numbers is going to run into this problem.

Kaly380 commented 2 years ago

I also used a 128-bit UUID extended from a 16-bit uuid (181d) and when calling the discoverAttributes() method the arduino stays there, it doesn't respond.

I don't know what could be happening, it's like I'm going into an infinite loop

nordblick2 commented 11 months ago

Run into same problem and dig into BLEDevice.cpp. In method bool BLEDevice::hasCharacteristic(const char* uuid, int index) const an strange variable index will be checked in addition to given uuid.

Using hasCharacteristics(uuid) an internal index-variable will also evaluated against a characteristic counter variable. Whenever an uuid matches, that hard coded index=0 will be compared against that counter variable. If you have only one characteristics, hasCharacteristic will return true in that case. If you have more, it will always fail as long as your uuid characteristic is not the very first one.

https://github.com/arduino-libraries/ArduinoBLE/blob/dff9e414abc20df491b46d0b38b360eb1a3507fb/src/BLEDevice.cpp#L472-L476

I didn't understand the reason for that! I would expect some code that just tests for a characteristic. Maybe within a special service, but that code didn't check that. Maybe some of you can explain what kind of index that method uses. Presently it's the reason my hasCharactristic and characteristic calls fail.

Edit: Commenting out block if (count == index) works for me! Would love to understand that index anyway