2020-03-29 17:44:20 -06:00
|
|
|
/*
|
|
|
|
* NimBLECharacteristic.cpp
|
|
|
|
*
|
|
|
|
* Created: on March 3, 2020
|
|
|
|
* Author H2zero
|
2020-05-13 22:03:56 -06:00
|
|
|
*
|
2020-03-29 17:44:20 -06:00
|
|
|
* BLECharacteristic.cpp
|
|
|
|
*
|
|
|
|
* Created on: Jun 22, 2017
|
|
|
|
* Author: kolban
|
|
|
|
*/
|
|
|
|
|
2020-05-13 22:03:56 -06:00
|
|
|
#include "nimconfig.h"
|
2021-09-06 21:14:43 -06:00
|
|
|
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
2020-05-13 22:03:56 -06:00
|
|
|
|
2024-07-26 14:47:36 -06:00
|
|
|
# include "NimBLECharacteristic.h"
|
|
|
|
# include "NimBLE2904.h"
|
|
|
|
# include "NimBLEDevice.h"
|
|
|
|
# include "NimBLELog.h"
|
2020-03-29 17:44:20 -06:00
|
|
|
|
2024-07-26 14:47:36 -06:00
|
|
|
# define NIMBLE_SUB_NOTIFY 0x0001
|
|
|
|
# define NIMBLE_SUB_INDICATE 0x0002
|
2020-03-29 17:44:20 -06:00
|
|
|
|
|
|
|
static NimBLECharacteristicCallbacks defaultCallback;
|
2024-07-26 14:47:36 -06:00
|
|
|
static const char* LOG_TAG = "NimBLECharacteristic";
|
2020-07-27 21:11:38 -06:00
|
|
|
|
2020-03-29 17:44:20 -06:00
|
|
|
/**
|
|
|
|
* @brief Construct a characteristic
|
|
|
|
* @param [in] uuid - UUID (const char*) for the characteristic.
|
|
|
|
* @param [in] properties - Properties for the characteristic.
|
2022-01-16 20:11:18 -07:00
|
|
|
* @param [in] max_len - The maximum length in bytes that the characteristic value can hold. (Default: 512 bytes for esp32, 20 for all others).
|
2020-06-07 18:42:28 -06:00
|
|
|
* @param [in] pService - pointer to the service instance this characteristic belongs to.
|
2020-03-29 17:44:20 -06:00
|
|
|
*/
|
2024-07-26 14:47:36 -06:00
|
|
|
NimBLECharacteristic::NimBLECharacteristic(const char* uuid, uint16_t properties, uint16_t max_len, NimBLEService* pService)
|
|
|
|
: NimBLECharacteristic(NimBLEUUID(uuid), properties, max_len, pService) {}
|
2020-03-29 17:44:20 -06:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Construct a characteristic
|
|
|
|
* @param [in] uuid - UUID for the characteristic.
|
|
|
|
* @param [in] properties - Properties for the characteristic.
|
2022-01-16 20:11:18 -07:00
|
|
|
* @param [in] max_len - The maximum length in bytes that the characteristic value can hold. (Default: 512 bytes for esp32, 20 for all others).
|
2020-06-07 18:42:28 -06:00
|
|
|
* @param [in] pService - pointer to the service instance this characteristic belongs to.
|
2020-03-29 17:44:20 -06:00
|
|
|
*/
|
2024-07-26 14:47:36 -06:00
|
|
|
NimBLECharacteristic::NimBLECharacteristic(const NimBLEUUID& uuid, uint16_t properties, uint16_t max_len, NimBLEService* pService)
|
|
|
|
: NimBLELocalValueAttribute{uuid, 0, max_len}, m_pCallbacks{&defaultCallback}, m_pService{pService} {
|
|
|
|
setProperties(properties);
|
2020-03-29 17:44:20 -06:00
|
|
|
} // NimBLECharacteristic
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Destructor.
|
|
|
|
*/
|
|
|
|
NimBLECharacteristic::~NimBLECharacteristic() {
|
2024-07-26 14:47:36 -06:00
|
|
|
for (const auto& dsc : m_vDescriptors) {
|
|
|
|
delete dsc;
|
2020-07-13 21:24:07 -06:00
|
|
|
}
|
2020-06-07 18:42:28 -06:00
|
|
|
} // ~NimBLECharacteristic
|
2020-03-29 17:44:20 -06:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Create a new BLE Descriptor associated with this characteristic.
|
|
|
|
* @param [in] uuid - The UUID of the descriptor.
|
|
|
|
* @param [in] properties - The properties of the descriptor.
|
2020-07-08 19:27:26 -06:00
|
|
|
* @param [in] max_len - The max length in bytes of the descriptor value.
|
2020-03-29 17:44:20 -06:00
|
|
|
* @return The new BLE descriptor.
|
|
|
|
*/
|
|
|
|
NimBLEDescriptor* NimBLECharacteristic::createDescriptor(const char* uuid, uint32_t properties, uint16_t max_len) {
|
2020-05-13 22:03:56 -06:00
|
|
|
return createDescriptor(NimBLEUUID(uuid), properties, max_len);
|
2020-03-29 17:44:20 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Create a new BLE Descriptor associated with this characteristic.
|
|
|
|
* @param [in] uuid - The UUID of the descriptor.
|
|
|
|
* @param [in] properties - The properties of the descriptor.
|
2020-07-08 19:27:26 -06:00
|
|
|
* @param [in] max_len - The max length in bytes of the descriptor value.
|
2020-03-29 17:44:20 -06:00
|
|
|
* @return The new BLE descriptor.
|
|
|
|
*/
|
2024-07-26 14:47:36 -06:00
|
|
|
NimBLEDescriptor* NimBLECharacteristic::createDescriptor(const NimBLEUUID& uuid, uint32_t properties, uint16_t max_len) {
|
2020-05-13 22:03:56 -06:00
|
|
|
NimBLEDescriptor* pDescriptor = nullptr;
|
2024-07-03 14:03:12 -06:00
|
|
|
if (uuid == NimBLEUUID(uint16_t(0x2904))) {
|
2020-05-13 22:03:56 -06:00
|
|
|
pDescriptor = new NimBLE2904(this);
|
|
|
|
} else {
|
|
|
|
pDescriptor = new NimBLEDescriptor(uuid, properties, max_len, this);
|
|
|
|
}
|
2020-06-07 18:42:28 -06:00
|
|
|
|
2021-05-23 13:07:00 -06:00
|
|
|
addDescriptor(pDescriptor);
|
2020-05-13 22:03:56 -06:00
|
|
|
return pDescriptor;
|
2021-05-23 13:07:00 -06:00
|
|
|
} // createDescriptor
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Add a descriptor to the characteristic.
|
2021-07-30 20:56:52 -06:00
|
|
|
* @param [in] pDescriptor A pointer to the descriptor to add.
|
2021-05-23 13:07:00 -06:00
|
|
|
*/
|
2024-07-26 14:47:36 -06:00
|
|
|
void NimBLECharacteristic::addDescriptor(NimBLEDescriptor* pDescriptor) {
|
2021-07-30 20:56:52 -06:00
|
|
|
bool foundRemoved = false;
|
2024-07-26 14:47:36 -06:00
|
|
|
if (pDescriptor->getRemoved() > 0) {
|
|
|
|
for (const auto& dsc : m_vDescriptors) {
|
|
|
|
if (dsc == pDescriptor) {
|
2021-07-30 20:56:52 -06:00
|
|
|
foundRemoved = true;
|
2024-07-26 14:47:36 -06:00
|
|
|
pDescriptor->setRemoved(0);
|
2021-07-30 20:56:52 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-07-26 14:47:36 -06:00
|
|
|
// Check if the descriptor is already in the vector and if so, return.
|
|
|
|
for (const auto& dsc : m_vDescriptors) {
|
|
|
|
if (dsc == pDescriptor) {
|
|
|
|
pDescriptor->setCharacteristic(this); // Update the characteristic pointer in the descriptor.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!foundRemoved) {
|
|
|
|
m_vDescriptors.push_back(pDescriptor);
|
2021-07-30 20:56:52 -06:00
|
|
|
}
|
|
|
|
|
2021-05-23 13:07:00 -06:00
|
|
|
pDescriptor->setCharacteristic(this);
|
2021-07-30 20:56:52 -06:00
|
|
|
NimBLEDevice::getServer()->serviceChanged();
|
2021-05-23 13:07:00 -06:00
|
|
|
}
|
2020-03-29 17:44:20 -06:00
|
|
|
|
2021-07-30 20:56:52 -06:00
|
|
|
/**
|
2022-07-31 11:00:12 -06:00
|
|
|
* @brief Remove a descriptor from the characteristic.
|
|
|
|
* @param[in] pDescriptor A pointer to the descriptor instance to remove from the characteristic.
|
2021-07-30 20:56:52 -06:00
|
|
|
* @param[in] deleteDsc If true it will delete the descriptor instance and free it's resources.
|
|
|
|
*/
|
2024-07-26 14:47:36 -06:00
|
|
|
void NimBLECharacteristic::removeDescriptor(NimBLEDescriptor* pDescriptor, bool deleteDsc) {
|
2021-07-30 20:56:52 -06:00
|
|
|
// Check if the descriptor was already removed and if so, check if this
|
|
|
|
// is being called to delete the object and do so if requested.
|
|
|
|
// Otherwise, ignore the call and return.
|
2024-07-26 14:47:36 -06:00
|
|
|
if (pDescriptor->getRemoved() > 0) {
|
|
|
|
if (deleteDsc) {
|
|
|
|
for (auto it = m_vDescriptors.begin(); it != m_vDescriptors.end(); ++it) {
|
2021-07-30 20:56:52 -06:00
|
|
|
if ((*it) == pDescriptor) {
|
2024-07-26 14:47:36 -06:00
|
|
|
delete (*it);
|
|
|
|
m_vDescriptors.erase(it);
|
2021-07-30 20:56:52 -06:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-07-26 14:47:36 -06:00
|
|
|
pDescriptor->setRemoved(deleteDsc ? NIMBLE_ATT_REMOVE_DELETE : NIMBLE_ATT_REMOVE_HIDE);
|
2021-07-30 20:56:52 -06:00
|
|
|
NimBLEDevice::getServer()->serviceChanged();
|
|
|
|
} // removeDescriptor
|
|
|
|
|
2020-03-29 17:44:20 -06:00
|
|
|
/**
|
2021-02-08 15:28:32 +00:00
|
|
|
* @brief Return the BLE Descriptor for the given UUID.
|
|
|
|
* @param [in] uuid The UUID of the descriptor.
|
|
|
|
* @return A pointer to the descriptor object or nullptr if not found.
|
2020-03-29 17:44:20 -06:00
|
|
|
*/
|
2024-07-26 14:47:36 -06:00
|
|
|
NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(const char* uuid) const {
|
2020-06-07 18:42:28 -06:00
|
|
|
return getDescriptorByUUID(NimBLEUUID(uuid));
|
2020-03-29 17:44:20 -06:00
|
|
|
} // getDescriptorByUUID
|
|
|
|
|
|
|
|
/**
|
2021-02-08 15:28:32 +00:00
|
|
|
* @brief Return the BLE Descriptor for the given UUID.
|
|
|
|
* @param [in] uuid The UUID of the descriptor.
|
|
|
|
* @return A pointer to the descriptor object or nullptr if not found.
|
2020-03-29 17:44:20 -06:00
|
|
|
*/
|
2024-07-26 14:47:36 -06:00
|
|
|
NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(const NimBLEUUID& uuid) const {
|
|
|
|
for (const auto& dsc : m_vDescriptors) {
|
|
|
|
if (dsc->getUUID() == uuid) {
|
|
|
|
return dsc;
|
2020-06-07 18:42:28 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return nullptr;
|
2020-03-29 17:44:20 -06:00
|
|
|
} // getDescriptorByUUID
|
|
|
|
|
2021-02-08 15:28:32 +00:00
|
|
|
/**
|
|
|
|
* @brief Return the BLE Descriptor for the given handle.
|
2021-02-08 11:46:11 -07:00
|
|
|
* @param [in] handle The handle of the descriptor.
|
2021-02-08 15:28:32 +00:00
|
|
|
* @return A pointer to the descriptor object or nullptr if not found.
|
|
|
|
*/
|
2024-07-26 14:47:36 -06:00
|
|
|
NimBLEDescriptor* NimBLECharacteristic::getDescriptorByHandle(uint16_t handle) const {
|
|
|
|
for (const auto& dsc : m_vDescriptors) {
|
|
|
|
if (dsc->getHandle() == handle) {
|
|
|
|
return dsc;
|
2021-02-08 15:28:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return nullptr;
|
2024-07-26 14:47:36 -06:00
|
|
|
} // getDescriptorByHandle
|
2020-03-29 17:44:20 -06:00
|
|
|
|
2020-07-08 19:27:26 -06:00
|
|
|
/**
|
|
|
|
* @brief Get the properties of the characteristic.
|
|
|
|
* @return The properties of the characteristic.
|
|
|
|
*/
|
2024-07-26 14:47:36 -06:00
|
|
|
uint16_t NimBLECharacteristic::getProperties() const {
|
2020-05-13 22:03:56 -06:00
|
|
|
return m_properties;
|
2020-03-29 17:44:20 -06:00
|
|
|
} // getProperties
|
|
|
|
|
|
|
|
/**
|
2024-07-26 14:47:36 -06:00
|
|
|
* @brief Get the service that owns this characteristic.
|
2020-03-29 17:44:20 -06:00
|
|
|
*/
|
2024-07-26 14:47:36 -06:00
|
|
|
NimBLEService* NimBLECharacteristic::getService() const {
|
2020-05-13 22:03:56 -06:00
|
|
|
return m_pService;
|
2020-03-29 17:44:20 -06:00
|
|
|
} // getService
|
|
|
|
|
2024-07-26 14:47:36 -06:00
|
|
|
void NimBLECharacteristic::setService(NimBLEService* pService) {
|
2021-05-23 13:07:00 -06:00
|
|
|
m_pService = pService;
|
2024-07-26 14:47:36 -06:00
|
|
|
} // setService
|
2020-03-29 17:44:20 -06:00
|
|
|
|
2020-07-27 21:11:38 -06:00
|
|
|
/**
|
|
|
|
* @brief Get the number of clients subscribed to the characteristic.
|
|
|
|
* @returns Number of clients subscribed to notifications / indications.
|
|
|
|
*/
|
2024-07-26 14:47:36 -06:00
|
|
|
size_t NimBLECharacteristic::getSubscribedCount() const {
|
2020-07-27 21:11:38 -06:00
|
|
|
return m_subscribedVec.size();
|
|
|
|
}
|
|
|
|
|
2020-03-29 17:44:20 -06:00
|
|
|
/**
|
2020-07-08 19:27:26 -06:00
|
|
|
* @brief Set the subscribe status for this characteristic.\n
|
|
|
|
* This will maintain a vector of subscribed clients and their indicate/notify status.
|
2020-03-29 17:44:20 -06:00
|
|
|
*/
|
2024-07-26 14:47:36 -06:00
|
|
|
void NimBLECharacteristic::setSubscribe(const ble_gap_event* event, NimBLEConnInfo& connInfo) {
|
2020-03-29 17:44:20 -06:00
|
|
|
uint16_t subVal = 0;
|
2024-07-26 14:47:36 -06:00
|
|
|
if (event->subscribe.cur_notify > 0 && (m_properties & NIMBLE_PROPERTY::NOTIFY)) {
|
2020-07-27 21:11:38 -06:00
|
|
|
subVal |= NIMBLE_SUB_NOTIFY;
|
2020-03-29 17:44:20 -06:00
|
|
|
}
|
2024-07-26 14:47:36 -06:00
|
|
|
if (event->subscribe.cur_indicate && (m_properties & NIMBLE_PROPERTY::INDICATE)) {
|
2020-07-27 21:11:38 -06:00
|
|
|
subVal |= NIMBLE_SUB_INDICATE;
|
2020-03-29 17:44:20 -06:00
|
|
|
}
|
2020-05-13 22:03:56 -06:00
|
|
|
|
2024-07-26 14:47:36 -06:00
|
|
|
NIMBLE_LOGI(LOG_TAG, "New subscribe value for conn: %d val: %d", connInfo.getConnHandle(), subVal);
|
2021-05-17 14:08:02 -06:00
|
|
|
|
2024-07-26 14:47:36 -06:00
|
|
|
if (!event->subscribe.cur_indicate && event->subscribe.prev_indicate) {
|
|
|
|
NimBLEDevice::getServer()->clearIndicateWait(connInfo.getConnHandle());
|
2021-05-17 14:08:02 -06:00
|
|
|
}
|
2020-05-13 22:03:56 -06:00
|
|
|
|
2020-07-27 21:11:38 -06:00
|
|
|
auto it = m_subscribedVec.begin();
|
2024-07-26 14:47:36 -06:00
|
|
|
for (; it != m_subscribedVec.end(); ++it) {
|
|
|
|
if ((*it).first == connInfo.getConnHandle()) {
|
2020-06-07 18:42:28 -06:00
|
|
|
break;
|
|
|
|
}
|
2020-03-29 17:44:20 -06:00
|
|
|
}
|
2020-06-07 18:42:28 -06:00
|
|
|
|
2024-07-26 14:47:36 -06:00
|
|
|
if (subVal > 0) {
|
|
|
|
if (it == m_subscribedVec.end()) {
|
|
|
|
m_subscribedVec.push_back({connInfo.getConnHandle(), subVal});
|
2021-05-19 22:27:32 -06:00
|
|
|
} else {
|
|
|
|
(*it).second = subVal;
|
2020-06-07 18:42:28 -06:00
|
|
|
}
|
2024-07-26 14:47:36 -06:00
|
|
|
} else if (it != m_subscribedVec.end()) {
|
2020-07-27 21:11:38 -06:00
|
|
|
m_subscribedVec.erase(it);
|
2020-03-29 17:44:20 -06:00
|
|
|
}
|
2021-05-19 22:27:32 -06:00
|
|
|
|
2024-07-26 14:47:36 -06:00
|
|
|
m_pCallbacks->onSubscribe(this, connInfo, subVal);
|
2020-03-29 17:44:20 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2022-01-16 20:11:18 -07:00
|
|
|
* @brief Send an indication.
|
2024-07-26 14:47:36 -06:00
|
|
|
* @param[in] conn_handle Connection handle to send an individual indication, or BLE_HS_CONN_HANDLE_NONE to send
|
|
|
|
* the indication to all subscribed clients.
|
2020-03-29 17:44:20 -06:00
|
|
|
*/
|
2024-07-26 14:47:36 -06:00
|
|
|
void NimBLECharacteristic::indicate(uint16_t conn_handle) const {
|
|
|
|
sendValue(m_value.data(), m_value.size(), false, conn_handle);
|
2020-03-29 17:44:20 -06:00
|
|
|
} // indicate
|
2020-05-13 22:03:56 -06:00
|
|
|
|
2020-03-29 17:44:20 -06:00
|
|
|
/**
|
2022-01-16 20:11:18 -07:00
|
|
|
* @brief Send an indication.
|
|
|
|
* @param[in] value A pointer to the data to send.
|
|
|
|
* @param[in] length The length of the data to send.
|
2024-07-26 14:47:36 -06:00
|
|
|
* @param[in] conn_handle Connection handle to send an individual indication, or BLE_HS_CONN_HANDLE_NONE to send
|
|
|
|
* the indication to all subscribed clients.
|
2022-01-16 20:11:18 -07:00
|
|
|
*/
|
2024-07-26 14:47:36 -06:00
|
|
|
void NimBLECharacteristic::indicate(const uint8_t* value, size_t length, uint16_t conn_handle) const {
|
|
|
|
sendValue(value, length, false, conn_handle);
|
2022-01-16 20:11:18 -07:00
|
|
|
} // indicate
|
|
|
|
|
|
|
|
/**
|
2024-07-26 14:47:36 -06:00
|
|
|
* @brief Send a notification.
|
|
|
|
* @param[in] conn_handle Connection handle to send an individual notification, or BLE_HS_CONN_HANDLE_NONE to send
|
|
|
|
* the notification to all subscribed clients.
|
2020-03-29 17:44:20 -06:00
|
|
|
*/
|
2024-07-26 14:47:36 -06:00
|
|
|
void NimBLECharacteristic::notify(uint16_t conn_handle) const {
|
|
|
|
sendValue(m_value.data(), m_value.size(), true, conn_handle);
|
2022-01-16 20:11:18 -07:00
|
|
|
} // notify
|
|
|
|
|
2024-07-26 14:47:36 -06:00
|
|
|
/**
|
|
|
|
* @brief Send a notification.
|
|
|
|
* @param[in] value A pointer to the data to send.
|
|
|
|
* @param[in] length The length of the data to send.
|
|
|
|
* @param[in] conn_handle Connection handle to send an individual notification, or BLE_HS_CONN_HANDLE_NONE to send
|
|
|
|
* the notification to all subscribed clients.
|
|
|
|
*/
|
|
|
|
void NimBLECharacteristic::notify(const uint8_t* value, size_t length, uint16_t conn_handle) const {
|
|
|
|
sendValue(value, length, true, conn_handle);
|
|
|
|
} // indicate
|
2022-01-16 20:11:18 -07:00
|
|
|
|
2021-12-29 03:11:37 +00:00
|
|
|
/**
|
2024-07-26 14:47:36 -06:00
|
|
|
* @brief Sends a notification or indication.
|
2022-01-16 20:11:18 -07:00
|
|
|
* @param[in] value A pointer to the data to send.
|
|
|
|
* @param[in] length The length of the data to send.
|
2021-12-29 03:11:37 +00:00
|
|
|
* @param[in] is_notification if true sends a notification, false sends an indication.
|
2024-07-26 14:47:36 -06:00
|
|
|
* @param[in] conn_handle Connection handle to send to a specific peer, or BLE_HS_CONN_HANDLE_NONE to send
|
|
|
|
* to all subscribed clients.
|
2021-12-29 03:11:37 +00:00
|
|
|
*/
|
2024-07-26 14:47:36 -06:00
|
|
|
void NimBLECharacteristic::sendValue(const uint8_t* value, size_t length, bool is_notification, uint16_t conn_handle) const {
|
|
|
|
NIMBLE_LOGD(LOG_TAG, ">> sendValue");
|
|
|
|
|
|
|
|
if (is_notification && !(getProperties() & NIMBLE_PROPERTY::NOTIFY)) {
|
|
|
|
NIMBLE_LOGE(LOG_TAG, "<< sendValue: notification not enabled for characteristic");
|
|
|
|
return;
|
2020-06-07 18:42:28 -06:00
|
|
|
}
|
2020-03-29 17:44:20 -06:00
|
|
|
|
2024-07-26 14:47:36 -06:00
|
|
|
if (!is_notification && !(getProperties() & NIMBLE_PROPERTY::INDICATE)) {
|
|
|
|
NIMBLE_LOGE(LOG_TAG, "<< sendValue: indication not enabled for characteristic");
|
2020-05-13 22:03:56 -06:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-07-26 14:47:36 -06:00
|
|
|
if (!m_subscribedVec.size()) {
|
|
|
|
NIMBLE_LOGD(LOG_TAG, "<< sendValue: No clients subscribed.");
|
|
|
|
return;
|
|
|
|
}
|
2021-12-29 08:10:57 -07:00
|
|
|
|
2024-07-26 14:47:36 -06:00
|
|
|
for (const auto& it : m_subscribedVec) {
|
|
|
|
// check if connected and subscribed
|
|
|
|
if (!it.second) {
|
|
|
|
continue;
|
|
|
|
}
|
2020-05-13 22:03:56 -06:00
|
|
|
|
2024-07-26 14:47:36 -06:00
|
|
|
// sending to a specific client?
|
2022-09-12 05:18:55 +03:00
|
|
|
if ((conn_handle <= BLE_HCI_LE_CONN_HANDLE_MAX) && (it.first != conn_handle)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2024-07-26 14:47:36 -06:00
|
|
|
if (is_notification && !(it.second & NIMBLE_SUB_NOTIFY)) {
|
|
|
|
continue;
|
|
|
|
}
|
2020-05-13 22:03:56 -06:00
|
|
|
|
2024-07-26 14:47:36 -06:00
|
|
|
if (!is_notification && !(it.second & NIMBLE_SUB_INDICATE)) {
|
2020-03-29 17:44:20 -06:00
|
|
|
continue;
|
|
|
|
}
|
2020-05-13 22:03:56 -06:00
|
|
|
|
2020-06-21 20:26:16 -06:00
|
|
|
// check if security requirements are satisfied
|
2024-07-26 14:47:36 -06:00
|
|
|
if ((getProperties() & BLE_GATT_CHR_F_READ_AUTHEN) || (getProperties() & BLE_GATT_CHR_F_READ_AUTHOR) ||
|
|
|
|
(getProperties() & BLE_GATT_CHR_F_READ_ENC)) {
|
|
|
|
ble_gap_conn_desc desc;
|
|
|
|
if (ble_gap_conn_find(it.first, &desc) != 0 || !desc.sec_state.encrypted) {
|
2020-06-21 20:26:16 -06:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-29 17:44:20 -06:00
|
|
|
// don't create the m_buf until we are sure to send the data or else
|
|
|
|
// we could be allocating a buffer that doesn't get released.
|
|
|
|
// We also must create it in each loop iteration because it is consumed with each host call.
|
2024-07-26 14:47:36 -06:00
|
|
|
os_mbuf* om = ble_hs_mbuf_from_flat(value, length);
|
|
|
|
if (!om) {
|
|
|
|
NIMBLE_LOGE(LOG_TAG, "<< sendValue: failed to allocate mbuf");
|
|
|
|
return;
|
|
|
|
}
|
2020-05-13 22:03:56 -06:00
|
|
|
|
2024-07-26 14:47:36 -06:00
|
|
|
if (is_notification) {
|
|
|
|
ble_gattc_notify_custom(it.first, getHandle(), om);
|
|
|
|
} else {
|
|
|
|
if (!NimBLEDevice::getServer()->setIndicateWait(it.first)) {
|
|
|
|
NIMBLE_LOGE(LOG_TAG, "<< sendValue: waiting for previous indicate");
|
|
|
|
os_mbuf_free_chain(om);
|
|
|
|
return;
|
2021-05-17 14:08:02 -06:00
|
|
|
}
|
2020-06-11 08:06:16 -06:00
|
|
|
|
2024-07-26 14:47:36 -06:00
|
|
|
if (ble_gattc_indicate_custom(it.first, getHandle(), om) != 0) {
|
2021-05-17 14:08:02 -06:00
|
|
|
NimBLEDevice::getServer()->clearIndicateWait(it.first);
|
2020-03-29 17:44:20 -06:00
|
|
|
}
|
|
|
|
}
|
2020-05-13 22:03:56 -06:00
|
|
|
}
|
2020-03-29 17:44:20 -06:00
|
|
|
|
2024-07-26 14:47:36 -06:00
|
|
|
NIMBLE_LOGD(LOG_TAG, "<< sendValue");
|
|
|
|
} // sendValue
|
2020-03-29 17:44:20 -06:00
|
|
|
|
2024-07-26 14:47:36 -06:00
|
|
|
void NimBLECharacteristic::readEvent(NimBLEConnInfo& connInfo) {
|
|
|
|
m_pCallbacks->onRead(this, connInfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
void NimBLECharacteristic::writeEvent(const uint8_t* val, uint16_t len, NimBLEConnInfo& connInfo) {
|
|
|
|
setValue(val, len);
|
|
|
|
m_pCallbacks->onWrite(this, connInfo);
|
|
|
|
}
|
2020-03-29 17:44:20 -06:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Set the callback handlers for this characteristic.
|
2020-07-08 19:27:26 -06:00
|
|
|
* @param [in] pCallbacks An instance of a NimBLECharacteristicCallbacks class\n
|
|
|
|
* used to define any callbacks for the characteristic.
|
2020-03-29 17:44:20 -06:00
|
|
|
*/
|
|
|
|
void NimBLECharacteristic::setCallbacks(NimBLECharacteristicCallbacks* pCallbacks) {
|
2024-07-26 14:47:36 -06:00
|
|
|
if (pCallbacks != nullptr) {
|
2020-05-13 22:03:56 -06:00
|
|
|
m_pCallbacks = pCallbacks;
|
|
|
|
} else {
|
|
|
|
m_pCallbacks = &defaultCallback;
|
|
|
|
}
|
2020-03-29 17:44:20 -06:00
|
|
|
} // setCallbacks
|
|
|
|
|
2021-05-19 22:21:05 -06:00
|
|
|
/**
|
|
|
|
* @brief Get the callback handlers for this characteristic.
|
|
|
|
*/
|
2024-07-26 14:47:36 -06:00
|
|
|
NimBLECharacteristicCallbacks* NimBLECharacteristic::getCallbacks() const {
|
2021-05-19 22:21:05 -06:00
|
|
|
return m_pCallbacks;
|
2024-07-26 14:47:36 -06:00
|
|
|
} // getCallbacks
|
2020-03-29 17:44:20 -06:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Return a string representation of the characteristic.
|
|
|
|
* @return A string representation of the characteristic.
|
|
|
|
*/
|
2024-07-26 14:47:36 -06:00
|
|
|
std::string NimBLECharacteristic::toString() const {
|
2020-05-13 22:03:56 -06:00
|
|
|
std::string res = "UUID: " + m_uuid.toString() + ", handle : 0x";
|
2024-07-26 14:47:36 -06:00
|
|
|
char hex[5];
|
|
|
|
snprintf(hex, sizeof(hex), "%04x", getHandle());
|
2020-05-13 22:03:56 -06:00
|
|
|
res += hex;
|
|
|
|
res += " ";
|
2024-07-26 14:47:36 -06:00
|
|
|
if (m_properties & BLE_GATT_CHR_PROP_READ) res += "Read ";
|
2020-05-13 22:03:56 -06:00
|
|
|
if (m_properties & BLE_GATT_CHR_PROP_WRITE) res += "Write ";
|
|
|
|
if (m_properties & BLE_GATT_CHR_PROP_WRITE_NO_RSP) res += "WriteNoResponse ";
|
|
|
|
if (m_properties & BLE_GATT_CHR_PROP_BROADCAST) res += "Broadcast ";
|
|
|
|
if (m_properties & BLE_GATT_CHR_PROP_NOTIFY) res += "Notify ";
|
|
|
|
if (m_properties & BLE_GATT_CHR_PROP_INDICATE) res += "Indicate ";
|
|
|
|
return res;
|
2020-03-29 17:44:20 -06:00
|
|
|
} // toString
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Callback function to support a read request.
|
|
|
|
* @param [in] pCharacteristic The characteristic that is the source of the event.
|
2022-08-27 08:28:15 -06:00
|
|
|
* @param [in] connInfo A reference to a NimBLEConnInfo instance containing the peer info.
|
2020-03-29 17:44:20 -06:00
|
|
|
*/
|
2022-08-27 08:28:15 -06:00
|
|
|
void NimBLECharacteristicCallbacks::onRead(NimBLECharacteristic* pCharacteristic, NimBLEConnInfo& connInfo) {
|
2020-05-13 22:03:56 -06:00
|
|
|
NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onRead: default");
|
2020-03-29 17:44:20 -06:00
|
|
|
} // onRead
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Callback function to support a write request.
|
|
|
|
* @param [in] pCharacteristic The characteristic that is the source of the event.
|
2022-08-27 08:28:15 -06:00
|
|
|
* @param [in] connInfo A reference to a NimBLEConnInfo instance containing the peer info.
|
2020-03-29 17:44:20 -06:00
|
|
|
*/
|
2022-08-27 08:28:15 -06:00
|
|
|
void NimBLECharacteristicCallbacks::onWrite(NimBLECharacteristic* pCharacteristic, NimBLEConnInfo& connInfo) {
|
2020-05-13 22:03:56 -06:00
|
|
|
NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onWrite: default");
|
2020-03-29 17:44:20 -06:00
|
|
|
} // onWrite
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Callback function to support a Notify/Indicate Status report.
|
|
|
|
* @param [in] pCharacteristic The characteristic that is the source of the event.
|
2022-08-26 20:40:21 -06:00
|
|
|
* @param [in] code Status return code from the NimBLE stack.
|
|
|
|
* @details The status code for success is 0 for notifications and BLE_HS_EDONE for indications,
|
|
|
|
* any other value is an error.
|
2020-03-29 17:44:20 -06:00
|
|
|
*/
|
2022-08-26 20:40:21 -06:00
|
|
|
void NimBLECharacteristicCallbacks::onStatus(NimBLECharacteristic* pCharacteristic, int code) {
|
2020-05-13 22:03:56 -06:00
|
|
|
NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onStatus: default");
|
2020-03-29 17:44:20 -06:00
|
|
|
} // onStatus
|
|
|
|
|
2020-07-27 21:11:38 -06:00
|
|
|
/**
|
|
|
|
* @brief Callback function called when a client changes subscription status.
|
|
|
|
* @param [in] pCharacteristic The characteristic that is the source of the event.
|
2022-08-27 08:28:15 -06:00
|
|
|
* @param [in] connInfo A reference to a NimBLEConnInfo instance containing the peer info.
|
2020-07-27 21:11:38 -06:00
|
|
|
* @param [in] subValue The subscription status:
|
|
|
|
* * 0 = Un-Subscribed
|
|
|
|
* * 1 = Notifications
|
|
|
|
* * 2 = Indications
|
|
|
|
* * 3 = Notifications and Indications
|
|
|
|
*/
|
|
|
|
void NimBLECharacteristicCallbacks::onSubscribe(NimBLECharacteristic* pCharacteristic,
|
2022-08-27 08:28:15 -06:00
|
|
|
NimBLEConnInfo& connInfo,
|
2024-07-26 14:47:36 -06:00
|
|
|
uint16_t subValue) {
|
2020-07-27 21:11:38 -06:00
|
|
|
NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onSubscribe: default");
|
|
|
|
}
|
|
|
|
|
2021-09-06 21:14:43 -06:00
|
|
|
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */
|