BLE5 features to use with C3/S3 (#5085)

Added new BLE5 features to use on C3/S3 family:

extended scan,
extended/multi advertising
New code is not fancy (no feedback from events), but i think it is functional. To get feedback from events i am suggesting to use custom GAP callback, which is already implemented in BLEDevice.
This commit is contained in:
chegewara 2021-04-22 12:01:20 +02:00 committed by GitHub
parent e62ff6dc37
commit 7856de7a57
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 909 additions and 1 deletions

View File

@ -0,0 +1,69 @@
/*
BLE5 extended scan example for esp32 C3 and S3
with this code it is simple to scan legacy (BLE4) compatible advertising,
and BLE5 extended advertising. New coded added in BLEScan is not changing old behavior,
which can be used with old esp32, but is adding functionality to use on C3/S3.
With this new API advertised device wont be stored in API, it is now user responsibility
author: chegewara
*/
#ifndef CONFIG_BT_BLE_50_FEATURES_SUPPORTED
#warning "Not compatible hardware"
#else
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>
uint32_t scanTime = 100; //In 10ms (1000ms)
BLEScan* pBLEScan;
/**
* @brief extend adv report parameters
*/
//typedef struct {
// esp_ble_gap_adv_type_t event_type; /*!< extend advertising type */
// uint8_t addr_type; /*!< extend advertising address type */
// esp_bd_addr_t addr; /*!< extend advertising address */
// esp_ble_gap_pri_phy_t primary_phy; /*!< extend advertising primary phy */
// esp_ble_gap_phy_t secondly_phy; /*!< extend advertising secondary phy */
// uint8_t sid; /*!< extend advertising sid */
// uint8_t tx_power; /*!< extend advertising tx power */
// int8_t rssi; /*!< extend advertising rssi */
// uint16_t per_adv_interval; /*!< periodic advertising interval */
// uint8_t dir_addr_type; /*!< direct address type */
// esp_bd_addr_t dir_addr; /*!< direct address */
// esp_ble_gap_ext_adv_data_status_t data_status; /*!< data type */
// uint8_t adv_data_len; /*!< extend advertising data length */
// uint8_t adv_data[251]; /*!< extend advertising data */
//} esp_ble_gap_ext_adv_reprot_t;
class MyBLEExtAdvertisingCallbacks: public BLEExtAdvertisingCallbacks {
void onResult(esp_ble_gap_ext_adv_reprot_t report) {
if(report.event_type & ESP_BLE_GAP_SET_EXT_ADV_PROP_LEGACY){
// here we can receive regular advertising data from BLE4.x devices
Serial.println("BLE4.2");
} else {
// here we will get extended advertising data that are advertised over data channel by BLE5 divices
Serial.printf("Ext advertise: data_le: %d, data_status: %d \n", report.adv_data_len, report.data_status);
}
}
};
void setup() {
Serial.begin(115200);
Serial.println("Scanning...");
BLEDevice::init("");
pBLEScan = BLEDevice::getScan(); //create new scan
pBLEScan->setExtendedScanCallback(new MyBLEExtAdvertisingCallbacks());
pBLEScan->setExtScanParams(); // use with pre-defined/default values, overloaded function allows to pass parameters
delay(1000); // it is just for simplicity this example, to let ble stack to set extended scan params
pBLEScan->startExtScan(scanTime, 3); // scan duration in n * 10ms, period - repeat after n seconds (period >= duration)
}
void loop() {
// put your main code here, to run repeatedly:
delay(2000);
}
#endif // CONFIG_BT_BLE_50_FEATURES_SUPPORTED

View File

@ -0,0 +1,142 @@
/*
Simple BLE5 multi advertising example on esp32 C3/S3
only ESP_BLE_GAP_SET_EXT_ADV_PROP_LEGACY_IND is backward compatible
and can be scanned with BLE4.2 devices
author: chegewara
*/
#include <BLEDevice.h>
#include <BLEAdvertising.h>
esp_ble_gap_ext_adv_params_t ext_adv_params_1M = {
.type = ESP_BLE_GAP_SET_EXT_ADV_PROP_CONNECTABLE,
.interval_min = 0x30,
.interval_max = 0x30,
.channel_map = ADV_CHNL_ALL,
.own_addr_type = BLE_ADDR_TYPE_RANDOM,
.filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY,
.primary_phy = ESP_BLE_GAP_PHY_CODED,
.max_skip = 0,
.secondary_phy = ESP_BLE_GAP_PHY_1M,
.sid = 0,
.scan_req_notif = false,
};
esp_ble_gap_ext_adv_params_t ext_adv_params_2M = {
.type = ESP_BLE_GAP_SET_EXT_ADV_PROP_SCANNABLE,
.interval_min = 0x40,
.interval_max = 0x40,
.channel_map = ADV_CHNL_ALL,
.own_addr_type = BLE_ADDR_TYPE_RANDOM,
.filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY,
.primary_phy = ESP_BLE_GAP_PHY_1M,
.max_skip = 0,
.secondary_phy = ESP_BLE_GAP_PHY_2M,
.sid = 1,
.scan_req_notif = false,
};
esp_ble_gap_ext_adv_params_t legacy_adv_params = {
.type = ESP_BLE_GAP_SET_EXT_ADV_PROP_LEGACY_IND,
.interval_min = 0x45,
.interval_max = 0x45,
.channel_map = ADV_CHNL_ALL,
.own_addr_type = BLE_ADDR_TYPE_RANDOM,
.filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY,
.primary_phy = ESP_BLE_GAP_PHY_1M,
.max_skip = 0,
.secondary_phy = ESP_BLE_GAP_PHY_1M,
.sid = 2,
.scan_req_notif = false,
};
esp_ble_gap_ext_adv_params_t ext_adv_params_coded = {
.type = ESP_BLE_GAP_SET_EXT_ADV_PROP_SCANNABLE,
.interval_min = 0x50,
.interval_max = 0x50,
.channel_map = ADV_CHNL_ALL,
.own_addr_type = BLE_ADDR_TYPE_RANDOM,
.filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY,
.primary_phy = ESP_BLE_GAP_PHY_1M,
.max_skip = 0,
.secondary_phy = ESP_BLE_GAP_PHY_CODED,
.sid = 3,
.scan_req_notif = false,
};
static uint8_t raw_adv_data_1m[] = {
0x02, 0x01, 0x06,
0x02, 0x0a, 0xeb,
0x12, 0x09, 'E', 'S', 'P', '_', 'M', 'U', 'L', 'T', 'I', '_', 'A',
'D', 'V', '_', '1', 'M', 0X0
};
static uint8_t raw_scan_rsp_data_2m[] = {
0x02, 0x01, 0x06,
0x02, 0x0a, 0xeb,
0x12, 0x09, 'E', 'S', 'P', '_', 'M', 'U', 'L', 'T', 'I', '_', 'A',
'D', 'V', '_', '2', 'M', 0X0
};
static uint8_t legacy_adv_data[] = {
0x02, 0x01, 0x06,
0x02, 0x0a, 0xeb,
0x15, 0x09, 'E', 'S', 'P', '_', 'M', 'U', 'L', 'T', 'I', '_', 'A',
'D', 'V', '_', 'C', 'O', 'D', 'E', 'D', 0X0
};
static uint8_t legacy_scan_rsp_data[] = {
0x02, 0x01, 0x06,
0x02, 0x0a, 0xeb,
0x16, 0x09, 'E', 'S', 'P', '_', 'M', 'U', 'L', 'T', 'I', '_', 'A',
'D', 'V', '_', 'L', 'E', 'G', 'A', 'C', 'Y', 0X0
};
static uint8_t raw_scan_rsp_data_coded[] = {
0x37, 0x09, 'V', 'E', 'R', 'Y', '_', 'L', 'O', 'N', 'G', '_', 'D', 'E', 'V', 'I', 'C', 'E', '_', 'N', 'A', 'M', 'E', '_',
'S', 'E', 'N', 'T', '_', 'U', 'S', 'I', 'N', 'G', '_', 'E', 'X', 'T', 'E', 'N', 'D', 'E', 'D', '_', 'A', 'D', 'V', 'E', 'R', 'T', 'I', 'S', 'I', 'N', 'G', 0X0
};
uint8_t addr_1m[6] = {0xc0, 0xde, 0x52, 0x00, 0x00, 0x01};
uint8_t addr_2m[6] = {0xc0, 0xde, 0x52, 0x00, 0x00, 0x02};
uint8_t addr_legacy[6] = {0xc0, 0xde, 0x52, 0x00, 0x00, 0x03};
uint8_t addr_coded[6] = {0xc0, 0xde, 0x52, 0x00, 0x00, 0x04};
BLEMultiAdvertising advert(4); // max number of advertisement data
void setup() {
Serial.begin(115200);
Serial.println("Multi-Advertising...");
BLEDevice::init("");
advert.setAdvertisingParams(0, &ext_adv_params_1M);
advert.setAdvertisingData(0, sizeof(raw_adv_data_1m), &raw_adv_data_1m[0]);
advert.setInstanceAddress(0, addr_1m);
advert.setDuration(0);
advert.setAdvertisingParams(1, &ext_adv_params_2M);
advert.setScanRspData(1, sizeof(raw_scan_rsp_data_2m), &raw_scan_rsp_data_2m[0]);
advert.setInstanceAddress(1, addr_2m);
advert.setDuration(1);
advert.setAdvertisingParams(2, &legacy_adv_params);
advert.setAdvertisingData(2, sizeof(legacy_adv_data), &legacy_adv_data[0]);
advert.setScanRspData(2, sizeof(legacy_scan_rsp_data), &legacy_scan_rsp_data[0]);
advert.setInstanceAddress(2, addr_legacy);
advert.setDuration(2);
advert.setAdvertisingParams(3, &ext_adv_params_coded);
advert.setDuration(3);
advert.setScanRspData(3, sizeof(raw_scan_rsp_data_coded), &raw_scan_rsp_data_coded[0]);
advert.setInstanceAddress(3, addr_coded);
delay(1000);
advert.start(4, 0);
}
void loop() {
delay(2000);
}

View File

@ -0,0 +1,72 @@
/*
Simple BLE5 multi advertising example on esp32 C3/S3
only ESP_BLE_GAP_SET_EXT_ADV_PROP_NONCONN_NONSCANNABLE_UNDIRECTED can be used for periodic advertising
author: chegewara
*/
#include <BLEDevice.h>
#include <BLEAdvertising.h>
esp_ble_gap_ext_adv_params_t ext_adv_params_2M = {
.type = ESP_BLE_GAP_SET_EXT_ADV_PROP_NONCONN_NONSCANNABLE_UNDIRECTED,
.interval_min = 0x40,
.interval_max = 0x40,
.channel_map = ADV_CHNL_ALL,
.own_addr_type = BLE_ADDR_TYPE_RANDOM,
.filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY,
.primary_phy = ESP_BLE_GAP_PHY_1M,
.max_skip = 0,
.secondary_phy = ESP_BLE_GAP_PHY_2M,
.sid = 1,
.scan_req_notif = false,
};
static uint8_t raw_scan_rsp_data_2m[] = {
0x02, 0x01, 0x06,
0x02, 0x0a, 0xeb,
0x12, 0x09, 'E', 'S', 'P', '_', 'M', 'U', 'L', 'T', 'I', '_', 'A',
'D', 'V', '_', '2', 'M', 0X0
};
static esp_ble_gap_periodic_adv_params_t periodic_adv_params = {
.interval_min = 0x320, // 1000 ms interval
.interval_max = 0x640,
.properties = 0, // Do not include TX power
};
static uint8_t periodic_adv_raw_data[] = {
0x02, 0x01, 0x06,
0x02, 0x0a, 0xeb,
0x03, 0x03, 0xab, 0xcd,
0x11, 0x09, 'E', 'S', 'P', '_', 'P', 'E', 'R', 'I', 'O', 'D', 'I',
'C', '_', 'A', 'D', 'V'
};
uint8_t addr_2m[6] = {0xc0, 0xde, 0x52, 0x00, 0x00, 0x02};
BLEMultiAdvertising advert(1); // max number of advertisement data
void setup() {
Serial.begin(115200);
Serial.println("Multi-Advertising...");
BLEDevice::init("");
advert.setAdvertisingParams(0, &ext_adv_params_2M);
advert.setAdvertisingData(0, sizeof(raw_scan_rsp_data_2m), &raw_scan_rsp_data_2m[0]);
advert.setInstanceAddress(0, addr_2m);
advert.setDuration(0, 0, 0);
delay(100);
advert.start();
advert.setPeriodicAdvertisingParams(0, &periodic_adv_params);
advert.setPeriodicAdvertisingData(0, sizeof(periodic_adv_raw_data), &periodic_adv_raw_data[0]);
advert.startPeriodicAdvertising(0);
}
void loop() {
delay(2000);
}

View File

@ -0,0 +1,127 @@
/*
BLE5 extended scan example for esp32 C3 and S3
with this code it is simple to scan legacy (BLE4) compatible advertising,
and BLE5 extended advertising. New coded added in BLEScan is not changing old behavior,
which can be used with old esp32, but is adding functionality to use on C3/S3.
With this new API advertised device wont be stored in API, it is now user responsibility
author: chegewara
*/
#ifndef CONFIG_BT_BLE_50_FEATURES_SUPPORTED
#warning "Not compatible hardware"
#else
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
BLEScan *pBLEScan;
static bool periodic_sync = false;
static esp_ble_gap_periodic_adv_sync_params_t periodic_adv_sync_params = {
.filter_policy = 0,
.sid = 0,
.addr_type = BLE_ADDR_TYPE_RANDOM,
.skip = 10,
.sync_timeout = 1000, // timeout: 1000 * 10ms
};
/**
* @brief extend adv report parameters
*/
//typedef struct {
// esp_ble_gap_adv_type_t event_type; /*!< extend advertising type */
// uint8_t addr_type; /*!< extend advertising address type */
// esp_bd_addr_t addr; /*!< extend advertising address */
// esp_ble_gap_pri_phy_t primary_phy; /*!< extend advertising primary phy */
// esp_ble_gap_phy_t secondly_phy; /*!< extend advertising secondary phy */
// uint8_t sid; /*!< extend advertising sid */
// uint8_t tx_power; /*!< extend advertising tx power */
// int8_t rssi; /*!< extend advertising rssi */
// uint16_t per_adv_interval; /*!< periodic advertising interval */
// uint8_t dir_addr_type; /*!< direct address type */
// esp_bd_addr_t dir_addr; /*!< direct address */
// esp_ble_gap_ext_adv_data_status_t data_status; /*!< data type */
// uint8_t adv_data_len; /*!< extend advertising data length */
// uint8_t adv_data[251]; /*!< extend advertising data */
//} esp_ble_gap_ext_adv_reprot_t;
class MyBLEExtAdvertisingCallbacks : public BLEExtAdvertisingCallbacks
{
void onResult(esp_ble_gap_ext_adv_reprot_t params)
{
uint8_t *adv_name = NULL;
uint8_t adv_name_len = 0;
adv_name = esp_ble_resolve_adv_data(params.adv_data, ESP_BLE_AD_TYPE_NAME_CMPL, &adv_name_len);
if ((adv_name != NULL) && (memcmp(adv_name, "ESP_MULTI_ADV_2M", adv_name_len) == 0) && !periodic_sync)
{
periodic_sync = true;
char adv_temp_name[60] = {'0'};
memcpy(adv_temp_name, adv_name, adv_name_len);
log_i("Start create sync with the peer device %s", adv_temp_name);
periodic_adv_sync_params.sid = params.sid;
// periodic_adv_sync_params.addr_type = params.addr_type;
memcpy(periodic_adv_sync_params.addr, params.addr, sizeof(esp_bd_addr_t));
esp_ble_gap_periodic_adv_create_sync(&periodic_adv_sync_params);
}
}
};
class MyPeriodicScan : public BLEPeriodicScanCallbacks
{
// void onCreateSync(esp_bt_status_t status){}
// void onCancelSync(esp_bt_status_t status){}
// void onTerminateSync(esp_bt_status_t status){}
void onStop(esp_bt_status_t status)
{
log_i("ESP_GAP_BLE_EXT_SCAN_STOP_COMPLETE_EVT");
periodic_sync = false;
pBLEScan->startExtScan(0, 0); // scan duration in n * 10ms, period - repeat after n seconds (period >= duration)
}
void onLostSync(uint16_t sync_handle)
{
log_i("ESP_GAP_BLE_PERIODIC_ADV_SYNC_LOST_EVT");
esp_ble_gap_stop_ext_scan();
}
void onSync(esp_ble_periodic_adv_sync_estab_param_t params)
{
log_i("ESP_GAP_BLE_PERIODIC_ADV_SYNC_ESTAB_EVT, status %d", params.status);
// esp_log_buffer_hex("sync addr", param->periodic_adv_sync_estab.adv_addr, 6);
log_i("sync handle %d sid %d perioic adv interval %d adv phy %d", params.sync_handle,
params.sid,
params.period_adv_interval,
params.adv_phy);
}
void onReport(esp_ble_gap_periodic_adv_report_t params)
{
log_i("periodic adv report, sync handle %d data status %d data len %d rssi %d", params.sync_handle,
params.data_status,
params.data_length,
params.rssi);
}
};
void setup()
{
Serial.begin(115200);
Serial.println("Periodic scan...");
BLEDevice::init("");
pBLEScan = BLEDevice::getScan(); //create new scan
pBLEScan->setExtendedScanCallback(new MyBLEExtAdvertisingCallbacks());
pBLEScan->setExtScanParams(); // use with pre-defined/default values, overloaded function allows to pass parameters
pBLEScan->setPeriodicScanCallback(new MyPeriodicScan());
delay(100); // it is just for simplicity this example, to let ble stack to set extended scan params
pBLEScan->startExtScan(0, 0);
}
void loop()
{
delay(2000);
}
#endif // CONFIG_BT_BLE_50_FEATURES_SUPPORTED

View File

@ -124,5 +124,20 @@ public:
virtual void onResult(BLEAdvertisedDevice advertisedDevice) = 0;
};
#ifdef CONFIG_BT_BLE_50_FEATURES_SUPPORTED
class BLEExtAdvertisingCallbacks {
public:
virtual ~BLEExtAdvertisingCallbacks() {}
/**
* @brief Called when a new scan result is detected.
*
* As we are scanning, we will find new devices. When found, this call back is invoked with a reference to the
* device that was found. During any individual scan, a device will only be detected one time.
*/
virtual void onResult(esp_ble_gap_ext_adv_reprot_t report) = 0;
};
#endif // CONFIG_BT_BLE_50_FEATURES_SUPPORTED
#endif /* CONFIG_BLUEDROID_ENABLED */
#endif /* COMPONENTS_CPP_UTILS_BLEADVERTISEDDEVICE_H_ */

View File

@ -528,5 +528,242 @@ void BLEAdvertising::handleGAPEvent(
}
}
#ifdef CONFIG_BT_BLE_50_FEATURES_SUPPORTED
/**
* @brief Creator
*
* @param[in] instance : number of multi advertising instances
*
*
*/
BLEMultiAdvertising::BLEMultiAdvertising(uint8_t num)
{
params_arrays = (esp_ble_gap_ext_adv_params_t*)calloc(num, sizeof(esp_ble_gap_ext_adv_params_t));
ext_adv = (esp_ble_gap_ext_adv_t*)calloc(num, sizeof(esp_ble_gap_ext_adv_t));
count = num;
}
/**
* @brief This function is used by the Host to set the advertising parameters.
*
* @param[in] instance : identifies the advertising set whose parameters are being configured.
* @param[in] params : advertising parameters
*
* @return - true : success
* - false : failed
*
*/
bool BLEMultiAdvertising::setAdvertisingParams(uint8_t instance, const esp_ble_gap_ext_adv_params_t* params)
{
if (params->type == ESP_BLE_GAP_SET_EXT_ADV_PROP_LEGACY_IND && params->primary_phy == ESP_BLE_GAP_PHY_2M) return false;
esp_err_t rc;
rc = esp_ble_gap_ext_adv_set_params(instance, params);
return ESP_OK == rc;
}
/**
* @brief This function is used to set the data used in advertising PDUs that have a data field
*
* @param[in] instance : identifies the advertising set whose data are being configured
* @param[in] length : data length
* @param[in] data : data information
*
* @return - true : success
* - false : failed
*
*/
bool BLEMultiAdvertising::setAdvertisingData(uint8_t instance, uint16_t length, const uint8_t* data)
{
esp_err_t rc;
rc = esp_ble_gap_config_ext_adv_data_raw(instance, length, data);
if (rc) log_e("set advertising data err: %d", rc);
return ESP_OK == rc;
}
bool BLEMultiAdvertising::setScanRspData(uint8_t instance, uint16_t length, const uint8_t* data)
{
esp_err_t rc;
rc = esp_ble_gap_config_ext_scan_rsp_data_raw(instance, length, data);
if (rc) log_e("set scan resp data err: %d", rc);
return ESP_OK == rc;
}
/**
* @brief This function is used to request the Controller to disable one or more
* advertising sets using the advertising sets identified by the instance parameter.
*
* @return - true : success
* - false : failed
*
*/
bool BLEMultiAdvertising::start()
{
return start(count, 0);
}
/**
* @brief This function is used to request the Controller to disable one or more
* advertising sets using the advertising sets identified by the instance parameter.
*
* @param[in] num : Number of advertising sets to enable or disable
* @param[in] from : first sxt adv set to use
*
* @return - true : success
* - false : failed
*
*/
bool BLEMultiAdvertising::start(uint8_t num, uint8_t from)
{
if (num > count || from >= count) return false;
esp_err_t rc;
rc = esp_ble_gap_ext_adv_start(num, &ext_adv[from]);
if (rc) log_e("start extended advertising err: %d", rc);
return ESP_OK == rc;
}
/**
* @brief This function is used to request the Controller to disable one or more
* advertising sets using the advertising sets identified by the instance parameter.
*
* @param[in] num_adv : Number of advertising sets to enable or disable
* @param[in] ext_adv_inst : ext adv instance
*
* @return - ESP_OK : success
* - other : failed
*
*/
bool BLEMultiAdvertising::stop(uint8_t num_adv, const uint8_t* ext_adv_inst)
{
esp_err_t rc;
rc = esp_ble_gap_ext_adv_stop(num_adv, ext_adv_inst);
if (rc) log_e("stop extended advertising err: %d", rc);
return ESP_OK == rc;
}
/**
* @brief This function is used to remove an advertising set from the Controller.
*
* @param[in] instance : Used to identify an advertising set
*
* @return - ESP_OK : success
* - other : failed
*
*/
bool BLEMultiAdvertising::remove(uint8_t instance)
{
esp_err_t rc;
rc = esp_ble_gap_ext_adv_set_remove(instance);
if (rc) log_e("remove extended advertising err: %d", rc);
return ESP_OK == rc;
}
/**
* @brief This function is used to remove all existing advertising sets from the Controller.
*
*
* @return - ESP_OK : success
* - other : failed
*
*/
bool BLEMultiAdvertising::clear()
{
esp_err_t rc;
rc = esp_ble_gap_ext_adv_set_clear();
if (rc) log_e("clear extended advertising err: %d", rc);
return ESP_OK == rc;
}
/**
* @brief This function is used by the Host to set the random device address specified by the Random_Address parameter.
*
* @param[in] instance : Used to identify an advertising set
* @param[in] addr_legacy : Random Device Address
*
* @return - true : success
* - false : failed
*
*/
bool BLEMultiAdvertising::setInstanceAddress(uint8_t instance, uint8_t* addr_legacy)
{
esp_err_t rc;
rc = esp_ble_gap_ext_adv_set_rand_addr(instance, addr_legacy);
if (rc) log_e("set random address err: %d", rc);
return ESP_OK == rc;
}
/**
* @brief This function is used by the Host to set the parameters for periodic advertising.
*
* @param[in] instance : identifies the advertising set whose periodic advertising parameters are being configured.
* @param[in] params : periodic adv parameters
*
* @return - true : success
* - false : failed
*
*/
bool BLEMultiAdvertising::setPeriodicAdvertisingParams(uint8_t instance, const esp_ble_gap_periodic_adv_params_t* params)
{
esp_err_t rc;
rc = esp_ble_gap_periodic_adv_set_params(instance, params);
if (rc) log_e("set periodic advertising params err: %d", rc);
return ESP_OK == rc;
}
/**
* @brief This function is used to set the data used in periodic advertising PDUs.
*
* @param[in] instance : identifies the advertising set whose periodic advertising parameters are being configured.
* @param[in] length : the length of periodic data
* @param[in] data : periodic data information
*
* @return - true : success
* - false : failed
*
*/
bool BLEMultiAdvertising::setPeriodicAdvertisingData(uint8_t instance, uint16_t length, const uint8_t* data)
{
esp_err_t rc;
rc = esp_ble_gap_config_periodic_adv_data_raw(instance, length, data);
if (rc) log_e("set periodic advertising raw data err: %d", rc);
return ESP_OK == rc;
}
/**
* @brief This function is used to request the Controller to enable the periodic advertising for the advertising set specified
*
* @param[in] instance : Used to identify an advertising set
*
* @return - true : success
* - false : failed
*
*/
bool BLEMultiAdvertising::startPeriodicAdvertising(uint8_t instance)
{
esp_err_t rc;
rc = esp_ble_gap_periodic_adv_start(instance);
if (rc) log_e("start periodic advertising err: %d", rc);
return ESP_OK == rc;
}
void BLEMultiAdvertising::setDuration(uint8_t instance, int duration, int max_events)
{
ext_adv[instance] = { instance, duration, max_events };
}
#endif // CONFIG_BT_BLE_50_FEATURES_SUPPORTED
#endif /* CONFIG_BLUEDROID_ENABLED */

