Skip to content

Commit 9db1540

Browse files
silabs-borislrzr
authored andcommitted
uic: zpc: UIC-3488: Allow to specify manually bitmask's size we want to parse
(cherry picked from commit 839f66f80c11c41663f601361a57f99fc12b0df9) Forwarded: #11 Signed-off-by: Philippe Coval <philippe.coval@silabs.com>
1 parent b882c29 commit 9db1540

File tree

3 files changed

+79
-7
lines changed

3 files changed

+79
-7
lines changed

applications/zpc/components/zpc_attribute_store/include/zwave_frame_parser.hpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,12 +250,14 @@ class zwave_frame_parser
250250
*
251251
* @note Calling this function will read the current value in the frame (starting index = 2) and increment it.
252252
*
253+
* @param bitmask_length The size of the bitmask to read. If 0, the function will read the first byte to determine the size. Accepted values : 0...4
254+
*
253255
* @exception std::out_of_range if the current index is out of range
254256
* @exception std::invalid_argument if bitmask length is greater than 4
255257
*
256258
* @return The bitmask read from the frame
257259
*/
258-
zwave_report_bitmask_t read_bitmask();
260+
zwave_report_bitmask_t read_bitmask(uint8_t bitmask_length = 0);
259261

260262
/**
261263
* @brief Read a bitmask (adaptive size) from the frame and store it in the attribute store
@@ -272,14 +274,16 @@ class zwave_frame_parser
272274
* @note Calling this function will read the current value in the frame (starting index = 2) and increment it (to 1 + bitmask size)
273275
*
274276
* @param node The node in the attribute store where to store the value.
277+
* @param bitmask_length The size of the bitmask to read. If 0, the function will read the first byte to determine the size. Accepted values : 0...4
275278
*
276279
* @exception std::out_of_range if the current index is out of range
277280
* @exception std::invalid_argument if something goes wrong when storing the value in the attribute store
278281
* @exception std::invalid_argument if bitmask length is greater than 4
279282
*
280283
* @return The bitmask read from the frame
281284
*/
282-
zwave_report_bitmask_t read_bitmask(attribute_store_node_t node);
285+
zwave_report_bitmask_t read_bitmask(attribute_store_node_t node,
286+
uint8_t bitmask_length = 0);
283287

