Skip to content

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

Closed
wakwak-koba opened this issue Jan 8, 2021 · 21 comments · Fixed by #171
Closed

Some devices fail setNotify #170

wakwak-koba opened this issue Jan 8, 2021 · 21 comments · Fixed by #171
Labels
bug Something isn't working

Comments

@wakwak-koba
Copy link
Contributor

wakwak-koba commented Jan 8, 2021

First of all, there are items to be confirmed before the main subject.

NimBLERemoteDescriptor* desc = getDescriptor(NimBLEUUID((uint16_t)0x2902));
if(desc == nullptr) {
NIMBLE_LOGW(LOG_TAG, "<< setNotify(): Callback set, CCCD not found");
return true;
}

If descriptor 0x2902 does not exist, setNotify() returns true, which is correct, isn't it false?
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.

@h2zero
Copy link
Owner

h2zero commented Jan 8, 2021

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.

@wakwak-koba
Copy link
Contributor Author

I understand the return value.
I'm sorry I didn't chase the difference.

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.

@h2zero
Copy link
Owner

h2zero commented Jan 8, 2021

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.

@wakwak-koba
Copy link
Contributor Author

wakwak-koba commented Jan 8, 2021

I tried NimBLERemoteCharacteristic::getDescriptors(true) instead of NimBLEClient::discoverAttributes() to list all the descriptors, but the Handle numbers were skipped and it was unnatural.
I feel that getDescriptors() is partially failing...

I will investigate a little more and report the continuation.

@wakwak-koba
Copy link
Contributor Author

wakwak-koba commented Jan 8, 2021

Failed in getDescriptors(true).

Name: VR BOX     , serviceUUID: 0x1812
02:56:23.918 -> Service: uuid: 0x1800, start_handle: 1 0x0001, end_handle: 7 0x0007
02:56:24.121 -> Characteristic: uuid: 0x2a00, handle: 3 0x0003, props:  0x12
02:56:24.415 -> Characteristic: uuid: 0x2a01, handle: 5 0x0005, props:  0x02
02:56:24.456 -> E NimBLERemoteCharacteristic: "Error: Failed to get descriptors"
02:56:24.497 -> Characteristic: uuid: 0x2a04, handle: 7 0x0007, props:  0x02
02:56:24.497 -> E NimBLERemoteCharacteristic: "ble_gattc_disc_all_chrs: rc=3 One or more arguments are invalid."
02:56:24.497 -> E NimBLERemoteCharacteristic: "Error: Failed to get descriptors"

if(taskData.rc != 0) {
return false;
}

I prepared LOGE() and checked it, it seems that taskData.rc = 10 in the first getDescriptors().

@h2zero
Copy link
Owner

h2zero commented Jan 8, 2021

I prepared LOGE() and checked it, it seems that taskData.rc = 10 in the first getDescriptors().

Those code need to be translated to ATT error codes

0x010a 0x0a BLE_ATT_ERR_ATTR_NOT_FOUND No attribute found within the given attribute handle range.

Which means the discovery is done.

E NimBLERemoteCharacteristic: "ble_gattc_disc_all_chrs: rc=3 One or more arguments are invalid."

This one I'm not sure of, perhaps a handle range error?

@wakwak-koba
Copy link
Contributor Author

