SDK 16: Get Device Name from Advertising Data

This seems to have changed in recent SDKs, so that none of the examples or techniques mentioned in previous posts is relevant any more.

I am using the SDK v16.0.0 ble_app_blinky_c_pca10040_s132 example on a PC10040 board.

I have added code in the ble_evt_handler() in main.c to handle the BLE_GAP_EVT_ADV_REPORT event:

static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
{
    ret_code_t err_code;

    // For readability.
    ble_gap_evt_t const * p_gap_evt = &p_ble_evt->evt.gap_evt;

    switch (p_ble_evt->header.evt_id)
    {
        case BLE_GAP_EVT_ADV_REPORT:
        {
            //sprintf( buf, )
            NRF_LOG_INFO("Adv Rep: %02X %02X %02X %02X %02X %02X",
                            p_gap_evt->params.adv_report.peer_addr.addr[5],
                            p_gap_evt->params.adv_report.peer_addr.addr[4],
                            p_gap_evt->params.adv_report.peer_addr.addr[3],
                            p_gap_evt->params.adv_report.peer_addr.addr[2],
                            p_gap_evt->params.adv_report.peer_addr.addr[1],
                            p_gap_evt->params.adv_report.peer_addr.addr[0]
                             );

            ;
            NRF_LOG_HEXDUMP_INFO(p_gap_evt->params.adv_report.data.p_data, p_gap_evt->params.adv_report.data.len);

            char * p_msg = "Full  Name: '%s'";
            uint8_t *device_name = ble_advdata_parse(p_gap_evt->params.adv_report.data.p_data, p_gap_evt->params.adv_report.data.len, BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME);
            if( NULL == device_name )
            {
                char * p_msg = "Short Name: '%s'";

                device_name = ble_advdata_parse(p_gap_evt->params.adv_report.data.p_data, p_gap_evt->params.adv_report.data.len, BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME);
            }
            if( NULL == device_name )
            {
                NRF_LOG_INFO( p_msg, device_name );
            }
            else
            {
                NRF_LOG_INFO( "No Name" );
            }
            

It should

  1. Log the device address from the Advertising Report;
  2. Log the entire Advertising Data;
  3. Extract the Device Name from the Advertising Data, and log it

Logging the Device Address works;

Logging the entire Advertising Data shows that the Device Name is present;

But Extracting the Device Name does not work.

eg, from a Thingy:52:

[Tue Jan 14 14:59:04.093 2020] <info> app: Adv Rep: C6 1A BD D5 43 2E
[Tue Jan 14 14:59:04.100 2020] <info> app:  02 01 06 11 06 42 00 74|.....B.t
[Tue Jan 14 14:59:04.102 2020] <info> app:  A9 FF 52 10 9B 33 49 35|..R..3I5
[Tue Jan 14 14:59:04.108 2020] <info> app:  9B 00 01 68 EF 09 08 54|...h.	.T
[Tue Jan 14 14:59:04.111 2020] <info> app:  68 69 6E 67 79 3A 35   |hingy:5 
[Tue Jan 14 14:59:04.117 2020] <info> app: No Name
[Tue Jan 14 14:59:04.120 2020] <info> app: Adv Rep: C6 1A BD D5 43 2E
[Tue Jan 14 14:59:04.124 2020] <info> app:  07 FF 59 00 14 42 71 53|..Y..BqS
[Tue Jan 14 14:59:04.128 2020] <info> app: Full  Name: ''

C6:1A:BD:D5:43:2E is, indeed, the address of the Thingy; and the "Thingy:5" text can clearly be seen in the 1st dump.

But why is it giving two BLE_GAP_EVT_ADV_REPORT events - where each one only seems to have part of the Advertising Data, and neither finds the Name properly?

Even in the old threads, it is never clearly explained how the "extracted" Name can be used. Some show it being printed (as above),  but I don't think that can be right - as it does not seem to be a valid NUL-terminated 'C' string.

Parents
No Data
Reply
  • Hi,

    why is it giving two BLE_GAP_EVT_ADV_REPORT events

    The second BLE_GAP_EVT_ADV_REPORT is most likely the scan response packet.

    and neither finds the Name properly

    I think the logic in the last if-else should be swithced. I.e.

                if( NULL == device_name )
                {
                    NRF_LOG_INFO( "No Name" );
                }
                else
                {
                    NRF_LOG_INFO( p_msg, device_name );
                }

    Also, if you are using deferred processing for the logger module, you should use nrf_log_push() to copy the string into the logger buffer. See this link.

    NRF_LOG_INFO( p_msg, NRF_LOG_PUSH(device_name));

    It might also be better to use ble_advdata_search() instead of ble_advdata_parse(), since you also get the length of the name with ble_advdata_search(). Take a look at how it's done in e.g. device_to_list_add() function in file ble_m.c found in \examples\ble_central_and_peripheral\experimental\ble_app_interactive

Children
  • Thanks

    The second BLE_GAP_EVT_ADV_REPORT is most likely the scan response

    I guess I could check that from 'type' field in the advertising report event?

    Does the Scan module always do filtering on Scan Response as well as Advertising ?

    I think the logic in the last if-else should be swithced

    Oops - I think you're right there!

    better to use ble_advdata_search()

    Having been fiddling with this since the OP, that's the conclusion I was coming to.

    So what is the point of ble_advdata_parse() ? It doesn't seem very useful to know where a thing is without also knowing its length ?

    if you are using deferred processing for the logger module, you should use nrf_log_push()

    Will check that ...

    Take a look at how it's done in e.g. device_to_list_add()

    ... and that

  • Take a look at ... \examples\ble_central_and_peripheral\experimental\ble_app_interactive

    actually, that example seems to be doing what I was trying to achieve anyhow - list devices currently advertising, and pick one to connect to.

    the connection drops immediately with reason 0x3E

    but that's another issue ...

Related