|
17 | 17 | #include <sstream>
|
18 | 18 | #include "BLEUtils.h"
|
19 | 19 | #include "GeneralUtils.h"
|
| 20 | +#include "BLERemoteDescriptor.h" |
20 | 21 |
|
21 | 22 |
|
22 |
| -static const char* LOG_TAG = "BLERemoteCharacteristic"; |
| 23 | +static const char* LOG_TAG = "BLERemoteCharacteristic"; // The logging tag for this class. |
23 | 24 |
|
| 25 | +/** |
| 26 | + * @brief Constructor. |
| 27 | + * @param [in] handle The BLE server side handle of this characteristic. |
| 28 | + * @param [in] uuid The UUID of this characteristic. |
| 29 | + * @param [in] charProp The properties of this characteristic. |
| 30 | + * @param [in] pRemoteService A reference to the remote service to which this remote characteristic pertains. |
| 31 | + */ |
24 | 32 | BLERemoteCharacteristic::BLERemoteCharacteristic(
|
25 | 33 | uint16_t handle,
|
26 | 34 | BLEUUID uuid,
|
27 | 35 | esp_gatt_char_prop_t charProp,
|
28 | 36 | BLERemoteService* pRemoteService) {
|
| 37 | + ESP_LOGD(LOG_TAG, ">> BLERemoteCharacteristic: handle: %d 0x%d, uuid: %s", handle, handle, uuid.toString().c_str()); |
29 | 38 | m_handle = handle;
|
30 | 39 | m_uuid = uuid;
|
31 | 40 | m_charProp = charProp;
|
32 | 41 | m_pRemoteService = pRemoteService;
|
33 | 42 | m_notifyCallback = nullptr;
|
| 43 | + |
| 44 | + getDescriptors(); // Get the descriptors for this characteristic |
| 45 | + ESP_LOGD(LOG_TAG, "<< BLERemoteCharacteristic"); |
34 | 46 | } // BLERemoteCharacteristic
|
35 | 47 |
|
| 48 | + |
| 49 | +/** |
| 50 | + *@brief Destructor. |
| 51 | + */ |
| 52 | +BLERemoteCharacteristic::~BLERemoteCharacteristic() { |
| 53 | + removeDescriptors(); // Release resources for any descriptor information we may have allocated. |
| 54 | +} // ~BLERemoteCharacteristic |
| 55 | + |
| 56 | + |
36 | 57 | /*
|
37 | 58 | static bool compareSrvcId(esp_gatt_srvc_id_t id1, esp_gatt_srvc_id_t id2) {
|
38 | 59 | if (id1.id.inst_id != id2.id.inst_id) {
|
@@ -72,6 +93,36 @@ void BLERemoteCharacteristic::gattClientEventHandler(
|
72 | 93 | esp_gatt_if_t gattc_if,
|
73 | 94 | esp_ble_gattc_cb_param_t* evtParam) {
|
74 | 95 | switch(event) {
|
| 96 | + // |
| 97 | + // ESP_GATTC_NOTIFY_EVT |
| 98 | + // |
| 99 | + // notify |
| 100 | + // - uint16_t conn_id |
| 101 | + // - esp_bd_addr_t remote_bda |
| 102 | + // - uint16_t handle |
| 103 | + // - uint16_t value_len |
| 104 | + // - uint8_t* value |
| 105 | + // - bool is_notify |
| 106 | + // |
| 107 | + // We have received a notification event which means that the server wishes us to know about a notification |
| 108 | + // piece of data. What we must now do is find the characteristic with the associated handle and then |
| 109 | + // invoke its notification callback (if it has one). |
| 110 | + // |
| 111 | + case ESP_GATTC_NOTIFY_EVT: { |
| 112 | + if (evtParam->notify.handle != getHandle()) { |
| 113 | + break; |
| 114 | + } |
| 115 | + if (m_notifyCallback != nullptr) { |
| 116 | + m_notifyCallback( |
| 117 | + this, |
| 118 | + evtParam->notify.value, |
| 119 | + evtParam->notify.value_len, |
| 120 | + evtParam->notify.is_notify |
| 121 | + ); |
| 122 | + } // End we have a callback function ... |
| 123 | + break; |
| 124 | + } // ESP_GATTC_NOTIFY_EVT |
| 125 | + |
75 | 126 | //
|
76 | 127 | // ESP_GATTC_READ_CHAR_EVT
|
77 | 128 | // This event indicates that the server has responded to the read request.
|
@@ -148,16 +199,127 @@ void BLERemoteCharacteristic::gattClientEventHandler(
|
148 | 199 | } // End switch
|
149 | 200 | }; // gattClientEventHandler
|
150 | 201 |
|
| 202 | + |
| 203 | +/** |
| 204 | + * @brief Populate the descriptors (if any) for this characteristic. |
| 205 | + */ |
| 206 | +void BLERemoteCharacteristic::getDescriptors() { |
| 207 | + ESP_LOGD(LOG_TAG, ">> getDescriptors() for characteristic: %s", getUUID().toString().c_str()); |
| 208 | + |
| 209 | + removeDescriptors(); // Remove any existing descriptors. |
| 210 | + |
| 211 | + /* |
| 212 | + uint16_t count; |
| 213 | + esp_gatt_status_t status = ::esp_ble_gattc_get_attr_count( |
| 214 | + getRemoteService()->getClient()->getGattcIf(), |
| 215 | + getRemoteService()->getClient()->getConnId(), |
| 216 | + ESP_GATT_DB_DESCRIPTOR, |
| 217 | + getRemoteService()->getStartHandle(), |
| 218 | + getRemoteService()->getEndHandle(), |
| 219 | + getHandle(), // Characteristic handle ... only used for ESP_GATT_DB_DESCRIPTOR |
| 220 | + &count |
| 221 | + ); |
| 222 | + if (status != ESP_GATT_OK) { |
| 223 | + ESP_LOGE(LOG_TAG, "esp_ble_gattc_get_attr_count: %s", BLEUtils::gattStatusToString(status).c_str()); |
| 224 | + } else { |
| 225 | + ESP_LOGD(LOG_TAG, "Number of descriptors associated with characteristic is %d", count); |
| 226 | + } |
| 227 | + */ |
| 228 | + |
| 229 | + |
| 230 | + // Loop over each of the descriptors within the service associated with this characteristic. |
| 231 | + // For each descriptor we find, create a BLERemoteDescriptor instance. |
| 232 | + uint16_t offset = 0; |
| 233 | + esp_gattc_descr_elem_t result; |
| 234 | + while(1) { |
| 235 | + uint16_t count = 1; |
| 236 | + esp_gatt_status_t status = ::esp_ble_gattc_get_all_descr( |
| 237 | + getRemoteService()->getClient()->getGattcIf(), |
| 238 | + getRemoteService()->getClient()->getConnId(), |
| 239 | + getHandle(), |
| 240 | + &result, |
| 241 | + &count, |
| 242 | + offset |
| 243 | + ); |
| 244 | + |
| 245 | + if (status == ESP_GATT_INVALID_OFFSET) { // We have reached the end of the entries. |
| 246 | + break; |
| 247 | + } |
| 248 | + |
| 249 | + if (status != ESP_GATT_OK) { |
| 250 | + ESP_LOGE(LOG_TAG, "esp_ble_gattc_get_all_descr: %s", BLEUtils::gattStatusToString(status).c_str()); |
| 251 | + break; |
| 252 | + } |
| 253 | + |
| 254 | + if (count == 0) { |
| 255 | + break; |
| 256 | + } |
| 257 | + ESP_LOGD(LOG_TAG, "Found a descriptor: Handle: %d, UUID: %s", result.handle, BLEUUID(result.uuid).toString().c_str()); |
| 258 | + |
| 259 | + // We now have a new characteristic ... let us add that to our set of known characteristics |
| 260 | + BLERemoteDescriptor *pNewRemoteDescriptor = new BLERemoteDescriptor( |
| 261 | + result.handle, |
| 262 | + BLEUUID(result.uuid), |
| 263 | + this |
| 264 | + ); |
| 265 | + |
| 266 | + m_descriptorMap.insert(std::pair<std::string, BLERemoteDescriptor*>(pNewRemoteDescriptor->getUUID().toString(), pNewRemoteDescriptor)); |
| 267 | + |
| 268 | + offset++; |
| 269 | + } // while true |
| 270 | + //m_haveCharacteristics = true; // Remember that we have received the characteristics. |
| 271 | + ESP_LOGD(LOG_TAG, "<< getDescriptors(): Found %d descriptors.", offset); |
| 272 | +} // getDescriptors |
| 273 | + |
| 274 | + |
| 275 | + |
| 276 | +/** |
| 277 | + * @brief Get the handle for this characteristic. |
| 278 | + * @return The handle for this characteristic. |
| 279 | + */ |
151 | 280 | uint16_t BLERemoteCharacteristic::getHandle() {
|
152 |
| - ESP_LOGD(LOG_TAG, ">> getHandle: Characteristic: %s", getUUID().toString().c_str()); |
153 |
| - ESP_LOGD(LOG_TAG, "<< getHandle: %d 0x%.2x", m_handle, m_handle); |
| 281 | + //ESP_LOGD(LOG_TAG, ">> getHandle: Characteristic: %s", getUUID().toString().c_str()); |
| 282 | + //ESP_LOGD(LOG_TAG, "<< getHandle: %d 0x%.2x", m_handle, m_handle); |
154 | 283 | return m_handle;
|
155 |
| -} |
| 284 | +} // getHandle |
156 | 285 |
|
157 | 286 |
|
| 287 | +/** |
| 288 | + * @brief Get the descriptor instance with the given UUID that belongs to this characteristic. |
| 289 | + * @param [in] uuid The UUID of the descriptor to find. |
| 290 | + * @return The Remote descriptor (if present) or null if not present. |
| 291 | + */ |
| 292 | +BLERemoteDescriptor* BLERemoteCharacteristic::getDescriptor(BLEUUID uuid) { |
| 293 | + ESP_LOGD(LOG_TAG, ">> getDescriptor: uuid: %s", uuid.toString().c_str()); |
| 294 | + std::string v = uuid.toString(); |
| 295 | + for (auto &myPair : m_descriptorMap) { |
| 296 | + if (myPair.first == v) { |
| 297 | + ESP_LOGD(LOG_TAG, "<< getDescriptor: found"); |
| 298 | + return myPair.second; |
| 299 | + } |
| 300 | + } |
| 301 | + ESP_LOGD(LOG_TAG, "<< getDescriptor: Not found"); |
| 302 | + return nullptr; |
| 303 | +} // getDescriptor |
| 304 | + |
| 305 | + |
| 306 | +/** |
| 307 | + * @brief Get the remote service associated with this characteristic. |
| 308 | + * @return The remote service associated with this characteristic. |
| 309 | + */ |
| 310 | +BLERemoteService *BLERemoteCharacteristic::getRemoteService() { |
| 311 | + return m_pRemoteService; |
| 312 | +} // getRemoteService |
| 313 | + |
| 314 | + |
| 315 | +/** |
| 316 | + * @brief Get the UUID for this characteristic. |
| 317 | + * @return The UUID for this characteristic. |
| 318 | + */ |
158 | 319 | BLEUUID BLERemoteCharacteristic::getUUID() {
|
159 | 320 | return m_uuid;
|
160 |
| -} |
| 321 | +} // getUUID |
| 322 | + |
161 | 323 |
|
162 | 324 | /**
|
163 | 325 | * @brief Read an unsigned 16 bit value
|
@@ -240,7 +402,7 @@ void BLERemoteCharacteristic::registerForNotify(
|
240 | 402 | uint8_t* pData,
|
241 | 403 | size_t length,
|
242 | 404 | bool isNotify)) {
|
243 |
| - ESP_LOGD(LOG_TAG, ">> registerForNotify()"); |
| 405 | + ESP_LOGD(LOG_TAG, ">> registerForNotify(): %s", toString().c_str()); |
244 | 406 |
|
245 | 407 | m_notifyCallback = notifyCallback; // Save the notification callback.
|
246 | 408 |
|
@@ -275,6 +437,21 @@ void BLERemoteCharacteristic::registerForNotify(
|
275 | 437 | } // registerForNotify
|
276 | 438 |
|
277 | 439 |
|
| 440 | +/** |
| 441 | + * @brief Delete the descriptors in the descriptor map. |
| 442 | + * We maintain a map called m_descriptorMap that contains pointers to BLERemoteDescriptors |
| 443 | + * object references. Since we allocated these in this class, we are also responsible for deleteing |
| 444 | + * them. This method does just that. |
| 445 | + * @return N/A. |
| 446 | + */ |
| 447 | +void BLERemoteCharacteristic::removeDescriptors() { |
| 448 | + for (auto &myPair : m_descriptorMap) { |
| 449 | + delete myPair.second; |
| 450 | + } |
| 451 | + m_descriptorMap.empty(); |
| 452 | +} // removeCharacteristics |
| 453 | + |
| 454 | + |
278 | 455 | /**
|
279 | 456 | * @brief Convert a BLERemoteCharacteristic to a string representation;
|
280 | 457 | * @return a String representation.
|
|
0 commit comments