GATT Service Discovery Failure on SIG BASE UUID

Support,

I've encountered a challenge while integrating my product with device from a third-party. Unfortunately, they've utilized the SIG base UUID for their unregistered vendor services, and with their product already on the market for a few years, they've expressed no intention to revise this approach. I'm integrating with two of their devices, which I'll distinguish as device A and device B for our discussion. Establishing a connection with device A poses no issue, as its service characteristics are easily discoverable due to the use of 16-bit UUIDs. However, with device B, their oldest product, I'm not as fortunate. During the discovery process on device B, I encounter the error BLE_GATT_STATUS_ATTERR_ATTRIBUTE_NOT_FOUND. Research conducted using tools such as nRF Connect for both iOS and desktop reveals differences in how devices A and B present their services and characteristics. I have attached screenshots and logs from these tools for reference. From what I've gathered from another topic on this support site, the Softdevice manages the SIG Base UUID internally in a manner that I haven't fully grasped yet. It seems like I need to adopt an approach where I utilize the full 128-bit UUID instead of the 16-bit UUID for service discovery. From the log screenshots below, you can clearly see the differences between the to devices.  However, I'm uncertain how to implement this when the SIG base UUID is in use, which is causing some confusion in getting this to work. I've reached the limits of my knowledge in resolving this issue and need assistance from support to guide me toward a solution. Are there questions I'm overlooking, and do you fully grasp my problem? If so, is there a viable path to resolving it? Thank you.

This screenshot merges the log outputs from nRF Connect for iOS. As evident, the implementation of the SIG Base UUID appears to vary slightly in the way it's being published. I'm having difficulty comprehending these two differences: the utilization of 128-bit and 16-bit UUIDs.

Here's a screenshot of the device connect to nRF Connect for Desktop

   

