NimBLE-Arduino 1.4.2
Loading...
Searching...
No Matches
NimBLEAttValue.h
1/*
2 * NimBLEAttValue.h
3 *
4 * Created: on March 18, 2021
5 * Author H2zero
6 *
7 */
8
9#ifndef MAIN_NIMBLEATTVALUE_H_
10#define MAIN_NIMBLEATTVALUE_H_
11#include "nimconfig.h"
12#if defined(CONFIG_BT_ENABLED)
13
14#ifdef NIMBLE_CPP_ARDUINO_STRING_AVAILABLE
15#include <Arduino.h>
16#endif
17
18#include "NimBLELog.h"
19
20/**** FIX COMPILATION ****/
21#undef min
22#undef max
23/**************************/
24
25#include <string>
26#include <vector>
27
28#ifndef CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
29# define CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED 0
30#endif
31
32#if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
33# include <time.h>
34#endif
35
36#if !defined(CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH)
37# define CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH 20
38#elif CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH > BLE_ATT_ATTR_MAX_LEN
39# error CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH cannot be larger than 512 (BLE_ATT_ATTR_MAX_LEN)
40#elif CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH < 1
41# error CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH cannot be less than 1; Range = 1 : 512
42#endif
43
44
45/* Used to determine if the type passed to a template has a c_str() and length() method. */
46template <typename T, typename = void, typename = void>
47struct Has_c_str_len : std::false_type {};
48
49template <typename T>
50struct Has_c_str_len<T, decltype(void(std::declval<T &>().c_str())),
51 decltype(void(std::declval<T &>().length()))> : std::true_type {};
52
53
61{
62 uint8_t* m_attr_value = nullptr;
63 uint16_t m_attr_max_len = 0;
64 uint16_t m_attr_len = 0;
65 uint16_t m_capacity = 0;
66#if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
67 time_t m_timestamp = 0;
68#endif
69 void deepCopy(const NimBLEAttValue & source);
70
71public:
77 NimBLEAttValue(uint16_t init_len = CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH,
78 uint16_t max_len = BLE_ATT_ATTR_MAX_LEN);
79
86 NimBLEAttValue(const uint8_t *value, uint16_t len,
87 uint16_t max_len = BLE_ATT_ATTR_MAX_LEN);
88
94 NimBLEAttValue(std::initializer_list<uint8_t> list,
95 uint16_t max_len = BLE_ATT_ATTR_MAX_LEN)
96 :NimBLEAttValue(list.begin(), (uint16_t)list.size(), max_len){}
97
103 NimBLEAttValue(const char *value, uint16_t max_len = BLE_ATT_ATTR_MAX_LEN)
104 :NimBLEAttValue((uint8_t*)value, (uint16_t)strlen(value), max_len){}
105
111 NimBLEAttValue(const std::string str, uint16_t max_len = BLE_ATT_ATTR_MAX_LEN)
112 :NimBLEAttValue((uint8_t*)str.data(), (uint16_t)str.length(), max_len){}
113
119 NimBLEAttValue(const std::vector<uint8_t> vec, uint16_t max_len = BLE_ATT_ATTR_MAX_LEN)
120 :NimBLEAttValue(&vec[0], (uint16_t)vec.size(), max_len){}
121
122#ifdef NIMBLE_CPP_ARDUINO_STRING_AVAILABLE
128 NimBLEAttValue(const String str, uint16_t max_len = BLE_ATT_ATTR_MAX_LEN)
129 :NimBLEAttValue((uint8_t*)str.c_str(), str.length(), max_len){}
130#endif
131
133 NimBLEAttValue(const NimBLEAttValue & source) { deepCopy(source); }
134
136 NimBLEAttValue(NimBLEAttValue && source) { *this = std::move(source); }
137
140
142 uint16_t max_size() const { return m_attr_max_len; }
143
145 uint16_t capacity() const { return m_capacity; }
146
148 uint16_t length() const { return m_attr_len; }
149
151 uint16_t size() const { return m_attr_len; }
152
154 const uint8_t* data() const { return m_attr_value; }
155
157 const char* c_str() const { return (const char*)m_attr_value; }
158
160 const uint8_t* begin() const { return m_attr_value; }
161
163 const uint8_t* end() const { return m_attr_value + m_attr_len; }
164
165#if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
167 time_t getTimeStamp() const { return m_timestamp; }
168
170 void setTimeStamp() { m_timestamp = time(nullptr); }
171
176 void setTimeStamp(time_t t) { m_timestamp = t; }
177#else
178 time_t getTimeStamp() const { return 0; }
179 void setTimeStamp() { }
180 void setTimeStamp(time_t t) { }
181#endif
182
189 bool setValue(const uint8_t *value, uint16_t len);
190
195 bool setValue(const char* s) {
196 return setValue((uint8_t*)s, (uint16_t)strlen(s)); }
197
203 const uint8_t* getValue(time_t *timestamp);
204
211 NimBLEAttValue& append(const uint8_t *value, uint16_t len);
212
213
214 /*********************** Template Functions ************************/
215
221 template<typename T>
222#ifdef _DOXYGEN_
223 bool
224#else
225 typename std::enable_if<!Has_c_str_len<T>::value, bool>::type
226#endif
227 setValue(const T &s) {
228 return setValue((uint8_t*)&s, sizeof(T));
229 }
230
236 template<typename T>
237#ifdef _DOXYGEN_
238 bool
239#else
240 typename std::enable_if<Has_c_str_len<T>::value, bool>::type
241#endif
242 setValue(const T & s) {
243 return setValue((uint8_t*)s.c_str(), (uint16_t)s.length());
244 }
245
256 template<typename T>
257 T getValue(time_t *timestamp = nullptr, bool skipSizeCheck = false) {
258 if(!skipSizeCheck && size() < sizeof(T)) {
259 return T();
260 }
261 return *((T *)getValue(timestamp));
262 }
263
264
265 /*********************** Operators ************************/
266
268 uint8_t operator [](int pos) const {
269 assert(pos < m_attr_len && "out of range"); return m_attr_value[pos]; }
270
272 operator std::vector<uint8_t>() const {
273 return std::vector<uint8_t>(m_attr_value, m_attr_value + m_attr_len); }
274
276 operator std::string() const {
277 return std::string((char*)m_attr_value, m_attr_len); }
278
280 operator const uint8_t*() const { return m_attr_value; }
281
284 return append(source.data(), source.size()); }
285
287 NimBLEAttValue& operator =(const std::string & source) {
288 setValue((uint8_t*)source.data(), (uint16_t)source.size()); return *this; }
289
292
295
297 bool operator ==(const NimBLEAttValue & source) {
298 return (m_attr_len == source.size()) ?
299 memcmp(m_attr_value, source.data(), m_attr_len) == 0 : false; }
300
302 bool operator !=(const NimBLEAttValue & source){ return !(*this == source); }
303
304#ifdef NIMBLE_CPP_ARDUINO_STRING_AVAILABLE
306 operator String() const { return String((char*)m_attr_value); }
307#endif
308
309};
310
311
312inline NimBLEAttValue::NimBLEAttValue(uint16_t init_len, uint16_t max_len) {
313 m_attr_value = (uint8_t*)calloc(init_len + 1, 1);
314 assert(m_attr_value && "No Mem");
315 m_attr_max_len = std::min(BLE_ATT_ATTR_MAX_LEN, (int)max_len);
316 m_attr_len = 0;
317 m_capacity = init_len;
318 setTimeStamp(0);
319}
320
321inline NimBLEAttValue::NimBLEAttValue(const uint8_t *value, uint16_t len, uint16_t max_len)
322: NimBLEAttValue(len, max_len) {
323 memcpy(m_attr_value, value, len);
324 m_attr_value[len] = '\0';
325 m_attr_len = len;
326}
327
329 if(m_attr_value != nullptr) {
330 free(m_attr_value);
331 }
332}
333
335 if (this != &source){
336 free(m_attr_value);
337
338 m_attr_value = source.m_attr_value;
339 m_attr_max_len = source.m_attr_max_len;
340 m_attr_len = source.m_attr_len;
341 m_capacity = source.m_capacity;
342 setTimeStamp(source.getTimeStamp());
343 source.m_attr_value = nullptr;
344 }
345 return *this;
346}
347
349 if (this != &source) {
350 deepCopy(source);
351 }
352 return *this;
353}
354
355inline void NimBLEAttValue::deepCopy(const NimBLEAttValue & source) {
356 uint8_t* res = (uint8_t*)realloc( m_attr_value, source.m_capacity + 1);
357 assert(res && "deepCopy: realloc failed");
358
359 ble_npl_hw_enter_critical();
360 m_attr_value = res;
361 m_attr_max_len = source.m_attr_max_len;
362 m_attr_len = source.m_attr_len;
363 m_capacity = source.m_capacity;
364 setTimeStamp(source.getTimeStamp());
365 memcpy(m_attr_value, source.m_attr_value, m_attr_len + 1);
366 ble_npl_hw_exit_critical(0);
367}
368
369inline const uint8_t* NimBLEAttValue::getValue(time_t *timestamp) {
370 if(timestamp != nullptr) {
371#if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
372 *timestamp = m_timestamp;
373#else
374 *timestamp = 0;
375#endif
376 }
377 return m_attr_value;
378}
379
380inline bool NimBLEAttValue::setValue(const uint8_t *value, uint16_t len) {
381 if (len > m_attr_max_len) {
382 NIMBLE_LOGE("NimBLEAttValue", "value exceeds max, len=%u, max=%u",
383 len, m_attr_max_len);
384 return false;
385 }
386
387 uint8_t *res = m_attr_value;
388 if (len > m_capacity) {
389 res = (uint8_t*)realloc(m_attr_value, (len + 1));
390 m_capacity = len;
391 }
392 assert(res && "setValue: realloc failed");
393
394#if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
395 time_t t = time(nullptr);
396#else
397 time_t t = 0;
398#endif
399
400 ble_npl_hw_enter_critical();
401 m_attr_value = res;
402 memcpy(m_attr_value, value, len);
403 m_attr_value[len] = '\0';
404 m_attr_len = len;
405 setTimeStamp(t);
406 ble_npl_hw_exit_critical(0);
407 return true;
408}
409
410inline NimBLEAttValue& NimBLEAttValue::append(const uint8_t *value, uint16_t len) {
411 if (len < 1) {
412 return *this;
413 }
414
415 if ((m_attr_len + len) > m_attr_max_len) {
416 NIMBLE_LOGE("NimBLEAttValue", "val > max, len=%u, max=%u",
417 len, m_attr_max_len);
418 return *this;
419 }
420
421 uint8_t* res = m_attr_value;
422 uint16_t new_len = m_attr_len + len;
423 if (new_len > m_capacity) {
424 res = (uint8_t*)realloc(m_attr_value, (new_len + 1));
425 m_capacity = new_len;
426 }
427 assert(res && "append: realloc failed");
428
429#if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
430 time_t t = time(nullptr);
431#else
432 time_t t = 0;
433#endif
434
435 ble_npl_hw_enter_critical();
436 m_attr_value = res;
437 memcpy(m_attr_value + m_attr_len, value, len);
438 m_attr_len = new_len;
439 m_attr_value[m_attr_len] = '\0';
440 setTimeStamp(t);
441 ble_npl_hw_exit_critical(0);
442
443 return *this;
444}
445
446#endif /*(CONFIG_BT_ENABLED) */
447#endif /* MAIN_NIMBLEATTVALUE_H_ */
A specialized container class to hold BLE attribute values.
Definition: NimBLEAttValue.h:61
NimBLEAttValue(const std::vector< uint8_t > vec, uint16_t max_len=BLE_ATT_ATTR_MAX_LEN)
Construct with an initial value from a std::vector<uint8_t>.
Definition: NimBLEAttValue.h:119
~NimBLEAttValue()
Destructor.
Definition: NimBLEAttValue.h:328
T getValue(time_t *timestamp=nullptr, bool skipSizeCheck=false)
Template to return the value as a <type>.
Definition: NimBLEAttValue.h:257
uint16_t length() const
Returns the current length of the value in bytes.
Definition: NimBLEAttValue.h:148
NimBLEAttValue(const char *value, uint16_t max_len=BLE_ATT_ATTR_MAX_LEN)
Construct with an initial value from a const char string.
Definition: NimBLEAttValue.h:103
uint16_t capacity() const
Returns the currently allocated capacity in bytes.
Definition: NimBLEAttValue.h:145
const char * c_str() const
Returns a pointer to the internal buffer of the value as a const char*.
Definition: NimBLEAttValue.h:157
NimBLEAttValue(const std::string str, uint16_t max_len=BLE_ATT_ATTR_MAX_LEN)
Construct with an initial value from a std::string.
Definition: NimBLEAttValue.h:111
bool setValue(const uint8_t *value, uint16_t len)
Set the value from a buffer.
Definition: NimBLEAttValue.h:380
const uint8_t * getValue(time_t *timestamp)
Get a pointer to the value buffer with timestamp.
Definition: NimBLEAttValue.h:369
NimBLEAttValue(std::initializer_list< uint8_t > list, uint16_t max_len=BLE_ATT_ATTR_MAX_LEN)
Construct with an initializer list.
Definition: NimBLEAttValue.h:94
NimBLEAttValue & operator+=(const NimBLEAttValue &source)
Operator; Append another NimBLEAttValue.
Definition: NimBLEAttValue.h:283
NimBLEAttValue(const NimBLEAttValue &source)
Copy constructor.
Definition: NimBLEAttValue.h:133
NimBLEAttValue(NimBLEAttValue &&source)
Move constructor.
Definition: NimBLEAttValue.h:136
const uint8_t * data() const
Returns a pointer to the internal buffer of the value.
Definition: NimBLEAttValue.h:154
uint8_t operator[](int pos) const
Subscript operator.
Definition: NimBLEAttValue.h:268
const uint8_t * end() const
Iterator end.
Definition: NimBLEAttValue.h:163
bool operator==(const NimBLEAttValue &source)
Equality operator.
Definition: NimBLEAttValue.h:297
bool setValue(const char *s)
Set value to the value of const char*.
Definition: NimBLEAttValue.h:195
bool operator!=(const NimBLEAttValue &source)
Inequality operator.
Definition: NimBLEAttValue.h:302
NimBLEAttValue & append(const uint8_t *value, uint16_t len)
Append data to the value.
Definition: NimBLEAttValue.h:410
NimBLEAttValue(uint16_t init_len=CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH, uint16_t max_len=BLE_ATT_ATTR_MAX_LEN)
Default constructor.
Definition: NimBLEAttValue.h:312
uint16_t size() const
Returns the current size of the value in bytes.
Definition: NimBLEAttValue.h:151
uint16_t max_size() const
Returns the max size in bytes.
Definition: NimBLEAttValue.h:142
bool setValue(const T &s)
Template to set value to the value of <type>val.
Definition: NimBLEAttValue.h:227
NimBLEAttValue & operator=(const std::string &source)
Operator; Set the value from a std::string source.
Definition: NimBLEAttValue.h:287
const uint8_t * begin() const
Iterator begin.
Definition: NimBLEAttValue.h:160