-
-
Notifications
You must be signed in to change notification settings - Fork 174
Some devices fail setNotify #170
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
Comments
This is an intended change from 8310b7b to support the "iTag" devices that do not have cccds but still send notifications. This was brought up in #152, also in espressif/arduino-esp32#4659 The reason for returning true is so the app knows to expect notifications if they come, regardless of the cccd existing. |
I understand the return value. However, since the device I am using for testing is a BLE-HID Device, CCCD should exist, and the device side will not complete the connection unless 0x01 is writeValue() for 0x2902. |
If you call NimBLEClient::discoverAttributes and print them out does it show a 2902? This could be a case of a 128bit descriptor used for the 2902 on the device. |
I tried I will investigate a little more and report the continuation. |
Failed in
NimBLE-Arduino/src/NimBLERemoteCharacteristic.cpp Lines 228 to 230 in bc52eac
I prepared |
Those code need to be translated to ATT error codes
Which means the discovery is done.
This one I'm not sure of, perhaps a handle range error? |
This just means that Dest doesn't exist, right? I rewrote the source code to dump everything. void setup() {
Serial.begin(115200);
NimBLEDevice::init("");
auto pBLEScan = NimBLEDevice::getScan();
pBLEScan->setActiveScan(true);
Serial.println("wait 10 secs..");
auto pScanResults = pBLEScan->start(10);
for (int i = 0; i < pScanResults.getCount(); i++) {
auto advertisedDevice = pScanResults.getDevice(i);
if (advertisedDevice.haveServiceUUID()) {
Serial.println(advertisedDevice.toString().c_str());
auto pClient = NimBLEDevice::createClient();
if(pClient && pClient->connect(&advertisedDevice)) {
auto pServices = pClient->getServices(true);
for (auto pService : *pServices) {
Serial.println();
Serial.print("**");
Serial.println(pService->toString().c_str());
auto pCharacteristics = pService->getCharacteristics(true);
for (auto pCharacteristic : *pCharacteristics) {
Serial.print("****");
Serial.println(pCharacteristic->toString().c_str());
auto pDescriptors = pCharacteristic->getDescriptors(true);
for (auto pDescriptor : *pDescriptors)
{
Serial.print("******");
Serial.println(pDescriptor->toString().c_str());
}
}
}
}
Serial.println();
}
}
if(NimBLEDevice::getClientListSize() == 0)
ESP.restart();
}
void loop() {
delay(1);
}
I have received |
Thanks for the log, looks like there is a bug somewhere in the handle values. I'll have to look into the code a bit more as I'm not very familiar with that error. |
I took a quick look into this and I can see where the error could occur. Since we do not have an end handle for the characteristic we use the service end handle as a proxy. The device you're connecting to does not accept as valid and produces the error. The only solution I can think of at this time is to get the handle of the next characteristic if less than service end handle and mark that value -1 as the end handle, then retrieve the descriptors in that range. This approach may work but also may fail as we have no way to know the end handle of the last characteristic of the last service. This also would result in reduced efficiency/performance, but not too much. There is one other possibility however, if you'd like to try it. This line could be changed to |
rc = ble_gattc_disc_all_dscs(getRemoteService()->getClient()->getConnId(),
m_handle,
getRemoteService()->getEndHandle() - 1,
NimBLERemoteCharacteristic::descriptorDiscCB,
&filter); I feel that it hasn't changed...
I was able to capture it correctly with the old BLEClient (not NimBLEClient), but what's the difference ... |
Here connection is already closed. |
The cause has been found !! I'm preparing to publish a fix in PR. I should be in time by morning in your country's local time ... |
I was able to overcome the error by finding the end of RemoteCharacteristic instead of terminating the service, assigning it to end_handle and executing it.
|
In that case no characteristics (and descriptors), so it could be checked before call |
Glad you found a way to get this working! |
Failed.. #include "NimBLEDevice.h"
static NimBLEUUID serviceUUID((uint16_t)0x1812);
void setup() {
Serial.begin(115200);
NimBLEDevice::init("");
auto pBLEScan = NimBLEDevice::getScan();
pBLEScan->setActiveScan(true);
Serial.println("wait 10 secs..");
auto pScanResults = pBLEScan->start(10);
for (int i = 0; i < pScanResults.getCount(); i++) {
auto advertisedDevice = pScanResults.getDevice(i);
if (advertisedDevice.haveServiceUUID()) {
Serial.println(advertisedDevice.toString().c_str());
auto pClient = NimBLEDevice::createClient();
if(pClient && pClient->connect(&advertisedDevice)) {
auto pService = pClient->getService(serviceUUID);
if(pService != NULL) {
Serial.println();
Serial.print("**");
Serial.println(pService->toString().c_str());
pService->getCharacteristic((uint16_t)0x2a4d);
auto pCharacteristics = pService->getCharacteristics();
for (auto pCharacteristic : *pCharacteristics) {
Serial.print("****");
Serial.println(pCharacteristic->toString().c_str());
auto pDescriptors = pCharacteristic->getDescriptors(true);
for (auto pDescriptor : *pDescriptors)
{
Serial.print("******");
Serial.println(pDescriptor->toString().c_str());
}
}
}
}
Serial.println();
}
}
if(NimBLEDevice::getClientListSize() == 0)
ESP.restart();
} I think it depends on the device, but I came to the conclusion that it is essential to do |
http://mynewt.apache.org/latest/network/ble_hs/ble_gattc.html#c.ble_gattc_disc_all_dscs
Does the end point exist in the characteristic definition ? |
Thanks for bringing that up, yes in the case of multiple characteristics with the same uuid there would be an issue. There isn't and real support for that in the library currently. What I'm thinking that could be done is using the start handle +1 and incrementally calling get descriptors until hitting a characteristic. Would have to check the return code and handle definition but that's already done mostly. |
No it is not reported by the device or NimBLE. That is not required by the Bluetooth spec. The spec simply says that the end handle is the next characteristic definition handle or the service end handle. So we are left to deal with the implementation on our own. |
Thank you very much. About #171, |
Thank you for the PR, I see no issues with it other than what was already stated. Just know that it will likely be changed in the near future when I have time to find a "complete" solution. |
…ixes #170 On some devices, searching for descriptors using the service end handle would return an invalid error. This patch instead uses the handle of the next characteristic as the end handle (if available).
First of all, there are items to be confirmed before the main subject.
NimBLE-Arduino/src/NimBLERemoteCharacteristic.cpp
Lines 529 to 533 in bc52eac
If descriptor 0x2902 does not exist,
setNotify()
returnstrue
, which is correct, isn't itfalse
?That's because I found that some devices couldn't get descriptor 0x2902 even though
canNotify() == true
.I don't think it's similar to the 16bit uuid problem I had before, but do you have any idea?
The device used for evaluation is this.
The text was updated successfully, but these errors were encountered: