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

BLE peripheral whitelist advertising

Dear all,

Can I achieve ble peripheral whitelist advertising without peer manager? (Assuming central address is already known)

Following are several places that I've modified based on ble_app_uart but it will cause an assert:

First part is whitelist address function.

static void whitelist_set()
{
	ble_gap_addr_t peer_address;
	ble_gap_addr_t const *p_peer_address;
	uint32_t err_code;
	
	/*
	Traget central addr:0x15ca97ce14f4
	*/
	peer_address.addr[5] = 0x15;
	peer_address.addr[4] = 0xca;
	peer_address.addr[3] = 0x97;
	peer_address.addr[2] = 0xce;
	peer_address.addr[1] = 0x14;
	peer_address.addr[0] = 0xf4;
	p_peer_address = &peer_address;
	
	err_code = sd_ble_gap_whitelist_set(&p_peer_address, 0x01);
	APP_ERROR_CHECK(err_code);
}

adding previous function into BLE_ADV_EVT_WHITELIST_REQUEST

static void on_adv_evt(ble_adv_evt_t ble_adv_evt)
{
    uint32_t err_code;

    switch (ble_adv_evt)
    {
        case BLE_ADV_EVT_FAST:
            err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING);
            APP_ERROR_CHECK(err_code);
            break;
        case BLE_ADV_EVT_IDLE:
            sleep_mode_enter();
            break;
		case BLE_ADV_EVT_WHITELIST_REQUEST:
            whitelist_set();
			break; //BLE_ADV_EVT_WHITELIST_REQUEST
        default:
            break;
    }
}

Enabling the whitelist in adv parameters.

static void advertising_init(void)
{
    uint32_t               err_code;
    ble_advertising_init_t init;

    memset(&init, 0, sizeof(init));

    init.advdata.name_type          = BLE_ADVDATA_FULL_NAME;
    init.advdata.include_appearance = false;
    init.advdata.flags              = BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE;

    init.srdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);
    init.srdata.uuids_complete.p_uuids  = m_adv_uuids;

    init.config.ble_adv_fast_enabled  = true;
    init.config.ble_adv_fast_interval = APP_ADV_INTERVAL;
    init.config.ble_adv_fast_timeout  = APP_ADV_DURATION;
    init.evt_handler = on_adv_evt;

		/* Modified parts */
		init.config.ble_adv_whitelist_enabled          = true;
    init.config.ble_adv_directed_high_duty_enabled = true;
    init.config.ble_adv_directed_enabled           = false;
    init.config.ble_adv_directed_interval          = 0;
    init.config.ble_adv_directed_timeout           = 0;
	
    err_code = ble_advertising_init(&m_advertising, &init);
    APP_ERROR_CHECK(err_code);

    ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG);
}

Did I implement anything wrong or did I miss anything?

Thanks,

Ava

Parents
  • Hi,

    This looks mostly correct. You should set the address type in the ble_gap_addr_t before calling sd_ble_gap_whitelist_set(), though.

    There could be some other errors also that I do not spot, but in general this looks good.

    Does it not work? If not, how does it fail and does any API call return an error?

  • Hi,

    Seems like the assert occurs here:

    err_code = sd_ble_gap_whitelist_set(&p_peer_address, 0x01);
    APP_ERROR_CHECK(err_code);

    When peer_address_type is selected to BLE_GAP_ADDR_TYPE_RANDOM_STATIC, it will assert...

  • Hi,

    When you say assert I assume you means that the error handler has detected an error? If you make a debug build (define "DEBUG") and enable logging I expect you will get more information. Alternatively, place a breakpoint on the line after the call to sd_ble_gap_whitelist_set() and inspect the return value. Looking at the address from your previous post I see it is not a valid static address (the 5th byte does not have the two most significant bits set). Therefor, it is expected that the call returns NRF_ERROR_INVALID_ADDR. The address type you specify must correspond with the address itself.

  • Thanks Einar,

    I'm trying to figure it out.

    BTW, what's the different between those address types?

    Basically I'll connect a peripheral to ble_app_uart_central to check its address. More specifically, the peripheral address will be printed here(in scan_evt_handler):

             case NRF_BLE_SCAN_EVT_CONNECTED:
             {
                  ble_gap_evt_connected_t const * p_connected =
                                   p_scan_evt->params.connected.p_connected;
                 // Scan is automatically stopped by the connection.
    							printf("Connecting to target %02x%02x%02x%02x%02x%02x",
                          p_connected->peer_addr.addr[0],
                          p_connected->peer_addr.addr[1],
                          p_connected->peer_addr.addr[2],
                          p_connected->peer_addr.addr[3],
                          p_connected->peer_addr.addr[4],
                          p_connected->peer_addr.addr[5]
                          );
             } break;

    What address type is this? If I burn new program(central) into the same device, does the address remain the same?

    If so, if I wanna put this address into the whitelist, which address type should I select?

    Thanks,

    Ava