BLE_ATT_ERR_ATTR_NOT_FOUND

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);
}
09:08:20.291 -> wait 10 secs..
09:08:30.307 -> Name: VR BOX     , serviceUUID: 0x1812
09:08:30.866 -> 
09:08:30.866 -> **Service: uuid: 0x1800, start_handle: 1 0x0001, end_handle: 7 0x0007
09:08:31.069 -> ****Characteristic: uuid: 0x2a00, handle: 3 0x0003, props:  0x12
09:08:31.181 -> ****Characteristic: uuid: 0x2a01, handle: 5 0x0005, props:  0x02
09:08:31.262 -> ****Characteristic: uuid: 0x2a04, handle: 7 0x0007, props:  0x02
09:08:31.262 -> E NimBLERemoteCharacteristic: "ble_gattc_disc_all_chrs: rc=3 One or more arguments are invalid."
09:08:31.262 -> E NimBLERemoteCharacteristic: "Error: Failed to get descriptors"
09:08:31.303 -> 
09:08:31.303 -> **Service: uuid: 0x1801, start_handle: 8 0x0008, end_handle: 11 0x000b
09:08:31.466 -> ****Characteristic: uuid: 0x2a05, handle: 10 0x000a, props:  0x20
09:08:31.577 -> ******Descriptor: uuid: 0x2902, handle: 11
09:08:31.577 -> 
09:08:31.577 -> **Service: uuid: 0x180a, start_handle: 12 0x000c, end_handle: 14 0x000e
09:08:32.431 -> ****Characteristic: uuid: 0x2a50, handle: 14 0x000e, props:  0x02
09:08:32.431 -> E NimBLERemoteCharacteristic: "ble_gattc_disc_all_chrs: rc=3 One or more arguments are invalid."
09:08:32.431 -> E NimBLERemoteCharacteristic: "Error: Failed to get descriptors"
09:08:32.431 -> 
09:08:32.431 -> **Service: uuid: 0x1812, start_handle: 15 0x000f, end_handle: 39 0x0027
09:08:32.834 -> ****Characteristic: uuid: 0x2a4e, handle: 17 0x0011, props:  0x06
09:08:35.428 -> E NimBLERemoteCharacteristic: "taskData.rc: rc=7 Offset specified was past the end of the attribute."
09:08:35.428 -> E NimBLERemoteCharacteristic: "Error: Failed to get descriptors"
09:08:35.428 -> ****Characteristic: uuid: 0x2a4d, handle: 19 0x0013, props:  0x12
09:08:35.428 -> E NimBLERemoteCharacteristic: "ble_gattc_disc_all_chrs: rc=7 No open connection with the specified handle."
09:08:35.469 -> E NimBLERemoteCharacteristic: "Error: Failed to get descriptors"
09:08:35.469 -> ****Characteristic: uuid: 0x2a4d, handle: 23 0x0017, props:  0x12
09:08:35.469 -> E NimBLERemoteCharacteristic: "ble_gattc_disc_all_chrs: rc=7 No open connection with the specified handle."
09:08:35.469 -> E NimBLERemoteCharacteristic: "Error: Failed to get descriptors"
09:08:35.469 -> ****Characteristic: uuid: 0x2a4d, handle: 27 0x001b, props:  0x12
09:08:35.469 -> E NimBLERemoteCharacteristic: "ble_gattc_disc_all_chrs: rc=7 No open connection with the specified handle."
09:08:35.509 -> E NimBLERemoteCharacteristic: "Error: Failed to get descriptors"
09:08:35.509 -> ****Characteristic: uuid: 0x2a4d, handle: 31 0x001f, props:  0x12
09:08:35.509 -> E NimBLERemoteCharacteristic: "ble_gattc_disc_all_chrs: rc=7 No open connection with the specified handle."
09:08:35.509 -> E NimBLERemoteCharacteristic: "Error: Failed to get descriptors"
09:08:35.509 -> ****Characteristic: uuid: 0x2a4b, handle: 35 0x0023, props:  0x02
09:08:35.509 -> E NimBLERemoteCharacteristic: "ble_gattc_disc_all_chrs: rc=7 No open connection with the specified handle."
09:08:35.550 -> E NimBLERemoteCharacteristic: "Error: Failed to get descriptors"
09:08:35.550 -> ****Characteristic: uuid: 0x2a4a, handle: 37 0x0025, props:  0x02
09:08:35.550 -> E NimBLERemoteCharacteristic: "ble_gattc_disc_all_chrs: rc=7 No open connection with the specified handle."
09:08:35.550 -> E NimBLERemoteCharacteristic: "Error: Failed to get descriptors"
09:08:35.550 -> ****Characteristic: uuid: 0x2a4c, handle: 39 0x0027, props:  0x04
09:08:35.590 -> E NimBLERemoteCharacteristic: "ble_gattc_disc_all_chrs: rc=3 One or more arguments are invalid."
09:08:35.590 -> E NimBLERemoteCharacteristic: "Error: Failed to get descriptors"
09:08:35.590 -> 
09:08:35.590 -> **Service: uuid: 0x180f, start_handle: 40 0x0028, end_handle: 42 0x002a
09:08:35.590 -> E NimBLERemoteService: "ble_gattc_disc_all_chrs: rc=7 No open connection with the specified handle."
09:08:35.590 -> E NimBLERemoteService: "Error: Failed to get characteristics"

I have received taskData.rc: rc = 7 at 09:08:35.428, which seems to trigger getDesctiptors() to fail.

@h2zero
Copy link
Owner

