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

Find name of advertiser

Hi - I am trying to port some code from nRF5 SDK to NRF Connect SDK. 

I set up a scan for a specific BT_SCAN_FILTER_TYPE_NAME name and then using the scan_filter_no_match event I get the details of the peripheral that caused the event.

I then make sure that the UUID matches what I am looking for and then see if the rssi is greater than the strongest value I have found so far. If so, then I save the peer address.

After three seconds I stop the scan and then start scanning again using SCAN_ADDR_FILTER so that that peripheral connects to me.

I would like to know how to achieve the same with NRF CONNECT SDK. Below is the existing code from NRF5 SDK.

Please help....

case NRF_BLE_SCAN_EVT_NOT_FOUND: // new case added. Implement ble_advdata.c->ble_advdata_name_find() type function here
{
ble_gap_evt_adv_report_t const * adv_report = p_scan_evt->params.p_not_found;

/* Scan encoded adv. payload for data of type BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME */
parsed_len = ble_advdata_search(adv_report->data.p_data, adv_report->data.len, &data_offset, BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME);

if (parsed_len != 0)
{
/* Name found if parsed_len != 0 */
p_parsed = &adv_report->data.p_data[data_offset];

// make sure not besecure
if (*p_parsed != 'B')
{
data_offset = 0;
parsed_len = ble_advdata_search(adv_report->data.p_data, adv_report->data.len, &data_offset, BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_COMPLETE);
p_parsed = &adv_report->data.p_data[data_offset];

if (parsed_len != 0)
{
if (memcmp(&bsc_service_uuid, p_parsed, parsed_len)== 0)
{
if (p_scan_evt->params.filter_match.p_adv_report->rssi > scanrssi)
{
memcpy_fast(&strongest_peer, &p_scan_evt->params.filter_match.p_adv_report->peer_addr, 8);
scanrssi = p_scan_evt->params.filter_match.p_adv_report->rssi;
sysStat.found = 1;
}
}
}
}
}
break;
}

Parents
  • Hi,

    There is a Scanning module in the nRF Connect SDK which  scan module in the nRF5 SDK which provide mostly the same functionality as what you are now using from the Scanning Module in the nRF5 SDK. That allows you to filter on both name and UUID, as well as other parameters. You can see examples of it's usage in the Bluetooth central samples in NCS.

  • Hi - I have looked at the scanning module documentation in depth and I cannot see how to do the equivalent. I just needed a pointer in the right direction. I am sure it is there, but whwre?

  • Hi,

    I am not sure exactly what problem you have. If it is about getting some advertising parameter you are not filtering on (like name when filtering on the UUID), then you need to parse the whole advertising packet which you get a pointer to. This is described in the API documentation for the adv_data field in the bt_scan_device_info struct: "Received advertising data. If further data processing is needed, you should use bt_data_parse() to get specific advertising data type.".

    If the above is not the problem, then perhaps you can clarify a bit more exactly what you are not able to do, as I am not able to see any specific features you need that are missing based on the description in your initial post.

  • Hi - I have probably not made myself clear enough. I would like to be able to check the UUID and the SCAN NAME of the peripheral each time a scan_filter_match event is called. I have set the scan module not to connect on match. I am trying to find the strongest rssi for a given UUID.

  • Hi,

    I made a simple example which I hope will show how this works. Here the scan module filter on UUID, and for advertising packets (and scan response packets) that match I also search for the name and print that. You can do the same in any combination to look fore more data and or other data.

    #include <zephyr/types.h>
    #include <stddef.h>
    #include <inttypes.h>
    #include <errno.h>
    #include <zephyr.h>
    #include <sys/printk.h>
    
    #include <bluetooth/bluetooth.h>
    #include <bluetooth/hci.h>
    #include <bluetooth/conn.h>
    #include <bluetooth/uuid.h>
    #include <bluetooth/gatt.h>
    #include <bluetooth/gatt_dm.h>
    #include <bluetooth/scan.h>
    #include <settings/settings.h>
    
    #define NAME_LEN            30
    
    
    static bool data_cb(struct bt_data *data, void *user_data)
    {
    	char *name = user_data;
    	uint8_t len;
    
    	switch (data->type) {
    
    	case BT_DATA_NAME_SHORTENED:
    		// Fallthrough
    	case BT_DATA_NAME_COMPLETE:
    	 	len = MIN(data->data_len, NAME_LEN - 1);
    		memcpy(name, data->data, len);
    		name[len] = '\0';
    		return false; // Do not search anymore
    	default:
    		return true; // Continue seraching through data
    	}
    }
    
    
    static void scan_filter_match(struct bt_scan_device_info *device_info,
    			      struct bt_scan_filter_match *filter_match,
    			      bool connectable)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	bt_addr_le_to_str(device_info->recv_info->addr, addr, sizeof(addr));
    
    	printk("Filters matched. Address: %s connectable: %s\n",
    		addr, connectable ? "yes" : "no");
    
    	// Parse advertising packet searching for advertising name.
    	char name[NAME_LEN];
    	(void)memset(name, 0, sizeof(name));
    	bt_data_parse(device_info->adv_data, data_cb, name);
    	printk("name: %s\n", name);
    }
    
    
    static void scan_filter_no_match(struct bt_scan_device_info *device_info,
    				 bool connectable)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	if (device_info->recv_info->adv_type == BT_GAP_ADV_TYPE_ADV_DIRECT_IND) {
    		bt_addr_le_to_str(device_info->recv_info->addr, addr,
    				  sizeof(addr));
    		printk("Direct advertising received from %s\n", addr);
    	}
    }
    
    
    BT_SCAN_CB_INIT(scan_cb, scan_filter_match, scan_filter_no_match,
    		NULL, NULL);
    
    static void scan_init(void)
    {
    	int err;
    
    	struct bt_scan_init_param scan_init = {
    		.connect_if_match = 0,
    		.scan_param = NULL,
    	};
    
    	bt_scan_init(&scan_init);
    	bt_scan_cb_register(&scan_cb);
    
    	err = bt_scan_filter_add(BT_SCAN_FILTER_TYPE_UUID, BT_UUID_BAS);
    	if (err) {
    		printk("Scanning filters cannot be set (err %d)\n", err);
    		return;
    	}
    
    	err = bt_scan_filter_enable(BT_SCAN_UUID_FILTER, false);
    	if (err) {
    		printk("Filters cannot be turned on (err %d)\n", err);
    	}
    }
    
    
    void main(void)
    {
    	int err;
    
    	printk("Starting Bluetooth Scanner sample");
    
    	err = bt_enable(NULL);
    	if (err) {
    		printk("Bluetooth init failed (err %d)\n", err);
    		return;
    	}
    
    	printk("Bluetooth initialized\n");
    
    	if (IS_ENABLED(CONFIG_SETTINGS)) {
    		settings_load();
    	}
    
    	scan_init();
    
    	err = bt_scan_start(BT_SCAN_TYPE_SCAN_ACTIVE);
    	if (err) {
    		printk("Scanning failed to start (err %d)\n", err);
    		return;
    	}
    
    	printk("Scanning successfully started\n");
    }
    

    I want to mention one thing which sometimes cause confusion. The functionality used here works on single packets alone, so if for instance the UUID is in the advertisement packet and the name in the scan response, then you will not find both with this approach (this is also the same with the scan module in the nRF5 DK). You would have to put your own logic on top if you need such functionality.

  • Great - That is what I wanted. Thank you. I appreciate your help.

    Will close.

Reply Children
No Data
Related