View File

@ -78,5 +78,36 @@ private:
bool m_scanResp = true;
};
#ifdef CONFIG_BT_BLE_50_FEATURES_SUPPORTED
class BLEMultiAdvertising
{
private:
esp_ble_gap_ext_adv_params_t* params_arrays;
esp_ble_gap_ext_adv_t* ext_adv;
uint8_t count;
public:
BLEMultiAdvertising(uint8_t num = 1);
~BLEMultiAdvertising() {}
bool setAdvertisingParams(uint8_t instance, const esp_ble_gap_ext_adv_params_t* params);
bool setAdvertisingData(uint8_t instance, uint16_t length, const uint8_t* data);
bool setScanRspData(uint8_t instance, uint16_t length, const uint8_t* data);
bool start();
bool start(uint8_t num, uint8_t from);
void setDuration(uint8_t instance, int duration = 0, int max_events = 0);
bool setInstanceAddress(uint8_t instance, esp_bd_addr_t rand_addr);
bool stop(uint8_t num_adv, const uint8_t* ext_adv_inst);
bool remove(uint8_t instance);
bool clear();
bool setPeriodicAdvertisingParams(uint8_t instance, const esp_ble_gap_periodic_adv_params_t* params);
bool setPeriodicAdvertisingData(uint8_t instance, uint16_t length, const uint8_t* data);
bool startPeriodicAdvertising(uint8_t instance);
};
#endif // CONFIG_BT_BLE_50_FEATURES_SUPPORTED
#endif /* CONFIG_BLUEDROID_ENABLED */
#endif /* COMPONENTS_CPP_UTILS_BLEADVERTISING_H_ */

