From 03cb7b21d948e7fd16674beeb2297bfac67b012e Mon Sep 17 00:00:00 2001 From: h2zero Date: Wed, 13 May 2020 22:03:56 -0600 Subject: [PATCH] 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. --- Kconfig | 27 ++ src/FreeRTOS.cpp | 34 +- src/FreeRTOS.h | 4 +- src/HIDKeyboardTypes.h | 58 +-- src/HIDTypes.h | 4 +- src/NimBLE2902.cpp | 38 +- src/NimBLE2902.h | 18 +- src/NimBLE2904.cpp | 48 +-- src/NimBLE2904.h | 86 +++-- src/NimBLEAddress.cpp | 2 +- src/NimBLEAddress.h | 8 +- src/NimBLEAdvertisedDevice.cpp | 38 +- src/NimBLEAdvertisedDevice.h | 8 +- src/NimBLEAdvertising.cpp | 600 +++++++++++++++-------------- src/NimBLEAdvertising.h | 83 ++-- src/NimBLEBeacon.cpp | 54 +-- src/NimBLEBeacon.h | 47 +-- src/NimBLECharacteristic.cpp | 388 ++++++++++--------- src/NimBLECharacteristic.h | 183 ++++----- src/NimBLECharacteristicMap.cpp | 68 ++-- src/NimBLEClient.cpp | 268 ++++++------- src/NimBLEClient.h | 26 +- src/NimBLEDescriptor.cpp | 101 ++--- src/NimBLEDescriptor.h | 77 ++-- src/NimBLEDescriptorMap.cpp | 74 ++-- src/NimBLEDevice.cpp | 213 +++++----- src/NimBLEDevice.h | 109 ++++-- src/NimBLEEddystoneTLM.cpp | 50 +-- src/NimBLEEddystoneTLM.h | 52 +-- src/NimBLEEddystoneURL.cpp | 182 ++++----- src/NimBLEEddystoneURL.h | 36 +- src/NimBLELog.h | 8 +- src/NimBLERemoteCharacteristic.cpp | 85 ++-- src/NimBLERemoteCharacteristic.h | 11 +- src/NimBLERemoteDescriptor.cpp | 63 +-- src/NimBLERemoteDescriptor.h | 7 +- src/NimBLERemoteService.cpp | 66 ++-- src/NimBLERemoteService.h | 10 +- src/NimBLEScan.cpp | 68 ++-- src/NimBLEScan.h | 13 +- src/NimBLESecurity.cpp | 6 +- src/NimBLESecurity.h | 6 +- src/NimBLEServer.cpp | 293 +++++++------- src/NimBLEServer.h | 25 +- src/NimBLEService.cpp | 178 ++++----- src/NimBLEService.h | 92 ++--- src/NimBLEServiceMap.cpp | 74 ++-- src/NimBLEUUID.cpp | 16 +- src/NimBLEUtils.cpp | 114 ++---- src/NimBLEUtils.h | 3 +- src/NimBLEValue.cpp | 53 +-- src/NimBLEValue.h | 40 +- src/nimconfig.h | 132 +++++++ 53 files changed, 2335 insertions(+), 2012 deletions(-) create mode 100644 Kconfig create mode 100644 src/nimconfig.h diff --git a/Kconfig b/Kconfig new file mode 100644 index 0000000..069b000 --- /dev/null +++ b/Kconfig @@ -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 diff --git a/src/FreeRTOS.cpp b/src/FreeRTOS.cpp index 2cc7a98..f6bbe17 100644 --- a/src/FreeRTOS.cpp +++ b/src/FreeRTOS.cpp @@ -89,28 +89,28 @@ uint32_t FreeRTOS::Semaphore::wait(std::string owner) { * @return True if we took the semaphore within timeframe. */ 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) { - assert(false); // We apparently don't have a timed wait for pthreads. - } + if (m_usePthreads && timeoutMs != portMAX_DELAY) { + assert(false); // We apparently don't have a timed wait for pthreads. + } - auto ret = pdTRUE; + auto ret = pdTRUE; - if (m_usePthreads) { - pthread_mutex_lock(&m_pthread_mutex); - } else { - ret = xSemaphoreTake(m_semaphore, timeoutMs); - } + if (m_usePthreads) { + pthread_mutex_lock(&m_pthread_mutex); + } else { + ret = xSemaphoreTake(m_semaphore, timeoutMs); + } - if (m_usePthreads) { - pthread_mutex_unlock(&m_pthread_mutex); - } else { - xSemaphoreGive(m_semaphore); - } + if (m_usePthreads) { + pthread_mutex_unlock(&m_pthread_mutex); + } else { + xSemaphoreGive(m_semaphore); + } - NIMBLE_LOGD(LOG_TAG, "<< wait: Semaphore %s released: %d", toString().c_str(), ret); - return ret; + NIMBLE_LOGD(LOG_TAG, "<< wait: Semaphore %s released: %d", toString().c_str(), ret); + return ret; } // wait diff --git a/src/FreeRTOS.h b/src/FreeRTOS.h index 0787727..a6737b7 100644 --- a/src/FreeRTOS.h +++ b/src/FreeRTOS.h @@ -40,9 +40,9 @@ public: bool take(std::string owner = ""); bool take(uint32_t timeoutMs, std::string owner = ""); std::string toString(); - bool timedWait(std::string owner = "", uint32_t timeoutMs = portMAX_DELAY); + bool timedWait(std::string owner = "", uint32_t timeoutMs = portMAX_DELAY); uint32_t wait(std::string owner = ""); - uint32_t value(){ return m_value; }; + uint32_t value(){ return m_value; }; private: SemaphoreHandle_t m_semaphore; diff --git a/src/HIDKeyboardTypes.h b/src/HIDKeyboardTypes.h index 4e221d5..531437e 100644 --- a/src/HIDKeyboardTypes.h +++ b/src/HIDKeyboardTypes.h @@ -26,9 +26,9 @@ /* Modifiers */ enum MODIFIER_KEY { - KEY_CTRL = 1, - KEY_SHIFT = 2, - KEY_ALT = 4, + KEY_CTRL = 1, + KEY_SHIFT = 2, + KEY_ALT = 4, }; @@ -43,37 +43,37 @@ enum MEDIA_KEY { }; enum FUNCTION_KEY { - KEY_F1 = 128, /* F1 key */ - KEY_F2, /* F2 key */ - KEY_F3, /* F3 key */ - KEY_F4, /* F4 key */ - KEY_F5, /* F5 key */ - KEY_F6, /* F6 key */ - KEY_F7, /* F7 key */ - KEY_F8, /* F8 key */ - KEY_F9, /* F9 key */ - KEY_F10, /* F10 key */ - KEY_F11, /* F11 key */ - KEY_F12, /* F12 key */ + KEY_F1 = 128, /* F1 key */ + KEY_F2, /* F2 key */ + KEY_F3, /* F3 key */ + KEY_F4, /* F4 key */ + KEY_F5, /* F5 key */ + KEY_F6, /* F6 key */ + KEY_F7, /* F7 key */ + KEY_F8, /* F8 key */ + KEY_F9, /* F9 key */ + KEY_F10, /* F10 key */ + KEY_F11, /* F11 key */ + KEY_F12, /* F12 key */ - KEY_PRINT_SCREEN, /* Print Screen key */ - KEY_SCROLL_LOCK, /* Scroll lock */ - KEY_CAPS_LOCK, /* caps lock */ - KEY_NUM_LOCK, /* num lock */ - KEY_INSERT, /* Insert key */ - KEY_HOME, /* Home key */ - KEY_PAGE_UP, /* Page Up key */ - KEY_PAGE_DOWN, /* Page Down key */ + KEY_PRINT_SCREEN, /* Print Screen key */ + KEY_SCROLL_LOCK, /* Scroll lock */ + KEY_CAPS_LOCK, /* caps lock */ + KEY_NUM_LOCK, /* num lock */ + KEY_INSERT, /* Insert key */ + KEY_HOME, /* Home key */ + KEY_PAGE_UP, /* Page Up key */ + KEY_PAGE_DOWN, /* Page Down key */ - RIGHT_ARROW, /* Right arrow */ - LEFT_ARROW, /* Left arrow */ - DOWN_ARROW, /* Down arrow */ - UP_ARROW, /* Up arrow */ + RIGHT_ARROW, /* Right arrow */ + LEFT_ARROW, /* Left arrow */ + DOWN_ARROW, /* Down arrow */ + UP_ARROW, /* Up arrow */ }; typedef struct { - unsigned char usage; - unsigned char modifier; + unsigned char usage; + unsigned char modifier; } KEYMAP; #ifdef US_KEYBOARD diff --git a/src/HIDTypes.h b/src/HIDTypes.h index 64850ef..726b84b 100644 --- a/src/HIDTypes.h +++ b/src/HIDTypes.h @@ -89,8 +89,8 @@ #define MAX_HID_REPORT_SIZE (64) typedef struct { - uint32_t length; - uint8_t data[MAX_HID_REPORT_SIZE]; + uint32_t length; + uint8_t data[MAX_HID_REPORT_SIZE]; } HID_REPORT; #endif diff --git a/src/NimBLE2902.cpp b/src/NimBLE2902.cpp index b232060..04a07b6 100644 --- a/src/NimBLE2902.cpp +++ b/src/NimBLE2902.cpp @@ -3,7 +3,7 @@ * * Created: on March 10, 2020 * Author H2zero - * + * * Originally: * * BLE2902.cpp @@ -20,16 +20,19 @@ #include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) +#include "nimconfig.h" +#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) + #include "NimBLE2902.h" -NimBLE2902::NimBLE2902(NimBLECharacteristic* pCharacterisitic) -: NimBLEDescriptor(NimBLEUUID((uint16_t) 0x2902), - BLE_GATT_CHR_F_READ | - BLE_GATT_CHR_F_WRITE, - 2, pCharacterisitic) +NimBLE2902::NimBLE2902(NimBLECharacteristic* pCharacterisitic) +: NimBLEDescriptor(NimBLEUUID((uint16_t) 0x2902), + BLE_GATT_CHR_F_READ | + BLE_GATT_CHR_F_WRITE, + 2, pCharacterisitic) { - uint8_t data[2] = { 0, 0 }; - setValue(data, 2); + uint8_t data[2] = { 0, 0 }; + setValue(data, 2); } // NimBLE2902 @@ -38,7 +41,7 @@ NimBLE2902::NimBLE2902(NimBLECharacteristic* pCharacterisitic) * @return The notifications value. True if notifications are enabled and false if not. */ bool NimBLE2902::getNotifications() { - return (getValue()[0] & (1 << 0)) != 0; + return (getValue()[0] & (1 << 0)) != 0; } // getNotifications @@ -47,7 +50,7 @@ bool NimBLE2902::getNotifications() { * @return The indications value. True if indications are enabled and false if not. */ bool NimBLE2902::getIndications() { - return (getValue()[0] & (1 << 1)) != 0; + return (getValue()[0] & (1 << 1)) != 0; } // getIndications @@ -56,9 +59,9 @@ bool NimBLE2902::getIndications() { * @param [in] flag The indications flag. */ void NimBLE2902::setIndications(bool flag) { - uint8_t *pValue = getValue(); - if (flag) pValue[0] |= 1 << 1; - else pValue[0] &= ~(1 << 1); + uint8_t *pValue = getValue(); + if (flag) pValue[0] |= 1 << 1; + else pValue[0] &= ~(1 << 1); } // setIndications @@ -67,9 +70,10 @@ void NimBLE2902::setIndications(bool flag) { * @param [in] flag The notifications flag. */ void NimBLE2902::setNotifications(bool flag) { - uint8_t *pValue = getValue(); - if (flag) pValue[0] |= 1 << 0; - else pValue[0] &= ~(1 << 0); + uint8_t *pValue = getValue(); + if (flag) pValue[0] |= 1 << 0; + else pValue[0] &= ~(1 << 0); } // setNotifications -#endif \ No newline at end of file +#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) +#endif diff --git a/src/NimBLE2902.h b/src/NimBLE2902.h index dcecbaa..f7fc555 100644 --- a/src/NimBLE2902.h +++ b/src/NimBLE2902.h @@ -3,7 +3,7 @@ * * Created: on March 10, 2020 * Author H2zero - * + * * Originally: * * BLE2902.h @@ -17,6 +17,9 @@ #include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) +#include "nimconfig.h" +#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) + #include "NimBLEDescriptor.h" #include @@ -35,16 +38,17 @@ */ class NimBLE2902: public NimBLEDescriptor { public: - bool getNotifications(); - bool getIndications(); - void setNotifications(bool flag); - void setIndications(bool flag); + bool getNotifications(); + bool getIndications(); + void setNotifications(bool flag); + void setIndications(bool flag); private: - NimBLE2902(NimBLECharacteristic* pCharacterisitic); + NimBLE2902(NimBLECharacteristic* pCharacterisitic); friend class NimBLECharacteristic; std::map m_subscribedMap; }; // NimBLE2902 +#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #endif /* CONFIG_BT_ENABLED */ -#endif /* MAIN_NIMBLE2902_H_ */ \ No newline at end of file +#endif /* MAIN_NIMBLE2902_H_ */ diff --git a/src/NimBLE2904.cpp b/src/NimBLE2904.cpp index 59ef005..d85cd87 100644 --- a/src/NimBLE2904.cpp +++ b/src/NimBLE2904.cpp @@ -3,7 +3,7 @@ * * Created: on March 13, 2020 * Author H2zero - * + * * Originally: * * BLE2904.cpp @@ -19,21 +19,24 @@ #include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) +#include "nimconfig.h" +#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) + #include "NimBLE2904.h" -NimBLE2904::NimBLE2904(NimBLECharacteristic* pCharacterisitic) +NimBLE2904::NimBLE2904(NimBLECharacteristic* pCharacterisitic) : NimBLEDescriptor(NimBLEUUID((uint16_t) 0x2904), - BLE_GATT_CHR_F_READ, - sizeof(BLE2904_Data), - pCharacterisitic) + BLE_GATT_CHR_F_READ, + sizeof(BLE2904_Data), + pCharacterisitic) { - m_data.m_format = 0; - m_data.m_exponent = 0; - m_data.m_namespace = 1; // 1 = Bluetooth SIG Assigned Numbers - m_data.m_unit = 0; - m_data.m_description = 0; - setValue((uint8_t*) &m_data, sizeof(m_data)); + m_data.m_format = 0; + m_data.m_exponent = 0; + m_data.m_namespace = 1; // 1 = Bluetooth SIG Assigned Numbers + m_data.m_unit = 0; + m_data.m_description = 0; + setValue((uint8_t*) &m_data, sizeof(m_data)); } // BLE2902 @@ -41,8 +44,8 @@ NimBLE2904::NimBLE2904(NimBLECharacteristic* pCharacterisitic) * @brief Set the description. */ void NimBLE2904::setDescription(uint16_t description) { - m_data.m_description = description; - setValue((uint8_t*) &m_data, sizeof(m_data)); + m_data.m_description = description; + setValue((uint8_t*) &m_data, sizeof(m_data)); } @@ -50,8 +53,8 @@ void NimBLE2904::setDescription(uint16_t description) { * @brief Set the exponent. */ void NimBLE2904::setExponent(int8_t exponent) { - m_data.m_exponent = exponent; - setValue((uint8_t*) &m_data, sizeof(m_data)); + m_data.m_exponent = exponent; + setValue((uint8_t*) &m_data, sizeof(m_data)); } // setExponent @@ -59,8 +62,8 @@ void NimBLE2904::setExponent(int8_t exponent) { * @brief Set the format. */ void NimBLE2904::setFormat(uint8_t format) { - m_data.m_format = format; - setValue((uint8_t*) &m_data, sizeof(m_data)); + m_data.m_format = format; + setValue((uint8_t*) &m_data, sizeof(m_data)); } // setFormat @@ -68,8 +71,8 @@ void NimBLE2904::setFormat(uint8_t format) { * @brief Set the namespace. */ void NimBLE2904::setNamespace(uint8_t namespace_value) { - m_data.m_namespace = namespace_value; - setValue((uint8_t*) &m_data, sizeof(m_data)); + m_data.m_namespace = namespace_value; + setValue((uint8_t*) &m_data, sizeof(m_data)); } // 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. */ void NimBLE2904::setUnit(uint16_t unit) { - m_data.m_unit = unit; - setValue((uint8_t*) &m_data, sizeof(m_data)); + m_data.m_unit = unit; + setValue((uint8_t*) &m_data, sizeof(m_data)); } // setUnit -#endif \ No newline at end of file +#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) +#endif diff --git a/src/NimBLE2904.h b/src/NimBLE2904.h index b2aafb0..dd665a2 100644 --- a/src/NimBLE2904.h +++ b/src/NimBLE2904.h @@ -3,7 +3,7 @@ * * Created: on March 13, 2020 * Author H2zero - * + * * Originally: * * BLE2904.h @@ -17,14 +17,17 @@ #include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) +#include "nimconfig.h" +#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) + #include "NimBLEDescriptor.h" struct BLE2904_Data { - uint8_t m_format; - int8_t m_exponent; - uint16_t m_unit; // See https://www.bluetooth.com/specifications/assigned-numbers/units - uint8_t m_namespace; - uint16_t m_description; + uint8_t m_format; + int8_t m_exponent; + uint16_t m_unit; // See https://www.bluetooth.com/specifications/assigned-numbers/units + uint8_t m_namespace; + uint16_t m_description; } __attribute__((packed)); @@ -38,45 +41,46 @@ struct BLE2904_Data { */ class NimBLE2904: public NimBLEDescriptor { public: - static const uint8_t FORMAT_BOOLEAN = 1; - static const uint8_t FORMAT_UINT2 = 2; - static const uint8_t FORMAT_UINT4 = 3; - static const uint8_t FORMAT_UINT8 = 4; - static const uint8_t FORMAT_UINT12 = 5; - static const uint8_t FORMAT_UINT16 = 6; - static const uint8_t FORMAT_UINT24 = 7; - static const uint8_t FORMAT_UINT32 = 8; - static const uint8_t FORMAT_UINT48 = 9; - static const uint8_t FORMAT_UINT64 = 10; - static const uint8_t FORMAT_UINT128 = 11; - static const uint8_t FORMAT_SINT8 = 12; - static const uint8_t FORMAT_SINT12 = 13; - static const uint8_t FORMAT_SINT16 = 14; - static const uint8_t FORMAT_SINT24 = 15; - static const uint8_t FORMAT_SINT32 = 16; - static const uint8_t FORMAT_SINT48 = 17; - static const uint8_t FORMAT_SINT64 = 18; - static const uint8_t FORMAT_SINT128 = 19; - static const uint8_t FORMAT_FLOAT32 = 20; - static const uint8_t FORMAT_FLOAT64 = 21; - static const uint8_t FORMAT_SFLOAT16 = 22; - static const uint8_t FORMAT_SFLOAT32 = 23; - static const uint8_t FORMAT_IEEE20601 = 24; - static const uint8_t FORMAT_UTF8 = 25; - static const uint8_t FORMAT_UTF16 = 26; - static const uint8_t FORMAT_OPAQUE = 27; + static const uint8_t FORMAT_BOOLEAN = 1; + static const uint8_t FORMAT_UINT2 = 2; + static const uint8_t FORMAT_UINT4 = 3; + static const uint8_t FORMAT_UINT8 = 4; + static const uint8_t FORMAT_UINT12 = 5; + static const uint8_t FORMAT_UINT16 = 6; + static const uint8_t FORMAT_UINT24 = 7; + static const uint8_t FORMAT_UINT32 = 8; + static const uint8_t FORMAT_UINT48 = 9; + static const uint8_t FORMAT_UINT64 = 10; + static const uint8_t FORMAT_UINT128 = 11; + static const uint8_t FORMAT_SINT8 = 12; + static const uint8_t FORMAT_SINT12 = 13; + static const uint8_t FORMAT_SINT16 = 14; + static const uint8_t FORMAT_SINT24 = 15; + static const uint8_t FORMAT_SINT32 = 16; + static const uint8_t FORMAT_SINT48 = 17; + static const uint8_t FORMAT_SINT64 = 18; + static const uint8_t FORMAT_SINT128 = 19; + static const uint8_t FORMAT_FLOAT32 = 20; + static const uint8_t FORMAT_FLOAT64 = 21; + static const uint8_t FORMAT_SFLOAT16 = 22; + static const uint8_t FORMAT_SFLOAT32 = 23; + static const uint8_t FORMAT_IEEE20601 = 24; + static const uint8_t FORMAT_UTF8 = 25; + static const uint8_t FORMAT_UTF16 = 26; + static const uint8_t FORMAT_OPAQUE = 27; - void setDescription(uint16_t); - void setExponent(int8_t exponent); - void setFormat(uint8_t format); - void setNamespace(uint8_t namespace_value); - void setUnit(uint16_t unit); + void setDescription(uint16_t); + void setExponent(int8_t exponent); + void setFormat(uint8_t format); + void setNamespace(uint8_t namespace_value); + void setUnit(uint16_t unit); private: - NimBLE2904(NimBLECharacteristic* pCharacterisitic); + NimBLE2904(NimBLECharacteristic* pCharacterisitic); friend class NimBLECharacteristic; - BLE2904_Data m_data; + BLE2904_Data m_data; }; // BLE2904 +#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #endif /* CONFIG_BT_ENABLED */ -#endif /* MAIN_NIMBLE2904_H_ */ \ No newline at end of file +#endif /* MAIN_NIMBLE2904_H_ */ diff --git a/src/NimBLEAddress.cpp b/src/NimBLEAddress.cpp index 3686e28..6aa919a 100644 --- a/src/NimBLEAddress.cpp +++ b/src/NimBLEAddress.cpp @@ -3,7 +3,7 @@ * * Created: on Jan 24 2020 * Author H2zero - * + * * Originally: * * BLEAddress.cpp diff --git a/src/NimBLEAddress.h b/src/NimBLEAddress.h index e2c3f72..917e376 100644 --- a/src/NimBLEAddress.h +++ b/src/NimBLEAddress.h @@ -3,7 +3,7 @@ * * Created: on Jan 24 2020 * Author H2zero - * + * * Originally: * * BLEAddress.h @@ -40,9 +40,9 @@ public: const uint8_t* getNative() const; std::string toString() const; - bool operator ==(const NimBLEAddress & rhs) const; - bool operator !=(const NimBLEAddress & rhs) const; - operator std::string() const; + bool operator ==(const NimBLEAddress & rhs) const; + bool operator !=(const NimBLEAddress & rhs) const; + operator std::string() const; private: uint8_t m_address[6]; diff --git a/src/NimBLEAdvertisedDevice.cpp b/src/NimBLEAdvertisedDevice.cpp index 83a2b67..3634bac 100644 --- a/src/NimBLEAdvertisedDevice.cpp +++ b/src/NimBLEAdvertisedDevice.cpp @@ -3,7 +3,7 @@ * * Created: on Jan 24 2020 * Author H2zero - * + * * Originally: * * BLEAdvertisedDevice.cpp @@ -14,6 +14,9 @@ #include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) +#include "nimconfig.h" +#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) + #include "NimBLEAdvertisedDevice.h" #include "NimBLEUtils.h" #include "NimBLELog.h" @@ -121,7 +124,7 @@ std::string NimBLEAdvertisedDevice::getServiceData() { * @brief Get the service data UUID. * @return The service data UUID. */ - + NimBLEUUID NimBLEAdvertisedDevice::getServiceDataUUID() { return m_serviceDataUUID; } // getServiceDataUUID @@ -131,7 +134,7 @@ NimBLEUUID NimBLEAdvertisedDevice::getServiceDataUUID() { * @brief Get the Service UUID. * @return The Service UUID of the advertised device. */ - + NimBLEUUID NimBLEAdvertisedDevice::getServiceUUID() { //TODO Remove it eventually, is no longer useful return m_serviceUUIDs[0]; } // getServiceUUID @@ -270,7 +273,7 @@ bool NimBLEAdvertisedDevice::haveTXPower() { u8p = fields->svc_data_uuid16; length = fields->svc_data_uuid16_len; - + if (length < 2) { 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; length = fields->svc_data_uuid16_len; - + if (length < 4) { NIMBLE_LOGE(LOG_TAG,"Length too small for ESP_BLE_AD_TYPE_32SERVICE_DATA"); } - + uint32_t uuid = *(uint32_t*) u8p; setServiceDataUUID(NimBLEUUID(uuid)); if (length > 4) { setServiceData(std::string(reinterpret_cast(u8p + 4), length - 4)); } } - + if (fields->svc_data_uuid128 != NULL) { u8p = fields->svc_data_uuid16; length = fields->svc_data_uuid16_len; - + if (length < 16) { 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); setAppearance(fields->appearance); } - + /**** TODO: create storage and fucntions for these parameters if (fields->public_tgt_addr != NULL) { NIMBLE_LOGD(LOG_TAG, " public_tgt_addr="); @@ -329,7 +332,7 @@ bool NimBLEAdvertisedDevice::haveTXPower() { } NIMBLE_LOGD(LOG_TAG, "\n"); } - + if (fields->slave_itvl_range != NULL) { NIMBLE_LOGD(LOG_TAG, " slave_itvl_range="); 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(fields->mfg_data), fields->mfg_data_len)); } } //parseAdvertisement - + /** * @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. * @param [in] serviceUUID The discovered serviceUUID */ - + void NimBLEAdvertisedDevice::setServiceUUID(const char* serviceUUID) { return setServiceUUID(NimBLEUUID(serviceUUID)); } // setServiceUUID @@ -488,9 +491,9 @@ void NimBLEAdvertisedDevice::setTXPower(int8_t txPower) { * @brief Create 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(); - + if (haveAppearance()) { char val[6]; snprintf(val, sizeof(val), "%d", getAppearance()); @@ -508,16 +511,16 @@ std::string NimBLEAdvertisedDevice::toString() { if (haveServiceUUID()) { res += ", serviceUUID: " + getServiceUUID().toString(); } - + if (haveTXPower()) { char val[5]; snprintf(val, sizeof(val), "%d", getTXPower()); res += ", txPower: "; res += val; } - + res += ", advType: " + std::string(NimBLEUtils::advTypeToString(m_advType)); - + return res; } // toString @@ -548,5 +551,6 @@ void NimBLEAdvertisedDevice::setAdvertisementResult(uint8_t* payload, uint8_t le m_payloadLength = length; } +#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) #endif /* CONFIG_BT_ENABLED */ diff --git a/src/NimBLEAdvertisedDevice.h b/src/NimBLEAdvertisedDevice.h index a00c059..df8c876 100644 --- a/src/NimBLEAdvertisedDevice.h +++ b/src/NimBLEAdvertisedDevice.h @@ -3,7 +3,7 @@ * * Created: on Jan 24 2020 * Author H2zero - * + * * Originally: * * BLEAdvertisedDevice.h @@ -17,6 +17,9 @@ #include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) +#include "nimconfig.h" +#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) + #include "NimBLEAddress.h" #include "NimBLEScan.h" #include "NimBLEUUID.h" @@ -24,7 +27,7 @@ #include "host/ble_hs_adv.h" #include -#include +#include class NimBLEScan; @@ -129,5 +132,6 @@ public: virtual void onResult(NimBLEAdvertisedDevice* advertisedDevice) = 0; }; +#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) #endif /* CONFIG_BT_ENABLED */ #endif /* COMPONENTS_NIMBLEADVERTISEDDEVICE_H_ */ diff --git a/src/NimBLEAdvertising.cpp b/src/NimBLEAdvertising.cpp index d1a3db9..4960e8e 100644 --- a/src/NimBLEAdvertising.cpp +++ b/src/NimBLEAdvertising.cpp @@ -3,7 +3,7 @@ * * Created: on March 3, 2020 * Author H2zero - * + * * Originally: * * BLEAdvertising.cpp @@ -15,6 +15,10 @@ */ #include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) + +#include "nimconfig.h" +#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) + #include "services/gap/ble_svc_gap.h" #include "NimBLEAdvertising.h" #include "NimBLEDevice.h" @@ -31,26 +35,26 @@ static const char* LOG_TAG = "NimBLEAdvertising"; */ NimBLEAdvertising::NimBLEAdvertising() { memset(&m_advData, 0, sizeof m_advData); - memset(&m_scanData, 0, sizeof m_scanData); - memset(&m_advParams, 0, sizeof m_advParams); + memset(&m_scanData, 0, sizeof m_scanData); + memset(&m_advParams, 0, sizeof m_advParams); 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_is_complete = 1; m_scanData.tx_pwr_lvl_is_present = 1; m_scanData.tx_pwr_lvl = NimBLEDevice::getPower(); m_advData.flags = (BLE_HS_ADV_F_DISC_GEN | BLE_HS_ADV_F_BREDR_UNSUP); - m_advData.appearance = 0; - m_advData.appearance_is_present = 0; - m_advData.mfg_data_len = 0; - m_advData.mfg_data = nullptr; - - m_advParams.conn_mode = BLE_GAP_CONN_MODE_UND; + m_advData.appearance = 0; + m_advData.appearance_is_present = 0; + m_advData.mfg_data_len = 0; + m_advData.mfg_data = nullptr; + + m_advParams.conn_mode = BLE_GAP_CONN_MODE_UND; m_advParams.disc_mode = BLE_GAP_DISC_MODE_GEN; - m_advParams.itvl_min = 0; - m_advParams.itvl_max = 0; - + m_advParams.itvl_min = 0; + m_advParams.itvl_max = 0; + } // NimBLEAdvertising @@ -59,7 +63,7 @@ NimBLEAdvertising::NimBLEAdvertising() { * @param [in] serviceUUID The UUID of the service to expose. */ void NimBLEAdvertising::addServiceUUID(const NimBLEUUID &serviceUUID) { - m_serviceUUIDs.push_back(serviceUUID); + m_serviceUUIDs.push_back(serviceUUID); } // addServiceUUID @@ -68,7 +72,7 @@ void NimBLEAdvertising::addServiceUUID(const NimBLEUUID &serviceUUID) { * @param [in] serviceUUID The string representation of the service to expose. */ void NimBLEAdvertising::addServiceUUID(const char* serviceUUID) { - addServiceUUID(NimBLEUUID(serviceUUID)); + addServiceUUID(NimBLEUUID(serviceUUID)); } // addServiceUUID @@ -80,34 +84,34 @@ void NimBLEAdvertising::addServiceUUID(const char* serviceUUID) { * @return N/A. */ void NimBLEAdvertising::setAppearance(uint16_t appearance) { - m_advData.appearance = appearance; - m_advData.appearance_is_present = 1; + m_advData.appearance = appearance; + m_advData.appearance_is_present = 1; } // setAppearance void NimBLEAdvertising::setAdvertisementType(uint8_t adv_type){ - m_advParams.conn_mode = adv_type; + m_advParams.conn_mode = adv_type; } // setAdvertisementType void NimBLEAdvertising::setMinInterval(uint16_t mininterval) { - m_advParams.itvl_min = mininterval; + m_advParams.itvl_min = mininterval; } // setMinInterval void NimBLEAdvertising::setMaxInterval(uint16_t maxinterval) { - m_advParams.itvl_max = maxinterval; + m_advParams.itvl_max = maxinterval; } // setMaxInterval // These are dummy functions for now for compatibility void NimBLEAdvertising::setMinPreferred(uint16_t mininterval) { - //m_advData.min_interval = mininterval; -} // + //m_advData.min_interval = mininterval; +} // void NimBLEAdvertising::setMaxPreferred(uint16_t maxinterval) { - //m_advData.max_interval = maxinterval; -} // + //m_advData.max_interval = maxinterval; +} // ////////////////////////////////////////////////////////// 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. */ void NimBLEAdvertising::setScanFilter(bool scanRequestWhitelistOnly, bool connectWhitelistOnly) { - NIMBLE_LOGD(LOG_TAG, ">> setScanFilter: scanRequestWhitelistOnly: %d, connectWhitelistOnly: %d", scanRequestWhitelistOnly, connectWhitelistOnly); - if (!scanRequestWhitelistOnly && !connectWhitelistOnly) { - m_advParams.filter_policy = BLE_HCI_ADV_FILT_NONE; - NIMBLE_LOGD(LOG_TAG, "<< setScanFilter"); - return; - } - if (scanRequestWhitelistOnly && !connectWhitelistOnly) { - m_advParams.filter_policy = BLE_HCI_ADV_FILT_SCAN; - NIMBLE_LOGD(LOG_TAG, "<< setScanFilter"); - return; - } - if (!scanRequestWhitelistOnly && connectWhitelistOnly) { - m_advParams.filter_policy = BLE_HCI_ADV_FILT_CONN; - NIMBLE_LOGD(LOG_TAG, "<< setScanFilter"); - return; - } - if (scanRequestWhitelistOnly && connectWhitelistOnly) { - m_advParams.filter_policy = BLE_HCI_ADV_FILT_BOTH; - NIMBLE_LOGD(LOG_TAG, "<< setScanFilter"); - return; - } + NIMBLE_LOGD(LOG_TAG, ">> setScanFilter: scanRequestWhitelistOnly: %d, connectWhitelistOnly: %d", scanRequestWhitelistOnly, connectWhitelistOnly); + if (!scanRequestWhitelistOnly && !connectWhitelistOnly) { + m_advParams.filter_policy = BLE_HCI_ADV_FILT_NONE; + NIMBLE_LOGD(LOG_TAG, "<< setScanFilter"); + return; + } + if (scanRequestWhitelistOnly && !connectWhitelistOnly) { + m_advParams.filter_policy = BLE_HCI_ADV_FILT_SCAN; + NIMBLE_LOGD(LOG_TAG, "<< setScanFilter"); + return; + } + if (!scanRequestWhitelistOnly && connectWhitelistOnly) { + m_advParams.filter_policy = BLE_HCI_ADV_FILT_CONN; + NIMBLE_LOGD(LOG_TAG, "<< setScanFilter"); + return; + } + if (scanRequestWhitelistOnly && connectWhitelistOnly) { + m_advParams.filter_policy = BLE_HCI_ADV_FILT_BOTH; + NIMBLE_LOGD(LOG_TAG, "<< setScanFilter"); + return; + } } // setScanFilter /** * @brief Set the advertisement data that is to be published in a regular advertisement. * @param [in] advertisementData The data to be advertised. */ - + void NimBLEAdvertising::setAdvertisementData(NimBLEAdvertisementData& advertisementData) { - NIMBLE_LOGD(LOG_TAG, ">> setAdvertisementData"); - int rc = ble_gap_adv_set_data( - (uint8_t*)advertisementData.getPayload().data(), - advertisementData.getPayload().length()); - if (rc != 0) { - 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. - NIMBLE_LOGD(LOG_TAG, "<< setAdvertisementData"); + NIMBLE_LOGD(LOG_TAG, ">> setAdvertisementData"); + int rc = ble_gap_adv_set_data( + (uint8_t*)advertisementData.getPayload().data(), + advertisementData.getPayload().length()); + if (rc != 0) { + 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. + NIMBLE_LOGD(LOG_TAG, "<< setAdvertisementData"); } // setAdvertisementData @@ -162,15 +166,15 @@ void NimBLEAdvertising::setAdvertisementData(NimBLEAdvertisementData& advertisem * @param [in] advertisementData The data to be advertised. */ void NimBLEAdvertising::setScanResponseData(NimBLEAdvertisementData& advertisementData) { - NIMBLE_LOGD(LOG_TAG, ">> setScanResponseData"); - int rc = ble_gap_adv_rsp_set_data( - (uint8_t*)advertisementData.getPayload().data(), - advertisementData.getPayload().length()); - if (rc != 0) { - 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. - NIMBLE_LOGD(LOG_TAG, "<< setScanResponseData"); + NIMBLE_LOGD(LOG_TAG, ">> setScanResponseData"); + int rc = ble_gap_adv_rsp_set_data( + (uint8_t*)advertisementData.getPayload().data(), + advertisementData.getPayload().length()); + if (rc != 0) { + 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. + NIMBLE_LOGD(LOG_TAG, "<< setScanResponseData"); } // setScanResponseData @@ -180,186 +184,191 @@ void NimBLEAdvertising::setScanResponseData(NimBLEAdvertisementData& advertiseme * @return N/A. */ 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(!NimBLEDevice::m_synced) { NIMBLE_LOGE(LOG_TAG, "Host reset, wait for sync."); 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"); return; } - - int numServices = m_serviceUUIDs.size(); +#endif + + int numServices = m_serviceUUIDs.size(); int rc = 0; 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(ble_gap_adv_active()) { return; } - - NimBLEServer* pServer = NimBLEDevice::createServer(); - if(!pServer->m_gattsStarted){ - pServer->start(); - } - - if (!m_customAdvData && !m_advSvcsSet && numServices > 0) { - for (int i = 0; i < numServices; i++) { - if(m_serviceUUIDs[i].getNative()->u.type == BLE_UUID_TYPE_16) { - int add = (m_advData.num_uuids16 > 0) ? 2 : 4; - if((payloadLen + add) > 31){ - m_advData.uuids16_is_complete = 0; - continue; - } - payloadLen += add; - - if(nullptr == (m_advData.uuids16 = (ble_uuid16_t*)realloc(m_advData.uuids16, - (m_advData.num_uuids16 + 1) * sizeof(ble_uuid16_t)))) + + if (!m_customAdvData && !m_advSvcsSet && numServices > 0) { + for (int i = 0; i < numServices; i++) { + if(m_serviceUUIDs[i].getNative()->u.type == BLE_UUID_TYPE_16) { + int add = (m_advData.num_uuids16 > 0) ? 2 : 4; + if((payloadLen + add) > 31){ + m_advData.uuids16_is_complete = 0; + continue; + } + 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"); 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_advData.uuids16[m_advData.num_uuids16].u.type = BLE_UUID_TYPE_16; m_advData.uuids16_is_complete = 1; m_advData.num_uuids16++; - } - if(m_serviceUUIDs[i].getNative()->u.type == BLE_UUID_TYPE_32) { - int add = (m_advData.num_uuids32 > 0) ? 4 : 6; - if((payloadLen + add) > 31){ - m_advData.uuids32_is_complete = 0; - continue; - } - payloadLen += add; - + } + if(m_serviceUUIDs[i].getNative()->u.type == BLE_UUID_TYPE_32) { + int add = (m_advData.num_uuids32 > 0) ? 4 : 6; + if((payloadLen + add) > 31){ + m_advData.uuids32_is_complete = 0; + continue; + } + payloadLen += add; + 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"); 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_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.num_uuids32++; - } - if(m_serviceUUIDs[i].getNative()->u.type == BLE_UUID_TYPE_128){ - int add = (m_advData.num_uuids128 > 0) ? 16 : 18; - if((payloadLen + add) > 31){ - m_advData.uuids128_is_complete = 0; - continue; - } - payloadLen += add; - - if(nullptr == (m_advData.uuids128 = (ble_uuid128_t*)realloc(m_advData.uuids128, + } + if(m_serviceUUIDs[i].getNative()->u.type == BLE_UUID_TYPE_128){ + int add = (m_advData.num_uuids128 > 0) ? 16 : 18; + if((payloadLen + add) > 31){ + m_advData.uuids128_is_complete = 0; + continue; + } + payloadLen += add; + + if(nullptr == (m_advData.uuids128 = (ble_uuid128_t*)realloc(m_advData.uuids128, (m_advData.num_uuids128 + 1) * sizeof(ble_uuid128_t)))) { NIMBLE_LOGE(LOG_TAG, "Error, no mem"); 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_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.num_uuids128++; - } - } - - // check if there is room for the name, if not put it in scan data - if((payloadLen + m_advData.name_len) > 29) { - if(m_scanResp){ - m_scanData.name = m_advData.name; - m_scanData.name_len = m_advData.name_len; - m_scanData.name_is_complete = m_advData.name_is_complete; - m_advData.name = nullptr; - m_advData.name_len = 0; - } else { - // if not using scan response just cut the name down - // leaving 2 bytes for the data specifier. - m_advData.name_len = (29 - payloadLen); - } - m_advData.name_is_complete = 0; - } - - if(m_advData.name_len > 0) { - payloadLen += (m_advData.name_len + 2); - } - - if(m_scanResp) { - // name length + type byte + length byte + tx power type + length + data - if((m_scanData.name_len + 5) > 31) { - // prioritize name data over tx power - m_scanData.tx_pwr_lvl_is_present = 0; - m_scanData.tx_pwr_lvl = 0; - // limit name to 29 to leave room for the data specifiers - if(m_scanData.name_len > 29) { - m_scanData.name_len = 29; - m_scanData.name_is_complete = false; - } - } - - rc = ble_gap_adv_rsp_set_fields(&m_scanData); - if (rc != 0) { - NIMBLE_LOGE(LOG_TAG, "error setting scan response data; rc=%d, %s", rc, NimBLEUtils::returnCodeToString(rc)); - abort(); - } - // if not using scan response and there is room, - // throw the tx power data into the advertisment + } + } + + // check if there is room for the name, if not put it in scan data + if((payloadLen + m_advData.name_len) > 29) { + if(m_scanResp){ + m_scanData.name = m_advData.name; + m_scanData.name_len = m_advData.name_len; + m_scanData.name_is_complete = m_advData.name_is_complete; + m_advData.name = nullptr; + m_advData.name_len = 0; + } else { + // if not using scan response just cut the name down + // leaving 2 bytes for the data specifier. + m_advData.name_len = (29 - payloadLen); + } + m_advData.name_is_complete = 0; + } + + if(m_advData.name_len > 0) { + payloadLen += (m_advData.name_len + 2); + } + + if(m_scanResp) { + // name length + type byte + length byte + tx power type + length + data + if((m_scanData.name_len + 5) > 31) { + // prioritize name data over tx power + m_scanData.tx_pwr_lvl_is_present = 0; + m_scanData.tx_pwr_lvl = 0; + // limit name to 29 to leave room for the data specifiers + if(m_scanData.name_len > 29) { + m_scanData.name_len = 29; + m_scanData.name_is_complete = false; + } + } + + rc = ble_gap_adv_rsp_set_fields(&m_scanData); + if (rc != 0) { + NIMBLE_LOGE(LOG_TAG, "error setting scan response data; rc=%d, %s", rc, NimBLEUtils::returnCodeToString(rc)); + abort(); + } + // if not using scan response and there is room, + // throw the tx power data into the advertisment } else if (payloadLen < 29) { - m_advData.tx_pwr_lvl_is_present = 1; - m_advData.tx_pwr_lvl = NimBLEDevice::getPower(); - } - + m_advData.tx_pwr_lvl_is_present = 1; + m_advData.tx_pwr_lvl = NimBLEDevice::getPower(); + } + rc = ble_gap_adv_set_fields(&m_advData); if (rc != 0) { NIMBLE_LOGE(LOG_TAG, "error setting advertisement data; rc=%d, %s", rc, NimBLEUtils::returnCodeToString(rc)); abort(); } - + if(m_advData.num_uuids128 > 0) { free(m_advData.uuids128); m_advData.uuids128 = nullptr; m_advData.num_uuids128 = 0; } - + if(m_advData.num_uuids32 > 0) { free(m_advData.uuids32); m_advData.uuids32 = nullptr; m_advData.num_uuids32 = 0; } - + if(m_advData.num_uuids16 > 0) { free(m_advData.uuids16); m_advData.uuids16 = nullptr; m_advData.num_uuids16 = 0; } - + m_advSvcsSet = true; } - + rc = ble_hs_id_infer_auto(0, &addressType); if (rc != 0) { NIMBLE_LOGC(LOG_TAG, "Error determining address type; rc=%d, %s", rc, NimBLEUtils::returnCodeToString(rc)); abort(); - } + } +#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) 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) +#else + rc = ble_gap_adv_start(addressType, NULL, BLE_HS_FOREVER, + &m_advParams, NULL,NULL); +#endif if (rc != 0) { NIMBLE_LOGC(LOG_TAG, "Error enabling advertising; rc=%d, %s", rc, NimBLEUtils::returnCodeToString(rc)); abort(); } - - NIMBLE_LOGD(LOG_TAG, "<< Advertising start"); + + NIMBLE_LOGD(LOG_TAG, "<< Advertising start"); } // start @@ -369,35 +378,35 @@ void NimBLEAdvertising::start() { * @return N/A. */ void NimBLEAdvertising::stop() { - NIMBLE_LOGD(LOG_TAG, ">> stop"); - int rc = ble_gap_adv_stop(); - if (rc != 0 && rc != BLE_HS_EALREADY) { - NIMBLE_LOGE(LOG_TAG, "ble_gap_adv_stop rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc)); - return; - } + NIMBLE_LOGD(LOG_TAG, ">> stop"); + int rc = ble_gap_adv_stop(); + if (rc != 0 && rc != BLE_HS_EALREADY) { + NIMBLE_LOGE(LOG_TAG, "ble_gap_adv_stop rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc)); + return; + } - NIMBLE_LOGD(LOG_TAG, "<< stop"); + NIMBLE_LOGD(LOG_TAG, "<< 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. - */ + */ void NimBLEAdvertising::onHostReset() { m_advSvcsSet = false; } - + /** * @brief Add data to the payload to be advertised. * @param [in] data The data to be added to the payload. */ void NimBLEAdvertisementData::addData(const std::string &data) { - if ((m_payload.length() + data.length()) > BLE_HS_ADV_MAX_SZ) { - return; - } - m_payload.append(data); + if ((m_payload.length() + data.length()) > BLE_HS_ADV_MAX_SZ) { + return; + } + m_payload.append(data); } // 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 */ void NimBLEAdvertisementData::setAppearance(uint16_t appearance) { - char cdata[2]; - cdata[0] = 3; - cdata[1] = BLE_HS_ADV_TYPE_APPEARANCE; // 0x19 - addData(std::string(cdata, 2) + std::string((char*) &appearance, 2)); + char cdata[2]; + cdata[0] = 3; + cdata[1] = BLE_HS_ADV_TYPE_APPEARANCE; // 0x19 + addData(std::string(cdata, 2) + std::string((char*) &appearance, 2)); } // setAppearance @@ -421,35 +430,35 @@ void NimBLEAdvertisementData::setAppearance(uint16_t appearance) { * @param [in] uuid The single service to advertise. */ void NimBLEAdvertisementData::setCompleteServices(const NimBLEUUID &uuid) { - char cdata[2]; - switch (uuid.bitSize()) { - case 16: { - // [Len] [0x02] [LL] [HH] - cdata[0] = 3; - cdata[1] = BLE_HS_ADV_TYPE_COMP_UUIDS16; // 0x03 - addData(std::string(cdata, 2) + std::string((char*) &uuid.getNative()->u16.value, 2)); - break; - } + char cdata[2]; + switch (uuid.bitSize()) { + case 16: { + // [Len] [0x02] [LL] [HH] + cdata[0] = 3; + cdata[1] = BLE_HS_ADV_TYPE_COMP_UUIDS16; // 0x03 + addData(std::string(cdata, 2) + std::string((char*) &uuid.getNative()->u16.value, 2)); + break; + } - case 32: { - // [Len] [0x04] [LL] [LL] [HH] [HH] - cdata[0] = 5; - cdata[1] = BLE_HS_ADV_TYPE_COMP_UUIDS32; // 0x05 - addData(std::string(cdata, 2) + std::string((char*) &uuid.getNative()->u32.value, 4)); - break; - } + case 32: { + // [Len] [0x04] [LL] [LL] [HH] [HH] + cdata[0] = 5; + cdata[1] = BLE_HS_ADV_TYPE_COMP_UUIDS32; // 0x05 + addData(std::string(cdata, 2) + std::string((char*) &uuid.getNative()->u32.value, 4)); + break; + } - case 128: { - // [Len] [0x04] [0] [1] ... [15] - cdata[0] = 17; - cdata[1] = BLE_HS_ADV_TYPE_COMP_UUIDS128; // 0x07 - addData(std::string(cdata, 2) + std::string((char*) uuid.getNative()->u128.value, 16)); - break; - } + case 128: { + // [Len] [0x04] [0] [1] ... [15] + cdata[0] = 17; + cdata[1] = BLE_HS_ADV_TYPE_COMP_UUIDS128; // 0x07 + addData(std::string(cdata, 2) + std::string((char*) uuid.getNative()->u128.value, 16)); + break; + } - default: - return; - } + default: + return; + } } // setCompleteServices @@ -463,18 +472,18 @@ void NimBLEAdvertisementData::setCompleteServices(const NimBLEUUID &uuid) { * * ESP_BLE_ADV_FLAG_DMT_CONTROLLER_SPT * * ESP_BLE_ADV_FLAG_DMT_HOST_SPT * * ESP_BLE_ADV_FLAG_NON_LIMIT_DISC - * * + * * * * ****THESE ARE SUPPORTED**** * * BLE_HS_ADV_F_DISC_LTD * * BLE_HS_ADV_F_DISC_GEN * * BLE_HS_ADV_F_BREDR_UNSUP - must always use with NimBLE */ void NimBLEAdvertisementData::setFlags(uint8_t flag) { - char cdata[3]; - cdata[0] = 2; - cdata[1] = BLE_HS_ADV_TYPE_FLAGS; // 0x01 - cdata[2] = flag | BLE_HS_ADV_F_BREDR_UNSUP; - addData(std::string(cdata, 3)); + char cdata[3]; + cdata[0] = 2; + cdata[1] = BLE_HS_ADV_TYPE_FLAGS; // 0x01 + cdata[2] = flag | BLE_HS_ADV_F_BREDR_UNSUP; + addData(std::string(cdata, 3)); } // setFlag @@ -483,12 +492,12 @@ void NimBLEAdvertisementData::setFlags(uint8_t flag) { * @param [in] data Manufacturer data. */ void NimBLEAdvertisementData::setManufacturerData(const std::string &data) { - NIMBLE_LOGD("NimBLEAdvertisementData", ">> setManufacturerData"); - char cdata[2]; - cdata[0] = data.length() + 1; - cdata[1] = BLE_HS_ADV_TYPE_MFG_DATA ; // 0xff - addData(std::string(cdata, 2) + data); - NIMBLE_LOGD("NimBLEAdvertisementData", "<< setManufacturerData"); + NIMBLE_LOGD("NimBLEAdvertisementData", ">> setManufacturerData"); + char cdata[2]; + cdata[0] = data.length() + 1; + cdata[1] = BLE_HS_ADV_TYPE_MFG_DATA ; // 0xff + addData(std::string(cdata, 2) + data); + NIMBLE_LOGD("NimBLEAdvertisementData", "<< setManufacturerData"); } // setManufacturerData @@ -497,12 +506,12 @@ void NimBLEAdvertisementData::setManufacturerData(const std::string &data) { * @param [in] The complete name of the device. */ void NimBLEAdvertisementData::setName(const std::string &name) { - NIMBLE_LOGD("NimBLEAdvertisementData", ">> setName: %s", name.c_str()); - char cdata[2]; - cdata[0] = name.length() + 1; - cdata[1] = BLE_HS_ADV_TYPE_COMP_NAME; // 0x09 - addData(std::string(cdata, 2) + name); - NIMBLE_LOGD("NimBLEAdvertisementData", "<< setName"); + NIMBLE_LOGD("NimBLEAdvertisementData", ">> setName: %s", name.c_str()); + char cdata[2]; + cdata[0] = name.length() + 1; + cdata[1] = BLE_HS_ADV_TYPE_COMP_NAME; // 0x09 + addData(std::string(cdata, 2) + name); + NIMBLE_LOGD("NimBLEAdvertisementData", "<< setName"); } // setName @@ -511,35 +520,35 @@ void NimBLEAdvertisementData::setName(const std::string &name) { * @param [in] uuid The single service to advertise. */ void NimBLEAdvertisementData::setPartialServices(const NimBLEUUID &uuid) { - char cdata[2]; - switch (uuid.bitSize()) { - case 16: { - // [Len] [0x02] [LL] [HH] - cdata[0] = 3; - cdata[1] = BLE_HS_ADV_TYPE_INCOMP_UUIDS16; // 0x02 - addData(std::string(cdata, 2) + std::string((char *) &uuid.getNative()->u16.value, 2)); - break; - } + char cdata[2]; + switch (uuid.bitSize()) { + case 16: { + // [Len] [0x02] [LL] [HH] + cdata[0] = 3; + cdata[1] = BLE_HS_ADV_TYPE_INCOMP_UUIDS16; // 0x02 + addData(std::string(cdata, 2) + std::string((char *) &uuid.getNative()->u16.value, 2)); + break; + } - case 32: { - // [Len] [0x04] [LL] [LL] [HH] [HH] - cdata[0] = 5; - cdata[1] = BLE_HS_ADV_TYPE_INCOMP_UUIDS32; // 0x04 - addData(std::string(cdata, 2) + std::string((char *) &uuid.getNative()->u32.value, 4)); - break; - } + case 32: { + // [Len] [0x04] [LL] [LL] [HH] [HH] + cdata[0] = 5; + cdata[1] = BLE_HS_ADV_TYPE_INCOMP_UUIDS32; // 0x04 + addData(std::string(cdata, 2) + std::string((char *) &uuid.getNative()->u32.value, 4)); + break; + } - case 128: { - // [Len] [0x04] [0] [1] ... [15] - cdata[0] = 17; - cdata[1] = BLE_HS_ADV_TYPE_INCOMP_UUIDS128; // 0x06 - addData(std::string(cdata, 2) + std::string((char *) &uuid.getNative()->u128.value, 16)); - break; - } + case 128: { + // [Len] [0x04] [0] [1] ... [15] + cdata[0] = 17; + cdata[1] = BLE_HS_ADV_TYPE_INCOMP_UUIDS128; // 0x06 + addData(std::string(cdata, 2) + std::string((char *) &uuid.getNative()->u128.value, 16)); + break; + } - default: - return; - } + default: + return; + } } // setPartialServices @@ -549,35 +558,35 @@ void NimBLEAdvertisementData::setPartialServices(const NimBLEUUID &uuid) { * @param [in] data The data to be associated with the service data advert. */ void NimBLEAdvertisementData::setServiceData(const NimBLEUUID &uuid, const std::string &data) { - char cdata[2]; - switch (uuid.bitSize()) { - case 16: { - // [Len] [0x16] [UUID16] data - cdata[0] = data.length() + 3; - cdata[1] = BLE_HS_ADV_TYPE_SVC_DATA_UUID16; // 0x16 - addData(std::string(cdata, 2) + std::string((char*) &uuid.getNative()->u16.value, 2) + data); - break; - } + char cdata[2]; + switch (uuid.bitSize()) { + case 16: { + // [Len] [0x16] [UUID16] data + cdata[0] = data.length() + 3; + cdata[1] = BLE_HS_ADV_TYPE_SVC_DATA_UUID16; // 0x16 + addData(std::string(cdata, 2) + std::string((char*) &uuid.getNative()->u16.value, 2) + data); + break; + } - case 32: { - // [Len] [0x20] [UUID32] data - cdata[0] = data.length() + 5; - cdata[1] = BLE_HS_ADV_TYPE_SVC_DATA_UUID32; // 0x20 - addData(std::string(cdata, 2) + std::string((char*) &uuid.getNative()->u32.value, 4) + data); - break; - } + case 32: { + // [Len] [0x20] [UUID32] data + cdata[0] = data.length() + 5; + cdata[1] = BLE_HS_ADV_TYPE_SVC_DATA_UUID32; // 0x20 + addData(std::string(cdata, 2) + std::string((char*) &uuid.getNative()->u32.value, 4) + data); + break; + } - case 128: { - // [Len] [0x21] [UUID128] data - cdata[0] = data.length() + 17; - cdata[1] = BLE_HS_ADV_TYPE_SVC_DATA_UUID128; // 0x21 - addData(std::string(cdata, 2) + std::string((char*) &uuid.getNative()->u128.value, 16) + data); - break; - } + case 128: { + // [Len] [0x21] [UUID128] data + cdata[0] = data.length() + 17; + cdata[1] = BLE_HS_ADV_TYPE_SVC_DATA_UUID128; // 0x21 + addData(std::string(cdata, 2) + std::string((char*) &uuid.getNative()->u128.value, 16) + data); + break; + } - default: - return; - } + default: + return; + } } // setServiceData @@ -586,12 +595,12 @@ void NimBLEAdvertisementData::setServiceData(const NimBLEUUID &uuid, const std:: * @param [in] The short name of the device. */ void NimBLEAdvertisementData::setShortName(const std::string &name) { - NIMBLE_LOGD("NimBLEAdvertisementData", ">> setShortName: %s", name.c_str()); - char cdata[2]; - cdata[0] = name.length() + 1; - cdata[1] = BLE_HS_ADV_TYPE_INCOMP_NAME; // 0x08 - addData(std::string(cdata, 2) + name); - NIMBLE_LOGD("NimBLEAdvertisementData", "<< setShortName"); + NIMBLE_LOGD("NimBLEAdvertisementData", ">> setShortName: %s", name.c_str()); + char cdata[2]; + cdata[0] = name.length() + 1; + cdata[1] = BLE_HS_ADV_TYPE_INCOMP_NAME; // 0x08 + addData(std::string(cdata, 2) + name); + NIMBLE_LOGD("NimBLEAdvertisementData", "<< setShortName"); } // setShortName @@ -600,7 +609,8 @@ void NimBLEAdvertisementData::setShortName(const std::string &name) { * @return The payload that is to be advertised. */ std::string NimBLEAdvertisementData::getPayload() { - return m_payload; + return m_payload; } // getPayload +#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #endif /* CONFIG_BT_ENABLED */ diff --git a/src/NimBLEAdvertising.h b/src/NimBLEAdvertising.h index d5409e5..f30b158 100644 --- a/src/NimBLEAdvertising.h +++ b/src/NimBLEAdvertising.h @@ -3,7 +3,7 @@ * * Created: on March 3, 2020 * Author H2zero - * + * * Originally: * * BLEAdvertising.h @@ -17,6 +17,9 @@ #include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) +#include "nimconfig.h" +#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) + #include "host/ble_gap.h" /**** FIX COMPILATION ****/ #undef min @@ -42,24 +45,24 @@ * @brief Advertisement data set by the programmer to be published by the %BLE server. */ class NimBLEAdvertisementData { - // Only a subset of the possible BLE architected advertisement fields are currently exposed. Others will - // be exposed on demand/request or as time permits. - // + // Only a subset of the possible BLE architected advertisement fields are currently exposed. Others will + // be exposed on demand/request or as time permits. + // public: - void setAppearance(uint16_t appearance); - void setCompleteServices(const NimBLEUUID &uuid); - void setFlags(uint8_t); - void setManufacturerData(const std::string &data); - void setName(const std::string &name); - void setPartialServices(const NimBLEUUID &uuid); - void setServiceData(const NimBLEUUID &uuid, const std::string &data); - void setShortName(const std::string &name); - void addData(const std::string &data); // Add data to the payload. - std::string getPayload(); // Retrieve the current advert payload. + void setAppearance(uint16_t appearance); + void setCompleteServices(const NimBLEUUID &uuid); + void setFlags(uint8_t); + void setManufacturerData(const std::string &data); + void setName(const std::string &name); + void setPartialServices(const NimBLEUUID &uuid); + void setServiceData(const NimBLEUUID &uuid, const std::string &data); + void setShortName(const std::string &name); + void addData(const std::string &data); // Add data to the payload. + std::string getPayload(); // Retrieve the current advert payload. private: - friend class NimBLEAdvertising; - std::string m_payload; // The payload of the advertisement. + friend class NimBLEAdvertising; + std::string m_payload; // The payload of the advertisement. }; // NimBLEAdvertisementData @@ -70,36 +73,40 @@ private: */ class NimBLEAdvertising { public: - NimBLEAdvertising(); - void addServiceUUID(const NimBLEUUID &serviceUUID); - void addServiceUUID(const char* serviceUUID); - void start(); - void stop(); - void setAppearance(uint16_t appearance); + NimBLEAdvertising(); + void addServiceUUID(const NimBLEUUID &serviceUUID); + void addServiceUUID(const char* serviceUUID); + void start(); + void stop(); + void setAppearance(uint16_t appearance); void setAdvertisementType(uint8_t adv_type); - void setMaxInterval(uint16_t maxinterval); - void setMinInterval(uint16_t mininterval); - void setAdvertisementData(NimBLEAdvertisementData& advertisementData); - void setScanFilter(bool scanRequertWhitelistOnly, bool connectWhitelistOnly); - void setScanResponseData(NimBLEAdvertisementData& advertisementData); - void setPrivateAddress(uint8_t type = BLE_ADDR_RANDOM); + void setMaxInterval(uint16_t maxinterval); + void setMinInterval(uint16_t mininterval); + void setAdvertisementData(NimBLEAdvertisementData& advertisementData); + void setScanFilter(bool scanRequertWhitelistOnly, bool connectWhitelistOnly); + void setScanResponseData(NimBLEAdvertisementData& advertisementData); + void setPrivateAddress(uint8_t type = BLE_ADDR_RANDOM); - void setMinPreferred(uint16_t); - void setMaxPreferred(uint16_t); - void setScanResponse(bool); + void setMinPreferred(uint16_t); + void setMaxPreferred(uint16_t); + void setScanResponse(bool); private: friend class NimBLEDevice; + void onHostReset(); - ble_hs_adv_fields m_advData; - ble_hs_adv_fields m_scanData; - ble_gap_adv_params m_advParams; - std::vector m_serviceUUIDs; - bool m_customAdvData = false; // Are we using custom advertising data? - bool m_customScanResponseData = false; // Are we using custom scan response data? - bool m_scanResp = true; + + ble_hs_adv_fields m_advData; + ble_hs_adv_fields m_scanData; + ble_gap_adv_params m_advParams; + std::vector m_serviceUUIDs; + bool m_customAdvData = false; // Are we using custom advertising data? + bool m_customScanResponseData = false; // Are we using custom scan response data? + bool m_scanResp = true; bool m_advSvcsSet = false; }; + +#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #endif /* CONFIG_BT_ENABLED */ #endif /* MAIN_BLEADVERTISING_H_ */ diff --git a/src/NimBLEBeacon.cpp b/src/NimBLEBeacon.cpp index 2144cef..718a507 100644 --- a/src/NimBLEBeacon.cpp +++ b/src/NimBLEBeacon.cpp @@ -3,7 +3,7 @@ * * Created: on March 15 2020 * Author H2zero - * + * * Originally: * * BLEBeacon.cpp @@ -13,6 +13,7 @@ */ #include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) + #include #include "NimBLEBeacon.h" #include "NimBLELog.h" @@ -22,72 +23,71 @@ static const char* LOG_TAG = "NimBLEBeacon"; NimBLEBeacon::NimBLEBeacon() { - m_beaconData.manufacturerId = 0x4c00; - m_beaconData.subType = 0x02; - m_beaconData.subTypeLength = 0x15; - m_beaconData.major = 0; - m_beaconData.minor = 0; - m_beaconData.signalPower = 0; - memset(m_beaconData.proximityUUID, 0, sizeof(m_beaconData.proximityUUID)); + m_beaconData.manufacturerId = 0x4c00; + m_beaconData.subType = 0x02; + m_beaconData.subTypeLength = 0x15; + m_beaconData.major = 0; + m_beaconData.minor = 0; + m_beaconData.signalPower = 0; + memset(m_beaconData.proximityUUID, 0, sizeof(m_beaconData.proximityUUID)); } // NimBLEBeacon std::string NimBLEBeacon::getData() { - return std::string((char*) &m_beaconData, sizeof(m_beaconData)); + return std::string((char*) &m_beaconData, sizeof(m_beaconData)); } // getData uint16_t NimBLEBeacon::getMajor() { - return m_beaconData.major; + return m_beaconData.major; } uint16_t NimBLEBeacon::getManufacturerId() { - return m_beaconData.manufacturerId; + return m_beaconData.manufacturerId; } uint16_t NimBLEBeacon::getMinor() { - return m_beaconData.minor; + return m_beaconData.minor; } NimBLEUUID NimBLEBeacon::getProximityUUID() { - return NimBLEUUID(m_beaconData.proximityUUID, 16, false); + return NimBLEUUID(m_beaconData.proximityUUID, 16, false); } int8_t NimBLEBeacon::getSignalPower() { - return m_beaconData.signalPower; + return m_beaconData.signalPower; } /** * Set the raw data for the beacon record. */ void NimBLEBeacon::setData(const std::string &data) { - if (data.length() != sizeof(m_beaconData)) { - NIMBLE_LOGE(LOG_TAG, "Unable to set the data ... length passed in was %d and expected %d", + if (data.length() != sizeof(m_beaconData)) { + NIMBLE_LOGE(LOG_TAG, "Unable to set the data ... length passed in was %d and expected %d", data.length(), sizeof(m_beaconData)); - return; - } - memcpy(&m_beaconData, data.data(), sizeof(m_beaconData)); + return; + } + memcpy(&m_beaconData, data.data(), sizeof(m_beaconData)); } // setData void NimBLEBeacon::setMajor(uint16_t major) { - m_beaconData.major = ENDIAN_CHANGE_U16(major); + m_beaconData.major = ENDIAN_CHANGE_U16(major); } // setMajor void NimBLEBeacon::setManufacturerId(uint16_t manufacturerId) { - m_beaconData.manufacturerId = ENDIAN_CHANGE_U16(manufacturerId); + m_beaconData.manufacturerId = ENDIAN_CHANGE_U16(manufacturerId); } // setManufacturerId void NimBLEBeacon::setMinor(uint16_t minor) { - m_beaconData.minor = ENDIAN_CHANGE_U16(minor); + m_beaconData.minor = ENDIAN_CHANGE_U16(minor); } // setMinior void NimBLEBeacon::setProximityUUID(const NimBLEUUID &uuid) { - NimBLEUUID temp_uuid = uuid; - temp_uuid.to128(); - memcpy(m_beaconData.proximityUUID, temp_uuid.getNative()->u128.value, 16); + NimBLEUUID temp_uuid = uuid; + temp_uuid.to128(); + memcpy(m_beaconData.proximityUUID, temp_uuid.getNative()->u128.value, 16); } // setProximityUUID void NimBLEBeacon::setSignalPower(int8_t signalPower) { - m_beaconData.signalPower = signalPower; + m_beaconData.signalPower = signalPower; } // setSignalPower - #endif diff --git a/src/NimBLEBeacon.h b/src/NimBLEBeacon.h index 67a3595..82ee61c 100644 --- a/src/NimBLEBeacon.h +++ b/src/NimBLEBeacon.h @@ -3,7 +3,7 @@ * * Created: on March 15 2020 * Author H2zero - * + * * Originally: * * BLEBeacon2.h @@ -14,6 +14,7 @@ #ifndef MAIN_NIMBLEBEACON_H_ #define MAIN_NIMBLEBEACON_H_ + #include "NimBLEUUID.h" /** * @brief Representation of a beacon. @@ -22,29 +23,29 @@ */ class NimBLEBeacon { private: - struct { - uint16_t manufacturerId; - uint8_t subType; - uint8_t subTypeLength; - uint8_t proximityUUID[16]; - uint16_t major; - uint16_t minor; - int8_t signalPower; - } __attribute__((packed)) m_beaconData; + struct { + uint16_t manufacturerId; + uint8_t subType; + uint8_t subTypeLength; + uint8_t proximityUUID[16]; + uint16_t major; + uint16_t minor; + int8_t signalPower; + } __attribute__((packed)) m_beaconData; public: - NimBLEBeacon(); - std::string getData(); - uint16_t getMajor(); - uint16_t getMinor(); - uint16_t getManufacturerId(); - NimBLEUUID getProximityUUID(); - int8_t getSignalPower(); - void setData(const std::string &data); - void setMajor(uint16_t major); - void setMinor(uint16_t minor); - void setManufacturerId(uint16_t manufacturerId); - void setProximityUUID(const NimBLEUUID &uuid); - void setSignalPower(int8_t signalPower); + NimBLEBeacon(); + std::string getData(); + uint16_t getMajor(); + uint16_t getMinor(); + uint16_t getManufacturerId(); + NimBLEUUID getProximityUUID(); + int8_t getSignalPower(); + void setData(const std::string &data); + void setMajor(uint16_t major); + void setMinor(uint16_t minor); + void setManufacturerId(uint16_t manufacturerId); + void setProximityUUID(const NimBLEUUID &uuid); + void setSignalPower(int8_t signalPower); }; // NimBLEBeacon #endif /* MAIN_NIMBLEBEACON_H_ */ diff --git a/src/NimBLECharacteristic.cpp b/src/NimBLECharacteristic.cpp index 03c6b52..dd1be3b 100644 --- a/src/NimBLECharacteristic.cpp +++ b/src/NimBLECharacteristic.cpp @@ -3,7 +3,7 @@ * * Created: on March 3, 2020 * Author H2zero - * + * * BLECharacteristic.cpp * * Created on: Jun 22, 2017 @@ -12,6 +12,9 @@ #include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) +#include "nimconfig.h" +#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) + #include "NimBLECharacteristic.h" #include "NimBLE2902.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] 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) { } @@ -42,18 +45,18 @@ NimBLECharacteristic::NimBLECharacteristic(const char* uuid, uint16_t properties * @param [in] properties - Properties for the characteristic. */ NimBLECharacteristic::NimBLECharacteristic(const NimBLEUUID &uuid, uint16_t properties, NimBLEService* pService) { - m_uuid = uuid; - m_handle = NULL_HANDLE; - m_properties = properties; - m_pCallbacks = &defaultCallback; + m_uuid = uuid; + m_handle = NULL_HANDLE; + m_properties = properties; + m_pCallbacks = &defaultCallback; m_pService = pService; // Backward Compatibility - to be removed -/* setBroadcastProperty((properties & PROPERTY_BROADCAST) != 0); - setReadProperty((properties & PROPERTY_READ) != 0); - setWriteProperty((properties & PROPERTY_WRITE) != 0); - setNotifyProperty((properties & PROPERTY_NOTIFY) != 0); - setIndicateProperty((properties & PROPERTY_INDICATE) != 0); - setWriteNoResponseProperty((properties & PROPERTY_WRITE_NR) != 0); +/* setBroadcastProperty((properties & PROPERTY_BROADCAST) != 0); + setReadProperty((properties & PROPERTY_READ) != 0); + setWriteProperty((properties & PROPERTY_WRITE) != 0); + setNotifyProperty((properties & PROPERTY_NOTIFY) != 0); + setIndicateProperty((properties & PROPERTY_INDICATE) != 0); + setWriteNoResponseProperty((properties & PROPERTY_WRITE_NR) != 0); */ /////////////////////////////////////////// } // NimBLECharacteristic @@ -71,14 +74,14 @@ NimBLECharacteristic::~NimBLECharacteristic() { * @return N/A. */ void NimBLECharacteristic::addDescriptor(NimBLEDescriptor* pDescriptor) { - 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. - if (m_descriptorMap.getByUUID(pDescriptor->getUUID()) != nullptr) { - NIMBLE_LOGW(LOG_TAG, "<< Adding a new descriptor with the same UUID as a previous one"); - //return; - } - m_descriptorMap.setByUUID(pDescriptor->getUUID(), pDescriptor); - NIMBLE_LOGD(LOG_TAG, "<< addDescriptor()"); + 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. + if (m_descriptorMap.getByUUID(pDescriptor->getUUID()) != nullptr) { + NIMBLE_LOGW(LOG_TAG, "<< Adding a new descriptor with the same UUID as a previous one"); + //return; + } + m_descriptorMap.setByUUID(pDescriptor->getUUID(), pDescriptor); + NIMBLE_LOGD(LOG_TAG, "<< addDescriptor()"); } // addDescriptor @@ -89,7 +92,7 @@ void NimBLECharacteristic::addDescriptor(NimBLEDescriptor* pDescriptor) { * @return The new BLE descriptor. */ 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. */ NimBLEDescriptor* NimBLECharacteristic::createDescriptor(const NimBLEUUID &uuid, uint32_t properties, uint16_t max_len) { - NimBLEDescriptor* pDescriptor = nullptr; - if(uuid.equals(NimBLEUUID((uint16_t)0x2902))) { + NimBLEDescriptor* pDescriptor = nullptr; + if(uuid.equals(NimBLEUUID((uint16_t)0x2902))) { 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"); } @@ -112,15 +115,15 @@ NimBLEDescriptor* NimBLECharacteristic::createDescriptor(const NimBLEUUID &uuid, } else { return pDescriptor; } - - } else if (uuid.equals(NimBLEUUID((uint16_t)0x2904))) { - pDescriptor = new NimBLE2904(this); - - } else { - pDescriptor = new NimBLEDescriptor(uuid, properties, max_len, this); - } - addDescriptor(pDescriptor); - return pDescriptor; + + } else if (uuid.equals(NimBLEUUID((uint16_t)0x2904))) { + pDescriptor = new NimBLE2904(this); + + } else { + pDescriptor = new NimBLEDescriptor(uuid, properties, max_len, this); + } + addDescriptor(pDescriptor); + return pDescriptor; } // 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. */ NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(const char* descriptorUUID) { - return m_descriptorMap.getByUUID(NimBLEUUID(descriptorUUID)); + return m_descriptorMap.getByUUID(NimBLEUUID(descriptorUUID)); } // 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. */ NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(const NimBLEUUID &descriptorUUID) { - return m_descriptorMap.getByUUID(descriptorUUID); + return m_descriptorMap.getByUUID(descriptorUUID); } // getDescriptorByUUID @@ -149,17 +152,17 @@ NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(const NimBLEUUID &de * @return The handle of the characteristic. */ uint16_t NimBLECharacteristic::getHandle() { - return m_handle; + return m_handle; } // getHandle /* void NimBLECharacteristic::setAccessPermissions(uint16_t perm) { - m_permissions = perm; + m_permissions = perm; } */ uint8_t NimBLECharacteristic::getProperties() { - return m_properties; + return m_properties; } // getProperties @@ -167,7 +170,7 @@ uint8_t NimBLECharacteristic::getProperties() { * @brief Get the service associated with this characteristic. */ NimBLEService* NimBLECharacteristic::getService() { - return m_pService; + return m_pService; } // getService @@ -176,7 +179,7 @@ NimBLEService* NimBLECharacteristic::getService() { * @return The UUID of the characteristic. */ NimBLEUUID NimBLECharacteristic::getUUID() { - return m_uuid; + return m_uuid; } // getUUID @@ -185,7 +188,7 @@ NimBLEUUID NimBLECharacteristic::getUUID() { * @return A pointer to storage containing the current characteristic value. */ std::string NimBLECharacteristic::getValue() { - return m_value.getValue(); + return m_value.getValue(); } // getValue @@ -194,7 +197,7 @@ std::string NimBLECharacteristic::getValue() { * @return A pointer to storage containing the current characteristic data. */ uint8_t* NimBLECharacteristic::getData() { - return m_value.getData(); + return m_value.getData(); } // getData @@ -203,7 +206,7 @@ uint8_t* NimBLECharacteristic::getData() { * @return The length of the current characteristic data. */ 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, void *arg) { - const ble_uuid_t *uuid; + const ble_uuid_t *uuid; int rc; - NimBLECharacteristic* pCharacteristic = (NimBLECharacteristic*)arg; - - NIMBLE_LOGD(LOG_TAG, "Characteristic %s %s event", pCharacteristic->getUUID().toString().c_str(), + NimBLECharacteristic* pCharacteristic = (NimBLECharacteristic*)arg; + + NIMBLE_LOGD(LOG_TAG, "Characteristic %s %s event", pCharacteristic->getUUID().toString().c_str(), ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR ? "Read" : "Write"); - - uuid = ctxt->chr->uuid; - if(ble_uuid_cmp(uuid, &pCharacteristic->getUUID().getNative()->u) == 0){ + + uuid = ctxt->chr->uuid; + if(ble_uuid_cmp(uuid, &pCharacteristic->getUUID().getNative()->u) == 0){ switch(ctxt->op) { 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); - // 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. - if(ctxt->om->om_pkthdr_len > 8) { - pCharacteristic->m_pCallbacks->onRead(pCharacteristic); - } + // 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. + if(ctxt->om->om_pkthdr_len > 8) { + pCharacteristic->m_pCallbacks->onRead(pCharacteristic); + } rc = os_mbuf_append(ctxt->om, pCharacteristic->getData(), pCharacteristic->m_value.getLength()); return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; } - + 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); if (ctxt->om->om_len > BLE_ATT_ATTR_MAX_LEN) { return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } - + //pCharacteristic->setValue(ctxt->om->om_data, ctxt->om->om_len); - pCharacteristic->m_value.addPart(ctxt->om->om_data, ctxt->om->om_len); - os_mbuf *next; - next = SLIST_NEXT(ctxt->om, om_next); - while(next != NULL){ - //NIMBLE_LOGD(LOG_TAG, "Found long write data, len:%d", next->om_len); - pCharacteristic->m_value.addPart(next->om_data, next->om_len); - next = SLIST_NEXT(next, om_next); - } - pCharacteristic->m_value.commit(); + pCharacteristic->m_value.addPart(ctxt->om->om_data, ctxt->om->om_len); + os_mbuf *next; + next = SLIST_NEXT(ctxt->om, om_next); + while(next != NULL){ + //NIMBLE_LOGD(LOG_TAG, "Found long write data, len:%d", next->om_len); + pCharacteristic->m_value.addPart(next->om_data, next->om_len); + next = SLIST_NEXT(next, om_next); + } + pCharacteristic->m_value.commit(); pCharacteristic->m_pCallbacks->onWrite(pCharacteristic); return 0; @@ -255,11 +258,11 @@ int NimBLECharacteristic::handleGapEvent(uint16_t conn_handle, uint16_t attr_han default: break; } - } - + } + return BLE_ATT_ERR_UNLIKELY; } - + /** * @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) { subVal |= NIMBLE_DESC_FLAG_INDICATE; } - + m_semaphoreConfEvt.give((subVal | NIMBLE_DESC_FLAG_INDICATE) ? 0 : NimBLECharacteristicCallbacks::Status::ERROR_INDICATE_DISABLED); - + NIMBLE_LOGI(LOG_TAG, "New subscribe value for conn: %d val: %d", event->subscribe.conn_handle, subVal); - + NimBLE2902* p2902 = (NimBLE2902*)getDescriptorByUUID((uint16_t)0x2902); - if(p2902 == nullptr){ - ESP_LOGE(LOG_TAG, "No 2902 descriptor found for %s", getUUID().toString().c_str()); + if(p2902 == nullptr){ + ESP_LOGE(LOG_TAG, "No 2902 descriptor found for %s", getUUID().toString().c_str()); return; - } - + } + p2902->setNotifications(subVal & NIMBLE_DESC_FLAG_NOTIFY); p2902->setIndications(subVal & NIMBLE_DESC_FLAG_INDICATE); p2902->m_pCallbacks->onWrite(p2902); - - + + auto it = p2902->m_subscribedMap.find(event->subscribe.conn_handle); if(subVal > 0 && it == p2902->m_subscribedMap.cend()) { p2902->m_subscribedMap.insert(std::pair(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); return; } -/* +/* if(event->subscribe.reason == BLE_GAP_SUBSCRIBE_REASON_TERM) { p2902->m_subscribedMap.erase(event->subscribe.conn_handle); return; } -*/ +*/ (*it).second = subVal; } @@ -316,11 +319,11 @@ void NimBLECharacteristic::setSubscribe(struct ble_gap_event *event) { * @return N/A */ void NimBLECharacteristic::indicate() { - NIMBLE_LOGD(LOG_TAG, ">> indicate: length: %d", m_value.getValue().length()); - notify(false); - NIMBLE_LOGD(LOG_TAG, "<< indicate"); + NIMBLE_LOGD(LOG_TAG, ">> indicate: length: %d", m_value.getValue().length()); + notify(false); + NIMBLE_LOGD(LOG_TAG, "<< indicate"); } // indicate - + /** * @brief Send a notify. * 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. */ 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()->getServer() != nullptr); + assert(getService() != nullptr); + assert(getService()->getServer() != nullptr); if (getService()->getServer()->getConnectedCount() == 0) { - NIMBLE_LOGD(LOG_TAG, "<< notify: No connected clients."); - return; - } - + NIMBLE_LOGD(LOG_TAG, "<< notify: No connected clients."); + return; + } + m_pCallbacks->onNotify(this); - + int rc = 0; NimBLE2902* p2902 = (NimBLE2902*)getDescriptorByUUID((uint16_t)0x2902); - + for (auto it = p2902->m_subscribedMap.cbegin(); it != p2902->m_subscribedMap.cend(); ++it) { 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(); uint8_t* data = (uint8_t*)m_value.getValue().data(); os_mbuf *om; - + if(_mtu == 0) { //NIMBLE_LOGD(LOG_TAG, "peer not connected, removing from map"); p2902->m_subscribedMap.erase((*it).first); @@ -360,33 +363,33 @@ void NimBLECharacteristic::notify(bool is_notification) { } continue; } - + 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) { //NIMBLE_LOGI(LOG_TAG, "Skipping unsubscribed client"); continue; } - + 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"); is_notification = false; } - + if(!is_notification && (!((*it).second & NIMBLE_DESC_FLAG_INDICATE))) { NIMBLE_LOGW(LOG_TAG, "Sending indication to client subscribed to notifications, sending notifications instead"); is_notification = true; } - + // 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 also must create it in each loop iteration because it is consumed with each host call. om = ble_hs_mbuf_from_flat(data, length); - + if(!is_notification) { m_semaphoreConfEvt.take("indicate"); 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); return; } - + rc = m_semaphoreConfEvt.wait(); - + if(rc == BLE_HS_ETIMEOUT) { m_pCallbacks->onStatus(this, NimBLECharacteristicCallbacks::Status::ERROR_INDICATE_TIMEOUT, rc); } else if(rc == BLE_HS_EDONE) { @@ -410,12 +413,12 @@ void NimBLECharacteristic::notify(bool is_notification) { if(rc == 0) { m_pCallbacks->onStatus(this, NimBLECharacteristicCallbacks::Status::SUCCESS_NOTIFY, 0); } 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 @@ -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. */ void NimBLECharacteristic::setCallbacks(NimBLECharacteristicCallbacks* pCallbacks) { - if (pCallbacks != nullptr){ - m_pCallbacks = pCallbacks; - } else { - m_pCallbacks = &defaultCallback; - } + if (pCallbacks != nullptr){ + m_pCallbacks = pCallbacks; + } else { + m_pCallbacks = &defaultCallback; + } } // setCallbacks // Backward compatibility - to be removed //////////////////////////////// @@ -440,11 +443,11 @@ void NimBLECharacteristic::setCallbacks(NimBLECharacteristicCallbacks* pCallback * @return N/A */ void NimBLECharacteristic::setBroadcastProperty(bool value) { - if (value) { - m_properties = (m_properties | BLE_GATT_CHR_F_BROADCAST); - } else { - m_properties = (m_properties & ~BLE_GATT_CHR_F_BROADCAST); - } + if (value) { + m_properties = (m_properties | BLE_GATT_CHR_F_BROADCAST); + } else { + m_properties = (m_properties & ~BLE_GATT_CHR_F_BROADCAST); + } } // setBroadcastProperty @@ -453,11 +456,11 @@ void NimBLECharacteristic::setBroadcastProperty(bool value) { * @param [in] value Set to true if we are to allow indicate messages. */ void NimBLECharacteristic::setIndicateProperty(bool value) { - if (value) { - m_properties = (m_properties | BLE_GATT_CHR_F_INDICATE); - } else { - m_properties = (m_properties & ~BLE_GATT_CHR_F_INDICATE); - } + if (value) { + m_properties = (m_properties | BLE_GATT_CHR_F_INDICATE); + } else { + m_properties = (m_properties & ~BLE_GATT_CHR_F_INDICATE); + } } // setIndicateProperty @@ -466,11 +469,11 @@ void NimBLECharacteristic::setIndicateProperty(bool value) { * @param [in] value Set to true if we are to allow notification messages. */ void NimBLECharacteristic::setNotifyProperty(bool value) { - if (value) { - m_properties = (m_properties | BLE_GATT_CHR_F_NOTIFY); - } else { - m_properties = (m_properties & ~BLE_GATT_CHR_F_NOTIFY); - } + if (value) { + m_properties = (m_properties | BLE_GATT_CHR_F_NOTIFY); + } else { + m_properties = (m_properties & ~BLE_GATT_CHR_F_NOTIFY); + } } // setNotifyProperty @@ -479,11 +482,11 @@ void NimBLECharacteristic::setNotifyProperty(bool value) { * @param [in] value Set to true if we are to allow reads. */ void NimBLECharacteristic::setReadProperty(bool value) { - if (value) { - m_properties = (m_properties | BLE_GATT_CHR_F_READ); - } else { - m_properties = (m_properties & ~BLE_GATT_CHR_F_READ); - } + if (value) { + m_properties = (m_properties | BLE_GATT_CHR_F_READ); + } else { + m_properties = (m_properties & ~BLE_GATT_CHR_F_READ); + } } // 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. */ void NimBLECharacteristic::setWriteNoResponseProperty(bool value) { - if (value) { - m_properties = (m_properties | BLE_GATT_CHR_F_WRITE_NO_RSP); - } else { - m_properties = (m_properties & ~BLE_GATT_CHR_F_WRITE_NO_RSP); - } + if (value) { + m_properties = (m_properties | BLE_GATT_CHR_F_WRITE_NO_RSP); + } else { + m_properties = (m_properties & ~BLE_GATT_CHR_F_WRITE_NO_RSP); + } } // setWriteNoResponseProperty @@ -505,11 +508,11 @@ void NimBLECharacteristic::setWriteNoResponseProperty(bool value) { * @param [in] value Set to true if we are to allow writes. */ void NimBLECharacteristic::setWriteProperty(bool value) { - if (value) { - m_properties = (m_properties | BLE_GATT_CHR_F_WRITE ); - } else { - m_properties = (m_properties & ~BLE_GATT_CHR_F_WRITE ); - } + if (value) { + m_properties = (m_properties | BLE_GATT_CHR_F_WRITE ); + } else { + m_properties = (m_properties & ~BLE_GATT_CHR_F_WRITE ); + } } // setWriteProperty ////////////////////////////////////////////////////////////////////////////////// @@ -519,23 +522,23 @@ void NimBLECharacteristic::setWriteProperty(bool value) { * @param [in] length The length of the data in bytes. */ void NimBLECharacteristic::setValue(const uint8_t* data, size_t 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()); - free(pHex); + 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()); + 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) { //ble_gatts_chr_updated(m_handle); // ble_gattc_notify(getService()->getServer()->m_connId, m_handle); // } - - NIMBLE_LOGD(LOG_TAG, "<< setValue"); + + NIMBLE_LOGD(LOG_TAG, "<< setValue"); } // setValue @@ -547,42 +550,42 @@ void NimBLECharacteristic::setValue(const uint8_t* data, size_t length) { * @return N/A. */ void NimBLECharacteristic::setValue(const std::string &value) { - setValue((uint8_t*)(value.data()), value.length()); + setValue((uint8_t*)(value.data()), value.length()); } // setValue void NimBLECharacteristic::setValue(uint16_t& data16) { - uint8_t temp[2]; - temp[0] = data16; - temp[1] = data16 >> 8; - setValue(temp, 2); + uint8_t temp[2]; + temp[0] = data16; + temp[1] = data16 >> 8; + setValue(temp, 2); } // setValue void NimBLECharacteristic::setValue(uint32_t& data32) { - uint8_t temp[4]; - temp[0] = data32; - temp[1] = data32 >> 8; - temp[2] = data32 >> 16; - temp[3] = data32 >> 24; - setValue(temp, 4); + uint8_t temp[4]; + temp[0] = data32; + temp[1] = data32 >> 8; + temp[2] = data32 >> 16; + temp[3] = data32 >> 24; + setValue(temp, 4); } // setValue void NimBLECharacteristic::setValue(int& data32) { - uint8_t temp[4]; - temp[0] = data32; - temp[1] = data32 >> 8; - temp[2] = data32 >> 16; - temp[3] = data32 >> 24; - setValue(temp, 4); + uint8_t temp[4]; + temp[0] = data32; + temp[1] = data32 >> 8; + temp[2] = data32 >> 16; + temp[3] = data32 >> 24; + setValue(temp, 4); } // setValue void NimBLECharacteristic::setValue(float& data32) { - float temp = data32; - setValue((uint8_t*)&temp, 4); + float temp = data32; + setValue((uint8_t*)&temp, 4); } // setValue void NimBLECharacteristic::setValue(double& data64) { - double temp = data64; - setValue((uint8_t*)&temp, 8); + double temp = data64; + setValue((uint8_t*)&temp, 8); } // setValue @@ -591,18 +594,18 @@ void NimBLECharacteristic::setValue(double& data64) { * @return A string representation of the characteristic. */ std::string NimBLECharacteristic::toString() { - std::string res = "UUID: " + m_uuid.toString() + ", handle : 0x"; - char hex[5]; - snprintf(hex, sizeof(hex), "%04x", m_handle); - res += hex; - res += " "; - 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_NO_RSP) res += "WriteNoResponse "; - 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_INDICATE) res += "Indicate "; - return res; + std::string res = "UUID: " + m_uuid.toString() + ", handle : 0x"; + char hex[5]; + snprintf(hex, sizeof(hex), "%04x", m_handle); + res += hex; + res += " "; + 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_NO_RSP) res += "WriteNoResponse "; + 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_INDICATE) res += "Indicate "; + return res; } // toString @@ -614,7 +617,7 @@ NimBLECharacteristicCallbacks::~NimBLECharacteristicCallbacks() {} * @param [in] pCharacteristic The characteristic that is the source of the event. */ void NimBLECharacteristicCallbacks::onRead(NimBLECharacteristic* pCharacteristic) { - NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onRead: default"); + NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onRead: default"); } // onRead @@ -623,7 +626,7 @@ void NimBLECharacteristicCallbacks::onRead(NimBLECharacteristic* pCharacteristic * @param [in] pCharacteristic The characteristic that is the source of the event. */ void NimBLECharacteristicCallbacks::onWrite(NimBLECharacteristic* pCharacteristic) { - NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onWrite: default"); + NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onWrite: default"); } // onWrite @@ -632,7 +635,7 @@ void NimBLECharacteristicCallbacks::onWrite(NimBLECharacteristic* pCharacteristi * @param [in] pCharacteristic The characteristic that is the source of the event. */ void NimBLECharacteristicCallbacks::onNotify(NimBLECharacteristic* pCharacteristic) { - NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onNotify: default"); + NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onNotify: default"); } // onNotify @@ -643,7 +646,8 @@ void NimBLECharacteristicCallbacks::onNotify(NimBLECharacteristic* pCharacterist * @param [in] code Additional code of underlying errors */ void NimBLECharacteristicCallbacks::onStatus(NimBLECharacteristic* pCharacteristic, Status s, int code) { - NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onStatus: default"); + NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onStatus: default"); } // onStatus +#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #endif /* CONFIG_BT_ENABLED */ diff --git a/src/NimBLECharacteristic.h b/src/NimBLECharacteristic.h index 1793203..25e1ec7 100644 --- a/src/NimBLECharacteristic.h +++ b/src/NimBLECharacteristic.h @@ -3,7 +3,7 @@ * * Created: on March 3, 2020 * Author H2zero - * + * * Originally: * BLECharacteristic.h * @@ -16,6 +16,9 @@ #include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) +#include "nimconfig.h" +#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) + #include "host/ble_hs.h" /**** FIX COMPILATION ****/ #undef min @@ -23,10 +26,10 @@ /**************************/ typedef enum { - READ = BLE_GATT_CHR_F_READ, + READ = BLE_GATT_CHR_F_READ, READ_ENC = BLE_GATT_CHR_F_READ_ENC, 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_NR = BLE_GATT_CHR_F_WRITE_NO_RSP, WRITE_ENC = BLE_GATT_CHR_F_WRITE_ENC, @@ -57,21 +60,21 @@ class NimBLECharacteristicCallbacks; */ class NimBLEDescriptorMap { public: - void setByUUID(const char* uuid, NimBLEDescriptor* pDescriptor); - void setByUUID(const NimBLEUUID &uuid, NimBLEDescriptor* pDescriptor); -// void setByHandle(uint16_t handle, NimBLEDescriptor* pDescriptor); - NimBLEDescriptor* getByUUID(const char* uuid); - NimBLEDescriptor* getByUUID(const NimBLEUUID &uuid); -// NimBLEDescriptor* getByHandle(uint16_t handle); - std::string toString(); - NimBLEDescriptor* getFirst(); - NimBLEDescriptor* getNext(); + void setByUUID(const char* uuid, NimBLEDescriptor* pDescriptor); + void setByUUID(const NimBLEUUID &uuid, NimBLEDescriptor* pDescriptor); +// void setByHandle(uint16_t handle, NimBLEDescriptor* pDescriptor); + NimBLEDescriptor* getByUUID(const char* uuid); + NimBLEDescriptor* getByUUID(const NimBLEUUID &uuid); +// NimBLEDescriptor* getByHandle(uint16_t handle); + std::string toString(); + NimBLEDescriptor* getFirst(); + NimBLEDescriptor* getNext(); uint8_t getSize(); - + private: - std::map m_uuidMap; -// std::map m_handleMap; - std::map::iterator m_iterator; + std::map m_uuidMap; +// std::map m_handleMap; + std::map::iterator m_iterator; }; @@ -83,85 +86,85 @@ private: */ class NimBLECharacteristic { public: - NimBLEDescriptor* createDescriptor(const char* uuid, - uint32_t properties = NIMBLE_PROPERTY::READ | - NIMBLE_PROPERTY::WRITE, + NimBLEDescriptor* createDescriptor(const char* uuid, + uint32_t properties = NIMBLE_PROPERTY::READ | + NIMBLE_PROPERTY::WRITE, uint16_t max_len = 100); - NimBLEDescriptor* createDescriptor(const NimBLEUUID &uuid, - uint32_t properties = NIMBLE_PROPERTY::READ | - NIMBLE_PROPERTY::WRITE, + NimBLEDescriptor* createDescriptor(const NimBLEUUID &uuid, + uint32_t properties = NIMBLE_PROPERTY::READ | + NIMBLE_PROPERTY::WRITE, 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(); - void notify(bool is_notification = true); - void setCallbacks(NimBLECharacteristicCallbacks* pCallbacks); + NimBLEDescriptor* getDescriptorByUUID(const char* descriptorUUID); + NimBLEDescriptor* getDescriptorByUUID(const NimBLEUUID &descriptorUUID); + 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 void setBroadcastProperty(bool value); - void setIndicateProperty(bool value); - void setNotifyProperty(bool value); - void setReadProperty(bool value); + void setIndicateProperty(bool value); + void setNotifyProperty(bool value); + void setReadProperty(bool value); void setWriteProperty(bool value); - void setWriteNoResponseProperty(bool value); -////////////////////////////////////////////////////// - void setValue(const uint8_t* data, size_t size); - void setValue(const std::string &value); - void setValue(uint16_t& data16); - void setValue(uint32_t& data32); - void setValue(int& data32); - void setValue(float& data32); - void setValue(double& data64); + void setWriteNoResponseProperty(bool value); +////////////////////////////////////////////////////// + void setValue(const uint8_t* data, size_t size); + void setValue(const std::string &value); + void setValue(uint16_t& data16); + void setValue(uint32_t& data32); + void setValue(int& data32); + void setValue(float& data32); + void setValue(double& data64); - std::string toString(); - uint16_t getHandle(); -// void setAccessPermissions(uint16_t perm); + std::string toString(); + uint16_t getHandle(); +// void setAccessPermissions(uint16_t perm); // Backward Compatibility - to be removed -/* static const uint32_t PROPERTY_READ = 1<<0; - static const uint32_t PROPERTY_WRITE = 1<<1; - static const uint32_t PROPERTY_NOTIFY = 1<<2; - static const uint32_t PROPERTY_BROADCAST = 1<<3; - static const uint32_t PROPERTY_INDICATE = 1<<4; - static const uint32_t PROPERTY_WRITE_NR = 1<<5; +/* static const uint32_t PROPERTY_READ = 1<<0; + static const uint32_t PROPERTY_WRITE = 1<<1; + static const uint32_t PROPERTY_NOTIFY = 1<<2; + static const uint32_t PROPERTY_BROADCAST = 1<<3; + static const uint32_t PROPERTY_INDICATE = 1<<4; + static const uint32_t PROPERTY_WRITE_NR = 1<<5; */ ////////////////////////////////////////////////////// - + private: - friend class NimBLEServer; - friend class NimBLEService; -// friend class NimBLEDescriptor; -// friend class NimBLECharacteristicMap; + friend class NimBLEServer; + friend class NimBLEService; +// friend class NimBLEDescriptor; +// friend class NimBLECharacteristicMap; - NimBLECharacteristic(const char* uuid, uint16_t properties = NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE, - NimBLEService* pService = nullptr); - NimBLECharacteristic(const NimBLEUUID &uuid, uint16_t properties = NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE, - NimBLEService* pService = nullptr); - virtual ~NimBLECharacteristic(); + NimBLECharacteristic(const char* uuid, uint16_t properties = NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE, + NimBLEService* pService = nullptr); + NimBLECharacteristic(const NimBLEUUID &uuid, uint16_t properties = NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE, + NimBLEService* pService = nullptr); + virtual ~NimBLECharacteristic(); - NimBLEUUID m_uuid; - NimBLEDescriptorMap m_descriptorMap; - uint16_t m_handle; - uint16_t m_properties; - NimBLECharacteristicCallbacks* m_pCallbacks; - NimBLEService* m_pService; - NimBLEValue m_value; -// uint16_t m_permissions; - - void addDescriptor(NimBLEDescriptor* pDescriptor); + NimBLEUUID m_uuid; + NimBLEDescriptorMap m_descriptorMap; + uint16_t m_handle; + uint16_t m_properties; + NimBLECharacteristicCallbacks* m_pCallbacks; + NimBLEService* m_pService; + NimBLEValue m_value; +// uint16_t m_permissions; + + void addDescriptor(NimBLEDescriptor* pDescriptor); NimBLEService* getService(); uint8_t getProperties(); 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); - FreeRTOS::Semaphore m_semaphoreConfEvt = FreeRTOS::Semaphore("ConfEvt"); + FreeRTOS::Semaphore m_semaphoreConfEvt = FreeRTOS::Semaphore("ConfEvt"); }; // NimBLECharacteristic @@ -175,21 +178,23 @@ private: class NimBLECharacteristicCallbacks { public: typedef enum { - SUCCESS_INDICATE, - SUCCESS_NOTIFY, - ERROR_INDICATE_DISABLED, - ERROR_NOTIFY_DISABLED, - ERROR_GATT, - ERROR_NO_CLIENT, - ERROR_INDICATE_TIMEOUT, - ERROR_INDICATE_FAILURE - }Status; - - virtual ~NimBLECharacteristicCallbacks(); - virtual void onRead(NimBLECharacteristic* pCharacteristic); - virtual void onWrite(NimBLECharacteristic* pCharacteristic); + SUCCESS_INDICATE, + SUCCESS_NOTIFY, + ERROR_INDICATE_DISABLED, + ERROR_NOTIFY_DISABLED, + ERROR_GATT, + ERROR_NO_CLIENT, + ERROR_INDICATE_TIMEOUT, + ERROR_INDICATE_FAILURE + }Status; + + virtual ~NimBLECharacteristicCallbacks(); + virtual void onRead(NimBLECharacteristic* pCharacteristic); + virtual void onWrite(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 /*MAIN_NIMBLECHARACTERISTIC_H_*/ diff --git a/src/NimBLECharacteristicMap.cpp b/src/NimBLECharacteristicMap.cpp index f566d53..b3cdcf9 100644 --- a/src/NimBLECharacteristicMap.cpp +++ b/src/NimBLECharacteristicMap.cpp @@ -12,6 +12,9 @@ #include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) +#include "nimconfig.h" +#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) + #include "NimBLEService.h" #include "NimBLELog.h" @@ -20,9 +23,9 @@ * @brief Return the characteristic by handle. * @param [in] handle The handle to look up the characteristic. * @return The characteristic. - */ + */ NimBLECharacteristic* NimBLECharacteristicMap::getByHandle(uint16_t handle) { - return m_handleMap.at(handle); + return m_handleMap.at(handle); } // getByHandle @@ -42,20 +45,20 @@ NimBLECharacteristic* NimBLECharacteristicMap::getByUUID(const char* uuid) { * @return The characteristic. */ NimBLECharacteristic* NimBLECharacteristicMap::getByUUID(const NimBLEUUID &uuid) { - for (auto &myPair : m_uuidMap) { - if (myPair.first->getUUID().equals(uuid)) { - return myPair.first; - } - } + for (auto &myPair : m_uuidMap) { + if (myPair.first->getUUID().equals(uuid)) { + return myPair.first; + } + } - return nullptr; + return nullptr; } // getByUUID /** * @brief Get the number of characteristics in the map. */ uint8_t NimBLECharacteristicMap::getSize() { - return (uint8_t)m_uuidMap.size(); + return (uint8_t)m_uuidMap.size(); } // getSize /** @@ -63,11 +66,11 @@ uint8_t NimBLECharacteristicMap::getSize() { * @return The first characteristic in the map. */ NimBLECharacteristic* NimBLECharacteristicMap::getFirst() { - m_iterator = m_uuidMap.begin(); - if (m_iterator == m_uuidMap.end()) return nullptr; - NimBLECharacteristic* pRet = m_iterator->first; - m_iterator++; - return pRet; + m_iterator = m_uuidMap.begin(); + if (m_iterator == m_uuidMap.end()) return nullptr; + NimBLECharacteristic* pRet = m_iterator->first; + m_iterator++; + return pRet; } // getFirst @@ -76,10 +79,10 @@ NimBLECharacteristic* NimBLECharacteristicMap::getFirst() { * @return The next characteristic in the map. */ NimBLECharacteristic* NimBLECharacteristicMap::getNext() { - if (m_iterator == m_uuidMap.end()) return nullptr; - NimBLECharacteristic* pRet = m_iterator->first; - m_iterator++; - return pRet; + if (m_iterator == m_uuidMap.end()) return nullptr; + NimBLECharacteristic* pRet = m_iterator->first; + m_iterator++; + return pRet; } // getNext @@ -90,7 +93,7 @@ NimBLECharacteristic* NimBLECharacteristicMap::getNext() { * @return N/A. */ void NimBLECharacteristicMap::setByHandle(uint16_t handle, NimBLECharacteristic* characteristic) { - m_handleMap.insert(std::pair(handle, characteristic)); + m_handleMap.insert(std::pair(handle, characteristic)); } // setByHandle @@ -101,7 +104,7 @@ void NimBLECharacteristicMap::setByHandle(uint16_t handle, NimBLECharacteristic* * @return N/A. */ void NimBLECharacteristicMap::setByUUID(NimBLECharacteristic* pCharacteristic, const NimBLEUUID &uuid) { - m_uuidMap.insert(std::pair(pCharacteristic, uuid.toString())); + m_uuidMap.insert(std::pair(pCharacteristic, uuid.toString())); } // setByUUID @@ -110,19 +113,20 @@ void NimBLECharacteristicMap::setByUUID(NimBLECharacteristic* pCharacteristic, c * @return A string representation of the characteristic map. */ std::string NimBLECharacteristicMap::toString() { - std::string res; - int count = 0; - char hex[5]; - for (auto &myPair: m_uuidMap) { - if (count > 0) {res += "\n";} - snprintf(hex, sizeof(hex), "%04x", myPair.first->getHandle()); - count++; - res += "handle: 0x"; - res += hex; - res += ", uuid: " + myPair.first->getUUID().toString(); - } - return res; + std::string res; + int count = 0; + char hex[5]; + for (auto &myPair: m_uuidMap) { + if (count > 0) {res += "\n";} + snprintf(hex, sizeof(hex), "%04x", myPair.first->getHandle()); + count++; + res += "handle: 0x"; + res += hex; + res += ", uuid: " + myPair.first->getUUID().toString(); + } + return res; } // toString +#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #endif /* CONFIG_BT_ENABLED */ diff --git a/src/NimBLEClient.cpp b/src/NimBLEClient.cpp index 8cd5660..9e24298 100644 --- a/src/NimBLEClient.cpp +++ b/src/NimBLEClient.cpp @@ -3,17 +3,20 @@ * * Created: on Jan 26 2020 * Author H2zero - * + * * Originally: * BLEClient.cpp * * Created on: Mar 22, 2017 * Author: kolban */ - + #include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) +#include "nimconfig.h" +#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) + #include "NimBLEClient.h" #include "NimBLEUtils.h" #include "NimBLEDevice.h" @@ -52,16 +55,16 @@ NimBLEClient::NimBLEClient() m_conn_id = BLE_HS_CONN_HANDLE_NONE; m_haveServices = false; m_isConnected = false; - m_connectTimeout = 30000; - - m_pConnParams.scan_itvl = 16; // Scan interval in 0.625ms units (NimBLE Default) + m_connectTimeout = 30000; + + 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.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.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.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.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.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 @@ -69,11 +72,11 @@ NimBLEClient::NimBLEClient() * @brief Destructor, private - only callable by NimBLEDevice::deleteClient * to ensure proper disconnect and removal from device list. */ -NimBLEClient::~NimBLEClient() { - // We may have allocated service references associated with this client. +NimBLEClient::~NimBLEClient() { + // We may have allocated service references associated with this client. // Before we are finished with the client, we must release resources. clearServices(); - + if(m_deleteCallbacks && m_pClientCallbacks != &defaultCallbacks) { delete m_pClientCallbacks; } @@ -101,10 +104,10 @@ void NimBLEClient::clearServices() { */ /* void NimBLEClient::onHostReset() { - + } - */ - + */ + /** * 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) { NIMBLE_LOGD(LOG_TAG, ">> connect(%s)", address.toString().c_str()); - + if(!NimBLEDevice::m_synced) { NIMBLE_LOGC(LOG_TAG, "Host reset, wait for sync."); return false; } - + if(ble_gap_conn_active()) { NIMBLE_LOGE(LOG_TAG, "Connection in progress - must wait."); return false; @@ -135,15 +138,15 @@ bool NimBLEClient::connect(const NimBLEAddress &address, uint8_t type, bool refr int rc = 0; m_peerAddress = address; - + ble_addr_t peerAddrt; memcpy(&peerAddrt.val, address.getNative(),6); peerAddrt.type = type; - + m_semaphoreOpenEvt.take("connect"); - + /** 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. */ do{ @@ -153,21 +156,21 @@ bool NimBLEClient::connect(const NimBLEAddress &address, uint8_t type, bool refr vTaskDelay(1); } }while(rc == BLE_HS_EBUSY); - + if (rc != 0 && rc != BLE_HS_EDONE) { NIMBLE_LOGE(LOG_TAG, "Error: Failed to connect to device; addr_type=%d " "addr=%s, rc=%d; %s", - type, + type, m_peerAddress.toString().c_str(), rc, NimBLEUtils::returnCodeToString(rc)); - + m_semaphoreOpenEvt.give(); m_waitingToConnect = false; return false; } - + m_waitingToConnect = true; - + rc = m_semaphoreOpenEvt.wait("connect"); // Wait for the connection to complete. 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()); clearServices(); } - + if (!m_haveServices) { if (!retrieveServices()) { // 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()"); return true; } // connect @@ -204,23 +207,23 @@ bool NimBLEClient::connect(const NimBLEAddress &address, uint8_t type, bool refr * @return True on success. */ bool NimBLEClient::secureConnection() { - + m_semeaphoreSecEvt.take("secureConnection"); - + int rc = NimBLEDevice::startSecurity(m_conn_id); if(rc != 0){ m_semeaphoreSecEvt.give(); return false; } - + rc = m_semeaphoreSecEvt.wait("secureConnection"); if(rc != 0){ return false; } - + return true; } - + /** * @brief Disconnect from the peer. @@ -240,7 +243,7 @@ int NimBLEClient::disconnect(uint8_t reason) { // the device can be found again. NimBLEDevice::removeIgnored(m_peerAddress); } - + NIMBLE_LOGD(LOG_TAG, "<< disconnect()"); return rc; } // disconnect @@ -250,23 +253,23 @@ int NimBLEClient::disconnect(uint8_t reason) { * @brief Set the connection paramaters to use when connecting to a server. */ 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 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.itvl_min = minInterval; // min_int = 0x10*1.25ms = 20ms - 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.supervision_timeout = timeout; // timeout = 400*10ms = 4000ms - - // These are not used by NimBLE at this time - Must leave at defaults + m_pConnParams.itvl_min = minInterval; // min_int = 0x10*1.25ms = 20ms + 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.supervision_timeout = timeout; // timeout = 400*10ms = 4000ms + + // 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->max_ce_len = maxConnTime; // Maximum length of connection event in 0.625ms units - - int rc = NimBLEUtils::checkConnParams(&m_pConnParams); + //m_pConnParams->max_ce_len = maxConnTime; // Maximum length of connection event in 0.625ms units + + int rc = NimBLEUtils::checkConnParams(&m_pConnParams); 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 */ -void NimBLEClient::updateConnParams(uint16_t minInterval, uint16_t maxInterval, +void NimBLEClient::updateConnParams(uint16_t minInterval, uint16_t maxInterval, uint16_t latency, uint16_t timeout) -{ - ble_gap_upd_params params; +{ + ble_gap_upd_params params; - params.latency = latency; - params.itvl_max = maxInterval; - params.itvl_min = minInterval; - params.supervision_timeout = timeout; - // These are not used by NimBLE at this time - Must leave at defaults + params.latency = latency; + params.itvl_max = maxInterval; + params.itvl_min = minInterval; + params.supervision_timeout = timeout; + // 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.max_ce_len = BLE_GAP_INITIAL_CONN_MAX_CE_LEN; - + int rc = ble_gap_update_params(m_conn_id, ¶ms); if(rc != 0) { NIMBLE_LOGE(LOG_TAG, "Update params error: %d, %s", rc, NimBLEUtils::returnCodeToString(rc)); - } + } } @@ -331,15 +334,15 @@ int NimBLEClient::getRssi() { NIMBLE_LOGE(LOG_TAG, "<< getRssi(): Not connected"); return 0; } - + int8_t rssiValue = 0; int rc = ble_gap_conn_rssi(m_conn_id, &rssiValue); 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)); return 0; } - + return rssiValue; } // 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()); return myPair.second; } - } + } NIMBLE_LOGD(LOG_TAG, "<< getService: not found"); return nullptr; } // getService @@ -379,7 +382,7 @@ NimBLERemoteService* NimBLEClient::getService(const NimBLEUUID &uuid) { /** * @Get a pointer to the map of found services. - */ + */ std::map* NimBLEClient::getServices() { return &m_servicesMap; } @@ -391,7 +394,7 @@ std::map* NimBLEClient::getServices() { * services and wait until we have received them all. * We then ask for the characteristics for each service found and their desciptors. * @return true on success otherwise false if an error occurred - */ + */ bool NimBLEClient::retrieveServices() { /** * 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 * peer BLE partner to be returned in the callback function provided. */ - + NIMBLE_LOGD(LOG_TAG, ">> retrieveServices"); - + if(!m_isConnected){ NIMBLE_LOGE(LOG_TAG, "Disconnected, could not retrieve services -aborting"); return false; } m_semaphoreSearchCmplEvt.take("retrieveServices"); - + int rc = ble_gattc_disc_all_svcs(m_conn_id, NimBLEClient::serviceDiscoveredCB, this); - + if (rc != 0) { NIMBLE_LOGE(LOG_TAG, "ble_gattc_disc_all_svcs: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc)); m_haveServices = false; m_semaphoreSearchCmplEvt.give(); return false; } - + // wait until we have all the services // If sucessful, remember that we now have services. m_haveServices = (m_semaphoreSearchCmplEvt.wait("retrieveServices") == 0); @@ -428,7 +431,7 @@ bool NimBLEClient::retrieveServices() { return false; } } - + NIMBLE_LOGD(LOG_TAG, "<< retrieveServices"); 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 * the API will call this and report findings. */ int NimBLEClient::serviceDiscoveredCB( - uint16_t conn_handle, + uint16_t conn_handle, 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); NimBLEClient *peer = (NimBLEClient*)arg; @@ -466,7 +469,7 @@ int NimBLEClient::serviceDiscoveredCB( break; } case BLE_HS_EDONE:{ - // All services discovered; start discovering characteristics. + // All services discovered; start discovering characteristics. //NIMBLE_LOGD(LOG_TAG,"Giving search semaphore - completed"); peer->m_semaphoreSearchCmplEvt.give(0); @@ -481,7 +484,7 @@ int NimBLEClient::serviceDiscoveredCB( if (rc != 0) { // 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); return rc; @@ -496,10 +499,10 @@ int NimBLEClient::serviceDiscoveredCB( */ 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()); - + std::string ret = ""; NimBLERemoteService* pService = getService(serviceUUID); - + if(pService != nullptr) { NimBLERemoteCharacteristic* pChar = pService->getCharacteristic(characteristicUUID); 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) { NIMBLE_LOGD(LOG_TAG, ">> setValue: serviceUUID: %s, characteristicUUID: %s", serviceUUID.toString().c_str(), characteristicUUID.toString().c_str()); - + bool ret = false; NimBLERemoteService* pService = getService(serviceUUID); - + if(pService != nullptr) { NimBLERemoteCharacteristic* pChar = pService->getCharacteristic(characteristicUUID); if(pChar != nullptr) { ret = pChar->writeValue(value); } } - + NIMBLE_LOGD(LOG_TAG, "<< setValue"); return ret; } // setValue @@ -552,8 +555,8 @@ uint16_t NimBLEClient::getMTU() { * @param [in] arg = pointer to the client instance */ /*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_hs_adv_fields fields; int rc; @@ -566,22 +569,22 @@ uint16_t NimBLEClient::getMTU() { case BLE_GAP_EVENT_DISCONNECT: { if(!client->m_isConnected) return 0; - + if(client->m_conn_id != event->disconnect.conn.conn_handle) return 0; - + client->m_isConnected = false; client->m_waitingToConnect=false; // Remove the device from ignore list so we will scan it again NimBLEDevice::removeIgnored(client->m_peerAddress); - + NIMBLE_LOGI(LOG_TAG, "disconnect; reason=%d, %s", event->disconnect.reason, NimBLEUtils::returnCodeToString(event->disconnect.reason)); //print_conn_desc(&event->disconnect.conn); //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. switch(event->disconnect.reason) { 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); NimBLEDevice::onReset(event->disconnect.reason); break; - default: + default: break; } - + //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_semaphoreSearchCmplEvt.give(1); client->m_semeaphoreSecEvt.give(1); - + client->m_pClientCallbacks->onDisconnect(client); - + return 0; } // BLE_GAP_EVENT_DISCONNECT @@ -611,26 +614,26 @@ uint16_t NimBLEClient::getMTU() { if(!client->m_waitingToConnect) return 0; - + //if(client->m_conn_id != BLE_HS_CONN_HANDLE_NONE) // return 0; - + client->m_waitingToConnect=false; - + if (event->connect.status == 0) { client->m_isConnected = true; - + NIMBLE_LOGD(LOG_TAG, "Connection established"); - + client->m_conn_id = event->connect.conn_handle; - + // rc = ble_gap_conn_find(event->connect.conn_handle, &desc); // assert(rc == 0); // print_conn_desc(&desc); // 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 NimBLEDevice::addIgnored(client->m_peerAddress); @@ -638,9 +641,9 @@ uint16_t NimBLEClient::getMTU() { if(rc != 0) { NIMBLE_LOGE(LOG_TAG, "ble_gattc_exchange_mtu: rc=%d %s",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); - } + } } else { // Connection attempt failed NIMBLE_LOGE(LOG_TAG, "Error: Connection failed; status=%d %s", @@ -654,11 +657,11 @@ uint16_t NimBLEClient::getMTU() { case BLE_GAP_EVENT_NOTIFY_RX: { if(client->m_conn_id != event->notify_rx.conn_handle) return 0; - + NIMBLE_LOGD(LOG_TAG, "Notify Recieved for handle: %d",event->notify_rx.attr_handle); if(!client->m_haveServices) return 0; - + for(auto &sPair : client->m_servicesMap){ // Dont waste cycles searching services without this handle in their range 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); if(characteristic != cMap->end()) { NIMBLE_LOGD(LOG_TAG, "Got Notification for characteristic %s", characteristic->second->toString().c_str()); - + if (characteristic->second->m_notifyCallback != nullptr) { 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); } - + break; } } - + return 0; } // 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: { if(client->m_conn_id != event->conn_update_req.conn_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, event->conn_update_req.peer_params) ? 0 : BLE_ERR_CONN_PARMS; - + if(!rc && event->type == BLE_GAP_EVENT_CONN_UPDATE_REQ ) { 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"); return rc; } // BLE_GAP_EVENT_CONN_UPDATE_REQ, BLE_GAP_EVENT_L2CAP_UPDATE_REQ - + case BLE_GAP_EVENT_CONN_UPDATE: { if(client->m_conn_id != event->conn_update.conn_handle){ return 0; //BLE_HS_ENOTCONN BLE_ATT_ERR_INVALID_HANDLE @@ -720,28 +723,28 @@ uint16_t NimBLEClient::getMTU() { } return 0; } // BLE_GAP_EVENT_CONN_UPDATE - + case BLE_GAP_EVENT_ENC_CHANGE: { if(client->m_conn_id != event->enc_change.conn_handle){ return 0; //BLE_HS_ENOTCONN BLE_ATT_ERR_INVALID_HANDLE } - + if(event->enc_change.status == 0) { struct ble_gap_conn_desc desc; rc = ble_gap_conn_find(event->conn_update.conn_handle, &desc); assert(rc == 0); - + if(NimBLEDevice::m_securityCallbacks != nullptr) { NimBLEDevice::m_securityCallbacks->onAuthenticationComplete(&desc); } else { client->m_pClientCallbacks->onAuthenticationComplete(&desc); } } - + client->m_semeaphoreSecEvt.give(event->enc_change.status); return 0; } //BLE_GAP_EVENT_ENC_CHANGE - + case BLE_GAP_EVENT_MTU: { if(client->m_conn_id != event->mtu.conn_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", event->mtu.conn_handle, event->mtu.value); - client->m_semaphoreOpenEvt.give(0); + client->m_semaphoreOpenEvt.give(0); //client->m_mtu = event->mtu.value; return 0; } // BLE_GAP_EVENT_MTU - + case BLE_GAP_EVENT_PASSKEY_ACTION: { 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; 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 rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey); NIMBLE_LOGD(LOG_TAG, "ble_sm_inject_io result: %d", rc); - + } else if (event->passkey.params.action == BLE_SM_IOACT_NUMCMP) { NIMBLE_LOGD(LOG_TAG, "Passkey on device's display: %d", event->passkey.params.numcmp); pkey.action = event->passkey.params.action; @@ -779,8 +782,8 @@ uint16_t NimBLEClient::getMTU() { rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey); 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) { static uint8_t tem_oob[16] = {0}; pkey.action = event->passkey.params.action; @@ -789,11 +792,11 @@ uint16_t NimBLEClient::getMTU() { } rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey); NIMBLE_LOGD(LOG_TAG, "ble_sm_inject_io result: %d", rc); - //////// + //////// } else if (event->passkey.params.action == BLE_SM_IOACT_INPUT) { NIMBLE_LOGD(LOG_TAG, "Enter the passkey"); pkey.action = event->passkey.params.action; - + // Compatibility only - Do not use, should be removed the in future if(NimBLEDevice::m_securityCallbacks != nullptr) { pkey.passkey = NimBLEDevice::m_securityCallbacks->onPassKeyRequest(); @@ -804,14 +807,14 @@ uint16_t NimBLEClient::getMTU() { rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey); NIMBLE_LOGD(LOG_TAG, "ble_sm_inject_io result: %d", rc); - + } else if (event->passkey.params.action == BLE_SM_IOACT_NONE) { NIMBLE_LOGD(LOG_TAG, "No passkey action required"); } return 0; } // BLE_GAP_EVENT_PASSKEY_ACTION - + default: { return 0; } @@ -833,10 +836,10 @@ bool NimBLEClient::isConnected() { */ void NimBLEClient::setClientCallbacks(NimBLEClientCallbacks* pClientCallbacks, bool deleteCallbacks) { if (pClientCallbacks != nullptr){ - m_pClientCallbacks = pClientCallbacks; - } else { - m_pClientCallbacks = &defaultCallbacks; - } + m_pClientCallbacks = pClientCallbacks; + } else { + m_pClientCallbacks = &defaultCallbacks; + } m_deleteCallbacks = deleteCallbacks; } // setClientCallbacks @@ -865,7 +868,7 @@ void NimBLEClientCallbacks::onDisconnect(NimBLEClient* pClient) { } bool NimBLEClientCallbacks::onConnParamsUpdateRequest(NimBLEClient* pClient, const ble_gap_upd_params* params) { - NIMBLE_LOGD("NimBLEClientCallbacks", "onConnParamsUpdateRequest: default"); + NIMBLE_LOGD("NimBLEClientCallbacks", "onConnParamsUpdateRequest: default"); return true; } @@ -890,4 +893,5 @@ bool NimBLEClientCallbacks::onConfirmPIN(uint32_t pin){ return true; } +#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) #endif // CONFIG_BT_ENABLED diff --git a/src/NimBLEClient.h b/src/NimBLEClient.h index 1a39581..b140d95 100644 --- a/src/NimBLEClient.h +++ b/src/NimBLEClient.h @@ -3,7 +3,7 @@ * * Created: on Jan 26 2020 * Author H2zero - * + * * Originally: * BLEClient.h * @@ -14,8 +14,11 @@ #ifndef MAIN_NIMBLECLIENT_H_ #define MAIN_NIMBLECLIENT_H_ -#if defined(CONFIG_BT_ENABLED) #include "sdkconfig.h" +#if defined(CONFIG_BT_ENABLED) + +#include "nimconfig.h" +#if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) #include "NimBLEAddress.h" #include "NimBLEAdvertisedDevice.h" @@ -50,13 +53,13 @@ public: uint16_t getMTU(); bool secureConnection(); void setConnectTimeout(uint8_t timeout); - void setConnectionParams(uint16_t minInterval, uint16_t maxInterval, - uint16_t latency, uint16_t timeout, + void setConnectionParams(uint16_t minInterval, uint16_t maxInterval, + uint16_t latency, uint16_t timeout, uint16_t scanInterval=16, uint16_t scanWindow=16); // NimBLE default scan settings - void updateConnParams(uint16_t minInterval, uint16_t maxInterval, - uint16_t latency, uint16_t timeout); - - + void updateConnParams(uint16_t minInterval, uint16_t maxInterval, + uint16_t latency, uint16_t timeout); + + private: NimBLEClient(); ~NimBLEClient(); @@ -75,7 +78,7 @@ private: bool m_isConnected = false; // Are we currently connected. bool m_waitingToConnect =false; bool m_deleteCallbacks = true; - int32_t m_connectTimeout; + int32_t m_connectTimeout; //uint16_t m_mtu = 23; NimBLEClientCallbacks* m_pClientCallbacks = nullptr; @@ -85,12 +88,12 @@ private: FreeRTOS::Semaphore m_semeaphoreSecEvt = FreeRTOS::Semaphore("Security"); std::map m_servicesMap; - + private: friend class NimBLEClientCallbacks; ble_gap_conn_params m_pConnParams; -}; // class NimBLEClient +}; // class NimBLEClient /** @@ -109,5 +112,6 @@ public: virtual bool onConfirmPIN(uint32_t pin); }; +#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) #endif // CONFIG_BT_ENABLED #endif /* MAIN_NIMBLECLIENT_H_ */ diff --git a/src/NimBLEDescriptor.cpp b/src/NimBLEDescriptor.cpp index 184af5a..0d414d3 100644 --- a/src/NimBLEDescriptor.cpp +++ b/src/NimBLEDescriptor.cpp @@ -3,7 +3,7 @@ * * Created: on March 10, 2020 * Author H2zero - * + * * Originally: * * BLEDescriptor.cpp @@ -14,6 +14,9 @@ #include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) +#include "nimconfig.h" +#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) + #include "NimBLEService.h" #include "NimBLEDescriptor.h" #include "NimBLELog.h" @@ -29,26 +32,26 @@ static NimBLEDescriptorCallbacks defaultCallbacks; /** * @brief NimBLEDescriptor constructor. */ -NimBLEDescriptor::NimBLEDescriptor(const char* uuid, uint16_t properties, uint16_t max_len, - NimBLECharacteristic* pCharacteristic) +NimBLEDescriptor::NimBLEDescriptor(const char* uuid, uint16_t properties, uint16_t max_len, + NimBLECharacteristic* pCharacteristic) : NimBLEDescriptor(NimBLEUUID(uuid), max_len, properties, pCharacteristic) { -} +} /** * @brief NimBLEDescriptor constructor. */ NimBLEDescriptor::NimBLEDescriptor(NimBLEUUID uuid, uint16_t properties, uint16_t max_len, - NimBLECharacteristic* pCharacteristic) + NimBLECharacteristic* pCharacteristic) { - m_uuid = uuid; - m_value.attr_len = 0; // Initial length is 0. - m_value.attr_max_len = max_len; // Maximum length of the data. - m_handle = NULL_HANDLE; // Handle is initially unknown. - m_pCharacteristic = nullptr; // No initial characteristic. + m_uuid = uuid; + m_value.attr_len = 0; // Initial length is 0. + m_value.attr_max_len = max_len; // Maximum length of the data. + m_handle = NULL_HANDLE; // Handle is initially unknown. + m_pCharacteristic = nullptr; // No initial characteristic. m_pCallbacks = &defaultCallbacks; // No initial callback. m_value.attr_value = (uint8_t*) calloc(max_len,1); // Allocate storage for the value. m_properties = 0; - + if (properties & BLE_GATT_CHR_F_READ) { // convert uint16_t properties to uint8_t m_properties |= BLE_ATT_F_READ; } @@ -81,7 +84,7 @@ NimBLEDescriptor::NimBLEDescriptor(NimBLEUUID uuid, uint16_t properties, uint16_ * @brief NimBLEDescriptor destructor. */ 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 /** @@ -89,7 +92,7 @@ NimBLEDescriptor::~NimBLEDescriptor() { * @return The handle for this descriptor. */ uint16_t NimBLEDescriptor::getHandle() { - return m_handle; + return m_handle; } // getHandle @@ -98,7 +101,7 @@ uint16_t NimBLEDescriptor::getHandle() { * @return The length (in bytes) of the value of this descriptor. */ size_t NimBLEDescriptor::getLength() { - return m_value.attr_len; + return m_value.attr_len; } // getLength @@ -106,7 +109,7 @@ size_t NimBLEDescriptor::getLength() { * @brief Get the UUID of the descriptor. */ NimBLEUUID NimBLEDescriptor::getUUID() { - return m_uuid; + return m_uuid; } // getUUID @@ -115,7 +118,7 @@ NimBLEUUID NimBLEDescriptor::getUUID() { * @return A pointer to the value of this descriptor. */ uint8_t* NimBLEDescriptor::getValue() { - return m_value.attr_value; + return m_value.attr_value; } // getValue @@ -125,25 +128,25 @@ int NimBLEDescriptor::handleGapEvent(uint16_t conn_handle, uint16_t attr_handle, { const ble_uuid_t *uuid; int rc; - NimBLEDescriptor* pDescriptor = (NimBLEDescriptor*)arg; - - NIMBLE_LOGD(LOG_TAG, "Descriptor %s %s event", pDescriptor->getUUID().toString().c_str(), + NimBLEDescriptor* pDescriptor = (NimBLEDescriptor*)arg; + + NIMBLE_LOGD(LOG_TAG, "Descriptor %s %s event", pDescriptor->getUUID().toString().c_str(), ctxt->op == BLE_GATT_ACCESS_OP_READ_DSC ? "Read" : "Write"); - - uuid = ctxt->chr->uuid; - if(ble_uuid_cmp(uuid, &pDescriptor->getUUID().getNative()->u) == 0){ + + uuid = ctxt->chr->uuid; + if(ble_uuid_cmp(uuid, &pDescriptor->getUUID().getNative()->u) == 0){ switch(ctxt->op) { case BLE_GATT_ACCESS_OP_READ_DSC: { pDescriptor->m_pCallbacks->onRead(pDescriptor); rc = os_mbuf_append(ctxt->om, pDescriptor->getValue(), pDescriptor->getLength()); return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; } - + case BLE_GATT_ACCESS_OP_WRITE_DSC: { if (ctxt->om->om_len > BLE_ATT_ATTR_MAX_LEN) { return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } - + pDescriptor->setValue(ctxt->om->om_data, ctxt->om->om_len); pDescriptor->m_pCallbacks->onWrite(pDescriptor); return 0; @@ -151,8 +154,8 @@ int NimBLEDescriptor::handleGapEvent(uint16_t conn_handle, uint16_t attr_handle, default: break; } - } - + } + 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) { if (pCallbacks != nullptr){ - m_pCallbacks = pCallbacks; - } else { - m_pCallbacks = &defaultCallbacks; - } + m_pCallbacks = pCallbacks; + } else { + m_pCallbacks = &defaultCallbacks; + } } // setCallbacks @@ -176,9 +179,9 @@ void NimBLEDescriptor::setCallbacks(NimBLEDescriptorCallbacks* pCallbacks) { * @return N/A. */ void NimBLEDescriptor::setHandle(uint16_t handle) { - NIMBLE_LOGD(LOG_TAG, ">> setHandle(0x%.2x): Setting descriptor handle to be 0x%.2x", handle, handle); - m_handle = handle; - NIMBLE_LOGD(LOG_TAG, "<< setHandle()"); + NIMBLE_LOGD(LOG_TAG, ">> setHandle(0x%.2x): Setting descriptor handle to be 0x%.2x", handle, handle); + m_handle = handle; + NIMBLE_LOGD(LOG_TAG, "<< setHandle()"); } // setHandle @@ -188,12 +191,12 @@ void NimBLEDescriptor::setHandle(uint16_t handle) { * @param [in] length The length of the data in bytes. */ void NimBLEDescriptor::setValue(const uint8_t* data, size_t 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.attr_len = length; - memcpy(m_value.attr_value, 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.attr_len = length; + memcpy(m_value.attr_value, data, length); } // 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. */ void NimBLEDescriptor::setValue(const std::string &value) { - setValue((uint8_t*) value.data(), value.length()); + setValue((uint8_t*) value.data(), value.length()); } // setValue /* 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. */ std::string NimBLEDescriptor::toString() { - char hex[5]; - snprintf(hex, sizeof(hex), "%04x", m_handle); - std::string res = "UUID: " + m_uuid.toString() + ", handle: 0x" + hex; - return res; + char hex[5]; + snprintf(hex, sizeof(hex), "%04x", m_handle); + std::string res = "UUID: " + m_uuid.toString() + ", handle: 0x" + hex; + return res; } // toString @@ -232,7 +235,7 @@ NimBLEDescriptorCallbacks::~NimBLEDescriptorCallbacks() {} * @param [in] pDescriptor The descriptor that is the source of the event. */ void NimBLEDescriptorCallbacks::onRead(NimBLEDescriptor* pDescriptor) { - NIMBLE_LOGD("NimBLEDescriptorCallbacks", "onRead: default"); + NIMBLE_LOGD("NimBLEDescriptorCallbacks", "onRead: default"); } // onRead @@ -241,8 +244,8 @@ void NimBLEDescriptorCallbacks::onRead(NimBLEDescriptor* pDescriptor) { * @param [in] pDescriptor The descriptor that is the source of the event. */ void NimBLEDescriptorCallbacks::onWrite(NimBLEDescriptor* pDescriptor) { - NIMBLE_LOGD("NimBLEDescriptorCallbacks", "onWrite: default"); + NIMBLE_LOGD("NimBLEDescriptorCallbacks", "onWrite: default"); } // onWrite - +#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #endif /* CONFIG_BT_ENABLED */ diff --git a/src/NimBLEDescriptor.h b/src/NimBLEDescriptor.h index 3d8da68..8af3560 100644 --- a/src/NimBLEDescriptor.h +++ b/src/NimBLEDescriptor.h @@ -3,7 +3,7 @@ * * Created: on March 10, 2020 * Author H2zero - * + * * Originally: * * BLEDescriptor.h @@ -17,6 +17,9 @@ #include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) +#include "nimconfig.h" +#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) + #include "NimBLECharacteristic.h" #include "NimBLEUUID.h" #include "FreeRTOS.h" @@ -43,44 +46,44 @@ class NimBLEDescriptorCallbacks; */ class NimBLEDescriptor { public: - virtual ~NimBLEDescriptor(); - uint16_t getHandle(); // Get the handle of the descriptor. - size_t getLength(); // Get the length of the value of the descriptor. - NimBLEUUID getUUID(); // Get the UUID 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 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 std::string &value); // Set the value of the descriptor as a data buffer. + virtual ~NimBLEDescriptor(); + uint16_t getHandle(); // Get the handle of the descriptor. + size_t getLength(); // Get the length of the value of the descriptor. + NimBLEUUID getUUID(); // Get the UUID 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 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 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: - friend class NimBLEDescriptorMap; - friend class NimBLECharacteristic; + friend class NimBLEDescriptorMap; + friend class NimBLECharacteristic; friend class NimBLEService; - friend class NimBLE2902; - 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; + friend class NimBLE2902; + friend class NimBLE2904; - 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); - - void setHandle(uint16_t handle); + + void setHandle(uint16_t handle); }; // BLEDescriptor @@ -93,9 +96,11 @@ private: */ class NimBLEDescriptorCallbacks { public: - virtual ~NimBLEDescriptorCallbacks(); - virtual void onRead(NimBLEDescriptor* pDescriptor); - virtual void onWrite(NimBLEDescriptor* pDescriptor); + virtual ~NimBLEDescriptorCallbacks(); + virtual void onRead(NimBLEDescriptor* pDescriptor); + virtual void onWrite(NimBLEDescriptor* pDescriptor); }; + +#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #endif /* CONFIG_BT_ENABLED */ #endif /* MAIN_NIMBLEDESCRIPTOR_H_ */ diff --git a/src/NimBLEDescriptorMap.cpp b/src/NimBLEDescriptorMap.cpp index 05dc676..0ca1cbe 100644 --- a/src/NimBLEDescriptorMap.cpp +++ b/src/NimBLEDescriptorMap.cpp @@ -3,7 +3,7 @@ * * Created: on March 10, 2020 * Author H2zero - * + * * Originally: * * BLEDescriptorMap.cpp @@ -13,6 +13,10 @@ */ #include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) + +#include "nimconfig.h" +#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) + #include "NimBLECharacteristic.h" #include "NimBLEDescriptor.h" @@ -23,7 +27,7 @@ * @return The descriptor. If not present, then nullptr is returned. */ 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. */ NimBLEDescriptor* NimBLEDescriptorMap::getByUUID(const NimBLEUUID &uuid) { - for (auto &myPair : m_uuidMap) { - if (myPair.first->getUUID().equals(uuid)) { - return myPair.first; - } - } - return nullptr; + for (auto &myPair : m_uuidMap) { + if (myPair.first->getUUID().equals(uuid)) { + return myPair.first; + } + } + return nullptr; } // getByUUID @@ -49,7 +53,7 @@ NimBLEDescriptor* NimBLEDescriptorMap::getByUUID(const NimBLEUUID &uuid) { */ /* NimBLEDescriptor* NimBLEDescriptorMap::getByHandle(uint16_t handle) { - return m_handleMap.at(handle); + return m_handleMap.at(handle); } // getByHandle */ @@ -60,7 +64,7 @@ NimBLEDescriptor* NimBLEDescriptorMap::getByHandle(uint16_t handle) { * @return N/A. */ void NimBLEDescriptorMap::setByUUID(const char* uuid, NimBLEDescriptor* pDescriptor){ - m_uuidMap.insert(std::pair(pDescriptor, uuid)); + m_uuidMap.insert(std::pair(pDescriptor, uuid)); } // setByUUID @@ -72,7 +76,7 @@ void NimBLEDescriptorMap::setByUUID(const char* uuid, NimBLEDescriptor* pDescrip * @return N/A. */ void NimBLEDescriptorMap::setByUUID(const NimBLEUUID &uuid, NimBLEDescriptor* pDescriptor) { - m_uuidMap.insert(std::pair(pDescriptor, uuid.toString())); + m_uuidMap.insert(std::pair(pDescriptor, uuid.toString())); } // setByUUID @@ -84,7 +88,7 @@ void NimBLEDescriptorMap::setByUUID(const NimBLEUUID &uuid, NimBLEDescriptor* pD */ /* void NimBLEDescriptorMap::setByHandle(uint16_t handle, NimBLEDescriptor* pDescriptor) { - m_handleMap.insert(std::pair(handle, pDescriptor)); + m_handleMap.insert(std::pair(handle, pDescriptor)); } // setByHandle */ @@ -93,7 +97,7 @@ void NimBLEDescriptorMap::setByHandle(uint16_t handle, NimBLEDescriptor* pDescri * @brief Get the number of descriptors in the map. */ uint8_t NimBLEDescriptorMap::getSize() { - return (uint8_t)m_uuidMap.size(); + return (uint8_t)m_uuidMap.size(); } // getSize @@ -102,18 +106,18 @@ uint8_t NimBLEDescriptorMap::getSize() { * @return A string representation of the descriptor map. */ std::string NimBLEDescriptorMap::toString() { - std::string res; - char hex[5]; - int count = 0; - for (auto &myPair : m_uuidMap) { - if (count > 0) {res += "\n";} - snprintf(hex, sizeof(hex), "%04x", myPair.first->getHandle()); - count++; - res += "handle: 0x"; - res += hex; - res += ", uuid: " + myPair.first->getUUID().toString(); - } - return res; + std::string res; + char hex[5]; + int count = 0; + for (auto &myPair : m_uuidMap) { + if (count > 0) {res += "\n";} + snprintf(hex, sizeof(hex), "%04x", myPair.first->getHandle()); + count++; + res += "handle: 0x"; + res += hex; + res += ", uuid: " + myPair.first->getUUID().toString(); + } + return res; } // toString @@ -122,11 +126,11 @@ std::string NimBLEDescriptorMap::toString() { * @return The first descriptor in the map. */ NimBLEDescriptor* NimBLEDescriptorMap::getFirst() { - m_iterator = m_uuidMap.begin(); - if (m_iterator == m_uuidMap.end()) return nullptr; - NimBLEDescriptor* pRet = m_iterator->first; - m_iterator++; - return pRet; + m_iterator = m_uuidMap.begin(); + if (m_iterator == m_uuidMap.end()) return nullptr; + NimBLEDescriptor* pRet = m_iterator->first; + m_iterator++; + return pRet; } // getFirst @@ -135,9 +139,11 @@ NimBLEDescriptor* NimBLEDescriptorMap::getFirst() { * @return The next descriptor in the map. */ NimBLEDescriptor* NimBLEDescriptorMap::getNext() { - if (m_iterator == m_uuidMap.end()) return nullptr; - NimBLEDescriptor* pRet = m_iterator->first; - m_iterator++; - return pRet; + if (m_iterator == m_uuidMap.end()) return nullptr; + NimBLEDescriptor* pRet = m_iterator->first; + m_iterator++; + return pRet; } // getNext + +#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #endif /* CONFIG_BT_ENABLED */ diff --git a/src/NimBLEDevice.cpp b/src/NimBLEDevice.cpp index 728b74f..2264f57 100644 --- a/src/NimBLEDevice.cpp +++ b/src/NimBLEDevice.cpp @@ -3,7 +3,7 @@ * * Created: on Jan 24 2020 * Author H2zero - * + * * Originally: * * BLEDevice.cpp @@ -14,6 +14,7 @@ #include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) +#include "nimconfig.h" #include "NimBLEDevice.h" #include "NimBLEUtils.h" @@ -40,61 +41,63 @@ static const char* LOG_TAG = "NimBLEDevice"; * Singletons for the NimBLEDevice. */ bool initialized = false; +#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) NimBLEScan* NimBLEDevice::m_pScan = nullptr; +#endif +#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) NimBLEServer* NimBLEDevice::m_pServer = nullptr; +#endif uint32_t NimBLEDevice::m_passkey = 123456; bool NimBLEDevice::m_synced = false; +#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) NimBLEAdvertising* NimBLEDevice::m_bleAdvertising = nullptr; +#endif gap_event_handler NimBLEDevice::m_customGapHandler = nullptr; ble_gap_event_listener NimBLEDevice::m_listener; +#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) std::list NimBLEDevice::m_cList; +#endif std::list NimBLEDevice::m_ignoreList; NimBLESecurityCallbacks* NimBLEDevice::m_securityCallbacks = nullptr; - -//std::map 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. * @return A new instance of the server. */ +#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) /* 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) { NimBLEDevice::m_pServer = new NimBLEServer(); - ble_gatts_reset(); + ble_gatts_reset(); ble_svc_gap_init(); ble_svc_gatt_init(); } return m_pServer; } // createServer +#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) +#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) NimBLEAdvertising* NimBLEDevice::getAdvertising() { - if(m_bleAdvertising == nullptr) { - m_bleAdvertising = new NimBLEAdvertising(); - } - return m_bleAdvertising; + if(m_bleAdvertising == nullptr) { + m_bleAdvertising = new NimBLEAdvertising(); + } + return m_bleAdvertising; } void NimBLEDevice::startAdvertising() { - getAdvertising()->start(); + getAdvertising()->start(); } // startAdvertising void NimBLEDevice::stopAdvertising() { getAdvertising()->stop(); } // 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 * try and release/delete it. */ +#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) /* STATIC */ NimBLEScan* NimBLEDevice::getScan() { if (m_pScan == nullptr) { m_pScan = new NimBLEScan(); } return m_pScan; } // getScan - +#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) /** * @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. */ +#if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) /* STATIC */ NimBLEClient* NimBLEDevice::createClient() { 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); } - + NimBLEClient* pClient = new NimBLEClient(); m_cList.push_back(pClient); @@ -137,7 +142,7 @@ void NimBLEDevice::stopAdvertising() { if(pClient == nullptr) { return false; } - + if(pClient->m_isConnected) { if (pClient->disconnect() != 0) { return false; @@ -146,7 +151,7 @@ void NimBLEDevice::stopAdvertising() { vTaskDelay(1); } } - + if(pClient->m_waitingToConnect) { if(ble_gap_conn_cancel() != 0){ return false; @@ -155,10 +160,10 @@ void NimBLEDevice::stopAdvertising() { vTaskDelay(1); } } - + m_cList.remove(pClient); delete pClient; - + return true; } // deleteClient @@ -225,18 +230,20 @@ void NimBLEDevice::stopAdvertising() { return nullptr; } // getDisconnectedClient +#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) + /** * @brief Set the transmission power. * The power level can be one of: - * * ESP_PWR_LVL_N12 = 0, !< Corresponding to -12dbm - * * ESP_PWR_LVL_N9 = 1, !< Corresponding to -9dbm - * * ESP_PWR_LVL_N6 = 2, !< Corresponding to -6dbm - * * ESP_PWR_LVL_N3 = 3, !< Corresponding to -3dbm - * * ESP_PWR_LVL_N0 = 4, !< Corresponding to 0dbm - * * ESP_PWR_LVL_P3 = 5, !< Corresponding to +3dbm - * * ESP_PWR_LVL_P6 = 6, !< Corresponding to +6dbm - * * ESP_PWR_LVL_P9 = 7, !< Corresponding to +9dbm + * * ESP_PWR_LVL_N12 = 0, !< Corresponding to -12dbm + * * ESP_PWR_LVL_N9 = 1, !< Corresponding to -9dbm + * * ESP_PWR_LVL_N6 = 2, !< Corresponding to -6dbm + * * ESP_PWR_LVL_N3 = 3, !< Corresponding to -3dbm + * * ESP_PWR_LVL_N0 = 4, !< Corresponding to 0dbm + * * ESP_PWR_LVL_P3 = 5, !< Corresponding to +3dbm + * * ESP_PWR_LVL_P6 = 6, !< Corresponding to +6dbm + * * ESP_PWR_LVL_P9 = 7, !< Corresponding to +9dbm * @param [in] powerLevel. */ /* 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) { - switch(esp_ble_tx_power_get(powerType)) { - case ESP_PWR_LVL_N12: - return -12; - case ESP_PWR_LVL_N9: - return -9; - case ESP_PWR_LVL_N6: - return -6; - case ESP_PWR_LVL_N3: - return -6; - case ESP_PWR_LVL_N0: - return 0; - case ESP_PWR_LVL_P3: - return 3; - case ESP_PWR_LVL_P6: - return 6; - case ESP_PWR_LVL_P9: - return 9; - default: - return BLE_HS_ADV_TX_PWR_LVL_AUTO; - } + switch(esp_ble_tx_power_get(powerType)) { + case ESP_PWR_LVL_N12: + return -12; + case ESP_PWR_LVL_N9: + return -9; + case ESP_PWR_LVL_N6: + return -6; + case ESP_PWR_LVL_N3: + return -6; + case ESP_PWR_LVL_N0: + return 0; + case ESP_PWR_LVL_P3: + return 3; + case ESP_PWR_LVL_P6: + return 6; + case ESP_PWR_LVL_P9: + return 9; + default: + return BLE_HS_ADV_TX_PWR_LVL_AUTO; + } } // setPower @@ -282,13 +289,13 @@ void NimBLEDevice::stopAdvertising() { /* STATIC*/ NimBLEAddress NimBLEDevice::getAddress() { ble_addr_t addr = {BLE_ADDR_PUBLIC, 0}; //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"); addr.type = BLE_ADDR_RANDOM; ble_hs_id_copy_addr(BLE_ADDR_RANDOM, addr.val, NULL); } - + return NimBLEAddress(addr); } // getAddress @@ -309,13 +316,13 @@ void NimBLEDevice::stopAdvertising() { */ /* STATIC */int NimBLEDevice::setMTU(uint16_t mtu) { NIMBLE_LOGD(LOG_TAG, ">> setLocalMTU: %d", mtu); - + int rc = ble_att_set_preferred_mtu(mtu); if (rc != 0) { NIMBLE_LOGE(LOG_TAG, "Could not set local mtu value to: %d", mtu); } - + NIMBLE_LOGD(LOG_TAG, "<< setLocalMTU"); return rc; } // setMTU @@ -337,26 +344,32 @@ void NimBLEDevice::stopAdvertising() { if(!m_synced) { return; } - + m_synced = false; - + +#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) if(m_pScan != nullptr) { m_pScan->onHostReset(); } -/* Not needed +#endif + +/* Not needed if(m_pServer != nullptr) { m_pServer->onHostReset(); } - + for(auto it = m_cList.cbegin(); it != m_cList.cend(); ++it) { (*it)->onHostReset(); } -*/ +*/ + +#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) if(m_bleAdvertising != nullptr) { m_bleAdvertising->onHostReset(); } - - NIMBLE_LOGC(LOG_TAG, "Resetting state; reason=%d, %s", reason, +#endif + + NIMBLE_LOGC(LOG_TAG, "Resetting state; reason=%d, %s", reason, NimBLEUtils::returnCodeToString(reason)); } // onReset @@ -372,23 +385,27 @@ void NimBLEDevice::stopAdvertising() { if(m_synced) { return; } - + /* Make sure we have proper identity address set (public preferred) */ int rc = ble_hs_util_ensure_addr(0); assert(rc == 0); - + m_synced = true; - + if(initialized) { +#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) if(m_pScan != nullptr) { // Restart scanning with the last values sent, allow to clear results. m_pScan->start(m_pScan->m_duration, m_pScan->m_scanCompleteCB); } +#endif +#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) if(m_bleAdvertising != nullptr) { // Restart advertisng, parameters should already be set. m_bleAdvertising->start(); } +#endif } } // onSync @@ -414,7 +431,7 @@ void NimBLEDevice::stopAdvertising() { if(!initialized){ int rc=0; esp_err_t errRc = ESP_OK; - + #ifdef ARDUINO_ARCH_ESP32 // make sure the linker includes esp32-hal-bt.c so ardruino init doesn't release BLE memory. btStarted(); @@ -428,25 +445,25 @@ void NimBLEDevice::stopAdvertising() { } ESP_ERROR_CHECK(errRc); - + ESP_ERROR_CHECK(esp_nimble_hci_and_controller_init()); - + nimble_port_init(); - - // Setup callbacks for host events + + // Setup callbacks for host events ble_hs_cfg.reset_cb = NimBLEDevice::onReset; ble_hs_cfg.sync_cb = NimBLEDevice::onSync; - + // 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_mitm = 0; ble_hs_cfg.sm_sc = 1; ble_hs_cfg.sm_our_key_dist = 1; ble_hs_cfg.sm_their_key_dist = 3; - + ble_hs_cfg.store_status_cb = ble_store_util_status_rr; /*TODO: Implement handler for this*/ - + // Set the device name. rc = ble_svc_gap_device_name_set(deviceName.c_str()); assert(rc == 0); @@ -471,12 +488,12 @@ void NimBLEDevice::stopAdvertising() { int ret = nimble_port_stop(); if (ret == 0) { nimble_port_deinit(); - + ret = esp_nimble_hci_and_controller_deinit(); if (ret != ESP_OK) { NIMBLE_LOGE(LOG_TAG, "esp_nimble_hci_and_controller_deinit() failed with error: %d", ret); } - + initialized = false; m_synced = false; } @@ -509,12 +526,12 @@ bool NimBLEDevice::getInitialized() { * @brief Set the authorization mode for this device. * @param A bitmap indicating what modes are supported. * The bits are defined as follows: - ** 0x01 BLE_SM_PAIR_AUTHREQ_BOND - ** 0x04 BLE_SM_PAIR_AUTHREQ_MITM - ** 0x08 BLE_SM_PAIR_AUTHREQ_SC - ** 0x10 BLE_SM_PAIR_AUTHREQ_KEYPRESS - not yet supported. + ** 0x01 BLE_SM_PAIR_AUTHREQ_BOND + ** 0x04 BLE_SM_PAIR_AUTHREQ_MITM + ** 0x08 BLE_SM_PAIR_AUTHREQ_SC + ** 0x10 BLE_SM_PAIR_AUTHREQ_KEYPRESS - not yet supported. ** 0xe2 BLE_SM_PAIR_AUTHREQ_RESERVED - for reference only. - */ + */ /*STATIC*/void NimBLEDevice::setSecurityAuth(uint8_t auth_req) { NimBLEDevice::setSecurityAuth((auth_req & BLE_SM_PAIR_AUTHREQ_BOND)>0, (auth_req & BLE_SM_PAIR_AUTHREQ_MITM)>0, @@ -527,8 +544,8 @@ bool NimBLEDevice::getInitialized() { * @param One of the following: ** 0x00 BLE_HS_IO_DISPLAY_ONLY DisplayOnly IO capability ** 0x01 BLE_HS_IO_DISPLAY_YESNO DisplayYesNo IO capability - ** 0x02 BLE_HS_IO_KEYBOARD_ONLY KeyboardOnly IO capability - ** 0x03 BLE_HS_IO_NO_INPUT_OUTPUT NoInputNoOutput IO capability + ** 0x02 BLE_HS_IO_KEYBOARD_ONLY KeyboardOnly IO capability + ** 0x03 BLE_HS_IO_NO_INPUT_OUTPUT NoInputNoOutput IO capability ** 0x04 BLE_HS_IO_KEYBOARD_DISPLAY KeyboardDisplay Only IO capability */ /*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. * @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. ** 0x02: BLE_SM_PAIR_KEY_DIST_ID - Distribute the ID key (IRK). ** 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. * @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. ** 0x02: BLE_SM_PAIR_KEY_DIST_ID - Accept the ID key (IRK). ** 0x04: BLE_SM_PAIR_KEY_DIST_SIGN @@ -596,14 +613,14 @@ void NimBLEDevice::setSecurityCallbacks(NimBLESecurityCallbacks* callbacks) { */ /* STATIC */int NimBLEDevice::startSecurity(uint16_t conn_id) { /* if(m_securityCallbacks != nullptr) { - m_securityCallbacks->onSecurityRequest(); + m_securityCallbacks->onSecurityRequest(); } - */ + */ int rc = ble_gap_security_initiate(conn_id); if(rc != 0){ NIMBLE_LOGE(LOG_TAG, "ble_gap_security_initiate: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc)); } - + return rc; } // startSecurity @@ -661,20 +678,4 @@ void NimBLEDevice::setCustomGapHandler(gap_event_handler handler) { } // 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 diff --git a/src/NimBLEDevice.h b/src/NimBLEDevice.h index a0a4278..a3d4360 100644 --- a/src/NimBLEDevice.h +++ b/src/NimBLEDevice.h @@ -3,7 +3,7 @@ * * Created: on Jan 24 2020 * Author H2zero - * + * * Originally: * * BLEDevice.h @@ -17,11 +17,27 @@ #include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) +#include "nimconfig.h" + +#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) #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" +#endif + +#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #include "NimBLEServer.h" +#endif + +#include "NimBLEUtils.h" #include "NimBLESecurity.h" +#include "NimBLEAddress.h" #include "esp_bt.h" @@ -50,43 +66,46 @@ #define BLEAdvertising NimBLEAdvertising #define BLEServerCallbacks NimBLEServerCallbacks #define BLECharacteristicCallbacks NimBLECharacteristicCallbacks -#define BLEAdvertisementData NimBLEAdvertisementData -#define BLEDescriptor NimBLEDescriptor -#define BLE2902 NimBLE2902 -#define BLE2904 NimBLE2904 -#define BLEDescriptorCallbacks NimBLEDescriptorCallbacks +#define BLEAdvertisementData NimBLEAdvertisementData +#define BLEDescriptor NimBLEDescriptor +#define BLE2902 NimBLE2902 +#define BLE2904 NimBLE2904 +#define BLEDescriptorCallbacks NimBLEDescriptorCallbacks #define BLEBeacon NimBLEBeacon #define BLEEddystoneTLM NimBLEEddystoneTLM #define BLEEddystoneURL NimBLEEddystoneURL #ifdef CONFIG_BT_NIMBLE_MAX_CONNECTIONS #define NIMBLE_MAX_CONNECTIONS CONFIG_BT_NIMBLE_MAX_CONNECTIONS -#else +#else #define NIMBLE_MAX_CONNECTIONS CONFIG_NIMBLE_MAX_CONNECTIONS #endif - + /** * @brief BLE functions. */ 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); class NimBLEDevice { public: - static void init(const std::string &deviceName); // Initialize the local BLE environment. + static void init(const std::string &deviceName); static void deinit(); static bool getInitialized(); static NimBLEAddress getAddress(); static std::string toString(); - static NimBLEScan* getScan(); // Get the scan object - static NimBLEClient* createClient(); - static NimBLEServer* createServer(); - static bool deleteClient(NimBLEClient* pClient); + +#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) + static NimBLEScan* getScan(); +#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 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 setSecurityAuth(bool bonding, bool mitm, bool sc); static void setSecurityAuth(uint8_t auth_req); @@ -101,36 +120,66 @@ public: static bool isIgnored(const NimBLEAddress &address); static void addIgnored(const NimBLEAddress &address); static void removeIgnored(const NimBLEAddress &address); + +#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) static NimBLEAdvertising* getAdvertising(); - static void startAdvertising(); - static void stopAdvertising(); + static void startAdvertising(); + 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* getClientByPeerAddress(const NimBLEAddress &peer_addr); static NimBLEClient* getDisconnectedClient(); - static size_t getClientListSize(); - static std::list* getClientList(); - + static size_t getClientListSize(); + static std::list* getClientList(); +#endif + private: - friend class NimBLEServer; +#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) friend class NimBLEClient; +#endif + +#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) friend class NimBLEScan; - friend class NimBLEAdvertising; +#endif + +#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) + friend class NimBLEServer; friend class NimBLECharacteristic; - +#endif + +#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) + friend class NimBLEAdvertising; +#endif + static void onReset(int reason); static void onSync(void); static void host_task(void *param); - static int startSecurity( uint16_t conn_id); - - static bool m_synced; + static int startSecurity(uint16_t conn_id); + static bool m_synced; + +#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) static NimBLEScan* m_pScan; +#endif + +#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) static NimBLEServer* m_pServer; +#endif + +#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) static NimBLEAdvertising* m_bleAdvertising; - static ble_gap_event_listener m_listener; - static uint32_t m_passkey; +#endif + +#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) static std::list m_cList; +#endif static std::list m_ignoreList; static NimBLESecurityCallbacks* m_securityCallbacks; + static uint32_t m_passkey; + static ble_gap_event_listener m_listener; public: static gap_event_handler m_customGapHandler; diff --git a/src/NimBLEEddystoneTLM.cpp b/src/NimBLEEddystoneTLM.cpp index 27d0b39..990a36f 100644 --- a/src/NimBLEEddystoneTLM.cpp +++ b/src/NimBLEEddystoneTLM.cpp @@ -3,7 +3,7 @@ * * Created: on March 15 2020 * Author H2zero - * + * * Originally: * * BLEEddystoneTLM.cpp @@ -26,41 +26,41 @@ static const char LOG_TAG[] = "NimBLEEddystoneTLM"; NimBLEEddystoneTLM::NimBLEEddystoneTLM() { - beaconUUID = 0xFEAA; - m_eddystoneData.frameType = EDDYSTONE_TLM_FRAME_TYPE; - m_eddystoneData.version = 0; - m_eddystoneData.volt = 3300; // 3300mV = 3.3V - m_eddystoneData.temp = (uint16_t) ((float) 23.00 * 256); // 8.8 fixed format - m_eddystoneData.advCount = 0; - m_eddystoneData.tmil = 0; + beaconUUID = 0xFEAA; + m_eddystoneData.frameType = EDDYSTONE_TLM_FRAME_TYPE; + m_eddystoneData.version = 0; + m_eddystoneData.volt = 3300; // 3300mV = 3.3V + m_eddystoneData.temp = (uint16_t) ((float) 23.00 * 256); // 8.8 fixed format + m_eddystoneData.advCount = 0; + m_eddystoneData.tmil = 0; } // NimBLEEddystoneTLM std::string NimBLEEddystoneTLM::getData() { - return std::string((char*) &m_eddystoneData, sizeof(m_eddystoneData)); + return std::string((char*) &m_eddystoneData, sizeof(m_eddystoneData)); } // getData NimBLEUUID NimBLEEddystoneTLM::getUUID() { - return NimBLEUUID(beaconUUID); + return NimBLEUUID(beaconUUID); } // getUUID uint8_t NimBLEEddystoneTLM::getVersion() { - return m_eddystoneData.version; + return m_eddystoneData.version; } // getVersion uint16_t NimBLEEddystoneTLM::getVolt() { - return ENDIAN_CHANGE_U16(m_eddystoneData.volt); + return ENDIAN_CHANGE_U16(m_eddystoneData.volt); } // getVolt float NimBLEEddystoneTLM::getTemp() { - return ENDIAN_CHANGE_U16(m_eddystoneData.temp) / 256.0f; + return ENDIAN_CHANGE_U16(m_eddystoneData.temp) / 256.0f; } // getTemp uint32_t NimBLEEddystoneTLM::getCount() { - return ENDIAN_CHANGE_U32(m_eddystoneData.advCount); + return ENDIAN_CHANGE_U32(m_eddystoneData.advCount); } // getCount uint32_t NimBLEEddystoneTLM::getTime() { - return (ENDIAN_CHANGE_U32(m_eddystoneData.tmil)) / 10; + return (ENDIAN_CHANGE_U32(m_eddystoneData.tmil)) / 10; } // getTime std::string NimBLEEddystoneTLM::toString() { @@ -117,36 +117,36 @@ std::string NimBLEEddystoneTLM::toString() { * Set the raw data for the beacon record. */ void NimBLEEddystoneTLM::setData(const std::string &data) { - if (data.length() != sizeof(m_eddystoneData)) { - NIMBLE_LOGE(LOG_TAG, "Unable to set the data ... length passed in was %d and expected %d", + if (data.length() != sizeof(m_eddystoneData)) { + NIMBLE_LOGE(LOG_TAG, "Unable to set the data ... length passed in was %d and expected %d", data.length(), sizeof(m_eddystoneData)); - return; - } + return; + } memcpy(&m_eddystoneData, data.data(), data.length()); } // setData void NimBLEEddystoneTLM::setUUID(const NimBLEUUID &l_uuid) { - beaconUUID = l_uuid.getNative()->u16.value; + beaconUUID = l_uuid.getNative()->u16.value; } // setUUID void NimBLEEddystoneTLM::setVersion(uint8_t version) { - m_eddystoneData.version = version; + m_eddystoneData.version = version; } // setVersion void NimBLEEddystoneTLM::setVolt(uint16_t volt) { - m_eddystoneData.volt = volt; + m_eddystoneData.volt = volt; } // setVolt void NimBLEEddystoneTLM::setTemp(float temp) { - m_eddystoneData.temp = (uint16_t)temp; + m_eddystoneData.temp = (uint16_t)temp; } // setTemp void NimBLEEddystoneTLM::setCount(uint32_t advCount) { - m_eddystoneData.advCount = advCount; + m_eddystoneData.advCount = advCount; } // setCount void NimBLEEddystoneTLM::setTime(uint32_t tmil) { - m_eddystoneData.tmil = tmil; + m_eddystoneData.tmil = tmil; } // setTime #endif diff --git a/src/NimBLEEddystoneTLM.h b/src/NimBLEEddystoneTLM.h index 9cae6f6..eb1cb07 100644 --- a/src/NimBLEEddystoneTLM.h +++ b/src/NimBLEEddystoneTLM.h @@ -3,7 +3,7 @@ * * Created: on March 15 2020 * Author H2zero - * + * * Originally: * * BLEEddystoneTLM.h @@ -27,33 +27,33 @@ */ class NimBLEEddystoneTLM { public: - NimBLEEddystoneTLM(); - std::string getData(); - NimBLEUUID getUUID(); - uint8_t getVersion(); - uint16_t getVolt(); - float getTemp(); - uint32_t getCount(); - uint32_t getTime(); - std::string toString(); - void setData(const std::string &data); - void setUUID(const NimBLEUUID &l_uuid); - void setVersion(uint8_t version); - void setVolt(uint16_t volt); - void setTemp(float temp); - void setCount(uint32_t advCount); - void setTime(uint32_t tmil); + NimBLEEddystoneTLM(); + std::string getData(); + NimBLEUUID getUUID(); + uint8_t getVersion(); + uint16_t getVolt(); + float getTemp(); + uint32_t getCount(); + uint32_t getTime(); + std::string toString(); + void setData(const std::string &data); + void setUUID(const NimBLEUUID &l_uuid); + void setVersion(uint8_t version); + void setVolt(uint16_t volt); + void setTemp(float temp); + void setCount(uint32_t advCount); + void setTime(uint32_t tmil); private: - uint16_t beaconUUID; - struct { - uint8_t frameType; - uint8_t version; - uint16_t volt; - uint16_t temp; - uint32_t advCount; - uint32_t tmil; - } __attribute__((packed)) m_eddystoneData; + uint16_t beaconUUID; + struct { + uint8_t frameType; + uint8_t version; + uint16_t volt; + uint16_t temp; + uint32_t advCount; + uint32_t tmil; + } __attribute__((packed)) m_eddystoneData; }; // NimBLEEddystoneTLM diff --git a/src/NimBLEEddystoneURL.cpp b/src/NimBLEEddystoneURL.cpp index 622b772..ce79759 100644 --- a/src/NimBLEEddystoneURL.cpp +++ b/src/NimBLEEddystoneURL.cpp @@ -3,7 +3,7 @@ * * Created: on March 15 2020 * Author H2zero - * + * * Originally: * * BLEEddystoneURL.cpp @@ -22,102 +22,102 @@ static const char LOG_TAG[] = "NimBLEEddystoneURL"; NimBLEEddystoneURL::NimBLEEddystoneURL() { - beaconUUID = 0xFEAA; - lengthURL = 0; - m_eddystoneData.frameType = EDDYSTONE_URL_FRAME_TYPE; - m_eddystoneData.advertisedTxPower = 0; - memset(m_eddystoneData.url, 0, sizeof(m_eddystoneData.url)); + beaconUUID = 0xFEAA; + lengthURL = 0; + m_eddystoneData.frameType = EDDYSTONE_URL_FRAME_TYPE; + m_eddystoneData.advertisedTxPower = 0; + memset(m_eddystoneData.url, 0, sizeof(m_eddystoneData.url)); } // BLEEddystoneURL std::string NimBLEEddystoneURL::getData() { - return std::string((char*) &m_eddystoneData, sizeof(m_eddystoneData)); + return std::string((char*) &m_eddystoneData, sizeof(m_eddystoneData)); } // getData NimBLEUUID NimBLEEddystoneURL::getUUID() { - return NimBLEUUID(beaconUUID); + return NimBLEUUID(beaconUUID); } // getUUID int8_t NimBLEEddystoneURL::getPower() { - return m_eddystoneData.advertisedTxPower; + return m_eddystoneData.advertisedTxPower; } // getPower 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 std::string NimBLEEddystoneURL::getDecodedURL() { - std::string decodedURL = ""; + std::string decodedURL = ""; - switch (m_eddystoneData.url[0]) { - case 0x00: - decodedURL += "http://www."; - break; - case 0x01: - decodedURL += "https://www."; - break; - case 0x02: - decodedURL += "http://"; - break; - case 0x03: - decodedURL += "https://"; - break; - default: - decodedURL += m_eddystoneData.url[0]; - } + switch (m_eddystoneData.url[0]) { + case 0x00: + decodedURL += "http://www."; + break; + case 0x01: + decodedURL += "https://www."; + break; + case 0x02: + decodedURL += "http://"; + break; + case 0x03: + decodedURL += "https://"; + break; + default: + decodedURL += m_eddystoneData.url[0]; + } - for (int i = 1; i < lengthURL; i++) { - if (m_eddystoneData.url[i] > 33 && m_eddystoneData.url[i] < 127) { - decodedURL += m_eddystoneData.url[i]; - } else { - switch (m_eddystoneData.url[i]) { - case 0x00: - decodedURL += ".com/"; - break; - case 0x01: - decodedURL += ".org/"; - break; - case 0x02: - decodedURL += ".edu/"; - break; - case 0x03: - decodedURL += ".net/"; - break; - case 0x04: - decodedURL += ".info/"; - break; - case 0x05: - decodedURL += ".biz/"; - break; - case 0x06: - decodedURL += ".gov/"; - break; - case 0x07: - decodedURL += ".com"; - break; - case 0x08: - decodedURL += ".org"; - break; - case 0x09: - decodedURL += ".edu"; - break; - case 0x0A: - decodedURL += ".net"; - break; - case 0x0B: - decodedURL += ".info"; - break; - case 0x0C: - decodedURL += ".biz"; - break; - case 0x0D: - decodedURL += ".gov"; - break; - default: - break; - } - } - } - return decodedURL; + for (int i = 1; i < lengthURL; i++) { + if (m_eddystoneData.url[i] > 33 && m_eddystoneData.url[i] < 127) { + decodedURL += m_eddystoneData.url[i]; + } else { + switch (m_eddystoneData.url[i]) { + case 0x00: + decodedURL += ".com/"; + break; + case 0x01: + decodedURL += ".org/"; + break; + case 0x02: + decodedURL += ".edu/"; + break; + case 0x03: + decodedURL += ".net/"; + break; + case 0x04: + decodedURL += ".info/"; + break; + case 0x05: + decodedURL += ".biz/"; + break; + case 0x06: + decodedURL += ".gov/"; + break; + case 0x07: + decodedURL += ".com"; + break; + case 0x08: + decodedURL += ".org"; + break; + case 0x09: + decodedURL += ".edu"; + break; + case 0x0A: + decodedURL += ".net"; + break; + case 0x0B: + decodedURL += ".info"; + break; + case 0x0C: + decodedURL += ".biz"; + break; + case 0x0D: + decodedURL += ".gov"; + break; + default: + break; + } + } + } + return decodedURL; } // getDecodedURL @@ -126,29 +126,29 @@ std::string NimBLEEddystoneURL::getDecodedURL() { * Set the raw data for the beacon record. */ void NimBLEEddystoneURL::setData(const std::string &data) { - if (data.length() > sizeof(m_eddystoneData)) { - NIMBLE_LOGE(LOG_TAG, "Unable to set the data ... length passed in was %d and max expected %d", + if (data.length() > sizeof(m_eddystoneData)) { + NIMBLE_LOGE(LOG_TAG, "Unable to set the data ... length passed in was %d and max expected %d", data.length(), sizeof(m_eddystoneData)); - return; - } - memset(&m_eddystoneData, 0, sizeof(m_eddystoneData)); - memcpy(&m_eddystoneData, data.data(), data.length()); - lengthURL = data.length() - (sizeof(m_eddystoneData) - sizeof(m_eddystoneData.url)); + return; + } + memset(&m_eddystoneData, 0, sizeof(m_eddystoneData)); + memcpy(&m_eddystoneData, data.data(), data.length()); + lengthURL = data.length() - (sizeof(m_eddystoneData) - sizeof(m_eddystoneData.url)); } // setData void NimBLEEddystoneURL::setUUID(const NimBLEUUID &l_uuid) { - beaconUUID = l_uuid.getNative()->u16.value; + beaconUUID = l_uuid.getNative()->u16.value; } // setUUID void NimBLEEddystoneURL::setPower(int8_t advertisedTxPower) { - m_eddystoneData.advertisedTxPower = advertisedTxPower; + m_eddystoneData.advertisedTxPower = advertisedTxPower; } // setPower void NimBLEEddystoneURL::setURL(const std::string &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)); - return; + return; } memset(m_eddystoneData.url, 0, sizeof(m_eddystoneData.url)); memcpy(m_eddystoneData.url, url.data(), url.length()); diff --git a/src/NimBLEEddystoneURL.h b/src/NimBLEEddystoneURL.h index 326cd98..9c5f37f 100644 --- a/src/NimBLEEddystoneURL.h +++ b/src/NimBLEEddystoneURL.h @@ -3,7 +3,7 @@ * * Created: on March 15 2020 * Author H2zero - * + * * Originally: * * BLEEddystoneURL.h @@ -27,25 +27,25 @@ */ class NimBLEEddystoneURL { public: - NimBLEEddystoneURL(); - std::string getData(); - NimBLEUUID getUUID(); - int8_t getPower(); - std::string getURL(); - std::string getDecodedURL(); - void setData(const std::string &data); - void setUUID(const NimBLEUUID &l_uuid); - void setPower(int8_t advertisedTxPower); - void setURL(const std::string &url); + NimBLEEddystoneURL(); + std::string getData(); + NimBLEUUID getUUID(); + int8_t getPower(); + std::string getURL(); + std::string getDecodedURL(); + void setData(const std::string &data); + void setUUID(const NimBLEUUID &l_uuid); + void setPower(int8_t advertisedTxPower); + void setURL(const std::string &url); private: - uint16_t beaconUUID; - uint8_t lengthURL; - struct { - uint8_t frameType; - int8_t advertisedTxPower; - uint8_t url[16]; - } __attribute__((packed)) m_eddystoneData; + uint16_t beaconUUID; + uint8_t lengthURL; + struct { + uint8_t frameType; + int8_t advertisedTxPower; + uint8_t url[16]; + } __attribute__((packed)) m_eddystoneData; }; // NIMBLEEddystoneURL diff --git a/src/NimBLELog.h b/src/NimBLELog.h index d223a04..b519c0f 100644 --- a/src/NimBLELog.h +++ b/src/NimBLELog.h @@ -14,11 +14,11 @@ #include "modlog/modlog.h" -// 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 +// 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 // otherwise no messages will be printed above that level. #ifdef ARDUINO_ARCH_ESP32 -#ifndef CORE_DEBUG_LEVEL +#ifndef CORE_DEBUG_LEVEL #define CORE_DEBUG_LEVEL CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL #endif @@ -48,7 +48,7 @@ #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_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__) diff --git a/src/NimBLERemoteCharacteristic.cpp b/src/NimBLERemoteCharacteristic.cpp index de28e43..86bf7ee 100644 --- a/src/NimBLERemoteCharacteristic.cpp +++ b/src/NimBLERemoteCharacteristic.cpp @@ -3,7 +3,7 @@ * * Created: on Jan 27 2020 * Author H2zero - * + * * Originally: * * BLERemoteCharacteristic.cpp @@ -15,6 +15,9 @@ #include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) +#include "nimconfig.h" +#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) + #include "NimBLERemoteCharacteristic.h" #include "NimBLEUtils.h" #include "NimBLELog.h" @@ -35,13 +38,13 @@ static const char* LOG_TAG = "NimBLERemoteCharacteristic"; NimBLERemoteCharacteristic::NimBLERemoteCharacteristic(NimBLERemoteService *pRemoteService, const struct ble_gatt_chr *chr) { switch (chr->uuid.u.type) { - case BLE_UUID_TYPE_16: + case BLE_UUID_TYPE_16: m_uuid = NimBLEUUID(chr->uuid.u16.value); break; - case BLE_UUID_TYPE_32: + case BLE_UUID_TYPE_32: m_uuid = NimBLEUUID(chr->uuid.u32.value); break; - case BLE_UUID_TYPE_128: + case BLE_UUID_TYPE_128: m_uuid = NimBLEUUID(const_cast(&chr->uuid.u128)); break; default: @@ -136,14 +139,14 @@ bool NimBLERemoteCharacteristic::canWriteNoResponse() { /** * @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, - uint16_t chr_val_handle, + uint16_t chr_val_handle, const struct ble_gatt_dsc *dsc, - void *arg) + void *arg) { NIMBLE_LOGD(LOG_TAG,"Descriptor Discovered >> status: %d handle: %d", error->status, conn_handle); - + NimBLERemoteCharacteristic *characteristic = (NimBLERemoteCharacteristic*)arg; int rc=0; @@ -151,13 +154,13 @@ int NimBLERemoteCharacteristic::descriptorDiscCB(uint16_t conn_handle, if(characteristic->getRemoteService()->getClient()->getConnId() != conn_handle){ return 0; } - + switch (error->status) { case 0: { // Found a descriptor - add it to the map NimBLERemoteDescriptor* pNewRemoteDescriptor = new NimBLERemoteDescriptor(characteristic, dsc); characteristic->m_descriptorMap.insert(std::pair(pNewRemoteDescriptor->getUUID().toString(), pNewRemoteDescriptor)); - + break; } case BLE_HS_EDONE:{ @@ -188,9 +191,9 @@ bool NimBLERemoteCharacteristic::retrieveDescriptors(uint16_t endHdl) { int rc = 0; //removeDescriptors(); // Remove any existing descriptors. - + m_semaphoreGetDescEvt.take("retrieveDescriptors"); - + rc = ble_gattc_disc_all_dscs(getRemoteService()->getClient()->getConnId(), m_handle, endHdl, @@ -201,13 +204,13 @@ bool NimBLERemoteCharacteristic::retrieveDescriptors(uint16_t endHdl) { m_semaphoreGetDescEvt.give(); return false; } - + if(m_semaphoreGetDescEvt.wait("retrieveCharacteristics") != 0) { // if there was an error release the resources //removeDescriptors(); return false; } - + return true; NIMBLE_LOGD(LOG_TAG, "<< retrieveDescriptors(): Found %d descriptors.", m_descriptorMap.size()); } // getDescriptors @@ -215,7 +218,7 @@ bool NimBLERemoteCharacteristic::retrieveDescriptors(uint16_t endHdl) { /** * @brief Retrieve the map of descriptors keyed by UUID. - */ + */ std::map* NimBLERemoteCharacteristic::getDescriptors() { return &m_descriptorMap; } // getDescriptors @@ -313,7 +316,7 @@ uint8_t NimBLERemoteCharacteristic::readUInt8() { return 0; } // readUInt8 - + /** * @brief Read 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); return ""; } - + rc = m_semaphoreReadCharEvt.wait("readValue"); switch(rc){ case 0: @@ -356,19 +359,19 @@ std::string NimBLERemoteCharacteristic::readValue() { // Characteristic is not long-readable, return with what we have. case BLE_HS_ATT_ERR(BLE_ATT_ERR_ATTR_NOT_LONG): NIMBLE_LOGI(LOG_TAG, "Attribute not long"); - rc = 0; + rc = 0; break; 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_ENC): if (retryCount && pClient->secureConnection()) break; - /* Else falls through. */ + /* Else falls through. */ default: return ""; } } while(rc != 0 && retryCount--); - + NIMBLE_LOGD(LOG_TAG, "<< readValue(): length: %d", m_value.length()); return m_value; } // readValue @@ -380,11 +383,11 @@ std::string NimBLERemoteCharacteristic::readValue() { */ int NimBLERemoteCharacteristic::onReadCB(uint16_t conn_handle, const struct ble_gatt_error *error, - struct ble_gatt_attr *attr, void *arg) + struct ble_gatt_attr *attr, void *arg) { NimBLERemoteCharacteristic* characteristic = (NimBLERemoteCharacteristic*)arg; uint16_t conn_id = characteristic->getRemoteService()->getClient()->getConnId(); - + // Make sure the read is for this client if(conn_id != conn_handle) { return 0; @@ -401,7 +404,7 @@ int NimBLERemoteCharacteristic::onReadCB(uint16_t conn_handle, } // Read complete release semaphore and let the app can continue. 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}; NimBLERemoteDescriptor* desc = getDescriptor(NimBLEUUID((uint16_t)0x2902)); - if(desc == nullptr) + if(desc == nullptr) return false; if(notifyCallback != nullptr){ @@ -435,7 +438,7 @@ bool NimBLERemoteCharacteristic::registerForNotify(notify_callback notifyCallbac } NIMBLE_LOGD(LOG_TAG, "<< registerForNotify()"); - + return desc->writeValue(val, 2, response); } // registerForNotify @@ -474,11 +477,11 @@ std::string NimBLERemoteCharacteristic::toString() { res += " 0x"; snprintf(val, sizeof(val), "%02x", m_charProp); res += val; - + for (auto &myPair : m_descriptorMap) { res += "\n" + myPair.second->toString(); } - + return res; } // 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. */ bool NimBLERemoteCharacteristic::writeValue(const uint8_t* data, size_t length, bool response) { - + NIMBLE_LOGD(LOG_TAG, ">> writeValue(), length: %d", length); - + NimBLEClient* pClient = getRemoteService()->getClient(); int rc = 0; int retryCount = 1; uint16_t mtu; - + // Check to see that we are connected. if (!pClient->isConnected()) { NIMBLE_LOGE(LOG_TAG, "Disconnected"); return false; } - + mtu = ble_att_mtu(pClient->getConnId()) - 3; // 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); return (rc==0); } - + do { m_semaphoreWriteCharEvt.take("writeValue"); @@ -558,26 +561,26 @@ bool NimBLERemoteCharacteristic::writeValue(const uint8_t* data, size_t length, m_semaphoreWriteCharEvt.give(); return false; } - + rc = m_semaphoreWriteCharEvt.wait("writeValue"); switch(rc){ case 0: case BLE_HS_EDONE: - rc = 0; + rc = 0; break; 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); retryCount++; length = mtu; break; - + 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_ENC): if (retryCount && pClient->secureConnection()) break; - /* Else falls through. */ + /* Else falls through. */ default: return false; } @@ -594,17 +597,17 @@ bool NimBLERemoteCharacteristic::writeValue(const uint8_t* data, size_t length, */ int NimBLERemoteCharacteristic::onWriteCB(uint16_t conn_handle, const struct ble_gatt_error *error, - struct ble_gatt_attr *attr, void *arg) + struct ble_gatt_attr *attr, void *arg) { NimBLERemoteCharacteristic* characteristic = (NimBLERemoteCharacteristic*)arg; - + // Make sure the discovery is for this device if(characteristic->getRemoteService()->getClient()->getConnId() != conn_handle){ return 0; } - + NIMBLE_LOGI(LOG_TAG, "Write complete; status=%d conn_handle=%d", error->status, conn_handle); - + characteristic->m_semaphoreWriteCharEvt.give(error->status); return 0; @@ -649,4 +652,6 @@ void NimBLERemoteCharacteristic::releaseSemaphores() { m_semaphoreGetDescEvt.give(1); m_semaphoreReadCharEvt.give(1); } + +#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) #endif /* CONFIG_BT_ENABLED */ diff --git a/src/NimBLERemoteCharacteristic.h b/src/NimBLERemoteCharacteristic.h index 98233ac..2c9cdb3 100644 --- a/src/NimBLERemoteCharacteristic.h +++ b/src/NimBLERemoteCharacteristic.h @@ -3,7 +3,7 @@ * * Created: on Jan 27 2020 * Author H2zero - * + * * Originally: * * BLERemoteCharacteristic.h @@ -17,6 +17,9 @@ #include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) +#include "nimconfig.h" +#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) + //#include "NimBLEUUID.h" //#include "FreeRTOS.h" #include "NimBLERemoteService.h" @@ -66,7 +69,7 @@ public: private: NimBLERemoteCharacteristic(NimBLERemoteService *pRemoteservice, const struct ble_gatt_chr *chr); - + friend class NimBLEClient; friend class NimBLERemoteService; friend class NimBLERemoteDescriptor; @@ -80,7 +83,7 @@ private: static int descriptorDiscCB(uint16_t conn_handle, const struct ble_gatt_error *error, uint16_t chr_val_handle, const struct ble_gatt_dsc *dsc, void *arg); - + // Private properties NimBLEUUID m_uuid; 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. std::map m_descriptorMap; }; // BLERemoteCharacteristic + +#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) #endif /* CONFIG_BT_ENABLED */ #endif /* COMPONENTS_NIMBLEREMOTECHARACTERISTIC_H_ */ diff --git a/src/NimBLERemoteDescriptor.cpp b/src/NimBLERemoteDescriptor.cpp index d7a3e56..52743bb 100644 --- a/src/NimBLERemoteDescriptor.cpp +++ b/src/NimBLERemoteDescriptor.cpp @@ -3,7 +3,7 @@ * * Created: on Jan 27 2020 * Author H2zero - * + * * Originally: * * BLERemoteDescriptor.cpp @@ -14,6 +14,9 @@ #include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) +#include "nimconfig.h" +#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) + #include "NimBLERemoteDescriptor.h" #include "NimBLEUtils.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 struct that contains the descriptor information. */ -NimBLERemoteDescriptor::NimBLERemoteDescriptor(NimBLERemoteCharacteristic* pRemoteCharacteristic, +NimBLERemoteDescriptor::NimBLERemoteDescriptor(NimBLERemoteCharacteristic* pRemoteCharacteristic, const struct ble_gatt_dsc *dsc) { switch (dsc->uuid.u.type) { - case BLE_UUID_TYPE_16: + case BLE_UUID_TYPE_16: m_uuid = NimBLEUUID(dsc->uuid.u16.value); break; - case BLE_UUID_TYPE_32: + case BLE_UUID_TYPE_32: m_uuid = NimBLEUUID(dsc->uuid.u32.value); break; - case BLE_UUID_TYPE_128: + case BLE_UUID_TYPE_128: m_uuid = NimBLEUUID(const_cast(&dsc->uuid.u128)); break; default: @@ -44,7 +47,7 @@ NimBLERemoteDescriptor::NimBLERemoteDescriptor(NimBLERemoteCharacteristic* pRemo } m_handle = dsc->handle; m_pRemoteCharacteristic = pRemoteCharacteristic; - + } @@ -81,18 +84,18 @@ NimBLEUUID NimBLERemoteDescriptor::getUUID() { */ int NimBLERemoteDescriptor::onReadCB(uint16_t conn_handle, const struct ble_gatt_error *error, - struct ble_gatt_attr *attr, void *arg) + struct ble_gatt_attr *attr, void *arg) { NimBLERemoteDescriptor* desc = (NimBLERemoteDescriptor*)arg; uint16_t conn_id = desc->getRemoteCharacteristic()->getRemoteService()->getClient()->getConnId(); - + // Make sure the discovery is for this device if(conn_id != conn_handle){ return 0; } - + NIMBLE_LOGD(LOG_TAG, "Read complete; status=%d conn_handle=%d", error->status, conn_handle); - + if(error->status == 0){ if(attr){ 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() { NIMBLE_LOGD(LOG_TAG, ">> Descriptor readValue: %s", toString().c_str()); - + int rc = 0; int retryCount = 1; // Clear the value before reading. m_value = ""; NimBLEClient* pClient = getRemoteCharacteristic()->getRemoteService()->getClient(); - + // Check to see that we are connected. if (!pClient->isConnected()) { NIMBLE_LOGE(LOG_TAG, "Disconnected"); return ""; } - + do { m_semaphoreReadDescrEvt.take("ReadDescriptor"); - + rc = ble_gattc_read_long(pClient->getConnId(), m_handle, 0, NimBLERemoteDescriptor::onReadCB, this); @@ -136,7 +139,7 @@ std::string NimBLERemoteDescriptor::readValue() { m_semaphoreReadDescrEvt.give(0); return ""; } - + rc = m_semaphoreReadDescrEvt.wait("ReadDescriptor"); switch(rc){ @@ -147,14 +150,14 @@ std::string NimBLERemoteDescriptor::readValue() { // Descriptor is not long-readable, return with what we have. case BLE_HS_ATT_ERR(BLE_ATT_ERR_ATTR_NOT_LONG): NIMBLE_LOGI(LOG_TAG, "Attribute not long"); - rc = 0; + rc = 0; break; 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_ENC): if (retryCount && pClient->secureConnection()) break; - /* Else falls through. */ + /* Else falls through. */ default: return ""; } @@ -202,7 +205,7 @@ std::string NimBLERemoteDescriptor::toString() { res += ", handle: "; snprintf(val, sizeof(val), "%d", getHandle()); res += val; - + return res; } // toString @@ -213,10 +216,10 @@ std::string NimBLERemoteDescriptor::toString() { */ int NimBLERemoteDescriptor::onWriteCB(uint16_t conn_handle, const struct ble_gatt_error *error, - struct ble_gatt_attr *attr, void *arg) + struct ble_gatt_attr *attr, void *arg) { NimBLERemoteDescriptor* descriptor = (NimBLERemoteDescriptor*)arg; - + // Make sure the discovery is for this device if(descriptor->getRemoteCharacteristic()->getRemoteService()->getClient()->getConnId() != conn_handle){ 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) { NIMBLE_LOGD(LOG_TAG, ">> Descriptor writeValue: %s", toString().c_str()); - + NimBLEClient* pClient = getRemoteCharacteristic()->getRemoteService()->getClient(); - + int rc = 0; int retryCount = 1; uint16_t mtu; - + // Check to see that we are connected. if (!pClient->isConnected()) { NIMBLE_LOGE(LOG_TAG, "Disconnected"); return false; } - + mtu = ble_att_mtu(pClient->getConnId()) - 3; // 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); return (rc == 0); } - + do { m_semaphoreDescWrite.take("WriteDescriptor"); - + if(length > mtu) { NIMBLE_LOGI(LOG_TAG,"long write %d bytes", 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(); return false; } - + rc = m_semaphoreDescWrite.wait("WriteDescriptor"); switch(rc){ @@ -295,13 +298,13 @@ bool NimBLERemoteDescriptor::writeValue(const uint8_t* data, size_t length, bool retryCount++; length = mtu; break; - + 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_ENC): if (retryCount && pClient->secureConnection()) break; - /* Else falls through. */ + /* Else falls through. */ default: return false; } @@ -339,4 +342,6 @@ void NimBLERemoteDescriptor::releaseSemaphores() { m_semaphoreDescWrite.give(1); m_semaphoreReadDescrEvt.give(1); } + +#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) #endif /* CONFIG_BT_ENABLED */ diff --git a/src/NimBLERemoteDescriptor.h b/src/NimBLERemoteDescriptor.h index 9f9f32b..4763292 100644 --- a/src/NimBLERemoteDescriptor.h +++ b/src/NimBLERemoteDescriptor.h @@ -3,7 +3,7 @@ * * Created: on Jan 27 2020 * Author H2zero - * + * * Originally: * * BLERemoteDescriptor.h @@ -17,6 +17,9 @@ #include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) +#include "nimconfig.h" +#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) + #include "NimBLERemoteCharacteristic.h" class NimBLERemoteCharacteristic; @@ -54,5 +57,7 @@ private: }; + +#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) #endif /* CONFIG_BT_ENABLED */ #endif /* COMPONENTS_NIMBLEREMOTEDESCRIPTOR_H_ */ diff --git a/src/NimBLERemoteService.cpp b/src/NimBLERemoteService.cpp index 43c1085..1832793 100644 --- a/src/NimBLERemoteService.cpp +++ b/src/NimBLERemoteService.cpp @@ -3,7 +3,7 @@ * * Created: on Jan 27 2020 * Author H2zero - * + * * Originally: * * BLERemoteService.cpp @@ -14,6 +14,9 @@ #include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) +#include "nimconfig.h" +#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) + #include "NimBLERemoteService.h" #include "NimBLEUtils.h" #include "NimBLEDevice.h" @@ -25,19 +28,19 @@ static const char* LOG_TAG = "NimBLERemoteService"; * @brief Remote Service constructor. * @param [in] Reference to the client this belongs to. * @param [in] Refernce to the structure with the services' information. - */ + */ NimBLERemoteService::NimBLERemoteService(NimBLEClient* pClient, const struct ble_gatt_svc* service) { NIMBLE_LOGD(LOG_TAG, ">> BLERemoteService()"); m_pClient = pClient; switch (service->uuid.u.type) { - case BLE_UUID_TYPE_16: + case BLE_UUID_TYPE_16: m_uuid = NimBLEUUID(service->uuid.u16.value); break; - case BLE_UUID_TYPE_32: + case BLE_UUID_TYPE_32: m_uuid = NimBLEUUID(service->uuid.u32.value); break; - case BLE_UUID_TYPE_128: + case BLE_UUID_TYPE_128: m_uuid = NimBLEUUID(const_cast(&service->uuid.u128)); break; 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. * Also release any semaphores they may be holding. - */ + */ NimBLERemoteService::~NimBLERemoteService() { removeCharacteristics(); } @@ -65,12 +68,12 @@ NimBLERemoteService::~NimBLERemoteService() { * @brief Get the remote characteristic object for the characteristic UUID. * @param [in] uuid Remote characteristic uuid. * @return Reference to the remote characteristic object. - */ + */ NimBLERemoteCharacteristic* NimBLERemoteService::getCharacteristic(const char* uuid) { return getCharacteristic(NimBLEUUID(uuid)); } // getCharacteristic - + /** * @brief Get the characteristic object for the UUID. * @param [in] uuid Characteristic uuid. @@ -93,12 +96,12 @@ NimBLERemoteCharacteristic* NimBLERemoteService::getCharacteristic(const NimBLEU /** * @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_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); - + NimBLERemoteService *service = (NimBLERemoteService*)arg; int rc=0; @@ -106,7 +109,7 @@ int NimBLERemoteService::characteristicDiscCB(uint16_t conn_handle, if(service->getClient()->getConnId() != conn_handle){ return 0; } - + switch (error->status) { case 0: { // Found a service - add it to the map @@ -147,12 +150,12 @@ int NimBLERemoteService::characteristicDiscCB(uint16_t conn_handle, */ bool NimBLERemoteService::retrieveCharacteristics() { NIMBLE_LOGD(LOG_TAG, ">> retrieveCharacteristics() for service: %s", getUUID().toString().c_str()); - + int rc = 0; //removeCharacteristics(); // Forget any previous characteristics. - + m_semaphoreGetCharEvt.take("retrieveCharacteristics"); - + rc = ble_gattc_disc_all_chrs(m_pClient->getConnId(), m_startHandle, m_endHandle, @@ -164,7 +167,7 @@ bool NimBLERemoteService::retrieveCharacteristics() { m_semaphoreGetCharEvt.give(); return false; } - + m_haveCharacteristics = (m_semaphoreGetCharEvt.wait("retrieveCharacteristics") == 0); if(m_haveCharacteristics){ 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()); // 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 - + // Make sure we don't go past the service end handle 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()); - + endHdl = (*it).second->getDefHandle()-1; } - else{ + else{ NIMBLE_LOGD(LOG_TAG, "END CHARS"); endHdl = m_endHandle; } --it; - + //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(!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, "<< retrieveCharacteristics()"); return true; } - + NIMBLE_LOGE(LOG_TAG, "Could not retrieve characteristics"); return false; - + } // retrieveCharacteristics @@ -263,10 +266,10 @@ NimBLEUUID NimBLERemoteService::getUUID() { */ std::string NimBLERemoteService::getValue(const NimBLEUUID &characteristicUuid) { NIMBLE_LOGD(LOG_TAG, ">> readValue: uuid: %s", characteristicUuid.toString().c_str()); - + std::string ret = ""; NimBLERemoteCharacteristic* pChar = getCharacteristic(characteristicUuid); - + if(pChar != nullptr) { ret = pChar->readValue(); } @@ -284,10 +287,10 @@ std::string NimBLERemoteService::getValue(const NimBLEUUID &characteristicUuid) */ bool NimBLERemoteService::setValue(const NimBLEUUID &characteristicUuid, const std::string &value) { NIMBLE_LOGD(LOG_TAG, ">> setValue: uuid: %s", characteristicUuid.toString().c_str()); - + bool ret = false; NimBLERemoteCharacteristic* pChar = getCharacteristic(characteristicUuid); - + if(pChar != nullptr) { ret = pChar->writeValue(value); } @@ -306,12 +309,12 @@ bool NimBLERemoteService::setValue(const NimBLEUUID &characteristicUuid, const s */ void NimBLERemoteService::removeCharacteristics() { m_characteristicMap.clear(); // Clear the map - + for (auto &myPair : m_characteristicMapByHandle) { delete myPair.second; } m_characteristicMapByHandle.clear(); // Clear the map - + } // removeCharacteristics @@ -334,7 +337,7 @@ std::string NimBLERemoteService::toString() { snprintf(val, sizeof(val), "%04x", m_endHandle); res += " 0x"; res += val; - + for (auto &myPair : m_characteristicMap) { 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. - * 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() { for (auto &cPair : m_characteristicMapByHandle) { @@ -354,4 +357,5 @@ void NimBLERemoteService::releaseSemaphores() { m_semaphoreGetCharEvt.give(1); } +#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) #endif /* CONFIG_BT_ENABLED */ diff --git a/src/NimBLERemoteService.h b/src/NimBLERemoteService.h index a88a74e..c893e07 100644 --- a/src/NimBLERemoteService.h +++ b/src/NimBLERemoteService.h @@ -3,7 +3,7 @@ * * Created: on Jan 27 2020 * Author H2zero - * + * * Originally: * * BLERemoteService.h @@ -17,6 +17,9 @@ #include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) +#include "nimconfig.h" +#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) + #include "NimBLEClient.h" #include "NimBLEUUID.h" #include "FreeRTOS.h" @@ -52,7 +55,7 @@ public: private: // 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 friend class NimBLEClient; @@ -60,7 +63,7 @@ private: // Private methods 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_chr *chr, void *arg); @@ -85,5 +88,6 @@ private: uint16_t m_endHandle; // The ending handle of this service. }; // BLERemoteService +#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) #endif /* CONFIG_BT_ENABLED */ #endif /* COMPONENTS_NIMBLEREMOTESERVICE_H_ */ diff --git a/src/NimBLEScan.cpp b/src/NimBLEScan.cpp index c15e1fe..49d94da 100644 --- a/src/NimBLEScan.cpp +++ b/src/NimBLEScan.cpp @@ -3,7 +3,7 @@ * * Created: on Jan 24 2020 * Author H2zero - * + * * Originally: * * BLEScan.cpp @@ -14,6 +14,9 @@ #include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) +#include "nimconfig.h" +#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) + #include "NimBLEScan.h" #include "NimBLEUtils.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 * resolvable private address. */ - + //#define BLE_HCI_SCAN_FILT_NO_WL (0) //#define BLE_HCI_SCAN_FILT_USE_WL (1) //#define BLE_HCI_SCAN_FILT_NO_WL_INITA (2) @@ -76,33 +79,33 @@ NimBLEScan::NimBLEScan() { * @param [in] param Parameter data for this event. */ /*STATIC*/int NimBLEScan::handleGapEvent(ble_gap_event* event, void* arg) { - + NimBLEScan* pScan = (NimBLEScan*)arg; struct ble_hs_adv_fields fields; int rc = 0; - + switch(event->type) { case BLE_GAP_EVENT_DISC: { - if(pScan->m_stopped) { - NIMBLE_LOGE(LOG_TAG, "Scan stop called, ignoring results."); - return 0; - } - + if(pScan->m_stopped) { + NIMBLE_LOGE(LOG_TAG, "Scan stop called, ignoring results."); + return 0; + } + rc = ble_hs_adv_parse_fields(&fields, event->disc.data, event->disc.length_data); if (rc != 0) { NIMBLE_LOGE(LOG_TAG, "Gap Event Parse ERROR."); return 0; } - + NimBLEAddress advertisedAddress(event->disc.addr); // Print advertisement data // print_adv_fields(&fields); // If we are not scanning, nothing to do with the extra results. - if (pScan->m_stopped) { + if (pScan->m_stopped) { return 0; } @@ -111,9 +114,9 @@ NimBLEScan::NimBLEScan() { NIMBLE_LOGI(LOG_TAG, "Ignoring device: address: %s", advertisedAddress.toString().c_str()); return 0; } - - NimBLEAdvertisedDevice* advertisedDevice = nullptr; - + + NimBLEAdvertisedDevice* advertisedDevice = nullptr; + // 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()); if(it != pScan->m_scanResults.m_advertisedDevicesMap.cend()) { @@ -134,7 +137,7 @@ NimBLEScan::NimBLEScan() { else{ 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->setScan(pScan); advertisedDevice->setAdvertisementResult(event->disc.data, event->disc.length_data); @@ -155,13 +158,13 @@ NimBLEScan::NimBLEScan() { case BLE_GAP_EVENT_DISC_COMPLETE: { NIMBLE_LOGD(LOG_TAG, "discovery complete; reason=%d", event->disc_complete.reason); - + if (pScan->m_scanCompleteCB != nullptr) { pScan->m_scanCompleteCB(pScan->m_scanResults); } - + pScan->m_stopped = true; - pScan->m_semaphoreScanEnd.give(); + pScan->m_semaphoreScanEnd.give(); return 0; } @@ -224,13 +227,13 @@ void NimBLEScan::setWindow(uint16_t windowMSecs) { */ bool NimBLEScan::start(uint32_t duration, void (*scanCompleteCB)(NimBLEScanResults), bool is_continue) { NIMBLE_LOGD(LOG_TAG, ">> start(duration=%d)", duration); - + // If Host is not synced we cannot start scanning. if(!NimBLEDevice::m_synced) { NIMBLE_LOGC(LOG_TAG, "Host reset, wait for sync."); return false; } - + if(ble_gap_conn_active()) { NIMBLE_LOGE(LOG_TAG, "Connection in progress - must wait."); return false; @@ -244,12 +247,12 @@ bool NimBLEScan::start(uint32_t duration, void (*scanCompleteCB)(NimBLEScanResul m_stopped = false; m_semaphoreScanEnd.take("start"); - + // 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. m_duration = duration; - + // If 0 duration specified then we assume a continuous scan is desired. if(duration == 0){ duration = BLE_HS_FOREVER; @@ -257,22 +260,22 @@ bool NimBLEScan::start(uint32_t duration, void (*scanCompleteCB)(NimBLEScanResul else{ duration = duration*1000; // convert duration to milliseconds } - + // 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 if(!is_continue) { clearResults(); } - + int rc = 0; - do{ - rc = ble_gap_disc(m_own_addr_type, duration, &m_scan_params, + do{ + rc = ble_gap_disc(m_own_addr_type, duration, &m_scan_params, NimBLEScan::handleGapEvent, this); if(rc == BLE_HS_EBUSY) { vTaskDelay(2); } } while(rc == BLE_HS_EBUSY); - + if (rc != 0 && rc != BLE_HS_EDONE) { NIMBLE_LOGE(LOG_TAG, "Error initiating GAP discovery procedure; rc=%d, %s", rc, NimBLEUtils::returnCodeToString(rc)); @@ -305,7 +308,7 @@ NimBLEScanResults NimBLEScan::start(uint32_t duration, bool is_continue) { */ void NimBLEScan::stop() { NIMBLE_LOGD(LOG_TAG, ">> stop()"); - + int rc = ble_gap_disc_cancel(); if (rc != 0 && rc != BLE_HS_EALREADY) { NIMBLE_LOGE(LOG_TAG, "Failed to cancel scan; rc=%d\n", rc); @@ -313,13 +316,13 @@ void NimBLEScan::stop() { } m_stopped = true; - + if (m_scanCompleteCB != nullptr) { m_scanCompleteCB(m_scanResults); } - + m_semaphoreScanEnd.give(); - + NIMBLE_LOGD(LOG_TAG, "<< stop()"); } // stop @@ -400,4 +403,5 @@ NimBLEAdvertisedDevice NimBLEScanResults::getDevice(uint32_t i) { return dev; } +#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) #endif /* CONFIG_BT_ENABLED */ diff --git a/src/NimBLEScan.h b/src/NimBLEScan.h index cdcbdc7..cb453fd 100644 --- a/src/NimBLEScan.h +++ b/src/NimBLEScan.h @@ -3,7 +3,7 @@ * * Created: on Jan 24 2020 * Author H2zero - * + * * Originally: * * BLEScan.h @@ -16,6 +16,9 @@ #include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) +#include "nimconfig.h" +#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) + #include "NimBLEAdvertisedDevice.h" #include "FreeRTOS.h" @@ -63,14 +66,14 @@ public: void clearResults(); NimBLEScanResults getResults(); void erase(const NimBLEAddress &address); - - + + private: NimBLEScan(); friend class NimBLEDevice; static int handleGapEvent(ble_gap_event* event, void* arg); void onHostReset(); - + NimBLEAdvertisedDeviceCallbacks* m_pAdvertisedDeviceCallbacks = nullptr; void (*m_scanCompleteCB)(NimBLEScanResults scanResults); ble_gap_disc_params m_scan_params; @@ -82,6 +85,6 @@ private: uint32_t m_duration; }; - +#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) #endif /* CONFIG_BT_ENABLED */ #endif /* COMPONENTS_NIMBLE_SCAN_H_ */ diff --git a/src/NimBLESecurity.cpp b/src/NimBLESecurity.cpp index 0651858..8a0dbd9 100644 --- a/src/NimBLESecurity.cpp +++ b/src/NimBLESecurity.cpp @@ -3,7 +3,7 @@ * * Created: on Feb 22 2020 * Author H2zero - * + * * Originally: * * BLESecurity.cpp @@ -73,7 +73,7 @@ void NimBLESecurity::setRespEncryptionKey(uint8_t resp_key) { * */ void NimBLESecurity::setKeySize(uint8_t key_size) { - + //m_keySize = key_size; //esp_ble_gap_set_security_param(ESP_BLE_SM_MAX_KEY_SIZE, &m_keySize, sizeof(uint8_t)); } //setKeySize @@ -132,7 +132,7 @@ char* BLESecurity::esp_key_type_to_str(esp_ble_key_type_t key_type) { break; } return key_str; - + } // esp_key_type_to_str */ #endif // CONFIG_BT_ENABLED diff --git a/src/NimBLESecurity.h b/src/NimBLESecurity.h index 60e4f44..50c732c 100644 --- a/src/NimBLESecurity.h +++ b/src/NimBLESecurity.h @@ -3,7 +3,7 @@ * * Created: on Feb 22 2020 * Author H2zero - * + * * Originally: * * BLESecurity.h @@ -12,8 +12,8 @@ * Author: chegewara */ -/** This class exists for backward compatibility - Should not be used in new code - * See the security functions in NimBLEDevice and callbacks in NimBLEServer / NimBLEClient +/** This class exists for backward compatibility - Should not be used in new code + * See the security functions in NimBLEDevice and callbacks in NimBLEServer / NimBLEClient */ #ifndef COMPONENTS_NIMBLESECURITY_H_ diff --git a/src/NimBLEServer.cpp b/src/NimBLEServer.cpp index 25e551f..d731bad 100644 --- a/src/NimBLEServer.cpp +++ b/src/NimBLEServer.cpp @@ -3,7 +3,7 @@ * * Created: on March 2, 2020 * Author H2zero - * + * * Originally: * * BLEServer.cpp @@ -15,6 +15,9 @@ #include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) +#include "nimconfig.h" +#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) + #include "NimBLEServer.h" #include "NimBLE2902.h" #include "NimBLEUtils.h" @@ -32,10 +35,10 @@ static NimBLEServerCallbacks defaultCallbacks; * the BLEDevice class. */ NimBLEServer::NimBLEServer() { - m_connId = BLE_HS_CONN_HANDLE_NONE; + m_connId = BLE_HS_CONN_HANDLE_NONE; m_svcChgChrHdl = 0xffff; - m_pServerCallbacks = &defaultCallbacks; - m_gattsStarted = false; + m_pServerCallbacks = &defaultCallbacks; + m_gattsStarted = false; } // BLEServer @@ -48,7 +51,7 @@ NimBLEServer::NimBLEServer() { * @return A reference to the new service object. */ 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. */ 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. - 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.", - uuid.toString().c_str()); - } + // Check that a service with the supplied UUID does not already exist. + 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.", + uuid.toString().c_str()); + } - NimBLEService* pService = new NimBLEService(uuid, numHandles, this); - pService->m_instId = inst_id; - m_serviceMap.setByUUID(uuid, pService); // Save a reference to this service being on this server. + NimBLEService* pService = new NimBLEService(uuid, numHandles, this); + pService->m_instId = inst_id; + m_serviceMap.setByUUID(uuid, pService); // Save a reference to this service being on this server. - NIMBLE_LOGD(LOG_TAG, "<< createService"); - return pService; + NIMBLE_LOGD(LOG_TAG, "<< createService"); + return pService; } // createService @@ -86,7 +89,7 @@ NimBLEService* NimBLEServer::createService(const NimBLEUUID &uuid, uint32_t numH * @return A reference to the service object. */ 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. */ 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. */ NimBLEAdvertising* NimBLEServer::getAdvertising() { - return BLEDevice::getAdvertising(); + return BLEDevice::getAdvertising(); } @@ -116,58 +119,58 @@ NimBLEAdvertising* NimBLEServer::getAdvertising() { * @return Client connection id. */ 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. */ void NimBLEServer::start() { - if(m_gattsStarted) { - NIMBLE_LOGW(LOG_TAG, "Gatt server already started"); - return; - } - + if(m_gattsStarted) { + NIMBLE_LOGW(LOG_TAG, "Gatt server already started"); + return; + } + int rc = ble_gatts_start(); 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)); 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(); -#endif +#endif ble_uuid16_t svc = {BLE_UUID_TYPE_16, 0x1801}; 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) { - 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)); abort(); } - + NIMBLE_LOGI(LOG_TAG, "Service changed characterisic handle: %d", m_svcChgChrHdl); - + // Build a map of characteristics with Notify / Indicate capabilities for event handling uint8_t numSvcs = m_serviceMap.getRegisteredServiceCount(); NimBLEService* pService = m_serviceMap.getFirst(); - + for(int i = 0; i < numSvcs; i++) { - uint8_t numChrs = pService->m_characteristicMap.getSize(); - NimBLECharacteristic* pChr = pService->m_characteristicMap.getFirst(); - + uint8_t numChrs = pService->m_characteristicMap.getSize(); + NimBLECharacteristic* pChr = pService->m_characteristicMap.getFirst(); + if(pChr != nullptr) { for( int d = 0; d < numChrs; d++) { // if Notify / Indicate is enabled but we didn't create the descriptor // 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)) { - + if(nullptr == pChr->getDescriptorByUUID("2902")) { pChr->createDescriptor("2902"); } @@ -179,8 +182,8 @@ void NimBLEServer::start() { } 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) { NIMBLE_LOGD(LOG_TAG, ">> disconnect()"); - + int rc = ble_gap_terminate(connId, reason); 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)); } - + return rc; NIMBLE_LOGD(LOG_TAG, "<< disconnect()"); } @@ -209,7 +212,7 @@ int NimBLEServer::disconnect(uint16_t connId, uint8_t reason) { * @return The number of connected clients. */ uint32_t NimBLEServer::getConnectedCount() { - return m_connectedServersMap.size(); + return m_connectedServersMap.size(); } // getConnectedCount @@ -222,15 +225,15 @@ uint32_t NimBLEServer::getConnectedCount() { * */ /*STATIC*/int NimBLEServer::handleGapEvent(struct ble_gap_event *event, void *arg) { - NimBLEServer* server = (NimBLEServer*)arg; - NIMBLE_LOGD(LOG_TAG, ">> handleGapEvent: %s", - NimBLEUtils::gapEventToString(event->type)); + NimBLEServer* server = (NimBLEServer*)arg; + NIMBLE_LOGD(LOG_TAG, ">> handleGapEvent: %s", + NimBLEUtils::gapEventToString(event->type)); int rc = 0; struct ble_gap_conn_desc desc; - - switch(event->type) { - - case BLE_GAP_EVENT_CONNECT: { + + switch(event->type) { + + case BLE_GAP_EVENT_CONNECT: { if (event->connect.status != 0) { /* Connection failed; resume advertising */ NIMBLE_LOGC(LOG_TAG, "Connection failed"); @@ -240,21 +243,21 @@ uint32_t NimBLEServer::getConnectedCount() { else { server->m_connId = event->connect.conn_handle; server->addPeerDevice((void*)server, false, server->m_connId); - + ble_gap_conn_desc desc; rc = ble_gap_conn_find(event->connect.conn_handle, &desc); assert(rc == 0); - + server->m_pServerCallbacks->onConnect(server); - server->m_pServerCallbacks->onConnect(server, &desc); + server->m_pServerCallbacks->onConnect(server, &desc); } return 0; - } // BLE_GAP_EVENT_CONNECT - - + } // BLE_GAP_EVENT_CONNECT + + 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. switch(event->disconnect.reason) { 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); NimBLEDevice::onReset(event->disconnect.reason); break; - default: + default: break; } - + 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); - + return 0; } // BLE_GAP_EVENT_DISCONNECT - + case BLE_GAP_EVENT_SUBSCRIBE: { NIMBLE_LOGI(LOG_TAG, "subscribe event; cur_notify=%d\n value handle; " "val_handle=%d\n", event->subscribe.cur_notify, event->subscribe.attr_handle); - + auto it = server->m_notifyChrMap.find(event->subscribe.attr_handle); if(it != server->m_notifyChrMap.cend()) { (*it).second->setSubscribe(event); @@ -287,7 +290,7 @@ uint32_t NimBLEServer::getConnectedCount() { return 0; } // BLE_GAP_EVENT_SUBSCRIBE - + case BLE_GAP_EVENT_MTU: { NIMBLE_LOGI(LOG_TAG, "mtu update event; conn_handle=%d mtu=%d", event->mtu.conn_handle, @@ -295,7 +298,7 @@ uint32_t NimBLEServer::getConnectedCount() { server->updatePeerMTU(event->mtu.conn_handle, event->mtu.value); return 0; } // BLE_GAP_EVENT_MTU - + case BLE_GAP_EVENT_NOTIFY_TX: { if(event->notify_tx.indication && event->notify_tx.status != 0) { 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); } } - + return 0; } // BLE_GAP_EVENT_NOTIFY_TX - + case BLE_GAP_EVENT_CONN_UPDATE: { NIMBLE_LOGD(LOG_TAG, "Connection parameters updated."); return 0; } // BLE_GAP_EVENT_CONN_UPDATE - + case BLE_GAP_EVENT_REPEAT_PAIRING: { /* We already have a bond with the peer, but it is attempting to * establish a new secure link. This app sacrifices security for @@ -328,8 +331,8 @@ uint32_t NimBLEServer::getConnectedCount() { */ return BLE_GAP_REPEAT_PAIRING_RETRY; } // 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); if(rc != 0) { return BLE_ATT_ERR_INVALID_HANDLE; @@ -341,10 +344,10 @@ uint32_t NimBLEServer::getConnectedCount() { } else { server->m_pServerCallbacks->onAuthenticationComplete(&desc); } - + return 0; } // BLE_GAP_EVENT_ENC_CHANGE - + case BLE_GAP_EVENT_PASSKEY_ACTION: { struct ble_sm_io pkey = {0}; @@ -359,7 +362,7 @@ uint32_t NimBLEServer::getConnectedCount() { } 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); - + } else if (event->passkey.params.action == BLE_SM_IOACT_NUMCMP) { NIMBLE_LOGD(LOG_TAG, "Passkey on device's display: %d", event->passkey.params.numcmp); pkey.action = event->passkey.params.action; @@ -370,11 +373,11 @@ uint32_t NimBLEServer::getConnectedCount() { } else { pkey.numcmp_accept = server->m_pServerCallbacks->onConfirmPIN(event->passkey.params.numcmp); } - + 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); - - //TODO: Handle out of band pairing + + //TODO: Handle out of band pairing } else if (event->passkey.params.action == BLE_SM_IOACT_OOB) { static uint8_t tem_oob[16] = {0}; pkey.action = event->passkey.params.action; @@ -383,35 +386,35 @@ uint32_t NimBLEServer::getConnectedCount() { } 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); - ////////////////////////////////// + ////////////////////////////////// } else if (event->passkey.params.action == BLE_SM_IOACT_INPUT) { NIMBLE_LOGD(LOG_TAG, "Enter the passkey"); pkey.action = event->passkey.params.action; - + // Compatibility only - Do not use, should be removed the in future if(NimBLEDevice::m_securityCallbacks != nullptr) { pkey.passkey = NimBLEDevice::m_securityCallbacks->onPassKeyRequest(); ///////////////////////////////////////////// } else { pkey.passkey = server->m_pServerCallbacks->onPassKeyRequest(); - } + } 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); - + } else if (event->passkey.params.action == BLE_SM_IOACT_NONE) { NIMBLE_LOGD(LOG_TAG, "No passkey action required"); } - + NIMBLE_LOGD(LOG_TAG, "<< handleGATTServerEvent"); return 0; } // BLE_GAP_EVENT_PASSKEY_ACTION - default: - break; - } + default: + break; + } - NIMBLE_LOGD(LOG_TAG, "<< handleGATTServerEvent"); + NIMBLE_LOGD(LOG_TAG, "<< handleGATTServerEvent"); return 0; } // handleGATTServerEvent @@ -427,10 +430,10 @@ uint32_t NimBLEServer::getConnectedCount() { */ void NimBLEServer::setCallbacks(NimBLEServerCallbacks* pCallbacks) { if (pCallbacks != nullptr){ - m_pServerCallbacks = pCallbacks; - } else { - m_pServerCallbacks = &defaultCallbacks; - } + m_pServerCallbacks = pCallbacks; + } else { + m_pServerCallbacks = &defaultCallbacks; + } } // setCallbacks @@ -439,9 +442,9 @@ void NimBLEServer::setCallbacks(NimBLEServerCallbacks* pCallbacks) { */ /* void BLEServer::removeService(BLEService* service) { - service->stop(); - service->executeDelete(); - m_serviceMap.removeService(service); + service->stop(); + service->executeDelete(); + m_serviceMap.removeService(service); } */ @@ -453,9 +456,9 @@ void BLEServer::removeService(BLEService* service) { * retrieving the advertising object and invoking start upon it. */ void NimBLEServer::startAdvertising() { - NIMBLE_LOGD(LOG_TAG, ">> startAdvertising"); - NimBLEDevice::startAdvertising(); - NIMBLE_LOGD(LOG_TAG, "<< startAdvertising"); + NIMBLE_LOGD(LOG_TAG, ">> startAdvertising"); + NimBLEDevice::startAdvertising(); + NIMBLE_LOGD(LOG_TAG, "<< startAdvertising"); } // startAdvertising @@ -463,51 +466,51 @@ void NimBLEServer::startAdvertising() { * @brief Stop advertising. */ void NimBLEServer::stopAdvertising() { - NIMBLE_LOGD(LOG_TAG, ">> stopAdvertising"); - NimBLEDevice::stopAdvertising(); - NIMBLE_LOGD(LOG_TAG, "<< stopAdvertising"); + NIMBLE_LOGD(LOG_TAG, ">> stopAdvertising"); + NimBLEDevice::stopAdvertising(); + NIMBLE_LOGD(LOG_TAG, "<< stopAdvertising"); } // startAdvertising - + /** * Allow to connect GATT server to peer device * Probably can be used in ANCS for iPhone */ /* bool BLEServer::connect(BLEAddress address) { - esp_bd_addr_t addr; - memcpy(&addr, address.getNative(), 6); - // Perform the open connection request against the target BLE Server. - m_semaphoreOpenEvt.take("connect"); - esp_err_t errRc = ::esp_ble_gatts_open( - getGattsIf(), - addr, // address - 1 // direct connection - ); - if (errRc != ESP_OK) { - ESP_LOGE(LOG_TAG, "esp_ble_gattc_open: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); - return false; - } + esp_bd_addr_t addr; + memcpy(&addr, address.getNative(), 6); + // Perform the open connection request against the target BLE Server. + m_semaphoreOpenEvt.take("connect"); + esp_err_t errRc = ::esp_ble_gatts_open( + getGattsIf(), + addr, // address + 1 // direct connection + ); + if (errRc != ESP_OK) { + ESP_LOGE(LOG_TAG, "esp_ble_gattc_open: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); + return false; + } - uint32_t rc = m_semaphoreOpenEvt.wait("connect"); // Wait for the connection to complete. - ESP_LOGD(LOG_TAG, "<< connect(), rc=%d", rc==ESP_GATT_OK); - return rc == ESP_GATT_OK; + uint32_t rc = m_semaphoreOpenEvt.wait("connect"); // Wait for the connection to complete. + ESP_LOGD(LOG_TAG, "<< connect(), rc=%d", rc==ESP_GATT_OK); + return rc == ESP_GATT_OK; } // connect */ void NimBLEServerCallbacks::onConnect(NimBLEServer* pServer) { - NIMBLE_LOGD("NimBLEServerCallbacks", "onConnect(): Default"); + NIMBLE_LOGD("NimBLEServerCallbacks", "onConnect(): Default"); } // onConnect void NimBLEServerCallbacks::onConnect(NimBLEServer* pServer, ble_gap_conn_desc* desc) { - NIMBLE_LOGD("NimBLEServerCallbacks", "onConnect(): Default"); + NIMBLE_LOGD("NimBLEServerCallbacks", "onConnect(): Default"); } // onConnect void NimBLEServerCallbacks::onDisconnect(NimBLEServer* pServer) { - NIMBLE_LOGD("NimBLEServerCallbacks", "onDisconnect(): Default"); + NIMBLE_LOGD("NimBLEServerCallbacks", "onDisconnect(): Default"); } // onDisconnect uint32_t NimBLEServerCallbacks::onPassKeyRequest(){ @@ -533,14 +536,14 @@ bool NimBLEServerCallbacks::onConfirmPIN(uint32_t pin){ /* multi connect support */ void NimBLEServer::updatePeerMTU(uint16_t conn_id, uint16_t mtu) { - const std::map::iterator it = m_connectedServersMap.find(conn_id); - if (it != m_connectedServersMap.end()) { - it->second.mtu = mtu; - } + const std::map::iterator it = m_connectedServersMap.find(conn_id); + if (it != m_connectedServersMap.end()) { + it->second.mtu = mtu; + } } std::map 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) { - conn_status_t status = { - .peer_device = peer, - .connected = true, - .mtu = 23 - }; + conn_status_t status = { + .peer_device = peer, + .connected = true, + .mtu = 23 + }; - m_connectedServersMap.insert(std::pair(conn_id, status)); + m_connectedServersMap.insert(std::pair(conn_id, status)); } void NimBLEServer::removePeerDevice(uint16_t conn_id, bool _client) { - m_connectedServersMap.erase(conn_id); + m_connectedServersMap.erase(conn_id); } /* 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 */ -void NimBLEServer::updateConnParams(uint16_t conn_handle, - uint16_t minInterval, uint16_t maxInterval, +void NimBLEServer::updateConnParams(uint16_t conn_handle, + uint16_t minInterval, uint16_t maxInterval, 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.itvl_max = maxInterval; // max_int = 0x20*1.25ms = 40ms - params.itvl_min = minInterval; // min_int = 0x10*1.25ms = 20ms - params.supervision_timeout = timeout; // timeout = 400*10ms = 4000ms + params.latency = latency; + params.itvl_max = maxInterval; // max_int = 0x20*1.25ms = 40ms + params.itvl_min = minInterval; // min_int = 0x10*1.25ms = 20ms + params.supervision_timeout = timeout; // timeout = 400*10ms = 4000ms 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 - + int rc = ble_gap_update_params(conn_handle, ¶ms); if(rc != 0) { 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) { (*it).second->m_semaphoreConfEvt.give(0); } - + } */ + +#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #endif // CONFIG_BT_ENABLED diff --git a/src/NimBLEServer.h b/src/NimBLEServer.h index eabc348..903eb23 100644 --- a/src/NimBLEServer.h +++ b/src/NimBLEServer.h @@ -3,7 +3,7 @@ * * Created: on March 2, 2020 * Author H2zero - * + * * Originally: * * BLEServer.h @@ -17,6 +17,9 @@ #include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) +#include "nimconfig.h" +#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) + #include "NimBLEAddress.h" #include "NimBLEUUID.h" #include "NimBLEAdvertising.h" @@ -24,14 +27,13 @@ #include "NimBLESecurity.h" #include "FreeRTOS.h" - #include class NimBLEService; class NimBLECharacteristic; class NimBLEServerCallbacks; -/* TODO possibly refactor this struct */ +/* TODO possibly refactor this struct */ typedef struct { void *peer_device; // peer device BLEClient or BLEServer - maybe its better to have 2 structures or union here bool connected; // do we need it? @@ -45,7 +47,7 @@ typedef struct { class NimBLEServiceMap { public: // 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); // void setByHandle(uint16_t handle, NimBLEService* service); void setByUUID(const char* uuid, NimBLEService* service); @@ -69,7 +71,7 @@ private: class NimBLEServer { public: 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); NimBLEAdvertising* getAdvertising(); void setCallbacks(NimBLEServerCallbacks* pCallbacks); @@ -81,8 +83,8 @@ public: NimBLEService* getServiceByUUID(const NimBLEUUID &uuid); int disconnect(uint16_t connID, uint8_t reason = BLE_ERR_REM_USER_CONN_TERM); // bool connect(BLEAddress address); - void updateConnParams(uint16_t conn_handle, - uint16_t minInterval, uint16_t maxInterval, + void updateConnParams(uint16_t conn_handle, + uint16_t minInterval, uint16_t maxInterval, uint16_t latency, uint16_t timeout, uint16_t minConnTime=0, uint16_t maxConnTime=0); @@ -106,15 +108,15 @@ private: // BLEAdvertising m_bleAdvertising; uint16_t m_connId; uint16_t m_svcChgChrHdl; - bool m_gattsStarted; - + bool m_gattsStarted; + std::map m_connectedServersMap; std::map m_notifyChrMap; NimBLEServiceMap m_serviceMap; NimBLEServerCallbacks* m_pServerCallbacks; - static int handleGapEvent(struct ble_gap_event *event, void *arg); + static int handleGapEvent(struct ble_gap_event *event, void *arg); }; // NimBLEServer @@ -141,7 +143,7 @@ public: * @param [in] pServer A reference to the %BLE server that received the existing client disconnection. */ virtual void onDisconnect(NimBLEServer* pServer); - + virtual uint32_t onPassKeyRequest(); //{return 0;} virtual void onPassKeyNotify(uint32_t pass_key); //{} virtual bool onSecurityRequest(); //{return true;} @@ -150,5 +152,6 @@ public: }; // BLEServerCallbacks +#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #endif /* CONFIG_BT_ENABLED */ #endif /* MAIN_NIMBLESERVER_H_ */ diff --git a/src/NimBLEService.cpp b/src/NimBLEService.cpp index 60887d7..6036a38 100644 --- a/src/NimBLEService.cpp +++ b/src/NimBLEService.cpp @@ -3,7 +3,7 @@ * * Created: on March 2, 2020 * Author H2zero - * + * * Originally: * * BLEService.cpp @@ -17,6 +17,9 @@ #include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) +#include "nimconfig.h" +#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) + #include "NimBLEService.h" #include "NimBLEUtils.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] 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) { } @@ -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. */ NimBLEService::NimBLEService(const NimBLEUUID &uuid, uint16_t numHandles, NimBLEServer* pServer) { - m_uuid = uuid; - m_handle = NULL_HANDLE; - m_pServer = pServer; - m_numHandles = numHandles; + m_uuid = uuid; + m_handle = NULL_HANDLE; + m_pServer = pServer; + m_numHandles = numHandles; } // NimBLEService @@ -56,10 +59,10 @@ NimBLEService::NimBLEService(const NimBLEUUID &uuid, uint16_t numHandles, NimBLE * @return N/A. */ void NimBLEService::dump() { - NIMBLE_LOGD(LOG_TAG, "Service: uuid:%s, handle: 0x%.2x", - m_uuid.toString().c_str(), - m_handle); - NIMBLE_LOGD(LOG_TAG, "Characteristics:\n%s", m_characteristicMap.toString().c_str()); + NIMBLE_LOGD(LOG_TAG, "Service: uuid:%s, handle: 0x%.2x", + m_uuid.toString().c_str(), + m_handle); + NIMBLE_LOGD(LOG_TAG, "Characteristics:\n%s", m_characteristicMap.toString().c_str()); } // dump @@ -68,7 +71,7 @@ void NimBLEService::dump() { * @return the UUID of the service. */ NimBLEUUID NimBLEService::getUUID() { - return m_uuid; + return m_uuid; } // getUUID @@ -78,46 +81,46 @@ NimBLEUUID NimBLEService::getUUID() { * Starting a service also means that we can create the corresponding characteristics. * @return Start the service. */ - + bool NimBLEService::start() { - NIMBLE_LOGD(LOG_TAG, ">> start(): Starting service: %s", toString().c_str()); - int rc = 0; - // 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 - // of the second service to 0 to indicate the end of the array. + NIMBLE_LOGD(LOG_TAG, ">> start(): Starting service: %s", toString().c_str()); + int rc = 0; + // 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 + // 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_chr_def* pChr_a = nullptr; + ble_gatt_chr_def* pChr_a = nullptr; ble_gatt_dsc_def* pDsc_a = nullptr; - + svc[0].type = BLE_GATT_SVC_TYPE_PRIMARY; svc[0].uuid = &m_uuid.getNative()->u; - svc[0].includes = NULL; - - uint8_t numChrs = m_characteristicMap.getSize(); - - NIMBLE_LOGD(LOG_TAG,"Adding %d characteristics for service %s", numChrs, toString().c_str()); - - if(!numChrs){ - svc[0].characteristics = NULL; - }else{ + svc[0].includes = NULL; + + uint8_t numChrs = m_characteristicMap.getSize(); + + NIMBLE_LOGD(LOG_TAG,"Adding %d characteristics for service %s", numChrs, toString().c_str()); + + if(!numChrs){ + svc[0].characteristics = NULL; + }else{ // 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 // for this purpose. - pChr_a = new ble_gatt_chr_def[numChrs+1]; - NimBLECharacteristic* pCharacteristic = m_characteristicMap.getFirst(); - - for(uint8_t i=0; i < numChrs; i++) { + pChr_a = new ble_gatt_chr_def[numChrs+1]; + NimBLECharacteristic* pCharacteristic = m_characteristicMap.getFirst(); + + for(uint8_t i=0; i < numChrs; i++) { uint8_t numDscs = pCharacteristic->m_descriptorMap.getSize(); if(numDscs) { // skip 2902 as it's automatically created by NimBLE // 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->getDescriptorByUUID("2902") != nullptr) { numDscs--; } } - + if(!numDscs){ pChr_a[i].descriptors = NULL; } else { @@ -140,41 +143,41 @@ bool NimBLEService::start() { pDescriptor = pCharacteristic->m_descriptorMap.getNext(); d++; } - + pDsc_a[numDscs].uuid = NULL; 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].arg = pCharacteristic; pChr_a[i].flags = pCharacteristic->m_properties; pChr_a[i].min_key_size = 0; pChr_a[i].val_handle = &pCharacteristic->m_handle; - pCharacteristic = m_characteristicMap.getNext(); - } - - pChr_a[numChrs].uuid = NULL; - svc[0].characteristics = pChr_a; - } - - // end of services must indicate to api with type = 0 - svc[1].type = 0; - + pCharacteristic = m_characteristicMap.getNext(); + } + + pChr_a[numChrs].uuid = NULL; + svc[0].characteristics = pChr_a; + } + + // end of services must indicate to api with type = 0 + svc[1].type = 0; + rc = ble_gatts_count_cfg((const ble_gatt_svc_def*)svc); if (rc != 0) { NIMBLE_LOGE(LOG_TAG, "ble_gatts_count_cfg failed, rc= %d, %s", rc, NimBLEUtils::returnCodeToString(rc)); return false; } - + rc = ble_gatts_add_svcs((const ble_gatt_svc_def*)svc); if (rc != 0) { NIMBLE_LOGE(LOG_TAG, "ble_gatts_add_svcs, rc= %d, %s", rc, NimBLEUtils::returnCodeToString(rc)); return false; - + } - NIMBLE_LOGD(LOG_TAG, "<< start()"); + NIMBLE_LOGD(LOG_TAG, "<< start()"); return true; } // start @@ -184,13 +187,13 @@ bool NimBLEService::start() { * @param [in] handle The handle associated with the service. */ void NimBLEService::setHandle(uint16_t handle) { - NIMBLE_LOGD(LOG_TAG, ">> setHandle - Handle=0x%.2x, service UUID=%s)", handle, getUUID().toString().c_str()); - if (m_handle != NULL_HANDLE) { - NIMBLE_LOGE(LOG_TAG, "!!! Handle is already set %.2x", m_handle); - return; - } - m_handle = handle; - NIMBLE_LOGD(LOG_TAG, "<< setHandle"); + NIMBLE_LOGD(LOG_TAG, ">> setHandle - Handle=0x%.2x, service UUID=%s)", handle, getUUID().toString().c_str()); + if (m_handle != NULL_HANDLE) { + NIMBLE_LOGE(LOG_TAG, "!!! Handle is already set %.2x", m_handle); + return; + } + m_handle = handle; + NIMBLE_LOGD(LOG_TAG, "<< setHandle"); } // setHandle @@ -199,7 +202,7 @@ void NimBLEService::setHandle(uint16_t handle) { * @return The handle associated with this service. */ uint16_t NimBLEService::getHandle() { - return m_handle; + return m_handle; } // getHandle @@ -208,26 +211,26 @@ uint16_t NimBLEService::getHandle() { * @param [in] pCharacteristic A pointer to the characteristic to be added. */ void NimBLEService::addCharacteristic(NimBLECharacteristic* pCharacteristic) { - // 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 - // to the map and then ask the service to add the characteristic at the BLE level (ESP-IDF). + // 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 + // 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, "Adding characteristic: uuid=%s to service: %s", - pCharacteristic->getUUID().toString().c_str(), - toString().c_str()); + NIMBLE_LOGD(LOG_TAG, ">> addCharacteristic()"); + NIMBLE_LOGD(LOG_TAG, "Adding characteristic: uuid=%s to service: %s", + pCharacteristic->getUUID().toString().c_str(), + toString().c_str()); - // Check that we don't add the same characteristic twice. - if (m_characteristicMap.getByUUID(pCharacteristic->getUUID()) != nullptr) { - NIMBLE_LOGW(LOG_TAG, "<< Adding a new characteristic with the same UUID as a previous one"); - //return; - } + // Check that we don't add the same characteristic twice. + if (m_characteristicMap.getByUUID(pCharacteristic->getUUID()) != nullptr) { + NIMBLE_LOGW(LOG_TAG, "<< Adding a new characteristic with the same UUID as a previous one"); + //return; + } - // 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. - m_characteristicMap.setByUUID(pCharacteristic, pCharacteristic->getUUID()); + // 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. + m_characteristicMap.setByUUID(pCharacteristic, pCharacteristic->getUUID()); - NIMBLE_LOGD(LOG_TAG, "<< addCharacteristic()"); + NIMBLE_LOGD(LOG_TAG, "<< addCharacteristic()"); } // addCharacteristic @@ -238,7 +241,7 @@ void NimBLEService::addCharacteristic(NimBLECharacteristic* pCharacteristic) { * @return The new BLE characteristic. */ 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. */ NimBLECharacteristic* NimBLEService::createCharacteristic(const NimBLEUUID &uuid, uint32_t properties) { - NimBLECharacteristic* pCharacteristic = new NimBLECharacteristic(uuid, properties, this); - addCharacteristic(pCharacteristic); + NimBLECharacteristic* pCharacteristic = new NimBLECharacteristic(uuid, properties, this); + addCharacteristic(pCharacteristic); //pCharacteristic->executeCreate(this); - return pCharacteristic; + return pCharacteristic; } // createCharacteristic NimBLECharacteristic* NimBLEService::getCharacteristic(const char* uuid) { - return getCharacteristic(NimBLEUUID(uuid)); + return getCharacteristic(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. */ std::string NimBLEService::toString() { - std::string res = "UUID: " + getUUID().toString(); - char hex[5]; - snprintf(hex, sizeof(hex), "%04x", getHandle()); - res += ", handle: 0x"; - res += hex; - return res; + std::string res = "UUID: " + getUUID().toString(); + char hex[5]; + snprintf(hex, sizeof(hex), "%04x", getHandle()); + res += ", handle: 0x"; + res += hex; + return res; } // toString @@ -288,7 +291,8 @@ std::string NimBLEService::toString() { * @return The BLEServer associated with this service. */ NimBLEServer* NimBLEService::getServer() { - return m_pServer; + return m_pServer; } // getServer +#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #endif // CONFIG_BT_ENABLED diff --git a/src/NimBLEService.h b/src/NimBLEService.h index fa6c2b2..1cb0f61 100644 --- a/src/NimBLEService.h +++ b/src/NimBLEService.h @@ -3,7 +3,7 @@ * * Created: on March 2, 2020 * Author H2zero - * + * * Originally: * * BLEService.h @@ -17,6 +17,9 @@ #include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) +#include "nimconfig.h" +#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) + #include "NimBLECharacteristic.h" #include "NimBLEServer.h" #include "NimBLEUUID.h" @@ -31,21 +34,21 @@ class NimBLECharacteristic; */ class NimBLECharacteristicMap { public: - void setByUUID(NimBLECharacteristic* pCharacteristic, const char* uuid); - void setByUUID(NimBLECharacteristic* pCharacteristic, const NimBLEUUID &uuid); - void setByHandle(uint16_t handle, NimBLECharacteristic* pCharacteristic); - NimBLECharacteristic* getByUUID(const char* uuid); - NimBLECharacteristic* getByUUID(const NimBLEUUID &uuid); - NimBLECharacteristic* getByHandle(uint16_t handle); - NimBLECharacteristic* getFirst(); - NimBLECharacteristic* getNext(); - uint8_t getSize(); - std::string toString(); + void setByUUID(NimBLECharacteristic* pCharacteristic, const char* uuid); + void setByUUID(NimBLECharacteristic* pCharacteristic, const NimBLEUUID &uuid); + void setByHandle(uint16_t handle, NimBLECharacteristic* pCharacteristic); + NimBLECharacteristic* getByUUID(const char* uuid); + NimBLECharacteristic* getByUUID(const NimBLEUUID &uuid); + NimBLECharacteristic* getByHandle(uint16_t handle); + NimBLECharacteristic* getFirst(); + NimBLECharacteristic* getNext(); + uint8_t getSize(); + std::string toString(); private: - std::map m_uuidMap; - std::map m_handleMap; - std::map::iterator m_iterator; + std::map m_uuidMap; + std::map m_handleMap; + std::map::iterator m_iterator; }; @@ -55,42 +58,43 @@ private: */ class NimBLEService { public: - NimBLECharacteristic* createCharacteristic(const char* uuid, - uint32_t properties = NIMBLE_PROPERTY::READ | - NIMBLE_PROPERTY::WRITE); - - NimBLECharacteristic* createCharacteristic(const NimBLEUUID &uuid, - uint32_t properties = NIMBLE_PROPERTY::READ | - NIMBLE_PROPERTY::WRITE); - - void dump(); - NimBLECharacteristic* getCharacteristic(const char* uuid); - NimBLECharacteristic* getCharacteristic(const NimBLEUUID &uuid); - NimBLEUUID getUUID(); - NimBLEServer* getServer(); - bool start(); -// void stop(); - std::string toString(); - uint16_t getHandle(); - uint8_t m_instId = 0; + NimBLECharacteristic* createCharacteristic(const char* uuid, + uint32_t properties = NIMBLE_PROPERTY::READ | + NIMBLE_PROPERTY::WRITE); + + NimBLECharacteristic* createCharacteristic(const NimBLEUUID &uuid, + uint32_t properties = NIMBLE_PROPERTY::READ | + NIMBLE_PROPERTY::WRITE); + + void dump(); + NimBLECharacteristic* getCharacteristic(const char* uuid); + NimBLECharacteristic* getCharacteristic(const NimBLEUUID &uuid); + NimBLEUUID getUUID(); + NimBLEServer* getServer(); + bool start(); +// void stop(); + std::string toString(); + uint16_t getHandle(); + uint8_t m_instId = 0; private: - NimBLEService(const char* uuid, uint16_t numHandles, NimBLEServer* pServer); - NimBLEService(const NimBLEUUID &uuid, uint16_t numHandles, NimBLEServer* pServer); - friend class NimBLEServer; - friend class NimBLEDevice; - - void addCharacteristic(NimBLECharacteristic* pCharacteristic); + NimBLEService(const char* uuid, uint16_t numHandles, NimBLEServer* pServer); + NimBLEService(const NimBLEUUID &uuid, uint16_t numHandles, NimBLEServer* pServer); + friend class NimBLEServer; + friend class NimBLEDevice; - NimBLECharacteristicMap m_characteristicMap; - uint16_t m_handle; - NimBLEServer* m_pServer = nullptr; - NimBLEUUID m_uuid; + void addCharacteristic(NimBLECharacteristic* pCharacteristic); - uint16_t m_numHandles; - void setHandle(uint16_t handle); + NimBLECharacteristicMap m_characteristicMap; + uint16_t m_handle; + NimBLEServer* m_pServer = nullptr; + NimBLEUUID m_uuid; + + uint16_t m_numHandles; + void setHandle(uint16_t handle); }; // BLEService +#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #endif // CONFIG_BT_ENABLED #endif /* MAIN_NIMBLESERVICE_H_ */ diff --git a/src/NimBLEServiceMap.cpp b/src/NimBLEServiceMap.cpp index 3ec4887..e5b96e6 100644 --- a/src/NimBLEServiceMap.cpp +++ b/src/NimBLEServiceMap.cpp @@ -3,7 +3,7 @@ * * Created: on March 7, 2020 * Author H2zero - * + * * Originally: * * BLEServiceMap.cpp @@ -14,6 +14,9 @@ #include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) +#include "nimconfig.h" +#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) + #include "NimBLEService.h" @@ -23,7 +26,7 @@ * @return The characteristic. */ 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. */ NimBLEService* NimBLEServiceMap::getByUUID(const NimBLEUUID &uuid, uint8_t inst_id) { - for (auto &myPair : m_uuidMap) { - if (myPair.first->getUUID().equals(uuid)) { - return myPair.first; - } - } - //return m_uuidMap.at(uuid.toString()); - return nullptr; + for (auto &myPair : m_uuidMap) { + if (myPair.first->getUUID().equals(uuid)) { + return myPair.first; + } + } + //return m_uuidMap.at(uuid.toString()); + return nullptr; } // getByUUID @@ -49,7 +52,7 @@ NimBLEService* NimBLEServiceMap::getByUUID(const NimBLEUUID &uuid, uint8_t inst_ */ /* NimBLEService* NimBLEServiceMap::getByHandle(uint16_t handle) { - return m_handleMap.at(handle); + return m_handleMap.at(handle); } // getByHandle */ @@ -60,7 +63,7 @@ NimBLEService* NimBLEServiceMap::getByHandle(uint16_t handle) { * @return N/A. */ void NimBLEServiceMap::setByUUID(const NimBLEUUID &uuid, NimBLEService* service) { - m_uuidMap.insert(std::pair(service, uuid.toString())); + m_uuidMap.insert(std::pair(service, uuid.toString())); } // setByUUID @@ -72,7 +75,7 @@ void NimBLEServiceMap::setByUUID(const NimBLEUUID &uuid, NimBLEService* service) */ /* void NimBLEServiceMap::setByHandle(uint16_t handle, NimBLEService* service) { - m_handleMap.insert(std::pair(handle, service)); + m_handleMap.insert(std::pair(handle, service)); } // setByHandle */ @@ -81,15 +84,15 @@ void NimBLEServiceMap::setByHandle(uint16_t handle, NimBLEService* service) { * @return A string representation of the service map. */ std::string NimBLEServiceMap::toString() { - std::string res; - //char hex[5]; - for (auto &myPair: m_uuidMap) { - // res += "handle: 0x"; - // snprintf(hex, sizeof(hex), "%04x", myPair.first); - // res += hex; - res += ", uuid: " + myPair.second + "\n"; - } - return res; + std::string res; + //char hex[5]; + for (auto &myPair: m_uuidMap) { + // res += "handle: 0x"; + // snprintf(hex, sizeof(hex), "%04x", myPair.first); + // res += hex; + res += ", uuid: " + myPair.second + "\n"; + } + return res; } // toString @@ -98,40 +101,45 @@ std::string NimBLEServiceMap::toString() { * @return The first service in the map. */ NimBLEService* NimBLEServiceMap::getFirst() { - m_iterator = m_uuidMap.begin(); - if (m_iterator == m_uuidMap.end()) return nullptr; - NimBLEService* pRet = m_iterator->first; - m_iterator++; - return pRet; + m_iterator = m_uuidMap.begin(); + if (m_iterator == m_uuidMap.end()) return nullptr; + NimBLEService* pRet = m_iterator->first; + m_iterator++; + return pRet; } // getFirst + /** * @brief Get the next service in the map. * @return The next service in the map. */ NimBLEService* NimBLEServiceMap::getNext() { - if (m_iterator == m_uuidMap.end()) return nullptr; - NimBLEService* pRet = m_iterator->first; - m_iterator++; - return pRet; + if (m_iterator == m_uuidMap.end()) return nullptr; + NimBLEService* pRet = m_iterator->first; + m_iterator++; + return pRet; } // getNext + /** * @brief Removes service from maps. * @return N/A. */ void NimBLEServiceMap::removeService(NimBLEService* service) { - //m_handleMap.erase(service->getHandle()); - m_uuidMap.erase(service); + //m_handleMap.erase(service->getHandle()); + m_uuidMap.erase(service); } // removeService + /** * @brief Returns the amount of registered services * @return amount of registered services */ int NimBLEServiceMap::getRegisteredServiceCount(){ - //return m_handleMap.size(); + //return m_handleMap.size(); return m_uuidMap.size(); } + +#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #endif /* CONFIG_BT_ENABLED */ diff --git a/src/NimBLEUUID.cpp b/src/NimBLEUUID.cpp index 33f8019..4a9d7e8 100644 --- a/src/NimBLEUUID.cpp +++ b/src/NimBLEUUID.cpp @@ -3,7 +3,7 @@ * * Created: on Jan 24 2020 * Author H2zero - * + * * Originally: * * 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 // UUID format. char * position = const_cast(value.c_str()); - uint32_t first = strtoul(position, &position, 16); - uint16_t second = strtoul(position + 1, &position, 16); - uint16_t third = strtoul(position + 1, &position, 16); - uint16_t fourth = strtoul(position + 1, &position, 16); - uint64_t fifth = strtoull(position + 1, NULL, 16); + uint32_t first = strtoul(position, &position, 16); + uint16_t second = strtoul(position + 1, &position, 16); + uint16_t third = strtoul(position + 1, &position, 16); + uint16_t fourth = strtoul(position + 1, &position, 16); + uint64_t fifth = strtoull(position + 1, NULL, 16); *this = NimBLEUUID(first, second, third, (uint64_t(fourth) << 48) + fifth); } 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, - * instead of BLEUUID("ebe0ccb0-7a0a-4b0c-8a1a-6ff2997da3a6"), it becomes + * @brief Create a UUID from the 128bit value using hex parts instead of string, + * instead of BLEUUID("ebe0ccb0-7a0a-4b0c-8a1a-6ff2997da3a6"), it becomes * BLEUUID(0xebe0ccb0, 0x7a0a, 0x4b0c, 0x8a1a6ff2997da3a6) * * @param [in] first The first 32bit of the UUID. diff --git a/src/NimBLEUtils.cpp b/src/NimBLEUtils.cpp index e9da1da..9036d4d 100644 --- a/src/NimBLEUtils.cpp +++ b/src/NimBLEUtils.cpp @@ -3,7 +3,7 @@ * * Created: on Jan 25 2020 * Author H2zero - * + * */ #include "sdkconfig.h" @@ -11,42 +11,10 @@ #include "NimBLEUtils.h" #include "NimBLELog.h" - -#if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_NIMBLE_ENABLED) #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) { /* Check connection interval min */ @@ -82,7 +50,7 @@ int NimBLEUtils::checkConnParams(ble_gap_conn_params* params) { 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) { case 0: return "SUCCESS"; @@ -363,19 +331,19 @@ const char* NimBLEUtils::returnCodeToString(int rc) { default: return "Unknown"; } -#else // #if CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT +#else // #if defined(CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT) 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. * @param adFlags The flags to convert * @return std::string A string representation of the advertising flags. */ - 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) { case BLE_HCI_ADV_TYPE_ADV_IND : //0 return "Undirected - Connectable / Scannable"; @@ -390,9 +358,9 @@ const char* NimBLEUtils::advTypeToString(uint8_t advType) { default: return "Unknown flag"; } -#else // #if CONFIG_NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT +#else // #if defined(CONFIG_NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT) return ""; -#endif // #if CONFIG_NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT +#endif // #if defined(CONFIG_NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT) } // adFlagsToString @@ -432,85 +400,87 @@ char* NimBLEUtils::buildHexData(uint8_t* target, const uint8_t* source, uint8_t } // buildHexData - 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)); +#endif } + /** * @brief Convert a BT GAP event type to a string representation. * @param [in] eventType The type of event. * @return A string representation of the event type. */ 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) { case BLE_GAP_EVENT_CONNECT : //0 return "BLE_GAP_EVENT_CONNECT "; - + case BLE_GAP_EVENT_DISCONNECT: //1 return "BLE_GAP_EVENT_DISCONNECT"; - + case BLE_GAP_EVENT_CONN_UPDATE: //3 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"; - - case BLE_GAP_EVENT_L2CAP_UPDATE_REQ: //5 + + case BLE_GAP_EVENT_L2CAP_UPDATE_REQ: //5 return "BLE_GAP_EVENT_L2CAP_UPDATE_REQ"; - + case BLE_GAP_EVENT_TERM_FAILURE: //6 return "BLE_GAP_EVENT_TERM_FAILURE"; - + case BLE_GAP_EVENT_DISC: //7 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"; - - case BLE_GAP_EVENT_ADV_COMPLETE: //9 + + case BLE_GAP_EVENT_ADV_COMPLETE: //9 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"; - + case BLE_GAP_EVENT_PASSKEY_ACTION : //11 return "BLE_GAP_EVENT_PASSKEY_ACTION"; - + case BLE_GAP_EVENT_NOTIFY_RX: //12 return "BLE_GAP_EVENT_NOTIFY_RX"; - + case BLE_GAP_EVENT_NOTIFY_TX : //13 return "BLE_GAP_EVENT_NOTIFY_TX"; - + case BLE_GAP_EVENT_SUBSCRIBE : //14 return "BLE_GAP_EVENT_SUBSCRIBE"; - + case BLE_GAP_EVENT_MTU: //15 return "BLE_GAP_EVENT_MTU"; - + case BLE_GAP_EVENT_IDENTITY_RESOLVED: //16 return "BLE_GAP_EVENT_IDENTITY_RESOLVED"; - + case BLE_GAP_EVENT_REPEAT_PAIRING: //17 return "BLE_GAP_EVENT_REPEAT_PAIRING"; - + case BLE_GAP_EVENT_PHY_UPDATE_COMPLETE: //18 return "BLE_GAP_EVENT_PHY_UPDATE_COMPLETE"; - + case BLE_GAP_EVENT_EXT_DISC: //19 return "BLE_GAP_EVENT_EXT_DISC"; #ifdef BLE_GAP_EVENT_PERIODIC_SYNC // IDF 4.0 does not support these case BLE_GAP_EVENT_PERIODIC_SYNC: //20 return "BLE_GAP_EVENT_PERIODIC_SYNC"; - + case BLE_GAP_EVENT_PERIODIC_REPORT: //21 return "BLE_GAP_EVENT_PERIODIC_REPORT"; - + case BLE_GAP_EVENT_PERIODIC_SYNC_LOST: //22 return "BLE_GAP_EVENT_PERIODIC_SYNC_LOST"; - + case BLE_GAP_EVENT_SCAN_REQ_RCVD: //23 return "BLE_GAP_EVENT_SCAN_REQ_RCVD"; #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); 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 ""; -#endif // #if CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT +#endif // #if defined(CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT) } // gapEventToString diff --git a/src/NimBLEUtils.h b/src/NimBLEUtils.h index 1b75757..b26d41a 100644 --- a/src/NimBLEUtils.h +++ b/src/NimBLEUtils.h @@ -3,7 +3,7 @@ * * Created: on Jan 25 2020 * Author H2zero - * + * */ #ifndef COMPONENTS_NIMBLEUTILS_H_ @@ -28,7 +28,6 @@ public: static char* buildHexData(uint8_t* target, const uint8_t* source, uint8_t length); static const char* advTypeToString(uint8_t advType); 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); }; diff --git a/src/NimBLEValue.cpp b/src/NimBLEValue.cpp index f5d20f6..aa437c6 100644 --- a/src/NimBLEValue.cpp +++ b/src/NimBLEValue.cpp @@ -3,7 +3,7 @@ * * Created: on March 6, 2020 * Author H2zero - * + * * Originally: * * BLEValue.cpp @@ -14,15 +14,18 @@ #include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) +#include "nimconfig.h" +#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) + #include "NimBLEValue.h" #include "NimBLELog.h" static const char* LOG_TAG="NimBLEValue"; NimBLEValue::NimBLEValue() { - m_accumulation = ""; - m_value = ""; - m_readOffset = 0; + m_accumulation = ""; + m_value = ""; + m_readOffset = 0; } // NimBLEValue @@ -32,8 +35,8 @@ NimBLEValue::NimBLEValue() { * @param [in] part A message part being added. */ void NimBLEValue::addPart(const std::string &part) { - NIMBLE_LOGD(LOG_TAG, ">> addPart: length=%d", part.length()); - m_accumulation += part; + NIMBLE_LOGD(LOG_TAG, ">> addPart: length=%d", part.length()); + m_accumulation += part; } // addPart @@ -44,8 +47,8 @@ void NimBLEValue::addPart(const std::string &part) { * @param [in] length The number of bytes being added. */ void NimBLEValue::addPart(const uint8_t* pData, size_t length) { - NIMBLE_LOGD(LOG_TAG, ">> addPart: length=%d", length); - m_accumulation += std::string((char*) pData, length); + NIMBLE_LOGD(LOG_TAG, ">> addPart: length=%d", length); + m_accumulation += std::string((char*) pData, length); } // addPart @@ -53,9 +56,9 @@ void NimBLEValue::addPart(const uint8_t* pData, size_t length) { * @brief Cancel the current accumulation. */ void NimBLEValue::cancel() { - NIMBLE_LOGD(LOG_TAG, ">> cancel"); - m_accumulation = ""; - m_readOffset = 0; + NIMBLE_LOGD(LOG_TAG, ">> cancel"); + m_accumulation = ""; + m_readOffset = 0; } // cancel @@ -66,12 +69,12 @@ void NimBLEValue::cancel() { * we now have the complete message and commit the change as a unit. */ void NimBLEValue::commit() { - NIMBLE_LOGD(LOG_TAG, ">> commit"); - // If there is nothing to commit, do nothing. - if (m_accumulation.length() == 0) return; - setValue(m_accumulation); - m_accumulation = ""; - m_readOffset = 0; + NIMBLE_LOGD(LOG_TAG, ">> commit"); + // If there is nothing to commit, do nothing. + if (m_accumulation.length() == 0) return; + setValue(m_accumulation); + m_accumulation = ""; + m_readOffset = 0; } // commit @@ -80,7 +83,7 @@ void NimBLEValue::commit() { * @return A pointer to the data. */ 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. */ size_t NimBLEValue::getLength() { - return m_value.length(); + return m_value.length(); } // getLength @@ -98,7 +101,7 @@ size_t NimBLEValue::getLength() { * @return The read offset into the read. */ uint16_t NimBLEValue::getReadOffset() { - return m_readOffset; + return m_readOffset; } // getReadOffset @@ -106,7 +109,7 @@ uint16_t NimBLEValue::getReadOffset() { * @brief Get the current value. */ std::string NimBLEValue::getValue() { - return m_value; + return m_value; } // getValue @@ -115,7 +118,7 @@ std::string NimBLEValue::getValue() { * @param [in] readOffset The offset into the read. */ void NimBLEValue::setReadOffset(uint16_t readOffset) { - m_readOffset = readOffset; + m_readOffset = readOffset; } // setReadOffset @@ -123,7 +126,7 @@ void NimBLEValue::setReadOffset(uint16_t readOffset) { * @brief Set the current value. */ void NimBLEValue::setValue(const std::string &value) { - m_value = value; + m_value = value; } // setValue @@ -133,8 +136,8 @@ void NimBLEValue::setValue(const std::string &value) { * @param [in] The length of the new current value. */ 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 - +#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #endif // CONFIG_BT_ENABLED diff --git a/src/NimBLEValue.h b/src/NimBLEValue.h index 75372ad..4fdeb9b 100644 --- a/src/NimBLEValue.h +++ b/src/NimBLEValue.h @@ -3,9 +3,9 @@ * * Created: on March 6, 2020 * Author H2zero - * + * * Originally: - * + * * BLEValue.h * * Created on: Jul 17, 2017 @@ -16,6 +16,10 @@ #define MAIN_BLEVALUE_H_ #include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) + +#include "nimconfig.h" +#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) + #include /** @@ -23,24 +27,26 @@ */ class NimBLEValue { public: - NimBLEValue(); - void addPart(const std::string &part); - void addPart(const uint8_t* pData, size_t length); - void cancel(); - void commit(); - uint8_t* getData(); - size_t getLength(); - uint16_t getReadOffset(); - std::string getValue(); - void setReadOffset(uint16_t readOffset); - void setValue(const std::string &value); - void setValue(const uint8_t* pData, size_t length); + NimBLEValue(); + void addPart(const std::string &part); + void addPart(const uint8_t* pData, size_t length); + void cancel(); + void commit(); + uint8_t* getData(); + size_t getLength(); + uint16_t getReadOffset(); + std::string getValue(); + void setReadOffset(uint16_t readOffset); + void setValue(const std::string &value); + void setValue(const uint8_t* pData, size_t length); private: - std::string m_accumulation; - uint16_t m_readOffset; - std::string m_value; + std::string m_accumulation; + uint16_t m_readOffset; + std::string m_value; }; + +#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #endif // CONFIG_BT_ENABLED #endif /* MAIN_BLEVALUE_H_ */ diff --git a/src/nimconfig.h b/src/nimconfig.h new file mode 100644 index 0000000..94147f1 --- /dev/null +++ b/src/nimconfig.h @@ -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