From 7064a82fbf7095f49d0740650cb3392ccf57a3bb Mon Sep 17 00:00:00 2001 From: Staars Date: Tue, 26 May 2020 20:43:55 +0200 Subject: [PATCH 1/3] update NimBLE-Arduino --- libesp32/NimBLE-Arduino/API_DIFFERENCES.md | 42 +- libesp32/NimBLE-Arduino/README.md | 18 +- .../examples/NimBLE_Server/NimBLE_Server.ino | 3 +- libesp32/NimBLE-Arduino/src/FreeRTOS.cpp | 34 +- libesp32/NimBLE-Arduino/src/FreeRTOS.h | 4 +- .../NimBLE-Arduino/src/HIDKeyboardTypes.h | 58 +- libesp32/NimBLE-Arduino/src/HIDTypes.h | 4 +- libesp32/NimBLE-Arduino/src/NimBLE2902.cpp | 38 +- libesp32/NimBLE-Arduino/src/NimBLE2902.h | 18 +- libesp32/NimBLE-Arduino/src/NimBLE2904.cpp | 48 +- libesp32/NimBLE-Arduino/src/NimBLE2904.h | 86 +-- libesp32/NimBLE-Arduino/src/NimBLEAddress.cpp | 87 ++- libesp32/NimBLE-Arduino/src/NimBLEAddress.h | 34 +- .../src/NimBLEAdvertisedDevice.cpp | 46 +- .../src/NimBLEAdvertisedDevice.h | 12 +- .../NimBLE-Arduino/src/NimBLEAdvertising.cpp | 628 +++++++++--------- .../NimBLE-Arduino/src/NimBLEAdvertising.h | 85 +-- libesp32/NimBLE-Arduino/src/NimBLEBeacon.cpp | 57 +- libesp32/NimBLE-Arduino/src/NimBLEBeacon.h | 47 +- .../src/NimBLECharacteristic.cpp | 407 ++++++------ .../NimBLE-Arduino/src/NimBLECharacteristic.h | 184 ++--- .../src/NimBLECharacteristicMap.cpp | 74 ++- libesp32/NimBLE-Arduino/src/NimBLEClient.cpp | 448 +++++++------ libesp32/NimBLE-Arduino/src/NimBLEClient.h | 105 +-- .../NimBLE-Arduino/src/NimBLEDescriptor.cpp | 107 +-- .../NimBLE-Arduino/src/NimBLEDescriptor.h | 79 +-- .../src/NimBLEDescriptorMap.cpp | 80 +-- libesp32/NimBLE-Arduino/src/NimBLEDevice.cpp | 268 ++++---- libesp32/NimBLE-Arduino/src/NimBLEDevice.h | 118 +++- .../NimBLE-Arduino/src/NimBLEEddystoneTLM.cpp | 54 +- .../NimBLE-Arduino/src/NimBLEEddystoneTLM.h | 52 +- .../NimBLE-Arduino/src/NimBLEEddystoneURL.cpp | 188 +++--- .../NimBLE-Arduino/src/NimBLEEddystoneURL.h | 36 +- libesp32/NimBLE-Arduino/src/NimBLELog.h | 8 +- .../src/NimBLERemoteCharacteristic.cpp | 412 +++++++----- .../src/NimBLERemoteCharacteristic.h | 99 +-- .../src/NimBLERemoteDescriptor.cpp | 167 +++-- .../src/NimBLERemoteDescriptor.h | 49 +- .../src/NimBLERemoteService.cpp | 230 ++++--- .../NimBLE-Arduino/src/NimBLERemoteService.h | 64 +- libesp32/NimBLE-Arduino/src/NimBLEScan.cpp | 153 +++-- libesp32/NimBLE-Arduino/src/NimBLEScan.h | 29 +- .../NimBLE-Arduino/src/NimBLESecurity.cpp | 6 +- libesp32/NimBLE-Arduino/src/NimBLESecurity.h | 6 +- libesp32/NimBLE-Arduino/src/NimBLEServer.cpp | 299 +++++---- libesp32/NimBLE-Arduino/src/NimBLEServer.h | 35 +- libesp32/NimBLE-Arduino/src/NimBLEService.cpp | 189 +++--- libesp32/NimBLE-Arduino/src/NimBLEService.h | 94 +-- .../NimBLE-Arduino/src/NimBLEServiceMap.cpp | 80 ++- libesp32/NimBLE-Arduino/src/NimBLEUUID.cpp | 156 ++--- libesp32/NimBLE-Arduino/src/NimBLEUUID.h | 23 +- libesp32/NimBLE-Arduino/src/NimBLEUtils.cpp | 114 ++-- libesp32/NimBLE-Arduino/src/NimBLEUtils.h | 7 +- libesp32/NimBLE-Arduino/src/NimBLEValue.cpp | 63 +- libesp32/NimBLE-Arduino/src/NimBLEValue.h | 42 +- libesp32/NimBLE-Arduino/src/console/console.h | 2 +- .../src/esp-hci/src/esp_nimble_hci.c | 2 +- libesp32/NimBLE-Arduino/src/esp_nimble_cfg.h | 4 +- libesp32/NimBLE-Arduino/src/esp_nimble_hci.h | 2 +- libesp32/NimBLE-Arduino/src/esp_nimble_mem.h | 3 +- libesp32/NimBLE-Arduino/src/host/ble_gap.h | 32 +- libesp32/NimBLE-Arduino/src/host/ble_store.h | 2 - libesp32/NimBLE-Arduino/src/mesh/glue.h | 7 +- libesp32/NimBLE-Arduino/src/modlog/modlog.h | 34 +- .../nimble/host/mesh/src/src/ble_gap_priv.h | 1 + .../nimble/host/mesh/src/src/ble_hs_id_priv.h | 4 + .../host/mesh/src/src/ble_hs_pvcy_priv.h | 3 + .../host/mesh/src/src/ble_hs_resolv_priv.h | 108 +++ .../nimble/host/mesh/src/src/ble_sm_priv.h | 4 + .../src/nimble/host/src/ble_att_cmd.c | 7 +- .../src/nimble/host/src/ble_gap.c | 55 +- .../src/nimble/host/src/ble_gap_priv.h | 2 +- .../src/nimble/host/src/ble_gatts.c | 37 +- .../src/nimble/host/src/ble_hs_conn.c | 8 +- .../src/nimble/host/src/ble_hs_hci.c | 2 +- .../src/nimble/host/src/ble_hs_hci_evt.c | 18 +- .../src/nimble/host/src/ble_hs_misc.c | 8 +- .../src/nimble/host/src/ble_hs_priv.h | 6 +- .../src/nimble/host/src/ble_l2cap_sig.c | 9 +- .../src/nimble/host/src/ble_l2cap_sig_cmd.c | 8 +- .../src/nimble/host/src/ble_sm.c | 27 +- .../src/nimble/host/src/ble_sm_cmd.c | 11 +- .../src/nimble/host/src/ble_sm_priv.h | 8 +- .../src/nimble/host/src/ble_store_util.c | 195 +----- .../host/store/config/src/ble_store_nvs.c | 4 +- .../NimBLE-Arduino/src/nimble/nimble_npl.h | 3 +- .../NimBLE-Arduino/src/nimble/nimble_port.h | 1 - libesp32/NimBLE-Arduino/src/nimconfig.h | 128 +++- .../src/port/src/esp_nimble_mem.c | 8 +- 89 files changed, 3612 insertions(+), 3015 deletions(-) create mode 100644 libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_resolv_priv.h diff --git a/libesp32/NimBLE-Arduino/API_DIFFERENCES.md b/libesp32/NimBLE-Arduino/API_DIFFERENCES.md index d50356924..32bf4a2f0 100644 --- a/libesp32/NimBLE-Arduino/API_DIFFERENCES.md +++ b/libesp32/NimBLE-Arduino/API_DIFFERENCES.md @@ -100,7 +100,7 @@ The `BLEAdvertisedDeviceCallbacks` class `onResult()` method now receives a poin Defined as: ``` bool connect(NimBLEAdvertisedDevice* device, bool refreshServices = true); -bool connect(NimBLEAddress address, uint8_t type = BLE_ADDR_TYPE_PUBLIC, bool refreshServices = true); +bool connect(NimBLEAddress address, uint8_t type = BLE_ADDR_PUBLIC, bool refreshServices = true); ``` If set to false the client will use the services database it retrieved from the peripheral last time it connected. This allows for faster connections and power saving if the devices just dropped connection and want to reconnect. @@ -111,6 +111,46 @@ NimBLERemoteCharacteristic::registerForNotify(); ``` Now return true or false to indicate success or failure so you can choose to disconnect or try again. +``` +NimBLEClient::getServices() +NimBLERemoteService::getCharacteristics() +``` +Now return a pointer to a `std::vector` of the respective object database instead of `std::map`. + +`NimBLERemoteService::getCharacteristicsByHandle()` +Has been removed from the API as it is no longer maintained in the library. + +The last two above changes reduce the heap usage significantly with minimal application code adjustments. + +**NEW** on May 23, 2020 +> ``` +> NimBLEClient::getServices(bool refresh = false) +> NimBLERemoteService::getCharacteristics(bool refresh = false) +> NimBLERemoteCharacteristic::getDecriptors(bool refresh = false) +>``` +> These methods now take an optional (bool) parameter. +If true it will clear the respective vector and retrieve all the respective attributes from the peripheral. +If false it will retrieve the attributes only if the vector is empty, otherwise the vector is returned +with the currently stored attributes. + +> Removed the automatic discovery of all peripheral attributes as they consumed time and resources for data +the user may not be interested in. + +> Added `NimBLEClient::discoverAtrributes()` for the user to discover all the peripheral attributes +to replace the the former functionality. + + +> ``` +>getService(NimBLEUUID) +>getCharacteristic(NimBLEUUID) +>getDescriptor(NimBLEUUID) +>``` +>These methods will now check the respective vectors for the attribute object and, if not found, will retrieve (only) +the specified attribute from the peripheral. + +> These changes allow more control for the user to manage the resources used for the attributes. + + #### Client Security: The client will automatically initiate security when the peripheral responds that it's required. The default configuration will use "just-works" pairing with no bonding, if you wish to enable bonding see below. diff --git a/libesp32/NimBLE-Arduino/README.md b/libesp32/NimBLE-Arduino/README.md index 5271d12a3..514416e29 100644 --- a/libesp32/NimBLE-Arduino/README.md +++ b/libesp32/NimBLE-Arduino/README.md @@ -1,11 +1,14 @@ # *** UPDATE *** -Server now handles long reads and writes, still work to do on client. - -NEW Client callback created - ```bool onConnParamsUpdateRequest(NimBLEClient* pClient, const ble_gap_upd_params* params)``` -Called when the server wants to change the connection parameters, return true to accept them or false if not. -Check NimBLE_Client.ino example for a demonstration. +**Breaking change:** Client and scan now use `std::vector` instead of `std::map` for storing the remote attribute database. + +This change will affect your application code if you use `NimBLEClient::getServices()` or `NimBLERemoteService::getCharacteristics()` +in your application as they now return a pointer to `std::vector` of the respective attributes. +In addition `NimBLERemoteService::getCharacteristicsByHandle()` has been removed as it is no longer maintained in the library. +These changes were necessary due to the amount of resources required to use `std::map`, it was not justifed by any benfit it provided. + +It is expected that there will be minimal impact on most applications, if you need help adjusting your code please create an issue. # NimBLE-Arduino A fork of the NimBLE stack restructured for compilation in the Ardruino IDE with a CPP library for use with ESP32. @@ -59,10 +62,9 @@ Change the settings in the `nimconfig.h` file to customize NimBLE to your projec # Continuing development: -This Library is tracking the esp-nimble repo, nimble-1.2.0-idf master branch, currently [@0a1604a.](https://github.com/espressif/esp-nimble) - -Also tracking the NimBLE related changes in esp-idf, master branch, currently [@48bd2d7.](https://github.com/espressif/esp-idf/tree/master/components/bt/host/nimble) +This Library is tracking the esp-nimble repo, nimble-1.2.0-idf master branch, currently [@fead24e.](https://github.com/espressif/esp-nimble) +Also tracking the NimBLE related changes in esp-idf, master branch, currently [@2bc28bb.](https://github.com/espressif/esp-idf/tree/master/components/bt/host/nimble) # Acknowledgments: diff --git a/libesp32/NimBLE-Arduino/examples/NimBLE_Server/NimBLE_Server.ino b/libesp32/NimBLE-Arduino/examples/NimBLE_Server/NimBLE_Server.ino index cd48cb348..e0be793d5 100644 --- a/libesp32/NimBLE-Arduino/examples/NimBLE_Server/NimBLE_Server.ino +++ b/libesp32/NimBLE-Arduino/examples/NimBLE_Server/NimBLE_Server.ino @@ -61,8 +61,7 @@ class ServerCallbacks: public NimBLEServerCallbacks { void onAuthenticationComplete(ble_gap_conn_desc* desc){ /** Check that encryption was successful, if not we disconnect the client */ if(!desc->sec_state.encrypted) { - /** NOTE: createServer returns the current server reference unless one is not already created */ - NimBLEDevice::createServer()->disconnect(desc->conn_handle); + NimBLEDevice::getServer()->disconnect(desc->conn_handle); Serial.println("Encrypt connection failed - disconnecting client"); return; } diff --git a/libesp32/NimBLE-Arduino/src/FreeRTOS.cpp b/libesp32/NimBLE-Arduino/src/FreeRTOS.cpp index 2cc7a988f..f6bbe171b 100644 --- a/libesp32/NimBLE-Arduino/src/FreeRTOS.cpp +++ b/libesp32/NimBLE-Arduino/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/libesp32/NimBLE-Arduino/src/FreeRTOS.h b/libesp32/NimBLE-Arduino/src/FreeRTOS.h index 07877275f..a6737b757 100644 --- a/libesp32/NimBLE-Arduino/src/FreeRTOS.h +++ b/libesp32/NimBLE-Arduino/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/libesp32/NimBLE-Arduino/src/HIDKeyboardTypes.h b/libesp32/NimBLE-Arduino/src/HIDKeyboardTypes.h index 4e221d57f..531437ee4 100644 --- a/libesp32/NimBLE-Arduino/src/HIDKeyboardTypes.h +++ b/libesp32/NimBLE-Arduino/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/libesp32/NimBLE-Arduino/src/HIDTypes.h b/libesp32/NimBLE-Arduino/src/HIDTypes.h index 64850ef8a..726b84be3 100644 --- a/libesp32/NimBLE-Arduino/src/HIDTypes.h +++ b/libesp32/NimBLE-Arduino/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/libesp32/NimBLE-Arduino/src/NimBLE2902.cpp b/libesp32/NimBLE-Arduino/src/NimBLE2902.cpp index b23206032..04a07b6f9 100644 --- a/libesp32/NimBLE-Arduino/src/NimBLE2902.cpp +++ b/libesp32/NimBLE-Arduino/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/libesp32/NimBLE-Arduino/src/NimBLE2902.h b/libesp32/NimBLE-Arduino/src/NimBLE2902.h index dcecbaa28..f7fc55569 100644 --- a/libesp32/NimBLE-Arduino/src/NimBLE2902.h +++ b/libesp32/NimBLE-Arduino/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/libesp32/NimBLE-Arduino/src/NimBLE2904.cpp b/libesp32/NimBLE-Arduino/src/NimBLE2904.cpp index 59ef00580..d85cd87e4 100644 --- a/libesp32/NimBLE-Arduino/src/NimBLE2904.cpp +++ b/libesp32/NimBLE-Arduino/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/libesp32/NimBLE-Arduino/src/NimBLE2904.h b/libesp32/NimBLE-Arduino/src/NimBLE2904.h index b2aafb0c6..dd665a2bb 100644 --- a/libesp32/NimBLE-Arduino/src/NimBLE2904.h +++ b/libesp32/NimBLE-Arduino/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/libesp32/NimBLE-Arduino/src/NimBLEAddress.cpp b/libesp32/NimBLE-Arduino/src/NimBLEAddress.cpp index 074ce7e84..b6bc9526b 100644 --- a/libesp32/NimBLE-Arduino/src/NimBLEAddress.cpp +++ b/libesp32/NimBLE-Arduino/src/NimBLEAddress.cpp @@ -3,7 +3,7 @@ * * Created: on Jan 24 2020 * Author H2zero - * + * * Originally: * * BLEAddress.cpp @@ -14,9 +14,13 @@ #include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) +#include + #include "NimBLEAddress.h" #include "NimBLEUtils.h" +#include "NimBLELog.h" +static const char* LOG_TAG = "NimBLEAddress"; /************************************************* NOTE: NimBLE addresses are in INVERSE ORDER! @@ -43,26 +47,49 @@ NimBLEAddress::NimBLEAddress(ble_addr_t address) { * * @param [in] stringAddress The hex representation of the address. */ -NimBLEAddress::NimBLEAddress(std::string stringAddress) { - if (stringAddress.length() != 17) return; +NimBLEAddress::NimBLEAddress(const std::string &stringAddress) { + if (stringAddress.length() == 0) { + memset(m_address, 0, 6); + return; + } + + if (stringAddress.length() == 6) { + std::reverse_copy(stringAddress.data(), stringAddress.data() + 6, m_address); + return; + } + + if (stringAddress.length() != 17) { + memset(m_address, 0, sizeof m_address); // "00:00:00:00:00:00" represents an invalid address + NIMBLE_LOGD(LOG_TAG, "Invalid address '%s'", stringAddress.c_str()); + return; + } int data[6]; - sscanf(stringAddress.c_str(), "%x:%x:%x:%x:%x:%x", &data[5], &data[4], &data[3], &data[2], &data[1], &data[0]); - m_address[0] = (uint8_t) data[0]; - m_address[1] = (uint8_t) data[1]; - m_address[2] = (uint8_t) data[2]; - m_address[3] = (uint8_t) data[3]; - m_address[4] = (uint8_t) data[4]; - m_address[5] = (uint8_t) data[5]; + if(sscanf(stringAddress.c_str(), "%x:%x:%x:%x:%x:%x", &data[5], &data[4], &data[3], &data[2], &data[1], &data[0]) != 6) { + memset(m_address, 0, sizeof m_address); // "00:00:00:00:00:00" represents an invalid address + NIMBLE_LOGD(LOG_TAG, "Invalid address '%s'", stringAddress.c_str()); + } + for(size_t index = 0; index < sizeof m_address; index++) { + m_address[index] = data[index]; + } } // BLEAddress /** - * @brief Constructor for compatibility with bluedrioid esp library. - * @param [in] esp_bd_addr_t struct containing the address. + * @brief Constructor for compatibility with bluedroid esp library. + * @param [in] uint8_t[6] or esp_bd_addr_t struct containing the address. */ -NimBLEAddress::NimBLEAddress(esp_bd_addr_t address) { - NimBLEUtils::memrcpy(m_address, address, 6); +NimBLEAddress::NimBLEAddress(uint8_t address[6]) { + std::reverse_copy(address, address + sizeof m_address, m_address); +} // NimBLEAddress + + +/** + * @brief Constructor for address using a hex value. Use the same byte order, so use 0xa4c1385def16 for "a4:c1:38:5d:ef:16" + * @param [in] uint64_t containing the address. + */ +NimBLEAddress::NimBLEAddress(const uint64_t &address) { + memcpy(m_address, &address, sizeof m_address); } // NimBLEAddress @@ -71,8 +98,8 @@ NimBLEAddress::NimBLEAddress(esp_bd_addr_t address) { * @param [in] otherAddress The other address to compare against. * @return True if the addresses are equal. */ -bool NimBLEAddress::equals(NimBLEAddress otherAddress) { - return memcmp(otherAddress.getNative(), m_address, 6) == 0; +bool NimBLEAddress::equals(const NimBLEAddress &otherAddress) const { + return *this == otherAddress; } // equals @@ -80,7 +107,7 @@ bool NimBLEAddress::equals(NimBLEAddress otherAddress) { * @brief Return the native representation of the address. * @return The native representation of the address. */ -uint8_t *NimBLEAddress::getNative() { +const uint8_t *NimBLEAddress::getNative() const { return m_address; } // getNative @@ -96,13 +123,23 @@ uint8_t *NimBLEAddress::getNative() { * * @return The string representation of the address. */ -std::string NimBLEAddress::toString() { - auto size = 18; - char *res = (char*)malloc(size); - snprintf(res, size, "%02x:%02x:%02x:%02x:%02x:%02x", m_address[5], m_address[4], m_address[3], m_address[2], m_address[1], m_address[0]); - std::string ret(res); - free(res); - return ret; - +std::string NimBLEAddress::toString() const { + return std::string(*this); } // toString + + +bool NimBLEAddress::operator ==(const NimBLEAddress & rhs) const { + return memcmp(rhs.m_address, m_address, sizeof m_address) == 0; +} + +bool NimBLEAddress::operator !=(const NimBLEAddress & rhs) const { + return !this->operator==(rhs); +} + +NimBLEAddress::operator std::string() const { + char buffer[18]; + sprintf(buffer, "%02x:%02x:%02x:%02x:%02x:%02x", m_address[5], m_address[4], m_address[3], m_address[2], m_address[1], m_address[0]); + return std::string(buffer); +} + #endif diff --git a/libesp32/NimBLE-Arduino/src/NimBLEAddress.h b/libesp32/NimBLE-Arduino/src/NimBLEAddress.h index ac1f26ca6..e81a2bdf3 100644 --- a/libesp32/NimBLE-Arduino/src/NimBLEAddress.h +++ b/libesp32/NimBLE-Arduino/src/NimBLEAddress.h @@ -3,7 +3,7 @@ * * Created: on Jan 24 2020 * Author H2zero - * + * * Originally: * * BLEAddress.h @@ -24,22 +24,7 @@ /**************************/ #include - -typedef enum { - BLE_ADDR_TYPE_PUBLIC = 0x00, - BLE_ADDR_TYPE_RANDOM = 0x01, - BLE_ADDR_TYPE_RPA_PUBLIC = 0x02, - BLE_ADDR_TYPE_RPA_RANDOM = 0x03, -} esp_nimble_addr_type_t; - -typedef uint8_t esp_ble_addr_type_t ; - -/// Bluetooth address length -#define ESP_BD_ADDR_LEN 6 - -/// Bluetooth device address -typedef uint8_t esp_bd_addr_t[ESP_BD_ADDR_LEN]; - +#include /** * @brief A %BLE device address. @@ -49,11 +34,16 @@ typedef uint8_t esp_bd_addr_t[ESP_BD_ADDR_LEN]; class NimBLEAddress { public: NimBLEAddress(ble_addr_t address); - NimBLEAddress(esp_bd_addr_t address); - NimBLEAddress(std::string stringAddress); - bool equals(NimBLEAddress otherAddress); - uint8_t* getNative(); - std::string toString(); + NimBLEAddress(uint8_t address[6]); + NimBLEAddress(const std::string &stringAddress); + NimBLEAddress(const uint64_t &address); + bool equals(const NimBLEAddress &otherAddress) const; + 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; private: uint8_t m_address[6]; diff --git a/libesp32/NimBLE-Arduino/src/NimBLEAdvertisedDevice.cpp b/libesp32/NimBLE-Arduino/src/NimBLEAdvertisedDevice.cpp index ff0097a25..3634bac8a 100644 --- a/libesp32/NimBLE-Arduino/src/NimBLEAdvertisedDevice.cpp +++ b/libesp32/NimBLE-Arduino/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 @@ -141,7 +144,7 @@ NimBLEUUID NimBLEAdvertisedDevice::getServiceUUID() { //TODO Remove it eventual * @brief Check advertised serviced for existence required UUID * @return Return true if service is advertised */ -bool NimBLEAdvertisedDevice::isAdvertisingService(NimBLEUUID uuid){ +bool NimBLEAdvertisedDevice::isAdvertisingService(const NimBLEUUID &uuid){ for (int i = 0; i < m_serviceUUIDs.size(); i++) { NIMBLE_LOGI(LOG_TAG, "Comparing UUIDS: %s %s", m_serviceUUIDs[i].toString().c_str(), uuid.toString().c_str()); if (m_serviceUUIDs[i].equals(uuid)) return true; @@ -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 @@ -441,6 +444,12 @@ void NimBLEAdvertisedDevice::setServiceUUID(const char* serviceUUID) { * @param [in] serviceUUID The discovered serviceUUID */ void NimBLEAdvertisedDevice::setServiceUUID(NimBLEUUID serviceUUID) { + // Don't add duplicates + for (int i = 0; i < m_serviceUUIDs.size(); i++) { + if (m_serviceUUIDs[i].equals(serviceUUID)) { + return; + } + } m_serviceUUIDs.push_back(serviceUUID); m_haveServiceUUID = true; NIMBLE_LOGD(LOG_TAG,"- addServiceUUID(): serviceUUID: %s", serviceUUID.toString().c_str()); @@ -482,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()); @@ -502,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 @@ -542,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/libesp32/NimBLE-Arduino/src/NimBLEAdvertisedDevice.h b/libesp32/NimBLE-Arduino/src/NimBLEAdvertisedDevice.h index b6b2f706b..7a4115f28 100644 --- a/libesp32/NimBLE-Arduino/src/NimBLEAdvertisedDevice.h +++ b/libesp32/NimBLE-Arduino/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; @@ -54,7 +57,7 @@ public: void setAddressType(uint8_t type); - bool isAdvertisingService(NimBLEUUID uuid); + bool isAdvertisingService(const NimBLEUUID &uuid); bool haveAppearance(); bool haveManufacturerData(); bool haveName(); @@ -92,7 +95,7 @@ private: bool m_haveTXPower; - NimBLEAddress m_address = NimBLEAddress("\0\0\0\0\0\0"); + NimBLEAddress m_address = NimBLEAddress(""); uint8_t m_advType; uint16_t m_appearance; int m_deviceType; @@ -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/libesp32/NimBLE-Arduino/src/NimBLEAdvertising.cpp b/libesp32/NimBLE-Arduino/src/NimBLEAdvertising.cpp index bfdf49dfe..7c930bfc6 100644 --- a/libesp32/NimBLE-Arduino/src/NimBLEAdvertising.cpp +++ b/libesp32/NimBLE-Arduino/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 @@ -58,8 +62,8 @@ NimBLEAdvertising::NimBLEAdvertising() { * @brief Add a service uuid to exposed list of services. * @param [in] serviceUUID The UUID of the service to expose. */ -void NimBLEAdvertising::addServiceUUID(NimBLEUUID serviceUUID) { - m_serviceUUIDs.push_back(serviceUUID); +void NimBLEAdvertising::addServiceUUID(const NimBLEUUID &serviceUUID) { + m_serviceUUIDs.push_back(serviceUUID); } // addServiceUUID @@ -68,7 +72,7 @@ void NimBLEAdvertising::addServiceUUID(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,195 @@ 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) { - NIMBLE_LOGW(LOG_TAG, "Max connections reached - not advertising"); - return; + +#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) + NimBLEServer* pServer = NimBLEDevice::getServer(); + if(pServer != nullptr) { + 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) + &m_advParams, + (pServer != nullptr) ? NimBLEServer::handleGapEvent : NULL, + pServer); +#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 +382,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(std::string data) { - if ((m_payload.length() + data.length()) > BLE_HS_ADV_MAX_SZ) { - return; - } - m_payload.append(data); +void NimBLEAdvertisementData::addData(const std::string &data) { + if ((m_payload.length() + data.length()) > BLE_HS_ADV_MAX_SZ) { + return; + } + m_payload.append(data); } // addData @@ -409,10 +422,10 @@ void NimBLEAdvertisementData::addData(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 @@ -420,36 +433,36 @@ void NimBLEAdvertisementData::setAppearance(uint16_t appearance) { * @brief Set the complete services. * @param [in] uuid The single service to advertise. */ -void NimBLEAdvertisementData::setCompleteServices(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; - } +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; + } - 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 +476,18 @@ void NimBLEAdvertisementData::setCompleteServices(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 @@ -482,13 +495,13 @@ void NimBLEAdvertisementData::setFlags(uint8_t flag) { * @brief Set manufacturer specific data. * @param [in] data Manufacturer data. */ -void NimBLEAdvertisementData::setManufacturerData(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"); +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"); } // setManufacturerData @@ -496,13 +509,13 @@ void NimBLEAdvertisementData::setManufacturerData(std::string data) { * @brief Set the name. * @param [in] The complete name of the device. */ -void NimBLEAdvertisementData::setName(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"); +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"); } // setName @@ -510,36 +523,36 @@ void NimBLEAdvertisementData::setName(std::string name) { * @brief Set the partial services. * @param [in] uuid The single service to advertise. */ -void NimBLEAdvertisementData::setPartialServices(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; - } +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; + } - 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 @@ -548,36 +561,36 @@ void NimBLEAdvertisementData::setPartialServices(NimBLEUUID uuid) { * @param [in] uuid The UUID to set with the service data. Size of UUID will be used. * @param [in] data The data to be associated with the service data advert. */ -void NimBLEAdvertisementData::setServiceData(NimBLEUUID uuid, 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; - } +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; + } - 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 @@ -585,13 +598,13 @@ void NimBLEAdvertisementData::setServiceData(NimBLEUUID uuid, std::string data) * @brief Set the short name. * @param [in] The short name of the device. */ -void NimBLEAdvertisementData::setShortName(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"); +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"); } // setShortName @@ -600,7 +613,8 @@ void NimBLEAdvertisementData::setShortName(std::string name) { * @return The payload that is to be advertised. */ std::string NimBLEAdvertisementData::getPayload() { - return m_payload; + return m_payload; } // getPayload -#endif /* CONFIG_BT_ENABLED */ \ No newline at end of file +#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) +#endif /* CONFIG_BT_ENABLED */ diff --git a/libesp32/NimBLE-Arduino/src/NimBLEAdvertising.h b/libesp32/NimBLE-Arduino/src/NimBLEAdvertising.h index 5e4d58a9a..f30b1581c 100644 --- a/libesp32/NimBLE-Arduino/src/NimBLEAdvertising.h +++ b/libesp32/NimBLE-Arduino/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(NimBLEUUID uuid); - void setFlags(uint8_t); - void setManufacturerData(std::string data); - void setName(std::string name); - void setPartialServices(NimBLEUUID uuid); - void setServiceData(NimBLEUUID uuid, std::string data); - void setShortName(std::string name); - void addData(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(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_ */ \ No newline at end of file +#endif /* MAIN_BLEADVERTISING_H_ */ diff --git a/libesp32/NimBLE-Arduino/src/NimBLEBeacon.cpp b/libesp32/NimBLE-Arduino/src/NimBLEBeacon.cpp index d9f32aee6..718a507f5 100644 --- a/libesp32/NimBLE-Arduino/src/NimBLEBeacon.cpp +++ b/libesp32/NimBLE-Arduino/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,71 +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(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", +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", 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(NimBLEUUID uuid) { - uuid = uuid.to128(); - memcpy(m_beaconData.proximityUUID, uuid.getNative()->u128.value, 16); +void NimBLEBeacon::setProximityUUID(const NimBLEUUID &uuid) { + 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/libesp32/NimBLE-Arduino/src/NimBLEBeacon.h b/libesp32/NimBLE-Arduino/src/NimBLEBeacon.h index c0c15c8eb..82ee61c53 100644 --- a/libesp32/NimBLE-Arduino/src/NimBLEBeacon.h +++ b/libesp32/NimBLE-Arduino/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(std::string data); - void setMajor(uint16_t major); - void setMinor(uint16_t minor); - void setManufacturerId(uint16_t manufacturerId); - void setProximityUUID(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/libesp32/NimBLE-Arduino/src/NimBLECharacteristic.cpp b/libesp32/NimBLE-Arduino/src/NimBLECharacteristic.cpp index d69fee8cd..dd1be3bf0 100644 --- a/libesp32/NimBLE-Arduino/src/NimBLECharacteristic.cpp +++ b/libesp32/NimBLE-Arduino/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) { } @@ -41,19 +44,19 @@ NimBLECharacteristic::NimBLECharacteristic(const char* uuid, uint16_t properties * @param [in] uuid - UUID for the characteristic. * @param [in] properties - Properties for the characteristic. */ -NimBLECharacteristic::NimBLECharacteristic(NimBLEUUID uuid, uint16_t properties, NimBLEService* pService) { - m_uuid = uuid; - m_handle = NULL_HANDLE; - m_properties = properties; - m_pCallbacks = &defaultCallback; +NimBLECharacteristic::NimBLECharacteristic(const NimBLEUUID &uuid, uint16_t properties, NimBLEService* pService) { + 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); } @@ -99,9 +102,9 @@ NimBLEDescriptor* NimBLECharacteristic::createDescriptor(const char* uuid, uint3 * @param [in] properties - The properties of the descriptor. * @return The new BLE descriptor. */ -NimBLEDescriptor* NimBLECharacteristic::createDescriptor(NimBLEUUID uuid, uint32_t properties, uint16_t max_len) { - NimBLEDescriptor* pDescriptor = nullptr; - if(uuid.equals(NimBLEUUID((uint16_t)0x2902))) { +NimBLEDescriptor* NimBLECharacteristic::createDescriptor(const NimBLEUUID &uuid, uint32_t properties, uint16_t max_len) { + 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(NimBLEUUID uuid, uint32 } 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(NimBLEUUID uuid, uint32 * @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 @@ -139,8 +142,8 @@ NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(const char* descript * @param [in] descriptorUUID The UUID of the descriptor that we wish to retrieve. * @return The BLE Descriptor. If no such descriptor is associated with the characteristic, nullptr is returned. */ -NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(NimBLEUUID descriptorUUID) { - return m_descriptorMap.getByUUID(descriptorUUID); +NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(const NimBLEUUID &descriptorUUID) { + return m_descriptorMap.getByUUID(descriptorUUID); } // getDescriptorByUUID @@ -149,17 +152,17 @@ NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(NimBLEUUID descripto * @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,51 +197,60 @@ 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 +/** + * @brief Retrieve the the current data length of the characteristic. + * @return The length of the current characteristic data. + */ +size_t NimBLECharacteristic:: getDataLength() { + return m_value.getLength(); +} + + int NimBLECharacteristic::handleGapEvent(uint16_t conn_handle, uint16_t attr_handle, 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; @@ -246,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. @@ -265,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)); @@ -290,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; } @@ -307,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 @@ -319,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); @@ -351,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); @@ -386,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) { @@ -401,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 @@ -415,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 //////////////////////////////// @@ -431,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 @@ -444,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 @@ -457,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 @@ -470,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 @@ -483,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 @@ -496,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 ////////////////////////////////////////////////////////////////////////////////// @@ -509,24 +521,24 @@ void NimBLECharacteristic::setWriteProperty(bool value) { * @param [in] data The data to set for the characteristic. * @param [in] length The length of the data in bytes. */ -void NimBLECharacteristic::setValue(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); +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); + + 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 @@ -537,43 +549,43 @@ void NimBLECharacteristic::setValue(uint8_t* data, size_t length) { * @param [in] Set the value of the characteristic. * @return N/A. */ -void NimBLECharacteristic::setValue(std::string value) { - setValue((uint8_t*)(value.data()), value.length()); +void NimBLECharacteristic::setValue(const std::string &value) { + 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 @@ -582,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 @@ -605,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 @@ -614,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 @@ -623,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 @@ -634,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 /* CONFIG_BT_ENABLED */ \ No newline at end of file +#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) +#endif /* CONFIG_BT_ENABLED */ diff --git a/libesp32/NimBLE-Arduino/src/NimBLECharacteristic.h b/libesp32/NimBLE-Arduino/src/NimBLECharacteristic.h index 1787937bd..25e1ec7f7 100644 --- a/libesp32/NimBLE-Arduino/src/NimBLECharacteristic.h +++ b/libesp32/NimBLE-Arduino/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(NimBLEUUID uuid, NimBLEDescriptor* pDescriptor); -// void setByHandle(uint16_t handle, NimBLEDescriptor* pDescriptor); - NimBLEDescriptor* getByUUID(const char* uuid); - NimBLEDescriptor* getByUUID(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,84 +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(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(NimBLEUUID descriptorUUID); - NimBLEUUID getUUID(); - std::string getValue(); - uint8_t* getData(); - 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(uint8_t* data, size_t size); - void setValue(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(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 @@ -174,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_*/ \ No newline at end of file +#endif /*MAIN_NIMBLECHARACTERISTIC_H_*/ diff --git a/libesp32/NimBLE-Arduino/src/NimBLECharacteristicMap.cpp b/libesp32/NimBLE-Arduino/src/NimBLECharacteristicMap.cpp index 9ee741bc0..b3cdcf9c6 100644 --- a/libesp32/NimBLE-Arduino/src/NimBLECharacteristicMap.cpp +++ b/libesp32/NimBLE-Arduino/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 @@ -41,21 +44,21 @@ NimBLECharacteristic* NimBLECharacteristicMap::getByUUID(const char* uuid) { * @param [in] UUID The UUID to look up the characteristic. * @return The characteristic. */ -NimBLECharacteristic* NimBLECharacteristicMap::getByUUID(NimBLEUUID uuid) { - for (auto &myPair : m_uuidMap) { - if (myPair.first->getUUID().equals(uuid)) { - return myPair.first; - } - } +NimBLECharacteristic* NimBLECharacteristicMap::getByUUID(const NimBLEUUID &uuid) { + 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 @@ -100,8 +103,8 @@ void NimBLECharacteristicMap::setByHandle(uint16_t handle, NimBLECharacteristic* * @param [in] characteristic The characteristic to cache. * @return N/A. */ -void NimBLECharacteristicMap::setByUUID(NimBLECharacteristic* pCharacteristic, NimBLEUUID uuid) { - m_uuidMap.insert(std::pair(pCharacteristic, uuid.toString())); +void NimBLECharacteristicMap::setByUUID(NimBLECharacteristic* pCharacteristic, const NimBLEUUID &uuid) { + m_uuidMap.insert(std::pair(pCharacteristic, uuid.toString())); } // setByUUID @@ -110,19 +113,20 @@ void NimBLECharacteristicMap::setByUUID(NimBLECharacteristic* pCharacteristic, N * @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 /* CONFIG_BT_ENABLED */ \ No newline at end of file +#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) +#endif /* CONFIG_BT_ENABLED */ diff --git a/libesp32/NimBLE-Arduino/src/NimBLEClient.cpp b/libesp32/NimBLE-Arduino/src/NimBLEClient.cpp index 3930acf88..a385126d2 100644 --- a/libesp32/NimBLE-Arduino/src/NimBLEClient.cpp +++ b/libesp32/NimBLE-Arduino/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" @@ -40,8 +43,8 @@ static NimBLEClientCallbacks defaultCallbacks; * Since there is a hierarchical relationship here, we will have the idea that from a NimBLERemoteService will own * zero or more remote characteristics and a NimBLERemoteCharacteristic will own zero or more remote NimBLEDescriptors. * - * We will assume that a NimBLERemoteService contains a map that maps NimBLEUUIDs to the set of owned characteristics - * and that a NimBLECharacteristic contains a map that maps NimBLEUUIDs to the set of owned descriptors. + * We will assume that a NimBLERemoteService contains a vector of owned characteristics + * and that a NimBLECharacteristic contains a vector of owned descriptors. * * */ @@ -50,18 +53,17 @@ NimBLEClient::NimBLEClient() { m_pClientCallbacks = &defaultCallbacks; 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,12 +71,12 @@ 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) { + + if(m_deleteCallbacks && m_pClientCallbacks != &defaultCallbacks) { delete m_pClientCallbacks; } @@ -87,11 +89,11 @@ NimBLEClient::~NimBLEClient() { void NimBLEClient::clearServices() { NIMBLE_LOGD(LOG_TAG, ">> clearServices"); // Delete all the services. - for (auto &myPair : m_servicesMap) { - delete myPair.second; + for(auto &it: m_servicesVector) { + delete it; } - m_servicesMap.clear(); - m_haveServices = false; + m_servicesVector.clear(); + NIMBLE_LOGD(LOG_TAG, "<< clearServices"); } // clearServices @@ -101,10 +103,10 @@ void NimBLEClient::clearServices() { */ /* void NimBLEClient::onHostReset() { - + } - */ - + */ + /** * Add overloaded function to ease connect to peer device with not public address */ @@ -120,14 +122,14 @@ bool NimBLEClient::connect(NimBLEAdvertisedDevice* device, bool refreshServices) * @param [in] address The address of the partner. * @return True on success. */ -bool NimBLEClient::connect(NimBLEAddress address, uint8_t type, bool refreshServices) { +bool NimBLEClient::connect(const NimBLEAddress &address, uint8_t type, bool refreshServices) { NIMBLE_LOGD(LOG_TAG, ">> connect(%s)", address.toString().c_str()); - + 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 +137,15 @@ bool NimBLEClient::connect(NimBLEAddress address, uint8_t type, bool refreshServ 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 +155,21 @@ bool NimBLEClient::connect(NimBLEAddress address, uint8_t type, bool refreshServ 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,21 +180,9 @@ bool NimBLEClient::connect(NimBLEAddress address, uint8_t type, bool refreshServ 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 - disconnect(); - clearServices(); - return false; - } - else{ - NIMBLE_LOGD(LOG_TAG, "Found %d services", getServices()->size()); - } - } - m_pClientCallbacks->onConnect(this); - + m_pClientCallbacks->onConnect(this); + NIMBLE_LOGD(LOG_TAG, "<< connect()"); return true; } // connect @@ -204,23 +194,23 @@ bool NimBLEClient::connect(NimBLEAddress address, uint8_t type, bool refreshServ * @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 +230,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 +240,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 +264,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,19 +321,37 @@ 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 +/** + * @brief Get iterator to the beginning of the vector of remote service pointers. + * @return An iterator to the beginning of the vector of remote service pointers. + */ +std::vector::iterator NimBLEClient::begin() { + return m_servicesVector.begin(); +} + + +/** + * @brief Get iterator to the end of the vector of remote service pointers. + * @return An iterator to the end of the vector of remote service pointers. + */ +std::vector::iterator NimBLEClient::end() { + return m_servicesVector.end(); +} + + /** * @brief Get the service BLE Remote Service instance corresponding to the uuid. * @param [in] uuid The UUID of the service being sought. @@ -359,29 +367,62 @@ NimBLERemoteService* NimBLEClient::getService(const char* uuid) { * @param [in] uuid The UUID of the service being sought. * @return A reference to the Service or nullptr if don't know about it. */ -NimBLERemoteService* NimBLEClient::getService(NimBLEUUID uuid) { +NimBLERemoteService* NimBLEClient::getService(const NimBLEUUID &uuid) { NIMBLE_LOGD(LOG_TAG, ">> getService: uuid: %s", uuid.toString().c_str()); - if (!m_haveServices) { - return nullptr; - } - std::string uuidStr = uuid.toString(); - for (auto &myPair : m_servicesMap) { - if (myPair.first == uuidStr) { + for(auto &it: m_servicesVector) { + if(it->getUUID() == uuid) { NIMBLE_LOGD(LOG_TAG, "<< getService: found the service with uuid: %s", uuid.toString().c_str()); - return myPair.second; + return it; } - } + } + + size_t prev_size = m_servicesVector.size(); + if(retrieveServices(&uuid)) { + if(m_servicesVector.size() > prev_size) { + return m_servicesVector.back(); + } + } + NIMBLE_LOGD(LOG_TAG, "<< getService: not found"); return nullptr; } // getService /** - * @Get a pointer to the map of found services. - */ -std::map* NimBLEClient::getServices() { - return &m_servicesMap; + * @Get a pointer to the vector of found services. + * @param [in] bool value to indicate if the current vector should be cleared and + * subsequently all services retrieved from the peripheral. + * If false the vector will be returned with the currently stored services, + * if vector is empty it will retrieve all services from the peripheral. + * @return a pointer to the vector of available services. + */ +std::vector* NimBLEClient::getServices(bool refresh) { + if(refresh) { + clearServices(); + } + + if(m_servicesVector.empty()) { + if (!retrieveServices()) { + NIMBLE_LOGE(LOG_TAG, "Error: Failed to get services"); + } + else{ + NIMBLE_LOGI(LOG_TAG, "Found %d services", m_servicesVector.size()); + } + } + return &m_servicesVector; +} + + +/** + * @ Retrieves the full database of attributes that the peripheral has available. + */ +void NimBLEClient::discoverAttributes() { + for(auto svc: *getServices(true)) { + for(auto chr: *svc->getCharacteristics(true)) { + chr->getDescriptors(true); + } + } } @@ -391,44 +432,40 @@ 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() { + */ +bool NimBLEClient::retrieveServices(const NimBLEUUID *uuid_filter) { /** * Design * ------ * 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"); - + int rc = 0; + 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(uuid_filter == nullptr) { + rc = ble_gattc_disc_all_svcs(m_conn_id, NimBLEClient::serviceDiscoveredCB, this); + } else { + rc = ble_gattc_disc_svc_by_uuid(m_conn_id, &uuid_filter->getNative()->u, + 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); - if(m_haveServices){ - for (auto &myPair : m_servicesMap) { - if(!m_isConnected || !myPair.second->retrieveCharacteristics()) { - NIMBLE_LOGE(LOG_TAG, "Disconnected, could not retrieve characteristics -aborting"); - return false; - } - } - + if(m_semaphoreSearchCmplEvt.wait("retrieveServices") == 0){ NIMBLE_LOGD(LOG_TAG, "<< retrieveServices"); return true; } @@ -440,16 +477,18 @@ 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); + NIMBLE_LOGD(LOG_TAG,"Service Discovered >> status: %d handle: %d", + error->status, (error->status == 0) ? service->start_handle : -1); + NimBLEClient *peer = (NimBLEClient*)arg; int rc=0; @@ -460,13 +499,13 @@ int NimBLEClient::serviceDiscoveredCB( switch (error->status) { case 0: { - // Found a service - add it to the map + // Found a service - add it to the vector NimBLERemoteService* pRemoteService = new NimBLERemoteService(peer, service); - peer->m_servicesMap.insert(std::pair(pRemoteService->getUUID().toString(), pRemoteService)); + peer->m_servicesVector.push_back(pRemoteService); 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 +520,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; @@ -494,12 +533,13 @@ int NimBLEClient::serviceDiscoveredCB( * @param [in] characteristicUUID The characteristic whose value we wish to read. * @returns characteristic value or an empty string if not found */ -std::string NimBLEClient::getValue(NimBLEUUID serviceUUID, NimBLEUUID characteristicUUID) { - NIMBLE_LOGD(LOG_TAG, ">> getValue: serviceUUID: %s, characteristicUUID: %s", serviceUUID.toString().c_str(), characteristicUUID.toString().c_str()); - +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) { @@ -518,19 +558,22 @@ std::string NimBLEClient::getValue(NimBLEUUID serviceUUID, NimBLEUUID characteri * @param [in] characteristicUUID The characteristic whose value we wish to write. * @returns true if successful otherwise false */ -bool NimBLEClient::setValue(NimBLEUUID serviceUUID, NimBLEUUID characteristicUUID, std::string value) { - NIMBLE_LOGD(LOG_TAG, ">> setValue: serviceUUID: %s, characteristicUUID: %s", serviceUUID.toString().c_str(), characteristicUUID.toString().c_str()); - +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 +595,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 +609,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 +634,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 +654,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 +681,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,35 +697,45 @@ 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){ + + for(auto &it: client->m_servicesVector) { // Dont waste cycles searching services without this handle in their range - if(sPair.second->getEndHandle() < event->notify_rx.attr_handle) { + if(it->getEndHandle() < event->notify_rx.attr_handle) { continue; } - auto cMap = sPair.second->getCharacteristicsByHandle(); - NIMBLE_LOGD(LOG_TAG, "checking service %s for handle: %d", sPair.second->getUUID().toString().c_str(),event->notify_rx.attr_handle); - 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); + + auto cVector = &it->m_characteristicVector; + NIMBLE_LOGD(LOG_TAG, "checking service %s for handle: %d", + it->getUUID().toString().c_str(), + event->notify_rx.attr_handle); + + auto characteristic = cVector->cbegin(); + for(; characteristic != cVector->cend(); ++characteristic) { + if((*characteristic)->m_handle == event->notify_rx.attr_handle) + break; + } + + if(characteristic != cVector->cend()) { + NIMBLE_LOGD(LOG_TAG, "Got Notification for characteristic %s", (*characteristic)->toString().c_str()); + + if ((*characteristic)->m_notifyCallback != nullptr) { + NIMBLE_LOGD(LOG_TAG, "Invoking callback for notification on characteristic %s", + (*characteristic)->toString().c_str()); + (*characteristic)->m_notifyCallback(*characteristic, 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 +749,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 +761,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 +773,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 +802,14 @@ 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_mtu = event->mtu.value; + client->m_semaphoreOpenEvt.give(0); 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 +817,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 +831,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 +841,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 +856,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 +885,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 @@ -848,8 +900,9 @@ void NimBLEClient::setClientCallbacks(NimBLEClientCallbacks* pClientCallbacks, b std::string NimBLEClient::toString() { std::string res = "peer address: " + m_peerAddress.toString(); res += "\nServices:\n"; - for (auto &myPair : m_servicesMap) { - res += myPair.second->toString() + "\n"; + + for(auto &it: m_servicesVector) { + res += it->toString() + "\n"; } return res; @@ -865,7 +918,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 +943,5 @@ bool NimBLEClientCallbacks::onConfirmPIN(uint32_t pin){ return true; } +#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) #endif // CONFIG_BT_ENABLED diff --git a/libesp32/NimBLE-Arduino/src/NimBLEClient.h b/libesp32/NimBLE-Arduino/src/NimBLEClient.h index 3d3613c0f..4bf2c33d2 100644 --- a/libesp32/NimBLE-Arduino/src/NimBLEClient.h +++ b/libesp32/NimBLE-Arduino/src/NimBLEClient.h @@ -3,7 +3,7 @@ * * Created: on Jan 26 2020 * Author H2zero - * + * * Originally: * BLEClient.h * @@ -14,16 +14,24 @@ #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" #include "NimBLERemoteService.h" -#include +#include #include +typedef struct { + const NimBLEUUID *uuid; + const void *attribute; +} disc_filter_t; + class NimBLERemoteService; class NimBLEClientCallbacks; class NimBLEAdvertisedDevice; @@ -33,64 +41,68 @@ class NimBLEAdvertisedDevice; */ class NimBLEClient { public: - bool connect(NimBLEAdvertisedDevice* device, bool refreshServices = true); - bool connect(NimBLEAddress address, uint8_t type = BLE_ADDR_TYPE_PUBLIC, bool refreshServices = true); // Connect to the remote BLE Server - int disconnect(uint8_t reason = BLE_ERR_REM_USER_CONN_TERM); // Disconnect from the remote BLE Server - NimBLEAddress getPeerAddress(); // Get the address of the remote BLE Server - int getRssi(); // Get the RSSI of the remote BLE Server - std::map* getServices(); // Get a map of the services offered by the remote BLE Server - NimBLERemoteService* getService(const char* uuid); // Get a reference to a specified service offered by the remote BLE server. - NimBLERemoteService* getService(NimBLEUUID uuid); // Get a reference to a specified service offered by the remote BLE server. - std::string getValue(NimBLEUUID serviceUUID, NimBLEUUID characteristicUUID); // Get the value of a given characteristic at a given service. - bool setValue(NimBLEUUID serviceUUID, NimBLEUUID characteristicUUID, std::string value); // Set the value of a given characteristic at a given service. - bool isConnected(); // Return true if we are connected. - void setClientCallbacks(NimBLEClientCallbacks *pClientCallbacks, bool deleteCallbacks = true); - std::string toString(); // Return a string representation of this client. - uint16_t getConnId(); - uint16_t getMTU(); - bool secureConnection(); - void setConnectTimeout(uint8_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); - - + bool connect(NimBLEAdvertisedDevice* device, bool refreshServices = true); + bool connect(const NimBLEAddress &address, uint8_t type = BLE_ADDR_PUBLIC, + bool refreshServices = true); + int disconnect(uint8_t reason = BLE_ERR_REM_USER_CONN_TERM); + NimBLEAddress getPeerAddress(); + int getRssi(); + std::vector* getServices(bool refresh = false); + std::vector::iterator begin(); + std::vector::iterator end(); + NimBLERemoteService* getService(const char* uuid); + NimBLERemoteService* getService(const NimBLEUUID &uuid); + std::string getValue(const NimBLEUUID &serviceUUID, const NimBLEUUID &characteristicUUID); + bool setValue(const NimBLEUUID &serviceUUID, const NimBLEUUID &characteristicUUID, + const std::string &value); + bool isConnected(); + void setClientCallbacks(NimBLEClientCallbacks *pClientCallbacks, + bool deleteCallbacks = true); + std::string toString(); + uint16_t getConnId(); + uint16_t getMTU(); + bool secureConnection(); + void setConnectTimeout(uint8_t timeout); + void setConnectionParams(uint16_t minInterval, uint16_t maxInterval, + uint16_t latency, uint16_t timeout, + uint16_t scanInterval=16, uint16_t scanWindow=16); + void updateConnParams(uint16_t minInterval, uint16_t maxInterval, + uint16_t latency, uint16_t timeout); + void discoverAttributes(); + private: NimBLEClient(); ~NimBLEClient(); - friend class NimBLEDevice; - friend class NimBLERemoteService; - static int handleGapEvent(struct ble_gap_event *event, void *arg); - static int serviceDiscoveredCB(uint16_t conn_handle, const struct ble_gatt_error *error, const struct ble_gatt_svc *service, void *arg); - void clearServices(); // Clear any existing services. - bool retrieveServices(); //Retrieve services from the server -// void onHostReset(); + friend class NimBLEDevice; + friend class NimBLERemoteService; - NimBLEAddress m_peerAddress = NimBLEAddress("\0\0\0\0\0\0"); // The BD address of the remote server. - uint16_t m_conn_id; - bool m_haveServices = false; // Have we previously obtain the set of services from the remote server. - bool m_isConnected = false; // Are we currently connected. - bool m_waitingToConnect =false; - bool m_deleteCallbacks = true; - int32_t m_connectTimeout; - //uint16_t m_mtu = 23; + static int handleGapEvent(struct ble_gap_event *event, void *arg); + static int serviceDiscoveredCB(uint16_t conn_handle, + const struct ble_gatt_error *error, + const struct ble_gatt_svc *service, + void *arg); + void clearServices(); + bool retrieveServices(const NimBLEUUID *uuid_filter = nullptr); + NimBLEAddress m_peerAddress = NimBLEAddress(""); + uint16_t m_conn_id; + bool m_isConnected = false; + bool m_waitingToConnect =false; + bool m_deleteCallbacks = true; + int32_t m_connectTimeout; NimBLEClientCallbacks* m_pClientCallbacks = nullptr; - FreeRTOS::Semaphore m_semaphoreOpenEvt = FreeRTOS::Semaphore("OpenEvt"); FreeRTOS::Semaphore m_semaphoreSearchCmplEvt = FreeRTOS::Semaphore("SearchCmplEvt"); FreeRTOS::Semaphore m_semeaphoreSecEvt = FreeRTOS::Semaphore("Security"); - std::map m_servicesMap; - + std::vector m_servicesVector; + private: friend class NimBLEClientCallbacks; ble_gap_conn_params m_pConnParams; -}; // class NimBLEClient +}; // class NimBLEClient /** @@ -109,5 +121,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/libesp32/NimBLE-Arduino/src/NimBLEDescriptor.cpp b/libesp32/NimBLE-Arduino/src/NimBLEDescriptor.cpp index 828334505..0d414d316 100644 --- a/libesp32/NimBLE-Arduino/src/NimBLEDescriptor.cpp +++ b/libesp32/NimBLE-Arduino/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 @@ -187,13 +190,13 @@ void NimBLEDescriptor::setHandle(uint16_t handle) { * @param [in] data The data to set for the descriptor. * @param [in] length The length of the data in bytes. */ -void NimBLEDescriptor::setValue(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); +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); } // setValue @@ -201,16 +204,16 @@ void NimBLEDescriptor::setValue(uint8_t* data, size_t length) { * @brief Set the value of the descriptor. * @param [in] value The value of the descriptor in string form. */ -void NimBLEDescriptor::setValue(std::string value) { - setValue((uint8_t*) value.data(), value.length()); +void NimBLEDescriptor::setValue(const std::string &value) { + 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 /* CONFIG_BT_ENABLED */ \ No newline at end of file +#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) +#endif /* CONFIG_BT_ENABLED */ diff --git a/libesp32/NimBLE-Arduino/src/NimBLEDescriptor.h b/libesp32/NimBLE-Arduino/src/NimBLEDescriptor.h index 4f376a99b..8af3560d3 100644 --- a/libesp32/NimBLE-Arduino/src/NimBLEDescriptor.h +++ b/libesp32/NimBLE-Arduino/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(uint8_t* data, size_t size); // Set the value of the descriptor as a pointer to data. - void setValue(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_ */ \ No newline at end of file +#endif /* MAIN_NIMBLEDESCRIPTOR_H_ */ diff --git a/libesp32/NimBLE-Arduino/src/NimBLEDescriptorMap.cpp b/libesp32/NimBLE-Arduino/src/NimBLEDescriptorMap.cpp index 8d0a13d29..0ca1cbeeb 100644 --- a/libesp32/NimBLE-Arduino/src/NimBLEDescriptorMap.cpp +++ b/libesp32/NimBLE-Arduino/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)); } @@ -32,13 +36,13 @@ NimBLEDescriptor* NimBLEDescriptorMap::getByUUID(const char* uuid) { * @param [in] UUID The UUID to look up the descriptor. * @return The descriptor. If not present, then nullptr is returned. */ -NimBLEDescriptor* NimBLEDescriptorMap::getByUUID(NimBLEUUID uuid) { - for (auto &myPair : m_uuidMap) { - if (myPair.first->getUUID().equals(uuid)) { - return myPair.first; - } - } - return nullptr; +NimBLEDescriptor* NimBLEDescriptorMap::getByUUID(const NimBLEUUID &uuid) { + for (auto &myPair : m_uuidMap) { + if (myPair.first->getUUID().equals(uuid)) { + return myPair.first; + } + } + return nullptr; } // getByUUID @@ -49,7 +53,7 @@ NimBLEDescriptor* NimBLEDescriptorMap::getByUUID(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 @@ -71,8 +75,8 @@ void NimBLEDescriptorMap::setByUUID(const char* uuid, NimBLEDescriptor* pDescrip * @param [in] characteristic The descriptor to cache. * @return N/A. */ -void NimBLEDescriptorMap::setByUUID(NimBLEUUID uuid, NimBLEDescriptor* pDescriptor) { - m_uuidMap.insert(std::pair(pDescriptor, uuid.toString())); +void NimBLEDescriptorMap::setByUUID(const NimBLEUUID &uuid, NimBLEDescriptor* pDescriptor) { + m_uuidMap.insert(std::pair(pDescriptor, uuid.toString())); } // setByUUID @@ -84,7 +88,7 @@ void NimBLEDescriptorMap::setByUUID(NimBLEUUID uuid, NimBLEDescriptor* pDescript */ /* 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 /* CONFIG_BT_ENABLED */ \ No newline at end of file + +#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) +#endif /* CONFIG_BT_ENABLED */ diff --git a/libesp32/NimBLE-Arduino/src/NimBLEDevice.cpp b/libesp32/NimBLE-Arduino/src/NimBLEDevice.cpp index a8de6718c..1540f6327 100644 --- a/libesp32/NimBLE-Arduino/src/NimBLEDevice.cpp +++ b/libesp32/NimBLE-Arduino/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" @@ -39,38 +40,37 @@ static const char* LOG_TAG = "NimBLEDevice"; /** * Singletons for the NimBLEDevice. */ -bool NimBLEDevice_initialized = false; +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(); } @@ -79,22 +79,34 @@ NimBLESecurityCallbacks* NimBLEDevice::m_securityCallbacks = nullptr; } // createServer +/** + * @brief Get the instance of the server. + * @return A pointer to the server instance. + */ +/* STATIC */ NimBLEServer* NimBLEDevice::getServer() { + return m_pServer; +} // getServer +#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 +114,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 +151,7 @@ void NimBLEDevice::stopAdvertising() { if(pClient == nullptr) { return false; } - + if(pClient->m_isConnected) { if (pClient->disconnect() != 0) { return false; @@ -146,7 +160,7 @@ void NimBLEDevice::stopAdvertising() { vTaskDelay(1); } } - + if(pClient->m_waitingToConnect) { if(ble_gap_conn_cancel() != 0){ return false; @@ -155,10 +169,10 @@ void NimBLEDevice::stopAdvertising() { vTaskDelay(1); } } - + m_cList.remove(pClient); delete pClient; - + return true; } // deleteClient @@ -202,7 +216,7 @@ void NimBLEDevice::stopAdvertising() { * @param [in] a NimBLEAddress of the peer to search for. * @return A reference pointer to the client with the peer address. */ -/* STATIC */NimBLEClient* NimBLEDevice::getClientByPeerAddress(NimBLEAddress peer_addr) { +/* STATIC */NimBLEClient* NimBLEDevice::getClientByPeerAddress(const NimBLEAddress &peer_addr) { for(auto it = m_cList.cbegin(); it != m_cList.cend(); ++it) { if((*it)->getPeerAddress().equals(peer_addr)) { return (*it); @@ -225,18 +239,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 +267,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 +298,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 +325,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 +353,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,21 +394,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(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); - } - - if(m_bleAdvertising != nullptr) { - // Restart advertisng, parameters should already be set. - m_bleAdvertising->start(); + + 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 @@ -408,58 +436,57 @@ void NimBLEDevice::stopAdvertising() { * @brief Initialize the %BLE environment. * @param deviceName The device name of the device. */ -/* STATIC */ void NimBLEDevice::init(std::string deviceName) { - if(!NimBLEDevice_initialized){ - NimBLEDevice_initialized = true; // Set the initialization flag to ensure we are only initialized once. - +/* STATIC */ void NimBLEDevice::init(const std::string &deviceName) { + 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(); #endif errRc = nvs_flash_init(); - + if (errRc == ESP_ERR_NVS_NO_FREE_PAGES || errRc == ESP_ERR_NVS_NEW_VERSION_FOUND) { ESP_ERROR_CHECK(nvs_flash_erase()); errRc = nvs_flash_init(); } 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); ble_store_config_init(); - + nimble_port_freertos_init(NimBLEDevice::host_task); } // Wait for host and controller to sync before returning and accepting new tasks while(!m_synced){ vTaskDelay(1 / portTICK_PERIOD_MS); } - //vTaskDelay(200 / portTICK_PERIOD_MS); // Delay for 200 msecs as a workaround to an apparent Arduino environment issue. + + initialized = true; // Set the initialization flag to ensure we are only initialized once. } // init @@ -470,13 +497,14 @@ 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); } - - NimBLEDevice_initialized = false; + + initialized = false; + m_synced = false; } } // deinit @@ -485,7 +513,7 @@ void NimBLEDevice::stopAdvertising() { * @brief Check if the initialization is complete. */ bool NimBLEDevice::getInitialized() { - return NimBLEDevice_initialized; + return initialized; } // getInitialized @@ -507,12 +535,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, @@ -525,8 +553,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) { @@ -537,7 +565,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 @@ -551,7 +579,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 @@ -594,14 +622,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 @@ -610,7 +638,7 @@ void NimBLEDevice::setSecurityCallbacks(NimBLESecurityCallbacks* callbacks) { * @brief Check if the device address is on our ignore list. * @return True if ignoring. */ -/*STATIC*/ bool NimBLEDevice::isIgnored(NimBLEAddress address) { +/*STATIC*/ bool NimBLEDevice::isIgnored(const NimBLEAddress &address) { for(auto &it : m_ignoreList) { if(it.equals(address)){ return true; @@ -625,7 +653,7 @@ void NimBLEDevice::setSecurityCallbacks(NimBLESecurityCallbacks* callbacks) { * @brief Add a device to the ignore list. * @param Address of the device we want to ignore. */ -/*STATIC*/ void NimBLEDevice::addIgnored(NimBLEAddress address) { +/*STATIC*/ void NimBLEDevice::addIgnored(const NimBLEAddress &address) { m_ignoreList.push_back(address); } @@ -634,7 +662,7 @@ void NimBLEDevice::setSecurityCallbacks(NimBLESecurityCallbacks* callbacks) { * @brief Remove a device from the ignore list. * @param Address of the device we want to remove from the list. */ -/*STATIC*/void NimBLEDevice::removeIgnored(NimBLEAddress address) { +/*STATIC*/void NimBLEDevice::removeIgnored(const NimBLEAddress &address) { for(auto it = m_ignoreList.begin(); it != m_ignoreList.end(); ++it) { if((*it).equals(address)){ m_ignoreList.erase(it); @@ -659,20 +687,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/libesp32/NimBLE-Arduino/src/NimBLEDevice.h b/libesp32/NimBLE-Arduino/src/NimBLEDevice.h index b2731c23f..c4a6d0417 100644 --- a/libesp32/NimBLE-Arduino/src/NimBLEDevice.h +++ b/libesp32/NimBLE-Arduino/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,47 @@ #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(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(); + static NimBLEServer* getServer(); +#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); @@ -98,39 +118,69 @@ public: static void setSecurityCallbacks(NimBLESecurityCallbacks* pCallbacks); static int setMTU(uint16_t mtu); static uint16_t getMTU(); - static bool isIgnored(NimBLEAddress address); - static void addIgnored(NimBLEAddress address); - static void removeIgnored(NimBLEAddress address); + 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(NimBLEAddress peer_addr); + 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/libesp32/NimBLE-Arduino/src/NimBLEEddystoneTLM.cpp b/libesp32/NimBLE-Arduino/src/NimBLEEddystoneTLM.cpp index b601d8de0..990a36f52 100644 --- a/libesp32/NimBLE-Arduino/src/NimBLEEddystoneTLM.cpp +++ b/libesp32/NimBLE-Arduino/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() { @@ -116,37 +116,37 @@ std::string NimBLEEddystoneTLM::toString() { /** * Set the raw data for the beacon record. */ -void NimBLEEddystoneTLM::setData(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", +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", data.length(), sizeof(m_eddystoneData)); - return; - } + return; + } memcpy(&m_eddystoneData, data.data(), data.length()); } // setData -void NimBLEEddystoneTLM::setUUID(NimBLEUUID l_uuid) { - beaconUUID = l_uuid.getNative()->u16.value; +void NimBLEEddystoneTLM::setUUID(const NimBLEUUID &l_uuid) { + 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/libesp32/NimBLE-Arduino/src/NimBLEEddystoneTLM.h b/libesp32/NimBLE-Arduino/src/NimBLEEddystoneTLM.h index 3c7219eb6..eb1cb0721 100644 --- a/libesp32/NimBLE-Arduino/src/NimBLEEddystoneTLM.h +++ b/libesp32/NimBLE-Arduino/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(std::string data); - void setUUID(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/libesp32/NimBLE-Arduino/src/NimBLEEddystoneURL.cpp b/libesp32/NimBLE-Arduino/src/NimBLEEddystoneURL.cpp index c1d2aff6f..ce7975958 100644 --- a/libesp32/NimBLE-Arduino/src/NimBLEEddystoneURL.cpp +++ b/libesp32/NimBLE-Arduino/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 @@ -125,30 +125,30 @@ std::string NimBLEEddystoneURL::getDecodedURL() { /** * Set the raw data for the beacon record. */ -void NimBLEEddystoneURL::setData(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", +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", 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(NimBLEUUID l_uuid) { - beaconUUID = l_uuid.getNative()->u16.value; +void NimBLEEddystoneURL::setUUID(const NimBLEUUID &l_uuid) { + 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(std::string url) { +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/libesp32/NimBLE-Arduino/src/NimBLEEddystoneURL.h b/libesp32/NimBLE-Arduino/src/NimBLEEddystoneURL.h index 2e135886a..9c5f37f80 100644 --- a/libesp32/NimBLE-Arduino/src/NimBLEEddystoneURL.h +++ b/libesp32/NimBLE-Arduino/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(std::string data); - void setUUID(NimBLEUUID l_uuid); - void setPower(int8_t advertisedTxPower); - void setURL(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/libesp32/NimBLE-Arduino/src/NimBLELog.h b/libesp32/NimBLE-Arduino/src/NimBLELog.h index d223a046e..b519c0faa 100644 --- a/libesp32/NimBLE-Arduino/src/NimBLELog.h +++ b/libesp32/NimBLE-Arduino/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/libesp32/NimBLE-Arduino/src/NimBLERemoteCharacteristic.cpp b/libesp32/NimBLE-Arduino/src/NimBLERemoteCharacteristic.cpp index a48354c57..85760b433 100644 --- a/libesp32/NimBLE-Arduino/src/NimBLERemoteCharacteristic.cpp +++ b/libesp32/NimBLE-Arduino/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" @@ -32,27 +35,31 @@ static const char* LOG_TAG = "NimBLERemoteCharacteristic"; * ble_uuid_any_t uuid; * }; */ - NimBLERemoteCharacteristic::NimBLERemoteCharacteristic(NimBLERemoteService *pRemoteService, const struct ble_gatt_chr *chr) { + NimBLERemoteCharacteristic::NimBLERemoteCharacteristic(NimBLERemoteService *pRemoteService, + const struct ble_gatt_chr *chr) +{ switch (chr->uuid.u.type) { - 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: m_uuid = nullptr; break; } - m_handle = chr->val_handle; - m_defHandle = chr->def_handle; - m_charProp = chr->properties; - m_pRemoteService = pRemoteService; - m_notifyCallback = nullptr; + m_handle = chr->val_handle; + m_defHandle = chr->def_handle; + m_charProp = chr->properties; + m_pRemoteService = pRemoteService; + m_notifyCallback = nullptr; + m_rawData = nullptr; + m_dataLen = 0; } // NimBLERemoteCharacteristic @@ -61,7 +68,9 @@ static const char* LOG_TAG = "NimBLERemoteCharacteristic"; */ NimBLERemoteCharacteristic::~NimBLERemoteCharacteristic() { removeDescriptors(); // Release resources for any descriptor information we may have allocated. - if(m_rawData != nullptr) free(m_rawData); + if(m_rawData != nullptr) { + free(m_rawData); + } } // ~NimBLERemoteCharacteristic /* @@ -132,91 +141,170 @@ 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; + NIMBLE_LOGD(LOG_TAG,"Descriptor Discovered >> status: %d handle: %d", + error->status, (error->status == 0) ? dsc->handle : -1); + + disc_filter_t *filter = (disc_filter_t*)arg; + NimBLEUUID *uuid_filter = (NimBLEUUID*)filter->uuid; + NimBLERemoteCharacteristic *characteristic = (NimBLERemoteCharacteristic*)filter->attribute; int rc=0; // Make sure the discovery is for this device if(characteristic->getRemoteService()->getClient()->getConnId() != conn_handle){ return 0; } - + switch (error->status) { case 0: { - // Found a descriptor - add it to the map + if(dsc->uuid.u.type == BLE_UUID_TYPE_16 && dsc->uuid.u16.value == uint16_t(0x2803)) { + NIMBLE_LOGD(LOG_TAG,"Descriptor NOT found - end of Characteristic definintion"); + rc = BLE_HS_EDONE; + break; + } + if(uuid_filter != nullptr) { + if(ble_uuid_cmp(&uuid_filter->getNative()->u, &dsc->uuid.u) != 0) { + return 0; + } else { + NIMBLE_LOGD(LOG_TAG,"Descriptor Found"); + rc = BLE_HS_EDONE; + } + } + // Found a descriptor - add it to the vector NimBLERemoteDescriptor* pNewRemoteDescriptor = new NimBLERemoteDescriptor(characteristic, dsc); - characteristic->m_descriptorMap.insert(std::pair(pNewRemoteDescriptor->getUUID().toString(), pNewRemoteDescriptor)); - - break; - } - case BLE_HS_EDONE:{ - /* All descriptors in this characteristic discovered; */ - characteristic->m_semaphoreGetDescEvt.give(0); - rc = 0; + characteristic->m_descriptorVector.push_back(pNewRemoteDescriptor); break; } default: rc = error->status; break; } - if (rc != 0) { + + /** If rc == BLE_HS_EDONE, release the semaphore with a success error code and stop the discovery process. + * Else if rc == 0, just return 0 to continue the discovery until we get BLE_HS_EDONE. + * If we get any other error code tell the application to abort by returning non-zero in the semaphore rc. + */ + if (rc == BLE_HS_EDONE) { + characteristic->m_semaphoreGetDescEvt.give(0); + } else if(rc != 0) { /* Error; abort discovery. */ - // pass non-zero to semaphore on error to indicate an error finding descriptors - characteristic->m_semaphoreGetDescEvt.give(1); + // pass error code to semaphore waiting + characteristic->m_semaphoreGetDescEvt.give(rc); } NIMBLE_LOGD(LOG_TAG,"<< Descriptor Discovered. status: %d", rc); return rc; } + /** * @brief Populate the descriptors (if any) for this characteristic. * @param [in] the end handle of the characteristic, or the service, whichever comes first. */ -bool NimBLERemoteCharacteristic::retrieveDescriptors(uint16_t endHdl) { +bool NimBLERemoteCharacteristic::retrieveDescriptors(const NimBLEUUID *uuid_filter) { NIMBLE_LOGD(LOG_TAG, ">> retrieveDescriptors() for characteristic: %s", getUUID().toString().c_str()); int rc = 0; - //removeDescriptors(); // Remove any existing descriptors. - + disc_filter_t filter; + filter.uuid = uuid_filter; + filter.attribute = this; + m_semaphoreGetDescEvt.take("retrieveDescriptors"); - + rc = ble_gattc_disc_all_dscs(getRemoteService()->getClient()->getConnId(), m_handle, - endHdl, + getRemoteService()->getEndHandle(), NimBLERemoteCharacteristic::descriptorDiscCB, - this); + &filter); if (rc != 0) { NIMBLE_LOGE(LOG_TAG, "ble_gattc_disc_all_chrs: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc)); m_semaphoreGetDescEvt.give(); return false; } - - if(m_semaphoreGetDescEvt.wait("retrieveCharacteristics") != 0) { - // if there was an error release the resources - //removeDescriptors(); + + if(m_semaphoreGetDescEvt.wait("retrieveDescriptors") != 0) { return false; } - + return true; - NIMBLE_LOGD(LOG_TAG, "<< retrieveDescriptors(): Found %d descriptors.", m_descriptorMap.size()); + NIMBLE_LOGD(LOG_TAG, "<< retrieveDescriptors(): Found %d descriptors.", m_descriptorVector.size()); } // getDescriptors /** - * @brief Retrieve the map of descriptors keyed by UUID. - */ -std::map* NimBLERemoteCharacteristic::getDescriptors() { - return &m_descriptorMap; + * @brief Get the descriptor instance with the given UUID that belongs to this characteristic. + * @param [in] uuid The UUID of the descriptor to find. + * @return The Remote descriptor (if present) or null if not present. + */ +NimBLERemoteDescriptor* NimBLERemoteCharacteristic::getDescriptor(const NimBLEUUID &uuid) { + NIMBLE_LOGD(LOG_TAG, ">> getDescriptor: uuid: %s", uuid.toString().c_str()); + + for(auto &it: m_descriptorVector) { + if(it->getUUID() == uuid) { + NIMBLE_LOGD(LOG_TAG, "<< getDescriptor: found"); + return it; + } + } + + size_t prev_size = m_descriptorVector.size(); + if(retrieveDescriptors(&uuid)) { + if(m_descriptorVector.size() > prev_size) { + return m_descriptorVector.back(); + } + } + NIMBLE_LOGD(LOG_TAG, "<< getDescriptor: Not found"); + return nullptr; +} // getDescriptor + + +/** + * @Get a pointer to the vector of found descriptors. + * @param [in] bool value to indicate if the current vector should be cleared and + * subsequently all descriptors for this characteristic retrieved from the peripheral. + * If false the vector will be returned with the currently stored descriptors, + * if the vector is empty it will retrieve all descriptors for this characteristic + * from the peripheral. + * @return a pointer to the vector of descriptors for this characteristic. + */ +std::vector* NimBLERemoteCharacteristic::getDescriptors(bool refresh) { + if(refresh) { + removeDescriptors(); + } + + if(m_descriptorVector.empty()) { + if (!retrieveDescriptors()) { + NIMBLE_LOGE(LOG_TAG, "Error: Failed to get descriptors"); + } + else{ + NIMBLE_LOGI(LOG_TAG, "Found %d descriptor(s)", m_descriptorVector.size()); + } + } + return &m_descriptorVector; } // getDescriptors +/** + * @brief Get iterator to the beginning of the vector of remote descriptor pointers. + * @return An iterator to the beginning of the vector of remote descriptor pointers. + */ +std::vector::iterator NimBLERemoteCharacteristic::begin() { + return m_descriptorVector.begin(); +} + + +/** + * @brief Get iterator to the end of the vector of remote descriptor pointers. + * @return An iterator to the end of the vector of remote descriptor pointers. + */ +std::vector::iterator NimBLERemoteCharacteristic::end() { + return m_descriptorVector.end(); +} + + /** * @brief Get the handle for this characteristic. * @return The handle for this characteristic. @@ -234,25 +322,6 @@ uint16_t NimBLERemoteCharacteristic::getDefHandle() { } // getDefHandle -/** - * @brief Get the descriptor instance with the given UUID that belongs to this characteristic. - * @param [in] uuid The UUID of the descriptor to find. - * @return The Remote descriptor (if present) or null if not present. - */ -NimBLERemoteDescriptor* NimBLERemoteCharacteristic::getDescriptor(NimBLEUUID uuid) { - NIMBLE_LOGD(LOG_TAG, ">> getDescriptor: uuid: %s", uuid.toString().c_str()); - std::string v = uuid.toString(); - for (auto &myPair : m_descriptorMap) { - if (myPair.first == v) { - NIMBLE_LOGD(LOG_TAG, "<< getDescriptor: found"); - return myPair.second; - } - } - NIMBLE_LOGD(LOG_TAG, "<< getDescriptor: Not found"); - return nullptr; -} // getDescriptor - - /** * @brief Get the remote service associated with this characteristic. * @return The remote service associated with this characteristic. @@ -309,19 +378,22 @@ uint8_t NimBLERemoteCharacteristic::readUInt8() { return 0; } // readUInt8 - + /** * @brief Read the value of the remote characteristic. * @return The value of the remote characteristic. */ std::string NimBLERemoteCharacteristic::readValue() { - NIMBLE_LOGD(LOG_TAG, ">> readValue(): uuid: %s, handle: %d 0x%.2x", getUUID().toString().c_str(), getHandle(), getHandle()); + NIMBLE_LOGD(LOG_TAG, ">> readValue(): uuid: %s, handle: %d 0x%.2x", + getUUID().toString().c_str(), getHandle(), getHandle()); int rc = 0; int retryCount = 1; + // Clear the value before reading. + m_value = ""; NimBLEClient* pClient = getRemoteService()->getClient(); - + // Check to see that we are connected. if (!pClient->isConnected()) { NIMBLE_LOGE(LOG_TAG, "Disconnected"); @@ -330,38 +402,41 @@ std::string NimBLERemoteCharacteristic::readValue() { do { m_semaphoreReadCharEvt.take("readValue"); - - rc = ble_gattc_read(pClient->getConnId(), m_handle, - NimBLERemoteCharacteristic::onReadCB, this); - -// long read experiment -/* rc = ble_gattc_read_long(pClient->getConnId(), m_handle, 0, - NimBLERemoteCharacteristic::onReadCB, this); -*/ + + rc = ble_gattc_read_long(pClient->getConnId(), m_handle, 0, + NimBLERemoteCharacteristic::onReadCB, + this); if (rc != 0) { - NIMBLE_LOGE(LOG_TAG, "Error: Failed to read characteristic; rc=%d", rc); - m_semaphoreReadCharEvt.give(); + NIMBLE_LOGE(LOG_TAG, "Error: Failed to read characteristic; rc=%d, %s", + rc, NimBLEUtils::returnCodeToString(rc)); + m_semaphoreReadCharEvt.give(0); return ""; } - + rc = m_semaphoreReadCharEvt.wait("readValue"); switch(rc){ case 0: + case BLE_HS_EDONE: + rc = 0; + break; + // 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; 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 (rc == 0) ? m_value : ""; + return m_value; } // readValue @@ -371,39 +446,28 @@ 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; - - // Make sure the discovery is for this device - if(characteristic->getRemoteService()->getClient()->getConnId() != conn_handle){ + uint16_t conn_id = characteristic->getRemoteService()->getClient()->getConnId(); + + // Make sure the read is for this client + if(conn_id != conn_handle) { return 0; } NIMBLE_LOGI(LOG_TAG, "Read complete; status=%d conn_handle=%d", error->status, conn_handle); -// long read experiment -/* if(attr && (attr->om->om_len >= (ble_att_mtu(characteristic->getRemoteService()->getClient()->getConnId()) - 1))){ - - return 0; + + if(error->status == 0) { + if(attr) { + NIMBLE_LOGD(LOG_TAG, "Got %d bytes", attr->om->om_len); + + characteristic->m_value += std::string((char*) attr->om->om_data, attr->om->om_len); + return 0; + } } -*/ - - if(characteristic->m_rawData != nullptr) { - free(characteristic->m_rawData); - } - - if (error->status == 0) { - characteristic->m_value = std::string((char*) attr->om->om_data, attr->om->om_len); - characteristic->m_rawData = (uint8_t*) calloc(attr->om->om_len, sizeof(uint8_t)); - memcpy(characteristic->m_rawData, attr->om->om_data, attr->om->om_len); - characteristic->m_semaphoreReadCharEvt.give(0); - } else { - characteristic->m_rawData = nullptr; - characteristic->m_value = ""; - characteristic->m_semaphoreReadCharEvt.give(error->status); - } - -// characteristic->m_semaphoreReadCharEvt.give(error->status); - return 0; //1 + // Read complete release semaphore and let the app can continue. + characteristic->m_semaphoreReadCharEvt.give(error->status); + return 0; } @@ -423,7 +487,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){ @@ -437,25 +501,24 @@ bool NimBLERemoteCharacteristic::registerForNotify(notify_callback notifyCallbac } NIMBLE_LOGD(LOG_TAG, "<< registerForNotify()"); - + return desc->writeValue(val, 2, response); } // registerForNotify /** - * @brief Delete the descriptors in the descriptor map. - * We maintain a map called m_descriptorMap that contains pointers to BLERemoteDescriptors - * object references. Since we allocated these in this class, we are also responsible for deleteing - * them. This method does just that. + * @brief Delete the descriptors in the descriptor vector. + * We maintain a vector called m_descriptorVector that contains pointers to BLERemoteDescriptors + * object references. Since we allocated these in this class, we are also responsible for deleteing + * them. This method does just that. * @return N/A. */ void NimBLERemoteCharacteristic::removeDescriptors() { - // Iterate through all the descriptors releasing their storage and erasing them from the map. - for (auto &myPair : m_descriptorMap) { - m_descriptorMap.erase(myPair.first); - delete myPair.second; + // Iterate through all the descriptors releasing their storage and erasing them from the vector. + for(auto &it: m_descriptorVector) { + delete it; } - m_descriptorMap.clear(); // Technically not neeeded, but just to be sure. + m_descriptorVector.clear(); } // removeCharacteristics @@ -476,11 +539,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(); + + for(auto &it: m_descriptorVector) { + res += "\n" + it->toString(); } - + return res; } // toString @@ -491,7 +554,7 @@ std::string NimBLERemoteCharacteristic::toString() { * @param [in] response Do we expect a response? * @return false if not connected or cant perform write for some reason. */ -bool NimBLERemoteCharacteristic::writeValue(std::string newValue, bool response) { +bool NimBLERemoteCharacteristic::writeValue(const std::string &newValue, bool response) { return writeValue((uint8_t*)newValue.c_str(), strlen(newValue.c_str()), response); } // writeValue @@ -516,62 +579,70 @@ bool NimBLERemoteCharacteristic::writeValue(uint8_t newValue, bool response) { * @param [in] response Whether we require a response from the write. * @return false if not connected or cant perform write for some reason. */ -bool NimBLERemoteCharacteristic::writeValue(uint8_t* data, size_t length, bool response) { - +bool NimBLERemoteCharacteristic::writeValue(const uint8_t* data, size_t length, bool response) { + NIMBLE_LOGD(LOG_TAG, ">> writeValue(), length: %d", length); - + NimBLEClient* pClient = getRemoteService()->getClient(); int rc = 0; int retryCount = 1; -// uint16_t mtu; - + 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; - if(/*!length > mtu &&*/ !response) { + mtu = ble_att_mtu(pClient->getConnId()) - 3; + + // Check if the data length is longer than we can write in 1 connection event. + // If so we must do a long write which requires a response. + if(length <= mtu && !response) { rc = ble_gattc_write_no_rsp_flat(pClient->getConnId(), m_handle, data, length); return (rc==0); } - + do { m_semaphoreWriteCharEvt.take("writeValue"); -// long write experiment -/* if(length > mtu) { - NIMBLE_LOGD(LOG_TAG,"long write"); + + if(length > mtu) { + NIMBLE_LOGI(LOG_TAG,"long write %d bytes", length); os_mbuf *om = ble_hs_mbuf_from_flat(data, length); rc = ble_gattc_write_long(pClient->getConnId(), m_handle, 0, om, - NimBLERemoteCharacteristic::onWriteCB, + NimBLERemoteCharacteristic::onWriteCB, this); } else { -*/ - rc = ble_gattc_write_flat(pClient->getConnId(), m_handle, - data, length, - NimBLERemoteCharacteristic::onWriteCB, - this); -// } + rc = ble_gattc_write_flat(pClient->getConnId(), m_handle, + data, length, + NimBLERemoteCharacteristic::onWriteCB, + this); + } if (rc != 0) { NIMBLE_LOGE(LOG_TAG, "Error: Failed to write characteristic; rc=%d", rc); m_semaphoreWriteCharEvt.give(); return false; } - + rc = m_semaphoreWriteCharEvt.wait("writeValue"); switch(rc){ case 0: + case BLE_HS_EDONE: + 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; } @@ -588,44 +659,61 @@ bool NimBLERemoteCharacteristic::writeValue(uint8_t* data, size_t length, bool r */ 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 + + // 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); - - if (error->status == 0) { - characteristic->m_semaphoreWriteCharEvt.give(0); - } else { + characteristic->m_semaphoreWriteCharEvt.give(error->status); - characteristic->m_semaphoreWriteCharEvt.give(error->status); - } - return 0; } /** * @brief Read raw data from remote characteristic as hex bytes - * @return return pointer data read + * @return uint8_t pointer to the data read. */ uint8_t* NimBLERemoteCharacteristic::readRawData() { + if(m_rawData != nullptr) { + free(m_rawData); + m_rawData = nullptr; + } + + m_dataLen = m_value.length(); + // If we have data copy it to rawData + if(m_dataLen) { + m_rawData = (uint8_t*) calloc(m_dataLen, sizeof(uint8_t)); + memcpy(m_rawData, m_value.data(), m_dataLen); + } + return m_rawData; } +/** + * @brief Get the length of the data read from the remote characteristic. + * @return size_t length of the data in bytes. + */ +size_t NimBLERemoteCharacteristic::getDataLength() { + return m_value.length(); +} + + void NimBLERemoteCharacteristic::releaseSemaphores() { - for (auto &dPair : m_descriptorMap) { - dPair.second->releaseSemaphores(); + for (auto &it: m_descriptorVector) { + it->releaseSemaphores(); } m_semaphoreWriteCharEvt.give(1); m_semaphoreGetDescEvt.give(1); m_semaphoreReadCharEvt.give(1); } + +#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) #endif /* CONFIG_BT_ENABLED */ diff --git a/libesp32/NimBLE-Arduino/src/NimBLERemoteCharacteristic.h b/libesp32/NimBLE-Arduino/src/NimBLERemoteCharacteristic.h index c107be79d..0b7d490d6 100644 --- a/libesp32/NimBLE-Arduino/src/NimBLERemoteCharacteristic.h +++ b/libesp32/NimBLE-Arduino/src/NimBLERemoteCharacteristic.h @@ -3,7 +3,7 @@ * * Created: on Jan 27 2020 * Author H2zero - * + * * Originally: * * BLERemoteCharacteristic.h @@ -17,19 +17,20 @@ #include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) -//#include "NimBLEUUID.h" -//#include "FreeRTOS.h" +#include "nimconfig.h" +#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) + #include "NimBLERemoteService.h" #include "NimBLERemoteDescriptor.h" -//#include -#include +#include class NimBLERemoteService; class NimBLERemoteDescriptor; -typedef void (*notify_callback)(NimBLERemoteCharacteristic* pBLERemoteCharacteristic, uint8_t* pData, size_t length, bool isNotify); +typedef void (*notify_callback)(NimBLERemoteCharacteristic* pBLERemoteCharacteristic, + uint8_t* pData, size_t length, bool isNotify); /** * @brief A model of a remote %BLE characteristic. @@ -39,47 +40,58 @@ public: ~NimBLERemoteCharacteristic(); // Public member functions - bool canBroadcast(); - bool canIndicate(); - bool canNotify(); - bool canRead(); - bool canWrite(); - bool canWriteNoResponse(); - NimBLERemoteDescriptor* getDescriptor(NimBLEUUID uuid); - std::map* getDescriptors(); - uint16_t getHandle(); - uint16_t getDefHandle(); - NimBLEUUID getUUID(); - std::string readValue(); - uint8_t readUInt8(); - uint16_t readUInt16(); - uint32_t readUInt32(); - bool registerForNotify(notify_callback _callback, bool notifications = true, bool response = true); - bool writeValue(uint8_t* data, size_t length, bool response = false); - bool writeValue(std::string newValue, bool response = false); - bool writeValue(uint8_t newValue, bool response = false); - std::string toString(); - uint8_t* readRawData(); - NimBLERemoteService* getRemoteService(); + bool canBroadcast(); + bool canIndicate(); + bool canNotify(); + bool canRead(); + bool canWrite(); + bool canWriteNoResponse(); + std::vector::iterator begin(); + std::vector::iterator end(); + NimBLERemoteDescriptor* getDescriptor(const NimBLEUUID &uuid); + std::vector* getDescriptors(bool refresh = false); + uint16_t getHandle(); + uint16_t getDefHandle(); + NimBLEUUID getUUID(); + std::string readValue(); + uint8_t readUInt8(); + uint16_t readUInt16(); + uint32_t readUInt32(); + bool registerForNotify(notify_callback _callback, + bool notifications = true, + bool response = true); + bool writeValue(const uint8_t* data, + size_t length, + bool response = false); + bool writeValue(const std::string &newValue, + bool response = false); + bool writeValue(uint8_t newValue, + bool response = false); + std::string toString(); + uint8_t* readRawData(); + size_t getDataLength(); + NimBLERemoteService* getRemoteService(); private: NimBLERemoteCharacteristic(NimBLERemoteService *pRemoteservice, const struct ble_gatt_chr *chr); - - friend class NimBLEClient; - friend class NimBLERemoteService; - friend class NimBLERemoteDescriptor; + + friend class NimBLEClient; + friend class NimBLERemoteService; + friend class NimBLERemoteDescriptor; // Private member functions void removeDescriptors(); - bool retrieveDescriptors(uint16_t endHdl); - static int onReadCB(uint16_t conn_handle, const struct ble_gatt_error *error, struct ble_gatt_attr *attr, void *arg); - static int onWriteCB(uint16_t conn_handle, const struct ble_gatt_error *error, struct ble_gatt_attr *attr, void *arg); + bool retrieveDescriptors(const NimBLEUUID *uuid_filter = nullptr); + static int onReadCB(uint16_t conn_handle, const struct ble_gatt_error *error, + struct ble_gatt_attr *attr, void *arg); + static int onWriteCB(uint16_t conn_handle, const struct ble_gatt_error *error, + struct ble_gatt_attr *attr, void *arg); void releaseSemaphores(); 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); - + uint16_t chr_val_handle, const struct ble_gatt_dsc *dsc, + void *arg); + // Private properties NimBLEUUID m_uuid; uint8_t m_charProp; @@ -90,11 +102,14 @@ private: FreeRTOS::Semaphore m_semaphoreReadCharEvt = FreeRTOS::Semaphore("ReadCharEvt"); FreeRTOS::Semaphore m_semaphoreWriteCharEvt = FreeRTOS::Semaphore("WriteCharEvt"); std::string m_value; - uint8_t* m_rawData = nullptr; + uint8_t* m_rawData; + size_t m_dataLen; notify_callback m_notifyCallback; - // We maintain a map of descriptors owned by this characteristic keyed by a string representation of the UUID. - std::map m_descriptorMap; -}; // BLERemoteCharacteristic + // We maintain a vector of descriptors owned by this characteristic. + std::vector m_descriptorVector; +}; // NimBLERemoteCharacteristic + +#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) #endif /* CONFIG_BT_ENABLED */ #endif /* COMPONENTS_NIMBLEREMOTECHARACTERISTIC_H_ */ diff --git a/libesp32/NimBLE-Arduino/src/NimBLERemoteDescriptor.cpp b/libesp32/NimBLE-Arduino/src/NimBLERemoteDescriptor.cpp index d862a8cd0..057a68a1c 100644 --- a/libesp32/NimBLE-Arduino/src/NimBLERemoteDescriptor.cpp +++ b/libesp32/NimBLE-Arduino/src/NimBLERemoteDescriptor.cpp @@ -3,7 +3,7 @@ * * Created: on Jan 27 2020 * Author H2zero - * + * * Originally: * * BLERemoteDescriptor.cpp @@ -14,7 +14,11 @@ #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" static const char* LOG_TAG = "NimBLERemoteDescriptor"; @@ -24,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, - const struct ble_gatt_dsc *dsc) +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: @@ -43,7 +47,7 @@ NimBLERemoteDescriptor::NimBLERemoteDescriptor(NimBLERemoteCharacteristic* pRemo } m_handle = dsc->handle; m_pRemoteCharacteristic = pRemoteCharacteristic; - + } @@ -80,75 +84,87 @@ 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(desc->getRemoteCharacteristic()->getRemoteService()->getClient()->getConnId() != conn_handle){ + 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) { - desc->m_value = std::string((char*) attr->om->om_data, attr->om->om_len); - desc->m_semaphoreReadDescrEvt.give(0); - } else { - desc->m_value = ""; - desc->m_semaphoreReadDescrEvt.give(error->status); + + if(error->status == 0){ + if(attr){ + NIMBLE_LOGD(LOG_TAG, "Got %d bytes", attr->om->om_len); + + desc->m_value += std::string((char*) attr->om->om_data, attr->om->om_len); + return 0; + } } - + + // Read complete release semaphore and let the app can continue. + desc->m_semaphoreReadDescrEvt.give(error->status); return 0; } std::string NimBLERemoteDescriptor::readValue() { NIMBLE_LOGD(LOG_TAG, ">> Descriptor readValue: %s", toString().c_str()); - - NimBLEClient* pClient = getRemoteCharacteristic()->getRemoteService()->getClient(); - + 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(pClient->getConnId(), m_handle, - NimBLERemoteDescriptor::onReadCB, this); - + + rc = ble_gattc_read_long(pClient->getConnId(), m_handle, 0, + NimBLERemoteDescriptor::onReadCB, + this); if (rc != 0) { - NIMBLE_LOGE(LOG_TAG, "Descriptor read failed, code: %d", rc); - m_semaphoreReadDescrEvt.give(); + NIMBLE_LOGE(LOG_TAG, "Error: Failed to read descriptor; rc=%d, %s", + rc, NimBLEUtils::returnCodeToString(rc)); + m_semaphoreReadDescrEvt.give(0); return ""; } - + rc = m_semaphoreReadDescrEvt.wait("ReadDescriptor"); switch(rc){ case 0: + case BLE_HS_EDONE: + rc = 0; + break; + // 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; 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, "<< Descriptor readValue(): length: %d, rc: %d", m_value.length(), rc); - - return (rc == 0) ? m_value : ""; + NIMBLE_LOGD(LOG_TAG, "<< Descriptor readValue(): length: %d", m_value.length()); + return m_value; } // readValue @@ -189,7 +205,7 @@ std::string NimBLERemoteDescriptor::toString() { res += ", handle: "; snprintf(val, sizeof(val), "%d", getHandle()); res += val; - + return res; } // toString @@ -200,23 +216,19 @@ 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 + + // Make sure the discovery is for this device if(descriptor->getRemoteCharacteristic()->getRemoteService()->getClient()->getConnId() != conn_handle){ return 0; } - + NIMBLE_LOGD(LOG_TAG, "Write complete; status=%d conn_handle=%d", error->status, conn_handle); - - if (error->status == 0) { - descriptor->m_semaphoreDescWrite.give(0); - } else { - descriptor->m_semaphoreDescWrite.give(error->status); - } - + + descriptor->m_semaphoreDescWrite.give(error->status); + return 0; } @@ -227,58 +239,79 @@ int NimBLERemoteDescriptor::onWriteCB(uint16_t conn_handle, * @param [in] length The length of the data to send. * @param [in] response True if we expect a response. */ -bool NimBLERemoteDescriptor::writeValue(uint8_t* data, size_t length, bool response) { +bool NimBLERemoteDescriptor::writeValue(const uint8_t* data, size_t length, bool response) { NIMBLE_LOGD(LOG_TAG, ">> Descriptor writeValue: %s", toString().c_str()); - + 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; } - - if(!response) { + + mtu = ble_att_mtu(pClient->getConnId()) - 3; + + // Check if the data length is longer than we can write in 1 connection event. + // If so we must do a long write which requires a response. + if(length <= mtu && !response) { rc = ble_gattc_write_no_rsp_flat(pClient->getConnId(), m_handle, data, length); - return (rc==0); + return (rc == 0); } - + do { m_semaphoreDescWrite.take("WriteDescriptor"); - - rc = ble_gattc_write_flat(pClient->getConnId(), m_handle, - data, length, - NimBLERemoteDescriptor::onWriteCB, - this); + + if(length > mtu) { + NIMBLE_LOGI(LOG_TAG,"long write %d bytes", length); + os_mbuf *om = ble_hs_mbuf_from_flat(data, length); + rc = ble_gattc_write_long(pClient->getConnId(), m_handle, 0, om, + NimBLERemoteDescriptor::onWriteCB, + this); + } else { + rc = ble_gattc_write_flat(pClient->getConnId(), m_handle, + data, length, + NimBLERemoteDescriptor::onWriteCB, + this); + } + if (rc != 0) { NIMBLE_LOGE(LOG_TAG, "Error: Failed to write descriptor; rc=%d", rc); m_semaphoreDescWrite.give(); return false; } - + rc = m_semaphoreDescWrite.wait("WriteDescriptor"); switch(rc){ case 0: + case BLE_HS_EDONE: + 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; } } while(rc != 0 && retryCount--); NIMBLE_LOGD(LOG_TAG, "<< Descriptor writeValue, rc: %d",rc); - return (rc == 0); //true; + return (rc == 0); } // writeValue @@ -287,7 +320,7 @@ bool NimBLERemoteDescriptor::writeValue(uint8_t* data, size_t length, bool respo * @param [in] newValue The data to send to the remote descriptor. * @param [in] response True if we expect a response. */ -bool NimBLERemoteDescriptor::writeValue(std::string newValue, bool response) { +bool NimBLERemoteDescriptor::writeValue(const std::string &newValue, bool response) { return writeValue((uint8_t*) newValue.data(), newValue.length(), response); } // writeValue @@ -309,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/libesp32/NimBLE-Arduino/src/NimBLERemoteDescriptor.h b/libesp32/NimBLE-Arduino/src/NimBLERemoteDescriptor.h index 004d89705..23fe13f6b 100644 --- a/libesp32/NimBLE-Arduino/src/NimBLERemoteDescriptor.h +++ b/libesp32/NimBLE-Arduino/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; @@ -25,34 +28,40 @@ class NimBLERemoteCharacteristic; */ class NimBLERemoteDescriptor { public: - uint16_t getHandle(); + uint16_t getHandle(); NimBLERemoteCharacteristic* getRemoteCharacteristic(); - NimBLEUUID getUUID(); - std::string readValue(void); - uint8_t readUInt8(void); - uint16_t readUInt16(void); - uint32_t readUInt32(void); - std::string toString(void); - bool writeValue(uint8_t* data, size_t length, bool response = false); - bool writeValue(std::string newValue, bool response = false); - bool writeValue(uint8_t newValue, bool response = false); + NimBLEUUID getUUID(); + std::string readValue(void); + uint8_t readUInt8(void); + uint16_t readUInt16(void); + uint32_t readUInt32(void); + std::string toString(void); + bool writeValue(const uint8_t* data, size_t length, bool response = false); + bool writeValue(const std::string &newValue, bool response = false); + bool writeValue(uint8_t newValue, bool response = false); private: - friend class NimBLERemoteCharacteristic; - NimBLERemoteDescriptor(NimBLERemoteCharacteristic* pRemoteCharacteristic, const struct ble_gatt_dsc *dsc); - static int onWriteCB(uint16_t conn_handle, const struct ble_gatt_error *error, struct ble_gatt_attr *attr, void *arg); - static int onReadCB(uint16_t conn_handle, const struct ble_gatt_error *error, struct ble_gatt_attr *attr, void *arg); - void releaseSemaphores(); + friend class NimBLERemoteCharacteristic; - uint16_t m_handle; // Server handle of this descriptor. - NimBLEUUID m_uuid; // UUID of this descriptor. - std::string m_value; // Last received value of the descriptor. - NimBLERemoteCharacteristic* m_pRemoteCharacteristic; // Reference to the Remote characteristic of which this descriptor is associated. + NimBLERemoteDescriptor (NimBLERemoteCharacteristic* pRemoteCharacteristic, + const struct ble_gatt_dsc *dsc); + static int onWriteCB(uint16_t conn_handle, const struct ble_gatt_error *error, + struct ble_gatt_attr *attr, void *arg); + static int onReadCB(uint16_t conn_handle, const struct ble_gatt_error *error, + struct ble_gatt_attr *attr, void *arg); + void releaseSemaphores(); + + uint16_t m_handle; + NimBLEUUID m_uuid; + std::string m_value; + NimBLERemoteCharacteristic* m_pRemoteCharacteristic; FreeRTOS::Semaphore m_semaphoreReadDescrEvt = FreeRTOS::Semaphore("ReadDescrEvt"); FreeRTOS::Semaphore m_semaphoreDescWrite = FreeRTOS::Semaphore("WriteDescEvt"); }; + +#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) #endif /* CONFIG_BT_ENABLED */ #endif /* COMPONENTS_NIMBLEREMOTEDESCRIPTOR_H_ */ diff --git a/libesp32/NimBLE-Arduino/src/NimBLERemoteService.cpp b/libesp32/NimBLE-Arduino/src/NimBLERemoteService.cpp index 28c2cc33e..193a40b1a 100644 --- a/libesp32/NimBLE-Arduino/src/NimBLERemoteService.cpp +++ b/libesp32/NimBLE-Arduino/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()"); + NIMBLE_LOGD(LOG_TAG, ">> NimBLERemoteService()"); 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: @@ -46,43 +49,63 @@ NimBLERemoteService::NimBLERemoteService(NimBLEClient* pClient, const struct ble } m_startHandle = service->start_handle; m_endHandle = service->end_handle; - m_haveCharacteristics = false; - - NIMBLE_LOGD(LOG_TAG, "<< BLERemoteService()"); + NIMBLE_LOGD(LOG_TAG, "<< NimBLERemoteService()"); } /** * @brief When deleting the service make sure we delete all characteristics and descriptors. * Also release any semaphores they may be holding. - */ + */ NimBLERemoteService::~NimBLERemoteService() { removeCharacteristics(); } +/** + * @brief Get iterator to the beginning of the vector of remote characteristic pointers. + * @return An iterator to the beginning of the vector of remote characteristic pointers. + */ +std::vector::iterator NimBLERemoteService::begin() { + return m_characteristicVector.begin(); +} + + +/** + * @brief Get iterator to the end of the vector of remote characteristic pointers. + * @return An iterator to the end of the vector of remote characteristic pointers. + */ +std::vector::iterator NimBLERemoteService::end() { + return m_characteristicVector.end(); +} + + /** * @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. * @return Reference to the characteristic object, or nullptr if not found. */ -NimBLERemoteCharacteristic* NimBLERemoteService::getCharacteristic(NimBLEUUID uuid) { - if (m_haveCharacteristics) { - std::string v = uuid.toString(); - for (auto &myPair : m_characteristicMap) { - if (myPair.first == v) { - return myPair.second; - } +NimBLERemoteCharacteristic* NimBLERemoteService::getCharacteristic(const NimBLEUUID &uuid) { + for(auto &it: m_characteristicVector) { + if(it->getUUID() == uuid) { + return it; + } + } + + size_t prev_size = m_characteristicVector.size(); + if(retrieveCharacteristics(&uuid)) { + if(m_characteristicVector.size() > prev_size) { + return m_characteristicVector.back(); } } @@ -90,15 +113,43 @@ NimBLERemoteCharacteristic* NimBLERemoteService::getCharacteristic(NimBLEUUID uu } // getCharacteristic +/** + * @Get a pointer to the vector of found characteristics. + * @param [in] bool value to indicate if the current vector should be cleared and + * subsequently all characteristics for this service retrieved from the peripheral. + * If false the vector will be returned with the currently stored characteristics, + * if the vector is empty it will retrieve all characteristics of this service + * from the peripheral. + * @return a pointer to the vector of descriptors for this characteristic. + */ + +std::vector* NimBLERemoteService::getCharacteristics(bool refresh) { + if(refresh) { + removeCharacteristics(); + } + + if(m_characteristicVector.empty()) { + if (!retrieveCharacteristics()) { + NIMBLE_LOGE(LOG_TAG, "Error: Failed to get characteristics"); + } + else{ + NIMBLE_LOGI(LOG_TAG, "Found %d characteristics", m_characteristicVector.size()); + } + } + return &m_characteristicVector; +} // getCharacteristics + + /** * @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); - + NIMBLE_LOGD(LOG_TAG,"Characteristic Discovered >> status: %d handle: %d", + error->status, (error->status == 0) ? chr->val_handle : -1); + NimBLERemoteService *service = (NimBLERemoteService*)arg; int rc=0; @@ -106,13 +157,12 @@ 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 + // Found a service - add it to the vector NimBLERemoteCharacteristic* pRemoteCharacteristic = new NimBLERemoteCharacteristic(service, chr); - service->m_characteristicMap.insert(std::pair(pRemoteCharacteristic->getUUID().toString(), pRemoteCharacteristic)); - service->m_characteristicMapByHandle.insert(std::pair(chr->val_handle, pRemoteCharacteristic)); + service->m_characteristicVector.push_back(pRemoteCharacteristic); break; } case BLE_HS_EDONE:{ @@ -145,84 +195,46 @@ int NimBLERemoteService::characteristicDiscCB(uint16_t conn_handle, * This function will not return until we have all the characteristics. * @return N/A */ -bool NimBLERemoteService::retrieveCharacteristics() { +bool NimBLERemoteService::retrieveCharacteristics(const NimBLEUUID *uuid_filter) { 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, - NimBLERemoteService::characteristicDiscCB, - this); + + if(uuid_filter == nullptr) { + rc = ble_gattc_disc_all_chrs(m_pClient->getConnId(), + m_startHandle, + m_endHandle, + NimBLERemoteService::characteristicDiscCB, + this); + } else { + rc = ble_gattc_disc_chrs_by_uuid(m_pClient->getConnId(), + m_startHandle, + m_endHandle, + &uuid_filter->getNative()->u, + NimBLERemoteService::characteristicDiscCB, + this); + } + if (rc != 0) { NIMBLE_LOGE(LOG_TAG, "ble_gattc_disc_all_chrs: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc)); - m_haveCharacteristics = false; m_semaphoreGetCharEvt.give(); return false; } - - m_haveCharacteristics = (m_semaphoreGetCharEvt.wait("retrieveCharacteristics") == 0); - if(m_haveCharacteristics){ - uint16_t endHdl = 0xFFFF; - NIMBLE_LOGD(LOG_TAG, "Found %d Characteristics", m_characteristicMapByHandle.size()); - for (auto it = m_characteristicMapByHandle.cbegin(); it != m_characteristicMapByHandle.cend(); ++it) { - 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{ - 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)) { - return false; - } - } - //NIMBLE_LOGD(LOG_TAG, "Found %d Characteristics in service UUID: %s", chars->size(), myPair.first.c_str()); - } - + + if(m_semaphoreGetCharEvt.wait("retrieveCharacteristics") == 0){ NIMBLE_LOGD(LOG_TAG, "<< retrieveCharacteristics()"); return true; } - + NIMBLE_LOGE(LOG_TAG, "Could not retrieve characteristics"); return false; - + } // retrieveCharacteristics -/** - * @brief Retrieve a map of all the characteristics of this service. - * @return A map of all the characteristics of this service. - */ -std::map* NimBLERemoteService::getCharacteristics() { - return &m_characteristicMap; -} // getCharacteristics - - -/** - * @brief Retrieve a map of all the characteristics of this service. - * @return A map of all the characteristics of this service. - */ -std::map* NimBLERemoteService::getCharacteristicsByHandle() { - return &m_characteristicMapByHandle; -} // getCharacteristicsByHandle - - /** * @brief Get the client associated with this service. * @return A reference to the client associated with this service. @@ -261,12 +273,12 @@ NimBLEUUID NimBLERemoteService::getUUID() { * @param [in] characteristicUuid The characteristic to read. * @returns a string containing the value or an empty string if not found or error. */ -std::string NimBLERemoteService::getValue(NimBLEUUID characteristicUuid) { +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(); } @@ -282,12 +294,12 @@ std::string NimBLERemoteService::getValue(NimBLEUUID characteristicUuid) { * @param [in] value The value to set. * @returns true on success, false if not found or error */ -bool NimBLERemoteService::setValue(NimBLEUUID characteristicUuid, std::string value) { +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); } @@ -298,20 +310,17 @@ bool NimBLERemoteService::setValue(NimBLEUUID characteristicUuid, std::string va /** - * @brief Delete the characteristics in the characteristics map. - * We maintain a map called m_characteristicsMap that contains pointers to BLERemoteCharacteristic - * object references. Since we allocated these in this class, we are also responsible for deleteing - * them. This method does just that. + * @brief Delete the characteristics in the characteristics vector. + * We maintain a vector called m_characteristicsVector that contains pointers to BLERemoteCharacteristic + * object references. Since we allocated these in this class, we are also responsible for deleting + * them. This method does just that. * @return N/A. */ void NimBLERemoteService::removeCharacteristics() { - m_characteristicMap.clear(); // Clear the map - - for (auto &myPair : m_characteristicMapByHandle) { - delete myPair.second; + for(auto &it: m_characteristicVector) { + delete it; } - m_characteristicMapByHandle.clear(); // Clear the map - + m_characteristicVector.clear(); // Clear the vector } // removeCharacteristics @@ -334,9 +343,9 @@ 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(); + + for (auto &it: m_characteristicVector) { + res += "\n" + it->toString(); } return res; @@ -345,13 +354,14 @@ 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) { - cPair.second->releaseSemaphores(); + for(auto &it: m_characteristicVector) { + it->releaseSemaphores(); } m_semaphoreGetCharEvt.give(1); } +#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) #endif /* CONFIG_BT_ENABLED */ diff --git a/libesp32/NimBLE-Arduino/src/NimBLERemoteService.h b/libesp32/NimBLE-Arduino/src/NimBLERemoteService.h index bef8f0b52..3803498d0 100644 --- a/libesp32/NimBLE-Arduino/src/NimBLERemoteService.h +++ b/libesp32/NimBLE-Arduino/src/NimBLERemoteService.h @@ -3,7 +3,7 @@ * * Created: on Jan 27 2020 * Author H2zero - * + * * Originally: * * BLERemoteService.h @@ -17,12 +17,15 @@ #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" #include "NimBLERemoteCharacteristic.h" -#include +#include class NimBLEClient; class NimBLERemoteCharacteristic; @@ -36,54 +39,51 @@ public: virtual ~NimBLERemoteService(); // Public methods - NimBLERemoteCharacteristic* getCharacteristic(const char* uuid); // Get the specified characteristic reference. - NimBLERemoteCharacteristic* getCharacteristic(NimBLEUUID uuid); // Get the specified characteristic reference. -// BLERemoteCharacteristic* getCharacteristic(uint16_t uuid); // Get the specified characteristic reference. - std::map* getCharacteristics(); - std::map* getCharacteristicsByHandle(); // Get the characteristics map. -// void getCharacteristics(std::map* pCharacteristicMap); - - NimBLEClient* getClient(void); // Get a reference to the client associated with this service. - uint16_t getHandle(); // Get the handle of this service. - NimBLEUUID getUUID(void); // Get the UUID of this service. - std::string getValue(NimBLEUUID characteristicUuid); // Get the value of a characteristic. - bool setValue(NimBLEUUID characteristicUuid, std::string value); // Set the value of a characteristic. - std::string toString(void); + std::vector::iterator begin(); + std::vector::iterator end(); + NimBLERemoteCharacteristic* getCharacteristic(const char* uuid); + NimBLERemoteCharacteristic* getCharacteristic(const NimBLEUUID &uuid); + NimBLEClient* getClient(void); + uint16_t getHandle(); + NimBLEUUID getUUID(void); + std::string getValue(const NimBLEUUID &characteristicUuid); + bool setValue(const NimBLEUUID &characteristicUuid, + const std::string &value); + std::string toString(void); + std::vector* getCharacteristics(bool refresh = false); 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; friend class NimBLERemoteCharacteristic; // Private methods - bool retrieveCharacteristics(void); // Retrieve the characteristics from the BLE Server. - static int characteristicDiscCB(uint16_t conn_handle, - const struct ble_gatt_error *error, - const struct ble_gatt_chr *chr, void *arg); + bool retrieveCharacteristics(const NimBLEUUID *uuid_filter = nullptr); + static int characteristicDiscCB(uint16_t conn_handle, + const struct ble_gatt_error *error, + const struct ble_gatt_chr *chr, + void *arg); - uint16_t getStartHandle(); // Get the start handle for this service. - uint16_t getEndHandle(); // Get the end handle for this service. + uint16_t getStartHandle(); + uint16_t getEndHandle(); void releaseSemaphores(); void removeCharacteristics(); // Properties - // We maintain a map of characteristics owned by this service keyed by a string representation of the UUID. - std::map m_characteristicMap; + // We maintain a vector of characteristics owned by this service. + std::vector m_characteristicVector; - // We maintain a map of characteristics owned by this service keyed by a handle. - std::map m_characteristicMapByHandle; - - bool m_haveCharacteristics; // Have we previously obtained the characteristics. NimBLEClient* m_pClient; FreeRTOS::Semaphore m_semaphoreGetCharEvt = FreeRTOS::Semaphore("GetCharEvt"); - NimBLEUUID m_uuid; // The UUID of this service. - uint16_t m_startHandle; // The starting handle of this service. - uint16_t m_endHandle; // The ending handle of this service. -}; // BLERemoteService + NimBLEUUID m_uuid; + uint16_t m_startHandle; + uint16_t m_endHandle; +}; // NimBLERemoteService +#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) #endif /* CONFIG_BT_ENABLED */ #endif /* COMPONENTS_NIMBLEREMOTESERVICE_H_ */ diff --git a/libesp32/NimBLE-Arduino/src/NimBLEScan.cpp b/libesp32/NimBLE-Arduino/src/NimBLEScan.cpp index e5cbed1f0..6d738f951 100644 --- a/libesp32/NimBLE-Arduino/src/NimBLEScan.cpp +++ b/libesp32/NimBLE-Arduino/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) @@ -63,7 +66,7 @@ NimBLEScan::NimBLEScan() { m_scan_params.itvl = 0; // This is defined as the time interval from when the Controller started its last LE scan until it begins the subsequent LE scan. (units=0.625 msec) m_scan_params.window = 0; // The duration of the LE scan. LE_Scan_Window shall be less than or equal to LE_Scan_Interval (units=0.625 msec) m_scan_params.limited = 0; // If set, only discover devices in limited discoverable mode. - m_scan_params.filter_duplicates = 1; // If set, the controller ignores all but the first advertisement from each device. + m_scan_params.filter_duplicates = 0; // If set, the controller ignores all but the first advertisement from each device. m_pAdvertisedDeviceCallbacks = nullptr; m_stopped = true; m_wantDuplicates = false; @@ -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,16 +114,18 @@ NimBLEScan::NimBLEScan() { NIMBLE_LOGI(LOG_TAG, "Ignoring device: address: %s", advertisedAddress.toString().c_str()); return 0; } - - 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()) { - advertisedDevice = (*it).second; + + NimBLEAdvertisedDevice* advertisedDevice = nullptr; + + // If we've seen this device before get a pointer to it from the vector + for(auto &it: pScan->m_scanResults.m_advertisedDevicesVector) { + if(it->getAddress() == advertisedAddress) { + advertisedDevice = it; + break; + } } - // If we haven't seen this device before; create a new instance and insert it in the map. + // If we haven't seen this device before; create a new instance and insert it in the vector. // Otherwise just update the relevant parameters of the already known device. if(advertisedDevice == nullptr){ advertisedDevice = new NimBLEAdvertisedDevice(); @@ -128,20 +133,20 @@ NimBLEScan::NimBLEScan() { advertisedDevice->setAddress(advertisedAddress); //NIMBLE_LOGE(LOG_TAG, "advertisement type: %d, %s",event->disc.event_type, NimBLEUtils::advTypeToString(event->disc.event_type)); advertisedDevice->setAdvType(event->disc.event_type); - pScan->m_scanResults.m_advertisedDevicesMap.insert(std::pair(advertisedAddress.toString(), advertisedDevice)); + pScan->m_scanResults.m_advertisedDevicesVector.push_back(advertisedDevice); NIMBLE_LOGI(LOG_TAG, "NEW DEVICE FOUND: %s", advertisedAddress.toString().c_str()); } 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); if (pScan->m_pAdvertisedDeviceCallbacks) { // If not active scanning report the result to the listener. - if(pScan->m_scan_params.passive) { + if(pScan->m_scan_params.passive || event->disc.event_type == BLE_HCI_ADV_TYPE_ADV_NONCONN_IND) { pScan->m_pAdvertisedDeviceCallbacks->onResult(advertisedDevice); // Otherwise wait for the scan response so we can report all of the data at once. } else if (event->disc.event_type == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP) { @@ -155,13 +160,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 +229,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 +249,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 +262,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 + // then we should not clear vector 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 +310,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,23 +318,28 @@ void NimBLEScan::stop() { } m_stopped = true; - + if (m_scanCompleteCB != nullptr) { m_scanCompleteCB(m_scanResults); } - + m_semaphoreScanEnd.give(); - + NIMBLE_LOGD(LOG_TAG, "<< stop()"); } // stop // delete peer device from cache after disconnecting, it is required in case we are connecting to devices with not public address -void NimBLEScan::erase(NimBLEAddress address) { +void NimBLEScan::erase(const NimBLEAddress &address) { NIMBLE_LOGI(LOG_TAG, "erase device: %s", address.toString().c_str()); - NimBLEAdvertisedDevice *advertisedDevice = m_scanResults.m_advertisedDevicesMap.find(address.toString())->second; - m_scanResults.m_advertisedDevicesMap.erase(address.toString()); - delete advertisedDevice; + + for(auto it = m_scanResults.m_advertisedDevicesVector.begin(); it != m_scanResults.m_advertisedDevicesVector.end(); ++it) { + if((*it)->getAddress() == address) { + delete *it; + m_scanResults.m_advertisedDevicesVector.erase(it); + break; + } + } } @@ -356,10 +366,10 @@ NimBLEScanResults NimBLEScan::getResults() { * @brief Clear the results of the scan. */ void NimBLEScan::clearResults() { - for(auto _dev : m_scanResults.m_advertisedDevicesMap){ - delete _dev.second; + for(auto &it: m_scanResults.m_advertisedDevicesVector) { + delete it; } - m_scanResults.m_advertisedDevicesMap.clear(); + m_scanResults.m_advertisedDevicesVector.clear(); } @@ -379,7 +389,7 @@ void NimBLEScanResults::dump() { * @return The number of devices found in the last scan. */ int NimBLEScanResults::getCount() { - return m_advertisedDevicesMap.size(); + return m_advertisedDevicesVector.size(); } // getCount @@ -390,14 +400,43 @@ int NimBLEScanResults::getCount() { * @return The device at the specified index. */ NimBLEAdvertisedDevice NimBLEScanResults::getDevice(uint32_t i) { - uint32_t x = 0; - NimBLEAdvertisedDevice dev = *m_advertisedDevicesMap.begin()->second; - for (auto it = m_advertisedDevicesMap.begin(); it != m_advertisedDevicesMap.end(); it++) { - dev = *it->second; - if (x==i) break; - x++; - } - return dev; + return *m_advertisedDevicesVector[i]; } + +/** + * @brief Get iterator to the beginning of the vector of advertised device pointers. + * @return An iterator to the beginning of the vector of advertised device pointers. + */ +std::vector::iterator NimBLEScanResults::begin() { + return m_advertisedDevicesVector.begin(); +} + + +/** + * @brief Get iterator to the end of the vector of advertised device pointers. + * @return An iterator to the end of the vector of advertised device pointers. + */ +std::vector::iterator NimBLEScanResults::end() { + return m_advertisedDevicesVector.end(); +} + + +/** + * @brief Return a pointer to the specified device at the given address. + * If the address is not found a nullptr is returned. + * @param [in] address The address of the device. + * @return A pointer to the device at the specified address. + */ +NimBLEAdvertisedDevice *NimBLEScanResults::getDevice(const NimBLEAddress &address) { + for(size_t index = 0; index < m_advertisedDevicesVector.size(); index++) { + if(m_advertisedDevicesVector[index]->getAddress() == address) { + return m_advertisedDevicesVector[index]; + } + } + + return nullptr; +} + +#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) #endif /* CONFIG_BT_ENABLED */ diff --git a/libesp32/NimBLE-Arduino/src/NimBLEScan.h b/libesp32/NimBLE-Arduino/src/NimBLEScan.h index a19a3da0e..3cab25784 100644 --- a/libesp32/NimBLE-Arduino/src/NimBLEScan.h +++ b/libesp32/NimBLE-Arduino/src/NimBLEScan.h @@ -3,7 +3,7 @@ * * Created: on Jan 24 2020 * Author H2zero - * + * * Originally: * * BLEScan.h @@ -16,17 +16,21 @@ #include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) +#include "nimconfig.h" +#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) + #include "NimBLEAdvertisedDevice.h" #include "FreeRTOS.h" #include "host/ble_gap.h" -#include +#include class NimBLEDevice; class NimBLEScan; class NimBLEAdvertisedDevice; class NimBLEAdvertisedDeviceCallbacks; +class NimBLEAddress; /** * @brief The result of having performed a scan. @@ -37,13 +41,16 @@ class NimBLEAdvertisedDeviceCallbacks; */ class NimBLEScanResults { public: - void dump(); - int getCount(); - NimBLEAdvertisedDevice getDevice(uint32_t i); + void dump(); + int getCount(); + NimBLEAdvertisedDevice getDevice(uint32_t i); + std::vector::iterator begin(); + std::vector::iterator end(); + NimBLEAdvertisedDevice *getDevice(const NimBLEAddress &address); private: friend NimBLEScan; - std::map m_advertisedDevicesMap; + std::vector m_advertisedDevicesVector; }; /** @@ -62,15 +69,15 @@ public: void stop(); void clearResults(); NimBLEScanResults getResults(); - void erase(NimBLEAddress address); - - + 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 +89,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/libesp32/NimBLE-Arduino/src/NimBLESecurity.cpp b/libesp32/NimBLE-Arduino/src/NimBLESecurity.cpp index 0651858d0..8a0dbd952 100644 --- a/libesp32/NimBLE-Arduino/src/NimBLESecurity.cpp +++ b/libesp32/NimBLE-Arduino/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/libesp32/NimBLE-Arduino/src/NimBLESecurity.h b/libesp32/NimBLE-Arduino/src/NimBLESecurity.h index 60e4f443d..50c732c9b 100644 --- a/libesp32/NimBLE-Arduino/src/NimBLESecurity.h +++ b/libesp32/NimBLE-Arduino/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/libesp32/NimBLE-Arduino/src/NimBLEServer.cpp b/libesp32/NimBLE-Arduino/src/NimBLEServer.cpp index 5e94b563d..d731bad5b 100644 --- a/libesp32/NimBLE-Arduino/src/NimBLEServer.cpp +++ b/libesp32/NimBLE-Arduino/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)); } @@ -62,21 +65,21 @@ NimBLEService* NimBLEServer::createService(const char* uuid) { * @param [in] inst_id With multiple services with the same UUID we need to provide inst_id value different for each service. * @return A reference to the new service object. */ -NimBLEService* NimBLEServer::createService(NimBLEUUID uuid, uint32_t numHandles, uint8_t inst_id) { - NIMBLE_LOGD(LOG_TAG, ">> createService - %s", uuid.toString().c_str()); +NimBLEService* NimBLEServer::createService(const NimBLEUUID &uuid, uint32_t numHandles, uint8_t inst_id) { + 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(NimBLEUUID uuid, uint32_t numHandles, * @return A reference to the service object. */ NimBLEService* NimBLEServer::getServiceByUUID(const char* uuid) { - return m_serviceMap.getByUUID(uuid); + return m_serviceMap.getByUUID(uuid); } @@ -95,8 +98,8 @@ NimBLEService* NimBLEServer::getServiceByUUID(const char* uuid) { * @param [in] uuid The UUID of the new service. * @return A reference to the service object. */ -NimBLEService* NimBLEServer::getServiceByUUID(NimBLEUUID uuid) { - return m_serviceMap.getByUUID(uuid); +NimBLEService* NimBLEServer::getServiceByUUID(const NimBLEUUID &uuid) { + return m_serviceMap.getByUUID(uuid); } @@ -106,7 +109,7 @@ NimBLEService* NimBLEServer::getServiceByUUID(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 // CONFIG_BT_ENABLED \ No newline at end of file + +#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) +#endif // CONFIG_BT_ENABLED diff --git a/libesp32/NimBLE-Arduino/src/NimBLEServer.h b/libesp32/NimBLE-Arduino/src/NimBLEServer.h index 436f20361..903eb2392 100644 --- a/libesp32/NimBLE-Arduino/src/NimBLEServer.h +++ b/libesp32/NimBLE-Arduino/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,11 +47,11 @@ typedef struct { class NimBLEServiceMap { public: // NimBLEService* getByHandle(uint16_t handle); - NimBLEService* getByUUID(const char* uuid); - NimBLEService* getByUUID(NimBLEUUID uuid, uint8_t inst_id = 0); + 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); - void setByUUID(NimBLEUUID uuid, NimBLEService* service); + void setByUUID(const NimBLEUUID &uuid, NimBLEService* service); std::string toString(); NimBLEService* getFirst(); NimBLEService* getNext(); @@ -69,8 +71,8 @@ private: class NimBLEServer { public: uint32_t getConnectedCount(); - NimBLEService* createService(const char* uuid); - NimBLEService* createService(NimBLEUUID uuid, uint32_t numHandles=15, uint8_t inst_id=0); + 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); void startAdvertising(); @@ -78,11 +80,11 @@ public: void start(); // void removeService(BLEService* service); NimBLEService* getServiceByUUID(const char* uuid); - NimBLEService* getServiceByUUID(NimBLEUUID uuid); + 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_ */ \ No newline at end of file +#endif /* MAIN_NIMBLESERVER_H_ */ diff --git a/libesp32/NimBLE-Arduino/src/NimBLEService.cpp b/libesp32/NimBLE-Arduino/src/NimBLEService.cpp index 4bf6f34ff..6036a38ad 100644 --- a/libesp32/NimBLE-Arduino/src/NimBLEService.cpp +++ b/libesp32/NimBLE-Arduino/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) { } @@ -43,11 +46,11 @@ NimBLEService::NimBLEService(const char* uuid, uint16_t numHandles, NimBLEServer * @param [in] uuid The UUID of the service. * @param [in] numHandles The maximum number of handles associated with the service. */ -NimBLEService::NimBLEService(NimBLEUUID uuid, uint16_t numHandles, NimBLEServer* pServer) { - m_uuid = uuid; - m_handle = NULL_HANDLE; - m_pServer = pServer; - m_numHandles = numHandles; +NimBLEService::NimBLEService(const NimBLEUUID &uuid, uint16_t numHandles, NimBLEServer* pServer) { + m_uuid = uuid; + m_handle = NULL_HANDLE; + m_pServer = pServer; + m_numHandles = numHandles; } // NimBLEService @@ -56,10 +59,10 @@ NimBLEService::NimBLEService(NimBLEUUID uuid, uint16_t numHandles, NimBLEServer* * @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,45 +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) || - (pCharacteristic->m_properties & BLE_GATT_CHR_F_NOTIFY)) { + 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 { @@ -139,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 @@ -183,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 @@ -198,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 @@ -207,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 @@ -237,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); } @@ -247,21 +251,21 @@ NimBLECharacteristic* NimBLEService::createCharacteristic(const char* uuid, uint * @param [in] properties - The properties of the characteristic. * @return The new BLE characteristic. */ -NimBLECharacteristic* NimBLEService::createCharacteristic(NimBLEUUID uuid, uint32_t properties) { - NimBLECharacteristic* pCharacteristic = new NimBLECharacteristic(uuid, properties, this); - addCharacteristic(pCharacteristic); +NimBLECharacteristic* NimBLEService::createCharacteristic(const NimBLEUUID &uuid, uint32_t properties) { + 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(NimBLEUUID uuid) { - return m_characteristicMap.getByUUID(uuid); +NimBLECharacteristic* NimBLEService::getCharacteristic(const NimBLEUUID &uuid) { + return m_characteristicMap.getByUUID(uuid); } @@ -273,12 +277,12 @@ NimBLECharacteristic* NimBLEService::getCharacteristic(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 @@ -287,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 // CONFIG_BT_ENABLED \ No newline at end of file +#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) +#endif // CONFIG_BT_ENABLED diff --git a/libesp32/NimBLE-Arduino/src/NimBLEService.h b/libesp32/NimBLE-Arduino/src/NimBLEService.h index 70fed3bb2..1cb0f6153 100644 --- a/libesp32/NimBLE-Arduino/src/NimBLEService.h +++ b/libesp32/NimBLE-Arduino/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, NimBLEUUID uuid); - void setByHandle(uint16_t handle, NimBLECharacteristic* pCharacteristic); - NimBLECharacteristic* getByUUID(const char* uuid); - NimBLECharacteristic* getByUUID(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(NimBLEUUID uuid, - uint32_t properties = NIMBLE_PROPERTY::READ | - NIMBLE_PROPERTY::WRITE); - - void dump(); - NimBLECharacteristic* getCharacteristic(const char* uuid); - NimBLECharacteristic* getCharacteristic(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(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_ */ \ No newline at end of file +#endif /* MAIN_NIMBLESERVICE_H_ */ diff --git a/libesp32/NimBLE-Arduino/src/NimBLEServiceMap.cpp b/libesp32/NimBLE-Arduino/src/NimBLEServiceMap.cpp index 779c49a13..e5b96e676 100644 --- a/libesp32/NimBLE-Arduino/src/NimBLEServiceMap.cpp +++ b/libesp32/NimBLE-Arduino/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)); } /** @@ -31,14 +34,14 @@ NimBLEService* NimBLEServiceMap::getByUUID(const char* uuid) { * @param [in] UUID The UUID to look up the service. * @return The characteristic. */ -NimBLEService* NimBLEServiceMap::getByUUID(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; +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; } // getByUUID @@ -49,7 +52,7 @@ NimBLEService* NimBLEServiceMap::getByUUID(NimBLEUUID uuid, uint8_t inst_id) { */ /* NimBLEService* NimBLEServiceMap::getByHandle(uint16_t handle) { - return m_handleMap.at(handle); + return m_handleMap.at(handle); } // getByHandle */ @@ -59,8 +62,8 @@ NimBLEService* NimBLEServiceMap::getByHandle(uint16_t handle) { * @param [in] characteristic The service to cache. * @return N/A. */ -void NimBLEServiceMap::setByUUID(NimBLEUUID uuid, NimBLEService* service) { - m_uuidMap.insert(std::pair(service, uuid.toString())); +void NimBLEServiceMap::setByUUID(const NimBLEUUID &uuid, NimBLEService* service) { + m_uuidMap.insert(std::pair(service, uuid.toString())); } // setByUUID @@ -72,7 +75,7 @@ void NimBLEServiceMap::setByUUID(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 /* CONFIG_BT_ENABLED */ \ No newline at end of file + +#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) +#endif /* CONFIG_BT_ENABLED */ diff --git a/libesp32/NimBLE-Arduino/src/NimBLEUUID.cpp b/libesp32/NimBLE-Arduino/src/NimBLEUUID.cpp index 0002d1911..4a9d7e876 100644 --- a/libesp32/NimBLE-Arduino/src/NimBLEUUID.cpp +++ b/libesp32/NimBLE-Arduino/src/NimBLEUUID.cpp @@ -3,7 +3,7 @@ * * Created: on Jan 24 2020 * Author H2zero - * + * * Originally: * * BLEUUID.cpp @@ -18,6 +18,8 @@ #include "NimBLEUUID.h" #include "NimBLELog.h" +#include + static const char* LOG_TAG = "NimBLEUUID"; @@ -38,54 +40,29 @@ static const char* LOG_TAG = "NimBLEUUID"; * * @param [in] value The string to build a UUID from. */ - NimBLEUUID::NimBLEUUID(std::string value) { + NimBLEUUID::NimBLEUUID(const std::string &value) { m_valueSet = true; if (value.length() == 4) { m_uuid.u.type = BLE_UUID_TYPE_16; - m_uuid.u16.value = 0; - for(int i=0;i '9') MSB -= 7; - if(LSB > '9') LSB -= 7; - m_uuid.u16.value += (((MSB&0x0F) <<4) | (LSB & 0x0F))<<(2-i)*4; - i+=2; - } + m_uuid.u16.value = strtoul(value.c_str(), NULL, 16); } else if (value.length() == 8) { m_uuid.u.type = BLE_UUID_TYPE_32; - m_uuid.u32.value = 0; - for(int i=0;i '9') MSB -= 7; - if(LSB > '9') LSB -= 7; - m_uuid.u32.value += (((MSB&0x0F) <<4) | (LSB & 0x0F))<<(6-i)*4; - i+=2; - } + m_uuid.u32.value = strtoul(value.c_str(), NULL, 16); } - else if (value.length() == 16) { // how we can have 16 byte length string reprezenting 128 bit uuid??? needs to be investigated (lack of time) - m_uuid.u.type = BLE_UUID_TYPE_128; - NimBLEUtils::memrcpy(m_uuid.u128.value, (uint8_t*)value.data(), 16); + else if (value.length() == 16) { + *this = NimBLEUUID((uint8_t*)value.data(), 16, true); } else if (value.length() == 36) { // If the length of the string is 36 bytes then we will assume it is a long hex string in // UUID format. - m_uuid.u.type = BLE_UUID_TYPE_128; - int n = 0; - for(int i=0;i '9') MSB -= 7; - if(LSB > '9') LSB -= 7; - m_uuid.u128.value[15-n++] = ((MSB&0x0F) <<4) | (LSB & 0x0F); - i+=2; - } + 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); + *this = NimBLEUUID(first, second, third, (uint64_t(fourth) << 48) + fifth); } else { NIMBLE_LOGE(LOG_TAG,"ERROR: UUID value not 2, 4, 16 or 36 bytes"); @@ -101,7 +78,7 @@ static const char* LOG_TAG = "NimBLEUUID"; * @param [in] size The size of the data. * @param [in] msbFirst Is the MSB first in pData memory? */ -NimBLEUUID::NimBLEUUID(uint8_t* pData, size_t size, bool msbFirst) { +NimBLEUUID::NimBLEUUID(const uint8_t* pData, size_t size, bool msbFirst) { /*** TODO: change this to use the Nimble function for various lenght UUIDs: int ble_uuid_init_from_buf(ble_uuid_any_t *uuid, const void *buf, size_t len); ***/ @@ -110,8 +87,9 @@ NimBLEUUID::NimBLEUUID(uint8_t* pData, size_t size, bool msbFirst) { return; } m_uuid.u.type = BLE_UUID_TYPE_128; + if (msbFirst) { - NimBLEUtils::memrcpy(m_uuid.u128.value, pData, 16); + std::reverse_copy(pData, pData + 16, m_uuid.u128.value); } else { memcpy(m_uuid.u128.value, pData, 16); } @@ -148,14 +126,33 @@ NimBLEUUID::NimBLEUUID(uint32_t uuid) { * * @param [in] uuid The native UUID. */ - -NimBLEUUID::NimBLEUUID(ble_uuid128_t* uuid) { +NimBLEUUID::NimBLEUUID(const ble_uuid128_t* uuid) { m_uuid.u.type = BLE_UUID_TYPE_128; memcpy(m_uuid.u128.value, uuid->value, 16); m_valueSet = true; } // NimBLEUUID +/** + * @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. + * @param [in] second The next 16bit of the UUID. + * @param [in] third The next 16bit of the UUID. + * @param [in] fourth The last 64bit of the UUID, combining the last 2 parts of the string equivalent + */ +NimBLEUUID::NimBLEUUID(uint32_t first, uint16_t second, uint16_t third, uint64_t fourth) { + m_uuid.u.type = BLE_UUID_TYPE_128; + memcpy(m_uuid.u128.value + 12, &first, 4); + memcpy(m_uuid.u128.value + 10, &second, 2); + memcpy(m_uuid.u128.value + 8, &third, 2); + memcpy(m_uuid.u128.value, &fourth, 8); + m_valueSet = true; +} + + NimBLEUUID::NimBLEUUID() { m_valueSet = false; } // NimBLEUUID @@ -165,7 +162,7 @@ NimBLEUUID::NimBLEUUID() { * @brief Get the number of bits in this uuid. * @return The number of bits in the UUID. One of 16, 32 or 128. */ -uint8_t NimBLEUUID::bitSize() { +uint8_t NimBLEUUID::bitSize() const { if (!m_valueSet) return 0; return m_uuid.u.type; } // bitSize @@ -177,11 +174,8 @@ uint8_t NimBLEUUID::bitSize() { * @param [in] uuid The UUID to compare against. * @return True if the UUIDs are equal and false otherwise. */ -bool NimBLEUUID::equals(NimBLEUUID uuid) { - if(ble_uuid_cmp(&m_uuid.u, &uuid.getNative()->u) == 0){ - return true; - } - return false; +bool NimBLEUUID::equals(const NimBLEUUID &uuid) const { + return *this == uuid; } @@ -194,8 +188,7 @@ bool NimBLEUUID::equals(NimBLEUUID uuid) { * NNNNNNNN * */ - -NimBLEUUID NimBLEUUID::fromString(std::string _uuid) { +NimBLEUUID NimBLEUUID::fromString(const std::string &_uuid) { uint8_t start = 0; if (strstr(_uuid.c_str(), "0x") != nullptr) { // If the string starts with 0x, skip those characters. start = 2; @@ -220,7 +213,7 @@ NimBLEUUID NimBLEUUID::fromString(std::string _uuid) { * * @return The native UUID value or NULL if not set. */ -ble_uuid_any_t* NimBLEUUID::getNative() { +const ble_uuid_any_t* NimBLEUUID::getNative() const { if (m_valueSet == false) { NIMBLE_LOGD(LOG_TAG,"<< Return of un-initialized UUID!"); return nullptr; @@ -235,47 +228,20 @@ ble_uuid_any_t* NimBLEUUID::getNative() { * A UUID can be internally represented as 16bit, 32bit or the full 128bit. This method * will convert 16 or 32 bit representations to the full 128bit. */ -NimBLEUUID NimBLEUUID::to128() { +const NimBLEUUID &NimBLEUUID::to128() { // If we either don't have a value or are already a 128 bit UUID, nothing further to do. if (!m_valueSet || m_uuid.u.type == BLE_UUID_TYPE_128) { return *this; } - // If we are 16 bit or 32 bit, then set the 4 bytes of the variable part of the UUID. + // If we are 16 bit or 32 bit, then set the other bytes of the UUID. if (m_uuid.u.type == BLE_UUID_TYPE_16) { - uint16_t temp = m_uuid.u16.value; - m_uuid.u128.value[15] = 0; - m_uuid.u128.value[14] = 0; - m_uuid.u128.value[13] = (temp >> 8) & 0xff; - m_uuid.u128.value[12] = temp & 0xff; - + *this = NimBLEUUID(m_uuid.u16.value, 0x0000, 0x1000, 0x800000805f9b34fb); } else if (m_uuid.u.type == BLE_UUID_TYPE_32) { - uint32_t temp = m_uuid.u32.value; - m_uuid.u128.value[15] = (temp >> 24) & 0xff; - m_uuid.u128.value[14] = (temp >> 16) & 0xff; - m_uuid.u128.value[13] = (temp >> 8) & 0xff; - m_uuid.u128.value[12] = temp & 0xff; + *this = NimBLEUUID(m_uuid.u32.value, 0x0000, 0x1000, 0x800000805f9b34fb); } - // Set the fixed parts of the UUID. - m_uuid.u128.value[11] = 0x00; - m_uuid.u128.value[10] = 0x00; - - m_uuid.u128.value[9] = 0x10; - m_uuid.u128.value[8] = 0x00; - - m_uuid.u128.value[7] = 0x80; - m_uuid.u128.value[6] = 0x00; - - m_uuid.u128.value[5] = 0x00; - m_uuid.u128.value[4] = 0x80; - m_uuid.u128.value[3] = 0x5f; - m_uuid.u128.value[2] = 0x9b; - m_uuid.u128.value[1] = 0x34; - m_uuid.u128.value[0] = 0xfb; - - m_uuid.u.type = BLE_UUID_TYPE_128; return *this; } // to128 @@ -290,12 +256,32 @@ NimBLEUUID NimBLEUUID::to128() { * * @return A string representation of the UUID. */ -std::string NimBLEUUID::toString() { - if (!m_valueSet) return ""; // If we have no value, nothing to format. +std::string NimBLEUUID::toString() const { + return std::string(*this); +} // toString + + +bool NimBLEUUID::operator ==(const NimBLEUUID & rhs) const { + if(m_valueSet && rhs.m_valueSet) { + return ble_uuid_cmp(&m_uuid.u, &rhs.m_uuid.u) == 0; + } + + return m_valueSet == rhs.m_valueSet; +} + + +bool NimBLEUUID::operator !=(const NimBLEUUID & rhs) const { + return !this->operator==(rhs); +} + + +NimBLEUUID::operator std::string() const { + if (!m_valueSet) return std::string(); // If we have no value, nothing to format. char buf[BLE_UUID_STR_LEN]; return ble_uuid_to_str(&m_uuid.u, buf); -} // toString +} + #endif /* CONFIG_BT_ENABLED */ diff --git a/libesp32/NimBLE-Arduino/src/NimBLEUUID.h b/libesp32/NimBLE-Arduino/src/NimBLEUUID.h index 63230fba5..f07bb3df5 100644 --- a/libesp32/NimBLE-Arduino/src/NimBLEUUID.h +++ b/libesp32/NimBLE-Arduino/src/NimBLEUUID.h @@ -30,18 +30,23 @@ */ class NimBLEUUID { public: - NimBLEUUID(std::string uuid); + NimBLEUUID(const std::string &uuid); NimBLEUUID(uint16_t uuid); NimBLEUUID(uint32_t uuid); - NimBLEUUID(ble_uuid128_t* uuid); - NimBLEUUID(uint8_t* pData, size_t size, bool msbFirst); + NimBLEUUID(const ble_uuid128_t* uuid); + NimBLEUUID(const uint8_t* pData, size_t size, bool msbFirst); + NimBLEUUID(uint32_t first, uint16_t second, uint16_t third, uint64_t fourth); NimBLEUUID(); - uint8_t bitSize(); // Get the number of bits in this uuid. - bool equals(NimBLEUUID uuid); - ble_uuid_any_t* getNative(); - NimBLEUUID to128(); - std::string toString(); - static NimBLEUUID fromString(std::string uuid); // Create a NimBLEUUID from a string + uint8_t bitSize() const; // Get the number of bits in this uuid. + bool equals(const NimBLEUUID &uuid) const; + const ble_uuid_any_t* getNative() const; + const NimBLEUUID & to128(); + std::string toString() const; + static NimBLEUUID fromString(const std::string &uuid); // Create a NimBLEUUID from a string + + bool operator ==(const NimBLEUUID & rhs) const; + bool operator !=(const NimBLEUUID & rhs) const; + operator std::string() const; private: ble_uuid_any_t m_uuid; // The underlying UUID structure that this class wraps. diff --git a/libesp32/NimBLE-Arduino/src/NimBLEUtils.cpp b/libesp32/NimBLE-Arduino/src/NimBLEUtils.cpp index 3911fd7ed..9036d4d30 100644 --- a/libesp32/NimBLE-Arduino/src/NimBLEUtils.cpp +++ b/libesp32/NimBLE-Arduino/src/NimBLEUtils.cpp @@ -3,7 +3,7 @@ * * Created: on Jan 25 2020 * Author H2zero - * + * */ #include "sdkconfig.h" @@ -11,38 +11,10 @@ #include "NimBLEUtils.h" #include "NimBLELog.h" +#include "nimconfig.h" -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, 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 */ @@ -78,6 +50,7 @@ int NimBLEUtils::checkConnParams(ble_gap_conn_params* params) { const char* NimBLEUtils::returnCodeToString(int rc) { +#if defined(CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT) switch(rc) { case 0: return "SUCCESS"; @@ -355,19 +328,22 @@ const char* NimBLEUtils::returnCodeToString(int rc) { return "Pairing over the LE transport failed - Pairing Request sent over the BR/EDR transport in process."; case (0x0500+BLE_SM_ERR_CROSS_TRANS ): return "BR/EDR Link Key generated on the BR/EDR transport cannot be used to derive and distribute keys for the LE transport."; - default: return "Unknown"; } -} +#else // #if defined(CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT) + return ""; +#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 defined(CONFIG_NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT) switch(advType) { case BLE_HCI_ADV_TYPE_ADV_IND : //0 return "Undirected - Connectable / Scannable"; @@ -382,7 +358,9 @@ const char* NimBLEUtils::advTypeToString(uint8_t advType) { default: return "Unknown flag"; } - +#else // #if defined(CONFIG_NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT) + return ""; +#endif // #if defined(CONFIG_NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT) } // adFlagsToString @@ -394,7 +372,7 @@ const char* NimBLEUtils::advTypeToString(uint8_t advType) { * @param [in] length The length of the data to convert. * @return A pointer to the formatted buffer. */ -char* NimBLEUtils::buildHexData(uint8_t* target, uint8_t* source, uint8_t length) { +char* NimBLEUtils::buildHexData(uint8_t* target, const uint8_t* source, uint8_t length) { // Guard against too much data. if (length > 100) length = 100; @@ -422,91 +400,97 @@ char* NimBLEUtils::buildHexData(uint8_t* target, uint8_t* source, uint8_t length } // 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 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 +#endif default: NIMBLE_LOGD(LOG_TAG, "gapEventToString: Unknown event type %d 0x%.2x", eventType, eventType); return "Unknown event type"; } +#else // #if defined(CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT) + return ""; +#endif // #if defined(CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT) } // gapEventToString @@ -698,4 +682,4 @@ void print_addr(const void *addr) u8p[5], u8p[4], u8p[3], u8p[2], u8p[1], u8p[0]); } -#endif //CONFIG_BT_ENABLED \ No newline at end of file +#endif //CONFIG_BT_ENABLED diff --git a/libesp32/NimBLE-Arduino/src/NimBLEUtils.h b/libesp32/NimBLE-Arduino/src/NimBLEUtils.h index 3c7021db0..b26d41a51 100644 --- a/libesp32/NimBLE-Arduino/src/NimBLEUtils.h +++ b/libesp32/NimBLE-Arduino/src/NimBLEUtils.h @@ -3,7 +3,7 @@ * * Created: on Jan 25 2020 * Author H2zero - * + * */ #ifndef COMPONENTS_NIMBLEUTILS_H_ @@ -25,13 +25,12 @@ class NimBLEUtils { public: static void dumpGapEvent(ble_gap_event *event, void *arg); static const char* gapEventToString(uint8_t eventType); - static char* buildHexData(uint8_t* target, uint8_t* source, uint8_t length); + static char* buildHexData(uint8_t* target, const uint8_t* source, uint8_t length); static const char* advTypeToString(uint8_t advType); static const char* returnCodeToString(int rc); - static void memrcpy(uint8_t* target, uint8_t* source, uint32_t size); static int checkConnParams(ble_gap_conn_params* params); }; #endif // CONFIG_BT_ENABLED -#endif // COMPONENTS_NIMBLEUTILS_H_ \ No newline at end of file +#endif // COMPONENTS_NIMBLEUTILS_H_ diff --git a/libesp32/NimBLE-Arduino/src/NimBLEValue.cpp b/libesp32/NimBLE-Arduino/src/NimBLEValue.cpp index 808812bc3..aa437c60c 100644 --- a/libesp32/NimBLE-Arduino/src/NimBLEValue.cpp +++ b/libesp32/NimBLE-Arduino/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 @@ -31,9 +34,9 @@ NimBLEValue::NimBLEValue() { * The accumulation is a growing set of data that is added to until a commit or cancel. * @param [in] part A message part being added. */ -void NimBLEValue::addPart(std::string part) { - NIMBLE_LOGD(LOG_TAG, ">> addPart: length=%d", part.length()); - m_accumulation += part; +void NimBLEValue::addPart(const std::string &part) { + NIMBLE_LOGD(LOG_TAG, ">> addPart: length=%d", part.length()); + m_accumulation += part; } // addPart @@ -43,9 +46,9 @@ void NimBLEValue::addPart(std::string part) { * @param [in] pData A message part being added. * @param [in] length The number of bytes being added. */ -void NimBLEValue::addPart(uint8_t* pData, size_t length) { - NIMBLE_LOGD(LOG_TAG, ">> addPart: length=%d", length); - m_accumulation += std::string((char*) pData, length); +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); } // addPart @@ -53,9 +56,9 @@ void NimBLEValue::addPart(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,15 +118,15 @@ 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 /** * @brief Set the current value. */ -void NimBLEValue::setValue(std::string value) { - m_value = value; +void NimBLEValue::setValue(const std::string &value) { + m_value = value; } // setValue @@ -132,9 +135,9 @@ void NimBLEValue::setValue(std::string value) { * @param [in] pData The data for the current value. * @param [in] The length of the new current value. */ -void NimBLEValue::setValue(uint8_t* pData, size_t length) { - m_value = std::string((char*) pData, length); +void NimBLEValue::setValue(const uint8_t* pData, size_t length) { + m_value = std::string((char*) pData, length); } // setValue - -#endif // CONFIG_BT_ENABLED \ No newline at end of file +#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) +#endif // CONFIG_BT_ENABLED diff --git a/libesp32/NimBLE-Arduino/src/NimBLEValue.h b/libesp32/NimBLE-Arduino/src/NimBLEValue.h index 2fa1fcb4e..4fdeb9bc4 100644 --- a/libesp32/NimBLE-Arduino/src/NimBLEValue.h +++ b/libesp32/NimBLE-Arduino/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(std::string part); - void addPart(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(std::string value); - void setValue(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_ */ \ No newline at end of file +#endif /* MAIN_BLEVALUE_H_ */ diff --git a/libesp32/NimBLE-Arduino/src/console/console.h b/libesp32/NimBLE-Arduino/src/console/console.h index 342d6f699..96f965159 100644 --- a/libesp32/NimBLE-Arduino/src/console/console.h +++ b/libesp32/NimBLE-Arduino/src/console/console.h @@ -18,4 +18,4 @@ #define console_printf printf -#endif \ No newline at end of file +#endif diff --git a/libesp32/NimBLE-Arduino/src/esp-hci/src/esp_nimble_hci.c b/libesp32/NimBLE-Arduino/src/esp-hci/src/esp_nimble_hci.c index 8d994c444..e4ab99932 100644 --- a/libesp32/NimBLE-Arduino/src/esp-hci/src/esp_nimble_hci.c +++ b/libesp32/NimBLE-Arduino/src/esp-hci/src/esp_nimble_hci.c @@ -519,4 +519,4 @@ esp_err_t esp_nimble_hci_and_controller_deinit(void) } return ESP_OK; -} \ No newline at end of file +} diff --git a/libesp32/NimBLE-Arduino/src/esp_nimble_cfg.h b/libesp32/NimBLE-Arduino/src/esp_nimble_cfg.h index 16d4253be..384ec4a56 100644 --- a/libesp32/NimBLE-Arduino/src/esp_nimble_cfg.h +++ b/libesp32/NimBLE-Arduino/src/esp_nimble_cfg.h @@ -1,6 +1,4 @@ -/* Modifications copyright (C) 2020 Ryan Powell */ - #ifndef __ESP_NIMBLE_CFG__ #define __ESP_NIMBLE_CFG__ #include "nimconfig.h" @@ -470,7 +468,7 @@ #endif #ifndef MYNEWT_VAL_BLE_HS_FLOW_CTRL_TX_ON_DISCONNECT -#define MYNEWT_VAL_BLE_HS_FLOW_CTRL_TX_ON_DISCONNECT CONFIG_BT_NIMBLE_FLOW_CTRL_TX_ON_DISCONNECT +#define MYNEWT_VAL_BLE_HS_FLOW_CTRL_TX_ON_DISCONNECT CONFIG_BT_NIMBLE_HS_FLOW_CTRL_TX_ON_DISCONNECT #endif #ifndef MYNEWT_VAL_BLE_HS_PHONY_HCI_ACKS diff --git a/libesp32/NimBLE-Arduino/src/esp_nimble_hci.h b/libesp32/NimBLE-Arduino/src/esp_nimble_hci.h index 3c66ca796..e10436f3c 100644 --- a/libesp32/NimBLE-Arduino/src/esp_nimble_hci.h +++ b/libesp32/NimBLE-Arduino/src/esp_nimble_hci.h @@ -135,4 +135,4 @@ esp_err_t esp_nimble_hci_and_controller_deinit(void); } #endif -#endif /* __ESP_NIMBLE_HCI_H__ */ \ No newline at end of file +#endif /* __ESP_NIMBLE_HCI_H__ */ diff --git a/libesp32/NimBLE-Arduino/src/esp_nimble_mem.h b/libesp32/NimBLE-Arduino/src/esp_nimble_mem.h index d257c5466..90e52a20d 100644 --- a/libesp32/NimBLE-Arduino/src/esp_nimble_mem.h +++ b/libesp32/NimBLE-Arduino/src/esp_nimble_mem.h @@ -1,4 +1,3 @@ - /* * Copyright 2020 Espressif Systems (Shanghai) PTE LTD * @@ -37,4 +36,4 @@ void nimble_platform_mem_free(void *ptr); } #endif -#endif /* __ESP_NIMBLE_MEM_H__ */ \ No newline at end of file +#endif /* __ESP_NIMBLE_MEM_H__ */ diff --git a/libesp32/NimBLE-Arduino/src/host/ble_gap.h b/libesp32/NimBLE-Arduino/src/host/ble_gap.h index 9ef4e18ef..b4dbdb051 100644 --- a/libesp32/NimBLE-Arduino/src/host/ble_gap.h +++ b/libesp32/NimBLE-Arduino/src/host/ble_gap.h @@ -98,8 +98,8 @@ struct hci_conn_update; #define BLE_GAP_INITIAL_CONN_LATENCY 0 #define BLE_GAP_INITIAL_SUPERVISION_TIMEOUT 0x0100 -#define BLE_GAP_INITIAL_CONN_MIN_CE_LEN 0x0010 -#define BLE_GAP_INITIAL_CONN_MAX_CE_LEN 0x0300 +#define BLE_GAP_INITIAL_CONN_MIN_CE_LEN 0x0000 +#define BLE_GAP_INITIAL_CONN_MAX_CE_LEN 0x0000 #define BLE_GAP_ROLE_MASTER 0 #define BLE_GAP_ROLE_SLAVE 1 @@ -1783,6 +1783,20 @@ int ble_gap_unpair(const ble_addr_t *peer_addr); */ int ble_gap_unpair_oldest_peer(void); +/** + * Similar to `ble_gap_unpair_oldest_peer()`, except it makes sure that the + * peer received in input parameters is not deleted. + * + * @param peer_addr Address of the peer (not to be deleted) + * + * @return 0 on success; + * A BLE host HCI return code if the controller + * rejected the request; + * A BLE host core return code on unexpected + * error. + */ +int ble_gap_unpair_oldest_except(const ble_addr_t *peer_addr); + #define BLE_GAP_PRIVATE_MODE_NETWORK 0 #define BLE_GAP_PRIVATE_MODE_DEVICE 1 @@ -1886,20 +1900,6 @@ struct ble_gap_event_listener { SLIST_ENTRY(ble_gap_event_listener) link; }; -/** - * Similar to `ble_gap_unpair_oldest_peer()`, except it makes sure that current - * peer is not deleted. - * - * @param peer_addr Address of the current peer (not to be deleted) - * - * @return 0 on success; - * A BLE host HCI return code if the controller - * rejected the request; - * A BLE host core return code on unexpected - * error. - */ -int ble_gap_unpair_oldest_except_curr(const ble_addr_t *curr_peer); - /** * Registers listener for GAP events * diff --git a/libesp32/NimBLE-Arduino/src/host/ble_store.h b/libesp32/NimBLE-Arduino/src/host/ble_store.h index e470f8ec3..a3eca5d23 100644 --- a/libesp32/NimBLE-Arduino/src/host/ble_store.h +++ b/libesp32/NimBLE-Arduino/src/host/ble_store.h @@ -288,8 +288,6 @@ int ble_store_clear(void); /*** Utility functions. */ -int ble_store_clean_old_cccds(const ble_addr_t *curr_peer); - int ble_store_util_bonded_peers(ble_addr_t *out_peer_id_addrs, int *out_num_peers, int max_peers); diff --git a/libesp32/NimBLE-Arduino/src/mesh/glue.h b/libesp32/NimBLE-Arduino/src/mesh/glue.h index 3b1636dcc..08e81fa41 100644 --- a/libesp32/NimBLE-Arduino/src/mesh/glue.h +++ b/libesp32/NimBLE-Arduino/src/mesh/glue.h @@ -330,11 +330,8 @@ static inline void net_buf_simple_restore(struct os_mbuf *buf, buf->om_len = state->len; } -static inline void sys_memcpy_swap(void *destination, const void *source, size_t length) +static inline void sys_memcpy_swap(void *dst, const void *src, size_t length) { - u8_t *dst = destination; - const u8_t *src = source; - __ASSERT(((src < dst && (src + length) <= dst) || (src > dst && (dst + length) <= src)), "Source and destination buffers must not overlap"); @@ -342,7 +339,7 @@ static inline void sys_memcpy_swap(void *destination, const void *source, size_t src += length - 1; for (; length > 0; length--) { - *dst++ = *src--; + *((u8_t *)dst++) = *((u8_t *)src--); } } diff --git a/libesp32/NimBLE-Arduino/src/modlog/modlog.h b/libesp32/NimBLE-Arduino/src/modlog/modlog.h index e8752d465..e81ea3812 100644 --- a/libesp32/NimBLE-Arduino/src/modlog/modlog.h +++ b/libesp32/NimBLE-Arduino/src/modlog/modlog.h @@ -41,31 +41,43 @@ modlog_dummy(const char *msg, ...) #endif #ifdef ESP_PLATFORM -/// Uncomment these and comment out the 3 defines below to see NimBLE messages in Arduino. -/* +#define MODLOG_ESP_LOCAL(level, ml_msg_, ...) do { \ + if (LOG_LOCAL_LEVEL >= level) esp_log_write(level, "NimBLE", ml_msg_, ##__VA_ARGS__); \ +} while(0) + +#ifdef ARDUINO_ARCH_ESP32 +#include "nimconfig.h" +#endif + +#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_BT_NIMBLE_DEBUG) + #define MODLOG_DEBUG(ml_mod_, ml_msg_, ...) \ - esp_log_write(ESP_LOG_ERROR, "NimBLE",ml_msg_, ##__VA_ARGS__) + MODLOG_ESP_LOCAL(ESP_LOG_ERROR, ml_msg_, ##__VA_ARGS__) #define MODLOG_INFO(ml_mod_, ml_msg_, ...) \ - esp_log_write(ESP_LOG_ERROR, "NimBLE",ml_msg_, ##__VA_ARGS__) + MODLOG_ESP_LOCAL(ESP_LOG_ERROR, ml_msg_, ##__VA_ARGS__) #define MODLOG_WARN(ml_mod_, ml_msg_, ...) \ - esp_log_write(ESP_LOG_ERROR, "NimBLE",ml_msg_, ##__VA_ARGS__) -*/ + MODLOG_ESP_LOCAL(ESP_LOG_ERROR, ml_msg_, ##__VA_ARGS__) + +#else + #define MODLOG_DEBUG(ml_mod_, ml_msg_, ...) \ - esp_log_write(ESP_LOG_DEBUG, "NimBLE",ml_msg_, ##__VA_ARGS__) + MODLOG_ESP_LOCAL(ESP_LOG_DEBUG, ml_msg_, ##__VA_ARGS__) #define MODLOG_INFO(ml_mod_, ml_msg_, ...) \ - esp_log_write(ESP_LOG_INFO, "NimBLE",ml_msg_, ##__VA_ARGS__) + MODLOG_ESP_LOCAL(ESP_LOG_INFO, ml_msg_, ##__VA_ARGS__) #define MODLOG_WARN(ml_mod_, ml_msg_, ...) \ - esp_log_write(ESP_LOG_WARN, "NimBLE",ml_msg_, ##__VA_ARGS__) + MODLOG_ESP_LOCAL(ESP_LOG_WARN, ml_msg_, ##__VA_ARGS__) + +#endif #define MODLOG_ERROR(ml_mod_, ml_msg_, ...) \ - esp_log_write(ESP_LOG_ERROR, "NimBLE",ml_msg_, ##__VA_ARGS__) + MODLOG_ESP_LOCAL(ESP_LOG_ERROR, ml_msg_, ##__VA_ARGS__) #define MODLOG_CRITICAL(ml_mod_, ml_msg_, ...) \ - esp_log_write(ESP_LOG_ERROR, "NimBLE",ml_msg_, ##__VA_ARGS__) + MODLOG_ESP_LOCAL(ESP_LOG_ERROR, ml_msg_, ##__VA_ARGS__) #else diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_gap_priv.h b/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_gap_priv.h index 4285cfa43..c80872898 100644 --- a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_gap_priv.h +++ b/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_gap_priv.h @@ -119,6 +119,7 @@ void ble_gap_preempt(void); void ble_gap_preempt_done(void); void ble_gap_conn_broken(uint16_t conn_handle, int reason); +void ble_gap_reset_state(int reason); int32_t ble_gap_timer(void); int ble_gap_init(void); diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_id_priv.h b/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_id_priv.h index aa2827d41..c031b9511 100644 --- a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_id_priv.h +++ b/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_id_priv.h @@ -33,6 +33,10 @@ int ble_hs_id_use_addr(uint8_t addr_type); void ble_hs_id_reset(void); void ble_hs_id_rnd_reset(void); +#if MYNEWT_VAL(BLE_HOST_BASED_PRIVACY) +bool ble_hs_is_rpa(uint8_t *addr, uint8_t addr_type); +int ble_hs_id_set_pseudo_rnd(const uint8_t *); +#endif #ifdef __cplusplus } #endif diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_pvcy_priv.h b/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_pvcy_priv.h index 7f0aa4b90..86157da0f 100644 --- a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_pvcy_priv.h +++ b/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_pvcy_priv.h @@ -35,6 +35,9 @@ int ble_hs_pvcy_add_entry(const uint8_t *addr, uint8_t addrtype, const uint8_t *irk); int ble_hs_pvcy_ensure_started(void); int ble_hs_pvcy_set_mode(const ble_addr_t *addr, uint8_t priv_mode); +#if MYNEWT_VAL(BLE_HOST_BASED_PRIVACY) +bool ble_hs_pvcy_enabled(void); +#endif #ifdef __cplusplus } diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_resolv_priv.h b/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_resolv_priv.h new file mode 100644 index 000000000..568aa89ab --- /dev/null +++ b/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_hs_resolv_priv.h @@ -0,0 +1,108 @@ +/* + * Copyright 2020 Espressif Systems (Shanghai) PTE LTD + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if MYNEWT_VAL(BLE_HOST_BASED_PRIVACY) +/* + * An entry in the resolving list. + */ +struct ble_hs_resolv_entry { + uint8_t rl_addr_type; + uint8_t rl_local_irk[16]; + uint8_t rl_peer_irk[16]; + uint8_t rl_identity_addr[BLE_DEV_ADDR_LEN]; + uint8_t rl_pseudo_id[BLE_DEV_ADDR_LEN]; + uint8_t rl_local_rpa[BLE_DEV_ADDR_LEN]; + uint8_t rl_peer_rpa[BLE_DEV_ADDR_LEN]; +}; + +#if MYNEWT_VAL(BLE_STORE_CONFIG_PERSIST) +/* Persist peer records in NVS. XXX Need to handle this in `store` module */ +int ble_store_persist_peer_records(void); +#endif + +struct ble_hs_peer_sec { + ble_addr_t peer_addr; + uint8_t irk[16]; + uint8_t irk_present: 1; +}; +/* + * BLE host peer device record, this helps in storing peer RPA before bond is + * created and IRKs are exchanged. + */ +struct ble_hs_dev_records { + bool rec_used; + uint8_t pseudo_addr[BLE_DEV_ADDR_LEN]; + uint8_t rand_addr[BLE_DEV_ADDR_LEN]; + uint8_t identity_addr[BLE_DEV_ADDR_LEN]; + struct ble_hs_peer_sec peer_sec; +}; + +/* Add a device to the resolving list */ +int ble_hs_resolv_list_add(uint8_t *cmdbuf); +int ble_hs_gen_own_rpa_random(void); +uint8_t *ble_hs_get_rpa_local(void); + +/* Remove a device from the resolving list */ +int ble_hs_resolv_list_rmv(uint8_t, uint8_t *); +/* Clear the resolving list and peer dev record */ +void ble_hs_resolv_list_clear_all(void); + +/* Address resolution enable command */ +void ble_hs_resolv_enable(bool); + +/* Finds 'addr' in resolving list. Doesnt check if address resolution enabled */ +struct ble_hs_resolv_entry * +ble_hs_resolv_list_find(uint8_t *addr); + +/* Returns true if host based RPA (privacy) is enabled */ +bool ble_host_rpa_enabled(void); + +/* Searches peer device records (RPA) and fetches matching RL, peer_address + * into input parameters if RL is found */ +void +ble_rpa_replace_peer_params_with_rl(uint8_t *, uint8_t *, struct ble_hs_resolv_entry **); + +int ble_rpa_resolv_add_peer_rec(uint8_t *); + +struct ble_hs_dev_records *ble_rpa_get_peer_dev_records(void); +int ble_rpa_get_num_peer_dev_records(void); +void ble_rpa_set_num_peer_dev_records(int); +int ble_rpa_remove_peer_dev_rec(struct ble_hs_dev_records *); +struct ble_hs_dev_records *ble_rpa_find_peer_dev_rec(uint8_t *); + +/* Set the resolvable private address timeout */ +int ble_hs_resolv_set_rpa_tmo(uint16_t); + +/* Resolve a resolvable private address */ +int ble_hs_resolv_rpa(uint8_t *rpa, uint8_t *irk); + +/* Initialize resolv*/ +void ble_hs_resolv_init(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_sm_priv.h b/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_sm_priv.h index 3f64b7786..74205bd0c 100644 --- a/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_sm_priv.h +++ b/libesp32/NimBLE-Arduino/src/nimble/host/mesh/src/src/ble_sm_priv.h @@ -399,6 +399,7 @@ int ble_sm_slave_initiate(uint16_t conn_handle); int ble_sm_enc_initiate(uint16_t conn_handle, uint8_t key_size, const uint8_t *ltk, uint16_t ediv, uint64_t rand_val, int auth); +int ble_sm_alg_encrypt(uint8_t *key, uint8_t *plaintext, uint8_t *enc_data); int ble_sm_init(void); #define BLE_SM_LOG_CMD(is_tx, cmd_name, conn_handle, log_cb, cmd) \ @@ -419,6 +420,9 @@ int ble_sm_init(void); #define ble_sm_init() 0 +#define ble_sm_alg_encrypt(key, plaintext, enc_data) \ + BLE_HS_ENOTSUP + #endif struct ble_l2cap_chan *ble_sm_create_chan(uint16_t handle); diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_att_cmd.c b/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_att_cmd.c index 999f57a2b..bad192df5 100644 --- a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_att_cmd.c +++ b/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_att_cmd.c @@ -66,11 +66,10 @@ ble_att_tx(uint16_t conn_handle, struct os_mbuf *txom) ble_hs_lock(); - ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_ATT, &conn, - &chan); - if (chan == NULL) { + rc = ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_ATT, &conn, + &chan); + if (rc != 0) { os_mbuf_free_chain(txom); - rc = BLE_HS_ENOTCONN; } else { ble_att_truncate_to_mtu(chan, txom); rc = ble_l2cap_tx(conn, chan, txom); diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_gap.c b/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_gap.c index e65640128..09ae27047 100644 --- a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_gap.c +++ b/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_gap.c @@ -17,8 +17,6 @@ * under the License. */ - /* Modifications copyright (C) 2020 Ryan Powell */ - #include #include #include @@ -1855,7 +1853,6 @@ ble_gap_update_timer(void) ble_hs_unlock(); if (entry != NULL) { - ble_gap_update_notify(conn_handle, BLE_HS_ETIMEOUT); ble_gap_update_entry_free(entry); } } while (entry != NULL); @@ -5303,8 +5300,7 @@ ble_gap_unpair_oldest_peer(void) } if (num_peers == 0) { - return BLE_HS_ENOENT; - //return 0; + return 0; } rc = ble_gap_unpair(&oldest_peer_id_addr); @@ -5316,14 +5312,14 @@ ble_gap_unpair_oldest_peer(void) } int -ble_gap_unpair_oldest_except_curr(const ble_addr_t *curr_peer) +ble_gap_unpair_oldest_except(const ble_addr_t *peer_addr) { - ble_addr_t oldest_peer_id_addr[MYNEWT_VAL(BLE_STORE_MAX_BONDS)]; + ble_addr_t peer_id_addrs[MYNEWT_VAL(BLE_STORE_MAX_BONDS)]; int num_peers; int rc, i; rc = ble_store_util_bonded_peers( - &oldest_peer_id_addr[0], &num_peers, MYNEWT_VAL(BLE_STORE_MAX_BONDS)); + &peer_id_addrs[0], &num_peers, MYNEWT_VAL(BLE_STORE_MAX_BONDS)); if (rc != 0) { return rc; } @@ -5333,21 +5329,16 @@ ble_gap_unpair_oldest_except_curr(const ble_addr_t *curr_peer) } for (i = 0; i < num_peers; i++) { - if (memcmp(curr_peer, &oldest_peer_id_addr[i], sizeof (ble_addr_t)) != 0) { + if (ble_addr_cmp(peer_addr, &peer_id_addrs[i]) != 0) { break; } } - if (i < num_peers) { - rc = ble_gap_unpair(&oldest_peer_id_addr[i]); - if (rc != 0) { - return rc; - } - } else { + if (i >= num_peers) { return BLE_HS_ENOMEM; } - return 0; + return ble_gap_unpair(&peer_id_addrs[i]); } void @@ -5371,7 +5362,8 @@ ble_gap_passkey_event(uint16_t conn_handle, } void -ble_gap_enc_event(uint16_t conn_handle, int status, int security_restored) +ble_gap_enc_event(uint16_t conn_handle, int status, + int security_restored, int bonded) { #if !NIMBLE_BLE_SM return; @@ -5387,17 +5379,24 @@ ble_gap_enc_event(uint16_t conn_handle, int status, int security_restored) ble_gap_event_listener_call(&event); ble_gap_call_conn_event_cb(&event, conn_handle); -/* H2zero mod - If bonding is not enabled don't store cccd data - if (status == 0) { -*/ - if (status == 0 && ble_hs_cfg.sm_bonding) { -/* End mod */ - if (security_restored) { - ble_gatts_bonding_restored(conn_handle); - } else { - ble_gatts_bonding_established(conn_handle); - } + if (status != 0) { + return; + } + + /* If encryption succeded and encryption has been restored for bonded device, + * notify gatt server so it has chance to send notification/indication if needed. + */ + if (security_restored) { + ble_gatts_bonding_restored(conn_handle); + return; + } + + /* If this is fresh pairing and bonding has been established, + * notify gatt server about that so previous subscriptions (before bonding) + * can be stored. + */ + if (bonded) { + ble_gatts_bonding_established(conn_handle); } } diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_gap_priv.h b/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_gap_priv.h index c80872898..90c32e22a 100644 --- a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_gap_priv.h +++ b/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_gap_priv.h @@ -99,7 +99,7 @@ int ble_gap_rx_l2cap_update_req(uint16_t conn_handle, struct ble_gap_upd_params *params); void ble_gap_rx_phy_update_complete(struct hci_le_phy_upd_complete *evt); void ble_gap_enc_event(uint16_t conn_handle, int status, - int security_restored); + int security_restored, int bonded); void ble_gap_passkey_event(uint16_t conn_handle, struct ble_gap_passkey_params *passkey_params); void ble_gap_notify_rx_event(uint16_t conn_handle, uint16_t attr_handle, diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_gatts.c b/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_gatts.c index e84361cbe..fccf10274 100644 --- a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_gatts.c +++ b/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_gatts.c @@ -1689,30 +1689,29 @@ ble_gatts_bonding_established(uint16_t conn_handle) conn = ble_hs_conn_find(conn_handle); BLE_HS_DBG_ASSERT(conn != NULL); + BLE_HS_DBG_ASSERT(conn->bhc_sec_state.bonded); - if (conn->bhc_sec_state.bonded) { - cccd_value.peer_addr = conn->bhc_peer_addr; - gatt_srv = &conn->bhc_gatt_svr; + cccd_value.peer_addr = conn->bhc_peer_addr; + gatt_srv = &conn->bhc_gatt_svr; - for (i = 0; i < gatt_srv->num_clt_cfgs; ++i) { - clt_cfg = (gatt_srv->clt_cfgs + i); - if (clt_cfg == NULL) { - continue; - } + for (i = 0; i < gatt_srv->num_clt_cfgs; ++i) { + clt_cfg = (gatt_srv->clt_cfgs + i); + if (clt_cfg == NULL) { + continue; + } - if (clt_cfg->flags != 0) { - cccd_value.chr_val_handle = clt_cfg->chr_val_handle; - cccd_value.flags = clt_cfg->flags; - cccd_value.value_changed = 0; + if (clt_cfg->flags != 0) { + cccd_value.chr_val_handle = clt_cfg->chr_val_handle; + cccd_value.flags = clt_cfg->flags; + cccd_value.value_changed = 0; - /* Store write use ble_hs_lock */ - ble_hs_unlock(); - ble_store_write_cccd(&cccd_value); - ble_hs_lock(); + /* Store write use ble_hs_lock */ + ble_hs_unlock(); + ble_store_write_cccd(&cccd_value); + ble_hs_lock(); - conn = ble_hs_conn_find(conn_handle); - BLE_HS_DBG_ASSERT(conn != NULL); - } + conn = ble_hs_conn_find(conn_handle); + BLE_HS_DBG_ASSERT(conn != NULL); } } diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_conn.c b/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_conn.c index c19851577..eb65e3288 100644 --- a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_conn.c +++ b/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_conn.c @@ -410,18 +410,16 @@ ble_hs_conn_addrs(const struct ble_hs_conn *conn, #if MYNEWT_VAL(BLE_HOST_BASED_PRIVACY) /* RPA: Override peer address information. */ - struct ble_hs_resolv_entry *rl = NULL; - ble_addr_t bhc_peer_addr; bhc_peer_addr.type = conn->bhc_peer_addr.type; memcpy(bhc_peer_addr.val, conn->bhc_peer_addr.val, BLE_DEV_ADDR_LEN); - + + struct ble_hs_resolv_entry *rl = NULL; rl = ble_hs_resolv_list_find(bhc_peer_addr.val); if (rl != NULL) { - addrs->peer_ota_addr = conn->bhc_peer_rpa_addr; memcpy(addrs->peer_id_addr.val, rl->rl_identity_addr, BLE_DEV_ADDR_LEN); addrs->peer_id_addr.type = rl->rl_addr_type; - + if (ble_host_rpa_enabled()) { uint8_t *local_id = NULL; ble_hs_id_addr(BLE_ADDR_PUBLIC, (const uint8_t **) &local_id, NULL); diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci.c b/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci.c index 94126679c..92ffde8fd 100644 --- a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci.c +++ b/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci.c @@ -240,7 +240,7 @@ ble_hs_hci_process_ack(uint16_t expected_opcode, } if (rc == 0) { - if (params_buf == NULL) { + if (params_buf == NULL || out_ack->bha_params == NULL) { out_ack->bha_params_len = 0; } else { if (out_ack->bha_params_len > params_buf_len) { diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_evt.c b/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_evt.c index 3f7c5d791..30dc92f28 100644 --- a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_evt.c +++ b/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_hci_evt.c @@ -333,18 +333,10 @@ ble_hs_hci_evt_le_conn_complete(uint8_t subevent, uint8_t *data, int len) uint8_t *local_id_rpa = ble_hs_get_rpa_local(); memcpy(evt.local_rpa, local_id_rpa, 6); } - + struct ble_hs_resolv_entry *rl = NULL; ble_rpa_replace_peer_params_with_rl(evt.peer_addr, &evt.peer_addr_type, &rl); - if (rl == NULL) { - if (ble_rpa_resolv_add_peer_rec(evt.peer_addr) != 0) { - BLE_HS_LOG(DEBUG, "Memory unavailable for new peer record\n"); - } - } - /* Set the correct RPA for logging */ - memcpy(evt.peer_rpa, data + 6, BLE_DEV_ADDR_LEN); - #endif } else { memset(evt.local_rpa, 0, BLE_DEV_ADDR_LEN); @@ -441,14 +433,6 @@ ble_hs_hci_evt_le_adv_rpt(uint8_t subevent, uint8_t *data, int len) memcpy(desc.addr.val, data + off, 6); off += 6; -#if MYNEWT_VAL(BLE_HOST_BASED_PRIVACY) - if (ble_host_rpa_enabled()) { - /* Now RPA to be resolved here, since controller is unaware of the - * address is RPA */ - ble_rpa_replace_peer_params_with_rl(desc.addr.val, - &desc.addr.type, NULL); - } -#endif desc.length_data = data[off]; ++off; diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_misc.c b/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_misc.c index e6bb3825b..00200d316 100644 --- a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_misc.c +++ b/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_misc.c @@ -56,7 +56,7 @@ ble_hs_misc_conn_chan_find(uint16_t conn_handle, uint16_t cid, return rc; } -void +int ble_hs_misc_conn_chan_find_reqd(uint16_t conn_handle, uint16_t cid, struct ble_hs_conn **out_conn, struct ble_l2cap_chan **out_chan) @@ -66,7 +66,9 @@ ble_hs_misc_conn_chan_find_reqd(uint16_t conn_handle, uint16_t cid, int rc; rc = ble_hs_misc_conn_chan_find(conn_handle, cid, &conn, &chan); - BLE_HS_DBG_ASSERT_EVAL(rc == 0); + if (rc != 0) { + return rc; + } if (out_conn != NULL) { *out_conn = conn; @@ -74,6 +76,8 @@ ble_hs_misc_conn_chan_find_reqd(uint16_t conn_handle, uint16_t cid, if (out_chan != NULL) { *out_chan = chan; } + + return 0; } uint8_t diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_priv.h b/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_priv.h index 27bf904b7..49269546c 100644 --- a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_priv.h +++ b/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_hs_priv.h @@ -115,9 +115,9 @@ int ble_hs_hci_evt_acl_process(struct os_mbuf *om); int ble_hs_misc_conn_chan_find(uint16_t conn_handle, uint16_t cid, struct ble_hs_conn **out_conn, struct ble_l2cap_chan **out_chan); -void ble_hs_misc_conn_chan_find_reqd(uint16_t conn_handle, uint16_t cid, - struct ble_hs_conn **out_conn, - struct ble_l2cap_chan **out_chan); +int ble_hs_misc_conn_chan_find_reqd(uint16_t conn_handle, uint16_t cid, + struct ble_hs_conn **out_conn, + struct ble_l2cap_chan **out_chan); uint8_t ble_hs_misc_addr_type_to_id(uint8_t addr_type); int ble_hs_misc_restore_irks(void); diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_sig.c b/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_sig.c index 07a338ae6..bc73d954a 100644 --- a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_sig.c +++ b/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_sig.c @@ -473,8 +473,13 @@ ble_l2cap_sig_update(uint16_t conn_handle, STATS_INC(ble_l2cap_stats, update_init); ble_hs_lock(); - ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_SIG, - &conn, &chan); + rc = ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_SIG, + &conn, &chan); + if (rc != 0) { + ble_hs_unlock(); + goto done; + } + master = conn->bhc_flags & BLE_HS_CONN_F_MASTER; ble_hs_unlock(); diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_sig_cmd.c b/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_sig_cmd.c index 366dde625..510420f09 100644 --- a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_sig_cmd.c +++ b/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_l2cap_sig_cmd.c @@ -28,9 +28,11 @@ ble_l2cap_sig_tx(uint16_t conn_handle, struct os_mbuf *txom) int rc; ble_hs_lock(); - ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_SIG, - &conn, &chan); - rc = ble_l2cap_tx(conn, chan, txom); + rc = ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_SIG, + &conn, &chan); + if (rc == 0) { + rc = ble_l2cap_tx(conn, chan, txom); + } ble_hs_unlock(); return rc; diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_sm.c b/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_sm.c index 1bc55a625..6fa6f00c4 100644 --- a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_sm.c +++ b/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_sm.c @@ -538,6 +538,11 @@ ble_sm_persist_keys(struct ble_sm_proc *proc) case BLE_ADDR_PUBLIC: case BLE_ADDR_PUBLIC_ID: conn->bhc_peer_addr.type = BLE_ADDR_PUBLIC_ID; +#if MYNEWT_VAL(BLE_HOST_BASED_PRIVACY) + /* In case of Host based privacy, we should not be changing + * peer address type to BLE_ADDR_PUBLIC_ID */ + conn->bhc_peer_addr.type = BLE_ADDR_PUBLIC; +#endif break; case BLE_ADDR_RANDOM: @@ -944,7 +949,7 @@ ble_sm_process_result(uint16_t conn_handle, struct ble_sm_result *res) if (res->enc_cb) { BLE_HS_DBG_ASSERT(proc == NULL || rm); - ble_gap_enc_event(conn_handle, res->app_status, res->restore); + ble_gap_enc_event(conn_handle, res->app_status, res->restore, res->bonded); } if (res->app_status == 0 && @@ -1198,6 +1203,7 @@ ble_sm_enc_event_rx(uint16_t conn_handle, uint8_t evt_status, int encrypted) ble_hs_unlock(); + res.bonded = bonded; ble_sm_process_result(conn_handle, &res); } @@ -1793,8 +1799,21 @@ ble_sm_pair_req_rx(uint16_t conn_handle, struct os_mbuf **om, */ proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_NONE, -1, &prev); if (proc != NULL) { - /* Pairing already in progress; abort old procedure and start new. */ - /* XXX: Check the spec on this. */ + /* Fail if procedure is in progress unless we sent a slave security + * request to peer. + */ + if (proc->state != BLE_SM_PROC_STATE_SEC_REQ) { + res->sm_err = BLE_SM_ERR_UNSPECIFIED; + res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_UNSPECIFIED); + ble_hs_unlock(); + return; + } + + /* Remove the procedure because it was allocated when + * sending the Slave Security Request and it will be allocated + * again later in this method. We should probably refactor this + * in the future. + */ ble_sm_proc_remove(proc, prev); ble_sm_proc_free(proc); } @@ -2459,7 +2478,7 @@ ble_sm_timer(void) * procedures without reconnect. */ while ((proc = STAILQ_FIRST(&exp_list)) != NULL) { - ble_gap_enc_event(proc->conn_handle, BLE_HS_ETIMEOUT, 0); + ble_gap_enc_event(proc->conn_handle, BLE_HS_ETIMEOUT, 0, 0); STAILQ_REMOVE_HEAD(&exp_list, next); ble_sm_proc_free(proc); diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_sm_cmd.c b/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_sm_cmd.c index b5e674e75..e12e109d5 100644 --- a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_sm_cmd.c +++ b/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_sm_cmd.c @@ -52,14 +52,19 @@ ble_sm_tx(uint16_t conn_handle, struct os_mbuf *txom) { struct ble_l2cap_chan *chan; struct ble_hs_conn *conn; + int rc; BLE_HS_DBG_ASSERT(ble_hs_locked_by_cur_task()); STATS_INC(ble_l2cap_stats, sm_tx); - ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_SM, - &conn, &chan); - return ble_l2cap_tx(conn, chan, txom); + rc = ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_SM, + &conn, &chan); + if (rc == 0) { + rc = ble_l2cap_tx(conn, chan, txom); + } + + return rc; } #if NIMBLE_BLE_SM diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_sm_priv.h b/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_sm_priv.h index 74205bd0c..bbb4b03ae 100644 --- a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_sm_priv.h +++ b/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_sm_priv.h @@ -277,10 +277,10 @@ struct ble_sm_result { uint8_t sm_err; struct ble_gap_passkey_params passkey_params; void *state_arg; - unsigned execute:1; - unsigned enc_cb:1; - unsigned persist_keys:1; - unsigned restore:1; + unsigned execute : 1; + unsigned enc_cb : 1; + unsigned bonded : 1; + unsigned restore : 1; }; #if MYNEWT_VAL(BLE_HS_DEBUG) diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_store_util.c b/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_store_util.c index 9813a8650..73c71d93b 100644 --- a/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_store_util.c +++ b/libesp32/NimBLE-Arduino/src/nimble/host/src/ble_store_util.c @@ -19,6 +19,7 @@ #include "host/ble_store.h" #include "ble_hs_priv.h" +#include "ble_hs_resolv_priv.h" struct ble_store_util_peer_set { ble_addr_t *peer_id_addrs; @@ -27,12 +28,6 @@ struct ble_store_util_peer_set { int status; }; -struct ble_store_util_peer_cccd_set { - struct ble_store_util_peer_set peer_set; - ble_addr_t *curr_peer_addr; -}; - - static int ble_store_util_iter_unique_peer(int obj_type, union ble_store_value *val, @@ -65,42 +60,6 @@ ble_store_util_iter_unique_peer(int obj_type, return 0; } -static int -ble_store_util_iter_peer_cccd(int obj_type, - union ble_store_value *val, - void *arg) -{ - struct ble_store_util_peer_cccd_set *set; - int i; - - set = arg; - - /* Do nothing if this peer is a duplicate or current peer */ - for (i = 0; i < set->peer_set.num_peers; i++) { - if (ble_addr_cmp(set->peer_set.peer_id_addrs + i, &val->cccd.peer_addr) == 0) { - return 0; - } - - if (set->curr_peer_addr != NULL) { - if (ble_addr_cmp(set->curr_peer_addr, &val->cccd.peer_addr) == 0) { - return 0; - } - } - } - - if (set->peer_set.num_peers >= set->peer_set.max_peers) { - /* Overflow; abort the iterate procedure. */ - set->peer_set.status = BLE_HS_ENOMEM; - return 1; - } - - set->peer_set.peer_id_addrs[set->peer_set.num_peers] = val->cccd.peer_addr; - set->peer_set.num_peers++; - - return 0; -} - - /** * Retrieves the set of peer addresses for which a bond has been established. * @@ -141,51 +100,6 @@ ble_store_util_bonded_peers(ble_addr_t *out_peer_id_addrs, int *out_num_peers, return 0; } -/** - * Retrieves the set of peer addresses for which CCCDs are subscribed. - * - * @param out_peer_id_addrs On success, the set of peer addresses - * gets written here. - * @param out_num_peers On success, the number of peer addresses gets written - * here. - * @param max_peers The capacity of the destination buffer. - * - * @param curr_peer_addrs Current peer's address, ignore if NULL - * - * @return 0 on success; - * BLE_HS_ENOMEM if the destination buffer is too - * small; - * Other nonzero on error. - */ -static int -ble_store_util_subscribed_cccds(ble_addr_t *out_peer_id_addrs, int *out_num_peers, - int max_peers, ble_addr_t *curr_peer_addr) -{ - struct ble_store_util_peer_cccd_set set = { - .peer_set = { - .peer_id_addrs = out_peer_id_addrs, - .num_peers = 0, - .max_peers = max_peers, - .status = 0, - }, - .curr_peer_addr = curr_peer_addr, - }; - int rc; - - rc = ble_store_iterate(BLE_STORE_OBJ_TYPE_CCCD, - ble_store_util_iter_peer_cccd, - &set); - if (rc != 0) { - return rc; - } - if (set.peer_set.status != 0) { - return set.peer_set.status; - } - - *out_num_peers = set.peer_set.num_peers; - return 0; -} - /** * Deletes all entries from the store that are attached to the specified peer * address. This function deletes security entries and CCCD records. @@ -222,6 +136,25 @@ ble_store_util_delete_peer(const ble_addr_t *peer_id_addr) return rc; } +#if MYNEWT_VAL(BLE_HOST_BASED_PRIVACY) + struct ble_hs_dev_records *peer_rec = + ble_rpa_find_peer_dev_rec(key.sec.peer_addr.val); + + if (peer_rec != NULL) { + rc = ble_hs_resolv_list_rmv(peer_rec->peer_sec.peer_addr.type, + peer_rec->peer_sec.peer_addr.val); + if (rc != 0) { + /* We can't do anything much here, continue with removing from peer_record */ + BLE_HS_LOG(DEBUG, "Peer Device was not removed from RL \n"); + } + + rc = ble_rpa_remove_peer_dev_rec(peer_rec); + if (rc != 0) { + return rc; + } + } +#endif + return 0; } @@ -305,63 +238,6 @@ ble_store_util_delete_oldest_peer(void) return 0; } -/** - * Delete CCCDs of unbonded devices. - * - * @param curr_peer Current peer's address (not to delete), ignore - * ignore if NULL - * - * @return 0 on success; - * nonzero on error. - */ -int -ble_store_clean_old_cccds(const ble_addr_t *curr_peer) -{ - ble_addr_t peer_cccd_addrs[MYNEWT_VAL(BLE_STORE_MAX_CCCDS)]; - ble_addr_t peer_bonded_addrs[MYNEWT_VAL(BLE_STORE_MAX_BONDS)]; - int num_bonded_peers, num_cccd_peers; - int i, j, rc; - - rc = ble_store_util_subscribed_cccds(&peer_cccd_addrs[0], &num_cccd_peers, - MYNEWT_VAL(BLE_STORE_MAX_CCCDS), - (void *) curr_peer); - if (rc != 0) { - return rc; - } - - rc = ble_store_util_bonded_peers(&peer_bonded_addrs[0], &num_bonded_peers, - MYNEWT_VAL(BLE_STORE_MAX_BONDS)); - if (rc != 0) { - return rc; - } - - union ble_store_key key = {0}; - /* Init rc to BLE_HS_ENOENT to indicate no CCCD is deleted */ - rc = BLE_HS_ENOENT; - - for (i = 0; i < num_cccd_peers; i++) { - key.cccd.peer_addr = peer_cccd_addrs[i]; - - for (j = 0; j < num_bonded_peers; j++) { - if (memcmp(&peer_cccd_addrs[i], &peer_bonded_addrs[j], - sizeof(ble_addr_t)) == 0) { - break; - } - } - - if (j < num_bonded_peers) { - continue; - } - - rc = ble_store_util_delete_all(BLE_STORE_OBJ_TYPE_CCCD, &key); - if (rc != 0) { - return rc; - } - } - - return rc; -} - /** * Round-robin status callback. If a there is insufficient storage capacity * for a new record, delete the oldest bond and proceed with the persist @@ -374,33 +250,18 @@ ble_store_clean_old_cccds(const ble_addr_t *curr_peer) int ble_store_util_status_rr(struct ble_store_status_event *event, void *arg) { - int rc = BLE_HS_EUNKNOWN; switch (event->event_code) { case BLE_STORE_EVENT_OVERFLOW: switch (event->overflow.obj_type) { - case BLE_STORE_OBJ_TYPE_OUR_SEC: - case BLE_STORE_OBJ_TYPE_PEER_SEC: - return ble_gap_unpair_oldest_peer(); - case BLE_STORE_OBJ_TYPE_CCCD: - /* Try to remove unbonded CCCDs first */ - if ((rc = ble_store_clean_old_cccds((void *) &event->overflow.value->cccd.peer_addr)) == BLE_HS_ENOENT) { - /* No unbonded CCCDs found to delete, try unpairing oldest peer - * except current peer */ - return ble_gap_unpair_oldest_except_curr((void *) &event->overflow.value->cccd.peer_addr); - } - return rc; + case BLE_STORE_OBJ_TYPE_OUR_SEC: + case BLE_STORE_OBJ_TYPE_PEER_SEC: + return ble_gap_unpair_oldest_peer(); + case BLE_STORE_OBJ_TYPE_CCCD: + /* Try unpairing oldest peer except current peer */ + return ble_gap_unpair_oldest_except(&event->overflow.value->cccd.peer_addr); - default: - return BLE_HS_EUNKNOWN; - - /* case BLE_STORE_OBJ_TYPE_OUR_SEC: - case BLE_STORE_OBJ_TYPE_PEER_SEC: - case BLE_STORE_OBJ_TYPE_CCCD: - return ble_gap_unpair_oldest_peer(); - - default: - return BLE_HS_EUNKNOWN; - */ + default: + return BLE_HS_EUNKNOWN; } case BLE_STORE_EVENT_FULL: diff --git a/libesp32/NimBLE-Arduino/src/nimble/host/store/config/src/ble_store_nvs.c b/libesp32/NimBLE-Arduino/src/nimble/host/store/config/src/ble_store_nvs.c index 450b0e7f4..a6fea44c7 100644 --- a/libesp32/NimBLE-Arduino/src/nimble/host/store/config/src/ble_store_nvs.c +++ b/libesp32/NimBLE-Arduino/src/nimble/host/store/config/src/ble_store_nvs.c @@ -210,11 +210,11 @@ get_nvs_db_attribute(int obj_type, bool empty, void *value, int num_value) err = get_nvs_matching_index(&p_dev_rec, value, num_value, sizeof(struct ble_hs_dev_records)); } else { - if (obj_type == BLE_STORE_OBJ_TYPE_CCCD) { + if (obj_type != BLE_STORE_OBJ_TYPE_CCCD) { err = get_nvs_matching_index(&cur.sec, value, num_value, sizeof(struct ble_store_value_sec)); } else { - err = get_nvs_matching_index(&cur.sec, value, num_value, + err = get_nvs_matching_index(&cur.cccd, value, num_value, sizeof(struct ble_store_value_cccd)); } } diff --git a/libesp32/NimBLE-Arduino/src/nimble/nimble_npl.h b/libesp32/NimBLE-Arduino/src/nimble/nimble_npl.h index 689d363d9..883832289 100644 --- a/libesp32/NimBLE-Arduino/src/nimble/nimble_npl.h +++ b/libesp32/NimBLE-Arduino/src/nimble/nimble_npl.h @@ -16,8 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - -/* Modifications copyright (C) 2020 Ryan Powell*/ #ifndef _NIMBLE_NPL_H_ #define _NIMBLE_NPL_H_ @@ -26,6 +24,7 @@ #include #include #include "nimconfig.h" + #ifdef __cplusplus extern "C" { #endif diff --git a/libesp32/NimBLE-Arduino/src/nimble/nimble_port.h b/libesp32/NimBLE-Arduino/src/nimble/nimble_port.h index aa5e6390f..e8996a666 100644 --- a/libesp32/NimBLE-Arduino/src/nimble/nimble_port.h +++ b/libesp32/NimBLE-Arduino/src/nimble/nimble_port.h @@ -17,7 +17,6 @@ * under the License. */ - /* Modifications copyright (C) 2020 Ryan Powell */ #ifndef _NIMBLE_PORT_H #define _NIMBLE_PORT_H diff --git a/libesp32/NimBLE-Arduino/src/nimconfig.h b/libesp32/NimBLE-Arduino/src/nimconfig.h index 4db8562bb..0be27c198 100644 --- a/libesp32/NimBLE-Arduino/src/nimconfig.h +++ b/libesp32/NimBLE-Arduino/src/nimconfig.h @@ -1,17 +1,100 @@ #pragma once -#define CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL 1 -#define CONFIG_BT_NIMBLE_MAX_CONNECTIONS 3 -#define CONFIG_BT_NIMBLE_MAX_BONDS 3 -#define CONFIG_BT_NIMBLE_MAX_CCCDS 8 -#define CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM 0 -#define CONFIG_BT_NIMBLE_PINNED_TO_CORE_0 1 + +#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 // Tasmota + +/** Comment out if not using NimBLE Advertising functions + * Reduces flash size by approx. 5kB. + */ +// #define CONFIG_BT_NIMBLE_ROLE_BROADCASTER // Tasmota + +/** 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 -#define CONFIG_BT_NIMBLE_ROLE_CENTRAL 1 -#define CONFIG_BT_NIMBLE_ROLE_PERIPHERAL 1 -#define CONFIG_BT_NIMBLE_ROLE_BROADCASTER 1 -#define CONFIG_BT_NIMBLE_ROLE_OBSERVER 1 -#define CONFIG_BT_NIMBLE_NVS_PERSIST 1 + +/** 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 // Tasmota + +/** Sets the number of CCCD's to store per bonded device */ +#define CONFIG_BT_NIMBLE_MAX_CCCDS 3 // Tasmota + +#define CONFIG_BT_NIMBLE_NVS_PERSIST 0 // Tasmota #define CONFIG_BT_NIMBLE_SM_LEGACY 1 #define CONFIG_BT_NIMBLE_SM_SC 1 #define CONFIG_BT_NIMBLE_SVC_GAP_DEVICE_NAME "nimble" @@ -29,6 +112,23 @@ #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_ENABLED 1 -#define CONFIG_BTDM_CONTROLLER_MODE_BLE_ONLY 1 -#define CONFIG_BT_NIMBLE_DEBUG 0 +#define CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM 0 + +/** Do not comment out */ +#ifndef CONFIG_BT_ENABLED +#define CONFIG_BT_ENABLED +#endif +#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 diff --git a/libesp32/NimBLE-Arduino/src/port/src/esp_nimble_mem.c b/libesp32/NimBLE-Arduino/src/port/src/esp_nimble_mem.c index ae2a69c20..a26e9b2f4 100644 --- a/libesp32/NimBLE-Arduino/src/port/src/esp_nimble_mem.c +++ b/libesp32/NimBLE-Arduino/src/port/src/esp_nimble_mem.c @@ -19,8 +19,6 @@ * under the License. */ - /* Modifications copyright (C) 2020 Ryan Powell */ - #include "esp_attr.h" #include "esp_heap_caps.h" #include "nimconfig.h" @@ -32,6 +30,8 @@ IRAM_ATTR void *nimble_platform_mem_malloc(size_t size) return heap_caps_malloc(size, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); #elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL return heap_caps_malloc(size, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT); +#elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_IRAM_8BIT + return heap_caps_malloc_prefer(size, 2, MALLOC_CAP_INTERNAL|MALLOC_CAP_IRAM_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); #else return malloc(size); #endif @@ -43,6 +43,8 @@ IRAM_ATTR void *nimble_platform_mem_calloc(size_t n, size_t size) return heap_caps_calloc(n, size, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); #elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL return heap_caps_calloc(n, size, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT); +#elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_IRAM_8BIT + return heap_caps_calloc_prefer(n, size, 2, MALLOC_CAP_INTERNAL|MALLOC_CAP_IRAM_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); #else return calloc(n, size); #endif @@ -51,4 +53,4 @@ IRAM_ATTR void *nimble_platform_mem_calloc(size_t n, size_t size) IRAM_ATTR void nimble_platform_mem_free(void *ptr) { heap_caps_free(ptr); -} \ No newline at end of file +} From 9f8d0fcd85744705d8ccdf99026ba46c0943670d Mon Sep 17 00:00:00 2001 From: Staars Date: Tue, 26 May 2020 20:44:40 +0200 Subject: [PATCH 2/3] update driver --- tasmota/xsns_62_MI_ESP32.ino | 360 +++++++++++++++++++---------------- 1 file changed, 201 insertions(+), 159 deletions(-) diff --git a/tasmota/xsns_62_MI_ESP32.ino b/tasmota/xsns_62_MI_ESP32.ino index c9a5ba73a..28c927db9 100644 --- a/tasmota/xsns_62_MI_ESP32.ino +++ b/tasmota/xsns_62_MI_ESP32.ino @@ -225,18 +225,26 @@ class MI32SensorCallback : public NimBLEClientCallbacks { class MI32AdvCallbacks: public NimBLEAdvertisedDeviceCallbacks { void onResult(NimBLEAdvertisedDevice* advertisedDevice) { - // AddLog_P2(LOG_LEVEL_DEBUG,PSTR("Advertised Device: %s Buffer: %u"),advertisedDevice.getAddress().toString().c_str(),advertisedDevice.getServiceData().length()); - if (advertisedDevice->getServiceData().length() == 0) return; + // AddLog_P2(LOG_LEVEL_DEBUG,PSTR("Advertised Device: %s Buffer: %u"),advertisedDevice->getAddress().toString().c_str(),advertisedDevice->getServiceData().length()); + if (advertisedDevice->getServiceData().length() == 0) { + // AddLog_P2(LOG_LEVEL_DEBUG,PSTR("No Xiaomi Device: %s Buffer: %u"),advertisedDevice->getAddress().toString().c_str(),advertisedDevice->getServiceData().length()); + MI32Scan->erase(advertisedDevice->getAddress()); + return; + } uint16_t uuid = advertisedDevice->getServiceDataUUID().getNative()->u16.value; - AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%x"),uuid); + // AddLog_P2(LOG_LEVEL_DEBUG,PSTR("UUID: %x"),uuid); uint8_t addr[6]; memcpy(addr,advertisedDevice->getAddress().getNative(),6); MI32_ReverseMAC(addr); if(uuid==0xfe95) { - MI32ParseResponse((char*)advertisedDevice->getServiceData().c_str(),advertisedDevice->getServiceData().length(), addr); + MI32ParseResponse((char*)advertisedDevice->getServiceData().data(),advertisedDevice->getServiceData().length(), addr); } else if(uuid==0xfdcd) { - MI32parseCGD1Packet((char*)advertisedDevice->getServiceData().c_str(),advertisedDevice->getServiceData().length(), addr); + MI32parseCGD1Packet((char*)advertisedDevice->getServiceData().data(),advertisedDevice->getServiceData().length(), addr); + } + else { + // AddLog_P2(LOG_LEVEL_DEBUG,PSTR("No Xiaomi Device: %s Buffer: %u"),advertisedDevice->getAddress().toString().c_str(),advertisedDevice->getServiceData().length()); + MI32Scan->erase(advertisedDevice->getAddress()); } }; }; @@ -391,47 +399,57 @@ void MI32StartTask(uint32_t task){ } } -void MI32ConnectActiveSensor(){ // only use inside a task !! +bool MI32ConnectActiveSensor(){ // only use inside a task !! + MI32.mode.connected = 0; MI32Client = nullptr; - esp_bd_addr_t address; - memcpy(address,MIBLEsensors[MI32.state.sensor].serial,sizeof(address)); + Wifi.counter = Wifi.counter + 20; // hopefully less interference + NimBLEAddress _address = NimBLEAddress(MIBLEsensors[MI32.state.sensor].serial); if(NimBLEDevice::getClientListSize()) { - MI32Client = NimBLEDevice::getClientByPeerAddress(NimBLEAddress(address)); + // AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s: found any clients in the cList"),D_CMND_MI32); + MI32Client = NimBLEDevice::getClientByPeerAddress(_address); if(MI32Client){ - if(!MI32Client->connect(NimBLEAddress(address), 0,false)) { - MI32.mode.willConnect = 0; - vTaskDelete( NULL ); - } + // Should be impossible + // AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s: got connected client"),D_CMND_MI32); } else { + // Should be the norm after the first iteration MI32Client = NimBLEDevice::getDisconnectedClient(); + DEBUG_SENSOR_LOG(PSTR("%s: got disconnected client"),D_CMND_MI32); } } + + if(NimBLEDevice::getClientListSize() >= NIMBLE_MAX_CONNECTIONS) { + MI32.mode.willConnect = 0; + DEBUG_SENSOR_LOG(PSTR("%s: max connection already reached"),D_CMND_MI32); + return false; + } if(!MI32Client) { - if(NimBLEDevice::getClientListSize() >= NIMBLE_MAX_CONNECTIONS) { - MI32.mode.willConnect = 0; - vTaskDelete( NULL ); - } + AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s: will create client"),D_CMND_MI32); MI32Client = NimBLEDevice::createClient(); MI32Client->setClientCallbacks(&MI32SensorCB , false); - MI32Client->setConnectionParams(12,12,0,51); - MI32Client->setConnectTimeout(10); - if (!MI32Client->connect(NimBLEAddress(address),0,false)) { - MI32.mode.willConnect = 0; - NimBLEDevice::deleteClient(MI32Client); - vTaskDelete( NULL ); - } + MI32Client->setConnectionParams(12,12,0,48); + MI32Client->setConnectTimeout(30); } + if (!MI32Client->connect(_address,false)) { + MI32.mode.willConnect = 0; + NimBLEDevice::deleteClient(MI32Client); + DEBUG_SENSOR_LOG(PSTR("%s: did not connect client"),D_CMND_MI32); + return false; + } + DEBUG_SENSOR_LOG(PSTR("%s: did create new client"),D_CMND_MI32); + return true; + // } } void MI32StartScanTask(){ if (MI32.mode.connected) return; MI32.mode.runningScan = 1; + // Wifi.counter = Wifi.counter + 3; xTaskCreatePinnedToCore( MI32ScanTask, /* Function to implement the task */ "MI32ScanTask", /* Name of the task */ - 4096, /* Stack size in words */ + 8192, /* Stack size in words */ NULL, /* Task input parameter */ 0, /* Priority of the task */ NULL, /* Task handle. */ @@ -440,17 +458,18 @@ void MI32StartScanTask(){ } void MI32ScanTask(void *pvParameters){ - NimBLEScan* pScan = NimBLEDevice::getScan(); - pScan->setAdvertisedDeviceCallbacks(&MI32ScanCallbacks); - pScan->setActiveScan(false); - pScan->start(5, MI32scanEndedCB); // hard coded duration + if (MI32Scan == nullptr) MI32Scan = NimBLEDevice::getScan(); + DEBUG_SENSOR_LOG(PSTR("%s: Scan Cache Length: %u"),D_CMND_MI32, MI32Scan->getResults().getCount()); + MI32Scan->setAdvertisedDeviceCallbacks(&MI32ScanCallbacks); + MI32Scan->setActiveScan(false); + MI32Scan->start(5, MI32scanEndedCB, true); // hard coded duration uint32_t timer = 0; while (MI32.mode.runningScan){ if (timer>15){ vTaskDelete( NULL ); } timer++; - vTaskDelay(1000); + vTaskDelay(1000/ portTICK_PERIOD_MS); } vTaskDelete( NULL ); } @@ -474,47 +493,62 @@ void MI32SensorTask(void *pvParameters){ MI32.mode.willConnect = 0; vTaskDelete( NULL ); } - MI32ConnectActiveSensor(); - MI32.mode.readingDone = 1; - switch(MIBLEsensors[MI32.state.sensor].type){ - case LYWSD03MMC: - MI32.mode.readingDone = 0; - MI32connectLYWSD03(); - break; - default: - break; - } - uint32_t timer = 0; - while (!MI32.mode.readingDone){ - if (timer>150){ + if (MI32ConnectActiveSensor()){ + uint32_t timer = 0; + while (MI32.mode.connected == 0){ + if (timer>1000){ + MI32Client->disconnect(); + NimBLEDevice::deleteClient(MI32Client); + MI32.mode.willConnect = 0; + vTaskDelay(100/ portTICK_PERIOD_MS); + vTaskDelete( NULL ); + } + timer++; + vTaskDelay(10/ portTICK_PERIOD_MS); + } + + timer = 150; + switch(MIBLEsensors[MI32.state.sensor].type){ + case LYWSD03MMC: + MI32.mode.readingDone = 0; + if(MI32connectLYWSD03forNotification()) timer=0; + break; + default: break; } - timer++; - vTaskDelay(100); + + while (!MI32.mode.readingDone){ + if (timer>150){ + break; + } + timer++; + vTaskDelay(100/ portTICK_PERIOD_MS); + } + MI32Client->disconnect(); + DEBUG_SENSOR_LOG(PSTR("%s: requested disconnect"),D_CMND_MI32); } - MI32Client->disconnect(); - NimBLEDevice::deleteClient(MI32Client); - vTaskDelay(500); + vTaskDelay(500/ portTICK_PERIOD_MS); MI32.mode.connected = 0; vTaskDelete( NULL ); } -void MI32connectLYWSD03(){ +bool MI32connectLYWSD03forNotification(){ NimBLERemoteService* pSvc = nullptr; NimBLERemoteCharacteristic* pChr = nullptr; - static BLEUUID serviceUUID("ebe0ccb0-7a0a-4b0c-8a1a-6ff2997da3a6"); - static BLEUUID charUUID("ebe0ccc1-7a0a-4b0c-8a1a-6ff2997da3a6"); + static BLEUUID serviceUUID(0xebe0ccb0,0x7a0a,0x4b0c,0x8a1a6ff2997da3a6); + static BLEUUID charUUID(0xebe0ccc1,0x7a0a,0x4b0c,0x8a1a6ff2997da3a6); pSvc = MI32Client->getService(serviceUUID); if(pSvc) { pChr = pSvc->getCharacteristic(charUUID); } - if(pChr->canNotify()) { - if(!pChr->registerForNotify(MI32notifyCB)) { - MI32.mode.willConnect = 0; - MI32Client->disconnect(); - return; + if (pChr){ + if(pChr->canNotify()) { + if(pChr->registerForNotify(MI32notifyCB)) { + return true; + } } } + return false; } void MI32StartTimeTask(){ @@ -536,45 +570,48 @@ void MI32TimeTask(void *pvParameters){ MI32.mode.shallSetTime = 0; vTaskDelete( NULL ); } - MI32ConnectActiveSensor(); - uint32_t timer = 0; - while (MI32.mode.connected == 0){ - if (timer>1000){ - break; + if(MI32ConnectActiveSensor()){ + uint32_t timer = 0; + while (MI32.mode.connected == 0){ + if (timer>1000){ + break; + } + timer++; + vTaskDelay(10/ portTICK_PERIOD_MS); } - timer++; - vTaskDelay(10); - } - NimBLERemoteService* pSvc = nullptr; - NimBLERemoteCharacteristic* pChr = nullptr; - static BLEUUID serviceUUID("EBE0CCB0-7A0A-4B0C-8A1A-6FF2997DA3A6"); - static BLEUUID charUUID("EBE0CCB7-7A0A-4B0C-8A1A-6FF2997DA3A6"); - pSvc = MI32Client->getService(serviceUUID); - if(pSvc) { - pChr = pSvc->getCharacteristic(charUUID); - } - if(pChr->canWrite()) { - union { - uint8_t buf[5]; - uint32_t time; - } _utc; - _utc.time = Rtc.utc_time; - _utc.buf[4] = Rtc.time_timezone / 60; + NimBLERemoteService* pSvc = nullptr; + NimBLERemoteCharacteristic* pChr = nullptr; + static BLEUUID serviceUUID(0xEBE0CCB0,0x7A0A,0x4B0C,0x8A1A6FF2997DA3A6); + static BLEUUID charUUID(0xEBE0CCB7,0x7A0A,0x4B0C,0x8A1A6FF2997DA3A6); + pSvc = MI32Client->getService(serviceUUID); + if(pSvc) { + pChr = pSvc->getCharacteristic(charUUID); - if(!pChr->writeValue(_utc.buf,sizeof(_utc.buf),true)) { // true is important ! - MI32.mode.willConnect = 0; - MI32Client->disconnect(); } - else { - MI32.mode.shallSetTime = 0; - MI32.mode.willSetTime = 0; + if (pChr){ + if(pChr->canWrite()) { + union { + uint8_t buf[5]; + uint32_t time; + } _utc; + _utc.time = Rtc.utc_time; + _utc.buf[4] = Rtc.time_timezone / 60; + + if(!pChr->writeValue(_utc.buf,sizeof(_utc.buf),true)) { // true is important ! + MI32.mode.willConnect = 0; + MI32Client->disconnect(); + } + else { + MI32.mode.shallSetTime = 0; + MI32.mode.willSetTime = 0; + } + } } + MI32Client->disconnect(); } - MI32Client->disconnect(); - NimBLEDevice::deleteClient(MI32Client); - vTaskDelay(500); + vTaskDelay(500/ portTICK_PERIOD_MS); MI32.mode.connected = 0; vTaskDelete( NULL ); } @@ -582,6 +619,8 @@ void MI32TimeTask(void *pvParameters){ void MI32StartBatteryTask(){ if (MI32.mode.connected) return; MI32.mode.willReadBatt = 1; + MI32.mode.willConnect = 1; + MI32.mode.canScan = 0; xTaskCreatePinnedToCore( MI32BatteryTask, /* Function to implement the task */ "MI32BatteryTask", /* Name of the task */ @@ -605,31 +644,32 @@ void MI32BatteryTask(void *pvParameters){ } MI32.mode.connected = 0; - MI32ConnectActiveSensor(); - uint32_t timer = 0; - while (MI32.mode.connected == 0){ - if (timer>1000){ + if(MI32ConnectActiveSensor()){ + uint32_t timer = 0; + while (MI32.mode.connected == 0){ + if (timer>1000){ + break; + } + timer++; + vTaskDelay(30/ portTICK_PERIOD_MS); + } + + switch(MIBLEsensors[MI32.state.sensor].type){ + case FLORA: + MI32batteryFLORA(); + break; + case LYWSD02: + MI32batteryLYWSD02(); + break; + case CGD1: + MI32batteryCGD1(); break; } - timer++; - vTaskDelay(10); - } - - switch(MIBLEsensors[MI32.state.sensor].type){ - case FLORA: - MI32batteryFLORA(); - break; - case LYWSD02: - MI32batteryLYWSD02(); - break; - case CGD1: - MI32batteryCGD1(); - break; - } - MI32Client->disconnect(); + MI32Client->disconnect(); + } MI32.mode.willReadBatt = 0; - NimBLEDevice::deleteClient(MI32Client); - vTaskDelay(500); + // Wifi.counter = 0; // Now check it + vTaskDelay(500/ portTICK_PERIOD_MS); MI32.mode.connected = 0; vTaskDelete( NULL ); } @@ -641,27 +681,26 @@ void MI32batteryFLORA(){ break; } timer++; - vTaskDelay(10); + vTaskDelay(10/ portTICK_PERIOD_MS); } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s connected for battery"),kMI32SlaveType[MIBLEsensors[MI32.state.sensor].type-1] ); + DEBUG_SENSOR_LOG(PSTR("%s connected for battery"),kMI32SlaveType[MIBLEsensors[MI32.state.sensor].type-1] ); NimBLERemoteService* pSvc = nullptr; NimBLERemoteCharacteristic* pChr = nullptr; - static BLEUUID FLserviceUUID("00001204-0000-1000-8000-00805f9b34fb"); - static BLEUUID FLcharUUID("00001a02-0000-1000-8000-00805f9b34fb"); + static BLEUUID FLserviceUUID(0x00001204,0x0000,0x1000,0x800000805f9b34fb); + static BLEUUID FLcharUUID(0x00001a02,0x0000,0x1000,0x800000805f9b34fb); pSvc = MI32Client->getService(FLserviceUUID); - if(pSvc) { /** make sure it's not null */ + if(pSvc) { pChr = pSvc->getCharacteristic(FLcharUUID); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: got Flora char %s"),D_CMND_MI32, pChr->getUUID().toString().c_str()); } - else { - MI32.mode.readingDone = 1; - return; - } - if(pChr->canRead()) { - const char *buf = pChr->readValue().c_str(); - MI32readBat((char*)buf); + if (pChr){ + DEBUG_SENSOR_LOG(PSTR("%s: got Flora char %s"),D_CMND_MI32, pChr->getUUID().toString().c_str()); + if(pChr->canRead()) { + const char *buf = pChr->readValue().c_str(); + MI32readBat((char*)buf); + } } + MI32.mode.readingDone = 1; } void MI32batteryLYWSD02(){ @@ -671,27 +710,27 @@ void MI32batteryLYWSD02(){ break; } timer++; - vTaskDelay(10); + vTaskDelay(10/ portTICK_PERIOD_MS); } NimBLERemoteService* pSvc = nullptr; NimBLERemoteCharacteristic* pChr = nullptr; - static BLEUUID LY2serviceUUID("EBE0CCB0-7A0A-4B0C-8A1A-6FF2997DA3A6"); - static BLEUUID LY2charUUID("EBE0CCC4-7A0A-4B0C-8A1A-6FF2997DA3A6"); + static BLEUUID LY2serviceUUID(0xEBE0CCB0,0x7A0A,0x4B0C,0x8A1A6FF2997DA3A6); + static BLEUUID LY2charUUID(0xEBE0CCC4,0x7A0A,0x4B0C,0x8A1A6FF2997DA3A6); pSvc = MI32Client->getService(LY2serviceUUID); if(pSvc) { pChr = pSvc->getCharacteristic(LY2charUUID); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: got LYWSD02 char %s"),D_CMND_MI32, pChr->getUUID().toString().c_str()); } - else { - return; - } - if(pChr->canRead()) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("LYWSD02 char")); - const char *buf = pChr->readValue().c_str(); - MI32readBat((char*)buf); + if (pChr){ + DEBUG_SENSOR_LOG( PSTR("%s: got LYWSD02 char %s"),D_CMND_MI32, pChr->getUUID().toString().c_str()); + if(pChr->canRead()) { + DEBUG_SENSOR_LOG(PSTR("LYWSD02 char")); + const char *buf = pChr->readValue().c_str(); + MI32readBat((char*)buf); + } } + MI32.mode.readingDone = 1; } void MI32batteryCGD1(){ @@ -701,26 +740,26 @@ void MI32batteryCGD1(){ break; } timer++; - vTaskDelay(10); + vTaskDelay(10/ portTICK_PERIOD_MS); } NimBLERemoteService* pSvc = nullptr; NimBLERemoteCharacteristic* pChr = nullptr; - static BLEUUID CGD1serviceUUID("180F"); - static BLEUUID CGD1charUUID("2A19"); + static BLEUUID CGD1serviceUUID((uint16_t)0x180F); + static BLEUUID CGD1charUUID((uint16_t)0x2A19); pSvc = MI32Client->getService(CGD1serviceUUID); if(pSvc) { pChr = pSvc->getCharacteristic(CGD1charUUID); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s: got CGD1 char %s"),D_CMND_MI32, pChr->getUUID().toString().c_str()); } - else { - return; - } - if(pChr->canRead()) { - const char *buf = pChr->readValue().c_str(); - MI32readBat((char*)buf); + if (pChr){ + DEBUG_SENSOR_LOG(PSTR("%s: got CGD1 char %s"),D_CMND_MI32, pChr->getUUID().toString().c_str()); + if(pChr->canRead()) { + const char *buf = pChr->readValue().c_str(); + MI32readBat((char*)buf); + } } + MI32.mode.readingDone = 1; } @@ -740,14 +779,14 @@ void MI32parseMiBeacon(char * _buf, uint32_t _slot){ } MI32_ReverseMAC(_beacon.Mac); - DEBUG_SENSOR_LOG(PSTR("MiBeacon type:%02x: %02x %02x %02x %02x %02x %02x %02x %02x"),_beacon.type, (uint8_t)_buf[0],(uint8_t)_buf[1],(uint8_t)_buf[2],(uint8_t)_buf[3],(uint8_t)_buf[4],(uint8_t)_buf[5],(uint8_t)_buf[6],(uint8_t)_buf[7]); - DEBUG_SENSOR_LOG(PSTR(" type:%02x: %02x %02x %02x %02x %02x %02x %02x %02x"),_beacon.type, (uint8_t)_buf[8],(uint8_t)_buf[9],(uint8_t)_buf[10],(uint8_t)_buf[11],(uint8_t)_buf[12],(uint8_t)_buf[13],(uint8_t)_buf[14],(uint8_t)_buf[15]); + // AddLog_P2(LOG_LEVEL_DEBUG,PSTR("MiBeacon type:%02x: %02x %02x %02x %02x %02x %02x %02x %02x"),_beacon.type, (uint8_t)_buf[0],(uint8_t)_buf[1],(uint8_t)_buf[2],(uint8_t)_buf[3],(uint8_t)_buf[4],(uint8_t)_buf[5],(uint8_t)_buf[6],(uint8_t)_buf[7]); + // AddLog_P2(LOG_LEVEL_DEBUG,PSTR(" type:%02x: %02x %02x %02x %02x %02x %02x %02x %02x"),_beacon.type, (uint8_t)_buf[8],(uint8_t)_buf[9],(uint8_t)_buf[10],(uint8_t)_buf[11],(uint8_t)_buf[12],(uint8_t)_buf[13],(uint8_t)_buf[14],(uint8_t)_buf[15]); if(MIBLEsensors[_slot].type==4 || MIBLEsensors[_slot].type==6){ DEBUG_SENSOR_LOG(PSTR("LYWSD03 and CGD1 no support for MiBeacon, type %u"),MIBLEsensors[_slot].type); return; } - DEBUG_SENSOR_LOG(PSTR("%s at slot %u"), kMI32SlaveType[MIBLEsensors[_slot].type-1],_slot); + AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s at slot %u"), kMI32SlaveType[MIBLEsensors[_slot].type-1],_slot); switch(_beacon.type){ case 0x04: _tempFloat=(float)(_beacon.temp)/10.0f; @@ -755,7 +794,7 @@ void MI32parseMiBeacon(char * _buf, uint32_t _slot){ MIBLEsensors[_slot].temp=_tempFloat; DEBUG_SENSOR_LOG(PSTR("Mode 4: temp updated")); } - DEBUG_SENSOR_LOG(PSTR("Mode 4: U16: %u Temp"), _beacon.temp ); + // AddLog_P2(LOG_LEVEL_DEBUG,PSTR("Mode 4: U16: %u Temp"), _beacon.temp ); break; case 0x06: _tempFloat=(float)(_beacon.hum)/10.0f; @@ -763,11 +802,11 @@ void MI32parseMiBeacon(char * _buf, uint32_t _slot){ MIBLEsensors[_slot].hum=_tempFloat; DEBUG_SENSOR_LOG(PSTR("Mode 6: hum updated")); } - DEBUG_SENSOR_LOG(PSTR("Mode 6: U16: %u Hum"), _beacon.hum); + // AddLog_P2(LOG_LEVEL_DEBUG,PSTR("Mode 6: U16: %u Hum"), _beacon.hum); break; case 0x07: MIBLEsensors[_slot].lux=_beacon.lux & 0x00ffffff; - DEBUG_SENSOR_LOG(PSTR("Mode 7: U24: %u Lux"), _beacon.lux & 0x00ffffff); + // AddLog_P2(LOG_LEVEL_DEBUG,PSTR("Mode 7: U24: %u Lux"), _beacon.lux & 0x00ffffff); break; case 0x08: _tempFloat =(float)_beacon.moist; @@ -775,7 +814,7 @@ void MI32parseMiBeacon(char * _buf, uint32_t _slot){ MIBLEsensors[_slot].moisture=_tempFloat; DEBUG_SENSOR_LOG(PSTR("Mode 8: moisture updated")); } - DEBUG_SENSOR_LOG(PSTR("Mode 8: U8: %u Moisture"), _beacon.moist); + // AddLog_P2(LOG_LEVEL_DEBUG,PSTR("Mode 8: U8: %u Moisture"), _beacon.moist); break; case 0x09: _tempFloat=(float)(_beacon.fert); @@ -783,14 +822,14 @@ void MI32parseMiBeacon(char * _buf, uint32_t _slot){ MIBLEsensors[_slot].fertility=_tempFloat; DEBUG_SENSOR_LOG(PSTR("Mode 9: fertility updated")); } - DEBUG_SENSOR_LOG(PSTR("Mode 9: U16: %u Fertility"), _beacon.fert); + // AddLog_P2(LOG_LEVEL_DEBUG,PSTR("Mode 9: U16: %u Fertility"), _beacon.fert); break; case 0x0a: if(_beacon.bat<101){ MIBLEsensors[_slot].bat = _beacon.bat; DEBUG_SENSOR_LOG(PSTR("Mode a: bat updated")); } - DEBUG_SENSOR_LOG(PSTR("Mode a: U8: %u %%"), _beacon.bat); + // AddLog_P2(LOG_LEVEL_DEBUG,PSTR("Mode a: U8: %u %%"), _beacon.bat); break; case 0x0d: _tempFloat=(float)(_beacon.HT.temp)/10.0f; @@ -803,7 +842,7 @@ void MI32parseMiBeacon(char * _buf, uint32_t _slot){ MIBLEsensors[_slot].hum = _tempFloat; DEBUG_SENSOR_LOG(PSTR("Mode d: hum updated")); } - DEBUG_SENSOR_LOG(PSTR("Mode d: U16: %x Temp U16: %x Hum"), _beacon.HT.temp, _beacon.HT.hum); + // AddLog_P2(LOG_LEVEL_DEBUG,PSTR("Mode d: U16: %x Temp U16: %x Hum"), _beacon.HT.temp, _beacon.HT.hum); break; } } @@ -911,6 +950,8 @@ void MI32EverySecond(bool restart){ _counter = 0; MI32.mode.canScan = 0; MI32.mode.canConnect = 1; + MI32.mode.willReadBatt = 0; + MI32.mode.willConnect = 0; return; } @@ -940,9 +981,9 @@ void MI32EverySecond(bool restart){ if(_counter==0) { MI32.state.sensor = _nextSensorSlot; - AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s: active sensor now: %u"),D_CMND_MI32, MI32.state.sensor); + AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s: active sensor now: %u of %u"),D_CMND_MI32, MI32.state.sensor, MIBLEsensors.size()-1); MI32.mode.canScan = 0; - if (MI32.mode.runningScan == 1 || MI32.mode.connected == 1) return; + if (MI32.mode.runningScan|| MI32.mode.connected || MI32.mode.willConnect) return; _nextSensorSlot++; MI32.mode.canConnect = 1; if(MI32.mode.connected == 0) { @@ -956,7 +997,7 @@ void MI32EverySecond(bool restart){ } } - if (MI32.state.sensor==MIBLEsensors.size()-1) { + if (_nextSensorSlot>(MIBLEsensors.size()-1)) { _nextSensorSlot= 0; _counter++; if (MI32.mode.shallReadBatt){ @@ -1056,6 +1097,7 @@ const char HTTP_MI32_HL[] PROGMEM = "{s}
{m}
{e}"; void MI32Show(bool json) { + if (json) { for (uint32_t i = 0; i < MIBLEsensors.size(); i++) { /* @@ -1069,7 +1111,7 @@ void MI32Show(bool json) MIBLEsensors[i].serial[3], MIBLEsensors[i].serial[4], MIBLEsensors[i].serial[5]); if (MIBLEsensors[i].type == FLORA) { - if (!isnan(MIBLEsensors[i].temp)) { // this is the error code -> no temperature + if (!isnan(MIBLEsensors[i].temp)) { char temperature[FLOATSZ]; // all sensors have temperature dtostrfd(MIBLEsensors[i].temp, Settings.flag2.temperature_resolution, temperature); ResponseAppend_P(PSTR("\"" D_JSON_TEMPERATURE "\":%s"), temperature); @@ -1196,4 +1238,4 @@ bool Xsns62(uint8_t function) return result; } #endif // USE_MI_ESP32 -#endif // ESP32 +#endif // ESP32 \ No newline at end of file From ba905255ee5f3ab11ab37942a89d6922eeff8498 Mon Sep 17 00:00:00 2001 From: Staars Date: Tue, 26 May 2020 20:45:55 +0200 Subject: [PATCH 3/3] remove second method to suppress warning --- platformio_override_sample.ini | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/platformio_override_sample.ini b/platformio_override_sample.ini index edfb35678..ee6fca3df 100644 --- a/platformio_override_sample.ini +++ b/platformio_override_sample.ini @@ -175,9 +175,7 @@ upload_speed = 921600 extra_scripts = ${common.extra_scripts} build_flags = ${esp_defaults.build_flags} -; NimBLE-Arduino uses arithmetic on void- and function-pointers, this is only a cosmetic warning suppression - -Wno-pointer-arith - + -D BUFFER_LENGTH=128 -D MQTT_MAX_PACKET_SIZE=1200 -D uint32=uint32_t