Reply
  • Thanks Einar,

    I'm trying to figure it out.

    BTW, what's the different between those address types?

    Basically I'll connect a peripheral to ble_app_uart_central to check its address. More specifically, the peripheral address will be printed here(in scan_evt_handler):

             case NRF_BLE_SCAN_EVT_CONNECTED:
             {
                  ble_gap_evt_connected_t const * p_connected =
                                   p_scan_evt->params.connected.p_connected;
                 // Scan is automatically stopped by the connection.
    							printf("Connecting to target %02x%02x%02x%02x%02x%02x",
                          p_connected->peer_addr.addr[0],
                          p_connected->peer_addr.addr[1],
                          p_connected->peer_addr.addr[2],
                          p_connected->peer_addr.addr[3],
                          p_connected->peer_addr.addr[4],
                          p_connected->peer_addr.addr[5]
                          );
             } break;

    What address type is this? If I burn new program(central) into the same device, does the address remain the same?

    If so, if I wanna put this address into the whitelist, which address type should I select?

    Thanks,

    Ava

Children
  • Hi Ava,

    Avadacadabara said:
    BTW, what's the different between those address types?

    This page has a good explanation of the different address types.

    Avadacadabara said:
    What address type is this?

    Looking at the code snippet from your post a few days ago, where the most significant byte was 0x15, you can look at the two most significant bits to see that the address type there is private resolvable. This is typically used by modern mobile phones for instance. Note that the upper bits does not have this meaning for a public address so it cannot be ruled out by looking at this. That means that there could also be another issue here instead.

    Avadacadabara said:
    If I burn new program(central) into the same device, does the address remain the same?

    If the central is using private resolvable address, then the address change regularly.

    Avadacadabara said:
    If so, if I wanna put this address into the whitelist, which address type should I select?

    If this is as it seems private resolvable address then you should select BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE. Note that if the central is using a resolvable private address then whitelisting like this will not work. That is because the address will change regularly, and in that case you will need to obtain the Identity Resolution Key (IRK) in order to make whitelisting work even as the address change. And to obtain this the devices need to pair, and then the IRK is exchanged during the pairing process (if you have another method to obtain the IRK that would also work, but the only standard way to exchange it is via pairing).

  • Thanks Einar,

    Thanks for your help!

    I read through the explanation and I found that I've messed up the MSB and LSB.

    I tried to get central address with "sd_ble_gap_addr_get()"

    then I got:

    Type: 1
    addr[0]: 0x48
    addr[1]:0x90
    addr[2]: 0x51
    addr[3]: 0xeb
    addr[4]: 0x76
    addr[5]: 0xf2

    Which means the address type is RANDOM STATIC.

    Whitelist setting seems passed with this address, but I could still connect to the peripheral with nrf_connect app(the address is another nRF52832 DK board).

    I try to modify the whitelist address to  a wrong one but it could still connect with 52832 DK, seems like the whitelist is nor working...

    P.S.: I forgot to inform you that I'm using SDK16.

    Thanks,

    Ava

  • Hi Ava, 

    Avadacadabara said:
    I read through the explanation and I found that I've messed up the MSB and LSB.

    I see, then it makes sense. 

    Avadacadabara said:
    I try to modify the whitelist address to  a wrong one but it could still connect with 52832 DK, seems like the whitelist is nor working...

    I see. Could it be that you (like most example) disable whitelisting after some time? I do not see any reference to that in your code snippets here, but perhaps in other parts of your code?

Related