mirror of
https://github.com/h2zero/esp-nimble-cpp.git
synced 2024-11-24 14:10:55 +01:00
[NimBLEServer] Support duplicate characteristics (#36)
* Add method to get all characteristics of a service * Added method on NimBLEDescriptor to get the value out as a std::string * Added methods to get things by handle where UUID could be used already. * Added helper methods for getting a list of characteristics with a given UUID and service * Demote the warning log for adding duplicate characteristics to a debug level log. * Add methods to get services and characteristics using UUID + index
This commit is contained in:
parent
28d6492ea4
commit
7dd4d68806
8 changed files with 157 additions and 53 deletions
|
@ -101,9 +101,9 @@ NimBLEDescriptor* NimBLECharacteristic::createDescriptor(const NimBLEUUID &uuid,
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Return the BLE Descriptor for the given UUID if associated with this characteristic.
|
* @brief Return the BLE Descriptor for the given UUID.
|
||||||
* @param [in] uuid The UUID of the descriptor that we wish to retrieve.
|
* @param [in] uuid The UUID of the descriptor.
|
||||||
* @return pointer to the NimBLEDescriptor. If no such descriptor is associated with the characteristic, nullptr is returned.
|
* @return A pointer to the descriptor object or nullptr if not found.
|
||||||
*/
|
*/
|
||||||
NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(const char* uuid) {
|
NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(const char* uuid) {
|
||||||
return getDescriptorByUUID(NimBLEUUID(uuid));
|
return getDescriptorByUUID(NimBLEUUID(uuid));
|
||||||
|
@ -111,9 +111,9 @@ NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(const char* uuid) {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Return the BLE Descriptor for the given UUID if associated with this characteristic.
|
* @brief Return the BLE Descriptor for the given UUID.
|
||||||
* @param [in] uuid The UUID of the descriptor that we wish to retrieve.
|
* @param [in] uuid The UUID of the descriptor.
|
||||||
* @return pointer to the NimBLEDescriptor. If no such descriptor is associated with the characteristic, nullptr is returned.
|
* @return A pointer to the descriptor object or nullptr if not found.
|
||||||
*/
|
*/
|
||||||
NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(const NimBLEUUID &uuid) {
|
NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(const NimBLEUUID &uuid) {
|
||||||
for (auto &it : m_dscVec) {
|
for (auto &it : m_dscVec) {
|
||||||
|
@ -124,6 +124,20 @@ NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(const NimBLEUUID &uu
|
||||||
return nullptr;
|
return nullptr;
|
||||||
} // getDescriptorByUUID
|
} // getDescriptorByUUID
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Return the BLE Descriptor for the given handle.
|
||||||
|
* @param [in] uuid The handle of the descriptor.
|
||||||
|
* @return A pointer to the descriptor object or nullptr if not found.
|
||||||
|
*/
|
||||||
|
NimBLEDescriptor *NimBLECharacteristic::getDescriptorByHandle(uint16_t handle) {
|
||||||
|
for (auto &it : m_dscVec) {
|
||||||
|
if (it->getHandle() == handle) {
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the handle of the characteristic.
|
* @brief Get the handle of the characteristic.
|
||||||
|
|
|
@ -59,6 +59,17 @@ class NimBLECharacteristicCallbacks;
|
||||||
*/
|
*/
|
||||||
class NimBLECharacteristic {
|
class NimBLECharacteristic {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
uint16_t getHandle();
|
||||||
|
NimBLEUUID getUUID();
|
||||||
|
std::string toString();
|
||||||
|
|
||||||
|
void setCallbacks(NimBLECharacteristicCallbacks* pCallbacks);
|
||||||
|
|
||||||
|
void indicate();
|
||||||
|
void notify(bool is_notification = true);
|
||||||
|
size_t getSubscribedCount();
|
||||||
|
|
||||||
NimBLEDescriptor* createDescriptor(const char* uuid,
|
NimBLEDescriptor* createDescriptor(const char* uuid,
|
||||||
uint32_t properties =
|
uint32_t properties =
|
||||||
NIMBLE_PROPERTY::READ |
|
NIMBLE_PROPERTY::READ |
|
||||||
|
@ -72,9 +83,10 @@ public:
|
||||||
|
|
||||||
NimBLEDescriptor* getDescriptorByUUID(const char* uuid);
|
NimBLEDescriptor* getDescriptorByUUID(const char* uuid);
|
||||||
NimBLEDescriptor* getDescriptorByUUID(const NimBLEUUID &uuid);
|
NimBLEDescriptor* getDescriptorByUUID(const NimBLEUUID &uuid);
|
||||||
NimBLEUUID getUUID();
|
NimBLEDescriptor* getDescriptorByHandle(uint16_t handle);
|
||||||
std::string getValue(time_t *timestamp = nullptr);
|
|
||||||
|
|
||||||
|
std::string getValue(time_t *timestamp = nullptr);
|
||||||
|
size_t getDataLength();
|
||||||
/**
|
/**
|
||||||
* @brief A template to convert the characteristic data to <type\>.
|
* @brief A template to convert the characteristic data to <type\>.
|
||||||
* @tparam T The type to convert the data to.
|
* @tparam T The type to convert the data to.
|
||||||
|
@ -92,25 +104,20 @@ public:
|
||||||
return *((T *)pData);
|
return *((T *)pData);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t getDataLength();
|
|
||||||
void indicate();
|
|
||||||
void notify(bool is_notification = true);
|
|
||||||
void setCallbacks(NimBLECharacteristicCallbacks* pCallbacks);
|
|
||||||
void setValue(const uint8_t* data, size_t size);
|
void setValue(const uint8_t* data, size_t size);
|
||||||
void setValue(const std::string &value);
|
void setValue(const std::string &value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Convenience template to set the characteristic value to <type\>val.
|
* @brief Convenience template to set the characteristic value to <type\>val.
|
||||||
* @param [in] s The value to set.
|
* @param [in] s The value to set.
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void setValue(const T &s) {
|
void setValue(const T &s) {
|
||||||
setValue((uint8_t*)&s, sizeof(T));
|
setValue((uint8_t*)&s, sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string toString();
|
|
||||||
uint16_t getHandle();
|
|
||||||
size_t getSubscribedCount();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
|
@ -122,11 +122,17 @@ uint8_t* NimBLEDescriptor::getValue() {
|
||||||
return m_value.attr_value;
|
return m_value.attr_value;
|
||||||
} // getValue
|
} // 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((char *) m_value.attr_value, m_value.attr_len);
|
||||||
|
}
|
||||||
|
|
||||||
int NimBLEDescriptor::handleGapEvent(uint16_t conn_handle, uint16_t attr_handle,
|
int NimBLEDescriptor::handleGapEvent(uint16_t conn_handle, uint16_t attr_handle,
|
||||||
struct ble_gatt_access_ctxt *ctxt,
|
struct ble_gatt_access_ctxt *ctxt,
|
||||||
void *arg)
|
void *arg) {
|
||||||
{
|
|
||||||
const ble_uuid_t *uuid;
|
const ble_uuid_t *uuid;
|
||||||
int rc;
|
int rc;
|
||||||
NimBLEDescriptor* pDescriptor = (NimBLEDescriptor*)arg;
|
NimBLEDescriptor* pDescriptor = (NimBLEDescriptor*)arg;
|
||||||
|
|
|
@ -44,20 +44,23 @@ class NimBLEDescriptorCallbacks;
|
||||||
class NimBLEDescriptor {
|
class NimBLEDescriptor {
|
||||||
public:
|
public:
|
||||||
uint16_t getHandle();
|
uint16_t getHandle();
|
||||||
size_t getLength();
|
|
||||||
NimBLEUUID getUUID();
|
NimBLEUUID getUUID();
|
||||||
uint8_t* getValue();
|
|
||||||
void setCallbacks(NimBLEDescriptorCallbacks* pCallbacks);
|
|
||||||
void setValue(const uint8_t* data, size_t size);
|
|
||||||
void setValue(const std::string &value);
|
|
||||||
std::string toString();
|
std::string toString();
|
||||||
|
|
||||||
|
void setCallbacks(NimBLEDescriptorCallbacks* pCallbacks);
|
||||||
|
|
||||||
|
size_t getLength();
|
||||||
|
uint8_t* getValue();
|
||||||
|
std::string getStringValue();
|
||||||
|
|
||||||
|
void setValue(const uint8_t* data, size_t size);
|
||||||
|
void setValue(const std::string &value);
|
||||||
/**
|
/**
|
||||||
* @brief Convenience template to set the descriptor value to <type\>val.
|
* @brief Convenience template to set the descriptor value to <type\>val.
|
||||||
* @param [in] s The value to set.
|
* @param [in] s The value to set.
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void setValue(const T &s) {
|
void setValue(const T &s) {
|
||||||
setValue((uint8_t*)&s, sizeof(T));
|
setValue((uint8_t*)&s, sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -104,28 +104,47 @@ NimBLEService* NimBLEServer::createService(const NimBLEUUID &uuid, uint32_t numH
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get a %BLE Service by its UUID
|
* @brief Get a %BLE Service by its UUID
|
||||||
* @param [in] uuid The UUID of the new service.
|
* @param [in] uuid The UUID of the service.
|
||||||
* @return A reference to the service object.
|
* @param instanceId The index of the service to return (used when multiple services have the same UUID).
|
||||||
|
* @return A pointer to the service object or nullptr if not found.
|
||||||
*/
|
*/
|
||||||
NimBLEService* NimBLEServer::getServiceByUUID(const char* uuid) {
|
NimBLEService* NimBLEServer::getServiceByUUID(const char* uuid, uint16_t instanceId) {
|
||||||
return getServiceByUUID(NimBLEUUID(uuid));
|
return getServiceByUUID(NimBLEUUID(uuid), instanceId);
|
||||||
} // getServiceByUUID
|
} // getServiceByUUID
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get a %BLE Service by its UUID
|
* @brief Get a %BLE Service by its UUID
|
||||||
* @param [in] uuid The UUID of the new service.
|
* @param [in] uuid The UUID of the service.
|
||||||
* @return A reference to the service object.
|
* @param instanceId The index of the service to return (used when multiple services have the same UUID).
|
||||||
|
* @return A pointer to the service object or nullptr if not found.
|
||||||
*/
|
*/
|
||||||
NimBLEService* NimBLEServer::getServiceByUUID(const NimBLEUUID &uuid) {
|
NimBLEService* NimBLEServer::getServiceByUUID(const NimBLEUUID &uuid, uint16_t instanceId) {
|
||||||
|
uint16_t position = 0;
|
||||||
for (auto &it : m_svcVec) {
|
for (auto &it : m_svcVec) {
|
||||||
if (it->getUUID() == uuid) {
|
if (it->getUUID() == uuid) {
|
||||||
return it;
|
if (position == instanceId){
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
position++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
} // getServiceByUUID
|
} // getServiceByUUID
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get a %BLE Service by its handle
|
||||||
|
* @param handle The handle of the service.
|
||||||
|
* @return A pointer to the service object or nullptr if not found.
|
||||||
|
*/
|
||||||
|
NimBLEService *NimBLEServer::getServiceByHandle(uint16_t handle) {
|
||||||
|
for (auto &it : m_svcVec) {
|
||||||
|
if (it->getHandle() == handle) {
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Retrieve the advertising object that can be used to advertise the existence of the server.
|
* @brief Retrieve the advertising object that can be used to advertise the existence of the server.
|
||||||
|
@ -646,7 +665,7 @@ void NimBLEServer::updateConnParams(uint16_t conn_handle,
|
||||||
if(rc != 0) {
|
if(rc != 0) {
|
||||||
NIMBLE_LOGE(LOG_TAG, "Update params error: %d, %s", rc, NimBLEUtils::returnCodeToString(rc));
|
NIMBLE_LOGE(LOG_TAG, "Update params error: %d, %s", rc, NimBLEUtils::returnCodeToString(rc));
|
||||||
}
|
}
|
||||||
} // updateConnParams
|
}// updateConnParams
|
||||||
|
|
||||||
|
|
||||||
/** Default callback handlers */
|
/** Default callback handlers */
|
||||||
|
|
|
@ -49,8 +49,9 @@ public:
|
||||||
void startAdvertising();
|
void startAdvertising();
|
||||||
void stopAdvertising();
|
void stopAdvertising();
|
||||||
void start();
|
void start();
|
||||||
NimBLEService* getServiceByUUID(const char* uuid);
|
NimBLEService* getServiceByUUID(const char* uuid, uint16_t instanceId = 0);
|
||||||
NimBLEService* getServiceByUUID(const NimBLEUUID &uuid);
|
NimBLEService* getServiceByUUID(const NimBLEUUID &uuid, uint16_t instanceId = 0);
|
||||||
|
NimBLEService* getServiceByHandle(uint16_t handle);
|
||||||
int disconnect(uint16_t connID,
|
int disconnect(uint16_t connID,
|
||||||
uint8_t reason = BLE_ERR_REM_USER_CONN_TERM);
|
uint8_t reason = BLE_ERR_REM_USER_CONN_TERM);
|
||||||
void updateConnParams(uint16_t conn_handle,
|
void updateConnParams(uint16_t conn_handle,
|
||||||
|
|
|
@ -233,9 +233,9 @@ NimBLECharacteristic* NimBLEService::createCharacteristic(const char* uuid, uint
|
||||||
*/
|
*/
|
||||||
NimBLECharacteristic* NimBLEService::createCharacteristic(const NimBLEUUID &uuid, uint32_t properties) {
|
NimBLECharacteristic* NimBLEService::createCharacteristic(const NimBLEUUID &uuid, uint32_t properties) {
|
||||||
NimBLECharacteristic* pCharacteristic = new NimBLECharacteristic(uuid, properties, this);
|
NimBLECharacteristic* pCharacteristic = new NimBLECharacteristic(uuid, properties, this);
|
||||||
// Check that we don't add the same characteristic twice.
|
|
||||||
if (getCharacteristic(uuid) != nullptr) {
|
if (getCharacteristic(uuid) != nullptr) {
|
||||||
NIMBLE_LOGW(LOG_TAG, "<< Adding a duplicate characteristic with UUID: %s",
|
NIMBLE_LOGD(LOG_TAG, "<< Adding a duplicate characteristic with UUID: %s",
|
||||||
std::string(uuid).c_str());
|
std::string(uuid).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,28 +249,72 @@ NimBLECharacteristic* NimBLEService::createCharacteristic(const NimBLEUUID &uuid
|
||||||
/**
|
/**
|
||||||
* @brief Get a pointer to the characteristic object with the specified UUID.
|
* @brief Get a pointer to the characteristic object with the specified UUID.
|
||||||
* @param [in] uuid The UUID of the characteristic.
|
* @param [in] uuid The UUID of the characteristic.
|
||||||
|
* @param instanceId The index of the characteristic to return (used when multiple characteristics have the same UUID).
|
||||||
* @return A pointer to the characteristic object or nullptr if not found.
|
* @return A pointer to the characteristic object or nullptr if not found.
|
||||||
*/
|
*/
|
||||||
NimBLECharacteristic* NimBLEService::getCharacteristic(const char* uuid) {
|
NimBLECharacteristic* NimBLEService::getCharacteristic(const char* uuid, uint16_t instanceId) {
|
||||||
return getCharacteristic(NimBLEUUID(uuid));
|
return getCharacteristic(NimBLEUUID(uuid), instanceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get a pointer to the characteristic object with the specified UUID.
|
* @brief Get a pointer to the characteristic object with the specified UUID.
|
||||||
* @param [in] uuid The UUID of the characteristic.
|
* @param [in] uuid The UUID of the characteristic.
|
||||||
|
* @param instanceId The index of the characteristic to return (used when multiple characteristics have the same UUID).
|
||||||
* @return A pointer to the characteristic object or nullptr if not found.
|
* @return A pointer to the characteristic object or nullptr if not found.
|
||||||
*/
|
*/
|
||||||
NimBLECharacteristic* NimBLEService::getCharacteristic(const NimBLEUUID &uuid) {
|
NimBLECharacteristic* NimBLEService::getCharacteristic(const NimBLEUUID &uuid, uint16_t instanceId) {
|
||||||
|
uint16_t position = 0;
|
||||||
for (auto &it : m_chrVec) {
|
for (auto &it : m_chrVec) {
|
||||||
if (it->getUUID() == uuid) {
|
if (it->getUUID() == uuid) {
|
||||||
return it;
|
if (position == instanceId) {
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
position++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get a pointer to the characteristic object with the specified handle.
|
||||||
|
* @param handle The handle of the characteristic.
|
||||||
|
* @return A pointer to the characteristic object or nullptr if not found.
|
||||||
|
*/
|
||||||
|
NimBLECharacteristic *NimBLEService::getCharacteristicByHandle(uint16_t handle) {
|
||||||
|
for (auto &it : m_chrVec) {
|
||||||
|
if (it->getHandle() == handle) {
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return A vector containing pointers to each characteristic associated with this service.
|
||||||
|
*/
|
||||||
|
std::vector<NimBLECharacteristic *> NimBLEService::getCharacteristics() {
|
||||||
|
return m_chrVec;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return A vector containing pointers to each characteristic with the provided UUID associated with this service.
|
||||||
|
*/
|
||||||
|
std::vector<NimBLECharacteristic *> NimBLEService::getCharacteristics(const char *uuid) {
|
||||||
|
return getCharacteristics(NimBLEUUID(uuid));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return A vector containing pointers to each characteristic with the provided UUID associated with this service.
|
||||||
|
*/
|
||||||
|
std::vector<NimBLECharacteristic *> NimBLEService::getCharacteristics(const NimBLEUUID &uuid) {
|
||||||
|
std::vector<NimBLECharacteristic*> result;
|
||||||
|
for (auto &it : m_chrVec) {
|
||||||
|
if (it->getUUID() == uuid) {
|
||||||
|
result.push_back(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Return a string representation of this service.
|
* @brief Return a string representation of this service.
|
||||||
|
@ -295,7 +339,7 @@ std::string NimBLEService::toString() {
|
||||||
*/
|
*/
|
||||||
NimBLEServer* NimBLEService::getServer() {
|
NimBLEServer* NimBLEService::getServer() {
|
||||||
return m_pServer;
|
return m_pServer;
|
||||||
} // getServer
|
}// getServer
|
||||||
|
|
||||||
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
#endif // CONFIG_BT_ENABLED
|
#endif // CONFIG_BT_ENABLED
|
||||||
|
|
|
@ -35,6 +35,16 @@ class NimBLECharacteristic;
|
||||||
*/
|
*/
|
||||||
class NimBLEService {
|
class NimBLEService {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
NimBLEServer* getServer();
|
||||||
|
|
||||||
|
NimBLEUUID getUUID();
|
||||||
|
uint16_t getHandle();
|
||||||
|
std::string toString();
|
||||||
|
void dump();
|
||||||
|
|
||||||
|
bool start();
|
||||||
|
|
||||||
NimBLECharacteristic* createCharacteristic(const char* uuid,
|
NimBLECharacteristic* createCharacteristic(const char* uuid,
|
||||||
uint32_t properties =
|
uint32_t properties =
|
||||||
NIMBLE_PROPERTY::READ |
|
NIMBLE_PROPERTY::READ |
|
||||||
|
@ -45,14 +55,14 @@ public:
|
||||||
NIMBLE_PROPERTY::READ |
|
NIMBLE_PROPERTY::READ |
|
||||||
NIMBLE_PROPERTY::WRITE);
|
NIMBLE_PROPERTY::WRITE);
|
||||||
|
|
||||||
void dump();
|
NimBLECharacteristic* getCharacteristic(const char* uuid, uint16_t instanceId = 0);
|
||||||
NimBLECharacteristic* getCharacteristic(const char* uuid);
|
NimBLECharacteristic* getCharacteristic(const NimBLEUUID &uuid, uint16_t instanceId = 0);
|
||||||
NimBLECharacteristic* getCharacteristic(const NimBLEUUID &uuid);
|
NimBLECharacteristic* getCharacteristicByHandle(uint16_t handle);
|
||||||
NimBLEUUID getUUID();
|
|
||||||
NimBLEServer* getServer();
|
std::vector<NimBLECharacteristic*> getCharacteristics();
|
||||||
bool start();
|
std::vector<NimBLECharacteristic*> getCharacteristics(const char* uuid);
|
||||||
std::string toString();
|
std::vector<NimBLECharacteristic*> getCharacteristics(const NimBLEUUID &uuid);
|
||||||
uint16_t getHandle();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NimBLEService(const char* uuid, uint16_t numHandles, NimBLEServer* pServer);
|
NimBLEService(const char* uuid, uint16_t numHandles, NimBLEServer* pServer);
|
||||||
|
|
Loading…
Reference in a new issue