284288
/**
285289
* @brief Convenience function to read a string (ASCII) from the frame

applications/zpc/components/zpc_attribute_store/src/zwave_frame_parser.cpp

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,23 @@ uint8_t zwave_frame_parser::read_byte(attribute_store_node_t node)
7171
return value;
7272
}
7373

74-
zwave_report_bitmask_t zwave_frame_parser::read_bitmask()
74+
zwave_report_bitmask_t zwave_frame_parser::read_bitmask(uint8_t bitmask_length)
7575
{
7676
constexpr uint8_t SUPPORT_BITMASK_SIZE = sizeof(zwave_report_bitmask_t);
7777
constexpr uint8_t BITMASK_SIZE = SUPPORT_BITMASK_SIZE * 8;
7878

79-
uint8_t bitmask_length = this->read_byte();
79+
if (bitmask_length > BITMASK_SIZE) {
80+
sl_log_critical(LOG_TAG,
81+
"Invalid bitmask size in read_bitmask, must be less than or equal to %d",
82+
SUPPORT_BITMASK_SIZE);
83+
throw std::runtime_error("Critical error in read_bitmask. This should not happen.");
84+
}
85+
86+
// Read the first byte if the length is not provided
87+
if (bitmask_length == 0) {
88+
bitmask_length = read_byte();
89+
}
90+
8091
std::bitset<BITMASK_SIZE> support_bitmask = 0;
8192

8293
if (bitmask_length > SUPPORT_BITMASK_SIZE) {
@@ -100,9 +111,10 @@ zwave_report_bitmask_t zwave_frame_parser::read_bitmask()
100111
}
101112

102113
zwave_report_bitmask_t
103-
zwave_frame_parser::read_bitmask(attribute_store_node_t node)
114+
zwave_frame_parser::read_bitmask(attribute_store_node_t node,
115+
uint8_t bitmask_length)
104116
{
105-
zwave_report_bitmask_t value = read_bitmask();
117+
zwave_report_bitmask_t value = read_bitmask(bitmask_length);
106118

107119
// Store value if applicable
108120
helper_store_value(node, value);
@@ -118,7 +130,7 @@ zwave_frame_parser::zwave_parser_bitmask_result
118130

119131
if (!bitmask_data.empty()) {
120132
uint8_t value_from_frame = read_byte();
121-
133+
122134
for (const auto &current_bitmask: bitmask_data) {
123135
// Extract value
124136
uint8_t current_value = current_bitmask.bitmask & value_from_frame;

applications/zpc/components/zpc_attribute_store/test/zwave_frame_parser_test.cpp

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -548,6 +548,23 @@ void test_read_bitmask_no_attribute_happy_case()
548548
"Should be able to read support bitmask value");
549549
}
550550

551+
void test_read_bitmask_no_attribute_with_size_happy_case()
552+
{
553+
const uint8_t tested_frame[] = {0x01, 0x02, 0xFF, 0x02, 0x12};
554+
uint8_t expected_frame_size = sizeof(tested_frame);
555+
556+
zwave_frame_parser parser(tested_frame, expected_frame_size);
557+
558+
// Read first value
559+
zwave_report_bitmask_t reported_value
560+
= parser.read_bitmask(static_cast<uint8_t>(3));
561+
zwave_report_bitmask_t tested_value = 0x1202FF;
562+
563+
TEST_ASSERT_EQUAL_MESSAGE(tested_value,
564+
reported_value,
565+
"Should be able to read support bitmask value");
566+
}
567+
551568
void test_read_bitmask_attribute_happy_case()
552569
{
553570
const uint8_t tested_frame[] = {0x01, 0x02, 3, 0x12, 0xFF, 0x02};
@@ -574,6 +591,33 @@ void test_read_bitmask_attribute_happy_case()
574591
"Value on node should match the returned value");
575592
}
576593

594+
void test_read_bitmask_attribute_given_size_happy_case()
595+
{
596+
const uint8_t tested_frame[] = {0x01, 0x02, 0x12, 0xFF, 0x02, 0x15};
597+
uint8_t expected_frame_size = sizeof(tested_frame);
598+
599+
zwave_frame_parser parser(tested_frame, expected_frame_size);
600+
601+
// Any nodes that have the right type (zwave_report_bitmask_t) and under endpoint_id will do the trick here
602+
attribute_store::attribute endpoint_id_node_cpp(endpoint_id_node);
603+
auto bitmask_node = endpoint_id_node_cpp.add_node(
604+
ATTRIBUTE_COMMAND_CLASS_THERMOSTAT_SUPPORTED_MODES);
605+
606+
// Read first value
607+
zwave_report_bitmask_t reported_value
608+
= parser.read_bitmask(bitmask_node, static_cast<uint8_t>(4));
609+
zwave_report_bitmask_t tested_value = 0x1502FF12;
610+
611+
TEST_ASSERT_EQUAL_MESSAGE(tested_value,
612+
reported_value,
613+
"Should be able to read support bitmask value");
614+
615+
TEST_ASSERT_EQUAL_MESSAGE(
616+
tested_value,
617+
bitmask_node.get<zwave_report_bitmask_t>(REPORTED_ATTRIBUTE),
618+
"Value on node should match the returned value");
619+
}
620+
577621
void test_read_bitmask_value_too_big()
578622
{
579623
const uint8_t tested_frame[] = {0x01, 0x02, 5, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
@@ -586,6 +630,18 @@ void test_read_bitmask_value_too_big()
586630
"a support bitmask value that is too big");
587631
}
588632

633+
void test_read_bitmask_specified_value_too_big()
634+
{
635+
const uint8_t tested_frame[] = {0x01, 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
636+
637+
uint8_t expected_frame_size = sizeof(tested_frame);
638+
zwave_frame_parser parser(tested_frame, expected_frame_size);
639+
640+
TEST_ASSERT_EXCEPTION_MESSAGE(parser.read_bitmask(static_cast<uint8_t>(5)),
641+
"Should throw an exception when trying to read "
642+
"a support bitmask value that is too big");
643+
}
644+
589645
void test_read_string_no_attribute_happy_case()
590646
{
591647
const uint8_t tested_frame[] = {0x01, 0x02, 5, 'D', 'o', 'U', 'z', 'E'};

0 commit comments

Comments
 (0)