mirror of
https://github.com/h2zero/esp-nimble-cpp.git
synced 2026-02-01 02:49:30 +01:00
[BREAKING] Refactor attributes
Refactor attributes to reduce code duplication and improve maintainability. * Add attribute base classes to provide common code. * Add const where possible to functions and parameters. * `NimBLECharacteristic::notify` no longer takes a `bool is_notification` parameter, instead `indicate()` should be called to send indications. * `NimBLECharacteristic::indicate` now takes the same parameters as `notify`. * `NimBLECharacteristicCallbacks` and `NimBLEDescriptorCallbacks` methods now take `const NimBLEConnInfo&` instead of non-const. * `NimBLECharacteristic::onNotify` callback removed as unnecessary, the library does not call notify without app input. * `NimBLERemoteCharacteristic::getRemoteService` now returns a `const NimBLERemoteService*` instead of non-const. * Add NimBLEUUID constructor that takes a reference to `ble_uuid_any_t`. * `NimBLERemoteService::getCharacteristics` now returns a `const std::vector<NimBLERemoteCharacteristic*>&` instead of non-const `std::vector<NimBLERemoteCharacteristic*>*` * `NimBLERemoteService::getValue` now returns `NimBLEAttValue` instead of `std::string` * `NimBLEService::getCharacteristics` now returns a `const std::vector<NimBLECharacteristic*>&` instead of a copy of std::vector<NimBLECharacteristic *>. * Remove const requirement for NimBLEConnInfo parameter in callbacks. Const is unnecessary as the data can't be changed by application code. * Change NimBLERemoteCharacteristic::getRemoteService to return const pointer.
This commit is contained in:
@@ -15,17 +15,24 @@
|
||||
#include "nimconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
|
||||
#include "NimBLEService.h"
|
||||
#include "NimBLEDescriptor.h"
|
||||
#include "NimBLELog.h"
|
||||
# include "NimBLEService.h"
|
||||
# include "NimBLEDescriptor.h"
|
||||
# include "NimBLELog.h"
|
||||
|
||||
#include <string>
|
||||
# include <string>
|
||||
|
||||
#define NULL_HANDLE (0xffff)
|
||||
|
||||
static const char* LOG_TAG = "NimBLEDescriptor";
|
||||
static const char* LOG_TAG = "NimBLEDescriptor";
|
||||
static NimBLEDescriptorCallbacks defaultCallbacks;
|
||||
|
||||
/**
|
||||
* @brief Construct a descriptor
|
||||
* @param [in] uuid - UUID (const char*) for the descriptor.
|
||||
* @param [in] properties - Properties for the descriptor.
|
||||
* @param [in] max_len - The maximum length in bytes that the descriptor value can hold. (Default: 512 bytes for esp32, 20 for all others).
|
||||
* @param [in] pCharacteristic - pointer to the characteristic instance this descriptor belongs to.
|
||||
*/
|
||||
NimBLEDescriptor::NimBLEDescriptor(const char* uuid, uint16_t properties, uint16_t max_len, NimBLECharacteristic* pCharacteristic)
|
||||
: NimBLEDescriptor(NimBLEUUID(uuid), properties, max_len, pCharacteristic) {}
|
||||
|
||||
/**
|
||||
* @brief Construct a descriptor
|
||||
@@ -34,239 +41,64 @@ static NimBLEDescriptorCallbacks defaultCallbacks;
|
||||
* @param [in] max_len - The maximum length in bytes that the descriptor value can hold. (Default: 512 bytes for esp32, 20 for all others).
|
||||
* @param [in] pCharacteristic - pointer to the characteristic instance this descriptor belongs to.
|
||||
*/
|
||||
NimBLEDescriptor::NimBLEDescriptor(const char* uuid, uint16_t properties, uint16_t max_len,
|
||||
NimBLECharacteristic* pCharacteristic)
|
||||
: NimBLEDescriptor(NimBLEUUID(uuid), properties, max_len, pCharacteristic) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Construct a descriptor
|
||||
* @param [in] uuid - UUID (const char*) for the descriptor.
|
||||
* @param [in] properties - Properties for the descriptor.
|
||||
* @param [in] max_len - The maximum length in bytes that the descriptor value can hold. (Default: 512 bytes for esp32, 20 for all others).
|
||||
* @param [in] pCharacteristic - pointer to the characteristic instance this descriptor belongs to.
|
||||
*/
|
||||
NimBLEDescriptor::NimBLEDescriptor(NimBLEUUID uuid, uint16_t properties, uint16_t max_len,
|
||||
NimBLECharacteristic* pCharacteristic)
|
||||
: m_value(std::min(CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH , (int)max_len), max_len) {
|
||||
m_uuid = uuid;
|
||||
m_handle = NULL_HANDLE; // Handle is initially unknown.
|
||||
m_pCharacteristic = pCharacteristic;
|
||||
m_pCallbacks = &defaultCallbacks; // No initial callback.
|
||||
m_properties = 0;
|
||||
|
||||
NimBLEDescriptor::NimBLEDescriptor(const NimBLEUUID& uuid, uint16_t properties, uint16_t max_len, NimBLECharacteristic* pCharacteristic)
|
||||
: NimBLELocalValueAttribute{uuid, 0, max_len}, m_pCallbacks{&defaultCallbacks}, m_pCharacteristic{pCharacteristic} {
|
||||
// Check if this is the client configuration descriptor and set to removed if true.
|
||||
if (uuid == NimBLEUUID((uint16_t)0x2902)) {
|
||||
NIMBLE_LOGW(LOG_TAG, "Manually created 2902 descriptor has no functionality; please remove.");
|
||||
m_removed = 1;
|
||||
} else {
|
||||
m_removed = 0;
|
||||
setRemoved(NIMBLE_ATT_REMOVE_HIDE);
|
||||
}
|
||||
|
||||
if (properties & BLE_GATT_CHR_F_READ) { // convert uint16_t properties to uint8_t
|
||||
m_properties |= BLE_ATT_F_READ;
|
||||
// convert uint16_t properties to uint8_t for descriptor properties
|
||||
uint8_t descProperties = 0;
|
||||
if (properties & NIMBLE_PROPERTY::READ) {
|
||||
descProperties |= BLE_ATT_F_READ;
|
||||
}
|
||||
if (properties & (BLE_GATT_CHR_F_WRITE_NO_RSP | BLE_GATT_CHR_F_WRITE)) {
|
||||
m_properties |= BLE_ATT_F_WRITE;
|
||||
if (properties & (NIMBLE_PROPERTY::WRITE_NR | NIMBLE_PROPERTY::WRITE)) {
|
||||
descProperties |= BLE_ATT_F_WRITE;
|
||||
}
|
||||
if (properties & BLE_GATT_CHR_F_READ_ENC) {
|
||||
m_properties |= BLE_ATT_F_READ_ENC;
|
||||
if (properties & NIMBLE_PROPERTY::READ_ENC) {
|
||||
descProperties |= BLE_ATT_F_READ_ENC;
|
||||
}
|
||||
if (properties & BLE_GATT_CHR_F_READ_AUTHEN) {
|
||||
m_properties |= BLE_ATT_F_READ_AUTHEN;
|
||||
if (properties & NIMBLE_PROPERTY::READ_AUTHEN) {
|
||||
descProperties |= BLE_ATT_F_READ_AUTHEN;
|
||||
}
|
||||
if (properties & BLE_GATT_CHR_F_READ_AUTHOR) {
|
||||
m_properties |= BLE_ATT_F_READ_AUTHOR;
|
||||
if (properties & NIMBLE_PROPERTY::READ_AUTHOR) {
|
||||
descProperties |= BLE_ATT_F_READ_AUTHOR;
|
||||
}
|
||||
if (properties & BLE_GATT_CHR_F_WRITE_ENC) {
|
||||
m_properties |= BLE_ATT_F_WRITE_ENC;
|
||||
if (properties & NIMBLE_PROPERTY::WRITE_ENC) {
|
||||
descProperties |= BLE_ATT_F_WRITE_ENC;
|
||||
}
|
||||
if (properties & BLE_GATT_CHR_F_WRITE_AUTHEN) {
|
||||
m_properties |= BLE_ATT_F_WRITE_AUTHEN;
|
||||
if (properties & NIMBLE_PROPERTY::WRITE_AUTHEN) {
|
||||
descProperties |= BLE_ATT_F_WRITE_AUTHEN;
|
||||
}
|
||||
if (properties & BLE_GATT_CHR_F_WRITE_AUTHOR) {
|
||||
m_properties |= BLE_ATT_F_WRITE_AUTHOR;
|
||||
if (properties & NIMBLE_PROPERTY::WRITE_AUTHOR) {
|
||||
descProperties |= BLE_ATT_F_WRITE_AUTHOR;
|
||||
}
|
||||
|
||||
setProperties(descProperties);
|
||||
} // NimBLEDescriptor
|
||||
|
||||
|
||||
/**
|
||||
* @brief NimBLEDescriptor destructor.
|
||||
*/
|
||||
NimBLEDescriptor::~NimBLEDescriptor() {
|
||||
} // ~NimBLEDescriptor
|
||||
|
||||
/**
|
||||
* @brief Get the BLE handle for this descriptor.
|
||||
* @return The handle for this descriptor.
|
||||
*/
|
||||
uint16_t NimBLEDescriptor::getHandle() {
|
||||
return m_handle;
|
||||
} // getHandle
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the length of the value of this descriptor.
|
||||
* @return The length (in bytes) of the value of this descriptor.
|
||||
*/
|
||||
size_t NimBLEDescriptor::getLength() {
|
||||
return m_value.size();
|
||||
} // getLength
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the UUID of the descriptor.
|
||||
*/
|
||||
NimBLEUUID NimBLEDescriptor::getUUID() {
|
||||
return m_uuid;
|
||||
} // getUUID
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the value of this descriptor.
|
||||
* @return The NimBLEAttValue of this descriptor.
|
||||
*/
|
||||
NimBLEAttValue NimBLEDescriptor::getValue(time_t *timestamp) {
|
||||
if (timestamp != nullptr) {
|
||||
m_value.getValue(timestamp);
|
||||
}
|
||||
|
||||
return m_value;
|
||||
} // getValue
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the value of this descriptor as a string.
|
||||
* @return A std::string instance containing a copy of the descriptor's value.
|
||||
*/
|
||||
std::string NimBLEDescriptor::getStringValue() {
|
||||
return std::string(m_value);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the characteristic this descriptor belongs to.
|
||||
* @return A pointer to the characteristic this descriptor belongs to.
|
||||
*/
|
||||
NimBLECharacteristic* NimBLEDescriptor::getCharacteristic() {
|
||||
NimBLECharacteristic* NimBLEDescriptor::getCharacteristic() const {
|
||||
return m_pCharacteristic;
|
||||
} // getCharacteristic
|
||||
|
||||
|
||||
int NimBLEDescriptor::handleGapEvent(uint16_t conn_handle, uint16_t attr_handle,
|
||||
struct ble_gatt_access_ctxt *ctxt, void *arg) {
|
||||
(void)conn_handle;
|
||||
(void)attr_handle;
|
||||
|
||||
const ble_uuid_t *uuid;
|
||||
int rc;
|
||||
NimBLEConnInfo peerInfo{};
|
||||
NimBLEDescriptor* pDescriptor = (NimBLEDescriptor*)arg;
|
||||
|
||||
NIMBLE_LOGD(LOG_TAG, "Descriptor %s %s event", pDescriptor->getUUID().toString().c_str(),
|
||||
ctxt->op == BLE_GATT_ACCESS_OP_READ_DSC ? "Read" : "Write");
|
||||
|
||||
uuid = ctxt->chr->uuid;
|
||||
if(ble_uuid_cmp(uuid, pDescriptor->getUUID().getBase()) == 0){
|
||||
switch(ctxt->op) {
|
||||
case BLE_GATT_ACCESS_OP_READ_DSC: {
|
||||
ble_gap_conn_find(conn_handle, &peerInfo.m_desc);
|
||||
|
||||
// If the packet header is only 8 bytes this is a follow up of a long read
|
||||
// so we don't want to call the onRead() callback again.
|
||||
if(ctxt->om->om_pkthdr_len > 8 ||
|
||||
conn_handle == BLE_HS_CONN_HANDLE_NONE ||
|
||||
pDescriptor->m_value.size() <= (ble_att_mtu(peerInfo.getConnHandle()) - 3)) {
|
||||
pDescriptor->m_pCallbacks->onRead(pDescriptor, peerInfo);
|
||||
}
|
||||
|
||||
ble_npl_hw_enter_critical();
|
||||
rc = os_mbuf_append(ctxt->om, pDescriptor->m_value.data(), pDescriptor->m_value.size());
|
||||
ble_npl_hw_exit_critical(0);
|
||||
return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
|
||||
}
|
||||
|
||||
case BLE_GATT_ACCESS_OP_WRITE_DSC: {
|
||||
ble_gap_conn_find(conn_handle, &peerInfo.m_desc);
|
||||
|
||||
uint16_t att_max_len = pDescriptor->m_value.max_size();
|
||||
if (ctxt->om->om_len > att_max_len) {
|
||||
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
|
||||
}
|
||||
|
||||
uint8_t buf[att_max_len];
|
||||
size_t len = ctxt->om->om_len;
|
||||
memcpy(buf, ctxt->om->om_data,len);
|
||||
os_mbuf *next;
|
||||
next = SLIST_NEXT(ctxt->om, om_next);
|
||||
while(next != NULL){
|
||||
if((len + next->om_len) > att_max_len) {
|
||||
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
|
||||
}
|
||||
memcpy(&buf[len], next->om_data, next->om_len);
|
||||
len += next->om_len;
|
||||
next = SLIST_NEXT(next, om_next);
|
||||
}
|
||||
|
||||
pDescriptor->setValue(buf, len);
|
||||
pDescriptor->m_pCallbacks->onWrite(pDescriptor, peerInfo);
|
||||
return 0;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return BLE_ATT_ERR_UNLIKELY;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the callback handlers for this descriptor.
|
||||
* @param [in] pCallbacks An instance of a callback structure used to define any callbacks for the descriptor.
|
||||
*/
|
||||
void NimBLEDescriptor::setCallbacks(NimBLEDescriptorCallbacks* pCallbacks) {
|
||||
if (pCallbacks != nullptr){
|
||||
if (pCallbacks != nullptr) {
|
||||
m_pCallbacks = pCallbacks;
|
||||
} else {
|
||||
m_pCallbacks = &defaultCallbacks;
|
||||
}
|
||||
} // setCallbacks
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the handle of this descriptor.
|
||||
* Set the handle of this descriptor to be the supplied value.
|
||||
* @param [in] handle The handle to be associated with this descriptor.
|
||||
* @return N/A.
|
||||
*/
|
||||
void NimBLEDescriptor::setHandle(uint16_t handle) {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> setHandle(0x%.2x): Setting descriptor handle to be 0x%.2x", handle, handle);
|
||||
m_handle = handle;
|
||||
NIMBLE_LOGD(LOG_TAG, "<< setHandle()");
|
||||
} // setHandle
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the value of the descriptor.
|
||||
* @param [in] data The data to set for the descriptor.
|
||||
* @param [in] length The length of the data in bytes.
|
||||
*/
|
||||
void NimBLEDescriptor::setValue(const uint8_t* data, size_t length) {
|
||||
m_value.setValue(data, length);
|
||||
} // setValue
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the value of the descriptor from a `std::vector<uint8_t>`.\n
|
||||
* @param [in] vec The std::vector<uint8_t> reference to set the descriptor value from.
|
||||
*/
|
||||
void NimBLEDescriptor::setValue(const std::vector<uint8_t>& vec) {
|
||||
return setValue((uint8_t*)&vec[0], vec.size());
|
||||
} // setValue
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the characteristic this descriptor belongs to.
|
||||
* @param [in] pChar A pointer to the characteristic this descriptor belongs to.
|
||||
@@ -275,18 +107,25 @@ void NimBLEDescriptor::setCharacteristic(NimBLECharacteristic* pChar) {
|
||||
m_pCharacteristic = pChar;
|
||||
} // setCharacteristic
|
||||
|
||||
|
||||
/**
|
||||
* @brief Return a string representation of the descriptor.
|
||||
* @return A string representation of the descriptor.
|
||||
*/
|
||||
std::string NimBLEDescriptor::toString() {
|
||||
std::string NimBLEDescriptor::toString() const {
|
||||
char hex[5];
|
||||
snprintf(hex, sizeof(hex), "%04x", m_handle);
|
||||
snprintf(hex, sizeof(hex), "%04x", getHandle());
|
||||
std::string res = "UUID: " + m_uuid.toString() + ", handle: 0x" + hex;
|
||||
return res;
|
||||
} // toString
|
||||
|
||||
void NimBLEDescriptor::readEvent(NimBLEConnInfo& connInfo) {
|
||||
m_pCallbacks->onRead(this, connInfo);
|
||||
} // readEvent
|
||||
|
||||
void NimBLEDescriptor::writeEvent(const uint8_t* val, uint16_t len, NimBLEConnInfo& connInfo) {
|
||||
setValue(val, len);
|
||||
m_pCallbacks->onWrite(this, connInfo);
|
||||
} // writeEvent
|
||||
|
||||
/**
|
||||
* @brief Callback function to support a read request.
|
||||
@@ -294,18 +133,15 @@ std::string NimBLEDescriptor::toString() {
|
||||
* @param [in] connInfo A reference to a NimBLEConnInfo instance containing the peer info.
|
||||
*/
|
||||
void NimBLEDescriptorCallbacks::onRead(NimBLEDescriptor* pDescriptor, NimBLEConnInfo& connInfo) {
|
||||
(void)pDescriptor;
|
||||
NIMBLE_LOGD("NimBLEDescriptorCallbacks", "onRead: default");
|
||||
} // onRead
|
||||
|
||||
|
||||
/**
|
||||
* @brief Callback function to support a write request.
|
||||
* @param [in] pDescriptor The descriptor that is the source of the event.
|
||||
* @param [in] connInfo A reference to a NimBLEConnInfo instance containing the peer info.
|
||||
*/
|
||||
void NimBLEDescriptorCallbacks::onWrite(NimBLEDescriptor* pDescriptor, NimBLEConnInfo& connInfo) {
|
||||
(void)pDescriptor;
|
||||
NIMBLE_LOGD("NimBLEDescriptorCallbacks", "onWrite: default");
|
||||
} // onWrite
|
||||
|
||||
|
||||
Reference in New Issue
Block a user