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
Improper characteristic list implementation of LBLEClient class #90
Comments
We really appreciate such helpful issue report. If I understood correctly, this involves 2 major issues in the LBLE library:
For the 1st issue, we need to look further into that bug. For the 2nd issue, you have described the problem and solution clearly. The LBLEClient has to be redesigned. It should allow enumerations of characteristics from either services or UUIDs. The result should be a collection of characteristic objects, which are in fact attribute handles in the underlying implementation. For example, instead of calling |
* #89: use `equal_range` when searching for elements in STL multimap, instead of using `find`. `find` is not guaranteed to return the first element in the equal range. * #90: Add a new set of interfaces to `LBLEClient` that allows user to identify a characteristic by using service index and characteristic index, instead of using UUID. Note that it is possible for a device to have multiple characteristics with the same UUID. * #90: Add a new example `EnumerateCharacteristic.ino` that uses the new indices-based interface of `LBLEClient` to list all the services and characteristics in the connected BLE device. * #90: Use `bt_gattc_read_charc` instead of `bt_gattc_read_using_charc_uuid` to read characteristics. * #91: when calling `bt_gattc_discover_charc`, we need to wait for multiple `BT_GATTC_DISCOVER_CHARC` event. We added new helper function `waitAndProcessEventMultiple` that supports such event waiting behavior. * Refactored `LBLEValueBuffer` to support re-interpreting its raw buffer content into String, float, int, and char types.
## Bug Fixes * #89: use `equal_range` when searching for elements in STL multimap, instead of using `find`. `find` is not guaranteed to return the first element in the equal range. * #90: Add a new set of interfaces to `LBLEClient` that allows user to identify a characteristic by using service index and characteristic index, instead of using UUID. Note that it is possible for a device to have multiple characteristics with the same UUID. * #90: Add a new example `EnumerateCharacteristic.ino` that uses the new indices-based interface of `LBLEClient` to list all the services and characteristics in the connected BLE device. * #90: Use `bt_gattc_read_charc` instead of `bt_gattc_read_using_charc_uuid` to read characteristics. * #91: when calling `bt_gattc_discover_charc`, we need to wait for multiple `BT_GATTC_DISCOVER_CHARC` event. We added new helper function `waitAndProcessEventMultiple` that supports such event waiting behavior. * Refactored `LBLEValueBuffer` to support re-interpreting its raw buffer content into String, float, int, and char types.
There are several issues concerning the LBLEClient class declared in LBLECentral.h and implemented in LBLECentral.cpp, and this is one of them.
With current implementation of the
LBLEClient
class, a flat characteristic listm_characteristics
implemented withstd::map
container using the UUID of the characteristic as the key and the value handle as the value is used to store the characteristic found by the protectedLBLEClient::discoverCharacteristicsOfService()
method. This way of the implementation could have the following problems:std::map
container is a sorted associative container that contains key-value pairs with unique keys, this means that if the peripheral contains services having identical characteristics, a characteristic could never be recorded to the list if other characteristic with the same UUID from other services had been discovered and inserted to the list before it, since thestd::map::insert()
in this case returns the iterator for the first occurrence of the element with the same key preventing the insertion of the new element.LBLEClient
class to output a service-characteristic list showing which characteristic is associated to which service.To demonstrate this issue, consider the following slightly modified version of the 'ConnectPeripheral.ino' example code from the LBLE library, which is extended to add methods and code segment for dumping the content of the characteristic list:
Now run the code on the LinkIt 7697 HDK and connect to a peripheral having several custom services which have some common characteristic with UUID 'E604E95D-A759-4817-87D3-AA005083A0D1' (yes, this is a nRF52-dk running Apple HomeKit server, and the peripheral list of the scanning result is shortened.):
Here is a Node.js code
main.js
using the noble library to perform similar tasks as the ConnectPeripheral.ino does:And the output of the above-mentioned code connecting to the same device:
Other than quite some obviously missing characteristics which itself is another serious issue to the LBLE library, the characteristic list from the
ABLEClient
class, a extended version of theLBLEClient
class, does not show the duplicated characteristics with UUID 'E604E95D-A759-4817-87D3-AA005083A0D1'. This also means that those duplicated characteristics missing from the list can never be written using theLBLEClient::writeCharacteristic()
method under current implementation if they are writable characteristics.By the way, since the implementation of the
LBLEClient::readCharacteristic()
does not even use theLBLEClient::m_characteristics
list during its operation, it, in theory, does not be affected directly by this issue. However, due to the way the read request is constructed by specifying the handle range to be the full range from 0x0001 to 0xFFFF, if theLBLEClient::readCharacteristic()
method is used to read characteristics affected by this issue (that is, characteristics with identical UUID but belonging to different services on the same peripheral), according to "Read Using Characteristic UUID" from Bluetooth Core Specification v4.2 Vol.3 Part G, the GATT server returns a list of Attribute Handle and Attribute Value pairs, which is not really what theLBLEClient::readCharacteristic()
is designed for, and this could break theLBLEClient::readCharacteristic()
wrapper methods likeLBLEClient::readCharacteristicInt
, etc.The text was updated successfully, but these errors were encountered: