diff options
author | Neil Kolban <kolban1@kolban.com> | 2017-11-21 09:51:03 -0600 |
---|---|---|
committer | Neil Kolban <kolban1@kolban.com> | 2017-11-21 09:51:03 -0600 |
commit | 4a781e01832176d61af010669b8c362f5a777768 (patch) | |
tree | 6a7a16309d61c4728512f5eb632d3ad565288c36 | |
parent | Fixes for #121 (diff) | |
download | thermostat-4a781e01832176d61af010669b8c362f5a777768.tar.gz thermostat-4a781e01832176d61af010669b8c362f5a777768.tar.bz2 thermostat-4a781e01832176d61af010669b8c362f5a777768.zip |
Updates 2017-11-21 0950
-rw-r--r-- | src/BLEAdvertisedDevice.cpp | 47 | ||||
-rw-r--r-- | src/BLEAdvertisedDevice.h | 3 | ||||
-rw-r--r-- | src/BLECharacteristic.cpp | 31 | ||||
-rw-r--r-- | src/BLECharacteristic.h | 2 | ||||
-rw-r--r-- | src/BLECharacteristicMap.cpp | 18 | ||||
-rw-r--r-- | src/BLEClient.cpp | 106 | ||||
-rw-r--r-- | src/BLEClient.h | 9 | ||||
-rw-r--r-- | src/BLEDescriptor.cpp | 92 | ||||
-rw-r--r-- | src/BLEDescriptor.h | 19 | ||||
-rw-r--r-- | src/BLEDevice.cpp | 154 | ||||
-rw-r--r-- | src/BLEDevice.h | 4 | ||||
-rw-r--r-- | src/BLERemoteCharacteristic.cpp | 1 | ||||
-rw-r--r-- | src/BLERemoteService.cpp | 14 | ||||
-rw-r--r-- | src/BLERemoteService.h | 8 | ||||
-rw-r--r-- | src/BLEScan.cpp | 28 | ||||
-rw-r--r-- | src/BLEScan.h | 6 | ||||
-rw-r--r-- | src/BLEServer.cpp | 2 | ||||
-rw-r--r-- | src/BLEService.cpp | 10 | ||||
-rw-r--r-- | src/BLEService.h | 10 | ||||
-rw-r--r-- | src/BLEUUID.cpp | 22 | ||||
-rw-r--r-- | src/BLEUUID.h | 1 | ||||
-rw-r--r-- | src/BLEUtils.cpp | 209 | ||||
-rw-r--r-- | src/BLEUtils.h | 1 | ||||
-rw-r--r-- | src/FreeRTOS.cpp | 128 | ||||
-rw-r--r-- | src/FreeRTOS.h | 41 | ||||
-rw-r--r-- | src/GeneralUtils.cpp | 12 | ||||
-rw-r--r-- | src/GeneralUtils.h | 16 |
27 files changed, 751 insertions, 243 deletions
diff --git a/src/BLEAdvertisedDevice.cpp b/src/BLEAdvertisedDevice.cpp index 83869cf..4347526 100644 --- a/src/BLEAdvertisedDevice.cpp +++ b/src/BLEAdvertisedDevice.cpp @@ -108,10 +108,21 @@ BLEScan* BLEAdvertisedDevice::getScan() { * @brief Get the Service UUID. * @return The Service UUID of the advertised device. */ -BLEUUID BLEAdvertisedDevice::getServiceUUID() { - return m_serviceUUID; +BLEUUID BLEAdvertisedDevice::getServiceUUID() { //TODO Remove it eventually, is no longer useful + return m_serviceUUIDs[0]; } // getServiceUUID +/** + * @brief Check advertised serviced for existence required UUID + * @return Return true if service is advertised + */ +bool BLEAdvertisedDevice::isAdvertisingService(BLEUUID uuid){ + for (int i = 0; i < m_serviceUUIDs.size(); ++i) { + if(m_serviceUUIDs[i].equals(uuid)) + return true; + } + return false; +} /** * @brief Get the TX Power. @@ -198,7 +209,7 @@ void BLEAdvertisedDevice::parseAdvertisement(uint8_t* payload) { payload++; // Skip to type sizeConsumed += 1 + length; // increase the size consumed. - if (length != 0) { // A length of 0 indicate that we have reached the end. + if (length != 0) { // A length of 0 indicates that we have reached the end. ad_type = *payload; payload++; length--; @@ -231,23 +242,19 @@ void BLEAdvertisedDevice::parseAdvertisement(uint8_t* payload) { break; } // ESP_BLE_AD_TYPE_FLAG - case ESP_BLE_AD_TYPE_16SRV_CMPL: { // Adv Data Type: 0x03 - setServiceUUID(BLEUUID(*reinterpret_cast<uint16_t*>(payload))); - break; - } // ESP_BLE_AD_TYPE_16SRV_CMPL - + case ESP_BLE_AD_TYPE_16SRV_CMPL: case ESP_BLE_AD_TYPE_16SRV_PART: { // Adv Data Type: 0x02 - setServiceUUID(BLEUUID(*reinterpret_cast<uint16_t*>(payload))); + for (int var = 0; var < length/2; ++var) { + setServiceUUID(BLEUUID(*reinterpret_cast<uint16_t*>(payload+var*2))); + } break; } // ESP_BLE_AD_TYPE_16SRV_PART - case ESP_BLE_AD_TYPE_32SRV_CMPL: { // Adv Data Type: 0x05 - setServiceUUID(BLEUUID(*reinterpret_cast<uint32_t*>(payload))); - break; - } // ESP_BLE_AD_TYPE_32SRV_CMPL - + case ESP_BLE_AD_TYPE_32SRV_CMPL: case ESP_BLE_AD_TYPE_32SRV_PART: { // Adv Data Type: 0x04 - setServiceUUID(BLEUUID(*reinterpret_cast<uint32_t*>(payload))); + for (int var = 0; var < length/4; ++var) { + setServiceUUID(BLEUUID(*reinterpret_cast<uint32_t*>(payload+var*4))); + } break; } // ESP_BLE_AD_TYPE_32SRV_PART @@ -355,23 +362,25 @@ void BLEAdvertisedDevice::setScan(BLEScan* pScan) { m_pScan = pScan; } // setScan + /** * @brief Set the Service UUID for this device. * @param [in] serviceUUID The discovered serviceUUID */ void BLEAdvertisedDevice::setServiceUUID(const char* serviceUUID) { return setServiceUUID(BLEUUID(serviceUUID)); -} // setRSSI +} // setServiceUUID + /** * @brief Set the Service UUID for this device. * @param [in] serviceUUID The discovered serviceUUID */ void BLEAdvertisedDevice::setServiceUUID(BLEUUID serviceUUID) { - m_serviceUUID = serviceUUID; + m_serviceUUIDs.push_back(serviceUUID); m_haveServiceUUID = true; - ESP_LOGD(LOG_TAG, "- setServiceUUID(): serviceUUID: %s", serviceUUID.toString().c_str()); -} // setRSSI + ESP_LOGD(LOG_TAG, "- addServiceUUID(): serviceUUID: %s", serviceUUID.toString().c_str()); +} // setServiceUUID /** diff --git a/src/BLEAdvertisedDevice.h b/src/BLEAdvertisedDevice.h index fbdeeec..aea6da0 100644 --- a/src/BLEAdvertisedDevice.h +++ b/src/BLEAdvertisedDevice.h @@ -38,6 +38,7 @@ public: BLEUUID getServiceUUID(); int8_t getTXPower(); + bool isAdvertisingService(BLEUUID uuid); bool haveAppearance(); bool haveManufacturerData(); bool haveName(); @@ -79,7 +80,7 @@ private: std::string m_name; BLEScan* m_pScan; int m_rssi; - BLEUUID m_serviceUUID; + std::vector<BLEUUID> m_serviceUUIDs; int8_t m_txPower; }; diff --git a/src/BLECharacteristic.cpp b/src/BLECharacteristic.cpp index 18ba65d..6d746cf 100644 --- a/src/BLECharacteristic.cpp +++ b/src/BLECharacteristic.cpp @@ -244,6 +244,7 @@ void BLECharacteristic::handleGATTServerEvent( // - 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) { m_semaphoreCreateEvt.give(); } @@ -418,11 +419,8 @@ void BLECharacteristic::handleGATTServerEvent( // Give each of the descriptors associated with this characteristic the opportunity to handle the // event. - BLEDescriptor *pDescriptor = m_descriptorMap.getFirst(); - while(pDescriptor != nullptr) { - pDescriptor->handleGATTServerEvent(event, gatts_if, param); - pDescriptor = m_descriptorMap.getNext(); - } + + m_descriptorMap.handleGATTServerEvent(event, gatts_if, param); } // handleGATTServerEvent @@ -556,7 +554,9 @@ 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); m_pCallbacks = pCallbacks; + ESP_LOGD(LOG_TAG, "<< setCallbacks"); } // setCallbacks @@ -695,4 +695,25 @@ std::string BLECharacteristic::toString() { return stringstream.str(); } // toString +BLECharacteristicCallbacks::~BLECharacteristicCallbacks() {} + +/** + * @brief Callback function to support a read request. + * @param [in] pCharacteristic The characteristic that is the source of the event. + */ +void BLECharacteristicCallbacks::onRead(BLECharacteristic *pCharacteristic) { + ESP_LOGD("BLECharacteristicCallbacks", ">> onRead: default"); + ESP_LOGD("BLECharacteristicCallbacks", "<< onRead"); +} // onRead + + +/** + * @brief Callback function to support a write request. + * @param [in] pCharacteristic The characteristic that is the source of the event. + */ +void BLECharacteristicCallbacks::onWrite(BLECharacteristic *pCharacteristic) { + ESP_LOGD("BLECharacteristicCallbacks", ">> onWrite: default"); + ESP_LOGD("BLECharacteristicCallbacks", "<< onWrite"); +} // onWrite + #endif /* CONFIG_BT_ENABLED */ diff --git a/src/BLECharacteristic.h b/src/BLECharacteristic.h index 24977c0..cacf1e5 100644 --- a/src/BLECharacteristic.h +++ b/src/BLECharacteristic.h @@ -77,6 +77,7 @@ public: void setWriteProperty(bool value); void setWriteNoResponseProperty(bool value); std::string toString(); + uint16_t getHandle(); static const uint32_t PROPERTY_READ = 1<<0; @@ -106,7 +107,6 @@ private: esp_ble_gatts_cb_param_t* param); void executeCreate(BLEService* pService); - uint16_t getHandle(); esp_gatt_char_prop_t getProperties(); BLEService* getService(); void setHandle(uint16_t handle); diff --git a/src/BLECharacteristicMap.cpp b/src/BLECharacteristicMap.cpp index bcf4a75..86a9744 100644 --- a/src/BLECharacteristicMap.cpp +++ b/src/BLECharacteristicMap.cpp @@ -41,8 +41,8 @@ BLECharacteristic* BLECharacteristicMap::getByUUID(const char* uuid) { */ BLECharacteristic* BLECharacteristicMap::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()); @@ -59,7 +59,7 @@ BLECharacteristic* BLECharacteristicMap::getFirst() { if (m_iterator == m_uuidMap.end()) { return nullptr; } - BLECharacteristic* pRet = m_iterator->second; + BLECharacteristic* pRet = m_iterator->first; m_iterator++; return pRet; } // getFirst @@ -73,7 +73,7 @@ BLECharacteristic* BLECharacteristicMap::getNext() { if (m_iterator == m_uuidMap.end()) { return nullptr; } - BLECharacteristic* pRet = m_iterator->second; + BLECharacteristic* pRet = m_iterator->first; m_iterator++; return pRet; } // getNext @@ -91,7 +91,7 @@ void BLECharacteristicMap::handleGATTServerEvent( esp_ble_gatts_cb_param_t* param) { // Invoke the handler for every Service we have. for (auto &myPair : m_uuidMap) { - myPair.second->handleGATTServerEvent(event, gatts_if, param); + myPair.first->handleGATTServerEvent(event, gatts_if, param); } } // handleGATTServerEvent @@ -115,9 +115,9 @@ void BLECharacteristicMap::setByHandle(uint16_t handle, * @return N/A. */ void BLECharacteristicMap::setByUUID( - BLEUUID uuid, - BLECharacteristic *pCharacteristic) { - m_uuidMap.insert(std::pair<std::string, BLECharacteristic *>(uuid.toString(), pCharacteristic)); + BLECharacteristic *pCharacteristic, + BLEUUID uuid) { + m_uuidMap.insert(std::pair<BLECharacteristic *, std::string>(pCharacteristic, uuid.toString())); } // setByUUID @@ -134,7 +134,7 @@ std::string BLECharacteristicMap::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 diff --git a/src/BLEClient.cpp b/src/BLEClient.cpp index 93f703a..83e778d 100644 --- a/src/BLEClient.cpp +++ b/src/BLEClient.cpp @@ -49,6 +49,7 @@ BLEClient::BLEClient() { m_conn_id = 0; m_gattc_if = 0; m_haveServices = false; + m_isConnected = false; // Initially, we are flagged as not connected. } // BLEClient @@ -76,7 +77,8 @@ bool BLEClient::connect(BLEAddress address) { // 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"); - esp_err_t errRc = esp_ble_gattc_app_register(0); + + 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; @@ -115,6 +117,7 @@ void BLEClient::disconnect() { 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 @@ -130,6 +133,22 @@ void BLEClient::gattClientEventHandler( // Execute handler code based on the type of event received. switch(event) { + + // + // ESP_GATTC_DISCONNECT_EVT + // + // disconnect: + // - esp_gatt_status_t status + // - 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. + m_isConnected = false; + break; + } // ESP_GATTC_DISCONNECT_EVT + + // // ESP_GATTC_OPEN_EVT // @@ -144,7 +163,10 @@ void BLEClient::gattClientEventHandler( if (m_pClientCallbacks != nullptr) { m_pClientCallbacks->onConnect(this); } - m_semaphoreOpenEvt.give(); + if (evtParam->open.status == ESP_GATT_OK) { + m_isConnected = true; // Flag us as connected. + } + m_semaphoreOpenEvt.give(evtParam->open.status); break; } // ESP_GATTC_OPEN_EVT @@ -211,6 +233,17 @@ void BLEClient::gattClientEventHandler( } // gattClientEventHandler +uint16_t BLEClient::getConnId() { + return m_conn_id; +} // getConnId + + + +esp_gatt_if_t BLEClient::getGattcIf() { + return m_gattc_if; +} // getGattcIf + + /** * @brief Retrieve the address of the peer. * @@ -221,14 +254,29 @@ BLEAddress BLEClient::getPeerAddress() { } // getAddress -uint16_t BLEClient::getConnId() { - return m_conn_id; -} // getConnId - - -esp_gatt_if_t BLEClient::getGattcIf() { - return m_gattc_if; -} // getGattcIf +/** + * @brief Ask the BLE server for the RSSI value. + * @return The RSSI value. + */ +int BLEClient::getRssi() { + ESP_LOGD(LOG_TAG, ">> getRssi()"); + if (!isConnected()) { + ESP_LOGD(LOG_TAG, "<< getRssi(): Not connected"); + return 0; + } + // We make the API call to read the RSSI value which is an asynchronous operation. We expect to receive + // an ESP_GAP_BLE_READ_RSSI_COMPLETE_EVT to indicate completion. + // + m_semaphoreRssiCmplEvt.take("getRssi"); + esp_err_t rc = ::esp_ble_gap_read_rssi(*getPeerAddress().getNative()); + if (rc != ESP_OK) { + ESP_LOGE(LOG_TAG, "<< getRssi: esp_ble_gap_read_rssi: rc=%d %s", rc, GeneralUtils::errorToString(rc)); + return 0; + } + int rssiValue = m_semaphoreRssiCmplEvt.wait("getRssi"); + ESP_LOGD(LOG_TAG, "<< getRssi(): %d", rssiValue); + return rssiValue; +} // getRssi /** @@ -301,6 +349,44 @@ std::map<std::string, BLERemoteService*>* BLEClient::getServices() { return &m_servicesMap; } // getServices +/** + * @brief Handle a received GAP event. + * + * @param [in] event + * @param [in] param + */ +void BLEClient::handleGAPEvent( + esp_gap_ble_cb_event_t event, + esp_ble_gap_cb_param_t* param) { + ESP_LOGD(LOG_TAG, "BLEClient ... handling GAP event!"); + switch(event) { + // + // ESP_GAP_BLE_READ_RSSI_COMPLETE_EVT + // + // read_rssi_cmpl + // - esp_bt_status_t status + // - int8_t rssi + // - esp_bd_addr_t remote_addr + // + case ESP_GAP_BLE_READ_RSSI_COMPLETE_EVT: { + m_semaphoreRssiCmplEvt.give((uint32_t)param->read_rssi_cmpl.rssi); + break; + } // ESP_GAP_BLE_READ_RSSI_COMPLETE_EVT + + default: + break; + } +} // handleGAPEvent + + +/** + * @brief Are we connected to a partner? + * @return True if we are connected and false if we are not connected. + */ +bool BLEClient::isConnected() { + return m_isConnected; +} // isConnected + /** * @brief Set the callbacks that will be invoked. diff --git a/src/BLEClient.h b/src/BLEClient.h index 494f51d..b24c71a 100644 --- a/src/BLEClient.h +++ b/src/BLEClient.h @@ -15,7 +15,7 @@ #include <string.h> #include <map> #include <string> -#include <BLERemoteService.h> +#include "BLERemoteService.h" #include "BLEService.h" #include "BLEAddress.h" @@ -32,9 +32,14 @@ public: bool connect(BLEAddress address); void disconnect(); BLEAddress getPeerAddress(); + int getRssi(); std::map<std::string, BLERemoteService*>* getServices(); BLERemoteService* getService(const char* uuid); BLERemoteService* getService(BLEUUID uuid); + void handleGAPEvent( + esp_gap_ble_cb_event_t event, + esp_ble_gap_cb_param_t* param); + bool isConnected(); void setClientCallbacks(BLEClientCallbacks *pClientCallbacks); std::string toString(); @@ -55,11 +60,13 @@ private: uint16_t m_conn_id; // int m_deviceType; esp_gatt_if_t m_gattc_if; + bool m_isConnected; BLEClientCallbacks* m_pClientCallbacks; 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<std::string, BLERemoteService*> m_servicesMap; bool m_haveServices; // Have we previously obtain the set of services. }; // class BLEDevice diff --git a/src/BLEDescriptor.cpp b/src/BLEDescriptor.cpp index 8362af0..054ef42 100644 --- a/src/BLEDescriptor.cpp +++ b/src/BLEDescriptor.cpp @@ -41,7 +41,8 @@ BLEDescriptor::BLEDescriptor(BLEUUID uuid) { m_value.attr_len = 0; m_value.attr_max_len = ESP_GATT_MAX_ATTR_LEN; m_handle = NULL_HANDLE; - m_pCharacteristic = nullptr; // No initial characteristic. + m_pCharacteristic = nullptr; // No initial characteristic. + m_pCallback = nullptr; // No initial callback. } // BLEDescriptor @@ -177,19 +178,30 @@ void BLEDescriptor::handleGATTServerEvent( // - uint8_t *value case ESP_GATTS_WRITE_EVT: { if (param->write.handle == m_handle) { - setValue(param->write.value, param->write.len); - esp_gatt_rsp_t rsp; + 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) { + 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. + } + } // End of ... this is our handle. + break; } // ESP_GATTS_WRITE_EVT @@ -205,25 +217,36 @@ void BLEDescriptor::handleGATTServerEvent( // - bool need_rsp // case ESP_GATTS_READ_EVT: { - ESP_LOGD(LOG_TAG, "- Testing: Sought handle: 0x%.2x == descriptor handle: 0x%.2x ?", param->read.handle, m_handle); - if (param->read.handle == m_handle) { - ESP_LOGD(LOG_TAG, "Sending a response (esp_ble_gatts_send_response)"); - if (param->read.need_rsp) { + if (param->read.handle == m_handle) { // If this event is for this descriptor ... process it + + if (m_pCallback != nullptr) { // If we have a user supplied callback, invoke it now. + 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.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) { + 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)); } - } - } // ESP_GATTS_READ_EVT + } // End of need a response. + } // End of this is our handle break; } // ESP_GATTS_READ_EVT + default: { break; } @@ -232,6 +255,17 @@ void BLEDescriptor::handleGATTServerEvent( /** + * @brief Set the callback handlers for this descriptor. + * @param [in] pCallbacks An instance of a callback structure used to define any callbacks for the descriptor. + */ +void BLEDescriptor::setCallbacks(BLEDescriptorCallbacks* pCallback) { + ESP_LOGD(LOG_TAG, ">> setCallbacks: 0x%x", (uint32_t)pCallback); + m_pCallback = pCallback; + ESP_LOGD(LOG_TAG, "<< setCallbacks"); +} // setCallbacks + + +/** * @brief Set the handle of this descriptor. * Set the handle of this descriptor to be the supplied value. * @param [in] handle The handle to be associated with this descriptor. @@ -278,4 +312,28 @@ std::string BLEDescriptor::toString() { stringstream << "UUID: " << m_bleUUID.toString() + ", handle: 0x" << std::setw(2) << m_handle; return stringstream.str(); } // toString + + +BLEDescriptorCallbacks::~BLEDescriptorCallbacks() {} + +/** + * @brief Callback function to support a read request. + * @param [in] pDescriptor The descriptor that is the source of the event. + */ +void BLEDescriptorCallbacks::onRead(BLEDescriptor* pDescriptor) { + ESP_LOGD("BLEDescriptorCallbacks", ">> onRead: default"); + ESP_LOGD("BLEDescriptorCallbacks", "<< onRead"); +} // onRead + + +/** + * @brief Callback function to support a write request. + * @param [in] pDescriptor The descriptor that is the source of the event. + */ +void BLEDescriptorCallbacks::onWrite(BLEDescriptor* pDescriptor) { + ESP_LOGD("BLEDescriptorCallbacks", ">> onWrite: default"); + ESP_LOGD("BLEDescriptorCallbacks", "<< onWrite"); +} // onWrite + + #endif /* CONFIG_BT_ENABLED */ diff --git a/src/BLEDescriptor.h b/src/BLEDescriptor.h index 1d32d50..4eda4c9 100644 --- a/src/BLEDescriptor.h +++ b/src/BLEDescriptor.h @@ -17,6 +17,7 @@ class BLEService; class BLECharacteristic; +class BLEDescriptorCallbacks; /** * @brief A model of a %BLE descriptor. @@ -27,6 +28,7 @@ public: BLEDescriptor(BLEUUID uuid); virtual ~BLEDescriptor(); + uint16_t getHandle(); size_t getLength(); BLEUUID getUUID(); uint8_t* getValue(); @@ -34,6 +36,7 @@ public: esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t* param); + void setCallbacks(BLEDescriptorCallbacks* pCallbacks); void setValue(uint8_t* data, size_t size); void setValue(std::string value); std::string toString(); @@ -45,10 +48,24 @@ private: esp_attr_value_t m_value; uint16_t m_handle; BLECharacteristic* m_pCharacteristic; + BLEDescriptorCallbacks* m_pCallback; void executeCreate(BLECharacteristic* pCharacteristic); - uint16_t getHandle(); void setHandle(uint16_t handle); FreeRTOS::Semaphore m_semaphoreCreateEvt = FreeRTOS::Semaphore("CreateEvt"); }; + +/** + * @brief Callbacks that can be associated with a %BLE descriptors to inform of events. + * + * When a server application creates a %BLE descriptor, we may wish to be informed when there is either + * a read or write request to the descriptors value. An application can register a + * sub-classed instance of this class and will be notified when such an event happens. + */ +class BLEDescriptorCallbacks { +public: + virtual ~BLEDescriptorCallbacks(); + virtual void onRead(BLEDescriptor* pDescriptor); + virtual void onWrite(BLEDescriptor* pDescriptor); +}; #endif /* CONFIG_BT_ENABLED */ #endif /* COMPONENTS_CPP_UTILS_BLEDESCRIPTOR_H_ */ diff --git a/src/BLEDevice.cpp b/src/BLEDevice.cpp index 97d02b1..a701459 100644 --- a/src/BLEDevice.cpp +++ b/src/BLEDevice.cpp @@ -39,7 +39,7 @@ static const char* LOG_TAG = "BLEDevice"; BLEServer* BLEDevice::m_pServer = nullptr; BLEScan* BLEDevice::m_pScan = nullptr; BLEClient* BLEDevice::m_pClient = nullptr; - +bool initialized = false; /** * @brief Create a new instance of a client. * @return A new instance of the client. @@ -147,20 +147,28 @@ void BLEDevice::gapEventHandler( BLEDevice::m_pServer->handleGAPEvent(event, param); } + if (BLEDevice::m_pClient != nullptr) { + BLEDevice::m_pClient->handleGAPEvent(event, param); + } + if (BLEDevice::m_pScan != nullptr) { - BLEDevice::getScan()->gapEventHandler(event, param); + BLEDevice::getScan()->handleGAPEvent(event, param); } } // gapEventHandler /** * @brief Retrieve the Scan object that we use for scanning. - * @return The scanning object reference. + * @return The scanning object reference. This is a singleton object. The caller should not + * try and release/delete it. */ BLEScan* BLEDevice::getScan() { + //ESP_LOGD(LOG_TAG, ">> getScan"); if (m_pScan == nullptr) { m_pScan = new BLEScan(); + //ESP_LOGD(LOG_TAG, " - creating a new scan object"); } + //ESP_LOGD(LOG_TAG, "<< getScan: Returning object at 0x%x", (uint32_t)m_pScan); return m_pScan; } // getScan @@ -170,70 +178,102 @@ BLEScan* BLEDevice::getScan() { * @param deviceName The device name of the device. */ void BLEDevice::init(std::string deviceName) { - esp_err_t errRc = ::nvs_flash_init(); - if (errRc != ESP_OK) { - ESP_LOGE(LOG_TAG, "nvs_flash_init: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); - return; - } - - esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); - errRc = esp_bt_controller_init(&bt_cfg); - if (errRc != ESP_OK) { - ESP_LOGE(LOG_TAG, "esp_bt_controller_init: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); - return; - } + if(!initialized){ + initialized = true; + esp_err_t errRc = ::nvs_flash_init(); + if (errRc != ESP_OK) { + ESP_LOGE(LOG_TAG, "nvs_flash_init: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); + return; + } - errRc = esp_bt_controller_enable(ESP_BT_MODE_BTDM); - if (errRc != ESP_OK) { - ESP_LOGE(LOG_TAG, "esp_bt_controller_enable: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); - return; - } + esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); + errRc = esp_bt_controller_init(&bt_cfg); + if (errRc != ESP_OK) { + ESP_LOGE(LOG_TAG, "esp_bt_controller_init: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); + return; + } +#ifndef CLASSIC_BT_ENABLED + // esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT); //FIXME waiting for response from esp-idf issue + errRc = esp_bt_controller_enable(ESP_BT_MODE_BLE); + //errRc = esp_bt_controller_enable(ESP_BT_MODE_BTDM); + 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) { + ESP_LOGE(LOG_TAG, "esp_bt_controller_enable: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); + return; + } +#endif + errRc = esp_bluedroid_init(); + if (errRc != ESP_OK) { + ESP_LOGE(LOG_TAG, "esp_bluedroid_init: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); + return; + } - errRc = esp_bluedroid_init(); - if (errRc != ESP_OK) { - ESP_LOGE(LOG_TAG, "esp_bluedroid_init: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); - return; - } + errRc = esp_bluedroid_enable(); + if (errRc != ESP_OK) { + ESP_LOGE(LOG_TAG, "esp_bluedroid_enable: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); + return; + } - errRc = esp_bluedroid_enable(); - if (errRc != ESP_OK) { - ESP_LOGE(LOG_TAG, "esp_bluedroid_enable: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); - return; - } + errRc = esp_ble_gap_register_callback(BLEDevice::gapEventHandler); + if (errRc != ESP_OK) { + ESP_LOGE(LOG_TAG, "esp_ble_gap_register_callback: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); + return; + } - errRc = esp_ble_gap_register_callback(BLEDevice::gapEventHandler); - if (errRc != ESP_OK) { - ESP_LOGE(LOG_TAG, "esp_ble_gap_register_callback: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); - return; - } + errRc = esp_ble_gattc_register_callback(BLEDevice::gattClientEventHandler); + if (errRc != ESP_OK) { + ESP_LOGE(LOG_TAG, "esp_ble_gattc_register_callback: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); + return; + } - errRc = esp_ble_gattc_register_callback(BLEDevice::gattClientEventHandler); - if (errRc != ESP_OK) { - ESP_LOGE(LOG_TAG, "esp_ble_gattc_register_callback: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); - return; - } + errRc = esp_ble_gatts_register_callback(BLEDevice::gattServerEventHandler); + if (errRc != ESP_OK) { + ESP_LOGE(LOG_TAG, "esp_ble_gatts_register_callback: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); + return; + } - errRc = esp_ble_gatts_register_callback(BLEDevice::gattServerEventHandler); - if (errRc != ESP_OK) { - ESP_LOGE(LOG_TAG, "esp_ble_gatts_register_callback: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); - return; + errRc = ::esp_ble_gap_set_device_name(deviceName.c_str()); + if (errRc != ESP_OK) { + ESP_LOGE(LOG_TAG, "esp_ble_gap_set_device_name: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); + return; + }; + + esp_ble_io_cap_t iocap = ESP_IO_CAP_NONE; + errRc = ::esp_ble_gap_set_security_param(ESP_BLE_SM_IOCAP_MODE, &iocap, sizeof(uint8_t)); + if (errRc != ESP_OK) { + ESP_LOGE(LOG_TAG, "esp_ble_gap_set_security_param: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); + return; + }; } + vTaskDelay(200/portTICK_PERIOD_MS); // Delay for 200 msecs as a workaround to an apparent Arduino environment issue. +} // init - errRc = ::esp_ble_gap_set_device_name(deviceName.c_str()); - if (errRc != ESP_OK) { - ESP_LOGE(LOG_TAG, "esp_ble_gap_set_device_name: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); - return; - }; - esp_ble_io_cap_t iocap = ESP_IO_CAP_NONE; - errRc = ::esp_ble_gap_set_security_param(ESP_BLE_SM_IOCAP_MODE, &iocap, sizeof(uint8_t)); +/** + * @brief Set the transmission power. + * The power level can be one of: + * * ESP_PWR_LVL_N14 + * * ESP_PWR_LVL_N11 + * * ESP_PWR_LVL_N8 + * * ESP_PWR_LVL_N5 + * * ESP_PWR_LVL_N2 + * * ESP_PWR_LVL_P1 + * * ESP_PWR_LVL_P4 + * * ESP_PWR_LVL_P7 + * @param [in] powerLevel. + */ +/* STATIC */ void BLEDevice::setPower(esp_power_level_t powerLevel) { + ESP_LOGD(LOG_TAG, ">> setPower: %d", powerLevel); + esp_err_t errRc = ::esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_DEFAULT, powerLevel); if (errRc != ESP_OK) { - ESP_LOGE(LOG_TAG, "esp_ble_gap_set_security_param: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); - return; + ESP_LOGE(LOG_TAG, "esp_ble_tx_power_set: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); }; - - vTaskDelay(200/portTICK_PERIOD_MS); // Delay for 200 msecs as a workaround to an apparent Arduino environment issue. -} // init - + ESP_LOGD(LOG_TAG, "<< setPower"); +} // setPower #endif // CONFIG_BT_ENABLED diff --git a/src/BLEDevice.h b/src/BLEDevice.h index eb9fdaa..acf20f3 100644 --- a/src/BLEDevice.h +++ b/src/BLEDevice.h @@ -13,6 +13,7 @@ #include <esp_gattc_api.h> // ESP32 BLE #include <map> // Part of C++ STL #include <string> +#include <bt.h> #include "BLEServer.h" #include "BLEClient.h" @@ -52,6 +53,9 @@ private: esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t* param); +public: + static void setPower(esp_power_level_t powerLevel); + }; // class BLE #endif // CONFIG_BT_ENABLED diff --git a/src/BLERemoteCharacteristic.cpp b/src/BLERemoteCharacteristic.cpp index ba781d2..64b0a92 100644 --- a/src/BLERemoteCharacteristic.cpp +++ b/src/BLERemoteCharacteristic.cpp @@ -311,6 +311,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 diff --git a/src/BLERemoteService.cpp b/src/BLERemoteService.cpp index c0df06c..5227964 100644 --- a/src/BLERemoteService.cpp +++ b/src/BLERemoteService.cpp @@ -115,7 +115,7 @@ void BLERemoteService::gattClientEventHandler( // Send the event to each of the characteristics owned by this service. for (auto &myPair : m_characteristicMap) { - myPair.second->gattClientEventHandler(event, gattc_if, evtParam); + myPair.first->gattClientEventHandler(event, gattc_if, evtParam); } } // gattClientEventHandler @@ -147,8 +147,8 @@ BLERemoteCharacteristic* BLERemoteService::getCharacteristic(BLEUUID uuid) { } std::string v = uuid.toString(); for (auto &myPair : m_characteristicMap) { - if (myPair.first == v) { - return myPair.second; + if (myPair.second == v) { + return myPair.first; } } return nullptr; @@ -257,7 +257,7 @@ void BLERemoteService::retrieveCharacteristics() { this ); - m_characteristicMap.insert(std::pair<std::string, BLERemoteCharacteristic*>(pNewRemoteCharacteristic->getUUID().toString(), pNewRemoteCharacteristic)); + m_characteristicMap.insert(std::pair<BLERemoteCharacteristic*, std::string>(pNewRemoteCharacteristic, pNewRemoteCharacteristic->getUUID().toString())); offset++; // Increment our count of number of descriptors found. } // Loop forever (until we break inside the loop). @@ -271,7 +271,7 @@ void BLERemoteService::retrieveCharacteristics() { * @brief Retrieve a map of all the characteristics of this service. * @return A map of all the characteristics of this service. */ -std::map<std::string, BLERemoteCharacteristic*>* BLERemoteService::getCharacteristics() { +std::map<BLERemoteCharacteristic*, std::string>* BLERemoteService::getCharacteristics() { ESP_LOGD(LOG_TAG, ">> getCharacteristics() 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 @@ -325,7 +325,7 @@ BLEUUID BLERemoteService::getUUID() { */ void BLERemoteService::removeCharacteristics() { for (auto &myPair : m_characteristicMap) { - delete myPair.second; + delete myPair.first; m_characteristicMap.erase(myPair.first); } m_characteristicMap.clear(); // Clear the map @@ -343,7 +343,7 @@ std::string BLERemoteService::toString() { ss << ", start_handle: " << std::dec << m_startHandle << " 0x" << std::hex << m_startHandle << ", end_handle: " << std::dec << m_endHandle << " 0x" << std::hex << m_endHandle; for (auto &myPair : m_characteristicMap) { - ss << "\n" << myPair.second->toString(); + ss << "\n" << myPair.first->toString(); // myPair.second is the value } return ss.str(); diff --git a/src/BLERemoteService.h b/src/BLERemoteService.h index 2007fa2..521effc 100644 --- a/src/BLERemoteService.h +++ b/src/BLERemoteService.h @@ -32,7 +32,9 @@ public: // Public methods BLERemoteCharacteristic* getCharacteristic(const char* uuid); BLERemoteCharacteristic* getCharacteristic(BLEUUID uuid); - std::map<std::string, BLERemoteCharacteristic*>* getCharacteristics(); + BLERemoteCharacteristic* getCharacteristic(uint16_t uuid); + std::map<BLERemoteCharacteristic*, std::string>* getCharacteristics(); + void getCharacteristics(std::map<uint16_t, BLERemoteCharacteristic*>* ptr); BLEClient* getClient(void); uint16_t getHandle(); @@ -61,7 +63,9 @@ private: // Properties // We maintain a map of characteristics owned by this service keyed by a string representation of the UUID. - std::map<std::string, BLERemoteCharacteristic *> m_characteristicMap; + std::map<BLERemoteCharacteristic *, std::string> m_characteristicMap; + // We maintain a map of characteristics owned by this service keyed by a handle. + std::map<uint16_t, BLERemoteCharacteristic *> m_characteristicMapByHandle; bool m_haveCharacteristics; // Have we previously obtained the characteristics. BLEClient* m_pClient; diff --git a/src/BLEScan.cpp b/src/BLEScan.cpp index d3157b7..7c5b7bd 100644 --- a/src/BLEScan.cpp +++ b/src/BLEScan.cpp @@ -43,7 +43,7 @@ BLEScan::BLEScan() { * @param [in] event The event type for this event. * @param [in] param Parameter data for this event. */ -void BLEScan::gapEventHandler( +void BLEScan::handleGAPEvent( esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t* param) { @@ -66,12 +66,21 @@ void BLEScan::gapEventHandler( case ESP_GAP_BLE_SCAN_RESULT_EVT: { switch(param->scan_rst.search_evt) { + // + // ESP_GAP_SEARCH_INQ_CMPL_EVT + // + // 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: { m_stopped = true; m_semaphoreScanEnd.give(); break; } // ESP_GAP_SEARCH_INQ_CMPL_EVT + // + // ESP_GAP_SEARCH_INQ_RES_EVT + // + // Result that has arrived back from a Scan inquiry. case ESP_GAP_SEARCH_INQ_RES_EVT: { if (m_stopped) { // If we are not scanning, nothing to do with the extra results. break; @@ -177,7 +186,7 @@ void BLEScan::setWindow(uint16_t windowMSecs) { BLEScanResults BLEScan::start(uint32_t duration) { ESP_LOGD(LOG_TAG, ">> start(duration=%d)", duration); - m_semaphoreScanEnd.take("start"); + m_semaphoreScanEnd.take(std::string("start")); m_scanResults.m_vectorAdvertisedDevices.clear(); @@ -199,8 +208,7 @@ BLEScanResults BLEScan::start(uint32_t duration) { m_stopped = false; - m_semaphoreScanEnd.take("start"); - m_semaphoreScanEnd.give(); + m_semaphoreScanEnd.wait("start"); // Wait for the semaphore to release. ESP_LOGD(LOG_TAG, "<< start()"); return m_scanResults; @@ -230,6 +238,17 @@ void BLEScan::stop() { /** + * @brief Dump the scan results to the log. + */ +void BLEScanResults::dump() { + ESP_LOGD(LOG_TAG, ">> Dump scan results:"); + for (int i=0; i<getCount(); i++) { + ESP_LOGD(LOG_TAG, "- %s", getDevice(i).toString().c_str()); + } +} // dump + + +/** * @brief Return the count of devices found in the last scan. * @return The number of devices found in the last scan. */ @@ -248,4 +267,5 @@ BLEAdvertisedDevice BLEScanResults::getDevice(uint32_t i) { return m_vectorAdvertisedDevices.at(i); } + #endif /* CONFIG_BT_ENABLED */ diff --git a/src/BLEScan.h b/src/BLEScan.h index bc7f431..edf79a9 100644 --- a/src/BLEScan.h +++ b/src/BLEScan.h @@ -31,6 +31,7 @@ class BLEScan; */ class BLEScanResults { public: + void dump(); int getCount(); BLEAdvertisedDevice getDevice(uint32_t i); @@ -46,8 +47,6 @@ private: */ class BLEScan { public: - BLEScan(); - void setActiveScan(bool active); void setAdvertisedDeviceCallbacks(BLEAdvertisedDeviceCallbacks* pAdvertisedDeviceCallbacks); void setInterval(uint16_t intervalMSecs); @@ -56,8 +55,9 @@ public: void stop(); private: + BLEScan(); // One doesn't create a new instance instead one asks the BLEDevice for the singleton. friend class BLEDevice; - void gapEventHandler( + void handleGAPEvent( esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t* param); void parseAdvertisement(BLEClient* pRemoteDevice, uint8_t *payload); diff --git a/src/BLEServer.cpp b/src/BLEServer.cpp index 0e66ec0..0d9bd6b 100644 --- a/src/BLEServer.cpp +++ b/src/BLEServer.cpp @@ -123,7 +123,7 @@ uint16_t BLEServer::getGattsIf() { } /** - * @brief Handle a receiver GAP event. + * @brief Handle a received GAP event. * * @param [in] event * @param [in] param diff --git a/src/BLEService.cpp b/src/BLEService.cpp index 669ed26..32bcc57 100644 --- a/src/BLEService.cpp +++ b/src/BLEService.cpp @@ -22,6 +22,10 @@ #include "BLEUtils.h" #include "GeneralUtils.h" +#ifdef ARDUINO_ARCH_ESP32 +#include "esp32-hal-log.h" +#endif + #define NULL_HANDLE (0xffff) static const char* LOG_TAG = "BLEService"; // Tag for logging. @@ -189,12 +193,12 @@ void BLEService::addCharacteristic(BLECharacteristic* pCharacteristic) { // Check that we don't add the same characteristic twice. if (m_characteristicMap.getByUUID(pCharacteristic->getUUID()) != nullptr) { ESP_LOGE(LOG_TAG, "<< Attempt to add a characteristic but we already have one with this UUID"); - return; + //return; } // Remember this characteristic in our map of characteristics. At this point, we can lookup by UUID // but not by handle. The handle is allocated to us on the ESP_GATTS_ADD_CHAR_EVT. - m_characteristicMap.setByUUID(pCharacteristic->getUUID(), pCharacteristic); + m_characteristicMap.setByUUID(pCharacteristic, pCharacteristic->getUUID()); ESP_LOGD(LOG_TAG, "<< addCharacteristic()"); } // addCharacteristic @@ -245,7 +249,7 @@ void BLEService::handleGATTServerEvent( // for that characteristic. case ESP_GATTS_ADD_CHAR_EVT: { if (m_handle == param->add_char.service_handle) { - BLECharacteristic *pCharacteristic = getCharacteristic(BLEUUID(param->add_char.char_uuid)); + BLECharacteristic *pCharacteristic = getLastCreatedCharacteristic(); if (pCharacteristic == nullptr) { ESP_LOGE(LOG_TAG, "Expected to find characteristic with UUID: %s, but didnt!", BLEUUID(param->add_char.char_uuid).toString().c_str()); diff --git a/src/BLEService.h b/src/BLEService.h index 19b472e..b37092f 100644 --- a/src/BLEService.h +++ b/src/BLEService.h @@ -24,8 +24,8 @@ class BLEServer; */ class BLECharacteristicMap { public: - void setByUUID(const char* uuid, BLECharacteristic* pCharacteristic); - void setByUUID(BLEUUID uuid, BLECharacteristic* pCharacteristic); + 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(BLEUUID uuid); @@ -40,9 +40,9 @@ public: private: - std::map<std::string, BLECharacteristic*> m_uuidMap; + std::map<BLECharacteristic*, std::string> m_uuidMap; std::map<uint16_t, BLECharacteristic*> m_handleMap; - std::map<std::string, BLECharacteristic*>::iterator m_iterator; + std::map<BLECharacteristic*, std::string>::iterator m_iterator; }; @@ -66,6 +66,7 @@ public: BLEServer* getServer(); void start(); std::string toString(); + uint16_t getHandle(); private: friend class BLEServer; @@ -86,7 +87,6 @@ private: uint32_t m_numHandles; - uint16_t getHandle(); BLECharacteristic* getLastCreatedCharacteristic(); void handleGATTServerEvent( esp_gatts_cb_event_t event, diff --git a/src/BLEUUID.cpp b/src/BLEUUID.cpp index 19da518..f5c6cee 100644 --- a/src/BLEUUID.cpp +++ b/src/BLEUUID.cpp @@ -14,6 +14,9 @@ #include "BLEUUID.h" static const char* LOG_TAG = "BLEUUID"; +#ifdef ARDUINO_ARCH_ESP32 +#include "esp32-hal-log.h" +#endif /** * @brief Copy memory from source to target but in reverse order. @@ -144,6 +147,7 @@ BLEUUID::BLEUUID(uint16_t uuid) { m_uuid.len = ESP_UUID_LEN_16; m_uuid.uuid.uuid16 = uuid; m_valueSet = true; + } // BLEUUID @@ -345,4 +349,22 @@ std::string BLEUUID::toString() { std::setw(2) << (int)m_uuid.uuid.uuid128[0]; return ss.str(); } // toString + +BLEUUID BLEUUID::fromString(std::string _uuid){ + uint8_t start = 0; + if(strstr(_uuid.c_str(), "0x") != nullptr){ + start = 2; + } + uint8_t len = _uuid.length() - start; + if(len == 4 ){ + uint16_t x = strtoul(_uuid.substr(start, len).c_str(), NULL, 16); + return BLEUUID(x); + }else if(len == 8){ + uint32_t x = strtoul(_uuid.substr(start, len).c_str(), NULL, 16); + return BLEUUID(x); + }else if (len == 36){ + return BLEUUID(_uuid); + } + return BLEUUID(); +} #endif /* CONFIG_BT_ENABLED */ diff --git a/src/BLEUUID.h b/src/BLEUUID.h index a11220b..bbe9b87 100644 --- a/src/BLEUUID.h +++ b/src/BLEUUID.h @@ -28,6 +28,7 @@ public: esp_bt_uuid_t* getNative(); BLEUUID to128(); std::string toString(); + static BLEUUID fromString(std::string uuid); private: esp_bt_uuid_t m_uuid; // The underlying UUID structure that this class wraps. diff --git a/src/BLEUtils.cpp b/src/BLEUtils.cpp index a91bbcc..5d1dec9 100644 --- a/src/BLEUtils.cpp +++ b/src/BLEUtils.cpp @@ -24,6 +24,10 @@ #include <sstream> #include <iomanip> +#ifdef ARDUINO_ARCH_ESP32 +#include "esp32-hal-log.h" +#endif + static const char* LOG_TAG = "BLEUtils"; // Tag for logging. /* @@ -33,7 +37,7 @@ static std::map<uint16_t, BLEClient *> g_connIdMap; typedef struct { uint32_t assignedNumber; - std::string name; + const char* name; } member_t; static const member_t members_ids[] = { @@ -291,7 +295,7 @@ static const member_t members_ids[] = { typedef struct { uint32_t assignedNumber; - std::string name; + const char* name; } gattdescriptor_t; static const gattdescriptor_t g_descriptor_ids[] = { @@ -315,7 +319,7 @@ static const gattdescriptor_t g_descriptor_ids[] = { typedef struct { uint32_t assignedNumber; - std::string name; + const char* name; } characteristicMap_t; static const characteristicMap_t g_characteristicsMappings[] = { @@ -542,8 +546,8 @@ static const characteristicMap_t g_characteristicsMappings[] = { * @brief Mapping from service ids to names */ typedef struct { - std::string name; - std::string type; + const char* name; + const char* type; uint32_t assignedNumber; } gattService_t; @@ -634,12 +638,38 @@ const char* BLEUtils::addressTypeToString(esp_ble_addr_type_t type) { case BLE_ADDR_TYPE_RPA_RANDOM: return "BLE_ADDR_TYPE_RPA_RANDOM"; default: - return "Unknown esp_ble_addr_type_t"; + return " esp_ble_addr_type_t"; } } // addressTypeToString /** + * @brief Convert the BLE Advertising Data flags to a string. + * @param adFlags The flags to convert + * @return std::string A string representation of the advertising flags. + */ +std::string BLEUtils::adFlagsToString(uint8_t adFlags) { + std::stringstream ss; + if (adFlags & (1<<0)) { + ss << "[LE Limited Discoverable Mode] "; + } + if (adFlags & (1<<1)) { + ss << "[LE General Discoverable Mode] "; + } + if (adFlags & (1<<2)) { + ss << "[BR/EDR Not Supported] "; + } + if (adFlags & (1<<3)) { + ss << "[Simultaneous LE and BR/EDR to Same Device Capable (Controller)] "; + } + if (adFlags & (1<<4)) { + ss << "[Simultaneous LE and BR/EDR to Same Device Capable (Host)] "; + } + return ss.str(); +} // adFlagsToString + + +/** * @brief Given an advertising type, return a string representation of the type. * * For details see ... @@ -649,59 +679,84 @@ const char* BLEUtils::addressTypeToString(esp_ble_addr_type_t type) { */ const char* BLEUtils::advTypeToString(uint8_t advType) { switch(advType) { - case ESP_BLE_AD_TYPE_FLAG: + case ESP_BLE_AD_TYPE_FLAG: // 0x01 return "ESP_BLE_AD_TYPE_FLAG"; - case ESP_BLE_AD_TYPE_16SRV_PART: + + case ESP_BLE_AD_TYPE_16SRV_PART: // 0x02 return "ESP_BLE_AD_TYPE_16SRV_PART"; - case ESP_BLE_AD_TYPE_16SRV_CMPL: + + case ESP_BLE_AD_TYPE_16SRV_CMPL: // 0x03 return "ESP_BLE_AD_TYPE_16SRV_CMPL"; - case ESP_BLE_AD_TYPE_32SRV_PART: + + case ESP_BLE_AD_TYPE_32SRV_PART: // 0x04 return "ESP_BLE_AD_TYPE_32SRV_PART"; - case ESP_BLE_AD_TYPE_32SRV_CMPL: + + case ESP_BLE_AD_TYPE_32SRV_CMPL: // 0x05 return "ESP_BLE_AD_TYPE_32SRV_CMPL"; - case ESP_BLE_AD_TYPE_128SRV_PART: + + case ESP_BLE_AD_TYPE_128SRV_PART: // 0x06 return "ESP_BLE_AD_TYPE_128SRV_PART"; - case ESP_BLE_AD_TYPE_128SRV_CMPL: + + case ESP_BLE_AD_TYPE_128SRV_CMPL: // 0x07 return "ESP_BLE_AD_TYPE_128SRV_CMPL"; - case ESP_BLE_AD_TYPE_NAME_SHORT: + + case ESP_BLE_AD_TYPE_NAME_SHORT: // 0x08 return "ESP_BLE_AD_TYPE_NAME_SHORT"; - case ESP_BLE_AD_TYPE_NAME_CMPL: + + case ESP_BLE_AD_TYPE_NAME_CMPL: // 0x09 return "ESP_BLE_AD_TYPE_NAME_CMPL"; - case ESP_BLE_AD_TYPE_TX_PWR: + + case ESP_BLE_AD_TYPE_TX_PWR: // 0x0a return "ESP_BLE_AD_TYPE_TX_PWR"; - case ESP_BLE_AD_TYPE_DEV_CLASS: + + case ESP_BLE_AD_TYPE_DEV_CLASS: // 0x0b return "ESP_BLE_AD_TYPE_DEV_CLASS"; - case ESP_BLE_AD_TYPE_SM_TK: + + case ESP_BLE_AD_TYPE_SM_TK: // 0x10 return "ESP_BLE_AD_TYPE_SM_TK"; - case ESP_BLE_AD_TYPE_SM_OOB_FLAG: + + case ESP_BLE_AD_TYPE_SM_OOB_FLAG: // 0x11 return "ESP_BLE_AD_TYPE_SM_OOB_FLAG"; - case ESP_BLE_AD_TYPE_INT_RANGE: + + case ESP_BLE_AD_TYPE_INT_RANGE: // 0x12 return "ESP_BLE_AD_TYPE_INT_RANGE"; - case ESP_BLE_AD_TYPE_SOL_SRV_UUID: + + case ESP_BLE_AD_TYPE_SOL_SRV_UUID: // 0x14 return "ESP_BLE_AD_TYPE_SOL_SRV_UUID"; - case ESP_BLE_AD_TYPE_128SOL_SRV_UUID: + + case ESP_BLE_AD_TYPE_128SOL_SRV_UUID: // 0x15 return "ESP_BLE_AD_TYPE_128SOL_SRV_UUID"; - case ESP_BLE_AD_TYPE_SERVICE_DATA: + + case ESP_BLE_AD_TYPE_SERVICE_DATA: // 0x16 return "ESP_BLE_AD_TYPE_SERVICE_DATA"; - case ESP_BLE_AD_TYPE_PUBLIC_TARGET: + + case ESP_BLE_AD_TYPE_PUBLIC_TARGET: // 0x17 return "ESP_BLE_AD_TYPE_PUBLIC_TARGET"; - case ESP_BLE_AD_TYPE_RANDOM_TARGET: - return "ESP_BLE_Amap1D_TYPE_RANDOM_TARGET"; - case ESP_BLE_AD_TYPE_APPEARANCE: + + case ESP_BLE_AD_TYPE_RANDOM_TARGET: // 0x18 + return "ESP_BLE_AD_TYPE_RANDOM_TARGET"; + + case ESP_BLE_AD_TYPE_APPEARANCE: // 0x19 return "ESP_BLE_AD_TYPE_APPEARANCE"; - case ESP_BLE_AD_TYPE_ADV_INT: + + case ESP_BLE_AD_TYPE_ADV_INT: // 0x1a return "ESP_BLE_AD_TYPE_ADV_INT"; + case ESP_BLE_AD_TYPE_32SOL_SRV_UUID: return "ESP_BLE_AD_TYPE_32SOL_SRV_UUID"; - case ESP_BLE_AD_TYPE_32SERVICE_DATA: + + case ESP_BLE_AD_TYPE_32SERVICE_DATA: // 0x20 return "ESP_BLE_AD_TYPE_32SERVICE_DATA"; - case ESP_BLE_AD_TYPE_128SERVICE_DATA: + + case ESP_BLE_AD_TYPE_128SERVICE_DATA: // 0x21 return "ESP_BLE_AD_TYPE_128SERVICE_DATA"; - case ESP_BLE_AD_MANUFACTURER_SPECIFIC_TYPE: + + case ESP_BLE_AD_MANUFACTURER_SPECIFIC_TYPE: // 0xff return "ESP_BLE_AD_MANUFACTURER_SPECIFIC_TYPE"; + default: - ESP_LOGD(LOG_TAG, "Unknown adv data type: 0x%x", advType); - return "Unknown"; + ESP_LOGD(LOG_TAG, " adv data type: 0x%x", advType); + return ""; } // End switch } // advTypeToString @@ -909,52 +964,76 @@ std::string BLEUtils::gattServerEventTypeToString(esp_gatts_cb_event_t eventType switch(eventType) { case ESP_GATTS_REG_EVT: return "ESP_GATTS_REG_EVT"; + case ESP_GATTS_READ_EVT: return "ESP_GATTS_READ_EVT"; + case ESP_GATTS_WRITE_EVT: return "ESP_GATTS_WRITE_EVT"; + case ESP_GATTS_EXEC_WRITE_EVT: return "ESP_GATTS_EXEC_WRITE_EVT"; + case ESP_GATTS_MTU_EVT: return "ESP_GATTS_MTU_EVT"; + case ESP_GATTS_CONF_EVT: return "ESP_GATTS_CONF_EVT"; + case ESP_GATTS_UNREG_EVT: return "ESP_GATTS_UNREG_EVT"; + case ESP_GATTS_CREATE_EVT: return "ESP_GATTS_CREATE_EVT"; + case ESP_GATTS_ADD_INCL_SRVC_EVT: return "ESP_GATTS_ADD_INCL_SRVC_EVT"; + case ESP_GATTS_ADD_CHAR_EVT: return "ESP_GATTS_ADD_CHAR_EVT"; + case ESP_GATTS_ADD_CHAR_DESCR_EVT: return "ESP_GATTS_ADD_CHAR_DESCR_EVT"; + case ESP_GATTS_DELETE_EVT: return "ESP_GATTS_DELETE_EVT"; + case ESP_GATTS_START_EVT: return "ESP_GATTS_START_EVT"; + case ESP_GATTS_STOP_EVT: return "ESP_GATTS_STOP_EVT"; + case ESP_GATTS_CONNECT_EVT: return "ESP_GATTS_CONNECT_EVT"; + case ESP_GATTS_DISCONNECT_EVT: return "ESP_GATTS_DISCONNECT_EVT"; + case ESP_GATTS_OPEN_EVT: return "ESP_GATTS_OPEN_EVT"; + case ESP_GATTS_CANCEL_OPEN_EVT: return "ESP_GATTS_CANCEL_OPEN_EVT"; + case ESP_GATTS_CLOSE_EVT: return "ESP_GATTS_CLOSE_EVT"; + case ESP_GATTS_LISTEN_EVT: return "ESP_GATTS_LISTEN_EVT"; + case ESP_GATTS_CONGEST_EVT: return "ESP_GATTS_CONGEST_EVT"; + case ESP_GATTS_RESPONSE_EVT: return "ESP_GATTS_RESPONSE_EVT"; + case ESP_GATTS_CREAT_ATTR_TAB_EVT: return "ESP_GATTS_CREAT_ATTR_TAB_EVT"; + case ESP_GATTS_SET_ATTR_VAL_EVT: return "ESP_GATTS_SET_ATTR_VAL_EVT"; + } return "Unknown"; } // gattServerEventTypeToString @@ -1141,11 +1220,13 @@ void BLEUtils::dumpGapEvent( // - ble_adv // - flag // - num_resps + // - adv_data_len + // - scan_rsp_len // 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, num_resps: %d, adv_data_len: %d, scan_rsp_len: %d", + 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", searchEventTypeToString(param->scan_rst.search_evt), BLEAddress(param->scan_rst.bda).toString().c_str(), devTypeToString(param->scan_rst.dev_type), @@ -1153,6 +1234,7 @@ void BLEUtils::dumpGapEvent( eventTypeToString(param->scan_rst.ble_evt_type), param->scan_rst.rssi, param->scan_rst.flag, + adFlagsToString(param->scan_rst.flag).c_str(), param->scan_rst.num_resps, param->scan_rst.adv_data_len, param->scan_rst.scan_rsp_len @@ -1286,8 +1368,7 @@ void BLEUtils::dumpGattClientEvent( // - uint16_t conn_id // - esp_bd_addr_t remote_bda case ESP_GATTC_CONNECT_EVT: { - ESP_LOGD(LOG_TAG, "[staus: %s, conn_id: %d, remote_bda: %s]", - BLEUtils::gattStatusToString(evtParam->connect.status).c_str(), + ESP_LOGD(LOG_TAG, "[conn_id: %d, remote_bda: %s]", evtParam->connect.conn_id, BLEAddress(evtParam->connect.remote_bda).toString().c_str() ); @@ -1302,8 +1383,7 @@ void BLEUtils::dumpGattClientEvent( // - uint16_t conn_id // - esp_bd_addr_t remote_bda case ESP_GATTC_DISCONNECT_EVT: { - ESP_LOGD(LOG_TAG, "[staus: %s, conn_id: %d, remote_bda: %s]", - BLEUtils::gattStatusToString(evtParam->disconnect.status).c_str(), + ESP_LOGD(LOG_TAG, "[conn_id: %d, remote_bda: %s]", evtParam->disconnect.conn_id, BLEAddress(evtParam->disconnect.remote_bda).toString().c_str() ); @@ -1586,10 +1666,9 @@ void BLEUtils::dumpGattServerEvent( } // ESP_GATTS_CONGEST_EVT case ESP_GATTS_CONNECT_EVT: { - ESP_LOGD(LOG_TAG, "[conn_id: %d, remote_bda: %s, is_connected: %d]", + ESP_LOGD(LOG_TAG, "[conn_id: %d, remote_bda: %s]", evtParam->connect.conn_id, - BLEAddress(evtParam->connect.remote_bda).toString().c_str(), - evtParam->connect.is_connected); + BLEAddress(evtParam->connect.remote_bda).toString().c_str()); break; } // ESP_GATTS_CONNECT_EVT @@ -1603,10 +1682,9 @@ void BLEUtils::dumpGattServerEvent( } // ESP_GATTS_CREATE_EVT case ESP_GATTS_DISCONNECT_EVT: { - ESP_LOGD(LOG_TAG, "[conn_id: %d, remote_bda: %s, is_connected: %d]", + ESP_LOGD(LOG_TAG, "[conn_id: %d, remote_bda: %s]", evtParam->connect.conn_id, - BLEAddress(evtParam->connect.remote_bda).toString().c_str(), - evtParam->connect.is_connected); + BLEAddress(evtParam->connect.remote_bda).toString().c_str()); break; } // ESP_GATTS_DISCONNECT_EVT @@ -1763,59 +1841,86 @@ const char* BLEUtils::gapEventToString(uint32_t eventType) { switch(eventType) { case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT: return "ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT"; + case ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT: return "ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT"; + case ESP_GAP_BLE_ADV_START_COMPLETE_EVT: return "ESP_GAP_BLE_ADV_START_COMPLETE_EVT"; + case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT: /*!< When stop adv complete, the event comes */ return "ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT"; + case ESP_GAP_BLE_AUTH_CMPL_EVT: /* Authentication complete indication. */ return "ESP_GAP_BLE_AUTH_CMPL_EVT"; + case ESP_GAP_BLE_CLEAR_BOND_DEV_COMPLETE_EVT: return "ESP_GAP_BLE_CLEAR_BOND_DEV_COMPLETE_EVT"; + case ESP_GAP_BLE_GET_BOND_DEV_COMPLETE_EVT: return "ESP_GAP_BLE_GET_BOND_DEV_COMPLETE_EVT"; + case ESP_GAP_BLE_KEY_EVT: /* BLE key event for peer device keys */ return "ESP_GAP_BLE_KEY_EVT"; + case ESP_GAP_BLE_LOCAL_IR_EVT: /* BLE local IR event */ return "ESP_GAP_BLE_LOCAL_IR_EVT"; + case ESP_GAP_BLE_LOCAL_ER_EVT: /* BLE local ER event */ return "ESP_GAP_BLE_LOCAL_ER_EVT"; + case ESP_GAP_BLE_NC_REQ_EVT: /* Numeric Comparison request event */ return "ESP_GAP_BLE_NC_REQ_EVT"; + case ESP_GAP_BLE_OOB_REQ_EVT: /* OOB request event */ return "ESP_GAP_BLE_OOB_REQ_EVT"; + case ESP_GAP_BLE_PASSKEY_NOTIF_EVT: /* passkey notification event */ return "ESP_GAP_BLE_PASSKEY_NOTIF_EVT"; + case ESP_GAP_BLE_PASSKEY_REQ_EVT: /* passkey request event */ return "ESP_GAP_BLE_PASSKEY_REQ_EVT"; + case ESP_GAP_BLE_READ_RSSI_COMPLETE_EVT: return "ESP_GAP_BLE_READ_RSSI_COMPLETE_EVT"; + case ESP_GAP_BLE_REMOVE_BOND_DEV_COMPLETE_EVT: return "ESP_GAP_BLE_REMOVE_BOND_DEV_COMPLETE_EVT"; + case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT: return "ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT"; + case ESP_GAP_BLE_SCAN_RESULT_EVT: return "ESP_GAP_BLE_SCAN_RESULT_EVT"; + case ESP_GAP_BLE_SCAN_RSP_DATA_RAW_SET_COMPLETE_EVT: return "ESP_GAP_BLE_SCAN_RSP_DATA_RAW_SET_COMPLETE_EVT"; + case ESP_GAP_BLE_SCAN_RSP_DATA_SET_COMPLETE_EVT: return "ESP_GAP_BLE_SCAN_RSP_DATA_SET_COMPLETE_EVT"; + case ESP_GAP_BLE_SCAN_START_COMPLETE_EVT: return "ESP_GAP_BLE_SCAN_START_COMPLETE_EVT"; + case ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT: return "ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT"; + case ESP_GAP_BLE_SEC_REQ_EVT: /* BLE security request */ return "ESP_GAP_BLE_SEC_REQ_EVT"; + case ESP_GAP_BLE_SET_LOCAL_PRIVACY_COMPLETE_EVT: return "ESP_GAP_BLE_SET_LOCAL_PRIVACY_COMPLETE_EVT"; + case ESP_GAP_BLE_SET_PKT_LENGTH_COMPLETE_EVT: return "ESP_GAP_BLE_SET_PKT_LENGTH_COMPLETE_EVT"; + case ESP_GAP_BLE_SET_STATIC_RAND_ADDR_EVT: return "ESP_GAP_BLE_SET_STATIC_RAND_ADDR_EVT"; + 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); return "Unknown event type"; @@ -1825,9 +1930,9 @@ const char* BLEUtils::gapEventToString(uint32_t eventType) { std::string BLEUtils::gattCharacteristicUUIDToString(uint32_t characteristicUUID) { const characteristicMap_t *p = g_characteristicsMappings; - while (p->name.length() > 0) { + while (strlen(p->name) > 0) { if (p->assignedNumber == characteristicUUID) { - return p->name; + return std::string(p->name); } p++; } @@ -1842,9 +1947,9 @@ std::string BLEUtils::gattCharacteristicUUIDToString(uint32_t characteristicUUID */ std::string BLEUtils::gattDescriptorUUIDToString(uint32_t descriptorUUID) { gattdescriptor_t* p = (gattdescriptor_t *)g_descriptor_ids; - while (p->name.length() > 0) { + while (strlen(p->name) > 0) { if (p->assignedNumber == descriptorUUID) { - return p->name; + return std::string(p->name); } p++; } @@ -1878,9 +1983,9 @@ std::string BLEUtils::gattServiceIdToString(esp_gatt_srvc_id_t srvcId) { std::string BLEUtils::gattServiceToString(uint32_t serviceId) { gattService_t* p = (gattService_t *)g_gattServices; - while (p->name.length() > 0) { + while (strlen(p->name) > 0) { if (p->assignedNumber == serviceId) { - return p->name; + return std::string(p->name); } p++; } @@ -1992,9 +2097,9 @@ std::string BLEUtils::gattStatusToString(esp_gatt_status_t status) { std::string BLEUtils::getMember(uint32_t memberId) { member_t* p = (member_t *)members_ids; - while (p->name.length() > 0) { + while (strlen(p->name) > 0) { if (p->assignedNumber == memberId) { - return p->name; + return std::string(p->name); } p++; } diff --git a/src/BLEUtils.h b/src/BLEUtils.h index 5ef6c37..b2baee5 100644 --- a/src/BLEUtils.h +++ b/src/BLEUtils.h @@ -21,6 +21,7 @@ class BLEUtils { public: static const char* addressTypeToString(esp_ble_addr_type_t type); + static std::string adFlagsToString(uint8_t adFlags); static const char* advTypeToString(uint8_t advType); static esp_gatt_id_t buildGattId(esp_bt_uuid_t uuid, uint8_t inst_id=0); static esp_gatt_srvc_id_t buildGattSrvcId(esp_gatt_id_t gattId, bool is_primary=true); diff --git a/src/FreeRTOS.cpp b/src/FreeRTOS.cpp index 3cabd91..9239042 100644 --- a/src/FreeRTOS.cpp +++ b/src/FreeRTOS.cpp @@ -76,24 +76,49 @@ uint32_t FreeRTOS::getTimeSinceStart() { * @return The value associated with the semaphore. */ uint32_t FreeRTOS::Semaphore::wait(std::string owner) { - ESP_LOGV(LOG_TAG, "Semaphore waiting: %s for %s", toString().c_str(), owner.c_str()); - xSemaphoreTake(m_semaphore, portMAX_DELAY); + ESP_LOGV(LOG_TAG, ">> wait: Semaphore waiting: %s for %s", toString().c_str(), owner.c_str()); + + + if (m_usePthreads) { + pthread_mutex_lock(&m_pthread_mutex); + } else { + xSemaphoreTake(m_semaphore, portMAX_DELAY); + } + m_owner = owner; - xSemaphoreGive(m_semaphore); - ESP_LOGV(LOG_TAG, "Semaphore released: %s", toString().c_str()); - m_owner = "<N/A>"; + + if (m_usePthreads) { + pthread_mutex_unlock(&m_pthread_mutex); + } else { + xSemaphoreGive(m_semaphore); + } + + ESP_LOGV(LOG_TAG, "<< wait: Semaphore released: %s", toString().c_str()); + m_owner = std::string("<N/A>"); return m_value; } // wait + FreeRTOS::Semaphore::Semaphore(std::string name) { - m_semaphore = xSemaphoreCreateMutex(); + m_usePthreads = false; // Are we using pThreads or FreeRTOS? + if (m_usePthreads) { + pthread_mutex_init(&m_pthread_mutex, nullptr); + } else { + m_semaphore = xSemaphoreCreateMutex(); + } + m_name = name; - m_owner = "<N/A>"; + m_owner = std::string("<N/A>"); m_value = 0; } + FreeRTOS::Semaphore::~Semaphore() { - vSemaphoreDelete(m_semaphore); + if (m_usePthreads) { + pthread_mutex_destroy(&m_pthread_mutex); + } else { + vSemaphoreDelete(m_semaphore); + } } @@ -102,12 +127,17 @@ FreeRTOS::Semaphore::~Semaphore() { * The Semaphore is given. */ void FreeRTOS::Semaphore::give() { - xSemaphoreGive(m_semaphore); + ESP_LOGV(LOG_TAG, "Semaphore giving: %s", toString().c_str()); + if (m_usePthreads) { + pthread_mutex_unlock(&m_pthread_mutex); + } else { + xSemaphoreGive(m_semaphore); + } #ifdef ARDUINO_ARCH_ESP32 FreeRTOS::sleep(10); #endif - ESP_LOGV(LOG_TAG, "Semaphore giving: %s", toString().c_str()); - m_owner = "<N/A>"; + + m_owner = std::string("<N/A>"); } // Semaphore::give @@ -119,7 +149,7 @@ void FreeRTOS::Semaphore::give() { void FreeRTOS::Semaphore::give(uint32_t value) { m_value = value; give(); -} +} // give /** @@ -127,7 +157,11 @@ void FreeRTOS::Semaphore::give(uint32_t value) { */ void FreeRTOS::Semaphore::giveFromISR() { BaseType_t higherPriorityTaskWoken; - xSemaphoreGiveFromISR(m_semaphore, &higherPriorityTaskWoken); + if (m_usePthreads) { + assert(false); + } else { + xSemaphoreGiveFromISR(m_semaphore, &higherPriorityTaskWoken); + } } // giveFromISR @@ -138,7 +172,11 @@ void FreeRTOS::Semaphore::giveFromISR() { void FreeRTOS::Semaphore::take(std::string owner) { ESP_LOGD(LOG_TAG, "Semaphore taking: %s for %s", toString().c_str(), owner.c_str()); - xSemaphoreTake(m_semaphore, portMAX_DELAY); + if (m_usePthreads) { + pthread_mutex_lock(&m_pthread_mutex); + } else { + xSemaphoreTake(m_semaphore, portMAX_DELAY); + } m_owner = owner; ESP_LOGD(LOG_TAG, "Semaphore taken: %s", toString().c_str()); } // Semaphore::take @@ -150,19 +188,75 @@ void FreeRTOS::Semaphore::take(std::string owner) * @param [in] timeoutMs Timeout in milliseconds. */ void FreeRTOS::Semaphore::take(uint32_t timeoutMs, std::string owner) { + ESP_LOGV(LOG_TAG, "Semaphore taking: %s for %s", toString().c_str(), owner.c_str()); + + if (m_usePthreads) { + assert(false); + } else { + xSemaphoreTake(m_semaphore, timeoutMs/portTICK_PERIOD_MS); + } m_owner = owner; - xSemaphoreTake(m_semaphore, timeoutMs/portTICK_PERIOD_MS); ESP_LOGV(LOG_TAG, "Semaphore taken: %s", toString().c_str()); } // Semaphore::take + std::string FreeRTOS::Semaphore::toString() { std::stringstream stringStream; stringStream << "name: "<< m_name << " (0x" << std::hex << std::setfill('0') << (uint32_t)m_semaphore << "), owner: " << m_owner; return stringStream.str(); -} +} // toString + void FreeRTOS::Semaphore::setName(std::string name) { m_name = name; -} +} // setName + + +/** + * @brief Create a ring buffer. + * @param [in] length The amount of storage to allocate for the ring buffer. + * @param [in] type The type of buffer. One of RINGBUF_TYPE_NOSPLIT, RINGBUF_TYPE_ALLOWSPLIT, RINGBUF_TYPE_BYTEBUF. + */ +Ringbuffer::Ringbuffer(size_t length, ringbuf_type_t type) { + m_handle = ::xRingbufferCreate(length, type); +} // Ringbuffer + + +Ringbuffer::~Ringbuffer() { + ::vRingbufferDelete(m_handle); +} // ~Ringbuffer + + +/** + * @brief Receive data from the buffer. + * @param [out] size On return, the size of data returned. + * @param [in] wait How long to wait. + * @return A pointer to the storage retrieved. + */ +void* Ringbuffer::receive(size_t* size, TickType_t wait) { + return ::xRingbufferReceive(m_handle, size, wait); +} // receive + + +/** + * @brief Return an item. + * @param [in] item The item to be returned/released. + */ +void Ringbuffer::returnItem(void* item) { + ::vRingbufferReturnItem(m_handle, item); +} // returnItem + + +/** + * @brief Send data to the buffer. + * @param [in] data The data to place into the buffer. + * @param [in] length The length of data to place into the buffer. + * @param [in] wait How long to wait before giving up. The default is to wait indefinitely. + * @return + */ +uint32_t Ringbuffer::send(void* data, size_t length, TickType_t wait) { + return ::xRingbufferSend(m_handle, data, length, wait); +} // send + diff --git a/src/FreeRTOS.h b/src/FreeRTOS.h index edaa9df..43a3b8f 100644 --- a/src/FreeRTOS.h +++ b/src/FreeRTOS.h @@ -9,10 +9,12 @@ #define MAIN_FREERTOS_H_ #include <stdint.h> #include <string> +#include <pthread.h> -#include <freertos/FreeRTOS.h> // Include the base FreeRTOS definitions -#include <freertos/task.h> // Include the task definitions -#include <freertos/semphr.h> // Include the semaphore definitions +#include <freertos/FreeRTOS.h> // Include the base FreeRTOS definitions. +#include <freertos/task.h> // Include the task definitions. +#include <freertos/semphr.h> // Include the semaphore definitions. +#include <freertos/ringbuf.h> // Include the ringbuffer definitions. /** @@ -30,20 +32,39 @@ public: public: Semaphore(std::string owner = "<Unknown>"); ~Semaphore(); - void give(); - void giveFromISR(); - void give(uint32_t value); - void setName(std::string name); - void take(std::string owner="<Unknown>"); - void take(uint32_t timeoutMs, std::string owner="<Unknown>"); - uint32_t wait(std::string owner="<Unknown>"); + void give(); + void give(uint32_t value); + void giveFromISR(); + void setName(std::string name); + void take(std::string owner="<Unknown>"); + void take(uint32_t timeoutMs, std::string owner="<Unknown>"); std::string toString(); + uint32_t wait(std::string owner="<Unknown>"); + private: SemaphoreHandle_t m_semaphore; + pthread_mutex_t m_pthread_mutex; std::string m_name; std::string m_owner; uint32_t m_value; + bool m_usePthreads; }; }; + +/** + * @brief Ringbuffer. + */ +class Ringbuffer { +public: + Ringbuffer(size_t length, ringbuf_type_t type = RINGBUF_TYPE_NOSPLIT); + ~Ringbuffer(); + + void* receive(size_t* size, TickType_t wait = portMAX_DELAY); + void returnItem(void* item); + uint32_t send(void* data, size_t length, TickType_t wait = portMAX_DELAY); +private: + RingbufHandle_t m_handle; +}; + #endif /* MAIN_FREERTOS_H_ */ diff --git a/src/GeneralUtils.cpp b/src/GeneralUtils.cpp index 6bfde84..e8eb3a0 100644 --- a/src/GeneralUtils.cpp +++ b/src/GeneralUtils.cpp @@ -24,15 +24,6 @@ static const char kBase64Alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789+/"; -GeneralUtils::GeneralUtils() { - // TODO Auto-generated constructor stub - -} - -GeneralUtils::~GeneralUtils() { - // TODO Auto-generated destructor stub -} - static int base64EncodedLength(size_t length) { return (length + 2 - ((length + 2) % 3)) / 3 * 4; } // base64EncodedLength @@ -272,6 +263,7 @@ void GeneralUtils::hexDump(uint8_t* pData, uint32_t length) { } */ + /** * @brief Dump a representation of binary data to the console. * @@ -315,6 +307,7 @@ void GeneralUtils::hexDump(const uint8_t* pData, uint32_t length) { } } // hexDump + /** * @brief Convert an IP address to string. * @param ip The 4 byte IP address. @@ -404,6 +397,7 @@ const char* GeneralUtils::errorToString(esp_err_t errCode) { return "Unknown ESP_ERR error"; } // errorToString + /** * @brief Restart the ESP32. */ diff --git a/src/GeneralUtils.h b/src/GeneralUtils.h index ce75e43..2d55abf 100644 --- a/src/GeneralUtils.h +++ b/src/GeneralUtils.h @@ -16,15 +16,13 @@ */ class GeneralUtils { public: - GeneralUtils(); - virtual ~GeneralUtils(); - static bool base64Encode(const std::string &in, std::string *out); - static bool base64Decode(const std::string &in, std::string *out); - static bool endsWith(std::string str, char c); - static const char *errorToString(esp_err_t errCode); - static void hexDump(const uint8_t *pData, uint32_t length); - static std::string ipToString(uint8_t *ip); - static void restart(); + static bool base64Decode(const std::string& in, std::string* out); + static bool base64Encode(const std::string& in, std::string* out); + static bool endsWith(std::string str, char c); + static const char* errorToString(esp_err_t errCode); + static void hexDump(const uint8_t* pData, uint32_t length); + static std::string ipToString(uint8_t* ip); + static void restart(); }; #endif /* COMPONENTS_CPP_UTILS_GENERALUTILS_H_ */ |