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

Service Discovery Failed using pc-ble-driver

I am using an nRF52840 Dongle to try and connect to a product over Bluetooth and communicate with it. I have been able to open this dongle using nRF Connect Bluetooth Low Energy, and can successfully find my product, connect to it, and write to its characteristics. I am now needing to use a C program to do this same thing.

I have downloaded the pc-ble-driver, created a project in my C IDE, and copied the code from the heart rate collector example to be the project's source file. I got the project to build without issue, and following the instructions in the examples github page, have flashed the dongle with the correct firmware to allow the c program to connect to it. I am able to successfully connect to the dongle's COM port and scan for devices.

I did have to make some modifications to the source file. My product I want to connect to doesn't advertise its name, so I was unable to connect to it even when finding it. This product does, however, advertise the Manufacturer Specific Data field, and after some trial and error, I was able to modify the find_adv_name routine to instead check for Manufacturer Specific Data, and I was able to connect to the device this way.

After this, I get output strings that read: "Connection Established", "Discovering Primary Services", and "Received Service Discovery Response". However, I then get an error message saying "Service Discovery Failed. Error Code 0x10A". Stepping through the code, this error is getting set after the "on_connected" routine is finished, but before starting the on_service_discovery_response routine.

I have changed the value of BLE_UUID_HEART_RATE_SERVICE to match the UUID of my product's service, but there was no effect. I had also been told in the past to try changing the srvc_uuid.type from BLE_UUID_TYPE_BLE to BLE_UUID_TYPE_VENDOR_BEGIN, but when doing this, I get a failure returned from the function "sd_ble_gattc_primary_services_discover", with the error code 0x8005, which seemingly corresponds to NRF_ERROR_SD_RPC_NO_RESPONSE. 

Could anyone give me any pointers for where to look for what all to change in the source code in order to connect to my product rather than whatever heart rate monitor it is expecting? Thanks!

Parents
  • Ok, so I think I may have been getting the 0x8005 error due to stopping the program with a breakpoint, and the BLE device losing connectivity when stepping through slowly. I moved the breakpoint to right at the printing of the error message, and now my error code is consistently 0x7, which (according to nrf_error.h) should be an invalid parameter error.

    Considering this does not result in an error when I have srvc_uuid.type set to BLE_UUID_TYPE_BLE, I am assuming the invalid parameter is my srvc_uuid struct. I have been trying to figure out how exactly to set the "uuid" parameter of this struct properly. According to the struct definition, it should be either the 16bit uuid, or "octets 12-13" of the 128bit uuid. Considering I'm using BLE_UUID_TYPE_VENDOR_BEGIN, I'm guessing it will need to be the 2nd option.

    How do I determine what "octets 12-13" are though? Is this a little endian value? Big endian? Does it begin at octet 0, or 1? My full 128bit uuid is 17C30001EB0747848BF33212453B0D32. Thanks!

Reply
  • Ok, so I think I may have been getting the 0x8005 error due to stopping the program with a breakpoint, and the BLE device losing connectivity when stepping through slowly. I moved the breakpoint to right at the printing of the error message, and now my error code is consistently 0x7, which (according to nrf_error.h) should be an invalid parameter error.

    Considering this does not result in an error when I have srvc_uuid.type set to BLE_UUID_TYPE_BLE, I am assuming the invalid parameter is my srvc_uuid struct. I have been trying to figure out how exactly to set the "uuid" parameter of this struct properly. According to the struct definition, it should be either the 16bit uuid, or "octets 12-13" of the 128bit uuid. Considering I'm using BLE_UUID_TYPE_VENDOR_BEGIN, I'm guessing it will need to be the 2nd option.

    How do I determine what "octets 12-13" are though? Is this a little endian value? Big endian? Does it begin at octet 0, or 1? My full 128bit uuid is 17C30001EB0747848BF33212453B0D32. Thanks!

