This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Can services/characteristics/descriptors discovery could be made faster

I'm working with a nrf51422/s110 dev kit on which I downloaded the Heart rate Monitoring sample project. On my PC, using a s130 dongle, I connect the device and wrote some code (based on Heart Rate Collector sample program) to discover all services/characteristics/descriptors of the BLE device.

When you request to disover services/characteristic/descriptors, only the first few one are retrieved, and you have to do a new request for the next ones.

For HRM device, here is the services/characteristics/descriptors hierarchy:

  • Service 0x1800
    • Characteristic 0x2A00
      • Descriptor 0x2803
      • Descriptor 0x2A00
    • Characteristic 0x2A01
      • Descriptor 0x2803
      • Descriptor 0x2A01
    • Characteristic 0x2A04
      • Descriptor 0x2803
      • Descriptor 0x2A04
  • Service 0x1801
    • Characteristic 0x2A05
      • Descriptor 0x2803
      • Descriptor 0x2A05
      • Descriptor 0x2902
  • Service 0x180D
    • Characteristic 0x2A37
      • Descriptor 0x2803
      • Descriptor 0x2A37
      • Descriptor 0x2902
    • Characteristic 0x2A38
      • Descriptor 0x2803
      • Descriptor 0x2A38
  • Service 0x180F
    • Characteristic 0x2A19
      • Descriptor 0x2803
      • Descriptor 0x2A19
      • Descriptor 0x2902
  • Service 0x180A
    • Characteristic 0x2A29
      • Descriptor 0x2803
      • Descriptor 0x2A29

Here are the timings upon services/characteristic/descriptors discovery process:

  • t0, Discovering primary services from handle 0x0001
  • t0+110ms, Received service discovery response: UUID 0x1800, 0x1801, 0x180D (handles 0x0001 to 0x0011)
  • t0+110ms, Discovering next primary services from handle 0x0012
  • t0+220ms, Received service discovery response: UUID 0x180F, 0x180A (handles 0x0012 to 0xFFFF)
  • t0+220ms, Discovering characteristics for service 0x1800 from 0x0001 to 0x0007
  • t0+330ms, Found 3 new characteristic with handles: UUID 0x2A00 0x2A01 and 0x2A04 (handles 0x0003, 0x0005 and 0x0007)
  • t0+330ms, Discovering descriptors for characteristic 0x2A00
  • t0+440ms, Received descriptor discovery response: 0x2803 0x2A00

You see that, at this point, we only discovered:

  • Service 0x1800
    • Characteristic 0x2A00
      • Descriptor 0x2803
      • Descriptor 0x2A00

And it took more than 400ms.

In the end, to discover the whole services/characteristic/descriptors hierarchy, it takes up to 2 seconds. For bigger devices (with much more complex services/characteristic/descriptors hierarchy), it can take up to 10 seconds, which is hardly acceptable.

Is there really no way to speed this up? Is there any setting that could be changed at the softdevice or firmware level)?

If not, the API should probably be reworked. When deploying the same code (C++) on an Android device (using Qt to access BLE), full services/characteristic/descriptors for HRM device takes only 700ms (3 times faster).

  • What's your connection interval, looks like it's about 100ms? You only get one request/response per connection interval so if that's higher, it takes longer. Some people reduce the connection interval to a low value before connection so that service discovery is faster, then drop it back down later if such a connection interval isn't required.

    And the 'few at a time' discovery API isn't going to get reworked, that's how discovery is specified in the bluetooth spec, max information which fits in a request, then a new request. The only thing which could change there is a higher MTU which currently isn't supported (it's not supported by many implementations).

  • "Some people reduce the connection interval" how can I do that? Can it be done on application side (PC/dongle)? How do you explain the fact that QtBluetooth API on Android goes 3 time faster with the same BLE device being connected?

  • Half the connection interval/slave latency comes from the peripheral, other half from the central connecting. So first off you need to figure out which one is limiting the connection interval and you need to also see if there was slave latency set on the connection. You have both halves of that code so it should be quite practical to see what's set. Log it too - on connection you are given the actual parameters, dump them and see what you've got. Or sniff, you can see them in the connection packet.

    Most likely reason the other thing is faster is because it negotiates a lower connection interval or no slave latency. Dump it or sniff it and see what you get. Interval goes down to 7.5ms, so you should be able to get a request/response pair in 15ms.

    I've never seen anything manage to receive a response and send the next request same interval, sniff to see if that's happening too.

  • With RK help, I finally solved this.

    On the application side (PC), I was keeping the connection parameters from Nordic example:

    #define MIN_CONNECTION_INTERVAL          MSEC_TO_UNITS(30, UNIT_1_25_MS)
    #define MAX_CONNECTION_INTERVAL          MSEC_TO_UNITS(60, UNIT_1_25_MS)
    

    I changed them to:

    #define MIN_CONNECTION_INTERVAL          MSEC_TO_UNITS(10, UNIT_1_25_MS)
    #define MAX_CONNECTION_INTERVAL          MSEC_TO_UNITS(10, UNIT_1_25_MS)
    

    Now, full services/characteristic/descriptors is done in ~400ms. It's even faster than what I have when using Android/Qt API!

    Now, Im' not sure about the consequences of such a change....will it only impact my device power consumption? Or could it alterate data or performances...?

  • @RK: Got it. I changed connection min/max interval and it's now much faster (see posted answer below). I'm just wondering if changing those parameters present any risk of any kind...

Related