summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeil Kolban <kolban1@kolban.com>2017-11-21 09:51:03 -0600
committerNeil Kolban <kolban1@kolban.com>2017-11-21 09:51:03 -0600
commit4a781e01832176d61af010669b8c362f5a777768 (patch)
tree6a7a16309d61c4728512f5eb632d3ad565288c36
parentFixes for #121 (diff)
downloadthermostat-4a781e01832176d61af010669b8c362f5a777768.tar.gz
thermostat-4a781e01832176d61af010669b8c362f5a777768.tar.bz2
thermostat-4a781e01832176d61af010669b8c362f5a777768.zip
Updates 2017-11-21 0950
-rw-r--r--src/BLEAdvertisedDevice.cpp47
-rw-r--r--src/BLEAdvertisedDevice.h3
-rw-r--r--src/BLECharacteristic.cpp31
-rw-r--r--src/BLECharacteristic.h2
-rw-r--r--src/BLECharacteristicMap.cpp18
-rw-r--r--src/BLEClient.cpp106
-rw-r--r--src/BLEClient.h9
-rw-r--r--src/BLEDescriptor.cpp92
-rw-r--r--src/BLEDescriptor.h19
-rw-r--r--src/BLEDevice.cpp154
-rw-r--r--src/BLEDevice.h4
-rw-r--r--src/BLERemoteCharacteristic.cpp1
-rw-r--r--src/BLERemoteService.cpp14
-rw-r--r--src/BLERemoteService.h8
-rw-r--r--src/BLEScan.cpp28
-rw-r--r--src/BLEScan.h6
-rw-r--r--src/BLEServer.cpp2
-rw-r--r--src/BLEService.cpp10
-rw-r--r--src/BLEService.h10
-rw-r--r--src/BLEUUID.cpp22
-rw-r--r--src/BLEUUID.h1
-rw-r--r--src/BLEUtils.cpp209
-rw-r--r--src/BLEUtils.h1
-rw-r--r--src/FreeRTOS.cpp128
-rw-r--r--src/FreeRTOS.h41
-rw-r--r--src/GeneralUtils.cpp12
-rw-r--r--src/GeneralUtils.h16
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_ */