From d9d794ae40031dc636f6168cdfc30f4c0e137d43 Mon Sep 17 00:00:00 2001 From: h2zero Date: Sun, 23 May 2021 13:07:00 -0600 Subject: [PATCH] [Server] Add ability to create static attributes. This allows creating instances of services/characteristics and decriptors without needing to call the parent createX() methods. This allows creation of the attibutes within a class or other structure and the attributes can be linked to the parent by calling the parent addX() method. Additonally this increases the backward compatibility with the original bluedroid library to further support user migration. --- src/NimBLE2904.h | 2 +- src/NimBLECharacteristic.cpp | 20 ++++++++++++++-- src/NimBLECharacteristic.h | 38 +++++++++++++++---------------- src/NimBLEDescriptor.cpp | 25 +++++++++++++++++--- src/NimBLEDescriptor.h | 44 +++++++++++++++++++----------------- src/NimBLEServer.cpp | 13 +++++++++-- src/NimBLEService.cpp | 5 ++++ src/NimBLEService.h | 8 ++++--- 8 files changed, 103 insertions(+), 52 deletions(-) diff --git a/src/NimBLE2904.h b/src/NimBLE2904.h index 0a6d036..d8800dd 100644 --- a/src/NimBLE2904.h +++ b/src/NimBLE2904.h @@ -42,6 +42,7 @@ struct BLE2904_Data { */ class NimBLE2904: public NimBLEDescriptor { public: + NimBLE2904(NimBLECharacteristic* pCharacterisitic = nullptr); static const uint8_t FORMAT_BOOLEAN = 1; static const uint8_t FORMAT_UINT2 = 2; static const uint8_t FORMAT_UINT4 = 3; @@ -77,7 +78,6 @@ public: void setUnit(uint16_t unit); private: - NimBLE2904(NimBLECharacteristic* pCharacterisitic); friend class NimBLECharacteristic; BLE2904_Data m_data; }; // BLE2904 diff --git a/src/NimBLECharacteristic.cpp b/src/NimBLECharacteristic.cpp index 9e31255..39e7edf 100644 --- a/src/NimBLECharacteristic.cpp +++ b/src/NimBLECharacteristic.cpp @@ -94,9 +94,20 @@ NimBLEDescriptor* NimBLECharacteristic::createDescriptor(const NimBLEUUID &uuid, pDescriptor = new NimBLEDescriptor(uuid, properties, max_len, this); } - m_dscVec.push_back(pDescriptor); + addDescriptor(pDescriptor); + return pDescriptor; -} // createCharacteristic +} // createDescriptor + + +/** + * @brief Add a descriptor to the characteristic. + * @param [in] A pointer to the descriptor to add. + */ +void NimBLECharacteristic::addDescriptor(NimBLEDescriptor *pDescriptor) { + pDescriptor->setCharacteristic(this); + m_dscVec.push_back(pDescriptor); +} /** @@ -164,6 +175,11 @@ NimBLEService* NimBLECharacteristic::getService() { } // getService +void NimBLECharacteristic::setService(NimBLEService *pService) { + m_pService = pService; +} + + /** * @brief Get the UUID of the characteristic. * @return The UUID of the characteristic. diff --git a/src/NimBLECharacteristic.h b/src/NimBLECharacteristic.h index aee21b0..7685b2a 100644 --- a/src/NimBLECharacteristic.h +++ b/src/NimBLECharacteristic.h @@ -59,6 +59,18 @@ class NimBLECharacteristicCallbacks; */ class NimBLECharacteristic { public: + NimBLECharacteristic(const char* uuid, + uint16_t properties = + NIMBLE_PROPERTY::READ | + NIMBLE_PROPERTY::WRITE, + NimBLEService* pService = nullptr); + NimBLECharacteristic(const NimBLEUUID &uuid, + uint16_t properties = + NIMBLE_PROPERTY::READ | + NIMBLE_PROPERTY::WRITE, + NimBLEService* pService = nullptr); + + ~NimBLECharacteristic(); uint16_t getHandle(); NimBLEUUID getUUID(); @@ -83,6 +95,7 @@ public: NIMBLE_PROPERTY::WRITE, uint16_t max_len = 100); + void addDescriptor(NimBLEDescriptor *pDescriptor); NimBLEDescriptor* getDescriptorByUUID(const char* uuid); NimBLEDescriptor* getDescriptorByUUID(const NimBLEUUID &uuid); NimBLEDescriptor* getDescriptorByHandle(uint16_t handle); @@ -117,30 +130,15 @@ public: setValue((uint8_t*)&s, sizeof(T)); } - - - + NimBLEService* getService(); + uint16_t getProperties(); private: - friend class NimBLEServer; - friend class NimBLEService; + friend class NimBLEServer; + friend class NimBLEService; - NimBLECharacteristic(const char* uuid, - uint16_t properties = - NIMBLE_PROPERTY::READ | - NIMBLE_PROPERTY::WRITE, - NimBLEService* pService = nullptr); - NimBLECharacteristic(const NimBLEUUID &uuid, - uint16_t properties = - NIMBLE_PROPERTY::READ | - NIMBLE_PROPERTY::WRITE, - NimBLEService* pService = nullptr); - - ~NimBLECharacteristic(); - - NimBLEService* getService(); - uint16_t getProperties(); + void setService(NimBLEService *pService); void setSubscribe(struct ble_gap_event *event); static int handleGapEvent(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg); diff --git a/src/NimBLEDescriptor.cpp b/src/NimBLEDescriptor.cpp index 5f3e97f..db7aea5 100644 --- a/src/NimBLEDescriptor.cpp +++ b/src/NimBLEDescriptor.cpp @@ -37,6 +37,7 @@ NimBLEDescriptor::NimBLEDescriptor(const char* uuid, uint16_t properties, uint16 : NimBLEDescriptor(NimBLEUUID(uuid), max_len, properties, pCharacteristic) { } + /** * @brief NimBLEDescriptor constructor. */ @@ -47,7 +48,7 @@ NimBLEDescriptor::NimBLEDescriptor(NimBLEUUID uuid, uint16_t properties, uint16_ m_value.attr_len = 0; // Initial length is 0. m_value.attr_max_len = max_len; // Maximum length of the data. m_handle = NULL_HANDLE; // Handle is initially unknown. - m_pCharacteristic = nullptr; // No initial characteristic. + m_pCharacteristic = pCharacteristic; m_pCallbacks = &defaultCallbacks; // No initial callback. m_value.attr_value = (uint8_t*) calloc(max_len,1); // Allocate storage for the value. m_valMux = portMUX_INITIALIZER_UNLOCKED; @@ -122,6 +123,7 @@ 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. @@ -130,9 +132,18 @@ std::string NimBLEDescriptor::getStringValue() { return std::string((char *) m_value.attr_value, m_value.attr_len); } + +/** + * @brief Get the characteristic this descriptor belongs to. + * @return A pointer to the characteristic this descriptor belongs to. + */ +NimBLECharacteristic* NimBLEDescriptor::getCharacteristic() { + return m_pCharacteristic; +} // getCharacteristic + + int NimBLEDescriptor::handleGapEvent(uint16_t conn_handle, uint16_t attr_handle, - struct ble_gatt_access_ctxt *ctxt, - void *arg) { + struct ble_gatt_access_ctxt *ctxt, void *arg) { const ble_uuid_t *uuid; int rc; NimBLEDescriptor* pDescriptor = (NimBLEDescriptor*)arg; @@ -237,6 +248,14 @@ void NimBLEDescriptor::setValue(const std::string &value) { setValue((uint8_t*) value.data(), value.length()); } // setValue +/** + * @brief Set the characteristic this descriptor belongs to. + * @param [in] pChar A pointer to the characteristic this descriptior belongs to. + */ +void NimBLEDescriptor::setCharacteristic(NimBLECharacteristic* pChar) { + m_pCharacteristic = pChar; +} // setCharacteristic + /** * @brief Return a string representation of the descriptor. diff --git a/src/NimBLEDescriptor.h b/src/NimBLEDescriptor.h index 76318b7..d325c7b 100644 --- a/src/NimBLEDescriptor.h +++ b/src/NimBLEDescriptor.h @@ -43,46 +43,48 @@ class NimBLEDescriptorCallbacks; */ class NimBLEDescriptor { public: - uint16_t getHandle(); - NimBLEUUID getUUID(); - std::string toString(); + NimBLEDescriptor(const char* uuid, uint16_t properties, + uint16_t max_len, + NimBLECharacteristic* pCharacteristic = nullptr); - void setCallbacks(NimBLEDescriptorCallbacks* pCallbacks); + NimBLEDescriptor(NimBLEUUID uuid, uint16_t properties, + uint16_t max_len, + NimBLECharacteristic* pCharacteristic = nullptr); - size_t getLength(); - uint8_t* getValue(); - std::string getStringValue(); + ~NimBLEDescriptor(); + + uint16_t getHandle(); + NimBLEUUID getUUID(); + 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); + NimBLECharacteristic* getCharacteristic(); - void setValue(const uint8_t* data, size_t size); - void setValue(const std::string &value); /** * @brief Convenience template to set the descriptor value to val. * @param [in] s The value to set. */ template - void setValue(const T &s) { + void setValue(const T &s) { setValue((uint8_t*)&s, sizeof(T)); } private: friend class NimBLECharacteristic; friend class NimBLEService; - friend class NimBLE2902; friend class NimBLE2904; - NimBLEDescriptor(const char* uuid, uint16_t properties, - uint16_t max_len, - NimBLECharacteristic* pCharacteristic); - - NimBLEDescriptor(NimBLEUUID uuid, uint16_t properties, - uint16_t max_len, - NimBLECharacteristic* pCharacteristic); - - ~NimBLEDescriptor(); - static int handleGapEvent(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg); void setHandle(uint16_t handle); + void setCharacteristic(NimBLECharacteristic* pChar); NimBLEUUID m_uuid; uint16_t m_handle; diff --git a/src/NimBLEServer.cpp b/src/NimBLEServer.cpp index 1b88503..ca4729d 100644 --- a/src/NimBLEServer.cpp +++ b/src/NimBLEServer.cpp @@ -650,14 +650,23 @@ void NimBLEServer::removeService(NimBLEService* service, bool deleteSvc) { /** - * @brief Adds a service which was already created, but removed from availability. + * @brief Adds a service which was either already created but removed from availability,\n + * or created and later added to services list. * @param [in] service The service object to add. * @note If it is desired to advertise the service it must be added by * calling NimBLEAdvertising::addServiceUUID. */ void NimBLEServer::addService(NimBLEService* service) { - // If adding a service that was not removed just return. + // Check that a service with the supplied UUID does not already exist. + if(getServiceByUUID(service->getUUID()) != nullptr) { + NIMBLE_LOGW(LOG_TAG, "Warning creating a duplicate service UUID: %s", + std::string(service->getUUID()).c_str()); + } + + // If adding a service that was not removed add it and return. + // Else reset GATT and send service changed notification. if(service->m_removed == 0) { + m_svcVec.push_back(service); return; } diff --git a/src/NimBLEService.cpp b/src/NimBLEService.cpp index a830eec..422eefe 100644 --- a/src/NimBLEService.cpp +++ b/src/NimBLEService.cpp @@ -246,6 +246,11 @@ NimBLECharacteristic* NimBLEService::createCharacteristic(const NimBLEUUID &uuid } // createCharacteristic +void NimBLEService::addCharacteristic(NimBLECharacteristic* pCharacteristic) { + pCharacteristic->setService(this); + m_chrVec.push_back(pCharacteristic); +} + /** * @brief Get a pointer to the characteristic object with the specified UUID. * @param [in] uuid The UUID of the characteristic. diff --git a/src/NimBLEService.h b/src/NimBLEService.h index 1203d3e..57e92c0 100644 --- a/src/NimBLEService.h +++ b/src/NimBLEService.h @@ -36,6 +36,10 @@ class NimBLECharacteristic; class NimBLEService { public: + NimBLEService(const char* uuid, uint16_t numHandles, NimBLEServer* pServer); + NimBLEService(const NimBLEUUID &uuid, uint16_t numHandles, NimBLEServer* pServer); + ~NimBLEService(); + NimBLEServer* getServer(); NimBLEUUID getUUID(); @@ -55,6 +59,7 @@ public: NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE); + void addCharacteristic(NimBLECharacteristic* pCharacteristic); NimBLECharacteristic* getCharacteristic(const char* uuid, uint16_t instanceId = 0); NimBLECharacteristic* getCharacteristic(const NimBLEUUID &uuid, uint16_t instanceId = 0); NimBLECharacteristic* getCharacteristicByHandle(uint16_t handle); @@ -65,9 +70,6 @@ public: private: - NimBLEService(const char* uuid, uint16_t numHandles, NimBLEServer* pServer); - NimBLEService(const NimBLEUUID &uuid, uint16_t numHandles, NimBLEServer* pServer); - ~NimBLEService(); friend class NimBLEServer; friend class NimBLEDevice;