4545// Log tag
4646constexpr char LOG_TAG[] = " zwave_command_class_switch_all" ;
4747
48+ enum class switch_all_mode_t : uint8_t {
49+ DEVICE_EXCLUDED = 0x00 ,
50+ DEVICE_ONLY_ON = 0x01 ,
51+ DEVICE_ONLY_OFF = 0x02 ,
52+ DEVICE_ON_OFF = 0xFF
53+ };
54+
55+ constexpr uint8_t SWITCH_ALL_ON_VALUE = 1 ;
56+ constexpr uint8_t SWITCH_ALL_OFF_VALUE = 0 ;
4857
4958namespace
5059{
@@ -68,39 +77,87 @@ zwave_cc_version_t get_current_switch_all_version(attribute_store_node_t node)
6877// /////////////////////////////////////////////////////////////////////////////
6978// Resolution functions
7079// /////////////////////////////////////////////////////////////////////////////
71- // static sl_status_t zwave_command_class_switch_all_get(
72- // attribute_store_node_t node, uint8_t *frame, uint16_t *frame_length)
73- // {
74- // return frame_generator.generate_no_args_frame(switch_all_GET,
75- // frame,
76- // frame_length);
77- // }
80+ static sl_status_t zwave_command_class_switch_all_set_on_off (
81+ attribute_store_node_t node, uint8_t *frame, uint16_t *frame_length)
82+ {
83+ try {
84+ attribute_store::attribute value_node (node);
85+ // Creating the frame
86+ if (value_node.type () != ATTRIBUTE (ON_OFF)) {
87+ return SL_STATUS_INVALID_TYPE;
88+ }
89+ auto mode = static_cast <switch_all_mode_t >(
90+ value_node.parent ().child_by_type (ATTRIBUTE (MODE)).reported <uint8_t >());
91+ bool send_command = false ;
92+ uint8_t zwave_command_id;
93+ auto on_off_desired = value_node.desired <uint8_t >();
7894
79- // static sl_status_t zwave_command_class_switch_all_set(
80- // attribute_store_node_t node, uint8_t *frame, uint16_t *frame_length)
81- // {
82- // try {
83- // attribute_store::attribute value_node(node);
84- // auto current_version = get_current_switch_all_version(node);
85- //
86- // // Compute expected size for set frame
87- // const uint8_t expected_frame_size = 12;
88- //
89- // // Creating the frame
90- // frame_generator.initialize_frame(switch_all_SET,
91- // frame,
92- // expected_frame_size);
93- // frame_generator.add_value(value_node, DESIRED_OR_REPORTED_ATTRIBUTE);
94- // frame_generator.validate_frame(frame_length);
95- // } catch (const std::exception &e) {
96- // sl_log_error(LOG_TAG,
97- // "Error while generating switch_all Set frame : %s",
98- // e.what());
99- // return SL_STATUS_FAIL;
100- // }
101- //
102- // return SL_STATUS_OK;
103- // }
95+ switch (on_off_desired) {
96+ case SWITCH_ALL_ON_VALUE:
97+ zwave_command_id = SWITCH_ALL_ON;
98+ send_command = (mode == switch_all_mode_t ::DEVICE_ONLY_ON
99+ || mode == switch_all_mode_t ::DEVICE_ON_OFF);
100+ break ;
101+ case SWITCH_ALL_OFF_VALUE:
102+ zwave_command_id = SWITCH_ALL_OFF;
103+ send_command = (mode == switch_all_mode_t ::DEVICE_ONLY_OFF
104+ || mode == switch_all_mode_t ::DEVICE_ON_OFF);
105+ break ;
106+ default :
107+ return SL_STATUS_INVALID_RANGE;
108+ }
109+ if (!send_command) {
110+ sl_log_debug (LOG_TAG,
111+ " Not sending command %d since mode is %d" ,
112+ zwave_command_id,
113+ mode);
114+ return SL_STATUS_OK;
115+ }
116+ return frame_generator.generate_no_args_frame (zwave_command_id,
117+ frame,
118+ frame_length);
119+ } catch (const std::exception &e) {
120+ sl_log_error (LOG_TAG,
121+ " Error while generating switch_all Set frame : %s" ,
122+ e.what ());
123+ return SL_STATUS_FAIL;
124+ }
125+
126+ return SL_STATUS_OK;
127+ }
128+
129+ static sl_status_t zwave_command_class_switch_all_get (
130+ attribute_store_node_t node, uint8_t *frame, uint16_t *frame_length)
131+ {
132+ if (attribute_store_get_node_type (node) == ATTRIBUTE (MODE)) {
133+ return frame_generator.generate_no_args_frame (SWITCH_ALL_GET,
134+ frame,
135+ frame_length);
136+ }
137+ return SL_STATUS_INVALID_TYPE;
138+ }
139+
140+ static sl_status_t zwave_command_class_switch_all_set (
141+ attribute_store_node_t node, uint8_t *frame, uint16_t *frame_length)
142+ {
143+ try {
144+ attribute_store::attribute value_node (node);
145+ // Creating the frame
146+ if (value_node.type () == ATTRIBUTE (MODE)) {
147+ frame_generator.initialize_frame (SWITCH_ALL_SET, frame, 3 );
148+ frame_generator.add_value (value_node, DESIRED_ATTRIBUTE);
149+ frame_generator.validate_frame (frame_length);
150+ }
151+ return SL_STATUS_INVALID_TYPE;
152+ } catch (const std::exception &e) {
153+ sl_log_error (LOG_TAG,
154+ " Error while generating switch_all Set frame : %s" ,
155+ e.what ());
156+ return SL_STATUS_FAIL;
157+ }
158+
159+ return SL_STATUS_OK;
160+ }
104161
105162// /////////////////////////////////////////////////////////////////////////////
106163// Frame parsing functions
@@ -187,13 +244,65 @@ static void zwave_command_class_switch_all_on_version_attribute_update(
187244
188245 // Now we know we have a switch_all supporting endpoint.
189246 attribute_store::attribute endpoint_node
190- = version_node.first_parent (ATTRIBUTE_ENDPOINT_ID);
247+ = version_node.first_parent (ATTRIBUTE_ENDPOINT_ID);
191248
192249 // Create the switch_all attributes
193250 endpoint_node.emplace_node (ATTRIBUTE (MODE));
194251
195252 endpoint_node.emplace_node (ATTRIBUTE (ON_OFF));
253+ }
254+
255+ sl_status_t
256+ zwave_command_class_check_ep_support (const dotdot_unid_t unid,
257+ const dotdot_endpoint_id_t endpoint)
258+ {
259+ attribute_store::attribute node
260+ = attribute_store_network_helper_get_node_id_node (unid);
261+ attribute_store::attribute ep
262+ = node.child_by_type_and_value <>(ATTRIBUTE_ENDPOINT_ID, endpoint);
263+
264+ if (ep.child_by_type (ATTRIBUTE (MODE)).is_valid ())
265+ return SL_STATUS_OK;
266+ return SL_STATUS_FAIL;
267+ }
196268
269+ sl_status_t zwave_command_class_unify_switch_all_write_attributes_callback (
270+ const dotdot_unid_t unid,
271+ const dotdot_endpoint_id_t endpoint,
272+ uic_mqtt_dotdot_callback_call_type_t call_type,
273+ uic_mqtt_dotdot_unify_switch_all_state_t value,
274+ uic_mqtt_dotdot_unify_switch_all_updated_state_t changed)
275+ {
276+ if (call_type == UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK) {
277+ return zwave_command_class_check_ep_support (unid, endpoint);
278+ }
279+
280+ attribute_store::attribute home
281+ = attribute_store_network_helper_get_home_id_node (unid);
282+
283+ if (changed.mode ) {
284+ attribute_store::attribute node
285+ = attribute_store_network_helper_get_node_id_node (unid);
286+ attribute_store::attribute ep
287+ = node.child_by_type_and_value <>(ATTRIBUTE_ENDPOINT_ID, endpoint);
288+ attribute_store::attribute mode
289+ = ep.emplace_node (DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_ALL_MODE);
290+
291+ sl_log_debug (LOG_TAG, " write callback set desired mode" );
292+ mode.set_desired <>(value.mode );
293+ }
294+ if (changed.on_off ) {
295+ for (auto node: home.children ()) {
296+ auto ep = node.child_by_type (ATTRIBUTE_ENDPOINT_ID);
297+ auto on_off
298+ = ep.emplace_node (DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_ALL_ON_OFF);
299+
300+ sl_log_debug (LOG_TAG, " write callback set desired on_off" );
301+ on_off.set_desired <>(value.on_off );
302+ }
303+ }
304+
305+ return SL_STATUS_OK;
197306}
198307
199308// /////////////////////////////////////////////////////////////////////////////
@@ -207,19 +316,22 @@ sl_status_t zwave_command_class_switch_all_init()
207316 ATTRIBUTE (VERSION));
208317
209318 // Attribute resolver rules
210- // attribute_resolver_register_rule(ATTRIBUTE(MODE),
211- // zwave_command_class_switch_all_set,
212- // zwave_command_class_switch_all_get);
213- // attribute_resolver_register_rule(ATTRIBUTE(ON_OFF),
214- // zwave_command_class_switch_all_set,
215- // nullptr);
319+ attribute_resolver_register_rule (ATTRIBUTE (MODE),
320+ zwave_command_class_switch_all_set,
321+ zwave_command_class_switch_all_get);
322+ attribute_resolver_register_rule (ATTRIBUTE (ON_OFF),
323+ zwave_command_class_switch_all_set_on_off,
324+ nullptr );
325+ // Attribute write callback
326+ uic_mqtt_dotdot_set_unify_switch_all_write_attributes_callback (
327+ zwave_command_class_unify_switch_all_write_attributes_callback);
216328
217329 // The support side of things: Register our handler to the Z-Wave CC framework:
218330 zwave_command_handler_t handler = {};
219331 handler.support_handler = NULL ;
220332 handler.control_handler = &zwave_command_class_switch_all_control_handler;
221333 // Not supported, so this does not really matter
222- handler.minimal_scheme = ZWAVE_CONTROLLER_ENCAPSULATION_NETWORK_SCHEME;
334+ handler.minimal_scheme = ZWAVE_CONTROLLER_ENCAPSULATION_NETWORK_SCHEME;
223335 handler.manual_security_validation = false ;
224336 handler.command_class = COMMAND_CLASS_SWITCH_ALL;
225337 handler.version = SWITCH_ALL_VERSION;
0 commit comments