h2zero commented Jan 9, 2021

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.

@h2zero
Copy link
Owner

h2zero commented Jan 9, 2021

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 getRemoteService()->getEndHandle() -1. The device may only be checking if the end handle is < service end handle and returning the error instead of >.

@h2zero h2zero added the bug Something isn't working label Jan 9, 2021
@wakwak-koba
Copy link
Contributor Author

    rc = ble_gattc_disc_all_dscs(getRemoteService()->getClient()->getConnId(),
                                 m_handle,
                                 getRemoteService()->getEndHandle() - 1,
                                 NimBLERemoteCharacteristic::descriptorDiscCB,
                                 &filter);

I feel that it hasn't changed...

15:14:21.252 -> wait 10 secs..
15:14:31.261 -> Name: VR BOX     , serviceUUID: 0x1812
15:14:31.780 -> 
15:14:31.780 -> **Service: uuid: 0x1800, start_handle: 1 0x0001, end_handle: 7 0x0007
15:14:31.918 -> ****Characteristic: uuid: 0x2a00, handle: 3 0x0003, props:  0x12
15:14:32.019 -> ****Characteristic: uuid: 0x2a01, handle: 5 0x0005, props:  0x02
15:14:32.119 -> ****Characteristic: uuid: 0x2a04, handle: 7 0x0007, props:  0x02
15:14:32.119 -> E NimBLERemoteCharacteristic: "ble_gattc_disc_all_chrs: rc=3 One or more arguments are invalid."
15:14:32.119 -> E NimBLERemoteCharacteristic: "Error: Failed to get descriptors"
15:14:32.119 -> 
15:14:32.119 -> **Service: uuid: 0x1801, start_handle: 8 0x0008, end_handle: 11 0x000b
15:14:32.320 -> ****Characteristic: uuid: 0x2a05, handle: 10 0x000a, props:  0x20
15:14:32.320 -> E NimBLERemoteCharacteristic: "ble_gattc_disc_all_chrs: rc=3 One or more arguments are invalid."
15:14:32.320 -> E NimBLERemoteCharacteristic: "Error: Failed to get descriptors"
15:14:32.320 -> 
15:14:32.320 -> **Service: uuid: 0x180a, start_handle: 12 0x000c, end_handle: 14 0x000e
15:14:33.122 -> ****Characteristic: uuid: 0x2a50, handle: 14 0x000e, props:  0x02
15:14:33.122 -> E NimBLERemoteCharacteristic: "ble_gattc_disc_all_chrs: rc=3 One or more arguments are invalid."
15:14:33.122 -> E NimBLERemoteCharacteristic: "Error: Failed to get descriptors"
15:14:33.122 -> 
15:14:33.122 -> **Service: uuid: 0x1812, start_handle: 15 0x000f, end_handle: 39 0x0027
15:14:33.571 -> ****Characteristic: uuid: 0x2a4e, handle: 17 0x0011, props:  0x06
15:14:36.181 -> E NimBLERemoteCharacteristic: "taskData.rc: rc=7 Offset specified was past the end of the attribute."
15:14:36.181 -> E NimBLERemoteCharacteristic: "Error: Failed to get descriptors"
15:14:36.181 -> ****Characteristic: uuid: 0x2a4d, handle: 19 0x0013, props:  0x12
15:14:36.181 -> E NimBLERemoteCharacteristic: "ble_gattc_disc_all_chrs: rc=7 No open connection with the specified handle."
15:14:36.234 -> E NimBLERemoteCharacteristic: "Error: Failed to get descriptors"
15:14:36.234 -> ****Characteristic: uuid: 0x2a4d, handle: 23 0x0017, props:  0x12
15:14:36.234 -> E NimBLERemoteCharacteristic: "ble_gattc_disc_all_chrs: rc=7 No open connection with the specified handle."
15:14:36.234 -> E NimBLERemoteCharacteristic: "Error: Failed to get descriptors"
15:14:36.234 -> ****Characteristic: uuid: 0x2a4d, handle: 27 0x001b, props:  0x12
15:14:36.234 -> E NimBLERemoteCharacteristic: "ble_gattc_disc_all_chrs: rc=7 No open connection with the specified handle."
15:14:36.234 -> E NimBLERemoteCharacteristic: "Error: Failed to get descriptors"
15:14:36.234 -> ****Characteristic: uuid: 0x2a4d, handle: 31 0x001f, props:  0x12
15:14:36.281 -> E NimBLERemoteCharacteristic: "ble_gattc_disc_all_chrs: rc=7 No open connection with the specified handle."
15:14:36.281 -> E NimBLERemoteCharacteristic: "Error: Failed to get descriptors"
15:14:36.281 -> ****Characteristic: uuid: 0x2a4b, handle: 35 0x0023, props:  0x02
15:14:36.281 -> E NimBLERemoteCharacteristic: "ble_gattc_disc_all_chrs: rc=7 No open connection with the specified handle."
15:14:36.281 -> E NimBLERemoteCharacteristic: "Error: Failed to get descriptors"
15:14:36.281 -> ****Characteristic: uuid: 0x2a4a, handle: 37 0x0025, props:  0x02
15:14:36.281 -> E NimBLERemoteCharacteristic: "ble_gattc_disc_all_chrs: rc=7 No open connection with the specified handle."
15:14:36.334 -> E NimBLERemoteCharacteristic: "Error: Failed to get descriptors"
15:14:36.334 -> ****Characteristic: uuid: 0x2a4c, handle: 39 0x0027, props:  0x04
15:14:36.334 -> E NimBLERemoteCharacteristic: "ble_gattc_disc_all_chrs: rc=3 One or more arguments are invalid."
15:14:36.334 -> E NimBLERemoteCharacteristic: "Error: Failed to get descriptors"
15:14:36.334 -> 
15:14:36.334 -> **Service: uuid: 0x180f, start_handle: 40 0x0028, end_handle: 42 0x002a
15:14:36.334 -> E NimBLERemoteService: "ble_gattc_disc_all_chrs: rc=7 No open connection with the specified handle."
15:14:36.334 -> E NimBLERemoteService: "Error: Failed to get characteristics"

