mirror of
https://github.com/h2zero/esp-nimble-cpp.git
synced 2024-11-21 20:50:55 +01:00
Refactor NimBLEAttValue.
* Add length parameter to `setValue()` templates, with defaults for backward compatibility. * Changed `setValue(const char*)` to add an optional length parameter so that a NULL character can be included, defaults to strlen. * Moved non-inline functions to `NimBLEAttValue.cpp` file. * Corrected includes to permit compilation as a stand-alone utility. * Removed repeated code in `setValue()` by using `append()` after clearing the value. * General code cleanup.
This commit is contained in:
parent
8c4832f711
commit
d1d1b49a26
3 changed files with 268 additions and 261 deletions
|
@ -39,6 +39,7 @@ idf_component_register(
|
||||||
"src/NimBLEAddress.cpp"
|
"src/NimBLEAddress.cpp"
|
||||||
"src/NimBLEAdvertisedDevice.cpp"
|
"src/NimBLEAdvertisedDevice.cpp"
|
||||||
"src/NimBLEAdvertising.cpp"
|
"src/NimBLEAdvertising.cpp"
|
||||||
|
"src/NimBLEAttValue.cpp"
|
||||||
"src/NimBLEBeacon.cpp"
|
"src/NimBLEBeacon.cpp"
|
||||||
"src/NimBLECharacteristic.cpp"
|
"src/NimBLECharacteristic.cpp"
|
||||||
"src/NimBLEClient.cpp"
|
"src/NimBLEClient.cpp"
|
||||||
|
|
130
src/NimBLEAttValue.cpp
Normal file
130
src/NimBLEAttValue.cpp
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
/*
|
||||||
|
* NimBLEAttValue.cpp
|
||||||
|
*
|
||||||
|
* Created: on July 17, 2024
|
||||||
|
* Author H2zero
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "nimconfig.h"
|
||||||
|
#if defined(CONFIG_BT_ENABLED)
|
||||||
|
|
||||||
|
# if defined(CONFIG_NIMBLE_CPP_IDF)
|
||||||
|
# include "nimble/nimble_npl.h"
|
||||||
|
# else
|
||||||
|
# include "nimble/nimble/include/nimble/nimble_npl.h"
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# include "NimBLEAttValue.h"
|
||||||
|
|
||||||
|
// Default constructor implementation.
|
||||||
|
NimBLEAttValue::NimBLEAttValue(uint16_t init_len, uint16_t max_len)
|
||||||
|
: m_attr_value{static_cast<uint8_t*>(calloc(init_len + 1, 1))},
|
||||||
|
m_attr_max_len{std::min<uint16_t>(BLE_ATT_ATTR_MAX_LEN, max_len)},
|
||||||
|
m_attr_len{},
|
||||||
|
m_capacity{init_len}
|
||||||
|
# if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
|
||||||
|
,
|
||||||
|
m_timestamp{}
|
||||||
|
# endif
|
||||||
|
{
|
||||||
|
NIMBLE_CPP_DEBUG_ASSERT(m_attr_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value constructor implementation.
|
||||||
|
NimBLEAttValue::NimBLEAttValue(const uint8_t *value, uint16_t len, uint16_t max_len)
|
||||||
|
: NimBLEAttValue(len, max_len) {
|
||||||
|
memcpy(m_attr_value, value, len);
|
||||||
|
m_attr_value[len] = '\0';
|
||||||
|
m_attr_len = len;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destructor implementation.
|
||||||
|
NimBLEAttValue::~NimBLEAttValue() {
|
||||||
|
if (m_attr_value != nullptr) {
|
||||||
|
free(m_attr_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move assignment operator implementation.
|
||||||
|
NimBLEAttValue& NimBLEAttValue::operator=(NimBLEAttValue&& source) {
|
||||||
|
if (this != &source) {
|
||||||
|
free(m_attr_value);
|
||||||
|
m_attr_value = source.m_attr_value;
|
||||||
|
m_attr_max_len = source.m_attr_max_len;
|
||||||
|
m_attr_len = source.m_attr_len;
|
||||||
|
m_capacity = source.m_capacity;
|
||||||
|
setTimeStamp(source.getTimeStamp());
|
||||||
|
source.m_attr_value = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy assignment implementation.
|
||||||
|
NimBLEAttValue& NimBLEAttValue::operator=(const NimBLEAttValue& source) {
|
||||||
|
if (this != &source) {
|
||||||
|
deepCopy(source);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy all the data from the source object to this object, including allocated space.
|
||||||
|
void NimBLEAttValue::deepCopy(const NimBLEAttValue& source) {
|
||||||
|
uint8_t* res = static_cast<uint8_t*>(realloc(m_attr_value, source.m_capacity + 1));
|
||||||
|
NIMBLE_CPP_DEBUG_ASSERT(res);
|
||||||
|
|
||||||
|
ble_npl_hw_enter_critical();
|
||||||
|
m_attr_value = res;
|
||||||
|
m_attr_max_len = source.m_attr_max_len;
|
||||||
|
m_attr_len = source.m_attr_len;
|
||||||
|
m_capacity = source.m_capacity;
|
||||||
|
setTimeStamp(source.getTimeStamp());
|
||||||
|
memcpy(m_attr_value, source.m_attr_value, m_attr_len + 1);
|
||||||
|
ble_npl_hw_exit_critical(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the value of the attribute.
|
||||||
|
bool NimBLEAttValue::setValue(const uint8_t* value, uint16_t len) {
|
||||||
|
m_attr_len = 0; // Just set the value length to 0 and append instead of repeating code.
|
||||||
|
append(value, len);
|
||||||
|
return memcmp(m_attr_value, value, len) == 0 && m_attr_len == len;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append the new data, allocate as necessary.
|
||||||
|
NimBLEAttValue& NimBLEAttValue::append(const uint8_t* value, uint16_t len) {
|
||||||
|
if (len == 0) {
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((m_attr_len + len) > m_attr_max_len) {
|
||||||
|
NIMBLE_LOGE("NimBLEAttValue", "val > max, len=%u, max=%u", len, m_attr_max_len);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t* res = m_attr_value;
|
||||||
|
uint16_t new_len = m_attr_len + len;
|
||||||
|
if (new_len > m_capacity) {
|
||||||
|
res = static_cast<uint8_t*>(realloc(m_attr_value, (new_len + 1)));
|
||||||
|
m_capacity = new_len;
|
||||||
|
}
|
||||||
|
NIMBLE_CPP_DEBUG_ASSERT(res);
|
||||||
|
|
||||||
|
# if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
|
||||||
|
time_t t = time(nullptr);
|
||||||
|
# else
|
||||||
|
time_t t = 0;
|
||||||
|
# endif
|
||||||
|
|
||||||
|
ble_npl_hw_enter_critical();
|
||||||
|
memcpy(res + m_attr_len, value, len);
|
||||||
|
m_attr_value = res;
|
||||||
|
m_attr_len = new_len;
|
||||||
|
m_attr_value[m_attr_len] = '\0';
|
||||||
|
setTimeStamp(t);
|
||||||
|
ble_npl_hw_exit_critical(0);
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CONFIG_BT_ENABLED
|
|
@ -6,50 +6,45 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef MAIN_NIMBLEATTVALUE_H_
|
#ifndef NIMBLE_CPP_ATTVALUE_H
|
||||||
#define MAIN_NIMBLEATTVALUE_H_
|
#define NIMBLE_CPP_ATTVALUE_H
|
||||||
#include "nimconfig.h"
|
#include "nimconfig.h"
|
||||||
#if defined(CONFIG_BT_ENABLED)
|
#if defined(CONFIG_BT_ENABLED)
|
||||||
|
|
||||||
#ifdef NIMBLE_CPP_ARDUINO_STRING_AVAILABLE
|
# ifdef NIMBLE_CPP_ARDUINO_STRING_AVAILABLE
|
||||||
#include <Arduino.h>
|
# include <Arduino.h>
|
||||||
#endif
|
# endif
|
||||||
|
|
||||||
#include "NimBLELog.h"
|
# include "NimBLELog.h"
|
||||||
|
# include <string>
|
||||||
|
# include <vector>
|
||||||
|
# include <ctime>
|
||||||
|
# include <cstring>
|
||||||
|
# include <cstdint>
|
||||||
|
|
||||||
/**** FIX COMPILATION ****/
|
# ifndef CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
|
||||||
#undef min
|
|
||||||
#undef max
|
|
||||||
/**************************/
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include <ctime>
|
|
||||||
|
|
||||||
#ifndef CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
|
|
||||||
# define CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED 0
|
# define CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED 0
|
||||||
#endif
|
# endif
|
||||||
|
|
||||||
#if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
|
# ifndef BLE_ATT_ATTR_MAX_LEN
|
||||||
# include <time.h>
|
# define BLE_ATT_ATTR_MAX_LEN 512
|
||||||
#endif
|
# endif
|
||||||
|
|
||||||
#if !defined(CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH)
|
# if !defined(CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH)
|
||||||
# define CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH 20
|
# define CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH 20
|
||||||
#elif CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH > BLE_ATT_ATTR_MAX_LEN
|
# elif CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH > BLE_ATT_ATTR_MAX_LEN
|
||||||
# error CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH cannot be larger than 512 (BLE_ATT_ATTR_MAX_LEN)
|
# error CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH cannot be larger than 512 (BLE_ATT_ATTR_MAX_LEN)
|
||||||
#elif CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH < 1
|
# elif CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH < 1
|
||||||
# error CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH cannot be less than 1; Range = 1 : 512
|
# error CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH cannot be less than 1; Range = 1 : 512
|
||||||
#endif
|
# endif
|
||||||
|
|
||||||
/* Used to determine if the type passed to a template has a c_str() and length() method. */
|
/* Used to determine if the type passed to a template has a c_str() and length() method. */
|
||||||
template <typename T, typename = void, typename = void>
|
template <typename T, typename = void, typename = void>
|
||||||
struct Has_c_str_len : std::false_type {};
|
struct Has_c_str_len : std::false_type {};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct Has_c_str_len<T, decltype(void(std::declval<T &>().c_str())),
|
struct Has_c_str_len<T, decltype(void(std::declval<T&>().c_str())), decltype(void(std::declval<T&>().length()))>
|
||||||
decltype(void(std::declval<T &>().length()))> : std::true_type {};
|
: std::true_type {};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A specialized container class to hold BLE attribute values.
|
* @brief A specialized container class to hold BLE attribute values.
|
||||||
|
@ -57,25 +52,23 @@ struct Has_c_str_len<T, decltype(void(std::declval<T &>().c_str())),
|
||||||
* standard container types for value storage, while being convertible to\n
|
* standard container types for value storage, while being convertible to\n
|
||||||
* many different container classes.
|
* many different container classes.
|
||||||
*/
|
*/
|
||||||
class NimBLEAttValue
|
class NimBLEAttValue {
|
||||||
{
|
uint8_t* m_attr_value{};
|
||||||
uint8_t* m_attr_value = nullptr;
|
uint16_t m_attr_max_len{};
|
||||||
uint16_t m_attr_max_len = 0;
|
uint16_t m_attr_len{};
|
||||||
uint16_t m_attr_len = 0;
|
uint16_t m_capacity{};
|
||||||
uint16_t m_capacity = 0;
|
# if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
|
||||||
#if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
|
time_t m_timestamp{};
|
||||||
time_t m_timestamp = 0;
|
# endif
|
||||||
#endif
|
void deepCopy(const NimBLEAttValue& source);
|
||||||
void deepCopy(const NimBLEAttValue & source);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief Default constructor.
|
* @brief Default constructor.
|
||||||
* @param[in] init_len The initial size in bytes.
|
* @param[in] init_len The initial size in bytes.
|
||||||
* @param[in] max_len The max size in bytes that the value can be.
|
* @param[in] max_len The max size in bytes that the value can be.
|
||||||
*/
|
*/
|
||||||
NimBLEAttValue(uint16_t init_len = CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH,
|
NimBLEAttValue(uint16_t init_len = CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH, uint16_t max_len = BLE_ATT_ATTR_MAX_LEN);
|
||||||
uint16_t max_len = BLE_ATT_ATTR_MAX_LEN);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Construct with an initial value from a buffer.
|
* @brief Construct with an initial value from a buffer.
|
||||||
|
@ -86,15 +79,6 @@ public:
|
||||||
NimBLEAttValue(const uint8_t *value, uint16_t len,
|
NimBLEAttValue(const uint8_t *value, uint16_t len,
|
||||||
uint16_t max_len = BLE_ATT_ATTR_MAX_LEN);
|
uint16_t max_len = BLE_ATT_ATTR_MAX_LEN);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Construct with an initializer list.
|
|
||||||
* @param list An initializer list containing the initial value to set.
|
|
||||||
* @param[in] max_len The max size in bytes that the value can be.
|
|
||||||
*/
|
|
||||||
NimBLEAttValue(std::initializer_list<uint8_t> list,
|
|
||||||
uint16_t max_len = BLE_ATT_ATTR_MAX_LEN)
|
|
||||||
:NimBLEAttValue(list.begin(), (uint16_t)list.size(), max_len){}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Construct with an initial value from a const char string.
|
* @brief Construct with an initial value from a const char string.
|
||||||
* @param value A pointer to the initial value to set.
|
* @param value A pointer to the initial value to set.
|
||||||
|
@ -103,13 +87,21 @@ public:
|
||||||
NimBLEAttValue(const char *value, uint16_t max_len = BLE_ATT_ATTR_MAX_LEN)
|
NimBLEAttValue(const char *value, uint16_t max_len = BLE_ATT_ATTR_MAX_LEN)
|
||||||
:NimBLEAttValue((uint8_t*)value, (uint16_t)strlen(value), max_len){}
|
:NimBLEAttValue((uint8_t*)value, (uint16_t)strlen(value), max_len){}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Construct with an initializer list.
|
||||||
|
* @param list An initializer list containing the initial value to set.
|
||||||
|
* @param[in] max_len The max size in bytes that the value can be.
|
||||||
|
*/
|
||||||
|
NimBLEAttValue(std::initializer_list<uint8_t> list, uint16_t max_len = BLE_ATT_ATTR_MAX_LEN)
|
||||||
|
: NimBLEAttValue(list.begin(), list.size(), max_len) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Construct with an initial value from a std::string.
|
* @brief Construct with an initial value from a std::string.
|
||||||
* @param str A std::string containing to the initial value to set.
|
* @param str A std::string containing to the initial value to set.
|
||||||
* @param[in] max_len The max size in bytes that the value can be.
|
* @param[in] max_len The max size in bytes that the value can be.
|
||||||
*/
|
*/
|
||||||
NimBLEAttValue(const std::string str, uint16_t max_len = BLE_ATT_ATTR_MAX_LEN)
|
NimBLEAttValue(const std::string str, uint16_t max_len = BLE_ATT_ATTR_MAX_LEN)
|
||||||
:NimBLEAttValue((uint8_t*)str.data(), (uint16_t)str.length(), max_len){}
|
: NimBLEAttValue(reinterpret_cast<const uint8_t*>(&str[0]), str.length(), max_len) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Construct with an initial value from a std::vector<uint8_t>.
|
* @brief Construct with an initial value from a std::vector<uint8_t>.
|
||||||
|
@ -117,23 +109,23 @@ public:
|
||||||
* @param[in] max_len The max size in bytes that the value can be.
|
* @param[in] max_len The max size in bytes that the value can be.
|
||||||
*/
|
*/
|
||||||
NimBLEAttValue(const std::vector<uint8_t> vec, uint16_t max_len = BLE_ATT_ATTR_MAX_LEN)
|
NimBLEAttValue(const std::vector<uint8_t> vec, uint16_t max_len = BLE_ATT_ATTR_MAX_LEN)
|
||||||
:NimBLEAttValue(&vec[0], (uint16_t)vec.size(), max_len){}
|
: NimBLEAttValue(&vec[0], vec.size(), max_len) {}
|
||||||
|
|
||||||
#ifdef NIMBLE_CPP_ARDUINO_STRING_AVAILABLE
|
# ifdef NIMBLE_CPP_ARDUINO_STRING_AVAILABLE
|
||||||
/**
|
/**
|
||||||
* @brief Construct with an initial value from an Arduino String.
|
* @brief Construct with an initial value from an Arduino String.
|
||||||
* @param str An Arduino String containing to the initial value to set.
|
* @param str An Arduino String containing to the initial value to set.
|
||||||
* @param[in] max_len The max size in bytes that the value can be.
|
* @param[in] max_len The max size in bytes that the value can be.
|
||||||
*/
|
*/
|
||||||
NimBLEAttValue(const String str, uint16_t max_len = BLE_ATT_ATTR_MAX_LEN)
|
NimBLEAttValue(const String str, uint16_t max_len = BLE_ATT_ATTR_MAX_LEN)
|
||||||
:NimBLEAttValue((uint8_t*)str.c_str(), str.length(), max_len){}
|
: NimBLEAttValue(reinterpret_cast<const uint8_t*>(str.c_str()), str.length(), max_len) {}
|
||||||
#endif
|
# endif
|
||||||
|
|
||||||
/** @brief Copy constructor */
|
/** @brief Copy constructor */
|
||||||
NimBLEAttValue(const NimBLEAttValue & source) { deepCopy(source); }
|
NimBLEAttValue(const NimBLEAttValue& source) { deepCopy(source); }
|
||||||
|
|
||||||
/** @brief Move constructor */
|
/** @brief Move constructor */
|
||||||
NimBLEAttValue(NimBLEAttValue && source) { *this = std::move(source); }
|
NimBLEAttValue(NimBLEAttValue&& source) { *this = std::move(source); }
|
||||||
|
|
||||||
/** @brief Destructor */
|
/** @brief Destructor */
|
||||||
~NimBLEAttValue();
|
~NimBLEAttValue();
|
||||||
|
@ -154,7 +146,7 @@ public:
|
||||||
const uint8_t* data() const { return m_attr_value; }
|
const uint8_t* data() const { return m_attr_value; }
|
||||||
|
|
||||||
/** @brief Returns a pointer to the internal buffer of the value as a const char* */
|
/** @brief Returns a pointer to the internal buffer of the value as a const char* */
|
||||||
const char* c_str() const { return (const char*)m_attr_value; }
|
const char* c_str() const { return reinterpret_cast<const char*>(m_attr_value); }
|
||||||
|
|
||||||
/** @brief Iterator begin */
|
/** @brief Iterator begin */
|
||||||
const uint8_t* begin() const { return m_attr_value; }
|
const uint8_t* begin() const { return m_attr_value; }
|
||||||
|
@ -162,7 +154,7 @@ public:
|
||||||
/** @brief Iterator end */
|
/** @brief Iterator end */
|
||||||
const uint8_t* end() const { return m_attr_value + m_attr_len; }
|
const uint8_t* end() const { return m_attr_value + m_attr_len; }
|
||||||
|
|
||||||
#if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
|
# if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
|
||||||
/** @brief Returns a timestamp of when the value was last updated */
|
/** @brief Returns a timestamp of when the value was last updated */
|
||||||
time_t getTimeStamp() const { return m_timestamp; }
|
time_t getTimeStamp() const { return m_timestamp; }
|
||||||
|
|
||||||
|
@ -174,33 +166,47 @@ public:
|
||||||
* @param[in] t The timestamp value to set
|
* @param[in] t The timestamp value to set
|
||||||
*/
|
*/
|
||||||
void setTimeStamp(time_t t) { m_timestamp = t; }
|
void setTimeStamp(time_t t) { m_timestamp = t; }
|
||||||
#else
|
# else
|
||||||
time_t getTimeStamp() const { return 0; }
|
time_t getTimeStamp() const { return 0; }
|
||||||
void setTimeStamp() { }
|
void setTimeStamp() {}
|
||||||
void setTimeStamp(time_t t) { }
|
void setTimeStamp(time_t t) {}
|
||||||
#endif
|
# endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set the value from a buffer
|
* @brief Set the value from a buffer
|
||||||
* @param[in] value A ponter to a buffer containing the value.
|
* @param[in] value A pointer to a buffer containing the value.
|
||||||
* @param[in] len The length of the value in bytes.
|
* @param[in] len The length of the value in bytes.
|
||||||
* @returns True if successful.
|
* @returns True if successful.
|
||||||
*/
|
*/
|
||||||
bool setValue(const uint8_t *value, uint16_t len);
|
bool setValue(const uint8_t* value, uint16_t len);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set value to the value of const char*.
|
* @brief Set value to the value of const char*.
|
||||||
* @param [in] s A ponter to a const char value to set.
|
* @param [in] s A pointer to a const char value to set.
|
||||||
|
* @param [in] len The length of the value in bytes, defaults to strlen(s).
|
||||||
*/
|
*/
|
||||||
bool setValue(const char* s) {
|
bool setValue(const char* s, uint16_t len = 0) {
|
||||||
return setValue((uint8_t*)s, (uint16_t)strlen(s)); }
|
if (len == 0) {
|
||||||
|
len = strlen(s);
|
||||||
|
}
|
||||||
|
return setValue(reinterpret_cast<const uint8_t*>(s), len);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get a pointer to the value buffer with timestamp.
|
* @brief Get a pointer to the value buffer with timestamp.
|
||||||
* @param[in] timestamp A ponter to a time_t variable to store the timestamp.
|
* @param[in] timestamp A pointer to a time_t variable to store the timestamp.
|
||||||
* @returns A pointer to the internal value buffer.
|
* @returns A pointer to the internal value buffer.
|
||||||
*/
|
*/
|
||||||
const uint8_t* getValue(time_t *timestamp);
|
const uint8_t* getValue(time_t* timestamp = nullptr) const {
|
||||||
|
if (timestamp != nullptr) {
|
||||||
|
# if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
|
||||||
|
*timestamp = m_timestamp;
|
||||||
|
# else
|
||||||
|
*timestamp = 0;
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
return m_attr_value;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Append data to the value.
|
* @brief Append data to the value.
|
||||||
|
@ -208,39 +214,46 @@ public:
|
||||||
* @param[in] len The length of the value to append in bytes.
|
* @param[in] len The length of the value to append in bytes.
|
||||||
* @returns A reference to the appended NimBLEAttValue.
|
* @returns A reference to the appended NimBLEAttValue.
|
||||||
*/
|
*/
|
||||||
NimBLEAttValue& append(const uint8_t *value, uint16_t len);
|
NimBLEAttValue& append(const uint8_t* value, uint16_t len);
|
||||||
|
|
||||||
|
|
||||||
/*********************** Template Functions ************************/
|
/*********************** Template Functions ************************/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Template to set value to the value of <type\>val.
|
* @brief Template to set value to the value of <type\>val.
|
||||||
* @param [in] s The <type\>value to set.
|
* @param [in] s The <type\>value to set.
|
||||||
|
* @param [in] len The length of the value in bytes, defaults to sizeof(T).
|
||||||
* @details Only used for types without a `c_str()` method.
|
* @details Only used for types without a `c_str()` method.
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template <typename T>
|
||||||
#ifdef _DOXYGEN_
|
# ifdef _DOXYGEN_
|
||||||
bool
|
bool
|
||||||
#else
|
# else
|
||||||
typename std::enable_if<!Has_c_str_len<T>::value, bool>::type
|
typename std::enable_if<!Has_c_str_len<T>::value, bool>::type
|
||||||
#endif
|
# endif
|
||||||
setValue(const T &s) {
|
setValue(const T& s, uint16_t len = 0) {
|
||||||
return setValue((uint8_t*)&s, sizeof(T));
|
if (len == 0) {
|
||||||
|
len = sizeof(T);
|
||||||
|
}
|
||||||
|
return setValue(reinterpret_cast<const uint8_t*>(&s), len);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Template to set value to the value of <type\>val.
|
* @brief Template to set value to the value of <type\>val.
|
||||||
* @param [in] s The <type\>value to set.
|
* @param [in] s The <type\>value to set.
|
||||||
|
* @param [in] len The length of the value in bytes, defaults to string.length().
|
||||||
* @details Only used if the <type\> has a `c_str()` method.
|
* @details Only used if the <type\> has a `c_str()` method.
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template <typename T>
|
||||||
#ifdef _DOXYGEN_
|
# ifdef _DOXYGEN_
|
||||||
bool
|
bool
|
||||||
#else
|
# else
|
||||||
typename std::enable_if<Has_c_str_len<T>::value, bool>::type
|
typename std::enable_if<Has_c_str_len<T>::value, bool>::type
|
||||||
#endif
|
# endif
|
||||||
setValue(const T & s) {
|
setValue(const T& s, uint16_t len = 0) {
|
||||||
return setValue((uint8_t*)s.c_str(), (uint16_t)s.length());
|
if (len == 0) {
|
||||||
|
len = s.length();
|
||||||
|
}
|
||||||
|
return setValue(reinterpret_cast<const uint8_t*>(s.c_str()), len);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -253,196 +266,59 @@ public:
|
||||||
* less than <tt>sizeof(<type\>)</tt>.
|
* less than <tt>sizeof(<type\>)</tt>.
|
||||||
* @details <b>Use:</b> <tt>getValue<type>(×tamp, skipSizeCheck);</tt>
|
* @details <b>Use:</b> <tt>getValue<type>(×tamp, skipSizeCheck);</tt>
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template <typename T>
|
||||||
T getValue(time_t *timestamp = nullptr, bool skipSizeCheck = false) {
|
T getValue(time_t* timestamp = nullptr, bool skipSizeCheck = false) const {
|
||||||
if(!skipSizeCheck && size() < sizeof(T)) {
|
if (!skipSizeCheck && size() < sizeof(T)) {
|
||||||
return T();
|
return T();
|
||||||
}
|
}
|
||||||
return *((T *)getValue(timestamp));
|
return *(reinterpret_cast<const T*>(getValue(timestamp)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*********************** Operators ************************/
|
/*********************** Operators ************************/
|
||||||
|
|
||||||
/** @brief Subscript operator */
|
/** @brief Subscript operator */
|
||||||
uint8_t operator [](int pos) const {
|
uint8_t operator[](int pos) const {
|
||||||
NIMBLE_CPP_DEBUG_ASSERT(pos < m_attr_len);
|
NIMBLE_CPP_DEBUG_ASSERT(pos < m_attr_len);
|
||||||
return m_attr_value[pos]; }
|
return m_attr_value[pos];
|
||||||
|
}
|
||||||
|
|
||||||
/** @brief Operator; Get the value as a std::vector<uint8_t>. */
|
/** @brief Operator; Get the value as a std::vector<uint8_t>. */
|
||||||
operator std::vector<uint8_t>() const {
|
operator std::vector<uint8_t>() const { return std::vector<uint8_t>(m_attr_value, m_attr_value + m_attr_len); }
|
||||||
return std::vector<uint8_t>(m_attr_value, m_attr_value + m_attr_len); }
|
|
||||||
|
|
||||||
/** @brief Operator; Get the value as a std::string. */
|
/** @brief Operator; Get the value as a std::string. */
|
||||||
operator std::string() const {
|
operator std::string() const { return std::string(reinterpret_cast<char*>(m_attr_value), m_attr_len); }
|
||||||
return std::string((char*)m_attr_value, m_attr_len); }
|
|
||||||
|
|
||||||
/** @brief Operator; Get the value as a const uint8_t*. */
|
/** @brief Operator; Get the value as a const uint8_t*. */
|
||||||
operator const uint8_t*() const { return m_attr_value; }
|
operator const uint8_t*() const { return m_attr_value; }
|
||||||
|
|
||||||
/** @brief Operator; Append another NimBLEAttValue. */
|
/** @brief Operator; Append another NimBLEAttValue. */
|
||||||
NimBLEAttValue& operator +=(const NimBLEAttValue & source) {
|
NimBLEAttValue& operator+=(const NimBLEAttValue& source) { return append(source.data(), source.size()); }
|
||||||
return append(source.data(), source.size()); }
|
|
||||||
|
|
||||||
/** @brief Operator; Set the value from a std::string source. */
|
/** @brief Operator; Set the value from a std::string source. */
|
||||||
NimBLEAttValue& operator =(const std::string & source) {
|
NimBLEAttValue& operator=(const std::string& source) {
|
||||||
setValue((uint8_t*)source.data(), (uint16_t)source.size()); return *this; }
|
setValue(reinterpret_cast<const uint8_t*>(&source[0]), source.size());
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
/** @brief Move assignment operator */
|
/** @brief Move assignment operator */
|
||||||
NimBLEAttValue& operator =(NimBLEAttValue && source);
|
NimBLEAttValue& operator=(NimBLEAttValue&& source);
|
||||||
|
|
||||||
/** @brief Copy assignment operator */
|
/** @brief Copy assignment operator */
|
||||||
NimBLEAttValue& operator =(const NimBLEAttValue & source);
|
NimBLEAttValue& operator=(const NimBLEAttValue& source);
|
||||||
|
|
||||||
/** @brief Equality operator */
|
/** @brief Equality operator */
|
||||||
bool operator ==(const NimBLEAttValue & source) {
|
bool operator==(const NimBLEAttValue& source) const {
|
||||||
return (m_attr_len == source.size()) ?
|
return (m_attr_len == source.size()) ? memcmp(m_attr_value, source.data(), m_attr_len) == 0 : false;
|
||||||
memcmp(m_attr_value, source.data(), m_attr_len) == 0 : false; }
|
}
|
||||||
|
|
||||||
/** @brief Inequality operator */
|
/** @brief Inequality operator */
|
||||||
bool operator !=(const NimBLEAttValue & source){ return !(*this == source); }
|
bool operator!=(const NimBLEAttValue& source) const { return !(*this == source); }
|
||||||
|
|
||||||
#ifdef NIMBLE_CPP_ARDUINO_STRING_AVAILABLE
|
# ifdef NIMBLE_CPP_ARDUINO_STRING_AVAILABLE
|
||||||
/** @brief Operator; Get the value as an Arduino String value. */
|
/** @brief Operator; Get the value as an Arduino String value. */
|
||||||
operator String() const { return String((char*)m_attr_value); }
|
operator String() const { return String(reinterpret_cast<char*>(m_attr_value)); }
|
||||||
#endif
|
# endif
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
inline NimBLEAttValue::NimBLEAttValue(uint16_t init_len, uint16_t max_len) {
|
|
||||||
m_attr_value = (uint8_t*)calloc(init_len + 1, 1);
|
|
||||||
NIMBLE_CPP_DEBUG_ASSERT(m_attr_value);
|
|
||||||
m_attr_max_len = std::min(BLE_ATT_ATTR_MAX_LEN, (int)max_len);
|
|
||||||
m_attr_len = 0;
|
|
||||||
m_capacity = init_len;
|
|
||||||
setTimeStamp(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline NimBLEAttValue::NimBLEAttValue(const uint8_t *value, uint16_t len, uint16_t max_len)
|
|
||||||
: NimBLEAttValue(len, max_len) {
|
|
||||||
memcpy(m_attr_value, value, len);
|
|
||||||
m_attr_value[len] = '\0';
|
|
||||||
m_attr_len = len;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline NimBLEAttValue::~NimBLEAttValue() {
|
|
||||||
if(m_attr_value != nullptr) {
|
|
||||||
free(m_attr_value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline NimBLEAttValue& NimBLEAttValue::operator =(NimBLEAttValue && source) {
|
|
||||||
if (this != &source){
|
|
||||||
free(m_attr_value);
|
|
||||||
|
|
||||||
m_attr_value = source.m_attr_value;
|
|
||||||
m_attr_max_len = source.m_attr_max_len;
|
|
||||||
m_attr_len = source.m_attr_len;
|
|
||||||
m_capacity = source.m_capacity;
|
|
||||||
setTimeStamp(source.getTimeStamp());
|
|
||||||
source.m_attr_value = nullptr;
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline NimBLEAttValue& NimBLEAttValue::operator =(const NimBLEAttValue & source) {
|
|
||||||
if (this != &source) {
|
|
||||||
deepCopy(source);
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void NimBLEAttValue::deepCopy(const NimBLEAttValue & source) {
|
|
||||||
uint8_t* res = (uint8_t*)realloc( m_attr_value, source.m_capacity + 1);
|
|
||||||
NIMBLE_CPP_DEBUG_ASSERT(res);
|
|
||||||
|
|
||||||
ble_npl_hw_enter_critical();
|
|
||||||
m_attr_value = res;
|
|
||||||
m_attr_max_len = source.m_attr_max_len;
|
|
||||||
m_attr_len = source.m_attr_len;
|
|
||||||
m_capacity = source.m_capacity;
|
|
||||||
setTimeStamp(source.getTimeStamp());
|
|
||||||
memcpy(m_attr_value, source.m_attr_value, m_attr_len + 1);
|
|
||||||
ble_npl_hw_exit_critical(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const uint8_t* NimBLEAttValue::getValue(time_t *timestamp) {
|
|
||||||
if(timestamp != nullptr) {
|
|
||||||
#if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
|
|
||||||
*timestamp = m_timestamp;
|
|
||||||
#else
|
|
||||||
*timestamp = 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
return m_attr_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool NimBLEAttValue::setValue(const uint8_t *value, uint16_t len) {
|
|
||||||
if (len > m_attr_max_len) {
|
|
||||||
NIMBLE_LOGE("NimBLEAttValue", "value exceeds max, len=%u, max=%u",
|
|
||||||
len, m_attr_max_len);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t *res = m_attr_value;
|
|
||||||
if (len > m_capacity) {
|
|
||||||
res = (uint8_t*)realloc(m_attr_value, (len + 1));
|
|
||||||
m_capacity = len;
|
|
||||||
}
|
|
||||||
NIMBLE_CPP_DEBUG_ASSERT(res);
|
|
||||||
|
|
||||||
#if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
|
|
||||||
time_t t = time(nullptr);
|
|
||||||
#else
|
|
||||||
time_t t = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ble_npl_hw_enter_critical();
|
|
||||||
m_attr_value = res;
|
|
||||||
memcpy(m_attr_value, value, len);
|
|
||||||
m_attr_value[len] = '\0';
|
|
||||||
m_attr_len = len;
|
|
||||||
setTimeStamp(t);
|
|
||||||
ble_npl_hw_exit_critical(0);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline NimBLEAttValue& NimBLEAttValue::append(const uint8_t *value, uint16_t len) {
|
|
||||||
if (len < 1) {
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((m_attr_len + len) > m_attr_max_len) {
|
|
||||||
NIMBLE_LOGE("NimBLEAttValue", "val > max, len=%u, max=%u",
|
|
||||||
len, m_attr_max_len);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t* res = m_attr_value;
|
|
||||||
uint16_t new_len = m_attr_len + len;
|
|
||||||
if (new_len > m_capacity) {
|
|
||||||
res = (uint8_t*)realloc(m_attr_value, (new_len + 1));
|
|
||||||
m_capacity = new_len;
|
|
||||||
}
|
|
||||||
NIMBLE_CPP_DEBUG_ASSERT(res);
|
|
||||||
|
|
||||||
#if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
|
|
||||||
time_t t = time(nullptr);
|
|
||||||
#else
|
|
||||||
time_t t = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ble_npl_hw_enter_critical();
|
|
||||||
m_attr_value = res;
|
|
||||||
memcpy(m_attr_value + m_attr_len, value, len);
|
|
||||||
m_attr_len = new_len;
|
|
||||||
m_attr_value[m_attr_len] = '\0';
|
|
||||||
setTimeStamp(t);
|
|
||||||
ble_npl_hw_exit_critical(0);
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /*(CONFIG_BT_ENABLED) */
|
#endif /*(CONFIG_BT_ENABLED) */
|
||||||
#endif /* MAIN_NIMBLEATTVALUE_H_ */
|
#endif /* NIMBLE_CPP_ATTVALUE_H_ */
|
||||||
|
|
Loading…
Reference in a new issue