Z-Wave Protocol Controller Reference
zwave_frame_parser.hpp
Go to the documentation of this file.
1/******************************************************************************
2 * # License
3 * <b>Copyright 2024 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
23#ifndef ZWAVE_FRAME_PARSER_HPP
24#define ZWAVE_FRAME_PARSER_HPP
25
26#ifdef __cplusplus
27
28// Attribute store
29#include "attribute_store.h"
30#include "attribute.hpp"
31
32// Unify
33#include "sl_log.h"
34
35// Generic C++ includes
36#include <vector>
37#include <string>
38#include <bitset>
39#include <map>
40
41// Typedef
42using zwave_report_bitmask_t = uint32_t;
43
113class zwave_frame_parser
114{
115 public:
116 using zwave_parser_bitmask_result = std::map<uint8_t, uint8_t>;
117
121 struct bitmask_data {
125 uint8_t bitmask = 0b00000000;
130 attribute_store_node_t destination_node = ATTRIBUTE_STORE_INVALID_NODE;
131 };
132
139 explicit zwave_frame_parser(const uint8_t *data, uint16_t length);
140 ~zwave_frame_parser() = default;
141
154 bool is_frame_size_valid(uint8_t min_size, uint8_t max_size = 0) const;
155
165 uint8_t read_byte();
166
179 uint8_t read_byte(attribute_store_node_t node);
180
221 zwave_parser_bitmask_result
222 read_byte_with_bitmask(const std::vector<bitmask_data> &bitmask_data);
223
236 zwave_parser_bitmask_result
237 read_byte_with_bitmask(const bitmask_data &bitmask_data);
238
260 zwave_report_bitmask_t read_bitmask(uint8_t bitmask_length = 0);
261
285 zwave_report_bitmask_t read_bitmask(attribute_store_node_t node,
286 uint8_t bitmask_length = 0);
287
306 std::string read_string();
327 std::string read_string(attribute_store_node_t node);
328
329
344 template<typename T> T read_sequential(uint8_t bytes_to_read)
345 {
346 static_assert(std::is_integral<T>::value
347 || std::is_same<T, std::string>::value
348 || std::is_same<T, std::vector<uint8_t>>::value,
349 "Unsupported type");
350
351 T value_from_frame;
352 if constexpr (std::is_integral<T>::value) {
353 value_from_frame = 0;
354
355 for (uint8_t i = 0; i < bytes_to_read; i++) {
356 T current_byte = zwave_report_frame.at(current_index);
357 // Z-Wave always have MSB first and LSB last
358 // If we have read 2 bytes : 0x34,0x56 the result should be 0x3456
359 // First iteration : 0x34 << 8 = 0x3400
360 // Second iteration : 0x56 << 0 = 0x3456
361 uint8_t offset = (bytes_to_read - 1 - i) * 8;
362 value_from_frame |= current_byte << offset;
363
364 current_index++;
365 }
366
367 // Convert value to signed if needed
368 // This is used in the case of a signed value that is smaller than the T type
369 // e.g. int8_t stored in a int32_t.
370 if constexpr (std::is_signed<T>::value) {
371 switch (bytes_to_read) {
372 case 1:
373 value_from_frame = static_cast<int8_t>(value_from_frame);
374 break;
375 case 2:
376 value_from_frame = static_cast<int16_t>(value_from_frame);
377 break;
378 case 4:
379 value_from_frame = static_cast<int32_t>(value_from_frame);
380 break;
381 default:
382 throw std::runtime_error("Unsupported size for signed value, only "
383 "1, 2 or 4 are supported");
384 }
385 }
386 } else if constexpr (std::is_same<T, std::string>::value
387 || std::is_same<T, std::vector<uint8_t>>::value) {
388 value_from_frame.resize(bytes_to_read);
389 for (uint8_t i = 0; i < bytes_to_read; i++) {
390 value_from_frame[i] = read_byte();
391 }
392 }
393 return value_from_frame;
394 }
395
412 template<typename T>
413 T read_sequential(uint8_t bytes_to_read, attribute_store_node_t node)
414 {
415 T value = read_sequential<T>(bytes_to_read);
416 helper_store_value(node, value);
417 return value;
418 }
419
420 private:
431 template<typename T>
432 void helper_store_value(attribute_store_node_t node, T value)
433 {
434 attribute_store::attribute current_attribute(node);
435
436 if (current_attribute.is_valid()) {
437 current_attribute.set_reported<T>(value);
438 sl_log_debug("zwave_frame_parser",
439 "Attribute updated : %s",
440 current_attribute.value_to_string().c_str());
441 } else {
442 sl_log_warning(
443 "zwave_frame_parser",
444 "Node does not exist in the attribute store. Not updating value");
445 }
446 }
447
462 uint8_t get_trailing_zeroes(const std::bitset<8> &bitset) const;
463
464 // Contains the frame data
465 std::vector<uint8_t> zwave_report_frame;
466 // The first two bytes contains the command class and the command ID
467 // Those informations are supposed to be valid when we parse the frame.
468 uint8_t current_index = 2;
469};
470
471#endif // #ifdef __cplusplus
472#endif // #ifndef ZWAVE_FRAME_PARSER_HPP