Add NimBLEAttValue class. (#67)

This is a specialized container class to hold BLE attribute values.

- Removes the use of std::string previously used to store the values.
- Allows for setting/getting/notifying values from std::string, std::vector<uint8_t>, Arduino String, const char*, and uint8_t buffers.
- Has operators retrieve the value as std::string, Arduino String, std::vector<uint8_t>, uint8_t* or char pointers.
- Includes iterators and subscript/random access operator.
- Introduces a max length parameter to the creation of server characteristics/descriptors to limit the size of the memory footprint.
- Nearly Seamless integration with existing code.
- Adds a config option to enable/disable timestamp storage when the value is updated.
- Adds a config option to specify the initial size of the value container if not specified in the constructor.
This commit is contained in:
h2zero authored and GitHub committed 2022-01-16 20:11:18 -07:00
1 parent be9cdc1ab6
commit e3ee082dd7
17 files changed
+901 -296

No files matched your search

+76 -47
View File
@@ -44,6 +44,7 @@ typedef enum {
#include "NimBLEService.h"
#include "NimBLEDescriptor.h"
#include "NimBLEAttValue.h"
#include <string>
#include <vector>
@@ -65,11 +66,13 @@ public:
uint16_t properties =
NIMBLE_PROPERTY::READ |
NIMBLE_PROPERTY::WRITE,
uint16_t max_len = BLE_ATT_ATTR_MAX_LEN,
NimBLEService* pService = nullptr);
NimBLECharacteristic(const NimBLEUUID &uuid,
uint16_t properties =
NIMBLE_PROPERTY::READ |
NIMBLE_PROPERTY::WRITE,
uint16_t max_len = BLE_ATT_ATTR_MAX_LEN,
NimBLEService* pService = nullptr);
~NimBLECharacteristic();
@@ -77,66 +80,93 @@ public:
uint16_t getHandle();
NimBLEUUID getUUID();
std::string toString();
void setCallbacks(NimBLECharacteristicCallbacks* pCallbacks);
NimBLECharacteristicCallbacks*
getCallbacks();
void indicate();
void indicate(const uint8_t* value, size_t length);
void indicate(const std::vector<uint8_t>& value);
void notify(bool is_notification = true);
void notify(std::string value, bool is_notification = true);
void notify(const uint8_t* value, size_t length, bool is_notification = true);
void notify(const std::vector<uint8_t>& value, bool is_notification = true);
size_t getSubscribedCount();
NimBLEDescriptor* createDescriptor(const char* uuid,
uint32_t properties =
NIMBLE_PROPERTY::READ |
NIMBLE_PROPERTY::WRITE,
uint16_t max_len = 100);
NimBLEDescriptor* createDescriptor(const NimBLEUUID &uuid,
uint32_t properties =
NIMBLE_PROPERTY::READ |
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);
void removeDescriptor(NimBLEDescriptor *pDescriptor, bool deleteDsc = false);
std::string getValue(time_t *timestamp = nullptr);
NimBLEService* getService();
uint16_t getProperties();
NimBLEAttValue 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.
* @param [in] timestamp A pointer to a time_t struct to store the time the value was read.
* @param [in] skipSizeCheck If true it will skip checking if the data size is less than <tt>sizeof(<type\>)</tt>.
* @return The data converted to <type\> or NULL if skipSizeCheck is false and the data is
* less than <tt>sizeof(<type\>)</tt>.
* @details <b>Use:</b> <tt>getValue<type>(&timestamp, skipSizeCheck);</tt>
*/
template<typename T>
T getValue(time_t *timestamp = nullptr, bool skipSizeCheck = false) {
std::string value = getValue();
if(!skipSizeCheck && value.size() < sizeof(T)) return T();
const char *pData = value.data();
return *((T *)pData);
}
void setValue(const uint8_t* data, size_t size);
void setValue(const std::string &value);
void setValue(const std::vector<uint8_t>& vec);
void setCallbacks(NimBLECharacteristicCallbacks* pCallbacks);
NimBLEDescriptor* createDescriptor(const char* uuid,
uint32_t properties =
NIMBLE_PROPERTY::READ |
NIMBLE_PROPERTY::WRITE,
uint16_t max_len = BLE_ATT_ATTR_MAX_LEN);;
NimBLEDescriptor* createDescriptor(const NimBLEUUID &uuid,
uint32_t properties =
NIMBLE_PROPERTY::READ |
NIMBLE_PROPERTY::WRITE,
uint16_t max_len = BLE_ATT_ATTR_MAX_LEN);
NimBLECharacteristicCallbacks* getCallbacks();
/*********************** Template Functions ************************/
/**
* @brief Convenience template to set the characteristic value to <type\>val.
* @brief Template to set the characteristic value to <type\>val.
* @param [in] s The value to set.
*/
template<typename T>
void setValue(const T &s) {
setValue((uint8_t*)&s, sizeof(T));
void setValue(const T &s) { m_value.setValue<T>(s); }
/**
* @brief Template to convert the characteristic data to <type\>.
* @tparam T The type to convert the data to.
* @param [in] timestamp (Optional) A pointer to a time_t struct to store the time the value was read.
* @param [in] skipSizeCheck (Optional) If true it will skip checking if the data size is less than <tt>sizeof(<type\>)</tt>.
* @return The data converted to <type\> or NULL if skipSizeCheck is false and the data is less than <tt>sizeof(<type\>)</tt>.
* @details <b>Use:</b> <tt>getValue<type>(&timestamp, skipSizeCheck);</tt>
*/
template<typename T>
T getValue(time_t *timestamp = nullptr, bool skipSizeCheck = false) {
return m_value.getValue<T>(timestamp, skipSizeCheck);
}
NimBLEService* getService();
uint16_t getProperties();
/**
* @brief Template to send a notification from a class type that has a c_str() and length() method.
* @tparam T The a reference to a class containing the data to send.
* @param[in] value The <type\>value to set.
* @param[in] is_notification if true sends a notification, false sends an indication.
* @details Only used if the <type\> has a `c_str()` method.
*/
template<typename T>
#ifdef _DOXYGEN_
void
#else
typename std::enable_if<Has_c_str_len<T>::value, void>::type
#endif
notify(const T& value, bool is_notification = true) {
notify((uint8_t*)value.c_str(), value.length(), is_notification);
}
/**
* @brief Template to send an indication from a class type that has a c_str() and length() method.
* @tparam T The a reference to a class containing the data to send.
* @param[in] value The <type\>value to set.
* @details Only used if the <type\> has a `c_str()` method.
*/
template<typename T>
#ifdef _DOXYGEN_
void
#else
typename std::enable_if<Has_c_str_len<T>::value, void>::type
#endif
indicate(const T& value) {
indicate((uint8_t*)value.c_str(), value.length());
}
private:
@@ -153,9 +183,8 @@ private:
uint16_t m_properties;
NimBLECharacteristicCallbacks* m_pCallbacks;
NimBLEService* m_pService;
std::string m_value;
NimBLEAttValue m_value;
std::vector<NimBLEDescriptor*> m_dscVec;
time_t m_timestamp;
uint8_t m_removed;
std::vector<std::pair<uint16_t, uint16_t>> m_subscribedVec;
@@ -188,7 +217,7 @@ public:
ERROR_INDICATE_FAILURE
}Status;
virtual ~NimBLECharacteristicCallbacks();
virtual ~NimBLECharacteristicCallbacks();
virtual void onRead(NimBLECharacteristic* pCharacteristic);
virtual void onRead(NimBLECharacteristic* pCharacteristic, ble_gap_conn_desc* desc);
virtual void onWrite(NimBLECharacteristic* pCharacteristic);