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

sd_ble_gattc_characteristics_discover sees only the first characteristic of private service

Hello Nordic team,

I'm having some trouble with discovering the characteristics of a custom device. 

The peripheral device has a private service with UUID 06000002-0000-0000-0000-0000004E4553 and two characteristics with write enabled : 06000003-0000-0000-0000-0000004E4553 & 06000004-0000-0000-0000-0000004E4553. 

I'm using the SDK nRF5 v15.3.0 on an nrf52840 DK as central.

I'm using the ble_app_interactive example.

When I'm requesting the characteristics from the peripheral device private service, it only finds one characteristic (the first added so first in the memory list ?).

Here is the CLI call and responses: 

uart_cli:~$ scan on
Scan started
<info> app: Scanning
uart_cli:~$ connect 00:1E:C0:43:15:8B
<info> app: CENTRAL: Connecting...
Connected to address: 00 1E C0 43 15 8B
<info> app: CENTRAL: Connected, handle: 0.
Current MTU: 23
MTU changed successfully
<info> app: Data length updated to 27 bytes.
uart_cli:~$ gatt services 00:1E:C0:43:15:8B  -> Here is somthing strange: I have to repeat gatt services twice to see the correct UUID in the list
<info> app: Services count: 3
Found service UUIDs:
UUID: 1800 type: 0x1
UUID: 1801 type: 0x1
UUID: 0 type: 0x2
uart_cli:~$ gatt services 00:1E:C0:43:15:8B
<info> app: Services count: 3
Found service UUIDs:
UUID: 1800 type: 0x1
UUID: 1801 type: 0x1
UUID: 2 type: 0x2
uart_cli:~$ gatt characteristics 00:1E:C0:43:15:8B 2
on_characteristics_discovery_rsp
Characteristic UUID: 3
Parameters:
broadcast: 0 read: 0 write_wo_resp: 0 write: 1 notify: 0
indicate: 0 auth_signed_wr: 0
Number of characteristics: 1
uart_cli:~$

Here is a screeshot from nrf connect for the exact same device: 

I've created a similar Gatt server advertiser with the same UUIDs on nrf connect and when I request the characteristics with the smartphone as peripheral device here the 2 characteristics are retrieved correctly:

uart_cli:~$ connect 60:66:4B:0A:51:EC
<info> app: CENTRAL: Connecting...
Connected to address: 60 66 4B 0A 51 EC
<info> app: CENTRAL: Connected, handle: 0.
<info> app: Data length updated to 251 bytes.
Current MTU: 247
MTU changed successfully
uart_cli:~$
Connection parameters update success
Connection parameters update success
uart_cli:~$ gatt services 60:66:4B:0A:51:EC
<info> app: Services count: 5
Found service UUIDs:
UUID: 1801 type: 0x1
UUID: 1800 type: 0x1
UUID: FE35 type: 0x1
UUID: 46A type: 0x1
UUID: 2 type: 0x2
uart_cli:~$
uart_cli:~$
uart_cli:~$ gatt characteristics 60:66:4B:0A:51:EC 2
on_characteristics_discovery_rsp
Characteristic UUID: 3
Parameters:
broadcast: 0 read: 0 write_wo_resp: 0 write: 1 notify: 0
indicate: 0 auth_signed_wr: 0
Characteristic UUID: 4
Parameters:
broadcast: 0 read: 0 write_wo_resp: 0 write: 1 notify: 0
indicate: 0 auth_signed_wr: 0
Number of characteristics: 2

Here is the Gatt server configuration on nrf connect :

I will try to get a sniffer capture tomorrow, any idea why this could happen ?

Thanks in advance,

Best regards,

Aloïs KYROU