As always, thank you for the amazing support!

  • Hello,

    When working with vendor-specific UUIDs that do not use the BT SIG base UUID, you must first add the 128-bit base UUID to the SoftDevice's UUID table. This allows the application to reference the UUID later. New base UUIDs are added through the sd_ble_uuid_vs_add()  function.

    Note: If sd_ble_uuid_vs_add() returns NRF_ERROR_NO_MEM, it means you must increase the 'NRF_SDH_BLE_VS_UUID_COUNT' in sdk_config.h to allocate additional UUID slots in the SoftDevice table.

    You can take a look at the Nordic UART Service Client  project for a practical example of a client using a 128-bit vendor-specific UUID. This client include the following service and characteristics:

    Code to add the Nordic UART service base uuid

    #define NUS_BASE_UUID                   {{0x9E, 0xCA, 0xDC, 0x24, 0x0E, 0xE5, 0xA9, 0xE0, 0x93, 0xF3, 0xA3, 0xB5, 0x00, 0x00, 0x40, 0x6E}} /**< Used vendor-specific UUID. */
    
    ...
    
    uint32_t ble_nus_c_init(ble_nus_c_t * p_ble_nus_c, ble_nus_c_init_t * p_ble_nus_c_init)
    {
        uint32_t      err_code;
        ble_uuid_t    uart_uuid;
        ble_uuid128_t nus_base_uuid = NUS_BASE_UUID;
    
        VERIFY_PARAM_NOT_NULL(p_ble_nus_c);
        VERIFY_PARAM_NOT_NULL(p_ble_nus_c_init);
        VERIFY_PARAM_NOT_NULL(p_ble_nus_c_init->p_gatt_queue);
    
        err_code = sd_ble_uuid_vs_add(&nus_base_uuid, &p_ble_nus_c->uuid_type);
        VERIFY_SUCCESS(err_code);
        ...

    Notice that the NUS_BASE_UUID symbol is represented in little-endian format, as opposed to the big-endian representation that tends to be used in user-facing applications and documentation. Also, the 'p_ble_nus_c-->uuid_type' holds the index of the base UUID, which the app uses as a tag to reference the UUID. 

    Service discovery registration

    Characteristic discovery

    If anything is unclear, please let me know.

    Best regards,

    Vidar

  • Vidar,

    Thanks for getting back to me promptly. I fully understand your reply. My product also interfaces with multiple other vendor products through their distinct UUIDs and services. When I integrated other products a few years back, I followed the NUS client model as outlined.

    In my explanation, both devices utilize the SIG base UUID for their services. This can be verified in the screenshot of the nRF Connect logs I posted.  My client code for connecting to Device-A functions smoothly. Since the services of Device-A and Device-B appear identical, I aimed to utilize the same code to connect to either device. When connecting to Device-A, there are no issues with discovering the service. Upon reviewing the logs, we observe that it returns the short UUID (2-byte). However, Device-B is now returning the full UUID (16-byte), and inexplicably, it cannot be discovered, resulting in an "attribute not found" error. So in short, the discovery process cannot find the service "0000FFE0-0000-1000-8000-00805F9B34FB" (Device-B) but can find "FFE0" (Device-A).

    Logs from nRF Connect for both devices, with the highlighted comparison.

    Device-B debug output from the connection attempt reveals failure due to the inability to find the service FFE0 during the discovery process.

    <info> srm_ble_svcs: CENTRAL: Scan Event - Found Peripheral Device PeekSmith-030CA3
    .
    <info> srm_ble_svcs: CENTEAL: Peripheral Device Address - D0:78:87:05:0C:A3
    <debug> nrf_sdh_ble: BLE event: 0x10.
    <debug> nrf_ble_gatt: Requesting to update ATT MTU to 247 bytes on connection 0x0.
    <debug> nrf_ble_gatt: Updating data length to 251 on connection 0x0.
    <info> srm_ble_svcs: CENTRAL: Scan Event - Connected to device.
    <debug> ble_display_c: CONNECTED Event Recieved!
    <info> srm_ble_svcs: CENTRAL: GAP - Device Connected, handle 0
    <info> ble_display_c: Assigning Connection Handle, handle 0
    <debug> nrf_ble_gq: Registering connection handle: 0x0000
    <debug> ble_db_disc: Starting discovery of service with UUID 0xFFE0 on connection handle 0x0.
    <debug> nrf_ble_gq: Adding item to the request queue
    <debug> nrf_ble_gq: GATTC Primary Services Discovery Request
    <debug> nrf_ble_gq: SD is currently busy. The GATT request procedure will be attempted                       again later.
    <debug> nrf_ble_gq: Processing the request queue...
    <debug> nrf_ble_gq: GATTC Primary Service Discovery Request
    <debug> nrf_ble_gq: SD is currently busy. The GATT request procedure will be attempted                           again later.
    <debug> nrf_sdh_ble: BLE event: 0x39.
    <debug> nrf_ble_gq: Processing the request queue...
    <debug> nrf_ble_gq: GATTC Primary Service Discovery Request
    <debug> nrf_ble_gq: SD is currently busy. The GATT request procedure will be attempted                           again later.
    <debug> nrf_sdh_ble: BLE event: 0x3A.
    <debug> nrf_ble_gatt: ATT MTU updated to 247 bytes on connection 0x0 (response).
    <debug> srm_ble_svcs: GATT: ATT MTU exchange completed. central 0xF7 peripheral 0xF7
    <debug> nrf_ble_gq: Processing the request queue...
    <debug> nrf_ble_gq: GATTC Primary Service Discovery Request
    <debug> nrf_ble_gq: SD GATT procedure (2) succeeded on connection handle: 0.
    <debug> nrf_sdh_ble: BLE event: 0x24.
    <debug> nrf_ble_gatt: Data length updated to 251 on connection 0x0.
    <debug> nrf_ble_gatt: max_rx_octets: 27
    <debug> nrf_ble_gatt: max_tx_octets: 251
    <debug> nrf_ble_gatt: max_rx_time: 328
    <debug> nrf_ble_gatt: max_tx_time: 2120
    <debug> srm_ble_svcs: GATT: ATT MTU exchange completed. central 0xF7 peripheral 0xF7
    <debug> nrf_sdh_ble: BLE event: 0x30.
    <debug> ble_db_disc: Service UUID 0xFFE0 not found.
    <info> srm_ble_svcs: CENTRAL: Display Database Discovery Event.
    <debug> ble_display_c: Database Discovery Event: BLE_DB_DISCOVERY_SRV_NOT_FOUND
    <info> srm_ble_svcs: CENTRAL: Display Database Discovery Event.
    <debug> ble_display_c: Database Discovery Event: BLE_DB_DISCOVERY_AVAILABLE
    <debug> nrf_ble_gq: Processing the request queue...
    <debug> nrf_sdh_ble: BLE event: 0x39.
    <debug> nrf_ble_gq: Processing the request queue...
    <debug> nrf_sdh_ble: BLE event: 0x39.
    <debug> nrf_ble_gq: Processing the request queue...
    <debug> nrf_sdh_ble: BLE event: 0x39.
    <debug> nrf_ble_gq: Processing the request queue...

    Here's the code snippet for initializing the client.

    // 00000000-0000-1000-8000-00805F9B34FB
    #define BLE_SIG_UUID_BASE                 { 0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80, \
                                                0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
    
    ....
    
    #define PS_UUID_DISPLAY_SERVICE  0xFFE0
    #define PS_UUID_DISPLAY_CHAR_1   0xFFE1
    #define PS_UUID_DISPLAY_CHAR_2   0xFFE2
    #define PS_UUID_DISPLAY_CHAR_3   0xFFE3
    #define PS_UUID_DISPLAY_CHAR_4   0xFFFF
    
    ....
    
    ret_code_t m_ble_display_c_init(ble_display_c_init_t  *p_ble_display_c_init,
                                    ble_display_config_t **p_display_config) {
        ret_code_t err_code;
        
        VERIFY_PARAM_NOT_NULL(p_ble_display_c_init);
        VERIFY_PARAM_NOT_NULL(p_ble_display_c_init->p_gatt_queue);
    
        memcpy(&s_display_config, &s_display_config_default, sizeof(ble_display_config_t));
        *p_display_config = &s_display_config;
    
        ble_uuid128_t base_uuid = BLE_SIG_UUID_BASE;
        err_code = sd_ble_uuid_vs_add(&base_uuid, &m_ble_display_c.uuid_type);
        VERIFY_SUCCESS(err_code);
        
        ble_uuid_t srvc_uuid = {
    	.type = m_ble_display_c.uuid_type,
    	.uuid = PS_UUID_DISPLAY_SERVICE
        };
    
        m_ble_display_c.peer_display_db.cccd_handle    = BLE_GATT_HANDLE_INVALID;
        m_ble_display_c.peer_display_db.display_handle = BLE_GATT_HANDLE_INVALID;
        m_ble_display_c.conn_handle                    = BLE_CONN_HANDLE_INVALID;
        m_ble_display_c.p_gatt_queue                   = p_ble_display_c_init->p_gatt_queue;
        //m_ble_display_c.uuid_type                      = BLE_UUID_TYPE_VENDOR_BEGIN;
        //m_ble_display_c.uuid_type                      = BLE_UUID_TYPE_BLE;
    
        return ble_db_discovery_evt_register(&srvc_uuid);
    }

    Thank you,

    - Matt

  • Vidar

    Based on what I've seen, Device-B is advertising its service with a 128-bit UUID. We see that in the logs.  Since it's using the SIG base UUID, is the Softdevice defaulting to searching for services with a 16-bit UUID, which might explain why it's not discovering the service? Device-A is broadcasting a 16-bit UUID, which can be accurately identified since it also employs the SIG base UUID.

    - Matt

  • Matt,

    Sorry, I misunderstood the problem; I assumed it was the other way around. That is, I assumed you were able to discover the service on device B.

    I don't understand why iOS doesn't discover the service as having a 16-bit UUID for device B considering it's using the same reserved base UUID. I tried replicating this by using the UART peripheral sample and replacing the NUS base UUID with the Bluetooth SIG's, but that resulted in the same behavior as seen with device A.

    nRF Connect log

    Attempting to connect...
    cbCentralManager.connect()
    [Callback] centralManager(central, didConnect: peripheral)
    Connected.
    Discovering Services...
    peripheral.discoverServices(nil)
    [Callback] peripheral(peripheral, didDiscoverServices: nil)
    Discovered FFFE Services.
    Discovering Characteristics for FFFE...
    peripheral.discoverCharacteristics(nil, for: FFFE)
    [Callback] peripheral(peripheral, didDiscoverCharacteristicsFor: FFFE, error: nil)
    Discovering Descriptors for Characteristic 0002...
    peripheral.discoverDescriptors(for: 0002)
    Discovering Descriptors for Characteristic 0003...
    peripheral.discoverDescriptors(for: 0003)
    [Callback] peripheral(peripheral, didDiscoverDescriptorsFor: 0002, error: nil)
    Discovered Characteristics 0002 and 0003 for Service FFFE.
    Characteristic 0002 has no Descriptors.
    [Callback] peripheral(peripheral, didDiscoverDescriptorsFor: 0003, error: nil)
    Discovered Client Characteristic Configuration for Characteristic 0003

    There must be some details in the specification that I'm not aware of. I will need to investigate this further on my side. The advertisement payload should not have any influence on the service discovery.

    Best regards,

    Vidar

  • Vidar,

    Thanks for investigating this. I recall having a GATT Browser app installed on my Mac. I utilized it with the two devices, and you can also observe where it highlights the disparities between them. Device-A reports the short UUID while Device-B reports the full UUID. I'm able to discover and connect to Device-A with the short UUID when utilizing the SIG base UUID.

    Device-A

    Device-B

    - Matt

Related