Unify Framework Lib 1.7.0
attribute.hpp
Go to the documentation of this file.
1/******************************************************************************
2 * # License
3 * <b>Copyright 2021 Silicon Laboratories Inc. www.silabs.com</b>
4 ******************************************************************************
5 * The licensor of this software is Silicon Laboratories Inc. Your use of this
6 * software is governed by the terms of Silicon Labs Master Software License
7 * Agreement (MSLA) available at
8 * www.silabs.com/about-us/legal/master-software-license-agreement. This
9 * software is distributed to you in Source Code format and is governed by the
10 * sections of the MSLA applicable to Source Code.
11 *
12 *****************************************************************************/
13
25#ifndef ATTRIBUTE_HPP
26#define ATTRIBUTE_HPP
27
28#ifdef __cplusplus
29
30#include "attribute_store.h"
33
34#include <vector>
35#include <stdexcept>
36#include <string>
37#include <iterator>
38#include <functional>
39#include <cstring>
40#include <sstream> // for ostringstream
41namespace attribute_store
42{
49template<typename T, typename = void> struct is_iterable : std::false_type {};
50template<typename T>
51struct is_iterable<T,
52 std::void_t<decltype(std::declval<T>().begin()),
53 decltype(std::declval<T>().end()),
54 decltype(std::declval<T>().push_back(
55 *(std::declval<T>().begin())))>> :
56 std::true_type {};
57
62class attribute
63{
64 public:
69 attribute() {};
70
76 attribute(attribute_store_node_t n) : _n(n) {};
77
81 attribute parent() const
82 {
84 }
85
86 inline bool get(attribute_store_node_value_state_t value_type,
87 uint8_t *buffer,
88 uint8_t *size) const
89 {
90 return (SL_STATUS_OK
92 value_type,
93 buffer,
94 size));
95 }
96
102 inline attribute
103 first_parent_or_self(attribute_store_type_t parent_type) const
104 {
105 if (type() == parent_type) {
106 return *this;
107 } else {
108 return first_parent(parent_type);
109 }
110 }
111
115 attribute first_parent(attribute_store_type_t type) const
116 {
118 }
119
133 template<typename T>
134 inline T get(attribute_store_node_value_state_t value_type) const
135 {
137 uint8_t size = 0;
138 if (get(value_type, (uint8_t *)buffer, &size)) {
139 if constexpr (std::is_same<T, std::string>::value) {
140 return std::string(reinterpret_cast<char *>(buffer));
141 } else if constexpr (
142 is_iterable<T>::value) { // For iterable containers we copy the data
143 typedef typename T::value_type v_t;
144 //Make sure that value type of the container int,float,bool ... etc
145 static_assert(std::is_trivially_copyable<v_t>::value);
146 T v;
147 v_t *start = reinterpret_cast<v_t *>(buffer);
148 v_t *end = reinterpret_cast<v_t *>(buffer + size);
149 std::copy(start, end, std::back_insert_iterator(v));
150 return v;
151 } else if constexpr (std::is_integral<T>::value) {
152 if (size == 1) {
153 return *(reinterpret_cast<uint8_t *>(buffer));
154 } else if (size == 2) {
155 return *(reinterpret_cast<uint16_t *>(buffer));
156 }
157 } else {
158 static_assert(std::is_trivially_copyable<T>::value);
159 }
160
161 if (size == sizeof(T)) {
162 return *(reinterpret_cast<T *>(buffer));
163 } else {
164 throw std::invalid_argument(
165 "Unexpected attribute size for node " + name_and_id() + ".Expected: "
166 + std::to_string(sizeof(T)) + ", actual: " + std::to_string(size)
167 + " value state: " + std::to_string(value_type) + ".");
168 }
169 } else {
170 throw std::invalid_argument("Unable to read attribute " + name_and_id());
171 }
172 }
173
174 inline attribute &set(attribute_store_node_value_state_t value_type,
175 const uint8_t *value,
176 size_t size)
177 {
178 if (SL_STATUS_OK
180 value_type,
181 value,
182 size)) {
183 throw std::invalid_argument("Unable to write attribute " + name_and_id());
184 } else {
185 return *this;
186 }
187 }
188
201 template<typename T> inline attribute &
202 set(attribute_store_node_value_state_t value_type, const T &value)
203 {
204 if constexpr (std::is_same<T, char const *>::value) {
205 // We are storing strings as C Strings with the null termination character in the attribute store.
206 return set(value_type, std::string(value));
207 } else if constexpr (std::is_same<T, std::string>::value) {
208 // We are storing strings as C Strings with the null termination character in the attribute store.
209 return set(value_type,
210 reinterpret_cast<const uint8_t *>(value.c_str()),
211 value.size() + 1);
212 } else if constexpr (is_iterable<T>::value) {
213 typedef typename T::value_type v_t;
214 //Make sure that value type of the container int,float,bool ... etc
215 static_assert(std::is_trivially_copyable<v_t>::value);
216
217 //The purpose of this is to convert the iterable container into a linear buffer
218 std::vector<v_t> v;
219 std::copy(value.begin(), value.end(), std::back_insert_iterator(v));
220 return set(value_type,
221 reinterpret_cast<const uint8_t *>(v.data()),
222 v.size() * sizeof(v_t));
223 } else {
224 static_assert(std::is_trivially_copyable<T>::value);
225 return set(value_type,
226 reinterpret_cast<const uint8_t *>(&value),
227 sizeof(T));
228 }
229 }
230
231 inline void clear(attribute_store_node_value_state_t value_type)
232 {
233 if (SL_STATUS_OK
234 != attribute_store_set_node_attribute_value(_n, value_type, 0, 0)) {
235 throw std::invalid_argument("Unable to write attribute");
236 }
237 }
238
242 template<typename T> T reported() const
243 {
244 return get<T>(REPORTED_ATTRIBUTE);
245 }
249 template<typename T> T desired() const
250 {
251 return get<T>(DESIRED_ATTRIBUTE);
252 }
253
254 bool exists(attribute_store_node_value_state_t state) const
255 {
256 return attribute_store_is_value_defined(_n, state);
257 }
258
262 bool desired_exists() const
263 {
264 return exists(DESIRED_ATTRIBUTE);
265 }
266
271 bool reported_exists() const
272 {
273 return exists(REPORTED_ATTRIBUTE);
274 }
275
276 template<typename T> T desired_or_reported()
277 {
278 return get<T>(DESIRED_OR_REPORTED_ATTRIBUTE);
279 }
280
281 void clear_reported()
282 {
283 clear(REPORTED_ATTRIBUTE);
284 }
285
286 void clear_desired()
287 {
288 clear(DESIRED_ATTRIBUTE);
289 }
290
294 template<typename T> attribute &set_reported(T v)
295 {
296 return set<T>(REPORTED_ATTRIBUTE, v);
297 }
298
302 template<typename T> attribute &set_desired(T v)
303 {
304 return set<T>(DESIRED_ATTRIBUTE, v);
305 }
306
312 size_t child_count() const
313 {
315 }
316
323 attribute child(size_t index) const
324 {
325 return attribute_store_get_node_child(_n, index);
326 }
327
335 attribute child_by_type(attribute_store_type_t type, size_t index = 0) const
336 {
337 return attribute_store_get_node_child_by_type(_n, type, index);
338 }
339
345 std::vector<attribute> children() const
346 {
347 std::vector<attribute> _children;
348 size_t n_childs = child_count();
349 for (size_t i = 0; i < n_childs; i++) {
350 _children.push_back(child(i));
351 }
352 return _children;
353 }
354
362 std::vector<attribute> children(attribute_store_type_t type) const
363 {
364 std::vector<attribute> _children;
365 for (size_t i = 0; i < child_count(); i++) {
366 if (child(i).type() == type) {
367 _children.push_back(child(i));
368 }
369 }
370 return _children;
371 }
372
384 template<typename T>
385 attribute child_by_type_and_value(attribute_store_type_t type, T value) const
386 {
387 for (auto c: children(type)) {
388 if (c.reported_exists() && c.reported<T>() == value) {
389 return c;
390 }
391 }
393 }
394
407 template<typename T> attribute
408 child_by_type_and_value(attribute_store_type_t type,
409 T value,
410 attribute_store_node_value_state_t value_type) const
411 {
412 for (auto c: children(type)) {
413 if (c.exists(value_type) && c.get<T>(value_type) == value) {
414 return c;
415 }
416 }
418 }
419
426 bool is_valid() const
427 {
429 }
430
436 attribute_store_type_t type() const
437 {
439 }
440
446 static attribute root()
447 {
449 }
450
454 attribute add_node(attribute_store_type_t type)
455 {
456 return attribute_store_add_node(type, _n);
457 }
458
466 template<typename T>
467 attribute emplace_node(attribute_store_type_t type,
468 T val,
471 {
472 attribute a = child_by_type_and_value(type, val, value_state);
473 if (a.is_valid()) {
474 return a;
475 } else {
476 return add_node(type).set(value_state, val);
477 }
478 }
479
487 attribute emplace_node(attribute_store_type_t type)
488 {
489 attribute a = child_by_type(type);
490 if (a.is_valid()) {
491 return a;
492 } else {
493 return add_node(type);
494 }
495 }
496
501 void delete_node()
502 {
505 }
506
518 inline sl_status_t visit(
519 const std::function<sl_status_t(attribute_store::attribute &, int)> &func,
520 int depth = 0)
521 {
522 sl_status_t status = func(*this, depth);
523 if (SL_STATUS_OK == status) {
524 for (auto c: children()) {
525 status = c.visit(func, depth + 1);
526 if (status == SL_STATUS_ABORT) {
527 return status;
528 }
529 }
530 }
531 return status;
532 }
533
534 std::string name() const
535 {
536 return attribute_store_get_type_name(this->type());
537 }
538
539 std::string name_and_id() const
540 {
541 std::ostringstream out;
542 out << name() << " (Node " << _n << ")";
543 return out.str();
544 }
545
546
547 std::string value_to_string() const
548 {
549
550 std::string str_value;
551 try {
552 switch (attribute_store_get_storage_type(this->type())) {
557 return "Not displayable value for " + name_and_id();
558 case U8_STORAGE_TYPE:
559 case U16_STORAGE_TYPE:
560 case U32_STORAGE_TYPE:
561 case U64_STORAGE_TYPE:
562 str_value = _get_str_value<uint64_t>();
563 break;
564 case I8_STORAGE_TYPE:
565 case I16_STORAGE_TYPE:
566 case I32_STORAGE_TYPE:
567 case I64_STORAGE_TYPE:
568 str_value = _get_str_value<int64_t>();
569 break;
572 str_value = _get_str_value<double>();
573 break;
575 str_value = _get_str_value<std::string>();
576 break;
578 str_value = _get_str_value<std::vector<uint8_t>>();
579 break;
580 default:
581 return "Unkown value type for " + name_and_id();
582 }
583 } catch (...) {
584 return "Can't get values of " + name_and_id();
585 }
586
587 return name_and_id() + " values : " + str_value;
588 }
589
590 //type conversion back to attribute_store_node_t
591 operator attribute_store_node_t() const
592 {
593 return _n;
594 }
595
596 //Comparison operators
597 bool operator==(const attribute &a) const
598 {
599 return _n == a._n;
600 }
602 {
603 return _n == a;
604 }
605
606 private:
608
609 template<typename T>
610 std::string _get_str_value() const {
611 auto desired_value = _get_str_value_with_state<T>(DESIRED_ATTRIBUTE);
612 auto reported_value = _get_str_value_with_state<T>(REPORTED_ATTRIBUTE);
613
614 return reported_value + " (" + desired_value + ")";
615 }
616
617 template<typename T>
618 std::string _get_str_value_with_state(attribute_store_node_value_state_t state) const {
619 if (!exists(state)) {
620 return "<>";
621 }
622
623 std::string str_value = "";
624
625 if constexpr (std::is_same<T, std::vector<uint8_t>>::value) {
626 str_value = "[";
627 for (uint8_t byte: get<std::vector<uint8_t>>(state)) {
628 str_value += std::to_string(byte) + ",";
629 }
630 str_value.pop_back();
631 str_value += "]";
632 } else if constexpr (std::is_same<T, int64_t>::value
633 || std::is_same<T, uint64_t>::value
634 || std::is_same<T, double>::value) {
635 str_value = std::to_string(get<T>(state));
636 } else if constexpr (std::is_same<T, std::string>::value) {
637 str_value = get<std::string>(state);
638 }
639
640 return str_value;
641 }
642};
643
644} // namespace attribute_store
645
646#endif
647#endif //ATTRIBUTE_HPP
uint32_t attribute_store_type_t
Definition: attribute_store.h:50
#define ATTRIBUTE_STORE_MAXIMUM_VALUE_LENGTH
Maximum length for a value associated to an attribute.
Definition: attribute_store.h:104
bool attribute_store_node_exists(attribute_store_node_t node)
Verify whether a node is in the Attribute Store.
attribute_store_node_t attribute_store_get_node_child(attribute_store_node_t node, uint32_t child_index)
Get the node handle of a child of a node.
sl_status_t attribute_store_get_node_attribute_value(attribute_store_node_t node, attribute_store_node_value_state_t value_state, uint8_t *value, uint8_t *value_size)
Get the attribute value of a node.
attribute_store_node_value_state_t
This is the value state of a value.
Definition: attribute_store.h:121
attribute_store_node_t attribute_store_get_node_parent(attribute_store_node_t node)
Get the node handle of the parent of a node.
attribute_store_node_t attribute_store_get_root()
Retrieve the root node of the tree.
attribute_store_node_t attribute_store_add_node(attribute_store_type_t type, attribute_store_node_t parent_node)
Add a new node in the current attribute store.
attribute_store_node_t attribute_store_get_node_child_by_type(attribute_store_node_t node, attribute_store_type_t child_type, uint32_t child_index)
Get the node handle of a child of a node with a certain type.
datastore_attribute_id_t attribute_store_node_t
Handle to identify attribute store nodes.
Definition: attribute_store.h:101
attribute_store_node_t attribute_store_get_first_parent_with_type(attribute_store_node_t node, attribute_store_type_t parent_type)
Traverse up the tree from a node and finds the first parent with a given type.
attribute_store_type_t attribute_store_get_node_type(attribute_store_node_t node)
Get the type of a node.
size_t attribute_store_get_node_child_count(attribute_store_node_t node)
Get the number of children of the given node.
sl_status_t attribute_store_delete_node(attribute_store_node_t node)
Delete a node and all its children from the attribute store.
sl_status_t attribute_store_set_node_attribute_value(attribute_store_node_t node, attribute_store_node_value_state_t value_state, const uint8_t *value, uint8_t value_size)
Set the attribute value of a node in the current attribute store tree.
#define ATTRIBUTE_STORE_INVALID_NODE
Special attribute_store_node_t value indicating that it does not exist.
Definition: attribute_store.h:106
@ DESIRED_OR_REPORTED_ATTRIBUTE
Retrieve the desired value if it exists if not then provide the reported attribute only used for read...
Definition: attribute_store.h:124
@ REPORTED_ATTRIBUTE
This is the value reported by the node or actual value.
Definition: attribute_store.h:122
@ DESIRED_ATTRIBUTE
This is the value to be applied to the node.
Definition: attribute_store.h:123
attribute_store_storage_type_t attribute_store_get_storage_type(attribute_store_type_t type)
Returns the storage type of a given attribute.
const char * attribute_store_get_type_name(attribute_store_type_t type)
Returns the registered name of an attribute.
@ I32_STORAGE_TYPE
Definition: attribute_store_type_registration.h:59
@ INVALID_STORAGE_TYPE
Definition: attribute_store_type_registration.h:73
@ U32_STORAGE_TYPE
Definition: attribute_store_type_registration.h:51
@ I16_STORAGE_TYPE
Definition: attribute_store_type_registration.h:57
@ U64_STORAGE_TYPE
Definition: attribute_store_type_registration.h:53
@ C_STRING_STORAGE_TYPE
Definition: attribute_store_type_registration.h:67
@ EMPTY_STORAGE_TYPE
Definition: attribute_store_type_registration.h:45
@ U16_STORAGE_TYPE
Definition: attribute_store_type_registration.h:49
@ BYTE_ARRAY_STORAGE_TYPE
Definition: attribute_store_type_registration.h:69
@ I8_STORAGE_TYPE
Definition: attribute_store_type_registration.h:55
@ I64_STORAGE_TYPE
Definition: attribute_store_type_registration.h:61
@ UNKNOWN_STORAGE_TYPE
Definition: attribute_store_type_registration.h:42
@ DOUBLE_STORAGE_TYPE
Definition: attribute_store_type_registration.h:65
@ U8_STORAGE_TYPE
Definition: attribute_store_type_registration.h:47
@ FIXED_SIZE_STRUCT_STORAGE_TYPE
Definition: attribute_store_type_registration.h:71
@ FLOAT_STORAGE_TYPE
Definition: attribute_store_type_registration.h:63
bool attribute_store_is_value_defined(attribute_store_node_t node, attribute_store_node_value_state_t value_state)
Indicate whether a value is defined in the attribute store.
Definition: attribute_store_helper.c:30
#define SL_STATUS_OK
No error.
Definition: sl_status.h:49
uint32_t sl_status_t
Definition: sl_status.h:139
#define SL_STATUS_ABORT
Operation aborted.
Definition: sl_status.h:57
bool operator==(const nil &a, const nil &b)
Definition: attribute_callbacks.hpp:23
void get(const std::string &image_key, const std::string &subscribe_topic, const std::string &publish_topic, const uic_ota::image_ready_funct_t &image_ready_cb, uint32_t timeout_s)
Function for downloading images.