summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkolban <kolban1@kolban.com>2017-10-13 10:52:17 -0500
committerkolban <kolban1@kolban.com>2017-10-13 10:52:17 -0500
commit34902f4e7fc6926a005a5ccfd4e530d6a6321613 (patch)
tree512593068ed656012ee31fced9526bff80ecad55
parentMerge pull request #5 from sebastiankliem/master (diff)
downloadthermostat-34902f4e7fc6926a005a5ccfd4e530d6a6321613.tar.gz
thermostat-34902f4e7fc6926a005a5ccfd4e530d6a6321613.tar.bz2
thermostat-34902f4e7fc6926a005a5ccfd4e530d6a6321613.zip
Sync update for 0.4.3 take 2
-rw-r--r--examples/BLE_client/BLE_client.ino16
-rw-r--r--examples/BLE_notify/BLE_notify.ino2
-rw-r--r--examples/BLE_scan/BLE_scan.ino2
-rw-r--r--examples/BLE_server/BLE_server.ino2
-rw-r--r--examples/BLE_uart/BLE_uart.ino2
-rw-r--r--examples/BLE_write/BLE_write.ino2
-rw-r--r--library.properties4
-rw-r--r--src/BLEAdvertisedDevice.cpp12
-rw-r--r--src/BLEAdvertisedDevice.h2
-rw-r--r--src/BLEAdvertising.cpp109
-rw-r--r--src/BLEAdvertising.h7
-rw-r--r--src/BLECharacteristic.cpp16
-rw-r--r--src/BLECharacteristic.h14
-rw-r--r--src/BLECharacteristicMap.cpp122
-rw-r--r--src/BLEClient.cpp84
-rw-r--r--src/BLEClient.h4
-rw-r--r--src/BLEDevice.cpp108
-rw-r--r--src/BLEDevice.h30
-rw-r--r--src/BLERemoteCharacteristic.cpp389
-rw-r--r--src/BLERemoteCharacteristic.h32
-rw-r--r--src/BLERemoteDescriptor.cpp148
-rw-r--r--src/BLERemoteDescriptor.h35
-rw-r--r--src/BLERemoteService.cpp159
-rw-r--r--src/BLERemoteService.h21
-rw-r--r--src/BLEScan.cpp42
-rw-r--r--src/BLEScan.h17
-rw-r--r--src/BLEServer.cpp24
-rw-r--r--src/BLEServer.h6
-rw-r--r--src/BLEService.cpp50
-rw-r--r--src/BLEService.h10
-rw-r--r--src/BLEUUID.cpp102
-rw-r--r--src/BLEUUID.h6
-rw-r--r--src/BLEUtils.cpp907
-rw-r--r--src/BLEUtils.h56
-rw-r--r--src/BLEValue.cpp23
-rw-r--r--src/BLEValue.h2
-rw-r--r--src/FreeRTOS.cpp5
-rw-r--r--src/GeneralUtils.cpp26
-rw-r--r--src/GeneralUtils.h6
39 files changed, 1986 insertions, 618 deletions
diff --git a/examples/BLE_client/BLE_client.ino b/examples/BLE_client/BLE_client.ino
index 3fc5efa..c0b6163 100644
--- a/examples/BLE_client/BLE_client.ino
+++ b/examples/BLE_client/BLE_client.ino
@@ -26,7 +26,7 @@ static void notifyCallback(
Serial.println(length);
}
-void connectToServer(BLEAddress pAddress) {
+bool connectToServer(BLEAddress pAddress) {
Serial.print("Forming a connection to ");
Serial.println(pAddress.toString().c_str());
@@ -42,8 +42,9 @@ void connectToServer(BLEAddress pAddress) {
if (pRemoteService == nullptr) {
Serial.print("Failed to find our service UUID: ");
Serial.println(serviceUUID.toString().c_str());
- return;
+ return false;
}
+ Serial.println(" - Found our service");
// Obtain a reference to the characteristic in the service of the remote BLE server.
@@ -51,8 +52,9 @@ void connectToServer(BLEAddress pAddress) {
if (pRemoteCharacteristic == nullptr) {
Serial.print("Failed to find our characteristic UUID: ");
Serial.println(charUUID.toString().c_str());
- return;
+ return false;
}
+ Serial.println(" - Found our characteristic");
// Read the value of the characteristic.
std::string value = pRemoteCharacteristic->readValue();
@@ -109,9 +111,13 @@ void loop() {
// BLE Server with which we wish to connect. Now we connect to it. Once we are
// connected we set the connected flag to be true.
if (doConnect == true) {
- connectToServer(*pServerAddress);
+ if (connectToServer(*pServerAddress)) {
+ Serial.println("We are now connected to the BLE Server.");
+ connected = true;
+ } else {
+ Serial.println("We have failed to connect to the server; there is nothin more we will do.");
+ }
doConnect = false;
- connected = true;
}
// If we are connected to a peer BLE Server, update the characteristic each time we are reached
diff --git a/examples/BLE_notify/BLE_notify.ino b/examples/BLE_notify/BLE_notify.ino
index f2539f7..44506c2 100644
--- a/examples/BLE_notify/BLE_notify.ino
+++ b/examples/BLE_notify/BLE_notify.ino
@@ -1,6 +1,6 @@
/*
Video: https://www.youtube.com/watch?v=oCMOYS71NIU
- Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLETests/SampleNotify.cpp
+ Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleNotify.cpp
Ported to Arduino ESP32 by Evandro Copercini
Create a BLE server that, once we receive a connection, will send periodic notifications.
diff --git a/examples/BLE_scan/BLE_scan.ino b/examples/BLE_scan/BLE_scan.ino
index a884062..ef7d892 100644
--- a/examples/BLE_scan/BLE_scan.ino
+++ b/examples/BLE_scan/BLE_scan.ino
@@ -1,5 +1,5 @@
/*
- Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLETests/SampleScan.cpp
+ Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleScan.cpp
Ported to Arduino ESP32 by Evandro Copercini
*/
diff --git a/examples/BLE_server/BLE_server.ino b/examples/BLE_server/BLE_server.ino
index c70c935..45ebf99 100644
--- a/examples/BLE_server/BLE_server.ino
+++ b/examples/BLE_server/BLE_server.ino
@@ -1,5 +1,5 @@
/*
- Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLETests/SampleServer.cpp
+ Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleServer.cpp
Ported to Arduino ESP32 by Evandro Copercini
*/
diff --git a/examples/BLE_uart/BLE_uart.ino b/examples/BLE_uart/BLE_uart.ino
index 444ba6b..a8ab2d7 100644
--- a/examples/BLE_uart/BLE_uart.ino
+++ b/examples/BLE_uart/BLE_uart.ino
@@ -1,6 +1,6 @@
/*
Video: https://www.youtube.com/watch?v=oCMOYS71NIU
- Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLETests/SampleNotify.cpp
+ Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleNotify.cpp
Ported to Arduino ESP32 by Evandro Copercini
Create a BLE server that, once we receive a connection, will send periodic notifications.
diff --git a/examples/BLE_write/BLE_write.ino b/examples/BLE_write/BLE_write.ino
index 0573669..ed5ebc6 100644
--- a/examples/BLE_write/BLE_write.ino
+++ b/examples/BLE_write/BLE_write.ino
@@ -1,5 +1,5 @@
/*
- Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLETests/SampleWrite.cpp
+ Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleWrite.cpp
Ported to Arduino ESP32 by Evandro Copercini
*/
diff --git a/library.properties b/library.properties
index afb6d27..fdb01e2 100644
--- a/library.properties
+++ b/library.properties
@@ -1,5 +1,5 @@
name=ESP32 BLE Arduino
-version=0.4.2
+version=0.4.3
author=Neil Kolban <kolban1@kolban.com>
maintainer=Neil Kolban <kolban1@kolban.com>
sentence=BLE functions for ESP32
@@ -7,4 +7,4 @@ paragraph=This library provides an implementation Bluetooth Low Energy support f
category=Communication
url=https://github.com/nkolban/ESP32_BLE_Arduino
architectures=esp32
-includes=BLEDevice.h, BLEUtils.h, BLEScan.h, BLEAdvertisedDevice.h \ No newline at end of file
+includes=BLE.h, BLEUtils.h, BLEScan.h, BLEAdvertisedDevice.h \ No newline at end of file
diff --git a/src/BLEAdvertisedDevice.cpp b/src/BLEAdvertisedDevice.cpp
index 97ec1e3..5074b81 100644
--- a/src/BLEAdvertisedDevice.cpp
+++ b/src/BLEAdvertisedDevice.cpp
@@ -60,7 +60,7 @@ BLEAddress BLEAdvertisedDevice::getAddress() {
*
* @return The appearance of the advertised device.
*/
-uint16_t BLEAdvertisedDevice::getApperance() {
+uint16_t BLEAdvertisedDevice::getAppearance() {
return m_appearance;
}
@@ -265,7 +265,7 @@ void BLEAdvertisedDevice::parseAdvertisement(uint8_t* payload) {
} // ESP_BLE_AD_MANUFACTURER_SPECIFIC_TYPE
default: {
- ESP_LOGD(LOG_TAG, "Unhandled type");
+ ESP_LOGD(LOG_TAG, "Unhandled type: adType: %d - 0x%.2x", ad_type, ad_type);
break;
}
} // switch
@@ -329,7 +329,7 @@ void BLEAdvertisedDevice::setManufacturerData(std::string manufacturerData) {
void BLEAdvertisedDevice::setName(std::string name) {
m_name = name;
m_haveName = true;
- ESP_LOGD(LOG_TAG, "- name: %s", m_name.c_str());
+ ESP_LOGD(LOG_TAG, "- setName(): name: %s", m_name.c_str());
} // setName
@@ -340,7 +340,7 @@ void BLEAdvertisedDevice::setName(std::string name) {
void BLEAdvertisedDevice::setRSSI(int rssi) {
m_rssi = rssi;
m_haveRSSI = true;
- ESP_LOGD(LOG_TAG, "- rssi: %d", m_rssi);
+ ESP_LOGD(LOG_TAG, "- setRSSI(): rssi: %d", m_rssi);
} // setRSSI
@@ -367,7 +367,7 @@ void BLEAdvertisedDevice::setServiceUUID(const char* serviceUUID) {
void BLEAdvertisedDevice::setServiceUUID(BLEUUID serviceUUID) {
m_serviceUUID = serviceUUID;
m_haveServiceUUID = true;
- ESP_LOGD(LOG_TAG, "- serviceUUID: %s", serviceUUID.toString().c_str());
+ ESP_LOGD(LOG_TAG, "- setServiceUUID(): serviceUUID: %s", serviceUUID.toString().c_str());
} // setRSSI
@@ -390,7 +390,7 @@ std::string BLEAdvertisedDevice::toString() {
std::stringstream ss;
ss << "Name: " << getName() << ", Address: " << getAddress().toString();
if (haveAppearance()) {
- ss << ", appearance: " << getApperance();
+ ss << ", appearance: " << getAppearance();
}
if (haveManufacturerData()) {
char *pHex = BLEUtils::buildHexData(nullptr, (uint8_t*)getManufacturerData().data(), getManufacturerData().length());
diff --git a/src/BLEAdvertisedDevice.h b/src/BLEAdvertisedDevice.h
index 2fb2652..fbdeeec 100644
--- a/src/BLEAdvertisedDevice.h
+++ b/src/BLEAdvertisedDevice.h
@@ -30,7 +30,7 @@ public:
BLEAdvertisedDevice();
BLEAddress getAddress();
- uint16_t getApperance();
+ uint16_t getAppearance();
std::string getManufacturerData();
std::string getName();
int getRSSI();
diff --git a/src/BLEAdvertising.cpp b/src/BLEAdvertising.cpp
index ad076dd..2647966 100644
--- a/src/BLEAdvertising.cpp
+++ b/src/BLEAdvertising.cpp
@@ -45,6 +45,24 @@ BLEAdvertising::BLEAdvertising() {
/**
+ * @brief Add a service uuid to exposed list of services.
+ * @param [in] serviceUUID The UUID of the service to expose.
+ */
+void BLEAdvertising::addServiceUUID(BLEUUID serviceUUID) {
+ m_serviceUUIDs.push_back(serviceUUID);
+} // addServiceUUID
+
+
+/**
+ * @brief Add a service uuid to exposed list of services.
+ * @param [in] serviceUUID The string representation of the service to expose.
+ */
+void BLEAdvertising::addServiceUUID(const char* serviceUUID) {
+ addServiceUUID(BLEUUID(serviceUUID));
+} // addServiceUUID
+
+
+/**
* @brief Set the device appearance in the advertising data.
* The appearance attribute is of type 0x19. The codes for distinct appearances can be found here:
* https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.gap.appearance.xml.
@@ -57,52 +75,6 @@ void BLEAdvertising::setAppearance(uint16_t appearance) {
/**
- * @brief Set the service UUID.
- * We maintain a class member called m_advData (esp_ble_adv_data_t) that is passed to the
- * ESP-IDF advertising functions. In this method, we see two fields within that structure
- * namely service_uuid_len and p_service_uuid to be the information supplied in the passed
- * in service uuid.
- * @param [in] uuid The UUID of the service.
- * @return N/A.
- */
-void BLEAdvertising::setServiceUUID(const char* serviceUUID) {
- return setServiceUUID(BLEUUID(serviceUUID));
-}
-/**
- * @brief Set the service UUID.
- * We maintain a class member called m_advData (esp_ble_adv_data_t) that is passed to the
- * ESP-IDF advertising functions. In this method, we see two fields within that structure
- * namely service_uuid_len and p_service_uuid to be the information supplied in the passed
- * in service uuid.
- * @param [in] uuid The UUID of the service.
- * @return N/A.
- */
-void BLEAdvertising::setServiceUUID(BLEUUID serviceUUID) {
- ESP_LOGD(LOG_TAG, ">> setServiceUUID - %s", serviceUUID.toString().c_str());
- m_serviceUUID = serviceUUID; // Save the new service UUID
- esp_bt_uuid_t* espUUID = m_serviceUUID.getNative();
- switch(espUUID->len) {
- case ESP_UUID_LEN_16: {
- m_advData.service_uuid_len = 2;
- m_advData.p_service_uuid = reinterpret_cast<uint8_t*>(&espUUID->uuid.uuid16);
- break;
- }
- case ESP_UUID_LEN_32: {
- m_advData.service_uuid_len = 4;
- m_advData.p_service_uuid = reinterpret_cast<uint8_t*>(&espUUID->uuid.uuid32);
- break;
- }
- case ESP_UUID_LEN_128: {
- m_advData.service_uuid_len = 16;
- m_advData.p_service_uuid = reinterpret_cast<uint8_t*>(&espUUID->uuid.uuid128);
- break;
- }
- } // switch
- ESP_LOGD(LOG_TAG, "<< setServiceUUID");
-} // setServiceUUID
-
-
-/**
* @brief Start advertising.
* Start advertising.
* @return N/A.
@@ -110,24 +82,49 @@ void BLEAdvertising::setServiceUUID(BLEUUID serviceUUID) {
void BLEAdvertising::start() {
ESP_LOGD(LOG_TAG, ">> start");
- if (m_advData.service_uuid_len > 0) {
- uint8_t hexData[16*2+1];
- BLEUtils::buildHexData(hexData, m_advData.p_service_uuid, m_advData.service_uuid_len);
- ESP_LOGD(LOG_TAG, " - Service: service_uuid_len=%d, p_service_uuid=0x%x (data=%s)",
- m_advData.service_uuid_len,
- (uint32_t)m_advData.p_service_uuid,
- (m_advData.service_uuid_len > 0?(char *)hexData:"N/A")
- );
- } // We have a service to advertise
+ // We have a vector of service UUIDs that we wish to advertise. In order to use the
+ // ESP-IDF framework, these must be supplied in a contiguous array of their 128bit (16 byte)
+ // representations. If we have 1 or more services to advertise then we allocate enough
+ // storage to host them and then copy them in one at a time into the contiguous storage.
+ int numServices = m_serviceUUIDs.size();
+ if (numServices > 0) {
+ m_advData.service_uuid_len = 16*numServices;
+ m_advData.p_service_uuid = new uint8_t[m_advData.service_uuid_len];
+ uint8_t* p = m_advData.p_service_uuid;
+ for (int i=0; i<numServices; i++) {
+ ESP_LOGD(LOG_TAG, "- advertising service: %s", m_serviceUUIDs[i].toString().c_str());
+ BLEUUID serviceUUID128 = m_serviceUUIDs[i].to128();
+ memcpy(p, serviceUUID128.getNative()->uuid.uuid128, 16);
+ p+=16;
+ }
+ } else {
+ m_advData.service_uuid_len = 0;
+ ESP_LOGD(LOG_TAG, "- no services advertised");
+ }
// Set the configuration for advertising.
+ m_advData.set_scan_rsp = false;
esp_err_t errRc = ::esp_ble_gap_config_adv_data(&m_advData);
if (errRc != ESP_OK) {
ESP_LOGE(LOG_TAG, "<< esp_ble_gap_config_adv_data: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
return;
}
+ m_advData.set_scan_rsp = true;
+ errRc = ::esp_ble_gap_config_adv_data(&m_advData);
+ if (errRc != ESP_OK) {
+ ESP_LOGE(LOG_TAG, "<< esp_ble_gap_config_adv_data (Scan response): rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
+ return;
+ }
+
+ // If we had services to advertise then we previously allocated some storage for them.
+ // Here we release that storage.
+ if (m_advData.service_uuid_len > 0) {
+ delete[] m_advData.p_service_uuid;
+ m_advData.p_service_uuid = nullptr;
+ }
+
// Start advertising.
errRc = ::esp_ble_gap_start_advertising(&m_advParams);
if (errRc != ESP_OK) {
@@ -152,4 +149,6 @@ void BLEAdvertising::stop() {
}
ESP_LOGD(LOG_TAG, "<< stop");
} // stop
+
+
#endif /* CONFIG_BT_ENABLED */
diff --git a/src/BLEAdvertising.h b/src/BLEAdvertising.h
index 2d0b51c..6f315b8 100644
--- a/src/BLEAdvertising.h
+++ b/src/BLEAdvertising.h
@@ -11,6 +11,7 @@
#if defined(CONFIG_BT_ENABLED)
#include <esp_gap_ble_api.h>
#include "BLEUUID.h"
+#include <vector>
/**
* @brief Perform and manage %BLE advertising.
@@ -20,15 +21,15 @@
class BLEAdvertising {
public:
BLEAdvertising();
+ void addServiceUUID(BLEUUID serviceUUID);
+ void addServiceUUID(const char* serviceUUID);
void start();
void stop();
void setAppearance(uint16_t appearance);
- void setServiceUUID(const char* serviceUUID);
- void setServiceUUID(BLEUUID serviceUUID);
private:
esp_ble_adv_data_t m_advData;
esp_ble_adv_params_t m_advParams;
- BLEUUID m_serviceUUID;
+ std::vector<BLEUUID> m_serviceUUIDs;
};
#endif /* CONFIG_BT_ENABLED */
#endif /* COMPONENTS_CPP_UTILS_BLEADVERTISING_H_ */
diff --git a/src/BLECharacteristic.cpp b/src/BLECharacteristic.cpp
index f5b8200..284032e 100644
--- a/src/BLECharacteristic.cpp
+++ b/src/BLECharacteristic.cpp
@@ -94,19 +94,20 @@ void BLECharacteristic::executeCreate(BLEService* pService) {
m_semaphoreCreateEvt.take("executeCreate");
- std::string strValue = m_value.getValue();
-
+ /*
esp_attr_value_t value;
- value.attr_len = strValue.length();
+ value.attr_len = m_value.getLength();
value.attr_max_len = ESP_GATT_MAX_ATTR_LEN;
- value.attr_value = (uint8_t*)strValue.data();
+ value.attr_value = m_value.getData();
+ */
esp_err_t errRc = ::esp_ble_gatts_add_char(
m_pService->getHandle(),
getUUID().getNative(),
static_cast<esp_gatt_perm_t>(ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE),
getProperties(),
- &value,
+ //&value,
+ nullptr,
&control); // Whether to auto respond or not.
if (errRc != ESP_OK) {
@@ -131,7 +132,6 @@ void BLECharacteristic::executeCreate(BLEService* pService) {
} // executeCreate
-
/**
* @brief Return the BLE Descriptor for the given UUID if associated with this characteristic.
* @param [in] descriptorUUID The UUID of the descriptor that we wish to retrieve.
@@ -141,6 +141,7 @@ BLEDescriptor* BLECharacteristic::getDescriptorByUUID(const char* descriptorUUID
return m_descriptorMap.getByUUID(BLEUUID(descriptorUUID));
} // getDescriptorByUUID
+
/**
* @brief Return the BLE Descriptor for the given UUID if associated with this characteristic.
* @param [in] descriptorUUID The UUID of the descriptor that we wish to retrieve.
@@ -274,7 +275,7 @@ void BLECharacteristic::handleGATTServerEvent(
ESP_LOGD(LOG_TAG, " - Response to write event: New value: handle: %.2x, uuid: %s",
getHandle(), getUUID().toString().c_str());
- char *pHexData = BLEUtils::buildHexData(nullptr, param->write.value, param->write.len);
+ char* pHexData = BLEUtils::buildHexData(nullptr, param->write.value, param->write.len);
ESP_LOGD(LOG_TAG, " - Data: length: %d, data: %s", param->write.len, pHexData);
free(pHexData);
@@ -422,6 +423,7 @@ void BLECharacteristic::handleGATTServerEvent(
} // handleGATTServerEvent
+
/**
* @brief Send an indication.
* An indication is a transmission of up to the first 20 bytes of the characteristic value. An indication
diff --git a/src/BLECharacteristic.h b/src/BLECharacteristic.h
index b39c022..24977c0 100644
--- a/src/BLECharacteristic.h
+++ b/src/BLECharacteristic.h
@@ -29,16 +29,16 @@ public:
void setByUUID(const char* uuid, BLEDescriptor *pDescriptor);
void setByUUID(BLEUUID uuid, BLEDescriptor *pDescriptor);
void setByHandle(uint16_t handle, BLEDescriptor *pDescriptor);
- BLEDescriptor *getByUUID(const char* uuid);
- BLEDescriptor *getByUUID(BLEUUID uuid);
- BLEDescriptor *getByHandle(uint16_t handle);
- std::string toString();
+ BLEDescriptor* getByUUID(const char* uuid);
+ BLEDescriptor* getByUUID(BLEUUID uuid);
+ BLEDescriptor* getByHandle(uint16_t handle);
+ std::string toString();
void handleGATTServerEvent(
esp_gatts_cb_event_t event,
esp_gatt_if_t gatts_if,
- esp_ble_gatts_cb_param_t *param);
- BLEDescriptor *getFirst();
- BLEDescriptor *getNext();
+ esp_ble_gatts_cb_param_t* param);
+ BLEDescriptor* getFirst();
+ BLEDescriptor* getNext();
private:
std::map<std::string, BLEDescriptor *> m_uuidMap;
std::map<uint16_t, BLEDescriptor *> m_handleMap;
diff --git a/src/BLECharacteristicMap.cpp b/src/BLECharacteristicMap.cpp
index f475e83..6ded0a6 100644
--- a/src/BLECharacteristicMap.cpp
+++ b/src/BLECharacteristicMap.cpp
@@ -10,6 +10,17 @@
#include <iomanip>
#include "BLEService.h"
+
+/**
+ * @brief Return the characteristic by handle.
+ * @param [in] handle The handle to look up the characteristic.
+ * @return The characteristic.
+ */
+BLECharacteristic* BLECharacteristicMap::getByHandle(uint16_t handle) {
+ return m_handleMap.at(handle);
+} // getByHandle
+
+
/**
* @brief Return the characteristic by UUID.
* @param [in] UUID The UUID to look up the characteristic.
@@ -19,6 +30,7 @@ BLECharacteristic* BLECharacteristicMap::getByUUID(const char* uuid) {
return getByUUID(BLEUUID(uuid));
}
+
/**
* @brief Return the characteristic by UUID.
* @param [in] UUID The UUID to look up the characteristic.
@@ -36,26 +48,49 @@ BLECharacteristic* BLECharacteristicMap::getByUUID(BLEUUID uuid) {
/**
- * @brief Return the characteristic by handle.
- * @param [in] handle The handle to look up the characteristic.
- * @return The characteristic.
+ * @brief Get the first characteristic in the map.
+ * @return The first characteristic in the map.
*/
-BLECharacteristic* BLECharacteristicMap::getByHandle(uint16_t handle) {
- return m_handleMap.at(handle);
-} // getByHandle
+BLECharacteristic* BLECharacteristicMap::getFirst() {
+ m_iterator = m_uuidMap.begin();
+ if (m_iterator == m_uuidMap.end()) {
+ return nullptr;
+ }
+ BLECharacteristic* pRet = m_iterator->second;
+ m_iterator++;
+ return pRet;
+} // getFirst
/**
- * @brief Set the characteristic by UUID.
- * @param [in] uuid The uuid of the characteristic.
- * @param [in] characteristic The characteristic to cache.
- * @return N/A.
+ * @brief Get the next characteristic in the map.
+ * @return The next characteristic in the map.
*/
-void BLECharacteristicMap::setByUUID(
- BLEUUID uuid,
- BLECharacteristic *pCharacteristic) {
- m_uuidMap.insert(std::pair<std::string, BLECharacteristic *>(uuid.toString(), pCharacteristic));
-} // setByUUID
+BLECharacteristic* BLECharacteristicMap::getNext() {
+ if (m_iterator == m_uuidMap.end()) {
+ return nullptr;
+ }
+ BLECharacteristic* pRet = m_iterator->second;
+ m_iterator++;
+ return pRet;
+} // getNext
+
+
+/**
+ * @brief Pass the GATT server event onwards to each of the characteristics found in the mapping
+ * @param [in] event
+ * @param [in] gatts_if
+ * @param [in] param
+ */
+void BLECharacteristicMap::handleGATTServerEvent(
+ esp_gatts_cb_event_t event,
+ esp_gatt_if_t gatts_if,
+ 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);
+ }
+} // handleGATTServerEvent
/**
@@ -71,6 +106,19 @@ void BLECharacteristicMap::setByHandle(uint16_t handle,
/**
+ * @brief Set the characteristic by UUID.
+ * @param [in] uuid The uuid of the characteristic.
+ * @param [in] characteristic The characteristic to cache.
+ * @return N/A.
+ */
+void BLECharacteristicMap::setByUUID(
+ BLEUUID uuid,
+ BLECharacteristic *pCharacteristic) {
+ m_uuidMap.insert(std::pair<std::string, BLECharacteristic *>(uuid.toString(), pCharacteristic));
+} // setByUUID
+
+
+/**
* @brief Return a string representation of the characteristic map.
* @return A string representation of the characteristic map.
*/
@@ -89,48 +137,4 @@ std::string BLECharacteristicMap::toString() {
} // toString
-/**
- * @breif Pass the GATT server event onwards to each of the characteristics found in the mapping
- * @param [in] event
- * @param [in] gatts_if
- * @param [in] param
- */
-void BLECharacteristicMap::handleGATTServerEvent(
- esp_gatts_cb_event_t event,
- esp_gatt_if_t gatts_if,
- 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);
- }
-} // handleGATTServerEvent
-
-
-/**
- * @brief Get the first characteristic in the map.
- * @return The first characteristic in the map.
- */
-BLECharacteristic* BLECharacteristicMap::getFirst() {
- m_iterator = m_uuidMap.begin();
- if (m_iterator == m_uuidMap.end()) {
- return nullptr;
- }
- BLECharacteristic *pRet = m_iterator->second;
- m_iterator++;
- return pRet;
-} // getFirst
-
-
-/**
- * @brief Get the next characteristic in the map.
- * @return The next characteristic in the map.
- */
-BLECharacteristic* BLECharacteristicMap::getNext() {
- if (m_iterator == m_uuidMap.end()) {
- return nullptr;
- }
- BLECharacteristic *pRet = m_iterator->second;
- m_iterator++;
- return pRet;
-} // getNext
#endif /* CONFIG_BT_ENABLED */
diff --git a/src/BLEClient.cpp b/src/BLEClient.cpp
index f9b38c3..645c4ae 100644
--- a/src/BLEClient.cpp
+++ b/src/BLEClient.cpp
@@ -48,12 +48,28 @@ BLEClient::BLEClient() {
m_haveServices = false;
} // BLEClient
+
/**
- * @brief Connect to the partner.
+ * @brief Destructor.
+ */
+BLEClient::~BLEClient() {
+ // We may have allocated service references associated with this client. Before we are finished
+ // with the client, we must release resources.
+ for (auto &myPair : m_servicesMap) {
+ delete myPair.second;
+ }
+ m_servicesMap.clear();
+} // ~BLEClient
+
+
+/**
+ * @brief Connect to the partner (BLE Server).
* @param [in] address The address of the partner.
+ * @return True on success.
*/
bool BLEClient::connect(BLEAddress address) {
ESP_LOGD(LOG_TAG, ">> connect(%s)", address.toString().c_str());
+
// We need the connection handle that we get from registering the application. We register the app
// and then block on its completion. When the event has arrived, we will have the handle.
m_semaphoreRegEvt.take("connect");
@@ -62,10 +78,12 @@ bool BLEClient::connect(BLEAddress address) {
ESP_LOGE(LOG_TAG, "esp_ble_gattc_app_register: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
return false;
}
+
m_semaphoreRegEvt.wait("connect");
m_peerAddress = address;
+ // Perform the open connection request against the target BLE Server.
m_semaphoreOpenEvt.take("connect");
errRc = ::esp_ble_gattc_open(
getGattcIf(),
@@ -110,36 +128,6 @@ void BLEClient::gattClientEventHandler(
// Execute handler code based on the type of event received.
switch(event) {
//
- // ESP_GATTC_NOTIFY_EVT
- //
- // notify
- // uint16_t conn_id
- // esp_bd_addr_t remote_bda
- // esp_gatt_srvc_id_t srvc_id
- // esp_gatt_id_t char_id
- // esp_gatt_id_t descr_id
- // uint16_t value_len
- // uint8_t* value
- // bool is_notify
- //
- case ESP_GATTC_NOTIFY_EVT: {
- BLERemoteService *pBLERemoteService = getService(BLEUUID(evtParam->notify.srvc_id.id.uuid));
- if (pBLERemoteService == nullptr) {
- ESP_LOGE(LOG_TAG, "Could not find service with UUID %s for notification", BLEUUID(evtParam->notify.srvc_id.id.uuid).toString().c_str());
- break;
- }
- BLERemoteCharacteristic* pBLERemoteCharacteristic = pBLERemoteService->getCharacteristic(BLEUUID(evtParam->notify.char_id.uuid));
- if (pBLERemoteCharacteristic == nullptr) {
- ESP_LOGE(LOG_TAG, "Could not find characteristic with UUID %s for notification", BLEUUID(evtParam->notify.char_id.uuid).toString().c_str());
- break;
- }
- if (pBLERemoteCharacteristic->m_notifyCallback != nullptr) {
- pBLERemoteCharacteristic->m_notifyCallback(pBLERemoteCharacteristic, evtParam->notify.value, evtParam->notify.value_len, evtParam->notify.is_notify);
- }
- break;
- } // ESP_GATTC_NOTIFY_EVT
-
- //
// ESP_GATTC_OPEN_EVT
//
// open:
@@ -189,12 +177,19 @@ void BLEClient::gattClientEventHandler(
// ESP_GATTC_SEARCH_RES_EVT
//
// search_res:
- // - uint16_t conn_id
- // - esp_gatt_srvc_id_t srvc_id
+ // - uint16_t conn_id
+ // - uint16_t start_handle
+ // - uint16_t end_handle
+ // - esp_gatt_id_t srvc_id
//
case ESP_GATTC_SEARCH_RES_EVT: {
BLEUUID uuid = BLEUUID(evtParam->search_res.srvc_id);
- BLERemoteService* pRemoteService = new BLERemoteService(evtParam->search_res.srvc_id, this);
+ BLERemoteService* pRemoteService = new BLERemoteService(
+ evtParam->search_res.srvc_id,
+ this,
+ evtParam->search_res.start_handle,
+ evtParam->search_res.end_handle
+ );
m_servicesMap.insert(std::pair<std::string, BLERemoteService *>(uuid.toString(), pRemoteService));
break;
} // ESP_GATTC_SEARCH_RES_EVT
@@ -205,6 +200,7 @@ void BLEClient::gattClientEventHandler(
}
} // Switch
+ // Pass the request on to all services.
for (auto &myPair : m_servicesMap) {
myPair.second->gattClientEventHandler(event, gattc_if, evtParam);
}
@@ -215,7 +211,7 @@ void BLEClient::gattClientEventHandler(
/**
* @brief Retrieve the address of the peer.
*
- * Returns the address of the %BLE peer to which this client is connected.
+ * Returns the Bluetooth device address of the %BLE peer to which this client is connected.
*/
BLEAddress BLEClient::getPeerAddress() {
return m_peerAddress;
@@ -232,15 +228,14 @@ esp_gatt_if_t BLEClient::getGattcIf() {
} // getGattcIf
-
/**
- * @brief Get the service object corresponding to the uuid.
+ * @brief Get the service BLE Remote Service instance corresponding to the uuid.
* @param [in] uuid The UUID of the service being sought.
* @return A reference to the Service or nullptr if don't know about it.
*/
BLERemoteService* BLEClient::getService(const char* uuid) {
return getService(BLEUUID(uuid));
-}
+} // getService
/**
@@ -249,6 +244,7 @@ BLERemoteService* BLEClient::getService(const char* uuid) {
* @return A reference to the Service or nullptr if don't know about it.
*/
BLERemoteService* BLEClient::getService(BLEUUID uuid) {
+ ESP_LOGD(LOG_TAG, ">> getService: uuid: %s", uuid.toString().c_str());
// Design
// ------
// We wish to retrieve the service given its UUID. It is possible that we have not yet asked the
@@ -258,12 +254,14 @@ BLERemoteService* BLEClient::getService(BLEUUID uuid) {
if (!m_haveServices) {
getServices();
}
- std::string v = uuid.toString();
+ std::string uuidStr = uuid.toString();
for (auto &myPair : m_servicesMap) {
- if (myPair.first == v) {
+ if (myPair.first == uuidStr) {
+ ESP_LOGD(LOG_TAG, "<< getService: found the service with uuid: %s", uuid.toString().c_str());
return myPair.second;
}
- }
+ } // End of each of the services.
+ ESP_LOGD(LOG_TAG, "<< getService: not found");
return nullptr;
} // getService
@@ -287,7 +285,7 @@ std::map<std::string, BLERemoteService*>* BLEClient::getServices() {
esp_err_t errRc = esp_ble_gattc_search_service(
getGattcIf(),
getConnId(),
- NULL // Filter UUID
+ nullptr // Filter UUID
);
m_semaphoreSearchCmplEvt.take("getServices");
if (errRc != ESP_OK) {
@@ -319,7 +317,7 @@ std::string BLEClient::toString() {
ss << "\nServices:\n";
for (auto &myPair : m_servicesMap) {
ss << myPair.second->toString() << "\n";
- // myPair.second is the value
+ // myPair.second is the value
}
return ss.str();
} // toString
diff --git a/src/BLEClient.h b/src/BLEClient.h
index 898f98c..494f51d 100644
--- a/src/BLEClient.h
+++ b/src/BLEClient.h
@@ -28,6 +28,7 @@ class BLEClientCallbacks;
class BLEClient {
public:
BLEClient();
+ ~BLEClient();
bool connect(BLEAddress address);
void disconnect();
BLEAddress getPeerAddress();
@@ -39,8 +40,9 @@ public:
private:
friend class BLEDevice;
- friend class BLERemoteCharacteristic;
friend class BLERemoteService;
+ friend class BLERemoteCharacteristic;
+ friend class BLERemoteDescriptor;
void gattClientEventHandler(
esp_gattc_cb_event_t event,
diff --git a/src/BLEDevice.cpp b/src/BLEDevice.cpp
index 04cae14..b2777e5 100644
--- a/src/BLEDevice.cpp
+++ b/src/BLEDevice.cpp
@@ -7,21 +7,20 @@
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)
#include <freertos/FreeRTOS.h>
+#include <freertos/event_groups.h>
#include <freertos/task.h>
#include <esp_err.h>
#include <nvs_flash.h>
-#include <freertos/FreeRTOS.h>
-#include <freertos/event_groups.h>
-#include <bt.h> // ESP32 BLE
-#include <esp_bt_main.h> // ESP32 BLE
-#include <esp_gap_ble_api.h> // ESP32 BLE
-// ESP32 BLE
-#include <esp_gatts_api.h> // ESP32 BLE
-#include <esp_err.h> // ESP32 ESP-IDF
-#include <esp_log.h> // ESP32 ESP-IDF
-#include <map> // Part of C++ STL
-#include <sstream>
-#include <iomanip>
+#include <bt.h> // ESP32 BLE
+#include <esp_bt_main.h> // ESP32 BLE
+#include <esp_gap_ble_api.h> // ESP32 BLE
+#include <esp_gatts_api.h> // ESP32 BLE
+#include <esp_gattc_api.h> // ESP32 BLE
+#include <esp_err.h> // ESP32 ESP-IDF
+#include <esp_log.h> // ESP32 ESP-IDF
+#include <map> // Part of C++ Standard library
+#include <sstream> // Part of C++ Standard library
+#include <iomanip> // Part of C++ Standard library
#include "BLEDevice.h"
#include "BLEClient.h"
@@ -30,13 +29,18 @@
static const char* LOG_TAG = "BLEDevice";
-BLEServer *BLEDevice::m_bleServer = nullptr;
-BLEScan *BLEDevice::m_pScan = nullptr;
-BLEClient *BLEDevice::m_pClient = nullptr;
-
-#include <esp_gattc_api.h>
+/**
+ * Singletons for the BLEDevice.
+ */
+BLEServer* BLEDevice::m_pServer = nullptr;
+BLEScan* BLEDevice::m_pScan = nullptr;
+BLEClient* BLEDevice::m_pClient = nullptr;
+/**
+ * @brief Create a new instance of a client.
+ * @return A new instance of the client.
+ */
BLEClient* BLEDevice::createClient() {
m_pClient = new BLEClient();
return m_pClient;
@@ -44,23 +48,38 @@ BLEClient* BLEDevice::createClient() {
/**
+ * @brief Create a new instance of a server.
+ * @return A new instance of the server.
+ */
+BLEServer* BLEDevice::createServer() {
+ ESP_LOGD(LOG_TAG, ">> createServer");
+ m_pServer = new BLEServer();
+ m_pServer->createApp(0);
+ ESP_LOGD(LOG_TAG, "<< createServer");
+ return m_pServer;
+} // createServer
+
+
+/**
* @brief Handle GATT server events.
*
- * @param [in] event
- * @param [in] gatts_if
- * @param [in] param
+ * @param [in] event The event that has been newly received.
+ * @param [in] gatts_if The connection to the GATT interface.
+ * @param [in] param Parameters for the event.
*/
void BLEDevice::gattServerEventHandler(
esp_gatts_cb_event_t event,
esp_gatt_if_t gatts_if,
- esp_ble_gatts_cb_param_t *param
+ esp_ble_gatts_cb_param_t* param
) {
ESP_LOGD(LOG_TAG, "gattServerEventHandler [esp_gatt_if: %d] ... %s",
gatts_if,
BLEUtils::gattServerEventTypeToString(event).c_str());
+
BLEUtils::dumpGattServerEvent(event, gatts_if, param);
- if (BLEDevice::m_bleServer != nullptr) {
- BLEDevice::m_bleServer->handleGATTServerEvent(event, gatts_if, param);
+
+ if (BLEDevice::m_pServer != nullptr) {
+ BLEDevice::m_pServer->handleGATTServerEvent(event, gatts_if, param);
}
} // gattServerEventHandler
@@ -69,29 +88,26 @@ void BLEDevice::gattServerEventHandler(
* @brief Handle GATT client events.
*
* Handler for the GATT client events.
- * * `ESP_GATTC_OPEN_EVT` – Invoked when a connection is opened.
- * * `ESP_GATTC_PREP_WRITE_EVT` – Response to write a characteristic.
- * * `ESP_GATTC_READ_CHAR_EVT` – Response to read a characteristic.
- * * `ESP_GATTC_REG_EVT` – Invoked when a GATT client has been registered.
*
* @param [in] event
* @param [in] gattc_if
* @param [in] param
*/
void BLEDevice::gattClientEventHandler(
- esp_gattc_cb_event_t event,
- esp_gatt_if_t gattc_if,
- esp_ble_gattc_cb_param_t *param) {
+ esp_gattc_cb_event_t event,
+ esp_gatt_if_t gattc_if,
+ esp_ble_gattc_cb_param_t* param) {
ESP_LOGD(LOG_TAG, "gattClientEventHandler [esp_gatt_if: %d] ... %s",
gattc_if, BLEUtils::gattClientEventTypeToString(event).c_str());
BLEUtils::dumpGattClientEvent(event, gattc_if, param);
-
+/*
switch(event) {
default: {
break;
}
} // switch
+ */
// If we have a client registered, call it.
if (BLEDevice::m_pClient != nullptr) {
@@ -124,8 +140,8 @@ void BLEDevice::gapEventHandler(
}
} // switch
- if (BLEDevice::m_bleServer != nullptr) {
- BLEDevice::m_bleServer->handleGAPEvent(event, param);
+ if (BLEDevice::m_pServer != nullptr) {
+ BLEDevice::m_pServer->handleGAPEvent(event, param);
}
if (BLEDevice::m_pScan != nullptr) {
@@ -135,6 +151,18 @@ void BLEDevice::gapEventHandler(
/**
+ * @brief Retrieve the Scan object that we use for scanning.
+ * @return The scanning object reference.
+ */
+BLEScan* BLEDevice::getScan() {
+ if (m_pScan == nullptr) {
+ m_pScan = new BLEScan();
+ }
+ return m_pScan;
+} // getScan
+
+
+/**
* @brief Initialize the %BLE environment.
* @param deviceName The device name of the device.
*/
@@ -205,18 +233,4 @@ void BLEDevice::init(std::string deviceName) {
} // init
-
-/**
- * @brief Retrieve the Scan object that we use for scanning.
- * @return The scanning object reference.
- */
-BLEScan* BLEDevice::getScan() {
- if (m_pScan == nullptr) {
- m_pScan = new BLEScan();
- }
- return m_pScan;
-} // getScan
-
-
-
#endif // CONFIG_BT_ENABLED
diff --git a/src/BLEDevice.h b/src/BLEDevice.h
index 9d767c1..eb9fdaa 100644
--- a/src/BLEDevice.h
+++ b/src/BLEDevice.h
@@ -24,30 +24,34 @@
*/
class BLEDevice {
public:
- static void dumpDevices();
- static BLEClient *createClient();
- static void init(std::string deviceName);
- //static void scan(int duration, esp_ble_scan_type_t scan_type = BLE_SCAN_TYPE_PASSIVE);
- static BLEScan *getScan();
- static BLEServer *m_bleServer;
+ static BLEClient* createClient();
+ static BLEServer* createServer();
+ static void dumpDevices();
+ static BLEScan* getScan();
+ static void init(std::string deviceName);
+
+private:
+ static BLEServer *m_pServer;
static BLEScan *m_pScan;
static BLEClient *m_pClient;
-private:
static esp_gatt_if_t getGattcIF();
static void gattClientEventHandler(
- esp_gattc_cb_event_t event,
- esp_gatt_if_t gattc_if,
- esp_ble_gattc_cb_param_t *param);
+ esp_gattc_cb_event_t event,
+ esp_gatt_if_t gattc_if,
+ esp_ble_gattc_cb_param_t* param);
+
static void gattServerEventHandler(
esp_gatts_cb_event_t event,
esp_gatt_if_t gatts_if,
- esp_ble_gatts_cb_param_t *param);
+ esp_ble_gatts_cb_param_t* param);
+
static void gapEventHandler(
- esp_gap_ble_cb_event_t event,
- esp_ble_gap_cb_param_t *param);
+ esp_gap_ble_cb_event_t event,
+ esp_ble_gap_cb_param_t* param);
+
}; // class BLE
#endif // CONFIG_BT_ENABLED
diff --git a/src/BLERemoteCharacteristic.cpp b/src/BLERemoteCharacteristic.cpp
index 5227bf6..2e0fbb0 100644
--- a/src/BLERemoteCharacteristic.cpp
+++ b/src/BLERemoteCharacteristic.cpp
@@ -17,21 +17,98 @@
#include <sstream>
#include "BLEUtils.h"
#include "GeneralUtils.h"
+#include "BLERemoteDescriptor.h"
-static const char* LOG_TAG = "BLERemoteCharacteristic";
+static const char* LOG_TAG = "BLERemoteCharacteristic"; // The logging tag for this class.
+/**
+ * @brief Constructor.
+ * @param [in] handle The BLE server side handle of this characteristic.
+ * @param [in] uuid The UUID of this characteristic.
+ * @param [in] charProp The properties of this characteristic.
+ * @param [in] pRemoteService A reference to the remote service to which this remote characteristic pertains.
+ */
BLERemoteCharacteristic::BLERemoteCharacteristic(
- esp_gatt_id_t charId,
+ uint16_t handle,
+ BLEUUID uuid,
esp_gatt_char_prop_t charProp,
BLERemoteService* pRemoteService) {
- m_charId = charId;
+ ESP_LOGD(LOG_TAG, ">> BLERemoteCharacteristic: handle: %d 0x%d, uuid: %s", handle, handle, uuid.toString().c_str());
+ m_handle = handle;
+ m_uuid = uuid;
m_charProp = charProp;
m_pRemoteService = pRemoteService;
m_notifyCallback = nullptr;
+
+ retrieveDescriptors(); // Get the descriptors for this characteristic
+ ESP_LOGD(LOG_TAG, "<< BLERemoteCharacteristic");
} // BLERemoteCharacteristic
+/**
+ *@brief Destructor.
+ */
+BLERemoteCharacteristic::~BLERemoteCharacteristic() {
+ removeDescriptors(); // Release resources for any descriptor information we may have allocated.
+} // ~BLERemoteCharacteristic
+
+
+/**
+ * @brief Does the characteristic support broadcasting?
+ * @return True if the characteristic supports broadcasting.
+ */
+bool BLERemoteCharacteristic::canBroadcast() {
+ return (m_charProp & ESP_GATT_CHAR_PROP_BIT_BROADCAST) != 0;
+} // canBroadcast
+
+
+/**
+ * @brief Does the characteristic support indications?
+ * @return True if the characteristic supports indications.
+ */
+bool BLERemoteCharacteristic::canIndicate() {
+ return (m_charProp & ESP_GATT_CHAR_PROP_BIT_INDICATE) != 0;
+} // canIndicate
+
+
+/**
+ * @brief Does the characteristic support notifications?
+ * @return True if the characteristic supports notifications.
+ */
+bool BLERemoteCharacteristic::canNotify() {
+ return (m_charProp & ESP_GATT_CHAR_PROP_BIT_NOTIFY) != 0;
+} // canNotify
+
+
+/**
+ * @brief Does the characteristic support reading?
+ * @return True if the characteristic supports reading.
+ */
+bool BLERemoteCharacteristic::canRead() {
+ return (m_charProp & ESP_GATT_CHAR_PROP_BIT_READ) != 0;
+} // canRead
+
+
+/**
+ * @brief Does the characteristic support writing?
+ * @return True if the characteristic supports writing.
+ */
+bool BLERemoteCharacteristic::canWrite() {
+ return (m_charProp & ESP_GATT_CHAR_PROP_BIT_WRITE) != 0;
+} // canWrite
+
+
+/**
+ * @brief Does the characteristic support writing with no response?
+ * @return True if the characteristic supports writing with no response.
+ */
+bool BLERemoteCharacteristic::canWriteNoResponse() {
+ return (m_charProp & ESP_GATT_CHAR_PROP_BIT_WRITE_NR) != 0;
+} // canWriteNoResponse
+
+
+/*
static bool compareSrvcId(esp_gatt_srvc_id_t id1, esp_gatt_srvc_id_t id2) {
if (id1.id.inst_id != id2.id.inst_id) {
return false;
@@ -41,8 +118,9 @@ static bool compareSrvcId(esp_gatt_srvc_id_t id1, esp_gatt_srvc_id_t id2) {
}
return true;
} // compareSrvcId
+*/
-
+/*
static bool compareGattId(esp_gatt_id_t id1, esp_gatt_id_t id2) {
if (id1.inst_id != id2.inst_id) {
return false;
@@ -52,6 +130,7 @@ static bool compareGattId(esp_gatt_id_t id1, esp_gatt_id_t id2) {
}
return true;
} // compareCharId
+*/
/**
@@ -69,31 +148,56 @@ void BLERemoteCharacteristic::gattClientEventHandler(
esp_ble_gattc_cb_param_t* evtParam) {
switch(event) {
//
- // ESP_GATTC_READ_CHAR_EVT
- // This event indicates that the server has responded to the read request.
+ // ESP_GATTC_NOTIFY_EVT
//
- // read:
- // esp_gatt_status_t status
- // uint16_t conn_id
- // esp_gatt_srvc_id_t srvc_id
- // esp_gatt_id_t char_id
- // esp_gatt_id_t descr_id
- // uint8_t* value
- // uint16_t value_type
- // uint16_t value_len
- case ESP_GATTC_READ_CHAR_EVT: {
- if (compareSrvcId(evtParam->read.srvc_id, *m_pRemoteService->getSrvcId()) == false) {
+ // notify
+ // - uint16_t conn_id - The connection identifier of the server.
+ // - esp_bd_addr_t remote_bda - The device address of the BLE server.
+ // - uint16_t handle - The handle of the characteristic for which the event is being received.
+ // - uint16_t value_len - The length of the received data.
+ // - uint8_t* value - The received data.
+ // - bool is_notify - True if this is a notify, false if it is an indicate.
+ //
+ // We have received a notification event which means that the server wishes us to know about a notification
+ // piece of data. What we must now do is find the characteristic with the associated handle and then
+ // invoke its notification callback (if it has one).
+ //
+ case ESP_GATTC_NOTIFY_EVT: {
+ if (evtParam->notify.handle != getHandle()) {
break;
}
+ if (m_notifyCallback != nullptr) {
+ ESP_LOGD(LOG_TAG, "Invoking callback for notification on characteristic %s", toString().c_str());
+ m_notifyCallback(
+ this,
+ evtParam->notify.value,
+ evtParam->notify.value_len,
+ evtParam->notify.is_notify
+ );
+ } // End we have a callback function ...
+ break;
+ } // ESP_GATTC_NOTIFY_EVT
- if (evtParam->read.conn_id != m_pRemoteService->getClient()->getConnId()) {
- break;
- }
- if (compareGattId(evtParam->read.char_id, m_charId) == false) {
+ //
+ // ESP_GATTC_READ_CHAR_EVT
+ // This event indicates that the server has responded to the read request.
+ //
+ // read:
+ // - esp_gatt_status_t status
+ // - uint16_t conn_id
+ // - uint16_t handle
+ // - uint8_t* value
+ // - uint16_t value_len
+ //
+ case ESP_GATTC_READ_CHAR_EVT: {
+ // If this event is not for us, then nothing further to do.
+ if (evtParam->read.handle != getHandle()) {
break;
}
+ // At this point, we have determined that the event is for us, so now we save the value
+ // and unlock the semaphore to ensure that the requestor of the data can continue.
if (evtParam->read.status == ESP_GATT_OK) {
m_value = std::string((char*)evtParam->read.value, evtParam->read.value_len);
} else {
@@ -110,39 +214,53 @@ void BLERemoteCharacteristic::gattClientEventHandler(
//
// reg_for_notify:
// - esp_gatt_status_t status
- // - esp_gatt_srvc_id_t srvc_id
- // - esp_gatt_id_t char_id
+ // - uint16_t handle
+ //
case ESP_GATTC_REG_FOR_NOTIFY_EVT: {
- if (compareSrvcId(evtParam->reg_for_notify.srvc_id, *m_pRemoteService->getSrvcId()) == false) {
+ // If the request is not for this BLERemoteCharacteristic then move on to the next.
+ if (evtParam->reg_for_notify.handle != getHandle()) {
break;
}
- if (compareGattId(evtParam->reg_for_notify.char_id, m_charId) == false) {
+
+ // We have processed the notify registration and can unlock the semaphore.
+ m_semaphoreRegForNotifyEvt.give();
+ break;
+ } // ESP_GATTC_REG_FOR_NOTIFY_EVT
+
+
+ //
+ // ESP_GATTC_UNREG_FOR_NOTIFY_EVT
+ //
+ // unreg_for_notify:
+ // - esp_gatt_status_t status
+ // - uint16_t handle
+ //
+ case ESP_GATTC_UNREG_FOR_NOTIFY_EVT: {
+ if (evtParam->unreg_for_notify.handle != getHandle()) {
break;
}
+ // We have processed the notify un-registration and can unlock the semaphore.
m_semaphoreRegForNotifyEvt.give();
break;
- } // ESP_GATTC_REG_FOR_NOTIFY_EVT
+ } // ESP_GATTC_UNREG_FOR_NOTIFY_EVT:
//
// ESP_GATTC_WRITE_CHAR_EVT
//
// write:
- // esp_gatt_status_t status
- // uint16_t conn_id
- // esp_gatt_srvc_id_t srvc_id
- // esp_gatt_id_t char_id
- // esp_gatt_id_t descr_id
+ // - esp_gatt_status_t status
+ // - uint16_t conn_id
+ // - uint16_t handle
+ //
case ESP_GATTC_WRITE_CHAR_EVT: {
- if (compareSrvcId(evtParam->write.srvc_id, *m_pRemoteService->getSrvcId()) == false) {
- break;
- }
- if (evtParam->write.conn_id != m_pRemoteService->getClient()->getConnId()) {
- break;
- }
- if (compareGattId(evtParam->write.char_id, m_charId) == false) {
+ // Determine if this event is for us and, if not, pass onwards.
+ if (evtParam->write.handle != getHandle()) {
break;
}
+
+ // There is nothing further we need to do here. This is merely an indication
+ // that the write has completed and we can unlock the caller.
m_semaphoreWriteCharEvt.give();
break;
} // ESP_GATTC_WRITE_CHAR_EVT
@@ -151,13 +269,118 @@ void BLERemoteCharacteristic::gattClientEventHandler(
default: {
break;
}
- }
+ } // End switch
}; // gattClientEventHandler
+/**
+ * @brief Populate the descriptors (if any) for this characteristic.
+ */
+void BLERemoteCharacteristic::retrieveDescriptors() {
+ ESP_LOGD(LOG_TAG, ">> retrieveDescriptors() for characteristic: %s", getUUID().toString().c_str());
+
+ removeDescriptors(); // Remove any existing descriptors.
+
+ // Loop over each of the descriptors within the service associated with this characteristic.
+ // For each descriptor we find, create a BLERemoteDescriptor instance.
+ uint16_t offset = 0;
+ esp_gattc_descr_elem_t result;
+ while(1) {
+ uint16_t count = 1;
+ esp_gatt_status_t status = ::esp_ble_gattc_get_all_descr(
+ getRemoteService()->getClient()->getGattcIf(),
+ getRemoteService()->getClient()->getConnId(),
+ getHandle(),
+ &result,
+ &count,
+ offset
+ );
+
+ if (status == ESP_GATT_INVALID_OFFSET) { // We have reached the end of the entries.
+ break;
+ }
+
+ if (status != ESP_GATT_OK) {
+ ESP_LOGE(LOG_TAG, "esp_ble_gattc_get_all_descr: %s", BLEUtils::gattStatusToString(status).c_str());
+ break;
+ }
+
+ if (count == 0) {
+ break;
+ }
+ 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
+ BLERemoteDescriptor *pNewRemoteDescriptor = new BLERemoteDescriptor(
+ result.handle,
+ BLEUUID(result.uuid),
+ this
+ );
+
+ m_descriptorMap.insert(std::pair<std::string, BLERemoteDescriptor*>(pNewRemoteDescriptor->getUUID().toString(), pNewRemoteDescriptor));
+
+ offset++;
+ } // while true
+ //m_haveCharacteristics = true; // Remember that we have received the characteristics.
+ ESP_LOGD(LOG_TAG, "<< retrieveDescriptors(): Found %d descriptors.", offset);
+} // getDescriptors
+
+
+/**
+ * @brief Retrieve the map of descriptors keyed by UUID.
+ */
+std::map<std::string, BLERemoteDescriptor *>* BLERemoteCharacteristic::getDescriptors() {
+ return &m_descriptorMap;
+} // getDescriptors
+
+
+/**
+ * @brief Get the handle for this characteristic.
+ * @return The handle for this characteristic.
+ */
+uint16_t BLERemoteCharacteristic::getHandle() {
+ //ESP_LOGD(LOG_TAG, ">> getHandle: Characteristic: %s", getUUID().toString().c_str());
+ //ESP_LOGD(LOG_TAG, "<< getHandle: %d 0x%.2x", m_handle, m_handle);
+ return m_handle;
+} // getHandle
+
+
+/**
+ * @brief Get the descriptor instance with the given UUID that belongs to this characteristic.
+ * @param [in] uuid The UUID of the descriptor to find.
+ * @return The Remote descriptor (if present) or null if not present.
+ */
+BLERemoteDescriptor* BLERemoteCharacteristic::getDescriptor(BLEUUID uuid) {
+ ESP_LOGD(LOG_TAG, ">> getDescriptor: uuid: %s", uuid.toString().c_str());
+ std::string v = uuid.toString();
+ for (auto &myPair : m_descriptorMap) {
+ if (myPair.first == v) {
+ ESP_LOGD(LOG_TAG, "<< getDescriptor: found");
+ return myPair.second;
+ }
+ }
+ ESP_LOGD(LOG_TAG, "<< getDescriptor: Not found");
+ return nullptr;
+} // getDescriptor
+
+
+/**
+ * @brief Get the remote service associated with this characteristic.
+ * @return The remote service associated with this characteristic.
+ */
+BLERemoteService* BLERemoteCharacteristic::getRemoteService() {
+ return m_pRemoteService;
+} // getRemoteService
+
+
+/**
+ * @brief Get the UUID for this characteristic.
+ * @return The UUID for this characteristic.
+ */
BLEUUID BLERemoteCharacteristic::getUUID() {
- return BLEUUID(m_charId.uuid);
-}
+ return m_uuid;
+} // getUUID
+
/**
* @brief Read an unsigned 16 bit value
@@ -203,17 +426,18 @@ uint8_t BLERemoteCharacteristic::readUInt8(void) {
* @return The value of the remote characteristic.
*/
std::string BLERemoteCharacteristic::readValue() {
- ESP_LOGD(LOG_TAG, ">> readValue()");
+ ESP_LOGD(LOG_TAG, ">> readValue(): uuid: %s, handle: %d 0x%.2x", getUUID().toString().c_str(), getHandle(), getHandle());
m_semaphoreReadCharEvt.take("readValue");
// Ask the BLE subsystem to retrieve the value for the remote hosted characteristic.
+ // This is an asynchronous request which means that we must block waiting for the response
+ // to become available.
esp_err_t errRc = ::esp_ble_gattc_read_char(
m_pRemoteService->getClient()->getGattcIf(),
- m_pRemoteService->getClient()->getConnId(),
- m_pRemoteService->getSrvcId(),
- &m_charId,
- ESP_GATT_AUTH_REQ_NONE);
+ m_pRemoteService->getClient()->getConnId(), // The connection ID to the BLE server
+ getHandle(), // The handle of this characteristic
+ ESP_GATT_AUTH_REQ_NONE); // Security
if (errRc != ESP_OK) {
ESP_LOGE(LOG_TAG, "esp_ble_gattc_read_char: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
@@ -224,38 +448,51 @@ std::string BLERemoteCharacteristic::readValue() {
// in m_value will contain our data.
m_semaphoreReadCharEvt.wait("readValue");
- ESP_LOGD(LOG_TAG, "<< readValue()");
+ ESP_LOGD(LOG_TAG, "<< readValue(): length: %d", m_value.length());
return m_value;
} // readValue
/**
* @brief Register for notifications.
- * @param [in] notifyCallback A callback to be invoked for a notification.
+ * @param [in] notifyCallback A callback to be invoked for a notification. If NULL is provided then we are
+ * unregistering a notification.
* @return N/A.
*/
void BLERemoteCharacteristic::registerForNotify(
void (*notifyCallback)(
BLERemoteCharacteristic* pBLERemoteCharacteristic,
- uint8_t* pData,
- size_t length,
- bool isNotify)) {
- ESP_LOGD(LOG_TAG, ">> registerForNotify()");
+ uint8_t* pData,
+ size_t length,
+ bool isNotify)) {
+ ESP_LOGD(LOG_TAG, ">> registerForNotify(): %s", toString().c_str());
- m_notifyCallback = notifyCallback; // Save the notification callback.
+ m_notifyCallback = notifyCallback; // Save the notification callback.
m_semaphoreRegForNotifyEvt.take("registerForNotify");
- esp_err_t errRc = ::esp_ble_gattc_register_for_notify(
- m_pRemoteService->getClient()->getGattcIf(),
- *m_pRemoteService->getClient()->getPeerAddress().getNative(),
- m_pRemoteService->getSrvcId(),
- &m_charId);
+ if (notifyCallback != nullptr) { // If we have a callback function, then this is a registration.
+ esp_err_t errRc = ::esp_ble_gattc_register_for_notify(
+ m_pRemoteService->getClient()->getGattcIf(),
+ *m_pRemoteService->getClient()->getPeerAddress().getNative(),
+ getHandle()
+ );
- if (errRc != ESP_OK) {
- ESP_LOGE(LOG_TAG, "esp_ble_gattc_register_for_notify: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
- return;
- }
+ if (errRc != ESP_OK) {
+ ESP_LOGE(LOG_TAG, "esp_ble_gattc_register_for_notify: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
+ }
+ } // End Register
+ else { // If we weren't passed a callback function, then this is an unregistration.
+ esp_err_t errRc = ::esp_ble_gattc_unregister_for_notify(
+ m_pRemoteService->getClient()->getGattcIf(),
+ *m_pRemoteService->getClient()->getPeerAddress().getNative(),
+ getHandle()
+ );
+
+ if (errRc != ESP_OK) {
+ ESP_LOGE(LOG_TAG, "esp_ble_gattc_unregister_for_notify: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
+ }
+ } // End Unregister
m_semaphoreRegForNotifyEvt.wait("registerForNotify");
@@ -264,14 +501,31 @@ void BLERemoteCharacteristic::registerForNotify(
/**
+ * @brief Delete the descriptors in the descriptor map.
+ * We maintain a map called m_descriptorMap that contains pointers to BLERemoteDescriptors
+ * object references. Since we allocated these in this class, we are also responsible for deleteing
+ * them. This method does just that.
+ * @return N/A.
+ */
+void BLERemoteCharacteristic::removeDescriptors() {
+ // Iterate through all the descriptors releasing their storage and erasing them from the map.
+ for (auto &myPair : m_descriptorMap) {
+ m_descriptorMap.erase(myPair.first);
+ delete myPair.second;
+ }
+ m_descriptorMap.clear(); // Technically not neeeded, but just to be sure.
+} // removeCharacteristics
+
+
+/**
* @brief Convert a BLERemoteCharacteristic to a string representation;
* @return a String representation.
*/
std::string BLERemoteCharacteristic::toString() {
std::ostringstream ss;
- ss << "Characteristic: uuid: " << BLEUUID(m_charId.uuid).toString() <<
- ", props: " << BLEUtils::characteristicPropertiesToString(m_charProp) <<
- ", inst_id: " << (int)m_charId.inst_id;
+ ss << "Characteristic: uuid: " << m_uuid.toString() <<
+ ", handle: " << getHandle() << " 0x" << std::hex << getHandle() <<
+ ", props: " << BLEUtils::characteristicPropertiesToString(m_charProp);
return ss.str();
} // toString
@@ -287,11 +541,11 @@ void BLERemoteCharacteristic::writeValue(std::string newValue, bool response) {
m_semaphoreWriteCharEvt.take("writeValue");
+ // Invoke the ESP-IDF API to perform the write.
esp_err_t errRc = ::esp_ble_gattc_write_char(
m_pRemoteService->getClient()->getGattcIf(),
m_pRemoteService->getClient()->getConnId(),
- m_pRemoteService->getSrvcId(),
- &m_charId,
+ getHandle(),
newValue.length(),
(uint8_t*)newValue.data(),
response?ESP_GATT_WRITE_TYPE_RSP:ESP_GATT_WRITE_TYPE_NO_RSP,
@@ -332,5 +586,4 @@ void BLERemoteCharacteristic::writeValue(uint8_t* data, size_t length, bool resp
writeValue(std::string((char *)data, length), response);
} // writeValue
-
#endif /* CONFIG_BT_ENABLED */
diff --git a/src/BLERemoteCharacteristic.h b/src/BLERemoteCharacteristic.h
index b5b22b6..6f23f49 100644
--- a/src/BLERemoteCharacteristic.h
+++ b/src/BLERemoteCharacteristic.h
@@ -15,49 +15,71 @@
#include <esp_gattc_api.h>
#include "BLERemoteService.h"
+#include "BLERemoteDescriptor.h"
#include "BLEUUID.h"
#include "FreeRTOS.h"
class BLERemoteService;
+class BLERemoteDescriptor;
/**
* @brief A model of a remote %BLE characteristic.
*/
class BLERemoteCharacteristic {
public:
- BLERemoteCharacteristic(esp_gatt_id_t charId, esp_gatt_char_prop_t charProp, BLERemoteService* pRemoteService);
+ ~BLERemoteCharacteristic();
// Public member functions
+ bool canBroadcast();
+ bool canIndicate();
+ bool canNotify();
+ bool canRead();
+ bool canWrite();
+ bool canWriteNoResponse();
+ BLERemoteDescriptor* getDescriptor(BLEUUID uuid);
+ std::map<std::string, BLERemoteDescriptor *>* getDescriptors();
+ uint16_t getHandle();
BLEUUID getUUID();
std::string readValue(void);
uint8_t readUInt8(void);
uint16_t readUInt16(void);
uint32_t readUInt32(void);
- void registerForNotify(void (*notifyCallback)(BLERemoteCharacteristic *pBLERemoteCharacteristic, uint8_t *pData, size_t length, bool isNotify));
+ void registerForNotify(void (*notifyCallback)(BLERemoteCharacteristic* pBLERemoteCharacteristic, uint8_t* pData, size_t length, bool isNotify));
void writeValue(uint8_t* data, size_t length, bool response = false);
void writeValue(std::string newValue, bool response = false);
void writeValue(uint8_t newValue, bool response = false);
std::string toString(void);
private:
+ BLERemoteCharacteristic(uint16_t handle, BLEUUID uuid, esp_gatt_char_prop_t charProp, BLERemoteService* pRemoteService);
friend class BLEClient;
friend class BLERemoteService;
+ friend class BLERemoteDescriptor;
// Private member functions
void gattClientEventHandler(
esp_gattc_cb_event_t event,
esp_gatt_if_t gattc_if,
- esp_ble_gattc_cb_param_t *evtParam);
+ esp_ble_gattc_cb_param_t* evtParam);
+
+
+ BLERemoteService* getRemoteService();
+ void removeDescriptors();
+ void retrieveDescriptors();
// Private properties
- esp_gatt_id_t m_charId;
+ BLEUUID m_uuid;
esp_gatt_char_prop_t m_charProp;
+ uint16_t m_handle;
BLERemoteService* m_pRemoteService;
FreeRTOS::Semaphore m_semaphoreReadCharEvt = FreeRTOS::Semaphore("ReadCharEvt");
FreeRTOS::Semaphore m_semaphoreRegForNotifyEvt = FreeRTOS::Semaphore("RegForNotifyEvt");
FreeRTOS::Semaphore m_semaphoreWriteCharEvt = FreeRTOS::Semaphore("WriteCharEvt");
std::string m_value;
- void (*m_notifyCallback)(BLERemoteCharacteristic *pBLERemoteCharacteristic, uint8_t *pData, size_t length, bool isNotify);
+ void (*m_notifyCallback)(BLERemoteCharacteristic* pBLERemoteCharacteristic, uint8_t* pData, size_t length, bool isNotify);
+
+ // We maintain a map of descriptors owned by this characteristic keyed by a string representation of the UUID.
+ std::map<std::string, BLERemoteDescriptor*> m_descriptorMap;
}; // BLERemoteCharacteristic
#endif /* CONFIG_BT_ENABLED */
#endif /* COMPONENTS_CPP_UTILS_BLEREMOTECHARACTERISTIC_H_ */
diff --git a/src/BLERemoteDescriptor.cpp b/src/BLERemoteDescriptor.cpp
index 2be312a..a606929 100644
--- a/src/BLERemoteDescriptor.cpp
+++ b/src/BLERemoteDescriptor.cpp
@@ -6,6 +6,154 @@
*/
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)
+#include <sstream>
#include "BLERemoteDescriptor.h"
+#include "GeneralUtils.h"
+#include <esp_log.h>
+
+static const char* LOG_TAG = "BLERemoteDescriptor";
+
+
+BLERemoteDescriptor::BLERemoteDescriptor(
+ uint16_t handle,
+ BLEUUID uuid,
+ BLERemoteCharacteristic* pRemoteCharacteristic) {
+
+ m_handle = handle;
+ m_uuid = uuid;
+ m_pRemoteCharacteristic = pRemoteCharacteristic;
+}
+
+/**
+ * @brief Retrieve the handle associated with this remote descriptor.
+ * @return The handle associated with this remote descriptor.
+ */
+uint16_t BLERemoteDescriptor::getHandle() {
+ return m_handle;
+} // getHandle
+
+
+/**
+ * @brief Retrieve the UUID associated this remote descriptor.
+ * @return The UUID associated this remote descriptor.
+ */
+BLEUUID BLERemoteDescriptor::getUUID() {
+ return m_uuid;
+} // getUUID
+
+
+std::string BLERemoteDescriptor::readValue(void) {
+ m_semaphoreReadDescrEvt.take("readValue");
+
+ // Ask the BLE subsystem to retrieve the value for the remote hosted characteristic.
+ esp_err_t errRc = ::esp_ble_gattc_read_char_descr(
+ m_pRemoteCharacteristic->getRemoteService()->getClient()->getGattcIf(),
+ m_pRemoteCharacteristic->getRemoteService()->getClient()->getConnId(), // The connection ID to the BLE server
+ getHandle(), // The handle of this characteristic
+ ESP_GATT_AUTH_REQ_NONE); // Security
+
+ if (errRc != ESP_OK) {
+ ESP_LOGE(LOG_TAG, "esp_ble_gattc_read_char: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
+ return "";
+ }
+
+ // Block waiting for the event that indicates that the read has completed. When it has, the std::string found
+ // in m_value will contain our data.
+ m_semaphoreReadDescrEvt.wait("readValue");
+
+ ESP_LOGD(LOG_TAG, "<< readValue(): length: %d", m_value.length());
+ return m_value;
+ return "";
+} // readValue
+
+
+uint8_t BLERemoteDescriptor::readUInt8(void) {
+ std::string value = readValue();
+ if (value.length() >= 1) {
+ return (uint8_t)value[0];
+ }
+ return 0;
+} // readUInt8
+
+
+uint16_t BLERemoteDescriptor::readUInt16(void) {
+ std::string value = readValue();
+ if (value.length() >= 2) {
+ return *(uint16_t*)(value.data());
+ }
+ return 0;
+} // readUInt16
+
+
+uint32_t BLERemoteDescriptor::readUInt32(void) {
+ std::string value = readValue();
+ if (value.length() >= 4) {
+ return *(uint32_t*)(value.data());
+ }
+ return 0;
+} // readUInt32
+
+
+/**
+ * @brief Return a string representation of this BLE Remote Descriptor.
+ * @retun A string representation of this BLE Remote Descriptor.
+ */
+std::string BLERemoteDescriptor::toString(void) {
+ std::stringstream ss;
+ ss << "handle: " << getHandle() << ", uuid: " << getUUID().toString();
+ return ss.str();
+} // toString
+
+
+/**
+ * @brief Write data to the BLE Remote Descriptor.
+ * @param [in] data The data to send to the remote descriptor.
+ * @param [in] length The length of the data to send.
+ * @param [in] response True if we expect a response.
+ */
+void BLERemoteDescriptor::writeValue(
+ uint8_t* data,
+ size_t length,
+ bool response) {
+ ESP_LOGD(LOG_TAG, ">> writeValue: %s", toString().c_str());
+ esp_err_t errRc = ::esp_ble_gattc_write_char_descr(
+ m_pRemoteCharacteristic->getRemoteService()->getClient()->getGattcIf(),
+ m_pRemoteCharacteristic->getRemoteService()->getClient()->getConnId(),
+ getHandle(),
+ length, // Data length
+ data, // Data
+ ESP_GATT_WRITE_TYPE_NO_RSP,
+ ESP_GATT_AUTH_REQ_NONE
+ );
+ if (errRc != ESP_OK) {
+ ESP_LOGE(LOG_TAG, "esp_ble_gattc_write_char_descr: %d", errRc);
+ }
+ ESP_LOGD(LOG_TAG, "<< writeValue");
+} // writeValue
+
+
+/**
+ * @brief Write data represented as a string to the BLE Remote Descriptor.
+ * @param [in] newValue The data to send to the remote descriptor.
+ * @param [in] response True if we expect a response.
+ */
+void BLERemoteDescriptor::writeValue(
+ std::string newValue,
+ bool response) {
+ writeValue(newValue.data(), newValue.length());
+} // writeValue
+
+
+/**
+ * @brief Write a byte value to the Descriptor.
+ * @param [in] The single byte to write.
+ * @param [in] True if we expect a response.
+ */
+void BLERemoteDescriptor::writeValue(
+ uint8_t newValue,
+ bool response) {
+ writeValue(&newValue, 1, response);
+} // writeValue
+
#endif /* CONFIG_BT_ENABLED */
diff --git a/src/BLERemoteDescriptor.h b/src/BLERemoteDescriptor.h
index a8d944d..c2cf383 100644
--- a/src/BLERemoteDescriptor.h
+++ b/src/BLERemoteDescriptor.h
@@ -9,12 +9,47 @@
#define COMPONENTS_CPP_UTILS_BLEREMOTEDESCRIPTOR_H_
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)
+#include <string>
+#include <esp_gattc_api.h>
+
+#include "BLERemoteCharacteristic.h"
+#include "BLEUUID.h"
+#include "FreeRTOS.h"
+
+class BLERemoteCharacteristic;
/**
* @brief A model of remote %BLE descriptor.
*/
class BLERemoteDescriptor {
public:
+ uint16_t getHandle();
+ BLEUUID getUUID();
+ std::string readValue(void);
+ uint8_t readUInt8(void);
+ uint16_t readUInt16(void);
+ uint32_t readUInt32(void);
+ std::string toString(void);
+ //void registerForNotify(void (*notifyCallback)(BLERemoteCharacteristic *pBLERemoteCharacteristic, uint8_t *pData, size_t length, bool isNotify));
+ void writeValue(uint8_t* data, size_t length, bool response = false);
+ void writeValue(std::string newValue, bool response = false);
+ void writeValue(uint8_t newValue, bool response = false);
+
+
+private:
+ friend class BLERemoteCharacteristic;
+ BLERemoteDescriptor(
+ uint16_t handle,
+ BLEUUID uuid,
+ BLERemoteCharacteristic* pRemoteCharacteristic
+ );
+ uint16_t m_handle; // Server handle of this descriptor.
+ BLEUUID m_uuid; // UUID of this descriptor.
+ std::string m_value; // Last received value of the descriptor.
+ BLERemoteCharacteristic* m_pRemoteCharacteristic; // Reference to the Remote characteristic of which this descriptor is associated.
+ FreeRTOS::Semaphore m_semaphoreReadDescrEvt = FreeRTOS::Semaphore("ReadDescrEvt");
+
+
};
#endif /* CONFIG_BT_ENABLED */
#endif /* COMPONENTS_CPP_UTILS_BLEREMOTEDESCRIPTOR_H_ */
diff --git a/src/BLERemoteService.cpp b/src/BLERemoteService.cpp
index 4d18625..c312e94 100644
--- a/src/BLERemoteService.cpp
+++ b/src/BLERemoteService.cpp
@@ -17,13 +17,21 @@
static const char* LOG_TAG = "BLERemoteService";
BLERemoteService::BLERemoteService(
- esp_gatt_srvc_id_t srvcId,
- BLEClient *pClient) {
+ esp_gatt_id_t srvcId,
+ BLEClient* pClient,
+ uint16_t startHandle,
+ uint16_t endHandle
+ ) {
+ ESP_LOGD(LOG_TAG, ">> BLERemoteService()");
m_srvcId = srvcId;
m_pClient = pClient;
m_uuid = BLEUUID(m_srvcId);
m_haveCharacteristics = false;
+ m_startHandle = startHandle;
+ m_endHandle = endHandle;
+
+ ESP_LOGD(LOG_TAG, "<< BLERemoteService()");
}
@@ -31,6 +39,7 @@ BLERemoteService::~BLERemoteService() {
removeCharacteristics();
}
+/*
static bool compareSrvcId(esp_gatt_srvc_id_t id1, esp_gatt_srvc_id_t id2) {
if (id1.id.inst_id != id2.id.inst_id) {
return false;
@@ -40,7 +49,7 @@ static bool compareSrvcId(esp_gatt_srvc_id_t id1, esp_gatt_srvc_id_t id2) {
}
return true;
} // compareSrvcId
-
+*/
/**
* @brief Handle GATT Client events
@@ -60,6 +69,7 @@ void BLERemoteService::gattClientEventHandler(
// - esp_gatt_id_t char_id
// - esp_gatt_char_prop_t char_prop
//
+ /*
case ESP_GATTC_GET_CHAR_EVT: {
// Is this event for this service? If yes, then the local srvc_id and the event srvc_id will be
// the same.
@@ -94,7 +104,7 @@ void BLERemoteService::gattClientEventHandler(
//m_semaphoreGetCharEvt.give();
break;
} // ESP_GATTC_GET_CHAR_EVT
-
+*/
default: {
break;
}
@@ -108,13 +118,13 @@ void BLERemoteService::gattClientEventHandler(
/**
- * @brief Get the characteristic object for the UUID.
- * @param [in] uuid Characteristic uuid.
- * @return Reference to the characteristic object.
+ * @brief Get the remote characteristic object for the characteristic UUID.
+ * @param [in] uuid Remote characteristic uuid.
+ * @return Reference to the remote characteristic object.
*/
BLERemoteCharacteristic* BLERemoteService::getCharacteristic(const char* uuid) {
return getCharacteristic(BLEUUID(uuid));
-}
+} // getCharacteristic
/**
@@ -130,7 +140,7 @@ BLERemoteCharacteristic* BLERemoteService::getCharacteristic(BLEUUID uuid) {
// asked the device about its characteristics, then we do that now. Once we get the results we can then
// examine the characteristics map to see if it has the characteristic we are looking for.
if (!m_haveCharacteristics) {
- getCharacteristics();
+ retrieveCharacteristics();
}
std::string v = uuid.toString();
for (auto &myPair : m_characteristicMap) {
@@ -144,14 +154,15 @@ BLERemoteCharacteristic* BLERemoteService::getCharacteristic(BLEUUID uuid) {
/**
* @brief Retrieve all the characteristics for this service.
+ * This function will not return until we have all the characteristics.
* @return N/A
*/
-void BLERemoteService::getCharacteristics() {
+void BLERemoteService::retrieveCharacteristics() {
ESP_LOGD(LOG_TAG, ">> getCharacteristics() for service: %s", getUUID().toString().c_str());
removeCharacteristics(); // Forget any previous characteristics.
-
+ /*
m_semaphoreGetCharEvt.take("getCharacteristics");
esp_err_t errRc = ::esp_ble_gattc_get_characteristic(
@@ -168,18 +179,135 @@ void BLERemoteService::getCharacteristics() {
m_semaphoreGetCharEvt.wait("getCharacteristics"); // Wait for the characteristics to become available.
m_haveCharacteristics = true; // Remember that we have received the characteristics.
+ */
+ //ESP_LOGE(LOG_TAG, "!!! NOT IMPLEMENTED !!!");
+ //ESP_LOGD(LOG_TAG, "--- test code ---");
+ /*
+ uint16_t count;
+ esp_gatt_status_t status = ::esp_ble_gattc_get_attr_count(
+ getClient()->getGattcIf(),
+ getClient()->getConnId(),
+ ESP_GATT_DB_CHARACTERISTIC,
+ m_startHandle,
+ m_endHandle,
+ 0, // Characteristic handle ... only used for ESP_GATT_DB_DESCRIPTOR
+ &count
+ );
+ if (status != ESP_GATT_OK) {
+ ESP_LOGE(LOG_TAG, "esp_ble_gattc_get_attr_count: %s", BLEUtils::gattStatusToString(status).c_str());
+ } else {
+ ESP_LOGD(LOG_TAG, "Number of characteristics associated with service is %d", count);
+ }
+
+ count = 1;
+ esp_gattc_service_elem_t srvcElem;
+ status = ::esp_ble_gattc_get_service(
+ getClient()->getGattcIf(),
+ getClient()->getConnId(),
+ &m_srvcId.uuid, // UUID of service
+ &srvcElem, // Records
+ &count, // records retrieved
+ 0 // offset
+ );
+ if (status != ESP_GATT_OK) {
+ ESP_LOGE(LOG_TAG, "esp_ble_gattc_get_service: %s", BLEUtils::gattStatusToString(status).c_str());
+ }
+ else {
+ ESP_LOGD(LOG_TAG, "%s", BLEUtils::gattcServiceElementToString(&srvcElem).c_str());
+ }
+ */
+
+ uint16_t offset = 0;
+ esp_gattc_char_elem_t result;
+ while(1) {
+ uint16_t count = 1;
+ esp_gatt_status_t status = ::esp_ble_gattc_get_all_char(
+ getClient()->getGattcIf(),
+ getClient()->getConnId(),
+ m_startHandle,
+ m_endHandle,
+ &result,
+ &count,
+ offset
+ );
+
+ if (status == ESP_GATT_INVALID_OFFSET) { // We have reached the end of the entries.
+ break;
+ }
+
+ if (status != ESP_GATT_OK) { // If we got an error, end.
+ ESP_LOGE(LOG_TAG, "esp_ble_gattc_get_all_char: %s", BLEUtils::gattStatusToString(status).c_str());
+ break;
+ }
+
+ if (count == 0) { // If we failed to get any new records, end.
+ break;
+ }
+
+ ESP_LOGD(LOG_TAG, "Found a characteristic: Handle: %d, UUID: %s", result.char_handle, BLEUUID(result.uuid).toString().c_str());
+
+ // We now have a new characteristic ... let us add that to our set of known characteristics
+ BLERemoteCharacteristic *pNewRemoteCharacteristic = new BLERemoteCharacteristic(
+ result.char_handle,
+ BLEUUID(result.uuid),
+ result.properties,
+ this
+ );
+
+ m_characteristicMap.insert(std::pair<std::string, BLERemoteCharacteristic*>(pNewRemoteCharacteristic->getUUID().toString(), pNewRemoteCharacteristic));
+
+ offset++; // Increment our count of number of descriptors found.
+ } // Loop forever (until we break inside the loop).
+
+ m_haveCharacteristics = true; // Remember that we have received the characteristics.
ESP_LOGD(LOG_TAG, "<< getCharacteristics()");
} // getCharacteristics
+/**
+ * @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() {
+ 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
+ // call and does not return until all the characteristics are available.
+ if (!m_haveCharacteristics) {
+ retrieveCharacteristics();
+ }
+ ESP_LOGD(LOG_TAG, "<< getCharacteristics() for service: %s", getUUID().toString().c_str());
+ return &m_characteristicMap;
+} // getCharacteristics
+
+
BLEClient* BLERemoteService::getClient() {
return m_pClient;
}
-esp_gatt_srvc_id_t* BLERemoteService::getSrvcId() {
+
+uint16_t BLERemoteService::getEndHandle() {
+ return m_endHandle;
+}
+
+
+esp_gatt_id_t* BLERemoteService::getSrvcId() {
return &m_srvcId;
}
+
+uint16_t BLERemoteService::getStartHandle() {
+ return m_startHandle;
+}
+
+uint16_t BLERemoteService::getHandle() {
+ ESP_LOGD(LOG_TAG, ">> getHandle: service: %s", getUUID().toString().c_str());
+ //ESP_LOGE(LOG_TAG, "!!! getHandle: NOT IMPLEMENTED !!!");
+ ESP_LOGD(LOG_TAG, "<< getHandle: %d 0x%.2x", getStartHandle(), getStartHandle());
+ return getStartHandle();
+}
+
+
BLEUUID BLERemoteService::getUUID() {
return m_uuid;
}
@@ -195,8 +323,9 @@ BLEUUID BLERemoteService::getUUID() {
void BLERemoteService::removeCharacteristics() {
for (auto &myPair : m_characteristicMap) {
delete myPair.second;
+ m_characteristicMap.erase(myPair.first);
}
- m_characteristicMap.clear();
+ m_characteristicMap.clear(); // Clear the map
} // removeCharacteristics
@@ -208,6 +337,8 @@ void BLERemoteService::removeCharacteristics() {
std::string BLERemoteService::toString() {
std::ostringstream ss;
ss << "Service: uuid: " + m_uuid.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();
// myPair.second is the value
@@ -217,4 +348,6 @@ std::string BLERemoteService::toString() {
+
+
#endif /* CONFIG_BT_ENABLED */
diff --git a/src/BLERemoteService.h b/src/BLERemoteService.h
index 4393fbc..2007fa2 100644
--- a/src/BLERemoteService.h
+++ b/src/BLERemoteService.h
@@ -26,24 +26,32 @@ class BLERemoteCharacteristic;
*/
class BLERemoteService {
public:
- BLERemoteService(esp_gatt_srvc_id_t srvcId, BLEClient* pClient);
+
virtual ~BLERemoteService();
// Public methods
BLERemoteCharacteristic* getCharacteristic(const char* uuid);
BLERemoteCharacteristic* getCharacteristic(BLEUUID uuid);
- void getCharacteristics(void);
+ std::map<std::string, BLERemoteCharacteristic*>* getCharacteristics();
+
BLEClient* getClient(void);
+ uint16_t getHandle();
BLEUUID getUUID(void);
std::string toString(void);
private:
+ // Private constructor ... never meant to be created by a user application.
+ BLERemoteService(esp_gatt_id_t srvcId, BLEClient* pClient, uint16_t startHandle, uint16_t endHandle);
+
// Friends
friend class BLEClient;
friend class BLERemoteCharacteristic;
// Private methods
- esp_gatt_srvc_id_t* getSrvcId(void);
+ void retrieveCharacteristics(void);
+ esp_gatt_id_t* getSrvcId(void);
+ uint16_t getStartHandle();
+ uint16_t getEndHandle();
void gattClientEventHandler(
esp_gattc_cb_event_t event,
esp_gatt_if_t gattc_if,
@@ -51,12 +59,17 @@ private:
void removeCharacteristics();
// 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;
+
bool m_haveCharacteristics; // Have we previously obtained the characteristics.
BLEClient* m_pClient;
FreeRTOS::Semaphore m_semaphoreGetCharEvt = FreeRTOS::Semaphore("GetCharEvt");
- esp_gatt_srvc_id_t m_srvcId;
+ esp_gatt_id_t m_srvcId;
BLEUUID m_uuid;
+ uint16_t m_startHandle;
+ uint16_t m_endHandle;
}; // BLERemoteService
#endif /* CONFIG_BT_ENABLED */
diff --git a/src/BLEScan.cpp b/src/BLEScan.cpp
index 54fcac0..925c09d 100644
--- a/src/BLEScan.cpp
+++ b/src/BLEScan.cpp
@@ -21,32 +21,20 @@
static const char* LOG_TAG = "BLEScan";
+/**
+ * Constructor
+ */
BLEScan::BLEScan() {
m_scan_params.scan_type = BLE_SCAN_TYPE_PASSIVE; // Default is a passive scan.
m_scan_params.own_addr_type = BLE_ADDR_TYPE_PUBLIC;
m_scan_params.scan_filter_policy = BLE_SCAN_FILTER_ALLOW_ALL;
+ m_pAdvertisedDeviceCallbacks = nullptr;
+ m_stopped = true;
setInterval(100);
setWindow(100);
- m_pAdvertisedDeviceCallbacks = nullptr;
- m_stopped = true;
} // BLEScan
-
-/**
- * @brief Clear the history of previously detected advertised devices.
- * @return N/A
- */
-/*
-void BLEScan::clearAdvertisedDevices() {
- for (int i=0; i<m_vectorAvdertisedDevices.size(); i++) {
- delete m_vectorAvdertisedDevices[i];
- }
- m_vectorAvdertisedDevices.clear();
-} // clearAdvertisedDevices
-*/
-
-
/**
* @brief Handle GAP events related to scans.
* @param [in] event The event type for this event.
@@ -90,14 +78,7 @@ void BLEScan::gapEventHandler(
// ignore it.
BLEAddress advertisedAddress(param->scan_rst.bda);
bool found = false;
- /*
- for (int i=0; i<m_vectorAvdertisedDevices.size(); i++) {
- if (m_vectorAvdertisedDevices[i]->getAddress().equals(advertisedAddress)) {
- found = true;
- break;
- }
- }
- */
+
for (int i=0; i<m_scanResults.getCount(); i++) {
if (m_scanResults.getDevice(i).getAddress().equals(advertisedAddress)) {
found = true;
@@ -118,7 +99,6 @@ void BLEScan::gapEventHandler(
advertisedDevice.parseAdvertisement((uint8_t*)param->scan_rst.ble_adv);
advertisedDevice.setScan(this);
- //m_vectorAvdertisedDevices.push_back(pAdvertisedDevice);
if (m_pAdvertisedDeviceCallbacks) {
m_pAdvertisedDeviceCallbacks->onResult(advertisedDevice);
}
@@ -144,14 +124,6 @@ void BLEScan::gapEventHandler(
} // gapEventHandler
-/*
-void BLEScan::onResults() {
- ESP_LOGD(LOG_TAG, ">> onResults: default");
- ESP_LOGD(LOG_TAG, "<< onResults");
-} // onResults
-*/
-
-
/**
* @brief Should we perform an active or passive scan?
* The default is a passive scan. An active scan means that we will wish a scan response.
@@ -200,7 +172,7 @@ void BLEScan::setWindow(uint16_t windowMSecs) {
* @return N/A.
*/
BLEScanResults BLEScan::start(uint32_t duration) {
- ESP_LOGD(LOG_TAG, ">> start(%d)", duration);
+ ESP_LOGD(LOG_TAG, ">> start(duration=%d)", duration);
m_semaphoreScanEnd.take("start");
diff --git a/src/BLEScan.h b/src/BLEScan.h
index f9575ea..bc7f431 100644
--- a/src/BLEScan.h
+++ b/src/BLEScan.h
@@ -21,10 +21,19 @@ class BLEAdvertisedDeviceCallbacks;
class BLEClient;
class BLEScan;
+
+/**
+ * @brief The result of having performed a scan.
+ * When a scan completes, we have a set of found devices. Each device is described
+ * by a BLEAdvertisedDevice object. The number of items in the set is given by
+ * getCount(). We can retrieve a device by calling getDevice() passing in the
+ * index (starting at 0) of the desired device.
+ */
class BLEScanResults {
public:
- int getCount();
+ int getCount();
BLEAdvertisedDevice getDevice(uint32_t i);
+
private:
friend BLEScan;
std::vector<BLEAdvertisedDevice> m_vectorAdvertisedDevices;
@@ -39,7 +48,6 @@ class BLEScan {
public:
BLEScan();
- //virtual void onResults();
void setActiveScan(bool active);
void setAdvertisedDeviceCallbacks(BLEAdvertisedDeviceCallbacks* pAdvertisedDeviceCallbacks);
void setInterval(uint16_t intervalMSecs);
@@ -58,9 +66,8 @@ private:
esp_ble_scan_params_t m_scan_params;
BLEAdvertisedDeviceCallbacks* m_pAdvertisedDeviceCallbacks;
bool m_stopped;
- FreeRTOS::Semaphore m_semaphoreScanEnd = FreeRTOS::Semaphore("ScanEnd");
- //std::vector<BLEAdvertisedDevice*> m_vectorAvdertisedDevices;
- BLEScanResults m_scanResults;
+ FreeRTOS::Semaphore m_semaphoreScanEnd = FreeRTOS::Semaphore("ScanEnd");
+ BLEScanResults m_scanResults;
}; // BLEScan
#endif /* CONFIG_BT_ENABLED */
diff --git a/src/BLEServer.cpp b/src/BLEServer.cpp
index be9773d..4a8dfd5 100644
--- a/src/BLEServer.cpp
+++ b/src/BLEServer.cpp
@@ -35,17 +35,16 @@ BLEServer::BLEServer() {
m_gatts_if = -1;
m_connectedCount = 0;
m_connId = -1;
- BLEDevice::m_bleServer = this;
m_pServerCallbacks = nullptr;
- createApp(0);
+ //createApp(0);
} // BLEServer
void BLEServer::createApp(uint16_t appId) {
m_appId = appId;
registerApp();
-}
+} // createApp
/**
@@ -67,9 +66,10 @@ BLEService* BLEServer::createService(const char* uuid) {
* With a %BLE server, we can host one or more services. Invoking this function causes the creation of a definition
* of a new service. Every service must have a unique UUID.
* @param [in] uuid The UUID of the new service.
+ * @param [in] numHandles The maximum number of handles associated with this service.
* @return A reference to the new service object.
*/
-BLEService* BLEServer::createService(BLEUUID uuid) {
+BLEService* BLEServer::createService(BLEUUID uuid, uint32_t numHandles) {
ESP_LOGD(LOG_TAG, ">> createService - %s", uuid.toString().c_str());
m_semaphoreCreateEvt.take("createService");
@@ -81,7 +81,7 @@ BLEService* BLEServer::createService(BLEUUID uuid) {
return nullptr;
}
- BLEService* pService = new BLEService(uuid);
+ BLEService* pService = new BLEService(uuid, numHandles);
m_serviceMap.setByUUID(uuid, pService); // Save a reference to this service being on this server.
pService->executeCreate(this); // Perform the API calls to actually create the service.
@@ -169,7 +169,7 @@ void BLEServer::handleGATTServerEvent(
esp_ble_gatts_cb_param_t* param) {
ESP_LOGD(LOG_TAG, ">> handleGATTServerEvent: %s",
- BLEUtils::gattServerEventTypeToString(event).c_str());
+ BLEUtils::gattServerEventTypeToString(event).c_str());
// Invoke the handler for every Service we have.
m_serviceMap.handleGATTServerEvent(event, gatts_if, param);
@@ -199,7 +199,7 @@ void BLEServer::handleGATTServerEvent(
case ESP_GATTS_REG_EVT: {
m_gatts_if = gatts_if;
- m_semaphoreRegisterAppEvt.give();
+ m_semaphoreRegisterAppEvt.give(); // Unlock the mutex waiting for the registration of the app.
break;
} // ESP_GATTS_REG_EVT
@@ -350,4 +350,14 @@ void BLEServer::addCharacteristic(BLECharacteristic *characteristic, BLEService
}
*/
+void BLEServerCallbacks::onConnect(BLEServer* pServer) {
+ ESP_LOGD("BLEServerCallbacks", ">> onConnect(): Default");
+ ESP_LOGD("BLEServerCallbacks", "<< onConnect()");
+} // onConnect
+
+void BLEServerCallbacks::onDisconnect(BLEServer* pServer) {
+ ESP_LOGD("BLEServerCallbacks", ">> onDisconnect(): Default");
+ ESP_LOGD("BLEServerCallbacks", "<< onDisconnect()");
+} // onDisconnect
+
#endif // CONFIG_BT_ENABLED
diff --git a/src/BLEServer.h b/src/BLEServer.h
index c6307bc..64b34b4 100644
--- a/src/BLEServer.h
+++ b/src/BLEServer.h
@@ -51,18 +51,16 @@ private:
*/
class BLEServer {
public:
- BLEServer();
-
-
uint32_t getConnectedCount();
BLEService* createService(const char* uuid);
- BLEService* createService(BLEUUID uuid);
+ BLEService* createService(BLEUUID uuid, uint32_t numHandles=15);
BLEAdvertising* getAdvertising();
void setCallbacks(BLEServerCallbacks *pCallbacks);
void startAdvertising();
private:
+ BLEServer();
friend class BLEService;
friend class BLECharacteristic;
friend class BLEDevice;
diff --git a/src/BLEService.cpp b/src/BLEService.cpp
index ec16db8..9e7fa28 100644
--- a/src/BLEService.cpp
+++ b/src/BLEService.cpp
@@ -29,21 +29,24 @@ static const char* LOG_TAG = "BLEService"; // Tag for logging.
/**
* @brief Construct an instance of the BLEService
* @param [in] uuid The UUID of the service.
+ * @param [in] numHandles The maximum number of handles associated with the service.
*/
-BLEService::BLEService(const char* uuid) : BLEService(BLEUUID(uuid)) {
+BLEService::BLEService(const char* uuid, uint32_t numHandles) : BLEService(BLEUUID(uuid), numHandles) {
}
/**
* @brief Construct an instance of the BLEService
* @param [in] uuid The UUID of the service.
+ * @param [in] numHandles The maximum number of handles associated with the service.
*/
-BLEService::BLEService(BLEUUID uuid) {
- m_uuid = uuid;
- m_handle = NULL_HANDLE;
- m_pServer = nullptr;
+BLEService::BLEService(BLEUUID uuid, uint32_t numHandles) {
+ m_uuid = uuid;
+ m_handle = NULL_HANDLE;
+ m_pServer = nullptr;
//m_serializeMutex.setName("BLEService");
m_lastCreatedCharacteristic = nullptr;
+ m_numHandles = numHandles;
} // BLEService
@@ -54,16 +57,19 @@ BLEService::BLEService(BLEUUID uuid) {
* @return N/A.
*/
void BLEService::executeCreate(BLEServer *pServer) {
- ESP_LOGD(LOG_TAG, ">> executeCreate() - Creating service (esp_ble_gatts_create_service) service uuid: %s", getUUID().toString().c_str());
-
+ //ESP_LOGD(LOG_TAG, ">> executeCreate() - Creating service (esp_ble_gatts_create_service) service uuid: %s", getUUID().toString().c_str());
+ getUUID(); // Needed for a weird bug fix
m_pServer = pServer;
+ m_semaphoreCreateEvt.take("executeCreate"); // Take the mutex and release at event ESP_GATTS_CREATE_EVT
+
esp_gatt_srvc_id_t srvc_id;
srvc_id.id.inst_id = 0;
srvc_id.id.uuid = *m_uuid.getNative();
-
- m_semaphoreCreateEvt.take("executeCreate"); // Take the mutex and release at event ESP_GATTS_CREATE_EVT
-
- esp_err_t errRc = ::esp_ble_gatts_create_service(getServer()->getGattsIf(), &srvc_id, 10);
+ esp_err_t errRc = ::esp_ble_gatts_create_service(
+ getServer()->getGattsIf(),
+ &srvc_id,
+ m_numHandles // The maximum number of handles associated with the service.
+ );
if (errRc != ESP_OK) {
ESP_LOGE(LOG_TAG, "esp_ble_gatts_create_service: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
@@ -71,7 +77,6 @@ void BLEService::executeCreate(BLEServer *pServer) {
}
m_semaphoreCreateEvt.wait("executeCreate");
-
ESP_LOGD(LOG_TAG, "<< executeCreate");
} // executeCreate
@@ -87,18 +92,6 @@ void BLEService::dump() {
ESP_LOGD(LOG_TAG, "Characteristics:\n%s", m_characteristicMap.toString().c_str());
} // dump
-/*
-void BLEService::setService(esp_gatt_srvc_id_t srvc_id) {
- m_srvc_id = srvc_id;
-}
-*/
-
-/*
-esp_gatt_srvc_id_t BLEService::getService() {
- return m_srvc_id;
-}
-*/
-
/**
* @brief Get the UUID of the service.
@@ -184,7 +177,7 @@ void BLEService::addCharacteristic(BLECharacteristic* pCharacteristic) {
// to the map and then ask the service to add the characteristic at the BLE level (ESP-IDF).
//
ESP_LOGD(LOG_TAG, ">> addCharacteristic()");
- ESP_LOGD(LOG_TAG, "Adding characteristic (esp_ble_gatts_add_char): uuid=%s to service: %s",
+ ESP_LOGD(LOG_TAG, "Adding characteristic: uuid=%s to service: %s",
pCharacteristic->getUUID().toString().c_str(),
toString().c_str());
@@ -212,6 +205,7 @@ BLECharacteristic* BLEService::createCharacteristic(const char* uuid, uint32_t p
return createCharacteristic(BLEUUID(uuid), properties);
}
+
/**
* @brief Create a new BLE Characteristic associated with this service.
* @param [in] uuid - The UUID of the characteristic.
@@ -235,7 +229,7 @@ void BLEService::handleGATTServerEvent(
switch(event) {
- // ESP_GATTS_ADD_CHAR_EVT - Indicate that a characteristic was added to the service.
+ // ESP_GATTS_ADD_CHAR_EVT - Indicate that a characteristic was added to the service.
// add_char:
// - esp_gatt_status_t status
// - uint16_t attr_handle
@@ -251,18 +245,17 @@ void BLEService::handleGATTServerEvent(
ESP_LOGE(LOG_TAG, "Expected to find characteristic with UUID: %s, but didnt!",
BLEUUID(param->add_char.char_uuid).toString().c_str());
dump();
- m_semaphoreAddCharEvt.give();
break;
}
pCharacteristic->setHandle(param->add_char.attr_handle);
m_characteristicMap.setByHandle(param->add_char.attr_handle, pCharacteristic);
//ESP_LOGD(tag, "Characteristic map: %s", m_characteristicMap.toString().c_str());
- m_semaphoreAddCharEvt.give();
break;
} // Reached the correct service.
break;
} // ESP_GATTS_ADD_CHAR_EVT
+
// ESP_GATTS_START_EVT
//
// start:
@@ -301,6 +294,7 @@ void BLEService::handleGATTServerEvent(
} // Default
} // Switch
+ // Invoke the GATTS handler in each of the associated characteristics.
m_characteristicMap.handleGATTServerEvent(event, gatts_if, param);
} // handleGATTServerEvent
diff --git a/src/BLEService.h b/src/BLEService.h
index 86d0776..9a93aff 100644
--- a/src/BLEService.h
+++ b/src/BLEService.h
@@ -52,8 +52,8 @@ private:
*/
class BLEService {
public:
- BLEService(const char* uuid);
- BLEService(BLEUUID uuid);
+ BLEService(const char* uuid, uint32_t numHandles=10);
+ BLEService(BLEUUID uuid, uint32_t numHandles=10);
void addCharacteristic(BLECharacteristic* pCharacteristic);
BLECharacteristic* createCharacteristic(const char* uuid, uint32_t properties);
@@ -79,10 +79,10 @@ private:
BLECharacteristic* m_lastCreatedCharacteristic;
BLEServer* m_pServer;
//FreeRTOS::Semaphore m_serializeMutex;
- FreeRTOS::Semaphore m_semaphoreAddCharEvt = FreeRTOS::Semaphore("AddCharEvt");
- FreeRTOS::Semaphore m_semaphoreCreateEvt = FreeRTOS::Semaphore("CreateEvt");
- FreeRTOS::Semaphore m_semaphoreStartEvt = FreeRTOS::Semaphore("StartEvt");
+ FreeRTOS::Semaphore m_semaphoreCreateEvt = FreeRTOS::Semaphore("CreateEvt");
+ FreeRTOS::Semaphore m_semaphoreStartEvt = FreeRTOS::Semaphore("StartEvt");
BLEUUID m_uuid;
+ uint32_t m_numHandles;
uint16_t getHandle();
BLECharacteristic* getLastCreatedCharacteristic();
diff --git a/src/BLEUUID.cpp b/src/BLEUUID.cpp
index 9a4fe45..19da518 100644
--- a/src/BLEUUID.cpp
+++ b/src/BLEUUID.cpp
@@ -35,6 +35,7 @@ static const char* LOG_TAG = "BLEUUID";
* @param [in] size The number of bytes to copy
*/
static void memrcpy(uint8_t* target, uint8_t* source, uint32_t size) {
+ assert(size > 0);
target+=(size-1); // Point target to the last byte of the target data
while (size > 0) {
*target = *source;
@@ -65,15 +66,18 @@ static void memrcpy(uint8_t* target, uint8_t* source, uint32_t size) {
BLEUUID::BLEUUID(std::string value) {
m_valueSet = true;
if (value.length() == 2) {
- m_uuid.len = ESP_UUID_LEN_16;
+ m_uuid.len = ESP_UUID_LEN_16;
m_uuid.uuid.uuid16 = value[0] | (value[1] << 8);
- } else if (value.length() == 4) {
- m_uuid.len = ESP_UUID_LEN_32;
+ }
+ else if (value.length() == 4) {
+ m_uuid.len = ESP_UUID_LEN_32;
m_uuid.uuid.uuid32 = value[0] | (value[1] << 8) | (value[2] << 16) | (value[3] << 24);
- } else if (value.length() == 16) {
+ }
+ else if (value.length() == 16) {
m_uuid.len = ESP_UUID_LEN_128;
memrcpy(m_uuid.uuid.uuid128, (uint8_t*)value.data(), 16);
- } else if (value.length() == 36) {
+ }
+ else if (value.length() == 36) {
// If the length of the string is 36 bytes then we will assume it is a long hex string in
// UUID format.
m_uuid.len = ESP_UUID_LEN_128;
@@ -130,6 +134,7 @@ BLEUUID::BLEUUID(uint8_t* pData, size_t size, bool msbFirst) {
m_valueSet = true;
} // BLEUUID
+
/**
* @brief Create a UUID from the 16bit value.
*
@@ -166,11 +171,11 @@ BLEUUID::BLEUUID(esp_bt_uuid_t uuid) {
/**
- * @brief Create a UUID from the ESP32 esp_gatt_srvc_id_t.
+ * @brief Create a UUID from the ESP32 esp_gat_id_t.
*
- * @param [in] srvcId The data to create the UUID from.
+ * @param [in] gattId The data to create the UUID from.
*/
-BLEUUID::BLEUUID(esp_gatt_srvc_id_t srcvId) : BLEUUID(srcvId.id.uuid) {
+BLEUUID::BLEUUID(esp_gatt_id_t gattId) : BLEUUID(gattId.uuid) {
} // BLEUUID
@@ -277,50 +282,67 @@ BLEUUID BLEUUID::to128() {
} // to128
-//01234567 8901 2345 6789 012345678901
-//0000180d-0000-1000-8000-00805f9b34fb
-//0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+
/**
* @brief Get a string representation of the UUID.
*
+ * The format of a string is:
+ * 01234567 8901 2345 6789 012345678901
+ * 0000180d-0000-1000-8000-00805f9b34fb
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ *
* @return A string representation of the UUID.
*/
std::string BLEUUID::toString() {
- if (m_valueSet == false) {
+ if (m_valueSet == false) { // If we have no value, nothing to format.
return "<NULL>";
}
- if (m_uuid.len == ESP_UUID_LEN_16) {
- std::stringstream ss;
- ss << "0000" << std::hex << std::setfill('0') << std::setw(4) << m_uuid.uuid.uuid16 << "-0000-1000-8000-00805f9b34fb";
- return ss.str();
- }
-
- if (m_uuid.len == ESP_UUID_LEN_32) {
- std::stringstream ss;
- ss << std::hex << std::setfill('0') << std::setw(8) << m_uuid.uuid.uuid32 << "-0000-1000-8000-00805f9b34fb";
- return ss.str();
- }
-
+ // If the UUIDs are 16 or 32 bit, pad correctly.
std::stringstream ss;
+
+ if (m_uuid.len == ESP_UUID_LEN_16) { // If the UUID is 16bit, pad correctly.
+ ss << "0000" <<
+ std::hex <<
+ std::setfill('0') <<
+ std::setw(4) <<
+ m_uuid.uuid.uuid16 <<
+ "-0000-1000-8000-00805f9b34fb";
+ return ss.str(); // Return the string
+ } // End 16bit UUID
+
+ if (m_uuid.len == ESP_UUID_LEN_32) { // If the UUID is 32bit, pad correctly.
+ ss << std::hex <<
+ std::setfill('0') <<
+ std::setw(8) <<
+ m_uuid.uuid.uuid32 <<
+ "-0000-1000-8000-00805f9b34fb";
+ return ss.str(); // return the string
+ } // End 32bit UUID
+
+ // The UUID is not 16bit or 32bit which means that it is 128bit.
+ //
+ // UUID string format:
+ // AABBCCDD-EEFF-GGHH-IIJJ-KKLLMMNNOOPP
+ //
ss << std::hex << std::setfill('0') <<
- std::setw(2) << (int)m_uuid.uuid.uuid128[15] <<
- std::setw(2) << (int)m_uuid.uuid.uuid128[14] <<
- std::setw(2) << (int)m_uuid.uuid.uuid128[13] <<
- std::setw(2) << (int)m_uuid.uuid.uuid128[12] << "-" <<
- std::setw(2) << (int)m_uuid.uuid.uuid128[11] <<
- std::setw(2) << (int)m_uuid.uuid.uuid128[10] << "-" <<
- std::setw(2) << (int)m_uuid.uuid.uuid128[9] <<
- std::setw(2) << (int)m_uuid.uuid.uuid128[8] << "-" <<
- std::setw(2) << (int)m_uuid.uuid.uuid128[7] <<
- std::setw(2) << (int)m_uuid.uuid.uuid128[6] << "-" <<
- std::setw(2) << (int)m_uuid.uuid.uuid128[5] <<
- std::setw(2) << (int)m_uuid.uuid.uuid128[4] <<
- std::setw(2) << (int)m_uuid.uuid.uuid128[3] <<
- std::setw(2) << (int)m_uuid.uuid.uuid128[2] <<
- std::setw(2) << (int)m_uuid.uuid.uuid128[1] <<
- std::setw(2) << (int)m_uuid.uuid.uuid128[0];
+ std::setw(2) << (int)m_uuid.uuid.uuid128[15] <<
+ std::setw(2) << (int)m_uuid.uuid.uuid128[14] <<
+ std::setw(2) << (int)m_uuid.uuid.uuid128[13] <<
+ std::setw(2) << (int)m_uuid.uuid.uuid128[12] << "-" <<
+ std::setw(2) << (int)m_uuid.uuid.uuid128[11] <<
+ std::setw(2) << (int)m_uuid.uuid.uuid128[10] << "-" <<
+ std::setw(2) << (int)m_uuid.uuid.uuid128[9] <<
+ std::setw(2) << (int)m_uuid.uuid.uuid128[8] << "-" <<
+ std::setw(2) << (int)m_uuid.uuid.uuid128[7] <<
+ std::setw(2) << (int)m_uuid.uuid.uuid128[6] << "-" <<
+ std::setw(2) << (int)m_uuid.uuid.uuid128[5] <<
+ std::setw(2) << (int)m_uuid.uuid.uuid128[4] <<
+ std::setw(2) << (int)m_uuid.uuid.uuid128[3] <<
+ std::setw(2) << (int)m_uuid.uuid.uuid128[2] <<
+ std::setw(2) << (int)m_uuid.uuid.uuid128[1] <<
+ std::setw(2) << (int)m_uuid.uuid.uuid128[0];
return ss.str();
} // toString
#endif /* CONFIG_BT_ENABLED */
diff --git a/src/BLEUUID.h b/src/BLEUUID.h
index c364796..a11220b 100644
--- a/src/BLEUUID.h
+++ b/src/BLEUUID.h
@@ -22,7 +22,7 @@ public:
BLEUUID(uint32_t uuid);
BLEUUID(esp_bt_uuid_t uuid);
BLEUUID(uint8_t* pData, size_t size, bool msbFirst);
- BLEUUID(esp_gatt_srvc_id_t srcvId);
+ BLEUUID(esp_gatt_id_t gattId);
BLEUUID();
bool equals(BLEUUID uuid);
esp_bt_uuid_t* getNative();
@@ -30,8 +30,8 @@ public:
std::string toString();
private:
- esp_bt_uuid_t m_uuid;
- bool m_valueSet;
+ esp_bt_uuid_t m_uuid; // The underlying UUID structure that this class wraps.
+ bool m_valueSet; // Is there a value set for this instance.
}; // BLEUUID
#endif /* CONFIG_BT_ENABLED */
#endif /* COMPONENTS_CPP_UTILS_BLEUUID_H_ */
diff --git a/src/BLEUtils.cpp b/src/BLEUtils.cpp
index 468a7e1..a91bbcc 100644
--- a/src/BLEUtils.cpp
+++ b/src/BLEUtils.cpp
@@ -6,10 +6,10 @@
*/
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)
+#include "BLEAddress.h"
+#include "BLEClient.h"
#include "BLEUtils.h"
#include "BLEUUID.h"
-#include "BLEClient.h"
-#include "BLEAddress.h"
#include "GeneralUtils.h"
#include <freertos/FreeRTOS.h>
@@ -24,7 +24,7 @@
#include <sstream>
#include <iomanip>
-static const char* LOG_TAG = "BLEUtils";
+static const char* LOG_TAG = "BLEUtils"; // Tag for logging.
/*
static std::map<std::string, BLEClient *> g_addressMap;
@@ -32,13 +32,509 @@ static std::map<uint16_t, BLEClient *> g_connIdMap;
*/
typedef struct {
- uint32_t assignedNumber;
+ uint32_t assignedNumber;
+ std::string name;
+} member_t;
+
+static const member_t members_ids[] = {
+ {0xFE08, "Microsoft"},
+ {0xFE09, "Pillsy, Inc."},
+ {0xFE0A, "ruwido austria gmbh"},
+ {0xFE0B, "ruwido austria gmbh"},
+ {0xFE0C, "Procter & Gamble"},
+ {0xFE0D, "Procter & Gamble"},
+ {0xFE0E, "Setec Pty Ltd"},
+ {0xFE0F, "Philips Lighting B.V."},
+ {0xFE10, "Lapis Semiconductor Co., Ltd."},
+ {0xFE11, "GMC-I Messtechnik GmbH"},
+ {0xFE12, "M-Way Solutions GmbH"},
+ {0xFE13, "Apple Inc."},
+ {0xFE14, "Flextronics International USA Inc."},
+ {0xFE15, "Amazon Fulfillment Services, Inc."},
+ {0xFE16, "Footmarks, Inc."},
+ {0xFE17, "Telit Wireless Solutions GmbH"},
+ {0xFE18, "Runtime, Inc."},
+ {0xFE19, "Google Inc."},
+ {0xFE1A, "Tyto Life LLC"},
+ {0xFE1B, "Tyto Life LLC"},
+ {0xFE1C, "NetMedia, Inc."},
+ {0xFE1D, "Illuminati Instrument Corporation"},
+ {0xFE1E, "Smart Innovations Co., Ltd"},
+ {0xFE1F, "Garmin International, Inc."},
+ {0xFE20, "Emerson"},
+ {0xFE21, "Bose Corporation"},
+ {0xFE22, "Zoll Medical Corporation"},
+ {0xFE23, "Zoll Medical Corporation"},
+ {0xFE24, "August Home Inc"},
+ {0xFE25, "Apple, Inc. "},
+ {0xFE26, "Google Inc."},
+ {0xFE27, "Google Inc."},
+ {0xFE28, "Ayla Networks"},
+ {0xFE29, "Gibson Innovations"},
+ {0xFE2A, "DaisyWorks, Inc."},
+ {0xFE2B, "ITT Industries"},
+ {0xFE2C, "Google Inc."},
+ {0xFE2D, "SMART INNOVATION Co.,Ltd"},
+ {0xFE2E, "ERi,Inc."},
+ {0xFE2F, "CRESCO Wireless, Inc"},
+ {0xFE30, "Volkswagen AG"},
+ {0xFE31, "Volkswagen AG"},
+ {0xFE32, "Pro-Mark, Inc."},
+ {0xFE33, "CHIPOLO d.o.o."},
+ {0xFE34, "SmallLoop LLC"},
+ {0xFE35, "HUAWEI Technologies Co., Ltd"},
+ {0xFE36, "HUAWEI Technologies Co., Ltd"},
+ {0xFE37, "Spaceek LTD"},
+ {0xFE38, "Spaceek LTD"},
+ {0xFE39, "TTS Tooltechnic Systems AG & Co. KG"},
+ {0xFE3A, "TTS Tooltechnic Systems AG & Co. KG"},
+ {0xFE3B, "Dolby Laboratories"},
+ {0xFE3C, "Alibaba"},
+ {0xFE3D, "BD Medical"},
+ {0xFE3E, "BD Medical"},
+ {0xFE3F, "Friday Labs Limited"},
+ {0xFE40, "Inugo Systems Limited"},
+ {0xFE41, "Inugo Systems Limited"},
+ {0xFE42, "Nets A/S "},
+ {0xFE43, "Andreas Stihl AG & Co. KG"},
+ {0xFE44, "SK Telecom "},
+ {0xFE45, "Snapchat Inc"},
+ {0xFE46, "B&O Play A/S "},
+ {0xFE47, "General Motors"},
+ {0xFE48, "General Motors"},
+ {0xFE49, "SenionLab AB"},
+ {0xFE4A, "OMRON HEALTHCARE Co., Ltd."},
+ {0xFE4B, "Philips Lighting B.V."},
+ {0xFE4C, "Volkswagen AG"},
+ {0xFE4D, "Casambi Technologies Oy"},
+ {0xFE4E, "NTT docomo"},
+ {0xFE4F, "Molekule, Inc."},
+ {0xFE50, "Google Inc."},
+ {0xFE51, "SRAM"},
+ {0xFE52, "SetPoint Medical"},
+ {0xFE53, "3M"},
+ {0xFE54, "Motiv, Inc."},
+ {0xFE55, "Google Inc."},
+ {0xFE56, "Google Inc."},
+ {0xFE57, "Dotted Labs"},
+ {0xFE58, "Nordic Semiconductor ASA"},
+ {0xFE59, "Nordic Semiconductor ASA"},
+ {0xFE5A, "Chronologics Corporation"},
+ {0xFE5B, "GT-tronics HK Ltd"},
+ {0xFE5C, "million hunters GmbH"},
+ {0xFE5D, "Grundfos A/S"},
+ {0xFE5E, "Plastc Corporation"},
+ {0xFE5F, "Eyefi, Inc."},
+ {0xFE60, "Lierda Science & Technology Group Co., Ltd."},
+ {0xFE61, "Logitech International SA"},
+ {0xFE62, "Indagem Tech LLC"},
+ {0xFE63, "Connected Yard, Inc."},
+ {0xFE64, "Siemens AG"},
+ {0xFE65, "CHIPOLO d.o.o."},
+ {0xFE66, "Intel Corporation"},
+ {0xFE67, "Lab Sensor Solutions"},
+ {0xFE68, "Qualcomm Life Inc"},
+ {0xFE69, "Qualcomm Life Inc"},
+ {0xFE6A, "Kontakt Micro-Location Sp. z o.o."},
+ {0xFE6B, "TASER International, Inc."},
+ {0xFE6C, "TASER International, Inc."},
+ {0xFE6D, "The University of Tokyo"},
+ {0xFE6E, "The University of Tokyo"},
+ {0xFE6F, "LINE Corporation"},
+ {0xFE70, "Beijing Jingdong Century Trading Co., Ltd."},
+ {0xFE71, "Plume Design Inc"},
+ {0xFE72, "St. Jude Medical, Inc."},
+ {0xFE73, "St. Jude Medical, Inc."},
+ {0xFE74, "unwire"},
+ {0xFE75, "TangoMe"},
+ {0xFE76, "TangoMe"},
+ {0xFE77, "Hewlett-Packard Company"},
+ {0xFE78, "Hewlett-Packard Company"},
+ {0xFE79, "Zebra Technologies"},
+ {0xFE7A, "Bragi GmbH"},
+ {0xFE7B, "Orion Labs, Inc."},
+ {0xFE7C, "Telit Wireless Solutions (Formerly Stollmann E+V GmbH)"},
+ {0xFE7D, "Aterica Health Inc."},
+ {0xFE7E, "Awear Solutions Ltd"},
+ {0xFE7F, "Doppler Lab"},
+ {0xFE80, "Doppler Lab"},
+ {0xFE81, "Medtronic Inc."},
+ {0xFE82, "Medtronic Inc."},
+ {0xFE83, "Blue Bite"},
+ {0xFE84, "RF Digital Corp"},
+ {0xFE85, "RF Digital Corp"},
+ {0xFE86, "HUAWEI Technologies Co., Ltd. ( )"},
+ {0xFE87, "Qingdao Yeelink Information Technology Co., Ltd. ( )"},
+ {0xFE88, "SALTO SYSTEMS S.L."},
+ {0xFE89, "B&O Play A/S"},
+ {0xFE8A, "Apple, Inc."},
+ {0xFE8B, "Apple, Inc."},
+ {0xFE8C, "TRON Forum"},
+ {0xFE8D, "Interaxon Inc."},
+ {0xFE8E, "ARM Ltd"},
+ {0xFE8F, "CSR"},
+ {0xFE90, "JUMA"},
+ {0xFE91, "Shanghai Imilab Technology Co.,Ltd"},
+ {0xFE92, "Jarden Safety & Security"},
+ {0xFE93, "OttoQ Inc."},
+ {0xFE94, "OttoQ Inc."},
+ {0xFE95, "Xiaomi Inc."},
+ {0xFE96, "Tesla Motor Inc."},
+ {0xFE97, "Tesla Motor Inc."},
+ {0xFE98, "Currant, Inc."},
+ {0xFE99, "Currant, Inc."},
+ {0xFE9A, "Estimote"},
+ {0xFE9B, "Samsara Networks, Inc"},
+ {0xFE9C, "GSI Laboratories, Inc."},
+ {0xFE9D, "Mobiquity Networks Inc"},
+ {0xFE9E, "Dialog Semiconductor B.V."},
+ {0xFE9F, "Google Inc."},
+ {0xFEA0, "Google Inc."},
+ {0xFEA1, "Intrepid Control Systems, Inc."},
+ {0xFEA2, "Intrepid Control Systems, Inc."},
+ {0xFEA3, "ITT Industries"},
+ {0xFEA4, "Paxton Access Ltd"},
+ {0xFEA5, "GoPro, Inc."},
+ {0xFEA6, "GoPro, Inc."},
+ {0xFEA7, "UTC Fire and Security"},
+ {0xFEA8, "Savant Systems LLC"},
+ {0xFEA9, "Savant Systems LLC"},
+ {0xFEAA, "Google Inc."},
+ {0xFEAB, "Nokia Corporation"},
+ {0xFEAC, "Nokia Corporation"},
+ {0xFEAD, "Nokia Corporation"},
+ {0xFEAE, "Nokia Corporation"},
+ {0xFEAF, "Nest Labs Inc."},
+ {0xFEB0, "Nest Labs Inc."},
+ {0xFEB1, "Electronics Tomorrow Limited"},
+ {0xFEB2, "Microsoft Corporation"},
+ {0xFEB3, "Taobao"},
+ {0xFEB4, "WiSilica Inc."},
+ {0xFEB5, "WiSilica Inc."},
+ {0xFEB6, "Vencer Co, Ltd"},
+ {0xFEB7, "Facebook, Inc."},
+ {0xFEB8, "Facebook, Inc."},
+ {0xFEB9, "LG Electronics"},
+ {0xFEBA, "Tencent Holdings Limited"},
+ {0xFEBB, "adafruit industries"},
+ {0xFEBC, "Dexcom, Inc. "},
+ {0xFEBD, "Clover Network, Inc."},
+ {0xFEBE, "Bose Corporation"},
+ {0xFEBF, "Nod, Inc."},
+ {0xFEC0, "KDDI Corporation"},
+ {0xFEC1, "KDDI Corporation"},
+ {0xFEC2, "Blue Spark Technologies, Inc."},
+ {0xFEC3, "360fly, Inc."},
+ {0xFEC4, "PLUS Location Systems"},
+ {0xFEC5, "Realtek Semiconductor Corp."},
+ {0xFEC6, "Kocomojo, LLC"},
+ {0xFEC7, "Apple, Inc."},
+ {0xFEC8, "Apple, Inc."},
+ {0xFEC9, "Apple, Inc."},
+ {0xFECA, "Apple, Inc."},
+ {0xFECB, "Apple, Inc."},
+ {0xFECC, "Apple, Inc."},
+ {0xFECD, "Apple, Inc."},
+ {0xFECE, "Apple, Inc."},
+ {0xFECF, "Apple, Inc."},
+ {0xFED0, "Apple, Inc."},
+ {0xFED1, "Apple, Inc."},
+ {0xFED2, "Apple, Inc."},
+ {0xFED3, "Apple, Inc."},
+ {0xFED4, "Apple, Inc."},
+ {0xFED5, "Plantronics Inc."},
+ {0xFED6, "Broadcom Corporation"},
+ {0xFED7, "Broadcom Corporation"},
+ {0xFED8, "Google Inc."},
+ {0xFED9, "Pebble Technology Corporation"},
+ {0xFEDA, "ISSC Technologies Corporation"},
+ {0xFEDB, "Perka, Inc."},
+ {0xFEDC, "Jawbone"},
+ {0xFEDD, "Jawbone"},
+ {0xFEDE, "Coin, Inc."},
+ {0xFEDF, "Design SHIFT"},
+ {0xFEE0, "Anhui Huami Information Technology Co."},
+ {0xFEE1, "Anhui Huami Information Technology Co."},
+ {0xFEE2, "Anki, Inc."},
+ {0xFEE3, "Anki, Inc."},
+ {0xFEE4, "Nordic Semiconductor ASA"},
+ {0xFEE5, "Nordic Semiconductor ASA"},
+ {0xFEE6, "Silvair, Inc."},
+ {0xFEE7, "Tencent Holdings Limited"},
+ {0xFEE8, "Quintic Corp."},
+ {0xFEE9, "Quintic Corp."},
+ {0xFEEA, "Swirl Networks, Inc."},
+ {0xFEEB, "Swirl Networks, Inc."},
+ {0xFEEC, "Tile, Inc."},
+ {0xFEED, "Tile, Inc."},
+ {0xFEEE, "Polar Electro Oy"},
+ {0xFEEF, "Polar Electro Oy"},
+ {0xFEF0, "Intel"},
+ {0xFEF1, "CSR"},
+ {0xFEF2, "CSR"},
+ {0xFEF3, "Google Inc."},
+ {0xFEF4, "Google Inc."},
+ {0xFEF5, "Dialog Semiconductor GmbH"},
+ {0xFEF6, "Wicentric, Inc."},
+ {0xFEF7, "Aplix Corporation"},
+ {0xFEF8, "Aplix Corporation"},
+ {0xFEF9, "PayPal, Inc."},
+ {0xFEFA, "PayPal, Inc."},
+ {0xFEFB, "Telit Wireless Solutions (Formerly Stollmann E+V GmbH)"},
+ {0xFEFC, "Gimbal, Inc."},
+ {0xFEFD, "Gimbal, Inc."},
+ {0xFEFE, "GN ReSound A/S"},
+ {0xFEFF, "GN Netcom"},
+ {0xFFFF, "Reserved"}, /*for testing purposes only*/
+ {0, "" }
+};
+
+typedef struct {
+ uint32_t assignedNumber;
+ std::string name;
+} gattdescriptor_t;
+
+static const gattdescriptor_t g_descriptor_ids[] = {
+ {0x2905,"Characteristic Aggregate Format"},
+ {0x2900,"Characteristic Extended Properties"},
+ {0x2904,"Characteristic Presentation Format"},
+ {0x2901,"Characteristic User Description"},
+ {0x2902,"Client Characteristic Configuration"},
+ {0x290B,"Environmental Sensing Configuration"},
+ {0x290C,"Environmental Sensing Measurement"},
+ {0x290D,"Environmental Sensing Trigger Setting"},
+ {0x2907,"External Report Reference"},
+ {0x2909,"Number of Digitals"},
+ {0x2908,"Report Reference"},
+ {0x2903,"Server Characteristic Configuration"},
+ {0x290E,"Time Trigger Setting"},
+ {0x2906,"Valid Range"},
+ {0x290A,"Value Trigger Setting"},
+ { 0, "" }
+};
+
+typedef struct {
+ uint32_t assignedNumber;
std::string name;
} characteristicMap_t;
-static characteristicMap_t g_characteristicsMappings[] = {
- {0x2a00, "Device Name"},
- {0x2a01, "Appearance"},
+static const characteristicMap_t g_characteristicsMappings[] = {
+ {0x2A7E,"Aerobic Heart Rate Lower Limit"},
+ {0x2A84,"Aerobic Heart Rate Upper Limit"},
+ {0x2A7F,"Aerobic Threshold"},
+ {0x2A80,"Age"},
+ {0x2A5A,"Aggregate"},
+ {0x2A43,"Alert Category ID"},
+ {0x2A42,"Alert Category ID Bit Mask"},
+ {0x2A06,"Alert Level"},
+ {0x2A44,"Alert Notification Control Point"},
+ {0x2A3F,"Alert Status"},
+ {0x2AB3,"Altitude"},
+ {0x2A81,"Anaerobic Heart Rate Lower Limit"},
+ {0x2A82,"Anaerobic Heart Rate Upper Limit"},
+ {0x2A83,"Anaerobic Threshold"},
+ {0x2A58,"Analog"},
+ {0x2A59,"Analog Output"},
+ {0x2A73,"Apparent Wind Direction"},
+ {0x2A72,"Apparent Wind Speed"},
+ {0x2A01,"Appearance"},
+ {0x2AA3,"Barometric Pressure Trend"},
+ {0x2A19,"Battery Level"},
+ {0x2A1B,"Battery Level State"},
+ {0x2A1A,"Battery Power State"},
+ {0x2A49,"Blood Pressure Feature"},
+ {0x2A35,"Blood Pressure Measurement"},
+ {0x2A9B,"Body Composition Feature"},
+ {0x2A9C,"Body Composition Measurement"},
+ {0x2A38,"Body Sensor Location"},
+ {0x2AA4,"Bond Management Control Point"},
+ {0x2AA5,"Bond Management Features"},
+ {0x2A22,"Boot Keyboard Input Report"},
+ {0x2A32,"Boot Keyboard Output Report"},
+ {0x2A33,"Boot Mouse Input Report"},
+ {0x2AA6,"Central Address Resolution"},
+ {0x2AA8,"CGM Feature"},
+ {0x2AA7,"CGM Measurement"},
+ {0x2AAB,"CGM Session Run Time"},
+ {0x2AAA,"CGM Session Start Time"},
+ {0x2AAC,"CGM Specific Ops Control Point"},
+ {0x2AA9,"CGM Status"},
+ {0x2ACE,"Cross Trainer Data"},
+ {0x2A5C,"CSC Feature"},
+ {0x2A5B,"CSC Measurement"},
+ {0x2A2B,"Current Time"},
+ {0x2A66,"Cycling Power Control Point"},
+ {0x2A66,"Cycling Power Control Point"},
+ {0x2A65,"Cycling Power Feature"},
+ {0x2A65,"Cycling Power Feature"},
+ {0x2A63,"Cycling Power Measurement"},
+ {0x2A64,"Cycling Power Vector"},
+ {0x2A99,"Database Change Increment"},
+ {0x2A85,"Date of Birth"},
+ {0x2A86,"Date of Threshold Assessment"},
+ {0x2A08,"Date Time"},
+ {0x2A0A,"Day Date Time"},
+ {0x2A09,"Day of Week"},
+ {0x2A7D,"Descriptor Value Changed"},
+ {0x2A00,"Device Name"},
+ {0x2A7B,"Dew Point"},
+ {0x2A56,"Digital"},
+ {0x2A57,"Digital Output"},
+ {0x2A0D,"DST Offset"},
+ {0x2A6C,"Elevation"},
+ {0x2A87,"Email Address"},
+ {0x2A0B,"Exact Time 100"},
+ {0x2A0C,"Exact Time 256"},
+ {0x2A88,"Fat Burn Heart Rate Lower Limit"},
+ {0x2A89,"Fat Burn Heart Rate Upper Limit"},
+ {0x2A26,"Firmware Revision String"},
+ {0x2A8A,"First Name"},
+ {0x2AD9,"Fitness Machine Control Point"},
+ {0x2ACC,"Fitness Machine Feature"},
+ {0x2ADA,"Fitness Machine Status"},
+ {0x2A8B,"Five Zone Heart Rate Limits"},
+ {0x2AB2,"Floor Number"},
+ {0x2A8C,"Gender"},
+ {0x2A51,"Glucose Feature"},
+ {0x2A18,"Glucose Measurement"},
+ {0x2A34,"Glucose Measurement Context"},
+ {0x2A74,"Gust Factor"},
+ {0x2A27,"Hardware Revision String"},
+ {0x2A39,"Heart Rate Control Point"},
+ {0x2A8D,"Heart Rate Max"},
+ {0x2A37,"Heart Rate Measurement"},
+ {0x2A7A,"Heat Index"},
+ {0x2A8E,"Height"},
+ {0x2A4C,"HID Control Point"},
+ {0x2A4A,"HID Information"},
+ {0x2A8F,"Hip Circumference"},
+ {0x2ABA,"HTTP Control Point"},
+ {0x2AB9,"HTTP Entity Body"},
+ {0x2AB7,"HTTP Headers"},
+ {0x2AB8,"HTTP Status Code"},
+ {0x2ABB,"HTTPS Security"},
+ {0x2A6F,"Humidity"},
+ {0x2A2A,"IEEE 11073-20601 Regulatory Certification Data List"},
+ {0x2AD2,"Indoor Bike Data"},
+ {0x2AAD,"Indoor Positioning Configuration"},
+ {0x2A36,"Intermediate Cuff Pressure"},
+ {0x2A1E,"Intermediate Temperature"},
+ {0x2A77,"Irradiance"},
+ {0x2AA2,"Language"},
+ {0x2A90,"Last Name"},
+ {0x2AAE,"Latitude"},
+ {0x2A6B,"LN Control Point"},
+ {0x2A6A,"LN Feature"},
+ {0x2AB1,"Local East Coordinate"},
+ {0x2AB0,"Local North Coordinate"},
+ {0x2A0F,"Local Time Information"},
+ {0x2A67,"Location and Speed Characteristic"},
+ {0x2AB5,"Location Name"},
+ {0x2AAF,"Longitude"},
+ {0x2A2C,"Magnetic Declination"},
+ {0x2AA0,"Magnetic Flux Density - 2D"},
+ {0x2AA1,"Magnetic Flux Density - 3D"},
+ {0x2A29,"Manufacturer Name String"},
+ {0x2A91,"Maximum Recommended Heart Rate"},
+ {0x2A21,"Measurement Interval"},
+ {0x2A24,"Model Number String"},
+ {0x2A68,"Navigation"},
+ {0x2A3E,"Network Availability"},
+ {0x2A46,"New Alert"},
+ {0x2AC5,"Object Action Control Point"},
+ {0x2AC8,"Object Changed"},
+ {0x2AC1,"Object First-Created"},
+ {0x2AC3,"Object ID"},
+ {0x2AC2,"Object Last-Modified"},
+ {0x2AC6,"Object List Control Point"},
+ {0x2AC7,"Object List Filter"},
+ {0x2ABE,"Object Name"},
+ {0x2AC4,"Object Properties"},
+ {0x2AC0,"Object Size"},
+ {0x2ABF,"Object Type"},
+ {0x2ABD,"OTS Feature"},
+ {0x2A04,"Peripheral Preferred Connection Parameters"},
+ {0x2A02,"Peripheral Privacy Flag"},
+ {0x2A5F,"PLX Continuous Measurement Characteristic"},
+ {0x2A60,"PLX Features"},
+ {0x2A5E,"PLX Spot-Check Measurement"},
+ {0x2A50,"PnP ID"},
+ {0x2A75,"Pollen Concentration"},
+ {0x2A2F,"Position 2D"},
+ {0x2A30,"Position 3D"},
+ {0x2A69,"Position Quality"},
+ {0x2A6D,"Pressure"},
+ {0x2A4E,"Protocol Mode"},
+ {0x2A62,"Pulse Oximetry Control Point"},
+ {0x2A60,"Pulse Oximetry Pulsatile Event Characteristic"},
+ {0x2A78,"Rainfall"},
+ {0x2A03,"Reconnection Address"},
+ {0x2A52,"Record Access Control Point"},
+ {0x2A14,"Reference Time Information"},
+ {0x2A3A,"Removable"},
+ {0x2A4D,"Report"},
+ {0x2A4B,"Report Map"},
+ {0x2AC9,"Resolvable Private Address Only"},
+ {0x2A92,"Resting Heart Rate"},
+ {0x2A40,"Ringer Control point"},
+ {0x2A41,"Ringer Setting"},
+ {0x2AD1,"Rower Data"},
+ {0x2A54,"RSC Feature"},
+ {0x2A53,"RSC Measurement"},
+ {0x2A55,"SC Control Point"},
+ {0x2A4F,"Scan Interval Window"},
+ {0x2A31,"Scan Refresh"},
+ {0x2A3C,"Scientific Temperature Celsius"},
+ {0x2A10,"Secondary Time Zone"},
+ {0x2A5D,"Sensor Location"},
+ {0x2A25,"Serial Number String"},
+ {0x2A05,"Service Changed"},
+ {0x2A3B,"Service Required"},
+ {0x2A28,"Software Revision String"},
+ {0x2A93,"Sport Type for Aerobic and Anaerobic Thresholds"},
+ {0x2AD0,"Stair Climber Data"},
+ {0x2ACF,"Step Climber Data"},
+ {0x2A3D,"String"},
+ {0x2AD7,"Supported Heart Rate Range"},
+ {0x2AD5,"Supported Inclination Range"},
+ {0x2A47,"Supported New Alert Category"},
+ {0x2AD8,"Supported Power Range"},
+ {0x2AD6,"Supported Resistance Level Range"},
+ {0x2AD4,"Supported Speed Range"},
+ {0x2A48,"Supported Unread Alert Category"},
+ {0x2A23,"System ID"},
+ {0x2ABC,"TDS Control Point"},
+ {0x2A6E,"Temperature"},
+ {0x2A1F,"Temperature Celsius"},
+ {0x2A20,"Temperature Fahrenheit"},
+ {0x2A1C,"Temperature Measurement"},
+ {0x2A1D,"Temperature Type"},
+ {0x2A94,"Three Zone Heart Rate Limits"},
+ {0x2A12,"Time Accuracy"},
+ {0x2A15,"Time Broadcast"},
+ {0x2A13,"Time Source"},
+ {0x2A16,"Time Update Control Point"},
+ {0x2A17,"Time Update State"},
+ {0x2A11,"Time with DST"},
+ {0x2A0E,"Time Zone"},
+ {0x2AD3,"Training Status"},
+ {0x2ACD,"Treadmill Data"},
+ {0x2A71,"True Wind Direction"},
+ {0x2A70,"True Wind Speed"},
+ {0x2A95,"Two Zone Heart Rate Limit"},
+ {0x2A07,"Tx Power Level"},
+ {0x2AB4,"Uncertainty"},
+ {0x2A45,"Unread Alert Status"},
+ {0x2AB6,"URI"},
+ {0x2A9F,"User Control Point"},
+ {0x2A9A,"User Index"},
+ {0x2A76,"UV Index"},
+ {0x2A96,"VO2 Max"},
+ {0x2A97,"Waist Circumference"},
+ {0x2A98,"Weight"},
+ {0x2A9D,"Weight Measurement"},
+ {0x2A9E,"Weight Scale Feature"},
+ {0x2A79,"Wind Chill"},
{0, ""}
};
@@ -48,7 +544,7 @@ static characteristicMap_t g_characteristicsMappings[] = {
typedef struct {
std::string name;
std::string type;
- uint32_t assignedNumber;
+ uint32_t assignedNumber;
} gattService_t;
@@ -94,6 +590,7 @@ static const gattService_t g_gattServices[] = {
{"", "", 0 }
};
+
/**
* @brief Convert characteristic properties into a string representation.
* @param [in] prop Characteristic properties.
@@ -137,7 +634,7 @@ 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 addr_t";
+ return "Unknown esp_ble_addr_type_t";
}
} // addressTypeToString
@@ -232,13 +729,12 @@ esp_gatt_srvc_id_t BLEUtils::buildGattSrvcId(esp_gatt_id_t gattId,
* @param [in] length The length of the data to convert.
* @return A pointer to the formatted buffer.
*/
-char *BLEUtils::buildHexData(uint8_t *target, uint8_t *source, uint8_t length) {
+char* BLEUtils::buildHexData(uint8_t *target, uint8_t *source, uint8_t length) {
// Guard against too much data.
if (length > 100) {
length = 100;
}
-
if (target == nullptr) {
target = (uint8_t *)malloc(length * 2 + 1);
if (target == nullptr) {
@@ -349,12 +845,12 @@ std::string BLEUtils::gattClientEventTypeToString(esp_gattc_cb_event_t eventType
return "ESP_GATTC_ENC_CMPL_CB_EVT";
case ESP_GATTC_EXEC_EVT:
return "ESP_GATTC_EXEC_EVT";
- case ESP_GATTC_GET_CHAR_EVT:
- return "ESP_GATTC_GET_CHAR_EVT";
- case ESP_GATTC_GET_DESCR_EVT:
- return "ESP_GATTC_GET_DESCR_EVT";
- case ESP_GATTC_GET_INCL_SRVC_EVT:
- return "ESP_GATTC_GET_INCL_SRVC_EVT";
+ //case ESP_GATTC_GET_CHAR_EVT:
+// return "ESP_GATTC_GET_CHAR_EVT";
+ //case ESP_GATTC_GET_DESCR_EVT:
+// return "ESP_GATTC_GET_DESCR_EVT";
+ //case ESP_GATTC_GET_INCL_SRVC_EVT:
+// return "ESP_GATTC_GET_INCL_SRVC_EVT";
case ESP_GATTC_MULT_ADV_DATA_EVT:
return "ESP_GATTC_MULT_ADV_DATA_EVT";
case ESP_GATTC_MULT_ADV_DIS_EVT:
@@ -487,24 +983,41 @@ const char* BLEUtils::devTypeToString(esp_bt_dev_type_t type) {
* @brief Dump the GAP event to the log.
*/
void BLEUtils::dumpGapEvent(
- esp_gap_ble_cb_event_t event,
- esp_ble_gap_cb_param_t *param) {
+ esp_gap_ble_cb_event_t event,
+ esp_ble_gap_cb_param_t* param) {
ESP_LOGD(LOG_TAG, "Received a GAP event: %s", gapEventToString(event));
switch(event) {
//
// ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT
+ // adv_data_cmpl
+ // - esp_bt_status_t
//
case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT: {
- ESP_LOGD(LOG_TAG, "[status: %d]", param->scan_rsp_data_cmpl.status);
+ ESP_LOGD(LOG_TAG, "[status: %d]", param->adv_data_cmpl.status);
break;
} // ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT
//
+ // ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT
+ //
+ // adv_data_raw_cmpl
+ // - esp_bt_status_t status
+ //
+ case ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT: {
+ ESP_LOGD(LOG_TAG, "[status: %d]", param->adv_data_raw_cmpl.status);
+ break;
+ } // ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT
+
+
+ //
// ESP_GAP_BLE_ADV_START_COMPLETE_EVT
//
+ // adv_start_cmpl
+ // - esp_bt_status_t status
+ //
case ESP_GAP_BLE_ADV_START_COMPLETE_EVT: {
- ESP_LOGD(LOG_TAG, "[status: %d]", param->scan_start_cmpl.status);
+ ESP_LOGD(LOG_TAG, "[status: %d]", param->adv_start_cmpl.status);
break;
} // ESP_GAP_BLE_ADV_START_COMPLETE_EVT
@@ -512,8 +1025,11 @@ void BLEUtils::dumpGapEvent(
//
// ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT
//
+ // adv_stop_cmpl
+ // - esp_bt_status_t status
+ //
case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT: {
- ESP_LOGD(LOG_TAG, "[status: %d]", param->scan_stop_cmpl.status);
+ ESP_LOGD(LOG_TAG, "[status: %d]", param->adv_stop_cmpl.status);
break;
} // ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT
@@ -521,6 +1037,15 @@ void BLEUtils::dumpGapEvent(
//
// ESP_GAP_BLE_AUTH_CMPL_EVT
//
+ // auth_cmpl
+ // - esp_bd_addr_t bd_addr
+ // - bool key_present
+ // - esp_link_key key
+ // - bool success
+ // - uint8_t fail_reason
+ // - esp_bd_addr_type_t addr_type
+ // - esp_bt_dev_type_t dev_type
+ //
case ESP_GAP_BLE_AUTH_CMPL_EVT: {
ESP_LOGD(LOG_TAG, "[bd_addr: %s, key_present: %d, key: ***, key_type: %d, success: %d, fail_reason: %d, addr_type: ***, dev_type: %s]",
BLEAddress(param->ble_security.auth_cmpl.bd_addr).toString().c_str(),
@@ -535,6 +1060,18 @@ void BLEUtils::dumpGapEvent(
//
+ // ESP_GAP_BLE_CLEAR_BOND_DEV_COMPLETE_EVT
+ //
+ // clear_bond_dev_cmpl
+ // - esp_bt_status_t status
+ //
+ case ESP_GAP_BLE_CLEAR_BOND_DEV_COMPLETE_EVT: {
+ ESP_LOGD(LOG_TAG, "[status: %d]", param->clear_bond_dev_cmpl.status);
+ break;
+ } // ESP_GAP_BLE_CLEAR_BOND_DEV_COMPLETE_EVT
+
+
+ //
// ESP_GAP_BLE_LOCAL_IR_EVT
//
case ESP_GAP_BLE_LOCAL_IR_EVT: {
@@ -562,13 +1099,35 @@ void BLEUtils::dumpGapEvent(
//
+ // 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: {
+ ESP_LOGD(LOG_TAG, "[status: %d, rssi: %d, remote_addr: %s]",
+ param->read_rssi_cmpl.status,
+ param->read_rssi_cmpl.rssi,
+ BLEAddress(param->read_rssi_cmpl.remote_addr).toString().c_str()
+ );
+ break;
+ } // ESP_GAP_BLE_READ_RSSI_COMPLETE_EVT
+
+
+ //
// ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT
//
+ // scan_param_cmpl.
+ // - esp_bt_status_t status
+ //
case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT: {
ESP_LOGD(LOG_TAG, "[status: %d]", param->scan_param_cmpl.status);
break;
} // ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT
+
//
// ESP_GAP_BLE_SCAN_RESULT_EVT
//
@@ -582,6 +1141,7 @@ void BLEUtils::dumpGapEvent(
// - ble_adv
// - flag
// - num_resps
+ //
case ESP_GAP_BLE_SCAN_RESULT_EVT: {
switch(param->scan_rst.search_evt) {
case ESP_GAP_SEARCH_INQ_RES_EVT: {
@@ -610,31 +1170,75 @@ void BLEUtils::dumpGapEvent(
//
- // ESP_GAP_BLE_SCAN_START_COMPLETE_EVT
+ // ESP_GAP_BLE_SCAN_RSP_DATA_SET_COMPLETE_EVT
//
- case ESP_GAP_BLE_SCAN_START_COMPLETE_EVT: {
- ESP_LOGD(LOG_TAG, "[status: %d]", param->scan_start_cmpl.status);
+ // scan_rsp_data_cmpl
+ // - esp_bt_status_t status
+ //
+ case ESP_GAP_BLE_SCAN_RSP_DATA_SET_COMPLETE_EVT: {
+ ESP_LOGD(LOG_TAG, "[status: %d]", param->scan_rsp_data_cmpl.status);
break;
- } // ESP_GAP_BLE_SCAN_START_COMPLETE_EVT
+ } // ESP_GAP_BLE_SCAN_RSP_DATA_SET_COMPLETE_EVT
//
- // ESP_GAP_BLE_SEC_REQ_EVT
+ // ESP_GAP_BLE_SCAN_START_COMPLETE_EVT
//
- case ESP_GAP_BLE_SEC_REQ_EVT: {
- ESP_LOGD(LOG_TAG, "[bd_addr: %s]", BLEAddress(param->ble_security.ble_req.bd_addr).toString().c_str());
+ // scan_start_cmpl
+ // - esp_bt_status_t status
+ case ESP_GAP_BLE_SCAN_START_COMPLETE_EVT: {
+ ESP_LOGD(LOG_TAG, "[status: %d]", param->scan_start_cmpl.status);
break;
- } // ESP_GAP_BLE_SEC_REQ_EVT
+ } // ESP_GAP_BLE_SCAN_START_COMPLETE_EVT
//
// ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT
//
+ // scan_stop_cmpl
+ // - esp_bt_status_t status
+ //
case ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT: {
ESP_LOGD(LOG_TAG, "[status: %d]", param->scan_stop_cmpl.status);
break;
} // ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT
+
+ //
+ // ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT
+ //
+ // update_conn_params
+ // - esp_bt_status_t status
+ // - esp_bd_addr_t bda
+ // - uint16_t min_int
+ // - uint16_t max_int
+ // - uint16_t latency
+ // - uint16_t conn_int
+ // - uint16_t timeout
+ //
+ case ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT: {
+ ESP_LOGD(LOG_TAG, "[status: %d, bd_addr: %s, min_int: %d, max_int: %d, latency: %d, conn_int: %d, timeout: %d]",
+ param->update_conn_params.status,
+ BLEAddress(param->update_conn_params.bda).toString().c_str(),
+ param->update_conn_params.min_int,
+ param->update_conn_params.max_int,
+ param->update_conn_params.latency,
+ param->update_conn_params.conn_int,
+ param->update_conn_params.timeout
+ );
+ break;
+ } // ESP_GAP_BLE_SCAN_UPDATE_CONN_PARAMS_EVT
+
+
+ //
+ // ESP_GAP_BLE_SEC_REQ_EVT
+ //
+ case ESP_GAP_BLE_SEC_REQ_EVT: {
+ ESP_LOGD(LOG_TAG, "[bd_addr: %s]", BLEAddress(param->ble_security.ble_req.bd_addr).toString().c_str());
+ break;
+ } // ESP_GAP_BLE_SEC_REQ_EVT
+
+
default: {
ESP_LOGD(LOG_TAG, "*** dumpGapEvent: Logger not coded ***");
break;
@@ -650,9 +1254,9 @@ void BLEUtils::dumpGapEvent(
* @param [in] evtParam The data associated with the event.
*/
void BLEUtils::dumpGattClientEvent(
- esp_gattc_cb_event_t event,
- esp_gatt_if_t gattc_if,
- esp_ble_gattc_cb_param_t *evtParam) {
+ esp_gattc_cb_event_t event,
+ esp_gatt_if_t gattc_if,
+ esp_ble_gattc_cb_param_t* evtParam) {
//esp_ble_gattc_cb_param_t *evtParam = (esp_ble_gattc_cb_param_t *)param;
ESP_LOGD(LOG_TAG, "GATT Event: %s", BLEUtils::gattClientEventTypeToString(event).c_str());
@@ -716,6 +1320,7 @@ void BLEUtils::dumpGattClientEvent(
// - esp_gatt_id_t char_id
// - esp_gatt_char_prop_t char_prop
//
+ /*
case ESP_GATTC_GET_CHAR_EVT: {
// If the status of the event shows that we have a value other than ESP_GATT_OK then the
@@ -742,6 +1347,7 @@ void BLEUtils::dumpGattClientEvent(
}
break;
} // ESP_GATTC_GET_CHAR_EVT
+ */
//
// ESP_GATTC_NOTIFY_EVT
@@ -749,20 +1355,17 @@ void BLEUtils::dumpGattClientEvent(
// notify
// uint16_t conn_id
// esp_bd_addr_t remote_bda
- // esp_gatt_srvc_id_t srvc_id
- // esp_gatt_id_t char_id
- // esp_gatt_id_t descr_id
+ // handle handle
// uint16_t value_len
// uint8_t* value
// bool is_notify
//
case ESP_GATTC_NOTIFY_EVT: {
- ESP_LOGD(LOG_TAG, "[conn_id: %d, remote_bda: %s, srvc_id: <%s>, char_id: <%s>, descr_id: <%s>, value_len: %d, is_notify: %d]",
+ ESP_LOGD(LOG_TAG, "[conn_id: %d, remote_bda: %s, handle: %d 0x%.2x, value_len: %d, is_notify: %d]",
evtParam->notify.conn_id,
BLEAddress(evtParam->notify.remote_bda).toString().c_str(),
- BLEUtils::gattServiceIdToString(evtParam->notify.srvc_id).c_str(),
- gattIdToString(evtParam->notify.char_id).c_str(),
- gattIdToString(evtParam->notify.descr_id).c_str(),
+ evtParam->notify.handle,
+ evtParam->notify.handle,
evtParam->notify.value_len,
evtParam->notify.is_notify
);
@@ -796,20 +1399,16 @@ void BLEUtils::dumpGattClientEvent(
// read:
// esp_gatt_status_t status
// uint16_t conn_id
- // esp_gatt_srvc_id_t srvc_id
- // esp_gatt_id_t char_id
- // esp_gatt_id_t descr_id
+ // uint16_t handle
// uint8_t* value
// uint16_t value_type
// uint16_t value_len
case ESP_GATTC_READ_CHAR_EVT: {
- ESP_LOGD(LOG_TAG, "[status: %s, conn_id: %d, srvc_id: <%s>, char_id: <%s>, descr_id: <%s>, value_type: 0x%x, value_len: %d]",
+ ESP_LOGD(LOG_TAG, "[status: %s, conn_id: %d, handle: %d 0x%.2x, value_len: %d]",
BLEUtils::gattStatusToString(evtParam->read.status).c_str(),
evtParam->read.conn_id,
- BLEUtils::gattServiceIdToString(evtParam->read.srvc_id).c_str(),
- gattIdToString(evtParam->read.char_id).c_str(),
- gattIdToString(evtParam->read.descr_id).c_str(),
- evtParam->read.value_type,
+ evtParam->read.handle,
+ evtParam->read.handle,
evtParam->read.value_len
);
if (evtParam->read.status == ESP_GATT_OK) {
@@ -844,13 +1443,13 @@ void BLEUtils::dumpGattClientEvent(
//
// reg_for_notify:
// - esp_gatt_status_t status
- // - esp_gatt_srvc_id_t srvc_id
- // - esp_gatt_id_t char_id
+ // - uint16_t handle
case ESP_GATTC_REG_FOR_NOTIFY_EVT: {
- ESP_LOGD(LOG_TAG, "[status: %s, srvc_id: <%s>, char_id: <%s>]",
+ ESP_LOGD(LOG_TAG, "[status: %s, handle: %d 0x%.2x]",
BLEUtils::gattStatusToString(evtParam->reg_for_notify.status).c_str(),
- BLEUtils::gattServiceIdToString(evtParam->reg_for_notify.srvc_id).c_str(),
- gattIdToString(evtParam->reg_for_notify.char_id).c_str());
+ evtParam->reg_for_notify.handle,
+ evtParam->reg_for_notify.handle
+ );
break;
} // ESP_GATTC_REG_FOR_NOTIFY_EVT
@@ -874,23 +1473,19 @@ void BLEUtils::dumpGattClientEvent(
// ESP_GATTC_SEARCH_RES_EVT
//
// search_res:
- // - uint16_t conn_id
- // - esp_gatt_srvc_id_t srvc_id
+ // - uint16_t conn_id
+ // - uint16_t start_handle
+ // - uint16_t end_handle
+ // - esp_gatt_id_t srvc_id
//
case ESP_GATTC_SEARCH_RES_EVT: {
- std::string name = "";
- if (evtParam->search_res.srvc_id.id.uuid.len == ESP_UUID_LEN_16) {
- name = BLEUtils::gattServiceToString(evtParam->search_res.srvc_id.id.uuid.uuid.uuid16);
- }
- if (name.length() == 0) {
- name = "<Unknown Service>";
- }
-
- ESP_LOGD(LOG_TAG, "[srvc_id: %s [%s], instanceId: 0x%.2x conn_id: %d]",
- BLEUtils::gattServiceIdToString(evtParam->search_res.srvc_id).c_str(),
- name.c_str(),
- evtParam->search_res.srvc_id.id.inst_id,
- evtParam->search_res.conn_id);
+ ESP_LOGD(LOG_TAG, "[conn_id: %d, start_handle: %d 0x%.2x, end_handle: %d 0x%.2x, srvc_id: %s",
+ evtParam->search_res.conn_id,
+ evtParam->search_res.start_handle,
+ evtParam->search_res.start_handle,
+ evtParam->search_res.end_handle,
+ evtParam->search_res.end_handle,
+ gattIdToString(evtParam->search_res.srvc_id).c_str());
break;
} // ESP_GATTC_SEARCH_RES_EVT
@@ -899,21 +1494,19 @@ void BLEUtils::dumpGattClientEvent(
// ESP_GATTC_WRITE_CHAR_EVT
//
// write:
- // esp_gatt_status_t status
- // uint16_t conn_id
- // esp_gatt_srvc_id_t srvc_id
- // esp_gatt_id_t char_id
- // esp_gatt_id_t descr_id
+ // - esp_gatt_status_t status
+ // - uint16_t conn_id
+ // - uint16_t handle
+ //
case ESP_GATTC_WRITE_CHAR_EVT: {
- ESP_LOGD(LOG_TAG, "[status: %s, conn_id: %d, srvc_id: <%s>, char_id: <%s>, descr_id: <%s>]",
+ ESP_LOGD(LOG_TAG, "[status: %s, conn_id: %d, handle: %d 0x%.2x]",
BLEUtils::gattStatusToString(evtParam->write.status).c_str(),
evtParam->write.conn_id,
- BLEUtils::gattServiceIdToString(evtParam->write.srvc_id).c_str(),
- gattIdToString(evtParam->write.char_id).c_str(),
- gattIdToString(evtParam->write.descr_id).c_str()
+ evtParam->write.handle,
+ evtParam->write.handle
);
break;
- }
+ } // ESP_GATTC_WRITE_CHAR_EVT
default:
break;
@@ -932,27 +1525,41 @@ void BLEUtils::dumpGattClientEvent(
* @param [in] evtParam A union of structures only one of which is populated.
*/
void BLEUtils::dumpGattServerEvent(
- esp_gatts_cb_event_t event,
- esp_gatt_if_t gatts_if,
- esp_ble_gatts_cb_param_t *evtParam) {
+ esp_gatts_cb_event_t event,
+ esp_gatt_if_t gatts_if,
+ esp_ble_gatts_cb_param_t* evtParam) {
ESP_LOGD(LOG_TAG, "GATT ServerEvent: %s", BLEUtils::gattServerEventTypeToString(event).c_str());
switch(event) {
case ESP_GATTS_ADD_CHAR_DESCR_EVT: {
- ESP_LOGD(LOG_TAG, "[status: %s, attr_handle: 0x%.2x, service_handle: 0x%.2x, char_uuid: %s]",
+ ESP_LOGD(LOG_TAG, "[status: %s, attr_handle: %d 0x%.2x, service_handle: %d 0x%.2x, char_uuid: %s]",
gattStatusToString(evtParam->add_char_descr.status).c_str(),
evtParam->add_char_descr.attr_handle,
+ evtParam->add_char_descr.attr_handle,
+ evtParam->add_char_descr.service_handle,
evtParam->add_char_descr.service_handle,
BLEUUID(evtParam->add_char_descr.char_uuid).toString().c_str());
break;
} // ESP_GATTS_ADD_CHAR_DESCR_EVT
case ESP_GATTS_ADD_CHAR_EVT: {
- ESP_LOGD(LOG_TAG, "[status: %s, attr_handle: 0x%.2x, service_handle: 0x%.2x, char_uuid: %s]",
- gattStatusToString(evtParam->add_char.status).c_str(),
- evtParam->add_char.attr_handle,
- evtParam->add_char.service_handle,
- BLEUUID(evtParam->add_char.char_uuid).toString().c_str());
+ if (evtParam->add_char.status == ESP_GATT_OK) {
+ ESP_LOGD(LOG_TAG, "[status: %s, attr_handle: %d 0x%.2x, service_handle: %d 0x%.2x, char_uuid: %s]",
+ gattStatusToString(evtParam->add_char.status).c_str(),
+ evtParam->add_char.attr_handle,
+ evtParam->add_char.attr_handle,
+ evtParam->add_char.service_handle,
+ evtParam->add_char.service_handle,
+ BLEUUID(evtParam->add_char.char_uuid).toString().c_str());
+ } else {
+ ESP_LOGE(LOG_TAG, "[status: %s, attr_handle: %d 0x%.2x, service_handle: %d 0x%.2x, char_uuid: %s]",
+ gattStatusToString(evtParam->add_char.status).c_str(),
+ evtParam->add_char.attr_handle,
+ evtParam->add_char.attr_handle,
+ evtParam->add_char.service_handle,
+ evtParam->add_char.service_handle,
+ BLEUUID(evtParam->add_char.char_uuid).toString().c_str());
+ }
break;
} // ESP_GATTS_ADD_CHAR_EVT
@@ -987,9 +1594,10 @@ void BLEUtils::dumpGattServerEvent(
} // ESP_GATTS_CONNECT_EVT
case ESP_GATTS_CREATE_EVT: {
- ESP_LOGD(LOG_TAG, "[status: %s, service_handle: 0x%.2x, service_id: [%s]]",
+ ESP_LOGD(LOG_TAG, "[status: %s, service_handle: %d 0x%.2x, service_id: [%s]]",
gattStatusToString(evtParam->create.status).c_str(),
evtParam->create.service_handle,
+ evtParam->create.service_handle,
gattServiceIdToString(evtParam->create.service_id).c_str());
break;
} // ESP_GATTS_CREATE_EVT
@@ -1108,7 +1716,7 @@ void BLEUtils::dumpGattServerEvent(
evtParam->write.need_rsp,
evtParam->write.is_prep,
evtParam->write.len);
- char *pHex = buildHexData(nullptr, evtParam->write.value, evtParam->write.len);
+ char* pHex = buildHexData(nullptr, evtParam->write.value, evtParam->write.len);
ESP_LOGD(LOG_TAG, "[Data: %s]", pHex);
free(pHex);
break;
@@ -1139,7 +1747,7 @@ const char* BLEUtils::eventTypeToString(esp_ble_evt_type_t eventType) {
case ESP_BLE_EVT_SCAN_RSP:
return "ESP_BLE_EVT_SCAN_RSP";
default:
- ESP_LOGD(LOG_TAG, "Unknown esp_ble_evt_type_t: %d", eventType);
+ ESP_LOGD(LOG_TAG, "Unknown esp_ble_evt_type_t: %d (0x%.2x)", eventType, eventType);
return "*** Unknown ***";
}
} // eventTypeToString
@@ -1153,53 +1761,70 @@ const char* BLEUtils::eventTypeToString(esp_ble_evt_type_t eventType) {
*/
const char* BLEUtils::gapEventToString(uint32_t eventType) {
switch(eventType) {
- 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_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_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_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_SEC_REQ_EVT: /* BLE security request */
- return "ESP_GAP_BLE_SEC_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_OOB_REQ_EVT: /* OOB request event */
- return "ESP_GAP_BLE_OOB_REQ_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_ADV_STOP_COMPLETE_EVT: /*!< When stop adv complete, the event comes */
- return "ESP_GAP_BLE_ADV_STOP_COMPLETE_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 0x%x", eventType);
+ ESP_LOGD(LOG_TAG, "gapEventToString: Unknown event type %d 0x%.2x", eventType, eventType);
return "Unknown event type";
}
} // gapEventToString
std::string BLEUtils::gattCharacteristicUUIDToString(uint32_t characteristicUUID) {
- characteristicMap_t *p = g_characteristicsMappings;
+ const characteristicMap_t *p = g_characteristicsMappings;
while (p->name.length() > 0) {
if (p->assignedNumber == characteristicUUID) {
return p->name;
@@ -1211,6 +1836,39 @@ std::string BLEUtils::gattCharacteristicUUIDToString(uint32_t characteristicUUID
/**
+ * @brief Given the UUID for a BLE defined descriptor, return its string representation.
+ * @param [in] descriptorUUID UUID of the descriptor to be returned as a string.
+ * @return The string representation of a descriptor UUID.
+ */
+std::string BLEUtils::gattDescriptorUUIDToString(uint32_t descriptorUUID) {
+ gattdescriptor_t* p = (gattdescriptor_t *)g_descriptor_ids;
+ while (p->name.length() > 0) {
+ if (p->assignedNumber == descriptorUUID) {
+ return p->name;
+ }
+ p++;
+ }
+ return "";
+} // gattDescriptorUUIDToString
+
+
+/**
+ * @brief Return a string representation of an esp_gattc_service_elem_t.
+ * @return A string representation of an esp_gattc_service_elem_t.
+ */
+std::string BLEUtils::gattcServiceElementToString(esp_gattc_service_elem_t* pGATTCServiceElement) {
+ std::stringstream ss;
+
+ ss << "[uuid: " << BLEUUID(pGATTCServiceElement->uuid).toString() <<
+ ", start_handle: " << pGATTCServiceElement->start_handle <<
+ " 0x" << std::hex << pGATTCServiceElement->start_handle <<
+ ", end_handle: " << std::dec << pGATTCServiceElement->end_handle <<
+ " 0x" << std::hex << pGATTCServiceElement->end_handle << "]";
+ return ss.str();
+} // gattcServiceElementToString
+
+
+/**
* @brief Convert an esp_gatt_srvc_id_t to a string.
*/
std::string BLEUtils::gattServiceIdToString(esp_gatt_srvc_id_t srvcId) {
@@ -1312,16 +1970,37 @@ std::string BLEUtils::gattStatusToString(esp_gatt_status_t status) {
return "ESP_GATT_ALREADY_OPEN";
case ESP_GATT_CANCEL:
return "ESP_GATT_CANCEL";
+ case ESP_GATT_STACK_RSP:
+ return "ESP_GATT_STACK_RSP";
+ case ESP_GATT_APP_RSP:
+ return "ESP_GATT_APP_RSP";
+ case ESP_GATT_UNKNOWN_ERROR:
+ return "ESP_GATT_UNKNOWN_ERROR";
case ESP_GATT_CCC_CFG_ERR:
return "ESP_GATT_CCC_CFG_ERR";
case ESP_GATT_PRC_IN_PROGRESS:
return "ESP_GATT_PRC_IN_PROGRESS";
+ case ESP_GATT_OUT_OF_RANGE:
+ return "ESP_GATT_OUT_OF_RANGE";
default:
return "Unknown";
}
} // gattStatusToString
+
+std::string BLEUtils::getMember(uint32_t memberId) {
+ member_t* p = (member_t *)members_ids;
+
+ while (p->name.length() > 0) {
+ if (p->assignedNumber == memberId) {
+ return p->name;
+ }
+ p++;
+ }
+ return "Unknown";
+}
+
/**
* @brief convert a GAP search event to a string.
* @param [in] searchEvt
diff --git a/src/BLEUtils.h b/src/BLEUtils.h
index 28c7a7e..5ef6c37 100644
--- a/src/BLEUtils.h
+++ b/src/BLEUtils.h
@@ -20,40 +20,42 @@
*/
class BLEUtils {
public:
- static const char* advTypeToString(uint8_t advType);
- static esp_gatt_id_t buildGattId(esp_bt_uuid_t uuid, uint8_t inst_id=0);
-
+ static const char* addressTypeToString(esp_ble_addr_type_t type);
+ 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);
- static std::string characteristicPropertiesToString(esp_gatt_char_prop_t prop);
- static char* buildHexData(uint8_t *target, uint8_t *source, uint8_t length);
- static BLEClient* findByConnId(uint16_t conn_id);
- static BLEClient* findByAddress(BLEAddress address);
- static std::string gattClientEventTypeToString(esp_gattc_cb_event_t eventType);
- static std::string gattServerEventTypeToString(esp_gatts_cb_event_t eventType);
- static std::string gattServiceIdToString(esp_gatt_srvc_id_t srvcId);
- static std::string gattStatusToString(esp_gatt_status_t status);
- static std::string gattServiceToString(uint32_t serviceId);
- static std::string gattCloseReasonToString(esp_gatt_conn_reason_t reason);
- static void registerByAddress(BLEAddress address, BLEClient* pDevice);
- static void registerByConnId(uint16_t conn_id, BLEClient* pDevice);
- static std::string gattCharacteristicUUIDToString(uint32_t characteristicUUID);
- static std::string buildPrintData(uint8_t* source, size_t length);
+ static char* buildHexData(uint8_t* target, uint8_t* source, uint8_t length);
+ static std::string buildPrintData(uint8_t* source, size_t length);
+ static std::string characteristicPropertiesToString(esp_gatt_char_prop_t prop);
+ static const char* devTypeToString(esp_bt_dev_type_t type);
+ static void dumpGapEvent(
+ esp_gap_ble_cb_event_t event,
+ esp_ble_gap_cb_param_t* param);
static void dumpGattClientEvent(
- esp_gattc_cb_event_t event,
- esp_gatt_if_t gattc_if,
+ esp_gattc_cb_event_t event,
+ esp_gatt_if_t gattc_if,
esp_ble_gattc_cb_param_t* evtParam);
static void dumpGattServerEvent(
- esp_gatts_cb_event_t event,
- esp_gatt_if_t gatts_if,
+ esp_gatts_cb_event_t event,
+ esp_gatt_if_t gatts_if,
esp_ble_gatts_cb_param_t* evtParam);
- static const char* devTypeToString(esp_bt_dev_type_t type);
- static void dumpGapEvent(
- esp_gap_ble_cb_event_t event,
- esp_ble_gap_cb_param_t* param);
+ static const char* eventTypeToString(esp_ble_evt_type_t eventType);
+ static BLEClient* findByAddress(BLEAddress address);
+ static BLEClient* findByConnId(uint16_t conn_id);
static const char* gapEventToString(uint32_t eventType);
+ static std::string gattCharacteristicUUIDToString(uint32_t characteristicUUID);
+ static std::string gattClientEventTypeToString(esp_gattc_cb_event_t eventType);
+ static std::string gattCloseReasonToString(esp_gatt_conn_reason_t reason);
+ static std::string gattcServiceElementToString(esp_gattc_service_elem_t *pGATTCServiceElement);
+ static std::string gattDescriptorUUIDToString(uint32_t descriptorUUID);
+ static std::string gattServerEventTypeToString(esp_gatts_cb_event_t eventType);
+ static std::string gattServiceIdToString(esp_gatt_srvc_id_t srvcId);
+ static std::string gattServiceToString(uint32_t serviceId);
+ static std::string gattStatusToString(esp_gatt_status_t status);
+ static std::string getMember(uint32_t memberId);
+ static void registerByAddress(BLEAddress address, BLEClient* pDevice);
+ static void registerByConnId(uint16_t conn_id, BLEClient* pDevice);
static const char* searchEventTypeToString(esp_gap_search_evt_t searchEvt);
- static const char* addressTypeToString(esp_ble_addr_type_t type);
- static const char *eventTypeToString(esp_ble_evt_type_t eventType);
};
#endif // CONFIG_BT_ENABLED
diff --git a/src/BLEValue.cpp b/src/BLEValue.cpp
index 1989993..d36d207 100644
--- a/src/BLEValue.cpp
+++ b/src/BLEValue.cpp
@@ -72,6 +72,24 @@ void BLEValue::commit() {
/**
+ * @brief Get a pointer to the data.
+ * @return A pointer to the data.
+ */
+uint8_t* BLEValue::getData() {
+ return (uint8_t*)m_value.data();
+}
+
+
+/**
+ * @brief Get the length of the data in bytes.
+ * @return The length of the data in bytes.
+ */
+size_t BLEValue::getLength() {
+ return m_value.length();
+} // getLength
+
+
+/**
* @brief Get the read offset.
* @return The read offset into the read.
*/
@@ -113,4 +131,9 @@ void BLEValue::setValue(std::string value) {
void BLEValue::setValue(uint8_t* pData, size_t length) {
m_value = std::string((char*)pData, length);
} // setValue
+
+
+
+
+
#endif // CONFIG_BT_ENABLED
diff --git a/src/BLEValue.h b/src/BLEValue.h
index a292c6e..92a7f9a 100644
--- a/src/BLEValue.h
+++ b/src/BLEValue.h
@@ -21,6 +21,8 @@ public:
void addPart(uint8_t* pData, size_t length);
void cancel();
void commit();
+ uint8_t* getData();
+ size_t getLength();
uint16_t getReadOffset();
std::string getValue();
void setReadOffset(uint16_t readOffset);
diff --git a/src/FreeRTOS.cpp b/src/FreeRTOS.cpp
index 663128d..dea73bf 100644
--- a/src/FreeRTOS.cpp
+++ b/src/FreeRTOS.cpp
@@ -133,11 +133,10 @@ void FreeRTOS::Semaphore::giveFromISR() {
*/
void FreeRTOS::Semaphore::take(std::string owner)
{
-
- ESP_LOGV(LOG_TAG, "Semaphore taking: %s for %s", toString().c_str(), owner.c_str());
+ ESP_LOGD(LOG_TAG, "Semaphore taking: %s for %s", toString().c_str(), owner.c_str());
xSemaphoreTake(m_semaphore, portMAX_DELAY);
m_owner = owner;
- ESP_LOGV(LOG_TAG, "Semaphore taken: %s", toString().c_str());
+ ESP_LOGD(LOG_TAG, "Semaphore taken: %s", toString().c_str());
} // Semaphore::take
diff --git a/src/GeneralUtils.cpp b/src/GeneralUtils.cpp
index 4237b14..6bfde84 100644
--- a/src/GeneralUtils.cpp
+++ b/src/GeneralUtils.cpp
@@ -7,6 +7,7 @@
#include "GeneralUtils.h"
#include <esp_log.h>
+#include <esp_system.h>
#include <string.h>
#include <stdio.h>
#include <string>
@@ -106,6 +107,23 @@ bool GeneralUtils::base64Encode(const std::string &in, std::string *out) {
} // base64Encode
+/**
+ * @brief Does the string end with a specific character?
+ * @param [in] str The string to examine.
+ * @param [in] c The character to look form.
+ * @return True if the string ends with the given character.
+ */
+bool GeneralUtils::endsWith(std::string str, char c) {
+ if (str.empty()) {
+ return false;
+ }
+ if (str.at(str.length()-1) == c) {
+ return true;
+ }
+ return false;
+} // endsWidth
+
+
static int DecodedLength(const std::string &in) {
int numEq = 0;
int n = in.size();
@@ -261,7 +279,7 @@ void GeneralUtils::hexDump(uint8_t* pData, uint32_t length) {
* @param [in] length Length of the data (in bytes) to be logged.
* @return N/A.
*/
-void GeneralUtils::hexDump(uint8_t* pData, uint32_t length) {
+void GeneralUtils::hexDump(const uint8_t* pData, uint32_t length) {
char ascii[80];
char hex[80];
char tempBuf[80];
@@ -386,3 +404,9 @@ const char* GeneralUtils::errorToString(esp_err_t errCode) {
return "Unknown ESP_ERR error";
} // errorToString
+/**
+ * @brief Restart the ESP32.
+ */
+void GeneralUtils::restart() {
+ esp_restart();
+} // restart
diff --git a/src/GeneralUtils.h b/src/GeneralUtils.h
index 152abca..ce75e43 100644
--- a/src/GeneralUtils.h
+++ b/src/GeneralUtils.h
@@ -18,11 +18,13 @@ class GeneralUtils {
public:
GeneralUtils();
virtual ~GeneralUtils();
- static void hexDump(uint8_t *pData, uint32_t length);
- static std::string ipToString(uint8_t *ip);
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();
};
#endif /* COMPONENTS_CPP_UTILS_GENERALUTILS_H_ */