diff --git a/.gitignore b/.gitignore index 099e1f7c..15d2ae94 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,10 @@ .project .cproject .settings/ -/esp32-snippets/.vs + +# IDEs +.vs/ +.idea/ + +# CMake +cmake-build-debug/ diff --git a/README.md b/README.md index c785b3c6..fbea27ae 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,2 @@ # ESP32 Snippets -This repository hosts a set of ESP32 snippets that are in different -stages of completeness. They are made available in the hope that there -may be something of value to you and under the notion that something -is better than nothing. The samples are being categorized. - -* vfs - Virtual File System -* wifi - WiFi access -* curl - Examples of curl usage +This repository is no longer being actively maintained. It was previously archived to make it read-only but, by request, has been un-archived so that others may continue to post comments and issues. However, please understand that issues raised are unlikely to be resolved against this repository. diff --git a/cpp_utils/BLEAdvertisedDevice.cpp b/cpp_utils/BLEAdvertisedDevice.cpp index 104b2e12..d3e60bdd 100644 --- a/cpp_utils/BLEAdvertisedDevice.cpp +++ b/cpp_utils/BLEAdvertisedDevice.cpp @@ -13,14 +13,16 @@ */ #include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) -#include #include #include "BLEAdvertisedDevice.h" #include "BLEUtils.h" -#ifdef ARDUINO_ARCH_ESP32 +#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) #include "esp32-hal-log.h" -#endif +#define LOG_TAG "" +#else +#include "esp_log.h" static const char* LOG_TAG="BLEAdvertisedDevice"; +#endif BLEAdvertisedDevice::BLEAdvertisedDevice() { m_adFlag = 0; @@ -228,16 +230,17 @@ bool BLEAdvertisedDevice::haveTXPower() { * * https://www.bluetooth.com/specifications/assigned-numbers/generic-access-profile */ -void BLEAdvertisedDevice::parseAdvertisement(uint8_t* payload) { +void BLEAdvertisedDevice::parseAdvertisement(uint8_t* payload, size_t total_len) { uint8_t length; uint8_t ad_type; uint8_t sizeConsumed = 0; bool finished = false; - setPayload(payload); + m_payload = payload; + m_payloadLength = total_len; + while(!finished) { length = *payload; // Retrieve the length of the record. payload++; // Skip to type - while (!finished) { sizeConsumed += 1 + length; // increase the size consumed. if (length != 0) { // A length of 0 indicates that we have reached the end. @@ -250,7 +253,7 @@ void BLEAdvertisedDevice::parseAdvertisement(uint8_t* payload) { ad_type, BLEUtils::advTypeToString(ad_type), length, pHex); free(pHex); - switch (ad_type) { + switch(ad_type) { case ESP_BLE_AD_TYPE_NAME_CMPL: { // Adv Data Type: 0x09 setName(std::string(reinterpret_cast(payload), length)); break; @@ -273,7 +276,7 @@ void BLEAdvertisedDevice::parseAdvertisement(uint8_t* payload) { case ESP_BLE_AD_TYPE_16SRV_CMPL: case ESP_BLE_AD_TYPE_16SRV_PART: { // Adv Data Type: 0x02 - for (int var = 0; var < length / 2; ++var) { + for (int var = 0; var < length/2; ++var) { setServiceUUID(BLEUUID(*reinterpret_cast(payload + var * 2))); } break; @@ -281,7 +284,7 @@ void BLEAdvertisedDevice::parseAdvertisement(uint8_t* payload) { case ESP_BLE_AD_TYPE_32SRV_CMPL: case ESP_BLE_AD_TYPE_32SRV_PART: { // Adv Data Type: 0x04 - for (int var = 0; var < length / 4; ++var) { + for (int var = 0; var < length/4; ++var) { setServiceUUID(BLEUUID(*reinterpret_cast(payload + var * 4))); } break; @@ -308,7 +311,7 @@ void BLEAdvertisedDevice::parseAdvertisement(uint8_t* payload) { ESP_LOGE(LOG_TAG, "Length too small for ESP_BLE_AD_TYPE_SERVICE_DATA"); break; } - uint16_t uuid = *(uint16_t*) payload; + uint16_t uuid = *(uint16_t*)payload; setServiceDataUUID(BLEUUID(uuid)); if (length > 2) { setServiceData(std::string(reinterpret_cast(payload + 2), length - 2)); @@ -335,7 +338,7 @@ void BLEAdvertisedDevice::parseAdvertisement(uint8_t* payload) { break; } - setServiceDataUUID(BLEUUID(payload, (size_t) 16, false)); + setServiceDataUUID(BLEUUID(payload, (size_t)16, false)); if (length > 16) { setServiceData(std::string(reinterpret_cast(payload + 16), length - 16)); } @@ -351,9 +354,9 @@ void BLEAdvertisedDevice::parseAdvertisement(uint8_t* payload) { } // Length <> 0 - if (sizeConsumed >= 31 || length == 0) { + if (sizeConsumed >= total_len) finished = true; - } + } // !finished } // parseAdvertisement @@ -510,9 +513,20 @@ uint8_t* BLEAdvertisedDevice::getPayload() { return m_payload; } -void BLEAdvertisedDevice::setPayload(uint8_t* payload) { - m_payload = payload; +esp_ble_addr_type_t BLEAdvertisedDevice::getAddressType() { + return m_addressType; } +void BLEAdvertisedDevice::setAddressType(esp_ble_addr_type_t type) { + m_addressType = type; +} + +size_t BLEAdvertisedDevice::getPayloadLength() { + return m_payloadLength; +} + +void BLEAdvertisedDeviceCallbacks::onResult(BLEAdvertisedDevice dev) {} +void BLEAdvertisedDeviceCallbacks::onResult(BLEAdvertisedDevice* dev) {} #endif /* CONFIG_BT_ENABLED */ + diff --git a/cpp_utils/BLEAdvertisedDevice.h b/cpp_utils/BLEAdvertisedDevice.h index eebdd6ef..cd206d4a 100644 --- a/cpp_utils/BLEAdvertisedDevice.h +++ b/cpp_utils/BLEAdvertisedDevice.h @@ -40,6 +40,9 @@ class BLEAdvertisedDevice { BLEUUID getServiceUUID(); int8_t getTXPower(); uint8_t* getPayload(); + size_t getPayloadLength(); + esp_ble_addr_type_t getAddressType(); + void setAddressType(esp_ble_addr_type_t type); bool isAdvertisingService(BLEUUID uuid); @@ -56,7 +59,7 @@ class BLEAdvertisedDevice { private: friend class BLEScan; - void parseAdvertisement(uint8_t* payload); + void parseAdvertisement(uint8_t* payload, size_t total_len=62); void setAddress(BLEAddress address); void setAdFlag(uint8_t adFlag); void setAdvertizementResult(uint8_t* payload); @@ -70,7 +73,6 @@ class BLEAdvertisedDevice { void setServiceUUID(const char* serviceUUID); void setServiceUUID(BLEUUID serviceUUID); void setTXPower(int8_t txPower); - void setPayload(uint8_t* payload); bool m_haveAppearance; bool m_haveManufacturerData; @@ -81,6 +83,7 @@ class BLEAdvertisedDevice { bool m_haveTXPower; + BLEAddress m_address = BLEAddress((uint8_t*)"\0\0\0\0\0\0"); uint8_t m_adFlag; uint16_t m_appearance; int m_deviceType; @@ -92,8 +95,9 @@ class BLEAdvertisedDevice { int8_t m_txPower; std::string m_serviceData; BLEUUID m_serviceDataUUID; - uint8_t* m_payload; - BLEAddress m_address = BLEAddress((uint8_t*) "\0\0\0\0\0\0"); + uint8_t* m_payload = nullptr; + size_t m_payloadLength = 0; + esp_ble_addr_type_t m_addressType; }; /** @@ -112,7 +116,8 @@ class BLEAdvertisedDeviceCallbacks { * As we are scanning, we will find new devices. When found, this call back is invoked with a reference to the * device that was found. During any individual scan, a device will only be detected one time. */ - virtual void onResult(BLEAdvertisedDevice advertisedDevice) = 0; + virtual void onResult(BLEAdvertisedDevice advertisedDevice); + virtual void onResult(BLEAdvertisedDevice* advertisedDevice); }; #endif /* CONFIG_BT_ENABLED */ diff --git a/cpp_utils/BLEAdvertising.cpp b/cpp_utils/BLEAdvertising.cpp index d4fd6332..230d77cb 100644 --- a/cpp_utils/BLEAdvertising.cpp +++ b/cpp_utils/BLEAdvertising.cpp @@ -19,16 +19,18 @@ #include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) #include "BLEAdvertising.h" -#include #include #include "BLEUtils.h" #include "GeneralUtils.h" -#ifdef ARDUINO_ARCH_ESP32 +#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) #include "esp32-hal-log.h" +#define LOG_TAG "" +#else +#include "esp_log.h" +static const char* LOG_TAG = "BLEAdvertising"; #endif -static const char* LOG_TAG = "BLEAdvertising"; /** @@ -56,6 +58,7 @@ BLEAdvertising::BLEAdvertising() { m_advParams.own_addr_type = BLE_ADDR_TYPE_PUBLIC; m_advParams.channel_map = ADV_CHNL_ALL; m_advParams.adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY; + m_advParams.peer_addr_type = BLE_ADDR_TYPE_PUBLIC; m_customAdvData = false; // No custom advertising data m_customScanResponseData = false; // No custom scan response data @@ -92,15 +95,24 @@ void BLEAdvertising::setAppearance(uint16_t appearance) { } // setAppearance void BLEAdvertising::setMinInterval(uint16_t mininterval) { - m_advData.min_interval = mininterval; m_advParams.adv_int_min = mininterval; } // setMinInterval void BLEAdvertising::setMaxInterval(uint16_t maxinterval) { - m_advData.max_interval = maxinterval; m_advParams.adv_int_max = maxinterval; } // setMaxInterval +void BLEAdvertising::setMinPreferred(uint16_t mininterval) { + m_advData.min_interval = mininterval; +} // + +void BLEAdvertising::setMaxPreferred(uint16_t maxinterval) { + m_advData.max_interval = maxinterval; +} // + +void BLEAdvertising::setScanResponse(bool set) { + m_scanResp = set; +} /** * @brief Set the filtering for the scan filter. @@ -198,6 +210,8 @@ void BLEAdvertising::start() { if (!m_customAdvData) { // Set the configuration for advertising. m_advData.set_scan_rsp = false; + m_advData.include_name = !m_scanResp; + m_advData.include_txpower = !m_scanResp; errRc = ::esp_ble_gap_config_adv_data(&m_advData); if (errRc != ESP_OK) { ESP_LOGE(LOG_TAG, "<< esp_ble_gap_config_adv_data: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); @@ -205,8 +219,10 @@ void BLEAdvertising::start() { } } - if (!m_customScanResponseData) { + if (!m_customScanResponseData && m_scanResp) { m_advData.set_scan_rsp = true; + m_advData.include_name = m_scanResp; + m_advData.include_txpower = m_scanResp; errRc = ::esp_ble_gap_config_adv_data(&m_advData); if (errRc != ESP_OK) { ESP_LOGE(LOG_TAG, "<< esp_ble_gap_config_adv_data (Scan response): rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); @@ -456,5 +472,34 @@ std::string BLEAdvertisementData::getPayload() { return m_payload; } // getPayload +void BLEAdvertising::handleGAPEvent( + esp_gap_ble_cb_event_t event, + esp_ble_gap_cb_param_t* param) { + + ESP_LOGD(LOG_TAG, "handleGAPEvent [event no: %d]", (int)event); + + switch(event) { + case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT: { + // m_semaphoreSetAdv.give(); + break; + } + case ESP_GAP_BLE_SCAN_RSP_DATA_SET_COMPLETE_EVT: { + // m_semaphoreSetAdv.give(); + break; + } + case ESP_GAP_BLE_ADV_START_COMPLETE_EVT: { + // m_semaphoreSetAdv.give(); + break; + } + case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT: { + ESP_LOGI(LOG_TAG, "STOP advertising"); + start(); + break; + } + default: + break; + } +} + #endif /* CONFIG_BT_ENABLED */ diff --git a/cpp_utils/BLEAdvertising.h b/cpp_utils/BLEAdvertising.h index f7cfc240..3128b50f 100644 --- a/cpp_utils/BLEAdvertising.h +++ b/cpp_utils/BLEAdvertising.h @@ -12,6 +12,7 @@ #include #include "BLEUUID.h" #include +#include "FreeRTOS.h" /** * @brief Advertisement data set by the programmer to be published by the %BLE server. @@ -19,6 +20,7 @@ class BLEAdvertisementData { // 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(BLEUUID uuid); @@ -55,13 +57,22 @@ class BLEAdvertising { void setAdvertisementData(BLEAdvertisementData& advertisementData); void setScanFilter(bool scanRequertWhitelistOnly, bool connectWhitelistOnly); void setScanResponseData(BLEAdvertisementData& advertisementData); + void setPrivateAddress(esp_ble_addr_type_t type = BLE_ADDR_TYPE_RANDOM); + + void handleGAPEvent(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t* param); + void setMinPreferred(uint16_t); + void setMaxPreferred(uint16_t); + void setScanResponse(bool); private: esp_ble_adv_data_t m_advData; esp_ble_adv_params_t m_advParams; std::vector m_serviceUUIDs; - bool m_customAdvData; // Are we using custom advertising data? - bool m_customScanResponseData; // Are we using custom scan response data? + bool m_customAdvData = false; // Are we using custom advertising data? + bool m_customScanResponseData = false; // Are we using custom scan response data? + FreeRTOS::Semaphore m_semaphoreSetAdv = FreeRTOS::Semaphore("startAdvert"); + bool m_scanResp = true; + }; #endif /* CONFIG_BT_ENABLED */ -#endif /* COMPONENTS_CPP_UTILS_BLEADVERTISING_H_ */ +#endif /* COMPONENTS_CPP_UTILS_BLEADVERTISING_H_ */ \ No newline at end of file diff --git a/cpp_utils/BLEBeacon.cpp b/cpp_utils/BLEBeacon.cpp index 854b661d..68f8d8ed 100644 --- a/cpp_utils/BLEBeacon.cpp +++ b/cpp_utils/BLEBeacon.cpp @@ -7,12 +7,17 @@ #include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) #include -#include #include "BLEBeacon.h" +#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) +#include "esp32-hal-log.h" +#define LOG_TAG "" +#else +#include "esp_log.h" +static const char* LOG_TAG = "BLEBeacon"; +#endif #define ENDIAN_CHANGE_U16(x) ((((x)&0xFF00)>>8) + (((x)&0xFF)<<8)) -static const char LOG_TAG[] = "BLEBeacon"; BLEBeacon::BLEBeacon() { m_beaconData.manufacturerId = 0x4c00; diff --git a/cpp_utils/BLECharacteristic.cpp b/cpp_utils/BLECharacteristic.cpp index 6f696c7c..2868ee26 100644 --- a/cpp_utils/BLECharacteristic.cpp +++ b/cpp_utils/BLECharacteristic.cpp @@ -11,7 +11,6 @@ #include #include #include "sdkconfig.h" -#include #include #include "BLECharacteristic.h" #include "BLEService.h" @@ -19,11 +18,13 @@ #include "BLEUtils.h" #include "BLE2902.h" #include "GeneralUtils.h" -#ifdef ARDUINO_ARCH_ESP32 +#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) #include "esp32-hal-log.h" -#endif - +#define LOG_TAG "" +#else +#include "esp_log.h" static const char* LOG_TAG = "BLECharacteristic"; +#endif #define NULL_HANDLE (0xffff) @@ -44,7 +45,7 @@ BLECharacteristic::BLECharacteristic(const char* uuid, uint32_t properties) : BL BLECharacteristic::BLECharacteristic(BLEUUID uuid, uint32_t properties) { m_bleUUID = uuid; m_handle = NULL_HANDLE; - m_properties = (esp_gatt_char_prop_t) 0; + m_properties = (esp_gatt_char_prop_t)0; m_pCallbacks = nullptr; setBroadcastProperty((properties & PROPERTY_BROADCAST) != 0); @@ -87,7 +88,7 @@ void BLECharacteristic::executeCreate(BLEService* pService) { return; } - m_pService = pService; // Save the service for to which this characteristic belongs. + m_pService = pService; // Save the service to which this characteristic belongs. ESP_LOGD(LOG_TAG, "Registering characteristic (esp_ble_gatts_add_char): uuid: %s, service: %s", getUUID().toString().c_str(), @@ -97,20 +98,11 @@ void BLECharacteristic::executeCreate(BLEService* pService) { control.auto_rsp = ESP_GATT_RSP_BY_APP; m_semaphoreCreateEvt.take("executeCreate"); - - /* - esp_attr_value_t value; - value.attr_len = m_value.getLength(); - value.attr_max_len = ESP_GATT_MAX_ATTR_LEN; - value.attr_value = m_value.getData(); - */ - esp_err_t errRc = ::esp_ble_gatts_add_char( m_pService->getHandle(), getUUID().getNative(), static_cast(m_permissions), getProperties(), - //&value, nullptr, &control); // Whether to auto respond or not. @@ -118,15 +110,9 @@ void BLECharacteristic::executeCreate(BLEService* pService) { ESP_LOGE(LOG_TAG, "<< esp_ble_gatts_add_char: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); return; } - m_semaphoreCreateEvt.wait("executeCreate"); - // Now that we have registered the characteristic, we must also register all the descriptors associated with this - // characteristic. We iterate through each of those and invoke the registration call to register them with the - // ESP environment. - BLEDescriptor* pDescriptor = m_descriptorMap.getFirst(); - while (pDescriptor != nullptr) { pDescriptor->executeCreate(this); pDescriptor = m_descriptorMap.getNext(); @@ -216,7 +202,7 @@ void BLECharacteristic::handleGATTServerEvent( esp_ble_gatts_cb_param_t* param) { ESP_LOGD(LOG_TAG, ">> handleGATTServerEvent: %s", BLEUtils::gattServerEventTypeToString(event).c_str()); - switch (event) { + switch(event) { // Events handled: // // ESP_GATTS_ADD_CHAR_EVT @@ -238,21 +224,24 @@ void BLECharacteristic::handleGATTServerEvent( // - uint8_t exec_write_flag - Either ESP_GATT_PREP_WRITE_EXEC or ESP_GATT_PREP_WRITE_CANCEL // case ESP_GATTS_EXEC_WRITE_EVT: { - if (param->exec_write.exec_write_flag == ESP_GATT_PREP_WRITE_EXEC) { - m_value.commit(); - if (m_pCallbacks != nullptr) { - m_pCallbacks->onWrite(this); // Invoke the onWrite callback handler. + if(m_writeEvt){ + m_writeEvt = false; + if (param->exec_write.exec_write_flag == ESP_GATT_PREP_WRITE_EXEC) { + m_value.commit(); + if (m_pCallbacks != nullptr) { + m_pCallbacks->onWrite(this); // Invoke the onWrite callback handler. + } + } else { + m_value.cancel(); + } + // ??? + esp_err_t errRc = ::esp_ble_gatts_send_response( + gatts_if, + param->write.conn_id, + param->write.trans_id, ESP_GATT_OK, nullptr); + if (errRc != ESP_OK) { + ESP_LOGE(LOG_TAG, "esp_ble_gatts_send_response: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); } - } else { - m_value.cancel(); - } - - esp_err_t errRc = ::esp_ble_gatts_send_response( - gatts_if, - param->write.conn_id, - param->write.trans_id, ESP_GATT_OK, nullptr); - if (errRc != ESP_OK) { - ESP_LOGE(LOG_TAG, "esp_ble_gatts_send_response: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); } break; } // ESP_GATTS_EXEC_WRITE_EVT @@ -265,9 +254,13 @@ void BLECharacteristic::handleGATTServerEvent( // - uint16_t service_handle // - esp_bt_uuid_t char_uuid case ESP_GATTS_ADD_CHAR_EVT: { - if (getUUID().equals(BLEUUID(param->add_char.char_uuid)) && - getHandle() == param->add_char.attr_handle && - getService()->getHandle() == param->add_char.service_handle) { + if (getHandle() == param->add_char.attr_handle) { + // we have created characteristic, now we can create descriptors + // BLEDescriptor* pDescriptor = m_descriptorMap.getFirst(); + // while (pDescriptor != nullptr) { + // pDescriptor->executeCreate(this); + // pDescriptor = m_descriptorMap.getNext(); + // } // End while m_semaphoreCreateEvt.give(); } break; @@ -294,8 +287,12 @@ void BLECharacteristic::handleGATTServerEvent( if (param->write.handle == m_handle) { if (param->write.is_prep) { m_value.addPart(param->write.value, param->write.len); + m_writeEvt = true; } else { setValue(param->write.value, param->write.len); + if (m_pCallbacks != nullptr && param->write.is_prep != true) { + m_pCallbacks->onWrite(this); // Invoke the onWrite callback handler. + } } ESP_LOGD(LOG_TAG, " - Response to write event: New value: handle: %.2x, uuid: %s", @@ -323,9 +320,6 @@ void BLECharacteristic::handleGATTServerEvent( } } // Response needed - if (m_pCallbacks != nullptr && param->write.is_prep != true) { - m_pCallbacks->onWrite(this); // Invoke the onWrite callback handler. - } } // Match on handles. break; } // ESP_GATTS_WRITE_EVT @@ -357,7 +351,7 @@ void BLECharacteristic::handleGATTServerEvent( // // If the is_long flag is set then this is a follow on from an original read and we will already have sent at least 22 bytes. // If the is_long flag is not set then we need to check how much data we are going to send. If we are sending LESS than -// 22 bytes, then we "just" send it and that's the end of the story. +// 22 bytes, then we "just" send it and thats the end of the story. // If we are sending 22 bytes exactly, we just send it BUT we will get a follow on request. // If we are sending more than 22 bytes, we send the first 22 bytes and we will get a follow on request. // Because of follow on request processing, we need to maintain an offset of how much data we have already sent @@ -367,10 +361,11 @@ void BLECharacteristic::handleGATTServerEvent( // // The following code has deliberately not been factored to make it fewer statements because this would cloud the // the logic flow comprehension. +// - // TODO requires some more research to confirm that 512 is max PDU like in bluetooth specs - uint16_t maxOffset = BLEDevice::getMTU() - 1; - if (BLEDevice::getMTU() > 512) maxOffset = 512; + // get mtu for peer device that we are sending read request to + uint16_t maxOffset = getService()->getServer()->getPeerMTU(param->read.conn_id) - 1; + ESP_LOGD(LOG_TAG, "mtu value: %d", maxOffset); if (param->read.need_rsp) { ESP_LOGD(LOG_TAG, "Sending a response (esp_ble_gatts_send_response)"); esp_gatt_rsp_t rsp; @@ -396,7 +391,6 @@ void BLECharacteristic::handleGATTServerEvent( if (m_pCallbacks != nullptr) { // If is.long is false then this is the first (or only) request to read data, so invoke the callback m_pCallbacks->onRead(this); // Invoke the read callback. } - std::string value = m_value.getValue(); if (value.length() + 1 > maxOffset) { @@ -411,6 +405,10 @@ void BLECharacteristic::handleGATTServerEvent( rsp.attr_value.offset = 0; memcpy(rsp.attr_value.value, value.data(), rsp.attr_value.len); } + + // if (m_pCallbacks != nullptr) { // If is.long is false then this is the first (or only) request to read data, so invoke the callback + // m_pCallbacks->onRead(this); // Invoke the read callback. + // } } rsp.attr_value.handle = param->read.handle; rsp.attr_value.auth_req = ESP_GATT_AUTH_REQ_NONE; @@ -440,12 +438,13 @@ void BLECharacteristic::handleGATTServerEvent( // - uint16_t conn_id – The connection used. // case ESP_GATTS_CONF_EVT: { - m_semaphoreConfEvt.give(); + // ESP_LOGD(LOG_TAG, "m_handle = %d, conf->handle = %d", m_handle, param->conf.handle); + if(param->conf.conn_id == getService()->getServer()->getConnId()) // && param->conf.handle == m_handle) // bug in esp-idf and not implemented in arduino yet + m_semaphoreConfEvt.give(param->conf.status); break; } case ESP_GATTS_CONNECT_EVT: { - m_semaphoreConfEvt.give(); break; } @@ -475,46 +474,9 @@ void BLECharacteristic::handleGATTServerEvent( * @return N/A */ void BLECharacteristic::indicate() { - ESP_LOGD(LOG_TAG, ">> indicate: length: %d", m_value.getValue().length()); - - assert(getService() != nullptr); - assert(getService()->getServer() != nullptr); - - GeneralUtils::hexDump((uint8_t*)m_value.getValue().data(), m_value.getValue().length()); - if (getService()->getServer()->getConnectedCount() == 0) { - ESP_LOGD(LOG_TAG, "<< indicate: No connected clients."); - return; - } - - // Test to see if we have a 0x2902 descriptor. If we do, then check to see if indications are enabled - // and, if not, prevent the indication. - - BLE2902 *p2902 = (BLE2902*) getDescriptorByUUID((uint16_t) 0x2902); - if (p2902 != nullptr && !p2902->getIndications()) { - ESP_LOGD(LOG_TAG, "<< indications disabled; ignoring"); - return; - } - - if (m_value.getValue().length() > (BLEDevice::getMTU() - 3)) { - ESP_LOGI(LOG_TAG, "- Truncating to %d bytes (maximum indicate size)", BLEDevice::getMTU() - 3); - } - - size_t length = m_value.getValue().length(); - - m_semaphoreConfEvt.take("indicate"); - - esp_err_t errRc = ::esp_ble_gatts_send_indicate( - getService()->getServer()->getGattsIf(), - getService()->getServer()->getConnId(), - getHandle(), length, (uint8_t*)m_value.getValue().data(), true); // The need_confirm = true makes this an indication. - - if (errRc != ESP_OK) { - ESP_LOGE(LOG_TAG, "<< esp_ble_gatts_send_indicate: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); - return; - } - - m_semaphoreConfEvt.wait("indicate"); + ESP_LOGD(LOG_TAG, ">> indicate: length: %d", m_value.getValue().length()); + notify(false); ESP_LOGD(LOG_TAG, "<< indicate"); } // indicate @@ -525,7 +487,7 @@ void BLECharacteristic::indicate() { * will not block; it is a fire and forget. * @return N/A. */ -void BLECharacteristic::notify() { +void BLECharacteristic::notify(bool is_notification) { ESP_LOGD(LOG_TAG, ">> notify: length: %d", m_value.getValue().length()); assert(getService() != nullptr); @@ -541,31 +503,44 @@ void BLECharacteristic::notify() { // Test to see if we have a 0x2902 descriptor. If we do, then check to see if notification is enabled // and, if not, prevent the notification. - BLE2902 *p2902 = (BLE2902*) getDescriptorByUUID((uint16_t) 0x2902); - if (p2902 != nullptr && !p2902->getNotifications()) { - ESP_LOGD(LOG_TAG, "<< notifications disabled; ignoring"); + BLE2902* p2902 = (BLE2902*)getDescriptorByUUID((uint16_t)0x2902); + if(p2902 == nullptr){ + ESP_LOGE(LOG_TAG, "Characteristic without 0x2902 descriptor"); return; } - - if (m_value.getValue().length() > (BLEDevice::getMTU() - 3)) { - ESP_LOGI(LOG_TAG, "- Truncating to %d bytes (maximum notify size)", BLEDevice::getMTU() - 3); + if(is_notification) { + if (p2902 != nullptr && !p2902->getNotifications()) { + ESP_LOGD(LOG_TAG, "<< notifications disabled; ignoring"); + return; + } } - - size_t length = m_value.getValue().length(); - - m_semaphoreConfEvt.take("notify"); - - esp_err_t errRc = ::esp_ble_gatts_send_indicate( - getService()->getServer()->getGattsIf(), - getService()->getServer()->getConnId(), - getHandle(), length, (uint8_t*)m_value.getValue().data(), false); // The need_confirm = false makes this a notify. - if (errRc != ESP_OK) { - ESP_LOGE(LOG_TAG, "<< esp_ble_gatts_send_indicate: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); - return; + else{ + if (p2902 != nullptr && !p2902->getIndications()) { + ESP_LOGD(LOG_TAG, "<< indications disabled; ignoring"); + return; + } } + for (auto &myPair : getService()->getServer()->getPeerDevices(false)) { + uint16_t _mtu = (myPair.second.mtu); + if (m_value.getValue().length() > _mtu - 3) { + ESP_LOGW(LOG_TAG, "- Truncating to %d bytes (maximum notify size)", _mtu - 3); + } - m_semaphoreConfEvt.wait("notify"); - + size_t length = m_value.getValue().length(); + if(!is_notification) + m_semaphoreConfEvt.take("indicate"); + esp_err_t errRc = ::esp_ble_gatts_send_indicate( + getService()->getServer()->getGattsIf(), + myPair.first, + getHandle(), length, (uint8_t*)m_value.getValue().data(), !is_notification); // The need_confirm = false makes this a notify. + if (errRc != ESP_OK) { + ESP_LOGE(LOG_TAG, "<< esp_ble_gatts_send_ %s: rc=%d %s",is_notification?"notify":"indicate", errRc, GeneralUtils::errorToString(errRc)); + m_semaphoreConfEvt.give(); + return; + } + if(!is_notification) + m_semaphoreConfEvt.wait("indicate"); + } ESP_LOGD(LOG_TAG, "<< notify"); } // Notify @@ -580,9 +555,9 @@ void BLECharacteristic::notify() { void BLECharacteristic::setBroadcastProperty(bool value) { //ESP_LOGD(LOG_TAG, "setBroadcastProperty(%d)", value); if (value) { - m_properties = (esp_gatt_char_prop_t) (m_properties | ESP_GATT_CHAR_PROP_BIT_BROADCAST); + m_properties = (esp_gatt_char_prop_t)(m_properties | ESP_GATT_CHAR_PROP_BIT_BROADCAST); } else { - m_properties = (esp_gatt_char_prop_t) (m_properties & ~ESP_GATT_CHAR_PROP_BIT_BROADCAST); + m_properties = (esp_gatt_char_prop_t)(m_properties & ~ESP_GATT_CHAR_PROP_BIT_BROADCAST); } } // setBroadcastProperty @@ -592,7 +567,7 @@ void BLECharacteristic::setBroadcastProperty(bool value) { * @param [in] pCallbacks An instance of a callbacks structure used to define any callbacks for the characteristic. */ void BLECharacteristic::setCallbacks(BLECharacteristicCallbacks* pCallbacks) { - ESP_LOGD(LOG_TAG, ">> setCallbacks: 0x%x", (uint32_t) pCallbacks); + ESP_LOGD(LOG_TAG, ">> setCallbacks: 0x%x", (uint32_t)pCallbacks); m_pCallbacks = pCallbacks; ESP_LOGD(LOG_TAG, "<< setCallbacks"); } // setCallbacks @@ -622,9 +597,9 @@ void BLECharacteristic::setHandle(uint16_t handle) { void BLECharacteristic::setIndicateProperty(bool value) { //ESP_LOGD(LOG_TAG, "setIndicateProperty(%d)", value); if (value) { - m_properties = (esp_gatt_char_prop_t) (m_properties | ESP_GATT_CHAR_PROP_BIT_INDICATE); + m_properties = (esp_gatt_char_prop_t)(m_properties | ESP_GATT_CHAR_PROP_BIT_INDICATE); } else { - m_properties = (esp_gatt_char_prop_t) (m_properties & ~ESP_GATT_CHAR_PROP_BIT_INDICATE); + m_properties = (esp_gatt_char_prop_t)(m_properties & ~ESP_GATT_CHAR_PROP_BIT_INDICATE); } } // setIndicateProperty @@ -636,9 +611,9 @@ void BLECharacteristic::setIndicateProperty(bool value) { void BLECharacteristic::setNotifyProperty(bool value) { //ESP_LOGD(LOG_TAG, "setNotifyProperty(%d)", value); if (value) { - m_properties = (esp_gatt_char_prop_t) (m_properties | ESP_GATT_CHAR_PROP_BIT_NOTIFY); + m_properties = (esp_gatt_char_prop_t)(m_properties | ESP_GATT_CHAR_PROP_BIT_NOTIFY); } else { - m_properties = (esp_gatt_char_prop_t) (m_properties & ~ESP_GATT_CHAR_PROP_BIT_NOTIFY); + m_properties = (esp_gatt_char_prop_t)(m_properties & ~ESP_GATT_CHAR_PROP_BIT_NOTIFY); } } // setNotifyProperty @@ -650,9 +625,9 @@ void BLECharacteristic::setNotifyProperty(bool value) { void BLECharacteristic::setReadProperty(bool value) { //ESP_LOGD(LOG_TAG, "setReadProperty(%d)", value); if (value) { - m_properties = (esp_gatt_char_prop_t) (m_properties | ESP_GATT_CHAR_PROP_BIT_READ); + m_properties = (esp_gatt_char_prop_t)(m_properties | ESP_GATT_CHAR_PROP_BIT_READ); } else { - m_properties = (esp_gatt_char_prop_t) (m_properties & ~ESP_GATT_CHAR_PROP_BIT_READ); + m_properties = (esp_gatt_char_prop_t)(m_properties & ~ESP_GATT_CHAR_PROP_BIT_READ); } } // setReadProperty @@ -683,7 +658,7 @@ void BLECharacteristic::setValue(uint8_t* data, size_t length) { * @return N/A. */ void BLECharacteristic::setValue(std::string value) { - setValue((uint8_t*) (value.data()), value.length()); + setValue((uint8_t*)(value.data()), value.length()); } // setValue void BLECharacteristic::setValue(uint16_t& data16) { @@ -713,13 +688,13 @@ void BLECharacteristic::setValue(int& data32) { void BLECharacteristic::setValue(float& data32) { uint8_t temp[4]; - *((float*) temp) = data32; + *((float*)temp) = data32; setValue(temp, 4); } // setValue void BLECharacteristic::setValue(double& data64) { uint8_t temp[8]; - *((double*) temp) = data64; + *((double*)temp) = data64; setValue(temp, 8); } // setValue @@ -731,9 +706,9 @@ void BLECharacteristic::setValue(double& data64) { void BLECharacteristic::setWriteNoResponseProperty(bool value) { //ESP_LOGD(LOG_TAG, "setWriteNoResponseProperty(%d)", value); if (value) { - m_properties = (esp_gatt_char_prop_t) (m_properties | ESP_GATT_CHAR_PROP_BIT_WRITE_NR); + m_properties = (esp_gatt_char_prop_t)(m_properties | ESP_GATT_CHAR_PROP_BIT_WRITE_NR); } else { - m_properties = (esp_gatt_char_prop_t) (m_properties & ~ESP_GATT_CHAR_PROP_BIT_WRITE_NR); + m_properties = (esp_gatt_char_prop_t)(m_properties & ~ESP_GATT_CHAR_PROP_BIT_WRITE_NR); } } // setWriteNoResponseProperty @@ -745,9 +720,9 @@ void BLECharacteristic::setWriteNoResponseProperty(bool value) { void BLECharacteristic::setWriteProperty(bool value) { //ESP_LOGD(LOG_TAG, "setWriteProperty(%d)", value); if (value) { - m_properties = (esp_gatt_char_prop_t) (m_properties | ESP_GATT_CHAR_PROP_BIT_WRITE); + m_properties = (esp_gatt_char_prop_t)(m_properties | ESP_GATT_CHAR_PROP_BIT_WRITE); } else { - m_properties = (esp_gatt_char_prop_t) (m_properties & ~ESP_GATT_CHAR_PROP_BIT_WRITE); + m_properties = (esp_gatt_char_prop_t)(m_properties & ~ESP_GATT_CHAR_PROP_BIT_WRITE); } } // setWriteProperty diff --git a/cpp_utils/BLECharacteristic.h b/cpp_utils/BLECharacteristic.h index bad5ba7a..82a8d7d0 100644 --- a/cpp_utils/BLECharacteristic.h +++ b/cpp_utils/BLECharacteristic.h @@ -27,30 +27,27 @@ class BLECharacteristicCallbacks; */ class BLEDescriptorMap { public: - void setByUUID(const char* uuid, BLEDescriptor* pDescriptor); - void setByUUID(BLEUUID uuid, BLEDescriptor* pDescriptor); + void setByUUID(const char* uuid, BLEDescriptor* pDescriptor); + void setByUUID(BLEUUID uuid, BLEDescriptor* pDescriptor); void setByHandle(uint16_t handle, BLEDescriptor* pDescriptor); BLEDescriptor* getByUUID(const char* uuid); BLEDescriptor* getByUUID(BLEUUID uuid); BLEDescriptor* getByHandle(uint16_t handle); std::string toString(); - void handleGATTServerEvent( - esp_gatts_cb_event_t event, - esp_gatt_if_t gatts_if, - esp_ble_gatts_cb_param_t* param); + void handleGATTServerEvent(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t* param); BLEDescriptor* getFirst(); BLEDescriptor* getNext(); 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; }; /** * @brief The model of a %BLE Characteristic. * - * A %BLE Characteristic is an identified value container that manages a value. It is exposed by a %BLE server and + * A BLE Characteristic is an identified value container that manages a value. It is exposed by a BLE server and * can be read and written to by a %BLE client. */ class BLECharacteristic { @@ -59,16 +56,15 @@ class BLECharacteristic { BLECharacteristic(BLEUUID uuid, uint32_t properties = 0); virtual ~BLECharacteristic(); - void addDescriptor(BLEDescriptor* pDescriptor); + void addDescriptor(BLEDescriptor* pDescriptor); BLEDescriptor* getDescriptorByUUID(const char* descriptorUUID); BLEDescriptor* getDescriptorByUUID(BLEUUID descriptorUUID); - //size_t getLength(); - BLEUUID getUUID(); - std::string getValue(); - uint8_t* getData(); + BLEUUID getUUID(); + std::string getValue(); + uint8_t* getData(); void indicate(); - void notify(); + void notify(bool is_notification = true); void setBroadcastProperty(bool value); void setCallbacks(BLECharacteristicCallbacks* pCallbacks); void setIndicateProperty(bool value); @@ -80,19 +76,19 @@ class BLECharacteristic { void setValue(uint32_t& data32); void setValue(int& data32); void setValue(float& data32); - void setValue(double& data64); + void setValue(double& data64); void setWriteProperty(bool value); void setWriteNoResponseProperty(bool value); std::string toString(); uint16_t getHandle(); void setAccessPermissions(esp_gatt_perm_t perm); - 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: @@ -101,24 +97,25 @@ class BLECharacteristic { friend class BLEDescriptor; friend class BLECharacteristicMap; - BLEUUID m_bleUUID; - BLEDescriptorMap m_descriptorMap; - uint16_t m_handle; - esp_gatt_char_prop_t m_properties; + BLEUUID m_bleUUID; + BLEDescriptorMap m_descriptorMap; + uint16_t m_handle; + esp_gatt_char_prop_t m_properties; BLECharacteristicCallbacks* m_pCallbacks; - BLEService* m_pService; - BLEValue m_value; - esp_gatt_perm_t m_permissions = ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE; + BLEService* m_pService; + BLEValue m_value; + esp_gatt_perm_t m_permissions = ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE; + bool m_writeEvt = false; void handleGATTServerEvent( - esp_gatts_cb_event_t event, - esp_gatt_if_t gatts_if, + esp_gatts_cb_event_t event, + esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t* param); - void executeCreate(BLEService* pService); + void executeCreate(BLEService* pService); esp_gatt_char_prop_t getProperties(); - BLEService* getService(); - void setHandle(uint16_t handle); + BLEService* getService(); + void setHandle(uint16_t handle); FreeRTOS::Semaphore m_semaphoreCreateEvt = FreeRTOS::Semaphore("CreateEvt"); FreeRTOS::Semaphore m_semaphoreConfEvt = FreeRTOS::Semaphore("ConfEvt"); }; // BLECharacteristic diff --git a/cpp_utils/BLEClient.cpp b/cpp_utils/BLEClient.cpp index 2a8d6f0c..d6e75988 100644 --- a/cpp_utils/BLEClient.cpp +++ b/cpp_utils/BLEClient.cpp @@ -6,7 +6,6 @@ */ #include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) -#include #include #include #include @@ -18,10 +17,16 @@ #include #include #include -#ifdef ARDUINO_ARCH_ESP32 +#include "BLEDevice.h" +#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) #include "esp32-hal-log.h" +#define LOG_TAG "" +#else +#include "esp_log.h" +static const char* LOG_TAG = "BLEClient"; #endif + /* * Design * ------ @@ -40,15 +45,30 @@ * We will assume that a BLERemoteService contains a map that maps BLEUUIDs to the set of owned characteristics * and that a BLECharacteristic contains a map that maps BLEUUIDs to the set of owned descriptors. * + * */ -static const char* LOG_TAG = "BLEClient"; BLEClient::BLEClient() { m_pClientCallbacks = nullptr; - m_conn_id = 0; - m_gattc_if = 0; + m_conn_id = ESP_GATT_IF_NONE; + m_gattc_if = ESP_GATT_IF_NONE; m_haveServices = false; m_isConnected = false; // Initially, we are flagged as not connected. + + + m_appId = BLEDevice::m_appId++; + m_appId = m_appId%100; + BLEDevice::addPeerDevice(this, true, m_appId); + m_semaphoreRegEvt.take("connect"); + + esp_err_t errRc = ::esp_ble_gattc_app_register(m_appId); + if (errRc != ESP_OK) { + ESP_LOGE(LOG_TAG, "esp_ble_gattc_app_register: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); + return; + } + + m_semaphoreRegEvt.wait("connect"); + } // BLEClient @@ -58,10 +78,12 @@ BLEClient::BLEClient() { BLEClient::~BLEClient() { // We may have allocated service references associated with this client. Before we are finished // with the client, we must release resources. - for (auto &myPair : m_servicesMap) { - delete myPair.second; - } - m_servicesMap.clear(); + clearServices(); + esp_ble_gattc_app_unregister(m_gattc_if); + BLEDevice::removePeerDevice(m_appId, true); + if(m_deleteCallbacks) + delete m_pClientCallbacks; + } // ~BLEClient @@ -76,42 +98,38 @@ void BLEClient::clearServices() { delete myPair.second; } m_servicesMap.clear(); + m_servicesMapByInstID.clear(); m_haveServices = false; ESP_LOGD(LOG_TAG, "<< clearServices"); } // clearServices +/** + * Add overloaded function to ease connect to peer device with not public address + */ +bool BLEClient::connect(BLEAdvertisedDevice* device) { + BLEAddress address = device->getAddress(); + esp_ble_addr_type_t type = device->getAddressType(); + return connect(address, type); +} /** * @brief Connect to the partner (BLE Server). * @param [in] address The address of the partner. * @return True on success. */ -bool BLEClient::connect(BLEAddress address) { +bool BLEClient::connect(BLEAddress address, esp_ble_addr_type_t type) { ESP_LOGD(LOG_TAG, ">> connect(%s)", address.toString().c_str()); -// We need the connection handle that we get from registering the application. We register the app -// and then block on its completion. When the event has arrived, we will have the handle. - m_semaphoreRegEvt.take("connect"); - - clearServices(); // Delete any services that may exist. - - esp_err_t errRc = ::esp_ble_gattc_app_register(0); - if (errRc != ESP_OK) { - ESP_LOGE(LOG_TAG, "esp_ble_gattc_app_register: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); - return false; - } - - m_semaphoreRegEvt.wait("connect"); - + clearServices(); m_peerAddress = address; // Perform the open connection request against the target BLE Server. m_semaphoreOpenEvt.take("connect"); - errRc = ::esp_ble_gattc_open( - getGattcIf(), + esp_err_t errRc = ::esp_ble_gattc_open( + m_gattc_if, *getPeerAddress().getNative(), // address - BLE_ADDR_TYPE_PUBLIC, // Note: This was added on 2018-04-03 when the latest ESP-IDF was detected to have changed the signature. - 1 // direct connection + type, // Note: This was added on 2018-04-03 when the latest ESP-IDF was detected to have changed the signature. + 1 // direct connection <-- maybe needs to be changed in case of direct indirect connection??? ); if (errRc != ESP_OK) { ESP_LOGE(LOG_TAG, "esp_ble_gattc_open: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); @@ -130,13 +148,12 @@ bool BLEClient::connect(BLEAddress address) { */ void BLEClient::disconnect() { ESP_LOGD(LOG_TAG, ">> disconnect()"); + // ESP_LOGW(__func__, "gattIf: %d, connId: %d", getGattcIf(), getConnId()); esp_err_t errRc = ::esp_ble_gattc_close(getGattcIf(), getConnId()); if (errRc != ESP_OK) { ESP_LOGE(LOG_TAG, "esp_ble_gattc_close: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); return; } - esp_ble_gattc_app_unregister(getGattcIf()); - m_peerAddress = BLEAddress("00:00:00:00:00:00"); ESP_LOGD(LOG_TAG, "<< disconnect()"); } // disconnect @@ -149,8 +166,21 @@ void BLEClient::gattClientEventHandler( esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t* evtParam) { + ESP_LOGD(LOG_TAG, "gattClientEventHandler [esp_gatt_if: %d] ... %s", + gattc_if, BLEUtils::gattClientEventTypeToString(event).c_str()); + // Execute handler code based on the type of event received. - switch (event) { + switch(event) { + + case ESP_GATTC_SRVC_CHG_EVT: + if(m_gattc_if != gattc_if) + break; + + ESP_LOGI(LOG_TAG, "SERVICE CHANGED"); + break; + + case ESP_GATTC_CLOSE_EVT: + break; // // ESP_GATTC_DISCONNECT_EVT @@ -160,15 +190,20 @@ void BLEClient::gattClientEventHandler( // - uint16_t conn_id // - esp_bd_addr_t remote_bda case ESP_GATTC_DISCONNECT_EVT: { - // If we receive a disconnect event, set the class flag that indicates that we are - // no longer connected. - if (m_pClientCallbacks != nullptr) { - m_pClientCallbacks->onDisconnect(this); - } - m_isConnected = false; - m_semaphoreRssiCmplEvt.give(); - m_semaphoreSearchCmplEvt.give(1); + ESP_LOGE(__func__, "disconnect event, reason: %d, connId: %d, my connId: %d, my IF: %d, gattc_if: %d", (int)evtParam->disconnect.reason, evtParam->disconnect.conn_id, getConnId(), getGattcIf(), gattc_if); + if(m_gattc_if != gattc_if) break; + m_semaphoreOpenEvt.give(evtParam->disconnect.reason); + if(!m_isConnected) + break; + // If we receive a disconnect event, set the class flag that indicates that we are + // no longer connected. + esp_ble_gattc_close(m_gattc_if, m_conn_id); + m_isConnected = false; + if (m_pClientCallbacks != nullptr) { + m_pClientCallbacks->onDisconnect(this); + } + break; } // ESP_GATTC_DISCONNECT_EVT // @@ -178,15 +213,17 @@ void BLEClient::gattClientEventHandler( // - esp_gatt_status_t status // - uint16_t conn_id // - esp_bd_addr_t remote_bda - // - uint16_t mtu // case ESP_GATTC_OPEN_EVT: { + if(m_gattc_if != gattc_if) + break; m_conn_id = evtParam->open.conn_id; if (m_pClientCallbacks != nullptr) { m_pClientCallbacks->onConnect(this); } if (evtParam->open.status == ESP_GATT_OK) { m_isConnected = true; // Flag us as connected. + m_mtu = evtParam->open.mtu; } m_semaphoreOpenEvt.give(evtParam->open.status); break; @@ -201,11 +238,38 @@ void BLEClient::gattClientEventHandler( // uint16_t app_id // case ESP_GATTC_REG_EVT: { - m_gattc_if = gattc_if; - m_semaphoreRegEvt.give(); + if(m_appId == evtParam->reg.app_id){ + ESP_LOGI(__func__, "register app id: %d, %d, gattc_if: %d", m_appId, evtParam->reg.app_id, gattc_if); + m_gattc_if = gattc_if; + m_semaphoreRegEvt.give(); + } break; } // ESP_GATTC_REG_EVT + case ESP_GATTC_CFG_MTU_EVT: + if(evtParam->cfg_mtu.status != ESP_GATT_OK) { + ESP_LOGE(LOG_TAG,"Config mtu failed"); + } + else + m_mtu = evtParam->cfg_mtu.mtu; + break; + + case ESP_GATTC_CONNECT_EVT: { + if(m_gattc_if != gattc_if) + break; + m_conn_id = evtParam->connect.conn_id; + BLEDevice::updatePeerDevice(this, true, m_gattc_if); + esp_err_t errRc = esp_ble_gattc_send_mtu_req(gattc_if, evtParam->connect.conn_id); + if (errRc != ESP_OK) { + ESP_LOGE(LOG_TAG, "esp_ble_gattc_send_mtu_req: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); + } +#ifdef CONFIG_BLE_SMP_ENABLE // Check that BLE SMP (security) is configured in make menuconfig + if(BLEDevice::m_securityLevel){ + esp_ble_set_encryption(evtParam->connect.remote_bda, BLEDevice::m_securityLevel); + } +#endif // CONFIG_BLE_SMP_ENABLE + break; + } // ESP_GATTC_CONNECT_EVT // // ESP_GATTC_SEARCH_CMPL_EVT @@ -215,7 +279,22 @@ void BLEClient::gattClientEventHandler( // - uint16_t conn_id // case ESP_GATTC_SEARCH_CMPL_EVT: { - m_semaphoreSearchCmplEvt.give(0); + if(m_gattc_if != gattc_if) + break; + if (evtParam->search_cmpl.status != ESP_GATT_OK){ + ESP_LOGE(LOG_TAG, "search service failed, error status = %x", evtParam->search_cmpl.status); + } +#ifndef ARDUINO_ARCH_ESP32 +// commented out just for now to keep backward compatibility + // if(p_data->search_cmpl.searched_service_source == ESP_GATT_SERVICE_FROM_REMOTE_DEVICE) { + // ESP_LOGI(LOG_TAG, "Get service information from remote device"); + // } else if (p_data->search_cmpl.searched_service_source == ESP_GATT_SERVICE_FROM_NVS_FLASH) { + // ESP_LOGI(LOG_TAG, "Get service information from flash"); + // } else { + // ESP_LOGI(LOG_TAG, "unknown service source"); + // } +#endif + m_semaphoreSearchCmplEvt.give(evtParam->search_cmpl.status); break; } // ESP_GATTC_SEARCH_CMPL_EVT @@ -230,6 +309,9 @@ void BLEClient::gattClientEventHandler( // - esp_gatt_id_t srvc_id // case ESP_GATTC_SEARCH_RES_EVT: { + if(m_gattc_if != gattc_if) + break; + BLEUUID uuid = BLEUUID(evtParam->search_res.srvc_id); BLERemoteService* pRemoteService = new BLERemoteService( evtParam->search_res.srvc_id, @@ -238,6 +320,7 @@ void BLEClient::gattClientEventHandler( evtParam->search_res.end_handle ); m_servicesMap.insert(std::pair(uuid.toString(), pRemoteService)); + m_servicesMapByInstID.insert(std::pair(pRemoteService, evtParam->search_res.srvc_id.inst_id)); break; } // ESP_GATTC_SEARCH_RES_EVT @@ -336,7 +419,7 @@ BLERemoteService* BLEClient::getService(BLEUUID uuid) { } } // End of each of the services. ESP_LOGD(LOG_TAG, "<< getService: not found"); - throw new BLEUuidNotFoundException; + return nullptr; } // getService @@ -355,20 +438,21 @@ std::map* BLEClient::getServices() { * and will culminate with an ESP_GATTC_SEARCH_CMPL_EVT when all have been received. */ ESP_LOGD(LOG_TAG, ">> getServices"); - +// TODO implement retrieving services from cache clearServices(); // Clear any services that may exist. esp_err_t errRc = esp_ble_gattc_search_service( getGattcIf(), getConnId(), - nullptr // Filter UUID + NULL // Filter UUID ); + m_semaphoreSearchCmplEvt.take("getServices"); if (errRc != ESP_OK) { ESP_LOGE(LOG_TAG, "esp_ble_gattc_search_service: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); return &m_servicesMap; } - // If successful, remember that we now have services. + // If sucessfull, remember that we now have services. m_haveServices = (m_semaphoreSearchCmplEvt.wait("getServices") == 0); ESP_LOGD(LOG_TAG, "<< getServices"); return &m_servicesMap; @@ -433,8 +517,9 @@ bool BLEClient::isConnected() { /** * @brief Set the callbacks that will be invoked. */ -void BLEClient::setClientCallbacks(BLEClientCallbacks* pClientCallbacks) { +void BLEClient::setClientCallbacks(BLEClientCallbacks* pClientCallbacks, bool deleteCallbacks) { m_pClientCallbacks = pClientCallbacks; + m_deleteCallbacks = deleteCallbacks; } // setClientCallbacks @@ -450,6 +535,9 @@ void BLEClient::setValue(BLEUUID serviceUUID, BLEUUID characteristicUUID, std::s ESP_LOGD(LOG_TAG, "<< setValue"); } // setValue +uint16_t BLEClient::getMTU() { + return m_mtu; +} /** * @brief Return a string representation of this client. diff --git a/cpp_utils/BLEClient.h b/cpp_utils/BLEClient.h index d66a8b4f..4b3c7eea 100644 --- a/cpp_utils/BLEClient.h +++ b/cpp_utils/BLEClient.h @@ -19,9 +19,11 @@ #include "BLERemoteService.h" #include "BLEService.h" #include "BLEAddress.h" +#include "BLEAdvertisedDevice.h" class BLERemoteService; class BLEClientCallbacks; +class BLEAdvertisedDevice; /** * @brief A model of a %BLE client. @@ -31,7 +33,8 @@ class BLEClient { BLEClient(); ~BLEClient(); - bool connect(BLEAddress address); // Connect to the remote BLE Server + bool connect(BLEAdvertisedDevice* device); + bool connect(BLEAddress address, esp_ble_addr_type_t type = BLE_ADDR_TYPE_PUBLIC); // Connect to the remote BLE Server void disconnect(); // Disconnect from the remote BLE Server BLEAddress getPeerAddress(); // Get the address of the remote BLE Server int getRssi(); // Get the RSSI of the remote BLE Server @@ -47,39 +50,39 @@ class BLEClient { bool isConnected(); // Return true if we are connected. + void setClientCallbacks(BLEClientCallbacks *pClientCallbacks, bool deleteCallbacks = true); void setValue(BLEUUID serviceUUID, BLEUUID characteristicUUID, std::string value); // Set the value of a given characteristic at a given service. - void setClientCallbacks(BLEClientCallbacks* pClientCallbacks); std::string toString(); // Return a string representation of this client. + uint16_t getConnId(); + esp_gatt_if_t getGattcIf(); + uint16_t getMTU(); - +uint16_t m_appId; private: friend class BLEDevice; friend class BLERemoteService; friend class BLERemoteCharacteristic; friend class BLERemoteDescriptor; - void gattClientEventHandler( - esp_gattc_cb_event_t event, - esp_gatt_if_t gattc_if, - esp_ble_gattc_cb_param_t* param); + void gattClientEventHandler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t* param); - uint16_t getConnId(); - esp_gatt_if_t getGattcIf(); + BLEAddress m_peerAddress = BLEAddress((uint8_t*)"\0\0\0\0\0\0"); // The BD address of the remote server. uint16_t m_conn_id; -// int m_deviceType; - BLEAddress m_peerAddress = BLEAddress((uint8_t*) "\0\0\0\0\0\0"); // The BD address of the remote server. esp_gatt_if_t m_gattc_if; - bool m_haveServices; // Have we previously obtain the set of services from the remote server. - bool m_isConnected; // Are we currently connected. + 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_deleteCallbacks = true; - BLEClientCallbacks* m_pClientCallbacks; + BLEClientCallbacks* m_pClientCallbacks = nullptr; FreeRTOS::Semaphore m_semaphoreRegEvt = FreeRTOS::Semaphore("RegEvt"); FreeRTOS::Semaphore m_semaphoreOpenEvt = FreeRTOS::Semaphore("OpenEvt"); FreeRTOS::Semaphore m_semaphoreSearchCmplEvt = FreeRTOS::Semaphore("SearchCmplEvt"); FreeRTOS::Semaphore m_semaphoreRssiCmplEvt = FreeRTOS::Semaphore("RssiCmplEvt"); std::map m_servicesMap; + std::map m_servicesMapByInstID; void clearServices(); // Clear any existing services. + uint16_t m_mtu = 23; }; // class BLEDevice diff --git a/cpp_utils/BLEDescriptor.cpp b/cpp_utils/BLEDescriptor.cpp index 5f23026f..ba5753de 100644 --- a/cpp_utils/BLEDescriptor.cpp +++ b/cpp_utils/BLEDescriptor.cpp @@ -11,16 +11,19 @@ #include #include #include "sdkconfig.h" -#include #include #include "BLEService.h" #include "BLEDescriptor.h" #include "GeneralUtils.h" -#ifdef ARDUINO_ARCH_ESP32 +#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) #include "esp32-hal-log.h" +#define LOG_TAG "" +#else +#include "esp_log.h" +static const char* LOG_TAG = "BLEDescriptor"; #endif -static const char* LOG_TAG = "BLEDescriptor"; + #define NULL_HANDLE (0xffff) @@ -29,21 +32,21 @@ static const char* LOG_TAG = "BLEDescriptor"; /** * @brief BLEDescriptor constructor. */ -BLEDescriptor::BLEDescriptor(const char* uuid) : BLEDescriptor(BLEUUID(uuid)) { +BLEDescriptor::BLEDescriptor(const char* uuid, uint16_t len) : BLEDescriptor(BLEUUID(uuid), len) { } /** * @brief BLEDescriptor constructor. */ -BLEDescriptor::BLEDescriptor(BLEUUID uuid) { +BLEDescriptor::BLEDescriptor(BLEUUID uuid, uint16_t max_len) { m_bleUUID = uuid; m_value.attr_len = 0; // Initial length is 0. - m_value.attr_max_len = ESP_GATT_MAX_ATTR_LEN; // Maximum length of the data. + m_value.attr_max_len = max_len; // Maximum length of the data. m_handle = NULL_HANDLE; // Handle is initially unknown. m_pCharacteristic = nullptr; // No initial characteristic. m_pCallback = nullptr; // No initial callback. - m_value.attr_value = (uint8_t*) malloc(ESP_GATT_MAX_ATTR_LEN); // Allocate storage for the value. + m_value.attr_value = (uint8_t*) malloc(max_len); // Allocate storage for the value. } // BLEDescriptor @@ -70,12 +73,12 @@ void BLEDescriptor::executeCreate(BLECharacteristic* pCharacteristic) { m_pCharacteristic = pCharacteristic; // Save the characteristic associated with this service. esp_attr_control_t control; - control.auto_rsp = ESP_GATT_RSP_BY_APP; + control.auto_rsp = ESP_GATT_AUTO_RSP; m_semaphoreCreateEvt.take("executeCreate"); esp_err_t errRc = ::esp_ble_gatts_add_char_descr( pCharacteristic->getService()->getHandle(), getUUID().getNative(), - (esp_gatt_perm_t)(ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE), + (esp_gatt_perm_t)m_permissions, &m_value, &control); if (errRc != ESP_OK) { @@ -143,17 +146,6 @@ void BLEDescriptor::handleGATTServerEvent( // - uint16_t service_handle // - esp_bt_uuid_t char_uuid case ESP_GATTS_ADD_CHAR_DESCR_EVT: { - /* - ESP_LOGD(LOG_TAG, "DEBUG: m_pCharacteristic: %x", (uint32_t)m_pCharacteristic); - ESP_LOGD(LOG_TAG, "DEBUG: m_bleUUID: %s, add_char_descr.char_uuid: %s, equals: %d", - m_bleUUID.toString().c_str(), - BLEUUID(param->add_char_descr.char_uuid).toString().c_str(), - m_bleUUID.equals(BLEUUID(param->add_char_descr.char_uuid))); - ESP_LOGD(LOG_TAG, "DEBUG: service->getHandle: %x, add_char_descr.service_handle: %x", - m_pCharacteristic->getService()->getHandle(), param->add_char_descr.service_handle); - ESP_LOGD(LOG_TAG, "DEBUG: service->lastCharacteristic: %x", - (uint32_t)m_pCharacteristic->getService()->getLastCreatedCharacteristic()); - */ if (m_pCharacteristic != nullptr && m_bleUUID.equals(BLEUUID(param->add_char_descr.descr_uuid)) && m_pCharacteristic->getService()->getHandle() == param->add_char_descr.service_handle && @@ -180,23 +172,6 @@ void BLEDescriptor::handleGATTServerEvent( if (param->write.handle == m_handle) { setValue(param->write.value, param->write.len); // Set the value of the descriptor. - esp_gatt_rsp_t rsp; // Build a response. - rsp.attr_value.len = getLength(); - rsp.attr_value.handle = m_handle; - rsp.attr_value.offset = 0; - rsp.attr_value.auth_req = ESP_GATT_AUTH_REQ_NONE; - memcpy(rsp.attr_value.value, getValue(), rsp.attr_value.len); - esp_err_t errRc = ::esp_ble_gatts_send_response( - gatts_if, - param->write.conn_id, - param->write.trans_id, - ESP_GATT_OK, - &rsp); - - if (errRc != ESP_OK) { // Check the return code from the send of the response. - ESP_LOGE(LOG_TAG, "esp_ble_gatts_send_response: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); - } - if (m_pCallback != nullptr) { // We have completed the write, if there is a user supplied callback handler, invoke it now. m_pCallback->onWrite(this); // Invoke the onWrite callback handler. } @@ -223,26 +198,6 @@ void BLEDescriptor::handleGATTServerEvent( m_pCallback->onRead(this); // Invoke the onRead callback method in the callback handler. } - if (param->read.need_rsp) { // Do we need a response - ESP_LOGD(LOG_TAG, "Sending a response (esp_ble_gatts_send_response)"); - esp_gatt_rsp_t rsp; - rsp.attr_value.len = getLength(); - rsp.attr_value.handle = param->read.handle; - rsp.attr_value.offset = 0; - rsp.attr_value.auth_req = ESP_GATT_AUTH_REQ_NONE; - memcpy(rsp.attr_value.value, getValue(), rsp.attr_value.len); - - esp_err_t errRc = ::esp_ble_gatts_send_response( - gatts_if, - param->read.conn_id, - param->read.trans_id, - ESP_GATT_OK, - &rsp); - - if (errRc != ESP_OK) { // Check the return code from the send of the response. - ESP_LOGE(LOG_TAG, "esp_ble_gatts_send_response: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); - } - } // End of need a response. } // End of this is our handle break; } // ESP_GATTS_READ_EVT diff --git a/cpp_utils/BLEDescriptor.h b/cpp_utils/BLEDescriptor.h index d9e0aefb..03cc5791 100644 --- a/cpp_utils/BLEDescriptor.h +++ b/cpp_utils/BLEDescriptor.h @@ -24,8 +24,8 @@ class BLEDescriptorCallbacks; */ class BLEDescriptor { public: - BLEDescriptor(const char* uuid); - BLEDescriptor(BLEUUID uuid); + BLEDescriptor(const char* uuid, uint16_t max_len = 100); + BLEDescriptor(BLEUUID uuid, uint16_t max_len = 100); virtual ~BLEDescriptor(); uint16_t getHandle(); // Get the handle of the descriptor. diff --git a/cpp_utils/BLEDescriptorMap.cpp b/cpp_utils/BLEDescriptorMap.cpp index 075b3025..6b845833 100644 --- a/cpp_utils/BLEDescriptorMap.cpp +++ b/cpp_utils/BLEDescriptorMap.cpp @@ -32,8 +32,8 @@ BLEDescriptor* BLEDescriptorMap::getByUUID(const char* uuid) { */ BLEDescriptor* BLEDescriptorMap::getByUUID(BLEUUID uuid) { for (auto &myPair : m_uuidMap) { - if (myPair.second->getUUID().equals(uuid)) { - return myPair.second; + if (myPair.first->getUUID().equals(uuid)) { + return myPair.first; } } //return m_uuidMap.at(uuid.toString()); @@ -58,7 +58,7 @@ BLEDescriptor* BLEDescriptorMap::getByHandle(uint16_t handle) { * @return N/A. */ void BLEDescriptorMap::setByUUID(const char* uuid, BLEDescriptor* pDescriptor){ - m_uuidMap.insert(std::pair(uuid, pDescriptor)); + m_uuidMap.insert(std::pair(pDescriptor, uuid)); } // setByUUID @@ -70,7 +70,7 @@ void BLEDescriptorMap::setByUUID(const char* uuid, BLEDescriptor* pDescriptor){ * @return N/A. */ void BLEDescriptorMap::setByUUID(BLEUUID uuid, BLEDescriptor* pDescriptor) { - m_uuidMap.insert(std::pair(uuid.toString(), pDescriptor)); + m_uuidMap.insert(std::pair(pDescriptor, uuid.toString())); } // setByUUID @@ -98,7 +98,7 @@ std::string BLEDescriptorMap::toString() { stringStream << "\n"; } count++; - stringStream << "handle: 0x" << std::setw(2) << myPair.second->getHandle() << ", uuid: " + myPair.second->getUUID().toString(); + stringStream << "handle: 0x" << std::setw(2) << myPair.first->getHandle() << ", uuid: " + myPair.first->getUUID().toString(); } return stringStream.str(); } // toString @@ -116,7 +116,7 @@ void BLEDescriptorMap::handleGATTServerEvent( esp_ble_gatts_cb_param_t* param) { // Invoke the handler for every descriptor we have. for (auto &myPair : m_uuidMap) { - myPair.second->handleGATTServerEvent(event, gatts_if, param); + myPair.first->handleGATTServerEvent(event, gatts_if, param); } } // handleGATTServerEvent @@ -128,7 +128,7 @@ void BLEDescriptorMap::handleGATTServerEvent( BLEDescriptor* BLEDescriptorMap::getFirst() { m_iterator = m_uuidMap.begin(); if (m_iterator == m_uuidMap.end()) return nullptr; - BLEDescriptor* pRet = m_iterator->second; + BLEDescriptor* pRet = m_iterator->first; m_iterator++; return pRet; } // getFirst @@ -140,7 +140,7 @@ BLEDescriptor* BLEDescriptorMap::getFirst() { */ BLEDescriptor* BLEDescriptorMap::getNext() { if (m_iterator == m_uuidMap.end()) return nullptr; - BLEDescriptor* pRet = m_iterator->second; + BLEDescriptor* pRet = m_iterator->first; m_iterator++; return pRet; } // getNext diff --git a/cpp_utils/BLEDevice.cpp b/cpp_utils/BLEDevice.cpp index fd86abe0..78bd13d3 100644 --- a/cpp_utils/BLEDevice.cpp +++ b/cpp_utils/BLEDevice.cpp @@ -19,7 +19,6 @@ #include // ESP32 BLE #include // ESP32 BLE #include // ESP32 ESP-IDF -#include // ESP32 ESP-IDF #include // Part of C++ Standard library #include // Part of C++ Standard library #include // Part of C++ Standard library @@ -28,24 +27,34 @@ #include "BLEClient.h" #include "BLEUtils.h" #include "GeneralUtils.h" -#ifdef ARDUINO_ARCH_ESP32 +#if defined(CONFIG_ARDUHAL_ESP_LOG) #include "esp32-hal-log.h" -#include "esp32-hal-bt.h" +#define LOG_TAG "" +#else +#include "esp_log.h" +static const char* LOG_TAG = "BLEDevice"; #endif -static const char* LOG_TAG = "BLEDevice"; +#if defined(ARDUINO_ARCH_ESP32) +#include "esp32-hal-bt.h" +#endif /** * Singletons for the BLEDevice. */ BLEServer* BLEDevice::m_pServer = nullptr; BLEScan* BLEDevice::m_pScan = nullptr; -BLEClient* BLEDevice::m_pClient = nullptr; -bool initialized = false; // Have we been initialized? -esp_ble_sec_act_t BLEDevice::m_securityLevel = (esp_ble_sec_act_t) 0; +// BLEClient* BLEDevice::m_pClient = nullptr; +bool initialized = false; +esp_ble_sec_act_t BLEDevice::m_securityLevel = (esp_ble_sec_act_t)0; BLESecurityCallbacks* BLEDevice::m_securityCallbacks = nullptr; -uint16_t BLEDevice::m_localMTU = 23; +uint16_t BLEDevice::m_localMTU = 23; // not sure if this variable is useful BLEAdvertising* BLEDevice::m_bleAdvertising = nullptr; +uint16_t BLEDevice::m_appId = 0; +std::map BLEDevice::m_connectedClientsMap; +gap_event_handler BLEDevice::m_customGapHandler = nullptr; +gattc_event_handler BLEDevice::m_customGattcHandler = nullptr; +gatts_event_handler BLEDevice::m_customGattsHandler = nullptr; /** * @brief Create a new instance of a client. @@ -57,7 +66,7 @@ BLEAdvertising* BLEDevice::m_bleAdvertising = nullptr; ESP_LOGE(LOG_TAG, "BLE GATTC is not enabled - CONFIG_GATTC_ENABLE not defined"); abort(); #endif // CONFIG_GATTC_ENABLE - m_pClient = new BLEClient(); + BLEClient* m_pClient = new BLEClient(); ESP_LOGD(LOG_TAG, "<< createClient"); return m_pClient; } // createClient @@ -73,8 +82,8 @@ BLEAdvertising* BLEDevice::m_bleAdvertising = nullptr; ESP_LOGE(LOG_TAG, "BLE GATTS is not enabled - CONFIG_GATTS_ENABLE not defined"); abort(); #endif // CONFIG_GATTS_ENABLE - m_pServer = new BLEServer(); - m_pServer->createApp(0); + BLEDevice::m_pServer = new BLEServer(); + m_pServer->createApp(m_appId++); ESP_LOGD(LOG_TAG, "<< createServer"); return m_pServer; } // createServer @@ -100,20 +109,14 @@ BLEAdvertising* BLEDevice::m_bleAdvertising = nullptr; switch (event) { case ESP_GATTS_CONNECT_EVT: { - BLEDevice::m_localMTU = 23; #ifdef CONFIG_BLE_SMP_ENABLE // Check that BLE SMP (security) is configured in make menuconfig - if (BLEDevice::m_securityLevel) { + if(BLEDevice::m_securityLevel){ esp_ble_set_encryption(param->connect.remote_bda, BLEDevice::m_securityLevel); } #endif // CONFIG_BLE_SMP_ENABLE break; } // ESP_GATTS_CONNECT_EVT - case ESP_GATTS_MTU_EVT: { - BLEDevice::m_localMTU = param->mtu.mtu; - ESP_LOGI(LOG_TAG, "ESP_GATTS_MTU_EVT, MTU %d", BLEDevice::m_localMTU); - break; - } default: { break; } @@ -123,6 +126,11 @@ BLEAdvertising* BLEDevice::m_bleAdvertising = nullptr; if (BLEDevice::m_pServer != nullptr) { BLEDevice::m_pServer->handleGATTServerEvent(event, gatts_if, param); } + + if(m_customGattsHandler != nullptr) { + m_customGattsHandler(event, gatts_if, param); + } + } // gattServerEventHandler @@ -146,30 +154,29 @@ BLEAdvertising* BLEDevice::m_bleAdvertising = nullptr; switch(event) { case ESP_GATTC_CONNECT_EVT: { - if (BLEDevice::getMTU() != 23) { - esp_err_t errRc = esp_ble_gattc_send_mtu_req(gattc_if, param->connect.conn_id); - if (errRc != ESP_OK) { - ESP_LOGE(LOG_TAG, "esp_ble_gattc_send_mtu_req: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); - } - } #ifdef CONFIG_BLE_SMP_ENABLE // Check that BLE SMP (security) is configured in make menuconfig - if (BLEDevice::m_securityLevel) { + if(BLEDevice::m_securityLevel){ esp_ble_set_encryption(param->connect.remote_bda, BLEDevice::m_securityLevel); } #endif // CONFIG_BLE_SMP_ENABLE break; - } // ESP_GATTC_CONNECT_EVT + } // ESP_GATTS_CONNECT_EVT default: break; } // switch + for(auto &myPair : BLEDevice::getPeerDevices(true)) { + conn_status_t conn_status = (conn_status_t)myPair.second; + if(((BLEClient*)conn_status.peer_device)->getGattcIf() == gattc_if || ((BLEClient*)conn_status.peer_device)->getGattcIf() == ESP_GATT_IF_NONE || gattc_if == ESP_GATT_IF_NONE){ + ((BLEClient*)conn_status.peer_device)->gattClientEventHandler(event, gattc_if, param); + } + } - - // If we have a client registered, call it. - if (BLEDevice::m_pClient != nullptr) { - BLEDevice::m_pClient->gattClientEventHandler(event, gattc_if, param); + if(m_customGattcHandler != nullptr) { + m_customGattcHandler(event, gattc_if, param); } + } // gattClientEventHandler @@ -178,33 +185,34 @@ BLEAdvertising* BLEDevice::m_bleAdvertising = nullptr; */ /* STATIC */ void BLEDevice::gapEventHandler( esp_gap_ble_cb_event_t event, - esp_ble_gap_cb_param_t* param) { + esp_ble_gap_cb_param_t *param) { BLEUtils::dumpGapEvent(event, param); - switch (event) { - case ESP_GAP_BLE_OOB_REQ_EVT: /* OOB request event */ - ESP_LOGI(LOG_TAG, "ESP_GAP_BLE_OOB_REQ_EVT"); - break; - case ESP_GAP_BLE_LOCAL_IR_EVT: /* BLE local IR event */ - ESP_LOGI(LOG_TAG, "ESP_GAP_BLE_LOCAL_IR_EVT"); - break; - case ESP_GAP_BLE_LOCAL_ER_EVT: /* BLE local ER event */ - ESP_LOGI(LOG_TAG, "ESP_GAP_BLE_LOCAL_ER_EVT"); - break; - case ESP_GAP_BLE_NC_REQ_EVT: - ESP_LOGI(LOG_TAG, "ESP_GAP_BLE_NC_REQ_EVT"); -#ifdef CONFIG_BLE_SMP_ENABLE // Check that BLE SMP (security) is configured in make menuconfig - if (BLEDevice::m_securityCallbacks != nullptr) { - esp_ble_confirm_reply(param->ble_security.ble_req.bd_addr, BLEDevice::m_securityCallbacks->onConfirmPIN(param->ble_security.key_notif.passkey)); + switch(event) { + + case ESP_GAP_BLE_OOB_REQ_EVT: /* OOB request event */ + ESP_LOGI(LOG_TAG, "ESP_GAP_BLE_OOB_REQ_EVT"); + break; + case ESP_GAP_BLE_LOCAL_IR_EVT: /* BLE local IR event */ + ESP_LOGI(LOG_TAG, "ESP_GAP_BLE_LOCAL_IR_EVT"); + break; + case ESP_GAP_BLE_LOCAL_ER_EVT: /* BLE local ER event */ + ESP_LOGI(LOG_TAG, "ESP_GAP_BLE_LOCAL_ER_EVT"); + break; + case ESP_GAP_BLE_NC_REQ_EVT: /* NUMERIC CONFIRMATION */ + ESP_LOGI(LOG_TAG, "ESP_GAP_BLE_NC_REQ_EVT"); +#ifdef CONFIG_BLE_SMP_ENABLE // Check that BLE SMP (security) is configured in make menuconfig + if(BLEDevice::m_securityCallbacks != nullptr){ + esp_ble_confirm_reply(param->ble_security.ble_req.bd_addr, BLEDevice::m_securityCallbacks->onConfirmPIN(param->ble_security.key_notif.passkey)); } #endif // CONFIG_BLE_SMP_ENABLE - break; - case ESP_GAP_BLE_PASSKEY_REQ_EVT: /* passkey request event */ + break; + case ESP_GAP_BLE_PASSKEY_REQ_EVT: /* passkey request event */ ESP_LOGI(LOG_TAG, "ESP_GAP_BLE_PASSKEY_REQ_EVT: "); // esp_log_buffer_hex(LOG_TAG, m_remote_bda, sizeof(m_remote_bda)); -#ifdef CONFIG_BLE_SMP_ENABLE // Check that BLE SMP (security) is configured in make menuconfig - if (BLEDevice::m_securityCallbacks != nullptr) { +#ifdef CONFIG_BLE_SMP_ENABLE // Check that BLE SMP (security) is configured in make menuconfig + if(BLEDevice::m_securityCallbacks != nullptr){ esp_ble_passkey_reply(param->ble_security.ble_req.bd_addr, true, BLEDevice::m_securityCallbacks->onPassKeyRequest()); } #endif // CONFIG_BLE_SMP_ENABLE @@ -212,14 +220,15 @@ BLEAdvertising* BLEDevice::m_bleAdvertising = nullptr; /* * TODO should we add white/black list comparison? */ - case ESP_GAP_BLE_SEC_REQ_EVT: - /* send the positive(true) security response to the peer device to accept the security request. - If not accept the security request, should sent the security response with negative(false) accept value*/ - ESP_LOGI(LOG_TAG, "ESP_GAP_BLE_SEC_REQ_EVT"); -#ifdef CONFIG_BLE_SMP_ENABLE // Check that BLE SMP (security) is configured in make menuconfig - if (BLEDevice::m_securityCallbacks != nullptr) { + case ESP_GAP_BLE_SEC_REQ_EVT: + /* send the positive(true) security response to the peer device to accept the security request. + If not accept the security request, should sent the security response with negative(false) accept value*/ + ESP_LOGI(LOG_TAG, "ESP_GAP_BLE_SEC_REQ_EVT"); +#ifdef CONFIG_BLE_SMP_ENABLE // Check that BLE SMP (security) is configured in make menuconfig + if(BLEDevice::m_securityCallbacks!=nullptr){ esp_ble_gap_security_rsp(param->ble_security.ble_req.bd_addr, BLEDevice::m_securityCallbacks->onSecurityRequest()); - } else { + } + else{ esp_ble_gap_security_rsp(param->ble_security.ble_req.bd_addr, true); } #endif // CONFIG_BLE_SMP_ENABLE @@ -227,51 +236,47 @@ BLEAdvertising* BLEDevice::m_bleAdvertising = nullptr; /* * */ - case ESP_GAP_BLE_PASSKEY_NOTIF_EVT: // the app will receive this evt when the IO has Output capability and the peer device IO has Input capability. - // show the passkey number to the user to input it in the peer device. - ESP_LOGI(LOG_TAG, "ESP_GAP_BLE_PASSKEY_NOTIF_EVT"); -#ifdef CONFIG_BLE_SMP_ENABLE // Check that BLE SMP (security) is configured in make menuconfig - if (BLEDevice::m_securityCallbacks != nullptr) { - ESP_LOGI(LOG_TAG, "passKey = %d", param->ble_security.key_notif.passkey); + case ESP_GAP_BLE_PASSKEY_NOTIF_EVT: //the app will receive this evt when the IO has Output capability and the peer device IO has Input capability. + //display the passkey number to the user to input it in the peer deivce within 30 seconds + ESP_LOGI(LOG_TAG, "ESP_GAP_BLE_PASSKEY_NOTIF_EVT"); +#ifdef CONFIG_BLE_SMP_ENABLE // Check that BLE SMP (security) is configured in make menuconfig + ESP_LOGI(LOG_TAG, "passKey = %d", param->ble_security.key_notif.passkey); + if(BLEDevice::m_securityCallbacks!=nullptr){ BLEDevice::m_securityCallbacks->onPassKeyNotify(param->ble_security.key_notif.passkey); } #endif // CONFIG_BLE_SMP_ENABLE - break; - case ESP_GAP_BLE_KEY_EVT: - //shows the ble key type info share with peer device to the user. - ESP_LOGI(LOG_TAG, "ESP_GAP_BLE_KEY_EVT"); -#ifdef CONFIG_BLE_SMP_ENABLE // Check that BLE SMP (security) is configured in make menuconfig - ESP_LOGI(LOG_TAG, "key type = %s", BLESecurity::esp_key_type_to_str(param->ble_security.ble_key.key_type)); + break; + case ESP_GAP_BLE_KEY_EVT: + //shows the ble key type info share with peer device to the user. + ESP_LOGD(LOG_TAG, "ESP_GAP_BLE_KEY_EVT"); +#ifdef CONFIG_BLE_SMP_ENABLE // Check that BLE SMP (security) is configured in make menuconfig + ESP_LOGI(LOG_TAG, "key type = %s", BLESecurity::esp_key_type_to_str(param->ble_security.ble_key.key_type)); #endif // CONFIG_BLE_SMP_ENABLE - break; - case ESP_GAP_BLE_AUTH_CMPL_EVT: - ESP_LOGI(LOG_TAG, "ESP_GAP_BLE_AUTH_CMPL_EVT"); -#ifdef CONFIG_BLE_SMP_ENABLE // Check that BLE SMP (security) is configured in make menuconfig - if (BLEDevice::m_securityCallbacks != nullptr) { - BLEDevice::m_securityCallbacks->onAuthenticationComplete(param->ble_security.auth_cmpl); - } + break; + case ESP_GAP_BLE_AUTH_CMPL_EVT: + ESP_LOGI(LOG_TAG, "ESP_GAP_BLE_AUTH_CMPL_EVT"); +#ifdef CONFIG_BLE_SMP_ENABLE // Check that BLE SMP (security) is configured in make menuconfig + if(BLEDevice::m_securityCallbacks != nullptr){ + BLEDevice::m_securityCallbacks->onAuthenticationComplete(param->ble_security.auth_cmpl); + } #endif // CONFIG_BLE_SMP_ENABLE - break; - default: + break; + default: { break; + } } // switch - if (BLEDevice::m_pServer != nullptr) { - BLEDevice::m_pServer->handleGAPEvent(event, param); - } - - if (BLEDevice::m_pClient != nullptr) { - BLEDevice::m_pClient->handleGAPEvent(event, param); - } - if (BLEDevice::m_pScan != nullptr) { BLEDevice::getScan()->handleGAPEvent(event, param); } - /* - * Security events: - */ + if(m_bleAdvertising != nullptr) { + BLEDevice::getAdvertising()->handleGAPEvent(event, param); + } + if(m_customGapHandler != nullptr) { + BLEDevice::m_customGapHandler(event, param); + } } // gapEventHandler @@ -326,7 +331,7 @@ BLEAdvertising* BLEDevice::m_bleAdvertising = nullptr; * @param deviceName The device name of the device. */ /* STATIC */ void BLEDevice::init(std::string deviceName) { - if (!initialized) { + if(!initialized){ initialized = true; // Set the initialization flag to ensure we are only initialized once. esp_err_t errRc = ESP_OK; @@ -342,6 +347,9 @@ BLEAdvertising* BLEDevice::m_bleAdvertising = nullptr; return; } +#ifndef CLASSIC_BT_ENABLED + esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT); +#endif esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); errRc = esp_bt_controller_init(&bt_cfg); if (errRc != ESP_OK) { @@ -350,7 +358,11 @@ BLEAdvertising* BLEDevice::m_bleAdvertising = nullptr; } #ifndef CLASSIC_BT_ENABLED - esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT); + errRc = esp_bt_controller_enable(ESP_BT_MODE_BLE); + if (errRc != ESP_OK) { + ESP_LOGE(LOG_TAG, "esp_bt_controller_enable: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); + return; + } #else errRc = esp_bt_controller_enable(ESP_BT_MODE_BTDM); if (errRc != ESP_OK) { @@ -538,12 +550,12 @@ bool BLEDevice::getInitialized() { } BLEAdvertising* BLEDevice::getAdvertising() { - if (m_bleAdvertising == nullptr) { + if(m_bleAdvertising == nullptr) { m_bleAdvertising = new BLEAdvertising(); ESP_LOGI(LOG_TAG, "create advertising"); } ESP_LOGD(LOG_TAG, "get advertising"); - return m_bleAdvertising; + return m_bleAdvertising; } void BLEDevice::startAdvertising() { @@ -552,4 +564,81 @@ void BLEDevice::startAdvertising() { ESP_LOGD(LOG_TAG, "<< startAdvertising"); } // startAdvertising +/* multi connect support */ +/* requires a little more work */ +std::map BLEDevice::getPeerDevices(bool _client) { + return m_connectedClientsMap; +} + +BLEClient* BLEDevice::getClientByGattIf(uint16_t conn_id) { + return (BLEClient*)m_connectedClientsMap.find(conn_id)->second.peer_device; +} + +void BLEDevice::updatePeerDevice(void* peer, bool _client, uint16_t conn_id) { + ESP_LOGD(LOG_TAG, "update conn_id: %d, GATT role: %s", conn_id, _client? "client":"server"); + std::map::iterator it = m_connectedClientsMap.find(ESP_GATT_IF_NONE); + if (it != m_connectedClientsMap.end()) { + std::swap(m_connectedClientsMap[conn_id], it->second); + m_connectedClientsMap.erase(it); + }else{ + it = m_connectedClientsMap.find(conn_id); + if (it != m_connectedClientsMap.end()) { + conn_status_t _st = it->second; + _st.peer_device = peer; + std::swap(m_connectedClientsMap[conn_id], _st); + } + } +} + +void BLEDevice::addPeerDevice(void* peer, bool _client, uint16_t conn_id) { + ESP_LOGI(LOG_TAG, "add conn_id: %d, GATT role: %s", conn_id, _client? "client":"server"); + conn_status_t status = { + .peer_device = peer, + .connected = true, + .mtu = 23 + }; + + m_connectedClientsMap.insert(std::pair(conn_id, status)); +} + +void BLEDevice::removePeerDevice(uint16_t conn_id, bool _client) { + ESP_LOGI(LOG_TAG, "remove: %d, GATT role %s", conn_id, _client?"client":"server"); + if(m_connectedClientsMap.find(conn_id) != m_connectedClientsMap.end()) + m_connectedClientsMap.erase(conn_id); +} + +/* multi connect support */ + +/** + * @brief de-Initialize the %BLE environment. + * @param release_memory release the internal BT stack memory + */ +/* STATIC */ void BLEDevice::deinit(bool release_memory) { + if (!initialized) return; + + esp_bluedroid_disable(); + esp_bluedroid_deinit(); + esp_bt_controller_disable(); + esp_bt_controller_deinit(); +#ifndef ARDUINO_ARCH_ESP32 + if (release_memory) { + esp_bt_controller_mem_release(ESP_BT_MODE_BTDM); // <-- require tests because we released classic BT memory and this can cause crash (most likely not, esp-idf takes care of it) + } else { + initialized = false; + } +#endif +} + +void BLEDevice::setCustomGapHandler(gap_event_handler handler) { + m_customGapHandler = handler; +} + +void BLEDevice::setCustomGattcHandler(gattc_event_handler handler) { + m_customGattcHandler = handler; +} + +void BLEDevice::setCustomGattsHandler(gatts_event_handler handler) { + m_customGattsHandler = handler; +} + #endif // CONFIG_BT_ENABLED diff --git a/cpp_utils/BLEDevice.h b/cpp_utils/BLEDevice.h index 9fd53ebb..b01f09be 100644 --- a/cpp_utils/BLEDevice.h +++ b/cpp_utils/BLEDevice.h @@ -22,8 +22,12 @@ #include "BLEAddress.h" /** - * @brief %BLE functions. + * @brief BLE functions. */ +typedef void (*gap_event_handler)(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t* param); +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); + class BLEDevice { public: @@ -43,19 +47,31 @@ class BLEDevice { static esp_err_t setMTU(uint16_t mtu); static uint16_t getMTU(); static bool getInitialized(); // Returns the state of the device, is it initialized or not? - static BLEAdvertising* getAdvertising(); - static void startAdvertising(); + /* move advertising to BLEDevice for saving ram and flash in beacons */ + static BLEAdvertising* getAdvertising(); + static void startAdvertising(); + static uint16_t m_appId; + /* multi connect */ + static std::map getPeerDevices(bool client); + static void addPeerDevice(void* peer, bool is_client, uint16_t conn_id); + static void updatePeerDevice(void* peer, bool _client, uint16_t conn_id); + static void removePeerDevice(uint16_t conn_id, bool client); + static BLEClient* getClientByGattIf(uint16_t conn_id); + static void setCustomGapHandler(gap_event_handler handler); + static void setCustomGattcHandler(gattc_event_handler handler); + static void setCustomGattsHandler(gatts_event_handler handler); + static void deinit(bool release_memory = false); + static uint16_t m_localMTU; + static esp_ble_sec_act_t m_securityLevel; private: - static BLEServer* m_pServer; - static BLEScan* m_pScan; - static BLEClient* m_pClient; - static esp_ble_sec_act_t m_securityLevel; + static BLEServer* m_pServer; + static BLEScan* m_pScan; + // static BLEClient* m_pClient; static BLESecurityCallbacks* m_securityCallbacks; - static uint16_t m_localMTU; - static BLEAdvertising* m_bleAdvertising; - + static BLEAdvertising* m_bleAdvertising; static esp_gatt_if_t getGattcIF(); + static std::map m_connectedClientsMap; static void gattClientEventHandler( esp_gattc_cb_event_t event, @@ -71,6 +87,12 @@ class BLEDevice { esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t* param); +public: +/* custom gap and gatt handlers for flexibility */ + static gap_event_handler m_customGapHandler; + static gattc_event_handler m_customGattcHandler; + static gatts_event_handler m_customGattsHandler; + }; // class BLE #endif // CONFIG_BT_ENABLED diff --git a/cpp_utils/BLEHIDDevice.cpp b/cpp_utils/BLEHIDDevice.cpp index 69e18be7..46770b74 100644 --- a/cpp_utils/BLEHIDDevice.cpp +++ b/cpp_utils/BLEHIDDevice.cpp @@ -194,6 +194,7 @@ BLECharacteristic* BLEHIDDevice::protocolMode() { void BLEHIDDevice::setBatteryLevel(uint8_t level) { m_batteryLevelCharacteristic->setValue(&level, 1); + m_batteryLevelCharacteristic->notify(); } /* * @brief Returns battery level characteristic diff --git a/cpp_utils/BLERemoteCharacteristic.cpp b/cpp_utils/BLERemoteCharacteristic.cpp index 14177eac..ef16da7b 100644 --- a/cpp_utils/BLERemoteCharacteristic.cpp +++ b/cpp_utils/BLERemoteCharacteristic.cpp @@ -11,7 +11,6 @@ #if defined(CONFIG_BT_ENABLED) #include -#include #include #include @@ -19,12 +18,15 @@ #include "BLEUtils.h" #include "GeneralUtils.h" #include "BLERemoteDescriptor.h" -#ifdef ARDUINO_ARCH_ESP32 +#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) #include "esp32-hal-log.h" +#define LOG_TAG "" +#else +#include "esp_log.h" +static const char* LOG_TAG = "BLERemoteCharacteristic"; // The logging tag for this class. #endif -static const char* LOG_TAG = "BLERemoteCharacteristic"; // The logging tag for this class. /** * @brief Constructor. @@ -55,6 +57,7 @@ BLERemoteCharacteristic::BLERemoteCharacteristic( */ BLERemoteCharacteristic::~BLERemoteCharacteristic() { removeDescriptors(); // Release resources for any descriptor information we may have allocated. + if(m_rawData != nullptr) free(m_rawData); } // ~BLERemoteCharacteristic @@ -147,7 +150,7 @@ static bool compareGattId(esp_gatt_id_t id1, esp_gatt_id_t id2) { * @returns N/A */ void BLERemoteCharacteristic::gattClientEventHandler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t* evtParam) { - switch (event) { + switch(event) { // ESP_GATTC_NOTIFY_EVT // // notify @@ -187,8 +190,7 @@ void BLERemoteCharacteristic::gattClientEventHandler(esp_gattc_cb_event_t event, // and unlock the semaphore to ensure that the requestor of the data can continue. if (evtParam->read.status == ESP_GATT_OK) { m_value = std::string((char*) evtParam->read.value, evtParam->read.value_len); - if (m_rawData != nullptr) free(m_rawData); - + if(m_rawData != nullptr) free(m_rawData); m_rawData = (uint8_t*) calloc(evtParam->read.value_len, sizeof(uint8_t)); memcpy(m_rawData, evtParam->read.value, evtParam->read.value_len); } else { @@ -260,7 +262,7 @@ void BLERemoteCharacteristic::retrieveDescriptors() { // For each descriptor we find, create a BLERemoteDescriptor instance. uint16_t offset = 0; esp_gattc_descr_elem_t result; - while (true) { + while(true) { uint16_t count = 1; esp_gatt_status_t status = ::esp_ble_gattc_get_all_descr( getRemoteService()->getClient()->getGattcIf(), @@ -271,7 +273,7 @@ void BLERemoteCharacteristic::retrieveDescriptors() { offset ); - if (status == ESP_GATT_INVALID_OFFSET) { // We have reached the end of the entries. + if (status == ESP_GATT_INVALID_OFFSET || status == ESP_GATT_NOT_FOUND) { // We have reached the end of the entries. break; } @@ -281,7 +283,7 @@ void BLERemoteCharacteristic::retrieveDescriptors() { } if (count == 0) break; - ESP_LOGE(LOG_TAG, ""); + ESP_LOGD(LOG_TAG, "Found a descriptor: Handle: %d, UUID: %s", result.handle, BLEUUID(result.uuid).toString().c_str()); // We now have a new characteristic ... let us add that to our set of known characteristics @@ -327,7 +329,7 @@ uint16_t BLERemoteCharacteristic::getHandle() { BLERemoteDescriptor* BLERemoteCharacteristic::getDescriptor(BLEUUID uuid) { ESP_LOGD(LOG_TAG, ">> getDescriptor: uuid: %s", uuid.toString().c_str()); std::string v = uuid.toString(); - for (auto& myPair : m_descriptorMap) { + for (auto &myPair : m_descriptorMap) { if (myPair.first == v) { ESP_LOGD(LOG_TAG, "<< getDescriptor: found"); return myPair.second; @@ -363,7 +365,7 @@ BLEUUID BLERemoteCharacteristic::getUUID() { uint16_t BLERemoteCharacteristic::readUInt16() { std::string value = readValue(); if (value.length() >= 2) { - return *(uint16_t*) value.data(); + return *(uint16_t*)(value.data()); } return 0; } // readUInt16 @@ -376,7 +378,7 @@ uint16_t BLERemoteCharacteristic::readUInt16() { uint32_t BLERemoteCharacteristic::readUInt32() { std::string value = readValue(); if (value.length() >= 4) { - return *(uint32_t*) value.data(); + return *(uint32_t*)(value.data()); } return 0; } // readUInt32 @@ -389,7 +391,7 @@ uint32_t BLERemoteCharacteristic::readUInt32() { uint8_t BLERemoteCharacteristic::readUInt8() { std::string value = readValue(); if (value.length() >= 1) { - return (uint8_t) value[0]; + return (uint8_t)value[0]; } return 0; } // readUInt8 @@ -439,12 +441,7 @@ std::string BLERemoteCharacteristic::readValue() { * unregistering a notification. * @return N/A. */ -void BLERemoteCharacteristic::registerForNotify( - void (*notifyCallback)( - BLERemoteCharacteristic* pBLERemoteCharacteristic, - uint8_t* pData, - size_t length, - bool isNotify), bool notifications) { +void BLERemoteCharacteristic::registerForNotify(notify_callback notifyCallback, bool notifications) { ESP_LOGD(LOG_TAG, ">> registerForNotify(): %s", toString().c_str()); m_notifyCallback = notifyCallback; // Save the notification callback. @@ -463,9 +460,10 @@ void BLERemoteCharacteristic::registerForNotify( } uint8_t val[] = {0x01, 0x00}; - if (!notifications) val[0] = 0x02; - BLERemoteDescriptor* desc = getDescriptor(BLEUUID("0x2902")); - desc->writeValue(val, 2); + if(!notifications) val[0] = 0x02; + BLERemoteDescriptor* desc = getDescriptor(BLEUUID((uint16_t)0x2902)); + if(desc != nullptr) + desc->writeValue(val, 2); } // End Register else { // If we weren't passed a callback function, then this is an unregistration. esp_err_t errRc = ::esp_ble_gattc_unregister_for_notify( @@ -479,8 +477,9 @@ void BLERemoteCharacteristic::registerForNotify( } uint8_t val[] = {0x00, 0x00}; - BLERemoteDescriptor* desc = getDescriptor(BLEUUID("0x2902")); - desc->writeValue(val, 2); + BLERemoteDescriptor* desc = getDescriptor((uint16_t)0x2902); + if(desc != nullptr) + desc->writeValue(val, 2); } // End Unregister m_semaphoreRegForNotifyEvt.wait("registerForNotify"); @@ -523,62 +522,64 @@ std::string BLERemoteCharacteristic::toString() { * @brief Write the new value for the characteristic. * @param [in] newValue The new value to write. * @param [in] response Do we expect a response? - * @return N/A. + * @return false if not connected or cant perform write for some reason. + */ +bool BLERemoteCharacteristic::writeValue(std::string newValue, bool response) { + return writeValue((uint8_t*)newValue.c_str(), strlen(newValue.c_str()), response); +} // writeValue + + +/** + * @brief Write the new value for the characteristic. + * + * This is a convenience function. Many BLE characteristics are a single byte of data. + * @param [in] newValue The new byte value to write. + * @param [in] response Whether we require a response from the write. + * @return false if not connected or cant perform write for some reason. + */ +bool BLERemoteCharacteristic::writeValue(uint8_t newValue, bool response) { + return writeValue(&newValue, 1, response); +} // writeValue + + +/** + * @brief Write the new value for the characteristic from a data buffer. + * @param [in] data A pointer to a data buffer. + * @param [in] length The length of the data in the data buffer. + * @param [in] response Whether we require a response from the write. + * @return false if not connected or cant perform write for some reason. */ -void BLERemoteCharacteristic::writeValue(std::string newValue, bool response) { - ESP_LOGD(LOG_TAG, ">> writeValue(), length: %d", newValue.length()); +bool BLERemoteCharacteristic::writeValue(uint8_t* data, size_t length, bool response) { + // writeValue(std::string((char*)data, length), response); + ESP_LOGD(LOG_TAG, ">> writeValue(), length: %d", length); // Check to see that we are connected. if (!getRemoteService()->getClient()->isConnected()) { ESP_LOGE(LOG_TAG, "Disconnected"); - throw BLEDisconnectedException(); + return false; } m_semaphoreWriteCharEvt.take("writeValue"); - // Invoke the ESP-IDF API to perform the write. esp_err_t errRc = ::esp_ble_gattc_write_char( m_pRemoteService->getClient()->getGattcIf(), m_pRemoteService->getClient()->getConnId(), getHandle(), - newValue.length(), - (uint8_t*)newValue.data(), + length, + data, response?ESP_GATT_WRITE_TYPE_RSP:ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE ); if (errRc != ESP_OK) { ESP_LOGE(LOG_TAG, "esp_ble_gattc_write_char: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); - return; + return false; } m_semaphoreWriteCharEvt.wait("writeValue"); ESP_LOGD(LOG_TAG, "<< writeValue"); -} // writeValue - - -/** - * @brief Write the new value for the characteristic. - * - * This is a convenience function. Many BLE characteristics are a single byte of data. - * @param [in] newValue The new byte value to write. - * @param [in] response Whether we require a response from the write. - * @return N/A. - */ -void BLERemoteCharacteristic::writeValue(uint8_t newValue, bool response) { - writeValue(std::string(reinterpret_cast(&newValue), 1), response); -} // writeValue - - -/** - * @brief Write the new value for the characteristic from a data buffer. - * @param [in] data A pointer to a data buffer. - * @param [in] length The length of the data in the data buffer. - * @param [in] response Whether we require a response from the write. - */ -void BLERemoteCharacteristic::writeValue(uint8_t* data, size_t length, bool response) { - writeValue(std::string((char*) data, length), response); + return true; } // writeValue /** diff --git a/cpp_utils/BLERemoteCharacteristic.h b/cpp_utils/BLERemoteCharacteristic.h index 0750c1a9..910b11a4 100644 --- a/cpp_utils/BLERemoteCharacteristic.h +++ b/cpp_utils/BLERemoteCharacteristic.h @@ -21,6 +21,7 @@ class BLERemoteService; class BLERemoteDescriptor; +typedef void (*notify_callback)(BLERemoteCharacteristic* pBLERemoteCharacteristic, uint8_t* pData, size_t length, bool isNotify); /** * @brief A model of a remote %BLE characteristic. @@ -37,19 +38,20 @@ class BLERemoteCharacteristic { bool canWrite(); bool canWriteNoResponse(); BLERemoteDescriptor* getDescriptor(BLEUUID uuid); + std::map* getDescriptors(); uint16_t getHandle(); BLEUUID getUUID(); - std::map* getDescriptors(); - std::string readValue(void); - uint8_t readUInt8(void); - uint16_t readUInt16(void); - uint32_t readUInt32(void); - void registerForNotify(void (*notifyCallback)(BLERemoteCharacteristic* pBLERemoteCharacteristic, uint8_t* pData, size_t length, bool isNotify), bool notifications = true); - void writeValue(uint8_t* data, size_t length, bool response = false); - void writeValue(std::string newValue, bool response = false); - void writeValue(uint8_t newValue, bool response = false); - std::string toString(void); + std::string readValue(); + uint8_t readUInt8(); + uint16_t readUInt16(); + uint32_t readUInt32(); + void registerForNotify(notify_callback _callback, bool notifications = 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(); + BLERemoteService* getRemoteService(); private: BLERemoteCharacteristic(uint16_t handle, BLEUUID uuid, esp_gatt_char_prop_t charProp, BLERemoteService* pRemoteService); @@ -58,26 +60,22 @@ class BLERemoteCharacteristic { friend class BLERemoteDescriptor; // Private member functions - void gattClientEventHandler( - esp_gattc_cb_event_t event, - esp_gatt_if_t gattc_if, - esp_ble_gattc_cb_param_t* evtParam); + void gattClientEventHandler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t* evtParam); - BLERemoteService* getRemoteService(); - void removeDescriptors(); - void retrieveDescriptors(); + void removeDescriptors(); + void retrieveDescriptors(); // Private properties - BLEUUID m_uuid; + BLEUUID m_uuid; esp_gatt_char_prop_t m_charProp; - uint16_t m_handle; - BLERemoteService* m_pRemoteService; - FreeRTOS::Semaphore m_semaphoreReadCharEvt = FreeRTOS::Semaphore("ReadCharEvt"); + uint16_t m_handle; + BLERemoteService* m_pRemoteService; + FreeRTOS::Semaphore m_semaphoreReadCharEvt = FreeRTOS::Semaphore("ReadCharEvt"); FreeRTOS::Semaphore m_semaphoreRegForNotifyEvt = FreeRTOS::Semaphore("RegForNotifyEvt"); - FreeRTOS::Semaphore m_semaphoreWriteCharEvt = FreeRTOS::Semaphore("WriteCharEvt"); - std::string m_value; - uint8_t* m_rawData; - void (*m_notifyCallback)(BLERemoteCharacteristic* pBLERemoteCharacteristic, uint8_t* pData, size_t length, bool isNotify); + FreeRTOS::Semaphore m_semaphoreWriteCharEvt = FreeRTOS::Semaphore("WriteCharEvt"); + std::string m_value; + uint8_t *m_rawData = nullptr; + notify_callback m_notifyCallback = nullptr; // We maintain a map of descriptors owned by this characteristic keyed by a string representation of the UUID. std::map m_descriptorMap; diff --git a/cpp_utils/BLERemoteDescriptor.cpp b/cpp_utils/BLERemoteDescriptor.cpp index ea7eeebd..96a8a577 100644 --- a/cpp_utils/BLERemoteDescriptor.cpp +++ b/cpp_utils/BLERemoteDescriptor.cpp @@ -9,12 +9,15 @@ #include #include "BLERemoteDescriptor.h" #include "GeneralUtils.h" -#include -#ifdef ARDUINO_ARCH_ESP32 +#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) #include "esp32-hal-log.h" +#define LOG_TAG "" +#else +#include "esp_log.h" +static const char* LOG_TAG = "BLERemoteDescriptor"; #endif -static const char* LOG_TAG = "BLERemoteDescriptor"; + BLERemoteDescriptor::BLERemoteDescriptor( diff --git a/cpp_utils/BLERemoteService.cpp b/cpp_utils/BLERemoteService.cpp index d632cff5..91089eab 100644 --- a/cpp_utils/BLERemoteService.cpp +++ b/cpp_utils/BLERemoteService.cpp @@ -11,13 +11,16 @@ #include "BLERemoteService.h" #include "BLEUtils.h" #include "GeneralUtils.h" -#include #include -#ifdef ARDUINO_ARCH_ESP32 +#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) #include "esp32-hal-log.h" +#define LOG_TAG "" +#else +#include "esp_log.h" +static const char* LOG_TAG = "BLERemoteService"; #endif -static const char* LOG_TAG = "BLERemoteService"; + BLERemoteService::BLERemoteService( esp_gatt_id_t srvcId, @@ -62,52 +65,6 @@ void BLERemoteService::gattClientEventHandler( esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t* evtParam) { switch (event) { - // - // ESP_GATTC_GET_CHAR_EVT - // - // get_char: - // - esp_gatt_status_t status - // - uin1t6_t conn_id - // - esp_gatt_srvc_id_t srvc_id - // - esp_gatt_id_t char_id - // - esp_gatt_char_prop_t char_prop - // - /* - case ESP_GATTC_GET_CHAR_EVT: { - // Is this event for this service? If yes, then the local srvc_id and the event srvc_id will be - // the same. - if (compareSrvcId(m_srvcId, evtParam->get_char.srvc_id) == false) { - break; - } - - // If the status is NOT OK then we have a problem and continue. - if (evtParam->get_char.status != ESP_GATT_OK) { - m_semaphoreGetCharEvt.give(); - break; - } - - // This is an indication that we now have the characteristic details for a characteristic owned - // by this service so remember it. - m_characteristicMap.insert(std::pair( - BLEUUID(evtParam->get_char.char_id.uuid).toString(), - new BLERemoteCharacteristic(evtParam->get_char.char_id, evtParam->get_char.char_prop, this) )); - - - // Now that we have received a characteristic, lets ask for the next one. - esp_err_t errRc = ::esp_ble_gattc_get_characteristic( - m_pClient->getGattcIf(), - m_pClient->getConnId(), - &m_srvcId, - &evtParam->get_char.char_id); - if (errRc != ESP_OK) { - ESP_LOGE(LOG_TAG, "esp_ble_gattc_get_characteristic: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); - break; - } - - //m_semaphoreGetCharEvt.give(); - break; - } // ESP_GATTC_GET_CHAR_EVT -*/ default: break; } // switch @@ -126,10 +83,9 @@ void BLERemoteService::gattClientEventHandler( * @throws BLEUuidNotFoundException */ BLERemoteCharacteristic* BLERemoteService::getCharacteristic(const char* uuid) { - return getCharacteristic(BLEUUID(uuid)); + return getCharacteristic(BLEUUID(uuid)); } // getCharacteristic - - + /** * @brief Get the characteristic object for the UUID. * @param [in] uuid Characteristic uuid. @@ -152,7 +108,8 @@ BLERemoteCharacteristic* BLERemoteService::getCharacteristic(BLEUUID uuid) { return myPair.second; } } - throw new BLEUuidNotFoundException(); + // throw new BLEUuidNotFoundException(); // <-- we dont want exception here, which will cause app crash, we want to search if any characteristic can be found one after another + return nullptr; } // getCharacteristic @@ -162,14 +119,14 @@ BLERemoteCharacteristic* BLERemoteService::getCharacteristic(BLEUUID uuid) { * @return N/A */ void BLERemoteService::retrieveCharacteristics() { - ESP_LOGD(LOG_TAG, ">> getCharacteristics() for service: %s", getUUID().toString().c_str()); + ESP_LOGD(LOG_TAG, ">> retrieveCharacteristics() for service: %s", getUUID().toString().c_str()); removeCharacteristics(); // Forget any previous characteristics. uint16_t offset = 0; esp_gattc_char_elem_t result; while (true) { - uint16_t count = 1; + uint16_t count = 1; // this value is used as in parameter that allows to search max 10 chars with the same uuid esp_gatt_status_t status = ::esp_ble_gattc_get_all_char( getClient()->getGattcIf(), getClient()->getConnId(), @@ -180,7 +137,7 @@ void BLERemoteService::retrieveCharacteristics() { offset ); - if (status == ESP_GATT_INVALID_OFFSET) { // We have reached the end of the entries. + if (status == ESP_GATT_INVALID_OFFSET || status == ESP_GATT_NOT_FOUND) { // We have reached the end of the entries. break; } @@ -209,8 +166,8 @@ void BLERemoteService::retrieveCharacteristics() { } // Loop forever (until we break inside the loop). m_haveCharacteristics = true; // Remember that we have received the characteristics. - ESP_LOGD(LOG_TAG, "<< getCharacteristics()"); -} // getCharacteristics + ESP_LOGD(LOG_TAG, "<< retrieveCharacteristics()"); +} // retrieveCharacteristics /** @@ -229,12 +186,28 @@ std::map* BLERemoteService::getCharacteri 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* BLERemoteService::getCharacteristicsByHandle() { + ESP_LOGD(LOG_TAG, ">> getCharacteristicsByHandle() for service: %s", getUUID().toString().c_str()); + // If is possible that we have not read the characteristics associated with the service so do that + // now. The request to retrieve the characteristics by calling "retrieveCharacteristics" is a blocking + // call and does not return until all the characteristics are available. + if (!m_haveCharacteristics) { + retrieveCharacteristics(); + } + ESP_LOGD(LOG_TAG, "<< getCharacteristicsByHandle() for service: %s", getUUID().toString().c_str()); + return &m_characteristicMapByHandle; +} // getCharacteristicsByHandle + /** * @brief This function is designed to get characteristics map when we have multiple characteristics with the same UUID */ void BLERemoteService::getCharacteristics(std::map* pCharacteristicMap) { #pragma GCC diagnostic ignored "-Wunused-but-set-parameter" - pCharacteristicMap = &m_characteristicMapByHandle; + *pCharacteristicMap = m_characteristicMapByHandle; } // Get the characteristics map. /** @@ -292,10 +265,6 @@ std::string BLERemoteService::getValue(BLEUUID characteristicUuid) { * @return N/A. */ void BLERemoteService::removeCharacteristics() { - for (auto &myPair : m_characteristicMap) { - delete myPair.second; - //m_characteristicMap.erase(myPair.first); // Should be no need to delete as it will be deleted by the clear - } m_characteristicMap.clear(); // Clear the map for (auto &myPair : m_characteristicMapByHandle) { delete myPair.second; diff --git a/cpp_utils/BLERemoteService.h b/cpp_utils/BLERemoteService.h index 387afbdf..2ab86738 100644 --- a/cpp_utils/BLERemoteService.h +++ b/cpp_utils/BLERemoteService.h @@ -33,7 +33,8 @@ class BLERemoteService { BLERemoteCharacteristic* getCharacteristic(BLEUUID uuid); // Get the specified characteristic reference. BLERemoteCharacteristic* getCharacteristic(uint16_t uuid); // Get the specified characteristic reference. std::map* getCharacteristics(); - void getCharacteristics(std::map* pCharacteristicMap); // Get the characteristics map. + std::map* getCharacteristicsByHandle(); // Get the characteristics map. + void getCharacteristics(std::map* pCharacteristicMap); BLEClient* getClient(void); // Get a reference to the client associated with this service. uint16_t getHandle(); // Get the handle of this service. diff --git a/cpp_utils/BLEScan.cpp b/cpp_utils/BLEScan.cpp index 25b60a0b..a96e6df6 100644 --- a/cpp_utils/BLEScan.cpp +++ b/cpp_utils/BLEScan.cpp @@ -8,7 +8,6 @@ #if defined(CONFIG_BT_ENABLED) -#include #include #include @@ -17,11 +16,15 @@ #include "BLEScan.h" #include "BLEUtils.h" #include "GeneralUtils.h" -#ifdef ARDUINO_ARCH_ESP32 +#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) #include "esp32-hal-log.h" +#define LOG_TAG "" +#else +#include "esp_log.h" +static const char* LOG_TAG = "BLEScan"; #endif -static const char* LOG_TAG = "BLEScan"; + /** @@ -48,22 +51,21 @@ void BLEScan::handleGAPEvent( esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t* param) { - switch (event) { - - // ESP_GAP_BLE_SCAN_RESULT_EVT - // --------------------------- - // scan_rst: - // esp_gap_search_evt_t search_evt - // esp_bd_addr_t bda - // esp_bt_dev_type_t dev_type - // esp_ble_addr_type_t ble_addr_type - // esp_ble_evt_type_t ble_evt_type - // int rssi - // uint8_t ble_adv[ESP_BLE_ADV_DATA_LEN_MAX] - // int flag - // int num_resps - // uint8_t adv_data_len - // uint8_t scan_rsp_len + switch(event) { + + // --------------------------- + // scan_rst: + // esp_gap_search_evt_t search_evt + // esp_bd_addr_t bda + // esp_bt_dev_type_t dev_type + // esp_ble_addr_type_t ble_addr_type + // esp_ble_evt_type_t ble_evt_type + // int rssi + // uint8_t ble_adv[ESP_BLE_ADV_DATA_LEN_MAX] + // int flag + // int num_resps + // uint8_t adv_data_len + // uint8_t scan_rsp_len case ESP_GAP_BLE_SCAN_RESULT_EVT: { switch(param->scan_rst.search_evt) { @@ -73,11 +75,12 @@ void BLEScan::handleGAPEvent( // Event that indicates that the duration allowed for the search has completed or that we have been // asked to stop. case ESP_GAP_SEARCH_INQ_CMPL_EVT: { + ESP_LOGW(LOG_TAG, "ESP_GAP_SEARCH_INQ_CMPL_EVT"); m_stopped = true; + m_semaphoreScanEnd.give(); if (m_scanCompleteCB != nullptr) { m_scanCompleteCB(m_scanResults); } - m_semaphoreScanEnd.give(); break; } // ESP_GAP_SEARCH_INQ_CMPL_EVT @@ -90,52 +93,59 @@ void BLEScan::handleGAPEvent( break; } - // Examine our list of previously scanned addresses and, if we found this one already, - // ignore it. +// Examine our list of previously scanned addresses and, if we found this one already, +// ignore it. BLEAddress advertisedAddress(param->scan_rst.bda); bool found = false; - for (uint32_t i = 0; i < m_scanResults.getCount(); i++) { - if (m_scanResults.getDevice(i).getAddress().equals(advertisedAddress)) { - found = true; - break; - } + if (m_scanResults.m_vectorAdvertisedDevices.count(advertisedAddress.toString()) != 0) { + found = true; } + if (found && !m_wantDuplicates) { // If we found a previous entry AND we don't want duplicates, then we are done. ESP_LOGD(LOG_TAG, "Ignoring %s, already seen it.", advertisedAddress.toString().c_str()); + vTaskDelay(1); // <--- allow to switch task in case we scan infinity and dont have new devices to report, or we are blocked here break; } // We now construct a model of the advertised device that we have just found for the first // time. - BLEAdvertisedDevice advertisedDevice; - advertisedDevice.setAddress(advertisedAddress); - advertisedDevice.setRSSI(param->scan_rst.rssi); - advertisedDevice.setAdFlag(param->scan_rst.flag); - advertisedDevice.parseAdvertisement((uint8_t*)param->scan_rst.ble_adv); - advertisedDevice.setScan(this); + // ESP_LOG_BUFFER_HEXDUMP(LOG_TAG, (uint8_t*)param->scan_rst.ble_adv, param->scan_rst.adv_data_len + param->scan_rst.scan_rsp_len, ESP_LOG_DEBUG); + // ESP_LOGW(LOG_TAG, "bytes length: %d + %d, addr type: %d", param->scan_rst.adv_data_len, param->scan_rst.scan_rsp_len, param->scan_rst.ble_addr_type); + BLEAdvertisedDevice *advertisedDevice = new BLEAdvertisedDevice(); + advertisedDevice->setAddress(advertisedAddress); + advertisedDevice->setRSSI(param->scan_rst.rssi); + advertisedDevice->setAdFlag(param->scan_rst.flag); + advertisedDevice->parseAdvertisement((uint8_t*)param->scan_rst.ble_adv, param->scan_rst.adv_data_len + param->scan_rst.scan_rsp_len); + advertisedDevice->setScan(this); + advertisedDevice->setAddressType(param->scan_rst.ble_addr_type); - if (m_pAdvertisedDeviceCallbacks) { - m_pAdvertisedDeviceCallbacks->onResult(advertisedDevice); + if (!found) { // If we have previously seen this device, don't record it again. + m_scanResults.m_vectorAdvertisedDevices.insert(std::pair(advertisedAddress.toString(), advertisedDevice)); } - if (!found) { // If we have previously seen this device, don't record it again. - m_scanResults.m_vectorAdvertisedDevices.push_back(advertisedDevice); + if (m_pAdvertisedDeviceCallbacks) { + m_pAdvertisedDeviceCallbacks->onResult(advertisedDevice); + m_pAdvertisedDeviceCallbacks->onResult(*advertisedDevice); } + if(found) + delete advertisedDevice; break; } // ESP_GAP_SEARCH_INQ_RES_EVT - default: + default: { break; + } } // switch - search_evt break; } // ESP_GAP_BLE_SCAN_RESULT_EVT - default: + default: { break; + } // default } // End switch } // gapEventHandler @@ -188,15 +198,23 @@ void BLEScan::setWindow(uint16_t windowMSecs) { * @brief Start scanning. * @param [in] duration The duration in seconds for which to scan. * @param [in] scanCompleteCB A function to be called when scanning has completed. + * @param [in] are we continue scan (true) or we want to clear stored devices (false) * @return True if scan started or false if there was an error. */ -bool BLEScan::start(uint32_t duration, void (*scanCompleteCB)(BLEScanResults)) { +bool BLEScan::start(uint32_t duration, void (*scanCompleteCB)(BLEScanResults), bool is_continue) { ESP_LOGD(LOG_TAG, ">> start(duration=%d)", duration); m_semaphoreScanEnd.take(std::string("start")); m_scanCompleteCB = scanCompleteCB; // Save the callback to be invoked when the scan completes. - m_scanResults.m_vectorAdvertisedDevices.clear(); + // if we are connecting to devices that are advertising even after being connected, multiconnecting peripherals + // then we should not clear map or we will connect the same device few times + if(!is_continue) { + for(auto _dev : m_scanResults.m_vectorAdvertisedDevices){ + delete _dev.second; + } + m_scanResults.m_vectorAdvertisedDevices.clear(); + } esp_err_t errRc = ::esp_ble_gap_set_scan_params(&m_scan_params); @@ -226,8 +244,8 @@ bool BLEScan::start(uint32_t duration, void (*scanCompleteCB)(BLEScanResults)) { * @param [in] duration The duration in seconds for which to scan. * @return The BLEScanResults. */ -BLEScanResults BLEScan::start(uint32_t duration) { - if (start(duration, nullptr)) { +BLEScanResults BLEScan::start(uint32_t duration, bool is_continue) { + if(start(duration, nullptr, is_continue)) { m_semaphoreScanEnd.wait("start"); // Wait for the semaphore to release. } return m_scanResults; @@ -244,24 +262,31 @@ void BLEScan::stop() { esp_err_t errRc = ::esp_ble_gap_stop_scanning(); m_stopped = true; + m_semaphoreScanEnd.give(); if (errRc != ESP_OK) { ESP_LOGE(LOG_TAG, "esp_ble_gap_stop_scanning: err: %d, text: %s", errRc, GeneralUtils::errorToString(errRc)); return; } - m_semaphoreScanEnd.give(); - ESP_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 BLEScan::erase(BLEAddress address) { + ESP_LOGI(LOG_TAG, "erase device: %s", address.toString().c_str()); + BLEAdvertisedDevice *advertisedDevice = m_scanResults.m_vectorAdvertisedDevices.find(address.toString())->second; + m_scanResults.m_vectorAdvertisedDevices.erase(address.toString()); + delete advertisedDevice; +} + /** * @brief Dump the scan results to the log. */ void BLEScanResults::dump() { ESP_LOGD(LOG_TAG, ">> Dump scan results:"); - for (uint32_t i = 0; i < getCount(); i++) { + for (int i=0; isecond; + for (auto it = m_vectorAdvertisedDevices.begin(); it != m_vectorAdvertisedDevices.end(); it++) { + dev = *it->second; + if (x==i) break; + x++; + } + return dev; } +BLEScanResults BLEScan::getResults() { + return m_scanResults; +} + +void BLEScan::clearResults() { + for(auto _dev : m_scanResults.m_vectorAdvertisedDevices){ + delete _dev.second; + } + m_scanResults.m_vectorAdvertisedDevices.clear(); +} #endif /* CONFIG_BT_ENABLED */ diff --git a/cpp_utils/BLEScan.h b/cpp_utils/BLEScan.h index aec4e3db..2f71a727 100644 --- a/cpp_utils/BLEScan.h +++ b/cpp_utils/BLEScan.h @@ -11,7 +11,8 @@ #if defined(CONFIG_BT_ENABLED) #include -#include +// #include +#include #include "BLEAdvertisedDevice.h" #include "BLEClient.h" #include "FreeRTOS.h" @@ -37,7 +38,7 @@ class BLEScanResults { private: friend BLEScan; - std::vector m_vectorAdvertisedDevices; + std::map m_vectorAdvertisedDevices; }; /** @@ -53,9 +54,12 @@ class BLEScan { bool wantDuplicates = false); void setInterval(uint16_t intervalMSecs); void setWindow(uint16_t windowMSecs); - bool start(uint32_t duration, void (*scanCompleteCB)(BLEScanResults)); - BLEScanResults start(uint32_t duration); + bool start(uint32_t duration, void (*scanCompleteCB)(BLEScanResults), bool is_continue = false); + BLEScanResults start(uint32_t duration, bool is_continue = false); void stop(); + void erase(BLEAddress address); + BLEScanResults getResults(); + void clearResults(); private: BLEScan(); // One doesn't create a new instance instead one asks the BLEDevice for the singleton. @@ -63,12 +67,12 @@ class BLEScan { void handleGAPEvent( esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t* param); - void parseAdvertisement(BLEClient* pRemoteDevice, uint8_t* payload); + void parseAdvertisement(BLEClient* pRemoteDevice, uint8_t *payload); esp_ble_scan_params_t m_scan_params; - BLEAdvertisedDeviceCallbacks* m_pAdvertisedDeviceCallbacks; - bool m_stopped; + BLEAdvertisedDeviceCallbacks* m_pAdvertisedDeviceCallbacks = nullptr; + bool m_stopped = true; FreeRTOS::Semaphore m_semaphoreScanEnd = FreeRTOS::Semaphore("ScanEnd"); BLEScanResults m_scanResults; bool m_wantDuplicates; diff --git a/cpp_utils/BLESecurity.cpp b/cpp_utils/BLESecurity.cpp index 114f630d..f3b2cd3c 100644 --- a/cpp_utils/BLESecurity.cpp +++ b/cpp_utils/BLESecurity.cpp @@ -5,7 +5,7 @@ * Author: chegewara */ -#include +#include "BLESecurity.h" #include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) @@ -61,6 +61,17 @@ void BLESecurity::setKeySize(uint8_t key_size) { esp_ble_gap_set_security_param(ESP_BLE_SM_MAX_KEY_SIZE, &m_keySize, sizeof(uint8_t)); } //setKeySize +/** + * Setup for static PIN connection, call it first and then call setAuthenticationMode eventually to change it + */ +void BLESecurity::setStaticPIN(uint32_t pin){ + uint32_t passkey = pin; + esp_ble_gap_set_security_param(ESP_BLE_SM_SET_STATIC_PASSKEY, &passkey, sizeof(uint32_t)); + setCapability(ESP_IO_CAP_OUT); + setKeySize(); + setAuthenticationMode(ESP_LE_AUTH_REQ_SC_ONLY); + setInitEncryptionKey(ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK); +} /** * @brief Debug function to display what keys are exchanged by peers diff --git a/cpp_utils/BLESecurity.h b/cpp_utils/BLESecurity.h index 48d09d2f..dc6d6d71 100644 --- a/cpp_utils/BLESecurity.h +++ b/cpp_utils/BLESecurity.h @@ -21,6 +21,7 @@ class BLESecurity { void setInitEncryptionKey(uint8_t init_key); void setRespEncryptionKey(uint8_t resp_key); void setKeySize(uint8_t key_size = 16); + void setStaticPIN(uint32_t pin); static char* esp_key_type_to_str(esp_ble_key_type_t key_type); private: diff --git a/cpp_utils/BLEServer.cpp b/cpp_utils/BLEServer.cpp index b40cd345..83497331 100755 --- a/cpp_utils/BLEServer.cpp +++ b/cpp_utils/BLEServer.cpp @@ -7,11 +7,10 @@ #include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) -#include #include #include -#include -//#include +#include +#include "GeneralUtils.h" #include "BLEDevice.h" #include "BLEServer.h" #include "BLEService.h" @@ -19,11 +18,15 @@ #include #include #include -#ifdef ARDUINO_ARCH_ESP32 +#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) #include "esp32-hal-log.h" +#define LOG_TAG "" +#else +#include "esp_log.h" +static const char* LOG_TAG = "BLEServer"; #endif -static const char* LOG_TAG = "BLEServer"; + /** @@ -33,18 +36,17 @@ static const char* LOG_TAG = "BLEServer"; * the BLEDevice class. */ BLEServer::BLEServer() { - m_appId = -1; - m_gatts_if = -1; + m_appId = ESP_GATT_IF_NONE; + m_gatts_if = ESP_GATT_IF_NONE; m_connectedCount = 0; - m_connId = -1; + m_connId = ESP_GATT_IF_NONE; m_pServerCallbacks = nullptr; - //createApp(0); } // BLEServer void BLEServer::createApp(uint16_t appId) { m_appId = appId; - registerApp(); + registerApp(appId); } // createApp @@ -79,12 +81,10 @@ BLEService* BLEServer::createService(BLEUUID uuid, uint32_t numHandles, uint8_t if (m_serviceMap.getByUUID(uuid) != nullptr) { ESP_LOGW(LOG_TAG, "<< Attempt to create a new service with uuid %s but a service with that UUID already exists.", uuid.toString().c_str()); - //m_semaphoreCreateEvt.give(); - //return nullptr; } BLEService* pService = new BLEService(uuid, numHandles); - pService->m_id = inst_id; + pService->m_instId = inst_id; m_serviceMap.setByUUID(uuid, pService); // Save a reference to this service being on this server. pService->executeCreate(this); // Perform the API calls to actually create the service. @@ -104,7 +104,6 @@ BLEService* BLEServer::getServiceByUUID(const char* uuid) { return m_serviceMap.getByUUID(uuid); } - /** * @brief Get a %BLE Service by its UUID * @param [in] uuid The UUID of the new service. @@ -114,20 +113,6 @@ BLEService* BLEServer::getServiceByUUID(BLEUUID uuid) { return m_serviceMap.getByUUID(uuid); } - -/** - * @brief Returns the amount of services registered to this server - * @param [in] includeDefaultServices Add the amount of default BluetoothLE services defined by the BLE standard - * @return The amount of registered services - */ -int BLEServer::getServiceCount(bool includeDefaultServices) { - if(includeDefaultServices){ - return m_serviceMap.getRegisteredServiceCount() + 2; - } - return m_serviceMap.getRegisteredServiceCount(); -} - - /** * @brief Retrieve the advertising object that can be used to advertise the existence of the server. * @@ -137,7 +122,6 @@ BLEAdvertising* BLEServer::getAdvertising() { return BLEDevice::getAdvertising(); } - uint16_t BLEServer::getConnId() { return m_connId; } @@ -156,41 +140,6 @@ uint16_t BLEServer::getGattsIf() { return m_gatts_if; } -/** - * @brief Handle a received GAP event. - * - * @param [in] event - * @param [in] param - */ -void BLEServer::handleGAPEvent( - esp_gap_ble_cb_event_t event, - esp_ble_gap_cb_param_t* param) { - ESP_LOGD(LOG_TAG, "BLEServer ... handling GAP event!"); - switch (event) { - case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT: { - /* - esp_ble_adv_params_t adv_params; - adv_params.adv_int_min = 0x20; - adv_params.adv_int_max = 0x40; - adv_params.adv_type = ADV_TYPE_IND; - adv_params.own_addr_type = BLE_ADDR_TYPE_PUBLIC; - adv_params.channel_map = ADV_CHNL_ALL; - adv_params.adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY; - ESP_LOGD(tag, "Starting advertising"); - esp_err_t errRc = ::esp_ble_gap_start_advertising(&adv_params); - if (errRc != ESP_OK) { - ESP_LOGE(tag, "esp_ble_gap_start_advertising: rc=%d %s", errRc, espToString(errRc)); - return; - } - */ - break; - } - - default: - break; - } -} // handleGAPEvent - /** * @brief Handle a GATT Server Event. @@ -201,12 +150,10 @@ void BLEServer::handleGAPEvent( * */ void BLEServer::handleGATTServerEvent(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t* param) { - ESP_LOGD(LOG_TAG, ">> handleGATTServerEvent: %s", BLEUtils::gattServerEventTypeToString(event).c_str()); - - // Invoke the handler for every Service we have. - m_serviceMap.handleGATTServerEvent(event, gatts_if, param); + ESP_LOGD(LOG_TAG, ">> handleGATTServerEvent: %s", + BLEUtils::gattServerEventTypeToString(event).c_str()); - switch (event) { + switch(event) { // ESP_GATTS_ADD_CHAR_EVT - Indicate that a characteristic was added to the service. // add_char: // - esp_gatt_status_t status @@ -218,20 +165,23 @@ void BLEServer::handleGATTServerEvent(esp_gatts_cb_event_t event, esp_gatt_if_t break; } // ESP_GATTS_ADD_CHAR_EVT + case ESP_GATTS_MTU_EVT: + updatePeerMTU(param->mtu.conn_id, param->mtu.mtu); + break; // ESP_GATTS_CONNECT_EVT // connect: // - uint16_t conn_id // - esp_bd_addr_t remote_bda - // - bool is_connected // case ESP_GATTS_CONNECT_EVT: { - m_connId = param->connect.conn_id; // Save the connection id. + m_connId = param->connect.conn_id; + addPeerDevice((void*)this, false, m_connId); if (m_pServerCallbacks != nullptr) { m_pServerCallbacks->onConnect(this); - m_pServerCallbacks->onConnect(this, param); + m_pServerCallbacks->onConnect(this, param); } - m_connectedCount++; // Increment the number of connected devices count. + m_connectedCount++; // Increment the number of connected devices count. break; } // ESP_GATTS_CONNECT_EVT @@ -245,7 +195,7 @@ void BLEServer::handleGATTServerEvent(esp_gatts_cb_event_t event, esp_gatt_if_t // * esp_gatt_srvc_id_t service_id // case ESP_GATTS_CREATE_EVT: { - BLEService* pService = m_serviceMap.getByUUID(param->create.service_id.id.uuid); + BLEService* pService = m_serviceMap.getByUUID(param->create.service_id.id.uuid, param->create.service_id.id.inst_id); // <--- very big bug for multi services with the same uuid m_serviceMap.setByHandle(param->create.service_handle, pService); m_semaphoreCreateEvt.give(); break; @@ -255,9 +205,9 @@ void BLEServer::handleGATTServerEvent(esp_gatts_cb_event_t event, esp_gatt_if_t // ESP_GATTS_DISCONNECT_EVT // // disconnect - // - uint16_t conn_id - // - esp_bd_addr_t remote_bda - // - bool is_connected + // - uint16_t conn_id + // - esp_bd_addr_t remote_bda + // - esp_gatt_conn_reason_t reason // // If we receive a disconnect event then invoke the callback for disconnects (if one is present). // we also want to start advertising again. @@ -267,6 +217,7 @@ void BLEServer::handleGATTServerEvent(esp_gatts_cb_event_t event, esp_gatt_if_t m_pServerCallbacks->onDisconnect(this); } startAdvertising(); //- do this with some delay from the loop() + removePeerDevice(param->disconnect.conn_id, false); break; } // ESP_GATTS_DISCONNECT_EVT @@ -316,9 +267,17 @@ void BLEServer::handleGATTServerEvent(esp_gatts_cb_event_t event, esp_gatt_if_t break; } + case ESP_GATTS_OPEN_EVT: + m_semaphoreOpenEvt.give(param->open.status); + break; + default: break; } + + // Invoke the handler for every Service we have. + m_serviceMap.handleGATTServerEvent(event, gatts_if, param); + ESP_LOGD(LOG_TAG, "<< handleGATTServerEvent"); } // handleGATTServerEvent @@ -328,7 +287,7 @@ void BLEServer::handleGATTServerEvent(esp_gatts_cb_event_t event, esp_gatt_if_t * * @return N/A */ -void BLEServer::registerApp() { +void BLEServer::registerApp(uint16_t m_appId) { ESP_LOGD(LOG_TAG, ">> registerApp - %d", m_appId); m_semaphoreRegisterAppEvt.take("registerApp"); // Take the mutex, will be released by ESP_GATTS_REG_EVT event. ::esp_ble_gatts_app_register(m_appId); @@ -355,7 +314,7 @@ void BLEServer::setCallbacks(BLEServerCallbacks* pCallbacks) { */ void BLEServer::removeService(BLEService* service) { service->stop(); - service->executeDelete(); + service->executeDelete(); m_serviceMap.removeService(service); } @@ -371,6 +330,31 @@ void BLEServer::startAdvertising() { ESP_LOGD(LOG_TAG, "<< startAdvertising"); } // 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; + } + + 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 BLEServerCallbacks::onConnect(BLEServer* pServer) { ESP_LOGD("BLEServerCallbacks", ">> onConnect(): Default"); @@ -391,4 +375,56 @@ void BLEServerCallbacks::onDisconnect(BLEServer* pServer) { ESP_LOGD("BLEServerCallbacks", "<< onDisconnect()"); } // onDisconnect +/* multi connect support */ +/* TODO do some more tweaks */ +void BLEServer::updatePeerMTU(uint16_t conn_id, uint16_t mtu) { + // set mtu in conn_status_t + const std::map::iterator it = m_connectedServersMap.find(conn_id); + if (it != m_connectedServersMap.end()) { + it->second.mtu = mtu; + std::swap(m_connectedServersMap[conn_id], it->second); + } +} + +std::map BLEServer::getPeerDevices(bool _client) { + return m_connectedServersMap; +} + + +uint16_t BLEServer::getPeerMTU(uint16_t conn_id) { + return m_connectedServersMap.find(conn_id)->second.mtu; +} + +void BLEServer::addPeerDevice(void* peer, bool _client, uint16_t conn_id) { + conn_status_t status = { + .peer_device = peer, + .connected = true, + .mtu = 23 + }; + + m_connectedServersMap.insert(std::pair(conn_id, status)); +} + +void BLEServer::removePeerDevice(uint16_t conn_id, bool _client) { + m_connectedServersMap.erase(conn_id); +} +/* multi connect support */ + +/** + * Update connection parameters can be called only after connection has been established + */ +void BLEServer::updateConnParams(esp_bd_addr_t remote_bda, uint16_t minInterval, uint16_t maxInterval, uint16_t latency, uint16_t timeout) { + esp_ble_conn_update_params_t conn_params; + memcpy(conn_params.bda, remote_bda, sizeof(esp_bd_addr_t)); + conn_params.latency = latency; + conn_params.max_int = maxInterval; // max_int = 0x20*1.25ms = 40ms + conn_params.min_int = minInterval; // min_int = 0x10*1.25ms = 20ms + conn_params.timeout = timeout; // timeout = 400*10ms = 4000ms + esp_ble_gap_update_conn_params(&conn_params); +} + +void BLEServer::disconnect(uint16_t connId){ + esp_ble_gatts_close(m_gatts_if, connId); +} + #endif // CONFIG_BT_ENABLED diff --git a/cpp_utils/BLEServer.h b/cpp_utils/BLEServer.h index 799eb25d..d2f8038d 100755 --- a/cpp_utils/BLEServer.h +++ b/cpp_utils/BLEServer.h @@ -13,6 +13,7 @@ #include #include +// #include "BLEDevice.h" #include "BLEUUID.h" #include "BLEAdvertising.h" @@ -20,8 +21,15 @@ #include "BLEService.h" #include "BLESecurity.h" #include "FreeRTOS.h" +#include "BLEAddress.h" class BLEServerCallbacks; +/* 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? + uint16_t mtu; // every peer device negotiate own mtu +} conn_status_t; /** @@ -31,26 +39,21 @@ class BLEServiceMap { public: BLEService* getByHandle(uint16_t handle); BLEService* getByUUID(const char* uuid); - BLEService* getByUUID(BLEUUID uuid); - void handleGATTServerEvent( - esp_gatts_cb_event_t event, - esp_gatt_if_t gatts_if, - esp_ble_gatts_cb_param_t* param); + BLEService* getByUUID(BLEUUID uuid, uint8_t inst_id = 0); + void handleGATTServerEvent(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t* param); void setByHandle(uint16_t handle, BLEService* service); void setByUUID(const char* uuid, BLEService* service); void setByUUID(BLEUUID uuid, BLEService* service); std::string toString(); BLEService* getFirst(); BLEService* getNext(); - void removeService(BLEService* service); + void removeService(BLEService *service); int getRegisteredServiceCount(); - private: std::map m_handleMap; std::map m_uuidMap; std::map::iterator m_iterator; - }; @@ -61,14 +64,27 @@ class BLEServer { public: uint32_t getConnectedCount(); BLEService* createService(const char* uuid); - BLEService* createService(BLEUUID uuid, uint32_t numHandles = 15, uint8_t inst_id = 0); + BLEService* createService(BLEUUID uuid, uint32_t numHandles=15, uint8_t inst_id=0); BLEAdvertising* getAdvertising(); void setCallbacks(BLEServerCallbacks* pCallbacks); void startAdvertising(); + void removeService(BLEService* service); BLEService* getServiceByUUID(const char* uuid); BLEService* getServiceByUUID(BLEUUID uuid); - void removeService(BLEService* service); - int getServiceCount(bool includeDefaultServices); + bool connect(BLEAddress address); + void disconnect(uint16_t connId); + uint16_t m_appId; + void updateConnParams(esp_bd_addr_t remote_bda, uint16_t minInterval, uint16_t maxInterval, uint16_t latency, uint16_t timeout); + + /* multi connection support */ + std::map getPeerDevices(bool client); + void addPeerDevice(void* peer, bool is_client, uint16_t conn_id); + void removePeerDevice(uint16_t conn_id, bool client); + BLEServer* getServerByConnId(uint16_t conn_id); + void updatePeerMTU(uint16_t connId, uint16_t mtu); + uint16_t getPeerMTU(uint16_t conn_id); + uint16_t getConnId(); + private: BLEServer(); @@ -76,22 +92,22 @@ class BLEServer { friend class BLECharacteristic; friend class BLEDevice; esp_ble_adv_data_t m_adv_data; - uint16_t m_appId; // BLEAdvertising m_bleAdvertising; - uint16_t m_connId; - uint32_t m_connectedCount; - uint16_t m_gatts_if; - FreeRTOS::Semaphore m_semaphoreRegisterAppEvt = FreeRTOS::Semaphore("RegisterAppEvt"); - FreeRTOS::Semaphore m_semaphoreCreateEvt = FreeRTOS::Semaphore("CreateEvt"); + uint16_t m_connId; + uint32_t m_connectedCount; + uint16_t m_gatts_if; + std::map m_connectedServersMap; + + FreeRTOS::Semaphore m_semaphoreRegisterAppEvt = FreeRTOS::Semaphore("RegisterAppEvt"); + FreeRTOS::Semaphore m_semaphoreCreateEvt = FreeRTOS::Semaphore("CreateEvt"); + FreeRTOS::Semaphore m_semaphoreOpenEvt = FreeRTOS::Semaphore("OpenEvt"); BLEServiceMap m_serviceMap; - BLEServerCallbacks* m_pServerCallbacks; + BLEServerCallbacks* m_pServerCallbacks = nullptr; void createApp(uint16_t appId); - uint16_t getConnId(); uint16_t getGattsIf(); void handleGATTServerEvent(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param); - void registerApp(); - void handleGAPEvent(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t* param); + void registerApp(uint16_t); }; // BLEServer @@ -109,7 +125,7 @@ class BLEServerCallbacks { * @param [in] pServer A reference to the %BLE server that received the client connection. */ virtual void onConnect(BLEServer* pServer); - virtual void onConnect(BLEServer* pServer, esp_ble_gatts_cb_param_t* param); + virtual void onConnect(BLEServer* pServer, esp_ble_gatts_cb_param_t *param); /** * @brief Handle an existing client disconnection. * diff --git a/cpp_utils/BLEService.cpp b/cpp_utils/BLEService.cpp index 68019608..3034cf18 100644 --- a/cpp_utils/BLEService.cpp +++ b/cpp_utils/BLEService.cpp @@ -11,7 +11,6 @@ #if defined(CONFIG_BT_ENABLED) #include #include -#include #include #include @@ -22,13 +21,16 @@ #include "BLEUtils.h" #include "GeneralUtils.h" -#ifdef ARDUINO_ARCH_ESP32 +#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) #include "esp32-hal-log.h" +#define LOG_TAG "" +#else +#include "esp_log.h" +static const char* LOG_TAG = "BLEService"; // Tag for logging. #endif #define NULL_HANDLE (0xffff) -static const char* LOG_TAG = "BLEService"; // Tag for logging. /** * @brief Construct an instance of the BLEService @@ -62,18 +64,13 @@ BLEService::BLEService(BLEUUID uuid, uint16_t numHandles) { */ void BLEService::executeCreate(BLEServer* pServer) { - //ESP_LOGD(LOG_TAG, ">> executeCreate() - Creating service (esp_ble_gatts_create_service) service uuid: %s", getUUID().toString().c_str()); - //getUUID(); // Needed for a weird bug fix - //char x[1000]; - //memcpy(x, &m_uuid, sizeof(m_uuid)); - //char x[10]; - //memcpy(x, &deleteMe, 10); + ESP_LOGD(LOG_TAG, ">> executeCreate() - Creating service (esp_ble_gatts_create_service) service uuid: %s", getUUID().toString().c_str()); m_pServer = pServer; m_semaphoreCreateEvt.take("executeCreate"); // Take the mutex and release at event ESP_GATTS_CREATE_EVT esp_gatt_srvc_id_t srvc_id; srvc_id.is_primary = true; - srvc_id.id.inst_id = m_id; + srvc_id.id.inst_id = m_instId; srvc_id.id.uuid = *m_uuid.getNative(); esp_err_t errRc = ::esp_ble_gatts_create_service(getServer()->getGattsIf(), &srvc_id, m_numHandles); // The maximum number of handles associated with the service. @@ -137,10 +134,10 @@ BLEUUID BLEService::getUUID() { * @return Start the service. */ void BLEService::start() { - // We ask the BLE runtime to start the service and then create each of the characteristics. - // We start the service through its local handle which was returned in the ESP_GATTS_CREATE_EVT event - // obtained as a result of calling esp_ble_gatts_create_service(). - // +// We ask the BLE runtime to start the service and then create each of the characteristics. +// We start the service through its local handle which was returned in the ESP_GATTS_CREATE_EVT event +// obtained as a result of calling esp_ble_gatts_create_service(). +// ESP_LOGD(LOG_TAG, ">> start(): Starting service (esp_ble_gatts_start_service): %s", toString().c_str()); if (m_handle == NULL_HANDLE) { ESP_LOGE(LOG_TAG, "<< !!! We attempted to start a service but don't know its handle!"); @@ -174,9 +171,9 @@ void BLEService::start() { * @brief Stop the service. */ void BLEService::stop() { - // We ask the BLE runtime to start the service and then create each of the characteristics. - // We start the service through its local handle which was returned in the ESP_GATTS_CREATE_EVT event - // obtained as a result of calling esp_ble_gatts_create_service(). +// We ask the BLE runtime to start the service and then create each of the characteristics. +// We start the service through its local handle which was returned in the ESP_GATTS_CREATE_EVT event +// obtained as a result of calling esp_ble_gatts_create_service(). ESP_LOGD(LOG_TAG, ">> stop(): Stopping service (esp_ble_gatts_stop_service): %s", toString().c_str()); if (m_handle == NULL_HANDLE) { ESP_LOGE(LOG_TAG, "<< !!! We attempted to stop a service but don't know its handle!"); @@ -228,6 +225,7 @@ void BLEService::addCharacteristic(BLECharacteristic* 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). + ESP_LOGD(LOG_TAG, ">> addCharacteristic()"); ESP_LOGD(LOG_TAG, "Adding characteristic: uuid=%s to service: %s", pCharacteristic->getUUID().toString().c_str(), @@ -256,7 +254,7 @@ void BLEService::addCharacteristic(BLECharacteristic* pCharacteristic) { BLECharacteristic* BLEService::createCharacteristic(const char* uuid, uint32_t properties) { return createCharacteristic(BLEUUID(uuid), properties); } - + /** * @brief Create a new BLE Characteristic associated with this service. @@ -296,7 +294,6 @@ void BLEService::handleGATTServerEvent(esp_gatts_cb_event_t event, esp_gatt_if_t } pCharacteristic->setHandle(param->add_char.attr_handle); m_characteristicMap.setByHandle(param->add_char.attr_handle, pCharacteristic); - //ESP_LOGD(tag, "Characteristic map: %s", m_characteristicMap.toString().c_str()); break; } // Reached the correct service. break; @@ -342,7 +339,7 @@ void BLEService::handleGATTServerEvent(esp_gatts_cb_event_t event, esp_gatt_if_t // * - bool is_primary // case ESP_GATTS_CREATE_EVT: { - if (getUUID().equals(BLEUUID(param->create.service_id.id.uuid)) && m_id == param->create.service_id.id.inst_id) { + if (getUUID().equals(BLEUUID(param->create.service_id.id.uuid)) && m_instId == param->create.service_id.id.inst_id) { setHandle(param->create.service_handle); m_semaphoreCreateEvt.give(); } diff --git a/cpp_utils/BLEService.h b/cpp_utils/BLEService.h index 711ac707..b42d57f2 100644 --- a/cpp_utils/BLEService.h +++ b/cpp_utils/BLEService.h @@ -27,7 +27,7 @@ class BLECharacteristicMap { void setByUUID(BLECharacteristic* pCharacteristic, const char* uuid); void setByUUID(BLECharacteristic* pCharacteristic, BLEUUID uuid); void setByHandle(uint16_t handle, BLECharacteristic* pCharacteristic); - BLECharacteristic* getByUUID(const char* uuid); + BLECharacteristic* getByUUID(const char* uuid); BLECharacteristic* getByUUID(BLEUUID uuid); BLECharacteristic* getByHandle(uint16_t handle); BLECharacteristic* getFirst(); @@ -53,16 +53,16 @@ class BLEService { BLECharacteristic* createCharacteristic(BLEUUID uuid, uint32_t properties); void dump(); void executeCreate(BLEServer* pServer); - void executeDelete(); + void executeDelete(); BLECharacteristic* getCharacteristic(const char* uuid); BLECharacteristic* getCharacteristic(BLEUUID uuid); BLEUUID getUUID(); BLEServer* getServer(); void start(); - void stop(); + void stop(); std::string toString(); uint16_t getHandle(); - uint8_t m_id = 0; + uint8_t m_instId = 0; private: BLEService(const char* uuid, uint16_t numHandles); @@ -75,8 +75,8 @@ class BLEService { BLECharacteristicMap m_characteristicMap; uint16_t m_handle; - BLECharacteristic* m_lastCreatedCharacteristic; - BLEServer* m_pServer; + BLECharacteristic* m_lastCreatedCharacteristic = nullptr; + BLEServer* m_pServer = nullptr; BLEUUID m_uuid; FreeRTOS::Semaphore m_semaphoreCreateEvt = FreeRTOS::Semaphore("CreateEvt"); @@ -87,10 +87,9 @@ class BLEService { uint16_t m_numHandles; BLECharacteristic* getLastCreatedCharacteristic(); - void handleGATTServerEvent(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t* param); + void handleGATTServerEvent(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t* param); void setHandle(uint16_t handle); //void setService(esp_gatt_srvc_id_t srvc_id); - }; // BLEService diff --git a/cpp_utils/BLEServiceMap.cpp b/cpp_utils/BLEServiceMap.cpp index aa371f47..cf4f75f4 100755 --- a/cpp_utils/BLEServiceMap.cpp +++ b/cpp_utils/BLEServiceMap.cpp @@ -17,15 +17,15 @@ * @return The characteristic. */ BLEService* BLEServiceMap::getByUUID(const char* uuid) { - return getByUUID(BLEUUID(uuid)); + return getByUUID(BLEUUID(uuid)); } - + /** * @brief Return the service by UUID. * @param [in] UUID The UUID to look up the service. * @return The characteristic. */ -BLEService* BLEServiceMap::getByUUID(BLEUUID uuid) { +BLEService* BLEServiceMap::getByUUID(BLEUUID uuid, uint8_t inst_id) { for (auto &myPair : m_uuidMap) { if (myPair.first->getUUID().equals(uuid)) { return myPair.first; @@ -52,9 +52,8 @@ BLEService* BLEServiceMap::getByHandle(uint16_t handle) { * @param [in] characteristic The service to cache. * @return N/A. */ -void BLEServiceMap::setByUUID(BLEUUID uuid, - BLEService *service) { - m_uuidMap.insert(std::pair(service, uuid.toString())); +void BLEServiceMap::setByUUID(BLEUUID uuid, BLEService* service) { + m_uuidMap.insert(std::pair(service, uuid.toString())); } // setByUUID @@ -64,9 +63,8 @@ void BLEServiceMap::setByUUID(BLEUUID uuid, * @param [in] service The service to cache. * @return N/A. */ -void BLEServiceMap::setByHandle(uint16_t handle, - BLEService* service) { - m_handleMap.insert(std::pair(handle, service)); +void BLEServiceMap::setByHandle(uint16_t handle, BLEService* service) { + m_handleMap.insert(std::pair(handle, service)); } // setByHandle @@ -86,7 +84,7 @@ std::string BLEServiceMap::toString() { void BLEServiceMap::handleGATTServerEvent( esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, - esp_ble_gatts_cb_param_t *param) { + esp_ble_gatts_cb_param_t* param) { // Invoke the handler for every Service we have. for (auto &myPair : m_uuidMap) { myPair.first->handleGATTServerEvent(event, gatts_if, param); @@ -99,9 +97,7 @@ void BLEServiceMap::handleGATTServerEvent( */ BLEService* BLEServiceMap::getFirst() { m_iterator = m_uuidMap.begin(); - if (m_iterator == m_uuidMap.end()) { - return nullptr; - } + if (m_iterator == m_uuidMap.end()) return nullptr; BLEService* pRet = m_iterator->first; m_iterator++; return pRet; @@ -112,9 +108,7 @@ BLEService* BLEServiceMap::getFirst() { * @return The next service in the map. */ BLEService* BLEServiceMap::getNext() { - if (m_iterator == m_uuidMap.end()) { - return nullptr; - } + if (m_iterator == m_uuidMap.end()) return nullptr; BLEService* pRet = m_iterator->first; m_iterator++; return pRet; @@ -124,7 +118,7 @@ BLEService* BLEServiceMap::getNext() { * @brief Removes service from maps. * @return N/A. */ -void BLEServiceMap::removeService(BLEService *service){ +void BLEServiceMap::removeService(BLEService* service) { m_handleMap.erase(service->getHandle()); m_uuidMap.erase(service); } // removeService diff --git a/cpp_utils/BLEUUID.cpp b/cpp_utils/BLEUUID.cpp index 512c24ea..4ddf8fc2 100644 --- a/cpp_utils/BLEUUID.cpp +++ b/cpp_utils/BLEUUID.cpp @@ -6,7 +6,6 @@ */ #include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) -#include #include #include #include @@ -14,12 +13,16 @@ #include #include #include "BLEUUID.h" -static const char* LOG_TAG = "BLEUUID"; -#ifdef ARDUINO_ARCH_ESP32 +#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) #include "esp32-hal-log.h" +#define LOG_TAG "" +#else +#include "esp_log.h" +static const char* LOG_TAG = "BLEUUID"; #endif + /** * @brief Copy memory from source to target but in reverse order. * @@ -70,46 +73,54 @@ static void memrcpy(uint8_t* target, uint8_t* source, uint32_t size) { */ BLEUUID::BLEUUID(std::string value) { m_valueSet = true; - if (value.length() == 2) { + if (value.length() == 4) { m_uuid.len = ESP_UUID_LEN_16; - m_uuid.uuid.uuid16 = value[0] | (value[1] << 8); + m_uuid.uuid.uuid16 = 0; + for(int i=0;i '9') MSB -= 7; + if(LSB > '9') LSB -= 7; + m_uuid.uuid.uuid16 += (((MSB&0x0F) <<4) | (LSB & 0x0F))<<(2-i)*4; + i+=2; + } } - else if (value.length() == 4) { + else if (value.length() == 8) { m_uuid.len = ESP_UUID_LEN_32; - m_uuid.uuid.uuid32 = value[0] | (value[1] << 8) | (value[2] << 16) | (value[3] << 24); + m_uuid.uuid.uuid32 = 0; + for(int i=0;i '9') MSB -= 7; + if(LSB > '9') LSB -= 7; + m_uuid.uuid.uuid32 += (((MSB&0x0F) <<4) | (LSB & 0x0F))<<(6-i)*4; + i+=2; + } } - else if (value.length() == 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.len = ESP_UUID_LEN_128; - memrcpy(m_uuid.uuid.uuid128, (uint8_t*) value.data(), 16); + memrcpy(m_uuid.uuid.uuid128, (uint8_t*)value.data(), 16); } 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.len = ESP_UUID_LEN_128; - int vals[16]; - sscanf(value.c_str(), "%2x%2x%2x%2x-%2x%2x-%2x%2x-%2x%2x-%2x%2x%2x%2x%2x%2x", - &vals[15], - &vals[14], - &vals[13], - &vals[12], - &vals[11], - &vals[10], - &vals[9], - &vals[8], - &vals[7], - &vals[6], - &vals[5], - &vals[4], - &vals[3], - &vals[2], - &vals[1], - &vals[0] - ); - - for (int i = 0; i < 16; i++) { - m_uuid.uuid.uuid128[i] = vals[i]; + int n = 0; + for(int i=0;i '9') MSB -= 7; + if(LSB > '9') LSB -= 7; + m_uuid.uuid.uuid128[15-n++] = ((MSB&0x0F) <<4) | (LSB & 0x0F); + i+=2; } - } else { + } + else { ESP_LOGE(LOG_TAG, "ERROR: UUID value not 2, 4, 16 or 36 bytes"); m_valueSet = false; } @@ -249,7 +260,7 @@ BLEUUID BLEUUID::fromString(std::string _uuid) { } uint8_t len = _uuid.length() - start; // Calculate the length of the string we are going to use. - if (len == 4) { + if(len == 4) { uint16_t x = strtoul(_uuid.substr(start, len).c_str(), NULL, 16); return BLEUUID(x); } else if (len == 8) { @@ -269,7 +280,7 @@ BLEUUID BLEUUID::fromString(std::string _uuid) { */ esp_bt_uuid_t* BLEUUID::getNative() { //ESP_LOGD(TAG, ">> getNative()") - if (!m_valueSet) { + if (m_valueSet == false) { ESP_LOGD(LOG_TAG, "<< Return of un-initialized UUID!"); return nullptr; } diff --git a/cpp_utils/BLEUUID.h b/cpp_utils/BLEUUID.h index e81dd130..700739be 100644 --- a/cpp_utils/BLEUUID.h +++ b/cpp_utils/BLEUUID.h @@ -32,8 +32,8 @@ class BLEUUID { static BLEUUID fromString(std::string uuid); // Create a BLEUUID from a string private: - esp_bt_uuid_t m_uuid; // The underlying UUID structure that this class wraps. - bool m_valueSet; // Is there a value set for this instance. + esp_bt_uuid_t m_uuid; // The underlying UUID structure that this class wraps. + bool m_valueSet = false; // Is there a value set for this instance. }; // BLEUUID #endif /* CONFIG_BT_ENABLED */ #endif /* COMPONENTS_CPP_UTILS_BLEUUID_H_ */ diff --git a/cpp_utils/BLEUtils.cpp b/cpp_utils/BLEUtils.cpp index 0dd5f461..a9b735df 100644 --- a/cpp_utils/BLEUtils.cpp +++ b/cpp_utils/BLEUtils.cpp @@ -41,6 +41,7 @@ typedef struct { } member_t; static const member_t members_ids[] = { +#if CONFIG_LOG_DEFAULT_LEVEL > 4 {0xFE08, "Microsoft"}, {0xFE09, "Pillsy, Inc."}, {0xFE0A, "ruwido austria gmbh"}, @@ -290,6 +291,7 @@ static const member_t members_ids[] = { {0xFEFE, "GN ReSound A/S"}, {0xFEFF, "GN Netcom"}, {0xFFFF, "Reserved"}, /*for testing purposes only*/ +#endif {0, "" } }; @@ -299,6 +301,7 @@ typedef struct { } gattdescriptor_t; static const gattdescriptor_t g_descriptor_ids[] = { +#if CONFIG_LOG_DEFAULT_LEVEL > 4 {0x2905,"Characteristic Aggregate Format"}, {0x2900,"Characteristic Extended Properties"}, {0x2904,"Characteristic Presentation Format"}, @@ -314,6 +317,7 @@ static const gattdescriptor_t g_descriptor_ids[] = { {0x290E,"Time Trigger Setting"}, {0x2906,"Valid Range"}, {0x290A,"Value Trigger Setting"}, +#endif { 0, "" } }; @@ -323,6 +327,7 @@ typedef struct { } characteristicMap_t; static const characteristicMap_t g_characteristicsMappings[] = { +#if CONFIG_LOG_DEFAULT_LEVEL > 4 {0x2A7E,"Aerobic Heart Rate Lower Limit"}, {0x2A84,"Aerobic Heart Rate Upper Limit"}, {0x2A7F,"Aerobic Threshold"}, @@ -539,6 +544,7 @@ static const characteristicMap_t g_characteristicsMappings[] = { {0x2A9D,"Weight Measurement"}, {0x2A9E,"Weight Scale Feature"}, {0x2A79,"Wind Chill"}, +#endif {0, ""} }; @@ -556,6 +562,7 @@ typedef struct { * Definition of the service ids to names that we know about. */ static const gattService_t g_gattServices[] = { +#if CONFIG_LOG_DEFAULT_LEVEL > 4 {"Alert Notification Service", "org.bluetooth.service.alert_notification", 0x1811}, {"Automation IO", "org.bluetooth.service.automation_io", 0x1815 }, {"Battery Service","org.bluetooth.service.battery_service", 0x180F}, @@ -591,6 +598,7 @@ static const gattService_t g_gattServices[] = { {"Tx Power", "org.bluetooth.service.tx_power", 0x1804}, {"User Data", "org.bluetooth.service.user_data", 0x181C}, {"Weight Scale", "org.bluetooth.service.weight_scale", 0x181D}, +#endif {"", "", 0 } }; @@ -730,7 +738,7 @@ const char* BLEUtils::advTypeToString(uint8_t advType) { case ESP_BLE_AD_MANUFACTURER_SPECIFIC_TYPE: // 0xff return "ESP_BLE_AD_MANUFACTURER_SPECIFIC_TYPE"; default: - ESP_LOGD(LOG_TAG, " adv data type: 0x%x", advType); + ESP_LOGV(LOG_TAG, " adv data type: 0x%x", advType); return ""; } // End switch } // advTypeToString @@ -815,39 +823,30 @@ std::string BLEUtils::gattCloseReasonToString(esp_gatt_conn_reason_t reason) { case ESP_GATT_CONN_UNKNOWN: { return "ESP_GATT_CONN_UNKNOWN"; } - case ESP_GATT_CONN_L2C_FAILURE: { return "ESP_GATT_CONN_L2C_FAILURE"; } - case ESP_GATT_CONN_TIMEOUT: { return "ESP_GATT_CONN_TIMEOUT"; } - case ESP_GATT_CONN_TERMINATE_PEER_USER: { return "ESP_GATT_CONN_TERMINATE_PEER_USER"; } - case ESP_GATT_CONN_TERMINATE_LOCAL_HOST: { return "ESP_GATT_CONN_TERMINATE_LOCAL_HOST"; } - case ESP_GATT_CONN_FAIL_ESTABLISH: { return "ESP_GATT_CONN_FAIL_ESTABLISH"; } - case ESP_GATT_CONN_LMP_TIMEOUT: { return "ESP_GATT_CONN_LMP_TIMEOUT"; } - case ESP_GATT_CONN_CONN_CANCEL: { return "ESP_GATT_CONN_CONN_CANCEL"; } - case ESP_GATT_CONN_NONE: { return "ESP_GATT_CONN_NONE"; } - default: { return "Unknown"; } @@ -940,7 +939,7 @@ std::string BLEUtils::gattClientEventTypeToString(esp_gattc_cb_event_t eventType case ESP_GATTC_WRITE_DESCR_EVT: return "ESP_GATTC_WRITE_DESCR_EVT"; default: - ESP_LOGW(LOG_TAG, "Unknown GATT Client event type: %d", eventType); + ESP_LOGV(LOG_TAG, "Unknown GATT Client event type: %d", eventType); return "Unknown"; } } // gattClientEventTypeToString @@ -1034,13 +1033,14 @@ const char* BLEUtils::devTypeToString(esp_bt_dev_type_t type) { void BLEUtils::dumpGapEvent( esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t* param) { - ESP_LOGD(LOG_TAG, "Received a GAP event: %s", gapEventToString(event)); + ESP_LOGV(LOG_TAG, "Received a GAP event: %s", gapEventToString(event)); switch (event) { +#if CONFIG_LOG_DEFAULT_LEVEL > 4 // ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT // adv_data_cmpl // - esp_bt_status_t case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT: { - ESP_LOGD(LOG_TAG, "[status: %d]", param->adv_data_cmpl.status); + ESP_LOGV(LOG_TAG, "[status: %d]", param->adv_data_cmpl.status); break; } // ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT @@ -1049,7 +1049,7 @@ void BLEUtils::dumpGapEvent( // adv_data_raw_cmpl // - esp_bt_status_t status case ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT: { - ESP_LOGD(LOG_TAG, "[status: %d]", param->adv_data_raw_cmpl.status); + ESP_LOGV(LOG_TAG, "[status: %d]", param->adv_data_raw_cmpl.status); break; } // ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT @@ -1058,7 +1058,7 @@ void BLEUtils::dumpGapEvent( // adv_start_cmpl // - esp_bt_status_t status case ESP_GAP_BLE_ADV_START_COMPLETE_EVT: { - ESP_LOGD(LOG_TAG, "[status: %d]", param->adv_start_cmpl.status); + ESP_LOGV(LOG_TAG, "[status: %d]", param->adv_start_cmpl.status); break; } // ESP_GAP_BLE_ADV_START_COMPLETE_EVT @@ -1067,7 +1067,7 @@ void BLEUtils::dumpGapEvent( // adv_stop_cmpl // - esp_bt_status_t status case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT: { - ESP_LOGD(LOG_TAG, "[status: %d]", param->adv_stop_cmpl.status); + ESP_LOGV(LOG_TAG, "[status: %d]", param->adv_stop_cmpl.status); break; } // ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT @@ -1082,7 +1082,7 @@ void BLEUtils::dumpGapEvent( // - esp_bd_addr_type_t addr_type // - esp_bt_dev_type_t dev_type case ESP_GAP_BLE_AUTH_CMPL_EVT: { - ESP_LOGD(LOG_TAG, "[bd_addr: %s, key_present: %d, key: ***, key_type: %d, success: %d, fail_reason: %d, addr_type: ***, dev_type: %s]", + ESP_LOGV(LOG_TAG, "[bd_addr: %s, key_present: %d, key: ***, key_type: %d, success: %d, fail_reason: %d, addr_type: ***, dev_type: %s]", BLEAddress(param->ble_security.auth_cmpl.bd_addr).toString().c_str(), param->ble_security.auth_cmpl.key_present, param->ble_security.auth_cmpl.key_type, @@ -1098,7 +1098,7 @@ void BLEUtils::dumpGapEvent( // clear_bond_dev_cmpl // - esp_bt_status_t status case ESP_GAP_BLE_CLEAR_BOND_DEV_COMPLETE_EVT: { - ESP_LOGD(LOG_TAG, "[status: %d]", param->clear_bond_dev_cmpl.status); + ESP_LOGV(LOG_TAG, "[status: %d]", param->clear_bond_dev_cmpl.status); break; } // ESP_GAP_BLE_CLEAR_BOND_DEV_COMPLETE_EVT @@ -1114,7 +1114,7 @@ void BLEUtils::dumpGapEvent( // ESP_GAP_BLE_NC_REQ_EVT case ESP_GAP_BLE_NC_REQ_EVT: { - ESP_LOGD(LOG_TAG, "[bd_addr: %s, passkey: %d]", + ESP_LOGV(LOG_TAG, "[bd_addr: %s, passkey: %d]", BLEAddress(param->ble_security.key_notif.bd_addr).toString().c_str(), param->ble_security.key_notif.passkey); break; @@ -1127,7 +1127,7 @@ void BLEUtils::dumpGapEvent( // - int8_t rssi // - esp_bd_addr_t remote_addr case ESP_GAP_BLE_READ_RSSI_COMPLETE_EVT: { - ESP_LOGD(LOG_TAG, "[status: %d, rssi: %d, remote_addr: %s]", + ESP_LOGV(LOG_TAG, "[status: %d, rssi: %d, remote_addr: %s]", param->read_rssi_cmpl.status, param->read_rssi_cmpl.rssi, BLEAddress(param->read_rssi_cmpl.remote_addr).toString().c_str() @@ -1140,7 +1140,7 @@ void BLEUtils::dumpGapEvent( // scan_param_cmpl. // - esp_bt_status_t status case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT: { - ESP_LOGD(LOG_TAG, "[status: %d]", param->scan_param_cmpl.status); + ESP_LOGV(LOG_TAG, "[status: %d]", param->scan_param_cmpl.status); break; } // ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT @@ -1161,7 +1161,7 @@ void BLEUtils::dumpGapEvent( case ESP_GAP_BLE_SCAN_RESULT_EVT: { switch (param->scan_rst.search_evt) { case ESP_GAP_SEARCH_INQ_RES_EVT: { - ESP_LOGD(LOG_TAG, "search_evt: %s, bda: %s, dev_type: %s, ble_addr_type: %s, ble_evt_type: %s, rssi: %d, ble_adv: ??, flag: %d (%s), num_resps: %d, adv_data_len: %d, scan_rsp_len: %d", + ESP_LOGV(LOG_TAG, "search_evt: %s, bda: %s, dev_type: %s, ble_addr_type: %s, ble_evt_type: %s, rssi: %d, ble_adv: ??, flag: %d (%s), num_resps: %d, adv_data_len: %d, scan_rsp_len: %d", searchEventTypeToString(param->scan_rst.search_evt), BLEAddress(param->scan_rst.bda).toString().c_str(), devTypeToString(param->scan_rst.dev_type), @@ -1178,7 +1178,7 @@ void BLEUtils::dumpGapEvent( } // ESP_GAP_SEARCH_INQ_RES_EVT default: { - ESP_LOGD(LOG_TAG, "search_evt: %s",searchEventTypeToString(param->scan_rst.search_evt)); + ESP_LOGV(LOG_TAG, "search_evt: %s",searchEventTypeToString(param->scan_rst.search_evt)); break; } } @@ -1190,13 +1190,13 @@ void BLEUtils::dumpGapEvent( // scan_rsp_data_cmpl // - esp_bt_status_t status case ESP_GAP_BLE_SCAN_RSP_DATA_SET_COMPLETE_EVT: { - ESP_LOGD(LOG_TAG, "[status: %d]", param->scan_rsp_data_cmpl.status); + ESP_LOGV(LOG_TAG, "[status: %d]", param->scan_rsp_data_cmpl.status); break; } // ESP_GAP_BLE_SCAN_RSP_DATA_SET_COMPLETE_EVT // ESP_GAP_BLE_SCAN_RSP_DATA_RAW_SET_COMPLETE_EVT case ESP_GAP_BLE_SCAN_RSP_DATA_RAW_SET_COMPLETE_EVT: { - ESP_LOGD(LOG_TAG, "[status: %d]", param->scan_rsp_data_raw_cmpl.status); + ESP_LOGV(LOG_TAG, "[status: %d]", param->scan_rsp_data_raw_cmpl.status); break; } // ESP_GAP_BLE_SCAN_RSP_DATA_RAW_SET_COMPLETE_EVT @@ -1205,7 +1205,7 @@ void BLEUtils::dumpGapEvent( // scan_start_cmpl // - esp_bt_status_t status case ESP_GAP_BLE_SCAN_START_COMPLETE_EVT: { - ESP_LOGD(LOG_TAG, "[status: %d]", param->scan_start_cmpl.status); + ESP_LOGV(LOG_TAG, "[status: %d]", param->scan_start_cmpl.status); break; } // ESP_GAP_BLE_SCAN_START_COMPLETE_EVT @@ -1214,7 +1214,7 @@ void BLEUtils::dumpGapEvent( // scan_stop_cmpl // - esp_bt_status_t status case ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT: { - ESP_LOGD(LOG_TAG, "[status: %d]", param->scan_stop_cmpl.status); + ESP_LOGV(LOG_TAG, "[status: %d]", param->scan_stop_cmpl.status); break; } // ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT @@ -1229,7 +1229,7 @@ void BLEUtils::dumpGapEvent( // - uint16_t conn_int // - uint16_t timeout case ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT: { - ESP_LOGD(LOG_TAG, "[status: %d, bd_addr: %s, min_int: %d, max_int: %d, latency: %d, conn_int: %d, timeout: %d]", + ESP_LOGV(LOG_TAG, "[status: %d, bd_addr: %s, min_int: %d, max_int: %d, latency: %d, conn_int: %d, timeout: %d]", param->update_conn_params.status, BLEAddress(param->update_conn_params.bda).toString().c_str(), param->update_conn_params.min_int, @@ -1243,12 +1243,12 @@ void BLEUtils::dumpGapEvent( // ESP_GAP_BLE_SEC_REQ_EVT case ESP_GAP_BLE_SEC_REQ_EVT: { - ESP_LOGD(LOG_TAG, "[bd_addr: %s]", BLEAddress(param->ble_security.ble_req.bd_addr).toString().c_str()); + ESP_LOGV(LOG_TAG, "[bd_addr: %s]", BLEAddress(param->ble_security.ble_req.bd_addr).toString().c_str()); break; } // ESP_GAP_BLE_SEC_REQ_EVT - +#endif default: { - ESP_LOGD(LOG_TAG, "*** dumpGapEvent: Logger not coded ***"); + ESP_LOGV(LOG_TAG, "*** dumpGapEvent: Logger not coded ***"); break; } // default } // switch @@ -1267,8 +1267,9 @@ void BLEUtils::dumpGattClientEvent( esp_ble_gattc_cb_param_t* evtParam) { //esp_ble_gattc_cb_param_t* evtParam = (esp_ble_gattc_cb_param_t*) param; - ESP_LOGD(LOG_TAG, "GATT Event: %s", BLEUtils::gattClientEventTypeToString(event).c_str()); + ESP_LOGV(LOG_TAG, "GATT Event: %s", BLEUtils::gattClientEventTypeToString(event).c_str()); switch (event) { +#if CONFIG_LOG_DEFAULT_LEVEL > 4 // ESP_GATTC_CLOSE_EVT // // close: @@ -1277,7 +1278,7 @@ void BLEUtils::dumpGattClientEvent( // - esp_bd_addr_t remote_bda // - esp_gatt_conn_reason_t reason case ESP_GATTC_CLOSE_EVT: { - ESP_LOGD(LOG_TAG, "[status: %s, reason:%s, conn_id: %d]", + ESP_LOGV(LOG_TAG, "[status: %s, reason:%s, conn_id: %d]", BLEUtils::gattStatusToString(evtParam->close.status).c_str(), BLEUtils::gattCloseReasonToString(evtParam->close.reason).c_str(), evtParam->close.conn_id); @@ -1291,7 +1292,7 @@ void BLEUtils::dumpGattClientEvent( // - uint16_t conn_id // - esp_bd_addr_t remote_bda case ESP_GATTC_CONNECT_EVT: { - ESP_LOGD(LOG_TAG, "[conn_id: %d, remote_bda: %s]", + ESP_LOGV(LOG_TAG, "[conn_id: %d, remote_bda: %s]", evtParam->connect.conn_id, BLEAddress(evtParam->connect.remote_bda).toString().c_str() ); @@ -1305,7 +1306,7 @@ void BLEUtils::dumpGattClientEvent( // - uint16_t conn_id // - esp_bd_addr_t remote_bda case ESP_GATTC_DISCONNECT_EVT: { - ESP_LOGD(LOG_TAG, "[reason: %s, conn_id: %d, remote_bda: %s]", + ESP_LOGV(LOG_TAG, "[reason: %s, conn_id: %d, remote_bda: %s]", BLEUtils::gattCloseReasonToString(evtParam->disconnect.reason).c_str(), evtParam->disconnect.conn_id, BLEAddress(evtParam->disconnect.remote_bda).toString().c_str() @@ -1331,7 +1332,7 @@ void BLEUtils::dumpGattClientEvent( if (evtParam->get_char.char_id.uuid.len == ESP_UUID_LEN_16) { description = BLEUtils::gattCharacteristicUUIDToString(evtParam->get_char.char_id.uuid.uuid.uuid16); } - ESP_LOGD(LOG_TAG, "[status: %s, conn_id: %d, srvc_id: %s, char_id: %s [description: %s]\nchar_prop: %s]", + ESP_LOGV(LOG_TAG, "[status: %s, conn_id: %d, srvc_id: %s, char_id: %s [description: %s]\nchar_prop: %s]", BLEUtils::gattStatusToString(evtParam->get_char.status).c_str(), evtParam->get_char.conn_id, BLEUtils::gattServiceIdToString(evtParam->get_char.srvc_id).c_str(), @@ -1340,7 +1341,7 @@ void BLEUtils::dumpGattClientEvent( BLEUtils::characteristicPropertiesToString(evtParam->get_char.char_prop).c_str() ); } else { - ESP_LOGD(LOG_TAG, "[status: %s, conn_id: %d, srvc_id: %s]", + ESP_LOGV(LOG_TAG, "[status: %s, conn_id: %d, srvc_id: %s]", BLEUtils::gattStatusToString(evtParam->get_char.status).c_str(), evtParam->get_char.conn_id, BLEUtils::gattServiceIdToString(evtParam->get_char.srvc_id).c_str() @@ -1361,7 +1362,7 @@ void BLEUtils::dumpGattClientEvent( // bool is_notify // case ESP_GATTC_NOTIFY_EVT: { - ESP_LOGD(LOG_TAG, "[conn_id: %d, remote_bda: %s, handle: %d 0x%.2x, value_len: %d, is_notify: %d]", + ESP_LOGV(LOG_TAG, "[conn_id: %d, remote_bda: %s, handle: %d 0x%.2x, value_len: %d, is_notify: %d]", evtParam->notify.conn_id, BLEAddress(evtParam->notify.remote_bda).toString().c_str(), evtParam->notify.handle, @@ -1381,7 +1382,7 @@ void BLEUtils::dumpGattClientEvent( // - uint16_t mtu // case ESP_GATTC_OPEN_EVT: { - ESP_LOGD(LOG_TAG, "[status: %s, conn_id: %d, remote_bda: %s, mtu: %d]", + ESP_LOGV(LOG_TAG, "[status: %s, conn_id: %d, remote_bda: %s, mtu: %d]", BLEUtils::gattStatusToString(evtParam->open.status).c_str(), evtParam->open.conn_id, BLEAddress(evtParam->open.remote_bda).toString().c_str(), @@ -1401,7 +1402,7 @@ void BLEUtils::dumpGattClientEvent( // uint16_t value_type // uint16_t value_len case ESP_GATTC_READ_CHAR_EVT: { - ESP_LOGD(LOG_TAG, "[status: %s, conn_id: %d, handle: %d 0x%.2x, value_len: %d]", + ESP_LOGV(LOG_TAG, "[status: %s, conn_id: %d, handle: %d 0x%.2x, value_len: %d]", BLEUtils::gattStatusToString(evtParam->read.status).c_str(), evtParam->read.conn_id, evtParam->read.handle, @@ -1412,7 +1413,7 @@ void BLEUtils::dumpGattClientEvent( GeneralUtils::hexDump(evtParam->read.value, evtParam->read.value_len); /* char* pHexData = BLEUtils::buildHexData(nullptr, evtParam->read.value, evtParam->read.value_len); - ESP_LOGD(LOG_TAG, "value: %s \"%s\"", pHexData, BLEUtils::buildPrintData(evtParam->read.value, evtParam->read.value_len).c_str()); + ESP_LOGV(LOG_TAG, "value: %s \"%s\"", pHexData, BLEUtils::buildPrintData(evtParam->read.value, evtParam->read.value_len).c_str()); free(pHexData); */ } @@ -1425,7 +1426,7 @@ void BLEUtils::dumpGattClientEvent( // - esp_gatt_status_t status // - uint16_t app_id case ESP_GATTC_REG_EVT: { - ESP_LOGD(LOG_TAG, "[status: %s, app_id: 0x%x]", + ESP_LOGV(LOG_TAG, "[status: %s, app_id: 0x%x]", BLEUtils::gattStatusToString(evtParam->reg.status).c_str(), evtParam->reg.app_id); break; @@ -1437,7 +1438,7 @@ void BLEUtils::dumpGattClientEvent( // - esp_gatt_status_t status // - uint16_t handle case ESP_GATTC_REG_FOR_NOTIFY_EVT: { - ESP_LOGD(LOG_TAG, "[status: %s, handle: %d 0x%.2x]", + ESP_LOGV(LOG_TAG, "[status: %s, handle: %d 0x%.2x]", BLEUtils::gattStatusToString(evtParam->reg_for_notify.status).c_str(), evtParam->reg_for_notify.handle, evtParam->reg_for_notify.handle @@ -1451,7 +1452,7 @@ void BLEUtils::dumpGattClientEvent( // - esp_gatt_status_t status // - uint16_t conn_id case ESP_GATTC_SEARCH_CMPL_EVT: { - ESP_LOGD(LOG_TAG, "[status: %s, conn_id: %d]", + ESP_LOGV(LOG_TAG, "[status: %s, conn_id: %d]", BLEUtils::gattStatusToString(evtParam->search_cmpl.status).c_str(), evtParam->search_cmpl.conn_id); break; @@ -1465,7 +1466,7 @@ void BLEUtils::dumpGattClientEvent( // - uint16_t end_handle // - esp_gatt_id_t srvc_id case ESP_GATTC_SEARCH_RES_EVT: { - ESP_LOGD(LOG_TAG, "[conn_id: %d, start_handle: %d 0x%.2x, end_handle: %d 0x%.2x, srvc_id: %s", + ESP_LOGV(LOG_TAG, "[conn_id: %d, start_handle: %d 0x%.2x, end_handle: %d 0x%.2x, srvc_id: %s", evtParam->search_res.conn_id, evtParam->search_res.start_handle, evtParam->search_res.start_handle, @@ -1483,7 +1484,7 @@ void BLEUtils::dumpGattClientEvent( // - uint16_t handle // - uint16_t offset case ESP_GATTC_WRITE_CHAR_EVT: { - ESP_LOGD(LOG_TAG, "[status: %s, conn_id: %d, handle: %d 0x%.2x, offset: %d]", + ESP_LOGV(LOG_TAG, "[status: %s, conn_id: %d, handle: %d 0x%.2x, offset: %d]", BLEUtils::gattStatusToString(evtParam->write.status).c_str(), evtParam->write.conn_id, evtParam->write.handle, @@ -1492,7 +1493,7 @@ void BLEUtils::dumpGattClientEvent( ); break; } // ESP_GATTC_WRITE_CHAR_EVT - +#endif default: break; } @@ -1513,11 +1514,12 @@ void BLEUtils::dumpGattServerEvent( esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t* evtParam) { - ESP_LOGD(LOG_TAG, "GATT ServerEvent: %s", BLEUtils::gattServerEventTypeToString(event).c_str()); + ESP_LOGV(LOG_TAG, "GATT ServerEvent: %s", BLEUtils::gattServerEventTypeToString(event).c_str()); switch (event) { +#if CONFIG_LOG_DEFAULT_LEVEL > 4 case ESP_GATTS_ADD_CHAR_DESCR_EVT: { - ESP_LOGD(LOG_TAG, "[status: %s, attr_handle: %d 0x%.2x, service_handle: %d 0x%.2x, char_uuid: %s]", + ESP_LOGV(LOG_TAG, "[status: %s, attr_handle: %d 0x%.2x, service_handle: %d 0x%.2x, char_uuid: %s]", gattStatusToString(evtParam->add_char_descr.status).c_str(), evtParam->add_char_descr.attr_handle, evtParam->add_char_descr.attr_handle, @@ -1529,7 +1531,7 @@ void BLEUtils::dumpGattServerEvent( case ESP_GATTS_ADD_CHAR_EVT: { if (evtParam->add_char.status == ESP_GATT_OK) { - ESP_LOGD(LOG_TAG, "[status: %s, attr_handle: %d 0x%.2x, service_handle: %d 0x%.2x, char_uuid: %s]", + ESP_LOGV(LOG_TAG, "[status: %s, attr_handle: %d 0x%.2x, service_handle: %d 0x%.2x, char_uuid: %s]", gattStatusToString(evtParam->add_char.status).c_str(), evtParam->add_char.attr_handle, evtParam->add_char.attr_handle, @@ -1555,7 +1557,7 @@ void BLEUtils::dumpGattServerEvent( // - esp_gatt_status_t status – The status code. // - uint16_t conn_id – The connection used. case ESP_GATTS_CONF_EVT: { - ESP_LOGD(LOG_TAG, "[status: %s, conn_id: 0x%.2x]", + ESP_LOGV(LOG_TAG, "[status: %s, conn_id: 0x%.2x]", gattStatusToString(evtParam->conf.status).c_str(), evtParam->conf.conn_id); break; @@ -1563,21 +1565,21 @@ void BLEUtils::dumpGattServerEvent( case ESP_GATTS_CONGEST_EVT: { - ESP_LOGD(LOG_TAG, "[conn_id: %d, congested: %d]", + ESP_LOGV(LOG_TAG, "[conn_id: %d, congested: %d]", evtParam->congest.conn_id, evtParam->congest.congested); break; } // ESP_GATTS_CONGEST_EVT case ESP_GATTS_CONNECT_EVT: { - ESP_LOGD(LOG_TAG, "[conn_id: %d, remote_bda: %s]", + ESP_LOGV(LOG_TAG, "[conn_id: %d, remote_bda: %s]", evtParam->connect.conn_id, BLEAddress(evtParam->connect.remote_bda).toString().c_str()); break; } // ESP_GATTS_CONNECT_EVT case ESP_GATTS_CREATE_EVT: { - ESP_LOGD(LOG_TAG, "[status: %s, service_handle: %d 0x%.2x, service_id: [%s]]", + ESP_LOGV(LOG_TAG, "[status: %s, service_handle: %d 0x%.2x, service_id: [%s]]", gattStatusToString(evtParam->create.status).c_str(), evtParam->create.service_handle, evtParam->create.service_handle, @@ -1586,7 +1588,7 @@ void BLEUtils::dumpGattServerEvent( } // ESP_GATTS_CREATE_EVT case ESP_GATTS_DISCONNECT_EVT: { - ESP_LOGD(LOG_TAG, "[conn_id: %d, remote_bda: %s]", + ESP_LOGV(LOG_TAG, "[conn_id: %d, remote_bda: %s]", evtParam->connect.conn_id, BLEAddress(evtParam->connect.remote_bda).toString().c_str()); break; @@ -1617,7 +1619,7 @@ void BLEUtils::dumpGattServerEvent( break; } - ESP_LOGD(LOG_TAG, "[conn_id: %d, trans_id: %d, bda: %s, exec_write_flag: 0x%.2x=%s]", + ESP_LOGV(LOG_TAG, "[conn_id: %d, trans_id: %d, bda: %s, exec_write_flag: 0x%.2x=%s]", evtParam->exec_write.conn_id, evtParam->exec_write.trans_id, BLEAddress(evtParam->exec_write.bda).toString().c_str(), @@ -1628,14 +1630,14 @@ void BLEUtils::dumpGattServerEvent( case ESP_GATTS_MTU_EVT: { - ESP_LOGD(LOG_TAG, "[conn_id: %d, mtu: %d]", + ESP_LOGV(LOG_TAG, "[conn_id: %d, mtu: %d]", evtParam->mtu.conn_id, evtParam->mtu.mtu); break; } // ESP_GATTS_MTU_EVT case ESP_GATTS_READ_EVT: { - ESP_LOGD(LOG_TAG, "[conn_id: %d, trans_id: %d, bda: %s, handle: 0x%.2x, is_long: %d, need_rsp:%d]", + ESP_LOGV(LOG_TAG, "[conn_id: %d, trans_id: %d, bda: %s, handle: 0x%.2x, is_long: %d, need_rsp:%d]", evtParam->read.conn_id, evtParam->read.trans_id, BLEAddress(evtParam->read.bda).toString().c_str(), @@ -1646,14 +1648,14 @@ void BLEUtils::dumpGattServerEvent( } // ESP_GATTS_READ_EVT case ESP_GATTS_RESPONSE_EVT: { - ESP_LOGD(LOG_TAG, "[status: %s, handle: 0x%.2x]", + ESP_LOGV(LOG_TAG, "[status: %s, handle: 0x%.2x]", gattStatusToString(evtParam->rsp.status).c_str(), evtParam->rsp.handle); break; } // ESP_GATTS_RESPONSE_EVT case ESP_GATTS_REG_EVT: { - ESP_LOGD(LOG_TAG, "[status: %s, app_id: %d]", + ESP_LOGV(LOG_TAG, "[status: %s, app_id: %d]", gattStatusToString(evtParam->reg.status).c_str(), evtParam->reg.app_id); break; @@ -1666,7 +1668,7 @@ void BLEUtils::dumpGattServerEvent( // - esp_gatt_status_t status // - uint16_t service_handle case ESP_GATTS_START_EVT: { - ESP_LOGD(LOG_TAG, "[status: %s, service_handle: 0x%.2x]", + ESP_LOGV(LOG_TAG, "[status: %s, service_handle: 0x%.2x]", gattStatusToString(evtParam->start.status).c_str(), evtParam->start.service_handle); break; @@ -1686,7 +1688,7 @@ void BLEUtils::dumpGattServerEvent( // - uint16_t len – The length of the incoming value part. // - uint8_t* value – The data for this value part. case ESP_GATTS_WRITE_EVT: { - ESP_LOGD(LOG_TAG, "[conn_id: %d, trans_id: %d, bda: %s, handle: 0x%.2x, offset: %d, need_rsp: %d, is_prep: %d, len: %d]", + ESP_LOGV(LOG_TAG, "[conn_id: %d, trans_id: %d, bda: %s, handle: 0x%.2x, offset: %d, need_rsp: %d, is_prep: %d, len: %d]", evtParam->write.conn_id, evtParam->write.trans_id, BLEAddress(evtParam->write.bda).toString().c_str(), @@ -1696,13 +1698,13 @@ void BLEUtils::dumpGattServerEvent( evtParam->write.is_prep, evtParam->write.len); char* pHex = buildHexData(nullptr, evtParam->write.value, evtParam->write.len); - ESP_LOGD(LOG_TAG, "[Data: %s]", pHex); + ESP_LOGV(LOG_TAG, "[Data: %s]", pHex); free(pHex); break; } // ESP_GATTS_WRITE_EVT - +#endif default: - ESP_LOGD(LOG_TAG, "dumpGattServerEvent: *** NOT CODED ***"); + ESP_LOGV(LOG_TAG, "dumpGattServerEvent: *** NOT CODED ***"); break; } } // dumpGattServerEvent @@ -1726,7 +1728,7 @@ const char* BLEUtils::eventTypeToString(esp_ble_evt_type_t eventType) { case ESP_BLE_EVT_SCAN_RSP: return "ESP_BLE_EVT_SCAN_RSP"; default: - ESP_LOGD(LOG_TAG, "Unknown esp_ble_evt_type_t: %d (0x%.2x)", eventType, eventType); + ESP_LOGV(LOG_TAG, "Unknown esp_ble_evt_type_t: %d (0x%.2x)", eventType, eventType); return "*** Unknown ***"; } } // eventTypeToString @@ -1795,7 +1797,7 @@ const char* BLEUtils::gapEventToString(uint32_t eventType) { case ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT: return "ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT"; default: - ESP_LOGD(LOG_TAG, "gapEventToString: Unknown event type %d 0x%.2x", eventType, eventType); + ESP_LOGV(LOG_TAG, "gapEventToString: Unknown event type %d 0x%.2x", eventType, eventType); return "Unknown event type"; } } // gapEventToString @@ -2001,7 +2003,7 @@ const char* BLEUtils::searchEventTypeToString(esp_gap_search_evt_t searchEvt) { case ESP_GAP_SEARCH_SEARCH_CANCEL_CMPL_EVT: return "ESP_GAP_SEARCH_SEARCH_CANCEL_CMPL_EVT"; default: - ESP_LOGD(LOG_TAG, "Unknown event type: 0x%x", searchEvt); + ESP_LOGV(LOG_TAG, "Unknown event type: 0x%x", searchEvt); return "Unknown event type"; } } // searchEventTypeToString diff --git a/cpp_utils/BLEValue.cpp b/cpp_utils/BLEValue.cpp index aac0f500..ec1e61f5 100644 --- a/cpp_utils/BLEValue.cpp +++ b/cpp_utils/BLEValue.cpp @@ -6,15 +6,17 @@ */ #include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) - -#include - #include "BLEValue.h" -#ifdef ARDUINO_ARCH_ESP32 + +#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) #include "esp32-hal-log.h" +#define LOG_TAG "" +#else +#include "esp_log.h" +static const char* LOG_TAG="BLEValue"; #endif -static const char* LOG_TAG="BLEValue"; + BLEValue::BLEValue() { m_accumulation = ""; diff --git a/cpp_utils/CMakeLists.txt b/cpp_utils/CMakeLists.txt new file mode 100644 index 00000000..cb9b7267 --- /dev/null +++ b/cpp_utils/CMakeLists.txt @@ -0,0 +1,20 @@ +# Edit following two lines to set component requirements (see docs) +set(COMPONENT_REQUIRES + "console" + "fatfs" + "json" + "mdns" + "nvs_flash" +) +set(COMPONENT_PRIV_REQUIRES ) + +file(GLOB COMPONENT_SRCS + LIST_DIRECTORIES false + "*.h" + "*.cpp" + "*.c" + "*.S" +) +set(COMPONENT_ADD_INCLUDEDIRS ".") + +register_component() diff --git a/cpp_utils/File.cpp b/cpp_utils/File.cpp index 3b245a85..3ac4672f 100644 --- a/cpp_utils/File.cpp +++ b/cpp_utils/File.cpp @@ -11,7 +11,7 @@ #include #include #include -#include +#include "GeneralUtils.h" static const char* LOG_TAG = "File"; /** diff --git a/cpp_utils/FreeRTOS.cpp b/cpp_utils/FreeRTOS.cpp index 9514eed4..1920fa43 100644 --- a/cpp_utils/FreeRTOS.cpp +++ b/cpp_utils/FreeRTOS.cpp @@ -11,10 +11,14 @@ #include #include #include "FreeRTOS.h" -#include #include "sdkconfig.h" - +#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) +#include "esp32-hal-log.h" +#define LOG_TAG "" +#else +#include "esp_log.h" static const char* LOG_TAG = "FreeRTOS"; +#endif /** * Sleep for the specified number of milliseconds. @@ -63,6 +67,8 @@ uint32_t FreeRTOS::getTimeSinceStart() { */ uint32_t FreeRTOS::Semaphore::wait(std::string owner) { ESP_LOGV(LOG_TAG, ">> wait: Semaphore waiting: %s for %s", toString().c_str(), owner.c_str()); + + m_owner = owner; if (m_usePthreads) { pthread_mutex_lock(&m_pthread_mutex); @@ -70,8 +76,6 @@ uint32_t FreeRTOS::Semaphore::wait(std::string owner) { xSemaphoreTake(m_semaphore, portMAX_DELAY); } - m_owner = owner; - if (m_usePthreads) { pthread_mutex_unlock(&m_pthread_mutex); } else { @@ -79,7 +83,6 @@ uint32_t FreeRTOS::Semaphore::wait(std::string owner) { } ESP_LOGV(LOG_TAG, "<< wait: Semaphore released: %s", toString().c_str()); - m_owner = std::string(""); return m_value; } // wait @@ -89,7 +92,8 @@ FreeRTOS::Semaphore::Semaphore(std::string name) { if (m_usePthreads) { pthread_mutex_init(&m_pthread_mutex, nullptr); } else { - m_semaphore = xSemaphoreCreateMutex(); + m_semaphore = xSemaphoreCreateBinary(); + xSemaphoreGive(m_semaphore); } m_name = name; diff --git a/cpp_utils/GeneralUtils.cpp b/cpp_utils/GeneralUtils.cpp index 80c5cc6e..019c81bd 100644 --- a/cpp_utils/GeneralUtils.cpp +++ b/cpp_utils/GeneralUtils.cpp @@ -6,21 +6,27 @@ */ #include "GeneralUtils.h" -#include #include #include #include #include #include #include -#include +#include "FreeRTOS.h" #include #include #include #include #include +#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) +#include "esp32-hal-log.h" +#define LOG_TAG "" +#else +#include "esp_log.h" static const char* LOG_TAG = "GeneralUtils"; +#endif + static const char kBase64Alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" @@ -365,6 +371,7 @@ std::vector GeneralUtils::split(std::string source, char delimiter) */ const char* GeneralUtils::errorToString(esp_err_t errCode) { switch (errCode) { +#if CONFIG_LOG_DEFAULT_LEVEL > 4 case ESP_OK: return "ESP_OK"; case ESP_FAIL: @@ -431,6 +438,7 @@ const char* GeneralUtils::errorToString(esp_err_t errCode) { return "ESP_ERR_WIFI_TIMEOUT"; case ESP_ERR_WIFI_WAKE_FAIL: return "ESP_ERR_WIFI_WAKE_FAIL"; +#endif default: return "Unknown ESP_ERR error"; } @@ -440,7 +448,7 @@ const char* GeneralUtils::errorToString(esp_err_t errCode) { * @brief Convert a wifi_err_reason_t code to a string. * @param [in] errCode The errCode to be converted. * @return A string representation of the error code. - * + * * @note: wifi_err_reason_t values as of April 2018 are: (1-24, 200-204) and are defined in ~/esp-idf/components/esp32/include/esp_wifi_types.h. */ const char* GeneralUtils::wifiErrorToString(uint8_t errCode) { @@ -448,6 +456,7 @@ const char* GeneralUtils::wifiErrorToString(uint8_t errCode) { if (errCode == UINT8_MAX) return "Not Connected (default value)"; switch ((wifi_err_reason_t) errCode) { +#if CONFIG_LOG_DEFAULT_LEVEL > 4 case WIFI_REASON_UNSPECIFIED: return "WIFI_REASON_UNSPECIFIED"; case WIFI_REASON_AUTH_EXPIRE: @@ -504,6 +513,7 @@ const char* GeneralUtils::wifiErrorToString(uint8_t errCode) { return "WIFI_REASON_ASSOC_FAIL"; case WIFI_REASON_HANDSHAKE_TIMEOUT: return "WIFI_REASON_HANDSHAKE_TIMEOUT"; +#endif default: return "Unknown ESP_ERR error"; } diff --git a/cpp_utils/MFRC522.cpp b/cpp_utils/MFRC522.cpp index 4082d4ac..940c170c 100644 --- a/cpp_utils/MFRC522.cpp +++ b/cpp_utils/MFRC522.cpp @@ -18,8 +18,8 @@ #include "MFRC522.h" #include "MFRC522Debug.h" -#include -#include +#include "FreeRTOS.h" +#include "GPIO.h" #include #include #include @@ -48,7 +48,11 @@ void MFRC522::PCD_WriteRegister(PCD_Register reg, byte value) { uint8_t data[2]; data[0] = reg; data[1] = value; + + ESP32CPP::GPIO::low((gpio_num_t)_chipSelectPin); // Select slave m_spi.transfer(data, 2); + ESP32CPP::GPIO::high((gpio_num_t)_chipSelectPin); // Release slave + } // End PCD_WriteRegister() @@ -63,7 +67,11 @@ void MFRC522::PCD_WriteRegister(PCD_Register reg, byte count, byte* values) { uint8_t* pData = new uint8_t[count + 1]; pData[0] = reg; memcpy(pData + 1, values, count); + + ESP32CPP::GPIO::low((gpio_num_t)_chipSelectPin); // Select slave m_spi.transfer(pData, count + 1); + ESP32CPP::GPIO::high((gpio_num_t)_chipSelectPin); // Release slave + delete[] pData; } // End PCD_WriteRegister() @@ -77,7 +85,11 @@ byte MFRC522::PCD_ReadRegister(PCD_Register reg) { uint8_t data[2]; data[0] = reg | 0x80; data[1] = 0; + + ESP32CPP::GPIO::low((gpio_num_t)_chipSelectPin); // Select slave m_spi.transfer(data, 2); + ESP32CPP::GPIO::high((gpio_num_t)_chipSelectPin); // Release slave + return data[1]; } // End PCD_ReadRegister() @@ -97,6 +109,8 @@ void MFRC522::PCD_ReadRegister(PCD_Register reg, byte count, byte* values, byte byte address = 0x80 | reg; // MSB == 1 is for reading. LSB is not used in address. Datasheet section 8.1.2.3. byte index = 0; // Index in values array. count--; // One read is performed outside of the loop + + ESP32CPP::GPIO::low((gpio_num_t)_chipSelectPin); // Select slave m_spi.transferByte(address); // Tell MFRC522 which address we want to read if (rxAlign) { // Only update bit positions rxAlign..7 in values[0] // Create bit mask for bit positions rxAlign..7 @@ -112,6 +126,7 @@ void MFRC522::PCD_ReadRegister(PCD_Register reg, byte count, byte* values, byte index++; } values[index] = m_spi.transferByte(0); // Read the final byte. Send 0 to stop reading. + ESP32CPP::GPIO::high((gpio_num_t)_chipSelectPin); // Release slave } // End PCD_ReadRegister() @@ -181,6 +196,8 @@ MFRC522::StatusCode MFRC522::PCD_CalculateCRC(byte* data, byte length, byte* res */ void MFRC522::PCD_Init() { //m_spi.setHost(VSPI_HOST); + + ESP32CPP::GPIO::setOutput((gpio_num_t)_chipSelectPin); m_spi.init(); bool hardReset = false; diff --git a/cpp_utils/MMU.cpp b/cpp_utils/MMU.cpp index 57c0ccce..ee7adb59 100644 --- a/cpp_utils/MMU.cpp +++ b/cpp_utils/MMU.cpp @@ -47,7 +47,7 @@ static uint32_t flashPageToOffset(uint32_t page) { const uint32_t mappingInvalid = 1 << 8; printf("PRO CPU MMU\n"); - for (uint8_t i = 0; i < 256; i++) { + for (uint16_t i = 0; i < 256; i++) { if (!(DPORT_PRO_FLASH_MMU_TABLE[i] & mappingInvalid)) { addressRange_t addressRange = entryNumberToAddressRange(i); printf("Entry: %2d (0x%8.8x - 0x%8.8x), Page: %d - offset: 0x%x\n", @@ -59,7 +59,7 @@ static uint32_t flashPageToOffset(uint32_t page) { } printf("\n"); printf("APP CPU MMU\n"); - for (uint8_t i = 0; i < 256; i++) { + for (uint16_t i = 0; i < 256; i++) { if (!(DPORT_APP_FLASH_MMU_TABLE[i] & mappingInvalid)) { addressRange_t addressRange = entryNumberToAddressRange(i); printf("Entry: %2d (0x%8.8x - 0x%8.8x), Page: %d - offset: 0x%x\n", diff --git a/cpp_utils/PCF8574.cpp b/cpp_utils/PCF8574.cpp index 79be44c0..d246b7a6 100644 --- a/cpp_utils/PCF8574.cpp +++ b/cpp_utils/PCF8574.cpp @@ -116,5 +116,6 @@ void PCF8574::setInvert(bool value) { * @param [in] clkPin The pin to use for the %I2C CLK functions. */ void PCF8574::init(gpio_num_t sdaPin, gpio_num_t clkPin) { - i2c->init(0, sdaPin, clkPin); + uint8_t addr = i2c->getAddress(); + i2c->init(addr, sdaPin, clkPin); } // init diff --git a/cpp_utils/SockServ.cpp b/cpp_utils/SockServ.cpp index 38ecc823..020ed096 100644 --- a/cpp_utils/SockServ.cpp +++ b/cpp_utils/SockServ.cpp @@ -7,15 +7,15 @@ #include #include -#include #include #include - #include + #include #include #include "sdkconfig.h" +#include "FreeRTOS.h" #include "SockServ.h" #include "Socket.h" diff --git a/cpp_utils/TFTP.cpp b/cpp_utils/TFTP.cpp index d554bd45..b1591a9f 100644 --- a/cpp_utils/TFTP.cpp +++ b/cpp_utils/TFTP.cpp @@ -9,13 +9,13 @@ #include "TFTP.h" #include -#include -#include +#include "FreeRTOS.h" +#include "GeneralUtils.h" #include #include #include #include -#include +#include "Socket.h" #include "sdkconfig.h" diff --git a/cpp_utils/WS2812.cpp b/cpp_utils/WS2812.cpp index 0b8a3cbe..af4bc512 100644 --- a/cpp_utils/WS2812.cpp +++ b/cpp_utils/WS2812.cpp @@ -158,7 +158,7 @@ void WS2812::show() { (getChannelValueByType(this->colorOrder[2], this->pixels[i])); ESP_LOGD(LOG_TAG, "Pixel value: %x", currentPixel); - for (uint8_t j = 23; j >= 0; j--) { + for (int8_t j = 23; j >= 0; j--) { // We have 24 bits of data representing the red, green amd blue channels. The value of the // 24 bits to output is in the variable current_pixel. We now need to stream this value // through RMT in most significant bit first. To do this, we iterate through each of the 24 diff --git a/cpp_utils/tests/BLETests/Arduino/BLE_client/BLE_client.ino b/cpp_utils/tests/BLETests/Arduino/BLE_client/BLE_client.ino index c0b6163c..7bce73f1 100644 --- a/cpp_utils/tests/BLETests/Arduino/BLE_client/BLE_client.ino +++ b/cpp_utils/tests/BLETests/Arduino/BLE_client/BLE_client.ino @@ -6,9 +6,9 @@ //#include "BLEScan.h" // The remote service we wish to connect to. -static BLEUUID serviceUUID("91bad492-b950-4226-aa2b-4ede9fa42f59"); +static BLEUUID serviceUUID("4fafc201-1fb5-459e-8fcc-c5c9c331914b"); // The characteristic of the remote service we are interested in. -static BLEUUID charUUID("0d563a58-196a-48ce-ace2-dfec78acc814"); +static BLEUUID charUUID("beb5483e-36e1-4688-b7f5-ea07361b26a8"); static BLEAddress *pServerAddress; static boolean doConnect = false; @@ -62,6 +62,8 @@ bool connectToServer(BLEAddress pAddress) { Serial.println(value.c_str()); pRemoteCharacteristic->registerForNotify(notifyCallback); + + return true; } /** * Scan for BLE servers and find the first one that advertises the service we are looking for. diff --git a/cpp_utils/tests/BLETests/Arduino/BLE_server/BLE_server.ino b/cpp_utils/tests/BLETests/Arduino/BLE_server/BLE_server.ino index 38224a67..79793975 100644 --- a/cpp_utils/tests/BLETests/Arduino/BLE_server/BLE_server.ino +++ b/cpp_utils/tests/BLETests/Arduino/BLE_server/BLE_server.ino @@ -29,6 +29,7 @@ void setup() { pCharacteristic->setValue("Hello World says Neil"); pService->start(); BLEAdvertising *pAdvertising = pServer->getAdvertising(); + pAdvertising->addServiceUUID(SERVICE_UUID); pAdvertising->start(); Serial.println("Characteristic defined! Now you can read it in your phone!"); } @@ -36,4 +37,4 @@ void setup() { void loop() { // put your main code here, to run repeatedly: delay(2000); -} \ No newline at end of file +} diff --git a/cpp_utils/tests/BLETests/Arduino/security/BLE_client/BLE_client_encrypted.ino b/cpp_utils/tests/BLETests/Arduino/security/BLE_client/BLE_client_encrypted.ino deleted file mode 100644 index e77d774f..00000000 --- a/cpp_utils/tests/BLETests/Arduino/security/BLE_client/BLE_client_encrypted.ino +++ /dev/null @@ -1,138 +0,0 @@ -/** - * A BLE client example that is rich in capabilities. - */ - -#include "BLEDevice.h" -//#include "BLEScan.h" - -// The remote service we wish to connect to. -static BLEUUID serviceUUID("91bad492-b950-4226-aa2b-4ede9fa42f59"); -// The characteristic of the remote service we are interested in. -static BLEUUID charUUID("0d563a58-196a-48ce-ace2-dfec78acc814"); - -static BLEAddress *pServerAddress; -static boolean doConnect = false; -static boolean connected = false; -static BLERemoteCharacteristic* pRemoteCharacteristic; - -static void notifyCallback( - BLERemoteCharacteristic* pBLERemoteCharacteristic, - uint8_t* pData, - size_t length, - bool isNotify) { - Serial.print("Notify callback for characteristic "); - Serial.print(pBLERemoteCharacteristic->getUUID().toString().c_str()); - Serial.print(" of data length "); - Serial.println(length); -} - -bool connectToServer(BLEAddress pAddress) { - Serial.print("Forming a connection to "); - Serial.println(pAddress.toString().c_str()); - - /* - * Here we have implemented simplest security. This kind security does not provide authentication - */ - BLEDevice::setEncryptionLevel(ESP_BLE_SEC_ENCRYPT); - BLEClient* pClient = BLEDevice::createClient(); - Serial.println(" - Created client"); - - // Connect to the remove BLE Server. - pClient->connect(pAddress); - Serial.println(" - Connected to server"); - - // Obtain a reference to the service we are after in the remote BLE server. - BLERemoteService* pRemoteService = pClient->getService(serviceUUID); - if (pRemoteService == nullptr) { - Serial.print("Failed to find our service UUID: "); - Serial.println(serviceUUID.toString().c_str()); - return false; - } - Serial.println(" - Found our service"); - - - // Obtain a reference to the characteristic in the service of the remote BLE server. - pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID); - if (pRemoteCharacteristic == nullptr) { - Serial.print("Failed to find our characteristic UUID: "); - Serial.println(charUUID.toString().c_str()); - return false; - } - Serial.println(" - Found our characteristic"); - - // Read the value of the characteristic. - std::string value = pRemoteCharacteristic->readValue(); - Serial.print("The characteristic value was: "); - Serial.println(value.c_str()); - - pRemoteCharacteristic->registerForNotify(notifyCallback); -} -/** - * Scan for BLE servers and find the first one that advertises the service we are looking for. - */ -class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks { - /** - * Called for each advertising BLE server. - */ - void onResult(BLEAdvertisedDevice advertisedDevice) { - Serial.print("BLE Advertised Device found: "); - Serial.println(advertisedDevice.toString().c_str()); - - // We have found a device, let us now see if it contains the service we are looking for. - if (advertisedDevice.haveServiceUUID() && advertisedDevice.getServiceUUID().equals(serviceUUID)) { - - // - Serial.print("Found our device! address: "); - advertisedDevice.getScan()->stop(); - - pServerAddress = new BLEAddress(advertisedDevice.getAddress()); - doConnect = true; - - } // Found our server - } // onResult -}; // MyAdvertisedDeviceCallbacks - - -void setup() { - Serial.begin(115200); - Serial.println("Starting Arduino BLE Client application..."); - BLEDevice::init(""); - - // Retrieve a Scanner and set the callback we want to use to be informed when we - // have detected a new device. Specify that we want active scanning and start the - // scan to run for 30 seconds. - BLEScan* pBLEScan = BLEDevice::getScan(); - pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks()); - pBLEScan->setActiveScan(true); - pBLEScan->start(30); -} // End of setup. - - -// This is the Arduino main loop function. -void loop() { - - // If the flag "doConnect" is true then we have scanned for and found the desired - // BLE Server with which we wish to connect. Now we connect to it. Once we are - // connected we set the connected flag to be true. - if (doConnect == true) { - if (connectToServer(*pServerAddress)) { - Serial.println("We are now connected to the BLE Server."); - connected = true; - } else { - Serial.println("We have failed to connect to the server; there is nothin more we will do."); - } - doConnect = false; - } - - // If we are connected to a peer BLE Server, update the characteristic each time we are reached - // with the current time since boot. - if (connected) { - String newValue = "Time since boot: " + String(millis()/1000); - Serial.println("Setting new characteristic value to \"" + newValue + "\""); - - // Set the characteristic's value to be the array of bytes that is actually a string. - pRemoteCharacteristic->writeValue(newValue.c_str(), newValue.length()); - } - - delay(1000); // Delay a second between loops. -} // End of loop diff --git a/cpp_utils/tests/BLETests/Arduino/security/BLE_client/BLE_client_numeric_confirmation.ino b/cpp_utils/tests/BLETests/Arduino/security/BLE_client/BLE_client_numeric_confirmation.ino deleted file mode 100644 index 846a664b..00000000 --- a/cpp_utils/tests/BLETests/Arduino/security/BLE_client/BLE_client_numeric_confirmation.ino +++ /dev/null @@ -1,169 +0,0 @@ -/** - * A BLE client example that is rich in capabilities. - */ - -#include "BLEDevice.h" -//#include "BLEScan.h" - -// The remote service we wish to connect to. -static BLEUUID serviceUUID("91bad492-b950-4226-aa2b-4ede9fa42f59"); -// The characteristic of the remote service we are interested in. -static BLEUUID charUUID("0d563a58-196a-48ce-ace2-dfec78acc814"); - -static BLEAddress *pServerAddress; -static boolean doConnect = false; -static boolean connected = false; -static BLERemoteCharacteristic* pRemoteCharacteristic; - -class MySecurity : public BLESecurityCallbacks { - - uint32_t onPassKeyRequest(){ - return 123456; - } - void onPassKeyNotify(uint32_t pass_key){ - ESP_LOGE(LOG_TAG, "The passkey Notify number:%d", pass_key); - } - bool onConfirmPIN(uint32_t pass_key){ - ESP_LOGI(LOG_TAG, "The passkey YES/NO number:%d", pass_key); - vTaskDelay(5000); - return true; - } - bool onSecurityRequest(){ - ESP_LOGI(LOG_TAG, "Security Request"); - return true; - } - void onAuthenticationComplete(esp_ble_auth_cmpl_t auth_cmpl){ - if(auth_cmpl.success){ - ESP_LOGI(LOG_TAG, "remote BD_ADDR:"); - esp_log_buffer_hex(LOG_TAG, auth_cmpl.bd_addr, sizeof(auth_cmpl.bd_addr)); - ESP_LOGI(LOG_TAG, "address type = %d", auth_cmpl.addr_type); - } - ESP_LOGI(LOG_TAG, "pair status = %s", auth_cmpl.success ? "success" : "fail"); - } -}; - -static void notifyCallback( - BLERemoteCharacteristic* pBLERemoteCharacteristic, - uint8_t* pData, - size_t length, - bool isNotify) { - Serial.print("Notify callback for characteristic "); - Serial.print(pBLERemoteCharacteristic->getUUID().toString().c_str()); - Serial.print(" of data length "); - Serial.println(length); -} - -bool connectToServer(BLEAddress pAddress) { - Serial.print("Forming a connection to "); - Serial.println(pAddress.toString().c_str()); - - BLEDevice::setEncryptionLevel(ESP_BLE_SEC_ENCRYPT); - BLEDevice::setSecurityCallbacks(new MySecurity()); - - BLESecurity *pSecurity = new BLESecurity(); - pSecurity->setKeySize(); - pSecurity->setAuthenticationMode(ESP_LE_AUTH_REQ_SC_ONLY); - pSecurity->setCapability(ESP_IO_CAP_IO); - pSecurity->setRespEncryptionKey(ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK); - BLEClient* pClient = BLEDevice::createClient(); - Serial.println(" - Created client"); - - // Connect to the remove BLE Server. - pClient->connect(pAddress); - Serial.println(" - Connected to server"); - - // Obtain a reference to the service we are after in the remote BLE server. - BLERemoteService* pRemoteService = pClient->getService(serviceUUID); - if (pRemoteService == nullptr) { - Serial.print("Failed to find our service UUID: "); - Serial.println(serviceUUID.toString().c_str()); - return false; - } - Serial.println(" - Found our service"); - - - // Obtain a reference to the characteristic in the service of the remote BLE server. - pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID); - if (pRemoteCharacteristic == nullptr) { - Serial.print("Failed to find our characteristic UUID: "); - Serial.println(charUUID.toString().c_str()); - return false; - } - Serial.println(" - Found our characteristic"); - - // Read the value of the characteristic. - std::string value = pRemoteCharacteristic->readValue(); - Serial.print("The characteristic value was: "); - Serial.println(value.c_str()); - - pRemoteCharacteristic->registerForNotify(notifyCallback); -} -/** - * Scan for BLE servers and find the first one that advertises the service we are looking for. - */ -class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks { - /** - * Called for each advertising BLE server. - */ - void onResult(BLEAdvertisedDevice advertisedDevice) { - Serial.print("BLE Advertised Device found: "); - Serial.println(advertisedDevice.toString().c_str()); - - // We have found a device, let us now see if it contains the service we are looking for. - if (advertisedDevice.haveServiceUUID() && advertisedDevice.getServiceUUID().equals(serviceUUID)) { - - // - Serial.print("Found our device! address: "); - advertisedDevice.getScan()->stop(); - - pServerAddress = new BLEAddress(advertisedDevice.getAddress()); - doConnect = true; - - } // Found our server - } // onResult -}; // MyAdvertisedDeviceCallbacks - - -void setup() { - Serial.begin(115200); - Serial.println("Starting Arduino BLE Client application..."); - BLEDevice::init(""); - - // Retrieve a Scanner and set the callback we want to use to be informed when we - // have detected a new device. Specify that we want active scanning and start the - // scan to run for 30 seconds. - BLEScan* pBLEScan = BLEDevice::getScan(); - pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks()); - pBLEScan->setActiveScan(true); - pBLEScan->start(30); -} // End of setup. - - -// This is the Arduino main loop function. -void loop() { - - // If the flag "doConnect" is true then we have scanned for and found the desired - // BLE Server with which we wish to connect. Now we connect to it. Once we are - // connected we set the connected flag to be true. - if (doConnect == true) { - if (connectToServer(*pServerAddress)) { - Serial.println("We are now connected to the BLE Server."); - connected = true; - } else { - Serial.println("We have failed to connect to the server; there is nothin more we will do."); - } - doConnect = false; - } - - // If we are connected to a peer BLE Server, update the characteristic each time we are reached - // with the current time since boot. - if (connected) { - String newValue = "Time since boot: " + String(millis()/1000); - Serial.println("Setting new characteristic value to \"" + newValue + "\""); - - // Set the characteristic's value to be the array of bytes that is actually a string. - pRemoteCharacteristic->writeValue(newValue.c_str(), newValue.length()); - } - - delay(1000); // Delay a second between loops. -} // End of loop diff --git a/cpp_utils/tests/BLETests/Arduino/security/BLE_client/BLE_client_passkey.ino b/cpp_utils/tests/BLETests/Arduino/security/BLE_client/BLE_client_passkey.ino deleted file mode 100644 index 763a87d2..00000000 --- a/cpp_utils/tests/BLETests/Arduino/security/BLE_client/BLE_client_passkey.ino +++ /dev/null @@ -1,168 +0,0 @@ -/** - * A BLE client example that is rich in capabilities. - */ - -#include "BLEDevice.h" -//#include "BLEScan.h" - -// The remote service we wish to connect to. -static BLEUUID serviceUUID("91bad492-b950-4226-aa2b-4ede9fa42f59"); -// The characteristic of the remote service we are interested in. -static BLEUUID charUUID("0d563a58-196a-48ce-ace2-dfec78acc814"); - -static BLEAddress *pServerAddress; -static boolean doConnect = false; -static boolean connected = false; -static BLERemoteCharacteristic* pRemoteCharacteristic; - -class MySecurity : public BLESecurityCallbacks { - - uint32_t onPassKeyRequest(){ - return 123456; - } - void onPassKeyNotify(uint32_t pass_key){ - ESP_LOGE(LOG_TAG, "The passkey Notify number:%d", pass_key); - } - bool onConfirmPIN(uint32_t pass_key){ - ESP_LOGI(LOG_TAG, "The passkey YES/NO number:%d", pass_key); - vTaskDelay(5000); - return true; - } - bool onSecurityRequest(){ - ESP_LOGI(LOG_TAG, "Security Request"); - return true; - } - void onAuthenticationComplete(esp_ble_auth_cmpl_t auth_cmpl){ - if(auth_cmpl.success){ - ESP_LOGI(LOG_TAG, "remote BD_ADDR:"); - esp_log_buffer_hex(LOG_TAG, auth_cmpl.bd_addr, sizeof(auth_cmpl.bd_addr)); - ESP_LOGI(LOG_TAG, "address type = %d", auth_cmpl.addr_type); - } - ESP_LOGI(LOG_TAG, "pair status = %s", auth_cmpl.success ? "success" : "fail"); - } -}; - -static void notifyCallback( - BLERemoteCharacteristic* pBLERemoteCharacteristic, - uint8_t* pData, - size_t length, - bool isNotify) { - Serial.print("Notify callback for characteristic "); - Serial.print(pBLERemoteCharacteristic->getUUID().toString().c_str()); - Serial.print(" of data length "); - Serial.println(length); -} - -bool connectToServer(BLEAddress pAddress) { - Serial.print("Forming a connection to "); - Serial.println(pAddress.toString().c_str()); - - BLEDevice::setEncryptionLevel(ESP_BLE_SEC_ENCRYPT); - BLEDevice::setSecurityCallbacks(new MySecurity()); - - BLESecurity *pSecurity = new BLESecurity(); - pSecurity->setAuthenticationMode(ESP_LE_AUTH_REQ_SC_ONLY); - pSecurity->setCapability(ESP_IO_CAP_OUT); - pSecurity->setRespEncryptionKey(ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK); - BLEClient* pClient = BLEDevice::createClient(); - Serial.println(" - Created client"); - - // Connect to the remove BLE Server. - pClient->connect(pAddress); - Serial.println(" - Connected to server"); - - // Obtain a reference to the service we are after in the remote BLE server. - BLERemoteService* pRemoteService = pClient->getService(serviceUUID); - if (pRemoteService == nullptr) { - Serial.print("Failed to find our service UUID: "); - Serial.println(serviceUUID.toString().c_str()); - return false; - } - Serial.println(" - Found our service"); - - - // Obtain a reference to the characteristic in the service of the remote BLE server. - pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID); - if (pRemoteCharacteristic == nullptr) { - Serial.print("Failed to find our characteristic UUID: "); - Serial.println(charUUID.toString().c_str()); - return false; - } - Serial.println(" - Found our characteristic"); - - // Read the value of the characteristic. - std::string value = pRemoteCharacteristic->readValue(); - Serial.print("The characteristic value was: "); - Serial.println(value.c_str()); - - pRemoteCharacteristic->registerForNotify(notifyCallback); -} -/** - * Scan for BLE servers and find the first one that advertises the service we are looking for. - */ -class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks { - /** - * Called for each advertising BLE server. - */ - void onResult(BLEAdvertisedDevice advertisedDevice) { - Serial.print("BLE Advertised Device found: "); - Serial.println(advertisedDevice.toString().c_str()); - - // We have found a device, let us now see if it contains the service we are looking for. - if (advertisedDevice.haveServiceUUID() && advertisedDevice.getServiceUUID().equals(serviceUUID)) { - - // - Serial.print("Found our device! address: "); - advertisedDevice.getScan()->stop(); - - pServerAddress = new BLEAddress(advertisedDevice.getAddress()); - doConnect = true; - - } // Found our server - } // onResult -}; // MyAdvertisedDeviceCallbacks - - -void setup() { - Serial.begin(115200); - Serial.println("Starting Arduino BLE Client application..."); - BLEDevice::init(""); - - // Retrieve a Scanner and set the callback we want to use to be informed when we - // have detected a new device. Specify that we want active scanning and start the - // scan to run for 30 seconds. - BLEScan* pBLEScan = BLEDevice::getScan(); - pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks()); - pBLEScan->setActiveScan(true); - pBLEScan->start(30); -} // End of setup. - - -// This is the Arduino main loop function. -void loop() { - - // If the flag "doConnect" is true then we have scanned for and found the desired - // BLE Server with which we wish to connect. Now we connect to it. Once we are - // connected we set the connected flag to be true. - if (doConnect == true) { - if (connectToServer(*pServerAddress)) { - Serial.println("We are now connected to the BLE Server."); - connected = true; - } else { - Serial.println("We have failed to connect to the server; there is nothin more we will do."); - } - doConnect = false; - } - - // If we are connected to a peer BLE Server, update the characteristic each time we are reached - // with the current time since boot. - if (connected) { - String newValue = "Time since boot: " + String(millis()/1000); - Serial.println("Setting new characteristic value to \"" + newValue + "\""); - - // Set the characteristic's value to be the array of bytes that is actually a string. - pRemoteCharacteristic->writeValue(newValue.c_str(), newValue.length()); - } - - delay(1000); // Delay a second between loops. -} // End of loop diff --git a/cpp_utils/tests/BLETests/Arduino/security/BLE_server/BLE_server_passkey/BLE_server_passkey.ino b/cpp_utils/tests/BLETests/Arduino/security/BLE_server/BLE_server_passkey/BLE_server_passkey.ino index a48ad482..93f8c89f 100644 --- a/cpp_utils/tests/BLETests/Arduino/security/BLE_server/BLE_server_passkey/BLE_server_passkey.ino +++ b/cpp_utils/tests/BLETests/Arduino/security/BLE_server/BLE_server_passkey/BLE_server_passkey.ino @@ -14,7 +14,11 @@ #define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8" class MySecurity : public BLESecurityCallbacks { - + + bool onConfirmPIN(uint32_t pin){ + return false; + } + uint32_t onPassKeyRequest(){ ESP_LOGI(LOG_TAG, "PassKeyRequest"); return 123456; diff --git a/cpp_utils/tests/BLETests/Arduino/security/StaticPIN/StaticPIN.ino b/cpp_utils/tests/BLETests/Arduino/security/StaticPIN/StaticPIN.ino new file mode 100644 index 00000000..d89c14f9 --- /dev/null +++ b/cpp_utils/tests/BLETests/Arduino/security/StaticPIN/StaticPIN.ino @@ -0,0 +1,47 @@ +/* + Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleServer.cpp + Ported to Arduino ESP32 by Evandro Copercini +*/ + +#include +#include +#include + +// See the following for generating UUIDs: +// https://www.uuidgenerator.net/ + +#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b" +#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8" + +void setup() { + Serial.begin(115200); + Serial.println("Starting BLE work!"); + + BLEDevice::init("ESP32"); + /* + * Required in authentication process to provide displaying and/or input passkey or yes/no butttons confirmation + */ + BLEServer *pServer = BLEDevice::createServer(); + BLEService *pService = pServer->createService(SERVICE_UUID); + BLECharacteristic *pCharacteristic = pService->createCharacteristic( + CHARACTERISTIC_UUID, + BLECharacteristic::PROPERTY_READ | + BLECharacteristic::PROPERTY_WRITE + ); + pCharacteristic->setAccessPermissions(ESP_GATT_PERM_READ_ENCRYPTED | ESP_GATT_PERM_WRITE_ENCRYPTED); + pCharacteristic->setValue("Hello World says Neil"); + pService->start(); + BLEAdvertising *pAdvertising = pServer->getAdvertising(); + pAdvertising->start(); + + BLESecurity *pSecurity = new BLESecurity(); + pSecurity->setStaticPIN(123456); + + //set static passkey + Serial.println("Characteristic defined! Now you can read it in your phone!"); +} + +void loop() { + // put your main code here, to run repeatedly: + delay(2000); +}