diff --git a/.github/workflows/build-rootfs.yml b/.github/workflows/build-rootfs.yml
index a48806909..49a8f0c2e 100644
--- a/.github/workflows/build-rootfs.yml
+++ b/.github/workflows/build-rootfs.yml
@@ -52,7 +52,7 @@ jobs:
env:
token-defined: ${{ secrets.GH_UNIFY_ACCESS_TOKEN != '' }}
# yamllint disable-line rule:line-length
- if: ${{ env.token-defined == true && startsWith(github.ref, 'refs/tags/') }}
+ if: github.ref_type == 'tag' && env.token-defined
# yamllint disable-line rule:line-length
uses: softprops/action-gh-release@da05d552573ad5aba039eaac05058a918a7bf631 # v2.2.2
with:
diff --git a/applications/zpc/components/dotdot_mapper/rules/SwitchColor.uam b/applications/zpc/components/dotdot_mapper/rules/SwitchColor.uam
new file mode 100644
index 000000000..4da4c0a5f
--- /dev/null
+++ b/applications/zpc/components/dotdot_mapper/rules/SwitchColor.uam
@@ -0,0 +1,130 @@
+
+// Swtich Color Command Class
+def zwSTATE 0x3303
+def zwCOLOR_COMPONENT_ID 0x3304
+def zwVALUE 0x3305
+
+// We have 7 Color Component ID.
+def ZW_COLOR_ID_WARM_WHITE 0x00
+def ZW_COLOR_ID_COLD_WHITE 0x01
+def ZW_COLOR_ID_RED 0x02
+def ZW_COLOR_ID_GREEN 0x03
+def ZW_COLOR_ID_BLUE 0x04
+def ZW_COLOR_ID_AMBER 0x05
+def ZW_COLOR_ID_CYAN 0x06
+def ZW_COLOR_ID_PURPLE 0x07
+
+// ZCL Swich Color cluster attributes
+def zb_SWITCH_COLOR_WARM_WHITE 0xffa10000
+def zb_SWITCH_COLOR_COLD_WHITE 0xffa10001
+def zb_SWITCH_COLOR_RED 0xffa10002
+def zb_SWITCH_COLOR_GREEN 0xffa10003
+def zb_SWITCH_COLOR_BLUE 0xffa10004
+def zb_SWITCH_COLOR_AMBER 0xffa10005
+def zb_SWITCH_COLOR_CYAN 0xffa10006
+def zb_SWITCH_COLOR_PURPLE 0xffa10007
+
+
+scope 25 chain_reaction(0) {
+
+ d'zwSTATE.zwCOLOR_COMPONENT_ID[ZW_COLOR_ID_WARM_WHITE].zwVALUE =
+ if(e'zb_SWITCH_COLOR_WARM_WHITE) d'zb_SWITCH_COLOR_WARM_WHITE
+ undefined
+ d'zwSTATE.zwCOLOR_COMPONENT_ID[ZW_COLOR_ID_COLD_WHITE].zwVALUE =
+ if(e'zb_SWITCH_COLOR_COLD_WHITE) d'zb_SWITCH_COLOR_COLD_WHITE
+ undefined
+ d'zwSTATE.zwCOLOR_COMPONENT_ID[ZW_COLOR_ID_RED].zwVALUE =
+ if(e'zb_SWITCH_COLOR_RED) d'zb_SWITCH_COLOR_RED
+ undefined
+ d'zwSTATE.zwCOLOR_COMPONENT_ID[ZW_COLOR_ID_GREEN].zwVALUE =
+ if(e'zb_SWITCH_COLOR_GREEN) d'zb_SWITCH_COLOR_GREEN
+ undefined
+ d'zwSTATE.zwCOLOR_COMPONENT_ID[ZW_COLOR_ID_BLUE].zwVALUE =
+ if(e'zb_SWITCH_COLOR_BLUE) d'zb_SWITCH_COLOR_BLUE
+ undefined
+ d'zwSTATE.zwCOLOR_COMPONENT_ID[ZW_COLOR_ID_AMBER].zwVALUE =
+ if(e'zb_SWITCH_COLOR_AMBER) d'zb_SWITCH_COLOR_AMBER
+ undefined
+ d'zwSTATE.zwCOLOR_COMPONENT_ID[ZW_COLOR_ID_CYAN].zwVALUE =
+ if(e'zb_SWITCH_COLOR_CYAN) d'zb_SWITCH_COLOR_CYAN
+ undefined
+ d'zwSTATE.zwCOLOR_COMPONENT_ID[ZW_COLOR_ID_PURPLE].zwVALUE =
+ if(e'zb_SWITCH_COLOR_PURPLE) d'zb_SWITCH_COLOR_PURPLE
+ undefined
+
+ r'zwSTATE.zwCOLOR_COMPONENT_ID[ZW_COLOR_ID_WARM_WHITE].zwVALUE =
+ if(e'zb_SWITCH_COLOR_WARM_WHITE) r'zb_SWITCH_COLOR_WARM_WHITE
+ undefined
+ r'zwSTATE.zwCOLOR_COMPONENT_ID[ZW_COLOR_ID_COLD_WHITE].zwVALUE =
+ if(e'zb_SWITCH_COLOR_COLD_WHITE) r'zb_SWITCH_COLOR_COLD_WHITE
+ undefined
+ r'zwSTATE.zwCOLOR_COMPONENT_ID[ZW_COLOR_ID_RED].zwVALUE =
+ if(e'zb_SWITCH_COLOR_RED) r'zb_SWITCH_COLOR_RED
+ undefined
+ r'zwSTATE.zwCOLOR_COMPONENT_ID[ZW_COLOR_ID_GREEN].zwVALUE =
+ if(e'zb_SWITCH_COLOR_GREEN) r'zb_SWITCH_COLOR_GREEN
+ undefined
+ r'zwSTATE.zwCOLOR_COMPONENT_ID[ZW_COLOR_ID_BLUE].zwVALUE =
+ if(e'zb_SWITCH_COLOR_BLUE) r'zb_SWITCH_COLOR_BLUE
+ undefined
+ r'zwSTATE.zwCOLOR_COMPONENT_ID[ZW_COLOR_ID_AMBER].zwVALUE =
+ if(e'zb_SWITCH_COLOR_AMBER) r'zb_SWITCH_COLOR_AMBER
+ undefined
+ r'zwSTATE.zwCOLOR_COMPONENT_ID[ZW_COLOR_ID_CYAN].zwVALUE =
+ if(e'zb_SWITCH_COLOR_CYAN) r'zb_SWITCH_COLOR_CYAN
+ undefined
+ r'zwSTATE.zwCOLOR_COMPONENT_ID[ZW_COLOR_ID_PURPLE].zwVALUE =
+ if(e'zb_SWITCH_COLOR_PURPLE) r'zb_SWITCH_COLOR_PURPLE
+ undefined
+
+ r'zb_SWITCH_COLOR_WARM_WHITE =
+ if(e'zwSTATE.zwCOLOR_COMPONENT_ID[ZW_COLOR_ID_WARM_WHITE].zwVALUE) (r'zwSTATE.zwCOLOR_COMPONENT_ID[ZW_COLOR_ID_WARM_WHITE].zwVALUE)
+ undefined
+ r'zb_SWITCH_COLOR_COLD_WHITE =
+ if(e'zwSTATE.zwCOLOR_COMPONENT_ID[ZW_COLOR_ID_COLD_WHITE].zwVALUE) (r'zwSTATE.zwCOLOR_COMPONENT_ID[ZW_COLOR_ID_COLD_WHITE].zwVALUE)
+ undefined
+ r'zb_SWITCH_COLOR_RED =
+ if(e'zwSTATE.zwCOLOR_COMPONENT_ID[ZW_COLOR_ID_RED].zwVALUE) (r'zwSTATE.zwCOLOR_COMPONENT_ID[ZW_COLOR_ID_RED].zwVALUE)
+ undefined
+ r'zb_SWITCH_COLOR_GREEN =
+ if(e'zwSTATE.zwCOLOR_COMPONENT_ID[ZW_COLOR_ID_GREEN].zwVALUE) (r'zwSTATE.zwCOLOR_COMPONENT_ID[ZW_COLOR_ID_GREEN].zwVALUE)
+ undefined
+ r'zb_SWITCH_COLOR_BLUE =
+ if(e'zwSTATE.zwCOLOR_COMPONENT_ID[ZW_COLOR_ID_BLUE].zwVALUE) (r'zwSTATE.zwCOLOR_COMPONENT_ID[ZW_COLOR_ID_BLUE].zwVALUE)
+ undefined
+ r'zb_SWITCH_COLOR_AMBER =
+ if(e'zwSTATE.zwCOLOR_COMPONENT_ID[ZW_COLOR_ID_AMBER].zwVALUE) (r'zwSTATE.zwCOLOR_COMPONENT_ID[ZW_COLOR_ID_AMBER].zwVALUE)
+ undefined
+ r'zb_SWITCH_COLOR_CYAN =
+ if(e'zwSTATE.zwCOLOR_COMPONENT_ID[ZW_COLOR_ID_CYAN].zwVALUE) (r'zwSTATE.zwCOLOR_COMPONENT_ID[ZW_COLOR_ID_CYAN].zwVALUE)
+ undefined
+ r'zb_SWITCH_COLOR_PURPLE =
+ if(e'zwSTATE.zwCOLOR_COMPONENT_ID[ZW_COLOR_ID_PURPLE].zwVALUE) (r'zwSTATE.zwCOLOR_COMPONENT_ID[ZW_COLOR_ID_PURPLE].zwVALUE)
+ undefined
+
+ d'zb_SWITCH_COLOR_WARM_WHITE =
+ if(e'zwSTATE.zwCOLOR_COMPONENT_ID[ZW_COLOR_ID_WARM_WHITE].zwVALUE) (d'zwSTATE.zwCOLOR_COMPONENT_ID[ZW_COLOR_ID_WARM_WHITE].zwVALUE)
+ undefined
+ d'zb_SWITCH_COLOR_COLD_WHITE =
+ if(e'zwSTATE.zwCOLOR_COMPONENT_ID[ZW_COLOR_ID_COLD_WHITE].zwVALUE) (d'zwSTATE.zwCOLOR_COMPONENT_ID[ZW_COLOR_ID_COLD_WHITE].zwVALUE)
+ undefined
+ d'zb_SWITCH_COLOR_RED =
+ if(e'zwSTATE.zwCOLOR_COMPONENT_ID[ZW_COLOR_ID_RED].zwVALUE) (d'zwSTATE.zwCOLOR_COMPONENT_ID[ZW_COLOR_ID_RED].zwVALUE)
+ undefined
+ d'zb_SWITCH_COLOR_GREEN =
+ if(e'zwSTATE.zwCOLOR_COMPONENT_ID[ZW_COLOR_ID_GREEN].zwVALUE) (d'zwSTATE.zwCOLOR_COMPONENT_ID[ZW_COLOR_ID_GREEN].zwVALUE)
+ undefined
+ d'zb_SWITCH_COLOR_BLUE =
+ if(e'zwSTATE.zwCOLOR_COMPONENT_ID[ZW_COLOR_ID_BLUE].zwVALUE) (d'zwSTATE.zwCOLOR_COMPONENT_ID[ZW_COLOR_ID_BLUE].zwVALUE)
+ undefined
+ d'zb_SWITCH_COLOR_AMBER =
+ if(e'zwSTATE.zwCOLOR_COMPONENT_ID[ZW_COLOR_ID_AMBER].zwVALUE) (d'zwSTATE.zwCOLOR_COMPONENT_ID[ZW_COLOR_ID_AMBER].zwVALUE)
+ undefined
+ d'zb_SWITCH_COLOR_CYAN =
+ if(e'zwSTATE.zwCOLOR_COMPONENT_ID[ZW_COLOR_ID_CYAN].zwVALUE) (d'zwSTATE.zwCOLOR_COMPONENT_ID[ZW_COLOR_ID_CYAN].zwVALUE)
+ undefined
+ d'zb_SWITCH_COLOR_PURPLE =
+ if(e'zwSTATE.zwCOLOR_COMPONENT_ID[ZW_COLOR_ID_PURPLE].zwVALUE) (d'zwSTATE.zwCOLOR_COMPONENT_ID[ZW_COLOR_ID_PURPLE].zwVALUE)
+ undefined
+}
+
diff --git a/applications/zpc/components/zcl_cluster_servers/CMakeLists.txt b/applications/zpc/components/zcl_cluster_servers/CMakeLists.txt
index bef0569bc..2e4215344 100644
--- a/applications/zpc/components/zcl_cluster_servers/CMakeLists.txt
+++ b/applications/zpc/components/zcl_cluster_servers/CMakeLists.txt
@@ -18,6 +18,7 @@ add_library(
src/zcl_OTA_cluster_server.cpp
src/zcl_rf_telemetry_cluster_server.c
src/zcl_scenes_cluster_server.cpp
+ src/switch_color_cluster_server.cpp
)
target_include_directories(
diff --git a/applications/zpc/components/zcl_cluster_servers/src/switch_color_cluster_server.cpp b/applications/zpc/components/zcl_cluster_servers/src/switch_color_cluster_server.cpp
new file mode 100644
index 000000000..78c39b3c8
--- /dev/null
+++ b/applications/zpc/components/zcl_cluster_servers/src/switch_color_cluster_server.cpp
@@ -0,0 +1,322 @@
+
+/******************************************************************************
+ * # License
+ * Copyright 2021 Silicon Laboratories Inc. www.silabs.com
+ ******************************************************************************
+ * The licensor of this software is Silicon Laboratories Inc. Your use of this
+ * software is governed by the terms of Silicon Labs Master Software License
+ * Agreement (MSLA) available at
+ * www.silabs.com/about-us/legal/master-software-license-agreement. This
+ * software is distributed to you in Source Code format and is governed by the
+ * sections of the MSLA applicable to Source Code.
+ *
+ *****************************************************************************/
+// Includes from this component
+#include "switch_color_cluster_server.h"
+
+// Includes from Unify
+#include "sl_log.h"
+#include "sl_status.h"
+#include "attribute_store_helper.h"
+#include "attribute_store.h"
+#include "zpc_attribute_store_network_helper.h"
+#include "zwave_command_class_color_switch_types.h"
+
+#include "attribute_store_defined_attribute_types.h"
+#include "unify_dotdot_defined_attribute_types.h"
+#include "unify_dotdot_attribute_store.h"
+#include "unify_dotdot_attribute_store_node_state.h"
+#include "unify_dotdot_attribute_store_helpers.h"
+
+// Includes from auto-generated files
+#include "dotdot_mqtt.h"
+
+// Cpp include
+#include "attribute.hpp"
+
+// Setup Log ID
+#define LOG_TAG "switch_color_cluster_server"
+
+// Attribute macro, shortening those long defines for attribute types:
+#define ATTRIBUTE(type) ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_##type
+
+////////////////////////////////////////////////////////////////////////////////
+// Private helper functions
+////////////////////////////////////////////////////////////////////////////////
+attribute_store_node_t
+ get_state_node_by_unid_endpoint(dotdot_unid_t unid,
+ attribute_store_node_t endpoint)
+{
+ attribute_store::attribute endpoint_node
+ = attribute_store_network_helper_get_endpoint_node(unid, endpoint);
+ return endpoint_node.child_by_type(ATTRIBUTE(STATE));
+}
+
+attribute_store_node_t
+ get_duration_node_by_unid_endpoint(dotdot_unid_t unid,
+ attribute_store_node_t endpoint)
+{
+ attribute_store::attribute state_node
+ = get_state_node_by_unid_endpoint(unid, endpoint);
+ attribute_store::attribute duration_node
+ = state_node.child_by_type(ATTRIBUTE(DURATION));
+
+ return duration_node;
+}
+
+attribute_store_node_t
+ get_up_down_node_by_unid_endpoint(dotdot_unid_t unid,
+ attribute_store_node_t endpoint)
+{
+ attribute_store::attribute state_node
+ = get_state_node_by_unid_endpoint(unid, endpoint);
+ attribute_store::attribute up_down
+ = state_node.child_by_type(ATTRIBUTE(UP_DOWN));
+
+ return up_down;
+}
+
+attribute_store_node_t
+ get_ignore_start_level_node_by_unid_endpoint(dotdot_unid_t unid,
+ attribute_store_node_t endpoint)
+{
+ attribute_store::attribute state_node
+ = get_state_node_by_unid_endpoint(unid, endpoint);
+ attribute_store::attribute ignore_start_level_node
+ = state_node.child_by_type(ATTRIBUTE(IGNORE_START_LEVEL));
+
+ return ignore_start_level_node;
+}
+
+attribute_store_node_t
+ get_start_level_node_by_unid_endpoint(dotdot_unid_t unid,
+ attribute_store_node_t endpoint)
+{
+ attribute_store::attribute state_node
+ = get_state_node_by_unid_endpoint(unid, endpoint);
+ attribute_store::attribute start_level_node
+ = state_node.child_by_type(ATTRIBUTE(START_LEVEL));
+
+ return start_level_node;
+}
+
+attribute_store_node_t
+ get_start_change_node_by_unid_endpoint_color_component_id(
+ dotdot_unid_t unid,
+ attribute_store_node_t endpoint,
+ uint8_t color_component_id)
+{
+ attribute_store::attribute state_node
+ = get_state_node_by_unid_endpoint(unid, endpoint);
+ attribute_store::attribute color_component_id_node
+ = state_node.child_by_type_and_value(ATTRIBUTE(COLOR_COMPONENT_ID),
+ color_component_id);
+
+ attribute_store::attribute start_change_node
+ = color_component_id_node.child_by_type(ATTRIBUTE(START_CHANGE));
+
+ return start_change_node;
+}
+
+attribute_store_node_t get_stop_change_node_by_unid_endpoint_color_component_id(
+ dotdot_unid_t unid,
+ attribute_store_node_t endpoint,
+ uint8_t color_component_id)
+{
+ attribute_store::attribute state_node
+ = get_state_node_by_unid_endpoint(unid, endpoint);
+ attribute_store::attribute color_component_id_node
+ = state_node.child_by_type_and_value(ATTRIBUTE(COLOR_COMPONENT_ID),
+ color_component_id);
+
+ attribute_store::attribute stop_change_node
+ = color_component_id_node.child_by_type(ATTRIBUTE(STOP_CHANGE));
+
+ return stop_change_node;
+}
+
+sl_status_t unify_switch_color_cluster_set_color_command(
+ const dotdot_unid_t unid,
+ const dotdot_endpoint_id_t endpoint,
+ uic_mqtt_dotdot_callback_call_type_t callback_type,
+ uint8_t color_component_id,
+ uint8_t value,
+ uint32_t duration)
+{
+ try {
+ if (callback_type == UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK) {
+ return dotdot_is_any_unify_switch_color_attribute_supported(unid,
+ endpoint)
+ ? SL_STATUS_OK
+ : SL_STATUS_FAIL;
+ }
+
+ sl_log_debug(LOG_TAG,
+ "Updating ZCL desired values after Unify_SwitchColor::Set "
+ "command. color_component_id: %d, value :%d, duration : %d",
+ color_component_id,
+ value,
+ duration);
+
+ sl_status_t result = SL_STATUS_FAIL;
+
+ //Set value for attribute by color component id
+ switch (color_component_id) {
+ case WARM_WHITE:
+ result = dotdot_set_unify_switch_color_warm_white(unid,
+ endpoint,
+ DESIRED_ATTRIBUTE,
+ value);
+ break;
+ case COLD_WHITE:
+ result = dotdot_set_unify_switch_color_cold_white(unid,
+ endpoint,
+ DESIRED_ATTRIBUTE,
+ value);
+ break;
+ case RED:
+ result = dotdot_set_unify_switch_color_red(unid,
+ endpoint,
+ DESIRED_ATTRIBUTE,
+ value);
+ break;
+ case GREEN:
+ result = dotdot_set_unify_switch_color_green(unid,
+ endpoint,
+ DESIRED_ATTRIBUTE,
+ value);
+ break;
+ case BLUE:
+ result = dotdot_set_unify_switch_color_blue(unid,
+ endpoint,
+ DESIRED_ATTRIBUTE,
+ value);
+ break;
+ case AMBER:
+ result = dotdot_set_unify_switch_color_amber(unid,
+ endpoint,
+ DESIRED_ATTRIBUTE,
+ value);
+ break;
+ case CYAN:
+ result = dotdot_set_unify_switch_color_cyan(unid,
+ endpoint,
+ DESIRED_ATTRIBUTE,
+ value);
+ break;
+ case PURPLE:
+ result = dotdot_set_unify_switch_color_purple(unid,
+ endpoint,
+ DESIRED_ATTRIBUTE,
+ value);
+ break;
+ default:
+ sl_log_debug(
+ LOG_TAG,
+ "Invalid Colol Component ID Unify_SwitchColor::Set command");
+ break;
+ }
+
+ if (result != SL_STATUS_OK) {
+ sl_log_warning(LOG_TAG, "Can't set value for Unify Switch Color cluster");
+ return SL_STATUS_FAIL;
+ }
+ // Find duration node and set desired value
+ attribute_store::attribute duration_node
+ = get_duration_node_by_unid_endpoint(unid, endpoint);
+ if (duration_node.is_valid()) {
+ duration_node.set_desired(duration);
+ }
+ } catch (const std::exception &e) {
+ sl_log_error(
+ LOG_TAG,
+ "Error while handle unify_switch_color_cluster_set_color_command : %s",
+ e.what());
+ return SL_STATUS_FAIL;
+ }
+ return SL_STATUS_OK;
+}
+
+sl_status_t unify_switch_color_cluster_start_stop_change_command(
+ const dotdot_unid_t unid,
+ const dotdot_endpoint_id_t endpoint,
+ uic_mqtt_dotdot_callback_call_type_t callback_type,
+ bool start_stop,
+ bool up_down,
+ bool ignor_start_level,
+ uint8_t color_component_id,
+ uint8_t start_level,
+ uint32_t duration)
+{
+ try {
+ if (callback_type == UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK) {
+ return dotdot_is_any_unify_switch_color_attribute_supported(unid,
+ endpoint)
+ ? SL_STATUS_OK
+ : SL_STATUS_FAIL;
+ }
+
+ sl_log_debug(LOG_TAG,
+ "Updating ZCL desired values after Unify_SwitchColor::Start "
+ "Stop Change command");
+
+ // Find duration node and set desired value
+ attribute_store::attribute duration_node
+ = get_duration_node_by_unid_endpoint(unid, endpoint);
+ if (duration_node.is_valid()) {
+ duration_node.set_desired(duration);
+ }
+
+ // Find up down node and set desired value
+ attribute_store::attribute up_down_node
+ = get_up_down_node_by_unid_endpoint(unid, endpoint);
+ up_down_node.set_desired(up_down);
+
+ // Find irnore start level node and set desired value
+ attribute_store::attribute ignore_start_level_node
+ = get_ignore_start_level_node_by_unid_endpoint(unid, endpoint);
+ ignore_start_level_node.set_desired(ignor_start_level);
+
+ // Find start level node and set desired value
+ attribute_store::attribute start_level_node
+ = get_start_level_node_by_unid_endpoint(unid, endpoint);
+ start_level_node.set_desired(start_level);
+
+ if (start_stop) {
+ attribute_store::attribute start_change_node
+ = get_start_change_node_by_unid_endpoint_color_component_id(
+ unid,
+ endpoint,
+ color_component_id);
+ start_change_node.set_desired(start_stop);
+ } else {
+ attribute_store::attribute stop_change_node
+ = get_stop_change_node_by_unid_endpoint_color_component_id(
+ unid,
+ endpoint,
+ color_component_id);
+ stop_change_node.set_desired(!start_stop);
+ }
+ } catch (const std::exception &e) {
+ sl_log_error(LOG_TAG,
+ "Error while handle "
+ "unify_switch_color_cluster_start_stop_change_command : %s",
+ e.what());
+ return SL_STATUS_FAIL;
+ }
+ return SL_STATUS_OK;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Init and teardown functions
+///////////////////////////////////////////////////////////////////////////////
+sl_status_t switch_color_cluster_server_init()
+{
+ sl_log_debug(LOG_TAG, "SwitchColor cluster (ZWave) server initialization");
+
+ uic_mqtt_dotdot_unify_switch_color_set_color_callback_set(
+ &unify_switch_color_cluster_set_color_command);
+ uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback_set(
+ &unify_switch_color_cluster_start_stop_change_command);
+ return SL_STATUS_OK;
+}
diff --git a/applications/zpc/components/zcl_cluster_servers/src/switch_color_cluster_server.h b/applications/zpc/components/zcl_cluster_servers/src/switch_color_cluster_server.h
new file mode 100644
index 000000000..11e5cbe80
--- /dev/null
+++ b/applications/zpc/components/zcl_cluster_servers/src/switch_color_cluster_server.h
@@ -0,0 +1,46 @@
+/******************************************************************************
+ * # License
+ * Copyright 2024 Silicon Laboratories Inc. www.silabs.com
+ ******************************************************************************
+ * The licensor of this software is Silicon Laboratories Inc. Your use of this
+ * software is governed by the terms of Silicon Labs Master Software License
+ * Agreement (MSLA) available at
+ * www.silabs.com/about-us/legal/master-software-license-agreement. This
+ * software is distributed to you in Source Code format and is governed by the
+ * sections of the MSLA applicable to Source Code.
+ *
+ *****************************************************************************/
+
+/**
+ * @defgroup zpc_on_off_cluster_mapper ZPC Fan Control
+ * @ingroup dotdot_mapper
+ * @brief Maps OnOff Cluster incoming Commands to attribute modifications.
+ *
+ * @{
+ */
+
+#ifndef SWITCH_COLOR_CLUSTER_SERVER_H
+#define SWITCH_COLOR_CLUSTER_SERVER_H
+
+// Generic includes
+#include "sl_status.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Initialize the FanControl cluster server
+ *
+ * @returns true on success
+ * @returns false on failure
+ *
+ */
+sl_status_t switch_color_cluster_server_init(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //SWITCH_COLOR_CLUSTER_SERVER_H
+/** @} end switch_color_cluster_server */
diff --git a/applications/zpc/components/zcl_cluster_servers/src/zcl_cluster_servers.cpp b/applications/zpc/components/zcl_cluster_servers/src/zcl_cluster_servers.cpp
index 43bc4c385..52cfd1d80 100644
--- a/applications/zpc/components/zcl_cluster_servers/src/zcl_cluster_servers.cpp
+++ b/applications/zpc/components/zcl_cluster_servers/src/zcl_cluster_servers.cpp
@@ -20,6 +20,7 @@
#include "user_code_cluster_server.h"
#include "fan_control_cluster_server.h"
#include "user_credential_cluster_server.h"
+#include "switch_color_cluster_server.cpp"
//Includes from other components
#include "attribute_store.h"
@@ -44,6 +45,7 @@ sl_status_t zcl_cluster_servers_init()
init_status |= user_code_cluster_server_init();
init_status |= fan_control_cluster_server_init();
init_status |= user_credential_cluster_server_init();
+ init_status |= switch_color_cluster_server_init();
return init_status;
}
diff --git a/applications/zpc/components/zcl_cluster_servers/test/CMakeLists.txt b/applications/zpc/components/zcl_cluster_servers/test/CMakeLists.txt
index 6112d25e8..da646b28b 100644
--- a/applications/zpc/components/zcl_cluster_servers/test/CMakeLists.txt
+++ b/applications/zpc/components/zcl_cluster_servers/test/CMakeLists.txt
@@ -142,4 +142,19 @@ target_add_unittest(
uic_mqtt_stub
uic_attribute_store
unify)
-target_include_directories(user_credential_cluster_server_test PRIVATE ../src)
\ No newline at end of file
+target_include_directories(user_credential_cluster_server_test PRIVATE ../src)
+
+ # Switch Color Server test
+target_add_unittest(
+ zcl_cluster_servers
+ NAME
+ switch_color_cluster_server_test
+ SOURCES
+ switch_color_cluster_server_test.c
+ DEPENDS
+ zpc_attribute_store_test_helper
+ uic_dotdot_mqtt_mock
+ uic_mqtt_stub
+ uic_contiki_stub
+ unify)
+
diff --git a/applications/zpc/components/zcl_cluster_servers/test/switch_color_cluster_server_test.c b/applications/zpc/components/zcl_cluster_servers/test/switch_color_cluster_server_test.c
new file mode 100644
index 000000000..88a6a3c00
--- /dev/null
+++ b/applications/zpc/components/zcl_cluster_servers/test/switch_color_cluster_server_test.c
@@ -0,0 +1,470 @@
+/******************************************************************************
+ * # License
+ * Copyright 2022 Silicon Laboratories Inc. www.silabs.com
+ ******************************************************************************
+ * The licensor of this software is Silicon Laboratories Inc. Your use of this
+ * software is governed by the terms of Silicon Labs Master Software License
+ * Agreement (MSLA) available at
+ * www.silabs.com/about-us/legal/master-software-license-agreement. This
+ * software is distributed to you in Source Code format and is governed by the
+ * sections of the MSLA applicable to Source Code.
+ *
+ *****************************************************************************/
+#include "switch_color_cluster_server.h"
+#include "unify_dotdot_attribute_store.h"
+#include "unity.h"
+
+// Unify components
+#include "datastore.h"
+#include "attribute_store_fixt.h"
+#include "attribute_store_helper.h"
+#include "unify_dotdot_defined_attribute_types.h"
+#include "dotdot_mqtt_mock.h"
+
+// ZPC Components
+#include "zwave_unid.h"
+#include "zwave_command_class_thermostat_fan_types.h"
+
+// Test helpers
+#include "zpc_attribute_store_test_helper.h"
+#include "attribute_store_defined_attribute_types.h"
+
+#define ATTRIBUTE(type) ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_##type
+
+static uic_mqtt_dotdot_unify_switch_color_set_color_callback_t set_color_command = NULL;
+static uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback_t start_stop_change_command = NULL;
+
+void uic_mqtt_dotdot_unify_switch_color_set_color_callback_set_stub(
+ const uic_mqtt_dotdot_unify_switch_color_set_color_callback_t callback,
+ int cmock_num_calls)
+{
+ set_color_command = callback;
+}
+
+void uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback_set_stub(
+ const uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback_t callback,
+ int cmock_num_calls)
+{
+ start_stop_change_command = callback;
+}
+
+/// Setup the test suite (called once before all test_xxx functions are called)
+void suiteSetUp()
+{
+ datastore_init(":memory:");
+ attribute_store_init();
+}
+
+/// Teardown the test suite (called once after all test_xxx functions are called)
+int suiteTearDown(int num_failures)
+{
+ attribute_store_teardown();
+ datastore_teardown();
+ return num_failures;
+}
+
+/// Called before each and every test
+void setUp()
+{
+ zpc_attribute_store_test_helper_create_network();
+
+ set_color_command = NULL;
+ start_stop_change_command = NULL;
+
+ uic_mqtt_dotdot_unify_switch_color_set_color_callback_set_Stub(&uic_mqtt_dotdot_unify_switch_color_set_color_callback_set_stub);
+ uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback_set_Stub(&uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback_set_stub);
+
+ // Call init
+ TEST_ASSERT_EQUAL(SL_STATUS_OK, switch_color_cluster_server_init());
+}
+
+/// Called after each and every test
+void tearDown()
+{
+ attribute_store_delete_node(attribute_store_get_root());
+}
+
+void test_color_set_command_v1_happy_case()
+{
+ TEST_ASSERT_NOT_NULL(set_color_command);
+
+ const uint8_t color_component_id_tested = 3; //Green Color
+ const uint8_t value_tested = 0xAB;
+ const uint16_t duration_tested = 100;
+
+ // It should not work since we don't have the attribute yet
+ TEST_ASSERT_EQUAL(SL_STATUS_FAIL,
+ set_color_command(supporting_node_unid,
+ endpoint_id,
+ UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK,
+ color_component_id_tested,
+ value_tested,
+ duration_tested));
+
+ // Simulate that the nodes is created by an another function
+ attribute_store_node_t green_node = attribute_store_add_node(DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_GREEN,
+ endpoint_id_node);
+
+ // Test support
+ TEST_ASSERT_EQUAL(SL_STATUS_OK,
+ set_color_command(supporting_node_unid,
+ endpoint_id,
+ UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK,
+ color_component_id_tested,
+ value_tested,
+ duration_tested));
+
+ // Test callback
+ TEST_ASSERT_EQUAL(SL_STATUS_OK,
+ set_color_command(supporting_node_unid,
+ endpoint_id,
+ UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL,
+ color_component_id_tested,
+ value_tested,
+ duration_tested));
+
+ uint8_t color_value = 0;
+
+ TEST_ASSERT_EQUAL_MESSAGE(
+ SL_STATUS_OK,
+ attribute_store_get_desired(green_node, &color_value, sizeof(color_value)),
+ "Can't get color value");
+
+ // Test value
+ TEST_ASSERT_EQUAL(value_tested, color_value);
+}
+
+void test_color_set_command_v2_happy_case()
+{
+ TEST_ASSERT_NOT_NULL(set_color_command);
+
+ const uint8_t color_component_id_tested = 3; //Green Color
+ const uint8_t value_tested = 0xAB;
+ const uint16_t duration_tested = 100;
+
+ // It should not work since we don't have the attribute yet
+ TEST_ASSERT_EQUAL(SL_STATUS_FAIL,
+ set_color_command(supporting_node_unid,
+ endpoint_id,
+ UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK,
+ color_component_id_tested,
+ value_tested,
+ duration_tested));
+
+ // Simulate that the nodes is created by an another function
+ attribute_store_node_t green_node = attribute_store_add_node(DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_GREEN,
+ endpoint_id_node);
+
+ attribute_store_node_t state_node = attribute_store_add_node(ATTRIBUTE(STATE),
+ endpoint_id_node);
+
+ attribute_store_node_t duration_node = attribute_store_add_node(ATTRIBUTE(DURATION),
+ state_node);
+
+ // Test support
+ TEST_ASSERT_EQUAL(SL_STATUS_OK,
+ set_color_command(supporting_node_unid,
+ endpoint_id,
+ UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK,
+ color_component_id_tested,
+ value_tested,
+ duration_tested));
+
+ // Test callback
+ TEST_ASSERT_EQUAL(SL_STATUS_OK,
+ set_color_command(supporting_node_unid,
+ endpoint_id,
+ UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL,
+ color_component_id_tested,
+ value_tested,
+ duration_tested));
+
+ uint8_t color_value = 0;
+ uint32_t duration_value = 0;
+
+ TEST_ASSERT_EQUAL_MESSAGE(
+ SL_STATUS_OK,
+ attribute_store_get_desired(green_node, &color_value, sizeof(color_value)),
+ "Can't get color value");
+
+ TEST_ASSERT_EQUAL_MESSAGE(
+ SL_STATUS_OK,
+ attribute_store_get_desired(duration_node, &duration_value, sizeof(duration_value)),
+ "Can't get duration value");
+
+ // Test value
+ TEST_ASSERT_EQUAL(value_tested, color_value);
+ TEST_ASSERT_EQUAL(duration_tested, duration_value);
+}
+
+void test_color_set_command_v1_invalid_color_component_id()
+{
+ TEST_ASSERT_NOT_NULL(set_color_command);
+
+ const uint8_t color_component_id_tested = 10; //Green Color
+ const uint8_t value_tested = 0xAB;
+ const uint16_t duration_tested = 100;
+
+ // It should not work since we don't have the attribute yet
+ TEST_ASSERT_EQUAL(SL_STATUS_FAIL,
+ set_color_command(supporting_node_unid,
+ endpoint_id,
+ UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK,
+ color_component_id_tested,
+ value_tested,
+ duration_tested));
+
+ // Simulate that the nodes is created by an another function
+ attribute_store_add_node(DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_GREEN,
+ endpoint_id_node);
+
+ // Test support
+ TEST_ASSERT_EQUAL(SL_STATUS_OK,
+ set_color_command(supporting_node_unid,
+ endpoint_id,
+ UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK,
+ color_component_id_tested,
+ value_tested,
+ duration_tested));
+
+ // Test callback
+ TEST_ASSERT_EQUAL(SL_STATUS_FAIL,
+ set_color_command(supporting_node_unid,
+ endpoint_id,
+ UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL,
+ color_component_id_tested,
+ value_tested,
+ duration_tested));
+}
+
+void test_start_stop_change_command_start_change_happy_case()
+{
+ TEST_ASSERT_NOT_NULL(set_color_command);
+
+ const bool start_stop_tested = 1; //Start change
+ const uint8_t start_change_value_tested = 1;
+ const bool up_down_tested = 1;
+ const bool ignor_start_level_tested = 1;
+ const uint8_t color_component_id_tested = 3; //Green Color;
+ const uint8_t start_level_tested = 0xAB;
+ const uint32_t duration_tested = 100;
+
+ // It should not work since we don't have the attribute yet
+ TEST_ASSERT_EQUAL(SL_STATUS_FAIL,
+ start_stop_change_command(supporting_node_unid,
+ endpoint_id,
+ UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK,
+ start_stop_tested,
+ up_down_tested,
+ ignor_start_level_tested,
+ color_component_id_tested,
+ start_level_tested,
+ duration_tested));
+
+ // Simulate that the nodes is created by an another function
+ attribute_store_add_node(DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_GREEN,
+ endpoint_id_node);
+
+ attribute_store_node_t state_node = attribute_store_add_node(ATTRIBUTE(STATE),
+ endpoint_id_node);
+ attribute_store_node_t color_component_id_node = attribute_store_add_node(ATTRIBUTE(COLOR_COMPONENT_ID),
+ state_node);
+
+ attribute_store_set_node_attribute_value(color_component_id_node,
+ REPORTED_ATTRIBUTE,
+ (uint8_t*)&color_component_id_tested,
+ sizeof(color_component_id_tested));
+
+ attribute_store_node_t start_change_node = attribute_store_add_node(ATTRIBUTE(START_CHANGE),
+ color_component_id_node);
+
+ attribute_store_node_t duration_node = attribute_store_add_node(ATTRIBUTE(DURATION),
+ state_node);
+
+ attribute_store_node_t up_down_node = attribute_store_add_node(ATTRIBUTE(UP_DOWN),
+ state_node);
+
+ attribute_store_node_t ignore_start_level_node = attribute_store_add_node(ATTRIBUTE(IGNORE_START_LEVEL),
+ state_node);
+
+ attribute_store_node_t start_level_node = attribute_store_add_node(ATTRIBUTE(START_LEVEL),
+ state_node);
+
+ // Test support
+ TEST_ASSERT_EQUAL(SL_STATUS_OK,
+ start_stop_change_command(supporting_node_unid,
+ endpoint_id,
+ UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK,
+ start_stop_tested,
+ up_down_tested,
+ ignor_start_level_tested,
+ color_component_id_tested,
+ start_level_tested,
+ duration_tested));
+
+ // Test callback
+ TEST_ASSERT_EQUAL(SL_STATUS_OK,
+ start_stop_change_command(supporting_node_unid,
+ endpoint_id,
+ UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL,
+ start_stop_tested,
+ up_down_tested,
+ ignor_start_level_tested,
+ color_component_id_tested,
+ start_level_tested,
+ duration_tested));
+
+ uint8_t start_change_value = 0;
+ uint8_t up_down_value = 0;
+ uint8_t ignor_start_level_value = 0;
+ uint8_t start_level_value = 0;
+ uint32_t duration_value = 0;
+
+ TEST_ASSERT_EQUAL_MESSAGE(
+ SL_STATUS_OK,
+ attribute_store_get_desired(start_change_node, &start_change_value, sizeof(start_change_value)),
+ "Can't get start change value");
+
+ TEST_ASSERT_EQUAL_MESSAGE(
+ SL_STATUS_OK,
+ attribute_store_get_desired(up_down_node, &up_down_value, sizeof(up_down_value)),
+ "Can't get up down value");
+
+ TEST_ASSERT_EQUAL_MESSAGE(
+ SL_STATUS_OK,
+ attribute_store_get_desired(ignore_start_level_node, &ignor_start_level_value, sizeof(ignor_start_level_value)),
+ "Can't get ignore start level value");
+
+ TEST_ASSERT_EQUAL_MESSAGE(
+ SL_STATUS_OK,
+ attribute_store_get_desired(start_level_node, &start_level_value, sizeof(start_level_value)),
+ "Can't get tart level value");
+
+ TEST_ASSERT_EQUAL_MESSAGE(
+ SL_STATUS_OK,
+ attribute_store_get_desired(duration_node, &duration_value, sizeof(duration_value)),
+ "Can't get duration value");
+
+ // Test value
+ TEST_ASSERT_EQUAL(start_change_value_tested, start_change_value);
+ TEST_ASSERT_EQUAL(up_down_tested, up_down_value);
+ TEST_ASSERT_EQUAL(ignor_start_level_tested, ignor_start_level_value);
+ TEST_ASSERT_EQUAL(start_level_tested, start_level_value);
+ TEST_ASSERT_EQUAL(duration_tested, duration_value);
+}
+
+void test_start_stop_change_command_stop_change_happy_case()
+{
+ TEST_ASSERT_NOT_NULL(set_color_command);
+
+ const bool start_stop_tested = 0; //Stop change
+ const uint8_t stop_change_value_tested = 1;
+ const bool up_down_tested = 1;
+ const bool ignor_start_level_tested = 1;
+ const uint8_t color_component_id_tested = 3; //Green Color;
+ const uint8_t start_level_tested = 0xAB;
+ const uint32_t duration_tested = 100;
+
+ // It should not work since we don't have the attribute yet
+ TEST_ASSERT_EQUAL(SL_STATUS_FAIL,
+ start_stop_change_command(supporting_node_unid,
+ endpoint_id,
+ UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK,
+ start_stop_tested,
+ up_down_tested,
+ ignor_start_level_tested,
+ color_component_id_tested,
+ start_level_tested,
+ duration_tested));
+
+ // Simulate that the nodes is created by an another function
+ attribute_store_add_node(DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_GREEN,
+ endpoint_id_node);
+
+ attribute_store_node_t state_node = attribute_store_add_node(ATTRIBUTE(STATE),
+ endpoint_id_node);
+ attribute_store_node_t color_component_id_node = attribute_store_add_node(ATTRIBUTE(COLOR_COMPONENT_ID),
+ state_node);
+
+ attribute_store_set_node_attribute_value(color_component_id_node,
+ REPORTED_ATTRIBUTE,
+ (uint8_t*)&color_component_id_tested,
+ sizeof(color_component_id_tested));
+
+ attribute_store_node_t stop_change_node = attribute_store_add_node(ATTRIBUTE(STOP_CHANGE),
+ color_component_id_node);
+
+ attribute_store_node_t duration_node = attribute_store_add_node(ATTRIBUTE(DURATION),
+ state_node);
+
+ attribute_store_node_t up_down_node = attribute_store_add_node(ATTRIBUTE(UP_DOWN),
+ state_node);
+
+ attribute_store_node_t ignore_start_level_node = attribute_store_add_node(ATTRIBUTE(IGNORE_START_LEVEL),
+ state_node);
+
+ attribute_store_node_t start_level_node = attribute_store_add_node(ATTRIBUTE(START_LEVEL),
+ state_node);
+
+ // Test support
+ TEST_ASSERT_EQUAL(SL_STATUS_OK,
+ start_stop_change_command(supporting_node_unid,
+ endpoint_id,
+ UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK,
+ start_stop_tested,
+ up_down_tested,
+ ignor_start_level_tested,
+ color_component_id_tested,
+ start_level_tested,
+ duration_tested));
+
+ // Test callback
+ TEST_ASSERT_EQUAL(SL_STATUS_OK,
+ start_stop_change_command(supporting_node_unid,
+ endpoint_id,
+ UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL,
+ start_stop_tested,
+ up_down_tested,
+ ignor_start_level_tested,
+ color_component_id_tested,
+ start_level_tested,
+ duration_tested));
+
+ uint8_t stop_change_value = 0;
+ uint8_t up_down_value = 0;
+ uint8_t ignor_start_level_value = 0;
+ uint8_t start_level_value = 0;
+ uint32_t duration_value = 0;
+
+ TEST_ASSERT_EQUAL_MESSAGE(
+ SL_STATUS_OK,
+ attribute_store_get_desired(stop_change_node, &stop_change_value, sizeof(stop_change_value)),
+ "Can't get stop change value");
+
+ TEST_ASSERT_EQUAL_MESSAGE(
+ SL_STATUS_OK,
+ attribute_store_get_desired(up_down_node, &up_down_value, sizeof(up_down_value)),
+ "Can't get up down value");
+
+ TEST_ASSERT_EQUAL_MESSAGE(
+ SL_STATUS_OK,
+ attribute_store_get_desired(ignore_start_level_node, &ignor_start_level_value, sizeof(ignor_start_level_value)),
+ "Can't get ignore start level value");
+
+ TEST_ASSERT_EQUAL_MESSAGE(
+ SL_STATUS_OK,
+ attribute_store_get_desired(start_level_node, &start_level_value, sizeof(start_level_value)),
+ "Can't get tart level value");
+
+ TEST_ASSERT_EQUAL_MESSAGE(
+ SL_STATUS_OK,
+ attribute_store_get_desired(duration_node, &duration_value, sizeof(duration_value)),
+ "Can't get duration value");
+
+ // Test value
+ TEST_ASSERT_EQUAL(stop_change_value_tested, stop_change_value);
+ TEST_ASSERT_EQUAL(up_down_tested, up_down_value);
+ TEST_ASSERT_EQUAL(ignor_start_level_tested, ignor_start_level_value);
+ TEST_ASSERT_EQUAL(start_level_tested, start_level_value);
+ TEST_ASSERT_EQUAL(duration_tested, duration_value);
+}
\ No newline at end of file
diff --git a/applications/zpc/components/zpc_attribute_store/include/attribute_store_defined_attribute_types.h b/applications/zpc/components/zpc_attribute_store/include/attribute_store_defined_attribute_types.h
index 3b084d146..28107fbd2 100644
--- a/applications/zpc/components/zpc_attribute_store/include/attribute_store_defined_attribute_types.h
+++ b/applications/zpc/components/zpc_attribute_store/include/attribute_store_defined_attribute_types.h
@@ -416,6 +416,31 @@ DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_VALUE,
DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_DURATION,
((COMMAND_CLASS_SWITCH_COLOR << 8) | 0x6))
+///< This represents a Up/Down value in Color Switch Start Level Change Command
+/// Located under ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_STATE
+DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_UP_DOWN,
+ ((COMMAND_CLASS_SWITCH_COLOR << 8) | 0x7))
+
+///< This represents a Ignore Start Level in Color Switch Start Level Change Command
+/// Located under ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_STATE
+DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_IGNORE_START_LEVEL,
+ ((COMMAND_CLASS_SWITCH_COLOR << 8) | 0x8))
+
+///< This represents a Start Level in Color Switch Start Level Change Command
+/// Located under ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_STATE
+DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_START_LEVEL,
+ ((COMMAND_CLASS_SWITCH_COLOR << 8) | 0x9))
+
+///< This represents a Color Switch Start Level Change
+/// Located under ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_STATE
+DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_START_CHANGE,
+ ((COMMAND_CLASS_SWITCH_COLOR << 8) | 0x0A))
+
+///< This represents a Color Switch Stop Level Change
+/// Located under ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_STATE
+DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_STOP_CHANGE,
+ ((COMMAND_CLASS_SWITCH_COLOR << 8) | 0x0B))
+
///////////////////////////////////
// Multilevel Sensor Command Class
DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_SENSOR_MULTILEVEL_VERSION,
diff --git a/applications/zpc/components/zpc_attribute_store/include/command_class_types/zwave_command_class_color_switch_types.h b/applications/zpc/components/zpc_attribute_store/include/command_class_types/zwave_command_class_color_switch_types.h
index fc85882ae..cdc4294a9 100644
--- a/applications/zpc/components/zpc_attribute_store/include/command_class_types/zwave_command_class_color_switch_types.h
+++ b/applications/zpc/components/zpc_attribute_store/include/command_class_types/zwave_command_class_color_switch_types.h
@@ -89,5 +89,17 @@ typedef uint8_t color_component_id_t;
typedef uint32_t color_component_id_value_t;
typedef uint32_t color_component_id_duration_t;
+///> Color Component ID
+typedef enum {
+ WARM_WHITE = 0,
+ COLD_WHITE = 1,
+ RED = 2,
+ GREEN = 3,
+ BLUE = 4,
+ AMBER = 5,
+ CYAN = 6,
+ PURPLE = 7
+} color_component_id_enum;
+
#endif //ZWAVE_COMMAND_CLASS_COLOR_SWITCH_TYPES_H
/** @} end zwave_command_class_color_switch_types */
diff --git a/applications/zpc/components/zpc_attribute_store/src/zpc_attribute_store_type_registration.cpp b/applications/zpc/components/zpc_attribute_store/src/zpc_attribute_store_type_registration.cpp
index 44bcf8f6f..ee8c49700 100644
--- a/applications/zpc/components/zpc_attribute_store/src/zpc_attribute_store_type_registration.cpp
+++ b/applications/zpc/components/zpc_attribute_store/src/zpc_attribute_store_type_registration.cpp
@@ -167,7 +167,12 @@ static const std::vector attribute_schema = {
{ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_STATE, "Color Switch State", ATTRIBUTE_ENDPOINT_ID, ENUM_STORAGE_TYPE},
{ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_COLOR_COMPONENT_ID, "Component ID", ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_STATE, U8_STORAGE_TYPE},
{ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_VALUE, "Value", ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_COLOR_COMPONENT_ID, U32_STORAGE_TYPE},
+ {ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_START_CHANGE, "Color Start Level Change", ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_COLOR_COMPONENT_ID, U8_STORAGE_TYPE},
+ {ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_STOP_CHANGE, "Color Stop Level Change", ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_COLOR_COMPONENT_ID, U8_STORAGE_TYPE},
{ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_DURATION, "Duration", ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_STATE, U32_STORAGE_TYPE},
+ {ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_UP_DOWN, "Up Down", ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_STATE, U8_STORAGE_TYPE},
+ {ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_IGNORE_START_LEVEL, "Ignore Start Level", ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_STATE, U8_STORAGE_TYPE},
+ {ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_START_LEVEL, "Start Level", ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_STATE, U8_STORAGE_TYPE},
/////////////////////////////////////////////////////////////////////
// Configuration Command Class attributes
/////////////////////////////////////////////////////////////////////
diff --git a/applications/zpc/components/zpc_rust/src/rust_command_handlers/zwave_command_classes/mod.rs b/applications/zpc/components/zpc_rust/src/rust_command_handlers/zwave_command_classes/mod.rs
index d7adceb9d..34673eb48 100644
--- a/applications/zpc/components/zpc_rust/src/rust_command_handlers/zwave_command_classes/mod.rs
+++ b/applications/zpc/components/zpc_rust/src/rust_command_handlers/zwave_command_classes/mod.rs
@@ -12,7 +12,5 @@
///////////////////////////////////////////////////////////////////////////////
pub mod zwave_command_class_firmware_update;
-mod zwave_command_class_switch_color;
pub use zwave_command_class_firmware_update::*;
-pub use zwave_command_class_switch_color::*;
diff --git a/applications/zpc/components/zpc_rust/src/rust_command_handlers/zwave_command_classes/zwave_command_class_switch_color.rs b/applications/zpc/components/zpc_rust/src/rust_command_handlers/zwave_command_classes/zwave_command_class_switch_color.rs
deleted file mode 100644
index 278455d53..000000000
--- a/applications/zpc/components/zpc_rust/src/rust_command_handlers/zwave_command_classes/zwave_command_class_switch_color.rs
+++ /dev/null
@@ -1,530 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-// # License
-// Copyright 2021 Silicon Laboratories Inc. www.silabs.com
-///////////////////////////////////////////////////////////////////////////////
-// The licensor of this software is Silicon Laboratories Inc. Your use of this
-// software is governed by the terms of Silicon Labs Master Software License
-// Agreement (MSLA) available at
-// www.silabs.com/about-us/legal/master-software-license-agreement. This
-// software is distributed to you in Source Code format and is governed by the
-// sections of the MSLA applicable to Source Code.
-//
-///////////////////////////////////////////////////////////////////////////////
-#![allow(
- missing_docs,
- dead_code,
- non_snake_case,
- non_camel_case_types,
- non_upper_case_globals
-)]
-use crate::rust_command_handlers::{
- zwave_command_class_definitions::{ConnectionInfoTrait, ZwaveControllerEncapsulationScheme},
- zwave_command_class_interface::{
- CommandClassConfigurationTrait, FrameControlSupportTrait, ZwaveVersionChangedTrait,
- },
-};
-use crate::zwave_command_classes_sys::{
- is_zwave_command_class_filtered_for_root_device, sl_status_t,
-};
-use rust_command_class_frame_types::command_class_switch_color::*;
-use unify_attribute_resolver_sys::{
- attribute_resolver_register_rule, attribute_resolver_restart_set_resolution,
- is_node_pending_set_resolution,
-};
-use unify_log_sys::*;
-use unify_middleware::{
- attribute_callback_by_type_and_state, attribute_store_or_return_with, Attribute,
- AttributeEvent, AttributeEventType, AttributeStoreError, AttributeTrait, AttributeValueState,
-};
-use unify_proc_macro::{as_extern_c, generate_resolver_callback};
-use unify_sl_status_sys::{map_to_sl_status_fail, SL_STATUS_FAIL, SL_STATUS_OK};
-use zwave_rust_proc_macros::zwave_command_class;
-
-/// Attribute definitions
-const ATTRIBUTE_ENDPOINT_ID: u32 = 0x4;
-const ATTRIBUTE_VERSION: u32 = 0x3301;
-const ATTRIBUTE_SUPPORTED_COLOR_COMPONENT_MASK: u32 = 0x3302;
-const ATTRIBUTE_STATE: u32 = 0x3303;
-const ATTRIBUTE_COLOR_COMPONENT_ID: u32 = 0x3304;
-const ATTRIBUTE_COLOR_VALUE: u32 = 0x3305;
-const ATTRIBUTE_COLOR_DURATION: u32 = 0x3306;
-
-// Attribute types, copy from zwave_command_class_color_switch_types.h
-type color_component_bitmask_t = u16;
-type color_component_id_t = u8;
-type color_component_id_value_t = u32;
-type color_component_id_duration_t = u32;
-
-type command_status_values_t = u32;
-const FINAL_STATE: command_status_values_t = 0;
-const NEEDS_ONE_COMMAND: command_status_values_t = 1;
-const NEEDS_MULTIPLE_COMMANDS: command_status_values_t = 2;
-
-declare_app_name!("zwave_command_class_switch_color_control");
-
-fn on_value_update(event: &AttributeEvent) {
- if event.event_type != AttributeEventType::ATTRIBUTE_UPDATED {
- return;
- }
- // Verify if any of the values has a desired/reported mismatch under the state.
- let mut command_needed = false;
-
- let state_node = match event.attribute.get_first_parent_with_type(ATTRIBUTE_STATE) {
- Some(state) => state,
- None => {
- log_warning!("Cannot find state parent attribute for {}", event.attribute);
- return;
- }
- };
-
- let component_nodes = state_node.get_children_by_type(ATTRIBUTE_COLOR_COMPONENT_ID);
-
- // Verify if we have any mismatch
- for component_node in &component_nodes {
- let value_node = component_node.get_child_by_type(ATTRIBUTE_COLOR_VALUE);
- if true == value_node.is_desired_set() && false == value_node.is_value_matched() {
- command_needed = true;
- break;
- }
- }
-
- if command_needed == true {
- let _ = state_node
- .set_reported(Some(FINAL_STATE))
- .and(state_node.set_desired(Some(NEEDS_ONE_COMMAND)));
- if is_node_pending_set_resolution(state_node.handle) {
- attribute_resolver_restart_set_resolution(state_node.handle);
- }
- } else {
- let _ = state_node
- .set_reported(Some(FINAL_STATE))
- .and(state_node.set_desired(Some(FINAL_STATE)));
- }
-}
-
-///////////////////////// Command class registration ////////////////////
-#[zwave_command_class]
-impl CommandClassConfigurationTrait for CommandClassSwitchColorFrame {
- const COMMAND_CLASS_NAME: &'static str = "Color Switch";
- const MINIMAL_SCHEME: ZwaveControllerEncapsulationScheme =
- ZwaveControllerEncapsulationScheme::ZwaveControllerEncapsulationNetworkScheme;
- const COMMENTS: &'static str = "Partial Control:
1. Durations are ignored
2. No support for Start/Stop Level Change
3. No support for other Color Component IDs than 0,1,2,3,4";
- const MANUAL_SECURITY_VALIDATION: bool = false;
- const INCLUDE_SUPPORT: bool = false;
- const INCLUDE_CONTROL: bool = true;
-
- fn on_init() -> sl_status_t {
- attribute_resolver_register_rule(
- ATTRIBUTE_SUPPORTED_COLOR_COMPONENT_MASK,
- None,
- as_extern_c!(switch_color_supported_get),
- );
-
- attribute_resolver_register_rule(ATTRIBUTE_STATE, as_extern_c!(switch_color_set), None);
-
- attribute_resolver_register_rule(
- ATTRIBUTE_COLOR_VALUE,
- None,
- as_extern_c!(switch_color_get),
- );
-
- attribute_callback_by_type_and_state(
- ATTRIBUTE_COLOR_VALUE,
- AttributeValueState::DESIRED_ATTRIBUTE,
- on_value_update,
- );
- attribute_callback_by_type_and_state(
- ATTRIBUTE_COLOR_DURATION,
- AttributeValueState::DESIRED_ATTRIBUTE,
- on_value_update,
- );
-
- SL_STATUS_OK
- }
-}
-
-///////////////////////////// Version Update ///////////////////////////////
-#[zwave_command_class]
-impl ZwaveVersionChangedTrait for CommandClassSwitchColorFrame {
- const ATTRIBUTE_STORE_TYPE: u32 = ATTRIBUTE_VERSION;
-
- fn on_attribute_version(ep: Attribute, version: u8) {
- if unsafe {
- is_zwave_command_class_filtered_for_root_device(COMMAND_CLASS_SWITCH_COLOR, ep.handle)
- } == true
- {
- return;
- }
-
- // Use any color component id at token for starting the supported get
- if version > 0 {
- if !ep
- .get_child_by_type(ATTRIBUTE_SUPPORTED_COLOR_COMPONENT_MASK)
- .valid()
- {
- let _ = ep.add::(
- ATTRIBUTE_SUPPORTED_COLOR_COMPONENT_MASK,
- None,
- None,
- );
- }
- }
- }
-}
-
-/////////////////////////// Command Handlers ///////////////////////////
-impl FrameControlSupportTrait for SwitchColorSupportedReportFrame {
- fn on_control(&self, info: &dyn ConnectionInfoTrait) -> Result<(), sl_status_t> {
- let ep = info.get_endpoint();
-
- // Save the bitmask of supported component IDs in the attribute store
- if let Err(e) = ep
- .get_child_by_type(ATTRIBUTE_SUPPORTED_COLOR_COMPONENT_MASK)
- .set_reported::(Some(self.color_component_mask))
- {
- log_warning!("could not set bitmask for color component {}", e);
- }
-
- let mut state_node = ep.get_child_by_type(ATTRIBUTE_STATE);
- if !state_node.valid() {
- state_node = ep
- .add::(ATTRIBUTE_STATE, None, None)
- .map_err(map_to_sl_status_fail)?;
- }
-
- // Create the duration under the State node, if does not exist
- if !state_node
- .get_child_by_type(ATTRIBUTE_COLOR_DURATION)
- .valid()
- {
- state_node
- .add::(ATTRIBUTE_COLOR_DURATION, None, None)
- .map_err(map_to_sl_status_fail)?;
- }
-
- // The bits bitmask is byte reversed order with LSB bits in the first byte
- let mask = (self.color_component_mask >> 8) | (self.color_component_mask & 0xff);
- for i in 0..15 {
- if (mask & (1 << i)) != 0 {
- // Create all the attributes under the state (component IDs and their value/duration)
- let component = state_node
- .emplace::(ATTRIBUTE_COLOR_COMPONENT_ID, Some(i), None)
- .map_err(map_to_sl_status_fail)?;
-
- // Create the value under the component, if does not exist
- if !component.get_child_by_type(ATTRIBUTE_COLOR_VALUE).valid() {
- component
- .add::(ATTRIBUTE_COLOR_VALUE, None, None)
- .map_err(map_to_sl_status_fail)?;
- }
- }
- }
- Ok(())
- }
-}
-
-impl FrameControlSupportTrait for SwitchColorReportFrame {
- fn on_control(&self, info: &dyn ConnectionInfoTrait) -> Result<(), sl_status_t> {
- let ep = info.get_endpoint();
-
- let state_node = ep.get_child_by_type(ATTRIBUTE_STATE);
- let component_node = state_node.get_child_by_type_and_value(
- ATTRIBUTE_COLOR_COMPONENT_ID,
- &Some(self.color_component_id),
- );
- let value_node = component_node.get_child_by_type(ATTRIBUTE_COLOR_VALUE);
- let duration_node = state_node.get_child_by_type(ATTRIBUTE_COLOR_DURATION);
-
- if !value_node.valid() || !duration_node.valid() {
- return Err(SL_STATUS_FAIL);
- }
-
- value_node.stop_transition();
-
- // UIC-1927 : change value_node.set_desired(current_value) to
- // .set_desired::(Some(self.target_value.into()))
- // This will trigger the Rust callbacks to invoke on_value_update() later on.
- // which provokes that we try to set this desired value again.
-
- // Set all the values in the attribute store
- value_node
- .set_desired::(Some(self.current_value.into()))
- .and(
- value_node
- .set_reported::(Some(self.current_value.into())),
- )
- .and(duration_node.set_desired::(None))
- .and(duration_node.set_reported(Some(self.duration as color_component_id_duration_t)))
- .map_err(map_to_sl_status_fail)?;
-
- // FIXME: UIC-1926 Here when we get the real duration, we want to
- // do like in Multilevel switch:
- // clock_time_t duration_time = zwave_duration_to_time(self.duration);
- // value_node.start_transition(duration_time);
-
- // FIXME: UIC-1927 See above. this is normally how we prevent to resolve
- // after updating the desired value ourselves.
- // Make sure not to resolve Color Switch values if the node tells us its desired state
- let _ = state_node
- .set_reported(Some(FINAL_STATE))
- .and(state_node.set_desired(Some(FINAL_STATE)));
-
- log_debug!(
- "NodeID {}:{} reported Color ID {} set to {}",
- unsafe { info.get_remote().__bindgen_anon_1.node_id },
- info.get_remote().endpoint_id,
- self.color_component_id,
- self.current_value
- );
-
- Ok(())
- }
-}
-
-/////////////////////// Command Generators //////////////////////////
-
-#[generate_resolver_callback]
-fn switch_color_get(value_node: Attribute) -> Result<(sl_status_t, Vec), AttributeStoreError> {
- let component_node = value_node
- .get_first_parent_with_type(ATTRIBUTE_COLOR_COMPONENT_ID)
- .ok_or(AttributeStoreError::InvalidType)?;
- let get_frame = SwitchColorGetFrame {
- color_component_id: component_node.get_reported::()?,
- };
- Ok((SL_STATUS_OK, get_frame.into()))
-}
-
-#[generate_resolver_callback]
-fn switch_color_set(state_node: Attribute) -> Result<(sl_status_t, Vec), AttributeStoreError> {
- let mut colors = Vec::new();
- // FIXME: UIC-1926 Default should be 0xFF if we have no desired value in the
- // attribute store. I really can't use SwitchColorSetDurationEnum::Default, which is 0
- // the "real" default value is 0xFF
- let mut _duration: color_component_id_duration_t = 0xFF as color_component_id_duration_t;
- // Check if this component has a desired duration
- match state_node
- .get_child_by_type(ATTRIBUTE_COLOR_DURATION)
- .get_desired::()
- {
- Ok(desired_duration) => _duration = desired_duration,
- Err(_) => (),
- }
- // Gather data tor all color components
- for component in state_node.get_children_by_type(ATTRIBUTE_COLOR_COMPONENT_ID) {
- let value_attribute = component.get_child_by_type(ATTRIBUTE_COLOR_VALUE);
- let value: u32 = value_attribute.get_desired_or_reported::()?;
- let color_value = SwitchColorSetVg1Vg {
- color_component_id: component.get_reported::()?,
- value: value as u8,
- };
- colors.push(color_value);
- }
-
- let set_frame = SwitchColorSetFrame {
- properties1: SwitchColorSetProperties1Bits {
- color_component_count: 0, //The component count is updated by the frame generator
- reserved: 0,
- },
- vg1: colors,
- duration: _duration as u8,
- };
-
- Ok((SL_STATUS_OK, set_frame.into()))
-}
-
-#[generate_resolver_callback]
-fn switch_color_supported_get(_: Attribute) -> Result<(sl_status_t, Vec), AttributeStoreError> {
- Ok((SL_STATUS_OK, (SwitchColorSupportedGetFrame {}).into()))
-}
-
-//////////////////////////////////////// Tests ///////////////////////////////////
-#[cfg(test)]
-mod test {
- use super::*;
- use crate::zwave_command_class_definitions::MockConnectionInfoTrait;
- use crate::zwave_controller_sys::zwave_controller_endpoint_t;
- use serial_test::serial;
- use std::ffi::CString;
- use std::sync::Once;
- use unify_middleware::AttributeStore;
- use unify_middleware::AttributeStoreTrait;
-
- extern "C" {
- pub fn datastore_init(database: *const std::os::raw::c_char) -> u32;
- pub fn zpc_attribute_store_test_helper_create_network();
- pub fn attribute_store_log();
- }
-
- static INIT: Once = Once::new();
- pub fn initialize() {
- INIT.call_once(|| unsafe {
- let database_name = CString::new(":memory:").unwrap();
- assert_eq!(0, datastore_init(database_name.as_ptr()));
- });
- AttributeStore::new().unwrap().root().delete().unwrap();
- }
-
- #[test]
- #[serial]
- fn test_on_interview() {
- use std::convert::TryInto;
-
- initialize();
- let ep = AttributeStore::new().unwrap().root();
-
- //Check that we create the first color component id
- CommandClassSwitchColorFrame::on_attribute_version(ep, 2);
-
- // Check that we can handle a SUPPORTED report
- let z = [0x33u8, 0x02u8, 0x03u8, 0x00u8];
- let f: CommandClassSwitchColorFrame = (z[..]).try_into().unwrap();
-
- let mut mock_connection_info = MockConnectionInfoTrait::new();
- mock_connection_info
- .expect_get_endpoint()
- .times(1)
- .return_const(ep);
-
- let status = f.on_control(&mock_connection_info);
- assert_eq!(Ok(()), status);
-
- //Expect that we get two color components, 0 and 1
- let state = ep.get_child_by_type(ATTRIBUTE_STATE);
- let components = state.get_children_by_type(ATTRIBUTE_COLOR_COMPONENT_ID);
-
- assert_eq!(2, components.len());
- assert_eq!(
- 0,
- components[0]
- .get_reported::()
- .unwrap()
- );
- assert_eq!(
- 1,
- components[1]
- .get_reported::()
- .unwrap()
- );
-
- //Check that we can do a get
- let value0 = components[0].get_child_by_type(ATTRIBUTE_COLOR_VALUE);
- let duration = state.get_child_by_type(ATTRIBUTE_COLOR_DURATION);
- let value1 = components[1].get_child_by_type(ATTRIBUTE_COLOR_VALUE);
-
- let mut frame_result = switch_color_get_rust(value0).unwrap();
- assert_eq!((SL_STATUS_OK, vec![0x33u8, 0x03u8, 0x00u8]), frame_result);
-
- frame_result = switch_color_get_rust(value1).unwrap();
- assert_eq!((SL_STATUS_OK, vec![0x33u8, 0x03u8, 0x01u8]), frame_result);
-
- // Check that we can handle a V3 report
- // FIXME: UIC-1926 Frame parsing dies if duration is not one of these
- // 3 values : SwitchColorReportDurationEnum
- // We should be very tolerant in frame parsing and accept quirky values (event when they are out of spec)
- // so stopping the frame parsing when a value is wrong is a bit strong here.
- let z = [
- 0x33u8, 0x04u8, 0x01u8, 0x42u8, 0xaau8, 0xFEu8, 0x00u8, 0x00u8, 0x00u8,
- ];
- let f: CommandClassSwitchColorFrame = (z[..]).try_into().unwrap();
-
- mock_connection_info
- .expect_get_endpoint()
- .times(1)
- .return_const(ep);
- let mock_controller_endpoint_info: zwave_controller_endpoint_t = Default::default();
- mock_connection_info
- .expect_get_remote()
- .times(2)
- .return_const(mock_controller_endpoint_info);
-
- let status = f.on_control(&mock_connection_info);
- assert_eq!(Ok(()), status);
-
- // Verify that the attribute store was updated
- assert_eq!(
- 0x42,
- value1.get_reported::().unwrap()
- );
- // UIC-1927 : Reactivate this test
- //assert_eq!(
- // 0xaa,
- // value1.get_desired::().unwrap()
- //);
- // FIXME: UIC-1926 Frame parser fail. Here we receive 0xFE in the report and saves value 0x01
- // SwitchColorReportDurationEnum::UnknownDuration in the attribute store
- /*
- assert_eq!(
- 0xFEu32,
- duration
- .get_reported::()
- .unwrap()
- );
- */
-
- //Check that we can handle a V1 report
- let z = [0x33u8, 0x04u8, 0x01u8, 0x52u8];
- let f: CommandClassSwitchColorFrame = (z[..]).try_into().unwrap();
- // ZwaveCommandClassSwitchColor::handle_control(ep, f.unwrap()).unwrap();
-
- mock_connection_info
- .expect_get_endpoint()
- .times(1)
- .return_const(ep);
- mock_connection_info
- .expect_get_remote()
- .times(2)
- .return_const(mock_controller_endpoint_info);
-
- let status = f.on_control(&mock_connection_info);
- assert_eq!(Ok(()), status);
- assert_eq!(
- 0x52,
- value1.get_reported::().unwrap()
- );
- // UIC-1927 : Reactivate this test
- //assert_eq!(
- // 0x00,
- // value1.get_desired::().unwrap()
- //);
-
- let test_event = AttributeEvent {
- attribute: value0,
- event_type: AttributeEventType::ATTRIBUTE_UPDATED,
- value_state: AttributeValueState::DESIRED_ATTRIBUTE,
- };
-
- //Can we generate a set?
- value0
- .set_desired(Some(0xaa as color_component_id_value_t))
- .unwrap();
- value1
- .set_desired(Some(0xbb as color_component_id_value_t))
- .unwrap();
- duration
- .set_desired(Some(0x12 as color_component_id_value_t))
- .unwrap();
-
- // Trigger the attribute store callback, now the state node should
- // indicate that we need a set command
- assert_eq!(true, state.is_value_matched());
- on_value_update(&test_event);
- assert_eq!(false, state.is_value_matched());
-
- frame_result = switch_color_set_rust(state).unwrap();
- assert_eq!(
- (
- SL_STATUS_OK,
- vec![0x33u8, 0x05u8, 0x02u8, 0x00u8, 0xaau8, 0x01u8, 0xbbu8, 0x00u8]
- ),
- frame_result
- );
-
- // Align all the values
- assert_eq!(true, value0.set_desired_as_reported());
- assert_eq!(true, value1.set_desired_as_reported());
- // State attribute gets updated accordingly:
- assert_eq!(false, state.is_value_matched());
- on_value_update(&test_event);
- assert_eq!(true, state.is_value_matched());
- }
-}
diff --git a/applications/zpc/components/zwave_command_classes/src/zwave_command_class_switch_color.cpp b/applications/zpc/components/zwave_command_classes/src/zwave_command_class_switch_color.cpp
index 649307245..3c8df24d4 100644
--- a/applications/zpc/components/zwave_command_classes/src/zwave_command_class_switch_color.cpp
+++ b/applications/zpc/components/zwave_command_classes/src/zwave_command_class_switch_color.cpp
@@ -1,6 +1,6 @@
/******************************************************************************
* # License
- * Copyright 2022 Silicon Laboratories Inc. www.silabs.com
+ * Copyright 2024 Silicon Laboratories Inc. www.silabs.com
******************************************************************************
* The licensor of this software is Silicon Laboratories Inc. Your use of this
* software is governed by the terms of Silicon Labs Master Software License
@@ -10,201 +10,588 @@
* sections of the MSLA applicable to Source Code.
*
*****************************************************************************/
+// Includes from this component
#include "zwave_command_class_switch_color.h"
+#include "zwave_command_classes_utils.h"
-// Interfaces
-#include "zwave_command_class_color_switch_types.h"
-#include "zwave_command_class_generic_types.h"
+// Generic includes
+#include
+#include
// Includes from other ZPC Components
#include "zwave_command_class_indices.h"
-#include "zwave_unid.h"
#include "zwave_command_handler.h"
#include "zpc_attribute_store_network_helper.h"
#include "attribute_store_defined_attribute_types.h"
#include "ZW_classcmd.h"
#include "zpc_attribute_resolver.h"
-#include "zwave_command_classes_utils.h"
// Includes from other Unify Components
#include "dotdot_mqtt.h"
#include "dotdot_mqtt_generated_commands.h"
#include "attribute_store_helper.h"
#include "attribute_resolver.h"
-#include "attribute_transitions.h"
#include "attribute_timeouts.h"
#include "sl_log.h"
-#define LOG_TAG "zwave_command_class_switch_color"
+// Cpp include
+#include "attribute.hpp"
+#include "zwave_frame_generator.hpp"
+#include "zwave_frame_parser.hpp"
+
+// Interfaces
+#include "zwave_command_class_color_switch_types.h"
+
+// Attribute macro, shortening those long defines for attribute types:
+#define ATTRIBUTE(type) ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_##type
+
+// Max component ID color supported
+constexpr uint8_t MAX_SUPPORTED_COLOR_COMPONENT = 9;
+
+// Index of obsoleted component ID
+constexpr uint8_t COMPONENT_ID_INDEXED_COLOR = 8;
+
+// Define initial state of attribute
+constexpr uint8_t INITIAL_STATE = 0;
-static void set_duration(attribute_store_node_t state_node,
- attribute_store_node_value_state_t state,
- uint32_t duration)
+// Log tag
+constexpr char LOG_TAG[] = "zwave_command_class_switch_color";
+
+namespace
{
- attribute_store_node_t duration_node
- = attribute_store_get_first_child_by_type(
- state_node,
- ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_DURATION);
+zwave_frame_generator frame_generator(COMMAND_CLASS_SWITCH_COLOR);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Helper functions
+///////////////////////////////////////////////////////////////////////////////
+zwave_cc_version_t get_current_switch_color_version(attribute_store_node_t node)
+{
+ zwave_cc_version_t version
+ = zwave_command_class_get_version_from_node(node,
+ COMMAND_CLASS_SWITCH_COLOR);
+
+ if (version == 0) {
+ sl_log_error(LOG_TAG, "Switch_color Command Class Version not found");
+ }
- attribute_store_set_node_attribute_value(duration_node,
- state,
- (uint8_t *)&duration,
- sizeof(duration));
+ return version;
}
-[[maybe_unused]]
-static void
- set_all_color_switch_durations(attribute_store_node_t state_node,
- attribute_store_node_value_state_t value_state,
- color_component_id_duration_t duration)
+///////////////////////////////////////////////////////////////////////////////
+// Validation function
+///////////////////////////////////////////////////////////////////////////////
+bool zwave_command_class_switch_color_validate_value(uint8_t value)
{
- uint32_t index = 0;
- attribute_store_node_t component_node
- = attribute_store_get_first_child_by_type(
- state_node,
- ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_COLOR_COMPONENT_ID);
- while (component_node != ATTRIBUTE_STORE_INVALID_NODE) {
- index += 1;
+ return (value >= 0x00 && value <= 0xFF);
+}
- set_duration(component_node, value_state, duration);
+///////////////////////////////////////////////////////////////////////////////
+// Resolution functions
+///////////////////////////////////////////////////////////////////////////////
+static sl_status_t zwave_command_class_switch_color_supported_get(
+ attribute_store_node_t node, uint8_t *frame, uint16_t *frame_length)
+{
+ return frame_generator.generate_no_args_frame(SWITCH_COLOR_SUPPORTED_GET,
+ frame,
+ frame_length);
+}
- component_node = attribute_store_get_node_child_by_type(
- state_node,
- ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_COLOR_COMPONENT_ID,
- index);
+static sl_status_t zwave_command_class_switch_color_get(
+ attribute_store_node_t node, uint8_t *frame, uint16_t *frame_length)
+{
+ sl_log_debug(LOG_TAG, "Switch Color Get");
+ try {
+ attribute_store::attribute value_node(node);
+ assert(value_node.is_valid() && value_node.type() == ATTRIBUTE(VALUE));
+
+ // Compute expected size for set frame
+ const uint8_t expected_frame_size = sizeof(ZW_SWITCH_COLOR_GET_FRAME);
+
+ // Creating the frame
+ frame_generator.initialize_frame(SWITCH_COLOR_GET,
+ frame,
+ expected_frame_size);
+
+ auto component_id_node
+ = value_node.first_parent(ATTRIBUTE(COLOR_COMPONENT_ID));
+ // Add Color Component ID field to the frame
+ frame_generator.add_value(component_id_node, DESIRED_OR_REPORTED_ATTRIBUTE);
+
+ frame_generator.validate_frame(frame_length);
+ } catch (const std::exception &e) {
+ sl_log_error(LOG_TAG,
+ "Error while generating Switch Color get frame : %s",
+ e.what());
+ return SL_STATUS_FAIL;
}
+
+ return SL_STATUS_OK;
}
-static void switch_color_undefine_reported(attribute_store_node_t state_node)
+static sl_status_t zwave_command_class_switch_color_set(
+ attribute_store_node_t node, uint8_t *frame, uint16_t *frame_length)
{
- zwave_command_class_switch_color_invoke_on_all_attributes_with_return_value(
- state_node,
- ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_VALUE,
- attribute_stop_transition);
-
- attribute_store_node_t duration_node
- = attribute_store_get_first_child_by_type(
- state_node,
- ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_DURATION);
- color_component_id_duration_t duration = 0;
- attribute_store_undefine_desired(duration_node);
- attribute_store_set_reported(duration_node,
- &duration,
- sizeof(duration));
-
- sl_log_debug(LOG_TAG, "Transition time expired, probe color");
- zwave_command_class_switch_color_invoke_on_all_attributes(
- state_node,
- ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_VALUE,
- attribute_store_undefine_desired);
- zwave_command_class_switch_color_invoke_on_all_attributes(
- state_node,
- ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_VALUE,
- attribute_store_undefine_reported);
+ sl_log_debug(LOG_TAG, "Switch Color Set");
+ try {
+ attribute_store::attribute value_node(node);
+ assert(value_node.is_valid() && value_node.type() == ATTRIBUTE(VALUE));
+
+ auto current_version = get_current_switch_color_version(node);
+
+ constexpr uint8_t ZWAVE_CC_HEADER_SIZE = 2;
+
+ attribute_store::attribute state_node
+ = value_node.first_parent(ATTRIBUTE(STATE));
+ //Get number of COLOR_COMPONENT_ID
+ auto supported_color_component_count
+ = state_node.children(ATTRIBUTE(COLOR_COMPONENT_ID)).size();
+
+ // Compute expected size for set frame
+ auto expected_frame_size
+ = ZWAVE_CC_HEADER_SIZE + supported_color_component_count * 2;
+ if (current_version >= 2) {
+ // V2 have color component count + duration size
+ expected_frame_size += 2;
+ }
+
+ // Creating the frame
+ frame_generator.initialize_frame(SWITCH_COLOR_SET,
+ frame,
+ expected_frame_size);
+
+ if (current_version >= 2) {
+ //Set Color Component Count in frame
+ frame_generator.add_raw_byte(supported_color_component_count);
+ }
+
+ // Iterate on all color count
+ for (auto color_component_id_node:
+ state_node.children(ATTRIBUTE(COLOR_COMPONENT_ID))) {
+ // Set Color Component ID in frame
+ frame_generator.add_value(color_component_id_node,
+ DESIRED_OR_REPORTED_ATTRIBUTE);
+ // Set Value in frame
+ auto value_node = color_component_id_node.child_by_type(ATTRIBUTE(VALUE));
+ // Can't set value directly since attribute store uses uint32_t and we only want to set 1 byte (uint8_t)
+ auto value = value_node.desired_or_reported();
+ frame_generator.add_raw_byte(static_cast(value));
+ }
+
+ if (current_version >= 2) {
+ auto duration_node = state_node.child_by_type(ATTRIBUTE(DURATION));
+ // Can't set value directly since attribute store uses uint32_t and we only want to set 1 byte (uint8_t)
+ auto duration = duration_node.desired_or_reported();
+ frame_generator.add_raw_byte(static_cast(duration));
+ }
+
+ frame_generator.validate_frame(frame_length);
+ } catch (const std::exception &e) {
+ sl_log_error(LOG_TAG,
+ "Error while generating Switch Color Set frame : %s",
+ e.what());
+ return SL_STATUS_FAIL;
+ }
+
+ return SL_STATUS_OK;
}
-// FIXME: UIC-1901 This function belongs to zwave_command_class_switch_color.rs, but this
-// component really cannot interact with the attribute resolver.
-static void
- on_color_switch_state_send_data_complete(attribute_store_node_t state_node,
- resolver_rule_type_t rule_type,
- zpc_resolver_event_t event)
+static sl_status_t zwave_command_class_switch_color_start_level_change(
+ attribute_store_node_t node, uint8_t *frame, uint16_t *frame_length)
{
- if (rule_type == RESOLVER_GET_RULE) {
- sl_log_error("zwave_command_class_switch_color_control",
- "Received a Get Rule type callback for State node %d "
- "whereas no Get rule is registered. Something is broken.");
- return;
+ sl_log_debug(LOG_TAG, "Switch Color Start Level Change");
+ try {
+ attribute_store::attribute start_change_node(node);
+ assert(start_change_node.is_valid()
+ && start_change_node.type() == ATTRIBUTE(START_CHANGE));
+
+ uint8_t start_change = start_change_node.desired_or_reported();
+ sl_log_debug(LOG_TAG, "start_change: %d", start_change);
+
+ //Set start change = 0 to be able to handle the next command
+ start_change_node.set_desired(INITIAL_STATE);
+
+ //We only handle if Start Change is 1
+ if (start_change != 1) {
+ sl_log_error(LOG_TAG,
+ "Start Change have invalid value: %d",
+ start_change);
+ return SL_STATUS_FAIL;
+ }
+
+ auto current_version = get_current_switch_color_version(node);
+
+ // Compute expected size for set frame
+ const uint8_t expected_frame_size
+ = current_version >= 3
+ ? sizeof(ZW_SWITCH_COLOR_START_LEVEL_CHANGE_V3_FRAME)
+ : sizeof(ZW_SWITCH_COLOR_START_LEVEL_CHANGE_FRAME);
+
+ // Creating the frame
+ frame_generator.initialize_frame(SWITCH_COLOR_START_LEVEL_CHANGE,
+ frame,
+ expected_frame_size);
+
+ //Get color component id node
+ auto color_component_id_node = start_change_node.parent();
+
+ //Get state node
+ attribute_store::attribute state_node
+ = start_change_node.first_parent(ATTRIBUTE(STATE));
+
+ //Get start level node
+ attribute_store::attribute start_level_node(
+ state_node.child_by_type(ATTRIBUTE(START_LEVEL)));
+ uint8_t start_level = start_level_node.desired_or_reported();
+ if (!zwave_command_class_switch_color_validate_value(start_level)) {
+ sl_log_error(
+ LOG_TAG,
+ "Start Level have invalid value: %d, it should in range <0 - 255>",
+ start_level);
+ return SL_STATUS_FAIL;
+ }
+
+ //Get up down node and value
+ attribute_store::attribute up_down_node(
+ state_node.child_by_type(ATTRIBUTE(UP_DOWN)));
+ uint8_t up_down = up_down_node.desired_or_reported();
+ if ((up_down != 0) && (up_down != 1)) {
+ sl_log_error(LOG_TAG,
+ "Up/Down have invalid value: %d, it should be 0 or 1",
+ up_down);
+ return SL_STATUS_FAIL;
+ }
+
+ //Get ignore start level node and value
+ attribute_store::attribute ignore_start_level_node(
+ state_node.child_by_type(ATTRIBUTE(IGNORE_START_LEVEL)));
+ uint8_t ignore_start_level
+ = ignore_start_level_node.desired_or_reported();
+ if ((ignore_start_level != 0) && (ignore_start_level != 1)) {
+ sl_log_error(
+ LOG_TAG,
+ "Ignore Start Level have invalid value: %d, it should be 0 or 1",
+ ignore_start_level);
+ return SL_STATUS_FAIL;
+ }
+
+ uint8_t properties1 = ((up_down << 6) | (ignore_start_level << 5));
+
+ //Add data to frame
+ frame_generator.add_raw_byte(properties1);
+ frame_generator.add_value(color_component_id_node,
+ DESIRED_OR_REPORTED_ATTRIBUTE);
+ frame_generator.add_raw_byte(start_level);
+
+ if (current_version >= 3) {
+ auto duration_node = state_node.child_by_type(ATTRIBUTE(DURATION));
+ auto duration = duration_node.desired_or_reported();
+ frame_generator.add_raw_byte(static_cast(duration));
+ }
+
+ frame_generator.validate_frame(frame_length);
+ } catch (const std::exception &e) {
+ sl_log_error(
+ LOG_TAG,
+ "Error while generating Switch Color Start Level Change frame : %s",
+ e.what());
+ return SL_STATUS_FAIL;
}
- attribute_store_node_t duration_node
- = attribute_store_get_first_child_by_type(
- state_node,
- ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_DURATION);
-
- color_component_id_duration_t duration = 0;
- attribute_store_get_desired(duration_node,
- &duration,
- sizeof(duration));
-
- clock_time_t zwave_desired_duration
- = zwave_duration_to_time((uint8_t)duration);
-
- switch (event) {
- case FRAME_SENT_EVENT_OK_SUPERVISION_WORKING:
- attribute_store_set_reported_as_desired(duration_node);
- break;
-
- case FRAME_SENT_EVENT_OK_SUPERVISION_SUCCESS:
- zwave_command_class_switch_color_invoke_on_all_attributes_with_return_value(
- state_node,
- ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_VALUE,
- &attribute_store_set_reported_as_desired);
- zwave_command_class_switch_color_invoke_on_all_attributes(
- state_node,
- ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_VALUE,
- &attribute_store_undefine_desired);
- set_duration(state_node, REPORTED_ATTRIBUTE, 0);
- attribute_store_undefine_desired(duration_node);
- break;
-
- case FRAME_SENT_EVENT_OK_NO_SUPERVISION:
- zwave_command_class_switch_color_invoke_on_all_attributes_with_return_value(
- state_node,
- ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_VALUE,
- attribute_stop_transition);
- if(zwave_desired_duration > 0) {
- // Should we estimate reported color values during transition
- // and publish them as reported, like we did for level cluster?
-
- zwave_command_class_switch_color_invoke_on_all_attributes(
- state_node,
- ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_VALUE,
- attribute_store_undefine_desired);
-
- attribute_store_set_reported_as_desired(duration_node);
- attribute_store_undefine_desired(duration_node);
-
- // Probe again after this duration
- attribute_timeout_set_callback(state_node,
- zwave_desired_duration + PROBE_BACK_OFF,
- &switch_color_undefine_reported);
- } else {
- zwave_command_class_switch_color_invoke_on_all_attributes(
- state_node,
- ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_VALUE,
- attribute_store_undefine_desired);
- zwave_command_class_switch_color_invoke_on_all_attributes(
- state_node,
- ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_VALUE,
- attribute_store_undefine_reported);
- attribute_store_undefine_desired(duration_node);
+ return SL_STATUS_OK;
+}
+
+static sl_status_t zwave_command_class_switch_color_stop_level_change(
+ attribute_store_node_t node, uint8_t *frame, uint16_t *frame_length)
+{
+ sl_log_debug(LOG_TAG, "Switch Color Stop Level Change");
+ try {
+ attribute_store::attribute stop_change_node(node);
+ assert(stop_change_node.is_valid()
+ && stop_change_node.type() == ATTRIBUTE(STOP_CHANGE));
+
+ uint8_t stop_change = stop_change_node.desired_or_reported();
+ sl_log_debug(LOG_TAG, "stop_change: %d", stop_change);
+
+ //Set start change = 0 to be able to handle the next command
+ stop_change_node.set_desired(INITIAL_STATE);
+
+ //We only handle if Stop Change is 1
+ if (stop_change != 1) {
+ sl_log_error(LOG_TAG, "Start Change have invalid value: %d", stop_change);
+ return SL_STATUS_FAIL;
+ }
+
+ // Compute expected size for set frame
+ const uint8_t expected_frame_size
+ = sizeof(ZW_SWITCH_COLOR_STOP_LEVEL_CHANGE_V3_FRAME);
+
+ // Creating the frame
+ frame_generator.initialize_frame(SWITCH_COLOR_STOP_LEVEL_CHANGE,
+ frame,
+ expected_frame_size);
+
+ //Get color component id node
+ auto color_component_id_node = stop_change_node.parent();
+
+ //Add data to frame
+ frame_generator.add_value(color_component_id_node,
+ DESIRED_OR_REPORTED_ATTRIBUTE);
+
+ frame_generator.validate_frame(frame_length);
+ } catch (const std::exception &e) {
+ sl_log_error(
+ LOG_TAG,
+ "Error while generating Switch Color Stop Level Change frame : %s",
+ e.what());
+ return SL_STATUS_FAIL;
+ }
+
+ return SL_STATUS_OK;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Frame parsing functions
+///////////////////////////////////////////////////////////////////////////////
+static sl_status_t zwave_command_class_switch_color_handle_supported_report(
+ const zwave_controller_connection_info_t *connection_info,
+ const uint8_t *frame_data,
+ uint16_t frame_length)
+{
+ // Setup
+ attribute_store::attribute endpoint_node(
+ zwave_command_class_get_endpoint_node(connection_info));
+
+ sl_log_debug(LOG_TAG, "Switch_color Supported Report frame received");
+
+ // Compute expected size for report frame
+ const uint8_t expected_size = sizeof(ZW_SWITCH_COLOR_SUPPORTED_REPORT_FRAME);
+
+ // Parse the frame
+ try {
+ zwave_frame_parser parser(frame_data, frame_length);
+
+ if (!parser.is_frame_size_valid(expected_size)) {
+ sl_log_error(LOG_TAG, "Invalid frame size for Switch_color Report frame");
+ return SL_STATUS_FAIL;
+ }
+
+ const uint8_t bitmask_1 = parser.read_byte();
+ const uint8_t bitmask_2 = parser.read_byte();
+ color_component_bitmask_t bitmask = (bitmask_2 << 8) | bitmask_1;
+ sl_log_debug(LOG_TAG,
+ "Switch Color Report Color Component Mask : %d",
+ bitmask);
+
+ //Get mask node
+ attribute_store::attribute mask_node
+ = endpoint_node.child_by_type(ATTRIBUTE(SUPPORTED_COLOR_COMPONENT_MASK));
+ //Set reported mask node
+ mask_node.set_reported(bitmask);
+
+ //Get state node
+ attribute_store::attribute state_node(
+ endpoint_node.child_by_type(ATTRIBUTE(STATE)));
+
+ // Create the color component ID attributes
+ color_component_bitmask_t current_bit;
+ for (uint8_t i = 0; i < MAX_SUPPORTED_COLOR_COMPONENT; i++) {
+ current_bit = 1 << i;
+ current_bit &= bitmask;
+
+ // Marked as not supported, we check the next one
+ if (current_bit == 0) {
+ continue;
+ }
+
+ // Ignore special case
+ if (i == COMPONENT_ID_INDEXED_COLOR) {
+ sl_log_warning(LOG_TAG,
+ "Component ID 8 is obsoleted, not creating attribute\n");
+ continue;
}
- break;
- // FRAME_SENT_EVENT_OK_SUPERVISION_NO_SUPPORT:
- // FRAME_SENT_EVENT_OK_SUPERVISION_FAIL:
+ // Create component ID
+ color_component_id_t component_id = i;
+ auto color_component_node
+ = state_node.emplace_node(ATTRIBUTE(COLOR_COMPONENT_ID), component_id);
+
+ // New we associate a value to it so the controller can get it's values
+ color_component_node.emplace_node(ATTRIBUTE(VALUE));
+
+ // Create Start and Stop Level change
+ auto start_node
+ = color_component_node.emplace_node(ATTRIBUTE(START_CHANGE));
+ start_node.set_reported(INITIAL_STATE);
+
+ auto stop_node
+ = color_component_node.emplace_node(ATTRIBUTE(STOP_CHANGE));
+ stop_node.set_reported(INITIAL_STATE);
+ }
+
+ } catch (const std::exception &e) {
+ sl_log_error(LOG_TAG,
+ "Error while parsing Switch_color Supported Report frame : %s",
+ e.what());
+ return SL_STATUS_FAIL;
+ }
+ return SL_STATUS_OK;
+}
+
+static sl_status_t zwave_command_class_switch_color_handle_report(
+ const zwave_controller_connection_info_t *connection_info,
+ const uint8_t *frame_data,
+ uint16_t frame_length)
+{
+ // Setup
+ attribute_store::attribute endpoint_node(
+ zwave_command_class_get_endpoint_node(connection_info));
+ auto current_version = get_current_switch_color_version(endpoint_node);
+
+ sl_log_debug(LOG_TAG, "Switch_color Report frame received");
+
+ // Compute expected size for report frame
+ const uint8_t expected_size = (current_version >= 3)
+ ? sizeof(ZW_SWITCH_COLOR_REPORT_V3_FRAME)
+ : sizeof(ZW_SWITCH_COLOR_REPORT_FRAME);
+
+ attribute_store::attribute state_node
+ = endpoint_node.child_by_type(ATTRIBUTE(STATE));
+
+ if (!state_node.is_valid()) {
+ sl_log_error(
+ LOG_TAG,
+ "Can't find state node when parsing Switch Color Report frame");
+ return SL_STATUS_FAIL;
+ }
+
+ // Parse the frame
+ try {
+ zwave_frame_parser parser(frame_data, frame_length);
+
+ if (!parser.is_frame_size_valid(expected_size)) {
+ sl_log_error(LOG_TAG, "Invalid frame size for Switch_color Report frame");
+ return SL_STATUS_FAIL;
+ }
+
+ //Get Color Component ID
+ uint8_t component_id = parser.read_byte();
+
+ //Get Color Current Value
+ uint32_t current_value = parser.read_byte();
+
+ attribute_store::attribute component_id_node
+ = state_node.child_by_type_and_value(ATTRIBUTE(COLOR_COMPONENT_ID),
+ component_id);
+
+ attribute_store::attribute value_node
+ = component_id_node.child_by_type(ATTRIBUTE(VALUE));
+
+ value_node.set_reported(current_value);
+
+ if (current_version >= 3) {
+ //Get Target Value
+
+ uint32_t target_value = parser.read_byte();
+ sl_log_debug(LOG_TAG,
+ "Switch Color Report Target Value : %d",
+ target_value);
+
+ //Get Duration from frame and Set value
+ auto duration_node = state_node.child_by_type(ATTRIBUTE(DURATION));
+ auto duration_value = parser.read_byte();
+ duration_node.set_reported(duration_value);
+ }
+
+ } catch (const std::exception &e) {
+ sl_log_error(LOG_TAG,
+ "Error while parsing Switch_color Report frame : %s",
+ e.what());
+ return SL_STATUS_FAIL;
+ }
+ return SL_STATUS_OK;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Incoming commands handler
+///////////////////////////////////////////////////////////////////////////////
+sl_status_t zwave_command_class_switch_color_control_handler(
+ const zwave_controller_connection_info_t *connection_info,
+ const uint8_t *frame_data,
+ uint16_t frame_length)
+{
+ // Frame too short, it should have not come here.
+ if (frame_length <= COMMAND_INDEX) {
+ return SL_STATUS_NOT_SUPPORTED;
+ }
+
+ switch (frame_data[COMMAND_INDEX]) {
+ case SWITCH_COLOR_SUPPORTED_REPORT:
+ return zwave_command_class_switch_color_handle_supported_report(
+ connection_info,
+ frame_data,
+ frame_length);
+ case SWITCH_COLOR_REPORT:
+ return zwave_command_class_switch_color_handle_report(connection_info,
+ frame_data,
+ frame_length);
default:
- zwave_command_class_switch_color_invoke_on_all_attributes_with_return_value(
- state_node,
- ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_VALUE,
- &attribute_stop_transition);
- zwave_command_class_switch_color_invoke_on_all_attributes(
- state_node,
- ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_VALUE,
- &attribute_store_undefine_desired);
- zwave_command_class_switch_color_invoke_on_all_attributes(
- state_node,
- ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_VALUE,
- &attribute_store_undefine_reported);
- attribute_store_undefine_desired(duration_node);
- attribute_store_undefine_reported(duration_node);
- break;
+ return SL_STATUS_NOT_SUPPORTED;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Attribute Store callback functions
+///////////////////////////////////////////////////////////////////////////////
+static void zwave_command_class_switch_color_on_version_attribute_update(
+ attribute_store_node_t updated_node, attribute_store_change_t change)
+{
+ if (change == ATTRIBUTE_DELETED) {
+ return;
}
- command_status_values_t state = FINAL_STATE;
- attribute_store_set_reported(state_node, &state, sizeof(state));
- attribute_store_set_desired(state_node, &state, sizeof(state));
+ // Confirm that we have a version attribute update
+ assert(ATTRIBUTE(VERSION) == attribute_store_get_node_type(updated_node));
+
+ attribute_store::attribute version_node(updated_node);
+ // Do not create the attributes until we are sure of the version
+ zwave_cc_version_t supporting_node_version = 0;
+
+ // Wait for the version
+ if (!version_node.reported_exists()) {
+ return;
+ }
+
+ sl_log_debug(LOG_TAG, "Switch Color version attribute update received");
+
+ supporting_node_version = version_node.reported();
+
+ // Now we know we have a switch_color supporting endpoint.
+ attribute_store::attribute endpoint_node
+ = version_node.first_parent(ATTRIBUTE_ENDPOINT_ID);
+
+ // Emplace supported color mask
+ endpoint_node.emplace_node(ATTRIBUTE(SUPPORTED_COLOR_COMPONENT_MASK));
+ // Emplace state
+ auto state_node = endpoint_node.emplace_node(ATTRIBUTE(STATE));
+
+ // Set Reported state
+ state_node.set_reported(FINAL_STATE);
+
+ // Emplace color start level change
+ std::vector switch_color_start_change_attributes;
+ switch_color_start_change_attributes.push_back(ATTRIBUTE(UP_DOWN));
+ switch_color_start_change_attributes.push_back(ATTRIBUTE(IGNORE_START_LEVEL));
+ switch_color_start_change_attributes.push_back(ATTRIBUTE(START_LEVEL));
+
+ for (auto attribute: switch_color_start_change_attributes) {
+ state_node.emplace_node(attribute);
+ }
+
+ // Emplace duration
+ if (supporting_node_version >= 2) {
+ state_node.emplace_node(ATTRIBUTE(DURATION));
+ }
}
///////////////////////////////////////////////////////////////////////////////
@@ -212,11 +599,45 @@ static void
///////////////////////////////////////////////////////////////////////////////
sl_status_t zwave_command_class_switch_color_init()
{
- // FIXME: UIC-1901
- register_send_event_handler(ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_STATE,
- &on_color_switch_state_send_data_complete);
+ // Attribute store callbacks
+ attribute_store_register_callback_by_type(
+ zwave_command_class_switch_color_on_version_attribute_update,
+ ATTRIBUTE(VERSION));
+
+ // Attribute resolver rules
+ attribute_resolver_register_rule(
+ ATTRIBUTE(SUPPORTED_COLOR_COMPONENT_MASK),
+ NULL,
+ &zwave_command_class_switch_color_supported_get);
+
+ attribute_resolver_register_rule(
+ ATTRIBUTE(START_CHANGE),
+ &zwave_command_class_switch_color_start_level_change,
+ NULL);
+
+ attribute_resolver_register_rule(
+ ATTRIBUTE(STOP_CHANGE),
+ &zwave_command_class_switch_color_stop_level_change,
+ NULL);
+
+ attribute_resolver_register_rule(ATTRIBUTE(VALUE),
+ &zwave_command_class_switch_color_set,
+ &zwave_command_class_switch_color_get);
+
+ // The support side of things: Register our handler to the Z-Wave CC framework:
+ zwave_command_handler_t handler = {};
+ handler.support_handler = NULL;
+ handler.control_handler = &zwave_command_class_switch_color_control_handler;
+ // Not supported, so this does not really matter
+ handler.minimal_scheme = ZWAVE_CONTROLLER_ENCAPSULATION_NETWORK_SCHEME;
+ handler.manual_security_validation = false;
+ handler.command_class = COMMAND_CLASS_SWITCH_COLOR;
+ handler.version = SWITCH_COLOR_VERSION_V3;
+ handler.command_class_name = "Switch_color";
+ handler.comments = "";
+
+ zwave_command_handler_register_handler(handler);
- // zwave_command_handler_t is registered using rust, see zwave_command_class_switch_color.rs
return SL_STATUS_OK;
}
@@ -266,4 +687,4 @@ void zwave_command_class_switch_color_invoke_on_all_attributes_with_return_value
ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_COLOR_COMPONENT_ID,
index);
}
-}
+}
\ No newline at end of file
diff --git a/applications/zpc/components/zwave_command_classes/src/zwave_command_class_switch_color.h b/applications/zpc/components/zwave_command_classes/src/zwave_command_class_switch_color.h
index 2bb0720e6..d42c7311f 100644
--- a/applications/zpc/components/zwave_command_classes/src/zwave_command_class_switch_color.h
+++ b/applications/zpc/components/zwave_command_classes/src/zwave_command_class_switch_color.h
@@ -1,6 +1,6 @@
/******************************************************************************
* # License
- * Copyright 2022 Silicon Laboratories Inc. www.silabs.com
+ * Copyright 2021 Silicon Laboratories Inc. www.silabs.com
******************************************************************************
* The licensor of this software is Silicon Laboratories Inc. Your use of this
* software is governed by the terms of Silicon Labs Master Software License
@@ -12,15 +12,70 @@
*****************************************************************************/
/**
- * @defgroup zwave_command_class_switch_color Switch Color Command Class
+ * @defgroup switch_color_command_class Switch Color Command Class
* @ingroup command_classes
* @brief Switch Color Command Class handlers and control functions
*
- * This module implement some of the functions to control the Color Switch
- * Command Class
+ * This module implement functions for generating and parsing the Z-Wave frames
+ * for controlling the Switch Color Command Class.
+ *
+ * The data model used for this command class is tailored to be mapped to the
+ * ZCL Level cluster.
+ *
+ * The State attribute is a hook for the Set / Get rule registrations. The
+ * actual values being set and resolved are the duration and the value.
+ * If the duration and/or the value needs a resolution, the Command Class
+ * handler adjusts the state in order to trigger the resolver:
+ *
+ * - state = reported [] for a get resolution
+ * - state = desired [1] reported [0] for a set resolution
+ * - state = desired [0] reported [0] for a no resolution
+ *
+@startuml{attribute_store_switch_color_command_class.png} "Switch Color data model" width=10cm
+title Switch Color data model
+allow_mixing
+skinparam objectBorderColor black
+
+legend top
+ATTRIBUTE(type) : ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_type
+endlegend
+
+package "Attribute Store" <> {
+ object "NodeID" as node #f2ffe6
+ node : Attribute Type = ATTRIBUTE_NODE_ID
+ node : value = Desired: [], Reported: [03]
+
+ object "Endpoint Attribute" as endpoint #e6fff7
+ endpoint : Attribute Type = ATTRIBUTE_ENDPOINT_ID
+ endpoint : value = Desired: [] - Reported: [04]
+
+ object "Version" as version #FEFEFE
+ version : Attribute Type = ATTRIBUTE(VERSION)
+ version : value = Desired: [] - Reported: [2]
+
+ object "State" as state #FFFFFF
+ state : Attribute Type = ATTRIBUTE(STATE)
+ state : value = Desired: [1] - Reported: [0]
+
+ object "Value" as value #FFFFFF
+ value : Attribute Type = ATTRIBUTE(VALUE)
+ value : value = Desired: [0x00], Reported: [0xFF]
+
+ object "Duration" as duration #FFFFFF
+ duration : Attribute Type = ATTRIBUTE(DURATION)
+ duration : value = Desired: [10], Reported: [10]
+}
+
+node *-- endpoint
+endpoint *-- version
+endpoint *-- state
+state *-- value
+state *-- duration
+
+@enduml
*
* @{
- */
+*/
#ifndef ZWAVE_COMMAND_CLASS_SWITCH_COLOR_H
#define ZWAVE_COMMAND_CLASS_SWITCH_COLOR_H
@@ -59,7 +114,7 @@ void zwave_command_class_switch_color_invoke_on_all_attributes_with_return_value
sl_status_t (*function)(attribute_store_node_t));
/**
- * @brief This function initialize the Color Switch Command Class handler
+ * @brief This function initialize the Switch Color Command Class handler
*
* @return SL_STATUS_OK on success, any other error code for an error.
*/
@@ -70,4 +125,4 @@ sl_status_t zwave_command_class_switch_color_init();
#endif
#endif //ZWAVE_COMMAND_CLASS_SWITCH_COLOR_H
-/** @} end zwave_command_class_switch_color */
+/** @} end switch_color_command_class */
diff --git a/applications/zpc/components/zwave_command_classes/test/CMakeLists.txt b/applications/zpc/components/zwave_command_classes/test/CMakeLists.txt
index e79a13e0d..8ec25f7ce 100644
--- a/applications/zpc/components/zwave_command_classes/test/CMakeLists.txt
+++ b/applications/zpc/components/zwave_command_classes/test/CMakeLists.txt
@@ -451,17 +451,18 @@ target_add_unittest(
NAME
zwave_command_class_switch_color_test
SOURCES
- zwave_command_class_switch_color_test.c
+ zwave_command_class_switch_color_test.cpp
DEPENDS
+ zwave_command_class_test_helpers
zpc_attribute_store_test_helper
- uic_attribute_utils_mock
zwave_command_handler_mock
zwave_controller_mock
uic_attribute_resolver_mock
zpc_attribute_resolver_mock
zpc_config_mock
zwave_tx_scheme_selector_mock
- zwave_tx_mock)
+ zwave_tx_mock
+ uic_dotdot_mqtt_mock)
# Z-Wave Binary Switch Command Class test
target_add_unittest(
diff --git a/applications/zpc/components/zwave_command_classes/test/zwave_command_class_switch_color_test.c b/applications/zpc/components/zwave_command_classes/test/zwave_command_class_switch_color_test.c
deleted file mode 100644
index 5a69252ac..000000000
--- a/applications/zpc/components/zwave_command_classes/test/zwave_command_class_switch_color_test.c
+++ /dev/null
@@ -1,262 +0,0 @@
-/******************************************************************************
- * # License
- * Copyright 2021 Silicon Laboratories Inc. www.silabs.com
- ******************************************************************************
- * The licensor of this software is Silicon Laboratories Inc. Your use of this
- * software is governed by the terms of Silicon Labs Master Software License
- * Agreement (MSLA) available at
- * www.silabs.com/about-us/legal/master-software-license-agreement. This
- * software is distributed to you in Source Code format and is governed by the
- * sections of the MSLA applicable to Source Code.
- *
- *****************************************************************************/
-#include "zwave_command_class_switch_color.h"
-#include "zwave_command_classes_utils.h"
-#include "unity.h"
-
-// Generic includes
-#include
-
-// Includes from other components
-#include "datastore.h"
-#include "attribute_store.h"
-#include "attribute_store_helper.h"
-#include "attribute_store_fixt.h"
-#include "zwave_unid.h"
-#include "zpc_attribute_store_type_registration.h"
-
-// Interface includes
-#include "attribute_store_defined_attribute_types.h"
-#include "zwave_command_class_color_switch_types.h" //FIXME: UIC-1901 remove this
-#include "ZW_classcmd.h"
-#include "zwave_utils.h"
-#include "zwave_controller_types.h"
-#include "zwave_command_class_color_switch_types.h"
-
-// Test helpers
-#include "zpc_attribute_store_test_helper.h"
-
-// Mock includes
-#include "attribute_resolver_mock.h"
-#include "zpc_attribute_resolver_mock.h"
-#include "zwave_command_handler_mock.h"
-#include "attribute_transitions_mock.h"
-#include "attribute_timeouts_mock.h"
-
-// Attribute macro, shortening those long defines for attribute types:
-#define ATTRIBUTE(type) ATTRIBUTE_COMMAND_CLASS_MULTILEVEL_SWITCH_##type
-
-// Static variables
-static zpc_resolver_event_notification_function_t on_send_complete = NULL;
-static attribute_timeout_callback_t switch_color_undefine_reported = NULL;
-
-// Stub functions
-static sl_status_t register_send_event_handler_stub(
- attribute_store_type_t type,
- zpc_resolver_event_notification_function_t function,
- int cmock_num_calls)
-{
- if (ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_STATE == type) {
- on_send_complete = function;
- }
- TEST_ASSERT_NOT_NULL(on_send_complete);
- TEST_ASSERT_EQUAL(ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_STATE, type);
- return SL_STATUS_OK;
-}
-
-static sl_status_t attribute_timeout_set_callback_stub(
- attribute_store_node_t node,
- clock_time_t duration,
- attribute_timeout_callback_t callback_function,
- int cmock_num_calls)
-{
- TEST_ASSERT_EQUAL(ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_STATE, attribute_store_get_node_type(node));
- switch_color_undefine_reported = callback_function;
- return SL_STATUS_OK;
-}
-
-
-/// Setup the test suite (called once before all test_xxx functions are called)
-void suiteSetUp()
-{
- on_send_complete = NULL;
- switch_color_undefine_reported = NULL;
-
- datastore_init(":memory:");
- attribute_store_init();
- zpc_attribute_store_register_known_attribute_types();
- zpc_attribute_store_test_helper_create_network();
- zwave_unid_set_home_id(home_id);
-}
-
-/// Teardown the test suite (called once after all test_xxx functions are called)
-int suiteTearDown(int num_failures)
-{
- attribute_store_teardown();
- datastore_teardown();
- return num_failures;
-}
-
-/// Called before each and every test
-void setUp()
-{
- is_attribute_transition_ongoing_IgnoreAndReturn(false);
-}
-
-void test_zwave_command_class_switch_color_init()
-{
- // On send complete handler
- register_send_event_handler_Stub(®ister_send_event_handler_stub);
-
- // Call init
- TEST_ASSERT_EQUAL(SL_STATUS_OK, zwave_command_class_switch_color_init());
-}
-
-void test_zwave_command_class_on_send_complete()
-{
- attribute_stop_transition_IgnoreAndReturn(SL_STATUS_OK);
-
- // First check the frame creation.
- TEST_ASSERT_NOT_NULL(on_send_complete);
-
- // Create a small network with color switch values
- attribute_store_node_t state_node
- = attribute_store_add_node(ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_STATE,
- endpoint_id_node);
-
- color_component_id_t id = 1;
- attribute_store_node_t component_1_node = attribute_store_add_node(
- ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_COLOR_COMPONENT_ID,
- state_node);
- attribute_store_set_reported(component_1_node, &id, sizeof(id));
- attribute_store_node_t value_1_node
- = attribute_store_add_node(ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_VALUE,
- component_1_node);
- color_component_id_value_t value = 1;
- attribute_store_set_reported(value_1_node, &value, sizeof(value));
- value = 2;
- attribute_store_set_desired(value_1_node, &value, sizeof(value));
-
- attribute_store_node_t component_2_node = attribute_store_add_node(
- ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_COLOR_COMPONENT_ID,
- state_node);
- id = 2;
- attribute_store_set_reported(component_1_node, &id, sizeof(id));
- attribute_store_node_t value_2_node
- = attribute_store_add_node(ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_VALUE,
- component_2_node);
- value = 2;
- attribute_store_set_reported(value_2_node, &value, sizeof(value));
- value = 3;
- attribute_store_set_desired(value_2_node, &value, sizeof(value));
-
- on_send_complete(state_node,
- RESOLVER_GET_RULE,
- FRAME_SENT_EVENT_OK_SUPERVISION_WORKING);
-
- TEST_ASSERT_FALSE(attribute_store_is_value_matched(value_1_node));
-
- on_send_complete(state_node,
- RESOLVER_SET_RULE,
- FRAME_SENT_EVENT_OK_SUPERVISION_WORKING);
-
- TEST_ASSERT_FALSE(attribute_store_is_value_matched(value_1_node));
-
- on_send_complete(state_node,
- RESOLVER_SET_RULE,
- FRAME_SENT_EVENT_OK_SUPERVISION_SUCCESS);
-
- TEST_ASSERT_FALSE(attribute_store_is_value_matched(value_1_node));
- TEST_ASSERT_TRUE(
- attribute_store_is_value_defined(value_1_node, REPORTED_ATTRIBUTE));
-
- // Test without duration
- on_send_complete(state_node,
- RESOLVER_SET_RULE,
- FRAME_SENT_EVENT_OK_NO_SUPERVISION);
-
- TEST_ASSERT_FALSE(
- attribute_store_is_value_defined(value_2_node, REPORTED_ATTRIBUTE));
- TEST_ASSERT_FALSE(
- attribute_store_is_value_defined(value_2_node, DESIRED_ATTRIBUTE));
- TEST_ASSERT_FALSE(
- attribute_store_is_value_defined(value_1_node, REPORTED_ATTRIBUTE));
- TEST_ASSERT_FALSE(
- attribute_store_is_value_defined(value_1_node, DESIRED_ATTRIBUTE));
-
- // Test with duration
- value = 0;
- attribute_store_set_reported(value_1_node, &value, sizeof(value));
- value = 1;
- attribute_store_set_desired(value_1_node, &value, sizeof(value));
- value = 2;
- attribute_store_set_reported(value_2_node, &value, sizeof(value));
- value = 3;
- attribute_store_set_desired(value_2_node, &value, sizeof(value));
-
- color_component_id_duration_t duration_value = 20;
- attribute_store_node_t duration_node
- = attribute_store_add_node(ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_DURATION,
- state_node);
- attribute_store_set_desired(duration_node, &duration_value, sizeof(duration_value));
-
- attribute_timeout_set_callback_ExpectAndReturn(
- state_node,
- zwave_duration_to_time(duration_value) + PROBE_BACK_OFF,
- NULL,
- SL_STATUS_OK);
- attribute_timeout_set_callback_IgnoreArg_callback_function();
- attribute_timeout_set_callback_Stub(&attribute_timeout_set_callback_stub);
-
- on_send_complete(state_node,
- RESOLVER_SET_RULE,
- FRAME_SENT_EVENT_OK_NO_SUPERVISION);
- TEST_ASSERT_FALSE(
- attribute_store_is_value_defined(value_2_node, DESIRED_ATTRIBUTE));
- TEST_ASSERT_FALSE(
- attribute_store_is_value_defined(value_1_node, DESIRED_ATTRIBUTE));
- TEST_ASSERT_FALSE(
- attribute_store_is_value_defined(duration_node, DESIRED_ATTRIBUTE));
- TEST_ASSERT_TRUE(
- attribute_store_is_value_defined(duration_node, REPORTED_ATTRIBUTE));
- TEST_ASSERT_TRUE(
- attribute_store_is_value_defined(value_1_node, REPORTED_ATTRIBUTE));
- TEST_ASSERT_TRUE(
- attribute_store_is_value_defined(value_2_node, REPORTED_ATTRIBUTE));
-
- on_send_complete(state_node,
- RESOLVER_SET_RULE,
- FRAME_SENT_EVENT_OK_SUPERVISION_NO_SUPPORT);
-
- TEST_ASSERT_FALSE(
- attribute_store_is_value_defined(value_1_node, REPORTED_ATTRIBUTE));
-}
-
-void test_switch_color_undefine_reported_happy_case()
-{
- //
- TEST_ASSERT_NOT_NULL(switch_color_undefine_reported);
-
- const int COLOR_VALUE_COUNT = 3;
-
- for (int i = 0; i < COLOR_VALUE_COUNT; i++) {
- attribute_store_node_t color_value_node
- = attribute_store_add_node(ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_VALUE,
- endpoint_id_node);
-
- attribute_store_set_reported(color_value_node, &i, sizeof(i));
- }
-
- switch_color_undefine_reported(endpoint_id_node);
-
- for (int i = 0; i < COLOR_VALUE_COUNT; i++) {
- int j;
- attribute_store_node_t color_value_node
- = attribute_store_add_node(ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_VALUE,
- endpoint_id_node);
-
- TEST_ASSERT_EQUAL(
- SL_STATUS_FAIL,
- attribute_store_get_reported(color_value_node, &j, sizeof(j)));
- }
-}
\ No newline at end of file
diff --git a/applications/zpc/components/zwave_command_classes/test/zwave_command_class_switch_color_test.cpp b/applications/zpc/components/zwave_command_classes/test/zwave_command_class_switch_color_test.cpp
new file mode 100644
index 000000000..6596c4e47
--- /dev/null
+++ b/applications/zpc/components/zwave_command_classes/test/zwave_command_class_switch_color_test.cpp
@@ -0,0 +1,743 @@
+/******************************************************************************
+ * # License
+ * Copyright 2024 Silicon Laboratories Inc. www.silabs.com
+ ******************************************************************************
+ * The licensor of this software is Silicon Laboratories Inc. Your use of this
+ * software is governed by the terms of Silicon Labs Master Software License
+ * Agreement (MSLA) available at
+ * www.silabs.com/about-us/legal/master-software-license-agreement. This
+ * software is distributed to you in Source Code format and is governed by the
+ * sections of the MSLA applicable to Source Code.
+ *
+ *****************************************************************************/
+// Base class
+#include "zwave_command_class_switch_color.h"
+#include "zwave_command_class_color_switch_types.h"
+#include "zwave_command_class_generic_types.h"
+#include "zwave_command_classes_utils.h"
+#include "unity.h"
+
+// Generic includes
+#include
+
+// Unify
+#include "datastore.h"
+#include "attribute_store.h"
+#include "attribute_store_fixt.h"
+
+// Interface includes
+#include "ZW_classcmd.h"
+#include "sl_log.h"
+
+// ZPC includes
+#include "attribute_store_defined_attribute_types.h"
+#include "zpc_attribute_store_type_registration.h"
+
+// Test helpers
+#include "zwave_command_class_test_helper.hpp"
+
+// Attribute macro, shortening those long defines for attribute types:
+#define ATTRIBUTE(type) ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_##type
+
+// Max component ID color supported
+#define MAX_SUPPORTED_COLOR_COMPONENT 9
+// Index of obsoleted component ID
+#define COMPONENT_ID_INDEXED_COLOR 8
+
+// Log tag
+constexpr char LOG_TAG[] = "zwave_command_class_switch_color_test";
+
+using namespace zwave_command_class_test_helper;
+
+extern "C" {
+
+/// Setup the test suite (called once before all test_xxx functions are called)
+void suiteSetUp()
+{
+ datastore_init(":memory:");
+ attribute_store_init();
+ zpc_attribute_store_register_known_attribute_types();
+}
+
+/// Teardown the test suite (called once after all test_xxx functions are called)
+int suiteTearDown(int num_failures)
+{
+ attribute_store_teardown();
+ datastore_teardown();
+ return num_failures;
+}
+
+// Tested command class handler
+const zwave_struct_handler_args command_class_handler
+ = {.command_class_id = COMMAND_CLASS_SWITCH_COLOR,
+ .supported_version = 3,
+ .scheme = ZWAVE_CONTROLLER_ENCAPSULATION_NETWORK_SCHEME};
+// Get Set function map
+const resolver_function_map attribute_bindings = {
+ {ATTRIBUTE(VALUE), {SWITCH_COLOR_GET, SWITCH_COLOR_SET}},
+ {ATTRIBUTE(STOP_CHANGE), {0, SWITCH_COLOR_STOP_LEVEL_CHANGE}},
+ {ATTRIBUTE(START_CHANGE), {0, SWITCH_COLOR_START_LEVEL_CHANGE}},
+ {ATTRIBUTE(SUPPORTED_COLOR_COMPONENT_MASK), {SWITCH_COLOR_SUPPORTED_GET, 0}},
+};
+
+/// Called before each and every test
+void setUp()
+{
+ zwave_setUp(command_class_handler,
+ &zwave_command_class_switch_color_init,
+ attribute_bindings);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Internal helpers
+///////////////////////////////////////////////////////////////////////////////
+attribute_store::attribute helper_get_component_maks_node()
+{
+ return helper_test_and_get_node(ATTRIBUTE(SUPPORTED_COLOR_COMPONENT_MASK));
+}
+
+attribute_store::attribute helper_get_state_node()
+{
+ return helper_test_and_get_node(ATTRIBUTE(STATE));
+}
+
+attribute_store::attribute helper_get_component_id_node()
+{
+ auto state_node = helper_test_and_get_node(ATTRIBUTE(STATE));
+
+ return helper_test_and_get_node(ATTRIBUTE(COLOR_COMPONENT_ID), state_node);
+}
+
+attribute_store::attribute helper_get_duration_node()
+{
+ auto state_node = helper_test_and_get_node(ATTRIBUTE(STATE));
+
+ return helper_test_and_get_node(ATTRIBUTE(DURATION), state_node);
+}
+
+attribute_store::attribute helper_get_up_down_node()
+{
+ auto state_node = helper_test_and_get_node(ATTRIBUTE(STATE));
+
+ return helper_test_and_get_node(ATTRIBUTE(UP_DOWN), state_node);
+}
+
+attribute_store::attribute helper_get_ignore_start_level_node()
+{
+ auto state_node = helper_test_and_get_node(ATTRIBUTE(STATE));
+
+ return helper_test_and_get_node(ATTRIBUTE(IGNORE_START_LEVEL), state_node);
+}
+
+attribute_store::attribute helper_get_start_level_node()
+{
+ auto state_node = helper_test_and_get_node(ATTRIBUTE(STATE));
+
+ return helper_test_and_get_node(ATTRIBUTE(START_LEVEL), state_node);
+}
+
+attribute_store::attribute helper_get_value_node_from_color_component_id_node(attribute_store_node_t color_component_id_node)
+{
+ return helper_test_and_get_node(ATTRIBUTE(VALUE), color_component_id_node);
+}
+
+attribute_store::attribute helper_get_start_change_node_from_color_component_id_node(attribute_store_node_t color_component_id_node)
+{
+ return helper_test_and_get_node(ATTRIBUTE(START_CHANGE), color_component_id_node);
+}
+
+attribute_store::attribute helper_get_stop_change_node_from_color_component_id_node(attribute_store_node_t color_component_id_node)
+{
+ return helper_test_and_get_node(ATTRIBUTE(STOP_CHANGE), color_component_id_node);
+}
+
+std::vector get_supported_color_component_id_node(uint16_t bitmask_tested)
+{
+ std::vector supported_colors_node;
+ uint8_t current_bit;
+
+ //Get state node form endpoint node
+ auto vector_state_node = cpp_endpoint_id_node.children(ATTRIBUTE(STATE));
+ attribute_store::attribute state_node(vector_state_node.front());
+
+ for (uint8_t i = 0; i < MAX_SUPPORTED_COLOR_COMPONENT; i++) {
+ current_bit = 1 << i;
+ current_bit &= bitmask_tested;
+
+ // Marked as not supported, we check the next one
+ if (current_bit == 0) {
+ continue;
+ }
+
+ // Ignore special case
+ if (i == COMPONENT_ID_INDEXED_COLOR) {
+ sl_log_warning(LOG_TAG,
+ "Component ID 8 is obsoleted, not creating attribute\n");
+ continue;
+ }
+
+ // Get color component id node
+ color_component_id_t component_id = i;
+ supported_colors_node.push_back(state_node.child_by_type_and_value(ATTRIBUTE(COLOR_COMPONENT_ID), component_id));
+ }
+
+ return supported_colors_node;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Test cases
+///////////////////////////////////////////////////////////////////////////////
+
+void test_switch_color_interview_v1_happy_case()
+{
+ helper_set_version(1);
+
+ helper_test_and_get_node(ATTRIBUTE(SUPPORTED_COLOR_COMPONENT_MASK));
+ auto state_node = helper_test_and_get_node(ATTRIBUTE(STATE));
+
+ // Verify that we have the correct node(s)
+ helper_test_node_exists(ATTRIBUTE(UP_DOWN), state_node);
+ helper_test_node_exists(ATTRIBUTE(IGNORE_START_LEVEL), state_node);
+ helper_test_node_exists(ATTRIBUTE(START_LEVEL), state_node);
+
+ helper_test_node_does_not_exists(ATTRIBUTE(DURATION), state_node);
+}
+
+void test_switch_color_interview_v2_happy_case()
+{
+ helper_set_version(2);
+
+ helper_test_and_get_node(ATTRIBUTE(SUPPORTED_COLOR_COMPONENT_MASK));
+ auto state_node = helper_test_and_get_node(ATTRIBUTE(STATE));
+
+ // Verify that we have the correct node(s)
+ helper_test_node_exists(ATTRIBUTE(UP_DOWN), state_node);
+ helper_test_node_exists(ATTRIBUTE(IGNORE_START_LEVEL), state_node);
+ helper_test_node_exists(ATTRIBUTE(START_LEVEL), state_node);
+ helper_test_node_exists(ATTRIBUTE(DURATION), state_node);
+}
+
+void test_switch_color_supported_get_happy_case()
+{
+ helper_test_get_set_frame_happy_case(SWITCH_COLOR_SUPPORTED_GET);
+}
+
+void test_switch_color_supported_report_happy_case()
+{
+
+ helper_set_version(1);
+
+ uint8_t mask_1 = 0x1C;
+ uint8_t mask_2 = 0x00;
+ uint16_t bitmask_tested = (mask_2 << 8) | mask_1; // 0000 0000 0001 1100
+
+ auto component_mask_node = helper_get_component_maks_node();
+ helper_test_report_frame(SWITCH_COLOR_SUPPORTED_REPORT, {mask_1, mask_2});
+
+ // Verify that the value of color component mask is updated
+ TEST_ASSERT_EQUAL_MESSAGE(bitmask_tested,
+ component_mask_node.reported(),
+ "Value of color component mask isn't updated after report");
+
+ //Get state node form endpoint node
+ auto vector_state_node = cpp_endpoint_id_node.children(ATTRIBUTE(STATE));
+ attribute_store::attribute state_node(vector_state_node.front());
+
+
+ auto vector_supported_node_id = get_supported_color_component_id_node(bitmask_tested);
+
+
+ for (auto color_component_id_node : vector_supported_node_id) {
+ // Verify that color component id node exist
+ uint8_t component_id_not_expect_tested = ATTRIBUTE_STORE_INVALID_NODE;
+ TEST_ASSERT_NOT_EQUAL_MESSAGE(component_id_not_expect_tested,
+ color_component_id_node,
+ "Can not find attribute");
+
+ // Verify that we value note exist
+ helper_get_value_node_from_color_component_id_node(color_component_id_node);
+
+ // Verify that we start change note exist and have correct value
+ auto start_change_node = helper_get_start_change_node_from_color_component_id_node(color_component_id_node);
+ uint8_t start_change_value_tested = 0;
+ TEST_ASSERT_EQUAL_MESSAGE(start_change_value_tested,
+ start_change_node.reported(),
+ "Start change node isn't have correct value");
+
+ // Verify that we stop change note exist and have correct value
+ auto stop_change_node = helper_get_stop_change_node_from_color_component_id_node(color_component_id_node);
+ uint8_t stop_change_value_tested = 0;
+ TEST_ASSERT_EQUAL_MESSAGE(stop_change_value_tested,
+ stop_change_node.reported(),
+ "Stop change node isn't have correct value");
+ }
+
+ // Test number of Color Component ID
+ auto supported_color_component_count = attribute_store_get_node_child_count_by_type(state_node,
+ ATTRIBUTE(COLOR_COMPONENT_ID));
+
+ TEST_ASSERT_EQUAL_MESSAGE(vector_supported_node_id.size(),
+ supported_color_component_count,
+ "Number of Color Component ID attribute is not correct");
+}
+
+void test_switch_color_get_happy_case()
+{
+ helper_set_version(1);
+
+ uint8_t mask_1 = 0x1C;
+ uint8_t mask_2 = 0x00;
+ uint16_t bitmask_tested = (mask_2 << 8) | mask_1; // 0000 0000 0001 1100
+
+ //Send Color Switch Supported Report frame to create necessary attributes.
+ helper_test_report_frame(SWITCH_COLOR_SUPPORTED_REPORT, {mask_1, mask_2});
+
+ // attribute_store_log();
+
+ auto vector_supported_node_id = get_supported_color_component_id_node(bitmask_tested);
+
+ for (auto element : vector_supported_node_id) {
+ //Get value node
+ attribute_store::attribute color_component_id_node(element);
+ auto value_node = color_component_id_node.child_by_type(ATTRIBUTE(VALUE));
+ //Test switch color get frame
+ helper_test_get_set_frame_happy_case(SWITCH_COLOR_GET, value_node, {color_component_id_node.reported()});
+ }
+}
+
+void test_switch_color_report_v1_happy_case()
+{
+ helper_set_version(1);
+
+ uint8_t mask_1 = 0x1C;
+ uint8_t mask_2 = 0x00;
+ uint16_t bitmask_tested = (mask_2 << 8) | mask_1; // 0000 0000 0001 1100
+ uint8_t value_tested = 0xAB;
+
+ auto component_mask_node = helper_get_component_maks_node();
+ helper_test_report_frame(SWITCH_COLOR_SUPPORTED_REPORT, {mask_1, mask_2});
+
+ // Verify that the value of color component mask is updated
+ TEST_ASSERT_EQUAL_MESSAGE(bitmask_tested,
+ component_mask_node.reported(),
+ "Value of color component mask isn't updated after report");
+
+ auto vector_supported_node_id = get_supported_color_component_id_node(bitmask_tested);
+
+ for (auto color_component_id_node : vector_supported_node_id) {
+
+ // Verify that we value note exist
+ auto value_node = helper_get_value_node_from_color_component_id_node(color_component_id_node);
+
+ helper_test_report_frame(SWITCH_COLOR_REPORT, {color_component_id_node.reported(), value_tested});
+ // attribute_store_log();
+ // Verify that the value is updated correct
+ TEST_ASSERT_EQUAL_MESSAGE(value_tested,
+ value_node.reported(),
+ "Value of isn't updated correct after swich color report");
+ }
+}
+
+void test_switch_color_report_v3_happy_case()
+{
+ helper_set_version(3);
+
+ uint8_t mask_1 = 0x1C;
+ uint8_t mask_2 = 0x00;
+ uint16_t bitmask_tested = (mask_2 << 8) | mask_1; // 0000 0000 0001 1100
+ uint8_t current_value_tested = 0xAB;
+ uint8_t target_value_tested = 0xAB;
+ uint8_t duration_tested = 10;
+
+ auto component_mask_node = helper_get_component_maks_node();
+ helper_test_report_frame(SWITCH_COLOR_SUPPORTED_REPORT, {mask_1, mask_2});
+
+ // Verify that the value of color component mask is updated
+ TEST_ASSERT_EQUAL_MESSAGE(bitmask_tested,
+ component_mask_node.reported(),
+ "Value of color component mask isn't updated after report");
+
+ auto vector_supported_node_id = get_supported_color_component_id_node(bitmask_tested);
+
+ for (auto color_component_id_node : vector_supported_node_id) {
+ // Verify that we value note exist
+ auto value_node = helper_get_value_node_from_color_component_id_node(color_component_id_node);
+
+ //Verify that we duration note exist
+ auto duration_node = helper_get_duration_node();
+
+ helper_test_report_frame(SWITCH_COLOR_REPORT, {color_component_id_node.reported(), current_value_tested, target_value_tested, duration_tested});
+
+ // attribute_store_log();
+
+ // Verify that the value is updated correct
+ TEST_ASSERT_EQUAL_MESSAGE(current_value_tested,
+ value_node.reported(),
+ "Value of value node isn't updated correct after swich color report");
+
+ // Verify that the duration is updated correct
+ TEST_ASSERT_EQUAL_MESSAGE(duration_tested,
+ duration_node.reported(),
+ "Value of duration node isn't updated correct after swich color report");
+ }
+}
+
+void test_switch_color_report_v1_invalid_color_component_id()
+{
+ helper_set_version(1);
+
+ uint8_t mask_1 = 0x1C;
+ uint8_t mask_2 = 0x00;
+ uint16_t bitmask_tested = (mask_2 << 8) | mask_1; // 0000 0000 0001 1100
+ uint8_t value_tested = 0xAB;
+ uint8_t color_component_id_invalid_tested = 5;
+
+ auto component_mask_node = helper_get_component_maks_node();
+ helper_test_report_frame(SWITCH_COLOR_SUPPORTED_REPORT, {mask_1, mask_2});
+
+ // Verify that the value of color component mask is updated
+ TEST_ASSERT_EQUAL_MESSAGE(bitmask_tested,
+ component_mask_node.reported(),
+ "Value of color component mask isn't updated after report");
+
+ auto vector_supported_node_id = get_supported_color_component_id_node(bitmask_tested);
+
+ for (auto color_component_id_node : vector_supported_node_id) {
+ // Verify that we value note exist
+ helper_get_value_node_from_color_component_id_node(color_component_id_node);
+
+ helper_test_report_frame(SWITCH_COLOR_REPORT, {color_component_id_invalid_tested, value_tested}, SL_STATUS_FAIL);
+ }
+}
+
+void test_switch_color_start_level_change_v1_happy_case()
+{
+ helper_set_version(1);
+
+ uint8_t mask_1 = 0x1C;
+ uint8_t mask_2 = 0x00;
+ uint16_t bitmask_tested = (mask_2 << 8) | mask_1; // 0000 0000 0001 1100
+ uint8_t start_change_node_tested = 1;
+ uint8_t start_change_node_finnal_state = FINAL_STATE;
+ uint8_t up_down_tested = 1;
+ uint8_t ignore_start_level_tested = 1;
+ uint8_t start_level_tested = 0xAB;
+ uint8_t start_level_change_properties1_tested = ((up_down_tested << 6) | (ignore_start_level_tested << 5));
+
+ auto component_mask_node = helper_get_component_maks_node();
+ helper_test_report_frame(SWITCH_COLOR_SUPPORTED_REPORT, {mask_1, mask_2});
+
+ // Verify that the value of color component mask is updated
+ TEST_ASSERT_EQUAL_MESSAGE(bitmask_tested,
+ component_mask_node.reported(),
+ "Value of color component mask isn't updated after report");
+
+ auto vector_supported_node_id = get_supported_color_component_id_node(bitmask_tested);
+
+ for (auto color_component_id_node : vector_supported_node_id) {
+ // Get color start change node and set desired value
+ auto start_change_node = helper_get_start_change_node_from_color_component_id_node(color_component_id_node);
+ start_change_node.set_desired(start_change_node_tested);
+
+ // Get color start change node and set desired value
+ auto up_down_node = helper_get_up_down_node();
+ up_down_node.set_desired(up_down_tested);
+
+ // Get color start change node and set desired value
+ auto ignore_start_level_node = helper_get_ignore_start_level_node();
+ ignore_start_level_node.set_desired(ignore_start_level_tested);
+
+ // Get color start change node and set desired value
+ auto start_level_node = helper_get_start_level_node();
+ start_level_node.set_desired(start_level_tested);
+
+ // attribute_store_log();
+ helper_test_get_set_frame_happy_case(SWITCH_COLOR_START_LEVEL_CHANGE,
+ start_change_node,
+ {start_level_change_properties1_tested, color_component_id_node.reported(), start_level_tested});
+
+ //Verify start leve change = 0 after send frame
+ TEST_ASSERT_EQUAL_MESSAGE(start_change_node_finnal_state,
+ start_change_node.reported(),
+ "Value of start change isn't updated correct after send frame");
+ }
+}
+
+void test_switch_color_start_level_change_v3_happy_case()
+{
+ helper_set_version(3);
+
+ uint8_t mask_1 = 0x1C;
+ uint8_t mask_2 = 0x00;
+ uint16_t bitmask_tested = (mask_2 << 8) | mask_1; // 0000 0000 0001 1100
+ uint8_t start_change_node_tested = 1;
+ uint8_t start_change_node_finnal_state = FINAL_STATE;
+ uint8_t up_down_tested = 1;
+ uint8_t ignore_start_level_tested = 1;
+ uint8_t start_level_tested = 0xAB;
+ uint8_t duration_tested = 10;
+ uint8_t start_level_change_properties1_tested = ((up_down_tested << 6) | (ignore_start_level_tested << 5));
+
+ auto component_mask_node = helper_get_component_maks_node();
+ helper_test_report_frame(SWITCH_COLOR_SUPPORTED_REPORT, {mask_1, mask_2});
+
+ // Verify that the value of color component mask is updated
+ TEST_ASSERT_EQUAL_MESSAGE(bitmask_tested,
+ component_mask_node.reported(),
+ "Value of color component mask isn't updated after report");
+
+ auto vector_supported_node_id = get_supported_color_component_id_node(bitmask_tested);
+
+ for (auto color_component_id_node : vector_supported_node_id) {
+ // Get color start change node and set desired value
+ auto start_change_node = helper_get_start_change_node_from_color_component_id_node(color_component_id_node);
+ start_change_node.set_desired(start_change_node_tested);
+
+ // Get up down node and set desired value
+ auto up_down_node = helper_get_up_down_node();
+ up_down_node.set_desired(up_down_tested);
+
+ // Get ignore start level node and set desired value
+ auto ignore_start_level_node = helper_get_ignore_start_level_node();
+ ignore_start_level_node.set_desired(ignore_start_level_tested);
+
+ // Get start level node and set desired value
+ auto start_level_node = helper_get_start_level_node();
+ start_level_node.set_desired(start_level_tested);
+
+ // Get duration node and set desired value
+ auto duration_node = helper_get_duration_node();
+ duration_node.set_desired(duration_tested);
+
+ // attribute_store_log();
+ helper_test_get_set_frame_happy_case(SWITCH_COLOR_START_LEVEL_CHANGE_V3,
+ start_change_node,
+ {start_level_change_properties1_tested, color_component_id_node.reported(), start_level_tested, duration_tested});
+
+ //Verify start leve change = 0 after send frame
+ TEST_ASSERT_EQUAL_MESSAGE(start_change_node_finnal_state,
+ start_change_node.reported(),
+ "Value of start change isn't updated correct after send frame");
+ }
+}
+
+void test_switch_color_start_level_change_invalid_start_change_value()
+{
+ helper_set_version(1);
+
+ uint8_t mask_1 = 0x1C;
+ uint8_t mask_2 = 0x00;
+ uint16_t bitmask_tested = (mask_2 << 8) | mask_1; // 0000 0000 0001 1100
+ uint8_t start_change_node_tested = 2;
+ uint8_t start_change_node_finnal_state = FINAL_STATE;
+
+ auto component_mask_node = helper_get_component_maks_node();
+ helper_test_report_frame(SWITCH_COLOR_SUPPORTED_REPORT, {mask_1, mask_2});
+
+ // Verify that the value of color component mask is updated
+ TEST_ASSERT_EQUAL_MESSAGE(bitmask_tested,
+ component_mask_node.reported(),
+ "Value of color component mask isn't updated after report");
+
+ auto vector_supported_node_id = get_supported_color_component_id_node(bitmask_tested);
+
+ for (auto color_component_id_node : vector_supported_node_id) {
+ // Get color start change node and set desired value
+ auto start_change_node = helper_get_start_change_node_from_color_component_id_node(color_component_id_node);
+ start_change_node.set_desired(start_change_node_tested);
+
+ // attribute_store_log();
+
+ helper_test_get_set_fail_case(SWITCH_COLOR_START_LEVEL_CHANGE,
+ SL_STATUS_FAIL,
+ start_change_node);
+
+ //Verify start leve change = 0 after send frame
+ TEST_ASSERT_EQUAL_MESSAGE(start_change_node_finnal_state,
+ start_change_node.reported(),
+ "Value of start change isn't updated correct after send frame");
+ }
+}
+
+void test_switch_color_stop_level_change_happy_case()
+{
+ helper_set_version(3);
+
+ uint8_t mask_1 = 0x1C;
+ uint8_t mask_2 = 0x00;
+ uint16_t bitmask_tested = (mask_2 << 8) | mask_1; // 0000 0000 0001 1100
+ uint8_t stop_change_node_tested = 1;
+ uint8_t stop_change_node_finnal_state = FINAL_STATE;
+
+ auto component_mask_node = helper_get_component_maks_node();
+ helper_test_report_frame(SWITCH_COLOR_SUPPORTED_REPORT, {mask_1, mask_2});
+
+ // Verify that the value of color component mask is updated
+ TEST_ASSERT_EQUAL_MESSAGE(bitmask_tested,
+ component_mask_node.reported(),
+ "Value of color component mask isn't updated after report");
+
+ auto vector_supported_node_id = get_supported_color_component_id_node(bitmask_tested);
+
+ for (auto color_component_id_node : vector_supported_node_id) {
+
+ // Get color start change node and set desired value
+ auto stop_change_node = helper_get_stop_change_node_from_color_component_id_node(color_component_id_node);
+ stop_change_node.set_desired(stop_change_node_tested);
+
+ // attribute_store_log();
+ helper_test_get_set_frame_happy_case(SWITCH_COLOR_STOP_LEVEL_CHANGE,
+ stop_change_node,
+ {color_component_id_node.reported()});
+
+ //Verify start leve change = 0 after send frame
+ TEST_ASSERT_EQUAL_MESSAGE(stop_change_node_finnal_state,
+ stop_change_node.reported(),
+ "Value of stop change isn't updated correct after send frame");
+ }
+}
+
+void test_switch_color_stop_level_change_invalid_stop_change_value()
+{
+ helper_set_version(3);
+
+ uint8_t mask_1 = 0x1C;
+ uint8_t mask_2 = 0x00;
+ uint16_t bitmask_tested = (mask_2 << 8) | mask_1; // 0000 0000 0001 1100
+ uint8_t stop_change_node_tested = 2;
+ uint8_t stop_change_node_finnal_state = FINAL_STATE;
+
+ auto component_mask_node = helper_get_component_maks_node();
+ helper_test_report_frame(SWITCH_COLOR_SUPPORTED_REPORT, {mask_1, mask_2});
+
+ // Verify that the value of color component mask is updated
+ TEST_ASSERT_EQUAL_MESSAGE(bitmask_tested,
+ component_mask_node.reported(),
+ "Value of color component mask isn't updated after report");
+
+ auto vector_supported_node_id = get_supported_color_component_id_node(bitmask_tested);
+
+ for (auto color_component_id_node : vector_supported_node_id) {
+
+ // Get color start change node and set desired value
+ auto stop_change_node = helper_get_stop_change_node_from_color_component_id_node(color_component_id_node);
+ stop_change_node.set_desired(stop_change_node_tested);
+
+ // attribute_store_log();
+
+ helper_test_get_set_fail_case(SWITCH_COLOR_STOP_LEVEL_CHANGE,
+ SL_STATUS_FAIL,
+ stop_change_node);
+
+ //Verify start leve change = 0 after send frame
+ TEST_ASSERT_EQUAL_MESSAGE(stop_change_node_finnal_state,
+ stop_change_node.reported(),
+ "Value of stop change isn't updated correct after send frame");
+ }
+}
+
+void test_switch_color_set_v1_happy_case()
+{
+ helper_set_version(1);
+
+ uint8_t mask_1 = 0x1C;
+ uint8_t mask_2 = 0x00;
+ uint16_t bitmask_tested = (mask_2 << 8) | mask_1; // 0000 0000 0001 1100
+ uint8_t value_reported_tested = 0xAB;
+ uint8_t value_desired_tested = 0xCD;
+ attribute_store::attribute value_node_tested;
+
+ std::vector arg_tested_frame;
+
+ auto component_mask_node = helper_get_component_maks_node();
+ helper_test_report_frame(SWITCH_COLOR_SUPPORTED_REPORT, {mask_1, mask_2});
+
+ // Verify that the value of color component mask is updated
+ TEST_ASSERT_EQUAL_MESSAGE(bitmask_tested,
+ component_mask_node.reported(),
+ "Value of color component mask isn't updated after report");
+
+ auto vector_supported_node_id = get_supported_color_component_id_node(bitmask_tested);
+
+ for (auto color_component_id_node : vector_supported_node_id) {
+
+ //Send report frame to initialize the value
+ helper_test_report_frame(SWITCH_COLOR_REPORT, {color_component_id_node.reported(), value_reported_tested});
+
+ attribute_store::attribute value_node = helper_get_value_node_from_color_component_id_node(color_component_id_node);
+ value_node.set_desired(value_desired_tested);
+
+ arg_tested_frame.push_back(color_component_id_node.reported());
+ arg_tested_frame.push_back(value_desired_tested);
+
+ value_node_tested = value_node;
+ }
+
+ // attribute_store_log();
+
+ helper_test_get_set_frame_happy_case(SWITCH_COLOR_SET,
+ value_node_tested,
+ arg_tested_frame);
+}
+
+
+
+void test_switch_color_set_v2_happy_case()
+{
+ helper_set_version(2);
+
+ uint8_t mask_1 = 0x1C;
+ uint8_t mask_2 = 0x00;
+ uint16_t bitmask_tested = (mask_2 << 8) | mask_1; // 0000 0000 0001 1100
+ uint8_t value_reported_tested = 0xAB;
+ uint8_t value_desired_tested = 0xCD;
+ uint8_t value_duration_tested = 100;
+ attribute_store::attribute value_node_tested;
+
+ std::vector arg_tested_frame;
+
+ auto component_mask_node = helper_get_component_maks_node();
+ helper_test_report_frame(SWITCH_COLOR_SUPPORTED_REPORT, {mask_1, mask_2});
+
+ // Verify that the value of color component mask is updated
+ TEST_ASSERT_EQUAL_MESSAGE(bitmask_tested,
+ component_mask_node.reported(),
+ "Value of color component mask isn't updated after report");
+
+ //Get state node form endpoint node
+ auto vector_state_node = cpp_endpoint_id_node.children(ATTRIBUTE(STATE));
+ attribute_store::attribute state_node(vector_state_node.front());
+
+ auto vector_supported_node_id = get_supported_color_component_id_node(bitmask_tested);
+
+ for (auto color_component_id_node : vector_supported_node_id) {
+
+ //Send report frame to initialize the value
+ helper_test_report_frame(SWITCH_COLOR_REPORT, {color_component_id_node.reported(), value_reported_tested});
+
+ attribute_store::attribute value_node = helper_get_value_node_from_color_component_id_node(color_component_id_node);
+ value_node.set_desired(value_desired_tested);
+
+ arg_tested_frame.push_back(color_component_id_node.reported());
+ arg_tested_frame.push_back(value_desired_tested);
+
+ value_node_tested = value_node;
+ }
+
+ // attribute_store_log();
+
+ attribute_store::attribute duration_node = helper_get_duration_node();
+ duration_node.set_desired(value_duration_tested);
+
+ arg_tested_frame.push_back(value_duration_tested);
+
+ auto supported_color_component_count = attribute_store_get_node_child_count_by_type(state_node,
+ ATTRIBUTE(COLOR_COMPONENT_ID));
+ arg_tested_frame.insert(arg_tested_frame.begin(), (uint8_t)supported_color_component_count);
+
+ helper_test_get_set_frame_happy_case(SWITCH_COLOR_SET_V2,
+ value_node_tested,
+ arg_tested_frame);
+}
+
+}
\ No newline at end of file
diff --git a/applications/zpc/doc/command_classes/color_switch.rst b/applications/zpc/doc/command_classes/color_switch.rst
new file mode 100644
index 000000000..fe8d7b008
--- /dev/null
+++ b/applications/zpc/doc/command_classes/color_switch.rst
@@ -0,0 +1,227 @@
+Color Switch
+=============
+
+Version supported : 3
+
+.. contents::
+ :depth: 2
+ :local:
+ :backlinks: none
+
+
+Interview process
+*****************
+
+#. :ref:`Color Switch Supported Get `
+#. For each supported Color Component: :ref:`Color Switch Get `
+
+Command Class Commands
+**********************
+
+.. _color-switch-supported-get-command:
+
+Color Switch Supported Get
+---------------------------
+
+Trigger on undefined **reported** value of ``SUPPORTED_COLOR_COMPONENT_MASK``.
+
+Color Switch Supported Report
+------------------------------
+
+Mapping between Report command and attribute store :
+
+.. list-table::
+ :header-rows: 1
+
+ * - Z-Wave Command Attribute
+ - Z-Wave Attribute Store
+ * - ``Color Component mask 1 | ((Color Component mask 2) << 8)``
+ - ``SUPPORTED_COLOR_COMPONENT_MASK``
+
+.. note::
+ ``Color Component mask 1``, ``Color Component mask 2`` used for calculating supported ``COLOR_COMPONENT_ID``
+
+
+Color Switch Set
+-------------------------------
+
+Trigger on new **desired** value of ``VALUE``.
+
+Mapping between attribute store and Set command:
+
+.. list-table::
+ :header-rows: 1
+
+ * - Z-wave Attribute Store
+ - Attribute State
+ - Z-wave Set Field
+ * - ``VALUE``
+ - Desired or Reported
+ - ``Value``
+ * - ``DURATION``
+ - Desired or Reported
+ - ``Duration``
+ * - ``COLOR_COMPONENT_ID``
+ - Desired or Reported
+ - ``Color Component ID``
+
+.. _color-switch-get-command:
+
+Color Switch Get
+-------------------------------
+
+Trigger on undefined **reported** value of ``VALUE``.
+
+
+Color Switch Report
+----------------------------------
+
+Mapping between Report command and attribute store :
+
+.. list-table::
+ :header-rows: 1
+
+ * - Report Field Command
+ - Z-Wave Attribute Store
+ * - ``Color Component ID``
+ - ``COLOR_COMPONENT_ID``
+ * - ``Current Value``
+ - ``VALUE``
+ * - ``Duration``
+ - ``DURATION``
+
+Color Switch Start Level Change
+--------------------------
+
+Trigger on new **desired** value of ``START_CHANGE``.
+
+Mapping between attribute store and command:
+
+.. list-table::
+ :header-rows: 1
+
+ * - Z-wave Attribute Store
+ - Attribute State
+ - Z-wave Set Field
+ * - ``START_LEVEL``
+ - Desired or Reported
+ - ``Start Level``
+ * - ``UP_DOWN``
+ - Desired or Reported
+ - ``Up/Down``
+ * - ``IGNORE_START_LEVEL``
+ - Desired or Reported
+ - ``Ignore Start State``
+ * - ``COLOR_COMPONENT_ID``
+ - Desired or Reported
+ - ``Color Component ID``
+ * - ``START_LEVEL``
+ - Desired or Reported
+ - ``Start Level``
+ * - ``DURATION``
+ - Desired or Reported
+ - ``Duration``
+
+
+
+Color Switch Stop Level Change
+--------------------------
+
+Trigger on new **desired** value of ``STOP_CHANGE``.
+
+Mapping between attribute store and command:
+
+.. list-table::
+ :header-rows: 1
+
+ * - Z-wave Attribute Store
+ - Attribute State
+ - Z-wave Set Field
+ * - ``COLOR_COMPONENT_ID``
+ - Desired or Reported
+ - ``Color Component ID``
+
+.. note::
+ The structure of the attribute store is :
+
+ .. code:: text
+
+ |__ SUPPORTED_COLOR_COMPONENT_MASK
+ |__ STATE
+ |__ COLOR_COMPONENT_ID
+ | |__ VALUE
+ | |__ START_CHANGE
+ | |__ STOP_CHANGE
+ |__ DURATION
+ |__ UP_DOWN
+ |__ IGNORE_START_LEVEL
+ |__ START_LEVEL
+
+
+Unify Clusters
+**************
+
+UAM files
+---------
+
+.. list-table::
+ :header-rows: 1
+
+ * - UAM File
+ - Cluster
+ - Comments
+ * - ``SwitchColor.uam``
+ - ``Unify_SwitchColor.xml``
+ - Mapping between Color Switch command class and Color Switch cluster
+
+Bindings
+--------
+
+.. list-table::
+ :header-rows: 1
+
+ * - Z-Wave Attribute Store
+ - Cluster attribute
+ - Comments
+ * - ``VALUE``
+ - UnifySwitchColor WarmWhite
+ - Z-Wave <-> Cluster (If ``COMPONENT_ID`` = 0x00)
+ * - ``VALUE``
+ - UnifySwitchColor ColdWhite
+ - Z-Wave <-> Cluster (If ``COMPONENT_ID`` = 0x01)
+ * - ``VALUE``
+ - UnifySwitchColor Red
+ - Z-Wave <-> Cluster (If ``COMPONENT_ID`` = 0x02)
+ * - ``VALUE``
+ - UnifySwitchColor Green
+ - Z-Wave <-> Cluster (If ``COMPONENT_ID`` = 0x03)
+ * - ``VALUE``
+ - UnifySwitchColor Blue
+ - Z-Wave <-> Cluster (If ``COMPONENT_ID`` = 0x04)
+ * - ``VALUE``
+ - UnifySwitchColor Amber
+ - Z-Wave <-> Cluster (If ``COMPONENT_ID`` = 0x05)
+ * - ``VALUE``
+ - UnifySwitchColor Cyan
+ - Z-Wave <-> Cluster (If ``COMPONENT_ID`` = 0x06)
+ * - ``VALUE``
+ - UnifySwitchColor Purple
+ - Z-Wave <-> Cluster (If ``COMPONENT_ID`` = 0x07)
+
+
+Command actions
+---------------
+
+.. list-table::
+ :widths: 20 50 30
+ :header-rows: 1
+
+ * - Action
+ - MQTT Topic
+ - Comments
+ * - End user performs set the color
+ - ``ucl/by-unid///UnifySwitchColor/Commands/SetColor {"ColorComponentId" : 4, "Value" : 100, "Duration" : 0}``
+ - See ``ColorComponentId`` values in Bindings table
+ * - End user performs start/stop enhancing a color component
+ - ``ucl/by-unid///UnifySwitchColor/Commands/StartStopChange {"StartStop" : true, "UpDown" : false, "IgnorStartLevel" : true, "ColorComponentId" : 2, "StartLevel" : 50, "Duration" : 10}``
+ - ``StartStop`` = ``true`` for Start level change, = ``false`` for Stop level change; ``UpDown`` = ``true`` for decreasing, = ``false`` for increasing
\ No newline at end of file
diff --git a/applications/zpc/scripts/certification/command_classes/clusters/unify_switch_color.py b/applications/zpc/scripts/certification/command_classes/clusters/unify_switch_color.py
new file mode 100644
index 000000000..46c478728
--- /dev/null
+++ b/applications/zpc/scripts/certification/command_classes/clusters/unify_switch_color.py
@@ -0,0 +1,17 @@
+import mqtt.mqtt_manager as mqtt_manager
+import utils.utils as utils
+
+CLUSTER_NAME = "UnifySwitchColor"
+
+def command_set_color(color_component_id, value, duration = 0):
+ mqtt_manager.send_unify_cluster_command(CLUSTER_NAME, "SetColor",
+ '{"ColorComponentId" : %d, "Value" : %d, "Duration" : %d}'
+ % (color_component_id, value, duration)
+ )
+
+
+def command_start_stop_level_change(start_stop, up_down, ignor_start_level, color_component_id, start_level, duration = 1):
+ mqtt_manager.send_unify_cluster_command(CLUSTER_NAME, "StartStopChange",
+ '{"StartStop" : %s, "UpDown" : %s, "IgnorStartLevel" : %s, "ColorComponentId" : %d, "StartLevel" : %d, "Duration" : %d}'
+ % (utils.bool_to_str(start_stop), utils.bool_to_str(up_down), utils.bool_to_str(ignor_start_level), color_component_id, start_level, duration)
+ )
\ No newline at end of file
diff --git a/applications/zpc/scripts/certification/command_classes/color_switch.py b/applications/zpc/scripts/certification/command_classes/color_switch.py
new file mode 100644
index 000000000..8e5ab756a
--- /dev/null
+++ b/applications/zpc/scripts/certification/command_classes/color_switch.py
@@ -0,0 +1,46 @@
+#!/usr/bin/env python3
+
+import mqtt.mqtt_manager as mqtt_manager
+import utils.pretty_print as display
+
+from clusters import on_off, level, unify_switch_color
+
+def color_set(color_id, color_value):
+ display.action_description(f"Color ID {color_id} Set to {color_value}")
+ unify_switch_color.command_set_color(color_id, color_value, 0)
+
+def color_start_change_up(color_id):
+ display.action_description(f"Color ID {color_id} Start Level Change Up")
+ unify_switch_color.command_start_stop_level_change(True, False, True, color_id, 50, 1)
+
+def color_stop_change(color_id):
+ display.action_description(f"Color ID {color_id} Stop Level Change")
+ unify_switch_color.command_start_stop_level_change(False, False, True, color_id, 50, 1)
+
+def switch_multilevel_set(level_value):
+ display.action_description(f"Switch Multilevel Set to {level_value}")
+ level.command_move_level(level_value, True, True)
+
+def switch_binary_set_on():
+ display.action_description(f"Switch Binary Set On")
+ on_off.command_on()
+
+def switch_binary_set_off():
+ display.action_description(f"Switch Binary Set Off")
+ on_off.command_off()
+
+if __name__ == '__main__':
+ mqtt_manager.add_node()
+
+ # set color component 'Green' (ID = 0x03) with value= 255
+ color_set(3, 255)
+ # start level change for color component 'Red' (ID = 0x02) increasing its brightness
+ color_start_change_up(2)
+ # stop level change for color component 'Red' (ID = 0x02)
+ color_stop_change(2)
+ # binary switch set
+ switch_binary_set_on()
+ # multilevel switch set
+ switch_multilevel_set(50)
+
+ mqtt_manager.remove_node()
diff --git a/patches/UnifySDK/0015-UIC-3272-Generated-files-for-Switch-Color.patch b/patches/UnifySDK/0015-UIC-3272-Generated-files-for-Switch-Color.patch
new file mode 100644
index 000000000..1847144f1
--- /dev/null
+++ b/patches/UnifySDK/0015-UIC-3272-Generated-files-for-Switch-Color.patch
@@ -0,0 +1,7384 @@
+From 44fedc439961733d8ba06700d15975a0e4d45c41 Mon Sep 17 00:00:00 2001
+From: Viet
+Date: Wed, 11 Sep 2024 18:06:50 +0700
+Subject: [PATCH] UIC-3272: Generated files for Switch Color
+
+---
+ .../zap-generated/include/dotdot_mqtt.h | 511 ++++++
+ .../include/dotdot_mqtt_attributes.h | 113 ++
+ .../include/dotdot_mqtt_generated_commands.h | 64 +
+ .../include/dotdot_mqtt_group_commands.h | 49 +
+ .../include/dotdot_mqtt_send_commands.h | 78 +
+ ...dotdot_mqtt_supported_generated_commands.h | 30 +
+ .../zap-generated/src/dotdot_mqtt.cpp | 1462 +++++++++++++++++
+ .../zap-generated/src/dotdot_mqtt.hpp | 66 +
+ .../src/dotdot_mqtt_attributes.cpp | 707 ++++++++
+ .../src/dotdot_mqtt_command_helpers.cpp | 176 ++
+ .../src/dotdot_mqtt_command_helpers.hpp | 82 +
+ .../src/dotdot_mqtt_generated_commands.cpp | 112 ++
+ .../src/dotdot_mqtt_group_commands.cpp | 335 ++++
+ .../zap-generated/src/dotdot_mqtt_helpers.cpp | 102 ++
+ .../src/dotdot_mqtt_send_commands.cpp | 148 ++
+ ...tdot_mqtt_supported_generated_commands.cpp | 49 +
+ .../test/dotdot_mqtt_test.include | 49 +
+ .../include/dotdot_attributes.uam | 10 +
+ .../include/dotdot_attributes_camel_case.uam | 10 +
+ .../unify_dotdot_attribute_store_helpers.h | 876 ++++++++++
+ .../unify_dotdot_defined_attribute_types.h | 9 +
+ ...ot_attribute_store_attribute_publisher.cpp | 481 ++++++
+ ..._force_read_attributes_command_callbacks.c | 67 +
+ .../unify_dotdot_attribute_store_helpers.cpp | 931 +++++++++++
+ ...fy_dotdot_attribute_store_registration.cpp | 192 +++
+ ...store_write_attributes_command_callbacks.c | 33 +
+ .../test/unify_dotdot_attribute_store_test.c | 158 ++
+ .../test/unify_dotdot_attribute_store_test.h | 10 +
+ 28 files changed, 6910 insertions(+)
+
+diff --git a/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt.h b/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt.h
+index 7106f0f0fc..650ce8ed54 100644
+--- a/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt.h
++++ b/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt.h
+@@ -42337,6 +42337,517 @@ void uic_mqtt_dotdot_unify_humidity_control_publish_supported_commands(
+ void uic_mqtt_dotdot_unify_humidity_control_publish_empty_supported_commands(
+ const dotdot_unid_t unid
+ ,dotdot_endpoint_id_t endpoint);
++// Callback types used by the unify_switch_color cluster
++typedef sl_status_t (*uic_mqtt_dotdot_unify_switch_color_set_color_callback_t)(
++ dotdot_unid_t unid,
++ dotdot_endpoint_id_t endpoint,
++ uic_mqtt_dotdot_callback_call_type_t call_type,
++ uint8_t color_component_id,
++
++ uint8_t value,
++
++ uint32_t duration
++
++);
++typedef sl_status_t (*uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback_t)(
++ dotdot_unid_t unid,
++ dotdot_endpoint_id_t endpoint,
++ uic_mqtt_dotdot_callback_call_type_t call_type,
++ bool start_stop,
++
++ bool up_down,
++
++ bool ignor_start_level,
++
++ uint8_t color_component_id,
++
++ uint8_t start_level,
++
++ uint32_t duration
++
++);
++
++typedef struct {
++ uint8_t warm_white;
++ uint8_t cold_white;
++ uint8_t red;
++ uint8_t green;
++ uint8_t blue;
++ uint8_t amber;
++ uint8_t cyan;
++ uint8_t purple;
++} uic_mqtt_dotdot_unify_switch_color_state_t;
++
++typedef struct {
++ bool warm_white;
++ bool cold_white;
++ bool red;
++ bool green;
++ bool blue;
++ bool amber;
++ bool cyan;
++ bool purple;
++} uic_mqtt_dotdot_unify_switch_color_updated_state_t;
++
++typedef sl_status_t (*uic_mqtt_dotdot_unify_switch_color_write_attributes_callback_t)(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint,
++ uic_mqtt_dotdot_callback_call_type_t call_type,
++ uic_mqtt_dotdot_unify_switch_color_state_t,
++ uic_mqtt_dotdot_unify_switch_color_updated_state_t
++);
++
++typedef sl_status_t (*uic_mqtt_dotdot_unify_switch_color_force_read_attributes_callback_t)(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint,
++ uic_mqtt_dotdot_callback_call_type_t call_type,
++ uic_mqtt_dotdot_unify_switch_color_updated_state_t
++);
++
++
++/**
++ * @brief Command fields for UnifySwitchColor/SetColor
++ */
++typedef struct {
++ uint8_t color_component_id;
++
++ uint8_t value;
++
++ uint32_t duration;
++} uic_mqtt_dotdot_unify_switch_color_command_set_color_fields_t;
++
++/**
++ * @brief Command fields for UnifySwitchColor/StartStopChange
++ */
++typedef struct {
++ bool start_stop;
++
++ bool up_down;
++
++ bool ignor_start_level;
++
++ uint8_t color_component_id;
++
++ uint8_t start_level;
++
++ uint32_t duration;
++} uic_mqtt_dotdot_unify_switch_color_command_start_stop_change_fields_t;
++
++
++/**
++ * @brief Setup callback to be called when a
++ * UnifySwitchColor/Commands/set_color is received.
++ *
++ * Setting this callback will not overwrite the previous set callback
++ * @param callback Function to be called on command reception
++ */
++void uic_mqtt_dotdot_unify_switch_color_set_color_callback_set(const uic_mqtt_dotdot_unify_switch_color_set_color_callback_t callback);
++/**
++ * @brief Unsets callback to be called when a
++ * UnifySwitchColor/Commands/set_color is received.
++ *
++ * @param callback Function to be no longer called on command reception
++ */
++void uic_mqtt_dotdot_unify_switch_color_set_color_callback_unset(const uic_mqtt_dotdot_unify_switch_color_set_color_callback_t callback);
++/**
++ * @brief Clears all callbacks registered for when
++ * UnifySwitchColor/Commands/set_color is received.
++ */
++void uic_mqtt_dotdot_unify_switch_color_set_color_callback_clear();
++
++/**
++ * @brief Setup callback to be called when a
++ * +/UnifySwitchColor/GeneratedCommands/set_color is received.
++ *
++ * Setting this callback will not overwrite the previous set callback
++ * @param callback Function to be called on command reception
++ */
++void uic_mqtt_dotdot_unify_switch_color_generated_set_color_callback_set(const uic_mqtt_dotdot_unify_switch_color_set_color_callback_t callback);
++/**
++ * @brief Unsets callback to be called when a
++ * +/UnifySwitchColor/GeneratedCommands/set_color is received.
++ * @param callback Function to be no longer called on command reception
++ */
++void uic_mqtt_dotdot_unify_switch_color_generated_set_color_callback_unset(const uic_mqtt_dotdot_unify_switch_color_set_color_callback_t callback);
++/**
++ * @brief Clears all callbacks registered for when
++ * +/UnifySwitchColor/GeneratedCommands/set_color is received.
++ */
++void uic_mqtt_dotdot_unify_switch_color_generated_set_color_callback_clear();
++/**
++ * @brief Setup callback to be called when a
++ * UnifySwitchColor/Commands/start_stop_change is received.
++ *
++ * Setting this callback will not overwrite the previous set callback
++ * @param callback Function to be called on command reception
++ */
++void uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback_set(const uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback_t callback);
++/**
++ * @brief Unsets callback to be called when a
++ * UnifySwitchColor/Commands/start_stop_change is received.
++ *
++ * @param callback Function to be no longer called on command reception
++ */
++void uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback_unset(const uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback_t callback);
++/**
++ * @brief Clears all callbacks registered for when
++ * UnifySwitchColor/Commands/start_stop_change is received.
++ */
++void uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback_clear();
++
++/**
++ * @brief Setup callback to be called when a
++ * +/UnifySwitchColor/GeneratedCommands/start_stop_change is received.
++ *
++ * Setting this callback will not overwrite the previous set callback
++ * @param callback Function to be called on command reception
++ */
++void uic_mqtt_dotdot_unify_switch_color_generated_start_stop_change_callback_set(const uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback_t callback);
++/**
++ * @brief Unsets callback to be called when a
++ * +/UnifySwitchColor/GeneratedCommands/start_stop_change is received.
++ * @param callback Function to be no longer called on command reception
++ */
++void uic_mqtt_dotdot_unify_switch_color_generated_start_stop_change_callback_unset(const uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback_t callback);
++/**
++ * @brief Clears all callbacks registered for when
++ * +/UnifySwitchColor/GeneratedCommands/start_stop_change is received.
++ */
++void uic_mqtt_dotdot_unify_switch_color_generated_start_stop_change_callback_clear();
++
++/**
++ * @brief Setup a callback for WriteAttribute to be called when a
++ * +/unify_switch_color/Commands/WriteAttributes is received.
++ *
++ * Setting this callback will not overwrite the previous set callback
++ * @param callback Function to be called on command reception
++ */
++void uic_mqtt_dotdot_set_unify_switch_color_write_attributes_callback(
++ const uic_mqtt_dotdot_unify_switch_color_write_attributes_callback_t callback
++);
++/**
++ * @brief Unsets a callback for WriteAttribute to be called when a
++ * +/unify_switch_color/Commands/WriteAttributes is received.
++ * @param callback Function to be no longer called on command reception
++ */
++void uic_mqtt_dotdot_unset_unify_switch_color_write_attributes_callback(
++ const uic_mqtt_dotdot_unify_switch_color_write_attributes_callback_t callback
++);
++/**
++ * @brief Clears all callbacks registered for when
++ * +/unify_switch_color/Commands/WriteAttributes is received.
++ */
++void uic_mqtt_dotdot_clear_unify_switch_color_write_attributes_callbacks();
++
++/**
++ * @brief Setup a callback for ForceReadAttributes to be called when a
++ * +/unify_switch_color/Commands/ForceReadAttributes is received.
++ *
++ * Setting this callback will not overwrite the previous set callback
++ * @param callback Function to be called on command reception
++ */
++void uic_mqtt_dotdot_set_unify_switch_color_force_read_attributes_callback(
++ const uic_mqtt_dotdot_unify_switch_color_force_read_attributes_callback_t callback
++);
++/**
++ * @brief Unsets a callback for ForceReadAttributes to be called when a
++ * +/unify_switch_color/Commands/ForceReadAttributes is received.
++ *
++ * @param callback Function to be no longer called on command reception
++ */
++void uic_mqtt_dotdot_unset_unify_switch_color_force_read_attributes_callback(
++ const uic_mqtt_dotdot_unify_switch_color_force_read_attributes_callback_t callback
++);
++/**
++ * @brief Clears all callbacks registered for when
++ * +/unify_switch_color/Commands/ForceReadAttributes is received.
++ */
++void uic_mqtt_dotdot_clear_unify_switch_color_force_read_attributes_callbacks();
++
++/**
++ * @brief Publish the attribute; UnifySwitchColor/Attributes/WarmWhite
++ *
++ * @param base_topic topic prefix to publish, /warm_white
++ * will be appended
++ * @param value Value to publish
++ * @param publish_type Whether to publish as Desired, Reported, or Both.
++ *
++ * @returns SL_STATUS_OK on success
++ */
++sl_status_t uic_mqtt_dotdot_unify_switch_color_warm_white_publish(
++ const char *base_topic,
++ uint8_t value,
++ uic_mqtt_dotdot_attribute_publish_type_t publish_type
++);
++
++/**
++ * @brief Unretains a published attribute; UnifySwitchColor/Attributes/WarmWhite
++ *
++ * @param base_topic topic prefix to publish, /warm_white
++ * will be appended
++ * @param publish_type Whether to publish as Desired, Reported, or Both.
++ *
++ * @returns SL_STATUS_OK on success
++ */
++sl_status_t uic_mqtt_dotdot_unify_switch_color_warm_white_unretain(
++ const char *base_topic,
++ uic_mqtt_dotdot_attribute_publish_type_t publish_type
++);
++
++/**
++ * @brief Publish the attribute; UnifySwitchColor/Attributes/ColdWhite
++ *
++ * @param base_topic topic prefix to publish, /cold_white
++ * will be appended
++ * @param value Value to publish
++ * @param publish_type Whether to publish as Desired, Reported, or Both.
++ *
++ * @returns SL_STATUS_OK on success
++ */
++sl_status_t uic_mqtt_dotdot_unify_switch_color_cold_white_publish(
++ const char *base_topic,
++ uint8_t value,
++ uic_mqtt_dotdot_attribute_publish_type_t publish_type
++);
++
++/**
++ * @brief Unretains a published attribute; UnifySwitchColor/Attributes/ColdWhite
++ *
++ * @param base_topic topic prefix to publish, /cold_white
++ * will be appended
++ * @param publish_type Whether to publish as Desired, Reported, or Both.
++ *
++ * @returns SL_STATUS_OK on success
++ */
++sl_status_t uic_mqtt_dotdot_unify_switch_color_cold_white_unretain(
++ const char *base_topic,
++ uic_mqtt_dotdot_attribute_publish_type_t publish_type
++);
++
++/**
++ * @brief Publish the attribute; UnifySwitchColor/Attributes/Red
++ *
++ * @param base_topic topic prefix to publish, /red
++ * will be appended
++ * @param value Value to publish
++ * @param publish_type Whether to publish as Desired, Reported, or Both.
++ *
++ * @returns SL_STATUS_OK on success
++ */
++sl_status_t uic_mqtt_dotdot_unify_switch_color_red_publish(
++ const char *base_topic,
++ uint8_t value,
++ uic_mqtt_dotdot_attribute_publish_type_t publish_type
++);
++
++/**
++ * @brief Unretains a published attribute; UnifySwitchColor/Attributes/Red
++ *
++ * @param base_topic topic prefix to publish, /red
++ * will be appended
++ * @param publish_type Whether to publish as Desired, Reported, or Both.
++ *
++ * @returns SL_STATUS_OK on success
++ */
++sl_status_t uic_mqtt_dotdot_unify_switch_color_red_unretain(
++ const char *base_topic,
++ uic_mqtt_dotdot_attribute_publish_type_t publish_type
++);
++
++/**
++ * @brief Publish the attribute; UnifySwitchColor/Attributes/Green
++ *
++ * @param base_topic topic prefix to publish, /green
++ * will be appended
++ * @param value Value to publish
++ * @param publish_type Whether to publish as Desired, Reported, or Both.
++ *
++ * @returns SL_STATUS_OK on success
++ */
++sl_status_t uic_mqtt_dotdot_unify_switch_color_green_publish(
++ const char *base_topic,
++ uint8_t value,
++ uic_mqtt_dotdot_attribute_publish_type_t publish_type
++);
++
++/**
++ * @brief Unretains a published attribute; UnifySwitchColor/Attributes/Green
++ *
++ * @param base_topic topic prefix to publish, /green
++ * will be appended
++ * @param publish_type Whether to publish as Desired, Reported, or Both.
++ *
++ * @returns SL_STATUS_OK on success
++ */
++sl_status_t uic_mqtt_dotdot_unify_switch_color_green_unretain(
++ const char *base_topic,
++ uic_mqtt_dotdot_attribute_publish_type_t publish_type
++);
++
++/**
++ * @brief Publish the attribute; UnifySwitchColor/Attributes/Blue
++ *
++ * @param base_topic topic prefix to publish, /blue
++ * will be appended
++ * @param value Value to publish
++ * @param publish_type Whether to publish as Desired, Reported, or Both.
++ *
++ * @returns SL_STATUS_OK on success
++ */
++sl_status_t uic_mqtt_dotdot_unify_switch_color_blue_publish(
++ const char *base_topic,
++ uint8_t value,
++ uic_mqtt_dotdot_attribute_publish_type_t publish_type
++);
++
++/**
++ * @brief Unretains a published attribute; UnifySwitchColor/Attributes/Blue
++ *
++ * @param base_topic topic prefix to publish, /blue
++ * will be appended
++ * @param publish_type Whether to publish as Desired, Reported, or Both.
++ *
++ * @returns SL_STATUS_OK on success
++ */
++sl_status_t uic_mqtt_dotdot_unify_switch_color_blue_unretain(
++ const char *base_topic,
++ uic_mqtt_dotdot_attribute_publish_type_t publish_type
++);
++
++/**
++ * @brief Publish the attribute; UnifySwitchColor/Attributes/Amber
++ *
++ * @param base_topic topic prefix to publish, /amber
++ * will be appended
++ * @param value Value to publish
++ * @param publish_type Whether to publish as Desired, Reported, or Both.
++ *
++ * @returns SL_STATUS_OK on success
++ */
++sl_status_t uic_mqtt_dotdot_unify_switch_color_amber_publish(
++ const char *base_topic,
++ uint8_t value,
++ uic_mqtt_dotdot_attribute_publish_type_t publish_type
++);
++
++/**
++ * @brief Unretains a published attribute; UnifySwitchColor/Attributes/Amber
++ *
++ * @param base_topic topic prefix to publish, /amber
++ * will be appended
++ * @param publish_type Whether to publish as Desired, Reported, or Both.
++ *
++ * @returns SL_STATUS_OK on success
++ */
++sl_status_t uic_mqtt_dotdot_unify_switch_color_amber_unretain(
++ const char *base_topic,
++ uic_mqtt_dotdot_attribute_publish_type_t publish_type
++);
++
++/**
++ * @brief Publish the attribute; UnifySwitchColor/Attributes/Cyan
++ *
++ * @param base_topic topic prefix to publish, /cyan
++ * will be appended
++ * @param value Value to publish
++ * @param publish_type Whether to publish as Desired, Reported, or Both.
++ *
++ * @returns SL_STATUS_OK on success
++ */
++sl_status_t uic_mqtt_dotdot_unify_switch_color_cyan_publish(
++ const char *base_topic,
++ uint8_t value,
++ uic_mqtt_dotdot_attribute_publish_type_t publish_type
++);
++
++/**
++ * @brief Unretains a published attribute; UnifySwitchColor/Attributes/Cyan
++ *
++ * @param base_topic topic prefix to publish, /cyan
++ * will be appended
++ * @param publish_type Whether to publish as Desired, Reported, or Both.
++ *
++ * @returns SL_STATUS_OK on success
++ */
++sl_status_t uic_mqtt_dotdot_unify_switch_color_cyan_unretain(
++ const char *base_topic,
++ uic_mqtt_dotdot_attribute_publish_type_t publish_type
++);
++
++/**
++ * @brief Publish the attribute; UnifySwitchColor/Attributes/Purple
++ *
++ * @param base_topic topic prefix to publish, /purple
++ * will be appended
++ * @param value Value to publish
++ * @param publish_type Whether to publish as Desired, Reported, or Both.
++ *
++ * @returns SL_STATUS_OK on success
++ */
++sl_status_t uic_mqtt_dotdot_unify_switch_color_purple_publish(
++ const char *base_topic,
++ uint8_t value,
++ uic_mqtt_dotdot_attribute_publish_type_t publish_type
++);
++
++/**
++ * @brief Unretains a published attribute; UnifySwitchColor/Attributes/Purple
++ *
++ * @param base_topic topic prefix to publish, /purple
++ * will be appended
++ * @param publish_type Whether to publish as Desired, Reported, or Both.
++ *
++ * @returns SL_STATUS_OK on success
++ */
++sl_status_t uic_mqtt_dotdot_unify_switch_color_purple_unretain(
++ const char *base_topic,
++ uic_mqtt_dotdot_attribute_publish_type_t publish_type
++);
++
++
++/**
++ * @brief Publish the UnifySwitchColor/ClusterRevision attribute
++ *
++ * @param base_topic topic prefix to publish, /UnifySwitchColor/Attributes/ClusterRevision
++ * will be appended.
++ * @param value Value to publish.
++ */
++void uic_mqtt_dotdot_unify_switch_color_publish_cluster_revision(const char* base_topic, uint16_t value);
++
++/**
++ * @brief Unretain a publication to UnifySwitchColor/ClusterRevision attribute
++ *
++ * @param base_topic topic prefix to publish, /UnifySwitchColor/Attributes/ClusterRevision
++ * will be appended.
++ */
++void uic_mqtt_dotdot_unify_switch_color_unretain_cluster_revision(const char* base_topic);
++
++/**
++ * @brief Publish the SupportedCommands for UNID/EndPoint for the UnifySwitchColor Cluster
++ *
++ * This function will iterate over all Commands in the UnifySwitchColor Cluster and
++ * call all registered callback functions with UNID/endpoint, and
++ * callback_type = UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK.
++ * All Cluster Command callback functions that return SL_STATUS_OK
++ * will be added to the list of supported commands and published.
++ *
++ * @param unid
++ * @param endpoint
++ */
++void uic_mqtt_dotdot_unify_switch_color_publish_supported_commands(
++ const dotdot_unid_t unid,
++ dotdot_endpoint_id_t endpoint);
++
++/**
++ * @brief Publish an empty array of SupportedCommands for UNID/EndPoint for
++ * the UnifySwitchColor Cluster
++ *
++ * @param unid
++ * @param endpoint )
++ */
++void uic_mqtt_dotdot_unify_switch_color_publish_empty_supported_commands(
++ const dotdot_unid_t unid
++ ,dotdot_endpoint_id_t endpoint);
+
+ /**
+ * @brief Publish the SupportedCommands for UNID/EndPoint
+diff --git a/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_attributes.h b/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_attributes.h
+index 9f094654e3..8cba2ecb59 100644
+--- a/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_attributes.h
++++ b/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_attributes.h
+@@ -5230,6 +5230,63 @@ typedef sl_status_t (*uic_mqtt_dotdot_unify_humidity_control_attribute_auto_setp
+ uic_mqtt_dotdot_attribute_update_type_t update_type,
+ uint8_t auto_setpoint_precision
+ );
++// Callback types used by the unify_switch_color cluster
++typedef sl_status_t (*uic_mqtt_dotdot_unify_switch_color_attribute_warm_white_callback_t)(
++ dotdot_unid_t unid,
++ dotdot_endpoint_id_t endpoint,
++ bool unretained,
++ uic_mqtt_dotdot_attribute_update_type_t update_type,
++ uint8_t warm_white
++);
++typedef sl_status_t (*uic_mqtt_dotdot_unify_switch_color_attribute_cold_white_callback_t)(
++ dotdot_unid_t unid,
++ dotdot_endpoint_id_t endpoint,
++ bool unretained,
++ uic_mqtt_dotdot_attribute_update_type_t update_type,
++ uint8_t cold_white
++);
++typedef sl_status_t (*uic_mqtt_dotdot_unify_switch_color_attribute_red_callback_t)(
++ dotdot_unid_t unid,
++ dotdot_endpoint_id_t endpoint,
++ bool unretained,
++ uic_mqtt_dotdot_attribute_update_type_t update_type,
++ uint8_t red
++);
++typedef sl_status_t (*uic_mqtt_dotdot_unify_switch_color_attribute_green_callback_t)(
++ dotdot_unid_t unid,
++ dotdot_endpoint_id_t endpoint,
++ bool unretained,
++ uic_mqtt_dotdot_attribute_update_type_t update_type,
++ uint8_t green
++);
++typedef sl_status_t (*uic_mqtt_dotdot_unify_switch_color_attribute_blue_callback_t)(
++ dotdot_unid_t unid,
++ dotdot_endpoint_id_t endpoint,
++ bool unretained,
++ uic_mqtt_dotdot_attribute_update_type_t update_type,
++ uint8_t blue
++);
++typedef sl_status_t (*uic_mqtt_dotdot_unify_switch_color_attribute_amber_callback_t)(
++ dotdot_unid_t unid,
++ dotdot_endpoint_id_t endpoint,
++ bool unretained,
++ uic_mqtt_dotdot_attribute_update_type_t update_type,
++ uint8_t amber
++);
++typedef sl_status_t (*uic_mqtt_dotdot_unify_switch_color_attribute_cyan_callback_t)(
++ dotdot_unid_t unid,
++ dotdot_endpoint_id_t endpoint,
++ bool unretained,
++ uic_mqtt_dotdot_attribute_update_type_t update_type,
++ uint8_t cyan
++);
++typedef sl_status_t (*uic_mqtt_dotdot_unify_switch_color_attribute_purple_callback_t)(
++ dotdot_unid_t unid,
++ dotdot_endpoint_id_t endpoint,
++ bool unretained,
++ uic_mqtt_dotdot_attribute_update_type_t update_type,
++ uint8_t purple
++);
+
+ #ifdef __cplusplus
+ extern "C" {
+@@ -10054,6 +10111,62 @@ void uic_mqtt_dotdot_unify_humidity_control_attribute_auto_setpoint_scale_callba
+ void uic_mqtt_dotdot_unify_humidity_control_attribute_auto_setpoint_precision_callback_set(const uic_mqtt_dotdot_unify_humidity_control_attribute_auto_setpoint_precision_callback_t callback);
+
+
++/**
++ * Initializes the attributes features for the UnifySwitchColor cluster,
++ * allowing to receive attribute updates from other UNIDs.
++ */
++sl_status_t uic_mqtt_dotdot_unify_switch_color_attributes_init();
++
++/**
++ * Setup callback to be called when a
++ * UnifySwitchColor/Attributes/warm_white/# is received. Setting
++ * this callback will overwrite the previous set callback
++ */
++void uic_mqtt_dotdot_unify_switch_color_attribute_warm_white_callback_set(const uic_mqtt_dotdot_unify_switch_color_attribute_warm_white_callback_t callback);
++/**
++ * Setup callback to be called when a
++ * UnifySwitchColor/Attributes/cold_white/# is received. Setting
++ * this callback will overwrite the previous set callback
++ */
++void uic_mqtt_dotdot_unify_switch_color_attribute_cold_white_callback_set(const uic_mqtt_dotdot_unify_switch_color_attribute_cold_white_callback_t callback);
++/**
++ * Setup callback to be called when a
++ * UnifySwitchColor/Attributes/red/# is received. Setting
++ * this callback will overwrite the previous set callback
++ */
++void uic_mqtt_dotdot_unify_switch_color_attribute_red_callback_set(const uic_mqtt_dotdot_unify_switch_color_attribute_red_callback_t callback);
++/**
++ * Setup callback to be called when a
++ * UnifySwitchColor/Attributes/green/# is received. Setting
++ * this callback will overwrite the previous set callback
++ */
++void uic_mqtt_dotdot_unify_switch_color_attribute_green_callback_set(const uic_mqtt_dotdot_unify_switch_color_attribute_green_callback_t callback);
++/**
++ * Setup callback to be called when a
++ * UnifySwitchColor/Attributes/blue/# is received. Setting
++ * this callback will overwrite the previous set callback
++ */
++void uic_mqtt_dotdot_unify_switch_color_attribute_blue_callback_set(const uic_mqtt_dotdot_unify_switch_color_attribute_blue_callback_t callback);
++/**
++ * Setup callback to be called when a
++ * UnifySwitchColor/Attributes/amber/# is received. Setting
++ * this callback will overwrite the previous set callback
++ */
++void uic_mqtt_dotdot_unify_switch_color_attribute_amber_callback_set(const uic_mqtt_dotdot_unify_switch_color_attribute_amber_callback_t callback);
++/**
++ * Setup callback to be called when a
++ * UnifySwitchColor/Attributes/cyan/# is received. Setting
++ * this callback will overwrite the previous set callback
++ */
++void uic_mqtt_dotdot_unify_switch_color_attribute_cyan_callback_set(const uic_mqtt_dotdot_unify_switch_color_attribute_cyan_callback_t callback);
++/**
++ * Setup callback to be called when a
++ * UnifySwitchColor/Attributes/purple/# is received. Setting
++ * this callback will overwrite the previous set callback
++ */
++void uic_mqtt_dotdot_unify_switch_color_attribute_purple_callback_set(const uic_mqtt_dotdot_unify_switch_color_attribute_purple_callback_t callback);
++
++
+ #ifdef __cplusplus
+ }
+ #endif // __cplusplus
+diff --git a/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_generated_commands.h b/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_generated_commands.h
+index 96e33e47d2..e1f17dad77 100644
+--- a/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_generated_commands.h
++++ b/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_generated_commands.h
+@@ -5461,6 +5461,70 @@ void uic_mqtt_dotdot_unify_humidity_control_publish_generated_write_attributes_c
+ uic_mqtt_dotdot_unify_humidity_control_updated_state_t attribute_list
+ );
+
++/**
++ * @brief Publishes an incoming/generated SetColor command for
++ * the UnifySwitchColor cluster.
++ *
++ * Publication will be made at the following topic
++ * ucl/by-unid/UNID/epID/UnifySwitchColor/GeneratedCommands/SetColor
++ *
++ * @param unid The UNID of the node that sent us the command.
++ *
++ * @param endpoint The Endpoint ID of the node that sent us the command.
++ *
++ *
++ * @param fields Struct pointer with the fields value of the command
++ *
++ */
++void uic_mqtt_dotdot_unify_switch_color_publish_generated_set_color_command(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint,
++ const uic_mqtt_dotdot_unify_switch_color_command_set_color_fields_t *fields
++
++);
++/**
++ * @brief Publishes an incoming/generated StartStopChange command for
++ * the UnifySwitchColor cluster.
++ *
++ * Publication will be made at the following topic
++ * ucl/by-unid/UNID/epID/UnifySwitchColor/GeneratedCommands/StartStopChange
++ *
++ * @param unid The UNID of the node that sent us the command.
++ *
++ * @param endpoint The Endpoint ID of the node that sent us the command.
++ *
++ *
++ * @param fields Struct pointer with the fields value of the command
++ *
++ */
++void uic_mqtt_dotdot_unify_switch_color_publish_generated_start_stop_change_command(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint,
++ const uic_mqtt_dotdot_unify_switch_color_command_start_stop_change_fields_t *fields
++
++);
++
++/**
++ * @brief Publishes an incoming/generated WriteAttributes command for
++ * the UnifySwitchColor cluster.
++ *
++ * Publication will be made at the following topic
++ * ucl/by-unid/UNID/epID/UnifySwitchColor/GeneratedCommands/WriteAttributes
++ *
++ * @param unid The UNID of the node that sent us the command.
++ *
++ * @param endpoint The Endpoint ID of the node that sent us the command.
++ *
++ * @param attribute_values Values to assign to the attributes
++ * @param attribute_list List of attributes that are written
++ */
++void uic_mqtt_dotdot_unify_switch_color_publish_generated_write_attributes_command(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint,
++ uic_mqtt_dotdot_unify_switch_color_state_t attribute_values,
++ uic_mqtt_dotdot_unify_switch_color_updated_state_t attribute_list
++);
++
+
+ #ifdef __cplusplus
+ }
+diff --git a/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_group_commands.h b/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_group_commands.h
+index e052483320..6bf8346dae 100644
+--- a/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_group_commands.h
++++ b/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_group_commands.h
+@@ -4073,6 +4073,55 @@ void uic_mqtt_dotdot_by_group_unify_humidity_control_write_attributes_callback_s
+
+
+
++/**
++ * @brief Callback signature for by-group UnifySwitchColor::SetColor command.
++ */
++typedef void (*uic_mqtt_dotdot_by_group_unify_switch_color_set_color_callback_t)(
++ const dotdot_group_id_t group_id,
++ const uic_mqtt_dotdot_unify_switch_color_command_set_color_fields_t *fields
++);
++
++/**
++ * Setup handler to be called when a
++ * ucl/by-group/+/UnifySwitchColor/set_color is received.
++ * Setting this callback will overwrite the previous set callback.
++ *
++ */
++void uic_mqtt_dotdot_by_group_unify_switch_color_set_color_callback_set(const uic_mqtt_dotdot_by_group_unify_switch_color_set_color_callback_t callback);
++
++/**
++ * @brief Callback signature for by-group UnifySwitchColor::StartStopChange command.
++ */
++typedef void (*uic_mqtt_dotdot_by_group_unify_switch_color_start_stop_change_callback_t)(
++ const dotdot_group_id_t group_id,
++ const uic_mqtt_dotdot_unify_switch_color_command_start_stop_change_fields_t *fields
++);
++
++/**
++ * Setup handler to be called when a
++ * ucl/by-group/+/UnifySwitchColor/start_stop_change is received.
++ * Setting this callback will overwrite the previous set callback.
++ *
++ */
++void uic_mqtt_dotdot_by_group_unify_switch_color_start_stop_change_callback_set(const uic_mqtt_dotdot_by_group_unify_switch_color_start_stop_change_callback_t callback);
++
++typedef void (*uic_mqtt_dotdot_by_group_unify_switch_color_write_attributes_callback_t)(
++ const dotdot_group_id_t group_id,
++ uic_mqtt_dotdot_unify_switch_color_state_t,
++ uic_mqtt_dotdot_unify_switch_color_updated_state_t
++);
++
++/**
++ * Setup a callback for WriteAttribute to be called when a
++ * ucl/by-group/+/unify_switch_color/Commands/WriteAttributes is received.
++ * Setting this callback will overwrite any previously set callback.
++ */
++void uic_mqtt_dotdot_by_group_unify_switch_color_write_attributes_callback_set(
++ const uic_mqtt_dotdot_by_group_unify_switch_color_write_attributes_callback_t callback
++);
++
++
++
+ #ifdef __cplusplus
+ }
+ #endif // __cplusplus
+diff --git a/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_send_commands.h b/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_send_commands.h
+index 3d8d69ac9e..fdbeda4042 100644
+--- a/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_send_commands.h
++++ b/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_send_commands.h
+@@ -7926,6 +7926,84 @@ void uic_mqtt_dotdot_unify_humidity_control_publish_setpoint_set_command_to_grou
+ const uic_mqtt_dotdot_unify_humidity_control_command_setpoint_set_fields_t *fields
+
+ );
++/**
++ * @brief Sends/Publishes a SetColor command for
++ * the UnifySwitchColor cluster to a destination.
++ *
++ * Publication will be made at the following topic
++ * ucl/by-unid/UNID/epID/UnifySwitchColor/Commands/SetColor
++ *
++ * @param destination_unid The UNID of the node that should receive the command.
++ *
++ * @param destination_endpoint The Endpoint ID of the node that should receive the command.
++ *
++ *
++ * @param fields Struct pointer with the fields value of the command
++ *
++ */
++void uic_mqtt_dotdot_unify_switch_color_publish_set_color_command(
++ const dotdot_unid_t destination_unid,
++ const dotdot_endpoint_id_t destination_endpoint,
++ const uic_mqtt_dotdot_unify_switch_color_command_set_color_fields_t *fields
++
++);
++
++/**
++ * @brief Sends/Publishes a SetColor command for
++ * the UnifySwitchColor cluster to a group.
++ *
++ * Publication will be made at the following topic
++ * ucl/by-group/GroupID/UnifySwitchColor/Commands/SetColor
++ *
++ * @param destination_group_id The GroupID that should receive the command.
++ *
++ * @param fields Struct pointer with the fields value of the command
++ *
++ */
++void uic_mqtt_dotdot_unify_switch_color_publish_set_color_command_to_group(
++ uint16_t destination_group_id,
++ const uic_mqtt_dotdot_unify_switch_color_command_set_color_fields_t *fields
++
++);
++/**
++ * @brief Sends/Publishes a StartStopChange command for
++ * the UnifySwitchColor cluster to a destination.
++ *
++ * Publication will be made at the following topic
++ * ucl/by-unid/UNID/epID/UnifySwitchColor/Commands/StartStopChange
++ *
++ * @param destination_unid The UNID of the node that should receive the command.
++ *
++ * @param destination_endpoint The Endpoint ID of the node that should receive the command.
++ *
++ *
++ * @param fields Struct pointer with the fields value of the command
++ *
++ */
++void uic_mqtt_dotdot_unify_switch_color_publish_start_stop_change_command(
++ const dotdot_unid_t destination_unid,
++ const dotdot_endpoint_id_t destination_endpoint,
++ const uic_mqtt_dotdot_unify_switch_color_command_start_stop_change_fields_t *fields
++
++);
++
++/**
++ * @brief Sends/Publishes a StartStopChange command for
++ * the UnifySwitchColor cluster to a group.
++ *
++ * Publication will be made at the following topic
++ * ucl/by-group/GroupID/UnifySwitchColor/Commands/StartStopChange
++ *
++ * @param destination_group_id The GroupID that should receive the command.
++ *
++ * @param fields Struct pointer with the fields value of the command
++ *
++ */
++void uic_mqtt_dotdot_unify_switch_color_publish_start_stop_change_command_to_group(
++ uint16_t destination_group_id,
++ const uic_mqtt_dotdot_unify_switch_color_command_start_stop_change_fields_t *fields
++
++);
+
+
+ #ifdef __cplusplus
+diff --git a/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_supported_generated_commands.h b/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_supported_generated_commands.h
+index 4c1c15b4eb..7872bdcec3 100644
+--- a/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_supported_generated_commands.h
++++ b/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_supported_generated_commands.h
+@@ -1742,6 +1742,36 @@ void uic_mqtt_dotdot_unify_humidity_control_publish_supported_generated_commands
+ );
+
+
++/**
++ * @brief Struct containing the list of commands for UnifySwitchColor
++ */
++typedef struct _uic_mqtt_dotdot_unify_switch_color_supported_commands_ {
++ bool set_color;
++ bool start_stop_change;
++ bool write_attributes;
++} uic_mqtt_dotdot_unify_switch_color_supported_commands_t;
++
++/**
++ * @brief Sends/Publishes a the SupportedGenerated commands for
++ * the UnifySwitchColor cluster for a UNID/Endpoint
++ *
++ * Publication will be made at the following topic
++ * ucl/by-unid/UNID/epID/UnifySwitchColor/SupportedGeneratedCommands
++ *
++ * @param unid The UNID of the node on behalf of which the advertisment is made
++ *
++ * @param endpoint The Endpoint ID of the node on behalf of which the advertisment is made
++ *
++ * @param command_list Struct pointer with the fields value indicating if
++ * individual commands can be generated.
++ */
++void uic_mqtt_dotdot_unify_switch_color_publish_supported_generated_commands(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint,
++ const uic_mqtt_dotdot_unify_switch_color_supported_commands_t *command_list
++);
++
++
+
+ #ifdef __cplusplus
+ }
+diff --git a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt.cpp b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt.cpp
+index 2ad8e173db..0a2f0bbdb7 100644
+--- a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt.cpp
++++ b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt.cpp
+@@ -99777,6 +99777,1164 @@ sl_status_t uic_mqtt_dotdot_unify_humidity_control_init()
+ return SL_STATUS_OK;
+ }
+
++// Callbacks pointers
++static std::set uic_mqtt_dotdot_unify_switch_color_set_color_callback;
++static std::set uic_mqtt_dotdot_unify_switch_color_generated_set_color_callback;
++static std::set uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback;
++static std::set uic_mqtt_dotdot_unify_switch_color_generated_start_stop_change_callback;
++static std::set uic_mqtt_dotdot_unify_switch_color_write_attributes_callback;
++static std::set uic_mqtt_dotdot_unify_switch_color_force_read_attributes_callback;
++
++// Callbacks setters
++void uic_mqtt_dotdot_unify_switch_color_set_color_callback_set(const uic_mqtt_dotdot_unify_switch_color_set_color_callback_t callback)
++{
++ if (callback != nullptr) {
++ uic_mqtt_dotdot_unify_switch_color_set_color_callback.insert(callback);
++ }
++}
++void uic_mqtt_dotdot_unify_switch_color_set_color_callback_unset(const uic_mqtt_dotdot_unify_switch_color_set_color_callback_t callback)
++{
++ uic_mqtt_dotdot_unify_switch_color_set_color_callback.erase(callback);
++}
++void uic_mqtt_dotdot_unify_switch_color_set_color_callback_clear()
++{
++ uic_mqtt_dotdot_unify_switch_color_set_color_callback.clear();
++}
++std::set& get_uic_mqtt_dotdot_unify_switch_color_set_color_callback()
++{
++ return uic_mqtt_dotdot_unify_switch_color_set_color_callback;
++}
++
++void uic_mqtt_dotdot_unify_switch_color_generated_set_color_callback_set(const uic_mqtt_dotdot_unify_switch_color_set_color_callback_t callback)
++{
++ if (callback != nullptr) {
++ uic_mqtt_dotdot_unify_switch_color_generated_set_color_callback.insert(callback);
++ }
++}
++void uic_mqtt_dotdot_unify_switch_color_generated_set_color_callback_unset(const uic_mqtt_dotdot_unify_switch_color_set_color_callback_t callback)
++{
++ uic_mqtt_dotdot_unify_switch_color_generated_set_color_callback.erase(callback);
++}
++void uic_mqtt_dotdot_unify_switch_color_generated_set_color_callback_clear()
++{
++ uic_mqtt_dotdot_unify_switch_color_generated_set_color_callback.clear();
++}
++void uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback_set(const uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback_t callback)
++{
++ if (callback != nullptr) {
++ uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback.insert(callback);
++ }
++}
++void uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback_unset(const uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback_t callback)
++{
++ uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback.erase(callback);
++}
++void uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback_clear()
++{
++ uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback.clear();
++}
++std::set& get_uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback()
++{
++ return uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback;
++}
++
++void uic_mqtt_dotdot_unify_switch_color_generated_start_stop_change_callback_set(const uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback_t callback)
++{
++ if (callback != nullptr) {
++ uic_mqtt_dotdot_unify_switch_color_generated_start_stop_change_callback.insert(callback);
++ }
++}
++void uic_mqtt_dotdot_unify_switch_color_generated_start_stop_change_callback_unset(const uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback_t callback)
++{
++ uic_mqtt_dotdot_unify_switch_color_generated_start_stop_change_callback.erase(callback);
++}
++void uic_mqtt_dotdot_unify_switch_color_generated_start_stop_change_callback_clear()
++{
++ uic_mqtt_dotdot_unify_switch_color_generated_start_stop_change_callback.clear();
++}
++
++void uic_mqtt_dotdot_set_unify_switch_color_write_attributes_callback(
++ const uic_mqtt_dotdot_unify_switch_color_write_attributes_callback_t callback)
++{
++ if (callback != nullptr) {
++ uic_mqtt_dotdot_unify_switch_color_write_attributes_callback.insert(callback);
++ }
++}
++void uic_mqtt_dotdot_unset_unify_switch_color_write_attributes_callback(
++ const uic_mqtt_dotdot_unify_switch_color_write_attributes_callback_t callback)
++{
++ uic_mqtt_dotdot_unify_switch_color_write_attributes_callback.erase(callback);
++}
++void uic_mqtt_dotdot_clear_unify_switch_color_write_attributes_callbacks()
++{
++ uic_mqtt_dotdot_unify_switch_color_write_attributes_callback.clear();
++}
++std::set& get_uic_mqtt_dotdot_unify_switch_color_write_attributes_callback()
++{
++ return uic_mqtt_dotdot_unify_switch_color_write_attributes_callback;
++}
++
++void uic_mqtt_dotdot_set_unify_switch_color_force_read_attributes_callback(
++ const uic_mqtt_dotdot_unify_switch_color_force_read_attributes_callback_t callback)
++{
++ if (callback != nullptr) {
++ uic_mqtt_dotdot_unify_switch_color_force_read_attributes_callback.insert(callback);
++ }
++}
++void uic_mqtt_dotdot_unset_unify_switch_color_force_read_attributes_callback(
++ const uic_mqtt_dotdot_unify_switch_color_force_read_attributes_callback_t callback)
++{
++ uic_mqtt_dotdot_unify_switch_color_force_read_attributes_callback.erase(callback);
++}
++void uic_mqtt_dotdot_clear_unify_switch_color_force_read_attributes_callbacks()
++{
++ uic_mqtt_dotdot_unify_switch_color_force_read_attributes_callback.clear();
++}
++
++
++// Callback function for incoming publications on ucl/by-unid/+/+/UnifySwitchColor/Commands/SetColor
++void uic_mqtt_dotdot_on_unify_switch_color_set_color(
++ const char *topic,
++ const char *message,
++ const size_t message_length)
++{
++ if (message_length == 0 || (uic_mqtt_dotdot_unify_switch_color_set_color_callback.empty())) {
++ return;
++ }
++
++ std::string unid;
++ uint8_t endpoint = 0; // Default value for endpoint-less topics.
++ if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) {
++ sl_log_debug(LOG_TAG,
++ "Error parsing UNID / Endpoint ID from topic %s. Ignoring",
++ topic);
++ return;
++ }
++
++ uint8_t color_component_id = {};
++ uint8_t value = {};
++ uint32_t duration = {};
++
++
++ nlohmann::json jsn;
++ try {
++ jsn = nlohmann::json::parse(std::string(message));
++
++
++ uic_mqtt_dotdot_parse_unify_switch_color_set_color(
++ jsn,
++ color_component_id,
++
++ value,
++
++ duration
++ );
++
++ } catch (const nlohmann::json::parse_error& e) {
++ // Catch JSON object field parsing errors
++ sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UnifySwitchColor", "SetColor");
++ return;
++ } catch (const nlohmann::json::exception& e) {
++ // Catch JSON object field parsing errors
++ sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifySwitchColor", "SetColor", e.what());
++ return;
++ } catch (const std::exception& e) {
++ sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifySwitchColor", "SetColor", "");
++ return;
++ }
++
++
++
++ for (const auto& callback: uic_mqtt_dotdot_unify_switch_color_set_color_callback){
++ callback(
++ static_cast(unid.c_str()),
++ endpoint,
++ UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL,
++ color_component_id,
++
++ value,
++
++ duration
++
++ );
++ }
++
++}
++
++// Callback function for incoming publications on ucl/by-unid/+/+/UnifySwitchColor/GeneratedCommands/SetColor
++static void uic_mqtt_dotdot_on_generated_unify_switch_color_set_color(
++ const char *topic,
++ const char *message,
++ const size_t message_length)
++{
++ if (message_length == 0 || (uic_mqtt_dotdot_unify_switch_color_generated_set_color_callback.empty())) {
++ return;
++ }
++
++ std::string unid;
++ uint8_t endpoint = 0; // Default value for endpoint-less topics.
++ if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) {
++ sl_log_debug(LOG_TAG,
++ "Error parsing UNID / Endpoint ID from topic %s. Ignoring",
++ topic);
++ return;
++ }
++
++ uint8_t color_component_id = {};
++ uint8_t value = {};
++ uint32_t duration = {};
++
++
++ nlohmann::json jsn;
++ try {
++ jsn = nlohmann::json::parse(std::string(message));
++
++
++ uic_mqtt_dotdot_parse_unify_switch_color_set_color(
++ jsn,
++ color_component_id,
++
++ value,
++
++ duration
++ );
++
++ } catch (const nlohmann::json::parse_error& e) {
++ // Catch JSON object field parsing errors
++ sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UnifySwitchColor", "SetColor");
++ return;
++ } catch (const nlohmann::json::exception& e) {
++ // Catch JSON object field parsing errors
++ sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifySwitchColor", "SetColor", e.what());
++ return;
++ } catch (const std::exception& e) {
++ sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifySwitchColor", "SetColor", "");
++ return;
++ }
++
++
++
++
++ for (const auto& callback: uic_mqtt_dotdot_unify_switch_color_generated_set_color_callback){
++ callback(
++ static_cast(unid.c_str()),
++ endpoint,
++ UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL,
++ color_component_id,
++
++ value,
++
++ duration
++
++ );
++ }
++}
++
++
++// Callback function for incoming publications on ucl/by-unid/+/+/UnifySwitchColor/Commands/StartStopChange
++void uic_mqtt_dotdot_on_unify_switch_color_start_stop_change(
++ const char *topic,
++ const char *message,
++ const size_t message_length)
++{
++ if (message_length == 0 || (uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback.empty())) {
++ return;
++ }
++
++ std::string unid;
++ uint8_t endpoint = 0; // Default value for endpoint-less topics.
++ if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) {
++ sl_log_debug(LOG_TAG,
++ "Error parsing UNID / Endpoint ID from topic %s. Ignoring",
++ topic);
++ return;
++ }
++
++ bool start_stop = {};
++ bool up_down = {};
++ bool ignor_start_level = {};
++ uint8_t color_component_id = {};
++ uint8_t start_level = {};
++ uint32_t duration = {};
++
++
++ nlohmann::json jsn;
++ try {
++ jsn = nlohmann::json::parse(std::string(message));
++
++
++ uic_mqtt_dotdot_parse_unify_switch_color_start_stop_change(
++ jsn,
++ start_stop,
++
++ up_down,
++
++ ignor_start_level,
++
++ color_component_id,
++
++ start_level,
++
++ duration
++ );
++
++ } catch (const nlohmann::json::parse_error& e) {
++ // Catch JSON object field parsing errors
++ sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UnifySwitchColor", "StartStopChange");
++ return;
++ } catch (const nlohmann::json::exception& e) {
++ // Catch JSON object field parsing errors
++ sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifySwitchColor", "StartStopChange", e.what());
++ return;
++ } catch (const std::exception& e) {
++ sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifySwitchColor", "StartStopChange", "");
++ return;
++ }
++
++
++
++ for (const auto& callback: uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback){
++ callback(
++ static_cast(unid.c_str()),
++ endpoint,
++ UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL,
++ start_stop,
++
++ up_down,
++
++ ignor_start_level,
++
++ color_component_id,
++
++ start_level,
++
++ duration
++
++ );
++ }
++
++}
++
++// Callback function for incoming publications on ucl/by-unid/+/+/UnifySwitchColor/GeneratedCommands/StartStopChange
++static void uic_mqtt_dotdot_on_generated_unify_switch_color_start_stop_change(
++ const char *topic,
++ const char *message,
++ const size_t message_length)
++{
++ if (message_length == 0 || (uic_mqtt_dotdot_unify_switch_color_generated_start_stop_change_callback.empty())) {
++ return;
++ }
++
++ std::string unid;
++ uint8_t endpoint = 0; // Default value for endpoint-less topics.
++ if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) {
++ sl_log_debug(LOG_TAG,
++ "Error parsing UNID / Endpoint ID from topic %s. Ignoring",
++ topic);
++ return;
++ }
++
++ bool start_stop = {};
++ bool up_down = {};
++ bool ignor_start_level = {};
++ uint8_t color_component_id = {};
++ uint8_t start_level = {};
++ uint32_t duration = {};
++
++
++ nlohmann::json jsn;
++ try {
++ jsn = nlohmann::json::parse(std::string(message));
++
++
++ uic_mqtt_dotdot_parse_unify_switch_color_start_stop_change(
++ jsn,
++ start_stop,
++
++ up_down,
++
++ ignor_start_level,
++
++ color_component_id,
++
++ start_level,
++
++ duration
++ );
++
++ } catch (const nlohmann::json::parse_error& e) {
++ // Catch JSON object field parsing errors
++ sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UnifySwitchColor", "StartStopChange");
++ return;
++ } catch (const nlohmann::json::exception& e) {
++ // Catch JSON object field parsing errors
++ sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifySwitchColor", "StartStopChange", e.what());
++ return;
++ } catch (const std::exception& e) {
++ sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifySwitchColor", "StartStopChange", "");
++ return;
++ }
++
++
++
++
++ for (const auto& callback: uic_mqtt_dotdot_unify_switch_color_generated_start_stop_change_callback){
++ callback(
++ static_cast(unid.c_str()),
++ endpoint,
++ UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL,
++ start_stop,
++
++ up_down,
++
++ ignor_start_level,
++
++ color_component_id,
++
++ start_level,
++
++ duration
++
++ );
++ }
++}
++
++
++// Callback function for incoming publications on ucl/by-unid/+/+/UnifySwitchColor/Commands/WriteAttributes
++void uic_mqtt_dotdot_on_unify_switch_color_WriteAttributes(
++ const char *topic,
++ const char *message,
++ const size_t message_length)
++{
++ if (uic_mqtt_dotdot_unify_switch_color_write_attributes_callback.empty()) {
++ return;
++ }
++
++ if (message_length == 0) {
++ return;
++ }
++
++ std::string unid;
++ uint8_t endpoint = 0; // Default value for endpoint-less topics.
++ if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) {
++ sl_log_debug(LOG_TAG,
++ "Error parsing UNID / Endpoint ID from topic %s. Ignoring",
++ topic);
++ return;
++ }
++
++ uic_mqtt_dotdot_unify_switch_color_state_t new_state = {};
++ uic_mqtt_dotdot_unify_switch_color_updated_state_t new_updated_state = {};
++
++
++ nlohmann::json jsn;
++ try {
++ jsn = nlohmann::json::parse(std::string(message));
++
++ uic_mqtt_dotdot_parse_unify_switch_color_write_attributes(
++ jsn,
++ new_state,
++ new_updated_state
++ );
++ } catch (const nlohmann::json::parse_error& e) {
++ // Catch JSON object field parsing errors
++ sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UnifySwitchColor", "WriteAttributes");
++ return;
++ } catch (const nlohmann::json::exception& e) {
++ // Catch JSON object field parsing errors
++ sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifySwitchColor", "WriteAttributes", e.what());
++ return;
++ } catch (const std::exception& e) {
++ sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifySwitchColor", "WriteAttributes", "");
++ return;
++ }
++
++ for (const auto& callback: uic_mqtt_dotdot_unify_switch_color_write_attributes_callback){
++ callback(
++ static_cast(unid.c_str()),
++ endpoint,
++ UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL,
++ new_state,
++ new_updated_state
++ );
++ }
++
++}
++
++static void uic_mqtt_dotdot_on_unify_switch_color_force_read_attributes(
++ const char *topic,
++ const char *message,
++ const size_t message_length)
++{
++ uint8_t endpoint = 0;
++ std::string unid;
++
++ if ((message_length == 0) || (uic_mqtt_dotdot_unify_switch_color_force_read_attributes_callback.empty())) {
++ return;
++ }
++
++ if(! uic_dotdot_mqtt::parse_topic(topic, unid, endpoint)) {
++ sl_log_debug(LOG_TAG,
++ "Error parsing UNID / Endpoint ID from topic %s. Ignoring",
++ topic);
++ return;
++ }
++
++ try {
++ uic_mqtt_dotdot_unify_switch_color_updated_state_t force_update = {0};
++ bool trigger_handler = false;
++
++ nlohmann::json jsn = nlohmann::json::parse(std::string(message));
++ std::vector attributes = jsn["value"].get>();
++
++ // Assume all attributes to be read on empty array received
++ if (attributes.size() == 0) {
++ force_update.warm_white = true;
++ force_update.cold_white = true;
++ force_update.red = true;
++ force_update.green = true;
++ force_update.blue = true;
++ force_update.amber = true;
++ force_update.cyan = true;
++ force_update.purple = true;
++ trigger_handler = true;
++ } else {
++ std::unordered_map supported_attrs = {
++ {"WarmWhite", &force_update.warm_white },
++ {"ColdWhite", &force_update.cold_white },
++ {"Red", &force_update.red },
++ {"Green", &force_update.green },
++ {"Blue", &force_update.blue },
++ {"Amber", &force_update.amber },
++ {"Cyan", &force_update.cyan },
++ {"Purple", &force_update.purple },
++ };
++
++ for (auto& attribute : attributes) {
++ auto found_attr = supported_attrs.find(attribute);
++ if (found_attr != supported_attrs.end()) {
++ *(found_attr->second) = true;
++ trigger_handler = true;
++ }
++ }
++ }
++
++ if (trigger_handler == true) {
++ for (const auto& callback: uic_mqtt_dotdot_unify_switch_color_force_read_attributes_callback) {
++ callback(
++ static_cast(unid.c_str()),
++ endpoint,
++ UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL,
++ force_update
++ );
++ }
++ }
++ } catch (...) {
++ sl_log_debug(LOG_TAG, "UnifySwitchColor/Commands/ForceReadAttributes: Unable to parse JSON payload");
++ return;
++ }
++}
++
++sl_status_t uic_mqtt_dotdot_unify_switch_color_warm_white_publish(
++ const char *base_topic,
++ uint8_t value,
++ uic_mqtt_dotdot_attribute_publish_type_t publish_type
++)
++{
++ nlohmann::json jsn;
++
++ // This is a single value
++
++ if (true == uic_dotdot_has_attribute_value_a_name(65441,0,value)) {
++ jsn["value"] = uic_dotdot_get_attribute_value_name(65441,0,value);
++ }else{
++ jsn["value"] = value;
++ }
++
++
++ std::string payload_str;
++ try {
++ // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters
++ payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace);
++ } catch (const nlohmann::json::exception& e) {
++ sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifySwitchColor/Attributes/WarmWhite", e.what());
++ return SL_STATUS_OK;
++ }
++
++
++ std::string topic = std::string(base_topic) + "/UnifySwitchColor/Attributes/WarmWhite";
++ if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED)
++ {
++ std::string topic_desired = topic + "/Desired";
++ uic_mqtt_publish(topic_desired.c_str(),
++ payload_str.c_str(),
++ payload_str.length(),
++ true);
++ }
++ if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED)
++ {
++ std::string topic_reported = topic + "/Reported";
++ uic_mqtt_publish(topic_reported.c_str(),
++ payload_str.c_str(),
++ payload_str.length(),
++ true);
++ }
++ return SL_STATUS_OK;
++}
++
++sl_status_t uic_mqtt_dotdot_unify_switch_color_warm_white_unretain(
++ const char *base_topic,
++ uic_mqtt_dotdot_attribute_publish_type_t publish_type)
++{
++ // clang-format on
++ std::string topic
++ = std::string(base_topic)
++ + "/UnifySwitchColor/Attributes/WarmWhite";
++
++ if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED)
++ || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) {
++ std::string topic_desired = topic + "/Desired";
++ uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true);
++ }
++ if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED)
++ || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) {
++ std::string topic_reported = topic + "/Reported";
++ uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true);
++ }
++ return SL_STATUS_OK;
++}
++// clang-format off
++
++sl_status_t uic_mqtt_dotdot_unify_switch_color_cold_white_publish(
++ const char *base_topic,
++ uint8_t value,
++ uic_mqtt_dotdot_attribute_publish_type_t publish_type
++)
++{
++ nlohmann::json jsn;
++
++ // This is a single value
++
++ if (true == uic_dotdot_has_attribute_value_a_name(65441,1,value)) {
++ jsn["value"] = uic_dotdot_get_attribute_value_name(65441,1,value);
++ }else{
++ jsn["value"] = value;
++ }
++
++
++ std::string payload_str;
++ try {
++ // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters
++ payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace);
++ } catch (const nlohmann::json::exception& e) {
++ sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifySwitchColor/Attributes/ColdWhite", e.what());
++ return SL_STATUS_OK;
++ }
++
++
++ std::string topic = std::string(base_topic) + "/UnifySwitchColor/Attributes/ColdWhite";
++ if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED)
++ {
++ std::string topic_desired = topic + "/Desired";
++ uic_mqtt_publish(topic_desired.c_str(),
++ payload_str.c_str(),
++ payload_str.length(),
++ true);
++ }
++ if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED)
++ {
++ std::string topic_reported = topic + "/Reported";
++ uic_mqtt_publish(topic_reported.c_str(),
++ payload_str.c_str(),
++ payload_str.length(),
++ true);
++ }
++ return SL_STATUS_OK;
++}
++
++sl_status_t uic_mqtt_dotdot_unify_switch_color_cold_white_unretain(
++ const char *base_topic,
++ uic_mqtt_dotdot_attribute_publish_type_t publish_type)
++{
++ // clang-format on
++ std::string topic
++ = std::string(base_topic)
++ + "/UnifySwitchColor/Attributes/ColdWhite";
++
++ if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED)
++ || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) {
++ std::string topic_desired = topic + "/Desired";
++ uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true);
++ }
++ if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED)
++ || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) {
++ std::string topic_reported = topic + "/Reported";
++ uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true);
++ }
++ return SL_STATUS_OK;
++}
++// clang-format off
++
++sl_status_t uic_mqtt_dotdot_unify_switch_color_red_publish(
++ const char *base_topic,
++ uint8_t value,
++ uic_mqtt_dotdot_attribute_publish_type_t publish_type
++)
++{
++ nlohmann::json jsn;
++
++ // This is a single value
++
++ if (true == uic_dotdot_has_attribute_value_a_name(65441,2,value)) {
++ jsn["value"] = uic_dotdot_get_attribute_value_name(65441,2,value);
++ }else{
++ jsn["value"] = value;
++ }
++
++
++ std::string payload_str;
++ try {
++ // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters
++ payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace);
++ } catch (const nlohmann::json::exception& e) {
++ sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifySwitchColor/Attributes/Red", e.what());
++ return SL_STATUS_OK;
++ }
++
++
++ std::string topic = std::string(base_topic) + "/UnifySwitchColor/Attributes/Red";
++ if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED)
++ {
++ std::string topic_desired = topic + "/Desired";
++ uic_mqtt_publish(topic_desired.c_str(),
++ payload_str.c_str(),
++ payload_str.length(),
++ true);
++ }
++ if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED)
++ {
++ std::string topic_reported = topic + "/Reported";
++ uic_mqtt_publish(topic_reported.c_str(),
++ payload_str.c_str(),
++ payload_str.length(),
++ true);
++ }
++ return SL_STATUS_OK;
++}
++
++sl_status_t uic_mqtt_dotdot_unify_switch_color_red_unretain(
++ const char *base_topic,
++ uic_mqtt_dotdot_attribute_publish_type_t publish_type)
++{
++ // clang-format on
++ std::string topic
++ = std::string(base_topic)
++ + "/UnifySwitchColor/Attributes/Red";
++
++ if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED)
++ || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) {
++ std::string topic_desired = topic + "/Desired";
++ uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true);
++ }
++ if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED)
++ || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) {
++ std::string topic_reported = topic + "/Reported";
++ uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true);
++ }
++ return SL_STATUS_OK;
++}
++// clang-format off
++
++sl_status_t uic_mqtt_dotdot_unify_switch_color_green_publish(
++ const char *base_topic,
++ uint8_t value,
++ uic_mqtt_dotdot_attribute_publish_type_t publish_type
++)
++{
++ nlohmann::json jsn;
++
++ // This is a single value
++
++ if (true == uic_dotdot_has_attribute_value_a_name(65441,3,value)) {
++ jsn["value"] = uic_dotdot_get_attribute_value_name(65441,3,value);
++ }else{
++ jsn["value"] = value;
++ }
++
++
++ std::string payload_str;
++ try {
++ // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters
++ payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace);
++ } catch (const nlohmann::json::exception& e) {
++ sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifySwitchColor/Attributes/Green", e.what());
++ return SL_STATUS_OK;
++ }
++
++
++ std::string topic = std::string(base_topic) + "/UnifySwitchColor/Attributes/Green";
++ if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED)
++ {
++ std::string topic_desired = topic + "/Desired";
++ uic_mqtt_publish(topic_desired.c_str(),
++ payload_str.c_str(),
++ payload_str.length(),
++ true);
++ }
++ if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED)
++ {
++ std::string topic_reported = topic + "/Reported";
++ uic_mqtt_publish(topic_reported.c_str(),
++ payload_str.c_str(),
++ payload_str.length(),
++ true);
++ }
++ return SL_STATUS_OK;
++}
++
++sl_status_t uic_mqtt_dotdot_unify_switch_color_green_unretain(
++ const char *base_topic,
++ uic_mqtt_dotdot_attribute_publish_type_t publish_type)
++{
++ // clang-format on
++ std::string topic
++ = std::string(base_topic)
++ + "/UnifySwitchColor/Attributes/Green";
++
++ if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED)
++ || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) {
++ std::string topic_desired = topic + "/Desired";
++ uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true);
++ }
++ if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED)
++ || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) {
++ std::string topic_reported = topic + "/Reported";
++ uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true);
++ }
++ return SL_STATUS_OK;
++}
++// clang-format off
++
++sl_status_t uic_mqtt_dotdot_unify_switch_color_blue_publish(
++ const char *base_topic,
++ uint8_t value,
++ uic_mqtt_dotdot_attribute_publish_type_t publish_type
++)
++{
++ nlohmann::json jsn;
++
++ // This is a single value
++
++ if (true == uic_dotdot_has_attribute_value_a_name(65441,4,value)) {
++ jsn["value"] = uic_dotdot_get_attribute_value_name(65441,4,value);
++ }else{
++ jsn["value"] = value;
++ }
++
++
++ std::string payload_str;
++ try {
++ // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters
++ payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace);
++ } catch (const nlohmann::json::exception& e) {
++ sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifySwitchColor/Attributes/Blue", e.what());
++ return SL_STATUS_OK;
++ }
++
++
++ std::string topic = std::string(base_topic) + "/UnifySwitchColor/Attributes/Blue";
++ if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED)
++ {
++ std::string topic_desired = topic + "/Desired";
++ uic_mqtt_publish(topic_desired.c_str(),
++ payload_str.c_str(),
++ payload_str.length(),
++ true);
++ }
++ if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED)
++ {
++ std::string topic_reported = topic + "/Reported";
++ uic_mqtt_publish(topic_reported.c_str(),
++ payload_str.c_str(),
++ payload_str.length(),
++ true);
++ }
++ return SL_STATUS_OK;
++}
++
++sl_status_t uic_mqtt_dotdot_unify_switch_color_blue_unretain(
++ const char *base_topic,
++ uic_mqtt_dotdot_attribute_publish_type_t publish_type)
++{
++ // clang-format on
++ std::string topic
++ = std::string(base_topic)
++ + "/UnifySwitchColor/Attributes/Blue";
++
++ if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED)
++ || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) {
++ std::string topic_desired = topic + "/Desired";
++ uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true);
++ }
++ if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED)
++ || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) {
++ std::string topic_reported = topic + "/Reported";
++ uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true);
++ }
++ return SL_STATUS_OK;
++}
++// clang-format off
++
++sl_status_t uic_mqtt_dotdot_unify_switch_color_amber_publish(
++ const char *base_topic,
++ uint8_t value,
++ uic_mqtt_dotdot_attribute_publish_type_t publish_type
++)
++{
++ nlohmann::json jsn;
++
++ // This is a single value
++
++ if (true == uic_dotdot_has_attribute_value_a_name(65441,5,value)) {
++ jsn["value"] = uic_dotdot_get_attribute_value_name(65441,5,value);
++ }else{
++ jsn["value"] = value;
++ }
++
++
++ std::string payload_str;
++ try {
++ // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters
++ payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace);
++ } catch (const nlohmann::json::exception& e) {
++ sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifySwitchColor/Attributes/Amber", e.what());
++ return SL_STATUS_OK;
++ }
++
++
++ std::string topic = std::string(base_topic) + "/UnifySwitchColor/Attributes/Amber";
++ if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED)
++ {
++ std::string topic_desired = topic + "/Desired";
++ uic_mqtt_publish(topic_desired.c_str(),
++ payload_str.c_str(),
++ payload_str.length(),
++ true);
++ }
++ if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED)
++ {
++ std::string topic_reported = topic + "/Reported";
++ uic_mqtt_publish(topic_reported.c_str(),
++ payload_str.c_str(),
++ payload_str.length(),
++ true);
++ }
++ return SL_STATUS_OK;
++}
++
++sl_status_t uic_mqtt_dotdot_unify_switch_color_amber_unretain(
++ const char *base_topic,
++ uic_mqtt_dotdot_attribute_publish_type_t publish_type)
++{
++ // clang-format on
++ std::string topic
++ = std::string(base_topic)
++ + "/UnifySwitchColor/Attributes/Amber";
++
++ if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED)
++ || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) {
++ std::string topic_desired = topic + "/Desired";
++ uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true);
++ }
++ if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED)
++ || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) {
++ std::string topic_reported = topic + "/Reported";
++ uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true);
++ }
++ return SL_STATUS_OK;
++}
++// clang-format off
++
++sl_status_t uic_mqtt_dotdot_unify_switch_color_cyan_publish(
++ const char *base_topic,
++ uint8_t value,
++ uic_mqtt_dotdot_attribute_publish_type_t publish_type
++)
++{
++ nlohmann::json jsn;
++
++ // This is a single value
++
++ if (true == uic_dotdot_has_attribute_value_a_name(65441,6,value)) {
++ jsn["value"] = uic_dotdot_get_attribute_value_name(65441,6,value);
++ }else{
++ jsn["value"] = value;
++ }
++
++
++ std::string payload_str;
++ try {
++ // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters
++ payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace);
++ } catch (const nlohmann::json::exception& e) {
++ sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifySwitchColor/Attributes/Cyan", e.what());
++ return SL_STATUS_OK;
++ }
++
++
++ std::string topic = std::string(base_topic) + "/UnifySwitchColor/Attributes/Cyan";
++ if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED)
++ {
++ std::string topic_desired = topic + "/Desired";
++ uic_mqtt_publish(topic_desired.c_str(),
++ payload_str.c_str(),
++ payload_str.length(),
++ true);
++ }
++ if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED)
++ {
++ std::string topic_reported = topic + "/Reported";
++ uic_mqtt_publish(topic_reported.c_str(),
++ payload_str.c_str(),
++ payload_str.length(),
++ true);
++ }
++ return SL_STATUS_OK;
++}
++
++sl_status_t uic_mqtt_dotdot_unify_switch_color_cyan_unretain(
++ const char *base_topic,
++ uic_mqtt_dotdot_attribute_publish_type_t publish_type)
++{
++ // clang-format on
++ std::string topic
++ = std::string(base_topic)
++ + "/UnifySwitchColor/Attributes/Cyan";
++
++ if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED)
++ || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) {
++ std::string topic_desired = topic + "/Desired";
++ uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true);
++ }
++ if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED)
++ || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) {
++ std::string topic_reported = topic + "/Reported";
++ uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true);
++ }
++ return SL_STATUS_OK;
++}
++// clang-format off
++
++sl_status_t uic_mqtt_dotdot_unify_switch_color_purple_publish(
++ const char *base_topic,
++ uint8_t value,
++ uic_mqtt_dotdot_attribute_publish_type_t publish_type
++)
++{
++ nlohmann::json jsn;
++
++ // This is a single value
++
++ if (true == uic_dotdot_has_attribute_value_a_name(65441,7,value)) {
++ jsn["value"] = uic_dotdot_get_attribute_value_name(65441,7,value);
++ }else{
++ jsn["value"] = value;
++ }
++
++
++ std::string payload_str;
++ try {
++ // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters
++ payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace);
++ } catch (const nlohmann::json::exception& e) {
++ sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifySwitchColor/Attributes/Purple", e.what());
++ return SL_STATUS_OK;
++ }
++
++
++ std::string topic = std::string(base_topic) + "/UnifySwitchColor/Attributes/Purple";
++ if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED)
++ {
++ std::string topic_desired = topic + "/Desired";
++ uic_mqtt_publish(topic_desired.c_str(),
++ payload_str.c_str(),
++ payload_str.length(),
++ true);
++ }
++ if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED)
++ {
++ std::string topic_reported = topic + "/Reported";
++ uic_mqtt_publish(topic_reported.c_str(),
++ payload_str.c_str(),
++ payload_str.length(),
++ true);
++ }
++ return SL_STATUS_OK;
++}
++
++sl_status_t uic_mqtt_dotdot_unify_switch_color_purple_unretain(
++ const char *base_topic,
++ uic_mqtt_dotdot_attribute_publish_type_t publish_type)
++{
++ // clang-format on
++ std::string topic
++ = std::string(base_topic)
++ + "/UnifySwitchColor/Attributes/Purple";
++
++ if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED)
++ || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) {
++ std::string topic_desired = topic + "/Desired";
++ uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true);
++ }
++ if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED)
++ || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) {
++ std::string topic_reported = topic + "/Reported";
++ uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true);
++ }
++ return SL_STATUS_OK;
++}
++// clang-format off
++
++
++sl_status_t uic_mqtt_dotdot_unify_switch_color_init()
++{
++ std::string base_topic = "ucl/by-unid/+/+/";
++
++ std::string subscription_topic;
++ if(!uic_mqtt_dotdot_unify_switch_color_write_attributes_callback.empty()) {
++ subscription_topic = base_topic + "UnifySwitchColor/Commands/WriteAttributes";
++ uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_unify_switch_color_WriteAttributes);
++ }
++
++ if(!uic_mqtt_dotdot_unify_switch_color_force_read_attributes_callback.empty()) {
++ subscription_topic = base_topic + "UnifySwitchColor/Commands/ForceReadAttributes";
++ uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_unify_switch_color_force_read_attributes);
++ }
++ if (!uic_mqtt_dotdot_unify_switch_color_set_color_callback.empty()) {
++ subscription_topic = base_topic + "UnifySwitchColor/Commands/SetColor";
++ uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_unify_switch_color_set_color);
++ }
++ if (!uic_mqtt_dotdot_unify_switch_color_generated_set_color_callback.empty()) {
++ subscription_topic = base_topic + "UnifySwitchColor/GeneratedCommands/SetColor";
++ uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_generated_unify_switch_color_set_color);
++ }
++ if (!uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback.empty()) {
++ subscription_topic = base_topic + "UnifySwitchColor/Commands/StartStopChange";
++ uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_unify_switch_color_start_stop_change);
++ }
++ if (!uic_mqtt_dotdot_unify_switch_color_generated_start_stop_change_callback.empty()) {
++ subscription_topic = base_topic + "UnifySwitchColor/GeneratedCommands/StartStopChange";
++ uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_generated_unify_switch_color_start_stop_change);
++ }
++
++ // Init the attributes for that cluster
++ uic_mqtt_dotdot_unify_switch_color_attributes_init();
++
++ uic_mqtt_dotdot_by_group_unify_switch_color_init();
++
++ return SL_STATUS_OK;
++}
++
+
+ sl_status_t uic_mqtt_dotdot_init() {
+
+@@ -99998,6 +101156,10 @@ sl_status_t uic_mqtt_dotdot_init() {
+ status_flag = uic_mqtt_dotdot_unify_humidity_control_init();
+ }
+
++ if (status_flag == SL_STATUS_OK) {
++ status_flag = uic_mqtt_dotdot_unify_switch_color_init();
++ }
++
+
+ return status_flag;
+ }
+@@ -100061,6 +101223,7 @@ void uic_mqtt_dotdot_publish_supported_commands(
+ uic_mqtt_dotdot_unify_fan_control_publish_supported_commands(unid, endpoint_id);
+ uic_mqtt_dotdot_unify_thermostat_publish_supported_commands(unid, endpoint_id);
+ uic_mqtt_dotdot_unify_humidity_control_publish_supported_commands(unid, endpoint_id);
++ uic_mqtt_dotdot_unify_switch_color_publish_supported_commands(unid, endpoint_id);
+ }
+
+ void uic_mqtt_dotdot_publish_empty_supported_commands(
+@@ -100121,6 +101284,7 @@ void uic_mqtt_dotdot_publish_empty_supported_commands(
+ uic_mqtt_dotdot_unify_fan_control_publish_empty_supported_commands(unid, endpoint_id);
+ uic_mqtt_dotdot_unify_thermostat_publish_empty_supported_commands(unid, endpoint_id);
+ uic_mqtt_dotdot_unify_humidity_control_publish_empty_supported_commands(unid, endpoint_id);
++ uic_mqtt_dotdot_unify_switch_color_publish_empty_supported_commands(unid, endpoint_id);
+ }
+
+ // Publishing Cluster Revision for Basic Cluster
+@@ -114499,6 +115663,232 @@ void uic_mqtt_dotdot_unify_humidity_control_publish_empty_supported_commands(
+ }
+ }
+
++// Publishing Cluster Revision for UnifySwitchColor Cluster
++void uic_mqtt_dotdot_unify_switch_color_publish_cluster_revision(const char* base_topic, uint16_t value)
++{
++ std::string cluster_topic = std::string(base_topic) + "/UnifySwitchColor/Attributes/ClusterRevision";
++ // Publish Desired
++ std::string pub_topic_des = cluster_topic + "/Desired";
++ std::string payload = std::string(R"({"value": )")
++ + std::to_string(value) + std::string("}");
++ uic_mqtt_publish(pub_topic_des.c_str(),
++ payload.c_str(),
++ payload.size(),
++ true);
++ // Publish Reported
++ std::string pub_topic_rep = cluster_topic + "/Reported";
++ uic_mqtt_publish(pub_topic_rep.c_str(),
++ payload.c_str(),
++ payload.size(),
++ true);
++}
++
++// Unretain Cluster Revision for UnifySwitchColor Cluster
++void uic_mqtt_dotdot_unify_switch_color_unretain_cluster_revision(const char* base_topic)
++{
++ // clang-format on
++ std::string cluster_topic
++ = std::string(base_topic)
++ + "/UnifySwitchColor/Attributes/ClusterRevision";
++ // Publish Desired
++ std::string desired_topic = cluster_topic + "/Desired";
++ uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true);
++ // Publish Reported
++ std::string reported_topic = cluster_topic + "/Reported";
++ uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true);
++ // clang-format off
++}
++
++static inline bool uic_mqtt_dotdot_unify_switch_color_set_color_is_supported(
++ const dotdot_unid_t unid,
++ dotdot_endpoint_id_t endpoint_id)
++{
++ uint8_t color_component_id_value;
++ memset(&color_component_id_value, 0x00, sizeof(color_component_id_value));
++ uint8_t value_value;
++ memset(&value_value, 0x00, sizeof(value_value));
++ uint32_t duration_value;
++ memset(&duration_value, 0x00, sizeof(duration_value));
++ for (const auto& callback: uic_mqtt_dotdot_unify_switch_color_set_color_callback) {
++ if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK
++ ,
++ color_component_id_value,
++
++ value_value,
++
++ duration_value
++
++ ) == SL_STATUS_OK) {
++ return true;
++ }
++ }
++
++ return false;
++}
++static inline bool uic_mqtt_dotdot_unify_switch_color_start_stop_change_is_supported(
++ const dotdot_unid_t unid,
++ dotdot_endpoint_id_t endpoint_id)
++{
++ bool start_stop_value;
++ memset(&start_stop_value, 0x00, sizeof(start_stop_value));
++ bool up_down_value;
++ memset(&up_down_value, 0x00, sizeof(up_down_value));
++ bool ignor_start_level_value;
++ memset(&ignor_start_level_value, 0x00, sizeof(ignor_start_level_value));
++ uint8_t color_component_id_value;
++ memset(&color_component_id_value, 0x00, sizeof(color_component_id_value));
++ uint8_t start_level_value;
++ memset(&start_level_value, 0x00, sizeof(start_level_value));
++ uint32_t duration_value;
++ memset(&duration_value, 0x00, sizeof(duration_value));
++ for (const auto& callback: uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback) {
++ if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK
++ ,
++ start_stop_value,
++
++ up_down_value,
++
++ ignor_start_level_value,
++
++ color_component_id_value,
++
++ start_level_value,
++
++ duration_value
++
++ ) == SL_STATUS_OK) {
++ return true;
++ }
++ }
++
++ return false;
++}
++
++static inline bool uic_mqtt_dotdot_unify_switch_color_write_attributes_is_supported(
++ const dotdot_unid_t unid,
++ dotdot_endpoint_id_t endpoint_id)
++{
++ for (const auto& callback: uic_mqtt_dotdot_unify_switch_color_write_attributes_callback) {
++ uic_mqtt_dotdot_unify_switch_color_state_t unify_switch_color_new_state = {};
++ uic_mqtt_dotdot_unify_switch_color_updated_state_t unify_switch_color_new_updated_state = {};
++
++ if (callback(
++ unid,
++ endpoint_id,
++ UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK,
++ unify_switch_color_new_state,
++ unify_switch_color_new_updated_state
++ ) == SL_STATUS_OK) {
++ return true;
++ }
++ }
++ return false;
++}
++
++static inline bool uic_mqtt_dotdot_unify_switch_color_force_read_attributes_is_supported(
++ const dotdot_unid_t unid,
++ dotdot_endpoint_id_t endpoint_id)
++{
++ for (const auto& callback: uic_mqtt_dotdot_unify_switch_color_force_read_attributes_callback) {
++ uic_mqtt_dotdot_unify_switch_color_updated_state_t unify_switch_color_force_update = {0};
++ if (callback(
++ unid,
++ endpoint_id,
++ UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK,
++ unify_switch_color_force_update
++ ) == SL_STATUS_OK) {
++ return true;
++ }
++ }
++ return false;
++}
++
++// Publishing Supported Commands for UnifySwitchColor Cluster
++void uic_mqtt_dotdot_unify_switch_color_publish_supported_commands(
++ const dotdot_unid_t unid,
++ dotdot_endpoint_id_t endpoint_id)
++{
++ std::stringstream ss;
++ bool first_command = true;
++ ss.str("");
++
++ // check if there is callback for each command
++ if (uic_mqtt_dotdot_unify_switch_color_set_color_is_supported(unid, endpoint_id)) {
++ if (first_command == false) {
++ ss << ", ";
++ }
++ first_command = false;
++ ss << R"("SetColor")";
++ }
++ if (uic_mqtt_dotdot_unify_switch_color_start_stop_change_is_supported(unid, endpoint_id)) {
++ if (first_command == false) {
++ ss << ", ";
++ }
++ first_command = false;
++ ss << R"("StartStopChange")";
++ }
++
++ // Check for a WriteAttributes Callback
++ if(uic_mqtt_dotdot_unify_switch_color_write_attributes_is_supported(unid, endpoint_id)) {
++ if (first_command == false) {
++ ss << ", ";
++ }
++ first_command = false;
++ ss << R"("WriteAttributes")";
++ }
++
++ // Check for a ForceReadAttributes Callback
++ if (uic_mqtt_dotdot_unify_switch_color_force_read_attributes_is_supported(unid, endpoint_id)) {
++ if (first_command == false) {
++ ss << ", ";
++ }
++ first_command = false;
++ ss << R"("ForceReadAttributes")";
++ }
++
++ // Publish supported commands
++ std::string topic = "ucl/by-unid/" + std::string(unid);
++ topic += "/ep"+ std::to_string(endpoint_id);
++ topic += "/UnifySwitchColor/SupportedCommands";
++ std::string payload_str("{\"value\": [" + ss.str() + "]" + "}");
++ if (first_command == false) {
++ uic_mqtt_publish(topic.c_str(),
++ payload_str.c_str(),
++ payload_str.length(),
++ true);
++ } else if (uic_mqtt_count_topics(topic.c_str()) == 0) {
++ // There are no supported commands, but make sure we publish some
++ // SupportedCommands = [] if any attribute has been published for a cluster.
++ std::string attributes_topic = "ucl/by-unid/" + std::string(unid);
++ attributes_topic += "/ep"+ std::to_string(endpoint_id);
++ attributes_topic += "/UnifySwitchColor/Attributes";
++
++ if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) {
++ uic_mqtt_publish(topic.c_str(),
++ EMPTY_VALUE_ARRAY,
++ strlen(EMPTY_VALUE_ARRAY),
++ true);
++ }
++ }
++}
++
++// Publishing empty/no Supported Commands for UnifySwitchColor Cluster
++void uic_mqtt_dotdot_unify_switch_color_publish_empty_supported_commands(
++ const dotdot_unid_t unid
++ , dotdot_endpoint_id_t endpoint_id)
++{
++ std::string topic = "ucl/by-unid/" + std::string(unid);
++ topic += "/ep"+ std::to_string(endpoint_id);
++ topic += "/UnifySwitchColor/SupportedCommands";
++
++ if (uic_mqtt_count_topics(topic.c_str()) > 0) {
++ uic_mqtt_publish(topic.c_str(),
++ EMPTY_VALUE_ARRAY,
++ strlen(EMPTY_VALUE_ARRAY),
++ true);
++ }
++}
++
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Generated Commands publications functions
+@@ -121907,3 +123297,75 @@ void uic_mqtt_dotdot_unify_humidity_control_publish_generated_setpoint_set_comma
+ payload.size(),
+ false);
+ }
++/**
++ * @brief Publishes an incoming/generated SetColor command for
++ * the UnifySwitchColor cluster.
++ *
++ * Publication will be made at the following topic
++ * ucl/by-unid/UNID/epID/UnifySwitchColor/GeneratedCommands/SetColor
++ *
++ * @param unid The UNID of the node that sent us the command.
++ *
++ * @param endpoint The Endpoint ID of the node that sent us the command.
++ *
++ *
++ * @param fields Struct pointer with the fields value of the command
++ *
++ */
++void uic_mqtt_dotdot_unify_switch_color_publish_generated_set_color_command(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint,
++ const uic_mqtt_dotdot_unify_switch_color_command_set_color_fields_t *fields
++
++) {
++ // Create the topic
++ std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" +
++ std::to_string(endpoint) + "/";
++ topic += "UnifySwitchColor/GeneratedCommands/SetColor";
++
++ std::string payload =
++ get_json_payload_for_unify_switch_color_set_color_command(
++ fields);
++
++ // Publish our command
++ uic_mqtt_publish(topic.c_str(),
++ payload.c_str(),
++ payload.size(),
++ false);
++}
++/**
++ * @brief Publishes an incoming/generated StartStopChange command for
++ * the UnifySwitchColor cluster.
++ *
++ * Publication will be made at the following topic
++ * ucl/by-unid/UNID/epID/UnifySwitchColor/GeneratedCommands/StartStopChange
++ *
++ * @param unid The UNID of the node that sent us the command.
++ *
++ * @param endpoint The Endpoint ID of the node that sent us the command.
++ *
++ *
++ * @param fields Struct pointer with the fields value of the command
++ *
++ */
++void uic_mqtt_dotdot_unify_switch_color_publish_generated_start_stop_change_command(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint,
++ const uic_mqtt_dotdot_unify_switch_color_command_start_stop_change_fields_t *fields
++
++) {
++ // Create the topic
++ std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" +
++ std::to_string(endpoint) + "/";
++ topic += "UnifySwitchColor/GeneratedCommands/StartStopChange";
++
++ std::string payload =
++ get_json_payload_for_unify_switch_color_start_stop_change_command(
++ fields);
++
++ // Publish our command
++ uic_mqtt_publish(topic.c_str(),
++ payload.c_str(),
++ payload.size(),
++ false);
++}
+diff --git a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt.hpp b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt.hpp
+index cef2277e5a..626983fca7 100644
+--- a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt.hpp
++++ b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt.hpp
+@@ -378,6 +378,13 @@ sl_status_t uic_mqtt_dotdot_by_group_unify_thermostat_init();
+ */
+ sl_status_t uic_mqtt_dotdot_by_group_unify_humidity_control_init();
+
++/**
++ * @brief Initialize UnifySwitchColor dotdot bygroup command handlers
++ *
++ * @returns SL_STATUS_OK on success, error otherwise.
++ */
++sl_status_t uic_mqtt_dotdot_by_group_unify_switch_color_init();
++
+
+
+ // clang-format on
+@@ -5523,6 +5530,65 @@ void uic_mqtt_dotdot_on_unify_humidity_control_WriteAttributes(
+ const size_t message_length);
+
+
++// clang-format on
++
++/**
++ * @brief Retrieves the container with callbacks pointer for
++ * by-unid UnifySwitchColor/Commands/SetColor messages
++ *
++ * @returns std::set of callbacks.
++ */
++std::set &get_uic_mqtt_dotdot_unify_switch_color_set_color_callback();
++
++/**
++ * @brief MQTT Subscribe handler for incoming publications on:
++ * ucl/by-unid/+/+/UnifySwitchColor/Commands/SetColor
++ */
++// clang-format off
++void uic_mqtt_dotdot_on_unify_switch_color_set_color(
++ const char *topic,
++ const char *message,
++ const size_t message_length);
++// clang-format on
++
++/**
++ * @brief Retrieves the container with callbacks pointer for
++ * by-unid UnifySwitchColor/Commands/StartStopChange messages
++ *
++ * @returns std::set of callbacks.
++ */
++std::set &get_uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback();
++
++/**
++ * @brief MQTT Subscribe handler for incoming publications on:
++ * ucl/by-unid/+/+/UnifySwitchColor/Commands/StartStopChange
++ */
++// clang-format off
++void uic_mqtt_dotdot_on_unify_switch_color_start_stop_change(
++ const char *topic,
++ const char *message,
++ const size_t message_length);
++// clang-format on
++
++/**
++ * @brief Retrieves the container with callback pointers for by-unid
++ * /Commands/WriteAttributes messages
++ *
++ * @returns std::set of callbacks.
++ */
++std::set & get_uic_mqtt_dotdot_unify_switch_color_write_attributes_callback();
++
++/**
++ * @brief MQTT Subscribe handler for incoming publications on:
++ * ucl/by-unid/+/+/UnifySwitchColor/Commands/WriteAttributes
++ */
++// clang-format off
++void uic_mqtt_dotdot_on_unify_switch_color_WriteAttributes(
++ const char *topic,
++ const char *message,
++ const size_t message_length);
++
++
+
+
+ // All bitmaps are defined as the cluster label for the bitmap plus the command/attribute name
+diff --git a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_attributes.cpp b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_attributes.cpp
+index 87fddb1ebf..d652e2f9eb 100644
+--- a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_attributes.cpp
++++ b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_attributes.cpp
+@@ -64347,3 +64347,710 @@ void uic_mqtt_dotdot_unify_humidity_control_attribute_auto_setpoint_precision_ca
+
+ // End of supported cluster.
+
++///////////////////////////////////////////////////////////////////////////////
++// Callback pointers for UnifySwitchColor
++///////////////////////////////////////////////////////////////////////////////
++static uic_mqtt_dotdot_unify_switch_color_attribute_warm_white_callback_t uic_mqtt_dotdot_unify_switch_color_attribute_warm_white_callback = nullptr;
++static uic_mqtt_dotdot_unify_switch_color_attribute_cold_white_callback_t uic_mqtt_dotdot_unify_switch_color_attribute_cold_white_callback = nullptr;
++static uic_mqtt_dotdot_unify_switch_color_attribute_red_callback_t uic_mqtt_dotdot_unify_switch_color_attribute_red_callback = nullptr;
++static uic_mqtt_dotdot_unify_switch_color_attribute_green_callback_t uic_mqtt_dotdot_unify_switch_color_attribute_green_callback = nullptr;
++static uic_mqtt_dotdot_unify_switch_color_attribute_blue_callback_t uic_mqtt_dotdot_unify_switch_color_attribute_blue_callback = nullptr;
++static uic_mqtt_dotdot_unify_switch_color_attribute_amber_callback_t uic_mqtt_dotdot_unify_switch_color_attribute_amber_callback = nullptr;
++static uic_mqtt_dotdot_unify_switch_color_attribute_cyan_callback_t uic_mqtt_dotdot_unify_switch_color_attribute_cyan_callback = nullptr;
++static uic_mqtt_dotdot_unify_switch_color_attribute_purple_callback_t uic_mqtt_dotdot_unify_switch_color_attribute_purple_callback = nullptr;
++
++///////////////////////////////////////////////////////////////////////////////
++// Attribute update handlers for UnifySwitchColor
++///////////////////////////////////////////////////////////////////////////////
++static void uic_mqtt_dotdot_on_unify_switch_color_warm_white_attribute_update(
++ const char *topic,
++ const char *message,
++ const size_t message_length) {
++ if (uic_mqtt_dotdot_unify_switch_color_attribute_warm_white_callback == nullptr) {
++ return;
++ }
++
++ std::string unid;
++ uint8_t endpoint = 0; // Default value for endpoint-less topics.
++ if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) {
++ sl_log_debug(LOG_TAG,
++ "Error parsing UNID / Endpoint ID from topic %s. Ignoring",
++ topic);
++ return;
++ }
++
++ std::string last_item;
++ if (SL_STATUS_OK != uic_dotdot_mqtt::get_topic_last_item(topic,last_item)){
++ sl_log_debug(LOG_TAG,
++ "Error parsing last item from topic %s. Ignoring",
++ topic);
++ return;
++ }
++
++ uic_mqtt_dotdot_attribute_update_type_t update_type;
++ if (last_item == "Reported") {
++ update_type = UCL_REPORTED_UPDATED;
++ } else if (last_item == "Desired") {
++ update_type = UCL_DESIRED_UPDATED;
++ } else {
++ sl_log_debug(LOG_TAG,
++ "Unknown value type (neither Desired/Reported) for topic %s. Ignoring",
++ topic);
++ return;
++ }
++
++ // Empty message means unretained value.
++ bool unretained = false;
++ if (message_length == 0) {
++ unretained = true;
++ }
++
++
++ uint8_t warm_white = {};
++
++ nlohmann::json json_payload;
++ try {
++
++ if (unretained == false) {
++ json_payload = nlohmann::json::parse(std::string(message));
++
++ if (json_payload.find("value") == json_payload.end()) {
++ sl_log_debug(LOG_TAG, "UnifySwitchColor::WarmWhite: Missing attribute element: 'value'\n");
++ return;
++ }
++// Start parsing value
++ warm_white = json_payload.at("value").get();
++
++ // End parsing value
++ }
++
++ } catch (const std::exception& e) {
++ sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "value", message);
++ return;
++ }
++
++ uic_mqtt_dotdot_unify_switch_color_attribute_warm_white_callback(
++ static_cast(unid.c_str()),
++ endpoint,
++ unretained,
++ update_type,
++ warm_white
++ );
++
++}
++static void uic_mqtt_dotdot_on_unify_switch_color_cold_white_attribute_update(
++ const char *topic,
++ const char *message,
++ const size_t message_length) {
++ if (uic_mqtt_dotdot_unify_switch_color_attribute_cold_white_callback == nullptr) {
++ return;
++ }
++
++ std::string unid;
++ uint8_t endpoint = 0; // Default value for endpoint-less topics.
++ if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) {
++ sl_log_debug(LOG_TAG,
++ "Error parsing UNID / Endpoint ID from topic %s. Ignoring",
++ topic);
++ return;
++ }
++
++ std::string last_item;
++ if (SL_STATUS_OK != uic_dotdot_mqtt::get_topic_last_item(topic,last_item)){
++ sl_log_debug(LOG_TAG,
++ "Error parsing last item from topic %s. Ignoring",
++ topic);
++ return;
++ }
++
++ uic_mqtt_dotdot_attribute_update_type_t update_type;
++ if (last_item == "Reported") {
++ update_type = UCL_REPORTED_UPDATED;
++ } else if (last_item == "Desired") {
++ update_type = UCL_DESIRED_UPDATED;
++ } else {
++ sl_log_debug(LOG_TAG,
++ "Unknown value type (neither Desired/Reported) for topic %s. Ignoring",
++ topic);
++ return;
++ }
++
++ // Empty message means unretained value.
++ bool unretained = false;
++ if (message_length == 0) {
++ unretained = true;
++ }
++
++
++ uint8_t cold_white = {};
++
++ nlohmann::json json_payload;
++ try {
++
++ if (unretained == false) {
++ json_payload = nlohmann::json::parse(std::string(message));
++
++ if (json_payload.find("value") == json_payload.end()) {
++ sl_log_debug(LOG_TAG, "UnifySwitchColor::ColdWhite: Missing attribute element: 'value'\n");
++ return;
++ }
++// Start parsing value
++ cold_white = json_payload.at("value").get();
++
++ // End parsing value
++ }
++
++ } catch (const std::exception& e) {
++ sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "value", message);
++ return;
++ }
++
++ uic_mqtt_dotdot_unify_switch_color_attribute_cold_white_callback(
++ static_cast(unid.c_str()),
++ endpoint,
++ unretained,
++ update_type,
++ cold_white
++ );
++
++}
++static void uic_mqtt_dotdot_on_unify_switch_color_red_attribute_update(
++ const char *topic,
++ const char *message,
++ const size_t message_length) {
++ if (uic_mqtt_dotdot_unify_switch_color_attribute_red_callback == nullptr) {
++ return;
++ }
++
++ std::string unid;
++ uint8_t endpoint = 0; // Default value for endpoint-less topics.
++ if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) {
++ sl_log_debug(LOG_TAG,
++ "Error parsing UNID / Endpoint ID from topic %s. Ignoring",
++ topic);
++ return;
++ }
++
++ std::string last_item;
++ if (SL_STATUS_OK != uic_dotdot_mqtt::get_topic_last_item(topic,last_item)){
++ sl_log_debug(LOG_TAG,
++ "Error parsing last item from topic %s. Ignoring",
++ topic);
++ return;
++ }
++
++ uic_mqtt_dotdot_attribute_update_type_t update_type;
++ if (last_item == "Reported") {
++ update_type = UCL_REPORTED_UPDATED;
++ } else if (last_item == "Desired") {
++ update_type = UCL_DESIRED_UPDATED;
++ } else {
++ sl_log_debug(LOG_TAG,
++ "Unknown value type (neither Desired/Reported) for topic %s. Ignoring",
++ topic);
++ return;
++ }
++
++ // Empty message means unretained value.
++ bool unretained = false;
++ if (message_length == 0) {
++ unretained = true;
++ }
++
++
++ uint8_t red = {};
++
++ nlohmann::json json_payload;
++ try {
++
++ if (unretained == false) {
++ json_payload = nlohmann::json::parse(std::string(message));
++
++ if (json_payload.find("value") == json_payload.end()) {
++ sl_log_debug(LOG_TAG, "UnifySwitchColor::Red: Missing attribute element: 'value'\n");
++ return;
++ }
++// Start parsing value
++ red = json_payload.at("value").get();
++
++ // End parsing value
++ }
++
++ } catch (const std::exception& e) {
++ sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "value", message);
++ return;
++ }
++
++ uic_mqtt_dotdot_unify_switch_color_attribute_red_callback(
++ static_cast(unid.c_str()),
++ endpoint,
++ unretained,
++ update_type,
++ red
++ );
++
++}
++static void uic_mqtt_dotdot_on_unify_switch_color_green_attribute_update(
++ const char *topic,
++ const char *message,
++ const size_t message_length) {
++ if (uic_mqtt_dotdot_unify_switch_color_attribute_green_callback == nullptr) {
++ return;
++ }
++
++ std::string unid;
++ uint8_t endpoint = 0; // Default value for endpoint-less topics.
++ if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) {
++ sl_log_debug(LOG_TAG,
++ "Error parsing UNID / Endpoint ID from topic %s. Ignoring",
++ topic);
++ return;
++ }
++
++ std::string last_item;
++ if (SL_STATUS_OK != uic_dotdot_mqtt::get_topic_last_item(topic,last_item)){
++ sl_log_debug(LOG_TAG,
++ "Error parsing last item from topic %s. Ignoring",
++ topic);
++ return;
++ }
++
++ uic_mqtt_dotdot_attribute_update_type_t update_type;
++ if (last_item == "Reported") {
++ update_type = UCL_REPORTED_UPDATED;
++ } else if (last_item == "Desired") {
++ update_type = UCL_DESIRED_UPDATED;
++ } else {
++ sl_log_debug(LOG_TAG,
++ "Unknown value type (neither Desired/Reported) for topic %s. Ignoring",
++ topic);
++ return;
++ }
++
++ // Empty message means unretained value.
++ bool unretained = false;
++ if (message_length == 0) {
++ unretained = true;
++ }
++
++
++ uint8_t green = {};
++
++ nlohmann::json json_payload;
++ try {
++
++ if (unretained == false) {
++ json_payload = nlohmann::json::parse(std::string(message));
++
++ if (json_payload.find("value") == json_payload.end()) {
++ sl_log_debug(LOG_TAG, "UnifySwitchColor::Green: Missing attribute element: 'value'\n");
++ return;
++ }
++// Start parsing value
++ green = json_payload.at("value").get();
++
++ // End parsing value
++ }
++
++ } catch (const std::exception& e) {
++ sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "value", message);
++ return;
++ }
++
++ uic_mqtt_dotdot_unify_switch_color_attribute_green_callback(
++ static_cast(unid.c_str()),
++ endpoint,
++ unretained,
++ update_type,
++ green
++ );
++
++}
++static void uic_mqtt_dotdot_on_unify_switch_color_blue_attribute_update(
++ const char *topic,
++ const char *message,
++ const size_t message_length) {
++ if (uic_mqtt_dotdot_unify_switch_color_attribute_blue_callback == nullptr) {
++ return;
++ }
++
++ std::string unid;
++ uint8_t endpoint = 0; // Default value for endpoint-less topics.
++ if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) {
++ sl_log_debug(LOG_TAG,
++ "Error parsing UNID / Endpoint ID from topic %s. Ignoring",
++ topic);
++ return;
++ }
++
++ std::string last_item;
++ if (SL_STATUS_OK != uic_dotdot_mqtt::get_topic_last_item(topic,last_item)){
++ sl_log_debug(LOG_TAG,
++ "Error parsing last item from topic %s. Ignoring",
++ topic);
++ return;
++ }
++
++ uic_mqtt_dotdot_attribute_update_type_t update_type;
++ if (last_item == "Reported") {
++ update_type = UCL_REPORTED_UPDATED;
++ } else if (last_item == "Desired") {
++ update_type = UCL_DESIRED_UPDATED;
++ } else {
++ sl_log_debug(LOG_TAG,
++ "Unknown value type (neither Desired/Reported) for topic %s. Ignoring",
++ topic);
++ return;
++ }
++
++ // Empty message means unretained value.
++ bool unretained = false;
++ if (message_length == 0) {
++ unretained = true;
++ }
++
++
++ uint8_t blue = {};
++
++ nlohmann::json json_payload;
++ try {
++
++ if (unretained == false) {
++ json_payload = nlohmann::json::parse(std::string(message));
++
++ if (json_payload.find("value") == json_payload.end()) {
++ sl_log_debug(LOG_TAG, "UnifySwitchColor::Blue: Missing attribute element: 'value'\n");
++ return;
++ }
++// Start parsing value
++ blue = json_payload.at("value").get();
++
++ // End parsing value
++ }
++
++ } catch (const std::exception& e) {
++ sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "value", message);
++ return;
++ }
++
++ uic_mqtt_dotdot_unify_switch_color_attribute_blue_callback(
++ static_cast(unid.c_str()),
++ endpoint,
++ unretained,
++ update_type,
++ blue
++ );
++
++}
++static void uic_mqtt_dotdot_on_unify_switch_color_amber_attribute_update(
++ const char *topic,
++ const char *message,
++ const size_t message_length) {
++ if (uic_mqtt_dotdot_unify_switch_color_attribute_amber_callback == nullptr) {
++ return;
++ }
++
++ std::string unid;
++ uint8_t endpoint = 0; // Default value for endpoint-less topics.
++ if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) {
++ sl_log_debug(LOG_TAG,
++ "Error parsing UNID / Endpoint ID from topic %s. Ignoring",
++ topic);
++ return;
++ }
++
++ std::string last_item;
++ if (SL_STATUS_OK != uic_dotdot_mqtt::get_topic_last_item(topic,last_item)){
++ sl_log_debug(LOG_TAG,
++ "Error parsing last item from topic %s. Ignoring",
++ topic);
++ return;
++ }
++
++ uic_mqtt_dotdot_attribute_update_type_t update_type;
++ if (last_item == "Reported") {
++ update_type = UCL_REPORTED_UPDATED;
++ } else if (last_item == "Desired") {
++ update_type = UCL_DESIRED_UPDATED;
++ } else {
++ sl_log_debug(LOG_TAG,
++ "Unknown value type (neither Desired/Reported) for topic %s. Ignoring",
++ topic);
++ return;
++ }
++
++ // Empty message means unretained value.
++ bool unretained = false;
++ if (message_length == 0) {
++ unretained = true;
++ }
++
++
++ uint8_t amber = {};
++
++ nlohmann::json json_payload;
++ try {
++
++ if (unretained == false) {
++ json_payload = nlohmann::json::parse(std::string(message));
++
++ if (json_payload.find("value") == json_payload.end()) {
++ sl_log_debug(LOG_TAG, "UnifySwitchColor::Amber: Missing attribute element: 'value'\n");
++ return;
++ }
++// Start parsing value
++ amber = json_payload.at("value").get();
++
++ // End parsing value
++ }
++
++ } catch (const std::exception& e) {
++ sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "value", message);
++ return;
++ }
++
++ uic_mqtt_dotdot_unify_switch_color_attribute_amber_callback(
++ static_cast(unid.c_str()),
++ endpoint,
++ unretained,
++ update_type,
++ amber
++ );
++
++}
++static void uic_mqtt_dotdot_on_unify_switch_color_cyan_attribute_update(
++ const char *topic,
++ const char *message,
++ const size_t message_length) {
++ if (uic_mqtt_dotdot_unify_switch_color_attribute_cyan_callback == nullptr) {
++ return;
++ }
++
++ std::string unid;
++ uint8_t endpoint = 0; // Default value for endpoint-less topics.
++ if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) {
++ sl_log_debug(LOG_TAG,
++ "Error parsing UNID / Endpoint ID from topic %s. Ignoring",
++ topic);
++ return;
++ }
++
++ std::string last_item;
++ if (SL_STATUS_OK != uic_dotdot_mqtt::get_topic_last_item(topic,last_item)){
++ sl_log_debug(LOG_TAG,
++ "Error parsing last item from topic %s. Ignoring",
++ topic);
++ return;
++ }
++
++ uic_mqtt_dotdot_attribute_update_type_t update_type;
++ if (last_item == "Reported") {
++ update_type = UCL_REPORTED_UPDATED;
++ } else if (last_item == "Desired") {
++ update_type = UCL_DESIRED_UPDATED;
++ } else {
++ sl_log_debug(LOG_TAG,
++ "Unknown value type (neither Desired/Reported) for topic %s. Ignoring",
++ topic);
++ return;
++ }
++
++ // Empty message means unretained value.
++ bool unretained = false;
++ if (message_length == 0) {
++ unretained = true;
++ }
++
++
++ uint8_t cyan = {};
++
++ nlohmann::json json_payload;
++ try {
++
++ if (unretained == false) {
++ json_payload = nlohmann::json::parse(std::string(message));
++
++ if (json_payload.find("value") == json_payload.end()) {
++ sl_log_debug(LOG_TAG, "UnifySwitchColor::Cyan: Missing attribute element: 'value'\n");
++ return;
++ }
++// Start parsing value
++ cyan = json_payload.at("value").get();
++
++ // End parsing value
++ }
++
++ } catch (const std::exception& e) {
++ sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "value", message);
++ return;
++ }
++
++ uic_mqtt_dotdot_unify_switch_color_attribute_cyan_callback(
++ static_cast(unid.c_str()),
++ endpoint,
++ unretained,
++ update_type,
++ cyan
++ );
++
++}
++static void uic_mqtt_dotdot_on_unify_switch_color_purple_attribute_update(
++ const char *topic,
++ const char *message,
++ const size_t message_length) {
++ if (uic_mqtt_dotdot_unify_switch_color_attribute_purple_callback == nullptr) {
++ return;
++ }
++
++ std::string unid;
++ uint8_t endpoint = 0; // Default value for endpoint-less topics.
++ if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) {
++ sl_log_debug(LOG_TAG,
++ "Error parsing UNID / Endpoint ID from topic %s. Ignoring",
++ topic);
++ return;
++ }
++
++ std::string last_item;
++ if (SL_STATUS_OK != uic_dotdot_mqtt::get_topic_last_item(topic,last_item)){
++ sl_log_debug(LOG_TAG,
++ "Error parsing last item from topic %s. Ignoring",
++ topic);
++ return;
++ }
++
++ uic_mqtt_dotdot_attribute_update_type_t update_type;
++ if (last_item == "Reported") {
++ update_type = UCL_REPORTED_UPDATED;
++ } else if (last_item == "Desired") {
++ update_type = UCL_DESIRED_UPDATED;
++ } else {
++ sl_log_debug(LOG_TAG,
++ "Unknown value type (neither Desired/Reported) for topic %s. Ignoring",
++ topic);
++ return;
++ }
++
++ // Empty message means unretained value.
++ bool unretained = false;
++ if (message_length == 0) {
++ unretained = true;
++ }
++
++
++ uint8_t purple = {};
++
++ nlohmann::json json_payload;
++ try {
++
++ if (unretained == false) {
++ json_payload = nlohmann::json::parse(std::string(message));
++
++ if (json_payload.find("value") == json_payload.end()) {
++ sl_log_debug(LOG_TAG, "UnifySwitchColor::Purple: Missing attribute element: 'value'\n");
++ return;
++ }
++// Start parsing value
++ purple = json_payload.at("value").get();
++
++ // End parsing value
++ }
++
++ } catch (const std::exception& e) {
++ sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "value", message);
++ return;
++ }
++
++ uic_mqtt_dotdot_unify_switch_color_attribute_purple_callback(
++ static_cast(unid.c_str()),
++ endpoint,
++ unretained,
++ update_type,
++ purple
++ );
++
++}
++
++///////////////////////////////////////////////////////////////////////////////
++// Attribute init functions for UnifySwitchColor
++///////////////////////////////////////////////////////////////////////////////
++sl_status_t uic_mqtt_dotdot_unify_switch_color_attributes_init()
++{
++ std::string base_topic = "ucl/by-unid/+/+/";
++
++ std::string subscription_topic;
++ if(uic_mqtt_dotdot_unify_switch_color_attribute_warm_white_callback) {
++ subscription_topic = base_topic + "UnifySwitchColor/Attributes/WarmWhite/#";
++ uic_mqtt_subscribe(subscription_topic.c_str(), &uic_mqtt_dotdot_on_unify_switch_color_warm_white_attribute_update);
++ }
++ if(uic_mqtt_dotdot_unify_switch_color_attribute_cold_white_callback) {
++ subscription_topic = base_topic + "UnifySwitchColor/Attributes/ColdWhite/#";
++ uic_mqtt_subscribe(subscription_topic.c_str(), &uic_mqtt_dotdot_on_unify_switch_color_cold_white_attribute_update);
++ }
++ if(uic_mqtt_dotdot_unify_switch_color_attribute_red_callback) {
++ subscription_topic = base_topic + "UnifySwitchColor/Attributes/Red/#";
++ uic_mqtt_subscribe(subscription_topic.c_str(), &uic_mqtt_dotdot_on_unify_switch_color_red_attribute_update);
++ }
++ if(uic_mqtt_dotdot_unify_switch_color_attribute_green_callback) {
++ subscription_topic = base_topic + "UnifySwitchColor/Attributes/Green/#";
++ uic_mqtt_subscribe(subscription_topic.c_str(), &uic_mqtt_dotdot_on_unify_switch_color_green_attribute_update);
++ }
++ if(uic_mqtt_dotdot_unify_switch_color_attribute_blue_callback) {
++ subscription_topic = base_topic + "UnifySwitchColor/Attributes/Blue/#";
++ uic_mqtt_subscribe(subscription_topic.c_str(), &uic_mqtt_dotdot_on_unify_switch_color_blue_attribute_update);
++ }
++ if(uic_mqtt_dotdot_unify_switch_color_attribute_amber_callback) {
++ subscription_topic = base_topic + "UnifySwitchColor/Attributes/Amber/#";
++ uic_mqtt_subscribe(subscription_topic.c_str(), &uic_mqtt_dotdot_on_unify_switch_color_amber_attribute_update);
++ }
++ if(uic_mqtt_dotdot_unify_switch_color_attribute_cyan_callback) {
++ subscription_topic = base_topic + "UnifySwitchColor/Attributes/Cyan/#";
++ uic_mqtt_subscribe(subscription_topic.c_str(), &uic_mqtt_dotdot_on_unify_switch_color_cyan_attribute_update);
++ }
++ if(uic_mqtt_dotdot_unify_switch_color_attribute_purple_callback) {
++ subscription_topic = base_topic + "UnifySwitchColor/Attributes/Purple/#";
++ uic_mqtt_subscribe(subscription_topic.c_str(), &uic_mqtt_dotdot_on_unify_switch_color_purple_attribute_update);
++ }
++
++ return SL_STATUS_OK;
++}
++
++
++///////////////////////////////////////////////////////////////////////////////
++// Callback setters and getters for UnifySwitchColor
++///////////////////////////////////////////////////////////////////////////////
++void uic_mqtt_dotdot_unify_switch_color_attribute_warm_white_callback_set(const uic_mqtt_dotdot_unify_switch_color_attribute_warm_white_callback_t callback)
++{
++ uic_mqtt_dotdot_unify_switch_color_attribute_warm_white_callback = callback;
++}
++void uic_mqtt_dotdot_unify_switch_color_attribute_cold_white_callback_set(const uic_mqtt_dotdot_unify_switch_color_attribute_cold_white_callback_t callback)
++{
++ uic_mqtt_dotdot_unify_switch_color_attribute_cold_white_callback = callback;
++}
++void uic_mqtt_dotdot_unify_switch_color_attribute_red_callback_set(const uic_mqtt_dotdot_unify_switch_color_attribute_red_callback_t callback)
++{
++ uic_mqtt_dotdot_unify_switch_color_attribute_red_callback = callback;
++}
++void uic_mqtt_dotdot_unify_switch_color_attribute_green_callback_set(const uic_mqtt_dotdot_unify_switch_color_attribute_green_callback_t callback)
++{
++ uic_mqtt_dotdot_unify_switch_color_attribute_green_callback = callback;
++}
++void uic_mqtt_dotdot_unify_switch_color_attribute_blue_callback_set(const uic_mqtt_dotdot_unify_switch_color_attribute_blue_callback_t callback)
++{
++ uic_mqtt_dotdot_unify_switch_color_attribute_blue_callback = callback;
++}
++void uic_mqtt_dotdot_unify_switch_color_attribute_amber_callback_set(const uic_mqtt_dotdot_unify_switch_color_attribute_amber_callback_t callback)
++{
++ uic_mqtt_dotdot_unify_switch_color_attribute_amber_callback = callback;
++}
++void uic_mqtt_dotdot_unify_switch_color_attribute_cyan_callback_set(const uic_mqtt_dotdot_unify_switch_color_attribute_cyan_callback_t callback)
++{
++ uic_mqtt_dotdot_unify_switch_color_attribute_cyan_callback = callback;
++}
++void uic_mqtt_dotdot_unify_switch_color_attribute_purple_callback_set(const uic_mqtt_dotdot_unify_switch_color_attribute_purple_callback_t callback)
++{
++ uic_mqtt_dotdot_unify_switch_color_attribute_purple_callback = callback;
++}
++
++// End of supported cluster.
++
+diff --git a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_command_helpers.cpp b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_command_helpers.cpp
+index 9dcceb98fc..9c5fea5705 100644
+--- a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_command_helpers.cpp
++++ b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_command_helpers.cpp
+@@ -15957,5 +15957,181 @@ void uic_mqtt_dotdot_parse_unify_humidity_control_write_attributes(
+
+
+
++}
++
++
++std::string get_json_payload_for_unify_switch_color_set_color_command(
++
++ const uic_mqtt_dotdot_unify_switch_color_command_set_color_fields_t *fields
++
++){
++ bool command_with_no_fields = true;
++
++ // Create a JSON payload from all the parameters
++ nlohmann::json json_payload;
++ command_with_no_fields = false;
++ // Single Value
++ // Non-enum and non-bitmask (struct, string or scalar)
++ json_payload["ColorComponentId"] = nlohmann::json(fields->color_component_id);
++ command_with_no_fields = false;
++ // Single Value
++ // Non-enum and non-bitmask (struct, string or scalar)
++ json_payload["Value"] = nlohmann::json(fields->value);
++ command_with_no_fields = false;
++ // Single Value
++ // Non-enum and non-bitmask (struct, string or scalar)
++ json_payload["Duration"] = nlohmann::json(fields->duration);
++
++ // Get the string
++ if (command_with_no_fields == true) {
++ return std::string("{}");
++ }
++ // Payload may contain data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters
++ return json_payload.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace);
++}
++
++
++void uic_mqtt_dotdot_parse_unify_switch_color_set_color(
++ nlohmann::json &jsn,
++ uint8_t &color_component_id,
++
++ uint8_t &value,
++
++ uint32_t &duration
++
++) {
++
++ if (jsn.at("ColorComponentId").is_null()) {
++ sl_log_debug(LOG_TAG, "Ignoring JSON Null object");
++ return;
++ }
++
++ color_component_id = jsn.at("ColorComponentId").get< uint8_t >();
++ if (jsn.at("Value").is_null()) {
++ sl_log_debug(LOG_TAG, "Ignoring JSON Null object");
++ return;
++ }
++
++ value = jsn.at("Value").get< uint8_t >();
++ if (jsn.at("Duration").is_null()) {
++ sl_log_debug(LOG_TAG, "Ignoring JSON Null object");
++ return;
++ }
++
++ duration = jsn.at("Duration").get< uint32_t >();
++ }
++
++
++std::string get_json_payload_for_unify_switch_color_start_stop_change_command(
++
++ const uic_mqtt_dotdot_unify_switch_color_command_start_stop_change_fields_t *fields
++
++){
++ bool command_with_no_fields = true;
++
++ // Create a JSON payload from all the parameters
++ nlohmann::json json_payload;
++ command_with_no_fields = false;
++ // Single Value
++ // Non-enum and non-bitmask (struct, string or scalar)
++ json_payload["StartStop"] = nlohmann::json(fields->start_stop);
++ command_with_no_fields = false;
++ // Single Value
++ // Non-enum and non-bitmask (struct, string or scalar)
++ json_payload["UpDown"] = nlohmann::json(fields->up_down);
++ command_with_no_fields = false;
++ // Single Value
++ // Non-enum and non-bitmask (struct, string or scalar)
++ json_payload["IgnorStartLevel"] = nlohmann::json(fields->ignor_start_level);
++ command_with_no_fields = false;
++ // Single Value
++ // Non-enum and non-bitmask (struct, string or scalar)
++ json_payload["ColorComponentId"] = nlohmann::json(fields->color_component_id);
++ command_with_no_fields = false;
++ // Single Value
++ // Non-enum and non-bitmask (struct, string or scalar)
++ json_payload["StartLevel"] = nlohmann::json(fields->start_level);
++ command_with_no_fields = false;
++ // Single Value
++ // Non-enum and non-bitmask (struct, string or scalar)
++ json_payload["Duration"] = nlohmann::json(fields->duration);
++
++ // Get the string
++ if (command_with_no_fields == true) {
++ return std::string("{}");
++ }
++ // Payload may contain data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters
++ return json_payload.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace);
++}
++
++
++void uic_mqtt_dotdot_parse_unify_switch_color_start_stop_change(
++ nlohmann::json &jsn,
++ bool &start_stop,
++
++ bool &up_down,
++
++ bool &ignor_start_level,
++
++ uint8_t &color_component_id,
++
++ uint8_t &start_level,
++
++ uint32_t &duration
++
++) {
++
++ if (jsn.at("StartStop").is_null()) {
++ sl_log_debug(LOG_TAG, "Ignoring JSON Null object");
++ return;
++ }
++
++ start_stop = jsn.at("StartStop").get< bool >();
++ if (jsn.at("UpDown").is_null()) {
++ sl_log_debug(LOG_TAG, "Ignoring JSON Null object");
++ return;
++ }
++
++ up_down = jsn.at("UpDown").get< bool >();
++ if (jsn.at("IgnorStartLevel").is_null()) {
++ sl_log_debug(LOG_TAG, "Ignoring JSON Null object");
++ return;
++ }
++
++ ignor_start_level = jsn.at("IgnorStartLevel").get< bool >();
++ if (jsn.at("ColorComponentId").is_null()) {
++ sl_log_debug(LOG_TAG, "Ignoring JSON Null object");
++ return;
++ }
++
++ color_component_id = jsn.at("ColorComponentId").get< uint8_t >();
++ if (jsn.at("StartLevel").is_null()) {
++ sl_log_debug(LOG_TAG, "Ignoring JSON Null object");
++ return;
++ }
++
++ start_level = jsn.at("StartLevel").get< uint8_t >();
++ if (jsn.at("Duration").is_null()) {
++ sl_log_debug(LOG_TAG, "Ignoring JSON Null object");
++ return;
++ }
++
++ duration = jsn.at("Duration").get< uint32_t >();
++ }
++
++
++/**
++ * @brief JSON parser for ::WriteAttributes command arguments.
++ *
++ * Parse incoming JSON object to populate command arguments passed in by reference.
++ */
++void uic_mqtt_dotdot_parse_unify_switch_color_write_attributes(
++ nlohmann::json &jsn,
++ uic_mqtt_dotdot_unify_switch_color_state_t &new_state,
++ uic_mqtt_dotdot_unify_switch_color_updated_state_t &new_updated_state
++) {
++
++
++
+ }
+
+diff --git a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_command_helpers.hpp b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_command_helpers.hpp
+index ede2d6189e..5ecd3fe972 100644
+--- a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_command_helpers.hpp
++++ b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_command_helpers.hpp
+@@ -6650,6 +6650,88 @@ void uic_mqtt_dotdot_parse_unify_humidity_control_write_attributes(
+ );
+
+
++/**
++ * @brief Private helper function that will create a JSON string based on the
++ * fields of a UnifySwitchColor SetColor command
++ *
++ * @param fields Struct pointer with the list of fields for the command
++ *
++ * @returns std::string that contains JSON payload
++ */
++std::string get_json_payload_for_unify_switch_color_set_color_command(
++
++ const uic_mqtt_dotdot_unify_switch_color_command_set_color_fields_t *fields
++
++);
++
++
++/**
++ * @brief JSON parser for UnifySwitchColor SetColor command arguments.
++ *
++ * Parse incoming JSON object to populate command arguments passed in by reference.
++ */
++void uic_mqtt_dotdot_parse_unify_switch_color_set_color(
++ nlohmann::json &jsn,
++ uint8_t &color_component_id,
++
++ uint8_t &value,
++
++ uint32_t &duration
++
++);
++
++
++
++/**
++ * @brief Private helper function that will create a JSON string based on the
++ * fields of a UnifySwitchColor StartStopChange command
++ *
++ * @param fields Struct pointer with the list of fields for the command
++ *
++ * @returns std::string that contains JSON payload
++ */
++std::string get_json_payload_for_unify_switch_color_start_stop_change_command(
++
++ const uic_mqtt_dotdot_unify_switch_color_command_start_stop_change_fields_t *fields
++
++);
++
++
++/**
++ * @brief JSON parser for UnifySwitchColor StartStopChange command arguments.
++ *
++ * Parse incoming JSON object to populate command arguments passed in by reference.
++ */
++void uic_mqtt_dotdot_parse_unify_switch_color_start_stop_change(
++ nlohmann::json &jsn,
++ bool &start_stop,
++
++ bool &up_down,
++
++ bool &ignor_start_level,
++
++ uint8_t &color_component_id,
++
++ uint8_t &start_level,
++
++ uint32_t &duration
++
++);
++
++
++
++/**
++ * @brief JSON parser for UnifySwitchColor WriteAttributes command arguments.
++ *
++ * Parse incoming JSON object to populate command arguments passed in by reference.
++ */
++void uic_mqtt_dotdot_parse_unify_switch_color_write_attributes(
++ nlohmann::json &jsn,
++ uic_mqtt_dotdot_unify_switch_color_state_t &new_state,
++ uic_mqtt_dotdot_unify_switch_color_updated_state_t &new_updated_state
++);
++
++
+
+ #endif //DOTDOT_MQTT_COMMAND_HELPERS_HPP
+ /** @} end dotdot_mqtt_command_helpers */
+diff --git a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_generated_commands.cpp b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_generated_commands.cpp
+index 523ffd0855..e2e522b193 100644
+--- a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_generated_commands.cpp
++++ b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_generated_commands.cpp
+@@ -12047,3 +12047,115 @@ void uic_mqtt_dotdot_unify_humidity_control_publish_generated_write_attributes_c
+ false);
+ }
+
++/**
++ * @brief Publishes an incoming/generated SetColor command for
++ * the UnifySwitchColor cluster.
++ *
++ * Publication will be made at the following topic
++ * ucl/by-unid/UNID/epID/UnifySwitchColor/GeneratedCommands/SetColor
++ *
++ * @param unid The UNID of the node that sent us the command.
++ *
++ * @param endpoint The Endpoint ID of the node that sent us the command.
++ *
++ *
++ * @param fields Struct pointer with the fields value of the command
++ *
++ */
++void uic_mqtt_dotdot_unify_switch_color_publish_generated_set_color_command(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint,
++ const uic_mqtt_dotdot_unify_switch_color_command_set_color_fields_t *fields
++
++) {
++ // Create the topic
++ std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" +
++ std::to_string(endpoint) + "/";
++ topic += "UnifySwitchColor/GeneratedCommands/SetColor";
++
++ std::string payload =
++ get_json_payload_for_unify_switch_color_set_color_command(
++ fields);
++
++ // Publish our command
++ uic_mqtt_publish(topic.c_str(),
++ payload.c_str(),
++ payload.size(),
++ false);
++}
++/**
++ * @brief Publishes an incoming/generated StartStopChange command for
++ * the UnifySwitchColor cluster.
++ *
++ * Publication will be made at the following topic
++ * ucl/by-unid/UNID/epID/UnifySwitchColor/GeneratedCommands/StartStopChange
++ *
++ * @param unid The UNID of the node that sent us the command.
++ *
++ * @param endpoint The Endpoint ID of the node that sent us the command.
++ *
++ *
++ * @param fields Struct pointer with the fields value of the command
++ *
++ */
++void uic_mqtt_dotdot_unify_switch_color_publish_generated_start_stop_change_command(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint,
++ const uic_mqtt_dotdot_unify_switch_color_command_start_stop_change_fields_t *fields
++
++) {
++ // Create the topic
++ std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" +
++ std::to_string(endpoint) + "/";
++ topic += "UnifySwitchColor/GeneratedCommands/StartStopChange";
++
++ std::string payload =
++ get_json_payload_for_unify_switch_color_start_stop_change_command(
++ fields);
++
++ // Publish our command
++ uic_mqtt_publish(topic.c_str(),
++ payload.c_str(),
++ payload.size(),
++ false);
++}
++
++
++/**
++ * @brief Publishes an incoming/generated WriteAttributes command for
++ * the UnifySwitchColor cluster.
++ *
++ * Publication will be made at the following topic
++ * ucl/by-unid/UNID/epID/UnifySwitchColor/GeneratedCommands/WriteAttributes
++ *
++ * @param unid The UNID of the node that sent us the command.
++ *
++ * @param endpoint The Endpoint ID of the node that sent us the command.
++ *
++ * @param attribute_values Values to assign to the attributes
++ * @param attribute_list List of attributes that are written
++ */
++void uic_mqtt_dotdot_unify_switch_color_publish_generated_write_attributes_command(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint,
++ uic_mqtt_dotdot_unify_switch_color_state_t attribute_values,
++ uic_mqtt_dotdot_unify_switch_color_updated_state_t attribute_list
++){
++ // Create the topic
++ std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" +
++ std::to_string(endpoint) + "/";
++ topic += "UnifySwitchColor/GeneratedCommands/WriteAttributes";
++
++ nlohmann::json json_object = nlohmann::json::object();
++
++
++ // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters
++ std::string payload = json_object.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace);
++
++ // Publish our command
++ uic_mqtt_publish(topic.c_str(),
++ payload.c_str(),
++ payload.size(),
++ false);
++}
++
+diff --git a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_group_commands.cpp b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_group_commands.cpp
+index 295e2af47e..15eb05a694 100644
+--- a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_group_commands.cpp
++++ b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_group_commands.cpp
+@@ -393,6 +393,11 @@ static uic_mqtt_dotdot_by_group_unify_humidity_control_setpoint_set_callback_t u
+ static uic_mqtt_dotdot_by_group_unify_humidity_control_write_attributes_callback_t uic_mqtt_dotdot_by_group_unify_humidity_control_write_attributes_callback = nullptr;
+
+
++static uic_mqtt_dotdot_by_group_unify_switch_color_set_color_callback_t uic_mqtt_dotdot_by_group_unify_switch_color_set_color_callback = nullptr;
++static uic_mqtt_dotdot_by_group_unify_switch_color_start_stop_change_callback_t uic_mqtt_dotdot_by_group_unify_switch_color_start_stop_change_callback = nullptr;
++static uic_mqtt_dotdot_by_group_unify_switch_color_write_attributes_callback_t uic_mqtt_dotdot_by_group_unify_switch_color_write_attributes_callback = nullptr;
++
++
+
+ // Callbacks setters
+
+@@ -2047,6 +2052,27 @@ void uic_mqtt_dotdot_by_group_unify_humidity_control_write_attributes_callback_s
+
+
+
++// Callbacks setters
++
++void uic_mqtt_dotdot_by_group_unify_switch_color_set_color_callback_set(const uic_mqtt_dotdot_by_group_unify_switch_color_set_color_callback_t callback)
++{
++ uic_mqtt_dotdot_by_group_unify_switch_color_set_color_callback = callback;
++}
++
++
++void uic_mqtt_dotdot_by_group_unify_switch_color_start_stop_change_callback_set(const uic_mqtt_dotdot_by_group_unify_switch_color_start_stop_change_callback_t callback)
++{
++ uic_mqtt_dotdot_by_group_unify_switch_color_start_stop_change_callback = callback;
++}
++
++void uic_mqtt_dotdot_by_group_unify_switch_color_write_attributes_callback_set(
++ const uic_mqtt_dotdot_by_group_unify_switch_color_write_attributes_callback_t callback)
++{
++ uic_mqtt_dotdot_by_group_unify_switch_color_write_attributes_callback = callback;
++}
++
++
++
+
+ // Callback function for incoming publications on ucl/by-group/+/Basic/Commands/ResetToFactoryDefaults
+ static void uic_mqtt_dotdot_on_by_group_basic_reset_to_factory_defaults(
+@@ -25768,6 +25794,311 @@ sl_status_t uic_mqtt_dotdot_by_group_unify_humidity_control_init()
+
+
+
++
++// Callback function for incoming publications on ucl/by-group/+/UnifySwitchColor/Commands/SetColor
++static void uic_mqtt_dotdot_on_by_group_unify_switch_color_set_color(
++ const char *topic,
++ const char *message,
++ const size_t message_length)
++{
++ if ((group_dispatch_callback == nullptr) && (uic_mqtt_dotdot_by_group_unify_switch_color_set_color_callback == nullptr)) {
++ return;
++ }
++ if (message_length == 0) {
++ return;
++ }
++
++ dotdot_group_id_t group_id = 0U;
++ if(!uic_dotdot_mqtt::parse_topic_group_id(topic,group_id)) {
++ sl_log_debug(LOG_TAG,
++ "Failed to parse GroupId from topic %s. Ignoring",
++ topic);
++ return;
++ }
++
++ // Pass to command-specific callback if set. Otherwise, pass to
++ // group-dispatch callback
++ if (uic_mqtt_dotdot_by_group_unify_switch_color_set_color_callback != nullptr) {
++
++
++ uic_mqtt_dotdot_unify_switch_color_command_set_color_fields_t fields;
++
++
++ nlohmann::json jsn;
++ try {
++ jsn = nlohmann::json::parse(std::string(message));
++
++
++ uic_mqtt_dotdot_parse_unify_switch_color_set_color(
++ jsn,
++ fields.color_component_id,
++
++ fields.value,
++
++ fields.duration
++ );
++
++ // Populate list fields from vector or string types
++
++
++ } catch (const nlohmann::json::parse_error& e) {
++ // Catch JSON object field parsing errors
++ sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UnifySwitchColor", "SetColor");
++ return;
++ } catch (const nlohmann::json::exception& e) {
++ // Catch JSON object field parsing errors
++ sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifySwitchColor", "SetColor", e.what());
++ return;
++ } catch (const std::exception& e) {
++ sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifySwitchColor", "SetColor", "");
++ return;
++ }
++
++ uic_mqtt_dotdot_by_group_unify_switch_color_set_color_callback(
++ group_id,
++ &fields
++ );
++ } else if ((group_dispatch_callback != nullptr) && (!get_uic_mqtt_dotdot_unify_switch_color_set_color_callback().empty())) {
++ // group-dispatch callback only called if the command-specific by-unid
++ // callback is set
++ try {
++ nlohmann::json jsn = nlohmann::json::parse(std::string(message));
++ if (jsn.find("ColorComponentId") == jsn.end()) {
++ sl_log_debug(LOG_TAG, "UnifySwitchColor::SetColor: Missing command-argument: ColorComponentId\n");
++ return;
++ }
++ if (jsn.find("Value") == jsn.end()) {
++ sl_log_debug(LOG_TAG, "UnifySwitchColor::SetColor: Missing command-argument: Value\n");
++ return;
++ }
++ if (jsn.find("Duration") == jsn.end()) {
++ sl_log_debug(LOG_TAG, "UnifySwitchColor::SetColor: Missing command-argument: Duration\n");
++ return;
++ }
++
++ group_dispatch_callback(
++ group_id,
++ "UnifySwitchColor",
++ "SetColor",
++ message,
++ message_length,
++ uic_mqtt_dotdot_on_unify_switch_color_set_color);
++
++ } catch (...) {
++ sl_log_debug(LOG_TAG, "SetColor: Unable to parse JSON payload.\n");
++ return;
++ }
++ }
++
++}
++
++// Callback function for incoming publications on ucl/by-group/+/UnifySwitchColor/Commands/StartStopChange
++static void uic_mqtt_dotdot_on_by_group_unify_switch_color_start_stop_change(
++ const char *topic,
++ const char *message,
++ const size_t message_length)
++{
++ if ((group_dispatch_callback == nullptr) && (uic_mqtt_dotdot_by_group_unify_switch_color_start_stop_change_callback == nullptr)) {
++ return;
++ }
++ if (message_length == 0) {
++ return;
++ }
++
++ dotdot_group_id_t group_id = 0U;
++ if(!uic_dotdot_mqtt::parse_topic_group_id(topic,group_id)) {
++ sl_log_debug(LOG_TAG,
++ "Failed to parse GroupId from topic %s. Ignoring",
++ topic);
++ return;
++ }
++
++ // Pass to command-specific callback if set. Otherwise, pass to
++ // group-dispatch callback
++ if (uic_mqtt_dotdot_by_group_unify_switch_color_start_stop_change_callback != nullptr) {
++
++
++ uic_mqtt_dotdot_unify_switch_color_command_start_stop_change_fields_t fields;
++
++
++ nlohmann::json jsn;
++ try {
++ jsn = nlohmann::json::parse(std::string(message));
++
++
++ uic_mqtt_dotdot_parse_unify_switch_color_start_stop_change(
++ jsn,
++ fields.start_stop,
++
++ fields.up_down,
++
++ fields.ignor_start_level,
++
++ fields.color_component_id,
++
++ fields.start_level,
++
++ fields.duration
++ );
++
++ // Populate list fields from vector or string types
++
++
++ } catch (const nlohmann::json::parse_error& e) {
++ // Catch JSON object field parsing errors
++ sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UnifySwitchColor", "StartStopChange");
++ return;
++ } catch (const nlohmann::json::exception& e) {
++ // Catch JSON object field parsing errors
++ sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifySwitchColor", "StartStopChange", e.what());
++ return;
++ } catch (const std::exception& e) {
++ sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifySwitchColor", "StartStopChange", "");
++ return;
++ }
++
++ uic_mqtt_dotdot_by_group_unify_switch_color_start_stop_change_callback(
++ group_id,
++ &fields
++ );
++ } else if ((group_dispatch_callback != nullptr) && (!get_uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback().empty())) {
++ // group-dispatch callback only called if the command-specific by-unid
++ // callback is set
++ try {
++ nlohmann::json jsn = nlohmann::json::parse(std::string(message));
++ if (jsn.find("StartStop") == jsn.end()) {
++ sl_log_debug(LOG_TAG, "UnifySwitchColor::StartStopChange: Missing command-argument: StartStop\n");
++ return;
++ }
++ if (jsn.find("UpDown") == jsn.end()) {
++ sl_log_debug(LOG_TAG, "UnifySwitchColor::StartStopChange: Missing command-argument: UpDown\n");
++ return;
++ }
++ if (jsn.find("IgnorStartLevel") == jsn.end()) {
++ sl_log_debug(LOG_TAG, "UnifySwitchColor::StartStopChange: Missing command-argument: IgnorStartLevel\n");
++ return;
++ }
++ if (jsn.find("ColorComponentId") == jsn.end()) {
++ sl_log_debug(LOG_TAG, "UnifySwitchColor::StartStopChange: Missing command-argument: ColorComponentId\n");
++ return;
++ }
++ if (jsn.find("StartLevel") == jsn.end()) {
++ sl_log_debug(LOG_TAG, "UnifySwitchColor::StartStopChange: Missing command-argument: StartLevel\n");
++ return;
++ }
++ if (jsn.find("Duration") == jsn.end()) {
++ sl_log_debug(LOG_TAG, "UnifySwitchColor::StartStopChange: Missing command-argument: Duration\n");
++ return;
++ }
++
++ group_dispatch_callback(
++ group_id,
++ "UnifySwitchColor",
++ "StartStopChange",
++ message,
++ message_length,
++ uic_mqtt_dotdot_on_unify_switch_color_start_stop_change);
++
++ } catch (...) {
++ sl_log_debug(LOG_TAG, "StartStopChange: Unable to parse JSON payload.\n");
++ return;
++ }
++ }
++
++}
++
++static void uic_mqtt_dotdot_on_by_group_unify_switch_color_WriteAttributes(
++ const char *topic,
++ const char *message,
++ const size_t message_length)
++{
++
++ if ((group_dispatch_callback == nullptr) && (uic_mqtt_dotdot_by_group_unify_switch_color_write_attributes_callback == nullptr)) {
++ return;
++ }
++ if (message_length == 0) {
++ return;
++ }
++
++ dotdot_group_id_t group_id = 0U;
++ if(!uic_dotdot_mqtt::parse_topic_group_id(topic,group_id)) {
++ sl_log_debug(LOG_TAG,
++ "Failed to parse GroupId from topic %s. Ignoring",
++ topic);
++ return;
++ }
++
++ if ((group_dispatch_callback != nullptr) && (!get_uic_mqtt_dotdot_unify_switch_color_write_attributes_callback().empty())) {
++ try {
++ group_dispatch_callback(group_id,
++ "UnifySwitchColor",
++ "WriteAttributes",
++ message,
++ message_length,
++ uic_mqtt_dotdot_on_unify_switch_color_WriteAttributes);
++
++ } catch (...) {
++ sl_log_debug(LOG_TAG, "UnifySwitchColor: Unable to parse JSON payload.\n");
++ return;
++ }
++ } else if (uic_mqtt_dotdot_by_group_unify_switch_color_write_attributes_callback != nullptr) {
++
++ uic_mqtt_dotdot_unify_switch_color_state_t new_state = {};
++ uic_mqtt_dotdot_unify_switch_color_updated_state_t new_updated_state = {};
++
++
++ nlohmann::json jsn;
++ try {
++ jsn = nlohmann::json::parse(std::string(message));
++
++ uic_mqtt_dotdot_parse_unify_switch_color_write_attributes(
++ jsn,
++ new_state,
++ new_updated_state
++ );
++ } catch (const nlohmann::json::parse_error& e) {
++ // Catch JSON object field parsing errors
++ sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UnifySwitchColor", "WriteAttributes");
++ return;
++ } catch (const nlohmann::json::exception& e) {
++ // Catch JSON object field parsing errors
++ sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifySwitchColor", "WriteAttributes", e.what());
++ return;
++ } catch (const std::exception& e) {
++ sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifySwitchColor", "WriteAttributes", "");
++ return;
++ }
++
++ uic_mqtt_dotdot_by_group_unify_switch_color_write_attributes_callback(
++ group_id,
++ new_state,
++ new_updated_state
++ );
++ }
++}
++
++sl_status_t uic_mqtt_dotdot_by_group_unify_switch_color_init()
++{
++ std::string subscription_topic;
++ const std::string topic_bygroup = TOPIC_BY_GROUP_PREFIX;
++ if(uic_mqtt_dotdot_by_group_unify_switch_color_write_attributes_callback) {
++ subscription_topic = topic_bygroup + "UnifySwitchColor/Commands/WriteAttributes";
++ uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_by_group_unify_switch_color_WriteAttributes);
++ }
++ if (uic_mqtt_dotdot_by_group_unify_switch_color_set_color_callback) {
++ subscription_topic = topic_bygroup + "UnifySwitchColor/Commands/SetColor";
++ uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_by_group_unify_switch_color_set_color);
++ }
++ if (uic_mqtt_dotdot_by_group_unify_switch_color_start_stop_change_callback) {
++ subscription_topic = topic_bygroup + "UnifySwitchColor/Commands/StartStopChange";
++ uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_by_group_unify_switch_color_start_stop_change);
++ }
++
++ return SL_STATUS_OK;
++}
++
++
++
+ void uic_mqtt_dotdot_set_group_dispatch_callback(group_dispatch_t callback)
+ {
+ // Check for uninitialized value in order to subscribe with on_group handlers
+@@ -26074,6 +26405,10 @@ void uic_mqtt_dotdot_set_group_dispatch_callback(group_dispatch_t callback)
+ uic_mqtt_subscribe("ucl/by-group/+/UnifyHumidityControl/Commands/ModeSet", uic_mqtt_dotdot_on_by_group_unify_humidity_control_mode_set);
+ uic_mqtt_subscribe("ucl/by-group/+/UnifyHumidityControl/Commands/SetpointSet", uic_mqtt_dotdot_on_by_group_unify_humidity_control_setpoint_set);
+
++ uic_mqtt_subscribe("ucl/by-group/+/UnifySwitchColor/Commands/WriteAttributes", uic_mqtt_dotdot_on_by_group_unify_switch_color_WriteAttributes);
++ uic_mqtt_subscribe("ucl/by-group/+/UnifySwitchColor/Commands/SetColor", uic_mqtt_dotdot_on_by_group_unify_switch_color_set_color);
++ uic_mqtt_subscribe("ucl/by-group/+/UnifySwitchColor/Commands/StartStopChange", uic_mqtt_dotdot_on_by_group_unify_switch_color_start_stop_change);
++
+ }
+
+ group_dispatch_callback = callback;
+diff --git a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_helpers.cpp b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_helpers.cpp
+index 620772af1c..082fdb9bdf 100644
+--- a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_helpers.cpp
++++ b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_helpers.cpp
+@@ -10644,6 +10644,57 @@ std::string get_enum_value_name(
+ #endif
+ }
+
++ if (65441 == cluster_id) {
++ #ifdef UNIFY_SWITCH_COLOR_WARM_WHITE_ENUM_NAME_AVAILABLE
++ if (0 == attribute_id) {
++ // FIXME: Some attributes don't work because multi-upper case names end up like this: unify_switch_colorwarm_white instead of this: unify_switch_color_warm_white
++ return unify_switch_color_warm_white_get_enum_value_name(value);
++ }
++ #endif
++ #ifdef UNIFY_SWITCH_COLOR_COLD_WHITE_ENUM_NAME_AVAILABLE
++ if (1 == attribute_id) {
++ // FIXME: Some attributes don't work because multi-upper case names end up like this: unify_switch_colorcold_white instead of this: unify_switch_color_cold_white
++ return unify_switch_color_cold_white_get_enum_value_name(value);
++ }
++ #endif
++ #ifdef UNIFY_SWITCH_COLOR_RED_ENUM_NAME_AVAILABLE
++ if (2 == attribute_id) {
++ // FIXME: Some attributes don't work because multi-upper case names end up like this: unify_switch_colorred instead of this: unify_switch_color_red
++ return unify_switch_color_red_get_enum_value_name(value);
++ }
++ #endif
++ #ifdef UNIFY_SWITCH_COLOR_GREEN_ENUM_NAME_AVAILABLE
++ if (3 == attribute_id) {
++ // FIXME: Some attributes don't work because multi-upper case names end up like this: unify_switch_colorgreen instead of this: unify_switch_color_green
++ return unify_switch_color_green_get_enum_value_name(value);
++ }
++ #endif
++ #ifdef UNIFY_SWITCH_COLOR_BLUE_ENUM_NAME_AVAILABLE
++ if (4 == attribute_id) {
++ // FIXME: Some attributes don't work because multi-upper case names end up like this: unify_switch_colorblue instead of this: unify_switch_color_blue
++ return unify_switch_color_blue_get_enum_value_name(value);
++ }
++ #endif
++ #ifdef UNIFY_SWITCH_COLOR_AMBER_ENUM_NAME_AVAILABLE
++ if (5 == attribute_id) {
++ // FIXME: Some attributes don't work because multi-upper case names end up like this: unify_switch_coloramber instead of this: unify_switch_color_amber
++ return unify_switch_color_amber_get_enum_value_name(value);
++ }
++ #endif
++ #ifdef UNIFY_SWITCH_COLOR_CYAN_ENUM_NAME_AVAILABLE
++ if (6 == attribute_id) {
++ // FIXME: Some attributes don't work because multi-upper case names end up like this: unify_switch_colorcyan instead of this: unify_switch_color_cyan
++ return unify_switch_color_cyan_get_enum_value_name(value);
++ }
++ #endif
++ #ifdef UNIFY_SWITCH_COLOR_PURPLE_ENUM_NAME_AVAILABLE
++ if (7 == attribute_id) {
++ // FIXME: Some attributes don't work because multi-upper case names end up like this: unify_switch_colorpurple instead of this: unify_switch_color_purple
++ return unify_switch_color_purple_get_enum_value_name(value);
++ }
++ #endif
++ }
++
+
+ std::string value_name;
+ return value_name;
+@@ -15202,6 +15253,57 @@ uint32_t get_enum_name_value(
+ #endif
+ }
+
++ if (65441 == cluster_id) {
++ #ifdef UNIFY_SWITCH_COLOR_WARM_WHITE_ENUM_NAME_AVAILABLE
++ if (0 == attribute_id) {
++ // FIXME: Some attributes don't work because multi-upper case names end up like this: unify_switch_colorwarm_white instead of this: unify_switch_color_warm_white
++ return unify_switch_color_warm_white_get_enum_value_number(name);
++ }
++ #endif
++ #ifdef UNIFY_SWITCH_COLOR_COLD_WHITE_ENUM_NAME_AVAILABLE
++ if (1 == attribute_id) {
++ // FIXME: Some attributes don't work because multi-upper case names end up like this: unify_switch_colorcold_white instead of this: unify_switch_color_cold_white
++ return unify_switch_color_cold_white_get_enum_value_number(name);
++ }
++ #endif
++ #ifdef UNIFY_SWITCH_COLOR_RED_ENUM_NAME_AVAILABLE
++ if (2 == attribute_id) {
++ // FIXME: Some attributes don't work because multi-upper case names end up like this: unify_switch_colorred instead of this: unify_switch_color_red
++ return unify_switch_color_red_get_enum_value_number(name);
++ }
++ #endif
++ #ifdef UNIFY_SWITCH_COLOR_GREEN_ENUM_NAME_AVAILABLE
++ if (3 == attribute_id) {
++ // FIXME: Some attributes don't work because multi-upper case names end up like this: unify_switch_colorgreen instead of this: unify_switch_color_green
++ return unify_switch_color_green_get_enum_value_number(name);
++ }
++ #endif
++ #ifdef UNIFY_SWITCH_COLOR_BLUE_ENUM_NAME_AVAILABLE
++ if (4 == attribute_id) {
++ // FIXME: Some attributes don't work because multi-upper case names end up like this: unify_switch_colorblue instead of this: unify_switch_color_blue
++ return unify_switch_color_blue_get_enum_value_number(name);
++ }
++ #endif
++ #ifdef UNIFY_SWITCH_COLOR_AMBER_ENUM_NAME_AVAILABLE
++ if (5 == attribute_id) {
++ // FIXME: Some attributes don't work because multi-upper case names end up like this: unify_switch_coloramber instead of this: unify_switch_color_amber
++ return unify_switch_color_amber_get_enum_value_number(name);
++ }
++ #endif
++ #ifdef UNIFY_SWITCH_COLOR_CYAN_ENUM_NAME_AVAILABLE
++ if (6 == attribute_id) {
++ // FIXME: Some attributes don't work because multi-upper case names end up like this: unify_switch_colorcyan instead of this: unify_switch_color_cyan
++ return unify_switch_color_cyan_get_enum_value_number(name);
++ }
++ #endif
++ #ifdef UNIFY_SWITCH_COLOR_PURPLE_ENUM_NAME_AVAILABLE
++ if (7 == attribute_id) {
++ // FIXME: Some attributes don't work because multi-upper case names end up like this: unify_switch_colorpurple instead of this: unify_switch_color_purple
++ return unify_switch_color_purple_get_enum_value_number(name);
++ }
++ #endif
++ }
++
+
+ // No known numeric value is set for this string.
+ // Return UINT32_MAX to indicate an error.
+diff --git a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_send_commands.cpp b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_send_commands.cpp
+index cbee8704d9..d142a852d8 100644
+--- a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_send_commands.cpp
++++ b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_send_commands.cpp
+@@ -15295,3 +15295,151 @@ void uic_mqtt_dotdot_unify_humidity_control_publish_setpoint_set_command_to_grou
+ payload.size(),
+ false);
+ }
++
++/**
++ * @brief Sends/Publishes a SetColor command for
++ * the UnifySwitchColor cluster to a destination.
++ *
++ * Publication will be made at the following topic
++ * ucl/by-unid/UNID/epID/UnifySwitchColor/Commands/SetColor
++ *
++ * @param destination_unid The UNID of the node that should receive the command.
++ *
++ * @param destination_endpoint The Endpoint ID of the node that should receive the command.
++ *
++ *
++ * @param fields Struct pointer with the fields value of the command
++ *
++ */
++void uic_mqtt_dotdot_unify_switch_color_publish_set_color_command(
++ const dotdot_unid_t destination_unid,
++ const dotdot_endpoint_id_t destination_endpoint,
++ const uic_mqtt_dotdot_unify_switch_color_command_set_color_fields_t *fields
++
++) {
++ // Create the topic
++ std::string topic = "ucl/by-unid/"+ std::string(destination_unid) + "/ep" +
++ std::to_string(destination_endpoint) + "/";
++ topic += "UnifySwitchColor/Commands/SetColor";
++
++
++ std::string payload =
++ get_json_payload_for_unify_switch_color_set_color_command(
++ fields);
++
++ sl_log_debug(LOG_TAG, "Sending command to %s with payload %s ---", topic.c_str() , payload.c_str());
++
++ // Publish our command, not retained
++ uic_mqtt_publish(topic.c_str(),
++ payload.c_str(),
++ payload.size(),
++ false);
++}
++
++/**
++ * @brief Sends/Publishes a SetColor command for
++ * the UnifySwitchColor cluster to a group.
++ *
++ * Publication will be made at the following topic
++ * ucl/by-group/GroupID/UnifySwitchColor/Commands/SetColor
++ *
++ * @param destination_group_id The GroupID that should receive the command.
++ *
++ * @param fields Struct pointer with the fields value of the command
++ *
++ */
++void uic_mqtt_dotdot_unify_switch_color_publish_set_color_command_to_group(
++ uint16_t destination_group_id,
++ const uic_mqtt_dotdot_unify_switch_color_command_set_color_fields_t *fields
++
++){
++ // Create the topic
++ std::string topic = "ucl/by-group/"+ std::to_string(destination_group_id) +
++ "/UnifySwitchColor/Commands/SetColor";
++
++ std::string payload =
++ get_json_payload_for_unify_switch_color_set_color_command(
++ fields);
++
++ sl_log_info(LOG_TAG, "Sending group command to %s with payload %s ---", topic.c_str() , payload.c_str());
++
++ // Publish our command, not retained
++ uic_mqtt_publish(topic.c_str(),
++ payload.c_str(),
++ payload.size(),
++ false);
++}
++
++/**
++ * @brief Sends/Publishes a StartStopChange command for
++ * the UnifySwitchColor cluster to a destination.
++ *
++ * Publication will be made at the following topic
++ * ucl/by-unid/UNID/epID/UnifySwitchColor/Commands/StartStopChange
++ *
++ * @param destination_unid The UNID of the node that should receive the command.
++ *
++ * @param destination_endpoint The Endpoint ID of the node that should receive the command.
++ *
++ *
++ * @param fields Struct pointer with the fields value of the command
++ *
++ */
++void uic_mqtt_dotdot_unify_switch_color_publish_start_stop_change_command(
++ const dotdot_unid_t destination_unid,
++ const dotdot_endpoint_id_t destination_endpoint,
++ const uic_mqtt_dotdot_unify_switch_color_command_start_stop_change_fields_t *fields
++
++) {
++ // Create the topic
++ std::string topic = "ucl/by-unid/"+ std::string(destination_unid) + "/ep" +
++ std::to_string(destination_endpoint) + "/";
++ topic += "UnifySwitchColor/Commands/StartStopChange";
++
++
++ std::string payload =
++ get_json_payload_for_unify_switch_color_start_stop_change_command(
++ fields);
++
++ sl_log_debug(LOG_TAG, "Sending command to %s with payload %s ---", topic.c_str() , payload.c_str());
++
++ // Publish our command, not retained
++ uic_mqtt_publish(topic.c_str(),
++ payload.c_str(),
++ payload.size(),
++ false);
++}
++
++/**
++ * @brief Sends/Publishes a StartStopChange command for
++ * the UnifySwitchColor cluster to a group.
++ *
++ * Publication will be made at the following topic
++ * ucl/by-group/GroupID/UnifySwitchColor/Commands/StartStopChange
++ *
++ * @param destination_group_id The GroupID that should receive the command.
++ *
++ * @param fields Struct pointer with the fields value of the command
++ *
++ */
++void uic_mqtt_dotdot_unify_switch_color_publish_start_stop_change_command_to_group(
++ uint16_t destination_group_id,
++ const uic_mqtt_dotdot_unify_switch_color_command_start_stop_change_fields_t *fields
++
++){
++ // Create the topic
++ std::string topic = "ucl/by-group/"+ std::to_string(destination_group_id) +
++ "/UnifySwitchColor/Commands/StartStopChange";
++
++ std::string payload =
++ get_json_payload_for_unify_switch_color_start_stop_change_command(
++ fields);
++
++ sl_log_info(LOG_TAG, "Sending group command to %s with payload %s ---", topic.c_str() , payload.c_str());
++
++ // Publish our command, not retained
++ uic_mqtt_publish(topic.c_str(),
++ payload.c_str(),
++ payload.size(),
++ false);
++}
+diff --git a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_supported_generated_commands.cpp b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_supported_generated_commands.cpp
+index a615166fa3..0229839e9f 100644
+--- a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_supported_generated_commands.cpp
++++ b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_supported_generated_commands.cpp
+@@ -2964,3 +2964,52 @@ void uic_mqtt_dotdot_unify_humidity_control_publish_supported_generated_commands
+
+ }
+
++
++/**
++ * @brief Sends/Publishes a the SupportedGenerated commands for
++ * the UnifySwitchColor cluster for a UNID/Endpoint
++ *
++ * Publication will be made at the following topic
++ * ucl/by-unid/UNID/epID/UnifySwitchColor/SupportedGeneratedCommands
++ *
++ * @param unid The UNID of the node on behalf of which the advertisment is made
++ *
++ * @param endpoint The Endpoint ID of the node on behalf of which the advertisment is made
++ *
++ * @param command_list Struct pointer with the fields value indicating if
++ * individual commands can be generated.
++ */
++void uic_mqtt_dotdot_unify_switch_color_publish_supported_generated_commands(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint,
++ const uic_mqtt_dotdot_unify_switch_color_supported_commands_t *command_list)
++{
++ std::string topic = "ucl/by-unid/" + std::string(unid);
++ topic += "/ep"+ std::to_string(endpoint);
++ topic += "/UnifySwitchColor/SupportedGeneratedCommands";
++
++ // Assemble of vector of strings for the Supported Commands:
++ std::vector command_vector;
++ if (command_list->set_color == true) {
++ command_vector.emplace_back("SetColor");
++ }
++ if (command_list->start_stop_change == true) {
++ command_vector.emplace_back("StartStopChange");
++ }
++ if (command_list->write_attributes == true) {
++ command_vector.emplace_back("WriteAttributes");
++ }
++
++ // JSONify, then Stringify
++ nlohmann::json json_payload;
++ json_payload["value"] = command_vector;
++ std::string string_payload = json_payload.dump();
++
++ // Publish to MQTT
++ uic_mqtt_publish(topic.c_str(),
++ string_payload.c_str(),
++ string_payload.length(),
++ true);
++
++}
++
+diff --git a/components/uic_dotdot_mqtt/zap-generated/test/dotdot_mqtt_test.include b/components/uic_dotdot_mqtt/zap-generated/test/dotdot_mqtt_test.include
+index 89a5002b0f..0ce338a51e 100644
+--- a/components/uic_dotdot_mqtt/zap-generated/test/dotdot_mqtt_test.include
++++ b/components/uic_dotdot_mqtt/zap-generated/test/dotdot_mqtt_test.include
+@@ -3339,6 +3339,46 @@ static sl_status_t uic_mqtt_dotdot_unify_humidity_control_setpoint_set_callback_
+ return SL_STATUS_OK;
+ }
+
++static unsigned int uic_mqtt_dotdot_unify_switch_color_set_color_callback_count;
++static sl_status_t uic_mqtt_dotdot_unify_switch_color_set_color_callback_func(
++ dotdot_unid_t unid,
++ dotdot_endpoint_id_t endpoint,
++ uic_mqtt_dotdot_callback_call_type_t callback_type,
++ uint8_t color_component_id,
++
++ uint8_t value,
++
++ uint32_t duration
++
++) {
++ uic_mqtt_dotdot_unify_switch_color_set_color_callback_count++;
++ num_command_callbacks++;
++ return SL_STATUS_OK;
++}
++
++static unsigned int uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback_count;
++static sl_status_t uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback_func(
++ dotdot_unid_t unid,
++ dotdot_endpoint_id_t endpoint,
++ uic_mqtt_dotdot_callback_call_type_t callback_type,
++ bool start_stop,
++
++ bool up_down,
++
++ bool ignor_start_level,
++
++ uint8_t color_component_id,
++
++ uint8_t start_level,
++
++ uint32_t duration
++
++) {
++ uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback_count++;
++ num_command_callbacks++;
++ return SL_STATUS_OK;
++}
++
+ static unsigned int set_all_callbacks()
+ {
+ unsigned int num_callbacks = 0;
+@@ -3765,6 +3805,10 @@ static unsigned int set_all_callbacks()
+ num_callbacks++;
+ uic_mqtt_dotdot_unify_humidity_control_setpoint_set_callback_set(&uic_mqtt_dotdot_unify_humidity_control_setpoint_set_callback_func);
+ num_callbacks++;
++ uic_mqtt_dotdot_unify_switch_color_set_color_callback_set(&uic_mqtt_dotdot_unify_switch_color_set_color_callback_func);
++ num_callbacks++;
++ uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback_set(&uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback_func);
++ num_callbacks++;
+ return num_callbacks;
+ }
+
+@@ -4036,6 +4080,9 @@ static void unset_all_callbacks()
+ uic_mqtt_dotdot_unify_humidity_control_mode_set_callback_clear();
+ uic_mqtt_dotdot_unify_humidity_control_setpoint_set_callback_clear();
+ uic_mqtt_dotdot_clear_unify_humidity_control_write_attributes_callbacks();
++ uic_mqtt_dotdot_unify_switch_color_set_color_callback_clear();
++ uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback_clear();
++ uic_mqtt_dotdot_clear_unify_switch_color_write_attributes_callbacks();
+ }
+
+ static void reset_callback_counters()
+@@ -4252,4 +4299,6 @@ static void reset_callback_counters()
+ uic_mqtt_dotdot_unify_fan_control_turn_off_callback_count = 0;
+ uic_mqtt_dotdot_unify_humidity_control_mode_set_callback_count = 0;
+ uic_mqtt_dotdot_unify_humidity_control_setpoint_set_callback_count = 0;
++ uic_mqtt_dotdot_unify_switch_color_set_color_callback_count = 0;
++ uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback_count = 0;
+ }
+diff --git a/components/unify_dotdot_attribute_store/zap-generated/include/dotdot_attributes.uam b/components/unify_dotdot_attribute_store/zap-generated/include/dotdot_attributes.uam
+index 68ed25df42..b3cb71a58e 100644
+--- a/components/unify_dotdot_attribute_store/zap-generated/include/dotdot_attributes.uam
++++ b/components/unify_dotdot_attribute_store/zap-generated/include/dotdot_attributes.uam
+@@ -904,3 +904,13 @@ def DOTDOT_ATTRIBUTE_ID_UNIFY_HUMIDITY_CONTROL_AUTO_SETPOINT 0xfda00011
+ def DOTDOT_ATTRIBUTE_ID_UNIFY_HUMIDITY_CONTROL_AUTO_SETPOINT_SCALE 0xfda00012
+ def DOTDOT_ATTRIBUTE_ID_UNIFY_HUMIDITY_CONTROL_AUTO_SETPOINT_PRECISION 0xfda00013
+
++// This represents the attributes in the DotDot UnifySwitchColor cluster
++def DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_WARM_WHITE 0xffa10000
++def DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_COLD_WHITE 0xffa10001
++def DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_RED 0xffa10002
++def DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_GREEN 0xffa10003
++def DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_BLUE 0xffa10004
++def DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_AMBER 0xffa10005
++def DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_CYAN 0xffa10006
++def DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_PURPLE 0xffa10007
++
+diff --git a/components/unify_dotdot_attribute_store/zap-generated/include/dotdot_attributes_camel_case.uam b/components/unify_dotdot_attribute_store/zap-generated/include/dotdot_attributes_camel_case.uam
+index 440dddc2ea..ede33f9966 100644
+--- a/components/unify_dotdot_attribute_store/zap-generated/include/dotdot_attributes_camel_case.uam
++++ b/components/unify_dotdot_attribute_store/zap-generated/include/dotdot_attributes_camel_case.uam
+@@ -904,3 +904,13 @@ def zb_AutoSetpoint 0xfda00011
+ def zb_AutoSetpointScale 0xfda00012
+ def zb_AutoSetpointPrecision 0xfda00013
+
++// This represents short CamelCase labels the attributes in the DotDot UnifySwitchColor cluster
++def zb_WarmWhite 0xffa10000
++def zb_ColdWhite 0xffa10001
++def zb_Red 0xffa10002
++def zb_Green 0xffa10003
++def zb_Blue 0xffa10004
++def zb_Amber 0xffa10005
++def zb_Cyan 0xffa10006
++def zb_Purple 0xffa10007
++
+diff --git a/components/unify_dotdot_attribute_store/zap-generated/include/unify_dotdot_attribute_store_helpers.h b/components/unify_dotdot_attribute_store/zap-generated/include/unify_dotdot_attribute_store_helpers.h
+index 8027848315..9ebb9bc489 100644
+--- a/components/unify_dotdot_attribute_store/zap-generated/include/unify_dotdot_attribute_store_helpers.h
++++ b/components/unify_dotdot_attribute_store/zap-generated/include/unify_dotdot_attribute_store_helpers.h
+@@ -79177,6 +79177,882 @@ bool dotdot_is_any_unify_humidity_control_writable_attribute_supported(
+ const dotdot_unid_t unid,
+ const dotdot_endpoint_id_t endpoint_id);
+
++////////////////////////////////////////////////////////////////////////////////
++// Start of cluster UnifySwitchColor
++////////////////////////////////////////////////////////////////////////////////
++// UnifySwitchColor WarmWhite
++/**
++ * @brief Verifies if the DotDot UnifySwitchColor - WarmWhite is supported
++ * under a UNID/EndpoinID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ *
++ * @returns true if WarmWhite is supported
++ * @returns false if WarmWhite is not supported
++ */
++bool dotdot_is_supported_unify_switch_color_warm_white (
++ const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint_id);
++
++/**
++ * @brief Gets the DotDot UnifySwitchColor - WarmWhite attribute value under a UNID/EndpoinID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @param value_state value state to get,
++ * see \ref attribute_store_get_node_attribute_value
++ *
++ *
++ * @returns WarmWhite attribute
++ */
++uint8_t dotdot_get_unify_switch_color_warm_white(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id,
++ attribute_store_node_value_state_t value_state);
++
++/**
++ * @brief Set the DotDot UnifySwitchColor - WarmWhite attribute under a UNID/EndpoinID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @param value_state value state to write for the node,
++ * see \ref attribute_store_set_node_attribute_value
++ *
++ * @param new_warm_white new value to set
++ * @returns sl_status_t SL_STATUS_OK on success
++ */
++sl_status_t dotdot_set_unify_switch_color_warm_white(
++ const dotdot_unid_t unid,
++ dotdot_endpoint_id_t endpoint_id,
++ attribute_store_node_value_state_t value_state,
++ uint8_t new_warm_white
++ );
++
++/**
++ * @brief Undefines the Reported value of the the DotDot UnifySwitchColor - WarmWhite
++ * attribute under a UNID/EndpoinID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @returns sl_status_t SL_STATUS_OK on success
++ */
++sl_status_t dotdot_unify_switch_color_warm_white_undefine_reported(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id);
++
++/**
++ * @brief Undefines the Desired value of the DotDot
++ * UnifySwitchColor - WarmWhite attribute under a UNID/EndpointID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @returns sl_status_t SL_STATUS_OK on success
++ */
++sl_status_t dotdot_unify_switch_color_warm_white_undefine_desired(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id);
++
++/**
++ * @brief Checks if the reported value is defined for the DotDot
++ * UnifySwitchColor - WarmWhite attribute under a UNID/EndpointID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @returns true if defined, false is undefined or non-existent
++ */
++bool dotdot_unify_switch_color_warm_white_is_reported_defined(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id);
++
++/**
++ * @brief Checks if the desired value is defined for the DotDot
++ * UnifySwitchColor - WarmWhite attribute under a UNID/EndpointID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @returns true if defined, false is undefined or non-existent
++ */
++bool dotdot_unify_switch_color_warm_white_is_desired_defined(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id);
++
++/**
++ * @brief Creates a DotDot UnifySwitchColor - WarmWhite attribute under a UNID/EndpoinID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @returns sl_status_t SL_STATUS_OK on success
++ */
++sl_status_t dotdot_create_unify_switch_color_warm_white(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id);
++// UnifySwitchColor ColdWhite
++/**
++ * @brief Verifies if the DotDot UnifySwitchColor - ColdWhite is supported
++ * under a UNID/EndpoinID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ *
++ * @returns true if ColdWhite is supported
++ * @returns false if ColdWhite is not supported
++ */
++bool dotdot_is_supported_unify_switch_color_cold_white (
++ const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint_id);
++
++/**
++ * @brief Gets the DotDot UnifySwitchColor - ColdWhite attribute value under a UNID/EndpoinID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @param value_state value state to get,
++ * see \ref attribute_store_get_node_attribute_value
++ *
++ *
++ * @returns ColdWhite attribute
++ */
++uint8_t dotdot_get_unify_switch_color_cold_white(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id,
++ attribute_store_node_value_state_t value_state);
++
++/**
++ * @brief Set the DotDot UnifySwitchColor - ColdWhite attribute under a UNID/EndpoinID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @param value_state value state to write for the node,
++ * see \ref attribute_store_set_node_attribute_value
++ *
++ * @param new_cold_white new value to set
++ * @returns sl_status_t SL_STATUS_OK on success
++ */
++sl_status_t dotdot_set_unify_switch_color_cold_white(
++ const dotdot_unid_t unid,
++ dotdot_endpoint_id_t endpoint_id,
++ attribute_store_node_value_state_t value_state,
++ uint8_t new_cold_white
++ );
++
++/**
++ * @brief Undefines the Reported value of the the DotDot UnifySwitchColor - ColdWhite
++ * attribute under a UNID/EndpoinID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @returns sl_status_t SL_STATUS_OK on success
++ */
++sl_status_t dotdot_unify_switch_color_cold_white_undefine_reported(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id);
++
++/**
++ * @brief Undefines the Desired value of the DotDot
++ * UnifySwitchColor - ColdWhite attribute under a UNID/EndpointID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @returns sl_status_t SL_STATUS_OK on success
++ */
++sl_status_t dotdot_unify_switch_color_cold_white_undefine_desired(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id);
++
++/**
++ * @brief Checks if the reported value is defined for the DotDot
++ * UnifySwitchColor - ColdWhite attribute under a UNID/EndpointID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @returns true if defined, false is undefined or non-existent
++ */
++bool dotdot_unify_switch_color_cold_white_is_reported_defined(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id);
++
++/**
++ * @brief Checks if the desired value is defined for the DotDot
++ * UnifySwitchColor - ColdWhite attribute under a UNID/EndpointID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @returns true if defined, false is undefined or non-existent
++ */
++bool dotdot_unify_switch_color_cold_white_is_desired_defined(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id);
++
++/**
++ * @brief Creates a DotDot UnifySwitchColor - ColdWhite attribute under a UNID/EndpoinID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @returns sl_status_t SL_STATUS_OK on success
++ */
++sl_status_t dotdot_create_unify_switch_color_cold_white(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id);
++// UnifySwitchColor Red
++/**
++ * @brief Verifies if the DotDot UnifySwitchColor - Red is supported
++ * under a UNID/EndpoinID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ *
++ * @returns true if Red is supported
++ * @returns false if Red is not supported
++ */
++bool dotdot_is_supported_unify_switch_color_red (
++ const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint_id);
++
++/**
++ * @brief Gets the DotDot UnifySwitchColor - Red attribute value under a UNID/EndpoinID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @param value_state value state to get,
++ * see \ref attribute_store_get_node_attribute_value
++ *
++ *
++ * @returns Red attribute
++ */
++uint8_t dotdot_get_unify_switch_color_red(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id,
++ attribute_store_node_value_state_t value_state);
++
++/**
++ * @brief Set the DotDot UnifySwitchColor - Red attribute under a UNID/EndpoinID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @param value_state value state to write for the node,
++ * see \ref attribute_store_set_node_attribute_value
++ *
++ * @param new_red new value to set
++ * @returns sl_status_t SL_STATUS_OK on success
++ */
++sl_status_t dotdot_set_unify_switch_color_red(
++ const dotdot_unid_t unid,
++ dotdot_endpoint_id_t endpoint_id,
++ attribute_store_node_value_state_t value_state,
++ uint8_t new_red
++ );
++
++/**
++ * @brief Undefines the Reported value of the the DotDot UnifySwitchColor - Red
++ * attribute under a UNID/EndpoinID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @returns sl_status_t SL_STATUS_OK on success
++ */
++sl_status_t dotdot_unify_switch_color_red_undefine_reported(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id);
++
++/**
++ * @brief Undefines the Desired value of the DotDot
++ * UnifySwitchColor - Red attribute under a UNID/EndpointID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @returns sl_status_t SL_STATUS_OK on success
++ */
++sl_status_t dotdot_unify_switch_color_red_undefine_desired(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id);
++
++/**
++ * @brief Checks if the reported value is defined for the DotDot
++ * UnifySwitchColor - Red attribute under a UNID/EndpointID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @returns true if defined, false is undefined or non-existent
++ */
++bool dotdot_unify_switch_color_red_is_reported_defined(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id);
++
++/**
++ * @brief Checks if the desired value is defined for the DotDot
++ * UnifySwitchColor - Red attribute under a UNID/EndpointID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @returns true if defined, false is undefined or non-existent
++ */
++bool dotdot_unify_switch_color_red_is_desired_defined(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id);
++
++/**
++ * @brief Creates a DotDot UnifySwitchColor - Red attribute under a UNID/EndpoinID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @returns sl_status_t SL_STATUS_OK on success
++ */
++sl_status_t dotdot_create_unify_switch_color_red(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id);
++// UnifySwitchColor Green
++/**
++ * @brief Verifies if the DotDot UnifySwitchColor - Green is supported
++ * under a UNID/EndpoinID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ *
++ * @returns true if Green is supported
++ * @returns false if Green is not supported
++ */
++bool dotdot_is_supported_unify_switch_color_green (
++ const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint_id);
++
++/**
++ * @brief Gets the DotDot UnifySwitchColor - Green attribute value under a UNID/EndpoinID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @param value_state value state to get,
++ * see \ref attribute_store_get_node_attribute_value
++ *
++ *
++ * @returns Green attribute
++ */
++uint8_t dotdot_get_unify_switch_color_green(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id,
++ attribute_store_node_value_state_t value_state);
++
++/**
++ * @brief Set the DotDot UnifySwitchColor - Green attribute under a UNID/EndpoinID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @param value_state value state to write for the node,
++ * see \ref attribute_store_set_node_attribute_value
++ *
++ * @param new_green new value to set
++ * @returns sl_status_t SL_STATUS_OK on success
++ */
++sl_status_t dotdot_set_unify_switch_color_green(
++ const dotdot_unid_t unid,
++ dotdot_endpoint_id_t endpoint_id,
++ attribute_store_node_value_state_t value_state,
++ uint8_t new_green
++ );
++
++/**
++ * @brief Undefines the Reported value of the the DotDot UnifySwitchColor - Green
++ * attribute under a UNID/EndpoinID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @returns sl_status_t SL_STATUS_OK on success
++ */
++sl_status_t dotdot_unify_switch_color_green_undefine_reported(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id);
++
++/**
++ * @brief Undefines the Desired value of the DotDot
++ * UnifySwitchColor - Green attribute under a UNID/EndpointID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @returns sl_status_t SL_STATUS_OK on success
++ */
++sl_status_t dotdot_unify_switch_color_green_undefine_desired(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id);
++
++/**
++ * @brief Checks if the reported value is defined for the DotDot
++ * UnifySwitchColor - Green attribute under a UNID/EndpointID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @returns true if defined, false is undefined or non-existent
++ */
++bool dotdot_unify_switch_color_green_is_reported_defined(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id);
++
++/**
++ * @brief Checks if the desired value is defined for the DotDot
++ * UnifySwitchColor - Green attribute under a UNID/EndpointID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @returns true if defined, false is undefined or non-existent
++ */
++bool dotdot_unify_switch_color_green_is_desired_defined(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id);
++
++/**
++ * @brief Creates a DotDot UnifySwitchColor - Green attribute under a UNID/EndpoinID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @returns sl_status_t SL_STATUS_OK on success
++ */
++sl_status_t dotdot_create_unify_switch_color_green(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id);
++// UnifySwitchColor Blue
++/**
++ * @brief Verifies if the DotDot UnifySwitchColor - Blue is supported
++ * under a UNID/EndpoinID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ *
++ * @returns true if Blue is supported
++ * @returns false if Blue is not supported
++ */
++bool dotdot_is_supported_unify_switch_color_blue (
++ const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint_id);
++
++/**
++ * @brief Gets the DotDot UnifySwitchColor - Blue attribute value under a UNID/EndpoinID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @param value_state value state to get,
++ * see \ref attribute_store_get_node_attribute_value
++ *
++ *
++ * @returns Blue attribute
++ */
++uint8_t dotdot_get_unify_switch_color_blue(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id,
++ attribute_store_node_value_state_t value_state);
++
++/**
++ * @brief Set the DotDot UnifySwitchColor - Blue attribute under a UNID/EndpoinID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @param value_state value state to write for the node,
++ * see \ref attribute_store_set_node_attribute_value
++ *
++ * @param new_blue new value to set
++ * @returns sl_status_t SL_STATUS_OK on success
++ */
++sl_status_t dotdot_set_unify_switch_color_blue(
++ const dotdot_unid_t unid,
++ dotdot_endpoint_id_t endpoint_id,
++ attribute_store_node_value_state_t value_state,
++ uint8_t new_blue
++ );
++
++/**
++ * @brief Undefines the Reported value of the the DotDot UnifySwitchColor - Blue
++ * attribute under a UNID/EndpoinID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @returns sl_status_t SL_STATUS_OK on success
++ */
++sl_status_t dotdot_unify_switch_color_blue_undefine_reported(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id);
++
++/**
++ * @brief Undefines the Desired value of the DotDot
++ * UnifySwitchColor - Blue attribute under a UNID/EndpointID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @returns sl_status_t SL_STATUS_OK on success
++ */
++sl_status_t dotdot_unify_switch_color_blue_undefine_desired(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id);
++
++/**
++ * @brief Checks if the reported value is defined for the DotDot
++ * UnifySwitchColor - Blue attribute under a UNID/EndpointID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @returns true if defined, false is undefined or non-existent
++ */
++bool dotdot_unify_switch_color_blue_is_reported_defined(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id);
++
++/**
++ * @brief Checks if the desired value is defined for the DotDot
++ * UnifySwitchColor - Blue attribute under a UNID/EndpointID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @returns true if defined, false is undefined or non-existent
++ */
++bool dotdot_unify_switch_color_blue_is_desired_defined(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id);
++
++/**
++ * @brief Creates a DotDot UnifySwitchColor - Blue attribute under a UNID/EndpoinID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @returns sl_status_t SL_STATUS_OK on success
++ */
++sl_status_t dotdot_create_unify_switch_color_blue(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id);
++// UnifySwitchColor Amber
++/**
++ * @brief Verifies if the DotDot UnifySwitchColor - Amber is supported
++ * under a UNID/EndpoinID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ *
++ * @returns true if Amber is supported
++ * @returns false if Amber is not supported
++ */
++bool dotdot_is_supported_unify_switch_color_amber (
++ const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint_id);
++
++/**
++ * @brief Gets the DotDot UnifySwitchColor - Amber attribute value under a UNID/EndpoinID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @param value_state value state to get,
++ * see \ref attribute_store_get_node_attribute_value
++ *
++ *
++ * @returns Amber attribute
++ */
++uint8_t dotdot_get_unify_switch_color_amber(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id,
++ attribute_store_node_value_state_t value_state);
++
++/**
++ * @brief Set the DotDot UnifySwitchColor - Amber attribute under a UNID/EndpoinID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @param value_state value state to write for the node,
++ * see \ref attribute_store_set_node_attribute_value
++ *
++ * @param new_amber new value to set
++ * @returns sl_status_t SL_STATUS_OK on success
++ */
++sl_status_t dotdot_set_unify_switch_color_amber(
++ const dotdot_unid_t unid,
++ dotdot_endpoint_id_t endpoint_id,
++ attribute_store_node_value_state_t value_state,
++ uint8_t new_amber
++ );
++
++/**
++ * @brief Undefines the Reported value of the the DotDot UnifySwitchColor - Amber
++ * attribute under a UNID/EndpoinID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @returns sl_status_t SL_STATUS_OK on success
++ */
++sl_status_t dotdot_unify_switch_color_amber_undefine_reported(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id);
++
++/**
++ * @brief Undefines the Desired value of the DotDot
++ * UnifySwitchColor - Amber attribute under a UNID/EndpointID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @returns sl_status_t SL_STATUS_OK on success
++ */
++sl_status_t dotdot_unify_switch_color_amber_undefine_desired(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id);
++
++/**
++ * @brief Checks if the reported value is defined for the DotDot
++ * UnifySwitchColor - Amber attribute under a UNID/EndpointID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @returns true if defined, false is undefined or non-existent
++ */
++bool dotdot_unify_switch_color_amber_is_reported_defined(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id);
++
++/**
++ * @brief Checks if the desired value is defined for the DotDot
++ * UnifySwitchColor - Amber attribute under a UNID/EndpointID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @returns true if defined, false is undefined or non-existent
++ */
++bool dotdot_unify_switch_color_amber_is_desired_defined(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id);
++
++/**
++ * @brief Creates a DotDot UnifySwitchColor - Amber attribute under a UNID/EndpoinID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @returns sl_status_t SL_STATUS_OK on success
++ */
++sl_status_t dotdot_create_unify_switch_color_amber(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id);
++// UnifySwitchColor Cyan
++/**
++ * @brief Verifies if the DotDot UnifySwitchColor - Cyan is supported
++ * under a UNID/EndpoinID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ *
++ * @returns true if Cyan is supported
++ * @returns false if Cyan is not supported
++ */
++bool dotdot_is_supported_unify_switch_color_cyan (
++ const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint_id);
++
++/**
++ * @brief Gets the DotDot UnifySwitchColor - Cyan attribute value under a UNID/EndpoinID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @param value_state value state to get,
++ * see \ref attribute_store_get_node_attribute_value
++ *
++ *
++ * @returns Cyan attribute
++ */
++uint8_t dotdot_get_unify_switch_color_cyan(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id,
++ attribute_store_node_value_state_t value_state);
++
++/**
++ * @brief Set the DotDot UnifySwitchColor - Cyan attribute under a UNID/EndpoinID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @param value_state value state to write for the node,
++ * see \ref attribute_store_set_node_attribute_value
++ *
++ * @param new_cyan new value to set
++ * @returns sl_status_t SL_STATUS_OK on success
++ */
++sl_status_t dotdot_set_unify_switch_color_cyan(
++ const dotdot_unid_t unid,
++ dotdot_endpoint_id_t endpoint_id,
++ attribute_store_node_value_state_t value_state,
++ uint8_t new_cyan
++ );
++
++/**
++ * @brief Undefines the Reported value of the the DotDot UnifySwitchColor - Cyan
++ * attribute under a UNID/EndpoinID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @returns sl_status_t SL_STATUS_OK on success
++ */
++sl_status_t dotdot_unify_switch_color_cyan_undefine_reported(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id);
++
++/**
++ * @brief Undefines the Desired value of the DotDot
++ * UnifySwitchColor - Cyan attribute under a UNID/EndpointID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @returns sl_status_t SL_STATUS_OK on success
++ */
++sl_status_t dotdot_unify_switch_color_cyan_undefine_desired(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id);
++
++/**
++ * @brief Checks if the reported value is defined for the DotDot
++ * UnifySwitchColor - Cyan attribute under a UNID/EndpointID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @returns true if defined, false is undefined or non-existent
++ */
++bool dotdot_unify_switch_color_cyan_is_reported_defined(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id);
++
++/**
++ * @brief Checks if the desired value is defined for the DotDot
++ * UnifySwitchColor - Cyan attribute under a UNID/EndpointID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @returns true if defined, false is undefined or non-existent
++ */
++bool dotdot_unify_switch_color_cyan_is_desired_defined(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id);
++
++/**
++ * @brief Creates a DotDot UnifySwitchColor - Cyan attribute under a UNID/EndpoinID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @returns sl_status_t SL_STATUS_OK on success
++ */
++sl_status_t dotdot_create_unify_switch_color_cyan(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id);
++// UnifySwitchColor Purple
++/**
++ * @brief Verifies if the DotDot UnifySwitchColor - Purple is supported
++ * under a UNID/EndpoinID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ *
++ * @returns true if Purple is supported
++ * @returns false if Purple is not supported
++ */
++bool dotdot_is_supported_unify_switch_color_purple (
++ const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint_id);
++
++/**
++ * @brief Gets the DotDot UnifySwitchColor - Purple attribute value under a UNID/EndpoinID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @param value_state value state to get,
++ * see \ref attribute_store_get_node_attribute_value
++ *
++ *
++ * @returns Purple attribute
++ */
++uint8_t dotdot_get_unify_switch_color_purple(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id,
++ attribute_store_node_value_state_t value_state);
++
++/**
++ * @brief Set the DotDot UnifySwitchColor - Purple attribute under a UNID/EndpoinID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @param value_state value state to write for the node,
++ * see \ref attribute_store_set_node_attribute_value
++ *
++ * @param new_purple new value to set
++ * @returns sl_status_t SL_STATUS_OK on success
++ */
++sl_status_t dotdot_set_unify_switch_color_purple(
++ const dotdot_unid_t unid,
++ dotdot_endpoint_id_t endpoint_id,
++ attribute_store_node_value_state_t value_state,
++ uint8_t new_purple
++ );
++
++/**
++ * @brief Undefines the Reported value of the the DotDot UnifySwitchColor - Purple
++ * attribute under a UNID/EndpoinID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @returns sl_status_t SL_STATUS_OK on success
++ */
++sl_status_t dotdot_unify_switch_color_purple_undefine_reported(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id);
++
++/**
++ * @brief Undefines the Desired value of the DotDot
++ * UnifySwitchColor - Purple attribute under a UNID/EndpointID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @returns sl_status_t SL_STATUS_OK on success
++ */
++sl_status_t dotdot_unify_switch_color_purple_undefine_desired(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id);
++
++/**
++ * @brief Checks if the reported value is defined for the DotDot
++ * UnifySwitchColor - Purple attribute under a UNID/EndpointID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @returns true if defined, false is undefined or non-existent
++ */
++bool dotdot_unify_switch_color_purple_is_reported_defined(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id);
++
++/**
++ * @brief Checks if the desired value is defined for the DotDot
++ * UnifySwitchColor - Purple attribute under a UNID/EndpointID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @returns true if defined, false is undefined or non-existent
++ */
++bool dotdot_unify_switch_color_purple_is_desired_defined(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id);
++
++/**
++ * @brief Creates a DotDot UnifySwitchColor - Purple attribute under a UNID/EndpoinID
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @returns sl_status_t SL_STATUS_OK on success
++ */
++sl_status_t dotdot_create_unify_switch_color_purple(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id);
++
++/**
++ * @brief Checks if a UNID/Endpoint supports any attribute for the UnifySwitchColor
++ * Cluster
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @returns true if at least 1 attribute in the Attribute Store, false otherwise
++ */
++bool dotdot_is_any_unify_switch_color_attribute_supported(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id);
++
++/**
++ * @brief Checks if a UNID/Endpoint supports any writable attribute for the
++ * UnifySwitchColor Cluster
++ *
++ * @param unid Node's UNID
++ * @param endpoint_id Endpoint ID
++ * @returns true if at least 1 writable attribute in the Attribute Store, false otherwise
++ */
++bool dotdot_is_any_unify_switch_color_writable_attribute_supported(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id);
++
+ #ifdef __cplusplus
+ }
+ #endif // __cplusplus
+diff --git a/components/unify_dotdot_attribute_store/zap-generated/include/unify_dotdot_defined_attribute_types.h b/components/unify_dotdot_attribute_store/zap-generated/include/unify_dotdot_defined_attribute_types.h
+index 6f3c5b0f35..6ca13e5787 100644
+--- a/components/unify_dotdot_attribute_store/zap-generated/include/unify_dotdot_defined_attribute_types.h
++++ b/components/unify_dotdot_attribute_store/zap-generated/include/unify_dotdot_defined_attribute_types.h
+@@ -810,6 +810,15 @@ DEFINE_ATTRIBUTE(DOTDOT_ATTRIBUTE_ID_UNIFY_HUMIDITY_CONTROL_AUTO_SETPOINT_MAX ,
+ DEFINE_ATTRIBUTE(DOTDOT_ATTRIBUTE_ID_UNIFY_HUMIDITY_CONTROL_AUTO_SETPOINT , 0xfda00011)
+ DEFINE_ATTRIBUTE(DOTDOT_ATTRIBUTE_ID_UNIFY_HUMIDITY_CONTROL_AUTO_SETPOINT_SCALE , 0xfda00012)
+ DEFINE_ATTRIBUTE(DOTDOT_ATTRIBUTE_ID_UNIFY_HUMIDITY_CONTROL_AUTO_SETPOINT_PRECISION , 0xfda00013)
++// Attribute Defines for UnifySwitchColor
++DEFINE_ATTRIBUTE(DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_WARM_WHITE , 0xffa10000)
++DEFINE_ATTRIBUTE(DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_COLD_WHITE , 0xffa10001)
++DEFINE_ATTRIBUTE(DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_RED , 0xffa10002)
++DEFINE_ATTRIBUTE(DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_GREEN , 0xffa10003)
++DEFINE_ATTRIBUTE(DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_BLUE , 0xffa10004)
++DEFINE_ATTRIBUTE(DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_AMBER , 0xffa10005)
++DEFINE_ATTRIBUTE(DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_CYAN , 0xffa10006)
++DEFINE_ATTRIBUTE(DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_PURPLE , 0xffa10007)
+
+ // Additional manually defined types:
+
+diff --git a/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_attribute_publisher.cpp b/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_attribute_publisher.cpp
+index 75631aebad..559bcfb380 100644
+--- a/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_attribute_publisher.cpp
++++ b/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_attribute_publisher.cpp
+@@ -26377,6 +26377,375 @@ static void unify_humidity_control_cluster_cluster_revision_callback(
+ }
+
+
++/**
++ * @brief Publishes the desired value of an updated attribute store node for
++ * the UnifySwitchColor cluster.
++ * @param updated_node Updated attribute store node
++ * @param change Type of change applied
++ */
++static void unify_switch_color_cluster_publish_desired_value_callback(
++ attribute_store_node_t updated_node, attribute_store_change_t change)
++{
++ // clang-format on
++ if (false == is_publish_desired_attribute_values_to_mqtt_enabled()) {
++ return;
++ }
++ if (change == ATTRIBUTE_DELETED || change == ATTRIBUTE_CREATED) {
++ return;
++ }
++ // Scene exception: check that the attribute is not under the Scene Table extension, which is a config and not the node's state.
++ if (ATTRIBUTE_STORE_INVALID_NODE
++ != attribute_store_get_first_parent_with_type(
++ updated_node,
++ DOTDOT_ATTRIBUTE_ID_SCENES_SCENE_TABLE)) {
++ return;
++ }
++
++ // Get the UNID and EndPoint, and prepare the basic topic
++ char unid[MAXIMUM_UNID_SIZE] = {};
++ // clang-format off
++ // clang-format on
++ dotdot_endpoint_id_t endpoint_id = 0;
++ if (SL_STATUS_OK
++ != unify_dotdot_attributes_get_unid_endpoint()(updated_node,
++ unid,
++ &endpoint_id)) {
++ return;
++ }
++ // clang-format off
++ // clang-format on
++
++ std::string base_topic = "ucl/by-unid/" + std::string(unid);
++ // clang-format off
++ base_topic += "/ep" + std::to_string(endpoint_id);
++ // clang-format on
++
++ attribute_store_type_t type = attribute_store_get_node_type(updated_node);
++ if (type == ATTRIBUTE_STORE_INVALID_ATTRIBUTE_TYPE) {
++ sl_log_debug(LOG_TAG,
++ "Warning: Invalid type for Attribute ID %d, "
++ "this should not happen.",
++ updated_node);
++ return;
++ }
++
++ // If the value got updated but both Reported and Desired undefined, we skip publication
++ if (false == attribute_store_is_reported_defined(updated_node)
++ && false == attribute_store_is_desired_defined(updated_node)) {
++ sl_log_debug(LOG_TAG,
++ "Reported/Desired values are undefined. "
++ "Skipping publication");
++ return;
++ }
++
++ // clang-format off
++ try {
++ attribute_store::attribute attr(updated_node);
++ if (type == DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_WARM_WHITE) {
++ uic_mqtt_dotdot_unify_switch_color_warm_white_publish(
++ base_topic.c_str(),
++ static_cast(attr.desired_or_reported()),
++ UCL_MQTT_PUBLISH_TYPE_DESIRED);
++ return;
++ }
++ if (type == DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_COLD_WHITE) {
++ uic_mqtt_dotdot_unify_switch_color_cold_white_publish(
++ base_topic.c_str(),
++ static_cast(attr.desired_or_reported()),
++ UCL_MQTT_PUBLISH_TYPE_DESIRED);
++ return;
++ }
++ if (type == DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_RED) {
++ uic_mqtt_dotdot_unify_switch_color_red_publish(
++ base_topic.c_str(),
++ static_cast(attr.desired_or_reported()),
++ UCL_MQTT_PUBLISH_TYPE_DESIRED);
++ return;
++ }
++ if (type == DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_GREEN) {
++ uic_mqtt_dotdot_unify_switch_color_green_publish(
++ base_topic.c_str(),
++ static_cast(attr.desired_or_reported()),
++ UCL_MQTT_PUBLISH_TYPE_DESIRED);
++ return;
++ }
++ if (type == DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_BLUE) {
++ uic_mqtt_dotdot_unify_switch_color_blue_publish(
++ base_topic.c_str(),
++ static_cast(attr.desired_or_reported()),
++ UCL_MQTT_PUBLISH_TYPE_DESIRED);
++ return;
++ }
++ if (type == DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_AMBER) {
++ uic_mqtt_dotdot_unify_switch_color_amber_publish(
++ base_topic.c_str(),
++ static_cast(attr.desired_or_reported()),
++ UCL_MQTT_PUBLISH_TYPE_DESIRED);
++ return;
++ }
++ if (type == DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_CYAN) {
++ uic_mqtt_dotdot_unify_switch_color_cyan_publish(
++ base_topic.c_str(),
++ static_cast(attr.desired_or_reported()),
++ UCL_MQTT_PUBLISH_TYPE_DESIRED);
++ return;
++ }
++ if (type == DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_PURPLE) {
++ uic_mqtt_dotdot_unify_switch_color_purple_publish(
++ base_topic.c_str(),
++ static_cast(attr.desired_or_reported()),
++ UCL_MQTT_PUBLISH_TYPE_DESIRED);
++ return;
++ }
++ } catch (std::exception &ex) {
++ sl_log_warning(LOG_TAG, "Failed to publish the Desired attribute value: %s", ex.what());
++ }
++}
++
++/**
++ * @brief Publishes the reported value of an updated attribute store node for
++ * the UnifySwitchColor cluster.
++ * @param updated_node Updated attribute store node
++ * @param change Type of change applied
++ */
++static void unify_switch_color_cluster_publish_reported_value_callback(
++ attribute_store_node_t updated_node, attribute_store_change_t change)
++{
++ // clang-format on
++ if (false == is_publish_reported_attribute_values_to_mqtt_enabled()) {
++ return;
++ }
++ if (change == ATTRIBUTE_CREATED) {
++ return;
++ }
++ // Scene exception: check that the attribute is not under the Scene Table extension, which is a config and not the node's state.
++ if (ATTRIBUTE_STORE_INVALID_NODE
++ != attribute_store_get_first_parent_with_type(
++ updated_node,
++ DOTDOT_ATTRIBUTE_ID_SCENES_SCENE_TABLE)) {
++ return;
++ }
++
++ // Get the UNID and EndPoint, and prepare the basic topic
++ char unid[MAXIMUM_UNID_SIZE] = {};
++ // clang-format off
++ // clang-format on
++ dotdot_endpoint_id_t endpoint_id = 0;
++ if (SL_STATUS_OK
++ != unify_dotdot_attributes_get_unid_endpoint()(updated_node,
++ unid,
++ &endpoint_id)) {
++ return;
++ }
++ // clang-format off
++ // clang-format on
++
++ std::string base_topic = "ucl/by-unid/" + std::string(unid);
++ // clang-format off
++ base_topic += "/ep" + std::to_string(endpoint_id);
++ // clang-format on
++
++ attribute_store_type_t type = attribute_store_get_node_type(updated_node);
++ if (type == ATTRIBUTE_STORE_INVALID_ATTRIBUTE_TYPE) {
++ sl_log_debug(LOG_TAG,
++ "Warning: Invalid type for Attribute ID %d, "
++ "this should not happen.",
++ updated_node);
++ return;
++ }
++
++ // Deletion case:
++ if (change == ATTRIBUTE_DELETED) {
++ // clang-format off
++ switch(type) {
++ case DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_WARM_WHITE:
++ // clang-format on
++ sl_log_debug(LOG_TAG,
++ "Unretaining UnifySwitchColor::WarmWhite under topic %s",
++ base_topic.c_str());
++ // clang-format off
++ uic_mqtt_dotdot_unify_switch_color_warm_white_unretain(base_topic.c_str(), UCL_MQTT_PUBLISH_TYPE_ALL);
++ break;
++ case DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_COLD_WHITE:
++ // clang-format on
++ sl_log_debug(LOG_TAG,
++ "Unretaining UnifySwitchColor::ColdWhite under topic %s",
++ base_topic.c_str());
++ // clang-format off
++ uic_mqtt_dotdot_unify_switch_color_cold_white_unretain(base_topic.c_str(), UCL_MQTT_PUBLISH_TYPE_ALL);
++ break;
++ case DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_RED:
++ // clang-format on
++ sl_log_debug(LOG_TAG,
++ "Unretaining UnifySwitchColor::Red under topic %s",
++ base_topic.c_str());
++ // clang-format off
++ uic_mqtt_dotdot_unify_switch_color_red_unretain(base_topic.c_str(), UCL_MQTT_PUBLISH_TYPE_ALL);
++ break;
++ case DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_GREEN:
++ // clang-format on
++ sl_log_debug(LOG_TAG,
++ "Unretaining UnifySwitchColor::Green under topic %s",
++ base_topic.c_str());
++ // clang-format off
++ uic_mqtt_dotdot_unify_switch_color_green_unretain(base_topic.c_str(), UCL_MQTT_PUBLISH_TYPE_ALL);
++ break;
++ case DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_BLUE:
++ // clang-format on
++ sl_log_debug(LOG_TAG,
++ "Unretaining UnifySwitchColor::Blue under topic %s",
++ base_topic.c_str());
++ // clang-format off
++ uic_mqtt_dotdot_unify_switch_color_blue_unretain(base_topic.c_str(), UCL_MQTT_PUBLISH_TYPE_ALL);
++ break;
++ case DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_AMBER:
++ // clang-format on
++ sl_log_debug(LOG_TAG,
++ "Unretaining UnifySwitchColor::Amber under topic %s",
++ base_topic.c_str());
++ // clang-format off
++ uic_mqtt_dotdot_unify_switch_color_amber_unretain(base_topic.c_str(), UCL_MQTT_PUBLISH_TYPE_ALL);
++ break;
++ case DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_CYAN:
++ // clang-format on
++ sl_log_debug(LOG_TAG,
++ "Unretaining UnifySwitchColor::Cyan under topic %s",
++ base_topic.c_str());
++ // clang-format off
++ uic_mqtt_dotdot_unify_switch_color_cyan_unretain(base_topic.c_str(), UCL_MQTT_PUBLISH_TYPE_ALL);
++ break;
++ case DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_PURPLE:
++ // clang-format on
++ sl_log_debug(LOG_TAG,
++ "Unretaining UnifySwitchColor::Purple under topic %s",
++ base_topic.c_str());
++ // clang-format off
++ uic_mqtt_dotdot_unify_switch_color_purple_unretain(base_topic.c_str(), UCL_MQTT_PUBLISH_TYPE_ALL);
++ break;
++ default:
++ break;
++ }
++ // clang-format on
++ return;
++ }
++
++ // If the value got updated but undefined, we skip publication
++ if (false == attribute_store_is_reported_defined(updated_node)) {
++ sl_log_debug(LOG_TAG, "Reported value is undefined. Skipping publication");
++ return;
++ }
++
++ // Else we assume update case:
++ // clang-format off
++ try {
++ attribute_store::attribute attr(updated_node);
++ if (type == DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_WARM_WHITE) {
++ uic_mqtt_dotdot_unify_switch_color_warm_white_publish(
++ base_topic.c_str(),
++ static_cast(attr.reported()),
++ (attr.desired_exists() && !attribute_store_is_value_matched(updated_node)) ? UCL_MQTT_PUBLISH_TYPE_REPORTED : UCL_MQTT_PUBLISH_TYPE_ALL);
++ return;
++ }
++ if (type == DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_COLD_WHITE) {
++ uic_mqtt_dotdot_unify_switch_color_cold_white_publish(
++ base_topic.c_str(),
++ static_cast(attr.reported()),
++ (attr.desired_exists() && !attribute_store_is_value_matched(updated_node)) ? UCL_MQTT_PUBLISH_TYPE_REPORTED : UCL_MQTT_PUBLISH_TYPE_ALL);
++ return;
++ }
++ if (type == DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_RED) {
++ uic_mqtt_dotdot_unify_switch_color_red_publish(
++ base_topic.c_str(),
++ static_cast(attr.reported()),
++ (attr.desired_exists() && !attribute_store_is_value_matched(updated_node)) ? UCL_MQTT_PUBLISH_TYPE_REPORTED : UCL_MQTT_PUBLISH_TYPE_ALL);
++ return;
++ }
++ if (type == DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_GREEN) {
++ uic_mqtt_dotdot_unify_switch_color_green_publish(
++ base_topic.c_str(),
++ static_cast(attr.reported()),
++ (attr.desired_exists() && !attribute_store_is_value_matched(updated_node)) ? UCL_MQTT_PUBLISH_TYPE_REPORTED : UCL_MQTT_PUBLISH_TYPE_ALL);
++ return;
++ }
++ if (type == DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_BLUE) {
++ uic_mqtt_dotdot_unify_switch_color_blue_publish(
++ base_topic.c_str(),
++ static_cast(attr.reported()),
++ (attr.desired_exists() && !attribute_store_is_value_matched(updated_node)) ? UCL_MQTT_PUBLISH_TYPE_REPORTED : UCL_MQTT_PUBLISH_TYPE_ALL);
++ return;
++ }
++ if (type == DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_AMBER) {
++ uic_mqtt_dotdot_unify_switch_color_amber_publish(
++ base_topic.c_str(),
++ static_cast(attr.reported()),
++ (attr.desired_exists() && !attribute_store_is_value_matched(updated_node)) ? UCL_MQTT_PUBLISH_TYPE_REPORTED : UCL_MQTT_PUBLISH_TYPE_ALL);
++ return;
++ }
++ if (type == DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_CYAN) {
++ uic_mqtt_dotdot_unify_switch_color_cyan_publish(
++ base_topic.c_str(),
++ static_cast(attr.reported()),
++ (attr.desired_exists() && !attribute_store_is_value_matched(updated_node)) ? UCL_MQTT_PUBLISH_TYPE_REPORTED : UCL_MQTT_PUBLISH_TYPE_ALL);
++ return;
++ }
++ if (type == DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_PURPLE) {
++ uic_mqtt_dotdot_unify_switch_color_purple_publish(
++ base_topic.c_str(),
++ static_cast(attr.reported()),
++ (attr.desired_exists() && !attribute_store_is_value_matched(updated_node)) ? UCL_MQTT_PUBLISH_TYPE_REPORTED : UCL_MQTT_PUBLISH_TYPE_ALL);
++ return;
++ }
++ } catch (std::exception &ex) {
++ sl_log_warning(LOG_TAG, "Failed to publish the Reported attribute value: %s", ex.what());
++ }
++}
++
++static void unify_switch_color_cluster_cluster_revision_callback(
++ attribute_store_node_t updated_node, attribute_store_change_t change)
++{
++ // clang-format on
++ if (false == is_publish_reported_attribute_values_to_mqtt_enabled()) {
++ return;
++ }
++
++ // Get the UNID and EndPoint, and prepare the basic topic
++ char unid[MAXIMUM_UNID_SIZE] = {};
++ dotdot_endpoint_id_t endpoint_id = 0;
++ // clang-format off
++ // clang-format on
++ if (SL_STATUS_OK
++ != unify_dotdot_attributes_get_unid_endpoint()(updated_node,
++ unid,
++ &endpoint_id)) {
++ return;
++ }
++ // clang-format off
++ // clang-format on
++
++ std::string base_topic = "ucl/by-unid/" + std::string(unid);
++ // clang-format off
++ base_topic += "/ep" + std::to_string(endpoint_id);
++
++ if ((change == ATTRIBUTE_CREATED) || (change == ATTRIBUTE_UPDATED)) {
++ // On attribute creation, make sure to publish the attribute revision for the first time
++ std::string cluster_revision_topic = base_topic + "/UnifySwitchColor/Attributes/ClusterRevision";
++ if (uic_mqtt_count_topics(cluster_revision_topic.c_str()) == 0) {
++ uic_mqtt_dotdot_unify_switch_color_publish_cluster_revision(base_topic.c_str(), 1);
++ }
++ }
++
++ if (change == ATTRIBUTE_DELETED) {
++ // Check if we just erased the last attribute under a cluster, if yes, unretain
++ // the Cluster revision too.
++ if (false == dotdot_is_any_unify_switch_color_attribute_supported(unid, endpoint_id)) {
++ base_topic += "/UnifySwitchColor";
++ sl_log_debug(LOG_TAG, "No more attributes supported for UnifySwitchColor cluster for UNID %s Endpoint %d. Unretaining leftover topics at %s",unid, endpoint_id, base_topic.c_str());
++ uic_mqtt_unretain(base_topic.c_str());
++ }
++ }
++}
++
++
+
+ // Initialization of the component.
+ sl_status_t unify_dotdot_attribute_store_attribute_publisher_init()
+@@ -36615,6 +36984,118 @@ sl_status_t unify_dotdot_attribute_store_attribute_publisher_init()
+ attribute_store_register_callback_by_type(
+ unify_humidity_control_cluster_cluster_revision_callback,
+ DOTDOT_ATTRIBUTE_ID_UNIFY_HUMIDITY_CONTROL_AUTO_SETPOINT_PRECISION);
++ //Desired attribute state
++ attribute_store_register_callback_by_type_and_state(
++ unify_switch_color_cluster_publish_desired_value_callback,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_WARM_WHITE,
++ DESIRED_ATTRIBUTE);
++ //Reported attribute state
++ attribute_store_register_callback_by_type_and_state(
++ unify_switch_color_cluster_publish_reported_value_callback,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_WARM_WHITE,
++ REPORTED_ATTRIBUTE);
++ //registering a callback when an attribute is created for publishing cluster revision
++ attribute_store_register_callback_by_type(
++ unify_switch_color_cluster_cluster_revision_callback,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_WARM_WHITE);
++ //Desired attribute state
++ attribute_store_register_callback_by_type_and_state(
++ unify_switch_color_cluster_publish_desired_value_callback,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_COLD_WHITE,
++ DESIRED_ATTRIBUTE);
++ //Reported attribute state
++ attribute_store_register_callback_by_type_and_state(
++ unify_switch_color_cluster_publish_reported_value_callback,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_COLD_WHITE,
++ REPORTED_ATTRIBUTE);
++ //registering a callback when an attribute is created for publishing cluster revision
++ attribute_store_register_callback_by_type(
++ unify_switch_color_cluster_cluster_revision_callback,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_COLD_WHITE);
++ //Desired attribute state
++ attribute_store_register_callback_by_type_and_state(
++ unify_switch_color_cluster_publish_desired_value_callback,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_RED,
++ DESIRED_ATTRIBUTE);
++ //Reported attribute state
++ attribute_store_register_callback_by_type_and_state(
++ unify_switch_color_cluster_publish_reported_value_callback,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_RED,
++ REPORTED_ATTRIBUTE);
++ //registering a callback when an attribute is created for publishing cluster revision
++ attribute_store_register_callback_by_type(
++ unify_switch_color_cluster_cluster_revision_callback,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_RED);
++ //Desired attribute state
++ attribute_store_register_callback_by_type_and_state(
++ unify_switch_color_cluster_publish_desired_value_callback,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_GREEN,
++ DESIRED_ATTRIBUTE);
++ //Reported attribute state
++ attribute_store_register_callback_by_type_and_state(
++ unify_switch_color_cluster_publish_reported_value_callback,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_GREEN,
++ REPORTED_ATTRIBUTE);
++ //registering a callback when an attribute is created for publishing cluster revision
++ attribute_store_register_callback_by_type(
++ unify_switch_color_cluster_cluster_revision_callback,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_GREEN);
++ //Desired attribute state
++ attribute_store_register_callback_by_type_and_state(
++ unify_switch_color_cluster_publish_desired_value_callback,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_BLUE,
++ DESIRED_ATTRIBUTE);
++ //Reported attribute state
++ attribute_store_register_callback_by_type_and_state(
++ unify_switch_color_cluster_publish_reported_value_callback,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_BLUE,
++ REPORTED_ATTRIBUTE);
++ //registering a callback when an attribute is created for publishing cluster revision
++ attribute_store_register_callback_by_type(
++ unify_switch_color_cluster_cluster_revision_callback,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_BLUE);
++ //Desired attribute state
++ attribute_store_register_callback_by_type_and_state(
++ unify_switch_color_cluster_publish_desired_value_callback,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_AMBER,
++ DESIRED_ATTRIBUTE);
++ //Reported attribute state
++ attribute_store_register_callback_by_type_and_state(
++ unify_switch_color_cluster_publish_reported_value_callback,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_AMBER,
++ REPORTED_ATTRIBUTE);
++ //registering a callback when an attribute is created for publishing cluster revision
++ attribute_store_register_callback_by_type(
++ unify_switch_color_cluster_cluster_revision_callback,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_AMBER);
++ //Desired attribute state
++ attribute_store_register_callback_by_type_and_state(
++ unify_switch_color_cluster_publish_desired_value_callback,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_CYAN,
++ DESIRED_ATTRIBUTE);
++ //Reported attribute state
++ attribute_store_register_callback_by_type_and_state(
++ unify_switch_color_cluster_publish_reported_value_callback,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_CYAN,
++ REPORTED_ATTRIBUTE);
++ //registering a callback when an attribute is created for publishing cluster revision
++ attribute_store_register_callback_by_type(
++ unify_switch_color_cluster_cluster_revision_callback,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_CYAN);
++ //Desired attribute state
++ attribute_store_register_callback_by_type_and_state(
++ unify_switch_color_cluster_publish_desired_value_callback,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_PURPLE,
++ DESIRED_ATTRIBUTE);
++ //Reported attribute state
++ attribute_store_register_callback_by_type_and_state(
++ unify_switch_color_cluster_publish_reported_value_callback,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_PURPLE,
++ REPORTED_ATTRIBUTE);
++ //registering a callback when an attribute is created for publishing cluster revision
++ attribute_store_register_callback_by_type(
++ unify_switch_color_cluster_cluster_revision_callback,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_PURPLE);
+
+ return SL_STATUS_OK;
+ }
+diff --git a/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_force_read_attributes_command_callbacks.c b/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_force_read_attributes_command_callbacks.c
+index fe3a605125..17cb0e11f5 100644
+--- a/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_force_read_attributes_command_callbacks.c
++++ b/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_force_read_attributes_command_callbacks.c
+@@ -4619,6 +4619,71 @@ static sl_status_t uic_mqtt_dotdot_unify_humidity_control_force_read_attributes_
+ }
+ return SL_STATUS_OK;
+ }
++////////////////////////////////////////////////////////////////////////////////
++// Start of cluster UnifySwitchColor
++////////////////////////////////////////////////////////////////////////////////
++static sl_status_t uic_mqtt_dotdot_unify_switch_color_force_read_attributes_callback (
++ const dotdot_unid_t unid,
++ dotdot_endpoint_id_t endpoint_id,
++ uic_mqtt_dotdot_callback_call_type_t call_type,
++ uic_mqtt_dotdot_unify_switch_color_updated_state_t attribute_list) {
++
++ if (false == is_force_read_attributes_enabled()){
++ return SL_STATUS_FAIL;
++ }
++
++ if (call_type == UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK) {
++ if (is_automatic_deduction_of_supported_commands_enabled()) {
++ return dotdot_is_any_unify_switch_color_attribute_supported(unid, endpoint_id) ?
++ SL_STATUS_OK : SL_STATUS_FAIL;
++ } else {
++ return SL_STATUS_FAIL;
++ }
++ }
++
++ // Go and undefine everything that needs to be read again:
++ if (true == attribute_list.warm_white) {
++ if (SL_STATUS_OK == dotdot_unify_switch_color_warm_white_undefine_reported(unid, endpoint_id)) {
++ sl_log_debug(LOG_TAG, "Undefined Reported value of UnifySwitchColor::WarmWhite under %s - Endpoint %d", unid, endpoint_id);
++ }
++ }
++ if (true == attribute_list.cold_white) {
++ if (SL_STATUS_OK == dotdot_unify_switch_color_cold_white_undefine_reported(unid, endpoint_id)) {
++ sl_log_debug(LOG_TAG, "Undefined Reported value of UnifySwitchColor::ColdWhite under %s - Endpoint %d", unid, endpoint_id);
++ }
++ }
++ if (true == attribute_list.red) {
++ if (SL_STATUS_OK == dotdot_unify_switch_color_red_undefine_reported(unid, endpoint_id)) {
++ sl_log_debug(LOG_TAG, "Undefined Reported value of UnifySwitchColor::Red under %s - Endpoint %d", unid, endpoint_id);
++ }
++ }
++ if (true == attribute_list.green) {
++ if (SL_STATUS_OK == dotdot_unify_switch_color_green_undefine_reported(unid, endpoint_id)) {
++ sl_log_debug(LOG_TAG, "Undefined Reported value of UnifySwitchColor::Green under %s - Endpoint %d", unid, endpoint_id);
++ }
++ }
++ if (true == attribute_list.blue) {
++ if (SL_STATUS_OK == dotdot_unify_switch_color_blue_undefine_reported(unid, endpoint_id)) {
++ sl_log_debug(LOG_TAG, "Undefined Reported value of UnifySwitchColor::Blue under %s - Endpoint %d", unid, endpoint_id);
++ }
++ }
++ if (true == attribute_list.amber) {
++ if (SL_STATUS_OK == dotdot_unify_switch_color_amber_undefine_reported(unid, endpoint_id)) {
++ sl_log_debug(LOG_TAG, "Undefined Reported value of UnifySwitchColor::Amber under %s - Endpoint %d", unid, endpoint_id);
++ }
++ }
++ if (true == attribute_list.cyan) {
++ if (SL_STATUS_OK == dotdot_unify_switch_color_cyan_undefine_reported(unid, endpoint_id)) {
++ sl_log_debug(LOG_TAG, "Undefined Reported value of UnifySwitchColor::Cyan under %s - Endpoint %d", unid, endpoint_id);
++ }
++ }
++ if (true == attribute_list.purple) {
++ if (SL_STATUS_OK == dotdot_unify_switch_color_purple_undefine_reported(unid, endpoint_id)) {
++ sl_log_debug(LOG_TAG, "Undefined Reported value of UnifySwitchColor::Purple under %s - Endpoint %d", unid, endpoint_id);
++ }
++ }
++ return SL_STATUS_OK;
++}
+ // clang-format on
+
+ ////////////////////////////////////////////////////////////////////////////////
+@@ -4733,6 +4798,8 @@ sl_status_t
+
+ uic_mqtt_dotdot_set_unify_humidity_control_force_read_attributes_callback(&uic_mqtt_dotdot_unify_humidity_control_force_read_attributes_callback);
+
++ uic_mqtt_dotdot_set_unify_switch_color_force_read_attributes_callback(&uic_mqtt_dotdot_unify_switch_color_force_read_attributes_callback);
++
+ // clang-format on
+
+ return SL_STATUS_OK;
+diff --git a/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_helpers.cpp b/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_helpers.cpp
+index ba326df8ab..2d6b9ffc81 100644
+--- a/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_helpers.cpp
++++ b/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_helpers.cpp
+@@ -85167,5 +85167,936 @@ bool dotdot_is_any_unify_humidity_control_writable_attribute_supported(
+ const dotdot_endpoint_id_t endpoint_id) {
+
+
++ return false;
++}
++////////////////////////////////////////////////////////////////////////////////
++// Start of cluster UnifySwitchColor
++////////////////////////////////////////////////////////////////////////////////
++bool dotdot_is_supported_unify_switch_color_warm_white(
++ const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint_id)
++{
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_WARM_WHITE);
++ return attribute_store_node_exists(node);
++}
++
++uint8_t dotdot_get_unify_switch_color_warm_white(
++ const dotdot_unid_t unid,
++ dotdot_endpoint_id_t endpoint_id,
++ attribute_store_node_value_state_t value_state)
++{
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_WARM_WHITE);
++
++ uint8_t result = {};
++ attribute_store_read_value(node,
++ value_state,
++ (uint8_t *)&result,
++ sizeof(result));
++ return result;
++}
++
++sl_status_t dotdot_set_unify_switch_color_warm_white(
++ const dotdot_unid_t unid,
++ dotdot_endpoint_id_t endpoint_id,
++ attribute_store_node_value_state_t value_state,
++ uint8_t new_warm_white
++ )
++{
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_WARM_WHITE);
++
++ return attribute_store_set_node_attribute_value(node,
++ value_state,
++ (uint8_t *)&new_warm_white,
++ sizeof(uint8_t));
++ }
++
++sl_status_t dotdot_unify_switch_color_warm_white_undefine_reported(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id) {
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_WARM_WHITE);
++ attribute_store_undefine_reported(node);
++ return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL;
++}
++
++sl_status_t dotdot_unify_switch_color_warm_white_undefine_desired(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id) {
++
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_WARM_WHITE);
++ attribute_store_undefine_desired(node);
++ return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL;
++}
++
++
++bool dotdot_unify_switch_color_warm_white_is_reported_defined(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id)
++{
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_WARM_WHITE);
++ return attribute_store_is_reported_defined(node);
++}
++
++bool dotdot_unify_switch_color_warm_white_is_desired_defined(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id)
++{
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_WARM_WHITE);
++ return attribute_store_is_desired_defined(node);
++}
++
++sl_status_t dotdot_create_unify_switch_color_warm_white(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id) {
++
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node =
++ attribute_store_create_child_if_missing(endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_WARM_WHITE);
++
++ return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL;
++}
++bool dotdot_is_supported_unify_switch_color_cold_white(
++ const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint_id)
++{
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_COLD_WHITE);
++ return attribute_store_node_exists(node);
++}
++
++uint8_t dotdot_get_unify_switch_color_cold_white(
++ const dotdot_unid_t unid,
++ dotdot_endpoint_id_t endpoint_id,
++ attribute_store_node_value_state_t value_state)
++{
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_COLD_WHITE);
++
++ uint8_t result = {};
++ attribute_store_read_value(node,
++ value_state,
++ (uint8_t *)&result,
++ sizeof(result));
++ return result;
++}
++
++sl_status_t dotdot_set_unify_switch_color_cold_white(
++ const dotdot_unid_t unid,
++ dotdot_endpoint_id_t endpoint_id,
++ attribute_store_node_value_state_t value_state,
++ uint8_t new_cold_white
++ )
++{
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_COLD_WHITE);
++
++ return attribute_store_set_node_attribute_value(node,
++ value_state,
++ (uint8_t *)&new_cold_white,
++ sizeof(uint8_t));
++ }
++
++sl_status_t dotdot_unify_switch_color_cold_white_undefine_reported(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id) {
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_COLD_WHITE);
++ attribute_store_undefine_reported(node);
++ return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL;
++}
++
++sl_status_t dotdot_unify_switch_color_cold_white_undefine_desired(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id) {
++
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_COLD_WHITE);
++ attribute_store_undefine_desired(node);
++ return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL;
++}
++
++
++bool dotdot_unify_switch_color_cold_white_is_reported_defined(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id)
++{
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_COLD_WHITE);
++ return attribute_store_is_reported_defined(node);
++}
++
++bool dotdot_unify_switch_color_cold_white_is_desired_defined(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id)
++{
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_COLD_WHITE);
++ return attribute_store_is_desired_defined(node);
++}
++
++sl_status_t dotdot_create_unify_switch_color_cold_white(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id) {
++
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node =
++ attribute_store_create_child_if_missing(endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_COLD_WHITE);
++
++ return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL;
++}
++bool dotdot_is_supported_unify_switch_color_red(
++ const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint_id)
++{
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_RED);
++ return attribute_store_node_exists(node);
++}
++
++uint8_t dotdot_get_unify_switch_color_red(
++ const dotdot_unid_t unid,
++ dotdot_endpoint_id_t endpoint_id,
++ attribute_store_node_value_state_t value_state)
++{
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_RED);
++
++ uint8_t result = {};
++ attribute_store_read_value(node,
++ value_state,
++ (uint8_t *)&result,
++ sizeof(result));
++ return result;
++}
++
++sl_status_t dotdot_set_unify_switch_color_red(
++ const dotdot_unid_t unid,
++ dotdot_endpoint_id_t endpoint_id,
++ attribute_store_node_value_state_t value_state,
++ uint8_t new_red
++ )
++{
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_RED);
++
++ return attribute_store_set_node_attribute_value(node,
++ value_state,
++ (uint8_t *)&new_red,
++ sizeof(uint8_t));
++ }
++
++sl_status_t dotdot_unify_switch_color_red_undefine_reported(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id) {
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_RED);
++ attribute_store_undefine_reported(node);
++ return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL;
++}
++
++sl_status_t dotdot_unify_switch_color_red_undefine_desired(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id) {
++
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_RED);
++ attribute_store_undefine_desired(node);
++ return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL;
++}
++
++
++bool dotdot_unify_switch_color_red_is_reported_defined(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id)
++{
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_RED);
++ return attribute_store_is_reported_defined(node);
++}
++
++bool dotdot_unify_switch_color_red_is_desired_defined(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id)
++{
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_RED);
++ return attribute_store_is_desired_defined(node);
++}
++
++sl_status_t dotdot_create_unify_switch_color_red(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id) {
++
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node =
++ attribute_store_create_child_if_missing(endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_RED);
++
++ return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL;
++}
++bool dotdot_is_supported_unify_switch_color_green(
++ const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint_id)
++{
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_GREEN);
++ return attribute_store_node_exists(node);
++}
++
++uint8_t dotdot_get_unify_switch_color_green(
++ const dotdot_unid_t unid,
++ dotdot_endpoint_id_t endpoint_id,
++ attribute_store_node_value_state_t value_state)
++{
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_GREEN);
++
++ uint8_t result = {};
++ attribute_store_read_value(node,
++ value_state,
++ (uint8_t *)&result,
++ sizeof(result));
++ return result;
++}
++
++sl_status_t dotdot_set_unify_switch_color_green(
++ const dotdot_unid_t unid,
++ dotdot_endpoint_id_t endpoint_id,
++ attribute_store_node_value_state_t value_state,
++ uint8_t new_green
++ )
++{
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_GREEN);
++
++ return attribute_store_set_node_attribute_value(node,
++ value_state,
++ (uint8_t *)&new_green,
++ sizeof(uint8_t));
++ }
++
++sl_status_t dotdot_unify_switch_color_green_undefine_reported(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id) {
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_GREEN);
++ attribute_store_undefine_reported(node);
++ return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL;
++}
++
++sl_status_t dotdot_unify_switch_color_green_undefine_desired(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id) {
++
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_GREEN);
++ attribute_store_undefine_desired(node);
++ return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL;
++}
++
++
++bool dotdot_unify_switch_color_green_is_reported_defined(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id)
++{
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_GREEN);
++ return attribute_store_is_reported_defined(node);
++}
++
++bool dotdot_unify_switch_color_green_is_desired_defined(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id)
++{
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_GREEN);
++ return attribute_store_is_desired_defined(node);
++}
++
++sl_status_t dotdot_create_unify_switch_color_green(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id) {
++
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node =
++ attribute_store_create_child_if_missing(endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_GREEN);
++
++ return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL;
++}
++bool dotdot_is_supported_unify_switch_color_blue(
++ const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint_id)
++{
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_BLUE);
++ return attribute_store_node_exists(node);
++}
++
++uint8_t dotdot_get_unify_switch_color_blue(
++ const dotdot_unid_t unid,
++ dotdot_endpoint_id_t endpoint_id,
++ attribute_store_node_value_state_t value_state)
++{
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_BLUE);
++
++ uint8_t result = {};
++ attribute_store_read_value(node,
++ value_state,
++ (uint8_t *)&result,
++ sizeof(result));
++ return result;
++}
++
++sl_status_t dotdot_set_unify_switch_color_blue(
++ const dotdot_unid_t unid,
++ dotdot_endpoint_id_t endpoint_id,
++ attribute_store_node_value_state_t value_state,
++ uint8_t new_blue
++ )
++{
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_BLUE);
++
++ return attribute_store_set_node_attribute_value(node,
++ value_state,
++ (uint8_t *)&new_blue,
++ sizeof(uint8_t));
++ }
++
++sl_status_t dotdot_unify_switch_color_blue_undefine_reported(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id) {
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_BLUE);
++ attribute_store_undefine_reported(node);
++ return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL;
++}
++
++sl_status_t dotdot_unify_switch_color_blue_undefine_desired(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id) {
++
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_BLUE);
++ attribute_store_undefine_desired(node);
++ return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL;
++}
++
++
++bool dotdot_unify_switch_color_blue_is_reported_defined(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id)
++{
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_BLUE);
++ return attribute_store_is_reported_defined(node);
++}
++
++bool dotdot_unify_switch_color_blue_is_desired_defined(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id)
++{
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_BLUE);
++ return attribute_store_is_desired_defined(node);
++}
++
++sl_status_t dotdot_create_unify_switch_color_blue(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id) {
++
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node =
++ attribute_store_create_child_if_missing(endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_BLUE);
++
++ return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL;
++}
++bool dotdot_is_supported_unify_switch_color_amber(
++ const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint_id)
++{
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_AMBER);
++ return attribute_store_node_exists(node);
++}
++
++uint8_t dotdot_get_unify_switch_color_amber(
++ const dotdot_unid_t unid,
++ dotdot_endpoint_id_t endpoint_id,
++ attribute_store_node_value_state_t value_state)
++{
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_AMBER);
++
++ uint8_t result = {};
++ attribute_store_read_value(node,
++ value_state,
++ (uint8_t *)&result,
++ sizeof(result));
++ return result;
++}
++
++sl_status_t dotdot_set_unify_switch_color_amber(
++ const dotdot_unid_t unid,
++ dotdot_endpoint_id_t endpoint_id,
++ attribute_store_node_value_state_t value_state,
++ uint8_t new_amber
++ )
++{
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_AMBER);
++
++ return attribute_store_set_node_attribute_value(node,
++ value_state,
++ (uint8_t *)&new_amber,
++ sizeof(uint8_t));
++ }
++
++sl_status_t dotdot_unify_switch_color_amber_undefine_reported(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id) {
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_AMBER);
++ attribute_store_undefine_reported(node);
++ return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL;
++}
++
++sl_status_t dotdot_unify_switch_color_amber_undefine_desired(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id) {
++
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_AMBER);
++ attribute_store_undefine_desired(node);
++ return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL;
++}
++
++
++bool dotdot_unify_switch_color_amber_is_reported_defined(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id)
++{
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_AMBER);
++ return attribute_store_is_reported_defined(node);
++}
++
++bool dotdot_unify_switch_color_amber_is_desired_defined(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id)
++{
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_AMBER);
++ return attribute_store_is_desired_defined(node);
++}
++
++sl_status_t dotdot_create_unify_switch_color_amber(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id) {
++
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node =
++ attribute_store_create_child_if_missing(endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_AMBER);
++
++ return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL;
++}
++bool dotdot_is_supported_unify_switch_color_cyan(
++ const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint_id)
++{
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_CYAN);
++ return attribute_store_node_exists(node);
++}
++
++uint8_t dotdot_get_unify_switch_color_cyan(
++ const dotdot_unid_t unid,
++ dotdot_endpoint_id_t endpoint_id,
++ attribute_store_node_value_state_t value_state)
++{
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_CYAN);
++
++ uint8_t result = {};
++ attribute_store_read_value(node,
++ value_state,
++ (uint8_t *)&result,
++ sizeof(result));
++ return result;
++}
++
++sl_status_t dotdot_set_unify_switch_color_cyan(
++ const dotdot_unid_t unid,
++ dotdot_endpoint_id_t endpoint_id,
++ attribute_store_node_value_state_t value_state,
++ uint8_t new_cyan
++ )
++{
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_CYAN);
++
++ return attribute_store_set_node_attribute_value(node,
++ value_state,
++ (uint8_t *)&new_cyan,
++ sizeof(uint8_t));
++ }
++
++sl_status_t dotdot_unify_switch_color_cyan_undefine_reported(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id) {
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_CYAN);
++ attribute_store_undefine_reported(node);
++ return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL;
++}
++
++sl_status_t dotdot_unify_switch_color_cyan_undefine_desired(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id) {
++
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_CYAN);
++ attribute_store_undefine_desired(node);
++ return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL;
++}
++
++
++bool dotdot_unify_switch_color_cyan_is_reported_defined(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id)
++{
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_CYAN);
++ return attribute_store_is_reported_defined(node);
++}
++
++bool dotdot_unify_switch_color_cyan_is_desired_defined(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id)
++{
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_CYAN);
++ return attribute_store_is_desired_defined(node);
++}
++
++sl_status_t dotdot_create_unify_switch_color_cyan(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id) {
++
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node =
++ attribute_store_create_child_if_missing(endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_CYAN);
++
++ return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL;
++}
++bool dotdot_is_supported_unify_switch_color_purple(
++ const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint_id)
++{
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_PURPLE);
++ return attribute_store_node_exists(node);
++}
++
++uint8_t dotdot_get_unify_switch_color_purple(
++ const dotdot_unid_t unid,
++ dotdot_endpoint_id_t endpoint_id,
++ attribute_store_node_value_state_t value_state)
++{
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_PURPLE);
++
++ uint8_t result = {};
++ attribute_store_read_value(node,
++ value_state,
++ (uint8_t *)&result,
++ sizeof(result));
++ return result;
++}
++
++sl_status_t dotdot_set_unify_switch_color_purple(
++ const dotdot_unid_t unid,
++ dotdot_endpoint_id_t endpoint_id,
++ attribute_store_node_value_state_t value_state,
++ uint8_t new_purple
++ )
++{
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_PURPLE);
++
++ return attribute_store_set_node_attribute_value(node,
++ value_state,
++ (uint8_t *)&new_purple,
++ sizeof(uint8_t));
++ }
++
++sl_status_t dotdot_unify_switch_color_purple_undefine_reported(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id) {
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_PURPLE);
++ attribute_store_undefine_reported(node);
++ return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL;
++}
++
++sl_status_t dotdot_unify_switch_color_purple_undefine_desired(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id) {
++
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_PURPLE);
++ attribute_store_undefine_desired(node);
++ return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL;
++}
++
++
++bool dotdot_unify_switch_color_purple_is_reported_defined(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id)
++{
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_PURPLE);
++ return attribute_store_is_reported_defined(node);
++}
++
++bool dotdot_unify_switch_color_purple_is_desired_defined(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id)
++{
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node
++ = attribute_store_get_first_child_by_type(
++ endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_PURPLE);
++ return attribute_store_is_desired_defined(node);
++}
++
++sl_status_t dotdot_create_unify_switch_color_purple(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id) {
++
++ attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id);
++ attribute_store_node_t node =
++ attribute_store_create_child_if_missing(endpoint_node,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_PURPLE);
++
++ return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL;
++}
++
++bool dotdot_is_any_unify_switch_color_attribute_supported(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id) {
++
++ if (true == dotdot_is_supported_unify_switch_color_warm_white(unid, endpoint_id)) {
++ return true;
++ }
++ if (true == dotdot_is_supported_unify_switch_color_cold_white(unid, endpoint_id)) {
++ return true;
++ }
++ if (true == dotdot_is_supported_unify_switch_color_red(unid, endpoint_id)) {
++ return true;
++ }
++ if (true == dotdot_is_supported_unify_switch_color_green(unid, endpoint_id)) {
++ return true;
++ }
++ if (true == dotdot_is_supported_unify_switch_color_blue(unid, endpoint_id)) {
++ return true;
++ }
++ if (true == dotdot_is_supported_unify_switch_color_amber(unid, endpoint_id)) {
++ return true;
++ }
++ if (true == dotdot_is_supported_unify_switch_color_cyan(unid, endpoint_id)) {
++ return true;
++ }
++ if (true == dotdot_is_supported_unify_switch_color_purple(unid, endpoint_id)) {
++ return true;
++ }
++
++ return false;
++}
++
++bool dotdot_is_any_unify_switch_color_writable_attribute_supported(
++ const dotdot_unid_t unid,
++ const dotdot_endpoint_id_t endpoint_id) {
++
++
+ return false;
+ }
+diff --git a/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_registration.cpp b/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_registration.cpp
+index 329813ba1c..15a883ab8a 100644
+--- a/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_registration.cpp
++++ b/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_registration.cpp
+@@ -17647,6 +17647,198 @@ sl_status_t unify_dotdot_attribute_store_registration_init()
+ // clang-format off
+ // clang-format on
+
++ {
++ // uint8 // uint8 // uint8_t
++ std::string attribute_type_string = "uint8_t";
++ attribute_store_storage_type_t storage_type = UNKNOWN_STORAGE_TYPE;
++
++ // clang-format off
++ storage_type = attribute_storage_type_conversion(attribute_type_string);
++
++ if (storage_type == UNKNOWN_STORAGE_TYPE) {
++ sl_log_warning(LOG_TAG,
++ "Unkown storage type for ZCL UnifySwitchColor WarmWhite, "
++ "type: uint8 // uint8_t");
++ }
++
++ status |= attribute_store_register_type(
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_WARM_WHITE,
++ "ZCL UnifySwitchColor WarmWhite",
++ ATTRIBUTE_STORE_INVALID_ATTRIBUTE_TYPE,
++ storage_type);
++ }
++
++ // clang-format off
++ // clang-format on
++
++ {
++ // uint8 // uint8 // uint8_t
++ std::string attribute_type_string = "uint8_t";
++ attribute_store_storage_type_t storage_type = UNKNOWN_STORAGE_TYPE;
++
++ // clang-format off
++ storage_type = attribute_storage_type_conversion(attribute_type_string);
++
++ if (storage_type == UNKNOWN_STORAGE_TYPE) {
++ sl_log_warning(LOG_TAG,
++ "Unkown storage type for ZCL UnifySwitchColor ColdWhite, "
++ "type: uint8 // uint8_t");
++ }
++
++ status |= attribute_store_register_type(
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_COLD_WHITE,
++ "ZCL UnifySwitchColor ColdWhite",
++ ATTRIBUTE_STORE_INVALID_ATTRIBUTE_TYPE,
++ storage_type);
++ }
++
++ // clang-format off
++ // clang-format on
++
++ {
++ // uint8 // uint8 // uint8_t
++ std::string attribute_type_string = "uint8_t";
++ attribute_store_storage_type_t storage_type = UNKNOWN_STORAGE_TYPE;
++
++ // clang-format off
++ storage_type = attribute_storage_type_conversion(attribute_type_string);
++
++ if (storage_type == UNKNOWN_STORAGE_TYPE) {
++ sl_log_warning(LOG_TAG,
++ "Unkown storage type for ZCL UnifySwitchColor Red, "
++ "type: uint8 // uint8_t");
++ }
++
++ status |= attribute_store_register_type(
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_RED,
++ "ZCL UnifySwitchColor Red",
++ ATTRIBUTE_STORE_INVALID_ATTRIBUTE_TYPE,
++ storage_type);
++ }
++
++ // clang-format off
++ // clang-format on
++
++ {
++ // uint8 // uint8 // uint8_t
++ std::string attribute_type_string = "uint8_t";
++ attribute_store_storage_type_t storage_type = UNKNOWN_STORAGE_TYPE;
++
++ // clang-format off
++ storage_type = attribute_storage_type_conversion(attribute_type_string);
++
++ if (storage_type == UNKNOWN_STORAGE_TYPE) {
++ sl_log_warning(LOG_TAG,
++ "Unkown storage type for ZCL UnifySwitchColor Green, "
++ "type: uint8 // uint8_t");
++ }
++
++ status |= attribute_store_register_type(
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_GREEN,
++ "ZCL UnifySwitchColor Green",
++ ATTRIBUTE_STORE_INVALID_ATTRIBUTE_TYPE,
++ storage_type);
++ }
++
++ // clang-format off
++ // clang-format on
++
++ {
++ // uint8 // uint8 // uint8_t
++ std::string attribute_type_string = "uint8_t";
++ attribute_store_storage_type_t storage_type = UNKNOWN_STORAGE_TYPE;
++
++ // clang-format off
++ storage_type = attribute_storage_type_conversion(attribute_type_string);
++
++ if (storage_type == UNKNOWN_STORAGE_TYPE) {
++ sl_log_warning(LOG_TAG,
++ "Unkown storage type for ZCL UnifySwitchColor Blue, "
++ "type: uint8 // uint8_t");
++ }
++
++ status |= attribute_store_register_type(
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_BLUE,
++ "ZCL UnifySwitchColor Blue",
++ ATTRIBUTE_STORE_INVALID_ATTRIBUTE_TYPE,
++ storage_type);
++ }
++
++ // clang-format off
++ // clang-format on
++
++ {
++ // uint8 // uint8 // uint8_t
++ std::string attribute_type_string = "uint8_t";
++ attribute_store_storage_type_t storage_type = UNKNOWN_STORAGE_TYPE;
++
++ // clang-format off
++ storage_type = attribute_storage_type_conversion(attribute_type_string);
++
++ if (storage_type == UNKNOWN_STORAGE_TYPE) {
++ sl_log_warning(LOG_TAG,
++ "Unkown storage type for ZCL UnifySwitchColor Amber, "
++ "type: uint8 // uint8_t");
++ }
++
++ status |= attribute_store_register_type(
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_AMBER,
++ "ZCL UnifySwitchColor Amber",
++ ATTRIBUTE_STORE_INVALID_ATTRIBUTE_TYPE,
++ storage_type);
++ }
++
++ // clang-format off
++ // clang-format on
++
++ {
++ // uint8 // uint8 // uint8_t
++ std::string attribute_type_string = "uint8_t";
++ attribute_store_storage_type_t storage_type = UNKNOWN_STORAGE_TYPE;
++
++ // clang-format off
++ storage_type = attribute_storage_type_conversion(attribute_type_string);
++
++ if (storage_type == UNKNOWN_STORAGE_TYPE) {
++ sl_log_warning(LOG_TAG,
++ "Unkown storage type for ZCL UnifySwitchColor Cyan, "
++ "type: uint8 // uint8_t");
++ }
++
++ status |= attribute_store_register_type(
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_CYAN,
++ "ZCL UnifySwitchColor Cyan",
++ ATTRIBUTE_STORE_INVALID_ATTRIBUTE_TYPE,
++ storage_type);
++ }
++
++ // clang-format off
++ // clang-format on
++
++ {
++ // uint8 // uint8 // uint8_t
++ std::string attribute_type_string = "uint8_t";
++ attribute_store_storage_type_t storage_type = UNKNOWN_STORAGE_TYPE;
++
++ // clang-format off
++ storage_type = attribute_storage_type_conversion(attribute_type_string);
++
++ if (storage_type == UNKNOWN_STORAGE_TYPE) {
++ sl_log_warning(LOG_TAG,
++ "Unkown storage type for ZCL UnifySwitchColor Purple, "
++ "type: uint8 // uint8_t");
++ }
++
++ status |= attribute_store_register_type(
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_PURPLE,
++ "ZCL UnifySwitchColor Purple",
++ ATTRIBUTE_STORE_INVALID_ATTRIBUTE_TYPE,
++ storage_type);
++ }
++
++ // clang-format off
++ // clang-format on
++
+ // Additional attributes:
+ for (auto const &a: zcl_additional_attribute_schema) {
+ status |= attribute_store_register_type(a.type,
+diff --git a/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_write_attributes_command_callbacks.c b/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_write_attributes_command_callbacks.c
+index 7443995a7b..8e992503d3 100644
+--- a/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_write_attributes_command_callbacks.c
++++ b/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_write_attributes_command_callbacks.c
+@@ -2585,6 +2585,36 @@ static sl_status_t unify_humidity_control_cluster_write_attributes_callback(
+ endpoint_id);
+ return SL_STATUS_OK;
+ }
++////////////////////////////////////////////////////////////////////////////////
++// Start of cluster UnifySwitchColor
++////////////////////////////////////////////////////////////////////////////////
++// WriteAttribute Callbacks unify_switch_color
++static sl_status_t unify_switch_color_cluster_write_attributes_callback(
++ const dotdot_unid_t unid,
++ dotdot_endpoint_id_t endpoint_id,
++ uic_mqtt_dotdot_callback_call_type_t call_type,
++ uic_mqtt_dotdot_unify_switch_color_state_t attributes,
++ uic_mqtt_dotdot_unify_switch_color_updated_state_t updated_attributes)
++{
++ if (false == is_write_attributes_enabled()) {
++ return SL_STATUS_FAIL;
++ }
++
++ if (call_type == UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK) {
++ if (is_automatic_deduction_of_supported_commands_enabled()) {
++ return dotdot_is_any_unify_switch_color_writable_attribute_supported(unid, endpoint_id) ?
++ SL_STATUS_OK : SL_STATUS_FAIL;
++ } else {
++ return SL_STATUS_FAIL;
++ }
++ }
++
++ sl_log_debug(LOG_TAG,
++ "unify_switch_color: Incoming WriteAttributes command for %s, endpoint %d.\n",
++ unid,
++ endpoint_id);
++ return SL_STATUS_OK;
++}
+ // clang-format on
+
+ ////////////////////////////////////////////////////////////////////////////////
+@@ -2758,6 +2788,9 @@ sl_status_t
+ uic_mqtt_dotdot_set_unify_humidity_control_write_attributes_callback(
+ &unify_humidity_control_cluster_write_attributes_callback);
+
++ uic_mqtt_dotdot_set_unify_switch_color_write_attributes_callback(
++ &unify_switch_color_cluster_write_attributes_callback);
++
+ // clang-format on
+
+ return SL_STATUS_OK;
+diff --git a/components/unify_dotdot_attribute_store/zap-generated/test/unify_dotdot_attribute_store_test.c b/components/unify_dotdot_attribute_store/zap-generated/test/unify_dotdot_attribute_store_test.c
+index 12f32c1833..40b1d826a4 100644
+--- a/components/unify_dotdot_attribute_store/zap-generated/test/unify_dotdot_attribute_store_test.c
++++ b/components/unify_dotdot_attribute_store/zap-generated/test/unify_dotdot_attribute_store_test.c
+@@ -1420,6 +1420,24 @@ static uic_mqtt_dotdot_unify_humidity_control_setpoint_set_callback_t test_uic_m
+ uic_mqtt_dotdot_unify_humidity_control_setpoint_set_callback_t get_uic_mqtt_dotdot_unify_humidity_control_setpoint_set_callback(){
+ return test_uic_mqtt_dotdot_unify_humidity_control_setpoint_set_callback;
+ }
++static uic_mqtt_dotdot_unify_switch_color_force_read_attributes_callback_t test_uic_mqtt_dotdot_unify_switch_color_force_read_attributes_callback = NULL;
++static uic_mqtt_dotdot_unify_switch_color_write_attributes_callback_t test_uic_mqtt_dotdot_unify_switch_color_write_attributes_callback = NULL;
++
++uic_mqtt_dotdot_unify_switch_color_force_read_attributes_callback_t get_uic_mqtt_dotdot_unify_switch_color_force_read_attributes_callback(){
++ return test_uic_mqtt_dotdot_unify_switch_color_force_read_attributes_callback;
++}
++uic_mqtt_dotdot_unify_switch_color_write_attributes_callback_t get_uic_mqtt_dotdot_unify_switch_color_write_attributes_callback(){
++ return test_uic_mqtt_dotdot_unify_switch_color_write_attributes_callback;
++}
++
++static uic_mqtt_dotdot_unify_switch_color_set_color_callback_t test_uic_mqtt_dotdot_unify_switch_color_set_color_callback = NULL;
++uic_mqtt_dotdot_unify_switch_color_set_color_callback_t get_uic_mqtt_dotdot_unify_switch_color_set_color_callback(){
++ return test_uic_mqtt_dotdot_unify_switch_color_set_color_callback;
++}
++static uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback_t test_uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback = NULL;
++uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback_t get_uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback(){
++ return test_uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback;
++}
+ // clang-format on
+
+ #define TEST_UNID "test-unid-123"
+@@ -3131,6 +3149,26 @@ void uic_mqtt_dotdot_unify_humidity_control_setpoint_set_callback_set_stub(
+ {
+ test_uic_mqtt_dotdot_unify_humidity_control_setpoint_set_callback = callback;
+ }
++void set_uic_mqtt_dotdot_unify_switch_color_force_read_attributes_callback_stub(
++ const uic_mqtt_dotdot_unify_switch_color_force_read_attributes_callback_t callback, int cmock_num_calls)
++{
++ test_uic_mqtt_dotdot_unify_switch_color_force_read_attributes_callback = callback;
++}
++void set_uic_mqtt_dotdot_unify_switch_color_write_attributes_callback_stub(
++ const uic_mqtt_dotdot_unify_switch_color_write_attributes_callback_t callback, int cmock_num_calls)
++{
++ test_uic_mqtt_dotdot_unify_switch_color_write_attributes_callback = callback;
++}
++void uic_mqtt_dotdot_unify_switch_color_set_color_callback_set_stub(
++ const uic_mqtt_dotdot_unify_switch_color_set_color_callback_t callback, int cmock_num_calls)
++{
++ test_uic_mqtt_dotdot_unify_switch_color_set_color_callback = callback;
++}
++void uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback_set_stub(
++ const uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback_t callback, int cmock_num_calls)
++{
++ test_uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback = callback;
++}
+ // clang-format on
+
+ // Test functions
+@@ -4129,6 +4167,18 @@ void setUp()
+ test_uic_mqtt_dotdot_unify_humidity_control_setpoint_set_callback = NULL;
+ uic_mqtt_dotdot_unify_humidity_control_setpoint_set_callback_set_Stub(
+ &uic_mqtt_dotdot_unify_humidity_control_setpoint_set_callback_set_stub);
++ test_uic_mqtt_dotdot_unify_switch_color_force_read_attributes_callback = NULL;
++ uic_mqtt_dotdot_set_unify_switch_color_force_read_attributes_callback_Stub(
++ &set_uic_mqtt_dotdot_unify_switch_color_force_read_attributes_callback_stub);
++ test_uic_mqtt_dotdot_unify_switch_color_write_attributes_callback = NULL;
++ uic_mqtt_dotdot_set_unify_switch_color_write_attributes_callback_Stub(
++ &set_uic_mqtt_dotdot_unify_switch_color_write_attributes_callback_stub);
++ test_uic_mqtt_dotdot_unify_switch_color_set_color_callback = NULL;
++ uic_mqtt_dotdot_unify_switch_color_set_color_callback_set_Stub(
++ &uic_mqtt_dotdot_unify_switch_color_set_color_callback_set_stub);
++ test_uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback = NULL;
++ uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback_set_Stub(
++ &uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback_set_stub);
+ // clang-format on
+
+ group_command_dispatch = NULL;
+@@ -4905,6 +4955,14 @@ void test_automatic_deduction_of_supported_commands()
+ TEST_ASSERT_EQUAL(SL_STATUS_OK, dotdot_create_unify_humidity_control_auto_setpoint(expected_unid,expected_endpoint_id) );
+ TEST_ASSERT_EQUAL(SL_STATUS_OK, dotdot_create_unify_humidity_control_auto_setpoint_scale(expected_unid,expected_endpoint_id) );
+ TEST_ASSERT_EQUAL(SL_STATUS_OK, dotdot_create_unify_humidity_control_auto_setpoint_precision(expected_unid,expected_endpoint_id) );
++ TEST_ASSERT_EQUAL(SL_STATUS_OK, dotdot_create_unify_switch_color_warm_white(expected_unid,expected_endpoint_id) );
++ TEST_ASSERT_EQUAL(SL_STATUS_OK, dotdot_create_unify_switch_color_cold_white(expected_unid,expected_endpoint_id) );
++ TEST_ASSERT_EQUAL(SL_STATUS_OK, dotdot_create_unify_switch_color_red(expected_unid,expected_endpoint_id) );
++ TEST_ASSERT_EQUAL(SL_STATUS_OK, dotdot_create_unify_switch_color_green(expected_unid,expected_endpoint_id) );
++ TEST_ASSERT_EQUAL(SL_STATUS_OK, dotdot_create_unify_switch_color_blue(expected_unid,expected_endpoint_id) );
++ TEST_ASSERT_EQUAL(SL_STATUS_OK, dotdot_create_unify_switch_color_amber(expected_unid,expected_endpoint_id) );
++ TEST_ASSERT_EQUAL(SL_STATUS_OK, dotdot_create_unify_switch_color_cyan(expected_unid,expected_endpoint_id) );
++ TEST_ASSERT_EQUAL(SL_STATUS_OK, dotdot_create_unify_switch_color_purple(expected_unid,expected_endpoint_id) );
+
+ // clang-format on
+ // ColorControl checks the value in the bitmask:
+@@ -8352,6 +8410,56 @@ void test_automatic_deduction_of_supported_commands()
+
+ ));
+ }
++ if (NULL != test_uic_mqtt_dotdot_unify_switch_color_set_color_callback) {
++ // Dummy command parameters
++ uint8_t color_component_id_value;
++ memset(&color_component_id_value, 0x00, sizeof(color_component_id_value));
++ uint8_t value_value;
++ memset(&value_value, 0x00, sizeof(value_value));
++ uint32_t duration_value;
++ memset(&duration_value, 0x00, sizeof(duration_value));
++ // Invoke with support check
++ TEST_ASSERT_EQUAL(SL_STATUS_FAIL, test_uic_mqtt_dotdot_unify_switch_color_set_color_callback(expected_unid,expected_endpoint_id,UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK
++ ,
++ color_component_id_value,
++
++ value_value,
++
++ duration_value
++
++ ));
++ }
++ if (NULL != test_uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback) {
++ // Dummy command parameters
++ bool start_stop_value;
++ memset(&start_stop_value, 0x00, sizeof(start_stop_value));
++ bool up_down_value;
++ memset(&up_down_value, 0x00, sizeof(up_down_value));
++ bool ignor_start_level_value;
++ memset(&ignor_start_level_value, 0x00, sizeof(ignor_start_level_value));
++ uint8_t color_component_id_value;
++ memset(&color_component_id_value, 0x00, sizeof(color_component_id_value));
++ uint8_t start_level_value;
++ memset(&start_level_value, 0x00, sizeof(start_level_value));
++ uint32_t duration_value;
++ memset(&duration_value, 0x00, sizeof(duration_value));
++ // Invoke with support check
++ TEST_ASSERT_EQUAL(SL_STATUS_FAIL, test_uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback(expected_unid,expected_endpoint_id,UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK
++ ,
++ start_stop_value,
++
++ up_down_value,
++
++ ignor_start_level_value,
++
++ color_component_id_value,
++
++ start_level_value,
++
++ duration_value
++
++ ));
++ }
+
+ // Invoke all commands with support check, they should return SL_STATUS_OK
+ // because all ZCL attributes are supported
+@@ -11791,5 +11899,55 @@ void test_automatic_deduction_of_supported_commands()
+
+ ));
+ }
++ if (NULL != test_uic_mqtt_dotdot_unify_switch_color_set_color_callback) {
++ // Dummy command parameters
++ uint8_t color_component_id_value;
++ memset(&color_component_id_value, 0x00, sizeof(color_component_id_value));
++ uint8_t value_value;
++ memset(&value_value, 0x00, sizeof(value_value));
++ uint32_t duration_value;
++ memset(&duration_value, 0x00, sizeof(duration_value));
++ // Invoke with support check
++ TEST_ASSERT_EQUAL(SL_STATUS_OK, test_uic_mqtt_dotdot_unify_switch_color_set_color_callback(expected_unid,expected_endpoint_id,UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK
++ ,
++ color_component_id_value,
++
++ value_value,
++
++ duration_value
++
++ ));
++ }
++ if (NULL != test_uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback) {
++ // Dummy command parameters
++ bool start_stop_value;
++ memset(&start_stop_value, 0x00, sizeof(start_stop_value));
++ bool up_down_value;
++ memset(&up_down_value, 0x00, sizeof(up_down_value));
++ bool ignor_start_level_value;
++ memset(&ignor_start_level_value, 0x00, sizeof(ignor_start_level_value));
++ uint8_t color_component_id_value;
++ memset(&color_component_id_value, 0x00, sizeof(color_component_id_value));
++ uint8_t start_level_value;
++ memset(&start_level_value, 0x00, sizeof(start_level_value));
++ uint32_t duration_value;
++ memset(&duration_value, 0x00, sizeof(duration_value));
++ // Invoke with support check
++ TEST_ASSERT_EQUAL(SL_STATUS_OK, test_uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback(expected_unid,expected_endpoint_id,UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK
++ ,
++ start_stop_value,
++
++ up_down_value,
++
++ ignor_start_level_value,
++
++ color_component_id_value,
++
++ start_level_value,
++
++ duration_value
++
++ ));
++ }
+
+ }
+diff --git a/components/unify_dotdot_attribute_store/zap-generated/test/unify_dotdot_attribute_store_test.h b/components/unify_dotdot_attribute_store/zap-generated/test/unify_dotdot_attribute_store_test.h
+index d5c2ed0913..7e291a589c 100644
+--- a/components/unify_dotdot_attribute_store/zap-generated/test/unify_dotdot_attribute_store_test.h
++++ b/components/unify_dotdot_attribute_store/zap-generated/test/unify_dotdot_attribute_store_test.h
+@@ -867,4 +867,14 @@
+
+ uic_mqtt_dotdot_unify_humidity_control_setpoint_set_callback_t get_uic_mqtt_dotdot_unify_humidity_control_setpoint_set_callback();
+
++
++ uic_mqtt_dotdot_unify_switch_color_force_read_attributes_callback_t get_uic_mqtt_dotdot_unify_switch_color_force_read_attributes_callback();
++ uic_mqtt_dotdot_unify_switch_color_write_attributes_callback_t get_uic_mqtt_dotdot_unify_switch_color_write_attributes_callback();
++
++
++ uic_mqtt_dotdot_unify_switch_color_set_color_callback_t get_uic_mqtt_dotdot_unify_switch_color_set_color_callback();
++
++
++ uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback_t get_uic_mqtt_dotdot_unify_switch_color_start_stop_change_callback();
++
+ #endif // UNIFY_DOTDOT_ATTRIBUTE_STORE_TEST_H
+\ No newline at end of file
+--
+2.39.5
+
diff --git a/patches/UnifySDK/0016-UIC-3272-Custom-Switch-Color-cluster.patch b/patches/UnifySDK/0016-UIC-3272-Custom-Switch-Color-cluster.patch
new file mode 100644
index 000000000..d7fcd5ab4
--- /dev/null
+++ b/patches/UnifySDK/0016-UIC-3272-Custom-Switch-Color-cluster.patch
@@ -0,0 +1,81 @@
+From d6dafa94d28e5abfacdab6ea03062f9ed01cfded Mon Sep 17 00:00:00 2001
+From: Viet
+Date: Wed, 11 Sep 2024 18:17:01 +0700
+Subject: [PATCH] UIC-3272: Custom Switch Color cluster
+
+---
+ .../dotdot-xml/Unify_SwitchColor.xml | 48 +++++++++++++++++++
+ components/uic_dotdot/dotdot-xml/library.xml | 4 +-
+ 2 files changed, 50 insertions(+), 2 deletions(-)
+ create mode 100644 components/uic_dotdot/dotdot-xml/Unify_SwitchColor.xml
+
+diff --git a/components/uic_dotdot/dotdot-xml/Unify_SwitchColor.xml b/components/uic_dotdot/dotdot-xml/Unify_SwitchColor.xml
+new file mode 100644
+index 0000000000..e4a5d1d6d9
+--- /dev/null
++++ b/components/uic_dotdot/dotdot-xml/Unify_SwitchColor.xml
+@@ -0,0 +1,48 @@
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
+diff --git a/components/uic_dotdot/dotdot-xml/library.xml b/components/uic_dotdot/dotdot-xml/library.xml
+index 79e165dbc6..892551c6b0 100644
+--- a/components/uic_dotdot/dotdot-xml/library.xml
++++ b/components/uic_dotdot/dotdot-xml/library.xml
+@@ -502,5 +502,5 @@ applicable to this document can be found in the LICENSE.md file.
+
+
+
+-
+-
+\ No newline at end of file
++
++
+--
+2.39.5
+
diff --git a/patches/UnifySDK/0017-UIC-3272-Regen-zap-files.patch b/patches/UnifySDK/0017-UIC-3272-Regen-zap-files.patch
new file mode 100644
index 000000000..1c2507b27
--- /dev/null
+++ b/patches/UnifySDK/0017-UIC-3272-Regen-zap-files.patch
@@ -0,0 +1,1073 @@
+From f91e80abb94fea222cdf8499b64ddcbec992cd16 Mon Sep 17 00:00:00 2001
+From: Philippe Coval
+Date: Mon, 29 Sep 2025 10:46:44 +0200
+Subject: [PATCH] UIC-3272: Regen zap files
+
+Signed-off-by: Philippe Coval
+---
+ .../src/eed_attribute_store_clusters.c | 32 +
+ .../src/eed_dotdot_create_clusters.cpp | 87 +++
+ .../include/dotdot_attribute_id_definitions.h | 9 +
+ .../dotdot_cluster_command_id_definitions.h | 4 +
+ .../include/dotdot_cluster_id_definitions.h | 4 +
+ .../readme_ucl_mqtt_reference.md | 697 ++++++++++++++++++
+ .../src/dotdot_attribute_id_definitions.c | 79 ++
+ .../src/dotdot_cluster_id_definitions.c | 5 +
+ 8 files changed, 917 insertions(+)
+
+diff --git a/applications/examples/applications/emulated_end_device/components/eed_attribute_store/zap-generated/src/eed_attribute_store_clusters.c b/applications/examples/applications/emulated_end_device/components/eed_attribute_store/zap-generated/src/eed_attribute_store_clusters.c
+index 05c5b08f6f..b0d111a7fa 100644
+--- a/applications/examples/applications/emulated_end_device/components/eed_attribute_store/zap-generated/src/eed_attribute_store_clusters.c
++++ b/applications/examples/applications/emulated_end_device/components/eed_attribute_store/zap-generated/src/eed_attribute_store_clusters.c
+@@ -2823,6 +2823,38 @@ sl_status_t eed_attribute_store_clusters_init()
+ &on_zcl_desired_value_update,
+ DOTDOT_ATTRIBUTE_ID_UNIFY_HUMIDITY_CONTROL_AUTO_SETPOINT_PRECISION,
+ DESIRED_ATTRIBUTE);
++ attribute_store_register_callback_by_type_and_state(
++ &on_zcl_desired_value_update,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_WARM_WHITE,
++ DESIRED_ATTRIBUTE);
++ attribute_store_register_callback_by_type_and_state(
++ &on_zcl_desired_value_update,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_COLD_WHITE,
++ DESIRED_ATTRIBUTE);
++ attribute_store_register_callback_by_type_and_state(
++ &on_zcl_desired_value_update,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_RED,
++ DESIRED_ATTRIBUTE);
++ attribute_store_register_callback_by_type_and_state(
++ &on_zcl_desired_value_update,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_GREEN,
++ DESIRED_ATTRIBUTE);
++ attribute_store_register_callback_by_type_and_state(
++ &on_zcl_desired_value_update,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_BLUE,
++ DESIRED_ATTRIBUTE);
++ attribute_store_register_callback_by_type_and_state(
++ &on_zcl_desired_value_update,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_AMBER,
++ DESIRED_ATTRIBUTE);
++ attribute_store_register_callback_by_type_and_state(
++ &on_zcl_desired_value_update,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_CYAN,
++ DESIRED_ATTRIBUTE);
++ attribute_store_register_callback_by_type_and_state(
++ &on_zcl_desired_value_update,
++ DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_PURPLE,
++ DESIRED_ATTRIBUTE);
+ // clang-format on
+ return SL_STATUS_OK;
+ }
+\ No newline at end of file
+diff --git a/applications/examples/applications/emulated_end_device/components/eed_attribute_store/zap-generated/src/eed_dotdot_create_clusters.cpp b/applications/examples/applications/emulated_end_device/components/eed_attribute_store/zap-generated/src/eed_dotdot_create_clusters.cpp
+index e3ce84ccee..5619115b87 100644
+--- a/applications/examples/applications/emulated_end_device/components/eed_attribute_store/zap-generated/src/eed_dotdot_create_clusters.cpp
++++ b/applications/examples/applications/emulated_end_device/components/eed_attribute_store/zap-generated/src/eed_dotdot_create_clusters.cpp
+@@ -4208,6 +4208,57 @@ void dotdot_create_unify_humidity_control_wrapper(const dotdot_unid_t unid, cons
+
+ }
+
++void dotdot_create_unify_switch_color_wrapper(const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint_id){
++ // Create and set a default value if undefined.
++ dotdot_create_unify_switch_color_warm_white(unid,endpoint_id);
++ if (false == dotdot_unify_switch_color_warm_white_is_reported_defined(unid,endpoint_id)){
++ dotdot_set_unify_switch_color_warm_white(unid,endpoint_id,REPORTED_ATTRIBUTE, static_cast(0));
++ }
++
++ // Create and set a default value if undefined.
++ dotdot_create_unify_switch_color_cold_white(unid,endpoint_id);
++ if (false == dotdot_unify_switch_color_cold_white_is_reported_defined(unid,endpoint_id)){
++ dotdot_set_unify_switch_color_cold_white(unid,endpoint_id,REPORTED_ATTRIBUTE, static_cast(0));
++ }
++
++ // Create and set a default value if undefined.
++ dotdot_create_unify_switch_color_red(unid,endpoint_id);
++ if (false == dotdot_unify_switch_color_red_is_reported_defined(unid,endpoint_id)){
++ dotdot_set_unify_switch_color_red(unid,endpoint_id,REPORTED_ATTRIBUTE, static_cast(0));
++ }
++
++ // Create and set a default value if undefined.
++ dotdot_create_unify_switch_color_green(unid,endpoint_id);
++ if (false == dotdot_unify_switch_color_green_is_reported_defined(unid,endpoint_id)){
++ dotdot_set_unify_switch_color_green(unid,endpoint_id,REPORTED_ATTRIBUTE, static_cast(0));
++ }
++
++ // Create and set a default value if undefined.
++ dotdot_create_unify_switch_color_blue(unid,endpoint_id);
++ if (false == dotdot_unify_switch_color_blue_is_reported_defined(unid,endpoint_id)){
++ dotdot_set_unify_switch_color_blue(unid,endpoint_id,REPORTED_ATTRIBUTE, static_cast(0));
++ }
++
++ // Create and set a default value if undefined.
++ dotdot_create_unify_switch_color_amber(unid,endpoint_id);
++ if (false == dotdot_unify_switch_color_amber_is_reported_defined(unid,endpoint_id)){
++ dotdot_set_unify_switch_color_amber(unid,endpoint_id,REPORTED_ATTRIBUTE, static_cast(0));
++ }
++
++ // Create and set a default value if undefined.
++ dotdot_create_unify_switch_color_cyan(unid,endpoint_id);
++ if (false == dotdot_unify_switch_color_cyan_is_reported_defined(unid,endpoint_id)){
++ dotdot_set_unify_switch_color_cyan(unid,endpoint_id,REPORTED_ATTRIBUTE, static_cast(0));
++ }
++
++ // Create and set a default value if undefined.
++ dotdot_create_unify_switch_color_purple(unid,endpoint_id);
++ if (false == dotdot_unify_switch_color_purple_is_reported_defined(unid,endpoint_id)){
++ dotdot_set_unify_switch_color_purple(unid,endpoint_id,REPORTED_ATTRIBUTE, static_cast(0));
++ }
++
++}
++
+
+ void dotdot_unretain_basic_wrapper(const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint_id){
+ char base_topic[256];
+@@ -6718,6 +6769,40 @@ void dotdot_unretain_unify_humidity_control_wrapper(const dotdot_unid_t unid, co
+ uic_mqtt_dotdot_unify_humidity_control_publish_empty_supported_commands(unid, endpoint_id);
+ }
+
++void dotdot_unretain_unify_switch_color_wrapper(const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint_id){
++ char base_topic[256];
++ snprintf(base_topic, sizeof(base_topic), "ucl/by-unid/%s/ep%d", unid, endpoint_id);
++ attribute_store::attribute ep_node = eed_attribute_store_get_endpoint_node(unid, endpoint_id);
++
++ uic_mqtt_dotdot_unify_switch_color_warm_white_unretain(base_topic,UCL_MQTT_PUBLISH_TYPE_ALL);
++ ep_node.child_by_type(DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_WARM_WHITE).delete_node();
++
++ uic_mqtt_dotdot_unify_switch_color_cold_white_unretain(base_topic,UCL_MQTT_PUBLISH_TYPE_ALL);
++ ep_node.child_by_type(DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_COLD_WHITE).delete_node();
++
++ uic_mqtt_dotdot_unify_switch_color_red_unretain(base_topic,UCL_MQTT_PUBLISH_TYPE_ALL);
++ ep_node.child_by_type(DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_RED).delete_node();
++
++ uic_mqtt_dotdot_unify_switch_color_green_unretain(base_topic,UCL_MQTT_PUBLISH_TYPE_ALL);
++ ep_node.child_by_type(DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_GREEN).delete_node();
++
++ uic_mqtt_dotdot_unify_switch_color_blue_unretain(base_topic,UCL_MQTT_PUBLISH_TYPE_ALL);
++ ep_node.child_by_type(DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_BLUE).delete_node();
++
++ uic_mqtt_dotdot_unify_switch_color_amber_unretain(base_topic,UCL_MQTT_PUBLISH_TYPE_ALL);
++ ep_node.child_by_type(DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_AMBER).delete_node();
++
++ uic_mqtt_dotdot_unify_switch_color_cyan_unretain(base_topic,UCL_MQTT_PUBLISH_TYPE_ALL);
++ ep_node.child_by_type(DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_CYAN).delete_node();
++
++ uic_mqtt_dotdot_unify_switch_color_purple_unretain(base_topic,UCL_MQTT_PUBLISH_TYPE_ALL);
++ ep_node.child_by_type(DOTDOT_ATTRIBUTE_ID_UNIFY_SWITCH_COLOR_PURPLE).delete_node();
++
++
++ uic_mqtt_dotdot_unify_switch_color_unretain_cluster_revision(base_topic);
++ uic_mqtt_dotdot_unify_switch_color_publish_empty_supported_commands(unid, endpoint_id);
++}
++
+
+ void eed_dotdot_create_clusters(const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint_id) {
+ for (auto& pair : CreateClusterMap) {
+@@ -6797,6 +6882,7 @@ std::map CreateClusterMap = {
+ { "UnifyFanControl", dotdot_create_unify_fan_control_wrapper },
+ { "UnifyThermostat", dotdot_create_unify_thermostat_wrapper },
+ { "UnifyHumidityControl", dotdot_create_unify_humidity_control_wrapper },
++{ "UnifySwitchColor", dotdot_create_unify_switch_color_wrapper },
+ };
+
+ std::map CreateUnretainMap = {
+@@ -6849,4 +6935,5 @@ std::map CreateUnretainMap = {
+ { "UnifyFanControl", dotdot_unretain_unify_fan_control_wrapper },
+ { "UnifyThermostat", dotdot_unretain_unify_thermostat_wrapper },
+ { "UnifyHumidityControl", dotdot_unretain_unify_humidity_control_wrapper },
++{ "UnifySwitchColor", dotdot_unretain_unify_switch_color_wrapper },
+ };
+\ No newline at end of file
+diff --git a/components/uic_dotdot/zap-generated/include/dotdot_attribute_id_definitions.h b/components/uic_dotdot/zap-generated/include/dotdot_attribute_id_definitions.h
+index b1512d6a82..643ace7524 100644
+--- a/components/uic_dotdot/zap-generated/include/dotdot_attribute_id_definitions.h
++++ b/components/uic_dotdot/zap-generated/include/dotdot_attribute_id_definitions.h
+@@ -893,6 +893,15 @@ typedef enum {
+ #define DOTDOT_UNIFY_HUMIDITY_CONTROL_AUTO_SETPOINT_ATTRIBUTE_ID ((dotdot_attribute_id_t)0x11)
+ #define DOTDOT_UNIFY_HUMIDITY_CONTROL_AUTO_SETPOINT_SCALE_ATTRIBUTE_ID ((dotdot_attribute_id_t)0x12)
+ #define DOTDOT_UNIFY_HUMIDITY_CONTROL_AUTO_SETPOINT_PRECISION_ATTRIBUTE_ID ((dotdot_attribute_id_t)0x13)
++// Definitions for cluster: UnifySwitchColor
++#define DOTDOT_UNIFY_SWITCH_COLOR_WARM_WHITE_ATTRIBUTE_ID ((dotdot_attribute_id_t)0x0)
++#define DOTDOT_UNIFY_SWITCH_COLOR_COLD_WHITE_ATTRIBUTE_ID ((dotdot_attribute_id_t)0x1)
++#define DOTDOT_UNIFY_SWITCH_COLOR_RED_ATTRIBUTE_ID ((dotdot_attribute_id_t)0x2)
++#define DOTDOT_UNIFY_SWITCH_COLOR_GREEN_ATTRIBUTE_ID ((dotdot_attribute_id_t)0x3)
++#define DOTDOT_UNIFY_SWITCH_COLOR_BLUE_ATTRIBUTE_ID ((dotdot_attribute_id_t)0x4)
++#define DOTDOT_UNIFY_SWITCH_COLOR_AMBER_ATTRIBUTE_ID ((dotdot_attribute_id_t)0x5)
++#define DOTDOT_UNIFY_SWITCH_COLOR_CYAN_ATTRIBUTE_ID ((dotdot_attribute_id_t)0x6)
++#define DOTDOT_UNIFY_SWITCH_COLOR_PURPLE_ATTRIBUTE_ID ((dotdot_attribute_id_t)0x7)
+
+ // clang-format on
+
+diff --git a/components/uic_dotdot/zap-generated/include/dotdot_cluster_command_id_definitions.h b/components/uic_dotdot/zap-generated/include/dotdot_cluster_command_id_definitions.h
+index 958a1064f5..6067e3ce74 100644
+--- a/components/uic_dotdot/zap-generated/include/dotdot_cluster_command_id_definitions.h
++++ b/components/uic_dotdot/zap-generated/include/dotdot_cluster_command_id_definitions.h
+@@ -397,6 +397,10 @@
+ #define DOTDOT_UNIFY_HUMIDITY_CONTROL_MODE_SET_COMMAND_ID (0x1)
+ #define DOTDOT_UNIFY_HUMIDITY_CONTROL_SETPOINT_SET_COMMAND_ID (0x2)
+
++// Commands for cluster: UnifySwitchColor
++#define DOTDOT_UNIFY_SWITCH_COLOR_SET_COLOR_COMMAND_ID (0x0)
++#define DOTDOT_UNIFY_SWITCH_COLOR_START_STOP_CHANGE_COMMAND_ID (0x1)
++
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+diff --git a/components/uic_dotdot/zap-generated/include/dotdot_cluster_id_definitions.h b/components/uic_dotdot/zap-generated/include/dotdot_cluster_id_definitions.h
+index ee7d429b0f..78c2cd96b4 100644
+--- a/components/uic_dotdot/zap-generated/include/dotdot_cluster_id_definitions.h
++++ b/components/uic_dotdot/zap-generated/include/dotdot_cluster_id_definitions.h
+@@ -270,6 +270,10 @@
+ #define DOTDOT_UNIFY_HUMIDITY_CONTROL_CLUSTER_ID ((dotdot_cluster_id_t)0xFDA0)
+
+
++// Definitions for cluster: UnifySwitchColor
++#define DOTDOT_UNIFY_SWITCH_COLOR_CLUSTER_ID ((dotdot_cluster_id_t)0xFFA1)
++
++
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+diff --git a/components/uic_dotdot/zap-generated/readme_ucl_mqtt_reference.md b/components/uic_dotdot/zap-generated/readme_ucl_mqtt_reference.md
+index 18ad4f947e..e1d6b1ddca 100644
+--- a/components/uic_dotdot/zap-generated/readme_ucl_mqtt_reference.md
++++ b/components/uic_dotdot/zap-generated/readme_ucl_mqtt_reference.md
+@@ -55997,6 +55997,703 @@ mosquitto_pub -t 'ucl/by-unid///UnifyHumidityControl/Commands/ForceRea
+
+
+
++
++
++
++
++
++
++
++
++\page unify_switch_color UnifySwitchColor Cluster
++The following commands and attributes are accepted as JSON payloads for the
++UnifySwitchColor cluster.
++
++
++
++
++
++
++\section unify_switch_color_attrs UnifySwitchColor Attributes
++The following attribute topics are used to retrieve the UnifySwitchColor cluster state.
++
++
++
++\subsection unify_switch_color_attr_warm_white UnifySwitchColor/WarmWhite Attribute
++
++**MQTT Topic Pattern:**
++
++```
++[PREFIX]/UnifySwitchColor/Attributes/WarmWhite/Reported
++[PREFIX]/UnifySwitchColor/Attributes/WarmWhite/Desired
++```
++
++**MQTT Payload JSON Schema:**
++
++```json
++{
++ "$schema": "http://json-schema.org/draft-07/schema#",
++ "title": "UnifySwitchColor Cluster WarmWhite Attribute Properties",
++ "type": "object",
++ "properties": {
++ "value": {
++ "type": "integer"
++ }
++ },
++ "required": [
++ "value"
++ ]
++}
++```
++
++
++**Example Mosquitto CLI Tool Usage**
++
++To see desired/reported value for WarmWhite attribute under the by-unid topic space:
++
++```console
++mosquitto_sub -t 'ucl/by-unid/+/+/UnifySwitchColor/Attributes/WarmWhite/+'
++
++# Example output
++
++ucl/by-unid//ep0/UnifySwitchColor/Attributes/WarmWhite/Desired { "value": }
++ucl/by-unid//ep0/UnifySwitchColor/Attributes/WarmWhite/Reported { "value": }
++
++```
++
++
++
++\subsection unify_switch_color_attr_cold_white UnifySwitchColor/ColdWhite Attribute
++
++**MQTT Topic Pattern:**
++
++```
++[PREFIX]/UnifySwitchColor/Attributes/ColdWhite/Reported
++[PREFIX]/UnifySwitchColor/Attributes/ColdWhite/Desired
++```
++
++**MQTT Payload JSON Schema:**
++
++```json
++{
++ "$schema": "http://json-schema.org/draft-07/schema#",
++ "title": "UnifySwitchColor Cluster ColdWhite Attribute Properties",
++ "type": "object",
++ "properties": {
++ "value": {
++ "type": "integer"
++ }
++ },
++ "required": [
++ "value"
++ ]
++}
++```
++
++
++**Example Mosquitto CLI Tool Usage**
++
++To see desired/reported value for ColdWhite attribute under the by-unid topic space:
++
++```console
++mosquitto_sub -t 'ucl/by-unid/+/+/UnifySwitchColor/Attributes/ColdWhite/+'
++
++# Example output
++
++ucl/by-unid//ep0/UnifySwitchColor/Attributes/ColdWhite/Desired { "value": }
++ucl/by-unid//ep0/UnifySwitchColor/Attributes/ColdWhite/Reported { "value": }
++
++```
++
++
++
++\subsection unify_switch_color_attr_red UnifySwitchColor/Red Attribute
++
++**MQTT Topic Pattern:**
++
++```
++[PREFIX]/UnifySwitchColor/Attributes/Red/Reported
++[PREFIX]/UnifySwitchColor/Attributes/Red/Desired
++```
++
++**MQTT Payload JSON Schema:**
++
++```json
++{
++ "$schema": "http://json-schema.org/draft-07/schema#",
++ "title": "UnifySwitchColor Cluster Red Attribute Properties",
++ "type": "object",
++ "properties": {
++ "value": {
++ "type": "integer"
++ }
++ },
++ "required": [
++ "value"
++ ]
++}
++```
++
++
++**Example Mosquitto CLI Tool Usage**
++
++To see desired/reported value for Red attribute under the by-unid topic space:
++
++```console
++mosquitto_sub -t 'ucl/by-unid/+/+/UnifySwitchColor/Attributes/Red/+'
++
++# Example output
++
++ucl/by-unid//ep0/UnifySwitchColor/Attributes/Red/Desired { "value": }
++ucl/by-unid//ep0/UnifySwitchColor/Attributes/Red/Reported { "value": }
++
++```
++
++
++
++\subsection unify_switch_color_attr_green UnifySwitchColor/Green Attribute
++
++**MQTT Topic Pattern:**
++
++```
++[PREFIX]/UnifySwitchColor/Attributes/Green/Reported
++[PREFIX]/UnifySwitchColor/Attributes/Green/Desired
++```
++
++**MQTT Payload JSON Schema:**
++
++```json
++{
++ "$schema": "http://json-schema.org/draft-07/schema#",
++ "title": "UnifySwitchColor Cluster Green Attribute Properties",
++ "type": "object",
++ "properties": {
++ "value": {
++ "type": "integer"
++ }
++ },
++ "required": [
++ "value"
++ ]
++}
++```
++
++
++**Example Mosquitto CLI Tool Usage**
++
++To see desired/reported value for Green attribute under the by-unid topic space:
++
++```console
++mosquitto_sub -t 'ucl/by-unid/+/+/UnifySwitchColor/Attributes/Green/+'
++
++# Example output
++
++ucl/by-unid//ep0/UnifySwitchColor/Attributes/Green/Desired { "value": }
++ucl/by-unid//ep0/UnifySwitchColor/Attributes/Green/Reported { "value": }
++
++```
++
++
++
++\subsection unify_switch_color_attr_blue UnifySwitchColor/Blue Attribute
++
++**MQTT Topic Pattern:**
++
++```
++[PREFIX]/UnifySwitchColor/Attributes/Blue/Reported
++[PREFIX]/UnifySwitchColor/Attributes/Blue/Desired
++```
++
++**MQTT Payload JSON Schema:**
++
++```json
++{
++ "$schema": "http://json-schema.org/draft-07/schema#",
++ "title": "UnifySwitchColor Cluster Blue Attribute Properties",
++ "type": "object",
++ "properties": {
++ "value": {
++ "type": "integer"
++ }
++ },
++ "required": [
++ "value"
++ ]
++}
++```
++
++
++**Example Mosquitto CLI Tool Usage**
++
++To see desired/reported value for Blue attribute under the by-unid topic space:
++
++```console
++mosquitto_sub -t 'ucl/by-unid/+/+/UnifySwitchColor/Attributes/Blue/+'
++
++# Example output
++
++ucl/by-unid//ep0/UnifySwitchColor/Attributes/Blue/Desired { "value": }
++ucl/by-unid//ep0/UnifySwitchColor/Attributes/Blue/Reported { "value": }
++
++```
++
++
++
++\subsection unify_switch_color_attr_amber UnifySwitchColor/Amber Attribute
++
++**MQTT Topic Pattern:**
++
++```
++[PREFIX]/UnifySwitchColor/Attributes/Amber/Reported
++[PREFIX]/UnifySwitchColor/Attributes/Amber/Desired
++```
++
++**MQTT Payload JSON Schema:**
++
++```json
++{
++ "$schema": "http://json-schema.org/draft-07/schema#",
++ "title": "UnifySwitchColor Cluster Amber Attribute Properties",
++ "type": "object",
++ "properties": {
++ "value": {
++ "type": "integer"
++ }
++ },
++ "required": [
++ "value"
++ ]
++}
++```
++
++
++**Example Mosquitto CLI Tool Usage**
++
++To see desired/reported value for Amber attribute under the by-unid topic space:
++
++```console
++mosquitto_sub -t 'ucl/by-unid/+/+/UnifySwitchColor/Attributes/Amber/+'
++
++# Example output
++
++ucl/by-unid//ep0/UnifySwitchColor/Attributes/Amber/Desired { "value": }
++ucl/by-unid//ep0/UnifySwitchColor/Attributes/Amber/Reported { "value": }
++
++```
++
++
++
++\subsection unify_switch_color_attr_cyan UnifySwitchColor/Cyan Attribute
++
++**MQTT Topic Pattern:**
++
++```
++[PREFIX]/UnifySwitchColor/Attributes/Cyan/Reported
++[PREFIX]/UnifySwitchColor/Attributes/Cyan/Desired
++```
++
++**MQTT Payload JSON Schema:**
++
++```json
++{
++ "$schema": "http://json-schema.org/draft-07/schema#",
++ "title": "UnifySwitchColor Cluster Cyan Attribute Properties",
++ "type": "object",
++ "properties": {
++ "value": {
++ "type": "integer"
++ }
++ },
++ "required": [
++ "value"
++ ]
++}
++```
++
++
++**Example Mosquitto CLI Tool Usage**
++
++To see desired/reported value for Cyan attribute under the by-unid topic space:
++
++```console
++mosquitto_sub -t 'ucl/by-unid/+/+/UnifySwitchColor/Attributes/Cyan/+'
++
++# Example output
++
++ucl/by-unid//ep0/UnifySwitchColor/Attributes/Cyan/Desired { "value": }
++ucl/by-unid//ep0/UnifySwitchColor/Attributes/Cyan/Reported { "value": }
++
++```
++
++
++
++\subsection unify_switch_color_attr_purple UnifySwitchColor/Purple Attribute
++
++**MQTT Topic Pattern:**
++
++```
++[PREFIX]/UnifySwitchColor/Attributes/Purple/Reported
++[PREFIX]/UnifySwitchColor/Attributes/Purple/Desired
++```
++
++**MQTT Payload JSON Schema:**
++
++```json
++{
++ "$schema": "http://json-schema.org/draft-07/schema#",
++ "title": "UnifySwitchColor Cluster Purple Attribute Properties",
++ "type": "object",
++ "properties": {
++ "value": {
++ "type": "integer"
++ }
++ },
++ "required": [
++ "value"
++ ]
++}
++```
++
++
++**Example Mosquitto CLI Tool Usage**
++
++To see desired/reported value for Purple attribute under the by-unid topic space:
++
++```console
++mosquitto_sub -t 'ucl/by-unid/+/+/UnifySwitchColor/Attributes/Purple/+'
++
++# Example output
++
++ucl/by-unid//ep0/UnifySwitchColor/Attributes/Purple/Desired { "value": }
++ucl/by-unid//ep0/UnifySwitchColor/Attributes/Purple/Reported { "value": }
++
++```
++
++
++
++
++\subsection unify_switch_color_attr_cluster_revision UnifySwitchColor/ClusterRevision Attribute
++
++**MQTT Topic Pattern:**
++
++```
++[PREFIX]/UnifySwitchColor/Attributes/ClusterRevision/Reported
++[PREFIX]/UnifySwitchColor/Attributes/ClusterRevision/Desired
++```
++
++**MQTT Payload JSON Schema:**
++
++```json
++{
++ "$schema": "http://json-schema.org/draft-07/schema#",
++ "title": "UnifySwitchColor Cluster ClusterRevision Attribute Properties",
++ "type": "object",
++ "properties": {
++ "value": {
++ "type": "integer"
++ }
++ },
++ "required": [
++ "value"
++ ]
++}
++```
++
++**Example Mosquitto CLI Tool Usage**
++
++To see desired/reported value for ClusterRevision attribute under the by-unid topic space:
++
++```console
++mosquitto_sub -t 'ucl/by-unid///UnifySwitchColor/Attributes/ClusterRevision/+'
++# Example output
++ucl/by-unid///UnifySwitchColor/Attributes/ClusterRevision/Desired { "value": }
++ucl/by-unid///UnifySwitchColor/Attributes/ClusterRevision/Reported { "value": }
++```
++
++
++
++
++
++
++
++
++
++
++\section unify_switch_color_recv_cmd_support UnifySwitchColor Command Support
++
++**MQTT Topic Pattern:**
++
++```
++[PREFIX]/UnifySwitchColor/SupportedCommands
++[PREFIX]/UnifySwitchColor/SupportedGeneratedCommands
++```
++
++**MQTT Payload JSON Schema:**
++
++```json
++{
++ "$schema": "http://json-schema.org/draft-07/schema#",
++ "title": "UnifySwitchColor Command Support Properties",
++ "type": "object",
++ "properties": {
++ "value": {
++ "type": "array",
++ "items" : {
++ "type": "string",
++ "enum": [
++ "SetColor",
++ "StartStopChange",
++ "WriteAttributes",
++ "ForceReadAttributes"
++ ]
++ }
++ }
++ }
++ },
++ "required": [
++ "value"
++ ]
++}
++```
++
++**Example Mosquitto CLI Tool Usage**
++
++To see supported commands for UnifySwitchColor cluster under the by-unid topic space:
++
++```console
++mosquitto_sub -t 'ucl/by-unid///UnifySwitchColor/SupportedCommands'
++# Example output
++ucl/by-unid///UnifySwitchColor/SupportedCommands { "value": ["SetColor","StartStopChange","WriteAttributes", "ForceReadAttributes"] }
++```
++
++To see supported generated commands for UnifySwitchColor cluster under the by-unid topic space:
++
++```console
++mosquitto_sub -t 'ucl/by-unid///UnifySwitchColor/SupportedGeneratedCommands'
++# Example output
++ucl/by-unid///UnifySwitchColor/SupportedGeneratedCommands { "value": [] }
++```
++
++
++
++
++
++
++
++
++
++
++\section unify_switch_color_cmds UnifySwitchColor Commands
++
++
++
++\subsection unify_switch_color_set_color_cmd UnifySwitchColor/SetColor Command
++
++**MQTT Topic Pattern:**
++
++```
++[PREFIX]/UnifySwitchColor/Commands/SetColor
++[PREFIX]/UnifySwitchColor/GeneratedCommands/SetColor
++```
++
++**MQTT Payload JSON Schema:**
++
++```json
++{
++ "$schema": "http://json-schema.org/draft-07/schema#",
++ "title": "UnifySwitchColor Cluster SetColor Command Properties",
++ "type": "object",
++ "properties": {
++ "ColorComponentId": {
++ "type": "integer"
++ },
++ "Value": {
++ "type": "integer"
++ },
++ "Duration": {
++ "type": "integer"
++ }
++ },
++ "required": [
++ "ColorComponentId",
++ "Value",
++ "Duration"
++ ]
++}
++```
++
++**Example Mosquitto CLI Tool Usage**
++
++To send a UnifySwitchColor/SetColor command under the by-unid topic space:
++
++```console
++mosquitto_pub -t 'ucl/by-unid///UnifySwitchColor/Commands/SetColor' -m '{ "ColorComponentId": ,"Value": ,"Duration": }'
++```
++
++To receive a UnifySwitchColor/SetColor generated command from a UNID/endpoint:
++
++```console
++mosquitto_sub -t 'ucl/by-unid///UnifySwitchColor/GeneratedCommands/SetColor'
++```
++
++
++
++\subsection unify_switch_color_start_stop_change_cmd UnifySwitchColor/StartStopChange Command
++
++**MQTT Topic Pattern:**
++
++```
++[PREFIX]/UnifySwitchColor/Commands/StartStopChange
++[PREFIX]/UnifySwitchColor/GeneratedCommands/StartStopChange
++```
++
++**MQTT Payload JSON Schema:**
++
++```json
++{
++ "$schema": "http://json-schema.org/draft-07/schema#",
++ "title": "UnifySwitchColor Cluster StartStopChange Command Properties",
++ "type": "object",
++ "properties": {
++ "StartStop": {
++ "type": "boolean"
++ },
++ "UpDown": {
++ "type": "boolean"
++ },
++ "IgnorStartLevel": {
++ "type": "boolean"
++ },
++ "ColorComponentId": {
++ "type": "integer"
++ },
++ "StartLevel": {
++ "type": "integer"
++ },
++ "Duration": {
++ "type": "integer"
++ }
++ },
++ "required": [
++ "StartStop",
++ "UpDown",
++ "IgnorStartLevel",
++ "ColorComponentId",
++ "StartLevel",
++ "Duration"
++ ]
++}
++```
++
++**Example Mosquitto CLI Tool Usage**
++
++To send a UnifySwitchColor/StartStopChange command under the by-unid topic space:
++
++```console
++mosquitto_pub -t 'ucl/by-unid///UnifySwitchColor/Commands/StartStopChange' -m '{ "StartStop": ,"UpDown": ,"IgnorStartLevel": ,"ColorComponentId": ,"StartLevel": ,"Duration": }'
++```
++
++To receive a UnifySwitchColor/StartStopChange generated command from a UNID/endpoint:
++
++```console
++mosquitto_sub -t 'ucl/by-unid///UnifySwitchColor/GeneratedCommands/StartStopChange'
++```
++
++
++
++\subsection unify_switch_color_write_attr_cmd UnifySwitchColor/WriteAttributes Command
++
++**MQTT Topic Pattern:**
++
++```
++[PREFIX]/UnifySwitchColor/Commands/WriteAttributes
++```
++
++**MQTT Payload JSON Schema:**
++
++```json
++{
++ "$schema": "http://json-schema.org/draft-07/schema#",
++ "title": "UnifySwitchColor Cluster WriteAttributes Command Properties",
++ "type": "object",
++ "properties": {
++ },
++ "required": [
++ "value"
++ ]
++}
++```
++
++**Example Mosquitto CLI Tool Usage**
++
++To update all UnifySwitchColor attributes under the by-unid topic space:
++
++```console
++mosquitto_pub -t 'ucl/by-unid///UnifySwitchColor/Commands/WriteAttributes' -m '{ }'
++```
++
++> NOTE: Specify only the list of attributes to write in this command.
++> Unspecified attributes will not be updated.
++
++