Zigbee Protocol Controller 1.6.0
zigpc_datastore_accessor.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
22#ifndef ZIGPC_DATASTORE_ACCESSOR_HPP
23#define ZIGPC_DATASTORE_ACCESSOR_HPP
24
25#include <sstream>
26
27// Unify shared includes
28#include <sl_status.h>
29#include <sl_log.h>
30#include <attribute_store.h>
31
32// ZigPC includes
33#include "zigpc_datastore.h"
34#include "zigpc_datastore_id.h"
35
36static constexpr char LOG_TAG[] = "zigpc_datastore";
37
52template<typename search_key_t, typename data_t> class StoreAccessor
53{
54 private:
56 std::string label;
58 public:
61 {}
62
63 virtual ~StoreAccessor() = default;
64
65 inline std::string get_label(void) const
66 {
67 return label;
68 }
69
71 {
72 return node_type;
73 }
74
84 {
85 auto found_node = ATTRIBUTE_STORE_INVALID_NODE;
86
87 std::stringstream ss;
88 ss << key;
89 std::string key_str = ss.str();
90
91 bool input_valid = attribute_store_node_exists(parent);
92 if (input_valid == false) {
94 "%s: %s entity[NodeId:%u] Failed to find parent node",
95 this->label.c_str(),
96 key_str.c_str());
97 } else {
99 parent,
100 this->node_type,
102 reinterpret_cast<uint8_t *>(&key),
103 sizeof(search_key_t),
104 0);
105 }
106
107 return found_node;
108 }
109
119 search_key_t key,
120 attribute_store_type_t child_type)
121 {
122 size_t child_count = 0U;
123
124 attribute_store_node_t found_node = this->find(parent, key);
125 if (found_node != ATTRIBUTE_STORE_INVALID_NODE) {
126 attribute_store_node_t child_node
128 child_type,
130
131 bool child_valid = !(child_node == ATTRIBUTE_STORE_INVALID_NODE);
132 while (child_valid) {
133 child_count++;
134 child_node = attribute_store_get_node_child_by_type(found_node,
135 child_type,
137 child_valid = !(child_node == ATTRIBUTE_STORE_INVALID_NODE);
138 }
139 }
140
141 return child_count;
142 }
143
155 size_t index,
156 search_key_t *key)
157 {
158 sl_status_t status = SL_STATUS_OK;
159
160 attribute_store_node_t found_child
162 this->node_type,
163 (uint32_t)index);
164 if (found_child == ATTRIBUTE_STORE_INVALID_NODE) {
165 status = SL_STATUS_NOT_FOUND;
166 } else {
167 uint8_t child_size(sizeof(search_key_t));
169 found_child,
171 reinterpret_cast<uint8_t *>(key),
172 &child_size);
173 }
174
175 return status;
176 }
177
187 sl_status_t create(attribute_store_node_t parent, search_key_t key)
188 {
189 sl_status_t status = SL_STATUS_OK;
190 auto found_node = ATTRIBUTE_STORE_INVALID_NODE;
191
192 std::stringstream ss;
193 ss << key;
194 std::string key_str = ss.str();
195
196 found_node = this->find(parent, key);
197 if (found_node != ATTRIBUTE_STORE_INVALID_NODE) {
199 } else {
200 found_node = attribute_store_add_node(this->node_type, parent);
201 if (found_node == ATTRIBUTE_STORE_INVALID_NODE) {
202 status = SL_STATUS_FAIL;
204 "%s: Failed to create entity %s",
205 this->label.c_str(),
206 key_str.c_str());
207 }
208 }
209
210 if (status == SL_STATUS_OK) {
211 uint8_t key_size = sizeof(search_key_t);
212
214 found_node,
216 reinterpret_cast<uint8_t *>(&key),
217 key_size);
218 if (status != SL_STATUS_OK) {
220 "%s: %s entity[NodeId:%u]: Failed to populate entity data",
221 this->label.c_str(),
222 key_str.c_str(),
223 found_node);
224 }
225 }
226
227 return status;
228 }
229
242 read(attribute_store_node_t parent, search_key_t key, data_t *const data)
243 {
244 sl_status_t status = SL_STATUS_OK;
245 auto found_node = ATTRIBUTE_STORE_INVALID_NODE;
246
247 if (data == nullptr) {
248 status = SL_STATUS_NULL_POINTER;
249 } else {
250 found_node = this->find(parent, key);
251 if (found_node == ATTRIBUTE_STORE_INVALID_NODE) {
252 status = SL_STATUS_NOT_FOUND;
253 }
254 }
255
256 if (status == SL_STATUS_OK) {
257 uint8_t data_size = sizeof(data_t);
259 found_node,
261 reinterpret_cast<uint8_t *>(data),
262 &data_size);
263 if (status != SL_STATUS_OK) {
264 std::stringstream ss;
265 ss << key;
266 std::string key_str = ss.str();
268 "%s: %s entity[NodeId:%u]: Failed to read entity data",
269 this->label.c_str(),
270 key_str.c_str(),
271 found_node);
272 }
273 }
274
275 return status;
276 }
277
290 write(attribute_store_node_t parent, search_key_t key, const data_t *data)
291 {
292 sl_status_t status = SL_STATUS_OK;
293 auto found_node = ATTRIBUTE_STORE_INVALID_NODE;
294
295 if (data == nullptr) {
296 status = SL_STATUS_NULL_POINTER;
297 } else {
298 found_node = this->find(parent, key);
299 if (found_node == ATTRIBUTE_STORE_INVALID_NODE) {
300 status = SL_STATUS_NOT_FOUND;
301 }
302 }
303
304 if (status == SL_STATUS_OK) {
305 uint8_t data_size = sizeof(data_t);
307 found_node,
309 reinterpret_cast<const uint8_t *>(data),
310 data_size);
311 if (status != SL_STATUS_OK) {
312 std::stringstream ss;
313 ss << key;
314 std::string key_str = ss.str();
316 "%s: %s entity[NodeId:%u]: Failed to write entity data",
317 this->label.c_str(),
318 key_str.c_str(),
319 found_node);
320 }
321 }
322
323 return status;
324 }
325
335 sl_status_t remove(attribute_store_node_t parent, search_key_t key)
336 {
337 sl_status_t status = SL_STATUS_OK;
338
339 std::stringstream ss;
340 ss << key;
341 std::string key_str = ss.str();
342
343 attribute_store_node_t found_node = this->find(parent, key);
344
345 if (found_node != ATTRIBUTE_STORE_INVALID_NODE) {
346 status = attribute_store_delete_node(found_node);
347 if (status != SL_STATUS_OK) {
349 "%s: %s entity[NodeId:%u]: Failed to remove entity",
350 this->label.c_str(),
351 key_str.c_str(),
352 found_node);
353 }
354 } else {
355 status = SL_STATUS_NOT_FOUND;
356 }
357
358 return status;
359 }
360
371 {
372 sl_status_t status = SL_STATUS_OK;
373
374 attribute_store_node_t found_node = this->find(parent, key);
375
376 std::stringstream ss;
377 ss << key;
378 std::string key_str = ss.str();
379 if (found_node == ATTRIBUTE_STORE_INVALID_NODE) {
380 status = SL_STATUS_NOT_FOUND;
382 "%s: Failed to find entity %s to remove children under",
383 this->label.c_str(),
384 key_str.c_str());
385 } else {
387 for (size_t i = 0; i < child_count; i++) {
388 attribute_store_node_t child_node
389 = attribute_store_get_node_child(found_node, i);
390 if (child_node != ATTRIBUTE_STORE_INVALID_NODE) {
391 status = attribute_store_delete_node(child_node);
392 if (status != SL_STATUS_OK) {
394 "%s: Failed to remove child[%u] remove entity",
395 this->label.c_str(),
396 i);
397 }
398 }
399 }
400 }
401
402 return status;
403 }
404
414 virtual std::string to_str(attribute_store_node_t parent, search_key_t key)
415 {
416 std::ostringstream ss;
417 data_t data;
418
419 sl_status_t status = this->read(parent, key, &data);
420 if (status == SL_STATUS_OK) {
421 ss << this->label << ": ";
422 uint8_t *buffer = reinterpret_cast<uint8_t *>(&data);
423 for (size_t i = 0U; i < sizeof(data_t); i++) {
424 ss << *buffer << " ";
425 buffer++;
426 }
427 }
428
429 return ss.str();
430 }
431};
432
433template<typename list_entry_t> class StoreListAccessor
434{
435 private:
437
438 public:
440 std::string label) :
441 list_entry(node_type, label)
442 {}
443
444 virtual ~StoreListAccessor() = default;
445
458 list_entry_t *const list,
459 size_t list_capacity)
460 {
461 sl_status_t status = SL_STATUS_OK;
462
463 if (list == nullptr) {
464 status = SL_STATUS_NULL_POINTER;
465 }
466 for (size_t i = 0; (status == SL_STATUS_OK) && (i < list_capacity); i++) {
467 status = this->list_entry.find_by_index(list_parent, i, list + i);
468 }
469 return status;
470 }
471
488 const list_entry_t *list,
489 size_t list_count)
490 {
491 sl_status_t status = SL_STATUS_OK;
492
493 if (list == nullptr) {
494 status = SL_STATUS_NULL_POINTER;
495 } else {
496 // Ensure there is no existing array under the parent by checking if
497 // first element exists.
498 attribute_store_node_t child_node
500 list_parent,
501 this->list_entry.get_node_type());
502 if (child_node != ATTRIBUTE_STORE_INVALID_NODE) {
504 }
505 }
506
507 for (size_t i = 0; (status == SL_STATUS_OK) && (i < list_count); i++) {
508 status = this->list_entry.create(list_parent, list[i]);
509 }
510
511 return status;
512 }
513
521 {
522 sl_status_t status = SL_STATUS_OK;
523
524 attribute_store_type_t entry_type = this->list_entry.get_node_type();
525
526 if (list_parent != ATTRIBUTE_STORE_INVALID_NODE) {
527 size_t list_index = 0U;
528
529 attribute_store_node_t entry_node
531 entry_type,
532 list_index);
533 while ((status == SL_STATUS_OK)
534 && entry_node != ATTRIBUTE_STORE_INVALID_NODE) {
535 status = attribute_store_delete_node(entry_node);
536 list_index++;
537 entry_node = attribute_store_get_node_child_by_type(list_parent,
538 entry_type,
539 list_index);
540 }
541 }
542
543 return status;
544 }
545
546 /* Abstract functions that must be implemented */
547
548 virtual std::string to_str(attribute_store_node_t parent, size_t list_count)
549 = 0;
550};
551
552/**********************************
553 **********************************
554 *
555 * Accessors used by component
556 *
557 **********************************
558 **********************************/
559
560class NetworkAccessor : public StoreAccessor<uint8_t, zigpc_network_data_t>
561{
562 public:
563 explicit NetworkAccessor();
564
573 std::string to_str(attribute_store_node_t parent, uint8_t index) override;
574};
575
577 public StoreAccessor<zigbee_eui64_uint_t, zigpc_device_data_t>
578{
579 public:
580 explicit DeviceAccessor();
581
590 std::string to_str(attribute_store_node_t parent,
591 zigbee_eui64_uint_t eui64) override;
592};
593
595 public StoreAccessor<zigbee_endpoint_id_t, zigpc_endpoint_data_t>
596{
597 public:
599
608 std::string to_str(attribute_store_node_t parent,
609 zigbee_endpoint_id_t endpoint_id) override;
610};
611
613 public StoreAccessor<zigbee_group_id_t, zigpc_group_data_t>
614{
615 private:
617
618 public:
619 explicit GroupAccessor( bool is_reported);
620
627 static inline std::string get_label_type(bool is_reported)
628 {
629 return is_reported ? "ReportedGroup" : "DesiredGroup";
630 }
631
640 static inline attribute_store_type_t
642 {
644 }
645
654 std::string to_str(attribute_store_node_t parent,
655 zigbee_group_id_t group_id) override;
656
657
658};
659
661 public StoreAccessor<zcl_cluster_id_t, zigpc_cluster_data_t>
662{
663 private:
665
666 public:
668
676 {
677 return (cluster_side == ZCL_CLUSTER_SERVER_SIDE) ? "ServerCluster"
678 : "ClientCluster";
679 }
680
689 static inline attribute_store_type_t
691 {
695 }
696
705 std::string to_str(attribute_store_node_t parent,
706 zcl_cluster_id_t cluster_id) override;
707};
708
710 public StoreListAccessor<zcl_attribute_id_t>
711{
712 public:
714
720 static inline std::string get_label_type(void)
721 {
722 return "Attribute";
723 }
724
733 std::string to_str(attribute_store_node_t parent, size_t list_count) override;
734};
735
736class ClusterCommandListAccessor : public StoreListAccessor<zcl_command_id_t>
737{
738 private:
740
741 public:
743
751 {
752 return (command_type == ZCL_CLUSTER_GENERATED_COMMAND) ? "GeneratedCommand"
753 : "RecievedCommand";
754 }
755
764 static inline attribute_store_type_t
766 {
770 }
771
780 std::string to_str(attribute_store_node_t parent, size_t list_count) override;
781};
782
783#endif //ZIGPC_DATASTORE_ACCESSOR_HPP
784
uint32_t attribute_store_type_t
Definition: attribute_store.h:50
Definition: zigpc_datastore_accessor.hpp:662
static std::string get_label_type(zcl_cluster_side_t cluster_side)
Get the label based on the cluster side used.
Definition: zigpc_datastore_accessor.hpp:675
static attribute_store_type_t get_entity_type(zcl_cluster_side_t cluster_side)
Retrieve the attribute store node type of the cluster based on the cluster side received.
Definition: zigpc_datastore_accessor.hpp:690
zcl_cluster_side_t cluster_side
Definition: zigpc_datastore_accessor.hpp:664
ClusterAccessor(zcl_cluster_side_t cluster_side)
std::string to_str(attribute_store_node_t parent, zcl_cluster_id_t cluster_id) override
Return string representation of cluster entity.
Definition: zigpc_datastore_accessor.hpp:711
std::string to_str(attribute_store_node_t parent, size_t list_count) override
Return string representation of attribute list.
static std::string get_label_type(void)
Get the label type of the attribute list.
Definition: zigpc_datastore_accessor.hpp:720
Definition: zigpc_datastore_accessor.hpp:737
zcl_command_type_t command_type
Definition: zigpc_datastore_accessor.hpp:739
static std::string get_label_type(zcl_command_type_t command_type)
Get the label type based on the command type passed in.
Definition: zigpc_datastore_accessor.hpp:750
std::string to_str(attribute_store_node_t parent, size_t list_count) override
Return string representation of command list.
static attribute_store_type_t get_entity_type(zcl_command_type_t command_type)
Retrieve the attribute store node type of the command based on the command type received.
Definition: zigpc_datastore_accessor.hpp:765
ClusterCommandListAccessor(zcl_command_type_t command_type)
Definition: zigpc_datastore_accessor.hpp:578
std::string to_str(attribute_store_node_t parent, zigbee_eui64_uint_t eui64) override
Return string representation of device entity.
Definition: zigpc_datastore_accessor.hpp:596
std::string to_str(attribute_store_node_t parent, zigbee_endpoint_id_t endpoint_id) override
Return string representation of endpoint entity.
Definition: zigpc_datastore_accessor.hpp:614
bool is_reported
Definition: zigpc_datastore_accessor.hpp:616
std::string to_str(attribute_store_node_t parent, zigbee_group_id_t group_id) override
Return string representation of group entity.
GroupAccessor(bool is_reported)
static attribute_store_type_t get_entity_type(bool is_reported)
Retrieve the attribute store node type of the group based on the reported/desired type received.
Definition: zigpc_datastore_accessor.hpp:641
static std::string get_label_type(bool is_reported)
Get the label type of the group.
Definition: zigpc_datastore_accessor.hpp:627
Definition: zigpc_datastore_accessor.hpp:561
std::string to_str(attribute_store_node_t parent, uint8_t index) override
Return string representation of network entity.
Template class for accessing entities using the attribute store API.
Definition: zigpc_datastore_accessor.hpp:53
virtual ~StoreAccessor()=default
sl_status_t remove(attribute_store_node_t parent, search_key_t key)
Remove the entity from the store.
Definition: zigpc_datastore_accessor.hpp:335
sl_status_t remove_children(attribute_store_node_t parent, search_key_t key)
Remove all child entities from the store.
Definition: zigpc_datastore_accessor.hpp:370
virtual std::string to_str(attribute_store_node_t parent, search_key_t key)
Get string representation of entity in byte buffer representation.
Definition: zigpc_datastore_accessor.hpp:414
attribute_store_node_t find(attribute_store_node_t parent, search_key_t key)
Find an entity based based on the key.
Definition: zigpc_datastore_accessor.hpp:83
sl_status_t write(attribute_store_node_t parent, search_key_t key, const data_t *data)
Write information to the entity.
Definition: zigpc_datastore_accessor.hpp:290
attribute_store_type_t node_type
Definition: zigpc_datastore_accessor.hpp:55
std::string label
Definition: zigpc_datastore_accessor.hpp:56
attribute_store_type_t get_node_type(void) const
Definition: zigpc_datastore_accessor.hpp:70
std::string get_label(void) const
Definition: zigpc_datastore_accessor.hpp:65
StoreAccessor(attribute_store_type_t node_type, std::string label)
Definition: zigpc_datastore_accessor.hpp:59
sl_status_t create(attribute_store_node_t parent, search_key_t key)
Create a new entity based on the search key.
Definition: zigpc_datastore_accessor.hpp:187
size_t child_count(attribute_store_node_t parent, search_key_t key, attribute_store_type_t child_type)
Retrive the count of child entities by type.
Definition: zigpc_datastore_accessor.hpp:118
sl_status_t read(attribute_store_node_t parent, search_key_t key, data_t *const data)
Read information of the entity.
Definition: zigpc_datastore_accessor.hpp:242
sl_status_t find_by_index(attribute_store_node_t parent, size_t index, search_key_t *key)
Find the search key of the child entity based on the index.
Definition: zigpc_datastore_accessor.hpp:154
Definition: zigpc_datastore_accessor.hpp:434
virtual ~StoreListAccessor()=default
sl_status_t read_list(attribute_store_node_t list_parent, list_entry_t *const list, size_t list_capacity)
Read the list of entries.
Definition: zigpc_datastore_accessor.hpp:457
sl_status_t remove_list(attribute_store_node_t list_parent)
Remove a list under the node ID passed in.
Definition: zigpc_datastore_accessor.hpp:520
StoreListAccessor(attribute_store_type_t node_type, std::string label)
Definition: zigpc_datastore_accessor.hpp:439
StoreAccessor< list_entry_t, uint8_t > list_entry
Definition: zigpc_datastore_accessor.hpp:436
virtual std::string to_str(attribute_store_node_t parent, size_t list_count)=0
sl_status_t create_list(attribute_store_node_t list_parent, const list_entry_t *list, size_t list_count)
Create the list into the store if it doesn't exist already.
Definition: zigpc_datastore_accessor.hpp:487
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_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.
attribute_store_node_t attribute_store_get_node_child_by_value(attribute_store_node_t node, attribute_store_type_t child_type, attribute_store_node_value_state_t value_state, const uint8_t *value, uint8_t value_size, uint32_t child_index)
Get the node handle of a child of a node with a certain type and value.
static attribute_store_node_t attribute_store_get_first_child_by_type(attribute_store_node_t node, attribute_store_type_t child_type)
Definition: attribute_store.h:353
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
@ 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
#define data
Definition: ctimer.c:49
#define sl_log_warning(tag, fmtstr,...)
Definition: sl_log.h:143
#define sl_log_error(tag, fmtstr,...)
Definition: sl_log.h:145
#define SL_STATUS_OK
No error.
Definition: sl_status.h:49
#define SL_STATUS_ALREADY_EXISTS
Item already exists.
Definition: sl_status.h:101
uint32_t sl_status_t
Definition: sl_status.h:139
#define SL_STATUS_FAIL
Generic error.
Definition: sl_status.h:50
#define SL_STATUS_NULL_POINTER
Invalid null pointer received as argument.
Definition: sl_status.h:89
#define SL_STATUS_NOT_FOUND
Item could not be found.
Definition: sl_status.h:100
enum e_zcl_cluster_side zcl_cluster_side_t
An enum representing the role of the cluster on the network.
uint16_t zcl_cluster_id_t
A representation of the endpoint cluster id used in ZCL.
Definition: zigpc_common_zigbee.h:254
zcl_command_type_t
Definition: zigpc_common_zigbee.h:267
uint64_t zigbee_eui64_uint_t
Zigbee Device Identifier (stored as integer)
Definition: zigpc_common_zigbee.h:199
uint16_t zigbee_group_id_t
Zigbee Group Id The internal representation of a group_id.
Definition: zigpc_common_zigbee.h:230
uint8_t zigbee_endpoint_id_t
A representation of the endpoint id used on the Zigbee protocol.
Definition: zigpc_common_zigbee.h:248
@ ZCL_CLUSTER_GENERATED_COMMAND
Definition: zigpc_common_zigbee.h:268
@ ZCL_CLUSTER_SERVER_SIDE
Definition: zigpc_common_zigbee.h:321
static constexpr char LOG_TAG[]
Definition: zigpc_datastore_accessor.hpp:36
@ ZIGPC_DS_TYPE_GROUP_REPORTED
Definition: zigpc_datastore_id.h:47
@ ZIGPC_DS_TYPE_CLIENT_CLUSTER
Definition: zigpc_datastore_id.h:43
@ ZIGPC_DS_TYPE_SERVER_CLUSTER
Definition: zigpc_datastore_id.h:42
@ ZIGPC_DS_TYPE_GROUP_DESIRED
Definition: zigpc_datastore_id.h:48
@ ZIGPC_DS_TYPE_CLUSTER_GENERATED_COMMAND
Definition: zigpc_datastore_id.h:45
@ ZIGPC_DS_TYPE_CLUSTER_RECEIVED_COMMAND
Definition: zigpc_datastore_id.h:46
SL Status Codes.
Definition: list.c:52