Conditionally compile code for specific roles.

This allows NimBLE options in menuconfig to reduce code size based on
the roles selected (scan/advertising/central/peripheral).

Significant code space can be saved by removing unnecessary roles for the application.
This commit is contained in:
h2zero 2020-05-13 22:03:56 -06:00
parent 3d6f8b691e
commit 03cb7b21d9
53 changed files with 2335 additions and 2012 deletions

27
Kconfig Normal file
View file

@ -0,0 +1,27 @@
menu "ESP-NimBLE-CPP configuration"
config NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT
bool "Show NimBLE return codes as text in debug log."
default "n"
help
Enabling this option will display return code values as text
messages in the debug log. This will use approximately 8kB
of flash memory.
config NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT
bool "Show NimBLE gap events as text in debug log."
default "n"
help
Enabling this option will display gap event codes as text
messages in the debug log. This will use approximately 1kB
of flash memory.
config NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT
bool "Show advertisment types as text in debug log."
default "n"
help
Enabling this option will display advertisment types recieved
while scanning as text messages in the debug log.
This will use approximately 250 bytes of flash memory.
endmenu

View file

@ -89,28 +89,28 @@ uint32_t FreeRTOS::Semaphore::wait(std::string owner) {
* @return True if we took the semaphore within timeframe. * @return True if we took the semaphore within timeframe.
*/ */
bool FreeRTOS::Semaphore::timedWait(std::string owner, uint32_t timeoutMs) { bool FreeRTOS::Semaphore::timedWait(std::string owner, uint32_t timeoutMs) {
NIMBLE_LOGD(LOG_TAG, ">> wait: Semaphore waiting: %s for %s", toString().c_str(), owner.c_str()); NIMBLE_LOGD(LOG_TAG, ">> wait: Semaphore waiting: %s for %s", toString().c_str(), owner.c_str());
if (m_usePthreads && timeoutMs != portMAX_DELAY) { if (m_usePthreads && timeoutMs != portMAX_DELAY) {
assert(false); // We apparently don't have a timed wait for pthreads. assert(false); // We apparently don't have a timed wait for pthreads.
} }
auto ret = pdTRUE; auto ret = pdTRUE;
if (m_usePthreads) { if (m_usePthreads) {
pthread_mutex_lock(&m_pthread_mutex); pthread_mutex_lock(&m_pthread_mutex);
} else { } else {
ret = xSemaphoreTake(m_semaphore, timeoutMs); ret = xSemaphoreTake(m_semaphore, timeoutMs);
} }
if (m_usePthreads) { if (m_usePthreads) {
pthread_mutex_unlock(&m_pthread_mutex); pthread_mutex_unlock(&m_pthread_mutex);
} else { } else {
xSemaphoreGive(m_semaphore); xSemaphoreGive(m_semaphore);
} }
NIMBLE_LOGD(LOG_TAG, "<< wait: Semaphore %s released: %d", toString().c_str(), ret); NIMBLE_LOGD(LOG_TAG, "<< wait: Semaphore %s released: %d", toString().c_str(), ret);
return ret; return ret;
} // wait } // wait

View file

@ -40,9 +40,9 @@ public:
bool take(std::string owner = "<Unknown>"); bool take(std::string owner = "<Unknown>");
bool take(uint32_t timeoutMs, std::string owner = "<Unknown>"); bool take(uint32_t timeoutMs, std::string owner = "<Unknown>");
std::string toString(); std::string toString();
bool timedWait(std::string owner = "<Unknown>", uint32_t timeoutMs = portMAX_DELAY); bool timedWait(std::string owner = "<Unknown>", uint32_t timeoutMs = portMAX_DELAY);
uint32_t wait(std::string owner = "<Unknown>"); uint32_t wait(std::string owner = "<Unknown>");
uint32_t value(){ return m_value; }; uint32_t value(){ return m_value; };
private: private:
SemaphoreHandle_t m_semaphore; SemaphoreHandle_t m_semaphore;

View file

@ -26,9 +26,9 @@
/* Modifiers */ /* Modifiers */
enum MODIFIER_KEY { enum MODIFIER_KEY {
KEY_CTRL = 1, KEY_CTRL = 1,
KEY_SHIFT = 2, KEY_SHIFT = 2,
KEY_ALT = 4, KEY_ALT = 4,
}; };
@ -43,37 +43,37 @@ enum MEDIA_KEY {
}; };
enum FUNCTION_KEY { enum FUNCTION_KEY {
KEY_F1 = 128, /* F1 key */ KEY_F1 = 128, /* F1 key */
KEY_F2, /* F2 key */ KEY_F2, /* F2 key */
KEY_F3, /* F3 key */ KEY_F3, /* F3 key */
KEY_F4, /* F4 key */ KEY_F4, /* F4 key */
KEY_F5, /* F5 key */ KEY_F5, /* F5 key */
KEY_F6, /* F6 key */ KEY_F6, /* F6 key */
KEY_F7, /* F7 key */ KEY_F7, /* F7 key */
KEY_F8, /* F8 key */ KEY_F8, /* F8 key */
KEY_F9, /* F9 key */ KEY_F9, /* F9 key */
KEY_F10, /* F10 key */ KEY_F10, /* F10 key */
KEY_F11, /* F11 key */ KEY_F11, /* F11 key */
KEY_F12, /* F12 key */ KEY_F12, /* F12 key */
KEY_PRINT_SCREEN, /* Print Screen key */ KEY_PRINT_SCREEN, /* Print Screen key */
KEY_SCROLL_LOCK, /* Scroll lock */ KEY_SCROLL_LOCK, /* Scroll lock */
KEY_CAPS_LOCK, /* caps lock */ KEY_CAPS_LOCK, /* caps lock */
KEY_NUM_LOCK, /* num lock */ KEY_NUM_LOCK, /* num lock */
KEY_INSERT, /* Insert key */ KEY_INSERT, /* Insert key */
KEY_HOME, /* Home key */ KEY_HOME, /* Home key */
KEY_PAGE_UP, /* Page Up key */ KEY_PAGE_UP, /* Page Up key */
KEY_PAGE_DOWN, /* Page Down key */ KEY_PAGE_DOWN, /* Page Down key */
RIGHT_ARROW, /* Right arrow */ RIGHT_ARROW, /* Right arrow */
LEFT_ARROW, /* Left arrow */ LEFT_ARROW, /* Left arrow */
DOWN_ARROW, /* Down arrow */ DOWN_ARROW, /* Down arrow */
UP_ARROW, /* Up arrow */ UP_ARROW, /* Up arrow */
}; };
typedef struct { typedef struct {
unsigned char usage; unsigned char usage;
unsigned char modifier; unsigned char modifier;
} KEYMAP; } KEYMAP;
#ifdef US_KEYBOARD #ifdef US_KEYBOARD

View file

@ -89,8 +89,8 @@
#define MAX_HID_REPORT_SIZE (64) #define MAX_HID_REPORT_SIZE (64)
typedef struct { typedef struct {
uint32_t length; uint32_t length;
uint8_t data[MAX_HID_REPORT_SIZE]; uint8_t data[MAX_HID_REPORT_SIZE];
} HID_REPORT; } HID_REPORT;
#endif #endif

View file

@ -3,7 +3,7 @@
* *
* Created: on March 10, 2020 * Created: on March 10, 2020
* Author H2zero * Author H2zero
* *
* Originally: * Originally:
* *
* BLE2902.cpp * BLE2902.cpp
@ -20,16 +20,19 @@
#include "sdkconfig.h" #include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED) #if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h"
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#include "NimBLE2902.h" #include "NimBLE2902.h"
NimBLE2902::NimBLE2902(NimBLECharacteristic* pCharacterisitic) NimBLE2902::NimBLE2902(NimBLECharacteristic* pCharacterisitic)
: NimBLEDescriptor(NimBLEUUID((uint16_t) 0x2902), : NimBLEDescriptor(NimBLEUUID((uint16_t) 0x2902),
BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ |
BLE_GATT_CHR_F_WRITE, BLE_GATT_CHR_F_WRITE,
2, pCharacterisitic) 2, pCharacterisitic)
{ {
uint8_t data[2] = { 0, 0 }; uint8_t data[2] = { 0, 0 };
setValue(data, 2); setValue(data, 2);
} // NimBLE2902 } // NimBLE2902
@ -38,7 +41,7 @@ NimBLE2902::NimBLE2902(NimBLECharacteristic* pCharacterisitic)
* @return The notifications value. True if notifications are enabled and false if not. * @return The notifications value. True if notifications are enabled and false if not.
*/ */
bool NimBLE2902::getNotifications() { bool NimBLE2902::getNotifications() {
return (getValue()[0] & (1 << 0)) != 0; return (getValue()[0] & (1 << 0)) != 0;
} // getNotifications } // getNotifications
@ -47,7 +50,7 @@ bool NimBLE2902::getNotifications() {
* @return The indications value. True if indications are enabled and false if not. * @return The indications value. True if indications are enabled and false if not.
*/ */
bool NimBLE2902::getIndications() { bool NimBLE2902::getIndications() {
return (getValue()[0] & (1 << 1)) != 0; return (getValue()[0] & (1 << 1)) != 0;
} // getIndications } // getIndications
@ -56,9 +59,9 @@ bool NimBLE2902::getIndications() {
* @param [in] flag The indications flag. * @param [in] flag The indications flag.
*/ */
void NimBLE2902::setIndications(bool flag) { void NimBLE2902::setIndications(bool flag) {
uint8_t *pValue = getValue(); uint8_t *pValue = getValue();
if (flag) pValue[0] |= 1 << 1; if (flag) pValue[0] |= 1 << 1;
else pValue[0] &= ~(1 << 1); else pValue[0] &= ~(1 << 1);
} // setIndications } // setIndications
@ -67,9 +70,10 @@ void NimBLE2902::setIndications(bool flag) {
* @param [in] flag The notifications flag. * @param [in] flag The notifications flag.
*/ */
void NimBLE2902::setNotifications(bool flag) { void NimBLE2902::setNotifications(bool flag) {
uint8_t *pValue = getValue(); uint8_t *pValue = getValue();
if (flag) pValue[0] |= 1 << 0; if (flag) pValue[0] |= 1 << 0;
else pValue[0] &= ~(1 << 0); else pValue[0] &= ~(1 << 0);
} // setNotifications } // setNotifications
#endif #endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#endif

View file

@ -3,7 +3,7 @@
* *
* Created: on March 10, 2020 * Created: on March 10, 2020
* Author H2zero * Author H2zero
* *
* Originally: * Originally:
* *
* BLE2902.h * BLE2902.h
@ -17,6 +17,9 @@
#include "sdkconfig.h" #include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED) #if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h"
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#include "NimBLEDescriptor.h" #include "NimBLEDescriptor.h"
#include <map> #include <map>
@ -35,16 +38,17 @@
*/ */
class NimBLE2902: public NimBLEDescriptor { class NimBLE2902: public NimBLEDescriptor {
public: public:
bool getNotifications(); bool getNotifications();
bool getIndications(); bool getIndications();
void setNotifications(bool flag); void setNotifications(bool flag);
void setIndications(bool flag); void setIndications(bool flag);
private: private:
NimBLE2902(NimBLECharacteristic* pCharacterisitic); NimBLE2902(NimBLECharacteristic* pCharacterisitic);
friend class NimBLECharacteristic; friend class NimBLECharacteristic;
std::map<uint16_t, uint16_t> m_subscribedMap; std::map<uint16_t, uint16_t> m_subscribedMap;
}; // NimBLE2902 }; // NimBLE2902
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#endif /* CONFIG_BT_ENABLED */ #endif /* CONFIG_BT_ENABLED */
#endif /* MAIN_NIMBLE2902_H_ */ #endif /* MAIN_NIMBLE2902_H_ */

View file

@ -3,7 +3,7 @@
* *
* Created: on March 13, 2020 * Created: on March 13, 2020
* Author H2zero * Author H2zero
* *
* Originally: * Originally:
* *
* BLE2904.cpp * BLE2904.cpp
@ -19,21 +19,24 @@
#include "sdkconfig.h" #include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED) #if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h"
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#include "NimBLE2904.h" #include "NimBLE2904.h"
NimBLE2904::NimBLE2904(NimBLECharacteristic* pCharacterisitic) NimBLE2904::NimBLE2904(NimBLECharacteristic* pCharacterisitic)
: NimBLEDescriptor(NimBLEUUID((uint16_t) 0x2904), : NimBLEDescriptor(NimBLEUUID((uint16_t) 0x2904),
BLE_GATT_CHR_F_READ, BLE_GATT_CHR_F_READ,
sizeof(BLE2904_Data), sizeof(BLE2904_Data),
pCharacterisitic) pCharacterisitic)
{ {
m_data.m_format = 0; m_data.m_format = 0;
m_data.m_exponent = 0; m_data.m_exponent = 0;
m_data.m_namespace = 1; // 1 = Bluetooth SIG Assigned Numbers m_data.m_namespace = 1; // 1 = Bluetooth SIG Assigned Numbers
m_data.m_unit = 0; m_data.m_unit = 0;
m_data.m_description = 0; m_data.m_description = 0;
setValue((uint8_t*) &m_data, sizeof(m_data)); setValue((uint8_t*) &m_data, sizeof(m_data));
} // BLE2902 } // BLE2902
@ -41,8 +44,8 @@ NimBLE2904::NimBLE2904(NimBLECharacteristic* pCharacterisitic)
* @brief Set the description. * @brief Set the description.
*/ */
void NimBLE2904::setDescription(uint16_t description) { void NimBLE2904::setDescription(uint16_t description) {
m_data.m_description = description; m_data.m_description = description;
setValue((uint8_t*) &m_data, sizeof(m_data)); setValue((uint8_t*) &m_data, sizeof(m_data));
} }
@ -50,8 +53,8 @@ void NimBLE2904::setDescription(uint16_t description) {
* @brief Set the exponent. * @brief Set the exponent.
*/ */
void NimBLE2904::setExponent(int8_t exponent) { void NimBLE2904::setExponent(int8_t exponent) {
m_data.m_exponent = exponent; m_data.m_exponent = exponent;
setValue((uint8_t*) &m_data, sizeof(m_data)); setValue((uint8_t*) &m_data, sizeof(m_data));
} // setExponent } // setExponent
@ -59,8 +62,8 @@ void NimBLE2904::setExponent(int8_t exponent) {
* @brief Set the format. * @brief Set the format.
*/ */
void NimBLE2904::setFormat(uint8_t format) { void NimBLE2904::setFormat(uint8_t format) {
m_data.m_format = format; m_data.m_format = format;
setValue((uint8_t*) &m_data, sizeof(m_data)); setValue((uint8_t*) &m_data, sizeof(m_data));
} // setFormat } // setFormat
@ -68,8 +71,8 @@ void NimBLE2904::setFormat(uint8_t format) {
* @brief Set the namespace. * @brief Set the namespace.
*/ */
void NimBLE2904::setNamespace(uint8_t namespace_value) { void NimBLE2904::setNamespace(uint8_t namespace_value) {
m_data.m_namespace = namespace_value; m_data.m_namespace = namespace_value;
setValue((uint8_t*) &m_data, sizeof(m_data)); setValue((uint8_t*) &m_data, sizeof(m_data));
} // setNamespace } // setNamespace
@ -79,8 +82,9 @@ void NimBLE2904::setNamespace(uint8_t namespace_value) {
* @param [in] unit The type of units of this characteristic as defined by assigned numbers. * @param [in] unit The type of units of this characteristic as defined by assigned numbers.
*/ */
void NimBLE2904::setUnit(uint16_t unit) { void NimBLE2904::setUnit(uint16_t unit) {
m_data.m_unit = unit; m_data.m_unit = unit;
setValue((uint8_t*) &m_data, sizeof(m_data)); setValue((uint8_t*) &m_data, sizeof(m_data));
} // setUnit } // setUnit
#endif #endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#endif

View file

@ -3,7 +3,7 @@
* *
* Created: on March 13, 2020 * Created: on March 13, 2020
* Author H2zero * Author H2zero
* *
* Originally: * Originally:
* *
* BLE2904.h * BLE2904.h
@ -17,14 +17,17 @@
#include "sdkconfig.h" #include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED) #if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h"
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#include "NimBLEDescriptor.h" #include "NimBLEDescriptor.h"
struct BLE2904_Data { struct BLE2904_Data {
uint8_t m_format; uint8_t m_format;
int8_t m_exponent; int8_t m_exponent;
uint16_t m_unit; // See https://www.bluetooth.com/specifications/assigned-numbers/units uint16_t m_unit; // See https://www.bluetooth.com/specifications/assigned-numbers/units
uint8_t m_namespace; uint8_t m_namespace;
uint16_t m_description; uint16_t m_description;
} __attribute__((packed)); } __attribute__((packed));
@ -38,45 +41,46 @@ struct BLE2904_Data {
*/ */
class NimBLE2904: public NimBLEDescriptor { class NimBLE2904: public NimBLEDescriptor {
public: public:
static const uint8_t FORMAT_BOOLEAN = 1; static const uint8_t FORMAT_BOOLEAN = 1;
static const uint8_t FORMAT_UINT2 = 2; static const uint8_t FORMAT_UINT2 = 2;
static const uint8_t FORMAT_UINT4 = 3; static const uint8_t FORMAT_UINT4 = 3;
static const uint8_t FORMAT_UINT8 = 4; static const uint8_t FORMAT_UINT8 = 4;
static const uint8_t FORMAT_UINT12 = 5; static const uint8_t FORMAT_UINT12 = 5;
static const uint8_t FORMAT_UINT16 = 6; static const uint8_t FORMAT_UINT16 = 6;
static const uint8_t FORMAT_UINT24 = 7; static const uint8_t FORMAT_UINT24 = 7;
static const uint8_t FORMAT_UINT32 = 8; static const uint8_t FORMAT_UINT32 = 8;
static const uint8_t FORMAT_UINT48 = 9; static const uint8_t FORMAT_UINT48 = 9;
static const uint8_t FORMAT_UINT64 = 10; static const uint8_t FORMAT_UINT64 = 10;
static const uint8_t FORMAT_UINT128 = 11; static const uint8_t FORMAT_UINT128 = 11;
static const uint8_t FORMAT_SINT8 = 12; static const uint8_t FORMAT_SINT8 = 12;
static const uint8_t FORMAT_SINT12 = 13; static const uint8_t FORMAT_SINT12 = 13;
static const uint8_t FORMAT_SINT16 = 14; static const uint8_t FORMAT_SINT16 = 14;
static const uint8_t FORMAT_SINT24 = 15; static const uint8_t FORMAT_SINT24 = 15;
static const uint8_t FORMAT_SINT32 = 16; static const uint8_t FORMAT_SINT32 = 16;
static const uint8_t FORMAT_SINT48 = 17; static const uint8_t FORMAT_SINT48 = 17;
static const uint8_t FORMAT_SINT64 = 18; static const uint8_t FORMAT_SINT64 = 18;
static const uint8_t FORMAT_SINT128 = 19; static const uint8_t FORMAT_SINT128 = 19;
static const uint8_t FORMAT_FLOAT32 = 20; static const uint8_t FORMAT_FLOAT32 = 20;
static const uint8_t FORMAT_FLOAT64 = 21; static const uint8_t FORMAT_FLOAT64 = 21;
static const uint8_t FORMAT_SFLOAT16 = 22; static const uint8_t FORMAT_SFLOAT16 = 22;
static const uint8_t FORMAT_SFLOAT32 = 23; static const uint8_t FORMAT_SFLOAT32 = 23;
static const uint8_t FORMAT_IEEE20601 = 24; static const uint8_t FORMAT_IEEE20601 = 24;
static const uint8_t FORMAT_UTF8 = 25; static const uint8_t FORMAT_UTF8 = 25;
static const uint8_t FORMAT_UTF16 = 26; static const uint8_t FORMAT_UTF16 = 26;
static const uint8_t FORMAT_OPAQUE = 27; static const uint8_t FORMAT_OPAQUE = 27;
void setDescription(uint16_t); void setDescription(uint16_t);
void setExponent(int8_t exponent); void setExponent(int8_t exponent);
void setFormat(uint8_t format); void setFormat(uint8_t format);
void setNamespace(uint8_t namespace_value); void setNamespace(uint8_t namespace_value);
void setUnit(uint16_t unit); void setUnit(uint16_t unit);
private: private:
NimBLE2904(NimBLECharacteristic* pCharacterisitic); NimBLE2904(NimBLECharacteristic* pCharacterisitic);
friend class NimBLECharacteristic; friend class NimBLECharacteristic;
BLE2904_Data m_data; BLE2904_Data m_data;
}; // BLE2904 }; // BLE2904
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#endif /* CONFIG_BT_ENABLED */ #endif /* CONFIG_BT_ENABLED */
#endif /* MAIN_NIMBLE2904_H_ */ #endif /* MAIN_NIMBLE2904_H_ */

View file

@ -3,7 +3,7 @@
* *
* Created: on Jan 24 2020 * Created: on Jan 24 2020
* Author H2zero * Author H2zero
* *
* Originally: * Originally:
* *
* BLEAddress.cpp * BLEAddress.cpp

View file

@ -3,7 +3,7 @@
* *
* Created: on Jan 24 2020 * Created: on Jan 24 2020
* Author H2zero * Author H2zero
* *
* Originally: * Originally:
* *
* BLEAddress.h * BLEAddress.h
@ -40,9 +40,9 @@ public:
const uint8_t* getNative() const; const uint8_t* getNative() const;
std::string toString() const; std::string toString() const;
bool operator ==(const NimBLEAddress & rhs) const; bool operator ==(const NimBLEAddress & rhs) const;
bool operator !=(const NimBLEAddress & rhs) const; bool operator !=(const NimBLEAddress & rhs) const;
operator std::string() const; operator std::string() const;
private: private:
uint8_t m_address[6]; uint8_t m_address[6];

View file

@ -3,7 +3,7 @@
* *
* Created: on Jan 24 2020 * Created: on Jan 24 2020
* Author H2zero * Author H2zero
* *
* Originally: * Originally:
* *
* BLEAdvertisedDevice.cpp * BLEAdvertisedDevice.cpp
@ -14,6 +14,9 @@
#include "sdkconfig.h" #include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED) #if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h"
#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
#include "NimBLEAdvertisedDevice.h" #include "NimBLEAdvertisedDevice.h"
#include "NimBLEUtils.h" #include "NimBLEUtils.h"
#include "NimBLELog.h" #include "NimBLELog.h"
@ -121,7 +124,7 @@ std::string NimBLEAdvertisedDevice::getServiceData() {
* @brief Get the service data UUID. * @brief Get the service data UUID.
* @return The service data UUID. * @return The service data UUID.
*/ */
NimBLEUUID NimBLEAdvertisedDevice::getServiceDataUUID() { NimBLEUUID NimBLEAdvertisedDevice::getServiceDataUUID() {
return m_serviceDataUUID; return m_serviceDataUUID;
} // getServiceDataUUID } // getServiceDataUUID
@ -131,7 +134,7 @@ NimBLEUUID NimBLEAdvertisedDevice::getServiceDataUUID() {
* @brief Get the Service UUID. * @brief Get the Service UUID.
* @return The Service UUID of the advertised device. * @return The Service UUID of the advertised device.
*/ */
NimBLEUUID NimBLEAdvertisedDevice::getServiceUUID() { //TODO Remove it eventually, is no longer useful NimBLEUUID NimBLEAdvertisedDevice::getServiceUUID() { //TODO Remove it eventually, is no longer useful
return m_serviceUUIDs[0]; return m_serviceUUIDs[0];
} // getServiceUUID } // getServiceUUID
@ -270,7 +273,7 @@ bool NimBLEAdvertisedDevice::haveTXPower() {
u8p = fields->svc_data_uuid16; u8p = fields->svc_data_uuid16;
length = fields->svc_data_uuid16_len; length = fields->svc_data_uuid16_len;
if (length < 2) { if (length < 2) {
NIMBLE_LOGE(LOG_TAG,"Length too small for ESP_BLE_AD_TYPE_SERVICE_DATA"); NIMBLE_LOGE(LOG_TAG,"Length too small for ESP_BLE_AD_TYPE_SERVICE_DATA");
} }
@ -287,23 +290,23 @@ bool NimBLEAdvertisedDevice::haveTXPower() {
u8p = fields->svc_data_uuid16; u8p = fields->svc_data_uuid16;
length = fields->svc_data_uuid16_len; length = fields->svc_data_uuid16_len;
if (length < 4) { if (length < 4) {
NIMBLE_LOGE(LOG_TAG,"Length too small for ESP_BLE_AD_TYPE_32SERVICE_DATA"); NIMBLE_LOGE(LOG_TAG,"Length too small for ESP_BLE_AD_TYPE_32SERVICE_DATA");
} }
uint32_t uuid = *(uint32_t*) u8p; uint32_t uuid = *(uint32_t*) u8p;
setServiceDataUUID(NimBLEUUID(uuid)); setServiceDataUUID(NimBLEUUID(uuid));
if (length > 4) { if (length > 4) {
setServiceData(std::string(reinterpret_cast<char*>(u8p + 4), length - 4)); setServiceData(std::string(reinterpret_cast<char*>(u8p + 4), length - 4));
} }
} }
if (fields->svc_data_uuid128 != NULL) { if (fields->svc_data_uuid128 != NULL) {
u8p = fields->svc_data_uuid16; u8p = fields->svc_data_uuid16;
length = fields->svc_data_uuid16_len; length = fields->svc_data_uuid16_len;
if (length < 16) { if (length < 16) {
NIMBLE_LOGE(LOG_TAG,"Length too small for ESP_BLE_AD_TYPE_128SERVICE_DATA"); NIMBLE_LOGE(LOG_TAG,"Length too small for ESP_BLE_AD_TYPE_128SERVICE_DATA");
} }
@ -318,7 +321,7 @@ bool NimBLEAdvertisedDevice::haveTXPower() {
NIMBLE_LOGD(LOG_TAG, " appearance=0x%04x", fields->appearance); NIMBLE_LOGD(LOG_TAG, " appearance=0x%04x", fields->appearance);
setAppearance(fields->appearance); setAppearance(fields->appearance);
} }
/**** TODO: create storage and fucntions for these parameters /**** TODO: create storage and fucntions for these parameters
if (fields->public_tgt_addr != NULL) { if (fields->public_tgt_addr != NULL) {
NIMBLE_LOGD(LOG_TAG, " public_tgt_addr="); NIMBLE_LOGD(LOG_TAG, " public_tgt_addr=");
@ -329,7 +332,7 @@ bool NimBLEAdvertisedDevice::haveTXPower() {
} }
NIMBLE_LOGD(LOG_TAG, "\n"); NIMBLE_LOGD(LOG_TAG, "\n");
} }
if (fields->slave_itvl_range != NULL) { if (fields->slave_itvl_range != NULL) {
NIMBLE_LOGD(LOG_TAG, " slave_itvl_range="); NIMBLE_LOGD(LOG_TAG, " slave_itvl_range=");
print_bytes(fields->slave_itvl_range, BLE_HS_ADV_SLAVE_ITVL_RANGE_LEN); print_bytes(fields->slave_itvl_range, BLE_HS_ADV_SLAVE_ITVL_RANGE_LEN);
@ -350,7 +353,7 @@ bool NimBLEAdvertisedDevice::haveTXPower() {
setManufacturerData(std::string(reinterpret_cast<char*>(fields->mfg_data), fields->mfg_data_len)); setManufacturerData(std::string(reinterpret_cast<char*>(fields->mfg_data), fields->mfg_data_len));
} }
} //parseAdvertisement } //parseAdvertisement
/** /**
* @brief Set the address of the advertised device. * @brief Set the address of the advertised device.
@ -430,7 +433,7 @@ void NimBLEAdvertisedDevice::setScan(NimBLEScan* pScan) {
* @brief Set the Service UUID for this device. * @brief Set the Service UUID for this device.
* @param [in] serviceUUID The discovered serviceUUID * @param [in] serviceUUID The discovered serviceUUID
*/ */
void NimBLEAdvertisedDevice::setServiceUUID(const char* serviceUUID) { void NimBLEAdvertisedDevice::setServiceUUID(const char* serviceUUID) {
return setServiceUUID(NimBLEUUID(serviceUUID)); return setServiceUUID(NimBLEUUID(serviceUUID));
} // setServiceUUID } // setServiceUUID
@ -488,9 +491,9 @@ void NimBLEAdvertisedDevice::setTXPower(int8_t txPower) {
* @brief Create a string representation of this device. * @brief Create a string representation of this device.
* @return A string representation of this device. * @return A string representation of this device.
*/ */
std::string NimBLEAdvertisedDevice::toString() { std::string NimBLEAdvertisedDevice::toString() {
std::string res = "Name: " + getName() + ", Address: " + getAddress().toString(); std::string res = "Name: " + getName() + ", Address: " + getAddress().toString();
if (haveAppearance()) { if (haveAppearance()) {
char val[6]; char val[6];
snprintf(val, sizeof(val), "%d", getAppearance()); snprintf(val, sizeof(val), "%d", getAppearance());
@ -508,16 +511,16 @@ std::string NimBLEAdvertisedDevice::toString() {
if (haveServiceUUID()) { if (haveServiceUUID()) {
res += ", serviceUUID: " + getServiceUUID().toString(); res += ", serviceUUID: " + getServiceUUID().toString();
} }
if (haveTXPower()) { if (haveTXPower()) {
char val[5]; char val[5];
snprintf(val, sizeof(val), "%d", getTXPower()); snprintf(val, sizeof(val), "%d", getTXPower());
res += ", txPower: "; res += ", txPower: ";
res += val; res += val;
} }
res += ", advType: " + std::string(NimBLEUtils::advTypeToString(m_advType)); res += ", advType: " + std::string(NimBLEUtils::advTypeToString(m_advType));
return res; return res;
} // toString } // toString
@ -548,5 +551,6 @@ void NimBLEAdvertisedDevice::setAdvertisementResult(uint8_t* payload, uint8_t le
m_payloadLength = length; m_payloadLength = length;
} }
#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
#endif /* CONFIG_BT_ENABLED */ #endif /* CONFIG_BT_ENABLED */

View file

@ -3,7 +3,7 @@
* *
* Created: on Jan 24 2020 * Created: on Jan 24 2020
* Author H2zero * Author H2zero
* *
* Originally: * Originally:
* *
* BLEAdvertisedDevice.h * BLEAdvertisedDevice.h
@ -17,6 +17,9 @@
#include "sdkconfig.h" #include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED) #if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h"
#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
#include "NimBLEAddress.h" #include "NimBLEAddress.h"
#include "NimBLEScan.h" #include "NimBLEScan.h"
#include "NimBLEUUID.h" #include "NimBLEUUID.h"
@ -24,7 +27,7 @@
#include "host/ble_hs_adv.h" #include "host/ble_hs_adv.h"
#include <map> #include <map>
#include <vector> #include <vector>
class NimBLEScan; class NimBLEScan;
@ -129,5 +132,6 @@ public:
virtual void onResult(NimBLEAdvertisedDevice* advertisedDevice) = 0; virtual void onResult(NimBLEAdvertisedDevice* advertisedDevice) = 0;
}; };
#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
#endif /* CONFIG_BT_ENABLED */ #endif /* CONFIG_BT_ENABLED */
#endif /* COMPONENTS_NIMBLEADVERTISEDDEVICE_H_ */ #endif /* COMPONENTS_NIMBLEADVERTISEDDEVICE_H_ */

View file

@ -3,7 +3,7 @@
* *
* Created: on March 3, 2020 * Created: on March 3, 2020
* Author H2zero * Author H2zero
* *
* Originally: * Originally:
* *
* BLEAdvertising.cpp * BLEAdvertising.cpp
@ -15,6 +15,10 @@
*/ */
#include "sdkconfig.h" #include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED) #if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h"
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
#include "services/gap/ble_svc_gap.h" #include "services/gap/ble_svc_gap.h"
#include "NimBLEAdvertising.h" #include "NimBLEAdvertising.h"
#include "NimBLEDevice.h" #include "NimBLEDevice.h"
@ -31,26 +35,26 @@ static const char* LOG_TAG = "NimBLEAdvertising";
*/ */
NimBLEAdvertising::NimBLEAdvertising() { NimBLEAdvertising::NimBLEAdvertising() {
memset(&m_advData, 0, sizeof m_advData); memset(&m_advData, 0, sizeof m_advData);
memset(&m_scanData, 0, sizeof m_scanData); memset(&m_scanData, 0, sizeof m_scanData);
memset(&m_advParams, 0, sizeof m_advParams); memset(&m_advParams, 0, sizeof m_advParams);
const char *name = ble_svc_gap_device_name(); const char *name = ble_svc_gap_device_name();
m_advData.name = (uint8_t *)name; m_advData.name = (uint8_t *)name;
m_advData.name_len = strlen(name); m_advData.name_len = strlen(name);
m_advData.name_is_complete = 1; m_advData.name_is_complete = 1;
m_scanData.tx_pwr_lvl_is_present = 1; m_scanData.tx_pwr_lvl_is_present = 1;
m_scanData.tx_pwr_lvl = NimBLEDevice::getPower(); m_scanData.tx_pwr_lvl = NimBLEDevice::getPower();
m_advData.flags = (BLE_HS_ADV_F_DISC_GEN | BLE_HS_ADV_F_BREDR_UNSUP); m_advData.flags = (BLE_HS_ADV_F_DISC_GEN | BLE_HS_ADV_F_BREDR_UNSUP);
m_advData.appearance = 0; m_advData.appearance = 0;
m_advData.appearance_is_present = 0; m_advData.appearance_is_present = 0;
m_advData.mfg_data_len = 0; m_advData.mfg_data_len = 0;
m_advData.mfg_data = nullptr; m_advData.mfg_data = nullptr;
m_advParams.conn_mode = BLE_GAP_CONN_MODE_UND; m_advParams.conn_mode = BLE_GAP_CONN_MODE_UND;
m_advParams.disc_mode = BLE_GAP_DISC_MODE_GEN; m_advParams.disc_mode = BLE_GAP_DISC_MODE_GEN;
m_advParams.itvl_min = 0; m_advParams.itvl_min = 0;
m_advParams.itvl_max = 0; m_advParams.itvl_max = 0;
} // NimBLEAdvertising } // NimBLEAdvertising
@ -59,7 +63,7 @@ NimBLEAdvertising::NimBLEAdvertising() {
* @param [in] serviceUUID The UUID of the service to expose. * @param [in] serviceUUID The UUID of the service to expose.
*/ */
void NimBLEAdvertising::addServiceUUID(const NimBLEUUID &serviceUUID) { void NimBLEAdvertising::addServiceUUID(const NimBLEUUID &serviceUUID) {
m_serviceUUIDs.push_back(serviceUUID); m_serviceUUIDs.push_back(serviceUUID);
} // addServiceUUID } // addServiceUUID
@ -68,7 +72,7 @@ void NimBLEAdvertising::addServiceUUID(const NimBLEUUID &serviceUUID) {
* @param [in] serviceUUID The string representation of the service to expose. * @param [in] serviceUUID The string representation of the service to expose.
*/ */
void NimBLEAdvertising::addServiceUUID(const char* serviceUUID) { void NimBLEAdvertising::addServiceUUID(const char* serviceUUID) {
addServiceUUID(NimBLEUUID(serviceUUID)); addServiceUUID(NimBLEUUID(serviceUUID));
} // addServiceUUID } // addServiceUUID
@ -80,34 +84,34 @@ void NimBLEAdvertising::addServiceUUID(const char* serviceUUID) {
* @return N/A. * @return N/A.
*/ */
void NimBLEAdvertising::setAppearance(uint16_t appearance) { void NimBLEAdvertising::setAppearance(uint16_t appearance) {
m_advData.appearance = appearance; m_advData.appearance = appearance;
m_advData.appearance_is_present = 1; m_advData.appearance_is_present = 1;
} // setAppearance } // setAppearance
void NimBLEAdvertising::setAdvertisementType(uint8_t adv_type){ void NimBLEAdvertising::setAdvertisementType(uint8_t adv_type){
m_advParams.conn_mode = adv_type; m_advParams.conn_mode = adv_type;
} // setAdvertisementType } // setAdvertisementType
void NimBLEAdvertising::setMinInterval(uint16_t mininterval) { void NimBLEAdvertising::setMinInterval(uint16_t mininterval) {
m_advParams.itvl_min = mininterval; m_advParams.itvl_min = mininterval;
} // setMinInterval } // setMinInterval
void NimBLEAdvertising::setMaxInterval(uint16_t maxinterval) { void NimBLEAdvertising::setMaxInterval(uint16_t maxinterval) {
m_advParams.itvl_max = maxinterval; m_advParams.itvl_max = maxinterval;
} // setMaxInterval } // setMaxInterval
// These are dummy functions for now for compatibility // These are dummy functions for now for compatibility
void NimBLEAdvertising::setMinPreferred(uint16_t mininterval) { void NimBLEAdvertising::setMinPreferred(uint16_t mininterval) {
//m_advData.min_interval = mininterval; //m_advData.min_interval = mininterval;
} // } //
void NimBLEAdvertising::setMaxPreferred(uint16_t maxinterval) { void NimBLEAdvertising::setMaxPreferred(uint16_t maxinterval) {
//m_advData.max_interval = maxinterval; //m_advData.max_interval = maxinterval;
} // } //
////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////
void NimBLEAdvertising::setScanResponse(bool set) { void NimBLEAdvertising::setScanResponse(bool set) {
m_scanResp = set; m_scanResp = set;
} }
/** /**
@ -116,44 +120,44 @@ void NimBLEAdvertising::setScanResponse(bool set) {
* @param [in] connectWhitelistOnly If true, only allow connections from those on the white list. * @param [in] connectWhitelistOnly If true, only allow connections from those on the white list.
*/ */
void NimBLEAdvertising::setScanFilter(bool scanRequestWhitelistOnly, bool connectWhitelistOnly) { void NimBLEAdvertising::setScanFilter(bool scanRequestWhitelistOnly, bool connectWhitelistOnly) {
NIMBLE_LOGD(LOG_TAG, ">> setScanFilter: scanRequestWhitelistOnly: %d, connectWhitelistOnly: %d", scanRequestWhitelistOnly, connectWhitelistOnly); NIMBLE_LOGD(LOG_TAG, ">> setScanFilter: scanRequestWhitelistOnly: %d, connectWhitelistOnly: %d", scanRequestWhitelistOnly, connectWhitelistOnly);
if (!scanRequestWhitelistOnly && !connectWhitelistOnly) { if (!scanRequestWhitelistOnly && !connectWhitelistOnly) {
m_advParams.filter_policy = BLE_HCI_ADV_FILT_NONE; m_advParams.filter_policy = BLE_HCI_ADV_FILT_NONE;
NIMBLE_LOGD(LOG_TAG, "<< setScanFilter"); NIMBLE_LOGD(LOG_TAG, "<< setScanFilter");
return; return;
} }
if (scanRequestWhitelistOnly && !connectWhitelistOnly) { if (scanRequestWhitelistOnly && !connectWhitelistOnly) {
m_advParams.filter_policy = BLE_HCI_ADV_FILT_SCAN; m_advParams.filter_policy = BLE_HCI_ADV_FILT_SCAN;
NIMBLE_LOGD(LOG_TAG, "<< setScanFilter"); NIMBLE_LOGD(LOG_TAG, "<< setScanFilter");
return; return;
} }
if (!scanRequestWhitelistOnly && connectWhitelistOnly) { if (!scanRequestWhitelistOnly && connectWhitelistOnly) {
m_advParams.filter_policy = BLE_HCI_ADV_FILT_CONN; m_advParams.filter_policy = BLE_HCI_ADV_FILT_CONN;
NIMBLE_LOGD(LOG_TAG, "<< setScanFilter"); NIMBLE_LOGD(LOG_TAG, "<< setScanFilter");
return; return;
} }
if (scanRequestWhitelistOnly && connectWhitelistOnly) { if (scanRequestWhitelistOnly && connectWhitelistOnly) {
m_advParams.filter_policy = BLE_HCI_ADV_FILT_BOTH; m_advParams.filter_policy = BLE_HCI_ADV_FILT_BOTH;
NIMBLE_LOGD(LOG_TAG, "<< setScanFilter"); NIMBLE_LOGD(LOG_TAG, "<< setScanFilter");
return; return;
} }
} // setScanFilter } // setScanFilter
/** /**
* @brief Set the advertisement data that is to be published in a regular advertisement. * @brief Set the advertisement data that is to be published in a regular advertisement.
* @param [in] advertisementData The data to be advertised. * @param [in] advertisementData The data to be advertised.
*/ */
void NimBLEAdvertising::setAdvertisementData(NimBLEAdvertisementData& advertisementData) { void NimBLEAdvertising::setAdvertisementData(NimBLEAdvertisementData& advertisementData) {
NIMBLE_LOGD(LOG_TAG, ">> setAdvertisementData"); NIMBLE_LOGD(LOG_TAG, ">> setAdvertisementData");
int rc = ble_gap_adv_set_data( int rc = ble_gap_adv_set_data(
(uint8_t*)advertisementData.getPayload().data(), (uint8_t*)advertisementData.getPayload().data(),
advertisementData.getPayload().length()); advertisementData.getPayload().length());
if (rc != 0) { if (rc != 0) {
NIMBLE_LOGE(LOG_TAG, "ble_gap_adv_set_data: %d %s", rc, NimBLEUtils::returnCodeToString(rc)); NIMBLE_LOGE(LOG_TAG, "ble_gap_adv_set_data: %d %s", rc, NimBLEUtils::returnCodeToString(rc));
} }
m_customAdvData = true; // Set the flag that indicates we are using custom advertising data. m_customAdvData = true; // Set the flag that indicates we are using custom advertising data.
NIMBLE_LOGD(LOG_TAG, "<< setAdvertisementData"); NIMBLE_LOGD(LOG_TAG, "<< setAdvertisementData");
} // setAdvertisementData } // setAdvertisementData
@ -162,15 +166,15 @@ void NimBLEAdvertising::setAdvertisementData(NimBLEAdvertisementData& advertisem
* @param [in] advertisementData The data to be advertised. * @param [in] advertisementData The data to be advertised.
*/ */
void NimBLEAdvertising::setScanResponseData(NimBLEAdvertisementData& advertisementData) { void NimBLEAdvertising::setScanResponseData(NimBLEAdvertisementData& advertisementData) {
NIMBLE_LOGD(LOG_TAG, ">> setScanResponseData"); NIMBLE_LOGD(LOG_TAG, ">> setScanResponseData");
int rc = ble_gap_adv_rsp_set_data( int rc = ble_gap_adv_rsp_set_data(
(uint8_t*)advertisementData.getPayload().data(), (uint8_t*)advertisementData.getPayload().data(),
advertisementData.getPayload().length()); advertisementData.getPayload().length());
if (rc != 0) { if (rc != 0) {
NIMBLE_LOGE(LOG_TAG, "ble_gap_adv_rsp_set_data: %d %s", rc, NimBLEUtils::returnCodeToString(rc)); NIMBLE_LOGE(LOG_TAG, "ble_gap_adv_rsp_set_data: %d %s", rc, NimBLEUtils::returnCodeToString(rc));
} }
m_customScanResponseData = true; // Set the flag that indicates we are using custom scan response data. m_customScanResponseData = true; // Set the flag that indicates we are using custom scan response data.
NIMBLE_LOGD(LOG_TAG, "<< setScanResponseData"); NIMBLE_LOGD(LOG_TAG, "<< setScanResponseData");
} // setScanResponseData } // setScanResponseData
@ -180,186 +184,191 @@ void NimBLEAdvertising::setScanResponseData(NimBLEAdvertisementData& advertiseme
* @return N/A. * @return N/A.
*/ */
void NimBLEAdvertising::start() { void NimBLEAdvertising::start() {
NIMBLE_LOGD(LOG_TAG, ">> Advertising start: customAdvData: %d, customScanResponseData: %d", m_customAdvData, m_customScanResponseData); NIMBLE_LOGD(LOG_TAG, ">> Advertising start: customAdvData: %d, customScanResponseData: %d", m_customAdvData, m_customScanResponseData);
// If Host is not synced we cannot start advertising. // If Host is not synced we cannot start advertising.
if(!NimBLEDevice::m_synced) { if(!NimBLEDevice::m_synced) {
NIMBLE_LOGE(LOG_TAG, "Host reset, wait for sync."); NIMBLE_LOGE(LOG_TAG, "Host reset, wait for sync.");
return; return;
} }
if(NimBLEDevice::createServer()->getConnectedCount() >= NIMBLE_MAX_CONNECTIONS) { #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
NimBLEServer* pServer = NimBLEDevice::createServer();
if(!pServer->m_gattsStarted){
pServer->start();
} else if(pServer->getConnectedCount() >= NIMBLE_MAX_CONNECTIONS) {
NIMBLE_LOGW(LOG_TAG, "Max connections reached - not advertising"); NIMBLE_LOGW(LOG_TAG, "Max connections reached - not advertising");
return; return;
} }
#endif
int numServices = m_serviceUUIDs.size();
int numServices = m_serviceUUIDs.size();
int rc = 0; int rc = 0;
uint8_t addressType; uint8_t addressType;
uint8_t payloadLen = 3; //start with 3 bytes for the flags data uint8_t payloadLen = 3; //start with 3 bytes for the flags data
// If already advertising just return // If already advertising just return
if(ble_gap_adv_active()) { if(ble_gap_adv_active()) {
return; return;
} }
NimBLEServer* pServer = NimBLEDevice::createServer(); if (!m_customAdvData && !m_advSvcsSet && numServices > 0) {
if(!pServer->m_gattsStarted){ for (int i = 0; i < numServices; i++) {
pServer->start(); if(m_serviceUUIDs[i].getNative()->u.type == BLE_UUID_TYPE_16) {
} int add = (m_advData.num_uuids16 > 0) ? 2 : 4;
if((payloadLen + add) > 31){
if (!m_customAdvData && !m_advSvcsSet && numServices > 0) { m_advData.uuids16_is_complete = 0;
for (int i = 0; i < numServices; i++) { continue;
if(m_serviceUUIDs[i].getNative()->u.type == BLE_UUID_TYPE_16) { }
int add = (m_advData.num_uuids16 > 0) ? 2 : 4; payloadLen += add;
if((payloadLen + add) > 31){
m_advData.uuids16_is_complete = 0; if(nullptr == (m_advData.uuids16 = (ble_uuid16_t*)realloc(m_advData.uuids16,
continue; (m_advData.num_uuids16 + 1) * sizeof(ble_uuid16_t))))
}
payloadLen += add;
if(nullptr == (m_advData.uuids16 = (ble_uuid16_t*)realloc(m_advData.uuids16,
(m_advData.num_uuids16 + 1) * sizeof(ble_uuid16_t))))
{ {
NIMBLE_LOGE(LOG_TAG, "Error, no mem"); NIMBLE_LOGE(LOG_TAG, "Error, no mem");
abort(); abort();
} }
memcpy(&m_advData.uuids16[m_advData.num_uuids16].value, memcpy(&m_advData.uuids16[m_advData.num_uuids16].value,
&m_serviceUUIDs[i].getNative()->u16.value, sizeof(uint16_t)); &m_serviceUUIDs[i].getNative()->u16.value, sizeof(uint16_t));
m_advData.uuids16[m_advData.num_uuids16].u.type = BLE_UUID_TYPE_16; m_advData.uuids16[m_advData.num_uuids16].u.type = BLE_UUID_TYPE_16;
m_advData.uuids16_is_complete = 1; m_advData.uuids16_is_complete = 1;
m_advData.num_uuids16++; m_advData.num_uuids16++;
} }
if(m_serviceUUIDs[i].getNative()->u.type == BLE_UUID_TYPE_32) { if(m_serviceUUIDs[i].getNative()->u.type == BLE_UUID_TYPE_32) {
int add = (m_advData.num_uuids32 > 0) ? 4 : 6; int add = (m_advData.num_uuids32 > 0) ? 4 : 6;
if((payloadLen + add) > 31){ if((payloadLen + add) > 31){
m_advData.uuids32_is_complete = 0; m_advData.uuids32_is_complete = 0;
continue; continue;
} }
payloadLen += add; payloadLen += add;
if(nullptr == (m_advData.uuids32 = (ble_uuid32_t*)realloc(m_advData.uuids32, if(nullptr == (m_advData.uuids32 = (ble_uuid32_t*)realloc(m_advData.uuids32,
(m_advData.num_uuids32 + 1) * sizeof(ble_uuid32_t)))) (m_advData.num_uuids32 + 1) * sizeof(ble_uuid32_t))))
{ {
NIMBLE_LOGE(LOG_TAG, "Error, no mem"); NIMBLE_LOGE(LOG_TAG, "Error, no mem");
abort(); abort();
} }
memcpy(&m_advData.uuids32[m_advData.num_uuids32].value, memcpy(&m_advData.uuids32[m_advData.num_uuids32].value,
&m_serviceUUIDs[i].getNative()->u32.value, sizeof(uint32_t)); &m_serviceUUIDs[i].getNative()->u32.value, sizeof(uint32_t));
m_advData.uuids32[m_advData.num_uuids32].u.type = BLE_UUID_TYPE_32; m_advData.uuids32[m_advData.num_uuids32].u.type = BLE_UUID_TYPE_32;
m_advData.uuids32_is_complete = 1; m_advData.uuids32_is_complete = 1;
m_advData.num_uuids32++; m_advData.num_uuids32++;
} }
if(m_serviceUUIDs[i].getNative()->u.type == BLE_UUID_TYPE_128){ if(m_serviceUUIDs[i].getNative()->u.type == BLE_UUID_TYPE_128){
int add = (m_advData.num_uuids128 > 0) ? 16 : 18; int add = (m_advData.num_uuids128 > 0) ? 16 : 18;
if((payloadLen + add) > 31){ if((payloadLen + add) > 31){
m_advData.uuids128_is_complete = 0; m_advData.uuids128_is_complete = 0;
continue; continue;
} }
payloadLen += add; payloadLen += add;
if(nullptr == (m_advData.uuids128 = (ble_uuid128_t*)realloc(m_advData.uuids128, if(nullptr == (m_advData.uuids128 = (ble_uuid128_t*)realloc(m_advData.uuids128,
(m_advData.num_uuids128 + 1) * sizeof(ble_uuid128_t)))) { (m_advData.num_uuids128 + 1) * sizeof(ble_uuid128_t)))) {
NIMBLE_LOGE(LOG_TAG, "Error, no mem"); NIMBLE_LOGE(LOG_TAG, "Error, no mem");
abort(); abort();
} }
memcpy(&m_advData.uuids128[m_advData.num_uuids128].value, memcpy(&m_advData.uuids128[m_advData.num_uuids128].value,
&m_serviceUUIDs[i].getNative()->u128.value, 16); &m_serviceUUIDs[i].getNative()->u128.value, 16);
m_advData.uuids128[m_advData.num_uuids128].u.type = BLE_UUID_TYPE_128; m_advData.uuids128[m_advData.num_uuids128].u.type = BLE_UUID_TYPE_128;
m_advData.uuids128_is_complete = 1; m_advData.uuids128_is_complete = 1;
m_advData.num_uuids128++; m_advData.num_uuids128++;
} }
} }
// check if there is room for the name, if not put it in scan data // check if there is room for the name, if not put it in scan data
if((payloadLen + m_advData.name_len) > 29) { if((payloadLen + m_advData.name_len) > 29) {
if(m_scanResp){ if(m_scanResp){
m_scanData.name = m_advData.name; m_scanData.name = m_advData.name;
m_scanData.name_len = m_advData.name_len; m_scanData.name_len = m_advData.name_len;
m_scanData.name_is_complete = m_advData.name_is_complete; m_scanData.name_is_complete = m_advData.name_is_complete;
m_advData.name = nullptr; m_advData.name = nullptr;
m_advData.name_len = 0; m_advData.name_len = 0;
} else { } else {
// if not using scan response just cut the name down // if not using scan response just cut the name down
// leaving 2 bytes for the data specifier. // leaving 2 bytes for the data specifier.
m_advData.name_len = (29 - payloadLen); m_advData.name_len = (29 - payloadLen);
} }
m_advData.name_is_complete = 0; m_advData.name_is_complete = 0;
} }
if(m_advData.name_len > 0) { if(m_advData.name_len > 0) {
payloadLen += (m_advData.name_len + 2); payloadLen += (m_advData.name_len + 2);
} }
if(m_scanResp) { if(m_scanResp) {
// name length + type byte + length byte + tx power type + length + data // name length + type byte + length byte + tx power type + length + data
if((m_scanData.name_len + 5) > 31) { if((m_scanData.name_len + 5) > 31) {
// prioritize name data over tx power // prioritize name data over tx power
m_scanData.tx_pwr_lvl_is_present = 0; m_scanData.tx_pwr_lvl_is_present = 0;
m_scanData.tx_pwr_lvl = 0; m_scanData.tx_pwr_lvl = 0;
// limit name to 29 to leave room for the data specifiers // limit name to 29 to leave room for the data specifiers
if(m_scanData.name_len > 29) { if(m_scanData.name_len > 29) {
m_scanData.name_len = 29; m_scanData.name_len = 29;
m_scanData.name_is_complete = false; m_scanData.name_is_complete = false;
} }
} }
rc = ble_gap_adv_rsp_set_fields(&m_scanData); rc = ble_gap_adv_rsp_set_fields(&m_scanData);
if (rc != 0) { if (rc != 0) {
NIMBLE_LOGE(LOG_TAG, "error setting scan response data; rc=%d, %s", rc, NimBLEUtils::returnCodeToString(rc)); NIMBLE_LOGE(LOG_TAG, "error setting scan response data; rc=%d, %s", rc, NimBLEUtils::returnCodeToString(rc));
abort(); abort();
} }
// if not using scan response and there is room, // if not using scan response and there is room,
// throw the tx power data into the advertisment // throw the tx power data into the advertisment
} else if (payloadLen < 29) { } else if (payloadLen < 29) {
m_advData.tx_pwr_lvl_is_present = 1; m_advData.tx_pwr_lvl_is_present = 1;
m_advData.tx_pwr_lvl = NimBLEDevice::getPower(); m_advData.tx_pwr_lvl = NimBLEDevice::getPower();
} }
rc = ble_gap_adv_set_fields(&m_advData); rc = ble_gap_adv_set_fields(&m_advData);
if (rc != 0) { if (rc != 0) {
NIMBLE_LOGE(LOG_TAG, "error setting advertisement data; rc=%d, %s", rc, NimBLEUtils::returnCodeToString(rc)); NIMBLE_LOGE(LOG_TAG, "error setting advertisement data; rc=%d, %s", rc, NimBLEUtils::returnCodeToString(rc));
abort(); abort();
} }
if(m_advData.num_uuids128 > 0) { if(m_advData.num_uuids128 > 0) {
free(m_advData.uuids128); free(m_advData.uuids128);
m_advData.uuids128 = nullptr; m_advData.uuids128 = nullptr;
m_advData.num_uuids128 = 0; m_advData.num_uuids128 = 0;
} }
if(m_advData.num_uuids32 > 0) { if(m_advData.num_uuids32 > 0) {
free(m_advData.uuids32); free(m_advData.uuids32);
m_advData.uuids32 = nullptr; m_advData.uuids32 = nullptr;
m_advData.num_uuids32 = 0; m_advData.num_uuids32 = 0;
} }
if(m_advData.num_uuids16 > 0) { if(m_advData.num_uuids16 > 0) {
free(m_advData.uuids16); free(m_advData.uuids16);
m_advData.uuids16 = nullptr; m_advData.uuids16 = nullptr;
m_advData.num_uuids16 = 0; m_advData.num_uuids16 = 0;
} }
m_advSvcsSet = true; m_advSvcsSet = true;
} }
rc = ble_hs_id_infer_auto(0, &addressType); rc = ble_hs_id_infer_auto(0, &addressType);
if (rc != 0) { if (rc != 0) {
NIMBLE_LOGC(LOG_TAG, "Error determining address type; rc=%d, %s", rc, NimBLEUtils::returnCodeToString(rc)); NIMBLE_LOGC(LOG_TAG, "Error determining address type; rc=%d, %s", rc, NimBLEUtils::returnCodeToString(rc));
abort(); abort();
} }
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
rc = ble_gap_adv_start(addressType, NULL, BLE_HS_FOREVER, rc = ble_gap_adv_start(addressType, NULL, BLE_HS_FOREVER,
&m_advParams, NimBLEServer::handleGapEvent, NimBLEDevice::createServer()); //get a reference to the server (does not create a new one) &m_advParams, NimBLEServer::handleGapEvent, NimBLEDevice::createServer()); //get a reference to the server (does not create a new one)
#else
rc = ble_gap_adv_start(addressType, NULL, BLE_HS_FOREVER,
&m_advParams, NULL,NULL);
#endif
if (rc != 0) { if (rc != 0) {
NIMBLE_LOGC(LOG_TAG, "Error enabling advertising; rc=%d, %s", rc, NimBLEUtils::returnCodeToString(rc)); NIMBLE_LOGC(LOG_TAG, "Error enabling advertising; rc=%d, %s", rc, NimBLEUtils::returnCodeToString(rc));
abort(); abort();
} }
NIMBLE_LOGD(LOG_TAG, "<< Advertising start"); NIMBLE_LOGD(LOG_TAG, "<< Advertising start");
} // start } // start
@ -369,35 +378,35 @@ void NimBLEAdvertising::start() {
* @return N/A. * @return N/A.
*/ */
void NimBLEAdvertising::stop() { void NimBLEAdvertising::stop() {
NIMBLE_LOGD(LOG_TAG, ">> stop"); NIMBLE_LOGD(LOG_TAG, ">> stop");
int rc = ble_gap_adv_stop(); int rc = ble_gap_adv_stop();
if (rc != 0 && rc != BLE_HS_EALREADY) { if (rc != 0 && rc != BLE_HS_EALREADY) {
NIMBLE_LOGE(LOG_TAG, "ble_gap_adv_stop rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc)); NIMBLE_LOGE(LOG_TAG, "ble_gap_adv_stop rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
return; return;
} }
NIMBLE_LOGD(LOG_TAG, "<< stop"); NIMBLE_LOGD(LOG_TAG, "<< stop");
} // stop } // stop
/** /**
* Host reset seems to clear advertising data, * Host reset seems to clear advertising data,
* we need clear the flag so it reloads it. * we need clear the flag so it reloads it.
*/ */
void NimBLEAdvertising::onHostReset() { void NimBLEAdvertising::onHostReset() {
m_advSvcsSet = false; m_advSvcsSet = false;
} }
/** /**
* @brief Add data to the payload to be advertised. * @brief Add data to the payload to be advertised.
* @param [in] data The data to be added to the payload. * @param [in] data The data to be added to the payload.
*/ */
void NimBLEAdvertisementData::addData(const std::string &data) { void NimBLEAdvertisementData::addData(const std::string &data) {
if ((m_payload.length() + data.length()) > BLE_HS_ADV_MAX_SZ) { if ((m_payload.length() + data.length()) > BLE_HS_ADV_MAX_SZ) {
return; return;
} }
m_payload.append(data); m_payload.append(data);
} // addData } // addData
@ -409,10 +418,10 @@ void NimBLEAdvertisementData::addData(const std::string &data) {
* https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.gap.appearance.xml * https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.gap.appearance.xml
*/ */
void NimBLEAdvertisementData::setAppearance(uint16_t appearance) { void NimBLEAdvertisementData::setAppearance(uint16_t appearance) {
char cdata[2]; char cdata[2];
cdata[0] = 3; cdata[0] = 3;
cdata[1] = BLE_HS_ADV_TYPE_APPEARANCE; // 0x19 cdata[1] = BLE_HS_ADV_TYPE_APPEARANCE; // 0x19
addData(std::string(cdata, 2) + std::string((char*) &appearance, 2)); addData(std::string(cdata, 2) + std::string((char*) &appearance, 2));
} // setAppearance } // setAppearance
@ -421,35 +430,35 @@ void NimBLEAdvertisementData::setAppearance(uint16_t appearance) {
* @param [in] uuid The single service to advertise. * @param [in] uuid The single service to advertise.
*/ */
void NimBLEAdvertisementData::setCompleteServices(const NimBLEUUID &uuid) { void NimBLEAdvertisementData::setCompleteServices(const NimBLEUUID &uuid) {
char cdata[2]; char cdata[2];
switch (uuid.bitSize()) { switch (uuid.bitSize()) {
case 16: { case 16: {
// [Len] [0x02] [LL] [HH] // [Len] [0x02] [LL] [HH]
cdata[0] = 3; cdata[0] = 3;
cdata[1] = BLE_HS_ADV_TYPE_COMP_UUIDS16; // 0x03 cdata[1] = BLE_HS_ADV_TYPE_COMP_UUIDS16; // 0x03
addData(std::string(cdata, 2) + std::string((char*) &uuid.getNative()->u16.value, 2)); addData(std::string(cdata, 2) + std::string((char*) &uuid.getNative()->u16.value, 2));
break; break;
} }
case 32: { case 32: {
// [Len] [0x04] [LL] [LL] [HH] [HH] // [Len] [0x04] [LL] [LL] [HH] [HH]
cdata[0] = 5; cdata[0] = 5;
cdata[1] = BLE_HS_ADV_TYPE_COMP_UUIDS32; // 0x05 cdata[1] = BLE_HS_ADV_TYPE_COMP_UUIDS32; // 0x05
addData(std::string(cdata, 2) + std::string((char*) &uuid.getNative()->u32.value, 4)); addData(std::string(cdata, 2) + std::string((char*) &uuid.getNative()->u32.value, 4));
break; break;
} }
case 128: { case 128: {
// [Len] [0x04] [0] [1] ... [15] // [Len] [0x04] [0] [1] ... [15]
cdata[0] = 17; cdata[0] = 17;
cdata[1] = BLE_HS_ADV_TYPE_COMP_UUIDS128; // 0x07 cdata[1] = BLE_HS_ADV_TYPE_COMP_UUIDS128; // 0x07
addData(std::string(cdata, 2) + std::string((char*) uuid.getNative()->u128.value, 16)); addData(std::string(cdata, 2) + std::string((char*) uuid.getNative()->u128.value, 16));
break; break;
} }
default: default:
return; return;
} }
} // setCompleteServices } // setCompleteServices
@ -463,18 +472,18 @@ void NimBLEAdvertisementData::setCompleteServices(const NimBLEUUID &uuid) {
* * ESP_BLE_ADV_FLAG_DMT_CONTROLLER_SPT * * ESP_BLE_ADV_FLAG_DMT_CONTROLLER_SPT
* * ESP_BLE_ADV_FLAG_DMT_HOST_SPT * * ESP_BLE_ADV_FLAG_DMT_HOST_SPT
* * ESP_BLE_ADV_FLAG_NON_LIMIT_DISC * * ESP_BLE_ADV_FLAG_NON_LIMIT_DISC
* * * *
* * ****THESE ARE SUPPORTED**** * * ****THESE ARE SUPPORTED****
* * BLE_HS_ADV_F_DISC_LTD * * BLE_HS_ADV_F_DISC_LTD
* * BLE_HS_ADV_F_DISC_GEN * * BLE_HS_ADV_F_DISC_GEN
* * BLE_HS_ADV_F_BREDR_UNSUP - must always use with NimBLE * * BLE_HS_ADV_F_BREDR_UNSUP - must always use with NimBLE
*/ */
void NimBLEAdvertisementData::setFlags(uint8_t flag) { void NimBLEAdvertisementData::setFlags(uint8_t flag) {
char cdata[3]; char cdata[3];
cdata[0] = 2; cdata[0] = 2;
cdata[1] = BLE_HS_ADV_TYPE_FLAGS; // 0x01 cdata[1] = BLE_HS_ADV_TYPE_FLAGS; // 0x01
cdata[2] = flag | BLE_HS_ADV_F_BREDR_UNSUP; cdata[2] = flag | BLE_HS_ADV_F_BREDR_UNSUP;
addData(std::string(cdata, 3)); addData(std::string(cdata, 3));
} // setFlag } // setFlag
@ -483,12 +492,12 @@ void NimBLEAdvertisementData::setFlags(uint8_t flag) {
* @param [in] data Manufacturer data. * @param [in] data Manufacturer data.
*/ */
void NimBLEAdvertisementData::setManufacturerData(const std::string &data) { void NimBLEAdvertisementData::setManufacturerData(const std::string &data) {
NIMBLE_LOGD("NimBLEAdvertisementData", ">> setManufacturerData"); NIMBLE_LOGD("NimBLEAdvertisementData", ">> setManufacturerData");
char cdata[2]; char cdata[2];
cdata[0] = data.length() + 1; cdata[0] = data.length() + 1;
cdata[1] = BLE_HS_ADV_TYPE_MFG_DATA ; // 0xff cdata[1] = BLE_HS_ADV_TYPE_MFG_DATA ; // 0xff
addData(std::string(cdata, 2) + data); addData(std::string(cdata, 2) + data);
NIMBLE_LOGD("NimBLEAdvertisementData", "<< setManufacturerData"); NIMBLE_LOGD("NimBLEAdvertisementData", "<< setManufacturerData");
} // setManufacturerData } // setManufacturerData
@ -497,12 +506,12 @@ void NimBLEAdvertisementData::setManufacturerData(const std::string &data) {
* @param [in] The complete name of the device. * @param [in] The complete name of the device.
*/ */
void NimBLEAdvertisementData::setName(const std::string &name) { void NimBLEAdvertisementData::setName(const std::string &name) {
NIMBLE_LOGD("NimBLEAdvertisementData", ">> setName: %s", name.c_str()); NIMBLE_LOGD("NimBLEAdvertisementData", ">> setName: %s", name.c_str());
char cdata[2]; char cdata[2];
cdata[0] = name.length() + 1; cdata[0] = name.length() + 1;
cdata[1] = BLE_HS_ADV_TYPE_COMP_NAME; // 0x09 cdata[1] = BLE_HS_ADV_TYPE_COMP_NAME; // 0x09
addData(std::string(cdata, 2) + name); addData(std::string(cdata, 2) + name);
NIMBLE_LOGD("NimBLEAdvertisementData", "<< setName"); NIMBLE_LOGD("NimBLEAdvertisementData", "<< setName");
} // setName } // setName
@ -511,35 +520,35 @@ void NimBLEAdvertisementData::setName(const std::string &name) {
* @param [in] uuid The single service to advertise. * @param [in] uuid The single service to advertise.
*/ */
void NimBLEAdvertisementData::setPartialServices(const NimBLEUUID &uuid) { void NimBLEAdvertisementData::setPartialServices(const NimBLEUUID &uuid) {
char cdata[2]; char cdata[2];
switch (uuid.bitSize()) { switch (uuid.bitSize()) {
case 16: { case 16: {
// [Len] [0x02] [LL] [HH] // [Len] [0x02] [LL] [HH]
cdata[0] = 3; cdata[0] = 3;
cdata[1] = BLE_HS_ADV_TYPE_INCOMP_UUIDS16; // 0x02 cdata[1] = BLE_HS_ADV_TYPE_INCOMP_UUIDS16; // 0x02
addData(std::string(cdata, 2) + std::string((char *) &uuid.getNative()->u16.value, 2)); addData(std::string(cdata, 2) + std::string((char *) &uuid.getNative()->u16.value, 2));
break; break;
} }
case 32: { case 32: {
// [Len] [0x04] [LL] [LL] [HH] [HH] // [Len] [0x04] [LL] [LL] [HH] [HH]
cdata[0] = 5; cdata[0] = 5;
cdata[1] = BLE_HS_ADV_TYPE_INCOMP_UUIDS32; // 0x04 cdata[1] = BLE_HS_ADV_TYPE_INCOMP_UUIDS32; // 0x04
addData(std::string(cdata, 2) + std::string((char *) &uuid.getNative()->u32.value, 4)); addData(std::string(cdata, 2) + std::string((char *) &uuid.getNative()->u32.value, 4));
break; break;
} }
case 128: { case 128: {
// [Len] [0x04] [0] [1] ... [15] // [Len] [0x04] [0] [1] ... [15]
cdata[0] = 17; cdata[0] = 17;
cdata[1] = BLE_HS_ADV_TYPE_INCOMP_UUIDS128; // 0x06 cdata[1] = BLE_HS_ADV_TYPE_INCOMP_UUIDS128; // 0x06
addData(std::string(cdata, 2) + std::string((char *) &uuid.getNative()->u128.value, 16)); addData(std::string(cdata, 2) + std::string((char *) &uuid.getNative()->u128.value, 16));
break; break;
} }
default: default:
return; return;
} }
} // setPartialServices } // setPartialServices
@ -549,35 +558,35 @@ void NimBLEAdvertisementData::setPartialServices(const NimBLEUUID &uuid) {
* @param [in] data The data to be associated with the service data advert. * @param [in] data The data to be associated with the service data advert.
*/ */
void NimBLEAdvertisementData::setServiceData(const NimBLEUUID &uuid, const std::string &data) { void NimBLEAdvertisementData::setServiceData(const NimBLEUUID &uuid, const std::string &data) {
char cdata[2]; char cdata[2];
switch (uuid.bitSize()) { switch (uuid.bitSize()) {
case 16: { case 16: {
// [Len] [0x16] [UUID16] data // [Len] [0x16] [UUID16] data
cdata[0] = data.length() + 3; cdata[0] = data.length() + 3;
cdata[1] = BLE_HS_ADV_TYPE_SVC_DATA_UUID16; // 0x16 cdata[1] = BLE_HS_ADV_TYPE_SVC_DATA_UUID16; // 0x16
addData(std::string(cdata, 2) + std::string((char*) &uuid.getNative()->u16.value, 2) + data); addData(std::string(cdata, 2) + std::string((char*) &uuid.getNative()->u16.value, 2) + data);
break; break;
} }
case 32: { case 32: {
// [Len] [0x20] [UUID32] data // [Len] [0x20] [UUID32] data
cdata[0] = data.length() + 5; cdata[0] = data.length() + 5;
cdata[1] = BLE_HS_ADV_TYPE_SVC_DATA_UUID32; // 0x20 cdata[1] = BLE_HS_ADV_TYPE_SVC_DATA_UUID32; // 0x20
addData(std::string(cdata, 2) + std::string((char*) &uuid.getNative()->u32.value, 4) + data); addData(std::string(cdata, 2) + std::string((char*) &uuid.getNative()->u32.value, 4) + data);
break; break;
} }
case 128: { case 128: {
// [Len] [0x21] [UUID128] data // [Len] [0x21] [UUID128] data
cdata[0] = data.length() + 17; cdata[0] = data.length() + 17;
cdata[1] = BLE_HS_ADV_TYPE_SVC_DATA_UUID128; // 0x21 cdata[1] = BLE_HS_ADV_TYPE_SVC_DATA_UUID128; // 0x21
addData(std::string(cdata, 2) + std::string((char*) &uuid.getNative()->u128.value, 16) + data); addData(std::string(cdata, 2) + std::string((char*) &uuid.getNative()->u128.value, 16) + data);
break; break;
} }
default: default:
return; return;
} }
} // setServiceData } // setServiceData
@ -586,12 +595,12 @@ void NimBLEAdvertisementData::setServiceData(const NimBLEUUID &uuid, const std::
* @param [in] The short name of the device. * @param [in] The short name of the device.
*/ */
void NimBLEAdvertisementData::setShortName(const std::string &name) { void NimBLEAdvertisementData::setShortName(const std::string &name) {
NIMBLE_LOGD("NimBLEAdvertisementData", ">> setShortName: %s", name.c_str()); NIMBLE_LOGD("NimBLEAdvertisementData", ">> setShortName: %s", name.c_str());
char cdata[2]; char cdata[2];
cdata[0] = name.length() + 1; cdata[0] = name.length() + 1;
cdata[1] = BLE_HS_ADV_TYPE_INCOMP_NAME; // 0x08 cdata[1] = BLE_HS_ADV_TYPE_INCOMP_NAME; // 0x08
addData(std::string(cdata, 2) + name); addData(std::string(cdata, 2) + name);
NIMBLE_LOGD("NimBLEAdvertisementData", "<< setShortName"); NIMBLE_LOGD("NimBLEAdvertisementData", "<< setShortName");
} // setShortName } // setShortName
@ -600,7 +609,8 @@ void NimBLEAdvertisementData::setShortName(const std::string &name) {
* @return The payload that is to be advertised. * @return The payload that is to be advertised.
*/ */
std::string NimBLEAdvertisementData::getPayload() { std::string NimBLEAdvertisementData::getPayload() {
return m_payload; return m_payload;
} // getPayload } // getPayload
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#endif /* CONFIG_BT_ENABLED */ #endif /* CONFIG_BT_ENABLED */

View file

@ -3,7 +3,7 @@
* *
* Created: on March 3, 2020 * Created: on March 3, 2020
* Author H2zero * Author H2zero
* *
* Originally: * Originally:
* *
* BLEAdvertising.h * BLEAdvertising.h
@ -17,6 +17,9 @@
#include "sdkconfig.h" #include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED) #if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h"
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
#include "host/ble_gap.h" #include "host/ble_gap.h"
/**** FIX COMPILATION ****/ /**** FIX COMPILATION ****/
#undef min #undef min
@ -42,24 +45,24 @@
* @brief Advertisement data set by the programmer to be published by the %BLE server. * @brief Advertisement data set by the programmer to be published by the %BLE server.
*/ */
class NimBLEAdvertisementData { class NimBLEAdvertisementData {
// Only a subset of the possible BLE architected advertisement fields are currently exposed. Others will // Only a subset of the possible BLE architected advertisement fields are currently exposed. Others will
// be exposed on demand/request or as time permits. // be exposed on demand/request or as time permits.
// //
public: public:
void setAppearance(uint16_t appearance); void setAppearance(uint16_t appearance);
void setCompleteServices(const NimBLEUUID &uuid); void setCompleteServices(const NimBLEUUID &uuid);
void setFlags(uint8_t); void setFlags(uint8_t);
void setManufacturerData(const std::string &data); void setManufacturerData(const std::string &data);
void setName(const std::string &name); void setName(const std::string &name);
void setPartialServices(const NimBLEUUID &uuid); void setPartialServices(const NimBLEUUID &uuid);
void setServiceData(const NimBLEUUID &uuid, const std::string &data); void setServiceData(const NimBLEUUID &uuid, const std::string &data);
void setShortName(const std::string &name); void setShortName(const std::string &name);
void addData(const std::string &data); // Add data to the payload. void addData(const std::string &data); // Add data to the payload.
std::string getPayload(); // Retrieve the current advert payload. std::string getPayload(); // Retrieve the current advert payload.
private: private:
friend class NimBLEAdvertising; friend class NimBLEAdvertising;
std::string m_payload; // The payload of the advertisement. std::string m_payload; // The payload of the advertisement.
}; // NimBLEAdvertisementData }; // NimBLEAdvertisementData
@ -70,36 +73,40 @@ private:
*/ */
class NimBLEAdvertising { class NimBLEAdvertising {
public: public:
NimBLEAdvertising(); NimBLEAdvertising();
void addServiceUUID(const NimBLEUUID &serviceUUID); void addServiceUUID(const NimBLEUUID &serviceUUID);
void addServiceUUID(const char* serviceUUID); void addServiceUUID(const char* serviceUUID);
void start(); void start();
void stop(); void stop();
void setAppearance(uint16_t appearance); void setAppearance(uint16_t appearance);
void setAdvertisementType(uint8_t adv_type); void setAdvertisementType(uint8_t adv_type);
void setMaxInterval(uint16_t maxinterval); void setMaxInterval(uint16_t maxinterval);
void setMinInterval(uint16_t mininterval); void setMinInterval(uint16_t mininterval);
void setAdvertisementData(NimBLEAdvertisementData& advertisementData); void setAdvertisementData(NimBLEAdvertisementData& advertisementData);
void setScanFilter(bool scanRequertWhitelistOnly, bool connectWhitelistOnly); void setScanFilter(bool scanRequertWhitelistOnly, bool connectWhitelistOnly);
void setScanResponseData(NimBLEAdvertisementData& advertisementData); void setScanResponseData(NimBLEAdvertisementData& advertisementData);
void setPrivateAddress(uint8_t type = BLE_ADDR_RANDOM); void setPrivateAddress(uint8_t type = BLE_ADDR_RANDOM);
void setMinPreferred(uint16_t); void setMinPreferred(uint16_t);
void setMaxPreferred(uint16_t); void setMaxPreferred(uint16_t);
void setScanResponse(bool); void setScanResponse(bool);
private: private:
friend class NimBLEDevice; friend class NimBLEDevice;
void onHostReset(); void onHostReset();
ble_hs_adv_fields m_advData;
ble_hs_adv_fields m_scanData; ble_hs_adv_fields m_advData;
ble_gap_adv_params m_advParams; ble_hs_adv_fields m_scanData;
std::vector<NimBLEUUID> m_serviceUUIDs; ble_gap_adv_params m_advParams;
bool m_customAdvData = false; // Are we using custom advertising data? std::vector<NimBLEUUID> m_serviceUUIDs;
bool m_customScanResponseData = false; // Are we using custom scan response data? bool m_customAdvData = false; // Are we using custom advertising data?
bool m_scanResp = true; bool m_customScanResponseData = false; // Are we using custom scan response data?
bool m_scanResp = true;
bool m_advSvcsSet = false; bool m_advSvcsSet = false;
}; };
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#endif /* CONFIG_BT_ENABLED */ #endif /* CONFIG_BT_ENABLED */
#endif /* MAIN_BLEADVERTISING_H_ */ #endif /* MAIN_BLEADVERTISING_H_ */

View file

@ -3,7 +3,7 @@
* *
* Created: on March 15 2020 * Created: on March 15 2020
* Author H2zero * Author H2zero
* *
* Originally: * Originally:
* *
* BLEBeacon.cpp * BLEBeacon.cpp
@ -13,6 +13,7 @@
*/ */
#include "sdkconfig.h" #include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED) #if defined(CONFIG_BT_ENABLED)
#include <string.h> #include <string.h>
#include "NimBLEBeacon.h" #include "NimBLEBeacon.h"
#include "NimBLELog.h" #include "NimBLELog.h"
@ -22,72 +23,71 @@
static const char* LOG_TAG = "NimBLEBeacon"; static const char* LOG_TAG = "NimBLEBeacon";
NimBLEBeacon::NimBLEBeacon() { NimBLEBeacon::NimBLEBeacon() {
m_beaconData.manufacturerId = 0x4c00; m_beaconData.manufacturerId = 0x4c00;
m_beaconData.subType = 0x02; m_beaconData.subType = 0x02;
m_beaconData.subTypeLength = 0x15; m_beaconData.subTypeLength = 0x15;
m_beaconData.major = 0; m_beaconData.major = 0;
m_beaconData.minor = 0; m_beaconData.minor = 0;
m_beaconData.signalPower = 0; m_beaconData.signalPower = 0;
memset(m_beaconData.proximityUUID, 0, sizeof(m_beaconData.proximityUUID)); memset(m_beaconData.proximityUUID, 0, sizeof(m_beaconData.proximityUUID));
} // NimBLEBeacon } // NimBLEBeacon
std::string NimBLEBeacon::getData() { std::string NimBLEBeacon::getData() {
return std::string((char*) &m_beaconData, sizeof(m_beaconData)); return std::string((char*) &m_beaconData, sizeof(m_beaconData));
} // getData } // getData
uint16_t NimBLEBeacon::getMajor() { uint16_t NimBLEBeacon::getMajor() {
return m_beaconData.major; return m_beaconData.major;
} }
uint16_t NimBLEBeacon::getManufacturerId() { uint16_t NimBLEBeacon::getManufacturerId() {
return m_beaconData.manufacturerId; return m_beaconData.manufacturerId;
} }
uint16_t NimBLEBeacon::getMinor() { uint16_t NimBLEBeacon::getMinor() {
return m_beaconData.minor; return m_beaconData.minor;
} }
NimBLEUUID NimBLEBeacon::getProximityUUID() { NimBLEUUID NimBLEBeacon::getProximityUUID() {
return NimBLEUUID(m_beaconData.proximityUUID, 16, false); return NimBLEUUID(m_beaconData.proximityUUID, 16, false);
} }
int8_t NimBLEBeacon::getSignalPower() { int8_t NimBLEBeacon::getSignalPower() {
return m_beaconData.signalPower; return m_beaconData.signalPower;
} }
/** /**
* Set the raw data for the beacon record. * Set the raw data for the beacon record.
*/ */
void NimBLEBeacon::setData(const std::string &data) { void NimBLEBeacon::setData(const std::string &data) {
if (data.length() != sizeof(m_beaconData)) { if (data.length() != sizeof(m_beaconData)) {
NIMBLE_LOGE(LOG_TAG, "Unable to set the data ... length passed in was %d and expected %d", NIMBLE_LOGE(LOG_TAG, "Unable to set the data ... length passed in was %d and expected %d",
data.length(), sizeof(m_beaconData)); data.length(), sizeof(m_beaconData));
return; return;
} }
memcpy(&m_beaconData, data.data(), sizeof(m_beaconData)); memcpy(&m_beaconData, data.data(), sizeof(m_beaconData));
} // setData } // setData
void NimBLEBeacon::setMajor(uint16_t major) { void NimBLEBeacon::setMajor(uint16_t major) {
m_beaconData.major = ENDIAN_CHANGE_U16(major); m_beaconData.major = ENDIAN_CHANGE_U16(major);
} // setMajor } // setMajor
void NimBLEBeacon::setManufacturerId(uint16_t manufacturerId) { void NimBLEBeacon::setManufacturerId(uint16_t manufacturerId) {
m_beaconData.manufacturerId = ENDIAN_CHANGE_U16(manufacturerId); m_beaconData.manufacturerId = ENDIAN_CHANGE_U16(manufacturerId);
} // setManufacturerId } // setManufacturerId
void NimBLEBeacon::setMinor(uint16_t minor) { void NimBLEBeacon::setMinor(uint16_t minor) {
m_beaconData.minor = ENDIAN_CHANGE_U16(minor); m_beaconData.minor = ENDIAN_CHANGE_U16(minor);
} // setMinior } // setMinior
void NimBLEBeacon::setProximityUUID(const NimBLEUUID &uuid) { void NimBLEBeacon::setProximityUUID(const NimBLEUUID &uuid) {
NimBLEUUID temp_uuid = uuid; NimBLEUUID temp_uuid = uuid;
temp_uuid.to128(); temp_uuid.to128();
memcpy(m_beaconData.proximityUUID, temp_uuid.getNative()->u128.value, 16); memcpy(m_beaconData.proximityUUID, temp_uuid.getNative()->u128.value, 16);
} // setProximityUUID } // setProximityUUID
void NimBLEBeacon::setSignalPower(int8_t signalPower) { void NimBLEBeacon::setSignalPower(int8_t signalPower) {
m_beaconData.signalPower = signalPower; m_beaconData.signalPower = signalPower;
} // setSignalPower } // setSignalPower
#endif #endif

View file

@ -3,7 +3,7 @@
* *
* Created: on March 15 2020 * Created: on March 15 2020
* Author H2zero * Author H2zero
* *
* Originally: * Originally:
* *
* BLEBeacon2.h * BLEBeacon2.h
@ -14,6 +14,7 @@
#ifndef MAIN_NIMBLEBEACON_H_ #ifndef MAIN_NIMBLEBEACON_H_
#define MAIN_NIMBLEBEACON_H_ #define MAIN_NIMBLEBEACON_H_
#include "NimBLEUUID.h" #include "NimBLEUUID.h"
/** /**
* @brief Representation of a beacon. * @brief Representation of a beacon.
@ -22,29 +23,29 @@
*/ */
class NimBLEBeacon { class NimBLEBeacon {
private: private:
struct { struct {
uint16_t manufacturerId; uint16_t manufacturerId;
uint8_t subType; uint8_t subType;
uint8_t subTypeLength; uint8_t subTypeLength;
uint8_t proximityUUID[16]; uint8_t proximityUUID[16];
uint16_t major; uint16_t major;
uint16_t minor; uint16_t minor;
int8_t signalPower; int8_t signalPower;
} __attribute__((packed)) m_beaconData; } __attribute__((packed)) m_beaconData;
public: public:
NimBLEBeacon(); NimBLEBeacon();
std::string getData(); std::string getData();
uint16_t getMajor(); uint16_t getMajor();
uint16_t getMinor(); uint16_t getMinor();
uint16_t getManufacturerId(); uint16_t getManufacturerId();
NimBLEUUID getProximityUUID(); NimBLEUUID getProximityUUID();
int8_t getSignalPower(); int8_t getSignalPower();
void setData(const std::string &data); void setData(const std::string &data);
void setMajor(uint16_t major); void setMajor(uint16_t major);
void setMinor(uint16_t minor); void setMinor(uint16_t minor);
void setManufacturerId(uint16_t manufacturerId); void setManufacturerId(uint16_t manufacturerId);
void setProximityUUID(const NimBLEUUID &uuid); void setProximityUUID(const NimBLEUUID &uuid);
void setSignalPower(int8_t signalPower); void setSignalPower(int8_t signalPower);
}; // NimBLEBeacon }; // NimBLEBeacon
#endif /* MAIN_NIMBLEBEACON_H_ */ #endif /* MAIN_NIMBLEBEACON_H_ */

View file

@ -3,7 +3,7 @@
* *
* Created: on March 3, 2020 * Created: on March 3, 2020
* Author H2zero * Author H2zero
* *
* BLECharacteristic.cpp * BLECharacteristic.cpp
* *
* Created on: Jun 22, 2017 * Created on: Jun 22, 2017
@ -12,6 +12,9 @@
#include "sdkconfig.h" #include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED) #if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h"
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#include "NimBLECharacteristic.h" #include "NimBLECharacteristic.h"
#include "NimBLE2902.h" #include "NimBLE2902.h"
#include "NimBLE2904.h" #include "NimBLE2904.h"
@ -32,7 +35,7 @@ static const char* LOG_TAG = "NimBLECharacteristic";
* @param [in] uuid - UUID (const char*) for the characteristic. * @param [in] uuid - UUID (const char*) for the characteristic.
* @param [in] properties - Properties for the characteristic. * @param [in] properties - Properties for the characteristic.
*/ */
NimBLECharacteristic::NimBLECharacteristic(const char* uuid, uint16_t properties, NimBLEService* pService) NimBLECharacteristic::NimBLECharacteristic(const char* uuid, uint16_t properties, NimBLEService* pService)
: NimBLECharacteristic(NimBLEUUID(uuid), properties, pService) { : NimBLECharacteristic(NimBLEUUID(uuid), properties, pService) {
} }
@ -42,18 +45,18 @@ NimBLECharacteristic::NimBLECharacteristic(const char* uuid, uint16_t properties
* @param [in] properties - Properties for the characteristic. * @param [in] properties - Properties for the characteristic.
*/ */
NimBLECharacteristic::NimBLECharacteristic(const NimBLEUUID &uuid, uint16_t properties, NimBLEService* pService) { NimBLECharacteristic::NimBLECharacteristic(const NimBLEUUID &uuid, uint16_t properties, NimBLEService* pService) {
m_uuid = uuid; m_uuid = uuid;
m_handle = NULL_HANDLE; m_handle = NULL_HANDLE;
m_properties = properties; m_properties = properties;
m_pCallbacks = &defaultCallback; m_pCallbacks = &defaultCallback;
m_pService = pService; m_pService = pService;
// Backward Compatibility - to be removed // Backward Compatibility - to be removed
/* setBroadcastProperty((properties & PROPERTY_BROADCAST) != 0); /* setBroadcastProperty((properties & PROPERTY_BROADCAST) != 0);
setReadProperty((properties & PROPERTY_READ) != 0); setReadProperty((properties & PROPERTY_READ) != 0);
setWriteProperty((properties & PROPERTY_WRITE) != 0); setWriteProperty((properties & PROPERTY_WRITE) != 0);
setNotifyProperty((properties & PROPERTY_NOTIFY) != 0); setNotifyProperty((properties & PROPERTY_NOTIFY) != 0);
setIndicateProperty((properties & PROPERTY_INDICATE) != 0); setIndicateProperty((properties & PROPERTY_INDICATE) != 0);
setWriteNoResponseProperty((properties & PROPERTY_WRITE_NR) != 0); setWriteNoResponseProperty((properties & PROPERTY_WRITE_NR) != 0);
*/ */
/////////////////////////////////////////// ///////////////////////////////////////////
} // NimBLECharacteristic } // NimBLECharacteristic
@ -71,14 +74,14 @@ NimBLECharacteristic::~NimBLECharacteristic() {
* @return N/A. * @return N/A.
*/ */
void NimBLECharacteristic::addDescriptor(NimBLEDescriptor* pDescriptor) { void NimBLECharacteristic::addDescriptor(NimBLEDescriptor* pDescriptor) {
NIMBLE_LOGD(LOG_TAG, ">> addDescriptor(): Adding %s to %s", pDescriptor->toString().c_str(), toString().c_str()); NIMBLE_LOGD(LOG_TAG, ">> addDescriptor(): Adding %s to %s", pDescriptor->toString().c_str(), toString().c_str());
// Check that we don't add the same descriptor twice. // Check that we don't add the same descriptor twice.
if (m_descriptorMap.getByUUID(pDescriptor->getUUID()) != nullptr) { if (m_descriptorMap.getByUUID(pDescriptor->getUUID()) != nullptr) {
NIMBLE_LOGW(LOG_TAG, "<< Adding a new descriptor with the same UUID as a previous one"); NIMBLE_LOGW(LOG_TAG, "<< Adding a new descriptor with the same UUID as a previous one");
//return; //return;
} }
m_descriptorMap.setByUUID(pDescriptor->getUUID(), pDescriptor); m_descriptorMap.setByUUID(pDescriptor->getUUID(), pDescriptor);
NIMBLE_LOGD(LOG_TAG, "<< addDescriptor()"); NIMBLE_LOGD(LOG_TAG, "<< addDescriptor()");
} // addDescriptor } // addDescriptor
@ -89,7 +92,7 @@ void NimBLECharacteristic::addDescriptor(NimBLEDescriptor* pDescriptor) {
* @return The new BLE descriptor. * @return The new BLE descriptor.
*/ */
NimBLEDescriptor* NimBLECharacteristic::createDescriptor(const char* uuid, uint32_t properties, uint16_t max_len) { NimBLEDescriptor* NimBLECharacteristic::createDescriptor(const char* uuid, uint32_t properties, uint16_t max_len) {
return createDescriptor(NimBLEUUID(uuid), properties, max_len); return createDescriptor(NimBLEUUID(uuid), properties, max_len);
} }
@ -100,8 +103,8 @@ NimBLEDescriptor* NimBLECharacteristic::createDescriptor(const char* uuid, uint3
* @return The new BLE descriptor. * @return The new BLE descriptor.
*/ */
NimBLEDescriptor* NimBLECharacteristic::createDescriptor(const NimBLEUUID &uuid, uint32_t properties, uint16_t max_len) { NimBLEDescriptor* NimBLECharacteristic::createDescriptor(const NimBLEUUID &uuid, uint32_t properties, uint16_t max_len) {
NimBLEDescriptor* pDescriptor = nullptr; NimBLEDescriptor* pDescriptor = nullptr;
if(uuid.equals(NimBLEUUID((uint16_t)0x2902))) { if(uuid.equals(NimBLEUUID((uint16_t)0x2902))) {
if(!(m_properties & BLE_GATT_CHR_F_NOTIFY) && !(m_properties & BLE_GATT_CHR_F_INDICATE)) { if(!(m_properties & BLE_GATT_CHR_F_NOTIFY) && !(m_properties & BLE_GATT_CHR_F_INDICATE)) {
assert(0 && "Cannot create 2902 descriptior without characteristic notification or indication property set"); assert(0 && "Cannot create 2902 descriptior without characteristic notification or indication property set");
} }
@ -112,15 +115,15 @@ NimBLEDescriptor* NimBLECharacteristic::createDescriptor(const NimBLEUUID &uuid,
} else { } else {
return pDescriptor; return pDescriptor;
} }
} else if (uuid.equals(NimBLEUUID((uint16_t)0x2904))) { } else if (uuid.equals(NimBLEUUID((uint16_t)0x2904))) {
pDescriptor = new NimBLE2904(this); pDescriptor = new NimBLE2904(this);
} else { } else {
pDescriptor = new NimBLEDescriptor(uuid, properties, max_len, this); pDescriptor = new NimBLEDescriptor(uuid, properties, max_len, this);
} }
addDescriptor(pDescriptor); addDescriptor(pDescriptor);
return pDescriptor; return pDescriptor;
} // createCharacteristic } // createCharacteristic
@ -130,7 +133,7 @@ NimBLEDescriptor* NimBLECharacteristic::createDescriptor(const NimBLEUUID &uuid,
* @return The BLE Descriptor. If no such descriptor is associated with the characteristic, nullptr is returned. * @return The BLE Descriptor. If no such descriptor is associated with the characteristic, nullptr is returned.
*/ */
NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(const char* descriptorUUID) { NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(const char* descriptorUUID) {
return m_descriptorMap.getByUUID(NimBLEUUID(descriptorUUID)); return m_descriptorMap.getByUUID(NimBLEUUID(descriptorUUID));
} // getDescriptorByUUID } // getDescriptorByUUID
@ -140,7 +143,7 @@ NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(const char* descript
* @return The BLE Descriptor. If no such descriptor is associated with the characteristic, nullptr is returned. * @return The BLE Descriptor. If no such descriptor is associated with the characteristic, nullptr is returned.
*/ */
NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(const NimBLEUUID &descriptorUUID) { NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(const NimBLEUUID &descriptorUUID) {
return m_descriptorMap.getByUUID(descriptorUUID); return m_descriptorMap.getByUUID(descriptorUUID);
} // getDescriptorByUUID } // getDescriptorByUUID
@ -149,17 +152,17 @@ NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(const NimBLEUUID &de
* @return The handle of the characteristic. * @return The handle of the characteristic.
*/ */
uint16_t NimBLECharacteristic::getHandle() { uint16_t NimBLECharacteristic::getHandle() {
return m_handle; return m_handle;
} // getHandle } // getHandle
/* /*
void NimBLECharacteristic::setAccessPermissions(uint16_t perm) { void NimBLECharacteristic::setAccessPermissions(uint16_t perm) {
m_permissions = perm; m_permissions = perm;
} }
*/ */
uint8_t NimBLECharacteristic::getProperties() { uint8_t NimBLECharacteristic::getProperties() {
return m_properties; return m_properties;
} // getProperties } // getProperties
@ -167,7 +170,7 @@ uint8_t NimBLECharacteristic::getProperties() {
* @brief Get the service associated with this characteristic. * @brief Get the service associated with this characteristic.
*/ */
NimBLEService* NimBLECharacteristic::getService() { NimBLEService* NimBLECharacteristic::getService() {
return m_pService; return m_pService;
} // getService } // getService
@ -176,7 +179,7 @@ NimBLEService* NimBLECharacteristic::getService() {
* @return The UUID of the characteristic. * @return The UUID of the characteristic.
*/ */
NimBLEUUID NimBLECharacteristic::getUUID() { NimBLEUUID NimBLECharacteristic::getUUID() {
return m_uuid; return m_uuid;
} // getUUID } // getUUID
@ -185,7 +188,7 @@ NimBLEUUID NimBLECharacteristic::getUUID() {
* @return A pointer to storage containing the current characteristic value. * @return A pointer to storage containing the current characteristic value.
*/ */
std::string NimBLECharacteristic::getValue() { std::string NimBLECharacteristic::getValue() {
return m_value.getValue(); return m_value.getValue();
} // getValue } // getValue
@ -194,7 +197,7 @@ std::string NimBLECharacteristic::getValue() {
* @return A pointer to storage containing the current characteristic data. * @return A pointer to storage containing the current characteristic data.
*/ */
uint8_t* NimBLECharacteristic::getData() { uint8_t* NimBLECharacteristic::getData() {
return m_value.getData(); return m_value.getData();
} // getData } // getData
@ -203,7 +206,7 @@ uint8_t* NimBLECharacteristic::getData() {
* @return The length of the current characteristic data. * @return The length of the current characteristic data.
*/ */
size_t NimBLECharacteristic:: getDataLength() { size_t NimBLECharacteristic:: getDataLength() {
return m_value.getLength(); return m_value.getLength();
} }
@ -211,43 +214,43 @@ int NimBLECharacteristic::handleGapEvent(uint16_t conn_handle, uint16_t attr_han
struct ble_gatt_access_ctxt *ctxt, struct ble_gatt_access_ctxt *ctxt,
void *arg) void *arg)
{ {
const ble_uuid_t *uuid; const ble_uuid_t *uuid;
int rc; int rc;
NimBLECharacteristic* pCharacteristic = (NimBLECharacteristic*)arg; NimBLECharacteristic* pCharacteristic = (NimBLECharacteristic*)arg;
NIMBLE_LOGD(LOG_TAG, "Characteristic %s %s event", pCharacteristic->getUUID().toString().c_str(), NIMBLE_LOGD(LOG_TAG, "Characteristic %s %s event", pCharacteristic->getUUID().toString().c_str(),
ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR ? "Read" : "Write"); ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR ? "Read" : "Write");
uuid = ctxt->chr->uuid; uuid = ctxt->chr->uuid;
if(ble_uuid_cmp(uuid, &pCharacteristic->getUUID().getNative()->u) == 0){ if(ble_uuid_cmp(uuid, &pCharacteristic->getUUID().getNative()->u) == 0){
switch(ctxt->op) { switch(ctxt->op) {
case BLE_GATT_ACCESS_OP_READ_CHR: { case BLE_GATT_ACCESS_OP_READ_CHR: {
//NIMBLE_LOGD(LOG_TAG, "read char pkthdr len:%d flags:%d", ctxt->om->om_pkthdr_len, ctxt->om->om_flags); //NIMBLE_LOGD(LOG_TAG, "read char pkthdr len:%d flags:%d", ctxt->om->om_pkthdr_len, ctxt->om->om_flags);
// If the packet header is only 8 bytes this is a follow up of a long read // If the packet header is only 8 bytes this is a follow up of a long read
// so we don't want to call the onRead() callback again. // so we don't want to call the onRead() callback again.
if(ctxt->om->om_pkthdr_len > 8) { if(ctxt->om->om_pkthdr_len > 8) {
pCharacteristic->m_pCallbacks->onRead(pCharacteristic); pCharacteristic->m_pCallbacks->onRead(pCharacteristic);
} }
rc = os_mbuf_append(ctxt->om, pCharacteristic->getData(), pCharacteristic->m_value.getLength()); rc = os_mbuf_append(ctxt->om, pCharacteristic->getData(), pCharacteristic->m_value.getLength());
return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
} }
case BLE_GATT_ACCESS_OP_WRITE_CHR: { case BLE_GATT_ACCESS_OP_WRITE_CHR: {
//NIMBLE_LOGD(LOG_TAG, "write char pkthdr len:%d datalen:%d", ctxt->om->om_pkthdr_len, ctxt->om->om_len); //NIMBLE_LOGD(LOG_TAG, "write char pkthdr len:%d datalen:%d", ctxt->om->om_pkthdr_len, ctxt->om->om_len);
if (ctxt->om->om_len > BLE_ATT_ATTR_MAX_LEN) { if (ctxt->om->om_len > BLE_ATT_ATTR_MAX_LEN) {
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
} }
//pCharacteristic->setValue(ctxt->om->om_data, ctxt->om->om_len); //pCharacteristic->setValue(ctxt->om->om_data, ctxt->om->om_len);
pCharacteristic->m_value.addPart(ctxt->om->om_data, ctxt->om->om_len); pCharacteristic->m_value.addPart(ctxt->om->om_data, ctxt->om->om_len);
os_mbuf *next; os_mbuf *next;
next = SLIST_NEXT(ctxt->om, om_next); next = SLIST_NEXT(ctxt->om, om_next);
while(next != NULL){ while(next != NULL){
//NIMBLE_LOGD(LOG_TAG, "Found long write data, len:%d", next->om_len); //NIMBLE_LOGD(LOG_TAG, "Found long write data, len:%d", next->om_len);
pCharacteristic->m_value.addPart(next->om_data, next->om_len); pCharacteristic->m_value.addPart(next->om_data, next->om_len);
next = SLIST_NEXT(next, om_next); next = SLIST_NEXT(next, om_next);
} }
pCharacteristic->m_value.commit(); pCharacteristic->m_value.commit();
pCharacteristic->m_pCallbacks->onWrite(pCharacteristic); pCharacteristic->m_pCallbacks->onWrite(pCharacteristic);
return 0; return 0;
@ -255,11 +258,11 @@ int NimBLECharacteristic::handleGapEvent(uint16_t conn_handle, uint16_t attr_han
default: default:
break; break;
} }
} }
return BLE_ATT_ERR_UNLIKELY; return BLE_ATT_ERR_UNLIKELY;
} }
/** /**
* @brief Set the subscribe status for this characteristic. * @brief Set the subscribe status for this characteristic.
@ -274,23 +277,23 @@ void NimBLECharacteristic::setSubscribe(struct ble_gap_event *event) {
if(event->subscribe.cur_indicate) { if(event->subscribe.cur_indicate) {
subVal |= NIMBLE_DESC_FLAG_INDICATE; subVal |= NIMBLE_DESC_FLAG_INDICATE;
} }
m_semaphoreConfEvt.give((subVal | NIMBLE_DESC_FLAG_INDICATE) ? 0 : m_semaphoreConfEvt.give((subVal | NIMBLE_DESC_FLAG_INDICATE) ? 0 :
NimBLECharacteristicCallbacks::Status::ERROR_INDICATE_DISABLED); NimBLECharacteristicCallbacks::Status::ERROR_INDICATE_DISABLED);
NIMBLE_LOGI(LOG_TAG, "New subscribe value for conn: %d val: %d", event->subscribe.conn_handle, subVal); NIMBLE_LOGI(LOG_TAG, "New subscribe value for conn: %d val: %d", event->subscribe.conn_handle, subVal);
NimBLE2902* p2902 = (NimBLE2902*)getDescriptorByUUID((uint16_t)0x2902); NimBLE2902* p2902 = (NimBLE2902*)getDescriptorByUUID((uint16_t)0x2902);
if(p2902 == nullptr){ if(p2902 == nullptr){
ESP_LOGE(LOG_TAG, "No 2902 descriptor found for %s", getUUID().toString().c_str()); ESP_LOGE(LOG_TAG, "No 2902 descriptor found for %s", getUUID().toString().c_str());
return; return;
} }
p2902->setNotifications(subVal & NIMBLE_DESC_FLAG_NOTIFY); p2902->setNotifications(subVal & NIMBLE_DESC_FLAG_NOTIFY);
p2902->setIndications(subVal & NIMBLE_DESC_FLAG_INDICATE); p2902->setIndications(subVal & NIMBLE_DESC_FLAG_INDICATE);
p2902->m_pCallbacks->onWrite(p2902); p2902->m_pCallbacks->onWrite(p2902);
auto it = p2902->m_subscribedMap.find(event->subscribe.conn_handle); auto it = p2902->m_subscribedMap.find(event->subscribe.conn_handle);
if(subVal > 0 && it == p2902->m_subscribedMap.cend()) { if(subVal > 0 && it == p2902->m_subscribedMap.cend()) {
p2902->m_subscribedMap.insert(std::pair<uint16_t, uint16_t>(event->subscribe.conn_handle, subVal)); p2902->m_subscribedMap.insert(std::pair<uint16_t, uint16_t>(event->subscribe.conn_handle, subVal));
@ -299,12 +302,12 @@ void NimBLECharacteristic::setSubscribe(struct ble_gap_event *event) {
p2902->m_subscribedMap.erase(event->subscribe.conn_handle); p2902->m_subscribedMap.erase(event->subscribe.conn_handle);
return; return;
} }
/* /*
if(event->subscribe.reason == BLE_GAP_SUBSCRIBE_REASON_TERM) { if(event->subscribe.reason == BLE_GAP_SUBSCRIBE_REASON_TERM) {
p2902->m_subscribedMap.erase(event->subscribe.conn_handle); p2902->m_subscribedMap.erase(event->subscribe.conn_handle);
return; return;
} }
*/ */
(*it).second = subVal; (*it).second = subVal;
} }
@ -316,11 +319,11 @@ void NimBLECharacteristic::setSubscribe(struct ble_gap_event *event) {
* @return N/A * @return N/A
*/ */
void NimBLECharacteristic::indicate() { void NimBLECharacteristic::indicate() {
NIMBLE_LOGD(LOG_TAG, ">> indicate: length: %d", m_value.getValue().length()); NIMBLE_LOGD(LOG_TAG, ">> indicate: length: %d", m_value.getValue().length());
notify(false); notify(false);
NIMBLE_LOGD(LOG_TAG, "<< indicate"); NIMBLE_LOGD(LOG_TAG, "<< indicate");
} // indicate } // indicate
/** /**
* @brief Send a notify. * @brief Send a notify.
* A notification is a transmission of up to the first 20 bytes of the characteristic value. An notification * A notification is a transmission of up to the first 20 bytes of the characteristic value. An notification
@ -328,29 +331,29 @@ void NimBLECharacteristic::indicate() {
* @return N/A. * @return N/A.
*/ */
void NimBLECharacteristic::notify(bool is_notification) { void NimBLECharacteristic::notify(bool is_notification) {
NIMBLE_LOGD(LOG_TAG, ">> notify: length: %d", m_value.getValue().length()); NIMBLE_LOGD(LOG_TAG, ">> notify: length: %d", m_value.getValue().length());
assert(getService() != nullptr); assert(getService() != nullptr);
assert(getService()->getServer() != nullptr); assert(getService()->getServer() != nullptr);
if (getService()->getServer()->getConnectedCount() == 0) { if (getService()->getServer()->getConnectedCount() == 0) {
NIMBLE_LOGD(LOG_TAG, "<< notify: No connected clients."); NIMBLE_LOGD(LOG_TAG, "<< notify: No connected clients.");
return; return;
} }
m_pCallbacks->onNotify(this); m_pCallbacks->onNotify(this);
int rc = 0; int rc = 0;
NimBLE2902* p2902 = (NimBLE2902*)getDescriptorByUUID((uint16_t)0x2902); NimBLE2902* p2902 = (NimBLE2902*)getDescriptorByUUID((uint16_t)0x2902);
for (auto it = p2902->m_subscribedMap.cbegin(); it != p2902->m_subscribedMap.cend(); ++it) { for (auto it = p2902->m_subscribedMap.cbegin(); it != p2902->m_subscribedMap.cend(); ++it) {
uint16_t _mtu = getService()->getServer()->getPeerMTU((*it).first); uint16_t _mtu = getService()->getServer()->getPeerMTU((*it).first);
// Must rebuild the data on each loop iteration as NimBLE will release it. // Must rebuild the data on each loop iteration as NimBLE will release it.
size_t length = m_value.getValue().length(); size_t length = m_value.getValue().length();
uint8_t* data = (uint8_t*)m_value.getValue().data(); uint8_t* data = (uint8_t*)m_value.getValue().data();
os_mbuf *om; os_mbuf *om;
if(_mtu == 0) { if(_mtu == 0) {
//NIMBLE_LOGD(LOG_TAG, "peer not connected, removing from map"); //NIMBLE_LOGD(LOG_TAG, "peer not connected, removing from map");
p2902->m_subscribedMap.erase((*it).first); p2902->m_subscribedMap.erase((*it).first);
@ -360,33 +363,33 @@ void NimBLECharacteristic::notify(bool is_notification) {
} }
continue; continue;
} }
if (length > _mtu - 3) { if (length > _mtu - 3) {
NIMBLE_LOGW(LOG_TAG, "- Truncating to %d bytes (maximum notify size)", _mtu - 3); NIMBLE_LOGW(LOG_TAG, "- Truncating to %d bytes (maximum notify size)", _mtu - 3);
} }
if((*it).second == 0) { if((*it).second == 0) {
//NIMBLE_LOGI(LOG_TAG, "Skipping unsubscribed client"); //NIMBLE_LOGI(LOG_TAG, "Skipping unsubscribed client");
continue; continue;
} }
if(is_notification && (!((*it).second & NIMBLE_DESC_FLAG_NOTIFY))) { if(is_notification && (!((*it).second & NIMBLE_DESC_FLAG_NOTIFY))) {
NIMBLE_LOGW(LOG_TAG, NIMBLE_LOGW(LOG_TAG,
"Sending notification to client subscribed to indications, sending indication instead"); "Sending notification to client subscribed to indications, sending indication instead");
is_notification = false; is_notification = false;
} }
if(!is_notification && (!((*it).second & NIMBLE_DESC_FLAG_INDICATE))) { if(!is_notification && (!((*it).second & NIMBLE_DESC_FLAG_INDICATE))) {
NIMBLE_LOGW(LOG_TAG, NIMBLE_LOGW(LOG_TAG,
"Sending indication to client subscribed to notifications, sending notifications instead"); "Sending indication to client subscribed to notifications, sending notifications instead");
is_notification = true; is_notification = true;
} }
// don't create the m_buf until we are sure to send the data or else // don't create the m_buf until we are sure to send the data or else
// we could be allocating a buffer that doesn't get released. // we could be allocating a buffer that doesn't get released.
// We also must create it in each loop iteration because it is consumed with each host call. // We also must create it in each loop iteration because it is consumed with each host call.
om = ble_hs_mbuf_from_flat(data, length); om = ble_hs_mbuf_from_flat(data, length);
if(!is_notification) { if(!is_notification) {
m_semaphoreConfEvt.take("indicate"); m_semaphoreConfEvt.take("indicate");
rc = ble_gattc_indicate_custom((*it).first, m_handle, om); rc = ble_gattc_indicate_custom((*it).first, m_handle, om);
@ -395,9 +398,9 @@ void NimBLECharacteristic::notify(bool is_notification) {
m_pCallbacks->onStatus(this, NimBLECharacteristicCallbacks::Status::ERROR_GATT, rc); m_pCallbacks->onStatus(this, NimBLECharacteristicCallbacks::Status::ERROR_GATT, rc);
return; return;
} }
rc = m_semaphoreConfEvt.wait(); rc = m_semaphoreConfEvt.wait();
if(rc == BLE_HS_ETIMEOUT) { if(rc == BLE_HS_ETIMEOUT) {
m_pCallbacks->onStatus(this, NimBLECharacteristicCallbacks::Status::ERROR_INDICATE_TIMEOUT, rc); m_pCallbacks->onStatus(this, NimBLECharacteristicCallbacks::Status::ERROR_INDICATE_TIMEOUT, rc);
} else if(rc == BLE_HS_EDONE) { } else if(rc == BLE_HS_EDONE) {
@ -410,12 +413,12 @@ void NimBLECharacteristic::notify(bool is_notification) {
if(rc == 0) { if(rc == 0) {
m_pCallbacks->onStatus(this, NimBLECharacteristicCallbacks::Status::SUCCESS_NOTIFY, 0); m_pCallbacks->onStatus(this, NimBLECharacteristicCallbacks::Status::SUCCESS_NOTIFY, 0);
} else { } else {
m_pCallbacks->onStatus(this, NimBLECharacteristicCallbacks::Status::ERROR_GATT, rc); m_pCallbacks->onStatus(this, NimBLECharacteristicCallbacks::Status::ERROR_GATT, rc);
} }
} }
} }
NIMBLE_LOGD(LOG_TAG, "<< notify"); NIMBLE_LOGD(LOG_TAG, "<< notify");
} // Notify } // Notify
@ -424,11 +427,11 @@ void NimBLECharacteristic::notify(bool is_notification) {
* @param [in] pCallbacks An instance of a callbacks structure used to define any callbacks for the characteristic. * @param [in] pCallbacks An instance of a callbacks structure used to define any callbacks for the characteristic.
*/ */
void NimBLECharacteristic::setCallbacks(NimBLECharacteristicCallbacks* pCallbacks) { void NimBLECharacteristic::setCallbacks(NimBLECharacteristicCallbacks* pCallbacks) {
if (pCallbacks != nullptr){ if (pCallbacks != nullptr){
m_pCallbacks = pCallbacks; m_pCallbacks = pCallbacks;
} else { } else {
m_pCallbacks = &defaultCallback; m_pCallbacks = &defaultCallback;
} }
} // setCallbacks } // setCallbacks
// Backward compatibility - to be removed //////////////////////////////// // Backward compatibility - to be removed ////////////////////////////////
@ -440,11 +443,11 @@ void NimBLECharacteristic::setCallbacks(NimBLECharacteristicCallbacks* pCallback
* @return N/A * @return N/A
*/ */
void NimBLECharacteristic::setBroadcastProperty(bool value) { void NimBLECharacteristic::setBroadcastProperty(bool value) {
if (value) { if (value) {
m_properties = (m_properties | BLE_GATT_CHR_F_BROADCAST); m_properties = (m_properties | BLE_GATT_CHR_F_BROADCAST);
} else { } else {
m_properties = (m_properties & ~BLE_GATT_CHR_F_BROADCAST); m_properties = (m_properties & ~BLE_GATT_CHR_F_BROADCAST);
} }
} // setBroadcastProperty } // setBroadcastProperty
@ -453,11 +456,11 @@ void NimBLECharacteristic::setBroadcastProperty(bool value) {
* @param [in] value Set to true if we are to allow indicate messages. * @param [in] value Set to true if we are to allow indicate messages.
*/ */
void NimBLECharacteristic::setIndicateProperty(bool value) { void NimBLECharacteristic::setIndicateProperty(bool value) {
if (value) { if (value) {
m_properties = (m_properties | BLE_GATT_CHR_F_INDICATE); m_properties = (m_properties | BLE_GATT_CHR_F_INDICATE);
} else { } else {
m_properties = (m_properties & ~BLE_GATT_CHR_F_INDICATE); m_properties = (m_properties & ~BLE_GATT_CHR_F_INDICATE);
} }
} // setIndicateProperty } // setIndicateProperty
@ -466,11 +469,11 @@ void NimBLECharacteristic::setIndicateProperty(bool value) {
* @param [in] value Set to true if we are to allow notification messages. * @param [in] value Set to true if we are to allow notification messages.
*/ */
void NimBLECharacteristic::setNotifyProperty(bool value) { void NimBLECharacteristic::setNotifyProperty(bool value) {
if (value) { if (value) {
m_properties = (m_properties | BLE_GATT_CHR_F_NOTIFY); m_properties = (m_properties | BLE_GATT_CHR_F_NOTIFY);
} else { } else {
m_properties = (m_properties & ~BLE_GATT_CHR_F_NOTIFY); m_properties = (m_properties & ~BLE_GATT_CHR_F_NOTIFY);
} }
} // setNotifyProperty } // setNotifyProperty
@ -479,11 +482,11 @@ void NimBLECharacteristic::setNotifyProperty(bool value) {
* @param [in] value Set to true if we are to allow reads. * @param [in] value Set to true if we are to allow reads.
*/ */
void NimBLECharacteristic::setReadProperty(bool value) { void NimBLECharacteristic::setReadProperty(bool value) {
if (value) { if (value) {
m_properties = (m_properties | BLE_GATT_CHR_F_READ); m_properties = (m_properties | BLE_GATT_CHR_F_READ);
} else { } else {
m_properties = (m_properties & ~BLE_GATT_CHR_F_READ); m_properties = (m_properties & ~BLE_GATT_CHR_F_READ);
} }
} // setReadProperty } // setReadProperty
@ -492,11 +495,11 @@ void NimBLECharacteristic::setReadProperty(bool value) {
* @param [in] value Set to true if we are to allow writes with no response. * @param [in] value Set to true if we are to allow writes with no response.
*/ */
void NimBLECharacteristic::setWriteNoResponseProperty(bool value) { void NimBLECharacteristic::setWriteNoResponseProperty(bool value) {
if (value) { if (value) {
m_properties = (m_properties | BLE_GATT_CHR_F_WRITE_NO_RSP); m_properties = (m_properties | BLE_GATT_CHR_F_WRITE_NO_RSP);
} else { } else {
m_properties = (m_properties & ~BLE_GATT_CHR_F_WRITE_NO_RSP); m_properties = (m_properties & ~BLE_GATT_CHR_F_WRITE_NO_RSP);
} }
} // setWriteNoResponseProperty } // setWriteNoResponseProperty
@ -505,11 +508,11 @@ void NimBLECharacteristic::setWriteNoResponseProperty(bool value) {
* @param [in] value Set to true if we are to allow writes. * @param [in] value Set to true if we are to allow writes.
*/ */
void NimBLECharacteristic::setWriteProperty(bool value) { void NimBLECharacteristic::setWriteProperty(bool value) {
if (value) { if (value) {
m_properties = (m_properties | BLE_GATT_CHR_F_WRITE ); m_properties = (m_properties | BLE_GATT_CHR_F_WRITE );
} else { } else {
m_properties = (m_properties & ~BLE_GATT_CHR_F_WRITE ); m_properties = (m_properties & ~BLE_GATT_CHR_F_WRITE );
} }
} // setWriteProperty } // setWriteProperty
////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////
@ -519,23 +522,23 @@ void NimBLECharacteristic::setWriteProperty(bool value) {
* @param [in] length The length of the data in bytes. * @param [in] length The length of the data in bytes.
*/ */
void NimBLECharacteristic::setValue(const uint8_t* data, size_t length) { void NimBLECharacteristic::setValue(const uint8_t* data, size_t length) {
char* pHex = NimBLEUtils::buildHexData(nullptr, data, length); char* pHex = NimBLEUtils::buildHexData(nullptr, data, length);
NIMBLE_LOGD(LOG_TAG, ">> setValue: length=%d, data=%s, characteristic UUID=%s", length, pHex, getUUID().toString().c_str()); NIMBLE_LOGD(LOG_TAG, ">> setValue: length=%d, data=%s, characteristic UUID=%s", length, pHex, getUUID().toString().c_str());
free(pHex); free(pHex);
if (length > BLE_ATT_ATTR_MAX_LEN) {
NIMBLE_LOGE(LOG_TAG, "Size %d too large, must be no bigger than %d", length, BLE_ATT_ATTR_MAX_LEN);
return;
}
m_value.setValue(data, length);
if (length > BLE_ATT_ATTR_MAX_LEN) {
NIMBLE_LOGE(LOG_TAG, "Size %d too large, must be no bigger than %d", length, BLE_ATT_ATTR_MAX_LEN);
return;
}
m_value.setValue(data, length);
// if(m_handle != NULL_HANDLE) { // if(m_handle != NULL_HANDLE) {
//ble_gatts_chr_updated(m_handle); //ble_gatts_chr_updated(m_handle);
// ble_gattc_notify(getService()->getServer()->m_connId, m_handle); // ble_gattc_notify(getService()->getServer()->m_connId, m_handle);
// } // }
NIMBLE_LOGD(LOG_TAG, "<< setValue"); NIMBLE_LOGD(LOG_TAG, "<< setValue");
} // setValue } // setValue
@ -547,42 +550,42 @@ void NimBLECharacteristic::setValue(const uint8_t* data, size_t length) {
* @return N/A. * @return N/A.
*/ */
void NimBLECharacteristic::setValue(const std::string &value) { void NimBLECharacteristic::setValue(const std::string &value) {
setValue((uint8_t*)(value.data()), value.length()); setValue((uint8_t*)(value.data()), value.length());
} // setValue } // setValue
void NimBLECharacteristic::setValue(uint16_t& data16) { void NimBLECharacteristic::setValue(uint16_t& data16) {
uint8_t temp[2]; uint8_t temp[2];
temp[0] = data16; temp[0] = data16;
temp[1] = data16 >> 8; temp[1] = data16 >> 8;
setValue(temp, 2); setValue(temp, 2);
} // setValue } // setValue
void NimBLECharacteristic::setValue(uint32_t& data32) { void NimBLECharacteristic::setValue(uint32_t& data32) {
uint8_t temp[4]; uint8_t temp[4];
temp[0] = data32; temp[0] = data32;
temp[1] = data32 >> 8; temp[1] = data32 >> 8;
temp[2] = data32 >> 16; temp[2] = data32 >> 16;
temp[3] = data32 >> 24; temp[3] = data32 >> 24;
setValue(temp, 4); setValue(temp, 4);
} // setValue } // setValue
void NimBLECharacteristic::setValue(int& data32) { void NimBLECharacteristic::setValue(int& data32) {
uint8_t temp[4]; uint8_t temp[4];
temp[0] = data32; temp[0] = data32;
temp[1] = data32 >> 8; temp[1] = data32 >> 8;
temp[2] = data32 >> 16; temp[2] = data32 >> 16;
temp[3] = data32 >> 24; temp[3] = data32 >> 24;
setValue(temp, 4); setValue(temp, 4);
} // setValue } // setValue
void NimBLECharacteristic::setValue(float& data32) { void NimBLECharacteristic::setValue(float& data32) {
float temp = data32; float temp = data32;
setValue((uint8_t*)&temp, 4); setValue((uint8_t*)&temp, 4);
} // setValue } // setValue
void NimBLECharacteristic::setValue(double& data64) { void NimBLECharacteristic::setValue(double& data64) {
double temp = data64; double temp = data64;
setValue((uint8_t*)&temp, 8); setValue((uint8_t*)&temp, 8);
} // setValue } // setValue
@ -591,18 +594,18 @@ void NimBLECharacteristic::setValue(double& data64) {
* @return A string representation of the characteristic. * @return A string representation of the characteristic.
*/ */
std::string NimBLECharacteristic::toString() { std::string NimBLECharacteristic::toString() {
std::string res = "UUID: " + m_uuid.toString() + ", handle : 0x"; std::string res = "UUID: " + m_uuid.toString() + ", handle : 0x";
char hex[5]; char hex[5];
snprintf(hex, sizeof(hex), "%04x", m_handle); snprintf(hex, sizeof(hex), "%04x", m_handle);
res += hex; res += hex;
res += " "; res += " ";
if (m_properties & BLE_GATT_CHR_PROP_READ ) res += "Read "; if (m_properties & BLE_GATT_CHR_PROP_READ ) res += "Read ";
if (m_properties & BLE_GATT_CHR_PROP_WRITE) res += "Write "; if (m_properties & BLE_GATT_CHR_PROP_WRITE) res += "Write ";
if (m_properties & BLE_GATT_CHR_PROP_WRITE_NO_RSP) res += "WriteNoResponse "; if (m_properties & BLE_GATT_CHR_PROP_WRITE_NO_RSP) res += "WriteNoResponse ";
if (m_properties & BLE_GATT_CHR_PROP_BROADCAST) res += "Broadcast "; if (m_properties & BLE_GATT_CHR_PROP_BROADCAST) res += "Broadcast ";
if (m_properties & BLE_GATT_CHR_PROP_NOTIFY) res += "Notify "; if (m_properties & BLE_GATT_CHR_PROP_NOTIFY) res += "Notify ";
if (m_properties & BLE_GATT_CHR_PROP_INDICATE) res += "Indicate "; if (m_properties & BLE_GATT_CHR_PROP_INDICATE) res += "Indicate ";
return res; return res;
} // toString } // toString
@ -614,7 +617,7 @@ NimBLECharacteristicCallbacks::~NimBLECharacteristicCallbacks() {}
* @param [in] pCharacteristic The characteristic that is the source of the event. * @param [in] pCharacteristic The characteristic that is the source of the event.
*/ */
void NimBLECharacteristicCallbacks::onRead(NimBLECharacteristic* pCharacteristic) { void NimBLECharacteristicCallbacks::onRead(NimBLECharacteristic* pCharacteristic) {
NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onRead: default"); NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onRead: default");
} // onRead } // onRead
@ -623,7 +626,7 @@ void NimBLECharacteristicCallbacks::onRead(NimBLECharacteristic* pCharacteristic
* @param [in] pCharacteristic The characteristic that is the source of the event. * @param [in] pCharacteristic The characteristic that is the source of the event.
*/ */
void NimBLECharacteristicCallbacks::onWrite(NimBLECharacteristic* pCharacteristic) { void NimBLECharacteristicCallbacks::onWrite(NimBLECharacteristic* pCharacteristic) {
NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onWrite: default"); NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onWrite: default");
} // onWrite } // onWrite
@ -632,7 +635,7 @@ void NimBLECharacteristicCallbacks::onWrite(NimBLECharacteristic* pCharacteristi
* @param [in] pCharacteristic The characteristic that is the source of the event. * @param [in] pCharacteristic The characteristic that is the source of the event.
*/ */
void NimBLECharacteristicCallbacks::onNotify(NimBLECharacteristic* pCharacteristic) { void NimBLECharacteristicCallbacks::onNotify(NimBLECharacteristic* pCharacteristic) {
NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onNotify: default"); NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onNotify: default");
} // onNotify } // onNotify
@ -643,7 +646,8 @@ void NimBLECharacteristicCallbacks::onNotify(NimBLECharacteristic* pCharacterist
* @param [in] code Additional code of underlying errors * @param [in] code Additional code of underlying errors
*/ */
void NimBLECharacteristicCallbacks::onStatus(NimBLECharacteristic* pCharacteristic, Status s, int code) { void NimBLECharacteristicCallbacks::onStatus(NimBLECharacteristic* pCharacteristic, Status s, int code) {
NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onStatus: default"); NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onStatus: default");
} // onStatus } // onStatus
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#endif /* CONFIG_BT_ENABLED */ #endif /* CONFIG_BT_ENABLED */

View file

@ -3,7 +3,7 @@
* *
* Created: on March 3, 2020 * Created: on March 3, 2020
* Author H2zero * Author H2zero
* *
* Originally: * Originally:
* BLECharacteristic.h * BLECharacteristic.h
* *
@ -16,6 +16,9 @@
#include "sdkconfig.h" #include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED) #if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h"
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#include "host/ble_hs.h" #include "host/ble_hs.h"
/**** FIX COMPILATION ****/ /**** FIX COMPILATION ****/
#undef min #undef min
@ -23,10 +26,10 @@
/**************************/ /**************************/
typedef enum { typedef enum {
READ = BLE_GATT_CHR_F_READ, READ = BLE_GATT_CHR_F_READ,
READ_ENC = BLE_GATT_CHR_F_READ_ENC, READ_ENC = BLE_GATT_CHR_F_READ_ENC,
READ_AUTHEN = BLE_GATT_CHR_F_READ_AUTHEN, READ_AUTHEN = BLE_GATT_CHR_F_READ_AUTHEN,
READ_AUTHOR = BLE_GATT_CHR_F_READ_AUTHOR, READ_AUTHOR = BLE_GATT_CHR_F_READ_AUTHOR,
WRITE = BLE_GATT_CHR_F_WRITE, WRITE = BLE_GATT_CHR_F_WRITE,
WRITE_NR = BLE_GATT_CHR_F_WRITE_NO_RSP, WRITE_NR = BLE_GATT_CHR_F_WRITE_NO_RSP,
WRITE_ENC = BLE_GATT_CHR_F_WRITE_ENC, WRITE_ENC = BLE_GATT_CHR_F_WRITE_ENC,
@ -57,21 +60,21 @@ class NimBLECharacteristicCallbacks;
*/ */
class NimBLEDescriptorMap { class NimBLEDescriptorMap {
public: public:
void setByUUID(const char* uuid, NimBLEDescriptor* pDescriptor); void setByUUID(const char* uuid, NimBLEDescriptor* pDescriptor);
void setByUUID(const NimBLEUUID &uuid, NimBLEDescriptor* pDescriptor); void setByUUID(const NimBLEUUID &uuid, NimBLEDescriptor* pDescriptor);
// void setByHandle(uint16_t handle, NimBLEDescriptor* pDescriptor); // void setByHandle(uint16_t handle, NimBLEDescriptor* pDescriptor);
NimBLEDescriptor* getByUUID(const char* uuid); NimBLEDescriptor* getByUUID(const char* uuid);
NimBLEDescriptor* getByUUID(const NimBLEUUID &uuid); NimBLEDescriptor* getByUUID(const NimBLEUUID &uuid);
// NimBLEDescriptor* getByHandle(uint16_t handle); // NimBLEDescriptor* getByHandle(uint16_t handle);
std::string toString(); std::string toString();
NimBLEDescriptor* getFirst(); NimBLEDescriptor* getFirst();
NimBLEDescriptor* getNext(); NimBLEDescriptor* getNext();
uint8_t getSize(); uint8_t getSize();
private: private:
std::map<NimBLEDescriptor*, std::string> m_uuidMap; std::map<NimBLEDescriptor*, std::string> m_uuidMap;
// std::map<uint16_t, BLEDescriptor*> m_handleMap; // std::map<uint16_t, BLEDescriptor*> m_handleMap;
std::map<NimBLEDescriptor*, std::string>::iterator m_iterator; std::map<NimBLEDescriptor*, std::string>::iterator m_iterator;
}; };
@ -83,85 +86,85 @@ private:
*/ */
class NimBLECharacteristic { class NimBLECharacteristic {
public: public:
NimBLEDescriptor* createDescriptor(const char* uuid, NimBLEDescriptor* createDescriptor(const char* uuid,
uint32_t properties = NIMBLE_PROPERTY::READ | uint32_t properties = NIMBLE_PROPERTY::READ |
NIMBLE_PROPERTY::WRITE, NIMBLE_PROPERTY::WRITE,
uint16_t max_len = 100); uint16_t max_len = 100);
NimBLEDescriptor* createDescriptor(const NimBLEUUID &uuid, NimBLEDescriptor* createDescriptor(const NimBLEUUID &uuid,
uint32_t properties = NIMBLE_PROPERTY::READ | uint32_t properties = NIMBLE_PROPERTY::READ |
NIMBLE_PROPERTY::WRITE, NIMBLE_PROPERTY::WRITE,
uint16_t max_len = 100); uint16_t max_len = 100);
NimBLEDescriptor* getDescriptorByUUID(const char* descriptorUUID);
NimBLEDescriptor* getDescriptorByUUID(const NimBLEUUID &descriptorUUID);
NimBLEUUID getUUID();
std::string getValue();
uint8_t* getData();
size_t getDataLength();
void indicate(); NimBLEDescriptor* getDescriptorByUUID(const char* descriptorUUID);
void notify(bool is_notification = true); NimBLEDescriptor* getDescriptorByUUID(const NimBLEUUID &descriptorUUID);
void setCallbacks(NimBLECharacteristicCallbacks* pCallbacks); NimBLEUUID getUUID();
std::string getValue();
uint8_t* getData();
size_t getDataLength();
void indicate();
void notify(bool is_notification = true);
void setCallbacks(NimBLECharacteristicCallbacks* pCallbacks);
// Backward Compatibility - to be removed // Backward Compatibility - to be removed
void setBroadcastProperty(bool value); void setBroadcastProperty(bool value);
void setIndicateProperty(bool value); void setIndicateProperty(bool value);
void setNotifyProperty(bool value); void setNotifyProperty(bool value);
void setReadProperty(bool value); void setReadProperty(bool value);
void setWriteProperty(bool value); void setWriteProperty(bool value);
void setWriteNoResponseProperty(bool value); void setWriteNoResponseProperty(bool value);
////////////////////////////////////////////////////// //////////////////////////////////////////////////////
void setValue(const uint8_t* data, size_t size); void setValue(const uint8_t* data, size_t size);
void setValue(const std::string &value); void setValue(const std::string &value);
void setValue(uint16_t& data16); void setValue(uint16_t& data16);
void setValue(uint32_t& data32); void setValue(uint32_t& data32);
void setValue(int& data32); void setValue(int& data32);
void setValue(float& data32); void setValue(float& data32);
void setValue(double& data64); void setValue(double& data64);
std::string toString(); std::string toString();
uint16_t getHandle(); uint16_t getHandle();
// void setAccessPermissions(uint16_t perm); // void setAccessPermissions(uint16_t perm);
// Backward Compatibility - to be removed // Backward Compatibility - to be removed
/* static const uint32_t PROPERTY_READ = 1<<0; /* static const uint32_t PROPERTY_READ = 1<<0;
static const uint32_t PROPERTY_WRITE = 1<<1; static const uint32_t PROPERTY_WRITE = 1<<1;
static const uint32_t PROPERTY_NOTIFY = 1<<2; static const uint32_t PROPERTY_NOTIFY = 1<<2;
static const uint32_t PROPERTY_BROADCAST = 1<<3; static const uint32_t PROPERTY_BROADCAST = 1<<3;
static const uint32_t PROPERTY_INDICATE = 1<<4; static const uint32_t PROPERTY_INDICATE = 1<<4;
static const uint32_t PROPERTY_WRITE_NR = 1<<5; static const uint32_t PROPERTY_WRITE_NR = 1<<5;
*/ */
////////////////////////////////////////////////////// //////////////////////////////////////////////////////
private: private:
friend class NimBLEServer; friend class NimBLEServer;
friend class NimBLEService; friend class NimBLEService;
// friend class NimBLEDescriptor; // friend class NimBLEDescriptor;
// friend class NimBLECharacteristicMap; // friend class NimBLECharacteristicMap;
NimBLECharacteristic(const char* uuid, uint16_t properties = NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE, NimBLECharacteristic(const char* uuid, uint16_t properties = NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE,
NimBLEService* pService = nullptr); NimBLEService* pService = nullptr);
NimBLECharacteristic(const NimBLEUUID &uuid, uint16_t properties = NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE, NimBLECharacteristic(const NimBLEUUID &uuid, uint16_t properties = NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE,
NimBLEService* pService = nullptr); NimBLEService* pService = nullptr);
virtual ~NimBLECharacteristic(); virtual ~NimBLECharacteristic();
NimBLEUUID m_uuid; NimBLEUUID m_uuid;
NimBLEDescriptorMap m_descriptorMap; NimBLEDescriptorMap m_descriptorMap;
uint16_t m_handle; uint16_t m_handle;
uint16_t m_properties; uint16_t m_properties;
NimBLECharacteristicCallbacks* m_pCallbacks; NimBLECharacteristicCallbacks* m_pCallbacks;
NimBLEService* m_pService; NimBLEService* m_pService;
NimBLEValue m_value; NimBLEValue m_value;
// uint16_t m_permissions; // uint16_t m_permissions;
void addDescriptor(NimBLEDescriptor* pDescriptor); void addDescriptor(NimBLEDescriptor* pDescriptor);
NimBLEService* getService(); NimBLEService* getService();
uint8_t getProperties(); uint8_t getProperties();
void setSubscribe(struct ble_gap_event *event); void setSubscribe(struct ble_gap_event *event);
static int handleGapEvent(uint16_t conn_handle, uint16_t attr_handle, static int handleGapEvent(uint16_t conn_handle, uint16_t attr_handle,
struct ble_gatt_access_ctxt *ctxt, void *arg); struct ble_gatt_access_ctxt *ctxt, void *arg);
FreeRTOS::Semaphore m_semaphoreConfEvt = FreeRTOS::Semaphore("ConfEvt"); FreeRTOS::Semaphore m_semaphoreConfEvt = FreeRTOS::Semaphore("ConfEvt");
}; // NimBLECharacteristic }; // NimBLECharacteristic
@ -175,21 +178,23 @@ private:
class NimBLECharacteristicCallbacks { class NimBLECharacteristicCallbacks {
public: public:
typedef enum { typedef enum {
SUCCESS_INDICATE, SUCCESS_INDICATE,
SUCCESS_NOTIFY, SUCCESS_NOTIFY,
ERROR_INDICATE_DISABLED, ERROR_INDICATE_DISABLED,
ERROR_NOTIFY_DISABLED, ERROR_NOTIFY_DISABLED,
ERROR_GATT, ERROR_GATT,
ERROR_NO_CLIENT, ERROR_NO_CLIENT,
ERROR_INDICATE_TIMEOUT, ERROR_INDICATE_TIMEOUT,
ERROR_INDICATE_FAILURE ERROR_INDICATE_FAILURE
}Status; }Status;
virtual ~NimBLECharacteristicCallbacks(); virtual ~NimBLECharacteristicCallbacks();
virtual void onRead(NimBLECharacteristic* pCharacteristic); virtual void onRead(NimBLECharacteristic* pCharacteristic);
virtual void onWrite(NimBLECharacteristic* pCharacteristic); virtual void onWrite(NimBLECharacteristic* pCharacteristic);
virtual void onNotify(NimBLECharacteristic* pCharacteristic); virtual void onNotify(NimBLECharacteristic* pCharacteristic);
virtual void onStatus(NimBLECharacteristic* pCharacteristic, Status s, int code); virtual void onStatus(NimBLECharacteristic* pCharacteristic, Status s, int code);
}; };
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#endif /* CONFIG_BT_ENABLED */ #endif /* CONFIG_BT_ENABLED */
#endif /*MAIN_NIMBLECHARACTERISTIC_H_*/ #endif /*MAIN_NIMBLECHARACTERISTIC_H_*/

View file

@ -12,6 +12,9 @@
#include "sdkconfig.h" #include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED) #if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h"
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#include "NimBLEService.h" #include "NimBLEService.h"
#include "NimBLELog.h" #include "NimBLELog.h"
@ -20,9 +23,9 @@
* @brief Return the characteristic by handle. * @brief Return the characteristic by handle.
* @param [in] handle The handle to look up the characteristic. * @param [in] handle The handle to look up the characteristic.
* @return The characteristic. * @return The characteristic.
*/ */
NimBLECharacteristic* NimBLECharacteristicMap::getByHandle(uint16_t handle) { NimBLECharacteristic* NimBLECharacteristicMap::getByHandle(uint16_t handle) {
return m_handleMap.at(handle); return m_handleMap.at(handle);
} // getByHandle } // getByHandle
@ -42,20 +45,20 @@ NimBLECharacteristic* NimBLECharacteristicMap::getByUUID(const char* uuid) {
* @return The characteristic. * @return The characteristic.
*/ */
NimBLECharacteristic* NimBLECharacteristicMap::getByUUID(const NimBLEUUID &uuid) { NimBLECharacteristic* NimBLECharacteristicMap::getByUUID(const NimBLEUUID &uuid) {
for (auto &myPair : m_uuidMap) { for (auto &myPair : m_uuidMap) {
if (myPair.first->getUUID().equals(uuid)) { if (myPair.first->getUUID().equals(uuid)) {
return myPair.first; return myPair.first;
} }
} }
return nullptr; return nullptr;
} // getByUUID } // getByUUID
/** /**
* @brief Get the number of characteristics in the map. * @brief Get the number of characteristics in the map.
*/ */
uint8_t NimBLECharacteristicMap::getSize() { uint8_t NimBLECharacteristicMap::getSize() {
return (uint8_t)m_uuidMap.size(); return (uint8_t)m_uuidMap.size();
} // getSize } // getSize
/** /**
@ -63,11 +66,11 @@ uint8_t NimBLECharacteristicMap::getSize() {
* @return The first characteristic in the map. * @return The first characteristic in the map.
*/ */
NimBLECharacteristic* NimBLECharacteristicMap::getFirst() { NimBLECharacteristic* NimBLECharacteristicMap::getFirst() {
m_iterator = m_uuidMap.begin(); m_iterator = m_uuidMap.begin();
if (m_iterator == m_uuidMap.end()) return nullptr; if (m_iterator == m_uuidMap.end()) return nullptr;
NimBLECharacteristic* pRet = m_iterator->first; NimBLECharacteristic* pRet = m_iterator->first;
m_iterator++; m_iterator++;
return pRet; return pRet;
} // getFirst } // getFirst
@ -76,10 +79,10 @@ NimBLECharacteristic* NimBLECharacteristicMap::getFirst() {
* @return The next characteristic in the map. * @return The next characteristic in the map.
*/ */
NimBLECharacteristic* NimBLECharacteristicMap::getNext() { NimBLECharacteristic* NimBLECharacteristicMap::getNext() {
if (m_iterator == m_uuidMap.end()) return nullptr; if (m_iterator == m_uuidMap.end()) return nullptr;
NimBLECharacteristic* pRet = m_iterator->first; NimBLECharacteristic* pRet = m_iterator->first;
m_iterator++; m_iterator++;
return pRet; return pRet;
} // getNext } // getNext
@ -90,7 +93,7 @@ NimBLECharacteristic* NimBLECharacteristicMap::getNext() {
* @return N/A. * @return N/A.
*/ */
void NimBLECharacteristicMap::setByHandle(uint16_t handle, NimBLECharacteristic* characteristic) { void NimBLECharacteristicMap::setByHandle(uint16_t handle, NimBLECharacteristic* characteristic) {
m_handleMap.insert(std::pair<uint16_t, NimBLECharacteristic*>(handle, characteristic)); m_handleMap.insert(std::pair<uint16_t, NimBLECharacteristic*>(handle, characteristic));
} // setByHandle } // setByHandle
@ -101,7 +104,7 @@ void NimBLECharacteristicMap::setByHandle(uint16_t handle, NimBLECharacteristic*
* @return N/A. * @return N/A.
*/ */
void NimBLECharacteristicMap::setByUUID(NimBLECharacteristic* pCharacteristic, const NimBLEUUID &uuid) { void NimBLECharacteristicMap::setByUUID(NimBLECharacteristic* pCharacteristic, const NimBLEUUID &uuid) {
m_uuidMap.insert(std::pair<NimBLECharacteristic*, std::string>(pCharacteristic, uuid.toString())); m_uuidMap.insert(std::pair<NimBLECharacteristic*, std::string>(pCharacteristic, uuid.toString()));
} // setByUUID } // setByUUID
@ -110,19 +113,20 @@ void NimBLECharacteristicMap::setByUUID(NimBLECharacteristic* pCharacteristic, c
* @return A string representation of the characteristic map. * @return A string representation of the characteristic map.
*/ */
std::string NimBLECharacteristicMap::toString() { std::string NimBLECharacteristicMap::toString() {
std::string res; std::string res;
int count = 0; int count = 0;
char hex[5]; char hex[5];
for (auto &myPair: m_uuidMap) { for (auto &myPair: m_uuidMap) {
if (count > 0) {res += "\n";} if (count > 0) {res += "\n";}
snprintf(hex, sizeof(hex), "%04x", myPair.first->getHandle()); snprintf(hex, sizeof(hex), "%04x", myPair.first->getHandle());
count++; count++;
res += "handle: 0x"; res += "handle: 0x";
res += hex; res += hex;
res += ", uuid: " + myPair.first->getUUID().toString(); res += ", uuid: " + myPair.first->getUUID().toString();
} }
return res; return res;
} // toString } // toString
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#endif /* CONFIG_BT_ENABLED */ #endif /* CONFIG_BT_ENABLED */

View file

@ -3,17 +3,20 @@
* *
* Created: on Jan 26 2020 * Created: on Jan 26 2020
* Author H2zero * Author H2zero
* *
* Originally: * Originally:
* BLEClient.cpp * BLEClient.cpp
* *
* Created on: Mar 22, 2017 * Created on: Mar 22, 2017
* Author: kolban * Author: kolban
*/ */
#include "sdkconfig.h" #include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED) #if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h"
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
#include "NimBLEClient.h" #include "NimBLEClient.h"
#include "NimBLEUtils.h" #include "NimBLEUtils.h"
#include "NimBLEDevice.h" #include "NimBLEDevice.h"
@ -52,16 +55,16 @@ NimBLEClient::NimBLEClient()
m_conn_id = BLE_HS_CONN_HANDLE_NONE; m_conn_id = BLE_HS_CONN_HANDLE_NONE;
m_haveServices = false; m_haveServices = false;
m_isConnected = false; m_isConnected = false;
m_connectTimeout = 30000; m_connectTimeout = 30000;
m_pConnParams.scan_itvl = 16; // Scan interval in 0.625ms units (NimBLE Default) m_pConnParams.scan_itvl = 16; // Scan interval in 0.625ms units (NimBLE Default)
m_pConnParams.scan_window = 16; // Scan window in 0.625ms units (NimBLE Default) m_pConnParams.scan_window = 16; // Scan window in 0.625ms units (NimBLE Default)
m_pConnParams.itvl_min = BLE_GAP_INITIAL_CONN_ITVL_MIN; // min_int = 0x10*1.25ms = 20ms m_pConnParams.itvl_min = BLE_GAP_INITIAL_CONN_ITVL_MIN; // min_int = 0x10*1.25ms = 20ms
m_pConnParams.itvl_max = BLE_GAP_INITIAL_CONN_ITVL_MAX; // max_int = 0x20*1.25ms = 40ms m_pConnParams.itvl_max = BLE_GAP_INITIAL_CONN_ITVL_MAX; // max_int = 0x20*1.25ms = 40ms
m_pConnParams.latency = BLE_GAP_INITIAL_CONN_LATENCY; // number of packets allowed to skip (extends max interval) m_pConnParams.latency = BLE_GAP_INITIAL_CONN_LATENCY; // number of packets allowed to skip (extends max interval)
m_pConnParams.supervision_timeout = BLE_GAP_INITIAL_SUPERVISION_TIMEOUT; // timeout = 400*10ms = 4000ms m_pConnParams.supervision_timeout = BLE_GAP_INITIAL_SUPERVISION_TIMEOUT; // timeout = 400*10ms = 4000ms
m_pConnParams.min_ce_len = BLE_GAP_INITIAL_CONN_MIN_CE_LEN; // Minimum length of connection event in 0.625ms units m_pConnParams.min_ce_len = BLE_GAP_INITIAL_CONN_MIN_CE_LEN; // Minimum length of connection event in 0.625ms units
m_pConnParams.max_ce_len = BLE_GAP_INITIAL_CONN_MAX_CE_LEN; // Maximum length of connection event in 0.625ms units m_pConnParams.max_ce_len = BLE_GAP_INITIAL_CONN_MAX_CE_LEN; // Maximum length of connection event in 0.625ms units
} // NimBLEClient } // NimBLEClient
@ -69,11 +72,11 @@ NimBLEClient::NimBLEClient()
* @brief Destructor, private - only callable by NimBLEDevice::deleteClient * @brief Destructor, private - only callable by NimBLEDevice::deleteClient
* to ensure proper disconnect and removal from device list. * to ensure proper disconnect and removal from device list.
*/ */
NimBLEClient::~NimBLEClient() { NimBLEClient::~NimBLEClient() {
// We may have allocated service references associated with this client. // We may have allocated service references associated with this client.
// Before we are finished with the client, we must release resources. // Before we are finished with the client, we must release resources.
clearServices(); clearServices();
if(m_deleteCallbacks && m_pClientCallbacks != &defaultCallbacks) { if(m_deleteCallbacks && m_pClientCallbacks != &defaultCallbacks) {
delete m_pClientCallbacks; delete m_pClientCallbacks;
} }
@ -101,10 +104,10 @@ void NimBLEClient::clearServices() {
*/ */
/* /*
void NimBLEClient::onHostReset() { void NimBLEClient::onHostReset() {
} }
*/ */
/** /**
* Add overloaded function to ease connect to peer device with not public address * Add overloaded function to ease connect to peer device with not public address
*/ */
@ -122,12 +125,12 @@ bool NimBLEClient::connect(NimBLEAdvertisedDevice* device, bool refreshServices)
*/ */
bool NimBLEClient::connect(const NimBLEAddress &address, uint8_t type, bool refreshServices) { bool NimBLEClient::connect(const NimBLEAddress &address, uint8_t type, bool refreshServices) {
NIMBLE_LOGD(LOG_TAG, ">> connect(%s)", address.toString().c_str()); NIMBLE_LOGD(LOG_TAG, ">> connect(%s)", address.toString().c_str());
if(!NimBLEDevice::m_synced) { if(!NimBLEDevice::m_synced) {
NIMBLE_LOGC(LOG_TAG, "Host reset, wait for sync."); NIMBLE_LOGC(LOG_TAG, "Host reset, wait for sync.");
return false; return false;
} }
if(ble_gap_conn_active()) { if(ble_gap_conn_active()) {
NIMBLE_LOGE(LOG_TAG, "Connection in progress - must wait."); NIMBLE_LOGE(LOG_TAG, "Connection in progress - must wait.");
return false; return false;
@ -135,15 +138,15 @@ bool NimBLEClient::connect(const NimBLEAddress &address, uint8_t type, bool refr
int rc = 0; int rc = 0;
m_peerAddress = address; m_peerAddress = address;
ble_addr_t peerAddrt; ble_addr_t peerAddrt;
memcpy(&peerAddrt.val, address.getNative(),6); memcpy(&peerAddrt.val, address.getNative(),6);
peerAddrt.type = type; peerAddrt.type = type;
m_semaphoreOpenEvt.take("connect"); m_semaphoreOpenEvt.take("connect");
/** Try to connect the the advertiser. Allow 30 seconds (30000 ms) for /** Try to connect the the advertiser. Allow 30 seconds (30000 ms) for
* timeout (default value of m_connectTimeout). * timeout (default value of m_connectTimeout).
* Loop on BLE_HS_EBUSY if the scan hasn't stopped yet. * Loop on BLE_HS_EBUSY if the scan hasn't stopped yet.
*/ */
do{ do{
@ -153,21 +156,21 @@ bool NimBLEClient::connect(const NimBLEAddress &address, uint8_t type, bool refr
vTaskDelay(1); vTaskDelay(1);
} }
}while(rc == BLE_HS_EBUSY); }while(rc == BLE_HS_EBUSY);
if (rc != 0 && rc != BLE_HS_EDONE) { if (rc != 0 && rc != BLE_HS_EDONE) {
NIMBLE_LOGE(LOG_TAG, "Error: Failed to connect to device; addr_type=%d " NIMBLE_LOGE(LOG_TAG, "Error: Failed to connect to device; addr_type=%d "
"addr=%s, rc=%d; %s", "addr=%s, rc=%d; %s",
type, type,
m_peerAddress.toString().c_str(), m_peerAddress.toString().c_str(),
rc, NimBLEUtils::returnCodeToString(rc)); rc, NimBLEUtils::returnCodeToString(rc));
m_semaphoreOpenEvt.give(); m_semaphoreOpenEvt.give();
m_waitingToConnect = false; m_waitingToConnect = false;
return false; return false;
} }
m_waitingToConnect = true; m_waitingToConnect = true;
rc = m_semaphoreOpenEvt.wait("connect"); // Wait for the connection to complete. rc = m_semaphoreOpenEvt.wait("connect"); // Wait for the connection to complete.
if(rc != 0){ if(rc != 0){
@ -178,7 +181,7 @@ bool NimBLEClient::connect(const NimBLEAddress &address, uint8_t type, bool refr
NIMBLE_LOGD(LOG_TAG, "Refreshing Services for: (%s)", address.toString().c_str()); NIMBLE_LOGD(LOG_TAG, "Refreshing Services for: (%s)", address.toString().c_str());
clearServices(); clearServices();
} }
if (!m_haveServices) { if (!m_haveServices) {
if (!retrieveServices()) { if (!retrieveServices()) {
// error getting services, make sure we disconnect and release any resources before returning // error getting services, make sure we disconnect and release any resources before returning
@ -191,8 +194,8 @@ bool NimBLEClient::connect(const NimBLEAddress &address, uint8_t type, bool refr
} }
} }
m_pClientCallbacks->onConnect(this); m_pClientCallbacks->onConnect(this);
NIMBLE_LOGD(LOG_TAG, "<< connect()"); NIMBLE_LOGD(LOG_TAG, "<< connect()");
return true; return true;
} // connect } // connect
@ -204,23 +207,23 @@ bool NimBLEClient::connect(const NimBLEAddress &address, uint8_t type, bool refr
* @return True on success. * @return True on success.
*/ */
bool NimBLEClient::secureConnection() { bool NimBLEClient::secureConnection() {
m_semeaphoreSecEvt.take("secureConnection"); m_semeaphoreSecEvt.take("secureConnection");
int rc = NimBLEDevice::startSecurity(m_conn_id); int rc = NimBLEDevice::startSecurity(m_conn_id);
if(rc != 0){ if(rc != 0){
m_semeaphoreSecEvt.give(); m_semeaphoreSecEvt.give();
return false; return false;
} }
rc = m_semeaphoreSecEvt.wait("secureConnection"); rc = m_semeaphoreSecEvt.wait("secureConnection");
if(rc != 0){ if(rc != 0){
return false; return false;
} }
return true; return true;
} }
/** /**
* @brief Disconnect from the peer. * @brief Disconnect from the peer.
@ -240,7 +243,7 @@ int NimBLEClient::disconnect(uint8_t reason) {
// the device can be found again. // the device can be found again.
NimBLEDevice::removeIgnored(m_peerAddress); NimBLEDevice::removeIgnored(m_peerAddress);
} }
NIMBLE_LOGD(LOG_TAG, "<< disconnect()"); NIMBLE_LOGD(LOG_TAG, "<< disconnect()");
return rc; return rc;
} // disconnect } // disconnect
@ -250,23 +253,23 @@ int NimBLEClient::disconnect(uint8_t reason) {
* @brief Set the connection paramaters to use when connecting to a server. * @brief Set the connection paramaters to use when connecting to a server.
*/ */
void NimBLEClient::setConnectionParams(uint16_t minInterval, uint16_t maxInterval, void NimBLEClient::setConnectionParams(uint16_t minInterval, uint16_t maxInterval,
uint16_t latency, uint16_t timeout, uint16_t latency, uint16_t timeout,
uint16_t scanInterval, uint16_t scanWindow)/*, uint16_t scanInterval, uint16_t scanWindow)/*,
uint16_t minConnTime, uint16_t maxConnTime)*/ uint16_t minConnTime, uint16_t maxConnTime)*/
{ {
m_pConnParams.scan_itvl = scanInterval; // Scan interval in 0.625ms units m_pConnParams.scan_itvl = scanInterval; // Scan interval in 0.625ms units
m_pConnParams.scan_window = scanWindow; // Scan window in 0.625ms units m_pConnParams.scan_window = scanWindow; // Scan window in 0.625ms units
m_pConnParams.itvl_min = minInterval; // min_int = 0x10*1.25ms = 20ms m_pConnParams.itvl_min = minInterval; // min_int = 0x10*1.25ms = 20ms
m_pConnParams.itvl_max = maxInterval; // max_int = 0x20*1.25ms = 40ms m_pConnParams.itvl_max = maxInterval; // max_int = 0x20*1.25ms = 40ms
m_pConnParams.latency = latency; // number of packets allowed to skip (extends max interval) m_pConnParams.latency = latency; // number of packets allowed to skip (extends max interval)
m_pConnParams.supervision_timeout = timeout; // timeout = 400*10ms = 4000ms m_pConnParams.supervision_timeout = timeout; // timeout = 400*10ms = 4000ms
// These are not used by NimBLE at this time - Must leave at defaults // These are not used by NimBLE at this time - Must leave at defaults
//m_pConnParams->min_ce_len = minConnTime; // Minimum length of connection event in 0.625ms units //m_pConnParams->min_ce_len = minConnTime; // Minimum length of connection event in 0.625ms units
//m_pConnParams->max_ce_len = maxConnTime; // Maximum length of connection event in 0.625ms units //m_pConnParams->max_ce_len = maxConnTime; // Maximum length of connection event in 0.625ms units
int rc = NimBLEUtils::checkConnParams(&m_pConnParams); int rc = NimBLEUtils::checkConnParams(&m_pConnParams);
assert(rc == 0 && "Invalid Connection parameters"); assert(rc == 0 && "Invalid Connection parameters");
} }
@ -274,24 +277,24 @@ void NimBLEClient::setConnectionParams(uint16_t minInterval, uint16_t maxInterva
/** /**
* Update connection parameters can be called only after connection has been established * Update connection parameters can be called only after connection has been established
*/ */
void NimBLEClient::updateConnParams(uint16_t minInterval, uint16_t maxInterval, void NimBLEClient::updateConnParams(uint16_t minInterval, uint16_t maxInterval,
uint16_t latency, uint16_t timeout) uint16_t latency, uint16_t timeout)
{ {
ble_gap_upd_params params; ble_gap_upd_params params;
params.latency = latency; params.latency = latency;
params.itvl_max = maxInterval; params.itvl_max = maxInterval;
params.itvl_min = minInterval; params.itvl_min = minInterval;
params.supervision_timeout = timeout; params.supervision_timeout = timeout;
// These are not used by NimBLE at this time - Must leave at defaults // These are not used by NimBLE at this time - Must leave at defaults
params.min_ce_len = BLE_GAP_INITIAL_CONN_MIN_CE_LEN; params.min_ce_len = BLE_GAP_INITIAL_CONN_MIN_CE_LEN;
params.max_ce_len = BLE_GAP_INITIAL_CONN_MAX_CE_LEN; params.max_ce_len = BLE_GAP_INITIAL_CONN_MAX_CE_LEN;
int rc = ble_gap_update_params(m_conn_id, &params); int rc = ble_gap_update_params(m_conn_id, &params);
if(rc != 0) { if(rc != 0) {
NIMBLE_LOGE(LOG_TAG, "Update params error: %d, %s", NIMBLE_LOGE(LOG_TAG, "Update params error: %d, %s",
rc, NimBLEUtils::returnCodeToString(rc)); rc, NimBLEUtils::returnCodeToString(rc));
} }
} }
@ -331,15 +334,15 @@ int NimBLEClient::getRssi() {
NIMBLE_LOGE(LOG_TAG, "<< getRssi(): Not connected"); NIMBLE_LOGE(LOG_TAG, "<< getRssi(): Not connected");
return 0; return 0;
} }
int8_t rssiValue = 0; int8_t rssiValue = 0;
int rc = ble_gap_conn_rssi(m_conn_id, &rssiValue); int rc = ble_gap_conn_rssi(m_conn_id, &rssiValue);
if(rc != 0) { if(rc != 0) {
NIMBLE_LOGE(LOG_TAG, "Failed to read RSSI error code: %d, %s", NIMBLE_LOGE(LOG_TAG, "Failed to read RSSI error code: %d, %s",
rc, NimBLEUtils::returnCodeToString(rc)); rc, NimBLEUtils::returnCodeToString(rc));
return 0; return 0;
} }
return rssiValue; return rssiValue;
} // getRssi } // getRssi
@ -371,7 +374,7 @@ NimBLERemoteService* NimBLEClient::getService(const NimBLEUUID &uuid) {
NIMBLE_LOGD(LOG_TAG, "<< getService: found the service with uuid: %s", uuid.toString().c_str()); NIMBLE_LOGD(LOG_TAG, "<< getService: found the service with uuid: %s", uuid.toString().c_str());
return myPair.second; return myPair.second;
} }
} }
NIMBLE_LOGD(LOG_TAG, "<< getService: not found"); NIMBLE_LOGD(LOG_TAG, "<< getService: not found");
return nullptr; return nullptr;
} // getService } // getService
@ -379,7 +382,7 @@ NimBLERemoteService* NimBLEClient::getService(const NimBLEUUID &uuid) {
/** /**
* @Get a pointer to the map of found services. * @Get a pointer to the map of found services.
*/ */
std::map<std::string, NimBLERemoteService*>* NimBLEClient::getServices() { std::map<std::string, NimBLERemoteService*>* NimBLEClient::getServices() {
return &m_servicesMap; return &m_servicesMap;
} }
@ -391,7 +394,7 @@ std::map<std::string, NimBLERemoteService*>* NimBLEClient::getServices() {
* services and wait until we have received them all. * services and wait until we have received them all.
* We then ask for the characteristics for each service found and their desciptors. * We then ask for the characteristics for each service found and their desciptors.
* @return true on success otherwise false if an error occurred * @return true on success otherwise false if an error occurred
*/ */
bool NimBLEClient::retrieveServices() { bool NimBLEClient::retrieveServices() {
/** /**
* Design * Design
@ -399,25 +402,25 @@ bool NimBLEClient::retrieveServices() {
* We invoke ble_gattc_disc_all_svcs. This will request a list of the services exposed by the * We invoke ble_gattc_disc_all_svcs. This will request a list of the services exposed by the
* peer BLE partner to be returned in the callback function provided. * peer BLE partner to be returned in the callback function provided.
*/ */
NIMBLE_LOGD(LOG_TAG, ">> retrieveServices"); NIMBLE_LOGD(LOG_TAG, ">> retrieveServices");
if(!m_isConnected){ if(!m_isConnected){
NIMBLE_LOGE(LOG_TAG, "Disconnected, could not retrieve services -aborting"); NIMBLE_LOGE(LOG_TAG, "Disconnected, could not retrieve services -aborting");
return false; return false;
} }
m_semaphoreSearchCmplEvt.take("retrieveServices"); m_semaphoreSearchCmplEvt.take("retrieveServices");
int rc = ble_gattc_disc_all_svcs(m_conn_id, NimBLEClient::serviceDiscoveredCB, this); int rc = ble_gattc_disc_all_svcs(m_conn_id, NimBLEClient::serviceDiscoveredCB, this);
if (rc != 0) { if (rc != 0) {
NIMBLE_LOGE(LOG_TAG, "ble_gattc_disc_all_svcs: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc)); NIMBLE_LOGE(LOG_TAG, "ble_gattc_disc_all_svcs: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
m_haveServices = false; m_haveServices = false;
m_semaphoreSearchCmplEvt.give(); m_semaphoreSearchCmplEvt.give();
return false; return false;
} }
// wait until we have all the services // wait until we have all the services
// If sucessful, remember that we now have services. // If sucessful, remember that we now have services.
m_haveServices = (m_semaphoreSearchCmplEvt.wait("retrieveServices") == 0); m_haveServices = (m_semaphoreSearchCmplEvt.wait("retrieveServices") == 0);
@ -428,7 +431,7 @@ bool NimBLEClient::retrieveServices() {
return false; return false;
} }
} }
NIMBLE_LOGD(LOG_TAG, "<< retrieveServices"); NIMBLE_LOGD(LOG_TAG, "<< retrieveServices");
return true; return true;
} }
@ -440,14 +443,14 @@ bool NimBLEClient::retrieveServices() {
/** /**
* @brief STATIC Callback for the service discovery API function. * @brief STATIC Callback for the service discovery API function.
* When a service is found or there is none left or there was an error * When a service is found or there is none left or there was an error
* the API will call this and report findings. * the API will call this and report findings.
*/ */
int NimBLEClient::serviceDiscoveredCB( int NimBLEClient::serviceDiscoveredCB(
uint16_t conn_handle, uint16_t conn_handle,
const struct ble_gatt_error *error, const struct ble_gatt_error *error,
const struct ble_gatt_svc *service, void *arg) const struct ble_gatt_svc *service, void *arg)
{ {
NIMBLE_LOGD(LOG_TAG,"Service Discovered >> status: %d handle: %d", error->status, conn_handle); NIMBLE_LOGD(LOG_TAG,"Service Discovered >> status: %d handle: %d", error->status, conn_handle);
NimBLEClient *peer = (NimBLEClient*)arg; NimBLEClient *peer = (NimBLEClient*)arg;
@ -466,7 +469,7 @@ int NimBLEClient::serviceDiscoveredCB(
break; break;
} }
case BLE_HS_EDONE:{ case BLE_HS_EDONE:{
// All services discovered; start discovering characteristics. // All services discovered; start discovering characteristics.
//NIMBLE_LOGD(LOG_TAG,"Giving search semaphore - completed"); //NIMBLE_LOGD(LOG_TAG,"Giving search semaphore - completed");
peer->m_semaphoreSearchCmplEvt.give(0); peer->m_semaphoreSearchCmplEvt.give(0);
@ -481,7 +484,7 @@ int NimBLEClient::serviceDiscoveredCB(
if (rc != 0) { if (rc != 0) {
// pass non-zero to semaphore on error to indicate an error finding services // pass non-zero to semaphore on error to indicate an error finding services
peer->m_semaphoreSearchCmplEvt.give(1); peer->m_semaphoreSearchCmplEvt.give(1);
} }
NIMBLE_LOGD(LOG_TAG,"<< Service Discovered. status: %d", rc); NIMBLE_LOGD(LOG_TAG,"<< Service Discovered. status: %d", rc);
return rc; return rc;
@ -496,10 +499,10 @@ int NimBLEClient::serviceDiscoveredCB(
*/ */
std::string NimBLEClient::getValue(const NimBLEUUID &serviceUUID, const NimBLEUUID &characteristicUUID) { std::string NimBLEClient::getValue(const NimBLEUUID &serviceUUID, const NimBLEUUID &characteristicUUID) {
NIMBLE_LOGD(LOG_TAG, ">> getValue: serviceUUID: %s, characteristicUUID: %s", serviceUUID.toString().c_str(), characteristicUUID.toString().c_str()); NIMBLE_LOGD(LOG_TAG, ">> getValue: serviceUUID: %s, characteristicUUID: %s", serviceUUID.toString().c_str(), characteristicUUID.toString().c_str());
std::string ret = ""; std::string ret = "";
NimBLERemoteService* pService = getService(serviceUUID); NimBLERemoteService* pService = getService(serviceUUID);
if(pService != nullptr) { if(pService != nullptr) {
NimBLERemoteCharacteristic* pChar = pService->getCharacteristic(characteristicUUID); NimBLERemoteCharacteristic* pChar = pService->getCharacteristic(characteristicUUID);
if(pChar != nullptr) { if(pChar != nullptr) {
@ -520,17 +523,17 @@ std::string NimBLEClient::getValue(const NimBLEUUID &serviceUUID, const NimBLEUU
*/ */
bool NimBLEClient::setValue(const NimBLEUUID &serviceUUID, const NimBLEUUID &characteristicUUID, const std::string &value) { bool NimBLEClient::setValue(const NimBLEUUID &serviceUUID, const NimBLEUUID &characteristicUUID, const std::string &value) {
NIMBLE_LOGD(LOG_TAG, ">> setValue: serviceUUID: %s, characteristicUUID: %s", serviceUUID.toString().c_str(), characteristicUUID.toString().c_str()); NIMBLE_LOGD(LOG_TAG, ">> setValue: serviceUUID: %s, characteristicUUID: %s", serviceUUID.toString().c_str(), characteristicUUID.toString().c_str());
bool ret = false; bool ret = false;
NimBLERemoteService* pService = getService(serviceUUID); NimBLERemoteService* pService = getService(serviceUUID);
if(pService != nullptr) { if(pService != nullptr) {
NimBLERemoteCharacteristic* pChar = pService->getCharacteristic(characteristicUUID); NimBLERemoteCharacteristic* pChar = pService->getCharacteristic(characteristicUUID);
if(pChar != nullptr) { if(pChar != nullptr) {
ret = pChar->writeValue(value); ret = pChar->writeValue(value);
} }
} }
NIMBLE_LOGD(LOG_TAG, "<< setValue"); NIMBLE_LOGD(LOG_TAG, "<< setValue");
return ret; return ret;
} // setValue } // setValue
@ -552,8 +555,8 @@ uint16_t NimBLEClient::getMTU() {
* @param [in] arg = pointer to the client instance * @param [in] arg = pointer to the client instance
*/ */
/*STATIC*/ int NimBLEClient::handleGapEvent(struct ble_gap_event *event, void *arg) { /*STATIC*/ int NimBLEClient::handleGapEvent(struct ble_gap_event *event, void *arg) {
NimBLEClient* client = (NimBLEClient*)arg; NimBLEClient* client = (NimBLEClient*)arg;
//struct ble_gap_conn_desc desc; //struct ble_gap_conn_desc desc;
//struct ble_hs_adv_fields fields; //struct ble_hs_adv_fields fields;
int rc; int rc;
@ -566,22 +569,22 @@ uint16_t NimBLEClient::getMTU() {
case BLE_GAP_EVENT_DISCONNECT: { case BLE_GAP_EVENT_DISCONNECT: {
if(!client->m_isConnected) if(!client->m_isConnected)
return 0; return 0;
if(client->m_conn_id != event->disconnect.conn.conn_handle) if(client->m_conn_id != event->disconnect.conn.conn_handle)
return 0; return 0;
client->m_isConnected = false; client->m_isConnected = false;
client->m_waitingToConnect=false; client->m_waitingToConnect=false;
// Remove the device from ignore list so we will scan it again // Remove the device from ignore list so we will scan it again
NimBLEDevice::removeIgnored(client->m_peerAddress); NimBLEDevice::removeIgnored(client->m_peerAddress);
NIMBLE_LOGI(LOG_TAG, "disconnect; reason=%d, %s", event->disconnect.reason, NIMBLE_LOGI(LOG_TAG, "disconnect; reason=%d, %s", event->disconnect.reason,
NimBLEUtils::returnCodeToString(event->disconnect.reason)); NimBLEUtils::returnCodeToString(event->disconnect.reason));
//print_conn_desc(&event->disconnect.conn); //print_conn_desc(&event->disconnect.conn);
//MODLOG_DFLT(INFO, "\n"); //MODLOG_DFLT(INFO, "\n");
// If Host reset tell the device now before returning to prevent // If Host reset tell the device now before returning to prevent
// any errors caused by calling host functions before resyncing. // any errors caused by calling host functions before resyncing.
switch(event->disconnect.reason) { switch(event->disconnect.reason) {
case BLE_HS_ETIMEOUT_HCI: case BLE_HS_ETIMEOUT_HCI:
@ -591,19 +594,19 @@ uint16_t NimBLEClient::getMTU() {
NIMBLE_LOGC(LOG_TAG, "Disconnect - host reset, rc=%d", event->disconnect.reason); NIMBLE_LOGC(LOG_TAG, "Disconnect - host reset, rc=%d", event->disconnect.reason);
NimBLEDevice::onReset(event->disconnect.reason); NimBLEDevice::onReset(event->disconnect.reason);
break; break;
default: default:
break; break;
} }
//client->m_conn_id = BLE_HS_CONN_HANDLE_NONE; //client->m_conn_id = BLE_HS_CONN_HANDLE_NONE;
// Indicate a non-success return value to any semaphores waiting // Indicate a non-success return value to any semaphores waiting
client->m_semaphoreOpenEvt.give(1); client->m_semaphoreOpenEvt.give(1);
client->m_semaphoreSearchCmplEvt.give(1); client->m_semaphoreSearchCmplEvt.give(1);
client->m_semeaphoreSecEvt.give(1); client->m_semeaphoreSecEvt.give(1);
client->m_pClientCallbacks->onDisconnect(client); client->m_pClientCallbacks->onDisconnect(client);
return 0; return 0;
} // BLE_GAP_EVENT_DISCONNECT } // BLE_GAP_EVENT_DISCONNECT
@ -611,26 +614,26 @@ uint16_t NimBLEClient::getMTU() {
if(!client->m_waitingToConnect) if(!client->m_waitingToConnect)
return 0; return 0;
//if(client->m_conn_id != BLE_HS_CONN_HANDLE_NONE) //if(client->m_conn_id != BLE_HS_CONN_HANDLE_NONE)
// return 0; // return 0;
client->m_waitingToConnect=false; client->m_waitingToConnect=false;
if (event->connect.status == 0) { if (event->connect.status == 0) {
client->m_isConnected = true; client->m_isConnected = true;
NIMBLE_LOGD(LOG_TAG, "Connection established"); NIMBLE_LOGD(LOG_TAG, "Connection established");
client->m_conn_id = event->connect.conn_handle; client->m_conn_id = event->connect.conn_handle;
// rc = ble_gap_conn_find(event->connect.conn_handle, &desc); // rc = ble_gap_conn_find(event->connect.conn_handle, &desc);
// assert(rc == 0); // assert(rc == 0);
// print_conn_desc(&desc); // print_conn_desc(&desc);
// MODLOG_DFLT(INFO, "\n"); // MODLOG_DFLT(INFO, "\n");
// In the case of a multiconnecting device we ignore this device when // In the case of a multiconnecting device we ignore this device when
// scanning since we are already connected to it // scanning since we are already connected to it
NimBLEDevice::addIgnored(client->m_peerAddress); NimBLEDevice::addIgnored(client->m_peerAddress);
@ -638,9 +641,9 @@ uint16_t NimBLEClient::getMTU() {
if(rc != 0) { if(rc != 0) {
NIMBLE_LOGE(LOG_TAG, "ble_gattc_exchange_mtu: rc=%d %s",rc, NIMBLE_LOGE(LOG_TAG, "ble_gattc_exchange_mtu: rc=%d %s",rc,
NimBLEUtils::returnCodeToString(rc)); NimBLEUtils::returnCodeToString(rc));
// if error getting mtu indicate a connection error. // if error getting mtu indicate a connection error.
client->m_semaphoreOpenEvt.give(rc); client->m_semaphoreOpenEvt.give(rc);
} }
} else { } else {
// Connection attempt failed // Connection attempt failed
NIMBLE_LOGE(LOG_TAG, "Error: Connection failed; status=%d %s", NIMBLE_LOGE(LOG_TAG, "Error: Connection failed; status=%d %s",
@ -654,11 +657,11 @@ uint16_t NimBLEClient::getMTU() {
case BLE_GAP_EVENT_NOTIFY_RX: { case BLE_GAP_EVENT_NOTIFY_RX: {
if(client->m_conn_id != event->notify_rx.conn_handle) if(client->m_conn_id != event->notify_rx.conn_handle)
return 0; return 0;
NIMBLE_LOGD(LOG_TAG, "Notify Recieved for handle: %d",event->notify_rx.attr_handle); NIMBLE_LOGD(LOG_TAG, "Notify Recieved for handle: %d",event->notify_rx.attr_handle);
if(!client->m_haveServices) if(!client->m_haveServices)
return 0; return 0;
for(auto &sPair : client->m_servicesMap){ for(auto &sPair : client->m_servicesMap){
// Dont waste cycles searching services without this handle in their range // Dont waste cycles searching services without this handle in their range
if(sPair.second->getEndHandle() < event->notify_rx.attr_handle) { if(sPair.second->getEndHandle() < event->notify_rx.attr_handle) {
@ -669,20 +672,20 @@ uint16_t NimBLEClient::getMTU() {
auto characteristic = cMap->find(event->notify_rx.attr_handle); auto characteristic = cMap->find(event->notify_rx.attr_handle);
if(characteristic != cMap->end()) { if(characteristic != cMap->end()) {
NIMBLE_LOGD(LOG_TAG, "Got Notification for characteristic %s", characteristic->second->toString().c_str()); NIMBLE_LOGD(LOG_TAG, "Got Notification for characteristic %s", characteristic->second->toString().c_str());
if (characteristic->second->m_notifyCallback != nullptr) { if (characteristic->second->m_notifyCallback != nullptr) {
NIMBLE_LOGD(LOG_TAG, "Invoking callback for notification on characteristic %s", characteristic->second->toString().c_str()); NIMBLE_LOGD(LOG_TAG, "Invoking callback for notification on characteristic %s", characteristic->second->toString().c_str());
characteristic->second->m_notifyCallback(characteristic->second, event->notify_rx.om->om_data, event->notify_rx.om->om_len, !event->notify_rx.indication); characteristic->second->m_notifyCallback(characteristic->second, event->notify_rx.om->om_data, event->notify_rx.om->om_len, !event->notify_rx.indication);
} }
break; break;
} }
} }
return 0; return 0;
} // BLE_GAP_EVENT_NOTIFY_RX } // BLE_GAP_EVENT_NOTIFY_RX
case BLE_GAP_EVENT_CONN_UPDATE_REQ: case BLE_GAP_EVENT_CONN_UPDATE_REQ:
case BLE_GAP_EVENT_L2CAP_UPDATE_REQ: { case BLE_GAP_EVENT_L2CAP_UPDATE_REQ: {
if(client->m_conn_id != event->conn_update_req.conn_handle){ if(client->m_conn_id != event->conn_update_req.conn_handle){
return 0; //BLE_HS_ENOTCONN BLE_ATT_ERR_INVALID_HANDLE return 0; //BLE_HS_ENOTCONN BLE_ATT_ERR_INVALID_HANDLE
@ -696,7 +699,7 @@ uint16_t NimBLEClient::getMTU() {
rc = client->m_pClientCallbacks->onConnParamsUpdateRequest(client, rc = client->m_pClientCallbacks->onConnParamsUpdateRequest(client,
event->conn_update_req.peer_params) ? 0 : BLE_ERR_CONN_PARMS; event->conn_update_req.peer_params) ? 0 : BLE_ERR_CONN_PARMS;
if(!rc && event->type == BLE_GAP_EVENT_CONN_UPDATE_REQ ) { if(!rc && event->type == BLE_GAP_EVENT_CONN_UPDATE_REQ ) {
event->conn_update_req.self_params->itvl_min = client->m_pConnParams.itvl_min; event->conn_update_req.self_params->itvl_min = client->m_pConnParams.itvl_min;
@ -708,7 +711,7 @@ uint16_t NimBLEClient::getMTU() {
NIMBLE_LOGD(LOG_TAG, "%s peer params", (rc == 0) ? "Accepted" : "Rejected"); NIMBLE_LOGD(LOG_TAG, "%s peer params", (rc == 0) ? "Accepted" : "Rejected");
return rc; return rc;
} // BLE_GAP_EVENT_CONN_UPDATE_REQ, BLE_GAP_EVENT_L2CAP_UPDATE_REQ } // BLE_GAP_EVENT_CONN_UPDATE_REQ, BLE_GAP_EVENT_L2CAP_UPDATE_REQ
case BLE_GAP_EVENT_CONN_UPDATE: { case BLE_GAP_EVENT_CONN_UPDATE: {
if(client->m_conn_id != event->conn_update.conn_handle){ if(client->m_conn_id != event->conn_update.conn_handle){
return 0; //BLE_HS_ENOTCONN BLE_ATT_ERR_INVALID_HANDLE return 0; //BLE_HS_ENOTCONN BLE_ATT_ERR_INVALID_HANDLE
@ -720,28 +723,28 @@ uint16_t NimBLEClient::getMTU() {
} }
return 0; return 0;
} // BLE_GAP_EVENT_CONN_UPDATE } // BLE_GAP_EVENT_CONN_UPDATE
case BLE_GAP_EVENT_ENC_CHANGE: { case BLE_GAP_EVENT_ENC_CHANGE: {
if(client->m_conn_id != event->enc_change.conn_handle){ if(client->m_conn_id != event->enc_change.conn_handle){
return 0; //BLE_HS_ENOTCONN BLE_ATT_ERR_INVALID_HANDLE return 0; //BLE_HS_ENOTCONN BLE_ATT_ERR_INVALID_HANDLE
} }
if(event->enc_change.status == 0) { if(event->enc_change.status == 0) {
struct ble_gap_conn_desc desc; struct ble_gap_conn_desc desc;
rc = ble_gap_conn_find(event->conn_update.conn_handle, &desc); rc = ble_gap_conn_find(event->conn_update.conn_handle, &desc);
assert(rc == 0); assert(rc == 0);
if(NimBLEDevice::m_securityCallbacks != nullptr) { if(NimBLEDevice::m_securityCallbacks != nullptr) {
NimBLEDevice::m_securityCallbacks->onAuthenticationComplete(&desc); NimBLEDevice::m_securityCallbacks->onAuthenticationComplete(&desc);
} else { } else {
client->m_pClientCallbacks->onAuthenticationComplete(&desc); client->m_pClientCallbacks->onAuthenticationComplete(&desc);
} }
} }
client->m_semeaphoreSecEvt.give(event->enc_change.status); client->m_semeaphoreSecEvt.give(event->enc_change.status);
return 0; return 0;
} //BLE_GAP_EVENT_ENC_CHANGE } //BLE_GAP_EVENT_ENC_CHANGE
case BLE_GAP_EVENT_MTU: { case BLE_GAP_EVENT_MTU: {
if(client->m_conn_id != event->mtu.conn_handle){ if(client->m_conn_id != event->mtu.conn_handle){
return 0; //BLE_HS_ENOTCONN BLE_ATT_ERR_INVALID_HANDLE return 0; //BLE_HS_ENOTCONN BLE_ATT_ERR_INVALID_HANDLE
@ -749,15 +752,15 @@ uint16_t NimBLEClient::getMTU() {
NIMBLE_LOGI(LOG_TAG, "mtu update event; conn_handle=%d mtu=%d", NIMBLE_LOGI(LOG_TAG, "mtu update event; conn_handle=%d mtu=%d",
event->mtu.conn_handle, event->mtu.conn_handle,
event->mtu.value); event->mtu.value);
client->m_semaphoreOpenEvt.give(0); client->m_semaphoreOpenEvt.give(0);
//client->m_mtu = event->mtu.value; //client->m_mtu = event->mtu.value;
return 0; return 0;
} // BLE_GAP_EVENT_MTU } // BLE_GAP_EVENT_MTU
case BLE_GAP_EVENT_PASSKEY_ACTION: { case BLE_GAP_EVENT_PASSKEY_ACTION: {
struct ble_sm_io pkey = {0}; struct ble_sm_io pkey = {0};
if(client->m_conn_id != event->passkey.conn_handle) if(client->m_conn_id != event->passkey.conn_handle)
return 0; return 0;
if (event->passkey.params.action == BLE_SM_IOACT_DISP) { if (event->passkey.params.action == BLE_SM_IOACT_DISP) {
@ -765,7 +768,7 @@ uint16_t NimBLEClient::getMTU() {
pkey.passkey = NimBLEDevice::m_passkey; // This is the passkey to be entered on peer pkey.passkey = NimBLEDevice::m_passkey; // This is the passkey to be entered on peer
rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey); rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey);
NIMBLE_LOGD(LOG_TAG, "ble_sm_inject_io result: %d", rc); NIMBLE_LOGD(LOG_TAG, "ble_sm_inject_io result: %d", rc);
} else if (event->passkey.params.action == BLE_SM_IOACT_NUMCMP) { } else if (event->passkey.params.action == BLE_SM_IOACT_NUMCMP) {
NIMBLE_LOGD(LOG_TAG, "Passkey on device's display: %d", event->passkey.params.numcmp); NIMBLE_LOGD(LOG_TAG, "Passkey on device's display: %d", event->passkey.params.numcmp);
pkey.action = event->passkey.params.action; pkey.action = event->passkey.params.action;
@ -779,8 +782,8 @@ uint16_t NimBLEClient::getMTU() {
rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey); rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey);
NIMBLE_LOGD(LOG_TAG, "ble_sm_inject_io result: %d", rc); NIMBLE_LOGD(LOG_TAG, "ble_sm_inject_io result: %d", rc);
//TODO: Handle out of band pairing //TODO: Handle out of band pairing
} else if (event->passkey.params.action == BLE_SM_IOACT_OOB) { } else if (event->passkey.params.action == BLE_SM_IOACT_OOB) {
static uint8_t tem_oob[16] = {0}; static uint8_t tem_oob[16] = {0};
pkey.action = event->passkey.params.action; pkey.action = event->passkey.params.action;
@ -789,11 +792,11 @@ uint16_t NimBLEClient::getMTU() {
} }
rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey); rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey);
NIMBLE_LOGD(LOG_TAG, "ble_sm_inject_io result: %d", rc); NIMBLE_LOGD(LOG_TAG, "ble_sm_inject_io result: %d", rc);
//////// ////////
} else if (event->passkey.params.action == BLE_SM_IOACT_INPUT) { } else if (event->passkey.params.action == BLE_SM_IOACT_INPUT) {
NIMBLE_LOGD(LOG_TAG, "Enter the passkey"); NIMBLE_LOGD(LOG_TAG, "Enter the passkey");
pkey.action = event->passkey.params.action; pkey.action = event->passkey.params.action;
// Compatibility only - Do not use, should be removed the in future // Compatibility only - Do not use, should be removed the in future
if(NimBLEDevice::m_securityCallbacks != nullptr) { if(NimBLEDevice::m_securityCallbacks != nullptr) {
pkey.passkey = NimBLEDevice::m_securityCallbacks->onPassKeyRequest(); pkey.passkey = NimBLEDevice::m_securityCallbacks->onPassKeyRequest();
@ -804,14 +807,14 @@ uint16_t NimBLEClient::getMTU() {
rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey); rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey);
NIMBLE_LOGD(LOG_TAG, "ble_sm_inject_io result: %d", rc); NIMBLE_LOGD(LOG_TAG, "ble_sm_inject_io result: %d", rc);
} else if (event->passkey.params.action == BLE_SM_IOACT_NONE) { } else if (event->passkey.params.action == BLE_SM_IOACT_NONE) {
NIMBLE_LOGD(LOG_TAG, "No passkey action required"); NIMBLE_LOGD(LOG_TAG, "No passkey action required");
} }
return 0; return 0;
} // BLE_GAP_EVENT_PASSKEY_ACTION } // BLE_GAP_EVENT_PASSKEY_ACTION
default: { default: {
return 0; return 0;
} }
@ -833,10 +836,10 @@ bool NimBLEClient::isConnected() {
*/ */
void NimBLEClient::setClientCallbacks(NimBLEClientCallbacks* pClientCallbacks, bool deleteCallbacks) { void NimBLEClient::setClientCallbacks(NimBLEClientCallbacks* pClientCallbacks, bool deleteCallbacks) {
if (pClientCallbacks != nullptr){ if (pClientCallbacks != nullptr){
m_pClientCallbacks = pClientCallbacks; m_pClientCallbacks = pClientCallbacks;
} else { } else {
m_pClientCallbacks = &defaultCallbacks; m_pClientCallbacks = &defaultCallbacks;
} }
m_deleteCallbacks = deleteCallbacks; m_deleteCallbacks = deleteCallbacks;
} // setClientCallbacks } // setClientCallbacks
@ -865,7 +868,7 @@ void NimBLEClientCallbacks::onDisconnect(NimBLEClient* pClient) {
} }
bool NimBLEClientCallbacks::onConnParamsUpdateRequest(NimBLEClient* pClient, const ble_gap_upd_params* params) { bool NimBLEClientCallbacks::onConnParamsUpdateRequest(NimBLEClient* pClient, const ble_gap_upd_params* params) {
NIMBLE_LOGD("NimBLEClientCallbacks", "onConnParamsUpdateRequest: default"); NIMBLE_LOGD("NimBLEClientCallbacks", "onConnParamsUpdateRequest: default");
return true; return true;
} }
@ -890,4 +893,5 @@ bool NimBLEClientCallbacks::onConfirmPIN(uint32_t pin){
return true; return true;
} }
#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
#endif // CONFIG_BT_ENABLED #endif // CONFIG_BT_ENABLED

View file

@ -3,7 +3,7 @@
* *
* Created: on Jan 26 2020 * Created: on Jan 26 2020
* Author H2zero * Author H2zero
* *
* Originally: * Originally:
* BLEClient.h * BLEClient.h
* *
@ -14,8 +14,11 @@
#ifndef MAIN_NIMBLECLIENT_H_ #ifndef MAIN_NIMBLECLIENT_H_
#define MAIN_NIMBLECLIENT_H_ #define MAIN_NIMBLECLIENT_H_
#if defined(CONFIG_BT_ENABLED)
#include "sdkconfig.h" #include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h"
#if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
#include "NimBLEAddress.h" #include "NimBLEAddress.h"
#include "NimBLEAdvertisedDevice.h" #include "NimBLEAdvertisedDevice.h"
@ -50,13 +53,13 @@ public:
uint16_t getMTU(); uint16_t getMTU();
bool secureConnection(); bool secureConnection();
void setConnectTimeout(uint8_t timeout); void setConnectTimeout(uint8_t timeout);
void setConnectionParams(uint16_t minInterval, uint16_t maxInterval, void setConnectionParams(uint16_t minInterval, uint16_t maxInterval,
uint16_t latency, uint16_t timeout, uint16_t latency, uint16_t timeout,
uint16_t scanInterval=16, uint16_t scanWindow=16); // NimBLE default scan settings uint16_t scanInterval=16, uint16_t scanWindow=16); // NimBLE default scan settings
void updateConnParams(uint16_t minInterval, uint16_t maxInterval, void updateConnParams(uint16_t minInterval, uint16_t maxInterval,
uint16_t latency, uint16_t timeout); uint16_t latency, uint16_t timeout);
private: private:
NimBLEClient(); NimBLEClient();
~NimBLEClient(); ~NimBLEClient();
@ -75,7 +78,7 @@ private:
bool m_isConnected = false; // Are we currently connected. bool m_isConnected = false; // Are we currently connected.
bool m_waitingToConnect =false; bool m_waitingToConnect =false;
bool m_deleteCallbacks = true; bool m_deleteCallbacks = true;
int32_t m_connectTimeout; int32_t m_connectTimeout;
//uint16_t m_mtu = 23; //uint16_t m_mtu = 23;
NimBLEClientCallbacks* m_pClientCallbacks = nullptr; NimBLEClientCallbacks* m_pClientCallbacks = nullptr;
@ -85,12 +88,12 @@ private:
FreeRTOS::Semaphore m_semeaphoreSecEvt = FreeRTOS::Semaphore("Security"); FreeRTOS::Semaphore m_semeaphoreSecEvt = FreeRTOS::Semaphore("Security");
std::map<std::string, NimBLERemoteService*> m_servicesMap; std::map<std::string, NimBLERemoteService*> m_servicesMap;
private: private:
friend class NimBLEClientCallbacks; friend class NimBLEClientCallbacks;
ble_gap_conn_params m_pConnParams; ble_gap_conn_params m_pConnParams;
}; // class NimBLEClient }; // class NimBLEClient
/** /**
@ -109,5 +112,6 @@ public:
virtual bool onConfirmPIN(uint32_t pin); virtual bool onConfirmPIN(uint32_t pin);
}; };
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
#endif // CONFIG_BT_ENABLED #endif // CONFIG_BT_ENABLED
#endif /* MAIN_NIMBLECLIENT_H_ */ #endif /* MAIN_NIMBLECLIENT_H_ */

View file

@ -3,7 +3,7 @@
* *
* Created: on March 10, 2020 * Created: on March 10, 2020
* Author H2zero * Author H2zero
* *
* Originally: * Originally:
* *
* BLEDescriptor.cpp * BLEDescriptor.cpp
@ -14,6 +14,9 @@
#include "sdkconfig.h" #include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED) #if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h"
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#include "NimBLEService.h" #include "NimBLEService.h"
#include "NimBLEDescriptor.h" #include "NimBLEDescriptor.h"
#include "NimBLELog.h" #include "NimBLELog.h"
@ -29,26 +32,26 @@ static NimBLEDescriptorCallbacks defaultCallbacks;
/** /**
* @brief NimBLEDescriptor constructor. * @brief NimBLEDescriptor constructor.
*/ */
NimBLEDescriptor::NimBLEDescriptor(const char* uuid, uint16_t properties, uint16_t max_len, NimBLEDescriptor::NimBLEDescriptor(const char* uuid, uint16_t properties, uint16_t max_len,
NimBLECharacteristic* pCharacteristic) NimBLECharacteristic* pCharacteristic)
: NimBLEDescriptor(NimBLEUUID(uuid), max_len, properties, pCharacteristic) { : NimBLEDescriptor(NimBLEUUID(uuid), max_len, properties, pCharacteristic) {
} }
/** /**
* @brief NimBLEDescriptor constructor. * @brief NimBLEDescriptor constructor.
*/ */
NimBLEDescriptor::NimBLEDescriptor(NimBLEUUID uuid, uint16_t properties, uint16_t max_len, NimBLEDescriptor::NimBLEDescriptor(NimBLEUUID uuid, uint16_t properties, uint16_t max_len,
NimBLECharacteristic* pCharacteristic) NimBLECharacteristic* pCharacteristic)
{ {
m_uuid = uuid; m_uuid = uuid;
m_value.attr_len = 0; // Initial length is 0. m_value.attr_len = 0; // Initial length is 0.
m_value.attr_max_len = max_len; // Maximum length of the data. m_value.attr_max_len = max_len; // Maximum length of the data.
m_handle = NULL_HANDLE; // Handle is initially unknown. m_handle = NULL_HANDLE; // Handle is initially unknown.
m_pCharacteristic = nullptr; // No initial characteristic. m_pCharacteristic = nullptr; // No initial characteristic.
m_pCallbacks = &defaultCallbacks; // No initial callback. m_pCallbacks = &defaultCallbacks; // No initial callback.
m_value.attr_value = (uint8_t*) calloc(max_len,1); // Allocate storage for the value. m_value.attr_value = (uint8_t*) calloc(max_len,1); // Allocate storage for the value.
m_properties = 0; m_properties = 0;
if (properties & BLE_GATT_CHR_F_READ) { // convert uint16_t properties to uint8_t if (properties & BLE_GATT_CHR_F_READ) { // convert uint16_t properties to uint8_t
m_properties |= BLE_ATT_F_READ; m_properties |= BLE_ATT_F_READ;
} }
@ -81,7 +84,7 @@ NimBLEDescriptor::NimBLEDescriptor(NimBLEUUID uuid, uint16_t properties, uint16_
* @brief NimBLEDescriptor destructor. * @brief NimBLEDescriptor destructor.
*/ */
NimBLEDescriptor::~NimBLEDescriptor() { NimBLEDescriptor::~NimBLEDescriptor() {
free(m_value.attr_value); // Release the storage we created in the constructor. free(m_value.attr_value); // Release the storage we created in the constructor.
} // ~NimBLEDescriptor } // ~NimBLEDescriptor
/** /**
@ -89,7 +92,7 @@ NimBLEDescriptor::~NimBLEDescriptor() {
* @return The handle for this descriptor. * @return The handle for this descriptor.
*/ */
uint16_t NimBLEDescriptor::getHandle() { uint16_t NimBLEDescriptor::getHandle() {
return m_handle; return m_handle;
} // getHandle } // getHandle
@ -98,7 +101,7 @@ uint16_t NimBLEDescriptor::getHandle() {
* @return The length (in bytes) of the value of this descriptor. * @return The length (in bytes) of the value of this descriptor.
*/ */
size_t NimBLEDescriptor::getLength() { size_t NimBLEDescriptor::getLength() {
return m_value.attr_len; return m_value.attr_len;
} // getLength } // getLength
@ -106,7 +109,7 @@ size_t NimBLEDescriptor::getLength() {
* @brief Get the UUID of the descriptor. * @brief Get the UUID of the descriptor.
*/ */
NimBLEUUID NimBLEDescriptor::getUUID() { NimBLEUUID NimBLEDescriptor::getUUID() {
return m_uuid; return m_uuid;
} // getUUID } // getUUID
@ -115,7 +118,7 @@ NimBLEUUID NimBLEDescriptor::getUUID() {
* @return A pointer to the value of this descriptor. * @return A pointer to the value of this descriptor.
*/ */
uint8_t* NimBLEDescriptor::getValue() { uint8_t* NimBLEDescriptor::getValue() {
return m_value.attr_value; return m_value.attr_value;
} // getValue } // getValue
@ -125,25 +128,25 @@ int NimBLEDescriptor::handleGapEvent(uint16_t conn_handle, uint16_t attr_handle,
{ {
const ble_uuid_t *uuid; const ble_uuid_t *uuid;
int rc; int rc;
NimBLEDescriptor* pDescriptor = (NimBLEDescriptor*)arg; NimBLEDescriptor* pDescriptor = (NimBLEDescriptor*)arg;
NIMBLE_LOGD(LOG_TAG, "Descriptor %s %s event", pDescriptor->getUUID().toString().c_str(), NIMBLE_LOGD(LOG_TAG, "Descriptor %s %s event", pDescriptor->getUUID().toString().c_str(),
ctxt->op == BLE_GATT_ACCESS_OP_READ_DSC ? "Read" : "Write"); ctxt->op == BLE_GATT_ACCESS_OP_READ_DSC ? "Read" : "Write");
uuid = ctxt->chr->uuid; uuid = ctxt->chr->uuid;
if(ble_uuid_cmp(uuid, &pDescriptor->getUUID().getNative()->u) == 0){ if(ble_uuid_cmp(uuid, &pDescriptor->getUUID().getNative()->u) == 0){
switch(ctxt->op) { switch(ctxt->op) {
case BLE_GATT_ACCESS_OP_READ_DSC: { case BLE_GATT_ACCESS_OP_READ_DSC: {
pDescriptor->m_pCallbacks->onRead(pDescriptor); pDescriptor->m_pCallbacks->onRead(pDescriptor);
rc = os_mbuf_append(ctxt->om, pDescriptor->getValue(), pDescriptor->getLength()); rc = os_mbuf_append(ctxt->om, pDescriptor->getValue(), pDescriptor->getLength());
return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
} }
case BLE_GATT_ACCESS_OP_WRITE_DSC: { case BLE_GATT_ACCESS_OP_WRITE_DSC: {
if (ctxt->om->om_len > BLE_ATT_ATTR_MAX_LEN) { if (ctxt->om->om_len > BLE_ATT_ATTR_MAX_LEN) {
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
} }
pDescriptor->setValue(ctxt->om->om_data, ctxt->om->om_len); pDescriptor->setValue(ctxt->om->om_data, ctxt->om->om_len);
pDescriptor->m_pCallbacks->onWrite(pDescriptor); pDescriptor->m_pCallbacks->onWrite(pDescriptor);
return 0; return 0;
@ -151,8 +154,8 @@ int NimBLEDescriptor::handleGapEvent(uint16_t conn_handle, uint16_t attr_handle,
default: default:
break; break;
} }
} }
return BLE_ATT_ERR_UNLIKELY; return BLE_ATT_ERR_UNLIKELY;
} }
@ -162,10 +165,10 @@ int NimBLEDescriptor::handleGapEvent(uint16_t conn_handle, uint16_t attr_handle,
*/ */
void NimBLEDescriptor::setCallbacks(NimBLEDescriptorCallbacks* pCallbacks) { void NimBLEDescriptor::setCallbacks(NimBLEDescriptorCallbacks* pCallbacks) {
if (pCallbacks != nullptr){ if (pCallbacks != nullptr){
m_pCallbacks = pCallbacks; m_pCallbacks = pCallbacks;
} else { } else {
m_pCallbacks = &defaultCallbacks; m_pCallbacks = &defaultCallbacks;
} }
} // setCallbacks } // setCallbacks
@ -176,9 +179,9 @@ void NimBLEDescriptor::setCallbacks(NimBLEDescriptorCallbacks* pCallbacks) {
* @return N/A. * @return N/A.
*/ */
void NimBLEDescriptor::setHandle(uint16_t handle) { void NimBLEDescriptor::setHandle(uint16_t handle) {
NIMBLE_LOGD(LOG_TAG, ">> setHandle(0x%.2x): Setting descriptor handle to be 0x%.2x", handle, handle); NIMBLE_LOGD(LOG_TAG, ">> setHandle(0x%.2x): Setting descriptor handle to be 0x%.2x", handle, handle);
m_handle = handle; m_handle = handle;
NIMBLE_LOGD(LOG_TAG, "<< setHandle()"); NIMBLE_LOGD(LOG_TAG, "<< setHandle()");
} // setHandle } // setHandle
@ -188,12 +191,12 @@ void NimBLEDescriptor::setHandle(uint16_t handle) {
* @param [in] length The length of the data in bytes. * @param [in] length The length of the data in bytes.
*/ */
void NimBLEDescriptor::setValue(const uint8_t* data, size_t length) { void NimBLEDescriptor::setValue(const uint8_t* data, size_t length) {
if (length > BLE_ATT_ATTR_MAX_LEN) { if (length > BLE_ATT_ATTR_MAX_LEN) {
NIMBLE_LOGE(LOG_TAG, "Size %d too large, must be no bigger than %d", length, BLE_ATT_ATTR_MAX_LEN); NIMBLE_LOGE(LOG_TAG, "Size %d too large, must be no bigger than %d", length, BLE_ATT_ATTR_MAX_LEN);
return; return;
} }
m_value.attr_len = length; m_value.attr_len = length;
memcpy(m_value.attr_value, data, length); memcpy(m_value.attr_value, data, length);
} // setValue } // setValue
@ -202,15 +205,15 @@ void NimBLEDescriptor::setValue(const uint8_t* data, size_t length) {
* @param [in] value The value of the descriptor in string form. * @param [in] value The value of the descriptor in string form.
*/ */
void NimBLEDescriptor::setValue(const std::string &value) { void NimBLEDescriptor::setValue(const std::string &value) {
setValue((uint8_t*) value.data(), value.length()); setValue((uint8_t*) value.data(), value.length());
} // setValue } // setValue
/* /*
void NimBLEDescriptor::setAccessPermissions(uint8_t perm) { void NimBLEDescriptor::setAccessPermissions(uint8_t perm) {
m_permissions = perm; m_permissions = perm;
} }
*/ */
/** /**
@ -218,10 +221,10 @@ void NimBLEDescriptor::setAccessPermissions(uint8_t perm) {
* @return A string representation of the descriptor. * @return A string representation of the descriptor.
*/ */
std::string NimBLEDescriptor::toString() { std::string NimBLEDescriptor::toString() {
char hex[5]; char hex[5];
snprintf(hex, sizeof(hex), "%04x", m_handle); snprintf(hex, sizeof(hex), "%04x", m_handle);
std::string res = "UUID: " + m_uuid.toString() + ", handle: 0x" + hex; std::string res = "UUID: " + m_uuid.toString() + ", handle: 0x" + hex;
return res; return res;
} // toString } // toString
@ -232,7 +235,7 @@ NimBLEDescriptorCallbacks::~NimBLEDescriptorCallbacks() {}
* @param [in] pDescriptor The descriptor that is the source of the event. * @param [in] pDescriptor The descriptor that is the source of the event.
*/ */
void NimBLEDescriptorCallbacks::onRead(NimBLEDescriptor* pDescriptor) { void NimBLEDescriptorCallbacks::onRead(NimBLEDescriptor* pDescriptor) {
NIMBLE_LOGD("NimBLEDescriptorCallbacks", "onRead: default"); NIMBLE_LOGD("NimBLEDescriptorCallbacks", "onRead: default");
} // onRead } // onRead
@ -241,8 +244,8 @@ void NimBLEDescriptorCallbacks::onRead(NimBLEDescriptor* pDescriptor) {
* @param [in] pDescriptor The descriptor that is the source of the event. * @param [in] pDescriptor The descriptor that is the source of the event.
*/ */
void NimBLEDescriptorCallbacks::onWrite(NimBLEDescriptor* pDescriptor) { void NimBLEDescriptorCallbacks::onWrite(NimBLEDescriptor* pDescriptor) {
NIMBLE_LOGD("NimBLEDescriptorCallbacks", "onWrite: default"); NIMBLE_LOGD("NimBLEDescriptorCallbacks", "onWrite: default");
} // onWrite } // onWrite
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#endif /* CONFIG_BT_ENABLED */ #endif /* CONFIG_BT_ENABLED */

View file

@ -3,7 +3,7 @@
* *
* Created: on March 10, 2020 * Created: on March 10, 2020
* Author H2zero * Author H2zero
* *
* Originally: * Originally:
* *
* BLEDescriptor.h * BLEDescriptor.h
@ -17,6 +17,9 @@
#include "sdkconfig.h" #include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED) #if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h"
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#include "NimBLECharacteristic.h" #include "NimBLECharacteristic.h"
#include "NimBLEUUID.h" #include "NimBLEUUID.h"
#include "FreeRTOS.h" #include "FreeRTOS.h"
@ -43,44 +46,44 @@ class NimBLEDescriptorCallbacks;
*/ */
class NimBLEDescriptor { class NimBLEDescriptor {
public: public:
virtual ~NimBLEDescriptor(); virtual ~NimBLEDescriptor();
uint16_t getHandle(); // Get the handle of the descriptor. uint16_t getHandle(); // Get the handle of the descriptor.
size_t getLength(); // Get the length of the value of the descriptor. size_t getLength(); // Get the length of the value of the descriptor.
NimBLEUUID getUUID(); // Get the UUID of the descriptor. NimBLEUUID getUUID(); // Get the UUID of the descriptor.
uint8_t* getValue(); // Get a pointer to the value of the descriptor. uint8_t* getValue(); // Get a pointer to the value of the descriptor.
// void setAccessPermissions(uint8_t perm); // Set the permissions of the descriptor. // void setAccessPermissions(uint8_t perm); // Set the permissions of the descriptor.
void setCallbacks(NimBLEDescriptorCallbacks* pCallbacks); // Set callbacks to be invoked for the descriptor. void setCallbacks(NimBLEDescriptorCallbacks* pCallbacks); // Set callbacks to be invoked for the descriptor.
void setValue(const uint8_t* data, size_t size); // Set the value of the descriptor as a pointer to data. void setValue(const uint8_t* data, size_t size); // Set the value of the descriptor as a pointer to data.
void setValue(const std::string &value); // Set the value of the descriptor as a data buffer. void setValue(const std::string &value); // Set the value of the descriptor as a data buffer.
std::string toString(); // Convert the descriptor to a string representation. std::string toString(); // Convert the descriptor to a string representation.
private: private:
friend class NimBLEDescriptorMap; friend class NimBLEDescriptorMap;
friend class NimBLECharacteristic; friend class NimBLECharacteristic;
friend class NimBLEService; friend class NimBLEService;
friend class NimBLE2902; friend class NimBLE2902;
friend class NimBLE2904; friend class NimBLE2904;
NimBLEDescriptor(const char* uuid, uint16_t properties,
uint16_t max_len,
NimBLECharacteristic* pCharacteristic);
NimBLEDescriptor(NimBLEUUID uuid, uint16_t properties,
uint16_t max_len,
NimBLECharacteristic* pCharacteristic);
NimBLEUUID m_uuid;
uint16_t m_handle;
NimBLEDescriptorCallbacks* m_pCallbacks;
NimBLECharacteristic* m_pCharacteristic;
uint8_t m_properties;
attr_value_t m_value;
static int handleGapEvent(uint16_t conn_handle, uint16_t attr_handle, NimBLEDescriptor(const char* uuid, uint16_t properties,
uint16_t max_len,
NimBLECharacteristic* pCharacteristic);
NimBLEDescriptor(NimBLEUUID uuid, uint16_t properties,
uint16_t max_len,
NimBLECharacteristic* pCharacteristic);
NimBLEUUID m_uuid;
uint16_t m_handle;
NimBLEDescriptorCallbacks* m_pCallbacks;
NimBLECharacteristic* m_pCharacteristic;
uint8_t m_properties;
attr_value_t m_value;
static int handleGapEvent(uint16_t conn_handle, uint16_t attr_handle,
struct ble_gatt_access_ctxt *ctxt, void *arg); struct ble_gatt_access_ctxt *ctxt, void *arg);
void setHandle(uint16_t handle); void setHandle(uint16_t handle);
}; // BLEDescriptor }; // BLEDescriptor
@ -93,9 +96,11 @@ private:
*/ */
class NimBLEDescriptorCallbacks { class NimBLEDescriptorCallbacks {
public: public:
virtual ~NimBLEDescriptorCallbacks(); virtual ~NimBLEDescriptorCallbacks();
virtual void onRead(NimBLEDescriptor* pDescriptor); virtual void onRead(NimBLEDescriptor* pDescriptor);
virtual void onWrite(NimBLEDescriptor* pDescriptor); virtual void onWrite(NimBLEDescriptor* pDescriptor);
}; };
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#endif /* CONFIG_BT_ENABLED */ #endif /* CONFIG_BT_ENABLED */
#endif /* MAIN_NIMBLEDESCRIPTOR_H_ */ #endif /* MAIN_NIMBLEDESCRIPTOR_H_ */

View file

@ -3,7 +3,7 @@
* *
* Created: on March 10, 2020 * Created: on March 10, 2020
* Author H2zero * Author H2zero
* *
* Originally: * Originally:
* *
* BLEDescriptorMap.cpp * BLEDescriptorMap.cpp
@ -13,6 +13,10 @@
*/ */
#include "sdkconfig.h" #include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED) #if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h"
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#include "NimBLECharacteristic.h" #include "NimBLECharacteristic.h"
#include "NimBLEDescriptor.h" #include "NimBLEDescriptor.h"
@ -23,7 +27,7 @@
* @return The descriptor. If not present, then nullptr is returned. * @return The descriptor. If not present, then nullptr is returned.
*/ */
NimBLEDescriptor* NimBLEDescriptorMap::getByUUID(const char* uuid) { NimBLEDescriptor* NimBLEDescriptorMap::getByUUID(const char* uuid) {
return getByUUID(NimBLEUUID(uuid)); return getByUUID(NimBLEUUID(uuid));
} }
@ -33,12 +37,12 @@ NimBLEDescriptor* NimBLEDescriptorMap::getByUUID(const char* uuid) {
* @return The descriptor. If not present, then nullptr is returned. * @return The descriptor. If not present, then nullptr is returned.
*/ */
NimBLEDescriptor* NimBLEDescriptorMap::getByUUID(const NimBLEUUID &uuid) { NimBLEDescriptor* NimBLEDescriptorMap::getByUUID(const NimBLEUUID &uuid) {
for (auto &myPair : m_uuidMap) { for (auto &myPair : m_uuidMap) {
if (myPair.first->getUUID().equals(uuid)) { if (myPair.first->getUUID().equals(uuid)) {
return myPair.first; return myPair.first;
} }
} }
return nullptr; return nullptr;
} // getByUUID } // getByUUID
@ -49,7 +53,7 @@ NimBLEDescriptor* NimBLEDescriptorMap::getByUUID(const NimBLEUUID &uuid) {
*/ */
/* /*
NimBLEDescriptor* NimBLEDescriptorMap::getByHandle(uint16_t handle) { NimBLEDescriptor* NimBLEDescriptorMap::getByHandle(uint16_t handle) {
return m_handleMap.at(handle); return m_handleMap.at(handle);
} // getByHandle } // getByHandle
*/ */
@ -60,7 +64,7 @@ NimBLEDescriptor* NimBLEDescriptorMap::getByHandle(uint16_t handle) {
* @return N/A. * @return N/A.
*/ */
void NimBLEDescriptorMap::setByUUID(const char* uuid, NimBLEDescriptor* pDescriptor){ void NimBLEDescriptorMap::setByUUID(const char* uuid, NimBLEDescriptor* pDescriptor){
m_uuidMap.insert(std::pair<NimBLEDescriptor*, std::string>(pDescriptor, uuid)); m_uuidMap.insert(std::pair<NimBLEDescriptor*, std::string>(pDescriptor, uuid));
} // setByUUID } // setByUUID
@ -72,7 +76,7 @@ void NimBLEDescriptorMap::setByUUID(const char* uuid, NimBLEDescriptor* pDescrip
* @return N/A. * @return N/A.
*/ */
void NimBLEDescriptorMap::setByUUID(const NimBLEUUID &uuid, NimBLEDescriptor* pDescriptor) { void NimBLEDescriptorMap::setByUUID(const NimBLEUUID &uuid, NimBLEDescriptor* pDescriptor) {
m_uuidMap.insert(std::pair<NimBLEDescriptor*, std::string>(pDescriptor, uuid.toString())); m_uuidMap.insert(std::pair<NimBLEDescriptor*, std::string>(pDescriptor, uuid.toString()));
} // setByUUID } // setByUUID
@ -84,7 +88,7 @@ void NimBLEDescriptorMap::setByUUID(const NimBLEUUID &uuid, NimBLEDescriptor* pD
*/ */
/* /*
void NimBLEDescriptorMap::setByHandle(uint16_t handle, NimBLEDescriptor* pDescriptor) { void NimBLEDescriptorMap::setByHandle(uint16_t handle, NimBLEDescriptor* pDescriptor) {
m_handleMap.insert(std::pair<uint16_t, NimBLEDescriptor*>(handle, pDescriptor)); m_handleMap.insert(std::pair<uint16_t, NimBLEDescriptor*>(handle, pDescriptor));
} // setByHandle } // setByHandle
*/ */
@ -93,7 +97,7 @@ void NimBLEDescriptorMap::setByHandle(uint16_t handle, NimBLEDescriptor* pDescri
* @brief Get the number of descriptors in the map. * @brief Get the number of descriptors in the map.
*/ */
uint8_t NimBLEDescriptorMap::getSize() { uint8_t NimBLEDescriptorMap::getSize() {
return (uint8_t)m_uuidMap.size(); return (uint8_t)m_uuidMap.size();
} // getSize } // getSize
@ -102,18 +106,18 @@ uint8_t NimBLEDescriptorMap::getSize() {
* @return A string representation of the descriptor map. * @return A string representation of the descriptor map.
*/ */
std::string NimBLEDescriptorMap::toString() { std::string NimBLEDescriptorMap::toString() {
std::string res; std::string res;
char hex[5]; char hex[5];
int count = 0; int count = 0;
for (auto &myPair : m_uuidMap) { for (auto &myPair : m_uuidMap) {
if (count > 0) {res += "\n";} if (count > 0) {res += "\n";}
snprintf(hex, sizeof(hex), "%04x", myPair.first->getHandle()); snprintf(hex, sizeof(hex), "%04x", myPair.first->getHandle());
count++; count++;
res += "handle: 0x"; res += "handle: 0x";
res += hex; res += hex;
res += ", uuid: " + myPair.first->getUUID().toString(); res += ", uuid: " + myPair.first->getUUID().toString();
} }
return res; return res;
} // toString } // toString
@ -122,11 +126,11 @@ std::string NimBLEDescriptorMap::toString() {
* @return The first descriptor in the map. * @return The first descriptor in the map.
*/ */
NimBLEDescriptor* NimBLEDescriptorMap::getFirst() { NimBLEDescriptor* NimBLEDescriptorMap::getFirst() {
m_iterator = m_uuidMap.begin(); m_iterator = m_uuidMap.begin();
if (m_iterator == m_uuidMap.end()) return nullptr; if (m_iterator == m_uuidMap.end()) return nullptr;
NimBLEDescriptor* pRet = m_iterator->first; NimBLEDescriptor* pRet = m_iterator->first;
m_iterator++; m_iterator++;
return pRet; return pRet;
} // getFirst } // getFirst
@ -135,9 +139,11 @@ NimBLEDescriptor* NimBLEDescriptorMap::getFirst() {
* @return The next descriptor in the map. * @return The next descriptor in the map.
*/ */
NimBLEDescriptor* NimBLEDescriptorMap::getNext() { NimBLEDescriptor* NimBLEDescriptorMap::getNext() {
if (m_iterator == m_uuidMap.end()) return nullptr; if (m_iterator == m_uuidMap.end()) return nullptr;
NimBLEDescriptor* pRet = m_iterator->first; NimBLEDescriptor* pRet = m_iterator->first;
m_iterator++; m_iterator++;
return pRet; return pRet;
} // getNext } // getNext
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#endif /* CONFIG_BT_ENABLED */ #endif /* CONFIG_BT_ENABLED */

View file

@ -3,7 +3,7 @@
* *
* Created: on Jan 24 2020 * Created: on Jan 24 2020
* Author H2zero * Author H2zero
* *
* Originally: * Originally:
* *
* BLEDevice.cpp * BLEDevice.cpp
@ -14,6 +14,7 @@
#include "sdkconfig.h" #include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED) #if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h"
#include "NimBLEDevice.h" #include "NimBLEDevice.h"
#include "NimBLEUtils.h" #include "NimBLEUtils.h"
@ -40,61 +41,63 @@ static const char* LOG_TAG = "NimBLEDevice";
* Singletons for the NimBLEDevice. * Singletons for the NimBLEDevice.
*/ */
bool initialized = false; bool initialized = false;
#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
NimBLEScan* NimBLEDevice::m_pScan = nullptr; NimBLEScan* NimBLEDevice::m_pScan = nullptr;
#endif
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
NimBLEServer* NimBLEDevice::m_pServer = nullptr; NimBLEServer* NimBLEDevice::m_pServer = nullptr;
#endif
uint32_t NimBLEDevice::m_passkey = 123456; uint32_t NimBLEDevice::m_passkey = 123456;
bool NimBLEDevice::m_synced = false; bool NimBLEDevice::m_synced = false;
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
NimBLEAdvertising* NimBLEDevice::m_bleAdvertising = nullptr; NimBLEAdvertising* NimBLEDevice::m_bleAdvertising = nullptr;
#endif
gap_event_handler NimBLEDevice::m_customGapHandler = nullptr; gap_event_handler NimBLEDevice::m_customGapHandler = nullptr;
ble_gap_event_listener NimBLEDevice::m_listener; ble_gap_event_listener NimBLEDevice::m_listener;
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
std::list <NimBLEClient*> NimBLEDevice::m_cList; std::list <NimBLEClient*> NimBLEDevice::m_cList;
#endif
std::list <NimBLEAddress> NimBLEDevice::m_ignoreList; std::list <NimBLEAddress> NimBLEDevice::m_ignoreList;
NimBLESecurityCallbacks* NimBLEDevice::m_securityCallbacks = nullptr; NimBLESecurityCallbacks* NimBLEDevice::m_securityCallbacks = nullptr;
//std::map<uint16_t, conn_status_t> BLEDevice::m_connectedClientsMap;
//gattc_event_handler BLEDevice::m_customGattcHandler = nullptr;
//gatts_event_handler BLEDevice::m_customGattsHandler = nullptr;
/** /**
* @brief Create a new instance of a server. * @brief Create a new instance of a server.
* @return A new instance of the server. * @return A new instance of the server.
*/ */
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
/* STATIC */ NimBLEServer* NimBLEDevice::createServer() { /* STATIC */ NimBLEServer* NimBLEDevice::createServer() {
/*#ifndef CONFIG_GATTS_ENABLE // Check that BLE GATTS is enabled in make menuconfig
NIMBLE_LOGE(LOG_TAG, "BLE GATTS is not enabled - CONFIG_GATTS_ENABLE not defined");
abort();
#endif // CONFIG_GATTS_ENABLE
*/
if(NimBLEDevice::m_pServer == nullptr) { if(NimBLEDevice::m_pServer == nullptr) {
NimBLEDevice::m_pServer = new NimBLEServer(); NimBLEDevice::m_pServer = new NimBLEServer();
ble_gatts_reset(); ble_gatts_reset();
ble_svc_gap_init(); ble_svc_gap_init();
ble_svc_gatt_init(); ble_svc_gatt_init();
} }
return m_pServer; return m_pServer;
} // createServer } // createServer
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
NimBLEAdvertising* NimBLEDevice::getAdvertising() { NimBLEAdvertising* NimBLEDevice::getAdvertising() {
if(m_bleAdvertising == nullptr) { if(m_bleAdvertising == nullptr) {
m_bleAdvertising = new NimBLEAdvertising(); m_bleAdvertising = new NimBLEAdvertising();
} }
return m_bleAdvertising; return m_bleAdvertising;
} }
void NimBLEDevice::startAdvertising() { void NimBLEDevice::startAdvertising() {
getAdvertising()->start(); getAdvertising()->start();
} // startAdvertising } // startAdvertising
void NimBLEDevice::stopAdvertising() { void NimBLEDevice::stopAdvertising() {
getAdvertising()->stop(); getAdvertising()->stop();
} // stopAdvertising } // stopAdvertising
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
/** /**
@ -102,25 +105,27 @@ void NimBLEDevice::stopAdvertising() {
* @return The scanning object reference. This is a singleton object. The caller should not * @return The scanning object reference. This is a singleton object. The caller should not
* try and release/delete it. * try and release/delete it.
*/ */
#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
/* STATIC */ NimBLEScan* NimBLEDevice::getScan() { /* STATIC */ NimBLEScan* NimBLEDevice::getScan() {
if (m_pScan == nullptr) { if (m_pScan == nullptr) {
m_pScan = new NimBLEScan(); m_pScan = new NimBLEScan();
} }
return m_pScan; return m_pScan;
} // getScan } // getScan
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
/** /**
* @brief Creates a new client object and maintains a list of all client objects * @brief Creates a new client object and maintains a list of all client objects
* each client can connect to 1 peripheral device. * each client can connect to 1 peripheral device.
* @return A reference to the new client object. * @return A reference to the new client object.
*/ */
#if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
/* STATIC */ NimBLEClient* NimBLEDevice::createClient() { /* STATIC */ NimBLEClient* NimBLEDevice::createClient() {
if(m_cList.size() >= NIMBLE_MAX_CONNECTIONS) { if(m_cList.size() >= NIMBLE_MAX_CONNECTIONS) {
NIMBLE_LOGW("Number of clients exceeds Max connections. Max=(%d)", NIMBLE_LOGW("Number of clients exceeds Max connections. Max=(%d)",
NIMBLE_MAX_CONNECTIONS); NIMBLE_MAX_CONNECTIONS);
} }
NimBLEClient* pClient = new NimBLEClient(); NimBLEClient* pClient = new NimBLEClient();
m_cList.push_back(pClient); m_cList.push_back(pClient);
@ -137,7 +142,7 @@ void NimBLEDevice::stopAdvertising() {
if(pClient == nullptr) { if(pClient == nullptr) {
return false; return false;
} }
if(pClient->m_isConnected) { if(pClient->m_isConnected) {
if (pClient->disconnect() != 0) { if (pClient->disconnect() != 0) {
return false; return false;
@ -146,7 +151,7 @@ void NimBLEDevice::stopAdvertising() {
vTaskDelay(1); vTaskDelay(1);
} }
} }
if(pClient->m_waitingToConnect) { if(pClient->m_waitingToConnect) {
if(ble_gap_conn_cancel() != 0){ if(ble_gap_conn_cancel() != 0){
return false; return false;
@ -155,10 +160,10 @@ void NimBLEDevice::stopAdvertising() {
vTaskDelay(1); vTaskDelay(1);
} }
} }
m_cList.remove(pClient); m_cList.remove(pClient);
delete pClient; delete pClient;
return true; return true;
} // deleteClient } // deleteClient
@ -225,18 +230,20 @@ void NimBLEDevice::stopAdvertising() {
return nullptr; return nullptr;
} // getDisconnectedClient } // getDisconnectedClient
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
/** /**
* @brief Set the transmission power. * @brief Set the transmission power.
* The power level can be one of: * The power level can be one of:
* * ESP_PWR_LVL_N12 = 0, !< Corresponding to -12dbm * * ESP_PWR_LVL_N12 = 0, !< Corresponding to -12dbm
* * ESP_PWR_LVL_N9 = 1, !< Corresponding to -9dbm * * ESP_PWR_LVL_N9 = 1, !< Corresponding to -9dbm
* * ESP_PWR_LVL_N6 = 2, !< Corresponding to -6dbm * * ESP_PWR_LVL_N6 = 2, !< Corresponding to -6dbm
* * ESP_PWR_LVL_N3 = 3, !< Corresponding to -3dbm * * ESP_PWR_LVL_N3 = 3, !< Corresponding to -3dbm
* * ESP_PWR_LVL_N0 = 4, !< Corresponding to 0dbm * * ESP_PWR_LVL_N0 = 4, !< Corresponding to 0dbm
* * ESP_PWR_LVL_P3 = 5, !< Corresponding to +3dbm * * ESP_PWR_LVL_P3 = 5, !< Corresponding to +3dbm
* * ESP_PWR_LVL_P6 = 6, !< Corresponding to +6dbm * * ESP_PWR_LVL_P6 = 6, !< Corresponding to +6dbm
* * ESP_PWR_LVL_P9 = 7, !< Corresponding to +9dbm * * ESP_PWR_LVL_P9 = 7, !< Corresponding to +9dbm
* @param [in] powerLevel. * @param [in] powerLevel.
*/ */
/* STATIC */ void NimBLEDevice::setPower(esp_power_level_t powerLevel, esp_ble_power_type_t powerType) { /* STATIC */ void NimBLEDevice::setPower(esp_power_level_t powerLevel, esp_ble_power_type_t powerType) {
@ -251,26 +258,26 @@ void NimBLEDevice::stopAdvertising() {
/* STATIC */ int NimBLEDevice::getPower(esp_ble_power_type_t powerType) { /* STATIC */ int NimBLEDevice::getPower(esp_ble_power_type_t powerType) {
switch(esp_ble_tx_power_get(powerType)) { switch(esp_ble_tx_power_get(powerType)) {
case ESP_PWR_LVL_N12: case ESP_PWR_LVL_N12:
return -12; return -12;
case ESP_PWR_LVL_N9: case ESP_PWR_LVL_N9:
return -9; return -9;
case ESP_PWR_LVL_N6: case ESP_PWR_LVL_N6:
return -6; return -6;
case ESP_PWR_LVL_N3: case ESP_PWR_LVL_N3:
return -6; return -6;
case ESP_PWR_LVL_N0: case ESP_PWR_LVL_N0:
return 0; return 0;
case ESP_PWR_LVL_P3: case ESP_PWR_LVL_P3:
return 3; return 3;
case ESP_PWR_LVL_P6: case ESP_PWR_LVL_P6:
return 6; return 6;
case ESP_PWR_LVL_P9: case ESP_PWR_LVL_P9:
return 9; return 9;
default: default:
return BLE_HS_ADV_TX_PWR_LVL_AUTO; return BLE_HS_ADV_TX_PWR_LVL_AUTO;
} }
} // setPower } // setPower
@ -282,13 +289,13 @@ void NimBLEDevice::stopAdvertising() {
/* STATIC*/ NimBLEAddress NimBLEDevice::getAddress() { /* STATIC*/ NimBLEAddress NimBLEDevice::getAddress() {
ble_addr_t addr = {BLE_ADDR_PUBLIC, 0}; ble_addr_t addr = {BLE_ADDR_PUBLIC, 0};
//ble_hs_id_copy_addr(BLE_ADDR_PUBLIC, addr.val, NULL) //ble_hs_id_copy_addr(BLE_ADDR_PUBLIC, addr.val, NULL)
if(BLE_HS_ENOADDR == ble_hs_id_copy_addr(BLE_ADDR_PUBLIC, addr.val, NULL)) { if(BLE_HS_ENOADDR == ble_hs_id_copy_addr(BLE_ADDR_PUBLIC, addr.val, NULL)) {
NIMBLE_LOGD(LOG_TAG, "Public address not found, checking random"); NIMBLE_LOGD(LOG_TAG, "Public address not found, checking random");
addr.type = BLE_ADDR_RANDOM; addr.type = BLE_ADDR_RANDOM;
ble_hs_id_copy_addr(BLE_ADDR_RANDOM, addr.val, NULL); ble_hs_id_copy_addr(BLE_ADDR_RANDOM, addr.val, NULL);
} }
return NimBLEAddress(addr); return NimBLEAddress(addr);
} // getAddress } // getAddress
@ -309,13 +316,13 @@ void NimBLEDevice::stopAdvertising() {
*/ */
/* STATIC */int NimBLEDevice::setMTU(uint16_t mtu) { /* STATIC */int NimBLEDevice::setMTU(uint16_t mtu) {
NIMBLE_LOGD(LOG_TAG, ">> setLocalMTU: %d", mtu); NIMBLE_LOGD(LOG_TAG, ">> setLocalMTU: %d", mtu);
int rc = ble_att_set_preferred_mtu(mtu); int rc = ble_att_set_preferred_mtu(mtu);
if (rc != 0) { if (rc != 0) {
NIMBLE_LOGE(LOG_TAG, "Could not set local mtu value to: %d", mtu); NIMBLE_LOGE(LOG_TAG, "Could not set local mtu value to: %d", mtu);
} }
NIMBLE_LOGD(LOG_TAG, "<< setLocalMTU"); NIMBLE_LOGD(LOG_TAG, "<< setLocalMTU");
return rc; return rc;
} // setMTU } // setMTU
@ -337,26 +344,32 @@ void NimBLEDevice::stopAdvertising() {
if(!m_synced) { if(!m_synced) {
return; return;
} }
m_synced = false; m_synced = false;
#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
if(m_pScan != nullptr) { if(m_pScan != nullptr) {
m_pScan->onHostReset(); m_pScan->onHostReset();
} }
/* Not needed #endif
/* Not needed
if(m_pServer != nullptr) { if(m_pServer != nullptr) {
m_pServer->onHostReset(); m_pServer->onHostReset();
} }
for(auto it = m_cList.cbegin(); it != m_cList.cend(); ++it) { for(auto it = m_cList.cbegin(); it != m_cList.cend(); ++it) {
(*it)->onHostReset(); (*it)->onHostReset();
} }
*/ */
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
if(m_bleAdvertising != nullptr) { if(m_bleAdvertising != nullptr) {
m_bleAdvertising->onHostReset(); m_bleAdvertising->onHostReset();
} }
#endif
NIMBLE_LOGC(LOG_TAG, "Resetting state; reason=%d, %s", reason,
NIMBLE_LOGC(LOG_TAG, "Resetting state; reason=%d, %s", reason,
NimBLEUtils::returnCodeToString(reason)); NimBLEUtils::returnCodeToString(reason));
} // onReset } // onReset
@ -372,23 +385,27 @@ void NimBLEDevice::stopAdvertising() {
if(m_synced) { if(m_synced) {
return; return;
} }
/* Make sure we have proper identity address set (public preferred) */ /* Make sure we have proper identity address set (public preferred) */
int rc = ble_hs_util_ensure_addr(0); int rc = ble_hs_util_ensure_addr(0);
assert(rc == 0); assert(rc == 0);
m_synced = true; m_synced = true;
if(initialized) { if(initialized) {
#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
if(m_pScan != nullptr) { if(m_pScan != nullptr) {
// Restart scanning with the last values sent, allow to clear results. // Restart scanning with the last values sent, allow to clear results.
m_pScan->start(m_pScan->m_duration, m_pScan->m_scanCompleteCB); m_pScan->start(m_pScan->m_duration, m_pScan->m_scanCompleteCB);
} }
#endif
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
if(m_bleAdvertising != nullptr) { if(m_bleAdvertising != nullptr) {
// Restart advertisng, parameters should already be set. // Restart advertisng, parameters should already be set.
m_bleAdvertising->start(); m_bleAdvertising->start();
} }
#endif
} }
} // onSync } // onSync
@ -414,7 +431,7 @@ void NimBLEDevice::stopAdvertising() {
if(!initialized){ if(!initialized){
int rc=0; int rc=0;
esp_err_t errRc = ESP_OK; esp_err_t errRc = ESP_OK;
#ifdef ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP32
// make sure the linker includes esp32-hal-bt.c so ardruino init doesn't release BLE memory. // make sure the linker includes esp32-hal-bt.c so ardruino init doesn't release BLE memory.
btStarted(); btStarted();
@ -428,25 +445,25 @@ void NimBLEDevice::stopAdvertising() {
} }
ESP_ERROR_CHECK(errRc); ESP_ERROR_CHECK(errRc);
ESP_ERROR_CHECK(esp_nimble_hci_and_controller_init()); ESP_ERROR_CHECK(esp_nimble_hci_and_controller_init());
nimble_port_init(); nimble_port_init();
// Setup callbacks for host events // Setup callbacks for host events
ble_hs_cfg.reset_cb = NimBLEDevice::onReset; ble_hs_cfg.reset_cb = NimBLEDevice::onReset;
ble_hs_cfg.sync_cb = NimBLEDevice::onSync; ble_hs_cfg.sync_cb = NimBLEDevice::onSync;
// Set initial security capabilities // Set initial security capabilities
ble_hs_cfg.sm_io_cap = BLE_HS_IO_NO_INPUT_OUTPUT; ble_hs_cfg.sm_io_cap = BLE_HS_IO_NO_INPUT_OUTPUT;
ble_hs_cfg.sm_bonding = 0; ble_hs_cfg.sm_bonding = 0;
ble_hs_cfg.sm_mitm = 0; ble_hs_cfg.sm_mitm = 0;
ble_hs_cfg.sm_sc = 1; ble_hs_cfg.sm_sc = 1;
ble_hs_cfg.sm_our_key_dist = 1; ble_hs_cfg.sm_our_key_dist = 1;
ble_hs_cfg.sm_their_key_dist = 3; ble_hs_cfg.sm_their_key_dist = 3;
ble_hs_cfg.store_status_cb = ble_store_util_status_rr; /*TODO: Implement handler for this*/ ble_hs_cfg.store_status_cb = ble_store_util_status_rr; /*TODO: Implement handler for this*/
// Set the device name. // Set the device name.
rc = ble_svc_gap_device_name_set(deviceName.c_str()); rc = ble_svc_gap_device_name_set(deviceName.c_str());
assert(rc == 0); assert(rc == 0);
@ -471,12 +488,12 @@ void NimBLEDevice::stopAdvertising() {
int ret = nimble_port_stop(); int ret = nimble_port_stop();
if (ret == 0) { if (ret == 0) {
nimble_port_deinit(); nimble_port_deinit();
ret = esp_nimble_hci_and_controller_deinit(); ret = esp_nimble_hci_and_controller_deinit();
if (ret != ESP_OK) { if (ret != ESP_OK) {
NIMBLE_LOGE(LOG_TAG, "esp_nimble_hci_and_controller_deinit() failed with error: %d", ret); NIMBLE_LOGE(LOG_TAG, "esp_nimble_hci_and_controller_deinit() failed with error: %d", ret);
} }
initialized = false; initialized = false;
m_synced = false; m_synced = false;
} }
@ -509,12 +526,12 @@ bool NimBLEDevice::getInitialized() {
* @brief Set the authorization mode for this device. * @brief Set the authorization mode for this device.
* @param A bitmap indicating what modes are supported. * @param A bitmap indicating what modes are supported.
* The bits are defined as follows: * The bits are defined as follows:
** 0x01 BLE_SM_PAIR_AUTHREQ_BOND ** 0x01 BLE_SM_PAIR_AUTHREQ_BOND
** 0x04 BLE_SM_PAIR_AUTHREQ_MITM ** 0x04 BLE_SM_PAIR_AUTHREQ_MITM
** 0x08 BLE_SM_PAIR_AUTHREQ_SC ** 0x08 BLE_SM_PAIR_AUTHREQ_SC
** 0x10 BLE_SM_PAIR_AUTHREQ_KEYPRESS - not yet supported. ** 0x10 BLE_SM_PAIR_AUTHREQ_KEYPRESS - not yet supported.
** 0xe2 BLE_SM_PAIR_AUTHREQ_RESERVED - for reference only. ** 0xe2 BLE_SM_PAIR_AUTHREQ_RESERVED - for reference only.
*/ */
/*STATIC*/void NimBLEDevice::setSecurityAuth(uint8_t auth_req) { /*STATIC*/void NimBLEDevice::setSecurityAuth(uint8_t auth_req) {
NimBLEDevice::setSecurityAuth((auth_req & BLE_SM_PAIR_AUTHREQ_BOND)>0, NimBLEDevice::setSecurityAuth((auth_req & BLE_SM_PAIR_AUTHREQ_BOND)>0,
(auth_req & BLE_SM_PAIR_AUTHREQ_MITM)>0, (auth_req & BLE_SM_PAIR_AUTHREQ_MITM)>0,
@ -527,8 +544,8 @@ bool NimBLEDevice::getInitialized() {
* @param One of the following: * @param One of the following:
** 0x00 BLE_HS_IO_DISPLAY_ONLY DisplayOnly IO capability ** 0x00 BLE_HS_IO_DISPLAY_ONLY DisplayOnly IO capability
** 0x01 BLE_HS_IO_DISPLAY_YESNO DisplayYesNo IO capability ** 0x01 BLE_HS_IO_DISPLAY_YESNO DisplayYesNo IO capability
** 0x02 BLE_HS_IO_KEYBOARD_ONLY KeyboardOnly IO capability ** 0x02 BLE_HS_IO_KEYBOARD_ONLY KeyboardOnly IO capability
** 0x03 BLE_HS_IO_NO_INPUT_OUTPUT NoInputNoOutput IO capability ** 0x03 BLE_HS_IO_NO_INPUT_OUTPUT NoInputNoOutput IO capability
** 0x04 BLE_HS_IO_KEYBOARD_DISPLAY KeyboardDisplay Only IO capability ** 0x04 BLE_HS_IO_KEYBOARD_DISPLAY KeyboardDisplay Only IO capability
*/ */
/*STATIC*/ void NimBLEDevice::setSecurityIOCap(uint8_t iocap) { /*STATIC*/ void NimBLEDevice::setSecurityIOCap(uint8_t iocap) {
@ -539,7 +556,7 @@ bool NimBLEDevice::getInitialized() {
/** /**
* @brief If we are the initiator of the security procedure this sets the keys we will distribute. * @brief If we are the initiator of the security procedure this sets the keys we will distribute.
* @param A bitmap indicating which keys to distribute during pairing. * @param A bitmap indicating which keys to distribute during pairing.
* The bits are defined as follows: * The bits are defined as follows:
** 0x01: BLE_SM_PAIR_KEY_DIST_ENC - Distribute the encryption key. ** 0x01: BLE_SM_PAIR_KEY_DIST_ENC - Distribute the encryption key.
** 0x02: BLE_SM_PAIR_KEY_DIST_ID - Distribute the ID key (IRK). ** 0x02: BLE_SM_PAIR_KEY_DIST_ID - Distribute the ID key (IRK).
** 0x04: BLE_SM_PAIR_KEY_DIST_SIGN ** 0x04: BLE_SM_PAIR_KEY_DIST_SIGN
@ -553,7 +570,7 @@ bool NimBLEDevice::getInitialized() {
/** /**
* @brief Set the keys we are willing to accept during pairing. * @brief Set the keys we are willing to accept during pairing.
* @param A bitmap indicating which keys to accept during pairing. * @param A bitmap indicating which keys to accept during pairing.
* The bits are defined as follows: * The bits are defined as follows:
** 0x01: BLE_SM_PAIR_KEY_DIST_ENC - Accept the encryption key. ** 0x01: BLE_SM_PAIR_KEY_DIST_ENC - Accept the encryption key.
** 0x02: BLE_SM_PAIR_KEY_DIST_ID - Accept the ID key (IRK). ** 0x02: BLE_SM_PAIR_KEY_DIST_ID - Accept the ID key (IRK).
** 0x04: BLE_SM_PAIR_KEY_DIST_SIGN ** 0x04: BLE_SM_PAIR_KEY_DIST_SIGN
@ -596,14 +613,14 @@ void NimBLEDevice::setSecurityCallbacks(NimBLESecurityCallbacks* callbacks) {
*/ */
/* STATIC */int NimBLEDevice::startSecurity(uint16_t conn_id) { /* STATIC */int NimBLEDevice::startSecurity(uint16_t conn_id) {
/* if(m_securityCallbacks != nullptr) { /* if(m_securityCallbacks != nullptr) {
m_securityCallbacks->onSecurityRequest(); m_securityCallbacks->onSecurityRequest();
} }
*/ */
int rc = ble_gap_security_initiate(conn_id); int rc = ble_gap_security_initiate(conn_id);
if(rc != 0){ if(rc != 0){
NIMBLE_LOGE(LOG_TAG, "ble_gap_security_initiate: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc)); NIMBLE_LOGE(LOG_TAG, "ble_gap_security_initiate: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
} }
return rc; return rc;
} // startSecurity } // startSecurity
@ -661,20 +678,4 @@ void NimBLEDevice::setCustomGapHandler(gap_event_handler handler) {
} // setCustomGapHandler } // setCustomGapHandler
/**
* @brief Backward compatibility for bluedroid gatt events.
* NimBLe does not send GATT events
*/
/*
void BLEDevice::setCustomGattcHandler(gattc_event_handler handler) {
setCustomGapHandler(handler);
}
void BLEDevice::setCustomGattsHandler(gatts_event_handler handler) {
setCustomGapHandler(handler);
}
*/
/**********************************************************/
#endif // CONFIG_BT_ENABLED #endif // CONFIG_BT_ENABLED

View file

@ -3,7 +3,7 @@
* *
* Created: on Jan 24 2020 * Created: on Jan 24 2020
* Author H2zero * Author H2zero
* *
* Originally: * Originally:
* *
* BLEDevice.h * BLEDevice.h
@ -17,11 +17,27 @@
#include "sdkconfig.h" #include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED) #if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h"
#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
#include "NimBLEScan.h" #include "NimBLEScan.h"
#include "NimBLEUtils.h" #endif
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
#include "NimBLEAdvertising.h"
#endif
#if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
#include "NimBLEClient.h" #include "NimBLEClient.h"
#endif
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#include "NimBLEServer.h" #include "NimBLEServer.h"
#endif
#include "NimBLEUtils.h"
#include "NimBLESecurity.h" #include "NimBLESecurity.h"
#include "NimBLEAddress.h"
#include "esp_bt.h" #include "esp_bt.h"
@ -50,43 +66,46 @@
#define BLEAdvertising NimBLEAdvertising #define BLEAdvertising NimBLEAdvertising
#define BLEServerCallbacks NimBLEServerCallbacks #define BLEServerCallbacks NimBLEServerCallbacks
#define BLECharacteristicCallbacks NimBLECharacteristicCallbacks #define BLECharacteristicCallbacks NimBLECharacteristicCallbacks
#define BLEAdvertisementData NimBLEAdvertisementData #define BLEAdvertisementData NimBLEAdvertisementData
#define BLEDescriptor NimBLEDescriptor #define BLEDescriptor NimBLEDescriptor
#define BLE2902 NimBLE2902 #define BLE2902 NimBLE2902
#define BLE2904 NimBLE2904 #define BLE2904 NimBLE2904
#define BLEDescriptorCallbacks NimBLEDescriptorCallbacks #define BLEDescriptorCallbacks NimBLEDescriptorCallbacks
#define BLEBeacon NimBLEBeacon #define BLEBeacon NimBLEBeacon
#define BLEEddystoneTLM NimBLEEddystoneTLM #define BLEEddystoneTLM NimBLEEddystoneTLM
#define BLEEddystoneURL NimBLEEddystoneURL #define BLEEddystoneURL NimBLEEddystoneURL
#ifdef CONFIG_BT_NIMBLE_MAX_CONNECTIONS #ifdef CONFIG_BT_NIMBLE_MAX_CONNECTIONS
#define NIMBLE_MAX_CONNECTIONS CONFIG_BT_NIMBLE_MAX_CONNECTIONS #define NIMBLE_MAX_CONNECTIONS CONFIG_BT_NIMBLE_MAX_CONNECTIONS
#else #else
#define NIMBLE_MAX_CONNECTIONS CONFIG_NIMBLE_MAX_CONNECTIONS #define NIMBLE_MAX_CONNECTIONS CONFIG_NIMBLE_MAX_CONNECTIONS
#endif #endif
/** /**
* @brief BLE functions. * @brief BLE functions.
*/ */
typedef int (*gap_event_handler)(ble_gap_event *event, void *arg); typedef int (*gap_event_handler)(ble_gap_event *event, void *arg);
//typedef void (*gattc_event_handler)(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t* param);
//typedef void (*gatts_event_handler)(esp_gatts_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gatts_cb_param_t* param);
extern "C" void ble_store_config_init(void); extern "C" void ble_store_config_init(void);
class NimBLEDevice { class NimBLEDevice {
public: public:
static void init(const std::string &deviceName); // Initialize the local BLE environment. static void init(const std::string &deviceName);
static void deinit(); static void deinit();
static bool getInitialized(); static bool getInitialized();
static NimBLEAddress getAddress(); static NimBLEAddress getAddress();
static std::string toString(); static std::string toString();
static NimBLEScan* getScan(); // Get the scan object
static NimBLEClient* createClient(); #if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
static NimBLEServer* createServer(); static NimBLEScan* getScan();
static bool deleteClient(NimBLEClient* pClient); #endif
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
static NimBLEServer* createServer();
#endif
static void setPower(esp_power_level_t powerLevel, esp_ble_power_type_t powerType=ESP_BLE_PWR_TYPE_DEFAULT); static void setPower(esp_power_level_t powerLevel, esp_ble_power_type_t powerType=ESP_BLE_PWR_TYPE_DEFAULT);
static int getPower(esp_ble_power_type_t powerType=ESP_BLE_PWR_TYPE_DEFAULT); static int getPower(esp_ble_power_type_t powerType=ESP_BLE_PWR_TYPE_DEFAULT);
static void setCustomGapHandler(gap_event_handler handler); static void setCustomGapHandler(gap_event_handler handler);
static void setSecurityAuth(bool bonding, bool mitm, bool sc); static void setSecurityAuth(bool bonding, bool mitm, bool sc);
static void setSecurityAuth(uint8_t auth_req); static void setSecurityAuth(uint8_t auth_req);
@ -101,36 +120,66 @@ public:
static bool isIgnored(const NimBLEAddress &address); static bool isIgnored(const NimBLEAddress &address);
static void addIgnored(const NimBLEAddress &address); static void addIgnored(const NimBLEAddress &address);
static void removeIgnored(const NimBLEAddress &address); static void removeIgnored(const NimBLEAddress &address);
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
static NimBLEAdvertising* getAdvertising(); static NimBLEAdvertising* getAdvertising();
static void startAdvertising(); static void startAdvertising();
static void stopAdvertising(); static void stopAdvertising();
#endif
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
static NimBLEClient* createClient();
static bool deleteClient(NimBLEClient* pClient);
static NimBLEClient* getClientByID(uint16_t conn_id); static NimBLEClient* getClientByID(uint16_t conn_id);
static NimBLEClient* getClientByPeerAddress(const NimBLEAddress &peer_addr); static NimBLEClient* getClientByPeerAddress(const NimBLEAddress &peer_addr);
static NimBLEClient* getDisconnectedClient(); static NimBLEClient* getDisconnectedClient();
static size_t getClientListSize(); static size_t getClientListSize();
static std::list<NimBLEClient*>* getClientList(); static std::list<NimBLEClient*>* getClientList();
#endif
private: private:
friend class NimBLEServer; #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
friend class NimBLEClient; friend class NimBLEClient;
#endif
#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
friend class NimBLEScan; friend class NimBLEScan;
friend class NimBLEAdvertising; #endif
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
friend class NimBLEServer;
friend class NimBLECharacteristic; friend class NimBLECharacteristic;
#endif
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
friend class NimBLEAdvertising;
#endif
static void onReset(int reason); static void onReset(int reason);
static void onSync(void); static void onSync(void);
static void host_task(void *param); static void host_task(void *param);
static int startSecurity( uint16_t conn_id); static int startSecurity(uint16_t conn_id);
static bool m_synced;
static bool m_synced;
#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
static NimBLEScan* m_pScan; static NimBLEScan* m_pScan;
#endif
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
static NimBLEServer* m_pServer; static NimBLEServer* m_pServer;
#endif
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
static NimBLEAdvertising* m_bleAdvertising; static NimBLEAdvertising* m_bleAdvertising;
static ble_gap_event_listener m_listener; #endif
static uint32_t m_passkey;
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
static std::list <NimBLEClient*> m_cList; static std::list <NimBLEClient*> m_cList;
#endif
static std::list <NimBLEAddress> m_ignoreList; static std::list <NimBLEAddress> m_ignoreList;
static NimBLESecurityCallbacks* m_securityCallbacks; static NimBLESecurityCallbacks* m_securityCallbacks;
static uint32_t m_passkey;
static ble_gap_event_listener m_listener;
public: public:
static gap_event_handler m_customGapHandler; static gap_event_handler m_customGapHandler;

View file

@ -3,7 +3,7 @@
* *
* Created: on March 15 2020 * Created: on March 15 2020
* Author H2zero * Author H2zero
* *
* Originally: * Originally:
* *
* BLEEddystoneTLM.cpp * BLEEddystoneTLM.cpp
@ -26,41 +26,41 @@ static const char LOG_TAG[] = "NimBLEEddystoneTLM";
NimBLEEddystoneTLM::NimBLEEddystoneTLM() { NimBLEEddystoneTLM::NimBLEEddystoneTLM() {
beaconUUID = 0xFEAA; beaconUUID = 0xFEAA;
m_eddystoneData.frameType = EDDYSTONE_TLM_FRAME_TYPE; m_eddystoneData.frameType = EDDYSTONE_TLM_FRAME_TYPE;
m_eddystoneData.version = 0; m_eddystoneData.version = 0;
m_eddystoneData.volt = 3300; // 3300mV = 3.3V m_eddystoneData.volt = 3300; // 3300mV = 3.3V
m_eddystoneData.temp = (uint16_t) ((float) 23.00 * 256); // 8.8 fixed format m_eddystoneData.temp = (uint16_t) ((float) 23.00 * 256); // 8.8 fixed format
m_eddystoneData.advCount = 0; m_eddystoneData.advCount = 0;
m_eddystoneData.tmil = 0; m_eddystoneData.tmil = 0;
} // NimBLEEddystoneTLM } // NimBLEEddystoneTLM
std::string NimBLEEddystoneTLM::getData() { std::string NimBLEEddystoneTLM::getData() {
return std::string((char*) &m_eddystoneData, sizeof(m_eddystoneData)); return std::string((char*) &m_eddystoneData, sizeof(m_eddystoneData));
} // getData } // getData
NimBLEUUID NimBLEEddystoneTLM::getUUID() { NimBLEUUID NimBLEEddystoneTLM::getUUID() {
return NimBLEUUID(beaconUUID); return NimBLEUUID(beaconUUID);
} // getUUID } // getUUID
uint8_t NimBLEEddystoneTLM::getVersion() { uint8_t NimBLEEddystoneTLM::getVersion() {
return m_eddystoneData.version; return m_eddystoneData.version;
} // getVersion } // getVersion
uint16_t NimBLEEddystoneTLM::getVolt() { uint16_t NimBLEEddystoneTLM::getVolt() {
return ENDIAN_CHANGE_U16(m_eddystoneData.volt); return ENDIAN_CHANGE_U16(m_eddystoneData.volt);
} // getVolt } // getVolt
float NimBLEEddystoneTLM::getTemp() { float NimBLEEddystoneTLM::getTemp() {
return ENDIAN_CHANGE_U16(m_eddystoneData.temp) / 256.0f; return ENDIAN_CHANGE_U16(m_eddystoneData.temp) / 256.0f;
} // getTemp } // getTemp
uint32_t NimBLEEddystoneTLM::getCount() { uint32_t NimBLEEddystoneTLM::getCount() {
return ENDIAN_CHANGE_U32(m_eddystoneData.advCount); return ENDIAN_CHANGE_U32(m_eddystoneData.advCount);
} // getCount } // getCount
uint32_t NimBLEEddystoneTLM::getTime() { uint32_t NimBLEEddystoneTLM::getTime() {
return (ENDIAN_CHANGE_U32(m_eddystoneData.tmil)) / 10; return (ENDIAN_CHANGE_U32(m_eddystoneData.tmil)) / 10;
} // getTime } // getTime
std::string NimBLEEddystoneTLM::toString() { std::string NimBLEEddystoneTLM::toString() {
@ -117,36 +117,36 @@ std::string NimBLEEddystoneTLM::toString() {
* Set the raw data for the beacon record. * Set the raw data for the beacon record.
*/ */
void NimBLEEddystoneTLM::setData(const std::string &data) { void NimBLEEddystoneTLM::setData(const std::string &data) {
if (data.length() != sizeof(m_eddystoneData)) { if (data.length() != sizeof(m_eddystoneData)) {
NIMBLE_LOGE(LOG_TAG, "Unable to set the data ... length passed in was %d and expected %d", NIMBLE_LOGE(LOG_TAG, "Unable to set the data ... length passed in was %d and expected %d",
data.length(), sizeof(m_eddystoneData)); data.length(), sizeof(m_eddystoneData));
return; return;
} }
memcpy(&m_eddystoneData, data.data(), data.length()); memcpy(&m_eddystoneData, data.data(), data.length());
} // setData } // setData
void NimBLEEddystoneTLM::setUUID(const NimBLEUUID &l_uuid) { void NimBLEEddystoneTLM::setUUID(const NimBLEUUID &l_uuid) {
beaconUUID = l_uuid.getNative()->u16.value; beaconUUID = l_uuid.getNative()->u16.value;
} // setUUID } // setUUID
void NimBLEEddystoneTLM::setVersion(uint8_t version) { void NimBLEEddystoneTLM::setVersion(uint8_t version) {
m_eddystoneData.version = version; m_eddystoneData.version = version;
} // setVersion } // setVersion
void NimBLEEddystoneTLM::setVolt(uint16_t volt) { void NimBLEEddystoneTLM::setVolt(uint16_t volt) {
m_eddystoneData.volt = volt; m_eddystoneData.volt = volt;
} // setVolt } // setVolt
void NimBLEEddystoneTLM::setTemp(float temp) { void NimBLEEddystoneTLM::setTemp(float temp) {
m_eddystoneData.temp = (uint16_t)temp; m_eddystoneData.temp = (uint16_t)temp;
} // setTemp } // setTemp
void NimBLEEddystoneTLM::setCount(uint32_t advCount) { void NimBLEEddystoneTLM::setCount(uint32_t advCount) {
m_eddystoneData.advCount = advCount; m_eddystoneData.advCount = advCount;
} // setCount } // setCount
void NimBLEEddystoneTLM::setTime(uint32_t tmil) { void NimBLEEddystoneTLM::setTime(uint32_t tmil) {
m_eddystoneData.tmil = tmil; m_eddystoneData.tmil = tmil;
} // setTime } // setTime
#endif #endif

View file

@ -3,7 +3,7 @@
* *
* Created: on March 15 2020 * Created: on March 15 2020
* Author H2zero * Author H2zero
* *
* Originally: * Originally:
* *
* BLEEddystoneTLM.h * BLEEddystoneTLM.h
@ -27,33 +27,33 @@
*/ */
class NimBLEEddystoneTLM { class NimBLEEddystoneTLM {
public: public:
NimBLEEddystoneTLM(); NimBLEEddystoneTLM();
std::string getData(); std::string getData();
NimBLEUUID getUUID(); NimBLEUUID getUUID();
uint8_t getVersion(); uint8_t getVersion();
uint16_t getVolt(); uint16_t getVolt();
float getTemp(); float getTemp();
uint32_t getCount(); uint32_t getCount();
uint32_t getTime(); uint32_t getTime();
std::string toString(); std::string toString();
void setData(const std::string &data); void setData(const std::string &data);
void setUUID(const NimBLEUUID &l_uuid); void setUUID(const NimBLEUUID &l_uuid);
void setVersion(uint8_t version); void setVersion(uint8_t version);
void setVolt(uint16_t volt); void setVolt(uint16_t volt);
void setTemp(float temp); void setTemp(float temp);
void setCount(uint32_t advCount); void setCount(uint32_t advCount);
void setTime(uint32_t tmil); void setTime(uint32_t tmil);
private: private:
uint16_t beaconUUID; uint16_t beaconUUID;
struct { struct {
uint8_t frameType; uint8_t frameType;
uint8_t version; uint8_t version;
uint16_t volt; uint16_t volt;
uint16_t temp; uint16_t temp;
uint32_t advCount; uint32_t advCount;
uint32_t tmil; uint32_t tmil;
} __attribute__((packed)) m_eddystoneData; } __attribute__((packed)) m_eddystoneData;
}; // NimBLEEddystoneTLM }; // NimBLEEddystoneTLM

View file

@ -3,7 +3,7 @@
* *
* Created: on March 15 2020 * Created: on March 15 2020
* Author H2zero * Author H2zero
* *
* Originally: * Originally:
* *
* BLEEddystoneURL.cpp * BLEEddystoneURL.cpp
@ -22,102 +22,102 @@
static const char LOG_TAG[] = "NimBLEEddystoneURL"; static const char LOG_TAG[] = "NimBLEEddystoneURL";
NimBLEEddystoneURL::NimBLEEddystoneURL() { NimBLEEddystoneURL::NimBLEEddystoneURL() {
beaconUUID = 0xFEAA; beaconUUID = 0xFEAA;
lengthURL = 0; lengthURL = 0;
m_eddystoneData.frameType = EDDYSTONE_URL_FRAME_TYPE; m_eddystoneData.frameType = EDDYSTONE_URL_FRAME_TYPE;
m_eddystoneData.advertisedTxPower = 0; m_eddystoneData.advertisedTxPower = 0;
memset(m_eddystoneData.url, 0, sizeof(m_eddystoneData.url)); memset(m_eddystoneData.url, 0, sizeof(m_eddystoneData.url));
} // BLEEddystoneURL } // BLEEddystoneURL
std::string NimBLEEddystoneURL::getData() { std::string NimBLEEddystoneURL::getData() {
return std::string((char*) &m_eddystoneData, sizeof(m_eddystoneData)); return std::string((char*) &m_eddystoneData, sizeof(m_eddystoneData));
} // getData } // getData
NimBLEUUID NimBLEEddystoneURL::getUUID() { NimBLEUUID NimBLEEddystoneURL::getUUID() {
return NimBLEUUID(beaconUUID); return NimBLEUUID(beaconUUID);
} // getUUID } // getUUID
int8_t NimBLEEddystoneURL::getPower() { int8_t NimBLEEddystoneURL::getPower() {
return m_eddystoneData.advertisedTxPower; return m_eddystoneData.advertisedTxPower;
} // getPower } // getPower
std::string NimBLEEddystoneURL::getURL() { std::string NimBLEEddystoneURL::getURL() {
return std::string((char*) &m_eddystoneData.url, sizeof(m_eddystoneData.url)); return std::string((char*) &m_eddystoneData.url, sizeof(m_eddystoneData.url));
} // getURL } // getURL
std::string NimBLEEddystoneURL::getDecodedURL() { std::string NimBLEEddystoneURL::getDecodedURL() {
std::string decodedURL = ""; std::string decodedURL = "";
switch (m_eddystoneData.url[0]) { switch (m_eddystoneData.url[0]) {
case 0x00: case 0x00:
decodedURL += "http://www."; decodedURL += "http://www.";
break; break;
case 0x01: case 0x01:
decodedURL += "https://www."; decodedURL += "https://www.";
break; break;
case 0x02: case 0x02:
decodedURL += "http://"; decodedURL += "http://";
break; break;
case 0x03: case 0x03:
decodedURL += "https://"; decodedURL += "https://";
break; break;
default: default:
decodedURL += m_eddystoneData.url[0]; decodedURL += m_eddystoneData.url[0];
} }
for (int i = 1; i < lengthURL; i++) { for (int i = 1; i < lengthURL; i++) {
if (m_eddystoneData.url[i] > 33 && m_eddystoneData.url[i] < 127) { if (m_eddystoneData.url[i] > 33 && m_eddystoneData.url[i] < 127) {
decodedURL += m_eddystoneData.url[i]; decodedURL += m_eddystoneData.url[i];
} else { } else {
switch (m_eddystoneData.url[i]) { switch (m_eddystoneData.url[i]) {
case 0x00: case 0x00:
decodedURL += ".com/"; decodedURL += ".com/";
break; break;
case 0x01: case 0x01:
decodedURL += ".org/"; decodedURL += ".org/";
break; break;
case 0x02: case 0x02:
decodedURL += ".edu/"; decodedURL += ".edu/";
break; break;
case 0x03: case 0x03:
decodedURL += ".net/"; decodedURL += ".net/";
break; break;
case 0x04: case 0x04:
decodedURL += ".info/"; decodedURL += ".info/";
break; break;
case 0x05: case 0x05:
decodedURL += ".biz/"; decodedURL += ".biz/";
break; break;
case 0x06: case 0x06:
decodedURL += ".gov/"; decodedURL += ".gov/";
break; break;
case 0x07: case 0x07:
decodedURL += ".com"; decodedURL += ".com";
break; break;
case 0x08: case 0x08:
decodedURL += ".org"; decodedURL += ".org";
break; break;
case 0x09: case 0x09:
decodedURL += ".edu"; decodedURL += ".edu";
break; break;
case 0x0A: case 0x0A:
decodedURL += ".net"; decodedURL += ".net";
break; break;
case 0x0B: case 0x0B:
decodedURL += ".info"; decodedURL += ".info";
break; break;
case 0x0C: case 0x0C:
decodedURL += ".biz"; decodedURL += ".biz";
break; break;
case 0x0D: case 0x0D:
decodedURL += ".gov"; decodedURL += ".gov";
break; break;
default: default:
break; break;
} }
} }
} }
return decodedURL; return decodedURL;
} // getDecodedURL } // getDecodedURL
@ -126,29 +126,29 @@ std::string NimBLEEddystoneURL::getDecodedURL() {
* Set the raw data for the beacon record. * Set the raw data for the beacon record.
*/ */
void NimBLEEddystoneURL::setData(const std::string &data) { void NimBLEEddystoneURL::setData(const std::string &data) {
if (data.length() > sizeof(m_eddystoneData)) { if (data.length() > sizeof(m_eddystoneData)) {
NIMBLE_LOGE(LOG_TAG, "Unable to set the data ... length passed in was %d and max expected %d", NIMBLE_LOGE(LOG_TAG, "Unable to set the data ... length passed in was %d and max expected %d",
data.length(), sizeof(m_eddystoneData)); data.length(), sizeof(m_eddystoneData));
return; return;
} }
memset(&m_eddystoneData, 0, sizeof(m_eddystoneData)); memset(&m_eddystoneData, 0, sizeof(m_eddystoneData));
memcpy(&m_eddystoneData, data.data(), data.length()); memcpy(&m_eddystoneData, data.data(), data.length());
lengthURL = data.length() - (sizeof(m_eddystoneData) - sizeof(m_eddystoneData.url)); lengthURL = data.length() - (sizeof(m_eddystoneData) - sizeof(m_eddystoneData.url));
} // setData } // setData
void NimBLEEddystoneURL::setUUID(const NimBLEUUID &l_uuid) { void NimBLEEddystoneURL::setUUID(const NimBLEUUID &l_uuid) {
beaconUUID = l_uuid.getNative()->u16.value; beaconUUID = l_uuid.getNative()->u16.value;
} // setUUID } // setUUID
void NimBLEEddystoneURL::setPower(int8_t advertisedTxPower) { void NimBLEEddystoneURL::setPower(int8_t advertisedTxPower) {
m_eddystoneData.advertisedTxPower = advertisedTxPower; m_eddystoneData.advertisedTxPower = advertisedTxPower;
} // setPower } // setPower
void NimBLEEddystoneURL::setURL(const std::string &url) { void NimBLEEddystoneURL::setURL(const std::string &url) {
if (url.length() > sizeof(m_eddystoneData.url)) { if (url.length() > sizeof(m_eddystoneData.url)) {
NIMBLE_LOGE(LOG_TAG, "Unable to set the url ... length passed in was %d and max expected %d", NIMBLE_LOGE(LOG_TAG, "Unable to set the url ... length passed in was %d and max expected %d",
url.length(), sizeof(m_eddystoneData.url)); url.length(), sizeof(m_eddystoneData.url));
return; return;
} }
memset(m_eddystoneData.url, 0, sizeof(m_eddystoneData.url)); memset(m_eddystoneData.url, 0, sizeof(m_eddystoneData.url));
memcpy(m_eddystoneData.url, url.data(), url.length()); memcpy(m_eddystoneData.url, url.data(), url.length());

View file

@ -3,7 +3,7 @@
* *
* Created: on March 15 2020 * Created: on March 15 2020
* Author H2zero * Author H2zero
* *
* Originally: * Originally:
* *
* BLEEddystoneURL.h * BLEEddystoneURL.h
@ -27,25 +27,25 @@
*/ */
class NimBLEEddystoneURL { class NimBLEEddystoneURL {
public: public:
NimBLEEddystoneURL(); NimBLEEddystoneURL();
std::string getData(); std::string getData();
NimBLEUUID getUUID(); NimBLEUUID getUUID();
int8_t getPower(); int8_t getPower();
std::string getURL(); std::string getURL();
std::string getDecodedURL(); std::string getDecodedURL();
void setData(const std::string &data); void setData(const std::string &data);
void setUUID(const NimBLEUUID &l_uuid); void setUUID(const NimBLEUUID &l_uuid);
void setPower(int8_t advertisedTxPower); void setPower(int8_t advertisedTxPower);
void setURL(const std::string &url); void setURL(const std::string &url);
private: private:
uint16_t beaconUUID; uint16_t beaconUUID;
uint8_t lengthURL; uint8_t lengthURL;
struct { struct {
uint8_t frameType; uint8_t frameType;
int8_t advertisedTxPower; int8_t advertisedTxPower;
uint8_t url[16]; uint8_t url[16];
} __attribute__((packed)) m_eddystoneData; } __attribute__((packed)) m_eddystoneData;
}; // NIMBLEEddystoneURL }; // NIMBLEEddystoneURL

View file

@ -14,11 +14,11 @@
#include "modlog/modlog.h" #include "modlog/modlog.h"
// If Arduino is being used, strip out the colors and ignore log printing below ui setting. // If Arduino is being used, strip out the colors and ignore log printing below ui setting.
// Note: because CONFIG_LOG_DEFAULT_LEVEL is set at ERROR in Arduino we must use MODLOG_DFLT(ERROR // Note: because CONFIG_LOG_DEFAULT_LEVEL is set at ERROR in Arduino we must use MODLOG_DFLT(ERROR
// otherwise no messages will be printed above that level. // otherwise no messages will be printed above that level.
#ifdef ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP32
#ifndef CORE_DEBUG_LEVEL #ifndef CORE_DEBUG_LEVEL
#define CORE_DEBUG_LEVEL CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL #define CORE_DEBUG_LEVEL CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL
#endif #endif
@ -48,7 +48,7 @@
#define NIMBLE_LOGC( tag, format, ... ) MODLOG_DFLT(CRITICAL, "CRIT %s: "#format"\n",tag,##__VA_ARGS__) #define NIMBLE_LOGC( tag, format, ... ) MODLOG_DFLT(CRITICAL, "CRIT %s: "#format"\n",tag,##__VA_ARGS__)
#else #else
#define NIMBLE_LOGE( tag, format, ... ) MODLOG_DFLT(ERROR, "\033[0;31mE %s: "#format"\033[0m\n",tag,##__VA_ARGS__) #define NIMBLE_LOGE( tag, format, ... ) MODLOG_DFLT(ERROR, "\033[0;31mE %s: "#format"\033[0m\n",tag,##__VA_ARGS__)
#define NIMBLE_LOGW( tag, format, ... ) MODLOG_DFLT(WARN, "\033[0;33mW %s: "#format"\033[0m\n",tag,##__VA_ARGS__) #define NIMBLE_LOGW( tag, format, ... ) MODLOG_DFLT(WARN, "\033[0;33mW %s: "#format"\033[0m\n",tag,##__VA_ARGS__)
#define NIMBLE_LOGI( tag, format, ... ) MODLOG_DFLT(INFO, "\033[0;32mI %s: "#format"\033[0m\n",tag,##__VA_ARGS__) #define NIMBLE_LOGI( tag, format, ... ) MODLOG_DFLT(INFO, "\033[0;32mI %s: "#format"\033[0m\n",tag,##__VA_ARGS__)

View file

@ -3,7 +3,7 @@
* *
* Created: on Jan 27 2020 * Created: on Jan 27 2020
* Author H2zero * Author H2zero
* *
* Originally: * Originally:
* *
* BLERemoteCharacteristic.cpp * BLERemoteCharacteristic.cpp
@ -15,6 +15,9 @@
#include "sdkconfig.h" #include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED) #if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h"
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
#include "NimBLERemoteCharacteristic.h" #include "NimBLERemoteCharacteristic.h"
#include "NimBLEUtils.h" #include "NimBLEUtils.h"
#include "NimBLELog.h" #include "NimBLELog.h"
@ -35,13 +38,13 @@ static const char* LOG_TAG = "NimBLERemoteCharacteristic";
NimBLERemoteCharacteristic::NimBLERemoteCharacteristic(NimBLERemoteService *pRemoteService, const struct ble_gatt_chr *chr) { NimBLERemoteCharacteristic::NimBLERemoteCharacteristic(NimBLERemoteService *pRemoteService, const struct ble_gatt_chr *chr) {
switch (chr->uuid.u.type) { switch (chr->uuid.u.type) {
case BLE_UUID_TYPE_16: case BLE_UUID_TYPE_16:
m_uuid = NimBLEUUID(chr->uuid.u16.value); m_uuid = NimBLEUUID(chr->uuid.u16.value);
break; break;
case BLE_UUID_TYPE_32: case BLE_UUID_TYPE_32:
m_uuid = NimBLEUUID(chr->uuid.u32.value); m_uuid = NimBLEUUID(chr->uuid.u32.value);
break; break;
case BLE_UUID_TYPE_128: case BLE_UUID_TYPE_128:
m_uuid = NimBLEUUID(const_cast<ble_uuid128_t*>(&chr->uuid.u128)); m_uuid = NimBLEUUID(const_cast<ble_uuid128_t*>(&chr->uuid.u128));
break; break;
default: default:
@ -136,14 +139,14 @@ bool NimBLERemoteCharacteristic::canWriteNoResponse() {
/** /**
* @brief Callback used by the API when a descriptor is discovered or search complete. * @brief Callback used by the API when a descriptor is discovered or search complete.
*/ */
int NimBLERemoteCharacteristic::descriptorDiscCB(uint16_t conn_handle, int NimBLERemoteCharacteristic::descriptorDiscCB(uint16_t conn_handle,
const struct ble_gatt_error *error, const struct ble_gatt_error *error,
uint16_t chr_val_handle, uint16_t chr_val_handle,
const struct ble_gatt_dsc *dsc, const struct ble_gatt_dsc *dsc,
void *arg) void *arg)
{ {
NIMBLE_LOGD(LOG_TAG,"Descriptor Discovered >> status: %d handle: %d", error->status, conn_handle); NIMBLE_LOGD(LOG_TAG,"Descriptor Discovered >> status: %d handle: %d", error->status, conn_handle);
NimBLERemoteCharacteristic *characteristic = (NimBLERemoteCharacteristic*)arg; NimBLERemoteCharacteristic *characteristic = (NimBLERemoteCharacteristic*)arg;
int rc=0; int rc=0;
@ -151,13 +154,13 @@ int NimBLERemoteCharacteristic::descriptorDiscCB(uint16_t conn_handle,
if(characteristic->getRemoteService()->getClient()->getConnId() != conn_handle){ if(characteristic->getRemoteService()->getClient()->getConnId() != conn_handle){
return 0; return 0;
} }
switch (error->status) { switch (error->status) {
case 0: { case 0: {
// Found a descriptor - add it to the map // Found a descriptor - add it to the map
NimBLERemoteDescriptor* pNewRemoteDescriptor = new NimBLERemoteDescriptor(characteristic, dsc); NimBLERemoteDescriptor* pNewRemoteDescriptor = new NimBLERemoteDescriptor(characteristic, dsc);
characteristic->m_descriptorMap.insert(std::pair<std::string, NimBLERemoteDescriptor*>(pNewRemoteDescriptor->getUUID().toString(), pNewRemoteDescriptor)); characteristic->m_descriptorMap.insert(std::pair<std::string, NimBLERemoteDescriptor*>(pNewRemoteDescriptor->getUUID().toString(), pNewRemoteDescriptor));
break; break;
} }
case BLE_HS_EDONE:{ case BLE_HS_EDONE:{
@ -188,9 +191,9 @@ bool NimBLERemoteCharacteristic::retrieveDescriptors(uint16_t endHdl) {
int rc = 0; int rc = 0;
//removeDescriptors(); // Remove any existing descriptors. //removeDescriptors(); // Remove any existing descriptors.
m_semaphoreGetDescEvt.take("retrieveDescriptors"); m_semaphoreGetDescEvt.take("retrieveDescriptors");
rc = ble_gattc_disc_all_dscs(getRemoteService()->getClient()->getConnId(), rc = ble_gattc_disc_all_dscs(getRemoteService()->getClient()->getConnId(),
m_handle, m_handle,
endHdl, endHdl,
@ -201,13 +204,13 @@ bool NimBLERemoteCharacteristic::retrieveDescriptors(uint16_t endHdl) {
m_semaphoreGetDescEvt.give(); m_semaphoreGetDescEvt.give();
return false; return false;
} }
if(m_semaphoreGetDescEvt.wait("retrieveCharacteristics") != 0) { if(m_semaphoreGetDescEvt.wait("retrieveCharacteristics") != 0) {
// if there was an error release the resources // if there was an error release the resources
//removeDescriptors(); //removeDescriptors();
return false; return false;
} }
return true; return true;
NIMBLE_LOGD(LOG_TAG, "<< retrieveDescriptors(): Found %d descriptors.", m_descriptorMap.size()); NIMBLE_LOGD(LOG_TAG, "<< retrieveDescriptors(): Found %d descriptors.", m_descriptorMap.size());
} // getDescriptors } // getDescriptors
@ -215,7 +218,7 @@ bool NimBLERemoteCharacteristic::retrieveDescriptors(uint16_t endHdl) {
/** /**
* @brief Retrieve the map of descriptors keyed by UUID. * @brief Retrieve the map of descriptors keyed by UUID.
*/ */
std::map<std::string, NimBLERemoteDescriptor*>* NimBLERemoteCharacteristic::getDescriptors() { std::map<std::string, NimBLERemoteDescriptor*>* NimBLERemoteCharacteristic::getDescriptors() {
return &m_descriptorMap; return &m_descriptorMap;
} // getDescriptors } // getDescriptors
@ -313,7 +316,7 @@ uint8_t NimBLERemoteCharacteristic::readUInt8() {
return 0; return 0;
} // readUInt8 } // readUInt8
/** /**
* @brief Read the value of the remote characteristic. * @brief Read the value of the remote characteristic.
* @return The value of the remote characteristic. * @return The value of the remote characteristic.
@ -346,7 +349,7 @@ std::string NimBLERemoteCharacteristic::readValue() {
m_semaphoreReadCharEvt.give(0); m_semaphoreReadCharEvt.give(0);
return ""; return "";
} }
rc = m_semaphoreReadCharEvt.wait("readValue"); rc = m_semaphoreReadCharEvt.wait("readValue");
switch(rc){ switch(rc){
case 0: case 0:
@ -356,19 +359,19 @@ std::string NimBLERemoteCharacteristic::readValue() {
// Characteristic is not long-readable, return with what we have. // Characteristic is not long-readable, return with what we have.
case BLE_HS_ATT_ERR(BLE_ATT_ERR_ATTR_NOT_LONG): case BLE_HS_ATT_ERR(BLE_ATT_ERR_ATTR_NOT_LONG):
NIMBLE_LOGI(LOG_TAG, "Attribute not long"); NIMBLE_LOGI(LOG_TAG, "Attribute not long");
rc = 0; rc = 0;
break; break;
case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_AUTHEN): case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_AUTHEN):
case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_AUTHOR): case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_AUTHOR):
case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_ENC): case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_ENC):
if (retryCount && pClient->secureConnection()) if (retryCount && pClient->secureConnection())
break; break;
/* Else falls through. */ /* Else falls through. */
default: default:
return ""; return "";
} }
} while(rc != 0 && retryCount--); } while(rc != 0 && retryCount--);
NIMBLE_LOGD(LOG_TAG, "<< readValue(): length: %d", m_value.length()); NIMBLE_LOGD(LOG_TAG, "<< readValue(): length: %d", m_value.length());
return m_value; return m_value;
} // readValue } // readValue
@ -380,11 +383,11 @@ std::string NimBLERemoteCharacteristic::readValue() {
*/ */
int NimBLERemoteCharacteristic::onReadCB(uint16_t conn_handle, int NimBLERemoteCharacteristic::onReadCB(uint16_t conn_handle,
const struct ble_gatt_error *error, const struct ble_gatt_error *error,
struct ble_gatt_attr *attr, void *arg) struct ble_gatt_attr *attr, void *arg)
{ {
NimBLERemoteCharacteristic* characteristic = (NimBLERemoteCharacteristic*)arg; NimBLERemoteCharacteristic* characteristic = (NimBLERemoteCharacteristic*)arg;
uint16_t conn_id = characteristic->getRemoteService()->getClient()->getConnId(); uint16_t conn_id = characteristic->getRemoteService()->getClient()->getConnId();
// Make sure the read is for this client // Make sure the read is for this client
if(conn_id != conn_handle) { if(conn_id != conn_handle) {
return 0; return 0;
@ -401,7 +404,7 @@ int NimBLERemoteCharacteristic::onReadCB(uint16_t conn_handle,
} }
// Read complete release semaphore and let the app can continue. // Read complete release semaphore and let the app can continue.
characteristic->m_semaphoreReadCharEvt.give(error->status); characteristic->m_semaphoreReadCharEvt.give(error->status);
return 0; return 0;
} }
@ -421,7 +424,7 @@ bool NimBLERemoteCharacteristic::registerForNotify(notify_callback notifyCallbac
uint8_t val[] = {0x01, 0x00}; uint8_t val[] = {0x01, 0x00};
NimBLERemoteDescriptor* desc = getDescriptor(NimBLEUUID((uint16_t)0x2902)); NimBLERemoteDescriptor* desc = getDescriptor(NimBLEUUID((uint16_t)0x2902));
if(desc == nullptr) if(desc == nullptr)
return false; return false;
if(notifyCallback != nullptr){ if(notifyCallback != nullptr){
@ -435,7 +438,7 @@ bool NimBLERemoteCharacteristic::registerForNotify(notify_callback notifyCallbac
} }
NIMBLE_LOGD(LOG_TAG, "<< registerForNotify()"); NIMBLE_LOGD(LOG_TAG, "<< registerForNotify()");
return desc->writeValue(val, 2, response); return desc->writeValue(val, 2, response);
} // registerForNotify } // registerForNotify
@ -474,11 +477,11 @@ std::string NimBLERemoteCharacteristic::toString() {
res += " 0x"; res += " 0x";
snprintf(val, sizeof(val), "%02x", m_charProp); snprintf(val, sizeof(val), "%02x", m_charProp);
res += val; res += val;
for (auto &myPair : m_descriptorMap) { for (auto &myPair : m_descriptorMap) {
res += "\n" + myPair.second->toString(); res += "\n" + myPair.second->toString();
} }
return res; return res;
} // toString } // toString
@ -515,20 +518,20 @@ bool NimBLERemoteCharacteristic::writeValue(uint8_t newValue, bool response) {
* @return false if not connected or cant perform write for some reason. * @return false if not connected or cant perform write for some reason.
*/ */
bool NimBLERemoteCharacteristic::writeValue(const uint8_t* data, size_t length, bool response) { bool NimBLERemoteCharacteristic::writeValue(const uint8_t* data, size_t length, bool response) {
NIMBLE_LOGD(LOG_TAG, ">> writeValue(), length: %d", length); NIMBLE_LOGD(LOG_TAG, ">> writeValue(), length: %d", length);
NimBLEClient* pClient = getRemoteService()->getClient(); NimBLEClient* pClient = getRemoteService()->getClient();
int rc = 0; int rc = 0;
int retryCount = 1; int retryCount = 1;
uint16_t mtu; uint16_t mtu;
// Check to see that we are connected. // Check to see that we are connected.
if (!pClient->isConnected()) { if (!pClient->isConnected()) {
NIMBLE_LOGE(LOG_TAG, "Disconnected"); NIMBLE_LOGE(LOG_TAG, "Disconnected");
return false; return false;
} }
mtu = ble_att_mtu(pClient->getConnId()) - 3; mtu = ble_att_mtu(pClient->getConnId()) - 3;
// Check if the data length is longer than we can write in 1 connection event. // Check if the data length is longer than we can write in 1 connection event.
@ -537,7 +540,7 @@ bool NimBLERemoteCharacteristic::writeValue(const uint8_t* data, size_t length,
rc = ble_gattc_write_no_rsp_flat(pClient->getConnId(), m_handle, data, length); rc = ble_gattc_write_no_rsp_flat(pClient->getConnId(), m_handle, data, length);
return (rc==0); return (rc==0);
} }
do { do {
m_semaphoreWriteCharEvt.take("writeValue"); m_semaphoreWriteCharEvt.take("writeValue");
@ -558,26 +561,26 @@ bool NimBLERemoteCharacteristic::writeValue(const uint8_t* data, size_t length,
m_semaphoreWriteCharEvt.give(); m_semaphoreWriteCharEvt.give();
return false; return false;
} }
rc = m_semaphoreWriteCharEvt.wait("writeValue"); rc = m_semaphoreWriteCharEvt.wait("writeValue");
switch(rc){ switch(rc){
case 0: case 0:
case BLE_HS_EDONE: case BLE_HS_EDONE:
rc = 0; rc = 0;
break; break;
case BLE_HS_ATT_ERR(BLE_ATT_ERR_ATTR_NOT_LONG): case BLE_HS_ATT_ERR(BLE_ATT_ERR_ATTR_NOT_LONG):
NIMBLE_LOGE(LOG_TAG, "Long write not supported by peer; Truncating length to %d", mtu); NIMBLE_LOGE(LOG_TAG, "Long write not supported by peer; Truncating length to %d", mtu);
retryCount++; retryCount++;
length = mtu; length = mtu;
break; break;
case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_AUTHEN): case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_AUTHEN):
case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_AUTHOR): case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_AUTHOR):
case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_ENC): case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_ENC):
if (retryCount && pClient->secureConnection()) if (retryCount && pClient->secureConnection())
break; break;
/* Else falls through. */ /* Else falls through. */
default: default:
return false; return false;
} }
@ -594,17 +597,17 @@ bool NimBLERemoteCharacteristic::writeValue(const uint8_t* data, size_t length,
*/ */
int NimBLERemoteCharacteristic::onWriteCB(uint16_t conn_handle, int NimBLERemoteCharacteristic::onWriteCB(uint16_t conn_handle,
const struct ble_gatt_error *error, const struct ble_gatt_error *error,
struct ble_gatt_attr *attr, void *arg) struct ble_gatt_attr *attr, void *arg)
{ {
NimBLERemoteCharacteristic* characteristic = (NimBLERemoteCharacteristic*)arg; NimBLERemoteCharacteristic* characteristic = (NimBLERemoteCharacteristic*)arg;
// Make sure the discovery is for this device // Make sure the discovery is for this device
if(characteristic->getRemoteService()->getClient()->getConnId() != conn_handle){ if(characteristic->getRemoteService()->getClient()->getConnId() != conn_handle){
return 0; return 0;
} }
NIMBLE_LOGI(LOG_TAG, "Write complete; status=%d conn_handle=%d", error->status, conn_handle); NIMBLE_LOGI(LOG_TAG, "Write complete; status=%d conn_handle=%d", error->status, conn_handle);
characteristic->m_semaphoreWriteCharEvt.give(error->status); characteristic->m_semaphoreWriteCharEvt.give(error->status);
return 0; return 0;
@ -649,4 +652,6 @@ void NimBLERemoteCharacteristic::releaseSemaphores() {
m_semaphoreGetDescEvt.give(1); m_semaphoreGetDescEvt.give(1);
m_semaphoreReadCharEvt.give(1); m_semaphoreReadCharEvt.give(1);
} }
#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
#endif /* CONFIG_BT_ENABLED */ #endif /* CONFIG_BT_ENABLED */

View file

@ -3,7 +3,7 @@
* *
* Created: on Jan 27 2020 * Created: on Jan 27 2020
* Author H2zero * Author H2zero
* *
* Originally: * Originally:
* *
* BLERemoteCharacteristic.h * BLERemoteCharacteristic.h
@ -17,6 +17,9 @@
#include "sdkconfig.h" #include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED) #if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h"
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
//#include "NimBLEUUID.h" //#include "NimBLEUUID.h"
//#include "FreeRTOS.h" //#include "FreeRTOS.h"
#include "NimBLERemoteService.h" #include "NimBLERemoteService.h"
@ -66,7 +69,7 @@ public:
private: private:
NimBLERemoteCharacteristic(NimBLERemoteService *pRemoteservice, const struct ble_gatt_chr *chr); NimBLERemoteCharacteristic(NimBLERemoteService *pRemoteservice, const struct ble_gatt_chr *chr);
friend class NimBLEClient; friend class NimBLEClient;
friend class NimBLERemoteService; friend class NimBLERemoteService;
friend class NimBLERemoteDescriptor; friend class NimBLERemoteDescriptor;
@ -80,7 +83,7 @@ private:
static int descriptorDiscCB(uint16_t conn_handle, const struct ble_gatt_error *error, static int descriptorDiscCB(uint16_t conn_handle, const struct ble_gatt_error *error,
uint16_t chr_val_handle, const struct ble_gatt_dsc *dsc, uint16_t chr_val_handle, const struct ble_gatt_dsc *dsc,
void *arg); void *arg);
// Private properties // Private properties
NimBLEUUID m_uuid; NimBLEUUID m_uuid;
uint8_t m_charProp; uint8_t m_charProp;
@ -98,5 +101,7 @@ private:
// We maintain a map of descriptors owned by this characteristic keyed by a string representation of the UUID. // We maintain a map of descriptors owned by this characteristic keyed by a string representation of the UUID.
std::map<std::string, NimBLERemoteDescriptor*> m_descriptorMap; std::map<std::string, NimBLERemoteDescriptor*> m_descriptorMap;
}; // BLERemoteCharacteristic }; // BLERemoteCharacteristic
#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
#endif /* CONFIG_BT_ENABLED */ #endif /* CONFIG_BT_ENABLED */
#endif /* COMPONENTS_NIMBLEREMOTECHARACTERISTIC_H_ */ #endif /* COMPONENTS_NIMBLEREMOTECHARACTERISTIC_H_ */

View file

@ -3,7 +3,7 @@
* *
* Created: on Jan 27 2020 * Created: on Jan 27 2020
* Author H2zero * Author H2zero
* *
* Originally: * Originally:
* *
* BLERemoteDescriptor.cpp * BLERemoteDescriptor.cpp
@ -14,6 +14,9 @@
#include "sdkconfig.h" #include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED) #if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h"
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
#include "NimBLERemoteDescriptor.h" #include "NimBLERemoteDescriptor.h"
#include "NimBLEUtils.h" #include "NimBLEUtils.h"
#include "NimBLELog.h" #include "NimBLELog.h"
@ -25,17 +28,17 @@ static const char* LOG_TAG = "NimBLERemoteDescriptor";
* @param [in] Reference to the Characteristic that this belongs to. * @param [in] Reference to the Characteristic that this belongs to.
* @param [in] Reference to the struct that contains the descriptor information. * @param [in] Reference to the struct that contains the descriptor information.
*/ */
NimBLERemoteDescriptor::NimBLERemoteDescriptor(NimBLERemoteCharacteristic* pRemoteCharacteristic, NimBLERemoteDescriptor::NimBLERemoteDescriptor(NimBLERemoteCharacteristic* pRemoteCharacteristic,
const struct ble_gatt_dsc *dsc) const struct ble_gatt_dsc *dsc)
{ {
switch (dsc->uuid.u.type) { switch (dsc->uuid.u.type) {
case BLE_UUID_TYPE_16: case BLE_UUID_TYPE_16:
m_uuid = NimBLEUUID(dsc->uuid.u16.value); m_uuid = NimBLEUUID(dsc->uuid.u16.value);
break; break;
case BLE_UUID_TYPE_32: case BLE_UUID_TYPE_32:
m_uuid = NimBLEUUID(dsc->uuid.u32.value); m_uuid = NimBLEUUID(dsc->uuid.u32.value);
break; break;
case BLE_UUID_TYPE_128: case BLE_UUID_TYPE_128:
m_uuid = NimBLEUUID(const_cast<ble_uuid128_t*>(&dsc->uuid.u128)); m_uuid = NimBLEUUID(const_cast<ble_uuid128_t*>(&dsc->uuid.u128));
break; break;
default: default:
@ -44,7 +47,7 @@ NimBLERemoteDescriptor::NimBLERemoteDescriptor(NimBLERemoteCharacteristic* pRemo
} }
m_handle = dsc->handle; m_handle = dsc->handle;
m_pRemoteCharacteristic = pRemoteCharacteristic; m_pRemoteCharacteristic = pRemoteCharacteristic;
} }
@ -81,18 +84,18 @@ NimBLEUUID NimBLERemoteDescriptor::getUUID() {
*/ */
int NimBLERemoteDescriptor::onReadCB(uint16_t conn_handle, int NimBLERemoteDescriptor::onReadCB(uint16_t conn_handle,
const struct ble_gatt_error *error, const struct ble_gatt_error *error,
struct ble_gatt_attr *attr, void *arg) struct ble_gatt_attr *attr, void *arg)
{ {
NimBLERemoteDescriptor* desc = (NimBLERemoteDescriptor*)arg; NimBLERemoteDescriptor* desc = (NimBLERemoteDescriptor*)arg;
uint16_t conn_id = desc->getRemoteCharacteristic()->getRemoteService()->getClient()->getConnId(); uint16_t conn_id = desc->getRemoteCharacteristic()->getRemoteService()->getClient()->getConnId();
// Make sure the discovery is for this device // Make sure the discovery is for this device
if(conn_id != conn_handle){ if(conn_id != conn_handle){
return 0; return 0;
} }
NIMBLE_LOGD(LOG_TAG, "Read complete; status=%d conn_handle=%d", error->status, conn_handle); NIMBLE_LOGD(LOG_TAG, "Read complete; status=%d conn_handle=%d", error->status, conn_handle);
if(error->status == 0){ if(error->status == 0){
if(attr){ if(attr){
NIMBLE_LOGD(LOG_TAG, "Got %d bytes", attr->om->om_len); NIMBLE_LOGD(LOG_TAG, "Got %d bytes", attr->om->om_len);
@ -110,23 +113,23 @@ int NimBLERemoteDescriptor::onReadCB(uint16_t conn_handle,
std::string NimBLERemoteDescriptor::readValue() { std::string NimBLERemoteDescriptor::readValue() {
NIMBLE_LOGD(LOG_TAG, ">> Descriptor readValue: %s", toString().c_str()); NIMBLE_LOGD(LOG_TAG, ">> Descriptor readValue: %s", toString().c_str());
int rc = 0; int rc = 0;
int retryCount = 1; int retryCount = 1;
// Clear the value before reading. // Clear the value before reading.
m_value = ""; m_value = "";
NimBLEClient* pClient = getRemoteCharacteristic()->getRemoteService()->getClient(); NimBLEClient* pClient = getRemoteCharacteristic()->getRemoteService()->getClient();
// Check to see that we are connected. // Check to see that we are connected.
if (!pClient->isConnected()) { if (!pClient->isConnected()) {
NIMBLE_LOGE(LOG_TAG, "Disconnected"); NIMBLE_LOGE(LOG_TAG, "Disconnected");
return ""; return "";
} }
do { do {
m_semaphoreReadDescrEvt.take("ReadDescriptor"); m_semaphoreReadDescrEvt.take("ReadDescriptor");
rc = ble_gattc_read_long(pClient->getConnId(), m_handle, 0, rc = ble_gattc_read_long(pClient->getConnId(), m_handle, 0,
NimBLERemoteDescriptor::onReadCB, NimBLERemoteDescriptor::onReadCB,
this); this);
@ -136,7 +139,7 @@ std::string NimBLERemoteDescriptor::readValue() {
m_semaphoreReadDescrEvt.give(0); m_semaphoreReadDescrEvt.give(0);
return ""; return "";
} }
rc = m_semaphoreReadDescrEvt.wait("ReadDescriptor"); rc = m_semaphoreReadDescrEvt.wait("ReadDescriptor");
switch(rc){ switch(rc){
@ -147,14 +150,14 @@ std::string NimBLERemoteDescriptor::readValue() {
// Descriptor is not long-readable, return with what we have. // Descriptor is not long-readable, return with what we have.
case BLE_HS_ATT_ERR(BLE_ATT_ERR_ATTR_NOT_LONG): case BLE_HS_ATT_ERR(BLE_ATT_ERR_ATTR_NOT_LONG):
NIMBLE_LOGI(LOG_TAG, "Attribute not long"); NIMBLE_LOGI(LOG_TAG, "Attribute not long");
rc = 0; rc = 0;
break; break;
case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_AUTHEN): case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_AUTHEN):
case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_AUTHOR): case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_AUTHOR):
case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_ENC): case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_ENC):
if (retryCount && pClient->secureConnection()) if (retryCount && pClient->secureConnection())
break; break;
/* Else falls through. */ /* Else falls through. */
default: default:
return ""; return "";
} }
@ -202,7 +205,7 @@ std::string NimBLERemoteDescriptor::toString() {
res += ", handle: "; res += ", handle: ";
snprintf(val, sizeof(val), "%d", getHandle()); snprintf(val, sizeof(val), "%d", getHandle());
res += val; res += val;
return res; return res;
} // toString } // toString
@ -213,10 +216,10 @@ std::string NimBLERemoteDescriptor::toString() {
*/ */
int NimBLERemoteDescriptor::onWriteCB(uint16_t conn_handle, int NimBLERemoteDescriptor::onWriteCB(uint16_t conn_handle,
const struct ble_gatt_error *error, const struct ble_gatt_error *error,
struct ble_gatt_attr *attr, void *arg) struct ble_gatt_attr *attr, void *arg)
{ {
NimBLERemoteDescriptor* descriptor = (NimBLERemoteDescriptor*)arg; NimBLERemoteDescriptor* descriptor = (NimBLERemoteDescriptor*)arg;
// Make sure the discovery is for this device // Make sure the discovery is for this device
if(descriptor->getRemoteCharacteristic()->getRemoteService()->getClient()->getConnId() != conn_handle){ if(descriptor->getRemoteCharacteristic()->getRemoteService()->getClient()->getConnId() != conn_handle){
return 0; return 0;
@ -239,19 +242,19 @@ int NimBLERemoteDescriptor::onWriteCB(uint16_t conn_handle,
bool NimBLERemoteDescriptor::writeValue(const uint8_t* data, size_t length, bool response) { bool NimBLERemoteDescriptor::writeValue(const uint8_t* data, size_t length, bool response) {
NIMBLE_LOGD(LOG_TAG, ">> Descriptor writeValue: %s", toString().c_str()); NIMBLE_LOGD(LOG_TAG, ">> Descriptor writeValue: %s", toString().c_str());
NimBLEClient* pClient = getRemoteCharacteristic()->getRemoteService()->getClient(); NimBLEClient* pClient = getRemoteCharacteristic()->getRemoteService()->getClient();
int rc = 0; int rc = 0;
int retryCount = 1; int retryCount = 1;
uint16_t mtu; uint16_t mtu;
// Check to see that we are connected. // Check to see that we are connected.
if (!pClient->isConnected()) { if (!pClient->isConnected()) {
NIMBLE_LOGE(LOG_TAG, "Disconnected"); NIMBLE_LOGE(LOG_TAG, "Disconnected");
return false; return false;
} }
mtu = ble_att_mtu(pClient->getConnId()) - 3; mtu = ble_att_mtu(pClient->getConnId()) - 3;
// Check if the data length is longer than we can write in 1 connection event. // Check if the data length is longer than we can write in 1 connection event.
@ -260,10 +263,10 @@ bool NimBLERemoteDescriptor::writeValue(const uint8_t* data, size_t length, bool
rc = ble_gattc_write_no_rsp_flat(pClient->getConnId(), m_handle, data, length); rc = ble_gattc_write_no_rsp_flat(pClient->getConnId(), m_handle, data, length);
return (rc == 0); return (rc == 0);
} }
do { do {
m_semaphoreDescWrite.take("WriteDescriptor"); m_semaphoreDescWrite.take("WriteDescriptor");
if(length > mtu) { if(length > mtu) {
NIMBLE_LOGI(LOG_TAG,"long write %d bytes", length); NIMBLE_LOGI(LOG_TAG,"long write %d bytes", length);
os_mbuf *om = ble_hs_mbuf_from_flat(data, length); os_mbuf *om = ble_hs_mbuf_from_flat(data, length);
@ -282,7 +285,7 @@ bool NimBLERemoteDescriptor::writeValue(const uint8_t* data, size_t length, bool
m_semaphoreDescWrite.give(); m_semaphoreDescWrite.give();
return false; return false;
} }
rc = m_semaphoreDescWrite.wait("WriteDescriptor"); rc = m_semaphoreDescWrite.wait("WriteDescriptor");
switch(rc){ switch(rc){
@ -295,13 +298,13 @@ bool NimBLERemoteDescriptor::writeValue(const uint8_t* data, size_t length, bool
retryCount++; retryCount++;
length = mtu; length = mtu;
break; break;
case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_AUTHEN): case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_AUTHEN):
case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_AUTHOR): case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_AUTHOR):
case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_ENC): case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_ENC):
if (retryCount && pClient->secureConnection()) if (retryCount && pClient->secureConnection())
break; break;
/* Else falls through. */ /* Else falls through. */
default: default:
return false; return false;
} }
@ -339,4 +342,6 @@ void NimBLERemoteDescriptor::releaseSemaphores() {
m_semaphoreDescWrite.give(1); m_semaphoreDescWrite.give(1);
m_semaphoreReadDescrEvt.give(1); m_semaphoreReadDescrEvt.give(1);
} }
#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
#endif /* CONFIG_BT_ENABLED */ #endif /* CONFIG_BT_ENABLED */

View file

@ -3,7 +3,7 @@
* *
* Created: on Jan 27 2020 * Created: on Jan 27 2020
* Author H2zero * Author H2zero
* *
* Originally: * Originally:
* *
* BLERemoteDescriptor.h * BLERemoteDescriptor.h
@ -17,6 +17,9 @@
#include "sdkconfig.h" #include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED) #if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h"
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
#include "NimBLERemoteCharacteristic.h" #include "NimBLERemoteCharacteristic.h"
class NimBLERemoteCharacteristic; class NimBLERemoteCharacteristic;
@ -54,5 +57,7 @@ private:
}; };
#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
#endif /* CONFIG_BT_ENABLED */ #endif /* CONFIG_BT_ENABLED */
#endif /* COMPONENTS_NIMBLEREMOTEDESCRIPTOR_H_ */ #endif /* COMPONENTS_NIMBLEREMOTEDESCRIPTOR_H_ */

View file

@ -3,7 +3,7 @@
* *
* Created: on Jan 27 2020 * Created: on Jan 27 2020
* Author H2zero * Author H2zero
* *
* Originally: * Originally:
* *
* BLERemoteService.cpp * BLERemoteService.cpp
@ -14,6 +14,9 @@
#include "sdkconfig.h" #include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED) #if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h"
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
#include "NimBLERemoteService.h" #include "NimBLERemoteService.h"
#include "NimBLEUtils.h" #include "NimBLEUtils.h"
#include "NimBLEDevice.h" #include "NimBLEDevice.h"
@ -25,19 +28,19 @@ static const char* LOG_TAG = "NimBLERemoteService";
* @brief Remote Service constructor. * @brief Remote Service constructor.
* @param [in] Reference to the client this belongs to. * @param [in] Reference to the client this belongs to.
* @param [in] Refernce to the structure with the services' information. * @param [in] Refernce to the structure with the services' information.
*/ */
NimBLERemoteService::NimBLERemoteService(NimBLEClient* pClient, const struct ble_gatt_svc* service) { NimBLERemoteService::NimBLERemoteService(NimBLEClient* pClient, const struct ble_gatt_svc* service) {
NIMBLE_LOGD(LOG_TAG, ">> BLERemoteService()"); NIMBLE_LOGD(LOG_TAG, ">> BLERemoteService()");
m_pClient = pClient; m_pClient = pClient;
switch (service->uuid.u.type) { switch (service->uuid.u.type) {
case BLE_UUID_TYPE_16: case BLE_UUID_TYPE_16:
m_uuid = NimBLEUUID(service->uuid.u16.value); m_uuid = NimBLEUUID(service->uuid.u16.value);
break; break;
case BLE_UUID_TYPE_32: case BLE_UUID_TYPE_32:
m_uuid = NimBLEUUID(service->uuid.u32.value); m_uuid = NimBLEUUID(service->uuid.u32.value);
break; break;
case BLE_UUID_TYPE_128: case BLE_UUID_TYPE_128:
m_uuid = NimBLEUUID(const_cast<ble_uuid128_t*>(&service->uuid.u128)); m_uuid = NimBLEUUID(const_cast<ble_uuid128_t*>(&service->uuid.u128));
break; break;
default: default:
@ -55,7 +58,7 @@ NimBLERemoteService::NimBLERemoteService(NimBLEClient* pClient, const struct ble
/** /**
* @brief When deleting the service make sure we delete all characteristics and descriptors. * @brief When deleting the service make sure we delete all characteristics and descriptors.
* Also release any semaphores they may be holding. * Also release any semaphores they may be holding.
*/ */
NimBLERemoteService::~NimBLERemoteService() { NimBLERemoteService::~NimBLERemoteService() {
removeCharacteristics(); removeCharacteristics();
} }
@ -65,12 +68,12 @@ NimBLERemoteService::~NimBLERemoteService() {
* @brief Get the remote characteristic object for the characteristic UUID. * @brief Get the remote characteristic object for the characteristic UUID.
* @param [in] uuid Remote characteristic uuid. * @param [in] uuid Remote characteristic uuid.
* @return Reference to the remote characteristic object. * @return Reference to the remote characteristic object.
*/ */
NimBLERemoteCharacteristic* NimBLERemoteService::getCharacteristic(const char* uuid) { NimBLERemoteCharacteristic* NimBLERemoteService::getCharacteristic(const char* uuid) {
return getCharacteristic(NimBLEUUID(uuid)); return getCharacteristic(NimBLEUUID(uuid));
} // getCharacteristic } // getCharacteristic
/** /**
* @brief Get the characteristic object for the UUID. * @brief Get the characteristic object for the UUID.
* @param [in] uuid Characteristic uuid. * @param [in] uuid Characteristic uuid.
@ -93,12 +96,12 @@ NimBLERemoteCharacteristic* NimBLERemoteService::getCharacteristic(const NimBLEU
/** /**
* @brief Callback for Characterisic discovery. * @brief Callback for Characterisic discovery.
*/ */
int NimBLERemoteService::characteristicDiscCB(uint16_t conn_handle, int NimBLERemoteService::characteristicDiscCB(uint16_t conn_handle,
const struct ble_gatt_error *error, const struct ble_gatt_error *error,
const struct ble_gatt_chr *chr, void *arg) const struct ble_gatt_chr *chr, void *arg)
{ {
NIMBLE_LOGD(LOG_TAG,"Characteristic Discovered >> status: %d handle: %d", error->status, conn_handle); NIMBLE_LOGD(LOG_TAG,"Characteristic Discovered >> status: %d handle: %d", error->status, conn_handle);
NimBLERemoteService *service = (NimBLERemoteService*)arg; NimBLERemoteService *service = (NimBLERemoteService*)arg;
int rc=0; int rc=0;
@ -106,7 +109,7 @@ int NimBLERemoteService::characteristicDiscCB(uint16_t conn_handle,
if(service->getClient()->getConnId() != conn_handle){ if(service->getClient()->getConnId() != conn_handle){
return 0; return 0;
} }
switch (error->status) { switch (error->status) {
case 0: { case 0: {
// Found a service - add it to the map // Found a service - add it to the map
@ -147,12 +150,12 @@ int NimBLERemoteService::characteristicDiscCB(uint16_t conn_handle,
*/ */
bool NimBLERemoteService::retrieveCharacteristics() { bool NimBLERemoteService::retrieveCharacteristics() {
NIMBLE_LOGD(LOG_TAG, ">> retrieveCharacteristics() for service: %s", getUUID().toString().c_str()); NIMBLE_LOGD(LOG_TAG, ">> retrieveCharacteristics() for service: %s", getUUID().toString().c_str());
int rc = 0; int rc = 0;
//removeCharacteristics(); // Forget any previous characteristics. //removeCharacteristics(); // Forget any previous characteristics.
m_semaphoreGetCharEvt.take("retrieveCharacteristics"); m_semaphoreGetCharEvt.take("retrieveCharacteristics");
rc = ble_gattc_disc_all_chrs(m_pClient->getConnId(), rc = ble_gattc_disc_all_chrs(m_pClient->getConnId(),
m_startHandle, m_startHandle,
m_endHandle, m_endHandle,
@ -164,7 +167,7 @@ bool NimBLERemoteService::retrieveCharacteristics() {
m_semaphoreGetCharEvt.give(); m_semaphoreGetCharEvt.give();
return false; return false;
} }
m_haveCharacteristics = (m_semaphoreGetCharEvt.wait("retrieveCharacteristics") == 0); m_haveCharacteristics = (m_semaphoreGetCharEvt.wait("retrieveCharacteristics") == 0);
if(m_haveCharacteristics){ if(m_haveCharacteristics){
uint16_t endHdl = 0xFFFF; uint16_t endHdl = 0xFFFF;
@ -173,19 +176,19 @@ bool NimBLERemoteService::retrieveCharacteristics() {
NIMBLE_LOGD(LOG_TAG, "Found UUID: %s Handle: %d Def Handle: %d", (*it).second->getUUID().toString().c_str(), (*it).second->getHandle(), (*it).second->getDefHandle()); NIMBLE_LOGD(LOG_TAG, "Found UUID: %s Handle: %d Def Handle: %d", (*it).second->getUUID().toString().c_str(), (*it).second->getHandle(), (*it).second->getDefHandle());
// The descriptor handle is between this characteristic val_handle and the next ones def_handle // The descriptor handle is between this characteristic val_handle and the next ones def_handle
// so make the end of the scan at the handle before the next characteristic def_handle // so make the end of the scan at the handle before the next characteristic def_handle
// Make sure we don't go past the service end handle // Make sure we don't go past the service end handle
if(++it != m_characteristicMapByHandle.cend()){ if(++it != m_characteristicMapByHandle.cend()){
NIMBLE_LOGD(LOG_TAG, "Next UUID: %s Handle: %d Def Handle: %d", (*it).second->getUUID().toString().c_str(), (*it).second->getHandle(),(*it).second->getDefHandle()); NIMBLE_LOGD(LOG_TAG, "Next UUID: %s Handle: %d Def Handle: %d", (*it).second->getUUID().toString().c_str(), (*it).second->getHandle(),(*it).second->getDefHandle());
endHdl = (*it).second->getDefHandle()-1; endHdl = (*it).second->getDefHandle()-1;
} }
else{ else{
NIMBLE_LOGD(LOG_TAG, "END CHARS"); NIMBLE_LOGD(LOG_TAG, "END CHARS");
endHdl = m_endHandle; endHdl = m_endHandle;
} }
--it; --it;
//If there is no handles between this characteristic and the next there is no descriptor so skip to the next //If there is no handles between this characteristic and the next there is no descriptor so skip to the next
if((*it).second->getHandle() != endHdl){ if((*it).second->getHandle() != endHdl){
if(!m_pClient->m_isConnected || !(*it).second->retrieveDescriptors(endHdl)) { if(!m_pClient->m_isConnected || !(*it).second->retrieveDescriptors(endHdl)) {
@ -194,14 +197,14 @@ bool NimBLERemoteService::retrieveCharacteristics() {
} }
//NIMBLE_LOGD(LOG_TAG, "Found %d Characteristics in service UUID: %s", chars->size(), myPair.first.c_str()); //NIMBLE_LOGD(LOG_TAG, "Found %d Characteristics in service UUID: %s", chars->size(), myPair.first.c_str());
} }
NIMBLE_LOGD(LOG_TAG, "<< retrieveCharacteristics()"); NIMBLE_LOGD(LOG_TAG, "<< retrieveCharacteristics()");
return true; return true;
} }
NIMBLE_LOGE(LOG_TAG, "Could not retrieve characteristics"); NIMBLE_LOGE(LOG_TAG, "Could not retrieve characteristics");
return false; return false;
} // retrieveCharacteristics } // retrieveCharacteristics
@ -263,10 +266,10 @@ NimBLEUUID NimBLERemoteService::getUUID() {
*/ */
std::string NimBLERemoteService::getValue(const NimBLEUUID &characteristicUuid) { std::string NimBLERemoteService::getValue(const NimBLEUUID &characteristicUuid) {
NIMBLE_LOGD(LOG_TAG, ">> readValue: uuid: %s", characteristicUuid.toString().c_str()); NIMBLE_LOGD(LOG_TAG, ">> readValue: uuid: %s", characteristicUuid.toString().c_str());
std::string ret = ""; std::string ret = "";
NimBLERemoteCharacteristic* pChar = getCharacteristic(characteristicUuid); NimBLERemoteCharacteristic* pChar = getCharacteristic(characteristicUuid);
if(pChar != nullptr) { if(pChar != nullptr) {
ret = pChar->readValue(); ret = pChar->readValue();
} }
@ -284,10 +287,10 @@ std::string NimBLERemoteService::getValue(const NimBLEUUID &characteristicUuid)
*/ */
bool NimBLERemoteService::setValue(const NimBLEUUID &characteristicUuid, const std::string &value) { bool NimBLERemoteService::setValue(const NimBLEUUID &characteristicUuid, const std::string &value) {
NIMBLE_LOGD(LOG_TAG, ">> setValue: uuid: %s", characteristicUuid.toString().c_str()); NIMBLE_LOGD(LOG_TAG, ">> setValue: uuid: %s", characteristicUuid.toString().c_str());
bool ret = false; bool ret = false;
NimBLERemoteCharacteristic* pChar = getCharacteristic(characteristicUuid); NimBLERemoteCharacteristic* pChar = getCharacteristic(characteristicUuid);
if(pChar != nullptr) { if(pChar != nullptr) {
ret = pChar->writeValue(value); ret = pChar->writeValue(value);
} }
@ -306,12 +309,12 @@ bool NimBLERemoteService::setValue(const NimBLEUUID &characteristicUuid, const s
*/ */
void NimBLERemoteService::removeCharacteristics() { void NimBLERemoteService::removeCharacteristics() {
m_characteristicMap.clear(); // Clear the map m_characteristicMap.clear(); // Clear the map
for (auto &myPair : m_characteristicMapByHandle) { for (auto &myPair : m_characteristicMapByHandle) {
delete myPair.second; delete myPair.second;
} }
m_characteristicMapByHandle.clear(); // Clear the map m_characteristicMapByHandle.clear(); // Clear the map
} // removeCharacteristics } // removeCharacteristics
@ -334,7 +337,7 @@ std::string NimBLERemoteService::toString() {
snprintf(val, sizeof(val), "%04x", m_endHandle); snprintf(val, sizeof(val), "%04x", m_endHandle);
res += " 0x"; res += " 0x";
res += val; res += val;
for (auto &myPair : m_characteristicMap) { for (auto &myPair : m_characteristicMap) {
res += "\n" + myPair.second->toString(); res += "\n" + myPair.second->toString();
} }
@ -345,7 +348,7 @@ std::string NimBLERemoteService::toString() {
/** /**
* @brief called when an error occurrs and we need to release the semaphores to resume operations. * @brief called when an error occurrs and we need to release the semaphores to resume operations.
* Will release all characteristic and subsequently all descriptor semaphores for this service. * Will release all characteristic and subsequently all descriptor semaphores for this service.
*/ */
void NimBLERemoteService::releaseSemaphores() { void NimBLERemoteService::releaseSemaphores() {
for (auto &cPair : m_characteristicMapByHandle) { for (auto &cPair : m_characteristicMapByHandle) {
@ -354,4 +357,5 @@ void NimBLERemoteService::releaseSemaphores() {
m_semaphoreGetCharEvt.give(1); m_semaphoreGetCharEvt.give(1);
} }
#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
#endif /* CONFIG_BT_ENABLED */ #endif /* CONFIG_BT_ENABLED */

View file

@ -3,7 +3,7 @@
* *
* Created: on Jan 27 2020 * Created: on Jan 27 2020
* Author H2zero * Author H2zero
* *
* Originally: * Originally:
* *
* BLERemoteService.h * BLERemoteService.h
@ -17,6 +17,9 @@
#include "sdkconfig.h" #include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED) #if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h"
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
#include "NimBLEClient.h" #include "NimBLEClient.h"
#include "NimBLEUUID.h" #include "NimBLEUUID.h"
#include "FreeRTOS.h" #include "FreeRTOS.h"
@ -52,7 +55,7 @@ public:
private: private:
// Private constructor ... never meant to be created by a user application. // Private constructor ... never meant to be created by a user application.
NimBLERemoteService(NimBLEClient* pClient, const struct ble_gatt_svc *service); NimBLERemoteService(NimBLEClient* pClient, const struct ble_gatt_svc *service);
// Friends // Friends
friend class NimBLEClient; friend class NimBLEClient;
@ -60,7 +63,7 @@ private:
// Private methods // Private methods
bool retrieveCharacteristics(void); // Retrieve the characteristics from the BLE Server. bool retrieveCharacteristics(void); // Retrieve the characteristics from the BLE Server.
static int characteristicDiscCB(uint16_t conn_handle, static int characteristicDiscCB(uint16_t conn_handle,
const struct ble_gatt_error *error, const struct ble_gatt_error *error,
const struct ble_gatt_chr *chr, void *arg); const struct ble_gatt_chr *chr, void *arg);
@ -85,5 +88,6 @@ private:
uint16_t m_endHandle; // The ending handle of this service. uint16_t m_endHandle; // The ending handle of this service.
}; // BLERemoteService }; // BLERemoteService
#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
#endif /* CONFIG_BT_ENABLED */ #endif /* CONFIG_BT_ENABLED */
#endif /* COMPONENTS_NIMBLEREMOTESERVICE_H_ */ #endif /* COMPONENTS_NIMBLEREMOTESERVICE_H_ */

View file

@ -3,7 +3,7 @@
* *
* Created: on Jan 24 2020 * Created: on Jan 24 2020
* Author H2zero * Author H2zero
* *
* Originally: * Originally:
* *
* BLEScan.cpp * BLEScan.cpp
@ -14,6 +14,9 @@
#include "sdkconfig.h" #include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED) #if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h"
#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
#include "NimBLEScan.h" #include "NimBLEScan.h"
#include "NimBLEUtils.h" #include "NimBLEUtils.h"
#include "NimBLEDevice.h" #include "NimBLEDevice.h"
@ -40,7 +43,7 @@ static const char* LOG_TAG = "NimBLEScan";
* directed advertisement shall not be ignored if the InitA is a * directed advertisement shall not be ignored if the InitA is a
* resolvable private address. * resolvable private address.
*/ */
//#define BLE_HCI_SCAN_FILT_NO_WL (0) //#define BLE_HCI_SCAN_FILT_NO_WL (0)
//#define BLE_HCI_SCAN_FILT_USE_WL (1) //#define BLE_HCI_SCAN_FILT_USE_WL (1)
//#define BLE_HCI_SCAN_FILT_NO_WL_INITA (2) //#define BLE_HCI_SCAN_FILT_NO_WL_INITA (2)
@ -76,33 +79,33 @@ NimBLEScan::NimBLEScan() {
* @param [in] param Parameter data for this event. * @param [in] param Parameter data for this event.
*/ */
/*STATIC*/int NimBLEScan::handleGapEvent(ble_gap_event* event, void* arg) { /*STATIC*/int NimBLEScan::handleGapEvent(ble_gap_event* event, void* arg) {
NimBLEScan* pScan = (NimBLEScan*)arg; NimBLEScan* pScan = (NimBLEScan*)arg;
struct ble_hs_adv_fields fields; struct ble_hs_adv_fields fields;
int rc = 0; int rc = 0;
switch(event->type) { switch(event->type) {
case BLE_GAP_EVENT_DISC: { case BLE_GAP_EVENT_DISC: {
if(pScan->m_stopped) { if(pScan->m_stopped) {
NIMBLE_LOGE(LOG_TAG, "Scan stop called, ignoring results."); NIMBLE_LOGE(LOG_TAG, "Scan stop called, ignoring results.");
return 0; return 0;
} }
rc = ble_hs_adv_parse_fields(&fields, event->disc.data, rc = ble_hs_adv_parse_fields(&fields, event->disc.data,
event->disc.length_data); event->disc.length_data);
if (rc != 0) { if (rc != 0) {
NIMBLE_LOGE(LOG_TAG, "Gap Event Parse ERROR."); NIMBLE_LOGE(LOG_TAG, "Gap Event Parse ERROR.");
return 0; return 0;
} }
NimBLEAddress advertisedAddress(event->disc.addr); NimBLEAddress advertisedAddress(event->disc.addr);
// Print advertisement data // Print advertisement data
// print_adv_fields(&fields); // print_adv_fields(&fields);
// If we are not scanning, nothing to do with the extra results. // If we are not scanning, nothing to do with the extra results.
if (pScan->m_stopped) { if (pScan->m_stopped) {
return 0; return 0;
} }
@ -111,9 +114,9 @@ NimBLEScan::NimBLEScan() {
NIMBLE_LOGI(LOG_TAG, "Ignoring device: address: %s", advertisedAddress.toString().c_str()); NIMBLE_LOGI(LOG_TAG, "Ignoring device: address: %s", advertisedAddress.toString().c_str());
return 0; return 0;
} }
NimBLEAdvertisedDevice* advertisedDevice = nullptr; NimBLEAdvertisedDevice* advertisedDevice = nullptr;
// If we've seen this device before get a pointer to it from the map // If we've seen this device before get a pointer to it from the map
auto it = pScan->m_scanResults.m_advertisedDevicesMap.find(advertisedAddress.toString()); auto it = pScan->m_scanResults.m_advertisedDevicesMap.find(advertisedAddress.toString());
if(it != pScan->m_scanResults.m_advertisedDevicesMap.cend()) { if(it != pScan->m_scanResults.m_advertisedDevicesMap.cend()) {
@ -134,7 +137,7 @@ NimBLEScan::NimBLEScan() {
else{ else{
NIMBLE_LOGI(LOG_TAG, "UPDATING PREVIOUSLY FOUND DEVICE: %s", advertisedAddress.toString().c_str()); NIMBLE_LOGI(LOG_TAG, "UPDATING PREVIOUSLY FOUND DEVICE: %s", advertisedAddress.toString().c_str());
} }
advertisedDevice->setRSSI(event->disc.rssi); advertisedDevice->setRSSI(event->disc.rssi);
advertisedDevice->parseAdvertisement(&fields); advertisedDevice->parseAdvertisement(&fields);
advertisedDevice->setScan(pScan); advertisedDevice->setScan(pScan);
advertisedDevice->setAdvertisementResult(event->disc.data, event->disc.length_data); advertisedDevice->setAdvertisementResult(event->disc.data, event->disc.length_data);
@ -155,13 +158,13 @@ NimBLEScan::NimBLEScan() {
case BLE_GAP_EVENT_DISC_COMPLETE: { case BLE_GAP_EVENT_DISC_COMPLETE: {
NIMBLE_LOGD(LOG_TAG, "discovery complete; reason=%d", NIMBLE_LOGD(LOG_TAG, "discovery complete; reason=%d",
event->disc_complete.reason); event->disc_complete.reason);
if (pScan->m_scanCompleteCB != nullptr) { if (pScan->m_scanCompleteCB != nullptr) {
pScan->m_scanCompleteCB(pScan->m_scanResults); pScan->m_scanCompleteCB(pScan->m_scanResults);
} }
pScan->m_stopped = true; pScan->m_stopped = true;
pScan->m_semaphoreScanEnd.give(); pScan->m_semaphoreScanEnd.give();
return 0; return 0;
} }
@ -224,13 +227,13 @@ void NimBLEScan::setWindow(uint16_t windowMSecs) {
*/ */
bool NimBLEScan::start(uint32_t duration, void (*scanCompleteCB)(NimBLEScanResults), bool is_continue) { bool NimBLEScan::start(uint32_t duration, void (*scanCompleteCB)(NimBLEScanResults), bool is_continue) {
NIMBLE_LOGD(LOG_TAG, ">> start(duration=%d)", duration); NIMBLE_LOGD(LOG_TAG, ">> start(duration=%d)", duration);
// If Host is not synced we cannot start scanning. // If Host is not synced we cannot start scanning.
if(!NimBLEDevice::m_synced) { if(!NimBLEDevice::m_synced) {
NIMBLE_LOGC(LOG_TAG, "Host reset, wait for sync."); NIMBLE_LOGC(LOG_TAG, "Host reset, wait for sync.");
return false; return false;
} }
if(ble_gap_conn_active()) { if(ble_gap_conn_active()) {
NIMBLE_LOGE(LOG_TAG, "Connection in progress - must wait."); NIMBLE_LOGE(LOG_TAG, "Connection in progress - must wait.");
return false; return false;
@ -244,12 +247,12 @@ bool NimBLEScan::start(uint32_t duration, void (*scanCompleteCB)(NimBLEScanResul
m_stopped = false; m_stopped = false;
m_semaphoreScanEnd.take("start"); m_semaphoreScanEnd.take("start");
// Save the callback to be invoked when the scan completes. // Save the callback to be invoked when the scan completes.
m_scanCompleteCB = scanCompleteCB; m_scanCompleteCB = scanCompleteCB;
// Save the duration in the case that the host is reset so we can reuse it. // Save the duration in the case that the host is reset so we can reuse it.
m_duration = duration; m_duration = duration;
// If 0 duration specified then we assume a continuous scan is desired. // If 0 duration specified then we assume a continuous scan is desired.
if(duration == 0){ if(duration == 0){
duration = BLE_HS_FOREVER; duration = BLE_HS_FOREVER;
@ -257,22 +260,22 @@ bool NimBLEScan::start(uint32_t duration, void (*scanCompleteCB)(NimBLEScanResul
else{ else{
duration = duration*1000; // convert duration to milliseconds duration = duration*1000; // convert duration to milliseconds
} }
// if we are connecting to devices that are advertising even after being connected, multiconnecting peripherals // if we are connecting to devices that are advertising even after being connected, multiconnecting peripherals
// then we should not clear map or we will connect the same device few times // then we should not clear map or we will connect the same device few times
if(!is_continue) { if(!is_continue) {
clearResults(); clearResults();
} }
int rc = 0; int rc = 0;
do{ do{
rc = ble_gap_disc(m_own_addr_type, duration, &m_scan_params, rc = ble_gap_disc(m_own_addr_type, duration, &m_scan_params,
NimBLEScan::handleGapEvent, this); NimBLEScan::handleGapEvent, this);
if(rc == BLE_HS_EBUSY) { if(rc == BLE_HS_EBUSY) {
vTaskDelay(2); vTaskDelay(2);
} }
} while(rc == BLE_HS_EBUSY); } while(rc == BLE_HS_EBUSY);
if (rc != 0 && rc != BLE_HS_EDONE) { if (rc != 0 && rc != BLE_HS_EDONE) {
NIMBLE_LOGE(LOG_TAG, "Error initiating GAP discovery procedure; rc=%d, %s", NIMBLE_LOGE(LOG_TAG, "Error initiating GAP discovery procedure; rc=%d, %s",
rc, NimBLEUtils::returnCodeToString(rc)); rc, NimBLEUtils::returnCodeToString(rc));
@ -305,7 +308,7 @@ NimBLEScanResults NimBLEScan::start(uint32_t duration, bool is_continue) {
*/ */
void NimBLEScan::stop() { void NimBLEScan::stop() {
NIMBLE_LOGD(LOG_TAG, ">> stop()"); NIMBLE_LOGD(LOG_TAG, ">> stop()");
int rc = ble_gap_disc_cancel(); int rc = ble_gap_disc_cancel();
if (rc != 0 && rc != BLE_HS_EALREADY) { if (rc != 0 && rc != BLE_HS_EALREADY) {
NIMBLE_LOGE(LOG_TAG, "Failed to cancel scan; rc=%d\n", rc); NIMBLE_LOGE(LOG_TAG, "Failed to cancel scan; rc=%d\n", rc);
@ -313,13 +316,13 @@ void NimBLEScan::stop() {
} }
m_stopped = true; m_stopped = true;
if (m_scanCompleteCB != nullptr) { if (m_scanCompleteCB != nullptr) {
m_scanCompleteCB(m_scanResults); m_scanCompleteCB(m_scanResults);
} }
m_semaphoreScanEnd.give(); m_semaphoreScanEnd.give();
NIMBLE_LOGD(LOG_TAG, "<< stop()"); NIMBLE_LOGD(LOG_TAG, "<< stop()");
} // stop } // stop
@ -400,4 +403,5 @@ NimBLEAdvertisedDevice NimBLEScanResults::getDevice(uint32_t i) {
return dev; return dev;
} }
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
#endif /* CONFIG_BT_ENABLED */ #endif /* CONFIG_BT_ENABLED */

View file

@ -3,7 +3,7 @@
* *
* Created: on Jan 24 2020 * Created: on Jan 24 2020
* Author H2zero * Author H2zero
* *
* Originally: * Originally:
* *
* BLEScan.h * BLEScan.h
@ -16,6 +16,9 @@
#include "sdkconfig.h" #include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED) #if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h"
#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
#include "NimBLEAdvertisedDevice.h" #include "NimBLEAdvertisedDevice.h"
#include "FreeRTOS.h" #include "FreeRTOS.h"
@ -63,14 +66,14 @@ public:
void clearResults(); void clearResults();
NimBLEScanResults getResults(); NimBLEScanResults getResults();
void erase(const NimBLEAddress &address); void erase(const NimBLEAddress &address);
private: private:
NimBLEScan(); NimBLEScan();
friend class NimBLEDevice; friend class NimBLEDevice;
static int handleGapEvent(ble_gap_event* event, void* arg); static int handleGapEvent(ble_gap_event* event, void* arg);
void onHostReset(); void onHostReset();
NimBLEAdvertisedDeviceCallbacks* m_pAdvertisedDeviceCallbacks = nullptr; NimBLEAdvertisedDeviceCallbacks* m_pAdvertisedDeviceCallbacks = nullptr;
void (*m_scanCompleteCB)(NimBLEScanResults scanResults); void (*m_scanCompleteCB)(NimBLEScanResults scanResults);
ble_gap_disc_params m_scan_params; ble_gap_disc_params m_scan_params;
@ -82,6 +85,6 @@ private:
uint32_t m_duration; uint32_t m_duration;
}; };
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
#endif /* CONFIG_BT_ENABLED */ #endif /* CONFIG_BT_ENABLED */
#endif /* COMPONENTS_NIMBLE_SCAN_H_ */ #endif /* COMPONENTS_NIMBLE_SCAN_H_ */

View file

@ -3,7 +3,7 @@
* *
* Created: on Feb 22 2020 * Created: on Feb 22 2020
* Author H2zero * Author H2zero
* *
* Originally: * Originally:
* *
* BLESecurity.cpp * BLESecurity.cpp
@ -73,7 +73,7 @@ void NimBLESecurity::setRespEncryptionKey(uint8_t resp_key) {
* *
*/ */
void NimBLESecurity::setKeySize(uint8_t key_size) { void NimBLESecurity::setKeySize(uint8_t key_size) {
//m_keySize = key_size; //m_keySize = key_size;
//esp_ble_gap_set_security_param(ESP_BLE_SM_MAX_KEY_SIZE, &m_keySize, sizeof(uint8_t)); //esp_ble_gap_set_security_param(ESP_BLE_SM_MAX_KEY_SIZE, &m_keySize, sizeof(uint8_t));
} //setKeySize } //setKeySize
@ -132,7 +132,7 @@ char* BLESecurity::esp_key_type_to_str(esp_ble_key_type_t key_type) {
break; break;
} }
return key_str; return key_str;
} // esp_key_type_to_str } // esp_key_type_to_str
*/ */
#endif // CONFIG_BT_ENABLED #endif // CONFIG_BT_ENABLED

View file

@ -3,7 +3,7 @@
* *
* Created: on Feb 22 2020 * Created: on Feb 22 2020
* Author H2zero * Author H2zero
* *
* Originally: * Originally:
* *
* BLESecurity.h * BLESecurity.h
@ -12,8 +12,8 @@
* Author: chegewara * Author: chegewara
*/ */
/** This class exists for backward compatibility - Should not be used in new code /** This class exists for backward compatibility - Should not be used in new code
* See the security functions in NimBLEDevice and callbacks in NimBLEServer / NimBLEClient * See the security functions in NimBLEDevice and callbacks in NimBLEServer / NimBLEClient
*/ */
#ifndef COMPONENTS_NIMBLESECURITY_H_ #ifndef COMPONENTS_NIMBLESECURITY_H_

View file

@ -3,7 +3,7 @@
* *
* Created: on March 2, 2020 * Created: on March 2, 2020
* Author H2zero * Author H2zero
* *
* Originally: * Originally:
* *
* BLEServer.cpp * BLEServer.cpp
@ -15,6 +15,9 @@
#include "sdkconfig.h" #include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED) #if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h"
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#include "NimBLEServer.h" #include "NimBLEServer.h"
#include "NimBLE2902.h" #include "NimBLE2902.h"
#include "NimBLEUtils.h" #include "NimBLEUtils.h"
@ -32,10 +35,10 @@ static NimBLEServerCallbacks defaultCallbacks;
* the BLEDevice class. * the BLEDevice class.
*/ */
NimBLEServer::NimBLEServer() { NimBLEServer::NimBLEServer() {
m_connId = BLE_HS_CONN_HANDLE_NONE; m_connId = BLE_HS_CONN_HANDLE_NONE;
m_svcChgChrHdl = 0xffff; m_svcChgChrHdl = 0xffff;
m_pServerCallbacks = &defaultCallbacks; m_pServerCallbacks = &defaultCallbacks;
m_gattsStarted = false; m_gattsStarted = false;
} // BLEServer } // BLEServer
@ -48,7 +51,7 @@ NimBLEServer::NimBLEServer() {
* @return A reference to the new service object. * @return A reference to the new service object.
*/ */
NimBLEService* NimBLEServer::createService(const char* uuid) { NimBLEService* NimBLEServer::createService(const char* uuid) {
return createService(NimBLEUUID(uuid)); return createService(NimBLEUUID(uuid));
} }
@ -63,20 +66,20 @@ NimBLEService* NimBLEServer::createService(const char* uuid) {
* @return A reference to the new service object. * @return A reference to the new service object.
*/ */
NimBLEService* NimBLEServer::createService(const NimBLEUUID &uuid, uint32_t numHandles, uint8_t inst_id) { NimBLEService* NimBLEServer::createService(const NimBLEUUID &uuid, uint32_t numHandles, uint8_t inst_id) {
NIMBLE_LOGD(LOG_TAG, ">> createService - %s", uuid.toString().c_str()); NIMBLE_LOGD(LOG_TAG, ">> createService - %s", uuid.toString().c_str());
// Check that a service with the supplied UUID does not already exist. // Check that a service with the supplied UUID does not already exist.
if (m_serviceMap.getByUUID(uuid) != nullptr) { if (m_serviceMap.getByUUID(uuid) != nullptr) {
NIMBLE_LOGW(LOG_TAG, "<< Attempt to create a new service with uuid %s but a service with that UUID already exists.", NIMBLE_LOGW(LOG_TAG, "<< Attempt to create a new service with uuid %s but a service with that UUID already exists.",
uuid.toString().c_str()); uuid.toString().c_str());
} }
NimBLEService* pService = new NimBLEService(uuid, numHandles, this); NimBLEService* pService = new NimBLEService(uuid, numHandles, this);
pService->m_instId = inst_id; pService->m_instId = inst_id;
m_serviceMap.setByUUID(uuid, pService); // Save a reference to this service being on this server. m_serviceMap.setByUUID(uuid, pService); // Save a reference to this service being on this server.
NIMBLE_LOGD(LOG_TAG, "<< createService"); NIMBLE_LOGD(LOG_TAG, "<< createService");
return pService; return pService;
} // createService } // createService
@ -86,7 +89,7 @@ NimBLEService* NimBLEServer::createService(const NimBLEUUID &uuid, uint32_t numH
* @return A reference to the service object. * @return A reference to the service object.
*/ */
NimBLEService* NimBLEServer::getServiceByUUID(const char* uuid) { NimBLEService* NimBLEServer::getServiceByUUID(const char* uuid) {
return m_serviceMap.getByUUID(uuid); return m_serviceMap.getByUUID(uuid);
} }
@ -96,7 +99,7 @@ NimBLEService* NimBLEServer::getServiceByUUID(const char* uuid) {
* @return A reference to the service object. * @return A reference to the service object.
*/ */
NimBLEService* NimBLEServer::getServiceByUUID(const NimBLEUUID &uuid) { NimBLEService* NimBLEServer::getServiceByUUID(const NimBLEUUID &uuid) {
return m_serviceMap.getByUUID(uuid); return m_serviceMap.getByUUID(uuid);
} }
@ -106,7 +109,7 @@ NimBLEService* NimBLEServer::getServiceByUUID(const NimBLEUUID &uuid) {
* @return An advertising object. * @return An advertising object.
*/ */
NimBLEAdvertising* NimBLEServer::getAdvertising() { NimBLEAdvertising* NimBLEServer::getAdvertising() {
return BLEDevice::getAdvertising(); return BLEDevice::getAdvertising();
} }
@ -116,58 +119,58 @@ NimBLEAdvertising* NimBLEServer::getAdvertising() {
* @return Client connection id. * @return Client connection id.
*/ */
uint16_t NimBLEServer::getConnId() { uint16_t NimBLEServer::getConnId() {
return m_connId; return m_connId;
} }
/** /**
* @brief Start the GATT server. Required to be called after setup of all * @brief Start the GATT server. Required to be called after setup of all
* services and characteristics / descriptors for the NimBLE host to register them. * services and characteristics / descriptors for the NimBLE host to register them.
*/ */
void NimBLEServer::start() { void NimBLEServer::start() {
if(m_gattsStarted) { if(m_gattsStarted) {
NIMBLE_LOGW(LOG_TAG, "Gatt server already started"); NIMBLE_LOGW(LOG_TAG, "Gatt server already started");
return; return;
} }
int rc = ble_gatts_start(); int rc = ble_gatts_start();
if (rc != 0) { if (rc != 0) {
NIMBLE_LOGE(LOG_TAG, "ble_gatts_start; rc=%d, %s", rc, NIMBLE_LOGE(LOG_TAG, "ble_gatts_start; rc=%d, %s", rc,
NimBLEUtils::returnCodeToString(rc)); NimBLEUtils::returnCodeToString(rc));
abort(); abort();
} }
#if CONFIG_LOG_DEFAULT_LEVEL > 3 || (ARDUINO_ARCH_ESP32 && CORE_DEBUG_LEVEL >= 4) #if CONFIG_LOG_DEFAULT_LEVEL > 3 || (ARDUINO_ARCH_ESP32 && CORE_DEBUG_LEVEL >= 4)
ble_gatts_show_local(); ble_gatts_show_local();
#endif #endif
ble_uuid16_t svc = {BLE_UUID_TYPE_16, 0x1801}; ble_uuid16_t svc = {BLE_UUID_TYPE_16, 0x1801};
ble_uuid16_t chr = {BLE_UUID_TYPE_16, 0x2a05}; ble_uuid16_t chr = {BLE_UUID_TYPE_16, 0x2a05};
rc = ble_gatts_find_chr(&svc.u, &chr.u, NULL, &m_svcChgChrHdl); rc = ble_gatts_find_chr(&svc.u, &chr.u, NULL, &m_svcChgChrHdl);
if(rc != 0) { if(rc != 0) {
NIMBLE_LOGE(LOG_TAG, "ble_gatts_find_chr: rc=%d, %s", rc, NIMBLE_LOGE(LOG_TAG, "ble_gatts_find_chr: rc=%d, %s", rc,
NimBLEUtils::returnCodeToString(rc)); NimBLEUtils::returnCodeToString(rc));
abort(); abort();
} }
NIMBLE_LOGI(LOG_TAG, "Service changed characterisic handle: %d", m_svcChgChrHdl); NIMBLE_LOGI(LOG_TAG, "Service changed characterisic handle: %d", m_svcChgChrHdl);
// Build a map of characteristics with Notify / Indicate capabilities for event handling // Build a map of characteristics with Notify / Indicate capabilities for event handling
uint8_t numSvcs = m_serviceMap.getRegisteredServiceCount(); uint8_t numSvcs = m_serviceMap.getRegisteredServiceCount();
NimBLEService* pService = m_serviceMap.getFirst(); NimBLEService* pService = m_serviceMap.getFirst();
for(int i = 0; i < numSvcs; i++) { for(int i = 0; i < numSvcs; i++) {
uint8_t numChrs = pService->m_characteristicMap.getSize(); uint8_t numChrs = pService->m_characteristicMap.getSize();
NimBLECharacteristic* pChr = pService->m_characteristicMap.getFirst(); NimBLECharacteristic* pChr = pService->m_characteristicMap.getFirst();
if(pChr != nullptr) { if(pChr != nullptr) {
for( int d = 0; d < numChrs; d++) { for( int d = 0; d < numChrs; d++) {
// if Notify / Indicate is enabled but we didn't create the descriptor // if Notify / Indicate is enabled but we didn't create the descriptor
// we do it now. // we do it now.
if((pChr->m_properties & BLE_GATT_CHR_F_INDICATE) || if((pChr->m_properties & BLE_GATT_CHR_F_INDICATE) ||
(pChr->m_properties & BLE_GATT_CHR_F_NOTIFY)) { (pChr->m_properties & BLE_GATT_CHR_F_NOTIFY)) {
if(nullptr == pChr->getDescriptorByUUID("2902")) { if(nullptr == pChr->getDescriptorByUUID("2902")) {
pChr->createDescriptor("2902"); pChr->createDescriptor("2902");
} }
@ -179,8 +182,8 @@ void NimBLEServer::start() {
} }
pService = m_serviceMap.getNext(); pService = m_serviceMap.getNext();
} }
m_gattsStarted = true; m_gattsStarted = true;
} }
@ -192,13 +195,13 @@ void NimBLEServer::start() {
*/ */
int NimBLEServer::disconnect(uint16_t connId, uint8_t reason) { int NimBLEServer::disconnect(uint16_t connId, uint8_t reason) {
NIMBLE_LOGD(LOG_TAG, ">> disconnect()"); NIMBLE_LOGD(LOG_TAG, ">> disconnect()");
int rc = ble_gap_terminate(connId, reason); int rc = ble_gap_terminate(connId, reason);
if(rc != 0){ if(rc != 0){
NIMBLE_LOGE(LOG_TAG, "ble_gap_terminate failed: rc=%d %s", rc, NIMBLE_LOGE(LOG_TAG, "ble_gap_terminate failed: rc=%d %s", rc,
NimBLEUtils::returnCodeToString(rc)); NimBLEUtils::returnCodeToString(rc));
} }
return rc; return rc;
NIMBLE_LOGD(LOG_TAG, "<< disconnect()"); NIMBLE_LOGD(LOG_TAG, "<< disconnect()");
} }
@ -209,7 +212,7 @@ int NimBLEServer::disconnect(uint16_t connId, uint8_t reason) {
* @return The number of connected clients. * @return The number of connected clients.
*/ */
uint32_t NimBLEServer::getConnectedCount() { uint32_t NimBLEServer::getConnectedCount() {
return m_connectedServersMap.size(); return m_connectedServersMap.size();
} // getConnectedCount } // getConnectedCount
@ -222,15 +225,15 @@ uint32_t NimBLEServer::getConnectedCount() {
* *
*/ */
/*STATIC*/int NimBLEServer::handleGapEvent(struct ble_gap_event *event, void *arg) { /*STATIC*/int NimBLEServer::handleGapEvent(struct ble_gap_event *event, void *arg) {
NimBLEServer* server = (NimBLEServer*)arg; NimBLEServer* server = (NimBLEServer*)arg;
NIMBLE_LOGD(LOG_TAG, ">> handleGapEvent: %s", NIMBLE_LOGD(LOG_TAG, ">> handleGapEvent: %s",
NimBLEUtils::gapEventToString(event->type)); NimBLEUtils::gapEventToString(event->type));
int rc = 0; int rc = 0;
struct ble_gap_conn_desc desc; struct ble_gap_conn_desc desc;
switch(event->type) { switch(event->type) {
case BLE_GAP_EVENT_CONNECT: { case BLE_GAP_EVENT_CONNECT: {
if (event->connect.status != 0) { if (event->connect.status != 0) {
/* Connection failed; resume advertising */ /* Connection failed; resume advertising */
NIMBLE_LOGC(LOG_TAG, "Connection failed"); NIMBLE_LOGC(LOG_TAG, "Connection failed");
@ -240,21 +243,21 @@ uint32_t NimBLEServer::getConnectedCount() {
else { else {
server->m_connId = event->connect.conn_handle; server->m_connId = event->connect.conn_handle;
server->addPeerDevice((void*)server, false, server->m_connId); server->addPeerDevice((void*)server, false, server->m_connId);
ble_gap_conn_desc desc; ble_gap_conn_desc desc;
rc = ble_gap_conn_find(event->connect.conn_handle, &desc); rc = ble_gap_conn_find(event->connect.conn_handle, &desc);
assert(rc == 0); assert(rc == 0);
server->m_pServerCallbacks->onConnect(server); server->m_pServerCallbacks->onConnect(server);
server->m_pServerCallbacks->onConnect(server, &desc); server->m_pServerCallbacks->onConnect(server, &desc);
} }
return 0; return 0;
} // BLE_GAP_EVENT_CONNECT } // BLE_GAP_EVENT_CONNECT
case BLE_GAP_EVENT_DISCONNECT: { case BLE_GAP_EVENT_DISCONNECT: {
// If Host reset tell the device now before returning to prevent // If Host reset tell the device now before returning to prevent
// any errors caused by calling host functions before resyncing. // any errors caused by calling host functions before resyncing.
switch(event->disconnect.reason) { switch(event->disconnect.reason) {
case BLE_HS_ETIMEOUT_HCI: case BLE_HS_ETIMEOUT_HCI:
@ -264,22 +267,22 @@ uint32_t NimBLEServer::getConnectedCount() {
NIMBLE_LOGC(LOG_TAG, "Disconnect - host reset, rc=%d", event->disconnect.reason); NIMBLE_LOGC(LOG_TAG, "Disconnect - host reset, rc=%d", event->disconnect.reason);
NimBLEDevice::onReset(event->disconnect.reason); NimBLEDevice::onReset(event->disconnect.reason);
break; break;
default: default:
break; break;
} }
server->removePeerDevice(event->disconnect.conn.conn_handle, false); server->removePeerDevice(event->disconnect.conn.conn_handle, false);
server->m_connId = BLE_HS_CONN_HANDLE_NONE; server->m_connId = BLE_HS_CONN_HANDLE_NONE;
server->m_pServerCallbacks->onDisconnect(server); server->m_pServerCallbacks->onDisconnect(server);
return 0; return 0;
} // BLE_GAP_EVENT_DISCONNECT } // BLE_GAP_EVENT_DISCONNECT
case BLE_GAP_EVENT_SUBSCRIBE: { case BLE_GAP_EVENT_SUBSCRIBE: {
NIMBLE_LOGI(LOG_TAG, "subscribe event; cur_notify=%d\n value handle; " NIMBLE_LOGI(LOG_TAG, "subscribe event; cur_notify=%d\n value handle; "
"val_handle=%d\n", "val_handle=%d\n",
event->subscribe.cur_notify, event->subscribe.attr_handle); event->subscribe.cur_notify, event->subscribe.attr_handle);
auto it = server->m_notifyChrMap.find(event->subscribe.attr_handle); auto it = server->m_notifyChrMap.find(event->subscribe.attr_handle);
if(it != server->m_notifyChrMap.cend()) { if(it != server->m_notifyChrMap.cend()) {
(*it).second->setSubscribe(event); (*it).second->setSubscribe(event);
@ -287,7 +290,7 @@ uint32_t NimBLEServer::getConnectedCount() {
return 0; return 0;
} // BLE_GAP_EVENT_SUBSCRIBE } // BLE_GAP_EVENT_SUBSCRIBE
case BLE_GAP_EVENT_MTU: { case BLE_GAP_EVENT_MTU: {
NIMBLE_LOGI(LOG_TAG, "mtu update event; conn_handle=%d mtu=%d", NIMBLE_LOGI(LOG_TAG, "mtu update event; conn_handle=%d mtu=%d",
event->mtu.conn_handle, event->mtu.conn_handle,
@ -295,7 +298,7 @@ uint32_t NimBLEServer::getConnectedCount() {
server->updatePeerMTU(event->mtu.conn_handle, event->mtu.value); server->updatePeerMTU(event->mtu.conn_handle, event->mtu.value);
return 0; return 0;
} // BLE_GAP_EVENT_MTU } // BLE_GAP_EVENT_MTU
case BLE_GAP_EVENT_NOTIFY_TX: { case BLE_GAP_EVENT_NOTIFY_TX: {
if(event->notify_tx.indication && event->notify_tx.status != 0) { if(event->notify_tx.indication && event->notify_tx.status != 0) {
auto it = server->m_notifyChrMap.find(event->notify_tx.attr_handle); auto it = server->m_notifyChrMap.find(event->notify_tx.attr_handle);
@ -303,15 +306,15 @@ uint32_t NimBLEServer::getConnectedCount() {
(*it).second->m_semaphoreConfEvt.give(event->notify_tx.status); (*it).second->m_semaphoreConfEvt.give(event->notify_tx.status);
} }
} }
return 0; return 0;
} // BLE_GAP_EVENT_NOTIFY_TX } // BLE_GAP_EVENT_NOTIFY_TX
case BLE_GAP_EVENT_CONN_UPDATE: { case BLE_GAP_EVENT_CONN_UPDATE: {
NIMBLE_LOGD(LOG_TAG, "Connection parameters updated."); NIMBLE_LOGD(LOG_TAG, "Connection parameters updated.");
return 0; return 0;
} // BLE_GAP_EVENT_CONN_UPDATE } // BLE_GAP_EVENT_CONN_UPDATE
case BLE_GAP_EVENT_REPEAT_PAIRING: { case BLE_GAP_EVENT_REPEAT_PAIRING: {
/* We already have a bond with the peer, but it is attempting to /* We already have a bond with the peer, but it is attempting to
* establish a new secure link. This app sacrifices security for * establish a new secure link. This app sacrifices security for
@ -328,8 +331,8 @@ uint32_t NimBLEServer::getConnectedCount() {
*/ */
return BLE_GAP_REPEAT_PAIRING_RETRY; return BLE_GAP_REPEAT_PAIRING_RETRY;
} // BLE_GAP_EVENT_REPEAT_PAIRING } // BLE_GAP_EVENT_REPEAT_PAIRING
case BLE_GAP_EVENT_ENC_CHANGE: { case BLE_GAP_EVENT_ENC_CHANGE: {
rc = ble_gap_conn_find(event->conn_update.conn_handle, &desc); rc = ble_gap_conn_find(event->conn_update.conn_handle, &desc);
if(rc != 0) { if(rc != 0) {
return BLE_ATT_ERR_INVALID_HANDLE; return BLE_ATT_ERR_INVALID_HANDLE;
@ -341,10 +344,10 @@ uint32_t NimBLEServer::getConnectedCount() {
} else { } else {
server->m_pServerCallbacks->onAuthenticationComplete(&desc); server->m_pServerCallbacks->onAuthenticationComplete(&desc);
} }
return 0; return 0;
} // BLE_GAP_EVENT_ENC_CHANGE } // BLE_GAP_EVENT_ENC_CHANGE
case BLE_GAP_EVENT_PASSKEY_ACTION: { case BLE_GAP_EVENT_PASSKEY_ACTION: {
struct ble_sm_io pkey = {0}; struct ble_sm_io pkey = {0};
@ -359,7 +362,7 @@ uint32_t NimBLEServer::getConnectedCount() {
} }
rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey); rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey);
NIMBLE_LOGD(LOG_TAG, "BLE_SM_IOACT_DISP; ble_sm_inject_io result: %d", rc); NIMBLE_LOGD(LOG_TAG, "BLE_SM_IOACT_DISP; ble_sm_inject_io result: %d", rc);
} else if (event->passkey.params.action == BLE_SM_IOACT_NUMCMP) { } else if (event->passkey.params.action == BLE_SM_IOACT_NUMCMP) {
NIMBLE_LOGD(LOG_TAG, "Passkey on device's display: %d", event->passkey.params.numcmp); NIMBLE_LOGD(LOG_TAG, "Passkey on device's display: %d", event->passkey.params.numcmp);
pkey.action = event->passkey.params.action; pkey.action = event->passkey.params.action;
@ -370,11 +373,11 @@ uint32_t NimBLEServer::getConnectedCount() {
} else { } else {
pkey.numcmp_accept = server->m_pServerCallbacks->onConfirmPIN(event->passkey.params.numcmp); pkey.numcmp_accept = server->m_pServerCallbacks->onConfirmPIN(event->passkey.params.numcmp);
} }
rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey); rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey);
NIMBLE_LOGD(LOG_TAG, "BLE_SM_IOACT_NUMCMP; ble_sm_inject_io result: %d", rc); NIMBLE_LOGD(LOG_TAG, "BLE_SM_IOACT_NUMCMP; ble_sm_inject_io result: %d", rc);
//TODO: Handle out of band pairing //TODO: Handle out of band pairing
} else if (event->passkey.params.action == BLE_SM_IOACT_OOB) { } else if (event->passkey.params.action == BLE_SM_IOACT_OOB) {
static uint8_t tem_oob[16] = {0}; static uint8_t tem_oob[16] = {0};
pkey.action = event->passkey.params.action; pkey.action = event->passkey.params.action;
@ -383,35 +386,35 @@ uint32_t NimBLEServer::getConnectedCount() {
} }
rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey); rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey);
NIMBLE_LOGD(LOG_TAG, "BLE_SM_IOACT_OOB; ble_sm_inject_io result: %d", rc); NIMBLE_LOGD(LOG_TAG, "BLE_SM_IOACT_OOB; ble_sm_inject_io result: %d", rc);
////////////////////////////////// //////////////////////////////////
} else if (event->passkey.params.action == BLE_SM_IOACT_INPUT) { } else if (event->passkey.params.action == BLE_SM_IOACT_INPUT) {
NIMBLE_LOGD(LOG_TAG, "Enter the passkey"); NIMBLE_LOGD(LOG_TAG, "Enter the passkey");
pkey.action = event->passkey.params.action; pkey.action = event->passkey.params.action;
// Compatibility only - Do not use, should be removed the in future // Compatibility only - Do not use, should be removed the in future
if(NimBLEDevice::m_securityCallbacks != nullptr) { if(NimBLEDevice::m_securityCallbacks != nullptr) {
pkey.passkey = NimBLEDevice::m_securityCallbacks->onPassKeyRequest(); pkey.passkey = NimBLEDevice::m_securityCallbacks->onPassKeyRequest();
///////////////////////////////////////////// /////////////////////////////////////////////
} else { } else {
pkey.passkey = server->m_pServerCallbacks->onPassKeyRequest(); pkey.passkey = server->m_pServerCallbacks->onPassKeyRequest();
} }
rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey); rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey);
NIMBLE_LOGD(LOG_TAG, "BLE_SM_IOACT_INPUT; ble_sm_inject_io result: %d", rc); NIMBLE_LOGD(LOG_TAG, "BLE_SM_IOACT_INPUT; ble_sm_inject_io result: %d", rc);
} else if (event->passkey.params.action == BLE_SM_IOACT_NONE) { } else if (event->passkey.params.action == BLE_SM_IOACT_NONE) {
NIMBLE_LOGD(LOG_TAG, "No passkey action required"); NIMBLE_LOGD(LOG_TAG, "No passkey action required");
} }
NIMBLE_LOGD(LOG_TAG, "<< handleGATTServerEvent"); NIMBLE_LOGD(LOG_TAG, "<< handleGATTServerEvent");
return 0; return 0;
} // BLE_GAP_EVENT_PASSKEY_ACTION } // BLE_GAP_EVENT_PASSKEY_ACTION
default: default:
break; break;
} }
NIMBLE_LOGD(LOG_TAG, "<< handleGATTServerEvent"); NIMBLE_LOGD(LOG_TAG, "<< handleGATTServerEvent");
return 0; return 0;
} // handleGATTServerEvent } // handleGATTServerEvent
@ -427,10 +430,10 @@ uint32_t NimBLEServer::getConnectedCount() {
*/ */
void NimBLEServer::setCallbacks(NimBLEServerCallbacks* pCallbacks) { void NimBLEServer::setCallbacks(NimBLEServerCallbacks* pCallbacks) {
if (pCallbacks != nullptr){ if (pCallbacks != nullptr){
m_pServerCallbacks = pCallbacks; m_pServerCallbacks = pCallbacks;
} else { } else {
m_pServerCallbacks = &defaultCallbacks; m_pServerCallbacks = &defaultCallbacks;
} }
} // setCallbacks } // setCallbacks
@ -439,9 +442,9 @@ void NimBLEServer::setCallbacks(NimBLEServerCallbacks* pCallbacks) {
*/ */
/* /*
void BLEServer::removeService(BLEService* service) { void BLEServer::removeService(BLEService* service) {
service->stop(); service->stop();
service->executeDelete(); service->executeDelete();
m_serviceMap.removeService(service); m_serviceMap.removeService(service);
} }
*/ */
@ -453,9 +456,9 @@ void BLEServer::removeService(BLEService* service) {
* retrieving the advertising object and invoking start upon it. * retrieving the advertising object and invoking start upon it.
*/ */
void NimBLEServer::startAdvertising() { void NimBLEServer::startAdvertising() {
NIMBLE_LOGD(LOG_TAG, ">> startAdvertising"); NIMBLE_LOGD(LOG_TAG, ">> startAdvertising");
NimBLEDevice::startAdvertising(); NimBLEDevice::startAdvertising();
NIMBLE_LOGD(LOG_TAG, "<< startAdvertising"); NIMBLE_LOGD(LOG_TAG, "<< startAdvertising");
} // startAdvertising } // startAdvertising
@ -463,51 +466,51 @@ void NimBLEServer::startAdvertising() {
* @brief Stop advertising. * @brief Stop advertising.
*/ */
void NimBLEServer::stopAdvertising() { void NimBLEServer::stopAdvertising() {
NIMBLE_LOGD(LOG_TAG, ">> stopAdvertising"); NIMBLE_LOGD(LOG_TAG, ">> stopAdvertising");
NimBLEDevice::stopAdvertising(); NimBLEDevice::stopAdvertising();
NIMBLE_LOGD(LOG_TAG, "<< stopAdvertising"); NIMBLE_LOGD(LOG_TAG, "<< stopAdvertising");
} // startAdvertising } // startAdvertising
/** /**
* Allow to connect GATT server to peer device * Allow to connect GATT server to peer device
* Probably can be used in ANCS for iPhone * Probably can be used in ANCS for iPhone
*/ */
/* /*
bool BLEServer::connect(BLEAddress address) { bool BLEServer::connect(BLEAddress address) {
esp_bd_addr_t addr; esp_bd_addr_t addr;
memcpy(&addr, address.getNative(), 6); memcpy(&addr, address.getNative(), 6);
// Perform the open connection request against the target BLE Server. // Perform the open connection request against the target BLE Server.
m_semaphoreOpenEvt.take("connect"); m_semaphoreOpenEvt.take("connect");
esp_err_t errRc = ::esp_ble_gatts_open( esp_err_t errRc = ::esp_ble_gatts_open(
getGattsIf(), getGattsIf(),
addr, // address addr, // address
1 // direct connection 1 // direct connection
); );
if (errRc != ESP_OK) { if (errRc != ESP_OK) {
ESP_LOGE(LOG_TAG, "esp_ble_gattc_open: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); ESP_LOGE(LOG_TAG, "esp_ble_gattc_open: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
return false; return false;
} }
uint32_t rc = m_semaphoreOpenEvt.wait("connect"); // Wait for the connection to complete. uint32_t rc = m_semaphoreOpenEvt.wait("connect"); // Wait for the connection to complete.
ESP_LOGD(LOG_TAG, "<< connect(), rc=%d", rc==ESP_GATT_OK); ESP_LOGD(LOG_TAG, "<< connect(), rc=%d", rc==ESP_GATT_OK);
return rc == ESP_GATT_OK; return rc == ESP_GATT_OK;
} // connect } // connect
*/ */
void NimBLEServerCallbacks::onConnect(NimBLEServer* pServer) { void NimBLEServerCallbacks::onConnect(NimBLEServer* pServer) {
NIMBLE_LOGD("NimBLEServerCallbacks", "onConnect(): Default"); NIMBLE_LOGD("NimBLEServerCallbacks", "onConnect(): Default");
} // onConnect } // onConnect
void NimBLEServerCallbacks::onConnect(NimBLEServer* pServer, ble_gap_conn_desc* desc) { void NimBLEServerCallbacks::onConnect(NimBLEServer* pServer, ble_gap_conn_desc* desc) {
NIMBLE_LOGD("NimBLEServerCallbacks", "onConnect(): Default"); NIMBLE_LOGD("NimBLEServerCallbacks", "onConnect(): Default");
} // onConnect } // onConnect
void NimBLEServerCallbacks::onDisconnect(NimBLEServer* pServer) { void NimBLEServerCallbacks::onDisconnect(NimBLEServer* pServer) {
NIMBLE_LOGD("NimBLEServerCallbacks", "onDisconnect(): Default"); NIMBLE_LOGD("NimBLEServerCallbacks", "onDisconnect(): Default");
} // onDisconnect } // onDisconnect
uint32_t NimBLEServerCallbacks::onPassKeyRequest(){ uint32_t NimBLEServerCallbacks::onPassKeyRequest(){
@ -533,14 +536,14 @@ bool NimBLEServerCallbacks::onConfirmPIN(uint32_t pin){
/* multi connect support */ /* multi connect support */
void NimBLEServer::updatePeerMTU(uint16_t conn_id, uint16_t mtu) { void NimBLEServer::updatePeerMTU(uint16_t conn_id, uint16_t mtu) {
const std::map<uint16_t, conn_status_t>::iterator it = m_connectedServersMap.find(conn_id); const std::map<uint16_t, conn_status_t>::iterator it = m_connectedServersMap.find(conn_id);
if (it != m_connectedServersMap.end()) { if (it != m_connectedServersMap.end()) {
it->second.mtu = mtu; it->second.mtu = mtu;
} }
} }
std::map<uint16_t, conn_status_t> NimBLEServer::getPeerDevices() { std::map<uint16_t, conn_status_t> NimBLEServer::getPeerDevices() {
return m_connectedServersMap; return m_connectedServersMap;
} }
@ -558,17 +561,17 @@ uint16_t NimBLEServer::getPeerMTU(uint16_t conn_id) {
} }
void NimBLEServer::addPeerDevice(void* peer, bool _client, uint16_t conn_id) { void NimBLEServer::addPeerDevice(void* peer, bool _client, uint16_t conn_id) {
conn_status_t status = { conn_status_t status = {
.peer_device = peer, .peer_device = peer,
.connected = true, .connected = true,
.mtu = 23 .mtu = 23
}; };
m_connectedServersMap.insert(std::pair<uint16_t, conn_status_t>(conn_id, status)); m_connectedServersMap.insert(std::pair<uint16_t, conn_status_t>(conn_id, status));
} }
void NimBLEServer::removePeerDevice(uint16_t conn_id, bool _client) { void NimBLEServer::removePeerDevice(uint16_t conn_id, bool _client) {
m_connectedServersMap.erase(conn_id); m_connectedServersMap.erase(conn_id);
} }
/* multi connect support */ /* multi connect support */
@ -576,20 +579,20 @@ void NimBLEServer::removePeerDevice(uint16_t conn_id, bool _client) {
/** /**
* Update connection parameters can be called only after connection has been established * Update connection parameters can be called only after connection has been established
*/ */
void NimBLEServer::updateConnParams(uint16_t conn_handle, void NimBLEServer::updateConnParams(uint16_t conn_handle,
uint16_t minInterval, uint16_t maxInterval, uint16_t minInterval, uint16_t maxInterval,
uint16_t latency, uint16_t timeout, uint16_t latency, uint16_t timeout,
uint16_t minConnTime, uint16_t maxConnTime) uint16_t minConnTime, uint16_t maxConnTime)
{ {
ble_gap_upd_params params; ble_gap_upd_params params;
params.latency = latency; params.latency = latency;
params.itvl_max = maxInterval; // max_int = 0x20*1.25ms = 40ms params.itvl_max = maxInterval; // max_int = 0x20*1.25ms = 40ms
params.itvl_min = minInterval; // min_int = 0x10*1.25ms = 20ms params.itvl_min = minInterval; // min_int = 0x10*1.25ms = 20ms
params.supervision_timeout = timeout; // timeout = 400*10ms = 4000ms params.supervision_timeout = timeout; // timeout = 400*10ms = 4000ms
params.min_ce_len = minConnTime; // Minimum length of connection event in 0.625ms units params.min_ce_len = minConnTime; // Minimum length of connection event in 0.625ms units
params.max_ce_len = maxConnTime; // Maximum length of connection event in 0.625ms units params.max_ce_len = maxConnTime; // Maximum length of connection event in 0.625ms units
int rc = ble_gap_update_params(conn_handle, &params); int rc = ble_gap_update_params(conn_handle, &params);
if(rc != 0) { if(rc != 0) {
NIMBLE_LOGE(LOG_TAG, "Update params error: %d, %s", rc, NimBLEUtils::returnCodeToString(rc)); NIMBLE_LOGE(LOG_TAG, "Update params error: %d, %s", rc, NimBLEUtils::returnCodeToString(rc));
@ -602,7 +605,9 @@ void NimBLEServer::onHostReset() {
for(auto it = m_notifyChrMap.cbegin(); it != m_notifyChrMap.cend(); ++it) { for(auto it = m_notifyChrMap.cbegin(); it != m_notifyChrMap.cend(); ++it) {
(*it).second->m_semaphoreConfEvt.give(0); (*it).second->m_semaphoreConfEvt.give(0);
} }
} }
*/ */
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#endif // CONFIG_BT_ENABLED #endif // CONFIG_BT_ENABLED

View file

@ -3,7 +3,7 @@
* *
* Created: on March 2, 2020 * Created: on March 2, 2020
* Author H2zero * Author H2zero
* *
* Originally: * Originally:
* *
* BLEServer.h * BLEServer.h
@ -17,6 +17,9 @@
#include "sdkconfig.h" #include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED) #if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h"
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#include "NimBLEAddress.h" #include "NimBLEAddress.h"
#include "NimBLEUUID.h" #include "NimBLEUUID.h"
#include "NimBLEAdvertising.h" #include "NimBLEAdvertising.h"
@ -24,14 +27,13 @@
#include "NimBLESecurity.h" #include "NimBLESecurity.h"
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include <map> #include <map>
class NimBLEService; class NimBLEService;
class NimBLECharacteristic; class NimBLECharacteristic;
class NimBLEServerCallbacks; class NimBLEServerCallbacks;
/* TODO possibly refactor this struct */ /* TODO possibly refactor this struct */
typedef struct { typedef struct {
void *peer_device; // peer device BLEClient or BLEServer - maybe its better to have 2 structures or union here void *peer_device; // peer device BLEClient or BLEServer - maybe its better to have 2 structures or union here
bool connected; // do we need it? bool connected; // do we need it?
@ -45,7 +47,7 @@ typedef struct {
class NimBLEServiceMap { class NimBLEServiceMap {
public: public:
// NimBLEService* getByHandle(uint16_t handle); // NimBLEService* getByHandle(uint16_t handle);
NimBLEService* getByUUID(const char* uuid); NimBLEService* getByUUID(const char* uuid);
NimBLEService* getByUUID(const NimBLEUUID &uuid, uint8_t inst_id = 0); NimBLEService* getByUUID(const NimBLEUUID &uuid, uint8_t inst_id = 0);
// void setByHandle(uint16_t handle, NimBLEService* service); // void setByHandle(uint16_t handle, NimBLEService* service);
void setByUUID(const char* uuid, NimBLEService* service); void setByUUID(const char* uuid, NimBLEService* service);
@ -69,7 +71,7 @@ private:
class NimBLEServer { class NimBLEServer {
public: public:
uint32_t getConnectedCount(); uint32_t getConnectedCount();
NimBLEService* createService(const char* uuid); NimBLEService* createService(const char* uuid);
NimBLEService* createService(const NimBLEUUID &uuid, uint32_t numHandles=15, uint8_t inst_id=0); NimBLEService* createService(const NimBLEUUID &uuid, uint32_t numHandles=15, uint8_t inst_id=0);
NimBLEAdvertising* getAdvertising(); NimBLEAdvertising* getAdvertising();
void setCallbacks(NimBLEServerCallbacks* pCallbacks); void setCallbacks(NimBLEServerCallbacks* pCallbacks);
@ -81,8 +83,8 @@ public:
NimBLEService* getServiceByUUID(const NimBLEUUID &uuid); NimBLEService* getServiceByUUID(const NimBLEUUID &uuid);
int disconnect(uint16_t connID, uint8_t reason = BLE_ERR_REM_USER_CONN_TERM); int disconnect(uint16_t connID, uint8_t reason = BLE_ERR_REM_USER_CONN_TERM);
// bool connect(BLEAddress address); // bool connect(BLEAddress address);
void updateConnParams(uint16_t conn_handle, void updateConnParams(uint16_t conn_handle,
uint16_t minInterval, uint16_t maxInterval, uint16_t minInterval, uint16_t maxInterval,
uint16_t latency, uint16_t timeout, uint16_t latency, uint16_t timeout,
uint16_t minConnTime=0, uint16_t maxConnTime=0); uint16_t minConnTime=0, uint16_t maxConnTime=0);
@ -106,15 +108,15 @@ private:
// BLEAdvertising m_bleAdvertising; // BLEAdvertising m_bleAdvertising;
uint16_t m_connId; uint16_t m_connId;
uint16_t m_svcChgChrHdl; uint16_t m_svcChgChrHdl;
bool m_gattsStarted; bool m_gattsStarted;
std::map<uint16_t, conn_status_t> m_connectedServersMap; std::map<uint16_t, conn_status_t> m_connectedServersMap;
std::map<uint16_t, NimBLECharacteristic*> m_notifyChrMap; std::map<uint16_t, NimBLECharacteristic*> m_notifyChrMap;
NimBLEServiceMap m_serviceMap; NimBLEServiceMap m_serviceMap;
NimBLEServerCallbacks* m_pServerCallbacks; NimBLEServerCallbacks* m_pServerCallbacks;
static int handleGapEvent(struct ble_gap_event *event, void *arg); static int handleGapEvent(struct ble_gap_event *event, void *arg);
}; // NimBLEServer }; // NimBLEServer
@ -141,7 +143,7 @@ public:
* @param [in] pServer A reference to the %BLE server that received the existing client disconnection. * @param [in] pServer A reference to the %BLE server that received the existing client disconnection.
*/ */
virtual void onDisconnect(NimBLEServer* pServer); virtual void onDisconnect(NimBLEServer* pServer);
virtual uint32_t onPassKeyRequest(); //{return 0;} virtual uint32_t onPassKeyRequest(); //{return 0;}
virtual void onPassKeyNotify(uint32_t pass_key); //{} virtual void onPassKeyNotify(uint32_t pass_key); //{}
virtual bool onSecurityRequest(); //{return true;} virtual bool onSecurityRequest(); //{return true;}
@ -150,5 +152,6 @@ public:
}; // BLEServerCallbacks }; // BLEServerCallbacks
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#endif /* CONFIG_BT_ENABLED */ #endif /* CONFIG_BT_ENABLED */
#endif /* MAIN_NIMBLESERVER_H_ */ #endif /* MAIN_NIMBLESERVER_H_ */

View file

@ -3,7 +3,7 @@
* *
* Created: on March 2, 2020 * Created: on March 2, 2020
* Author H2zero * Author H2zero
* *
* Originally: * Originally:
* *
* BLEService.cpp * BLEService.cpp
@ -17,6 +17,9 @@
#include "sdkconfig.h" #include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED) #if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h"
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#include "NimBLEService.h" #include "NimBLEService.h"
#include "NimBLEUtils.h" #include "NimBLEUtils.h"
#include "NimBLELog.h" #include "NimBLELog.h"
@ -33,7 +36,7 @@ static const char* LOG_TAG = "NimBLEService"; // Tag for logging.
* @param [in] uuid The UUID of the service. * @param [in] uuid The UUID of the service.
* @param [in] numHandles The maximum number of handles associated with the service. * @param [in] numHandles The maximum number of handles associated with the service.
*/ */
NimBLEService::NimBLEService(const char* uuid, uint16_t numHandles, NimBLEServer* pServer) NimBLEService::NimBLEService(const char* uuid, uint16_t numHandles, NimBLEServer* pServer)
: NimBLEService(NimBLEUUID(uuid), numHandles, pServer) { : NimBLEService(NimBLEUUID(uuid), numHandles, pServer) {
} }
@ -44,10 +47,10 @@ NimBLEService::NimBLEService(const char* uuid, uint16_t numHandles, NimBLEServer
* @param [in] numHandles The maximum number of handles associated with the service. * @param [in] numHandles The maximum number of handles associated with the service.
*/ */
NimBLEService::NimBLEService(const NimBLEUUID &uuid, uint16_t numHandles, NimBLEServer* pServer) { NimBLEService::NimBLEService(const NimBLEUUID &uuid, uint16_t numHandles, NimBLEServer* pServer) {
m_uuid = uuid; m_uuid = uuid;
m_handle = NULL_HANDLE; m_handle = NULL_HANDLE;
m_pServer = pServer; m_pServer = pServer;
m_numHandles = numHandles; m_numHandles = numHandles;
} // NimBLEService } // NimBLEService
@ -56,10 +59,10 @@ NimBLEService::NimBLEService(const NimBLEUUID &uuid, uint16_t numHandles, NimBLE
* @return N/A. * @return N/A.
*/ */
void NimBLEService::dump() { void NimBLEService::dump() {
NIMBLE_LOGD(LOG_TAG, "Service: uuid:%s, handle: 0x%.2x", NIMBLE_LOGD(LOG_TAG, "Service: uuid:%s, handle: 0x%.2x",
m_uuid.toString().c_str(), m_uuid.toString().c_str(),
m_handle); m_handle);
NIMBLE_LOGD(LOG_TAG, "Characteristics:\n%s", m_characteristicMap.toString().c_str()); NIMBLE_LOGD(LOG_TAG, "Characteristics:\n%s", m_characteristicMap.toString().c_str());
} // dump } // dump
@ -68,7 +71,7 @@ void NimBLEService::dump() {
* @return the UUID of the service. * @return the UUID of the service.
*/ */
NimBLEUUID NimBLEService::getUUID() { NimBLEUUID NimBLEService::getUUID() {
return m_uuid; return m_uuid;
} // getUUID } // getUUID
@ -78,46 +81,46 @@ NimBLEUUID NimBLEService::getUUID() {
* Starting a service also means that we can create the corresponding characteristics. * Starting a service also means that we can create the corresponding characteristics.
* @return Start the service. * @return Start the service.
*/ */
bool NimBLEService::start() { bool NimBLEService::start() {
NIMBLE_LOGD(LOG_TAG, ">> start(): Starting service: %s", toString().c_str()); NIMBLE_LOGD(LOG_TAG, ">> start(): Starting service: %s", toString().c_str());
int rc = 0; int rc = 0;
// Nimble requires an array of services to be sent to the api // Nimble requires an array of services to be sent to the api
// Since we are adding 1 at a time we create an array of 2 and set the type // Since we are adding 1 at a time we create an array of 2 and set the type
// of the second service to 0 to indicate the end of the array. // of the second service to 0 to indicate the end of the array.
ble_gatt_svc_def* svc = new ble_gatt_svc_def[2]; ble_gatt_svc_def* svc = new ble_gatt_svc_def[2];
ble_gatt_chr_def* pChr_a = nullptr; ble_gatt_chr_def* pChr_a = nullptr;
ble_gatt_dsc_def* pDsc_a = nullptr; ble_gatt_dsc_def* pDsc_a = nullptr;
svc[0].type = BLE_GATT_SVC_TYPE_PRIMARY; svc[0].type = BLE_GATT_SVC_TYPE_PRIMARY;
svc[0].uuid = &m_uuid.getNative()->u; svc[0].uuid = &m_uuid.getNative()->u;
svc[0].includes = NULL; svc[0].includes = NULL;
uint8_t numChrs = m_characteristicMap.getSize(); uint8_t numChrs = m_characteristicMap.getSize();
NIMBLE_LOGD(LOG_TAG,"Adding %d characteristics for service %s", numChrs, toString().c_str()); NIMBLE_LOGD(LOG_TAG,"Adding %d characteristics for service %s", numChrs, toString().c_str());
if(!numChrs){ if(!numChrs){
svc[0].characteristics = NULL; svc[0].characteristics = NULL;
}else{ }else{
// Nimble requires the last characteristic to have it's uuid = 0 to indicate the end // Nimble requires the last characteristic to have it's uuid = 0 to indicate the end
// of the characteristics for the service. We create 1 extra and set it to null // of the characteristics for the service. We create 1 extra and set it to null
// for this purpose. // for this purpose.
pChr_a = new ble_gatt_chr_def[numChrs+1]; pChr_a = new ble_gatt_chr_def[numChrs+1];
NimBLECharacteristic* pCharacteristic = m_characteristicMap.getFirst(); NimBLECharacteristic* pCharacteristic = m_characteristicMap.getFirst();
for(uint8_t i=0; i < numChrs; i++) { for(uint8_t i=0; i < numChrs; i++) {
uint8_t numDscs = pCharacteristic->m_descriptorMap.getSize(); uint8_t numDscs = pCharacteristic->m_descriptorMap.getSize();
if(numDscs) { if(numDscs) {
// skip 2902 as it's automatically created by NimBLE // skip 2902 as it's automatically created by NimBLE
// if Indicate or Notify flags are set // if Indicate or Notify flags are set
if(((pCharacteristic->m_properties & BLE_GATT_CHR_F_INDICATE) || if(((pCharacteristic->m_properties & BLE_GATT_CHR_F_INDICATE) ||
(pCharacteristic->m_properties & BLE_GATT_CHR_F_NOTIFY)) && (pCharacteristic->m_properties & BLE_GATT_CHR_F_NOTIFY)) &&
pCharacteristic->getDescriptorByUUID("2902") != nullptr) { pCharacteristic->getDescriptorByUUID("2902") != nullptr) {
numDscs--; numDscs--;
} }
} }
if(!numDscs){ if(!numDscs){
pChr_a[i].descriptors = NULL; pChr_a[i].descriptors = NULL;
} else { } else {
@ -140,41 +143,41 @@ bool NimBLEService::start() {
pDescriptor = pCharacteristic->m_descriptorMap.getNext(); pDescriptor = pCharacteristic->m_descriptorMap.getNext();
d++; d++;
} }
pDsc_a[numDscs].uuid = NULL; pDsc_a[numDscs].uuid = NULL;
pChr_a[i].descriptors = pDsc_a; pChr_a[i].descriptors = pDsc_a;
} }
pChr_a[i].uuid = &pCharacteristic->m_uuid.getNative()->u; pChr_a[i].uuid = &pCharacteristic->m_uuid.getNative()->u;
pChr_a[i].access_cb = NimBLECharacteristic::handleGapEvent; pChr_a[i].access_cb = NimBLECharacteristic::handleGapEvent;
pChr_a[i].arg = pCharacteristic; pChr_a[i].arg = pCharacteristic;
pChr_a[i].flags = pCharacteristic->m_properties; pChr_a[i].flags = pCharacteristic->m_properties;
pChr_a[i].min_key_size = 0; pChr_a[i].min_key_size = 0;
pChr_a[i].val_handle = &pCharacteristic->m_handle; pChr_a[i].val_handle = &pCharacteristic->m_handle;
pCharacteristic = m_characteristicMap.getNext(); pCharacteristic = m_characteristicMap.getNext();
} }
pChr_a[numChrs].uuid = NULL; pChr_a[numChrs].uuid = NULL;
svc[0].characteristics = pChr_a; svc[0].characteristics = pChr_a;
} }
// end of services must indicate to api with type = 0 // end of services must indicate to api with type = 0
svc[1].type = 0; svc[1].type = 0;
rc = ble_gatts_count_cfg((const ble_gatt_svc_def*)svc); rc = ble_gatts_count_cfg((const ble_gatt_svc_def*)svc);
if (rc != 0) { if (rc != 0) {
NIMBLE_LOGE(LOG_TAG, "ble_gatts_count_cfg failed, rc= %d, %s", rc, NimBLEUtils::returnCodeToString(rc)); NIMBLE_LOGE(LOG_TAG, "ble_gatts_count_cfg failed, rc= %d, %s", rc, NimBLEUtils::returnCodeToString(rc));
return false; return false;
} }
rc = ble_gatts_add_svcs((const ble_gatt_svc_def*)svc); rc = ble_gatts_add_svcs((const ble_gatt_svc_def*)svc);
if (rc != 0) { if (rc != 0) {
NIMBLE_LOGE(LOG_TAG, "ble_gatts_add_svcs, rc= %d, %s", rc, NimBLEUtils::returnCodeToString(rc)); NIMBLE_LOGE(LOG_TAG, "ble_gatts_add_svcs, rc= %d, %s", rc, NimBLEUtils::returnCodeToString(rc));
return false; return false;
} }
NIMBLE_LOGD(LOG_TAG, "<< start()"); NIMBLE_LOGD(LOG_TAG, "<< start()");
return true; return true;
} // start } // start
@ -184,13 +187,13 @@ bool NimBLEService::start() {
* @param [in] handle The handle associated with the service. * @param [in] handle The handle associated with the service.
*/ */
void NimBLEService::setHandle(uint16_t handle) { void NimBLEService::setHandle(uint16_t handle) {
NIMBLE_LOGD(LOG_TAG, ">> setHandle - Handle=0x%.2x, service UUID=%s)", handle, getUUID().toString().c_str()); NIMBLE_LOGD(LOG_TAG, ">> setHandle - Handle=0x%.2x, service UUID=%s)", handle, getUUID().toString().c_str());
if (m_handle != NULL_HANDLE) { if (m_handle != NULL_HANDLE) {
NIMBLE_LOGE(LOG_TAG, "!!! Handle is already set %.2x", m_handle); NIMBLE_LOGE(LOG_TAG, "!!! Handle is already set %.2x", m_handle);
return; return;
} }
m_handle = handle; m_handle = handle;
NIMBLE_LOGD(LOG_TAG, "<< setHandle"); NIMBLE_LOGD(LOG_TAG, "<< setHandle");
} // setHandle } // setHandle
@ -199,7 +202,7 @@ void NimBLEService::setHandle(uint16_t handle) {
* @return The handle associated with this service. * @return The handle associated with this service.
*/ */
uint16_t NimBLEService::getHandle() { uint16_t NimBLEService::getHandle() {
return m_handle; return m_handle;
} // getHandle } // getHandle
@ -208,26 +211,26 @@ uint16_t NimBLEService::getHandle() {
* @param [in] pCharacteristic A pointer to the characteristic to be added. * @param [in] pCharacteristic A pointer to the characteristic to be added.
*/ */
void NimBLEService::addCharacteristic(NimBLECharacteristic* pCharacteristic) { void NimBLEService::addCharacteristic(NimBLECharacteristic* pCharacteristic) {
// We maintain a mapping of characteristics owned by this service. These are managed by the // We maintain a mapping of characteristics owned by this service. These are managed by the
// BLECharacteristicMap class instance found in m_characteristicMap. We add the characteristic // BLECharacteristicMap class instance found in m_characteristicMap. We add the characteristic
// to the map and then ask the service to add the characteristic at the BLE level (ESP-IDF). // to the map and then ask the service to add the characteristic at the BLE level (ESP-IDF).
NIMBLE_LOGD(LOG_TAG, ">> addCharacteristic()"); NIMBLE_LOGD(LOG_TAG, ">> addCharacteristic()");
NIMBLE_LOGD(LOG_TAG, "Adding characteristic: uuid=%s to service: %s", NIMBLE_LOGD(LOG_TAG, "Adding characteristic: uuid=%s to service: %s",
pCharacteristic->getUUID().toString().c_str(), pCharacteristic->getUUID().toString().c_str(),
toString().c_str()); toString().c_str());
// Check that we don't add the same characteristic twice. // Check that we don't add the same characteristic twice.
if (m_characteristicMap.getByUUID(pCharacteristic->getUUID()) != nullptr) { if (m_characteristicMap.getByUUID(pCharacteristic->getUUID()) != nullptr) {
NIMBLE_LOGW(LOG_TAG, "<< Adding a new characteristic with the same UUID as a previous one"); NIMBLE_LOGW(LOG_TAG, "<< Adding a new characteristic with the same UUID as a previous one");
//return; //return;
} }
// Remember this characteristic in our map of characteristics. At this point, we can lookup by UUID // Remember this characteristic in our map of characteristics. At this point, we can lookup by UUID
// but not by handle. The handle is allocated to us on the ESP_GATTS_ADD_CHAR_EVT. // but not by handle. The handle is allocated to us on the ESP_GATTS_ADD_CHAR_EVT.
m_characteristicMap.setByUUID(pCharacteristic, pCharacteristic->getUUID()); m_characteristicMap.setByUUID(pCharacteristic, pCharacteristic->getUUID());
NIMBLE_LOGD(LOG_TAG, "<< addCharacteristic()"); NIMBLE_LOGD(LOG_TAG, "<< addCharacteristic()");
} // addCharacteristic } // addCharacteristic
@ -238,7 +241,7 @@ void NimBLEService::addCharacteristic(NimBLECharacteristic* pCharacteristic) {
* @return The new BLE characteristic. * @return The new BLE characteristic.
*/ */
NimBLECharacteristic* NimBLEService::createCharacteristic(const char* uuid, uint32_t properties) { NimBLECharacteristic* NimBLEService::createCharacteristic(const char* uuid, uint32_t properties) {
return createCharacteristic(NimBLEUUID(uuid), properties); return createCharacteristic(NimBLEUUID(uuid), properties);
} }
@ -249,20 +252,20 @@ NimBLECharacteristic* NimBLEService::createCharacteristic(const char* uuid, uint
* @return The new BLE characteristic. * @return The new BLE characteristic.
*/ */
NimBLECharacteristic* NimBLEService::createCharacteristic(const NimBLEUUID &uuid, uint32_t properties) { NimBLECharacteristic* NimBLEService::createCharacteristic(const NimBLEUUID &uuid, uint32_t properties) {
NimBLECharacteristic* pCharacteristic = new NimBLECharacteristic(uuid, properties, this); NimBLECharacteristic* pCharacteristic = new NimBLECharacteristic(uuid, properties, this);
addCharacteristic(pCharacteristic); addCharacteristic(pCharacteristic);
//pCharacteristic->executeCreate(this); //pCharacteristic->executeCreate(this);
return pCharacteristic; return pCharacteristic;
} // createCharacteristic } // createCharacteristic
NimBLECharacteristic* NimBLEService::getCharacteristic(const char* uuid) { NimBLECharacteristic* NimBLEService::getCharacteristic(const char* uuid) {
return getCharacteristic(NimBLEUUID(uuid)); return getCharacteristic(NimBLEUUID(uuid));
} }
NimBLECharacteristic* NimBLEService::getCharacteristic(const NimBLEUUID &uuid) { NimBLECharacteristic* NimBLEService::getCharacteristic(const NimBLEUUID &uuid) {
return m_characteristicMap.getByUUID(uuid); return m_characteristicMap.getByUUID(uuid);
} }
@ -274,12 +277,12 @@ NimBLECharacteristic* NimBLEService::getCharacteristic(const NimBLEUUID &uuid) {
* @return A string representation of this service. * @return A string representation of this service.
*/ */
std::string NimBLEService::toString() { std::string NimBLEService::toString() {
std::string res = "UUID: " + getUUID().toString(); std::string res = "UUID: " + getUUID().toString();
char hex[5]; char hex[5];
snprintf(hex, sizeof(hex), "%04x", getHandle()); snprintf(hex, sizeof(hex), "%04x", getHandle());
res += ", handle: 0x"; res += ", handle: 0x";
res += hex; res += hex;
return res; return res;
} // toString } // toString
@ -288,7 +291,8 @@ std::string NimBLEService::toString() {
* @return The BLEServer associated with this service. * @return The BLEServer associated with this service.
*/ */
NimBLEServer* NimBLEService::getServer() { NimBLEServer* NimBLEService::getServer() {
return m_pServer; return m_pServer;
} // getServer } // getServer
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#endif // CONFIG_BT_ENABLED #endif // CONFIG_BT_ENABLED

View file

@ -3,7 +3,7 @@
* *
* Created: on March 2, 2020 * Created: on March 2, 2020
* Author H2zero * Author H2zero
* *
* Originally: * Originally:
* *
* BLEService.h * BLEService.h
@ -17,6 +17,9 @@
#include "sdkconfig.h" #include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED) #if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h"
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#include "NimBLECharacteristic.h" #include "NimBLECharacteristic.h"
#include "NimBLEServer.h" #include "NimBLEServer.h"
#include "NimBLEUUID.h" #include "NimBLEUUID.h"
@ -31,21 +34,21 @@ class NimBLECharacteristic;
*/ */
class NimBLECharacteristicMap { class NimBLECharacteristicMap {
public: public:
void setByUUID(NimBLECharacteristic* pCharacteristic, const char* uuid); void setByUUID(NimBLECharacteristic* pCharacteristic, const char* uuid);
void setByUUID(NimBLECharacteristic* pCharacteristic, const NimBLEUUID &uuid); void setByUUID(NimBLECharacteristic* pCharacteristic, const NimBLEUUID &uuid);
void setByHandle(uint16_t handle, NimBLECharacteristic* pCharacteristic); void setByHandle(uint16_t handle, NimBLECharacteristic* pCharacteristic);
NimBLECharacteristic* getByUUID(const char* uuid); NimBLECharacteristic* getByUUID(const char* uuid);
NimBLECharacteristic* getByUUID(const NimBLEUUID &uuid); NimBLECharacteristic* getByUUID(const NimBLEUUID &uuid);
NimBLECharacteristic* getByHandle(uint16_t handle); NimBLECharacteristic* getByHandle(uint16_t handle);
NimBLECharacteristic* getFirst(); NimBLECharacteristic* getFirst();
NimBLECharacteristic* getNext(); NimBLECharacteristic* getNext();
uint8_t getSize(); uint8_t getSize();
std::string toString(); std::string toString();
private: private:
std::map<NimBLECharacteristic*, std::string> m_uuidMap; std::map<NimBLECharacteristic*, std::string> m_uuidMap;
std::map<uint16_t, NimBLECharacteristic*> m_handleMap; std::map<uint16_t, NimBLECharacteristic*> m_handleMap;
std::map<NimBLECharacteristic*, std::string>::iterator m_iterator; std::map<NimBLECharacteristic*, std::string>::iterator m_iterator;
}; };
@ -55,42 +58,43 @@ private:
*/ */
class NimBLEService { class NimBLEService {
public: public:
NimBLECharacteristic* createCharacteristic(const char* uuid, NimBLECharacteristic* createCharacteristic(const char* uuid,
uint32_t properties = NIMBLE_PROPERTY::READ | uint32_t properties = NIMBLE_PROPERTY::READ |
NIMBLE_PROPERTY::WRITE); NIMBLE_PROPERTY::WRITE);
NimBLECharacteristic* createCharacteristic(const NimBLEUUID &uuid, NimBLECharacteristic* createCharacteristic(const NimBLEUUID &uuid,
uint32_t properties = NIMBLE_PROPERTY::READ | uint32_t properties = NIMBLE_PROPERTY::READ |
NIMBLE_PROPERTY::WRITE); NIMBLE_PROPERTY::WRITE);
void dump(); void dump();
NimBLECharacteristic* getCharacteristic(const char* uuid); NimBLECharacteristic* getCharacteristic(const char* uuid);
NimBLECharacteristic* getCharacteristic(const NimBLEUUID &uuid); NimBLECharacteristic* getCharacteristic(const NimBLEUUID &uuid);
NimBLEUUID getUUID(); NimBLEUUID getUUID();
NimBLEServer* getServer(); NimBLEServer* getServer();
bool start(); bool start();
// void stop(); // void stop();
std::string toString(); std::string toString();
uint16_t getHandle(); uint16_t getHandle();
uint8_t m_instId = 0; uint8_t m_instId = 0;
private: private:
NimBLEService(const char* uuid, uint16_t numHandles, NimBLEServer* pServer); NimBLEService(const char* uuid, uint16_t numHandles, NimBLEServer* pServer);
NimBLEService(const NimBLEUUID &uuid, uint16_t numHandles, NimBLEServer* pServer); NimBLEService(const NimBLEUUID &uuid, uint16_t numHandles, NimBLEServer* pServer);
friend class NimBLEServer; friend class NimBLEServer;
friend class NimBLEDevice; friend class NimBLEDevice;
void addCharacteristic(NimBLECharacteristic* pCharacteristic);
NimBLECharacteristicMap m_characteristicMap; void addCharacteristic(NimBLECharacteristic* pCharacteristic);
uint16_t m_handle;
NimBLEServer* m_pServer = nullptr;
NimBLEUUID m_uuid;
uint16_t m_numHandles; NimBLECharacteristicMap m_characteristicMap;
void setHandle(uint16_t handle); uint16_t m_handle;
NimBLEServer* m_pServer = nullptr;
NimBLEUUID m_uuid;
uint16_t m_numHandles;
void setHandle(uint16_t handle);
}; // BLEService }; // BLEService
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#endif // CONFIG_BT_ENABLED #endif // CONFIG_BT_ENABLED
#endif /* MAIN_NIMBLESERVICE_H_ */ #endif /* MAIN_NIMBLESERVICE_H_ */

View file

@ -3,7 +3,7 @@
* *
* Created: on March 7, 2020 * Created: on March 7, 2020
* Author H2zero * Author H2zero
* *
* Originally: * Originally:
* *
* BLEServiceMap.cpp * BLEServiceMap.cpp
@ -14,6 +14,9 @@
#include "sdkconfig.h" #include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED) #if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h"
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#include "NimBLEService.h" #include "NimBLEService.h"
@ -23,7 +26,7 @@
* @return The characteristic. * @return The characteristic.
*/ */
NimBLEService* NimBLEServiceMap::getByUUID(const char* uuid) { NimBLEService* NimBLEServiceMap::getByUUID(const char* uuid) {
return getByUUID(NimBLEUUID(uuid)); return getByUUID(NimBLEUUID(uuid));
} }
/** /**
@ -32,13 +35,13 @@ NimBLEService* NimBLEServiceMap::getByUUID(const char* uuid) {
* @return The characteristic. * @return The characteristic.
*/ */
NimBLEService* NimBLEServiceMap::getByUUID(const NimBLEUUID &uuid, uint8_t inst_id) { NimBLEService* NimBLEServiceMap::getByUUID(const NimBLEUUID &uuid, uint8_t inst_id) {
for (auto &myPair : m_uuidMap) { for (auto &myPair : m_uuidMap) {
if (myPair.first->getUUID().equals(uuid)) { if (myPair.first->getUUID().equals(uuid)) {
return myPair.first; return myPair.first;
} }
} }
//return m_uuidMap.at(uuid.toString()); //return m_uuidMap.at(uuid.toString());
return nullptr; return nullptr;
} // getByUUID } // getByUUID
@ -49,7 +52,7 @@ NimBLEService* NimBLEServiceMap::getByUUID(const NimBLEUUID &uuid, uint8_t inst_
*/ */
/* /*
NimBLEService* NimBLEServiceMap::getByHandle(uint16_t handle) { NimBLEService* NimBLEServiceMap::getByHandle(uint16_t handle) {
return m_handleMap.at(handle); return m_handleMap.at(handle);
} // getByHandle } // getByHandle
*/ */
@ -60,7 +63,7 @@ NimBLEService* NimBLEServiceMap::getByHandle(uint16_t handle) {
* @return N/A. * @return N/A.
*/ */
void NimBLEServiceMap::setByUUID(const NimBLEUUID &uuid, NimBLEService* service) { void NimBLEServiceMap::setByUUID(const NimBLEUUID &uuid, NimBLEService* service) {
m_uuidMap.insert(std::pair<NimBLEService*, std::string>(service, uuid.toString())); m_uuidMap.insert(std::pair<NimBLEService*, std::string>(service, uuid.toString()));
} // setByUUID } // setByUUID
@ -72,7 +75,7 @@ void NimBLEServiceMap::setByUUID(const NimBLEUUID &uuid, NimBLEService* service)
*/ */
/* /*
void NimBLEServiceMap::setByHandle(uint16_t handle, NimBLEService* service) { void NimBLEServiceMap::setByHandle(uint16_t handle, NimBLEService* service) {
m_handleMap.insert(std::pair<uint16_t, NimBLEService*>(handle, service)); m_handleMap.insert(std::pair<uint16_t, NimBLEService*>(handle, service));
} // setByHandle } // setByHandle
*/ */
@ -81,15 +84,15 @@ void NimBLEServiceMap::setByHandle(uint16_t handle, NimBLEService* service) {
* @return A string representation of the service map. * @return A string representation of the service map.
*/ */
std::string NimBLEServiceMap::toString() { std::string NimBLEServiceMap::toString() {
std::string res; std::string res;
//char hex[5]; //char hex[5];
for (auto &myPair: m_uuidMap) { for (auto &myPair: m_uuidMap) {
// res += "handle: 0x"; // res += "handle: 0x";
// snprintf(hex, sizeof(hex), "%04x", myPair.first); // snprintf(hex, sizeof(hex), "%04x", myPair.first);
// res += hex; // res += hex;
res += ", uuid: " + myPair.second + "\n"; res += ", uuid: " + myPair.second + "\n";
} }
return res; return res;
} // toString } // toString
@ -98,40 +101,45 @@ std::string NimBLEServiceMap::toString() {
* @return The first service in the map. * @return The first service in the map.
*/ */
NimBLEService* NimBLEServiceMap::getFirst() { NimBLEService* NimBLEServiceMap::getFirst() {
m_iterator = m_uuidMap.begin(); m_iterator = m_uuidMap.begin();
if (m_iterator == m_uuidMap.end()) return nullptr; if (m_iterator == m_uuidMap.end()) return nullptr;
NimBLEService* pRet = m_iterator->first; NimBLEService* pRet = m_iterator->first;
m_iterator++; m_iterator++;
return pRet; return pRet;
} // getFirst } // getFirst
/** /**
* @brief Get the next service in the map. * @brief Get the next service in the map.
* @return The next service in the map. * @return The next service in the map.
*/ */
NimBLEService* NimBLEServiceMap::getNext() { NimBLEService* NimBLEServiceMap::getNext() {
if (m_iterator == m_uuidMap.end()) return nullptr; if (m_iterator == m_uuidMap.end()) return nullptr;
NimBLEService* pRet = m_iterator->first; NimBLEService* pRet = m_iterator->first;
m_iterator++; m_iterator++;
return pRet; return pRet;
} // getNext } // getNext
/** /**
* @brief Removes service from maps. * @brief Removes service from maps.
* @return N/A. * @return N/A.
*/ */
void NimBLEServiceMap::removeService(NimBLEService* service) { void NimBLEServiceMap::removeService(NimBLEService* service) {
//m_handleMap.erase(service->getHandle()); //m_handleMap.erase(service->getHandle());
m_uuidMap.erase(service); m_uuidMap.erase(service);
} // removeService } // removeService
/** /**
* @brief Returns the amount of registered services * @brief Returns the amount of registered services
* @return amount of registered services * @return amount of registered services
*/ */
int NimBLEServiceMap::getRegisteredServiceCount(){ int NimBLEServiceMap::getRegisteredServiceCount(){
//return m_handleMap.size(); //return m_handleMap.size();
return m_uuidMap.size(); return m_uuidMap.size();
} }
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#endif /* CONFIG_BT_ENABLED */ #endif /* CONFIG_BT_ENABLED */

View file

@ -3,7 +3,7 @@
* *
* Created: on Jan 24 2020 * Created: on Jan 24 2020
* Author H2zero * Author H2zero
* *
* Originally: * Originally:
* *
* BLEUUID.cpp * BLEUUID.cpp
@ -57,11 +57,11 @@ static const char* LOG_TAG = "NimBLEUUID";
// If the length of the string is 36 bytes then we will assume it is a long hex string in // If the length of the string is 36 bytes then we will assume it is a long hex string in
// UUID format. // UUID format.
char * position = const_cast<char *>(value.c_str()); char * position = const_cast<char *>(value.c_str());
uint32_t first = strtoul(position, &position, 16); uint32_t first = strtoul(position, &position, 16);
uint16_t second = strtoul(position + 1, &position, 16); uint16_t second = strtoul(position + 1, &position, 16);
uint16_t third = strtoul(position + 1, &position, 16); uint16_t third = strtoul(position + 1, &position, 16);
uint16_t fourth = strtoul(position + 1, &position, 16); uint16_t fourth = strtoul(position + 1, &position, 16);
uint64_t fifth = strtoull(position + 1, NULL, 16); uint64_t fifth = strtoull(position + 1, NULL, 16);
*this = NimBLEUUID(first, second, third, (uint64_t(fourth) << 48) + fifth); *this = NimBLEUUID(first, second, third, (uint64_t(fourth) << 48) + fifth);
} }
else { else {
@ -134,8 +134,8 @@ NimBLEUUID::NimBLEUUID(const ble_uuid128_t* uuid) {
/** /**
* @brief Create a UUID from the 128bit value using hex parts instead of string, * @brief Create a UUID from the 128bit value using hex parts instead of string,
* instead of BLEUUID("ebe0ccb0-7a0a-4b0c-8a1a-6ff2997da3a6"), it becomes * instead of BLEUUID("ebe0ccb0-7a0a-4b0c-8a1a-6ff2997da3a6"), it becomes
* BLEUUID(0xebe0ccb0, 0x7a0a, 0x4b0c, 0x8a1a6ff2997da3a6) * BLEUUID(0xebe0ccb0, 0x7a0a, 0x4b0c, 0x8a1a6ff2997da3a6)
* *
* @param [in] first The first 32bit of the UUID. * @param [in] first The first 32bit of the UUID.

View file

@ -3,7 +3,7 @@
* *
* Created: on Jan 25 2020 * Created: on Jan 25 2020
* Author H2zero * Author H2zero
* *
*/ */
#include "sdkconfig.h" #include "sdkconfig.h"
@ -11,42 +11,10 @@
#include "NimBLEUtils.h" #include "NimBLEUtils.h"
#include "NimBLELog.h" #include "NimBLELog.h"
#if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_NIMBLE_ENABLED)
#include "nimconfig.h" #include "nimconfig.h"
#endif
static const char* LOG_TAG = "NimBLEUtils"; static const char* LOG_TAG = "NimBLEUtils";
/**
* @brief Copy memory from source to target but in reverse order.
*
* When we move memory from one location it is normally:
*
* ```
* [0][1][2]...[n] -> [0][1][2]...[n]
* ```
*
* with this function, it is:
*
* ```
* [0][1][2]...[n] -> [n][n-1][n-2]...[0]
* ```
*
* @param [in] target The target of the copy
* @param [in] source The source of the copy
* @param [in] size The number of bytes to copy
*/
void NimBLEUtils::memrcpy(uint8_t* target, const uint8_t* source, uint32_t size) {
assert(size > 0);
target += (size - 1); // Point target to the last byte of the target data
while (size > 0) {
*target = *source;
target--;
source++;
size--;
}
} // memrcpy
int NimBLEUtils::checkConnParams(ble_gap_conn_params* params) { int NimBLEUtils::checkConnParams(ble_gap_conn_params* params) {
/* Check connection interval min */ /* Check connection interval min */
@ -82,7 +50,7 @@ int NimBLEUtils::checkConnParams(ble_gap_conn_params* params) {
const char* NimBLEUtils::returnCodeToString(int rc) { const char* NimBLEUtils::returnCodeToString(int rc) {
#if CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT > 0 #if defined(CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT)
switch(rc) { switch(rc) {
case 0: case 0:
return "SUCCESS"; return "SUCCESS";
@ -363,19 +331,19 @@ const char* NimBLEUtils::returnCodeToString(int rc) {
default: default:
return "Unknown"; return "Unknown";
} }
#else // #if CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT #else // #if defined(CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT)
return ""; return "";
#endif // #if CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT #endif // #if defined(CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT)
} }
/** /**
* @brief Convert the BLE Advertising Data flags to a string. * @brief Convert the BLE Advertising Data flags to a string.
* @param adFlags The flags to convert * @param adFlags The flags to convert
* @return std::string A string representation of the advertising flags. * @return std::string A string representation of the advertising flags.
*/ */
const char* NimBLEUtils::advTypeToString(uint8_t advType) { const char* NimBLEUtils::advTypeToString(uint8_t advType) {
#if CONFIG_NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT > 0 #if defined(CONFIG_NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT)
switch(advType) { switch(advType) {
case BLE_HCI_ADV_TYPE_ADV_IND : //0 case BLE_HCI_ADV_TYPE_ADV_IND : //0
return "Undirected - Connectable / Scannable"; return "Undirected - Connectable / Scannable";
@ -390,9 +358,9 @@ const char* NimBLEUtils::advTypeToString(uint8_t advType) {
default: default:
return "Unknown flag"; return "Unknown flag";
} }
#else // #if CONFIG_NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT #else // #if defined(CONFIG_NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT)
return ""; return "";
#endif // #if CONFIG_NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT #endif // #if defined(CONFIG_NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT)
} // adFlagsToString } // adFlagsToString
@ -432,85 +400,87 @@ char* NimBLEUtils::buildHexData(uint8_t* target, const uint8_t* source, uint8_t
} // buildHexData } // buildHexData
void NimBLEUtils::dumpGapEvent(ble_gap_event *event, void *arg){ void NimBLEUtils::dumpGapEvent(ble_gap_event *event, void *arg){
#if defined(CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT)
NIMBLE_LOGD(LOG_TAG, "Received a GAP event: %s", gapEventToString(event->type)); NIMBLE_LOGD(LOG_TAG, "Received a GAP event: %s", gapEventToString(event->type));
#endif
} }
/** /**
* @brief Convert a BT GAP event type to a string representation. * @brief Convert a BT GAP event type to a string representation.
* @param [in] eventType The type of event. * @param [in] eventType The type of event.
* @return A string representation of the event type. * @return A string representation of the event type.
*/ */
const char* NimBLEUtils::gapEventToString(uint8_t eventType) { const char* NimBLEUtils::gapEventToString(uint8_t eventType) {
#if CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT > 0 #if defined(CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT)
switch (eventType) { switch (eventType) {
case BLE_GAP_EVENT_CONNECT : //0 case BLE_GAP_EVENT_CONNECT : //0
return "BLE_GAP_EVENT_CONNECT "; return "BLE_GAP_EVENT_CONNECT ";
case BLE_GAP_EVENT_DISCONNECT: //1 case BLE_GAP_EVENT_DISCONNECT: //1
return "BLE_GAP_EVENT_DISCONNECT"; return "BLE_GAP_EVENT_DISCONNECT";
case BLE_GAP_EVENT_CONN_UPDATE: //3 case BLE_GAP_EVENT_CONN_UPDATE: //3
return "BLE_GAP_EVENT_CONN_UPDATE"; return "BLE_GAP_EVENT_CONN_UPDATE";
case BLE_GAP_EVENT_CONN_UPDATE_REQ: //4 case BLE_GAP_EVENT_CONN_UPDATE_REQ: //4
return "BLE_GAP_EVENT_CONN_UPDATE_REQ"; return "BLE_GAP_EVENT_CONN_UPDATE_REQ";
case BLE_GAP_EVENT_L2CAP_UPDATE_REQ: //5 case BLE_GAP_EVENT_L2CAP_UPDATE_REQ: //5
return "BLE_GAP_EVENT_L2CAP_UPDATE_REQ"; return "BLE_GAP_EVENT_L2CAP_UPDATE_REQ";
case BLE_GAP_EVENT_TERM_FAILURE: //6 case BLE_GAP_EVENT_TERM_FAILURE: //6
return "BLE_GAP_EVENT_TERM_FAILURE"; return "BLE_GAP_EVENT_TERM_FAILURE";
case BLE_GAP_EVENT_DISC: //7 case BLE_GAP_EVENT_DISC: //7
return "BLE_GAP_EVENT_DISC"; return "BLE_GAP_EVENT_DISC";
case BLE_GAP_EVENT_DISC_COMPLETE: //8 case BLE_GAP_EVENT_DISC_COMPLETE: //8
return "BLE_GAP_EVENT_DISC_COMPLETE"; return "BLE_GAP_EVENT_DISC_COMPLETE";
case BLE_GAP_EVENT_ADV_COMPLETE: //9 case BLE_GAP_EVENT_ADV_COMPLETE: //9
return "BLE_GAP_EVENT_ADV_COMPLETE"; return "BLE_GAP_EVENT_ADV_COMPLETE";
case BLE_GAP_EVENT_ENC_CHANGE: //10 case BLE_GAP_EVENT_ENC_CHANGE: //10
return "BLE_GAP_EVENT_ENC_CHANGE"; return "BLE_GAP_EVENT_ENC_CHANGE";
case BLE_GAP_EVENT_PASSKEY_ACTION : //11 case BLE_GAP_EVENT_PASSKEY_ACTION : //11
return "BLE_GAP_EVENT_PASSKEY_ACTION"; return "BLE_GAP_EVENT_PASSKEY_ACTION";
case BLE_GAP_EVENT_NOTIFY_RX: //12 case BLE_GAP_EVENT_NOTIFY_RX: //12
return "BLE_GAP_EVENT_NOTIFY_RX"; return "BLE_GAP_EVENT_NOTIFY_RX";
case BLE_GAP_EVENT_NOTIFY_TX : //13 case BLE_GAP_EVENT_NOTIFY_TX : //13
return "BLE_GAP_EVENT_NOTIFY_TX"; return "BLE_GAP_EVENT_NOTIFY_TX";
case BLE_GAP_EVENT_SUBSCRIBE : //14 case BLE_GAP_EVENT_SUBSCRIBE : //14
return "BLE_GAP_EVENT_SUBSCRIBE"; return "BLE_GAP_EVENT_SUBSCRIBE";
case BLE_GAP_EVENT_MTU: //15 case BLE_GAP_EVENT_MTU: //15
return "BLE_GAP_EVENT_MTU"; return "BLE_GAP_EVENT_MTU";
case BLE_GAP_EVENT_IDENTITY_RESOLVED: //16 case BLE_GAP_EVENT_IDENTITY_RESOLVED: //16
return "BLE_GAP_EVENT_IDENTITY_RESOLVED"; return "BLE_GAP_EVENT_IDENTITY_RESOLVED";
case BLE_GAP_EVENT_REPEAT_PAIRING: //17 case BLE_GAP_EVENT_REPEAT_PAIRING: //17
return "BLE_GAP_EVENT_REPEAT_PAIRING"; return "BLE_GAP_EVENT_REPEAT_PAIRING";
case BLE_GAP_EVENT_PHY_UPDATE_COMPLETE: //18 case BLE_GAP_EVENT_PHY_UPDATE_COMPLETE: //18
return "BLE_GAP_EVENT_PHY_UPDATE_COMPLETE"; return "BLE_GAP_EVENT_PHY_UPDATE_COMPLETE";
case BLE_GAP_EVENT_EXT_DISC: //19 case BLE_GAP_EVENT_EXT_DISC: //19
return "BLE_GAP_EVENT_EXT_DISC"; return "BLE_GAP_EVENT_EXT_DISC";
#ifdef BLE_GAP_EVENT_PERIODIC_SYNC // IDF 4.0 does not support these #ifdef BLE_GAP_EVENT_PERIODIC_SYNC // IDF 4.0 does not support these
case BLE_GAP_EVENT_PERIODIC_SYNC: //20 case BLE_GAP_EVENT_PERIODIC_SYNC: //20
return "BLE_GAP_EVENT_PERIODIC_SYNC"; return "BLE_GAP_EVENT_PERIODIC_SYNC";
case BLE_GAP_EVENT_PERIODIC_REPORT: //21 case BLE_GAP_EVENT_PERIODIC_REPORT: //21
return "BLE_GAP_EVENT_PERIODIC_REPORT"; return "BLE_GAP_EVENT_PERIODIC_REPORT";
case BLE_GAP_EVENT_PERIODIC_SYNC_LOST: //22 case BLE_GAP_EVENT_PERIODIC_SYNC_LOST: //22
return "BLE_GAP_EVENT_PERIODIC_SYNC_LOST"; return "BLE_GAP_EVENT_PERIODIC_SYNC_LOST";
case BLE_GAP_EVENT_SCAN_REQ_RCVD: //23 case BLE_GAP_EVENT_SCAN_REQ_RCVD: //23
return "BLE_GAP_EVENT_SCAN_REQ_RCVD"; return "BLE_GAP_EVENT_SCAN_REQ_RCVD";
#endif #endif
@ -518,9 +488,9 @@ const char* NimBLEUtils::gapEventToString(uint8_t eventType) {
NIMBLE_LOGD(LOG_TAG, "gapEventToString: Unknown event type %d 0x%.2x", eventType, eventType); NIMBLE_LOGD(LOG_TAG, "gapEventToString: Unknown event type %d 0x%.2x", eventType, eventType);
return "Unknown event type"; return "Unknown event type";
} }
#else // #if CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT #else // #if defined(CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT)
return ""; return "";
#endif // #if CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT #endif // #if defined(CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT)
} // gapEventToString } // gapEventToString

View file

@ -3,7 +3,7 @@
* *
* Created: on Jan 25 2020 * Created: on Jan 25 2020
* Author H2zero * Author H2zero
* *
*/ */
#ifndef COMPONENTS_NIMBLEUTILS_H_ #ifndef COMPONENTS_NIMBLEUTILS_H_
@ -28,7 +28,6 @@ public:
static char* buildHexData(uint8_t* target, const uint8_t* source, uint8_t length); static char* buildHexData(uint8_t* target, const uint8_t* source, uint8_t length);
static const char* advTypeToString(uint8_t advType); static const char* advTypeToString(uint8_t advType);
static const char* returnCodeToString(int rc); static const char* returnCodeToString(int rc);
static void memrcpy(uint8_t* target, const uint8_t* source, uint32_t size);
static int checkConnParams(ble_gap_conn_params* params); static int checkConnParams(ble_gap_conn_params* params);
}; };

View file

@ -3,7 +3,7 @@
* *
* Created: on March 6, 2020 * Created: on March 6, 2020
* Author H2zero * Author H2zero
* *
* Originally: * Originally:
* *
* BLEValue.cpp * BLEValue.cpp
@ -14,15 +14,18 @@
#include "sdkconfig.h" #include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED) #if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h"
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#include "NimBLEValue.h" #include "NimBLEValue.h"
#include "NimBLELog.h" #include "NimBLELog.h"
static const char* LOG_TAG="NimBLEValue"; static const char* LOG_TAG="NimBLEValue";
NimBLEValue::NimBLEValue() { NimBLEValue::NimBLEValue() {
m_accumulation = ""; m_accumulation = "";
m_value = ""; m_value = "";
m_readOffset = 0; m_readOffset = 0;
} // NimBLEValue } // NimBLEValue
@ -32,8 +35,8 @@ NimBLEValue::NimBLEValue() {
* @param [in] part A message part being added. * @param [in] part A message part being added.
*/ */
void NimBLEValue::addPart(const std::string &part) { void NimBLEValue::addPart(const std::string &part) {
NIMBLE_LOGD(LOG_TAG, ">> addPart: length=%d", part.length()); NIMBLE_LOGD(LOG_TAG, ">> addPart: length=%d", part.length());
m_accumulation += part; m_accumulation += part;
} // addPart } // addPart
@ -44,8 +47,8 @@ void NimBLEValue::addPart(const std::string &part) {
* @param [in] length The number of bytes being added. * @param [in] length The number of bytes being added.
*/ */
void NimBLEValue::addPart(const uint8_t* pData, size_t length) { void NimBLEValue::addPart(const uint8_t* pData, size_t length) {
NIMBLE_LOGD(LOG_TAG, ">> addPart: length=%d", length); NIMBLE_LOGD(LOG_TAG, ">> addPart: length=%d", length);
m_accumulation += std::string((char*) pData, length); m_accumulation += std::string((char*) pData, length);
} // addPart } // addPart
@ -53,9 +56,9 @@ void NimBLEValue::addPart(const uint8_t* pData, size_t length) {
* @brief Cancel the current accumulation. * @brief Cancel the current accumulation.
*/ */
void NimBLEValue::cancel() { void NimBLEValue::cancel() {
NIMBLE_LOGD(LOG_TAG, ">> cancel"); NIMBLE_LOGD(LOG_TAG, ">> cancel");
m_accumulation = ""; m_accumulation = "";
m_readOffset = 0; m_readOffset = 0;
} // cancel } // cancel
@ -66,12 +69,12 @@ void NimBLEValue::cancel() {
* we now have the complete message and commit the change as a unit. * we now have the complete message and commit the change as a unit.
*/ */
void NimBLEValue::commit() { void NimBLEValue::commit() {
NIMBLE_LOGD(LOG_TAG, ">> commit"); NIMBLE_LOGD(LOG_TAG, ">> commit");
// If there is nothing to commit, do nothing. // If there is nothing to commit, do nothing.
if (m_accumulation.length() == 0) return; if (m_accumulation.length() == 0) return;
setValue(m_accumulation); setValue(m_accumulation);
m_accumulation = ""; m_accumulation = "";
m_readOffset = 0; m_readOffset = 0;
} // commit } // commit
@ -80,7 +83,7 @@ void NimBLEValue::commit() {
* @return A pointer to the data. * @return A pointer to the data.
*/ */
uint8_t* NimBLEValue::getData() { uint8_t* NimBLEValue::getData() {
return (uint8_t*) m_value.data(); return (uint8_t*) m_value.data();
} }
@ -89,7 +92,7 @@ uint8_t* NimBLEValue::getData() {
* @return The length of the data in bytes. * @return The length of the data in bytes.
*/ */
size_t NimBLEValue::getLength() { size_t NimBLEValue::getLength() {
return m_value.length(); return m_value.length();
} // getLength } // getLength
@ -98,7 +101,7 @@ size_t NimBLEValue::getLength() {
* @return The read offset into the read. * @return The read offset into the read.
*/ */
uint16_t NimBLEValue::getReadOffset() { uint16_t NimBLEValue::getReadOffset() {
return m_readOffset; return m_readOffset;
} // getReadOffset } // getReadOffset
@ -106,7 +109,7 @@ uint16_t NimBLEValue::getReadOffset() {
* @brief Get the current value. * @brief Get the current value.
*/ */
std::string NimBLEValue::getValue() { std::string NimBLEValue::getValue() {
return m_value; return m_value;
} // getValue } // getValue
@ -115,7 +118,7 @@ std::string NimBLEValue::getValue() {
* @param [in] readOffset The offset into the read. * @param [in] readOffset The offset into the read.
*/ */
void NimBLEValue::setReadOffset(uint16_t readOffset) { void NimBLEValue::setReadOffset(uint16_t readOffset) {
m_readOffset = readOffset; m_readOffset = readOffset;
} // setReadOffset } // setReadOffset
@ -123,7 +126,7 @@ void NimBLEValue::setReadOffset(uint16_t readOffset) {
* @brief Set the current value. * @brief Set the current value.
*/ */
void NimBLEValue::setValue(const std::string &value) { void NimBLEValue::setValue(const std::string &value) {
m_value = value; m_value = value;
} // setValue } // setValue
@ -133,8 +136,8 @@ void NimBLEValue::setValue(const std::string &value) {
* @param [in] The length of the new current value. * @param [in] The length of the new current value.
*/ */
void NimBLEValue::setValue(const uint8_t* pData, size_t length) { void NimBLEValue::setValue(const uint8_t* pData, size_t length) {
m_value = std::string((char*) pData, length); m_value = std::string((char*) pData, length);
} // setValue } // setValue
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#endif // CONFIG_BT_ENABLED #endif // CONFIG_BT_ENABLED

View file

@ -3,9 +3,9 @@
* *
* Created: on March 6, 2020 * Created: on March 6, 2020
* Author H2zero * Author H2zero
* *
* Originally: * Originally:
* *
* BLEValue.h * BLEValue.h
* *
* Created on: Jul 17, 2017 * Created on: Jul 17, 2017
@ -16,6 +16,10 @@
#define MAIN_BLEVALUE_H_ #define MAIN_BLEVALUE_H_
#include "sdkconfig.h" #include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED) #if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h"
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#include <string> #include <string>
/** /**
@ -23,24 +27,26 @@
*/ */
class NimBLEValue { class NimBLEValue {
public: public:
NimBLEValue(); NimBLEValue();
void addPart(const std::string &part); void addPart(const std::string &part);
void addPart(const uint8_t* pData, size_t length); void addPart(const uint8_t* pData, size_t length);
void cancel(); void cancel();
void commit(); void commit();
uint8_t* getData(); uint8_t* getData();
size_t getLength(); size_t getLength();
uint16_t getReadOffset(); uint16_t getReadOffset();
std::string getValue(); std::string getValue();
void setReadOffset(uint16_t readOffset); void setReadOffset(uint16_t readOffset);
void setValue(const std::string &value); void setValue(const std::string &value);
void setValue(const uint8_t* pData, size_t length); void setValue(const uint8_t* pData, size_t length);
private: private:
std::string m_accumulation; std::string m_accumulation;
uint16_t m_readOffset; uint16_t m_readOffset;
std::string m_value; std::string m_value;
}; };
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#endif // CONFIG_BT_ENABLED #endif // CONFIG_BT_ENABLED
#endif /* MAIN_BLEVALUE_H_ */ #endif /* MAIN_BLEVALUE_H_ */

132
src/nimconfig.h Normal file
View file

@ -0,0 +1,132 @@
#pragma once
#include "sdkconfig.h"
/** For ESP-IDF compatibility
*
* Some versions of ESP-IDF used the config name format "CONFIG_NIMBLE_".
* This converts them to "CONFIG_BT_NIMBLE_" format used in the latest IDF.
*/
/* Detect if using ESP-IDF or Arduino (Arduino won't have these defines in sdkconfig)*/
#if defined(CONFIG_BT_NIMBLE_TASK_STACK_SIZE) || defined(CONFIG_NIMBLE_TASK_STACK_SIZE)
#if defined(CONFIG_NIMBLE_ENABLED)
#define CONFIG_BT_NIMBLE_ENABLED
#endif
#if defined(CONFIG_NIMBLE_ROLE_OBSERVER)
#define CONFIG_BT_NIMBLE_ROLE_OBSERVER
#endif
#if defined(CONFIG_NIMBLE_ROLE_BROADCASTER)
#define CONFIG_BT_NIMBLE_ROLE_BROADCASTER
#endif
#if defined(CONFIG_NIMBLE_ROLE_CENTRAL)
#define CONFIG_BT_NIMBLE_ROLE_CENTRAL
#endif
#if defined(CONFIG_NIMBLE_ROLE_PERIPHERAL)
#define CONFIG_BT_NIMBLE_ROLE_PERIPHERAL
#endif
#if defined(CONFIG_NIMBLE_DEBUG)
#define CONFIG_BT_NIMBLE_DEBUG
#endif
#else // Using Arduino
/***********************************************
* Arduino config options
**********************************************/
/** Comment out if not using NimBLE Client functions
* Reduces flash size by approx. 7kB.
*/
#define CONFIG_BT_NIMBLE_ROLE_CENTRAL
/** Comment out if not using NimBLE Scan functions
* Reduces flash size by approx. 26kB.
*/
#define CONFIG_BT_NIMBLE_ROLE_OBSERVER
/** Comment out if not using NimBLE Server functions
* Reduces flash size by approx. 16kB.
*/
#define CONFIG_BT_NIMBLE_ROLE_PERIPHERAL
/** Comment out if not using NimBLE Advertising functions
* Reduces flash size by approx. 5kB.
*/
#define CONFIG_BT_NIMBLE_ROLE_BROADCASTER
/** Uncomment to see debug log messages from the NimBLE host
* Uses approx. 32kB of flash memory.
*/
// #define CONFIG_BT_NIMBLE_DEBUG
/** Uncomment to see NimBLE host return codes as text debug log messages.
* Uses approx. 7kB of flash memory.
*/
// #define CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT
/** Uncomment to see GAP event codes as text in debug log messages.
* Uses approx. 1kB of flash memory.
*/
// #define CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT
/** Uncomment to see advertisment types as text while scanning in debug log messages.
* Uses approx. 250 bytes of flash memory.
*/
// #define CONFIG_NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT
/** Sets the core NimBLE host runs on */
#define CONFIG_BT_NIMBLE_PINNED_TO_CORE 0
/** Sets the stack size for the NimBLE host task */
#define CONFIG_BT_NIMBLE_TASK_STACK_SIZE 4096
/** Sets the number of simultaneous connections (esp controller max is 9) */
#define CONFIG_BT_NIMBLE_MAX_CONNECTIONS 3
/** Sets the number of devices allowed to store/bond with */
#define CONFIG_BT_NIMBLE_MAX_BONDS 3
/** Sets the number of CCCD's to store per bonded device */
#define CONFIG_BT_NIMBLE_MAX_CCCDS 8
#define CONFIG_BT_NIMBLE_NVS_PERSIST 1
#define CONFIG_BT_NIMBLE_SM_LEGACY 1
#define CONFIG_BT_NIMBLE_SM_SC 1
#define CONFIG_BT_NIMBLE_SVC_GAP_DEVICE_NAME "nimble"
#define CONFIG_BT_NIMBLE_GAP_DEVICE_NAME_MAX_LEN 31
#define CONFIG_BT_NIMBLE_ATT_PREFERRED_MTU 256
#define CONFIG_BT_NIMBLE_SVC_GAP_APPEARANCE 0x0
#define CONFIG_BT_NIMBLE_ACL_BUF_COUNT 12
#define CONFIG_BT_NIMBLE_ACL_BUF_SIZE 255
#define CONFIG_BT_NIMBLE_HCI_EVT_BUF_SIZE 70
#define CONFIG_BT_NIMBLE_HCI_EVT_HI_BUF_COUNT 30
#define CONFIG_BT_NIMBLE_HCI_EVT_LO_BUF_COUNT 8
#define CONFIG_BT_NIMBLE_MSYS1_BLOCK_COUNT 12
#define CONFIG_BT_NIMBLE_HS_FLOW_CTRL 1
#define CONFIG_BT_NIMBLE_HS_FLOW_CTRL_ITVL 1000
#define CONFIG_BT_NIMBLE_HS_FLOW_CTRL_THRESH 2
#define CONFIG_BT_NIMBLE_HS_FLOW_CTRL_TX_ON_DISCONNECT 1
#define CONFIG_BT_NIMBLE_RPA_TIMEOUT 900
#define CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM 0
/** Do not comment out */
#define CONFIG_BT_ENABLED
#define CONFIG_BTDM_CONTROLLER_MODE_BLE_ONLY
#define CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL
#endif // #if defined(CONFIG_BT_NIMBLE_TASK_STACK_SIZE) || defined(CONFIG_NIMBLE_TASK_STACK_SIZE)
/** Cannot use client without scan */
#if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) && !defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
#define CONFIG_BT_NIMBLE_ROLE_OBSERVER
#endif
/** Cannot use server without advertise */
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) && !defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
#define CONFIG_BT_NIMBLE_ROLE_BROADCASTER
#endif