Children
  • mmercier said:
    Is this a little endian value? Big endian?

    It is probably reversed, but I see it listed a bit different in different places. Let us say that the long UUID is "17C30001-EB07-4784-8BF3-3212453B0D32", then the UUID would be something like:

    "0100C317-07EB-8447-F38B-320D3B451232" in the source code.

    What you should do is to look at the examples. If you have an 128-bit UUID, you should look at the examples that use a 128-bit UUID, such as the ble_app_uart example. Try to flash it, and compare the UUID you get in nRF Connect to the one that is listed in ble_nus.c on line 64 in the SDK16.0.0:

    #define NUS_BASE_UUID                  {{0x9E, 0xCA, 0xDC, 0x24, 0x0E, 0xE5, 0xA9, 0xE0, 0x93, 0xF3, 0xA3, 0xB5, 0x00, 0x00, 0x40, 0x6E}} /**< Used vendor specific UUID. */

    When I connect to it in nRF Connect, it says:

    (you have to hover the mouse over the service to see the UUID when it is one of the standards in nRF Connect)

    So it translates to:

    6E400001B5A3F393E0A9E50E24DCCA9E

    While the raw UUID from ble_nus.c:

    9ECADC240EE5A9E093F3A3B50000406E

    Or:

    6E400001-B5A3-F393-E0A9-E50E24DCCA9E

    9ECADC24-0EE5-A9E0-93F3-A3B50000406E

    So it is basically reversed, but notice that one of the 0000 are replaced with 0001, which is the service UUID. You will note that the characteristic UUIDs are identical, but the 0001 are switched to 0002 and 0003 for each of the characteristics.

    BR,

    Edvin

  • This doesn't make any sense. The uuid field of the srvc_uuid struct is defined as a 16-bit value, not as an array of 8-bit values like in that example.

    I need to know how to define this struct to connect to my product under test, based on its UUID. I have tried using both 0x0100 and 0x0001 as the uuid field of this struct, both resulting in the same error message.

    Also, I am not sure what you are meaning when describing the above process. I do not have a "Nordic_UART" device I am connecting to. I am trying to connect to my product under test. I can do this just fine in the nRF Connect program, but I am getting error messages trying to discover the service with the routines in the C program.

    Thanks.

  • For further info, here is the definition of the struct being used, defined in ble_types.h:

    /** @brief Bluetooth Low Energy UUID type, encapsulates both 16-bit and 128-bit UUIDs. */
    typedef struct
    {
    uint16_t uuid; /**< 16-bit UUID value or octets 12-13 of 128-bit UUID. */
    uint8_t type; /**< UUID type, see @ref BLE_UUID_TYPES. If type is @ref BLE_UUID_TYPE_UNKNOWN, the value of uuid is undefined. */
    } ble_uuid_t;

    The "service_discovery_start" routine is creating a struct of this type and passing it to the function "sd_ble_gattc_primary_services_discover", which is defined in the pc-ble-driver libraries. I currently have the 'type' parameter of this struct set to BLE_UUID_TYPE_VENDOR_BEGIN, and I'm trying to figure out what value to set for the 'uuid' parameter.

  • Let's keep this in one ticket. If I understand correctly, we are currently discussing the same issue in both the tickets that you have with me. I'll close the other one, and we can continue here.

    What does the service of your peripheral look like in nRF Connect -> Bluetooth? Can you show me a screenshot? Didn't you say that it was a custom UUID?`Please note that you can't just change UUIDs from the standard Bluetooth UUIDs, such as the heart rate monitor UUID, and keep it as a short UUID. If you customize it, you must use a 128-bit UUID.

    However, if you have a standard Heart rate UUID, look at how the UUID is implemented in the ble_app_hrs example and how it appears in the nRF Connect -> Bluetooth Low Energy.

    So, what does your peripheral look like in nRF Connect?

  • The product has the service UUID of 17C30001EB0747848BF33212453B0D32. It is not a heart rate monitor. I am using the heart rate collector example because it is the only example that exists in the pc-ble-driver package.

    According to the description of the struct definition, this struct "encapsulates both 16-bit and 128-bit UUIDs". For 128-bit UUIDs, I need to define the 'uuid' parameter of the struct as "octets 12-13 of 128-bit UUID", according to the description.

    It is worth noting that there is another struct type defined in this header file called "ble_uuid128_t", which only has a single parameter made up of an array of 8-bit values. However, the "sd_ble_gattc_primary_services_discover" is expecting to be passed a parameter of type "ble_uuid_t", not "ble_uuid128_t". And this function is defined in the pc-ble-driver libraries, so it's not as if I can simply modify it to take the other struct instead.

    Considering that the "ble_uuid_t" struct has a parameter for type, and this can be set to "BLE_UUID_TYPE_VENDOR_BEGIN", this seems to suggest to me that this struct should be usable for defining 128-bit UUID services. I am wondering, then, if there needs to be some other function call that sets the rest of the 128-bit UUID. If there is, though, I can't find it. The program calls "sd_ble_gattc_primary_services_discover" as its first function call on connection.

    Could you please let me know if there is either a function I need to use to set the rest of the UUID, or if there is a function I can use to pass a "ble_uuid128_t" struct instead of a "ble_uuid_t"? Thanks.

Related