i am using the observer example but i am not seeing any advertising packet manufacturing data

Hi,

I am using the observer example which is quite good but i also want to see the manufacturing data of the advertising packet, i tried adding the buf->data for the net_buf_simple data type but this is not giving me what i would expect. below is the data i received:

[DEVICE]: 58:7B:5B:46:0B:41 (random), AD evt type 0, Tx Pwr: 127, RSSI -41 Data status: 0, AD data len: 31 Name: William's S21 C:1 S:1 D:0 SR:0 E:0 Pri PHY: LE 1M, Sec PHY: No packets, Interval: 0x0000 (0 ms), SID: 255, buf data 536901229

is there a way to print the advertising data manufacturing data?

thanks,

William

Parents
  • Hello William,

    Which observer example are you referring to here specifically, and where did you read out this buffer?
    Please use Insert -> Code when sharing code here on DevZone.

    Best regards,
    Karl

  • Hi Karl,

    Attached is the observer code i am using aswell as the config file.

    Thanks,

    William

    CONFIG_BT=y
    CONFIG_BT_OBSERVER=y
    
    # Enable Extended Scanning
    CONFIG_BT_EXT_ADV=y
    CONFIG_BT_EXT_SCAN_BUF_SIZE=1650
    
    # Zephyr Bluetooth LE Controller needs 16 event buffers to generate Extended
    # Advertising Report for receiving the complete 1650 bytes of data
    CONFIG_BT_BUF_EVT_RX_COUNT=16
    
    # Set maximum scan data length for Extended Scanning in Bluetooth LE Controller
    CONFIG_BT_CTLR_SCAN_DATA_LEN_MAX=1650
    
    # Increase Zephyr Bluetooth LE Controller Rx buffer to receive complete chain
    # of PDUs
    CONFIG_BT_CTLR_RX_BUFFERS=9
    

  • Hi Karl,

    Thanks for getting back to me, i have used the nrf connect app on my phone as an advertiser, here is the settings i used.

    Yes i commented out the call to bt_data_parse as i had added this in an attempt to get the manufacturing data. I then commented this out when it didnt work for me

    is there a way that is generally used to get the maufacturing data from a scan? or does this require a different function?

    Regards,

    William

  • Hello William,

    Thank you for sharing your configuration - it looks to me like your advertiser does not include the manufacturer specific data field, and so you will not be able to see it when you use the bt_data_parse function.
    On a related note, did you get the bt_data_parse function to work for the advertisers name?

    Please try this again against an advertiser that contains the manufacturer specific datafield, and let me know if you encounter any issues or questions! :) 

    Best regards,
    Karl

  • Hi Karl,

    thank you for your reply, i see, i had changed from manufacturing data to service data to see if it would give me the correct result for either as i originally was not getting the manufacturing data, i have tried this again and dont appear to be getting the correct data again. I do get the advertisers name: William's S21.

    Output from Observer:

    [DEVICE]: 45:05:A2:91:78:16 (random), AD evt type 0, Tx Pwr: 127, RSSI -81 Data status: 0, AD data len: 31 Name: William's S21 C:1 S:1 D:0 SR:0 E:0 Pri PHY: LE 1M, Sec PHY: No packets, Interval: 0x0000 (0 ms), SID: 255, buf data 536901229

    Advertiser setup:

    I am using the same code for this aswell.

    i had tried getting the buf->data before bt_data_parse() as it mentions the ad data can be consumed, i also did not get the correct data. 

    do i maybe need to parse the data using bt_data_parse() for the name and then the data aswell? im not sure i understand from the description of the function what is happening, is it only used for the device name?

    Regards,

    William

  • Hello,

    WilliamMcCoy21 said:
    thank you for your reply

    No problem at all, William - I am happy to help! :) 

    WilliamMcCoy21 said:
    i had changed from manufacturing data to service data to see if it would give me the correct result for either as i originally was not getting the manufacturing data, i have tried this again and dont appear to be getting the correct data again. I do get the advertisers name: William's S21.

    Thank you for clarifying, this is good to know.

    WilliamMcCoy21 said:
    do i maybe need to parse the data using bt_data_parse() for the name and then the data aswell? im not sure i understand from the description of the function what is happening, is it only used for the device name?

    Yes, you will need to populate the data_cb function for the BT_DATA_MANUFACTURER_DATA case in the same way that you have already populated it for the name case.
    Please give this a try and let me know if you are able to then have the manufacturer specific data returned in the same way as the device name is returned, or if you should encounter any issues or questions.

    Please make sure to use the same advertiser settings as shown in your last comment, with the Manufacturer specific datafield populated.

    Best regards,
    Karl

  • Hi Karl,

    I added a new callback function for Manufacturer data, with the same code in the case statement as the name. but that doesnt seem to work i am still getting the same data as before, it was not showing the type as manufacturer data before i added the manufacturing data to the scan response.

    Are there any examples that output manufacturing data or more details on how to set this up?

    Regards,

    William

