Zigbee Protocol Controller 1.6.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"
32#include <vector>
33#include <stdexcept>
34#include <string>
35#include <iterator>
36#include <functional>
37#include <cstring>
38namespace attribute_store
39{
46template<typename T, typename = void> struct is_iterable : std::false_type {};
47template<typename T>
48struct is_iterable<T,
49 std::void_t<decltype(std::declval<T>().begin()),
50 decltype(std::declval<T>().end()),
51 decltype(std::declval<T>().push_back(
52 *(std::declval<T>().begin())))>> :
53 std::true_type {};
54
59class attribute
60{
61 public:
66 attribute() {};
67
73 attribute(attribute_store_node_t n) : _n(n) {};
74
78 attribute parent() const
79 {
81 }
82
83 inline bool get(attribute_store_node_value_state_t value_type,
84 uint8_t *buffer,
85 uint8_t *size) const
86 {
87 return (SL_STATUS_OK
89 value_type,
90 buffer,
91 size));
92 }
93
99 inline attribute
100 first_parent_or_self(attribute_store_type_t parent_type) const
101 {
102 if (type() == parent_type) {
103 return *this;
104 } else {
105 return first_parent(parent_type);
106 }
107 }
108
112 attribute first_parent(attribute_store_type_t type) const
113 {
115 }
116
130 template<typename T>
131 inline T get(attribute_store_node_value_state_t value_type) const
132 {
134 uint8_t size = 0;
135 if (get(value_type, (uint8_t *)buffer, &size)) {
136 if constexpr(std::is_same<T,std::string>::value) {
137 return std::string(reinterpret_cast<char*>(buffer));
138 }else if constexpr (is_iterable<T>::value) { // For iterable containers we copy the data
139 typedef typename T::value_type v_t;
140 //Make sure that value type of the conrainter int,float,bool ... etc
141 static_assert(std::is_trivially_copyable<v_t>::value);
142 T v;
143 v_t *start = reinterpret_cast<v_t *>(buffer);
144 v_t *end = reinterpret_cast<v_t *>(buffer + size);
145 std::copy(start, end, std::back_insert_iterator(v));
146 return v;
147 } else if constexpr (std::is_integral<T>::value) {
148 if (size == 1) {
149 return *(reinterpret_cast<uint8_t *>(buffer));
150 } else if (size == 2) {
151 return *(reinterpret_cast<uint16_t *>(buffer));
152 }
153 } else {
154 static_assert(std::is_trivially_copyable<T>::value);
155 }
156
157 if (size == sizeof(T)) {
158 return *(reinterpret_cast<T *>(buffer));
159 } else {
160 throw std::invalid_argument(
161 "Unexpected attribute size for node " + std::to_string(_n)
162 + ".Expected: " + std::to_string(sizeof(T))
163 + ", actual: " + std::to_string(size)
164 + " value state: " + std::to_string(value_type) + ".");
165 }
166 } else {
167 throw std::invalid_argument("Unable to read attribute "
168 + std::to_string(_n));
169 }
170 }
171
172 inline attribute &set(attribute_store_node_value_state_t value_type,
173 const uint8_t *value,
174 size_t size)
175 {
176 if (SL_STATUS_OK
178 value_type,
179 value,
180 size)) {
181 throw std::invalid_argument("Unable to write attribute "
182 + std::to_string(_n));
183 } else {
184 return *this;
185 }
186 }
187
200 template<typename T>
201 inline attribute &set(attribute_store_node_value_state_t value_type, const T& value)
202 {
203 if constexpr(std::is_same<T,char const*>::value) {
204 // We are storing strings as C Strings with the null termination caracter in the attribute store.
205 return set(value_type, reinterpret_cast<const uint8_t *>(value), std::strlen(value)+1);
206 } else if constexpr(std::is_same<T,std::string>::value) {
207 // We are storing strings as C Strings with the null termination caracter in the attribute store.
208 return set(value_type, value.c_str());
209 } else if constexpr (is_iterable<T>::value) {
210 typedef typename T::value_type v_t;
211 //Make sure that value type of the conrainter int,float,bool ... etc
212 static_assert(std::is_trivially_copyable<v_t>::value);
213
214 //The purpose of this is to convert the iterable container into a linear buffer
215 std::vector<v_t> v;
216 std::copy(value.begin(), value.end(), std::back_insert_iterator(v));
217 return set(value_type,
218 reinterpret_cast<const uint8_t *>(v.data()),
219 v.size() * sizeof(v_t));
220 }
221 else {
222 static_assert(std::is_trivially_copyable<T>::value);
223 return set(value_type, reinterpret_cast<const uint8_t *>(&value), sizeof(T));
224 }
225 }
226
227
228 inline void clear(attribute_store_node_value_state_t value_type)
229 {
230 if (SL_STATUS_OK
231 != attribute_store_set_node_attribute_value(_n, value_type, 0, 0)) {
232 throw std::invalid_argument("Unable to write attribute");
233 }
234 }
235
239 template<typename T> T reported() const
240 {
241 return get<T>(REPORTED_ATTRIBUTE);
242 }
246 template<typename T> T desired() const
247 {
248 return get<T>(DESIRED_ATTRIBUTE);
249 }
250
254 bool desired_exists()
255 {
257 }
258
263 bool reported_exists()
264 {
266 }
267
268 template<typename T> T desired_or_reported()
269 {
270 return get<T>(DESIRED_OR_REPORTED_ATTRIBUTE);
271 }
272
273 void clear_reported()
274 {
276 }
277
278 void clear_desired()
279 {
281 }
282
286 template<typename T> attribute &set_reported(T v)
287 {
288 return set<T>(REPORTED_ATTRIBUTE, v);
289 }
290
294 template<typename T> attribute &set_desired(T v)
295 {
296 return set<T>(DESIRED_ATTRIBUTE, v);
297 }
298
304 size_t child_count() const
305 {
307 }
308
315 attribute child(size_t index) const
316 {
317 return attribute_store_get_node_child(_n, index);
318 }
319
327 attribute child_by_type(attribute_store_type_t type, size_t index = 0) const
328 {
329 return attribute_store_get_node_child_by_type(_n, type, index);
330 }
331
337 std::vector<attribute> children() const
338 {
339 std::vector<attribute> _children;
340 size_t n_childs = child_count();
341 for (size_t i = 0; i < n_childs; i++) {
342 _children.push_back(child(i));
343 }
344 return _children;
345 }
346
354 std::vector<attribute> children(attribute_store_type_t type) const
355 {
356 std::vector<attribute> _children;
357 for (size_t i = 0; i < child_count(); i++) {
358 if (child(i).type() == type) {
359 _children.push_back(child(i));
360 }
361 }
362 return _children;
363 }
364
376 template<typename T>
377 attribute child_by_type_and_value(attribute_store_type_t type, T value) const
378 {
379 for (auto c: children(type)) {
380 if (c.reported_exists() && c.reported<T>() == value) {
381 return c;
382 }
383 }
385 }
386
393 bool is_valid() const
394 {
396 }
397
403 attribute_store_type_t type() const
404 {
406 }
407
413 static attribute root()
414 {
416 }
417
421 attribute add_node(attribute_store_type_t type)
422 {
423 return attribute_store_add_node(type, _n);
424 }
425
433 template<typename T>
434 attribute emplace_node(attribute_store_type_t type, T val)
435 {
436 attribute a = child_by_type_and_value(type, val);
437 if (a.is_valid()) {
438 return a;
439 } else {
440 return add_node(type).set_reported(val);
441 }
442 }
443
451 attribute emplace_node(attribute_store_type_t type)
452 {
453 attribute a = child_by_type(type);
454 if (a.is_valid()) {
455 return a;
456 } else {
457 return add_node(type);
458 }
459 }
460
465 void delete_node()
466 {
469 }
470
482 inline sl_status_t visit(
483 const std::function<sl_status_t(attribute_store::attribute &, int)> &func,
484 int depth = 0)
485 {
486 sl_status_t status = func(*this, depth);
487 if (SL_STATUS_OK == status) {
488 for (auto c: children()) {
489 status = c.visit(func, depth + 1);
490 if (status == SL_STATUS_ABORT) {
491 return status;
492 }
493 }
494 }
495 return status;
496 }
497
498 //type conversion back to attribute_store_node_t
499 operator attribute_store_node_t() const
500 {
501 return _n;
502 }
503
504 //Comparison operators
505 bool operator==(const attribute &a) const
506 {
507 return _n == a._n;
508 }
510 {
511 return _n == a;
512 }
513
514 private:
516};
517
518} // namespace attribute_store
519
520#endif
521#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
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
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.
void clear(void)
Clear all registered callbacks.
bool operator==(const zigbee_binding_t &A, const zigbee_binding_t &B)
zigbee_binding_t operator== An operator override for equality. Allows zigbee_binding_t to be used in ...