Skip to content

Commit 5ceec9b

Browse files
Vietrzr
authored andcommitted
UIC-3275: Application Status CC
Origin: SiliconLabsSoftware#147 Signed-off-by: Philippe Coval <philippe.coval@silabs.com>
1 parent 0b41085 commit 5ceec9b

File tree

9 files changed

+618
-0
lines changed

9 files changed

+618
-0
lines changed

applications/zpc/components/zpc_attribute_store/include/attribute_store_defined_attribute_types.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1113,6 +1113,23 @@ DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_SOUND_SWITCH_TONE_INFO_NAME,
11131113
DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_SOUND_SWITCH_TONE_PLAY,
11141114
((COMMAND_CLASS_SOUND_SWITCH << 8) | 0x08))
11151115

1116+
/////////////////////////////////////////////////
1117+
// Application Status Command Class
1118+
///< This represents the version of the Sound Switch Command class.
1119+
/// zwave_cc_version_t
1120+
DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_APPLICATION_STATUS_VERSION,
1121+
ZWAVE_CC_VERSION_ATTRIBUTE(COMMAND_CLASS_APPLICATION_STATUS))
1122+
// Application Status Busy Status
1123+
DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_APPLICATION_STATUS_BUSY_STATUS,
1124+
((COMMAND_CLASS_APPLICATION_STATUS << 8) | 0x02))
1125+
// Application Status Busy Wait time
1126+
DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_APPLICATION_STATUS_WAIT_TIME,
1127+
((COMMAND_CLASS_APPLICATION_STATUS << 8) | 0x03))
1128+
// Application Status Reject Status
1129+
DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_APPLICATION_STATUS_REJECT_STATUS,
1130+
((COMMAND_CLASS_APPLICATION_STATUS << 8) | 0x04))
1131+
1132+
11161133
/////////////////////////////////////////////////
11171134
// Z-Wave Plus Info CC
11181135
DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_ZWAVEPLUS_INFO_VERSION,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
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+
14+
15+
#ifndef ZWAVE_COMMAND_CLASS_APPLICATION_STATUS_TYPES_H
16+
#define ZWAVE_COMMAND_CLASS_APPLICATION_STATUS_TYPES_H
17+
18+
#include <stdint.h>
19+
20+
///> Application busy status. uint8_t
21+
typedef uint8_t application_busy_status;
22+
23+
///> Application busy wait time. uint8_t
24+
typedef uint8_t application_busy_wait_time;
25+
26+
///> Application reject request. uint8_t
27+
typedef uint8_t application_reject_request;
28+
29+
typedef enum {
30+
TRY_AGAIN_LATER = 0,
31+
TRY_AGAIN_WAIT_TIME = 1,
32+
REQUEST_QUEUED = 2
33+
} application_busy_status_enum;
34+
35+
#endif //ZWAVE_COMMAND_CLASS_APPLICATION_STATUS_TYPES_H
36+
/** @} end zwave_command_class_application_status_types */

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,14 @@ static const std::vector<attribute_schema_t> attribute_schema = {
514514
{ATTRIBUTE_COMMAND_CLASS_SOUND_SWITCH_TONE_INFO_NAME, "Tone Info Name", ATTRIBUTE_COMMAND_CLASS_SOUND_SWITCH_TONE_INFO_IDENTIFIER, C_STRING_STORAGE_TYPE},
515515
{ATTRIBUTE_COMMAND_CLASS_SOUND_SWITCH_TONE_PLAY, "Tone Play", ATTRIBUTE_ENDPOINT_ID, U8_STORAGE_TYPE},
516516

517+
/////////////////////////////////////////////////////////////////////
518+
// Application Status Command Class attributes
519+
/////////////////////////////////////////////////////////////////////
520+
{ATTRIBUTE_COMMAND_CLASS_APPLICATION_STATUS_VERSION, "Application Status Version", ATTRIBUTE_ENDPOINT_ID, U8_STORAGE_TYPE},
521+
{ATTRIBUTE_COMMAND_CLASS_APPLICATION_STATUS_BUSY_STATUS, "Application Busy Status", ATTRIBUTE_ENDPOINT_ID, U8_STORAGE_TYPE},
522+
{ATTRIBUTE_COMMAND_CLASS_APPLICATION_STATUS_WAIT_TIME, "Application Busy Wait Time", ATTRIBUTE_COMMAND_CLASS_APPLICATION_STATUS_BUSY_STATUS, U8_STORAGE_TYPE},
523+
{ATTRIBUTE_COMMAND_CLASS_APPLICATION_STATUS_REJECT_STATUS, "Application Reject Status", ATTRIBUTE_ENDPOINT_ID, U8_STORAGE_TYPE},
524+
517525
//DoorLock Command Class attributes
518526
{ATTRIBUTE_DOOR_LOCK_CONFIGURATION_OPERATION_TYPE, "Door Lock Configuration Operation Type", ATTRIBUTE_ENDPOINT_ID, I32_STORAGE_TYPE },
519527
{ATTRIBUTE_DOOR_LOCK_CONFIGURATION_INSIDE_DOOR_HANDLES_STATE, "Door Lock Configuration Inside Handles State", ATTRIBUTE_ENDPOINT_ID, I32_STORAGE_TYPE },

applications/zpc/components/zwave_command_classes/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ add_library(
1010
platform/${COMPATIBLE_PLATFORM}/platform_exec.c
1111
src/zwave_command_class_agi.cpp
1212
src/zwave_command_class_alarm_sensor.c
13+
src/zwave_command_class_application_status.cpp
1314
src/zwave_command_class_association.cpp
1415
src/zwave_command_class_association_send.cpp
1516
src/zwave_command_class_basic.c
Lines changed: 263 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,263 @@
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+
// Includes from this component
14+
#include "zwave_command_class_application_status.h"
15+
#include "zwave_command_class_application_status_types.h"
16+
#include "zwave_command_classes_utils.h"
17+
18+
// Generic includes
19+
#include <stdlib.h>
20+
#include <assert.h>
21+
22+
// Includes from other ZPC Components
23+
#include "zwave_command_class_indices.h"
24+
#include "zwave_command_handler.h"
25+
#include "zpc_attribute_store_network_helper.h"
26+
#include "attribute_store_defined_attribute_types.h"
27+
#include "ZW_classcmd.h"
28+
#include "zpc_attribute_resolver.h"
29+
30+
// Includes from other Unify Components
31+
#include "dotdot_mqtt.h"
32+
#include "dotdot_mqtt_generated_commands.h"
33+
#include "attribute_store_helper.h"
34+
#include "attribute_store.h"
35+
#include "attribute_resolver.h"
36+
#include "attribute_timeouts.h"
37+
#include "sl_log.h"
38+
39+
// Cpp include
40+
#include "attribute.hpp"
41+
#include "zwave_frame_generator.hpp"
42+
#include "zwave_frame_parser.hpp"
43+
44+
// Attribute macro, shortening those long defines for attribute types:
45+
#define ATTRIBUTE(type) ATTRIBUTE_COMMAND_CLASS_APPLICATION_STATUS_##type
46+
47+
// Log tag
48+
constexpr char LOG_TAG[] = "zwave_command_class_application_status";
49+
50+
namespace
51+
{
52+
zwave_frame_generator frame_generator(COMMAND_CLASS_APPLICATION_STATUS);
53+
}
54+
55+
///////////////////////////////////////////////////////////////////////////////
56+
// Helper functions
57+
///////////////////////////////////////////////////////////////////////////////
58+
zwave_cc_version_t
59+
get_current_application_status_version(attribute_store_node_t node)
60+
{
61+
zwave_cc_version_t version = zwave_command_class_get_version_from_node(
62+
node,
63+
COMMAND_CLASS_APPLICATION_STATUS);
64+
65+
if (version == 0) {
66+
sl_log_error(LOG_TAG, "Application_status Command Class Version not found");
67+
}
68+
69+
return version;
70+
}
71+
72+
///////////////////////////////////////////////////////////////////////////////
73+
// Validation function
74+
///////////////////////////////////////////////////////////////////////////////
75+
bool zwave_command_class_application_status_validate_reject_value(uint8_t value)
76+
{
77+
return (value == 0x00 || value == 0x01);
78+
}
79+
80+
///////////////////////////////////////////////////////////////////////////////
81+
// Frame parsing functions
82+
///////////////////////////////////////////////////////////////////////////////
83+
static sl_status_t zwave_command_class_application_status_handle_status_busy(
84+
const zwave_controller_connection_info_t *connection_info,
85+
const uint8_t *frame_data,
86+
uint16_t frame_length)
87+
{
88+
// Setup
89+
attribute_store::attribute endpoint_node(
90+
zwave_command_class_get_endpoint_node(connection_info));
91+
92+
sl_log_debug(LOG_TAG,
93+
"Application Status Report Application Busy frame received");
94+
95+
// Compute expected size for report frame
96+
const uint8_t expected_size = sizeof(ZW_APPLICATION_BUSY_FRAME);
97+
98+
// Parse the frame
99+
try {
100+
zwave_frame_parser parser(frame_data, frame_length);
101+
102+
// Validate frame size with desired size
103+
if (!parser.is_frame_size_valid(expected_size)) {
104+
sl_log_error(LOG_TAG,
105+
"Invalid frame size for Application Status Report "
106+
"Application Busy frame");
107+
return SL_STATUS_FAIL;
108+
}
109+
110+
// Create the busy status attributes if not exists
111+
auto busy_status_node = endpoint_node.emplace_node(ATTRIBUTE(BUSY_STATUS));
112+
113+
//Read Status value from report frame and store attribute
114+
parser.read_byte(busy_status_node);
115+
116+
// Create the wait time attributes if not exists, Read Wait time from report frame store attribute
117+
parser.read_byte(busy_status_node.emplace_node(ATTRIBUTE(WAIT_TIME)));
118+
119+
} catch (const std::exception &e) {
120+
sl_log_error(LOG_TAG,
121+
"Error while parsing Application Status Report Application "
122+
"Busy frame : %s",
123+
e.what());
124+
return SL_STATUS_FAIL;
125+
}
126+
return SL_STATUS_OK;
127+
}
128+
129+
static sl_status_t zwave_command_class_application_status_handle_status_reject(
130+
const zwave_controller_connection_info_t *connection_info,
131+
const uint8_t *frame_data,
132+
uint16_t frame_length)
133+
{
134+
// Setup
135+
attribute_store::attribute endpoint_node(
136+
zwave_command_class_get_endpoint_node(connection_info));
137+
138+
sl_log_debug(LOG_TAG,
139+
"Application Status Report Application Reject frame received");
140+
141+
// Compute expected size for report frame
142+
const uint8_t expected_size = sizeof(ZW_APPLICATION_REJECTED_REQUEST_FRAME);
143+
144+
// Parse the frame
145+
try {
146+
zwave_frame_parser parser(frame_data, frame_length);
147+
148+
// Validate frame size with desired size
149+
if (!parser.is_frame_size_valid(expected_size)) {
150+
sl_log_error(LOG_TAG,
151+
"Invalid frame size for Application Status Report "
152+
"Application Reject frame");
153+
return SL_STATUS_FAIL;
154+
}
155+
156+
//Read Status and store attribute
157+
application_busy_status status = parser.read_byte();
158+
sl_log_debug(LOG_TAG, "Application Status Reject Status : %d", status);
159+
160+
if (!zwave_command_class_application_status_validate_reject_value(status)) {
161+
return SL_STATUS_FAIL;
162+
}
163+
164+
// Create the reject status attributes if not exists
165+
auto reject_status_node
166+
= endpoint_node.emplace_node(ATTRIBUTE(REJECT_STATUS));
167+
reject_status_node.set_reported<application_reject_request>(status);
168+
169+
} catch (const std::exception &e) {
170+
sl_log_error(LOG_TAG,
171+
"Error while parsing Application Status Report Application "
172+
"Reject frame : %s",
173+
e.what());
174+
return SL_STATUS_FAIL;
175+
}
176+
return SL_STATUS_OK;
177+
}
178+
179+
///////////////////////////////////////////////////////////////////////////////
180+
// Incoming commands handler
181+
///////////////////////////////////////////////////////////////////////////////
182+
sl_status_t zwave_command_class_application_status_control_handler(
183+
const zwave_controller_connection_info_t *connection_info,
184+
const uint8_t *frame_data,
185+
uint16_t frame_length)
186+
{
187+
// Frame too short, it should have not come here.
188+
if (frame_length <= COMMAND_INDEX) {
189+
return SL_STATUS_NOT_SUPPORTED;
190+
}
191+
192+
switch (frame_data[COMMAND_INDEX]) {
193+
case APPLICATION_BUSY:
194+
return zwave_command_class_application_status_handle_status_busy(
195+
connection_info,
196+
frame_data,
197+
frame_length);
198+
case APPLICATION_REJECTED_REQUEST:
199+
return zwave_command_class_application_status_handle_status_reject(
200+
connection_info,
201+
frame_data,
202+
frame_length);
203+
default:
204+
return SL_STATUS_NOT_SUPPORTED;
205+
}
206+
}
207+
208+
///////////////////////////////////////////////////////////////////////////////
209+
// Attribute Store callback functions
210+
///////////////////////////////////////////////////////////////////////////////
211+
static void zwave_command_class_application_status_on_version_attribute_update(
212+
attribute_store_node_t updated_node, attribute_store_change_t change)
213+
{
214+
if (change == ATTRIBUTE_DELETED) {
215+
return;
216+
}
217+
218+
// Confirm that we have a version attribute update
219+
assert(ATTRIBUTE(VERSION) == attribute_store_get_node_type(updated_node));
220+
221+
attribute_store::attribute version_node(updated_node);
222+
// Do not create the attributes until we are sure of the version
223+
zwave_cc_version_t supporting_node_version = 0;
224+
225+
// Wait for the version
226+
if (!version_node.reported_exists()) {
227+
return;
228+
}
229+
supporting_node_version = version_node.reported<uint8_t>();
230+
231+
// Wait that the version becomes non-zero.
232+
if (supporting_node_version == 0) {
233+
return;
234+
}
235+
}
236+
237+
///////////////////////////////////////////////////////////////////////////////
238+
// Public interface functions
239+
///////////////////////////////////////////////////////////////////////////////
240+
sl_status_t zwave_command_class_application_status_init()
241+
{
242+
// Attribute store callbacks
243+
attribute_store_register_callback_by_type(
244+
zwave_command_class_application_status_on_version_attribute_update,
245+
ATTRIBUTE(VERSION));
246+
247+
// The support side of things: Register our handler to the Z-Wave CC framework:
248+
zwave_command_handler_t handler = {};
249+
handler.support_handler = NULL;
250+
handler.control_handler
251+
= &zwave_command_class_application_status_control_handler;
252+
// Not supported, so this does not really matter
253+
handler.minimal_scheme = ZWAVE_CONTROLLER_ENCAPSULATION_NETWORK_SCHEME;
254+
handler.manual_security_validation = false;
255+
handler.command_class = COMMAND_CLASS_APPLICATION_STATUS;
256+
handler.version = APPLICATION_STATUS_VERSION;
257+
handler.command_class_name = "Application Status";
258+
handler.comments = "";
259+
260+
zwave_command_handler_register_handler(handler);
261+
262+
return SL_STATUS_OK;
263+
}

0 commit comments

Comments
 (0)