Reply Children
  • This is the code i was using

    /*
     * Copyright (c) 2022 Nordic Semiconductor ASA
     * Copyright (c) 2015-2016 Intel Corporation
     *
     * SPDX-License-Identifier: Apache-2.0
     */
    
    #include <zephyr/sys/printk.h>
    #include <zephyr/bluetooth/bluetooth.h>
    #include <zephyr/bluetooth/hci.h>
    
    #define NAME_LEN 30
    #define MD_LEN 31
    
    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];
    
    	bt_addr_le_to_str(addr, addr_str, sizeof(addr_str));
    	printk("Device found: %s (RSSI %d), type %u, AD data len %u\r\n",
    	       addr_str, rssi, type, ad->len);
    	//bt_data_parse(ad, data_cb, (void *)addr);
    }
    
    #if defined(CONFIG_BT_EXT_ADV)
    static bool data_cb(struct bt_data *data, void *user_data)
    {
    	char *btdata = user_data;
    	uint8_t len;
    
    	switch (data->type) {
    	case BT_DATA_MANUFACTURER_DATA:
    		len = MIN(data->data_len, MD_LEN - 1);
    		(void)memcpy(btdata, data->data, len);
    		btdata[len] = '\0';
    		return false;
    	default:
    		return true;
    	}
    }
    
    static bool name_cb(struct bt_data *data, void *user_data)
    {
    	char *name = user_data;
    	uint8_t len;
    
    	switch (data->type) {
    	case BT_DATA_NAME_SHORTENED:
    	case BT_DATA_NAME_COMPLETE:
    		len = MIN(data->data_len, NAME_LEN - 1);
    		(void)memcpy(name, data->data, len);
    		name[len] = '\0';
    		return false;
    	default:
    		return true;
    	}
    }
    
    static const char *phy2str(uint8_t phy)
    {
    	switch (phy) {
    	case BT_GAP_LE_PHY_NONE: return "No packets";
    	case BT_GAP_LE_PHY_1M: return "LE 1M";
    	case BT_GAP_LE_PHY_2M: return "LE 2M";
    	case BT_GAP_LE_PHY_CODED: return "LE Coded";
    	default: return "Unknown";
    	}
    }
    
    static void scan_recv(const struct bt_le_scan_recv_info *info,
    		      struct net_buf_simple *buf)
    {
    	char le_addr[BT_ADDR_LE_STR_LEN];
    	char name[NAME_LEN];
    	char ManufacturerData[MD_LEN];
    	uint8_t data_status;
    	uint16_t data_len;
    
    	(void)memset(ManufacturerData, 0, sizeof(ManufacturerData));
    	(void)memset(name, 0, sizeof(name));
    	data_len = buf->len;
    	//bt_data_parse(buf, name_cb, name);
    	bt_data_parse(buf, data_cb, ManufacturerData);
    
    	data_status = BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS(info->adv_props);
    
    	bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr));
    	printk("[DEVICE]: %s, AD evt type %u, Tx Pwr: %i, RSSI %i "
    	       "Data status: %u, AD data len: %u Name: %s "
    	       "C:%u S:%u D:%u SR:%u E:%u Pri PHY: %s, Sec PHY: %s, "
    	       "Interval: 0x%04x (%u ms), SID: %u, buf data %u\n",
    	       le_addr, info->adv_type, info->tx_power, info->rssi,
    	       data_status, data_len, name,
    	       (info->adv_props & BT_GAP_ADV_PROP_CONNECTABLE) != 0,
    	       (info->adv_props & BT_GAP_ADV_PROP_SCANNABLE) != 0,
    	       (info->adv_props & BT_GAP_ADV_PROP_DIRECTED) != 0,
    	       (info->adv_props & BT_GAP_ADV_PROP_SCAN_RESPONSE) != 0,
    	       (info->adv_props & BT_GAP_ADV_PROP_EXT_ADV) != 0,
    	       phy2str(info->primary_phy), phy2str(info->secondary_phy),
    	       info->interval, info->interval * 5 / 4, info->sid, ManufacturerData);
    }
    
    static struct bt_le_scan_cb scan_callbacks = {
    	.recv = scan_recv,
    };
    #endif /* CONFIG_BT_EXT_ADV */
    
    int observer_start(void)
    {
    	struct bt_le_scan_param scan_param = {
    		.type       = BT_LE_SCAN_TYPE_PASSIVE,
    		.options    = BT_LE_SCAN_OPT_FILTER_DUPLICATE,
    		.interval   = BT_GAP_SCAN_FAST_INTERVAL,
    		.window     = BT_GAP_SCAN_FAST_WINDOW,
    	};
    	int err;
    
    #if defined(CONFIG_BT_EXT_ADV)
    	bt_le_scan_cb_register(&scan_callbacks);
    	printk("Registered scan callbacks\n");
    #endif /* CONFIG_BT_EXT_ADV */
    
    	err = bt_le_scan_start(&scan_param, device_found);
    	if (err) {
    		printk("Start scanning failed (err %d)\n", err);
    		return err;
    	}
    	printk("Started scanning...\n");
    
    	return 0;
    }
    

Related