How to read advertising BLE devices' name?

I've google the heck out of this, but I feel like I'm missing something because there are zero results.

I am developing a BLE central device, and the program is supposed to scan for advertising BLE devices, and list their address and name. Since the program is based off the "BLE Central" example, I have no issue reading their addresses, however, I cannot figure out how to read device names (e.g. "Zephyr BLE Module").

I know the BLE devices are advertising their names because I can see their names when I use the nRF Connect bluetooth app, but I want to be able to see their names through my own program, and print it to the console.

If it matters, the peripheral device is using the "BLE Peripheral" example.

  • Hi

    I'm looking into it and will get back to you tomorrow

    Regards

    Runar

  • Hi, 

    I'm working on making an example on this. In short what needs to be done is to decode the advertisement package data  and extract the name from there. The function bt_data_parse is used to parse the advertising data. The device name may not be broadcasted from all devices, this depends on the settings for the advertainment on the peripheral device. 

    Regards

    Runar

  • Hi. 

    If you use the bt_central example I you can add the following lines and functions to print out the device names: 

    Updated device found function: 

    static void device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type,
    			 struct net_buf_simple *ad)
    {
    	char addr_str[BT_ADDR_LE_STR_LEN];
    	char name[30];
    	int err;
    
    	if (default_conn) {
    		return;
    	}
    
    	/* We're only interested in connectable events */
    	if (type != BT_GAP_ADV_TYPE_ADV_IND &&
    	    type != BT_GAP_ADV_TYPE_ADV_DIRECT_IND) {
    		return;
    	}
    
    	bt_addr_le_to_str(addr, addr_str, sizeof(addr_str));
    	printk("Device found: %s (RSSI %d)\n", addr_str, rssi);
    
    	//seting up the bt_data_parse function and prints it. 
    	//
    	bt_data_parse(ad, data_cb, name);
    	printk("Device found: %s \n", name);
    
    	/* connect only to devices in close proximity */
    	if (rssi < -70) {
    		return;
    	}
    
    	if (bt_le_scan_stop()) {
    		return;
    	}
    
    	err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN,
    				BT_LE_CONN_PARAM_DEFAULT, &default_conn);
    	if (err) {
    		printk("Create conn to %s failed (%u)\n", addr_str, err);
    		start_scan();
    	}
    }

    Added function data_cb 

    #define NAME_LEN 30
    
    static bool data_cb(struct bt_data *data, void *user_data)
    {
    	char *name = user_data;
    
    	switch (data->type) {
    	case BT_DATA_NAME_SHORTENED:
    	case BT_DATA_NAME_COMPLETE:
    		memcpy(name, data->data, MIN(data->data_len, NAME_LEN - 1));
    		return false;
    	default:
    		return true;
    	}
    }
    

    Now your central will print out the name of the devices found during scanning. 

    Regards

    Runar

  • Thanks for the reply. I added this code, but I'm still not getting anything.

    The terminal says "Device Found: ", but does not actually list a name. However, the available devices definitely do have friendly names, as proven by my iPhone.

    Scanning successfully started
    Device Found: xx:xx:xx:xx:xx:x1 (random) (RSSI -79)
    Device Found:
    Device Found: xx:xx:xx:xx:xx:x2 (random) (RSSI -82)
    Device Found:
    Device Found: xx:xx:xx:xx:xx:x3 (random) (RSSI -60)
    Device Found:
    Connected: xx:xx:xx:xx:xx:x3 (public)
    Disconnected: xx:xx:xx:xx:xx:x3 (public) (reason 0x3e)

    Here are the functions after I've edited them:

    static bool data_cb(struct bt_data *data, void *user_data){
    
    	char *name = user_data;
    
    	switch(data->type){
    		case BT_DATA_NAME_SHORTENED:
    		case BT_DATA_NAME_COMPLETE:
    			memcpy(name, data->data, MIN(data->data_len, NAME_LEN - 1));
    			return false;
    		default:
    			return false;
    	}
    }

    static void device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type,
    			 struct net_buf_simple *ad)
    {
    	char addr_str[BT_ADDR_LE_STR_LEN];
    	char name[30];
    	int err;
    
    	if (default_conn) {
    		return;
    	}
    
    	/* We're only interested in connectable events */
    	if (type != BT_GAP_ADV_TYPE_ADV_IND &&
    	    type != BT_GAP_ADV_TYPE_ADV_DIRECT_IND) {
    		return;
    	}
    
    	bt_addr_le_to_str(addr, addr_str, sizeof(addr_str));
    	printk("Device found: %s (RSSI %d)\n", addr_str, rssi);
    
    	//setting up the bt_data_parse function and prints it.
    	bt_data_parse(ad, data_cb, name);
    	printk("Device found: %s \n", name);
    
    	/* connect only to devices in close proximity */
    	if (rssi < -70) {
    		return;
    	}
    
    	if (bt_le_scan_stop()) {
    		return;
    	}
    
    	err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN,
    				BT_LE_CONN_PARAM_DEFAULT, &default_conn);
    	if (err) {
    		printk("Create conn to %s failed (%u)\n", addr_str, err);
    		start_scan();
    	}
    }

    In the switch-case statement in the 'data_cb' function, it is triggering 'default', not 'BT_DATA_NAME_SHORTENED' or 'BT_DATA_NAME_COMPLETE'.

  • Interesting, I will see if I can replicate it. You could not find any names at all? 

    Also, do you have another dk you can set up as an peripheral? 

    Regards

    Runar

Related