esp32c3 - BLE advertisements, extracting manufacturer specific data

iMrFelix
Posts: 1
Joined: Sat Apr 17, 2021 2:23 pm

esp32c3 - BLE advertisements, extracting manufacturer specific data

Postby iMrFelix » Sat Apr 17, 2021 3:17 pm

I am running two esp32c3, one sends advertisements (call A) and the other is simply scanning passively (call B). The goal is that A broadcasts some data via BLE, B receives it and print it to console. The data should be stored in the manufacturer specified data section of an advertisement.

Problem:
Although B receives packets from A, I don't know how to parse them to be able to extract the manufacturer specified data!

What I did so far:

I set up A to advertise and B to scan continuously.
I have an Ubertooth plugged into my PC and can confirm that the packets sent by A are well-formed and that they indeed contain the correct payload.


A advertisement setup:

Code: Select all

static esp_ble_adv_params_t ble_adv_params = {
    .adv_int_min        = 0x0800,
    .adv_int_max        = 0x0900,	
    .adv_type           = ADV_TYPE_NONCONN_IND,
    .own_addr_type      = BLE_ADDR_TYPE_PUBLIC,
    .channel_map        = ADV_CHNL_ALL,
    .adv_filter_policy  = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, // NO IDEA ABOUT THAT ONE, ESPECIALLY GIVEN THAT WE SEND NONCONNECTABLE AND NONSCANNABLE ADVERTISEMENTS!
};
A advertisement data setup:

Code: Select all

esp_ble_adv_data_t ble_adv_data =
    {
    		.set_scan_rsp 			= false,
    		.include_name 			= true,								// "Name" refers to the name passed as an argument within "esp_ble_gap_set_device_name()"
    		.include_txpower 		= false,
    		.min_interval 			= 0xffff,							// Not sure what those are for, as the chosen advertisement packets are non-connectable...
    		.max_interval 			= 0xFFFF,
    		.appearance   			= 64,								// 64 is appearance ID of phone. Only to maybe be able to find it on my smartphone
    		.manufacturer_len 		= ble_adv_payload_len,
    		.p_manufacturer_data 	= (uint8_t *) ble_adv_payload,
    		.service_data_len 		= 0,
    		.p_service_data 		= NULL,
    		.service_uuid_len 		= 0,
    		.p_service_uuid 		= NULL,
    		.flag = 0
    };
--------------

B has a whitelist only containing A's public address.
B's scan parameters:

Code: Select all

static esp_ble_scan_params_t ble_scan_params = {
    .scan_type              = BLE_SCAN_TYPE_PASSIVE,		// Don't send scan requests upon receiving an advertisement
    .own_addr_type          = BLE_ADDR_TYPE_PUBLIC,			// Use (static) public address, makes debugging easier
    .scan_filter_policy     = BLE_SCAN_FILTER_ALLOW_ONLY_WLST,	// Consider all advertisements
    .scan_interval          = 0x50,							// Time between each scan window begin
    .scan_window            = 0x30,							// Length of scan window
    .scan_duplicate         = BLE_SCAN_DUPLICATE_DISABLE		// Filters out duplicate advertisements, e.g. if an advertisement received k times, it is only reported once
};
B's logic:
The only real logic besides the boilerplate code of setting up the bluedroid stack is the callback function that gets called whenever a GAP-Event happens:

Code: Select all

void esp_ble_callback_fun(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)
{
	switch (event) {
	case ESP_GAP_BLE_SCAN_RESULT_EVT:
		if ((param->scan_rst).search_evt != ESP_GAP_SEARCH_INQ_RES_EVT) {
			printf(
					"B: Callback function received a non-\"ESP_GAP_SEARCH_INQ_RES_EVT\" event!\n");
			return;
		}

		// Copy the parameter UNION
		esp_ble_gap_cb_param_t scan_result = *param;


		// Create a POINTER to the "bda" entry, which is accessed by interpreting the scan_result UNION as a scan_rst STRUCT
		// Note that "esp_bd_addr_t" is a typedef for a uint8_t array!
		esp_bd_addr_t *ble_adv_addr = &scan_result.scan_rst.bda;

		printf("\n-------------------------\nMessage!: \n");
		uint8_t adv_data_len  = scan_result.scan_rst.adv_data_len;
		uint8_t *adv_data     = scan_result.scan_rst.ble_adv;
		esp_ble_adv_data_t* received_payload = (esp_ble_adv_data_t*) adv_data;
		printf("Message length: %i\n", adv_data_len);
		printf("Message body:\n");					// NOT SO SURE ABOUT THIS!

		for(int i = 0; i < adv_data_len; ++i)
		{
			printf("%X", adv_data[i]);
		}
		printf("\n-------------------------\n");

		break; // @suppress("No break at end of case")
	default:
		// WONT BE SUPPORTED! JUST IGNORE THEM!
		break;
	}
}
Sample output:
Serial output from B:

Code: Select all

Message!: 
Message length: 22
Message body:
31940069414C4943454FF486579512FFFFFFFF
Packet sniffed by Wireshark using the Ubertooth dongle:

Code: Select all

Frame 78135: 61 bytes on wire (488 bits), 61 bytes captured (488 bits) on interface /tmp/pipe, id 0
PPI version 0, 24 bytes
    Version: 0
    Flags: 0x00
        .... ...0 = Alignment: Not aligned
        0000 000. = Reserved: 0x00
    Header length: 24
    DLT: 251
    Reserved: 36750c0000620900e05b56b811051000
Bluetooth
Bluetooth Low Energy Link Layer
    Access Address: 0x8e89bed6
    Packet Header: 0x1c22 (PDU Type: ADV_NONCONN_IND, ChSel: #2, TxAdd: Public)
        .... 0010 = PDU Type: ADV_NONCONN_IND (0x2)
        ...0 .... = RFU: 0
        ..1. .... = Channel Selection Algorithm: #2
        .0.. .... = Tx Address: Public
        0... .... = Reserved: False
        Length: 28
    Advertising Address: Espressi_43:3e:d6 (7c:df:a1:43:3e:d6)
    Advertising Data
        Appearance: Generic Phone
        Device Name: ALICE
        Manufacturer Specific
        Slave Connection Interval Range: 81918.8 - 81918.8 msec
        Connection Interval Min: 65535 (81918.8 msec)
        Connection Interval Max: 65535 (81918.8 msec)
    CRC: 0x905934




My questions:
  • What is stored in "ble_adv" (esp_gap_ble_api.h, line 936)?
    Note: I reckon it contains the packet, but if I convert the content of the ble_adv to binary and compare it with the binary of the message received via the Ubertooth, only a very short substring of the binary matches (For an empty manufacturer payload, only 46 bits matched).
  • How can B extract the manufacturer specified data from the advertisement sent by A?

Who is online

Users browsing this forum: No registered users and 128 guests