I was able to capture it correctly with the old BLEClient (not NimBLEClient), but what's the difference ...

@chegewara
Copy link

15:14:36.181 -> E NimBLERemoteCharacteristic: "ble_gattc_disc_all_chrs: rc=7 No open connection with the specified handle."
15:14:36.234 -> E NimBLERemoteCharacteristic: "Error: Failed to get descriptors"
15:14:36.234 -> ****Characteristic: uuid: 0x2a4d, handle: 23 0x0017, props: 0x12
15:14:36.234 -> E NimBLERemoteCharacteristic: "ble_gattc_disc_all_chrs: rc=7 No open connection with the specified handle."
15:14:36.234 -> E NimBLERemoteCharacteristic: "Error: Failed to get descriptors"
15:14:36.234 -> ****Characteristic: uuid: 0x2a4d, handle: 27 0x001b, props: 0x12
15:14:36.234 -> E NimBLERemoteCharacteristic: "ble_gattc_disc_all_chrs: rc=7 No open connection with the specified handle."
15:14:36.234 -> E NimBLERemoteCharacteristic: "Error: Failed to get descriptors"
15:14:36.234 -> ****Characteristic: uuid: 0x2a4d, handle: 31 0x001f, props: 0x12
15:14:36.281 -> E NimBLERemoteCharacteristic: "ble_gattc_disc_all_chrs: rc=7 No open connection with the specified handle."
15:14:36.281 -> E NimBLERemoteCharacteristic: "Error: Failed to get descriptors"
15:14:36.281 -> ****Characteristic: uuid: 0x2a4b, handle: 35 0x0023, props: 0x02
15:14:36.281 -> E NimBLERemoteCharacteristic: "ble_gattc_disc_all_chrs: rc=7 No open connection with the specified handle."
15:14:36.281 -> E NimBLERemoteCharacteristic: "Error: Failed to get descriptors"
15:14:36.281 -> ****Characteristic: uuid: 0x2a4a, handle: 37 0x0025, props: 0x02
15:14:36.281 -> E NimBLERemoteCharacteristic: "ble_gattc_disc_all_chrs: rc=7 No open connection with the specified handle."
15:14:36.334 -> E NimBLERemoteCharacteristic: "Error: Failed to get descriptors"
15:14:36.334 -> ****Characteristic: uuid: 0x2a4c, handle: 39 0x0027, props: 0x04
15:14:36.334 -> E NimBLERemoteCharacteristic: "ble_gattc_disc_all_chrs: rc=3 One or more arguments are invalid."
15:14:36.334 -> E NimBLERemoteCharacteristic: "Error: Failed to get descriptors"
15:14:36.334 ->
15:14:36.334 -> **Service: uuid: 0x180f, start_handle: 40 0x0028, end_handle: 42 0x002a
15:14:36.334 -> E NimBLERemoteService: "ble_gattc_disc_all_chrs: rc=7 No open connection with the specified handle."
15:14:36.334 -> E NimBLERemoteService: "Error: Failed to get characteristics"