Parents
  • Hello,

    I don't really know what the issue is. The best hint I can give without seeing what you do on your central side is to look at one of the examples that use the service discovery. For example the ble_app_uart_c example discovers the UART Service with two characteristics. Did you use a similar approach?

    Best regards,

    Edvin

  • Hello Edvin,

    The ble_app_interactive uses : 

    when calling gatt characteristics AA:BB:CC:DD:EE:FF : 

    Ask for characterisctics discovery  in cli_m.c:

    static void cmd_char_get(nrf_cli_t const * p_cli, size_t argc, char ** argv)
    {
        if ((argc == 1) || nrf_cli_help_requested(p_cli))
        {
            nrf_cli_help_print(p_cli, NULL, 0);
            return;
        }
    
        uint16_t   conn_handle;
        ret_code_t err_code;
    
        // Search for a connection handle.
        conn_handle = addr_string_to_conn_handle(argv[1]);
    
        if(!conn_handle_is_valid(conn_handle, p_cli))
        {
            return;
        }
    
        // Look for start handle range.
        ble_gattc_handle_range_t * p_handle_range = handle_range_search(argv[2], conn_handle);
    
        // Characteristic discovery.
        err_code = sd_ble_gattc_characteristics_discover(conn_handle, p_handle_range);
    
        if (err_code != NRF_SUCCESS)
        {
            nrf_cli_fprintf(p_cli,
                            NRF_CLI_ERROR,
                            "incorrect service UUID or service does not exist\n");
        }
    }

    Catches the result in ble_m.c:

    // catches BLE_GATTC_EVT_CHAR_DISC_RSP in ble_evt and calls : 
    static void on_characteristics_discovery_rsp(ble_gattc_evt_t const * p_ble_gattc_evt)
    {
        uint16_t        count;
        static uint16_t offset = 0;;
        uint16_t        bytes_to_copy;
        ret_code_t      err_code;
        uint16_t        conn_handle = p_ble_gattc_evt->conn_handle;
    
        // For readability.
        count = p_ble_gattc_evt->params.char_disc_rsp.count;
        ble_gattc_evt_char_disc_rsp_t const * p_char_disc_rsp_evt;
    
        p_char_disc_rsp_evt = &(p_ble_gattc_evt->params.char_disc_rsp);
    
        if (p_ble_gattc_evt->gatt_status == BLE_GATT_STATUS_SUCCESS)
        {
            if ((count + offset) > MAX_CHARACTERISTIC_COUNT)
            {
                bytes_to_copy = MAX_CHARACTERISTIC_COUNT - offset;
                NRF_LOG_RAW_INFO("Too many characteristics discovered\r\n");
            }
            else
            {
                bytes_to_copy = count;
            }
    
            // Save characteristics data.
           for (uint8_t i = offset; i < bytes_to_copy; i++)
           {
               m_srv_char.char_data[i].decl_handle      = p_char_disc_rsp_evt->chars[i].handle_decl;
               m_srv_char.char_data[i].value_handle     = p_char_disc_rsp_evt->chars[i].handle_value;
               m_srv_char.char_data[i].uuid             = p_char_disc_rsp_evt->chars[i].uuid;
               m_srv_char.char_data[i].notify           = p_char_disc_rsp_evt->chars[i].char_props.notify;
               m_srv_char.char_data[i].cccd_desc_handle = 0;
    
               offset++;
           }
    
           // Display characteristics data.
           for (uint8_t i = 0; i < offset; i++)
           {
               ble_gatt_char_props_t char_param =
                    p_ble_gattc_evt->params.char_disc_rsp.chars[i].char_props;
    
               NRF_LOG_RAW_INFO("Characteristic UUID: %X\r\n",
                                p_ble_gattc_evt->params.char_disc_rsp.chars[i].uuid.uuid);
               NRF_LOG_RAW_INFO("Parameters:\r\n");
               NRF_LOG_RAW_INFO("broadcast: %d ", char_param.broadcast);
               NRF_LOG_RAW_INFO("read: %d ", char_param.read);
               NRF_LOG_RAW_INFO("write_wo_resp: %d ", char_param.write_wo_resp);
               NRF_LOG_RAW_INFO("write: %d ", char_param.write);
               NRF_LOG_RAW_INFO("notify: %d\r\n", char_param.notify);
               NRF_LOG_RAW_INFO("indicate: %d ", char_param.indicate);
               NRF_LOG_RAW_INFO("auth_signed_wr: %d\r\n", char_param.auth_signed_wr);
           }
        }
        // If the last characteristic has not been reached, look for a new handle range.
        ble_gattc_handle_range_t handle_range;
    
        handle_range.start_handle = m_srv_char.char_data[offset - 1].value_handle + 1;
    
        // Search for end handle.
        for (uint8_t j = 0; j < mp_device_srv[conn_handle]->count; j++)
        {
            if (handle_range.start_handle >
                 mp_device_srv[conn_handle]->services[j].handle_range.start_handle)
            {
                handle_range.end_handle =
                    mp_device_srv[conn_handle]->services[j].handle_range.end_handle;
                break;
            }
        }
    
        // Handle value of the characteristic being discovered is less than the end handle of
        // the service being discovered. There is no possibility of more characteristics being
        // present.
        if ((m_srv_char.char_data[offset - 1].value_handle >= handle_range.end_handle) ||
            (offset == MAX_CHARACTERISTIC_COUNT) ||
            (p_ble_gattc_evt->gatt_status != BLE_GATT_STATUS_SUCCESS))
        {
            NRF_LOG_RAW_INFO("Number of characteristics: %d\r\n", offset);
            m_srv_char.count = offset;
            offset           = 0;
    
            // Search for the CCCD descriptors.
            cccd_descriptors_discovery(p_ble_gattc_evt);
    
            return;
        }
    
        // If the last Characteristic has not been reached, this function must be called again with new handle range.
        err_code = sd_ble_gattc_characteristics_discover(p_ble_gattc_evt->conn_handle, &handle_range);
        APP_ERROR_CHECK(err_code);
    }
    

    Same principle for services with : 

    sd_ble_gattc_primary_services_discover and on_primary_srv_discovery_rsp.sd_ble_gattc_primary_services_discover

    I'm looking into the uart example, the same function are called, except the xample uses the ble_discovery_c module. I'll try to set the UART service and characteristic on my peripheral and advertises with the NUS UUID in the advertisement report but since the same SoftDevice function is called I expect the same result :) 

    I keep you in touch about this test, if you have suggestion about the ble_app_interactive example i would love to here them. 

    I join a  sniffer capture between my peripheral device as slave and the nr52840 as master that contains: 

    • Connection request at frame 1292
    • First Services discovery at frame 1359 that doesnt show the Private service with UUID 2
    • Second Services discovery at frame 1384 that does show the Private service with UUID 2
    • A characteristics discovery on Private Service with UUID 2   at frame 1491 that discovered only one of the two characteristics

    Maybe you can see something I don't... 

    Anyway thanks for your help :) 

    Regards,

    Aloïs KYROU. 

  • I don't understand. Do you use the on_characteristic_discovery_rsp from ble_db_discovery.c on you central at all? And what does your equivalent of ble_nus_c_on_db_disc_evt() from the ble_app_uart_c example look like?

  • The ble_app_interactive example uses on_characteristics_discovery_rsp whereas ble_app_uart_c uses on_characteristic_discovery_rsp. 

    The ble_app_interactive has its own implementation of what does ble_discovery_db. 

    Using the ble_discovery_db in the ble_app_uart_c example apparently solves the problem as the two characteristics are found. Maybe a bug in the ble_app_interactive example ? 

    Anyway thanks for your help, i'll close the ticket. 

    Best regards,

    Aloïs KYROU.

  • Hi AKYR,

    Since I'm having the same issue could you please tell me how did you solve it? Did you use the on_characteristic_discovery_rsp on ble_m?

    I can't seem to find why the on_characteristics_discovery_rsp doesn't recognise all characteristics even on Blinky example.

    Thanks!

    Best regards,

    Hugo

  • Hello Hugo,

    To solve the problem i added the database discovery : https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.sdk5.v15.0.0%2Fgroup__ble__db__discovery.html

    You can see the ble_app_uart_c example in the SDK to see the implementation. 

    You first init the with a handler : ble_db_discovery_init(db_disc_handler);

    Then in the uart example, this handler calls back ble_nus_c_on_db_disc_evt(ble_nus_c_t * p_ble_nus_c, ble_db_discovery_evt_t * p_evt)

    In this function: ble_gatt_db_char_t * p_chars = p_evt->params.discovered_db.charateristics;

    Finally inside p_chars I have all the characteristics, even the one missing with the other method. 

    Tweak it for your convenience and it should work :) 

    Aloïs KYROU.

  • Thanks!

    I kinda knew that I had to do something like that but was trying to work around that function! Slight smile

    Hugo

Reply Children
No Data
Related