[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:
David Robertson 2021-02-08 15:28:32 +00:00 committed by GitHub
parent 28d6492ea4
commit 7dd4d68806
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 157 additions and 53 deletions

View file

@ -101,9 +101,9 @@ NimBLEDescriptor* NimBLECharacteristic::createDescriptor(const NimBLEUUID &uuid,
/**
* @brief Return the BLE Descriptor for the given UUID if associated with this characteristic.
* @param [in] uuid The UUID of the descriptor that we wish to retrieve.
* @return pointer to the NimBLEDescriptor. If no such descriptor is associated with the characteristic, nullptr is returned.
* @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.
*/
NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(const char* 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.
* @param [in] uuid The UUID of the descriptor that we wish to retrieve.
* @return pointer to the NimBLEDescriptor. If no such descriptor is associated with the characteristic, nullptr is returned.
* @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.
*/
NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(const NimBLEUUID &uuid) {
for (auto &it : m_dscVec) {
@ -124,6 +124,20 @@ NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(const NimBLEUUID &uu
return nullptr;
} // 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.

View file

@ -59,6 +59,17 @@ class NimBLECharacteristicCallbacks;
*/
class NimBLECharacteristic {
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,
uint32_t properties =
NIMBLE_PROPERTY::READ |
@ -72,9 +83,10 @@ public:
NimBLEDescriptor* getDescriptorByUUID(const char* uuid);
NimBLEDescriptor* getDescriptorByUUID(const NimBLEUUID &uuid);
NimBLEUUID getUUID();
std::string getValue(time_t *timestamp = nullptr);
NimBLEDescriptor* getDescriptorByHandle(uint16_t handle);
std::string getValue(time_t *timestamp = nullptr);
size_t getDataLength();
/**
* @brief A template to convert the characteristic data to <type\>.
* @tparam T The type to convert the data to.
@ -92,13 +104,8 @@ public:
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 std::string &value);
/**
* @brief Convenience template to set the characteristic value to <type\>val.
* @param [in] s The value to set.
@ -108,9 +115,9 @@ public:
setValue((uint8_t*)&s, sizeof(T));
}
std::string toString();
uint16_t getHandle();
size_t getSubscribedCount();
private:

View file

@ -122,11 +122,17 @@ uint8_t* NimBLEDescriptor::getValue() {
return m_value.attr_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((char *) m_value.attr_value, m_value.attr_len);
}
int NimBLEDescriptor::handleGapEvent(uint16_t conn_handle, uint16_t attr_handle,
struct ble_gatt_access_ctxt *ctxt,
void *arg)
{
void *arg) {
const ble_uuid_t *uuid;
int rc;
NimBLEDescriptor* pDescriptor = (NimBLEDescriptor*)arg;

View file

@ -44,14 +44,17 @@ class NimBLEDescriptorCallbacks;
class NimBLEDescriptor {
public:
uint16_t getHandle();
size_t getLength();
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();
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.
* @param [in] s The value to set.

View file

@ -104,28 +104,47 @@ NimBLEService* NimBLEServer::createService(const NimBLEUUID &uuid, uint32_t numH
/**
* @brief Get a %BLE Service by its UUID
* @param [in] uuid The UUID of the new service.
* @return A reference to the service object.
* @param [in] uuid The UUID of the service.
* @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) {
return getServiceByUUID(NimBLEUUID(uuid));
NimBLEService* NimBLEServer::getServiceByUUID(const char* uuid, uint16_t instanceId) {
return getServiceByUUID(NimBLEUUID(uuid), instanceId);
} // getServiceByUUID
/**
* @brief Get a %BLE Service by its UUID
* @param [in] uuid The UUID of the new service.
* @return A reference to the service object.
* @param [in] uuid The UUID of the service.
* @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) {
if (it->getUUID() == uuid) {
if (position == instanceId){
return it;
}
position++;
}
}
return nullptr;
} // 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.

View file

@ -49,8 +49,9 @@ public:
void startAdvertising();
void stopAdvertising();
void start();
NimBLEService* getServiceByUUID(const char* uuid);
NimBLEService* getServiceByUUID(const NimBLEUUID &uuid);
NimBLEService* getServiceByUUID(const char* uuid, uint16_t instanceId = 0);
NimBLEService* getServiceByUUID(const NimBLEUUID &uuid, uint16_t instanceId = 0);
NimBLEService* getServiceByHandle(uint16_t handle);
int disconnect(uint16_t connID,
uint8_t reason = BLE_ERR_REM_USER_CONN_TERM);
void updateConnParams(uint16_t conn_handle,

View file

@ -233,9 +233,9 @@ NimBLECharacteristic* NimBLEService::createCharacteristic(const char* uuid, uint
*/
NimBLECharacteristic* NimBLEService::createCharacteristic(const NimBLEUUID &uuid, uint32_t properties) {
NimBLECharacteristic* pCharacteristic = new NimBLECharacteristic(uuid, properties, this);
// Check that we don't add the same characteristic twice.
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());
}
@ -249,28 +249,72 @@ NimBLECharacteristic* NimBLEService::createCharacteristic(const NimBLEUUID &uuid
/**
* @brief Get a pointer to the characteristic object with the specified UUID.
* @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.
*/
NimBLECharacteristic* NimBLEService::getCharacteristic(const char* uuid) {
return getCharacteristic(NimBLEUUID(uuid));
NimBLECharacteristic* NimBLEService::getCharacteristic(const char* uuid, uint16_t instanceId) {
return getCharacteristic(NimBLEUUID(uuid), instanceId);
}
/**
* @brief Get a pointer to the characteristic object with the specified UUID.
* @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.
*/
NimBLECharacteristic* NimBLEService::getCharacteristic(const NimBLEUUID &uuid) {
NimBLECharacteristic* NimBLEService::getCharacteristic(const NimBLEUUID &uuid, uint16_t instanceId) {
uint16_t position = 0;
for (auto &it : m_chrVec) {
if (it->getUUID() == uuid) {
if (position == instanceId) {
return it;
}
position++;
}
}
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.

View file

@ -35,6 +35,16 @@ class NimBLECharacteristic;
*/
class NimBLEService {
public:
NimBLEServer* getServer();
NimBLEUUID getUUID();
uint16_t getHandle();
std::string toString();
void dump();
bool start();
NimBLECharacteristic* createCharacteristic(const char* uuid,
uint32_t properties =
NIMBLE_PROPERTY::READ |
@ -45,14 +55,14 @@ public:
NIMBLE_PROPERTY::READ |
NIMBLE_PROPERTY::WRITE);
void dump();
NimBLECharacteristic* getCharacteristic(const char* uuid);
NimBLECharacteristic* getCharacteristic(const NimBLEUUID &uuid);
NimBLEUUID getUUID();
NimBLEServer* getServer();
bool start();
std::string toString();
uint16_t getHandle();
NimBLECharacteristic* getCharacteristic(const char* uuid, uint16_t instanceId = 0);
NimBLECharacteristic* getCharacteristic(const NimBLEUUID &uuid, uint16_t instanceId = 0);
NimBLECharacteristic* getCharacteristicByHandle(uint16_t handle);
std::vector<NimBLECharacteristic*> getCharacteristics();
std::vector<NimBLECharacteristic*> getCharacteristics(const char* uuid);
std::vector<NimBLECharacteristic*> getCharacteristics(const NimBLEUUID &uuid);
private:
NimBLEService(const char* uuid, uint16_t numHandles, NimBLEServer* pServer);