Here connection is already closed.

@wakwak-koba
Copy link
Contributor Author

wakwak-koba commented Jan 9, 2021

The cause has been found !!
It doesn't seem to work if you dig into the handle range of another characteristic.
(In some cases, it's not always bad and it's okay)

I'm preparing to publish a fix in PR. I should be in time by morning in your country's local time ...

@wakwak-koba
Copy link
Contributor Author

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.

17:18:04.957 -> wait 10 secs..
17:18:14.951 -> Name: VR BOX     , serviceUUID: 0x1812
17:18:15.772 -> 
17:18:15.772 -> **Service: uuid: 0x1800, start_handle: 1 0x0001, end_handle: 7 0x0007
17:18:15.957 -> ****Characteristic: uuid: 0x2a00, handle: 3 0x0003, props:  0x12
17:18:15.957 -> E NimBLERemoteCharacteristic: "ble_gattc_disc_all_chrs: rc=3 One or more arguments are invalid."
17:18:15.957 -> E NimBLERemoteCharacteristic: "Error: Failed to get descriptors"
17:18:15.957 -> E NimBLERemoteCharacteristic: "ble_gattc_disc_all_chrs: rc=3 One or more arguments are invalid."
17:18:16.011 -> ****Characteristic: uuid: 0x2a01, handle: 5 0x0005, props:  0x02
17:18:16.011 -> E NimBLERemoteCharacteristic: "ble_gattc_disc_all_chrs: rc=3 One or more arguments are invalid."
17:18:16.011 -> E NimBLERemoteCharacteristic: "Error: Failed to get descriptors"
17:18:16.011 -> ****Characteristic: uuid: 0x2a04, handle: 7 0x0007, props:  0x02
17:18:16.011 -> E NimBLERemoteCharacteristic: "ble_gattc_disc_all_chrs: rc=3 One or more arguments are invalid."
17:18:16.011 -> E NimBLERemoteCharacteristic: "Error: Failed to get descriptors"
17:18:16.011 -> 
17:18:16.011 -> **Service: uuid: 0x1801, start_handle: 8 0x0008, end_handle: 11 0x000b
17:18:16.211 -> ****Characteristic: uuid: 0x2a05, handle: 10 0x000a, props:  0x20
17:18:16.211 -> E NimBLERemoteCharacteristic: "ble_gattc_disc_all_chrs: rc=3 One or more arguments are invalid."
17:18:16.211 -> E NimBLERemoteCharacteristic: "Error: Failed to get descriptors"
17:18:16.211 -> 
17:18:16.211 -> **Service: uuid: 0x180a, start_handle: 12 0x000c, end_handle: 14 0x000e
17:18:16.428 -> ****Characteristic: uuid: 0x2a50, handle: 14 0x000e, props:  0x02
17:18:16.475 -> E NimBLERemoteCharacteristic: "ble_gattc_disc_all_chrs: rc=3 One or more arguments are invalid."
17:18:16.475 -> E NimBLERemoteCharacteristic: "Error: Failed to get descriptors"
17:18:16.475 -> 
17:18:16.475 -> **Service: uuid: 0x1812, start_handle: 15 0x000f, end_handle: 39 0x0027
17:18:17.518 -> ****Characteristic: uuid: 0x2a4e, handle: 17 0x0011, props:  0x06
17:18:17.518 -> E NimBLERemoteCharacteristic: "ble_gattc_disc_all_chrs: rc=3 One or more arguments are invalid."
17:18:17.518 -> E NimBLERemoteCharacteristic: "Error: Failed to get descriptors"
17:18:17.518 -> ****Characteristic: uuid: 0x2a4d, handle: 19 0x0013, props:  0x12
17:18:17.618 -> ******Descriptor: uuid: 0x2902, handle: 20
17:18:17.618 -> ******Descriptor: uuid: 0x2908, handle: 21
17:18:17.618 -> ****Characteristic: uuid: 0x2a4d, handle: 23 0x0017, props:  0x12
17:18:17.765 -> ******Descriptor: uuid: 0x2902, handle: 24
17:18:17.765 -> ******Descriptor: uuid: 0x2908, handle: 25
17:18:17.765 -> ****Characteristic: uuid: 0x2a4d, handle: 27 0x001b, props:  0x12
17:18:17.919 -> ******Descriptor: uuid: 0x2902, handle: 28
17:18:17.919 -> ******Descriptor: uuid: 0x2908, handle: 29
17:18:17.919 -> ****Characteristic: uuid: 0x2a4d, handle: 31 0x001f, props:  0x12
17:18:18.067 -> ******Descriptor: uuid: 0x2902, handle: 32
17:18:18.067 -> ******Descriptor: uuid: 0x2908, handle: 33
17:18:18.067 -> ****Characteristic: uuid: 0x2a4b, handle: 35 0x0023, props:  0x02
17:18:18.067 -> E NimBLERemoteCharacteristic: "ble_gattc_disc_all_chrs: rc=3 One or more arguments are invalid."
17:18:18.067 -> E NimBLERemoteCharacteristic: "Error: Failed to get descriptors"
17:18:18.067 -> ****Characteristic: uuid: 0x2a4a, handle: 37 0x0025, props:  0x02
17:18:18.067 -> E NimBLERemoteCharacteristic: "ble_gattc_disc_all_chrs: rc=3 One or more arguments are invalid."
17:18:18.105 -> E NimBLERemoteCharacteristic: "Error: Failed to get descriptors"
17:18:18.105 -> ****Characteristic: uuid: 0x2a4c, handle: 39 0x0027, props:  0x04
17:18:18.105 -> E NimBLERemoteCharacteristic: "ble_gattc_disc_all_chrs: rc=3 One or more arguments are invalid."
17:18:18.105 -> E NimBLERemoteCharacteristic: "Error: Failed to get descriptors"
17:18:18.105 -> 
17:18:18.105 -> **Service: uuid: 0x180f, start_handle: 40 0x0028, end_handle: 42 0x002a
17:18:18.283 -> ****Characteristic: uuid: 0x2a19, handle: 42 0x002a, props:  0x02
17:18:18.283 -> E NimBLERemoteCharacteristic: "ble_gattc_disc_all_chrs: rc=3 One or more arguments are invalid."
17:18:18.337 -> E NimBLERemoteCharacteristic: "Error: Failed to get descriptors"

