2020-03-30 01:44:20 +02:00
|
|
|
/*
|
|
|
|
* NimBLERemoteCharacteristic.cpp
|
|
|
|
*
|
|
|
|
* Created: on Jan 27 2020
|
|
|
|
* Author H2zero
|
2020-05-14 06:03:56 +02:00
|
|
|
*
|
2020-03-30 01:44:20 +02:00
|
|
|
* Originally:
|
|
|
|
*
|
|
|
|
* BLERemoteCharacteristic.cpp
|
|
|
|
*
|
|
|
|
* Created on: Mar 16, 2017
|
|
|
|
* Author: kolban
|
|
|
|
*/
|
|
|
|
|
2020-05-14 06:03:56 +02:00
|
|
|
#include "nimconfig.h"
|
2021-09-07 05:14:43 +02:00
|
|
|
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
2020-05-14 06:03:56 +02:00
|
|
|
|
2024-07-26 22:47:36 +02:00
|
|
|
# include "NimBLERemoteCharacteristic.h"
|
|
|
|
# include "NimBLERemoteDescriptor.h"
|
|
|
|
# include "NimBLERemoteService.h"
|
|
|
|
# include "NimBLEClient.h"
|
|
|
|
# include "NimBLEUtils.h"
|
|
|
|
# include "NimBLELog.h"
|
2020-03-30 01:44:20 +02:00
|
|
|
|
2024-07-26 22:47:36 +02:00
|
|
|
# include <climits>
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
const NimBLEUUID* uuid;
|
|
|
|
void* task_data;
|
|
|
|
} desc_filter_t;
|
2022-01-15 04:45:24 +01:00
|
|
|
|
2020-03-30 01:44:20 +02:00
|
|
|
static const char* LOG_TAG = "NimBLERemoteCharacteristic";
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Constructor.
|
2024-07-26 22:47:36 +02:00
|
|
|
* @param [in] svc A pointer to the service this characteristic belongs to.
|
2020-03-30 01:44:20 +02:00
|
|
|
* @param [in] ble_gatt_chr struct defined as:
|
|
|
|
* struct ble_gatt_chr {
|
|
|
|
* uint16_t def_handle;
|
|
|
|
* uint16_t val_handle;
|
|
|
|
* uint8_t properties;
|
|
|
|
* ble_uuid_any_t uuid;
|
|
|
|
* };
|
|
|
|
*/
|
2024-07-26 22:47:36 +02:00
|
|
|
NimBLERemoteCharacteristic::NimBLERemoteCharacteristic(const NimBLERemoteService* svc, const ble_gatt_chr* chr)
|
|
|
|
: NimBLERemoteValueAttribute{chr->uuid, chr->val_handle},
|
|
|
|
m_pRemoteService{svc},
|
|
|
|
m_properties{chr->properties},
|
|
|
|
m_notifyCallback{},
|
|
|
|
m_vDescriptors{} {} // NimBLERemoteCharacteristic
|
2020-03-30 01:44:20 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
*@brief Destructor.
|
|
|
|
*/
|
|
|
|
NimBLERemoteCharacteristic::~NimBLERemoteCharacteristic() {
|
2020-06-22 06:07:01 +02:00
|
|
|
deleteDescriptors();
|
2020-03-30 01:44:20 +02:00
|
|
|
} // ~NimBLERemoteCharacteristic
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Callback used by the API when a descriptor is discovered or search complete.
|
|
|
|
*/
|
2024-07-26 22:47:36 +02:00
|
|
|
int NimBLERemoteCharacteristic::descriptorDiscCB(
|
|
|
|
uint16_t conn_handle, const ble_gatt_error* error, uint16_t chr_val_handle, const ble_gatt_dsc* dsc, void* arg) {
|
2021-05-17 22:37:03 +02:00
|
|
|
int rc = error->status;
|
2024-07-26 22:47:36 +02:00
|
|
|
NIMBLE_LOGD(LOG_TAG, "Descriptor Discovery >> status: %d handle: %d", rc, (rc == 0) ? dsc->handle : -1);
|
2020-05-14 06:03:56 +02:00
|
|
|
|
2024-07-26 22:47:36 +02:00
|
|
|
auto filter = (desc_filter_t*)arg;
|
|
|
|
auto pTaskData = (ble_task_data_t*)filter->task_data;
|
|
|
|
const auto pChr = (NimBLERemoteCharacteristic*)pTaskData->pATT;
|
|
|
|
const NimBLEUUID* uuidFilter = filter->uuid;
|
2020-03-30 01:44:20 +02:00
|
|
|
|
2024-07-26 22:47:36 +02:00
|
|
|
if (pChr->getHandle() != chr_val_handle) {
|
|
|
|
rc = BLE_HS_EDONE; // descriptor not for this characteristic
|
2020-03-30 01:44:20 +02:00
|
|
|
}
|
2020-05-14 06:03:56 +02:00
|
|
|
|
2024-07-26 22:47:36 +02:00
|
|
|
if (rc == 0) {
|
|
|
|
if (uuidFilter != nullptr) {
|
|
|
|
if (ble_uuid_cmp(uuidFilter->getBase(), &dsc->uuid.u) == 0) {
|
|
|
|
rc = BLE_HS_EDONE; // Found the descriptor, stop the search
|
|
|
|
} else {
|
|
|
|
return 0; // Not the descriptor we are looking for
|
2020-05-23 18:27:32 +02:00
|
|
|
}
|
2020-03-30 01:44:20 +02:00
|
|
|
}
|
2020-05-23 18:27:32 +02:00
|
|
|
|
2024-07-26 22:47:36 +02:00
|
|
|
pChr->m_vDescriptors.push_back(new NimBLERemoteDescriptor(pChr, dsc));
|
2020-03-30 01:44:20 +02:00
|
|
|
}
|
2020-06-22 06:07:01 +02:00
|
|
|
|
2024-07-26 22:47:36 +02:00
|
|
|
if (rc != 0) {
|
|
|
|
pTaskData->rc = rc == BLE_HS_EDONE ? 0 : rc;
|
|
|
|
NIMBLE_LOGD(LOG_TAG, "<< Descriptor Discovery");
|
|
|
|
xTaskNotifyGive(pTaskData->task);
|
2021-05-17 22:37:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2020-03-30 01:44:20 +02:00
|
|
|
/**
|
|
|
|
* @brief Populate the descriptors (if any) for this characteristic.
|
|
|
|
* @param [in] the end handle of the characteristic, or the service, whichever comes first.
|
|
|
|
*/
|
2024-07-26 22:47:36 +02:00
|
|
|
bool NimBLERemoteCharacteristic::retrieveDescriptors(const NimBLEUUID* uuidFilter) const {
|
2020-03-30 01:44:20 +02:00
|
|
|
NIMBLE_LOGD(LOG_TAG, ">> retrieveDescriptors() for characteristic: %s", getUUID().toString().c_str());
|
|
|
|
|
2024-07-26 22:47:36 +02:00
|
|
|
TaskHandle_t cur_task = xTaskGetCurrentTaskHandle();
|
|
|
|
ble_task_data_t taskData = {const_cast<NimBLERemoteCharacteristic*>(this), cur_task, 0, nullptr};
|
|
|
|
desc_filter_t filter = {uuidFilter, &taskData};
|
2021-05-17 22:37:03 +02:00
|
|
|
|
2024-07-26 22:47:36 +02:00
|
|
|
int rc = ble_gattc_disc_all_dscs(getClient()->getConnId(),
|
|
|
|
getHandle(),
|
2021-05-17 22:37:03 +02:00
|
|
|
getRemoteService()->getEndHandle(),
|
2024-07-26 22:47:36 +02:00
|
|
|
NimBLERemoteCharacteristic::descriptorDiscCB,
|
|
|
|
&filter);
|
2020-03-30 01:44:20 +02:00
|
|
|
if (rc != 0) {
|
2021-05-17 22:37:03 +02:00
|
|
|
NIMBLE_LOGE(LOG_TAG, "ble_gattc_disc_all_dscs: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
|
2020-03-30 01:44:20 +02:00
|
|
|
return false;
|
|
|
|
}
|
2020-05-14 06:03:56 +02:00
|
|
|
|
2024-07-26 22:47:36 +02:00
|
|
|
# ifdef ulTaskNotifyValueClear
|
2022-01-10 03:04:41 +01:00
|
|
|
// Clear the task notification value to ensure we block
|
|
|
|
ulTaskNotifyValueClear(cur_task, ULONG_MAX);
|
2024-07-26 22:47:36 +02:00
|
|
|
# endif
|
2020-06-22 06:07:01 +02:00
|
|
|
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
|
|
|
|
2021-05-17 22:37:03 +02:00
|
|
|
if (taskData.rc != 0) {
|
2024-07-26 22:47:36 +02:00
|
|
|
NIMBLE_LOGE(LOG_TAG,
|
|
|
|
"<< retrieveDescriptors(): failed: rc=%d %s",
|
|
|
|
taskData.rc,
|
|
|
|
NimBLEUtils::returnCodeToString(taskData.rc));
|
|
|
|
} else {
|
|
|
|
NIMBLE_LOGD(LOG_TAG, "<< retrieveDescriptors(): found %d descriptors.", m_vDescriptors.size());
|
2020-03-30 01:44:20 +02:00
|
|
|
}
|
2020-05-14 06:03:56 +02:00
|
|
|
|
2024-07-26 22:47:36 +02:00
|
|
|
return taskData.rc == 0;
|
2021-01-14 02:04:52 +01:00
|
|
|
} // retrieveDescriptors
|
2020-03-30 01:44:20 +02:00
|
|
|
|
|
|
|
/**
|
2020-05-23 18:27:32 +02:00
|
|
|
* @brief Get the descriptor instance with the given UUID that belongs to this characteristic.
|
|
|
|
* @param [in] uuid The UUID of the descriptor to find.
|
2024-07-26 22:47:36 +02:00
|
|
|
* @return The Remote descriptor (if present) or nullptr if not present.
|
2020-05-23 18:27:32 +02:00
|
|
|
*/
|
2024-07-26 22:47:36 +02:00
|
|
|
NimBLERemoteDescriptor* NimBLERemoteCharacteristic::getDescriptor(const NimBLEUUID& uuid) const {
|
2020-05-23 18:27:32 +02:00
|
|
|
NIMBLE_LOGD(LOG_TAG, ">> getDescriptor: uuid: %s", uuid.toString().c_str());
|
2024-07-26 22:47:36 +02:00
|
|
|
NimBLERemoteDescriptor* pDsc = nullptr;
|
|
|
|
size_t prev_size = m_vDescriptors.size();
|
2020-03-30 01:44:20 +02:00
|
|
|
|
2024-07-26 22:47:36 +02:00
|
|
|
for (const auto& it : m_vDescriptors) {
|
|
|
|
if (it->getUUID() == uuid) {
|
|
|
|
pDsc = it;
|
|
|
|
goto Done;
|
2020-05-23 18:27:32 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-07-26 22:47:36 +02:00
|
|
|
if (retrieveDescriptors(&uuid)) {
|
|
|
|
if (m_vDescriptors.size() > prev_size) {
|
|
|
|
pDsc = m_vDescriptors.back();
|
|
|
|
goto Done;
|
2020-05-23 18:27:32 +02:00
|
|
|
}
|
2020-12-28 23:40:01 +01:00
|
|
|
|
2022-01-18 22:48:07 +01:00
|
|
|
// If the request was successful but 16/32 bit uuid not found
|
2020-12-28 23:40:01 +01:00
|
|
|
// try again with the 128 bit uuid.
|
2024-07-26 22:47:36 +02:00
|
|
|
if (uuid.bitSize() == BLE_UUID_TYPE_16 || uuid.bitSize() == BLE_UUID_TYPE_32) {
|
2020-12-28 23:40:01 +01:00
|
|
|
NimBLEUUID uuid128(uuid);
|
|
|
|
uuid128.to128();
|
2024-07-26 22:47:36 +02:00
|
|
|
if (retrieveDescriptors(&uuid128)) {
|
|
|
|
if (m_vDescriptors.size() > prev_size) {
|
|
|
|
pDsc = m_vDescriptors.back();
|
2022-02-15 04:18:18 +01:00
|
|
|
}
|
|
|
|
}
|
2022-01-18 22:48:07 +01:00
|
|
|
} else {
|
|
|
|
// If the request was successful but the 128 bit uuid not found
|
|
|
|
// try again with the 16 bit uuid.
|
|
|
|
NimBLEUUID uuid16(uuid);
|
|
|
|
uuid16.to16();
|
|
|
|
// if the uuid was 128 bit but not of the BLE base type this check will fail
|
|
|
|
if (uuid16.bitSize() == BLE_UUID_TYPE_16) {
|
2024-07-26 22:47:36 +02:00
|
|
|
if (retrieveDescriptors(&uuid16)) {
|
|
|
|
if (m_vDescriptors.size() > prev_size) {
|
|
|
|
pDsc = m_vDescriptors.back();
|
2022-02-15 04:18:18 +01:00
|
|
|
}
|
|
|
|
}
|
2022-01-18 22:48:07 +01:00
|
|
|
}
|
2020-12-28 23:40:01 +01:00
|
|
|
}
|
2020-05-23 18:27:32 +02:00
|
|
|
}
|
2020-12-28 23:40:01 +01:00
|
|
|
|
2024-07-26 22:47:36 +02:00
|
|
|
Done:
|
|
|
|
NIMBLE_LOGD(LOG_TAG, "<< getDescriptor: %sfound", pDsc ? "" : "not ");
|
|
|
|
return pDsc;
|
2020-05-23 18:27:32 +02:00
|
|
|
} // getDescriptor
|
2020-03-30 01:44:20 +02:00
|
|
|
|
|
|
|
/**
|
2020-07-09 03:27:26 +02:00
|
|
|
* @brief Get a pointer to the vector of found descriptors.
|
|
|
|
* @param [in] refresh If true the current descriptor vector will be cleared and\n
|
|
|
|
* all descriptors for this characteristic retrieved from the peripheral.\n
|
|
|
|
* If false the vector will be returned with the currently stored descriptors
|
|
|
|
* of this characteristic.
|
|
|
|
* @return A pointer to the vector of descriptors for this characteristic.
|
2020-03-30 01:44:20 +02:00
|
|
|
*/
|
2024-07-26 22:47:36 +02:00
|
|
|
const std::vector<NimBLERemoteDescriptor*>& NimBLERemoteCharacteristic::getDescriptors(bool refresh) const {
|
|
|
|
if (refresh) {
|
2020-05-30 05:21:56 +02:00
|
|
|
deleteDescriptors();
|
2024-07-26 22:47:36 +02:00
|
|
|
retrieveDescriptors();
|
2020-05-23 18:27:32 +02:00
|
|
|
}
|
2020-03-30 01:44:20 +02:00
|
|
|
|
2024-07-26 22:47:36 +02:00
|
|
|
return m_vDescriptors;
|
|
|
|
} // getDescriptors
|
2020-03-30 01:44:20 +02:00
|
|
|
|
Add iterators to client remote attributes.
Add iterators for NimBLEScan: NimBLEadvertisedDevice, NimBLEClient: NimBLERemoteService, NimBLERemoteService: NimBLERemoteCharacteristic and NimBLERemoteCharacteristic: NimBLERemoteDescriptor
This is handy e.g. for showing every address of the advertised devices from a scan. To do so, first get a new scan and next:
```
for(auto pAdvertisedDevice: pBLEScan->getResults()) {
Serial.printf("Address is %s\n", std::string(pAdvertisedDevice->getAddress()).c_str());
}
```
Of course any other property of the advertised device can be shown (or looked up, if that is your use case)
Also this is handy e.g. for showing every UUID in a peripheral. To do so, first connect to a peripheral and next:
```
for(auto pService: *pClient) {
Serial.printf("Service UUID is %s\n", std::string(pService->getUUID()).c_str());
for(auto pCharacteristic: *pService) {
Serial.printf("Characteristic UUID is %s\n", std::string(pCharacteristic->getUUID()).c_str());
for(auto pDescriptor: *pCharacteristic) {
Serial.printf("Descriptor UUID is %s\n", std::string(pDescriptor->getUUID()).c_str());
}
}
}
```
Again of course any other property can be shown, or looked up.
2020-05-23 04:13:52 +02:00
|
|
|
/**
|
|
|
|
* @brief Get iterator to the beginning of the vector of remote descriptor pointers.
|
|
|
|
* @return An iterator to the beginning of the vector of remote descriptor pointers.
|
|
|
|
*/
|
2024-07-26 22:47:36 +02:00
|
|
|
std::vector<NimBLERemoteDescriptor*>::iterator NimBLERemoteCharacteristic::begin() const {
|
|
|
|
return m_vDescriptors.begin();
|
Add iterators to client remote attributes.
Add iterators for NimBLEScan: NimBLEadvertisedDevice, NimBLEClient: NimBLERemoteService, NimBLERemoteService: NimBLERemoteCharacteristic and NimBLERemoteCharacteristic: NimBLERemoteDescriptor
This is handy e.g. for showing every address of the advertised devices from a scan. To do so, first get a new scan and next:
```
for(auto pAdvertisedDevice: pBLEScan->getResults()) {
Serial.printf("Address is %s\n", std::string(pAdvertisedDevice->getAddress()).c_str());
}
```
Of course any other property of the advertised device can be shown (or looked up, if that is your use case)
Also this is handy e.g. for showing every UUID in a peripheral. To do so, first connect to a peripheral and next:
```
for(auto pService: *pClient) {
Serial.printf("Service UUID is %s\n", std::string(pService->getUUID()).c_str());
for(auto pCharacteristic: *pService) {
Serial.printf("Characteristic UUID is %s\n", std::string(pCharacteristic->getUUID()).c_str());
for(auto pDescriptor: *pCharacteristic) {
Serial.printf("Descriptor UUID is %s\n", std::string(pDescriptor->getUUID()).c_str());
}
}
}
```
Again of course any other property can be shown, or looked up.
2020-05-23 04:13:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Get iterator to the end of the vector of remote descriptor pointers.
|
|
|
|
* @return An iterator to the end of the vector of remote descriptor pointers.
|
|
|
|
*/
|
2024-07-26 22:47:36 +02:00
|
|
|
std::vector<NimBLERemoteDescriptor*>::iterator NimBLERemoteCharacteristic::end() const {
|
|
|
|
return m_vDescriptors.end();
|
Add iterators to client remote attributes.
Add iterators for NimBLEScan: NimBLEadvertisedDevice, NimBLEClient: NimBLERemoteService, NimBLERemoteService: NimBLERemoteCharacteristic and NimBLERemoteCharacteristic: NimBLERemoteDescriptor
This is handy e.g. for showing every address of the advertised devices from a scan. To do so, first get a new scan and next:
```
for(auto pAdvertisedDevice: pBLEScan->getResults()) {
Serial.printf("Address is %s\n", std::string(pAdvertisedDevice->getAddress()).c_str());
}
```
Of course any other property of the advertised device can be shown (or looked up, if that is your use case)
Also this is handy e.g. for showing every UUID in a peripheral. To do so, first connect to a peripheral and next:
```
for(auto pService: *pClient) {
Serial.printf("Service UUID is %s\n", std::string(pService->getUUID()).c_str());
for(auto pCharacteristic: *pService) {
Serial.printf("Characteristic UUID is %s\n", std::string(pCharacteristic->getUUID()).c_str());
for(auto pDescriptor: *pCharacteristic) {
Serial.printf("Descriptor UUID is %s\n", std::string(pDescriptor->getUUID()).c_str());
}
}
}
```
Again of course any other property can be shown, or looked up.
2020-05-23 04:13:52 +02:00
|
|
|
}
|
|
|
|
|
2020-03-30 01:44:20 +02:00
|
|
|
/**
|
|
|
|
* @brief Get the remote service associated with this characteristic.
|
|
|
|
* @return The remote service associated with this characteristic.
|
|
|
|
*/
|
2024-07-26 22:47:36 +02:00
|
|
|
const NimBLERemoteService* NimBLERemoteCharacteristic::getRemoteService() const {
|
2020-03-30 01:44:20 +02:00
|
|
|
return m_pRemoteService;
|
|
|
|
} // getRemoteService
|
|
|
|
|
|
|
|
/**
|
2020-06-19 20:29:30 +02:00
|
|
|
* @brief Subscribe or unsubscribe for notifications or indications.
|
2020-07-09 03:27:26 +02:00
|
|
|
* @param [in] val 0x00 to unsubscribe, 0x01 for notifications, 0x02 for indications.
|
|
|
|
* @param [in] notifyCallback A callback to be invoked for a notification.
|
2020-07-09 05:10:11 +02:00
|
|
|
* @param [in] response If write response required set this to true.
|
2020-07-09 03:27:26 +02:00
|
|
|
* If NULL is provided then no callback is performed.
|
2020-12-25 03:59:14 +01:00
|
|
|
* @return false if writing to the descriptor failed.
|
2020-03-30 01:44:20 +02:00
|
|
|
*/
|
2024-07-26 22:47:36 +02:00
|
|
|
bool NimBLERemoteCharacteristic::setNotify(uint16_t val, notify_callback notifyCallback, bool response) const {
|
|
|
|
NIMBLE_LOGD(LOG_TAG, ">> setNotify()");
|
2020-06-19 20:29:30 +02:00
|
|
|
|
2024-07-26 22:47:36 +02:00
|
|
|
m_notifyCallback = notifyCallback;
|
2020-06-19 20:29:30 +02:00
|
|
|
NimBLERemoteDescriptor* desc = getDescriptor(NimBLEUUID((uint16_t)0x2902));
|
2024-07-26 22:47:36 +02:00
|
|
|
if (desc == nullptr) {
|
2020-12-25 03:59:14 +01:00
|
|
|
NIMBLE_LOGW(LOG_TAG, "<< setNotify(): Callback set, CCCD not found");
|
|
|
|
return true;
|
2020-06-19 20:29:30 +02:00
|
|
|
}
|
2020-03-30 01:44:20 +02:00
|
|
|
|
2020-06-19 20:29:30 +02:00
|
|
|
NIMBLE_LOGD(LOG_TAG, "<< setNotify()");
|
2024-07-26 22:47:36 +02:00
|
|
|
return desc->writeValue(reinterpret_cast<uint8_t*>(&val), 2, response);
|
2020-06-19 20:29:30 +02:00
|
|
|
} // setNotify
|
2020-03-30 01:44:20 +02:00
|
|
|
|
2020-06-19 20:29:30 +02:00
|
|
|
/**
|
|
|
|
* @brief Subscribe for notifications or indications.
|
2020-07-09 03:27:26 +02:00
|
|
|
* @param [in] notifications If true, subscribe for notifications, false subscribe for indications.
|
|
|
|
* @param [in] notifyCallback A callback to be invoked for a notification.
|
2022-10-24 03:16:33 +02:00
|
|
|
* @param [in] response If true, require a write response from the descriptor write operation.
|
2020-07-09 03:27:26 +02:00
|
|
|
* If NULL is provided then no callback is performed.
|
2020-12-25 03:59:14 +01:00
|
|
|
* @return false if writing to the descriptor failed.
|
2020-06-19 20:29:30 +02:00
|
|
|
*/
|
2024-07-26 22:47:36 +02:00
|
|
|
bool NimBLERemoteCharacteristic::subscribe(bool notifications, notify_callback notifyCallback, bool response) const {
|
|
|
|
return setNotify(notifications ? 0x01 : 0x02, notifyCallback, response);
|
2020-06-19 20:29:30 +02:00
|
|
|
} // subscribe
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Unsubscribe for notifications or indications.
|
2020-07-09 03:27:26 +02:00
|
|
|
* @param [in] response bool if true, require a write response from the descriptor write operation.
|
2020-12-25 03:59:14 +01:00
|
|
|
* @return false if writing to the descriptor failed.
|
2020-06-19 20:29:30 +02:00
|
|
|
*/
|
2024-07-26 22:47:36 +02:00
|
|
|
bool NimBLERemoteCharacteristic::unsubscribe(bool response) const {
|
2022-10-24 03:16:33 +02:00
|
|
|
return setNotify(0x00, nullptr, response);
|
2020-06-19 20:29:30 +02:00
|
|
|
} // unsubscribe
|
2020-03-30 01:44:20 +02:00
|
|
|
|
|
|
|
/**
|
2020-05-18 04:21:35 +02:00
|
|
|
* @brief Delete the descriptors in the descriptor vector.
|
2024-07-26 22:47:36 +02:00
|
|
|
* @details We maintain a vector called m_vDescriptors that contains pointers to NimBLERemoteDescriptors
|
2020-05-30 02:26:41 +02:00
|
|
|
* object references. Since we allocated these in this class, we are also responsible for deleting
|
2020-05-18 04:21:35 +02:00
|
|
|
* them. This method does just that.
|
2020-03-30 01:44:20 +02:00
|
|
|
*/
|
2024-07-26 22:47:36 +02:00
|
|
|
void NimBLERemoteCharacteristic::deleteDescriptors() const {
|
2020-05-30 05:21:56 +02:00
|
|
|
NIMBLE_LOGD(LOG_TAG, ">> deleteDescriptors");
|
2020-06-22 06:07:01 +02:00
|
|
|
|
2024-07-26 22:47:36 +02:00
|
|
|
for (const auto& it : m_vDescriptors) {
|
2020-05-18 04:21:35 +02:00
|
|
|
delete it;
|
2020-03-30 01:44:20 +02:00
|
|
|
}
|
2024-07-26 22:47:36 +02:00
|
|
|
std::vector<NimBLERemoteDescriptor*>().swap(m_vDescriptors);
|
|
|
|
|
2020-05-30 05:21:56 +02:00
|
|
|
NIMBLE_LOGD(LOG_TAG, "<< deleteDescriptors");
|
|
|
|
} // deleteDescriptors
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Delete descriptor by UUID
|
|
|
|
* @param [in] uuid The UUID of the descriptor to be deleted.
|
2020-07-09 03:27:26 +02:00
|
|
|
* @return Number of descriptors left in the vector.
|
2020-05-30 05:21:56 +02:00
|
|
|
*/
|
2024-07-26 22:47:36 +02:00
|
|
|
size_t NimBLERemoteCharacteristic::deleteDescriptor(const NimBLEUUID& uuid) const {
|
2020-05-30 05:21:56 +02:00
|
|
|
NIMBLE_LOGD(LOG_TAG, ">> deleteDescriptor");
|
2020-06-22 06:07:01 +02:00
|
|
|
|
2024-07-26 22:47:36 +02:00
|
|
|
for (auto it = m_vDescriptors.begin(); it != m_vDescriptors.end(); ++it) {
|
|
|
|
if ((*it)->getUUID() == uuid) {
|
|
|
|
delete (*it);
|
|
|
|
m_vDescriptors.erase(it);
|
2020-05-30 05:21:56 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
NIMBLE_LOGD(LOG_TAG, "<< deleteDescriptor");
|
2024-07-26 22:47:36 +02:00
|
|
|
return m_vDescriptors.size();
|
2020-05-30 05:21:56 +02:00
|
|
|
} // deleteDescriptor
|
2020-03-30 01:44:20 +02:00
|
|
|
|
2024-07-26 22:47:36 +02:00
|
|
|
/**
|
|
|
|
* @brief Does the characteristic support value broadcasting?
|
|
|
|
* @return True if supported.
|
|
|
|
*/
|
|
|
|
bool NimBLERemoteCharacteristic::canBroadcast() const {
|
|
|
|
return (m_properties & BLE_GATT_CHR_PROP_BROADCAST) != 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Does the characteristic support reading?
|
|
|
|
* @return True if supported.
|
|
|
|
*/
|
|
|
|
bool NimBLERemoteCharacteristic::canRead() const {
|
|
|
|
return (m_properties & BLE_GATT_CHR_PROP_READ);
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Does the characteristic support writing without a response?
|
|
|
|
* @return True if supported.
|
|
|
|
*/
|
|
|
|
bool NimBLERemoteCharacteristic::canWriteNoResponse() const {
|
|
|
|
return (m_properties & BLE_GATT_CHR_PROP_WRITE_NO_RSP);
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Does the characteristic support writing?
|
|
|
|
* @return True if supported.
|
|
|
|
*/
|
|
|
|
bool NimBLERemoteCharacteristic::canWrite() const {
|
|
|
|
return (m_properties & BLE_GATT_CHR_PROP_WRITE);
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Does the characteristic support reading with encryption?
|
|
|
|
* @return True if supported.
|
|
|
|
*/
|
|
|
|
bool NimBLERemoteCharacteristic::canNotify() const {
|
|
|
|
return (m_properties & BLE_GATT_CHR_PROP_NOTIFY);
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Does the characteristic support indication?
|
|
|
|
* @return True if supported.
|
|
|
|
*/
|
|
|
|
bool NimBLERemoteCharacteristic::canIndicate() const {
|
|
|
|
return (m_properties & BLE_GATT_CHR_PROP_INDICATE);
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Does the characteristic support signed writing?
|
|
|
|
* @return True if supported.
|
|
|
|
*/
|
|
|
|
bool NimBLERemoteCharacteristic::canWriteSigned() const {
|
|
|
|
return (m_properties & BLE_GATT_CHR_PROP_AUTH_SIGN_WRITE);
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Does the characteristic support extended properties?
|
|
|
|
* @return True if supported.
|
|
|
|
*/
|
|
|
|
bool NimBLERemoteCharacteristic::hasExtendedProps() const {
|
|
|
|
return (m_properties & BLE_GATT_CHR_PROP_EXTENDED);
|
|
|
|
};
|
2020-03-30 01:44:20 +02:00
|
|
|
|
|
|
|
/**
|
2020-07-09 03:27:26 +02:00
|
|
|
* @brief Convert a NimBLERemoteCharacteristic to a string representation;
|
2020-03-30 01:44:20 +02:00
|
|
|
* @return a String representation.
|
|
|
|
*/
|
2024-07-26 22:47:36 +02:00
|
|
|
std::string NimBLERemoteCharacteristic::toString() const {
|
2020-03-30 01:44:20 +02:00
|
|
|
std::string res = "Characteristic: uuid: " + m_uuid.toString();
|
2024-07-26 22:47:36 +02:00
|
|
|
char val[6];
|
2020-03-30 01:44:20 +02:00
|
|
|
res += ", handle: ";
|
|
|
|
snprintf(val, sizeof(val), "%d", getHandle());
|
|
|
|
res += val;
|
|
|
|
res += " 0x";
|
|
|
|
snprintf(val, sizeof(val), "%04x", getHandle());
|
|
|
|
res += val;
|
|
|
|
res += ", props: ";
|
|
|
|
res += " 0x";
|
2024-07-26 22:47:36 +02:00
|
|
|
snprintf(val, sizeof(val), "%02x", m_properties);
|
2020-03-30 01:44:20 +02:00
|
|
|
res += val;
|
2020-05-14 06:03:56 +02:00
|
|
|
|
2024-07-26 22:47:36 +02:00
|
|
|
for (const auto& it : m_vDescriptors) {
|
2020-05-18 04:21:35 +02:00
|
|
|
res += "\n" + it->toString();
|
2020-03-30 01:44:20 +02:00
|
|
|
}
|
2020-05-14 06:03:56 +02:00
|
|
|
|
2020-03-30 01:44:20 +02:00
|
|
|
return res;
|
|
|
|
} // toString
|
|
|
|
|
2024-07-26 22:47:36 +02:00
|
|
|
NimBLEClient* NimBLERemoteCharacteristic::getClient() const {
|
|
|
|
return getRemoteService()->getClient();
|
|
|
|
} // getClient
|
2020-03-30 01:44:20 +02:00
|
|
|
|
2021-09-07 05:14:43 +02:00
|
|
|
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */
|