View File

@ -3,6 +3,9 @@
*
* Created on: Jul 1, 2017
* Author: kolban
*
* Update: April, 2021
* add BLE5 support
*/
#include "sdkconfig.h"
#if defined(CONFIG_BLUEDROID_ENABLED)
@ -142,6 +145,98 @@ void BLEScan::handleGAPEvent(
break;
} // ESP_GAP_BLE_SCAN_RESULT_EVT
#ifdef CONFIG_BT_BLE_50_FEATURES_SUPPORTED
case ESP_GAP_BLE_EXT_ADV_REPORT_EVT: {
if (param->ext_adv_report.params.event_type & ESP_BLE_GAP_SET_EXT_ADV_PROP_LEGACY) {
log_v("legacy adv, adv type 0x%x data len %d", param->ext_adv_report.params.event_type, param->ext_adv_report.params.adv_data_len);
}
else {
log_v("extend adv, adv type 0x%x data len %d, data status: %d", param->ext_adv_report.params.event_type, param->ext_adv_report.params.adv_data_len, param->ext_adv_report.params.data_status);
}
if (m_pExtendedScanCb != nullptr)
{
m_pExtendedScanCb->onResult(param->ext_adv_report.params);
}
break;
}
case ESP_GAP_BLE_SET_EXT_SCAN_PARAMS_COMPLETE_EVT: {
if (param->set_ext_scan_params.status != ESP_BT_STATUS_SUCCESS) {
log_e("extend scan parameters set failed, error status = %x", param->set_ext_scan_params.status);
break;
}
log_v("extend scan params set successfully");
break;
}
case ESP_GAP_BLE_EXT_SCAN_START_COMPLETE_EVT:
if (param->ext_scan_start.status != ESP_BT_STATUS_SUCCESS) {
log_e("scan start failed, error status = %x", param->scan_start_cmpl.status);
break;
}
log_v("Scan start success");
break;
case ESP_GAP_BLE_EXT_SCAN_STOP_COMPLETE_EVT:
if (m_pPeriodicScanCb != nullptr)
{
m_pPeriodicScanCb->onStop(param->ext_scan_stop.status);
}
if (param->ext_scan_stop.status != ESP_BT_STATUS_SUCCESS){
log_e("extend Scan stop failed, error status = %x", param->ext_scan_stop.status);
break;
}
log_v("Stop extend scan successfully");
break;
case ESP_GAP_BLE_PERIODIC_ADV_CREATE_SYNC_COMPLETE_EVT:
if (m_pPeriodicScanCb != nullptr)
{
m_pPeriodicScanCb->onCreateSync(param->period_adv_create_sync.status);
}
log_v("ESP_GAP_BLE_PERIODIC_ADV_CREATE_SYNC_COMPLETE_EVT, status %d", param->period_adv_create_sync.status);
break;
case ESP_GAP_BLE_PERIODIC_ADV_SYNC_CANCEL_COMPLETE_EVT:
if (m_pPeriodicScanCb != nullptr)
{
m_pPeriodicScanCb->onCancelSync(param->period_adv_sync_cancel.status);
}
log_v("ESP_GAP_BLE_PERIODIC_ADV_SYNC_CANCEL_COMPLETE_EVT, status %d", param->period_adv_sync_cancel.status);
break;
case ESP_GAP_BLE_PERIODIC_ADV_SYNC_TERMINATE_COMPLETE_EVT:
if (m_pPeriodicScanCb != nullptr)
{
m_pPeriodicScanCb->onTerminateSync(param->period_adv_sync_term.status);
}
log_v("ESP_GAP_BLE_PERIODIC_ADV_SYNC_TERMINATE_COMPLETE_EVT, status %d", param->period_adv_sync_term.status);
break;
case ESP_GAP_BLE_PERIODIC_ADV_SYNC_LOST_EVT:
if (m_pPeriodicScanCb != nullptr)
{
m_pPeriodicScanCb->onLostSync(param->periodic_adv_sync_lost.sync_handle);
}
log_v("ESP_GAP_BLE_PERIODIC_ADV_SYNC_LOST_EVT, sync handle %d", param->periodic_adv_sync_lost.sync_handle);
break;
case ESP_GAP_BLE_PERIODIC_ADV_SYNC_ESTAB_EVT:
if (m_pPeriodicScanCb != nullptr)
{
m_pPeriodicScanCb->onSync(*(esp_ble_periodic_adv_sync_estab_param_t*)&param->periodic_adv_sync_estab);
}
log_v("ESP_GAP_BLE_PERIODIC_ADV_SYNC_ESTAB_EVT, status %d", param->periodic_adv_sync_estab.status);
break;
case ESP_GAP_BLE_PERIODIC_ADV_REPORT_EVT:
if (m_pPeriodicScanCb != nullptr)
{
m_pPeriodicScanCb->onReport(param->period_adv_report.params);
}
break;
#endif // CONFIG_BT_BLE_50_FEATURES_SUPPORTED
default: {
break;
@ -177,6 +272,89 @@ void BLEScan::setAdvertisedDeviceCallbacks(BLEAdvertisedDeviceCallbacks* pAdvert
m_shouldParse = shouldParse;
} // setAdvertisedDeviceCallbacks
#ifdef CONFIG_BT_BLE_50_FEATURES_SUPPORTED
void BLEScan::setExtendedScanCallback(BLEExtAdvertisingCallbacks* cb)
{
m_pExtendedScanCb = cb;
}
/**
* @brief This function is used to set the extended scan parameters to be used on the advertising channels.
*
*
* @return - ESP_OK : success
* - other : failed
*
*/
esp_err_t BLEScan::setExtScanParams()
{
esp_ble_ext_scan_params_t ext_scan_params = {
.own_addr_type = BLE_ADDR_TYPE_PUBLIC,
.filter_policy = BLE_SCAN_FILTER_ALLOW_ALL,
.scan_duplicate = BLE_SCAN_DUPLICATE_DISABLE,
.cfg_mask = ESP_BLE_GAP_EXT_SCAN_CFG_UNCODE_MASK | ESP_BLE_GAP_EXT_SCAN_CFG_CODE_MASK,
.uncoded_cfg = {BLE_SCAN_TYPE_ACTIVE, 40, 40},
.coded_cfg = {BLE_SCAN_TYPE_ACTIVE, 40, 40},
};
esp_err_t rc = esp_ble_gap_set_ext_scan_params(&ext_scan_params);
if (rc) {
log_e("set extend scan params error, error code = %x", rc);
}
return rc;
}
/**
* @brief This function is used to set the extended scan parameters to be used on the advertising channels.
*
* @param[in] params : scan parameters
*
* @return - ESP_OK : success
* - other : failed
*
*/
esp_err_t BLEScan::setExtScanParams(esp_ble_ext_scan_params_t* ext_scan_params)
{
esp_err_t rc = esp_ble_gap_set_ext_scan_params(ext_scan_params);
if (rc) {
log_e("set extend scan params error, error code = %x", rc);
}
return rc;
}
/**
* @brief This function is used to enable scanning.
*
* @param[in] duration : Scan duration
* @param[in] period : Time interval from when the Controller started its last Scan Duration until it begins the subsequent Scan Duration.
*
* @return - ESP_OK : success
* - other : failed
*
*/
esp_err_t BLEScan::startExtScan(uint32_t duration, uint16_t period)
{
esp_err_t rc = esp_ble_gap_start_ext_scan(duration, period);
if(rc) log_e("extended scan start failed: %d", rc);
return rc;
}
esp_err_t BLEScan::stopExtScan()
{
esp_err_t rc;
rc = esp_ble_gap_stop_ext_scan();
return rc;
}
void BLEScan::setPeriodicScanCallback(BLEPeriodicScanCallbacks* cb)
{
m_pPeriodicScanCb = cb;
}
#endif // CONFIG_BT_BLE_50_FEATURES_SUPPORTED
/**
* @brief Set the interval to scan.
* @param [in] The interval in msecs.

View File

@ -19,9 +19,21 @@
class BLEAdvertisedDevice;
class BLEAdvertisedDeviceCallbacks;
class BLEExtAdvertisingCallbacks;
class BLEClient;
class BLEScan;
class BLEPeriodicScanCallbacks;
struct esp_ble_periodic_adv_sync_estab_param_t {
uint8_t status; /*!< periodic advertising sync status */
uint16_t sync_handle; /*!< periodic advertising sync handle */
uint8_t sid; /*!< periodic advertising sid */
esp_ble_addr_type_t adv_addr_type; /*!< periodic advertising address type */
esp_bd_addr_t adv_addr; /*!< periodic advertising address */
esp_ble_gap_phy_t adv_phy; /*!< periodic advertising phy type */
uint16_t period_adv_interval; /*!< periodic advertising interval */
uint8_t adv_clk_accuracy; /*!< periodic advertising clock accuracy */
};
/**
* @brief The result of having performed a scan.
@ -62,13 +74,25 @@ public:
BLEScanResults getResults();
void clearResults();
#ifdef CONFIG_BT_BLE_50_FEATURES_SUPPORTED
void setExtendedScanCallback(BLEExtAdvertisingCallbacks* cb);
void setPeriodicScanCallback(BLEPeriodicScanCallbacks* cb);
esp_err_t stopExtScan();
esp_err_t setExtScanParams();
esp_err_t setExtScanParams(esp_ble_ext_scan_params_t* ext_scan_params);
esp_err_t startExtScan(uint32_t duration, uint16_t period);
private:
BLEExtAdvertisingCallbacks* m_pExtendedScanCb = nullptr;
BLEPeriodicScanCallbacks* m_pPeriodicScanCb = nullptr;
#endif // CONFIG_BT_BLE_50_FEATURES_SUPPORTED
private:
BLEScan(); // One doesn't create a new instance instead one asks the BLEDevice for the singleton.
friend class BLEDevice;
void handleGAPEvent(
esp_gap_ble_cb_event_t event,
esp_ble_gap_cb_param_t* param);
void parseAdvertisement(BLEClient* pRemoteDevice, uint8_t *payload);
esp_ble_scan_params_t m_scan_params;
@ -81,5 +105,18 @@ private:
void (*m_scanCompleteCB)(BLEScanResults scanResults);
}; // BLEScan
class BLEPeriodicScanCallbacks {
public:
virtual ~BLEPeriodicScanCallbacks() {}
virtual void onCreateSync(esp_bt_status_t status) {}
virtual void onCancelSync(esp_bt_status_t status) {}
virtual void onTerminateSync(esp_bt_status_t status) {}
virtual void onLostSync(uint16_t sync_handle) {}
virtual void onSync(esp_ble_periodic_adv_sync_estab_param_t) {}
virtual void onReport(esp_ble_gap_periodic_adv_report_t params) {}
virtual void onStop(esp_bt_status_t status) {}
};
#endif /* CONFIG_BLUEDROID_ENABLED */
#endif /* COMPONENTS_CPP_UTILS_BLESCAN_H_ */