rc=3 One or more arguments are invalid. message is a warning that occurs when start_handle == end_handle.
Is it okay to leave it alone?
Or is it better to judge and return before starting processing?

@chegewara
Copy link

message is a warning that occurs when start_handle == end_handle.
Is it okay to leave it alone?

In that case no characteristics (and descriptors), so it could be checked before call ble_gattc_disc_all_dscs and return (less radio usage, better performance);

wakwak-koba added a commit to wakwak-koba/NimBLE-Arduino that referenced this issue Jan 9, 2021
@h2zero
Copy link
Owner

h2zero commented Jan 9, 2021

Glad you found a way to get this working!
PR looks good but some accommodations need to be made for cases when the next characteristic has not been discovered yet, such as when finding a characteristic by UUID.

@wakwak-koba
Copy link
Contributor Author

wakwak-koba commented Jan 11, 2021

such as when finding a characteristic by UUID.

Failed..
I have received taskData.rc: rc = 7, too.

#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 getCharacteristics(true) in this case first.

@wakwak-koba
Copy link
Contributor Author

http://mynewt.apache.org/latest/network/ble_hs/ble_gattc.html#c.ble_gattc_disc_all_dscs

chr_end_handle: The last handle in the characteristic definition.

Does the end point exist in the characteristic definition ?

@h2zero
Copy link
Owner

h2zero commented Jan 11, 2021

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.

@h2zero
Copy link
Owner

h2zero commented Jan 11, 2021

Does the end point exist in the characteristic definition ?

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.

@wakwak-koba
Copy link
Contributor Author

wakwak-koba commented Jan 12, 2021

Thank you very much.

About #171,
It works perfectly if getCharacteristics(true) has been run in advance.
If the following characteristics are not found, the end_handle of service is used,
And it is considered so that it does not change from the original behavior, so please consider it positively.

@h2zero
Copy link
Owner

h2zero commented Jan 12, 2021

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.

h2zero pushed a commit that referenced this issue Jan 13, 2021
…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).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants