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.

Parents
  • 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'.

  • Hi, 

    Can you try to change "start_scan" to:

     

    err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, device_found);
    
    to
    
    err = bt_le_scan_start(BT_LE_SCAN_ACTIVE, device_found);

    and

    add update device_found with this:

    	if (type != BT_GAP_ADV_TYPE_ADV_IND &&
    	    type != BT_GAP_ADV_TYPE_ADV_DIRECT_IND &&
    		type != BT_GAP_ADV_TYPE_SCAN_RSP  ) {
    		return;
    	}

    Regards

    Runar

  • Just tried this, but no change to the result.

    "peripheral_uart" to "central" shows the name.

    "peripheral" to "central" does not show the name.

  • Hi, can you please upload your projects. I tested with the peripheral example and central example and I had no problems finding the peripheral device. 

    Regards

    Runar

  • I am working with a clean 'central' and clean 'peripheral' example, except the changes you suggested.

    I believe I found the cause of the issue, maybe you could explain why it's happening.

    In the 'central' sketch, in 'device_found()' there's a filter for proximity:

    if (rssi < -70) {
    		return;
    	}

    When I changed '-70' to '-50', this fixed the issue, however, I'm confused as to why, since the average RSSI for that device is -60, and often times around -40 to -50, but when the filter is set to -70, it NEVER reports the peripheral device name (even though it DOES find the MAC address).

    Even more confusing is why the signal strength is different for the 'peripheral' and 'peripheral_uart' examples when they're performed on the exact same device?

  • Hi, 

    Neither "peripheral" or "peripheral_uart" includes any code that changes the transmission gain rom what I can see, so they should be similar. 

    As for the code snippet

    if (rssi < -70) {
    		return;
    	}

    Its only for connecting to a device. The data from the advertisement package should be readable without connecting to the device. So the filter should not have any effect on the readout that happens before any connection. 

    When you say without any modifications: Did you remove the parsing of the advertisement data to extract the device name? 

    Regards

    Runar

Reply
  • Hi, 

    Neither "peripheral" or "peripheral_uart" includes any code that changes the transmission gain rom what I can see, so they should be similar. 

    As for the code snippet

    if (rssi < -70) {
    		return;
    	}

    Its only for connecting to a device. The data from the advertisement package should be readable without connecting to the device. So the filter should not have any effect on the readout that happens before any connection. 

    When you say without any modifications: Did you remove the parsing of the advertisement data to extract the device name? 

    Regards

    Runar

Children
No Data
Related