11 Commits

Author SHA1 Message Date
Julio Contreras Fuica
dd71e3e11a Add generic advertisement 'type' functions (#575) 2023-11-25 08:17:06 -07:00
h2zero
b2dba08649 Fix build with IDF v5 (#139)
Co-authored-by: h2zero <powellperalata@gmail.com>
2023-11-25 08:15:51 -07:00
h2zero
00d0bbd544 Fix compilation when CONFIG_BTDM_BLE_SCAN_DUPL is not enabled.
*  fix warning: variable 'pkey' set but not used [-Wunused-but-set-variable]
---------

Co-authored-by: Franz Höpfinger <f.hoepfinger@hr-agrartechnik.de>
2023-05-29 09:20:21 -06:00
Armandas Jarušauskas
648fd0ebfd Remove deprecated API in case of ESP-IDF V5. (#102)
* Remove deprecated API in case of ESP-IDF V5.

0a93ee1337/docs/en/migration-guides/release-5.x/bluetooth-low-energy.rst (id17)

* Fix initialization in case of ESP-IDF V5
2023-05-29 09:20:15 -06:00
JPZV
dab9f8b559 Fixed unhandled exception on handleGapEvent (#112)
Somehow, the conn_handle can have the value of `0xffff`. Not sure why or how, but anyway it should be managed before moving forward on NimBLECharacteristic::handleGapEvent. Otherwise, an unhandled exception will occur on `assert(rc == 0);`
2023-05-29 08:02:00 -06:00
eighty2fifty1
e0a5fac11e Add overloaded setManufacturerData to allow vector of uint8_t 2023-05-28 16:23:55 -06:00
h2zero
913bc0534e Fix build with platformio IDF+Arduino 2023-05-28 10:44:49 -06:00
h2zero
e93f943cc4 Set service handle in getHandle function if not set already.
If a service has been created and started but not yet added to the gatt server then the call to getHandle will result in an invalid handle. This adds a call to set the handle value in the getHandle function.
2023-05-14 16:39:34 -06:00
h2zero
bf956b9cdf Add index parameter for multiple manufacturer data sets.
Adds an index parameter to NimBLEAdvertisedDevice::getManufacturerData to allow for selecting from multiple instances in the advertisements.
Adds NimBLEAdvertisedDevice::getManufacturerDataCount to get the number of manufacturer data sets present in the advertised data.
2023-05-14 16:39:21 -06:00
Luca Niccoli
bc09c74ba6 Expose advertisement flags in NimBLEAdvertisedDevice 2023-05-14 16:39:10 -06:00
h2zero
0d38a3f43e Add directed peer address parameter to advertising start.
Adds a parameter to NimBLEAdvertising::start to take the peer address for use with directed advertising.
2023-05-14 16:38:50 -06:00
12 changed files with 164 additions and 15 deletions

View File

@@ -18,6 +18,10 @@ if("arduino" IN_LIST BUILD_COMPONENTS OR __hack_component_targets MATCHES "__idf
list(APPEND ESP_NIMBLE_PRIV_REQUIRES
arduino
)
elseif("framework-arduinoespressif32" IN_LIST BUILD_COMPONENTS OR __hack_component_targets MATCHES "___idf_framework-arduinoespressif32")
list(APPEND ESP_NIMBLE_PRIV_REQUIRES
framework-arduinoespressif32
)
endif()
idf_component_register(

View File

@@ -62,6 +62,25 @@ uint8_t NimBLEAdvertisedDevice::getAdvType() {
} // getAdvType
/**
* @brief Get the advertisement flags.
* @return The advertisement flags, a bitmask of:
* BLE_HS_ADV_F_DISC_LTD (0x01) - limited discoverability
* BLE_HS_ADV_F_DISC_GEN (0x02) - general discoverability
* BLE_HS_ADV_F_BREDR_UNSUP - BR/EDR not supported
*/
uint8_t NimBLEAdvertisedDevice::getAdvFlags() {
size_t data_loc = 0;
if(findAdvField(BLE_HS_ADV_TYPE_FLAGS, 0, &data_loc) > 0) {
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
if(field->length == BLE_HS_ADV_FLAGS_LEN + 1) {
return *field->value;
}
}
return 0;
} // getAdvFlags
/**
* @brief Get the appearance.
*
@@ -140,12 +159,14 @@ uint16_t NimBLEAdvertisedDevice::getMaxInterval() {
/**
* @brief Get the manufacturer data.
* @return The manufacturer data of the advertised device.
* @param [in] index The index of the of the manufacturer data set to get.
* @return The manufacturer data.
*/
std::string NimBLEAdvertisedDevice::getManufacturerData() {
std::string NimBLEAdvertisedDevice::getManufacturerData(uint8_t index) {
size_t data_loc = 0;
index++;
if(findAdvField(BLE_HS_ADV_TYPE_MFG_DATA, 0, &data_loc) > 0) {
if(findAdvField(BLE_HS_ADV_TYPE_MFG_DATA, index, &data_loc) > 0) {
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
if(field->length > 1) {
return std::string((char*)field->value, field->length - 1);
@@ -156,6 +177,15 @@ std::string NimBLEAdvertisedDevice::getManufacturerData() {
} // getManufacturerData
/**
* @brief Get the count of manufacturer data sets.
* @return The number of manufacturer data sets.
*/
uint8_t NimBLEAdvertisedDevice::getManufacturerDataCount() {
return findAdvField(BLE_HS_ADV_TYPE_MFG_DATA);
} // getManufacturerDataCount
/**
* @brief Get the URI from the advertisement.
* @return The URI data.
@@ -173,6 +203,24 @@ std::string NimBLEAdvertisedDevice::getURI() {
return "";
} // getURI
/**
* @brief Get the data from any type available in the advertisement
* @param [in] type The advertised data type BLE_HS_ADV_TYPE
* @return The data available under the type `type`
*/
std::string NimBLEAdvertisedDevice::getPayloadByType(uint16_t type) {
size_t data_loc = 0;
if(findAdvField(type, 0, &data_loc) > 0) {
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
if(field->length > 1) {
return std::string((char*)field->value, field->length - 1);
}
}
return "";
} // getPayloadByType
/**
* @brief Get the advertised name.
@@ -526,6 +574,14 @@ bool NimBLEAdvertisedDevice::haveURI() {
return findAdvField(BLE_HS_ADV_TYPE_URI) > 0;
} // haveURI
/**
* @brief Does this advertisement have a adv type `type`?
* @return True if there is a `type` present.
*/
bool NimBLEAdvertisedDevice::haveType(uint16_t type) {
return findAdvField(type) > 0;
}
/**
* @brief Does the advertisement contain a target address?

View File

@@ -45,12 +45,15 @@ public:
NimBLEAddress getAddress();
uint8_t getAdvType();
uint8_t getAdvFlags();
uint16_t getAppearance();
uint16_t getAdvInterval();
uint16_t getMinInterval();
uint16_t getMaxInterval();
std::string getManufacturerData();
uint8_t getManufacturerDataCount();
std::string getManufacturerData(uint8_t index = 0);
std::string getURI();
std::string getPayloadByType(uint16_t type);
/**
* @brief A template to convert the service data to <type\>.
@@ -132,6 +135,7 @@ public:
bool haveAdvInterval();
bool haveTargetAddress();
bool haveURI();
bool haveType(uint16_t type);
std::string toString();
bool isConnectable();
bool isLegacyAdvertisement();

View File

@@ -156,6 +156,18 @@ void NimBLEAdvertising::setManufacturerData(const std::string &data) {
} // setManufacturerData
/**
* @brief Set the advertised manufacturer data.
* @param [in] data The data to advertise.
*/
void NimBLEAdvertising::setManufacturerData(const std::vector<uint8_t> &data) {
m_mfgData = data;
m_advData.mfg_data = &m_mfgData[0];
m_advData.mfg_data_len = m_mfgData.size();
m_advDataSet = false;
} // setManufacturerData
/**
* @brief Set the advertised URI.
* @param [in] uri The URI to advertise.
@@ -387,9 +399,10 @@ void NimBLEAdvertising::setScanResponseData(NimBLEAdvertisementData& advertiseme
* @brief Start advertising.
* @param [in] duration The duration, in seconds, to advertise, 0 == advertise forever.
* @param [in] advCompleteCB A pointer to a callback to be invoked when advertising ends.
* @param [in] dirAddr The address of a peer to directly advertise to.
* @return True if advertising started successfully.
*/
bool NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdvertising *pAdv)) {
bool NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdvertising *pAdv), NimBLEAddress* dirAddr) {
NIMBLE_LOGD(LOG_TAG, ">> Advertising start: customAdvData: %d, customScanResponseData: %d",
m_customAdvData, m_customScanResponseData);
@@ -623,15 +636,27 @@ bool NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdv
m_advDataSet = true;
}
ble_addr_t peerAddr;
if (dirAddr != nullptr) {
memcpy(&peerAddr.val, dirAddr->getNative(), 6);
peerAddr.type = dirAddr->getType();
}
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
rc = ble_gap_adv_start(NimBLEDevice::m_own_addr_type, NULL, duration,
rc = ble_gap_adv_start(NimBLEDevice::m_own_addr_type,
(dirAddr != nullptr) ? &peerAddr : NULL,
duration,
&m_advParams,
(pServer != nullptr) ? NimBLEServer::handleGapEvent :
NimBLEAdvertising::handleGapEvent,
(void*)this);
#else
rc = ble_gap_adv_start(NimBLEDevice::m_own_addr_type, NULL, duration,
&m_advParams, NimBLEAdvertising::handleGapEvent, this);
rc = ble_gap_adv_start(NimBLEDevice::m_own_addr_type,
(dirAddr != nullptr) ? &peerAddr : NULL,
duration,
&m_advParams,
NimBLEAdvertising::handleGapEvent,
(void*)this);
#endif
switch(rc) {
case 0:
@@ -818,6 +843,18 @@ void NimBLEAdvertisementData::setManufacturerData(const std::string &data) {
} // setManufacturerData
/**
* @brief Set manufacturer specific data.
* @param [in] data The manufacturer data to advertise.
*/
void NimBLEAdvertisementData::setManufacturerData(const std::vector<uint8_t> &data) {
char cdata[2];
cdata[0] = data.size() + 1;
cdata[1] = BLE_HS_ADV_TYPE_MFG_DATA ; // 0xff
addData(std::string(cdata, 2) + std::string((char*)&data[0], data.size()));
} // setManufacturerData
/**
* @brief Set the URI to advertise.
* @param [in] uri The uri to advertise.

View File

@@ -31,6 +31,7 @@
/**************************/
#include "NimBLEUUID.h"
#include "NimBLEAddress.h"
#include <vector>
@@ -58,6 +59,7 @@ public:
void setCompleteServices32(const std::vector<NimBLEUUID> &v_uuid);
void setFlags(uint8_t);
void setManufacturerData(const std::string &data);
void setManufacturerData(const std::vector<uint8_t> &data);
void setURI(const std::string &uri);
void setName(const std::string &name);
void setPartialServices(const NimBLEUUID &uuid);
@@ -90,11 +92,12 @@ public:
void addServiceUUID(const NimBLEUUID &serviceUUID);
void addServiceUUID(const char* serviceUUID);
void removeServiceUUID(const NimBLEUUID &serviceUUID);
bool start(uint32_t duration = 0, void (*advCompleteCB)(NimBLEAdvertising *pAdv) = nullptr);
bool start(uint32_t duration = 0, void (*advCompleteCB)(NimBLEAdvertising *pAdv) = nullptr, NimBLEAddress* dirAddr = nullptr);
bool stop();
void setAppearance(uint16_t appearance);
void setName(const std::string &name);
void setManufacturerData(const std::string &data);
void setManufacturerData(const std::vector<uint8_t> &data);
void setURI(const std::string &uri);
void setServiceData(const NimBLEUUID &uuid, const std::string &data);
void setAdvertisementType(uint8_t adv_type);

View File

@@ -261,6 +261,12 @@ int NimBLECharacteristic::handleGapEvent(uint16_t conn_handle, uint16_t attr_han
struct ble_gatt_access_ctxt *ctxt,
void *arg)
{
if (conn_handle > BLE_HCI_LE_CONN_HANDLE_MAX)
{
NIMBLE_LOGW(LOG_TAG, "Conn_handle (%d) is above the maximum value (%d)", conn_handle, BLE_HCI_LE_CONN_HANDLE_MAX);
return BLE_ATT_ERR_INVALID_HANDLE;
}
const ble_uuid_t *uuid;
int rc;
struct ble_gap_conn_desc desc;

View File

@@ -1140,6 +1140,7 @@ int NimBLEClient::handleGapEvent(struct ble_gap_event *event, void *arg) {
case BLE_GAP_EVENT_PASSKEY_ACTION: {
struct ble_sm_io pkey = {0,0};
(void)pkey; //warning: variable 'pkey' set but not used [-Wunused-but-set-variable]
if(client->m_conn_id != event->passkey.conn_handle)
return 0;

View File

@@ -23,7 +23,9 @@
# include "esp_bt.h"
# include "nvs_flash.h"
# if defined(CONFIG_NIMBLE_CPP_IDF)
# include "esp_nimble_hci.h"
# if (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0) || CONFIG_BT_NIMBLE_LEGACY_VHCI_ENABLE)
# include "esp_nimble_hci.h"
# endif
# include "nimble/nimble_port.h"
# include "nimble/nimble_port_freertos.h"
# include "host/ble_hs.h"
@@ -86,8 +88,10 @@ std::vector<NimBLEAddress> NimBLEDevice::m_whiteList;
NimBLESecurityCallbacks* NimBLEDevice::m_securityCallbacks = nullptr;
uint8_t NimBLEDevice::m_own_addr_type = BLE_OWN_ADDR_PUBLIC;
#ifdef ESP_PLATFORM
# ifdef CONFIG_BTDM_BLE_SCAN_DUPL
uint16_t NimBLEDevice::m_scanDuplicateSize = CONFIG_BTDM_SCAN_DUPL_CACHE_SIZE;
uint8_t NimBLEDevice::m_scanFilterMode = CONFIG_BTDM_SCAN_DUPL_TYPE;
# endif
#endif
/**
@@ -493,6 +497,7 @@ uint16_t NimBLEDevice::getMTU() {
#ifdef ESP_PLATFORM
# ifdef CONFIG_BTDM_BLE_SCAN_DUPL
/**
* @brief Set the duplicate filter cache size for filtering scanned devices.
* @param [in] cacheSize The number of advertisements filtered before the cache is reset.\n
@@ -513,6 +518,7 @@ void NimBLEDevice::setScanDuplicateCacheSize(uint16_t cacheSize) {
}
/**
* @brief Set the duplicate filter mode for filtering scanned devices.
* @param [in] mode One of three possible options:
@@ -538,7 +544,8 @@ void NimBLEDevice::setScanFilterMode(uint8_t mode) {
m_scanFilterMode = mode;
}
#endif
# endif // CONFIG_BTDM_BLE_SCAN_DUPL
#endif // ESP_PLATFORM
#if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) || defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
/**
@@ -866,19 +873,23 @@ void NimBLEDevice::init(const std::string &deviceName) {
esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT);
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
#if defined (CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S3)
# if defined (CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S3)
bt_cfg.bluetooth_mode = ESP_BT_MODE_BLE;
#else
# else
bt_cfg.mode = ESP_BT_MODE_BLE;
bt_cfg.ble_max_conn = CONFIG_BT_NIMBLE_MAX_CONNECTIONS;
#endif
# endif
# ifdef CONFIG_BTDM_BLE_SCAN_DUPL
bt_cfg.normal_adv_size = m_scanDuplicateSize;
bt_cfg.scan_duplicate_type = m_scanFilterMode;
# endif
ESP_ERROR_CHECK(esp_bt_controller_init(&bt_cfg));
ESP_ERROR_CHECK(esp_bt_controller_enable(ESP_BT_MODE_BLE));
ESP_ERROR_CHECK(esp_nimble_hci_init());
# endif
#endif
nimble_port_init();
@@ -925,10 +936,12 @@ void NimBLEDevice::deinit(bool clearAll) {
if (ret == 0) {
nimble_port_deinit();
#ifdef ESP_PLATFORM
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
ret = esp_nimble_hci_and_controller_deinit();
if (ret != ESP_OK) {
NIMBLE_LOGE(LOG_TAG, "esp_nimble_hci_and_controller_deinit() failed with error: %d", ret);
}
#endif
#endif
initialized = false;
m_synced = false;

View File

@@ -230,8 +230,10 @@ private:
static gap_event_handler m_customGapHandler;
static uint8_t m_own_addr_type;
#ifdef ESP_PLATFORM
# ifdef CONFIG_BTDM_BLE_SCAN_DUPL
static uint16_t m_scanDuplicateSize;
static uint8_t m_scanFilterMode;
# endif
#endif
static std::vector<NimBLEAddress> m_whiteList;
};

View File

@@ -248,6 +248,9 @@ bool NimBLEService::start() {
* @return The handle associated with this service.
*/
uint16_t NimBLEService::getHandle() {
if (m_handle == NULL_HANDLE) {
ble_gatts_find_svc(&getUUID().getNative()->u, &m_handle);
}
return m_handle;
} // getHandle

View File

@@ -25,6 +25,18 @@
#define CONFIG_BT_NIMBLE_ROLE_BROADCASTER
#endif
#ifndef CONFIG_BTDM_SCAN_DUPL_TYPE_DEVICE
#define CONFIG_BTDM_SCAN_DUPL_TYPE_DEVICE 0
#endif
#ifndef CONFIG_BTDM_SCAN_DUPL_TYPE_DATA
#define CONFIG_BTDM_SCAN_DUPL_TYPE_DATA 1
#endif
#ifndef CONFIG_BTDM_SCAN_DUPL_TYPE_DATA_DEVICE
#define CONFIG_BTDM_SCAN_DUPL_TYPE_DATA_DEVICE 2
#endif
/* Enables the use of Arduino String class for attribute values */
#if defined __has_include
# if __has_include (<Arduino.h>)

View File

@@ -59,3 +59,11 @@
#if defined(CONFIG_NIMBLE_MAX_CONNECTIONS ) && !defined(CONFIG_BT_NIMBLE_MAX_CONNECTIONS)
#define CONFIG_BT_NIMBLE_MAX_CONNECTIONS CONFIG_NIMBLE_MAX_CONNECTIONS
#endif
#if !defined(CONFIG_BTDM_SCAN_DUPL_CACHE_SIZE) && defined(CONFIG_BT_LE_SCAN_DUPL_CACHE_SIZE)
#define CONFIG_BTDM_SCAN_DUPL_CACHE_SIZE CONFIG_BT_LE_SCAN_DUPL_CACHE_SIZE
#endif
#if !defined(CONFIG_BTDM_SCAN_DUPL_TYPE) && defined(CONFIG_BT_LE_SCAN_DUPL_TYPE)
#define CONFIG_BTDM_SCAN_DUPL_TYPE CONFIG_BT_LE_SCAN_DUPL_TYPE
#endif